pax_global_header00006660000000000000000000000064136562566250014532gustar00rootroot0000000000000052 comment=a0d37f5f94d2a3e94a2dd11660ea0c4e10f7ce01 libreswan-3.32/000077500000000000000000000000001365625662500134475ustar00rootroot00000000000000libreswan-3.32/.gitignore000066400000000000000000000010051365625662500154330ustar00rootroot00000000000000*~ .*.sw? \#*\# .\#* BACKUP RESULTS DEADJOE OBJ.* *.rej *.orig *.bak *.pyc *.o kvmrunner.pid TAGS tags modobj modobj24 modobj26 testing/*/*/OUTPUT* testing/*/*/NS* testing/x509/*/* testing/x509/index.* testing/x509/crlnumber.* testing/x509/serial* testing/x509/nss-pw osxApp/build Makefile.inc.local .ycm_extra_conf.py cscope.out testing/baseconfigs/all/etc/bind/signed/*.signed testing/baseconfigs/all/etc/bind/keys/*.key testing/baseconfigs/all/etc/bind/keys/*.private testing/baseconfigs/all/etc/bind/dsset/dsset* libreswan-3.32/.travis.yml000066400000000000000000000023121365625662500155560ustar00rootroot00000000000000sudo: required language: c os: - linux compiler: - gcc dist: xenial before_install: - echo $PWD - git rev-parse --abbrev-ref HEAD - git checkout $TRAVIS_BRANCH # # 'make travis-docker-image' reads the branch name # -- or default to Fedora 27 # - sudo add-apt-repository -y ppa:projectatomic/ppa - sudo apt-get update -qq - sudo apt-get install -qq -y software-properties-common podman - sudo mkdir -p /etc/containers - sudo sh -c 'echo "[registries.search]\nregistries = [\"docker.io\", \"registry.fedoraproject.org\", \"quay.io\", \"registry.access.redhat.com\", \"registry.centos.org\"]" > /etc/containers/registries.conf' # - sudo sh -c 'echo -e "[registries.search]\nregistries = [\"docker.io\"]" > /etc/containers/registries.conf' - cat /etc/containers/registries.conf - sudo podman --version - make TRAVIS_ENABLED=true travis-docker-image - git fetch --tags - git fetch --depth=100000 - make TRAVIS_ENABLED=true travis-docker-start #- sudo docker exec -ti swanbase /bin/bash -c 'cd /home/build/libreswan && make showdebversion' script: - make TRAVIS_ENABLED=true travis-docker-make - make TRAVIS_ENABLED=true travis-docker-make-install libreswan-3.32/CHANGES000066400000000000000000003105131365625662500144450ustar00rootroot00000000000000 See also https://libreswan.org/ v3.32 (May 11, 2020) * SECURITY: Fixes CVE-2020-1763 https://libreswan.org/security/CVE-2020-1763 * IKEv2: Support non-narrowed child rekey for narrowing (regression in 3.31) * FIPS: ECDSA keys were mistakenly rejected as "too weak" [Paul] * FIPS: Minimum RSA key size is 2048, not 3072 [Paul] * FIPS: Use NSS to check FIPS mode instead of manually checking fips=1 [Paul] * IKEv2: Do not use fragments if not appropriate (regression from v3.30) [Paul] * IKEv1: Add NSS KDF support for the Quick Mode KDF [Andrew/Paul] * libipsecconf: support old-style ",," to mean "\," in specifying id [Paul] * libipsecconf: left/rightinterface-ip= are not kt_obsolete [Paul] * whack: Add missing ecdsa/sha2 and compat rsa policy options to whack [Paul] * Fix left=%iface syntax due to string length miscalculation [Antony] * X509: don't try to match up ID on SAN when ID type is ID_DER_ASN1_DN [Paul] * packaging: debian fixes [Antony] * building: USE_NSS_KDF=true now uses NSS for all KDF functions Using this option, libreswan no longer needs FIPS certification v3.31 (March 3, 2020) * IKEv2: Opportunistic conns specifying keyingtries=0 are changed to 1 [Paul] * IKEv2: Fix ikev2 rekey failures due to bad Traffic Selector proposa [Antony] * IKEv2: Verify (not ignore) expected TSi/TSr payloads for IPsec rekeys [Paul] * IKEv1: Support for XFRMi interfaces [Paul] * X509: When IDr payload is type ID_DER_ASN1_DN, don't check for SAN [Paul] * pluto: Disable log_to_audit if kernel does not support audit [Paul] * pluto: Increase max IKEv2 fragments to 32 to support Windows [John Mah] * addconn: Do not assert on ipsec-interface=no [Paul] * nat_traversal: Fix not to send nat-t keepalives when there is no nat [Tuomo] * KLIPS: Fix _updown.klips (regression introduced in 3.30) [Wolfgang] v3.30 (February 13, 2020) * WARNING: This is the last release that supports the KLIPS stack, use the new ipsec-interface= virtual interfaces instead. * XFRM: Fix detection on kernels without xfrm_stat (debian et all) [Paul] * XFRM: XFRMi interface support using ipsec-interface= and iface-ip= [Antony] * IKEv2: Message ID handling: remove a O(#STATES) lookup [Andrew] * IKEv2: OE previous half-open state overwrites IPsec policy [Paul/Stepan] * IKEv2: On initiator, do not retransmit on IKE_AUTH processing failure [Paul] * IKEv2: Prevent leak in ikev2_send_certreq() on sending error [Paul] * IKEv2: Remove SHA1 from default proposal list [Paul] * IKEv2: On PPK failure with insist, return AUTHENTICATION_FAILED [Vukasin] * IKEv2: Do not try to delete (replaced) bare shunts [Paul] * IKEv2: Delete pending outgoing bare shunts if incoming IPsec happened [Paul] * IKEv2: Allow CP payload in CREATE_CHILD_SA (RFC 7296 Appendix C.4) [Paul] * IKEv2: calculate_sa_prio() now allows OE shunt to override priority [Paul] * IKEv2: calculate_sa_prio() support for /32 template vs instance [Hugh/Paul] * IKEv2: IPv6 support for addresspool= option [Antony] * IKEv2: Updated support for MOBIKE triggered events [Antony] * IKEv2: Support reconnecting authnull clients [Paul] * IKEv2: New whack commands --rekey-ike and --rekey-ipsec [Antony] * IKEv2: Prefer RFC 7427 Digital Signatures for default authby=rsasig [Sahana] * IKEv2: Refuse SHA1 for RFC 7427 Digital Signatures as per RFC 8247 [Sahana] * IKEv2: Use IKEv2 fragment size values (not IKEv1) [Andrew] * IKEv2: On initiator, do not retransmit on IKE_AUTH processing failure [Paul] * IKEv1: Re-implement CVE-2019-10155 fix to prevent future occurances [Andrew] * IKEv1: do not assert on bad virtual private entry [Paul] * pluto: Simplify plutodebug= options to: base, cpu-usage, crypt, private and tmi (maps old values to new ones for compatibility) [Andrew] * pluto: non-default ipsec.conf did not load auto=add connections [Paul] * pluto: fix %defaultroute for link-local and non-link-local gateway [Antony] * pluto: Improve whackfd handling (prevent console hangs/omissions) [Andrew] * pluto: Support to disable SAN checks (require-id-on-certificate=no) [Paul] * pluto: Audit log IKE SA and IPsec SA failures for Common Criteria (CC) [Paul] * pluto: Disable support for DH2/modp1024 at compile time [Paul] * pluto: Add audit-log=yes|no (default yes) [Paul] * pluto: DDNS event should not cause connection initialization [Paul] * pluto: Various O(STATE) optimializations [Andrew] * pluto: Fixup reporting of esp-hw-offload capabilities in kernel/nic [Paul] * pluto: Add chacha20_poly1305 and curve25519 to default proposals [Paul] * pluto: Updated SECCOMP syscall whitelist [Paul] * pluto: With non-default config file, connections loading was skipped [Paul] * pluto: Fix Opportunistic Encryption with Transport Mode policies [Paul] * pluto: Fix various memory leaks in IKE and X.509 code [Andrew] * pluto: netlink: increase the additional bufferspace to 32KiB [Antony] * pluto: pluto --selftest no longer logs to stderr with timestamps [Paul] * pluto: fix for redirect-to type when it is FQDN [John Mah] * pluto: addresspool: give new lease to different (xauth)usernames [Paul] * pluto: addresspool: reduce complexity from O(#LEASES) to O(1) [Andrew] * whack: Remove obsoleted --whackrecord and --whackstoprecord options [Andrew] * whack: Added whack --ddns to trigger DNS refresh event manually [Paul] * X509: Offload most code to helpers for significant performance boost [Andrew] * X509: Simplify code, cut redundant calculations, speed improvements [Andrew] * X509: SAN checks should confirm IKE peer ID on responder too [Paul] * letsencrypt: new command "ipsec letsencrypt" [Rishabh] * _updown.netkey: PLUTO_VIRT_INTERFACE replaces PLUTO_INTERFACE [Antony] * _updown.netkey: add IPv6 routing support [Tuomo] * _updown.netkey: don't remove old resolv.conf, just update it [Tuomo] * _updown.netkey: fix for iproute2 >= 5.1 which no longer ignores /mask [Paul] * libswan: Don't leak ECDSA pubkey on form_ckaid_ecdsa() failure [Paul] * libswan: Close netlink socket on send error in netlink_query() [Paul] * libipsecconf: don't throw error for not finding a wildcarded include [Paul] * verify: improve support for python2 and python3 [Anand Bibhuti/Paul] * KLIPS: Support for kernels >= 4.20 with SYNC_SKCIPHER_REQUEST_ON_STACK [Paul] * KLIPS: Userland tools compile fixes [Hugh/Paul] * building: No longer build with DH2(modp1024) support (see RFC 8247) [Paul] * building: Add config for PYTHON_BINARY, default being /usr/bin/python3 [Tuomo] * building: Add new USE_NSS_PRF, to use KDF from NSS [Robert Relyea/Andrew] * building: Add USE_PRF_AES_XCBC, replaces USE_XCBC [Paul] * building: Fixes for NetBSD build [Andrew] * building: Fixes for gcc10 [Paul] * packaging: fedora30 requires gcc to be listed as BuildRequires: [Paul] * packaging: Add Debian stretch specific configs and more cleanup [Antony] * packaging: make deb jessie and xenial config detection [Antony] * packaging: update python she-bang handling [Tuomo] * testing: Added a new namespaces based testrun method [Antony] * testing: setup: namespace based ipsec stop needs ip xfrm flush state [Paul] * testing: setup: namespace based ipsec skips initsystem [Paul] v3.29 (June 10, 2019) * SECURITY: Fixes CVE-2019-10155 https://libreswan.org/security/CVE-2019-10155 * programs: Change to /proc/sys/net/core/xfrm_acq_expires to detect XFRM [Paul] * barf: Fix shell script parse error and small cleanup [Tuomo/Hugh] * packaging: fedora30 requires gcc to be listed as BuildRequires: [Paul] * packaging: rhel6 doesn't need USE_AVA_COPY=true or WERROR_CFLAGS= [Tuomo] * packaging/rhel6: remove -lrt, not needed any more [Tuomo] * systemd: change Restart default to on-failure [Tuomo] * building: Makefiles: Use RT_LDFLAGS for glibc < 2.17 support [Tuomo] * building: userland-cflags.mk: add RT_LDFLAGS= for older glibc [Tuomo] v3.28 (May 20, 2019) * SECURITY: Fixes CVE-2019-12312 https://libreswan.org/security/CVE-2019-12312 * KLIPS: Disable KLIPS userland support per default [Paul] WARNING: Support for KLIPS will be removed in 2019 * MAST: Removed support for MAST variant of KLIPS stack [Paul] * IKE: Change default connection from IKEv1 to IKEv2 [Paul] * IKEv2: Don't try to encrypt notify response without SKEYSEED [Andrew/Paul/Hugh] * IKEv2: ikev2= keyword changed to only accept "yes" or "no" [Paul] * IKEv2: Support for REDIRECT (RFC 5685) [Vukasin Karadzic/GSoC] (new keywords redirect-to, accept-redirect, global-redirect= global-redirect-to and new ipsec whack --redirect command * IKEv2: Initialize daily secret used for DCOOKIES [Paul/Andrew] * IKEv2: Extend narrowing code to support protoports [Andrew/Paul] * IKEv2: Fix bug that prevented AH from rekeying [Andrew] * IKEv2: IKE SA rekey could lead to losing track of Child SA [Andrew/Antony] * IKEv2: A spurious DH calculation was performed and discarded [Andrew] * IKEv2: Support for IPCOMP (compress=yes) [Paul] * IKEv2: Initialize NAT keepalives check on IKE SA establishment [Paul] * IKEv2: Only sent NAT keepalives for IKE states (suppresses IPsec dups) [Paul] * IKEv2: Timeout in receiving IKE_AUTH reply would abort connection [Paul] * IKEv2: Add ECP384, ECP521 and CURVE25519 to default IKEv2 proposal [Paul] * IKEv2: Remove SHA1 from default IKEv2 proposal [Paul] * IKEv2: Delete on auto=start conn would not restart (introduced in 3.23) [Paul] * IKEv2: Compact proposals to prevent fragmentation of IKE_INIT [Andrew] * IKEv2: Fix opportunistic group policy on /32 groupinstances on delete [Paul] * IKEv2: Fix opportunistic /32 on non-defaultroute interface [Paul] * IKEv2: Do not send two requests for IKEv2_INTERNAL_IP4_ADDRESS [Paul] * IKEv2: Show payload structure of received packet in RFC notation [Andrew] * IKEv2: Release whack when peer ID is wrong [Paul] * IKEv2: Hardened PPK code and fixed memory leaks [Hugh] * IKEv2: Use less resources under DDoS attack to send/process COOKIES [Andrew] * IKEv2: Delete partial Child SA states that can never establish [Paul] * IKEv2: Remove SHA1 from default proposals [Paul] * IKEv2: Add ECP groups and Curve25519 to default proposal [Paul] * IKEv2: Fix AH rekeying (handle not having encrypter [Paul] * IKEv2: NAT-T keepalives did not start if only IKEv2 conns were in use [Paul] * IKEv2: Drop IKE_SA_INIT requests with non-zero SPIr [Andrew] * IKEv2: On rekey, sometimes a CHILD SA was lost (wrong hash slot) [Andrew] * IKEv1: Don't leave a dangling pointer after IKE SA delete [Paul/Hugh] * IKEv1: Only sent NAT keepalives for IPsec states (suppresses 1 dup) [Paul] * IKEv1: Do not activate DPD when peer does not support it [Paul] * IKEv1: Reject key sizes <= 0 properly instead of crashing [Paul] * IKEv1: Fix Aggressive Mode interop with Volans Technology [wuwei29] * IKEv1: Remove bogus "duplicate Delete" check causing Windows 1m outage [Paul] * IKEv1: If whack socket not there for passwd input, return STF_FATAL [Paul] * IKEv1: Remove Win98 workaround ignoring IPsec SA deletes in first 60s [Paul] * X509: Do not keep received CERTs beyond the connection lifetime [Andrew] * X509: Support for NSS IPsec profiles mbz#1252891 [Kai Engbert/Paul] * X509: Don't fail validation on critical flag in Key Usage payloads [Paul] * X509: Fix ocsp-method=get|post to actually skip get when asked) [Stepan Broz] * X509: Fix various leaks [Hugh, Andrew] * X509: Cache contents read from NSS database for performance [Andrew] * pluto: Re-initialize (w backoff) conns that should remain "up" [Paul/Hugh] * pluto: Use any sent IKE message to reset the DPD/liveness counter [Paul] * pluto: Add timing information to packet processing [Andrew] * pluto: Significant performance improvements for conns and certs [Andrew] * pluto: Simplify state lookups and SPI passing [Andrew] * pluto: Speed up state lookups by only looking at proper hash chain [Andrew] * pluto: metric= value should accept values > 255 [Tuomo] * pluto: New "cpu-usage" plutodebug option displaying timing info [Andrew/Paul] * pluto: Refuse to load connections with TFC and AH or Transport Mode [Paul] * pluto: Fix memory leak in CERTREQ sending [Hugh] * pluto: Revive (with back-off) auto=start conns that receive Delete/Notify [Paul] * pluto: Show all activated impairments in ipsec status [Andrew] * pluto: Do not load a connection if its certificate has a problem [Andrew] * pluto: Handle case when external use deletes certificate from NSS [Andrew] * pluto: Fix resource leaks [Andrew/Hugh] * pluto: Improve and extend pluto statistics [Paul] * pluto: Deleting a connection should bring it down first to run _updown [Paul] * pluto: Revive auto=start conns that receive Delete/Notify [Paul/Hugh/Andrew] * pluto: Refuse to load connections with unsupported type=transport [Paul] * pluto: Refuse to load connections with TFC and AH or Transport Mode [Paul] * addconn: Fix crash on startup with dnssec-enable=no [Stepan Broz] * libswan: Only use valid ephemeral ports for libunbound context [Stepan Broz] * libswan: Do not process DNSSEC root key or trust anchors when disabled [Paul] * libipsecconf: conn %default content could get overwritten rhbz#1704085 [Hugh] * libipsecconf: Allow IKEv2 style ike/esp proposals using '+' symbol [Andrew] (example: ike=aes_gcm+chacha20_poly1305,aes-sha2+sha1) * libipsecconf: Updated defaults for filling in proposal elements [Andrew] (drop sha1, sha2_512 before sha2_256 for esp, lots of new DH groups) * libipsecconf: Be more tolerant of duplicate proposals and 'none' DH [Andrew] * confreadwrite: Fix double host printing, line and bad ikev2=UNKNOWN [Paul] * ipsec: Add "ipsec traffic" as shorthand for "ipsec trafficstatus" [Paul] * ipsec: Add "ipsec brief" as shorthand for "ipsec briefcstatus" [Paul] * _stackmanager: Do not attempt to load PF_KEY (af_key.ko) module [Paul] * whack: Fix option name to and documentation of ms-dh-downgrade [Tuomo] * whack: Two new impairments: del-with-notify and bad-ikev2-xchg [Andrew/Paul] * whack: Fix non operational connection flags / arguments [Daniel Kautz] * whack: Add new --briefstatus which skips showing all states [Paul] * auto: Fix replace operation for when changing from subnet= to subnets= [wuwei29] * verify: Removed broken IP forwarding check [Paul] * FIPS: X.509 minimum public key size check was rejecting valid keys [Paul] * FIPS: Disallow AES-XCBC from PRF/INTEG, Allow AES-GMAC [Paul] * FIPS: Fixup FIPS_IKE_SA_LIFETIME_MAXIMUM to 24h as per NIST SP 800-77 [Paul] * FIPS: Force IKE maximum lifetime of 24h (default is 1h) [Paul/Vukasin] * XFRM: Use netlink for last remaining obsolete PF_KEY API API calls [Antony] * XFRM: Clean up and aadd logging to IPsec SA for nic-offload= [Hugh/Paul] * XFRM: Set default XFRM_LIFETIME_DEFAULT to 30 (was 300) [Paul] * libswan: Fix leaks in badly formed secrets/ppk_id [Vukasin Karadzic] * libswan: Don't crash on mangled PSK or PPK secrets [Vukasin Karadzic] * initsystems/systemd: Install tmpfiles config when installing unitfile [Tuomo] * barf: No longer look for netstat, ifconfig and mii-tool [Paul] * building: Sort all wildcarded object files for build reproducibility [dkg] * building: Update NSS includes to not use obsoleted header files [Paul/Andrew] * building: USE_NSS_AVA_COPY ?= false, only needed with NSS < 3.30 [Tuomo] * building: USE_UNBOUND_EVENT_H_COPY ?= false, enable only for [Tuomo] unbound <= 1.7.3 without unbound-event.h * building: Fix UNBOUND_VERSION testing so result compiles on Fedora 29 [Hugh] * building: USE_NSS_IPSEC_PROFILE ?= true, Requires nss >= 3.41 [Tuomo] * building: Support for unbound > 1.8.0 [Antony] * building: Update XFRM headers [Antony] * building: Add 'make install-rpm-dep' and 'make install-deb-dep' [Antony] * testing: Lots of new and improved test cases [lots of people] * packaging: Add a spec file for RHEL8/CentOS8 [Paul] * packaging: debian: explicitly set ARCH for reproducibility [dkg] * packaging: debian updates [Antony/Paul] v3.27 (October 7, 2018) * XFRM: SA marks must be included for delete operation [Tijs Van Buggenhout] * pluto: Resolve a crasher in ECDSA freeing code [Hugh/Sahana] * pluto: Resolve a hang when recursively loading same config file [Hugh] * pluto: Refuse to load conns with different subnet address families [Paul] * IKEv2: Fix regression on ID_NULL causing a new conn instance [Paul] * IKEv1: Drop duplicates when not a reply [Andrew] * IKEv1: Don't respond with errors to invalid encrypted packets [Andrew] * IKEv1: Don't print empty informational warning on delete payload [Paul] * IKEv1: Don't add spurious ESP-NULL proposal to AH proposals [Andrew] * whack: Release whack socket on IKE_AUTH errors [Andrew] * libswan: fix buffer size to getnameinfo() call in resolve_ppp_peer() [Hugh] * libipsecconf: Don't accidentally clear modecfgdomains= entries [Andrew] * building: Fixup NSS includes and links (fixes Debian builds) [Andrew/Paul] * documentation: Update (L)GPL license links and http -> https links [dkg] * Bugtracker bugs fixed: #177 left=%defaultroute not working when "src" in the default route [Kim] #80 VTI interface vanishes when peer goes down and up [yu-shiba] v3.26 (September 16, 2018) * IKEv2: Support for RSA-PSS (RFC 7427) via authby=rsa-sha2 [Sahana Prasad] * IKEv2: Support for ECDSA (RFC 7427) via authby=ecdsa-sha2 [Sahana Prasad] * IKEv2: Use DER handling code of NSS instead of our custom code [Andrew] * IKEv2: Fix core dump when impaired and proposing esp=null-none [Andrew] * IKEv2: Fix traffic selector lookup for asymmetric conns [Andrew/Paul] * IKEv2: Add IKE and ESP support for chacha20poly1305 (RFC 7634) [Andrew] * IKEv2: Fix leaks in ikev2_calculate_rsa_hash [Hugh] * IKEv2: Simplify proposal generating [Hugh] * IKEv1: Fix handling XAUTH empty passwords [Andrew] * IKEv1: Various code cleanup, next payload handling [Hugh] * IKEv1: fix optional key-length regression (in v3.25) with ESP prop [Andrew] * IKEv1: Don't delete replaced IKE SA, it confuses third party clients [Paul] * pluto: Relax strictness of DH in ESP/AH proposals [Andrew] * pluto: Fix for two roadwarriors using ID_IPv4 behind same NAT [Paul] * pluto: Do not hand out old lease address for authby=secret conns [Paul] * pluto: new --selftest option that exits pluto after startup tests [Paul] * pluto: Updated known Vendor ID table [Paul] * XFRM: Don't call init_pfkey() on boot so Linux upstream can kill it [Andrew] *_unbound-hook: Fixup adding IPv4 pubkey, unbound now quotes arg as 1 [Paul] * building: Fix listed patches for debian build [Paul] * building: enable DH31 (curve25519) per default [Paul] * building: disable DH23,DH24 per default [Paul] * testing: prepare to migrate from f22 to f28 [Andrew, Antony, Paul] * Bugtracker bugs fixed: #166 IPsec/XAuth reusing lease for multiple clients behind same NAT [Paul] v3.25 (June 27, 2018) * IKEv2: MOBIKE Initiator support (RFC 4555) [Antony] * IKEv2: Support for IKE SA rekeying RFC7296 1.3.2, initiator [Antony] * IKEv2: Support for IPsec SA rekeying RFC7296 1.3.3, initiator [Antony] * IKEv2: Support for IKE SA reauth=yes|no RFC7296 2.8.3 [Antony] * IKEv2: Temporarily disable Liveness/DPD when MOBIKE kick in [Antony] * IKEv2: No longer allow contradicting esp= and pfs= options [Andrew] * IKEv2: PPK support for authby=rsasig [Vukasin Karadzic] * IKEv2: Support for CURVE25519 (RFC 8031) [Andrew] * IKEv2: IANA INTERNAL_DNSSEC_TA allocation added [Paul] * IKEv2: Add PPK support to authby=rsasig [Vukasin] * IKEv2: Don't calculate NO_PPK_AUTH when the POLICY is INSIST [Vukasin] * IKEv2: fix PPK when responder is ppk=no but has a valid PPKID [Paul/Vukasin] * IKEv2: Support for protoport based Opportunistic IPsec [Paul] * IKEv2: Support multiple authby values (eg authby=rsasig,null) [Paul] * IKEv2: Support for AUTHNULL fallback via private use Notify [Vukasin] * IKEv2: Fix v3.23 regression causing liveness check to always fail [Tuomo] * IKEv2: Support for Microsoft rekey bug: ms-dh-downgrade=yes|no [Andrew/Paul] * IKEv2: Allow switching between OE instances with different protoports [Paul] * IKEv2: process INITIAL_CONTACT and delete old states from a connection [Paul] * IKEv2: Only retransmit fragments on receiving first fragment [Andrew] * IKEv2: When sending fragments, also update st_msgid_lastreplied [Paul] * IKEv2: Encrypt IKE_AUTH reply when authenticaion failed [Andrew] * IKEv2: Fix handling of corrupt encrypted packets [Andrew] * IKEv2: Do not call ISAKMP_SA_established() during CREATE_CHILD_SA [Paul] * IKEv2: When receiving Initial Contact, delete old IPsec SA's [Paul] * IKEv2: Harden IP triggered OE with new dns-match-id=yes|no [AntonyPaul] * IKEv2: Add PRF/INTEG support for AES_XCBC / AES_CMAC [Andrew] * IKEv2: permit DH=none (as in esp=aes;none,aes;dh22) [Andrew] * IKEv1: Prevent crashes with IKEv1 mistakenly allowing narrowing=yes [Paul] * IKEv1: DPD was not getting scheduled (bug introduced in 3.23) [Paul] * IKEv1: modecfg_send_set() must not ignore failure of modecfg_resp() [Hugh] * X509: Extend support for wildcard certs matching remote peer ID [Paul/Hugh] * X509: Support PKCS7 for Microsoft interop with intermediate certs [Andrew] * X509: Handle CRL fetching in separate thread [Andrew] * pluto: Obsoleted connaddrfamily= (fixes 6in4 and 4in6) [Paul] * pluto: New hostaddrfamily= and clientaddrfamily= (only needed w DNS) [Paul] * pluto: Cleanup of state/md passing code [Andrew] * pluto: Allow switching back from wrong instance to template conn [Paul] * pluto: disentangle IKEv1 and IKEv2 packet sending code [Andrew] * pluto: Allow rightsubnets= without leftsubnet(s)= [Paul] * pluto: don't share IP leases for authby=secret (in case of group ID) [Paul] * pluto: Parser bug prevented 4in6 config [mhuntxu at github, Daniel M. Weeks] * pluto: Find and delete old connection/states with same ID [Paul/Hugh] * pluto: traffic log (and updown) line had in/out bytes swapped [Paul/Tuomo] * pluto: Fix memory/fd leaks found by Coverity and in cert code [Hugh/Andrew] * pluto: Improve SPD longest prefix to priority calculation [Andrew/Paul/Hugh] * addconn: Fix auto=route and auto=start processing [Paul] * whack/auto: Ensure all status and list commands return no error code [Paul] * KLIPS: Replace deprecated blkcipher with skcipher crypto API [Tijs Van Buggenhout] * FIPS: Support new NIST ACVP protocol with cavp tool cmdline args [Andrew] * FIPS: Don't attempt HMAC integrity test on rsasigkey (rhbz#1544143) [Paul] * FIPS: Don't allow RSA keys < 3072 [Matt/Paul] * FIPS: Enable our PRF aes_xcbc wrapper on NSS hash code in FIPS mode [Andrew] * FIPS: Raise minimum RSA key length allowed to 3072 [Paul] * CAVP: Add - and -json(output) options to CAVP [Andrew] * portexcludes: new command ipsec portexcludes (see portexcludes.conf) [Paul] * _updown.netkey: fix deleting routes when half routes are used [Tuomo] * _updown.netkey: don't delete VTI interfaces until we can refcount [Tuomo] * _updown.netkey: fix unroute: "need at least a destination address" [Tuomo] * _updown.netkey: don't do proxyarp for direct host-host tunnels [Tuomo] * _updown.netkey: force routing if we don't have route to remote network [Tuomo] * _unbound-hook: Pass all IPSECKEY's to pluto, not just the first [Paul] * contrib/python-swan: module to check if traffic get be encrypted [Kim] * contrib/c-swan: example code to check if traffic get be encrypted [Kim] * building: added USE_GLIBC_KERN_FLIP_HEADERS (default off) [Paul] * building: when ElectricFence enabled, add extra system calls to seccomp [Andrew] * ipsec: add checknss option --settrusts to reset CA trusts in nss db [Tuomo] * _updown.netkey: force routing when necessary for IPsec to work [Tuomo] * _updown.netkey: do not proxyarp for host-host tunnels [Tuomo] * look: sort XFRM output by priority [Andrew] * Bugtracker bugs fixed: #311: segfault in crl fetching git master f5b17dc [Andrew, Tuomo] #314: IPv6 default route is deleted by mistake #318: vti interface gets down on previous initiator if roles switch [Tuomo] #320: nsspassword file location is half implemented #328: Addcon crash on duplicit "left" or "leftid" keys in conn config [Stepan Broz] v3.24 (June 26, 2018) * This release was never published v3.23 (January 25, 2018) * IKEv2: MOBIKE Responder support (RFC 4555) [Antony/Paul] * IKEv2: Add support for modecfgdns= and modecfgdomains= like for IKEv1 [Paul] * IKEv2: EXPERIMENTAL: Support for Postquantim Preshared Keys [Vukasin Karadzic] based on draft-ietf-ipsecme-qr-ikev2-01 (using private use numbers) new option: ppk=yes|no|insist (default no) * pluto: Fix DEFAULT_RUNDIR to be set so it is really configurable [Tuomo] * pluto: Add support IDr payload (You Tarzan, me Jane) [Paul] * pluto: pass state to send_crypto_helper_request() [Andrew] * pluto: Internal time/scheduling changes, micro-seconds logging [Andrew] * pluto: make counts of states consistently "unsigned" [Hugh] * pluto/lib: Remove obsoleted/unused %myid support [Paul] * pluto: add --impair replay-forward,replay-backward [Andrew] * pluto: add --impair dup-incoming-packets [Andrew] * pluto: Rework nic offload detection code [Aviv Heller] * pluto: Retry send on -EAGAIN in check_msg_errqueue() (up to 32x) [Paul/Hugh] * pluto: Pull latest kernel traffic counters before logging/deleting SA [Paul] * pluto: STF_INLINE, STF_TOOMUCHCRYPTO no longer needed in helpers [Andrew] * pluto: Replace socket queues with a simple queue and mutex+cont [Andrew] * pluto: Do not send DPD/liveness probes for replaced inactive IPsec SAs [Paul] * pluto: crypto processing cleanup [Andrew] * XFRM: XFRM_MIGRATE support, used for MOBIKE [Antony] * XFRM: Listen to NETLINK_ROUTE messages from kernel for MOBIKE [Antony] * XFRM: Fix unique marks accidentally setting -1 instead of random [Paul] * XFRM: Only install IPv6 holes when system has configured IPv6 [Antony] * XFRM: Add support for decap-dscp=yes|no (default no) [Paul] * XFRM: Add support for nopmtudisc=yes|no (default no) [Paul] * KLIPS: Support kernels 4.14+ with renamed dev->priv_destructor [Paul] * KLIPS: updown fixes for IPv6 default route and metric/mtu settings [Wolfgang] * SECCOMP: Update syscall whitelist for use of libunbound [Paul] * IKEv1: better handle ESP with no integrity vs unknown integrity [Andrew] * IKEv1: Fix packet retransmit code wrf timeouts vs duplucates [Andrew] * IKEv1: Prevent duplicate responder states on retransmision [Andrew] * IKEv1: Don't linger R1 states for 1h but use configured timeouts [Paul] * IKEv2: nat_traversal_change_port_lookup() code moved [Antony] * IKEv2: Macros could misinterpret some IKE/IPsec states [Paul/Antony] * IKEv2: Updated Group transforms to comply with RFC 8247 [Paul] * PAM: Don't cancel pam threads (unsupported!) but drop results instead [Andrew] * _updown: Fix resolv.conf handling (github #130) [Tuomo] * _updown: Fix POINTPOINT interfaces not to use nexthop [Tuomo] * _updown.netkey: Add source ip to dev lo by default [Tuomo] * Makefiles: Fix INC_MANDIR to be share/man and add FINALMANDIR [Tuomo] * packaging: Move debian/ to packaging ('make deb' still works) [Antony] * contrib: Added ipsec-dyndns to demonstrante how push an IPSECKEY [Paul] * Bugtracker bugs fixed: #313: changesource in updown_klips doesn't respect PLUTO_METRIC [Wolfgang] #314: IPv6 default route is deleted by mistake [Wolfgang] v3.22 (October 22, 2017) * IKEv2: EXPERIMENTAL: unbound DNS server ipsecmod support [Opportunistic IPsec] * IKEv2: Initial support for RFC 7427 Digital Signature [Sahana Prasad/GSoC] * IKEv2: Do not include INTEG=NONE in AEAD IKE proposals [Andrew] * IKEv2: Accept both ESP=AEAD+NONE and ESP=AEAD in proposals [Andrew] (See also: https://www.rfc-editor.org/errata/eid5109) * IKEV2: Fix interop with old pluto that rejected esp=aead+none [Andrew] * IKEv2: Add support for GMAC via esp=null_auth_aes_gcm [Andrew] * IKEv2: Fragmentation code cleanup and memory leak fixes [Andrew] * IKEv1: Fix XAUTH retransmits and packet storage [Antony] * IKEv1: Perform custom state change for XAUTH without ModeCFG [Paul] * IKEv1: Add support for nat-ikev1-method=none [Paul] * IKEv1: XAUTH password length wasn't consistent at 128 [Stepan Broz] * pluto: Natively install ICMPv6 neighbour discovery holes [Mayank Totale/GSoC] * pluto: Fixup XAUTH/PAM thread cancellation handling [Andrew/Antony] * pluto: Change default rundir from /var/run/pluto to /run/pluto [Paul] * pluto: Various ike_alg parsing updates [Andrew] * pluto: Various cleanups in addresspool and XAUTH code [Hugh] * pluto: Fix missing ntohl() on the SPI numbers in ipsec status [Paul] * pluto: Various memory leak fixes [Antony,Paul,Hugh] * pluto: Make ioctl(SIOCGIFFLAGS) failure for labeled devices non-fatal [Paul] * pluto: Give IKE traffic preference via SO_PRIO [Paul] * pluto: New setup options: ike-socket-errqueue= , ike-socket-bufsiza=e [Paul] * pluto: Improve whack --listevents with libevent [Antony] * pluto: Fixup NIC offload support [Antony, Hugh] * pluto: Track and try the number of EAGAIN errors on IKE socket [Hugh/Paul] * pluto: Prevent spurious initiating states on responder-only conn [Antony] * pluto: don't call sanitize_string() in fmt_log() as it is expensive [Paul] * pluto: No longer need to specify null for AEAD, can use esp=aes_gcm [Andrew] * pluto: Increase default nhelpers for 1 CPU (2) and 2 CPUs (4) [Paul] * pluto: New option logip= (default yes) to disable log of incoming IPs [Paul] * pluto: signal handling cleanup [Andrew/Hugh] * pluto: Don't try to retransmit unsent packet [Paul/Hugh] * pluto: state hashing improvements [Andrew] * pluto: Fix erranious connecting switching (bug in v3.21) [Paul] * pluto: when deleting parent, don't deschedule DH for wrong child [Andrew] * pluto: dpdaction=restart fixup when using %any [Antony] * pluto: Don't die on labeled interfaces without SIOCGIFFLAGS support [Paul] * addconn: left=%defaultroute would fail if >500 host routes [Kim] * showhostkey/rsasigkey: Fixup mismatch of public key display [Andrew] * FIPS: Some selftests did not run properly under FIPS mode [Andrew] * KLIPS: Removed old premade patches, use make targets instead [paul] * updown Don't remove source ip if it's still used (rhbz#1492501) [Tuomo] * updown: Allow disabling via leftupdown="" or leftupdown="%disabled" [Paul] * updown: SPI numbers were missing ntohl() conversion [Paul] * various: phase out --ctlbase for --ctlsocket and --rundir [Paul] * libipsecconf: reject unavailable kernel algorithms in parser [Andrew] * libswan/pluto: throw a clearer error for broken libunbound [Paul] * libswan/pluto: Cleanup logging and tighten logging lock [Andrew] * libswan/pluto: Greatly optimize logging code [Andrew] * libswan/pluto: Some logging algorithm renames for more consistency [Andrew] * building: remove -fexceptions; breaks pthread_cleanup_push [Andrew] * packaging: Update debian/ and move to packaging/debian [Antony] * packaging: Update fedora/rhel spec files [Tuomo] * testing: --impair-foo changed to --impair foo [Andrew] * testing: Some new impair options for testing [Andrew,Sahana,Paul] * testing: Allow null encryption with null auth for testing [Andrew] * Bugtracker bugs fixed: #294: Bug in public key reported by rsasigkey [Tijs Van Buggenhout/Andrew] #299: Fix overlapping addresspool and static lease from passwd file [Antony] #300: Fix bug in v3.21 that rejected hardcodes certs without a CA [Paul] #302: IKEv1-only and IKEv2-only must not share IKE SA [Paul] #303: xauth password length limited to 64 bytes [Stepan Broz] v3.21 (August 9, 2017) * FIPS: Don't crash on too weak PSK's in FIPS mode, warn for non-FIPS [Andrew] * FIPS: rsasigkey: Use modulus F4, not 3 (FIPS 186-4, section B.3.1) [Paul] * pluto: Support for "idXXX" esp/ike transform IDs removed [Andrew,Paul] * pluto: Do not return whack error when termining an alias connection [Paul] * pluto: Remove IKE policy bits on passthrough conns [Paul] * pluto: Minor memory leak fixes [Paul] * pluto: Fix memory leak due to addresspool reference count error [Antony] * pluto: Re-add support for ipsec whack --listevents [Antony] * pluto: Cleanup listed events on shutdown to please leak-detective [Antony] * pluto: Perform stricter SubjectAltName checks on configured ID's [Paul] * pluto: Handle *subnets in --route and --unroute via whack [Mika/Tuomo] * pluto: Unify IKEv1 XAUTH and IKEv2 PAM threading code [Andrew] * pluto: Use pthread_cancel() (not SIGINT, conflicts with debuggers) [Andrew] * pluto: Fix memory corruption with XAUTH/PAM threads [Andrew/Hugh] * pluto: Fix resource leak processing XAUTH password authentication [Andrew] * pluto: Fix warnings generated by gcc 7.1 [Lubomir Rintel] * pluto: NIC offload support nic-offload=auto|yes|no (eg mellanox) [Ilan Tayari] * pluto: Use common function in ikev1 / ikev2 for dpd/liveness actions [Antony] * NSS: Try harder finding private keys that reside on hardware tokens [Andrew] * IKEv2: Opportunistic IPsec support for IPSECKEY records [Antony] * IKEv2: New dnssec-enable=yes|no, dnssec-rootkey-file=, dnssec-anchors= [Paul] * IKEv2: If CREATE_CHILD_SA superseded retransmit, drop it [Antony] * IKEv2: Add PFS support for CREATE_CHILD_SA (RFC7296 1.3.1) [Antony] * IKEv2: Add PFS support for CREATE_CHILD_SA (RFC7296 1.3.2 responder) [Antony] * IKEv2: Add PFS support for CREATE_CHILD_SA (RFC7296 1.3.3 responder) [Antony] * IKEv2: Flush ESP/AH proposals on the initiator. It could be stale [Antony] * IKEv2: State Machine (svm) updates to simplify CREATE_CHILD_SA [Antony] * IKEv2: DH role is based on message role not Original Initiator role [Antony] * IKEv2: Return CHILD_SA_NOT_FOUND when appropriate [Antony] * IKEv2: After an IKE rekey, rehash inherited Child SA to new parent [Antony] * IKEv2: Rekeying must update SPIs when inheriting a Child SA [Antony] * IKEv2: Decrypt and verify the paylods before calling processor [Andrew] * IKEv2: Fragmentation code cleanup [Andrew] * IKEv2: Drop CREATE_CHILD_SA message when no IKE state found [Antony] * IKEv2: Do not send a new delete request for the same Child SA [Antony] * IKEv2: During Child SA rekey, abort when ESP proposals mismatch [Antony] * IKEv2: OE client check should take responders behind NAT into account [Paul] * IKEv2: Improved dpdaction=hold processing [Antony] * IKEv1: Only initiate and create IKE SA for appropriate dpdaction [Antony] * IKEv1: Re-add SHA2_256 (preferred) and SHA2_512 to IKEv1 defaults [Andrew] * IKEv1: Aggressive Mode fixes for sending CERT / CERTREQ payloads [Paul] * IKEv1: Multiple CISCO_SPLIT_INC's cause duplicate spd_routes [Oleg Rosowiecki] * X509: Improve some failure logging [Paul] * XFRM: Use proper alignment for IPv4 AH as per RFC4302 Section 3.3.3.2.1 [Paul] * XFRM: Update including system or local copy of xfrm.h [Paul/Antony] * XFRM: Remove no longer needed {rt}netlink.h copies [Paul] * KLIPS: cryptoapi: switch from hash to ahash [Richard] * KLIPS: Add traffic accounting support [Richard/Paul] * KLIPS: Support for linux 4.11 [Paul] * lib: Move the alg_info lookup-by-name code to libswan [Andrew] * lib: Move all conditionally compiled ike_alg*.c files to libswan.a [Andrew] * addconn: Replace ttoaddr() with calls supporting DNSSEC [Paul/Antony] * libswan: Algo code cleanup [Andrew] * libipsecconf: Load specified RSA keys irrespective of policy [Paul] * libipsecconf/pluto: Be more strict in authby= & type= combinations [Paul] * libipsecconf: Fail to load connections with unsatisfied auto= clause [Hugh] * parser: Numerous algorithm parser fixes, eg. esp=aes_ccm_8_128-null [Andrew] * algparse: (Experimental) modified to run algorithm parser stand-alone [Andrew] * newhostkey: Actually append to secrets as the warning claims it will [Paul] * _updown.netkey: Fix syntax failure when PLUTO_MY_SOURCEIP is not set [Tuomo] * _updown.netkey,klips: Fix use of printf when updating resolv.conf [Tuomo] * _updown.netkey: Remove wrong use of PLUTO_PEER_CLIENT netmask [Tuomo] * _updown: Add MAX_CIDR variable for host netmask [Tuomo] * ipsec import: Trust bits correction did not always trigger [Tuomo] * building: Convert lib/ to use mk/library.mk [Andrew] * building: Work around rhel-6 gcc [Andrew] * building: Add copy unbound-event.h work around broken unbound installs [Paul] * packaging: Better split rpm and make variables [Paul] * packaging: Updates for new requirements for ldns, unbound-devel [Paul] * testing: Add DNSSEC, Opportunistic IPsec testcases, fixups [Multiple people] * contrib: Munin plugin for libreswan [Kim/Paul] v3.20 (March 14, 2017) * pluto: Add ECP dh19(secp256r1), dh20(secp384r1) and dh21(secp521r1) [Andrew] * pluto: Add dh= aliases for all modp= groups (eg "dh2" for "modp1024") [Paul] * pluto: Add statistics support to ipsec whack --globalstatus [Paul] * pluto: Add statistics clearing support using ipsec whack --clearstats [Paul] * pluto: Fix use-after-free in whack event handler (since v3.19) [Andrew] * pluto: Cleanup kernel_netlink.c [Hugh] * pluto: Print AH= algorithm and ESN when established [Paul/Andrew] * pluto: strip file path from abort messages [Andrew] * pluto: Support initiating template conn with --remote-host [Paul] * pluto/libswan: Change most ttoaddr() to ttoaddr_num() to prevent DNS [Paul] * pluto: fix use-after-free with EVENT_v2_RELEASE_WHACK [Andrew] * pluto: orient() asserted on SPLIT_INC without remote-peer-type=cisco [Paul] (reported by Oleg Rosowiecki) * pluto: accurately size a buffer for the decimal representation [Hugh] (debian bug 853507) * pluto: avoid gcc unused variable warnings when USE_KLIPS=false [dkg] * pluto: Support for Linux systems without IFA_F_TENTATIVE (CentOS5) [Paul] * pluto: Ignore uniqueids= for roadwarrior PSK and assume non-unique [Paul] * IKEv2: CREATE_CHILD support for Parent SA and Child SA rekeying [Antony] * IKEv2: Various refactoring for CREATE_CHILD support [Antony] * IKEV2: OE/CAT: Don't send CP request when responder is behind NAT [Antony] * IKEv2: log first notify payload when we receive an Notify Error [Paul] * IKEv2: Fix memory leak in DH secret calculation (since v3.9) [Andrew] (reported by Eric Andersson) * IKEv2: If re-entering ikev2_crypto_start(), reset msgid [Paul] * IKEv2: prevent copying bogus peer id when ID kind is IPv4/IPv6 [Paul] (rhbz#1392191) * IKEv2: suppress DELETE notifies for connections being replaced [Paul] * IKEv2: re-instate ISAKMP_SA_established() [Paul] * IKEv1: For IKE (phase 1), prefer 256-bit bit encryption [Andrew] * IKEv1: Print conn algo's when using XAUTH [Andrew] * IKEv1: Simplify ike= defaults (drop MODP1024, MD5, add MODP2048) [Andrew] * IKEv1: Prefer 256-bit keys over 128-bit keys for IKE [Andrew] * IKEv1: Also call ISAKMP_SA_established() in Aggressive Mode [Paul] * newhostkey: Convert remaining --configdir for --nssdir [Tuomo] * barf: Ensure proper macros are used. Add certutil/crlutil output [Paul] * misc: Fix various spelling errors in code/comments/man pages [dkg] * packaging: spec files should use 0 and 1, not true and false [David Arnold] * building: NSS_REQ_AVA_COPY?=true to support new NSS lib export fix [Paul] * building: Remove no longer needed NSSCERT_CheckCrlTimes() copy [Paul] * building: fetch: remove support for ancient LDAP version 2 [Tuomo] * building: move whack to separate programs/whack/ directory [Andrew] * building: Various Makefile variable cleanups and double link fixes [Andrew] * building: Don't check runtime for SElinux/systemd with DESTDIR [Paul] * documentation: added oe-letsencrypt-* example configs [Paul] v3.19 (January 15, 2017) * NSS: Support for configurable nss dir via @IPSEC_NSSDIR@ [dkg/Tuomo] * FIPS: Only pluto needs a .hmac file, reducing crypto boundary [Paul] * FIPS: do not allow DBG_PRIVATE to be set when running in FIPS mode [Paul] * FIPS: Ignore failureshunt=passthrough and negotiationshunt=passthrough [Paul] * FIPS: Filter default proposals of non-FIPS allowed proposals [Andrew] * FIPS: Added CAVP test for pluto GCM code [Andrew] * FIPS: More cleanup of crypto related structs and functions [Andrew] * FIPS: Implement SHA based PRFs directly in NSS [Andrew] * FIPS: Support for CAVP testing 'HMAC construct' based SHA PRF code [Andrew] * IKEv2: Don't crash on bogus mixed protocol Delete Payloads [Hugh/Paul] * IKEv2: Add asymmetric AUTH support (leftauth= and rightauth=) [Antony/Paul] * IKEv2: refactored AUTH handling payload into v2_check_auth() [Paul] * IKEv2: support CERT chain sending [Paul] * IKEv2: Allow CERT and CERTREQ payloads multiple times [Paul] * IKEv2: do not attempt to send notify in reply to IKE_AUTH reply [Paul] * IKEv2: When receiving DELETE, ensure expire+restart when needed [Antony] * IKEv1: If a queued up DPD probe finds no IKE SA, create a new one [Paul] * IKEv1: accept_delete() check if IKE SA is shared before deleting [Paul] * IKEv1: Remove ADNS, DNS continuations and IKEv1 OE code [Paul/Antony] * IKEv1: Schedule IPsec SA REPLACE immediately when receiving DELETE [Antony] * IKEv1: Some IKE SA failure on initiator could lead to hanging whack [Paul] * KLIPS: fix for unregister_netdevice() for Linux 3.6.11 and up [Richard/Paul] * XFRM: EXPERIMENTAL Support for configuring IP address on the VTI device [Paul] keyword: leftvti=address/mask * XFRM: Fix NAT-T support when userland compiled without KLIPS support [Paul] * X509: Obsolete /etc/ipsec.d/crls (load_crls()) and whack --rereadcrls [Paul] * X509: New whack --fetchcrls (alias ipsec crls) to trigger a fetch [Paul] * X509: Iterate all X.509 certs and try to fetch their crls [Kim] * X509: Start a fetch for CRLs 5 seconds after startup [Kim] * X509: --rereadcrls no longer overwrites newer CRLs with older ones [Paul] * X509: log the NSS error when CERT_ImportCerts() fails [Paul] * X509: Don't attempt to fetch crl->uri when not present [Paul/Matt] * X509: Additional OCSP options to tweak the cache and fetch method [Paul] (new keywords: ocsp-method ocsp-cache-size ocsp-cache-min-age ocsp-cache-max-age) * X509: Fix memory leak in certificate handling (lsbz#278) [William Rios] * X509: Fix memory leak in certificate chain handling [Matt] * pluto: close whack socket in add_pending when dup pending is skipped [Hugh] * pluto: Avoid adding duplicate bare shunts causing lockup [Paul] * pluto: drop modp1024 (DH2) from IKEv1 "ike=" default list [Andrew] * pluto: send_packet() now refuses to send a packet to 0.0.0.0 [Paul] * pluto: find_hostpair ignore CK_INSTANCES that are ID_NULL [Antony] * pluto: Fix ca name and generalName leak lsbz#276 [Bill Rios] * pluto: EXPERIMENTAL SECCOMP support (seccomp=enabled|tolerant|disabled) [Paul] * pluto: connection instances need their own reqid [Antony] (this resolves multiple clients behind same NAT router issue) * pluto: Use a global reqid counter instead of looping every time [Paul] * pluto: use sets instead of nested loops for transform processing [Andrew] * pluto: Prefer not switching connections when possible [Paul/Hugh] * pluto: Move unique mark from rw_instantiate() to instantiate() for OE [Paul] * pluto: log more information when a bare shunt is missing [Hugh] * pluto: redo process_encrypted_informational_ikev2 [Hugh] * pluto: Add new config option encapsulation=auto|yes|no [Paul/Patrick Kerpan] replacing forceencaps=yes|no * pluto: No longer log bogus reapchildren warning [Paul] * libipsecconf: libipsecconf: remove last remnants of manual keying [Paul] * libipsecconf: remove auth= alias for phase2= [Paul] * _updown.netkey: Move addcat call from route-host to up-client [Paul] * ipsec: initnss|import use --nssdir for nssdb directory option [Tuomo] * newhostkey: use --nssdir for nssdb directory option [Tuomo] * showhostkey: use --nssdir for nssdb directory option [Tuomo] * barf: minor improvements with systemd/journalctl [Paul] * verify: fix "with FIPS" output to print OK [Paul] * _stackmanager: add cmac and chacha20poly1305 to modprobe list [Paul] * building: libreswan assumes -std=gnu99 when building [Andrew] * building: USE_EXTRACRYPTO replaced by USE_SERPENT and USE_TWOFISH [Paul] * building: Disable DH22 by default. To re-enable use USE_DH22=true [Paul] * building: work around flex 2.5.4 (CentOS 5); use: -o/output/file [Andrew] * sysvinit: remove unnecessary warnings about already stopped pluto [Tuomo] * initsystems: Enable "systemctl help ipsec" [dkg] * testing: various web output fixes (see testing.libreswan.org) [Andrew] * testing: various test updates / additions [Paul/Antony] * documentation: fixup changes in GPL 2.0 / LGPL like FSF address [dkg] * Bugtracker bugs fixed: #270 newhostkey: text output produces 1 character bug in pubkey [Andew] #272 Option --leak-detective causes assertion failure [Bill / Paul] #277 pluto: fix pluto events leak in timer_event_cb [Bill Rios] #152: ipsec whack --initiate for xauth does not release whack [Paul/Hugh] v3.18 (July 27, 2016) * SECURITY: CVE-2016-5391: IKEv2 proposal lacking DH causes restart [Andrew] * XFRM: EXPERIMENTAL Support for NAT OE Client Address Translation [Antony] keyword: leftcat=yes|no * XFRM: EXPERIMENTAL Support for routed-VPNs using VTI [Paul/Tuomo] keywords: vti-interface= vti-routing=yes|no vti-shared=yes|no * XFRM: EXPERIMENTAL Support for Traffic Flow Confidentiality tfc=XXX [Paul] * KLIPS: Fix for /proc/net/pf_key oops on < 4.4 [Erik Andersson] * KLIPS: Fix overwriting the sk pointer in 4.4 kernels [Ofer Heifetz] * FIPS: Only the pluto binary needs a fipscheck .hmac file for self-test [Paul] * FIPS: Change SA_LIFE_DURATION_MAXIMUM from 1 day to 8h [Paul] * FIPS: Do not allow Linux-style sha2 truncation for ESP in FIPS mode [Paul] * FIPS: Allow PSK in FIPS mode. This was erroneously not allowed [Paul] * FIPS: Added new ipsec whack --fipsstatus [Paul] * IKEv2: For default proposals, prefer MODP2048 over MODP1536 [Andrew] * IKEv2: For proposals like ike=aes-sha2, prefer AES_256 over AES_128 [Andrew] * IKEv2: For default ESP proposals, include and prefer AES_GCM [Andrew] * IKEv2: For default ESP/AH proposals, do not propose MD5 integrity [Andrew] * IKEv2: Add MODP3072 to defaults to ease interop with strongswan [Andrew] * IKEv2: Prefer sha2-512 over sha2-256 for ESP to avoid linux bug [Andrew] * IKEv2: fix use of ikev2_cert_req_fields [Lubomir Rintel] * IKEv2: Extend and improve notify handling [Paul] * IKEv2: Update ike endpoint as per rfc7296#section-2.23 [Antony/Paul] * IKEv2: If first liveness probe failed, we never noticed liveness failure [Paul] * pluto: Extend mark= support for mark-in= and mark-out= [Paul] * pluto: implement unique marks by using mark=-1 [Paul] * pluto: Add systemd watchdog support via USE_SYSTEMD_WATCHDOG [Matt/Paul] * pluto: Follow connaddrfamily when resolving hostnames [Daniel M. Weeks] * pluto: Check enum names consistency on startup [Hugh] * pluto: Log mismatched DH group (KE payload) to log (not debug) [Andrew] * pluto: Don't try to delete non-existing ipsec sa's (github #50) [Paul] * pluto: Prevent double free of id data [Hugh] * pluto: Avoid crashing on gaining remote ip locally (rhbz#1229766) [Paul] * pluto: ESN could use uninitialised values and fail [Paul/Andrew] * X509: Try subsequent crl distribution points when first one fails [Kim] * whack: Display IPv4 lease address in --trafficstatus [Andrew] * libipsecconf: New keyword left/rightckaid=XXX [Andrew] * libipsecconf: Remove legacy keyword subnetwithin= [Hugh] * libipsecconf: Clean out kv_auto / kv_manual attributes [Hugh] * updown: Add SPI_IN= and SPI_OUT= to updown scripts [Paul] * programs: Removed obsoleted ikeping and livetest [Paul] * newhostkey: No longer touch any secret files [Andrew] * showhostkey: Only look at NSS - don't require ipsec.secrets [Andrew] * libswan: Fix unbound dnsctx handling [Hugh/Paul] * libswan/libipsecconf: Clean up SECRETS code [Andrew] * libswan: Delete getNSSPassword; replaced by lsw_nss_get_password [Andrew] * addconn: Find peer IP address when resolving default route [Daniel M. Weeks] * barf: If systemd detected, use journalctl to get logs [Paul] * building: The make variable NSSLIBS was renamed to NSS_LDFLAGS [Andrew] * building: Fix building without DNSSEC support [Hugh/Paul] * packaging: Updates for debian packaging [dkg] * initsystem: Add docker support using 'make INITSYSTEM=docker' [Kim] * ipsec import: Add --configdir|--ipsecdir option for nss db location [Tuomo] * _import_crl: Fix to work with nsspasswd [Andrew] * _stackmanager: Remove loading of hardware random modules [Tuomo] * _stackmanager: hide error if /proc/sys/net is read-only (i.e. docker) [Kim] * ipsec: remove run by root check for Neutron/VPNaaS [Tuomo] * ipsec: add option [--configdir|--ipsecdir /etc/ipsec.d] [Tuomo] * testing: Various improvements for running tests, include web tree [Andrew] * testing: New makefile targets, see 'make kvm-help' [Andrew] * testing: pluto support for --expire-bare-shunt [Paul] v3.17 (April 4, 2016) * SECURITY: CVE-2016-3071: IKEv2 aes_xcbc transform causes restart [Andrew] * pluto: replace make variable HAVE_NO_FORK with USE_FORK, USE_DAEMON, and USE_VFORK [Andrew] * pluto: add make variable USE_PTHREAD_SETSCHEDPRIO used by Darwin [Andrew] * IKEv2: Add Vendor ID support and VID_OPPORTUNISTIC [Paul] * IKEv2: Send VID_OPPORTUNISTIC when doing AUTH-NULL Opportunistic IPsec [Paul] * IKEv2: New keyword drop-oppo-null=no|yes (default no) [Paul] * IKEv2: ikev2_out_generic{_raw}() functions [Paul] * IKEv2: Raise minimum nonce size from 8 to 16 bytes as per RFC-7296 [Paul] * IKEv2: Ignore IKE_INIT replies with DOS COOKIE > 64 bytes [Paul] * IKEv2: Fix memory leak of dcookies [Paul] * IKEv2: Switch pluto to native IKEv2 SA code, disentangle from IKEv1 [Andrew] * IKEv2: Log local and remote IKE and ESP/AH proposal sets [Andrew] * IKEv2: ESN support (XFRM linux 2.6.39+) via esn=yes|no(default)|either [Paul] * IKEv2: Do not include aes_xcbc in proposal list until NSS supports it [Paul] * IKEv2: Prefer sha2_512 over sha2_256 over sha1 [Paul] * IKEv2: Use SHA2-256 instead of SHA1 as hash algorithm for dcookies [Paul] * IKEv2: Validate unexpected dcookies to limit TRANSCRIPT attack [Paul] * IKEv2: Don't duplicate failed IKE SA every pending cycle of 120s [Paul] * IKEv2: add --impair-send-bogus-dcookie for testing [Paul] * IKEv1: Packet retransmit fixes for Main/Aggr/Xauth modes [Paul] * IKEv1: Minor logging changes for DPD/NAT-T/AGGR [Paul] * IKEv1: Prefix a few functions with ikev1_* where not obvious [Paul] * IKEv1: Always send modecfg banner and domain if they are set [Lubomir Rintel] * pluto: fetch crls from middleCA/endcert AIA distribution points [Kim/Mika] * pluto: crls must be refreshed periodically, not only near expiry [Kim/Mika] * pluto: Raise IKEv1 and IKEv2 default nonce size from 16 to 32 bytes [Paul] * pluto: Don't delete IKE SA when shared with multiple connections [Paul] * pluto: connection restart failed for dynamic dns conns [Wolfgang] * pluto: Ignore tentative and failed IPv6 addresses [Lubomir Rintel] * pluto: Fix various coverity warnings and corner cases [Hugh, Paul] * pluto: Rename *xauthusername= to *username= (keep compat alias) [Paul] * pluto: accept/verify the KE contents before creating the state [Andrew] * pluto: Parse the IKE SA proposals before creating the state [Andrew] * pluto/rsasigkey: libgmp functions obsoleted by native NSS [Andrew] * pluto: Be more careful handling realloc() failure [Hugh] * pluto: Fix leaks in NSS/certificate handling code [William Rios] * pluto: Refuse to load conns with protoport=XX/%any on both sides [Paul] * pluto: Ignore unsupported keys from the NSS database [Andrew] * pluto: orphan_hold() can encounter connection in delete phase [Antony] * rsasigkey: Only print the comment line, pubkey and CKAID [Paul] * secrets: Remove wrapper for "ipsec secrets" and make it inline [Paul] * libipsecconf: Make handling of policy bits more systematic [Hugh] * barf: Only sysvinit printed the string "subsystem" [Paul] * FIPS: Code cleanup and misc. fixes [Andrew / Paul] * FIPS: Add _import_crl to the FIPS file list [Paul] * KLIPS: Support for Linux 4.4.x kernel (lsw#256) [Wolfgang] * KLIPS: IPv6 can't determine routing device (lsw#237) [Wolfgang] * KLIPS: Fix pluto compile for USE_KLIPS=false [Paul] * barf: Does not show pluto log correctly in the output (rhbz#1309764) [Paul] * packaging: debian/ fixes [Marc-Christian Petersen / Tuomo] * sysvinit: Fix displaying number of tunnels in status command [Paul] * Bugtracker bugs fixed: #258 DPD with dynamic dns can't reconnect a host connection [Wolfgang] v3.16 (December 18, 2015) * auto: add new option --start which is like auto=start [Tuomo] * libipsecconf: allow time with no unit suffix (openswan compat) [Hugh] * libipsecconf: cleanup parser.y to work on old/new GCC and 32/64bit [Hugh] * libipsecconf: re-introduce strictcrlpolicy= as alias for crl-strict= [Paul] * libipsecconf: Allow time specification for dpdtimeout= / dpddelay= [Paul] * libipsecconf: aliases curl_timeout / curl_iface for openswan migration [Paul] * libswan: Fix memory leak in match_rdn() [Valeriu Goldberger] * PAM: Fix some IKEv1 XAUTH methods always returning "denied" [Antony] * PAM: stacked pam modules (eg pam_ssss) need CAP_DAC_READ_SEARCH [Matt] * newhostkey: fix seeddev device [Paul] * pluto: terminate_connection() when we become unoriented (rhbz#609343) [Paul] * pluto: find_client_connection() must ignore unoriented c (rhbz#1166146) [Paul] * pluto: Fix trafficstatus byte counter output [Antony] * pluto: accept racoon's over-sized padding (got rejected in 3.14) [Andrew] * pluto: obsolete plutofork= and ignore the keyword on startup [Paul] * pluto: send_crl_to_import: use waitpid(2) to wait for correct child [Hugh] * pluto: cleanup struct spd_route and related tidying [Hugh] * pluto: fix eclipsed to iterate over connection's spd_routes [Hugh] * pluto: accept delete payload with wrong side's SPI (CISCO bug) [Paul+Hugh] * pluto: initialise phase2 our_lastused/peer_lastused on creation [Paul+Hugh] * pluto: pluto: OE: add shunts.total count to ipsec whack --globalstatus [Paul] * pluto: Add keyword replay-window= (default 32, 0 means disable) [Paul] * pluto: Add fake-strongswan=yes|no (default no) to send strongswan VID [Paul] * pluto: Add support for XFRM marking cia mark=val/mask [Amir Naftali] * pluto: Use selinux dynamic class/perm discovery, not old API [Lubomir Rintel] * pluto: Fix for uniqueids killing second tunnel between hosts [Tuomo] * pluto: Don't refuse to load passthrough conn with ike= / esp= settings [Paul] * pluto: Free the event struct initialized in main loop and tidy [Antony] * pluto: Add event for child handling of addconn [Wolfgang/Antony] * pluto: release_fragments() cannot try both IKEv1 and IKEv2 fragments [Paul] * X509: load_end_nss_certificate() cleanup [Matt] * X509: Add on-demand loading of NSS certificate private keys [Matt] * X509: Fix possible NSS cert leaks in trusted_ca_nss() [Matt] * IKEv2: delete_state() should only handle shunt of real parent SA [Paul] * IKEv2: retransmit_v2_msg() should delete parent and child SA on failure [Paul] * IKEv2: mixup in parent/child SA caused keyingtries to be lost [Paul] * IKEv2: Remove two bogus state machine entries for INFORMATIONAL [Paul] * IKEv2: Remove duplicate SEND_V2_NOTIFICATION() [Paul] * IKEv2: Only let passthrough conn win if it has longer prefix [Paul] * OE: Deleting opportunistic Parent with no Child SA [Paul] * OE: Send authentication failed for OE child fail [Paul] * OE: Don't reject IPv6 family for OE foodgroups [Antony] * OE: Move orphan_holdpass() call into delete_state() [Paul] * OE: Call orphan_holdpass() for opportunistic conns for EVENT_SA_EXPIRE [Paul] * OE: Do not answer IKE request if we matched authby=never conn [Paul] * OE: Fix memory leaks in nullgw and bs->why [Antony] * OE: At IKE rekey time, delete the IKE/IPsec SA when idle [Antony] * FIPS: fips.h should only require compiled libexec/ components [Paul] * XAUTH: Fix for connection going up->down->up causing passert [Hugh] * XAUTH: Do not interpret padding as incomplete attribute [Lubomir Rintel] * XAUTH: Improve failure logging [Paul] * XFRM: Workaround bug in Linux kernel NLMSG_OK's definition [Hugh] * KLIPS: kernels 4.1.x+ always use the same interface to uids [Roel van Meer] * KLIPS: Various changes to support 4.1.x kernels [Wolfgang] * ipsec: custom directory not recognized, github issue #44 [Tuomo] * updown.*: Fix NetworkManager callback [Lubomir Rintel] * addconn: tidy [Hugh] * building: obsolete USE_ADNS and disable building adns helpers [Paul] * building: Do not link all binaries with nss,nspr and gmp [Paul] * building install "ipsec_initnss.8" and "ipsec_import.8" man pages [Andrew] * packaging: debian/ directory update [Paul/Daniel] * testing: Various testing updates and improvements [Antony/Paul/Andrew] * documentation: added CODE_OF_CONDUCT.d [Paul] * Bugtracker bugs fixed: #216 No longer require :RSA entries for X.509 certs in ipsec.secrets [Matt] #233 pluto sends delete SAs in wrong order and reconnection issues [Wolfgang] #247 KLIPS: fix pluto can't add ipv6 addresses to ipsec devices [Wolfgang] #248 keyingtries=%forever doesn't work anymore [Wolfgang] v3.15 (August 24, 2015) * SECURITY: CVE-2015-3240 IKE daemon restart when receiving a bad DH gx [Hugh] * KLIPS: fix use of *iovec() functions for linux 4.x kernels [Greg Ungerer] * IKEv1: Remove old IPsec SA's when newest IPsec SA is removed [CHEN, JIANFU] * IKEv1: Fix Labeled IPsec SECCTX parsing - bug introduced in 3.14 [Matt] * NETKEY: workaround for NLMSG_OK() macro causing build failure on i686 [Hugh] * NETKEY: Fix IPsec SA priority on type=passthrough conns [Antony] * NETKEY: Fix nflog= on type=passthrough conns [Paul] * pluto: Use PORT_ErrorToString() to translate NSS errors [Matt] * pluto/whack: add --impair-send-zero-gx to test CVE-2015-3240 [Paul] * ipsec: checknss/initnss must both convert old database if it exists [Tuomo] * packaging: debian fixes for userland package [Antony] v3.14 (August 11, 2015) * NSS: Major rewrite of PRF / PRFPLUS / integrity functions for FIPS [Andrew] * FIPS: Added programs/pluto/cavp for NIST CVAS testing [Andrew] * IKEv2: RFC 7383 IKEv2 Fragmentation support [Herbert/Hugh] * IKEv2: RFC 7619 Auth Null support (authby=null) [Paul/Antony/Hugh] * IKEv2: RFC 7619 ID Null support (leftid=%null) [Paul/Antony/Hugh] * IKEv2: whack and smc related time out fixes [Antony] * IKEv2: rekey, expire, delete refactoring and fixes [Antony] * IKEv2: do not pad IKE messages (fix interop w. InsideSecure) [Paul] * IKEv2: Fix esp=camellia to use the IKEv2 IANA registry number for ESP [Paul] * IKEv2: Fix memory leaks in addresspool and child exchange sadb [Antony] * IKEv2: Support for INVALID_KE DH group re-transmits [Paul/Hugh] * IKEv2: if applicable, add CERTREQ payload to IKE_SA_INIT response [Antony] * IKEv2: Various memory leak fixes [Hugh] * IKEv2: Delete parent/child SA when IPsec SA expires due inactivity [Antony] * IKEv2: Added pam-authorize= (default no) for userid verification [Antony] * IKEv2: Informational exchange did not always update msgid counters [Paul] * IKEv2: Don't send v2N_INVALID_MSGID in response to duplicate IKE_INIT packet * IKEv2: Time all crypto operations, not just DH IKEv2 [Antony] * IKEv2: reduce leaks involving sa_v2_convert [Hugh] * IKEv2: eliminate leaks of st_tpacket [Hugh] * IKEv2: fix send certreq [Antony] * IKEv2: find_host_connection now checks RSA, PSK and NULL one by one [Antony] * IKEv1: Don't copy isakmp_sa from received packet [Paul] * IKEv1: Do not retransmit forever [Antony/Herbert] * FIPS: Enforce crypto restrictions in FIPS mode (no md5,twofish, etc) [Paul] * XAUTH: retransmit user/password request in 10s (instead of 30s) [Wolfgang] * X509: Re-added CRL and OCSP support using NSS [Matt] * X509: Expired certificate could crash pluto [Wolfgang] * x509: New options: ocsp_enable= ocsp_strict= ocsp_timeout= [Matt] ocsp_uri= and ocsp_trust_name= * pluto: Converted select() loop to use libevent and subsecond timers [Antony] * pluto: unroute IPSEC SA instead of hold, if oppo and CK_INSTANCE [Antony] * pluto: Added --impair-send-no-ikev2-auth and --impair-force-fips [Paul] * pluto: Added retransmit-timeout= (default 60s) [Antony] * pluto: Added retransmit-interval= in ms (default 500) [Antony] * pluto: Greatly reduce time to retransmit from 20s to 0.5s [Antony] * pluto: Support for IKEv2 AES_CTR (ike=aes_ctr) [Andrew Cagney] * pluto: Support for CBC/CTR test vectors using NSS [Andrew Cagney] * pluto: Remove last weary old FreeS/WAN X.509 code and use NSS instead [Matt] * pluto: Static IP support using passwd file with addresspool= [Wolfgang] * pluto: major tidy of labeled ipsec code [Hugh] * pluto: fixes for uninitialized fields in output struct [Hugh/Paul] * pluto: audit format and log item update as per audit spec [Paul] * pluto: simplify and clarify sa_copy_sa and friends [Hugh] * pluto: small steps improving crypto helpers [Hugh] * pluto: plutostderrlog= renamed to logfile= [Paul] * pluto: plutostderrlogtime= renamed to logtime= [Paul] * pluto: New option logappend=yes|no (default yes) [Paul] * pluto: Removed obsoleted loopback= support [Paul] * pluto: advanced state counting (anon,auth,halfopen,child) [Paul/Andrew/Hugh] (see ipsec whack --globalstatus) * pluto/rsasigkey: added --seedbits option (and seedbits= option) [Paul] * pluto: do not terminate_connection() in-flight [Hugh] * pluto: don't use an expired reserved kernel SPI as fallback [Herbert Xu] * pluto: Use "third best" monotime() on mismatched kernel/glibc headers [Paul] * pluto: removed bool inbound_only from delete_ipsec_sa() [Paul/Herbert] * pluto: fix modecfg client/server status display (was swapped) [Herbert] * pluto: Global NFLOG support via nflog-all= keyword (default off) [Paul] * pluto: Per-conn NFLOG support via nflog= keyword (default off) [Paul] * pluto: Reduce default logging for unknown/halfopen/opportunistic SA's [Paul] * pluto: Fix bogus "no RSA public key known for '%fromcert'" [Herbert Xu] * pluto: exclude ike/esp options from %default for never-negotiate conns [Paul] * pluto: added xfrmlifetime= (default 300) to customise NETKEY acquires [Paul] * pluto: added shuntlifetime= (default 15m) for bare shunts [Paul] * pluto: added negotiationshunt= (default hold) [Paul] * pluto: Obsoleted force-busy= for ddos-mode= [Paul] * pluto: Added config setup keyword ddos-mode= (default auto) [Paul] * pluto: Added config setup keyword ddos-ike-threshold= (default 25000) [Paul] * pluto: Added config setup keyword max-halfopen-ike= (default 50000) [Paul] * pluto: route_owner() don't passert on changed interface [Paul] * pluto: Remove DNSSEC DLV support (DLV is decommissioned) [paul] * pluto: Support for unbound < 1.4.21 [Tony Whyman] * libipsecconf: Improve parser for pipe case (with NM) [Hugh/Lubomir Rintel] * libcrypto/twofish: Fix CALC_SB_* macros [Lubomir Rintel] * readwriteconf: improve error handling [Hugh] * ipsec: ipsec --import does not need to run restorecon [Paul] * ipsec: --checknss option automatically updates NSS DB to SQL [Matt] * ipsec: --checknflog option installs nflog-group= iptables rules [Paul] * rsasigkey: Rename --random to --seeddev [Paul] * packaging: Various SPEC file fixes and Buildrequires: updates [Tuomo/Kim] * packaging: Add v6neighbour-hole.conf for Neighbour Discovery hole [Paul] * initsystems: run ipsec --checknss before start [Tuomo] * building: overhaul of build system Makefiles (see mk/) [Andrew] * testing: docker test type support [Antony] * testing: test case updates/additions [Antony/Paul/Andrew/Matt] * testing: more FIPS support and --impair-force-fips option added [Paul] * NETKEY: Fix bare shunt management code to work properly for NETKEY [Paul/Hugh/Antony] * NETKEY: Increase netlink message buffer for larger SElinux labels [Paul] * NETKEY: kernel netlink decode and log policy expire message [Antony] * KLIPS: move udp_encap_enable() to not be within spinlock [Wolfgang] * KLIPS: ipsec_rcv_decap_ipip broken for IPv6 lsb#227 [Frank Schmirler] * KLIPS: Support for SHA2 via CryptoAPI [Wolfgang] * KLIPS: Support for sha2_truncbug [Wolfgang] * whack: New ipsec whack --purgeocsp [Matt] * whack: New ipsec whack --ddos-busy | --ddos-auto | --ddos-unlimited [Paul] * whack: New ipsec whack --globalstatus [Paul] * whack: New ipsec whack --shuntstatus [Paul] * whack: New ipsec whack --deleteid --name [Antony] * whack: cleanup help text [Tuomo] * _stackmanager: Don't load blacklisted modules (rhbz#1207689) [Paul/Tuomo] * _stackmanager: Support for xfrmlifetime= ipsec.conf option [Paul] * _updown: add proxy arp for cases where routing won't work [Tuomo/Wolfgang] * Bugtracker bugs fixed: #260: libswan: extra safety around same_id() when ID_FROMCERT is used [Paul] v3.13 (June 1, 2015) * SECURITY: CVE-2015-3204 malicious payload causing restart [Javantea/Hugh] v3.12 (November 6, 2014) * IKEv2: CP payload now installs internal address and dns [Antony] * IKEv2: Don't try to decrypt if DH is incomplete [Antony] * IKEv2: If applicable, add a CERTREQ payload in IKE_SA_INIT response [Antony] * IKEv2: Fix parent I2 replace event delay [Antony] * IKEv2: Liveness fix for restarting instantiated connection [Antony] * IKEv2: Schedule expire instead of replace when rekey=no [Antony] * IKEv2: Zero out CP payload before sending [Antony] * IKEv2: Fix message id in create child sa response [Antony] * IKEv2: Don't try to instantiate unoriented connections [Antony] * XAUTH: Fix 2 missing breaks when deciding on sending ModeCFG payloads [Paul] * X509: Ensure that root CA does not end up in the ca_path list [Matt] * pluto: Cleanup DYNDNS code and other clang warnings [Hugh] * pluto: lswconf.c: getNSSPassword: fix bugs and tidy [Hugh] * pluto: check return value of ike_alg_register_enc for twofish/serpent [Paul] * pluto: fix various uninitialised variables in out_struct() calls [Paul/Hugh] * KLIPS: Fix missing breaks in spi command algo type parsing [Paul] * KLIPS: Support for kernel 3.17 [David/Paul] * building: disable libcap-ng and NM support for OSX [Paul] v3.11 (October 22, 2014) * x509: IKEv1 CA cert chain support with sendca option [Matt] * pluto: Fix mtu= option mangling introduced in 3.10 [Kim] * pluto: Fixes auto=start and auto=route with %defaultroute [Kim/Tuomo/Paul] (troubled in 3.9 and 3.10) * pluto: Don't register ESP_BLOWFISH [Paul] * pluto: ESP support for aes_xcbc [Paul] * pluto: ESP support for aes_ctr [Paul] * pluto: ESP support for camellia on NETKEY [Paul] * pluto: IKE support for aes_xcbc (pending NSS update) [Paul] * IKEv1: Default to DH Group 2 and 5 for initiating Aggressive Mode [Paul] (3.9 included DH 14 which was preferred, causing interop issues) * pluto: Force ESP_CAST to only allow 128 bit key sizes [Paul] * pluto: Log_crypto_workers threads did not use static bool first_time [Coverity] * pluto: Warn (not fail) on empty NSS private key passwords [Oskari Saarenmaa] - rhbz#1145231 (rhel7) and rhbz#1144941 (fedora) * pluto: Added PLUTO_IN_BYTES= / PLUTO_OUT_BYTES= for updown [Antony] * pluto: Handle list of certs from parse_pkcs7_cert [Hugh] * pluto: Fix --impair-retransmits IMPAIR code [Hugh] * pluto: separate SEND_V2_NOTIFICATION from SEND_NOTIFICATION [Hugh] * pluto: Various fixes/cleanups in algo registration functions [Paul/Hugh] * pluto: ah=null as a valid phase2alg for a connection [Paul] * pluto: Clean up complete_v*_state_transitions and related things [Hugh] * pluto: More crypto helper cleanup [Hugh] * NETKEY: Don't trust PF_KEY API to tell us about IPCOMP support [Paul] * KLIPS: ip_select_ident was backported to 3.2.63 [Bram] * IKEv2: Don't copy reserved ISAKMP flags in reply msg (rhbz#1052811) [Paul] * IKEv2: ISAKMP_FLAGS_v2_IKE_I was not always set on Original Initiator [Paul] * IKEv2: CP payload support for responder [Antony] * IKEv2: CREATE_CHILD_SA support for responder [Antony] (NON_ADDITIONAL_SAS stub removed) * systemd: Use After=network-online.target instead of network.target [Kim] - rhbz#1145245 (rhel7) and rhbz#1144832 (fedora) * systemd: Add Wants=network-online.target [Lukas Wunner] * addconn: Route before and after listen (bug introduced in 3.10) [Paul/Hugh] * rsasigkey: Use a version of jam_str instead of strcpy() for hostname [Paul] * IKEv2: CERTREQ payload should use SHA1 hash of DN instead of IKEv1 DN [Matt] * updown: Pluto should give CAP_NET_RAW to updown for iptables -t mangle [Paul] * _stackmanager: Fixed to work again with mawk [Marc-Christian Petersen/Tuomo] * testing: Many test case updates [Paul/Antony/Hugh/Matt] * Bugtracker bugs fixed: #206: Libreswan v3.10 on 32-bit does not work [Kim] v3.10 (September 1, 2014) * XAUTH: New option: ipsec whack --trafficstatus [Antony] * XAUTH: New option: ipsec --deleteuser --name xauth-username [Antony] * XAUTH: Do not strip "-" from XAUTH usernames [Paul] * _updown.netkey: New environment variable PLUTO_ADDTIME for IPsec SA's [Paul] * _updown.netkey: Don't skip routing if mtu= option is used [Tuomo] * NETKEY: protoport= installed broken swapped src/dst passthrough SA's [Antony] * NETKEY: fix names for RIPEMD160 and AES_CTR [Paul] * KLIPS: support 3.16+ kernels with update __ip_select_ident() [Thomas Geulig] * _stackmanager: KLIPS support for alias devices [Marc-Christian Petersen] * pluto: Simplify/tidy alg_info [Hugh] * pluto: Simplify find_host_connection() and terminate_connection() [Hugh] * pluto: Fix a leaking socket in whack [Hugh] * pluto: Combine same_dn() and match_dn() to avoid deduplicate logic [Hugh] * pluto: Add strneq(); get rid of most remaining strncmp calls [Hugh] * pluto: Get rid of or document strcat, strncat, strcpy, etc [Hugh] * pluto: malloc/calloc/realloc/free tidying, including a few bug fixes [Hugh] * pluto: Fix memory allocation/free errors (especially in ike_frag) [Hugh/Paul] (triggered as of 3.9 when --leak-detective was used) * pluto: Various warning fixes from LLVM/Coverity [Hugh] * pluto: Don't listen before all connections are loaded [Paul] (this sub-optimal behaviour was introduced in 3.1) * cryptohelpers: cleanup and improved error logging [Hugh] * IKEv2: esp=/phase2alg= should be strict (bug introduced in 3.9) [Paul] * IKEv2: Don't abort all proposals when encountering unknown PRF [Hugh] * IKEv2: ikev2_parse_*_sa_body: stop matching after first success [Hugh] * IKEv2: Reject responder SA with multiple proposals [Hugh] * IKEv2: Enforce proposal numbering rules [Hugh] * IKEv2: first initiating XCHG of Original Responder is not a retransmit [Paul] * IKEv2: Don't respond to reply messages when parent SA was not found [Paul] * IKEv2: clarify O_responder/O_initiator and Request/Reply code [Paul] * IKEv2: Check received msgid is larger then previous before storing [Paul] * IKEv1: parse_ipsec_sa_body() did not allow newer AH transforms [Paul] * IKEv1: Add sha2 and aes_xcbc support for AH/ESP auth algorithm [Paul] * IKEv1: cap IKE lifetimes > 1d to 1d, instead of rejecting SA [Paul] * IKEv1: cisco-unity=yes now also sends VID when acting as VPN server * whack: Don't change exit status for RC_INFORMATIONAL* [Mike Gilbert] * rsasigkey: a logic error limited the randomness of the key size [Paul] * ipsec: create NSS DB on startup when missing [Paul] * ipsec: Added "ipsec --checknss" that creates-when-missing NSS DB [Paul] * verify: Make verify python3 compatible [Slavek Kabrda] * readwriteconf: Fix writing kt_invertbool's (like aggrmode=) [Paul] * testing: Obsoleted dotest.sh with dotest.py, speed increase [Antony] * testing: Added more test cases and general cleanup [Antony/Paul] * compiling: Fix ADNS without USE_DNSSEC compile [Tuomo] v3.9 (July 9, 2014) * Documentation: cleanup of README.* and docs/* [Paul] * libswan: Cleanup allocation and certificate handling functions [Hugh] * libswan: Introduce add_str() to replace abused strncat() [Hugh] * libswan: Complain when loading connection with expired certificate [Paul] * libswan: Some error messages did not make it to the whack log (user) [Paul] * pluto: STF_TOOMUCHCRYPTO handling should not delete the state [Paul/Hugh] * pluto: Default cipher keysizes is now RFC compliant 128 (not 256) [Paul] * pluto: Allow sha2 as an alias for sha2_256 [Paul/Matt] * pluto: Allow more DBG_* and IMPAIR options [Hugh] * pluto: Some enc transforms did not send KEY LENGTH for default key size [Paul] * pluto: Ensure required KEY_LENGTH attributes for some ciphers are sent [Paul] * pluto: Default ESP key size was "max" instead of "default" [Paul/Hugh] * pluto: Bogus keysizes (eg 3des666) was not rejected at IKE level [Paul/Hugh] * pluto: esp=aes now accepts both aes128 and aes256 [Paul/Hugh] * pluto: ipsec status did not display "000" for ESP default size [Paul] * pluto: ipsec status did not print IKE algo separator (",") [Paul] * pluto: ipsec status no longer prints remote nexthop when oriented [Paul] * pluto: sa_copy_sa_first() memory leak fixed [Hugh] * pluto: Improved exponential backoff in message retransmission [Hugh] * pluto: timer.c simplifications and improvements for monotonic time [Hugh] * pluto: Cleanup and document wire_chunk crypto helper code [Hugh] * pluto: rename program files using proper ikev[12]_* prefixes [Paul] * pluto: Don't load certs via load_acerts() from /etc/ipsec.d/acerts/ [Paul] * pluto: Drop CAP_DAC_OVERRIDE privs later to support non-root dirs [Paul] * pluto: Remove unused libaes/libdes/liblswcrypto [Paul] * pluto: Print proper cipher/algo/modp groups in phase1/parent SA [Paul] * pluto: Various IANA updates to ipsec/ike/ikev2 registries [Paul] * pluto: STF_TOOMUCHCRYPTO could cause double delete of state [Hugh] * pluto: Alias "sha" to "sha1" for ike= and esp= [Matt] * pluto: Simplify/cleanup NSS and cryptohelper code [Hugh] * pluto: pluto_crypt.c used non-thread-safe strerror() [Hugh] * pluto: ensure addconn thread uses the same ctlbase as pluto did [Paul] * pluto: LEAK_DETECTIVE is now a runtime --leak-detective pluto option [Paul] * pluto: Add modp2048 to default proposal list [Paul] * pluto: oakley_alg_makedb() algo preference picking fixed [Paul/Hugh] * pluto: Added --impair-send-key-size-check for testing [Paul] * pluto: Make timer.c code IKE version independent [Antony] * addconn: Default gateway finding logic fixes [Wolfgang] * addconn: Only resolve %defaultroute using the main routing table [Wolfgang] * addconn: ensure expired certificates show clearly over whack * NATT: Added nat-ikev1-method=drafts|rfc|both to workaround buggy Ciscos [Paul] * NATT: non port-floating (4500) NATT draft support removed [Paul] * NATT: Change order of NATT payloads to accommodate racoon sensitivity [Paul] * NATT: ignore incoming ISAKMP_NEXT_SAK (AKA ISAKMP_NEXT_NATD_BADDRAFTS) [Paul] * NATT: Added IKEv2 NAT-Traversal support [Antony] * XAUTH: Cleanup code [Hugh] * XAUTH: Workaround for Android bug sending trailing NULL with password [Hugh] * XAUTH: Improved logging and output for automated processing (eg for NM) [Paul] * XAUTH: Hand out previously given IP lease to same client on reconnect [Antony] * DPD: openbsd isakmpd bug workaround for duplicate DPD seqno [Paul] * IKEv1: aggr mode: print names of ignored proposals part [Paul] * IKEv1: rename init_am_st_oakley() to init_aggr_st_oakley() [Paul] * IKEv2: Rekey / Delete event scheduling fixes [Antony] * IKEv2: liveness (DPD) fix msgid handling for Informational XCHG [Matt] * IKEv2: Improved RESPONDER_TIMEOUT logic [Antony] * IKEv2: Extend smc with SMF2_CONTINUE_MATCH for cookie state matching [Hugh] * IKEv2: handle DDOS cookie without creating state and using memory [Hugh] * IKEv2: Fix IS_IPSEC_SA_ESTABLISHED macro to include IKEv2 [Antony] * IKEv2: CREATE_CHILD_SA exchange can return NO_ADDITIONAL_SAS [Antony] * IKEv2: Lingering states were never cleaned up [Antony] * IKEv2: Support Authenticated Header ("AH") [Hugh] * IKEv2: don't call dpd_active_locally() on an undefined state [Paul] * IKEv2: Return proper message to the user when our RSA/PSK is missing [Paul] * IKEv2: Always add SAi TSi TSr in I2 to allow IKE SA Reauthentication [Antony] * IKEv2: When deleting CHILD_SA without a IKE SA don't try to send v2D [Antony] * IKEv2: Fix process_informational_ikev2() for Delete payloads [Paul/Hugh] * IKEv2: Improved logging of IKEv2 transform IDs [Hugh] * pluto/whack: Allow shutdown command for different MAGIC [Paul] * NSS: Changed PR_ASSERT() calls to passert() calls [Paul] * NSS: ipsec initnss can now take a non-default location [Paul] * newhostkey: Return proper error codes, no longer allow stdin [Paul] * OCF: ipsec_ocf_cbimm KLIPS option was always ignored by mistake [Hugh] * OCF: Remove obsoleted HAVE_OCF support for IKE acceleration [Paul] (kernel OCF support is still available and supported) * NETKEY: esp=cast failed due to wrong crypto identifier [Paul] * KLIPS: SAref patches for Ubuntu kernel 3.11.0-15.25 [Simon Deziel] * KLIPS: Improved support for various 3.x Linux kernels [various] * KLIPS: support for CONFIG_USER_NS [Matt] * _stackmanager: only unload stack when switching (rhbz#1025687) [Paul/Tuomo] * building: remove LIBDIR as we install all programs in LIBEXECDIR [Tuomo] * packaging: NSS fixups for deb packaging [mountaincat] * testing: a LOT of test case updates [many people] * Bugfixes for better C-library compatibility with "musl" [Hugh/Paul] * Bugtracker bugs fixed: #67: uniqueids: don't compare ipv4 and ipv6 addresses [Tuomo] #86: left=%defaultroute does not work in a conn [Hugh/Paul] v3.8 (January 15, 2014) * SECURITY: CVE-2013-6467 missing IKEv2 payloads causes restart [Iustina/Hugh] * building: Remove #ifdef DEBUG - always compile into userland [Paul] * IKEv2: Updated AUTH names to latest IANA registry entries [Paul] * pluto/whack: Added --impair-send-ikev2-ke test option [Paul] * pluto: allow shutdown command even with bad WHACK_BASIC_MAGIC [Paul] * addconn: ignore obsoleted --defaultroute and --defaultroutenexthop [Paul] * Various code cleanup [Hugh] * initscripts: sysv should try harder to kill pluto without ctl file [Tuomo] * gentoo: fixes to build and init system on Gentoo [Mike Gilbert] * KLIPS: fix NAT-T status in eroute output [Paul] * pluto: updated ietf_constants.h with IANA entries [Paul] * IKE: Make sure sha2 is an alias for sha2_256 for ike= and esp= [Hugh/Paul] * Bugtracker bugs fixed: #171: showhostkey.c:322: bad switch statement v3.7 (December 10, 2013) * SECURITY: CVE-2013-4564 Denial of service via unauth packet [Paul/Hugh] * SECURITY: fix insecure tmp file in rpm %post - introduced in 3.6 [Tuomo] * SECURITY: Properly handle IKEv2 I1 notification without KE payload [Paul] * IKE: aes_gcm and aes_ccm now specify key size without salt [Paul/Hugh] * NETKEY: Added twofish and serpent as valid ESP algorithms [Paul] * KLIPS: Fix for crashes in ipsec_xmit_ipip() [Thomas/Roel/David] * KLIPS: Fix NAT-T (NEED_UDP_ENCAP_ENABLE) for 3.4 kernel [Roel] * KLIPS: Fix compiling for 3.9 kernels (PDE_DATA fix) [Paul] * KLIPS: Claim we do namespaces - makes it work on simple host case [Paul] * IKEv2: Add support for AES-GCM, AES-CCM [Paul/Hugh] * IKEv2: Check for inbound traffic before sending liveness exchange [Matt] * IKEv2: Fix some error codes that mistakenly used IKEv1 versions [Paul] * IKEv2: in R1 don't copy their IKEv2 minor for our reply packet [Paul] * IKEv2: Don't kill unrelated states on same hash chain in IKE DEL [Hugh] * pluto: change ipsec_notification_names to ikev[12]_notify_names [Paul] * pluto: Various cleanup and reducing scope of variables [Hugh] * building: support for slackware version/init system detection [Roel] * rsasigkey: Remove spurious debug line confusing ipsec showhostkey [Paul] (rhbz#1039655) * initsystems: fix typo in openrc script [Natanael Copa] * testing: KVM test system updates [Paul] * secrets: Log glob failing for secrets parser as warning, not error [Paul] * setup: fix systemd init detection [Tuomo] * labeled ipsec: Set default value of secctx_attr_value to 32001 [Paul] (rhbz#923250) * barf: don't load l2tp kernel modules and use new syntax (rhbz#1033191) [Paul] * Bugtracker bugs fixed: #116: Don't load connections when leftcert= cert not found in NSS DB [Matt] v3.6 (October 30, 2013) * IKEv2: Fix interoperability bug in SKEYSEED generation [Paul/Hugh/Antony] * IKEv2: Add liveness checks (a.k.a DPD for IKEv2) [Matt Rogers] * IKEv2: ikev2=insist allowed ikev1 when acting as responder [Matt Rogers] * IKEv2: Fix fallback to ikev1 when remote has ikev2=no [Paul] * IKEv1: Cleanup AGGR Mode VendorID - also send fragmentation vid [Paul] * IKEv1: Added cisco_unity= (default no) option which sends VID [Paul] * IKEv1: Fix compatibility with NAT-T and remote_peer_type=cisco [Paul] * IKEv1: dpdaction=restart_by_peer is now called dpdaction=restart [Paul] * IKEv1: Added support for modecfgbanner= and modecfgdomain= [Paul] * IKE: introduce ikepad=yes|no (default yes) for Checkpoint interop [David] * pluto: work around for Cisco VPN clients sending extraneous bytes [Paul/Hugh] * pluto: Support for google-authenticator OTP via pam [Paul] * pluto: fix kernel.c typo in word outgoing [Tuomo] * pluto: remove dsa/elgamal stubs from gnupg that were unused [Paul] * pluto: Added per conn priority= to specify kernel IPsec SA priority [Paul] * keyword: auto=route and ipsec auto --route renamed to "ondemand" [Paul] * NETKEY/BSD: Added per conn reqid= to specify kernel IPsec SA [Paul] (based on idea by Panagiotis Tamtamis) * pluto: %fromcert now works for local certs and those received via IKE [Matt] * pluto: Allow \\ masking in RDNs similar to ,, [Matt Rogers] * pluto: merge updateresolvconf/restoreresolv.conf in client-up|down [Paul] * building: Removed USE_MODP_RFC5114 flag. Support is always added [Paul] * building: Removed USE_AGGRESSIVE flag. Support is always added [Paul] * building: Removed USE_XAUTH flag, Support is always added [Paul] * building: Removed MODECFG* flags, Support is always added [Paul] * building: Remove blowfish (use twofish instead) [Paul] * building: Generate Makefile depend files automatically [Tuomo] * building: Add support for openrc initsystem on Alpine Linux [Paul] * packaging: spec files now initialise NSS DB when not found [Paul] * NETKEY: Take protoport= into account when setting IPsec SA priority [Paul] * NETKEY: Change Update SA to Add SA when existing SA is not found [Mattias] * NETKEY: Fix Labeled IPsec (broken in openswan 2.6.33) [Paul] * KLIPS: Support for 3.10+ kernels (/proc use via seq_* functions) [David] * Changed HAVE_STATSD compile option to statsbin= runtime option [Paul] * sysvinit: status function used incorrect variable for pid file [Tuomo] * _stackmanager: coding style cleanup - fixes bashism [Tuomo] * testing: Various interop test case updates [Paul] * FIPS: Support versioned hmac files, fips test in non-fips mode [Paul] * rsasigkey/newhostkey: Keysize for new RSA keys keysize increased from 2192 to randomised 3072-4096 (in blocks of 16) to fight keysize monoculture [Paul] * Removed unused and unmaintained USE_TAPROOM functionality [Paul] * NAT-T: Added 100.64.0.0/10 from RFC 6598 to virtual_private [Paul] * NSS: pluto should not open NSS files in readwrite, just read [Paul] * Bugtracker bugs fixed: #130: debian debuild creates a deb with /usr/libexec contents [Marc-Christian Petersen] #145: support old location of /selinux/enforce still in use by CentOS6 [Paul] v3.5 (July 13, 2013) * NETKEY: _stackmanager: Clear disable_xfm/disable_policy /proc files for labeled IPsec [Paul] * KLIPS: Added support for kernel 3.9.x [Paul/David] * KLIPS: NATT support for kernel 3.5+ needs udp_encap_enable() [David] * KLIPS: pointer can look valid during free process [Unknown/David] * KLIPS: change default for hidetos (quality of service) to yes [Paul] * KLIPS: preliminary SHA2 family support via OCF/CryptoAPI [David] * MAST: _stackmanager: bring mast0 up even if module was loaded [neoXite] * MAST: Add support for IPv6 iptables mangle table in updown.mast [Paul] * _stackmanager: Move iptables mangle rules to MAST only section [Paul] * _stackmanager: re-add support for hidetos=, overridemtu= and fragicmp= [Paul] * _stackmanager: Clear disable_xfm/disable_policy for labeled IPsec [Paul] * pluto: Fix reading ipsec.secrets without trailing newline [Hugh] * pluto: 'ipsec status' output changes, added 'config setup' items [Paul] * pluto: Added config setup, compile paths, runtime info to ipsec status [Paul] * pluto: removed IKE_ALG and KERNEL_ALG defines [Paul] * pluto: Simplify Pluto_IsFIPS(), remove redundant log message [Paul] * pluto: Added Pluto_IsSElinux() to log SElinux runtime status [Paul] * pluto: Removed unused alg_info parameters permitman and permitike [Paul] * pluto: Fix STATE_XAUTH_R0/STATE_XAUTH_R1 state names [Paul] * pluto: out_modify_previous_np() should allow ISAKMP_NEXT_SIG for RSA [Paul] * building: cleanup old vars, and allow more env overrides [Paul] * packaging: Fix systemd script Alias target (rhbz#982166) [Paul] * newhostkey: help the user when nssdb is not initialized yet [Paul] * newhostkey: simplify default nss dir handling [Paul] * lswan_detect: cleanup coding style and fix help for unknown options [Tuomo] * lswan_detect: add gentoo detection [Tuomo] * setup: add rhsysv, openrc, and real sysv init support [Tuomo] * barf: do not cause any iptables modules to get loaded (rhbz#954249) [Paul] * look: Don't cause loading of iptables kernel modules (rhbz#954249) [Paul] * FIPS: Remove hardcoded /usr/libexec/ipsec path, use IPSEC_EXECDIR [Paul] * FIPS: Add warning in ipsec verify for prelink command [Paul] * testing: Add option for "post" scripts during a test run [Matt Rogers] * testing: dist_cert support for commands in different path locations [Matt] * testing: Generate CRL with leading zero byte for testing [Paul] * Bugtracker bugs fixed: #82: Phase out DBG_KLIPS/DBG_NETKEY for DBG_KERNEL [Paul] #96: lswan_detect: Alpine linux compatibility [Tuomo] #99: NETKEY: Segfault on acquire_netlink with labeled_ipsec [Kim/Tuomo] #101: restore port when ipsec policy is generated for nat-t [Kim/Tuomo] #124: pluto: Add usage comment for addresspool.* [Paul] #126: pluto: nhelpers= does not default to -1 [Paul] #128: pluto: prevent libcurl sigalarm from crashing pluto (lsbz#128) [Paul] v3.4 (June 6, 2013) * Change coding style to Linux kernel [Team] * IN MEMORIAM: June 3rd, 2013 Hugh Daniel v3.3 (May 13, 2013) * SECURITY: atodn() buffer overflow with oe=yes [Florian/Hugh/Paul] affected: libreswan 3.0 and 3.1 (CVE-2013-2052) see also: openswan up to 2.6.38 (CVE-2013-2053) see also: strongswan up to 4.3.4 (CVE-2013-2054) * security: dn_parse(), hex_str() write beyond end of the buffer [Florian] * security: get_rnd_bytes: Abort on random number generator failure [Florian] * security: Integer overflow if the leak detective enabled [Florian] * security: Check that origin of netlink message is the kernel [Florian] * security: Abort on crypto failure for 3des/aes to prevent leaks [Florian] * security: Check PK11_CreateContextBySymKey() for NULL and SECFailure [Paul] * security: RSA: Check modulus length against key overall length [Florian] * security: fetch_curl: Set timeout for the entire request [Florian] * security: Multiple hardening fixes from security audit [Florian Weimer] * security: Cleanup buffer usage for traffic logging with XAUTH [Hugh] * security: Cleanup ASN1_BUF_LEN use and remove unused load_host_cert() [Paul] * security: cleanup CFLAGS handling [Paul] * security: IKEv2 crashed when using nhelpers=0 [Paul] * security: Remove stale non-NSS ASN1 handling and pem decryption code [Paul] * security: Initial loading of file CRL fails for NSS CAs [Matt Rogers] (rhbz#960171) * security: Removal of USE_WEAKSTUFF and USE_NOCRYPTO (1DES, modp768) [Paul] * security: Removal of 1DES for KLIPS using CryptoAPI [Paul] * security: * security: Cleanup of ASN1_BUF_LEN/BUF_LEN/PATH_MAX defines [Paul] * pluto: Add support for OID_SHA224_WITH_RSA signatures [Paul] * pluto: Always list section headers --list* calls, even when empty [Paul] * X509: Fix for CRL sig failure if first byte is zero [Dhr/Matt/Paul] (rhbz#958969) * _stackmanager: fix loading of aes-x86_64 module [Tuomo] * Bugtracker bugs fixed: #64: removal of /dev/*random everywhere put feeding nss pools [Paul] #90: NETKEY: Transport mode inbound eroute was from client [Kim/Tuomo] #91: SAREF: Patches updated for 3.4.x (tested on 3.4.42) [Andreas Herz] v3.2 (April 13, 2013) * addresspool: Identify reconnecting client and re-use lease [Antony] * IKEv1: Support for sending initial_contact in Main Mode [Paul] * addconn: improve defaultroute finder [Kim] * compiling: fix use of variables in buildsystem consistent [Tuomo] * ipsec: fix syntax error in --help introduced in 3.1 [Tuomo] * verify: fix wrong confdir location [Tuomo] * pluto: cleanup of XAUTHuser and traffic statistics logging [Paul] * pluto: Obsoleted force_keepalive= and --force_keepalive [Paul] * pluto: Added per-conn nat_keepalive=yes|no (default yes) [Paul] * pluto: Log our own vendorid as "received" instead of "ignored" [Paul] * pluto: Prevent logging from truncating XAUTHuser= [Paul] * pluto: Don't log (0 byte) SA traffic statistics for ISAKMP SA's [Paul] * pluto: Some more changes in the output of ipsec auto --status [Paul] * pluto: wipe old logfile on restart (match previous behaviour) [Antony] * _stackmanager: When unloading NETKEY, unload ip_vti before xfrm*tunnel [Paul] * _stackmanager: Stack was not cleaned up for upstart / non-modular [Paul] * building: Fix warnings when compiling with clang [Florian Weimer] * building: Add -pie to linker flags, ensure relro is not overwritten [Paul] * building: fix "make depend" in programs/pluto [Antony] * packaging: Split RHEL spec file into rhel5/rhel6, add USE_OCF flag [Paul] * initsystem: fixed default sysv init status function [Tuomo] * KLIPS: SAref patches for 3.0.55+ and RHEL 2.6.32-358.2.1 [Pavel Kopchyk] * Bugtracker bugs fixed: #75: Libreswan inserts wrong xfrm policies on some configurations [Tuomo] #76: NSS:: ipsec initnss fails with a @FINALCONFDDIR@ replace and no default configdir [Tuomo] #78: NSS: segfault on libnss functions when using ikev2 [Antony] #85: NETKEY: Pass traffic selectors to the kernel in Transport Mode support was incomplete and broke nat-t transport mode [Kim/Tuomo] v3.1 (March 14, 2013) * XAUTH: Support for leftaddresspool= [Antony] * XAUTH: Added xauthby=alwaysok option [Paul] * XAUTH: Added xauthfail=hard|soft option [Paul] * IKEv1: Support for IKE fragmentation via ike_frag= [Wolfgang/Paul/Hugh] * IKEv1: Support for removing bogus non-ESP markers [Paul/Hugh] * NETKEY: Show traffic stats in ipsec auto --status and teardown [Wes/Paul] * ipsec: Add "ipsec start|stop|restart|status" aliases [Paul] * testing: Many updates to KVM testing infrastructure [Paul/Antony] * starter: auto=route and auto=start only performed auto=add [Wolfgang] * libswan: logging cleanups from openswan 2.5.x era [DHR/Antony/Paul] * pluto: log XAUTHusername in the "established IPsec SA" line [Paul] * pluto: Show labeled IPsec information in ipsec auto --status [Paul] * pluto: Various minor changes to ipsec auto --status output [Paul] * pluto: Debug logs were not written if a file was specified [Paul/Antony] * pluto: fix for additional proposal sizes when enabling 1DES [Paul] * IKEv2: narrowing used a wrong port range in determining bestfit [Coverity] * IKEv1: Better logging of Vendor IDs in [Paul] * KLIPS: enable crytoAPI in packaging/makefiles/module.defs [Paul] * SAREF: patches for Ubuntu kernel 3.2.0-33.52 [Simon] * libipsecconf: Improved fix for osw#1370 (segfault on no EOL) [Philippe] * libipsecconf: Forbid rekey=no plus dpdaction=restart(_by_peer) [Paul] * libipsecconf: crlcheckinterval unit is time, not number [Tuomo] * libipsecconf: Remove bogus key_from_DNS_on_demand policy for PSK [Paul] * libipsecconf: Raise POLICY bits from int (32) to lset_t(64) [Paul] * libipsecconf: sourceip= setting could overwrite nexthop= setting [Paul] * XAUTH: ModeConfig DNS options only worked via whack, not config file [Paul] * XAUTH: modecfg_wins[12]= support removed [Paul] * XAUTH: Use re_entrant versions of localtime_r/gmtime_r [Paul] * XAUTH: Added threading mutex locks for log functions [Philippe/Paul] * XAUTH: Added threading mutex locks for crypt() [Philippe] (crypt_r is not available on all platforms) * XAUTH: Only try to update resolveconf/restoreconf when XAUTH client [Paul] * addconn: If no protostack= is configured, return "netkey" as default [Paul] * addconn: Fix for addconn loading Point-To-Point connections [Kim] * X509: Initialise libcurl for SSL to support CRLs over HTTPS [Paul] * X509: Warn 14 days before certificates expire [Tuomo] * packaging: add /etc/ipsec.d/{crls,cacerts} to rpm spec files [Tuomo] * packaging: Fixes to spec file, added kmod spec file for KLIPS [Paul] * compiling: added -pthread to CFLAGS [Tuomo] * _plutorun: pass all command line options to pluto [Tuomo] * _updown: Various fixes for klips/netkey version [Tuomo/Antony] * X509: Reintroduced lock_certs_and_keys()/unlock_certs_and_keys() [Paul] * initsystem: change sysv initscripts to use new _plutorun interface [Tuomo] * DPD: Don't try to delete non-events [Paul] * Bugtracker bugs fixed: #8 honour compress=no option [Matt Rogers] #50 It is assumed ipsec.conf lives in the same dir as rc.d/init.d [Tuomo] #53 ipsec auto --status does not show phase2 parameters when using (unspecified) defaults? [Matt Rogers] #71 Libreswan pre-3.1 git version breaks on-demand ipv6 tunneling [Tuomo] v3.0 (January 02, 2013) * FORK: Rename from Openswan to Libreswan [Team] (for older CHANGES see docs/CHANGES.openswan) * FORK: Changed our VendorID prefix to "OEN" [Team] * LICENSE: Updated FSF address on the GPLv2 COPYING file [Team] * TRADEMARK: Give everyone unlimitel eternal royalty-free license to use the name "libreswan" to refer to this software and website [Team] * NSS: is now mandatory - custom crypto code removed [Paul] * NSS: Support reading NSS password from file [Avesh] * NSS: Added "ipsec initnss" and "ipsec import" commands [Paul] * NSS: We need to include nsperror.h for PR_GetError() [Paul] * NSS: PK11_DigestFinal() passed sizeof pointer instead of passing sizeof *pointer [Paul] * NSS: use pkg-config to find the right cflags and libs [Paul] * DNS: Removed LWRES code and old static ISC libraries [Paul] * DNS: Don't attempt to resolve numerical sourceip= values [Paul] * DNS: starter and pluto now support USE_DNSSEC using libunbound [Paul] * OE: Removed support for old KEY and TXT DNS records [Paul] * OE: Add support for IPSECKEY in ipsec showhostkey [Paul] * pluto: --config uses libipsecconf to read 'config setup' [Kim B. Heino] * pluto: left=%defaultroute now obtains src ip from routing table [Kim B. Heino] * pluto: Removed support for non-strict ike/esp lines [Paul] * pluto: UDPFROMTO support was not enabled for NETKEY if not also build with KLIPS [Paul] * pluto: Pass traffic selectors to the kernel in Transport Mode [Avesh] (rhbz#831669) * pluto: Fix phase confusion in xauth/modeconfig [Avesh] * pluto: Added new option plutostderrlogtime= (default=no) [Paul] * pluto: Additional safety checks to strncat() calls for addrtot(), inet_addrtot(), sin_addrtot(), alg_info_snprint_esp(), alg_info_snprint_ah(), idtoa() and format_end() [Paul] * pluto: Removed unused OCSP code [Paul] * pluto: Add Linux audit support via USE_LINUX_AUDIT (incomplete) [Paul/Antony] * pluto: crlcheckinterval did not interpret plain numbers as seconds [Philippe] * pluto: Change ft_mbz to ft_zig - Don't error on "must be zero" but instead "zero ignore". This works around an Android ICS/racoon bug [Paul] * pluto: Update known vendorids [Paul] * pluto: phased out HAVE_THREADS, pluto/pam now thread-safe [Philippe/Paul] * pluto: Fixed IPSEC_CONFDDIR handling which broke NSS in tests [Paul] * pluto: obsoleted prepluto= postpluto= plutoopts= config setup options [Paul] * pluto: obsoleted plutowait= and pluto= config setup option [Paul] * pluto: obsoleted nocrsend= option removed (use leftsendcert=) [Paul] * pluto: removed manual keying remnants [Paul] * pluto: remove protostack=auto and --use-auto, netkey is new default [Paul] * pluto: Added perpeerlog=yes|no and perpeerlogdir=/var/log [Paul] * pluto: Added retransmits=yes|no (matches pluto --noretransmits) [Paul] * pluto: Added plutofork=yes|no to match pluto --nofork [Paul] * pluto: added ikeport= and nat_ikeport= options, and --natikeport [Paul] * pluto: support for secretsfile= and ipsecdir= in ipsec.conf [Paul] * pluto: remove old unused USE_IPSECPOLICY code [Paul] * pluto: rhbz#609343: pluto crashes when removing logical interface [Avesh] * pluto: don't stop processing after --coredir argument [Paul] * pluto: perform whack --listen and addconn --autoall on startup [Paul] * pluto: honour plutostderrlog= natively now _plutorun is gone This also adds a new option --logfile to the pluto daemon [Paul] * pluto: if started with --nofork, don't care about existing pid file [Paul] * pluto: incorrect free in scan_proc_shunts() [Roel van Meer] * pluto: eclipsed() was broken since freeswan-2.02 [Philippe] * _plutoload: obsoleted [Kim/Paul] * auto: no longer pass defaultroute/defaultrouteaddr to addconn [Paul] * whack: fix handling --sha2_truncbug and --nm_configured options [Paul] * whack: don't try to write to closed stdout tty [Philippe] * DPD: reduce flood of DPD messages with unexpected seqno [Andrey Alexandrenko] * DPD: We did not send DPD VID in aggressive mode with NAT-T disabled * DPD: dpdaction=restart can cause full phase1 timeout after DPD (rhbz#848132) [Avesh] * PAM: updated contrib/pam.d/pluto (rhbz#815127) [Philippe Vouters] * PAM: move pam out of contrib, and install config when HAVE_XAUTHPAM [Paul] * IKEv1: In aggressive mode: allow ISAKMP_NEXT_CR ISAKMP_NEXT_CERT as payloads [Philippe] * IKEv1: aggressive mode sometimes picked wrong RSA/PSK conn [Philippe] * IKEv1: Simplify outgoing NAT-T proposals, fix logging [Paul] * XAUTH: Support for runtime choice of xauthby= [Philippe] * XAUTH: Support for Mutual RSA + XAuth (interop with Shrew Soft) [Philippe] * XAUTH: Fixed updown to remove ModeCfg (cisco) obtained sourceip [Avesh/Tuomo] * XAUTH: Do not redo xauth/modecfg during rekey to cisco [Avesh] * XAUTH: Use incoming XAUTH VID when picking best connection [Philippe] * XAUTH: pam was failing when built with USE_LIBCAP_NG=true [Philippe Vouters] * XAUTH: Fixup of defines [Paul/Philippe] * XAUTH: Don't use XAUTH VID to put conn in policy XAUTH [Andrey Alexandrenko] * XAUTH: Fix XAUTH TYPE handling and logging [Philippe] * IKEv2: Comply to RFC's for "must be zero" to ignore instead of abort [Paul] (rhbz#831669) * IKEv2: road warrior support [Antony/Paul/Avesh] * IKEv2: narrowing code extended to cover ports,protocol,subnets [Antony/Paul] * Only set MODP768_MODULUS with USE_VERYWEAK_DH1 [Paul] * NETKEY: ignore interfaces= line for NETKEY [Paul] * NETKEY: Fix for three AES-GCM issues with key lengths 128, 192, 256 bits and IV of 8, 12, 16 bytes as per RFC 4106 [Avesh] * NETKEY: Labeled IPsec updates [Avesh] * NETKEY: Support for SHA384/SHA512 and integ(ikev2) in ESP [Avesh] * NETKEY: In _updown.netkey, insert route on correct interface when nexthop is used [Tuomo] * NETKEY: Revert "Always use XFRM_MSG_UPDPOLICY instead of XFRM_MSG_NEWPOLICY" This caused module unload issues and XFRM_MSG_REPLACE errors [Paul] * KLIPS: Removed support for Linux < 2.4.4 [Paul] * KLIPS: Changed _startklips to use ip route instead of netstat [Harald] * KLIPS: misc. fixes, mostly satot() related [David] * KLIPS: 20% speed gain on transmitting packets [David] * MAST: Fixed _updown.mast missing incomplete if-clause [Harald] * SAREF: kernel patches updated to linux 3.2.0 [Simon Deziel] * addconn: mimic _plutoload, cleanup and fixup of functions [Paul] * scripts: Support /etc/sysconfig/ipsec and /etc/default/ipsec (rhbz#789917) * _stackmanager: new script replacing _startnetkey/_startklips [Paul] * barf: do not grep lastlog, wtmp, tmp (rhbz#771612) [Paul] * verify: ported ipsec verify from perl to python [Paul] * verify: check ipsec.conf, ipsec.secrets syntax [Paul] * verify: warn on newly obsoleted keywords [Paul] * auto: fix --status output for vnet/vhost case [Ani] * copyright: Removed obsoleted/unmaintained "ipsec copyright" command [Paul] * showdefaults: removed ipsec showdefaults [Paul] * _include: Removed obsolete _include program [Paul] * policy: Removed broken 'ipsec policy' [Paul] * mailkey: Removed obsolete command. Was already not build or installed [Paul] * scripts: phased out /var/run/pluto/ipsec.info [Paul] * OSX: Set __APPLE_USE_RFC_3542 required for udpfromto functionality [Paul] * DOCS: Add man page leftid= note on Cisco ID_KEY_ID Group Name [Philippe] * liblibreswan: Remove unused optionsfrom() temp file handling [Paul] * liblibreswan: Support comma's inside OID's by using ",," to mean "," inside the OID (rhbz#868986) [Matt Rogers] * initsystems: Native support for systemd, upstart and sysvinit [Paul/Wes] * testing: Ported broken UML harness to KVM/libvirt/9p [Paul/Antony] (see the wiki on libreswan.org for details on how to use it) * packaging: Updated libreswan.spec to reflect updated options [Paul] * packaging: /usr/lib{64}/ipsec is no longer used [Paul] * manpages: Build during build phase, not during install phase [Wes] * compiling: Update standard compile options to be more hardened [Paul] * Bugtracker bugs fixed: #7 after 'make install' - check if the service is enabled or not and notify the user [Wes] #9 install /etc/pam.d/pluto if USE_XAUTH=true [Wes] #25 addconn behaves differently from whack regarding case [Paul] #33 warn on /usr/local install with selinux enabled [Wes] #40 ensure make install checks and restorecon's SElinux policies [Wes] osw#993 ipsec showhostkey: wrong kind of key PPK_XAUTH [Philippe Vouters] osw#1308 forceencaps= setting does now show up in "ipsec auto --status" [Matt Rogers] osw#1329 IKEv2 core dumps on 2.6.32 with changes backported from the 2.6.38 tree [Steve Lanser] osw#1334 Block rules created by openswan remain even after tunnel establishment or XFRM_MSG_POLEXPIRE [Panagiotis Tamtamis] osw#1349 pluto logging no subjectAltName matches ID '%fromcert', replaced by subject DN [Tuomo] osw#1359 Openswan L2TP and IPhone vpn connection [Paul] osw#1370 Segfault on no new line at the end of ipsec.conf [Wes] osw#1375 ipsec verify uses perl, should use python [Paul] osw#1381 XAuth: the variable PLUTO_XAUTH_USERNAME is empty in the updown script [Bram] osw#1384 confusing output from ipsec auto --status [Bram] For older changes, see docs/CHANGES.openswan libreswan-3.32/CODE_OF_CONDUCT.md000066400000000000000000000044541365625662500162550ustar00rootroot00000000000000# Contributor Code of Conduct As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality. Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery * Personal attacks * Trolling or insulting/derogatory comments * Public or private harassment * Publishing other's private information, such as physical or electronic addresses, without explicit permission * Other unethical or unprofessional conduct Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team. This code of conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting a project maintainer at abuse@libreswan.org. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. Maintainers are obligated to maintain confidentiality with regard to the reporter of an incident. This Code of Conduct is adapted from the [Contributor Covenant](https://contributor-covenant.org), version 1.3.0, available at [https://contributor-covenant.org/version/1/3/0/](https://contributor-covenant.org/version/1/3/0/) libreswan-3.32/COPYING000066400000000000000000000432541365625662500145120ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. libreswan-3.32/CREDITS000066400000000000000000000017701365625662500144740ustar00rootroot00000000000000The following people have contributed major resources or significant patches to The Libreswan Project. Avesh Agarwal Antony Antony Richard Guy Briggs Andrew Cagney Daniel Kahn Gillmor Wes Hardaker Kim B. Heino David McCullough Amir Naftali Wolfgang Nothdurft Hugh Redelmeier Lubomir Rintel Matt Rogers Tuomo Soini Philippe Vouters Paul Wouters Herbert Xu Libreswan is a fork of the Openswan 2.6.38 codebase. Please see the docs/CREDITS.openswan file from Openswan for details on original work. Openswan is a fork of the FreeS/WAN 2.04 codebase. Please see the doc/CREDITS.freeswan file from FreeS/WAN for details on original work. libreswan-3.32/CROSSCOMPILE.sh000077500000000000000000000026031365625662500157110ustar00rootroot00000000000000#!/bin/sh # # cross compile example # #export PREFIX=/volquad/arm-4.0.2 export PREFIX=/usr/local/arm_tools export DESTDIR=/tmp/libreswan.arm export ARCH=arm export CC=$PREFIX/bin/arm-elf-gcc export GCC=$PREFIX/bin/arm-elf-gcc export LD=$PREFIX/bin/arm-elf-ld export RANLIB=$PREFIX/bin/arm-elf-ranlib export AR=$PREFIX/bin/arm-elf-ar export AS=$PREFIX/bin/arm-elf-as export STRIP=$PREFIX/bin/arm-elf-strip export LD_LIBRARY_PATH=$PREFIX/lib/gcc-lib/arm-elf/3.0/ export PATH=$PATH:$PREFIX/bin export USERCOMPILE="-Wl,-elf2flt -DCOMPILER_HAS_NO_PRINTF_LIKE -O3 -g ${PORTDEFINE} -I$PREFIX/arm-elf/inc -L$PREFIX/lib/gcc-lib -DGCC_LINT -Dlinux -D__linux__" export WERROR=' ' #now you can run: # make programs #and binaries will appear in OBJ.linux.$ARCH/ #and run: # make install #and the install will go into $DESTDIR/ # note: the arm_tools I had failed to compile PRINTF_LIKE(x), so the code # for that was ifdef'ed with #ifndef COMPILER_HAS_NO_PRINTF_LIKE statements. # Add -DCOMPILER_HAS_NO_PRINTF_LIKE to enable the workaround. # EXECUTABLE FILE FORMAT # # Some uClibc/busybox combinations use different executable files formats from # ELF. This is configured during Linux kernel build. One common format is # the BLFT file format. Do not manually convert ELF binaries to BLTF using # elf2flt as that will create invalid binaries. Instead add -Wl,-elf2flt to # your flags (CFLAGS / LDFLAGS / USERCOMPILE) libreswan-3.32/INSTALL000066400000000000000000000030741365625662500145040ustar00rootroot00000000000000 Please read the documentation in docs or at https://libreswan.org/ Specific vendors/distribution build instructions available in packaging/ Build requirements ------------------ bison flex pkgconfig gcc make xmlto nss-devel nspr-devel libevent-devel for systemd: pkgconfig hostname systemd-devel for pam/xauth: pam-devel for dnssec support: unbound-devel ldns-devel for FIPS support: fipscheck-devel for libcap-ng support: libcap-ng-devel for CRL fetching support: libcurl-devel for CRL ldap fetching support: openldap-devel for audit support: audit-libs-devel Building userland ----------------- make all sudo make install For a minimal install (no manpages) type: make base sudo make install-base The file Makefile.inc.local can be used to enable/disable features configured by mk/config.mk and mk/userland-cflags.mk Optional building alternative KLIPS IPsec stack ----------------------------------------------- On Linux 2.6 or higher for the running kernel: make module sudo make module_install Build for a kernel different from the running kernel: make KERNELSRC=//usr/src/kernel/linux-9.42 module Building KLIPS kernel module for the old Linux 2.4 kernel make module24 sudo make minstall24 When using KLIPS with OCF: make CONFIG_KLIPS_OCF=y MODULE_DEF_INCLUDE=$${LIBRESWANSRCDIR}/packaging/ocf/config-all.hmodules module module_install When called in openwrt/packaging/libreswan/Makefile to build kmod-libreswan make MODULE_DEFCONFIG=$${LIBRESWANSRCDIR}/packaging/openwrt/defconfig MODULE_DEF_INCLUDE=$${LIBRESWANSRCDIR}/packaging/openwrt/config-all.h module libreswan-3.32/LIBRESWAN-GPG-KEY.txt000066400000000000000000000066671365625662500166160ustar00rootroot00000000000000-----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v1.4.13 (GNU/Linux) mQINBFDjilcBEAChkfasfBKTzGys9DwgBsmDVsPConW60uyKnu16+wO1kIKMFWi6 wGllwKUJmCBY2FSQHbOBy5eHPPT1ijJhYt4j7WU+YJVh5Ca5RE3trFt31FX0vzp+ KMqdQ8HOofA7jO6bgyHUwOJ539YkqYj1jHKfrdRqOnzB9fFyEb7485sq1F8j/rHk cSar1Hd9QfGAZHxXqgncgHFobB/xXEGRJIi+4kNL5SYasbw9tfYUGPrUXVol1+pn tsG92736O5Qe5K+wH2nAS4hwPJ1Xr4XIKeNNwxQW25wWqn4mLa4Vly+PA2uSE7ZP RcxE3yBCaLFMlw4rLhFAzd6TeslQONZ+9K51yfBYm7m0vWM3Ixq8yuD8E49OkKr8 QRMaA2g89NW3AuNLExiTE0zQzAs/g6eX8WZdeWCvKxhRTAUYkw0QTimFgv6LXIeS //5DOAAO9WwzlseTGmUgek3BbnnJJiGHVLBgnLaqWLOZ1Y8ON1uC8lQnbIeYbTQq EE5R0cbVLVXBJoKakBF8gwHF51HC2pSBYmHNZsSbjMuHpJWJM4fVldNWPNaqriKC OkL8QgvNoapgk20k1ajLl/ibv32k7QBKy3cTMtbQYPdreXcoZuMw38ysQcgFxPCs Zh92aaWW0ceWowkJ7CFnes2jdPcMSOYE37wodmV3/VV7cusmTD8wikyUdQARAQAB tCxMaWJyZXN3YW4gKFNpZ25pbmcgS2V5KSA8dGVhbUBsaWJyZXN3YW4ub3JnPokC OAQTAQIAIgUCUOOKVwIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQhf9L Q7MPxvkHyRAAgSq/QhdBurBaIjzqM4jZpaHEOURPlL38wHTBBeH4U5IZcwiPul9X Et1HqwHLDv89YjljHj76oOLt5xR14exgV0xWolZaLVpji3S6/NbCh37UMoWIBCSP j6/S6oAXxtX+oCI1lXmS4w60ZDDuYgVUrtAv77ODlQoPVf5TM0tU7Gb2Y3WB47DS XioIzwjFwJmtK3RzDRtF4oC2YFN3DBovVHmv6hbIt7NDNp7+NYRlx+wdi+XYFcNv +ZIARFkoc1Sr4HDk+lA2qx5jfvgZvabTn7OCTlCKwkSwO5sK0ICNcLmG9nb4ZNrU C2GXryTNQOMLcdvZAyBvxtgNzI7qqMAxeipsyCz5ypp5S3SwzHjqeCUJJ4pv7Ebn BnYIOgdLkq/WPsS6om7qwr3EdkR8iTZnuTi2Fejw7WnQP8dYLVXwG/90vNCU/HTE IYhal4ob7p0SsyLYF47U/iKl/b6ZErOcbq3YF0fMe8iusAtNLeIN4BLk9tpclGde weTPuB+MhRuDsLCF764ZB/R5v0CjWFVcBxnRXQbjlrm6dMlEXPFKjjV1fHL1HZhB GXopPmsw+NIf9sTSjcgNnLZGJFGGBsIxQD18AN6nzi2vtGRksB/FqLY7gIeGWaPu HlUI1qHdRLS7aus9nrS/RQTTUdCOsn1fRVozX2eVklAWgLuoz58oPhiJARwEEAEI AAYFAlDlHbkACgkQ5xgGprXMJ+Hc8Qf/Sd4NJMJifpU8hYET7IzMSgAdGZkkFV7/ 3/YCoEIVQS18xx+66L/TrUrAtJnlHLpmNUMA1wVFTtGJ/CRwFt3LsZYVM1jCwdRe AF492OHxEWXAboVnGRnGfJ3yhfCTd3XgRbthqBwR/8BSWCzs9Gy9YA5N6oceNf6q QkkLKk3YwdSNnW3b7o/AVdNcFbwkE+amNQ2mhWUtzzuvlsmgOrnCpUlq3djhnEKs pbl+T/apqvn7JRsOvuy/26kjoTbVrb7OpFmAjlIqbbxokaONFuDpqn/mtgG7Bk0r 3Pv501mRItACslhaKPJ02oPufAmzBrphjzzhCYlR1TeEek++9qoHyLkCDQRQ44pX ARAA1wzfaN4nMg8vorcuOQrEH6NX/OMS+qCSIAixhsJt0RT4Ds3YMWhO04i81tjQ bovsh8sOPFkU8WfVwuh7Riox+lz7z+ZxePMLLO7Y80Tc5jYE6exuOx5Ft5Q9FWF+ DanwpsUCvYE16G9fiRZlpBF5F5mWINnW59URLR29N8d+9GeeO6473aaKUFuo2ksN AueegzsW/cHiai6gHdrmTuJ8Ibg7P1TPkMsvvzJR0257Jp2CDKMwyzJh2dTzHiZU xTzH2qWrsfVA04EOXcC49hYkP7hDM731b1tt4cZaVlR7HHMGUe+zzA7eDW4/+0JT iCqYIndq/EsgZoYxE9rv1EksxWMyvCdlo6C3MYrjE8K5zOm926orkg1DABKDTfNe Am6c+siwdsMirOTe2QP5VSzRPDFe7aPDg8MNZ0tmww3+fyTDbeWlrv4jtmwa2BN9 C6h0d20lekD+eyZ87pzPWOFdQZxCmFteAPfq0R9ZNXuQrkubasaUrm54hfNAHVMj 4xfK1zmNFEQ+s2NLOPONzX/Uza/JHv9ZmqixJFABdNwMAUfKM9uO8pbu+aveMraW FBSQJDXqqZPF8qaiiTFXJeDXxD/d9CUfNrBozcpVbv2+BLKin5pKFPFRTNZX7mql 9btmQ6FKRtiKP86XldO0UNCkx3SgXo84sdiDdE+1uBtCV3MAEQEAAYkCHwQYAQIA CQUCUOOKVwIbDAAKCRCF/0tDsw/G+SkfD/43VjVVcO+P6Aj7be/Vda9FzeCNGQU0 GYCqdyZmXXGZUtlM8eLtVYcXHrw0O34f2eWNcQwYfiCsBfN4SSl8uevjyQZWCBo3 NhkxJlNcqOBPYrnT6uehRW+nnpV9agX8SNGR3VoM1pq7Zwheucxk5nmDKXJOGbin SQF9gDOpFnAYpLeI0/0qq3EvLf3blkUklYopMFw/Gj3sQM/V7nsyPstxMbqbf5al MlbQld7dP4FkQDLsKzB/0QARD02kHZsSs4tDpDA5R4cHl2VoNP7d9ly4YZsuH/99 DYSmJ57Tev6XTQ2/L4p+Tj9jEciQxyMpANh2XGL43WUuN/j24rqgwkyCzL8VA2I8 R7M4BIXi2q4kb5kcBNR0Y2VjU8xk41IMr/N11IayKAJYDFctrUAGrSmzVWAJ+XZg NDQgyp0rM2rON4AKUko4dlF5qv6MMKVY+s2B3KFdIHQriydQTy7LTdGRjvoPnkaU yPe/v9OLIM/4SJg7Juxtw4p3q7PxQ2nm7aTEc1bIYeZSIFQZwk9+oXR1vG7sogIE ULY6u21/CSzeBK5sZauGt9zmHO0xjQt4xUZuF0mOkVAzHeroUQ+YSmQdjfGs9O/e tNyu53Pd8d9grmpRwiQ/jO2dv4/a90903MuvaDPqYD+PMMkqPlxBhwjOThu2DTYi fMUPyfgigsi0FQ== =X982 -----END PGP PUBLIC KEY BLOCK----- libreswan-3.32/LICENSE000066400000000000000000000020301365625662500144470ustar00rootroot00000000000000Except for the exceptions listed below, this software is under the GNU General Public License (GPLv2+), see the file COPYING. See the file CREDITS and docs/CREDITS.openswan and docs/CREDITS.freeswan for contribution details. The linux/net/ipsec/radij.c code is derived from BSD 4.4lite code from sys/net/radix.c. In addition to the terms set out under the GPLv2+, permission is granted to link the software against the libdes, md5c.c, and radij.c libraries just mentioned. The following additional notes apply if you are NOT using CrytpoAPI: The DES library is under a BSD style license, see linux/crypto/ciphers/des/COPYRIGHT. Note that this software has a advertising clause in it. The MD5 implementation is from RSADSI, so this package must include the following phrase: "derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm". It is not under the GPL; see details in linux/net/ipsec/ipsec_md5c.c. Code in lib/libswan/nss_copies.c is used under the Mozilla Public License Version 2.0. https://www.mozilla.org/MPL/2.0/ libreswan-3.32/Makefile000066400000000000000000000214741365625662500151170ustar00rootroot00000000000000# Libreswan master makefile # # Copyright (C) 1998-2002 Henry Spencer. # Copyright (C) 2003-2004 Xelerance Corporation # Copyright (C) 2017, Richard Guy Briggs # Copyright (C) 2015-2018 Andrew Cagney # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # ifndef top_srcdir include mk/dirs.mk endif LIBRESWANSRCDIR?=$(shell pwd) include ${LIBRESWANSRCDIR}/Makefile.inc MAIN_RPM_VERSION = $(shell make showversion | sed "s/-.*//") MAIN_RPM_PREVER = $(shell make showversion | sed -e "s/^.[^-]*-\([^-]*\)-\(.*\)/rc\1_\2/" -e "s/-/_/") MAIN_RPM_PREFIX = libreswan-$(MAIN_RPM_VERSION)$(MAIN_RPM_PREVER) MAIN_RPM_RHEL_PKG = $(shell rpm -qf /etc/redhat-release) MAIN_RPM_RHEL_VERSION = $(shell echo $(MAIN_RPM_RHEL_PKG) | sed "s/.*-release-\(.\).*/\1/") MAIN_RPM_SPECFILE = $(shell if [ -f /etc/fedora-release ]; then echo packaging/fedora/libreswan.spec; elif [ -n "$(MAIN_RPM_RHEL_VERSION)" ]; then echo packaging/rhel/$(MAIN_RPM_RHEL_VERSION)/libreswan.spec; else echo "unknown distro, cannot find spec file to use in packaging directory"; fi) SRCDIR?=$(shell pwd)/ # dummy default rule def help: @echo @echo "To build and install on a recent Linux kernel that has NETKEY:" @echo @echo " make all && sudo make install" @echo @echo "For a minimal install (no manpages) type:" @echo @echo " make base && sudo make install-base" @echo @echo "See the files INSTALL and README for more general information," @echo "and details on how to build / install on KLIPS and other systems" @echo @echo "To build debian packages: make deb" @echo "To build fedora/rhel/centos rpms, see packaging/" @echo @false .PHONY: def help PATCHES=linux # where KLIPS goes in the kernel # note, some of the patches know the last part of this path KERNELKLIPS=$(KERNELSRC)/net/ipsec KERNELCRYPTODES=$(KERNELSRC)/crypto/ciphers/des KERNELLIBFREESWAN=$(KERNELSRC)/lib/libfreeswan KERNELLIBZLIB=$(KERNELSRC)/lib/zlib KERNELINCLUDE=$(KERNELSRC)/include MAKEUTILS=packaging/utils ERRCHECK=${MAKEUTILS}/errcheck KVUTIL=${MAKEUTILS}/kernelversion KVSHORTUTIL=${MAKEUTILS}/kernelversion-short SUBDIRS?=lib programs initsystems testing TAGSFILES=$(wildcard include/*.h lib/lib*/*.[ch] programs/*/*.[ch] linux/include/*.h linux/include/libreswan/*.h linux/net/ipsec/*.[ch]) tags: $(TAGSFILES) @LC_ALL=C ctags $(CTAGSFLAGS) ${TAGSFILES} cscope: @ls ${TAGSFILES} > cscope.files @cscope -b TAGS: $(TAGSFILES) @LC_ALL=C etags $(ETAGSFLAGS) ${TAGSFILES} .PHONY: dummy dummy: # Run regress stuff after the other check targets. .PHONY: regress check: regress regress: local-check recursive-check ifneq ($(strip(${REGRESSRESULTS})),) mkdir -p ${REGRESSRESULTS} -perl testing/utils/regress-summarize-results.pl ${REGRESSRESULTS} endif @echo "======== End of make check target. ========" include ${LIBRESWANSRCDIR}/mk/subdirs.mk # kernel details # what variant of our patches should we use, and where is it KERNELREL=$(shell ${KVSHORTUTIL} ${KERNELSRC}/Makefile) # directories visited by all recursion # programs ABSOBJDIR:=$(shell mkdir -p ${OBJDIR}; cd ${OBJDIR} && pwd) OBJDIRTOP=${ABSOBJDIR} # Recursive clean dealt with elsewhere. .PHONY: local-clean-base local-clean-base: $(foreach file,$(RPMTMPDIR) $(RPMDEST) out.*build out.*install, \ rm -rf $(file) ; ) # but leave out.kpatch # Delete absolutely everything. # # Since "clean" is a recursive target and requires the existence of # $(OBJDIR), "distclean" does not depend on it. If it did, "make # distclean" would have the quirky behaviour of first creating # $(OBJDIR) only to then delete it. .PHONY: distclean distclean: clean-kvm-keys rm -f $(RPMTMPDIR) $(RPMDEST) out.* rm -rf testing/pluto/*/OUTPUT* rm -rf OBJ.* $(OBJDIR) rm -rf BACKUP # set up for build buildready: rm -f dtrmakefile cvs.datemark # obsolete cd doc ; $(MAKE) -s rpm: # would be nice if we could support ~/.rpmmacros here @echo building rpm for libreswan testing mkdir -p ~/rpmbuild/SPECS/ sed -e "s/^Version:.*/Version: $(MAIN_RPM_VERSION)/g" \ -e "s/^#global prever.*/%global prever $(MAIN_RPM_PREVER)/" \ -e "s/^Release:.*/Release: 0.$(MAIN_RPM_PREVER)/" \ $(MAIN_RPM_SPECFILE) > ~/rpmbuild/SPECS/libreswan.spec mkdir -p ~/rpmbuild/SOURCES git archive --format=tar --prefix=libreswan-$(MAIN_RPM_VERSION)$(MAIN_RPM_PREVER)/ \ -o ~/rpmbuild/SOURCES/libreswan-$(MAIN_RPM_VERSION)$(MAIN_RPM_PREVER).tar HEAD if [ -a Makefile.inc.local ] ; then \ tar --transform "s|^|$(MAIN_RPM_PREFIX)/|" -rf ~/rpmbuild/SOURCES/$(MAIN_RPM_PREFIX).tar Makefile.inc.local ; \ fi; echo 'IPSECBASEVERSION=$(MAIN_RPM_VERSION)$(MAIN_RPM_PREVER)' > ~/rpmbuild/SOURCES/version.mk ( pushd ~/rpmbuild/SOURCES; tar --transform "s|^|$(MAIN_RPM_PREFIX)/mk/|" -rf ~/rpmbuild/SOURCES/$(MAIN_RPM_PREFIX).tar version.mk; popd) rm ~/rpmbuild/SOURCES/version.mk gzip -f ~/rpmbuild/SOURCES/$(MAIN_RPM_PREFIX).tar rpmbuild -ba ~/rpmbuild/SPECS/libreswan.spec tarpkg: @echo "Generating tar.gz package to install" @rm -rf /var/tmp/libreswan-${USER} @make DESTDIR=/var/tmp/libreswan-${USER} programs install @rm /var/tmp/libreswan-${USER}/etc/ipsec.conf @(cd /var/tmp/libreswan-${USER} && tar czf - . ) >libreswan-${IPSECVERSION}.tgz @ls -l libreswan-${IPSECVERSION}.tgz @rm -rf /var/tmp/libreswan-${USER} env: @env | sed -e "s/'/'\\\\''/g" -e "s/\([^=]*\)=\(.*\)/\1='\2'/" # # A target that does nothing intesting is sometimes interesting... war: @echo "Not Love?" showversion: @echo ${IPSECVERSION} | sed "s/^v//" showdebversion: @echo ${IPSECVERSION} | sed "s/^v//" | sed -e "s/\([0-9]\{1,3\}\)\.\([0-9]\{1,3\}\)\(.*\)/\1.\2~\3/" | sed "s/~-/~/" showrpmversion: @echo ${IPSECVERSION} | sed "s/^v//" | sed -e "s/^v//;s/\([0-9]\{1,3\}\)\.\([0-9]\{1,3\}\)\(.*\)/\1.\2_\3/;s/-/_/g;s/__/_/g" showrpmrelease: @echo ${IPSECVERSION} | sed "s/^v//" | sed "s/^[^-]*-\(.*\)/\1/" showobjdir: @echo $(OBJDIR) # these need to move elsewhere and get fixed not to use root .PHONY: deb-prepare DEBIPSECBASEVERSION=$(shell make -s showdebversion) deb-prepare: cp -r packaging/debian . cat debian/changelog grep "IPSECBASEVERSION" debian/changelog && \ sed -i "s/@IPSECBASEVERSION@/$(DEBIPSECBASEVERSION)/g" debian/changelog || \ echo "missing IPSECBASEVERSION in debian/changelog. This is not git repository?" cat debian/changelog .PHONY: deb deb: deb-prepare debuild -i -us -uc -b rm -fr debian #debuild -S -sa release: packaging/utils/makerelease local-install: @if test -z "$(DESTDIR)" -a -x /usr/sbin/selinuxenabled -a $(PUBDIR) != "$(DESTDIR)/usr/sbin" ; then \ if /usr/sbin/selinuxenabled ; then \ echo -e "\n************************** WARNING ***********************************" ; \ echo "SElinux is present on this system and the prefix path is not /usr." ; \ echo "This can cause software failures if selinux is running in Enforcing mode"; \ echo -e "unless selinux policies are updated manually to allow this.\n" ; \ echo "The following commands fix a common issue of /usr/local/ being mislabeled"; \ echo " restorecon /usr/local/sbin -Rv"; \ echo " restorecon /usr/local/libexec/ipsec -Rv"; \ if test -x /usr/sbin/getenforce ; then \ echo -e "\nSElinux is currently running in `/usr/sbin/getenforce` mode" ; \ fi ; \ echo -e "**********************************************************************\n" ; \ fi \ fi @if test ! -f $(DESTDIR)/etc/pam.d/pluto ; then \ mkdir -p $(DESTDIR)/etc/pam.d/ ; \ $(INSTALL) $(INSTCONFFLAGS) pam.d/pluto $(DESTDIR)/etc/pam.d/pluto ; \ else \ echo -e "\n************************** WARNING ***********************************" ; \ echo "We are not installing a new copy of the pam.d/pluto file, as one" ; \ echo "was already present. You may wish to update it yourself if desired." ; \ echo -e "**********************************************************************\n" ; \ fi # Test only target (run by swan-install) that generates FIPS .*.hmac # file for pluto that will be verified by fipscheck. # # (should really use fipshmac -d /usr/lib64/fipscheck but then # we need to hassle with multilib) # Without this fipscheck (run in FIPS mode) will fail. .PHONY: install-fipshmac install-fipshmac: ifeq ($(USE_FIPSCHECK),true) fipshmac $(LIBEXECDIR)/pluto else @echo "install-fipshmac target requires compiling with USE_FIPSCHECK" @exit 1 endif include ${LIBRESWANSRCDIR}/mk/docker-targets.mk include ${LIBRESWANSRCDIR}/mk/kvm-targets.mk include ${LIBRESWANSRCDIR}/mk/web-targets.mk ifeq ($(USE_KLIPS),true) include ${LIBRESWANSRCDIR}/mk/kernel.mk endif libreswan-3.32/Makefile.inc000066400000000000000000000001541365625662500156570ustar00rootroot00000000000000# For compatibility, new code should include mk/config.mk directly. include ${LIBRESWANSRCDIR}/mk/config.mk libreswan-3.32/Makefile.ver000066400000000000000000000001561365625662500157040ustar00rootroot00000000000000# For compatibility, new code should include mk/version.mk directly. include ${LIBRESWANSRCDIR}/mk/version.mk libreswan-3.32/README.KLIPS000066400000000000000000000141151365625662500152120ustar00rootroot00000000000000 ######################################################################### # 2018-10-23: # WARNING: KLIPS is obsolete. Please use VTI/XFRMi interfaces instead ######################################################################### ######################################################################### # KLIPS Libreswan 3.X Release Notes ######################################################################### KLIPS is an alternative IPsec stack for the Linux kernel. It features: - ipsecX devices for easy firewalling and tcpdumping - OCF support (crypto hardware offload) with many hardware drivers - SAref tracking for IPsec transport mode connections with NAT. - First+Last packet caching - Extensive debugging output (enabled via ipsec klipsdebug) - Native AES/3DES and MD5/SHA1 support as well as some CryptoAPI support ######################################################################### # REQUIREMENTS ######################################################################### A recent Linux distribution based on either Kernel 2.4.x, 2.6.x or 3.x, with the required tools to compile kernel modules. ######################################################################### # Compiling KLIPS ######################################################################### make module sudo make module_install This builds a module against the running kernel. It is the equivalent of running: make KERNELSRC=/lib/modules/`uname -r`/build module sudo make KERNELSRC=/lib/modules/`uname -r`/build module_install To compile a module for another kernel, one can set KERNELSRC to point to directory with kernel headers or a full kernel source tree (eg /usr/src/kernels/) ######################################################################### # NAT TRAVERSAL ######################################################################### For Linux 2.6 Kernels before 2.6.23, including 2.4 linux systems, the kernel requires patching if NAT-T support is required. The full kernel source is required as some of the actual kernel source files need to be patched. See your distribution documentation on how to build and install a new kernel Add NAT-T support (if required). From the Libreswan source directory: make KERNELSRC=/usr/src/linux nattpatch | patch -d /usr/src/linux -p1 ######################################################################### # SAref tracking support ######################################################################### Premade patches for some distributions kernels can be found in patches/kernel/ directory of the libreswan source directory. If there is no patch for your exact kernel version, pick the version of the patch that matches your kernel closest - but don't pick a higher version than the kernel you have. Documentation on SAref/MAST can be found in docs/HACKING/Mast* and doc/klips/mast.xml. To understand what SAref tracking does, see doc/ipsecsaref.png and the overlapip= entry in the ipsec.conf man page. ######################################################################### # OCF support ######################################################################### For OCF HW offloading support, you need a kernel that has support for an OCF kernel module, or has been patched with OCF support. See: http://ocf-linux.sourceforge.net/ for more details. Compile a module with MODULE_DEFCONFIG= set to packaging/ocf/config-all.h, eg: make module MODULE_DEFCONFIG=/opt/build/libreswan/packaging/ocf/config-all.h sudo make module_install To test if KLIPS is properly compiled: modprobe ocf modprobe ipsec dmesg packaging/ocf/config-all.h can be modified to enable specific hardware crypto processors. This usually requires vendor source code to compile. The "software module" works with the NETKEY/XFRM stack as well and can accelerate NETKEY/XFRM over multiple CPU's. The kernel module ocf_bench can be used for benchmarking. The ocf_bench module is designed to "fail" loading into the kernel. A benchmark can be done using: modprobe ocf_bench dmesg ######################################################################### # SUPPORT ######################################################################### Mailing Lists: https://lists.libreswan.org is home of the mailing lists Wiki: https://libreswan.org is home to the Libreswan WIKI. It has the most up to date documentation, interop guides and other related information. IRC: Libreswan developers and users can be found on IRC, on #swan irc.freenode.net. ######################################################################### # BUGS ######################################################################### Bugs with the package can be filed into our bug tracking system, at https://bugs.libreswan.org ######################################################################### # SECURITY HOLES ######################################################################### All security vulnerabilities found that require public disclosure will receive proper CVE tracking numbers (see http://mitre.org/) and co-ordinated via the vendor-sec (or successor) mailing list. A complete list of known security vulnerabilities is available at: https://www.libreswan.org/security/ ######################################################################### # DEVELOPMENT ######################################################################### Those interested in the development, patches, beta releases of Libreswan can join the development mailing list (https://lists.libreswan.org - dev@lists.libreswan.org) or join the development team on IRC in #swan on irc.freenode.net For those who want to track things a bit more closely, the commits@lists.libreswan.org mailinglist will mail all the commit messages. ######################################################################### # DOCUMENTATION ######################################################################### The most up to date docs are in the man pages and at https://libreswan.org/ The bulk of this software is under the GNU General Public License; see LICENSE. Some parts of it are not; see CREDITS for the details. libreswan-3.32/README.md000066400000000000000000000161001365625662500147240ustar00rootroot00000000000000# Libreswan The Libreswan Project https://libreswan.org/ Libreswan is an Internet Key Exchange (IKE) implementation for Linux. It supports IKEv1 and IKEv2 and has support for most of the extensions (RFC + IETF drafts) related to IPsec, including IKEv2, X.509 Digital Certificates, NAT Traversal, and many others. Libreswan uses the native Linux IPsec stack (NETKEY/XFRM) per default. Libreswan was forked from Openswan 2.6.38, which was forked from FreeS/WAN 2.04. See the CREDITS files for contributor acknowledgments. It can be downloaded from: https://download.libreswan.org/ A Git repository is available at: https://github.com/libreswan/libreswan/ ## License The bulk of libreswan is licensed under the GNU General Public License version 2; see the LICENSE and CREDIT.* files. Some smaller parts have a different license. ## Requirements Recent Linux distributions based on kernel 2.x, 3.x or 4.x are supported platforms. Libreswan has been ported to Win2k/BSD/OSX in the past as well. Most distributions have native packaged support for Libreswan. Libreswan is available for RHEL, Fedora, Ubuntu, Debian, Arch, OpenWrt and more. Unless a source-based build is truly needed, it is often best to use the pre-built version of the distribution you are using. There are a few packages required for Libreswan to compile from source: For Debian/Ubuntu apt-get install libnss3-dev libnspr4-dev pkg-config libpam-dev \ libcap-ng-dev libcap-ng-utils libselinux-dev \ libcurl3-nss-dev flex bison gcc make libldns-dev \ libunbound-dev libnss3-tools libevent-dev xmlto \ libsystemd-dev (there is no fipscheck library for these, set USE_FIPSCHECK=false) (unbound is build without event api, set USE_DNSSEC=false) For Fedora/RHEL8/CentOS8/RHEL7/CentOS7 yum install audit-libs-devel bison curl-devel fipscheck-devel flex \ gcc ldns-devel libcap-ng-devel libevent-devel \ libseccomp-devel libselinux-devel make nspr-devel nss-devel \ pam-devel pkgconfig systemd-devel unbound-devel xmlto For RHEL6/CentOS6 yum install audit-libs-devel bison curl-devel fipscheck-devel flex \ gcc libcap-ng-devel libevent2-devel libseccomp-devel \ libselinux-devel make nspr-devel nss-devel pam-devel \ pkgconfig systemd-devel xmlto (unbound is too old to build dnssec support, set USE_DNSSEC=false) Runtime requirements (usually already present on the system) nss, iproute2, iptables, sed, awk, bash, cut, procps-ng, which (note: the Busybox version of "ip" does not support 'ip xfrm', so ensure you enable the iproute(2) package for busybox) Python is used for "ipsec verify", which helps debugging problems python-ipaddress is used for "ipsec show", which shows tunnels ## Building for RPM based systems See packaging/ for an up to date spec file for your distribution. For example, to build for CentOS8, use: rpmbuild -ba packaging/centos/8/libreswan.spec ## Building for DEB based systems The packaging/debian directly is used to build deb files. Simply issue the command: make deb ## Compiling the userland and IKE daemon manually in /usr/local make programs sudo make install If you want to build without creating and installing manual pages, run: make base sudo make install-base Note: The ipsec-tools package or setkey is not needed. Instead the iproute2 packakge (>= 2.6.8) is required. Run `ipsec verify` to determine if your system misses any of the requirements. This will also tell you if any of the kernel sysctl values needs changing. ## Starting Libreswan The install will detect the init system used (systemd, upstart, sysvinit, openrc) and should integrate with the linux distribution. The service name is called "ipsec". For example, on RHEL8, one would use: systemctl enable ipsec.service systemctl start ipsec.service If unsure of the specific init system used on the system, the "ipsec" command can also be used to start or stop the ipsec service. This command will auto-detect the init system and invoke it: ipsec start ipsec stop ## Status For a connection status overview, use: ipsec trafficstatus For a brief status overview, use: ipsec briefstatus For a machine readable global status, use: ipsec globalstatus ## Configuration Most of the libreswan configuration is stored in /etc/ipsec.conf and /etc/ipsec.secrets. Include files may be present in /etc/ipsec.d/ See the respective man pages for more information. ## NSS initialisation Libreswan uses NSS to store private keys and X.509 certificates. The NSS database should have been initialised by the package installer. If not, the NSS database can be initialised using: ipsec initnss PKCS#12 certificates (.p12 files) can be imported using: ipsec import /path/to/your.p12 See README.NSS and `certutil --help` for more details on using NSS and migrating from the old Openswan `/etc/ipsec.d/` directories to using NSS. ## Upgrading If you are upgrading from FreeS/WAN 1.x or Openswan 2.x to Libreswan 3.x, you might need to adjust your config files, although great care has been put into making the configuration files full backwards compatible. See also: https://libreswan.org/wiki/HOWTO:_openswan_to_libreswan_migration See 'man ipsec.conf' for the list of options to find any new features. You can run `make install` on top of your old version - it will not overwrite your your `/etc/ipsec.*` configuration files. The default install target installs in `/usr/local`. Ensure you do not install libreswan twice, one from a distribution package in /usr and once manually in /usr/local. ## Support Mailing lists: https://lists.libreswan.org/ is home of all our the mailing lists Wiki: https://libreswan.org is home to the Libreswan wiki. it contains documentation, interop guides and other useful information. IRC: Libreswan developers and users can be found on IRC, on #swan irc.freenode.net. ## Bugs Bugs can be reported on the mailing list or using our bug tracking system, at https://bugs.libreswan.org/ ## Security Information All security issues found that require public disclosure will receive proper CVE tracking numbers (see https://www.mitre.org/) and will be co-ordinated via the vendor-sec / oss-security lists. A complete list of known security vulnerabilities is available at: https://libreswan.org/security/ ## Development Those interested in the development, patches, and beta releases of Libreswan can join the development mailing list "swan-dev" or talk to the development team on IRC in #swan on irc.freenode.net For those who want to track things a bit more closely, the swan-commits@lists.libreswan.org mailing list will mail all the commit messages when they happen. This list is quite busy during active development periods. ## Documentation The most up to date documentation consists of the man pages that come with the software. Further documentation can be found at https://libreswan.org/ and the wiki at https://libreswan.org/wiki/ ## KLIPS IPsec stack The KLIPS IPsec stack is no longer actively maintained or supported. Please migreate to using the Linux native netlink/XFRM stack. If you wish to have network interfaces like KLIPS has, please use the XFRMi (VTI) interfaces. libreswan-3.32/README.nss000066400000000000000000000241771365625662500151440ustar00rootroot00000000000000 ######################################################################### # Using the NSS crypto library with Pluto (Libreswan) # Based on initial documentation by Avesh Agarwal ######################################################################### For detailed developer information about NSS, see https://www.mozilla.org/projects/security/pki/nss/ The NSS crypto library is a user space library. It is only used with the libreswan userspace IKE daemon pluto for cryptographic operations. NSS does not perform IPsec crypto operations inside the kernel (KLIPS nor NETKEY) The NSS library exports a PKCS#11 API for the application to communicate to a cryptographic device. The cryptographic device is usually the "soft token" but can also be a Hardware Security Module (HSM). The advantage of using NSS is that pluto does need to know in detail how the cryptographic device works. Pluto does not access any private keys or data itself. Instead, it uses the PK11 wrapper API of NSS irrespective of the cryptographic device used. Pluto hands over work using the PK11 interface to NSS and never has direct access to the private key material itself. Both IKEv1 and IKEv2 operations are performed using NSS. Private RSA keys (raw RSA as well as X.509 based private RSA keys) are stored inside NSS. RSA keys are still referenced in /etc/ipsec.secrets. X.509 keys and certificates are referenced using their "nickname" instead of their filename in /etc/ipsec.conf. While PreShared Key (PSK) calculations are done using NSS, the actual preshared key ("secret") is still stored in /etc/ipsec.secrets. NSS as shipped by Red Hat is a FIPS certified library. Libreswan is currently being FIPS certified for RHEL7. ######################################################################### # The NSS command line tools used with libreswan ######################################################################### - certutil: Look and modify the NSS db. "ipsec initnss" and "ipsec look" use certutil under the hood. https://www.mozilla.org/projects/security/pki/nss/tools/certutil.html - pk12util: import and export certificates and keys from and to the NSS db. The "ipsec import" command is a simple wrapper around this utility. https://www.mozilla.org/projects/security/pki/nss/tools/pk12util.html - modutil: Put NSS into FIPS mode https://www.mozilla.org/projects/security/pki/nss/tools/modutil.html ######################################################################### # Creating the NSS db for use with libreswan's pluto IKE daemon ######################################################################### If you are not using a packaged libreswan version, you might need to create a new NSS db before you can start libreswan. This can be done using: ipsec initnss By default the NSS db is created in /etc/ipsec.d/ on RHEL/Fedora/CentOS but in /var/lib/ipsec/nss/ on Debian/Ubuntu. The remainder of this file uses /etc/ipsec.d/ in the examples. When creating a database, you are prompted for a password. The default libreswan package install for RHEL/Fedora/CentOS uses an empty password. It is up to the administrator to decide on whether to use a password or not. However, a non-empty database password must be provided when running in FIPS mode. To change the empty password, run: certutil -W -d sql:/etc/ipsec.d Enter return for the "old password", then enter your new password. If you create the database with a password, and want to run NSS in FIPS mode, you must create a password file with the name "nsspassword" in the /etc/ipsec.d directory before starting libreswan. The "nsspassword" file must contain the password you provided when creating NSS database. If the NSS db is protected with a non-empty password, the "nsspassword" file must exist for pluto to start. The syntax of the "nsspassword" file is: token_1_name:the_password token_2_name:the_password The name of NSS softtoken (the default software NSS db) when NOT running in FIPS mode is "NSS Certificate DB". If you wish to use software NSS db with password "secret", you would have the following entry in the nsspassword file: NSS Certificate DB:secret If running NSS in FIPS mode, the name of NSS softtoken is "NSS FIPS 140-2 Certificate DB". If there are smartcards in the system, the entries for passwords should be entered in this file as well. Note: do not enter any spaces before or after the token name or password. ######################################################################### # Using raw RSA keys with NSS ######################################################################### The "ipsec newhostkey" and "ipsec rsasigkey" utilities are used for creating raw RSA keys. If a non-default NSS directory is used, this can be specified using the --nssdir option. ipsec newhostkey --nssdir /tmp/ipsec.d [--password password] The password is only required if the NSS database is protected with a non-empty password. Public key information is available via the "ipsec showhostkey" command can be used to generate left/rightrsasigkey= entries for /etc/ipsec.conf. ######################################################################### # Using certificates with NSS ######################################################################### Any X.509 certificate management system can be used to generate Certificate Agencies, certificates, pkcs12 files and CRLs. Common tools people use are the openssl command, the GTK utility tinyca2, or the NSS certutil command. An example using openssl can be found as part of the libreswan test suite at https://github.com/libreswan/libreswan/tree/master/testing/x509 Below, we will be using the nss tools to generate certificates * To create a certificate authority (CA certificate): certutil -S -k rsa -n "ExampleCA" -s "CN=Example CA Inc" -v 12 \ -t "CT,," -x -d sql:/etc/ipsec.d It creates a certificate with RSA keys (-k rsa) with the nickname "ExampleCA", and with common name "Example CA Inc". The option "-v" specifies the certificates validy period. "-t" specifies the attributes of the certificate. "C" is required for creating a CA certificate. "-x" mean self signed. "-d" specifies the path of the database directory. The directory path should be prefixed with 'sql:' in order to use the SQLite format. NOTE: It is not a requirement to create the CA in NSS database. The CA certificate can be obtained from anywhere in the world. * To create a user certificate signed by the above CA certutil -S -k rsa -c "ExampleCA" -n "user1" -s "CN=User Common Name" \ -v 12 -t "u,u,u" -d sql:/etc/ipsec.d It creates a user cert with nickname "user1" with attributes "u,u,u" signed by the CA cert "ExampleCA". NOTE: You must provide a nick name when creating a user certificate, because pluto reads the user certificate from the NSS database based on the user certificate's nickname. ######################################################################### # Configuring certificates in ipsec.conf and ipsec.secrets ######################################################################### In ipsec.conf, the leftcert= option takes a certificate nickname as argument. For example if the nickname of the user cert is "hugh", then it can be "leftcert=hugh". NOTE: if you are migrating from openswan, you are used to specifying a filename for the leftcert= option. Filenames are not valid for the left/rightcert= options in libreswan. In ipsec.secrets, we need to list the certificate nickname to inform pluto there is a certificate within the NSS db. This is specified using: : RSA nickname NOTE: In openswan and freeswan it was required to specify a file name or password. With libreswan, this is not required. NOTE: openswan and freeswan stored private keys in /etc/ipsec.d/private/ This directory does not exist for libreswan. The directories /etc/ipsec.d/cacerts/ and /etc/ipsec.d/crls/ can still be used. NOTE: the freeswan and openswan directories /etc/ipsec.d/aacerts/ and /etc/ipsec.d/acerts/ are not used with libreswan. If you use an external CA certificate, you can either import it into the NSS db or place it in the /etc/ipsec.d/cacerts/ directory. Note that the preferred method is to store it inside the NSS db. ######################################################################### # Importing third-party certificates into NSS ######################################################################### If you do not have the third-party certificate in PKCS#12 format, use openssl to create a PKCS#12 file: openssl pkcs12 -export -in cert.pem -inkey key.pem \ -certfile cacert.pem -out certkey.p12 [-name YourName] Now you can import the file into the NSS db: ipsec import certkey.p12 If you did not pick a name using the -name option, you can use certutil -L -d sql:/etc/ipsec.d to figure out the name NSS picked during the import. Add following to /etc/ipsec.secrets file: : RSA "YourName" To specify the certificate in ipsec.conf, use a line like: leftcert=YourName ######################################################################### # Exporting a CA(?) certificate to load on another libreswan machine ######################################################################### Paul: wouldn't this also include the private key which we don't want????? Paul: add "ipsec export" ? To export the CA certificate: pk12util -o cacert1.p12 -n cacert1 -d sql:/etc/ipsec.d Copy the file "cacert1.p12" to the new machine and import it using: ipsec import cacert1.p12 certutil -M -n cacert1 -t "CT,," -d sql:/etc/ipsec.d Example connection for ipsec.conf: conn pluto-1-2 left=1.2.3.4 leftid="CN=usercert1" leftrsasigkey=%cert leftcert=usercert1 right=5.6.7.8 rightid="CN=usercert2" rightrsasigkey=%cert auto=add ######################################################################### # Configuring a smartcard with NSS ######################################################################### Required library: libcoolkey To make smartcard tokens visible through NSS modutil -add -libfile libcoolkeypk11.so \ -dbdir \ -mechanisms An example of mechanisms can be RC2:RC4:DES:DH:SHA1:MD5:MD2:SSL:TLS:AES:CAMELLIA. To check whether the token is visible or not, please run modutil -list -dbdir libreswan-3.32/README.x509000066400000000000000000000000751365625662500150350ustar00rootroot00000000000000 See README.nss or check the wiki at https://libreswan.org/ libreswan-3.32/TRADEMARK000066400000000000000000000005531365625662500147070ustar00rootroot00000000000000 placeholder: this should contain information to demonstrate trademark use similar to debian's policy, eg https://wiki.mako.cc/Draft_Debian_trademark_policy or Mozilla's https://www.mozilla.org/foundation/trademarks/faq.html The goal is to make it free to everyone, but avoid future problems where third parties claim to own the name, trademark, logo or code. libreswan-3.32/buildwin.sh000077500000000000000000000000741365625662500156240ustar00rootroot00000000000000#!/bin/sh make OS=cygwin BUILDENV=cygwin32-linux programs libreswan-3.32/contrib/000077500000000000000000000000001365625662500151075ustar00rootroot00000000000000libreswan-3.32/contrib/README000066400000000000000000000010411365625662500157630ustar00rootroot00000000000000 Unmaintained contrib files - mostly outdated and unwise to use cisco-decrypt - decrypt cisco obfuscation secrets in cisco *.pcf files cisco-pcf - convert cisco PCF configuration files to libreswan config files ldsaref - SAref example implementation lucent - interop hacking with some proprietary lucent gateway patching - klips patching scripts from/between klips trees (unused) scripts - perl scripts for emulating ipsec eroute output when using NETKEY python-swan - python module to determine if traffic to a destination would get encrypted libreswan-3.32/contrib/c-swan/000077500000000000000000000000001365625662500162775ustar00rootroot00000000000000libreswan-3.32/contrib/c-swan/Makefile000066400000000000000000000011101365625662500177300ustar00rootroot00000000000000.PHONY: clean CFLAGS += \ -I/usr/include/nspr4 \ -I../../include \ -I../../linux/include LIBSRC = \ ../../lib/libswan/initsubnet.c \ ../../lib/libswan/ip_address.c \ ../../lib/libswan/sameaddr.c \ ../../lib/libswan/subnettypeof.c \ ../../lib/libswan/ttoaddr.c \ ../../lib/libswan/ttosubnet.c \ ../../lib/libswan/ttoul.c \ ../../linux/net/ipsec/addrtot.c \ ../../linux/net/ipsec/addrtypeof.c \ ../../linux/net/ipsec/anyaddr.c \ ../../linux/net/ipsec/initaddr.c \ ../../linux/net/ipsec/ultot.c is_encrypted: is_encrypted.c swan.c $(LIBSRC) clean: rm -f is_encrypted libreswan-3.32/contrib/c-swan/is_encrypted.c000066400000000000000000000035711365625662500211410ustar00rootroot00000000000000/* * Is connection encrypted? -utility. * * Copyright (C) 2018 Kim B. Heino * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include "swan.h" /* Parse args and call is_encrypted() from swan.c */ int main(int argc, char *argv[]) { char source_ip[IPLEN + 1], dest_ip[IPLEN + 1]; int debug = 0, port = 0; *source_ip = 0; *dest_ip = 0; for (;;) { static struct option long_options[] = { {"debug", no_argument, 0, 1}, {"source", required_argument, 0, 2}, {"port", required_argument, 0, 3}, {0, 0, 0, 0} }; int option_index = 0, opt; opt = getopt_long(argc, argv, "", long_options, &option_index); if (opt == -1) break; switch (opt) { case 1: debug = 1; break; case 2: strncpy(source_ip, optarg, IPLEN); source_ip[IPLEN] = 0; break; case 3: port = atoi(optarg); break; default: exit(1); } } if (optind != argc - 1) { printf("No destination IP address specified\n"); exit(1); } strncpy(dest_ip, argv[optind], IPLEN); dest_ip[IPLEN] = 0; int ret = is_encrypted(dest_ip, port, source_ip, 2, debug); printf("%s\n", ret ? "True" : "False"); return ret; } libreswan-3.32/contrib/c-swan/swan.c000066400000000000000000000157231365625662500174230ustar00rootroot00000000000000/* * Is connection encrypted? -utility. * * Copyright (C) 2018 Kim B. Heino * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "libreswan.h" #include "swan.h" #define COMMAND_BUFFER 65536 /* Max length of "ip xfrm" output */ /* Dummy logger to require less lib dependencies. */ int libreswan_log(const char *fmt, ...) { return 0; } /* Run external command and return its output, NUL terminated. */ static char *run_command(char **params) { int link[2]; pid_t pid; char *buffer; if (pipe(link) == -1) return NULL; if ((pid = fork()) == -1) return NULL; if (pid == 0) { dup2(link[1], STDOUT_FILENO); close(link[0]); close(link[1]); execv(params[0], params); exit(0); } buffer = malloc(COMMAND_BUFFER); if (buffer == NULL) return NULL; close(link[1]); int nbytes = read(link[0], buffer, COMMAND_BUFFER - 1); wait(NULL); close(link[0]); if (nbytes < 0) nbytes = 0; buffer[nbytes] = 0; return buffer; } /* Split command output to NUL terminated words. */ static char *split_words(char *command_output) { char *buffer, *from, *to; /* Worst case is "\n\n...", resulting 2 * input size */ buffer = malloc(COMMAND_BUFFER * 2 + 2); if (buffer == NULL) return NULL; /* Split to words */ from = command_output; to = buffer; if (from != NULL) while (*from != 0) { /* Skip " " and "\" */ while (*from == ' ' || *from == '\t' || *from == '\\') from++; if (*from == '\n') { /* Copy "\n" as word */ *(to++) = *(from++); } else { /* Copy word */ while (*from > ' ' && *from != '\\') *(to++) = *(from++); } *(to++) = 0; } /* Add end marker */ *(to++) = 0; *(to++) = 0; /* Free command output buffer */ if (command_output != NULL) free(command_output); return buffer; } /* Get my source IP address */ static int get_source_ip(char *destination, char *source) { char *output, *p; char *params[8]; params[0] = "/sbin/ip"; params[1] = "-oneline"; params[2] = "route"; params[3] = "get"; params[4] = destination; params[5] = NULL; output = split_words(run_command(params)); for (p = output; *p != 0; p += strlen(p) + 1) { if (strcmp(p, "src") == 0) { strncpy(source, p + strlen(p) + 1, IPLEN); source[IPLEN] = 0; break; } } free(output); if (*source == 0) { printf("Failed to detect source IP\n"); return -1; } return 0; } /* Is address inside subnet+mask? */ static bool addr_in_mask(char *address_str, char *mask_str) { ip_address address; ip_subnet mask; err_t err; err = ttoaddr(address_str, 0, AF_UNSPEC, &address); if (err) return false; err = ttosubnet(mask_str, 0, '0', AF_UNSPEC, &mask); if (err) return false; return addrinsubnet(&address, &mask); } /* Get "ip xfrm" output */ static char *get_policy_list(void) { char *output; char *params[8]; params[0] = "/sbin/ip"; params[1] = "-oneline"; params[2] = "xfrm"; params[3] = "policy"; params[4] = "list"; params[5] = NULL; output = split_words(run_command(params)); return output; } /* Parse xfrm policy list */ static bool parse_policy_list(char *source, char *destination, char *xfrm, int debug) { struct { char src[128]; char dst[128]; char dir[128]; char priority[128]; char proto[128]; char reqid[128]; } parsed; bool encrypted = false; int priority = 65536; char *keyword, *p; memset(&parsed, 0, sizeof(parsed)); keyword = NULL; for (p = xfrm; *p != 0; p += strlen(p) + 1) { if (*p == '\n') { /* End of line - check it */ int prio = atoi(parsed.priority); if (strcmp(parsed.dir, "out") == 0 && strcmp(parsed.proto, "esp") == 0 && prio > 0 && prio < priority && *parsed.src != 0 && *parsed.dst != 0 && addr_in_mask(source, parsed.src) && addr_in_mask(destination, parsed.dst)) { /* Got match, update encrypted variable. */ if (debug) printf("src %s dst %s dir %s priority %s proto %s reqid %s\n", parsed.src, parsed.dst, parsed.dir, parsed.priority, parsed.proto, parsed.reqid); priority = prio; encrypted = *parsed.reqid != 0 && strcmp(parsed.reqid, "0") != 0; } memset(&parsed, 0, sizeof(parsed)); keyword = NULL; } else if (keyword != NULL) { if (*keyword == 0) { strncpy(keyword, p, IPLEN); keyword[IPLEN] = 0; } keyword = NULL; } else if (strcmp(p, "src") == 0) keyword = parsed.src; else if (strcmp(p, "dst") == 0) keyword = parsed.dst; else if (strcmp(p, "dir") == 0) keyword = parsed.dir; else if (strcmp(p, "priority") == 0) keyword = parsed.priority; else if (strcmp(p, "proto") == 0) keyword = parsed.proto; else if (strcmp(p, "reqid") == 0) keyword = parsed.reqid; } return encrypted; } /* Connect to dest:port, ignore errors */ static void connect_to(char *destination, int port, int timeout) { struct addrinfo hints; struct addrinfo *result, *rp; char port_str[16]; int sock; fd_set fdset; struct timeval tv; /* Parse destination:port */ memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = 0; hints.ai_protocol = 0; sprintf(port_str, "%d", port); if (getaddrinfo(destination, port_str, &hints, &result) != 0) return; for (rp = result; rp != NULL; rp = rp->ai_next) { /* Open non-blocking connection */ sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if (sock == -1) continue; fcntl(sock, F_SETFL, O_NONBLOCK); connect(sock, rp->ai_addr, rp->ai_addrlen); /* Wait until timeout or connected */ FD_ZERO(&fdset); FD_SET(sock, &fdset); tv.tv_sec = timeout; tv.tv_usec = 0; select(sock + 1, NULL, &fdset, NULL, &tv); close(sock); } freeaddrinfo(result); } /* Is connection encrypted? */ bool is_encrypted(char *destination, int port, char *source, int timeout, int debug) { if (*source == 0 && get_source_ip(destination, source) == -1) return false; if (debug) printf("Checking %s to %s port %d\n", source, destination, port); if (port > 0) connect_to(destination, port, timeout); char *xfrm = get_policy_list(); bool ret = parse_policy_list(source, destination, xfrm, debug); free(xfrm); return ret; } libreswan-3.32/contrib/c-swan/swan.h000066400000000000000000000017121365625662500174210ustar00rootroot00000000000000/* * Is connection encrypted? -utility. * * Copyright (C) 2018 Kim B. Heino * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #define IPLEN 100 /* Max length for IP address/mask string */ bool is_encrypted(char *destination, int port, char *source, int timeout, int debug); libreswan-3.32/contrib/cisco-decrypt/000077500000000000000000000000001365625662500176575ustar00rootroot00000000000000libreswan-3.32/contrib/cisco-decrypt/Makefile000066400000000000000000000004231365625662500213160ustar00rootroot00000000000000all: cisco-decrypt clean: rm cisco-decrypt install: echo "cisco-decrypt is also installed as part of the vpnc packae" install -D cisco-decrypt /usr/local/bin/ install -D cisco-decrypt.1 /usr/local/man/man1/ cisco-decrypt: cc -lgcrypt -o cisco-decrypt cisco-decrypt.c libreswan-3.32/contrib/cisco-decrypt/README000066400000000000000000000002601365625662500205350ustar00rootroot00000000000000See source code for copyrights and information. Taken from the vpnc package. It is not installed per default, because vpnc already installs it. It is here for reference only. libreswan-3.32/contrib/cisco-decrypt/cisco-decrypt.1000066400000000000000000000020261365625662500225110ustar00rootroot00000000000000.TH "CISCO-DECRYPT" "1" "August 2007" "cisco-decrypt" "vpnc" .SH "NAME" cisco-decrypt \- decrypts an obfuscated Cisco vpn client pre-shared key .\" .\" $Id: cisco-decrypt.1 204 2007-08-14 18:01:28Z Joerg Mayer $ .\" .SH "SYNOPSIS" .B cisco-decrypt \fI .SH "DESCRIPTION" This command accompanies \fBvpnc\fR. It decrypts the obfuscated pre-shared key from *.pcf\-configuration files, which must be specified on the command line. The result will be printed to STDOUT. .SH "AUTHOR" cisco-decrypt was originally written by Maurice Massar. This man\-page was written by Jörg Mayer, based on the pcf2vpnc manpage written by Wolfram Sang (ninja(at)the\-dreams.de). Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 2 any later version published by the Free Software Foundation. .PP On Debian systems, the complete text of the GNU General Public License can be found in /usr/share/common\-licenses/GPL. .SH "SEE ALSO" .BR vpnc(8) .BR pcf2vpnc(1) libreswan-3.32/contrib/cisco-decrypt/cisco-decrypt.c000066400000000000000000000104631365625662500225770ustar00rootroot00000000000000 /* IPsec VPN client compatible with Cisco equipment. Copyright (C) 2004-2005 Maurice Massar This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA $Id: config.c 242 2007-09-09 07:55:21Z Joerg Mayer $ */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include static int hex2bin_c(unsigned int c) { if ((c >= '0') && (c <= '9')) return c - '0'; if ((c >= 'A') && (c <= 'F')) return c - 'A' + 10; if ((c >= 'a') && (c <= 'f')) return c - 'a' + 10; return -1; } int hex2bin(const char *str, char **bin, int *len) { char *p; int i, l; if (!bin) return EINVAL; for (i = 0; str[i] != '\0'; i++) if (hex2bin_c(str[i]) == -1) return EINVAL; l = i; if ((l & 1) != 0) return EINVAL; l /= 2; p = malloc(l); if (p == NULL) return ENOMEM; for (i = 0; i < l; i++) p[i] = hex2bin_c(str[i * 2]) << 4 | hex2bin_c(str[i * 2 + 1]); *bin = p; if (len) *len = l; return 0; } int deobfuscate(char *ct, int len, const char **resp, char *reslenp) { const char *h1 = ct; const char *h4 = ct + 20; const char *enc = ct + 40; char ht[20], h2[20], h3[20], key[24]; const char *iv = h1; char *res; gcry_cipher_hd_t ctx; int reslen; if (len < 48) return -1; len -= 40; memcpy(ht, h1, 20); ht[19]++; gcry_md_hash_buffer(GCRY_MD_SHA1, h2, ht, 20); ht[19] += 2; gcry_md_hash_buffer(GCRY_MD_SHA1, h3, ht, 20); memcpy(key, h2, 20); memcpy(key + 20, h3, 4); /* who cares about parity anyway? */ gcry_md_hash_buffer(GCRY_MD_SHA1, ht, enc, len); if (!memeq(h4, ht, 20)) return -1; res = malloc(len); if (res == NULL) return -1; gcry_cipher_open(&ctx, GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC, 0); gcry_cipher_setkey(ctx, key, 24); gcry_cipher_setiv(ctx, iv, 8); gcry_cipher_decrypt(ctx, (unsigned char *)res, len, (unsigned char *)enc, len); gcry_cipher_close(ctx); reslen = len - res[len - 1]; res[reslen] = '\0'; if (resp) *resp = res; if (reslenp) *reslenp = reslen; return 0; } /* Decoder for password encoding of Cisco VPN client. Copyright (C) 2005 Maurice Massar Thanks to HAL-9000@evilscientists.de for decoding and posting the algorithm! This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include int main(int argc, char *argv[]) { int i, len, ret = 0; char *bin, *pw = NULL; gcry_check_version(NULL); if (argc == 1 || *argv[1] == '-') { fprintf(stderr, "\nUsage: %s DEADBEEF...012345678 424242...7261\n" " Print decoded result to stdout\n\n", argv[0]); exit(1); } /* Hack for use in pcf2vpnc */ if (*argv[1] == 'q') exit(1); for (i = 1; i < argc; i++) { ret = hex2bin(argv[i], &bin, &len); if (ret != 0) { perror("decoding input"); continue; } ret = deobfuscate(bin, len, (const char **)&pw, NULL); free(bin); if (ret != 0) { perror("decrypting input"); continue; } printf("%s\n", pw); free(pw); } exit(ret != 0); } libreswan-3.32/contrib/cisco-pcf/000077500000000000000000000000001365625662500167555ustar00rootroot00000000000000libreswan-3.32/contrib/cisco-pcf/README000066400000000000000000000006761365625662500176460ustar00rootroot00000000000000This little tool will convert a Cisco PCF file to an Libreswan style ipsec.conf connection. If your PCF file contains an "encrypted" (obfuscated) password, then you can find the plaintext version by running the Linux Cisco VPN client within strace. See http://femto.cs.uiuc.edu/~sbond/vpnc/ for more information. ExecSum: "ltrace -i ./vpnclient connect ... 2>&1 | grep -F 805ac57" to decode the passwords. (client: vpnclient-linux-4.0.3.B-k9). libreswan-3.32/contrib/cisco-pcf/pcf2os.pl000077500000000000000000000020501365625662500205060ustar00rootroot00000000000000#!/usr/bin/perl # # (C) 2004 Ken Bantoft # # This script converts most Cisco VPN client .pcf files to Libreswan's # ipsec.conf and ipsec.secrets format # die "Usage: ./pcf2os.pl cisco-config.pcf\n\n" if ! $ARGV[0]; open(PCF,$ARGV[0]); while() { chop; # print "[$_]"; if (m/^description/i) { s/.*=//; s/\ /\_/g; $desc=$_; } if (m/^host/i) { s/.*=//; $right=$_; } if (m/^groupname/i) { s/.*=//; $groupname=$_; } if (m/^grouppwd/i) { s/.*=//; $grouppassword=$_; } } close(PCF); print "ipsec.conf\n\n"; print "conn $desc\n"; print " ike=aes-sha1-modp1536\n"; print " aggressive=yes\n"; print " authby=secret\n"; print " left=%defaultroute\n"; print " leftid=\@$groupname\n"; print " leftxauthclient=yes\n"; print " leftmodecfgclient=yes\n"; print " right=$right\n"; print " rightxauthserver=yes\n"; print " rightmodecfgserver=yes\n"; print " pfs=no\n"; print " auto=add\n"; print "\n\n"; print "ipsec.secrets:\n\n"; print "\@$groupname $right : PSK \"$grouppassword\"\n"; libreswan-3.32/contrib/cisco-pcf/sample.pcf000066400000000000000000000010461365625662500207310ustar00rootroot00000000000000[main] Description=Example Cisco Config Profile Host=127.0.0.1 AuthType=1 GroupName=remote_users GroupPwd=password enc_GroupPwd= EnableISPConnect=0 ISPConnectType=0 ISPConnect= ISPCommand= Username=Remote_User UserPassword=user_password enc_UserPassword= SaveUserPassword=0 EnableBackup=0 BackupServer= CertStore=0 CertName= CertPath= CertSubjectName= CertSerialHash=00000000000000000000000000000000 DHGroup=2 ForceKeepAlives=1 NTDomain= EnableMSLogon=1 MSLogonType=0 EnableNat=1 TunnelingMode=0 TcpTunnelingPort=10000 SendCertChain=0 PeerTimeout=90 libreswan-3.32/contrib/ipsec-dyndns/000077500000000000000000000000001365625662500175075ustar00rootroot00000000000000libreswan-3.32/contrib/ipsec-dyndns/README000066400000000000000000000004011365625662500203620ustar00rootroot00000000000000 This is an example script that can be called via _updown to allows a new cloud/instance/host to send its raw RSA key to a DNS server. This IPSECKEY record can then be used for Opportunistic IPsec The authentication for the DNS update happens using TSIG libreswan-3.32/contrib/ipsec-dyndns/dyn.nohats.ca.key000066400000000000000000000001321365625662500226640ustar00rootroot00000000000000key "dyn.nohats.ca" { algorithm hmac-sha256; secret "NotTheRealSecretKeyObviously"; }; libreswan-3.32/contrib/ipsec-dyndns/ipseckey-update000077500000000000000000000041301365625662500225270ustar00rootroot00000000000000#!/bin/bash -e # Copyright (C) 2017 Paul Wouters # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # TSIG keys can be generated using bind's ddns-confgen command # #KEY=/etc/bind/keys/yourddns.key KEY="$(dirname $0)/dyn.nohats.ca.key" echo "Using keyfile: $KEY" # The zone in which the update happens #ZONE=yourdomain ZONE=dyn.nohats.ca # TTL to use for new DNS entries TTL=300 # Name of Dyn DNS update utility (eg nsupdate, kupdate, etc) DNSUPDATER=nsupdate # The name/IP of the server to send the Dynamic DNS update to #DNSSERVER=ns0.yourdomain.com # Demo server that accepts DYN DNS updates for the zone dyn.nohats.ca DNSSERVER=hiddenmaster.nohats.ca # Your IP address to update the A and/or PTR records for # 8.8.8.8 is a random IP to get the default route MYIP=$(ip route get 8.8.8.8 | head -1 | awk '{print $7}') # Your hostname, default is to use hostname.ZONE MYNAME="$(hostname -s).$ZONE" # If you don't have a raw RSA key, generate one using: # ipsec newhostkey --output /etc/ipsec.d/hostkey.secrets # # Get our raw RSA key and generate the IPSECKEY syntax CKAID="$(ipsec showhostkey --list | head -1 | sed 's/^.*://')" IPSECKEY="$(ipsec showhostkey --ipseckey --ckaid $CKAID)" #echo $MYNAME #echo $IPSECKEY KEYDATA=$(echo $IPSECKEY | sed "s/^.*IPSECKEY//") echo $KEYDATA echo "Updating $MYNAME A record to $MYIP and sending IPSECKEY using server $DNSSERVER" echo "->update add IPSECKEY $IPSECKEY" cat < Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. libreswan-3.32/contrib/labeled-ipsec/README000066400000000000000000000003531365625662500204610ustar00rootroot00000000000000 getpeercon_server.c written by Paul Moore, licensed as GPLv2 getpeercon_server displays the SElinux networking context (netlabel) of an incoming connection. This is used for testing labeled-ipsec. See testing/pluto/labeled-ipsec-* libreswan-3.32/contrib/labeled-ipsec/getpeercon_server.c000066400000000000000000000127211365625662500234700ustar00rootroot00000000000000/* * getpeercon_server: simple INET/INET6/UNIX socket getpeercon(3) test server * * compile: gcc -Wall -o getpeercon_server -lselinux getpeercon_server.c * * Copyright Paul Moore * * Paul Wouters added simplistic quit option. If * the server receives the text "quit" it will quit. */ /* * (c) Copyright Hewlett-Packard Development Company, L.P., 2008, 2010 * (c) Copyright Red Hat, 2012 * * This program is free software: you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include #define UNIX_PATH_MAX 108 #define LISTEN_QUEUE 1 #define RECV_BUF_LEN 1024 /** * main */ int main(int argc, char *argv[]) { int rc; short srv_sock_port; int srv_sock; const int true_const = 1; char *srv_sock_path = NULL; if (argc != 2) { fprintf(stderr, "usage: %s \n", argv[0]); return 1; } srv_sock_port = atoi(argv[1]); if (srv_sock_port == 0) srv_sock_path = argv[1]; { security_context_t ctx; int rc = getcon(&ctx); fprintf(stderr, "-> running as %s\n", rc < 0 ? "NO_CONTEXT" : ctx); if (rc >= 0) freecon(ctx); } fprintf(stderr, "-> creating socket ... "); if (srv_sock_path == NULL) srv_sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); else srv_sock = socket(AF_UNIX, SOCK_STREAM, 0); if (srv_sock < 0) { fprintf(stderr, "socket(2) error: %s\n", strerror(errno)); return 1; } rc = setsockopt(srv_sock, SOL_SOCKET, SO_REUSEADDR, &true_const, sizeof(true_const)); if (rc < 0) { fprintf(stderr, "setsockopt(2) error: %s\n", strerror(errno)); return 1; } fprintf(stderr, "ok\n"); if (srv_sock_path == NULL) { struct sockaddr_in6 srv_sock_addr; fprintf(stderr, "-> listening on TCP port %d ... ", srv_sock_port); memset(&srv_sock_addr, 0, sizeof(srv_sock_addr)); srv_sock_addr.sin6_family = AF_INET6; #ifdef NEED_SIN_LEN srv_sock_addr.sin6_len = sizeof(struct sockaddr_in6); #endif memcpy(&srv_sock_addr.sin6_addr, &in6addr_any, sizeof(in6addr_any)); srv_sock_addr.sin6_port = htons(srv_sock_port); rc = bind(srv_sock, (struct sockaddr *)&srv_sock_addr, sizeof(srv_sock_addr)); } else { struct sockaddr_un srv_sock_addr; fprintf(stderr, "-> listening on UNIX socket %s ... ", srv_sock_path); srv_sock_addr.sun_family = AF_UNIX; #ifdef NEED_SIN_LEN #error how do we set srv_sock_addr.sun_len? #endif /* make .sun_path both NUL-padded and NUL-terminated */ strncpy(srv_sock_addr.sun_path, srv_sock_path, UNIX_PATH_MAX-1); srv_sock_addr.sun_path[UNIX_PATH_MAX - 1] = '\0'; rc = bind(srv_sock, (struct sockaddr *)&srv_sock_addr, sizeof(srv_sock_addr)); } if (rc < 0) { fprintf(stderr, "bind(2) error: %s\n", strerror(errno)); return 1; } rc = listen(srv_sock, LISTEN_QUEUE); if (rc < 0) { fprintf(stderr, "listen(2) error: %s\n", strerror(errno)); return 1; } else fprintf(stderr, "ok\n"); fprintf(stderr, "-> waiting ... "); fflush(stdout); /* loop forever */ for (;;) { int cli_sock; struct sockaddr_storage cli_sock_saddr; struct sockaddr *const cli_sock_addr = (struct sockaddr *)&cli_sock_saddr; struct sockaddr_in6 *const cli_sock_6addr = (struct sockaddr_in6 *)&cli_sock_saddr; socklen_t cli_sock_addr_len; char cli_sock_addr_str[INET6_ADDRSTRLEN + 1]; security_context_t ctx; char *ctx_str; //fflush(stdout); memset(&cli_sock_saddr, 0, sizeof(cli_sock_saddr)); cli_sock_addr_len = sizeof(cli_sock_saddr); cli_sock = accept(srv_sock, cli_sock_addr, &cli_sock_addr_len); if (cli_sock < 0) { fprintf(stderr, "accept(2) error: %s\n", strerror(errno)); continue; } rc = getpeercon(cli_sock, &ctx); ctx_str = rc < 0 ? "NO_CONTEXT" : ctx; switch (cli_sock_saddr.ss_family) { case AF_INET6: if (IN6_IS_ADDR_V4MAPPED(&cli_sock_6addr->sin6_addr)) { inet_ntop(AF_INET, &cli_sock_6addr->sin6_addr.s6_addr32[3], cli_sock_addr_str, sizeof(cli_sock_addr_str)); } else { inet_ntop(cli_sock_6addr->sin6_family, &cli_sock_6addr->sin6_addr, cli_sock_addr_str, sizeof(cli_sock_addr_str)); } fprintf(stderr, "<- connect(%s,%s)\n", cli_sock_addr_str, ctx_str); break; case AF_UNIX: fprintf(stderr, "connect(UNIX,%s)\n", ctx_str); break; default: fprintf(stderr, "connect(%d,%s)\n", cli_sock_saddr.ss_family, ctx_str); } if (rc >= 0) freecon(ctx); for (;;) { char buffer[RECV_BUF_LEN + 1]; rc = recv(cli_sock, buffer, sizeof(buffer) - 1, 0); if (rc < 0) { fprintf(stderr, "recv(2) error: %s\n", strerror(errno)); break; } else if (rc == 0) { break; } else { buffer[rc] = '\0'; /* ??? should this format include a \n? */ printf(" %s", buffer); if (strcmp(buffer, "quit") == 0) break; } } close(cli_sock); fprintf(stderr, "-> connection closed\n"); } return 0; } libreswan-3.32/contrib/ldsaref/000077500000000000000000000000001365625662500165275ustar00rootroot00000000000000libreswan-3.32/contrib/ldsaref/Makefile000066400000000000000000000003751365625662500201740ustar00rootroot00000000000000LIBRESWANSRCDIR=../.. -include ${LIBRESWANSRCDIR}/Makefile.inc CFLAGS += -I${LIBRESWANSRCDIR}/include SOURCE=saref.c TARGET=libsaref.so ${TARGET}: ${SOURCE} $(CC) ${CFLAGS} -fPIC -o $@ -shared -ldl ${SOURCE} .PHONY: clean clean: rm -f *~ ${TARGET} libreswan-3.32/contrib/ldsaref/README000066400000000000000000000005451365625662500174130ustar00rootroot00000000000000This tool is used for testing the setsockopt IP_IPSEC_BINDREF option which allows a socket to be "bound" to a SAref. Each packet sent on that socket, as long as it's routed through mast0, will use the SA associated with the SAref. Example use case: saref 123 nc 192.168.0.1 80 given that 123 is a valid refhim value seen in ipsec auto --status. libreswan-3.32/contrib/ldsaref/saref000077500000000000000000000007461365625662500175640ustar00rootroot00000000000000#!/bin/sh set -e do_help() { cat < END exit 0 } [ -z "$1" ] && do_help case "$1" in -h|--help) do_help ;; esac export IPSEC_SAREF="$1" shift if [ "$IPSEC_SAREF" -lt 0 ] || [ "$IPSEC_SAREF" -gt 65536 ] ; then echo >&2 "Error: invalid SAref value of $IPSEC_SAREF" exit 1 fi dir=$(dirname $0) export LD_PRELOAD="$dir/libsaref.so $LD_PRELOAD" exec ${@} libreswan-3.32/contrib/ldsaref/saref.c000066400000000000000000000017031365625662500177740ustar00rootroot00000000000000#define _GNU_SOURCE #include #include #include #include #include #include #include #include #include typedef int (*socket_fn)(int, int, int); static socket_fn real_socket = NULL; static int saref = 0; #define UNASSIGNED_SAREF 0 #define INVALID_SAREF (-1) int socket(int domain, int type, int protocol) { int sk, rc; if (real_socket == NULL) real_socket = (socket_fn)dlsym(RTLD_NEXT, "socket"); sk = real_socket(domain, type, protocol); if (saref == UNASSIGNED_SAREF) { const char *str; saref = INVALID_SAREF; str = getenv("IPSEC_SAREF"); if (str != NULL) { char tmp = 0; rc = sscanf(str, "%u%c", &saref, &tmp); if (rc != 1) saref = INVALID_SAREF; } } if (saref != UNASSIGNED_SAREF && saref != INVALID_SAREF) (void) setsockopt(sk, IPPROTO_IP, IP_IPSEC_BINDREF, &saref, sizeof(saref)); return sk; } libreswan-3.32/contrib/lucent/000077500000000000000000000000001365625662500164015ustar00rootroot00000000000000libreswan-3.32/contrib/lucent/README000066400000000000000000000116411365625662500172640ustar00rootroot00000000000000 helper program to interop with non-rfc IPsec implementation of Lucent. From Rolando: Lucent's way to work around NATing is to change this: | IP | whatever L4 proto | Payload | where IP has the (IP source; IP dest) within it into this: | IP | UDP:XXX | IP | whatever L4 proto | Payload | where IP have the same (IP source; IP dest) within them and XXX is the configurable UDP port (default=501) In a nutshell, they "tunnelize" all the traffic to/from the client and the gateway into a IP/UDP:XXX header May be there are better ways to do it but using iptables QUEUE is the one we used to encapsulate/decapsulate. I thougth about adding it to LSW code as well as some code to make it manipulate iptables QUEUE stuff but got lost on it. :-( ---------- Forwarded message ---------- Date: Sun, 5 Apr 2009 10:36:54 -0700 (PDT) From: Rolando Zappacosta Cc: users@libreswan.org To: Paul Wouters Subject: Re: [Libreswan Users] Connection against a Lucent FW success!!!! but may be there's still room for improvement Hi all, I could finally manage to get LSW to work against a Lucen VPN Gateway even through NAT. So, in case someone else needs such connection, compile below code and then run this: modprobe ip_queue UDP501encap & iptables -A OUTPUT -d IPofLucentGW -j QUEUE iptables -A INPUT -s IPofLucentGW -j QUEUE before launching LSW as usual. > I discussed this subject here: > > https://lists.libreswan.org/pipermail/users/2008-February/014030.html > based on >> what I could capture under Windows, the relevant part > of it is: >> "I'm trying to connect OpenSwan to a Lucent > VPN Gateway, which according to >> its ASCII interpretation of its Vendor ID payload is: >> > 4C5647392E312E3235353A425249434B3A392E312E323535="LVG9.1.255:BRICK:9.1.255". > I >> can connect to it by means of the Lucent VPN Client > V7.1.2 on a Windows XP >> computer (Vendor ID= > 4C5643372E312E323A5850="LVC7.1.2:XP")." > > Thanks. Normally vendorids are md5sum's of some text, > though in this case > that does not seem to be the case. I added them as-is to > vendor.c for now. > >> Seems one can know the running version of the client > and server just looking >> on the vendor id part of an ASCII capture dump. >> Interesting thing is, as explained to you privatelly, > the way the PSK gets >> handled here. Under the LVC (windows) I had to > configure a PSK like: >> where the real PSK is 9 ASCII > characters long. However, I >> could find that in order to have LSW establishing > phase 1 successfully I had to >> add the string "01234567890" as a trailer, > i.e. my ipsec.secrets looks like: >> !@#$% : PSK > "01234567890" >> >> what gives a PSK of length 20. Not sure on how they > handle it but my guess is >> they just take the PSK the user configures, add the > string >> "01234567890123456789" and take the first 20 > bytes of it. Easy way to hook you >> on their client while still keeping it simply to > develop. >> >> And I'm not sure if the user !@#$% is the one the > GW admin configured on it or >> if it's the way they handle it but whatever else I > configure, the GW just >> don't respond anything back to me. > > Thanks! I put a note of this in docs/lucent-client.txt, and > it will end up > in the new wiki once we have it online. > >>> Looks like a resend, you can ignore it. >> Strangely, I *always* do receive the duplicate packet > warning. Another >> interesting thing is Lucent's VPN client > doesn't exchange any CFG at all... >> I'm wondering now if I need it indeed. The server > sends it to me but seems >> like LSW only configures the local IP address based on > it. I supossed it was >> going to be able to configure something else, such as > DNS or things like that. > > Libreswan does support DNS/WINS via XAUTH/ModeConfig. Though > as a client, we > might be ignoring it, since we have no structured way of > modifying resolv.conf > in any modern way (eg dbus/networkmanager). I believe we > might only pass it > as env variables to the updown script. > >> The LVC do more things with no CFG at all, configures > the DNS and WINS servers >> for instance, something I'll need to do manually > via a script (or can it be >> made automatically somehow by LSW?) > > You can copy the stock _updown script and add resolv.conf > rewriting to it, > and configure the new script using leftupdown= > >>>> and this one from pluto's debug: >>>> 3) "Intranet" #1: XAUTH: > Unsupported attribute: INTERNAL_ADDRESS_EXPIRY >>> You can also ignore this. Libreswan does not > support INTERNAL_ADDRESS_EXPIRY, >>> so it won't drop the IP address or ask for a new > one. >> Same for "ignoring informational payload, type > IPSEC_RESPONDER_LIFETIME" >> above? > > Yes. the remote is telling us how long they will keep the > SA around. Libreswan > does not really care what the remote does. If the remote > wants to rekey, it > will and can do it anytime. We do enforce our own SA life > similarly. > > Paul libreswan-3.32/contrib/lucent/UDP501encap.c000066400000000000000000000176531365625662500204460ustar00rootroot00000000000000 before launching LSW as usual. RJZ - LNX UDP501 # cat UDP501encap.c /* * This code is GPL. * To compile: gcc UDP501encap.c -o UDP501encap -lipq * * Use as follows: * * modprobe ip_queue * UDP501encap & * iptables -A OUTPUT -d IPofLucentGW -j QUEUE * iptables -A INPUT -s IPofLucentGW -j QUEUE */ #include #include #include #include #include #include #include #define BUFSIZE 2048 #define BOOL int #define DstPort 501 #define DstPortHi (DstPort >> 8) #define DstPortLo (DstPort & 0x00FF) #define SrcPort 501 #define SrcPortHi (SrcPort >> 8) #define SrcPortLo (SrcPort & 0x00FF) typedef unsigned short u16; typedef unsigned long u32; u16 ip_sum_calc(u16 len_ip_header, unsigned char buff[]) { u16 word16; u32 sum = 0; u16 i; // make 16 bit words out of every two adjacent 8 bit words in the packet // and add them up for (i = 0; i < len_ip_header; i = i + 2) { word16 = ((buff[i] << 8) & 0xFF00) + (buff[i + 1] & 0xFF); sum = sum + (u32) word16; } // take only 16 bits out of the 32 bit sum and add up the carries while (sum >> 16) sum = (sum & 0xFFFF) + (sum >> 16); // one's complement the result sum = ~sum; return (u16) sum; } static void die(struct ipq_handle *h) { ipq_perror("passer"); ipq_destroy_handle(h); exit(1); } int main(int argc, char **argv) { int status; unsigned char buf[BUFSIZE]; struct ipq_handle *h; unsigned char *newPayload; u16 srcaddr[4], dstaddr[4]; u16 newCS; int ip_header_len; u16 udp_len; int i; h = ipq_create_handle(0, PF_INET); if (!h) die(h); status = ipq_set_mode(h, IPQ_COPY_PACKET, BUFSIZE); if (status < 0) die(h); do { status = ipq_read(h, buf, BUFSIZE, 0); if (status < 0) die(h); switch (ipq_message_type(buf)) { case NLMSG_ERROR: fprintf(stderr, "Received error message %d\n", ipq_get_msgerr(buf)); break; case IPQM_PACKET: { ipq_packet_msg_t *m = ipq_get_packet(buf); //Enable this to debug the incoming/outgoing packets: //printf("0x%02x %s -> %s (%d)\n", m->payload[9], m->indev_name, m->outdev_name, m->data_len); if (m->outdev_name[0] == 0x0) { // INPUT ip_header_len = (m->payload[0] & 0xF) * 4; u16 new_ip_len = m->data_len - ip_header_len - 8; newPayload = malloc(new_ip_len); memcpy(newPayload, m->payload + ip_header_len + 8, new_ip_len); status = ipq_set_verdict(h, m->packet_id, NF_ACCEPT, new_ip_len, newPayload); free(newPayload); } else { u16 ip_len = (m->payload[2] << 8 & 0xff00) + (m->payload[3] & 0xff); ip_header_len = (m->payload[0] & 0xF) * 4; u16 new_ip_len = ip_len + ip_header_len + 8; newPayload = malloc(new_ip_len); // Copy prev packet char *dst = newPayload; char *org = m->payload; // Copy IP header memcpy(dst, org, ip_header_len); dst += ip_header_len; // Update IP length field newPayload[2] = new_ip_len >> 8; newPayload[3] = new_ip_len & 0x00ff; // Set IP protocol field to UDP newPayload[9] = 0x11; // Calculate and update IP cksum newPayload[10] = newPayload[11] = 0x00; newCS = ip_sum_calc(ip_header_len, newPayload); newPayload[10] = newCS >> 8; newPayload[11] = newCS & 0x00FF; // Create UDP header dst[0] = SrcPortHi; // src port dst[1] = SrcPortLo; // src port dst[2] = DstPortHi; // dst port dst[3] = DstPortLo; // dst port u16 new_udp_len = new_ip_len - ip_header_len; dst[4] = new_udp_len >> 8; // total len dst[5] = new_udp_len & 0x00ff; // total len dst[6] = 0x00; // Cksum dst[7] = 0x00; // Cksum dst += 8; // Clone the rest of the packet memcpy(dst, org, ip_len); status = ipq_set_verdict(h, m->packet_id, NF_ACCEPT, new_ip_len, newPayload); free(newPayload); } if (status < 0) die(h); break; } default: fprintf(stderr, "Unknown message type!\n"); break; } } while (1); ipq_destroy_handle(h); return 0; } /* >> I discussed this subject here: >> > https://lists.openswan.org/pipermail/users/2008-February/014030.html > based on >> what I could capture under Windows, the relevant part > of it is: >> "I'm trying to connect OpenSwan to a Lucent > VPN Gateway, which according to >> its ASCII interpretation of its Vendor ID payload is: >> > 4C5647392E312E3235353A425249434B3A392E312E323535="LVG9.1.255:BRICK:9.1.255". > I >> can connect to it by means of the Lucent VPN Client > V7.1.2 on a Windows XP >> computer (Vendor ID= > 4C5643372E312E323A5850="LVC7.1.2:XP")." > > Thanks. Normally vendorids are md5sum's of some text, > though in this case > that does not seem to be the case. I added them as-is to > vendor.c for now. > >> Seems one can know the running version of the client > and server just looking >> on the vendor id part of an ASCII capture dump. >> Interesting thing is, as explained to you privatelly, > the way the PSK gets >> handled here. Under the LVC (windows) I had to > configure a PSK like: >> where the real PSK is 9 ASCII > characters long. However, I >> could find that in order to have LSW establishing > phase 1 successfully I had to >> add the string "01234567890" as a trailer, > i.e. my ipsec.secrets looks like: >> !@#$% : PSK > "01234567890" >> >> what gives a PSK of length 20. Not sure on how they > handle it but my guess is >> they just take the PSK the user configures, add the > string >> "01234567890123456789" and take the first 20 > bytes of it. Easy way to hook you >> on their client while still keeping it simply to > develop. >> >> And I'm not sure if the user !@#$% is the one the > GW admin configured on it or >> if it's the way they handle it but whatever else I > configure, the GW just >> don't respond anything back to me. > > Thanks! I put a note of this in docs/lucent-client.txt, and > it will end up > in the new wiki once we have it online. > >>> Looks like a resend, you can ignore it. >> Strangely, I *always* do receive the duplicate packet > warning. Another >> interesting thing is Lucent's VPN client > doesn't exchange any CFG at all... >> I'm wondering now if I need it indeed. The server > sends it to me but seems >> like LSW only configures the local IP address based on > it. I supossed it was >> going to be able to configure something else, such as > DNS or things like that. > > Libreswan does support DNS/WINS via XAUTH/ModeConfig. Though > as a client, we > might be ignoring it, since we have no structured way of > modifying resolv.conf > in any modern way (eg dbus/networkmanager). I believe we > might only pass it > as env variables to the updown script. > >> The LVC do more things with no CFG at all, configures > the DNS and WINS servers >> for instance, something I'll need to do manually > via a script (or can it be >> made automatically somehow by LSW?) > > You can copy the stock _updown script and add resolv.conf > rewriting to it, > and configure the new script using leftupdown= > >>>> and this one from pluto's debug: >>>> 3) "Intranet" #1: XAUTH: > Unsupported attribute: INTERNAL_ADDRESS_EXPIRY >>> You can also ignore this. Libreswan does not > support INTERNAL_ADDRESS_EXPIRY, >>> so it won't drop the IP address or ask for a new > one. >> Same for "ignoring informational payload, type > IPSEC_RESPONDER_LIFETIME" >> above? > > Yes. the remote is telling us how long they will keep the > SA around. Libreswan > does not really care what the remote does. If the remote > wants to rekey, it > will and can do it anytime. We do enforce our own SA life > similarly. > > Paul */ libreswan-3.32/contrib/munin/000077500000000000000000000000001365625662500162355ustar00rootroot00000000000000libreswan-3.32/contrib/munin/README000066400000000000000000000001571365625662500171200ustar00rootroot00000000000000 this is a libreswan plugin for munin. See: http://munin-monitoring.org/ It requires libreswan 3.20 or later libreswan-3.32/contrib/munin/libreswan000077500000000000000000000172761365625662500201660ustar00rootroot00000000000000#!/usr/bin/python -tt """Munin plugin to monitor libreswan ipsec servers Copyright 2017, Kim B. Heino, b@bbbs.net, Foobar Oy Copyright 2017, Paul Wouters License GPLv2+ This plugin requires Munin config /etc/munin/plugin-conf.d/libreswan: [libreswan] user root #%# capabilities=autoconf #%# family=auto """ from __future__ import print_function, unicode_literals import subprocess import sys from collections import defaultdict def tree(): """Tree of defaultdicts""" return defaultdict(tree) def get_stats(): """Get statistics""" # Get status output try: pipe = subprocess.Popen( ['/usr/sbin/ipsec', 'whack', '--globalstatus'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) output = pipe.communicate()[0] except OSError: return {} # Parse output values = tree() for line in output.splitlines(): if '=' not in line: continue prefix, val = line.split('=') prefix = prefix.split('.') pos = values for key in prefix[:-1]: pos = pos[key] pos[prefix[-1]] = val return values def derive_gauge(entry, value, config, graph_type): """Print config or value""" if config: print('{}.label {}'.format(entry, entry)) print('{}.type {}'.format(entry, graph_type)) print('{}.min 0'.format(entry)) else: print('{}.value {}'.format(entry, value)) def derive(entry, value, config): """Print config or value""" derive_gauge(entry, value, config, 'DERIVE') def gauge(entry, value, config): """Print config or value""" derive_gauge(entry, value, config, 'GAUGE') def print_config(name, title, vlabel, config): """Print config header""" print('multigraph {}'.format(name)) if config: print('graph_title {}'.format(title)) print('graph_vlabel {}'.format(vlabel)) print('graph_category vpn') print('graph_args --base 1000 --lower-limit 0') def updown(name, title, values, config): """Print up/down header""" print('multigraph {}'.format(name)) if config: print('graph_title {}'.format(title)) print('graph_category vpn') print('graph_order down up') print('graph_args --base 1000') print('graph_vlabel bytes in (-) / out (+) per ${graph_period}') print('down.label received') print('down.type DERIVE') print('down.graph no') print('down.cdef down,8,*') print('down.min 0') print('up.label bps') print('up.type DERIVE') print('up.negative down') print('up.cdef up,8,*') print('up.min 0') for entry, value in values.items(): orig = 'down' if entry == 'in' else 'up' if config: print('{}.label {}'.format(orig, entry)) print('{}.type DERIVE'.format(orig)) print('{}.min 0'.format(orig)) else: print('{}.value {}'.format(orig, value)) def derive_all(name, title, vlabel, values, config): """Print config of value for all items""" print_config(name, title, vlabel, config) for entry, value in values.items(): derive(entry, value, config) def gauge_all(name, title, vlabel, values, config): """Print config of value for all items""" print_config(name, title, vlabel, config) for entry, value in values.items(): gauge(entry, value, config) def print_values(values, config): """Print values or config""" if not values: return derive_all( 'vpn_ipsec_types', 'IPsec SA Types', 'total', values['total']['ipsec']['type'], config) derive_all( 'vpn_ipsec_encr', 'IPsec SA ENCR', 'total', values['total']['ipsec']['encr'], config) derive_all( 'vpn_ipsec_integ', 'IPsec SA INTEG', 'total', values['total']['ipsec']['integ'], config) print_config('vpn_current', 'Current States', 'current', config) for entry, value in values['current']['states']. items(): if entry not in ('enumerate', 'iketype'): gauge(entry, value, config) gauge_all( 'vpn_iketype', 'Current IKE types', 'iketypes', values['current']['states']['iketype'], config) gauge_all( 'vpn_state_kind', 'Current pluto states', 'pluto_states', values['current']['states']['enumerate'], config) derive_all( 'vpn_state_transition_func', 'Pluto STFs', 'total', values['total']['pluto']['stf'], config) updown( 'vpn_traffic_ipsec', 'Total IPsec Traffic', values['total']['ipsec']['traffic'], config) updown( 'vpn_traffic_ike', 'Total IKE Traffic', values['total']['ike']['traffic'], config) derive_all( 'vpn_dpd', 'Total DPD Traffic', 'dpd_traffic', values['total']['ike']['dpd'], config) print_config('vpn_ike', 'Total IKE Sessions', 'ike_traffic', config) for entry in ('ikev2_ok', 'ikev2_fail', 'ikev1_ok', 'ikev1_fail'): if config: print('{}.label {}'.format(entry, entry)) print('{}.type DERIVE'.format(entry)) print('{}.min 0'.format(entry)) else: ike = entry[:5] if 'fail' in entry: status = 'failed' else: status = 'established' print('{}.value {}'.format( entry, values['total']['ike'][ike][status])) derive_all( 'vpn_ikev1_sent_notifies', 'IKEv1 sent NOTIFIES', 'total', values['total']['ikev1']['sent']['notifies']['error'], config) derive_all( 'vpn_ikev2_sent_notifies', 'IKEv2 sent NOTIFIES', 'total', values['total']['ikev2']['sent']['notifies']['error'], config) derive_all( 'vpn_ikev1_recv_notifies', 'IKEv1 recv NOTIFIES', 'total', values['total']['ikev1']['recv']['notifies']['error'], config) derive_all( 'vpn_ikev2_recv_notifies', 'IKEv2 recv NOTIFIES', 'total', values['total']['ikev2']['recv']['notifies']['error'], config) # Down from here it is all crypto params derive_all( 'vpn_ikev1_encr', 'IKEv1 ENCR', 'total', values['total']['ikev1']['encr'], config) derive_all( 'vpn_ikev2_encr', 'IKEv2 ENCR', 'total', values['total']['ikev2']['encr'], config) derive_all( 'vpn_ikev1_integ', 'IKEv1 INTEG', 'total', values['total']['ikev1']['integ'], config) derive_all( 'vpn_ikev2_integ', 'IKEv2 INTEG', 'total', values['total']['ikev2']['integ'], config) derive_all( 'vpn_ikev1_group', 'IKEv1 GROUP', 'total', values['total']['ikev1']['group'], config) derive_all( 'vpn_ikev2_group', 'IKEv2 GROUP', 'total', values['total']['ikev2']['group'], config) derive_all( 'vpn_ikev2_recv_badgroup_in', 'IKEv2 recv INVALID GROUP', 'total', values['total']['ikev2']['recv']['invalidke']['using'], config) derive_all( 'vpn_ikev2_recv_badgroup_out', 'IKEv2 recv-sent INVALID GROUP', 'total', values['total']['ikev2']['recv']['invalidke']['suggesting'], config) derive_all( 'vpn_ikev2_sent_badgroup_in', 'IKEv2 sent-recv INVALID GROUP', 'total', values['total']['ikev2']['sent']['invalidke']['using'], config) derive_all( 'vpn_ikev2_sent_badgroup_out', 'IKEv2 sent-sent INVALID GROUP', 'total', values['total']['ikev2']['sent']['invalidke']['suggesting'], config) def main(args): """Main program""" values = get_stats() if len(args) > 1 and args[1] == 'autoconf': print('yes' if values else 'no') elif len(args) > 1 and args[1] == 'config': print_values(values, True) else: print_values(values, False) if __name__ == '__main__': main(sys.argv) libreswan-3.32/contrib/patching/000077500000000000000000000000001365625662500167045ustar00rootroot00000000000000libreswan-3.32/contrib/patching/klips-patch-import000077500000000000000000000153021365625662500223620ustar00rootroot00000000000000#!/bin/bash # # Copyright (C) 2010 Bart Trojanowski # # This script imports patches generated from a linux/klips git tree into # an libreswan git tree. set -e prog=$(basename $0) say() { echo >&2 "$@" } warn() { say "$prog: $@" } die() { warn "$@" exit 1 } do_help() { local err=$1 local out=1 [[ -n "$err" && "$err" -eq 0 ]] || out=2 cat >&$out <] --patch[=] - import from stdin, -p is passed to patch (default is 1) Or import from an existing linux-2.6.git tree with klips applied: $prog -k [ -n ] [ -h ] -k --kernel - path to kernel git tree -n --number - number of patches to import (default is 1) -r --head - git ref/head to start from (default is HEAD) Generic options: -h --help - this help --dry-run - don't apply anything -q --quiet - pass quiet flag to git-am -t --tmp-dir - use this temporary directory END exit $err } # set defaults kernel_mode=false patch_mode=false dryrun_mode=false arg_head= arg_kernel= arg_count= arg_pnum= arg_quiet= arg_tmpdir=/tmp # this will queue a patch if it looks like it would apply queue_patch() { local queue="$1" local patch="$2" # make sure this patch contains only changes to files we care about diffstat -l -p1 "$patch" \ | while read fn ; do local dir=$(dirname "$fn") if ! [[ -d "linux/$dir" ]] ; then fn=$(basename "$fn") warn "Patch modifies $fn in $dir, but linux/$dir is not an libreswan" warn "directory. You could 'mkdir $dir' to skip this warning." exit 1 fi done # convert paths to contain linux/ prefix sed -ie 's,^\(\(---\|+++\) \([a-z]\+/\)\{'"$arg_pnum"'\}\)\(.*\)$,\1linux/\4,' "$patch" # add it to the queue cat "$patch" >> "$queue" # check if the patch applies (including all the ones that came before it git apply --check -p"$arg_pnum" "$queue" || die "patch doesn't apply" } apply_queue() { local queue="$1" $dryrun_mode && return 0 # import the patch git am < "$queue" } is_git_dir() { local dir="$1" [[ -d "$dir" \ && -f "$dir/HEAD" \ && -d "$dir/objects" \ && -d "$dir/refs" ]] } find_kernel_git_dir() { for dir in "$arg_kernel" "$arg_kernel/.git" ; do if is_git_dir "$dir" ; then echo "$dir" return 0 fi done die "cannot find git dir at $arg_kernel" } # imports $arg_count patches from $arg_kernel do_kernel_import() { local workdir="$arg_tmpdir/$prog-$$" local series="$workdir/series" local queue="$workdir/queue" [[ -d $workdir ]] && die "$workdir already exists, remove it" mkdir -p "$workdir" || die "failed to create: $workdir" trap "rm -rf $workdir" EXIT HUP INT QUIT ABRT # find the kernel dir local kernel_git=$(find_kernel_git_dir) # generate those patches git --git-dir "$kernel_git" \ format-patch \ -"$arg_count" \ --suffix=.patch \ --output-directory "$workdir" \ "$arg_head" \ > "$series" \ || die "failed to generate $arg_count patch(es) in from $kernel_git" for patch in $(cat "$series") ; do local name=$(basename "$patch") say "Testing $name..." queue_patch "$queue" "$patch" done say "Looks good, now applying..." apply_queue "$queue" say "DONE" } # import patch read from /dev/stdin do_patch_from_stdin() { local patch="$arg_tmpdir/$prog-$$.patch" local queue="$arg_tmpdir/$prog-$$.queue" trap "rm -f $patch $queue" EXIT HUP INT QUIT ABRT # read in the patch cat > "$patch" # reset the queue cat "$queue" say "Testing patch from stdin..." queue_patch "$queue" "$patch" say "Looks good, now applying..." apply_queue "$queue" say "DONE" } # parse parameters while [[ -n "$1" ]] ; do cmd="$1" shift case "$cmd" in -h|--help) do_help 0 ;; --dry-run) dryrun_mode=true ;; --debug) set -x ;; -r|--head) arg_head="$1" shift || die "--head requires an argument" ;; -k|--kernel) kernel_mode=true arg_kernel="$1" [[ -d "$arg_kernel" ]] || die "no such directory: $arg_kernel" shift ;; -p|--patch) patch_mode=true ;; -p[0-9]*) patch_mode=true arg_pnum="${cmd#-p}" ;; --patch=[0-9]*) patch_mode=true arg_pnum="${cmd#*=}" ;; -n|--number) arg_count="$1" shift || die "--number requires an argument" ;; -[0-9]*) arg_count="${cmd#-}" ;; -q|--quiet) arg_quiet="--quiet" ;; -t|--tmp-dir) arg_tmpdir="$1" [[ -d "$arg_tmpdir" ]] || die "no such directory: $arg_tmpdir" shift ;; *) warn "invalid option: $cmd" do_help 1 ;; esac done ( $kernel_mode || $patch_mode ) || die "need to use --kernel or --patch mode" ( $kernel_mode && $patch_mode ) && die "only use --kernel or --patch mode" for n in diffstat filterdiff ; do $n --help /dev/null 2>&1 || die "cannot find '$n' (part of patchutils package)" done if [[ -z "$arg_pnum" ]] ; then arg_pnum=1 elif [[ "$arg_pnum" -gt 0 ]] ; then die "--patch/-p level must be a number" fi if $kernel_mode; then [[ -z "$arg_count" ]] && arg_count=1 [[ -z "$arg_head" ]] && arg_head=HEAD do_kernel_import ret=$? elif $patch_mode; then do_patch_from_stdin ret=$? else ret=1 fi exit $ret libreswan-3.32/contrib/patching/patch-git-kernel000077500000000000000000000143731365625662500220000ustar00rootroot00000000000000#!/bin/bash # # Copyright (C) 2010 Bart Trojanowski # # This script applies saref, natt, and klips patches to a # linux kernel git tree. set -e prog=$(basename $0) say() { echo >&2 "$@" } warn() { say "$prog: $@" } die() { warn "$@" exit 1 } do_help() { local err=$1 local out=1 [[ -n "$err" && "$err" -eq 0 ]] || out=2 cat >&$out < Options: -s --saref - apply the saref patch(es), create commit(s) -n --natt - apply the natt patch(es), create commit(s) -k --klips - apply the klips patch(es), create commit(s) Generic options: -h --help - this help --dry-run - don't apply anything -q --quiet - pass quiet flag to git-am -t --tmp-dir - use this temporary directory END exit $err } # set defaults do_saref=false do_natt=false do_klips=false dryrun_mode=false cleen_up=true arg_kernel= arg_quiet= arg_tmpdir=/tmp libreswan_rev= kernel_ver= # this will queue a patch if it looks like it would apply queue_patch() { local queue="$1" local pnum="$2" local patch="$3" # add it to the queue cat "$patch" >> "$queue" # check if the patch applies (including all the ones that came before it) ( cd "$arg_kernel" git apply --ignore-space-change --ignore-whitespace --check -p"$pnum" "$queue" || die "patch doesn't apply" ) } # apply the patch in the kernel tree apply_a_patch() { local pnum="$1" local patch="$2" local desc="$3" $dryrun_mode && return 0 # import the patch ( cd "$arg_kernel" git apply --ignore-space-change --ignore-whitespace --index < "$patch" diffstat -l -p"$pnum" < "$patch" | xargs git add git commit -m"$desc" ) } is_git_dir() { local dir="$1" [[ -d "$dir" \ && -f "$dir/HEAD" \ && -d "$dir/objects" \ && -d "$dir/refs" ]] } generate_saref_patch() { local workdir="$1" local series="$2" local count=0 for src in patches/kernel/$kernel_ver/0*.patch ; do count=$(($count + 1)) local patch="$workdir/saref$count.patch" local desc="Applied saref patch #$count from Libreswan $libreswan_rev" local pnum=1 say "Reading ${src##*/}..." say "Generating ${patch##*/}..." cat "$src" > "$patch" echo "$pnum" "$patch" "$desc" >> $series done } generate_natt_patch() { local workdir="$1" local series="$2" local patch="$workdir/natt.patch" local desc="Applied NATT patch from Libreswan $libreswan_rev" local pnum=1 say "Generating ${patch##*/}..." cat "patches/kernel/$kernel_ver/natt.patch" > "$patch" echo "$pnum" "$patch" "$desc" >> $series } generate_klips_patch() { local workdir="$1" local series="$2" local patch="$workdir/klips.patch" local desc="Applied klips patch from Libreswan $libreswan_rev" local pnum=1 say "Generating ${patch##*/}..." make kernelpatch2.6 > "$patch" echo "$pnum" "$patch" "$desc" >> $series } apply_patches() { local workdir="$arg_tmpdir/$prog-$$" local series="$workdir/series" local queue="$workdir/queue" [[ -d $workdir ]] && die "$workdir already exists, remove it" mkdir -p "$workdir" || die "failed to create: $workdir" if $cleen_up ; then trap "rm -rf $workdir" EXIT HUP INT QUIT ABRT else trap "echo 'not cleaning: $workdir'" EXIT HUP INT QUIT ABRT fi $do_saref && generate_saref_patch "$workdir" "$series" $do_natt && generate_natt_patch "$workdir" "$series" $do_klips && generate_klips_patch "$workdir" "$series" while read pnum patch desc ; do local name=$(basename "$patch") say "Testing $name..." queue_patch "$queue" "$pnum" "$patch" done < "$series" while read pnum patch desc ; do local name=$(basename "$patch") say "Applying $name..." apply_a_patch "$pnum" "$patch" "$desc" done < "$series" say "DONE" } # parse parameters while [[ -n "$1" ]] ; do [[ -n "$arg_kernel" ]] && die "garbage at end of line; see $prog --help" cmd="$1" shift case "$cmd" in -h|--help) do_help 0 ;; --dry-run) dryrun_mode=true ;; --debug) set -x ;; --keep) cleen_up=false ;; -q|--quiet) arg_quiet="--quiet" ;; -t|--tmp-dir) arg_tmpdir="$1" [[ -d "$arg_tmpdir" ]] || die "no such directory: $arg_tmpdir" shift ;; -s|--saref) do_saref=true ;; -n|--natt) do_natt=true ;; -k|--klips) do_klips=true ;; -*) warn "invalid option: $cmd" do_help 1 ;; *) arg_kernel="$cmd" ;; esac done ( $do_saref || $do_natt || $do_klips ) || die "need to specify at least one of --saref, --natt, or --klips" is_git_dir ".git" && libreswan_rev=$(git describe) [[ "${libreswan_rev:0:1}" = "v" ]] || die "run this script from the top of the libreswan git tree" echo "Libreswan revision $libreswan_rev" [[ -n "$arg_kernel" ]] || die "missing kernel directory; see $prog --help" is_git_dir "$arg_kernel/.git" && kernel_ver=$(git --git-dir="$arg_kernel/.git" describe | sed -ne's/v\(2\.6\.[0-9]\+\).*/\1/p') [[ "${kernel_ver:0:2}" = "2." ]] || die "$arg_kernel: this dones't look like a kernel git tree" apply_patches exit $ret libreswan-3.32/contrib/python-swan/000077500000000000000000000000001365625662500173765ustar00rootroot00000000000000libreswan-3.32/contrib/python-swan/is_encrypted.py000066400000000000000000000034251365625662500224440ustar00rootroot00000000000000#!/usr/bin/python2 -tt # -*- coding: utf-8 -*- """Is connection encrypted? ./is_encrypted.py --debug --port 443 10.6.6.1 ./is_encrypted.py --debug --source 2001:998:2e:f00::42 2a00:1190:c00a:f00::1 ./is_encrypted.py --debug --source 193.65.3.113 172.27.129.42 /* * Is connection encrypted? -utility. * * Copyright (C) 2018 Kim B. Heino * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ """ from __future__ import print_function from __future__ import unicode_literals import argparse import swan def main(): """Main program""" parser = argparse.ArgumentParser( description='check if traffic would get encrypted by IPsec') parser.add_argument('--debug', action='store_true', help='show debugging') parser.add_argument('--source', help='source address of the packet') parser.add_argument('--port', help='connect to TCP port on destination') parser.add_argument('destination', help='destination IP address to check') args = parser.parse_args() print(swan.is_encrypted( args.destination, args.port, args.source, debug=args.debug)) if __name__ == '__main__': main() libreswan-3.32/contrib/python-swan/swan/000077500000000000000000000000001365625662500203465ustar00rootroot00000000000000libreswan-3.32/contrib/python-swan/swan/__init__.py000066400000000000000000000072061365625662500224640ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Random functions for Libreswan. /* * Is connection encrypted? -utility. * * Copyright (C) 2018 Kim B. Heino * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ """ from __future__ import print_function from __future__ import unicode_literals import socket import subprocess import sys try: import ipaddress except ImportError: sys.exit('Please install https://pypi.python.org/pypi/ipaddress') def run_command(params): """Run command and return it's output""" try: output = subprocess.check_output(params, stderr=subprocess.STDOUT) except subprocess.CalledProcessError: return '' return output.decode('utf-8', 'ignore') def is_encrypted(destination, port=None, source=None, timeout=1.0, debug=False): """Is connection encrypted? Returns True/False or raises ValueError """ # Parse destination, autodetect source if not specified destination = ipaddress.ip_address(unicode(destination)) if not source: output = run_command([ '/sbin/ip', '-oneline', 'route', 'get', unicode(destination)]) try: source = output.split(' src ')[1].split()[0] except IndexError: raise ValueError('failed to detect source IP') source = ipaddress.ip_address(unicode(source)) if debug: print('Checking {} to {} port {}'.format(source, destination, port)) # Connect to port if specified, ignore errors if port: try: sock = socket.create_connection( (unicode(destination), port), timeout, (unicode(source), 0)) sock.close() except socket.error as error: if debug: print('Connection error: {}'.format(error)) # Get "ip xfrm" output output = run_command(['/sbin/ip', '-oneline', 'xfrm', 'policy', 'list']) # Parse output encrypted = False priority = 65536 for line in output.splitlines(): # Parse single line parsed = { 'src': None, 'dst': None, 'dir': None, 'priority': None, 'proto': None, 'reqid': None, } keyword = None for item in line.replace('\\', ' ').split(): if item in parsed and not parsed[item]: keyword = item elif keyword: parsed[keyword] = item keyword = None # Is it our line? if not ( parsed['dir'] == 'out' and parsed['proto'] == 'esp' and priority > int(parsed['priority']) and source in ipaddress.ip_network(parsed['src']) and destination in ipaddress.ip_network(parsed['dst']) ): continue # It is, update priority/encrypted if debug: print(line) priority = int(parsed['priority']) encrypted = parsed['reqid'] not in (None, '0') return encrypted libreswan-3.32/contrib/scripts/000077500000000000000000000000001365625662500165765ustar00rootroot00000000000000libreswan-3.32/contrib/scripts/README000066400000000000000000000006501365625662500174570ustar00rootroot00000000000000This directory contains scripts that mimic certain KLIPS-only commands when using NETKEY. These may fold back into the distribution later on, or get replaced by new code. Output is not guaranteed to be identical to the KLIPS versions. eroute: replacement for KLIPS' "ipsec eroute" look: replacement for KLIPS' "ipsec look" Install: replace the KLIPS script in /usr/local/libexec/ipsec/ with a version from this directory. libreswan-3.32/contrib/scripts/eroute000077500000000000000000000022701365625662500200300ustar00rootroot00000000000000#!/usr/bin/perl # # (c) Xelerance # # I whipped this up in 15 minutes after switching my laptop to 2.6 # so it's ugly, and could use some major improvement. setkey output is # ugly to parse open(SETKEY,"setkey -PD|"); while() { if ( m/any/) { ($dst,$src, $any) = split(" ",$_); $src =~ s/\[any\]//g; $dst =~ s/\[any\]//g; } if ( m/ipsec/ ) { ($dir,$dummy) = split(" ",$_); } if ( m/unique/ ) { ($proto,$type,$tunnel,$dummy) = split("/",$_); ($net1,$net2) = split("-",$tunnel); if($dir eq "out" ) { $remotegw=$net2; $local=$net1; $temp = $src; $src=$dst; $dst=$temp; } if ($dir eq "in") { $remotegw=$net1; $local=$net2; } if ($dir eq "fwd") { $remotegw=$net1; $local=$net2; } } if ( m/spid/ ) { ($spidstr,$seqstr, $pidstr) = split(" ",$_); ($tmp,$spi) = split("\=",$spidstr); if ($spi != "" && $tunnel != "" ) { for ($src) { if (! m/\// ) { $src .= "/32"; } } for ($dst) { if (! m/\// ) { $dst .= "/32"; } } printf("%3s %-18s -> %-18s => tun0x%s@%s\n",$dir,$src,$dst,$spi,$remotegw); # Reset $tunnel = ""; $spi = ""; $dir = ""; } } } close(SETKEY); libreswan-3.32/contrib/scripts/look000077500000000000000000000022221365625662500174660ustar00rootroot00000000000000#!/usr/bin/perl # # (c) Feb 2008 - Matteo Vitturi # # A script to parse ip xfrm output - NETKEY version of "ipsec look" open(IPSXP,"ip -s x p|"); $dir = ''; $remotegw = ''; $spi = ''; while() { if ( m/src (.+) dst (.+) uid/ ) { ($src,$dst) = ($2,$1) }; if ( m/dir (.+) action/ ) { $dir = $1 } if ( m/index (.+) prio/ ) { $spi = $1 } if ( m/tmpl src (.+) dst (.+)/ and $remotegw eq '' ) { ($net1,$net2) = ($1,$2) ; if ( $dir eq "out" ) { $remotegw=$net2; $local=$net1; $temp = $src; $src=$dst; $dst=$temp; } if ($dir eq "in") { $remotegw=$net1; $local=$net2; } if ($dir eq "fwd") { $remotegw=$net1; $local=$net2; } } if ( m/proto/ && $dir ne '') { $src .= "/32" if $src !~ m/\//; $dst .= "/32" if $dst !~ m/\//; printf("%3s %-18s -> %-18s => tun0x%s@%s\n", $dir,$src,$dst,$spi,$remotegw) unless $remotegw eq '0.0.0.0'; $dir = ''; $remotegw = ''; $spi = ''; } } close(IPSXP); libreswan-3.32/contrib/updown-example/000077500000000000000000000000001365625662500200545ustar00rootroot00000000000000libreswan-3.32/contrib/updown-example/example-terminate.py000077500000000000000000000035751365625662500240640ustar00rootroot00000000000000#!/usr/bin/python # # example-terminate.py # # This is a script that can be ADDED to the updown scripts. Normally this would # be added to /usr/libexec/ipsec/_updown.netkey (for protostack=netkey) # This is an example that logs XAUTH users to /tmp/terminate.log when the # tunnel goes down: # # Inside _updown.netkey add a call to this script, like: # # # down-client) # # connection to my client subnet going down # downrule # # If you are doing a custom version, firewall commands go here. # restoreresolvconf # /usr/local/sbin/example-terminate.py $PLUTO_XAUTH_USERNAME # import os, sys, pipes import commands import requests import signal def child(username): # Send a GET request to our logserver to log disconnecting client # this might block if unavailable, so we must be detached from # pluto. url = 'https://logserver.example.com/delete/' payload = {'username': username} r = requests.get(url, data=payload) fp = open("/tmp/terminate.log","a") fp.write("Termination notification sent for %s\n"%username) fp.write("HTTP status code:%s\n"%r.status_code) fp.write(r.text) fp.write("\n") fp.close() os._exit(0) if __name__ == '__main__': if len(sys.argv) < 2: # nothing to log sys.exit(0) username = sys.argv[1] if username != pipes.quote(username): sys.exit("bogus characters in username '%s', ignored termination request"%username) # Redirect standard file descriptors to ensure pluto does not block on us os.close(0) os.close(1) os.close(2) os.close(3) # pluto.log - workaround for bug #202 # Do a double fork to decouple from the parent environment pid = os.fork() if pid > 0: # exit first parent sys.exit(0) os.chdir("/") os.setsid() os.umask(0) # do second fork pid = os.fork() if pid > 0: # exit from second parent sys.exit(0) # we're fully detached now - take as long as needed to do the work child(username) libreswan-3.32/docs/000077500000000000000000000000001365625662500143775ustar00rootroot00000000000000libreswan-3.32/docs/CHANGES.freeswan.pluto000066400000000000000000001171261365625662500203550ustar00rootroot00000000000000Changes to Pluto ================ - [MCR] changes to support co-terminal connections of the near kind. - --dontrekey is now a misnomer: the IPsec SA will be rekeyed if we are the Initiator and there is outbound traffic in the period leading up to the rekeying decision point. This is a heuristic: a mistake doesn't matter much since the connection, once deleted, will be rekeyed on demand. - accept a proposal with compression even if the connection does not have the POLICY_COMPRESSION flag. This is a reversal of a policy introduced in 1.6. - fixed load-triggered deadlock between asynch DNS process and pluto - add %myid to indirectly refer to current id. Set from $IPSECmyid on startup and via whack --myid - make whack/pluto version matching less stringent for --status and --shutdown. - remove all code for DODGE_DH_MISSING_ZERO_BUG - when attempting outbound Opportunism, check our side's DNS entries, not just the other side's. If we don't have them, fail: not worth attempting. Change since 2.00 release by MCR and DHR - "KEY Restrict": in each place where Pluto used the DNS KEY Resource Record, it now uses one of our special TXT Resource Records. For now, we continue to accept KEY records if the TXT record is not found. Changes since 1.99 release by D. Hugh Redelmeier - Fixed assertion failure in quick_inI1_outR1_continue. Can happen when the result of a DNS TXT query is not needed by the time it arrives (due to another negotiation providing the information). Can be demonstrated by the test "ipsec-oppo-race-iinr-net". Changes since 1.97 release by D. Hugh Redelmeier - added --dnskeyondemand option for connection ends. - Fixed a bug that provoked PF_KEY errors. If an updown script fails and it was invoked as part of a step that involved installing an eroute, any previous eroute should be restored as part of undoing that step. The bug was that any old eroute was lost. - When representing a long string in a DNS TXT resource record, it must be broken up into chunks less than 256. When reconstitute the original string, Pluto now just concatenates them. It used to add a space after a chunk if it was shorter than 255 characters. This should make it easier (not easy!) to edit the TXT record source by hand. - [mlafon@arkoon.net] fixed protocol numbers used in delete payload. - took -DDODGE_DH_MISSING_ZERO_BUG out of Makefile. Anyone planning on talking to FreeS/WAN 1.0 systems should put it back. And check into the Smithsonian Institution. - in --status and logging output, references to connection instances now contain a sequence number for the instance and details of the instantiation (i.e. more IP addresses). Perhaps too bulky. - reworked initiate_opportunistic to avoid race conditions introduced with Asynch DNS. - added impairment to aid testing: IMPAIR_DELAY_ADNS_ANSWER - whack --status now displays the bare shunt table. - Changed Main Mode hash calculation to use the ID Payload as sent by peer, rather than reconstituting it from our tables. This matters if we use different case than peer did (eg @example.com vs @Example.Com). - renamed source files: + kernel_comm.[hc] => rcv_whack.[hc] + preshared.[hc] => keys.[hc] + main.c => plutomain.c - added POLICY_UP to track whether our admin has requested that this connection be up. Changes since 1.96 release by D. Hugh Redelmeier - fixed a bug that would make the following (pointless) sequence to trigger a failure of Pluto assertion "c->routing == RT_ROUTED_TUNNEL": ipsec auto --add conn ipsec auto --up conn ipsec auto --route conn ipsec auto --down conn - send Delete Notifications when deleting IPSEC SAs. We don't yet understand ones we receive. - added "keyid" (see ipsec_keyblobtoid(3)) to appropriate messages so that RSA key being used is manifest. - track whether information (security gateway, public key) came from DNSsec or unauthenticated DNS. Untested since normal resolver calls can no longer return DNSsec results. The information isn't used. - use asynchronous DNS mechanism for all lookups during keying. - added --interface flag to Pluto to constrain interfaces considered. One use of this option is to specify which interface should be used when two or more share the same IP address. Another is to assist with test setups. - small cleanups: + fix compile without no -DKLIPS + use ttodatav in place of atobytes and ttodata + use hosttosubnet + define and use close_any + define and use USED_BY_KLIPS and USED_BY_DEBUG + define and use happy, a kind of assertion macro + define and use impossible, a kind of assertion macro + when an unknown attribute value is seen in an ISAKMP transform, reject only that transform, not the whole proposal. + add Hybrid auth methods to table to improve diagnostics Changes since 1.95 release by D. Hugh Redelmeier - fixed bug in ipsec_doi.c:main_inR3 with unknown consequences. When the Initiator finds out the peer's Phase 1 ID, it might change which connection it thinks is being used. If so, this routine used to perform an operation on the old connection data structure -- a mistake now corrected. There are few cases where the Responder surprises the Initiator about Phase 1 IDs. - fixed an error in network error handling that caused a segfault if there was a MSG_ERRQUEUE report on the last message of a Quick Mode exchange. - fix leak (detected by assertion failure) triggered by missing private key. Changes since 1.94 release by D. Hugh Redelmeier - added "whack --deletestate " as a crude tool for deleting instances of connections. - fix assertion in quick_inI1_outR1 introduced with key rollover support in 1.92. Assertion failed in Responder when Source was not the same as Initiator. - reduce level of routine logging. Add --debug-lifecycle, a temporary hack: it controls some logging, not debugging. - Reorganize code to prepare for asynchronous DNS. - Arrange for our file descriptors to be close-on-exec so that the updown script won't inherit them. Some library facilities (syslog?) may not be as careful. - Fix assertion failure in DNS record handling. Provoked by a malformed key in a TXT record. Introduced in 1.93. - Change Responder cookie generation algorithm so that a particular peer no longer gets the same cookie each time. - Tidy and correct setting and resetting cur_* variables. A per-connection debug setting could provoke a GLOBALS_ARE_RESET assertion failure. - Fix handing of pending list in release_dead_interfaces: connection must be released before it is removed from host_pair list. - Ignore IPv6 interface addresses that are of link-local scope. We think that they are never relevant. Trying to bind to these addresses without a scope-id causes bind to balk. Changes since 1.93 release by D. Hugh Redelmeier - Only run the up-* updown script for tunnel eroutes, not shunt eroutes. - Now only --routed connections may be initiated on demand (i.e. triggered by SADB_ACQUIRE triggered by trapped outbound packet). Among other things, this eliminates a bug whereby an ACQUIRE could be ascribed by Pluto to a Road Warrior template connection. Pluto will now refuse to --route a Road Warrior template. - Correct bug that lost track of a bare shunt table entry. Add debugging logging for changes to that table. Changes since 1.92 release by D. Hugh Redelmeier - [andreas.steffen@strongsec.com] Bug fix: carrying Phase 1 ID over when instantiating a different RW connection due to revelation of Phase 2 IDs. This bug should only have affected X509-authenticated negotiations. - add more context to log and status lines. If the connection or state is an instance, show the peer involved; if Opportunistic, also show the client subnet. - seed rand(3) with bytes from /dev/urandom. - propose 1536 MODP Group before 1024 MODP Group. This generates more entropy, so should be a little safer. And slower. - add --debug-dns flag - During Phase 1, when an RSA Public Key is require, only query DNS for a KEY record for an Opportunistic connection. (This does not change the whack --keyid way of querying for a KEY record during preconfiguration.) - Multiple RSA public keys, if available, will be tried when authenticating a signature. This facilitates key rollover. New whack flag --addkey. Multiple DNS TXT and KEY records are used if they are found (but only one Responder is tried). - no longer try to figure out --rsasig or --psk if neither specified. This would require an extra DNS lookup for a KEY record. Changes since 1.91 release by D. Hugh Redelmeier - got rid of caching of DNS results. They might become stale. - Added --dontrekey option for a connection. Crudely useful for Road Warrior and Opportunistic connections. - Ignore the Commit Flag. This should let us interoperate with implementations that insist on it. The damage should be minor. - Don't split the topology line of --status output. The output is now more consistent (if wider). - Improve diagnosis when ipsec.secrets has a non-indented "}" at the end of an RSA private key. - Savatier Sébastien : fix bug in emitting explicit IP address ID payload. - Support inbound policy check of source and destination inner addresses of tunneled packets. This will make it possible to prevent one peer from successfully spoofing packets from another. - Use poll(2) to check for MSG_ERRQUEUE messages before recvfrom: even though select(2) says that there is a message, a plain recvfrom(2) can block if the only message is on MSG_ERRQUEUE. I think that this blocking is a kernel bug, or at least a documentation bug. Also check for MSG_ERRQUEUE messages before sendto(2): their presence can cause sendto to fail confusingly (i.e. the failure has nothing to do with the actual sendto). Changes since 1.9 release by D. Hugh Redelmeier - SIGTERM now causes Pluto to exit cleanly. - if --nofork is used, Pluto prints the line "Pluto initialized" to standard out after creating the lock file and the control socket. - the startup script relies on the property that whack can be used immediately after the pluto command finishes (i.e. right after the parent process of the daemon exits). In the past, the control socket used by whack was created after the fork: not necessarily before the parent exits. This race condition has been eliminated. - refined the code for DODGE_DH_MISSING_ZERO_BUG to ensure Responder never drops a negotiation. - added and exploited builddiag(), a routine make it easier to add intermediate context to diagnostics. - For purposes of IPv4, Pluto will now only consider interfaces that are "up". It has always ignored those configured with address 0.0.0.0, thus ignoring "down" interfaces in most cases. - add a list of interface pairs to --status output. - replace signal(2) calls with sigaction(2) calls: glibc has further broken the semantics of signal(2). We want slow system calls to be interruptible and not be restarted. - improved error message for lack of preshared key by showing IDs that were used in lookup. Collateral tidying. - documented complex logic of routing and erouting in routing.txt - When a connection is --routed, a route is installed to direct outbound packets destined for the peer's client to go to the ipsec interface implicit in the connection. This is not allowed for Road Warrior connections -- they are strictly inbound. For Opportunistic connections, a new default root is installed that points to the ipsec interface. Note that the route does not take into account the source address. In addition, a TRAP shunt eroute is installed to catch any traffic sent on the not-yet-initiated connection. - When an outbound packet is trapped by the TRAP shunt eroute, Pluto attempts to initiate the corresponding connection. If the attempt fails because an Opportunistic connection was used and no gateway information was found, a PASS shunt eroute is installed (with no provision for automatic removal). - if negotiation fails at a later point, a shunt eroute is installed. The kind of shunt is a policy decision. It is specified as part of the connection. (Untested; can not be specified in ipsec.conf.) - When an inbound negotiation doesn't match a specific connection, and there is an Opportunistic connection, Pluto will try to respond using that connection. - Every 2 minutes (SHUNT_SCAN_INTERVAL seconds), Pluto scans for + PASS eroutes that it installed that haven't been used recently. These will be deleted. + HOLD eroutes for which Pluto hasn't received a PFKEY_ACQUIRE message. For any it finds, it will attempt an opportunistic initiate. - We no longer allow Phase 1 negotiations that we initiate to switch which connection is being used based on the Peer's Phase 1 ID. The fact that we used to do so was probably a bug. - When Pluto as the Responder receives the Peer's Phase 1 ID, it is now willing to use a connection with a different ID and private RSA key for our end. Nothing has committed us to the current guess. - Changes in internal data structures to aid in better tracking of history of attempted and successful communication. Needed for effective Opportunism. + struct host_pair represents information about pairs of hosts. + "Orientation" is done as soon as possible rather than as late as possible. + an arbitrary number of Quick Mode negotiations may now queue for the completion of a Main Mode negotiation. Formerly, a negotiation could only use a previously completed Keying Channel. Changes since 1.8 release by D. Hugh Redelmeier - [Svenning Soerensen] correct check requiring OAKLEY_LIFE_TYPE attribute before OAKLEY_LIFE_DURATION. - Improved whack diagnostics for various cases of failure to connect with Pluto. - Added function state_with_serialno to allow a serial number to be used as a safe reference to a state object. This avoids the risk of dangling pointers. - Add crude support for PF_KEY SADB_ACQUIRE messages from the kernel. These cause the initiation of opportunistic negotiation. - More processing of PF_KEY messages from the kernel. We check that each message we send to the kernel elicits a response. Other messages are queued to be processed at the head of the event loop. - Fix bug in find_client_connection. The manifestation is a Pluto segfault when a negotiation successfully gets to Phase 2, but there is no connection with the appropriate clients AND there is no wildcarded connection using our same host interface (not even an inappropriate one). - Purely internal change: simplify EVENT_SO_DISCARD logic. - Accept GROUP_DESCRIPTION in IPCA (IPcomp SA) proposal. Although this SHOULD NOT appear according to draft-shacham-ippcp-rfc2393bis-05.txt 4.1, it should harmlessly help interoperation. - Adjust to whether KLIPS supports IPCOMP. If it does not, ignore --compress policy flag in Connections. So Pluto would then neither propose nor accept IPCOMP transforms. Changes since 1.7 release by D. Hugh Redelmeier - Allow IPcomp transformations to use "well known CPIs". This perversion allows better interoperation. - Added rather experimental code to exploit IP_RECVERR. This facility allows us to report who refuses our packets when they are refused. I don't understand the documentation of the mechanism, hence the experimental nature of our use of it. Our code is pretty ugly too. - [Svenning Soerensen] found a bug in the calculation of the verb for the updown script and proposed a fix. The -host suffix was being used when the client subnet contained only one IP address, even if that address was not of the host. - [Svenning Soerensen] Allow Phase 1 ID Payloads of type FQDN and user@FQDN to specify UDP/500 explicitly as per RFC2407 (IPSEC DOI) 4.6.2. - When responding in Quick mode, after switching to an appropriate connection based on the ID payloads, copy the connection's IPSEC policy flags into the state object. Do this before consulting these flags. - --status output now indicates when a connection is an instance of another. "POLICY_" has been removed from the display of each policy flag, reducing clutter. An extra space has been added to further indent lines in the --status report. - Fixed a bug in displaying subnets in the error message "cannot respond to IPsec SA request..." - In SA proposals, accept CPIs that are 4 bytes too, as long as the high order 2 bytes are 0. - bug fix: no longer allocate tunnel SPIs below IPSEC_DOI_SPI_OUR_MIN. - Added recognition (not support) for new Assigned Numbers for AES and friends. Changes since 1.6 release by D. Hugh Redelmeier - only accept a proposal with compression if the connection has the POLICY_COMPRESSION flag. Normally, these flags don't affect what we propose. In this case, we need this control since our IPCOMP implementation has a history of crashing. - Fixed nasty bug in connections.c:fc_try(). For a Quick Mode exchange, if Pluto picked a connection as a starting point that had no peer client, it would not accept any proposed peer client. On the other hand, if it picked a connection with a peer client, it would not accept any proposal without a peer client. Changes since 1.5 release by D. Hugh Redelmeier - added a global pluto option --uniqueids. If this is enabled, whenever a new ISAKMP SA is established, any connections with the same Peer Id but different Peer IP address are unoriented, blowing away any of their SAs. This should help eliminate dangling Road Warrior connections when the same Road Warrior reconnects. It thus requires that IDs not be shared by hosts (a previously legal but probably useless capability). - introduced clearer notation: + --host %any signifying any IP address, for Road Warrior, replacing 0.0.0.0 or 0::0 + --nexthop %direct signifying "same IP as peer", replacing 0.0.0.0 or 0::0 + %any and %any6 as indices in ipsec.secrets to match IP addresses of Road Warriors (replacing 0.0.0.0 or 0::0) + --host %opportunistic signifying that the peer is actually to be discovered from the reverse DNS entry for the peer's client. This replaces --host 0.0.0.0 --client 0.0.0.0/32 (and IPv6 variants). - be more strict about Phase 2 ID payloads (the ones that specify clients): reject if they specify protocol or port (which we do not support). - Remove support for Diffie Hellman MODP 768 Group. Increase support for MODP 1536 Group. - Remove NO_RSA option -- patent expired!! - Improve support for newer resolvers. - [initially from Svenning Soerensen ] support IPcomp (compression) - [mostly Gerhard Gessler ] initial support for IPv6. - As part of the IPv6 support, changes were made to the Pluto/updown interface. See pluto(8) for the details. One oft-requested feature is the new PLUTO_*_CLIENT environment variables. The changes are "upward compatible", so the PLUTO_VERSION environment variable setting was changed from 1.0 to 1.1. Unfortunately, this will break many customized updown scripts. - Prototype support for initiating and responding to opportunistic negotiation. A connection is considered for instantiation for opportunism if it has a peer of %opportunistic (the connection description must not specify a client for the peer). Currently, the only way to provoke an opportunistic initiation is to use whack to simulate the interception of an outbound flow (do a "whack --help" and look at opportunistic initiation). These features are not documented because they are experimental. Limitations: no actual interception of packets, DNS query synchronous. - in ipsec.secrets, if multiple entries are the best match for the connection, they must all have the same secret. In the past there was no code to compare RSA keys, so separate RSA entries were assumed to be different. Now they are compared. - Introduce now() to protect against clock being set backwards. The risk is that events might be delayed a lot. Still no protection against clock being moved forward. - Don't "discover" interfaces that share IP addresses with others. This avoids an assertion failure. Eventually, Pluto will have to ask KLIPS about interfaces. - prevent infinite loop decoding certain malformed DNS records - explain "Phase 1", "Phase 2", "Main Mode", and "Quick Mode" - fiddled with "max number of retransmissions" diagnostic to add a bit of explanation. Changes since 1.4 release by D. Hugh Redelmeier - reorganized how messages are logged. More of the serious messages are distinguished with the code RC_LOG_SERIOUS and hence should make it through ipsec auto's filter. - Reserve Message IDs only within their ISAKMP SA. This eliminates the unbounded memory requirement when reserving them per peer. - Pluto's retransmission logic has been improved: + the initial retransmission occurs after 10 seconds of silence, down from 30 seconds. The theory is that this will ungum a lost-packet situation more quickly + the delay after each retransmission is twice the delay before it -- exponential backoff + In the special case of the first message initiating Main Mode, when --keyingtries is 0 (meaning unlimited retries), Pluto will attempt more retransmissions at the same rate (no exponential backoff). This cuts down on the pointless busywork while a peer isn't responding. - Pluto will no longer generate SPIs in the range 0x100-0xFFF. This has the effect of reserving this range for manual keying. Of course Pluto will still allow its peer to use this range. - Fixed another bug in Road Warrior support. In responding to Phase 2 / Quick Mode, once the client subnets (if any) are known, Pluto must reselect which connection to use. If it didn't happen to be using the right one already, and no ID was explicitly specified for the peer, and the right one is a Road Warrior connection, the right one would not be found. Changes since 1.3 release by D. Hugh Redelmeier - Pluto can now acquire a public key from DNS. It must be told to do so. Hint: --pubkeyrsa is optional when specifying keyid. - On the Responder, if a connection is to be routed, and the peer has a client that is a fixed subnet, and that subnet is already routed for other connections, and that route conflicts, Pluto will unorient the old connections (deleting the SAs that depend on the old route) on the theory that they have been superseded. Too bad we can't otherwise tell when a connection is outdated. - Support for netlink has been removed. We always use PFKEYV2. Pluto no longer #includes any kernel headers! - Added a TODO file - Road Warrior support is unconditionally included. No more need to define ROAD_WARRIOR_FUDGE. - Fixed bug preventing Road Warrior connections being instantiated during the connection reselection prompted by receipt of Phase 1 ID Payload [Kai Martius ]. Fixed bug that caused Phase 1 ID to be ignored by connection reselection prompted by receipt of Phase 2 client IDs. Changes since 1.2 release by D. Hugh Redelmeier - fixed deficiencies in id handling - changed to use updown script for routing (and firewalling) - In quick Mode, when Responder, avoid selecting same SPIs as initiator. This prevents KEYMAT being the same in both directions. See Ferguson and Schneier: "A Cryptographic Evaluation of IPsec", http://www.counterpane.com/ipsec.pdf, 5.6 #2. - In Quick Mode, when Responder, install inbound IPsec SA one message earlier. This eliminates the chance of a message being sent before the SA is established. - slight complication to RSA private key lookup rules to allow match to an entry with multiple identities for the host. - support per-connection debugging flags - more use of PFKEY (RGB+DHR) - inbound SAs are now spigrped and an inbound IPIP SA is created if tunneling is used. This more symmetric with outbound processing and it allows KLIPS to check that the correct SAs are all applied. - The way SA lifetime limits are proposed and accepted is better documented. whack now complains when a specified value exceeds the limit. Changes since 1.1 release by D. Hugh Redelmeier - Updated constants to track newer IETF drafts - added support for RSA Signature authentication + augmented demux.c to support packet syntax differences due to authentication technique. + preshared.c now can record RSA private keys + whack --keyid --pubkeyrsa records RSA public keys + whack --unlisten to allow a sequence of whack operations to be atomic with respect to IKE traffic (eg. loading public keys) + ipsec_doi.c will now do RSA Signature authentication + new policy bits are added to select authentication method (--rsasig, --psk) - started towards more general ids (@FQDN and user@FQDN, in addition to IP addresses). + Note: there is *no* meaning attached to the id used beyond being an identifier. Almost no syntax checking is done. + these forms of id work in: o ipsec.secrets indices o whack's --keyid for defining public keys o id payloads (generated and accepted) o --id option for each side in a connection description + the Id may be an IP address that isn't that of one end (but it must authenticate) + once and ID payload is received, Pluto will reconsider which potential connection should be used. It makes sure that any authentication already done would apply to the new connection too. This should make RSASIG + Road Warrior useful. - [RGB, Peter Onion, and DHR] start of PFKEY2 support Changes since 1.00 release by D. Hugh Redelmeier - revamped rekeying: + added --rekeyfuzz; defaults to 100% so lifetime must now be more than twice rekeymargin + added rekeying for responders (but rigged to favour initiators) + [BUGFIX] responder of an exchange will not reinitiate the exchange if it does not complete - Renamed --rekeywindow to --rekeymargin to match ipsec.conf. The old name will be accepted for a while. - improved error and debugging messages - updated list of notification messages (but we still don't support them). - In ID payload, support range representation, but only for a subnet. This may improve interoperability - scatter asterisks in debugging code to support EMACS outline mode. - many internal changes were made to improve to code. This should make it easier to add new states. There should be few behaviour changes. - whack --status now shows the SPIs for established SAs. - [BUGFIX] DH values are now represented with the length specified by the group description, not the length actually needed. About one time in 256, this will make a difference. In those cases, the new Pluto won't interoperate with old Plutos. It looks as if this change brings us in line with other IKE daemons. Added a fudge (select with DODGE_DH_MISSING_ZERO_BUG) so that when a problem arises, a new replacement exchange is initiated (idea from John Gilmore). - [BUGFIX] whack no longer assumes that UNIX domain sockets preserve record boundaries (they don't). This faulty assumption caused whack's exit status to be unreliable - [BUGFIX] pluto now correctly defaults the client subnet in a connection created for a Road Warrior exchange. - [BUGFIX] Road Warrior code now supports multiple connections terminating in a particular Road Warrior node (allowing all appropriate combinations of host and subnets to be simultaneously connected). - [BUGFIX] fix various peculiar Road Warrior crashes. - [BUGFIX] fix spurious deletion of control socket when lock could not be acquired (Thomas Bellman ) - [BUGFIX] interface discovery properly ignores nonAF_NET interfaces Changes since .92 release by D. Hugh Redelmeier - Communication between whack and pluto is now done using UNIX domain sockets. This channel can be secured! - liberalized ISAKMP SA acceptance. Now anything up to and including 16 bytes long is accepted. How silly. - All ISAKMP messages in UDP packets generated by pluto are now explicitly padded to be a multiple of 4 octets long. This was wrong if certain big numbers (eg. nonces) happened to have leading zero octets. - set socket option SO_REUSEADDR on pluto's whack socket. This allows Pluto to quickly restart. - Use new, consistent notation for topology: client===host---nexthop...nexthop---host===client - prefix every line of status output with connection name. This allows selection of output using grep. - Replaced system's assert with passert. This sends the diagnostic to syslog. - Changed secrets file name processing to support sh-like "globbing" for file names. - Where appropriate, log messages are prefixed by their connection name and state object serial numbers. Connection names are quoted with double quotes and serial numbers are prefixed with the number sign (#). Otherwise, where appropriate, log messages are prefixed by the IP address and port number from which the current message was sent. - some attempt at making the messages more helpful + warnings when authentication (preshared secrets) failure is likely cause of the observed symptom + status message now highlights which SAs are the most recent (those are the ones that are subject to rekeying)and which are erouted. + state names are slightly improved + status message prints the "meaning" of a state after its name. - the policy options of a connection (--pfs, --authenticate, --encrypt, (but not --tunnel)) now apply to negotiations being responded to. They continue to apply to negotiations initiated by Pluto. - The Oakley group used for PFS in Phase 2 is dictated by the initiator. We used to dictate one of our choice. To increase the chances for success, we now dictate the same group as was used in Phase 1. - First, some context. The "negotiated" lifetime of an SA is actually dictated by the initiator. If the responder doesn't like this lifetime, it can tell the initiator in a NOTIFY message. Pluto doesn't do this. Instead, it will just expire the lifetime sooner than negotiated. In the past, Pluto only initiated rekeying if it was the initiator. Now, a responder Pluto will initiate rekeying if it is going to expire the SA earlier than negotiated. To prevent an explosion of SAs, rekeying will only be done if the SA is the newest one for its connection. Rekeying of IPsec SA will respect the security properties of the old SA at the level of policy options (i.e. --pfs, --authenticate, --encrypt, --tunnel). - Replaced --rekeytries with --keyingtries. This option now applies to initial keying as well as rekeying, hence the name change. Even though initial keying will now try more than once, whack logging will be stopped after the first attempt. The value 0 is taken to mean, effectively, infinity: don't give up. Changes since .91 release by D. Hugh Redelmeier - A hack has been added to support mobile or anonymous initiators. - The isakmp-secrets file has been renamed ipsec.secrets and the format spruced up to aid scalability. Entries now can be shared between relevant machines verbatim. An include facility was added. The file is now only read upon --listen commands. - If --firewall appears on our end of a connection, Pluto will add a firewall rule to enable appropriate forwarding, without masquerading for any route it adds. It will delete the rule when it deletes the route. - When Pluto thinks whack's message is malformed, it now says so to whack, not just syslog. - In addition to the messages traditionally sent back to whack, non-debugging messages sent to the log that relate to whack's current activity are copied to whack. Whack's exit status now reflects the last message (if any) returned by Pluto. This should allow a script to tell, for example, if an SA was established. - top-level payload parsing has been centralized. This should make it easier to add new features. Payload ordering constraints have are now just those required by RFC2409 (IKE). In most cases, Pluto will now ignore duplicated packets. It should recover better from the reception of a corrupt packet. - Interface discovery is more clever. It notes each configured interface with a name ipsec[0-9] as a virtual public interface and considers any interface with a different kind of name and the same IP address to be the corresponding real public interface. This is only done when Pluto starts, so any interfaces of interest must be configured before then. This feature allows Pluto to support multiple public networks. - Pluto now exploits the fact that eroutes only conflict if their local clients AND peer clients are the same. So we can now support multiple subnets behind our security gateway all talking to clients behind another security gateway. - Switched to using ipsec_spi_t to represent SPIs. In the process fixed a related bug found by Peter Onion. Changes since .9 release by D. Hugh Redelmeier [incomplete] - Message IDs are now random, rather than counting up from 1. This should help keep messages in different but simultaneous Phase 2 exchanges being mixed up. - syslogged informative (i.e. debugging) messages are now prefixed with "| " to make the easier to ignore. - forbid zero cookies. Among other things, this prevents feedback confusing Pluto. - Use serial numbers to cause most recent of available ISAKMP SAs to be chosen. Also useful in debugging output. - Pluto will now only listen to Whack on the loopback interface (important security limitation). - implement rekeying, based on time, for ISAKMP and IPsec SAs - Whack now talks to Pluto using TCP. This allows status information to be returned to Whack. For now, not much interesting is sent back. The TCP port is the *same* as the IKE port -- no longer 1 greater. Pluto closes the socket once the "goal" is established or the state object is freed. All this will evolve. - For SAs that were initiated by Pluto, Pluto will try to replace the SA before it expires. There is a 10 minute window (SA_REPLACEMENT_WINDOW) in which this can occur. - Support --peer_nexthop for initiator of ISAKMP SA. - Support --optionsfrom - be more specific about error conditions: for each STF_FAIL, designate which notification message most applies. - use these results in reporting to whack - make whack back-talk look like FTP messages - add and use notion of (potential) connection database. All scripts change! - fix handling of the variable form of attribute - don't allow --initiate before --listen - use new number for ESP_NULL - demand each transform include an ENCAPSULATION_MODE attribute - demand each AH transform include an appropriate AUTH_ALGORITHM attribute - add not-yet-standardized OAKLEY_GROUP 5 (MODP 1536) - since KLIPS only allows one IPsec SA to be routed to a particular subnet (for a peer's client), detect when a subnet is engaged. If we are replacing that SA, OK. Otherwise, balk. - [experimental] exploit the new UDP 500 hole to support host mode. - add --route and --unroute: hysteresis in routing should prevent packets flowing in the clear during IPsec SA transitions. - add --status to display the internal state of Pluto. - deleted misleading README; other resources fulfill its role - eliminated EVENT_CLEANUP: using EVENT_RETRANSMIT seemed more correct - gave special meaning to combination of delete and add - improved and documented combinations of whack command types - improved logging - added and used LEAK_DETECTIVE. Fixed some leaks. Changes between .85 and .9 release by D. Hugh Redelmeier [incomplete] - change pluto and whack's argument processing to use getopt_long: the syntax and expressive power is quite different. - allow selection of debugging output. Change pluto to accept arguments for specifying this. Change whack and pluto allow settings to change during a run. - make most controls for debugging run-time rather than compile-time. This required the addition of many command line arguments (see README) - support 3DES encryption of Oakley messages (OAKLEY_3DES_CBC) - accept modestly long attribute values (32 bits) for OAKLEY_LIFE_DURATION and SA_LIFE_DURATION. Changes between .7alpha and .85 (highlights) by D. Hugh Redelmeier - support RHL5.0 (glibc): avoid clash between and - Lessons from porting to Solaris: endianness, careful typing, alignment, correct fd_set bugs in call_server(), correct rnd.c to use sig_atomic_t - Makefile: add distlist target to put out names of files in distribution - Makefile: when installing binaries, move old ones to .OLD - add and exploit pb_stream mechanism for systematically decoding and encoding packets - More flexible security policy, but still hard-wired. - support new Oakley group (2 -- modp 1024) - make returned IPsec proposal for acceptance a copy of winning proposal (as per spec) - add and use generic interface to hash functions - add many comments referencing the draft standards - change all uses of stdout to use stderr instead (choice between stdout and stderr was haphazard) - fix SPI stuff: Oakley and IPSEC SPIs are different beasts - generate initial IPSEC SPI as a random number (avoid clashes) - fix layout bug for struct isakmp_transform - fix several dangerous memory allocation and buffer overflow errors; eliminate all inline uses of calloc (use a wrapper) - avoid memory leak due to uncleared mpz variables - general tidying and restructuring; get rid of many "magic" numbers - de-lint everywhere (add -Wall -Wmissing-prototypes to Makefile) - switch from BSD b* functions to ANSI mem* functions - get rid of bitfields - generate the correct amount of keying material (PRF feedback, if needed) - improve get_preshared_key (new format too) - improve handling of informational exchanges. Still poor. - improve tracing output - print version information (whack and pluto) - wherever an enum-like value is printed, print the name of the value - make duplicate_state() duplicate the st_myidentity_type field. - make kernel interface do required route commands - open and close /dev/ipsec more carefully - support separate keys for esp encryption and esp authentication libreswan-3.32/docs/CHANGES.openswan000066400000000000000000002177011365625662500172330ustar00rootroot00000000000000 Note that listings are in chronological order of release times, not in order of version numbers, so you will find 2.5.x and 2.6.x releases intersperced. See also docs/KNOWN_BUGS.txt and http://www.openswan.org/ v2.6.39 (unreleased) * Bugtracker bugs fixed: #1349 pluto logging no subjectAltName matches ID '%fromcert', replaced by subject DN [Tuomo] v2.6.38 (March 23, 2012) * DPD: seq_no logged after hton() call [Shinichi Furuso] * DPD: With multiple phase 2 SAs, we sent too many [Shinichi Furuso] R_U_THERE's * barf: iptables-save on suse is in /usr/sbin, not /sbin [Paul/Shinichi] * SUSE: Package compliant with Kernel Module Package Manual [Shinichi Furuso] * verify: fix false positive on IP forwarding (perl dependent) [Steve Delaney] * IKEv2: Introduced new keyword narrowing=yes|no [Paul] * IKEv2: Send TS_UNACCEPTABLE when narrowing would violate local policy [Paul] * IKEv2: Fix for multiple SAs to the same peer with different ports [Avesh] * IKEv2: IKE-SA_INIT with INVALID_KE_PAYLOAD Notify Payload should continue [Avesh] * IKEv2: incorrecty sent PAYLOAD_MALFORMED on unknown minor version [Avesh] * IKEv2 should ignore unknown RESERVED bits in payload [Avesh] * IKEv2: Implement sending higher IKEv2 major and minor versions [Paul] * IKEv2: Delete SA states added to state machine [Avesh] * IKEv2: Informational Exchange added [Avesh] * hostpair: initial_connection_sent was never set to not FALSE [Avesh] * Crypto: handle leading zeroes in DH keys [Avesh] * Add PLUTO_IS_PEER_CISCO= to updown scripts [Avesh] * XFRM: update userland copies of xfrm.h netlink.h rtnetlink.h [Paul/Avesh] * SHA2 fix when pluto is compiled without USE_EXTRACRYPTO [Paul/Tuomo] * SHA2: Fix for Linux kernel using bad sha2_256 truncation (96 instead of 128) (to get the old behaviour for interop, specify sha2_truncbug=yes) [Paul] * Fix two format string buglets [Moritz Muehlenhoff] * XAUTH: Support unbound as local resolver in remote_peer_type=cisco [Paul] * NATT: Fix iphone/iOS by removing outdated OSX NAT-T workarounds [Paul] * SAREF: kernel patches updated to linux 3.0.0 [Jonathon Padfield] * SAREF: fix all patch versions to use new numbers for SAREF [Paul] * Fix various compiler warnings in lib, pluto and ikeping [dhr] * Various ESP_* and AH_* fixes/updates from IANA [Paul] * Fix authalg in esp_info to be u_int16_t, not u_int8_t [Paul] * Debian: Various debiacn packaging fixes [Simon] * KLIPS: Fix crasher on returning -ENODEV from ppp devices [David] * XAUTH: Support dynamic config update for unbound DNSSEC resolver [Paul/Tuomo] * Remove non-iproute2 version of _updown.klips and its USE_IPROUTE2 [Paul] * Bugracker bugs fixed: #1263 /usr/lib/ipsec/_startnetkey selects wrong default gateway if there are multiple [Petr Tichy] #1314 update the updateresolvconf routines to be able to reconfigure locally running unbound [Paul] #1322 get rid of unused bucketno argument in state_hash [Paul] #1326 0001-SAREF patch not compiling on 3.0.0 [Jonathon Padfield] v2.6.37 (October 28th, 2011) * Fix for CVE-2011-4073 crypto helper crash [Paul/dhr] * KLIPS: Fixes to run on Linux 3.1 [David McCullough / Greg Ungerer] * KLIPS: Fix sending icmpv6 packets in an ipv6 ipsec tunnel [David McCullough] * Fix for ike_alg_get_encrypter() possibly returning NULL [Steve Grubb] (this is rhbz#747852) * Bugtracker bugs fixed: #1241 vhost allows connections with subnets proposed and ignores virtual_privat [Wolfgang Nothdurft] v2.6.36 (October 5th, 2011) * CVE-2011-3380 Openswan IKE invalid key length fix [Paul/Hugh] * auto: Add --checkpubkeys option for checking expiry of X.509 certs [Mika Ilmaranta] * Update building (with SAref) on SLES10 / SLES11 / Opensuse [Shinichi Furuso] * KLIPS: backported 2.6.19 CryptoAPI for SuSe kernels [Shinichi Furuso] * KLIPS: ipsecdevices index overflow [Shinichi Furuso] * KLIPS: cleanup off by one interface,prevented module unload [Shinichi Furuso] * tncfg called incorrectly for adding more ipsecX interfaces [Shinichi Furuso] * KLIPS: ipsec_sa_getbyid() did not work properly on IPv6 [Shinichi Furuso] * NAT-T: Fix delete for port floating case [Shinichi Furuso] * IKEv2: We always sent the openswan VID instead of using #ifdef [Avesh/Paul] * IKEv2: ikev2_get_dcookie used SHA1Update() with pointer size [Avesh] * TESTING: Added some more consistent logging in prerunsetup() [Paul] * pcr_init() should memset the request helper size, not pointer size [Avesh] * Prevent deferencing ctx->trans_cur in db_trans_add() [Avesh/Paul] * XAUTH: whack_get_value() never decremeanted "tries" [Avesh] * Fix closing fd in lib/libopenswan/oswconf.c [Avesh] * rsasigkey: configdir is always set in the NSS #ifdef part [Avesh] * examples: clarify hub-spoke netkey design [Tuomo] * NAT-T: Fixed logging for broken NAT-T keepalives [Tobias Brunner] * Use iptables-save instead of iptables -L if possible (rhbz#737973) [Avesh] * ipsec verify: New kernels use nf_conntrack instead of ip_conntrack [Avesh] * LDAP/CRL needs liblber (rhbz#737975 [Avesh] * SAREF: kernel patch added for Linux 2.6.36 and 2.6.38 [Paul] * SAREF: Remap IP_IPSEC_REFINFO/BINDREF from 22/23 to 30/31 [Sony Japan] * Disable USE_IPSECPOLICY per default, was only proof of concept code [Paul] (local user could cause pluto to stop responding if /var/run is a tmpfs mount and /var/run/pluto was manually deleted, Found by Sony Japan) * Bugtracker bugs fixed: #1270 malloc is being used which does not use alloc_bytes/pfree [Paul] v2.6.35 (July 23, 2011) * OCF: Fix accidental 'always' setting of large resources [Sony Japan] * OCF: Give a hard #error in ipsec_ocf.h without proper CONFIG_KLIPS_OCF [Paul] * OCF: Only include ipsec_ocf.h when using CONFIG_KLIPS_OCF * MAST: Add ipsec_xmit_sanity_check_dev() in the mast path [Paul] * MAST: Be more careful about {mast,ipsec}priv structure [Bart] * MAST: Fix host-host connections, bug introduced in v2.6.34 [David] * SAREF: Fix crasher in ipsec.ko unload with saref kernel [Sony Japan] * SAREF: ip_cmsg_recv_ipsec_refinfo() doesn't initialize refs array [Sony Japan] * SAREF: Added null check of secpath_dup(NULL) [Sony Japan] * KLIPS: Fix possible double skb free [Sony Japan] * KLIPS: Fix MTU on interface - bug introduced in 2.6.33 [Wolfgang Nothdurft] * KLIPS: debug messages often had pre-refactor names in prefix [Paul] * DPD: Do not ignore failure in dpd_init() but return STF_FAIL [Paul] * pluto: Fix IPcomp pull-up from 2.4 introduced in 2.6.20 [Paul] (malloc <-> pfree caused assertion with LEAK_DETECTIVE set) * pluto: st_peeridentity_port missed ntohs() causing interop failure between big/little-endian machines [Magnus Öberg] * pluto: Fix for Tuomo's (rare) crasher where globals were not reset [dhr] v2.6.34 (June 8, 2011)) * Fix build without USE_EXTRACRYPTO introduced in 2.6.33 [Tuomo] * Fix new leftmtu= option to pass correctly to _updown [Mattias Walstrom] * Add Apple iOS work-around to l2tp example configs [Tuomo] * KLIPS: Support to compile on Linux 2.6.38 and 2.6.39 [David] * KLIPS: Make sin_family setting in delflow the same as addflow [David] * KLIPS: IPv6 and SLES10 compile fixes [Sony Japan] * KLIPS: IPv6 outbound policy check used wrong index [Sony Japan] * KLIPS: Enable CryptoAPI per default [Paul] * KLIPS: Module unload fixes [David] * KLIPS: Routing cache corruption due to ip_select_ident [David] * KLIPS: Only fixup the ethernet header it might be on [David] * KLIPS: Fix for ixs->skb->dev is null at the top of ipsec_xmit_send [David] * MAST: refcount bug in transport mode prevented ipsec.ko unload [Sony Japan] * MAST: Don't autopick mast [David] * NETKEY: Fix AH mode [Avesh] - rh #704548 * DYNDNS: using hostnames could lead to loss of ports in SA [Avesh] - rh #703473 * Many uml testing harness fixes and updates, mostly IPv6 related [Paul/Hugh] * "ipsec look" now shows NETKEY/XFRM and IPv6 routing table [Paul] * "ipsec look" now shows iptables NEW_IPSEC_CONN mangle table [Paul] * "ipsec look" and "ipsec barf" now shows ip6tables like iptables [Paul] * Fix inbound policy --addin, and added --replacein [David] * KLIPS: Fix family check when policies are not set [David] * MAST: Fix family check when policies are not set [Sony Japan] * Improve build speed (don't recalculate build version all the time [David] * XAUTH: Fix rekey with Cisco when remote_peer_type=cisco [Avesh] * Openswan (IKEv2/IKEv1) icmp issue (redhat bz 681974) [Avesh] * IKEv2: port range was hardcoded to 0-65535, not local policy [Avesh] * MAST: Fix oops on module unload [David] * Improve build speed, calculate version once [David] * Import OpenWRT packaging updates [Simon] * contrib: added openswan patch for 2.4.37.9 [Yannick Koehler] * KLIPS: Fix for compiling on 2.6.22 (Fedora Core 6 based) kernels [Paul] * KLIPS IPV6: Fix packet fragmentation [Paul] * Added PLUTO_CONN_ADDRFAMILY= to updown.* (to disable SAref on v6) [Paul] * KLIPS: cleanup packaging/*/config-* files [Paul] * Fix a bunch of gcc unused-but-set-variable warnings [Paul] * Fix some WERROR warnings [mcr] * Various file descriptor leaks and mimor memleaks [Avesh/dhr] * Removed reference to http://www.freeswan.org from ipsec --help [Tuomo] * Bugtracker bugs fixed: #1233 WARNING: at net/ipv4/af_inet.c:151 inet_sock_destruct on stop [David] v2.6.33 (February 18, 2011) * Merge in the klips-ipv6 branch [David] * modprobe more crypto modules on startup (gcm, camelia, sha2* etc) [Paul] * Added %v4:26/8 to virtual_private ("thanks" to T-Mobile/Rogers/FIDO) [Paul] * Pluto did not start nhelpers due to --nofork, bug introduced in 2.6.32 [Paul] * OCF: Set the OCF queues to 10000 when 256MB+ RAM and 1000+ bogomips [Paul] * Improved NetworkManager support [Avesh] - This is Red Hat bugzilla 642722, 658253, 659709 and 641068 * ipsec verify now also shows parse errors in ipsec.conf [Paul] * Always build SHA2 family support for IKE [Paul] * KLIPS: Add a new option to override the replay window via /sys [David] (echo 0 > /sys/module/ipsec/parameters/ipsec_replaywin_override) * Add aesni_intel to the list of crypto modules we attempt to load [Paul] * enable dumpdir= in stock ipsec.conf for use with abrtd [Paul] * New per-conn keyword mtu= allows setting the mtu per tunnel [Paul] * per-conn keyword metric= did not export to userland or updown [Paul/Tuomo] * Cleaned up and moved some old docs [Paul] * KLIPS: arp_broken_ops is no longer exported in 2.6.37+ [Paul] * KLIPS: Fix crasher in ipsec_xmit_state_delete [David] * KLIPS: Fix oops if packet is received on detached tunnel [David] * Bugtracker bugs fixed: # 601 KLIPS: NAT-OA UDP checksum bad in transport mode when both sides are NATted [Wolfgang] # 645 hundreds of replacements [...]: 000 #3: pending Phase 2 [Anthony Tong] #1182 Verification of X509 certificate signed by SHA2 [fryasu@yahoo.co.jp] #1183 Fix documentation typo (in ipsec.conf) [Tuomo] #1190 nat-t broke on transport mode for klips between 2.6.31 and 2.6.32 [Paul] #1199 when leftsubnet has a different netmask than the localnet, a route is added for the localnet to the ipsec device [Tuomo] #1201 dpd + ddns does not work [Mattias Walström] #1204 Workaround for iPhone/MacOS X NAT problem [Wolfgang Nothdurft] #1210 Fails to compile with uClibc >= 0.9.29 [mb@openwrt] v2.6.32 (December 17, 2010) * Remove by default forced -DLEAK_DETECTIVE [Tuomo] * Makefile.inc now uses USE_LEAK_DETECTIVE?=false [Paul] * NOMMU: Add -DCOMPILER_HAS_NO_PRINTF_LIKE to support arm-elf-gcc [Paul] * NOMMU: If pluto is started with --nofork, then also disable nhelpers [Paul] * NOMMU: Added HAVE_NO_FORK?= option to Makefile.inc (default false) [Paul] * INTEROP: Ignore IKEv1 notification type 40001 (Netscreen private use) [Andreas/Daniel] * IKEv2: Fix crash on receiving retransmitted STATE_PARENT_I2 on bad AUTH [Paul] * IKEv2: Check for USE_TRANSPORT_MODE in all received notification payloads, not just the first notify payload. This is Red Hat bugzilla 646718 [Avesh] * MAST: The mastX interface no longer gets/needs an IP address [Paul] * MAST: avoid routes towards virtual ipsecN interface [Bart/Roel] * Support for Isomorphic Algorithms and Identity Disks [Olivia Wilde] * SAREF: set sareftrack=yes as the default policy [Paul] * Fix printf format arguments [Simon] * Added ipsec addconn --checkconfig and initscript support [Harald] * Fix for: either "local" is duplicate, or "secondary" is garbage [Simon] * KLIPS: Better interface handling in _startklips [Paul] * fix interface parsing in getinterfaceinfo() [Bart/Roel] * KLIPS: Support more then 9 ipsec/mast interfaces in parser [Simon] * OCF: Change some hardcoded variables to module parameters [David] -ipsec_ocf_batch(1): Make OCF queue packets rather than process immediately -ipsec_ocf_cbimm(1): Does OCF immediately (ie., at irq time) run callbacks or queue and call later" -ipsec_ixs_cache_allocated_max(1000): * OCF: Fix up usage of crp_olen as returned from ocf [David] * OCF: Order algs correctly for processing when mixing AUTH/CIPHER algs [David] * OCF: Update to OCF for SMP systems to allow using multiple CPU's [David] * OCF: Added /proc/net/ipsec/ocf to indicate if we support OCF or not [Paul] * OCF: move netif_wake_queue inside the lock in ipsec_xmit_state_delete [David] * OCF: OCF: Attempt to load OCF kernel HW module on startup [Paul] * SMP/OCF: Fix up queue stop/start on SMP systems [David] * OCF: Fix OCF deadlock (do not call schedule with a lock) [David] * Fix bad memory read with full debugging enabled (pbs_room vs pbs_left) [Dhr] * Fix bad memory read with -lefence in osw_alias_cmp() [Dhr] * Fix for STF_INLINE case in quick_inI1_outR1_cryptocontinue1() [Dhr] * KLIPS: make kpatch is more robust, less manual patching [Paul] * UML: Various minor fixes to get uml system back online [Paul] * SPEC: Add "development" define in spec file to build devel version [Tuomo] * RSA: Fix generation of ipsec.secrets when missing on first startup [Paul] * DPD: DPD_ACTION_RESTART would always execute DPD_ACTION_RESTART_BY_PEER [dhr] * DPD: DPD_ACTION_CLEAR crash on CK_INSTANCE with -lefence [Tuomo] * DPD: flush_pending_by_connection() when doing a %clear on DPD timeout [dhr] * NAT: Put old/new style chatter into DBG_NATT [Paul] * NETKEY: Reduce bogus noise about Old/New NAT-T support [Paul] * Bugtracker bugs fixed: #1095 Local packets are dropped on ipsec device when marking packets in OUTPUT chain [Wolfgang Nothdurft] #1160 init.d script not reporting correct exit status on config parse error [James Mead] #1162 IKEv2 transport mode interop with racoon [PATCH] [Avesh] #1170 pluto option --impair-shared-phase1 causes segfaults on --down'ing a connection v2.6.31 (October 18, 2010) * Fix for OCSP compile of commit 934ce6c9443832c [Paul] v2.6.30 (October 18, 2010) * Fix for: ASSERTION FAILED at connections.c:1579: c->kind == CK_TEMPLATE [Paul] * Add --listen/listen= option to limit listening to a single IP [Paul] * sa_policy_bit_names was missing ModeConfig DNS and WINS bit names [Paul] * SAREF: Add sareftrack= connection option [Paul] * Fix for "handling event EVENT_RETRANSMIT for " [Paul] * Fix for specifying protport=47 (GRE has no ports) [Paul] * IKEv2: Don't fill traffic selector struct in IKEv2 child SA when not recv'd [Paul] * MODULES: Add geode-aes to the list of crypto modules to load [Paul] * Don't install ipsec init script as /etc/init.d/setup [David] * Don't create rc.? symlinks - let user use chkconfig etc instead [Paul] * Bugtracker bugs fixed: # 252/619 more than 20 payloads in message; ignored [paul] # 690 ipsec lwdnsq --help not implemented # 860 Port --random for newhostkey [Paul] #1005 Incorrect message "R_U_THERE_ACK has unexpected sequence number" [Mike] #1040 Fix to compile without DEBUG [Paul] #1054 Startup warning: "ignored obsolete keyword (null)" [Michael Smith] #1112 Prototypes only, if function enabled in c-source with KLIPS or PFKEY [Henry N.] #1115 Fix various warnings u_char * vs. char * for sscanf,... [Henry N.] #1149 pluto uses empty NAT_OA as IDci, Server behind NAT and non natted Windows XP [Wolfgang Nothdurft] #1151 The ipsec module is not removed by 'ipsec setup stop' [Paul] v2.6.29 (September 27, 2010) ! This release is made for CVE-2010-3302 and CVE-2010-3308 ! Duplicate CVE's issues for these are CVE-2010-3752 and CVE-2010-3753 * XAUTH: Avoid buffer overflow in CISCO DNS info [dhr/paul] Avoid shell problems with single quotes CISCO DNS parameters [dhr/paul] http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=2010-3302 * XAUTH: Avoid buffer overflow in CISCO BANNER [dhr/paul] Avoid shell problems with single quotes in CISCO parameters [dhr/paul] http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=2010-3308 * NETKEY: Fix for spurious %hold netlink-acquires [Paul/dhr] * KLIPS: Fix compiling on 2.6.18 based RHEL5 kernels [Paul] * Various fixes based on automated source code review [dhr] * SAREF: Updated for 2.6.35 kernel [Harald] * KLIPS: Updated for 2.6.35 kernel [Harald] * PACKAGING Use Epoch 1: for Debian/Ubuntu [Simon] * MAST: fix iptables rule "leak" on rekey [Bart] * MAST: use only the most recent iptables rule [Bart] * pluto: restrict rekeymargin to be smaller than salifetime [Bart] * MAST: ensure we don't end up with mtu=0 on mast0 [Bart/Paul] * MAST: enforce outgoing tunnel policy [Bart] * MAST: use addflow pfkey command to set policy on tunnel SAs [Bart] * Added a new pfkey flag, POLICYONLY, to the ADDFLOW command [Bart] * MAST: allow for setting of policy for inbound SAs [Bart] * MAST: favour deleting an SA even if the pfkey op failed [Bart] * HAVESTATSD: Log new phase2 messages as a result of a rekey [Paul] * MAST: use iptables --comment to show the conn name [Bart] * VNET: differentiate instantiation of road warriors and vnet [Paul] * Log LEAK_DETECTIVE and HAVE_LIBNSS support on startup [Paul] * IKEv2 connections were broken since 2.6.25 [Avesh] * MAST: new "ipsec policy" command replaces "ipsec eroute" [Bart] * Fix SElinux warning in realsetup (bz628879) [Avesh] * Support for SHA2_256 in IKEv2 (bz621790) [Avesh] * IKEv2: Fix for using MD5 and PRF conversion function [Avesh] * SAREF: Improved workaround for rp_filter [Bart] * NSS: Increase minimum nss for rhbz#453577 [Paul] (this allows us to revert workaround in git 6c8ff2791d1) * SAREF: Added /proc/net/ipsec/saref that shows kernel patch state [Bart] * SAREF: Add SAref checks to ipsec verify [bart/paul] * A bunch of Makefile.inc variables could not be overridden properly [Paul] * Bugtracker bugs fixed: #1042 NF_INET_LOCAL_OUT vs NF_IP_LOCAL_OUT still broken [David] #1102: Ensure KLIPS still works on older kernels [Paul] #1113: crypt_dh.c: Fix "warning: multi-line comment" [Tuomo] v2.6.28 (July 29, 2010) * MAST: Fix SAref vmalloc() call that could cause a kernel panic [Bart] * SAREF: rework exported interface to avoid might_sleep() during rcu lock [Bart] * SAREF: Use the correct mask when updating nfmark in rcv path [Bart] * MAST: Cleanup updown.mast iptables rule management [Bart] * MAST: Rework mast init scripts to use conntrack [Bart] * MAST: Remove iptables rules after SA is deleted [Bart] * SAREF: Fix bug in stream-socket saref mode [Bart] * SAREF: Ported to apply on Linux 2.6.34 [Harald] * MAST: Fix for NAT-T mode (set ixs->outgoing_said in mast mode) [Bart] * MAST: Fix module unload with mast [Bart] * Allow rightsubnet=vnet:%priv rightprotoport=17/%any w/o right=%any [Paul] * SAREF: Log SAref and SAbind capabilities on pluto startup [Paul] * Log tunnel down with HAVE_STATSD as "down", not "unknown" [Paul] * Changes to _realsetup.in for making the init script LSB compliant [Avesh] rhbz #594767 * _startnetkey update for DNS and NetworkManager [Avesh] * SAREF: fix bug in stream-socket saref mode [Bart] * Added TCP header flags to ipsec_print_ip() output [Bart] * KLIPS: Don't fail non-existent header_ops (breaks ppp) [David] * KLIPS: ip_select_ident hashing fix in AH xmit path [Kirill Berezin] * HAVE_STATSD: Fix phase1/phase2 logging through HAVE_STATSD interface [David] * HAVE_STATSD: log output fix when two connections share a phase1 [David] * HAVE_STATSD: Slightly clarified and changed log messages [Paul] * SAREF: Clarified defines and fixed nfmark printing in HAVE_STATSD [dhr/Paul] * MAST: Temp workaround in _updown.mast for martians problem [Bart/Paul] * Cleanup source code to use C-style comments [Tuomo] * Bugtracker bugs fixed: # 1120: [PATCH] netlink receive buffer size too small for linux 2.6.32 [Roman Hoog Antink] v2.6.27 (June 21, 2010) * Fixes to the SAREF / MAST code to avoid recursion loops [Bart] * KLIPS compile fixes for 2.4 kernels [David] * Memory leak fix unshare_connection_strings [Shinichi Furuso] * define ALLOW_MICROSOFT_BAD_PROPOSAL to allow connecting to behind NAT [Paul] * Missing load_oswcrypto() call 'ipsec showhostkey' [Kevin Locke] (this is http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=575757?) * Log the netfilter mark (him/me) with HAVE_STATSD=true [Paul] * saref-bind kernel patch that allows setsockopt() to an saref [Bart] * Rename /bin/statsd to /bin/openswan-statsd with HAVE_STATSD=true [Paul] * contrib/sarefnc is netcat (nc) with saref settable option [Bart] * Allow multiple proposals in Aggressive Mode, as long as the DH group is the same for all of them [Michael H. Warfield] * alg_info_addref() needed #ifdef KERNEL_ALG like alg_info_delref() [Shinichi] * Remove the obsolete _confread script. [Simon] * Correct the creation of the directory /var/lock/subsys. [Simon] * Set a default value for IPSECsyslog in setup to avoid logger errors. [Simon] * Cleanup source code to use C-style comments [Tuomo] * Enable addconn to read config from stdin when called with --config - [Simon] * Fix for broken enum_names regarding ENCAPSULATION_MODE_TUNNEL* [Paul] * Fix for a few gcc warnings in dnskey.c and xauth.c [Paul/Simon] * Fix for kernel_pfkey.c bad_case(esatype) introduced in 2.6.25 [Bart] * Bugtracker bugs fixed: # 76: ipsec verify warns about no RSA key when using X509 pem files [Paul] #1074: virtual_private broken on U2.6.19/K2.6.27.25-78.2.56.fc9.i686? Fix virtual_private checks to give correct warnings [Tuomo] #1101: protoport code and nat-t code are switching ports with netkey [Mika Ilmaranta/Tuomo] #1106: Incorrect xfrm policy with both-NAT client connection [Paul] v2.6.26 (May 25, 2010) * KLIPS fixes for 2.6.33 kernel [Greg Ungerger/David] * RFC-5114 Diffie-Hellman group 22, 23 and 24 support [Avesh] * Revert broken work-around for nspr4 warning [Tuomo] * Copy David's klips fixes to netlink where they are needed too [Tuomo] * Fix bogus initiations of existing tunnels on netkey introduced in 2.6.25 [Tuomo] * Compile fixes for compiling without NAT_TRAVERSAL [Paul] * Fix pfkey error on tunnel deletion [David] * Fix up eroute_connection for klips [David] * When we ASSERT, show where we asserted [Bart] * Merge in #osx branch [Paul] * Fix eroute_type to satype conversion for pfkey [Bart] * Fix confusion about transport_proto and proto in comments and bsdkame [Tuomo] * Updated SecureClient patch for hybrid mode in contrib [Yair Elharrar] * remote_peer_type= support for whack [Avesh Agarwal] * Cisco banner support in _updown via PLUTO_PEER_BANNER [Avesh Agarwal] * New option nm_configured=yes will skip reconfiguring resolv.conf, so that NetworkManager can handle this. Can be directory whack'ed using the --nm_controlled option. [Avesh Agarwal] * Clean up DPD logging. [Tuomo] * SAref updated to 2.6.32 kernel [Bart/Paul] * Bugtracker bugs fixed: # 414: Y2K38 bug in X.509 Digital Certificate handling [Andreas Steffen] (happened only on 32bit machines for certs expiring after 2038) # 428: Fix for representation of [...] used algorithms in ipsec auto --status [Martin Schiller] #1004: Better fix for bug #1004 [Mika Ilmaranta/Tuomo] #1035: Allow specifying interface name, eg left=%ppp0 [Martin Schiller] #1080: duplicate of #414 #1085: Random disconnects of (ipsec+l2tpd) tunnels [Mika Ilmaranta/Tuomo] #1087: acquires cause invalid policies being inserted into xfrm policy introduced in 2.6.25 [Tuomo] #1093: enc alg=0 not found in constants.c:oakley_enc_names [Henry N.] #1094: IPSEC_RCV_DECAPFAIL with auth=ah [Wolfgang Nothdurft] #1096: ipsec_xmit_send ignored mark of skb. causing ignoring of ip rules and only main routing table was used. [Wolfgang Nothdurft] #1104: Compile for NETKEY without KLIPS fails with missing symbols [Henry N.] #1107: buildfix for showpolicy.c when using gcc 4.5 by PaweÅ‚ Zuzelski #1108: gcc-4.5.0 enum warning fix [PaweÅ‚ Zuzelski] #1110: rightsubnet=vhost:%priv,%no not working as expected for non-natted case fixed by new #1004 fix [Mika Ilmaranta/Tuomo] * Fix for protostack=auto when KLIPS or NETKEY is not compiled in [Paul] * Fix for compiling without XAUTH (introduced with remote_peer=cisco support) [Thomas Geulig] * Fix %prompt for encrypted X.509 private keys [Harald] * Fix plutodebug=natt being accepted just like whack --debug-natt [Tuomo] v2.6.25 (Mar 21, 2010) * Google Summer of Code 2009 project for osxApp merged in [Paul] code contributed by student Jose Quaresma and mentor Stefan Arentz * Google Summer of Code 2009 project for livetest merged in [Paul] code contributed by student Daniel Snider and mentor Paul Wouters * Added exceptsocket NULL kernel_ops for non-bsd stacks [Paul] * Remove hardcoded sql: from nss db path (showhostkey, rsasigkey) [Tuomo] * Remove version from README.nss [Tuomo] * Fixed obvious errors on fedora and centos5 rpm specs [Tuomo] * Remove --key option from showhostkey [Paul] * Fix for NAT-T vendorid payload on some ARM processors [dhr] * Fix reference to unused file in README.nss [Tuomo] * Fix 'ip' failure when built against libcap-ng [Kyle McMartin] * Split networking support for remote_peer_type=cisco [Avesh] * Fixup for compiling with broken version of nspr [Avesh] * Update ipsec.conf man page [Tuomo] * In rare circumstances, DPD could kill an active tunnel [Shinichi Furuso] * Compile fixes for NETKEY without KLIPS [Ajay.V.Sarraju] * Fix tcpdump operation on KLIPS/ipsecX interfaces [David] * Report NETDEV_TX_BUSY when klips is overloaded with requests [David] * Fix usage of KLIPS_IP_SELECT_IDENT to prevent kernel trace/warnings [David] * Auth corruption due to unprotected data in sha1 (work_space) [Shinichi Furuso] * Correct locking for SA tables in pfkey interface [Shinichi Furuso/David] * Add locking to PRNG to prevent possible corruption [Shinichi Furuso/David] * Fix oops on held packets [David] * Implement remove_orphaned_holds for NETKEY [Tuomo] * Fix _plutorun to use standard restart option for ipsec setup [Tuomo] * Disable auto skb_dst_release so that icmp_send works [Ronen Shitrit/David] * Fix for unloading KLIPS module on latish kernels [Ronen Shitrit] * Fix init script default not to start up on boot by default [Tuomo] * Do not store XAUTH password in a variable if read from the prompt [Avesh] * spi/spigrp/tncfg blindly assumed KLIPS. Give nicer error output [Avesh] * Fix for _updown.netkey not being able to delete route [Tuomo] * Fix bad bare_shunt entry that break tunnel routing [David] * Fix oops when network driver doesn't support all header_ops [David] * Fix for hardcoded hmac 96 bits length [Avesh] * Check for clrngd as well as rngd in ipsec verify [Paul] * Fix default value for ikev2 in ipsec.conf man page [Tuomo] * Support for USE_TRANSPORT_MODE in IKEv2 [Avesh] * Fix fox implicit DSO linking with NSS [Avesh] - redhat bz#565140 * Fix various spelling errors [Harald] * Fix for leftid=@[foo] notation [Michael H. Warfield] * Interop issue with Cisco where with XAUTH and ModeConfig we expected ISAKMP_CFG_REPLY but we got ISAKMP_CFG_ACK [Paul] * Support for receiving Cisco dns and domain settings and updating /etc/resolv.conf. Requires remote_peer_type=cisco [Avesh] v2.6.24 (Jan 8, 2010) * Give clear warning about missing defaultroute [Tuomo] * Fix to allow ";" in the ike/esp parameters as per man page. [Avesh] * Fix for DPD with NETKEY [Frank Eberle] * Make initscript LSB compliant [Avesh] * Fix for compiling with nss and broken nspr header [Elio Maldonado Batiz] * Do not set the IKEv2 Critical flag for payloads defined in RFC 4306 [Avesh] * Client side support for Cisco load balance directives in IKEv1 [Avesh] - new keyword: remote_peer_type=cisco * Update ipsec_setup man page to match setup changes [Tuomo] * Zeroize ISAKMP and IPsec SA's when in FIPS mode [Avesh] * Initial contact from Windows/l2tp would fail once before succeeding [David] * KLIPS compiles on all recent (up to 2.6.31) kernels [mcr] * KLIPS fixes for 2.6.32 [david/paul] * Fix for mixed IPv6 in IPv4 and vice versa tunnels [Heiko Hund] * Fix for NETKEY on kernels 2.6.26+ [Andreas Steffan] * NAT-OA fixes [David] * Fixup cryptoapi sg_set_page for older kernels [David] * Honour kernel build verbose setting via V=1 [mcr] * Change NAT-Traversal support log message (It's not a patch) [Tuomo] * Some programs were installed twice causing .old files [Avesh] - This is redhat bugzilla #546024 * lwdns.req.log moved from /var/tmp/ to /var/run/pluto/ [Avesh] - This is to avoid an SElinux AVC Denial * Fix compilation so it does not require xmlto [paul] * Fix NSS by removing extra sql: from NSS db directory name [Tuomo] (sql: syntax not supported on RHEL/CentOS nss version) * Move NSS debug logging to DBG_PARSING [Tuomo] * Bugtracker bugs fixed: # 428: KLIPS NULL encryption patch (through cryptoapi) #1004: L2TP broken with NAT'ed clients [dhr/Tuomo/Paul] #1053: typo in notification sending routine [Seong-hun Lim] #1055: init script hangs on startup with semi-broken shells [Michael Smith] (eg busybox and debian's new default /bin/dash shell) #1056: setup script start_stop() checks for filesystem writability #1067: openswan fails on systems not supporting popen() [Jonathan Miller] #1072: Compiling with USE_VENDORID=false fails [paul] v2.6.23 (Sep 8, 2009) * Support for dropping unneeded capabilities using libcap-ng [Avesh] (Changed using USE_LIBCAP_NG= in Makefile.inc) * Additional ASN.1 parser checks by David McCullough [David] * PSK support with USE_LIBNSS [Avesh Agarwal] * Allow multiple different PSK road warriors with Aggressive Mode [David] * Additional KLIPS debugging can be enabled in /proc/net/ipsec_saraw [David] * Extended fipschecks [Avesh Agarwal] * auto=route tunnels could fail due to an Opportunstic Encryption bug [David] * passthrough routes on NETKEY where missing a a policy [Michael H. Warfield] * The init script was mistakenly installed twice, once as 'setup' [Paul/Harald] * LSB compliance error in initscript (debian bug#537335) [Petter Reinholdtsen] * Fix for old style nat-t patch on newstyle 2.6.23+ kernel [Paul] * ipsec verify now returns non-zero when an error is encountered [Paul] * Fix for ipsec whack --crash crasher [David] * Partial fix for #1004. We no longer drop the port from protoport= [dhr/Paul] transport mode L2TP now works again for the non-NAT'ed case * Fix for size (XXX) differs from size specified in ISAKMP HDR (YYY) [David] * Removed old USE_SMARTCARD code. Smartcards are now supported via NSS [Paul] (not all code was properly #ifdef'ed, so a few changes outside #ifdef SMARTCARD were needed) * Prevent aggressive mode tunnels losing phase2 [David] * Various fixes to eroutes [David] * Bugtracker bugs fixed: #1044: openswan.spec file builds an RPM that is missing lwdnsq [Joe Steele] v2.6.22 (Jun 23, 2009) * Malicious X.509 certificates could crash the asn.1 parser. Found by Orange Labs vulnerability research team. Patches via an irresponsible 0-day public announcement by Andreas Steffen (this is CVE-2009-2185) * NSS support via USE_LIBNSS updated [Avesh Agarwal] * Added USE_FIPSCHECK. [Avesh Agarwal] * NAT-T cleanup (no nat-t patch needed for >= 2.6.23) [Harald Jenny/David] * Enabled USE_DYNAMICDNS per default. Disabled USE_LWRES. [Paul] * Fix for gcc 4.4 errors [Avesh Agarwal] * AVC Denail with /var/tmp and openswan ipsec service [Avesh Agarwal] (see https://bugzilla.redhat.com/show_bug.cgi?id=489113) * misc. fixes to the build system [mcr] * Updated various Copyrights [Paul] * Fix for DYNAMICDNS when dns name was unknown on initial load [David] * Fix for ttoaddr when passing AF_INET/AF_INET6 [David] * newer CA's (openssl) now use a crlnumber. Create one with 01 [Paul] * Fixes to new nat-t code (HAVE_UDP_ENCAP_CONVERT ) [mcr] * Some ipsec_tunnel KLIPS cleanups [mcr] * Implement a fallback to SW for failed HW requests [David] * Make sure that ipsec starts after the crypto layer [David] * Fix compilation without OCF and cryptoapi instead [David] * Fixes to compile with 2.6.29 [David] * Fixed to compile on 2.6.30 [Harald Jenny] * Fix for the default assigned of "ipsec0" to all packets [David] * Fix for concurrent ISAKMP negotiations from different hosts to a single host with nhelpers>=1 [Anthony Tong] * UDP port 501 encaps to interop with Lucent in contrib/lucent Contributed by Rolando Zappacosta * Various warnings fixed in pluto [Gilles Espinasse] * Bugtracker bugs fixed: #1031: Fail to compile KLIPS module on RHEL5.3 or CentOS5.3 [Mark Keir] #1030: aggressive mode & dead peer detection fails [Tim Horsburgh] #1023: Oops due to improper ipsec_sa destruction [Nick Jones] #1036: sysctl variables are not correctly set anymore [David] v2.4.15 (Jun 25, 2009) * Fix for CVE-2009-2185 X.509 ASN.1 parser crasher [Andreas Steffen/Paul] v2.6.21 (Mar 30, 2009) * Fix for CVE-2009-0790 DPD crasher [Gerd v. Egidy/Paul] * Fix remaining SADB_EXT_MAX -> K_SADB_EXT_MAX entries. ["bencsathb"] * Fix ipsec setup --status not showing amount of tunnels with netkey [Tuomo] * Bugtracker bugs fixed: #1016: rightid=%fromcert without rightcert causes crash v2.4.14 (Mar 30, 2009) * Fix for CVE-2009-0790 DPD crasher [Gerd v. Egidy/Paul] * Fix for CVE-2009-1121 ipsec livetest tmp file "issue" [Paul] * Bugtracker bugs fixed: #986: Compile-Error and Debugging in 'linux/net/ipsec/ipsec_alg_cryptoapi.c' v2.6.20 (Feb 9, 2009) * Added support for USE_NSS (default false) [Avesh Agarwal] * USE_IPSEC_CONNECTION_LIMIT (default false) support for those who have to deal with export restrictions [David] * Added "metric=" keyword to the conn section to allow host failover from another interface to ipsec using route management. [David] * Split crypto calls off into liboswcrypto for easier FIPS handling [David] * Fix sprintf warning in init_crypto_helper [Owen Jacobson] * KLIPS could not be unloaded (requires updated nat-t patch) [David] * Fix crasher with disassociated pending (async) crypto requests [David] * Make pluto more verbose on aborting for embedded systems [David] * Fix for ipsec_kversion.h on kernels > 2.6.22 non-RHEL/SLE [David] * New parser was missing keep_alive= and force_keepalive= options [Paul] * Fix for ipsec whack --listevents [Shingo Yamawaki] * Fix compiling without OCF [David] * Fix for using kernel cryptoapi algs causing bad packets [David] * Fix ESP+IPCOMP processing [David] * Only calculate (expensive) irs->sa_len when debug is enabled [David] * Repaired missing code responsible for sending IPCOMP request to peer [David] * Make sure we only set NEXT_NONE on the last VID entry that we add [David] * Fix NETKEY with transport mode and NAT-T [Paul] (does not yet fully fix bug #1004, as the wrong IP (inside vs outsid) is used in the policy) * Fix for KLIPS with NAT-t so decrypted packets do not appear to come from the hardcoded ipsec0 interface [Hiren Joshi] * Send the remote host address to PAM during XAUTH so that it may be used for better logging/authentication purposes at the PAM end. [Ken Wilson] * Using Main and Aggressive mode could pick the wrong policy and fail [David] * Fix for main_inI2_outR2_tail() when compiled without DEBUG [Shingo Yamawaki] * Fix for bogus "discarding packet received during asynchronous work (DNS or crypto)". We were queueing/dropping packets that were needed to get the tunnel going [David] * The pluto event loop behaves more predictable under heavy load. * Fix for sending wrong state/cookies with async crypto [David] * Do not sent duplicate status changes to the stats daemon [David] * Disable the warning if DH operations take more than 200ms [David] * Use K_SADB_EXT_MAX, not SADB_EXT_MAX in eroute.c [Carsten Schlote] * Fix for fmt_common_shell_out() using long PLUTO* vars [Carsten Schlote] * Bugtracker bugs fixed: #1015: no building of ipsec.conf.5 manpage on 2.6.20dr2 #1018: ipsec eroute --clear segfaults (KLIPS) [Carsten Schlote] #1004: [partial fix] ipsec/l2tp server behind NAT/port forward broken [Paul] #1014: compress=yes on initiator does not propose IPcomp [David] #0982: kernel panic with compression=yes [Florian Westphal] #0949: not able to set nhelpers=0 [Shingo Yamawaki] v2.6.19 (Nov 24, 2008) * Fix for L2TP/IPsec with Windows machines having their packets discarded by accident [Hiren Joshi] * Workaround for bad "%v:" virtual_private= entries [paul] * Fixes to interop with SoftRemote/aggressive mode [David McCullough] * Fix for ERROR: Module xfrm6_tunnel is in use by ipcomp6 [paul] * Fix for using MODPROBE=insmod where insmod does not support -q [paul] * Enable all wins/dns options as specified in man pages [david] * build support for all WINS/DNS options as mentioned in the man pages [david] * Removed obsolete keywords: firewall (linux 2.0), spibase, spi,espenckey, espauthkey and espreplay_window (manual keying) [paul] * Fix unnecessary and bogus connection switching with NAT [Shingo Yamawaki] (this might relate to several reported bugs in the tracker) * Added cisco-decrypt utility for PCF obfuscation in contrib/ [paul] * Fix for crasher when the leftcert= filename was not found [paul] * Patch for "route already in use" when using two different IP's to talk to the same remote IP using two tunnels [Avesh Agarwal] * Fixes to init scripts [Avesh/Tuomo] See also: RedHat bugzilla #466861. * Bugtracker bugs fixed: #992: keyingretries default changed from %forever to 3 [ken] (bug was introduced in 2.6.x) #981: plutodebug=all klipsdebug=all not operate. [paul] #994: Not having leftid=%fromcert results in a pluto segmentation [paul] #1003: virtual_private broken? [paul] v2.6.18 (Oct 6, 2008) * Fix for compiling KLIPS on RHEL/Centos 2.6.18-92.1.10.el5 [dhr/paul] * Fix in deleting connections that might have caused some of our Delete Notifies to have gotten lost. Introduced in openswan 2.5.01 [paul] * Rekey= inverted yes/no, causing rekey=no to be rekey=yes [Shingo Yamawaki] * Some memory leaks / refcount fixes [Shingo Yamawaki] * Removed most of #ifdef CONFIG_KLIPS_DEBUG conditionals. We now always compile in DEBUG support. [paul] * No longer use the assembly version of des_encrypt (dx86unix.S). It is i386-i686 specific, requires framepointers and does not work with CONFIG_REGPARM=y, which is the unconditional default for 2.6.17+ [paul] * Fix memory leak when we run out of descriptors [David McCullough] * Various memory leak fixes for pluto (from #macosx) [Ilia Sotnikov] * LEAK_DETECTIVE should report better now [Ilia Sotnikov] * Add support for USE_DMALLOC [Ilia Sotnikov] * Update stats to show dropped packets [David McCullough] * Allow session migration of OCF devices [Brad Vrabete] * DNS/WINS ModeConfig fixes [David McCullough] * refineconnection bug fix. This might cover various problems where the right conn was not picked (eg rightca="%any" workaround, but perhaps also some rekey issues) [paul] * unregister_netdevice: waiting for ppp2 to become free. Usage count = -1 on kernels < 2.6.24 [Martin Schiller] * Fix for parallel building, eg with rpmbuild [tuomo] * Bugtracker bugs fixed: #989: Patch for fixing type-punned compiler warnings [Alin Nastac] #979: Two errors in debian/ packaging files (fix included) [ruben] #978: ipsec.conf man page has typo in virtual_private sample line [tuomo] #975: ipsec_setup: Unknown socket write error 96. [paul] #231: In Aggressive Mode with NAT-T,initiator should switch port [hiren joshi] #228: Problems with %any matching in ipsec.secrets? [David McCullough] #984: OpenSwan 2.4.13: Wrong ipsec_dev_get(x) function for Kernels < 2.6.24 v2.6.17 [will be skipped due to bad tag] v2.6.16 (Aug 18, 2008) * Merged in David McCullough's OCF patch [david/paul] Requires kernel patch, see http://ocf-linux.sourceforge.net/ * dpdaction=restart_by_peer support added [david] * dynamic dns support (do dns lookup at restart conn, eg after dpd) [david] Uses USE_DYNAMICDNS= * Added USE_SINGLE_CONF_DIR= [david] * KLIPS support for 2.6.24 / 2.6.25 [david] * Fix for "Unknown sysctl binary path" [david] * rekeyfuzz is percentage, not integer [david] * Added HAVE_STATSD= support to log state changes (for webgui etc) [david] (disabled per default) * Wrapper to handle more then 2048 NETKEY tunnels [david] * fixes for parser warnings [dhr] * Fix rmmod calls not to use -s since busybox rmmod does not support it [paul] * Fixes to KLIPS for newer 2.4 kernels [greg/davidm] * Road Warrior behind NAT - Aggressive Mode: wrong NAT-T decision [hiren joshi] * Added documentation for leftxauthusername= and XAUTH passwd support [paul] * Bugtracker bugs fixed: #977: KLIPS doesn't work when wan interface is a tagged vlan interface Regression from 2.4? [Tino Keitel / Krisztian KOVACS] #972: Aggressive mode connection breaks after DPD timeout for NATed peer #965: xmlto man fails to generate ipsec.conf.5 man page [tuomo] v2.6.15 (Jul 4, 2008) * Patch to support NETKEY backport on Debian kernels [Rene Mayrhofer] * Fix a crasher when using right=%any with plutodebug=controlmore [paul] * Fix a crasher when deleting connections in NETKEY [ken] * Added disable_port_floating support to scripts and parser and repair the default back to allow port floating [paul] * Change (back) defaults of plutorestartoncrash and uniqueids from no to yes. The new parser mistakenly did not set these [paul] * Revert af family code in find_host_pair causing some connections to not be found in find_host_connection2() [paul] * Fixes to _updown.mast, _realsetup (mast) and startklips [paul] * Fixed to saref code so we can build on OSX again [paul] * Use PREROUTING instead of OUTPUT/FORWARD for mast [mcr] * NETKEY support for eroute_idle using get_sa_info() [herbert/andreas] * Do not send DPD "R_Y_THERE" when eroute not idle [andreas] * Support for Relative Distinguished Name "unstructuredName"/"UN" in ID_DER_ASN1_DN identities (eg leftid="UN=John Doe") [andreas] * Removed forwardcontrol= and rp_filter= options. Ignore if present in config file. Use /etc/sysctl.conf [paul] * Fix for left="%defaultroute" when using NETKEY [tuomo] * Fix for KLIPS on SMP systems (missing SOCKOPS_WRAP for pfkey_ops) [dhr/paul] * Merged in some IPsec SAref related code [mcr/paul] * Merged in packaging/suse for building rpms on SLES [paul] * Bugtracker bugs fixed: #784 / #928 : openswan (pfs=yes) to vista (pfs=no) crasher [paul/dhr] #934: mem leak in klips:ipsec_rcv_decap [Wolfgang Nothdurft] #935: 935: Openswan 2.6.14rc5 refuses to start after carsh [paul] #939: Openswan 2.6.14rc5 crashes on startup if dns is not reachable [andreas] (curl issue on 64bit platforms when dns is not available) #953: disable_port_floating defaults to yes and config parser... [paul] #954: patch to support DEFAULT_SOURCE using netkey [mdw21] #957: pluto always gets --disable_port_floating parameter... [paul] #963: rp_filter=%unchanged option causes assertion failure [paul] #964: make -j4 programs fail [tuomo] v2.4.13 (Jun 26, 2008) * Fix a memory leak by removing unused variables alg_esp and alg_ike [dhr] * Recognise and log unsupported IKEv2 exchanges [paul] * Bugtracker bugs fixed: #198: Connection not coming up automatically, plutowait=yes workaround v2.6.14 (Jun 6, 2008) * Fix for integ vs prf mixup [herbert/antony] See: https://bugzilla.redhat.com/show_bug.cgi?id=439771 * Merged in v2.5.18 (see entries below) [paul] * Merged in v2.5.17 (see entries below) [paul] * Merged in v2.5.12-v2.5.16 (see entries below) [paul] * NETKEY and crypto modules did not get loaded automatically [paul] * Updated "clear" policy file for L root nameserver's new IP for OE. [paul] * Added testcase interop-ikev2-strongswan-06-aes192 [paul] * Removed "interfaces= is ignored when using the NETKEY stack" warning as it caused confusion and a wrong patch in Fedora 9. [paul] See: https://bugzilla.redhat.com/show_bug.cgi?id=445179 * Fix for a few warnings of using "en" uninitialised [dhr] * Various fixes on strnat, chdir, fwrite, fgets, etc. [paul] * Fix for a potential crasher when displaying status using certs [paul] * Removed obsoleted and unused hardware random related defines [paul] * Maintenance on IKEv2 properties and names [paul] * IKEv2 rekey fix for initiator [herbert] * KLIPS fixes to compile on 2.6.24+ [david/paul] * Added AES-CCM support [herbert] See: https://bugzilla.redhat.com/show_bug.cgi?id=441383 * Support for KLIPS on 2.6.24+ [david] * Bugtracker bugs fixed: #943: Openswan 2.6.14rc5 pluto crash at ikev1_main.c:1145 #936: EXPECTATION FAILED kernel_ops->eroute_idle != NULL [paul] #930: 'best.len' and 'cur.len' may be uninitialised. [Michal Nazarewicz] #781: %defaultroute detection broken on netkey for 2.5.x [paul] * Above 2.5.x merges brings in userland IPsec SAref support. Requires kernel support, currently only supported with USE_MAST.(KLIPSNG) Also requires kernel modification to add IP_IPSEC_REFINFO support This adds support for overlapip, allowing multiple clients behind the same NAT router and multi clients on identical IP's behind different NAT routers. For possible deployments, see doc/ipsecsaref.png v2.6.13 (May 17, 2008) * RFC4306 Section 3.3.5 IKEv2 Attribute KEY_LENGTH support [herbert/paul] See: https://bugzilla.redhat.com/show_bug.cgi?id=444166 https://bugzilla.redhat.com/show_bug.cgi?id=439771 * Support for ESP_NULL and AH_NULL [herbert/paul] See: https://bugzilla.redhat.com/show_bug.cgi?id=442955 https://bugzilla.redhat.com/show_bug.cgi?id=442956 * Close on file descriptors on exec (fixes SElinux avc denials) [Neil Horman] See: https://bugzilla.redhat.com/show_bug.cgi?id=442333 * Fix a memory leak by removing unused variables alg_esp and alg_ike [dhr] * linux/include/crypto renamed to linux/include/klips-crypto [paul] * Fix for IKEv1-only policies attempting bogus IKEv2 rekeys [Miloslav Trmac] * Bugtracker bugs fixed: #198: Connection not coming up automatically, plutowait=yes workaround [tuomo] #622: pluto memory leak [dhr] #916: KLIPS kmod fails to compile 2.6.22 based kernel (...) [paul] #917: pluto fails to compile when using pam. xauth [Tamas Pal] #922: pluto crashes on rekey failure [Miloslav Trmac] v2.6.12 (Apr 21, 2008) * Add aes-*-modp1024 proposals to default responder policy db [antony] This is bug https://bugzilla.redhat.com/show_bug.cgi?id=439985 * Fix for ikev1 continuation segfault (only the first helper's continuations were cleaned up properly (eg. on dpd, sa expires..) [Anthony Tong] * Redid fix for leftsourceip/rightsourceip getting deleted [paul] This is bug https://bugzilla.redhat.com/show_bug.cgi?id=432821 * As per RFC 4309, use modp2048 as default for PSK with IKEv2 [paul] Relates to https://bugzilla.redhat.com/show_bug.cgi?id=441588 * Added workaround for INITIATOR/RESPONDER keys being swapped [herbert] * Preliminary work to support IKEv2_ENCR_AES_CCM__* algos [paul] * modprobe the AES ccm kernel module on startup [paul] v2.6.11 (Apr 8, 2008) * Fix state machine to pick proper Responder STATE_UNDEFINED state when receiving R1 NO_PROPOSAL_CHOSEN [dhr/paul/antony] * Fixes to some enum tables that caused (null)'s in logs [dhr/paul] * Starting the prf+ counter from 1 instead of 0 [herbert] * Removed wrong Gr check [antony] * Added IKEv2 NO_PROPOSAL_CHOSEN processing [antony] * Clone st_ni/st_nr chunks for child SA [herbert] * Various smal logging changes - mostly to fix (null)'s [paul/dhr] * AUTH_ALGORITHM_HMAC_SHA2_* are now logged properly [paul] * interop-* testcase output updated [paul] v2.6.10 (Apr 3, 2008) * Includes fallback from IKEv2->IKEv1 [mcr] * IKEv2 bid-down attack recovery [mcr] * changes to I1 retransmission timers [mcr] * Only check for bid-down when POLICY_IKEV2_PROPOSE to avoid two ikev2 capable ikev1 instances from false detecting a biddown [paul] * Fix ikev2_trans struct (redhat bug #438826) [dhr/paul] * Revisit of 2.6.06 NOTIFY crasher - fixed again [paul] v2.6.09 (Mar 10, 2008) * Completed IKEv2 6msg exchange support [antony] v2.6.08 (Mar 9, 2008) * IKEv2 6msg exchange (responder, partially for initiator) [antony] * IKEv2 notify support [antony] * Some pullups from #testing related to NETKEY [paul/tuomo] * Added force_busy option for testing 6msg exchange [paul] * OSX compile fixes [paul] * sourceip= option fixed with NETKEY [paul] * ipsec setup restart with NETKEY fix [paul] * NETKEY, strongswan, racoon2 support in test harnass [paul/antony] v2.6.07 (Feb 8, 2008) * IKEv2 retransmit fixes [mcr] v2.5.18 (not released) * Do not use the KMEM_CACHE macro for now, so KLIPS works on 2.6.23 [paul] * Sha2 support for X.509 certificates in pluto [Daniel Mueller] * Various memory leaks * uclibc workaround for malloc(0) abort. Fixes to not malloc 0 [paul] * Bugtracker bugs fixed #917: pluto fails to compile when using pam. xauth [folti] #919: Invalid memory access in show_dnskey of showhostkey.c [paul] v2.5.17 (Feb 28, 2008) * Implemented netlink_shunt_eroute() [paul] * Simplified _updown.netkey [tuomo] * Bugtracker bugs fixed #460: Fix bogus header with delayed MAIN I2->R2 [Herbert Xu] #496: kernel_alg_esp_auth_ok() call fixed - [gernot] #761: pluto crashes after removing interface [Tillman Baumann] #897/731: crash in alg_info_snprint() - ["Deep Throat"] #889: backport from #ikev2 branch to fix ipsec_delete_sa with NETKEY [mcr] v2.4.12 (Feb 19, 2008) * Partial fix for 2.6.24 kernels (new proc_net macro and dev_get_by_name arg), no fix yet for changed dev struct [paul] * Fix for lingering 'dir out' XFRM policy when using NETKEY [paul] * Various memory leaks [gernot] * null_alg was not fixed for linux autoconf [paul] * enable HAVE_NEW_SKB_LINEARIZE for Suse Linux SLES10 SP1 [nicole haehnel] * Bugtracker bugs fixed #419: Use of "source" vs "." (breaks on Debian /bin/dash) [paul] #496: kernel_alg_esp_auth_ok() call fixed [gernot] #538/#892: IP compression proposal lostin negotiation [sscholz@astaro.com] #771: various memory leaks #814: KLIPS build fails against 2.6.22 kernel (linux.ip.h for iphdr) [sedrez] #816: CRYPTO_API error (KLIPS_ALG was undefined) [paul] #888: dir out XFRM bug #889: Backport of #ikev2: pluto crasher on --delete connection with netkey #891: passert(sr->eroute_owner ==SOS_NOBODY) crasher [mcr] v2.5.16 (Feb 18, 2008) * Implemented netlink_shunt_eroute() [paul] * Simplified _updown.netkey [tuomo] v2.6.06 (Feb 8, 2008) * Added IKEv2 X.509 CERTREQ [antony] * Interop fix for IKEv2 PSK - Use correct IETF Key Pad without \0 [paul] * Fixed a few IKEv2 related crashers on receiving a NOTIFY in R1 [paul] v2.6.05 (Feb 1, 2008) * Added IKEv2 X.509 CERT [antony/paul] v2.6.04 (Jan 25, 2008) * Added IKEv2 PSK AUTH [antony/paul] v2.6.03 (Jan 10, 2008) * Added IKEv2 RSA AUTH [mcr] v2.6.02 (Dec 20, 2007) * workaround for openswan.spec file v2.6.01 (Dec 18, 2007) * IKEv2 support v2.4.11 (Dec 4, 2007) * Fix typo in startklips bugfix for #834 * Fix display of nat-t vendor code picked [mcr] * Fix for KLIPS on 2.6.23.1 without CONFIG_NF_CONNTRACK* [paul] * Sync'ed openwrt packaging with upstream [paul/nbd] #stable * Merged in XAUTH DNS/WINS server-side patch from Anna Wiejak [paul] See: http://popoludnica.pl/?id=10100110 * Various fixes to the scripts for NETKEY [paul] * KLIPS support for the 2.6.23+ UDP ENCAP sockets [mcr] Userland support not yet finished. This should obsolete the NAT-T patch when finished. * incorporated changes between 2.4.8 and 2.4.9 * incorporated changes between 2.4.9 and 2.4.10 * Notice and gracefully fail to load KLIPS when we try to load esp/ah/ipcomp protocol and another module already has registered these (eg esp4, ah4, ipcomp) [paul] * Fix for KLIPS NAT-T dropping all packets on 64bit big endian machines [dhr] * FIx for KLIPS on 2.6.23.1 without CONFIG_NF_CONNTRACK* [paul] * Bugtracker bugs fixed: #600: multiple definitions of passert_fail when cross-compiling. #852: dd_connection() fails with ...not AH+ESP for type=passthrough conns #708: vanilla kernel-2.6.19, KLIPS compile error (sock_unregister) [sergeil] #654: XAUTH strips space out of username/password + patch [Dustin Lang] #641: Herein patches to fix warnings if -Wshadow is used [andygay/paul] #580: kernel 2.4.x cryptoapi broken [espakman] #582: Cannot initiate on demand a connection with traffic selectors [Ilia Sotnikov] #590: serpent lib used private kernel header [paul] #544: the following error should only show up for x509 debugging: ... [paul] #185: Deadlock in function "scx_release()" daemon pluto.(SMARTCARD) [Kurodo] v2.5.15 (Aug 14, 2007) change ipsec_breakroute to permit non-existent eroute's to be replaced. fix for NAT-T negotiation with IP address changes during negotiation. adjusted addconn to support nat-t debug keywords. v2.5.14 (Jul 19, 2007) failed attempt to fix ipsec_breakroute. fixed leftsendcert= to be implemented in keyword parser. introduced startnetkey functions. UML kernel configuration canonicalization updated. v2.5.13 (May 7, 2007) move DNS lookups from libipsecconf into pluto, where they belong. DNS lookups are still only done once during conn load time, and are done synchronously. v2.5.12 (Apr 30, 2007) A fix to detect that XEN has been patched into the kernel, and set some of the 2.6.18 changes. never log starter_log() things to stdout, they always go to stderr. when a packet is passed through, do not call NF_IP_LOCAL_OUT, as it has already passed through the output hooks, and doing it again, confuses things causing ip_route_me_harder() which creates a look, since it does the flow lookup again. (This doesn't happen if the kernel hasn't got XFRM support) fixed parsing of config file so that "version 2" is accepted. fixed addconn to respect "right/left"sourceip=, new test case sourceip-01 fixed processing of "first"/"last" packet for %trap/%hold conns in KLIPS, it now properly forwards the packets when the packet is released. v2.5.11 (Apr 19, 2007) Some fixes in KLIPS for "ipsec eroute --clear" bug. It is not clear why this suddendly became an issue, or if it would have been an issue previously, given the right compiler optimization. v2.5.10 (Apr 2, 2007) Includes fixes for xmlto generation for _confread directory. v2.5.09 (Apr 2, 2007) Minor fix to build process, updated CHANGES file. v2.5.08 (Apr 2, 2007) Correct release. Includes some changes to permit OE to work without nexthop, however this seems to cause it to return an unreachable on the first message. v2.5.07 -dud due to release script error. v2.5.06 (?) set LANGUAGE, LANG and LC_ALL in setup script. change OE off by default note and scripts. Merge of additional code from 2.4. v2.5.05 (Feb 14, 2007) 2.5.03 and 2.5.04 were not properly released, and 2.5.05 now is properly released and includes below items v2.5.04 (?) zero peer_ca to avoid crashes. (include glob's may still not work correctly) v2.5.0sbs5 (Dec 12, 2005) fixed issues with libwhack not getting built with VIRTUAL_IP. adjusted programs/pluto/Makefile to depend upon libraries better v2.5.0sbs4 (Dec 11, 2005) When a template conn is instantiated for a phase 1 configuration, it may still need to be adjusted to a virtual IP address. In addition, change the order of the virtual IP address setting and the port-wildcard processing. This patch also provides some additional debugging of the proposal that is actually processed by the machinery. tests for L2TP+X.509 L2TP configuration --- 2 clients behind the same NAT with certificates that need to have their connection both instantiated (in phase 1) and virtualized (in phase 2). v2.5.03 (Jan 10, 2007) ipsec.conf parsing should ignore keywords that start with x- they are a form of structured comment. added in forceencaps= keyword. process wildcards with glob() in include statements. v2.5.02 (?) fixed bug in ipsec.conf parser, where it could not read values that had = in them (such as base64 encoded keys) fixed bug in key continuation code that could cause a crash if the DNS request timed out after the state was deleted for other reasons. v2.5.01 (Jan 2, 2007) merged xauthusername code base + multinet tests in. removed /dev/hw_random from list of valid random sources on linux. use "rngd" instead to feed /dev/random. v2.5.00 (Nov 2, 2006) fixed various bugs with lifetime values in ipsec.conf parser AES-128 (group 5, MD5 or SHA1 for PRF) is now accepted for phase 1, and it is now the preferred cipher as well. This should be the case for Main mode, Aggressive mode, and for XAUTH client and XAUTH server, and PSK and RSA sig mode. fixes so that starter will now compile move whacklib to lib/libwhack adjust makefiles to work with OBJDIR version of Makefile.program switch to OBJDIR in programs/* and lib/* if it is defined added sanitizer for PID files be smarter about including git version info into version We need to use /dev/urandom first, as it has more random than /dev/random. Otherwise, we run out really fast (within a few minutes) Use endian.h when comiling out-of-kernel patch to turn error about 17/500,0/0 vs 17/0 error with Cisco VPN3000 into a warning. remove test for NAT-T VID vs NATD payload test. It fails for reasons that are unknown at this time, and this check is really being pedantic. MAJOR: use starter code for "addconn" MAJOR: always use OBJDIRs, and compile on Windows (no kernel) MAJOR: includes "Taproom" code --- TCL call outs from pluto at IKE transition states. v2.4.10 (Nov 6, 2007) * Some workarounds for openwrt related to starter and lack of modprobe [paul] * Fix for sock.sk_stamp type change in 2.6.22 [dhr] * Workaround for implementations that propose port 0 for l2tp to allow us to connect to all their ports (instead of only 1701). This happens with Cisco VPN 3000, OSX and Windows XP. This relates to various reported bugs about rightprotoport=17/%any and CK_INSTANCE crashers [mcr] Use the workaround for OSX clients using rightprotoport=17/0 * Backport of fix for xauth name containing a space [paul] * Fix for final next payload in Aggressive Mode [David McCullough] * Fixes for compiling against 2.6.22 [David McCullough / Hugh Redelmeier] (note: NAT-T KLIPS patch will not work on 2.6.23+) * Speed gains in the scripts on systems with many interfaces [David McCullough] * passert declaration fix [David McCullough] * A missed nfmark -> mark case in ipsec_sa.h [David McCullough] * Fix for ktime_to_timeval to use proper kernel versions [paul] * Added back -DCONFIG_KLIPS_ALG in KLIPSCOMPILE, which we require when not building KLIPS with David's OCF patch [paul] * Added SElinux patch in contrib/ [Venkat Yekkirala] * Bugtracker bugs fixed: #449: 17/%any is a template conn problem [mcr] #708: vanilla kernel-2.6.19, KLIPS compile error (sock_unregister) [sergeil] #796: can't compile 2.4.8 on kernel 2.4.34 (module_param fix) [sergeil] #802: Error: "our client ID returned doesn't match my proposal" [mcr/paul] #813: incorporate tuomo's lsb patch [tuomo] #824: defaultroute detection fails with PPP default route [sergeil] (this is also the bug introduced in 2.4.9 that causes failed subnet tunnels) #855: Pluto restart impossible on busybox [paul] v2.4.9 (July 17, 2007) * Fix for Aggressive Mode with NAT-T (no negotiation in aggrmode) [mcr] * Integrated most openwrt workarounds - tested on whiterussian [paul] * Typofix for smartcard support [andreas zwicker] * Fix for when responder PSK incorrectly uses pfs and has nhelpers=0 [Matthias Haas] #801: Patch for fixing type-punned compiler warnings [Alin Nastac] #811: Patch for using custom algs with CONFIG_KLIPS_ALG [iamscard] #812: Bogus defaultroute nexthop for PPPoE (& PPP?) [BruceS] v2.4.8 (May 24, 2007) * Added Andy Gay's ipcomp with esp= fix in contrib/ipcomp/ (see #538) * Added and enabled DISABLE_UDP_CHECKSUM until the cause of this bug has been fixed. This is bug#601. Found by Frank Vogt * fix for ikeping reporting wrong percentge of lost packets [Mark-Andre Hopf] * Fix for busybox' ifconfig (doesn't support 'inet') [Dave Chuha] * Fix for compiling on 2.6.20 (sk_buff's nfmark is now called mark) * NAT-T patch update for 2.6.20 * NAT-T patch broke NAT-T for NETKEY,even with CONFIG_IPSEC_NAT_TRAVERSAL unset * Fix for too small ike string buffer ipsec auto --status output [paul/dhr] * Fix for Aggressive Mode and NAT-T port floating, based on RedHat patch [paul] * Fix for Aggressive Mode and NAT-T (#491) by Delta Yeh * ikeping waits milliseconds instead of seconds, patch by Mark-Andre Hopf * Workaround for NETKEY's unlimited acquire stream by Michael Smiths (#726) * Some vendor ID's for Vista and Cisco VPN 3000 [jacco] * backports from git #git 5735f731ed474dbb22fce2f5bc0a9f5e1fea2994: rewrite of available worker code from egbert@ [mcr] #git c75967b03b2c478a612aef4ccb7e5dff6e4bdaf5: dpdaction=restart fix [mcr] #git 41e54a2684dc809d7952e816860ea646a3194a72: Fix for kernels > 2.6.18 #git c2e23a6e16a55632d618740518d419f3fad3323d: AggressiveMode with nhelpers=0 fix from Marin Hincks #git 1933710623a33fe8f3229b193721aed005fb87c2: Crasher in printing alg debug #git 9bfb2794bd9c239dfe9e9617616eaf6fc389de57: uninitialized sockaddrs fix #git e199785d8e11687534569b04a3e0a6956b2086b8: set helper # in child * bugtracker bugs fixed: #723: Bogus Code in pluto_crypt.c [egbert/mt/mcr] #698: Wrong IKE-Algorithm displayed on ipsec auto --status [martin/paul/mcr] original patch by Martin Schiller #719: Fix to authenticate with a smartcard (USB Aladdin eToken) ["pm"] v2.4.7 (Nov 14, 2006) * Remove direct use of /dev/hw* for random on Linux. It is not guaranteed to be secure (FIPS compliant) random [paul] * Fix bugs introduced in 2.4.6 using KLIPS and CryptoAPI on 2.6.17.6+ * fixes for displaying proper NAT-T draft/rfc used [jacco] * Various fixes to lwdnsq [mcr] * Extensively updated man pages [paul] * Added rootservers to the clear policy [idea by mcr] * Fix for pluto to allow NETKEY's ESP_NULL by JuanJo Ciarlante * Added ESP_NULL support to KLIPS by JuanJo Ciarlante (disabled per default) * Support Fedora style default RSA hostkey [paul] * Clarified various log messages * Possible interop fix for Sonicwall * Fixes to _startklips and logging cleanup [paul] * Fix for handling defaultroute to a p-t-p interface without gw ip. [bleve] - this might also fix #693 * Extended ipsec verify to complain misconfigured hardware random [paul] * Extended ipsec verify to complain about SElinux in enforced mode, until working security policies are known to exist as it breaks with both NETKEY and KLIPS [paul] * Cleanup of crypto module modprobing. It is now silent [paul] * bugtracker bugs fixed: #474 ASSERTION FAILED at spdb_struct.c:1233: trans->attr_cnt > == 4" #642: ipsec_xmit.c and CONFIG_KLIPS_DEBUG [completed fix] #655: /etc/rc.d/ipsec --status breaks connection #671: oops from __module_get during pfkey_create v2.4.6 (Aug 4, 2006) * Fix for VIA Nehemiah to use /dev/hw_random to generate new rsakey (using /dev/random on these chips caused it to block too long) * Various CryptoAPI related fixes. * Removed support for HIPPI which broke compilation on 2.6.16.* * Pull up of fix for rightnexthop->leftnexthop * Added logging when we don't find the right hash bucket * Changed a few x509 log messages to make automatic parsing easier * Unload KLIPS at shutdown again to prevent lingering IPs on ipsecX, also in case KLIPS is inline, and the ipsecX interfaces do not go away, remove IP addresses from IP aliases bound to ipsecX devices. * Fixed typo in ipsec.conf's virtual_private example * Improved protocol detection in ipsec_print_ip() [bart] * Fixed minimum skb length required for ipsec decompression [bart] (This is probably bug #609) * Fix a 64bit bug in compression code [bart] * Removing a left over '#else' that split another '#if/#endif' block in two in ipsec_xmit.c [bart] * MODULE_PARM has been obsoleted for module_param on 2.6.17+ [paul] * skb_linearize API changed in 2.6.18+ [paul] * bugtracker bugs fixed: #452: dpdaction=restart doesn't clear or restart quick mode SAs #537: Compilation will fail with kernel 2.6.14 and klips and CONFIG_HIPPI=y #636: KLIPS and vanilla-2.6.17 compilation error #642: ipsec_xmit.c and CONFIG_KLIPS_DEBUG on 2.4 compile issue [partial fix] #647: compile fails with version 2.4.6-rc2 + vanilla kernel linux-2.6.17.6 #631: KLIPS module does not build with 2.6.17-rc6 kernel #646: NATT + IPCOMP fails on rcv in KLIPS [bart] (This is a generic NATT+ESP bug, not just an ipcomp bug) v2.4.5 (Apr 6, 2006) * Fix for preferring RFC3947 over OSX-workaround by Jacco de Leeuw * Fix for openswan as l2tp server behind NAT by Bernd Galonska * Fix for compiling + working on SMP (including HyperThreaded) machines * Fix for arp_broken_ops relocation in 2.6.16 * Fix for compiling on 2.6.14 kernels * Fix patching against 2.6.15 kernels (NAT-T Patch) * Fix patching against 2.6.14 kernels * Fix for strict mode * Fix for ipsec module unload. Fix by Ankit Desai * Fix for ipsec: Unknown symbol sysctl_ip_default_ttl * Fix for AH hash by Ronen Shitrit * Additions to barf and verify commands for various kernel internals * load hw_random and padlock modules before aes module so hardware routines are preferred over software routines. * allow rightsubnet= with type=transport for L2TP behind NAT. * Refactored natd_lookup / hash code, probably fixes lot of NAT related bugs * Fix for interop with Cisco devices that propose port 0 (eg: VPN3000) * When DPD rcookie is invalid, just warn instead of ignoring entirely * Redid all the DPD log messages * Fix for manual.in to not use a complicated sed line that some embedded sed versions (busybox?) cannot handle. * Fix for NAT-T detection when Openswan is the initiator #401 l2tp connection is not work with 2.6 build in IPSEC #442 Pluto uses wrong port in NAT-D calculation #450 macosx (possible generic PSK+NAT-T rekey bug: eroute already in use. #454 klips module refcount bug (found by Matthias Haas) (prevented klips from unloading on 2.4 kernels) #462 updated patch for Openswan and OS X with NAT-T #509 KLIPS compilation fail with kernel-2.6.14.2 #518 Incorrect physical interface MTU detection #521 KLIPS module crash for kernel 2.6.12+ #545 unnecessary warnings from _updown script, remove weird control character. #558 two machines using incompatible ike= settings still establish a connection. (fix by Matthias Haas ) #560 Pluto crash (memory leak fixes in pluto by Ilia Sotnikov) #563 Error when unload ipsec.ko module "rmmod ipsec" [dupl bug] #568 uninitialized struct in ipsec_tunnel.c could break routing under 2.6 kernels #569 ipsec module unload crasher #573 Openswan fails to compile with NAT_TRAVERSAL=false #574 Openswan fails to compile with NAT_TRAVERSAL=false #2 #581 _Updown script installs direct (scope link) routes even for remote peers/subnets #589 userspace with USE_EXTRACRYPTO won't compile without kernel sourcecode v2.4.4 (Nov 18, 2005) #487 ASSERTION FAILED at state.c:120:IS_ISAKMP_ENCRYPTED(isakmp_sa->st_state) (see http://www.openswan.org/niscc2/) (proper fix in pluto_constants.h) * Fix for kernels having strstr * Various gcc4 warning fixes * disable CONFIG_IPSEC_NAT_TRAVERSAL per default so we can build KLIPS on Fedora systems. * questionable spin_unlock commented out. Might fix reported SMP crashers. * update to permit alg code without module support * Fix for detecting proper kernel source/header directory on fedora * Various bugfixes as reported on http://bugs.openswan.org/ #499: check for module support in kernel for IPsec Modular Extensions #500: recent awk breaks on 'setdefault' command v2.4.3 (-) #487 ASSERTION FAILED at state.c:120:IS_ISAKMP_ENCRYPTED(isakmp_sa->st_state) (see http://www.openswan.org/niscc2/) (incorrect fixed. version not released) v2.4.2 (Nov 13, 2005) * Fixes for compiling on 2.6.14 by David McCullough * Minor fixes to accommodate FC4 2.6.11 kernels. * Fix for compilation of KLIPS on 2.4.x kernels. * Fix for NAT-T on 2.4.31 * Fix for 'short' packets with KLIPS on 2.4.x * Merged in Jacco's l2tp configuration examples * Various bugfixes as reported on http://bugs.openswan.org/ #286 Incorrect links in intro.html #344 netkey-acquire patch #376 install_ipsec_sa and install_inbound_ipsec_sa #486 ASSERTION FAILED at crypto.c:258: key_size==(DES_CBC_BLOCK_SIZE * 3) (see http://www.openswan.org/niscc2/) v2.4.1 * Not publicly released v2.4.0 (Sep 12, 2005) * NAT-T support for KLIPS on 2.6 (Sponsored by Astaro) * Additional Cipher support with KLIPS on 2.6 (Sponsored by Astaro) * Fix for NAT-T/PSK rekey (Ulrich @ Astaro) * Delete _updown.c and _updown.posix versions as they were obsolete * Fixes for aggressive mode and policy mode * Various bugfixes as reported on http://bugs.openswan.org/ #201 pluto not accepting negotiations on port 500 after port floating to 4500 #249 two default routes confuses scripts #261 2 RW's w/DPD behind a NAT kick each other off at rekey time #267 pluto crashes on inbound X.509 roadwarrior #269 informational crasher in demux.c #301 kernel_netkey.c lists invalid ESP algorithm #302 pluto assumes it has 3DES #305 passert_fail (pred_str=0x80b88e3 "st->st_suspended_md->st == st", file_str=0x80b86a0 "state.c" #306 st->st_suspended_md->st == st passert() #316 Patch for ALG support from Astaro #324 Impossible to disable AGGRESSIVE mode #327 pluto nat-t detection on 2.6 without klips nat-t patch fails to disable nat-t #328 ipsec setup fxies for awk compiled with --enable-switch #341 Pluto crashes with: ipsec__plutorun: !pluto failure!: exited with error status 134 (signal 6) #342 fix for 2.6.12 undocumented API fixes for sk_zapped and sk_alloc() (based on fix from Sergeil. #350 fix for passert() at connections.c:1353: isanyaddr(&c->spd.that.host_addr) #355 dpdaction restart fix from Astaro #357 secure_xauth_username_str fix from Astaro #360 checkv199install creates bogus "old" files #361/#363 fix for passert() demux.c:1204: unknown address family in anyaddr/unspecaddr #368 Fix for ipsec --setup --status output and eroute counting #372 Netkey and device labels (eth#:#) #373 _updown_x509 still uses obsolete 'route add' commands #377 pluto crashes processing first connection if nhelpers=0 #380 pluto crashes when sent an IKEPING #381 assertion failure in init_demux if AGGRESSIVE not defined #383 MODP >= 4096 FIX #386 undefined symbols compiling klips as module #387 / #420 pfkey_ops undefined error on SMP kernel compiles. possibly fixed, but may result in SMP unsafe-ness. #342 KLIPS cannot be compiled for 2.6.12+ #415 RPM packaging errors for 2.4 based kernels #416 Need a way to tell if NAT-T is compiled in the IPSec kernel v2.3.1 * NAT-T RFC support (mlafon/mcr) * NAT-T Server Side rewrite - handles rekeying a lot better * NAT-T Client Side rekey bug fixed * Removed HowTo (obsolete) * IPKG packaging updates * Log message updates * dpdaction=restart support v2.3.0 * KLIPS for 2.6 support (Experimental) [ good results on FC3-AMD and vanilla/debian kernel source, but not FC3-intel. Might be the grsecurity patch ] * Aggressive Mode Support (client and server) * IKE Mode Config support (Experimental) * Cisco VPN 3xxx client Interop (Experimental) * Cryptographic helpers framework * Fixes for NAT-T on 2.4.28+ kernels. v2.2.0 * Added RFC 3706 DPD support (see README.DPD) * Added AES from JuanJo's ALG patches * Fixes for /proc filesystem issues that started to appear in 2.4.25 v2.1.2 * Fix loading of 2.6 modules * Fix for snprintfs() in /proc, new for 2.4.25 kernels (dhr/pw) * Fix checks for some log files/dirs in case they are sockets or pipes (pw) * Fix for crl.pem crash/core (dhr/as/kb) v2.1.1 * Fix _pluto_adns installation path (kb) * Fix sending of X.509 CR's when no CA present (mcr) v2.1.0 * NAT-T support (Mathieu Lafon - Arkoon) * X.509 fixes (Andreas Steffan) * New configuration file directive, {left|right}sourceip=#.#.#.# This will set the source address when talking to a particular connection. This is very useful to assign a static IP to your laptop while travelling. This is based on Tuomo Soini's Advanced Routing patch. libreswan-3.32/docs/CREDITS.freeswan000066400000000000000000000056111365625662500172330ustar00rootroot00000000000000We haven't kept proper track of everybody who has helped us, alas, but here's a first attempt at acknowledgements... Most of the FreeS/WAN software has been done by Richard Guy Briggs (KLIPS), D. Hugh Redelmeier (Pluto), Michael Richardson (technical lead, KLIPS, testing, etc.), Henry Spencer (past technical lead, scripts, libraries, packaging, etc.), Sandy Harris (documentation), Claudia Schmeing (support, documentation), and Sam Sgro (support, releases). Peter Onion has collaborated extensively with RGB on PFKEY2 stuff. The original version of our IPComp code came from Svenning Soerensen, who has also contributed various bug fixes and improvements. Kai Martius (admin@imib.med.tu-dresden.de) contributed the initial version of the code supporting PFS. The first versions of KLIPS were done by John Ioannidis . The first versions of Pluto (and further work on KLIPS) were done by Angelos D. Keromytis . Richard Guy Briggs (rgb@conscoop.ottawa.on.ca) and Peter Onion (ponion@srd.bt.co.uk) added the PFKEY2 support. The MD5 implementation is from RSADSI, so this package must include the following phrase: "derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm". It is not under the GPL; see details in linux/net/ipsec/ipsec_md5c.c. The LIBDES library by Eric Young is used. It is not under the GPL -- see details in libdes/COPYRIGHT -- although he has graciously waived the advertising clause for FreeS/WAN use of LIBDES. The SHA-1 code is derived from Steve Reid's; it is public domain. Some bits of Linux code, notably drivers/net/new_tunnel.c and net/ipv4/ipip.c, are used in heavily modified forms. The radix-tree code from 4.4BSD is used in a modified form. It is not under the GPL; see details in klips/net/ipsec/radij.c. The lib/pfkeyv2.h header file contains public-domain material published in RFC 2367. Delete SA code is based on Mathieu Lafon's Notification/Delete patch. Peter Onion has been immensely helpful in finding portability bugs in general, and in making FreeS/WAN work on the Alpha in particular. Rob Hatfield likewise found and fixed some problems making it work on the Netwinder. John S. Denker of AT&T Shannon Labs has found a number of bugs the hard way, has pointed out various problems (some of which we have fixed!) in using the software in production applications, and has suggested some substantial improvements to the documentation. Marc Boucher did a quick-and-dirty port of KLIPS to the Linux 2.2.x kernels, at a time when we needed it badly, and has helped chase down 2.2.xx bugs and keep us current with 2.4.x development. John Gilmore organized the FreeS/WAN project and continues to direct it. Hugh Daniel handles day-to-day management, customer interface, and both constructive and destructive testing. See the project's web page for other contributors to this project and related ones. libreswan-3.32/docs/CREDITS.openswan000066400000000000000000000046021365625662500172520ustar00rootroot00000000000000The following people have contributed major resources and/or significant patches to Openswan 2.x. There are many more unlisted contributors. If you feel you or your company are missing, please contact paul@nohats.ca. Michael Richardson - KLIPS, OCF, IKEv2, testing Paul Wouters - IKEv2, packaging, porting, support Antony Antony - IKEv2, testing Ken Bantoft - DPD, cross compiling, integration Bart Trojanowski - OCF, KLIPS Herbert Xu - NETKEY / XFRM, IKEv2, NAT-T David McCullough - KLIPS, OCF D. Hugh Redelmeier - Bug fixer extraordinaire Andreas Steffen - X.509 Certificates Dr{Who} on Freenode - Porting NAT-T + XAUTH to Openswan 2.x Jacco de Leeuw - Fixes for MS Interop Mathieu Lafon - NAT-T Support Nate Carlson - Force NAT-T framework, KLIPS for 2.6, etc... Stephen Bevan - RFC2409 port selectors Tuomo Soini - NETKEY, KLIPS, _updown scripts and more Matthew Galgoci Miloslav Trmac Avesh Agarwal , USE_LIBNSS, SElinux Hiren Joshi Cyberoam [www.cyberoam.com] - Various fixes Shingo Yamawaki - Various KLIPS patches willy@w.ods.org Openswan is a fork of the FreeS/WAN 2.04 codebase. Please see the doc/CREDITS.freeswan file from FreeS/WAN for details on original work. Xelerance (http://www.xelerance.com) has sponsored the continued development of Openswan since version 1.0 RedHat (http://www.redhat.com/) sponsored the development of IKEv2, USE_LIBNSS and various fixes related to NETKEY. Secure Computing / Snapgear contributed OCF integration, DYNDNS support and many other KLIPS and userland related fixes. IXIA Communications (http://www.ixiacom.com/) sponsored the cryptographic refit in pluto, which permitted Aggressive mode to be incorporated safely. Sony Japan contributed many fixes to KLIPS, and sponsored IPsec/L2TP development Siemens Germany sponsored IPsec/L2TP development Emagister sponsored IPsec/L2TP development Astaro (http://www.astaro.de/) contributed patches and hardware HP (http://www.hp.com/) donated hardware Cyberoam (http://www.cyberoam.com/) contributed various patches libreswan-3.32/docs/PlutoFlow.png000066400000000000000000001064051365625662500170460ustar00rootroot00000000000000‰PNG  IHDRë¼?Z pHYs M MÒέNtEXtSoftwareGPL Ghostscript 8.01L~þó IDATxœìÝÑr«¸¶Ps+ÿÿËܺ9jIÈ€±aIcÔ®]!l’L”…<Íóü‚ø¿»; Á@$ww€áLÓT]>Ïó4M—”u¥»xxØÒÕ¥“Wþ…Òî}ØÎ‡vzïû7ÌÎêǾ¡ôÁ<7˜ÿµ>^—Þø›ÒfŸ,íä£:¼f÷GõêœÓ‡°ÃìdÞºL€KHðüZ5})&.ãúßh™ËuóNí?™»9d~L ’V4Šm^ïêdÒÚjƒÒ5ôïßp«KNVw½~uÃjûkéÑΣ+{ÒèyYB³¿c[»Ëª†ª=Éö˜–WíÙWã…*¾ííÖ yèšs=®òðË¡ƒ?zðmÆày®­b›ôÙêV˃j6ÊžÍv‘µÐØWV¨³UsRíd¹ë­cO7)û™õ¶ÝÉ­}e=Ï.~/E|ß¾ÙQd¶;Yݤ±¯­ž—-7ÖßZ­±æô¯Æ{”-,ß>ó¼e žx²ÁË­À”f©r“W3ÒíßW¶Ótï Û»žÿœØ¤ìÌþFæÿioOg!é:Õw¤­ý&î|Ù×ö¬ÔémO¼ŒL‚'ª­åFjÊûúÞ†YÑÅkG°+7ù™»®®pâÙ³ÉÑ—ý“Ô¿§Š†Þì°×†ÝÃÉ Y¦Ü3ÁÎéúùëPöv«åË/0½ì¯K'-½qwyÜo2Æ‘ÝYøúo]Dõqu¸w+>¾¶Çk«Ç[cö[wFV;ÙÞ°Ú™­ÃÜÙ±ö±l½€[ÉÞ‹×»×°±ë¬«sí^Ò­g{¬îkÿË^6òö Ê½Wßô²‘²å­7èµñŽû™ À[<¼^@ÿF5&þ¸Ï• {ªhàéÒà.@FÔàÀÔ4wyB•Åí<D¢Š"‘à  îd"pà( "‘à  "‘à  "‘à  "‘à  "‘à¡~¼ëºùV;;ÛŸ¦émS—KwºµäÚöàF<ðš¦ižçôËrt…†tµ›|béê<ÏÙ¾®Ýõö“àaP[#åw¥UƒÜ°ÓßÝvIî<ÏÙ—í•·6_V[È®Kª‰¿š¿«›¼íOõèªÇ›mµÕ¬?ëÿowᢀg2a”…"ñòôÙ²Ôdy°ÕÂÛaøù_eû[—ÕB—FöÆd[µ»Q¶ÓîÒÎÖà÷ŒÁCÙvZSV±gE2YV¾\»ÙrïÙ(xjëèÊ? íF{e—wžI‚‡ŸjÇÐÆ³K¾lÏdë§ÍïéwU fRåèøzøWë²L¨Ý%xU4ðk§§kü¤œãÛ3<¾-@/W;z,{ÿã«fzxš÷•®•Ýy™Õp··Z4nÄÜsSf¶~ã¦Õj·«}nÜÞÚèmyDûûŸ½,n”‡ðve·ËÖà.<üZ:³yQîú~,+éýd€ÇRE·Éî§¼Qz!¾ÀÃIðp4%?!1{²à*<ÜfÎüHððk[£ï¢<°‡÷{B)<…÷Ú€s$xˆD‚€H$x¸AyÓªÛX€$x¸™‚xà n#»'Hð‰‘HðpŸÆ œ#ÁÔÂGIð‰‘Hð‰·Yn`u+pˆ‘Hð‰‘Ljp cð‰‘Hð‰‘üÝÝø¢išîîBçÜ ¿'ÁÓ9ó{\ À-TÑ@$<D"Á@$<D"Á@$<D"Á@$<D"ÁÕ¦iúÆçksÝÊG/@O$x¸Òs>vš¦´3B<tC‚‡~l º?çºøÜßÝ€'Z°×ÿ×åKn/i7›mø¶µ,|/OUW[¾\–©=•‚2›Ö¼;Ïs–}Ó%kª.W«¶YÍßÕÖ²m—ž.O¿\lõAv€nƒ‡–l`{ÍЖ©¤-4Zk²W;v¨@P<¼·UÊrÉí¡;[«® µÀ€TÑÀÕLyke³¦”ŒÁC]Z0SÞš•¯ìŸ¾z§é¡ÖÞv¬:0¯Ìºá—:={ZlýeÊùà/ßõÓ^^„1xøŠÛË]ÖÙ0_¢6ôE‚‡¯¨Îùúm˜®ÎiD'ÁÈÑÀ%ÌE‘Hð‰‘Hð‰‘Hð‰‘Hð‰‘Hð‰‘Hð‰‘Hð‰‘Hð‰‘Hð‰‘Hð‰‘üÝÝø®išîîÀ•¦yžïîŒkš|Ǩ¢€H$xˆD‚€H$xˆD‚€H$xˆD‚€H$xˆD‚€H$xˆD‚€H$xˆD‚€H$xˆD‚€H$xˆD‚€H$xˆD‚€H$xˆD‚‡Ÿš¦éô³/ ~o+¦‹ïÀ<Ü  ëË’yžïè‰?µfô4Ä}ö“àá6Kp߀C$xˆD‚‡{¤%ïÊ߀ýþîîŒ+ îr<°‡1xø5Iø„÷0 pŽ‘Hð‰ 8ØI‚‡ÈëÀi<ÜÆg²'Hð‰‘Hðp?eñÀ~<ÜCjΑàáNncŽ’à  "‘àáf â€C$x¸ìœ Á@$<D2ù;>b "ù»»ðE>/éÛü~O‚§s"æ÷¸@€[¨¢€H$xˆD‚€H$xˆD‚€H$xˆD‚€H$xˆD‚€H$xìô§¢.úPUˆH‚‡áLÓ4ÏóúøÞÎGIðп4¦§×òwwà6Õ,»ŒO¯ÿWWȾ]²'4ŸÞWºfcïé YÒ!yàùŒÁ3´yžËÔûJ‚o¶B¶°l']ÒørgÒ–·ö¾DðtaúåšÚ«}Ý  6Sl‚« ×dŸÝš¥ê2dïéÌr!Qwß*dßêÐ þqÂe¯Ïû™…ÔˆæÄ+ ÷YqËÑÃL7oìúm€žHðS÷íÛc´¸ÓQöƶ²–CÊ‚™êÞ£_û¹“µg·ß¡x{ÞZƒovWè¸ÓQóup½,k)W;¯·:“öª1ßèökû½xþ{düò>l+?mM²sò¾ê”Õ$·s_eß¶Ú9Ôxz‹çºmu“·ó±”‡\íü'ÚñôQáõ—Éæƒ?½ßG½€0U4gdÏYˆ©Žæ¾vÄ÷FáòV;½ou/]X_%¾Í²{y€[-W;>~{Ƚšj~܇9™br¨ú ŠæzçRÑÑMª3ŸÚ{:.ž†ìê_Ž6ø¶·¯ï ºïwW„ݺBûqgÞ^U%Á_,­B^‹’¯j¶º¼±÷Ï÷{HVfSÚ*æ¹Å£Âë£:<œ½¬@eg8»ªb»]ÿyû{öþã E„:,á.oîlܾùjÜ­Ú•ÆMŸoo?­ÆŸ¾“µÝFùÍžÞ–ý¼„‹„¯òòÀ-üþ…ê,wµ³3uõÎú8ŠÇòòÀ-TÑ|Ñšoʉ_2íTm€1Bû®“Áÿ¾·× Ÿïë •—na þ»®Ê7?nG,x,Ÿè‘Hð‰‘Hð‰‘Hð‰‘Hð‰¿ôóV M‚€H$xˆD‚€H$xˆD‚€Hþîî|—©~€ÎHðôlžç[˜¦éóF¥¿#€Ñ¨¢€H$xˆD‚€H$xˆD‚€H$xˆD‚€H$xˆD‚€H$xˆD‚€H$xˆD‚€H$xˆD‚€H$xˆD‚€H$xˆD‚€H$xˆD‚€H$xèÜ4M§ÏÏ$ÁCÿª1}Y8ÏóÏ»|D‚‡!d!ÞÐ;Ä%ÁCçÖQö5µ‹ïšCXr¼ìàaÓ4¥%ïÊß . ²÷5¾Ëñ‘cQNÑIðÐ?cíÐ "‘àa*g < Ji %ÁÃp Æ@h< Áˆ;tC‚€H$xˆúè€#RTqIð0Ãð£0î}à  "‘àa8Êi 4 "‘àa Fß <D"ÁÃX Ã@t<D"Á@$ww8`𦻻9¥Y?&ÁC0Òâªà÷TÑ@$<D"Á@$<D"Á@$<D"Á@$<D"Á@$<Dòwwl~½^Ó”|=ÿïqº<}jçò› µw``ÓìgÁݦɻð\O{wžÖpNüž*ˆD‚€H$xˆ£¬˜Æ#Á@$<D"Á@$<Œeš¦éÖ:Ú{¿¶“§[;ôr-kÞûòfÕ®"ÁÃXLÝ}Èþ—kýi¯°ß›‡`À-$x€O=ä/åæO»œàwwø…j(Üõ¶åºIÙÎ2 ½þ_>ûvÉÛž´›Z÷[¶v´? Sé«Q}e‡Vî.=Šô5,+ëUZÉSí0ý[óÜ"}ª\R•n[Ýdkaö lí\O^IrÝÚ°º0})¶i¿\o{XíðÛ ³×*Û$ý2]žNusÙ½7Ê¢cð0ˆ­¡è5¾ho7Þ.üx;ü¶…­õË Óqèv²o7rî@N;ݲ¤0 †vIìÛÊÁë.Ö]Úe$Gsü'žhdÏœó½–è’*·'$y;ľ¿Œäó]Ïÿ–W×ߺÌx»Îkw©Ï §[~ûWúc ú—ñn-lÇÇìî̵ˆ<«¯>»•,³åª«5vÝ8„­£Î©Nhbø—[ÏV_𲟮V7 ~²ßÏï×'{Ú»ó´þüØþÃÿý õØ·æÛ{ìtÌ<Л[2e»tg±§€çZâ5@—$x †ö 3Ùj·ø^­ÿiâ;@—$x †aTf¥sÓôr’ÃðÌE‘HðAZ!fòP›‘HðÁ<ÿ3ô®†'Á@$<Äaôà  ‚XJá ÃÃð$xˆD‚€H$xˆC ðzýÝÝà˜Ég1ÂÃeߤkæÞ¹üÄ&i¬ÿpï6eïëS®»¸Ú4;«î6MÞ…çêøÝéøÐàf)ç_ ŠFd â’à  "‘ààRŠžI9ø "‘à  .e®'Rξ@‚€H$xˆD‚€H$xÔl‚3ˆI‚€K¹<&å|à $xˆD‚€H$xˆD‚€KùRξ@‚‡áL~@d<Dòww€eî;=©âÚNÙÂò”é1xà –`=Ïÿ<8]¿·ô¬ñIð0µïð;2eiä×däcçkTÑÀè¦išý‚ÐÒKôtÄzžÿ÷u…ra¹muÍê ÀúÔÛ)ÕӖ˦²£ÈŽ«ÝÃê+°ç5i¼Dp+cð0Šê0¼±yèÄV±ÊC³²…[m–í—Û¶£í4ýó/[­½ëFkÞ–»h|Yn²t2;¨sý„/3ɆÛûï[7Ò]þySönï¿‘ —ÝHWH6¤‰}m»6[MêÕ—¥\˜mÛhª\3ëaõ¯Ù—[¯ÕÛf:½!l“àa,kj_ôVB“ýÙ½êèò{›²÷p{ï2±5.löl»ujz9‘ÉlÙzª÷Ó?¤_îéCµYxU40ÞÂ:°S5õV‹È6˜Å߯™=“KVëXÊ­vþ(Ë `Þ–Ù¬{÷£’Ç3ƒšç¹ÿ*GuÒô5’®Ãϯ$§ « V×,|Û¥´‘²â(ÛÑÛþdí¯·´fXõßêá´qÏnÙ,<ƒ9(îg&'ëéÝ)eIðÝà?º,` –ߟ„Nû ]Ù½;|*ZoñžÀ·UDÙ.ä|à TÑÀ@ÒaønKhü²d4[“ÀpÈlöw"‘à 2Yó*^IâPE—êõ\œã|à $x—"xˆH‚‡u[ÿ2Ü@ÿ$x…w胑Hð0(Cò”Ù$a,=WÀÃC¸<&å|à ŒÁ½X.N–_–.Tè—#계&ûHEè”—r%IÊùÀHð0>‡Þ3~YÐ;w²Ý™&·Žq³ô®ŒWqaùvù‰MÊkW{ÚÞá:ÓcrÏ6MÞ…çêïÝéïˆrYr€î¨¢€H$xˆD<Œ¥óš—úúg "1‘Lf6ø¦þÿ@@$xFÊüWGD¡Š"‘à  "‘à  "‘à  "‘à  "‘àºÓŸQú›7õª K‚êæyþñ†À<Dòww€O¥õ$ó<¯_.—ñl×vÊ:‚^ݶºy6è¾nØè[¹Uy8íþZ=‘à¡iÌ]§IúÕLÞ[a½ºf£Á­mmUö?;®F¯ÒMÄwz%ÁClKx-#l&‹Ñ¿Ùiùìén¤-œØz"ÁCÞæÚuû¿'L/{Ìö~m7ÊÝ}£exw²B‡ªAù®ÑëyžËbž¶²ÿ僭 çï1<›1xˆ-ä~ÕªMª!¸,o/ÌZØÚiºæV½ûÎÚ›Fÿ·,¿”ãè’›½îç–»'{Ú»ó´þ’€£$ø›-Á}ïr<mü=Œ¾Ã‡|ã0, þ)ÔòÂiÒ<C‘àï$µÃ‡|0 "‘àD%oIð·‘×áC¾‰“ÿjyá49€ÑHð7“Ý8D‚€H$ø§P 'øÆ`@ü„Žú»»(…g8Îù¯24Ð= ¸”ù%®ŽF Š"‘àÁx$;Ið7“Ý8D‚€H$xˆD‚€H$øû]^ ?MÓ€3ÊyÔÀ€$øywì˜G H‚ÑÎ±ê‡ i?¤á3Y#ÙʲËðóþ¤;Ïóºr:t]¶°,ÙZ§ÜïºfÖTµ‡i7¶Z[¾\»Ñ^Ÿ.UÏÕöÊÙëï3tF‚&Èi„Í‚ËÛ\»n›m¸¦äåA}Ò•Ëý.­¥M•)6Z«vã“£&–å­?”¿³Ë<ñ€.Iðý(“J5ÑVÓpz=ÐN“àLÅÀóƒ8Éh=·0 !MÛë@ûº0[²~Nj¶Iûsaà7ŒÁý[svÄ«KÒ ×ÊFÖÿÅw~L‚†°æì2pW#ø’××[³±v©€©¢Ø”&uUï<„1x`—äïµi€ƒú7Ïs:Ñ{ãNÖÆ&Ù’µ5ü˜ agùû¡Mdwn¡Š"1ðz5+jàQ$x€×Kp U4‰‘Hð‰‘Hð‰¹h€dŸl ì'Á¿fÞFø„*ˆD‚€H$xˆD‚€H$xˆD‚€H$xˆD‚€H$xˆD‚€H$xˆD‚‡¡MÓtw€c$xè\#£OÓ4Ïó/;|N‚‡þUC¼ÑwJ‚‡!dy]|€¸$xèÜZ'³¦vñB“àa ²;t@‚‡Q¤7­.ÝÆ Ið0Á: ÁÃX–ø®œâ’à¡Ý '<ŒÂ¸;ôA‚‡A˜€ $xˆD‚‡á(§€Ð$x‚šè†1úàaD†ä . "‘àa, i : F¡rú Á@$< Ç`<„&Á@$<D"ÁÃ@ÔÏ@$xˆD‚‡±†€è$xˆäïîøDÕ¯ò Bà!)óK\…*ˆD‚€H$xˆD‚€H$xˆD‚€H$xˆD‚€H$xˆD‚‡žMÓôƒýö.Òö«ûúÍaÀCHðгyž»ÙKc_¿ìÜN‚‡q·€ˆþîîp½­R“õñ<ÏË—åšËxö4MË:ë—Õ¥+Ww½î(]¿ìR¶Ó­õÛû€AHðЛ%×Vcndz€^Mêi€NÜë_µ€^®Ym¤ÝþÛÀ¾©¢U‡®_ɟ彡է>÷¶ñòÂ`‰õ{º¡ü€1ƒ‡4"ïWÓð¡ÆÓ?|­G˜1xèP¬ì›Öó¬Kölë0à*<ôf-"OkQª _ÿ-j/ŸJ›­>U>ÈÖÙj¼­¬º)÷~®eèÀ¤²±áÛ=­?=ñÚ…1xˆD‚€H$xˆD‚€H$xˆD‚€H$xàzÕ ÚÍÚ—àëU'V7Û:\B‚^¯oz€kýÝÝà~KÈ^þŸçyùtÒõÿuµe=KäåÂuÛ¬åW2 _6[m¹º Î<ðO8žç9MÉëãlùº¤\¸³åõR¡šþ·º,ŒÁ-Ù@xÃ:î¾³ÙíjF` hYÇËÛ«­£é×V½©YM‚ÞØ9^ÖÕ4ìO䇚€HðÀ?ÒT=ÎnHÝZ§ÑBú Y¯ɤ뀀ŒShyZöÓúÓ¯-Qƒ€H$xˆD‚€H$xˆD‚€H$xˆD‚€HþîîpŒ7€ÁIðÉç9äs‹ :U4‰‘Hð‰‘Hð‰‘Hð‰‘Hð‰‘Hð‰‘Hð‰‘Hð‰›¦éÄSÀcIðпjRß ( †åuñâ’à¡sóÎV+¿¬†ûêjÕ^e;}»ôÇ< !’oK³x{T{O›Õu²¡ýu/³åå†å:Ð+ ú·$ækcîž6wî÷t—AÐ1U40„ýµ%û£ðž6¯ªiÙÓ+!€Aƒ‡n­E){&P_¤£æ¯ÿÞoZ­cÙjgY¿qûéZ^_Ý]»WÕ Ëu W{KcaLûËÇãiý9äáx÷`¥Š"‘à_ÈfNSü‚¸Š1xˆD‚€H$xˆD‚€H$xˆÄ\4Œ `py¢SE‘Hð‰‘Hð‰‘Hð‰‘Hð‰‘Hð‰‘Hð‰‘Hð‰›¦©ñTãYà™$xè_5¦/ çyþyw€Hð0„,Äz€¸$xèÜ:ʾ¦vñB“àaKŽ—Ý < aš¦´ä]ù;Ä%ÁÃ@–à¾Æw9"’àa,Êi : úg¬z"Á@$<ŒBå ôA‚‡A)­€ $xŽÁxM‚‡!q€nHð‰Q?àaDŠj . Æb¢“àaÆÝ <D"Á@$< G9 „&Á@$< Äè;t@‚€H$x‹axˆN‚€H$xˆD‚€H$xˆD‚€HþîîpÀ4Mww¡g&ê  ‚‘2¿ÄÕQ¨¢€H$xˆD‚€H$xˆD‚€H$xˆD‚€H$xˆD‚‡!LÓë‹bõ~I‚‡!ø$Wè†\ã÷£æÆéÓßݾ¨Ì¸é’e`¾ºdžçåÿu…eIú ld]¡±»}ÈZ(wºµGèž1xèÖšnëòôËtlóö’u“4CoµSé{ú°\E¬Ë³Ç[[@ß$xèYu<{½«5ÀÞŠÂiÔÎÖÙŸž³ôŸÝY[íCºBµç0&U40œ­”ü3Õ˜R¹‚ávxƒ‡¾í èë:•Ó²øKTÿ8Píƒávȃ‡nU‹UÒ%Kyuªø·y=m¤½ÕÖšé&íéêËu…=Ð=¿ü åiñÆþ¤»Þß§½€-Ù%DÚí­§v.?±‰½ŸÞ{”ó àq~¹Âž@ïêO¶ß.| ®²I‚Æ x#«oÙ?ŒycàÔÁo\2ƒ$pcð‰@/üÙƒ‘Hð0–êÔïϹÙô9=€Ç’àa,åÇ*-Ÿët_þã9=!˜åÚo½t)tM‚b0À)<D"Á@$<Dòww€šµF¼œrqyÊTŒ0*cððHk@Ïn÷ßaxÀ)ªh Ó4͵_“[ËaDéÕìò}1M¯yþçÿê [ ×§ÖÍ«§K²‚™u§Ù³i³[=ß¿¯Æ4Ž xcð0„r¬Ýè;äæy3¬¯…+é—Ù­6³Æ«¾MÉíoجekÙ’lýåª`YRí0ð0À#©¢,Á]|‡dyú„ÆVe¬O¯ÒȾVÈd¥;eãàáÁŒÁÈ”¿ÃaÕ½.<Ê«¦e÷™¬Ä¥­,€i—Ù¬#ô~2@ÆàaóŸqš&³:@hªhè…«S` <D"Á@$<D"ÁÐ 35cà  "‘à  "ñ™¬ÀëõJnô™8ÄåìÆ ÁÃÀÒ‰;DB‚‡Qeóî-_®9¾œ•oë©·ËOlbïöþùÞú5Í~ÞÁ¶iêí{$?"Ãð1x[™æåxx6 ø—ì˜M:7mÎ|ã)à±$xè_5©‹ï”CÈòºøqIðйuæ™5µ‹ïš‘Ý <Œ"~yÜÙT÷0 "¸@$xËß•Ó@\<ôÏ ;ôD‚‡Qw€>Hð0(ó”‘Hð0å4šCP3Ýàa Fß <ŒÈ<Ä%Á@$<ŒE! D'ÁÃ(TÎ@$xˆD‚‡áŒ€Ð$xˆD‚€H$xˆú耑Hð0Ãð‘Hð‰‘Hð‰‘üÝÝà€išîîBÏLÔ@<#e~‰«#¢PE‘Hð‰‘Hð‰‘Hð‰‘Hð‰ƒš¦éÞÏ0Úߟµ) †³âyžïýx×ý{÷1´’à ’¿»;\)-8™ç9«?Y—¬Ãðå&Ë’eÍÆ Ù’­´[Û¹Õºm¹ùÛþ@$xèMj³ì[ Äë&éSi;{¢üÑÖö4XãÙæéµøÀTÑ@?ÖD›´¿•…ì·+´÷²¿µ» Ã2½I#ò÷Òðå£Ý§,‹… oÆàatoãïºÂž ¼¿µ«,Å3·O­?c ú±ŒF—ð¯í‚õ­MÖšòl…ö^N´¶g«W­Æ=mĬ Å_Ðò´›#ŸÖŸç¨^QmÁk @ªh€ÀÒà.0U4@`Ùm¬B<#àØ¤vF£Š"‘à  "‘àºrâöOšº½Ð È¥Ÿ÷toOnï<‘˜M†VN¦¾,Y‡ák66_§iÏÑ5ò¶«0&cð0®¬Z&ÍÜÕšlÍla¹òžÝ•¤«eîð’àapk&ÞŽÓ5—±ö­‘õê5À¡F2K›r<ƒ“àóª¥2_jd¹7; ƒ“àahŸ§áê@{u¾±»F¹|¶šxp'+Œ++_)ï[Ý ÖÕ;\·R{úl{wÕÕÊu`p< mçM¨[ËwŽˆ·«íw6kôªh€‹µã€IðÀ{é$ñ{Ö¾G ðÞ¹¹&€o0‘Hð‰‘Hð‰‘˜‹‚1]#±e'ð:yQybo=õvù‰MìýMíÜÄVpœ^N“ØH9àU4‰‘Hð‰À)z&å|€S$xˆD‚€H$x~Èr>À)>Ñ Zæ×¾Ï.QÊ üŠ-Óëµù‰NÙ'~ã <\!ÍÜü½çb ³5ÒᤡHððlGCÿ‰ë‡§¶þ|Á´Y!¼^Óä{ä¸5ßòGƒÆõŒÍ"èÅÿÝÝú²TшïOÞ“ÐHó‚>DãÓj Å':ÁXªõ'˨öúu…ráÖSÕÛ v®V®ÙذqC£81xHdwâ¦Ë×Ï (oÕ­þÙaë©êŸ)ö¬¶\E,KÖåÙ:ëŠtÛtór‰ìÏ&Á@áím»ÕÐ\nÕx*[mšW³¬—Ù´?[!o÷µÕ ð0îdà‡|‚OÕ:ZßÍÕÊAúÆÊ{öõË7Èù§ƒ€Ý™¸úìžI{‚ìZE³ÿ3€Oï x0cðغtÉÍiýÉZA¾U”Үɖ§Y¿qjyãiVîâuºlÉjO¶ÞŠko':<ô«ç¿JÏï!ð‘÷ħ‰]øyÀöþ½G˜M6¥Ùýú1xßzÀ)ªh  "‘àaÓZ9s}±™à, ~+½yË\Àq<Db6I¸C6›ÀnÆàá·æYñ ð cðÐ‧1‘Hðp£ûÀ)<üœì|@‚€H$x¸ƒaxà¬ØsÑLfåû¦¦aq†|['ÉœŸßæüz;Á¿ü€þšn²…3ä{º9Inäüüç'Ð1U4‰‘Hð‰‘Hð‰‘„ŸMà™ÒÙ Í À…$x€oYƒ»4À…$xà¼j0-?Igë©·ËOlò´½—+LÓ$Äð þS—ÿ2öÛ}d廿&ÂýgŲÉo΢ê^»ÞzêÂMž³÷õ½3ïÇÀµ$øO]þkiäßs¡ÐAdùožçC/‰Møª_^M0sÑœ´õ·ò'´W9üœúÞ~{k8mþ×Ý9ã÷g¾ï5€ý†ƒ/ÿ´½§¨wžçeIYÞ°µfú ÜKÚÚòeãî·îG©×äUòUÇÞxý«=ÉÞÄêÞ«mfkî9ßÖwÿÐY‘.¯ö¤]½­Æ#Š?¶Î«õÿ×ÁJ¼íUõ;¥Úùê¨w ~ýU‘ýZ—d¿„Ò5—ÕѵꚯâwÒžÖ¶úz`oê;Rõ'#ôi;Ùëß~k¯üÖ[\žHåÑmµöö¬ØÚdëÄ+Whwƒ§)ß©ýoh¹aµåõrq«‘Ó'vYå•~ßmm@iè1ø2夾÷'Ýýÿ¦?[žðGíò¸j¢}m FîovÝj먳îê-§Õ¸“n˜õ¶‘³ÎmõËù†·gàªý†¦çdãŒm›ÿû·²­ï¾´ýlêw; àïR­Êx {ó\ûïé—îm·—W¾ÚþÛ·¦‘™¶ÚÜÚüáï>ÏôÀ«¬?Ъ+øŽ8gÜ*šWmøçg¿BvþöWZµw«ffþ¯=í7ÖËZótì?«´yÕ‚xölµr=ÛWõ*¥¶ú¹L„«_~ÇùŸ1Í1&‘Ä:LùàæžÁ·™$àñÜÉzŒ7ïøª:ïõyù`<°‹°ÎG\Zr>ÀgÔÁCÅÑÏ%…~8ÏO‚€H$øcLÍ1”ßÌpˆŒ: àÑ>ÿåzàñ$x¾Ïð)ç|F‚‡ºï}¢À'$x€Ž¨€-Ó4¹vi§ø>"å|€ÏøD§c¦iRMôìô¸yþO,ó£àk$øcÄw`Ù(éúÓoçòõK?6®&Áæyž—WnŒhë´»ÜHüNÓtòõ©^D]ÕZÖ,ðH<@GnL]Ý:ñB-/rºá4ÏîeO֦ԩóIð\¡"»õŸÇès²Ûε°sá–sǾõ·šË·Nlbïí} îË<Ƭ£QEÁTsá1×ÿ«+” ·žZ³å:o—Š)ë!TmµÖÞ{Ö`ùe¶÷²'Цàf“èˆâ‡×ë5ÏõR4s§+d SÕõ×Õ²éjëãlÃFÊòl™§Óvö+§z€o›M·Ê0m¡Ú8ð5ü1ÆbG3ϳ7Bz{ÇmºBuáÛ§ÎõçÛ?RÖË’ìúd]òI;À3¨ƒàûî*¿ÅçµéŸ·S­:Ñà—Þµ¡Î~c°“Ê<#©FØuaùì‰ ½V¿4nÔ»ªýÍ^nN_ —r_&@G; õ³Ž5nTmÜyyèNÖW‘›Ó ûê³Õv²Mª Ûíì?Æv‡³ƒjß›5Xmê­Çž¨Ä5ØI%Ác.àÑs‰¼3=ÜW=ç·xˆïmçQžó6ÑÁN*uð)§Ù³ÚÛåŸo2NÑÅ#ÓÎü² GF”èÅC†«¯š"ÝTëÀ žžMF­¾Ìø=U4tNÄüHp ³Ið}®÷H9¸Ü`'•ŒAGî%Á@$ü1Šª¸—ü{÷¶ä(®mÔœ¨ÿÿeλ)•dÀ\´`Œèèpa²“LOä…"‘à8Ÿ/0I98ÜË* "‘à·1 ÷’à·q%+ë9߃¿ü:ruø/»Sz1 ¯šŽF ¯6Üq³¤>/Éð¼<Ý$}öS‰ÚéúË–­­iawã@ü6®M|ž,ìhm63Ã0ÌÖ?»lªǧ±öå¶›¢P¿±Löi9+àç,ž­?/¬ ÿoë+„ó²;cð¼Ýœz—zÓ¨‡Óà=\ˆÆ“~%kºÂ<æ]»`´ñì²µlÛ¯ý¬µ°æµÅ•¬p À<ÙeóYö¯€½l.uðÛˆ,œíÔZv…òð<üjžéå(|jžÖà$øm –À•ÌE‘Hð÷²ïÃ%xˆD‚ߦÛ{ýWñ Ú}¤õ_*àG<ܬx!쾫c³ùp„xÞâeyü6fásf2þ¥ål[Ç*<ÕY³I.ƒHv÷åHav/úåjó³[£‰Û0q yö÷Ïç3ŽãttÍÿŸWËøÚÂyÛ¬åϷ߈bˇü¾;k ~ΓO3¦gËÓ­ 7é±-\.ÿüû[°\ÿkËó/N1ý·SüÀ#]TEÓ€oo¥—@¦#vÍA;Ÿ©®l6{¼Ùu÷d]ÆñÚ÷ûéh}#²|--(V,û³rÛvŸáóoiMcµ4è;œà/û<½íJÖb•ð§^f“)–4ê >¥úœexªm +­V_ŸÝ@êιhj feŒ.ñZ:ß”óUzDe³ Rkë4ZHÌ¿ “ö7K˧ºí) IDAT±ð<×UÑsFVoŽc‹à•Ôs âIã§ò­Î×Õ¾ž‚6.{͈ìð—ŽÁ·ƒÈd}ÎÞq'K!žgKÏT¥y^äeïÜùàk׆ֲE6•GûrÒåšk6ÏæÞÎ:³u¶è‰kàñŒÒýµfÌÒ¸f,~^§òöЋaxÕt4w^É‘¼À½$øÿ)ν¹n.šÎ\ˆêeAÎ<D"Á@$ªh¶1ùF8®m€¾d¿’ó_Ôå¯jí©¯Ëwlbïg4µrŸªâeÇ’< pjk½ìS–/åeÇ’*ˆd[Ͳ ¡v7Ó_nnºu8sýúJˆnÛüÇÿ|I=»£{oq¹·þÀV?UÑd!¾OÇv¯ó Ð;#)¤åeÇÒ¯sÑŒã¸)Ô¦+/O–cäÙ³Ó?ÓkÖO·jì4{!ìèÐÁ³I¶Ó|»ÛQ¾¶þ2Ä/-×ϲxÖlºB-ÍgÀ]NðiÀ-†àeVnâ/×ÿÚ5ß ¬Ü;{ÙŒo|áxà(/;–~Mò÷ø[«‡é¡5èÍóÁoù1{Ðn¡¸þïý1î@PÛü|aè¬V8ž^B:KKϳ•³õ—¥êkÖ_ùlÚlq†øF¾ý¸—;mãžP90`­—Õªò…㣼ìX: ŠæU¤4î%Áp!ã ¤åeÇ’‘Hð‰¿¹h¾†ÿýW{fŽŽò²céà{²ðvs5júú²U€SIðÛ˜‹†¢éÉ¿K ¦ýÔ×å;6±w{ïaïérBŽ`k8€ùàáÑ÷—ÍÙ\6ŸÏürbÓ8UËVKϯz{ó;ìA½ìX: ~yÏÔßGçÿXšß–ߢì}.~ÆùÀ½«ŠÆ()ÀéÚiýþEc”1èÛmõ—½ïÛû:éÆU~ýêÕÇñÀ*‚­Mµ×?¶¼A±E oYù3Åå94½ÖeY/´l0•VÑÔêjj_§›×œ7_¾Šå:Å}Íͺ ú¶m >­B™óJ\æj™~ÙB±ÍÚúé Ãúõ—§Åf56Å@&¥<ÖyÓÔ›†ïl…la£Á¬…ôŸµi#éSÑÖåNk/³¶¯´‡_Û~Š¿S„]Ù9Ϲ¯çuÒm‹Éx¹~ñ´aÙ“lµ¬ý¬Ù,Í×:ÀúO„_ËTÒŠ ç%ÿóâï¾bµV.¿¼Þ`¹Ó}{ü|þ¶sê¬ÿã¯:ù!vÒ«üZŸ†Ý5Á·˜Å˜®‰ìÙúk.W]¹wØ©1ν^šÈ×\`pÈNÓ.mƒŸÂîáy·VÓCkð?Å¿yášy`ö}€ÖàëO·§Š¦³RõⳟEíJ»µlý¶5ñݸ;Àu¦Qäß«;Î6wry!iZ?¯.l4øI.'m¿Ë•åúÙãeSÅF–›‹d–åþÿÈà­6L ±æBÏORŸ^ÕZldY†þY\¥úËúµg³³‹ôJÖlµÆ«ƒ”ƒ'k_=Ù˜5¥øK1ôzו»:Öír—¿ügè䇨I7®²9vs9¼œOïVÆîbRɱ-Áq¬½’u(Å¡nβ¼ŠqÇ(ø×ùU6=õ€ŸIðp¾‹óLD³m6Éôn¦Ù†Ëâ×ßÓ´}·×¥ç¿T««tg‡òasà|Ï&"þ³ùŽNŸJ4ŸÂýüÔ0 µ(¼\žnÛØð2ÜÞ7Hƒ{ñ61FÁ€¬Jð;îÀ:…ò,ï®i'æ¿Åí °ìÈ1!p‚µcð;ž‹Q¸˜ì×+Þ¶q³Øé©¹'éƒö¶µ€§%;<†ÁÓ!÷²9›ùÂñðü;éÆUþïÊMñ·Q Ò÷søžëmj çõçå å¶b:ÇÇ¿ÿ亹h¾–¦¬ÉÍi_îtáÖJÅ3É.³^ys®5›4.&ùñÖ`ö~öÞ-NLðÙi.¸\U"èÑò/ÿŽ ²¼¶ÛÞ;Ü;ðÍU4 œFö4¯ÿ2Õã¦âp¯=cðݾ¨´¶dÞ¶=‡ã|lÚ~qam¿iÍraí|€²N"S'ݸÊÚ¨úÔP[»ÃÔ#_,çqÌ—Y[Eóž²rQ €žm¨ƒ^®]Vþ|žø2ÎÒÉo'ݸÊu³IvHX œKïèô/)% [¯ƒ¾rÖz*ß°ƒ¿[^ÈagG죊"‘àØ«“ïi;éÆU¾$øy¾ÅÔrÆS›z³û;å7ô½6=k%øùÞFóÿ§iÆÖ™Ÿ*6²¾7”Û6ú,ßp¯j‚¯EÕFÈÎîÛ4ì¶Ï":9ÇèB'y¯“n\¥5ÍÊ´:%õt´>maª®)6•Füyt^sùlcÃZk_—_EÖèdž+Yçb÷4ÚtúÔ¾!í¹8g¹Îµ—g µ…í ³Ý}í3ÜhÃ|ðY‘Lºüó_¾oú¢}CÝk¢ö| núÏâ†A«}x§m³I®©fI—/~Í6)Nb3—ßlê^qí m‹=€ní¹'k6Ö^+J™ÿY¼ÿ”ÊÓÍ.ŸÝ:„ߨpeSêã¡-;±oüî×JïÚ —g .W«mØn°¸¼ÖO€—êäOb'ݸʪ¿üHž ÇÓ‘òì³ðkD.~´§!;Ýé²í®.ûöu\͉Onh(–Ò-Oøk4Š¿zÅßÊå??Iˆ¯]®ÓngÚ¼X¸¦Ÿp™j‚O?Ì–—‡7n]­Q{³fÃõÝ(¾@àwéßåS+µÅÿk¾3üÚˆ?Ü®Ußø ;U6p~ýÞ}BÃnµïåÖl¸~å¯-¯lmÇ/»kßþÑÉ_ÅNºq•/U4·dÙìÌáâ>ˆï°[­Ž¥æ4¼gUÑĽ~Ôg*ÀZä½Nºq•ëà/ÎÁÓ Ãï§ â;=»t6ÉSIÞ¼ÁÕsÑD´4€Çà·1ÒÀ½$xöêdp³“n\E‚€H$xˆD‚`¯N&ùè¤W‘à·1 ÷’à·1 ÷’à  "‘àØ«“ãNºq•?ww ˜a”Âó6.à€®Hð@‹SVè*šm¤î%Á°W'•–tã*<D"Á@$ü6&åà^<D"Áoc.€¿:‰Ftã*<D"Á@$<{u2ÉG'ݸŠ¿¹h¸—‘HðÛ˜‹€{Ið‰À^”'tÒ«Hð‰¿¹h¸—¿+Yþêdp³“n\E‚€H$xˆD‚€H$xˆD‚߯\4ÜK‚߯\4u:éÆU$xˆD‚€H$xöêäÁNºq ~W²p/ "‘à·1 ÷’à  €½:)Oè¤W‘à  ~sÑp/ €½:Üì¤W‘à·1 ÷’à  "‘à  ~sÑüÕÉ%‚tã*<D"Áoc.î%Á@$<{ur‰`'ݸŠ‘ü¹»Á àžW1ÿÒ©ü=` ~·¼Ãþ$ÎŽØG D"Á°W'ßÓvÒ«Hð‰‘HðÛ¸ò à¯N¢Q'ݸŠ¿I9¸—‘Hð‰;:?I/™ÊÌj—‹Œã¸|ªQ™ÖhyÞjZ’ý³Ñ™âšËšw±©óp Øo†FzNW¨…ã´…¯-O1:[¹¯Ú&ÙîŠ=™6Ìö2=ÎöÞè<À‹tòg°“n\EÍ6梚9þCmmáš\ÿÞ±Ic_iOV†òöp ~ãm™†¢§Ç[AÚñwGË»;³ìÉšhÞá„ô`½5ïÛQï­Ÿð; دQV^3$Žm¹±É¼ÇeåL±'qÇ×;<©aåwA—í "éäOe'ݸŠüd®?Y™wÇı-76)î±Ý“gǬ''_¿09o×d\É ì”]º#™ÕRòŽ–ìL-Ä[Ô˜Þg_Ojï´wھΡÖà¦v²ë¡³‰€–§gÙÏhë¬Díê©­'í“Sà@Æà·ñ'RçýF>H¼oó5_ü²ÓõÒ¯ ²ï æt»òÊà´ÁO³,;»º·Ý~£Á­íÔ6,®“íz¹0[’¥üåû¶fFç‹?¦}?#€cðÀNÓðgc(w(ÍÌØ]Órm̵¶I±éSKŕӦ–{¿]£'í3“4sߢ•ï[»ÁÚ[Zëðו‹ëŒÉd i? fË—.×Ù­Ÿ£x ~‚!õ5ˆoZåš+ÓØŽ•‹ËkÃÀQ¬IÃÅÕÒ“¢â¸øÊkíÔzûuå• îþy-O8z#Áë}-†¾¬© YùF›¹Ó­>+BðÖBðÚYÐúk¿®¼µc5»ÇûOÚ„ÔÉÝI7®"ÁÃÛ ˆ/Þ;_‹R¦YÑÊÖ>ßÞüâUžµMV^œº²ÚÂ!¹onq…¹½Qß•.ÏÞ·å†[ßÛÆiëÏ Á ôs#ß| žÉ{{o#ðBÆà·ñQAMУç«3y¶¸Tq{§†.*X:éÆU$xx;ç¥Üâ¨âòÏåǰßàvü6þpó0iBsïäŽN‰‘HðìÕI1['ݸŠ¿MèIx ~WMp/ €½:)Oè¤W‘à  "‘à  ~sÑp/ ~sÑüÕI4ê¤W‘à  ~§¬œf†}K4ûµÙÝ;:©ÙNÞ–ËÞm 7ƒ²øÝ0<öWéÁ/ívÞ[ö1À^|sÛI7®"Á@$<D"Á@$îîÐ;³Ó@W$x Åd)´tò1ÑI7®¢Š"‘à  €½:¹Vª“n\E‚€H$xˆD‚€H$xˆD‚`¯N&bï¤W‘à  "‘àØ«“‰Ø;éÆU$xˆD‚€H$xˆD‚€H$xˆD‚`¯Nn¥ÔI7®"Á@$<D"Á°W'·Rê¤W‘à  "‘à  "‘àØ«“‰Ø;éÆU$xˆD‚€H$xöêd"öNºq "‘à  "‘à  €½:™ˆ½“n\åÏÝàM²ù"æÝå<µ§¾.ß±‰½ŸÑÔÊM^¼àÃè7~6 ~•`‰”ãvQE‘HðìÕÉ­”:éÆU$xˆD‚àBŠžI9` "‘à  € ½ìj3¾p<<@'¥Ptã*<D"Á@$<{uR ÕI7®"Á@$<zÙÕf|áx€]$xˆD‚€H$x.ô²«ÍøÂñð”BuÒ«HðjÄ2€Sý¹»<Ë4¶ ñ/!81x~¸Oÿ,ŽÁ˜o[¾?é;9¿±wxe³[W€¶N¡NºqcðÔeŠó8ú¼<Yÿº5Ë7jÿyÿÓ¦¿æ½ýºŽ$Á¼Æ×8ž-ÿÔã]#öM­É…§Úñö¦‰eúz%Á-Ã˾—¼ØxqŠÚÇÜËûúQq„{J·sÆ]®S_>•}Ñh³öl£çí•—/'[y>Ѫ5U<Á;üÇW;l<µæÌsë&ö^lŠŽIðÀW§Ì׸îìÈ€kÃ^³w) µé:Ëgk ~e0“e›ËøULW+ÃzqÍ4©ê‡Är¿i›§EÆwœynÝÄÞ'†lâp%+¯·&5¤+g—™Cs£…FgÆñïp‡V<zö ße×\–´–ç$ÇzöñðäþNºq êje0ŧ>õùõµ +Cí5Ùwê¹èŒ:x^¬8ë帳èeA|£ÁF­ù²Ít“­ê Ü×/\v5ÛÑ©W²Ò×ÌÄ1¸F ~7 ýUzðK»]ïïíóiÜN^Yé¼Ùýýº²ïÇÑɱ“n\Å<%'ͧ¡î9ô»ˆŸtD‚à_§eõ3H6O‘ÞO—z3Öo {à.€í$x€§R‹¼'kx— Kø¥ÝÎ{ ôe_‚ï$÷wÒ«˜M"‘àø—ò€¾IðO'‘<‹Àë¦TM‚à_ãhØX«“ÜßI7®"Á°ð²ÏB€X$x\3‰ðtÔót’û;éÆU$xˆD‚`áe£Y±HðO'Ž<‹€kf"‘àØ«“ÜßI7®"Á@$< /Í>×ÌD"Á<8œ§“ÜßI7®"Á@$<D"Á°ð²ï£b‘àžNx–?wwèÝ ÿ¼«Þãà–ñ¡ЇaxêK¸T'K;éÆUTѼ[ú]ëúï]÷mu¸Nºq-cð,œ6š¥(ëT¾Yâ'Ó¯çú£h?ÃÐÑàwW9™ðt}¤I™'qvÄ=:ÉÍ/;þUÑ@$<%/ЂW›êav»wþÇÎÇ$Á<Ýû>Û€¶ñêgf]uæd<D"Á@$æ¢x½Ý%(=Ô®ôЇkƒ ä}ŸˆQƒx:YBË.FŸ£—©×žúº|Ç&ö~ãÞÇqpg øÝ0øU Æì.׿óÓ}Žßé¾2ouÆûà¨~¬Nn™D'†á3Žªh(yÊ”ý„Ú,a»…*°›ðt[“bº¾”ù›9¦gy½Ÿó "uðô.¿ã8fÿü”òñúîvkµ%ÙæÅզΠ—©]Ý °1xþ5ߢ¼§êÛ,éŽãX\’&étÉׯ³žn˜¶–m8EðtyúÏéA­²;k9THãÇ<!¤×€~þ­N9*Ï£æË!ü,”Ï»Îz¸¦c¿“à(™Gâ;0EêF)˱j9¾Ø«åÂó:0QEÀÂÞø>$ŽîѪz˜´'?î®ØÚ²YSÊ×3ðt׎ gåãÙÂ}–WˆÖ.M‡Ïw\̺ìüT Ónm®†/v¬VN£Ì†µzº"…û¹£Å'q8ÆM¿šèoSmôúó_°îí—å².-çƒ?v¿¾·C‚'5 Ÿq4¼‘ óÝ0ìx›²«9?=½ÕÅÓ¶+»—žÀHÛÀ/$x€§Û7€·7_v›Mk¥,Ÿ û\œÓ`+ €Ã„ ¦á: ð‘ààùæ "g,ù©‘rG'x¬´î_„g‘ààY²kvçø¾rùŽMÒ3{?uïðù|>ŸN¯7‚Xº½tzã—å<ù{k þ1Ì&IÊl’ðXÅ4/Â#Hððt‚;<‹@~,º¬lÚѵçÉÿwåÎ`•ãû8þ￳Ýñ—Ð1EPEË™|jÆqÃÊý3<{kT¦‘ïùÿÅ– kOeíÌ-Ï+Ïå+ËŸ‹[غ¤¶ðë <”1x¶›kT–wNÏÅÀ]‹¶Ååi#ó s.Ï6ÉVXö-ÛjÙ¥bÏç%ÅÕj}8“бÎ+@¾Æñt…âÂÙ\¼¾»YÊÏRø|"‘QÔúÖîIíÙݯb¥aøHðÜoNÛ¿Ÿ±´KYæó3Bö¯¢I‚àhí2ñâ³µT•¹¥UòµöÛýl÷­±á²'çÒ¸’€íŠ÷úkHÒqè¹l½18]KüÅKQ—•ñ©âÞ‹Ë—]ªm»|ÉÅ×rUÉ“ÀvÅ•Ƴµ…_[k—Ô¯líë^6õ¤¶‹«¦þTE@p?ÞÀ5  cÓt.—ôÓ“ ¸£›õvRÑ[Îg "‘à:öª¾†*.6ˆ#¿‘à¸Îø¾rU€Ã©¢€H$xˆD‚à†a¨Uä7žú½qØLí©qüHð¼S±"ŠÝã8þX¯¯Ü8•‘˜‹€G©•¯Lãââ–é©y~z<ŽãüÿFS_‡ý†A!  Ãg%xžf.b™Â÷§”Î?‹À=‡õZkíàÞnà@</²¯B=ÍèÊß9Ët¤ÍXv~˜xµ§V.ß±‰½ß±w VIú2²tç,Ë3ÃÆ¹bí©­Ë¯ÙÄÞ÷nâJV^äÔœ-Ä×(ü[kg[d—¢~þ+pO̲ßÜùÙlóÏ¿é|啬þ,';àNðÆOõÔÀS©ƒ¾2Oâì€}ÔÁ@$<D"Á@$<D"Á@$<D"Á@$<DâŽNÀ)¾Þp>}vùTí6Rí5—7Çmì´±Uº¡ZÐ 8^š‰—Q>]¡”‡a(¦ê5k.7lì´±ÕGv W C¶Õ²©Z³Óòb#ó†û^N­'é’Æ™Cí݀颶ù‘§lÝ^çë¸{±ìŸµïÖtrý^>•q÷bS+w ¿àáÕ†ÿ¬\M>žÇÈ×ì}};Ùøw±‘M¯eå^jû-vÃ<àáíÒ¢”vÞR¿®¶µZqÎrÉŽÝØK¶¤öþÈî\F<#zÅÊQçâËl\HÚ^s9TŸ•Âg}›Ö_V®·{Õ¾ÌtÍ^æ%ó©N±Áb÷àp>làqsÛ2æ~i~÷K[–­ïkç@]u)îaÀ½ŒÁÃÛWÀÝa<í°K°•¯&Ñ@8®d€H$xˆD‚€H$xˆD‚€H$xˆD‚€H$xˆD‚€H$xˆD‚€H$xˆD‚€H$xˆD‚€H$xˆD‚€H$xˆD‚€H$xˆD‚€HþÜÝ wÃ0ÜÝà/ hÇñî.ÿPE‘Hð‰‘Hð‰‘Hð‰‘Hð‰‘Hð‰‘Hð‰‘Hð‰‘Hð‰‘Hð‰‘Hð‰‘Hð‰‘Hð‰‘Hð‰‘Hð‰‘Hð‰‘Hð‰‘Hð‰‘Hð‰‘Hð‰‘ü¹»@׆a¸» O6ŽãÝ]  øBÊ<‰³#öQE‘Hð‰‘Hð‰‘Hð‰‘Hð‰‘Hð‰‘Hð‰‘ü¹»@0Ã0ÔžÇq~vÇÚ&éjóšË%é¶ó’aæõ—²]d+û“m;÷-Ývùlíåמ€IðÀYÈNÿ¹ ²µÌýù/:/—¤Û6Bs±íõkk¦Ù}†ìÌ¡–ìWØf9à™ãï65˜¦êö†µ/ ¦å¯àF<°Ù8Ž¡ñéÙÃ÷¸#CoêI{Í3^죊ئ˜¤³zñƶÅô¿/ k`>+²xcͬ0¦Ñ±•/—_àì°¼V2Š¬Ú»¸Â¾—V»2õìm¯lóGqîe Þ®83Ì!ÍÞ²í•mÀ-$x8FèjŠâ%›"/ôI‚‡cÍ»é‰G‡u&À’ogÐb‘àáÕ¤vÇ|ð‰‘Hð‰‘Hð‰‘Hð‰‘Hð‰‘Hð‰‘Hð‰‘Hð‰‘Hð‰‘ü¹»@ï†a¸» À_<Ð2ŽãÝ]þ¡Š"‘à  "‘à  "‘à  "‘à  "‘à  "‘à  "‘à  "‘à  "‘à  "‘à  "‘à  "‘à  "‘à  "‘à  "‘à  "‘à  "‘à  "‘à  "‘à  "‘à  "‘à  "‘à  "‘à  "‘à  "‘à  "‘à ’?wwèÚ0 wwáÉÆq¼» Ä#Á_H™'qvÀ>ªh  "‘à  "‘à  "‘à  "qG'à:é=ŒÆq¬ÝÒ¨øTãÆR핇aȶ­uý«A‚.’&éehžŸ-æéa–A<Õ^9ûç¼£y¡ì@ ?® ó@\êàëL£ãÓãM¡|SÏVΆö :cðÀEæŠóv=Ìì—ÔžîôÓ¬¹€p$xà:ópøš¿©¦¸²ÔÀ#©¢®Mÿ²uóÝuðã>=O!Á¹8@çŸY¿í =€c¨¢®0U¢×.c-ÖÇO W&ïâÊÅ™àÓñøå–пUדm+/ÍŒèÁ/ívÞ[ö1¯ëv¤Å‘ò=€IððvË2’n3q·€+IðpŒè…Ôs8ž«ÕÅe蓈vç :ç%q_ ¼„oçzJˆE‚‡W“Ý wt€H$xˆD‚€H$xˆD‚€H$xˆD‚€H$xˆD‚€H$xˆD‚€H$xˆD‚€H$xˆD‚€H$xˆD‚€H$xˆäÏÝz7 ÃÝ]þÆq¼»ÀZÿkYÊÁa¸âØIEND®B`‚‰PNG  IHDRë¼?Z pHYs M MÒέNtEXtSoftwareGPL Ghostscript 8.01L~þó IDATxœìÖA À0À¿çC/²¤U°çöÌ, âü8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà ÄÁ@‰ƒ€%J<”8x(qðPâà€Ûnúÿº®81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81uJDhìIDATx81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x8 ¥Ï¬c 'IEND®B`‚libreswan-3.32/docs/PlutoFlow.svg000066400000000000000000000636551365625662500170720ustar00rootroot00000000000000 examine isa_xchg find/create state object determine valid transitions verify state is not suspended decrypt packet if appropriate calculate hash if appropriate enforce ordering of payloads state specific func complete_state_ transition() STF_IGNORE STF_SUSPEND STF_OK STF_FATAL STF_INTERNAL_ERROR STF_FAIL STF_TOO_MUCH_CRYPTO send_packet() encrypt packet continuation read_packet() process_packet() de-marshal payloads (in_struct) msg_digest populated md->st connected returns STF_* DNS lookup DH calculation g^x calculation (LDAP lookup) (RSA sig check) (radius/pam) md -> st->st_suspended_md md freed Time Sequence diagram of packet receive in Pluto select() indicates fd read proc recvRawMessage proc recvMessage proc changeState proc outgoingClearText proc sixtySeconds proc avoidEmitting proc adjustFailure libreswan-3.32/docs/ProgrammingConventions.txt000066400000000000000000000124641365625662500216570ustar00rootroot00000000000000Notes on Pluto Conventions ========================== Pluto previously had it's own stylistic conventions but they were abandoned and starting from Libreswan 3.4 only Linux Kernel coding style is accepted. Please read the Coding Style document thoroughly. https://www.kernel.org/doc/Documentation/CodingStyle - you can use checkpatch.pl utility from kernel to check your patches before committing. git diff | checkpatch.pl --no-tree --no-signoff - - sample formatting: void fun(char *s) { if (s == NULL) { return ""; } else { switch (*s) { default: s++; /* fall through */ case '\0': return s; } } } - try to keep lines shorter than 80 columns - space should be canonical: + no line should have trailing whitespace + leading whitespace should use tabs where possible + indentation should be precise + there should be no empty lines at the end of a file. + a single space separates a control flow reserved word and its operand. + no space follows a function name - if a case falls through, say so explicitly. See example above. - the operand of return need not be parenthesized - be careful with types. For example, use size_t and ssize_t. Use const wherever possible. Avoid casts. - we pretend that C has a strong boolean type. We define type bool with constants TRUE and FALSE. Other types should not be used where a boolean is natural: as the complete expression in a test or as an operand of ||, &&, or !. Hence: if (s == NULL) One exception: lset_t values may be treated as booleans (technically they are, in the original sense of the word) It rarely makes sense to compare a boolean value with TRUE or FALSE. - don't use malloc/free -- use the wrappers (see defs.h) They guarantee allocation or death. - streq(a,b) is clearer than strcmp(a,b) == 0. memeq is clearer than memcmp. zero is clearer than memset (but zero(&array) not zero(array)!). - use passert, not assert. - memset/calloc/alloc_thing can set memory to zero but a pointer set to zero is not guaranteed be NULL (surprising feature of the C language). What makes this insidious is that on most systems the result will be NULL. - side-effects of expressions are to be avoided. BAD: if (i++ == 9) OK: i++; - variables are to have as small a scope as is possible. Move definitions into inner blocks whenever possible. Often initializing definitions become possible and are clearer. User "static" to limit a variable or function scope to a file. - within a block that has declarations, separate the declarations from the other statements with a blank line. - Modern C allows declarations and statements to be mingled. We have avoided doing this but there are times where declaring in the middle of a block is clearer. - all functions and variables that are exported from a .c file should be declared in that file's corresponding header file. Make sure that the .c file includes the header so that the declaration and the definition will be checked for consistency by the compiler. There is almost no excuse for the "extern" keyword in a .c file. There is almost no excuse for the declaration of an object within a .h file to NOT have the "extern" keyword. We are a bit lax about this for function declarations (because a definition is clearly marked by the presence of the function body). Technical detail: C has declarations of variables and functions. Some of these are definitions. Some are even "tentative definitions". We don't want definitions or tentative definitions within .h files. We don't want declarations that are not definitions within .c files. "extern" usually signifies a variable declaration that isn't a definition. - "magic numbers" are suspect. Most integers in code stand for something. They should be given a name (using enum or #define), and that name used consistently. It is especially bad if the same number appears in two places in a way that requires both to be changed together (eg. an array bound and a loop bound). Often sizeof or ELEMSOF can help. - Conditional compilation is to be avoided. It makes testing hard. When conditionally compiling large chunks of text, it is good to put comments on #else and #endif to show what they match with. I use ! to indicate the sense of the test: #ifdef CRUD #else /* !CRUD */ #endif /* !CRUD */ #ifndef CRUD #else /* CRUD */ #endif /* CRUD */ - Never put two statements on one line. Especially empty statements. REALLY BAD: if (cat); Exception: some macro definitions. - C preprocessor macros are implemented by a kind of textual substitution. Be sure to put parentheses around references to macro arguments and around the whole macro body. If the body is meant to be a statement, put braces around it instead. #define RETURN_STF_FAILURE(f) \ { int r = (f); if (r != NOTHING_WRONG) return STF_FAIL + r; } Note: to make a macro body behave as a statement, some conventions wrap the whole body with do { } while (0) (eg. the Linux Kernel Style). This makes a difference only in this case, where a such a macro is used unbraced in the then part of an if with an else. if (test) MACRO(); else whatever; If the macro body were only wrapped in braces, the result would be a syntax error (automatically detected and easily fixed). This tradeoff favours simple braces. libreswan-3.32/docs/README.IANA-PEN000066400000000000000000000003271365625662500164100ustar00rootroot00000000000000 https://www.iana.org/assignments/enterprise-numbers The Private Enterprise Number 41286 has been assigned to The Libreswan Project. We might use this code in the future for DHCP,DHCP relay and/or SNMP add-ons. libreswan-3.32/docs/README.OCF000066400000000000000000000000471365625662500156660ustar00rootroot00000000000000 See http://ocf-linux.sourceforge.net/ libreswan-3.32/docs/README.XAUTH000066400000000000000000000053321365625662500161520ustar00rootroot00000000000000 XAUTH Server Support Based on FlexS/WAN code from Colubris Networks (www.colubris.com) Ported to Openswan by Xelerance (www.xelerance.com) Sponsored by Astaro AG (www.astaro.com) Ported to OpenSwan by Sean Mathews Nu Tech Software (www.nutech.com) Also added MD5/DES password file support and reworked the PAM code. XAUTH server code rewritten for Openswan 2.1.0 to permit both client and server side code. Many changes, most visible to user. Threading fixed by Philippe Vouters in Libreswan Addresspool support added by Antony Antony in Libreswan Installation: 1. If you want to be able to yse PAM to authenticate XAUTH users, you need to also set USE_XAUTHPAM=true in Makefile.inc. 2. Build & Install as normal. 3. If you compiled with PAM then 'make install' will install the /etc/pam.d/pluto policy file for pam authentication. 5. If you choose the password file then create /etc/ipsec.d/passwd with the following format. userid:password:conname comments are allowed by putting a '#' as the first character of any line. You can allow a user access to any connection class in ipsec.conf by leaving the last field of the password file blank or '*', or set this field to the connection name in your ipsec.conf that you wish this person to have access. Note: The crypt() call is used for passwords. This means you can have DES, MD5, SHA1 and SHA256 hashed passwords. In FIPS mode, DES and MD5 will not be available, so it is recommended not to use those. Some of these can be generated by any typical htpasswd utility. If you need to use DES, use htpasswd -d instead of htpasswd -m Configuration: One way to use XAUTH is to have a single shared secret (PSK) for all road warriors. This is not the best, but it does work. Configure as normal in /etc/ipsec.secrets - eg: 0.0.0.0 1.2.3.4 : PSK "a secret for the xauth users" On your conn block, simply add "{left|right}xauthserver=yes" to enable XAUTH, and "{right|left}xauthclient=yes" for the client side. Client Configurations - these assume you already have a working non-XAUTH connection setup. These are tested and known to work. SSH Sentinel 1.4.1 Note: 1.4.0 has a bug where it will only propose Single DES, even if Single DES is disabled. Please upgrade to 1.4.1 1. On the Rule Properties page, enabled Extended Authentication. 2. Click [Settings], and check "Use authentication method types" 3. Optionally set it to save your login information. SafeNet SoftRemote LT 10.0 1. In Security Policy Editor, open your connection. 2. Expand Authentication (Phase 1) 3. Click on Proposal, and set the Authentication Method to "Pre-Shared Key; Extended Authentication" Note: SoftRemote does not let you save your Username and Password. libreswan-3.32/docs/README.labeledipsec000066400000000000000000000002221365625662500176660ustar00rootroot00000000000000Be careful with deploying this. Please see: http://marc.info/?l=selinux&m=119550363105309&w=2 https://bugzilla.redhat.com/show_bug.cgi?id=235720 libreswan-3.32/docs/README.rfcs000066400000000000000000000157341365625662500162250ustar00rootroot00000000000000 An IPsec roadmap is released as RFC 6071, which lists a lot of relevant RFCs https://tools.ietf.org/html/rfc6071/ To search for IPsec related RFCs and drafts, see: https://datatracker.ietf.org/doc/search/?name=ipsec&rfcs=on&activeDrafts=on&oldDrafts=on IPsec related RFC's and drafts (list will likely be out of date): Overview RFCs RFC 6071 IP Security (IPsec) and Internet Key Exchange (IKE) Document Roadmap RFC 2401 Security Architecture for the Internet Protocol RFC 2411 IP Security Document Roadmap RFC 4301 Security Architecture for the Internet Protocol Basic protocols RFC 2402 IP Authentication Header (AH) RFC 2406 IP Encapsulating Security Payload (ESP) RFC 4302 IP Authentication Header RFC 4303 IP Encapsulating Security Payload (ESP) Key management RFC 2367 PF_KEY Key Management API, Version 2 RFC 2407 The Internet IP Security Domain of Interpretation for ISAKMP RFC 2408 Internet Security Association and Key Management Protocol (ISAKMP) RFC 2409 The Internet Key Exchange (IKE) RFC 2412 The OAKLEY Key Determination Protocol RFC 2528 Internet X.509 Public Key Infrastructure RFC 3526 More Modular Exponential (MODP) Diffie-Hellman groups for Internet Key Exchange (IKE) RFC 3664 The AES-XCBC-PRF-128 Algorithm for the Internet Key Exchange Protocol (IKE) RFC 4109 Algorithms for Internet Key Exchange version 1 (IKEv1) RFC 4210 Internet X.509 Public Key Infrastructure Certificate Management Protocol (CMP) RFC 4304 Extended Sequence Number (ESN) Addendum to IPsec Domain of Interpretation (DOI) for Internet Security Association and Key Management Protocol (ISAKMP) RFC 4306 Internet Key Exchange (IKEv2) Protocol RFC 4718 IKEv2 Clarifications and Implementation Guidelines RFC 5996 Internet Key Exchange Protocol Version 2 (IKEv2) Procedural and Operational RFC's RFC 1750 Randomness Recommendations for Security RFC 1918 Address Allocation for Private Internets RFC 1984 IAB and IESG Statement on Cryptographic Technology and the Internet RFC 2144 The CAST-128 Encryption Algorithm RFC 3457 Requirements for IPsec Remote Access Scenarios RFC 3585 IPsec Configuration Policy Information Model Detailed RFC's on specific cryptograhpic algorithms and ciphers RFC 1321 The MD5 Message-Digest Algorithm RFC 1828 IP Authentication using Keyed MD5 RFC 1829 The ESP DES-CBC Transform RFC 1851 The ESP Triple DES Transform RFC 1852 IP Authentication using Keyed SHA RFC 2085 HMAC-MD5 IP Authentication with Replay Prevention RFC 2104 HMAC: Keyed-Hashing for Message Authentication RFC 2202 Test Cases for HMAC-MD5 and HMAC-SHA-1 RFC 2403 The Use of HMAC-MD5-96 within ESP and AH RFC 2404 The Use of HMAC-SHA-1-96 within ESP and AH RFC 2405 The ESP DES-CBC Cipher Algorithm With Explicit IV RFC 2410 The NULL Encryption Algorithm and Its Use With IPsec RFC 2451 The ESP CBC-Mode Cipher Algorithms RFC 2521 ICMP Security Failures Messages RFC 3566 The AES-XCBC-MAC-96 Algorithm and Its Use With IPsec RFC 3602 The AES-CBC Cipher Algorithm and Its Use with IPsec RFC 3686 Using Advanced Encryption Standard (AES) Counter Mode With IPsec Encapsulating Security Payload (ESP) RFC 4196 The SEED Cipher Algorithm and Its Use with IPsec RFC 4106 The Use of Galois/Counter Mode (GCM) in IPsec Encapsulating Security Payload (ESP) RFC 4305 Cryptographic Algorithm Implementation Requirements for Encapsulating Security Payload (ESP) and Authentication Header (AH) RFC 4307 Cryptographic Algorithms for Use in the Internet Key Exchange Version 2 (IKEv2) RFC 4308 Cryptographic Suites for IPsec RFC 4309 Using Advanced Encryption Standard (AES) CCM Mode with IPsec Encapsulating Security Payload (ESP) Dead Peer Detection RFC's RFC 3706 A Traffic-Based Method of Detecting Dead Internet Key Exchange (IKE) Peers NAT-Traversal and UDP encapsulation RFC's RFC 2709 Security Model with Tunnel-mode IPsec for NAT Domains RFC 3715 IPsec-Network Address Translation (NAT) Compatibility Requirements RFC 3947 Negotiation of NAT-Traversal in the IKE RFC 3948 UDP Encapsulation of IPsec ESP Packets RFCs for secure DNS service, which IPSEC may use RFC 2137 Secure Domain Name System Dynamic Update RFC 2230 Key Exchange Delegation Record for the DNS RFC 2535 Domain Name System Security Extensions RFC 2536 DSA KEYs and SIGs in the Domain Name System (DNS) RFC 2537 RSA/MD5 KEYs and SIGs in the Domain Name System (DNS) RFC 2538 Storing Certificates in the Domain Name System (DNS) RFC 2539 Storage of Diffie-Hellman Keys in the Domain Name System (DNS) RFC 3007 Secure Domain Name System (DNS) Dynamic Update RFC 3008 Domain Name System Security (DNSSEC) Signing Authority [obsoleted] RFC 3130 Notes from the State-Of-The-Technology: DNSSEC RFC 3225 Indicating Resolver Support of DNSSEC RFC 3226 DNSSEC and IPv6 A6 aware server/resolver message size requirements RFC 3757 Domain Name System KEY (DNSKEY) Resource Record (RR) Secure Entry Point (SEP) Flag [obsoleted] RFC 3845 DNS Security (DNSSEC) NextSECure (NSEC) RDATA Format [obsoleted] RFC 4025 A Method for Storing IPsec Keying Material in DNS RFC 4033 DNS Security Introduction and Requirements RFC 4034 Resource Records for the DNS Security Extensions RFC 4035 Protocol Modifications for the DNS Security Extensions RFC 4322 Opportunistic Encryption using the Internet Key Exchange (IKE) RFC's related to L2TP, often used in combination with IPsec RFC 2341 Cisco Layer Two Forwarding (Protocol) "L2F". (A predecessor to L2TP) RFC 2637 Point-to-Point Tunneling Protocol (PPTP). (A predecessor to L2TP) RFC 2661 Layer Two Tunneling Protocol "L2TP" RFC 2809 Implementation of L2TP Compulsory Tunneling via RADIUS RFC 2888 Secure Remote Access with L2TP RFC 3070 Layer Two Tunneling Protocol (L2TP) over Frame Relay RFC 3145 L2TP Disconnect Cause Information RFC 3193 Securing L2TP using IPsec RFC 3301 Layer Two Tunnelling Protocol (L2TP): ATM access network RFC 3308 Layer Two Tunneling Protocol (L2TP) Differentiated Services RFC 3355 Layer Two Tunnelling Protocol (L2TP) Over ATM Adaptation Layer 5 (AAL5) RFC 3371 Layer Two Tunneling Protocol "L2TP" Management Information Base RFC 3437 Layer Two Tunneling Protocol Extensions for PPP Link Control Protocol Negotiation RFC 3438 Layer Two Tunneling Protocol (L2TP) Internet Assigned Numbers: Internet Assigned Numbers Authority (IANA) Considerations Update RFC 3573 Signaling of Modem-On-Hold status in Layer 2 Tunneling Protocol (L2TP) RFC 3817 Layer 2 Tunneling Protocol (L2TP) Active Discovery Relay for PPP over Ethernet (PPPoE) RFC's on IPsec in relation to other protocols RFC 2207 RSVP Extensions for IPSEC Data Flows RFC 2521 ICMP Security Failures Messages RFC 3104 RSIP Support for End-to-end IPsec RFC 3554 On the Use of Stream Control Transmission Protocol (SCTP) with IPsec RFC 3776 Using IPsec to Protect Mobile IPv6 Signaling Between Mobile Nodes and Home Agents RFC 3884 Use of IPsec Transport Mode for Dynamic Routing RFCs that are not really in use or implemented across multiple vendors RFC 2522 Photuris: Session-Key Management Protocol RFC 2523 Photuris: Extended Schemes and Attributes RFC 3456 Dynamic Host Configuration Protocol (DHCPv4) Configuration of IPsec Tunnel Mode libreswan-3.32/docs/copyright-sh000066400000000000000000000011641365625662500167440ustar00rootroot00000000000000#!/bin/sh # # script used to gather/commit updated copyrights not done by the authors YEAR=2019 cd ~/libreswan for i in `git log --since $YEAR/01/01 |grep ^commit | sed "s/commit //"`; do export a=`git show $i | grep -E "Author" | sed "s/Author: //"`; for f in `git show $i | grep "+++ b\/" |sed "s/^......//"`; do sed -i "s/^\(.*Copyright ... ....\)\([-,]\)20.. $a/\1-$YEAR $a/" $f sed -i "s/^\(.*Copyright ... ....\) $a/\1-$YEAR $a/" $f # builds a list of copyright lines that still needs to added semi-manually grep -E "Copyright.* $a" $f || echo "$f: Copyright (C) $YEAR $a" done done libreswan-3.32/docs/diagrams/000077500000000000000000000000001365625662500161665ustar00rootroot00000000000000libreswan-3.32/docs/diagrams/KLIPS.png000066400000000000000000000323221365625662500175600ustar00rootroot00000000000000‰PNG  IHDRÝ+é¹ pHYs M MÒέNtEXtSoftwareESP Ghostscript 7.07¦¼ž§ IDATxœíÝÛ’£º²Ps¢ÿÿ—9ÄVi!îה㡣šÂ€U¦Sº¾ïïéºnužw·xÌ¿çW™g‘-™c”]ÄhU÷Ìi~oÙ²(s{.bÄk¹oÉÀ+nÌ%ÏäéšqK.y>+H'ЀësI×=4f%Ôª€ó®<‘G(ZDØà˜ËrI¨ZE¨6ú¿K–-ô}¿åŽm@(ä’h¡d š@uÎæ’˜¡d š@]Nå’È¡d š@EŽç’ø¡d š@-æ’ZBÉ@4€*É%u…’hñ]spDnw.©±XTa_.©=”(™@dÿÞÞ¾H:|^Õß(€ïØQÿ¨½X’4óF*¥ýŸçy–@->4î•„’Wô}¯¨ÂÖ\ÒÒéÄú--íE5²çñU_/9vœu€~žP„=ˆlS.qFá$»Pþ @p¯ÕK|iF®¿Nx8†ïgùÄÔ‡’®H_¦ó«†‰£¦Uä¯Ê×ëë Ôk½^r ßÿO91ý<š2·ê|¶ÉÄ“oä®í4Ä¢y¢'UGò2Éä<ùSv¦,dñÚðÜý^‚Ũt±7g¨||VÙÍ—¦”ÿ-w’庅•Ž–¼¼ «ëìµø”•zÉ“—Qä}1ùP’í/ß»F¦vå3úï¯è@Ì;—ÿú“{~ÚKó-¯tãz—{->âÆ~œò[cêÊÍð›9Œ^XŽr[#üÖRõÞI—¬ty½[z-Úv}?Îä±µ<Î.LY~áä ŽãŒ¬æƒÑ_)ŸÙ—¶¼üŽõ4Ãó„iÐ\ålr¨Ç®¾Âcã¯÷®WL>«úûÐCiaÀi>Î#Ÿùw: ,Œ Ùµ^¡ø2¹„6­Ž½ãÜx8m"”'—ЬՔ0ºŠø’İ%š,¬W(>Îøê–nÖ—‚¹«·v]±5¹¨Éß.¬t×E¿ w4øˆk¾#Ö«ù7„vŽÃ߈L?…\DñN.9Öß?·  /×KÎß.hFeý8j$аã× /ÏÆ‰(e“ËoÖ—&ÚCžWÙ}èá¼í7Ý9¹LöÚšKn°VÅ’/ËGä»tÞk³0Oùs9¿‹ÂÛq†nætÞÌ©ˆ6Ã߈lG?N%ekßø’6¢ ӷƽ*–@d»sI½%¡‚;R/©1š%ßÁ~œ£ Ü'Æ—(–@Žç’ZJ&B ÔâT½$~4J‚ˆ¿«ÁÙ~œÑƒXCJ`ćT¨ã]z<ìÛ„ÚI>Hûñ]yœ rÔ ²LßâsTáâCÕëǾ×7€-bvüµÍç¨Âõgñ·¾û"µ»«ºðdJH  ÷özÜ&—¯+‡wÙûwëÒ‡£sLpáµ?s 4pwÙθ7— Rz8P.Ï7@(Oä’$•O&¿SæicuˆLWÀ1æ’dòg‘“Çtg¨Ñ;Ïž+‡$‡+Žð"{ ÀIO磀9ïÔK mžŸ pLS¹$•ÐÕÒyE¾ãÙ x'—ø6 ”Í%F šêǀΔíçnÄÅyæ½ï4À)ì>ê%@ïÜïK“=U~tßðò6âÃ0Çr°ãäœù “¹ƒz •Y¸+ÄhÊä=Ä'{aÊ9G· OèÌ}ÉY¥^@;R-dˆ©Â±|AèÆ»Wˆ#KhÄ/<vÔ1Ä‹ôãÐŽÃ,[^%µ<@½€*•}4å¸×4%&2÷s91Ÿ^c¸Ã 7`½û®¯î*Ë»ì‡éÇ¢K€(ä ¹ˆB.¢K€(ä ¹ˆB.¢K€(ä Ï >žBÕ*Ï탋ÙÓD!—QÈ%@r …\D!—QÈ%@r …\@}ºî®û•ß·d¶K€(ä Šoo7t» ¥Ê»`Ò”¾ïÓ¿ù ç^»äjU>&³L¿,p¤&Ì­›ÊFúq¨Ò(I ÿíº.ý°q »^ÂÝÔK¨RÙ5ó;Ô£û&õ*¦Èѹ.“+á1£¡¯©_&ÿm9ÿ®—ðý8Ôgˆ“ƒ^禔£_W_ÂóÔKàzå5l!—Àe&Gá°\D!—QÈ%p=ƒKŽ‘KàJ Àr …\S28Ì}Õh«sÈI@Eäáì;IbꢈB.¢K€(ä ¹ˆB.¢K€(ä ¹ˆÂý^á¬tOU÷œ8I½ŽIß÷ À%ä ý8°Iþ¼¡:2LI%“Ñœù<å«ú¾/_€z l•úkòH1êÄéºn4e®—G"(É%°ÏBžÈ«#¿¬ 2YYÌ P!ý8p™Ô;3šøÊÆÔH½.VF“‘!¾È+%õØjò>%“ÃWÓ(“Ô‰SÎ@I.­Ê`1ßZÎ<‹(ÛÑÈ%ð´wÓ@yé2@r ¬KÔœ?‘¯Ž>¹ÃÜJ_Ù˜cD(ø¹Ö]xR|åü:w“·ZT”Ÿ€“äøŠr¸î¯¶€4O./G€˜Ü¿ˆB.¢K€(Œ/á»Ê±Ÿù”;®^q3€eê%|×Üý[S(î%ÿs*ÀSä>m¡z‘~õ|…C >«Í~‡õ.ƒR÷JúaµéÊ^ž-SF/Ÿœ-Ý[öw[w@X æÇîp¶ÑèÜ_š’¿p”3F#WFË/˜Ï6,vôD@Mà#ôãÀï·ø™¹¤;üªìîYø¡\QªŽäe’å4L.¿rEÙÛ2—ÊÒÈ®u•“«VP#¹f-—(F1¢Ì £^žÉ_mÜ Åà#_ÇLMÝþÛÉa% ù#õΔ/üe¥eàSäøýæïerfþ…û£l¡J ð)úq€(ä ý8ûéìWÛ IrÉVù³^W“€È%ëB%’AyÕ4Àø’MžûÝ¡€–È%+$à1rÉ’*B‰’ ÍK€¸òÌ-ü3îõÂãKüzp˜r |Í ¹äÂ$á€5ŽÝ"µÓT@ò†pÿ’+åõ›å‡Á–¿›rx~;”+ž4@.¹L~ûµÉx1ùäú¼û<ŸáXžHKK=;¹3lÛïîã 1O‘K®”ÎŽÛO“——4†ƒøpx§ZX —¼)Ï}ß_õ½0¯ÊäÕšŸŒB¦º"DuœøÜÁvrÉ•tÄäâ¦ÚÉï¡'ßΟc%õìU”ª7NÁ+ä’ËäÅ\~H—É™ó^²U'BXöXø¹äJåÑ3ŸRŽ>Í¿| Ï}ªþ2 @KÜ¿$Šü™‡SBÙůP/‰bÔ­óVÃ8Y^$—r8ÜÑcœ,Ï“KX'£ð ¹„}dîcÜë’*n€ýâÕ4“·E€Ãä’UD“ N8I.Y6š ·q‹™b¶Á_²IÌh3‘ Cà¹d+§ÕÃd”×…­«ŒÈ%ð/ˆ©îoK¾í-Ð8äÊ~{È3´3ì¢^ísjjáþ%Ð>¡¨…\D!—QÈ%@r …\D!—QÈ%Ь®ëÜݨ‹ûªA³ÊÏ»‘ œ\ò'¾G_]¶kæg–Ÿlya¹ü3kÜ¢™æ°ü½kÌwò§¶`‡ºïN}íݵ»Wwco‡3&K&öghgØE½š¥:TG.ùãØMcìÒ@u\óÇ• ð.¹ˆB.¢K€(ä ¹ˆÂuÂp ×sœ'—Àeêº_Èù µüä…ûœ/Lï©«Ý€[éÇŽòÄ`ažÉé‚0G½8kxX`ž6ôjåjl Ù‘·È%ÀAywLyÂJžWæNÏÍ?ǧº÷Uc¢úq€#–ÓFVRˆ)»~Ò§C@½8(…‰8Ëeƒ¡¾ríÕQ/v[¾ç÷ߺˆ´l'—ü©®^´0X$ÿ( ì¢çû(ÀFiLkúoþÛò£4LÉ_2úíär€’K€#æ2Ää…9 /‘E€œ~8+¯èª8C.Ëè 8I.¢K€(ä8Ë Á®"—Àe .8I.¢K€(一€KÈ%p Ñà<¹ˆÂóq¸‘«g÷Rt>N.á^N´Û‰qúq€(ÔKà»Th€häø(]l@@úq€(ä ¹ˆB.¢K€(ä ¹ˆB.¢Kˆâá{v]wӇź•*Àr Q<|ûÑ›V×u]Z²h°—\—Ƀˆ»¼àù8D‘* “g÷ÑÄrž™`²†q`ás«­:/Ÿ°J½„ˆú¾_Miž4[>eR>ÛÜÒæµú’Éw±ø.S/!®QébTPI¿JI"½jy™£)å0ÕrQ£-YØHÎK¨ÃpúŸ+ŸœO˃USô¹;‚ˆ8[­i}ö/ò…7®¢“\B5–;MòjÊòø’-§¢rQÏÂ(Ÿ´ñÔûÁ?ÊÆE}!xUJ.!rèë¸×|ž²š2ir¶ri“‹Ê»æ6rîí°‘\B Wµ”SVgز–“ ŸœM8C.¡M“µ“CŠ& ÀrÉg‘ÒÕ1'ÿ·þ5—7r˜hw8@.ùã nUü ªØH€¹¯…\D!—QÈ%@r …\D!—QÈ%@r …\D!—Qx>÷š|®/L’K¸‘çÛ°‹~œ?N¢ð.¹ä‡¶ùûÄ'—QÈ%|ˆ’ @pr Ÿ ‘TA.¢K€(ä>¤ï{:‘É%´¯ë:7§¨‚\D!—о¼X¢p™\D!—QÈ%|ÅèŠ<è$—ðùÍ\©“\D!—QÈ%ôà]rÉ š—†˜ø.“\D!—QÈ%@ÿÞÞx”‘%‘©—Q¨—ðWAÆôn=I.à5ºT¢y=,êÇ¢K€(ä ¹ˆÂ¸WŽx}`Ô1•nö.FU“K8¨ºó_×uÕmó^_^@Ûôãüiþ¤ÁÉ%|×€wÉ%|…z@|r …\D!—КÈã¶møUä€\@k"'›Û¶ü^_Ž&r ¼ ùÏ‘CÕÜW €ÖÌÕæ&–ó¬…4ÃðòÕRG>CZãðïð«ÑZ¾p+ÈIê%4®ïûÕ´‘æùeqa!äËœ\TJ“ ÙòÛoR/àFu‘”'F£MóÆïÛáê%„|ð—ÁóP©”HòÎÁ[äB‹|€0xª¶AFå“…yFeN’Kàƒç!¸Q—Í ÿ.‘Š%yí¤œ²¼–Ñ'W½qâhã?{`1¾„ЖÕŸQŸ¯%$_.³àfð<„UD=9ÃòZò™'Þ2Ñ1d ^BMÊAõ'GÔ^[¾dûk7½ NÝ”kW‘_<üåCŠz õÉË—¨/_â`õºêÃûÌgòF&_#—üùø®P£!1ÌuÖ‰8°WG?Χ±Q¿å%º~ž¡^Bt“C_çÆ½ŽnE°½xXË®—Ìm$‡É%„¶.'—p„Àôãð„/W¾ðî&—À„€KÈ%<Ä™€Ur ·“HØH.ËH`'É%p–+Ì®"—ð¾ï•X&—p/µ¶“Kà2jB'É%Ü+/–´Z8ùÂ{x†\D!—QÈ%¿ßo;a|¼¥Ö\"I,Ð8TªÖ\rÓ…]ÔÚØÛ yµæ’k¹¼"¨>—( ”Ä,*U}.šQq.¹£LÒX饱·@ó*Î%×r €×UŸKä‰Iš€ÕK®=û6v.oìíðuç.ÿ®Œñ·“þ½¸îìR—×-*m·½›}U»=Ù\/þi”Çø7‰hÕ›¹ä÷ƒéM'*í¶‹æ‚ÒÝœõy‹~ ¹€j¸Ÿuóä꣛©Ur †ó½³>o‘K€(äj¢–Ó6¹€ÿˆâ¿…öòýK¸› Xö’{^T}.™û¼¥½j4Ã0}r⧤5Ôdû”³•Ók·ñ-oi‡Ñ ©ÊûS¿ü[Àåì]Û‰qïj¡§ÿŸôó0½ëºá”ÏŸ}G?erÈ}úoÞ>“çÎ&›nrWÉw¡ÑÌ¿©v˜¼Kædˆ)[û†÷P™êsÉäÑ|î¿kf’Õ"J{Ê ò›¿¡ÓB;´”ÛP}.Y6yjyeKj÷µv=³ôLWK{…%€ûT?¾ä ýú‡5Ùtsµ…ǘ•#Eæº{Ê…K*¥O璖Ωk²éFƒUGÓÓp¥¹—”–“ÇÜ꾬ñ~®òµgÙùr,ŠMŽ`Nã¹dt&pb8£ÉÉ‚Ô}³}þ…˃¿ÖzÇ´ÓS:õn>19bà;FƒÊn…¯5ÝäGsƒ^·´ÃäKʱ& 7)À^íä’ó Ðöiµéö6Åê¥^ 3ì¤ð)÷ã‘K€(ä ¹€?Í\·˜?µêÝ-a¹€?m Ä.¯ÛqcØE. )“Oð¦í\' Àyy¥aò ¦L®eáUçW7ù4+¥ ê%Ì*¤0yožQ”ɧ¬.y4euQ Sæúk$’Ѝ—°"¿OqYP0](Z̽jõ†£y¯n$õ’KØ*8ÃdþØž ŽÕ0ÒªEVéÇ`‡Õ>š /Ð\”N™¶©—ð“C_çF§ŽžmY>0µ´ðDÌÑ'Uv-Œ})ßÁÉ%üY~®äê+'§¬®å7Ó+´qáåF "õ’K¸ÑdíäîÐG¥./ç—ŽÑn»h.8 ]5sò¤~k&XØÈÕË‚ˆéÍ\b_9F»í¢¹à˜*>;Ul$»¸ˆâë¹D…°:~žŸ½à~_Ï%?'C.¤X€[É%°‰Dð€OçgšAyÏDxŧsÉÀóŸ ¹vbn%—À:÷±xÆws‰3Í oÅÞõÝ\²üÈÊïX}X(?{ ÀSïñÝ~ ¹ˆB.¢K€(ä ¹ˆB.¢K€(ä ¹ˆB.¢K€(ä ¹ˆB.¢K€(ä ¹ˆB.¢K€(ä ¹ˆB.¢K€(ä ¹ˆB.¢K€(ä ¹ˆB.¢K€(ä ¹ˆB.¢K€(ä ¹ˆB.¢K€(ä ¹ˆB.¢K€(ä ¹ˆB.¢K€(þ½½К®ëÞÞ¶ÚòÇò…'É%p½¾ïßÞÖu]·ú—Ú2p!ý8@r …\D!—QÈ%@r …\D!—QÈ%@r …\—ɤâ¡*È%@r \ÏÃÞŽ‘K€(ä¸Lß÷†•œ!—QÈ%p=ƒKŽ‘K€(丒J Àr \L48ìßÛp3A¸€"Ñ«nj"Q`ÐH.ù9²S-q ÑD!—QÈ%@r …\D!—QÈ%@r …\D!—QÈ%@r …\D!—QÈ%@ÿÞÞfu]—~îû~4%M½¤œµP/‰«ïû!d¤¨‘þ;S vrI­ÔEh~œ6Íõõ}Ÿ~˜›m˜GîàyrI}R˜XŽs}=)š,Ì&”𠹤>[BÃ(|äSR-$ýw˜A€×É%mõÚ,EˆÃ¸×f•ÃÀ‚“KB+»Z~k—ç3/ÏŸzsÒœ£%ÀÃôã„6ªm¬–:Fw:Ù»üí/€;¨—|ˆN‚“K¾Bï ñéÇù •âS/¢K€(ä ¹ˆB.¢K€(ä ¹ˆB.¢K€(ä ¹ˆB.¢K€(ä ¹ˆB.¢K€(þ½½—éºîíMNi$—ô}ÿö&géÇ©†‚Í“K€(ä’š(™Ð6¹¤ _ —QÈ%@rIMú¾×¡@Ãä’ t]ç-|\D!—T /–(œÐ0¹ˆB.¢K€(ä ¹ˆB.¢K€(ä ¹ˆB.¢K€(ä ¹ˆB.¢K€(ä ŠooÀ)]×½½ úÚû¥v}ß¿½ @eêÎ%?>ˆJŒÐD!—QÈ%@r …\D!—QÈ%@r …\ÂsF7Úêºîü­·†%¸…@äž“nÎ;Ĉ¾ïOÞ®·ëºÑ2¨š\Â½î‹ ù’=Ž  Õ?‡·ŒÇ FY!ïdþ[N\X~š9_`þ’ÑËG¿ :r ÇMö¡ä¥Ls·¬bùU£@ôãp™T1€cÔK¸˜žS/¡y¯ÐÛÛÀäÎJY!,ݘdòç-7/™¼âfî…½4@?¥°pÌÜo·ˆÕî? @ä^6YüØ~µNºœX@h€\ÂËNæ‰áåB @Œ/¢K€(ä ŠêÇ—¸¡4£î\b´#´D?ÅGs‰ÞŸc´¹-7íØå£¹äç{”và>ßÍ%@4_Ì%¾ñ£Ý¸Ûs p^z&‘À \軹dxØÛÛ[QíÀ}¾›K€h>—KRñ™]´ø\.ÉO®N´Ûi7FÒn`.ô¹\„%—QÈ%@r …\D!—QÈ%@r …\D!—QÈ%@r …\D!—QÈ%@r …\D!—QÈ%@r …\D!—QÈ%@r …\D!—QÈ%@r …\D!—Qü{{hP×uéç¾ïóÿSÊùˉ|z ×ëû~È£‡F1¹€G©‹°@?Œ:€Ò”ÔTV\Ò”a¹§jr Iab9:ÌõõŒÆ©LÎ&”ÔN.à![BÃä ÙaJª…¤ÿ3¨‘´D. Q¯ÍY¤IƽK8 ù¹€[ä½-£ž—…ù‡–çO½9iÎѨ—~n‘—7VKi†E‘ɚʞ­#(õ¢Ó‰ór ¡éùý8„¦Rò)ê%@r …\D!—QÈ%@r …\D!—Q¿³¯ð0ÇÍÐ8æ£Oð¨…c´#Uï[6¾ê75ÒD!—QÈ%@r …\D!—QÈ%@r …\D!—p¯®ë&]rÕóL<¥%r ÷š»—¿{üS’K€(þ½½´©ì^žƒ˜ž†˜þ;ü6Ÿ8zùhþ¹BËäK†ŸÓÇ–ÌcÔK¸^ʃüWËÿýªüírt˜|ÉäJ÷.™gÈ%Übûi>Í9*–¤³G¶5²r~É(‹"F¼F¦^@ËtâÔE. Yzgª£€f©”TG½ˆB.¢K€(ä ¹ˆB.¢K€(ä ¹ˆB.¢K€(ä ¹ˆB.¢K€(ä ¹ˆB.¢K€(ä Š¬£ëºÖ²×–­êûþ-YªwmL,…jÒ½žoÕåæŠÜ˜¯ì‘dYØ,Ÿrc.Iž"(øßIDATÎz÷õwß‚¼\´í9fx¼…šëÉ· ¹àÝûßcÇÍÇtÝ- µ°º_s ø{û=üG¼Û­Máïu­Éw´e—Ø8O¹ðª5öa¡.×/vèÆöé¾ï«Í¶Ú€ïn@{ÇÙa'¹o·Ô\µú­·7ŠÚ÷º•êI/6`{¡äVš‹Ÿ#ï¹8—´}D{àƒªÙåò&µàrê%4®í3@cä ¹ê¦Ø´D.¢K€(ä ¹ˆB.¢K€(ä ¹ˆ¢î\2w;©îÞžê,7àÃÓ˜Éì2ÏoR¥>Òb圜²Ði(šWw.™ÔäcǦõî0œ0ÒÎéü±Å—?Îù»í<¥/7©/—,ÍGisè/i“û¬¶mÚ9?– -é㼑†¢%ÿÞÞ€ù,=$}u(gÈ_ë¹!¿s ÈÈdcŽþ»Ð¶ßiÞ¹Ï]jí-97[“ÊvÈw¤¹]kä EÛ¢ç’ß?‡ùg5ÿíÏW„yðBåIôw¨mGs¶'ï“§ÒÑļaSK~mŸœÛaÊ]kaf¨]è\2úÚÔü¡ürðr“_a;ÛÖ¢ÌÚ„Î%ƒ½G+¸­q•álz²çËþùûo…é÷߆5ŽæÚHCÑŒúƽ.3ø‹[&âä1({%Ê–ñqÞHCÑ’Ðõ’Ñ×Ó²Ç:™F÷ñsÀ±üeoÀ‘r7ÛÛ¶“c,š”·CÞùUŽŠ˜;¦ _¿öqí0£›Û»>ØP´êâOóg²»ß l`Ï»ð=6ß\“iãü{Û€æß µÖÔK.¢K€(ä ¹ˆB.¢K€(ä ¹ˆB.¢K€(䨛'˜-‘K€(ä’æÈNdùóßîâ\Òü9àî‚yÛ ¨Çár—7©=pÍ—»¥^Òäõ±h«Gºq­6éMZm®›ö@Í׺>—ô}ßÞõᨼ\“Mz_«6Ù\÷íš .tãÎ×Òõ•¨¼œ&Ý¥ùæÚröÝ~†n¾¹àB1p\Õ_¬¯Í%À%\D!—oj©û8O.^#”#r …\D!—/Ó›$r ð—à%¹ˆB.¢K€—µ÷|à0¹xG>¸Ä@` —QÈ%@r …\D!—QÈ%@r …\D!—QÈ%@r |Qz.UùC9Ïäoï —ëžyŽ•\ßíiÞÿÞÞàQ“=8y9d˜>*äóäifnâ(ñ ³M¾0§^ß’ÁðCß÷£P2š2·Õ¨ÑÿO¹ä¹åË%ð-£zÉ™Á­“5•3#Qôã/‹Ö½ ÍK,ÃyŒ(û_ö.v²hûÂåàMÏŒðJ Ÿ¾QXٻ̹ð±e±r |ÔBõ"eˆÑp×r”ëä¸×¹µ¬Ž{=ˆ~'¾TÕ¢ù7Ès§ÛQ¯Ä\'Åêl“/\íðêÒôÉ7µÑ™Fhþó[9à°æOÛÍ¿A8æÀG£¼yr úq€ÒU<»¢IYÈ™œM.v8\DÜòB÷/¢K€(ä ¹ˆB.¢K€(ä ¹ˆB.¢K€(ä ¹ˆB.¢K€(ä ¹ˆB.¢K€(ä ŠooðŽ®ë6ÎÙ÷ý«òßž¤^ßÕÿOúyò‡<‹ä¿*{’z ,™;éö}?:[Oι:Ûä Wg;°º²ª1Y瘜m!y ¿íºî’ª‰\KN·£_Í͹:Ûö|pÉêöZ-‡,—]ä`Ú…4É%À)϶€Ç¤ZË…=5Ëäà¸R@Ë=5~?q=pÖUßRž¨É‘•×ì,ܤäÖû—È%@ÿÎh>{¨Ã‡IEND®B`‚‰PNG  IHDRÝ+é¹ pHYs M MÒέNtEXtSoftwareESP Ghostscript 7.07¦¼ž§ ùIDATxœíÖ1 À0À¿çñà‰‚žÝ3³Îï€Ç—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—¾¨ð%@…/*| PáK€ _Tø Â—4ÿ S }ÃIEND®B`‚libreswan-3.32/docs/diagrams/NETKEY.png000066400000000000000000000307771365625662500177110ustar00rootroot00000000000000‰PNG  IHDRÝ+é¹ pHYs M MÒέNtEXtSoftwareESP Ghostscript 7.07¦¼ž§ IDATxœíÝY¶›º¢PóFúßeÞ'º„ÊØ¦Xs~dxc* I@×÷ýë>]×½çÞ5.óçúEŽ³ÈžÌ1É.b ´ª»æ4ÿiÙ3+sz.bÄK9oÎÀ-NÌ%×äéšqJ.¹>+H'ЀãsI×]Ôg%jÑÀïŽ<‘'TZ$¬ðÃrIT]EÔÊ;ýß!sIË}ßïybå€\’J¢ Tç×\’J¢ Ôå§\’J¢ Täû\’J¢ ÔâË\RK(ˆ&P…orI]¡d š@¾chá>Î%5V–Uø,—ÔJT™@²?w¯O$^¯ê+ à9>¨ÿ¨½²¤hæ‡TÊö¿ž÷YµxP¿W%·èû^#&P…½¹¤¥Ó‰ô]Z*E5Rò|Õ×—|wœu€¾žPBÉ’íÊ%Î(üH áw[}‰‹6`âøû„'c¸>,m(år1=¾k`8™°,b<Õx¹. ^ïëK¾¨ïÿš,Ÿ'CÖ=m1ñŒWò£õÔÅÒ\ÑŽSjGÆÕ$‹ãŒÿ,Ùe²‘9Ä hÃuÏ{Ý“ª‹Os†šÇš7ó•!ó?ç…dguÝÆB'sÞ^‡·Ë]lµx”7õ%WÞF1n‹w%Ù?ù§Khj7/0“?_³Äq#ãöÿþbÉ/¥t¼ í…î\îv«%ÀCœØŽ3¿j,M9“^+ç€É„ó^®kK„×»Týi‡¤Cº½Ü=­–m;¾gñØ:?În ÙžpqÇq&ÞæƒÉ _%ÿR–öL~Æršá}Â4h­æl±«ÇGm…ßõ¿þt¹b ðXÕ?‡æ6:œŽûyŒG~ýœ6ú…|´\¡x2¹„6½í=zƹÿëî´…P<œ\B³Þ¦„É]ć$†=Ñdc¹B ðpú—P·ò°¾q X»{ë£;¶gµøíÆB?ºéwã‰ÆqÌ5b½šÿ!lçþ/€dÚq€r âž\ò]{ÿÚL€6Ü\_òûã"€fTÖŽ£Žöý}¯˜ýû,ËùÀñL6Æœ )wc¾þ}ðÃÛå..HóS}Éüͨ‹oißóêöÉKÞQ^Ñ·ø”ˆµåJ$P‹7¹dãíbÃWkoÙ9pq„ñ‡µElOÔèûú’ñã,Orö"<`êáö¤^®ôk;ÎQëñZ¹yxÏ"œZøŽT æ}¿×Wš“Ĥ{ÇâÛI_æ>|Xk²Y\Ääñã »Ö¾ý@‚] ;Û;G‹m+‰]±&Emíù½Z{n.Ûèhµ8þâ‚~\óCDý_LxŸ0Ï2é´4©iÛ÷ûäõÅãñÇ'þµŒÀ¢Ãž«6>@o„{Ík &­¥Üî/Àn 8Ä®ú’.&ãqvL *›±ñÃúÊ@%àz•=‡~·ÿ¡;?΀OíÍ%X«ŽÊ’'÷éq«ÍÆ8óÏóñÝðµÎÐ͜Λù!±Ísø¿’}ÐŽÓF•‰ƒ2Äú¬IÑÈô¬~¯*K Ùǹ¤Þ*¡Â}S_Rc4J ß—í85F Ü#ú—¨,€*|ŸKj©2J ?Õ—äG¡$D~Q Á¯í8“±FJ`ÂN„;ì u¼+¯‡½{EøGT!y ÛÈwäq*䨲,ïb¿ªpð¡êöcßí+À™ m³_U8þ,~×± q¨ÝYµ W¦‰Úpn«ÇÙ‰aqþšr¸—È"öøsê܇°t&8ðÞŸµê¸À½”@6ˆ&ðÖ¹¹dPöÃÊáùˆrE.)JõÉâ5å8m¼’¹,fBEìti.)ÙãýöÇcº³Ôèž÷ ¯U‡_ÏVáFJ Û¼( Þº:—Ø'€5÷Ô—@Û\3¦" ök*—”=ß!€[Œ žBH¡`À~÷äW“ÀÜ¥¹De&°¡©vØé—jûµqñ»Ks‰FVàvõ%@Š{ž÷ _+/“Ÿ¼U~òÜðùcćnŽóÎŽ‹cŽGXÈÔ—P™§BL†,>C|±f>æää%ýò\rÞR_@;J]È#J Çö ¡;Ÿ^!Ž\@. C¼øâ-°“†!n¤€v|ÝȲg*©åêK¨Ò¼fÞïµ wYû<8>¯Œá 7<€õì§¾zª,÷RY¤`ÀÚq€r B.RÈ%@ ¹H!—)ä …\¤K€r B.Rxÿõñ²¡VyoL d‘‚{hÇRÈ%@ ¹H!—)ä …\¤K€r B. >]wÖóÊÏ›3{È%@ ¹Hñçî€ï Í.û‡ÆM0eHß÷åßñ„k“p/¹€ZÍ߆8O¯Qà(Ì©«ÊNÚq¨Ò$I v]W>ìœÃG“p6õ%TiÞ4óúª-FóMõ%TL%Gcä8ÌøøèXI¡`œmÒõµ´ËŒ¿ÿÑ$\F;À¹›øÑ);½® ™÷~}; ×S_Ç›ß#Àr Æe1À䀋¨Hƒ·ä€Ó‰#°“\ÇsøŽ\G’H~!—\Dl…·ä8˜s‹ ØÃsÕh»s78BÛ¦˜q¹„F8,.r6=2¶F1ã@Úq€r B.RÈ%@ ¹H!—)ä …\¤K€ž÷ º®ûîážã ·g²øí×Ë%Öð:y"ê¸LÆ<Œ¶öçâ$kS-®Øâú(ÜK} Luhþ:Ùü¾hB”²Tþg‹~d>Éxœ·“Œ§šÏd²bkë£r/¹þñÅAùÀã¸KÕ–¬ŒÿåIþxíHÉe’IÂØ3á|}”@n§¦Æ‡æyõûäJwø³\}ŽG.'†µ:üñ"& uzhçÿ“ÿú=%aRYÒuÝ0dÞT4®\Ùž­Èäxcãøþú{&x{_ëO0ŸvÞf,öùXûïÞ(_-öeÙ.Q“B¨r/¹>0®yý|Yéèÿ4‹¥e-£Œ+?vN²±ÜRt?m'‚‹é_›ô:üe>G­m˜Wž½Þ%“±BH¹n¦Ö„ {¢Éþ*“ÅÜQ´ãÀ.ãÞ$ó^k-™wc\›¹H´m­å5*ZÛ#G{Ûõd±#ö★HˆÊßÙ…ÞNõ@Çþ§ß[„®ü-v–±3¶U[ø‹u®ñgK} Lí¼Åæ ,wñ)Ÿ¼VžšzÈ<+ÚÎu­-M’K`Á]‡æ“–ûŨ'ùèÞÛóæ¨ŒR×i¾®µ¥Ir ´oÞ)á®Ú O'¹ë4yû¶‚Ç’Kà){à:é²$Kà‰œwçlHàù%@ ¹H!—)äØ2~º+\l£ø)–´J.eåIÞºCr=ÅÇ’K€mÞ'¬†sàJkñ“<ÊC¸'/?†—ç³¶µÇ3yýûv´ñ´ó‡gŒúë$ÛbaØóî½Éh‹ó™—=HÖ`.±ï „³Ê}œ¶_ ?óêÆÖžŸæ_MÖdq¡´mü¿¿?®•Òí’ÉÌ%P‹Åê™×ÒɆ¶}—&“,–¢2P‰¢r Üc8gxö9¯YcßN‹ã+EÔN¿Wøò¬ð;w[P|]¶ ­.JTG.×ëß.#ãšðñç2òâçíÓC™Õdæ“N‹“}žc­„ìœöµ^Š .Úq`¡Cë§Ÿ·¯G¿]ëT»=Múâám)‚êÈ%p¤ÅëTg ¾öc‰ÒˆCuä8’sÇú¥DiÍ¡Fr @›¤dj¤ß+B.RÈ%@ ¹H!—)ä Å=÷ xW½á 7ä’“„§@K´ã)<ï•F¨<ãlÊ\@.¡ºq6e ®¡H!—)ä …\¤K€r B.RÈ%@ ¹H!—)ä …\¤K€r B.RÈ%@ ¹8]×u‹Ÿh†\œ®ï{ñØC.â”Óu]ß÷w¯p¹¸Žœl“K€r pÕ$Àr hÈ1Ò <ÍŸ»W¸Ç]7È|´Ü6îâ‘®`?¹žëâóå§^Ûè$ÛF´‚ËhÇ.òiÈh ”Ÿ’K€r B.RÈ%@ ¹H!—)ä …\¤K€r B.RÈ%@ ¹H!—)ä …\¤K€r B.RÈ%@ ¹H!—)ä …\¤K€r B.N×u]×uw¯P¹8ÑGú¾ïûþîu* —µÚ¨ƒQ=•ús÷ -(9 ïû®ë†Ú‘a`©2†O¾Û¨Y™O22,b²Ü=3¨/PZjJìxý “FœÉçòíζžµ™'_"‘@Ô—5çžbR)2ÿ5ªVYœÈ!—ÕòGi )Ûl&^³†À´ãÇx±Ö"#y@äà0%ŒX2ù<üçÚ8“ñ'B™/e2ŸÒëÅ3T  u7µj*Þ`ã°M ¹†í Ñ¿ˆ³X±áìO —qDx,¹à\5ök ¹‹\p®êÎñ5)šá~ …\¤K€r B.RÈ%@ ¹H!—)ä …\¤K€r B.RÈ%@ ¹H!—)ä …\¤K€r âÏÝ+ܦ뺻Wàr —ͨ8—¨&yË& .ç 1ÕçU‹ljTw.qöÝ`ãPºs Ð’;Ÿ«ö{Y¯·°Ý>bsTäæç½60=é¤h»}Äæ¨…v …\¤KRt]we«ÜxYZ !—Üoˆ}ßßÕªùnXÔB.RÜ|?À£”æ’á½ßC-Å0°T™¼þ¾)½ü»8«Žñ$e´ÅãI6Æ,ë6^I8ƒú€ë”–šq>ÌqÆ#”ow¶õŒôšµmô&ÙnQ’H8›\ЬqŒ˜Ä =SÍ?Œãœ¡úvœ·5œ“¯¸›+“ÇCÖ®¥¶·gvþä=ÛaràžÇ'þðX-Ô—¬ÕpwÜõ#¯Ͼ{ª4[U¶À|àëßí³xîlrÓ-•qšŒüZÚ‹W“‹!f¾µOøM$šôÕ¸x¹9 å*K¸@õ¹ä£PÍ¥ßy[‰ÒžÅÆõµÉÆvh)·q ÉåÓüókýá"‹¡a®ûk|'ç<óë_«¾gÛâ©å–5©Ýõ×v÷š¸¿®Õ6 MŠÅ~k•—kŸ÷÷Ù9dceàJç’mÚõ¿Öä¦[« 7è¬MR.1ך{æ3TÎã$ŸVàý¸¬–öwb=:—ØÇ¾Ö䦛tV _¬óØÞÛÉcmq°ßb ÜHÒ_SD¹Ì£s û=í¨4¯ÿø®%kÞ ûÀ•„Eg3E—ËTßïuÛäDò´“뱞v`?jçø“* öŸj§¾d^uYú–q&=~ý:©˜7+ ÅœJ.]$€ <:—8Ó ºî¿Û²lîõè\2èûÞùÈ%ð)àTr ¼Wšº8Õss‰3Í`¼Tp¯çæ’q(yr@™üö'oŠ J À5ž›K€4r B.RÈ%@ ¹H!—)ä …\¤K€r B.RÈ%@ ¹H!—)ä …\¤K€r B.RÈ%@ ¹H!—)ä …\¤K€r B.RÈ%@ ¹H!—)ä …\¤K€r B.RÈ%@ ¹H!—)ä …\¤K€r B.RÈ%@ ¹H!—)ä …\¤K€r B.RÈ%@ ¹H!—)ä …\¤K€r B.RÈ%@ ¹H!—)ä …\¤K€r B.RÈ%@ ¹HñçîhY×uw¯Âëõzõ}÷*À.r À¹nÏ!ÙöÐŽ¤h¤¾ä—«W…MñÖI›èöëi€ä’—#;Õ í8@ ¹H!—)ä …\¤K€r B.RÈ%@ ¹øR×uV{;ÿ4¦çÐ^þ0>/zÄÅ„Ú#—Àýš9»”" \ ëº¾ï›)<0Kà~UŸÅÕ—üh¾÷ VÉ%À—†“¥ÓäïÃǤ"¤ŒSªIlyš$—_r^üÝ>J)ic-v ‰D(¡arI®íºÜ×ÒYÁÑ j4ÙmKø˜UŒv|Zâ>á\}ßÇšrÄ).Æ e7ßøv~ˆ€¨/©•~øÐ€qÕÈk¥ftà^'B.iÓZPI3Ýþu©ƒ+Í÷µµž%;'‡ªÉ%õÙyÙ´vá5©hÙÙs. —ÔgOhX¼É°ôüg‘ù@”Éž m“KÚ4iµÙàHáì¤<ŠûqšµØhí’ €drI´ySËëÝíÁã‘·Ç?>rò,„V>§'ÚüiK;ÇßY)²óF¸†\ò qêâyÀÉ%O¡u¦ ^ <œ\òNráæÁ±Þ(©°_“K B9—«2žL.,ã,²ýFY€öÈ%K"žÆóK€r B;À¹ê½µ ®'—œH'!øˆv …\¤K€r B.RÈ%@ ¹H!—)ä …\¤K€í¼Ç›±€£8ž|Êk€8J#¹Ä.ËQe?1ŽiÇ©†=€æÉ%@ ¹¤&ªLh›\R‰€'K€r @õ6ªTËW]×m6A5-·KjÒ÷½#0·vWs×uå«;Ÿ‡Ñæ#8àp=¹¤ã# ИóÎý;ç<9”©v¸E#ÏU¸Øø¬?œÂ‡|9Í#”jÎI}çxœ·#ly­_½|š-敲®‹¸˜ú’ Œ  $‰ù.¹=¤LRæPNæ9®·˜Ìs>ÎIp¸ž\ð·ý66*3ÞN2þ°Ö_Uh Ir @®qµÊÙKr À7Æ÷ß®3înòÑ<'3ùbõö[ìô wÑïàckÍ+oSÈâÝ.å6Ýñ<ÇÍ@“™oÌäí¢Ç£{´|7O8œ\ð==^?jç<÷¶ýü}ê ¤à,·×7üò0ÆÛWžg’KN1È|àwóüh&_g ¡„[hÇ8ÅÎ{ƒ™'´G} B.RhÇXàIp ¹`J7¸‹v …\¤K€r ¢îÇ ë0ɪ>¼·¨þ~>Èä²ø‚v …\¤K€r B.RÈ%@ ¹H!—)ä®3yÐV×u¿?zk˜ƒGx´A.á:åá¼CŒèûþÇÇõv]7™'U“K8×yqa—ß͙˨/àx% Æ_mÿ9ùjþívtXœdq¡ŸÎ™kÈ%œbÿi¾Œ9©,)fwölê<æÕ!¿Ï™ËhÇ Ô§“V›çÌeÔ—pŠª"ŽêÞ±Ø:£ãHEäŽWM& +“°²–]vN>þ¶æÓ9s±‡FHÙù;¶P#Ç®Š¨/ eBI]䚥u¦:îÇ YjJª£¾H!—)ä …\¤K€r B.RÈ%@ ¹H!—)ä …\¤K€r B.RÈ%@ ¹H!—)ä …\¤èú¾?}]wö"NrÁÆÙÃ„ŠØaáΛuÙ9ë-ë÷þ*Ò@ioà'ЀSêK†ÂÝRÉîº+*–Æ‹{5·_mý"(Ú+Þñ`ìøÂ×j¾ìwÙ€P‘V v«¿‹|ú½îÕ÷}½ÍÆ l@¨ˆ–»œKÚŽØì¨6 TÄ ‡S_¤K€r B.RÈ%@ ¹H!—)ä …\¤K€r ¢î\²öî†î¯‹×§:Ûðâ•'›ïq‹C6vLÇ=ÚPw.Y4¼I«á—i]ÀÖƒÛwÃ!mlÙ÷hF}¹dûj`òzO—s¶ 4Æq–ü¹{Þï`å¥ÛåÒa>ÂxZ/é~ý¶+Í÷ÖñNº¶ÛN8îQ»ô\òúw?ï«ão_.ÖÙ€P…µq¾ÛnŒ µ‹nÇ)W ãËö³¨K5õ%ûÍ/,ÎÖ€æ9îÑŒèú’/èü<ã-‰Î%¥cÄä¦üíý‡¶Øq±Çún¾* IDATþíg\imW]|6Iâ¸G3®úk¾.ñìhBEš/ÏÍÿ@E×—"—)ä …\¤K€r B.RÈ%@ ¹H!—)ä …\¤K€rÉæ/tp.éû¾í“÷Ù¯ün{zg:±ÃÂáN©/irG½lmõHçG“ì°p¬³J^ceúúŸcBE+áýêrbákéâ–]Ô„ŠØaáB1Âý8@ ¹H!—)ä …\¤K€r B.RÈ%@ ¹H!—)ä …\¤K€r B.RÈ%@ ¹H!—)ä …\¤Kà‰º®[û0gñÛ3È%À{}ß_°¹žëšZýþܽÀ¥[pÆÕ!ÃðIÉxœqšY8I<Ãh‹Ž©/€g)`øÐ÷ý$”L†¬ÍämÔèÿšÏymþr <ˤ¾ä—έ‹u*¿ôD‘KàYæõ%󯾞m×ukáfhÜÙŽ>ú—ÀmDIw“Oç¹–<öÌV.€‡Ú¨º(bÒÝuÞËu±ßëÚRÞö{ý2ÀCl·J¬ý¹´Å ߎöõâÊðŵÓ×*¯¥@óÏ·r ð‘/rÉüVd¹øÕv…Çž 7¦•K€îRÈ%@ ¹H!—)ä …\¤K€r B.RÈ%@ ¹H!—)ä …\¤K€r B.RÈ%@ ¹HñçîîÑuÝÎ1û¾ß˜jüí¯«tༀŠtÝÿb@ù¼øá5‹&ã _ÇEõ%°e­R¡ïûñW“?÷¶8áÛѾXÜ<:,†‰ÅÑ6jV†oÇIåêK€× \ -d -oif libreswan-3.32/docs/examples/ipv6.conf000066400000000000000000000017131365625662500177520ustar00rootroot00000000000000# Example as taken from John Denker's IPv6 IPsec page at: # http://www.av8n.com/computer/htm/ipv6-howto.htm#htoc19 # # Note that IPv6 only works with the NETKEY stack # # (keys have not been fully written out in the examples) config setup protostack=netkey interfaces="%none" conn ipv6-host-host auto=add # leftid="@sunset.example.net" left="2002:4a6b:e723:3:205:4eff:fe4b:c8cf" leftrsasigkey="0sAQNM....hIp" leftnexthop="fe80::201:2ff:fe29:564d" # rightid="east.example.net" right="2002:4387:d370::" rightrsasigkey="0sAQP....LMsP" conn ipv6-subnet-subnet auto=add # leftid="@sunset.example.net" left="2002:4a6b:e723:3:205:4eff:fe4b:c8cf" leftrsasigkey="0sAQNM....hIp" leftnexthop="fe80::201:2ff:fe29:564d" leftsubnet="2002:4a6b:e723:8003:205:4eff:fe4b:c8cf/128" leftsourceip="2002:4a6b:e723:8003:205:4eff:fe4b:c8cf" # rightid="east.example.net" right="2002:4387:d370::" rightrsasigkey="0sAQP....LMsP" rightsubnet="2002:4387:d370:8000::/128" libreswan-3.32/docs/examples/l2tp-cert.conf000066400000000000000000000033101365625662500206750ustar00rootroot00000000000000conn l2tp-X.509 # # Configuration for one user with any type of IPsec/L2TP client # including the updated Windows 2000/XP (MS KB Q818043), but # excluding the non-updated Windows 2000/XP. # # # Use a certificate. Disable Perfect Forward Secrecy. # authby=rsasig pfs=no auto=add # we cannot rekey for %any, let client rekey rekey=no # Apple iOS doesn't send delete notify so we need dead peer detection # to detect vanishing clients dpddelay=10 dpdtimeout=90 dpdaction=clear # Set ikelifetime and keylife to same defaults windows has ikelifetime=8h keylife=1h # l2tp-over-ipsec is transport mode # See https://bugs.xelerance.com/view.php?id=466 type=transport # left=YourServerIP leftid=%fromcert leftrsasigkey=%cert leftcert=/etc/ipsec.d/certs/YourGatewayCertHere.pem leftprotoport=17/1701 # # The remote user. # right=%any rightca=%same rightrsasigkey=%cert # Using the magic port of "%any" means "any one single port". This is # a work around required for Apple OSX clients that use a randomly # high port. rightprotoport=17/%any rightsubnet=vhost:%priv,%no # Normally, KLIPS drops all plaintext traffic from IP's it has a crypted # connection with. With L2TP clients behind NAT, that's not really what # you want. The connection below allows both l2tp/ipsec and plaintext # connections from behind the same NAT router. # The l2tpd use a leftprotoport, so they are more specific and will be used # first. Then, packets for the host on different ports and protocols (eg ssh) # will match this passthrough conn. conn passthrough-for-non-l2tp type=passthrough left=YourServerIP leftnexthop=YourGwIP right=0.0.0.0 rightsubnet=0.0.0.0/0 auto=route libreswan-3.32/docs/examples/l2tp-psk.conf000066400000000000000000000034401365625662500205410ustar00rootroot00000000000000conn L2TP-PSK-NAT rightsubnet=vhost:%priv also=L2TP-PSK-noNAT conn L2TP-PSK-noNAT # # Configuration for one user with any type of IPsec/L2TP client # including the updated Windows 2000/XP (MS KB Q818043), but # excluding the non-updated Windows 2000/XP. # # # Use a Preshared Key. Disable Perfect Forward Secrecy. # # PreSharedSecret needs to be specified in /etc/ipsec.secrets as # YourIPAddress %any: "sharedsecret" authby=secret pfs=no auto=add keyingtries=3 # we cannot rekey for %any, let client rekey rekey=no # Apple iOS doesn't send delete notify so we need dead peer detection # to detect vanishing clients dpddelay=10 dpdtimeout=90 dpdaction=clear # Set ikelifetime and keylife to same defaults windows has ikelifetime=8h keylife=1h # l2tp-over-ipsec is transport mode type=transport # left=YourGatewayIP # # For updated Windows 2000/XP clients, # to support old clients as well, use leftprotoport=17/%any leftprotoport=17/1701 # # The remote user. # right=%any # Using the magic port of "%any" means "any one single port". This is # a work around required for Apple OSX clients that use a randomly # high port. rightprotoport=17/%any # Normally, KLIPS drops all plaintext traffic from IP's it has a crypted # connection with. With L2TP clients behind NAT, that's not really what # you want. The connection below allows both l2tp/ipsec and plaintext # connections from behind the same NAT router. # The l2tpd use a leftprotoport, so they are more specific and will be used # first. Then, packets for the host on different ports and protocols (eg ssh) # will match this passthrough conn. conn passthrough-for-non-l2tp type=passthrough left=YourServerIP leftnexthop=YourGwIP right=0.0.0.0 rightsubnet=0.0.0.0/0 auto=route libreswan-3.32/docs/examples/linux-linux.conf000066400000000000000000000022051365625662500213570ustar00rootroot00000000000000conn linux-to-linux # # Simple use raw RSA keys # After starting libreswan, run: ipsec showhostkey --left (or --right) # and fill in the connection similarly to the example below. # left=1.2.3.4 # optional # leftsubnet=10.0.1.0/24 leftid=@bofh.xelerance.com leftrsasigkey=0sAQPWTXt8DDlEhTZJ91ngNMxTSyuos6JZxXQmtRcwUl6ppUCcuuWvjXrF/qiz6eiL1LMlpGJyG1oVhtFhTaFJl7ZkF/4J1B9LCFzYxvYI97AnLuC0op5pVAZ1SZx29+aRjeMcKC4zbZ6dMMjUdn9H1gqG9rpE0MBEFNSVLEu9U8rtlz14RfxQAQ9ePj64HnGLfgJlDB0VYhKEIcRihy72bvjZ4eoX16S1EY1FgnHyrveZPxRi8sgn6Q19RytEzSmUAlGjvMDhNfenq6WCSYMeqgj0jFSArTNBQmR2QBkUG6NSOXfb+18c6jDPicGmbmWfoRx/PUJo46WiRF4RRmsxnFpbHpklILFzEJ+/k6qHVAekpVfp # The remote user. # right=5.6.7.8 rightid=@tla.xelerance.com # optional # rightsubnet=10.0.2.0/24 rightrsasigkey=0sAQNxf6caKULJklYZycuo66Ko0U+iHaJUDr0QZHnG4MJ9IRNYi5H6kPxcwKIXkg+OGo+NeUyyWDEc+ox27BFYViAHQNEyBRLZu0kyE681h+cHm7lfCSy0AOEBSCyZF3aGcL8GWxVhtimpJQ4tNxXZg7tLX5sfYw8mZnUBjkHvyccIred/q3cNWbDlq2WU4TL+NBb5FnxXi9Hk/SRV7sMe56fvZuXkcJu4e2C7uocltzzF1b0BZx7yeXwHjzqAWnW/UA54fbSTvzgnrpSC+FMuhWTI1EdxcqGaOFIjGWWGV2nxg/QaPU9i8vpwFwrEEdCJTiqlbYYNudblg4vYthnVNez0/RkfZHfhAaHdbJRSaQzOu88h auto=start libreswan-3.32/docs/examples/mast-l2tp-psk.conf000066400000000000000000000030311365625662500214770ustar00rootroot00000000000000config setup # assumes 192.168.1.0/24 is our L2TP range interfaces="%defaultroute" protostack=mast # T-Mobile and Rogers/FIDO now use 25/8 as "private space" too :( virtual_private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12,%v4:!192.168.1.0/24 conn L2TP-PSK-NAT rightsubnet=vhost:%priv also=L2TP-PSK-noNAT conn L2TP-PSK-noNAT # # Configuration for one user with any type of IPsec/L2TP client # including the updated Windows 2000/XP (MS KB Q818043), but # excluding the non-updated Windows 2000/XP. # # # Use a Preshared Key. Disable Perfect Forward Secrecy. # # PreSharedSecret needs to be specified in /etc/ipsec.secrets as # YourIPAddress %any: "sharedsecret" authby=secret pfs=no auto=add keyingtries=3 # we cannot rekey for %any, let client rekey rekey=no # Apple iOS doesn't send delete notify so we need dead peer detection # to detect vanishing clients dpddelay=10 dpdtimeout=90 dpdaction=clear # Set ikelifetime and keylife to same defaults windows has ikelifetime=8h keylife=1h # l2tp-over-ipsec is transport mode type=transport # # MAST parameters - requires # ipsec saref = yes in /etc/xl2tpd/xl2tpd.conf sareftrack=yes overlapip=yes # left=YourGatewayIP # # For updated Windows 2000/XP clients, # to support old clients as well, use leftprotoport=17/%any leftprotoport=17/1701 # # The remote user. # right=%any # Using the magic port of "%any" means "any one single port". This is # a work around required for Apple OSX clients that use a randomly # high port. rightprotoport=17/%any libreswan-3.32/docs/examples/oe-authnull.conf000066400000000000000000000024571365625662500213310ustar00rootroot00000000000000# /etc/ipsec.d/oe-authnull.conf # # Example file for Opportunstic Encryption using Auth NULL # During negotiation, hold traffic. On IKE Auth NULL failure, fail open # Traffic is held until IKE has failed or succeeded # Because it uses Auth NULL, there is no protection against active MITM attacks # # See also oe-upgrade-authnull.conf conn clear type=passthrough # temp workaround #authby=never authby=null leftid=%null rightid=%null left=%defaultroute right=%group auto=route conn clear-or-private type=tunnel authby=null leftid=%null rightid=%null left=%defaultroute right=%opportunisticgroup negotiationshunt=hold failureshunt=passthrough ikev2=insist # add, not route - because this policy is only for incoming IKE packets auto=add conn private-or-clear type=tunnel authby=null leftid=%null rightid=%null left=%defaultroute right=%opportunisticgroup negotiationshunt=hold failureshunt=passthrough ikev2=insist auto=route keyingtries=1 retransmit-timeout=2s conn private type=tunnel authby=null leftid=%null rightid=%null left=%defaultroute right=%opportunisticgroup negotiationshunt=hold failureshunt=drop ikev2=insist auto=route conn block type=reject # temp workaround #authby=never authby=null leftid=%null rightid=%null left=%defaultroute right=%group auto=route libreswan-3.32/docs/examples/oe-dnssec-client.conf000066400000000000000000000010411365625662500222140ustar00rootroot00000000000000 conn private-or-clear rightauth=rsasig right=%opportunisticgroup rightrsasigkey=%dnsondemand left=%defaultroute leftid=%null leftauth=null leftmodecfgclient=yes leftcat=yes narrowing=yes negotiationshunt=passthrough failureshunt=passthrough type=tunnel ikev2=insist auto=ondemand keyingtries=1 retransmit-timeout=2s conn block type=reject # temp workaround #authby=never authby=null leftid=%null rightid=%null left=%defaultroute right=%group auto=route libreswan-3.32/docs/examples/oe-dnssec-server.conf000066400000000000000000000010121365625662500222420ustar00rootroot00000000000000 # Opportunistic IPsec using DNSSEC and supporting an address # pool for clients behind NAT (Client Address Translation, cat) # conn clear-or-private leftckaid=YourCKAID left=%defaultroute leftaddresspool=100.64.0.1-100.64.255.254 leftid=@YOURFQDN leftauth=rsasig leftmodecfgclient=yes leftcat=yes right=%opportunisticgroup rightauth=null rightid=%null #narrowing=yes negotiationshunt=passthrough failureshunt=passthrough ikev2=insist type=tunnel auto=add libreswan-3.32/docs/examples/oe-exclude-dns.conf000066400000000000000000000003531365625662500217010ustar00rootroot00000000000000conn let-my-dns-go left=%defaultroute leftnexthop=%defaultroute leftprotoport=17/%any right=0.0.0.0 rightsubnet=0.0.0.0/0 rightprotoport=17/53 type=passthrough auto=route libreswan-3.32/docs/examples/oe-letsencrypt-README.txt000066400000000000000000000024301365625662500226650ustar00rootroot00000000000000 Instructions for running Opportunistic IPsec with Letsencrypt # Install libreswan 3.19oe2 via rpm or srpm listed here # Install the Letsencrypt related certificates: mkdir letsencrypt cd letsencrypt wget https://letsencrypt.org/certs/lets-encrypt-x4-cross-signed.pem wget https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem wget https://letsencrypt.org/certs/isrgrootx1.pem # based on https://www.identrust.com/certificates/trustid/root-download-x3.html wget https://nohats.ca/LE/identrust-x3.pem # certutil -A -i lets-encrypt-x3-cross-signed.pem -n lets-encrypt-x3 -t CT,, -d sql:/etc/ipsec.d certutil -A -i lets-encrypt-x4-cross-signed.pem -n lets-encrypt-x4 -t CT,, -d sql:/etc/ipsec.d certutil -A -i isrgrootx1.pem -n isrgrootx1 -t CT,, -d sql:/etc/ipsec.d certutil -A -i identrust-x3.pem -n identrust-x3 -t CT,, -d sql:/etc/ipsec.d # # configure libreswan for letsencrypt cd /etc/ipsec.d wget https://nohats.ca/LE/oe-letsencrypt-client.conf echo "193.110.157.131/32" >> /etc/ipsec.d/policies/private-or-clear # if you want to enable it for all remote servers, put 0.0.0.0/0 in private-or-clear # restart libreswan ipsec restart # [wait 2 seconds] ping letsencrypt.libreswan.org ipsec whack --trafficstatus # check if it was encrypting using # tcpdump -n host letsencrypt.libreswan.org libreswan-3.32/docs/examples/oe-letsencrypt-client.conf000066400000000000000000000007051365625662500233170ustar00rootroot00000000000000conn private-or-clear rightid=%fromcert rightrsasigkey=%cert rightauth=rsasig right=%opportunisticgroup rightmodecfgclient=yes rightcat=yes # Any CA will do because we only load the LetsEncrypt CA rightca=%any # left=%defaultroute leftid=%null leftauth=null leftmodecfgclient=yes leftcat=yes # narrowing=yes type=tunnel ikev2=insist negotiationshunt=drop failureshunt=passthrough keyingtries=1 retransmit-timeout=3s auto=ondemand libreswan-3.32/docs/examples/oe-letsencrypt-server.conf000066400000000000000000000007321365625662500233470ustar00rootroot00000000000000conn clear-or-private leftid=%fromcert leftrsasigkey=%cert # name of your generated letsencrypt certificate e.g. letsencrypt.libreswan.org leftcert=YourServerDNSName leftauth=rsasig left=%defaultroute #leftmodecfgclient=yes # rightid=%null rightauth=null right=%opportunisticgroup # negotiationshunt=passthrough failureshunt=passthrough type=tunnel ikev2=insist sendca=issuer auto=add # rightaddresspool=100.64.0.1-100.64.255.254 rightmodecfgclient=yes libreswan-3.32/docs/examples/oe-upgrade-authnull.conf000066400000000000000000000027221365625662500227510ustar00rootroot00000000000000# /etc/ipsec.d/oe-upgrade-authnull.conf # # Example file for Opportunstic Encryption using Auth NULL # Traffic should flow in the clear until IKE succeeds. Fail open. # This makes IPsec encryption "nice to have - not required" # Because it uses Auth NULL, there is no protection against active MITM attacks # # See also oe.authnull.conf conn clear type=passthrough # temp workaround #authby=never authby=null leftid=%null rightid=%null left=%defaultroute right=%group auto=route conn clear-or-private type=tunnel authby=null leftid=%null rightid=%null left=%defaultroute right=%opportunisticgroup negotiationshunt=passthrough failureshunt=passthrough ikev2=insist # add, not route - because this policy is only for incoming IKE packets auto=add conn private-or-clear type=tunnel authby=null leftid=%null rightid=%null left=%defaultroute right=%opportunisticgroup negotiationshunt=passthrough failureshunt=passthrough ikev2=insist auto=route keyingtries=1 retransmit-timeout=2s # To support being behind NAT leftmodecfgclient=yes leftcat=yes narrowing=yes conn private type=tunnel authby=null leftid=%null rightid=%null left=%defaultroute right=%opportunisticgroup # if we fail hard, we might as well hold traffic during IKE too negotiationshunt=hold failureshunt=drop ikev2=insist auto=route conn block type=reject # temp workaround #authby=never authby=null leftid=%null rightid=%null left=%defaultroute right=%group auto=route libreswan-3.32/docs/examples/sysctl.conf000066400000000000000000000042721365625662500204120ustar00rootroot00000000000000 # example entries for /etc/sysctl.conf # forwarding is needed for subnet or l2tp connections net.ipv4.ip_forward = 1 # rp_filter protects against packets "appearing out of nowhere". It is not # always clear to the kernel that a packet appeared as a result of decryption. # One such case is using KLIPS or MAST IPsec stacks, as they receive on one # interface but inject the packet on another interface. Another known case is # "appendix mode" using the XFRM/NETKEY stack. Here, packets are receiving, # decrypted and sent onwards on the same single interface. (these can also cause # bad redirects, see below net.ipv4.conf.default.rp_filter = 0 net.ipv4.conf.all.rp_filter = 0 # when using 1 interface for two networks when using NETKEY, the kernel # kernel thinks it can be clever by sending a redirect (cause it cannot # tell an encrypted packet came in, but a decrypted packet came out), # so it sends a bogus ICMP redirect net.ipv4.conf.all.send_redirects = 0 net.ipv4.conf.default.send_redirects = 0 net.ipv4.icmp_ignore_bogus_error_responses = 1 net.ipv4.conf.default.log_martians = 0 net.ipv4.conf.all.log_martians = 0 # seems the martian settings are not always enough. If not receiving packets # try running this: # for n in eth0 mast0 ipsec0 ipsec1 all default ; do # sysctl net.ipv4.conf.$n.rp_filter=0; # done # # these are non-ipsec specific security policies you should use net.ipv4.conf.default.accept_source_route = 0 net.ipv6.conf.default.accept_source_route = 0 net.ipv4.conf.all.accept_redirects = 0 net.ipv6.conf.all.accept_redirects = 0 net.ipv4.conf.default.accept_redirects = 0 net.ipv6.conf.default.accept_redirects = 0 # When using KLIPS in some situations, you will see errors like: # [ 8648.409997] __ratelimit: 168 messages suppressed # [ 8648.410009] Neighbour table overflow. # Especially when on large cable networks, though we've also # seen it when using combinations of xen/bridging/VM's. # If you do, and you are SURE there are no routing loops, # you can try these below: # net.ipv4.neigh.default.gc_thresh1 = 1024 net.ipv4.neigh.default.gc_thresh2 = 2048 net.ipv4.neigh.default.gc_thresh3 = 4096 # for enabling core dumps, see # http://fcp.surfsite.org/modules/smartfaq/faq.php?faqid=2746 libreswan-3.32/docs/examples/xauth.conf000066400000000000000000000011361365625662500202160ustar00rootroot00000000000000conn xauthserver # left=1.2.3.4 leftcert=/etc/ipsec.d/certs/xauthserver.pem leftxauthserver=yes leftmodecfgserver=yes # right=%any rightxauthclient=yes rightmodecfgclient=yes # auto=add rekey=yes modecfgpull=yes modecfgdns1.2.3.4,5.6.7.8 conn xauthclient # left=1.2.3.4 leftxauthserver=yes leftmodecfgserver=yes # right=%defaultroute rightxauthclient=yes rightmodecfgclient=yes # auto=add # you probably can not rekey, it requires xauth password, and libreswan does not # cache it for you. Other clients might cache it and rekey to an libreswan server rekey=no modecfgpull=yes libreswan-3.32/docs/ipsecsaref.png000066400000000000000000004774031365625662500172500ustar00rootroot00000000000000‰PNG  IHDR;Îç3žsBIT|dˆ pHYs-×+tEXtSoftwarewww.inkscape.org›î< IDATxœìÝy|\õ}ÿû÷ì3’FÒhß,ɲäEÞÀ»±mœ „„Bs³QÒ”Ü6¥·MÓüúKn›ÒÛ4¹·éï6 …@'ŽMÁ,€ÁÆkãÝò*[¶dkßF3šõÌùý¡h‚˖בÈëù¤s¾ç{>çÌ?óxë»X$™€w°KR__Ÿ\.Wºkf‘HD¹¹¹CÁ¡Ëå’ÛíNwMÆkº 0öHAp Á!€‡RHAp Á!€‡RHAp Á!€‡RHAp Á!€‡RHAp Á!€‡RHAp Á!€‡RHAp Á!€‡RHAp Á!€‡RHAp Á!€‡RHAp Á!€‡RHAp Á!€‡RHAp Á!€‡RHAp Á!€‡RHAp Á!€‡RHAp Á!€‡RHAp Á!€‡RHAp Á!€‡RHAp Á!€‡RHAp Á!€‡RHAp Á!€‡RHAp Á!€‡RHAp Á!€‡RHAp …=ÝŒgçB=ºkÓ?êoë?¢*—^´­?6¨7mÒö®#:êÕü¼ZÝY6WË‹¦_ñý_<»K¯·ïÓÞÞSªÉ*Ñ’‚©úäÄrZ¯þkÞ[¿%Ÿ3Kß›ÿù«îK’~Ü´Qÿvøym¸íÊwy/ÚöPÿ­kÞ¡]Gå²9´(²þ¤j™ª2 ¯I-¸4‚C€«°úôfíí=¥®ÈÀEÛhÕ=o}S‡ý-Éco¶п~NÿcÆýú‡™È"˨ïKzôíè'~<¶©ãž:¹AOžÜ g—ýŠÝ¹—ÿ@¿ÓhÓš3[õ¾’ÙWÜÇ»}ïø«Ú×פ˜i\´ÝÏOoÑC¿ù®BF4yì¹–ßè_<§_.ùk­,žyÍjÀȘª pL™ÚÜÙ o\sɶ†™ÐíoþOö·è–‚©znÙW´ïŽïèg}\V‹E_?ø‹óÀÑø‡«õƒ¿–×áÑÌ{Xïüÿô³[¾¬ÉÞ2më:¢nù—+}4µ vëÁÿ~Å׿۠Ñ?7¬Ó¶®#—l»³û¸>¶íß2¢úBÝÚþþц۾¡LX¤îÈ€þhã7t.ÔsÍjÀÈqp6uÒEÚ÷«+âÕ5Ï6ïPS°CU™…Zëß%§éÎÊ­V¦Ý¥¿Üý¤þߣ/èáÚÛG5ê0ë{'^•$=³èÿÔ‡+J’¦çTj~^­æÿú¯µµóˆ~ÛsBóójGUc[¸Oß<´V¯µíÕÿÙQ]s)ÿ~ì%=×òmí<¬h">ªk¾}d½$éÓWê?æ=œ<~kQ½nóëz³ý€þãØËúæìO\“02F\†ÎþV¿8³eÔ¡¡$}ûèó’¤Ï×þQÊÚ~N¾S>g–ŽøÏêWçvª¿zS½Ñ€ês&$CÃaµÞR}¬j™$é;¿ áFãÄ@«¾{ì¥kßÿÍö£ Ï vjmó6IÒW§ÿñyçì›þ¶þ#’¤ïŸxUƒFäšÕ € cÄ!ÀeøòÔ»õ‰êåÉ¿?÷ÛÿÔÎîã#¶4"ÚÑuL’tWÙÜ”óv‹MTz³VŸÞ¬×ÛöëÎ ´y· mû%I,›wÁó*Ÿ¯ÿ<þŠ^kÛwɾ†Ý웨=ôíäß¿8³E7<;êë/äå_SĈI’ñ°–½þwm¿©ã 3¡:o©ê¼¥)çWÍ×áQO4 ==§´¤pêUÕ€‹#8¸ ež<•yò’{íž‹¶o õJ’V›fæV]°Íœ¼­>½YmáÞQÕÐîI^w!7û†ŽwGKrXm—ì3ÓîÖM¾‰É¿·tU-3-»"ù{lð’í‡ßÕܼI<ï´Ú5=g‚vtõ»À•cª2Àu4†å9½#¶>7ÜöjûÌsfIÚÀ¥#Ò7êZÓíz¼+\9‚C€ëè÷aXÖˆm†Ïv][h( |÷z‰ÃœV»²ìîóî?\w€+GppECkü9¬#¯c· M%Æ/½áGÂ43‡6qXFž‚l³XGÝçX1ªweý»ÀÕ!8¸ŽŠÜ9’¤Þh`Ä6=ÑIR±;÷’ýY-¸²wÝ…û4Ì„ü±Ð¨û+Fõ®"CçÆÓsŒW‡×ÑpÀ5RÈ'I½Ñ $©Ôã»Ì>.x¾/”)S’T6Ê>ǂѽ«¡s£}W¸r‡×ÑpŒ‡Õî¿`›SÁvI:o·æ‹)r Ì;è¸àù¦àÐñ ›KÙŽŒËª7†ßÕ©@ûˆm†Ÿm´ï WŽàà:*qçªÎ[*Iz­mßÛ¼ÒºG’´¤pê¨ú¼µhº$é×m{¯IcŲÂi’¤ÝG5ð»©Öït¨ÿŒš»ä²:47oÒ.àÁ!Àuög“Þ/Iúù™Í)çv÷žÔQÿYå:3uß„[Î;K 1EñóŽ?T³JV‹EouJÙ59nZsf«$éáÚÛÏ;g˜ …˜ÂF,9•ùj ÷7«îkVnµä×)–0´®y{ÊùŸz°ø¢;/àÚ 8¸Î>=q¥<6§^<»K7<«„9Ú5v飛ÿE’ôàÄÛä±9Ï»î¿.Ïšûµìõ¿;ïxEF¾>X6_!#ª{7?®þØ $)šˆë »~ ý}M*õøtOùÂó®{æÔ›ò¬¹_ž5÷ëø@ëU?W,a$ûûÆÁ5WÝŸ$ýyíI’¾øöµ«çDòø³Í;ôxÃ:IÒçë>pM³§»€÷ºbw®Ößúwºû­oê+û~¬oy^ež<íï;-S¦î*›«Çoúäeõù£E_Ôío~]¿é>¦Âg?¥›r'ªÁߢ`<¬"wŽ^Yñ?ä°Ú®Ó]?ÖܦƒýgôoGž×üWÿZõ9ÔÔÙP·,²èÍ{XË ëÓ]&À›¤ÿù÷ÿ÷²ÛÉ®ÄìÜj­,ž©ò‹lØQ“U¢åE3Œ‡ÕîÕé`§ä×éÁ‰·é?ç^Në…¿‹ õ=CsÞµ¦ŸÇæÔUK5(lÄ´·ï”*2òõ¡òùú¯…jzNeJ_YTâÎÕŠ¢ZQ4Cv×EŸ«Ü“§•Å34;·ú‚ç-²È"%û›˜UŸ‰„ ÃP<Wcc£Âá° •H$FUWW§E‹¥»dŒápX‡à`S‹óÜòfxR¦0 («°°P………ŠF£òûýª®®ÖòåËeµ2aཎ5Æ¡×_]2 C¿=zB_ÜÝ~EýX,¦îÍ1u‹Ï©L—SÒÐHÆá1 *«¨¨HÅÅÅ2 CÝÝÝ*//×Ê•+år¹®åc` ™ª 0ŽÄb1™¦)Ó4õÛs=WÜiZôlŸEÏöÅuwNTKrlò8ì²X,’$Ç#Ã0ÔÑÑ¡ÖÖV•””¨¤¤DÑhT?ùÉOTXX¨åË—+''çZ=Æ‚C€qdxS”ÞÞ^m \›iÃëû­ZßoêNoHK²­rÛ¬ÉÑívË0 µµµ©¥¥E¥¥¥*//—$­[·N>ŸO‹/VIIÉ5©cS•Ɖ'N¨££CGM--ºÓ©ërŸÛ³ -ÍJÈ9”ž7…9‰È0 •••©¢¢B‹E===òx<š7ožjjj®KM¸qXã`œÙ°aCr}Ã-‡Žé¯öu\×û­ÊŒki†!»iHÒy›¨D£Q†¡ŠŠ UVVÊb±¨¿¿_6›M3fÌÐÌ™3¯km¸~Xã`œ‰Åb’†¼mW±¾áhmÚµ!h×­1-sÇeÇ“S˜m6›,‹ZZZÔÔÔ¤ÊÊJUVVÊf³©¡¡A{÷îÕäÉ“µpáÂë^'®‚C€q¦»»[›ƒ6Iñr¿·zkС[ÜvÝêŽHñh2@´X,²Ùl:}ú´U]]­êêjedd¨¥¥E‡RMMn½õVY­×fMFÜLU åp8tòL³xëú¬o8óÝ1­p†” Èb±œ7…Ù0 †¡‰'ªººZN§S†a¨»»[eeeZµj•œNgÚjÀ¥±Æ!À8²aÃ*‘Hèõ} úÊ®t—¤9Ψ–;‚J$)%@L$ª­­Uuuµ\.—LÓT{{»JJJ´|ùregg§ù p!¬q0Ž ¯oǵé\_š«²;êÔî¨S3™ZiÈð÷¦´9zô¨Ž9¢ºº:Mœ8Q%%%’¤µk×ÊçóiÉ’%***ºÑ¥`q0Æ™¦©×^{M%%%jmmÕÿ±ù¤üáXºËJ1ÍÑJÛ€b}C£!ß=Q’êêêT[[«ŒŒ ICë5Z­VÝ{ï½òz½i«¿ÇˆC€qbÿþý*(($õ‡#c24”¤Ã†K‡ —&ggë6KŸb]í’†‚OI2 C jhhД)STWW§üü|mß¾=$`ì 8ã:;;URR¢D"¡#ccšòÅ‹;uLEš”—£•fb­ç7 CÔ¡C‡TQQ¡)S¦Èf³¥©ZŒ„à`Œžæ‡µ±#˜æjF¯Ñp©Q¥ª.Ì×J³SƒmgÏ;LJU__Ÿ¦ p1Öt€‘ÅãqÙl6™¦©žÞ^íH¤»¤ËÖd:õ”ʵµô&Y¼¾äñx<.Ç£y󿥱:Œ„à` Û³gOr×ážÁˆ"q#Í]¹Ó©3‰ßOx1 C .d“>€1Šà` óûý²Û‡Â¶m=i®æê•Å’†6L©¬¬Lnú€±‡à` K$†¦&½ÑJs5WÇìS"à—iš2 C™™™ºùæ›Ó]F@p0FE"9™¦©~¿_ûüñt—tUfÆz’£'#‘ˆnºé&åææ¦¹*Œ„à`ŒÚ³gOr*o{ $#a¦¹¢«Seþþ÷ª*•””¤±\ Á!À e³Ù$IoŸíJs5WÇ Ê ôKš~íõzU__Ÿæªp1‡c”i0ìëëÓ}ãw7eIš:Ø.çï¦]‡B!M›6M¥¥¥é. Ap0 ÊívK’ü€Žú#i®èêL±‡“Ahyy¹ÊÊÊÒ\.…à` Ú³gòóó%I-ýÁ4Wsu,Ѱäï“44M9//Oµµµi® —Bp0E"Y­V™¦©mÍé.çªÔøÏÉåtH’€jjjTSS“æªp)‡ciš2MSÝÝÝÚäOw5Wg†3šü½¬¬Låååi¬£Ep0Æôõõ)##C’4 ©98Ž×74 Yý½’†ÂТ¢"UVV¦¹(ŒÁ!ÀsèСäú†§zÇ÷pÊžÓò¸œ’$¿ß¯òòr͘1#ÍU`4Ƙh4*‹Å"Ã0ôÖ™®t—sUf»â’†F–––ª¢¢"Í`´Ƙáõ »ººõVÀ’îr®œ™+Ø+Ó4%IEEE*--MsQ-‚C€1Äï÷'×7”LåÇïˆÃÂÎÓrÛí’†Öm,))ÑܹsÓ\F‹à` 1 CËÐ(â¢"ýôwè_gäËHse—ïfwLVëÐ×ÍââbUTT$ÿÀØÇ77€1Ä4Muwwk``((t:ºmÎL­{`¹þ¯jì‘Pš+=ïàï7v)--UQQQ«Àå²§»€?tgÏžÕ¯~õ+…BC¡`<WCCƒÜn·æÍ›§ŒŒ y³²ô‘Ås´tr·Öî>¬gÚâ’Ý‘æÊG–ÛÕ,—Í"Ó4Õ××§9sæhþüùé. —à Mâñ¸Ö¬Y£åææ*33S¦i*‘H$nݺUN§S‹/–ÅbQϧϮX¨œkÕS»éõ°[ÒØÛ@eŽ#,›aS"‘P~~¾***ät:Ó].S•Ò`Ó¦MúÁ~ ›Í&ŸÏ7b»¼¼‡Y­Vù|>uww«¹¹Y“&M’Ïç“ÅbQyAžõfêTg~tf@Íöë V[#ÉßKKK•ŸŸÝî€ëË"É …Br»Ýé®`Ü:qâ„6mÚ¤’’¹Ýn%‰äHÃD"¡ööv566jÆ Ú±c‡$©¸¸XÓ¦MSOOŽ?®É“'Ëår©¼¼\ååå2MS'NœPGG‡î¿ÿ~% y<¹\®d¿ï¼Ç; È4MM™2EN§3Ù688¨£}úQ[\~gæ5}ö@Ÿî5Êår©§§GË–-Ó=÷Ü£êêêkz\_ápX‡‡W# iݺuÊÈÈФI“’ݰ;vL{öìQoo¯¦Nª²²2íÙ³GøÀd·}«®®ÖË/¿,›Í¦ÌÌLåççËápÈëõj``@¿üå/URR¢%K–hppPÉk/$33S‰DBPVV–&Nœ(‹Å"·Ë¥¥úo@{:üúÅ€K±k´Ê´p§< ÃPFF†|>¡!À8ƈC€+ôꫯª««Kååå²X,ç ‡Ã:zô¨Nœ8¡§Ÿ~Z999ºãŽ;”™94ʯ­­M'OžÔ”)S”H$ÔÛÛ«ÂÂB jÓ¦M²Ùlr»ÝZ¸p¡JJJ$ m¦²nÝ:}ä#Ñĉeš¦¼^or§æw<þ=‹)(??_eeeÉs†a¨§ß¯-í½fæ*a±^ìq/é£ý‡•k3e†òòòtë­·ê®»îºê÷ €kxÄ!Á!Àe:~ü¸¶nݪ &ÈårÒ†¡ÆÆF8qB?þñÕÞÞ.I²X,Z¼x±JJJÔÛÛ+»Ý®É“'K’NŸ>-ŸÏ§œœIRoo¯žþyÕÔÔhîܹòx<êëëSVV–âñ¸vïÞ­{î¹G^¯7 Jqúòp˜‰DTVV¦ÜÜÜäñx<®ŽÞ>½ÖÕ.GÁ½k(¨Gäq»Õ××§¥K—ê}ï{Ÿ¦M›v Þ8n$‚C€Ë õÜsÏÉçóÉçó¥s---:räˆ^|ñEåææª¶¶VƒƒƒÚ¼y³¦OŸ®ºº:ICáÞ‰'TUU•\°±±Q………ŠD"r:ª®®V<×Þ½{õöÛo+++K·ß~{r‡âH$¢õë×+‹éÑG•Õj•išÉ)Ê#>L$ ƒ’¤òòreddÈ0 % E£Qëók}¯Ôä¾¼MM¦v×ÒŒ¸‰„µråJ=ôÐC×öÀ Á‡—áW¿ú•€jkkešfrgcÓ4ÕÛÛ«ýû÷kÏž=:}ú´Î;§3fÈãñÈãñhÉ’%úío+—Ë•\³Ðãñ( ©±±Qv»]óçÏ—4ô%­µµU‰DB‡C555’¤®®.½ôÒKš={¶¼^¯BÓîi½ IDAT¡>üáËn·k×®]:qâ„>õ©O) ­eø» _hfÇ£D"¡cÇŽÉãñ¨¢¢BN§S6›Må¾}Ú5¨æ@‡žp¨ÏãÕû™êŒ'g7e€÷F\DCCƒvïÞ­šš9Ž”‘|Û¶mÓþýûÇUP04Í7èå—_Veeer³“iÓ¦Éb±¨µµUš1c†¬Ö¡5:¤‚‚eeeÉï÷k``@ÙÙÙêèèÐĉ“Ó[ZZôÒK/)kéÒ¥š:uª\.—uðàAE"y½^}àP$‘Õj=¯æ DŒF£êíí•×ëUee¥¤ßOwö ¨1ÓK†OaWƈïÈ ëþef M§¾å–[tË-·hîܹ×ùÓÀõÀˆC€‹Ð /¼ ââbÕ××'ƒ¶aÃ#ùæÍ›'«Õªõë×+‘HÈétª½½]eeeÊÏÏWKK‹¬V«Âá°Ün·<Âá°Nœ8!»Ý®@  ‰'*33S===êééQ}}½,‹JJJtìØ1% Y­V…B!Ý~ûíJ$Ú¾}»Ž?.ŸÏ§‚‚-X°@’ÇõÌ3ÏhæÌ™š5k–€\.W2¤|wýv»]TCCƒ¼^¯ÊÊʆ¦=gdhºËPY·;õ–§L†Õ‘ò®*ûZäõM‘¶Ùlòx<š3gÎõúhpƒ0âà]^|ñE†¡êêê‹®øîGvìØ¡Ÿýìg²Z­Zµj•,‹$éÈ‘#Ú»w¯222TWW—Ü0dx éS§&7=ijj’$eee)(##C>ŸOýýý²Ùl*,,”$Åb1­[·N]]]***Ò¢E‹”ŸŸ¯P(¤¶¶6y½^uvvjöìÙ*,,T(RFÆÐ¨Áw?Çðï¦iª¯¯O‡CYYYÉu‡7PéêókWĦ}ÞJ™ïØùnÿQ•8†úÍÌÌÔ’%Ktï½÷ÞÀO ×›£¼Ë¡C‡tàÀÕÕÕÉét^r“‘wŸ7MS~¿_[·nÕ–-[TYY©H$"»Ý.ŸÏ§¾¾>íÝ»WÓ¦MSnn®‚Á ü~¿rrrä÷û588¨Ù³gËb±$CÅúúzeddÈ4M>}Z‰D"¹ÃrUU•œN§Nž<©7Êív«¤¤D«V­’Íf“$:uJ[¶lÑç?ÿùäÈÇŒŒŒƒÃá¿»»»•‘‘¡‚‚‚仞ÚÜáhs,S; R"®?é= oF†ü~¿,X yóæiñâÅiþ4p¥ÞaïÞ½êîîViié¨BÂ‘Ž ÿìííÕÆõúë¯kÉ’%ÊÊÊ’iš:s挶lÙ"—Ë¥ŠŠ -X° 9øèÑ£òx<ÊÏÏW8V[[›²³³ÇÕÞޮɓ'+//O±XLçÎSii©œN§"‘ˆvíÚ¥ŽŽuww«ººZÓ¦MS<W4Uqq±tàÀ}âŸP(JN©~Ó4‹Åä÷ûUPP ÌÌLY­ÖäÌ¡PH­Á°öõ êöò\™¦©þþ~­X±B>ø ìvVįÞá{ßûžV¬X1ªðbá»Û´··kÆ jhhaòx<š1c†,‹š››ÕÞÞ®ÊÊJ Êëõª  @:~ü¸æÏŸŸ Ož<)‡Ã¡ÒÒRIC¥ÙívuwwkáÂ…²ÛíŠD"Ú¸q£Ž?®ââbÝyçÊÌÌ”$µµµé¥—^RMMxàõ÷÷+‹Éét^ôy#‘ˆ,‹¼^¯‡,Ëy¢ÝnOŽ„\´h‘î»ï¾´}ޏz‡ïðøãk„ ºé¦›R¦íŽ&D¼Tûææf½òÊ+Ú¹s§/^¬‚‚‚dwðàA;wN+W®Tvv¶LÓTKK‹ÚÛÛ5a„dpWRR¢p8¬††M:U999’¤îîn…Ãa*êÔ©STKK‹¢Ñ¨êëë%I™™™š4i’‰„:$»Ý®¥K—ª¯¯O’d³Ù.ú¼Á`P.—K999²X,2M3 úý~ÕÔÔè¾ûîÓôéÓÓö9àê¼Ã·¿ým½öÚkšedd¨³³Såå媪ª’$={V’T^^.ihgㆆM˜0Añx\mmmòù| ƒÚºu«rss“£-Z”Ü0å7ÞÐ]wÝ%·Û­ÞÞ^¹\®‹Ž¤ŒÇã …B*((Pmm­>üákÒ¤Iiøäp­¼ƒišZ½zµÖ®]«h4š<¾jÕ*-X°@.—ëŠF^ìX4UCCƒ^~ùe•””¨¬¬L6›M¦iª©©I‡–ÅbÑÒ¥K“£ €“;?wwwëìÙ³ÊÏÏ—ÍfSoo¯*++år¹tîÜ9)++K’Ô××§çž{N@@UUUZ°`rss …´oß>8p@999ú¾ P(¤¾¾>¹Ý @@_ýêW5wîÜ´|n¸ö. ½½]O>ù¤¶nÝš<æv»uûí·kÆŒ²Z­#†Wºs8ÖþýûõÆo¨¶¶Vyyy’†F>îÛ·Oýýýºùæ›åt:ÕÕÕ%·Û-§Ó©'N¨²²R’¤P(¤cÇŽ©¾¾^‡Cñx\û÷ïWaa¡¤¡Ñ‰uuur¹\:zô¨vïÞ­œœ…ÃaùýþóÞCee¥V­Z¥p8¬ìììëïïï×Ã?¬»îºë}B¸Þ.¢¡¡A?üáuüøqIC# õ¾÷½O555—œ¦|¹!¢iš Ú½{·Þ~ûmM:U’¤ÁÁAíØ±C­­­Z¹r¥ª««“5íØ±C“&M’ÇãQ__ŸB¡rrrÔß߯¾¾>Ý|óÍr8 …BjmmUUU•l6› ÃЖ-[tàÀ”g/--Õ²eË”••uÞŽË <»»»µfÍù|¾öÙàú"8¸Ó4µqãF=ýôÓêêê’$ÅãqM™2EË–-Sqqñ¨ÃËÝ\¥¿¿_;wîTSS“jkkåt:%IGÕÎ;5{ölª¿¿_'NTFF†ÚÚÚÔÛÛ«éÓ§Ëb±H’öï߯ÒÒRù|>E"?~\™™™r8:yò¤Ž?®X,–|^§Ó©;ï¼Syyyòx<#Ö‹Å 5sæL}ë[ߺñ®‚C€QŠF£zöÙgµvíZ…ÃaIR,Ó‚ 4oÞ<åää\q`x±ŸÚ¹s§úûû•““£ÖÖVMž}Z»víRyy¹n¹åù|>Y­Öë‡Ãêéé‘a²Z­ÊËËÓC=DhðDpp…Nž<©'žxBû÷ïOóxô¡)???¹sò…êˆF£òûýêïï—Ãáišºûî»õÉO~29zï-‡WiÇŽzòÉ'uîÜ9ICk"iñâÅš0aˆ;-_l}ÃK…ˆ‰DB§NÒ–-[T^^®ââbÅãq566ª»»[¦iª»»[«V­JN;öûýZ·n‚Á ,‹î¸ãM˜0A999#Þ3+ &ÃÆx<®©S§êÑGÕ¤I“ÒùÚp\ñx\/½ô’V¯^­@ <6yòdÍ™3G×dºò» *ܼy³úúútÛm·ÉëõJ’NŸ>­Ã‡köìÙr:jnnÖ®]»4eÊÍ›7Oùùù²X,#Þ; ª««K±XL¦iÊëõêÓŸþ´î¸ãŽäÆ+xï"8¸†´zõj½üòËŠÇã’†Ä9s樾¾>¹áHS‘¯ts•H$¢£Gª¡¡!¹qJss³¶oß®h4*›Í&¯×«~ðƒ*((ËåñÞ‘HD}}}êîî–Ýn—$­\¹RŸùÌg”›››Î× €ˆàà:8{ö¬ž|òIýæ7¿I³Ùlš7ožêêêFÜ@åRë^j´âàà ôÖ[o©µµU¦iÊf³éÃþ°***”=bÑhT@@çΓÍf“$M˜0A<òˆfΜ™®W €4!8¸ŽöíÛ§'žxB§NJËÌÌÔœ9sTUU%«ÕzYÓ•G»FâÀÀ€:¤ÎÎNÝtÓM*((¤ ^g†‚Á š››“»D;N}ìcÓ½÷Þ›u€?,‡×™išzýõ×õÌ3Ϩ··7y¬¸¸X³fÍRIIÉ%wUmˆøîŸ†aHºp`8<-¹££C6›M>ŸO'NœÐ‚ ô¹Ï}NÅÅÅé|mH3‚C€$kíÚµzöÙgF%I†ahòäɪ««S^^Þ4¼’s±XL}}}êììÔ¬Y³ …ÔÚÚªGyD‹-Jó›ÀX@ppƒuuuéG?ú‘6mÚ”œlš¦fΜ©ªª*eff^õHÃ‘Ž Oc>sæŒ&Nœ¨üü|9rD‹-ÒC=ÄwA$¤É±cÇôÄO¨¡¡!yÌívkúôé*//—ÃáõtåÑŒL ƒjoo—$Õ××ëôéÓ²Ùlzì±ÇTUU•®×€1Šà ͶlÙ¢§žz*êI’ÏçS]]JJJdµZ/kc”w·‰F£êééѹsç4sæL†¡¦¦&}êSŸÒûßÿ~Y,–4>=Æ*‚C€1 ‹iýúõúÅ/~¡ÁÁAICÓ—ËÊÊ’SŠ/^hc”ÞÞ^577«¬¬L¥¥¥:räˆ&Ož¬G}T^¯7ÍO €±Œà` éïï×O~ò½úê«J$’†ÄÚÚZ•––*;;{T£€ÚÚÚ‡5kÖ,µ¶¶j``@=ö˜¦Nšæ§Àx@p09sFO<ñ„vïÞ<æp84yòdegg+;;{ÄiÉ:s挦OŸ.»Ý®ãÇëî»ïÖ}÷Ý'«ÕšÆ§ÀxBp0†½ýöÛú¯ÿú/9s&y,//O²ÙlÊÈÈÃáßï×àà :;;Õ××§eË–éèÑ£***Ò—¿üeåçç§ñ)0Œq‰DB¯¼òŠ~úÓŸª¿¿?yÜ4MeddÈ0 E£ÑóŽèK_ú’æÎ›Ž’ð@p0NƒA­Y³FëׯW,»`‡Ã¡~ô£ºÿþûåt:op…x/!8gÚÛÛµvíZmÛ¶-9ÑétjÑ¢EúøÇ?®òòò4W€÷‚C€q*‘H¨©©IV«U%%%|À5Ep ÅpphMw!Æ‚C€qnÆ š:uª>ûÙϦ»¼‡Œs:zô¨š››Ó] ÞC¤ 8‚à@ ‚C)¤ 8žîF+¾c§¢¯üZž¿}L·û¢m2vï‘qø¨,E…²Ï¹I¶)“%ëÅÿošhï±o¿â‡dÍΖµv’KKö«ÿÚúοËV;IÎÝu鯉„Œ†ÃŠíØ)E"²M›*Çòe’Í6ò5†¡Ø¯_—qü„d$d««•}ñBYrs®ºvãà!EÖþ·<_|D–ü¼‹7ŽÅß·_ñ·÷H‹ìso–}ÖLÉá¸èe‰ÎN»ö(~ø°l'Ê>oެ*®ºvI ÿ Yrräú“?¾&ýü! 8ãFø{?Tìò|ùKÒHÁ¡i*òäÓ =þ-™‘Èy§l³f*ë©ïËZX˜zY$¢Á¿økE_úUÊ9Û¤‰Êø§¯Ë~Ëâ+®Ý8~Báï|W®ÝÉàÐ8pPV¢³óü:fLWæw¿#Û¤‰¼.¾s—öçç³äæÈó7Éõñ?¹âÚ%)üÔ3ŠþòY¹>õqÙ.&ZÎ*ð™ÏË8|äüÚ§OSÖß“µ¼ì‚×E׬Sð+_“b±óŽ»¿øˆ<ý…d±\q퉮.…ÿ–·­ 8¸ ‡`\ˆm٦ئ͗lúçÿGáï=!Y­r}ì~ÙçÍU¢½]Ñuÿ-cÿ ÜýÇòþ÷/d-)N^c†øøƒŠ¿½[–¬L9ïºCöùó”èêRtÍ:§øôgå}alS§\~ñ¦©Ð?ý˨šÆ·ÿFÏ|Nf (ÇŠ[åX¾LÆÉSоø²Œƒ‡üÌçä}é9Y23’× C!Ê:¡b(˜t9[ÿ¢ŒÆSüÊ×dñfÉy÷/¿v ™±õ/]ú1{zåÿà½2{ze›:EÎÝ)%LEŸAÆ¡Ãòð#ÊyóÕ”‘ÿLƒ_ýÉj•óîʾ`žŒƒ‡}î…¿ûÿË ”ñõ¯]Qí’úæ¿J†qÅ×ü¡"8cVüí=нµYñ·¶*¾oß%ÃãÀA…ø”d±(ëÉïËqÛŠä9×gTàO?§ø¶íŠü×äùêß$ÏE׬ ½^eýôG²ß4+yÎýgªÀƒŸUlË6 þõßÉûºQÕnúýŠmØ¨Øæ­ŠoÙªD[û¥/J$üòßÈ åþÒ#ò<ö—ÉSž¿ú õ/])ãä)E~ºZî‡?“<ùÅ/%IÖü|ål}ó÷×üå—|ìo]³N¡¯ó²‚CãPƒbonª×€yæ§C¡áä:yÿ{M2Ütýé'5pÏ}2O)ò³ŸËýÈç~QÜPø}o¨Þ¿ù+¹ÿüáä)ûŠå þùùéÏåùÒ#²äçªvs0¤Ø›ß¼U±·¶(ÑrvÔÏ €ßcs0fþ‚Âßù®âoï–â—1Yûß’aÈù¡»Î %Éâñ(óñÿ[²Zùù/e†BÉsÑç_”¤¡Šï %é³wçñQÕ÷þÇßg¶ÌdYa ;²/"à‚ŠÚº‹k½u©Z­¶·›u©Z«µu«K]®U[Õªµ·Òk]ÄDEÄ…M‘U–IÙ—ÙÏùý1dH˜É0Á„$ðz>yÌÌ9ßïw>3ÑGÓ·ßE.—ú8©ÐP€üÏÿM’ä¹ý–V3"ÌLyn¿U’äî…V¿ËÀ[oËÜY*[ÿ~­BCIrö-9O˜)òí;¡O?Sãu?‘ÿ¥|Ì8Ý–û?•ö|VC£¼=’°}xÝI’ã¨#ãÞ· (û  ½Y¡%Kåœu‚$Éܾ]’d7&n?ûàÁ‘CIÂa™ÛJd?bä~k·«Ô;n‹¾,ø·BK–&ìãé’$×ù³ãÞ÷üü'òüü'­/š–¤=ûÿ9cÿ´3²ì`÷µW˪ªŠ¾núÍÝ Û?úXæîÝ2R=rN?*æ¾ãèé2<™eå -ûDŽÓ$I7çFJ?éĸã:Ož¥à)øú›±Ÿ½ ö!ƒ[}÷Á?RðÝÿ$Õ{€n+å¿.Š>7wïÞophUVJR—¬ÌÈxå{gºøÉ4#§'ÇZ±B ‡edgÉ>|XRµÛ‡ –}Èà½õ—–í78 ¯Z-Irî ÕZúÏþ£—_~9n¿ŠÌà‹7£ÐÿâK’$[ÿ~qg$¶Å5û¬½/,k¿Áaó¬Jû„ ’ËsßHI‘}üX…–.k5Ó,-“ÔvØÛ|=ÙY›’dë[¤”«¾··ü@àà€C†}È`…×­Wxíº¸÷-¿_áuë#ÏwíŽ^O¹â²¶5MùŸ{Q’äœu¢ä°w\Á­Š³dîŽÔdäå)ðê‘CEV®Öâ¦zÝ]½[ïj;<áöèjoP —\!çiß–‘âRà­y .Z,##C©÷ý®sên.×.I’-Á‰Ë¶^‘{-O‹Žöë¿_óu«±IV“WFª§CêÀþ€C†}Ê$iî<ùÿwŽR®»Z¶¼¼V÷}?*«)²ô¹exÕËçSãO¡àÛïÈHõ(å’ïtJÝ’dU×D÷þó?ýŒ|Ï<+I2R=Z½k—>®®ÐԷΛ~´\gÇr2ÀéÒ =®àâ\üÁÞ»2þñ‚ìcFwZí’dîŠ|Ÿûž˜Ü’‘-I²*ö„¶-ÃÒ6úY™’aH–%«¢BÆÀX5!8‡ ÷å—(ðÒ?Þ¸Iõ§Ï–ç?“}ìh™å»˜óŠo¼Ý«PNg±sçË{ß2·l•­O¡Òÿò'ÙGê´Ú›4Iò=ó¬\çœ)ÏÍ¿­o_yîÿ½ôË›u„Ë­«7mUZßr]pîÞ¾å»ÔxÍ …dë] û„ñ2ì6…V~!sÇ5Þü+¥ÿé ÙúuZýV]$µ:%†'²„ܬ®ŽôiòFÃR#--~»]†Ë%Ëï—Y]#Á!ÀACpN§Òþô„ÿûg ¯Y«Æ~ÙêvÊ÷.•Y^®àÛïÈÖ»wÜ!ÌÍ[ÔxÓ­ }ü‰$É1e²Òžz\¶‚üέݱ÷Ï2çñÇ)í±‡£¯”Èžö#FI;+ä}è‘hphUרþ´sdVTÈ}ÍUòÜtýÞ=CayB¾?<®ºÓÏQæ¼7d+Œÿ¹¿)#''RO]C›m¬úzI’mÏÌC#-5àƒ²êêãw dùý{úØA/80‡àb:D™o¼"ÿœW^µZfÉvÙG”ã˜rœêÏ¿X’dë]Ó×ÿìóòÞû€,ŸO¶Aå¹éz¹N?5²T¶“µ &S®¼rD¤œ•«¢д*¡¾^¡U«#mG kÑox¤ßGKãŽüpIL‡à^ý…êϹ@õg/«Å×fþÿ#Ir?»Õì5ßÓÏH’R.û®œ§œtpŠÃu~dßBÿ¿^{ß,)‘$Ùúõ•‘ÙïÏ>vŒ$)¸h±dšqûß{_’ä7¦CëmÉ1aœìÇIÁ Bïs?¸ð=)–}ìÙGŒ^O¹è‚½56‡ -û-ø·$ÉuáùT9ÚBpŽc–‘‘!«®NÞûj5Ã.ðÏWäîÉfSÊw¿½nîÞ­ÐGK’ŒŒŒÈéË ~ZΦó¿ôÕŸ}¾êÏ>?nèÕ^)/#%E9¯Èÿâßcî‡W¬’$¹üÃè5×Y§ÉHOWxõòÞó{)ÜÛ!’÷¡Gúp‰ärÉuÞìVãÕ_ø]ÕŸ}¾|Ï<ûk—Y.©éŽß¶:%Ú,-“÷7÷´jÓÌ1uŠìCË,-SÓoïiuÏÿÜ }ü‰Œô4¹Î>³Õ½ÀÜyÑïÞª¬êúÐ{€C†áv+õîߨñ'×ËÿâßxíM9¡ðÚõ‘åˇÒ}023nsÛöèsïØï{dÍ8JFjßHß²2…–¯ŒÜ°LIöoVN¶<¿»SM·üJM·þZþgŸ—}Cv° IDAT}ô(ù-Œ¼E0(ç‰Ç+å;DûØúöUêïîTãõ7É÷§ÿ§ÀoÉ>aœd)r8ÌÎÈžŽ©·Ý,ûˆá­Þ/¼b•,ŸOö ã¿QÝÍ\ßýŽ‚‹+¸h±ê¿u–œ'Ï’(¸p‘¬Ê*9O:Q){Nƒn)õ¡ûÕpé•ò?û¼Â«VËqäd…V}9ÙÚáPê÷ÊHm½¿¡U±;úÝ[€:ÿø€ÃÁ!è §SŽiS#/ìmÿ ã:çLÉ Ë{÷ïeVT(0w¾d·Ë>n¬<7]/çqÇ´îì7))ѧö~ýöö5/ä°  Ç´©² .N<üEçËV/ïoîVxÃÆÈO}äÄaÇä‰JÿËÓ1‡ ¸Î=[ö¡ƒÕtÇïú|¹Ì·ßÙ[ãè#”zç¯ä8êȘ÷rL"+½xPš$E?g¢JŒ”¥?ó¤o¼EÁù äé#×ÓR•rÑùJ½÷·q÷ŽtLš ô—žSÓõ7+ôù …>[.)²çcê¿’óäY1}l…½÷Öär%¬ÝַӦƧHÌdy½^¹Ýî®® ã„ oÙ"«b·ìcÇÈHOëêŠÚͪ©UxÍWz|þÛºþ®»ôƒü@O=õTâ>M ¯[/™aÙG —‘‘qªÝG(¬ðW_I6[äà{r³1­šZ…¿Z+ÛÁ²äwr‘ˆÇçóÉãñ0ã¢vÙ‡‘†éêJ˜‘%ÇŒi2–Å?q8nŸ´T9&MØÃÎæ°Gni#;KŽéGuBAh/Gƒà@ ‚C1Ä 8ƒà@ ‚C1Ä 8ƒà@ ‚C1Ä 8ƒà@ ‚C1Ä 8ƒà@ ‚C1Ä 8ƒà@ ‚C1Ä 8ƒà@ ‚C1 I–×ë•ÛíîêZ‡ßï—×ëUJJŠ<OW—€CœÏç“ÇãaÆ!@OðØcéý÷ß×Â… »º&º¹ûî»O .T0”aúòË/»º$º¹††™¦©5kÖ( * vuI8 ˆApÐ͆ÑÕ%à0Dp Á!€‡btsìq€®@p Á!€‡btsìq€®@p Á!€‡btsìq€®@pÐY–¥òòòV×6mÚÔEÕàpBpÐ-]ºTÆ “iš’"¡áÚµk»¸*]]Úf†^~ùe3Fõõõª¬¬ÔŠ+ºº,IÒ²eËôõ×_kРAš6mZW—€ÆŒC€nÌï÷«¢¢B•••Ú´i“ƯË/¿¼«ËÒ—_~©ýèGêÝ»·rrr´hÑ¢®. Œà  ƒ’$Ç£1cÆ(//¯‹+ŠøôÓOôî»ïªªªJ555]]:Á!@7bNUöûý]TMÛ8ùàÐCpÐmذ!æZ(Š9ièh‡ÝØÒ¥K5räÈèk¯×+‡Ã¡|° «Àá€S•º±;w*''G ÍfÓ矮††Mœ8±«KÀ!Žà s:ª¨¨ÍfSmm­&Nœ¨Ù³gkÇŽ]]q,UèÆB¡ ÃPVV–†ª>}útuI8Ltc@ îu˲r%8ÜtcÁ`0îu‚Ct6‚C€n¬­àèl‡ÝÀüwÿ£×Þšs¥Êè*‡]裗éäó¯Ô/-ÕÝÿ\®“λBŸ~ö¹$É4Í6gš¦y0ËÀaÈÑÕ޾øòKÝü»ÇTã.RöÈS”+ɲL ú뺇þOýÏèÞ[¢P(ÔÕ¥à0EppmÙ²E¿øÍCÚef+{Ø,å’iZÑ¥Çv›¡Ü#Ué’Ûþ¨ ¯¡ÞqÂC–* ³eeeºáδ½É¥¬âc•o·ï ›—[Šd‘G§Ã®œÁ“4¾ÏÚñÙÛjZ³IÅÅÅÑñÐÙ:Quuµ~y׃ÚXRÆàiÊs8eY¦LÓ’”(ü‹ˆî—O?K õuúÛ;ï騲J :ô`•€ÃÁ!@'hllÔ¯ï}D«¶U+}ðTå¸[-InÖr–a[A¢eI©iérO:MŸÕTèû7Ý£“§ŽÔìÙ³;ûc´©¢¢¢Õëêêê.ª…S•:P ÐoîDç]w»¶8†*Ì Jq§¶hÑÆ×:HŒ•ž•«”a'è­u|Þú|ùЬ>9¡PH^¯W6[äOÉŠŠ •••©¬¬ì ×€ÎCpÐÂá°ùãŸuÎ÷oÖÞBå;Yî´Œ3 Ï2ܷ;Abz~ÕçOÒ÷÷Wû½©¤¤¤c>H‡^ýuuÖYJKKS}}½–,Y"¯×{Ðj@ç3$Y^¯Wn·»«kèq,ËÒ³/þCÿ·`‰Ò‡L“;3O–eÉ4Í=VtOCËŠí@Ú4/{¶,SáPPÖîšTœ¥îü¥²³³;ýs1BÙÙÙêÛ·¯2335cÆ tÒIº‚C€6lß¾]Wýì6Ýÿ»ʙx¶Òû•ŒØ?Ÿö¿¸£—+'nhíí I2Ó ´Ý9Xßýåcš}ÙuÚ¾}û~êMlΜ9š5k–œN§êëëµvíZ9­^½ú €î…ÃQö±{÷nÝñÀåwõRúØÓdŽÈþ}->‰§õråøí:b)rËq¶ÙÛP2l fô×ꆠ¾}å-š6ª¯ºëeee%¨%¾ôôt}üñÇ1b„ü~4<<õÔSÛ=º/‚CIÚ°aƒÞœÿo­Y·Q…¿-—;Kfœ†Rûö4ŒÈRädÚÄŸÓ¨½3íy3ŠõﯛtÜy×èÌã§è×7µïæ@  ºº:ÕÔÔhøðá6l˜† ¦­[·&=º?‚CpX3MS¯½öšü~¿ÒÒÒtİb÷+”×W©FïN5zý ™RX†‚¦M~9åuö’™’#ÙœÑq’Ýë¼åÊ1÷nÕ¤ÕólÓÜEÿ¥k.>K?¸òR†Ñö¸{ƒÁ¸×“é €žƒà¶/^¬-[¶¨¨¨H™™™²,K)))JKK“eY2M3æ1 ª²ªJ¥›åK~Ó.¿=MMž"É቎̞†më¸}Û ›¹ÒµË9T÷¼´XùÇëúÍ ×éÔSf%¨­íà‡‚CpØY·n–.]ªÂÂB 0  ¶ÔÖ B‡Ã¡ü¼<ååæFÅÚÚZmÛ¹Zu~S>#UM©}%WÖžþRr§+w@¸gÐý.WŽ3HØÝK%V¶~p÷_4øñgôØ=·iÜØ1qß'Ľ¾ïw€žà6***ôÔSOi„ }úhÖ¬YÚ¶m›Þzë­VKq;bßÃx÷öë£éc©ŸR+–Kaÿì{¿a{ö4L¦MÌÂêôÞ 8ZËv„õ—9sµ­¤¤íqÐc’,¯×+·Û½ßÆ=Ñ[o½¥/¾øBGësá,ËRII‰ 4vìX™¦©ÆÆF-_¾\iiiš:ujôäå¶ÝK¦eYòûýZ½~‹jŒlù²†É´$Ë2ešV‹G+ε{ƲÌ=Ï÷}Lt¯Å£eYûmÓj<3¬”ÚMÝ7KW]|¶®¼òʘï=‹Ïç“ÇãaÆ!8ôy<ž¸'†¡H’Þ}÷]•––ÊãñhÚ´iêÝ»·^}õUmݺ5áØ2Ûpß{N§SF Ñä¾)Ê,_"gÃŽx-÷¿\9Ñ’äY®œÌŒDòeÑ'Õºáþgô_ßÿ‘¼z ‚CpÈóx< …BmÞw»Ý8p ¶nݪ?üP>ŸOyyy:ñÄUUU¥×_]ßxßÃý…Œééiš6n¸†º+å)ýX2cÃÎH)Ù 1Ñ½ŽØ÷0ÚÆæT}æpÍù´BÃŽú–®¿õ΄ß9º?‚CpÈkkÆ¡×ëUuuuôu~~¾úôé£eË–iÍš5’¤¡C‡júôéZ¶l™Þ{ï½èòb©ã÷=lÖ¿¨PGŽ(RFÙG2¼5JjßÃ6f ¶{á7 ©*sëÑW?ÓÉÇëÑ'þÔöxèÖÀ!/555îì7˲”-)²‹Y¾ûì3eggkæÌ™òù|zíµ×TSS÷ý‰É„Œ-ï9DÃ3¼r—"™á}[µ½\¹£fªAbAO¾6˜ýõÝ[ŸÐ]ýßíê €®EpyÙÙÙª¯¯OÖ9N†¡ªªªVí Ô·o_­\¹R7n”eY0`€f̘¡Õ«WkÁ‚ ‡÷ ô’—̾‰} 4uXo¥•.‘¨?Nd°[®üMg-F¥å)ËîWznR ’é€n‚àò²²²t÷ÝwÇìiØ’Ãá™h†vìØ¥h³Ù4hÐ 9N}ú駪¬¬”ÃáÐØ±c5bÄÍ›7O«V­’Ô1³ ãµs»Ýš>~¸òëVËQW¢[®Üû¶âpË‘–§<ï…‹¦¨ÒÊ‘‹¿<zþ|‡…ÜÜ\Ý~ûí:ùä“UVVÖæ‰¿iii’¤ÂÂBIRUUUtFazzº†ª¢¢"mß¾]@@éééš>}ºl6›^{í5UTTHêØåÊÍ6›MŽªbW¥ÜÕk›[µ=°£ONN&H4 )«¿z…Ë•“îTmŸcÞ½Iv_¥ÒÓR¼º‚CpX™9s¦î¹ç¥¦¦j×®]m¶³Ûí²ÙlJMM•ÏçSccc4ÀëÝ»·N9å¹\.íܹS’Ô§O͘1C6lмyóä÷û“®ißýµ“¤Aý‹44Ë”§êËxÚ“ ¿É¾‡©½”žâT~°DMÅß–/lÈ]·I6#z¦{\‰? º‚CpØq:úñ¬+¯¼RUUUjjjj³­ÛíVZZš*++ %)º„yÔ¨Qš>}ºª««USS#›Í¦#Fh̘1Z´h‘>ùä“è8±\¹¥¢Â| ëe“»be[uøRä6[Ù]²e÷Wžo³\…Ãåϧôº r„½²ÙlÑŸt7Á!@OBp[#FŒÐÝwß­#FhçΠú¾}ûÊåŠ_Í3MÓ”ÇãÑ´iÓT\\¬íÛ·+ ÉívkòäÉJOO×믿®’’’˜ñ:"H,,ÈÕ…yÊ?,Xn#ÜëÐ¥Èû‰Vf?e«Nyözy‡ž¡”P½Rý»Z†Í?iž„ŸÝ Á!8ì]xá…úõ¯­@  ªªª¸mìv{ôyshØò1??_Ǽ$©¬¬L’”——§iÓ¦içΚ;w®ÖÑžåÊÍy¹9Ó/Cž²O=¥£ONŽ·OcJ¦\i9Êm\¯Pñ ²ç Tž›†74´)¬Þy½öûùÐ}(ròò­·ÞªSO=UåååÑeÉñ´œqØò¹$9R“&MÒîÝ»UWW'I*..Ö¸qã´dÉ}øá‡ÑÃVÚ “ØÜ&';Kãö’§t™dEê8Єm6kncØÎ¨ì¦-JËÈ”1üÛ*4*•j5Ä„…ÍûDÚl6Ù,SE½óöûyÐ}´pÌ1Çèž{îQvv¶ÊËËã¶1M3&4lùÜívkêÔ©*,,ÔÎ;‡år¹4nÜ8åååé­·ÞÒÆ[™($L&HÌÊÌЄ!‘ð0Þ‘¾Ñ¾‡áô>r˯\ßùG«Ü^ÙÊ7Ëe·ñg¶  K} z‚C€}8]{íµºöÚkU]]­úúúV÷[†„‰Ä‚‚M›6M¡PHååå²,KYYYš:uªjjj4wî\ÕÖÖÆŒÝò1ž¶Úd¤§k\q¾RÊ—·o)ò~Ú˜ŽT…R{+³j•Œ¢IJz´†ºvËm„âÏ.ŒóãIq*7—¥Ê=‰!Éòz½r»Ý]] @·ô¯ýK|ðúôé#Ã0T\\¬ôôôhp‡£Ï[¾ny½®®NkÖ¬QJJŠRSSeY–€Ö¯_/Ã04}útÙíö˜½÷}Lt¯ùq{i¹ÖWÛåÍ&Ë4eZ–¬æ6{ž'|Œ>—|éý•Yñ‰ŒœbÙúMQG¥ 3˜ð³¶| ›QàÒý?¹PGNÓÕ¿J$ÁçóÉãñ$£¾¾^O<ñ„êëë5iÒ¤hp˜LhØòZYY™6mÚ¤Þ½{KŠ,{®¯¯×úõë5`À5*©pp÷ÖmÚª’p¾üiEm†„‰‚Ä@J®lÞJ¹Uò>Eƒ³ ¥M CÂ}?»ÛÒe³Æè¦\,Ã0ºø7€d€eË–iñâÅ>|xt†`{Â4Ó4 µqãFÕÕÕ)777ö•––jûöíš:uªrssÛ5Ë0Þµk6¨Ü=D!wîþgîé2\ò¦ä)³ôC…ûOW¯¾C5ÀÝ Ë ïwvaóóP(¤±…Nýá¦ïi@¿¢®þ• P8ÖóÏ?¯`0¨Þ½{'=ãpß×uuuÚ°aƒ<<OôÞ¦M› 5}út¹\®vÏ6lyí“Uë´;{¼L‡'ÎRäÖË“›ÜErïZ!»'SæÐ“4¦W@)Š]–Üæç4M¥Yºîì£tÙy§uõ¯ ˆàà*))ÑË/¿¬Þ½{Ëív·+4ly½y¦aAA¤Èòe¯×«7*//OãÇ?àeË>ŸOŸ­Ý¦šü©q—&[–%¿#Sþ`HiÕ_)8ä[Ú/OEž@Ò˯MÓT8àÕ‘ÓôàW*##½‹3ø&:È›o¾©uëÖ©OŸ>­N[n®Y–•0€ Ú²e‹|>Ÿrrr¢÷+++URR¢qãÆµ¿=⮊ÝújWH9£Z‡aË®:w¥•,’U0ZYCÒØÜF³ [,KÎVnüîIšuìQ]ý«@ 8è@úË_þ"›Í¦ŒŒŒ¸a[2Ë}ëëëµyóf¥¥¥)%%%þmÛ¶MMMMš:ujôTæöˆ_mجí¶~ ¸óeZ–S eí^§Ó§Ðð34e@ªrÝÉׇezk5sd/ÝñãËäp8ºúW€BpÐ >ýôS-X°@¹¹¹2 #éý÷½VQQ¡òòråååIŠ,_öù|Ú²e‹2335a„èøÉî{øñе*/8Fµ¶¥—~¨Ð 5xØHÎ7$+ù^BŸòlµúõÕ³5zäÐ.þÆÐÑ:‰išzþùçUVV¦ìììv‡†ÍσÁ JJJ¢ãX–¥ºº:mÛ¶M#FŒÐ€’Þï°©©Ió—­“+÷È“uÌ`ÒJú´dÓ4e5”ëŒ)uÝ%³»úk@'!8èd;wîÔsÏ='—Ë%—Ë•th¸ïžˆ*))‰Y¾\VV¦ºº:M™2Eééé ĺº:ƒA}QãÑÀ“®ÖÐ\G»–%‡|õ*r6è·?¾Xùy¹]ýÕ $o¿ý¶–.]ªÌÌÌý’’hOÄÊÊJUTT¨   fV¢ÇãÑĉe³ÙZ…†ÍËž‹ŠŠ4hÐ }RâWŸ‰§$? 2–­~‡¾sühý­™]ýUà 88ˆ¼^¯ž|òIÕÖÖÊãñ´+4ly=¨´´T¦iFƒH˲ÔÐР;v¨¸¸Xƒ–išjhhPSS“¦L™"»Ý.Iút{@E“¾•\pØX¥Aé~ÝþËù[à0BpÐV¬X¡9sæÈápÈf³ÅY˜L¨çõzU^^®´´4¹\®h›ªª*UVVjĈ8p Øêý?ÝR¿Éû C9ê¶éª3¦é¨Ic»è›@Wi]]Àád„ ?~¼ž{î9}ùå—JMMmó0“Dž¸\.©ººZeeeÊÏÏ—$9N¥¥¥)+++&4Œ0d³Ù$I–eµz”$Õ—kt®ô³Ÿ~_†atö×€nŒàà 3 CW\q…ÊÊÊôÄOÈçóÉáp$¶üÉÌÌ”ÇãQEE…uä‘GÊétÊçóÅs[lp(IFÈ'OýVý÷Å'iPÿ¾ãk@7gëêW………úío«“N:I^¯7zšr2¡aËë†a(//OEEE>|¸LÓŒ†ƒû2 ›l¶Ö?öúíšÑ'¤o¸œÐQÌ8èb§žzªN<ñD=üðÃÚ²e‹RRR¢{Æ ÛºÞ̲¬6ƒCËRôžá«•»±D?ÿÞÊÈH?(Ÿ=Á!@7’’¢[n¹E«V­ÒŸÿügƒÁèá)û†mÍJl¹ga[Á¡ C6Ã’Q½Q³ÆõÓÌiß9ˆŸ= K•º‘qãÆéñÇ×Ô©Såõz.SÞwÉr³DK•½U;•ß´A¿¾ò4Íœ6é`},ô@‡ÝÐ÷¿ÿ}=øàƒÊÊÊ’ßïO8ë°ù±Y¢àpl‘Gÿ}ÉYr8Xx€Äº©üü|=ôÐCºôÒK …ZžoŸÃf–eÉ0ŒVcù|>íÚµK—_~ùÁþ衺¹SO=Uýë_5räÈèòå¶–)K‘àÐn·G_WTT(//O÷ÝwŸ†z°Ë@Å€ÀétêÎ;ïÔªU«ôÀ¨ªªJv»=&4”"K• ÃP0TUU•.¿ür=º ª@OÆŒC€dܸqzá…tÆgD÷>Ü—iš´IYU IDATª¯¯Wjjªî½÷^BC‚C€èºë®Ó‹/¾¨~ýúÉï÷G¯‡Ãa†¡óÎ;O?ùÉOZ-YÚÃdy½^¹Ýî®®àÍ7ßÔSO=¥††yæ™úñ,—ËÕÕe ‡òù|òx<‡‡‚P(¤·ÞzKgŸ}vW—€Žà ùàƒ …4cÆ f Sô ÙÙÙª­­Uii© »ºšƒCGƒà@ ‚C1Ä8hÁaSدƯ]}BV¸Ck[¦,Y:fÐ «&ÐØ¡cÖ›0CI··duøw€Ã›ã`½Ñع?ÕàôB-8á΄íêƒ^ýjÕß´p×ZS[¢âôÞ::o¤îÿ]õõäÐ{?ûõ¿õ–÷ôIå9m•;L?vªÎì{ä×Ò/W>¯‡×¾®ú þ®tÇ7?™zEõfMœw½ž<òZ];ô[m¶ó†ºoÍÿéÍŸjmÝ­§ê„‚1ºcìwTèÎþƵàðuP‚Ã…å«õuC¹§&l·¹¡\g,¾[kjK$Iù)™ÚX_ªõ¥š_º\¯Ï¼MGöšôûš–¥}ú´žÚ8_’”áôÈök^érÍ/]¡ßŽû/Ý6úüþ\!ŸþwëÜ?žg6-Øo›ª@ƒŽœƒ¾n(—$¥;ÜJ·{´®n‡ÖÕíЋ[ÞÓ'ß«ñÙƒ:´6>:u©r™¯F/nyO—~ôhRí¯_þ¬ÖÔ–hlö@­;ã í:÷¯ÚvöŸuRáx•ùjtÅÒÇÛõþÿÚ¾TOmœ/‡aלcnTå¹/¨ò¼ôð¤+dÉÒ¯VýMË«¿n÷çò†z§l…Îûà÷Úé­jwÿxV×lÕ]_¼¬?n˜·ß¶¿Zõ7}ÝP®ü”LýçÄ»T}þ‹*Ÿýœ^=öM̬†O—~ôH‡/ËÀá£Sf®«Û¡ >|@«k¶&Ýgc}©^ß±Ln»S¯{‹ŠÓ{K’ú§æiÎÑ7jìÛ?Õ—µÛ´ l¥N.ŸÔ˜¯}]’tÏøKt~ÿ’$§ìúùˆ³´¾n§žÚ8_Xû†žŸþÓ¤ë<çý{5oçrùÍ`Ò}yfÓýjÕK*÷Õ$Õ>d…£³_>æF_0&rÃÎî7U›]g¼÷;­®Ùªõe–ѧCêÀá¥SfVµ­±BYÎTe9Så±»öÛç6Ì•iY:¡`l44l–íJ‹®{#©>«Ú¤%»×ÊfúÞàcî_=ôIÒ?¶} ]¾Ú¤Æ”"3Ýv§²œ©Êt¦&ݯ-_7”ËD¿+‡aOØ~S}™‚fXN›]3òFÆÜÿvŸ‰ÊOÉ”$}Y»í×€ÃS§Ì8œ–7\5çÿ-úúÖÏÕ?ûsÂ>+ª7K’Nï;%îýÓ‹&ë‘uohùžvûÓ<Þ‘½†Eƒ´–&å VOŽJ½Õú²v› Üc“wÓ™OEŸïðVªß«ßOª_[î‰îIôõ ÿ¾]‹v}Ñf{»aÓÍGœ«\W†\¶Ø_ŸiYj ù%I#2û~£Úpø:h§*ïO©·Z’Ú\Z;,£H’´ËW+K– ‰Çó%O’†¤ªÔ[mÛ Íè£ûÆ_ÚæýûÖüŸšÂ~õOÍÓ¨Ì~±2:Gcȧãÿ}»®|¢~8ìÔ„m}á ^زHKv¯Õæ†rMÊ¢“ûŒ×©}&ðûÿ§|µæ•~®O*7ª_j®¦çÐeÅ'(Ýá>à1›ýèÓ?©ÜW£sÓ7K’æîüL·®|Qÿ8ú†vM(ºâãÇ6Ívmç†C_÷ ÷„w½\éqï7_Yaíö×ÇEØj•þzýîË9ZP¶’ƒU‘P§œªÜ^)¶È)Å’T¨Û¦&ØýªÈÓk¿cövgGÆóÇ/ò^ ’¤>žœvÕÛ8 »Îì{¤.p´îû}uúÿhPZ^Þö¡þµ½}ÿ•€îà?å«ôüæ…I‡†’ôðÚ×%I— š ›}gà1–ÑG»|µúÛ–ÅI÷êöµ¹¡\y)™ºfÈ)­îõvgëê=×þ°'\LÆ._­ZûšVÕléÐP’žÚ8OóK—'JRIÓn=²î BCìW·˜q(Eþ¥« 6Eü}Uï¹î´Ù•—`ùqËñ$µ9^ä^$TL&ˆì)²]iºnØ·uóŠçõnÙ*]V|BW—@»\^|¢Nê=>úú¶UÓÜŸ%ìóïòU’¤Ó‹¦Ä½FÑ‘úú×õnÙJ]9xÖ~khï´¢Éq—"ŸÙwŠîXýw-*ÿB!+œÔÞ‰ÒòµüÛG_¿[¾R7.ÿë~û%òü´Ÿ©1䋾>ê›0C ûŒÈìÛªŽ×w|¢;VÿýÕCS· ûxr´¾~§V×l{ÒÑêš­‘vî^û=Q9Ò.§U¿}…¬°ÖÖí$õ ‡¿ÿê_z¥d©.->^?jã$©~©¹’¤5›fitˆü”ÌVgä¸Ò¶oyvÂä^Câ¶™Ôk°$%=‹±¹Ý¤œÁqïÏ.–Í0dZ–Ê}5êëÉÝï˜.›CrŠ£¯76”&UK"û¬’Ì~‹»«U+ªÉ_·Xª,Ig÷›*Iš_º<îýæÿ²pfßøÿå`_§M–ðë‹ÚmÚé­Š¹¿¤b­jÊKÉÔ´¼XõÁW’¥+×·ù=IÒÆú2IÒðŒ¢ƒU]¦9ä3d(Û?dìÕÎR÷ºš÷¾ÍØû^íYR ô$Ý&8¼lÐ rÙz¿b–WÝêÞö¦J½²g¿¾«‡¶ÞW`[S…æ•.×¼Òå­N"êãÉÑé}'K’ÛçÔa)r2’$}¯øD¹l{'^†¬pt¼Í åòÙ>¯þZóJ—ëʵßx¬ã FK’ÞÞùyÜÙ” !ŸžÙ´@’4-oø7~?º»Ò=a`¶+­Íw½\‘mÏÊ|5ÉÙºÚÞ.­×ž­ÔÊ¼É ô4Ý&8ÌMÉÐUCNRÐ ëœÅ÷iAÙJ5†|Z¼ëKµøUúëuJáÏÔªßkÛ—éÔEwéÔEw©rŸƒP®q–†]÷¯yE®}U»|µÚX_ªŸ~öŒþY²DN®ö­V}êƒÞèxsJ–tÈgûõª—tꢻtí'O~ã±§÷ÖéE“²Â:iáúó¦Z]³U_Õm׋[ÞÓ‘óoPIÓn‘Õ_ÿ=ìô¨€îÍŽL$rÚÚÞgÐa‹D -÷L$°grRËÉFû²{Æ '7&ÐÓt›=%éñÉW«.ؤ¿mY¬SÞÙêÞ ½Çê•con×xÇŒÖËÇÜ ‹>|P7.ÿk« G³]išwü¯5$½°#J?¨^9ö—ºèÃõêöuͲ?ÆÜŸÜkˆ^˜þ3¹íû?^€ž®À%iïÁªñ4žÚ|˜êþÇÌV™¯&z°j<ÕíèiJp8»ÿQ“= ºŸ@[ì†MÏOû™Îî{”>¨X£5[42³¯ŽÎ© -ÝÓçÜþÓ46{ $)¯ÅÆ©Ñ÷î7MKOù½æîüLK*ÖÊmwéèü‘:»ïT ÝgQIÊpz´pÖo%i¿¡b~JV´m¼ÚšÝ;þRÝ0ê¥;Ü Ç“¤G&_¥ê@CÂý ]6‡æs£Þ)]¡Oª6êÓªj ù52³ŸfäÔÅMj3TÍÁ]Ð «>èU†ÓÓ¦9äk>LuÿcFÂÈ*Ûadó˜Ež^íªè)JpØ×“›ÔéBRdsÑ ÌÐftØØ“r·y Ò¾†]ÇŒIª­ËæHªms°™Œ}—b·ÅaØuZÑdV49é±8å¥dFO8ÞÜX®qqþ¿õ–†]’¤¢ÔäB¾æYŒ›ãŸ°Ã[© –”| ô4ÝfC€a7lš‘7R’´ leÜ6o—~.I::oTRc—9œôÒqïÏÛ¹\Rd²P¼ŽÀ¡€àôxW9Y’4gÛ™–ÕêÞ¶¦ }X±VN›]—ŸÐê^Ð ËÊ¿ç0”fçõŸ®áEq@Ý¥7Ž»Mw~ñ¿ZX¾ZË«¿Vw/V4Y?y–Žì54¦Ï°ô>ºcÌE’¤i ë="³¿îsQôTè¶Ü4j¶šB~Mî5$a;IúÕè 4C*ô$`Ë„œbÝ1æ"õOÍKº†$ËëõÊíŽý—ÝCvv¶jkkUZZªÂ®.€!d…å0ìÝv< »òù|òx<ìqMòâpCp Á!€‡‡ ÆÆFÝyû­zøûäóùººô@‡‡`0¨GyH—]|¾ü5¥ªÚö•¾3ût=õÇÇ »º<ô ‡‡Ë²ô÷¿½ ‹/˜­Ý[×iæ”Q*è•©ì¬ MŸ0\W,Ñì3NÑ_Ÿý‹LÓìêrÐöpóçÏÓwÎ?G_-_¢“§SQAŽl6›ìv»l6›l6›rs25mÌ}òÞ\ñ­YúçœtuÙèæ I–×ë•ÛíîêZП~ò‰ûÃïUÜ··÷+e™ ‡Ã …B ‡Ã1?Í×C¡¶—W©´²Aÿý³tÚé§wõGIÈÎÎVmm­JKKUXXØÕåàæóùäñx{š 6è{îRa^¶F é'CV›!a¢kÁ`HÛJw«º)¤›n½]3gßÕ $@p€ƒ…à°‡)--Õ}¿ûÒ=M5XN»-©ÀpAb Ô¶²JyÃvÝq×=šrä‘]ýQ@O>ù¤ü~¿®¹æ¥¦¦vu98„öµµµzà¾{lªÓôI£åq;Û5³0Ùk>@›wì–Ó¡ßÝ÷ FÝÕ]€à°›óûýúŸGÿ ’-uÒ1S”‘æ9àpÐ4ÍV{Æ»fš‘=›|Ú¼s·²óúèÞÖ!Cºú«ÀADpØM™¦©çŸû‹>^ò¾Î˜u´òzeuجÂö´mhôjÃö Ÿ8UO<ýç®þZp4‡¶®.{½öê+ºöªË”“Öµ—œ«¢Â|Ùl¶˜»Ý~À×’mkZRYùnýëÕWÕÐÐÐÕ_ 2GWéý÷ë¹??©Óf«ëp©,+²lØ Y²Ùl²,+úcš¦ Ãhu=ÙkÉ´õùzï“/ÔÐèÕÌIÃUí ËáàÀÁã÷ûµxñb­_¿^M^ŸÊêCª ¹Uo¥ª!hhpZ“&Œ¢Fêˆl±t¡.ôÅ_豇ï×Ìi“uÛÏ CÖž¥Â’eņ†–eÉn·ðµDmC¡°>^¹^[JJ5eô åçH’*êëät:»ø›àÐÑü¿¿6 ?ØW ÐÓO?­>úH©©©²ÛíÑ{ŽÿÏÞ}Ç·UŸ‹ÿœs´e[òÞNâ Ç™d@€@ lÊ,¥¥´¥-Ý¥ãR Ý·-—ûëm{» ¥t\è`µ…° „•„IÈÞ{xÆvlÙÖÖ9ç÷‡mY²¥ÄIä8$Ï»/½Î9߯ŽSKzô<ÏÈØYÕ5žÅmÆlZÇìÊíL¯Ì惗7bóâT%=GÀþýûùŸ{Ì´Ú±\~áyX,Ú°ô+<Ò¢(º®ÆØ°m7+Öna¨b&Ž.Mšëî¦Nž{õ­ºRB!ÄÈÚ²eË÷9xð Ûwì`ó¶´ê ³ËOWw`ÃÝ4ÑMÐ ÝPÐMU°¨ © š¦`Q;9ÙYx<9äzr?f55())I9~AA………~æB!ĉ÷Úk¯ñÄO ëú¾`3PÙnŒ¢Ñ9‘KjܺΛ˥óf€Ù qjëëq(‡'P[[ÿïžQV˜Ãw¿v‡=ÔËtab6Cºmûšyyé*ò³]\waÏÖÄó=¡e!„Bàóùرcë7ocæ­´´ûF Wfv9–œbT{)Z¡ K¥ ÕbGT`¨¹û1 +¥=@м°}ê?^N›Fa^Ó'Mdê䉌?ž‚‚‚á{ÒB!Ä òøã³hÑ"rrr†œ•¯b0QÝCQ¨•'7ÎeF©Å­²ó±—øÒ‡/æ qzŒÃÀï÷ó‹Ÿý„HÀÇmý ùùyCÎ ŒÅb†qÜ+*÷mkkogÑËËÁˆ1æ, AEHî9ØÍ3//ÉË'„BŒˆmÛ¶ñ›þÀ;«ÖâE1mY(ž ´Ür\£Ðî™—hÝÑ^‡ÙYCÕñf9™1u·|è:fΜ9"óB!ŽÕóÏ?Ï?ÿùOl6Û1Ÿ#‚•·”³[äâœ3&@û^î¼y!N§Ä:„8}‡8F±XŒßÿî~¶mZËoý••åI›¦y\À£ vûý<»x9Í[˜?³†,—#>·¾í»›»yú¥7Nô¥B!†EKKKÚÇ¢Ñ(ËÞz‹>ó";÷7s—BÑDÜEc@9ySð5«ÍæÄpÑ}« }cÊK¸ñšË8þ|ìv{Úc¥ÄY!ÄHÛ¼y3ÿýßÿËå:ì~¦› i'OíÄJ,Í^ /ëg3§ÚËäÉ“P[·ñO ó“â4 Ãadš&O<ö(/¿ð4ŸÿÄMLª­I»ïÀžƒÇšEx¸máp˜ÅËV²nÓvΚRMi7m pàmws7‹þýú‰ºtB!İس°¥¥…W^}ƒÅK–Óˆ¢Õଚ-+w„f˜рྵ˜·âu[¸è¼s¸dá‚Ae͵µµ#4C!„¢çóð×¾ö5ÂáðöVˆ¡qÀ("jjŒ×¤ì¬ÆÆsæE\ScaÔØqGð¹/ÎôÔ…8åIàp˜¼òòËüåÏ¿çúgŸ5å ¦i[À0²zÝf^Zò.㫊™T]ž28x¸âîænž|áÕqé„Bˆa·eË¢Ñ(O=ý,ÿzî%¢VJÙtr*'£X†Ú‰ðýÅÔ£t×mÁl\]ïâ¹søð×ãv»%p(„bD=ú裼öÚk¨ªoÑ5”re…ýF19J“\¥3éñf#×Õóøäœ|ò²ì\5ÉÉÌ)‡ëiqJ’Àa†Õ8À·îüW_<ŸK/^´dü‘ôõ/<ÞÀaâö»÷ñØ3‹ÉÏq1gj5À³ Sw5wó¯ç^ÉüB!N°úúzîúî²jý6´Qg’=ö,uè¯×§ ÿþ Äö,£vt?½÷‡TWWô”„Bœ†¢Ñ(ßùÎwðù|„ÃaÜn7~¿à°­6úİ6­4™yŒUë“[oL ËSÃMó'¢µïâÛŸÅR„8²ªr†½µ|9ï­ZÅ¥óf¡˜0ô"}«†1h•äTÛ·Êr{G?ñ<Ñh„ËçNÁÒÀLTåˆÁÃ#eL !„'‹eÈ}Þ[½š?<üýÖ È]xzppWM…ª©ìioäª[ÿƒ\kˆÛn¹‰³Ï>;¾d" !„n‹-¢½½UU‰D"F™;w.Û¶m£µµ›Í–ös©…%ÆX¥aÐcSÕí<Ú1ŽýõÍT”°vóΘ4~XŸ“§" fˆ×ëåüY5üá¡G¸ÿOð³ÞÉ3f ¹™ºªªñbßï'n3 EQ’¶ùý~}êEvï«çüYÉv;âÁ?Ã0€ÔÂtÛûnŠªÏB!†Q4åÉEÏòä /õŒ&kâ xY#=­“Š=·û9· øÙo¢üöÏ\{ùB>xý5#=5!„§8Ó4Y±bjïçMÓ4),,ÄçóQ]]Mmm- ¬_¿žºº:¬Vk|ÿg´EªÌ:6ÖÙ¨*/fɆý8âHà0Cl6ªfaÎÔ±„ÂQn¿ûÇŒ®ªä~p¥•cŽx¼¢(CÎ,LÜDyþ•7YúÎjΜ\Í´ gÚ¿ïë±UE‡B!Þ_žøç“üýÉç±OÖü/¡ÈkÙaiv9Ó.Ç4/eÑ–ÕüóÓ_á#7\Å·ïü:Vë©Ù÷Q!ÄÈzõÕWiooGÓ4¢Ñ(^¯—íÛ·sÝu×=ŸM«««™8q"ÍÍͬZµŠ;vF±X,Cn V­5òv[¾ˆTÓ q,$p˜!v»SQPT·ËÁ¥çN£Í×Å5ÿ2W]|>w|é6Üž¼Ãžc`aªÌÂø6EåÝ5kyô©©]Ê Ï9rðˆRª,„âdâý­^½†Ÿüò·è¥3È»øk0ö1æÏŸÏóÏ?ϦM›‡Ã(Š‚Íf´¿n* ƒ=‹ƒm}.Bœ$p˜!v»p8äåç£*Q4âà¡NF—R˜›Ã™“ÇÆøîOî'×ó0?ûÁ7¨¨®”Õ§ªj<ÛPUUüÝÝüá¯O°nÓvœ5 O–+ep°ï˜Leq!„'£EÏ<ÏC?‰½ö2ò,ééœÒlY¹äÍ¿ Û9ç’ëøêg>Ƨoý˜´3BqÔêëëÙ¿?Š¢Fq»Ýìܹ“K.¹ä¨Ïåñx8óÌ3ÉÊÊbÆ tuu‡žÏç‰ ‹UÕðunu"„8< fˆÍfÃ0ÀátŸç Ò} ˜n²sÿAšÛ:SQDŽÛÉ%çN£Óäæ/~‹ygÁÝ_ûÙù%ñsõ•,†Á¿ž~‘§ÿýgOŸ0}Lfê IDAT¤>†ÙbúU«„BˆáÕÒÒ’T’  ¹ëû?¦.–GîÂáéc8Üá°Áë>3Õ>#Í]6³tÿû¯×yðÏó¿ÿýCòóó)((f!„CòøãÇïëºN~~>¡P(e¦àPY,Ün7ø|>òóó1M›ÍFHqâÐ T«Œ(¥…¹™xBœV$*”!v»]7pØmääcë]*¾ïæFظ£ŽíûšˆÆt¼Ùn®[8‡ ¿‹Koú ÿߟˆ»€ž²ãåï¼Ë§¿ò-víÞŇ¯8QeýÍbûnŠ¢ Ú–¸]Ó´øÏéöIµ]Ó44M‹ï#„Bœ vìØÁGoûÍgã~¹,~2EÅ3ù"ô)7òé¯ÜÍŠ•«FzJB!Þ':;;Ù±cŠ¢‹Åp8ìÙ³‡³Ï>;#ç7M“ææf6lØÿ¬[g–PጋÅÐ>¦ÕŽÏÈXBœN$ã0Cl6=DwNÛ6¬Ã›í”±wÈç§£+@Ya.•%ùŒ*/bTyo,??þ_ýôͼ°l 9.;¼ä€!e±g î8E•À¡Bˆ‘÷×Gžà/-%wþÐì²âH³å{á—¸÷ÁGÙ¸e;?ýïô”„Bœä{ì1b±ªª‹Å(..¦«« ‡#õâ¡Çjâĉñûû"js5b±J8(}z…88Ì»ÝNL7°;äæçcµÙX½iå%”.ßihé ¥£‹ªÒJ ¼ÌœTÍôšÑüúáñÅ]ƒ­wYù£ ±Ó'ÙB!N @ €ßïßÜõ½Ó ”P°àóC>Ïq}핉l{3}±qüìÇI8æhg0¥ÍŠf%oîÇyi综wÅ5üñ¾_ÜívãrIW!D£Q6n܈ªªèºŽÕjeÏž=Ì™3'£ãäææât:{/U¨7 ¹4ßB,#›PFÇât!Q¡ ±Ùl膉Ãn'/?²’"r=ÙD":+×oå¯+^Üw3 Ø[ßÊúíûéô‡°Ù¬xs²pÚíGUŠ|4eÈ} ¯ õ8)Bq"ùý~Z[[immeÍšµÜòÙÛi)ž‹gʉ[E9Æ[òI”#ÞÒû>㮞C{é\~ýÍ,Yº4þûë !„O=õ@è "æåå‹Åp»Ý§¸¸8~—QN©3Œ#§€X4Bu¾5£c qº¨P†ô,ŽÒÓ€5?/«ÕJ®'›ì,%Eù´µûXµa+Ýþà €](c_ckÏÏ]?ÂTÀÃSŸ+Õ>Š¢`±h#}i…Bœ†ž~þî¼÷7äÌÿ®¢1#=qŽ‚J¼ ¾Ä7⦅¿>òÄHOG!ÄIÄ4MV®\‰¦iñlÃ}ûö1cÆŒŒŽc±X°Ùl½ ­(¬Õk8³Ø$¦Ä:›¹îâ¹OˆÓ…3IQ°Y­äççc³YAQ(/)¤º²Œœì, ò¼ì>ÐÀÚÍ;G¢)ƒv(¤èÍí:£Ápì¨C F&ÞLÀb‘oe„BœXOükÿ÷ôR |Õæééˆ!RmNŠ.úO­ØÃÿüâ7#=!„'‰W_}•ööv 'Û0''‡`0HNNNFÇé땨( {blV•ÜÞÌÆ"‡ŽÓ)ï)„8Òã0ƒTUÅn·‘›—oºz ¡™Š²bFW”ÅØßÐŒ®ëlض‹,—“š±£°Z,hªÖ8ìÏö‹÷4 u3zÌh>8¯«¦ÒÒÑÅ’wVáTbØ­–Ãö)JÿÔÛu»Ý>"×R!Ä飥¥…ÖÖV g”§–n"ïÜ[†tlº2_å8újZ¶½™®{`º¦‚JêÇÍ„þ…fŠþ‡ UoE³çDƒ†ò±ÃÈ{ÆU¬Ø´˜o~ç|óë·PPP@aáàžÏB!N}o¾ùf<ÛÐb±PWWÇôéÓ3:F4Å0ŒÞlCX£×pvq\+Ÿ¼Y² …8V’q˜AŠ¢ * A¿ŸË®º–9³gQUQJ}S -mØm6&Œ©btEy^lV++Önf×¾zTµ§g¡Ò›qØ— Øê _RÆÍ7^͹³¦á°õdæe»øÀ…s™4e-]QtÃR&á‘ú&&e?¢`³ÚFö¢ !„8müñ¡¿òÔòmxç|h¤§"ŽSÎä…¬lB2…â4·~ýzˆÅbdeeÑÕÕ…×ëÍè8Á`Ó4Q…:£]uàÉÎ"‹QáÖ)+)ÊèxBœN$p˜AŠªaѼµøYüþøàÍ,¸ør¦ÔÖP”ŸÇÞºFZuàv9©7†Ê²Š r‰Æb¼½zSOÀNIæ5´v1kÚd¬vWÊ…JJò½\µð<Ê«ÆÐÜÞÓl6SD°X¥TY!Äð»ï?òâÚz¼³¯驈 É®½•MŠ…â4öÜsÏõ. Ú“èR__ϤI“2:F  »»kïg×5ÆDfåv¢£aú[øÜ 2:ž§)UÎ ‹Å‚ÇbÒ°åm¶ê6Š+ÇqΗ°wç6²ÜÛñuv±ç@ù¹¼žl¼žlZÚډƢI™†}åšÖS|¤G‚˜€b±‚®*K )+ÊgÛ®ýìÙ€¯ ³·üŽ­„Ù4ûûD!„™â«î~ÿG÷²dWž3>vÿ¤RÜÞ è)ûí+½UJ}K•S•Ü'i€Äó¤«TN÷@Ê ƒBê¹¥“nÎñ×mÀ<ÒyÒ=ït»qVG/»v«¶¼Î·p÷þð»¸Ýn\.×0Œ&„âdR__Ïž={PU•h4Jvv6 ???£ãÔÕÕaV«•&3¿’…Çå'‹11ßBaAfÇât#‡™”ÁçtØ)v+øöodÇ–õX]YŒ®™JEÕ(&TÂ4Möh ŽP\˜OíøÑ½C’²þ4U‰€1 =ÂTmp ±Œ]΅瞉aqÒêóy1”t¥Ê’q(„b8øý~Z[[ùÆÝßcé¾9S/ò±ª¢ ¨½7¥'$§@ÿ6UAQÕþ[Bÿàt7UÕâ·øù in©þ—hУ}çI|íxKšOß>ýÏi %Å-y‡„9 ¬Ú¼S§óÍïü€ÖÖÖxÀX!Ä©í‰'ž@UÕx¶aCCãÆËèÝÝÝ466b±ôäD­Ñk8#ûQ,¨6¾róåOˆÓ‘3HAEÓ´¤[ž'‹ %nèj¢±¡Ž°¡aÍÊ¥¸¸˜ Õ£èòØW߈aÐÛãPI æiZO UÉUÅÔcèÑ ¨ZÏmà<˜4ngÏžNwÄäPç±QÀj“À¡Bˆáñ'±ª>BvíE#=1̲j/`U³Æ/î{`¤§"„âèîîfÛ¶m@ÏÂ%‡ƒ¶¶6ŠŠ2ÛkpãÆèºŽ¦i´š^ÚL/YZ”X,Fm© ¯Ç“Ññ„8Ià0ƒ5}@®ª$95¥diaš››©oí¤Ý¦¤¸ˆ±£*éìîî ÜAÒqVM‹¯èøèÎ>ðü.š£=ÁB#! ƒjEÑWkŠÊô‰c™>y"mAº¡£ b"‹£!„6läïϾAÎô+Fz*âÉšx>˶µòï—ôT„B ³GyÃ00 EQhjjbÔ¨Q£»»›-[¶$dN`º»…¨bÃjãŽ[¯ÉèxBœ®¤Ça)J_‰ojªª2câh&Œ*eɪMlÙu€X,FiQ>SúJ•{w}}­ Ãè9ÞiQYw°‹³_ÏÆðÃYÅ8¢GƒèºŽj±£¡AãZ43&' ³aÛnr³8ìÖ#ö8TT›]z !„ÈŒ––Z[[ñù||éÎïá=ÿóƒöØË0U‘­¢*¨} †i¤,ÅMÚ¢ ηô=ý’ú#fn)ÇLÓW0ñ¸£+Nè¨öŸÛLœYâÝ„ñ“ú$¦)WNÜ'qáèw3óîùåo)/-¦´´”‚‚ ‡||ß¿!à¨BqbÄb16lØ€¢(D"û÷ïgáÂ…gùòåD"ìv;íf6f!cŒ]ÄbYÌ›GV–;£ã qº’ŒÃ 2IŸÁ—xËv;¹òüÙÜrõx³¬^¿‰7ß~¯7ã09Ðfµ`ôFZÿ¯ëÙ]­Ì|b÷ï aXìDà =†jµ§œŸÍjáŒÚ±æSw°½·×Dâ¢,‰7Ó›M2…BdŽiš|ýîïãœuªU¾œ:Ý(ŠJöÙãŽïüˆh4:ÒÓB‘a1Ã䇉÷³5M“X,ÆäÉ“yçwâåËÇ+ ²lÙ2´Þ/×è˜ìh&Œ {¤;?}CFÆBHà0£Wú›êVV”Ï>z5Ÿ»ù*Ê‹“x}¥ÄICËàlû×5pÆ¿¶óR›Šb±b‘`7†i Xl)WetØlL«©ÆnwP×Ô²|ÀjK„B!ŽÅO~þküÅgbÏ-驈buy0Æ-ä‡÷þt¤§"„"ƒî{qWþç"þ±I'â‡jub·Û{ªÙ…I“&‘““Ûo¾yÜÄ%K–°X,tšnö›¥ØÃÑõçÖ–ât:3ô¬„RªœaZšr¨Ã™^;–iµc{J„’J•- º®cQ5ìZê8¯iÂ]Ë÷ó#‹Ê}ó*©µ‰FÂè‘nLEEѬ ëƒŽËr9©WE»¯‹–¶C”$•/£HÆ¡Bˆ---Ç}Ž<¹ˆ•ûºðÌJ.UJ¹0=«'§lr”++CØ7Ý>Ê‘J˜='JØ`&?Ö;NRIpºrâ¾V" Ç&>®$–'+‰åÆ û¤yN}_H3’bî™ä*›È–u»øÛ#sËÍ7¥Ü'‹ÑÔÔÄÁƒin>Èþú&öìÛO}C#áH”ÊŠrjkÆ1nt%”——ùƒ¢”8 !Dfýse=ëöwR›CÀn¡%à¢!PÈ({V#š# bš&µµµÄb1^~ùe&L˜À´iÓŽj¬h4Êâŋ㟽×ê㩱7 ÙðÆ||ó3ƒ[¡!Ž3)Ýœ£:EæŸišØ¬tô¤RåTü1ƒO¾¾Š,¿šSD¡ÙE4A×C( èÁ¤cL²Ý.²\¶µ‹êäçyzˆŠ…BÄûÊ …ištvvâóùâ·ƒ-­üå©Åä-8›ù„ÀZbüñHG 4ÛúŽMì#¨(¨½Û“x Ð%›²÷ ¢$z2&ã} Iÿ¼OD_Ãt<Ó®à¿?ÀÄ c=z4õõõ¼òÚ›,y{%¾ Žâ·ރÅíÅê®Å6þ\P56ubõÚôeo¡Û0ü‡ÐŒv‹‚ËnåšËrñ S¾—‘À¡BdŽiš,ÙPGVV.—‹@ €ßï'àtRÈÆ4 ¨0ÑühªŠÏçCQjkk‰F£<÷ÜsL:•)S¦ i¼wß}—öövìv;~œì2*˜Þ¹’ˆê䙣±Û¥jNˆL’Àa™¦yÜpÔÞ•™ûÞàÛ¬bzÏ Û‡}êº#ÜðjgeñÃ),vbá 1]G³:@Ñe š&äyr0 æ–C8=o²¥TY!D:>ŸíÛ·³fÃfÖoÞFGW€pÌD7@µ»QìnL« Ãâ›ÏÜOU NœâÏ9çß½‡qգؽ¿ÝYˆZ:•¬Y·âÑÿ6Õ–S€-§ åc‘H?¿¹’?+¶Ö³yû.<^¯ǃÓé$ôÞ\Ôr±˜”Òˆª·`Ñ4š››Q…ššO>ù$gžy&“'ON;–®ë,^¼8þ¹{>Žq¶ƒt-hÝÜõùœ¨§-ÄiC‡¤iZÚÀáŽ}MìmhaÆÄÑäf§=‡Br©²ÕjÁè ò¥+UNgåÁn®x­›ëF{ø\•†ÒuˆhÈßSúlwN@ÌÏÍAÁ¤¾é N»d !„èÑÐÐÀK¯¼Î’wWáF‰ÙÜ(žJ,¹•¸&ÞˆÍbC^5ÄÑÐngÞBª’UŸ±óª6'žÚùP;ŸÖ®CÜû·ÅðËß1ûŒ)|ôÆë¨­­ÍØXBq4¾ñoðç?ÿ™îîîc:¾££#Ã3:zõÍ<úÂ6íkEEuw`¶ùhí(§»£_n>ÇÏ@ øNö ±SO‰Ñ„‹¡i@Ó4&L˜@kk+=öóçÏOù·zíÚµ´´´`·Û šv¶é£˜Ô¹¿®qù¼¬Vë\!Nm8Ì ›Í_\d ·×ï ½ÓÏöýM|äòs)ÌÍIy%!ã°§TÙJ4ë9¿vlYOíõñÔ^øRmWæл; ºÐ ‹Í FhÐ11Ý`Ty ­Ûßf[¾ƒšÙçƒ"ké!Ä©hË–-)·›¦Éºuëxö߯²qëbŽÔòédÍþY‡É°Ò«UbI²¦¢ªƒ{'žGQÕx9±9 ô·/‹ÑPú›xlü~±I%ÌéæŸ¦×_âX}½{ &ͱw²çÐÒìŸ<¼™t?éçÙ›‰¿•tÏ)±³™°—¡§é}˜nn)·=›gxˆmÙyØÎ¸ €u÷²êÞßsÏOÉ=ß»›âââ¤}% („n­­­twwsÏ=÷ðÑ~ô¨w»ÝÃ0«¡‰D"üà¾Gxé½½èªüŠ›ˆZ‰Óp0ªm+†o7]¾rüÞJ:s âD§Ó™…èb_ œ,e…zÃ@QvíÚ…Õj¥¦¦†}ûö±bÅ .¹ä&L˜ô¼¾þúëñ×Ô ÆXFYZi™”8ƒ|ós7صâT&à ²Û˜2pèv9ðu1 “7WmáC—ž“ö<‡zïyëq–Aß¿å¨ðé%LÖZуÂ. 4›S :¦»;Àkÿ~†5ï.áì—1zòœãšƒBˆ“_CCxèï¬Ý¼¥ {åLÜ\6ÒÓ⸹‹FCÑh‚¾>{ÇrÍÅsùäÇ?:¤t„"“òóóãý]ßþþô«<øô2:"Vüª—F­‚ ê&G‹`%FØâa¿1•âÀÆÜŒêkDﬤË[‰ÏãÅëõ’›››”p¹ØÓ]‰WÝ'܈ͦ ë:7nÄn·3uêT6oÞÌÒ¥K¹úê« ‡Ã466b³Ùˆ`e³>†q¾¥¢1®¿|‹„7„òÿ¬ ²Ùm@êŒÃéFÓÔê ¡¥ƒHLÇaœF­)jRæ‚Íf!`Í@ŸnÀw×"Çb忦•QØÝ„öwb**ªf´€ @kkO?öÊÊ^aþe×Sƒi]¯cíZC´£`î(|Þ"|>^¯—‚‚‚¤ìÀ;‡Ž®6 ƒ»°ê±Û­„B!–-[†Ûí&`³Ùˆba£1–ª¶%ø¢>zù‚ã^¤T‘ž3¨oÙ÷ÄÞA‰®œ?“Úê lV —Ó‘rESPSQ0MEQâ=‡,Ãð·powŒO­1'¿œ/–„Ñ[УáÞ˜í½ý“/ ²uËV¶nùO¦Ÿ1ƒùW}·wxû !„8~‰½ u]ç¯<ÎSÿ~ {ÍÅx~ý°Ç&õ5áË1Ó41zûªªï7¨ 8OüܪŠÚ»]Mè ý=õÔžI žd⇆4}ù’ŽKÓÇ/éÌiJX•T¯õ{/&œ#^M¦G¡bšÉ={÷Szß <§™fÿÄNz€Ic%×WM\„-aûÀ>‹Ç°ûûŽÅ™Eî¼Oñ^Ý&fœ{!?þöÔÖN”~‡BˆÓÖý]Ä£¯®£K·âS iTË)ÍËâÆ* N%B8 ¡(ä8m|êÂñØ,*6Må@K'¯­ÛÇÖý-™-xÌVvfŸ±njºÞÅèl!ÚQF oyID¿ßß“}ètÒÈ#êk¢8¼ 5Ò†Ýn'Ä_·cÈWº¨k>Du¯ßöá¾bBœÚ$p˜Av‡ÓLÝã°Ï¸ª’ÞCE‰7Œïû°‰õ¼ñ×MUÐÌ¿=·-Ì»mp]ùX®Îj£»­™h(@,Ãêtc00€h&«V®díê÷8{î<λâÃXYŸ›BˆÌú÷˯ð‡¿<Ž:ú\ò/>|ÀPˆÓ…»b2FQ5ßüñϹçîÛ%p(„8í,]¹–Ÿ<ôû;tÂj6 ZÎì\n¬õPä2 …B„ÃýûyL•ÿyL‰‡ùS+©oíâõµ{yaÅvÊ‚{ñ›Öå^AI`…‡6éµB 3 fÝnÇ4ãJ“VU%žmÑ—¡¡÷þWSzz ê .!Δ§êƒ<…‹/V×2-°n_;¡îNbºÝ•…©^9‰òÚâWxwùR.Xxg-¼Õj¶9 !„86kÖ®åç¿yP^ 9~%ÅJÆBœÎT›“‚ ¿Èwr?eeåÌŸwÞHOI!†]KÛ!¾ý«GXµ«…¨ê¢ÙZAqi%¹ª”ÚB+ :1v4Yº½5<ÜÙÔÉ‹ïíåòY£“ÎW^Í- §råœñ<ôò^[½‹ŠÀ|j.õE72±s)fãf"Dr«èô–Ƴ=O<€è÷û 84*°vì&/´íѲ” »÷`b©›Û?yÓ‰¿`Bœf$p˜A6»ÓôWàP1Aí-iê;®÷,Ž¢) ž /S~»;„U)æ®ê2ò[v û» vu`˜ôd ÆbƒŽéê°è_ÿàÍW_âòk>Ä´yÒT_!FBKKKÒÏ@€;îþ›šBäÌù96gúrÜ4%¾‰¯m‰åª‰Û÷Jüö¿¯VUµøþiK•ðø‘^Õe͇“Tú›.[!] sª]¥ÿÞêÃÍEðXâùÓ•'–-©¤ZIüÝ$<#Ý|«f¦$¼ù0õ„úÆ4Íä9¦9ÿû…b±Q°à |öÎñ_w}‘ùçÍMz¼°PÚ³!N †að“Ÿà™å[ð›YÊ9¨•1¥"›?ÞTŽÇÑÿ×=×eá¬1ÙL)wñÒúfÞÙÖÀ³+öÒÚÑÍÍ &£ ø°š›íàë7œÃgçwO¿Ëæ½M8­ìµ'V4“ÚÎ7XK´£€·ŠÎ΢xöab1t¹ðªEÔ´6ciÜÈ›†Éí7_yB¯—§+ fÃáDv8ìƒWL ESã‡} ¤èzÆ¡EUX2<\¢&ܳKÇk©æî*µn+¡P`g;&*V»3å Ìí>þòðŸù™…bD´¶¶Æï¯^½†{~öklÓ®Å{Ö¸”û§ X%í“&x”8L .ö—àÒT5¹pª`×  GþƬo¤þ~†1èñÒC™i‚ª©z/|¼o£÷õ¼÷ÔÁÙ㤠"&ëM¤T®AâùÍ‹Ÿ 'ñLŠ’ø…èàëj¦{NïcŠÅŠ÷¼Oq÷½¿áÎϵ1oî¹ñÇ$p(„8<ÿÚÛüê±Å4Tº•|´ j+rùô”lP-´ <ŽÁ• .›Æµ³JihëbgCxsS#­í>n˜7™ªbï cj* øÅ—®`ñ{;ùý3ï`tì!‚•YsÉËòQÒöAßAb¾rºs«èìÌÃÓ»³×ë¥0?Ÿbm7»6½‡Uµ2ÁáǨvò…ð\)!„3Èf·DyøÙ%œ3}ÓkF1;a ž€aOvF}éJsË€XJ¢ÓõdLê/˜°™¦¯aºbÜøuím3½c©iÎ(q»9`{ü±× ^ÞûóÀ}”4¥Ø‰åâFâ¸I¥Í©¯_â±zš’çS¢¨äÍ»•Ÿýö>¦L®eË–-ñÇdåe!ÄûÁ߽Ÿžy‹Cj MZçŒrpaµîP”µ{Q–[–ò5»<×Á>_ˆ6w …°©:·Í¯À‘ð^`l©—±¥^L«äO/­c˾xq=o­ßÅœ©ã8wò(ÜÎþ÷.»•{?w—þÇ‚:`bõíEéØÇº¼‰d™Îß4XM^A ïvM[ª¶’çͦ¬¬l¯˜"‘3Èn·c±Z¸bþL^_¹‰,§ƒ+ÏŸÅ»ëw²«î —œ;Ò‚Á=iª† IÃXïsUIÿn$,j3\Ùàë@QÕxÐÀér%í{É%—Û‹×…âtòðßeÑ’µä-øœD¯B¼ß)ª†sæÜýƒ{øÝ/:ÒÓBˆ!Y¿e'?~ðIv м4XÊSœÃ“·Táuõò‚5;›)+ðPâMN ë°¯=B–C#Ûj¥±-Dg0š8ìSQÍ7Ìá?x…ö®«÷u²r÷JþïÅ÷8«¦ŒyÓ«ÉÍvGhíèF øJ¢5­¥ËšÅÖ1—p†k9n%Hß×x…j'×d­ãÃühƯ•"= fÍf#аlÃæLíÉ8|yùzΜ2UQxrñ ¦Œ«ä¼™±ZRgk(ŠŠªöÜ Ãè)UîÍPsDK•SêÍBP°Zû„q:œ#5#!„8íèºÎ×îúk rÏýøBG^­M•<þ'¹éÆëGz:B‘–ßàÛ¿ü omn$¨ºi²TÓ¥y©²â{U$ œ6™ãŠiíŽðïmä8ñ¸¬´‡U¢1ƒ+j³ð8z¾Ô"ö4wÒÚÞEmUARE@W Lt@@°3å¥÷vóâŠ(ÄtHT'f¤Éåùp´o'šW„¦¶±Ð¶ ݶ—ÑÅg>ýI¦Nšú8!İÀaÙív, WÌ›Ák+z2¯˜?ƒwÖïÄ4M®œ?“5[÷ò×g—rÑÙSS^4蚦€ÙS¦¥iZOyPopNƒYåpL£/29ãÐát¤;D!ÄqøýþøÏÝÝÝÜúÙ/ã+:Ï´ÁÂÓ½l(iÊ–“Új$nO³ÿPÆŠ?®ªiM§¯Ä6©7qåÞĹ ø9帉'›X¦›æ¹©œ9aŽ}G¦]9q{šUš1ÍÔeȤ¼–iJž®Úœr>éæ™rôþñ×ZpÒû~•=é"}öwœwîÊËËGz:B1Èoÿ¶ˆG_YÏpÒf© M+anYŒé…šÚañê=L®ÌÇaœÈRe£4×ÅŠº(v»†Ónáêñ*vKÿ«‚¦*Œ+õ &«w4ÒÒ©,ÈÆ4M¶Õµ±aÏA.š1†Úª|:ºCl?Ы«wáê˜@L7ÑõÔmF çón~i9…¹Yt„ü¼±y=·\yyy\zéÇ;vìp]:!D8Ì ›ÍF0á•·7rÎôñøº¼¼|gN‹‚ÂKË×3mBÇ”óï·Ö3¦¼ˆgMÂiïÿÆÇ¢j ö—* Ì“ªTÀÔc¨š–8t¸Ò"„â8øý~Z[[èêêâ¶/~eêu¸‹FÕy†8LÚžÐÛîHÁ¿Ãy¤×±¡œ´¿ßaâö4H†rî´{¤ :&Í%¡×`Rð/!è™´=>ÝAÄAÒAcõ›xžtû§¹I§L¸ŸÔ 2M/þ}LÓŒ_S-P˜JöÙ7óÍïÝÃ_ÿxÿHOE!â–­\Ïÿ<ô,{Ûct[ iÐ*˜U¦ñï[Æã²÷W†ùüa^^¹òB3Æ—&}YŽ™ln R”e'×­Òƒ½í1j ­ƒÆÓT…YÊøÙSkxä­†ÇmåG›G–£ÿ‹fŒáà ¦òпWóÒŠm®;nŽÛI~AšÍE¨½ŽŽ½ Ç,Üu×]IÕmBˆK‡d·ÛQU•ËçÍàµÉq;¹rþ,Þ^¿Ó4¹|Þ ÖnÝËîº.9w:Û÷5ò—g–rÁ™“¨­îùÖZÕTÔ‹£¨ ™']Æ¡ÞWF­$íÉ8Bˆáä÷ûùÌíw M¿GAÅHOGˆÓ†ÕåÁ_5—_Ý÷þî7#=!Äi®¥íßùåßxoW‹‡[ÝJn×v¾sÉIACÛÎÕskÙÓÜÅož[Oy¡‡"¯›–îV«•ë§ç'eúB*öbtqÙŽäðÁA_ˆ†Cݘô|qT–—•4ì“›íäë7ÎeT±‡ûŸZ>èq»EÅ[‡Ýé&Òµu mÝ"¦7G¿À¦"³$p˜A6›P8Êâwú3_yggM‡iš,~g#Ó&T‘“åâõ›7ª„‹ÎžÊÒÕ[Ù¾¯‰KΆ¦Y01ã«Jš¦ÿH= 3ÞŒÃë* !„Èœ`0Èg¿ü(S®• ¡#À=zKßz˜ 6H¯-!ĈùÓãÏó§çß¡‹,š­ch#GûòCõØmVžxm-ß¼yö ™Œ)Φ¦²·vÂÖÁf³ñ¹ó “‚†‡ÆÔQyìo ²lû! ²¬XTØÕèãPwˆçŽgRe.‘˜ÁîÆvÞÚ°—Ù+SŽ9kByR濦(x<9¸Ü."XñXCG{;!Å…¡©‹a±X’Û¨!N8 fÝnGQ®˜?ƒWÞÞ€7ÛÅófòöúí((\9&«·ìaw] Ÿ;m{X¶fófÕÒØÒΛïmESL³¿TYQ”x–¡ÂÉ·8ŠÞ[¾4pUe»,Ž"„Ã"óù¯ÜY{ ®‚QñíjB‰¯’¦Ü8Ý+HârKB)Pßâ\µZÿöAI,ÙM(©=œTå»)NŒ÷S©³{Ƶ|õÎïpÿ/~BAA………#=%!ÄiäïO¾ÈƒÏ¾C»’Ç^­ÃWÏìœý\uùDôðöæ,ß|€{þü<×/˜ÉŒ É_4¶w‡Y»·Ñ…Yä¸í´v¬ÚëãÂÚ¼¤òå>UùN67…xeó!Âá0n‹Éí—×à´õ¿'(ôô|ܼ·‰`8ÆøÊBr\v"1-ûò»EoÇ_×\v+n·]µlÙI°µŽ€–nÍX,~ÎñU%I¯CBˆO‡d·ÛñuvQ]QÌ'¯Íç­5Ûxiù:æLiš¼´|=gÔŒ&ËíˆgΛU˲ÕÛ(-ôrÁ™“xêùúž`aB©râJí$«Uîû`aÑ´¤öI6»}„f$„§®P(ÄG>ùY¢ã¯ÀY4êÈ!†Õå¡ÑõõõŒôt„§™?>»œâ¤Q+'Ú´[ÛfJÏ™ÂMÍDS‚á(_¼ŽVì`çËWžÏ¸ŠB ½Yìoõ“›ãâŽLƪõáÔÜaɦFj*ò)õ&žëì:@QzÚgEb±´ís'.aOSŸÿÅÓäg;ñuië Űi ·4¡îvôæ÷ð+Nt[. è©›m3ùÖ—?™ñk'„8:8Ì ÒÒR4wüåŸ|ꦫ¸èì©ÔŽ­à•åëÑ4-žq¸«î —Ì=ƒ­{êy{ÝæÏ®¥¾ùËVoë š‡½$¦‰å$ ½Ü5M¥ÿEÇ!‡B‘qùÄgV_†Ó[6ÒSBÎÚ‹ùÍïÿÄû둞Šâ4ÒÑÑÁî-ëñŽŸƒÓ âï¬àÕ÷¶ó½ß=Ég¯¿€Ñ¥ùÜvål̨æÇ_ÂΦ.ö c³Ùp;ü¿…“’‚†Å96Ц”±µ)È{›:)ñº°k&õí!"1˦äQ™kGUÚ¼·£‘QŪ sÍÑjQ1ÑØßÒ…®ë(¸64ÍJ(Ãl\GD‡˜=Eד² Á¤8ÇÆ/¿ûU®¾ââá¼”Bˆ!Àa)ŠÂ÷x;vìàûߺ“«/<‹sΚɭ×^À;ëwòÒۘїq¸r3ã«J˜?»¬?ãð¬)<ýb X¥/ËP‰…øýŹ{ÉN–îoÁñzÓìÉ8TU %!¨iµIÆ¡B@ €ßïÿü³_ÞÇn£˜ì¢jŒhè)£—''”'– eõä¤û‰û$”$'óH+#÷ –æÁÁÛS•D$såµéJ¥S•?'žÏìÙp?6åÊËVXVR”k'퓾Íívãr¹Nà,„§£®–Ø‹ÆP’jY%¾ºž÷ ‹×ìeËþpáìZæÍOŽÛI±×ÍþÖþ÷QÝàõu\:kÔ ¿» P[âd·…>h4Šª+Ü0̓#¡ÿaU›ª7‡ºYüÞNŠrsUì!‰±u+ϼ½p4†‚‰USЬ¦…ØÁm¡. g~O†aRÀìjŒk/˜Îƒ?ý6›m¸.Ÿâ(HàpŒ?žGÿ¹ˆ¿>ü?üùƒÜ~ë œ7s"µÕå¼´|=¡º(—œ;=žqxþìIÔ5·±|ív4Mëé ”°8JUy)›¶ïaâØ*ÊU?]PÁ›-¥|oÙNtŽà*S†AßÛsMÓ’2eUe!„8>~¿ŸÖÖV–.[΢7×7÷ã‘P°IQâ_Ú(ô•”4ÀÄí‰m0ÒÕ„}†Ò+ñˆú*楦ˆ¥•.4”äÀ ^ªÓ¤9R?À”Ã÷ÿÏx>Ã0úKìÿhšñù›‰çOØž´ÿ€Àž™€L!1Ô›4·4û§ë™d³0Ó0ýßJ3]`ô$a°_Þ÷wÝñÕø6  !†[·– ÛWá.C~ÅDòªÇÑÖá#좥+ÊSomå…•»±Ûmh+åE^Šss¨oïùü¸xC-í>.œQMy~VÒ¹›ºb´øul6 ŠÁ¨Ž?là° î5Xš—EŽkß~x)þ@˜nŠÄÐõš©£ªSì„} (]à.B±8•%cD9cL!¿û¯;™0®zØ®›âèIàp}ì·rÕÕ×ðýo}“êR7\u1½jk¶ìañ;¨]ïqXVèeþìI<ÿrJB©2@^n.^‡M;öR˜çÅ›íä<ÎóWMà÷›ñð¦zº£úf“yšiÄßÈ«šŠªöÿs²IÆ¡BdD]]ÿóÛÿ£à¢/ôT„)¸KÇñÎâƒ8ÒªEqâøÕôöVèz­x%%„b9ø»º€ž/ª 4à WΤ¶ª€pTç­­M¼²¾Í1ö½¶ŠB£Š=¸V»t\;U;)ÊR0M-~Íuä9j+sU t£è†ID]7ÑÐÑõº¢°vlÅêÈÁôVô,²eôgêzŒâ,o}þÓ|èšËOèõB ¬k>ÌrssùÍଅ×r×ý†Ý»v1{òX>yíü¡H<ãÐé°³|ívTÍ‚aô|£ßwë[,eJM59Ùn–®Ú„n˜Øc~¾<ÎÆ“—OdniÎ _qÙ–³ ©‹%~³Ú%ãP!ŽW0äëwÿïyŸDÑä»>!NV–qóøûcOŒô4„§ UUãU¦æ dËÇlßC÷žUÄÂ!ò¼ÙØÝž¤ŒñûžYɶ-Ø­N-çÛןÁ„ÒÂØ8àÓY±·›·vû D.ç¢4[ESÀ¢Bi¶Æ¼š|¼Ùn^\¹‡···°÷`7»›»xiõ>î{n-p Å40¢‘AÌÖ¸‚M8ò«PíYƒž‡Õrëåg²æÅ‡%h(ÄIL>…œ sçžÇYg=ÅÏÿç¿yáwùÂÇoàC—žÃæ]u¼±j E¹œæ$^xù Š’\ªÜwó<üij誓«oº•î†íø5Qªvsÿœ–*àžUhDOÈs²©ý‹4­'pØÇj•ŒC!„8Z---ñòd€oÿð^´©×asyR–áö¼V¨ý÷{·[JŒÍ4ýéÔ4å§éJ’­–ÔoRõ;4ÓTsOy¶dIÅ©‰e±Ï×ûXR îz,¦+I&MÙtÚ2à#”''ÎWKsî¤ç7ྙøüR”K›ŠoH× ÅÜÞ%–¥9Oß¿Ó4“ʯã÷URþn0MúŽPµÿy اÿ®‰a¾[bºkŸnŸLË=ƒ^ù_nûä'†q!„è‘““CYQ ­¾ø¶˜Í‹j³áhÝHÈîÅR4‹ÅAÌìù[}¨+Ì/ž\ɼI%Ì;cU…YÜ2o ÷>½%éÜþ°NDgŠ£ò\;®)•Üÿò.ü‘H„@0D4! Ž„ êÚÿgï¼ã£(ó?þž™ÝMÙM#…@B $”¡wEi¢(ŠbálwXÎîÙ°7ôg;ÅîåÄ.<ÏrvéHï„^ÒËîfëÌïÍnf“Ýd„ExÞ¼æÅfæû<ó’ÍîgžÏ÷©Þ‹Eu`Jï€×ëõ2Ô¡ºíôÏkËëO>MRRã‰UÁ±…"F£‘»î}€¢¢"¼÷NÎ5˜SNBç™ÌY²Ž…¿oAV|e½U4¾Ÿ»ïæ-åþ‡£sg_Ís·$T–ppÛ*ìÖj†X¼Ì™Å;Û­|¸µ«§¥%É[x<º’çF£E÷¥Ò$j ÁañóÜyìrXHj›íTAÈéùlÙ²…´´´h§"NîýÛEÜùÌL~åÓÚk‘‹WaÉ$6% ðx5j=0wc9‹ŠVÐ69Ńª+„N/|õûA†æ%Ó¡Mãïtµ./ªæ³A«n¶êj ¯­ŠxÇA,™PQð4˜øÄãv’i‘xìþ›6¨ß‘>% •Vå(››ËÛ|‚š˜Í½¿ˆ½¦‚³Gàô“úbP ¨š°'o/ÚÉÍ÷?EB»|Þz÷Àhè'>9ÜcÉÌ-@V ˜<6þš 3OnÏà””Vt/›u7´*+1–@ *V«•—Þ|ŸÄÞgF;@!JÛüøËüh§!N®œ2‘YÏN#'=¯Ú Þ½lÀ˜Ú‰ Ë7a³Yñz\Øìµx=T Êl^*k}Â^·vþ62›ÉÒèÞ6–jÍÌÜ~ÞPƦ¥6/û«Ü,Ú^Åìeðx5T·“ò’ƒ”•WQesSµ¶™äœ$%ø» ªz1¸ª¸ñüSøù£—…h(üÁ#£È^ÌãÏâÁ{¦Ñ93‘‹'…,˨^•êêj^™9‹¸¤4^Ÿù11M[Ss HÊÌeφ%”ìßM[jxªOzi:KV®åî¼I±µ6X@”$³ H—½ܵ•=¶Ü^ kM5²³0™ÒùmÊú’ýäe&dŽÁîöɵÖ*Ö­]Kie n§ö&+í{ô@SL8ôß.Ý.'г‚û§Nd¸QGù,‚Ö@‡ÇŠ¢0ýÑÇ«_çüˆÁëÄ`عéwöíÜFÏ>ýi›OºVÃC]VÔxy›Ríð.lN(IR£?J²†.-æÞGÇÔ{"’,ÞC‚?"¦ö=ønÎ|! ‚¨1¸_/~zÿz÷SÞüÏ\%=ø»š1žɶ•°c×nöÔ¤âØºÄÒr’ÓHOOÇeÐpî·±¿¤Œâý{±–ÄîRi+Wй[æÔö8Ž:ѰkéÆëÉ=7?x”Z ´&B8<ÎX¾pmRñxAxJJJ(--eß¾},ß´›ÔãÅȲ¨1(éêY’ †@í ½mSÿ 'è½YoWÕ×5Ôí7¨¢½-4‚Ú‡!×6¨á°b‡ûûÎ>¬ë¿ÅÕpù6±¯P1þó§iªª6ÊEÓ]3ôõÃXsƒêûiZX›¸þ>•³ÂVìï3AçO_S·ZoD“ôÿûíó²\¿/M«·SëŽ[Ö]ï†yúQU5‚ë ’ÜO¡úözÃø-§C ¶M{Ö/üïaö"‡Ï5—žÏÔ‹Ïå¶é/²hÓ^2Ûçmm“MïÌÎtܳ‰í{KØ¿ßAee{vlEEAÆ‹¦ê°’eñÒ»c&YÝNÂét6 «JŸǬ7Ãl6ÍÃG!G”—•a«,Á¯Ýx<œÕ%,Zx¶òÉëУÇÎä4•)q¼¶ÃÁ 5D¡ò¦0ɾ×JÝLÊ~$Å( ß A ù¿g^ÄÒçœh§!“ZÕˆÍf_žAÔ1 <ÿðßÙ±{/w>ù:eV#íÚµŠÉÈëM‡1¸+÷²wÏ*k=Èx™ds :õ$©mÇ# kª*PjK™qÇŸéÛ«ÇÑ<4@pÂáqÄ_}FûŒ” ÁÐh4DDÇCå,9¸Žy]IµIÓj˜ÖQf•Mâͽ^* ‘ðŽ‘ê„C9xÄ¡l0…YS Ù¸i{­mÓ£Š@ 8\Òº±lÙ2N=õÔhg"têÅÇ/=ÄßÎå_ŸýHBFGbbb‚b,m;Ó;§€˜˜L&111¨ªR0t»]ؾ–Écqéä[Žæ¡‚( „ÃãˆÊâ=$ÅÅ… Ýn7^¯7ðzÏÖuì‰KaXÿ^T–—ÒËèàñܾ*­áÇNCL³û3Õ ‡%xÄ¡Ádlµc‚ã I’xbÆ+$ö½8ì̳’nöä [oƒ×rÃØ afLÖϼ¬_¯Ÿq7¢YŠÃØ–C>Jjø€É ãüý„y 4q¸¼ÂY’#™%9(•Ðp}|¸R#™Çþ IDATšî8BÙ†5I ¼n4qÖéÀù‰Ä†nVì¬æA³xûµÍZÒSàþÔÙ–%YOû·ª;ͧ°g(ÌïB8w$ç 9”Ä ¶ïÚ‹ Á±ÆÄ3FrÎé§òøËoóëš ä¶¸›×Òµm/¿ú°(O%œ áð`ïžÝ¼óú‹ >б§?¤>þò3mÛX%‚Æ–e½¨hIÏäŒ)׳~éÖ,]€ÑaçœD•¡æ8ÞÙog›’ˆÚDþ˜ºÏâŠÑˆÑX/ŒB8‚H™7>ÕÆ Râ€àºuAa݇sY÷:H°jïG_: {­BÂ Š‘$ºèÛ‰‘çšÖ¤` ±p[4lÛp¹7#ªJ:Ѭa®ú‡Á»m\ðˆÑ Vb`µ^@««É¨ÏÂ_× aY8M\3ô÷s¡S.ݹñ·Õ4-¸Îc]ŒJÂÔ>Ô_|ɾ¾ä¡`ŒOä@ñ®Cj+­$IÜsÃTVUq×ÓoRì£k·‚fÛíݵµr/Mû Â!!œHá0ŠhšÆû3_§f×.QÀÚm yìÞï™2õFr;wnQ_wo&%)±Y±Ð¿Øk y’$Ñsðh:ôgÉO_P´e©Z 7eʬµ{x¯Ìˆ->9ä> uÓŽ8 šµK Mòô ¯‘Ø÷ÏÑNC !ŒñIo/v@Ð$ÉIIüóÑ[Y²r-¯|ô-Zl2= û6ŠÛ²a µû¹øô!Œx‹I&>>6È–¬.šÑ€ÁC}˜’uîåtݾßÿ‡òÒb îokâ»r;óÕdÜ1Á¹ýVe£1تnN@ ±jÕ*l1m±›/!þȦ8ªj¬ÑNC "bp¿^ î׋¢]{x}Ö7ìwƒ™8“B‚î¸hkL²¼‘ËÏÌø¡Ý±Ú¼8ý6òûžÌ¤ ›‰²vù|:´Ïˆ†þÑ…¡êúþ÷`7†$³:pþÕÝX1ï,_ø3†Z;gXTª.f•ÙßMñÝ6FÉg)26˜UYX• iJJJ(--åŽûÁÔùŒ1’,!ûËEhª×ë{­(ø ÇŠ¢Þµº8£näw¸úCJ¸ºD‘ÔýkP‹1RôuѽÖXBýµíš²;‡´þŽ=:‹ª¾w½Ý7(ÿ1écäØ\M½Fkôb½µ9”µ8ŒÝ8¬U9Œ Ùãñ^«ºx9̵×ï?TŽAödÝq¨š~»tq©á¹ÐÕP 䨳ä{ý¿7Pÿ;Ô {EÑÛÎ5]¼ÎÁí kž‚c’Üœlþ£†@ 8ÕL"«V,ç©ûnfx–—.Ù)Ü÷¯oØa%·k:w) ±cþñÉbfÏY‰9.†KÆö&ÓµG¦ÝÀï+–‡ïØã$..ޏ¸8âãã- ·ÙÝO<ó"cÆŒaÛ¶mº“e™#ÏbÊõ÷Ò¹[ORÔj®J.çbu¦Š€†¢ù>+u#ý‹Ñ „C@ hŽÊÊJv—Z1YR¢Š@ 8Âx¼B8@p| „ã€Óéäåggó¼¹tL>ýy%ÿþa…CG‘˜”Ć ¨­­Å`0Э÷@Ê”Lyû'–­ßA§öiLדs?ä©G¬¬Qÿy…CØ_áý¯C‰‰û*j±X,lÞ¼™áÇóí·ß†Ì;!© g_r=ºì:’Û¤×CW¹’Û’ŠR¹{u5PoU‡bVe@ h–¿óÆ|1ïª@p<âöF2.Q hžë®»Ž>ø€Õ«W³nݺh§#‚aUneþ:—ùß~ʹÃò)©ð0}æ´ÏïM¼TΖ-[ÈÏÏ'55•;wâv»ÉËË#!1‰n}‡ó˶ÌYù3Wœ9}òp{<¼ûÜ$uèÉeS¯ Ì”Ù17ìœN,žû=™I&Ìññ[rC»rye å5.rss©®®føðáŒ;¶ÉcèÔ­7½½' ¿ŸÍos¿Ç[kgL¬ O¥ŒJc«²¢áP šÂãñðëâ•´9­N8ôÛ-©·‹J:+¥,Ë˱$Ë»¨$I¶²®9ŒýToáÔ›Bõ3/-|¹ë^ûÑZøT3{²ÞÒÒ^ÛTŸ‡8³n£þš›ñ¹AŽáöÚÒY¯›k§^YÜu¹©ºY˜¥Àæà™‹õt-”EZÓêïsMC q¾Ú¬ÃZ±›¹>úßômý15Ø—þXš£¡Í¾¾O·ÛÝl{ )6oÞÌwß}‡Åb!''‡²²2zöìí´@p‚!„ÃVÂjµòÆ‹OÓ%ÅË”Q=xÿ»¥l8PK¬%£ÉDÇŽñx”ø×h—úº†ºøPBm€§¿‡uõ ƒE*IR@(Ö÷£5¨eجp¨?>]-àãÐç¬ï'LíÃð÷qóõå¸DÊÊÊh×®]˜ yTUEUU<.—+ÚéàEX•[þ÷o] zÓ©S'–.]ÊŽ;0 tïÞ¸¸86lØ€ÃáúÙjµ"I]zôANïÆcïÏã‡ÅëÉh“Ä_Æbßò Ý{+»vîì» gºö?…µ;JPQ‚,Ê11±Ä&µ¥sçÎL™2…K/½´Å#’SÓ¹èoÓ˜rõ­¤¤¦`4úFƘiÓ©¸ñ!Y šâ£Ù_aÉí4A+!c±ÙlÑNCpœq¨#Ž@ 8ĈÃ#HII ïüsý²b˜|jk·îáoW3ô䑱ÿ~†ŽªªlÙ²…„„233INNf÷îÝìÛ·üüüF?ÇÆÆÒ­Ï6•³øí¹pT!}»fÓ§‹Æ×ïÌÀŸÉÔën Ô4g¯£š”1cºàÈ">o  «ò$=µ Oš€Ë’Ã?­Áåö0z`wî¾ød(ÛÌÒß~Åãñ0tèPL&‡¬¬,ºvíÊþýûYµj’$Ñ­[7, 6lÀn·DC=󺒖ןg>]¬–c‰å²q½Iµoæ‘i7²fõ臘¥sêøóX½£sRê õˆ1@9_}?sǾÑNC ´"²¦FeÒ!@p”ðzѪ«!¨FjómiÂ-Ï!¶k­¶Í^{h¹´¸MèT‡ŒªúÎ}Ksiɵòs(ÇÛ šÃf¥,,„pxéÊxVnÞOzZ*O>û¼|>o-ƒÂg eÚ…ÃðVì¢xÿ^’’’P…;v°bÅ $I¢°°íÛ·³oß>)(( ººšÍ›72÷£( Ý{¤:&‹éoÿÌâµÛÉËNg긬úî=žž~Œ>ý,Ú´is´O‰@ t¸\.Êj\(Ƙh§"Zƒ">b Ž<âaý±ƒóéì5ïÆÍMº\Ô>û<5gO¢²{*û Â3a³ý«;vb¿ÿajΙDE÷ÞTô¡úÌsq¾9óˆˆYÕ§…íÊ¿Eëúâ+l×ÞDe¿¡Tt+¤zÜœ~^ÌÔ4œ³>¥æœITô¡¢k/ªGŽý¡GѪª;w×·?PÙkî…¿5ëþuÖ+®¢²Ï *{ô£fòœï~Ðt#‡Úgž£zŸ¨èÚ‹ª¡§`»îf¼›·vîÖ /¡fÒEG¤/àh!¬ÊG¤ädÆœ=™m›7°iÃJúôìJA~'¾Y²‚C-à ;sÛÅ#Y¼¶ˆOæÌ¥ ßPÌ ^¯—mÛ¶qðàAòóó±Z­lÚ´‰ÌÌL²²²PU•­[·²6aBb" }‡±pçnæ¬ü‰ËÇ`Tÿ<\no=s/m:rÙÔkÂÛß@pTøeÞ<¤v½¢†@ heŒb°¡@pü¢ª¸f}Ú|ØÞ½X¯¸ï&Ÿ¸(g¶E³ÚPÀõ߯᪫ ÁèdÏòX§þ ­Ü7Dn›f³ã]»ûÚu8?ùŒ„O?B²˜)}ÏÂE¨»v£äth6¶öñ§q¼ú@`Þ›°O»Ï⥘Ÿ{:¸×‹õò+qÏ›ïûYQââðnÛŽwÛv\ÿù/ ³g¡tÎ=¤Ü\³>‰(Îùï·±OÜ7ÒÐhDЉÁ³x©oY¾ó?C°¢UVa½êZ<‹—úŽ9%õÀA\_}ƒ{î/˜_œq̨CÎÝ»i3ž•«P ºrA4JR+×µ€1§p°ÖÈÁòÆŒB»¼B>˜»‘½% é•ËS7œ¹v7[×ÿŽ$ItíÚ³Ù̦M›Ð4nݺQ[[mصkW’’’Ø»woØý¶Ëê@Ç^Cyãû¼þÅ.UHaRN»žys:Z§@ !øâ?bîØÏ÷ƒ¦ê¢išTC |uèEAQdEñÕ‹“$YÆ`4b0ÛEA’e_½DÀ`0$)°Å×õñ"ËõK˜Y·­««Ý¨_õ£ï¿n‘#ÌM–dd)|^ús IróK¸c Ê­ñÒTúc7( EAQäúÅ ÿvƒ¢`0×Ì (Áç±îÞe¥n ¬kfñßK —pñJˆ%h»Á€Ñ¿˜L&L&F£1°Þ`0èÎAýb0û7êb ŠØ—¾>£¬ûÑ_§P9*ºón¨«Xt9è wÜAëë®_dzFaS´bÄa”ñxð,]†íÖixV­n6Üvû=x7mFéY@âÏß’´d>Ék—c>Ì×Ý¢Å8ÞœÔF-.Ázñåhå†#qî÷$-]@òºXþý/ä´4¼ë7b¿ÿ᧯–”àšý¶[n(¾vÆ 8^} )) Ë{o‘¼z9É+~#~úƒ ˸fÿ×çÿ jãxå_¸çÍGŠ‹#þчH^¶€äUK°üû_(½z¢•W`»þ––[¯½^<+Wa¿ÿaÜs~i>|{ö‡¯—¸»ï yÍr’W/Ãòú+`2…ÌÀñâ+x/En›AâW³I^µ”äå¿aštšÕ†íïw Õ¶Üâ­UTâúêl×ÜÐâ¶Á±€[‘“FžÆðñ°å@ H çœ>’ýN ï|·¯ÇËE§ àÆsúR¶m%{vn'11‘nݺQSSÖ-[HOO§K—.ìܹ“;w’@VVV“û”$‰.=zcÊìÁcïÿÊ7 Ö’™šÄÔ3zS¹î'»ï6öìÞ}”΀@ ˆÞC©á"8*ì+.G6ÅE; @Њx6¢†@ 8‚ØœNeïÔLº×ìÿ4ïþþG< "YÌXÞ~%?Ï·A–‘Û· Ä9g¾4Y“ó½Ð”ü<,3_«™'IÇŽ&þùàúìs´ÊÈl¿ÞmET›@Õ€áØn¹õÀÁfÛhN'ηÞIÂ2óuŒ§œ ))‰˜Ë/Á4qB =®/¿ÀtîÙÄ\ög¤ÔT01ŽMÜ´Û|ù¬[º+ò/RÙg05ÏÇùö{µq¾94 Óyç{íÕHñq`P0ž~ñÞëë÷Í·‚ÙjõY°ó«/ ô.@JmƒùéÿC)ì…VY…ë³æ¯¿µ¤„ê³Î£²ßŸÝy{QÄm‚c !¶2111œ>ñ":ö>™-{+h›Ö†ÓÇŒäç å|:w I–xnœ<‚3z¥°mõ"ª*+hß¾=yyy±oß>òòòhÛ¶-7n¤¬¬,âýôBQm"¼õŠö3 {.™Ç—o=ÍË3žÂáp´òÑ ‚£É¸~êŸÉÉlÃ+/ÎYU=víÚ…dNv •q×V“–*êJ ŽÖ®‹(w­ª uï¾@î¡úmˆûëÿ¡UVa4À~¶ÇÝy+qwÝŽaä)õ+½^¼[·úòœpfãÜO9)1Ѻm{D¹x·oM«?÷Íüh55¸>õ š1Nn´Ý4é<0™ð®ß°$¸>™fµ¢äåb8 ¸‘Á@Ìùç> tÄØkQwìD2›}ùlj‡Ç‚?&B8MÉí6Fj×Ö»ac`V]ƒ”€¡c±ðMŒâõ=ŽT„2ôï”{Ü=w6Û&0rpâÙ!·ËYYÄ^w ±Wþ¥~¥¢ t÷ÕîóÌ_Ð8õÕk|³!J·®å`~qFPþú›¡ðn/B«­E²X0 Ôh»‡qè`_¬N|õ¬[€qtè†Æ±£}m¶n—+¢ÜåŽ9A¹Ç?óDDí‚c !e =™ _M©+–»““bLnÏ›ÿûý¥UœsJoî¸`(5»VS´u#ñññtíÚ‡ÃÁ–-[HII¡{÷îìÛ·ÚÔWèØ¹ ]òìçËxÿÛ%$Xâ¸|\o*×ñð7°níšV}—OÉ=·ß$Fü4ï7Ìí»ù~Ð k‡AC1¤ùú¥ùv-ÙÐS¤95™oh1òp––ŠŽ-:¿G‘põ%õǪ¾4n^T #¬Õn¤þœ Ø‘ˆˆÍÔË [[2„h¨èj 6ù‚;ÌI-Èpû­ÏMw”maØ £UÁ …””€z°8lŒVSã‹)) ¬Kø|ÉëV¬À ñ,^ŒV]œ–†¡_Ÿ#˜q0êþý€OøBUñnÜ„ëãÏp¾ýžeËÑ b‰™t.ÎYŸâž¿00´wÛvÏ<ø„L9«}«å®—ørï †ÐõfåÜN€¯¦d£vuÛµÉÎ Ld£–”„ŒŽWĬÊQ@–eΘ8™Šò2æ|óqF#£†÷gÍÎ|³h—Þ—kÿt2EûJ˜õó"2}V匌 vìØ¢(äææ¶x¿Š¢Ð½pÖš™ù3cûuää¾ùtí˜Á_¿ÅןÇsõ·“œœÜ G-Ž^¯—wþýÏ>ñã:Ã#ã@Sñz½èË&ÆÊü¹G-kç½ÉÀŸòükï0fìØè%~‚³û` ÆNIÑNC ´2ZÕºv|4@)ÇÊÈgAó(]»øföxÍÞ  íÚ1ñÁª9¼Û‹°M»㸱Ðð¡ÐD+ö‰™’A¡æÂK‚,½rNÌÏ>…aðÀ õ1S¯@SUj}ë”ˑڤ ·iã¥ÇŒÂüÒs­–7Ô‹RrøÏ\þmzÑV-.nº$!%%¢•W —"73÷€@pôêÃÏß~ɾíëè‘׫½–·¾]EAv"cuçÔ~]x÷Û¥l·ÉävíI—.](++cË–-äääÓLP´Ëê€Ö>›·~^GªÉÉ_ÎÊ”1½ÙWRÎôi×3öœ‹8iÄ©­pÄ ¥Ì›7{ÿ~ y vî8%“[7Â0²”ûej\7 šó¾ø•ŠŠ Ú¶mÛÊ JJJ(--å·E‹ð&fG;£F«‰9–FÛ„È¥ÑM «¯UˆÑooÐQàDZÛJºÆúÚ†]úv^oýƒB½µWÓíKߦ{°(Õ Ñt¹išhë·ûsׯ×ï'Ôz}ª¦ö«ùíÐ [—£~»¬ëSÿ~©?VýÔ 3ª;²¢èV7>ï~¬û·rÞ)'QPP6F 8TĈÃ?r»Lâî¿û]÷á|÷Üßþ€Ò·7ZUî~ðÅtȆФ´Ô°ýx×®Ãþðc1—\Lü#†µà ´ÚÚÀLÏZU% ÌÄ0|X`{ì-7`»ê:Üsça»ãÿ÷E`›óý°ßÿ0RŒ‰¸;oõÍÆl¶à]»Çs/øŽeÍZâŸx4¢IZÿß&¼áÂhnOÝ Ýß:£Á÷7 ‰ÏÖ~±7ÔßnàxFŒ8<†}ÆÙLúËÍTyãq¸¼ôíÑ™j‰W>_DYµ•¿LÊÔ±ÝÙ½~1÷í!55•.]ºpðàAvìØqHû”$‰üÏêÅõO}ˆ¦i´OOâÊ3z³ù×Üø·¿Ùƒ-bõêÕœ5z(7^v.guv0©oq¦ÈŸù¤Å©LìâæŒÎ^â `hbt¢ õX»a3rbf´Ó­ŒZ¼‰±#GD; Áqœ9s‚ÄÂ5kÖ`µZ£˜‘ %Ä\| ¾Ò9µ¤÷?áY² )Þ7âÎ_çOn›Ñ¸±ÛMíSÏR}ö$<‹—"gea~áYâÿï‘V $‹ŒFß1\úç Ñ@Љ!þ‘ð®[ºwà«ûg¿çPU,ïþ›Ø®Eé]ˆ’—‹iâ¾úrÇ\³¿Àõù[/ÿTŸ«UV†ño“tÒ¥´´ºmUáÛUU7j'œáð#..Ž .¿š¦P^+k2Ñ¿Wæ®ÝÏ¿þó©Éîüóh†æÙ²j1v›œœ²²²Øºu+%‡P¨Õáp°}ÝRîŸzfàÃɶÝ%ü´l#±’»™Ö 5(**âÒóÏâöË'0¥k O]Ð Ÿ¯(eÍ[³íÍF•±9Ævt`R±¹Á]÷àUŒX8úlݾƒØd! Ç;Zåzôèí4Ç {öì¡OŸ>ÔÔÔ°lÙ2âââ˜?~´Ó´Ãða$Îýžäß—0û#’_‚ñôÓß ÊrJ«ª¢úœóq¼ô*’Á@Ü}w‘ôË÷˜Î =Ãqk g¤`:$ôöN‘R|¶]ÿ¬Ðž¹¿‚¦a:ÃÀÆDIæøÀ,ÌîŸæ´FÚ¾ÜÒ#}ÛüÇ ×üÔ**B7òz¶r};àD@X•Qr:uæ²ëîà·_ç°jѲÒRHONà­o'9Nbòè~ êÙ‰ÓÏWW IDAT\Ζ.ò z“ŸŸOee%ŒØ†x`ßn ¶ÜÙ uO¯>ø~¥UV²R-Ä¥4=ݽ@ 8²óèýw°|ÁO\sR ÙݲPUßÄ'}r,ôÊŠcó~_ü^NÛý²ƒmFY£j-¹;®N a¬ˆKÊ0æ…®™$äê^Kèì—GJì7@µ¥§£ÅmC]7M ô£…‰ gaF’‚ödÚ Ø¢Ãä+…ˆ%ØÊÉ1…zð éúo¿–¶ êÛ£·ù66ŠG·>È>¬{t¾ô–kÝú Ù—uVl5ÌÄúãðÏX­ª2šÇAŠ%»Ýxk6›‰oÝz^‚ã—/¿ü’Î;ãp8عs'š¦Ñ¯_¿h§Å×_MQQ ==üüüh§tÌ#µIÁÐ&XL Ì\ܹ~ÒKÍéÄzÅÕx×­G霋ùÕP ºÕ\Á'¾©{÷59ºQЉñ½—Ö•rðü¾ ¥s§ðýætðÅ._q¤RmœW¨§îÜ…æp„´D{7nöå“Ù¶Q;ï¦Í!ûõnÙêûû"ËB8œpˆ‡Ç8ÃFŒâª[DIíHµÝM—œ bãxiöB–®ßÉE§ 䦉})Þ²œ=;‹HNNŽH4Ô4Ík–Ó;]ã†É§b0(Øj<7ëW¼¤'ÅoiíCø&ÏxèžÛ9ó”þzWðää<:¶ ]Ô9/#–‰}ÛbâëµUÌßjÃãUé–dç¬ì2:™C‹†~ĈãÃÝô„S’,!5°‘KuB‹¦¦[# 'þE©…KKÛ†Þ©Xšl¯»þAmÜ ã ·å®û'ë]ß²,–°ùËr` ÄëÚJ²>_}ÞºX¹n ÊEÿsƒ}*u‹¦­}Œþw$äq4è3ø„ȰîßBaAìv;¥¥¥”––b³5?B\ G||<ÕÕÕ´k׎‘#GrÝu×E\Û¸5™>}:»wï&66–µk×F;cÏ﫱^úWl×Ý žÐ×L«¨Dn—‰qÄIu®OfãY¾9«= _}ÑÀ0t0žU«Cn×ÊÊQ@éée­äuÀ»m{Ø~Õ;}±¹¹acC¯žÈí2ÑœN<‹–4Ú®UVùDNIÂ8fT`½iÜXÜ¿ü²_÷Ïs|uë¬ÜÁ‰‚ÿ(ŠÂùSþÂWßF­œˆGÕèÚ1“mj˜ñÑ<.·\x*§÷Lbëªß¨¬hz¶e›Õʦó¹vBFòý1Z¸fïÿ´–üœ ,qFìNæŒ<¦ÞØŠ3v \.Ï?ó$'÷ïFê¾ïxù²î憨u‚vIF&&1¦3ìÜ{·­ ¯ªÒŒF%ˆ.qM‚ãK»|æ®ØÌ'³ÿíTÇ ªüÇC’¤cB8ô‹ãEEE˜L¦h§sL¢äçá^¸×Wßàüø“àºësÑ{ηß öÊ¿ YÌïO=p÷Üy¸çÎóMnr˜Ä\2dç¿ßAÝ ÑöÚ§Ÿ@éY}gäQéY´Ï’eÚhVŽ7ÞòŴͳtî¹óð®[ع£(˜.<çÌw=DuÎ|¼^Œ'÷MPS‡qô(äŒtÔ={qÿøs£Ü]@Ì” ƒ·••ןûêêÃÏ_ 8Âáˆôô ®¼i#μ˜*—‚9ÖH~Nÿ™¿žW>û•‚ÜöÜwùÚ)elZ½ ÇÓ¨=;¶AùVüë8ÒSÑ4™ÿ[A©ºvl‹¢ÈTÖªœ2a ¿w:qqqQ8RàøGUUÞ}û-÷ÊñòÞ¸²á=²Z40ÅäbhòF¤—òçB/Ë"k'F]Š‹‹‘ãS¢†@ he$ƒ‰6§^Ŭyyøÿžjröe ªˆ²,ãp8¢”MhÄ}ÉbLµÿƒÚ§gà]·÷·ß㞿ГšJÌeSm4‡#`“uüóuª†lrñ¬\hë™7ëeS±^65¤Ð×R䜘ƟŽfµR3áO¸>™w[žßc»þœÌY&þñGm”Â^Äüù"Ð4¬W\‰ã•á]»ïÖm¸fAõYç¢îÞƒÜ!›Ø® ÚŸ}Ú}X/›Jí³/vîàd¥¤$Ü?ÏÅ~ÿè»v£–”à|s&µ3^Y&æê©Á 1Wù&µÝt®o¾C³Úð¬Zío7àÝ^„’×ãØ1AÍ<«VÎ}8›³@ðGGÔ8üÒgÀ ú Ä—³?bÝÒù´MIÀérñÒ§óÉJµ0ylNìbæ×‹©ÒÌäæwÇëõ²eÍ2Μˠ…ì-®à»•{èž—‹,y)¯¨Á!'rÃÝ÷“œ"¾ä ­ÅW_}É#wßÂiÝâù÷Õ… ¼^oÄ£âÝÍɉ­¢¸….8ññþè³{÷n0§Gf7֡鬯Z»²¦iHÚvõì¥uèk¼Õ–kan‚Èhö¼F âk‘ônŸ=$ÐÕÕ”õµë_$]+}ý@ÿýÙ ¦ ÿ'IÓ‚kúë6Ì L=GÿC©ÎN*‡P(ºXY7*(O}-CÝkýû°þ÷H ÓÖÿÖh2a0ø>Vý‰õ[—0õº[xþ©G)-- --ôtQK7nl4𝼼œ•+W2~üø(eåC<€ŒŒ¸{§á]·ϲå8^|Ç‹¯ •{ÍÔÀ À@`vbõ`qó;p:l 0?ÿe\_~í¶iAÛ¤ä$â{CßÞAëã¸ÍåÂõéçÔ>ñjŸøGÐv¥gÌÏ>٢є‡‚ܾ ½CÍ”Ëq¾ó>ÎwÞ¯ßhP0ÏøÆSG4j{Í•h•U8^þ'¶¿Ýœ{×.X>|»ÕgµŽE„pøæì?]Ę3ÎჿLeÑ&²Ò¨¶9xúýŸÕ¯ ×MÁ¶=ÅÌúù7dIã¶É'‘`ö üzáF –T†õ+Àét°s y…Ã9}¹Q>*àøeÁ‚ÜsË5ô΄^Þs|\‹C/LÉRJpx´‹†‚è°gßTSb´ÓGsÇ~8,\qíßyæÑûèÔ©S´SüÁxíµ×èÛ·/»wïFÓ4vïÞMee%¿ÿþ{´S–÷g‚׋ܩcØ)6–„Ï>Ä5û?¸]€ºg/JÏü ?ý€d ®%/g¤“0뽈sPz^Fh+·ozrKããHèÖ)9t-í&æ—f`:ç,<ËWàYµ95¥°'¦óÏCñ DŠ‹ÃüÌ“Ä\úgÜßý€wÓf4› ¥k ýûaš8B<ÜŒŸñØk‘Ú4?xÅüòóàt¢ôhºþ£Ò³‰_ÎÆõýx—-G³Ù1 èqô©(½ ö‹›v†Áñ,Zì;æví0 êéÌñ!Ï™¡¿À¹Wºwk2'ã°¡$ÌzÉ,&Íü±Âáœøøx®¼á¶mÙÄì÷ß@–´Oµ°h]?-ßÌ_ÏÂ=—Õ§v¹=|æd¼n[v¤}~!çŒíô‚ã’;wòà7±qÍrNëÙ†¿ž1YÒ;oŠ4¹’Lm'ñÔb;ÁP5jl6cjØí¾ÙfuvNþ¯cþ™j¡ÝX?s¬„KôWµÑ×ó\ó ~tí‚lÂRh{ضºšªÕu¡³Õ7ÈÏ/0Hèì̺8ýñIš¾´‚¾ßº>ÃÙóõ¢F¸s)…±ùëíÉ„yÐãÿ}”5-pn šØ—WN ÍèëxéãÙ¼µˆûî¾½Qf³™øx1úDŒË墪ªŠššÚ·oOaa!ݺucçÎÑNM 'B8<Î5n<§ŒÇ{o¾Âúåóic1át¹ytæL>ÿOŒÌNeq9û+L¼ô:1ù‰@Ð ”––òØÓXùÛ^/Ã…½ŸôR}€_: ’þt£5°æK¡~}¨}júœuÂdP¾:Á/hT£¡‚„CÝì¦z±Pÿ¸'”è¨@%£±¾— ¯ª’<ä"~Þ0‡}7ÝÊ#ÜÓ(! âÔÕ¯3›Íõޱ÷îuÄ¡@ œHˆY•CEáò«oäï=G|z'\n•î=è‘ÛŽÍ»JHÌîɤK®¢¡@p„±ÙlL¿ÿ.Î9€±mvòù½§Ó»{g2’â¸êô /ÈäíŸ6óÕÒ]xÕÆ¶M8içXOGû \vŸhx$øv«Ä¿–Ѣю‚#ƒÕV‹bŒv ÊX F±©¶ ÷=ühóÁ‚·;ô!Ô àh#„Ãã˜Ìví¸ãÁ'¹ðš;).«`ýÞjÆžw)½úövjÁq…Ûíæ¥çžaÄ€ît©]ÌÓÏæ”=¤Æo±m“ãøëiݘŸÎ»s·òÝʽ¨š†¬yHwl¡sÍbp!}oánxq1ä·†Hù˜­p¼cµÙMB8`î6‚-Îtîyà‘h§"8Æq¹\ÑN!,¢Æ¡@ œX«ò À ¡Ã4t¸Ï$àˆR[[ËàÞݸnL6óŸ:Å`Šhâ“Ì”8®Ý…ÝÅÕ|öÓrÆ·/%;ÅMí ×Ü"ž7 •‚ká Ž*v{#u6L?’¾®a×N aá gÏl¢jœà8$ì]ÓÂ÷)ìýäïN ¾wCf «5(I!ïE©AÆA–äærQ÷À¦~ôµþµW÷Z_OTÑY˜õ¿R]¼¦išˆ¾º¤&“ ƒÁ÷qÛíñàv»1w=™m[p×ýóÄô)--¥´´€´´4Ò#œà@p|Ó”p(>Ó àh"Fž@ˆÁ‘Çápе}"×ö(%¶r#šéLÉ`vîg„²ˆ+»ìgén÷e¸« ^^Å6¸q h×X€ïG§Ód0F; @p aîrEZÓî{(Ú©¢ˆªªüóÍwáU,]¾"h›¾Æ¡£ÑõшúÏ¢Š@ ÿáP UUINiƒ§Çhq©˜Šþ‡¡|!æ? `r•“U>—ä’…TVב<*jaÞNøý\;FçÖoS% ŠñfQ@’#š A œX˜ó‡±ƒlî¼çh§"ˆ~ò9£'_Íû+ªQ;âºg>ãœK¯cÇ߬ÉájšL¦°¢âÑBØ“àÄBX•à0ð=i×|ð-9Ÿƒ\YDÜîŸqZrðš;b ^;1–£TQ}ÐK’„ͯƒZ;<9Vèo—åúš†þúbÄáÑŇÕí@1…žJÓ´€'S’ꯗÔÀz¸~š&fD´ áî*-‚ûM e·‡ ~ÐlÄ¡t©ÞN/!5ÿž¥iÜš³SGJ¨Ùž3ks F’PêÖ«ªŠV¯jZà)½¢(ÁökM#¹ûvoùi÷=Ä“>„Ýn§¤¤ðͤ+f[>þøß÷?ò×fáÎèIrÏÓ|6wU#½S¬.7“oŽÂv&¬VkÈö&“)ê#@pb!„C@ 8 TUEBÃãñÔ¯´tK”êX. 6¶=šõ†ÒuØ]^G3ôIu{áÓõPë zÂÚÍ»QBí믭%FD‹ÅL¥Ë¬›’aôBD$êÌ…X' ÂÝ[{µ 1[k($†ˆ%(j’®†›ú=L’¤€0‰¸väoƒÚ¢!×ëÃõuýÂ¥.Y’Ðü1ªŠZ'"$ ­®V¢¦ªšˆ‰]†Q´ÆÆ¿Þ˜É5W^Ýnô/„Ãㇿ-búóoáLîBRáéhª†¦©u·¥ï^0 ´ÉëÇf»ƒ½•[±U:Èo`6 QÅH@ 8±¡@ ªª¢ij°pX‡'> bÛb\þ 67êÇ|©Áì¯6Ãþ‰ó{J¤Åû¾P+„˜4b×AÕÅõõ eYFÓVÓø6  ª«H‰v*àÅR0’ï~{ŸîÝpꈓ¢Žà²fÍZîyòì–Ž$õ8xð † âü¢¦A\l yÃ&P]} ËV~‹Õ¹‘.]ºÇ†UY 'B8‚Ã@UU$M )ú<Ê´’$Íš(Iswh¬+†³»Éœ[Po?ö×/܈—¾@ÌZ wo£Ñˆ$IÂåB0Œ  ÞªÚh§!Žq’†\̳ÿz‰N9ÙtìØ±ù‚cšmÛ¶3í±ç©6fT0ŽX@ 1Ê04>Ñb±Ò$J*ŠyúÍÙ\~ÞF |L8Ž@ 8þ¡@ ¾ÌM‡ÞÐÅÍ›B/J’ÄŠý°`Œî,qãP¹QŒŸ¼?p½ï¡d-¸‰” ÑPÓ4T)8:$%šñ7#j!^꾌i4j´>D Ôv“ 0{¶¾­T+1äË&­Óž¶å†ï)ú€ cÆkZpŸš…úuÁ¶åú¦Z°]ºÂE„ÚS}Êúz‡º\aa–e9PãЫª¨^¯? ~†Âº ¬Úœr·Ý;™ÿ|€ÒÒRÒÒÒHOOoâèÇ û÷ïçÎéÏRì±”?ŠIAÓTTµñý¤eØ”˜œ†¹ß>\º‹Ï¿Ž¿_9™nݺµÖ!4ÉÒ¥Kñúïc|Ç[^^N›6m¢’@ Z1«²@ ªª"IàñxB.^oA1 zAp[…ÄK‹5¸y˜LïÌúÙ‘ý6dÿä'þ×Û%‰}À÷ƒ'ØX¢ñÜo^lŽ–å#8|’PÝŽh§!þb͘úMææ;î#¹þ`”——sÍ­÷1õWqw8™ÔüA(JÃ1Z“wsB¢%-©ó©<öÁ|λüzvïÞ}ä B–,YB^^ªªRSSCff&o¿ýöQÏC G?¤p¨9¸¿ûõÀÁȸ\xW¯Áóûjp·`ôË…gÕj<Ë–£UTZ²!ðnÜ„û—_[ÔFÝ»ÏÂE¨Å%‘5p¹|û™¿uネžÄG–ˆŠûûQwEþAEݹ Ïâ¥hV[Äm4§ÏòhÕÕ‡’eè<öîó¢ {R*ªªú~/Üî°K¤øE¾Vxu©ÆÖ2‡ÊœÜQ)úÛ(ŠXÿ;%ITk¼÷»‡¢ •çzØQ©qóPKÜ¡§‡CR¢¯[X•AdĦfcm;éÿ#Ú©"ÀjµrÛ½rù]ÏR>ˆÔîÃQ &ô`ãáMmÓE…ˆ‘$ sfö˜ò™xÃÿqå-wSYyä¾§4Ç—_~‰×ë%--]»v1kÖ,RRD _@ 8žùCZ•Ý?ü„íº›1¿8ÓÄ aã´²rì÷>ˆëûÀS'™L‡%þÙ'‘ÓÒB¶ó¬\EíàY¿!Hh4 èGü# ö Ù.Rl·ßV\LÒ’ùMjµ3^ÀõÉç¨{÷ÖçqÒpÌÿ÷0rn§ÆM¬6/¼„ãÍ·ƒr—³Úwß]˜ÎX¹{/ÅzåµÄ?t1½¼ÉXç¬O©}âi´²òº$d ƒb~þäv™!ÛhV+öÛïÂõýOàñà.÷‰ÃîŸçÂ5×D<Ëh— ûƒÓq}ûZYY`µd1{Ó Ä^yþ¿‚cŸ8¼UYV#á'IT9áÓuW”1Èõ–8ýHCÿ¢_ ( ²›¶Ài^¸ä'1qóp#ÔMࢠ«òQÇb± ‡C^M û 'hödÝõeaû^fµ°- Ž:QMî}0Üý/+7—þR*€ÿýZÓ‚~§%#I_N ®OýS|Y‚„ܬ^ù_>ýü Î?o"v»’ßÃc³Ù,f[>p:<öÌËü^TBBÞÚ¤ÅMFÖ˜æk6-$ÇȲ©mw–W8{émœ1¸;L»“Ét艉‰ìÚµ I’(((àÎ;ïd×®]­ºO@ D—?ÞˆCç›3› Swî¢j외¾ù)1Ó™g`:kàÑSÈ8ýû¹ndyr¿sxwöwìÙ³»ÝNii)¥¥¥Øl‘;8GÇÃÓ/ü“ ¯€"%—´Â±˜â,íþÚÇ¡ÞÒ#­iØ’ÅhBMïÉ7Ô2â¼+yõÍwZÕæî³²²èÚµëÿ³wÞñm”÷ßiKÞÛŽ¯,gïE ö(…²w eµ¥?Ve¯–½Êh)ÊÞ $Â& „ì½ãÄñH¼mÍ»ûýq’,Ù’,Ç<ï¼îeéžïóÜWŠ%ß}î;°X,âüB qáPY»׿ÿKÓYçã[¼¤Sû–›nCÛ³ãÄñ$5ÇsOáxöI’¿›‹é詨;wâ¼óÞ°9Z}-¾ÍåÂ|Âq¤,YHÂóÏ´Í;îPUZ®½¾ki·-­x¿øŠÖ;î¡ùWÇ5Çõô³xÞû9;‹ä¯>#ñ×I|s:É?|‹\TˆZ]ƒóÞÃç¼ø¾Ÿ—‚ÑHâ{o<ÿkþó,ÉKb½òrœ<¤§.weÓÜ/¿Jóù—àýâ«NíÕŠ]¸ž}Çã‘ôéL^x†äŸ¾Ç0d0jM ®'Ÿéøš_žŽ²i3r~/’çCÂËÿÆ4õ}Ð ã™ñ1¾E‹ãöÛùðcø~\„”œLÒÌ÷Húø}?HâŒ÷HøÏ³`4âýü Üo¼÷šA{P•ÿ|¶† ;ë:‡±R• >X«GÞu¤ÌÃ$l¦ð‹ÎÀ$¶/tL–eš½ÏýলU%7I"'QæBÿyüŠª&šè®üK“••…ÚZ·¿Ý!‰ãÎåÖ»ìÜP°ÏÑ4¿òg^y3+YdŽ8³=¹³Y1À®§+G74Xì¸2‡ð̧k˜|ÊÌšóE'¾í‘2,D=N@ 8´9(„ÃÖ[n§ñ˜“pÞó¾Ÿujï[´ßüHvŽ'AJM ŽI 8)= ï·ß£lÚó|ðšÓ‰œ“ãéÇÁhŸ÷è?R’Q+«ðýܹx  54P?dÍ—\Žû¥éhõ ORܯ¿ €ãùg {‡äœllý3ÞÏ¿lKÁ|ßÏÀ|ì4ŒcF·ùn³a½æ $› ¼^|‹ŽËwç£OÐxä1´Þ~7ÞïæÅ5ÇýÒtð)˜O<óoæG Oƒ$á™9 µª-Gs»q¿úºþš~)-¼VŠiò$}íx#&½^<ï¾1½ÜtÌÑX/»D7ýdv|k PU•ÜT;ç^ÌÖªF^þb={Ú"•()ÌŸo‚/†ñ½à£$R¬»)·¯eº/ðØ­H¼ð£—ç~ð`4H¤'¶Í L”$VV‰úýÅxPü¹Ä@r·bØ­— ‘¼nŒ»¶€¦†Û¸Z0ÔV‚ªbܵ%âf¨ÖSú {vE—œÍÈ{ÂçíéxÓÏX¹ ÉݾSU1Vn ³‰t|äúê¨~J.Õv `NH¥5µŒ×ßzw»ò«æ­÷>âw—ÝÀ‚J3Y£NÁ’˜6,C@ëJ”aw„DÙ–B}Ê`nxf&GŸ~ ËâÉtê¿‹6lØÐ£ÇÁÅAQÜÍз¦cŽ>÷-XˆÖÔÕ^Y³NŸ7brvV‡q)) óÑSq¿õ.žwÞÃö·ëõyþôYÈaa¢ap^BÆ!ƒñ~7eÕLS&Åá¼±-j=·3áÎûÅW¨•Uú÷Ã8rx‡qó©'!êgªè¾„8ã˜Q}OLÄЯ/¾eËÑjvwê~aïð÷~ñ’°Z‘Dð™N<®Ãæ x IDAT˜Ü«ÆáCñ-Y†çíw±þé*¼Ÿ~ŽV[‡”–ŠqüØŽ~ ‹–áùl.ö=µHéi1}P+v¡µê5Å"½€žúýì¿QV¯¹–@ UUÑ4½9Êø¾iŒ-MeîŠJZ¼7"—Tk¸ý°¸¦•À´ÒŽÑ‘ž‡FÆ}ªÄëK<4{áØþVÖTû˜ý½“!´]FÈÀÕÀùK½(ªÌÙƒ£¤Ï ö™™™dff’—›M‹Õâc4ÚÒˆÛÿŸ„^x†þOi!?Cë#R‰|Ѿžø¿ß[Ì«ôÞ“ÔÜ÷ÆëI¿ç\šÎ½™–£Ï ÚXV|ýÛ÷©¿òaRžÒoòIŠCÍ|9E¨Ž$jo}äçoÄX³Õæ;NÓéÆ=j =‹õÇÙ¨‰úß;ÙÙŒf±Ó|âïqNþ-éw‰{Ðxê¯y"8_nm$ã¶S©üÏ2ÝæöÓPS²ÐŒá‘êÿüö¯ÞƼBoÖf¨­D³% úS.›Î¹ ÷8ÎsâD"FÎè9úÃ8Ã>+­ƒ®V§ «Y!zeë6 }Jâò]Jpèi±~|óæÓtNì¦"ŽË¦cŽl ËG ë°Û8~,ÊÚu¸ßû°CãeÓf|Ë–ë¾—ïæÓOÃ|úiÁçÍ\³#´VWì„MX5N™„oÉ2”mm…”ÿg¦I‡‹‹‡"çæ"¥§¡í©EÙ±c'¡æõêõ­VäüÈ'Iê–­úÚqþ_ ‘PU5Øx$ÀÔA™x|*s–íBÒ|üµ/¬Ù _mqùpÕ˜Žë´óB# C…%UƒVù¨hR9k¨™üT3UÍ ˜ðPrz™ï%ôœý‹›_x?]{-_|qœ³Ñ4 ßì.Çœû»Kpð Y8>z×È©(iá ¿T{"»ïŸ €±ºœŒ[N >¥é¬ëqŽ?!ê1\N¦ñÜ¿ŸÛÎ&éµpM89(š×-²øsÜ£¦E]§îÿžÇ—SØaã97Â97öÈqŽž†óð3b¼jÁþÂ1ê,n»ûAž{RtZþ%XðãO<ýò»8 †’5îtý^½ªF´?Ú0ÖXÕ= ˆÓŸ’Œ/±€•-޽ôÆÈãÑ{n&)))Æq¢³iÓ&š››™8q"µµµìܹ“ääd***p»ÝB8‚C”ƒB8ì*r¯<T¿È‰@вêïPëF÷djù$› ãäÃzÀÓȨþˆ@9'­© ÏdzQ–­@ݽCYLS&…¥"°œw6ž™Ÿ ¬XIë­w`>õd úáýâkܯ¼ €iòa‡ Úw¾WëQ’͆å¤DÎ΋| Ì“s²£®-gg¡ì©+bÒЧ4L°í€¦á™9 ÐS»‚½Eó7¬h_óGŽ–…ÇåâÕŸ!/)²`Ú´$Rçä@cMƒYë6Öªœ>ÄBQª!$Q¿ˆ(C-!ë§}ÐëòßK‰qøéGqÝþ€¦iÜøðÃB4ì!Fħ®Âá!„’’{äQ$M¿‡ºk;Öíݸ‡NFzá&äÚ](Yz“æ3¯'ù°»l<ª=ññCðËcIɦÆÃì9ŸsÁ¹çìowYV­^ÃCϾŠ5w™c~‹ªšWue º¸·7©ÈñØtjî¤b¾ÜêdòWpò᣸ãÆ?c2™¢Ï@SSkÖ¬ÁçóÑ»woêëëY¿~=gu§Kk ààá Ëð-[²v†ýÃÆÕ;ñ~úZˆp ßâ%4ÿþ˜Ž?iÞQ ø¤µ¶ÒtêïP6n ŽyçÌÅõÄ3X.8û·AÈ|Cÿ~$}ð¶ÞIøÕ׃5XÎ9û}wƒ¡cvO¡Vë¾K)Ñ‹EjNÄÂxæ}ûí·¸öT£67`~ãuŒ×ﵚχç÷QV¬D2™°ÖT"=÷Ü^¯'øu2eÊè@è(°5.-Qz¤DñÚ ‰_lRXQ©pÊ@ §6FìØY^«Ð pqh²Ÿ«4¦€Û«ÿÞ}7ïýóŸÈ.öaÃ>¼c©ÁÞ1°lòôÏ¡qÏ Mk”붆 úBRœé~GYA×h>å*Òo? ÛÂÙ8ÇEÏVˆ†që*¬æðó OÿQ¨ýo¡äv"7øo&:›±}÷ž’!AÑÀ5x"¦u?‘ðΣ4^tGÄã˜W/ÀX±)lŸkÄ Àµ7%©ËiÆAâ™%9Ry€xŽ&(Ivm<ög[ȪJ ®M’edÿºªª’4äX^˜þ$Ó¦\'33zv >***øòË/©oh`ùš Â'ƒ·q;^ÙŠf°‚ÑJè_×®Ô4ŒGHŒNÄÆhÃðÚÆ$£…¦„Rþ7¯œÙ'œÏåçžÄåŸw “¦¦¦àù‡Íf£´´”¾}ûâõzq»Ýq­!‚ƒCR84Žƒñ°‰øæÍ§ù²«p<ô@°ÎoáO´Üü÷`ý;ͽã)ø›vüç%\O<£w[>ý4ÿ¼oŸúˆ8t>ð’Õ‚í¦ëôCUÅûõ·¸žÿîW_GÊH6J à[¹ ­¶Vb6#§¥êµ5 eÝzÔ={"Ö}ì)´ÝzýÃhц ×[„ðˆÃÐy‡×_×EOY–ÉÊÊâ7Þà€ñ_Ô·žâæ›{n-Á¯† /¼#<’mÛ¶±~g³nJ²ì”f‡×+“ñÒÙd¨Pºï‡r•…;Žégæº)æéË¡ì®Uè˜ ?œäjàkÑXU&£!âÂÇ>ÈGwßM…¢ åæråŸþ&¾úê«(JtÑQÐÆðáÃ;ˆ®ýúõCiض/pÁÏ›b×Þ:T\Ük¡E°Whf MÞAò 7á<±ËóÍëa¬)ÛçË- ‡Ö…³°,ûF𺑼njo{½ý24ž}™·žŠkü‰øzõé0nùy.Xìaû\Ãïô»©'éÎo¦„ÔiÃ}ý›MPŒ$µ#Õv”U5ð‚b!²ŒH‰•$´@ SMC’e¬ÃNão·ßÃÃ÷ßtM8\ºt)K—.Ûþ`fÈ!Œ¹Æu§ÓÉûï¿Åb!77—ììlúõ틪êu‹[[[il¬¢±ÅIK£·UÆmpà2§¡YÚš/îtå˜ëÅ\0;¨1•òÀëóxéÍ™ÜqÝ9þ˜£bÌÒ‰Uh2™âŽ8¼÷Þ{Ùºuk\¶‡*óçÏßß.A—8$…CÇ?î¥é‚KQ·l¥éÌóôŽÂš†ær!¥¦`9çLÜo¼œ]DóÌúçÝ÷£VìIÂvÓuX¯¾bß;ïõ‹™’Dâ»o`408d?¹°7­7ÝŠëéç°œsV0½×õøÓ8}97ÇSéMY ´¦&\Ï<ë_ÏÓtü©$¼úbØš=‰”¨UלÎèF­þö¶‹˜À¼ÖÆFÞøÏ¸úê«÷‰AO1}út¦OŸ|þíJ8wb…é–0;>½Ð`'„Ї+«%¾Þâcb‘‘ë&›1 Á´åPÛPrñG¥Ñv{„o¶¨(ªF»Ä|‰•ëÂçjšÆàÂBŒ;v kª$aËÎî¢|Ùe—‰h‚8¹ãŽ;:‡6› »Q¯‡"îãp™Dâ›á:¹Ks[¹(fCç”ÓÛjª*ŽÏ_%ùùÙ}ߌ0;-!•¦³n éå;©»ñ¿Öi:ÿïk >l™…lÞô=[¶l¡¸¸¸Ks?üðCîºë®}äÙÅM7ÝU8Ô4™3gÒÜÜLnn.@‡†'F£‘„„ÙªlŠ¢i­­­ìªÚN]í:<ŠŒ+-¶<4K k&–¸×3“#­i‘°z‡P¬)”kÉ\ùÀtŠŸy‰'ï»™!ƒ£—4Šv`4ãyäêëëã²=”ÉÎÎÆn·wn(‡¬p(÷. éÓ¸Z~rn¦Q#°]w-žÙzªr¤è;mO-­·Ý‰ç“Ù€Þ}×~Ë †ùE|—23aW¥^£0‚Àg9ûw¸ uW%Ê’eÈǃærázæ9$ÿzã¨më%&bûÛõhÍ͸§¿†ëÅWp<ú}ã{z:Z}CTÕ?&gµÝ%Ìk¨¬âêûîÂd2ñÛßþ6lž÷ÛïÑ0ެcêŽ(+W£y½Hf3rß>Š #6aºJmm-›–/ /ÙH~ª¹CʲQRâ6ìÑøl“ÆÈ^2ÿ7Ù±æa$>^æbá&2 þ}»[T*|9$Jz$¢††¦¶ÕTüù矹ù¼ó0•—ÅFob"ýË_:ãÌ3Ïõ‹âdðàÁ÷÷-*`Cs­¨sxÒtö dÜzJ‡ÎÅ=Š,ãœp‰ï<†äu£™ÂoR8'žŒmÁÇ$̈QßWpH`|<>ýO=ò@—æ <˜³Î:kyu`1lXÇ&‚ Gzmذüü|’’’üõ £w£4fµZ)êOo¿èr¹ØZ¾‘Úz7nÉJ«5Õo[²¬{è7Œ”®L'c[kÜ §\y7C{'óìCw’—×ñ\Û뜩e±Xâ¾¹8bÄ6mÚÔ¹á!Ìž={¨ªª¢5L!8‡¬pzƒÛÍ7`»ùýdh-¨*v¡ZSCÓig¡n/GJOÃñðƒ˜Ž:’_930 *‹l IJKtápýLǃoþhn7†Òâ0Ñ0óé§ážþÞ¯¾UÝ'™œ©Ÿ(iMMàSÀرž¢V§ße ö”3ý‚cƒ>f·ÛyóÍ7Ãæ5L<uÇNÿùÆ ãâòÇùðc¸æ/†¤t,çž…í¶¿!%$t>Q ˆ“… òŸ[ÏåØ6 ãIµQŽ] ¼þ·\eL¾Ì_&1„Ô!í,uY…êJùèõ ë]unt»D/»Ä›À¥ªF`E5ä‚áÕ{î¡zíÚ°_njò/W¯CÊng„|Wu–¦X?h¥~a´õ»ƒ8—Š&@µòy|ŽUU VÏÓ ˜ž¬/hnÑöwÁš˜NE³Æ¶mÛ¾/ Ó×3Î8ƒ3ÎøuvÍÞ¸q#O?ý4cÆŒ¡¤¤$Añ6<‰.$šÍfú–¢ª*>ŸmååÔT¯Ç)'МP F[ÏvNî©tåöB¢$ÓjïÅüJ“w5GŒìËã÷ÿÄͦK=‘ªüå—_Æew(sñÅóÊ+¯ìo7 niá0ŒvbÞù?`rGÒë¥ùüKQ·—c7ÇÓïÓz€ÑvnlŒjH–üBZ¾CîÜ‹¸®¿)‰¶gZSRrô&{‹”™d± ¹Ýø–.Å8ºcšˆïç%º?ùm¾èc+VE\W­®AÝY¡ÛöÎhÓ÷ëoázò_H;öîÅü›“»ôZ‚xðz½¬Ü^O¦ÅÃÐG‡qÅ==µº>Zy‰—$q\ß¶‹Å0A(F´áÒ /›«| ðj4Õ+$Ù$2’å°zw[€öþûÿý/›fÍ Û§¦õIÝc„ ðÔ+PvøþvE°¨‰©xŠõhRÍš€·8< Á9þLë¡YÿT³OÿŽ-Õ}½Ë0¯_Œyýâ°ýîáGà˹_N!’þÉÕŒ&œcŽÅP[ €§ßH0šƒãJF/ϾÛŸ÷yúÆöÝûŽßzìE¸†|î-臚"m,ØÏcϼÀÝ¿¿]9 QU•'Ÿ|’‚‚N>ùdÖ®]˪U«8ꨣÂnÒA|u ;³5 õ. PÓhnnfã¶å4z ÕÞ¯=+d>ôhº²BÇÌèÎÓ•ƒ«ld# ¶Þ|°¬ŽïŽ=—3Ž;Œ»n¾“É5âÐl6ÓÐ=ÛH 7‡¤p¨V×Ð8iª^#pæ{úõ WÖ­GYµ)%Ó Ç÷{>ž²f-rF ÿ{ Ébi¿ô/‚é¸i¸_ßwóáÿ:¦ j (k×m¤ ƒõ”feõ½Žc„®Ï¾å+ó{íÑ@²X0 žgâý滎¡׋ïûyaBžù„ãh½ãÔ ‘S¼_}š†qÔHä^½:wħàzü)lwÜ&DCÁ>C’$å9H¶ÁŒ%»é•bfXA[ÍEëØm¹Þï¯$ \:ÌF‰W–µ­owC€Y œd¶¨$% dü'þ¡_@‘ÿykK ¿öZÌí¢¼W\ñ Ôqý•’€Uê<Up`âí;’†¾#½IÃeÓD/¼½Ã>5%‹ÚþÓÑöü[b¯uÚ÷7üñŸÁÇu혖ì<ü œ‡·E•Õ]÷BÌãh:óº¸ìæ¤ Êë}”——Sà¿ù*èˆÓéä»ï¾cذaLœ8‘PPPÀ÷ßÅbaìØ±QçîŠÝngÈ€RTUeëöìªÜH‹=·£ýyl×=Œ%vEH4Z©6òììU|øÙoøÓ%ÑK–t%âP ‡d‘79+Cÿ~hN'Î>6¦5·Ðz½ÞE×ò»ÓÃÄA÷[ï`:ù´šÝ¨;vFÝ´–¶šêÎ œ<„ó‡P6v¿f‡éðÉÈE…øÿŒûåWÃ} ­wÜ‹ÖÒŠaàŒþƆA‘s²Ñš[pÞû`‡µ¦çëëO ïšæyÿ#œ<„ë…žéTl9G¯ŸãžþZ02€ó±§ÐZZ1ކ¡¬-¥FJKÅ|ì´ˆëiõ ¸žÖ/Ž,çžÕa,ðÞû–-î÷~ó-jeRRÆ1£cþ_ª•U=òº¿NôT'ì™cÊHµIÌ\ZË¢-Mx}>¥M8lñÂ+Ë`ö8oœ1Œr|ÝuÛÕ´¨<5¯•4Æa)Æ$È螀—~Ê•þ_õÉC†`njêp ÍbÁᦃ ç\Öçî A'¢ѱX,`6›ùè£X¿~=6› &——ÇÇÌöíÛã슼÷6…½;¤}mõ$Tþ€ìªáuÕ=ŒUï° 6ª9‘rConyn&ÿ›ù5-ÎŽ¡Ùl ÔàæŒ8°Ý|=Mç^ŒwÎ\§ˆù´SКšñ~úʦ-†ÁzÍ•asÔõp¿4÷K±ëyÙ¸Ëygëó*«p=«Ÿ¸GÄЧ´{ÎK¶ÿ–?ý­·ß÷Ûï1M™„ÖÚŠgÖg(ËW€Á€ýÁû‚5%«û£ÿ¤ù¼‹qO eÙ LÇMCJMEY¿ÏÛï¡57#b»1<ªÀó鼟ÎÁPRŒõòßwÏwÀ8a¦iGáýü šÎ¿ëÅ ÷ÊÃûå׸_ Ìf¬7ü_‡yÖ?_…ôÕ×PšÓ…÷Ó9¨Õ5¸ßxuÛvŒÃ†b:9¼û¤ÖÐ|ïå¢BŒÃ† øÿ/µÆF<&¦¿†’b’¾žÓí×-øu¢iª¦âóé'ÝY ÓØ©hðññ²:ŠSeOƒ7V€WÕÅBGœ]–eYKWhvk¼¶Ä…Ý$±`¹›1ºPèê+‘û±T·èJ]]ÄqÉб&© g9æˆÃXüú·Ø3òÛ¢=$‰H’±ªªào¶£Ê2r Û' †ü^k£…ü¾D¯ëÖ¯B ø¤àﱄWà =T¿°[ë‡ÕhlûøŒ¶–BmBGörH4ºª* ¨XS²ØºÒÉÎ;#6²èÝ~5MÃd2QTTÄÎ;Ù¸q#ãÆ#33“©S§²aÖ,YÂÔ©Sƒ7Ϻ[÷°½M€^¹Ùäfg²nÓfª4š“ËÐ º]÷°“HÂ.§+GxM^k:nKìÙÌ‚•[IMK§o_=«+V³@ ~YáÐ8qöûïÂyïƒ(ëÖã|ðáà˜iÊ$Ï?ƒähK'Ô\.ÔÝ»÷‡«1Ÿt’ÝNËUÆ;÷K¼sÛ J‹±?òOŒÃ‡†Í1MšHÂôqÞq¾eËÃ"ðkÚþ~sØëÞW$<ÿ4ÍWýï§sh½ãžà~ÉfÃñŸg1MšØaŽa@Ï= GLŸ—æË¯ŽÇŒ&á•GLÁŽ„ºCDô~TUE¡]3e²0­¿¦V¯,…SúCr”_ßÎR“%I«À›K]´z5ÎaåÝ.R$HFï˜ àD =@ ²bèEKu ìiv’ꯑÚáµ´‚gذahO½´¿Ý‡ÖAÇóÄ¿^à÷Þ¹¿]9`‘CšÍ¤¦¦’ššÊüùóINNfôèÑôéÓ‡üü|-Z„¢(Lž<9hßu#õ+éM±×ËŠuK¨Sq¦ôCC¦3‘°+éʱƺ#$j©E4©¼¿`#‹×nãŽë® {m@ 8ô8(…äÙÅeg9÷lLÇïÛy([¶`()Á8~,rnN[Éj%uû†½òÇ8jDÜs‡MŒÛÖ4õ’ÿ€²l¾%ËÀbÁ8xÆ‘ÃÁlŽ<çðɘ>ÿßâ%(ëÖ£ÖÔ`(-Å0dPÔHÈ„ž‰Ë€„WÿŸ¡ÑHÂóO£lÞ‚oÑÏh»*1Œ†qÔˆ˜] ýõ;—’ÝŽí¦ë1Ž…a@¿ˆ] åÂÞßOû}wa¿ï®ø|ºªªh¨ø|퓃ur4N¬§)ï®t³£QãœV2úç`Î"y€](lF?É7ÿ‰Ú&7Ñåó…uøô<&“‰Ìdnw KÇf:@Ð,)Ùl\¶[¤‰Æ@ŽpþXPP€Çãá³Ï>£_¿~2jÔ(jkk™5k}úô¡OŸ>æu·îaè˜Á``è€RZ[[Y¾þš¬yx{‡Ø@ÜéÊmOÚÆüûº’®·(ÉxRú°ÎëáòÛžàÈÑŸqö©±3|@pðrP ‡]AÎÈÀüÛS÷·{ä°cœ8ãÄ ñO2™0Ž‹q|ô‚Ï¿’„¡´CiI×ç X¯M>ªª¢© ^oäh=ŸÜ¹§Gv<]ÿj³•*§ ¶ðÛ¡mÉů-r¢ G‚.ú—m‡êœN/ E÷Çäóñü¿þÅ¥—^Ú©Ï‚½çÜ3Ná©™?<è¨cZhB¦¦…\CHTª¦i(þý²,ƒÿ±$IméŽ"òC°?é,e>”)½÷`¿Ï¡Qâ½FMë^êt„÷R¢-mYÒ4äÜa|ñå×ô i—™):dˆÕo6›)..¦ººšÍ›73räH’““9üðÃÙ²e 3fÌ`Ò¤I$%%E]{oÒ•Ûc³Ù;´U5»Y_>Ÿ–äþø,)íW‰OHÔs¬'ê†v`nL,åÃõ|óÓ#ü´bÞy Fã!‰)¿*Éæ(@ðK¡ª*’¦áóù"nªÒ^‹LàBP’$–Uª<1ÏCº]æÚIVJÒÛNÀ—VøX\á#]lj* ½Æa3°Ðoß䆣Dn"ké0jžÚXÛ=ÁäI“P+Wu¨eþ~¡A¨·ª¦¡*о©j¸SU5¸ :? „ô %)òÖÕeB¶½ö!Æš¡kGÚ¨ˆ¤säƒYsؽ{wp´aè¤~ojj*,Z´ˆ¥K—¢ª*………Lš4‰U«V1wî\Eéñtåöd¦§1ahrݰԮ%Þº‡=RÓ0›X¯ßh£.¡}°ˆ>£â©g;v’ÁÁ‹ èÂU8 íªÜ[ê4žþÁG“®dahŽþ-±´ÂËš 2zd¡]üd™ÄÅÛǺü› H<û¯íÕ{!ˆŸ Ï9÷Æï÷·àÁ?œÙŸ}¾¿Ý8 ‰&Úíz³ÀÝ»w;[,JKK©­­å‡~Àét’Àa‡†ÉdbÆŒTWW‡­ÓéÊí×ÈÎÊ`\YI• \õ!vWºr¬±} $¶ÇkË`7—³ÿïŒ>â$–,]c@ èáP ºAee%Ë+ÜìhPÃÒCƒi¢1NÌ›=ðòRøz«ÆÃÇ«Ýy\ IDAT9i€¹XØ>ÚpU… ½ƒ²†.6ªÆ¢…•.ædŸ=¾¯w ]44v Ñçã…§žêòû èœÌÌLÊÊÊ(++cìØ±˜\Õhþß‘@ª±"Bk!iÆZ»ôcÅ¿µ·iŸÖ  ùí´yŠHaìKºX×/ZÚ¯äÿ×qù¿ç![§~iZ‡ÔßH[ègJkwŒN’ \3Ô‡(¶¡[ ¹ýV³Ïo›X4’™Ÿ}Ë£_-Ñ„C³¿Ñ ªªX­VœNgp,==ÂÂB–/_ÎêÕ«QU•ÜÜ\&MšÄæÍ›™={6'âºÝIWµ3›ÍŒ>€ç:Ìõ#Yé¿J‘ĽŠ Œ´^Wp&²DéDZgý¡Kó@p`!„C@ èÙÙÙ Ë5Òê…ï¶Ãgçs¼ ¼µ>X g‚ß ’0Fø6n¸¬Â‡ŠÞEÙ´u,kPXѨbM’±:$ê¿T> Ú€ ÑÿØ P_ÏË/¿×ëì=ÇOBÓ¶åûÛ @p M4y ÒoPRRBMMMÔñ¬¬,EÁétv¨ [TTDBB .¤ªª Y–0`Çç›o¾aáB½¢ðÞFÆ“î<¤ ý’ÝXvýjŒ,†X"áÞ‰ñØÄò?)t¹™ «JjÿÉ1VÁŽ hš†,AŸ4˜Ôªša~¹Míšo¯‡W–Á´R¸`(ÁÚƒíŽH©ÊË*|Áu<lmVÙÚ¨`´ÊÈ ·$±=u94’&Üaý‡ XGÈO+~á°±‘W^y¥›ïŒ 3NÿÍÉø¶.Øßn‚C¹÷(fÎ5åÚsÉ%—pÑEQWWUØž¤¤$dY¦¢¢"ÌÎf³Ñ·o_X½z5N§«ÕÊèÑ£IKKcÆŒ”——=›®J^v&cûçP9ÜÍĬ{ØÓ“ãC±$`KH!ËWNKþdj]²GÚ@p0#„C@ 說"ùO›%``&ŒË‡MµðãNpûƒ¾Þ Ï/‚aÙð‡‘f‹¾f´´*ÐOÐkZU¶4(X¬iÉ\4KÍèuM@ s´®Ÿô(ÃDôˆÃ€€h[[qŠ&)û‡ÃAqq1£÷ÁÝPÑF£-M2´“rèEepÌ¿)Š‚g'ïh©ÍA·éJ·âÐÒ ûȰcù·°”ãДä(Ÿ‹Î:)wø…¤$wšÖÜ×!‡lÉ…Cùü›ù£Ì픕•qï½÷Ò§Oªªª"Úú_ÎÔÔTl6 ìÙ³'8ž™™É˜1cHJJbÇŽhšFzz:“&M¢ººšY³fÑÚÚ t½)J¥µKs9²,c0°Y…p(3B8‚nqØ“&Â_Æë‘ˆñ¢iƒ!xQ¸²ÒÇC_·ŸbÀfÖ¨^ôš‡^ô‹Xz“ƒÿ§E_€F7øT=9](Lõ?ÎBsÍñ;,ØkrrrR’ƒsÏÎýíŠ@ 82ƒi³‚Ȥ¥¥qË-·0mÚ4ª««ñù"× ´ÛíØl6ZZZHKK 3Œ7޲²2***p¹\˜L&†Jnn.Ÿ|ò 6lè°fW…ÄhŒ؇Œ–uZk"‹{û srD“ Sr™ž-¨¹£ñ$’Ô´#¾°†>6q(5B8‚nK8„Ø©w‘¢ C¢l¯Wxä›VÊën8ÂA’µmµ€p¨ª¦‹}½hKAÎBÓ¼°¡*wÃ( üûS  7ëžæ_ÇÞØˆ£” ç¸í†kq­œµ¿Ý‡ZJ1K–‰¦Kñ0eÊî½÷^Ù½{wT»´´´àßå@‡ûÀÏÔÔTŽ8âìv;hšFRRãǧ©©‰?þ˜†¥?:+KhVVJ¦kÆÖªn§+ÓΦÓ&+€šRHºº›d›Œ»è½UØ|õ;Ûm–èÇÁ±s@ DCUÕ¸KyÅK Þ\æ"'Iæ¯SìÈQÖœ¼Ë@¢¤G Ê葃Nv×A¥ Šp¨yèMPRÑF;zÄ¡Ç?Ï4vŸ¹}ÄÈ >|xϾ@AÙÙÙôËO£¼¶[Z^ðÿUÓ´åYŠ,B‡\tJšLïôE©sh¶´]¼…^†^$Šêh‚nAœˆ˜*ÿKzÌ8Žš ¬j‘?/‘lÑ4´ÐÚ!µƒ0üuIƒ¾„>އ‚’ªiX³KXðÓ·ñ­!Àd2qÕUW±~ýz^}õUÌf3v»=ª}°îlˆx¨i¥¥¥äåå±téR|>ÉÉÉÜ7iÒ¤Ø5ŒãLWý9t@)+Ön¢Jñá¶çŒz>9t·-«Ò„ݵ géñ¤(»Ið”£J ÊrÄ×!R•ààFD A7è4â°&4âÐé“xñ'3V{¹b‚³†Y£Š†¡¤ùèу} ¤zØS …NíUÉRUr  (òÛæ¢§,ç™è"bú]¥š+X¶tiçºÍÿ]óG\«fïo7ÁAŽ9!•í»ö·ýúõãž{¬ŒÊÊʨâ]°Ölˆhxl2™9r$¥¥¥TVVâv»1 ”••QTTÄœ9sXµjU×=Ô¯˜eææí»ŸŠb£Éf”¤Þ¤¶lÄœÙCñDò´]XqGŒ2 ‹8´áP f„p(Ý@UUänôËÔ4 Ÿ o­Pxu‰—ß 1ñû±6,Æøâ¾ì´5BIÔ`O3ìØ¦f˜æñ‘âó‘¥@6ú ztaº¾D[—å@}DWSSÏvD%;;›>¹É¸ê*ö·+à Çé¥C“$A|œqÆÜzë­(Š1Ÿ}Äa¤èÔ”&L˜€Édb×®]hš†ÝngÔ¨Q(ŠÂ'Ÿ|Ò!5:žîö±lô)"GÝ…±9†h¼×éÊJb JiÔâx:9‰iZmL±Ð`0„¤* áP fDª²@ tƒÊÊJv4ªdGÉlêLþûtƒÆ¦zìD¸r¼%¬)J<$ G š]P·Ò½*ýƒ¦áEo–Ò„.ZÑ…B ºp˜à¬ùý´¡7YIõ¯½ÙíÆ·'‚½ÅápðÐ}wòÛ ¯ÂzÄ• IúEbàÚ_VQý÷ú$UE ˆ¡éqüÞ„vdÆùÞ¡H[t1•9ôwµÇnxìãtê€Ïa)Ì!Ç•ˆòZBDö)ÒRR.kÖ¬aРA=ê﯅””nºé&æÏŸÏŒ3HMMÅhÔ/™: C·ââb²³³ƒQ†IIIdee‘žžÎºuëhmmå°ÃÃÒ8doÒ• èS„sÕzª TSR¤+«æ$$’Vá.:Št$hÕzäe”3„P¿4MÃf’˜2vX o‚øiñ¹8â‹¿sIÉT®ê{|L[—âåÕ­_3÷Z¶4W12µ”i¹Ã8>wä^ÿ˪|ºëg~Ú³‘|{:2úsañ‘$­{½f€«½@•«žw'ÝØíµfU,æ–eÿã­Ã®§R¯˜¶‹j7òMõ*~Ú³‘Î=ôKÌcbÆ.*9£$®B8‚n‘™™I‚ì€ü$(H ¦å,(‡Å»à„~G÷‘ùp]À^ê’pètCÅ(P XQÈU4t‘ÐM›hh’Ð…Dz«ÿ±Ï¿¿Ùogôo’¢àq»ãöE°wØívìv;™™™üþœßðÒWßXv„>¸SIýTIB Ô04‚6rõÛ¢D8©`Rë/.öGIÄnMŽ]ÚD¿Pñ¦ƒí} ؇ֳ|¼ÓŠ™·`¡»Éĉ;v,/¾ø"[¶l!333LŒ&†î7›Í 6ŒššÖ¯_Ozz:²,SRR‚Óéä믿&###j-á® ‰ÃÊúðã²ìI ëÞ¥+kšlÄmÏ#¹z!Zά%¿¡ÄP ª‚¢´Ýtj/†þT‘™ïàñ/¤oIQì7[ ˆ“vþÈ¢Ú—;"¦]…³–Ó¾{÷´u7ÿ¦z­›ÁÕ}çñQ¿ï’ ¦¡qÛò×¹Õ»aûÿ·õžÝð)M¹…’„쮽˜ê<ͼ¸i.}s÷zö¼¸y.Ëê·âT<1íZó!7-Vûúûš5üwó<¾n&oOº²¤üóKpp"R• ¨ªJº &äë| Ê¡ª9ºýªxj!˜ð§qÐ'­m¬3ÑpX^Û½—ÖVÃîÝPäƒ>ŠJ¢¢`A¯u˜‚‰˜ÓV1]4t GšÑE€ˆ(¡G6š¢Ð£¤ ç¹ðüs°×­ÁÛ"Þw@°wØ2 Yø³è¬ÜFþøÇ?rùå—ÓØØˆËåŠYç0ÚþÔÔÔ`ªr †¢ÅbaÈ!˜Íf>ùävìØÑ©?ñ‰#õ%©f1(ÞH t*$z¹¼-¤4oÂ;ðwPlmÄ(KQÓ’%)dÌ` Ù¬rûÙãøä¹Û…h(è1–Ömẟ_ŠËö7ß>À{60$¥·»ž'<Ác#/Åf0ó̆ÙÜ×N쌧ÖÏâþUïb–üsøE,?þqÞ›t£ÒJYÙ°ã¾¾+¬‰VW¨rÕsñOáV#|f÷·êåß›>çýò:µ½gåÛܸô44þÜïD¾9ê^¶œò<ÿ›ðW ™¬lØÎ™ß?„+Ò÷‰àW…ˆ8‚n wUÖOò“ômSl.‡þmˆå 0c”eê‚aY–A9¤IJ4†çYT¥Â`+ú] lt0ýËÝënEOK†¶»E&ÿcÍo8ª (€=bqO»:L‚}Ï=·ÝÈ_îx„´#þ¸¿]!F«ƒšòÚýíÆ!EII wÝu3gÎdË–-äççG c¥2“™™É† e™ÄÄDRSSIJJbûöí¬ZµŠ &`³ÙºT÷0ÔV–e†õëÍÏëÑ9&vèlˆ¨í¸d‰5?ã+œJfn¹æÿë‹Ü-¹½šÏËa%‰<~󵤦¤Ä÷æ 1ø¹n3O¬û˜Ï+—²ËYלïjVóSíFÒ-‰Ìœr+…ŽL'÷&ÇšÊ9óá_fó·¿Å"›:]OÑT_7€'Fý+ú À”BËÀèÏ®gCÓ.>©XÄɽÆÄåc£·•»W¾Íç•ËXQ¿Ø1ÁññÊ–¯xcÛw|W½šV¥óŒ¡Fo+¯ý€ ¿ËN Ž9²82{0Cfý…• Ûùïæ¹¦† mDÄ¡@ tUU;œ”—¦Âø¨n¹›áéõ´ä+ÇÀÔâèkîÖGÂåƒ5 lØcÀФPäò`÷x0¡GîYУíè‘…¹è’Mþýf¿Mà(¡5¶üɯA[U’HÏí¹” A|ôîÝ›ÃG  yë’5³4M ^赯M¥¨*ÇnBè~EUÛ6Ÿ/¸á?ƾ®ï&8„‘¤¶-°+–m<û¥X‹üLÄý[ÁǸ ùŒhªªoš†êß´(ŸÑ¸Ö ™«…Ž…¹.! ÈRÈ?ƒ,ceŒ&3»w×°fÍÖ¬YÓõ×'ˆÊÉ'ŸÌyçÇÖ­[©««‹š¦-•YUU¬V+ƒ "##ƒŠŠ |>ôéÓ‡ ðã?ÅÆx»0‡b³ÙPNRýj}®¾@äχ$ÓšPˆ±n3 j#–Ñ2ºO½žN»%Ï[$‰ “›G®œÆ+ÿ¸^ˆ†‚ã˪åLßòUÜ¢!À£kgp~ÑáAÑ0ÀÙ…“蛘Kµ«×¶~×zîXÈ–æ*2,I\^zLØX¶5…Ëüûó‹‹ñPíjà‘µ±¼~kˆ†Ïmü”Ïv-‰K4øaÏz½­$™«#ˆ‚y¶4.(> ,å[ðëDD A7ˆÖUYd舿¾ .cEª¼½ÆÄs+“8ãÜK9KÃwsæú¸Œ.òJ2›ýû þÇò8ày Òÿ\#€ÍFRj*‚_žk®¸Œy—^‰’W†ÁdÙß ¯OÿûŠÄÄD®¹æ~úé'¾ÿþ{rss‘$).Ѱ}úrbb"Û·o§¾¾žôôtL&ýû÷§¡¡9sæÐ¿z÷îvüXBbèXjJ 9 å¸Zwá´å„…D·%µy7ަ%xœÂà^ dX¼( aQ†±Ž'yLÆý×]ÖèE è .*žÊÑÙmÍun]þ³*ÇœóE•^ªáļÑÇOÊÃcëf0·r—–Õ©õNÈÌ åä^£¹cÅ|]µŸ¦ÄU;±·#“%Ç=|>·j7,y¥Óy±˜>þZZ|®àóqsnÄ£ú¢Úoo© ,)G”æ.éæDê<-ÝòMpð#„C@ èªªÄ X1H`1t"ʲ?ð%¼Æá—[$þ±8… GžÈÜJjj*Ÿ±åË/Ùáó!¡GjhM9 zв ˜m¶.¬ èIŒF#wÜøn{ôEÒ§üa»#2|JŒ?:‚a̘1Œ9’W_}•––RSScÖ9Œô ??Ÿ´´46oÞŒÉdÂn·“˜˜È AƒØ¹s'ëÖ­c̘1$&&Fô#V$bQA/ö¬\Óƶ¿éŠl¡ÑœFâÎïP &Urei ¨JÁ0Òq4MCUrÌÍÜõ§Ó1dÀÞ¾AL2-IdZÚ:¦š1í[|.š¼NF¥•F´™VwcÀndjIÄña)ÅÈ’„ªiT¹êéeKïtM³ldxj[ÒÆæ]qù‹öU"‰œ¡œÒk,£ëC²ÉÕfÖ.]¤=1oT·ýÜáP ºª(]è¢"®¨†{L%µx/¼õ………A³O?ÇŽeÇüùÁÚ„vôˆÃÐûüñøšÖU ÄbBB¤i‚}ˆÃÑvBG …|f÷¶~Q. }ª3š]Ð3 .¾øb¶mÛÆ;ï¼CRRf³9L<Œô8R÷å~ýú±{÷nvîÜIzz:’$‘››Kzz:K–,Ád21jÔ( †ÈÑLѾë‡ö/fáÊe4dCC¢É–i×"­õH£.fRo ‰&E‘Pýg±º%È®z~3ª€ë.ûSO½•Aù$$RL‘EÆ4³~~[éêšp˜f‰|^,Kú±j=ÍìrÖÅ%dY“ɲ&GcÛw,ܽ ‰SòÇþ‚ž D„p(Ý ³ˆÃ®\·íh„‡—$Si(àÖGbäÈ‘íî|óM¦öí‹ÙíFE¿UmiÆñ6p Ho^Ž˜LüþÏæì‹/ŽÿºÝnÇn×ïüÖÔÔpÁ¹g²dùßÙµk= yýu£šg*ºx `”¤¶š•!x¡âDçÉ3ᢋ‡,ñÖŒ´{oÕþsd¢¬)íͱüøqÃà—¤°°ë¯¿žO>ù„•+W’––5Ê0V*sJJ ‡ƒòòrZ[[IOOÇ`0P\\LSS_~ù%EEE”–ê‘T¥+ƒÁÞ¿ %»ÖQ•8{õ÷xKc`¿ÞôIÅ/hFozºžêuQ`iåþ.¤Wnö>{?‚½e—_ L1;¢FÜ¥ùÓo+]õñ­Í‘£~Ò,‰Ôzš©tƷ挪i<¸ú=n[þ:w9‡«¨[úkG4G‚n™™Å¢ÚdQš²Å#¼4º`Æ&+—|UÀIyœ÷>ù"ªh]PÀ1§žŠ4M€ ]RhãA¦M4ôúתæge1pêÔ8WìK¼ûïhkgãiiØß®‚ƒM2àõz÷·¿:N<ñD®¹æZZZhnnî’hø)IùùùäççSSS\Çn·Ó¿ššš˜;w.µµm³cE–kšFRb"æ–57©S.çÔ }(Ë2a0ân€bqïáSKxåÁ¿ ÑPpÀâVôï=“ýV©ÑŸZ0U_Ó,G¹2Hþ5•øÖ¿ö&©ÎEò§' ä@½«bû¡‘F¡q(ÆÚXgÙùt@¤- bLß‹‡¦JÆq„.ûúå-Z+Jš›æ[`‰vkt’†“ÐÔPMDMÓ´QC¦…É`ÆétvõÈ‚d̘1Œ5ŠéÓ§³mÛ6G\‡í÷'%%ÅC—ËEZZyyy¸\.æÍ›GVVeeeaÇW…ššJKKÉÉÉáÛŸVR˜n ® j=CMÅÒZÁe§N`ʸèYÁD@¸óª M^'‰¦Žþ"_®55Î5u1²Ö]Œ ¬™gKë’¿_T-çœyPãn¤—-û†ÇEGtÚ\EðëBD A`µZ¹ÿá'yñƒ¯ù¢©ŒuvT­£Ø2¿\â¤÷Sù!áTf~ù#÷ÿãÑ.‹†ÁcÚlÌÚ¶ uØ0ö 4¢‹†ñ&§i~{7zC”Íu¥¥|°té^ù#Ø·L™|G(¦iåœýíŠ@ 8ÀѼ®½þÛ"è9dYæâ‹/æ÷¿ÿ=n·—ËS4Œ”Ò¬i’$‘““Cff&555´´´ if³™ÂÂB<sçÎ¥¦¦€¦¦&™0a999~o¤N£ ƒ›«Žá©­¼|ÏB4TdX’‚‚×––ªˆ6[›«ȳÇ'ò¢£­·Ó¹¯?#$^1ò@aážõœúíÔ¸9©×h–Ÿð8)DCA„p(=È!Cøö§•L¼ànÞÝœÊÎ&ýïºÝpþìT^¨ÏK~Ã˯¿KIII·çHH॥KvçlLN&ò)Md¡¨¶ÙÈ<é$î}óÍnû$Øw\õÇß3®ÀDÓê/ö·+àFõ´œ½[¦à—%??Ÿ[o½•Q£FÑÔÔ1e9šhjc±X(((À`0PUUKLL¤¨¨ˆ 60oÞ7–ÆŒ)·;N í¡@ ô0²,s͵×ñÙüå,0L樷S¸~q_nxôMÞ™1‡!C†ôø1ÿpÛmöè£x~óêÌf<ÄN ¤Ïùdwz:iC‡rÖwÒWÔ5< q8ddd‘‘Áí7ßȈ,•Æ5_£Ñv¡©¨*ŠÏ‡âó¡jZp Ô¼ th”:zÁº =ÉÞÔ_ÝgÒ}cýž‡ÚÄcŠ$S;}ÝRŸõÝñt~&â‡ZÒ!ú€œxâ‰Ü~ûí8Ž`Ô`{‘0žú‡‰‰‰äååÑÐÐÀîÝ»Ñ4¦¦&²²²ÈÈÈ ;»cóM‹-š+™ÔKáé[.£_iñ~xw‚žá²R½ç;ÛçëìCØÞZüšµ˜d6æU\Š·ž»sNádF+Ëë·±¦qGؘ†ÆÛ¾àòÒcÂÆTMÃ¥ü?{÷Gu5~ü;Ûwµê½Z–lYîrǦ0`Z€Ð ´@Ò?Iè^J%/¼$@€qSMÇ`\q·%Û²­Þë֙ߒV³ò®´’e¯dŸÏóìãÑÌ;wÖkk÷ì=çzqùƒíŽ£ IDAT½•܈„[íêϧíÍëÿìýš]íµ$[cùíÔ PFÎoh1IC!„8@rrrx}éǬ\¹’ &àtØoñæ]q\q{œ¦—^´~=Jk+Ÿ/è["ðX,’“qdf2þÆé2$h8b9uuuÜò‹Ÿrǽ`Öψ/>èªY¨u*ŒjoÝ3eé&úšiòý¢ˆE Ô”aûÐ5T]]Q”>ÿ.# :FÒj 6Æ0ãÑg·ÛùÅ/~ÁªU«x饗PUƒÁr–a ©(ŠBJJ .—‹ÊÊJŽ:ê(rssy÷ÝÐå,´îTåÀÏ=¯wñ®½üü‡ß!)qt¥Y ÊyyGò³ÕÏòUýV~±úÿx`Æe˜#uî|>ÍÏ÷òŽ ¤ ÷¸|ùÃüc×§ä9RÙuæSý±f;çÃSÛßåìOïããEw‘nKÀ§ùùý·/óAõ:œ&—ä/ êïªÕœöÑ|¼è.ŽI›¼ß÷–ýú•Ô»[¹ªðDžž{ý~õõN÷ Ê8³ƒëW<ÙoÛ#R&pí¸“÷ëzbt“À¡B`³fÍ:¨×˹þzr®ïz3ÑÞÞÎöuëhÙ¾C–ôt’&L `òd,Kàœ¸ƒ:B1n¿å—üö®ûØ¶í œãD{8BˆÄd™##ÝÌ™3™1cÏ<ó «W¯Æb±DTÿ°oZ³Éd"))‰ÜÜÜþ/¨ô ª*Æ–rŽŸ–É) /=Àw+ÄÁc7ZxçØßrâ²ßñÇ-ÿáÙP“ÎÚ¦ø5•)Å<9çºAõù§™WRÖVÍûUkÉ~ýJJDz½µ’fo±f;ÿ=æV,£«®ìÎö®Z;ÚªÙÑÖ±#·ê•ÀáaN‡Bq‹‰‰aúüù0~´‡"€;oÿüâ–ÛÙ³'‘ØœÈjõ!}F™,<*(ŠÂ•W^IEE=öƈV_î{l šÖ8T:HõÕrã5ß úQˆ‘ùŒsf²p€Ù{³’ Y¶èNÜô:Ÿ×mf]Ó.JDz0m2wL½“mŸsÎÍOQlVÈ ÝhaÉ1·ò»õ/±¬ú[V7–‘iKâ´¬YÜT¼˜9Iãö9g¼3“ßN¹€11iýŽwR\.¿rA`Uèp~5ñl:|nf%öÛà¶ÉçãU}dØCÏ$>+gG$ ØtÕo‡7  !„£HO­CèJ[öúü‰¨šŠQÙ·¦™×ç l«ºf¬ÖÀ¦!L-´ £º”g™Ë$†bЉ³ƒHñÕ¿&#ºŽ>…?\ÿa^ó}kfuu¡õÝد鶃šèþ ¨æb?×Õ+66މåË„Ñ"++‹{7ß|“7Þx#úIаçÏhŠ‚cãV1S>w&Äð:'÷ÎÉ="¢¶ÓòùûüŸàÓü˜B¼GÒ;7w>çæ†ÿ¢Ýf4sßôK#îo\l&¿›ú½ˆÆ:)>7¢¶¿šxvDýÜ:ù»ý—„b0äûH!„b”jiiagu–¸”hE1B¨>7±±£+eNt9ýôÓyä‘GÈËËÃårõ›²<؇ÅO¶·ŒÛ¯ZÌŒ©Åán„9 òE»?!F:  !„£ÔsÏÿsÔ7Bôò¶5’•±ïªºbt°ÙlÜzë­üìg?Ãb±àñxú Í$ïGN’ïŸ{ò ÌB!$p(„BŒRÿygΜ) ihj瀞ªßxhªx„£ÿ0ª©½!†“ ÓÜ5-╈ˆžë÷} Ð~ŸŠœݳ;Ä#T»×éGgÍΟ3p?bD+))á‰'ž`áÂ…x½Þ ••Sã°³³“¦¦&n»í6L&©R%„bð$p(„BŒBü ZÚ¤@ AÕ}¨ôëú `8A³Xt!Y‘–žÀâ`f‚õ7öÆ]Ì›;{xÆ&¢îšk®áá‡&55·Û½ÏŒÃþTWWSPPÀwÞIFFÆA±BˆC…BˆQè_xÇx)n/„¦µÕPX8ðŠ›bôÈÈÈàÑG媫®Â`0à÷ûC~!¤iŠ¢ÐÙÙImm-×]w]tQ”F-„âP!C!„bÚºc/fgb´‡!„I4‹QêØ¢/^Ì‹/¾È´iÓp»ÝûWU•ŽŽÒÓÓ¹÷Þ{;vlF)„âP#….„BˆQ¤¶¶–U«VѪÙ1´7ÒÌ>Ñ×3ôz½m}}ƒ¡÷»C£Q·: n¿ªú{Ûtm$(!"ÕóZ Uû¯{ÿ@úž*=3\/ƒNDÖ÷­{G²jmØ{Õ( k4sL—‚¬éKèÛ³ïsÒÃÝTŸ‚1UŒZ‹…»ï¾›5kÖpß}÷ÑÐЀ¦ix<êëëùõ¯Íi§ía !„8„ÈŒC!„b”Yúþ2ŒYÓ¢= !ÄÓY³ƒy³¦G{â ())ᥗ^bñâÅ477Ãý÷ß/AC!„ÃNf !„£Ì—+×3ûцb„Qšv1mʩц8ˆn¸á®¿þú YäB!Äp’À¡B1Šx½^š;<$t¯ÂÚ“L®¦™~¿¢OCÖ¥OêÓ0Uoz²Aß§|&û©çÕt0×1Öÿ«ØŸëîW?ºæÀs (A)Ì¡žE÷ï[ë>¿·½Ò½¿Ow[-999ƒ¡å$h(„â@’ß2B!Ä(RZZ ÎŒÇEÙ'€Ø³OQ ºGO]5MÓPU5ððûý‡ž¦{1];†P/3Ôë|Øtäé ì 4þpÝlìí>Ä¿ÑpcÐõÓ÷ŠßÝAj‚sÐcBˆhÙ¾eÿýçÿáñx¢=!D?dÆ¡B1Ь߰ â³¢= !ÄÓ¶c~çähC!TSUÁ'K^ +J2Syó™{ˆÍšÈ¢3ΗUá…$p(„BŒ"߬]=¥(ÚÃBŒ0ZÕ:Ž;öûцB„ÕÙÙÁÛ¯ü/Vw-Gåb2[ñû¼Ì*ʤ½£’—ý ùÓŽfþ±ò%ˆ#‰…BˆQd{ÙN,Óê¿Ñ~|[¯ÿ¦__ûPSÕÞm£±·ý¯$ ºú~ÃEƾ"¾f$Ç{ÆÕ] g¿þߎªkƒ¾M¨~úìÞ‘ÏÕNF¢«Õá !ÄÁ£ª*K_}Žæ½˜3q Fc~¿Ê¦]{Ñ€ 9IX-ffK¥¡âžÿÓgÌ8öL&—ÌŽöÐ…HàP!„UÚÝ~ÌJÿ%ŠÃó"Iÿ êö«ºà‡A8""ºÅ@l­Ìýê;’ d¨……4-doŸ¶!‚…}ë(öô©êú6!Ú¶ïXÁÅ’¦,„>y÷ v¬þ˜éãÒ)Ÿ¦iìªnæ›-¬³-Àd6S´íS楓CœÓÆ4›‰òåÿbõ§o²ðÌËÈÍíÛâ°&C!„béôø0G{BˆE­ÚÀÂc®Šö0„"`íŠ/Xùá¿)H³S2. £Ñ@c››w±Q+¢-í|ò’ìX­VªÜż¼c9ã·­a^qqv#éIN’}>>åOøc2ù΅ןíÛâ°$C!„b”ðx<`”_ÝBˆ^>W;Ù) ˜Íò•‚"úv•meÙkÿG¢¹“)¹ F:Ý^Öl+gs{<›c3>ÕF†µ7{!#΂qæq¬-/aëÚw˜dßͬq©XŒ0&=Ÿ¯…>r ñ¹S8ë’käÿ;!2ùô!„BŒ----Ž@*²Boj±Á`@1„HaÖ¥ûuéÆaßtëÓ™u)‘ŠÑr¿"ýYêЍ Q#ð€S]rïPÂŒ¥OºqO)MŸòÜ7…9èü®?TM£µì+~pÆILœ8q¿oC!†ª©±žÿ>ÿ´V0.+ƒÁ‰ÏçgýŽZ6ש,·˘cláË­¥;èŒ?¥;ØøÍ›LKt3-? €ÂÌ8<¥ç…sЊ̽«-{·-ãŠ_<4ˆÑ !ÄþûrÙRV¼û2©1›ì@Q µÃ͆òFv(cùºc ©7N›°ì×µbÌ06-žu­'±b×.æò-3ólÄÙÄ:,Ø}-,{þ~>}s ‹/½‘œ¼1Ãs“Bˆ€8\Û´“W3'fL¨}«·“Ueä8’)tfì÷õýšÊúær\~3 °†ç©©u·ðyí&ŽOŸJÜ0ÍYZ¹š\G2“ãó†t®ÝhaaÚäa‹Bˆ¯½½ºº:¼^/ª»-LPè J((ÀB¸ `P ÄpÁ}]Ãýs¸ ŠÅÁ¤½… jlÁ¹áÚïiÓO 1T]CMíú³½r fNÆáYÈBˆƒcËúU|ð¯¿bñÔ“î´c2™ðúü¬+«£RKfiÛ‘$ÐJ¼¥•ý ö•hñáIJeYû‰¬Ú²‰y1»˜–eÅl„$§_çnžàÇ$-á‚þŒ¸¸øa½¾‡³8¼üˇiöv°cñ“ý¶ÛÝQÇ%_þ‰Ïj7¢v¿¡J³Åó@Éå\>ö¸A_WÕ4nYûwßö6m>Vƒ™óòðäÜëp­ƒ¿?o}‹ß¯™5§þ‘é ùûÕÀöÖJNýè~^|&Îøþ Î}¦ì®üê1f'cÅÉØï±!„8¸âââмíцbðlyŸkþtW´‡!„8 TíÝÍ›Ï?B{åVâ-fTUcSy=µowÎÇ×ÞˆÃ\ –á ö•fê Ó™Á+®Öl^Íì¸:ŠÓº|KqšðU®á¡_^¸™ÇqÁ7Ê ÌB ƒ8|¿j-k›v’“Öo»Í»9þÃÛ©v5‘dqrlú¶µVòmÓ.¾¿üv´Uó»©ß‹øºg|r7oU¬Ä¤9:u“•kÖóüÎYß\Î'‹î&ÖlÒ}5zÚx¦ìƒ!Îÿl~cHçmm­àÇ+ÿ:¬cBqpÅÇÇ£¹$p(Äᮽf%ò‰‹‹‹öP„‡°¶ÖÞxîa*7/'ÁiÃé° i»k[©h…¯˜Mie3ã, °“n"¥ ‘®4PiÈáéÆbæ7®bFR'y ]™©Úuïpç 3ç„ïrÆy—”q q¨ŠZà°ÕÛɲšoy¿jÏïü8¢sîXÿ Õ®&æ§L`Ù¢;±º¾=xºô=®þúqîÙø*W;‰,{RDý½¹w%oU¬Än´ðé ÷0+©€]íµÌ}÷—¬iÜÁ_ËÞ㦠‹#¾/¿¦²¢~;ïU­áåòÏÙÝQñ¹áìj¯å½ª5,­\Í¿v9è󽪟‹¾xˆöî•B!F—ÔÔTRSSÑ4 …Þã ½iÉŠ.)3(%YO—úè÷ûÛ†0íýjïµ F]mÅ0)™J5JaÞŸúw"µz¨ý÷íOR´iuÃ;Øú…a…ym÷ô¯©jﶦoëÛêêêÏÕ÷ò\]ÿª¦áÚ¸”뼉'Ïý !„Žßïç¿/<Á¦åok…«UUiîð²³ÎE©mìôc÷íÀjµÂ~fé • ?©j «½¹|^åäØºULOv“âƒA!ÞÐÎÚ·žfå²%œxþ9òØ£2N!F»¨kÝ-d½v>Í?pãnåµ¼ºû ŠÂ+Gþ24øaá‰,­\Å¿w/çÏÛÞæîiGÔçC[þÀï¦~/4“Ês®åœOïç‘-oòã¢ï`TÂ|ëcч·óq͆ˆïk -}~ýø~õqëºçYÙPÊ„¸l¶´ì¦‘ !„8ØEÁÙ¯#!Ä!ÊÕPÉļT’’"û¢\!ã£7_á«·_Ĭ¶c3PU#ŸÊöÊfc‹xµ:])³¬Ñ öeöwbs7ñaŸwXhû–©I^&0› ]•¼û×ß²ìÍW¸íOG{¸BŒ:Q š§gÏ ü\ãjæËº-ýžóLéø5•ù)Èq$ïsü¼Ü#ù÷îå<µý݈‡Û[+YVý-çæÎßçøiY³ˆ1ÙØÙ^ÃûUk99sÆ€}ÌK."ÁøyÉÞZŒC‘eOâÌœ¹Ÿ×4î`W{mÄç¿_µ–7½Áì¤q\?þ®øê±!E!Dô™Œ2wMˆÃ™kýn¼û×Ñ†â³æ«ùàŸOâiØÁhD5QU-{›qÇäñ_õ(Z7nAu•î߬ðÈÔYK‡×Ë’Ø)¤$•SÄ^|šŠ_S¨uQw–F{ˆBŒJQ &Zœ¼~ô-Ÿ—V®æÔîè÷œÒ¶*NÊ( yü¤Ì®ýuîZ¼®`\Ö^ @3=äªÌVƒ™…i“y«b%ÛÛª8¹ßÞzÝ_rYÐ϶—ÏÇ­y#<{_§eÍâ´¬Þ ë¿~œ¿–¾ѹuî.[þ0“•üŒ¯ê·yB!F»ÅÔ›¾ˆ>ÅW ¤+ëSõiËA+,Gp­pm‚úé³òë`ú'ÌêÏC5ÜéÆCé8Î-¡áý±1¨«»PßÔcM·JñÐ/¤…ÜÖÂl«aÚëõ¤ík=ÿõiÈôþ; JIîol@ûÎÕ?g û¾wBˆ¡Ø±u#K_x„Ú²5 (FPUvÕ¶ÓaLdeìÙìÝ[¿sŠyÆ`´ÌʵsfÎV¼mutzUÚüvªjjqšU !>÷ !6"G‰Deg#Ù!f$YœØŒf\~/•ýÙC÷j%Vu·m®øê1*;yzîõŒÍ”À¡BÆäd±µ­‹3è h(šˆ8ia‚yú „¾aDª0QÁƒˆýÔ=Ô·ï¯Ýp™s$‚EkŒ‘Š‡Þ¹xý)‘öÙOÀ0D“» üÓ´ ÚÖã qnпýk¹OPP_³PÕ=µíûò{:ÑÊ>æºÛþ¦…BD®¡¶š%ûåë>Áãq£( ƒºV7 +UYßaC†R¹ƒÏÃH&9Œ\8À½½ µÓævU5ãPˆ³v}‡£FËWsBŒ,£'pèê Þ%YœaÛ$Yb©èl ÊÕÄ„¸ìþûë&[cöé9Våjìp£îñmo³dï ÎÉ=‚« ¥¬B*Žš7‹5ï—b7;ÚCBD-+_åΛoÂh4ߢ/BˆÃŽÛåbÉßfËWïàîl üÒÖéaO“ŠZpË;Æb«©Äâõ2ôܹƒÃhP8s‚ Ên¼®N4£‰j—‰öæ:âLªJ 詚9ýBŒ,£&pXãjªØW¼ÙAEgÕúzú‹ïgfbϱ*×èšq¸¡¹œŸ¯~–l{2OÏýQ´‡#„bÍžY‚á_8âpÑ^µ©¹ L™2U?ûQ!"¤iï¼ú k>|wK=¾îÿK|~•íUí²KX™<1ÕÄùêñDy¼‘(N†E‰•øÚjQý*£“Ý5hÀç[))H&ÑÒuŸ~ÅœùÇEwÀBŒR£&pg¶Sçn¡ÃçÛ¦½û˜#‚åàcÍ6:üýõç ÆhÌP£Êå÷rááöûxnþû¡)„bô)((@k«y¬g’>°`2›ÛúJýŒ%¿®½ÑhìÝïïML2èj%*aRžénô}~¸™QŠ6º¿s†"’³†cþV¿×Ñ4ÜíMX»ṠBëî§ëb¡¯îïX‰à¹ôs0Ôôᾩ¾!ú Ÿ°«ï&Lºqcѧ‡­e¨{ý‡MsÖ×)ì©_¨OOÖ´Þûë{Ÿºz‡èÎUµžšˆÝ}©~\kÿÃÍ}UUIII!%%%Ì !ľ–¸„/ß|ŽŽºÝ¸<½ÿ·m¯l„|ʦþƒ»…Do=ÞQPÔ#Þ§ŽiÆÚ¼ µÓÁlgWM&_-ñ6X¹£…Uë·’—:“ØD…ä܉\ô£[),ší¡ 1*šÀaº-²¶j…Ù`Üló0‹*3ºS,ƒÛö™©–~Ù_ÿƒZ sd+ø2(âš½+æúÙùþ3¶1£0?h¦XB| &{Z\¨5ÄÛ*;cH1vMRU°%årá~ÎÄi3¢û—ò»7,'..Žf¿‘ζNãã±ÛŠhl¨§¥j;ŽÎV.ð¿@…ó$66Z†ãvƒóëI®[ާ¾ U6ÍAuE 1f•j·÷W–26'”,~£9'žÃü ÚCâ3j‡³“Æ1=!ŸµM;¹{ëÜ>åüÀ±­­dmÓNN^ö{®*<³ÁÈ ;?áíÊUdÚùyñ™ûŒãá-Khð´ñÇ%pø~ÕZÙú&v£E‡B!"rþY§sçsïb&]Y>w'eK'Ö×ÀÜɘu«XGÊáp0cêDêêëÙöÂ/I˜q&iS¤þðáª}Ïz&&ú8ÿÜs¤®¡‡¨ÇœÇ|¿úðûý¼óï¿‘l‡â¢žzy)ޏ®«o÷ IDATDâ} ˜¬ÔÕÖÒÒPCzv>ŽŒqxj¶’’ÉêÄÝ\AÅæ/oYÅäÂcù .¯wàkhN“ù† xvƒÇçÅh²°·Åƒ§½š8³u»ÚY¶b3s¦Œå’ESP¬±œtÁ5LŸ=?ÚCâ6ª‡§dÎàßGÿšs?½ŸÇ¶¾Åc[ß »pÌÑümþOÕ_‚%†e‹îä„Ëgµ›ø¬vSàX®#…Ž¿ƒçè©o(„âЗššJjj*ÅÅÅÜ÷è3À‚_UQºÓ ºà•>ð”Âì÷‡ìß§›ífÔmûõõu³éŒÔJ샢(Áuì”Þzo½;C§”†Áv÷À3þ4-tJkØö}~Þ³ü5¼e_2©` qqãÕW()ÉÉ$'%±k÷'l^»”ì®!&57øïPŸ¬»Åî7\Úr8Aiíºç>l}Ë ‹éSuõ YpŸTè@ŠoèÔjŸþu®Û.…_âþpiÓªªêÒ5]Švï8U¿?0WS5ƲeüæÉGIJJ"5Uf !öµzùÇ´WogÖÄB|~?­mml-ÛE^vÿ>2ILËfÕªo((OSs;9i‰8cMy쉸êwѾéNHH¡"uŸïNxÀ Àtû^¬»—ájmDSýtbg÷ÞZâ¬*5.xëóuX-f.9ufƒŸÂY‹8çÒk#šá/„Ø?  uvvb³Ù¢=–ˆ5yÚù²~ +ê·“ëHæÈÔ‰Åf ¹?ŸægM㾨ۂËïáÈ”‰ÌN.Äjü¬±ªªªÈÌÌ$>>ž¦¦¦hG!F´K¯¼ŽõÆÉØ3@é ég½tÁ?«µ·ô†>à§_(E®>p¨o3ØÀa}Þ܇z¯ ‡A58ìѸk=5Ÿü‚ìT23ÌŒ^¯—­¥;i3&‘wÒÕ˜¬] b=¡‡û[/²›Ià0üɺ6C já‚…õAÁ8ôû|úÛ y}à0ÔÂ.=C¿ÇEÓGæÙ?ÿ‰‰‰¤¤¤HàPÒü†‹Ï[ŒßïÇãñàñx¸ýÇY¹¡”N8‰'â÷ûÙ¸q#¥¥¥8­Î=a^¯ǃÛíÆãñÐÙÙ‰êj¡½nh Yãø¤£˜mu><^¯7pŽ~[Ó4, V«5ðèùYÿ§ÍfÛgß6ãýLö­¦½º¬kµd£•­{›°i¸|ðáê¬ÞXÆÇÎdL’Gj>߽ꤤ¦ üD !ö‹ËåÂn·ÎÀ¡8tIàP!"·víZ¾÷£ÛH<òr î³{ø‡îÖFv-}Œ›Ja~Þ î}¨ZZ[ÙRº ó˜¹dqNpýC :C¿ŸÚeáÞ_ÿˆÉ“&HàPÖåg.ä¶Ûn##%¿ßÛíÆívóâ¿ÞäÃ/VRßÔ†Ñd$9Þɤqy5{ …@±ï£³£ƒ«žÎ–:Å€!k:oìJ¢¡ÝsÀ‡)±fŽMªÄXó-~ŸEQØÓ¤ÒÖ\Ílà›íµüçÃo˜5¥£§ä‚É‘§_Ìœ#öÓ/Äa£'p8ªR•…BÑ+;;›¼$+õmXb“‚ÓX»é·õ W$«Í†YUYŸÂ2 ¥:õM¹ ŠMu½Ÿ@RÈîÄÁiÐ}Ûë³¢C¬æ²/ÕOùGÇX¿•ãò±Ûí7âbc™S2…ʪl{ñפ,¸Ä±%@ð½‡Lû+‚ jPNyP¢s¿=kh¥!÷v:˜6@¨ß“ž¼?«'‡ †[U9TŸAALMëMgîs¯úößü“+Î?¹sæ^_}@Bˆ‰N+/¾ô 7Ýp5F£1ðÅàÅßýç->)0£Pÿ(ÝU×`×F|F"~¿–Æ:ëªq·ubs¤bµÄáoÙƒoïjÎuư'm*K¶ ïØ ,Hi¦@ÝŠ¿¶¿êÇ£Ø)ÛSC¼U¥¡ÝËëËVãr{øÁYG“è0’Q4‡s/ÿÑAùÂN±/ Ž2š¦ñþο^~§ÓÉ/n¹©Ó¦E{XB!¢@Ó4~zÝ•üìÞ§°,¸$\£ÞM5ô »H*aƒ1á‡=A(M ì×tû‚g.uˆA#ºÛ^µ?£iõåç2uâ Ç7\23ÒIOK¥tÓ¶­\Bî‰×b‹×ÍFë¾-%‚çTÿÏäÔ¿VqnŸ.´½}¯Õ;Æ zŠõ?k}Û÷9®ïoŸmý¸ôç† ö †¸‘ UÝØÕC}ëæoþÅ÷Íàì3¾ƒÃá %%%ä8…¢‡Éh¢¹| »«ÈËHÂh4b±XÇõÿg•WÖ²»¾“â© ÈÊÊÆårÑÑÞŽÝá ''‡˜˜Êwíä£÷Þ¢vçzŒÎì¸élØKªk9×å§²¬y ßìÞÿqÆy91½cg ~¿ÅdfG³¯ŽD;”VwòðßßæÌEó()HÅ›Êé—Ü@Vvîþ_\1d8EÞ{g)}òqrÓX0}<¯—Çø~ƒ›ó;ÆßÿÂìB!F—üü|R­^\-XñÑÎ!£½n{?x’ìDgNÅ× ã òÉu¹ØüÞŸðÄaÌñ?À`’šÌ£UÓÊqÞÂ)\pîÙÑŠb‰MΠuw5¯þóŸÜtÃ5( ˜L]íõ_RlÚ¾‹­•mŒ;Žß®eÓº•X Øí1hšÆW_~ŠÝd$§°˜ÓÎ:ŸÞ§tí§h+Äåaõ5ãn­e¡–¹Sòxi»“ÝõC¯EåÜñ­äkÑ<>4ƒBu»‰¦Æâ,àGÁï»ÕÂÿ»j1&“‰© sÔñ§ çÓ&„" Ž«V®äÞKfrÿX¯F4ß À¢1>ŽÍlÁ„¿_Å•í{ëH°ªÄÙ A5gc-àÌžÄÙ—Ý0"ÿ q¸’ÅQF°ÒÒR¸çâÆå¦£(>Ÿ÷ê{=Û~¿ŸÏGG§‹²=5¤çpëíw–6úVš’ÅQ„bhž²˜Îñgaމú``Ò-vb ³hоf~ñ ýâ(ýÂ*ú:t‚j,z¬ Á`ºÿ ZCß>lG¡îÐï7D8[°âë%¸K?cBañqq3”ïÙËîšÒþ€¸¬qý‘Þ÷þ ÷wî5 ¯û§(Jð‚.!Ò{®Ñ÷Üp©¿z¾îÅKô}ì³Az²~Ûãñô;®pô}4®|3æŒåòK.”EP„ƒ¶üËÏyöîHе‚-ýâ6⽿§½^/.—‹›îü3L3f̘~ûܲy“&O¡tËzœ¾ú@mD·Ûê÷oÕp·Ô`°8øª=Ÿå•¦°‹£LÍ´pÉt#évªª¢j Ûª;0xÛ±»Ê8ô|®ít{èPœ,:ç*ò %‹Nˆ‘¢gq”ÐïüETUUUñ³¯ç‰?ÞÇS ˜Z”‡ÅbÂ`0`41tØ2 A»ÍJñØ,ÌîF®ýþ÷¸ùç?•à›B&þç®Ûi^ñr´‡1*5•odë ¿&µ}3sgLUAC€¼œlæMoå ”¾ñ ÞÎÖhIô£iõ8}V>—_ra´‡"„¥Ž˜$–„,L¾6žúËcx|½_N˜Ífl6‹êêj¶më…¿ßOMm;w®‹Å‚ÅbÁl6c±X0MÔwh¸­iXíNTOs̹qR c‚¿¤Š³j\?×Ì/˜Èrj ©Ôv(lÙÓD¬ÑÝÒ‚Ð4hhWɘzWþò~  1BIàpiiiáöÿw3¸ó6fç2¯dv›uŸa¨GO@Ñ`0ã°1© ‹öÚ\|Þb~÷›[hooöí !„8€ÆŽ˱³'ÒºsM´‡2jxÚ›Øöï{Q×ý“#JŠÉÊ̈ö†Ìd21±¨i9Nªÿ{/{>} Mëœ8øš×ü‡SK²¹âò‹£=!Ä(7eÞqøü]ÿÏÛ«xúÙç‚o2›Íœ}ʱ´µ4òõ×_óî»ïÒÑѱO?{öìaÉ’%´µµ±eÃ:Òã­AACUSPQ°X,x|*•íˆIíÊ>h«â$ë Î[Ó¬rú3œ•Ä1…6LFp«F6Vt¢ºZIŠ =´vzqÛ3¹ð¦û8îT©ó*ÄH&©Ê#€ÛíæÏü‘ò²mÌ+™HlŒ-~ܓЬOIì¾Ææ6vU7²è¤ÓøÉÏ~‰U—n6ÒHª²B MGG---œ|ÖEÄ}5SWm £©·œ±Y·­OO·­Og6…IsÖ —Û·¦RàÏP©Ê>Í9DêíPR˜5UeÏ'/`¨ÝDñ¸|G¸^F­êÚZJË«ˆŸ}.ÉãçDô<ééÓji½÷p©ÇºTh}ý~ýkƯO³²_—¬†K[î3æ^¯7ô=鵚~×±–¯_æ‚çrý5WÝGLLÌ!ùBXüäò3I·v`6›1’ÇqÍU?Àdìý=ýÙò•ÜóðÓlÚ¾‹„„ÒÓÓq:(ŠB{{;( ä¤%rü¼)$Ä:hhj¡]³‘œNBj&6«•¶¦zj*ÊÙ¹i%šß‹Œ8îöFòÆOâÔãAUý¨~í5hÞNìf)É~¿·ÇK]‡ù§]LÑÄÉÑzú„èIU–Àa©ªÊßžý_V,ÿŒc敜;¤ a¤mkZØSÛÂ9ç_ȵ×ßXyk$‘À¡BìŸO?ûœ«ó0ÉG|èSË0LÑ& ¨„©ƒ8ÔŒz‚‚}·u炈}V!‡aÚ„.X¨S·u9-«Þ`ü˜,RS’êqTÓ4²]»©löyüq$vϨŒ .dP½¾Úka‡ÝCŽK ³?¨ŸpõuÇC]W_×PÿZ W§P_˜_ S§0(èè÷‡lÓ;^ MÕ×ô¹Ziüôî¼ùÇ\pþwCŸ+„C°ìÃ÷yõ/w’kÀd2a6qÛ3¹æš«±YzWYöx<|ðÉrÞýø öVTS][‡Ñh$59‰´”æL+&?'·ÛÛíᓵ;ÉSˆËå ,¼YQQÁ”)Sز~ õe«õcí$˜=Œ+žÌÑófP×5M$Ç(ACUU©jè ¹p'yA4Ÿ6!D„$peKÞx%o¼Ê¢#çžqP¿(Š~ŸþgŸÏ·Ï>ý£¢¦šfß¿òj.ÿÁ•agŽDƒ…bÿyÞE”ÇÍ&&-_‡Ý:*©øð)²lŒÍË šy¨s»Ýl-ÝE»-œã®ÄhéÍ<Àá vÖï¡ó›—xèžÛ™={6)))¡ÏBˆ!zâ‘ÙñÕâcºÒ‹M&.#ç_xcÆä]ÿÿ¹ÝîÀ‚'=A?ýÏ==•Õ¼ûõvRÓÒ˜7o^е֭[G^^.Û¾~‹‘@ªßÏìS_<™x«†Q ^ü¤¹ÍE›Çiß»†ØQVGXˆÃ™£ä³Ï>åoÏ<ÅÂy3˜P˜·ÏêÈû“’<¨¶>?ßn/'61·Þý0ÚOK€…bÿ­\¹’˯»‰Øc®ÅlíM<‡~¯‡Ýü•O  ó±X,õrÈjjnfkY9æqÇ1óT@‡pà‡måk±íþŒG¼—¸¸8RRR$p(„vªªrëMWÓ¾«µ7xØÜÚNê˜ÉœsÎYX­6TUí7p¨ÿùÁ§_¦Õ¥r 'PTT@YY6lÀàïdRvl m»ËØ‚ 9£ˆ¤c X¨ª*n·—½Mn¦uSf̉ò3%„, d6là±?þy3&1sêD@–ôã¡ìóx¼|¹f+uÍŒÍËá£/¿‰öÓ C!„Ø›6mbÓæÍÜrÿ¤{u`¿YW§0\]à`¡n[p †ª_¨Û¯)Š‚A \Ôôuët¸ôÇúŽ«zõR<Û>¡¸0øøø½žöVT±£²ž”#/!.§8°_ÕÄ"ÊF Æaס0µQËPSÕÞÀ]ß:ˆÝÛAÁ¿05 ÃÃì÷… † nö|HîÑ´ömŠb;xâÑ?’‘1zÝBŒüæ'? ÏéÆb±t¥-›ÍØYÝÆÑÇŸÄ‚óѺƒ‡Í>limã_o}ÈÖ•¸¼*f³™»…ôÓ‹rASq¹Ý˜ì±L›<‘I9ñ]µ u³ +êZ±¦ãä³/9¬fù q(‘ÀáAR^^΃÷ÝÅÄÂ<Ž;r.4`Øo[ŸŸU›ÊØRVNIQ.ùY©Ô´k¼ôúÒh?M8Bˆý·iÓ&þýÆøÇÇ[ˆŸ~:pø[*¶Q÷ùßÈÏH"'+3DoÂï÷³}Ç.ê>ûg;“+.»˜””RSSCö#„é¼¼œÇü=qÞâtiËf³¯ÇÃî7óŽ˜Ïœ¹sQU-là0’”æv·Œì\æga5œ–ÜÚI­ËÄqg]NrŠüÿ'ÄhÖ8y«c"êëëyàÞ;IOtrã`³Z½ž7ÃF£Q·ÚžÖïþH÷iš†Á`úYõ«ìÜ[Ë+¿%/#™³Îè}³/ßþ!Ä!ëœ3óíúؼg=19S¢=œýâooÀß\‰1>£3tº§·£…=ï?E²ÅÃüéÅAQÌh42a\¹lyï!|IãÉXð½ À±œÎÆ :¾y…_ýèJŽ\pD´‡#„8Ìäååñû?<ÎS>H]éJ2z9bb˜OKÅþüðdçpļ#ˆë·ÜDßc>UÃfgö¸²­€!€ß¯±£º•±%DZpÞ‘ô^…—Ì8füñÁûÐ<\xöiÄÅŰ„}ë#†Z¥º¶·?ú »ÍÌQÓÇ‚Š=j;þñÚ[Q|ƂɌC!„صµµíšš®¸î'ø'Grïì;}Pͤ¯_¨ßÖ}¹dÒÏVÔ—ô¦@ë0_J)œ®¢v^¨‡Þ¦ 6¿p+6›•„„ópL9ƒ¥»~£¦Rù嫘j7R<.Ÿ˜˜˜×áÕÕ5°m×ì“O%©xAÐß“þoS¿?ÜL½PúÎ2 ¼ U»°{OµŸÚ‡úY‰=üúqEP›Pß·~¶bÐ,Fݹû|ÀÖ4Z6}H&Õ<öà½$&&ÚÄÄÄàp8BˆƒéÝ·ÿË'ÿ}‘üD‹%xö¡ÉdÂd2Q]SO]‡FBR*)iiäçåR™CÍ8lîô‘’œÌôüÐzgúý~*j›qYÒ8å»—É—vBBdÆá0óù|<ù—?³sû&®¾ä<22Ò½ážA¨ß§?Ö³­( .—‡7>ø‚ÎŽNŽŸ3›Õh§(Jï¶Ì,BˆCŽ>5²¾¾ž?ÞwWÞðKLÇ\É „_4BO¿W8Ñ ºàо½~”ží¾‹\„¼fŸÀ¡´í\ÅbÆn·S^^Nbk+ñ{×3õt\>¶5o0~LiÓ'÷Û·/%%‰ääDvîþŠò|ô÷q¤ä„ "êtý¥’ÁiȪÚð‹àµ§iZè×M˜ýú b¸@g¸z[úñÝ«>è¨;×ÓZOëW/rÃßãÆëÿ²O!„8ØN:õ;Lž6ƒ—žý ®†ÝŒM þ¿RQrs2ÛLTÕV|¶ ÁŽÅjÇh2aµÙp:øX¬9>™X»¡+`ØÝ][§›òz7óO½”ôŒ¬(Ü©â`Àá~Ò4W^ú¾û×^~>ß?ç„ cªªb0‚|¡öõ$LàÑãñðî§+رk/ ¦#)Þôæ¼o­©þ?¾ !„8$%%ñè¿çÇ¿þqG_ƒÉ6ÊfäµV“‘‘ËåÂétÒÐÐ@{G'iê›$ÇÇ0mÖT)¼> Eal^Ù¶~ówöâÉ8öA+s‹^­[?#¦~O?t“&MŠöp„"Hvv6?¿í.öìÙÃëÿxWýn ÓCü·X,ÌžVÔ»¨ŠÁ@kkÎ;iN`†!€_ÕØ¾·ä‚Yœµøøƒy[Bˆ(éfûá½÷ÞåÊK¿GºCå¡;o¡h|aÐqƒÁ€Ñhì*ß( ·Ï`0„Ý×w¨}šªñÕê<ùˆ³™8ëøÙ¤&ÅØQ‘—€BrrrxøÞßÒü铸ÝíÑΠ(Žd CàCKrz¹cÆ2½¸€Âü< 3‹Å”‰ã™še§þíû©^ñŸhiDñu¶ÒðÑ“œVËÿ=ùiiiÑ’B„•““à ¿¼Ë~v7õæ\ÊêýÔµzû=Çh4’’’Ì‘³§k:V]ßʦ‹.ü)sŽ’ ¡‡™q8+¿ù†Gÿøgž|,ßscèà›>P7˜ôãÁÌ6TU•­¥å¼ùágd§%rî s€ÞÙŽú´ä}fjHª²BÒRRzQ…‡î¼•ŸÞz7)‹~„±{&™_ŸŠªKç —Î¬OùÔB¥±* JˆÙ튢µïI3UtýhšH5í9×›Jù×å8bœ$¦e2¡ Ÿ„„øA=bðâbc™[2…ʪrÊþõ[âf}—ø1ºEvú©OØWÏûNªw†Ö½bq¨>ƒVXÖí5®piËÁu u)É!†ÕR¶óÞ¯yäŽ[ÈËË üû’:†Bˆ‘.--«nø%š¦±fõ*Ö~õÞºZ’b<䦯…<§g² @§Û˦ÝL?z1sóÇÌ¡ !¢LG„mÛ¶qÿÝ¿cÁÌ)œ}Æ)X,–ÏÑ4mH‹¢è÷éAéùSUUöVTñ×ßÅb2pôÌ¢}‚„=×ïys*€XÕùõ÷¤ ’,Ž"„ΦM›€®ßg¿úýH:î: f&Sï÷ˆúm}àP¿?ì'ÝÛŠnßíp³]àPíHjÙò9®Íï‘›•Anvf¨ÓŦª*Ûw”SÓ®’z̰ƥ„øéw= œè‚=_ªöÝßßµõ5½ëëaFÄ ZTן¾~gÈë5;éXû§·€«¯¸,0þ‰'ö;v!„é¶nÝŠϗákk_f|äf$‘›‘ŠÅjaÙ7ÛÈÉLÁœ\È‚ãOöp…‘,Ž2HÿûôS¼þÊ üïc÷ãŒø¼žY‡C©Wj6¢Ñh¤­µ¿¿¶”††FŽ›Ý»ð „öôj¢¤w !ÄágüøñÜÿÛ_rËÿCì‚ïcŠOŽöBòv¶Qûés¤XÜL›15(x).ƒÁ@Qa>y.›?{‚zg.é .Â`<´ÿN¼íM´­~âìxnþó$$$D{HB1¬ŠŠ&PT4!ð³ßïgã†õ¬Ú¸¿«‰6¿‘yg\%„8ŒÚïö†QSS=ÛËvò³[ïâ®[~Bê Vê úõ,ŠÒ7Õ¸ï¾pÁC·ËÅko/cݦm5£ˆä©cûMCî µ_“åQ„â°4±¸˜'º“ÿê70ã<ì)yÑRê¯a­ÛĬqùÄÄŒ²Å\a6›’)ihldË’»0Gò¤…ÑÖ°Sý^ZÖ¾E¼·š‡ný)cÇJZžâð`4™:m:S§MöP„#„#äŒqrÖq3Ø[ÛÈ)ç]ÁEß=ƒ]u¶˜ÈfꃃúYˆ¡öég ü>Ÿ|ù oøÓ'är΢Þ:†á°o1Ô>E‘À¡B.ú¦UñÙûorúYçÓÜ4›˜ü’ TM“ÙØöù|mýlu³®l‡~»¾ÒÖ4Ç]Q‚j"öèùýä)ý‚³gJí¸*)1‘ù³Ùµ{»^ûçìóq¤Ž ª‡¥êêUêÓ„Ã¥ëišH3›z¬Û­O=öë^«Aõ8õµ û©«Ø¶íK´òåüìº+8rÁ@R’…Bqø’•1"dµÙQ…Ì”DΉ´Žá`Ó—y_,„‡½ää®ÅQ~zãuL?–»üöç—]ÔÛHÒ@o IDAT/R¢_‘6ìJʺßA½M´ž6šÖ›®Ü½RnJR"õõõØl6œN' 444““C\\œ|ñ59Nf—L¦º¦–moÞƒeÒ©ÄæMB¯–RˆôdM—òŽþu.=9è2>/­[?…Êu\zÁ¹\úð?°èÒî…B!D FÈj±¡ªG v·ÆÆ² ãä¤ã°qÚÑ%Ô7µqö÷ÌⓎáÇ×^#.iŸ~ú {jº].^ü×>ûjGÍ,fæøl ÿ:†¡…:¨ªMWEãÁ{…BŒH=C€Ù³fñüÓò›;îeOåâKÎ@1(¨þÞ`Œ>p¨¯WT˰'(¨(Àaߺ†J`sßð‰‰‰œzê)¬Y³†o¿ý–ôôtöìÙƒÙl&77»Ý¾ß÷.†_zZ*i©)”îü‚Š-;÷"̱)¡gŒöLìyÏ¢F8 ª›¦–¡AQð»ÛiÛôææ]\}áw9éÄ¥~¡B!D?$p!«Í† 8v’°`ôwÐÒæbí–rÒS“™BjRg/šKéÎ],:ûr~uýe,>ã;-Álô«,k,ûäsþþÏ7))ÃwOš?¨@`¸ã×ó°Z­õyB1ò9NþøÀݼ÷Á2þòÜ#8ç\ˆ96åà @ì)))¡££ƒ;všš €×륬¬Œ¸¸8233ƒ™bdP…qcÇëv³y͋ԒˆŸó] ¦èÌêó´ÔáÚü>IÆn½òRJJJ¢2!„BˆÑFÞiG¨+}EÁn·c´[i«w>ØÔÔ·PßÔFnFYiIŒ“ɸ1™¼ôúR{öþçö›˜>k.бëéîIYÞ°a>ù9iIœJoÀp¸Ò ¢`“À¡Bˆ0N9éæÎžÉÍ¿¹“zûX⊭€|àtýþòz½(ŠÂ‚ hhhü>ôù|øý~ZZZhii!--””I_¬V+Ó'O ©¹™Í?Š'k =(×Vý^ZJW î]C~F?þÕ•t“z™B!„‘Àa„¬V+ 1±Ž\MÕûÔÍÙ]ÕHMC+ùÙ©¤&Æ1zn¯—_ßóiI‰ÜûOÉSDee%÷<ü4~¯‡³Ž›ƒ!Â@!Dž†É~P0™ÍõyB1²ï³ï£wÿËo︛ÿýö©g`ÌëMí4{K^(ÝÁ˜Hß ÕF1Pº‡qqqÌœ9“õë×3sæL>úè#RRR°Ûí´¶¶ÒÒÒ‚Ó餦¦†ºº:rrrˆô=‹/!>žy3§²nÃZk p$g÷Ô½Ÿ •¸¬úýøôµ4õ_C÷dšF{Åfü»¾&Öäá²ÓNâä/ÅjµJJ²bØhõ ø¾Y‰iÁ(üÞÑÚ;ðoÚ„ƒqBD¸“ÖщðX0¢8cöwèøV®À4kfÄçø·—¢54b,’?`{­£uûv´ö ã 1¤ Oæ‚ÖÖ†ïó/1Íž‰¢+µ–ªâß¶­­ÓÔÉa=[­­ÿú ²21äåîç¨Mãÿ³wßáUÖ÷ÿÇŸ÷}Ÿ}²È&„°7Pâ:ÔZ[ªÕZkõ«VkÕªÕª?­mµØÖ-jÝÅ¢ 8Y 2„„0Bö>ó¿?9ä˜Híûq]ç29÷8Ÿ;á2ç¼îÏçý6ŠK°ÊÊPóú¢fe¡›±B> ;Éáp`Xn·o¯d>ØVB¿ìL¼žØeÈaÝdëŽröV×Ó?;x¯›s&£¶¾‰K®¹ÌÌt<žxN?qWäZ=± ¹3ÇØíR\!ÄÁ]òÃïqþ9Óøóc³X÷ÉçÄý>Žø¶µ|»…e ¬^½š1cÆPWW‡ßïÀç󘘈®ëTWW“’’Bii)n·›œœitqŒ ƒ466âv¹h²º¶Ÿ¿z7ÁíK°7ïåŒIùÁ¯n#%%Ef !zDðÅ—ñ?ò8 ïÿmXÇ7%Ìâš{;ú«¢7=”8/ö3§âù÷¢tP«7üþøÿò(ƶ"hõÿ1û™gà¹ëöà ²t¦ŸýÛˆaĽòÂwµ‚AüwßGhÁ‡XÕÕÑç3.Às×()mߘ•øø¡ÿ¼s£G:Ï=wa;á¸C;úÏñÝq7q/=‡}Òɼ…ÿ‘Ç >ýX !„è4¯×ËÝ·ßBYY÷>ôÕj2Éc.@éæºu-3ìv;º®³zõjE!!!ÄÄDü~?MMMÑÀ0>>žæææh­Ã­[·’””DïÞ½Q;9«Ct¿–eåõõõÑOA‰™0x8BM5øŠWBåFîÏoü ùùùò;Bô(«¾žàëot?}ù4ͼËïGÍÎÂvüx¬†Fô_z{fÑv➪Møxú9ü÷=¦‰š‘Žm XMÍèËWþ`! K—‘0ïÔ¼¾‡4þà«o`Õ×ü:›šhºâjôå_ ¸ÝاLª­C_û5¡ÿücË6Þy#fŸUWOãßÇÜS€6xjfáÏ—blÜLãE?&î¹a?mÊ!Ý ¾ør§öm¾æzBóæƒ¦a7%1}érBïÎÃ(ÜBü›ÿFé•sŒ±e+ÿ«º%)Û„0·—`n¡ùÆßb–îÂuãu¯¹£”¦™Wbl/»ۉǣææ`¬ùcë6šo¸£p îÛ~Û¥ŸƒGš‡äp80Mp¹ôJî…a‚ÛåÄåt°ak1ñ^ù}³Ñ´Ø.ÅÕuÍÔ6”—FVZ/U‹.áêjØÑöƒ'K•…B®ÔVKŒ222xûß/ðɧŸqσ`öMü “P£µ|Õ˜îÉÑ/[Ÿ°Õójë¥ÍV¤ƒnEEõõõ$&î_‡£K•·mÛ†Ûí&SWWGNN~¿ŸÝ»w“M]]uuudee‘””$õ0˲hhh  ÅnPÀ0ô˜.Èߨ9¾Õs-¡£¥‡iܽ ³lš¿–ýûpÙ•ròÉ÷Çü~[‡2ãPÑ- }í:ôÏ—šûæî=ÜÝ h¾å6,¿Ç÷gàyð(ûjË›e{iúù/Ñ×~ÿo³ðüá÷û_fÃ&ü÷>€ëWWãþÝÍÑmæÞrš¯úúÚ¯i¾þ&âÿûV§‡oÕÔ^²ý³%ß~§SÇøn»}ùhCÿÚK(ûþ[¶Òxá06l$ðϧq]÷«è1þÂÜS†š‘NÜ+/  ̼~]=¾;î&4÷=šoú-I«–Bg›YƆ„?[Bè½ù…[zˆ¾ty$4´Û‰m6¶ñã0Ë+h<ÿ{[·œý ®ës\à‘¿aUWc7–ø×_‚}Ÿ•ƒ/¿Šï¶;ñ?ñ$Ž_‚šžÖ©¡7ßú{ŒíŨ}ûÿÚK¨Y½£×xæyü÷>@àOc?íÔÞ‰)DO’à°“œN'¦eáöxHMIŦiäfeļQ]½¾Ì´òrz·ù€ÒÐ 7SCÁBÓ´ýwÞb€ˆv‡‡B!®¥£qk3¦_È ‚¼¿àC^xí ÂIHr*šÃ bkF¿V"³ÏÐ4´–Zu¦‰ièøƒ!–-[†Ûí¦wïÞ”••‘””DQQn·›üü|;wî$--êêjìv;999„B!ü~? ìÙ³‡ŠŠ rssñz½ûgÝ‹¡(JtFhG ]ÇÐõ˜c¾ùuËï)P»‡Àε˜UÛéçdúÉ'pÚU¿&++‹ÔÔÔ˜@[!zJã¥3Ñ—­èôþ¡9s1w”¢ææÄ„†jïL¼û+ SÏ%ôú[¸o¹ Åë øÊ«ØN<>&4P33ðþí¯ÔO:}Íט»÷ fgt,úš¯i¼ð±õaª®&4o8ÄÍ~6hqþügŸEhþ‡1Áaø³¥8~tQ44P’q]w ¡¹ïaÕÔbn=àïÖš¯½Ð»ó:=v€ÀSÏàºöêhh f¤ãùóƒ4]v9Á_ÂuÍUÑpÐܽ›Ðü@Uñ>ùxôyç/!üÉg„ç@ð…—pßrãAÇ`–ì@_º €¸'ß( ®+/G_¶‚ð‡‹Í›/Á¡8¦IpØI-3Ý.)))8NªªÉÊH#!ÎKm}#( ºa²ìËõôï“MVÆþ7³š¦í»®D»*1bu}qI©¤¦$SXXHZ¼EU{.@DÁ!5…BEQ8ç¬39ç¬3Y¶bÿxöjm)Ä Ÿ†ÝsðâéížSÕ¨nçq())ˆ.E®¯¯géÒ¥ôíÛ—aÆQQQAee%~¿Ÿââbòóóq8ìÚµ‹ÔÔT,Ë¢¸¸˜¸¸8²³³£çݧeYr]]ÝÃÙHXÜñö@Ý^%X•›qÍ ”ÏÙ—ÆÈ‘7´YÕ!„GŠmô¨˜&(á…‹cj~“±i3öӦĄ†-´ý±‰¾úKÂïÏÇñƒïEŽ+*޼^«°«µHSÞ˜{Ê06mîTp¨Äy±O==ú½¹sWt| ¾þ„Ã8Î=µ‡®_ýûi§Æ6y1 ¬ªªÈøÛiº¢ ÌGIHÀjhÀ¬¬D£sÁ¡6löV³×õO?Ç :Üß,¯ ¼øcgOk³Ý~Ò”¤DÌŠJ ?Â~ö™‘k~íM0 lãÆ¢ff´9ÎqÎY‘àð•W;Û#¿KÅãFÒ¶ñ€}≄?\tÐ߇G›¼sî$§Ó‰n8N’““ÉÊÌ  P²«ŒÔä$Rz%’Ò+‘Šª4U¥¶¡‘’]e ÉÏ#¥W"šª¢ª*Š [辊²o6¡e¨Û‹¿b;jÝNÌæ*¼.þy}9ñäQLœð=zõê=¿ÌBMîÛn‰ù¾nàp¬`°ÃýÍ¥\ÒªöÍ…Õ_bìÜ}N+È}S&µ{ŒÕÔ„Y ç´ý;5v-qO?ý>øül|wÝ{ÀcŸ|Dš±´Gñ¸±ýÒ°7ŽðçK ½=ûäSbϹè#¬†PÕ¶Ç€ëÚ_Æ|_?a2Ö–Š›;w‚e¡¦¥µØiö“&zï}Œ’´Ì+lùuÔp¥åz¬ê¬¦æƒw¸v8°ŸyZ^_èàÆ—Q\R'—B-vR¤«2šë©®®âg¿ü5Ÿ´/W.§¢ª†»Êè‘Ffz*™é©ì*«Àa·Qºg/Ûvìâ”ãFD‚C‹˜à°¸¼žK.8 ·Ë‰aÑš?6M布>¨?_|µúÚ*zŹº5@„Háy!„âP ÒvÆÀ!C˜1}:Û·oç÷?ÌŠù¯¡f %nàIØ= ‘Z‡v† UMEU#o°N$¾ßxv®xOs))‰qÑ¥° 0Ã0X²d yyy““ ·mÛFFFýû÷§®®MÓp8ÑŠ999$$$ôðOè»KQššš¢Ý®;Ųh^ù®ä$† Èãôé'qÚ”ÿ£oßC+ò/„Ç"5'c_ÕsßìB«¢2úœçÞ»xÞðü FË€Ú/ï°ÇÙ‘–1©™˜{Ë ¿¿ýëõà÷GfN›ŠV0°ÍqΫ¯D_¹šÐ»ï£æäà8÷l”ôTÂó?$øôs‘}~| Jþí5÷]ÉHïpŸ–mVåþŸ½Y¾ï¸vf‘F*v;„ÃX•• í'OÄ~òÄ·[Á áFö6õ€çâh“à°“œN'†iâVì\øœÉ9 EVŸ~¬YµœÝ¥%ì)¯¤²F'§w:}szcš%»öàóØS^…¦ EÕÔè EQÐ ðzݘ–‚bß(îÐT&ŒJ³?Àò/×a…Ä{œ]©¨™q(„¢‡ôïߟ¿¾Û"Á¢cÆÝ8Ú¶ZÆdîÜEóµ7`Vµã¼ùø}÷M×·™ hŸ| qÿ~¦™WøÛ,›³Ý}Û-¸®ùEŽÝ*¯@ýÆÏ¼55)²ÍlZ1ÛÚ=®WfE%feÕa·VM-M?¿so9jZö“&ò¹„8$8ì¤HC“ÈÒâx+PÁºå;±Å§“W0Œä´Lâ¶l¤©±‘]eå(ªBNf:ùy¹èºiêÑ™†­gš¦é i膎ªÙ1-ÚÔÌp9ìœrÜ(›ý¬øj=n›…Çåh¶W;ñ›bô9Àî‡B!z–¢(Lœ8‘“N: ŸÏǼù xçý§h¶Ü(™ÃˆËÍé>à9œ ©dŸóJ7Pþå[ôÍèEÿþý±,‹­[·’““CRR7nÄï÷“––ÆÐ¡C)//GQêëëñù| 8—ËÅÎ;ÉÈÈ °mÛ6’’’ÈÌÌ”:zÐRǰ¡¡¡Ã®È}ï#„ßaŽïM'ðäS˜;JiúÙ•xºmð …}°ß÷ìoVr2V]=þGÿFð¹Á²pßx}LC’ncÕ×Ð|ë¨ÉÉxî¿mø0¬ÆFÂsß#øÚ›øú jnŽ Î‹9\_õ–Ï€âõ x¼Ñ€N_³¶sË|ƒY]yíÌjT#ÛÌÊê¶Ç%Æ·{ ©sYQ8vUøƒ…øî¹sç.´Áƒˆ{îŸ1X„8IpØ­›š¤'ºÑzvnÝMX󜕇«±‡ÓI0 tÏ^Ü.™i)¤§¤ ª*ê7j*­ „+(zÃÐQ4'˜m‹¾zÝN&Ÿ0ššº¾ÜPH²×Óao,@lyNj !„èI^ïþ-3îù‹«øå/®¢¦¦†…‹>bμÿ°§²+1Göâ2úÇ.eŽž¼ÙƒðfÝÆî5 Pw}Ivz2  QWWG¿~ýp:±wï^òóó3f ÅÅÅÔÔÔ°uëVúöíÛf–[]]uuudff’’’Ò£?“o«††‚¨éÕŠ¢˜˜í†Üú߇B|W(.ÞG¦éÊkпZKÙç¡ÄÇcùý ë¨}û`?á8Bót\Ñ4 ¾ðþ¿>ŽU_âtâù˃m‚ºîf…[u½Oˆ'~þ;1 Rì“NFIL$ð¯gðÿá~çž­á×|ýM„æÌE2Ï÷`;³¢ÿýúÏiÜZDÜ+/´Û€¤;(Þ¸Èu ŒF4Øt»ö‡U[‡åï¸ñJË9÷ov¶Çزßw£¯X DçxŸx´GCT!º‹‡] ìkpÒšCUÐ;‰fˆ;vÒ4±T'6·Æ€¾}ðùý”ì*ÃaÛ×E‰]ª¬(‘ó)šÿî6˜–nKGù0L ÕæÀ0ÚþÏ+1ÞˤãFQQ]ˆÂíôN‰CÓ´.ˆ¦©Ý(„BôǃÇãiw[jj*üðߣªªŠÂÂBæ/ú˜UŸÏÇgØ ¥?¶”~xRsQµØ·,I#¦¢LdÛ²×HÕIŠ÷””DII YYY$&&ÒÔÔÄÖ­[Ù¶m£F"77¯×‹ßïgïÞ½$''·ÓÞ½{©ªª"''GB­}MMMÝr.EQHJJ’åÉBˆï<Û¸±$.œ‡ÿáGÑW­Æ(.‰tS>~<îßÞ„ÿ?í×â3‹Kh¾ù6ô•«@Qp\pî[nDíÛµfc‡Bñ¸Q¼¬f®«¯l¿«òÿ]Kà©g1«ª"ו?c[¡9sQâ¼Ä=÷/Ô¬ÞÑýÕô4¼þ³¢ }ÉRBÿy§Ç–,«i‘›V]]‡ûXu‘•j«Ÿ½šš‚¹s×AŽ«ksÜA<…ÿ‘¿A(„š›ƒûæqL?¿ý›¤Bƒ$8ìUÕÚ‡-â½.NÚ‡½Uu|±¡˜šúf4U!5)žü¼\’{Åí›iHL˜íèhY¼³­Škßßŧå35ÃFpЇhv†Ñö®Ij¯DN>n$;÷”³sw½Ó’bf4(@ …B; Ä Aƒðù|¬ZµŠUkÖ³~õB|!L»¥W_l©y¸Ss±9½dL¹õn¶}ñoú¤ÆÑ§Ol6555Øívââ⨬¬äË/¿$99™¡C‡¢uúÚ£ë:%%%x½^²³³ÿg‰†A}}}·--VU•êêj d…ÿ3””<þ1òeÅEfK-¾ŒØ™wƦÍ4þðÇX hýûá}ü/h#G±1(iiXÍ;ÚïJLdÉ®š™Y¶£p Zþ‹?À6qBLh¸ÿ ç÷/D_²”ðÂz,8TöÍh7kj;ÜǬlkÚô¸PË·oÆáºeǾIóu7zwhîßÜ€ëW¿¥Éâ[G‚Ã.PZû(;#…ééɬßRÊâåk(.ÙAB¼—“Ç@Ó4T•˜Z‡ÑÒ2qÙ5LËâW‹¶’è´óôéæ#Â…@Õ@ÑÚ4PÈÊH%#­Å¥{¨k¨##9©Ýú†­D éª,„âØäñx˜4i“&M"7¼ظq#+׬gýÚOi† ê&†bÇY@Ic=¶½%ôËÍ$!!@ €ßïGQ¼^/ |øá‡ <˜±cÇR^^NIII4óz½455Eo®577³eËRRRÈÈÈØ³ï;β,¤îVWƒAü~?O>ù$ƒ·ÿAT!¾ÓZÿ …ÐW} €môÈèÓfe%M—]ÕЀãÂóð-!ZËŒDs×îÈ÷©—ûPzõŠì[\ÒM#mKÍ͉¼ÆŽR¬ê””¶« ŒÕ_ åäì?®¥ö—kÚ=¯¾ïÅãFídIÿýzw^dÆåb;ñøÎ_ˆÇ »Bi»T¹#£†ôcH~.‹—­åãå_²qKFB˜ªùbY.Ûþ_G}0Ìçmf@¢‹Y“ú¡øÑÃ! Ã@Ñì‘/ß -è“•ANf*[‹wašɉqˆŠ"Á¡Bˆ£.--­ÓKW?þx~öçü~?;w´”…ÛxóÍ7in¨%%%§ÓI0¤±±§Ó‰Ó餼¼œ;v0dÈN<ñDŠ‹‹9ýôÓùÉO~¼yó˜5kVLhV]]MMM ÙÙÙ$&&vß…ƒü~?ÍÍÍÝv>˲سg×]wÓ§Oï¶ó !ıL_þ—]ŽOâÇ P¾ñ·#´pqdFáðah#†GŸ¾ðfe%¶1£ðþí‘#=ì(ÇYgF:?¾Ç…mk*…[" T%ÚAZ6½ƒà @_ûudßáC{`ÔÚ€þhÇa¬ß@ø³%‘%Á­˜¥;1ж£¸\ا}Þ1ãB‚ϽHøó¥‘ÏÙߘ0Ô2£Òqþ¹Ð‰LÀ¬ª"ðül¼ÿ|Û¸±‡yeB=vÁ7›£ŒËéàœ)Ç1qìPJv—GCÔ}µ #až½Õÿ<¶¶³‹êL›»…IÙ‰üqL .³ =ˆ,sÖ@¸M€hYÐ/·7–iRX¼¯ÛAœÇÝ&@4M™q(„âÛÏívSPP@AAgœq×_ûKÊÊʸñÆ©¬¬Äãñ`³Ù…Bø|>zõêE8¦¤¤„={öPPPÀoû[šššØ¾};Ñ:‡¤¦¦²k×.***ÈÍÍÅårdTß.áp˜ú}]4»KEE'Nä™gž‘Ò(Bˆÿ)¶ñãPÜn¬êj³þ…û¶[¢ÛÌÝ{ðßûÎË~s\èßoà¸ðüè ¾Ž¨éi°ïÿ­Æºõ„Þ}×ÕW¢$÷:¬ñ;~ø=üú+Á7ÞÆ~Þ9Ø'ŸÝf5ûðÝqwd¿³ÏD‰‹4#±Ÿ<ÅåÂØ\HðÙp^13æœÆæB‚ÿz&²ï§Ål <õ,VU5ZA>ŽïÏ8¬±8/½ßíwxì ìgœ#–…ÿ‡"c8Î˶Ñ#ц ÆØ´™ÀÿÀõ×î{Q1Á¿¹æK/‰½®¢í„^+òº?¹4:s1ôևѠfdð÷©¸](Ò˜MÃ$8ì¥ 3[KNŠ'9)ÒÖ]ÅŠÎ8TMU±ˆÌ:ô::/+¦š IDAT^ýéîz&ï®çÒ‚T~5ÀƒåoDúÐ ›ÓÝnf Ð' ÃÔÙ²}'éÉI8ŽV¢‡B!¾›z÷îÍ«¯¾Ê²e˸ùæ›ñz½hšFRR@€@ €Ãá  ±~ýz*++ÉÏϧ¶¶6zƒ­EVVº®SQQAzz:EEE$&&Ò»w09–)Š‚išÔÕÕa´SåPÏÙÐÐ@\\Ï=÷½{·SçJ!¾ëlî[ ¯žüúÊÕ8Î= £t'áyó1Ë+°O›ŠóûC2«¡³²ßîƒ?ÜwÀ—ˆýåèÒWcS!'ÿ€ãâ fp¨$$àºîüú+M3¯Äñ½éØÆÁ¬¨ ôö;˜;JQâãqßsWô5;÷·â»ó|¸ðGŸ`›tr$L\·žà¾ Í6qΟ\óz¡¿Ž±­ûÔÓ»%8t̸à˯blØHÓ†ãÒKPÜ.Bsç^ð!Jr/\×^Ýæ8÷ïn¦éÊkðÿõ1Ìêjì“OÁØZDðÅ—"ËÇÏ9 Û˜Q1ǘ;J£?{û§î_ò¼u[ä¿…[¨Ÿ8å€ãµO=¸gþqØ×-DO‘à° ,”Ãþ€ÐÒ™¹åC‰MÛ_ëÂe;x(ùÊ–*^Ù¿“ÉÙÉ:Š¿™¯ Ã0Ñœ.,Ý×ÎÀôÉÆÐuŠv–ѧwª¦a) !„øn›0aÿùÏx饗xë­·ˆ‹‹Ãn·Çƒ·Þz+;vì`Ê”)Œ9’%K–ðì³Ï2zôhJJJÈÍÍ%##ƒÚÚZ–eQ__Off&ÉÉÉßÊú‡mo<ªp8LMM ÷Üs'žxb·W!¾œ—ýsO<…¾j5úªÕ‘ Š‚óGáyàÞ˜å°æÎÏ0<Ò\¿¾%1ß]÷zómBo¾Ýf?ï_jÓ]Ø9ó2¯ÿþä3Ÿ|¶£¦á¼ü§¸o¾¡Ç» +^ñ¯¾Hã/Gÿj-úWk£ÛÔ´4âþýÚ€þm޳Ÿ:™¸ý¦«MðùÙ÷-5pL?ï_îô6cTˆo°ü~ÿwnÉMO¸ò§qöI£ëÿ~ïþ£Áañ®rÎ;ëtËäÉm!îùèëNŸË®)üé¸ÞŒÐê †(6'zÀ‡iš†ÑÎCg×Þjªš¹ü×·2bÄ‘íÒu {÷î¥wïÞ$&&R·¯Ý½BѹãŽ;X·nv»=&ìs8œþù :”={ö°páBªªª°Ûíø|>t]§´´”~ýú¡ë:›7ofàÀ¨ªŠ¦idgg¯®óMMMÝv>˲(++ã’K.áç?ÿù·2DBˆžbî(%¼læîÝØ† Åvüq‡½”øH²jëпZƒ±vJj ÚðaØF8`?«©ý˯0 ·@S3ê ØF@ÍÎ>‚# cs!úÊÕX>¶qcÑF@9Höa54 ¯þ cí:Ô¬ÞhãÇ¢õïw„-ı#àv»eÆaWh©òœÅ«Ø[UÇ©ÇeP^V‡çP•؇v‡Ã4±)àÖº¶ :lXܸ|ÉN¿ŽO!#XC(Ä5¢¨¶H DÃßÞ•‘LJ¢Ö=K“„Bˆc]||ÈÅKkx´: %>\†‚>¾&ÍjÛúŒ–›6n`ö÷³dîlB¾ÆÃƒBñmqî¹ç²xñb¦L™‚ßï.¹mllÄëõræ™g°uëÖh¨8tèP²²²>|8‡ƒ½{÷’••…ÇãaÏž=„Ãaª««Ù´iÓ1QrÃï÷SUUÕm¡¡a”••1sæLæÌ™#¡¡B!Äwœ‡]™qØÞcÂè‚è×å5 î‡û½Ý¦¡ï› x¸Áa‹OÊšùÁJï½qÄ%ð5ô7£ØXíÔ ë«¾XÎ3þ=«¾…©wÏ !„âXf·Û¹í¶Ûxë­·ÈÈÈ@×õ6Kysssq»ÝlÚ´‰eË–aY£G&))‰ÌÌLªªªðù|äääDk"655±{÷n ñù|G¼î_8¦ªªŠæææn9ŸeY”——3bÄÞÿ}Î=÷Ün9¯B!„8¶IpØŠÒqp8(/‹Éã‡b³ÙÈLMêp?US¢³ UUÅa·GƒC—Ö½*^.nâ¢u_»ópzâ4Õ£‡‚(vg»Ý¬ü }8Ÿý¿[ذl–Õ}u„BˆcUZZ³gÏæOúS´qKçåòòrš››IKKÃf³±eË–,YBrr2#FŒ //¯×KYYÁ`øøx1 ŸÏGqq1%%%èºÞã×ÑÒí¹¾¾¾ÛÎÙй!:{öl~÷»ß“5…B!Dχ]`Y×88aä@Æí¦©¨Í,°¬Øæ(v† =R Iá/…8U’JF})~_3þÆ:,Àîô¢mg#ÔÕ72çõWX²x>§Ÿ÷}Œ:Ê…m…Bˆ#`ܸq,\¸_|‘§žz ÇCvv6š¦±gÏâããñz½TTT°iÓ&\.Æ # Fø|><.—‹ÚÚZÂá0¦iÒÔÔDZZiii=2±¹¹¿¿½¦h‡& QWWÇý÷ßϸqãºí¼B!„âÛCfvAK ÃŽêjš†ËéÀn³u\ãð³vápd‚£›–*·'hÂm|ÜZ™‘ÑU³a¾ÆZ ÓŠÌ@lÇÞòJf?5‹ç¾•=Û¾î±ñ !„Ç’Ÿþô§,X°€‘#Gâóùƒ¤¥¥áv» ƒ8NÜn7uuu|þùçTTT0jÔ(rrrðz½X–E Àf³áõz£³ +++Ù´i Ý6ÖP(DUUU·…†¦i²k×.Î>ûlæÏŸ/¡¡B!Äÿ0 »Àérbí›1x¨EýfphGß7ãЮö|ý£Ê Áõ› féýqöÎEAð5ÔbX€ÍÑîqEÛK˜õç?òÊãwQ½g{S!„8Ú<?ü0Ï?ÿ<Ã00 —Ë…ªªø|>TUÎ@\´h–e1nÜ8 p¹\X–Eccã¾i–e±sçNŠŠŠƒ‡46EQ0 ƒšššn !-Ë¢ººšÞ½{3wî\fΜÙ-çB!„ß^vÝá@Q=4TUÅŠ­•¨iZt‚ã‡-66èüj«yÞáÄ¥g øð5ÔfÃj§³iZ¬]»Ž?ßýÞýÄ«Bq4ååå1gÎ~÷»ß ±,‹øøx<ªªR__Ãá@Ó46oÞ̲eËHIIaäÈ‘ddd””„±¯žqk¦i²mÛ6vïÞݦ!Ë´ÔJNKK#99ù°—=[–]æüÄOððÃãõzëœB!„â»A‚Ã.p9]4ùì*¯9äà°e©rë)ƾ ¶#¶X\æÚ]I¬ËK\¯TüM ø›Ql,%öŸˆ¢€®|±êË#>V!„âh:ýôÓY¼x1Ó¦MÃï÷ …p:¤¤¤‡ ôêÕ UUùàƒ(,,dàÀ 2„øøø6ç«®®¦¡¡††6oÞLMMM´!K{ZÞ;ÄÅÅQZZÊêÕ«©©©¡_¿~$$$Ò5…ÃaÊÊÊøå/É›o¾I¿~ýéþøc***;v, ˆY² Y¾|9+V¬Àï÷SQQAaa!>Ÿ/æ5EAÓ4âã㩨¨àµ×^cÅŠèºNII Ÿþ9†aЯ_?\.W§®Ã²,ÊËË9î¸ãX°`S§NíÖŸ“B!„ønà° œ. S'ŽÂ²àŹŸ²eÇÞêq¨ª*†™qhW•Ž»1 ïT¸WŒ:pvG¤aJsC  RVY‹iE>49[}0ùýïÛíî–G^^Þѹt!„¢ ’““yæ™gxì±ÇPU]×±Ùl¤¦¦âr¹(**ÂëõÇúõëùì³Ï0 ƒO<Ç@jj*}ûö¥¶¶–O?ý”ÊÊJ ุ˜âââh7fMÓhnnæÍ7ßäÓO?6AQÓ4 ”——³råJ²³³±ÙlŽÛ²,êëëq:¼òÊ+ÜtÓM1a¦B!„­IpØN‡ Ó4Y´b=v»ÓNÁç_òÎG«iò;·TÙ²b–)«ª­k¤* Õà0Âo*Ü·ËÉÓñÇãpG>ÜhšŠÝn>Üûžï ‰‰‰ÔÕÕõØù…Bˆî2|øpæÏŸÏ•W^‰ßï' ( ƒÆçóQ__Onn.ªªRRRÂÊ•+£µ† ÆäÉ“III!DŸ÷ù|ÑØØÀûï¿ýº5UUIOO'`………¤¤¤´;Ö@ @UUüãyúé§;ÜO!„BˆvÓåΜ0 ]7øtõ&N;„¤//½û9k KQj±Ë”[º"B$4ÔŽâråoÚ¥¥IŠ¢`³Ù¢ÖÁá}÷݇ßïï¶GyyùQºb!„âÐ\tÑE|øá‡Œ?ž@ @8ÆãñЫW/vìØ C¡¡PUUq8躎Óéäøã§oß¾mÎk·ÛÙ»wo»ÍSZfêºN0$ã÷ûÛÌ 4M“={ö0cÆ Þÿ}FŽÙ3?!„BñÓñZцÃéÄ0ü,^¹‰þ9L?ŒÏ¿ÚLFJ"gŸ2†%_²¥´Œ3'Œ$%©mt¬HhhYVô¡GƒCë˜ Œ}t4EYúÔº†RK˜(„Bü/s¹\ÜÿýìÚµ‹o¼‘ÚÚZTU%///º¼¸…¢(lß¾ÄÄD1 £ÝÎ˪ªvXÿ·eõB]]]ÌÍÈ–.Ë–eQ]]ÍèÑ£yê©§p»ÝÝÑB!„â;MÒž.p¹ÜX¾:¦4šÍÛw³tí&ÊîŠ._ÏÄÑø!^[°œqCûsÂÈ|45vR§¶¯ÆaëàÐ0#5Ž¥Ê1¬È EUbÂÁž\ª,„B|›åääðÆoðÙgŸq×]wEW|S `ãÆ$''3|øp¼^o›ðPQ”;-«ûÞc¨­Þk´¼Nss3š¦ñÏþ“ÜÜÜîº4!„Bñ?F–*wÓåB× ±—ËÉäñÃX¶v+ÁΙG±¶°”Ý•µœ;y;ʪyù½%”UÕÅ,U¶°bê‹5[3ôȘ–à°åáp:òÈ„BˆcÛ)§œÂ¢E‹8ÿüóñûý톇555|ú駬_¿]×c‚@ Ãã:ÒÜÜÌu×]Ç믿.¡¡B!„8,vÓéDÎ:y ºn°dM!§Œ‚×ãbñ7¬?Ùé)Ì_²–ü>™Œ؇9‹W±ø‹è†ù °/4lÝ ¥¥î‘ʱ¶TÙ²ZBM-¶Æ¡Gf !„£ª*×^{-sçÎ¥_¿~„Ãá芃¼¼<ÒÒÒ¢ûîܹ“Å‹G›¤h¶a˹Û3}út¦L™Ò­×!„B!þ7IpØN—›nðá²ux=n¦×vÆayM=çœ2†¢]å–”qΤ±44ûyqîgTÕ5¡@ÌlÃȇ‚Èù#ÍQŽ¡_‰i‘Á©ªÓUÙápøX!„BD%&&òä“O2kÖ,¦i¢iãÇgâĉx½Þè¾­».CÇ3[?ß:`ì(PB!„¢«äe8\N;?›>_ ÄÒµÛ8õøáÄyÝ|´r#㇠'#•—¯gp¿† ÈáƒeëÈHIbâ˜Á쩬™i ÷_Á:¦–*Û,“–TSUcg:] !„]5xð`Þ}÷]®¹æ¦iǤI“?~|›fcšq¨( º®£ë:¹¹¹ÖRB!„âPIp؉‰‰¬\³‘¯‹œy"SŽʧ«7ÖM¦4ºÍŒÃm¥åœsò*kY½q;yÙé(€¦i1¢µï=¾ªX¨ÇÐRe‡²ÿʦ©ß¨q(…BˆC5}út.\Èĉ ƒ†AJJ §Ÿ~: >Ãá oß¾”••¡iÐõšˆB!„BtD‚Ã.=z4S/ü·ý¿¿Sºs'Ãòs¹â{§â°ÛXüÅŽ>€ìô>X¶ŽAyÙ îŸÍË×Ñ;­㇠`Wy Šº?0l [fjX¤{™| eÆ¡BqxwÝu¯¾ú*©©©èºŽeYÑ¥Ê-`{A`AA—^z) TVV¶{œB!„‡K‚Ã.švÖY¼üÆ;,Z]ēϿ†M±8oò8Î4–՛Щ¬màÜSƶ™q¸¦pGdÆ¡[ßPUUÔ}«’´Poœ=Û'"Ñi?º 83úµªÆ‡v§‡B!DwÈÌÌäå—_æ ǦiÆìÇoû[>øà¦OŸÎ›o¾ÉäɓȲfEQpÉÍ=!„BÑM$8<.—‹û|˜+®»•;ÿü+¿\ÃÀ¾½¹bÆid¤$ñÁòu é©qøáŠõd¥'sÜð|vWÔ¶iŽ¢ª*# dåÚÍBa캫úÛ˜7c$gæ¥a;ŠK—ã´ý_kÚ7jJp(„Bt«ã?žE‹qÑEE;+744DnØÙíœvÚi,Z´ˆk¯½6.Úl6î¸ãfÍšÅðáÃ9r$#FŒ8š—!„B!¾CÀòûýrwú0<ûÔ?YòÑþïç“’šÆîŠZ>\ö5ªªpâÈ|µ©„FŸŸé§Çߟy‰ï¼9Zìܲ¬è£ª¦ŽÊšzúç¦cè*_Ô*ܵ¬˜’ÿ¿®‘®g–/Å0  „¢îOÏÿÑUôîÓÿˆI!„ø_ÐÔÔÄ]wÝEAAW_}5@·[ê !„Bˆ#£åý§‡Ý¤ªªŠßÿîf†õËà{çNÅRT–½•U¶3ª / qn ÃdÞ‚¢ÁaËöˆ>¿Ÿ¿?û¿üÙEXzÃ0(N^*jâÙ{©éGìšNð9¥l†aP0xª¶?8¼à²kHÍÈ:bcB!„B!„GFKp(K•»Ijj*ÿxúyFžt·üñ1Jwìà”±CøÉy“Ø[]Ϛ 蓉ª¨¨-µ [Õ:T…O–®äÁ¿Ïæ×·üžþãÎ %§ÍfÇ®û˜™ ¯žžÇ”ÞñØŽPÑsw«¥Ê6»=¶Æ¡ÝyDÆ „B|— 4»ÝÎE]t´‡"„B!Dv³ÉSNåù¿Å⯊ùÛÓ/‘àqpÙy§0~X>¥eÕhª û£¨*;Jwrûý“UÀ“O?OŸ>}HÊÎ'oÌ©$¦õ &ÏsÈõô|óg«|Òáp|£9ЇB!Äá*++C×uJJJŽöP„B!„hÃv´ð]äp8øýÝ÷RTTÄíwܦÂ)'(,øp!–e¡ª*MMM<ýòÛhž^üí©çq8mÎ¥Ùd >¤Ì*vn^IsC#]^œ˜Êk¥~^.ª£Ñè™ëðØ"ÉaKGåý4ÛÑïú,„B!„B!zŽÌ8ìA `ö«oÓlOáö§ºªMÕ0tw?XÌ]ù3¯¹‰Ûï¼»Ýа5OR*'œEÎÀ‘h6;6ÝÇ%™ÏLHç¤d¶X½ìT"õ[‚ÃèÃaGkUïP!„B!„B|÷Hpx\zÙOyðÑ0ëßó˜»`1¿¾ýÿ‘Üg8O=÷RtYrg(ŠBz¿a,Z¾†m»«°L‹³‘»Ûy`x"½íV·Ž»%8Ô´ØàÐnsHp(„B!„Bñ'K•¤¤$ùÛ?¸üª¯_mÞŽnZØt3R<:ÌÅx·Ã›ØÒÅn³coÕUÙáú†B!„B!„ßu2ãð[Ä4Mvâñx‡Ã躎®ëT–nå£]% Iïä8’­&ní¯°®Ùάí~ªÔCë€lÇ@Õ´èŒC˲+øBÑ} Ã`Ó¦M”––2tèPòòòŽöÄ1Â4MB¡š¦a·wî†_ Àåröë†A8"MãTõÀ÷ª[ÞÓ8‘• -çèÊ5KZ®Én—ÚÐB!„øö’‡ß"‹¼G/¯·ÛÇã‰y¸l Û6|Éʵi š`è ±ÕóçA ?L â1Ã]~=Û¾àPÓZÕ7´Û¿•oÞ…â»äé§Ÿf„ ÄÇÇ3bÄÎ=÷\úõëGrr2gœq‹-:ÚCGÙܹsq»ÝœþùÚß4MÜn7n·;øŽ]»v‘‘‘Ûíæâ‹/>à¾Á`#Fàv»™8qb4@|æ™gp»Ý\vÙeí§ë:k×®åé§ŸæÎ;ïäùçŸgÆ ‡=öîrÍ5×àv»yòÉ'öP„B!™‡ß"%›×’¶½^V°ukVR´« ›îã¼ÄfîËÓ¡4¢™F§_OÛ·ÔÙa·Å4G‘‡BqtTWW3cÆ ®ºê*–/_N0dÈ!œsÎ9äææR[[Ë¢E‹˜:u*7ÝtÁ`ðhYc>ýôSn¸áÞxã}¾}ûòÈ#ðæ›oòÖ[ou¸ïÝwßÍæÍ›q¹\¼ôÒKºAùå—_Ò§OFÍUW]Å}÷ÝÇå—_Έ#˜9s&UUUm޹å–[¸á†ðûý‡~aB!„ÿc$8d4r}V€ëSšéj€NÔ?´G»*LJ6›Ì8Bˆ#­¾¾ž1cÆ0gΜN'?þ8uuulܸ‘÷Þ{ÒÒRÊË˹þúë±,‹Gy„©S§ößñí4pà@n½õV.ºè¢˜ç¿úê+{ì±#2+õŠ+®à¼óÎàÚk¯¥¦¦¦Í>«V­âÏþ3=ôC‡=èy/^̤I“(++cĈÑÙ†×^{-v»_|‘‹/¾¸Í¿ý'žx‚Ç{Lu!„Bˆ.à°‡†Á ÿz‚‡oÿÿxüáC¾ËýÕ²ÉLKŽ Û[²Ü²Ýår3|܉L8ë"NŸ~‰½RÀÐdkàžœçj58CKËìD›ÃÚeÆ¡Bqwß}7;wî$++‹¥K—rÝu׳Ozz:=öo¿ý6‡ƒÏ>ûŒ—^zé(XMC‡åÁäŠ+®8ªãxê©§HII¡¼¼œn¸!f[(âòË/Ç0 Î8ã ®»îºNóÆo¤¹¹™iÓ¦ñÅ_pï½÷2sæLžxâ –/_ŽËåbñâÅ<ûì³=qIB!„ÿS$8ìAëÖ®á/ø ãÒüøŒ‘œ‘ïà_ýŽwÞz­KçÑu3ÐÔaPØÞÃÔ\œ;=2Ë #7ŸógÞÀØ“ÎÀîp¢é~¦Å7pkj TCo÷uÕ}³mߘqè‡BqD­[·Ž¿ÿýï<üðÃŒ;ö€ûϘ1ƒk®¹€Ûn»æææè¶P(m‚‘úrŸ|ò o¿ý6»wïîÔxššš¢ÇÔÖÖv¸ŸišhÍ:ˆ,·ž3gï¼ó%%%|ÚÚZ>ýôS^|ñEæÎË–-[Úìíά ‡ÃB¡P›m–eEý&]×),,dîܹ¼øâ‹,\¸ŠŠŠvÇØržÖukjjøïÿËœ9sؾ}û¯±5Ã0:5^Ó4Ûsëq´üì[¾ÿæ8[^ë@õ «««Y°`¯¾ú*_}õU§¯£µÌÌLfÍšÀìÙ³™7o^tÛ}÷ÝÇúõëéÕ«Ï?ÿ<Š¢ô|6Y’§ IDATlà믿àñÇoÓÈe̘1üâ¿"3aÿ¿ƒ–#Á`°Í÷­g!ú|>>øàæÎKeeåAÇ …Xµj¯¼ò ëÖ­k÷÷#„Bñm%Áa…B<ùèŸØüñ«\|Ê@Þúh ï}¾·ÓÁNLFpßý¾^Ó¹7áŸ.šO¿œ´65 Û[®Ü²=·ÿàh'dEQ9át¾åÍô4 €^f¿Hmà g9ÞÆJøÆ‡.ÕÚ×Å;ãÐf—‡Bq$=úè£èºÎøñãùÑ~Ô©cî¼óNÙ½{7¯¼òJôùQ£Fáv»ñûýÜqÇ$%%1eʾÿýï“““É'žHiii»çlnnæ'?ù ‰‰‰ÑcÒÒÒ8ùä“ÛÝõÉ'Ÿàv»¹êª«¨¯¯gÊ”)¤¥¥1cÆ ¦OŸÎ€¸âŠ+0ŒØú»áp˜›o¾™œœ&OžÌÌ™3¹à‚ 4h^xaLˆ7lØ0Ün7³gÏnóúƒ ÂívÓ¯_¿6Ûþûßÿâv»éÝ»wL°ùá‡RPPÀàÁƒ¹à‚ ˜9s&S§N%77—«®ºªMжbÅ Ün7?ýéOijjbêÔ©¤¦¦rá…2cÆ òóó¹ì²Ë:Õpä£>Âív“šš3&€… FÿÎßwß}mŽ=ÿüóq»ÝÜ~ûí@Ûæ([¶lÁívsË-·‘;n·›þð‡m·¹üòËIMM嬳ÎâG?úcǎ夓Nêt¸ÜÚE]Ä%—\ÀÕW_MCCkÖ¬áÁàÉ'Ÿ$;;»Sçj ›8p`»û yŸ³mÛ¶èë»Ýîh8˜™™‰Ûí¦°°€´´4²²²0 ƒ_üâ$%%1mÚ4.¸àÒÓÓ9묳¨®®n÷µž{î9’’’8î¸ãøñÌÈ‘#IOOç£>êÔõ!„BëlßEtŲ%Ÿ²dþ[œ|%e6þøÂbò†ŒaW(Èÿ{é#ΟPÀðÙ\š‘ÌŠÏ^ç£ïð“«®'99¹Ãs¾Zâ2Ñu=ú‡Ã1ßÛíöè×5ul+ÞC]]III1çòÆ'rÆ÷¯`ðöM|òÞTUìe ZÇïR,ªkâs+Ý“ÙyßReû¾À°…Ô8BˆýøÃzô5æÏŸ@BB·Ýv[§ËÊÊ¢¾¾žþóŸDgPM˜0µk×’––ÆÐ¡Cñù|”””°bÅ † Âe—ýöî<,Êr}àøw6f†]D]6qß7Ô2—LÓNj–©YY™¶k{YÇ<¦mZj—4Óì×bš•\pß7TpAEQAvffùýAL  (R÷纸”÷YÞûä¹yžç~”:uêØç2™L|ûí·dddàèèHhh(ŽŽŽ$''³mÛ6¶mÛÆüùóéܹ³}LIrçÎDFF’››KûöíÑjµÄÇÇsùòe,X@bb"QQQöqëׯgïÞ½(•Jüýýñóó#55•óçϳbÅ >l¯Ô[òsnÚ´i;vÌ>Gnn.gΜàâÅ‹Œ3¦ÔóüþûïøøøðÖ[oʼn¦’"...¡ÓéHNN&55•¹sçrðàAî¾ûnû</^`ß¾}DFFråÊÚµk‡^¯'!!ÔÔT¾ûî;Μ9C—.]Ê|®^éÖµkWœœœÈÍÍe÷îÝtìØÑÞkÿû¦M›xçw쟱eËî»ï¾2÷€âDÛˆ#ˆg÷îÝ4lب¨¨rW¯>øàƒlÙ²…gžy†°°0bbbX¿~=Û·ogĈö×®*¾üòKbccINNæÅ_äÀ1lذëV]¾Zpp0Ÿ~ú)ÞÞÞ®PܶmPüzôèÑ777/^ŒÅbáá‡ÆÁÁ777û‹Å°aÃøá‡h×®;v$))‰õë׳víZÚ¶mËž={ðôô´yï½÷˜4i-[¶¤sçΤ¥¥ñûï¿Ó»wïrÖB!„µ° †2[=DÕäåå1÷‹é„¸Ñ"Ì—¹¿n#9WÎÉ•ÐÐPûn/žOBe¸Ìc½ÛPÇÕ ³ÅÊêÝ'qñ‹àáÇž@¥R•š·°°­k¦a€§=ah±XÊ$¯þØ<™©3þ‹££#Ÿ~úi¹«  xÓ¾Íÿc禵 X¬V2¬:~ÊÔ’ìâÇdït®œ9A³­èØéÏ7‚Ž®x…¶¸u/¦BÔyyyüûßÿfêÔ©5ЍåzõêÅš5k0`+V¬àƒ>°'4ºtéÂÖ­[í«ÿ³²²Ðjµ@q¢¬sçθ¹¹‘žžŽZ­æ×_å°Ï[âóÏ?ç…^`̘1Ì™3Ç~ÝjµÚÿR§NbcciÖ¬™½}åÊ•ôïߥRINNNNNU~ÆÕ«W—Jlpøðá2¿ä,ñõ×_3fÌ̲e•;æåìÙ³´nÝšÌÌL¶nÝJ§Nìmz½£ÑHfff©{ººº’›› ÀäÉ“í«6¡xkt¯^½¸p᯽öS¦LŠ“âááá2qâD¦L™bÿ¿^RR÷Þ{¯}kýÌ™3yî¹ç*¿B!ÄÂh4¢×ëeÅauˆùß*⶯a`§†œ8—ÊÄY¿áéJÓÁös’ÜÜÜðññÁ7 ›-Y«ãhPGÅОmèÕˆŒì>ô2í»ßO×î®dppp cÏسeþŽ8:jʬ0¼z¢Á`âbF>ÁÁÁäääðꫯYn•B¥RI»n÷ѸU¿ÿ²˜ãGânÍc¤k>ÇM\É(Þº¬ÑÈŠC!„(O^^S§NE¥R•JòT§œœ>ýôSÆ_jÕÜõ:tˆåË—ãââÂK/½¯üJOOÇÝÝñãÇ—YµuþüyæÏŸB¡`üøñ¸»»SPPÀgŸ}†ÅbaìØ±å®’ÿù矉‹‹#::šnݺÅIœ… 0räH‚‚‚J)iwvvæå—_ 55•9sæ T*™8q"Wä²ÙlÄÆÆb6›iÓ¦ uêÔÁl63uêTÌf3Ï=÷uëÖŠ]û÷ï§uëÖìß¿Ÿ¦M›òàƒÅ[®§OŸŽB¡à•W^ÁÑÑ€üÑ¾Ýø¯[g }ôP\¨¦Drr2óæÍàÑG%44´Ô¸’vNÇĉ˼n3gÎäÊ•+ö×´oß¾¬X±‚õë×ÛÿMFvïÞMxx8¾¾¾ÄÆÆ²sçN¢££?Ïò»÷Þ{Ký¼¾Q¯¿þz©¤!o…vqq!77—‹/V¸MøZúöíË}÷ÝǪU«€â*Ê% oÄÞ½{éׯ™™™DEE•ZÅZwÝuW©¤!o{þøã:t(_|ñ¯¿þ:®®®|üñÇÒ²eKû–ëAAA̘1ƒÞ½{ßô3 !„BÔ4IÞ„ŒŒ æ1Vþ:ìҘϖþŽÕÑ›v]î!;;›„„üýýiܸ1YYYÄÇÇ€³³3¡›c0˜òÝ¢›úÒ¥U8G7âhâf>Þò;ƒG=C@@ :Ž.=û·7Ê‚,¼ÜËlY.Y…˜”’CÑDHHV«•I“&•›4¼š‹›GŽçLÂaÖü´ˆË©—SfcÉ·`4‡RoDTÕð¦D!þNÔjõ-Û®œœœlO>ÿüó„„„Tzì’%KX¾|9:Îß²eËHOOçå—_®0Ù¹ÿ~ÚpêBj¶LqGGGŠÔŽ4hЀ-Z0cÆ š6mZég nÜœ§^›J·>Ñ8hí×þHªÕjô.upñ–3{„âvñ÷÷ÇÕµøìÙ„„„*(÷»† V8®ägGIq‰’"éééŒ9²Ü’•…%ç ^­*ÉNOOÏR<éÕ«“'OæÈ‘#åŽ)It•$ÐRRR8qâíÚµ#88˜ÈÈH.]ºdŽë%ÚŒF#{öìá믿æ™gž±'E¯¥Aƒ•ª |=4mÚ“ÉÄÖ­[?Ï7ŒŽŽ¦GöâF£‘;v P(èÓ§ÏMß 00°Zæ¹ZQQÇÇh4Ò¹sgœÙ²e Ó§O¿©y.\HXXÓ§OÇjµòÁðÝwßÝÐ<}O(•J"""€?¿'Nž< üYˆ¥*ó !„BÔ&²t¬Š.$ŸgáìO‰nìA뎘ûëv2Šô(=(((@£Ñ––Fvv6¾¾¾øûûcµZILLÄÉɉ€€¬V+§NÂÑÑ<½¼ÁË›e;Nà®:ÁðÞméÙ6œc!³§L$¬eîø/<<êuÏýìÞº=xÕq²¯>©0æê<+ºoß¾9r„õë×Ó³gÏR‰ÃúõëãääÄÎ;1lÛ¶ “ÉDûöí¯ù5­Š[qîõ|À¾}ûpuueéÒ¥,_¾œqãÆñöÛoÓ»woš7o^¥ù._¾Ì¨Q£Xµj …‚Áƒ3yòdÂÂÂn8ÆÊ~OX,û*Q__ß Çx{{ßp,B!„w YqX_~>_ç}ÄcÝÃhà[—-Nœm%8¼17F£Ñ••EHHááádff²ÿ~ÂÃÃqqqáøñãäççÓ°aCÜÝ݉';;€ Ð†8ù7哟öð˦ƒ8êܵ1ž†L{÷eŽÄ²ÇÒ¾swô^!ÄŸMC©T¢ÓéP9{NïÞ½o(ix5wz<:ö F>÷õýq ˆ”¤¡BÔ’óæ–,Y‚Íf«Ô˜ôôt{õÛ6mÚ”i¿téR…cK*—$EJþ²²²Ø°a~øaµYYYøÑ®[_âÎ^á\Ê‚Â" )uüÍjÔ¼Í:õ…üSBˆšòâ‹/¢V«Ù·o‹/®Ô˜wß}—ììl¼¼¼èÞ½{™öcÇŽU8öСâ_T•À(ùsëÖ­ètºr?Ìf3)))äääTõñJ1deea0€â­Ë<òsçÎåÂ… ôêÕ €Y³f•wu²-66µZm¯¨Û­[7”J%›6m²Ÿ±÷ו›»wï&!!vìØÁÔ©Siݺµýœ¼¢¢¢›z®ªèÔ©®®®ìß¿ŸuëÖa0ìIP(½Ó‡ >‹ÅBÏž=yâ‰'P(Ì;NÇáÇyûí·+=çˆ#8tè:uâÀÜ}÷Ý×T }O˜Ífû6ù’ï…’"8,wŒÕj­òÑB!„w"ÉU’^¯';ÏD§»ZÓížÞ¬Ü{ÇÏãåáÊËw#*HÃî-1øûùÑ´iSš4i‚Õj%))‰ÐÐP2228räÙÙÙøøøÆÙ³g¹páB¹]\ iÚžØDŸ.ÛÌåÌ¢"ƒЃ¥_Lb颹X­V”J%]îé‹Ö3ÏzÕr¾’Bˆ;K“&MìE^}õUvíÚuÍþK—.å믿`Á‚åVAž;w.&“©Ìõ 6pøðaT*wÝumÛ¶ÅÁÁ‹/–›\±ÙlÜwß}3þü*?ßÕæÌ™C:uJ%ÊJ8;;sÿý÷؉V¢$øÃ?pìØ1Ú´icÿÅœ»»;­[·&55Õžpük¢mçÎtéÒ¥LEe€E‹ÝÔsU…Z­¦gÏžX­VÞÿ}€r‡+W®dïÞ½øøø”»ýNðÊ+¯pòäI\\\˜;wn©¶† ÚŸoúôélÙ²åºó8q‚+V T*™?þu çTÅ_“Ñ%–.]JZZÎÎÎö-Õ]»v`ÆŒå®^±bÅ5W# !„BÔ’8¬‚{<̹, Wr ôïÝ H¾Ûp”Œ¬\ÚGóéóq6žçÔ±ƒ\¼xN‡——;vìÀï„¢ÑhäĉX,BCC©S§'Ož´oWþ«ú¾Ôo؆¹ëX¸ªøbÿ¨†D:gò餗پeá Ý®—A!D xï½÷ $55•.]º0mÚ4222JõIJJbôèÑ 6 ³ÙÌøñã+<1%%…#F”Ú"zäÈüq}ôQ‚ƒ‹‹aùùùñôÓOпÿRÛ‘- S¦LaóæÍ¨Õê빞-Z°gÏÖ®][ª-;;›iÓ¦о}ûRm]»vÅÉɉ½{÷b³ÙÊ$K’m{öìA«ÕrÏ=÷”j/)²eËRSSKµíÚµ‹ÿûßöϯ.\v«”|ÝJª÷^ý<­Zµ¢N:8p³ÙLß¾}«ü‹Ã›]Zk×®eöìÙL›6­Ü¢+/½ôíÚµÃjµ2bĈëVmþᇰÙl„„„°}ûv¾ùæ› ?bbbÊ£¢{ÄÅÅñüóÏcµZí×¶nÝÊK/½ÀøñãqssŠ+œ»ºº’À“O>YjEj\\Ï=÷Ü5ŸC!„¢¶Äauèr7-£ûŸœ…^¯gð÷q&OÏ·k`³ÙrOÆ÷o…&ÿz®®®tìØƒÁÀñãÇñô,>‡0))‰¤¤$ Çh4rêÔ),K™{* ‚5φLYº•ßw'P×Í™¡]’›°‘?x ÉçkàÕBq»¸ººràÀLQQ&LÀÓÓ“àà`î¾ûn¼¼¼hР}Åß!C˜:uj…óµoßžeË–Ñ Azè!ºvíJÛ¶mIJJ"00I“&•êÿÖ[oѨQ#iܸ1]ºtaذax{{óæ›oðå—_tSÏM·nÝèÝ»7ÑÑÑ<ñÄtîÜ™zõê‘””„ŸŸŸ½òr ‡R[V+J–´]}L@Ïž=iР………DFF2lØ0&NœHß¾}騱#öâ?þ8;v츩缞>}úØ“ö$.Wù-y jÛ”Xµj¯¾ú*ß~ûmõüW®\±'¡{ôèÁSO=Un?•JÅüùóqppàÌ™3¼ð ל·¤øÎ©S§5jÔ5?þZ±¹äÙGÍ»ï¾KZZZ©ööíÛ3cÆ BBB:t(:t {÷§É+¯¼bï[§N>úè#”J%óæÍ#((ˆýë_tëÖöíÛ“——gß–-„BQ›IUå Óé¸û¾I>w–øýÛ ô#4È—˜ýG0ç¥Ñ¯SS^Úc§/²|Û.ê6ÂÏÏÏ^]Y«ÕŠÑh$!!zõêáíí——¹¹¹6Ñjµ„7kljŒtö.Þȃ]›Ð4¤>‘Á6b¾û ³³?ßx­V{›_!„·ƒ‡‡Ë–-càÀ|ýõ×8p€³gÏröìY øçÄ]wÝÅ”)SèØ±ã5çúì³Ïضmï¿ÿ>?þø#PœÄ¹ï¾ûøæ›oðôô,Õ¿^½zìÛ·^xï¾ûŽ­[·ÚÛ6lÈ”)S4hP©1%[Ž###ËA«ÕMݺßR*•|ÿý÷¼õÖ[,\¸Í›7Û«$+•J† Â|PîÕáÇ“B¡ sçÎ¥Ú:wîL·nݰÙlŒ9²ÌXWWWV®\ÉSO=ÅŽ;Xºt)P¼=ú½÷Þã7Þ`úôé¼öÚk,]º”ÀÀ@¢¢¢puu%::Ú~öÝ_©Õj¢££qqq)·½">>> >œ¤¤¤RIÂC† áÊ•+( zöìY¦ÝÓÓ“èèè2ÕŠû÷ïO‹-8tèÓ§OgÀ€ >…BaO¶V´z1**Šôzýuã_¼x1ááá4jÔˆyóæ]sEdÓ¦Mùè£øå—_8}ú4ÇŽ£I“&øúúM“&Mì}=<<ÊÝÆ^ž’Õ«%&L˜ÀsÏ=GLL 111<üðÃ¥*)/[¶ŒÙ³g3sæL–-[€F£á‘GaΜ98;;—šo̘1òÔSO‘œœÌO?ý@£FX²d )))œ>ž´´4ÂÃÃñ÷÷¿%gìæççÛ Œy{{lß*z+%%%qêÔ)üýý ·H8þ<‰‰‰4o޼ܳ#«*,,ŒÄÄD~øa–,YrÓóUVBB/^¤aÆö ÁÿùùùìÚµ 777š7oŽF£ÁÕÕ•ÜÜ\Î;G@@f³™¸¸8 iÙ²e¥~!{áÂŽ?NÓ¦MK%#…B!j+£Ñˆ^¯—Äau±X,l\ó+³ðrwäÜÅ4:ÊÃðpsÆ`*dáê=d[ m@jj*™™™„††¢Ñh8{ö,‹…J¿³X,œ=GCoÿêÑ …BAÒ¥+l;•ÉýƒGѸIù«<„Bܼ;!qXUMŠšUS‰Cñ§¿&…B!ÄŸ‰C9ã°š¨T*î¹o­¢ï')Ý€‹³½ºwdß¹¬ÚƒƒFÍÓ;1$ÊŸ¤£»ÈHOÃÛÛ›FqîÜ9Μ9Cƒ  äøñ㤤¤Tú¾¡MZ’£õgòâMì>z† †u %nÝ·|1ýß^B!„B!„¢"’8¬fu=ëqÿQÔ kÃ…ŒBƒüèÕŽŸ¶Ÿfå–8øz2ñ‘îD¸9·‡ÂÂBBCCñõõ%>>ž¬¬,7nŒN§Ãl6Wú¾NÎ΄5»‹]ç-|¼4–‹—³èØ,ˆû›¹óÝçïòý· °Ùl·ðÉ…B!„B!Ä߉$o‘&ÍZ2ð±g0;ÖçJ®‰¶ÍâÊü5‡8|ò=Ú6æõ‡;Cú Ξ<†ƒƒ( âããÑjµ¨ÕU¯]S¯¾/~íX´)‘y+¶cµÙЩõ—ùä½—Ù±mË-xZ!„B!„Bñw#gÞ¬Yþ= c®Ž’S38qê,÷ˆ¤Ž«3iWrX¼îj7_¼|Š+ï={³ÙLhhè 8_TTDÒñô ­Kï¨âŠ„‡O]$þ²•‡‹¯oµ=£BüÕÆ3sss±X,¸¸¸\·Š¸õäŒÃš—ÍfÃÍÍí–ùB!„¨¤8J 8{ú;6¬ÂQYˆZ©àdÒ%r23y_;TJ%»žaݾ³ø†6ÅÑÉ ³ÙÌ©S§pssÃÇÇç†ï›•™IÖÅ“ èØˆˆ`l6ëö&‚[ Ž~‡j|J!„øç¨‰Cqg‘Ä¡B!„¸Iq”Ð $Œ‡ŸxžzamHË1âïE£†¡|³î0+7ÇÑ>2˜7†wñà‰ñ‡P*ûD0 IDAT•4nܽ^O||!„BQ;IâðäììÌȧ_¤ÿðç0*Ѩ•„øÕa[Ü9¦·:.ŽLÖw#'ãö`2™H>w†ÂÔÞy7>žnØl6¾ýý0ÙV-¡Q«¸’o¦sŸ!<ñÜ«h4šš~L!„â¶*,,¤_¿~¼÷Þ{×í{èÐ!š7oާ§'=zôÀßߟàà`bbbnèÞ<öØc¸ººÒ¡CZ¶l‰»»;74ß_½ýöÛ 8£ÑX-óýþûï 8µk×VË|B!„¢v’­Êw°°†yþÉlX÷?vnü wg-ÎZ ~Û^«áÉ:Òµe‹×ì!*¨Zt íJ1‡ShÙ4µÒJzfùV=O¾ü ŽŽŽ5üTB!D͘7o™™™×í·~ýz @~~>¾¾¾têÔ‰}ûöqúôiúôéüyó1bD¥ï›››Ktt4@§ÓÑ»woòóóÙ¾}{µ¬ùä“j›O!„BÔ^’8¬zÜÛ‡.Ýïaé7_qúè^¼ê8b02}ñz{3²_{ßuûѺէGÇÖF/¤Ñ:šö»Ôà!„5#==õë×ÃâÅ‹+5f„ äçç3dȾÿþûR×§M›ÆÄ‰:t(Z­¶RóÍ›7àííÍž={`÷îÝtèÐ›ÍÆÅ‹«ô\&“‰mÛ¶Ã’%KÈÏÏ¯ÒøòÄÇÇï¿þʆ nz>!„BQû)›Á`@§ÓÕt,¢.^¸À g“‘œˆƒò ŠÈ5šéÕ˜SéÚ·o›^ÍÅ´L² •ôü5¶Bü-¥¤¤àããƒV«­¶-¢¢úìÚµ‹¨¨(l6[©ë={ödݺu厉¥[·nxzz’””Tj¥¾Õj¥M›6}ú”iwvv&##ƒÔÔTN:EXXXe»ï¾›œœ ø?u7{axx8 °¾uëÖj;Q!„BÔ^’8¬¥:tìÂ]Qùañ|vÇ®¥i³&ä¸bPÐØ“(ŠšQ!„¨Q¥Îþ›9s&ãÇ¿æ˜ÄÄDî½÷ÞrÛ{õêÅ;ï¼cïw=%ýºvíŠ^¯/Ó®V«Kõ­lâpÑ¢Eö¿'''Û·?ߨѣG3zôhûçݺu#66ö¦æB!„µŸTU®Å C†æÝOæréò¼¶§g¿A’4B!nÐ¥K—€â­ÀåñõõŠÏN4›Í7=ßÕª²UY!„BˆÛAVþ ¸ººòÆ{“k: !„¢Ö+IÞyxx”Û^·n]l6iiiöDbEJ‡ÍWÞ½…B!„¸SÈŠC!„B ;;“É€»»{¹}ôz=¨\¢ïòåËלïj©©©• U!„BˆÛB‡B!„*)9  Ü>………Tªz±‹‹Ë5ç»Ú_‹±!„BQÓ$q(„B¨T*ûVä+W®”Û'33ÓþwŸëÎéíí P© Å•™O!„BˆÛI‡B!„(Iô¥§§—Û^’tttÄÕÕµÒóU&qx½ó…B!„¸Ý¤8ŠB!Ä4hÀÑ£GÙ¹s' (Ó¾cÇ‚ƒƒ+=ÀÎ;Ëm·Ùlö¿?ùä“<óÌ3UŒ,‹ýï!!!öíÖ7£deå„ x÷Ýwoz>Qûôèу%K–ÔtB!„¨a’8B!„øÃ#<ªU«X»v-S¦L)Ó¾jÕ*† V©ùî¿ÿ~\]]INNæèÑ£DFF–j÷óóãôéÓ@åV%^OZZÚMÏqµœœrrrªuNQ;üôÓO 4ˆŸþ¹¦CB!D ’Ä¡B!Ä „‡‡`É’%¥„±±±üöÛo¨ÕjFUjÜöíÛY±bo¾ù¦½(Š££#Æ cΜ9Lœ8‘+V TŸ“——Ç‘#GèÓ§³fͲÏg4ùüóÏèÞ½;íÛ·¯0æ””¢¢¢8zôh…EV~üñGñòò*ÿ_ :”]»v1yòäJ'IÅßGll,#Gެð¬O!„BüsHâP!„âZ­–?ü§Ÿ~š'žx‚£GÒ©S'öìÙÃÌ™3)**bâĉe ™ìÝ»—©S§ðüóÏÛ‡¯¾ú*Ë—/gÕªU 8G}”¬¬,,X`ßܳgOû¶f(.Î2gΠxûñàÁƒ+ŒY­þó¿sAAAV{Þ¸q#«W¯¦Y³fLš4隯ƒN§ nݺ¥âÿ 5‚B!îwdâ°hóV NÅiÆ'¨†_³¯yçnŠ6lÄr4Q·n…¦G4ªF +TXHáï±:ŒùðT¡!hôCÝ¢ùMÇŸ?þ%:Ž}xݾÖóÉmÚŒyçn¬¨†£}dè5ã·ž9‹éûÿÃrâ$¶¼x˜ü'ŸÁšú—³”Ôjÿý.ÚaC˲Ù0|üƳÊ4©†ãƒ¢Ž;ÎË£ þs\d”þþ¼õ†éŸ¡1…Sù‡‹_Í–‘aÆ,Ì[¶a9•Xég6üg:˜Í8Nzí¨Çì×5Ý£±¦¥aÞµÓ¼…¥‡ÆÿÎ/îÓ¹c©ä ºesTÉá W¯AŸ’в¾w¥â(Zƒéÿ~Ƽ}'¶¼¼J1-ù[^>ªæÍpúê Z-úæÍ°Y,˜æ/Äôßù¥‡V+ƹ p|ï-´=€*¢1êvmȹo Ö¤sŬGÓ«g¥â°ååcüü жlżR [!„B!„BQ97¶·š™–|OÑÆØJ% ¡ø D¬V4Ý£K% KhG<ŠÒßËá8Ìûد›c· éÖµTÒÐ>nø°âsöÌf,ÇŽU*˹dL U)ih޵˩D”ånGÖ¿öjqÒíê•w6–Ãq8 RfŒC¿>(\]‹c:r´Ò±þò+Eë~¯tÒ³Ó‚…èž|Üž4´Ç>îYP*)Ú¼ˉ“öëE1ë±&Cáî†ö‘ÒÛ˜uëÚ¯•$+Ö™‰ñ«¹XŽ%HÒP!„B!„¢šÝ+¦ÿ[~ýó܇`+¨8‰h9~Ud“ò;(•¨[¶ 0ùæ»P·i€õÒ%ÔÍ›•?N¡@áæ†-/[vN¥bW5nˆëÿþ<ä¼ðkÊ=Ãïj¦~ÀaÐ(g‹’ºM+œ¿_&6eýúXNŸÁš|¡Ìkf¶‚|”Þ^•Š@ÿÖëèÆµž÷øSX/¥TØßræLq»J…¦[—2튺¨[µÀ¼ïæm;ìÅmжíŠWT¢R•§¹§†iŸbÞµ§øüF溱+ë{—zí‹¶ïÀðÁ”ëŽB!„B!„×wG$• ‚þrá: !-lv±YÌXÓ.Û¯9~<Œ&”þåO{òÖ Qhµ¨;FU"rPèõ¨"#þ ýà¡ëޱž> €úªÄ§5ù¶‚T!! .›XPwÆrú ¦ÅKÑ>òðŸUˆm6Ló€Ù‚¢Ž{Å Õr(ýýÀßïÏ ×ìoK+.†¢ @áæVnUÓHÌû”*œR2®¢ŠËªÆŠŠ Ö´Ë(ý|¯¼FSêµ·ž?ý1B!„B!„¢RîˆÄaU•¬b³8Xn»ÍhIJ·x‹²írúŸãBC*œÓf2a˜2 u—N(õÕnÖËÅÉLE] Ÿ|ŽiÑwØ®d_ÓjÑÜ{Žï¿ƒ¢®G©qޝ¿ŠíR …«×Õ²=šè.(}êS´6kjJ?_œçuá+{jqìJ÷ò“†Š?ÚJž³Ô¸:î R psÅv%ëåôÊ%…B!„B!Ä-sGœqXUšÝ@©Ä¼ÿ …?üTºÑbÁðÞd{ÒÊzåÊu糦]&oèpŠ~߀²^=ô/?_ýA_¥$™iøpÆÏ¾@¡V£‰î‚ºMk W®"§ç}¥Vìàà€ãäI(<ê@a!E1ë1-úÎÞÏñ½·PE4¾¥±—¬àT¸W”´]´µþ±âðšãꔌ»\a!„B!„Bq{Ô·‘MÐŽz Ó¼oÈå5 cÖ£nß[n.E1ë±Géé‰5=…‹K…óØ L_ÍÃ8çklT‘8Ïÿ¥Oý[»Íh´1ï݇nܳè_oßžlM:GÞÈ'±$ž¦àíI8ý¥}¬åXyO>ƒíJ&êŽQhºuEáâŒåÈQLÿ÷3yÏ>ãûï”)>R­ ‹ÿT_ãŸÎg^}ne¥Æ)Ë'„B!„B!jD­L8¾ùJww ŸAÑÚŠÖÆ7¨Tèßy[ZÆ9s+,bÞ¶üWÞÀzá(•h‡ü ý¤wnée(ÞŠŒZ f3šÝпúb©veP ŽM&÷Á‡)Z³kz:JOOlF#¹ÿŠ-/ý[¯¡{jt©qÚÑ#Éíÿ/ ^¥‡š>÷Þšø=ë`ËÊ®°OIae=Ï«ÆyBjÚuÆeÿ1®nu„*„B!„B!nB­Üª €Z…îù±¸mÝ€Óœ/ÐOx §93qÛ‹î‰Qö-µe‡6ï~@î°‘X/\@Ó=×µ+qœ6å–' âêÈ^õpèÛ»Ü.êvmí+%-Ç0ïØ…-/UxX™¤!€*,ÝØ1–$Qo¥=q˜UaëmŠ«^ûÊËþcœ÷MÇ)„B!„B!nN­]qXBé냃¯O™ëÖÓgŠÛýüJ]/xÿCL Ÿøî›h‡»-q^MY¯Ö‹—Ê?¹šÂ³.¶Ü\{¢Í¼u;ª–Í+SR±¸(vK5Fû׸ŠWZ/]³¥Ü ÐÖä öi©qç“Ë×zù²};óÕã„B!ÄíÕ²eK–.]Š—Wù;w„BñÏQ+WZÏœÅ8ë+L —ß~>ó¡8z=šž=ì׋b·`š÷ G=®Ë¨‘¤!€ªqC,§Ëï`6Ûl%ÅNì[„Ó3*œ·¤2s…•‹«*¢ lyù˜–SÕÚlƼ­8É©nÛÆ~Y}W;жl+w^óÆÍÅ󇇡pu­æ¨…B!DeÕ¯_Ÿ¡C‡Ò£GëwB!ÄßZ­LââŒá£O(x{E›6—i6þw>Ølhîï[ª8ŠiÁ"†CþK¯ùa9yÊ>´pùJ²Â›’Þ´Ôõ¥nÙu‹æX“/7â ¬çÎ7aZ² Ôi@q˜’ ÅêŽQ¨;vÀf07ê)ÌûöÛ“˜ÖÔ4ò_x•¢-ÛPètèž{ºÔýrú "+¼)y£K_¿QÚaCA©Ä´p1…¿¬°_·Ä'?áâ>YÍ©prÄaàòŸ[¼5ÀbÁðÉçű;êqô@©qE[·Û_{óÎÝÕ¿B!„B!„¸¾Z{Æ¡ãþMNŸþXO“÷è(nnØrsÁjEáìŒóü¯PEFØû[Ó.CQP¹3 @vËâwš3“¼O`Þ±‹ìÎ=PzzbÍζǨ6‡Áþ9@¡Àé“È{d$–'É8…³ kzzq½Ç)  ¹eq¨"#púä#ò_žHþó/cøÏ4NNö­×ÚaCÐŽ^fœþí×±&£hóV²ÛuFÙkÒ9l99(œq^ð_în·4v!„BQu{÷îeëÖ­Œ;FSÓá!„â6¹#‡º±Oc+,DY¿~…}”õ½qY…qÚ§mÚŒ55 UÃpÔwµCûÈPTýe€Ý‹ã*ƒ*0àÏ¿G4²UÖ­{ÍqêæMѽ8•¿ÿ5û)ý|qùù{ŒŸ}yï>ÌGãQ¸º n‰vÔchzt+;Æ×§ø™,¢hõZ,'NbÍÊD†ºuKt/ŒCéç[fœvø0¬—/£jÐàºÏ­{|Ö¬,TÁ×îë0h gLË~ļo?¶¬lÔQw¡¹»;º'…¢Ì…N‡óü¯0|2óŽ˜ãŽ¢ôª‡¦[W´OŒB]NáUPàŸ¯ýU_“ò(ÃÃн8¥GÅEg„B!D奧§3mÚ4._¾ŒF£áÉ'Ÿäž{îáÑG­éЄBq(›Á`@§ÓÕt,7§‚ ¿µÆÆo6ƒúÈÿZ,ömÕ•VÛ¿fBˆ¼””|||ÐjµË9³Vˆë9r$ .döìÙ<ýtõ)"Du0›Í|ùå—:t'''¬V+6› ‹Å‚ÑhD­VóøãÓ©S§šU!„·€ÑhD¯××Î3ËUÛP7ÿ4„ª' ¡öÍ„B!þ†V­ZųÏ>Kbb".W,áàà€B¡àË/¿dìØ±\¸p¡¢B!Äíp‡d„B!„5éäɓ̜9›Í†‹‹ V««ÕZaNG~~>Ï?ÿ<¼ñÆèõúÛ±B!n5I !„Bñ–——ÇôéÓIMMÅÕÕõº ÿrtt$11‘áÇӽ{wÆŽ{ £B!Äíô÷Ùª,„B!„¨4›ÍÆüùóyå•W0™L¸»»ßð\J¥6lØÀàÁƒY³fM5F*„Bˆš"‰C!„B!þa¶nÝÊsÏ=lj'¨W¯Jeõ¼-Ðh4|ñÅŒ1‚'NT˼B!„¨²UY!„Bˆˆ‹/òÉ'Ÿ`³Ù¨W¯6›­JÛ’+K§Ó‘››ËøñãiÔ¨|ð®®®Õ~!„BÜZ’8B!„âo®°°3fpþüy{ÂÐb±Üòûêt:NŸ>ÍC=D÷îÝ™0aBµ­nB!Ä­'?µ…B!„øûñÇy饗0x{{£P(nëý † 6Я_?~øá‡Ûz!„BÜ8I !„Bñ7Ç /¼À‘#G D­®ÙÍFjµ«ÕʬY³8p û÷ï¯Ñx„Bq}²UY!„Bˆ¿‘¬¬,>þøcÌf3AAAX,–[rŽáÒjµäåå1nÜ86lÈÔ©Sñòòªé°„BQI !„Bñ7`µZ™3g‰‰‰Þ²Â'ÕE«ÕröìYú÷ïO·nÝxÿý÷qpp¨é°„BqÙª,„B!D-ÃË/¿ŒÁ` 88ø¶Ÿcx3´Z-›7o¦{÷î|õÕWwt²S!„ø§‘‡B!„BÔRgΜaöìÙ¸»»Ó¨Q#¬Vk­L¼©T*ŒF#³fÍ¢uëÖ´k×®¦CB!’8B!n˜N§cÀ€²µNqÛðùçŸc0¿ã·%_‹ÙlF¥RÑ¿L&J¥lŠB!î’8B!n»»;Ë—/¯é0„ÿ0ß~û-G%$$Ä^©Øf³ÕtXUf³Ù(,,¤Y³føúú²nÝ:¢££kå³!„W’8B!„¢ؽ{7ÿ÷ÿGpp0µz•¡ÉdÂËË‹èèh6nÜÈ‘#GjÕÙŒB!Ä?$…B!„¸ƒ¥¥¥ñÅ_àææF«V­°X,µ6aXTT„F£aàÀÄÅÅñÓO?ÙW–$ %y(„BÜ9$q(„BÜùùù˜ÍfÜÜÜj:!D-QTTÄìÙ³ÉÊÊ¢I“&µ6ahµZ)**¢}ûöX­VV­Z…ÍfC©Tb±X€â­Ë’4B!î,’8B!n±o¾ù†ØØX, ­Zµbüøñ¨TªšKq[±b»ví"""ŸZ{Ž!€ÑhÄÏÏÈÈHbcc1¨Õj,‹=iXB¡PÔÚçB!þޤd™Bq‹lß¾§žzŠ;vàè舓“GŽáñÇç§Ÿ~ªéð„w „„Þ|óMÒÒÒhÛ¶-z½¾¦CºaF£¥RI¿~ý0¬Y³…BQa%ú¿nYB!DÍ“‡B!D5KIIaúôéäää ÓéJ­R©T(•J–/_ÎêÕ«7n-[¶¬áˆ…5-77—™3gâèèHTTT­>ÇÐl6SXXHçιpá+W®ÄÅÅWWWÌfsM‡'„Bˆ*Ä¡BQM ™1c'NœÀÙÙGGÇ ßø;88`µZ™2e >>>¼ñÆxyyÝæˆ…5)//›ÍÆÒ¥KIOO§Y³f(•ÊZ›0´Ùläç猧§'[·nE«ÕâááÕj-³êSi IDAT-¹åVKB!Dí$+…Bˆ*°Z­Ìž=›7ß|¥Riã_Ôj5EEEüç?ÿaôèÑ$%%Uû=„5Ãjµ²nÝ:¼½½íÅ’J®'%%±mÛ6Ο?G'ÞrrrÐh4DEEGrr2aaa7]ºd‹²lUB!î’8B!*é÷ßçÅ_äâÅ‹xyyÝò7·Z­–ôôtžzê)&L˜@AAÁ-½ŸâÖ;~ü8èt:{%û1f³™„„víÚEZZ6›íŽÙº[PP@nn.;w&77—;vF½zõªí’4B!î,²UY!„¸Ž³gÏ2kÖ,4 ÞÞÞ·½€ƒƒqqq 4ˆÞ½{óüóÏË›k!j©]»váää€^¯§¨¨È~¶ßÕ« GÅÍÍ àìì\S!c6›ÉÈÈ U«V$''³nÝ:7n\&æ›eµZQ*•wL¢T!„²âP!„¨Á``Ê”)|ùå—Ô­[·F߸+•J ¿ýö÷ß?+W®¬±X„7.%%…¼¼<²³³í«ˆqssÃÙÙùÿÙ»óø(Ë{ïãŸÙg²/ÈÂ’BvB«R7ì9.=õ¨Ý{NÏéyµµµÕóœ>ÖVÛZµZkëZíA¥* û²“Y !$!ٷٗç4c"[ÌÀïýzñ2ÌÜsß×ráýßuýÎh°Ô××GEE555X­Ö+>ÞÎÎNôz=IIIäçç£T*IIIA­¾|õòÁˆBá9$8B!ÎâÍ7ßäñÇG­V6ÕÃqS«ÕX­Vžyæî¹çªªª¦zHBˆ Ðétèõz”J%}}}ô÷÷c2™°Ûíøùùä^¾<ÂårÑÙÙIii)WdÿÃÞÞ^zzzX²d MMMœ8q‚¬¬,BCC/ûµ…Bá9$8B!F),,ä?þã?hnn&**êŒêO¡Ñhèììäk_û>ú(½½½S=$!ĈF£‘îînP*•øûû€¯¯ï˜ÑétÒÒÒBEE—%@4›Í´´´œœŒR©d÷îÝddd0þüI¿Ö) ©6B!<Œìq(„B§OŸæùçŸG¯×3gΜ+¾áÅÒjµTVV²víZnºé&~üã_Ö%„BˆÉS]]MHHÓ¦MC­Vãt:1›Íî°P£Ñ R©P(î½].v»ÆÆF:::ˆŒŒ¼änÆ0¼akk+sçÎE¯×³sçN222ðññÁáp\ÑùPÂC!„ÂsÈ…BˆkšÝnç·¿ý-ÝÝÝDFFâr¹¼"0m¤Jçã?æïÿ;ÅÅÅS=$!Ä8´´´ðÉ'Ÿ””D^^*• «ÕŠÕjE­V£ÕjÑjµh4, v»›Íæ®44™LÔÖÖâççÇŒ3ÆT'ND[[†E‹±ÿ~bccYµj‡ãŠ,‹1Ò$Fš£!„žC‚C!„׬?ü‚‚¢¢¢ˆŠŠÂétzí «B¡ %%eJš'!.žËåâÈ‘#„„„ ×ëILLÄn·£V«Q*•(•JÔjµ»êp¤zô\588ÈÐÐÚ“udÃÌÌLòó󩬬俛o¾âá—Ë…R);) !„žD‚C!„לªª*Þxã f̘A\\œ×,K>‡ÃÁôéÓY¹r%555Sr³/„¸t!!!Øív ˜>}:óçÏÇl6388ˆ¯¯/ƒN‡F£Ál6c³Ù°Z­îÑårÑÛÛËÀÀAAAŸóZf³™¦¦&°ÙlìÝ»—믿•Jåsˆ,UB!<‡‡B!®<ÿüóhµZâãã½:0t¹\hµZn¾ùfêëëyï½÷ !$$dª‡&„8ó…býýý8NšššèììdîܹDDD`³Ù0èt:|||ðõõÀb±0888f.s8tuuÑ××GPPûXž7êëëñ÷÷'::šÂÂBrssY¼xñ”U~‘·V} !„W+ …B\õ\.¯¾úª{ãÿ‘Ǽ•Ëå"55¶mÛ†Ñht¿©Ô»éõzôz=ƒƒƒTWW»+ýýýq¹\î&)#K˜õz=‡cÌ2fÞ¿µ³³Ó½„¹££ƒþþ~RSSÙ³g*•Š»ï¾ÛcÃJ¥Ò«çg!„âj#Á¡Bˆ«ÚÎ;Ùµk111Ì›7ïŠwL‡ƒ3f™™ÉŽ;èééA¥R¡T*q8î&)BÏu¡ŸQ‡ÃJ¥ÂÏÏ€¾¾>JKK "11ÑÝUY¥R¹ƒÃ‘Çf³»Ýî>ŸÉd¢¦¦†Å‹ÓÛÛKYYëׯ÷¸À@„B$» !„¸*555ñä“OR[[KRRz½~ª‡tÑœN'†µk×¢P(øàƒ0›ÍÝAUá™æÏŸB¡ ¯¯ÏýX`` ¾¾¾tttŸŸOuuµ{C‹Å€J¥B§Ó¡×ëQ©Tc‚·S§N‘™™ÉXµj·ß~»Gsž<6!„âZ$‡B!®*f³™_|€ääd¯ÞÇÐétb·ÛÉÊÊ¢¿¿Ÿ7º÷8ó´J!!Ä¥S*•,X°‹ÅBUU‡??? ÁÁÁØívioo'::šÙ³gÓÑÑN§ÃÏϵZMPP‹“ÉDkk+YYYóõ¯—Ëåñs‡B¡¥ÊB!„‘àP!ÄUãÝwßåäɓ̟?¥Réµ!€Õj%22’˜˜vïÞËåÂßßÿ¼Ë åf[Ïw®Šº’’222 C§Ó‘ššJoo/µµµh4ôz=jµšàà`,‹{ÿÃøøx÷žˆ.— ???t:jµ‡ÃÁÉ“'yðÁÝ[x©:B!<‡,UBáõJJJøùÏŽR©dáÂ…¨ÕÞû¹˜ÍfC¥RqÓM7ÑÕÕÅ®]»ðõõÅ`0LõЄ“à\u©©©´¶¶²gÏzzz "33“ÐÐPúúú°Ùlèt:‚ƒƒ±Ùl”••QPP€ÉdB©Tb4Àh4âïïO¿×mÕ ‚!„žÃ{fflB\ó*++yÿý÷™3gYYY^½,Ùáp`µZY²d uuu|üñÇL›6Í]54^R©#„wR©T¤¤¤`µZ©¨¨Àb±’’‚ŸŸQQQDFFrüøqzzz D¡Pàëë 7PÙ¿?aaa$%%¡T*ikkcáÂ…Oñ;£ÑHee%§N5¡V«Y´(…ÀÀÀ³«TJ]ƒBáI$8Bá•¶lÙÂÛo¿Í‚  ôÚ —ËÅÐб±±èõzvîÜIHH3gΜð²B—Ëåµß!®ç ÆÚÛÛ9~ü8 .D§ÓQ^^ŽB¡`Ñ¢E æÏŸÍf£ªª ‹ÅB@@€{lkkÃf³‘™™‰Ùl¦¹¹™˜˜˜+õÖÎàp88|ø0ÍM'øú*î_eçýNþ篇É^²ìœ¯“@„BÏ!Á¡B¯³sçNÞyçiiiq7 ˜;w®WÝp áççG^^»wïF«Õ2kÖ,ìv»×ìE&„˜˜‘¥Êçš«|}}9~ü¸{ë€ÒÒRôz=ÉÉÉhµZ-ZÄÀÀ555¨T*|||P(„„„000à¾0e‡'OžäPY _Zª!ÿÿñÕ¨q}šƒß}tî9Λæp!„âZ Á¡B¯âp8زe ˜L&w³ÚÚZ‰%""£+ï¬V+f³™¥K—RRR®]»ˆŠŠÂáp\òRk¹é³çgt¤’°²²­VKff&&“‰‚‚IJJÂßߟÌÌLÚÚÚhhhÀÇÇ­V{ƹ®ôö ÝÝÝ8°Ÿ¨P ~cfÁì1ÏÿçKì¯Àn·Ÿ±íȼíÉó·Bq­‘àP!„WÙ²e jµ­V‹ÍfÃétºo2­V+UUU466GPPÐv,‡ÃAoo/IIIôöö²mÛ6¢££ Æn·Oõð„SL§Óa4ñññ>_‚|èÐ!|}}ÉÉÉ¡§§‡}ûöF||<3gÎdæÌ™ÔÕÕÑÑÑáãÎWÕx9˜Ífúúú0èõzüüüÀÏÏoL€ØÝÝMYY'OžÄl>_}Ëå388H__¹¹¹tttpôèQ’““=®Rqeœ+Û¿?}ô½½½¤¥¥ÇÀÀF£ƒƒƒq8b2™¸îºëP«ÕìÚµ‹¦¦&T*~~~c®u9ƒÃ¦¦&Þ~ûMüG¨|mˆ§ìBuŽ»‹×7ì0¸!Î ^‰°S!„ã'eB!¼ŠJ¥B­V£P(°X,¨T* J¥­V‹ËåÂjµât:q8¸\.Z[[éèè`Ö¬Y„††^‘qZ­V:::ÈÌÌäøñãìܹ“””÷žŒ—ƒÜl áùFcK–,Án·søða\.ííílܸ‘¹sç²xñb233imm¥±±ƒÁ€N§C­VŒÑh¤  €ˆˆV¬XA]]»wï>£‹òå˜úûûÙºu+Jûi>xÂDÎÓy7ZàÉ?çÿ3¾óKÕ¡Bá9$8BáU”J¥{y¯ÃápWªÕjÔj5ƒ­V‹ÝnÇb±`³Ùp¹\Øívêëëiii!**ʽwØds:´µµÁ¼yóØ·o‹-böìÙWdÉ´Üp á=|||¸é¦›HKKcçÎ466Ɉ'33“ììlêëëiooÇßß߽ϫV«¥««‹ÖÖVæÎKLL §OŸsÉœçl6{ö졦òO|UÉckzÆõºçþ7eÂÂèáß+ç—|"„Bx …Bx­žž¦M›†ÃáÀn·£ÕjÝEU*•»êpt`g±X¨««ÃÏÏððpw‚ÉÐÙÙ‰B¡ ##ƒ}ûö1{öl–.]ŠÓ锿'BàìáþôéÓ¹çž{¨­­e÷îÝôôôàr¹¨®®¦¶¶–äädRRR˜3g555ôôô„B¡À`0`0hnn¦±±‘3f¸Ï{®ý/Æ‘#Gرý3¾¼BçéÃG?¾×uôÂï>€â—?ìBŸoHp(„Bx …Bx­íÛ·£T*¹îºë˜>}:v»¾¾> jµ___t:v»£Ñ8&¼¤¶¶–ÀÀ@ÂÂÂ.©IÉàà dggS\\LEEË—/Çn·{Dc!„ç8_˜GLL ¥¥¥äççc±X°Û픕•QUUEzz:‰‰‰Øívªªª°X,¸?ikk#))É}ÎK áZ[[ùèÈ 5rà7ƒÄδNèõ?^ ãØ%bd¬R9-„Bx …Bxµ††þò—¿pÝuב€¯¯/½½½¨Õj|||Ðëõh4´Z-CCC8÷òe—ËEoo/ýýý:¡V›ÍFCCóçÏ`ïÞ½äåå¡T*§$0”*!<ß…æ¥RIff&IIIìß¿Ÿòòr\.f³™pøða²²²HIIappšš€1MQF»ØyÁh4òñÇÓzªšç¿aåÖÅ>G] |¸*_û¸ä‚B!„÷àP!„W9ÛM·Ëå"&&†úúz\. ,@­Vc6›±Z­h4 î}m6V«—Ë…Ó餫«‹ÞÞ^BCCñ÷÷?ïœN'MMMèõz)..fñâÅîJ §Óy¹Þ¾âa0¸á†ÜûžMoo/Ó§OG£ÑœqŽŽzzzÈÈÈ`ÿþýèt:n»í¶ËÚ-y¼ …,ñÂÃMôg444”»îº‹úúzvíÚEWW0¼§ê'Ÿ|BTTÙÙÙ,^¼˜¦¦&z{{áT&z­ššÞï]rÂá?ô2-àâ¼Âj8ZïüäÌçÎ5*™¿„BÏ#Á¡Bˆ«†J¥ÂÇdzÙLcc#§OŸ&::šððpl6ðyWfFƒF£qW%Ž4Rq¹\X­Vš››1 ¡R© ¡¡””†††(--åK_ú’ûuB1 …⢖GGG3gÎÊËËÙ¿¿»£ü©S§8uêóæÍ#++ Nç¾Îx¯544Äë¯ÿ ‡±‰ÿý?ýdÆ™&<¾/ú·ßÁã÷sÖjÅsuUyL*…BÏ!Á¡Bˆ«Ž^¯G¯×344Duu5$$$ T*Ý7ÒjµN‡^?Ütd‰ñè›Y“É„Ùl¦¿¿Ÿ   fÏžMQQkÖ¬Á`0xd`(û áٔʋ\÷ûצ¥¥±`Áòóó)++s‡lÇçĉÜpà c^s¡®½½ßýöWüäŸÌüËÝ=¶Ñþ~jš†÷7¼oՙϻ8u¡ÌcB!„ç¸øÿsB!<Ì´iÓèëësß(ûúúâççÇàà ¥¥¥:tÈ]ah4éï àççç^Î<¢­­ÈÈH aýúõçlB0Õ.fi¢ÂûèõzV®\ÉW¿úUbccÝÞ2a<óÅbáw¿ý5¿~lhÒBC‡sxoÃß}w88|o×™ÇT58Ý•‘B!„ðlRq(„âªÁÌ™3©®®¦¯¯ÀÀ@p¹\tttÐ××ÇŒ3ˆÇápÐÑÑA`` jµ½^Á`Àb±`2™hii!>>žÚÚZxà)ë–<^R¥#„ç»Ø¥Êg̺uëhhh`çÎtvvžqîó]ë½wßä§÷¹cIߤŒàO› %Ö_'Û࿆)0#xøù–.èRŸ5Ô”>„BÏ#‡B!¼Ê¹n,›šš€á¥|‰‰‰,Z´£ÑÈàà ûuAAAèt:šššØ»w/MMM¨ÕjV«›Í†Ãáp/cö÷÷§¥¥…»ï¾ûŒn¥Bq1&;«©©A£Ñðàƒrã7º·_€ó/‹àpy1w-í™´±-ðßoÁÓÿþ?×ü(xìWŸó§-zÂ#çžõõ#!§|"„Bx …B\L&;vì µµ^Ê—––Ftt4ýýýîF*•ÊÝ𤦦†ƒÒÞÞŽÕjÅl6c±X°Ûí˜L&bbbÐëõøøøLå[›©Ø³)•ÊI Æš››9uêÛ·o'..Ž Œyþ\{~öÙgtt0ív¸íÇÕ‚]ý—6–§ß€»WÀܙÿW)áÏ?„-EðæV(¯Sñ‡OôDDD\Ú…„BqÅÈRe!„W…øøxæÍ›GUU555,\¸iÓ¦BHHMMM´´´àçç‡Z­F«Õ¢Õj1:t’““1 (•JÚÛÛñõõ%##cÒÆ¨Ñh Â××½^ÏÀÀÝÝÝôôô`·Û'í:BˆkG`` ÷Þ{/‡ƒ·ß~›œœàó=ÏRöôôðÑëЩLüýüß·á_ y‹`]ܱ f‡› àÓÈaìãó£ào>J•†ÔôÔ ~À!]•…BÏ!Á¡B¯r¾ζ¶6BCC‰çÈ‘#TVV’’’B`` ³fÍ"**ŠcÇŽÑÛÛK`` …Â]M800ÀþýûÉÊÊrïØÜÜL^^ÞEßÄΜ9“øø¢¢£ ðóÃG7¼ÜÙbwÐg±¬×¢Q ÿšÌtõôPUQN~~>'OžœðõdyŸžo²«‚}||ðóóãøñãìß¿ß^HGGs¦›H˜ ץ³ßî„ü÷°a|ÿ÷Ã{Þ¾î\‰sÎ}®’cðȳ°õ— ?Ë®?\ØX”†¿¿ÿ÷Š•àP!„ð !„¸*( zzz°Ùl455‹ŸŸåååØív-Z„ŸŸñññX­V*++±ÙlàïïÙl¦µµ•ÀÀ@T*Õy÷;___‰žOh`{[{ùùñjÚi1Zi1Yé¶ W*€éz ‘>Z¢|µÄøé¹+%›ŸÞ|3§ÚOS°o/[¶l¡¯oò!¦Öd6G0›ÍL›6cÇŽõZç á\.ðùXâgAü½ð÷BÏl*„¼4¼oáì°áJÄëÓaÁl°Ø ñ4üáïpà(¼ü}H˜=öü%Çu<ôŒ®AË–§¢×륺Z!„ð2 !„¸ªŒTž†QQQ,¿~'6þûX'=yœ£õœÇ»€Óf§Í6ʺ‡x¾ª•Y¾Z¾=‡oXÊU7ðÜ/Ÿ¡ººú‚×—ŠC!®=#û·FDDÆó;/ûÃËá‘_Âßž_=l-†_½‡jA§Yapc&¼ö_à£ûüµÝƒJþõ¹v–ÚHII%1, §ÓéÑ]é…Bqv !„¸ª8N”J%~~~TUU¡ÑhHKKÃjµR\\ŒÁ` 99™€€233imm¥±±qLÓ‚‰Ül+ RÓÒHMMãÿnæ§å§p\Bˆ×4dåGšy®ª•_gÎáÉŸýœ7ßø ~øáÇ!ÍQ„ðl—ãg´³³•JuFpx¾êF…BÁ…ï)þï ÃAáu©ç?Þå‚§þ:_ÿÕLlÜ\n¹%—Ë5¡*C—Ë%K•…B"Á¡Bˆ«‚Ëå"!!ªª*ŒF#AAAÀpã—ËEyy9>>>dgg300@~~>ÁÁÁ$%%Nxx8ÇŽC§û¼lf¼7ø .$6)™ÕÛªØÖ:yËŠ-'ß(¨gG[?þ§¦¿¿Ÿ­[·ž÷5Ru(„g›ì®Ê0ü‰¯¯ïYÏ{)×ÚTøyhx!Ÿðç”è|CXsK&Z­‡Ã!U†B!„—“àP!„W9W˜÷þûï³xñb’““1›ÍTUUa·Û @¡P„Ó餴´”€€òòòèèè`Ïž=ÿhbÏüùó'|“­ÑhHNIå+ûê&54ío ]Ì0hxê«ÿÂŽ;Îy#.¡¡žoôæt:±Ùlc>°¸˜ó©ÕjÇ<>ÒUù|¯s] °oS|ÿžóSß®ã_ž ¢æ”‚ÜÜ¥„††^r`(s™Bá9&¾ë»B1…FßPÆÇÇ£Ñ —ÂôööòÙgŸñÑGÑÛÛKZZóæÍc``£Ñ Wúár¹(,,d``€ë®»víÚE]]Ý„—È…††¢P*ØØÔ=yoò,Þ?ÙE¿‘‘‘ç=N–* á=6mÚÄ /¼ÀÆéî¾ø9Än·£×ëÏúÜùB8çž/N¶ wY^»äìÏ›m ¾õbYß0  NáÎ;ï",,lBã>×X%8B!<‡‡B!¼Êè`,55•‡~˜… ºkoogãÆ|öÙgdffNoo/‹•JEpp0&“‰ÂÂB×_=J¥’¡¡!÷¹ÆsóˆÃvçå½Ñ5;œ¸\.æÎ{Þã&»c«brîÖ>cÆ fΜɱcÇøÓŸþĦM›èïïŸÐù\.V««ÕzÆÏ¾R©¼èý7@ú<=ó¹W·†ýό⾯ü3 ,¸¨k!„ÂóÉRe!„^Í××—Õ«W“––ÆÎ;9uê0ÜU¹¡¡øøx233ÉÎΦ¾¾žöövüýýQ«ÕhµZ´Z-½½½´··3kÖ, 0þF#f³­RÁMAlié½lïsÝìœ(d¿“Ñ8 IDAT0!¼ÜèpÿÞ{諒½¢¢"ŠŠŠ8zô(UUU¤¤¤““3®nïCCCX,t:ݘàðBó×ð8Î}̦B¸5gìcEµ<òk_†l~ܾîz&uÑ1ˇB!„çàP!ÄUaÆŒ¬_¿žcÇŽ±{÷núúúp¹\TWWS[[Krr2)))Ì™3‡cÇŽÑÓÓCPP …½^^¯§©© ‡ÃAhèYJlÎÁf³aq8y%7–[·WQÑcœô÷¶4ÌŸg³æb²Ù/xƒ>JÈ’e!<ÓèŸÍÙ³gsûí·“––FZZÅÅÅRVVFEE™™™dees2€Z­æwÞᡇÂjµºw¹\lÄr®Bi‹ v”Âÿy`ø÷]¾ñûv—™¸á†ë™;wîem|"]•…BÏ!Á¡Bˆ«Êüù󉥤¤„ƒbµZ±Û픕•QUUEZZIII8*++±X, Óé°ÛíÀðM÷x«^ÌvÛZû8xËB¾Sx’WŸž”÷¢þsa$O§Íæ÷5­Ü7;øÂ¯‘¥ÊBx>ú»ÝNVVéé餧§“––FQQ………PVVFvv6éééî=]GKKKcÛ¶m<óÌ3˜L&RRRÆ<®î|.ì­€_HŸ§àé¿Íæ7ï ž±€ÇËpÏ““Mæ.!„ÂóHp(„⪣R©X¼x1 .dß¾}>|—Ë…Ùl&??Ÿ#GŽ••EJJ CCCTWWÕ;C¡Pð/ûkÙw:Œ²£¹cvªíà“S=˜¯œñU+¹mVΟAZ¨/ë÷ãº.ÊM·žot`~~>§NâСCdff²téRwõáH€XTTÄÞ½{)..&''‡””T*•û|ÜyçÔ××SRR2¡±œ«9ʦHŽ3ÿp ÁÓÂxäÑûÑëõ8Î+²]‚ÌeB!„çàP!„W™È\nºé&÷þ‡ °cÇÊËËÉÎÎ&##ƒ®®.ªªªÜÕ‡¹–òǽvü4Ń|?)‚×–Æ¢PÀÆÆ64vq¬ÏL³ÑJul¥Ž˜®×0ËWK¬¿ž;f‡pÛ¬`,ºyø@µæq¿g›n!<Ùèyåæ›o¦¡¡W_}•²²2ÊÊÊÈÌÌdÕªUîð0==ÂÂBŠ‹‹Ù±c………,]º”… Ž9Wtt4ÑÑÑg\ë|óŦÆÎI'Nðæj] ÷Üs‘‘‘8ŽËVe8šl± „Bx …B\õ¦OŸÎ=÷ÜC]]»ví¢§§€®®.>ýôS"##ÉÎÎfÙ²eŸïQ8î›ØQ7æ=FÜW‹N¥ä–È ÖGOã•ÜB´ÃK '§†¬tšmÌ0hˆòÕ¢ûG—ÕÓ&››{¹g÷q¶¶ôb›`§æ‘½ %8Âs}qßÁ9sæ0gÎ*++yùå—ÝbVV·Ür‹{ùrzzº»qË–-——G||ü9¯¥P(ιT9((ˆýU,IèÀdSóÃ7bywK77ß²šŒŒŒ+Va(„BÏ%Á¡BˆkFll,ÑÑÑ”••qàÀ, ÍÍÍlذ¸¸8–,Y2áóª•gŒ‡“»ù ±ƒJI„–-‘>ZB´j:-6šVZŒVZLÃMVÎG¥”PPˆ«Iqq1•••¤¤¤œœLbb"………¼ôÒK:tÈ ®[·î¬K˜ÿþ÷¿sðàAòòòˆ‰‰9ãüçûð#11‘'ÿt³c6ýZÞßÞOò¢h~ø£¯£V«§40”æ(B!„çàP!„W¹Ô¥lJ¥’ŒŒ 9pàåååî›ÔÚÚZ/^ì>v¼!FM¸AK«ÉzÎcL'ufê&¸ìxDVMˆAwÞ÷¯P(¤âÐËÄÆÆ’ÍŒ3¦z(â ý3ÜÕÕÅéÓ§Ùºu+ùùùäåå‘••EFF{öì¡°°ÜÜ\÷æûî»Ï]8Ò…¹´´” 6ÉŠ+ˆˆˆ×8–.]ÊéÓ§ykG9111|ëÛË ½¬Ý’/ddî’àP!„ð !„¸& V­ZEjj*»ví¢¾¾øüÆu$„‹ÓÅ7fðxYÓeï—fcw¹ÎÛÀE–*{ŸŸüä'üä'?™êaˆ+hôÏè]wÝENNEEE”••±iÓ&òóóY¾|9+W®Äb±°}ûvŠŠŠX²d‰»‰ÊC=ä´”²²2wâH€8þ|üqŒF£WV „²TY!„ð !„¸¦…‡‡ó‹_ü‚·ß~›}ûö±|ùràóe¿ã¡P(ø ±›‚ÎA^_Çñ/§ñ÷¦þ·¡‹Íͽ˜.Ðôä‹‚µjÖDñ𼤅øòO{Žó·†.ÖÝ•vÞ×Þˆ ÄÏÏoª‡!&Éè®Ê›7o¦»»ÛŽˆéééRTTıcÇxçwˆ‰‰aÙ²e¬_¿ž'NðÑG¹¨dff’••Å¿ýÛ¿ñÎ;ïÈ „BˆI#Á¡B¯r©ÍQ¾È`0ššÊ¾}ûؼyóE]Gùc[ŒVnþ¬’usB¸sv(¯/‹C­€Í-}ê¢ÙhåÔ•SF §M6ü5*BtjBuBujæúéXDn˜?Ý›š{ùêþZ-“úž…whmmåÉ'Ÿ¤¡¡ØØXžxâ ¦OŸ>Õ×hôܲråJvïÞMAA¹¹¹dee ŽT ÖÕÕqâÄ Xºt)<ð¼÷Þ{cªG7xRzº‘k´Z­×ŒY!„¸Hp(„âš§Õjþ£¸â®AœqïìMA8;«ÕÊ/~ñ Ñh4èt:y衇ÈÉÉá¿þë¿Ðh4S=Lq‘”J¥ûk•JÅõ×_ÙlfÛ¶mî.Ê™™™cÄÑK˜«««©©©aáÂ…ää䜜ÌÁƒyë­·(++#44”°°0\.—×Ì6›ððpV®\Iyy9k×®ê! !„â$8BqM³Ùl N¨‹ò)Ïñ2«ÓŦæ^65÷ŽyÜ_£"L¯aÀæ ÇjÇ6΄P¡¸p˜ém{š‰±þú׿òþûïãt:ÑétcözS(ìß¿Ÿ;3»îº‹x` G*&CCC $%%që­·Ò××ÇÇLqq1ÙÙÙî%È#”Gš qøða*++IIIaÉ’%dee±k×.Ž=Ê]wÝ…B¡Rz"«ÕŠ^¯gõêÕ455áççÇ‹/¾èñãB!®% !„¸æ½òÊ+èt:bbbÜMdC?íðRã.Ëø:Ø Ø£ŸZE¨A'M®Rååå<ûì³ ¡Ñhp:gý³V(Øl6Þxã >ùä¾÷½ï‘““3#kt¸_TTÄÉ“'),,$!!eË–qçwÒÖÖÆûï¿Oii©{ rff¦{ùòè ÄÒÒR***ÈÌÌ$//ÜÜ\4 ]]]€gîyêp8°X,ddd€Édâ©§ž"0ð  „BqeIp(„«Lö‡ …ƒÁ€N§sƒ=Þ D…BÍéâÁØéüª²uRÇ6Úªð@œ€N§;ç1ÞØEõZ×ÛÛËÏ~ö3ÜÇ+•Jº»»ùÑ~DLL ?ÿùωˆˆ¸#—jô¼rë­·ÒÐÐ0f rrr2¹¹¹Üwß}ÔÕÕñÆoŒÙÃp$@üâæƒRQQÁªU«ˆw_ËÓæƒ"##ÉÊÊ¢¶¶–{ÄÄÄ©–B!ÎA‚C!„×<«ÕŠZ}qÿ$º\.,vO¥Ï¦Ýlã­“<:ˆöÓñëÅs1ÛgìÃ8ÚH áiA8“Óéä7¿ù À`0àëë{QÕ¤ …‚'Nð•¯|…œœžxâ ôzýe±˜,£÷!]·nF£qLXQQÁ‘#GHOO';;›û￟òòr^yåÊÊÊÆtQYÂ<ÒDe÷îÝlÞ¼™ùóçO¨júJèëëC¯×³nÝ:ª««‰‰‰á»ßýîTK!„ Á¡B¯µgÏIMM½èj+…BÕjÅétž¸7€³9üŸòSüqi,k¢‚ùFþ ú'¸ù\îÊ˹1ìÀ?È0)çSkóæÍ¼ñƨÕjüüüÎúwo¢\.{÷îåÖ[oåÎ;ïäë_ÿú$V\Neee¬_¿Þ½9==ÂÂBŠ‹‹)..¦¼¼ÜÝiyÑ¢E8p€—_~Ù fee‘í®>œ3g¯¼ò ƒƒƒó‚Ùlf``€œœL&‡ƒ_ÿú×ç­žB!„çàP!„W]AÓÖÖFcc#•••DGG³|ùr¦OŸ>ásN›6íŒ%}¹éV(üº²•í­}¼•7ŠÛñZm4vs¸Ç8áñ(°dº?ÌŸÁW¢§ñ£ÒFž=ÚBû]i~­tUöX'Nœà¿øCCCøøøàr¹&uÏJ…BÉdâÏþ3Ÿ~ú)ßùÎw¸ñÆ'íübrŒžÃ>þøcúûûÏG*‹ŠŠ8pà%%%,Y²„ììl²³³Ù¹s'%%%:tÈ]¸bÅ ÒÒÒØ¼y3N§sÊ« ].mmmDGG“Mww7ßýîw‰ŒŒœÒq !„bb$8Báµ{ì1JJJ(**¢¾¾žúúzâããY¶lÁÁÁã:G?0±f(_4òªŠ#YŸæñ3¸sN(?Mʼn35vs´ÏDÓ…¦!+§†¬ Ú(¬UªSªÓ0×OÇš¨ ÖD U±§­ŸÜOPÜ58®qŒ†z“ÉÄÓO?M}}=½,y¼ §OŸæ‡?ü!¯½öO=õ±±±—ízbbF‡û‘‘‘üùÏSA8~qÃÝ»wSTTÄÒ¥KYµj&“‰íÛ·SRR2fÄn¸ø|N›Š†Jíííèt:n»í6ª««ÉÍÍeÙ²eW|B!„¸t !„ðZ>ø ™™™cªsjjj8vì .$77ÿ󞣫«‹ææf"##/:p7šN~UÙʯ*[ 7h¹cv0·F…p묢|´ø¨• Ùø¨”î°Ò ´­liîåÑü:¶¶ôM¸ó²ð<¯½ö;vì €   +ê* Ž;ÆúõëÉÍÍåé§ŸÆÏÏïŠ]_œ]`` ÇðÏvxx8wß}7µµµ¼òÊ+c*o¾ùfwå‘9®°°­[·RPPÀ²eËøÒ—¾DOOÛ·o§´´”²²2÷øñ6xšLýýýôöö²|ùrš››ñ÷÷ç7¿ù J¥òŠŽC!„“G‚C!„^kóæÍ\wÝug­Î9|ø0G%--ììl|||Îzލ¨(þð‡?°xñb:::.jçº9o5Yy±¦kÚÝkÕDùj Ók°9è¶Øé¶ÚéµÚqŽ#SºPðä‰]T¯Eùùù¼úê«hµZBCCq:SRù`·ÛÙµk7ÜpwÝuÿþïÿ.AÎZ¸p!*•jÌcqqqÄÅÅQVVÆK/½Dvv¶»‚ð¶Ûnsˆ£ç¸O?ý”‚‚òòò¸ûî»9uê»wïF«ÕrÓM7]Ñæ(6›'N°`Áâââ°Z­üìg?#00ðŠ\_!„— øéã?~ÑÝ$…Bˆ+iß¾}˜L&`x°ÎÎNl6©©©dgg3sæLÂÃÃñõõ¥»»›ºº:ÊÊʰÛí̘1ãŒï"## çÀ¸\.,XÀàà :Ž àr¹ÜûÑ|=òK¥R‘¼ ßV·ar\82;œœ6Û¨´Ðl´Òmµcr8¹PÔgP)ùyúl>ùøc:::ÆŒad\†ˆˆ–-[†Á T¦B{{;?þ8EEE¢R©ÆüYgýz"¿¾øºñžÇjµRVVƆ  $!!aj¾I‚ˆˆòóóq8h4÷ãááá$&&räÈvîÜÉéÓ§ikk#((ˆo¼‘èèhÂÃɈˆÀårQWWGuu5'Nœ`Ö¬Yäåå¡Ñhf``€¹sçÒßßOllìÎ6Ÿï×èãG][[‹B¡`ùòåôööòÀpçwJwo!„ÂËÙívž~úi …Bx—ýû÷c47ñññaãÆœ>>$%%æ®LB«Õ^084›ÍÌ_°€ºA+‡º‡.Ûû¾!"Š™ÎŸ^{ ‹Å"Á¡‡±Ùl<óÌ3¼÷Þ{øûû£Óé.úþúJ‡#Çö÷÷³mÛ6¶nÝJrr2aaaSð»¶EFF²víZZ[[©©©A§Ó¹«@ ³gÏfÞ¼y’ŸŸï§M›ÆêÕ«™5kÌœ9§ÓImm-•••´´´°hÑ"üýýéîÁass3---¬ZµŠÁÁA²²²øÎw¾sQ ª„Báy$8Bá•F‡ƒ¤¤$ìv;7näÔ©S´··£T*ÉÎÎ&%%Å jµZÚÛÛ9~ü8‡F­V6fÉæèåÌã N'v«•û3°¿cÆ!ˤ¿ç`­šw—ÅP²g'öï?ç ½F£!22’¥K—Jpxmذ矗ËE@@pî oôsç;îr‡#_wttðþûïSZZÊŠ+¤Bì S(ddd°jÕ*ÊÊÊhmm3©T*bcc™={6{÷´”öövÚÚÚ˜9s&·Þz+„‡‡†ÍfãøñãÔÔÔ••EOOsæÌ™ôàp``€£G’˜˜H`` þþþüèG?"11q ¿›B!„˜l !„ðJ£ƒÃcÇŽÑÚÚÊìÙ³III¡»»›?þ˜¶¶6ÚÚÚÐjµ,]º”¤¤$÷ ¶Z­¦¥¥…cÇŽQYY‰^¯gúôégì6Þàp$€ÑkÔü g!*¥‚½í\z<^¹aþì¸!gO/üæyÌfó9oèÕj5QQQäææžsOG1y*++yâ‰'hii!$$ÄÝ-w¼ÁÝ诧"8p8Ô××ó—¿ü…ÀÀ@-Zt¥¿×ûŒõë×_ô˜Ìf3{÷îa×®LŸ>ØØX~7РYhþÑ¥Çd¡ÃlÅO­&H¯ÁG3üϱÝáàXÝ ïØÏ[¥¥477ãp8Æ}m…Bá^.+&×öíÛÙ°aÓ¦M#**ʼx#…BArr2Ë–-ã“O>áØ±c|ÿûߟêa‰Q”J%=ö÷Ýw¿úÕ¯8uê!!!cŽIHH !!’’Þ}÷]÷ü6²¿©B¡¸è¹Àb±°oß>bbbHMMÅf³ñÓŸþ”   K~oB!„ð. !„ðZ­­­î0--ôôtŠŠŠ())á“O>!??ŸåË—³fÍÙ¶mÅÅÅdggSVVFVV÷ß?iii¤¥¥ñöÛoSXX8©ã;uêÎ;±ÛíhµZ|||ðóóÃ`0`6›bppz{{±X,Øíö †#$0œ|<÷Üsøøø0gΜN§×†.—‹°°0n¿ývöíÛÇ«¯¾ŠÙl>cOá9yòÉ'©ªªâå—_Æl6ãïï?昌Œ ÒÒÒØ»w/o¾ù&ÑÑѤ§§_ô5óóóQ(¬X±‚¦¦&î¾ûn’’’.õ­!„ÂKIp(„«Œ9^ýuŽ?NVV<ð€;@©>,//çÃ?dÆŒ¬X±‚;î¸ƒŽŽ¶oßNii)eeeî ć~˜øøxÖ¬YsÙÆn2™¤µµ‡Ã1æ×ņ…£¹\®Kª2Ÿ3›Íüò—¿¤··×]ax©>SÅåra0¸á†èëëã7Þ```@þžx‘ ðÜsÏññdzqãFôzý˜*J¥’+V““ÃŽ;Æt‹oÐ}üøqjkkY¾|9Ç'::šï~÷»“þ^„Bá]$8Báµ:;;yá…Xºt©;ü×ýWwáH€xôèQÞ{ï=fÍšÅòåËY¿~='OždÓ¦Mîðp¤199yªßÖE $º4o¼ñ%%%Ìš5 ???¯­0„á@)%%…¸¸86oÞLWW—{IûH:ò÷E*=ß­·ÞÊš5kx饗())!$$dÌŸ›V«eõêÕtttŒëœ}}}ìܹ“äädbbbxæ™gÆ“B!„¸vIp(„Âk¥§§“ššÊÞ½{)(( 77—C‡‘™™É£>:fùrQQÕÕÕ¼õÖ[ÄÆÆ’——Çý÷ßÏÑ£Gùàƒ(++ãСCOõÛš0§Ó‰¿¿?¹¹¹444 Õj§zH^©¸¸˜·Þz‹3fçõË’gΜÉM7ÝÄ–-[())A¥R¡V«Ï¨œ ž$pö*•Šo~ó›twwóÜsÏÑÒÒrÖyK¡Pœ7 v8lÚ´ ___/^ÌÀÀßþö·‰ŠŠºœÃB!„—‘àP!„×êééq/ѳZ­lÛ¶ÂÂBrssÉÊÊ"33“GyäŒ ÄÚÚZêêêX°`K—.塇¢  €÷Þ{éÓ§{MÕáHWÔÔÔTfÍšEww7O?ý´W†ŸS©³³“gŸ}ƒÁ@||¼W†N§½^ÏêÕ«©ªªâõ×_G£Ñ Õj/¸ÔzôòVáùBBBøÙÏ~FEEüã±Z­øùù9æ\aðÁƒ9uêK—.¥¶¶–œœòòò®Ä°…Báe$8BáµÞÿ}úûû™={6Ë—/ç–[napp­[·R\\Ì’%KÈÌÌtˆ£÷@,..¦ªªŠêêj’““ÉÉÉ!++‹ƒºÏïÉK7- 3gÎdÙ²eTVV²råJ²³³§zX^Ån·óÛßþ–ÎÎN¢££ñïçi\..—‹ììl|||ظq#v»½^ïµïIŒÏ¢E‹xþùçùðÃùôÓOñññA£Ñ¸—¤›L&÷±MMMìØ±ƒ%K–`³ÙðóóãÙgŸ•ÐX!„ç$Á¡B¯2:Ì[¹r%åååœ|}}Q©Tãjè"K”¯wÜqk׮套^¢¬¬ŒÐÐPúûûioogÇŽ444ÅÂ… ±Z­<ñÄMõ°…Báá$8Báµ{ì1ÊÊÊ(..¦°°ºº:êêêHLLdéÒ¥¬_¿žúúzÞ}÷]÷†#ˆ#ûŽT Õoí v»£ÑHzz::³ÙÌÓO?¿¿ÿTÍ«ôõõñÄOP__Onn.*•jª‡tÑl6ƒ;½{÷òî»ïD@@€×v€—F£Ñðío›ŽŽžþy X³f jµšÐÐP:;;¹ë®»HJJšê¡ !„ÂKHp(„ÂkEDD°xñâ1`QQ•••TUU‘’’BNN÷ß?GŽáõ×_ÓA933ÓýÚôôtÞyçš››§úm¡§§‡ÈÈHV®\Icc#_ûÚט?þTËë¸\.¾ñoÐÔÔ„R©dË–-Ì;—””÷ÒNo¨Üt:8–/_NOOýë_ñ÷÷gÚ´i ¦OŸÎSO=ʼn'øýïOxx8+W®$33sª‡&„B/#Á¡B¯2:ØùãÿH^^ž»‚ð‹MP:ÄáÇÉÈÈ`ñâÅ$%%QPPÀ«¯¾Ê¡C‡Æ,aNOOgöìÙ|ýë_œN§BCCuþùçkÅŠ*++Sbbâ †Àц•ƒOÿ¼ä’KTWW§^xÁJAA?@ì {+?ûì3­[·NsçÎÕÂ… år¹´råJÿ½%%%ÊÈÈ44UXn·[ûöíÓ„ ”››+»Ý®Ûn»M‰‰‰§|.#Ýn×¾}ûd±Xd³Ù,·Û-‡Ã!§Ó)©'°]·n¢¢¢”­ˆˆÆ!­>t¹\òx<:÷ÜsµuëV½òÊ+7nœÂ pÒ†• .¸@>ø âââ$I ºúꫵ{÷nýñô/A.((Ђ ú,aî­>üðõvíZÍŸ?_]t‘ÚÚÚôþû﫸¸XÉÉÉþgÊð°²²R!!!ºôÒKµcÇ{5kÖ){þHWYY©úúzEDDÈl6Ëf³ÉjµÊb±Èn·Ëår©»»[>ŸOÍÍÍZ½zµ’’’”™™©°°0™L§öW&¯×«ŽŽM™2EV«UË—/W||¼&L˜pÒª ‡ÃþŽ8µÃJvv¶’’’ÔÔÔ¤ˆˆÿõôôt¥§§kÓ¦Mzúé§ûìa¸dÉÿòåƒ÷@|ï½÷´fÍ-X°@W]u•ª««µzõjÿ˜§"H©¯¯W[[›.\¨ÊÊJÅÄÄè»ßý.!ÎIÒ¸ù÷2 VPP ƒ¿ÂO’jjjTWW§´´4eddÈ`0œ’êÃöövEFFjþüùzï½÷d2™4iÒ$¹Ýî“VeØ»l8˜QÒÝwÝu×)ÿK:ÇkñâÅ2*--•¤>ÿ ‹×Ô©SUVV¦÷ß_õõõª­­Uhh¨Î>ûleee)))IIII Òž={TVV¦íÛ·küøñš;w®¤že«V«U“'Oö‡*^¯×ÿùá>îs¸Ï}>Ÿìv»ÊÊÊ”™™©±cÇ*88X?ùÉO”——Ghx455éõ×_—Éd’×ë•Ûíöq&“IF£Qf³YF£QAAA}¾WÍÍÍþ“˜ÃÃÃû„wnGûÙ8´ß¡÷ØívuwwkÉ’%Ú³g6lØ ¬¬,EDD øço ?‹‡~x<Í›7OÍÍͺ袋Ný7§·Û­_üâT†§‹.ºH矾žyæ­]»VÑÑÑþý ƒæÎë?¥°°PsçÎõW ^qÅ}ö@ì=Då•W^Ñœ9stæ™gž´ ,ŸÏ§Í›7+**JK–,Q]]®¿þzMœ8qП…/|ØËåòŸžìr¹$³Ùì¯<ìm;8 t¹\*++Ó¾}û”‘‘¡ØØØ>ûmž—Ë¥¶¶6ååå©©©Io¼ñ†²³³•œœ,·Û=(ÏŽÁ!`Ø2úÎw¾£k¯½V¿úÕ¯TUU¥èèh»ÉdÒâÅ‹e·ÛõÁ¨°°PsæÌñïxíµ×ú—/çååéõ×_×¶mÛtæ™gJü¥Êååå²ÛíZ¼x±ÊËË•­þð‡ƒú ôïàïekk«vîÜ©ŒŒ ÅÇÇ«³³SF£QV«Õ¿ï¡Ùl–Óé”Ëå’Óé”×ë•ÔS‰ºqãFEFF*--M6›í¸O»öz½jjjR||¼rrr´jÕ*¥¤¤(??ÿ”Ÿ–ìóù-ÀÈApöÆŒ£{î¹G[¶lÑÓO?-‡ÃÑgÿÃ]rÉ%jnnÖû￯uëÖõ9DåÆoTnn®âââôÈ# úüöï߯;w*??_²X,z衇Ž;p‰s:Úºu«ººº«ÐÐPuttÈápÈd2),,Ì€Jpp°º»»ûˆ---Z¿~½ââ┚šªÐÐÐcz~[[›¼^¯-Z¤•+Wª¡¡A³fÍ:åáÁØã‡"8ŒS¦Lѯýk½ùæ›Z¶l™¿z¬WTT”¾úÕ¯ªººZ+V¬PqqqŸCTî¹ç=ûì³’ú.m=^.—KkÖ¬Qrr²æÍ›§îînýøÇ?VBB ‹cw¸ïeïIÅÛ·o—ÙlVPPÜn·ºººdµZý¢X, uwwû—û|>Õ×׫©©IIIIJLLbïA+»wïV]]’““&¯×«ÚÚZY,-\¸P+W®TRR’–,YrZ†cCŠß#Ztt´î¹çÝzë­r¹\êèèè“››«o~ó› ÒæÍ›ý×%ìkoo×òåËe45cÆ FÝ}÷ÝúÚ×¾Fh8L˜ÍfEGGËh4Êív«³³Sr»Ýr8þ Ðd2)88X‹ÅóÁìv»vîÜ©;vh÷îÝš={¶\.—>ûì3-Y²DÙÙÙCô†‡GÅ!úCÅ!`T˜>}ºüqýóŸÿÔÛo¿pnPP,X ¹sçÓ¸>ŸO+V¬ðW”566êºë®Sffæ`¿NÀ‘Â[›Íæ¯ ´X,þÓ•ív»º»»ý§.K’Ãáð/Y>¸o{{»º»»ý\o5á”)S´råJ-Y²DÁÁÁ§U…áÁ|>÷)²¬j­²#ÆjbxÒ€úïê¨S¥½A¹QéŠ0‡œðó[]v•4ïRZh¼ÒBãOx¼^kwÈáéÖYñ9'4ŽÝãTY[•šº;”ž¬ÔÄÏ&C…à0ª\~ùåºøâ‹õ»ßýN¥¥¥ŠŽŽîÓn2 ü?ëÖ­See¥.\¨Ý»w+''GK–,ì)ciC‹Å¢9sæø—GDDø÷4 Q[[›?´X,²Ûíòù|}‚ÃÈÈH9N¹ÝnÙív™ÍfÍ›7OúÊW¾rÚ-K>‡§Æç eºüã_êÁ™7è'Ù_9bß÷|¤ÛKžS£E’d0h^ìd½8÷GwÌÏÞÕQ§ë>Tkvȧžïw’-Jç}[_7ÿØ_æ ^ŸOK?ù¥ÒBãµzÉÇ5F¥½A?,þ£^¯\㟟$¥ØbtßôkõÍŒs,UŒ:&“I?øÁôàƒÊjµª¥¥¥ß~‡ SªªªôòË/+**J™™™²Ùlzà Oc‡«¦kllôŸ’œžž®Y³fÉçó©¹¹ÙÿýˆˆPxx¸\.—ºººÔÙÙ)©§ªÐétª««Ë¿„¹wÄ .¸@åååš7oÞ©yÁA@ÅáÉ÷ȶ7Ôï¾Í×7>\uŽM‹¯+ÆÎQ¤9TŸîߪ‚woׯ–½ÇôÜâæ]*x÷v}Ѱ]1–p]9v®²#RUÓÕ¬«?{Doؼç/{?RMWóqßßèlWî;?Ö?*¿ÅhÒÂø]5vžBŒUu5êÆ5¿Ñ[þqBsLJŠCÀ¨«{ï½W%%%zþùçÕÝÝ­ÐÐPI_.Ý<8<ìîîÖk¯½¦ØØXÍš5K’ôÃþPññƒ·Ü§–ÙlÖªU«”’’¢I“&)((H999r8Ú²e‹ÿƒÁ ÈÈHy½^µ¶¶ÊëõÊd2Éf³ÉårÉívËb±(((HqqqÚ¶m›Î=÷ÜÓºÊð`‡žÁ³£½F+jKõfU‘–×µ­£E÷nzE’ô‡YßÕ¿Oèùƒ„ÓëÒ9+ÿGŸ7”éžM¯èïgþ¿Ïá6üUMÝ:7ašÞ=çe2ô,½tÛ2ÝVòº{ãßôí ‹6à1›º;ôAÝ­¨]¯w4àûús׆¿¨ÑÙ®Œ°­ZtŸÆ†ÄJ’:ÜýlÃKz¬l™îÞø7]Ÿ¶ÐßN *£^nn®üq-^¼Xmmmþ hòäÉúè£äõzµ|ùr½ñÆ:óÌ3®Å‹ëÎ;ï$4&·T9""B‹/VHHˆV®\©òòrI’ÕjU^^ž&Nœ¨ÖÖVuuuIêÙ 3**JV«UN§SêêêRWW—º»»ÕÝÝ­ØØX566žÒ÷;>Ÿ=O’û7¿ª¬7¿«ï=3 ÐP’~»ýmu{ݺ,e–?4”$KY¯žù Az}ßÚÓY? ñ¶µUiyu±‚ƒLzyþíþÐP’~<ù2—8SvSOï|wÀﵩµBqÿ¸A_ýôa=³ó=Ù=ÎßÛŸV­•$=qÆM}‚Á0“U?͹Ræ £º½n}Ѱý„žŽÁ!\qÅzòÉ'•‘‘!£Ñ¨ÊÊJÕ××ë•W^QzzºRRR” ûï¿_ùùùC=]ƒC«Gåp8´hÑ"ÿa7•••’¤ÈÈHÍš5K111jjjRww·¤žJÅÈÈH™L&9uttÈn·«¡¡AiiiÇ´Wæé€=OŽô°]ž:Ëÿ‘h<ê=Ï”¿'Iºr윀¶d[´æÇeËãóêO»VhÏ–¯O>-ŒÏQ¬%" ý«ãz–Ó?³ó½'I¡F‹.M)ð¿WnTÆ€ï=T›Ëî_æœ×Ï8q–Í‹,IÚkXX Ïðú­€“Ìl6ëÖ[oÕÕW_­{ï½×¿D5$$D?ûÙÏüK™1¼épIª¯¯Wss³´hÑ"mÛ¶M+W®TNNŽ5vìX¥¦¦jûöíjjjRdd¤‚‚‚ü‡£444(,,Ì?Þ¡‡îœÎ¨4‰‡“– 7üÔÿïÿÛµRßZó䀿s(SQËÏþ™‚ %Ù¢úí³½½Z’47fòq=?‚Cú‘ 'Ÿ<¾ÿ#ŒáÇl6+**Jííí*,,Tjjª²²²´yófmÛ¶MÓ§OWtt´&Mš$—˥͛7Ëét*2²§‚,(¨gGoåžÙl²w9^ˆC¯·òÎd0*á0Õ‰)¶žPºÆ1°ÃHzÇL±ÅôÛž|`<Ÿ|ªw´úÿ}ª„-ºà0!iSw‡î,ý³jºš56$V³c'žÒ¹‚C0 4³X,²X,Ú¿¿ªªª”žž®ììlmذA›7oÖŒ3¡™3gª££C[¶l‘Ñøe…Öp ß¼^ïPO’jºš$IQÁ‡¯l޶ô`R;ÀSŒ{ƒÃÃ|b2añ/>ÕÁaÎYù?*iÞ¥V—]RO•å‹ó~4 jH0¸Àˆw¸¥Ê½´ÿ~………Éh4Êf³Éf³©¢¢B>ŸOYYY2›ÍZ¿~½|>Ÿf̘¡°°0Íš5KµµµÚ±cGŸñ†ãžÃ5ôIö;Û$I‘Gǘ{Úê-³ÞÙ2€1{‚ÃŽy²mlÝë %Éb4Ëë#Ü`(€ïp¡XQQ‘\.—¦OŸ®ñãÇkûöíjmmUDD„ ƒÂÂzª´ÊÊÊd45cÆ y<ËjµjúôéJLL”Óé”Ãáð;Ü‚CNU>=„›m’$»»û°}:Ý=?g!&ˀƌ0‡Èái•Ý}ø“uÌ“mÏeϨÛëÖŽöjý~ç»znךööêí³ÿGùÑ™C==F‚C0*ô†y!!!²Z­r8r¹\***Ò–-[tÆghÒ¤Ir»Ý*++“ÓéTxx¸$)"¢ç4Ú 6Èf³iÖ¬Y²Ûíúâ‹/áoï}Æp[ú;܂Αªw_ÃÆî¶Ãöiîî”$%Yû?HäPñ–1ªw´ª©»£ßvŸ|jqõŒy:,S–¤0“U’4;&K³c²$IÏíú@Ïïþà€S,h¨'p²¼T9$$DÊÈÈðïOh·ÛõÉ'ŸèÕW_UUU•¦M›¦ììlÙívÙí_.™ŒŒŒTpp°Š‹‹UUU¥ùóç+%%EuuuCò^ƒ‰ŠÃ¡o#Irx\²{ú¯lìn—$%‡ ,äë #œý‡‘ÍÝòŽF&·Ï#‡Ç%·ÏsØ>W;S’´²véš8€àŒx‡†bAAA;v¬fÏž­¤¤$ÿõ––­X±Bo¼ñ†ÚÛÛ•››«qãÆ©££Ã¿Ù`0(**JƒA………jnnVbbbŸñ‡[Åáp›ïHgPèj»ÏÊúíóyÃ6IRzh€ÆLëé÷EãöÃŒ×óœK¸©ô©ôôÎ÷d{åkúÊ'¶O¸©g^U§Á!ñw8ŠÙlVVV–òóóõeµU}}½–-[¦wß}WAAA:ãŒ3«¶¶6¹\.I’ÑhTTT”º»»UQQqÊÞåd¡âpè™ F]=n¾$éÝš’€vÏ«wkJ%I׌_0 1¯=Ðï½÷ê­ê¢ýÎ:æù†³â¦H’Jšv¶ê°¤y—$iZä¸S6/ЃàŒz¡¡¡š>}º¦N*›í˪«½{÷êÕW_ÕG}¤ÈÈHÈf³©µµUOOÈa6›e2õl=\Ã7*O7M8O’ô‡òÚÞ^ݧí›_Usw‡fD¦iVÌÄ>mÏïþPw®A•-ësýì„©Ê ORuW“ÝÖ·mC˽°{Õç.éÓ¶±e¯î\ÿ‚î\ÿ‚ª©Òï® Ñë_Ð[ÕëüצFŽStp˜ªºõà–×î©s´è—[^“$]”7(óÇá(`Äh £èèhUUUiïÞ½r»Ýòù|*++Syy¹¦Nª™3g*==]eeejkkó "}yÈÈp=¸å’¤«ÇÍ”ƒSÞú†º½nuOrëâä3üó{⌛ôÍ/~­»6üE«¶iQÂt…›mÚÔ²WÏíþPm.»r£2tGö'<plÀˆw,¡˜Á`Pjjª´wï^UWWËçóÉív«´´T[·nUnn®rrräñx´mÛ69=Y ÇS• O?÷c)H/W|ªÿÉÝj4ëµ3ïÐ…ÇXywÅØ9úÛüÛtÍgê±²e}ª¿=a±ž)øî Íýx\—v–‚ƒLúÆçëíêuzû ŠDIº>m¡Îý7™ƒŒC4CF/ƒ$_WW—¬VëPÏà¤hllÔÒ¥Ký§( »Ý®òòr55õ]®¦‚‚effª¼¼\G]]]ºæšk´iÓ&-X°@'àÃív÷{ýp}½^ï1ßwp¯×{Ä{Ýn·n¸áù|>Ýwß}ƒõ%Ç ØÞ^­ÏöoU¥½Q1™š3I‘Á¡Ç=^Sw‡VïߦuÍåJ×ü¸lMK<ú§ˆÃãÒú–Ý*lÜ©ýÎVMŠHQnT†²#R‡zjŒ:‡C6›ŠC0òHU]HHˆ¦M›¦¦¦&•——Ën·K’:::ôá‡jýúõ?~¼"""†mõžÏç¶sɲ“•žNU ¯ïûBQ¯]¯ê6µïŠÚõºä£ûûñ÷kµpå]úÝŽwŽûÙõŽVÝ´ö)M~ëû²¼üUå¼}«¾Sø{5ww÷˜½:Ü%¼þoº­äÿNx¬ƒ=[¾B‘¯^§[×=;¨ãGƒUMg0”œœ¬Y³f)55Õ?î¡ÁÛp â†Û|pjPq6ž-_1 ~¿.{S·•üŸ<>¯‚ƒL²ƒõqýf}\¿Y_4n׳³¾wL›ìohÙ£K?º_öý’¤8K„¶´VjKk¥VÔ®×[ ïÒ¤ˆ”ãz'IúëžÕåé>îûûSÖV¥ÿ\÷ÇA_òù|JKKSrr²víÚ5ÔÓ9a,U@¨8œÖ<>¯Ö4n×÷‹žÑ;5%Gí_ÖV¥ÿIŸWÌø†š®|AWþY¯/¸S– ³þ¼ûCýuïÇÇ4‡›×þNöýZŸ£=—=£ú+ž×ŽKžR^T†Ê;jõ½¢gŽëÝvwÔé÷;ßÕ¹Ò°ÛëÖ5«•ÝãÔq‡³ÁÅ:;;µ}ûvµ¶¶*''G&LèÓ>Ü*øÐ‚CÀiëç›^Vì?nМ÷îÐow,Ð=—ýK>ùt}ÚBÝ1å …šzöC\š:[å}Ëßg V7lÓšÆíеDèÕ3¢ñ¡q’¤Ìð$-[ø_Š0‡heÝmlÙ;à1?¬Û¨Ì}Gÿú}§ð÷êt;|ï@ü×úUÒ¼KcÌ!ƒ:îp6Ø¡XPPn¿ýv=øàƒÚ¿¿ÿ´æáGBp8m•µUÉçóiŒ9DcÌ!2èÈáO«Ë®çw(Iúö„ÅíßH?[– ³J›wëãú͚ïËÞ”$]–R XKDŸ¶[Œ.LÊ“$=±ý­'IÕ]Íjp¶ùß+8hðvy¯¶Tn[¦Y1õÍôsmÜán0G9˜ÅbQll¬Î;ïïõ™çøÞ#ÙïlÓ7?ÿµBMýeîdÄ@}FËb±¨¢¢BGߪÑá‡"8Œ5]Í’¤ôÐx™ ý~’ž$Iªu4lÌý&¸ïPÃ’{Æëj9¦¹ž 7~ñ„j-zâŒ÷¿'z †A Çš››•••¥öövI’×ëíÓ>Ü‚8*ЂCÀˆÑòE[ÂÛ':8¬§o×уÃN·Cí®®c†õ?ÞëuŽù4taÑo¶¿¥·ª×骱ótcÆ¢!›Çéj°—*KRii©^xáÝ{ï½c·àPü} 0üFŒÚa`o8ØŸÞ ¯Öqô ÁƒÃÅèàþÃÈÞg¹}58Û<×Á´±e¯~Rú¼“³‰øœIDATRCbô̬ï ÉNwƒŠõƒV«µßp8‡½Õ˜‡8Á!`Ä0õ,Ovû<‡íãòö´ $Ø9x@ÏÛoŸÞñ:æ`sx\ºfõ£êöºõÂÜ*ê¡)×ɨbJÃ)ìÀ©Ap1¬‘’¤&gÇaû4w÷´%Ù¢Ž:^¼uŒÿó¦îþ« {¯›ƒŒŠ³FôÛçdú¥Ïisk…þ_öWtvüÔSþüáâàÏn·kóæÍª««;á°Ìétö©Öëo¸…pÃm¾858n0bÄ[z‚¾¦îǽmɶ裎g3+ÜlS»«KMÎ ‰ èÓÜÝ)©'´4èÔWŸ}X·I’ô¯ªB½S]ܧ­º«I’ôÊÏUظC’ôÚ‚;4!,ñÔNò4pðrܶ¶6544¨¡¡A{öìQzzºâããkÌÐÐPíß¿¿ÏµáÆçó _‡€#9¤' ,ï¨Q—§[6cp@ŸM-’¤”˜™dR»«K[÷jfTz@ûÆ–½=ãÙ6Þɲ¥µò°mMÝþÀÔáé>US:­\q8wî\Í›7O………Ú´i“¶nݪ½{÷*##C11û>ú|>íß¿_qqaroûp‡èÁ!`ÄÈ‹ÊPjHŒöÙõQýf]”Û§½ÑÙ®/ËdA%å hÌËSgéá­oèÝš}#íì€ö·kÖI’.M)8áùÝ'×aötüùÆ¿é÷;ßÕuigé‘Ü%I±G8qz´˜3gŽfΜ©¼¼<ª°°P[·nÕ¦M›®ŒŒ EFFq ³Ù¬•+Wêë_ÿº¼^ï°?Uy¸Í§Á!`Ä0‚tcÆ"Ý»é=¹ý-Ÿ4³ÏòáßîX.¯Ï§óg*=,¡Ï½ÕoV—§[ɶ(MLó_ÿ÷ KôðÖ7ôfU‘vwÔõ¹oKk¥Þ¯]/“Á¨3Îí3ÞŽö•wÔJR@€y<:Ý}²«$izäxÿRë˜#¡&«$Éf´(Ñzä l¤;8Øûâ‹/4gÎÝ|óÍÊÍÍUnn®?@ܱc‡Ö¯_¯¨¨(¥§§+<¼ÿ¯¯ÅbÑš5kd6›ÕÜÜ,«µçkÝÀQ½€‘€ÃQ#ÊM–(*8LoU¯Ó÷‹þ ]uªéjÖceËt÷Æ¿)È`ÐmÙ—ÜwýçéÂU÷è¡­¯÷¹žž¬¥©³Õê²ëòO~©OöoQ§Û¡µëuéÇ¿ÃãÒuigì™ø»VêÂU÷èÂU÷ȧ¯æÚÛ¹ß?Þʺ '<ÞhsðRåââb=óÌ3úë_ÿª1cÆèæ›oÖ-·Ü¢›o¾Y_ûÚ×”‘‘¡ææfkóæÍêìì /44TÓ§O׆ ´fÍÿؽÿëõö ÷銥Ê臀elH¬Vžûs-ùðn=µc¹žÚ±Üßf2õÂÜê¼Ä™Ç4æKónÓÒO~©wkJtÖûÿÝ§íª±óô‡Yß”¹ãäé=E’"""´lÙ2­Y³FóçÏW~~¾òóóuË-·(//¯Ï把 544(!!AiiiþÊBI2™LÊÌÌTRR’ŒF£$NUÀÈBp6^ž»ÞnÍ8h)qr£2´ö¼‡õϪ5úlÿ6u¸š;Y%ç)?:³ß{þ>ÿ'rx»•ÐÏ’^«Ñ¬žõSý½bµ>Û¿U[Úöizäx—­«ÆÎ“ÑXÀÓ„%:/©' <ÚiË?ȺX_;爬¤…ÅëÃE÷J’²#R8^¯ïL¼@—¤äèéÑÄh4j„ r¹\zå•WTXX¨¹sçúÄÞåË/a®®®V}}½’’’4~üxyðNhhhÀ3â0$ùºººúü`$ñxŸ\.—êëë#«ÕªÎÎNíÙ³G999š5k– ”ŸŸ¯ððp­]»VEEE*,,ÔÚµkU__¯   ¥¤¤hìØ±2›Í}žc·Ûuíµ×jõêÕºøâ‹åñx>Ünw¿×××ëõó}÷÷z½G½÷ÒK/UBB‚îºë®!úàtâp8d³Ù¨8#ßÁû÷ÕÖÖj×®]Ú¹s§ rNNŽZZZô§?ýI%%%*))Q~~¾ ”——PXYY©êêj;V©©©}–*÷~ 'Ãm¾85Àˆ×{8ŠÏçÓôéÓ•••¥ÂÂBÕÕÕ©¾¾^ÉÉÉ7nœ¦Nªêêj=ýôÓþ±·±¿%Ì{öìQuuµ233çÖp;èÁ!z«êæÏŸ¯ &ô «ªªTSS£ÔÔT;Vqqq*//WQQQŸ ÄyóæùPÉÍÍUQQ‘>ûì3mÙ²Eùùù}aN:ЂC0â¼T¹²²R7ÜpCŸ%ÈEEEZ»v­***TUU¥qãÆ)%%EIIIÚ´i“Ö­[§Ù³g«´´Tùùù:çœs”››«¼¼}ºòòò´oß>ÝxãÊÌÌêià4FpF…ÞŠÀ³Î:Kñññ***ò€›7oVXX˜2224qâD9N½ùæ›***êsŠòÍ7ßPXVV¦¢¢"ø`98%$$袋.ÒÖ­[5mÚ4ÝvÛmC=- ‡`Tñz½þ ÂCÀ 6h̘1ÊÈÈPvv¶:::ôúë¯ûA)((ðW öˆŸ}ö™^ýuµ··+$$D’N‹eË.—K&“IK—.UKK‹L&“~ó›ßÈdâ×? ¿9€Q¡7Ì+,,ÔŸÿügåçç÷[AX^^®’’EGG+==]999jnnÖ+¯¼ÒgùrAA?€Ü¶m›Ün·¤žeÊCYuèõzÕÙÙ©ÜÜ\¥¦¦Êétê§?ý©âãã‡lNžŒ’î¾ë®»øë3Ñ^xáy½^UWW«¤¤Dû÷ïWKK‹233µhÑ"%&&*99Y‘‘‘²Ûíª©©QMMìv»âââ”’’¢¦¦&}þù窬¬Tmm­ÚÚÚ4yòd™Íf­_¿^‹ES¦LѾ}û4yòdˆxð‡×ëí÷úÑúä¾––ÅÄÄè²Ë.SKK‹®¼òJ]ýõ ê/?†·Û­_üâT€Ñ%>>^.—K¯½öš 5wî\aïòåƒ+÷íÛ§ýû÷+11QiiiŠ×¾}ûôüóÏ«¤¤D%%%ŠŠŠÒwê=”åŠ+®PEE…të­·éœ0ü€Q!!!Aûöí“$™ÍfeeeÉáp襗^RQQQŸ= sssûìXTT¤ššÕÕÕ)99YãÇWrr²víÚ¥ 6hÆŒ2§üÜn·ššš4{öl™Íf =ðÀT`P€QáòË/דO>Ùçà«ÕªÉ“'«££CÏ=÷œÿ”üüü€±÷檪*ÕÔÔ(55UãÆ“ÏçÓöíÛvJOU®©©Ñ¸qã´`ÁÕÖÖêÛßþ¶&L˜pJž €Ñ=À¨““£Ù³gkýúõjllìS!¬øøx566jÕªUª­­U]]<òòòTPP ¤¤$%%%Éf³©±±Quuuª©©‘ÑhTZZšÂÃÃåv»•}R÷8¬¯¯—ÓéÔe—]&»Ý® è;ßùŽ¢££‡ð« €‘„=À¨3eʽøâ‹zã7ô§?ýIMMM}þx­èèhíÝ»WëÖ­ÓìÙ³ýK˜gÏží¯>ÌËËÓÚµkµvíZíÚµKõõõš1c†¤žSO†ÎÎNÕ××káÂ…jkk“ÅbÑc=ÆpÒð›&u–.]ªK/½T>ú¨Þyç¹Ýî>K˜•˜˜¨­[·ª°°P¥¥¥þ%ÌguVŸqÕªU***R[[›l6›$ êreÇ£íÛ·kòäÉš:uªÜn·î¸ãÅÇÇÚ3€þ$ùºººdµZ‡z.§\SS“î¾ûn•––*((( ÝëõjÏž=r»Ýš3gŽÿ‚544¨°°P·ß~»"""4fÌ-]ºTkÖ¬ÑW¾òy<ž€·ÛÝïõþ>vìØ!«Õª… j÷îݺîºë”ŸŸ?_%Œ&‡C6›ŠC0ºEGGë‰'žÐúõëõÐCiÏž=2›Íþö   eddÈåré‹/¾PQQ‘fÏž­ÒÒRåççëÒK/ÕêÕ«õþûïKê©6<¸zñxìß¿_õõõZ¼x±*++•˜˜¨[o½õ„ÆŽÁ!€¤3fè/ù‹^}õU=ÿüójnnî³ ÙlVVV–ºººôñÇûO`.--Uzzº¿ß‰,Sv:Ú¸q£rss5vìXIÒý÷߯ÐÐÐã1à8䪫®ÒÒ¥KõÈ#hÅŠûÚl6egg«½½]+V¬PII‰fΜ)ƒÁpB•†¥¥¥ŠŽŽÖù矯††}ë[ßÒ„ 㕀㸑À(g2™tçwêå—_Ö´iÓú=)9<<\S§NUpp°V¬Xá¿~¬‡ååå*..Öy秨¨(MŸ>]<ð¡!†‡‡«'Ÿ|RÅÅÅzøá‡UQQÑgÿC©gÄèèh¹Ýn¹Ýî‡---*--Õ¼yó+›Í¦_ýêW}–GC‰ŠC€£ÈËËÓK/½¤ïÿû “ÛíèÓøõWx0¯×«>úH­­­š?¾$éŽ;îÐM7ÝDh€Ó ¿ Ð5×\£«®ºJ=ôV®\)ÇÓニ‡«:,,,”ÓéÔyç§ŠŠ ]xá…ÊÏÏ?ÙÓŽ ‡ÇÀl6ë¿ÿû¿õÒK/)''' Â°¿Ð°¢¢BË—/×ôéÓ•œœ¬ÄÄD=òÈ#„†8­$ùºººdµZ‡z.ÃΚ5kô裪ªªJAAAÊÎÎVss³.¾øbµ··ëwÞQNNŽŒF£bccuË-·(44t¨§ –ÃáÍf#8 /¾ø¢^zé%y½^hÛ¶m3fŒ&M𤦦&}ûÛßæ¤d ‡ƒÌétê¾ûîÓ† §ääd-X°@K–,ê©Fp @opÈá(@p Á!€‡@p Á!€‡@p Á!€‡`Äët;ÔévÓ=nŸgPçàñyunZû”žÛõ$)¢—CoU¯Óòšb=<óßôãÉ—÷{µºìzµòóã¾_’V7lÓåÿR Î6IR²-Zn‡Š›w©¸y—žÛõ>Y|¿ÂͶz†'–*€©º«IÏïþPßZó›õÿAÑ´£½FùÑ™ÚyéïTÅóÚ}ÙÓZ7E•öÝ´ö©czþK{?Ñs»>%ȬžõS5^ùg5^ùgÝ?ãzy}>Ý^òœ¶¶í;æ÷êt;´¼¦X_ùäàwýºìÍcz·ó?ü¹¢_û†.Zu¯>¬ÛxL÷êw;ßQ—§[Ù©zsá]Ê O–$dÐ¥)úóÜÿ”$ýy÷‡jêî8¡g`x"8#J£³]UöF1‡hŒ9DV£ù¨÷\Ô¸S’´8q†lÆà€öóg*Æ.I*n*?¡g`xbC0¢œ“0M-WýÅÿ¾¡Ÿ”>Ä{J›wK’.N>£ßöK’óõÌÎ÷Tr ßÑôŽwfÜE˜CÚçÆNRtp˜šº;´­­Jsb³4nõÒ?ù?ßÑ^£¬7¿; ûúÓê²kŒ9Dsc'õÛîöyü'A‡š¬Çý _‡`Ô«q4K’&X®{¨Ìð$IRmWóÀÆëê/©ßv£!Héa jjêP­c`c¶Ï–üòˆíÕoVKw§­‘60²°TŒj>ùTçh‘$E‡õÛ§÷z‡Û¡·ã¨cö‘‡ïà¶ÚÏ>lo¯Ö̓¹,u– 2 ñŒ0À¨Öèl—Ëë‘$EØÓïPÑÁ_^HÕaoÅáÁ÷nÌV1ž*oì[£¹ïÝ¡]uZœ8Cθa¨§€!ÂRe0ª™ Fÿ矧ß>.ŸÛÿ¹ocšƒŒÆó¶Oxò7ïÒŠÿ¤ë7K’þ#ó|ý&ÿ¦>_Œ.‡`T‹ UpIÝ^·íJ±Åôiîîðžl‹:ê˜ñ–1’¤¦îöÃöiröŒ™d‹>Ö)ªn¯[?ßô²Üòy|^Óý3®×µãÏÒy`è€Q/Þ:Fûìj:( ØãŒzɪþ6µTôÛ¾©µçzÊ«“T%nlÙÛo»ÓëÒŽöšž1C†¦âÐáqé’~¡’æ]Ê OÖšóÒm“/'4€Á!õ.K™%Iz·¶¤ßö·ª‹$I—$ h¼KS dAEM;Õè \®¼ªn“ì§Rl1ÊÊ8ÎYŸ˜çv Õ Û4.$NEç?¢é‘iC2œ¾À¨wcƹ2‚´²vƒ¶´VöiÛÝQ§Uõ‡7e. h{§¦DïÔ”È}ÐÁ*i¡ñZ’8C^ŸO¿Ý±¼Ï=>ùô›íoI’¾5a‘Œ†/sz]þñ*ìûåÝ ›vêš}Ѱ½Ïõßn[’ô£É—*Ül”g`daC0ê%Û¢u}ÚB=¿ûC]öñýzfÖw5;f¢Ö6îÐÖ=«6—]KSg++<¹Ï}¯T|¦;׿ Ij¾òEE‡úÛn˾\+ë6èç›þ¦¨àP]3~íz¬ì_z«z"ƒCuÓ„¾Ad£³]®ºG’ôÄÿ®d]|ÂïvGéŸõaÝFÍŠ™¨5ç=$Iêòtû—_?¼õ =^ö¯#ŽñòüÛ5;&ë„ç€á…à@Òf}On‡^«ü\‹>øYŸ¶ ’rõÒ¼ÛŽi¼ógê…¹?Ô7>\·®{V·®{Ößk‰Ð{çü¯Æ†ÄÊÜÕÞÎ/««»šŽÚßáqÌéà4eäëêê’Õzô†›J{ƒÊ;jk‰ÐÔ1ãŽØ×íóèÕŠÏõYÃVmhÙ«)©:3nо:nž‚ƒÿÞÚ;¶$—-“ÁÐgmã½SS¢Õ Ûf²j~Üd-M™­ô°„€¾Ý^·V7l“$M ORŠ-æ°síòtkMcÏòã³ã§¶ßú–=jîîP„9DyöSluÙUÒ¼ë_‰¾r£24Æ2àþÞ‡l6Á!€/õ‡Ž Á!€‡@p Á!€‡@p Á!€‡@p Á!€‡@p Á!€‡@p Á!€‡@p Á!€‡@p Á!€‡@p Á!€‡@p Á!€‡@p Á!€‡@p Á!€‡@p Á!€‡@p Á!€‡@p Á!€‡@p Á!€‡@p Á!€‡@p Á!€‡@p €I’œNçPÏÀi 7+4Hò íTœnþ?ó“¼ðèEIEND®B`‚libreswan-3.32/docs/klips-mast/000077500000000000000000000000001365625662500164635ustar00rootroot00000000000000libreswan-3.32/docs/klips-mast/Makefile000066400000000000000000000000461365625662500201230ustar00rootroot00000000000000mast.4: mast.xml xmlto man mast.xml libreswan-3.32/docs/klips-mast/mast.4000066400000000000000000000217321365625662500175210ustar00rootroot00000000000000.\"Generated by db2man.xsl. Don't modify this, modify the source. .de Sh \" Subsection .br .if t .Sp .ne 5 .PP \fB\\$1\fR .PP .. .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Ip \" List item .br .ie \\n(.$>=3 .ne \\$3 .el .ne 3 .IP "\\$1" \\$2 .. .TH "MAST" 4 "" "" "" .SH NAME mast \- pseudo-driver for attaching tunnelling protocols .SH "SYNOPSIS" .ad l .hy 0 #include .sp .HP 27 struct\ device\ *\fBmast_init\fR\ (int\ \fIfamily\fR, struct\ mast_callbacks\ *\fIcallbacks\fR, unsigned\ int\ \fIflags\fR, char\ *\fIunit\fR, unsigned\ int\ \fImax_flowref\fR, void\ *\fIcontext\fR); .HP 18 int\ \fBpacket_encap\fR\ (struct\ device\ *\fImast\fR, void\ *\fIcontext\fR, struct\ skb\ *\fIskb\fR, int\ \fIflowref\fR); .HP 18 int\ \fBlink_inquire\fR\ (struct\ device\ *\fImast\fR, void\ *\fIcontext\fR); .HP 19 int\ \fBmast_linkstat\fR\ (struct\ device\ *\fImast\fR, int\ \fIflowref\fR, int\ \fIstatus\fR); .HP 23 int\ \fBmast_setreference\fR\ (struct\ device\ *\fImast\fR, int\ \fIdefault_flowref\fR); .HP 23 int\ \fBmast_setneighbour\fR\ (struct\ device\ *\fImast\fR, struct\ sockaddr\ *\fIsource\fR, struct\ sockaddr\ *\fIdestination\fR, int\ \fIflowref\fR); .ad .hy .SH "DESCRIPTION" .PP The mast network interface is a pseudo device that allows tunnelling protocols to be attached to the base of the device, and routing protocols and daemons to the top. The metaphor is that of a blimp attached to a mooring post or mast. .PP mast stands for Mooring And Status Tunnel. .PP The network interfaces are named anything that can fit in 16 printable characters. We suggest \fBmast0\fR, \fBmast1\fR and so on, as many as desired, but they could also be named \fBmast\-rome\fR or even \fBvpn\-rome\fR or other more descriptive names. The names should be unique in the namespace of the network devices. .PP They are created with the "ip tncfg" command. .PP The mast device provides a way to anchor routing daemon to virtual topologies. It provides a consistent abstraction to various kinds of tunnelling technology: IP\-encap (protocol 4), IPv6 (protocol 41), GRE (protocol 47), ESP (protocol 50), AH (protocol 51), IPIP (protocol 94) and ENCAP (protocol 98). .PP There are three ways that a mast can be used. They correspond to how additional information (i.e. policy) is attached to the packets that are directed toward the device. mast devices are bi\-directional devices, but the flow of the packets that emerge do so in a uniform manner. .PP The first way is called the PPP method. A mast is considered to be portal to which packets that need a predefined kind of encapsulation may be sent. The mast acts as a point to point device \- a virtual leased line \- sending all packets into the an underlying tunnel mechanism, having attached a default security policy to each packet. (As is described under "SECURITY POLICY", the nfmark is used). A mast device used in this way should be indistinguishable from a SLIP interface \- it has no layer two protocol. The layer two link status of the mast device may reflect the state of the dead peer detection status for the remote end point, if this feature has been enabled. .PP The second way that a mast device may be used is as an entry into a non\-broadcast, multiple access encapsulation media. The is the NFMARK method. The choice of a particular tunnel is indicated by setting bits in the control structure (the skb). This is described under "SECURITY POLICY". .PP The third way that a mast device may be used is with a virtual link layer. This is the NMBA method. This is the This is a variation of the previous method \- the device is still a non\-broadcast, multiple access device, except that the mast device supports a layer two similar to ARP. The layer two information that the network stack attaches to each packet will be used to determine which tunnel will be used. The mast device will keep the neighbour cache updated with liveness info. If the tunnel to a given neighbour is known to be down (such as, because of a lack of a key, or expiration of such), then the neighbour cache entry will be removed. .PP Packets that are sent upwards (in the direction of decapsulation) from the mast device will be marked by the tunnel on which the packet was received. The choice of which mast device to emerge from is also defined by the tunnel decapsulation mechanism. Typically, a unique device will be created per major policy category. This is done to simplify the firewall rules. .PP The PPP method is most appropriate for use on the client side of a road warrior configuration, or when there is a sufficiently small number of VPN tunnels that it is practical (or desirable) for each tunnel to have its own device associated with it. The simplification of firewall rules for output is the primary benefit of this mode. .PP The NFMARK mechanism is used by more traditional VPN topologies, and by Opportunistic Encryption. These two categories of use mandate a different output device per major policy. Both would use specific setting of policy bits (skb\->nfmark) for selection of outgoing policy. .PP The NMBA mechanism, where an ARP\-like layer two is maintained, is most appropriate for layered systems like the xbone, where there may be too many tunnels for it to be practical to create a device per tunnel. At the same time, the reachability information that the layer\-two tables provide can be used by routing systems to determine the optimal path. .PP The mast device permits kernel code to create them with: .nf struct device *mast; mast = mast_init(family, callbacks, flags, unit, max_flowref, context) .fi .PP A new mast device is create per address family. This is not strictly necessary, but may simplify policy checks as well. .TP \fIfamily\fR is AF_INET or AF_INET6. .TP \fIflags\fR is one of MAST_PPP:the device will operate only as a point to point device ignoring any bits set in the nfmark field. MAST_NFMARK: the device will examine the nfmark field, extracting bits from this field to form an SArefence, which is passed to the encapsulation routine. MAST_NBMA: the device will examine virtual layer two information pointed to by the skb\->mac.raw field. .TP \fIunit\fR is an integer X, the unit number, and results in the creation of the appropriate mastX device. If this unit number is in use, then an error will result, and NULL will be returned. .TP \fImax_flowref\fR is the theoretical highest flowref that can be assigned. It is recorded for sanity checking. It may also be used for scaling of virtual layer\-2 structures. .TP \fIcallbacks\fR The callback is a structure containing function pointers for \fBpacket_encap\fR and \fBlink_inquire\fR. .TP \fIcontext\fR The context contains mast sub\-type\-specific information. .TP \fImast\fR The mast is a struct device * previously created by \fBmast_init\fR. .TP \fIskb\fR The skb is a struct sk_buff * passed down for processing. .TP \fIflowref\fR The flowref is a reference to a policy to be used for packet processing. .TP \fIstatus\fR The status is a flag indicating the link state. .TP \fIdefault_flowref\fR The default_flowref is a reference to a default policy to be used for packet processing. .TP \fIsource\fR and \fIdestination\fR The source and destination are IPv4 or IPv6 addresses. .PP The \fBpacket_encap\fR callback is called by the mast device when a packet has been forwarded into the mast device in some fashion. The function will be called with the \fIcontext\fR that was provided in the \fBmast_init\fR call. .PP The packet to be processed will be passed in the \fIskb\fR parameter. The flow reference will have been extracted and passed in the \fIflowref\fR parameter. .PP The link_inquire() function is a request from the mast device to have its link status updated by the tunnel apparatus. Link status can be updated with the \fBmast_linkstat\fR function. .PP In the link_inquire call(), status is up==1/down==0. Some mast devices may maintain per\-flowref link status (in the pseudo\-ARP case), in which case the flowref should be provided. A flowref of \-1 updates the global link status. .PP A mast device may have its default flow reference set via the \fBmast_setflowref\fR function. .PP A mast device examines packets that it receives, looks at the appropriate parts of the nfmark and turns that into the reference #. If these bits are zero, then the default flow reference is used. If the default flow reference is not set, then the packet is dropped as a transmit error. .PP The \fBmast_setneighbour\fR function will be filled out at a later time. .SH "SECURITY POLICY" .PP When the mast device is configured to be in \fBMAST_NFMARK\fR mode, it will examine the skb\->nfmark field of each incoming packet. The upper 24 bits of the nfmark will be extracted. If bit 31 is set, then the nfmark will be considered to be have been initialized. Bits 8 through 30 are then shifted to the right, resulting in a 23 bit number. This is considered the flowref. .PP If the bit is not set, then the packet will have the default flow reference applied to it. .SH AUTHOR Michael Richardson . libreswan-3.32/docs/klips-mast/mast.xml000066400000000000000000000336211365625662500201560ustar00rootroot00000000000000
mast Michael Richardson
mcr@sandelman.ottawa.on.ca
2003 Michael Richardson
Reference mast 4 mast pseudo-driver for attaching tunnelling protocols #include <net/mast.h> struct device *mast_init int family struct mast_callbacks *callbacks unsigned int flags char *unit unsigned int max_flowref void *context int packet_encap struct device *mast void *context struct skb *skb int flowref int link_inquire struct device *mast void *context int mast_linkstat struct device *mast int flowref int status int mast_setreference struct device *mast int default_flowref int mast_setneighbour struct device *mast struct sockaddr *source struct sockaddr *destination int flowref Description The mast network interface is a pseudo device that allows tunnelling protocols to be attached to the base of the device, and routing protocols and daemons to the top. The metaphor is that of a blimp attached to a mooring post or mast. mast stands for Mooring And Status Tunnel. The network interfaces are named anything that can fit in 16 printable characters. We suggest mast0, mast1 and so on, as many as desired, but they could also be named mast-rome or even vpn-rome or other more descriptive names. The names should be unique in the namespace of the network devices. They are created with the "ip tunnel" command. (XXX? are they. Maybe, maybe not.) The mast device provides a way to anchor routing daemon to virtual topologies. It provides a consistent abstraction to various kinds of tunnelling technology: IP-encap (protocol 4), IPv6 (protocol 41), GRE (protocol 47), ESP (protocol 50), AH (protocol 51), IPIP (protocol 94) and ENCAP (protocol 98). There are three ways that a mast can be used. They correspond to how additional information (i.e. policy) is attached to the packets that are directed toward the device. mast devices are bi-directional devices, but the flow of the packets that emerge do so in a uniform manner. The first way is called the PPP method. A mast is considered to be portal to which packets that need a predefined kind of encapsulation may be sent. The mast acts as a point to point device - a virtual leased line - sending all packets into the an underlying tunnel mechanism, having attached a default security policy to each packet. (As is described under "SECURITY POLICY", the nfmark is used). A mast device used in this way should be indistinguishable from a SLIP interface - it has no layer two protocol. The layer two link status of the mast device may reflect the state of the dead peer detection status for the remote end point, if this feature has been enabled. The second way that a mast device may be used is as an entry into a non-broadcast, multiple access encapsulation media. The is the NFMARK method. The choice of a particular tunnel is indicated by setting bits in the control structure (the skb). This is described under "SECURITY POLICY". The third way that a mast device may be used is with a virtual link layer. This is the NMBA method. This is the This is a variation of the previous method - the device is still a non-broadcast, multiple access device, except that the mast device supports a layer two similar to ARP. The layer two information that the network stack attaches to each packet will be used to determine which tunnel will be used. The mast device will keep the neighbour cache updated with liveness info. If the tunnel to a given neighbour is known to be down (such as, because of a lack of a key, or expiration of such), then the neighbour cache entry will be removed. Packets that are sent upwards (in the direction of decapsulation) from the mast device will be marked by the tunnel on which the packet was received. The choice of which mast device to emerge from is also defined by the tunnel decapsulation mechanism. Typically, a unique device will be created per major policy category. This is done to simplify the firewall rules. The PPP method is most appropriate for use on the client side of a road warrior configuration, or when there is a sufficiently small number of VPN tunnels that it is practical (or desirable) for each tunnel to have its own device associated with it. The simplification of firewall rules for output is the primary benefit of this mode. The NFMARK mechanism is used by more traditional VPN topologies, and by Opportunistic Encryption. These two categories of use mandate a different output device per major policy. Both would use specific setting of policy bits (skb->nfmark) for selection of outgoing policy. The NMBA mechanism, where an ARP-like layer two is maintained, is most appropriate for layered systems like the xbone, where there may be too many tunnels for it to be practical to create a device per tunnel. At the same time, the reachability information that the layer-two tables provide can be used by routing systems to determine the optimal path. The mast device permits kernel code to create them with: struct device *mast; mast = mast_init(family, callbacks, flags, unit, max_flowref, context) A new mast device is create per address family. This is not strictly necessary, but may simplify policy checks as well. family is AF_INET or AF_INET6. flags is one of MAST_PPP:the device will operate only as a point to point device ignoring any bits set in the nfmark field. MAST_NFMARK: the device will examine the nfmark field, extracting bits from this field to form an SArefence, which is passed to the encapsulation routine. MAST_NBMA: the device will examine virtual layer two information pointed to by the skb->mac.raw field. unit is an integer X, the unit number, and results in the creation of the appropriate mastX device. If this unit number is in use, then an error will result, and NULL will be returned. max_flowref is the theoretical highest flowref that can be assigned. It is recorded for sanity checking. It may also be used for scaling of virtual layer-2 structures. callbacks The callback is a structure containing function pointers for packet_encap and link_inquire. context The context contains mast sub-type-specific information. int packet_encap (struct device *mast, void *context, struct skb *skb, int flowref); mast The mast is a struct device * previously created by mast_init. skb The skb is a struct sk_buff * passed down for processing. flowref The flowref is a reference to a policy to be used for packet processing. int mast_linkstat (struct device *mast, int flowref, int status); status The status is a flag indicating the link state. default_flowref The default_flowref is a reference to a default policy to be used for packet processing. int mast_setneighbour (struct device *mast, struct sockaddr *source, struct sockaddr *destination, int flowref); source and destination The source and destination are IPv4 or IPv6 addresses. The packet_encap callback is called by the mast device when a packet has been forwarded into the mast device in some fashion. The function will be called with the context that was provided in the mast_init call. The packet to be processed will be passed in the skb parameter. The flow reference will have been extracted and passed in the flowref parameter. The link_inquire() function is a request from the mast device to have its link status updated by the tunnel apparatus. Link status can be updated with the mast_linkstat function. In the link_inquire call(), status is up==1/down==0. Some mast devices may maintain per-flowref link status (in the pseudo-ARP case), in which case the flowref should be provided. A flowref of -1 updates the global link status. A mast device may have its default flow reference set via the mast_setflowref function. A mast device examines packets that it receives, looks at the appropriate parts of the nfmark and turns that into the reference #. If these bits are zero, then the default flow reference is used. If the default flow reference is not set, then the packet is dropped as a transmit error. The mast_setneighbour function will be filled out at a later time. SECURITY POLICY When the mast device is configured to be in MAST_NFMARK mode, it will examine the skb->nfmark field of each incoming packet. The upper 24 bits of the nfmark will be extracted. If bit 31 is set, then the nfmark will be considered to be have been initialized. Bits 8 through 30 are then shifted to the right, resulting in a 23 bit number. This is considered the flowref. If the bit is not set, then the packet will have the default flow reference applied to it.
libreswan-3.32/docs/klips-using-kernel-crypto/000077500000000000000000000000001365625662500214405ustar00rootroot00000000000000libreswan-3.32/docs/klips-using-kernel-crypto/klips-fsm.png000066400000000000000000001772511365625662500240700ustar00rootroot00000000000000‰PNG  IHDRú¼å!€sRGB®ÎébKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEØ  C)² IDATxÚìÝw¼UùøñO R( =€R‚¥©ØŠˆˆ4QÁÅ" ¨`GADº€)¢¢¨€"|)¡w„R¨Iîïç¬w²l™½[g÷ó~½öuïîìÎΞÙ=3óœsž’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$IÀ(‹@’4B“у$Uõ°Àb$I’ÔnúÕmCTÓ:À==ºmwÓÝE’TÕEÀ®=¾¯^ç®’¤šŽæõè¶ÍŽvIRM½[i™±îgõ€Íû,éy+À6žœé®’¤ç™YíÜ8xÂ]&Iϳ °p½èx 8ÄÝ%Iϳð‘Aù°úÕ ž·¤Bšœk1HÒóìU m½èå$IZÚ.À…ØÎgÜ]’T±˜@¿¹•%I’$I’$I*0ý’$I’$I’$˜~I’$I’$I’ Ì@¿$I’$I’$If _’$I’$I’¤3Ð/I’$I’$IRè—zÓPºmÑÃï×ém”$I’$I’T~©¿å Æ'ÝæôÙçRq÷—ûز‘$IR1Ï#ûù|u‹Ìçóûäu‰ÔSÆZ’€C,µÑwÒß9…å)iàl\›þÕÁ÷-`¶þÝcïÓ©më¦AøŒ’äu‰×%RO±G¿ŠvÁ0| ¸xø°YÙónžMœ€ÉiÙ§Ò:¾Ÿî<ÝÿzºÿÅtÿ›u¶á“À-ÀSÀÀò™ç¼>m×|`ðp*°JÙºöM>O ¿UyÏ)éyøZÎÏ™½À"óúze»EæBü“ÀmiýÇ•}Î’m€YUÊ¢Ü.ÀÓ:¦rzgû¯Þç*ÿ•z[äÙ‡j­CÒíþܶe,OIêÛàC'F+öÒ¨Èf{V¶²gf+Êe¨Ê­dUàLàÑtÎýH:ŸÞ¡Â:–eŸ‘³W®TËøù¼.‘$õ¶!`zƒ'û “ˆàòKÈ?–»ø1peºÿ»´üåéþ5éþ/Òý+Òýߥû»ÖÙ†Ùiý§ûßÈó?ˆÆ•V}®Fý³Øî"ü>ºánàèò4$•^óQò7$åiÄ)=çSi½‹3Ëò6pÕk¤«×XU¯Á«ÞòòòÌÓºpð$psæ·fpCjŸ Ó­×ÍLõy»˜â þq±WÖÛk)ÊÏ÷¾]vÞ÷û´üVà‡é<õNà#Ö‘íèð*7Håv)À9ùL`nƒ¿«ZçØ­è¸–­O*u\ËsnÚìy{#׆µÎ£—OeôTÚŽ<çÑ^—x]"ëqi`/t ô”îo—î?“yÎé± Ò…À3¯{0˜—NX&Aê›Óqùt‚´¸ìàWiöH÷÷L÷ï+;(ï|88;=g^…í̦Ì[á}nI)ÛŽzŸ³Ñ ¶òçÝ•îï•áÞP+6Påæ§“ƒˆQEcZø¹9™kd»‹ðû膑úÛÕ”§§ôœ§ˆ§³3ËòlW½FºCéâuFÙò<Ÿ3ÏRµç=Wö9—ÍöºÄëYK©ÕþO0Ü[èt¢'Õ•Àc™çd$ÿHý&óØ[rlCy¬ìä½¥ž[W'¦‹Šòíühæ@NÚÎ[«|Öï¤ÿoVjàs’yïKh,G©1äqà' àÏl°,ÊÍ!æEøpyzþ½ î¿ZŸëéñÿ#ÐÖ8™kd»‹ðûè†f{ô·º!©‘ž3•F¹äÙ®zty«ê5xÕ[^턺VÝxoº¿{•À›¤ÖëÇ@žàOž ø£ÒýÏ2Ü©a÷6™Ú|è•Q‘µŽqyʳÖëóޏl¶üɹ=Yˤm˜Éð(‡ª¬ãK™û_Äù#Ô?¢V÷èïDǵ<ç¦Íž·7Ò ¬Öyt»{ô{]b],ëq©o´:Б‚çút`’˜øçËe¿ùéußJ}&Ý_œ9pÖÚ†lNÕ³ˆQ%[3C¶ÿ^峎~•î_™y¯zŸ“ôÞsY~ÙϤ“‡çˆ øwË>gž²(÷«t`_”¶ùÊT^ì¿ZŸkKàºôÚë>?Ôävá÷Ñ # ô·«!)ÏkjPçÙ®zty«ê5xÕ[>’ꯥûsˆHsaJí×þ<ÁŸ<‘éþu)8õKç§oe©ÝÁ‡^ ÕG<æ)ÏZ¯Ï;â’&Ë¿Þ:Ê•ŸCnËp¾ëJëX5w?“þ7Я~ µ"G§;®å97mö¼½‘N`µê¦o±tJºFÒºy]âu‰¬Ç¥R´[Þœ÷E²\æsm8 ß¹¢ìÃ~ ô·«!)Ïkjíÿ<Ûµé ~cU½¯zËGrB½\:ÁŠ˜`²tâ¿ÈÃÔ6ýèÏüɹ:óøI#xŸF‚Lí >ôʨH¨>â1OyÖz}Þ—4Yþž³ ¥cÚψ¹J?ç×XÇËilTÔ¯þnw\ËsnÚìy{#ÀjÕMãS=•Ž3Ÿj þòºÄëYKÅ@w½ 8-sA>v@¾sú[#O ¿“ IýØ×*ãY:—sé‚í‹Fj›~ ôç þä ˆ”yüu#xŸzŽNziTdµy˳ÖHÐ<#.i²ü=®›>ÏÆàŠ”$IRmH’$I’$I’T\ú%I’$I’$I*0ý’$I’$I’$˜~I’$I’$I’ Ì@¿$I’$I’$If _’$I’$I’¤3Ð/I’$I’$IRè—$I’$I’$©À ôK’$I’$I’T`ú%I’$I’$I*0ý’$I’$I’$˜~I’$I’$I’ Ì@¿$I’$I’$If _’$I’$I’¤3Ð/I’$I’$IRè—$I’$I’$©À ôK’$I’$I’T`ú%I’$I’$I*0ý’$I’$I’$˜~I’$I’$I’ Ì@¿$I’$I’$If _’$I’$I’¤3Ð/I’$I’$IRè—$I’$I’$©ÀÆZRW­ ìl l¬LVÀ²X,nn..î÷k"I’$I’$Ug _ê¼å€=½uK€+€S€Ûˆ`÷‚,—ˆFŽ €×_nOesðŒ_©çÙ€9ÌLÉúÊúJ’ÚoEàuÀ¶À‹€€‰À”,‹§R}~70 ¸ø3p£_©ÿè—:û{û00¸ø ä_lÑüïsðÑðq"0x#pp8p$p°Èâ’zŠ ˜•Ù€)Y_Y_IR{ŒÞ ì¼ø+ðàBàf`>0wËeùTŸ¯̶Nq‡SÓõô£~}$Ií0L€Ïùbàßébr3wûˆlü ¸ØÔßGO¸8Ú¯æ@ | x8؉h Suc€ó‰ž²ÆŽýêÂtëu3S}n}%ë+éùv)À9ùL/ ýVàz¢ÝDp[µ½ ø1ä?†ñ YKj©Aø±íMôRŸ»»%>ÊsO]g °Ù€Ù¼AlÀ$ú­¯¬¯¤â3Ðß[¦7#¿Õ¸5“€ûˆÆ\Éz\RËôûí DžÓ ÜÕ-5ƒÈ7x¨¿®2Ð?¸lÀl­08 ˜ƒÄ@¿õ•õ•T|ú{Ç6Dpú`œ_ͦm ÜE¤imqÈz\R+ôóm&ðO`ws[LMå;ÓßG×èL6`¶Ç 4`ýÖWÖWRñèï o!R¯mïW²¥V~üOd=Þlµ“Úc7`wàMÀ#G[ÌIå»ð.‹CêØ…äÛˆU·Z-5+•ëÛéïLÉúÊúJ’ñFà»ÄÜ*—Z-õ1¡ñbbâu箑$5¥[Õ6$†À­ãîíˆu‰žˆ/ô÷Ñqöè,»ÿ!FÓ¨}¦=mÀ,>{ô[_Y_IÅgþîÚœèÉïü*í5ø ð ‹BÖã’šÑo?¶QÀ_‰VquÎ;ˆ âü}t–þÁafg­Kÿ6`ýÖWÖWRñèë7ø5ìˆñÀµÀ®…¬Ç‹ËÔ=Rk½x¸ Á×ÍUø_ùü*ܾǢZnp"ðQú{ÂÎ^rðqà‹B²¾²¾’4 ¾ œüÁ¢èˆ'Óõô·€I‡TLú¥ÖKLúöùlk?6&̾”öƒ¤Öi¦šc¦d}Õ/õÕ ¢'Ýbn¥vœ‹ÎžÎÜ?Xˆg¤¢Ú”˜í‹¢£nNN×Õ’$5¬Ÿ†ÏìœÞÄÅI'{ô÷먳诠˜©{ÔmcÓ ÿ rÖ+¥ ˆ4?„¼^=5£Ÿ6nÄÌ¢2uOïÖWÍ(¯ßfAì ü}¯U_Uª¯Ûè”ã„ÚÏÔ=Ýñ à ÖÇjqÀÀš…¬Ç‹ÇýRëìü¤ÎsLÓ ëçXïÊÀ¹ÀÀ#ÀqeQSˆ†ÇÓ‰ÎÉ9ÞïRbÂé¶eº8=!½ÇãÀIÀrÛ?IûARkìü_:ÙoÄ-©nRsn%&ý…Ô¶úªQÙúmðUàUD.é…-zFÔ½̶¾’Ô*›¿®Sßy¾ÙÏß>iQHÅc _j5‰IÈ.Ëqô’tBr ðë>X ¬žNx¶Í,? Xž˜ màÇ9Þoû´ÎÒíZàx`2°°60 8¼`ûáÏÀÆÀj~%¥–ÈÓ€©ö²Sêúª¼·zé|ãf‹ÄõÕ>À=À¼t;.³¬V™©ÀED‡•YÀv¿Ô7ö~,é‘íÄ‘•§#åÇùu”$5¢_†Ï¼8¥Á×¼‚è=ÕS÷LJ'8Ù2Ú•à—–/Öiâý zó?ÇÒÃó¶î,à¾8ÈÑëï£ýLÝÓßÖ$‚/Õ:”Yd8mBysp/¬¹8$³¬Z §´ŽjA JõXÑG%U2:•™ ˜ÅcêžÞ¨¯>K¤€ÈúðÝuG©žÙ—˜tö’Ìc›¥z«”{þÀ§_–½×w©Þ±£ZÝø@f½¥‘—ÕêÊJÏíV}X­¾ª–ºgˆ•:>S®béN&;#[—!‚Ne–œAtv™ ü S÷¨=LÝÓy÷ÏÊ•×w»W¸†>x(Õ—¯N÷ïK÷óœ7VªûõšáaÍ_"†*“.†~ |3ÄŒe¸·S­÷{<-[+ó>gÇ2Ü mu¢‡\ÑÜIôÌÔœM¨ *6Êö¶ª(œ ¼؃6}Yº˜Ê^ÐUy4ÄÒ#šî¦r ›~•TÉiHj¼¾‚轿{úÿ½ ÷æÏSw,&zŒçu Ã#œÞG¤IÝX®(£4©¯F•]tO'Rl@tX9>}îÉéœtTZöpú»vÙk%߯ÀM#|íât 1¡ì3©Î,Ý_¶u?ºØã†R¡øƒ•Zc"K÷@ªäAàkÀ•éä府ëÞ‡È8›Èƒ}pdfù~DO†{ÓÉȇr¼ßÃÄèÒÉÍéBêét@ŸüxQ÷ÅôOpOê¦Z ˜Y."R9L.ÎJ× ä@í PÖ†G7MI·ÉÀJ}²/lÀ”F^_œKŒp\ x;ÃþvÔç=G7%zôŸ1‚ºq¨ìyµêÊ¡«­¯¾JtfYøbfßÔê°RêsÃ9ú?çÏ@êûú|¨EïÑïç­òdªo'J’”[¿ ŸrWº?ð÷aêžþ6ŸÈZÍDOÕRår*§îY“ÈY½,˜úpænõô=ß<-?µlCé±RèJ"‡sù{@Ó~BñG%U2‘ái*S÷ôN}p11¡byNçZuGµ”3µR÷Öw‘¯¾šZuã´Tÿ­•£®,n·ëÃJõU­rÌN¸~"î“Î1¦rùK§æ™–öéB¢C˘ºGíaêžÎú3Ñ0[Iy}W«>žQV'”ßo´îT7à¨RYŠ=ú%IR%+“¡U³/|„H9qf•ç!RŽÍIëÛØ3-«7Òi11ºh蹞èýYI¿ŒJªd>õç7¬¯j;“è=fêŽS€Í¨ž¶§^ÝX>òrUŠ3J³R}µ„ȇ=7óg©3~š.¼'¥í~6óºÏ)Š^@¤©\®ìs¿)-ߘñ]~1 öiR¡Œ¥z½R}7Rý|Þè9¨$©kìÑ/÷Gqöè÷w$÷‡ª³Gÿàþ>Ö&RL²¾’ Ïýu9°µ_;÷‡4`õxËØ£_’$I’Zç`b^SnI’$©cÆZ’$I’Ô´ DJ²{‰Þc’$IRÇØ£_R£6¤=CCY¯$I’¤^³H×ó"à.‹C’$Id _R£n¦h½’$I’$IR_3Ð/õ.SkI*Švô‘¤nÖO3ÇDZIRoY ãZ’ô?VˆRç”ÒÍìÜCLÐöc`\Ùò}‰áÞ§ÇW&&t{x8Ž¥¦§§ ѹÀÉ™e€ÒëN–Ë,?ˆÈ#»¸8$DzlÚœÒÿ§çoYÇ´ô9³Òóž®S>äüÜÔ(KI©ÏJ‘#©W´~š|x°B:’$u×ç9Àl`õtý9Íb‘¤` _ê¬1ÀöDì…ÀÀ¡eË_l¼9=v2°8ÈlBÒ³¯9 XXX…x—LÖÖN'A‡§eÓ€ï» ›ʱ¬ÒgZ+mß)À1™e?%‚ôSÓv¿·²ª÷¹ë•¥¤þãH'I²Zú{³E!I=ã‹ÀkRý ðzà1Ï%Iê CÀô>ùǫ̃ðywn-[>5³|°¤ì5»f^3‰†¯Sáý&ÏkfÛ ¸3ý?xؘXöÚZËÊ{ô+¦û[½ë³Û¾Væµo"_þzŸ»^Yùû舻£­Æúº~®æ´|AºíNå‘>¥ïÉ«ƒÓýûÒýl]UmäQùH§KÜ* Ó­×ÍL¿Ó~ý}42±d3¢©žûCz¼ÞhǼõÞ ÔWŸáíSÀ3·ýw•Ý^ìHtøxi*ÿéé|ÔÀžZm—œ“ϤR(^^¥^žHŒJ×|³2·Uêœ763Ê}ÐUÛ’õxjõ‰¡ýo”EPÑbX÷‚¿‘{2÷ïf¸ÇDÐ~Næ~ibö5we^3-í“Jè«¥ßø eûoqú.ðàãÀ·ÿ¤ ¬+ë,+·80<ÅpúœÒ¶ß—yî½9˳Þç®U–ù~%¥¶Ú¸>Õ{¥ «¬1Ä(¢5ˆžWç£tJ÷É\4,KŒ<Î"F}6³®ÒH'A’š•‰xxªÊƒðÿ%ÈÙz®4ÚqkàïĈÉé#¬÷ÁŠMìŸ ÊÎ]ËS/MINûa0>Nd¸fðdºÍ%‚xMÓë-«Ô3.ûŸ.Ûö숂fzôWýP©,×"ƒB~söèW7/¨VÈñ{­T/dGúlžîOÊÜ"ý_oäQ¥‘Nƒh"ã¥Töèï½úªÖHÄzõ\½ÑŽyë=ë«ö[&í‹u€‰F›€·ó;;E¤œ¼ø1òâét.ùWà4à0"íäËpšAfþκØ®ÎõÑ*e÷W«qÞØÌ(wE§ÁM,Y‡C¥Ö¸Èÿ`Žç~•Ú=žèáufçÎK GC—'_ÎÈ\Øþø&°Ñcé¥ÀUéµgÇàç2œïþOédg3àÏÀ³D/§%i½µ–å5˜ˆ÷Èôy'0ÜC7Ïkk}îZe¹^æÄMÒÈÍO< FðÚìHŸgÓÔ¼ÌýeÓÿõF•Ö5gÀ÷Åd'H(µ»¾ª6±žz£óÖ{ÖWí÷\Ú7øºe‰#k¦`À SpàãÀúi?Þü;s»{»J­4|ÕjÕñÙóÆfF¹+BæZ Rq8¯Ô7=†òœxü…È%x1$ü«u^³‘CpvzÝUDð¼d?¢ÇÙ½é¤æC™eû½“nNÁ^”–!‚çsÒ…ñÞÀž9–5b_¢qáQà à\ž?ja¤Ÿ»ZY¾¨ìDNÒÈ”0+iÕ¯9 Jš’n“•,þ¥Ø€)¼¾j¥‹ˆÜðS ˆôêŸúê™ô]º 8Hí±ðrb„Àfé±»‰ǧ¤sÜnÞâñKê¹ú<Ϲ¦u{eã‰F—Ù…Töè—Zã2àÀ‰9žûÓt+7«ÊorðÎë›K +®äIà#éVîªO WkYv;Ë·yKOl4;•KÉ›kœ(”÷â­õ¹³ï[^–Û¤“5IÍ)5`^QaÙã ç¹¾¯‰÷¨7òHÁLiäõU«´b´£õU±=œnÉ<¶ðb"¿÷¾Ä$Ÿ³Ó÷ä¢ôÜgüZH¹Í"×Z¥™Qîƒn#"u®å!ˆ=ú¥Ö¸ØÖ”ú§ IDATßÔólÂðH‡µ‰\§¿ªqaxO ê´mÓþԜˀ×VYö0ð}"˜3Ø¢‰÷©5òHaàr‹AQ}Õ*­íh}Õ_ž&F~ x+°*°;1ÚôÓDZÏ_¦ïË*~=¤¦ëóßùìýzi#å>è^›ö‡¤æd¼îß‘¬³_&Ĩ7qP¥ÉvûÝÖÄðí…ÀcÀOˆ!€å><¼»É÷Û¸¤Ï~sNÆ«nYƒH ffwîgx¢9‡“ñZ_Y_ir:¿=$^¼‹Á™³¡8ow®1¦ûÕë‰ó˜],YïdLRkœ|°Æòj©yúÙD®Ö DÄÒ„ÁåŽ"z9ÓäûíO¾ôI’ê{€®û:‹¢«¶'&{4?ªd}e}Uó^à\¿*]q1ºß~s¦îQ7%F#ـٓŒz¡[L¦î±¾²¾R=Ëï®®#zþ[†½ÅÔ=ÝqN^ÛÅrÀíDZ<Éz¼`<‰Zë,`eàíEG½‹Èýo#‹ÔZ‹€¯_³(ºâb‚¸%…d}e}Õ—žN'F8øÑë_d_Ãù,ºáÀ¯ˆ´x’ ¦×ýµ&/Í.ÛþhÁž Á¯g! ŽÖµ8:b}à›©Ü%µž ˜Ýa¦d}e}5Xþ¼†h°ú6ð¢@D³ˆÉ«³(:jcàÀá…$h}j—¼þ~0)}žhÿ–ÖÙÃgÞMLF6Õj¡­¦·ïìã:ÕÔ=êwaf§¬Ÿ~_ëY…fêë+ë+ÔXàÃÀƒD‡–å-’®1uO÷Œn æ°PgÊû:`g‹BÖãÅeêž‘ŸxµÚjéïÍo_88¸ƒýí²*ð;à§À/-©­n>üÖ:­í¦¦rþp§Å!Y_Y_ ¤EÀMÕÿ¯µX4`ž$:ÐýØÌâh«1Ĩ¸ S½.© Šè߸ƒèÍŸ•íÝ_úà`ðc`\æù÷ ûCê¼oiû=„.NO!r*>N´ Ÿœÿ,ð‹²u|øn•õoFLÀ4†HÛó‡:ÛYÚž€‡ˆ^4¯N÷ïK÷Ûá´§¡£} ø5py…﬚3#•ë9˜‹Wê0ÛÏLÉúÊúJY{ŸÎHדæ,× ¹˜¤úB` ‹£-Æ¥cæ|àP‹CRV;S÷@¤èX·Â²òÿ‡ˆüøtrÃ9Ʀ“D•á“©ß:\ZçÒ‰Õréñ_¦Ûd"øýªôø:DëóÄt 1ìòU9?k½í,mÏ‘i݇Áý#2÷¯hÓþý:°ðñ®³ß‡ÏìI4À|e5Ñ”QDƒÛà}R§šºG½æP"oª ˜­?ç¹…è, þ`êë+ë+µÒàçÀÕÀÚGǘº§7ìJLkŸÖZ™˜äç,Ý9V²о@ÿL"WØj–Uú¿|îB ã- =ìÍp >Ïv ±t IÀb"¨_ÉÀûÓÿ¯nÏùYɱ¥íY1Ýß<ÝŸ”¹ÿD÷ïZÀnÄDgû´`ƒðcÛøðgì‰0R/þ üß]°èW¯²³u­sè·¾²¾R;B<··(:Â@ïx5‘µáH J·ÂvDÆŠ£<>Êz\Õ´#п$Lî[aYµ@ÿ’²çnJ CÊîä?ÁðË€­rlGùÄ¿ëWxŸ¬3œâçd¢·}£ïQm;ËŸ;xºÆývíßéD£ÂqÀNŒ,¥Ï ýØF§ïŽéÂgb†ª[&•Ó…é¤îC ÖÜ"úÕËlÀlÞ 6`ýÖWÖWj—ב/­šg ¿·L~EŒ*ÚůçˆL'RõÜEÄq$ëqUÕ®ý[³·TXVéÿò¸3p[…õ>*¸<Û‘5‘èÑ?½Æè)¢÷û\`ã¼Gµíì•@ɪÄ„+i‡Yç ýØ–öKK³Óˆök‰É¶&hý11}þ×¥ò8è÷WbdË öÚ0Я^gfã½sè·¾²¾R;­IÌóöU‹¢­ ô÷¦¸{+øU­ëUÀO€GR½a™Éz\uµ3GÿK‰ ß›*,«è?•ÈÑ¿ €þJæ„h'"Ø:*ðßÑÀvdý‚˜ìkÑ›ý•eË/.I'`4øµ¶³×ý%“‰`í é ±YÎuòm bèóˆ€öÄÒCx›—>ÿ_RyìAþ½N5Я"°³20›~ë+ë+µÛàoÄ\r¦Þhý½kTÚ?çÁëó‰¹ß@Ìí¸â€~gÇ/_N¤“þ!Ññõzbn••üYËz\yµ3ÐH8Uܵý‹ˆÜñ÷ÁÃ3'§Ó¿§ÇÃO_ÓàvdO¬Î$Rë<ü´lùž©L>=‚ÏZk;{5П=àn œl0µÖé­wN Úö^j _Ec¦ ˜ ú­¯¬¯Ô ˆÎe§â(•A  j ?k2ðfàXà÷ÀÀcZŸ/$j¯N1™ ý)ËzÜØãHƒRÝV+Ž:¿w$]ÞF在þØzëÑ mïýæ ôKÅ?7Ñ`2Ð/ë+uʲDÞòã±g«è×H¾3Z ’õx7˜cQíöG†G:,!ft_×b‘$I’þgð¤Å zxÑk÷(‹CêªIÀ|‹AR7è6XPå6½@ïѫή®J½K€åýÚI’$IŒž+{¬4÷Ø`¯.n[yZÐ#‰ÔŽ¢î-Ïï z.hqH]3Šèä(I]9¡ì7³Fø¹î¡ý³Žwâ=zÝoÒßÏë§ÿ—#æPxÖŸ¤$I’ô?‹{ðúáPbãëÝ==ç `gà à>à‹D’¤Á1Ö"P—\“ùÿDÐÿX`[–$IÒ`=@Õ÷“’^@4ÆÜi‘Hµ Ï¡%I;¡”ºí7À'÷o^L´X$I’4 &’?§ó4àb"¥Ï,à–N­³2p.Ñ»ûà8–îàUoùTà¢Ìú·s÷ÎOç#§%uÎxì¼(©K ô«W,"ò}žAûW"ÒúH’$I ?%ôS­÷–-?™Hù³:°IzΡ ,? ˜›Ö¿ ÑGÅs.1?Ú7- I’ƒ~õ¢C€ÙDo¥ÉÀ‰$I’Ä$"û瀧ˆ€ÿÑeËw>Cô(}8œá`}Þå3ÓúçGYì…õIà5DG*I’Ôç ô«W= |™èémº ù´Å"I’¤>´K§ß©fZú{_æ±{+,¿'óØ]Àj .Ï®ónwOa=¼‹èÕ¿²Å!uÄ`¡Å ©ÚèòÖ··nxøðà·D¢÷Ëûó•$IRŸX–ÊÖópú»fæ±µ+,Ÿžylb´l#˳ëœîî)´;€c1…Ô)c‰‹’ÔqíôòÖ··nz ¸šü[à|à¥éÂD’$Ióˆ‰x$F¬ |¶lùEéœy<‘gÿKÄD#Àl`1!ë‘ ,ßX…Èÿp¦E^xK€€ï§}/©}F§ßœ$uÜX‹@UÊaúR`ÝtÁò ðBà‹G’$I2‰èMŸµxŽèäòQà´ôølà™ç½™áÔ;è¾³Æ{Õ[þ0ð¦²ÇŽÏüð1òÍ) Þqp!1BãˇÔ6',IÝ`~õƒ»îy´ð6`‹E’$I1Šçωu ‘>g ÃA~€M€Óÿk‡£\;å‹Àd`w[áìAŒ‘$I}Æ@¿úÉÕÀÉD¯§…DîÑÍ,I’$õ‘•ˆ9«ÿ®%‚ýR=OLJZ’$õS÷¨ý%ý]¸ø°KºzÎâ‘$IRY¦óÔ+€õ,2ЉDŸõ€;-©å–²$uƒ=úÕÏ.#z÷ïM /¾OäÌ“$I’zÅx¢·µÔnÏ“/nQHm±,ðŒÅ © ôkÜÜ ll |›èÁ²²EÄdÆ_Oåóêôÿº‹$I’ԗζ^dQH’Ô?LÝ£A2ŸÈgz1ð!bxôÝÄÐÕ‡¸\fo6H÷W¾ì×ERÁ]EL` ps:¼Ìb‘$‰%À7Ï{Y’$õýDCÀÒÿ_$òø¿ø 0¯ÃÛ²&°°5° °>0˜_ [6žêÂû. æQ¸¸ ¸¸¸ß¯¬TXc€ À®Û.öOÿ¯\|¶Kåð,ð1ÂìF¢ÑA’²VHçAR§üø ÑÉçA‹Cj™I]ˆ+HÐ{þÀõU¶+»lCàj†{êõª‘nçL"± °ª'ýmuˆ—nÇ&Úe9`Obî€uKˆIÕNnKû{AÊâïéï«»x;hhØx=‘FèöT6§a®C©&ÿxkªOft¸n[DŒÚÚ,ý]¬Ø¥2l ”Î n~GYfù•‘”ÎGY ê g‰ŽN&:?IjQmŽ'HRÇ4[™Í¨q‚;£à'¿y·RzÞF}¸«­sz|¾ À.DûoÐú9,Æ#‚]ç;¥‹º^ñºt뵋Þó‰žýf°F"õÒ»£=ô)Yø!ð(pð6ºß ?‰hh˜ÔCå4x%ð5à>àÏÀýúô¥ Ó­×ÍLõ¹ºë½DÞt©“Vî–·(ªÚ¥çä3¹îªžqFªÓ%YwåbS½eµô÷f‹¢ã¥Ýû€CÇÒºÙ§½ÒçÿöàçÿknÓbb^…ß›Çûï'FøHê¾å‰ž€û?&¶çôȶÍ#F õÒðéEÄüW¥ãÌnÀ±DcæGˆÞþ’ϘtÞ#uÒ#ij÷'ZRKŒ#攤ŽÝãÛ·;pG de{Ç—þ߇è04ŒË<ÿ "ûÂt!}H÷}!à}Iº¿´Ø6ó~= ^ œîßÇpê“ìv^šNà¤Û–Þw3àÚÌóþPgûÙ–VY‡áI[ûÕSDCË׉t1?¶¯ð=Ìkï´/¿I¤£ù¯Uψ\GŒ¶ø.ð'"ý‘¤îÚ¸&^LüçôØ6>ÑÃå·83•Ýo‰y>è×JH+ÐÔÒw‰QÇ’ZcyàI‹AR?heꞈ^mëVXVþÿp:0˜Jô’;<-Ÿ,a8à=™¨×³?1aÞxà÷D6û~GùÈ€ú™ûWÔÙæ¼ePoûÙ–Víß·=?J4(l¼ X¶‰uöúð™Ñ©Rꆳ€wc³Ô ¦b“Ô5½è_Bä1?xKÎ׌bé–™éD@¶ä"¢×ùTà‚t"“§rþ6p‘g¥&?W3£F²ýݰˆ˜Ðõfà3i»–îo—¶ÿÏDЉEup2Ñ£õ~àkDƒÆ(`C¢ã-ô^®ê~S ö“˜[CR{­ü4ýîœ4¶}ž#‹7öµ8¤0Žè¤#uÃlb$ûë- ©iN®.©kzu2ÞC+N$‚ y|•èa½ 1à™éñ5ˆžíÏ=å–äXßwˆ´ ûë5ù™OþZ ¾n¤Ûß+n"&6>Œ˜óà­À ™Ï°:1áíŠD°|l>ß¿‰œ–§§Ïúwàb‡ÁwÆ]Äpã, ©­F”'ï„'‰Ña_Ày^¤~öBb^Žíˆ9¹Ž$RDJv:ð>‹A’¤âêå€ê¿ˆÑ¤Ž{j«S ô«ÛF=:×m Îyz€Ë«]uê߈üÝ*ý½ãÅDÊÌKNÍÙkÞœÎk{ÕæÀŸˆ¹©6õçÝ·Ö Òô0f ¿·¼:Õç—oôëÙõ€ ß6ÜÊz\u Yî߬³U?¶±À4`Kà]Àˆ¼Æ;»›­Þ¦²Y“Ti‚ëlЧôÿļ ÷yaËŸ÷@*›RЖ5Ö ‘ƒð\"ß#ÄH‡±eÏÝ'mãÑË~ÛtàÛ”èù?©Î:®^SeY¥Ô=ÙeOçx^­u®ÏóGl ÌÏ<·Öòr»yîŸ †ómU°ïé6i»ûå7gêuÓ8¢°Ú„•“Rý²vYRª×&‡ÙaÁ[¥‹µ<¯¯UgÖ[w3¯­Uç–¶9ûÛÜ•á@⌠¿Ý]hM ñtbâwƒ©{ºg7b’F'l¯©D‡šwY}e4L]É¢øß1ÜÔ=Ý;½ø†_öz 1 ÕùWd=Þ'qiÐ-"‚?ç·{Î'&£Ú‹HÓð'`"ÃD–NñðàŽnS#*§¿ÙJk¢÷gɨ²åÓ‰üª•\D¤¾™J ‘<«`ûóN¢‡®¤æmHLÄ»¸ÊòiéyDzÃÒ©Òè\àwDOú<¯¯¥ÞºÛõÚÒ6ß“yì.–žd¨lùÝ´fîYDCBI©QaA:VµZ­Fç ThtÞˆ#‰yjY¶Þú:‘®ÑžŸí5xðMbô’úÃàJªwb’:åÈtÍú‹¢­þ|ø9‘6XRè—jðæçÞILæv_ºYB¿&ß'ÿó[øÞ3œË¿žyDpþhbhãTàKÀeÏûjZ¾ ðEàÌ ëZØ X–èíº|óô’'Ȭ“TßTjÊJ ÙùÙFÅ9D#Át`JºMf¸—`½×?›êÂq™íÉ»îf^KŽÏܪÆÕF<ÌpCCIi>—SZ°þF&¾%•[«µk2ãFŠùj‹j‘’ñ£ô÷ýä.bþ«,оr91JVê–‰9ööÇÌp>ðkbÞ)IÖŽ@ÿ·¾½ º{R@åP">èEùÏdYÐÂ÷z˜h@(õ6Ý¢Îó÷!FÌ&z|^Eô€(YLŒR˜EŒ<¸žü—C4ÌIŸgo`Ï‚í§ùDˤæMHõ]5¥†Æ£€å‰`úçÊ–Ÿ ËpPxub°<¯¿7ý¦ßA4@ÔÀº›y-9>s+Wµ{ZIµ¼x‘¨ÎùU:_}EÑ7 ô«›–¾C¤+|Êâè˜Ã€¯¶($I#Õ/y²:ݲ1ðŒ_ŸžÙƒúû0Gÿ{/Ï`—›\L4ÜÈÒiRÆ —÷›5ðú}ˆQNw7¸îf^›UÞË|*1™ú<àQà»À2eÏ݇h žGô0׆ýQ©÷{鱈Fã{Yz‚ò•s‰ÑO=·JÐ?Àp* Àî5ÖUi^™jïYÚÇ ˆç¨žJ§|¶¬³Í•L%cJïWþʳ¾VŒ,0GgM¿ã´a_¶c]ýfàÆ:¿MǸtüoQ˜£¿ >M¤S罸š!×ȱÑT’ù>‡©$­Ç¥¾g dþ­™Ø±Ÿ¿Wþ>ÚÏ@ÿËèïöIp'ôJãjÞ@ÿ1¢`Lúû÷Ìòó‰¬ã‰üÿ_®²¾Zë*ô×zÏ ÓˆQ«¦?ÝÀÅ\­m®äüTN¥Q"+{¿<ë3Ð_<{VÓ†}ÙŽuub:½½ga¯þ~r)°Å` ¿Ã–'F ç™Û¨Ï›ÕHàº]uüEÀÎ]<6V:íô±·ï9’ï« §osôKÅóyàGD !IRû½ˆ¥'×-‚oiÛ~ lš›ìJLj÷$Ñûþp"ÝI£ëjä=w&R2=Eô o¤°Ñm.=fz¿9Dj(š,õ¾ý€ŸX ]õ“´Ô®`éÑYR'¼‡H9;{@?»æ@jÄ·Cü*JÅd _*ž£ˆ‘çX’ÔvEl\]L¤\€v—Ò•&òÍ6ZÜEí^sÕÖÕè{Þ—yî½ |–F·yZ…÷¸»‰õ©Ö^HŒ©§^ê¦FREíNôœþf‡­®Ãp¯¹¡6¾çš™ÇÖ®ñü¡·¹ÚûeßczëS1ì@™—äxîÉDÃÔêÀ&)phËɶOõV=cÒsg[P½qð=`7"0¿ x!­c111÷ ÀµD:Ç—½@o!&±¬öÜãÉÀzéw2-}ŽVX’‚#;ú•ì ÿNßS©SV$F^^ey½Ài½†ÌZsøÔj¬­·îf^[®|]y‚Á4"ç­ËKŒ€lÆ¢±`u¢ñ昜ÇÚJÇ®ZëÊûž?Me85½ß{kl{¥mÈ{~Pr‘†i*1¹ùû<‘¤B2GçôcÃ"ï~ø}˜£¿ÿu#G¿òïZ“ñd9r IDATV«û/HëŸ.<®K˦¥zg­ëªÔƒªÚ{^ü,]Ô®L ɯv<*߆zÛ\É Ï 05 žnp}æè/–€ýsM&¥Föغ+ÃóÕ[^Z×Là:–î¹^ï÷R~Lß…êó-M!æÙ˜Øàwó)Qé¹€çXºám+àÎî‹£ Ô ‚PƒÌýóvàW5–×›ƒçTàìTo®Ž÷_Ïùúzç2µÖÝÌk©SÇ×›[iˆ˜Ÿ&{NÓŠÆÛw‘¿“K­9£VL÷·$"9ÖæYW¥9£j½göüòMäŸ3ªÞ6—+=í²ºäé×gŽþÁ©Ç[ÆýRûeg¡/Ý®Î,Y B,L¢ÿo){í?ËÖ¹Ñàé6m¯IêOû¤cÈl¢7ÛUÀ‘iÙÃÀ÷RÀ U=9÷%E© έqœ©´ µ¶¹Úû­B;/Îl  TL›7æx^½ÔMyR;>Iôšod$ÈPÙzï¦zŠ›¹À;ˆ †ïKßã­j¬{ÿ˜ü‘èW²Ñ´ôûš üŽèáß*7¦ý¡þ`¯~uÒK€kª,«7Ï"Ú'€ùéšû(àÝ9__K½u·ëµyçú|Z>ø µ{ªçuMÚÍ0•¤©$Õæ’:£4ì«Ü8¢§ãÄð°%ÀKeË^;…Æx}zìíÀCÀº­¤69¸ÙbèiKˆÞ¹s½Øg•ß•§B𼳯:?šn%?¯²®ìûÔ{ÏÙÀ3÷ßLíiù6Pg›Ë=LôÒÊ:¾28øƒ3 ®¼€È•Ÿç»Ñ£«tqMÝToyéw÷z"@>‡èm ð,‘2`\újÙ{*[ïôt.WÍEé688+÷•Z\9}¿wþÊp*âØTo@Œ¶Ù¡…ûâ Z;B@Ýe~uÒêÀƒU–Õ›ƒ'Û9%Ý&+å|}¶±¶t-wÝͼ¶–<ó *[^¯9¯ÅÄHÌimØÏõ޵åÇ®V½çÅÄÎR*ÉÏÖx~¥ãgžóƒòÏxé¢>×@HRa BŽþZ©p–I†¿$z8N«òÚuˆ™cÓÁf6°µ{ÖËa¸c:À-C4$\Tc{«=·ˆûÃßG똣¿F/'‚ö?J¿ßËÓÅûDpè1"ˆ4Tå6Gõ‚ïרGµnen³Û3·ëˆôp¥ÛóR]ÿàkéBè@b¨ø[‰†ãÍUsn÷ÖD/ß…i~’.jú9ú{óÕ{þ•Às3·d–¯ü¸´]ÎpùlÅ~)‘£ïP"/l­ÉuëMþR®ÖÄmµžÛ‹&Ò¾áèþ>–f ¿·­.HA¢o“$îL^_œêŸÓmTÙë—ê¶ÙDc£ºo¤“#¯˜¹­J¤9)Ý6KÕ¥ÛD0OàÃDÿkÀÓÅñyéxôŸôÝx&ÕOÛvXÚΗcxý=^ö²A»P7Ðß?F®A®Ï ôwÎu鼤šzÓz ™õ^_­±6Ϻ›ym­ãEžÆç¼È­Þ%ùðç¦óÇ¢xsŠÁôª#Rý»ÀCÑ@ÔãR_]ôÃí¢e¾Ù‹»U‰¬¯ðÚ÷¿ &[Û’Úþõâ]²iÙó³·ÍKçjÛ[í¹½h-›XÇßÇÈèïíßÁ D`v¤©¶~MLv©ÅÙ3>H4 ÷’q©žÚŠð™ø_.NnLßÉÜე6Ò@g—½Ì@¿Šì*¢£Ï 2Ðß9yË­¬›{m>ž‰Nƒ¸?Ú­<•ä¿€c¬â­Çû9ú¥Ö¸xa ÖóP:ؼ¨Â²_“¿=ILŒUK½„¥‰Ûö'rîÀpoÞj“¼Uzn/ZH! ª1À9Dì=yO•·Ã[§Y¤=cUZ“wµ•ž%z‘]Iä?؃ ­HLzûûT7OŒø9°Ÿß-I*„[‰IR%µß‹Xzr]µÎJÀo‰ÿ!b*‡Y,ê7ú¥Ö¸‰|ùëÊ­JôÀ(á§CÿUá¹ íwçXo½É_™¸­Ös{õäè¿’`»½sТ‹û¤:@Ý·ÅÊ•¼$O'æˆx9Ñ›ê×Dú¨Ó±jt¬’úÕ,bž%©ˆZÕ¡IRmŸ'æÓ:Ô¢h‹+ˆŽ'ˆ ÿ~D'J©¯è—Zã2àµ#xÝÓÄÄ.W¦ƒÌDú½ª<ÿ_äòìKLÈóHÚ¾33Ë$r._Ia®Ë,{˜È!x1tÕÏíEÛóHƒê£Àq-Z׳À-Dê/ußK€k þÎ>@Œ:ûÑ€}71`w³$õ”[ˆÜR¿™,×CÛsT::Ç]#I*ª~É“µ‘ÞÆ³î ܬæï£#ÌÑß{¦ y­¬‹Ž#zc«ûÇ™ûûøó­Oôb{ø‘*®èÌÑßÙãe52²ÜÕ¼nÐrð7³?T<¯ òô*sôwN¿å„wHÖãgPRjˆ¯³(ºj{"Äl‹BêeDï%-\çyÀÛ,Ú®{ p~¾Û€ˆôkSˆQe{ÐÛs¨nIß©N½.é‚sAævuY]~9‘¶q‘Kø-e¯ýgÙ:—#Ò/>í.Wêçõ-I’zŸ~©uN>h1tÕþÀ‰ƒØ br+]Fô~X×âíª÷§ÀçœêòwŸ. RÚIýf1°BæöŠôø8b‰††Óoâñ²×Naé´jo§÷&ëVx,ý]É¢$©·è—ZçÀ–8YU·llžöƒ4¨V£õ#Z†€ï[¼]³Uú{å}æ«€W×ÿGôp–F"›V§ôÿÄœD÷C×{DƒÓ¹ÀÄ\Çñü v÷î!záÿ˜Ú7j-" Û‰ÀsDPÿjž?ÿЩÄ\%{§¸»Õ&7ÂK’¤6Ö"ZfðbâÚwYw ð%Z›²D*šIÀímXï À‰ÜéXÌ÷eàˆ=®Î$8.$z5_à×AMCÓW'&€>xuŽ× <™^·ÑëþдŽÒz·'&¤ïì¡é÷Ûˆ{û€3‰Éª¯"%Ê’~3‰FÞÍOŽàý¤<î^À`58kdV¶^ l@Œ™’ÎQ'iÆ––¯ðÚ[-¾ž²‘§¿O±t ¹yDƒ5é:ý‰Ì²g€ùé9s3ÿÏO·¹éùó‰k`z:©.ýRkìG ŸþµÅÑ1ïÆ=í¤A6) ·Ú“D0ëXà=sG½ƒx_<Àeð"Èô[`àW~-Tf|_óùßJ‡_ËY·îJ¤0{2S'Çp àó™å_¾MõÀû–ž<ó À÷‰^ü¯%øÇÁÕ¿=öoË<ÿn"UÛND@íìôÚn›HeÔ_îÖ´TÃÖ©¾Ûø31·È/‰ÔOsà>nOUXÇ?ÙH(µÇD*Å›xÍòDCNöø9&ý?˜œY¶l:fL"ƒJÿ¯™þŸ’ž?XX#}o Åo#æÓ¹…h$º'ƒ— ôK-6|¸¸¸Ë"i»õoÛZRÛý§¦=Óÿj¿5‰Æ•í- þ ¼ø=Ñðq¾E¢Œù)'п˜á|÷O‘/¨4-ý½'óØ]DOúì9`vùÝeË+mGµÉ~ïLç“Áo©zÊGüŒHßóbàÝ=²/&³tMõ‡€õ,Uññtû°3#ot\HŒˆRoIÃíS,݈óx‹·iE"à¿vŠlìBŒ>X¸†ÿÏÞÇÍ5ÞÿÝÙ„¬–Db‰­"‚Ú¿ªEìT´µ´Tì!E‰¢JPŠªjo#k,ÕÚ»XCµ‹ÜI,‰Èz‡DöýþýñùœßœûdÖûž™sfæý|<æqfæ¬sÍvÎ纮Ïï`)ï^ÁRí‰ÔúEŠo"pÖò°Р")™n^ÎçùE±H­+e€¥ö5`¬ŸHK鬅µ„ûÖš]¬EÙXeúçXþ~°”e[ÓK´ý uN/RÁüMh:&J]d~/Š38îL,½ÐËiæ=ÜŠU:¼‡¥ ŠÛf:'«J_{ª$C°ñIþ–5K&ñkM3+aÇ5ÇocÓÌë ìì·c€aX¥û¿€çýFi~¥êi0^‘ÒxkyõŒ–â[ßÿ°ïö ])½)X«þ'±4Rm±Tpï¢Á5£ê±\ýayEÀ*¶.áöça9ù¯Á*áºaã=Yî*Ÿ¿p)–g¿9ç7C°Š°ÀÅX Ũ…XŸ£ô^lCúŒT¶iX+Z‘°VXÏêŸÓò ?X _&ÃfXÊ®etÌs°ÊñŸb½ê~‰õJøV }-°­Þ^©öf)k±<ýcHF «jÒÇËõ/g1k’>çi1½ˆ øøÖbFŠ«#V‘²¬âHëyà.lh€W±¼ö¥4Ë;<«pz¸:4%Ö꾞T“«š±Ÿ%XŽë7°\ÿŸc­*O̰ü;Àø½{ú9šTú%±ÓŪÜ{Gç–‰±•ß{wð6VI¿+p–VêY¿Ž9@o³ˆHñ5’j±T­ŽÇº]Ÿ„uë–æ«NÁÒ!§ïGì&û‰“$LJÀveÚ×±€×I*ö¢éƒå¢¿•ÔÀe’ùÿàßÀa >Ƨý–tCü÷¼’m€õ8*f#¦­¥úª¤Ö´‡Š¢ê´Ã*¡jñZ¦œ“¡éàÞår+pV··6–S] Rãw;©±bªM%|ˆU.i,,ýŽ‹HÕÊ—m[ÿy k¥%…ÛPçmj§‡„ýR¨rúúbéG°c¥yÚ¿Áò ž¤âÈÛظ8]z| ô—׋À>EÜÞOýó%ùÛË…,Õi–ZªÖ(ПٛXnþ$ÿ–KáZa•çÕÞ‹§8Kéó0굤ßñ*ú‹Hé}Œu{xÊ/üA-6siëåô4–éA`7¬[¼ˆÄï¿À|€¥Òê®bÉ[¸EÑÞÀ÷{U,yû Kßó;…øgáEÚÖÅXkÆKT¬Ü©b¨ZSQ¥¾4µÅO6 8AE«ýýZ•¿ÎFà¯XÃ¥ ÀûÀÏôö‹ˆ´üǵֺϬœŠµNŸ܇u‹Û è tªÑÏB'ýý¼<îÇR½‚ þÙNßÄQ‹þä)w‹þ°^ÀmÀ¬…ÿO±.ØÒTàØàuS±¡j¹Ö²ÿÔ‰ÀÆ <6µè/ÿw«ëé!å׫ôUC²êõ,–¶¯Ö¨Ezka‚ÛšXE~O}åô]/³°€ÿXƒCÑïxÅž‹Hy-ż ë¶/°0؈±ƒýóþçZ<‡¥²˜®ŒHEøËÓzp¤ÿ¦ÝŽåZ­ÇZ;ÅÇ*§îØ`–ãb(—Nþ»¾ëõòúVÁû™>:-þO½ky}ºŠ£¦­®Äz©E^ù]\Ãï»”Ïlÿ/èìçuŶø3pp®Š¹ìv÷sæçjðµ¿õT¾«ìø °H ©4 ô‹ÄkÖrýþ„O#0XDZf>–~æ^¬eç–Ø¸øEaÊßâsK¬•ʣ_äf¬+ôB}LŠên¬òd3,ϪԮ‡°^“‡c)ÿ¤<~†µî}TEQÕ¾ÖQ1ˆ+U ,ÐÿÖKõ#uÙ´ösÕ³k¸ æbyûoÂý‡bE*†ý"""R*«°Ü­ãc>ŽX—Í!zKªÒr¬÷È`à<GMkÄÒÿý x˜¤")¹ï`½jöVQT½9(%Ÿ¤”2п 6?|µª.—+wÿê\‚³€°`ÿþÀ2}<¤R(‡¢ˆˆˆˆTº‘ÀQXn_©m±”ÏÝT%ÕÍËù<Ô›¦¨E¿„•2Ðð"–>æÔã¼~Œ¥ªQƒ Óˆ¥ŽúkL"R1è‘ZÔÇOâ'ús½É0»>XNðZq5–r(©¯ù üTmÁ…‰ì/õç±ÔY«8j‚ý¶&–O¿”.ñÏÜu*î’úp pê=u°9ð+…T úEDD¤V­ÄÊé']U,i+1.vNøqÇÒ¶ˆ€ Êû0Æ?ÓRÜ߈1X…ʵ*Žšñ56H§H¹¬À*ðw÷ÿøÖ*’¢;x 8øTűšeØ84ƒTR èI£T¸ÿ½€Tâ®öÛ+ÀI(ýCKÕ§`Aþ+?¨HjŠZôK`½ˆz¨HŠ¢p)0 ø!ð¦Š$£` p—ÎÏ¥R¾Ü""""²zKöuGoÙÀiNð_byj‡írl;ÓòÁüS°DŸóç;`ùigc!ŽÚ‡¶{&0K«3ëbLëû;˜åÛØÃ罈µš[à·+äýkþ ©²„Ü쇵Æ{µÈk®—ý7cOà~IÍÑ`¼—EXZ™1À;Àq¨â¶%¶^övÞW‘äôªöÎUQHÒ)Ð/"""’Þ=XzŸž@_,~Ih~k`_,h¾@¼$Ëör-ߨ Ø ø‘?7 èll t®ðyÝ[±îÖü_m/ÛºÁþ6ò×7’TÜ}I¥5ê¼WAïÙÀáúèJÄÇX0ãQà)àià”"—¶^NOûwëA`7 ^ES“Ô¢_â´ëIt8Ö¨áu¬%ºäo ¬UúËÀCÀþÀ KÞ.ÀRDn¨¢ɬëf/Éy?Dß|M®ÑÛ”(Û©V3x ò\º<ôáç:«"ßÁC‰¡e£ßÑþ¡ù¤Ùv¶åƒùáC;Ë#»_øý®ÀRàd Sd¹Ö ö´ÎÜëe©l²=Ÿ$­€éX¥FÜžö[Ò ñßóZ±p*–ÎgÖâÿ4`/¬Ò«SþNvò×ßÏËã~`¦—ÓÉdî­$µ£-–¯ºÖô¯€sò!ÀÜÊ%®ÿ¸VXÞôwñX šPCÖtz'ÿôßô+P…]Küø³ŠA¿ãI¦üR""""« Å_†ž›DÓܰ‘ù“Éž;6×ò+±< ~®66ô\/‡_Ôu#¾ ø¸x#uƒýÍñû‹©Ž@Þ*,=ËþXëc‘¨¥X‹Æ»°œÏûb½u[b½Xj1Ø?KÕ5k±ÿð¬âL¬ò¸Öf¥ŠCbþ¯Ôo;c=ïÁz/Öc(¾ñß´E1ß.À8,­b9µñÿ¯µ±€fo`M¬·çíÀ3þ(Íwð°©_ˆ$Žý""""«›åÓ^¤‚ó›Ð´‹s]d~/¬µT&….߀Sz‘jmõŒßڿºbošçº™Tzï®—½Q _r›†µ\OJ¾ùF”wZ’mVö­ŠB⿸ûb•¶ëøg5Žq%úù¹WC™÷»kÀñ9–nm‚ß—âYüK½9HÅ!I¤@¿ˆˆˆÈêæaôküD¾p«§º œr-¬ëx®àr!ËÏF7çc-øƒñ^ÀÒòl‡ ¨¶ k9¶*Ïu³™C*ÿWøÞ½€¥1©$ˆ§å©H!úgU~I¢9Xîþ×c>ŽC°ž–é-©J£°Hë³U’4Êa&"""’Þ@ =ÖŠ¿x¸:4%Öz¼k1õ1ÈϤÐåÁ*–`9hçûúÛø¼ÖXåCÖÊòdàø<×Ífp–ög.–÷¶’|Ž5fÑ@RIÚ`©QD’l‰ÿ/ŠˆÔªeXOÀ* ‘Õi0Þä½¢ïG¾4oòh0ÞôÒ ÆÛËK?—Tp|kJ—»´²Íæ÷X Îr¼÷ÇÅ| ŒW Ñ…ò¦)¢óŒÜ4oæryZ_ }OjÔXj$5žÖïxâèC)"""µh6@YW,( ÖÚýKMZ—bÈŽr¼o»êm“ ».[¥b„ R÷ˆˆÔ²Ï°Fûª($‰'”""""µîbàvlp-©|ï;«¤‚tÂRl‰$™R÷ˆˆ˜ÑÀÑ*IúEDDD`(6¨Ö#%Ú~=–ƒ[Êã}¬Û|k…ˆHѨE¿ˆˆù;p¨Î5%iè‘j³KôµŠBD¤hP9)ÜDDJ©øè§¢$Q _DÞÆûýñÀÿT$""RáÞvR1H…h¥EI²•¨õªˆHà àpƒ$‰º‹ÄkC`?` /ð¬;lœ-ezû´±Ìû]€µÀœŒÆ/Sõ1‘f‡ZôKåXXªb„[… Šˆž~¥b$ÑŸ´HùµÿÞÆýoÛ=ºn÷úñÝÓþ{úë¿ÈË㟎Nõ `‘|Õ}T ""E38ZDò×kD·8ÑŸë Ì-`ý5T^Wc +á5ŠÅw6ÒÇ\’B~‘òiœ |ô®6ö?û;×™~‡_ayæâª‘^à¯ÿ5/¼|®~ìåöKÔIDDò3ØJÅ """1[‰õÚé']U,i+1.v® ×ð2°·ÞJI úEÊc{,ïý€ƒ€Ã°n^+tŒó€-}š¤¢g±@ÿ#·€mõ‘‘>6EÄR:'ìLDDjƒÎ“Zæeè—Q _¤ôNþ \¥£ù(ÁÇúm‚íC,ÍÑ-À Àñúh‰ˆHË/-TRê(ÿøH""hKöuGýz|6p#«àúyÍ<`8Ð.Ƕ3-Ì?˜<çÏwîðýÏF`iigS°´:SsBó²­ìït`–ocŸ÷"6À÷¿íXïå+@?}¤%)è)­ßøÙý*Ž¢¸×ÿH/ñ›ˆˆH&ŸbÝ‹ˆHË-¡iàODŠã¬7{O /?_ë¶öÅ‚æ[;ä¸ε|k`',Åáü¹a@`3,…nwà Ÿ×¸8 ê÷ÅߑǺÁþ6ò×7¸ÎŸß—TZ£ŽÀ{z®¹ŽßDb§@¿Hé ÁRôì LTqU½—ëá^Î"""é| ôR1Hh‹õBI²¥À*‘¢ê Š5\„µz¿8.²ÜÅ>¿ïo@ŽíæZþrÿN/Á‚÷Ççaƒn/†Gù²Ëü?j+l@îoIe*ȵnàOXPÿqª/ï»XʼnHìè)£ýÏî‡X÷5)¾/ߟ©8DD$IXž~‘¤[ ȈˆHméîÓ/#ç/=B#ó'GæGåZ~¥_Oz`©‚Æsýö<ÖJ|p,ðð*°{žëû›ã÷“9íP¥ú°‹>Ê’ ô‹_oàز *Ž’ ‚ý×£Ì""²:µè‘$›åÓðùÊ&ÀŒÐãºÈü^ÀÌ,Û,tù,ß èê·.4MGó °?Ð x x¨€u3©–±iÞvÖGY’@~‘âªîcµæRz“€s±ÁDDD¢ÿ›ªDDD$¡æaAôk°Þ]݀ˀ"Ë]åó×.̱ÝB–ŸŒnÀõ`ùô÷óûc©»–cò®ÊsÝlæÊß_É”ºG£þFݪþ&™LÇj¸¥|þŠuü¹ŠBDDBÔ¢_*EGœˆ$Ù·4MÇ!"Å1èz6Ý›ÀÕ¡ù+—}ÞçÀÇX ?“B—„åëåÚØÆçµÆ*°ü'Çç¹n6³€ÛH¥ýÙ¡Bß¿IÀúÀšú(K5R Xïo¡Û«– ð6þǶy ~.zûs>ú+Jp [ŸøûPMß·$?&c-O$9>¶S1¬f«·Š’ÚP‡ ÇÃÓ~Kº!¨¢~§Dòÿ½¨µs¿þpN>¤€k±b–ËÓúJäu>ÞËK?—Tp|kl ÜR(Õõv¹ü«T\PaÇýð]}üõ;7¥î)ž£·±óZ3T7½¸Lô?ןê£(""®˜uƒ‰ãZyM¿^¾ÏŸÛ†¦ƒåJÊ¥XÏ¡ŽvÜã° ‘X)Ð/R<§w©bu—¿"""éX®X‘$k¥Z‘êv1p;p‰Š¢ªŒ¶R1HÜè)Ž -€W3Ìï€ ;pf–ƒR]ëNÇrÔMö­Û œg–cï ,ÿ]x]B—¸ßæ{(c IDAT¬ÝÖºÀ£X—»ÙÀ¬ž6a ÖŠa0hW„÷á%¬½‡>’""âP‹~I¾ŽT^š)ÜPl€ÜGJ´ýzª+m¥¨Çâ""±R _¤8öÂ̫2̆u?Û Øè\šŒ4ß \š7Ëç× Øð7_¹ö[ªuïÁZ¥õúb—D^ï¾þG¸6èN1Z4¬^ö×GRDDœZô‹ˆˆˆH)}†Å6Db¥@¿Hqì¼–a^ààx•¦ñåÀ9ØÀ¹ã7 ØoKÖÍe ÐkÅ_¼é®•¾½z¬'ÄÇXà¿æc/""" ý’Ù†À ÀØ?3ü<¢±Œ·O_{ac}Yæchô×=ãåq¼—ˆˆˆäg2–Í@¤ª4Vð±÷ææ¹l`…Þߢl¯—Ê¥ }°|’l ,ÕïPI^G’¿“±ž’Û©V3€Õ{IíØ¿¥Üžö[Ò !ÿñªA{¬1ÀiØKƒ€ëc7ÊíT`!Öh䴘ʥ£¿þ=¼ö“ÍLõðó}üM[,Þvôy»ø êB,¥ÈÀ3ËRiJD$ÛÐtp]‘¤Pêhœõ$ì\‰¥È9¸x/hA Ç6øxSù,ð×ÿš—Ç ^>×øµÓçXσ6ú(‰ˆˆ¤5 Ø@Å qJZêžÖÀ½Xp~o œs%Ö¥𢟠¶Ãr…Æøkc-Tæè­)š‹ÛKT""’@ ôËöÀÿ€‡ÏûõC4b)ÏMX¹­žÅý?ŽÞ¶ÕGJDDd5³±´Ë"±IR ¿ Ö­¾°¯Aš{B:Ø ØèŽý—û¼·°þéD{¬ <Š î9¸‘Õ[± ÄZ2ÏÃZà´ËrlÝ°Š‡Xnò3H¥`‰î;šž¥ÖÓa¶_°ŽÀº·t]©<õ {ÿ†úŸÙ#zkDD$–ú9àZ*Ššt2ðOàzà¬å|=…UF$Õ‡À~À-À XIQ‹~‰]’ýb>@Ëò˵~Œ¦_aƒ—þ úâ¿0ì ôÅrV†[-·Æ*%ú[;½UómÝ€=ã 8–a@`3¬mwòÏýÕ’uEDDD*Ý< ³Š¡æü¸ÀÏáïWqŽ@?¿æQoN‘”,Þ'›V :ް–øóš¹ÖX}66˜Ö©X+þ½HµÆŸµæÿNÛë ê‹€YXp<œ¿Øç7`¹>äØÞ`±/?4Ï×Ö88˜õ UâuEDDDªÁb`MCM‚¥èÙ˜¨â(ªz/×ýœEDDÄbŽ=T §¤ ¦´ ‚?…¥–y ÛXIút¿Nóûë7£€ïçØ^Ðú?<Àè¤È—¶12r–/u°½)‘åóÑÃß«±¡çêÈ/¯hKÖ•ìºb•KÛ¨(DDDm6–“Ô†£±†.ûÓüt ’]–·ÿUà3¬w¶ˆˆH-[Œ¥Õî„5´)»$¥îy8Ësÿ³íc&pùfgù´Wè¹M°º@]d~/2 loãÈòeX¯„ ǷȉôJ_¾«ßºëaÝZTŸƒƒ|:ȧ—ûôNŸþÓ§Ÿøt®¿÷_øT¹éED’k7¬W[EMS ¿vôþ€ Û â(© Ø=–ÆTDD¤Öi@^‰U«„Ï¿°8÷?‰Ìk¹åsìëcÝIƒ€zWlÜwòXw6pî5ØàmÝ€ËX½·ÁU>=àRl<€lÛŠuï\š?«ñ;X83²îhàRAêžØ€X-]·’tÅë}üýß«à8h‹åam ü«ôxÒ§ïz¹Ìð²³½/T^m±1Úa)ŸÚ¯ûö¯õéá¾ßM°ÞkûT-úED’«-°p0p–ÿHíY„ã­uXCÁäßsVZfp.p‡ŠBDD„o¨í†µ³$¶n{˃ÿÖ²ÿ ,Ⱥ8²Üylk ¼Œe—/'æy,Û±ñr?¦«CóWb=ê± ôh,ðŸÉ)ÀH¬†ïKà`WŸ·88÷ZlLÃBëÂz#Œ÷ ÕiÀŸZ¸n9tÁ*¶Âr¤öÃÆJÆ38øã¬²äXàE¬ËõX`;àŸŽÄ‚ügoø{ü0ÖEªð&€¿ K 5ÀËh+ÿé•vòéCÇAè=¾×§/út¼O¿ÕO‡ˆÔˆ¾Ø`ö•lS,ø×kuzfè÷½}‚¥:”Â(Gm8˜®ïHÙýÕÏÝîçä"""µj‰EýõiŽã šv¯ÎÔúîö,Û Èþ¼€c‰æ®oŽÌã¸ïÎsû³°î­>‘ùwG¶usèþ",°}V†m·dÝB<ŽK†aƒ_‰µ úÖ’þ,¿ð6&Âp¬UüiX¯Šïúö–c•9oyùßàÏïǾ¿—›øò»ùôpŸþʧ×út¤O_ ½WÁç¡T‚” ô³;åÃ)ž€¨ì Y'Ÿ~õðz·‚O¾ûú§‚˜…›‡UöHu_×ü6r®Ý}€}»áû’ÞàïÀcXã‘Z¤@¿Ä~B,)ÛÐtp]I¯/Öób9Ö‚þ~ÿ¬×Ä©XûýÂzK_¯ŸOö鯱¼Éw ûýùW}:Á§•Ђ~>LR ?~]P¯ ‘bz àTªÝüdûè*øô×G²Y”º§ú ¼ |^æýöÆù¹lààÿüþ.XoÛ°-_`é>Ÿ ­ûŽ/hõLXÓïz<ùVJ³c"Öûö§¨U¿ˆˆÔ.ú%V­TÿßÅXKT9]„å» ä?äЯaþ XKžy5T&Ÿ¡AÈ’b3¿ˆKçÖUÄÖ:¥î©~§wÅ´ï•XÏÎàùÛacFci>ׯRjΉ¬ÛØ6ôÜáÀÌ |îò÷ADD¤V} ¬«b¸(П2P÷‘2î3V*ß8`kC"lƒë ""XtP1T­ ±¯f˜ßë9:ëuzOhÞØÀ½ ÿß)âqmtÇÒ[.Ç‚úoacU…N =>™T*ÊLΦøqOÅÆëK]Ù«Ü\ì˜å5¦[¶ÖÛv¶—׈®W^òóáúHŠˆHÒ`¼+úEŠãU`/C"ì™æZDDj[bOªÓ~XyU†ù#°›b {†‡æMÄÒêtÅz¥Þ\Äãš|<ˆ lÞ=Ãr#±Ô\m°ÊïOgÙnwàV,]Q,­æ >o_šö0x/ËkL·ì0, âfÀƾ¯+ò|½«°Êƒýõ‘‘¥Æ%«J ô?¬·¬`pr.Í÷"°7ª@£oïÄÐsÅ´·–BTÌÕX°I#‹ˆ”׃°<¸"""aj]UÝ6>Ï0o&Öš¼Wšyëb©jaÁìý°JR™ \‡'õ8p°K¡“Ë3XŠœnÀSÀCþ|c¯1ºlïEªÒ¢ …åþKû#""R‹è—XUJ ÿà•4'­b]Uƒî°A=hõp:0 ËîBZÈ SÁ¶_ú…âp ]žÛ Ö?˜<—a?™ ˵ÿh tÝV_úëã^raƒ˜m¡¢ˆEo,§íc* ‰X¬¥b¨Z°T3éÌž®Ç*{ÚJ]ÓK»óß\äãZBª’¡+60î;i–]ˆõLÌ'MΆXšŸ5°t< IO0Ç_ÓFy¼Æè²ó°´A7ø±‚õBد€×ü-…õÈv•m änXeÇ,íÑ>YöÑ’kÃ-¼ìvòÇ`"{“~0ã¨$š,""¥£q¡$Vm*à×ñ“Ïñ‘çïñ‹¶žX7Ðg°.ŠA>úव§?wð}Ÿ7ÌOŒ7ÃZ²<äË\˜áZû‰w?©zÚ÷õ»<·×ÚO·"s+¡>ÝÔOîv)`ÿ¹Œ¶×ǽäVW×?Sq”ÝuÀedˆODDj—ZWU·ŽX4“S±t–Sü<á àM`ºŸ·½µ¶ÿ …å£Ïe °\_Û¿D*O}Ô;yn·µŸó<â÷?Ž÷y³°ÔAcýºdï,¯1ݲƒüœj*ÒöøŽÒ¿%ƒÞæÛ¸سŒû|:tŽšdC°–Ä›Tøÿe>æ‰}?¢×+ù\ãDýð,°^èZp¬ò&X÷qÒ·j/Ƶᓤ‚ê»K3¼®°®XåÊéXÓù9Ê$Óë.›ï1çÚGs/ºÔع_ÿ=Oò9ù¿u-s¹œQäÿ¸·Q`9)b=º>RQ¤ ÚZE¡ßñ8TB‹þ9>í:9êîÓð4 @*°2´îbRÝ@ÃLê|ùl'«á}Mí+Ÿí­Ìñg•k°lûÏG'?”ò\Øœü ˯:IERrßÁºãï­¢©;ÊA] Á¹ !ÂŽXe{©Ö©¶óæl×8ƒ€ °Hm#ׂS"ëfÓÒkÃ;±`ÿ/° >‚A“ÏÅ*0>ÀZÜ¿‘aùL¯7ª9׳"•â&XNŠCTÍ¢t‘«JÈÑÿ ÖR¡wè¹Y> ªµ 0#í5g©ºÈ¾za­3𻽍lƒ„åÚÿ2¬+jp²š®«ÛÖ~b)å1ÑOÒŸ¥:º&Y7/çó°ÁßDDâp³ßÔ-¹VP \DjI¶kœlƒׂGÖmŽ|®å:bÁÇÀå¡yyl?©ƒ&‹ˆHiÌÃzŒ‰Ä¢Rã}èùâ<ƒuÁ^ËOœ.ÈóKלA¦®ò}­\ŠulÉö² –kÿS|ý#°çÓzŸÖa=æ„––ÉúúH‰Ä~}´BÇ*"""ͤ<ýëÉ¡dWs9Õë}ª«°àþ¬åæ…Ø@²ÿÂNã°€Ï,×f­é„)ÑkÙ¶'ä¯îÅœ^¦‘HâiNÁóÏF–™¿·Ä‚ð½Ólgè?km1ø[û ,Ïr¼S°^?ÀW ·‚`ÙWÀ¦À À}¡õ6!ÿVÏS}ù>þz·òçƒT=aÑ2™©”HQõÁ\ü¸¼ô!,ײÐüÓ°Á`'úùǺXê­ý7å>,-Wð[Ñ˛ޫÄ{ËÁ6ðó~îÒKAz&©VûÝüܦŸÿæÜœæxÛ„¿M–éXsí/Ƹï%Ø ¶ Ø)Ÿa)ÝDDDÊa6мHÙ)€,R~K»ü¶°/°–’aK,ØÝ©Ëe>VÉ1 î?çÔÓõ‘I´iXJ›Óݱ WÔhlðxK³L=–škW|7Ö¦ýäãFààz,Øÿ 6FÀ–>ÿVàOX€ï ÿ]Ú Ö¯“ç>†aƒ*Þì¯w?þaš¶æÇc/àðÐ2R| üÿUjSk?ßêƒÅŸ.ÁRówòïy0žÒ=~¡ÞÓ?;Ïø:Wøü>Ý "ïù X«TlÄ*® ü¥ÙèæÛþ[¯%z¬¹ö‡µcÜw{,åc7?×Þ´÷#, äËXå‰zÕŠˆH)|‹rôKQNF½¿…nObèû+•ùýPŽþä‰#GÿX¤eÀ»À@šæßkÑò¸ŸœŸf°¨Áóýš±Ÿh®ü2ìçT,ȳ Ðý'2ÿ ¬Õì2,Ð÷©€`¦ïjx¿uÀXšŸåX…å-4mÙ¬3«äXìe´V ßI¯ åÏ_¬ýå3ŸÌ9}ÒüŸö'•6+˜ß-4¿3Ö3¼Î¡¡u:cAâMÒ쯃ï7 =·;ðEdÛGŽgIèxVDŽI–c͵¿rëDÓ±S’ «ùV¹ú?¬§ÙmX…o~" ú½PŽþd¾/ÊÑ/èýHŒ1~í"ú/;µè‘–x Ø:òÜݑNj€c"Ï]Ÿf[ö[s÷ Ö¼OúNЫ*“a~ËGûÈëÄO$¯ó[&áãºU#‘™˜d˜ßˆ ø˜Ljì° }CèqwŸ†×™Z§»‡ÓUôðk¬±‘ïûÊȶ§DŽ'_Ñc͵¿r낵dL’Fÿ&aceáûGc½·VE­üEªÍXƒ ¨ŽJ½ ñÊŽ~ž[ªu¤8ç%"e×JE """Ò,ߨE~õJ<–дRFªËgÀYæ×Ñ´W/²‡1+´\`¬8¾n¦–a X°¸–Ç¿+ü^'²í#ÇX†¥ç ï–ãµçÚ_¹mF|½ ñ%ðGà»ÀŤzrí«¯“ˆ$ØÍ~kPQ$Ú*o•˜èƒ'"""Ò<cƒOÄÒê¬P‘$ÖR,‡¹T§q¬Þã'ê*,5ÖzØ@¶fYv–“ÿ_§p©ÔYó±Áw¯ÇRñ´v ­;“¤«?דÔXÁ¶‡kú¶/ í{ŠoÿÿÌž™ãuåÚ_¹mCÓÞI׈ ÕK¹v76ðrW}­D$ÎñÛT…ˆ¤£@¿ˆˆˆHó\îçR½T"±yÔ:“•جõXÏ›±À6±^ 3|½7«CóOÅ*÷¦`-+O Í„õ"í_ÆàS° ‡Ù~ìáJ‡åXg˜¯ÿF¯?×þÊiO,7q%z èëïËÛXkIŽ€üwnÖ»j”ÿžÖÄ*eûowô¿a$VÁ÷ëÐs÷øsç°Ÿ`¬¥³±±£–ú:Ñœö§`ér–`ãB½™:ð Ö›«¸ƒìƒ¸¦ê×À§¾iÀ^é~Ÿƒq¡ȰŒÇ"²»%RQ4˜§ÞßB·§Áxõý•Êü~h0Þä‰c0^)½-³ h[Æýi0ÞòÙ ¸§kÄÜVJ§ÖÊ´G¼–£±Jžëm]í÷Bƒñ&ó}©…ÁxOþIj,¥Oü½y<´Ìý¹™Àpÿ7†®s÷óûoúã¶ÀÿŸèYÀ~‚m.F`ôFšòûs+°1@î išÇ³}þT?Ö7üñó9®Ãþßøã¯±1G>óÇ÷§Ygºïg–?þc™¯+jÉ~Þ.úådLDDD¤VD/¤v¨uUõš†¥Ðê§¢ˆÕ¾X@lF¼–ÑÀØñ ö‹$Ã(,MÙ ¬UúGþü¡eŽñéyXO«ßD¶ñV1üؘ"b©ºþÂóÝOà¬Õþþx—мs}z>ð3àX/ÐÀ9>}×÷ |°yžerfèõžŽ¥} 2¯Yö|/“_GÊJDªHˆˆˆ”XЊjG¬ûr¹×»Ù§ Ex=Qu>]ë6}Öýz.–Rã2R)~CÓ­}>XëãOBÛªÓÇG$/w`A”—T±Dj€òjð!6Ë?°¹Ïê-‰Õpÿ‰êºô(šèÓ ‘eWa­Ý/ŽÂÒu¥ô)d?·|:ǧíBó‚A×_ =·"ÍüCÓlw#š¶þÏdCŸŽói}èü±gè¸Ò•ÉúúH•ŒÆ†’بE¿ˆˆˆÔ’bbö VqÜ£°VRß`ÁÇç±Ô"é ­Ãºv£à¾Hs<†Uny¾5n*‡ÞXNûǪìu~ˆ¥ïè­·Y$VÇûôÿ]?$Í2A¢-C¿MQ£|z,ðlP󿸟Àò,ó¦øô¡çÂÿG_ùô?÷ n›bã·ä#8ŸíãÓ­|¤ê ‹–ÉL}¤Jf 6ÎHUhÔ­êoÅþ¼(G²¾¿’¬÷C9ú¥qäèïui^†å)ý82ÇyA ÁÎ2ýµt³|S˶¨¥>ïÈóÓlãkýý¸çûsé^«rô·ÌÜŸbSŽþò€åA–òû–š¢ZýÄÿë:Ôøû¬ýÉ}_j!Gþ-¬÷д4çK¢iŽþ™Î©Þ =?¢û‰ž îf™ Gÿrà,‡þÄÐüóHåù¿ßç¿5É÷ôB<¸ øÂ?˜fhŽþëË|]QKþB*“èw¼¬JÑ¢¿N·ª¿‰ˆˆîÁZ=„¡“ê M[º?y¼_€ÝïR_c­¨†ç¹þÙX+Ë.~Ÿb]­G7ãu\ƒåFýk•z{ëü¸)t LóéC~ñx*Ö}z^šmŒ:'û­£_¨Iñ©uõ{X8\EQV?ÃÆ¿¨æJ–¿c•7ëí‰Í‰X/­€ß¦YæRàa¬ždp6œªgÊŠê< IDATT3ö“[ý¼t,VYxR%³õ&‘¥ýÉ{?Dß|©EòÄÑ¢®_\‰un´NóYN×¾Ëü;¿ØíËÍËsýÏýù§°@û_BËnžå{•®E0˜Ù>þxiŽïf¶žb]ÇÃó–ÓlcWR‰Nĺ`ïŠZô—ê7«œ¿©jÑ-IXê)½ïøçg³x­­ÿ{Õðû­ýÉ}_j¡E­k:?,G*1½Íw/E¿ãe§ý"""ÒçbAìǰÖO³€“ò\w8ðp¹oç(¾Sžë‡1ûM»ÈnTàëÈ6˜Z&;’¾ÇÛ?ýØúaƒ½÷í¥ Ž,Çz|Ço·“=ß«ˆd7¸8µ›Š£¤ºy9Ÿ‡µH­v+ýæ6 ­Þ~)£ï‘ì|ù Ô+"5H~i‰€À†X«øu±ÖùaAËôhú·|;Ë´~11 3¸¾‡oïUàZlhš£?l86ÆÀ2lŒi™G°T Ï¡`©¬ 4~7ðx ½î·×°Êe‘r9šÇw±àz/àà_Ç5XO µ|;·c­ð³ùMäxÎ ým << ¼<LO³¾“ý¿¦#6ÞÈúh‰Tµè‘À3À>‘ìþüXÅ Rí°ôjOb•k߆†æ‡[ºÿ1òx6 ø `1Ö3¬¥>ë÷ßõõßóÇ›ø:.NÎðÇ»ä±Î¬"¸NÃ*0z;I~?êQ¬à,àL¬’à1}¬Dª‹ý"ö{ˆˆˆQ¬¥ú,e@œÇ±$ås5–‚b…>*é5`{4è¢H9œ‹µä ?dpRžëÇÒm]îÛ9ÊŸÏ÷»»±OÅíg„æmTàëx˧s|Ú.uv$}ªÚú±õ.Æûö®I³åXïïøívNDªˆý""""R b]ô¥üVb)FVà±÷!ÿ |!Ë.vÖG¤b-^öQQˆ”ÜXËõ ±éëb­ô¼úÑ4hÇûô,…õ!ö‘iý¯|zMø:Š\ß÷÷*p-6ŽXþt†ciÇ–ac ˆH•QŽ~©+tî+ ·@EP‘þ‰¥ïxRE!RRSW°ô3Á·ó"ËÌÀȾKÓ\ö›cðݱ}ÓÉ´þ­Xº Ûýû¾ëͳ°NŒe2˜€åæ_ìÇð¯ ËÏÄ*‚ûL\¤Ê¨E¿ˆˆˆˆˆ”[w,Â,Ãé4M­³.–Oø[`66ŽP›æwÃÆ ¶Ÿ«Åõ™À¬çÇTRÁÖ¾Xú„3€É¾ì±™–퀵šœ¥i´Ïp +õ±¨H¯{©DJn °›ÿïì¿¿ÇD–ù­ÿÞîOÓ\ö'úÁ¾îo3ì#Óú7¿¾ÀÒþœà¿å7Ç\&7úÑÀ/ü?g$ésôÞö›ˆT!µj‘r» ¦tÃÌ¿X„µ6ìˆí/®Èsþ`®o¿#6hj&ݱ֚{ÿº½|Þ¾ÀǾÀºÀNXKÒX §†eGk›a)!òc¼Pªñ±¿¿kùgRDJãˆ<ÿ[îNóükÀÖi–Íw}€a~ËW]ŽÇï§y.×6¢ÎkÆqz R¸ydNŸ$RRjÑ/"""""åÔË|–j`6MìŒ xx8…Ç+pþß~04Ëñ,Ãro… Ìø-ðQ–åÿ |íë܆µ0M§ÖÚô<`>ÖÊ(©A ¥:¬>¾«¢¬b_( úEDDDD¤œºûô«ÐsSÒÌÿ2ôÜ$lÆB懷99ËñÌÅZŠëÇô*–Ã9“AÀD¬ÅÞ¿É<Ès¬õXßÇ\ày¬Ç€T—wÑ Ê"""3¥î)FŸîˆu+Õ:""ÅÖ—ÊO1ÑKµ1®Â_ÇÀ*}$¥ Ìòé†X>|€ÓÌïE*˜¿ 6Hb!ó7&ìï•㘞ñ[;,/óCÀ¦¡ó±ÀºXê†ý±Üì»`y£I³l–w¿«)Õåà{*‰“ý"åqsè‚OD¤R|üX»Â_Ç–À¤‚€•j2ªø•ê0ˆ÷jlÞ4­Pœ‡ݯÁZÏw.(pþPlpÂŽXš L6¶^ÂÒø,$U©6`w#¬µ;üßÚNtÙyÀhlÇó±ý=± Ôô1¨*c“T """'úEÊãˆT ÷©ŽÀòl Ì!zKEã`$–ëþK,×ý.¡ùÛ± ºåXÿêæÛŸíÛ¿Ø5ñ´Æ* ñûŸÇû¼Y~lc±û{×o3¿Ê¹ŸnÙAÀuÀxl°ÖiÀŸQ ¿ÚLÂä©YäîJ])¯#×üF,íØÀ,¿>ÅZŽMnÖL³Î` LîÈ2Ò¼÷Cßâ˜LÓÁ%~b­R¥©¤Zúоåò´ß’nÙó×·To?‡™K*xžÎü¼¨Öüüw¡—‘T¦:`I œ§©Ás¿þpN>$†ßþ%øÓy¬®+tí!µú;^4ŒW$ç×cé0îö às€;Ó,{1–v¾ÿa\©â‘ 1 ~vî =ߨÚïo \üµËçRlpÞÍ€¥ú¸T¬Fà l\‘X(Ð/3}z–›ö<€ÕsaŸœ†õ8FÅ'"""nàY¬%ûÀ{X°¿VµÇZ„KåR _DDDb¥ý"ñØÐ§ã|ZïÓ:l¶9¡e'út‚O×Wñ‰ˆˆH…{ å4—ê2 Ø\Å """qQ‹~‘xLõiŸnåÓF`zdÙ-}ÚÛ§3U|"""""‰2k°#""" úEâ1̧7w÷ÇÓ´5?X.ÿáÀŸBˈˆˆˆˆHrL6P1ˆˆˆH\è‰ÇuÀ…XPÿD,/ë­À©i– ô:aAþËT|"""""‰2•TzN©]+Ö*‰ƒrô‹”^ûÐýE>mÄ‚ý×eY¯.tÿV£ˆˆˆˆHbMC-úEZj 0£Â_Ã.ØX| +üutÓDZÙU úEJë{À™~ð¹ŠDDDDD¤êLG~‘–¸è¬]ᯣ0h¨ð×1² ^ƒHÍQ _¤´Ž&g+T$"""""Ug6ÐëÍ»DÅ!R°›ªäuâ¯å#½¥"RnÊÑ/RZ—û÷¬7ð‚ŠCDDDD2\—­R1T¼©ÀF*‰ë„RDDDDDDâÓ ˜¯b¨xÓ€ž*‰ƒý"RL~ÛAE!""""5FòŠˆˆHl”£_DŠéfŸjЩ5 ô‹ˆˆHlèI®¶Àò ;æsô¶‰ˆˆˆHRŽ~‰R÷ˆ”GÒæ×À`1ð°fšeÎê%¡yu¾î§À2¬µÐ‘õNÞ÷u¯GæŸ|âÛhæ÷>òù €# ˜MÝ<>xXêëlZ§=p°ïË뉈ˆˆˆT åè‘Ø(Ð/R^¿^Â[\™f™ßo…ž;¸X¸«(8¸3´Ì`à.`[à)¬"!|¡q60 ì߃U F‡–¹è<äë/ú0?“k€÷€/€ï·‡æ]‡ú_.ÑÇDDФ+0ø#p(0ø…ŠEDDJD©{DDD$6JÝ#R^¿Æä¯£€c°àØ¥XP?ìLŸžŒ¶ÇZîÀüs€s}™ó›Ò|ǃ´:ïbú÷€ï›Ÿí€À“ÀÇÀD¬7A ×üL.þ ì¼ìšwlèµÂz!Ü«ŠHUh ôÆ*7:Æp {a¾Ö.,ó1,Ã*&`½ªæë£!"R•¦¢@¿ˆˆˆÄD~‘òšèÓ >]?Í2cÒ<·¡OÇù´Þ§uX«ý9ÀÆþÜk¡õV„îóM³ý°@ÿ¹Xëû 7Á×X@l„?Î5?“·|:ǧíBózD^S½>&"­ ðSà'À÷Yþ½ž†U–ÛÛÀÖ~\¯a­üË­°#ViÛÛÿžÖožˆHU™†rô‹ˆˆHLè)¯-± wo<3Í2KÓ<7Økû°•?߈¥¢˜lüø_è;û¿6NÀrâ6&ûý°ô<‡a­ðo ÈÏ5?“lƒ O÷ ¢-"e#"•e3¬‡ÒÑÀ Xš±€¹ 8¶w±ŠÊ 9÷Ú8ø7V|-ð}„DD*ÞB¬×Ú¤¸ˆˆˆˆ”íbSDÊçz,…Äáþøá<׆‚nöõ÷ ­\DÜÜâûøð/·¥Ï¿ø–ÿ ¬eíöX¥Á:¾ÌT,OþtRêÎ G®ùÍñÖ+à`_àÇú˜ˆT”5±”c§ñ Ɇ„ãÃÀ³ 9–Ø8,obc’U˜NÎ"ÕãKDjKG,H,•/W~)+úEÊk(–º¡xº,Ïõ®ÃZˆåz¾ZæV,÷þYXÊŒÀ¡ù7øü3£|þx¬ò 0ØÍ/N–ÿ¥é¹æ7ÇåX‹þ#±JŒ?`+õqI¼mG±óÛ“êa”DóxL+Gü·{ Vir‡>Z"5§5MS.Jå òô¢¢‘rR _¤¼Æ`ùt² jÛˆû¯Ë±ý»ü–É0¿erDŽíçš_—ãñûižk…U^çúôK}\DíPÿ½ —æ[ ¢þ ôß8UxŠˆT"åé‘X(Ð/"që‹åò~hœæÏÿYE#’XGciÂÆ*ð¤8&{`½$ÄÆP°_D¤²LÃZô‹ˆˆˆ”U+ˆÄl6–èl°Ì©À`,}ˆ$ϾþýÜùKa!–~­=™{€‰ˆHr©{DDDDÊJ-úEÊ£NEÑ$`ƒHEØëóC4hl)-ŽžNF¨HDD*ÆWÀ*)7úEDD$uÀ}ÀÅÀG*Ž’[„¥Húð*–ÖGDD’ï+”£_DDDb @¿ˆˆˆäãd,xñ Š¢l¦ç·`½(DD$ù¦ @¿HÖ¶6Ö%¾x×d¬±Æ!1íÿ[àK`<ð™>"µE~É¥#p ðEÙý8è<£âI¼™@l¬•%*‘’Ú€¥ËÚ || ¬ˆé˜Æb±¶µcÚÿ¦À€­üþEà àI`©>2"ÕM~ÉepžQäíö>öó‘ðýlË•Bl`áö -ÿßaó*Ð/R½ÚËT Uã+`c”vM¤Zc-æ/ôßÎû€cý\±QÅÓÄúÀAXÏÜ¿·c=ET4"Õ©•Š@DDDrœ+œå·°VißWQˆT­5Å*†ª¡<ý"¥ñ}ଷãÀÖÀPlü(ùW7…¥ú?,¥ÑÇÀÙ¨á¯HÕ^¼‹ˆˆˆd²–çsR¼–6¼ßQÀ ú8ŠˆT„/±ý"R­+Gküüô*–‚|ü膥ôÙPÅ"R]è‘lþ–a^¬¥ù@,¨1Žu£¬ëeß³i~àût`6Ðá¡çÏÀ>[üøNäøNÁ**žóç»aipõÀ>¡m <z<Ñ?0Ø¡™ûíÜáå0Aþé‚þüDG‘Š¤î‘–ëàçf»ù9ØhI‹Ôûù¹ð›Ø8"R%è‘lö^Ê2¿5°/ÜÞÂ/À. Í¿X ôúbúKšq­±4=‘Àu¡y€®ÀàæÈz;a’ýÈŸÌÅþ{Ç…–ÅŸk… êÖØÝçmŽ jöa3÷;  q3,Ô¸"Ï×?øÆËPDD’M©{DŠc-¬åþXúå–/ŽFàØ8\Oc•("Rè‘LÚ[cs,w1°È/¾®øóC±ª‹°ÖøWÐ4°^ˆ?a•Û†žÿ7ð5°¸-ÍÅÊåÀR`I蘆`ù°°Ü®ÏùX…EÐ-|V‘ѬjÆ~;Ççùöø~*àõ¿쨥ˆHâ)uHqÎCÿ¼œéç€R\Ï?Åz¯n«â©||CDDD2é |–㪠h&=ü~wŸ†çO Í/ÄJ,Ý X€>œhV™°¾?nY/Üú+8¦)‘c{ØKÅó Öú¿Ö²ÿ•fî·‡Ÿw…+Mê ¼h­Ç*DD$Ù”ºG¤å®Æ“½@EQR¯gßãˆH…R‹~‘âiÔ-17)Žnäî"]ô =îåe`-ø‰ÌßKCS,ëb)qaiqöócÊ$8¦#Çú÷ôû¯`þ~¤ý…î· ê÷ÂRýtõõÖ)àµÎ"UQ!""É¥Ô="-³?p€Ÿgéú®ôžžÀÆÒ‘ ¦@¿HqÔé–¸›ˆ´\l Ù\®Âr¨®\ <èÏÏÃúºÆçw.(â1¶Ãòáã÷çX>8¦¡Àš~LE–y›`M,X38 î¿×‚ýŽnÀ‚ü`ã ìWÀk]€ "ÿ½û—£,?þ ¡$$Pˆ„PTŠ¢ EŠlX0‚ Q_5ˆ täEÀ‚(ˆ^Ë"6¦€¾ 4I‘’’Hzh9ÉïûÙ÷l–mçœm3ûý\×^çìÎìÌœ{Ÿ3sÏ3÷#u¶yÄ`ëà …Ôgkã}”¸‹S­ñMàuÀ®†BÊ.ý’$©’D‚ºšàV¢¬ÌcÀCDâ¿à"ÙñLšçâVìFy8“¨ßú½åVs$qQbp;½& ¦Iõ;ÒóEéoû3½¥vú³ÞÉD½þiDþ[mmf’ˆN öZÍË÷Hýs Q;þaCÑR=D Ÿó°ãœ”YÖè—$Iõ“ô(g.ð Ó¦‹L­r\R:m*qñ à8Ví•veÎÞYòÚ%ÏÇ—<}™åôu½ËÒ Ôgm2’JÔsaUÙ2›(ß3ÕPHu[ øïU>‰èŒ2¤ä÷jó5Ã$à%DZä¯éØýÀolŽRöØ£_’$I’¤Æš=ú¥¾úqÇã3†¢mÎŽ5 R6™è—$I’$©±fóÊÁÞ%UwpYþŽ!^ïÍÀV8 ¸”I&ú%IRMÅ2€’$•ó$&ʤ¾XØŽÞ1’ŠM–c?Í"JýZ4ÏhàZ`!1Ó¹8N=š(õ8Ø­èõO3¥ÀÝÀ«K¶ïHà bŒ€1ÀÄØOS½Š–u8p}Ñóiû fÛ÷s½Ã€ SæS¹ DÙžým’Rö˜è—$I’$©± 5ú%Õç-ÀíD¢¹œÁÀÞDr{ " ~|ÑôKˆeÇÛ úãû±ƒÓwwmóéEó>,&.Xìüø7q!cOâΆýXï0à à‹iùKÒz?܇¿ÿ¾ôyHÊo·—$I’$©±ŒWê›-_U™¾’(ÛS0—~›~O¢hz_ôån ôÅå&6HÏW/yßÜ¢çc‹öÅÛ\ì6âN†W§ßIþ]Òóþ¬w‘ë{¸èµAi¾z=Aï]/Ù4¥ì°G¿$I’$Iµè»®¡ê2xºÊôA¬z—ÌàÙôûœ¢× 6žiàö&JâL&Êâì“¶©’Â6mR²ÍÅ ‰þÝÓï·‰þ=éMô÷u½s‰¤þ¢ÔϨô¾õúð·öwŒµYJÙb¢_’$I’¤Æ›…å{¤z #›­æT`m`}ààÊôú"bÐÛ3Òô1À‰À ܾ¡D=üçÒ1a›NÖJÛt\É<·ô®E à}ð"¹ÿ÷¬÷jà"ÉqeŸ>þ½‹ul–R¶˜è—$IÕNFIjºz\Êž™˜è—êU«LLp+0•¨oÿ‘ø/8X“èÅ?¸8­Û÷4p&pð½åVs$qQb1Ðð•%Ó§5ôï(:ö~ ø3½¥vú³ÞÉD½þiDÂþV`Û>þ½Ë±Ü·”9~i%IR%K‰ä“:Ãðt2()ŸçeË CîÌ"ʇHjŒŸ¤G9sT˜6•ÞüWñïÕæ+<_³èùq¬Ú+ÿìËœ¼³äµ Jž/yþú2Ëéëz—ŸMI]Äý’$©’9X›³“l@o-ZIRç³t$Ijý’$©’À«ˆº j¿­ˆ[°%IÙ0{ôK’¤1Ñ/I’*y‰¨º¡è;÷IÊ {ôKQ­ÜŽ$)1Ñ/I’ªù°—ah» ‘Ä l’¤l0Ñ/I’ZÆD¿$Iªæ×Àû CÛ½¸Î0HR¦ü 5’$©ÙLôK’¤jn'z#nf(ÚêPàrà I™²‚Höob($IR³™è—$IÕ¬¾ |ÞP´Í.éç]†B’2Çò=’$©%LôK’¤Z.$JÇlh(ÚâÀ)†Aʵ՗ C.ÍÄD¿$Ijý’$©–eÀIÀ9†¢å–7 )×ÖNûZåÏ,`Sà ÕôŽgÑI†¤cPIb¢_’$Õã§ÀÀ!†¢e6".®c($)³,Ý#Õg)0Ì0tŒu€Å†AÊý’$åÇB`d“–½’öT`GCÝtk¿ ÊöÞ¸LIûó¼B$/þ üx‘Ôèo#jŸw’ÁÀ»€ëˆžÚŸ¦{:Š5²½lNûî¶k´=©œUkÃÏ êMÌ&—Ì’?[ã2Þ^Ƶ¬—õ¾÷*™^ís¥ó–k_}Yv¡ýŒNmhazÿ¹¼òn#€YDY‘Cm/’$凉~I’òÃD¿¤n´‘4\QfÚXà{D©–aDý曋¦_Œ6'r œ”¦íMÔ¡ž/³üÁÀÆÀxà2à¬:—}°{:ÛH¸î’¦½*­ïŒ}+ˆäõ¾n/ÉõDÂwbÐ^êü\éüåÚW_–]ê’´¼ñ©ï_ÒV÷&.lA\H:Þö¢~ZL ü*I’ôV#ÂKÊÞ÷c&p†SG9kÝ–s0p…aèz¯iáúnHN7%íϳìB`r…i£€‰ô¥I©aÄ æ½¶ ðxú½´Çt©Iéua°ÇˆžÒõ,¢×þŽÀGÒßð×´ÌÃë2úYü0Ãíe‘€Þ¤èµý€úÑfúÚ¾êi3¥íoyÉv7îOÜ)RÜV'”ü]3l/5í—cò)ÄÅ©Všƒÿy9ÞPgî7n0 îÇÛÁ¥$IÊ{ôKêFÛ½éËY|ñ~à«À]DÉ!ÀÃEó"zE׫‡(±ð<½¥PêYömÀ[€W§ß{ÉÝÛ2úYüøh†ÛËØôsvÑkÅÉ̾´™¾¶¯´ÇÂvÏ*zí V-‹³²dúLÚ_6' íE’¤Ì0Ñ/IR~,$nù—¤nò*à±*ÓoL¡À竀̀¹Du½=ñ‹­À6ÕZ6D2ÿÝD™–Ó‰DÿG‰Dÿ÷3úY<žþž¬¶—9éç&ô&û'ôñs­wÞ•ýh3ÔØî ô&ó7ž)šgPÉô À³¶õÓóÀZ†A’:‹5ú%IÊD™ …QÄ€„ÿM”0xø¤a‘rg¢^t9ïÖ Ê¢,¥·6û"àjàœ¢}çx¢†;DOýB þ¾ªµlˆDÿ^D²ìIàŽ´­£)?@dá‚sµö²ˆ¸(tzú\ÆÇõñs¥Ÿí«/Ë®´Ýgk§í>‘W–­;5M_8¸Òö¢~z‰öæ,I*Ãý’$åÇzoßDmà iOY¡=ˆÎ õˆ²­>žL'Ê,¶©J 5œ(]Vi?t"pMúýŸÀ!EÓ'èN# ÿÎ'ìCô¬˜è}ýà}Ø®jË&í– ~ˆdícôöì΢, ÐY­½I”ö™Gô~ÿ.ð†>|®  }õeÙ¥Ž êÝ?C\Ôº8­hzp+0•¸p5‘ø·½H’”ƒ Úl%q[é,C!eîû1“è vœUÇX0p-Ú—$ |x/°+‘ȘJ$+–´)&‡¦íúU›¾OC‰Þ“Óc:ð[bàä©6Û–y€(‹ò`‹ÖW„mÿËàSéÿM–ÿ_z^ãçÑmíekâÂÓ¶—¦* ªÙÉÇäSÒ£•wu#J?96Tû7Ô™ûOeà°›>Nß7Œ=ú%IÊÀsDR¹Õuw7¾ Hô<ü ‘`_Ðq¹ˆóà9öÚ x?ðG`p&ð;›¯$©¶ÅÎRjŸ¥D²_’ÔA¬Ñ/IR¾< lÐÂõ­EÔ2¾øQ¦çÃÀ¯éŒ$?DÏù·vȶ,O±šBô*¹ˆ¨Çü{¢·¿$Iµ|(Ós¼¡P›iì<*IÄD¿$Iùò$ý8²?¶#zËo ¼ŽØon‡ÆeQnSQþêuÀoˆ:Ý,Iªåtâî½k …Úh –Žb¢_’¤|™lÙ‚õìO”ž9•¨Cú´¡ï·åÀyÀnD=Ïó‰AC%I’:Õ"`„a¤Îa¢_’¤|™NóKÀ\¼¸Â7Ì "Ù¿9ÑÓßd¿4p©¿ŒØ$â›Ôß6Ò—ö&eÝb`à IÃD¿$Iùò(°E—¿7ðm`à†»á–ïÖ¾g8¤›ŒjÒ²'+‰ò…Ç_‹¦¿ž(ɵ”èùz?ðž’÷þoÉ2׿/ôs{–7a^µ¾½ùù( ,Ý#IÆD¿$IùòQ;¿6~¼“Hf¨9^JŸã‘†Cêh=D¢«ðØ9½>¸¸šHü® L&’øÅïU²Ï~?1¨º$u:ý’ÔaLôK’”/O/å_iðSàkÀƒ†¹é–%’¾NkÆ\òª´gôhàZ`!08Ròž#€YD/üIû¾Ú \D\¼ë!zûßQ2ßåÀÇ‹ž\VcÙŸfw <›^¿…(ùU¸»`bÜ™iÞ»WW™wpaŠË|àbâƒn36RÚÞjÅtð³4mpI•ÏGê4󉋘’¤1ÄH’”;w»7p™‡OµãÕO ¼ïwQH¸Kˆ i㉞¨7Ç'¥éƒ‰e“ˆ$í iú7ú¸žÙEûÌK{€9eæ» ¸ ˜Œ^ |©ÊúÆe½vþŒ&¤i{wu÷° ìH$¤/¾ìWaÞË5ˆ Å+«R\¾jéw¹ FL/N?7#.Ƽ¾Êg)ušgÒ~«S¬GÜ!õª´ïkW¾k&ÑYã]mZÿBâBä4¢¤§¤.b¢_’¤ü¹؃HÚ4Âp"‰ñfCÛrÿ8šHÌÝh8¤² å#–Ô˜o°?‘T]–'=¶O*šïkEÓOΣrâ}0«¾úuàûD/þ=ˆþ¹DâéÏÄEÓÍ?˜J nþ:¢ÔÏËUþ†—Òô­ˆ»«Rý.«?ýþ}à7æF” ÛŒ`àtâBE_ýë½?‹í¥‘m¤VLGïKmcaš~w—}w³Ð^TÙ\`L›·a'à`à­À†ÀÃÀcÀhß8¹¶vÝí°ðîôb8q‡Ð¯€ë€m¶R¾™è—$)~E$Ö¤:–šL$œŸéÃ{&½}¬Ñ¬åv²o=xMôKå-&†µýcÓÏYE¯=Áª=RW–LŸIõ«…:ûå<•~߀H_ìZ2ߥDùž×®ñ7,¾–w?‘4¾«Êþû+iý«W˜o\Ú¯>\ôÚ ô÷õÅHz“ÖYl/l#µb:6=ŸÙÅßÝ,´U6'í·Zm0Ñcþ«DÙ¬ŸMLJ+ýXV±ðvâ"ó€wŠÎ54R>Y£_’¤üy¸Ô±Ç ŸM'j¿½Òv5RY[Ô1_¡t΄¢×6eÕ‹˜ƒJ¦O 1ƒã> œl[fÚ/ˆÞ¨Ë€¿×±¬}‰ž´×å`à• ®ÑDé˜ÉDBuŸô÷•›w.‘€ž@\¸•Þ³^ÿÎÍilÙ¸V·—F¶‘Z1}6}ʼ·[’•Yh/ª¾OÛâuî ÜKÜíø`kâN™1É_éÏåD¡Óÿ…‡€c°ã¯”K&ú%IʧŸ£7©Ó_{=ŸÈy¼:ýdçràP›µTÖ#D²§–ED’ü `m"Q~"pEÉ|§¦éë'п±I6 Êö’¸£ˆqï-3ïR¢&û‡ëXîFD™Ÿ5ˆ>KiÚ|¢§ëÆéùÐôü¹ôû犖S:ï"¢lÐ9ôÞ¡0ž¸8ÐÛ²jö¬µ—F¶‘Z1]LÜw6QÆgðÆ ŸO^e¡½¨²'[ØFw«^›¾Ÿ{¿ó#è“ÇO{eÃnIÿS$刉~I’òéÎt@?y€Ëyðë*ÓG?#’ ˆA ‹MôøšM Y0 ¸˜—Þ{1Qj¨ÞåDÔbÔÇí›Dô’?’¸ˆqSz}t:‰\˜¶í\V½ð™ô·,ž"Ë­gÚ@ý?à½6k©¬Â¸$õ8"íkž!jãßœV4½¸5M{Œèùxj?¶é`{¢¤Î²´¬ÑÀaæ¿—8±–ÁDây.Qzæpà4mQ‡ÿá´¿Û83mÃ#ÀEË)wûôÿâ…´‹S¶íãß½;1 |–ÛK#ÛH­˜~"ý/š>Ó£ª|>y”…ö¢Ê¦[°žaÄÝKoLß…« ý€L%.8Þ˜öo;IR£Tº]URç?f=jÔ¹ÆIìݰŒû×V™þ‹ôI$Äß”^Ÿ”Úð©DbêTà/Eï»<¨­C v=ð­:—[\íèt’¹Ù¶ï|¢glá"ÃuÀωžšc¿Ñ;ÀâX¢çl¡„ÎHà5uLk”‡mlÖýö@>“jnHN7…ì×ßH”–ëÄ´5>Ø*«9Çe¸½ ”í-íe¿ “OaÕAÁ[iÍwm¢óÊùéxRõNàizï&Rãö7÷ãR7òË&e÷ûa¢?vþMôÌï«¡DOÔJ'V#ˆž›–™VH¤¯›žï@”1€è™õ2«Þ.¼ ½uzk-wy:©} F‚ žíS2ÿŠ’ïÝþÀŒôû("s8q¢Xµiò3b°9õ‰þòòè‡(A°W™×?XôVsí ü!ãíe loùk/&ú«»xs“–=4µ‘ÿöëÒTo&Êtng(ºß0Ñï~¼-,Ý#IR¾Ý ¼'$ݼúëöO$-ì©0}lZV¥$aQ2àùt‘œBoI‚Ào‰^ðõ,w5àKÀwXu€ÄþlßÜ’ùI';OÐ{1ap‘l’(ÿ°KÓe*•KIÝîBà“%¯} ø!p¼ái‰ÉÀEn/e{Ëo{Qeÿ¤ywžF &ûÃÜT>KÜÑ:ÜpH’ÂýRv¿öèÏ–!Ä\÷% ~ üq`'àUÄ ‚£ŠÞ³Ñë±’uˆdy¹vZ\b§ðü…ôûˆ4mÄ–»=‘äOƒ¶¯°]¥=ú÷£|ïÌ¡À—)?HqµiñIàG6å~³GyyéÑ?„¸¶…M½-&ã¬f{QÎÚ‹=ú«;¸¬ ËÝø°–_—–9/¾5r¿a~÷ãma~I’ºÃràÀëˆÁïî&j<’Hÿ!t?ž„Vµé—VYæbàWÀÙD’|õÕø\DÔç?‡Þ ã‰Áê]î?ÒAÛED}ÑFlß"b`²3ˆš°cˆA/¯HÓ7ÞAÔô9ÅfEÓe ö´’ªíãN&ŸUë•ö—+l/Êa{Qew¤ãÊFZƒ¸kó£Ä¡jo¦ó„] …”]&ú%Iê>O=ú¿ ¼x=Ñ«q QSPz\Ho]ýJ>A$LfepŽªs&=ü§ ù[mû¸Ü{‰ý—okÐöA Ìû ÑÛóâÖqˆ± NLËYBÔã?¤Ži’Zã*`4ð~CÑR".Ž^k{QŽÛ‹Ê{œèH±I—y QnòaÃÛR=D Ÿó¨¿Ì§$I«°t”Ý{òï`z{³ËÏ#ë,ÝS^^J÷lI\ÌÜÌ&߯NígsÛ‹rÚ^,ÝSÛ™ÀW´¬µ€Çè©åÊ16B³–ÛénÞåîjÀû K÷¸o {ôK’ÚiRú§»8¬IË!'üÅëžØÏºZï;(9³Ü¦))£f7þ†¸KIÍ3&Åù‹D¯^Û‹òÞ^TÞ%ÀÇiL/ðwy>cXÛæ<àXà e“‰~IR»õuÇ/3u›Îªƒæöç}å.ZO Ì+IYv p9QúÁämslüø ð Û‹º¨½è•¦Oc Ôa]pN0¤Ã·ïf`+`c›¶”=&ú%IÊæA¸$©²3‰Á¸ï .lªq&¥¸^C~³µ½Ø^40Çß&Æ_è¯uíR{)gð3`>q‡ê%%Óæã2íVôú0bÜ©yé½ã1ջ܂ƒˆ²B“ú¸}…Î5G¥ÂnJ¯&ƪX˜¶íÜ’óϤ¿e)q!åØ:§ Ô âî›ýmÖRö˜è—$uâ áò’ç/”L«t ?†¨+¹„Hu¯’eW;Яt^M­ôjÓ ë;˜E zû#`hcT“g‰Ú·»ŸOÏŸLÏKßw 1€ì’ôØÁ¦')gNKÛh\Y‰n6(ý¼8ø–íE]Ü^´ªwk\Zç±l9on'Íå\LÔðß X?7 &z 'î8«hÚÀHblˆM€±ÀIu.·àèôž½Ó9F¶oG¢§ü»Ók—w6¶Iç4ǧicï¦ó—mˆžöµ¦5Ê-éo•$©OŒWÊî÷£ƒñ–+S+Ñ¿850Ÿ ü¥hÞëˆÁJ×"’þfÕý—Wëå‚®/:ñ,,û|` VíéSiÛ®~Nô^ ü øFÓ ëûYš>¸§äÄ£ÒºK_™’ƒoÉýSŠžßYc•Öãà¯ÅÏc`Œ·¼¼ Æ[ÎvÀ½ÀŸ€íý*ôËNDüoä¿Ç»íÅöRÌÁxë·:pUúßן“§_¯0m‘ߴ±ëJ⎈Î+‹ÒïÀ—Šæß…Þq"j-wyŠïT ¸žíS2ÿŠ’vµ?1n)~/‡§ó–bÕ¦5ÊÀ¿Ü• h¿á`¼îÇ¥®ä—MÊî÷£‰þrò…æMJþ©¿Pç~¹ƒðjÛ[ë½ÖôIe>ãýЦW[w¹D!&¯MÏG=_Xc•Öcb¹³øy Œ‰þòº!Ñq'ó§‰;ÁnÞE\ Ue«§8Ý@ÜyvÝsG¸íÅöR|lf¢¿~ƒ‰>s/ŸÖãçD/õr^MåžþÕζHŸß‚¢ÇBà¹:—»"ý-GÖØö¾l_¥ù·—´½?¦í½=·Ô3­QŸã2úwF·3Ñï~¼m¬?,IÊš¢ìÀóE cÓÏÙEó'¯Æ¥ÿ{½6(-¯xÙsëÜŽÂúf½ö½½}jM'pÌ*ÙÞqŒÉKD/ŸEEÏ×°ÙHêr+€¥¾J úâ®§Gˆ ­KX5ÑÒ- wºM$’R»o%JT\ þŸØ^l/¶Õ:&ýRúîœH”¢ùpwúÎLOǬ‹ˆúòÏÓ›”<]a¹ÏÒ›¨›Õ‡í™›¶iBѱq_–»"µíߦe]נ훓~Ï¿)ðLÑ<7¦ÇP¢$çUDY ZÓõ9þ'ÏBt`9ƒ¸ ¶;Q2óZà.àÑtlUhWëÉÿrfŸMܵ:xcÛ±ˆ(Ûy½å„Æûôa¹ÿ z_¼³AÛ·(מAo Ïé½ss#àDg—S\VÔ1­‘Ó¼Ò@’¤œ²t”ÝïG³J÷¬ž~?’`Ný ÝëŸÒ[£ÿŽ’éW¤örú•JÙTÛÞëÓ2‹kì³Îé…’;—§éë§“ž“ëXwµ<¥1™T!~cÓú7®²žýÓßPÍ/Òcd:©ySÉßWi ‚¾&ú«¿PkYµÆfèï{[ÍÒ=céžòº¥t$õ‡¥{:çÿô(àJ¢\Í|â.›zŽåÖ¾Ot¦Y LŽéÇrßHtäyÛ·¯`L:†^Dôžÿn:"µ·¿Ð{çÃ߀7×1-ËÇMyÛoXºÇý¸Ô•ü²IÙý~4+ÑÑ |>QêæóÔŸÐKô*[JÜVÿ©>è÷'Ñ_í½Öôr=Þ/¢r-ÌF'ú¾—NFÐ;à`ñ<{·T‰G=Uƒ /‰þZã/T[V=c3ô÷½­öIâ®eã„ÕD¿$eŸ‰þüþŸ–ŸG3÷&úÝK]É/›”ÝïG#ý‰Úœ ˆ¸Ý¤ž ­v ‘ø_’žo o(Úf—ôó.C!I’$I*ÇD¿$IªåBà=Døz5{ ‚©Àš]ÿo§Ø %IRü ˜O”*º$½^(y0 XüZ2¢çÕÊ?Žn–¤ãÍOÍ_kYÃÒq󼴯佒Tý’$©–eÀIÀ9†¢åH'…7 I’”c/Ñ›œ/çb`-¢œäúD2¿`0°7‘<ߨ8¾ŸÛq1q!a °;ð±>¼÷`$°9° 06C7û½Í0„掷%© LôK’¤züØ8ÄP´ÌFÄÅ•c …$Iʹ¥D¯örFï¾,$Ðw—Ìó5¢sÊ\àdàà~lÃ`b€ãçÓ²N¯ó½Ã€ƒÒ6.&î8øp“ßÛ,ë¤m‘”!C $IªÃJb@Ø;‡û IS­ ü‚(Ûó˜á$I9÷40¾Â´±À `f•ãÔYEÏgãú± cÓÏÙ%˪Ç8"ÇöpÑkƒ€ž&¿·£96K)[ìÑ/I’ê58¸˜h8šfuà*âbÊe†C’$uéUŽ/Ÿ%’ù*LT2mBzDI Áô–Se ‰íMJ–EËšK$æ'ã Œ"Jñ¬×€÷¶ÚæÀSi›%eˆ‰~I’Ô·_nv2 7œ¸òð9Ã!I’ºÄ½UŽ-¿Î&Êë ÞX2ϩđë'W¦×g§÷¬|¦Ê6,"â=` p\ÑôjËZ\M”]•^ìÓ€÷¶ÚŽx÷®”I&ú%IR_] |2}Üp4Ì$à.à_D]ÙC"I’ºÄíÀnTÎS}‚¨Í?›èTÑ´àV`*Qòð!"ñð2p,1Øí´t¬UÍ‘ÄÅ‚yi›®,šVkY“‰ÎÓˆ¤þ­À¶ xo«íMtî‘$©OªÝ~'ùýèìïÇLà ?¦®¶ ð p 1p¬úguàËÄíâ7Móðš®ï†Ž6 IDATôètS¨¿þ°$u›ý2pL>X“xßìÕÇ÷L".4Ë$"ß-V#.¦lè×@û ƒûñv}%I’úãŸÀÎÀ#ÀýÀ™ôb¦Ú†#Ðov.5,’$©K]jÚjßtŒÿoC!e‰~I’4Ïß jy'n7¾ø °®áy…!À›‰³3‰Á?Mô4ù—á‘$I]ìj`¢>½ÚãXà<à e÷dS’$i fŸ%,ûQcþ‡D}Ó©D¯ EÀB`E‹·mCâ¢ÃÃmˆË:Äõ‰éñð‡t"û¨MG’$ ˆ$ç_¾Pç{¦ÒÜÜÖT`Í.‰ÿ.Àhà&›¢”M&ú%IR#-&ÊÏ\JÜ9¸%QÛtC`0’ÖßQ¸9°í¹y11`Ü߀ï·B/µ™H’$•u>p/1®Îƒ†£e§cÕc …”]&ú%IR³¬ JùLkóvL”Æ™âG"I’ÔÑ^$’ÍWo–’–8¸¸ÛPHÙe~I’$I’$uŠ[ˆò1ƒ GÓ½x/ðEC!e›‰~I’Ôm&+%Àa´MË;`ÝýXF­÷F”,Znó“$Iu8X8ËP4Õ›ïïû'¤Ì3Ñ/I’òn â6ðb=Ä ¹—žULF ð}å.Zìdx%IR–$ˆýQC^µ?ð?ÀÀ¿ ‡”}&ú%IRÞ­ ¼ÐAÛãI’$Iµ-ÞlügHb5àààÀ=†DÊÏ—[’$I0¸XÌÎ¥7)ÿU¢ÇS±ï·: #êÈÎæ ·‡û‘ÀDÍÙlK­é…õÌ=á†Ö±ÞâÞø…ßžf»ŸOÏŸLÏKßw ÑënIzì`Ó’$Iý´Œ(+sp/ð1¬Û?ÛöÞüÃHùa¢_’$)\B”ôlìF”œø9ð.`ô|0ðaàÊôü`$°9° 08©hÙƒ­€wp[ê™>Ø›HÀol_2½^ƒÓß³aZç5Àúéù)_7wozK# þnÓ’$IМ ¼8ø3Ñ]õÛ"»Ý \ì ü èy¹ò#€%ß¹ýEÏïM¿¿x4ý> xبhÞ]€Ç‹Ö·Se‹·©Ö¶Ôš>©Ìþc¿’¿¥ÒºK_ ¬›ž¿6=Qô|aeP#î­ôðš®ï†ôètSÒþ\’ôJûeà˜| ° ‹>“Õ€÷Óˆ4ÛcGÖrƇ¿'îÆ<‰àXÍßoÜ`Ü·ƒ5b%IRÞ ^ª1ÏØôsVÑkO°j-Ø+ƒ€ËƒéíÍ?.S=\4ï ¢÷YA0·Îí­µ-õlëÊ’é3é_]Û¢)†/¥€ Ï×°yI’¤ZA”/¼؉HöâÄ©Ddžçˆò˺(.Cˆ;O×%šµ€›7¦ã8I9ßH’$åÙZÀó5晓~N 7A¾)«ÞÒ|-ðm`câÖñ]Òës‰„øz“àQk[êÙÖA%Ó'=¹Zae‡¶ƒz.øH’¤ì¸7= ÜÛ[½Ö‡Ó{Wb7XNtÎx ø0=ý.©‹˜è—$IŠýD9ªÉD9ž+Šæ™KÔ5½„(ËóHÑ{¯Îþ‹¸}¾P;ÿæ&lK=Û p*1îÚÄmíW¶(–ó‰ÚþövŠz.øH’¤lšOÔîÿ³¡Ô­¬a&I’ŽÖ$zÆOîN+™çJbð²Ò¤ùdà¢Vìbâ‚À¶MÜ–ZÓ{Ò6L%zs=D$þ[að}¢”Ñ¢nn§÷®°™K’$I’ÔxÆ+e÷ûá`¼ÊŠ)%mu"ѳ{pHÿÞvz[Î)ÄÀ½KÚ¸ €‘-\ŸƒñJRö9¯¤þì7Œ×ýx[XºG’$åÝêÀËEϧe\Ô:'¤G; ¢sÇ$I’¤±t$IÊ»µe†¡«­‘‹ …$I’¤<2Ñ/I’”/Sñ®ÍRã§ ƒ$I’¤¼2Ñ/I’¤¼Ûø·a$I’”W&ú%I’”wöè—$I’”kÞÖ-I’ºáxg¹aèjöè—$IÀºÀžÀ[€m­€u€Q ^ÏÊ Äây`)0“(ÿyð'àŸ6“ìžøJ’$åÙ°t«îµðˆa$IêJƒ€wG{··7Ó€ÅÀ‚.ŒËZé\iS`° ðy ¸¸øÍ';LôK’$)ï¶®2 ’$I]ç½ÀiÀ2à;ÀADOvEžæ÷W¤×_L¦§CÔá¬Ñ/I’¤<[¸-û†B’$©kŒ®ξìL$²Mò×ö¿ÀQÀkÑıï2,ÏD¿$I’òì DQË7I’$u‡Ýû€û‰;;gHúå)àHà#À€oa.¹£ùáH’¤¼LÔ™TwÚø£a$Iê ï®N^2$v'°#qÑäJ`¨!éL&ú%IRÞ –†®õ!àZà I’”{o¾ ¼¸Åp4ÔsÄ€Æ=ÀeDg*uý’$IÊ«íÒχ …$IR®½¸„HF?`8šâ%âN‰µ3 Gç1Ñ/I’¤¼:†èÕ%I’¤üN””ù8ð áhªà ¢<æþ†£³˜è—$IRÞüÌPH’$åÚ7€_¿7-±Œ ÷ÛÀÃÑ9LôK’¤n8ÞYaºò„ï,àyC!I’”[ÛïN1-5(•t¢¡è¬_I’¤<[XlºÊ= …$IR®}“èàñb›Ö? XÞàå½Ð†õöÇ9ÀÀF6ÃÎ`¢_’$Iy²6Ñ»èpò#I’¤æÙ Øø•¡h‹—€ï_2ÁD¿$I’òb1Û/€» ‡$IR®\Jí2C UÓ\NÔëj(ÚÏD¿$I’òâ,"ÙÿMC!I’”{W•y½PÖæHà à¦ôú0¢´ã<`>p1°fÑû>Ì–OÇMü,½oqi±£9éý»½^kc€%ÀT`¯2GñóJe}j­§YþܼտØ~&ú%IRÞ V†ÜÆg»¦¾C"I’”k[ÉñÙ¦v$Êû¼;½v0ØØ œ”¦%ÊÐH$Í·n.ZÞÅÀZÀfÀúÀJÖµ10¸Œè|Bë,,w‘ðßøX?ãQk=Íô;àí6II+ †AÊä÷c&p†“2àVíU£|YƒèQu;1ðr§¸!=:Ý”´?—$½Ò~8&ŸB$ ¥n3™èÁ^ΤôÝSôÚ0àeV8vàñôû(b@ßÃËSŽ :’lZe]ë¦ç;‹ê\ç¢ìÐ&%ûŠ–]©Gñ´Zëi¶ˆ^ýîÇÛÌU’$IʪM€ÿ%z=oH$I’ºÂÖÀ#U¦÷s‹ž#ò ½6ˆÞ;A_Îî¾ ÜEôŽDåÎ=D¹ÒñèÐ:×96ý,¾+¡?0j­§Ù¦[•cVØ4ÛÇÒ=’$IʢÀ{k€ƒ1É/I’ÔM^<Ö‡ùç‰ï DïýQD©›õŠæ¹Ø—¸àzzëÿ?Kÿz…×Zçœô³¸Gñ:^"Ê.ŒÀßÖLˈ»ÆÙ,ÛËD¿$I’²dà·Äàho¾mH$I’ºÎH`aæ_\ œC$Â!jêï“~ßxQòeb@ÞBïôÅÀ¯ˆ1¡F½çߨ€u."..œNÔÿWôþÙiݤíúL?×Ó ŠÖ­61Ñ/I’¤, œÜüØ™¸¥Z’$IÝg«Ö¯¯Çd¢Æý4"~+°mš68‘è¿„¨ÕHÑ{?‘Ö7;ÍsTÖ p$1¸ï = lQaZ£Îæ‰ü ô^Ð+­M\tyÆP´—‰~I’”%ÍJòü8ŒÞdÿÎÄÀ\¿§|¢tP;2=F¥Ÿ#ÊüÅ+÷Cˆmÿ“Å¿Ï!³}®hÚ¼ôúJ›‚$I’ºØTà ¦Í'jçoL ®Û_‹€«s€ÿ"z¬¶nö#ø?[3€†¢½LôK’¤¬hv’¿àwÀñÀ­Dž5·ÖeÕäýjé`a:ð_˜‹Š~>LO'óY5©o{I’$©ïn¾TaÚàûDÉ•éÜ¡¿&ƒóN#z®ÿ8ýÅöHŸ‡ÚÌD¿$IÊŠ»ï§ù=Úï^Hó³oÉüâ$¾ÕJ’$I­7 X‹(«3«ÌôÏ¥GÁÏÓÏ©¬šJtì©ô|ðÙô(Uº¬nõVàÃÐ~«I’”getF7y]u?÷Ië[üø_¢wþ³˜ä—$I’Úé*à ÃÐVë;w?«Í¼ê$I’²ä¸ôóDÏ‘ÿ4agïHËŸÜF”ì‘$I’Ô9.®þë÷ËaÄ—— EûÙ£_’$eÍqDý?Ðøžý¥Iþ‚ù†]’$Iê(3€€жXø41X±:€‰~I’”EÍHöWJòK’$IêL'ßÖ0-÷Eà—ÄÅê&ú%IRV52Ùo’_’$IÊž©DùžoŠ–Úø8p’¡è&ú%IR–’ý¤ÿÉ~“ü’$IRv ¼x»¡h‰µ«c%†£s˜è—$IYwð[ú—ì7É/I’$eÛ2àÃÀO€×ަL ¾{ðÃÑYLôK’¤<èO²ß$¿$I’”‡ èí GS .ÇŽÎc¢_’$åE_’ý&ù%I’¤|¹ø ÑÓÜ2>5:Åu0p°Òtý’$)OêIö›ä—$I’òéàƒÀEÀiD/t Ì^À½À_ƒ€— Ig2Ñ/I’ò¦Z²ß$¿$I’”ov¶ö3$ý2(Õs p4ð5ìÉßÑLôK’¤<*—ì7É/I’$u‡¹ÀÀ±DÏþ{‰þà MMo~ Ü̶KçVêpC $IÊ©ãÒÏ?Þ€I~I’$©›ü¸ x08—èñÿ'bßéÀB`~ÆfmâÂǦÄÝoÞ¼ü˜0Á°H’$I’òfˆ!$I ´°°° ðj`0¼C¶of ×µX Ìînž²™H’$I’ÉD¿$I¨5C€ÃÍ€?w—ÿ"’ÝKÚ´m“€?¦mx°¨…ëN\䨨x+ð-àÑ›Ÿ/Ú|$I’$Ie¢_’$ ä8âÓÀà¯ÀÉD’¿§ƒ¶q*pðwZ›ä‡¸¸±x–¸ðq0x;p4ppp!°Üæ$I’$IÈ º$IR_½Žè•>—H\?ØÁÛz(ð|‡lKð›ôx-p.ð‰´Ù¬$I’$Iýá`¼’$©¯~œM”£y°Ã·w)°¢·ëb<ƒï7å$I’$Iê3{ôK’¤¾ø:ðQb°Ý†£!.î~ L ÊùH’$I’T7ý’$©^S€÷»ó GCMMq½‰(ïs¦!‘$I’$ÕËD¿$IªÇÀAÀ¾˜äo–¹À;ÛGk ‰$I’$©&ú%IR-o{Éh5O!Ùp‘ð—$I’$©*ã•$IÕ .>Ì4-ñðàBC!I’$Iª‡‰~I’TÍÇ€§ë EKýX|ÄPH’$I’j1Ñ/I’*|øZ‹Ö7 X>€éy38K-J’$I’j0Ñ/I’*9øð˜¡h‹ÀýÀ …$I’$©ý’$©’O?6 mõãô9H’$I’T‘‰~I’TÎFÀÀí¦#‹Ì.ÖLÓ %vŽæ³ÝŠÞû)b`ߥÀÝÀ«K–}0 XüÚmÈ‹?[ãl’’$I’¤JLôK’¤rö!’Ì+*L¿ llŒN*š>Ø\œU4m°#0 ˜|§ä}{ ¶¶Žïç6äÁ à`_›¤$I’$IêT+ †AÊä÷c&p†Sn]L®0mð2Ñë¿`àñôû¤Ô~×MÏw zç—³3Ñ#¿ø}Åí~?âÂ@aúò:·!OŽ~h“̜ңÓMIûséÿ³wo¡–ÕÇ¿“cuPòÚTC^2K K#ˆ¬ÐzIz((º2å‹BæKQÒÅL|Š"ÓŠ Cí%¢)Da”w1•J3#/3Šãô°öà™9ûŒ3gŽžù;Ÿ,8묽×Þç·ÖÞìó[kÿ°Ø|&?¯zÔ¦ö}|Ŭµ½€9ÞÔt&þCܺàwkª- æ·4 §Sõ¿¶~gcunuäl~ÿ˶6 Û³ÍýͶfWžÃ‹ÅmÕ'í’,EÑÌsLõ·%–=ÜT¨ohé3õ—rhÓ;ï«n¨N©n\°|Íl½ÛÊþ ÕC+üFsoÓðD0—1ú€yÖU›–XöxuEuqÓ8û5Åú.¬÷¥MãðÿwöóÙsnóÕê€ê°ê‹Õå+üFóXÓµ`.E?0ÏAÕæ,ßX=QÝÙt@àúêÄ]XïƒÕÕªÛ«¿ì°|Ël]w4}£à–¦â%ŸÃh65xØ+¹/Œûúp1Þÿþ‡íÁò¹/Àø\ŒÀûø0œÑSôÀÀý00E? LÑì©ãs8X5Š~`wP=½`þ®ê±ÀêPô£X+XLÑì®ëªýªÍ³éã={†ÿ¶³ýϪªî¯ÞY}n6ÿÙü6V—Tÿ©©.«^¾ÃºÎ¬î«®=,¦èv×iÕ–ê ÙtóË÷«^[­¯~X]Y6›¿´ºpÁm¿[\=»ÏÕWvX×Ûª7T=,¦èæÙÜTâ/×EM~Y½ºúÖ‚ù7Ïns`Ó·Ω6ÍóëÕGwX×—«'«'öÑm±n–Ìe¬[`žMMóæeÜwKÓ0Pí'šÚ–ÓÕMà ]^½£ºC4,×ZËôLõê²êSÕš.${muSu{uwµ¹Ú´æ³®:¨:¾i þS«÷7•ú?ª>\=e7`O)ú€=õduélZ_V½«úDõú¦²{Ý>˜Ë¦¦ƒw5•û×TŸ¯´Ë°’ýÀJz i¬yãÍÀ Äý00E? LÑSôÀÀý00E? LÑSôÀÀý00E? LÑSôÀÀý00E? LÑSôÀÀý00E? LÑSôÀÀý00E? LÑSôÀÀý00E? LÑSôÀÀý00E? LÑSôÀÀý00E? LÑSôÀÀý00E? LÑSôÀÀý00E? LÑSôÀÀý0°µ"`/°Á¾°<ÊUVÛ#Õ¯ÅK¾>ž;£ègµ½R0´U§ˆ`‘“ª?ô?Á16À"G ò<_Q}ÏæXdþôÇ*úX®›ª#Ä0ןgÓÖW÷ØdCúWõ×êdQÌõ§ê©}á]c[À>ëuÕqbØ©›ª'ÄUñNÑÕIDATüŸ=8òmUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU•öà€@Ðÿ×íT€‡+»‰®ÙòIEND®B`‚libreswan-3.32/docs/klips-using-kernel-crypto/klips-fsm.svg000066400000000000000000001223231365625662500240710ustar00rootroot00000000000000 image/svg+xml KLIPS job queue(one per cpu) klips_rcv_fsm klips_xmit_fsm allocateprocessing job init job's FSM data enqueue job dequeue job new packet job setup job processing advance jobstate in FSM [job present] [nothing to do] poll hardware check crosscpu queue [over loop limit] [under loop limit] disabletimer enabletimer advacing job state in FSM verify statein fsm lookup statein job FSM set newjob FSM state [good] [bad] delete jobobject background processing timerfires dequeue job advance jobstate in FSM [job present] [nothing to do] poll hardware check crosscpu queue rescheduletimer jobprocessing call FSM stateprocedure [bad next state] [good state] libreswan-3.32/docs/klips-using-kernel-crypto/rcv-flow.png000066400000000000000000002472601365625662500237200ustar00rootroot00000000000000‰PNG  IHDRú¼å!€sRGB®ÎébKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEØ † €õ IDATxÚìÝy¸U™øño‚d! $ 7²ˆ€$$€".€8(:(þFEFT@”QDqQ%ƒ¨#눂 ÊbTv‚¬ Q6!$$!¿?ÞÓO×­tWUßÛ÷¦ïíïçyú¹]]Õ§N®:·û=§ÎI’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$I’$©ŒfÇs)0ÝUê·ÿ®ì°<fùÑHêƒ[Uƒ$I’$i¸=ÌŽgð{à&?Z©Ïަt`¾¦óýx$õÁL`Q‡æm¤>xp­Å I’¤šÑÃð˜.æùÑJ}öÁÏßl`±“¤ f· |~¸ÍKREWY’$IÊmHb–K,IL"ùœ=s%I’$Iý0Ò"èHÛOZ \ ì“Yþ8p¢Å"I’$I’$IÁ@gú 0Éb`'`KzO ûMà0`²Å#õ‰ ‰kÛx¦Còb㦬“ÔIuR§±Ž”$I’š0ЯÔß¡¡~˜{m9ðKà@‹Wê;—›²N’¬#%I’¤>1Ðß™¶žË=?X,ÎÆd¶?xXüøpÅu〳¿cžŸ¼ ³~h_Bô¶ûnÅ|<\Q’αÀE¹4NNOÏßüºÁ~®öõ4‘†½n›GÆÆMÉ:IÖ‘’$I’€…À»†ÁqäýkÒ›±ÀTàê·)Ož^™–'³*¬8ø1Yáxàà¿2ë/N‰éÇí+*ä{ ð `}êÍÒ™ ¬¤>Yâ(à¡´~JJ«ÑDНþæéÞu×QO:'züˆÚZ¿ô§!q  ¯*I§¬±°™©ÀeD€hp½‡ÉèÏq‘®¡ÀõÀÖ-”õƒÀ. ò{õ†S ¿zc °»u’uRÖIÍl\,Myú*õFZºMŸÕîóZvœÖ‘Ö’$Iê"Ã9П Rì ÜùÁôà}¬/Z7xØ,óÚnÀýéù†Àj"ßJ¾×¤¬TLçZà ô|oàÞô|«”Öˆï™E4¨»®#ýW¿ô¥!:»±°ÈÏ€ó Ò1ÿŽÞAµþ×ëˆ Øz)Ë*–µ›Ý[oè·NêÄ:©,¿¤÷MþœK÷¤tü'¿¯˜×¢ã´Ž´Þ$IR—®þçsëwžÊ,ï ü‚èYõ"`_¶®H2óX <‘ÖoÝ`¿­ä›Šé|z/¬ïŸó]×\GãÙÀk€7§}~€èÙèq ú¢~ékCb§76³aª“6Ïó3p\/'z¦V)k7Æ`ú[­×ŽÅ€uRgÖIeù;ïM™÷ÕÒ­™?—¸[ ,¯eÇiÙ›~I’$­Å±F‡†éÕ¢Làâ‘ÌúËÒc ðÀ/*Y÷Xú±Õ“ù–õHæà¢~ä½, /3€·Roˆx‚¸%à¹÷lÜìi1äŒLÁ€·{÷·ç/#¯– NÍ‚ ˜`AöÚ\LOÏŸö>|-]wÇ×¥mF·çêªÕéù´´¼°Åü¬NõÓ™@ô}WZ.2-ý}0wÌ5ý=®÷6IËëU,ë%éïxz7äB4ŸôT–õš¬“:µN*Ëoö}äÞ·:S§=M}8 ¢¼–§u¤$I’Ôe†óÐ=ç·Hoœ~Ð~6­ß ؇¸¥|ÑCþ¾ ë nÿÑC`S`¯Ìú‹€ÿ!¬£][È7-¤s1îíŸs¯Ÿ |´AzçGyº©ëhà6b|àC©7DµÂ¡{®~É–é{¼o p Ð!]ÏÏѼfõÆÄ¾ä­j:S‰@Ò "г]É>õž}#õÞ³ý9®Ò{_›êÜ—eÒ­RÖ‹¤ëý}7õF;ê5°g®uRçÖIEùmv'@¾Ì¶Íì³(¯eÇii½!I’¤.3\ýùÉÒ¾M½wT1öé2b¢µ?ÿTaDÃÁD¯û§€»è@ŸDôD[Jô¤:·?ˆ«¤óîôƒå˜Üë;ʽ6žïvЧû¹Ž¶I?Îû›¦þ©_úÚßXØÌ%À¨‡ý[z‡Ý×ãÚ4•çìTfç±vP­YYƒ›a êvÕk`ÀÎ:©s뤢üžOï±ý?Ӥ̶ÍKQÙ•§u¤õ†$I’ºÈp ôWù‘Ù-~œ~Ô×SñG¨:ç:ºžÖ¢¿ ô·¿NéOC"t~ca3Óˆ@Ü àNàz¢ús\§¤tïަwP­¨¬ÁÆÍ0PõF»ê50`gÔ¹uR3S‰ u—§S¨,Ð_”ײ㴎´Þ$IR1Ð/uÖuô:¢Wc;è·~醲¶q³½¢Þhg½쬓,ëVXGZoH’$© 'ãU«z€;š¬ÛžþMÜ«áçbhIÕìŸ[>Õ"±^“d)I’$•it¼tVƒÌ"â6éFƒüÊÛ¸ÚbPF°¼É£gíCÖk²N®u’u¨$I’4Ù£_Ò@OLî÷€EѱÖECb­±p¨ïc(”µ¬×¬“¬“úRÖ˜_I’$I%ìÑ/i lÜo1H²^“$I’$i`è—4P&K,IÖk’$I’$ ,ý’ʆÀ2‹A’õš$I’$IË@¿¤b@L’õš$I’$IƒÀ@¿¤2Xj1H²^“$I’$i`è—4Pìù*ÉzM’$I’¤A` _Ò@¬±$Y¯I’$I’4° ôK’$I’$I’4„è—$I’$I’$i3Ð/I’$I’$IÒ6Ú"$Iêx¯³¤®0xÒb$IR«º5Ð? ãǯ.t?ðÄ0?Æ1é—4üÝ ¬ê’c½Ê[ê ¯®µ$I’Ôªn ô_ ôøñ« ÌæÇ8è 'iø› ,ê¢ã5( ok,I’$õU7Ýsp‘§€ºÈ-]v¼³Å~ìÒ°4£ ë4I’$I’šêæ@ÿ `‰§€ºÈó]v¼K½Æ¥ak‚E I’$IRÝH‹@’$IèA`§AØÏ§€othtrÞ$I’$uýkàI‹A9ûd–?œh±¨Cm ªƒóÖÌÆÀ&ÀëàÜhußë2¯ƒý9K’$Iýf _UŒ¶Úæpà‡¹×–¿´xäµÑËj`|îñS` pð#¢¡a2ð~zÏÉP{ïàjàÛ\¾ØxŒzƒC+¬´.H4T<<ì—Y? ¸<ßO rSÒºC€«€sÒ{?JÜísÑ· øy&­÷p×Ó›äi6pp:ð(ð7`ïÜ6ÍÒ*ÊïHàs™4ß l ÜV!ÝFÇšW´ïÃÓºo49¦*yËjµœ·&†C™òÿxª×N¾–yï ¢udÅó£J¾ší»Yy5Û¾ê9´!Ñà»qæµíSÞ'¶ùœ–$I’4ïjãvý•íÉY{~0°(ýH8‹XÕ™~Ô¬þš~ÈTY78ø;è:xAfý$"€¶„fã»ó}ћtŽ.Ê¥qZúq^¤Ù1ýÞ=yçG¤Ïmp}úØlÛ²ò(:æ¤Ø»W,ã÷—d¶½¸0³ü 0'ó|—û?¸b˜]ǧ´1ÿ=é³îiÓvÝ®êy[tm4ªãªÖKyùk£èn-Óg¼~…ºân§šl»Q:î¥)¯_¥LjV6òéTžÿ \Zá8ò=ú«.ÖU}Ðîz”¿ÝÛ¸]_|!}/Ù—¬þ¿Öl¼–èÙ<¸8>­;=]_ÿœ–ÇóÓÿøQiy×´î“iÝÌôúw€ï5ÉÓYDuÏ´|ÑF…´Šòû¢ño"àû;"h\%ÝFÇšW´ïoO{49¦²¼åõ¥œ$I³.Kÿjönláü¨š¯Fû.*¯FÛ·r-^Yþ õÆ™vÓ Ãú@’$Iêè_CÊÇS¨É< xxeZžHܶ^¶à¼ôChуõà¿2ë/N‰Dëò½†èq¶>õà\³tf½ª&¤åQÀC%û):¦F±×¹õÒñ^V°mYyóI)ÿ'¿¯˜æ–DÃÇHb<á…ƲµuKÒº)iìÿ•%?š‡âõa ¿³U=o‹®¢@+×a£k£(пÑ0p1ðæTŸ4«{G_¤wÐ*ëgÀ©^žF ósBI]ØÈ=À»‰^ŸÏº¢ãhèŒz`¸0Ðß^—U5SÓþÆ5Ùþ³ÀÉéù¯3×LÍ#ÀQô„O#ë·É¼¶pk“}\GïóÿJ=(ÞjZµüN%¸32ë>üoÅtk™lY]KÌÇÑè˜ÊòÖH_Êùì”nÖ_3ËŸ$è}=?å«Ù¾‹Ê+¿}«ŸûåÄ]ù…4o îË9= ôK’$IÉPôgƒ û½h!zËÿƒèQ•­G•6Ëýè¹?=ßÂbf‹ù^“~ÈQ1kƒÒó½{KöQtLeãèyÛhÛ²ò(;æÚøØs‰ÞkUÓ|è5üÎôÃôÆ”æûˆ@"Dï±5ÀˆûŸE4– §ëÃ@ç«rÞ]Íý­^‡®Ú~ŸÌ=^œÖoAôø½‡h4ü-õ;}òïý1 HÞ†é½ÙsåM™z¹Q]ØÈîDÐ~bZ¾øHÉq,cí@ÿ`ÔÃ…þöZDŒ_óbzßsPªjwô­Þ›Ö-!†DÉÚ“`?Nô¶žêˆìu°”ªæHûq浩ß)X–V³ü¾3ÕY_$†Ë©’n£cÍk¶ï)­íšSYÞéK9ß¼1“Æ´´}¶!óGÀ‡Z8?ªä«Ñ¾Ëέüö­œCµò;-=ÿ%½ïZhÇ9= ôK’$©Ï£p­I?–jRWôI`bÔÅÀoˆÀXÙºéDÕÛ3?z®¤pš–~\.l1¯«‰qK©˜Î¼ô "H<¯$ý¢cjäýDðmð š÷"++²c®ñý4õ^[UÒü5q ø«Óó_¯Il€¢wsÞ„”®4˜ªœ·E×mº›]«‰FÁ죄¿Ÿè©¹5°iªGÎkòÞ¢ñd–µ;²õòôï9_6òb¼æ¥iùÒkEÇñrëuˆIÀæ™óàmÔ‡‘Ú—’ê0âκ‰a¼n"ÿ×äҼ؋jï@ [8¸ '{LLõMÞéï=™×æ¦}R’VQ~7É]c£·fꇢt›kVѾ_”öwW“c*Ë[#­–óÈ´ÝM™4¶Oõê3™ýî‘ÙoÙùQ5_ö]T^¶o傘Û`{â®Ðé™ÿí:§%I’¤Žb p w¯ÂâVàšËÒ‘©Ä0ÿ]aÝcD©'÷£§ÖÓèÚÓ›±, ‰€áŒôÃt^…4›ÓšÜvgÁþ‰é‡Öˆ&Û–•G_TI³0}UzþkÖ˜>AÜ¿Mƒ}lGô–S•óv ®™¬¢k£jýôEz÷8­âÑL]\3x¸…46ÞNôö|8=ŽvLVXh]˜•®×ÓÿÖ=ˆ9s>“Ö¿”RêŽt‡¸Þ‘Îñ[‰;cjö£¨Ÿ@Ü9sg:·÷ ‚ÛÃeíCã»Üf§t³ÿãçf®¢´Šò{Ñ z›tí~™h,¼µBºŽ5¯hß³¼?{LeyËëK9o«sßMÇþÄ+S©úËΪùj´ï¢òj´}+çÔý'ãï¯nó9-I’$uýƒï¤ôÃdcàSÔ⛥+ëC^¬ÈüÈ(Z·Œ¸Åú+D0 ¢wë^éùSÄäc_J?LFÓ· ÄÊÒyŒè ü]¢§mÙ ¢cZBŒ^§vLZ~"=ÏÞNžß¶¬<ú¢Jš¿N?>7 zÿ6ßFÀŸ3Û]Nãžg¯ÁI85øªž·qÍä5»6Ù„B¥ ŸDLØýÇ>äó2"°U›;åÓÀù-¤ñ"x´=1yñ"`ÿ[êÙUe= uaV:çwKÿë¿NÜ™wGZÿÃô¿÷‰t~Þ›Ö­"‚¢7åÒÛ¸ž†êÀé:ûUª.Këî&z†¯i’§l£×ÆDìÛÒrQZEù½"}—¹%å»Ö“ýî é6:Ö¼¢}Ïν?Ley£ å¼øVz­6'˵iŸ ˆ;¯–¥uK*žUóÕhßEåÕhûVÎ!RZÓSýÓŠŸS+ç´$I’¤Ôécô?GÜê»(ýú6õ!0zˆ .—¥7 †›([ :ƒèÕúq[øQ™õ“ˆ…¥é‡Û¹-ä›Òywú±uL…²);¦¯§ý½wÊ0»>£h(;o‹®¢Éx[½ó×Fmlûå¹Ç‰˜w¬LÁš‹‰á%Šê°F¦¦÷.#Æ^>¶¡j:W=oóÞNôîßj“ñV=0\8FûœI}N ÉócÝrŒ~I’$)é´@V+' o?&zM×|v^úÕßk£› V=0\èoŸk»øº“çG§1Ð/I’¤>mHƒnÿÜò©‰ÔðÚè&ÖZWv x‚Yy~x~H’$IC€þîÕCóñU·'† ûÊù‘$i]›dÈóC’$Iú ôžVÞ‹ˆ1¡‡ú>†r~$I’$I’$©ß ôK’$ »/°$I’$IyÝèߨÙS@]dŒE°Vy̲¤Žt+°ÊbXËW-I’$IR#Ýè?)=$u§éÀ|‹AêH3qÞ”¼$I’$©™n ôÏFúñ« ­°Ö‹-©#Ìn±$I’$IjM·ú—úÑKÊÔK,©#L°$I’$Ij½Ú%I’$I’$I ôK’s6üx 8×â$I’$IC‰~IR»,æÑ}ÜF s°¥$I’$IJ ôK’Úac`àŽ6¦9j÷ùZàB?FI’$I’4è—$åm\,KŸgÖ}¸X \C y³5ð`úŸòxz4šìý@àWÀi›G€ý2ëIû='­ÿ(08X¬~L.Øg³í›CLȼp p+pðµÌ63RZµÿ™‡—ßþìK÷ýDÄò”—=*”­$I’$IRŸè—$åÍ~JÈ7>•^ÿ$ðoDÐzp/ðààhà"`<°ð\ƒtg;WSS33ëw^üOJã4àdà éõ€5Àç öÙlûfV»ûñ)s›sùºx>—Ï‹€iÀYÀq™í? ü¿”æ?#Ee+I’$I’Ôg£»ô¸g½8¥ns?ð„Å ›ÃæŒ"á7í㉠øÂ´Ý9ÀÙéùŽÀMêÞ/—¥åïÁþqDùÓúÿKë7þè½ÿHzíBàƒMöùÂ’í›™CïÀþàÓ™å[2˳‰ŽkÒòÀ«Óó©À ÀÎÀÝéµ%e+I’$I’Ô/Ýè¿èñãW:èQ,9€êŸ@ góQ`/`}àÆÌv#¨Úç=Õ‹Ì>žYžD m³"-ÏŽÈ¬ß ˜O=h1Yîß›ì³lûf²þiĸÿ·gÖï\›9æYÄÐ<5;d¶1üÏÝ-”­oªbE u…WeþçH’$I•îâc?ŒvAê·Xªèêô˜FŒE0ð,p1ðŽÛ$‚ÝE=ú'½Ù—f^{1ŒÀL`=z÷~ŸL½ f?¢±¶Ñ>‹¶/²#ðƒô|{"HÿLæÿäÀ7Óò‹ÒkweÞ?—zƒÃ4àÉËöKžrªè#Àmƒ4l]eH’$©¯º9пXâ) .ò¼E  ö#…î'zÃoÜ™êÌÚÐ=ÆÃÕü°Az¬.HwVZ ðEàµÄľ{¦õ;=á³çé|àD`+`1&ÿLàÜ&û,ھȎi[ˆûcÓÿÇÕÀ)Äp<µ†²Ù ò97í—´î³)Í›-‰¡â”­TÕ|ìé+I’$Ij`´E IÊØ“w1ÎW©©ÿ•ô|ÑPz9p%Ñð-¢'ü2`Fƒtgçß><¼‹ßñÿ{àËÀˆü/RþV¦õù}–mßÈtâN€Ú×ÁøÄdÃ׋©7 ÏÎåsã”F­—õÕ©œ®"&â]H4n”•­$I’$I’’…Dà¨]Ûõ×6á ·-õ!8Öµ‹}2Ë§Þ x8^ǽ¡Û¥‡£ºg·S{œI ;" åë¼Ýõ)»·q;µöy.!æ gq´ôÝê¹Lw]ϲ>$IÒ:5Ò"P!z¾ª?ôêå`Ú‰ÂãÊÌkß$折ìG®.0 ‡©‘Ôþï}µ!pð âî›­ß³$I’¤¡Ì@¿jÆi`ü0÷Úrà—Ô‡õ†³è=Ñî`êI×[£‡wtHÝù]dzú{W‡•Á&~‡ó{–$I’ÔúV¶×YíùÁÄ$‘Ë€³ˆIkŽ$z•ý•˜¨²f1¶ó߉ÛÌÏ^Y?)ýÀYB ôÝŠy;„+ûŠ’tŽ.Ê¥qpz…}|x4[ö6ã#ˆabV×[§×¯FQÄÝ™[ž[°Ï©Ä˜×ˉ â¹õý)Çfù­òÙ¾øuƒü^ì륢.0)Õ5ëÂ"¢Çn£Ç"?iÀ¿5ûÿØì»ÈFÀ…ÀÒôÿú«ÔƒÙW7øNP´}#³ˆIÅkéüœÆw>SñûLÑw‡¢ïvÜü/ð`½uø®ÊwËfåÑ®ï¬÷¥ã-+K¿gI’$©ëè\£ˆÉ·¶æÇ§uÓ€¯ïH?¶'z!Õœ L¶6OÛgÇ=Øx19äYó³ðàÍ%é\~DMȼ÷íÀ¼ û˜l |øbfÝÝiÿ“ˆaŽNK¯ï ¬¦ˆÛ.·üç‚ý“~4N^ü[n}ʱY~Ë>Û)© õ¼“˜„T’¤nûîÓì»ÈwÓÿýMÓ÷¡Ý3ïÙ³Áw‚¢í¹Ø9“Îë+G³ï3;;”}·kds"p,1øWˆ†‰uñ®è;QQy´ã;ëÒ{ö$:n•¥ß³$I’$¼Õw]ø$°2=> | 8X<›~°ÝJôJ»5½gÑ«éEÀS鵓Ó´c‰qfßBŒMº4­¿¾b~>ü#=/Jg!ð'à­Àyé‡×ÊŠûùrú1}1pTæõ_džŸ\ÞϲÝx0x:=NNûmG9–å·Ùg[vyƒSôÝ¡è»]3OßJ—ïIß7!&—½z¾ÃUùnÙ¨<Úñõ8à]À«‡+”¥ß³$I’$ ô¶5ô&ba&¨ñ$°?ð‘ôøæôƒèº´ÍhàöÌ{G¤W½œF¤ôZ±x,³\–μôãí¼ôl^Å},IÏŸ¦÷p6ïO?ZkãÑ®×Ïò–þ>˜+ãšþ–cQ~‹>ÛÚñÏüè­™>{­;—Z’*šH=8©þ÷iö]„Ü{ y#P«Û÷U³ï3EßоÛAïÀôøï_˜Þ3Ø-s¬ƒñ®,½fåÑßïZ#Áþ‡+–¥ß³$I’$ ô¶Äĵ£=D­šËÒc ðÀ=¢K?zˆñmóI?¤{èßxÓeé\HôÞšAô Û­ûÚˆ¸µûuĘª»¿ÍòA‚*M7§ìÏN´ÙŸr,ÊoÙgû1–ì6Àsén—~¬jð-&n÷—Ôy ¦wÏwŸfÿ˳ï™I=軦Åí«ZE G3&=¯z§WÙw§fßí qp1ôÐAÀÛ€ùÄÐDo¥>gÀ`|‡ëëwËþ~g}ظ2¥õ³ eé÷,I’$iZHôRj×vý•ŸŒw Ñ“j,1&éuÄ-ì›ûë§y$& «9øõÛ7öʬ¿øâ–èÑÀ®-äÈ£ð¯ IDATÒ¹¸Šâqò›í#;±Ý¦©/³nZZ7£Ér‘K€c¿N%‚ñÏ´¡‹ò[öÙBLJ÷Ñù=Þà §ëã8à”6æ¿'hÇv’†®uUœ’ê¶vZCï‰Lû»]')ûÿØì»È%éÿõØô¿üb˜šfß Š¶¯úe="0ýÎôþÖžŒ·Ñ÷™¢ïeßí¹˜èø‚ï=ƒñ®(½²òèëw­lº;o¨X–ð=Ëú@’$I딓ñ®ÕÀ¯ˆIÅînNJëFŸ&z/-Þ¼;óÞ÷§Qw·%ÿ xifý¡éÇу)Ãû˜Ç²tæ½Úçõ³,¾~ðß Ü’Y÷(1þíÄíÖ/Ì-Ï)H÷Hø;ð›ùìk9å·ì³…˜h.?1ðx¢×Ú½4$I]øÝ§™ƒ½òûÏ7ùŽ0§dûªž>LܽwõáuúóÝ©ì»]#=Ó?OÜy¶.¿Ãõõ»e;¾³þøb¢ß×W(K¿gI’$IÃL§õèÏjÖûJC_ÕÏöÇDo´šcèÝë¸]öè—4PìÑ?¼þ?Jí°®¿gYH’$irŒ~iðìŸ[>Õ"‘¤!e"ý› G’ß³$I’¤áÐ=Ã[q{s£GÏÚǺܟ$Iò{å#I’$©£Ù£ð,X彈Ÿt¨ïc]î¯S?[IÒà›@Œ9®¡ñÿ±¿3tËG’$IFìÑ/I’TÍFÀãƒ$I’$©Óts/ä-€=ÔEÆXk•Ç,‹AêH·«:0_Ó‡;´Ì¶&&•Ôynα$I’4º9ÐRzHêNÓùƒÔ‘fÒy“ÞŽ ‚éwwpvpv's€›¼\Ôáö$†H2Ð/I’¤Õ­þÙ8l‘ºÓ ‹ a}°Øb: à–ÍÛ‹€¿•v²Ã»è|ùpœ—:Üù$I’C·ú—úÑKÊÔK,©#Lèà¼í\éGÔQ¬»%I’$)±W»$IR¹wX e²E I’$IÁ@¿$u–5é1Ç¢¨lN¦ÜÔw‡¤2<:-¿.-ŸnÑðbràßXÅý’$I’”è—¤ÎrZz¬ÎJ¯ý¸8ئ‹ËfGbÍzštœvöèßxÒ"mh[à¹N¯]é^L ÑUóqàD?~I’$ ú%©³|8=þ:Dó¿žát ° p)ðTæõ ˆù|ŽêÒïHG ï!=ÔYÚÙ£ÿ/À$‹´kílIïy8¾ †CDI’$iýˆ•$uŽüÐ=µå¨§ó 2ïÙ—B®V7oË¥ûàŽ´ÍcÀÙÀÄÜ6‡7Ϥt~×B~¤÷VIóû™ãªù.½‡ŽifƒTO§}¾ºÉvý=æ½SY>Eô}8ظÁñ}>ÍŒHï»'åñoÀWsï­¥ð'à)O³ZüìÊÊb¿ô÷×¹÷ý:·¾l |¸—wà*«¦~ Ü Ü{}r:ǷȽ~:ðí’4'wqYª½~˜{m9ðK¢!T’$IÒ [¼Ëb:â::8¥ùê!‚A=ƒ¼Ý`kè˜RåÑ´|jæ=ÏÁó³ëOeÖ•Þó×”Æui9ÛsñCéµç€ S:÷µß§ÓþT1ͽҺÒòzDïÜçˆ@k‘SÓ{IÇó0kÑߎc~ðsàÌô¸#mqƒã/ú|š9&mû8ð-àÞ´üÃé¯ †Y–×ÂqT)‹Zî‘Ëã”L¦Âù?X×ù¢Áf6ðV¢qéà®Tç» â5¿{¶ÛΞ§â߉ÉÕÀ¸Ìë{i#rÛ_CÜQQäØ6æ/;ìKíùÁÀ"`YºvÆd¶?x0]›%îĪ—®Ã¿§zíà™õ“Òu¾„.è»óvðõ†§fé \”Kã4ÊçÛ8"}X‘þlÛÿR÷`Ås¶YþÊÒëkùå‡î9 Õ…ÛVøÌvip ‡WôóÜ:?=³>$IRêÖA³r?Ö¤nq?ð„Å0$}Œ\Kô*?€“ê³åÀψ^ÈwÓ;hV fü‰ÈÿxðÏÄP÷=˜!ž_ëÃÿˆO_ʽV”æ5D`ååDOÞí‰àÍÿ•ìë€ô÷£¹2¡ÍÇ|ј°+ÑûýV`;¢§+ŸO3GfŽãûÄXð7 m¢÷°$¾AE¯¦w@ªì8ª”Å”´ÍS¹<.Ë<ŸBÁÃq¹}çmØ`» Qéz¨’k§kb,àŸ’Ê÷oD˽DãÉwf GïOçJѸôÞtN¾¼ OÜÅñ®ô¿b›tÞíšÒ¸x}æ¼:*•ñ éœov~LN î ¹ Øz#ßêhY/Ž/9¦ìÑ? Ø“#†µ:>Ç4àëD õ÷éø²Ig맺m ðßÄX﵆‰sÒßAç]*æg'à%™ú½Y:¤|NH×ô(àíD£V‘»Ó>–¥´O#î«íÑ{"ðEà•%égQzí(¿¤ºuO¢q¤è3›’òrWƒtîLu³$I’¤AVµ'òBê=}øè¦Ç»ÚxU ÔÙ£¿uÍzô¿<-ïš–ŸÍ¼ç}ôîÕþw¢bͳçÄ«sÛìÒÇüîÚ`]Yš'§õÇRÊç€ û|®I™¬ió1Ÿ]-|>Í<›{ïú™ô¶Ï¥ÿ²´<§àXw)ÙOQYìÐ$b­÷Áô¬qéšÛ,óÚnDC;DƒÔêLùWÍÛštîR1kƒÒ󽉯¬V¼<ý/Éî¿Ö°2—↸²ü¥×Ÿò«}†Ç·äꬢÏl«”Ÿ ÒœELRÞöè—$IÒ èæ1>cíÛš¥áì‹`H{1p#ÑÃ"0[s>1tÁ ·=p¿B=x¶˜èùxðƒÌûf ;½ë·þ‰àÕþG#}FÛ•ìc£´×ô—QŸ\=¿ÿmY{âõV޳(½þ”_-Ý9Dÿ_š¤‘ÿÌ Dwn°­côK’$Iëˆ~©s®ý}Ó,Ðÿ!¢îÓÄxÅc3ïù1ØŽb຀#ˆñûW¥mþLôòÍ:”ÞãDPø÷}È/-¦yd&×T,£±© ž&ÚG³vð»Ǽ;Ñûx1ÜÈÁ4ô}>ÍŒ zÏÞG;"&Ë[P¾sškY9—•ÅX¢Áä)êÃ¥@Ü ôïšúû¾]³@ÿи7<Äp4IçÕH¢'õâ×ó4⮈£Sz?ªxlµ<-%¯§çµÔ;Ó{ˆžš Óÿ2_hãçÐ(Ðõy®>›ÖoìC4TŒ>Hï °Ï'ï&¥åM‰ Èk."å6Le¾k y£…t® îÐøs…ãß4óìt\çÑ¿@QþÊÒëkùeÓÝ9Õio¨ø™M4ŠæGÌEÑú%I’¤>0Ð?0$&g(Ÿ"†Y×ùh5?^Å ô·GY ]~>írh:–¥å×¥å¯b ô÷}»fþ=‰àzmBÑ-‰€(DCÓ¯ˆΓ‰^û«Òò~ÄPc˜ÿ…hx-qçÊÜ´n,@Ío>‚¸SàLb8–Úc×Ìgr(1ÉuÞ)Í2Ù£ÿ9¢qo1¬Ø·©/ÓC4¦-#Öþ@ E¦LΠÞxv½ƒÅ“ˆ»gjç¶7ZHçÝ©¬©X§¤ã¹hÔéo ¿YþÊÒëkùåÓÝ5«¯¯ð™íL4èf'`§ôóÜ2Ð/I’¤A1Ú"’o¦Z­þšLŒû}çîã¥ôz]壕üHÝäkM^ÿð0Ûg·ÇwÒ£æ4žœRCËÕÄœW˅ļC9½…Æé6¢çÿD°O¢—ó"àúUêw|%=ŸDZ/®Ìí÷@b¬÷c¨µõàíl¢ì¹÷M%æ¸)-ï \š^[Ùà»A»,hð½ø\á¯,Hk%1/Á¿7Yÿ$­5¨/hò½,Ð{^Ž2ŸHš/5ÙÿàÒk–¿²ôúZ~ùtksJÔ}f¤ÞÀT;— xž°‘$I’_7ôèߘâaý>¾T‹Û¿šú$}ýÕlß·» b>ÊTÉO;Êv¸_öèoNè1¾¦Éc¸ís >Ÿ¡rÂý}ßn÷.<·Ž t›õ —úÂý’$I#-‚޵ ÑûnYzüØš¾f$11ÞãDÏ¥éÇîBâväŸQïåvHJ眴}müÑ·f¯$z¯Oo’ÙÄäs§·?ÿ Ø;³~Ñ“ï1blê+©ßâÜhß#ÏeÒzg:®ÛJÊ£,EÇT”Ç*ùi–n³²•ÚiDzÜÔyÈ?†Û>âó*Ç! E“‡Ñ±ôw>4zôtè>#Ï’$I’*2Ðß¹æ?M?b7&Æ¿‡3õ"âöûˆg'“½"½¶†^CŒÉû bÒ²€Ó€OÿìAÜv/Í'´›ì’ò2 8‹ÞäM¾H¿7&·:7Û÷§‰1QgÛX>DÜÆ_¤,EÇT”Dzü¥Ûèø$IÒàX2@é6*g -Jßí=uè>#Ï’$I’*2Ðß¹6'†‚EŒ•{Cz}Gz÷}!1†é;ˆõ3À…Ô'­Ý‘cõÿÒò$àxbh–…)ísˆIÈ™ |žãbìÞ¬{‰‰üVc˜^Œk²ï‰Ä$cô.%ÆÝ½µByåcZÉ15ËãÔ’ü”¥›?¾Už¶CÒ¬ô™úðácÝ?fY%µÅ±]ò÷ ]v¼þš··J’$IÒ`p2ÞÎud>¸„æ bèŸf¶Û ˜Oªk&OÏgSï½^Û~}àÆÌk͆ì@ÂkvnÏ,D44¼8m?8¬`ß·“ ×LN¯)ËGÙ15ËcY~ÊÒÍŸ†¦K-IÃÌä.ùÛmÇëß¡ùwŒU’$I’Ãp'x!ð bØ›vl× jãË_|…÷tkb­ûà•Äe¶nNï¯Mð÷3¢¡á\`_à«ÀÛ‰àøHà”—%Möýúô>ˆ†¦;‰áq.ìG>ŠŽ©(¯)ÉOQº3Ÿ×GoÇwq|¢MùïIy›IñU·™ò'©ó,-©[Û]¬Kk€W×ös»ÝßÒ]s@|ÞÃøI¨6ïƒXH’$© Ù£¿3íG¥ï'zçoH 7HÕ™mç'[AŒ£‰€Æ¹Àëˆah²Á’›‰;æ&z·¿š~fM.³Óû³¯ÏMûx)Ñàp0ý*Ñ0q°Oƒ}ß|–˜høÁô}kʇî)ËGÑ1åq³’ü¥»cƒãÓÐò<7¾³$iàY‡K’$IRâýiOàz`%ð à à2`ð-ànêÃÍüø2ðàQblþ=Ó{óãùCŒUÿ•”ÞÊ”ÖÛX;È1VòÍ™å‰ moKË?$nG~¸‚ ÿb¬úFû¾ø шqSÚ÷3éo‘²|SQËòS”n£ã“$Iƒgr?ß¿ ð¤ÅØ1¶žëÀt/&:°Ô|œzgI’$Id!1qj»¶“¼>úî8à”6濇hdéiÓv’†®áT¬!†Ýéïv»Ó¸Ñ~8;ÖKaXéÄ@ÿNÄ]Y㇨ÞÐt>õá{«>$IR²G¿$I’Úm2Œ\ž{|8³Í¡Ä0x+€eÀïˆaõòï_ <ÆÚs¾Lî¢òt¸ÍuãpâîЬåÀ/©6æ¾$I’4h ô«Sô4ÔöÌ–$ih™C ›7>÷øZZ$1¯Ð{Óë›gQwÜOÌ‘s(p2°Efý£?ÛÓ»öü`bΣe)?c2ÛIÌé³ø+½-ÆgOù:xAfý$"`¼„.è»óvð1Ü`Q:ÇåÒ8 8½d?eùnvÌUÊ«™²²ø1åƒôîµÞ®2>¸/CÙçúFà× Ò¸Ø×Ë\’$IÄ@¿:Å¢Á€Úc‘Å#IRŸ¼Ÿ˜›f914ÛéõiÀåD0ýiàJ`JZ· p¼]ü<“Þ‡‰ éJ"Ø9½É~ç¤ý6ó>à›À‰žûKóRºµ÷ÿ!³ýïÒß±™×ÚÝ£1ÏѶÀV)ÇgÊëëÀ;ˆ€óöD¯îš3‰DCÄæiûì8îç/"æ:«b~v^¼¹$ ˆ ô„Ì{ßÌ+ÙGQ¾Ë޹¨¼Š•Å(`°)ð}à‹m.ã¤÷ì ,(9Æ))/w5HçNb¾&I’$IÄ1ú¥Î¹>£_Ò@qŒþµ5£ÿcÄÄñÛ§åm™éùVÀk‰Àêà:êAÚùD/çQDí]ÓëŸLëf¦×¿|¯I~Σ8˜ýsbØž%‚²ÞBz>)¥u;ÑIe_àžô¦?ò=úóçʾÀÝ™<üƒh ˜Kgð,õa‡vîOÏ7VgʾjÞÖS3¯•¥s-pPz¾7poÉ>Êò]tÌeåÕLÑ1ÔÒ¬5àÌ%šú[ƵÏù8àz7NãV)?#¤9‹z£TÇè—$IÒ èæñ>·vöPÓeÇ;‹ÞIÃÇt‹ ÔT"P¾3õàë‚Ìú{©‚Ÿ zðKË›AþQÀ*à¢çóñDðuaÚîb(•Fæ[=¥kÎ>šž¿—sÿËD¯éŸïɼâ‚§«ž.K/´¹ÌÖÐû.Â…™síÉ”ŸÃÝL —s]Úf4ÑQ3‚<“ÊnD¦ÜªZMÜqAÅtæÃÒœG4ØÏ«på»è˜ËÊ«™²cXM}H¦§3ß]ú[Æ#‰†¯ã€‡3¯c-ã§réMHï•$I’4@Z鱼Ƈ.|tS~>| ÿ‡=úëò=ú >ÜM#7RÏ||‡Öä—ÀãDý))½çÒ¶µÇR_¾>Ñûz—ŠePk<ørîý3JÞwl?˾¬Gÿ‰;òÆÇcçCô&.ýmdîécÞª¦3•ŽÏHŸÏv%û(ËwÑ1·R^U!ÌÛÏ´¡ŒkéÎ!‚üÿRñÓ¸cÐ!ÔçM(c~I’$ ŠníÑ?ç'PwZÑǸ˜ú8Ó’†·¥ASÓhÞãx_à?‰1ÜoI߉ †ùè=5õqü&ïÓ»‡~3;È[+æõÏé1.óþ©>/2yÊí$b÷±À§¨÷ŠßŒ¸Sì¢QdqwÄð2?¾BL0ü$1Æ|m¼÷§€Ÿ_"&^Ioh1oeé<üŠ˜„ö~bù"eù.:æ²òêë1ô5¯UÒ½)û—§óùŠ Çx9ðb.‰¬×P=Ð/I’$©{_êœëh]õè—¤¡To Tþ=‰†Ú„¡[=›>N„ÇÁòïAÎ1À~Äð†c”ÿ…޾x”è}ØÝ‡Æã—Jî›9xÑÀ°>qwÁSÔç8”â»jÚÝ£ÿ9¢QcXþ6õ¡cz€ß§×WÿS&­±ÀÄÐCO¸•Y?‰‚/%î¢8·…¼ÑB:ïNçÁ1Ë (ßEÇ\V^EšCQþþ”q>Ý]Ó¹üú ŸëÎÀŸrùz†Ð>:aŸ’$IR×mH’$iZÒÆ´¬ƒïÅ‹ˆñÞ‡â>ŠÊk0ŽK’$IRŽ=ú%I’4M¶$I’$)Ø£_’$iøx]ëF]v¼š¦[ ’$IhÝ蟌ñãWºxb˜ã˜tKþnVY ½\ÕeÇ{¨¹†€y$I’Z·ú/ÅÉÀÔì‚›Óù~ÔRW˜IŒ.¸a1H’$IRwêæ¡{.òP¹¥ËŽw6°Ø]–fta&I’$IRSÝè_,ñPy¾ËŽw©×¸4lM°$I’$IªiH’$I’$I’4tèï ÛOZ mµ-ðÜ îïb`ŸÌòÇý4DŒ[§åéÀo€§€s;8Ÿ’$I’$IÂ@§ø 0Éb²v¶®Ì¼öMbˆÉ†€5Ĥ¦÷¤åãÛˆáQÄ|,æ¶Ï*&gÞ—]^¬>‘Ù~prÚÇràaà`OI’$I’Ô© ô«U£-‚µü0÷Úrà—À† ×ò>7&‚éw´9Ý9Ä\ 3Ëã±À¡D` ¢Áõ·ÄoHÛìBÜ´¹§…$I’$IêTm;öDïÙљ營!Oÿ |X•¶?8˜B ùs*ðµ´nðU``ðã´ý3iý$à `_bŒŸï«·ÃOw{¤s,ð2àÿeÒ8-msT…ã¯-ß¼ ³îßÏÿ®mñx6¾¼xøp À+ÛGY™¾øvƒ}^“Êá Oqu¸C€7o'‚à—÷³rÛì—Öýkº†Þ\•ÙæÃézŸÜ®§‡/C•½%mw*qĠ€?ϧkpÖ~«–Ï·¤t¾ìšÖ]Ÿ®ï¼9©>É.ÿ!³ü»ôw,ðiàQàD¯ˆ» OÏGÃr}h˜øe:ö%)ooîKOùÜøHª«ÞO½åÀ´|[*ŸçR½ÿ¿žŽ*°°©Å I’$IÊ3Ðß™F{èqÀ¥ÄP'Ó€¯»¿&=™÷ž ¬OôN]C4œHà!† x°‚è­Z%?;/!]Eé\ò9ß{ôzk?ËcÜ8‘¾²Åãù.1LǦD/ÝËR™žXaEe:%½ï®û¼ØÑÓYCÀŽÀÍDcânD#Õ&Û¾‚Ò™®÷ã¨ú?I4ŠíOÜE°x7ÑP¹¦IZ'§òyÜÿð9¢‘pÇTÿœ”ÊåBàŠT—lI4f|’z VªWO%E>šêýjæ¾tIÞ×ù3ƒ$I’C3¼«Û –ìıÛA¦lð~_¢'=D`êD¯õ ¹tƽÕ7˼¶Ñó¢—îjêcUWÍÛ`jæµ²t®JÏ÷îmáøkËÏäö_ë~.°¬B>²in<Ÿ+Ó7eÊ´heeºUzïˆy˜E4.tëõqpJóßÓàÚèÏvªû5œ'}ö?/ØöZ¢W{Í¿=Û!"W½í³×Ë­™åÏ·¤ó,;ÎÙô+¿,Ÿò1%ï¹…àg——ú¿ÃnÍHuꢂt^H4^f@þhp­åíè̺Ï´5{åÊá2ₚ©é¼çéØuõÁ¢ÁK’¬7$I’ÔgŽÑß¹_Þ³§…ÄCõìO û°ø H#m3¸=m÷$1AìÄ´~^Øb~VÃyP1yÄPAÃyý,ÕDPài꽪Ç3-ýÍ–é™2-ÚGY™ÖÞ3¾Á~'¤í¥N7›zOù9™çy#ˆ¬K2¯í®ˆ`öúDùìõòDfû?§4><˜y½h¿òy1„ÐCÀ÷ˆ»kòÖ¶£Þ£¿¶¼-Ѱ÷B"X¿˜¸›§(¹!Ô IDATп0Ÿh`È^ãÏä-Øiny{â.ŸšYÀÅ™åIDÄ OGI’$I’Ô*ýi½{öÐ;¸tð:¢è%ÄP2ÁøÕiûIé1‘zìÚÓ³±, ‰Éü•Þ=˜k¶£1¤Ì bXˆáf~|…$AôRÝ+=Š˜¬öKÄp6£©OdÙŠ²t~EŒŸ}?½{±6ò`Jsÿt\G¶)dÊå2b™±DC§ó+죬L.§ÈÌz îÔùv$†³Y“YnèŸM ?ó|æµ¹™ío&Ææ¯—?6ÕW#RÝu ðb2ÛYDƒ À鱺b>÷#æÌ€èU¿a“zf.1Ùís™åÛ›¤ÿâΜϤ|C4à–êáùÀ?Ãu­GÜ‘087å-[.¦u·äò_+§YéXLe³1ñg<%I’$IR_èïL«‰@ù¢÷êmDà¢çû§‰`úrb\éìøÓï'Æ·¿‹„ÿŠB¢æP"èõ`Jãð>æ±,yÄ]U†íy–r™ò}]óQs0ð¢ÿàbÎ*ÊÊô,bø¬ñÄü?ôtV‡«Ð!†ªšœ®‘F²½Ò!àÓSEº6¾B4¬­$æÁxŒ¿<­ûYZwjæ\|+m¿¸B>÷®Oéü8#í3/ß«~N&¯yO¤t_A ´<åu1<Ïï/ îÚ)m¿2å-ß{ÿêstäïX˜E44î–ꔯÜÝáé(I’$I’4t'ãÍÊOL«¡áÇDÏåšcˆÉ8»ùúp2^©±3X Ö‰“jJ²Þ$IR¿¶¤¶Ø?·|ªE"©‰YÀÿZ ’$I’$©]ºG=—7yô ¡}HÒP°͇G’$I’$Ij™=ú;Ï‚uð¹,"Æ”êû¤¡`’E I’$I’ÚÉý’$I’$I’$ aÝÜ£ `gOu‘1ÁZå1Ëb:Ò­À*‹A’$I’¤jº9ÐRzHêNÓùƒÔ‘fC¾©nE u…W×Z ’$IjU·úgã°EêN+,‚†õÁb‹Aê3€[,†¦>Üf1HÃÖU$I’úª[ýKýè%eêƒ%ƒÔ&X…æcO_I’$IRöj—$I’$I’$i3Ð/IÎv„ý| ø†Å- ;^Û’$I’†ý’¤áj2ðBàÎAØ×Kqlyi8jåÚ^ Ì€<´šî@åC’$IR3Ð/IêQ¼¯YÀÀÓƒ·¾úGy I­êµ½1° pG›÷ßjº•ë6I’$©Ãè—$eü 8xxØ/³þà*àœ´þ£éõ÷+k€éÓ›\î+ï,"à´gZ>øef}QZEùú p5Ñkv"ð;"€V%ÝFǤî¾Î×»·q»nvð¾Ìò¾À-Ôoe×vQ½p$ð£\~Z©¯æ§4F¥mw-Hw ó±xufù'Ô$[­¯›“¬$I’4FwéqÏÂàŠºÓýÀƒJêÇ/3€ï§㈞±;¦õÿ—ÖO"=s‰F"ˆgWLïÞô ›W¥uôa_y³Ï;ˆ¡,j¬i%i5Ë×TàcÀvD/W€KWTL7L«<夶™|:³¼#½‡Ý)ªÆ–\ÛT¨¯nÊl;­Åújs" >*Õ 74Iw óq[*ƒßùˆ;ªì7_·5;&I’$I [ý—b/^u§yƒ Ì>žYž,'‚òÁó#2ë÷Ö§w¯ÙÔMeéü;ðâô¾±Àa}ܹ×wHé×ìÜ^1­fùÚ‹.μo2õ`bYºùc’ÔÓˆžø·g^Û¸¶býöæ’k»¬¾šü´õÀD@þà¢ý Òè|ÜF ×p2q—Ã?úP_“$I’¤0º‹ý0à"Ou‘[,•˜DôÀ\šyímÀéùL`=`Afý4àbà}Ho_à?·§ós$1yîM}ØWÞéï=™×æþöî<^ŽªLüÿ'$^4$Y@« 7 0£Œ(»ã„q”Ÿ‚€. ".Œ¢#¢"*¢2n(*\AA…$0lÈNBB ÷ûÇsú×u+ÝÕËÝzù¼_¯~Ýî®êS§N-·û©SÏ¡+*«¨^{Oæþ¾‘HQ«ÜJë$ipì,žÍ›{_©ó|4¥Æ±]t^X¸xK“ç+ˆ;®¥œÿàóÊêz,ÞìGäñÿN“çëjëtŽ»ª$I’¤zÔ›[Ü\þòøúãÃýíç•ÀsÀIDoͽ‡)÷î|‘“9k/bàÊ9éõXà5éóµÊ;‘³‡è9û-"½COËÊ;øCî½€]ë(«¨^s‰@áÀ‹€sÓ~4½Žr+­“<ÎÍÉ=8öNÿ¿Æ¤ãí³©Í&Öy~«ul6HóNiò|uå‹“ÛKõ©TîPÖ"UÏ߉;¬s¹•ÎmÕÖIž$I’4DÖ³ $II/ð]`wbPÅóˆ‹>‹ÒôJ¹¢¯'zΞ&zÔL!j•w1$ZFôª½;M[ÓIJ*­Ë­™×›½SÖQVQ½®$§œŸêWêA¼¸Žr+­“¤Áñ»t\Þ\E º»X^çù­Ö±]t^X |5Í»´‰óÕ>Ài¾k€/¥ÏU*w(ëA*k*°–þ)€=_W['I’$Iª‹=ú×5èÁÖè´zËÜþ·º—Á^î¥D·’Ox| ˆ=úÛÏùÀñ-\ž:Ÿ=ú>Ÿ<©}y>$IRÓìѯú‘÷¶—» °-Ѱä+Ä8ÝÄê"½Àí-\ž$y>’$I’¤ ô« ö ÒÇ·¤g­~fs«‹Ì`pŠìò$Éó‘$I’$U` ¿sK 4¹šDí¸*óÜCyp9€#€û‰|¶9Xë•MãSzþnbà·è[ñÀ׀ljœ¹/ÌL‘6f5‘×uû\¹G÷¹aói‡þLçKµÀÇë\îk_WX·ëpà8u— ékÕò$Éó‘$I’$U` ¿3L&•{ ÔÞ‰èž÷n"ïü>”{µN¯§Û³SP—ÑÀÀfÀ·Ïd¦lll™ê̓¿˜H£3HÍsn®Ü]€—¯¯°Ü]qéñz`1¨^­ånœê{g…2o'˜“$I’$I’¤–5Æ&èk€AðD{Anž“‰V_<œ›v ðtz|øpúêó9¢Gý¥ÀûÓ{wl <•Þ;¸8)½¾&SÆ—€+rå~øGe¿øp8pkË-åà_U¡¬§™ñ4¼zI6ƒÔ¦Ú’$I’$5Î@gx88žÒßJ±oHÓ×>DûóAþ>"mOÉhYK¤Çx†r ©i»-3ï¨4ÉQÀ‰À”ôú¹r«±ìM€yÀÀåu.·T×q”/”ŒOm«Îv¹M ©MüÖ&$I’$Ub ¿sÌKàÀÿ½Øžö®"‚å?Ë|n0r°ðÈÔï1"¸> o"ÅÎ~D¾üÝh, ÑC¤êùýSþÔZî2bLƒˆ<ÿY;MÔ™–©›$µž6Á:ö· ¤®°Ð&$IR3 ôw†éG®#Òø¬&‚ûY·Ë^A¤ù¹23í "ÿXà4"­Í`[ |ø`7©$Ï’$IS÷Há ÜëÏÚ$’$I’$I’Ú©{TÍ4Ê)pò{JK’$I’$IR‹°G¿ª¹ŸÈS/I’$I’$Ijaöè—$I’$I’$©usþm€]ÝÔEzºl}{Inv©#Mµ $I’$I*ëæ@ÿé!©3]nHê{¿µ¤®0Ê&$IR³º5Ð?Ó©;­î‚u\ l즖ºÂŠ.Z×ýÝÜRÇšüÍ I’¤èÖ@ÿ 7½Ô±ž–Û ’:Ì56Ô±žµ $I’4Pöj—$I’$I’$©è—$IR»ÙxÒfhÊtà¹!j÷é¬Û;ýRà5™×'Ÿp3H’$IƒË@¿$I’ÚÍ߀ 6C]Øh»ïl \•yï+ÀÑÀD7$I’4x ôK’$I ÇçÞ[ü 8Ìæ‘$I’~I’$µ›l/õÒó#€û•À@Ofþc€ÕÀßã2Ó6¾÷Zà×Öç:`®»±$I’4xÆØ’:Ì8àP›Aê —Fi4°ˆÞ¸88’Ÿìüؘ–ùìùÀúÀ6@ðDù“Òô Óß­‰àün5êRky‹‰”6+SÙçR;èýM"ˆ?)­ßsÓ‹Öa`aúÿHj£¢öºø8qãÉô{á­ÀT¨×…ižI©üË2Ó6¶î¬ð¹ÛYî¶’$IÒàéÖ@/ý{yIÝâ^`Y‡¯ãÆDÏÄÀ7¹Ô‘zÒÿò«0Я²S€§Óã“ÀˆÀõàŸÀKÓÿ†é/Dû"ˆÿTzïLâ"ÒIÀ†ÀDžùiú5êQ´<€k2Ï¿\Q£¼ ‰žñÓ€gÒã,à'u®C£íõð[àMÀ׉tþL\ÈÖëuÀV™zIùn€RþJÇèS8Æ‚$I’4¨º5Ð9ý{VIÝâ°ôÿ¼ŽHI ©óL#RŸH%}¹sþ`jzþ$pp<̾•€ßæÜ–ùì(`mz>9½nd+ZÀQÀ‰À”ôú5Ê›œþ.ͼ÷@æy­uh´½¾M¤ú:ð6à êõ@®œ’åéï8Ê JƧv’$I’4Hº9uÏÑÀÜÔEæÛ’¤5ЏT ^OÉLŸ—=ÀˆÔ6[ñiD*¼Gˆ x¶ìzT[Þ&DšýˆÜõ»½ç‹<šþ¾˜È÷°efz­uèk¢½.¾Ì .œŸXP¯-)û³i–¥úî@Ü µ#qD’$IÒ éæ@ÿjÊ=¤nð¼M 5 ¸Ø¸‹èUúbÀÈFJR-g½ÐǧQ¾ƒíÅDª§ëˆ´:«3ÿWß>œ@ô2ß Ø øÑý'À9À»ˆ47»,¨GÑòzˆüøËÒó÷Õ±^+‰x?Öoú§ä©µËÓ2· ÿ]ÕÚ " Ï¥é½?Qù"ÇJâbÆ™DšqÀGró\ìɺþ=Ó:I’$I$ëÙ’¤ÖGäx¾+½>•8r<ƒä_J\@¨õž¤ö²¸¸¸'CÎHÓF#z¾¯Þ ¼=óÙ£€g‰AcŸJå윙þ.à9¢×úcÀ15êR´¼‡€³‰4>·SÿÝvGÁû'€ßAŸ«s%Ƹ¸0»F{•|›¸`ñ¿5êµ)‘Ãÿ7¬›ð"õOÖ8`bÐ_I’$Iªh pè ΧPÊM»}z=5ý˜{ øfzïß_2|Þ\ä¦iéããdb°ÀÁ2rú„Á˜O­k°÷”»)1@æú5ÞSëë¤óA°GÁô=¨œzEeÓéô|qt¨lIÜÁ°áËù11 oɇ‰ÁÕüq^ë¼!I’¤.d~Õûc¢¨·íÖD­#œô0õô¸ýYú‘;ÎÍ#µ½#‰|Ð=À "'ôω€Þ1D*ˆ/½T$z†–LNÓ#RO\lL\¨| ýß{"=¦WxoŒ›CR Ú‰Èk€ÿ8@J îX9ÀrJçâ’Ïwø qçÑ‹€÷*OHŸG ˆyG…÷žssHªÃ4"-O¥Ç´!(ocâ"æêt¾ü+ì ÁýÿNwSK’$IíÁž‹ªÇ‘Dïù7½d7$zÛÞKôöš ¼!3ÿ1Àiú›ˆÀÙÿ\¦O¾ü \û5‘*fc¢o©wí?€W¤³Ù÷¦¤2¶sóHmopnz>›bU3“Èo}]z½xUfúÝé1ØåÕDЪ´œ[*,û7ÔÖîï´÷3¸wÖ*ï~`›aZ·Õ <]$I’¤af~Õ£¨·íQÀwˆà²óGÛ28©‚$¬™”ƒûEþQé¼óóÌ{3ˆ&Kþ,'<ø[AÙµ.,H’$I’$µ<ýªG)ÐëÅö¡ÞU¨Üã6ënàz`-ëq»p›Gjk[=qï©p¾ÉÛ:Í{gæ½9™óÃ\à£ÀÑÄEÁM‰ “·¤ÿw3rç’JïI’$I’$µS÷¨ÕzÛŽ#zìgù¥·GeÞ«Ôãö½ÀKÒüc‰À\©üËr˯ôÞŽÄ¿wóHmm0Ÿô»ôú„‚sÑúßÉ3øDz¾318ï"âN¡ÿÉœ£^”k3Ÿ­ôžÔªúlI’$IR5úUK¥Þ¶ÿ››'›¶gk*÷¸-êK=nßL÷Öî£ñ·GßžrIm­臸x7‘HÙUÉÌܹ`Óô™…éõÅÀÄB yDMz|XL 2¹‘‡:ÿžÔjûÛ ’$I’¤n²„Ôu°æS ²›í5ÿ0Ñc¿äख़×7æÊxØ5=?‘HÛÓCô¾Eàzˆô=}Ä`»%•ÞÛxØÖÍÓÒÇÇÉÀYƒXÿii_˜6HóIj_t>èöp“Jò¼!I’¤0G¿j©ÕÛö—ÀË2¯ëéqÛCô¸½’È×_êq›í]»4Í_é½/ŸÆüü’$I’$I’ÔqìÑ?üö`ÝÁx‡Ò;Klö¶8>ìÑ/i¨Ø£_R7ó¼!I’¤uØ£_õ;à5ø¼‹ð"$I’$I’$ýÿ ôK’$I’$I’ÔÆ ôK’$I’$I’ÔÆ ôK’$I’$I’ÔÆÆØ…z›Amà^`™ÍОtŒKj= €56ƒ$I’$Iõ1Ð_ìr`šÍ 6pp‰ÍЩÀÍ6ƒÔ’¶î·úé³ ¤®ðJàw6ƒ$I’e ¿¶£Ù jaóm‚™ ,µ¤–°…ç´BÇ m©c]mH’$©Yúk[ ,·Ôž· d…ǸÔ2ÆÛ…nÆž¾’$I’¤ ŒW’$I’$I’¤6f _­b*ðà)à›6‡Ôõv¢rçØ¼’8_Œ–Û·p]O¾Üĺ äûW«´‹ÿ/$I’$ ô«uœJä1À²&ƒ®Ê=ŽËÌó.`‘ši%ð{àÅ>ÿ4ðð7‘Ô¥4 ™lÜ>Èušl6å¶K»JÔù°dL:^ã>Û*ûøD"¾(}'Ø ¸«…·çÎTߢh]ùþ•ß6­Ð.þ¿$I’ýÝct‹/k/à‡ƒ´¬ÙÀ2`\îñ…4ýXààéý- (çiŸM÷Çc‰`È™À6îFê¢óÃ@ΛSˆ R3zû€gy={‰€Ô³mºÚ®uþ,y7ð°-°Á0ì³­´÷þÑ&Û´(Ð_´.õ~ÿjÕóÿ/$I’¤Ä@û: ¸øððp@fú‘ÀÕÀ…iúÓûÇ÷=Õ¯#zxÕSÞdà "þ p°q“ËÊê!Cüœè]8 8‰¸|5ð3¢gUѲ²f×ø!úNà+ÀŸ‰Þh+€ï¤z–>Sfþß§¿cÝíÔ‚ŽJûûªtÌìÞoô8jæ8®´ìí‰të¥rž úÀïÕê>“°|xxØ?÷ÙFëU*waæx¾ø1èÜ!­ÿÊôøešï Ê ¶Hí¹^¦-œŸÖõoÀNÀˆàÓ“À›ܦ•Ö­¨]«­¯ÔìÿA€€Ócˆ`猂ò*?ÕöÙjß'Šöñz¾O4ó]©è<93}')ç—Õ8njֽÀKfQyé¢ïUǤi_®r\øTfÚ[Sû-¬Ò•Ö¥Ò÷¯FÏ?Ùviæ\ØÈvm‡ÿ’$I’ÑàИo$œ~\ÌM?¼NH?nJ¾Hä[ý÷ôº8¸™¸Íºøð­:ËÛŽèõ5:ý½¸Ý»™eåí”~|—œ•~˜o¼øiú‘^mYyß!z&VóËôƒöMDµJŸ?==ŸÊºÖ½0ÖªûýÉi[–i) 5m˜çkenIÇÀôtÌ5s5z-ûXàû¨ûD hŸôútàW™Ï6[¯ RYÛMÏG¥i7§zNe¾,½?Š–Ìþ”;×>¼2#.MÇбéõÒ²êU´n•Úµh}ÛQ7ç}Àƒ8_=jý8‡6ü…ˆVSíø©´Ï}Ÿ¨4#ß'ý®Ttž¼ -»tœ¢Žcî¶´¬’Ë÷U©[Q;|…¸3qï*çÀ×=ì7":$ÜSÐÕÖ%ÿý«ÑóO¶¬FÏ…l×vùÑ®çI’$©%uS ð±ÌëIéKéÖú_SVCô[MôB*Ùr®Zåå}’HgÓ̲ò¥Üjs"Ø8%3ýmÀª,«’ùD¯­'3Ïg¦oœÜB\¤ àÜ—_—ü÷¯FÏ?ù²96²]ÛéÿE»ž$I’Ô!LÝÓ¾z‰ÞR%ˆàôêôz&ýs®î ¬OôD-¿¯"zŒÕSÞáé³ËÓgO&nËnfYy³[3Ÿ½™þ=ÌÆWYVÞúÀŽéö„Ì#û#ðA¢‡Ý4"€·cæuéóÓ)ðö6b:©•ì—‚•Élæ8jä8.Zvþ˜n´î£(§’(™Aô”H½J徑H-‘ŠBs"‚uA¢)™eÌÊ­ÛLú³vνމús¬uîÌ·k­í USôà3D–›ÓëÛÓ¾_M¥ã§Ú¹ èûD~þF¿O4ò]©èýxŸGä¯_Lô8ë«£¼‹‰žZˈžpw§ikšXVÞT¢W]©'ñÒÖ›ˆÞm»¬=]eYy³Óú¬Ê<žJ?¤!zÂ}/½ÿ8ðàµÀ3Ÿ_è.¦6pm:ήNÇǼÄhæ8jô8.Zöj"H¸˜êwÆ}¾—þé!6M牅¬W/å ÓeD¾éˈ`á>Àé3׃qÎ#òdÏOç§«ˆ|ÎK‰T•Úm&„{:ó?6Û öµiÝnªÒ.EëV©]‹Öw‡TßM=T”Sôð°4ýÔ{ó?L¤>y*íãyÕŽŸJûlÑ÷‰J󵎧ZßmŠÎ“ÙóŬÌó¢c¢“Á"¯û•Û ¨òwåÏWçùi¾Ò]G‹ Ú¡Òºä¿5zþ™•+·‘sa#ßÛåÿ…$I’¤AÖ-ƒñžßÂåÉýŒWÊû‘HçY¾94ÇÓH|·é!8~¹›Gž$I’4ÜìÑßžzÜÛ„»¸x x¸ Ø8Íó@úüé1&}æ8ààià:`j•ºï\ ¬L_”;TõØè#.”ì”Úi£‚å™êaZ“$I’¤!2Æ&ÔaÆ‡Ú RW¸Xe3(™ü(ózpð|zÝ ì|x?Œ>øišþ1ài¾g‰ öCÀSiúxà3Ào‰À÷<à=À§€WoÉ,ÿà `ïTÎW€³wTÙ—/^Cô†ŸÜU¥Ü¡ªÇJâBÁNÀoÒ{ŸþXlW°ÜYÀËsˆ ð‡ ë$I’$iˆtk ¿7ý‘ºÍ½À²_Ç €À7¹Ô‘zÒÿò«0Я²ÙD°¾dýÓîôèyéõ·‰ ÿÀXàCÀŽDv€Ë‰àuÉÝéAú_zuúliY·dæ œJ·—¤÷.¾V¥î[ÁðÑé׫”;ÔõX˜Úà7Àˈ #o­s¹ç¿H¯×¬“$I’¤!ЭþËin~u¡Ãˆ^ƒÝàuÀýnr©#M£´” ÚSˆü%³€ße^÷'f^O .­^O\Xš™>‘þ Þ ¼E\8:M› \–™w_`}àO™÷F±nоä" :ðsânƒeÊêz,$zôœ |øGËIôî¯g$I’$ nNÝs4ýoï–:Ý|›@’Ô¡v)wJßq÷&ÒÔ@õ·$RД \™žOžÌ}G~#‘ö`.ðQàÍéÿézÀ}DÀ|=`ëö¤¿”þ)tŠ\›¥<øGŸ¯PîP×c!ðv`?"ÿwêXîVÀ €;êX§sÜU%I’¤¡ÑÍþÕÀrwu‘çm5iÐÙ—È=ø‘ â‡Dð¦U<@ ®ù—!^Îi©Žu÷Zæ<56}·] œL¢|‘»7½‘g~/b€Ú}Òô»€OÈ>@ä°ßžH°31@ï""?ýÿìEÀ‹Òcm¦>·RN™ó×T·W©múru? Õó^"ÿþ†ÀíUÊÊz@¹Gÿ™éskëXîkR;=_Ç:I’$I"ëÙ’¤úˆ›w¥×§Á ñ o)Ń9N6gx‚I;ã]2R+ù]:&ï ÆnX™Î¥N½Àw݉ÁuÏ#n_”¦_ ü$•q å»§écC,KóÞ>»†è<òÕ4o)õÏõDüyÀÓiÚÁT®ïܘæ»øRú\¥r‡²¤²¦þl  ¢åVG Ú:I’$IR]–¤mƒ5_»: ør-ób°·Nl—n>>N&zT–iD`bÚ Í§æ- Rb §M¹¦«yå"‡£ voâs£Ý}<äô{ â|ªì|àx›A-Îó$I’šfþÎ4=M›]¦=p¥Öw$ѳ³‡Èo=ƒXqA…y!r1x”Hõ°nžã€{ˆžž×½G!Òid{~ø‘Fâô?ë‰ô¨”zn&q×Á›Xv)‡ôcÀ3Dà3ÿ+?•)ó­DJ…u”{$p5paª÷ݤÑ‹©c$I’$u0ý©ý½DîïgZ¸ŽöÀU·›Eäy^Côb—ŽßJó¾œì|2pqwGÉ)ÀÛˆ;&=ðÏNÓþ;½?x7‘÷ù "=Ä ©ÌqÀ&ÀsUÎ'» ]öxâBÃTàÅDê÷¤i^‘Êßxð‘þ£V¹¥öøAª÷¹îNÒˆ˜ÁºƒÅJ’$IRÇ0ÐßÛ°Ùž¦GA´UDÊ–R:ŽQÀIé½ÕÀψÞ÷ƒ±Ì,{àJ­¯è˜y^í˜>;SPÎ]:fO%RC-!.\욦?A ðømà#Àk‰;Ju¸¥F=gŸ®mbÙw¹¬×9¨¯6 óüp8ðHªÏå”ïf¨Uî,àbàKÒtIÃoѱ@’$I’:’þö7ž¦Žþ“è%ûïDààLà?ˆž¨›¹@?5Ë̳®ÔúfR_ T:æ~žyop[z¾/‘cÿOÀ“éqX/ùk*ã#DºêXniÙ3°ìÃÓ´åiÚÉÀßÒçæSØâ¢çü:Ë üÐ]H’$I’$©~Ý6ï$"p½Eæ½?MÏ'½ñwÈLßè‰: X ¼¤B¹›§r§dÞ{ð‡.³’èßcþMDNîfÊú$qb uü5pºÇÇ€9ogØ*O£Òë_¤óA%Û¤c+{ùgÀéù€ï,«—¸ç[À5™÷×#î¼Ù¼à³ÛæêÙȲçAýÙiYcˆÀþìô¹y™yNjӹªV¹[wKyQ}ð9¯¤Näù@’$IM3øÐÞÒÓt?"°½¸J¹7i*JÆ3ðÞ­YöÀ•Z߬tìôe^WëY?3WžÏ¼7'3ÿ­”sðŒ%òð"îÊù9‘›ÿ¿ˆ ÿ^i¾¥ÇÚ‚z––Ý×IJw&.0,"î úqAp‘ZlâÂà‹€ÏiÀÔQî¬ í! ÄoÓ>îÇÎ|H’$IMc´µ)D:»=ßH¤¥!ª.ÞRá³È}6k"Ñ+7ë"/õ@–™·Mú{Wæ½9DŸZeÍ> ¼™B®GäÞ½ØsuÜ xØ'•”ýi²&3éŸGÓô™ÒØ×Ÿ'zÈO .Ò]AÜ-tEšö³4ïg‰|û¯H磯&WÒÿn’^ú_€¨wÙWû¦yùô¯~’Ú` pð,勤EåÖ3®€T¯ým©+,´ $I’¤îKÝ3—²ÔÓô\¢7Ðô4}/b0ÚJ=M÷IŸ•¦m›ùÜ¿Áªíˆ ÷G€ÛÓç²Ì¼‰_Ö”±,*ëD"ÀÖC¿EåzXÇ7é„<>ÎÔ=’†J7¦î‘$Ï’$IªÊÔ=í-ÛÓô¢‡iµž¦O§÷N?®MÓ®NÓæoˆàû瀛ˆ€ø.Ä…§¸Ì¼FzàæËº˜ê/Kuº›Ê=p­£=p%I’$I’$iu[~©•{ôK*öè—ÔÍðµÔ¶æÛ UüÎf:VŸM I’¤fuk …›^Ræ|°ÜfZÂx›@’$I’¤ÆÙ«]’$IàdâÂí*`›£+Mž«1Ï¥Àk2¯O>aÓI’$©Ýè—$UrðåXîÀ`°Ø~˜—½Ë®“¤uÕ˜­Ç†ÄØK/ÆaªºVÜF­P·]€m«2ï}8˜è¦–$IR;3Ð/Iªdg†?WúDbäEDžâ­€»†qÙ›·A¹› A¹R;ΑSÓß;[¬ ¦´x»u›c€‹sï­~fóH’$©è—$U2þ^àoÀ?F`}{û€g† Ü»€gÝ¥ÔJ½§îV=¹éG¦ãéÊôþ&À‰1Qþ‡r0ûZ`4l]EÜýR4µã쯙r~ɺ=½§gŽÃÒ´wwÝì‘™w ^< \”™vlš5ðwà¸mvðSà@à5Ú5ßnÕêqð£\ç_¬Q—¢ºo|-µ÷ràBà…U¶Ñ!u´mµ}¤È{ˆ;¹V7R¾£«h[VÚ(ض¯~]aÙ×s=Ä%I’ÔÎ ôK’Ö>EEÞJX¦é£ˆÀR)ó3ª§88 ¸øððp@fzQY3éù‘Àe™ÏEôô_•>»7‘žc-Ñc¾dðÕu­TNiÙw²R;ìŸûìqÀ=ÀÓDPhjå–Úq,p ðãT÷€«‰@ØJ"8)µºÑÀ>D°u;`6pjnú.ÀK×§÷.Ê«;×ÒgöIÓÆ¥Ç_kÌ_É`×L9¯®s=¶HËø6ð™Ì´ [›j€ÉÀyÀ[ˆÀøNDOð"[û“€¥Àç‰ •ê“o·jõø°Ÿùì›Óù¥šZu?ØØ&Õy2å¼õ•¶Ñ@ö‘j§6˜@\ô=·ŽÏTª[µm»qz¿Ò]·³<¼%I’¤Ö±8ÔfZâ8:8kë5Hç2m˜çë'zEN!=¿'Ú%gÁû͈ž?%ù•œM­çN ‚æõ”upJzþEÊA¦·)ˆàÑVéùmôï…y9ð¾*u+*çâÂÄ>éõéô‚Üœæï¾|«ÎrO'‚gMÏG¥i7=lG§2_æ®Ø•Çyý{t¾¡4½B{Î%´Ùé“2Ó7žÏ}æu¹Ï<×ÀüEu{®Æëgsõ,]dœ“Î[¥å¯ÍÃYˆ;ŽÞIõ‹‰E^ œIô2¿9s¾©ÖnÕêð;àðô|àîË.ªûÀ?gÞÛ¸wm[m©×¿wÔ³¼ç*죕¶íviÚ¨ Ëë%.âz>$IRÛêÖ ½Ôw ±Ôiî–٠ʘDªw$zßCË_žžo¼—èá_šþC࿠ίçóÒëoŸ%IÕ(kfZ6DÏÊsSýN'zë–Ewd–wÑtð*"Ø~P•õ,*g&ðiâ‚DïüW¥ç“‰Þ¨sˆ a=m¿Vg¹}Ä .l”lIùGk€?º;ª ô)YJ–Ðÿî–µÀc™×“ÓßìgîË}†Ì߬µDŠˆ”]=™åÊëYO¦óËñÀ€[‰žú7¤é«2óŽ«ðù%é3sˆ@úäíV­½÷¾C\œ¿¤ÆúÕ}júMp[fþQ©NC±Tsp"åq ^0ÈÛvyfÛ<•ûÌøÔF’$IRÛêÖ@ÿ娋WÝé°:‚ê.û¹ø—fÞ›H9?ÿ¾DÏÓG2ÓÇSîi™×KjJ&Á¯ÕD©ZY£ˆ´;¥åÎ$Qûi9ªõ½)Í‘žá4"hžWTNiÙ‡gÞ›A9èµ/°>ð§Ügn©³Üm‰t?ÍM?„¸€p:ðsàƒx!N­oTúU äNËÓyfæ+}f+àáô¼¯Áù뵆òÝ2kèß[¾È#”{¤ß_aú¼ôè!.Þý‘Z*÷G=¯NçÀ‹€7Rrï÷¬¾Û¶Ñ}b\†óÓ9õ×ÀnÀoëX^_ûÄ2bl‚€?ç¦í˜þçH’$ImkL¯ûѬ;™ÔÉæÛª` ý{1Ž!‚F¥:‰ }Ö”{ÞgM z©¯È¼w0å%‹ÊÚ†4-!‚zcˆôA¯£¸—åMÄ……ƒ‰T@Õ.dM.(g›ô÷®Ì{s(0¸”Èm÷:ÊÝHô+"ÈWrmzL® ¯<Ç]Rmà b°Ó±Äŵ¢ È+‰àòYDí €ßMÓ—SΩ¾´ŽùëõÑkû à'Dš¬z<•æ?x‘ÎeW⎛3¯#Ϋ‰4CEî&RË|›¸€¹tꜿž¸hp/‘c¾HQÝWß'.HžÎi¥ñ~UaÕÓ¶ì#AüÑD0¾‡þ)ØŠ–—¯[-W{²n ÏÌÿ*I’$I- ÞÜâæò—ÇÇÐæèos‰ÀüÄ ç¦v™ž¦ÿHÙŽH£ð" 4¶BY¯$Z'=:÷&záîTGY9§Þ@Œ‘ÃzåA·ÍÔ ¢§ý?ˆÔÿQ°žEåü!7ÿDP `/¢—ñœôz,ðš´ŽµÊý}æù”>€ò…€íˆ'çzš2Gÿ Ì7”JùÐ zk¯¾N95J>_zÉ$âbÙJb,Œ/Ò?-Ëyé8z’¸µÖüEuË:"sî#.ÊåuÏö®Ÿ@¦W¤Ï3³?ý!Õk5q¡ñ5êµGíšW­%oOûŇë<¶Šê>–/å"¨~'ðþ‚mT«m«í#EÎJu»‡¸àðlÛ2_··Öض»É-w1ˆûÆž$I’¤Öa _jãÃ@{XTöY"°ó^"§ñèÌ<%zY.'ÒElV¥¬ÿ"z­^F¤ëYHy°ÉZe|%óüüÌgN'íOvÉ•y3ѳµ–jåä—·)10åú¹ýùÁôÙ¿«FË=èûBâ‚Ê#é3÷Ò? ÖÍ ô|¾¡T- -µÓ>òcâbmɇOz>$I’ZK§úK·$O!zM@Y§_®2­4èÛömºý‹Ö­^íÞ­t|èï>ç=§¢×èËmþŽ` àó %ýrñ| I’¤µžMÐòö"‚X?Ž!Rbœ6€òv¦z®ö>"7ö]#°žÛ=[³=…#zÐn9ëÖȬ‘j©ÝõR;Oô`;Hs£Í/u¼iÄÝB•^´mýöqûI’$IChŒMÐòN'Åüvz=u³lÄÎDʈVs7ðsà8âbÆîD®ØWy­Ûyݤn1¸c˜–µ 1¨ä|bð`ICïŽþîx?qg£Z·}Šö·Ÿ$I’4„ìÑߺ^ÜJÜ–{‘ëz!ð#Ê·D\A¤«y”èý¾nû~*3í­DJš…U–y$‘[¢7ýõD°ý "—ô™yw®&Y[ ü23í8b µ§‰@ÜÔÌ´£€EDï­%Ä`%ÿÖi‘?õb°¸jûn­u«T ‰^û›fæÛ)­ßF¹6¨Uߢõ”ºÑb Äáð—t̾xܦ—$I’$IÝÌý­ëŸD°ýZÊùâ§½WN¯gy©? Kôþ?™À| x‘NãYâ¢ÀCÀSU–9‹¸¸@úÌ.©ì÷$òoÿ4M¿¸ˆÌl40'½ pˆ\ólàÀ‡€·ÿIϧƒ~–üø1Xå?(hŸZëVTˆàþoÒ¼ŸNË[‘kƒ¢ú•/IÒp{!°¹Í µ¤UDçI’$iÈèom³€¿f^ï–^÷¥×3‰àòuéõ"àUéù$"P½#Ñ[àrЬœE9õM/p0/½þ6ô߀H´%à ¬!‚ó“S‰ ÿ’ô¹ ¯¥úœì ,NÓò)>ÖÖÏ÷jj­[Q= zýïHú_F\Ðxk® Šê[«|µ—^6Àµ¤ÁãQÍÛ ø­Í µ¤Kˆ<’$IÒ1ÐßÚv!z¹—ìšy=ŠP•™>¸-=ß—èý¿43}"ŃÕΤþ3Ó&½‘JãB»O'rë0-s}¢W>™zÞì, 4¯äsi9‹Ó¡oV™¯ÖºÕ"пSz~&ðqà¹6(ªo­òÕ^.· $uíºh]ïî²õU{ú›@’$IÃÁ@kÛ•H S²ðô|ë´ýîÌLŸC9¿üàÉܶ~#‘r¦’­Ò<÷Áö-‰T6%Wf^_›“‰´9Gé†.ÞR¡üäê“wLªß¿ép>N¤ê«0o­u›\Pˆ@ÿÛ‰`þÔL›fÛàuõ­U¾ÚÃR`c›AjI+l‚¦ÝÓEë:ÊÍ­6°Ê&$I’·8tçé¯+(çç‡prÇôüàÆÜg .ÌMŸßx‘ަÈ3_ɀߧç¯$ü=)Õcob\€2ËÞ&=ßø[ZÞ^DþÑR¾þ±DÿQÀ>”sàl›©Ë~Ä€¿3ÒëÑD/½«ÔµÖºÕâN‰¿=ò¬ÒEõ­U¾ÇG88kë?-mçiƒ4Ÿ¤öÕIçƒ>`A˜o*_ïd} jßMá<H’$© ­g´¬IDÐùîôzcà&Ê=øgÒ?U̦Dïô…éõ•ÀOˆt6·)hž¥zêœY”Sßô¦$»ƒÛžG~¥éûž®¾Däò¿ø|zþtZÖÁéÇȵiÚÕiÚ<"@>øÑþT÷µiÞ“ªÔµÖºÕƒ´SÓr.«ÒÕê[Où’$ièÙ£_’$I’:T'õèIçÇÛ d~ICÅýë²G;Pœ2°›M'îÜTsms)q'gɉÀ' æ·G¿$I’†…=úUI/p»Í I’ZXQþ¿ciäµò……Fë¶ ‘ÎñªÌ{_Ž&º©%I’4’ ô«’À6ƒ$I$cˆNù‚‰ÞÉÛäÞÿ"ðõeöuPÛ¨=\œ{oð+à0›G’$I#É@¿*™Üg3H’¤Aòn¢çô¶À™÷gÒü÷Ž^úETIQþlOíÒó#€û•À@Ofþc€ÕÀßã2Ó6¾<,.^˜ûÞtqšö$pQz—êsdZï+k”sð£\çCм‡HÇ·š[iû ÛäÑ´Þõ¤i¶®F§í¼ 8„þ½è§c-Õ»­]ßéËË×mN¶y-ðë ˾˜ëa.I’¤‘d"IêP`™Í u¤m‚†EŒ¿3 xxœœ | ø`Ä,?w¾ ¼,•q#ðêôü8àýÄàö$‚·WYöFÀéÀÄ ÷3Òg ý‹X·wþÎÀ©5Ö©úä ìCy7.O埞Úà<" û‡Tßì¸çëwôÿGäd?)M¿0ýÝš2ïVg}v^šY‡jå|/Õs<ðTúì›7ÖXÆâ´Œ•©ìs)£G[›¥uù ðoe ¤ö¦ý‹´ šÝVÍ®o5•êV­m6NïßY¡œÛYžf$I’4’º9п °«»€ºHO—¬çàÏÀºÉ¥Žöçt¼«¶oOçÅED0ó™4m<Èü-¼GôŒþ4p Ñ«ü5Dð³ÔÛùà `oà!"GùÙÄŃJNn"Äw3)úçÖ¬)À&Àüôz.´Ýx>3ߨÛáàéôø$ð"x¼ø't_¬H!͇Á÷§Ò{g¦¶9 Ø8¸SaEš~cõù8ðô¼¨œ%À_ˆÀþwˆàôÓu,çšÌó/Wä¦XK .ûþ:þ·6ÛFͨ¶­²¾¨Ô6¥ü«*ÌÿŽ !I’¤ÖÍþ3ÒCRgy˜úzSJR7˜DHw¥œ?;ÏÝéÑ‹ÿjÊ©u¶$ü£‰@ݧú%i¾ ‰´-•l ¼—rú“Û‰@Él"ÅÊ™÷FwQ¨ÎK¼Fzô÷©`J–w#@¤É9ˆ¸ãá À­D€ú†4Ïà¶ÌgGA`R{ŒÊ´E½Öe^×*ç"˜þ⎋KêXÆQÀ‰Ä…€ä–¿<=†ÚÒF*ÚȺ , IDATVÍ®o£Û¦RÛ”ÞGù‚FÉøÔF’$IÒˆéÖ@ÿLŸ@ÝiµM I]e?¢çõâ*Ó'ñ/!‚³c£Ó´C(§Lù9ðA`_"EËŸ2eŒ¢z>ýÏ¿nN¯o§œþg}`G" ÍM™Ïü°]ëÖHþQDª™RyðHfzébBð"õÌÖD0~mše…r!ÓÙ²›Q«œ½Ì· zöï^£¼Mˆt:ûé˜v#îÚˆfÛ(Ÿ–i q1§'=ŸÔà¶jt}‹–×È€Îˈ± v î(ÊÚ‘¸ø!I’$˜n ô¯pÓK’¤.0™ê=ç%íó‰N÷QÚ_›“‰4(Gé[.ÞRDz÷&‚¿¥üý/¢œ~gFZæÕôO‡òÖ ¤VÒH~ˆ;9ßM\Ì8r¯øƒÿ^G‚Wgê¸ø>ðyà„Ô–›;¿"zvÿ8x‘jfWÊ©‰êU«œÇ€ë‰TJ÷LŠôÁíeéùû¸ ¤–SÎ{¿”àö)⟃üÖ»­šYߢååëVËÀžöÏ=)ª,I’${µK’$u®DÀ½4Pè¶”CÝxÈÛ¿ð "¨¿ˆH¥³Mšo<‘Cþv¢×òÞ”óõ%røçÀïW‰¼î³ÓãÕD.ói©ŒE¬›óü_¨~‡@~õZKÊïî!Æ(¥p |Œ¦¯ÞIŒiPrð,1¾ÀS©œ3Óߢ·{§ÿí¶õõo{þ=¸ÄÓ’$I’†Z·ú/Ç\žêN‡uÁÍoàuR78øˆÍPѨ.ùÛmëëßöük_’$Iâ›sô üÈ]@]d~­ë€OºÉ¥Žu…M êÏÑ/I’$I¯›ý«åîê"ÏwѺ>ëñ-u´çlÑ?…ÏÀŸ€ 6‹Ùt`aßM—_®J¯O6N·ù$I’4\ŒW’$Ií(Û£ÿoäo'ÓiÝ vÖm`[ÊA~€¯wOtSK’$i¸èW3¦¿ž¾9åŸ|¹ÅÖù`Ž›^]b°Ø~˜Žùá>îòë'©=õµi½Ç¸é:Ê1ÀŹ÷V¿"ÆF’$I’†…~5ãTâæñÀCPþδV>ù‰D s‘›^]¢Ø ¸k˜ŽùjÇÝfÀíM|v)ÅòëWo}JŸË¾^< ŽËÌó.`‘Nq%ð{àÅ 7ÙýÙ^Ø¥çG÷§²/z2óK\L\ ü=W¯ €¯ià.^˜™>ì.ž.ªÑ¥ú Ü\Y£œ“Xw©s/ÖXN­zW[çzÚ«šfÛñZ`tf¿8„þ½è§iøZ¿÷vW7R¾À;½`yùº•þŸ¼x4­ï™Ï¾øu…e_ÌõT I’¤áb ¿5nñeíüp—Õjþ^"%À?Ü5Õ¥š=æzÜÝE9ðR¯M) þ…¹ÙD jIæõcÀ8`,°<ئÁy¥N5X–öûìã iú±À À;Òû[ÁÛå 7}5¾sìCp·K嚦MÎÞB£w"z_—œl”–µešÿ™é/¶Nçœ êü´ ðRàõ5Êù<Ÿùì›Kj,£¨ÞµÖ¹¨½ªH;î¬Íì­£ý­ÀâÔîÒw¹sëøL¥º¶ .@øLšwãôþʹ˜å©@’$IjÎàÐAœo°\| xx8 3ýHàêôƒï àÃéýã€{ˆžl×½Êë)o2pEúü ‘3tã&—•Õ¬ ÜÃnÑ›î$ʽ¥~F9iµee­|Šè!õ ðÖTçñ™yŠêvÐ[•ê°wmP«ýòÞ›~tSc}‹¦5ºÌN8>NÎÄúOKûÞ´óýv—ÛŽ.«rÌ7z~+:‹Žá÷RîÑ:–pý8]ª¶OËX›Ê{‚Ê)2Jë1€çÕDÑ•À/«´ÉñD/Ïìëy™×›¦vÚ¹ÁyÕœzózÏ#©þ½ƒ›o*¾›ù?Yt\Ôó}¡´ßÿ¶ ¾7ï/˜Þèq“ïÑŸßîs‰ /DÐ÷À;sß7 Öÿ¤|gÀîÀ½éù†é³UÛ¸TŸI™÷j•ó;àðô|àî˨Uï¢u®Õ^Õ ¤+õ¨/êÑßLýòþ•¸» žå=W¡}Jß鿤ãâ¢CvPè¬Þtœ|7=†ó| I’¤.dþáÑKô&º2ýÈû,ÑË©dðràÀ&Do£S€·¥äÒ¼³ë,o<ÑÓhjúµqër3ËÊZ“~¤=JÛz‰Þuÿ‘ÊÜ$ýðøTÁ²ò>¼"•µ#ð>à!"85êö!¢Gà¦úü{ >ÔjƒZíWiû•î0(Zߢi.SI³€[«óžßŠŽÅ¢c¸—¸°° ‘ÎãNà`"XYí¼pÑCøG©¼M¨< biý . \–8›c„T2¸%÷úOéùàÓD0õö畆R³ÿ'«õ~_(í÷EwÖ,#.B¼)-£Òç«7sÓñ^Ô£¿HóR²„òE‰'ƒˆ •K‰1HvOÓ¦oKó=I\Ù(MŸLyœF¬%.ªPg9—él .¾×êÍ_«ÞEë\«½ªH;6ª™ú‘ö±ÅD`þâD3ÖR¾ÛäÊiƒJï«ð™ñi½%I’$5¡U{ôÏ#Ú%“Ò–Ò_§ç~ü­&zÔ•ìN¹7m­òò>I¡›YVÞ¡”{ömNä§d¦¿ øC•eåMJŸß"óÞG€ŸÖQ·IéGÛKêÜÙ6h´ýn n³/ZßZmÑè2;áø°Gûú5¼Éó͜ߪ‹µŽá€¯ù¬hàœõ5jç¿Ï®ß#D¯âZ¹žçoϽ^Ey$òloÑļjŽ=úוïÑ?ÿ“•Ž‹F¿/Ì'z3?™y|>3}s"íËýÀóDxÊŽ›Z=ú_Kåq9zˆ;ïK¯7LålXe9㉠o#ûT¾‡x=åL"Ê[¤¶Û±Æ2jÕ»hi¯zˬUŸ—æÚdÛT‡Ò>÷JŠ{ô×S¿ÒÅÞ½ˆ‹*ÿ’)³hyùºõþ‡¸È±k…åI\·G¿$I’†…=ú‡G/piæõ„ôãuuz=“þù¯÷Ö'z²e{A-«³¼ÃÓgKƒ»Lä%mfYy³)÷„Ý—¸õþ‘Ü×Ç«,+oßôC~i潉”{ÏÕm¿\¨vÛvQÔj¿¬QÀŒT§¢õ­Õ,Si33Çyö˜oæüVíX,:†KÇ݉»~ÚÀ9«V}óëwq!á!à[ôO+T²>d»%÷zz:gmN\Ø[Úà¼ÒPÈÿÉJÇE#ßJûý«Ò9¡ôø`fž‰»ø¦AÒM[ |Ÿ¸(1!½·YZˆ‹ú?Î!‚Øc€—5±}j•ó‘í""ÝM­;€jÕ»hkµW5iÇå”óÞC pûqv}âNX¿ž´Œeéùû2ÓŠ–—¯[-W{VxOÊ/K’$ICÎ@ÿЛ@ @¶"óÞÁ™/þ[/îÈLŸLβ?Ž7J?j•7ø(p4Ñ“iS"íÆ-M,«’lÊ‹‰¬¨>€èý[iYySèKó"°7¿ŽºM¦úíÐEmP«ýò¶!zÜ-©±¾EÓ]¦4’¶JÇâ=ŽùFÏoEÇbÑ1\ls?"õÈnuž³Ö#.ÜÒÀú]KžvLŸ=¢Âgf¤óÀí™×«©¬od^i(5û²ÚqÑÈ÷…D~AuýkzlÐàq3ª`ÚZ"P~G:Þbˆ îLj`ú*"Ç|ö.œ£ˆÛwÁàëé?6À»ˆÞ¤2ŽirÕ*ç’t¼¤ÎòŠê]k‹Ú«š´ã£ÄØ.¥Ô>;ã?œŸæ¿¡íYÍCDj©Ò9y~fÚ? –—¯Ûì˹€¸•5Ž[ábOE’$IRsZ1uÏ+Ó¸“ÒÒ½‡Òô7Tø1³Wú‘1'½Kô˜UGy'¦B=Dðù[Džíž&–UÉÔótÿÑëi;"¨ÿ‘ôCjl•eU 4¬ Ò¼ˆÈáßGôà«U·}Ògg¥iÛf>WÔµÚ/ï@b@¼Zë[4­ÑevÊñaêžöô"'~¥c¾Ñó[ѱXt ˜©ÃDl³:Î ¤}dJëwå‹ Û½™çVøÌ»ˆ;v²¯_¥üFæUóLݳ®|êžfÿOV;.ù¾ð."p_Í D•õˆÞÔ‡à—5xÜTëÑ_)UŽªkõöj‡íùãt<”|˜H‡¦î‘$IÒ0±GÿÐëM_îwO?bÏ#‚¨¥êf±nïÓë‰[çùm½dûê(ïâôC}Ñ«öî4mMËÊ›š¥^ú>Ü”~üï’ OWYVÞ•ÄmëóÓ¼‹‰ž_‹ë¨ÛµiÚÕiÚ¼t¨ÕµÚ¯Òö›_ÇúMkt™ÒHš•ÙçóÇ|£ç·¢c±èÎw—y÷/^Xã¼°šÈ뿘ê=³ë·pc*ç¢ç¼ Ÿ™;ŸÍ&z“2Ày¥¡ÔìÿÉjÇE#ßf§ãxUæñåX§ßKï?¼ƒÈ¹þÇ:Ž›—=ÈÇRÜ£_N©¬J>Kÿñk$I’$5¨{ôŸßÂåu›‘h¿VÙföèW§îÛê>öè_W¾G7h¥ýÓèa#û˜ÖâË(j¯áX¯v¯_-öè—$IÒ°c ¹^ú$Ùjå¹=:s™’û¶¤NW­Gÿ#ð÷~"/{;.£¨½†c½Ú½~’$IRK0uÏЛAñ€´#]žÛ£3—)¹oKêt}6$I’${ô½ -^žÛ£3—)¹oKêtæè—$I’¤Ä@¿$IR縺‹Öu?bÀ`©•Í Ç–$I’†T7ú·vuPé± Öi^›AjI €56CC–ÿÝeëüg7»Úd?½Åf$IÒPëæ@ÿé!©;Mn¶¤–´Õÿcï¾ãí¨Ê…ÿ€)PBh'4CM…{•+ŠP.ñ¾\E@¸HQŠÒ¹ /"—&ˆ. ¼H±P¥\PªRB/J-”$¤ yÿxÖ¾{Îd×S÷Ùû÷ý|æsöž™½fÍÚ3sÎyfͳˆA6U»—lI’$IjM­è‹«5Í· J^^µ¤†°.ð„Í I’$IR}Z5Ðÿž_½¤Ìõ`–Í 5„¡6$I’$Iõ³W»$I’$I’$Iý˜~IRWœüÐ:K’$I’$õý’¤®Ø‚ÎåT,%];Ÿ,ÞNìĺ=YgI’$I’¤†d _’Ô š'ÆF˜–yÿ60œ lPçº=YgI’$I’¤†´¼M IªÑrÀiÀ¡ÀÀ7'Óò6à8àkÀêÀÿ ô`ÇãÇrïμÿSú9¨Îuë­3ÀQÀÀHàA`/àÍ´ì`àh xظ ü ø'â†Ã=ÀÞÀL`Ÿô¹'SY‡¿òR],²$I’$Iyú%Iµúð ` l¼x˜›–Ÿ l|œî_|øz‰²&Ð1x?x(½|xx8¾Žuë­óIÀîÀöiþ%ÀÙD@ÿ[À¾À¿§ò7¦Ï ÎîVnKuL¾OÜ@ø&p)úÕ5‡ÚRKxÑ&$IRg´Z ¢ç¥ÔjÞ^³ÔkïÍ€iÞo‰ >ÀÚD@ãÌòë‰Þý¥Œ'áÙ÷»½ëwŸ>¬sÝzê<8™¸qPH 4øqúì©ÀVÀ iÙ³™²_JD/þ;€Áéýà\"øpeªÿ``¾‡’:éÇ6$I’$©œV ô_lë×®t6õ V*åí@äµ53o8Å\÷;P ¨Côz§DY+Á÷Çrï7È•_ﺩóŠŸ€H?ô°#0•b?o?âÆÆGÓgéy ýÇeÖF l_’$I’$õˆVLÝs>pº_½ZÈ­6ºÁšÀìÜï݈Ô7ô| {W¢}Þ–ÀŠ©v¶LŸ}µ‹ëÖ[çÀ Àž%>{dî³Y“o_$n,¼LÜ ¬¼—Yà6!I’$I’ÔSZ1пˆÒCJÍê›@ÝàEâ&éh`:ñ”ÈÆD¯wˆÞü§¯Ç£€Ÿ–(k1Pí™÷O•Ùn=ëÖ[çÇ)¦îy”è•ÿ)àwiÓqi½ Dúž-€×‰¼ý«ÿEÜ4xøqcb"‡ÿ§‰C“<„$I’$IROYÎ&$Õà6à&¢ûcDJ›ESÛüøð0ð1í$`A‰²ÆÓqpÝñD0Ÿ.®[oïÎ#ré/Hó÷–yÿÏ#rï/Hë JŸ»šúÏLÛx‰ò/&Òö\C J<¸Ø;-—$I’$IR ¦•rîÎêƒz¦| Á¦t®×ùºÔv³ªÖö¯¥7;gÞGôbndõ÷ÕΣZÐÍç[;€mï¦ý­µ<©—GÛ žçuXŠãIòº!I’¤.²GïxžÈÛ܈:dï 'ook©8FôbûO$ÒwÜž™w 1çpsIDþglI’$I’Ô› ô«?9ø0x؉HÑ[%RvdÍþHäã–¤-‰<þ’$I’$I½Æ@ïÈöš/¼>€°rp‘ï¹àp¢·ú|à5b Ç‚ÁÀwˆA…§+e–#‚ѳˆt5WT©ÛÀ"`=Ø‹Ž=ü7%rZgëþU"÷tŠ WZVK½+JÎV"òd?›¦‹•ë¨[-íK…}ظ§Dýî&{˜KJ×à—mI’$I’Ô› ô÷Ä •›ƒKžœ– oÜ“ŽoNô/¸XØX/­ŸÍ?ø°>°:q¡’IÀ`Hš­¡îë©s®ΩqYµzW27µÄ—›¦i`ù·Oí[®ŒUÓüçJ”ù 0ÎÃZ’$I’$IR_XÞ&è3' Òt:p>p*°øÄž ¼—~B¦÷"‚øsÓ¼3kã‰ÞíŸ'òÈ¿—–?Ðuÿqsààˆ–U«woÕ*í[©ŒBþy%ÊœKãŽÁ êÆkØ RCiH’$I’T?ý}c)‘¶§`ÅàÆl`wàh"øÿ8 ¿?­³<ðTæ³mDP¢·z[*¯§,!Rï,¤cÊ¡r˪ջ7êF í[©ŒÂ¼!oV M媣U(Þpjd¿õ«’Ôà®ö¶¤¦w-Žû$I’¤N2Ðß7Ú€vŠÁþv`Ffù-i üœè ÿ6ˆn'rûçÍ n"dË®fiîýb"}ÍÀôº;z:W«wo+×¾•Ì$òùþ’[¶qÃ@ýË«DJ&Iç=›`wgÙ RÓ:Ñ&$IRWèï;gƒ¾N!zð¬C¤¹‹´Ï>LËæ×çǽÈ×¢˜g~.pp.p‘h+àÁ õ˜E1/ý«Ä´s‰^ï7×vUµz÷¦Jí[Í­Àv,è߸ÍCºßùâ“’ÔèÞþ`3HMë+6$I’ºÂÁxûÆànàYàoÀ“Dà"èþ¢ü¼ôGÿ¾™Ï ,"…›ÊÙ"³ü à"`ÿ6ph•º¼\L¤Õ™Ê:Š<÷9Š)mºªZ½kñ;"8Ÿ}ÿ~eTkßJ.¾œ›7Ø ¸ÚÃZ’$I’$I’ºn•sØÞKß?ö¾)ˆWÿt#°sæý±Ä`ʬÞã¾ÚyT«³€ºq?Ú)¦¦¢ÁÏsIq]«õºÑ—–ÛVYçš4õ£éŸãÖôÔßg½ýw_on¯+ßõ¦DžpCîoµã€ÓúÁ1XÏy^ËuC’$I-ÆÔ=R}vϽÿ¾MRÖ*Ô>V„$©9< ³ü®ûÈD`Càö̼K€€ó1eŸ$I’š˜©{ê×N¤|ÉOKÓTjY{ƒÖ¹êÖë)I’ÔÝì€Óu‡²l:ÅyĘPûØ<’$Ijfúë÷ ‘—=?µ¥©Ô²l¯ægûà¹ruÎ×­QÛ¶Ñê©Ú %Æc$µŽlê˜ÂëÒïñ9Äx73ëNŒ+4x'¨`0ðcà¢'ö`¥ÌòaDPw‘BæŠêWí3_%Æ/šNÇÔ(ÝU—½ˆñ™6Í´ÏÀËÀm5l«–6Í:ŒHÉ7xØ8Í?–Hq“u!p1~Ño2ó_®Ï¼ŸŒ/ó]—k¿5€[ˆ û³Àö¹m¯–¶ñ^ÚïÿÊü½\k}vî)Ñw“==%I’ÔÌ ôKê)«ïÚ ’ÔÒ“ˆ@ðFD@öä´lp°'ÜÞœèy]p)‘n`½´~6×úà#ÀúÀêDÀ»šJŸ¬ ¬\ œÓÍuùjúÌ$"Ø]ØæD`àßjÜV¥6Í{!•?ŒHµsAš5‘ǾzgyàKÀUD ü“éÿ„µ‰›Û¤õ6$:`«¦í?W¢nÏã<%I’ÔÌ|D¸´MÒ? R£{“èÙˆF¦úyžKj–ëš:ç$`AšN'r¥Ÿ ,þ‘®ÇS‰ÞÜSÓg½ß×§øtØ™ÀµÀñÀÊÀç‰@ï{iùUêQËg~@œoŽèƺœ@ tÿ©¿ÿx¿ÆmUkÓ¼?d^_ Üš^¿A jýà'DÐÿà/iù\âÂhàw{ðo“>÷a™6.Õ~+ŸF Ót&Å' Ë×ÏìÓiD¯þÓˆ' j©ÏðTÞ¼õš‹cGH’$©Éè/ír:>n,5ª³°^mDz€<Ï%5ÉuM³”Žé÷¦7‚!zxïMª'‚Ù÷§u–žÊýnY’^Hï§ÕQ—jŸYBq°Ö…Óátµ.Ëß"‚ýo–ØæÛ™÷Õ¶U­MóŽÖLïWÈ,»’xÊà'DûÿÎ,»øtú]~Oú®¶#ë÷ÔÙ~#ÒÏé¹:“[žÝ§—sûTK} Û²©‡¦ÏH’$IMË@yç=¤¤Fuk×m}¢gà<ÏsIMr]Sç´íƒ¸íÀŒÌò[Ò48øyúò68n'òÐçÍ ÞÙ²«éÌg膺|ìÜžÊúu¶UK›¬F¤Ú‘†oMô~/¸¸Ø’èQ\fÙ=D*¡ ˆÞ÷³‰Ál·!ž ¨Ç[éçzƒýí%–g÷ioŠÔRŸ™ÄÓ@£)>™P°q#I’$IjZúË[D±gÔˆ>hàºíL4<Ï%5ËuMwÑs|p ‘†`` 1PêbbÀØBJ˜9ÀuÀyÀ1D`·¿ýD훀sƒˆt/[V¨Gg>Ó]uyŒ öV"]ÑmÜVµ6ÍHäÍŸ™^#·|!‘>çZà!:Þ¤¸'Õaðjª×§ÿ­óûŸCÜÌ98„èqb‰ågO ¾\Ó‰úÜJôôÏú·«Ðæ’$IRSp0^I=áKÀ/lIjyK€»‰ÁgÿùLwÕå/Àÿ!Ræ|¦ ÛªÔ¦Yo©°î'£-5€î•ÄÍ–ÿÎÍ>}'…'æ¤mý‰Ži„ju 1Hñ;Àÿ°ì‰€•ˆ^üÏ7I¾×‰ú\Ʋý!ž¨¸ÚÓQ’$Iê?¦•s/Ñ[¨šZ×ëKÓ4Þ¯¯fã3íÖ¨Lõ;&½ß1½¿°·ÑSÇsµó¨šîè6m§˜~vž÷G§?ìƒíN&PÌw½q/o{bî“zÿºVëu£/-¥úx!×бws±)>¥ÑèmºñÂÊMÔF7OKÿHÓWÏy^ËuC’$I-ÆÔ=}ï‚ôóm›¢i "z¡- z–ü˜ Fä’}¾I÷}0ø¬‡A¿·‘N£7 '_|šbŒêåm¯Môzíîr×êr%©; \Oùñú£Ýsï¿ï×,I’¤V`êž¾wTš^ë§õ_Á¯pûk¿%¹/øqsíˆ&½–NÜÐø⦆ú·-(æ¡'!n‚½ßû;x™ÈYÝÝå¾H¤áÔóÚ‰/¥¦v›ç &‚ûÿ œjsH’$IýŸþ¾—OÝSxÿ-"àµxŒ÷#™ÏL&©…ëöÈ•ûU¢Wìbâi«äÖ9nQ*çOuÔ÷"‡ê¢˼2³_WÐ1½M9Im˜þæ IDAT°0móSeÖëê>ï”Úr.ñXü à*"§,u|?»¦Ÿ÷ä¶}Ony3X 8šÈü%â1ò;<­ûåï‚ïo¯§ïrãô½B¤Ñ9žH¥3ø5ÑS½”}ˆÜÑï¦ó({ÌW*k,Å›D7g>wp:¿ç¥ÏnOä]^’ŽÃ‚-‰¼ÔCËÔ¯T9…m¿H¤×*´ÃN¹ÏEä„^@<í0²Ær í8ˆÈK}cªûèt¾ÌIÓï=Õdž¥÷Ÿ}%_¥¦WlÓÿ5ŸH׳q“S’$IR?g ¿qK’æùÒ³¹E¯ r´þœb|óÌò#€K‰ ÷Dðê`àºÌ:ß.'‚b¿Iå¬UGý¾K ”öË˼*ýübú¹ðy"HW-éé© æÁò“J¬Óû¼6”¼ø ¤Ü—búZ¿Ÿ­ÓÏ|ªŽÂûué ltmÄÍŽ±ÀnÄ™)Ä ¦ö<ødš§þç;À'ˆÞ盥så ŠO¤œIôúü8°q³ë»eÊC乿 XƒH™pify¥²ÆP|Š`qã âÆÚáÀ¿ÁºÏ÷yDÐ+›Wÿì´¹%êV®œÂ¶·&n.ŒHçý ™ÏžD ð¸=0 x)m«–r§7Ÿ#nÌÎ#‚þ77:V'ÆE$I’$Iª›9ú×·ˆ@ô}D|/"¸ 0ýšè)úŒ-8*ýü+qàQ"¨öY`C"utZçàüN§çææU*ó.b@Ê&^›Á²ßÅJöJ?¿™kºyŸ¯"ý#nL%‚ž;Õùý¬š~æÙü·«ovÃqòiŠÁÆrÖOû™]oe`@:–§yÃÒq´&pðm"ø¸*0‹èáüRšþü_šw¬V²F:ž7KÇ?DÚ©§×k_'zø–_|­LycÒµá–ôþJ"Ø?8W•Ê›¶ è¿ ÕïT`«t­ƒîÜ]þ–+'¿½Õ‰‚+fæ@Üü[@<•ó“N”{ ‘‡%â†ÊŒô™¿ŠË@¿$yÝ$I’èŸþR¸W ¤«ïÿ±ªåû9(­÷­ô~Çôþ¢n¬‹þþ{ž7«K)zÝ[¯PúÎÔãz¢wûº©¬mº°_«—;yî·îíDJ©Tv¥ïhißõLâ‰ÇÑÀ_rË6#n®H’$IMÅ@y‹(ö’Ñ6A·µ£çºÔ8ÚýÒÄ ¨ƒ€S¨Ü›|?‹èÙ=øpMZ>‹bîõWkX¿VÓ‰ÞÝ»7ƒèÖbnZÿ\à "%ÎVÀƒDú·1ዉÁe?¬RÞKéwÏ•ÀØ´]­Dïÿ»‰›'rÑw¶¼é;˜™^£“u*¥RÙ•¾£üqQÍ­Àv,èߎâàÆ’$IRÓp0^I’$uÅ"Àü,ð7àI"ð_ÉÀJD¯üg‰Àð÷Ò²·ˆ¼íO)VÆWY¿Vÿ ž¹”âþ:>{œŸNÔMó7Þ&Òô|Ø·JYû=Í¿GíAþjõ(¸–è)mË{ƒHx?qÃà‰.Ô)¯RÙ•¾£RÇE%—_ÎÍì\íi+I’$5¶iDNÒr|ܵ®×ì 9W7NïGÿCô´úiš÷Yà÷ôÞM£/=ÕÔsÇsµó¨¯´SLÐ]û{¥S¨ÿ)u}êIÓ‰œÚê~µœ—µžçµ^7úÒRj¨ÖõzÛ¦ø„™×ÀΙ÷ÇÒØ©9ûûõ@’$I}ÈÔ=ªöOĨÌû“‰^zŸJï×'zKmKõÇÔkñ*ðoÀ£æýšèå5„ŽÜIê¿JûõÊ_ŸzÒp`-ª§Å$õ­Ýsï¿o“H’$©Y™ºGõø41Ð[Á ©ÿ±óRVÖž®2ï}â‘ýOúuHM¡ÔyÞ×§ž2€ÈÇý"•Í”Ô;Ú‰ÿ¥¦v›§ÏÚÇïE’$IêeúUÉÀÍÄ@iï[¿¦“ˆä.ɬ(1ðÙ‰<ª¯yP F¤åoƒ-Þ¬J¤šžŽÇwÓ´i‰y…'PfùõH g4p1pæ"­WÁQDîîÄ •#Ëœû¥ž4«tm)u}:øñôÏ»ÀóÀæÀ‘ÀËDnç/Ôpm*\捻²¾™®}O¦åƒˆ\Ø7OI­æYúö ÑWÒ¹Wjzů§ÏÚÇïE’$IêeúUÉ8àq`1° `Bôf=¸ŠŽ=ZÇ~IÎ.#r- Î!|뫇=cIŸ¬–ùy…À+Ñ=©‚$u¯k‰›ƒÃ‰žú§¤ù'"n ^"b|±ÂyN×–R×§qÀÖ©>kÁÿÛRÙ§¦:U»6e·ýÿRý.HÛ˜ lü‰0rL'&I’$I’úˆ9úUÉ8"¨0žúLöÊ­?–ÞÝ•Þ?MÇ|Ù/¥ `&ÑKvpf[•Øþc%êµ9p‘_ÔpÖ#RÛ ðù“‰k§¥õ¦©¿*çõ\[ò×§qÄ@­…]ŸV$ž€è¿|צs‰'Hû5–Ãä.â)_ùÕ«lL 4*©ñ<”~÷I’$I=Æýªd,ÅàY66„Þesj·½\“™·%`+Ø/ý£3‹Hq‘R#_>æmFôºý“_ÔpövÞ~F¤¿Ù²?”ÎûÙDjœ™Îsê¼¶äË ü6ó~‹ÜûÍé8n¥kÓX:æþoKÛßH d_b$pH‹íóx¿võ“Ò$I’$õ({ô«œQéøø[z?øïÜ:Ù´=ë§õŸËÌ›@¤ñ˜ |ø"ðq“ée¢'ïrDà,Û«·Ô<ˆ ÆuÀ\¿"©áÜ™¦BÎû€7{–X¿ÜyN×–üõi‘·ÿùÌòñÀ÷3ïÇf¶YéÚ4 XH%V°Aú¹#ðÇ4=âW¯rh íëÙtL(5¢klI’$õ{ô«œqDÐkiæ}¡Çì<"öš™õÇ9«³¹ó'd>³1€æÓDþëË)>ð‘4-É|¶Ô¼u}Óýz¤†³+Å øP`e¢×üãDnþ iÙ `g¢g|©ó<¯Úµ%}—[e"`ÿD™õ+]›Æ•ØöØTÖTâÆãMÀZ~ýRŸ˜eH’$IR0Яr ~ˆtÃ騫õ÷ÀÇ2ï³=d!âI业èe;“ó%"¶˜üxx5­_jÞ…À÷(>e ©qL.nîÎK¯¤szâ&b©ó<¯Úµ%}ÊçüK ú» ó{/ûA¥kS©ñÆd®7c ÜL .©w · $I’$©9Mö®°ü^b€Æjj]¯•mKäÙî-_®µÙ{åx®võ•v"8ÜÞû{Å[%5†ZÎËZÏóZ¯}iiúÚÕõ¶¥ø^«8ÞÓEýÀ5Ôž¾§»®’$IjAöèWgÝG¤ßè-WИÁgI’Ô7êéÑ?šl[ËÚø  ·ÕÕzÜû[÷8à4I’$5*ý’$IêêÉÑÿ<0Ì&kYõÞ`˜lHǧW/!Æf1e”$I’’~I’$õ´å‰º_ÈÍN¤!Ù 7ÿBà'UÊÞÄm¥¾u(1†KÖ<àÀ>6$I’‘~I’$õ´¯=ª7gæ'¨/çÖòƒaçÕÓ£?Û£»ðúà`p10wÁáÀtbÐð×€£2Ëq¿“ê0…Žr#‚ijˆtAWÔX·S;ÜV¥œã_æÊ¸€¸9RÉaÄ8<ó‰ÁÓ7.ñ½•ö»–üï•ö³Ú¶:ÛV•ÊÎ÷ÚßX”^ß HÇÚ<`B•}Þ¸§Ä¶ï&{:K’$©Ùc¨k6†Ø êo¦À‚zÞ`+›AjëØ=â`àhb`âwý‰ åàgÀ?¥ëá=Ę83‰¼ö?>–ÊxøLz}p0xØ+ýî*eàT`Wà`Ëôˆ@ÿÓ,;ðÀÉUö©+=ú“ˆ`ð`à·i{§¦6¹ˆüþ9Õ?; ó¥ÀŠÄSKŸ¹Û ƒOI?×'‚Ñ[×XŸ‰éo˶*åü"Õs(07}ö‹ÀnU¶ñBÚÆœTöƒÖ€uµÒ¾œüK•ò*íg¥mÕZFgö£œIÀ“™¿Û7­°Ï«¦ùÏ•(ç`œ—I’$©çM£ò€­÷gÕPN=ë-urê©»Ó³ºñ<ê+í©mÚ»qOðXsrjÈéÞn:Ïk½nô¥¥ÔÖ{ºÚzÛ²l°¼à[DïøÍ3AÎQéõFÀ§SÐsUà~ŠöGˆžíˆÞî…€ÿIiÙ¨4ÿrâfA9ç·¦×%n:\E1Ø[°&°„bPv2ð"Ë>‰z|íœïÑŸ?.&SL+4 xø LÏ üƒŽ7¤¶þž^¯œê>ªÎº-ÖÈÌ«VÎ}À~éõNÀKuwÿL<‘Ý~áÆÉ"ˆ^I=û™ßÖ]h«ZË.¼_TaY¹}Þ(-k+±½1À‚:ëxMšzóz I’¤dþ®;8ÝfP7ºÕ&èÕó÷2›Aj8ØÝf ¢÷÷VÙÏf–¿D1H<“èq_H­³ä,&zá nL n Cê\fû_§”|›Y>žH½²kfÞ"°?/½¿%My]éÑ¿”HÛS0x:"…ÌîÄç7îOë,<•ùl°&µO[¦mjµx;ó¾Z9×OQ\EÜœ¿¶†m GÜHX!·ýB*¤…tLcTJµúUÚ]l«ZÊ®µÍKísaÞ≉¬¡éø$I’Žþ®[D}9b¥j põîù»ÈfÔÄv¦²ì ¸ûøA×AÀ!iÙ^ÓÙüø&°‘¶æ¡Lm”ϧð;â ˆ@!ýÏŠÀfDÚ™‡3ŸùÑ«ºš®üýÕFôè/ûۙ兛 #‰ô<ëÁø%iýR½ÞgP|Zà•.Ô¯Z9×? RÌìFq4ð—͈ܲ?’$IRÃq0^I’¤æ5‚ò='ß&û««“‚öwý͈¼ú¤òn ÒÛ¦U€íJ”¿-°‘èÍ4K¤?!•¹ñÁ«™é£À£5ìÛð.¶ÍÄÕS(öŠ_Ø™¸ñ"wü‡iÙà:༴ï9ÞwH¯ç7éŠV&:Õ|¬u«VÎÛÀÝÄàµ'n T2‚ÏL¯¿ÑŶ«T¿Z·Õ™¶ªTöôTæîé»;<³lÅœüµ¸µÌ1½ÅÁ’%I’¤†b ¿ûŒÆGy]6Wk-ëötÏúR ¡à8b08I’ºËT"à^@tÃô;bÀÛ׉ÁpW!ríHïw%›…HW²2L~ØžHÝ(ß™eó™·ÁðÌŽOÓgˆy{*ãiŠ)z þ‰òOdu¥Gÿ"Pþ,ð7b Ö3Ò²Àwˆ`ú<"Wÿ¾™ÏœþžxŽ,ßÚ²à ô7ÄôTÆ¡¬cµr®%z¶×’¶ç àl"ýÐ3ÀÝpl•«_=Ûª·­*•ýbèKÓwsfÙ[ÀÅDÊ¥ÙéX¬ä2à˹yCˆñ®ö²"I’$õ¼¾Œ÷,›½ªz‚æ=`ï©@gê<‘e{+IÿÀÞƒñ–ÒƒñJꟌwY•ã=•t. ‚£Óüµ?Áìˆ^í…ûDj•Dñ#2å@Ü X@¤8ùI‰m~9ý>’›ßFôŠÿxýinùi? ùò?F€•ØÆÙ½ðw‰Z×tìq,—ËÁx%I’Ô+ÌÑߺ߻ÿàö­CY¶GØ<àÀÇmIR7:ÒOŒ½üKnÞwÓÏ#ÓTÊÙT²_MéžÏK‰§~[bùÛt|:àA:æZÏrŒ$õ¤Ýsï¿o“H’$©‘™º§ûd{‡^@ .6‡xx`fýÉǔç½áŽÊ, üx'ý;X)³|Xúçyñøñ5Öí@àeйEË•s<ðË\VÙN¹}º“x ~^š&‡=ýæ½7®°nµö(g b ½yÄ£ùÛç–×Sn¥u;Sç]ˆAäòîVõt’$©ªáý¨®í™¿òS{ƒn£7êÜHÛ•$I’ú5ý=g0‰²oDä=9-\ìI„7'zr\JäÊÝX/­Ÿí‰7ø°>1€Üe5Ög"‘'÷ߪ”ó "=4óÙ/R9l¥}šDäÂ’¦GR}†Ï7Ê­[­=Ê™BÜÀXø$ËæZ­§ÜJëÖ[çU‰Áàž+±gRûI’¤Ê:Û£ÿYzÿ©ÖW2'ä§Wt½QçFÚ®$I’¤Ò—9úó=úó9'ÁmˆàöûÄànCse&['3o"?.ÄãîK€Qu´K¡>ÙGß«•s°_z½ðR•mTÚ§j¹pÿ™èù^jÝjíQÎÊÀ‡D=û,ª±Ül=êY·–õ7JßG[‰zIß‹9ú—UOŽþ+€­œœœšvzsôçesôß"?ïn±ýõgÿüù(æè—$IR/0GÏþãžíu4âÀr³‰¼ŸGç§îOë,<•ùlü…èÞ–Ê«Ç"ï-5–s-°pô½¶Jù•ö©”ƒã€5ÓûʬW­=Ê‘~NÏ})·Þ:T[¿Ðq07÷Ù¡8~BwØ?M’š×í6AYÃ[äg«í¯?ûçÏ^’$I’ÔÚšl¦'R>(}/ÑSýÄ*åtf½M'‰ï¦D –Qƒý»9î7Ε1ìîp"…ÎÊÀL"½ËœÛJÕ7 öÇ—³u«µœ5Òü¦Ïn“ö©ù}Ú„z¶¿0Ø‘ÈS¿ujË•J¬[­=ÊY9íß(ŠÁþ]€Óvª•›m³jëv¦Î¯»ÉÍ?ìí²:N»ã<ê+í©n£ªûCñ&¦Ô  »éºÑ—–éåîëâzÛ¦ë}[ g'x*¨ÁzóïÓ‹×I’$µ ƒa=ë à«À àŠÓuˆ-w‹‰i?LËæ×çÇÁêµ(漟 Üœ , ÒÈk¿oæ³=Ÿ#‚–w[d–D¤w™žÊ8´“u¬VεD¯ûZzvWÚ§·€‹‰^ﳉt=gi}žžÈ”“_w| íQÎÄ ÃïÿSb?ê)·Òº©óe,;8ðb<„·<}$Iªjx•å£Óïe5¾jã95R=nvμ?8ͯP’$Iê^}9o#þ³¢ÆvcîÅcÓ{ñ8íìyÔWúàš’¼nÔ«'ãmÇ{ˆ7¾úÛ9¿Ýjõ˜H ®›5xƒò7ž®ÁÁx%I’Ô ìÑ/õÝé8˜ä÷‰§"$Iêï†ÁÈy¹é¨Ì:S‰ts€?©óŸ_@<1xb‰m4 Óiö‡WçæÍ#R3îcóH’$©/èoí%þ™.Líýhý¹>’$)Œ'Æâ’›ÎOË'ƱÙ?Í_Hk7+óù·Ó²AÄM3 2Û¨–£?Û;»ðúb`æ9i{3ëN¤3œ¼FÇ›ƒégS€•2ˇàYDº +j¬ÛÀËÀmUÊ9øe®Œ € «l§Z½Ëís-íUN¥¶8Œxrp>ð°q'Ê(§\Ù¥zí/J¯ï$ÒOþ~œæ•H¥8Ž=çwî)±í»€Éžö’$IêKú{Ƴæ jË IDATô~ϬWJü3]˜^éGÛèÏõ‘$©Ñ Bôô@ôàþXšRZ6*Í¿øY™ú\Eåàì=_ ¹¥>jz=,•õÑIe2ð"pB•6Ë÷èÏ “‰àpaï7 †æÊ üƒbZ!€m€¿§×+ÁâQu|ï…ú¬‘™W­œû€ýÒ뀗ªl£Z½+ísµö*§ž¶øgâIƒüwÕ™ö¬µìÂûE–-¥xiq³«pÎ,ÚJlo Å›Tyæè—$IR¯0h×¶²Ô†ØÝr^®c3HMo¥{×*ȧ¦¿Q ÁÙg3Ë_¢(žIôàœÞ¯Gù‹‰Þß'Ïii½)DZ˜RÆ©SöÌÌû)ðÍôz"çþˆ^Ò¿þ˜‘ùüîÄ ‰+Ÿ>nIÓÙu¶ÉR:>ñ7â ³ÓöŽ&Ò =N¤Ë¹?­³Wk¯rªíÃÁÀqÀšéý (ƒ.”]ë÷RH µbº¢Y™¿Óææ>34µ§$I’Ôg ôwÝþi’ºÓí6A—ÏKŸ¶‘šß}À'm†’v$zÌ—ë½ðuà£DPupHZ¶Ô?ø œßXx(SFñÄ@ÞŠÀfDïñGÊlÿuàišÜLi¿•ùüÀ«öqVmÒFôP/¯Û)ÞX€â „À‘ÀωÔ1oÁßvн»³fPìýÞ•ÔÕʹžâ‘ÝRûVR­Þ•ö¹–öªwV#R íHä¹ßšxê°;Ú³RÙ‹)>²˜ŽOQ,­ãû™IŒc0šH9•µq£D’$Iê3ú»fÛP=d‘MÐe¤sTRs:ŠÈ¯­ÒFP¾‡ñdàÛDŽ÷'ˆt8/S Úß™¦Bÿˆ07б‡~9[Ô©5ÖõÑ4 Î|~>•ƒüPŽ~€3ˆV§Pì¿‘~å."<Ÿxz"H~p1€ðl"{!§ý\à&à\bÐàÄ“ÖY·jå¼ ÜM Lûw"/|%Õê]iŸ«µWgöa pŸ™^£“íPJ¥²§§2wOåžY6‹bNþWkøŽn¶cÙ@ÿvT–$I’Ô z;G¿Ô—ÌÑ_Þ ”î%(©yÔrž·rŽþIÄ·…B7$òCôœ¿›ˆ'òì/Nïw%zÒCä$ž¸1ðià-¢÷=DàwgJç+?ˆÜ—s ðOÄ †‰§ æR à ŠƒïVr|•åùý7-^!‚à?¡˜–¥øsš?Ÿø™²½Íç)£ŽÈ,FÁß#‚Ç?­£nÔQξé{>¶Æã«R½+ísµöª¤Ò>œ•¶õ·t”Ë•_o{V*›´³ˆZGæ–]”¶3øåóùCÜpøkn»C€7(fgŽ~I’$© ô«•è/Ï@¿Ôü ôwTj0ÞS‰àü¢÷÷Ä4m"À;xúéнù/ ‚ ˆ^ãGäÚüõ´ì5"ð[ÊÅD°t^fš ¬’–Ÿ`Aš'S0]Lù|?FôlD}9úËÖe{ÕëFâ&WÁ±ÀéÖ7Ð/I’¤^aÚIR£™Nô*þk• 1 äá}\zë#Õë´4å½üKnÞwÓÏ#ÓTÊÙÔ\ÿzšÊ9–Ê=Ò+}öAŠ9Ögù«ìž{ÿ}›D’$I`9›@’TÅ«Óuô´áDoãgzp[yÉûºõÔGRéó´‘µÓñ©†ìÔÞ¶ÑÛìËíJ’$Iý‚=ú%©5 –tâs«kO÷ÒvÇ9”öà>oA¤'é­zTSK}ºó;•šE==úŸíƒ¿{_!ò·÷ÇmTj¯ÞدFÚ®$I’Ô/Ø£_’šÓÀÀà]à›iþQÄ@… €»ˆ”1£ÓúsÒô{`c"}Ír©Œw‰ÀO1æ4bàÃ_SìY[ïvóÆ/¹Å_vÊ,ÜJäè^ÜNqÄRÛ^ŽHIR(ëKi¿ž¬Ò~ÕêQiŸ*Õ±–ú”+·\ÛJ­j¸M I’$IÁý’ÔœÆÎ%Ä“ˆÜÂÛo—ù¶÷®® @¤êy8ø°g¦ì³€mRù³€ëˆàõ×;±Ý¼1ÀÖÀÿ%=•ôŽ´|(p1ë*À-ÀaÀ÷Êlû;À'R¹‹ˆüÄ •T«G¥}ªTÇjõ©Tn©ý“òvl¡}]­ÅöWýÓHàM›A’$I=Í@å?Ê·²ÔÀ||]•Œ#¿Kï‡'üiiÞàÇéõzD€°˜ð²PÎc™r×&ú3Ò¼ë¯ur»yc‰€øéýÓĆ‚—Ò0“¼.³íU€o›eêú["X^M¥zŒ¨²Oåê¸F•úT+7¿‹=ÌUÂ-¶¿ù•«¸Ö&$IRO3Ð_Þþ”îm*5’Ûm•1–èE^°°"ðPf^Å þ^DùTà7DZ˜™Àxàæ\9P TCô`§“Û%7K`¿Ì¼-§2ï÷#n4|4­?8¤Â¶Ÿ .Nõo«Õ£Ú>•«cµúT+7¿RÖ}éx‘$I’$µ ý¥íbÛ¨ŸXd¨„QÀ Ä`Š#€蘂'ëÎ4òËœG¸³AùáD^þ¬]‰žéÙnÖéç‹™y(Þh˜ |ø"_Ž0÷±2Û^˜û·‘§+õ¨´O•ê¸]•úT*·ÔþI’$I’$³Ë™kHêÇÆS3ó§˜æQ¢—ù§ˆ40ÿ‡Jÿè¿2ð ð‘4-É”óp°ð ‘ÃðS"Wv=Û]š«÷Øôùìü i{[Ø>M¤åù/"8þ41¶@~Û/§ O'rÝoœÖ«¤Z=*íS¥:®S¥>•Ê-õJ’$I’$ÑÓP’Ô\òyõî&zèß,^ö ‚Ù“€Òü?§õæ?JëÒÍüøð0ð01}~A'¶›7†v¬NŒ—òdz51íLà6"þÓD®úRÛ¾ ¸‰¸‰ñXÚö¢ô³’jõ¨´O•êX­>•Ê-µ’$I’$IMi°w…å÷gÙLj1õ÷ÕΣ¾ÒN<ÛkX÷„´ß’šW-çy=×¾²ضדÔy=$IR§Ù£_’$I’$I’¤~Ì@¿$©µóÊLí6$I’$IêOŒW’ÔŠ^†Ø êg¶Ö²$I’$Iyú%I’ß߀ým©éÏóE6ƒ$I’:£ý#­üêÕB†´ð~{®KÍkÛßüÊ%I’$Iå´b ì§Ös{ îóxà¿z©©ÝgH’$I’Ôzþ]0]‘ZS«=~>p™_»Ôô>° $I’$Ij½ ÷\¿r©%,·’$I’$IjËÙ’$I’$I’$õ_ú%I’$I’$IêÇ ôK’$I’$I’Ôè—$I’$I’$©3Ð/I’$I’$IR?¶¼M I’Ôðv´ ¤–ð0Ûf$IR½ ôKj616ƒÔ¦‹[d_ïðë–ZÂ'ûlI’$ÕË@¿¤f3’è '©ù^i¡ý5(5·¥6$I’:Ë@¿¤f5xÕfšÒºÀ6ƒ$I’$IÁ@¿¤fõ0ËfšÒP›@’$I’¤¢ålI’$õ‚S€¦×mÀ4`ãÙ÷éÀ„h÷fÞ×®S½ÝN’$IR·2Ð/I­! ü0øi/Ö£§@­4”:ëÕn:;SÎS.-%ÆXx±ìkW O×ܧû¨^Ùvïí}íM]=¦z³$I’¤ng _’ZC>r2ð$‘å€^ªÃp`-à™N|¶Z`¬3žá™ÏeßÏo'fÖ œ™¶1x˜¬éá¥~bõt¼>ÝGåôf µ3uÐCu<¼ßßAOµû€nÜ×þÆ@¿$I’ú5ý’Ôš> \ßËÛCÉÕù¹ž Œ'Æq˜–yÿ60Dö7†÷O ükZgkà`='õOÔ,¼›¦ÂXMG#npÝEôÈ ÜÌIÓï«”“ÿó»À[ÀëÀ—ÒgŸLËnά{6ðð°°˜¸ùFÖñÀôÙ)iovb[gçgÊ]˜Ÿù;{,0µŽznM×£…ÀíÀªiÙ¡iÙ3m»SíÞÕ6ظ¸8­?Ø5S^a_+íÇ` qã·`Kà J¿1hO¯¿JÜ-ÔçØT÷ü1ÕÕvjŽO¿æ¿ÎµÖG’$IRLö¶¤¦<ÚÓ?ÓíÝ´^«)@z®O-±nµ@N¥ ÀÁDP~^:ž¶Oó¿ü2½\ ÜH} t`iã´%©¼J»B€§\0.ïhàÎÜû[2ïWOí´pE*§­LY•‚B¿.MõØ8x˜ |¡ŽöWs]–Ûvãz•\—›wðñdË@àràgiÙ#é3Ò²U('ï?Óùµ&° ð§t~\œ–^Ÿü!][†ñž®ã…Dú²Ï¦÷;¹­[€¯dÊ <”yY*·ÖzmDÜŒ®­÷Oa\ÌÌ\WOþXG»wµ ÎN×ÕÉD°ü"P^j_+íÇS©Œ‚ßß(SÇééšÙ–~g½lšÞ¿Œ+qLuµÎJ×áµ€•€_¥kr=õiôë$I’šŒ=ú%©5Œ'zÉnCôbBô²ÏLnÖ¾O© †çøuˆ ÉaiÙ·ˆ@Ö¿§ò?K1x2†Šl@Užö ø'_&‚2À—ˆ€Ò‹D é—©¼Õˆ^ôåöâÂÍD }ub€ÅR&åÞ‚sÀïQ¼a±/È_Z¦¬3‰žþOu\Jô-ÔmëT¯5RÜ–öcC"uRí/uå:=æG×½‰›T‹‰ÞÈ[¥åëAÚiÙƒeÊÉ[#] ö#nT½Gr§–8g× nòퟮK³Ó±?µ‡ëXXç\âF\á¼ï̶ÆÓ1å˸Üûl/÷Zêõd^B«ïgÊ:›¸ Ÿtª¥Ý»ÚcÒú·WÁðÁ%öµÒ~<œ®sŸ"ç—•©ãìtýÿLúðdªçÎÄ —ø=ЕvZ›¸1½'ñ”Á"â ¸‰uÖG’$IêUú%©5d 㩈¨È)¼YƒZbPåYŠ©qƦrî"zSžFÄ«òj Øö©\0.o<ðhîý±D:Ÿ§Ó>}˜DôX}´L9Õ‚BãˆÞ¡÷¦ö|Š(ý0½’ŽO)Tk©³òçþÀŠÄ ®Ùiº=×)tvMÇõÏ(>¹Sí²è~53o8Ë¿/³îŠAמªc¡×w±=F½ÂŸ*s=j#ÒÒü&³î–™m×Òî]mƒ1À ™õ‡7Cç—Ø×rûýç7d—©ã¬tL\@”H-UO}$I’¤^e _’ZC!µúËr |ðfGŠi ò  ÝˆÞé¿Ê,«Xª5`WX§\à/kE`3Š7 ï7%6kO¼JÙ_©°íjA¡±DoÑ‚-rï7§ãÅÕÚ_êìß|[²lþÒ1V˜V¶KËïLÇ÷fé³”)'oÍt,ŸÎýB uTš÷·ë.G<óD×q°q3²+í±yºæ-Êìëö™úo@ÜVc½&ß!žZxÒá1`ýTþs™õ³O&Uk÷®¶Á0âFê{™õ÷ žÀÈïk¥ý€b "5εÚd6ñTÔHâ&óâfÊ–S¶e©®¶Óð×Û])¦«¥>’$IRŸüÓ'IjnÙtìmšW-S)x3‚ŽÁ“¬ Òω” [g–U ,Õ°Ëî_©`\Þ–D@ê™ÌûùtìáY0ƒHQTN¥ P!Çõó™eãsû36ó¾ZûKõ‘4-ÉÌ{œJOHïéGÚÒ1\8o‡+§ó¥T9y/ùÃG§u@Œ·‘M_óñDÏóÀ'Òò•ˆ§Y6ϬÛSu—¶ñaÛ£-­·|z}ñtÓ™óûÉ ßAÞÄDO§ëàåéù4Å´8Ù:OÈ\Ï«µ{WÛ`Lªû>éýöD¯öÿ,±¯•ö£°‘©Ž'R>-ÄM壋Òû9Ä'—eÚ2{LuµIÇäFÄÓµü§uÔG’$Iêuú{߀çÕ[†$•“ €Þ— ôW äT ÞL%‚'…7$zÈC^žHëÜDô”‡Ê¥Zv…ý+ŒË›@¤>ȼªLù7iþ3Õ "@tq££RP(H[9-Ëçó~¼Æö—:k>ð#¢÷yá†ÖÝÀyDš¨iÙé\š<æÿˆô–2åäݖΛ'ˆ›X…ï/äÎYˆ§wnLçÉãDoð÷)ö2ï©:–J Ö™mÝ—öåÙ´/sÒ6geÎé'*|yW7g¦v|)]_Óñ¦ éú3’bp½Z»wµ Æ×ã¼Ì%Ý{S Þg÷µÒ~¾ã©Ä€äÕndÎ"n¤zýÏ!nŠþ¤ÄﺡþLÿ&ndOLßÿ‚:ê#I’$©‹¦¥8jÑF ¬8-ýãõk¢W&À¡À­Dþä·ˆ ÖNUÊ;ŠèMº€È?=2Í?È_=x—Èÿ\j^¥ú”Z_j„ó¨7µ§@C{7­×JN¡8˜ëH"À²B™u¿Fä„¿™Hó$à(X›‚Ì#‚^§Ð1 rjºn. ìKÔ¡ðþA¢/DúŸ×Óç^£cÀäRŠÁ³jûwÑðwàˆ2Ÿ¹˜¸I‘}Y…6CñÞKûþ,1HnÁ·‰€Ö,"ßõZ™ºý(³Þ¶tL“±\ªë:5¶¿šïz°4ݵ^w@ú›GçR¢'{wH¤Dû¸Íêõ@’$I*¥žåYD¯¥µˆ@Ó¯ˆ@À%DÀfûôþTàÊ:‰èÑYHÑp9‘bP®¹Ä€Ž…lJÍ«TŸRëO&=ö© õåyÔ› ô÷Žî äÈö÷zP]«öþ‰â±OoâÍ­Fuñ´Uwø.ðs›Ôë$I’TN­ʵ‰Àùš™y_&z©þ‘9.³ì ”ô zàÎÌÛ†bžÏ{ˆYùyÕêSª ©¯Ï£Þf ¿wtg G¶¿×ƒêZ=°w8ñ$̼ô·Ó¿{x7¬ÙÄ@·]1‘x2ê^"¥Ž¼H’$©›,ߢû½ÑFfÞPàŠƒœY¶%ås7ï¬<”™×F1•ÅXà°Ügòó*Õ§\’Ô¶¤cjÙþROúašÔø†uC%Æw‘$I’ÔÍZ5Ð?œè…Ÿµ+ð[¢§ÒòÀs™eˆ|É¥Œnö,±l‘ûÙ*ó*Õ§Ôú’ÔS†Ù¶¿$I’$Iê_Z5Ðÿp°1Ø1D@ý§Ä »S3ëOHë—ò8prZçQ`‘cöwÀ¸e•šW©>;–X_’$µž­)`-I’$IÒÿjÕ@ÿŸivþ@ ü¶€H“óXfÝÕ‘À“eʺ8¸…è‰9 ¸¸ê?–[¿Ô¼Jõ)µþÇ(öö_àa,uÊ&À›Aj8o¯Ù %ý—M I’$Ij:ˆ¨äyÔuÝ=øæ½i=''§ÆšÎêƒëA_rPMI^7$I’ÔeËÛ’ZØùÀé6ƒÔ0nµ $I’$IªŸ~I­l‘nKRcøÀ&$I’$©~ËÙ’$I’$I’$õ_ú%I¥œü°¶;˜@ L> ظ—·=±÷I’$I’$©G˜ºG’TÊÀ]½¼ÍáÀHàib ÁQ½¼íµgz Üµz \I’$I’¤ÿe~IR)[Oôò6ÇÏï÷ÁþŽ^ö@¹/ãAH’þ?{÷/WU.þÿsHFHH( í†"!4/¸H³½(êUŠ|¤(^šÒ/RDôÚAi"\@¹J H»H„*BB~LŒ> ¸––ÏKËO>|˜ \Ft |£BY“ˆ<÷?ÎþPGY“(]E0x Ýÿ&ð%àsD0}Cbäý|àÑ´¿©iÝï§}Ì«P·jådõÞ øïT‰@<À±ÀnDÿEàÌ´¯/×Qî4`"Àp2‘šèRààãÀÌã/I’$I’Ä(Ê=ê\o‰7omxÛ£ßG}m|:†ñ=´ÞíÀ÷üØd4_3÷Ü1”ó«§å«å–ïÜY¥¼©DÇA¾ü%À:ʺ øTºXMŒvÿ—*ûû51q0À¿#îU9ÎZåÜEtJd>Ü”î!®>˜˜[þA"€_O¹¿$ÒíZ¶ìe¢Sa§aÃïËžþHj=7Ú’$IRh$uÏ6—|4ÕûÃÔ=½c ˜Ÿ¬œ–ÚoôüCD.ýõ€å‰´>Ë–Ûx—˜l·ƒÈgÿ°qe}šÒÆîH÷wHõ›œ¯›«ÄHû·‰Ô8Ÿ¨qœµÊù4K§"š l™î„˜ 7Ë¡?˜È«ßQG¹wäîϤ4qð®”:ÖO¯E»3uO÷דԼü<$IR—-gô{©=šuYÚêUs4Ô›Oäçîïu.:žÌåD/s$p’§ªšÔuÀ•DÊœû‰4oQJEs'ðcbäü+ÄÄ·; +”5 ¸„È_?ø9Ñi4½Ž²Ê'âÍîßL¤½¹1­7•Î o©sž¡tå@%µÊ™Diâ_€U±”FNßš¶š¶}‚¸‚`IåfÇqpNú»b:î»Ó6Π4¡°$I’$IR[sDߪž–mÐDu®'пð²ç†/iI|ôGô÷g©EúÒ àYà6KpD÷×[úó „ÞøñV |OëOç@o¶i³ ÎpD¿$I’ºÌýê-cÓßǪ,oÖù!..{n>‘{{O_vµ¹ID*ž¾t<‘çn›_Zf'æèPI_Ù=*Û‚H§v}î¹3ýéÿƒ3$I’¤†èo®ŠÙý}ˆ¬s³‰­™ƒˆ<Ð €çCsˆ©#^%RêœO¤ÈŒ ‚س‰QY4X×݉É3?OŒz@ÁoÈÕ}_:§Ø(ªSÑòjjµC¥:çs~×jß]€Û*”s æ×–6í£}mAäÆÿðŸ6½¤3Ð&è6gH’$©­èo>ˆÜÎ8n—–!rboœ~ÌdÎV&&€\+­Ÿ¿|ù|b2ε‰Õg7P¯SY;¿#&±\L¤µùh®î[é|>UgŠ–WRÔ•êühí; X“ÊW)1™w­cëÊ€ˆzê_O] RÜäNLÎþàšÜóO¤ïy™™é»R¥sà@b>–™tN3SÔ¦«¤}¼‘Žû§”:>ê­88C’$Ijj­˜£¿ü‡Sy®á)”&ÍALLù`XY9C€w€5rÏ}x:ÝNæ't¡nGNŽ-øa½$ý¸«·NEË«©ÕEu®Õ¾ë¥åö9‰Ê““úþè9æè—ZŸ9ú»¿^ù®r111õhàJôc€÷€¥Ç+§ÿ¡™‹€ËÒÿï¡DP÷¿sË/O·•‰àï¨[öø­:ë p51ÉøJiùtÎ'¿˜^>Õ}j•ý[V—_+P æ×³Mµú—סZ]ÇÁÿ,õÎ@"@¿°8T@ IDAT%‘úf18hõôá¹´ÞºDçÃrUÎSˆÎŽSˆÉØëmӫߦcCLà~BnŸõÔgTªÃ° çć€ü<$IR«ñ²à泄µ•™A)X=ؘ ógÀÀQÀ]iÀùm;ˆà~öû#•׈å€oó— Ö] ÌÊ=.ªSÑòjjµCQkµïìôw(0¯l»a´ÏD„­dl dHê†Ú-ãX¢|!prú|°ˆèÄߘFŒÚž–¶B¤Ô[;÷öTàÒô|8ði" ûFZ~w/Öu8ðIbÄ›év*G¿ÿ9wÿ àÚ*û(:¶Ì‰Ä`…F¶©VÿrÕêú"ÑÉöyà\bòÚW¿¥åóˆQò?QÁÿÁ´Ý{UŽùÇé;ÛåÀÁé¹¢6Í–¯;¦“ˆQý'éë©O–ƒ~…zÍÃ9%$I’Ô‚ ô7ŸbdbŒ¼œ[>5݇¿I?–f¥[ã‰K»Ë½LiÔã³ Ôç=`gb¢³YÄ(¬zÕ©hy-ÕÚ¡¨ÎµÚ÷u"ÅÀÄÜßÌFD‡‚šË—ÓMRÿq½MÐôúÛ „®ÖuLú;³lyÞ~À‘ÀjéñòUöSÏà…FDÕŸêz!‘jç\`/àrËn#æCY?ÝŸlGÖo«²¯Å”H¼I)PQ›fËóÇôLÙ1ÕSgH’$©íèoN§¤cƒã‰‘])n&¹G—ag£¬æ—~ÿøVú3ŽRþúyÀ•À€¯#¨¶$./r?‘âæZb”ÞuuGQŠ–WS«ê©sµö%­¿Kú·kà¸Õ?ìâg Ô/½e4½þ4(a‘>fPº?ºº¾’þ®E)0Oµ 1—ÐND€y+bD9©žy]¼PÏ6Em]O]®Î$&Uÿ$Ñ!¹˜[ibôýb2ÛW4¢¨M_É=—Ó:_YO}œ!I’$5¹vÈÑ_>éÚ¹”FI'r Î%‚Û>œ+kpúô2،ҥԗ1_J\?øUuØ:ý@û(•sâ¾[¡Œ¢:-¯¤V;ÔSçjí Ñùñ÷²ý %.{åû£WµRNnI~dZ5GÿEéøªÄhý“Óò5ˆÔ0+Aê¯éX2—çQJ­2Ø1·ü÷Àÿ)^¦ÿãµ,ŸþŸ1íó·,£¿Z]!râÿ¥|ò·ç¶—¶ß4•}QnÙ˜´lÍ:­Ú÷¤¢mjÕ?_f­ºfÎ#æ/º¹ìù‰é;Ø“éñp">—èD©ö}5~¼Ug›fË/¡ó¼'6XˆIŒ¯Ð¦Õñ]ÒÏI’$ikÅ@µÒZv®HAŠÌeAß½Ã@¿¤Vü:_ÉØH ¿¨MG9û篧³tJ¤¢ú@sÎ0Ð/I’$%ú¥Ö}è—ÔŠŸ­Øk¦ï*Íþ½ª§ë¿‘ºqx }V4Ûà ý’$Iê2óS«Èx`z•eӨĽíP/I’¤ftð;êŸC ìVöø‡¾Ì’$IjUú›Ë£Ëà5{–¸Ì¹¿é¯õ’$I}ËÎÿîB¤³™ L±9$I’¤æd _’$I=¥™%,‹ºöǶ^@k¥ë‘$I’ÚR;ú7vòPYÑ&$I’$I’ZO;úI7Iíi0Éfú¥iÀ"›A’$I’¤ú´k ‚/½ÔöÆ÷Ù R¿ý?m^õ¥ÝnH’$I’*1G¿¤v·)ðœÍ õ kÚ ílHmá!›@’$I]a _R»{˜m3HýÂ0› ª?Û’$I’¤j–³ $I’$I’$Ij^ú%I™ w»°¬+ûyËæ.t9ðñÜã#“lI’$I’TÎ@¿$IýÏÀºÀõ¹çÎöFÚ<’$I’$)Ï@¿$Iëí9n..{n>p°§Í/I’$I’ò ôKRû9˜ ,ž­²ÞîÀSDªÌ>À³À\àl`Pû L%ÕÛ—-œ¼JLŒ|>°bnù"è=˜\[¶ ð;bRåWŸR Âgé†^fIŸKóëV;¾lù¾À3ÀuuÖ½V[×Z¶ p[…¶¼˜â),I’$I’ò¶éqoCç@ŒÔ.^²ÚÚàçésðN`e`|…õv ÛÒã ‰÷〠öy>  ®*[~°°°ø ‘‹þ¨ÜökAñ­rÛ^,Æ¥²§¦:e¹ìk«Çÿ›¶Éÿ µuß"¥Î@Gu¯ÕÖµ–֫Ж“=%I’$IR+›ìQçzK¼ykÃÛ=ø>êkãÓ1ŒïãõZÍàmà+À°²eÙ¨õ£±eËÊÛk ðDÁþ†ïÁöüvÙd¼C€w€5rË?<Û~10¡FÙù:}2W§¬ÎYNûMÓãá¹ÇoÔy|ÙòѹåEu¯ÕÖµ–­—öÕQá˜'­ªßçK(u6I’Ÿ’$Iê’vNݳ'Dñæ­]nÏú‘'bdýné3ð9àÿˆàtþÿÂ7ÓXúê%eçÑ :wT2&ýY¶]f,quÙénsˆ hWÎmßQ¶MyÙù:=SV§ÅDJ€EDp}nîñ ßb`Vu¯ÕÖµ–eõZᘇ¥mÕ~ì¬öæ­=nð%I’Ô%mIj;SÓm‘¯þ7DZˆò;ëYÀÕ¹í:ˆ‘ÑY0|<‘ë¾–WÒßµ(ûó£«gôñ”ðy/S‘ýl•²óË&ÐõôT_Q݋ںڲ׉œý¿••·ð€§pÛ:ŒHÁ&©5ÝhH’$©« ôKR{YƒHÿr 1¢}ÜÏ»ŸH[s-‘šæºÜ²Sˆüýƒ‰÷—ìo.Ì>ØŸ¥~LÙòË€Ÿß"F«6næW?¾J¤­Ù¸'Wö÷€ýˆT:ß.éFû4r|Eu¯ÕÖE¯ÃµÀv,èß®ìõP{¹ø‹Í I’$I*·œMÐã&bZ…þnCJùÁëY÷Ý^®ÏåÀÇs¤4‘¨ÔÓÁðYÀ|"Gü—*¬÷7àß ¦ç·O#‹O©cŸû«¯)jʃçû¥÷äcD`ÿVà}¹å_MïÙ©Þä–íCL®þRª×=Àw»Ø6]9¾Zu¯ÕÖE¯ÃÙÀ^eûJ\mq±§±$I’$IjeLÆ»‡ÍÕç š÷f€½·ý]©óÀ?Êž ¼HiQßÁÉxÕ_>ŸúÊtî<8¹Å_'ãíþz*v41Æ|âJ õÜ÷¦þ ™Pøy I’¤.sD{3uÓ²wKÎO¤ýØÓæ‘ÚÚnÄ\ ™WHí¨§:ã†Wê|€èX_`Ó¶Ô9±°nÙgç™D긑6™$I’Z™þÞýÑ‘Ý߇˜Üq.‘ŽaPnýƒˆt ˆÉÍ-œC¤»˜ œO¤¨ÈŒ ‚ij‰tAÔY·}g(åy®VÎQÀïËÊ8 8½`?ÕŽéf"]ÅütÛø1‚|p7°~u‹Ú£šÑDïùDJŽíË–7Rn­u»Rç]€Û*ìç"GºÔ ÆçÎûò›WLH*Ò—Ʀ¿õ³6X­Ÿ·[³¼î $IRÛ2Ðßû;Aöõ€Í€ãÒ²1ÀÏ/álÇÌYÀÊÀ:ÀZiýü¥Çç+kù¯Ï®³>[Ÿ*(ç·D zXnÛÿ ö䔵Ži"öÐtûðDªÏàq¢#¡ÚºEíQÍùDÆh`[–Î{ÝH¹µÖm´Î£€5«&ûöQ“x6wÞ—ßžm’cx¯r’zJÑ@‡jV~¼Atÿ4÷¾¬Ô™^kýJ&¥ÿÍY97°ô¨ð|ššlÙÀ+Ä †|º”Z.j ä¨äIàÀ§å Úµ·ltw€DµúTªÿDª¼ÓS=‹Î£Jç„($I’¤Ñr—è/Ï <…ng?„Þ&&aVáGÔ;À¹ç><î'‚ʬےôŽ:Ëù °wº¿3ðÏ‚}Ô:¦¢Ëîÿ5ýh¬´nQ{T3x²ç_ƒ·ê,7_FÖ­gýõÒëÑQ%±°ßÝaŽ~©õ™£¿ûëõÙ÷‹Áé{Ç=”:º³å¿V $¾šd0˜èÿ+pBïµÖ¯ç{ZµÇo•Õó" | pgnÝËÓme¢ƒáéù1é»Ç‡Òã•Óÿõ¢ïOw/?©°Mµv«V é»D~ÀÆ‹¹åÕ\ \B  ÜAçý—¥r‡×ÿ]G»Tªÿ8¢3dDZg Ñ©²eçQþµ•ÖVá˜>¼ÐïsôK’$©Ë½Ø7_Øó#ZgPºl|‘ƒù0àgÀÄè«»Ò:‡sÛvAùìGdG*¯‹Y¹ÇEå\ ìž~ÔíAíÑüEÇTÉ~Ä$iÙ%ëÕF±µG5cÒß™e¯AWÊm´EëÏN‡óʶ–ÚR½o;¿$-;cm‚–r,h^HL$ý3:âO$@tÌ’¸º0Ûæ$b”~¥«ì]¿;~œþw_œÛÿ§‰|ðo¤çîNýÓÒòiu|úeºmü?àZ"è$1z½Z»U«Ç àïÀgÒ÷¸R;Ý]£Y»NÞL·S)º’¾®ûîrjú~xTA}*ÕÿEàvàóÀ¹Ä$º¯#ùõœG™,ÿü ËæQêL$I’Z’þÞ×AŒ$Ì‚ýãÓ¶ÌÔtü&ýxš•~TŽ'.U.÷2¥QŠÝIQTÎïÒÜ5ÓÅÖQfµcZR¶Þ*Dj›ˆË¬·J?ö¨°nQ{TóJú»¥`ÿø.–[´n£u~¸œbúA›·ÑI¢Þ÷G›@’z\­PyàeÛ‚è4xƒ2ÿªºÑ@9_J?¦Ž¨ãø‹Žéçi?sˆ‰‰¿—Ö{І¿UcÝ¢ö¨f 4_@tT|­l?µÊ-o³¢:4Zç-‰Ëêó†—²jÁ÷Gw˜{_R+~´rŽþ‹ÒÿÁU‰Ñì'|¹†È ŸÏÇ~bîù"`]Ïúõ~Z>}gù"‘7þ·,=o~Ûü÷‡ßÿK¤«lž_ƒHA³¨þzúžSËSÀãÀqeÇXÏ÷¸jõÈ\ÜHLD\kˆQõYŽþÛËŽûàÄ@‡gˆÑ÷õú« ”(ôPÉ6 ´k¹ž°Ý Q«>µ¾o›êø•ΣJçD_ ðó@’$IêEú¥æy4Ê@¿¤Vüp°§Í#I’$HÒ²3ØÃfÚÂ¥DPNýßDÊ—‰À`Az~³ô>S¶þ$à÷u”Û#ú7Jß“³ûû'#ýü'°(­p40ŠHùóCàgiÙà§ÀnDš¡+ÒúYÚšÀÀ”t,W_©£nÇ';×(ç(àýÀçreœ–Ö9¸Æ~¾–ŽiU`°ðdÙëy2ð6°;ð—‚6 üØx.Õ!¯;íT­®õ¼v»P¹Cé–ÔfgøÖ•$IR³hÅ@ÿ)Àá¾´R—mòúÎN?öùrJ-i¾ýõÚ8 ¼|™fŽ!°ï':Jo#:K_'‚ò¿¶NeÜ |4Ý?”î!‚½/UÙ÷ÊÀ À®ÀÀ&iˆ@ÿt–™ÿ>ขcê oFôv ÇC€?¦ºÚïçÀ6ÀéXÇç¶= X¸ba h>‰ÀœŸþ®Mt~lUg}¶6 ÔÑQ­œß¦zæ¥mÿøLÁ>žHû˜›Ê>²gû_—ŽåÀ‡ Ê;Ÿèγ«Ê–w§ŠêZíµ•Žã± õ}˜ìdž$I’šI«ú¿ ÷e•ºåwÀý-pŸžõå”ZÒx`†ÍP·o_"F(O'‚žo¦eÈ@ííDz*1Bú»Ä•6OÛKŒ¼Þx‘Èiþ}¢ó ’ã¿ðÇ€M)ú7'F]ç­¬<˜O!‚·÷rë½GïŒè¯äX`aºLŒØ?èP~‡ºOÞH!Ë»Áéyé¹SS»•¾³~šÈÿFZ~wõ9‘MOA93€¿ý‹ˆ ÷Â:öóçÜý3€kË–ÿXLLd{pAYÃÓÿä é¼{3µÃå=ÔNEu­öÚe9ø+uÎÃy$I’ÔdZ-Ж/©$IÒÿo4ÔÜ’R~üGsËÿ™n£øo$¯kþD@ûbûqD€>ël98§Êþ×¾AŒx‡)½inùfÀúÄhÿÌ"õJ€šnå–£oFô/¡sÇñ JW¿Í!:=#ÈÁé»Ò:‡sÛvrR[vÐx§Õb`VîqQ9—ô‹ˆ«5.­cûG.Ë—ívºÿ&q…M-cÒß™em˜én;Õªk­×.;†¡”:2ÃÒk+I’$5 '㕤֗¥YXhŒî¡rgÁ¾,³~K¶Ïj˶ìƒ:ôåñJݵ1Âü‰*Ë÷î%‚žsˆ\ç§e»ø‰ô>£€‰+÷¦õç)”^¯Rþ€?÷¥Çù”(+“žn–»E}W–õÕˆþ:§ã¼œ{<5µóhà"í D0~qZDº­œÚ‘TÆ’²²»¢¨œßIÿ>Cq •ôì—ê»c7Ûù•ôw­²6¤Ú©¨®µ^»×ç‰+EÊmDtÚH’$IMÃ@¿$µ¶£¯$&o<ŠH£Ñ]#‰Q‘Yní tž¨±7Œ$rB?RaÙ`õ*ËzZ£ÇûÕ;'¤Þ6†ê#“§ÿELVº 1™é+”‚ì7Óˆ¼úû¤ò.§Í‚²ÛU(à³ésè¥t;‚˜_TærÄUÏånÿü£Îï±Kú¨O§6:žR°| "µÑ D Ÿ”Ò Í.~B) ̸Ԧ£È¯~D¤§Hi>„F•3 ¸•HÃôtŸ“ƒˆâ×ÓýÿìfÛÍ%:CNV":DŽ)[ÞÕvª§®Õ^;ˆ4?•ÎÝí€ëüø$IR31Ð/I­í"?ñû‰ÜÄ—?ìr'£~ßîÃc™D×ߪ²ìY"s²*q%Åô.n?ÀSXÝ4¸g£è×%rôCLxûB:?WÎ#ùÓ‰‘üë¤õ†ÖGˆQÎÛSê¼LºËG|wÛ_ùë³Ñú%‚¹ãSÓY:Gúû©oDÿ›Dื-&åOs œ’{~›¦Ï¾ḂÙ/}f=F¬oMížù*ð.qEÒ,¢C¶+ŠÊ¹”¸ê ž´=/s.Ü•^ó{  ÷MŸ‡¯ÿW¡]m§¢ºÖzíÎö*Ûf(°3p±’$I’$õ¼ñÔ—â ÞõZÝòD@î"8þPî6.­s1šñÄ(ÞˆàFfLZ>‹¨]O)•Â7€ß¦ûûW¥û—Á®ì¶„ÒËC‰@ËBàJy’ËM$FøÎM·rûü}º?˜]Ae¾NLÈx‘‚d1éd5{ÁŸ3€×ˆTùáÄÕ3ˆºWSš¸1¼µÚpýÔn‹S[¼Finœjm±o:öóÓúGÔh?Zãó` ¥üõÝYoªn?!Ÿ ‰`èéùÕ‰ rç“›O)À~Zz_,$Fç'\=:ë ‰Ô'çVØç^éý3´ìùŽt2½ÿ~U¶|t:Žì=±uú \a‡½iC"À¬æSïkwÑY•9‚èï)—¤[_~H’$I’ÔoèoÜ&”r#gm3‡ÒÈÛ3‰tÛ§Ç'7åÖ_H¹1€ðßEL 1 òØtÿtठû?œH¿1*­{‘òf1rø×Uê}pPÚï J)ÎNu\'•{BîX²ÿÎÄÕj'Pš`´’ïÁÆ)iýoËÌ÷ˆŽ€qÀŠÀˆ dùñµáADçG^­¶8Íú±ôxPöðóÀ@^­@«:”Rª—Þb ¿yõ—×Î@¿$I’ú„©{$©uM¦sžë­Òã,¸)ð¾%=.O/óO"ؽ˜fß Ém;-·ŸòI !&ù܉Å~°1Âw1b½ÚĹkAíiÝ{rû—ê{"l/?–‰üØç)JUÙÇ$"ßóÔ´þ…©ì!Ä(ço_ ÒB¼ELf¹E…ã-jÃÉtNA2¦ -&§zý)=^T£=¤v×A)~+Oç+£ò·ñýt}QgI’$I5è—¤Öµð÷Üã-s;ˆ`÷5¹å›çï ÜKŒ”ŸC¤ëx"mI¾¼WËŽ·ž6ܬ¬mŠÚbS¢S¡¨=$E¿·¿Ë>J)åV_y–HyTéöl?ÝG_Ô¹^;I’$i™1Ð/I­kK–ÑŸú×& å–oNiôùà¿€ýUˆI_IË×!FùÏ ÒÏ $òÍCäÊ?hgñ1DP}Dî¶2°]•zßœ¶ßˆœïCiRЀo¦cÉL òtÏÉ=·1Z¿’Ä(ù7rÏ}¸.ÝIüóv%rãç·¨ —Kõ/Ñ_­-&s+íÅæ”FŸ¿ÈY?DŸG©§§mJëM&Fö/!:"‚Ò³rå>@ä°ß<=LL|ØQ¡Þ»R ê#ø¤}>˜ê¼?p%¥I…'y˜÷L?BL\m2ÅIDGÅž©Û¹¾OLËï>LÌQ°

p¥‰à%I’¤eÊ@¿$I’zÒfÄdÖCËn?K˾|9=¿p61ùu¶ý¬´l0Ñ)p*°NÙ~ÓµýùÔ]7ç IDATÛÙý}€g‰N‡³A¹õfÏÓ¹ÃbpðjªÿùÄ$á™D€x6‘.è‚:ë¶/Ñ!y]A9G¿/+ã4àô‚ýÕ»Ú1×Ó^ÕŒ¦òGí¬Sµ6¨ÔfG©vòNOmSt 7§ó*ë Úظ­Â1ÝLñ-/I’¤þÀ@¿$IRkÚ˜N+gP ¬Ž®%‚éoéHF¥e‰àç\à†\y‡O£ìo¡úD¸›¥ýVó"íÉ߈‘ûo¥r³íÿš[ÿŽôwpY9é™ý€ˆðziÿÇåÚêçÀˆ@ôÆÄ(îÌYÀÊD'ÄZiý|Þöó•€µU‰€r=õÙØøTA9¿%‚ÐÃrÛþpiÁ>jÕ»è˜kµW-çúÑÀ¶À^ Ô©¨-ËÛìb"ŸþˆÜ¹òÅtžÃé¼Ê:¨fkU8¦G€É~ÔH’$©?ðr`I­jbD©¤Ö3Ê&(ôMàKÀ爠û†DP"(üàv"°:øð]"@|$@Œf8Øè,x‘ÔŸ•_nsjú_':!^$: ^­°ý½éþˆT¯éDPu 1*{"1*{@µ×±DGÃBàdâꃀEÀ;DyÑ)1-m3Ø<ÏKÏšÚð(`8ði"·ûiùÝuÖçDàít¿V93€¿Ÿ!‚Ø;¤c¨µŸ¢z×:æ¢öªf8ðI`B:ßLû¼¼Û2ßf/¦óûóÀ¹é|~•è\Ú°ÁcÈrðϯ°lÎ÷ I’¤~Â@¿¤V³(ýÿœM!µ´¿¥÷»–6šXn <‘žËO@ýÏtƒºßHZ!FRH·EÀ=ÄÈêãˆüŒ´ÞùDš•J6Ö'F„g~žî™È¹ÿcb¤ô Àÿ^Îm¿qÁ›D*•“ïNM·ì{lOŒè_B¤pÉÌ tµÂœT—È@ðDàù®´Î@àáܶ¹:Ig4XŸÅÄÕÔYÎ¥Dü"¢“»h4Q½ksQ{U3&ýY¶]½u*jƒò6¸8ôïüO¯y¹,¥ÔPJ™a©½$I’$IRƧæãm I-ô¹±ئÖÛ&­ô½£Æº{#æ³\ç‹(ÌßHÓòðkâê‰Ý‰Ñósr·7¨œ³|b4øVuÖyðã²í׬cÛ(0WRž£¿üÙx²ÂvƒˆÜïϤÇÃS9ëìg€ßźÕ[Îh¢CdÍôÚlT°¢z×:æFÚ«|ŸïIùíÞ궬Ôfi~f›£ñÇ×y T(ï9¢ã¬Ü¾”æQ¨æ’tëËÏI’$µ!sôK’$µ–1Te<ø/``"×ù+ÀýiùÍÀŽD°xbÂÒ1DŠ•¹ÛÊÀvÊß„BN«³®ÿH·!¹íÕ"KˆQÞ=áb€Uã)Š_ƒHû’u@, Ös\ü„Rú–q©ý F_ üˆ`¶îBÝŠÊ™ÜJ¤\zšHqTKQ½ksQ{ÕÚçT"ÏJDçÄ1 Ô©+mùf:o/%:¶ž­ófW´ä;›®­r¾oGq _’$Iêú%I’ZË4b´o6I躔ò’¿xÈy¿2pÈŸìJL„ 1‚z84~€ÈÍŸåëL‚+Ù7'Ò¯¼]¥nßÞŸ¾ƒ®@\]°#¤Îo_E©ŒîZLÊ%&~ˆC|¿MÓç )·í~ĨôLj`ô­©3_%F‡ÏLeÐÅ:•s)°Å÷zê]t̵ګ–}‰ ú«ÀÿU¨ko´å…À$:§í):†W€3Òy8‡H%u6KO<Ø™˜øW’$I’$ÕÉÔ=’Zñs£7R÷@äè…˜hô`‹ôüêÀD÷nb$s6šÿ4"OþBbdøÁ¹òŽ&:ÏyÏ+9ƒÆÎÏÝæ ?$æX˜ž¿ضlû³«”½5àœïK})~j©–öE­Ñ^k¥smxÃDWæbß"¦î‘$I’$)Ç@¿¤VüÜè­@;ø2°v7Ë0ÐßÚíõ#bTÿ²<ý’$IêmI’$5é÷Øf Ò'R%U²1Kç’ï¯ûèû¬fð"‘ægŠoI’$µË$I’$©Ù¼Óße]߇Ÿ%ò»7ã>jµW_W½Ð9]ϲ~Í%I’¤^çd¼’$IjFËcÚI’$IÍ"©5mü«Í µ¼—€«m†¶Õ#ú%I’$©%øãHR+ú8pð˜M!µ¬±ÀÓèogïáÕ©’$I’è—Ժ¤–u4N²YÍ £ þ^lÔFÇëßæü»p©K’$IêmŽ‚’$Ij-mòwo"}OG›·›ë¯A~I’$õ ý’$5n&°y·=ø…M(uÛ"bB^I’$Ij{ú%I]õ]v7sÝFã€Gº¸ýû€[ ¥em1¢_’$I’Úž~Ij}z¡ÌUÕ€éýðxë©[wÚdð$ðV·¯7ÐߟÛXêæÃXuà™6k£V<æ5W›¬Î;ãgùÖ•$IRo0Ð/I­g_àFà|à5àðôü¡ÀSÀBà`lz~bZnºÝ+«Ò6ë©k–Kå¿FõÉÝ÷#ÕóÀöéùà¨ôÜàjb¤<ÀÀµDz›W€€seÖZ^­n•ÚdL*gð&p=0ªŽºo <”î&ò/_ ­òö;¹z~1Õ1Û¾ZªGQ¥eekàVàt¾Ÿ¬˜–m™>?æϦ÷VÞîÄÄ¥ÿ‘{n‹ôÜ÷r뼓Þó€S‰´=‹¨ã ÀÚmöº´ã1÷7c€·Ó¹ÿ'`[`´Í"I’$IjWã‰ Ïø:Ö=¸½Ûêt"ö±ôxp,p0!=>øuZ~p1Ê}°£`›ƒ€Ë êñMà~`ãôxÃTDðîV"ΊÀ€3Ò²3×)ÖOnÊ•[´¼RÝ*µÉzÀGÒq£îg§}®ü#Ýï¨Ò'7#óWî :N2µêPé8j­ßnêyŸ7ò¹±¬,¶éõ¶Ië, [/»¦ss,p Ñùõ~"Àù ¢ãjcॲc9øgúÌÉüxøRno§ûÿB\QóU`³;¯úï¾P³èøKîñßèåÏI’$µ!GôKRë™ üˆ90‚ïAŒL_DŒlß2-_‹Î HËî!F ÖÚf2¯f4ÿ<¥Ô3¦²V'‚_ ‚ƒo¿#FðBŒ˜ÿ>1–N]S´¼RÝÊÛdX¼XLtÜ )¨{¶ÿqiÿ''Q9À:šè0Øx™éüG`Znju¨vµÖ—2C_W‚Ì>—žß. ‰ôQë¦ç§ÁÈiùˆÜgÇeÄHüG€ªìïà0¢Ãn1Èß3•÷+à`à:à½ôž:¸º%³pÀÏIuŸž{.{ï<‘ÊBc#úóâìþwÓ{óÖÜqüW:îYÄ•My+¿LÛÏNÇ?(·|Uà¢sq&°Cu:6íëÀ‚2¾œ’Û~µ´ÝÀ8æZõ^¸—¸¢âj:§LÊÊ="ýýgú_qdªÛ3éó½hÿµl˜ÎÁW(uþt÷õè‰cª§]ÇÒ¹c⮂sB’$Iêý’Ôz6%癈€Æœt»žC¤ÄØ•ºÿš)^´ÍfÀ5ê°”{¢Â²‰+^Î=7Œ„t9ð¯É-Ûx8Ý/Z^­nåm€¿— Í!Fˆ?^P÷Ž´¿Ïy–ÿP£ v$‚©ÏåžIçüüÕêPí8j­/e. ¢«#è³ù»DP(pqÕÈ âjšOó/ÁJ€ÿ!ÒL~Bt°•û0œÊWøüqÅÎUeÏÏ$Ô™+)úIûڀҤק÷Î@àëé=0ƒÂwõª–‘éXW!RÜŸžNú7ImxmÙv?KŸkAީΙ_W1¬BtØ=SG=¤69· Œ+ÓçOf×T¿w»yÌEõ>;½Ž#ˆŽ¢ã+”»ÑA“­»B:¦3‰TKEû¯åéÿSvN÷ÄëÑSÇTë¸VJ·¹uŸ¬p ’$I’$µ S÷Ôg1:1ß‘{Åiv ‚÷ß*Øf9"(²z²¦VYv01²=ïzb”ÿ:D@$_ÿ«}Òý¢å•êV©M¦òÍÒó‰€üfu_—:‰¤nÕ@ $:>_G*G­õÛ‘©{:ËR÷lJö; ÊÛ…€Ž$:Ù6-[¾¥¹$ :ž¬PΑÄýJ¾MHËOiBÒé=5ê¯Mtf'R÷dë¼Mtn½FÌ#²Qz/50-Ýþ.„…H?”uNï¿VhÇåS}‡çž›D©3eâ*¥•¨Ó;”æ3¨§Œgˆ¹U ®”ص޹Ö>WLí?8w®=\¶w)¢_·Âãç ö_K¶ÿüv¯vóõè©c*j×ÕÒ~.É•½6ѱޛŸ’$IjCŽè—¤Ö2™p¼—{î"Ÿýæéñ`àãDkW"x1ª~8l«µM6BqqzL#‚“Óãu‰Ô  &òÍ/OŒ¼œ@¤øØ´Bý7§4²½hy¥ºUj“÷£.§ óˆŽŽéuß”U< ØŸ];®J<™Ê™˜êôcb’ÝiuÔ¡ÒqÔZ_Êì@t¤-©ðï$"H<‡Èÿ12þ¸t.ßE)=×GÒùš]Ñó<d/7šêAËÑD‡X¹)å,_™ÿ.qÅЩÀˆ@þ#¹u¦#¯W!ð°t€·Qs‰I­!Ò ­’î/Lïï3ˆÎ†Oä¶Etz<›k›Û)¥j™Ê|£z¼A£©³Œ«ˆQýÉ òŸzà˜kís$ÑÁº0=~>·]f¥4J‹*<^¡`ÿµdûÏo×Ý×£'©ÖqÍeé´JCÝmóZí1¤l»î¾=yLµŽëÍtËÏ¥²>¯–‘$I’$©­˜ºGR£ïóvLݳ7pxJ)½Ô÷)å߯|Š=èàúAZg/J“Š.G©ƒ ÜD"¨ùáôx5bRÒUˆ+af ®Ú–½¿Knûc‰+ FîgyúÏ¡”’ëX:O@›ùX*»^åil©ÊýŸ¤e«¤öìHíóHY9ç?¥4yëštž\õ àt⊥Q”&=.ªu–1€èD¹˜0½'޹hŸ&&¦Í¶ûac¨ö¸hÿµÜœÛÿ…eåwõõè‰cª§]Ÿ¤tKö^üZ/H’$© 9¢_’$©uü–¦¿H\õ‘åÞ¿øâ*šˆQÐOŸ&Rø¼NŒ¾ÿN®œ§‰+J^¾Gå‘ãùó‰¹0þFt2¼EÏ?)ÜÏè߈ʓNoOç Q5›Háò:ÑôÜ÷㟥ã98¬l»ƒÓ:Oéƒn"&ÎHt¢Ì&®æ™Ð…ºÕ*c1‘žé_Yz¾“®sÑ>¾@\-2¢l»žÚ-ßHç΋é¼ê‰×£§Ž©è¸ž¡sgã.,=9¼$I’$ImÃý’}Ÿ·ãˆþv²¥+ Um$}+[ÖÇܪm^t\—l㉫PÎìƒÏI’$µ¡6$I’šÐ;Ôž\ê/n$& ~–Æ&O–$I’êfêI’$5£•¨<v³:‘¨üöÝ&)¿ÚH’$IjyŽè—$IR3z“˜T¸+žVí£z¾@LŒ¼¬ËïËcntÿ½ÝFËê¸$I’¤>c _R« ìo3H-ë_m‚¶·Ða3H’$I’~I­é%à ôK­î~›`)g·Ñ±Ž#rôïîË®~ì_{mI’$õ6ý’ZѯÓM’ÚÅKÀ9mvÌ/ú²« ÜŒ~I’$õý’$IÍïIà›A’$I’ÚÓr6$I’$I’$IÍË@¿$I’$I’$IMÌ@¿$I’$I’$IMÌ@¿$I’$I’$IMÌ@¿$I’$I’$IMl M I’Ô¶ÆÙ ’$I’¤rú%I’ú¿§€/Û RË¿Ïß²$I’Ôú%µ¢±À6ƒÔòæµÉ±®çË-I’$IªÆ@¿¤Vôeà{6ƒÔòþlk3H’$I’Ú~I­ên`›AjY‡;Ø ’$I’$è—ÔºÞfÛ RËzÓ&$I’$),gH’$I’$I’Ô¼ ôK’šÅD`NîñÑÄUó!=¼¯Ëç œäK I’$I’ú#ý’¤þjC"Sæq`Dº?8ø0XЃûÝX¸>÷Ü™ÀþÀH_I’$I’Ôßè—$5£±éïc nWÏÜ4—=7¸ ØÓ¦—$I’$Iý~IRoÊFå¼Ì¶É-œ¼J¤á9X1-»@Ùç»§²&ÿÈ-»¡Žýï <\¬¼NŒÜX˜|$=Þ¸­BY·S|I%I’$IR3Ð&$õ²ÀšÀ8"Ïý€¥eg+ëK€ß¤uŽv"Ró@í¦[–-+ÚÿÀ@ðV*ÿb`+ààBàV`Tªk¥+&ûrjÙÉ&ÚÂ}tžF’$Iª‹~IR_ø1°˜˜äöàôÜb”þÚÀ¼ôÜ©À¥D ¾'¼{|.ð)ࢃáßÓóYþùʘGiŽ©¯ÝhHma[à/6ƒ$I’e _’ÔÛiyÞ¥ûcÓÿ¡‡sëv¤õ{zÿ³*<.p51ÉnÖ Õs(¥Î‡Ì0e©eË ÔÚ–Ø’$Iê*sôK’–•YD~<1R~°2‘>z7à1ø1'À‰¹}¾<L¬°ÍFÀ¾l’$I’$©¿1Ð/IZVæ—?¡”g°cº?›R~ÿžv‘ù«ÀTà—¹e×ÛUØf;b2_I’$I’¤~Å@¿$iYÚ˜÷1"UέÀûÒ²W€3ˆÔ>s€ÍzhŸ»¾–NLÖ»gz|6°WÙ6C‰ |%õÇ¿°–IûÍ6· %I’$IR#Æ©\Æ×±îÑÀí6™ºá ¢3 sp²ÍÒ¯Ôó>oäscYYlӃ뵛ßÔ¹îsôN`ºÑr{«½Ý~y#w€<ý<$IRÿàd¼’$-m·²Ç?´I¤~é}D*®"««Ó{xÿ–Û[õèíö+7 xœÒDæ’$I’–1S÷H’šÝx`~•Ûx›Gê7N!&Áά ,È}Ý“Hßuðð2‘j+ÿ½õ;DZ¯€/ë¥åcˆ96fo×m¯O¤™Y.•û¥Á.‡O [€±Uê>¸‘˜[d.pCr{³Õʆ™-‘Š'k£h¿Jö#:%æ3€íÓó›ÓrëU«wêÛÝóE’$I’$õC¦î‘ÔèûÜÔ=ýËTà+¹ÇS€{s¿OѧÁÜoÁß̉ÀÍĈø•;ˆàrf=à#Ä$Þ£€»€ãÒ²ƒˆÉ¿óŽ%&åž Î~]¥î÷¥2¤u·®QnoÖ£VÙg¯S ÆŸÜÔ@û•û&p?°qz¼aª#Ä\&ÇÖQÿîÔ·»çK32u$I’ºÌý’$Iê ›æO.{< øà}¸ F罉‘Ûo¤ó¨ò#¼äÓ¶Ù¾îÏ­;†8ïAŒT_œlY¥îkÁêiÝ{ª”ÛÛõ¨Uö¦Dðû–ô8Ÿ¨žö£lý€ÏçÊy4Õ1Û×´:êßÕúv÷|‘$I’ÚŽ9ú%µª¡T”Hj~kØMe 1’üáÜs“¿äOŽÌ=A¤ŒY|Šò>—[>’Îß½oÿtƒýӲ̀«rëîHL$›!ÞÁÒAûÌîD@ûààp"p]^no×£ZÙ©ýöË­»I®½w¬£ýòv"ùOTXÖ‘Ê~°Žúwµ¾Ý=_$I’$IR?Õhêž%Þ¼ykù›©{šÇG€GryÙ·KG¤c\³ì³üÓýCˆ‘ÛùíŸ FœC¤oyœ¤/—–?—{¼X=·ý!,B§cˆ45ߪRnoÖ£VÙëÐ9=ÀÕÀ>u¶_¹òõóÖæÔQÿîÔ·»çK³2u$I’ºÌý’ZÑψüÁ’ZÛ»6AÓÈFs$Ò¸|H“(Ÿ”žßøè=Ø!-8™˜w&‘òe}J©gÞGägŸNäŸÿ)”Ÿ¬”n‹sõy€¡¿9ðT·þDQóvMõ| '‚ЕÊíÍzÔ*û©-ÞË­¿9pRíWnZZrªãºDþýG‰”;ÕQÿîÔ·»ç‹$I’$Iê§šad®$?7Õ.#x—'RÞðpx•çjÕ§Òú’$I’$I’$µœñÀ’ô·È÷€[qÀŠÀ€3Ò²3×íÓ〛j”u,p0œü:-;˜|,=Tå¹Zõ©´þàI쌕úòscYYlãK%ÉÏ I’$IR;¨7`·:8_-÷Ü^Àéþ_€#sË>Oõ@ÿbþÄÜs¦¥û·yåÏÕ§R’úöscY2`'ÉÏ I’$u›£E%µš‰ø/çž¼J¤Ð™\“[¶ ðp²Vîæ¤ÛõÄ›¿+Û¦ü¹Zõ©V†$I’$I’T7ý’ZÍHb~Þ®À ÀÚÀ@à±Ü²Íû«”5¸‘»­ lG¤òYx4·~¥çjÕ§Òú’$I’$IRC ôKj5÷Ö#‚èÇõ_£ç§ïåÖßx JY¹ü7O'® ˜\¡¬JÏÕªO¥õ%I’$I’¤† ´ $µ˜;%òvþüèýU±ÀCUʺø 0•Í?¸–Hß3™¥¯¨ô\­úTZkàDgÀB_N©ímÜn3Hm¡Ã&$I’_&%µºñÀ "þ¬Í!©E>7–Û…W’úwöå”ZÖ&ÀOømVô¹!I’¤6äˆ~I’¤þïÏ6Ô²Þ² $I’Ô]æè—$I’$I’$©‰è—$I’7“˜¬½ƒHµ~ï{‹^<&I’$IMÆÔ=’$IRcF“¹O'ò¥Oèã}¯<Ò åŽë…r%I’$õGôK’$I™<¼½Œöý ðf/”û$æ‹—$I’š’~I’$µ£=[3€×€—]sË;€£ˆ´< €«‰Qï›ÓÒý}«rÛíGŒôŸŸ¶Ý ,&FÌg6^†U©_¥r²}? œ¼¼ì\¶í¡ÀSÀBàâêƒzÊ}(Ý \ \‘ê>¸˜›n7xúH’$Iý‹~I’$µ£IDžûë€ÑÀ³rËO>|X…HÑóܶ¦û“ÒýoŸ#ä#îóGéœWÿûió*Ô­Z9Ù¾·":ÆgGç¶=Ø‹àþ™öUO¹Ó€u€;€Ç€Ï¦º_šö7X8ÞÓG’$Iê_ÌÑ/©Õ "‚’Zß4`‘Í .šü˜š_Hû‡+ß &Ø}9-ÿðõtSàéþdà4¢³à`Kà‰´ìÿcïÞ£5+ëÃŽ”ëh!ê4Z£ÌVWÔDÑ£]ÅjMЦ6bÕX¯¹›”6mk›Fã-j²¬Ø˜J‚Q/©WˆŠ ^0*H­xQ0j„éÏ>ë¼Îe3 ç=óù¬µ×¼ûöìg?ï~÷œõÛÏþ=Ÿ˜9Þù@ÿ9ÕT÷®³L½Ö*gGõ›ÕyÓü%Sy5ÿÏo ¨{Ù´ìÕÕ+w±Ü7žU½ifÝ]«ý§é;Õ\>°±ô›ÍÑÕšö ÇV—kn¦íÕ/ÎÌomô^¿®€¿ Å ;_i¤ô9¾Åý;=úxãs IDATÖxøté Ç;Ú¦ê…^ñË=¨Z­œ…c?qfÙñÕǦÏ­ª>¸dŸìb¹w«^ÔƒüU§5 œQ½¹znu•K6~`³ÚQ]¡`SºK‹AV¸9¶6z©_3³ì±4>5RÔ\·dŸS½økäÛ¿¬ñ°é€Fú›V}m•cžßx°ðØê¶t8Ë9j•rŽ›þýô̲“Z#à¨ê¬ê§–Ù÷Y»Pîê·OÓìCóó¦é¨ê¯ªÓoC¬Ë¶FJm{h;Àý`#ØY¼Êú“§mس~¸únc°Ý-|ö_l¤Ó©zPuuu÷ê6Õ¯To RûèêÿLÛýóF>ûªSN˜æïVÝkæ˜Uß®>×Èý¿’ÕÊytõÞ%Û¾‘ާêÁzOšæ®1ãZå¾gæóç[8øÔܽúTõ(—еÞßùZ÷ öAã`_³½:³z`c0ÜWo仯Lÿ½F/ü/5rëŸR}³›Ä»ðù¼FÚ›s§íÎiÚ|»‘:çs-¾9°œÕÊÙÞâÀ¿5Æ=ººxšç´ï9Ó¾—6Þ Ø¹ å.œÇÙœþg7Þ<8¥zÿ´ÏÛª—´8®ÀºèÑ¿gݳÕSLÜšîÕèi»’_nô´½¶1hæF¯óZç³à¬FÏÛ¿Xý'—ꦿèÑëxYõœ½|ÌcJ<@󳛿s=ú¸ =úöMŸj䨞7‡Wÿ¥(;´›æÐžW÷m¤Ñxë̲—VOmä ö¬íT<{Ó¯7Òã¼_ó{š@?óäèéßO®°~^™Zõº%Ë®m ˆù_;ìqÇWŸØKǺo#7þƒ«ŸÓôÀ-A `ß4›Nfáóé´_¯^ÑH3±àÁ¯«þoõì™u‡4ò9¥‘RçռΠ¶6‚ØW7Òýñ:ëzZõ™êqÕ‡«ýAð¿™©û“»qÞëµê´Öú•¬ÖËÕyv ÎÕÚ÷‘Õ»–)çôn [§{ÆÞð¡êˆÆÀ_ÑôÀ¾LŽþ=ki g#pudõóÃUÝP=hš?¢‘öbÁk«7T‡5Òé¼¹ú¯3ëÏš¦#=î°Žºýl#ÍÐ÷-³n¶îXÔb°~­:­µ~9«µÃZu^­}ï0­?l™c>¨ú‚ËuSßäèäè`Ÿ!пg-èŸm³GU—NŸ·Vß®žÔMƒÑ‡TÿXÝyfÙ«ÏNŸ¯®¯Ž½uûåê£-¦ëYZïÙº¹Ž:­µ~%«µÃZu^­}ï>­ß²Ì1·Wßt¹nêû@? ÐÀn;@Ð\>3Y‹Áê¯U©žSý~uaõKÕû¦m¨>6³ï–Fp¿F/ø-Syë±_õ¼Fàü‹kl{}õå™ùµê´Öú•¬ÖkÕyµö½zú÷ÐêKö;l:.ö°"~jº·µŒÞV]9³þœi:°zVõ?©i¾Üokäž_êÊ{T_¾ŽúÜPýXõÖ鹎}תÓZëW³R;¬UçÕÚ÷ªF¾ÿ{V·äx?Ðx À¾ëâ麀¹'uÏžµ\êž×6rÈß±ÑKý7¦õw®ÑÈ¿¥úwfœY½ª‘Ú¦ê˜ê¡3ëßXýY#ÏÕ®£nÿ´ÿ‰eÖ-7¿«uZkýrVk‡µê¼ZûÖø¹ËóµÕ3]®›ú~ à¾À>C ÏZèÿnuz£Çù׫?jôZ_hÓ÷N˯«Î¯~h¦¬ƒ«—4‚Ûߨ>ÙƒÓ[«×W×4ÒÔ¼fu«ñ`àKÕÃÛõ@ÿZuZkýJ×ÖJí°+u^©}k<øÐ’ãZý¿Æ`½lÞû€à¾À>C ÿ–³R°œ½ëÏo ,ø…nÜëŸÍy?°Ü7ØmrôÀÆð˜%ó¿£I€]±Ÿ&àV°­ºv…i›zì:=úøÄ­ðÿÁåôÍF­ÀŠôè€9¦G?°Ym¯ŽÔ °)­ `‘@?°Y½E›Ä™Õã5lz¯¯ž ¸9úÍæŠêšö ×ìCçz^õÛ¾rØ´~E°;úÍæ†êjÍl2_¬Þ¦`Óz’&`wŒæ˜@?Ñ–ê²êû§ù£«wWߨ^³ëñùꤽp~7›@?ÑÎêØêÓÓü󫋫êÓ÷Rn_S}üfì{E«? Xz~»ZŸÕµK¦gÏlóo«‹ªëª¯Wï©î¼Ìþ߬¾Ü-Ÿþ€©ý.]á\Ž[²üª?rùÀúÿð€îÁÕ3÷ò1·7ñßZç~w¬îT]²‡ësbuUõ=+¬FõsÕªU‡W§¶8v͉àþQÓü©ÕÙÕŸVŸÝzí_]¿ÂºŸ­¾[ݳ:¤ñb¡.×VŸ[¦Íßèr€õÑ£€èÉ ôÕ5ÕñÕ›½Õ—zBõÎê%ÕW«+AìGUÕrÿCõÖê3ëŸÒÊ_ÛH§óiùŽÆ[UW¯¯þ¼:tZöìê3Þñïh¤úþFºŸý¦º|µå;×,œ_ ø¹ø_¯þf…69±Õ<©ziõwÞò×T¯ê·°ÿù3Û¿gæÜ–ÚRýÒÔ×UÙè…¿P÷s«WOç÷ÜêsDuFõ´ÆÃ’ã—9—Kö¹Oõa—?¬@?Ñ Õ…ÕwªV_jØ·/³íöê¾Õ_WGV¿S½lfýaÕ ø;7ÐOŸÖ=¯Ñþ_Nåÿx#x¿PîEô2ï©>Y=¶ñ@àW«Ÿn<ØZý}õ‚Æ?ßè•~h£÷ýwW9¿ÎnÒïXýú mrR«ú¯j<´xÜTÎrûpú¼µúÍ©¼åRýVõÕ¦sØYý発? ú³iÝ_¡>¿Þx°ðÞ©ív,©ËÅK¶¿ÓTÞG]þ°9mk¶i `Ý7vV'¯±Í™Ó´¯yWõ˜éóã[¹—{Õ9Õ˜™?rjÛCVØþ7ì#=èï±Âvï«^ÞH/³ô ë=ñ<°Å· ^ÙÚ¹ïgÏïÊFZ¢רç£Þù_›™^4³þ{«W—W74Þ\¸Ó’ý¯m¤òùBõºê.Ëç{ƒÏîûÓ€ýBÝÏX£®wkôâ¿ßÌuüâeÎå+3ÓÕû¢õüÎwå¾’@?°ïý+»ººûôù…^ú+¹¼‘òeÁ=êOlôd¿ºÿNõ3Õi-¦¯YjËTÆ•6³NkôÒŸ ¸_Ó€7ë‘ë8¿Sª·7ÒàüI7N+´à ê[ œ¯å¤FÚß[²ÿ]vaßÝHE4ëéô= u¿÷e¼±zÓÌü¯Uï^R—1Õgaú­ê ûèýJ €Ýb0^6šc§¿SRèœPý¶ÝZݵh_ðØFŸªG5‚Ì?ÙèE¾_£‡þGªmé—sÜôïÃAø·WLËŽªÎª~j™ýökä¢ÿÈ:Îï¼iZKàôêw—ìs|#À{Ñ.¶á‡§é™ý¯«®Ø…}oßâ ¹ N­Þ2Õý6Õ'VÙÿäé;øzõÅiÙío,Ôe¿Fžÿkgö»Gc|`äè`£9¡”ß93á Ûn¯®o È»¥‘3ÿÙÕœÖß§‘¦æ’FnþW5ê—4‚æ'Oå×H7s¯éóŽ©UO­þ¢:fZwátœ“¦ùƒ«GLÇ¿Ý4]¿‹çwj‹«oùœù'U«¾½B™?_Ýúûþ Æ[ ­þxÉþ»â‚ê‡oܦ‘†èØê5SÝ/j1h¿Ô–F:¡—Wÿ¤1èî‰ÕÃe¶µ8ÖÀµKö½«? V G?ÍB ¼Æº·oåäÛ)OØHµó¹FNÿ…Ak_W=º1PíÅ|þ—4Ò÷œ×JŸÛ8÷²Æƒ…rêpö4vã-€wNûÓ^_Ýè‰ÿÖFOø—W—6z´ßeó;¥‘Óÿ°Fš ÿ6•»Ô‰Sfƒã;§ò¯iäÓÿÓÆÃˆëƒà>²úÀÌþïbû¿·‘òçüFàþmS=¿9Õ}µ`ü¦ºüÂ’º^9}?;¦ºœ¿d¿#ú`“£ØŒ÷ 9úwß˪çhæœýì©{˜gÛ[>Õ À>C €yv|« °éÉÑÀ<Ûª €}ý0Çú`Ž ôÀ“£`þm­î§`Cz›&à–&Ð0ÿޝÎÕ °!mÑÜÒú6EØ8N®þV3°7ÈÑsL æ˜@?l,GW﮾Q½f/ïóÕIšæ—@?ì9W´ûAóçWW‡U§ßÂõ½}uLõq_Ì/~Ø3îXÝ©ºd7Ëypõ¿öB}÷¯¶WŸ®¾åë€ùu€&æÌöêHÍì‚£5»ážÕV?8Í¿¿zøôùÙÕ3§kìÕiÕ¡ÕEŽ4_­¾ÝúwI¹O«N­>[=nZÿoªs««/W‡Wož¶ùýê'«ÏLÿ~µztõcÕsª­ÕSZ|0pTõ'Õý§:½«z|uUõäê_U—Oe¼ ú‡ÆÛUW¯ªn[=±ºÖeìIÛª&“Ét3¦møÞ¶³:ymΜ¦Õœ<•ÅžsAõŒF¯÷[ øÿê´îØiù«õ¦íß°F¹/mÝ2ÍŸQ½}fý½«+gæÿ ÜÿáÆC„³ªË¦cíW=«úðÌöwo¼°u‡ê}T@ e}£úñiþÀêSŽ›Ê9£Úâëß#Öó»Ü•ßùzîìcôèæÅ€Àz]£ ¸îÚ–ï_}§Ñsÿ¨FÐü¤F°½êÕÕ+§Ï'TY£Üžôï˜æ/©~dfý‰Õ…3ó'T¿]ýí4ÿ±ê ÆÛ5zãÏþMÿ÷ÓTã¹Õ!3eýnõ¿§ùïLõÙ9ÕçYÕ›|õ0úyqCuµf`/9­Ô?£‘Fç¹ÕCAöÎl·¥Åàþ‰ÕÙ«”¹¥‘‚î)3ËŽoï›)c6п£‘îgÁ}ª·ÌÌß»¤ûÄêßW÷˜ŽwpõÔ™²ž¾¤>ÇWw«^” ?Ì-ƒñÀM×ìÿ@#~z£GÿY¼ø ÓÕNWßê=ú¿¯ÑÑæ“3ËNZ²Ï -úÒ}jfý‰K¶ß13ÿ¨ê×ýïi ü¥iý±ÕmªOÌì{ÜôïêçU÷óµÀ|è€;µÅ øaÁq?ÞÀ?¤œ¯Ñ[þžñ·›¦ëW)wGcÀÞf–ÔMSõ\8óyvûÃû®°ý}ª/4ÒÑ?à¨iþ„e޽c*ë¢ÆÃ¿¨ŽñõÀüè€;¥zõÍêmÕKªsªw6RÜœ3­»´zl#ÇýuÕ˧eW¬Pîlïû=înäÙoú|û{Ý/Íù¿£úôtì…¿ågß"x]ã €«ª¿nä꿤‘‹¹ñ¶·øÐàìÆXgW·u ìšÕÉklsæ4­æä©,`ãXÏïrW~çë¹o°Ñ£æ˜@?̱4À¦ñ MÆÑš€½E~€ù÷ÅÆ@ª€ß%û =úæß§«§i€}“ý0Çú`Ž ôÀè€9&ÐsìM°ám«§`SÿÆ/× Ü\ýÛ—ªT/а©]  `þì¬NÖ €û»CŽ~˜cý0Çú`Ž ôÀè€9&ÐsL æØšàVõêÍÀÍ%ÐpëùLõ3šXç}ã[šþ?{p äÿÚªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªÈfƒî ¸IDATªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªª*íÁ!€ ÿ¯½a ss<œ¾ífIEND®B`‚libreswan-3.32/docs/klips-using-kernel-crypto/rcv-flow.svg000066400000000000000000002254141365625662500237300ustar00rootroot00000000000000 ipssec_rcv() ipssec_rcv_state_new() ipsec_rcv_natt_decap() store hard_header ipsec_rcv_unclone() skb_linearize() if(natt) decode header find ipsecX device prepare for decap loop __ipsec_tunnel_finish() ipsec_kfree_skb() ipsec_rcv_state_delete() on error: ipsec_rcv_decap() ipsec_rcv_decap() prepare for ESP ipsec_rcv_state_delete() if(natt) while (ESP or AH) set proto_funcs if next is IPComp ipsec_rcv_decap_once() prepare header correct checksum, etc. if natt if next header do IPIP decap do policy checks if packet is IPIP do policy checks set nfmark restore hard_header skb_decompress() if packet is IPComp do policy checks finalize skb pointers reset conntrack data netif_rx() ipsec_kfree_skb() on error: ipsec_rcv_decap_once() parse header and setup state vars proto_funcs->rcv_checks() ipsec_rcv_ah_checks() ipsec_rcv_esp_checks() case AH: case ESP: update state vars ipsec_sa_getbyid() SA state, policy and lifetime checks update state vars proto_funcs->rcv_setup_auth() ipsec_rcv_ah_setup_auth() ipsec_rcv_esp_setup_auth() case AH: case ESP: ipsec_checkreplaywindow() proto_funcs->rcv_calc_auth() ipsec_rcv_ah_calc_auth() ipsec_rcv_esp_calc_auth() case AH: case ESP: test digest result and replay window ipsec_updatereplaywindow() proto_funcs->rcv_decrypt() ipsec_rcv_ah_decap() ipsec_rcv_esp_decrypt() case AH: case ESP: case COMP: ipsec_rcv_ipcomp_decomp() update state and cleanup policy checks set nfmark if packet is ESP or AH libreswan-3.32/docs/l2tp-overhead.txt000066400000000000000000000001351365625662500176130ustar00rootroot00000000000000IP 20 UDP 14 ESP spi 4 iv 8 auth 12 pad 8 total 36 UDP 14 L2TP 8 PPP 2 libreswan-3.32/docs/nss-howto.txt000066400000000000000000000100651365625662500171030ustar00rootroot00000000000000######################################################################### # Scenario: To setup ipsec with certs in tunnel mode using NSS ######################################################################### GW Mahine 1: w1.x1.y1.z1 GW Mahine 2: w2.x2.y2.z2 w1.x1.y1.z1 <---> w2.x2.y2.z2 Note: In this example setup, both machines are using NSS. If you want to use NSS only at one machine, say machine 1, you can use the following procedure only at machine 1, and you can use traditional ipsec setup at machine 2. 1. Create a new (if not already) nss db on both machines as follows: certutil -N -d sql:/ipsec.d (please note "sql:" in the beginning of all the path). 2. Creating CA certs at both machines: On machine 1: certutil -S -k rsa -n cacert1 -s "CN=cacert1" -v 12 -d . -t "C,C,C" -x -d sql:/ipsec.d As we want to use the same certificate "cacert1" at machine 2, it needs to be exported first. To export the cacert1, do the following at machine 1: pk12util -o cacert1.p12 -n cacert1 -d sql:/etc/ipsec.d Copy the file "cacert1.p12" to the machine2 in "/etc/ipsec.d" directory. On machine 2: Import the "cacert1" as follows: cd /etc/ipsec.d pk12util -i cacert1.p12 -d sql:/etc/ipsec.d certutil -M -n cacert1 -t "C, C, C" -d sql:/etc/ipsec.d Now machine 2 also has the CA certificates "cacert1" in its NSS database. 3. Creating user certs at both machines: On machine 1: certutil -S -k rsa -c cacert1 -n usercert1 -s "CN=usercert1" -v 12 -t "u,u,u" -d sql:/etc/ipsec.d (Note this cert is signed by "cacert1") On machine 2: certutil -S -k rsa -c cacert1 -n usercert2 -s "CN=usercert2" -v 12 -t "u,u,u" -d sql:/etc/ipsec.d (Note this cert is signed by "cacert1" too) 4. Preparing ipsec.conf at both machines ipsec.conf at machine 1: conn pluto-1-2 left=w1.x1.y1.z1 leftid="CN=usercert1" leftsourceip=w1.x1.y1.z1 leftrsasigkey=%cert leftcert=usercert1 leftnexthop=w2.x2.y2.z2 right=w2.x2.y2.z2 rightid="CN=usercert2" rightsourceip=w2.x2.y2.z2 rightrsasigkey=%cert rightnexthop=w1.x1.y1.z1 rekey=no esp="aes-sha1" ike="aes-sha1" auto=add ipsec.conf at machine 2: conn pluto-1-2 left=w2.x2.y2.z2 leftid="CN=usercert2" leftsourceip=w2.x2.y2.z2 leftrsasigkey=%cert leftcert=usercert2 leftnexthop=w1.x1.y1.z1 right=w1.x1.y1.z1 rightid="CN=usercert1" rightsourceip=w1.x1.y1.z1 rightrsasigkey=%cert rightnexthop=w2.x2.y2.z2 rekey=no esp="aes-sha1" ike="aes-sha1" auto=add 5. Preparing ipsec.secrets at both machines ipsec.secrets at machine 1: : RSA usercert1 ipsec.secrets at machine 1: : RSA usercert2 ######################################################################### # Import certificates ######################################################################### This example show how to import certificates in nss. Is useful if you want to migrate from openswan to libreswan. Import a CA: certutil -A -i -n "" -t "C,C,C" -d /etc/ipsec.d/ example: certutil -A -i /etc/ipsec.d/cacerts/CaCert.pem -n "CaCert" -t "C,C,C" -d /etc/ipsec.d/ Import a cert: certutil -A -i -n "" -t "C,C,C" -d /etc/ipsec.d/ example: certutil -A -i /etc/ipsec.d/certs/serverCert.pemm -n "serverCert" -t "C,C,C" -d /etc/ipsec.d/ Import a client cert: certutil -A -i -n "" -t "u,u,u" -d /etc/ipsec.d/ example: certutil -A -i /etc/ipsec.d/certs/userCert.pem -n "userCert" -t "u,u,u" -d /etc/ipsec.d/ Convert key: openssl pkcs12 -export -in /etc/ipsec.d/certs/userCert.pem -inkey /etc/ipsec.d/private/userKey.pem -name "userCert" -out /etc/ipsec.d/private/userKey.p12 Import Key: pk12util -i /etc/ipsec.d/private/userKey.p12 -d /etc/ipsec.d In your secret file you can use: : RSA "userCert" Show a list of the current certificates and trust attributes in a certificate database: certutil -L -d /etc/ipsec.d/ libreswan-3.32/docs/opportunistic-v1.historic/000077500000000000000000000000001365625662500214705ustar00rootroot00000000000000libreswan-3.32/docs/opportunistic-v1.historic/opportunism-spec.txt000066400000000000000000001407531365625662500255720ustar00rootroot00000000000000 Opportunistic Encryption Henry Spencer D. Hugh Redelmeier henry@spsystems.net hugh@mimosa.com Linux FreeS/WAN Project Opportunistic encryption permits secure (encrypted, authenticated) communication via IPsec without connection-by-connection prearrangement, either explicitly between hosts (when the hosts are capable of it) or transparently via packet- intercepting security gateways. It uses DNS records (authenticated with DNSSEC) to provide the necessary information for gateway discovery and gateway authentication, and constrains negotiation enough to guarantee success. Substantive changes since draft 3: write off inverse queries as a lost cause; use Invalid-SPI rather than Delete as notification of unknown SA; minor wording improvements and clarifications. This document takes over from the older ``Imple- menting Opportunistic Encryption'' document. 1. Introduction A major goal of the FreeS/WAN project is opportunistic encryption: a (security) gateway intercepts an outgoing packet aimed at a remote host, and quickly attempts to nego- tiate an IPsec tunnel to that host's security gateway. If the attempt succeeds, traffic can then be secure, transpar- ently (without changes to the host software). If the attempt fails, the packet (or a retry thereof) passes through in clear or is dropped, depending on local policy. Prearranged tunnels bypass the packet interception etc., so static VPNs can coexist with opportunistic encryption. This generalizes trivially to the end-to-end case: host and security gateway simply are one and the same. Some opti- mizations are possible in that case, but the basic scheme need not change. The objectives for security systems need to be explicitly stated. Opportunistic encryption is meant to achieve secure communication, without prearrangement of the individual con- nection (although some prearrangement on a per-host basis is Draft 4 3 May 2001 1 Opportunistic Encryption required), between any two hosts which implement the proto- col (and, if they act as security gateways, between hosts behind them). Here ``secure'' means strong encryption and authentication of packets, with authentication of partici- pants--to prevent man-in-the-middle and impersonation attacks--dependent on several factors. The biggest factor is the authentication of DNS records, via DNSSEC or equiva- lent means. A lesser factor is which exact variant of the setup procedure (see section 2.2) is used, because there is a tradeoff between strong authentication of the other end and ability to negotiate opportunistic encryption with hosts which have limited or no control of their reverse-map DNS records: without reverse-map information, we can verify that the host has the right to use a particular FQDN (Fully Qual- ified Domain Name), but not whether that FQDN is authorized to use that IP address. Local policy must decide whether authentication or connectivity has higher priority. Apart from careful attention to detail in various areas, there are three crucial design problems for opportunistic encryption. It needs a way to quickly identify the remote host's security gateway. It needs a way to quickly obtain an authentication key for the security gateway. And the numerous options which can be specified with IKE must be constrained sufficiently that two independent implementa- tions are guaranteed to reach agreement, without any explicit prearrangement or preliminary negotiation. The first two problems are solved using DNS, with DNSSEC ensur- ing that the data obtained is reliable; the third is solved by specifying a minimum standard which must be supported. A note on philosophy: we have deliberately avoided providing six different ways to do each job, in favor of specifying one good one. Choices are provided only when they appear to be necessary, or at least important. A note on terminology: to avoid constant circumlocutions, an ISAKMP/IKE SA, possibly recreated occasionally by rekeying, will be referred to as a ``keying channel'', and a set of IPsec SAs providing bidirectional communication between two IPsec hosts, possibly recreated occasionally by rekeying, will be referred to as a ``tunnel'' (it could conceivably use transport mode in the host-to-host case, but we advocate using tunnel mode even there). The word ``connection'' is here used in a more generic sense. The word ``lifetime'' will be avoided in favor of ``rekeying interval'', since many of the connections will have useful lives far shorter than any reasonable rekeying interval, and hence the two concepts must be separated. A note on document structure: Discussions of why things were done a particular way, or not done a particular way, are broken out in paragraphs headed ``Rationale:'' (to preserve the flow of the text, many such paragraphs are deferred to Draft 4 3 May 2001 2 Opportunistic Encryption the ends of sections). Paragraphs headed ``Ahem:'' are dis- cussions of where the problem is being made significantly harder by problems elsewhere, and how that might be cor- rected. Some meta-comments are enclosed in []. Rationale: The motive is to get the Internet encrypted. That requires encryption without connection-by-connection prearrangement: a system must be able to reliably negotiate an encrypted, authenticated connection with a total stranger. While end-to-end encryption is preferable, doing opportunistic encryption in security gateways gives enormous leverage for quick deployment of this technology, in a world where end-host software is often primitive, rigid, and out- dated. Rationale: Speed is of the essence in tunnel setup: a con- nection-establishment delay longer than about 10 seconds begins to cause problems for users and applications. Thus the emphasis on rapidity in gateway discovery and key fetch- ing. Ahem: Host-to-host opportunistic encryption would be utterly trivial if a fast public-key encryption/signature algorithm was available. You would do a reverse lookup on the desti- nation address to obtain a public key for that address, and simply encrypt all packets going to it with that key, sign- ing them with your own private key. Alas, this is impracti- cal with current CPU speeds and current algorithms (although as noted later, it might be of some use for limited pur- poses). Nevertheless, it is a useful model. 2. Connection Setup For purposes of discussion, the network is taken to look like this: Source----Initiator----...----Responder----Destination The intercepted packet comes from the Source, bound for the Destination, and is intercepted at the Initiator. The Ini- tiator communicates over the insecure Internet to the Responder. The Source and the Initiator might be the same host, or the Source might be an end-user host and the Ini- tiator a security gateway (SG). Likewise for the Responder and the Destination. Given an intercepted packet, whose useful information (for our purposes) is essentially only the Destination's IP address, the Initiator must quickly determine the Responder (the Destination's SG) and fetch everything needed to authenticate it. The Responder must do likewise for the Initiator. Both must eventually also confirm that the other is authorized to act on behalf of the client host behind it (if any). Draft 4 3 May 2001 3 Opportunistic Encryption An important subtlety here is that if the alternative to an IPsec tunnel is plaintext transmission, negative results must be obtained quickly. That is, the decision that no tunnel can be established must also be made rapidly. 2.1. Packet Interception Interception of outgoing packets is relatively straightfor- ward in principle. It is preferable to put the intercepted packet on hold rather than dropping it, since higher-level retries are not necessarily well-timed. There is a problem of hosts and applications retrying during negotiations. ARP implementations, which face the same problem, use the approach of keeping the most recent packet for an as-yet- unresolved address, and throwing away older ones. (Incre- menting of request numbers etc. means that replies to older ones may no longer be accepted.) Is it worth intercepting incoming packets, from the outside world, and attempting tunnel setup based on them? No, unless and until a way can be devised to initiate oppor- tunistic encryption to a non-opportunistic responder, because if the other end has not initiated tunnel setup itself, it will not be prepared to do so at our request. Rationale: Note, however, that most incoming packets will promptly be followed by an outgoing packet in response! Conceivably it might be useful to start early stages of negotiation, at least as far as looking up information, in response to an incoming packet. Rationale: If a plaintext incoming packet indicates that the other end is not prepared to do opportunistic encryption, it might seem that this fact should be noted, to avoid consum- ing resources and delaying traffic in an attempt at oppor- tunistic setup which is doomed to fail. However, this would be a major security hole, since the plaintext packet is not authenticated; see section 2.5. 2.2. Algorithm For clarity, the following defers most discussion of error handling to the end. Step 1. Initiator does a DNS reverse lookup on the Destina- tion address, asking not for the usual PTR records, but for TXT records. Meanwhile, Initiator also sends a ping to the Destination, to cause any other dynamic setup actions to start happening. (Ping replies are disregarded; the host might not be reachable with plaintext pings.) Step 2A. If at least one suitable TXT record (see section 2.3) comes back, each contains a potential Draft 4 3 May 2001 4 Opportunistic Encryption Responder's IP address and that Responder's public key (or where to find it). Initiator picks one TXT record, based on priority (see 2.3), thus picking a Responder. If there was no public key in the TXT record, the Initiator also starts a DNS lookup (as specified by the TXT record) to get KEY records. Step 2B. If no suitable TXT record is available, and policy permits, Initiator designates the Destination itself as the Responder (see section 2.4). If pol- icy does not permit, or the Destination is unre- sponsive to the negotiation, then opportunistic encryption is not possible, and Initiator gives up (see section 2.5). Step 3. If there already is a keying channel to the Respon- der's IP address, the Initiator uses the existing keying channel; skip to step 10. Otherwise, the Initiator starts an IKE Phase 1 negotiation (see section 2.7 for details) with the Responder. The address family of the Responder's IP address dic- tates whether the keying channel and the outside of the tunnel should be IPv4 or IPv6. Step 4. Responder gets the first IKE message, and responds. It also starts a DNS reverse lookup on the Initia- tor's IP address, for KEY records, on speculation. Step 5. Initiator gets Responder's reply, and sends first message of IKE's D-H exchange (see 2.4). Step 6. Responder gets Initiator's D-H message, and responds with a matching one. Step 7. Initiator gets Responder's D-H message; encryption is now established, authentication remains to be done. Initiator sends IKE authentication message, with an FQDN identity if a reverse lookup on its address will not yield a suitable KEY record. (Note, an FQDN need not actually correspond to a host--e.g., the DNS data for it need not include an A record.) Step 8. Responder gets Initiator's authentication message. If there is no identity included, Responder waits for step 4's speculative DNS lookup to finish; it should yield a suitable KEY record (see 2.3). If there is an FQDN identity, responder discards any data obtained from step 4's DNS lookup; does a for- ward lookup on the FQDN, for a KEY record; waits for that lookup to return; it should yield a suit- able KEY record. Either way, Responder uses the KEY data to verify the message's hash. Responder replies with an authentication message, with an Draft 4 3 May 2001 5 Opportunistic Encryption FQDN identity if a reverse lookup on its address will not yield a suitable KEY record. Step 9A. (If step 2A was used.) The Initiator gets the Responder's authentication message. Step 2A has provided a key (from the TXT record or via DNS lookup). Verify message's hash. Encrypted and authenticated keying channel established, man-in- middle attack precluded. Step 9B. (If step 2B was used.) The Initiator gets the Responder's authentication message, which must con- tain an FQDN identity (if the Responder can't put a TXT in his reverse map he presumably can't do a KEY either). Do forward lookup on the FQDN, get suit- able KEY record, verify hash. Encrypted keying channel established, man-in-middle attack pre- cluded, but authentication weak (see 2.4). Step 10. Initiator initiates IKE Phase 2 negotiation (see 2.7) to establish tunnel, specifying Source and Destination identities as IP addresses (see 2.6). The address family of those addresses also deter- mines whether the inside of the tunnel should be IPv4 or IPv6. Step 11. Responder gets first Phase 2 message. Now the Responder finally knows what's going on! Unless the specified Source is identical to the Initiator, Responder initiates DNS reverse lookup on Source IP address, for TXT records; waits for result; gets suitable TXT record(s) (see 2.3), which should con- tain either the Initiator's IP address or an FQDN identity identical to that supplied by the Initia- tor in step 7. This verifies that the Initiator is authorized to act as SG for the Source. Responder replies with second Phase 2 message, selecting acceptable details (see 2.7), and establishes tun- nel. Step 12. Initiator gets second Phase 2 message, establishes tunnel (if he didn't already), and releases the intercepted packet into it, finally. Step 13. Communication proceeds. See section 3 for what happens later. As additional information becomes available, notably in steps 1, 2, 4, 8, 9, 11, and 12, there is always a possibil- ity that local policy (e.g., access limitations) might pre- vent further progress. Whenever possible, at least attempt to inform the other end of this. Draft 4 3 May 2001 6 Opportunistic Encryption At any time, there is a possibility of the negotiation fail- ing due to unexpected responses, e.g. the Responder not responding at all or rejecting all Initiator's proposals. If multiple SGs were found as possible Responders, the Ini- tiator should try at least one more before giving up. The number tried should be influenced by what the alternative is: if the traffic will otherwise be discarded, trying the full list is probably appropriate, while if the alternative is plaintext transmission, it might be based on how long the tries are taking. The Initiator should try as many as it reasonably can, ideally all of them. There is a sticky problem with timeouts. If the Responder is down or otherwise inaccessible, in the worst case we won't hear about this except by not getting responses. Some other, more pathological or even evil, failure cases can have the same result. The problem is that in the case where plaintext is permitted, we want to decide whether a tunnel is possible quickly. There is no good solution to this, alas; we just have to take the time and do it right. (Pass- ing plaintext meanwhile looks attractive at first glance... but exposing the first few seconds of a connection is often almost as bad as exposing the whole thing. Worse, if the user checks the status of the connection, after that brief window it looks secure!) The flip side of waiting for a timeout is that all other forms of feedback, e.g. ``host not reachable'', arguably should be ignored, because in the absence of authenticated ICMP, you cannot trust them! Rationale: An alternative, sometimes suggested, to the use of explicit DNS records for SG discovery is to directly attempt IKE negotiation with the destination host, and assume that any relevant SG will be on the packet path, will intercept the IKE packets, and will impersonate the destina- tion host for the IKE negotiation. This is superficially attractive but is a very bad idea. It assumes that routing is stable throughout negotiation, that the SG is on the plaintext-packets path, and that the destination host is routable (yes, it is possible to have (private) DNS data for an unroutable host). Playing extra games in the plaintext- packet path hurts performance and can be expected to be unpopular. Various difficulties ensue when there are multi- ple SGs along the path (there is already bad experience with this, in RSVP), and the presence of even one can make it impossible to do IKE direct to the host when that is what's wanted. Worst of all, such impersonation breaks the IP net- work model badly, making problems difficult to diagnose and impossible to work around (and there is already bad experi- ence with this, in areas like web caching). Rationale: (Step 1.) Dynamic setup actions might include establishment of demand-dialed links. These might be Draft 4 3 May 2001 7 Opportunistic Encryption present anywhere along the path, so one cannot rely on out- of-band communication at the Initiator to trigger them. Hence the ping. Rationale: (Step 2.) In many cases, the IP address on the intercepted packet will be the result of a name lookup just done. Inverse queries, an obscure DNS feature from the dis- tant past, in theory can be used to ask a DNS server to reverse that lookup, giving the name that produced the address. This is not the same as a reverse lookup, and the difference can matter a great deal in cases where a host does not control its reverse map (e.g., when the host's IP address is dynamically assigned). Unfortunately, inverse queries were never widely implemented and are now considered obsolete. Phooey. Ahem: Support for a small subset of this admittedly-obscure feature would be useful. Unfortunately, it seems unlikely. Rationale: (Step 3.) Using only IP addresses to decide whether there is already a relevant keying channel avoids some difficult problems. In particular, it might seem that this should be based on identities, but those are not known until very late in IKE Phase 1 negotiations. Rationale: (Step 4.) The DNS lookup is done on speculation because the data will probably be useful and the lookup can be done in parallel with IKE activity, potentially speeding things up. Rationale: (Steps 7 and 8.) If an SG does not control its reverse map, there is no way it can prove its right to use an IP address, but it can nevertheless supply both an iden- tity (as an FQDN) and proof of its right to use that iden- tity. This is somewhat better than nothing, and may be quite useful if the SG is representing a client host which can prove its right to its IP address. (For example, a fixed-address subnet might live behind an SG with a dynami- cally-assigned address; such an SG has to be the Initiator, not the Responder, so the subnet's TXT records can contain FQDN identities, but with that restriction, this works.) It might sound like this would permit some man-in-the-middle attacks in important cases like Road Warrior, but the RW can still do full authentication of the home base, so a man in the middle cannot successfully impersonate home base, and the D-H exchange doesn't work unless the man in the middle impersonates both ends. Rationale: (Steps 7 and 8.) Another situation where proof of the right to use an identity can be very useful is when access is deliberately limited. While opportunistic encryp- tion is intended as a general-purpose connection mechanism between strangers, it may well be convenient for prearranged connections to use the same mechanism. Draft 4 3 May 2001 8 Opportunistic Encryption Rationale: (Steps 7 and 8.) FQDNs as identities are avoided where possible, since they can involve synchronous DNS lookups. Rationale: (Step 11.) Note that only here, in Phase 2, does the Responder actually learn who the Source and Destination hosts are. This unfortunately demands a synchronous DNS lookup to verify that the Initiator is authorized to repre- sent the Source, unless they are one and the same. This and the initial TXT lookup are the only synchronous DNS lookups absolutely required by the algorithm, and they appear to be unavoidable. Rationale: While it might seem unlikely that a refusal to cooperate from one SG could be remedied by trying another-- presumably they all use the same policies--it's conceivable that one might be misconfigured. Preferably they should all be tried, but it may be necessary to set some limits on this if alternatives exist. 2.3. DNS Records Gateway discovery and key lookup are based on TXT and KEY DNS records. The TXT record specifies IP address or other identity of a host's SG, and possibly supplies its public key as well, while the KEY record supplies public keys not found in TXT records. 2.3.1. TXT Opportunistic-encryption SG discovery uses TXT records with the content: X-IPsec-Gateway(nnn)=iii kkk following RFC 1464 attribute/value notation. Records which do not contain an ``='', or which do not have exactly the specified form to the left of it, are ignored. (Near misses perhaps should be reported.) The nnn is an unsigned integer which will fit in 16 bits, specifying an MX-style preference (lower number = stronger preference) to control the order in which multiple SGs are tried. If there are ties, pick one, randomly enough that the choice will probably be different each time. The pref- erence field is not optional; use ``0'' if there is no mean- ingful preference ordering. The iii part identifies the SG. Normally this is a dotted- decimal IPv4 address or a colon-hex IPv6 address. The sole exception is if the SG has no fixed address (see 2.4) but the host(s) behind it do, in which case iii is of the form ``@fqdn'', where fqdn is the FQDN that the SG will use to identify itself (in step 7 of section 2.2); such a record Draft 4 3 May 2001 9 Opportunistic Encryption cannot be used for SG discovery by an Initiator, but can be used for SG verification (step 11 of 2.2) by a Responder. The kkk part is optional. If it is present, it is an RSA- MD5 public key in base-64 notation, as in the text form of an RFC 2535 KEY record. If it is not present, this speci- fies that the public key can be found in a KEY record located based on the SG's identification: if iii is an IP address, do a reverse lookup on that address, else do a for- ward lookup on the FQDN. Rationale: While it is unusual for a reverse lookup to go for records other than PTR records (or possibly CNAME records, for RFC 2317 classless delegation), there's no rea- son why it can't. The TXT record is a temporary stand-in for (we hope, someday) a new DNS record for SG identifica- tion and keying. Keeping the setup process fast requires minimizing the number of DNS lookups, hence the desire to put all the information in one place. Rationale: The use of RFC 1464 notation avoids collisions with other uses of TXT records. The ``X-'' in the attribute name indicates that this format is tentative and experimen- tal; this design will probably need modification after ini- tial experiments. The format is chosen with an eye on even- tual binary encoding. Note, in particular, that the TXT record normally contains the address of the SG, not (repeat, not) its name. Name-to-address conversion is the job of whatever generates the TXT record, which is expected to be a program, not a human--this is conceptually a binary record, temporarily using a text encoding. The ``@fqdn'' form of the SG identity is for specialized uses and is never mapped to an address. Ahem: A DNS TXT record contains one or more character strings, but RFC 1035 does not describe exactly how a multi- string TXT record is interpreted. This is relevant because a string can be at most 255 characters, and public keys can exceed this. Empirically, the standard pattern is that each string which is both less than 255 characters and not the final string of the record should have a blank appended to it, and the strings of the record should then be concate- nated. (This observation is based on how BIND 8 transforms a TXT record from text to DNS binary.) 2.3.2. KEY An opportunistic-encryption KEY record is an Authentication- permitted, Entity (host), non-Signatory, IPsec, RSA/MD5 record (that is, its first four bytes are 0x42000401), as per RFCs 2535 and 2537. KEY records with other flags, pro- tocol, or algorithm values are ignored. Draft 4 3 May 2001 10 Opportunistic Encryption Rationale: Unfortunately, the public key has to be associ- ated with the SG, not the client host behind it. The Responder does not know which client it is supposed to be representing, or which client the Initiator is representing, until far too late. Ahem: Per-client keys would reduce vulnerability to key com- promise, and simplify key changes, but they would require changes to IKE Phase 1, to separately identify the SG and its initial client(s). (At present, the client identities are not known to the Responder until IKE Phase 2.) While the current IKE standard does not actually specify (!) who is being identified by identity payloads, the overwhelming consensus is that they identify the SG, and as seen earlier, this has important uses. 2.3.3. Summary For reference, the minimum set of DNS records needed to make this all work is either: 1. TXT in Destination reverse map, identifying Responder and providing public key. 2. KEY in Initiator reverse map, providing public key. 3. TXT in Source reverse map, verifying relationship to Initiator. or: 1. TXT in Destination reverse map, identifying Responder. 2. KEY in Responder reverse map, providing public key. 3. KEY in Initiator reverse map, providing public key. 4. TXT in Source reverse map, verifying relationship to Initiator. Slight complications ensue for dynamic addresses, lack of control over reverse maps, etc. 2.3.4. Implementation In the long run, we need either a tree of trust or a web of trust, so we can trust our DNS data. The obvious approach for DNS is a tree of trust, but there are various practical problems with running all of this through the root servers, and a web of trust is arguably more robust anyway. This is logically independent of opportunistic encryption, and a separate design proposal will be prepared. Draft 4 3 May 2001 11 Opportunistic Encryption Interim stages of implementation of this will require a bit of thought. Notably, we need some way of dealing with the lack of fully signed DNSSEC records right away. Without user interaction, probably the best we can do is to remember the results of old fetches, compare them to the results of new fetches, and complain and disbelieve all of it if there's a mismatch. This does mean that somebody who gets fake data into our very first fetch will fool us, at least for a while, but that seems an acceptable tradeoff. (Obvi- ously there needs to be a way to manually flush the remem- bered results for a specific host, to permit deliberate changes.) 2.4. Responders Without Credentials In cases where the Destination simply does not control its DNS reverse-map entries, there is no verifiable way to determine a suitable SG. This does not make communication utterly impossible, though. Simply attempting negotiation directly with the host is a last resort. (An aggressive implementation might wish to attempt it in parallel, rather than waiting until other options are known to be unavailable.) In particular, in many cases involving dynamic addresses, it will work. It has the disadvantage of delaying the discovery that oppor- tunistic encryption is entirely impossible, but the case seems common enough to justify the overhead. However, there are policy issues here either way, because it is possible to impersonate such a host. The host can supply an FQDN identity and verify its right to use that identity, but except by prearrangement, there is no way to verify that the FQDN is the right one for that IP address. (The data from forward lookups may be controlled by people who do not own the address, so it cannot be trusted.) The encryption is still solid, though, so in many cases this may be useful. 2.5. Failure of Opportunism When there is no way to do opportunistic encryption, a pol- icy issue arises: whether to put in a bypass (which allows plaintext traffic through) or a block (which discards it, perhaps with notification back to the sender). The choice is very much a matter of local policy, and may depend on details such as the higher-level protocol being used. For example, an SG might well permit plaintext HTTP but forbid plaintext Telnet, in which case both a block and a bypass would be set up if opportunistic encryption failed. A bypass/block must, in practice, be treated much like an IPsec tunnel. It should persist for a while, so that high- overhead processing doesn't have to be done for every packet, but should go away eventually to return resources. Draft 4 3 May 2001 12 Opportunistic Encryption It may be simplest to treat it as a degenerate tunnel. It should have a relatively long lifetime (say 6h) to keep the frequency of negotiation attempts down, except in the case where the other SG simply did not respond to IKE packets, where the lifetime should be short (say 10min) because the other SG is presumably down and might come back up again. (Cases where the other SG responded to IKE with unauthenti- cated error reports like ``port unreachable'' are border- line, and might deserve to be treated as an intermediate case: while such reports cannot be trusted unreservedly, in the absence of any other response, they do give some reason to suspect that the other SG is unable or unwilling to par- ticipate in opportunistic encryption.) As noted in section 2.1, one might think that arrival of a plaintext incoming packet should cause a bypass/block to be set up for its source host: such a packet is almost always followed by an outgoing reply packet; the incoming packet is clear evidence that opportunistic encryption is not avail- able at the other end; attempting it will waste resources and delay traffic to no good purpose. Unfortunately, this means that anyone out on the Internet who can forge a source address can prevent encrypted communication! Since their source addresses are not authenticated, plaintext packets cannot be taken as evidence of anything, except perhaps that communication from that host is likely to occur soon. There needs to be a way for local administrators to remove a bypass/block ahead of its normal expiry time, to force a retry after a problem at the other end is known to have been fixed. 2.6. Subnet Opportunism In principle, when the Source or Destination host belongs to a subnet and the corresponding SG is willing to provide tun- nels to the whole subnet, this should be done. There is no extra overhead, and considerable potential for avoiding later overhead if similar communication occurs with other members of the subnet. Unfortunately, at the moment, oppor- tunistic tunnels can only have degenerate subnets (single hosts) at their ends. (This does, at least, set up the key- ing channel, so that negotiations for tunnels to other hosts in the same subnets will be considerably faster.) The crucial problem is step 11 of section 2.2: the Responder must verify that the Initiator is authorized to represent the Source, and this is impossible for a subnet because there is no way to do a reverse lookup on it. Information in DNS records for a name or a single address cannot be trusted, because they may be controlled by people who do not control the whole subnet. Draft 4 3 May 2001 13 Opportunistic Encryption Ahem: Except in the special case of a subnet masked on a byte boundary (in which case RFC 1035's convention of an incomplete in-addr.arpa name could be used), subnet lookup would need extensions to the reverse-map name space, perhaps along the lines of that commonly done for RFC 2317 delega- tion. IPv6 already has suitable name syntax, as in RFC 2874, but has no specific provisions for subnet entries in its reverse maps. Fixing all this is is not conceptually difficult, but is logically independent of opportunistic encryption, and will be proposed separately. A less-troublesome problem is that the Initiator, in step 10 of 2.2, must know exactly what subnet is present on the Responder's end so he can propose a tunnel to it. This information could be included in the TXT record of the Des- tination (it would have to be verified with a subnet lookup, but that could be done in parallel with other operations). The Initiator presumably can be configured to know what sub- net(s) are present on its end. 2.7. Option Settings IPsec and IKE have far too many useless options, and a few useful ones. IKE negotiation is quite simplistic, and can- not handle even simple discrepancies between the two SGs. So it is necessary to be quite specific about what should be done and what should be proposed, to guarantee interoper- ability without prearrangement or other negotiation proto- cols. Rationale: The prohibition of other negotiations is simply because there is no time. The setup algorithm (section 2.2) is lengthy already. [Open question: should opportunistic IKE use a different port than normal IKE?] Somewhat arbitrarily and tentatively, opportunistic SGs must support Main Mode, Oakley group 5 for D-H, 3DES encryption and MD5 authentication for both ISAKMP and IPsec SAs, RSA/MD5 digital-signature authentication with keys between 2048 and 8192 bits, and ESP doing both encryption and authentication. They must do key PFS in Quick Mode, but not identity PFS. They may support IPComp, preferably using Deflate, but must not insist on it. They may support AES as an alternative to 3DES, but must not insist on it. Rationale: Identity PFS essentially requires establishing a complete new keying channel for each new tunnel, but key PFS just does a new Diffie-Hellman exchange for each rekeying, which is relatively cheap. Keying channels must remain in existence at least as long as any tunnel created with them remains (they are not costly, Draft 4 3 May 2001 14 Opportunistic Encryption and keeping the management path up and available simplifies various issues). See section 3.1 for related issues. Given the use of key PFS, frequent rekeying does not seem critical here. In the absence of strong reason to do otherwise, the Initiator should propose rekeying at 8hr-or-1MB. The Responder must accept any proposal which specifies a rekey- ing time between 1hr and 24hr inclusive and a rekeying vol- ume between 100KB and 10MB inclusive. Given the short expected useful life of most tunnels (see section 3.1), very few of them will survive long enough to be rekeyed. In the absence of strong reason to do other- wise, the Initiator should propose rekeying at 1hr-or-100MB. The Responder must accept any proposal which specifies a rekeying time between 10min and 8hr inclusive and a rekeying volume between 1MB and 1000MB inclusive. It is highly desirable to add some random jitter to the times of actual rekeying attempts, to break up ``convoys'' of rekeying events; this and certain other aspects of robust rekeying practice will be the subject of a separate design proposal. Rationale: The numbers used here for rekeying intervals are chosen quite arbitrarily and should be re-assessed after some implementation experience is gathered. 3. Renewal and Teardown 3.1. Aging When to tear tunnels down is a bit problematic, but if we're setting up a potentially unbounded number of them, we have to tear them down somehow sometime. Set a short initial tentative lifespan, say 1min, since most net flows in fact last only a few seconds. When that expires, look to see if the tunnel is still in use (defini- tion: has had traffic, in either direction, in the last half of the tentative lifespan). If so, assign it a somewhat longer tentative lifespan, say 20min, after which, look again. If not, close it down. (This tentative lifespan is independent of rekeying; it is just the time when the tun- nel's future is next considered. This should happen reason- ably frequently, unlike rekeying, which is costly and shouldn't be too frequent.) Multi-step backoff algorithms are not worth the trouble; looking every 20min doesn't seem onerous. If the security gateway and the client host are one and the same, tunnel teardown decisions might wish to pay attention to TCP connection status, as reported by the local TCP layer. A still-open TCP connection is almost a guarantee that more traffic is coming, while the demise of the only Draft 4 3 May 2001 15 Opportunistic Encryption TCP connection through a tunnel is a strong hint that none is. If the SG and the client host are separate machines, though, tracking TCP connection status requires packet snooping, which is complicated and probably not worthwhile. IKE keying channels likewise are torn down when it appears the need has passed. They always linger longer than the last tunnel they administer, in case they are needed again; the cost of retaining them is low. Other than that, unless the number of keying channels on the SG gets large, the SG should simply retain all of them until rekeying time, since rekeying is the only costly event. When about to rekey a keying channel which has no current tunnels, note when the last actual keying-channel traffic occurred, and close the keying channel down if it wasn't in the last, say, 30min. When rekeying a keying channel (or perhaps shortly before rekeying is expected), Initiator and Responder should re- fetch the public keys used for SG authentication, against the possibility that they have changed or disappeared. See section 2.7 for discussion of rekeying intervals. Given the low user impact of tearing down and rebuilding a connection (a tunnel or a keying channel), rekeying attempts should not be too persistent: one can always just rebuild when needed, so heroic efforts to preserve an existing con- nection are unnecessary. Say, try every 10s for a minute and every minute for 5min, and then give up and declare the connection (and all other connections to that IKE peer) dead. Rationale: In future, more sophisticated, versions of this protocol, examining the initial packet might permit a more intelligent guess at the tunnel's useful life. HTTP connec- tions in particular are notoriously bursty and repetitive. Rationale: Note that rekeying a keying connection basically consists of building a new keying connection from scratch, using IKE Phase 1, and abandoning the old one. 3.2. Teardown and Cleanup Teardown should always be coordinated with the other end. This means interpreting and sending Delete notifications. On receiving a Delete for the outbound SAs of a tunnel (or some subset of them), tear down the inbound ones too, and notify the other end with a Delete. Tunnels need to be con- sidered as bidirectional entities, even though the low-level protocols don't think of them that way. When the deletion is initiated locally, rather than as a response to a received Delete, send a Delete for (all) the inbound SAs of a tunnel. If no responding Delete is Draft 4 3 May 2001 16 Opportunistic Encryption received for the outbound SAs, try re-sending the original Delete. Three tries spaced 10s apart seems a reasonable level of effort. (Indefinite persistence is not necessary; whether the other end isn't cooperating because it doesn't feel like it, or because it is down/disconnected/etc., the problem will eventually be cleared up by other means.) After rekeying, transmission should switch to using the new SAs (ISAKMP or IPsec) immediately, and the old leftover SAs should be cleared out promptly (and Deletes sent) rather than waiting for them to expire. This reduces clutter and minimizes confusion. Since there is only one keying channel per remote IP address, the question of whether a Delete notification has appeared on a ``suitable'' keying channel does not arise. Rationale: The pairing of Delete notifications effectively constitutes an acknowledged Delete, which is highly desir- able. 3.3. Outages and Reboots Tunnels sometimes go down because the other end crashes, or disconnects, or has a network link break, and there is no notice of this in the general case. (Even in the event of a crash and successful reboot, other SGs don't hear about it unless the rebooted SG has specific reason to talk to them immediately.) Over-quick response to temporary network out- ages is undesirable... but note that a tunnel can be torn down and then re-established without any user-visible effect except a pause in traffic, whereas if one end does reboot, the other end can't get packets to it at all (except via IKE) until the situation is noticed. So a bias toward quick response is appropriate, even at the cost of occasional false alarms. Heartbeat mechanisms are somewhat unsatisfactory for this. Unless they are very frequent, which causes other problems, they do not detect the problem promptly. Ahem: What is really wanted is authenticated ICMP. This might be a case where public-key encryption/authentication of network packets is the right thing to do, despite the expense. In the absence of that, a two-part approach seems warranted. First, when an SG receives an IPsec packet that is addressed to it, and otherwise appears healthy, but specifies an unknown SA and is from a host that the receiver currently has no keying channel to, the receiver must attempt to inform the sender via an IKE Initial-Contact notification (necessarily sent in plaintext, since there is no suitable Draft 4 3 May 2001 17 Opportunistic Encryption keying channel). This must be severely rate-limited on both ends; one notification per SG pair per minute seems ample. Second, there is an obvious difficulty with this: the Ini- tial-Contact notification is unauthenticated and cannot be trusted. So it must be taken as a hint only: there must be a way to confirm it. What is needed here is something that's desirable for debug- ging and testing anyway: an IKE-level ping mechanism. Ping- ing direct at the IP level instead will not tell us about a crash/reboot event. Sending pings through tunnels has vari- ous complications (they should stop at the far mouth of the tunnel instead of going on to a subnet; they should not count against idle timers; etc.). What is needed is a con- tinuity check on a keying channel. (This could also be used as a heartbeat, should that seem useful.) IKE Ping delivery need not be reliable, since the whole point of a ping is simply to provoke an acknowledgement. They should preferably be authenticated, but it is not clear that this is absolutely necessary, although if they are not they need encryption plus a timestamp or a nonce, to foil replay mischief. How they are implemented is a secondary issue, and a separate design proposal will be prepared. Ahem: Some existing implementations are already using (pri- vate) notify value 30000 (``LIKE_HELLO'') as ping and (pri- vate) notify value 30002 (``SHUT_UP'') as ping reply. If an IKE Ping gets no response, try some (say 8) IP pings, spaced a few seconds apart, to check IP connectivity; if one comes back, try another IKE Ping; if that gets no response, the other end probably has rebooted, or otherwise been re- initialized, and its tunnels and keying channel(s) should be torn down. In a similar vein, giving limited rekeying persistence, a short network outage could take some tunnels down without disrupting others. On receiving a packet for an unknown SA from a host that a keying channel is currently open to, send that host a Invalid-SPI notification for that SA. The other host can then tear down the half-torn-down tunnel, and nego- tiate a new tunnel for the traffic it presumably still wants to send. Finally, it would be helpful if SGs made some attempt to deal intelligently with crashes and reboots. A deliberate shutdown should include an attempt to notify all other SGs currently connected by keying channels, using Deletes, that communication is about to fail. (Again, these will be taken as teardowns; attempts by the other SGs to negotiate new tunnels as replacements should be ignored at this point.) And when possible, SGs should attempt to preserve Draft 4 3 May 2001 18 Opportunistic Encryption information about currently-connected SGs in non-volatile storage, so that after a crash, an Initial-Contact can be sent to previous partners to indicate loss of all previ- ously-established connections. 4. Conclusions This design appears to achieve the objective of setting up encryption with strangers. The authentication aspects also seem adequately addressed if the destination controls its reverse-map DNS entries and the DNS data itself can be reli- ably authenticated as having originated from the legitimate administrators of that subnet/FQDN. The authentication sit- uation is less satisfactory when DNS is less helpful, but it is difficult to see what else could be done about it. 5. References [TBW] 6. Appendix: Separate Design Proposals TBW o How can we build a web of trust with DNSSEC? (See sec- tion 2.3.4.) o How can we extend DNS reverse lookups to permit reverse lookup on a subnet? (Both address and mask must appear in the name to be looked up.) (See section 2.6.) o How can rekeying be done as robustly as possible? (At least partly, this is just documenting current FreeS/WAN practice.) (See section 2.7.) o How should IKE Pings be implemented? (See section 3.3.) Draft 4 3 May 2001 19 libreswan-3.32/docs/opportunistic-v1.historic/opportunism.nr000066400000000000000000001304361365625662500244370ustar00rootroot00000000000000.DA "3 May 2001" .ds LH " .ds CH "Opportunistic Encryption .ds RH " .ds LF "Draft 4+ .ds CF "\\*(DY .ds RF % .de P .LP .. .de R .LP \fBRationale:\fR .. .de A .LP \fBAhem:\fR .. .TL Opportunistic Encryption .AU Henry Spencer D. Hugh Redelmeier .AI henry@spsystems.net hugh@mimosa.com Linux FreeS/WAN Project .AB no xxx cases where reverses not controlled, all possibilities. xxx DHR suggests okay if gateway doesn't control reverse but destination does. xxx level of patience where Responder just doesn't answer the phone. xxx IKE finger to get basic keying info, to be confirmed via DNSSEC? xxx packets from some OE connections might get special status, if the other end is definitely someone we trust. Opportunistic encryption permits secure (encrypted, authenticated) communication via IPsec without connection-by-connection prearrangement, either explicitly between hosts (when the hosts are capable of it) or transparently via packet-intercepting security gateways. It uses DNS records (authenticated with DNSSEC) to provide the necessary information for gateway discovery and gateway authentication, and constrains negotiation enough to guarantee success. .sp Substantive changes since draft 3: write off inverse queries as a lost cause; use Invalid-SPI rather than Delete as notification of unknown SA; minor wording improvements and clarifications. This document takes over from the older ``Implementing Opportunistic Encryption'' document. .AE .NH 1 Introduction .P A major goal of the FreeS/WAN project is opportunistic encryption: a (security) gateway intercepts an outgoing packet aimed at a remote host, and quickly attempts to negotiate an IPsec tunnel to that host's security gateway. If the attempt succeeds, traffic can then be secure, transparently (without changes to the host software). If the attempt fails, the packet (or a retry thereof) passes through in clear or is dropped, depending on local policy. Prearranged tunnels bypass the packet interception etc., so static VPNs can coexist with opportunistic encryption. .P This generalizes trivially to the end-to-end case: host and security gateway simply are one and the same. Some optimizations are possible in that case, but the basic scheme need not change. .P The objectives for security systems need to be explicitly stated. Opportunistic encryption is meant to achieve secure communication, without prearrangement of the individual connection (although some prearrangement on a per-host basis is required), between any two hosts which implement the protocol (and, if they act as security gateways, between hosts behind them). Here ``secure'' means strong encryption and authentication of packets, with authentication of participants\(emto prevent man-in-the-middle and impersonation attacks\(emdependent on several factors. The biggest factor is the authentication of DNS records, via DNSSEC or equivalent means. A lesser factor is which exact variant of the setup procedure (see section 2.2) is used, because there is a tradeoff between strong authentication of the other end and ability to negotiate opportunistic encryption with hosts which have limited or no control of their reverse-map DNS records: without reverse-map information, we can verify that the host has the right to use a particular FQDN (Fully Qualified Domain Name), but not whether that FQDN is authorized to use that IP address. Local policy must decide whether authentication or connectivity has higher priority. .P Apart from careful attention to detail in various areas, there are three crucial design problems for opportunistic encryption. It needs a way to quickly identify the remote host's security gateway. It needs a way to quickly obtain an authentication key for the security gateway. And the numerous options which can be specified with IKE must be constrained sufficiently that two independent implementations are guaranteed to reach agreement, without any explicit prearrangement or preliminary negotiation. The first two problems are solved using DNS, with DNSSEC ensuring that the data obtained is reliable; the third is solved by specifying a minimum standard which must be supported. .P A note on philosophy: we have deliberately avoided providing six different ways to do each job, in favor of specifying one good one. Choices are provided only when they appear to be necessary, or at least important. .P A note on terminology: to avoid constant circumlocutions, an ISAKMP/IKE SA, possibly recreated occasionally by rekeying, will be referred to as a ``keying channel'', and a set of IPsec SAs providing bidirectional communication between two IPsec hosts, possibly recreated occasionally by rekeying, will be referred to as a ``tunnel'' (it could conceivably use transport mode in the host-to-host case, but we advocate using tunnel mode even there). The word ``connection'' is here used in a more generic sense. The word ``lifetime'' will be avoided in favor of ``rekeying interval'', since many of the connections will have useful lives far shorter than any reasonable rekeying interval, and hence the two concepts must be separated. .P A note on document structure: Discussions of \fIwhy\fR things were done a particular way, or not done a particular way, are broken out in paragraphs headed ``Rationale:'' (to preserve the flow of the text, many such paragraphs are deferred to the ends of sections). Paragraphs headed ``Ahem:'' are discussions of where the problem is being made significantly harder by problems elsewhere, and how that might be corrected. Some meta-comments are enclosed in []. .R The motive is to get the Internet encrypted. That requires encryption without connection-by-connection prearrangement: a system must be able to reliably negotiate an encrypted, authenticated connection with a total stranger. While end-to-end encryption is preferable, doing opportunistic encryption in security gateways gives enormous leverage for quick deployment of this technology, in a world where end-host software is often primitive, rigid, and outdated. .R Speed is of the essence in tunnel setup: a connection-establishment delay longer than about 10 seconds begins to cause problems for users and applications. Thus the emphasis on rapidity in gateway discovery and key fetching. .A Host-to-host opportunistic encryption would be utterly trivial if a fast public-key encryption/signature algorithm was available. You would do a reverse lookup on the destination address to obtain a public key for that address, and simply encrypt all packets going to it with that key, signing them with your own private key. Alas, this is impractical with current CPU speeds and current algorithms (although as noted later, it might be of some use for limited purposes). Nevertheless, it is a useful model. .NH 1 Connection Setup .P For purposes of discussion, the network is taken to look like this: .DS Source----Initiator----...----Responder----Destination .DE The intercepted packet comes from the Source, bound for the Destination, and is intercepted at the Initiator. The Initiator communicates over the insecure Internet to the Responder. The Source and the Initiator might be the same host, or the Source might be an end-user host and the Initiator a security gateway (SG). Likewise for the Responder and the Destination. .P Given an intercepted packet, whose useful information (for our purposes) is essentially only the Destination's IP address, the Initiator must quickly determine the Responder (the Destination's SG) and fetch everything needed to authenticate it. The Responder must do likewise for the Initiator. Both must eventually also confirm that the other is authorized to act on behalf of the client host behind it (if any). .P An important subtlety here is that if the alternative to an IPsec tunnel is plaintext transmission, negative results must be obtained quickly. That is, the decision that \fIno\fR tunnel can be established must also be made rapidly. .NH 2 Packet Interception .P Interception of outgoing packets is relatively straightforward in principle. It is preferable to put the intercepted packet on hold rather than dropping it, since higher-level retries are not necessarily well-timed. There is a problem of hosts and applications retrying during negotiations. ARP implementations, which face the same problem, use the approach of keeping the \fImost recent\fR packet for an as-yet-unresolved address, and throwing away older ones. (Incrementing of request numbers etc. means that replies to older ones may no longer be accepted.) .P Is it worth intercepting \fIincoming\fR packets, from the outside world, and attempting tunnel setup based on them? No, unless and until a way can be devised to initiate opportunistic encryption to a non-opportunistic responder, because if the other end has not initiated tunnel setup itself, it will not be prepared to do so at our request. .R Note, however, that most incoming packets will promptly be followed by an outgoing packet in response! Conceivably it might be useful to start early stages of negotiation, at least as far as looking up information, in response to an incoming packet. .R If a plaintext incoming packet indicates that the other end is not prepared to do opportunistic encryption, it might seem that this fact should be noted, to avoid consuming resources and delaying traffic in an attempt at opportunistic setup which is doomed to fail. However, this would be a major security hole, since the plaintext packet is not authenticated; see section 2.5. .NH 2 Algorithm .P For clarity, the following defers most discussion of error handling to the end. .nr x \w'Step 3A.'u+1n .de S .IP "Step \\$1." \nxu .. .S 1 Initiator does a DNS reverse lookup on the Destination address, asking not for the usual PTR records, but for TXT records. Meanwhile, Initiator also sends a ping to the Destination, to cause any other dynamic setup actions to start happening. (Ping replies are disregarded; the host might not be reachable with plaintext pings.) .S 2A If at least one suitable TXT record (see section 2.3) comes back, each contains a potential Responder's IP address and that Responder's public key (or where to find it). Initiator picks one TXT record, based on priority (see 2.3), thus picking a Responder. If there was no public key in the TXT record, the Initiator also starts a DNS lookup (as specified by the TXT record) to get KEY records. .S 2B If no suitable TXT record is available, and policy permits, Initiator designates the Destination itself as the Responder (see section 2.4). If policy does not permit, or the Destination is unresponsive to the negotiation, then opportunistic encryption is not possible, and Initiator gives up (see section 2.5). .S 3 If there already is a keying channel to the Responder's IP address, the Initiator uses the existing keying channel; skip to step 10. Otherwise, the Initiator starts an IKE Phase 1 negotiation (see section 2.7 for details) with the Responder. The address family of the Responder's IP address dictates whether the keying channel and the outside of the tunnel should be IPv4 or IPv6. .S 4 Responder gets the first IKE message, and responds. It also starts a DNS reverse lookup on the Initiator's IP address, for KEY records, on speculation. .S 5 Initiator gets Responder's reply, and sends first message of IKE's D-H exchange (see 2.4). .S 6 Responder gets Initiator's D-H message, and responds with a matching one. .S 7 Initiator gets Responder's D-H message; encryption is now established, authentication remains to be done. Initiator sends IKE authentication message, with an FQDN identity if a reverse lookup on its address will not yield a suitable KEY record. (Note, an FQDN need not actually correspond to a host\(eme.g., the DNS data for it need not include an A record.) .S 8 Responder gets Initiator's authentication message. If there is no identity included, Responder waits for step 4's speculative DNS lookup to finish; it should yield a suitable KEY record (see 2.3). If there is an FQDN identity, responder discards any data obtained from step 4's DNS lookup; does a forward lookup on the FQDN, for a KEY record; waits for that lookup to return; it should yield a suitable KEY record. Either way, Responder uses the KEY data to verify the message's hash. Responder replies with an authentication message, with an FQDN identity if a reverse lookup on its address will not yield a suitable KEY record. .S 9A (If step 2A was used.) The Initiator gets the Responder's authentication message. Step 2A has provided a key (from the TXT record or via DNS lookup). Verify message's hash. Encrypted and authenticated keying channel established, man-in-middle attack precluded. .S 9B (If step 2B was used.) The Initiator gets the Responder's authentication message, which must contain an FQDN identity (if the Responder can't put a TXT in his reverse map he presumably can't do a KEY either). Do forward lookup on the FQDN, get suitable KEY record, verify hash. Encrypted keying channel established, man-in-middle attack precluded, but authentication weak (see 2.4). .S 10 Initiator initiates IKE Phase 2 negotiation (see 2.7) to establish tunnel, specifying Source and Destination identities as IP addresses (see 2.6). The address family of those addresses also determines whether the inside of the tunnel should be IPv4 or IPv6. .S 11 Responder gets first Phase 2 message. Now the Responder finally knows what's going on! Unless the specified Source is identical to the Initiator, Responder initiates DNS reverse lookup on Source IP address, for TXT records; waits for result; gets suitable TXT record(s) (see 2.3), which should contain either the Initiator's IP address or an FQDN identity identical to that supplied by the Initiator in step 7. This verifies that the Initiator is authorized to act as SG for the Source. Responder replies with second Phase 2 message, selecting acceptable details (see 2.7), and establishes tunnel. .S 12 Initiator gets second Phase 2 message, establishes tunnel (if he didn't already), and releases the intercepted packet into it, finally. .S 13 Communication proceeds. See section 3 for what happens later. .P As additional information becomes available, notably in steps 1, 2, 4, 8, 9, 11, and 12, there is always a possibility that local policy (e.g., access limitations) might prevent further progress. Whenever possible, at least attempt to inform the other end of this. .P At any time, there is a possibility of the negotiation failing due to unexpected responses, e.g. the Responder not responding at all or rejecting all Initiator's proposals. If multiple SGs were found as possible Responders, the Initiator should try at least one more before giving up. The number tried should be influenced by what the alternative is: if the traffic will otherwise be discarded, trying the full list is probably appropriate, while if the alternative is plaintext transmission, it might be based on how long the tries are taking. The Initiator should try as many as it reasonably can, ideally all of them. .P There is a sticky problem with timeouts. If the Responder is down or otherwise inaccessible, in the worst case we won't hear about this except by not getting responses. Some other, more pathological or even evil, failure cases can have the same result. The problem is that in the case where plaintext is permitted, we want to decide whether a tunnel is possible quickly. There is no good solution to this, alas; we just have to take the time and do it right. (Passing plaintext meanwhile looks attractive at first glance... but exposing the first few seconds of a connection is often almost as bad as exposing the whole thing. Worse, if the user checks the status of the connection, after that brief window it looks secure!) .P The flip side of waiting for a timeout is that all other forms of feedback, e.g. ``host not reachable'', arguably should be \fIignored\fR, because in the absence of authenticated ICMP, you cannot trust them! .R An alternative, sometimes suggested, to the use of explicit DNS records for SG discovery is to directly attempt IKE negotiation with the destination host, and assume that any relevant SG will be on the packet path, will intercept the IKE packets, and will impersonate the destination host for the IKE negotiation. This is superficially attractive but is a very bad idea. It assumes that routing is stable throughout negotiation, that the SG is on the plaintext-packets path, and that the destination host is routable (yes, it is possible to have (private) DNS data for an unroutable host). Playing extra games in the plaintext-packet path hurts performance and can be expected to be unpopular. Various difficulties ensue when there are multiple SGs along the path (there is already bad experience with this, in RSVP), and the presence of even one can make it impossible to do IKE direct to the host when that is what's wanted. Worst of all, such impersonation breaks the IP network model badly, making problems difficult to diagnose and impossible to work around (and there is already bad experience with this, in areas like web caching). .R (Step 1.) Dynamic setup actions might include establishment of demand-dialed links. These might be present anywhere along the path, so one cannot rely on out-of-band communication at the Initiator to trigger them. Hence the ping. .R (Step 2.) In many cases, the IP address on the intercepted packet will be the result of a name lookup just done. Inverse queries, an obscure DNS feature from the distant past, in theory can be used to ask a DNS server to reverse that lookup, giving the name that produced the address. This is not the same as a reverse lookup, and the difference can matter a great deal in cases where a host does not control its reverse map (e.g., when the host's IP address is dynamically assigned). Unfortunately, inverse queries were never widely implemented and are now considered obsolete. Phooey. .A Support for a small subset of this admittedly-obscure feature would be useful. Unfortunately, it seems unlikely. .R (Step 3.) Using only IP addresses to decide whether there is already a relevant keying channel avoids some difficult problems. In particular, it might seem that this should be based on identities, but those are not known until very late in IKE Phase 1 negotiations. .R (Step 4.) The DNS lookup is done on speculation because the data will probably be useful and the lookup can be done in parallel with IKE activity, potentially speeding things up. .R (Steps 7 and 8.) If an SG does not control its reverse map, there is no way it can prove its right to use an IP address, but it can nevertheless supply both an identity (as an FQDN) and proof of its right to use that identity. This is somewhat better than nothing, and may be quite useful if the SG is representing a client host which \fIcan\fR prove its right to \fIits\fR IP address. (For example, a fixed-address subnet might live behind an SG with a dynamically-assigned address; such an SG has to be the Initiator, not the Responder, so the subnet's TXT records can contain FQDN identities, but with that restriction, this works.) It might sound like this would permit some man-in-the-middle attacks in important cases like Road Warrior, but the RW can still do full authentication of the home base, so a man in the middle cannot successfully impersonate home base, and the D-H exchange doesn't work unless the man in the middle impersonates \fIboth\fR ends. .R (Steps 7 and 8.) Another situation where proof of the right to use an identity can be very useful is when access is deliberately limited. While opportunistic encryption is intended as a general-purpose connection mechanism between strangers, it may well be convenient for prearranged connections to use the same mechanism. .R (Steps 7 and 8.) FQDNs as identities are avoided where possible, since they can involve synchronous DNS lookups. .R (Step 11.) Note that only here, in Phase 2, does the Responder actually learn who the Source and Destination hosts are. This unfortunately demands a synchronous DNS lookup to verify that the Initiator is authorized to represent the Source, unless they are one and the same. This and the initial TXT lookup are the only synchronous DNS lookups absolutely required by the algorithm, and they appear to be unavoidable. .R While it might seem unlikely that a refusal to cooperate from one SG could be remedied by trying another\(empresumably they all use the same policies\(emit's conceivable that one might be misconfigured. Preferably they should all be tried, but it may be necessary to set some limits on this if alternatives exist. .NH 2 DNS Records .P Gateway discovery and key lookup are based on TXT and KEY DNS records. The TXT record specifies IP address or other identity of a host's SG, and possibly supplies its public key as well, while the KEY record supplies public keys not found in TXT records. .NH 3 TXT .P Opportunistic-encryption SG discovery uses TXT records with the content: .DS X-IPsec-Gateway(\fInnn\fR)=\fIiii\fR\ \fIkkk\fR .DE following RFC 1464 attribute/value notation. Records which do not contain an ``='', or which do not have exactly the specified form to the left of it, are ignored. (Near misses perhaps should be reported.) .P The \fInnn\fR is an unsigned integer which will fit in 16 bits, specifying an MX-style preference (lower number = stronger preference) to control the order in which multiple SGs are tried. If there are ties, pick one, randomly enough that the choice will probably be different each time. xxx rollover. The preference field is not optional; use ``0'' if there is no meaningful preference ordering. .P The \fIiii\fR part identifies the SG. Normally this is a dotted-decimal IPv4 address or a colon-hex IPv6 address. The sole exception is if the SG has no fixed address (see 2.4) but the host(s) behind it do, in which case \fIiii\fR is of the form ``@fqdn'', where \fIfqdn\fR is the FQDN that the SG will use to identify itself (in step 7 of section 2.2); such a record cannot be used for SG discovery by an Initiator, but can be used for SG verification (step 11 of 2.2) by a Responder. .P The \fIkkk\fR part is optional. If it is present, it is an RSA-MD5 public key in base-64 notation, as in the text form of an RFC 2535 KEY record. If it is not present, this specifies that the public key can be found in a KEY record located based on the SG's identification: if \fIiii\fR is an IP address, do a reverse lookup on that address, else do a forward lookup on the FQDN. .R While it is unusual for a reverse lookup to go for records other than PTR records (or possibly CNAME records, for RFC 2317 classless delegation), there's no reason why it can't. The TXT record is a temporary stand-in for (we hope, someday) a new DNS record for SG identification and keying. Keeping the setup process fast requires minimizing the number of DNS lookups, hence the desire to put all the information in one place. .R The use of RFC 1464 notation avoids collisions with other uses of TXT records. The ``X-'' in the attribute name indicates that this format is tentative and experimental; this design will probably need modification after initial experiments. The format is chosen with an eye on eventual binary encoding. Note, in particular, that the TXT record normally contains the \fIaddress\fR of the SG, not (repeat, not) its name. Name-to-address conversion is the job of whatever generates the TXT record, which is expected to be a program, not a human\(emthis is conceptually a \fIbinary\fR record, temporarily using a text encoding. The ``@fqdn'' form of the SG identity is for specialized uses and is never mapped to an address. .A A DNS TXT record contains one or more character strings, but RFC 1035 does not describe exactly how a multi-string TXT record is interpreted. This is relevant because a string can be at most 255 characters, and public keys can exceed this. Empirically, the standard pattern is that each string which is both less than 255 characters \fIand\fR not the final string of the record should have a blank appended to it, and the strings of the record should then be concatenated. (This observation is based on how BIND 8 transforms a TXT record from text to DNS binary.) .NH 3 KEY .P An opportunistic-encryption KEY record is an Authentication-permitted, Entity (host), non-Signatory, IPsec, RSA/MD5 record (that is, its first four bytes are 0x42000401), as per RFCs 2535 and 2537. KEY records with other \fIflags\fR, \fIprotocol\fR, or \fIalgorithm\fR values are ignored. .R Unfortunately, the public key has to be associated with the SG, not the client host behind it. The Responder does not know which client it is supposed to be representing, or which client the Initiator is representing, until far too late. .A Per-client keys would reduce vulnerability to key compromise, and simplify key changes, but they would require changes to IKE Phase 1, to separately identify the SG and its initial client(s). (At present, the client identities are not known to the Responder until IKE Phase 2.) While the current IKE standard does not actually specify (!) who is being identified by identity payloads, the overwhelming consensus is that they identify the SG, and as seen earlier, this has important uses. .NH 3 Summary .P For reference, the minimum set of DNS records needed to make this all work is either: .IP 1. \w'1.'u+2n TXT in Destination reverse map, identifying Responder and providing public key. .IP 2. KEY in Initiator reverse map, providing public key. .IP 3. TXT in Source reverse map, verifying relationship to Initiator. .P or: .IP 1. \w'1.'u+2n TXT in Destination reverse map, identifying Responder. .IP 2. KEY in Responder reverse map, providing public key. .IP 3. KEY in Initiator reverse map, providing public key. .IP 4. TXT in Source reverse map, verifying relationship to Initiator. .P Slight complications ensue for dynamic addresses, lack of control over reverse maps, etc. .NH 3 Implementation .P In the long run, we need either a tree of trust or a web of trust, so we can trust our DNS data. The obvious approach for DNS is a tree of trust, but there are various practical problems with running all of this through the root servers, and a web of trust is arguably more robust anyway. This is logically independent of opportunistic encryption, and a separate design proposal will be prepared. .P Interim stages of implementation of this will require a bit of thought. Notably, we need some way of dealing with the lack of fully signed DNSSEC records right away. Without user interaction, probably the best we can do is to remember the results of old fetches, compare them to the results of new fetches, and complain and disbelieve all of it if there's a mismatch. This does mean that somebody who gets fake data into our very first fetch will fool us, at least for a while, but that seems an acceptable tradeoff. (Obviously there needs to be a way to manually flush the remembered results for a specific host, to permit deliberate changes.) .NH 2 Responders Without Credentials .P In cases where the Destination simply does not control its DNS reverse-map entries, there is no verifiable way to determine a suitable SG. This does not make communication utterly impossible, though. .P Simply attempting negotiation directly with the host is a last resort. (An aggressive implementation might wish to attempt it in parallel, rather than waiting until other options are known to be unavailable.) In particular, in many cases involving dynamic addresses, it will work. It has the disadvantage of delaying the discovery that opportunistic encryption is entirely impossible, but the case seems common enough to justify the overhead. .P However, there are policy issues here either way, because it is possible to impersonate such a host. The host can supply an FQDN identity and verify its right to use that identity, but except by prearrangement, there is no way to verify that the FQDN is the right one for that IP address. (The data from forward lookups may be controlled by people who do not own the address, so it cannot be trusted.) The encryption is still solid, though, so in many cases this may be useful. .NH 2 Failure of Opportunism .P When there is no way to do opportunistic encryption, a policy issue arises: whether to put in a bypass (which allows plaintext traffic through) or a block (which discards it, perhaps with notification back to the sender). The choice is very much a matter of local policy, and may depend on details such as the higher-level protocol being used. For example, an SG might well permit plaintext HTTP but forbid plaintext Telnet, in which case \fIboth\fR a block and a bypass would be set up if opportunistic encryption failed. .P A bypass/block must, in practice, be treated much like an IPsec tunnel. It should persist for a while, so that high-overhead processing doesn't have to be done for every packet, but should go away eventually to return resources. It may be simplest to treat it as a degenerate tunnel. It should have a relatively long lifetime (say 6h) to keep the frequency of negotiation attempts down, except in the case where the other SG simply did not respond to IKE packets, where the lifetime should be short (say 10min) because the other SG is presumably down and might come back up again. (Cases where the other SG responded to IKE with unauthenticated error reports like ``port unreachable'' are borderline, and might deserve to be treated as an intermediate case: while such reports cannot be trusted unreservedly, in the absence of any other response, they do give some reason to suspect that the other SG is unable or unwilling to participate in opportunistic encryption.) .P As noted in section 2.1, one might think that arrival of a plaintext incoming packet should cause a bypass/block to be set up for its source host: such a packet is almost always followed by an outgoing reply packet; the incoming packet is clear evidence that opportunistic encryption is not available at the other end; attempting it will waste resources and delay traffic to no good purpose. Unfortunately, this means that anyone out on the Internet who can forge a source address can prevent encrypted communication! Since their source addresses are not authenticated, plaintext packets cannot be taken as evidence of anything, except perhaps that communication from that host is likely to occur soon. .P There needs to be a way for local administrators to remove a bypass/block ahead of its normal expiry time, to force a retry after a problem at the other end is known to have been fixed. .NH 2 Subnet Opportunism .P In principle, when the Source or Destination host belongs to a subnet and the corresponding SG is willing to provide tunnels to the whole subnet, this should be done. There is no extra overhead, and considerable potential for avoiding later overhead if similar communication occurs with other members of the subnet. Unfortunately, at the moment, opportunistic tunnels can only have degenerate subnets (single hosts) at their ends. (This does, at least, set up the keying channel, so that negotiations for tunnels to other hosts in the same subnets will be considerably faster.) .P The crucial problem is step 11 of section 2.2: the Responder must verify that the Initiator is authorized to represent the Source, and this is impossible for a subnet because there is no way to do a reverse lookup on it. Information in DNS records for a name or a single address cannot be trusted, because they may be controlled by people who do not control the whole subnet. .A Except in the special case of a subnet masked on a byte boundary (in which case RFC 1035's convention of an incomplete in-addr.arpa name could be used), subnet lookup would need extensions to the reverse-map name space, perhaps along the lines of that commonly done for RFC 2317 delegation. IPv6 already has suitable name syntax, as in RFC 2874, but has no specific provisions for subnet entries in its reverse maps. Fixing all this is is not conceptually difficult, but is logically independent of opportunistic encryption, and will be proposed separately. .P A less-troublesome problem is that the Initiator, in step 10 of 2.2, must know exactly what subnet is present on the Responder's end so he can propose a tunnel to it. This information could be included in the TXT record of the Destination (it would have to be verified with a subnet lookup, but that could be done in parallel with other operations). The Initiator presumably can be configured to know what subnet(s) are present on its end. .NH 2 Option Settings .P IPsec and IKE have far too many useless options, and a few useful ones. IKE negotiation is quite simplistic, and cannot handle even simple discrepancies between the two SGs. So it is necessary to be quite specific about what should be done and what should be proposed, to guarantee interoperability without prearrangement or other negotiation protocols. .R The prohibition of other negotiations is simply because there is no time. The setup algorithm (section 2.2) is lengthy already. .P [Open question: should opportunistic IKE use a different port than normal IKE?] .P Somewhat arbitrarily and tentatively, opportunistic SGs must support Main Mode, Oakley group 5 for D-H, 3DES encryption and MD5 authentication for both ISAKMP and IPsec SAs, RSA/MD5 digital-signature authentication with keys between 2048 and 8192 bits, and ESP doing both encryption and authentication. They must do key PFS in Quick Mode, but not identity PFS. They may support IPComp, preferably using Deflate, but must not insist on it. They may support AES as an alternative to 3DES, but must not insist on it. .R Identity PFS essentially requires establishing a complete new keying channel for each new tunnel, but key PFS just does a new Diffie-Hellman exchange for each rekeying, which is relatively cheap. .P Keying channels must remain in existence at least as long as any tunnel created with them remains (they are not costly, and keeping the management path up and available simplifies various issues). See section 3.1 for related issues. Given the use of key PFS, frequent rekeying does not seem critical here. In the absence of strong reason to do otherwise, the Initiator should propose rekeying at 8hr-or-1MB. The Responder must accept any proposal which specifies a rekeying time between 1hr and 24hr inclusive and a rekeying volume between 100KB and 10MB inclusive. .P Given the short expected useful life of most tunnels (see section 3.1), very few of them will survive long enough to be rekeyed. In the absence of strong reason to do otherwise, the Initiator should propose rekeying at 1hr-or-100MB. The Responder must accept any proposal which specifies a rekeying time between 10min and 8hr inclusive and a rekeying volume between 1MB and 1000MB inclusive. .P It is highly desirable to add some random jitter to the times of actual rekeying attempts, to break up ``convoys'' of rekeying events; this and certain other aspects of robust rekeying practice will be the subject of a separate design proposal. .R The numbers used here for rekeying intervals are chosen quite arbitrarily and should be re-assessed after some implementation experience is gathered. .NH 1 Renewal and Teardown .NH 2 Aging .P When to tear tunnels down is a bit problematic, but if we're setting up a potentially unbounded number of them, we have to tear them down \fIsomehow sometime\fR. .P Set a short initial tentative lifespan, say 1min, since most net flows in fact last only a few seconds. When that expires, look to see if the tunnel is still in use (definition: has had traffic, in either direction, in the last half of the tentative lifespan). If so, assign it a somewhat longer tentative lifespan, say 20min, after which, look again. If not, close it down. (This tentative lifespan is independent of rekeying; it is just the time when the tunnel's future is next considered. This should happen reasonably frequently, unlike rekeying, which is costly and shouldn't be too frequent.) Multi-step backoff algorithms are not worth the trouble; looking every 20min doesn't seem onerous. .P If the security gateway and the client host are one and the same, tunnel teardown decisions might wish to pay attention to TCP connection status, as reported by the local TCP layer. A still-open TCP connection is almost a guarantee that more traffic is coming, while the demise of the only TCP connection through a tunnel is a strong hint that none is. If the SG and the client host are separate machines, though, tracking TCP connection status requires packet snooping, which is complicated and probably not worthwhile. .P IKE keying channels likewise are torn down when it appears the need has passed. They always linger longer than the last tunnel they administer, in case they are needed again; the cost of retaining them is low. Other than that, unless the number of keying channels on the SG gets large, the SG should simply retain all of them until rekeying time, since rekeying is the only costly event. When about to rekey a keying channel which has no current tunnels, note when the last actual keying-channel traffic occurred, and close the keying channel down if it wasn't in the last, say, 30min. When rekeying a keying channel (or perhaps shortly before rekeying is expected), Initiator and Responder should re-fetch the public keys used for SG authentication, against the possibility that they have changed or disappeared. .P See section 2.7 for discussion of rekeying intervals. .P Given the low user impact of tearing down and rebuilding a connection (a tunnel or a keying channel), rekeying attempts should not be too persistent: one can always just rebuild when needed, so heroic efforts to preserve an existing connection are unnecessary. Say, try every 10s for a minute and every minute for 5min, and then give up and declare the connection (and all other connections to that IKE peer) dead. .R In future, more sophisticated, versions of this protocol, examining the initial packet might permit a more intelligent guess at the tunnel's useful life. HTTP connections in particular are notoriously bursty and repetitive. .R Note that rekeying a keying connection basically consists of building a new keying connection from scratch, using IKE Phase 1, and abandoning the old one. .NH 2 Teardown and Cleanup .P Teardown should always be coordinated with the other end. This means interpreting and sending Delete notifications. .P On receiving a Delete for the outbound SAs of a tunnel (or some subset of them), tear down the inbound ones too, and notify the other end with a Delete. Tunnels need to be considered as bidirectional entities, even though the low-level protocols don't think of them that way. .P When the deletion is initiated locally, rather than as a response to a received Delete, send a Delete for (all) the inbound SAs of a tunnel. If no responding Delete is received for the outbound SAs, try re-sending the original Delete. Three tries spaced 10s apart seems a reasonable level of effort. (Indefinite persistence is not necessary; whether the other end isn't cooperating because it doesn't feel like it, or because it is down/disconnected/etc., the problem will eventually be cleared up by other means.) .P After rekeying, transmission should switch to using the new SAs (ISAKMP or IPsec) immediately, and the old leftover SAs should be cleared out promptly (and Deletes sent) rather than waiting for them to expire. This reduces clutter and minimizes confusion. .P Since there is only one keying channel per remote IP address, the question of whether a Delete notification has appeared on a ``suitable'' keying channel does not arise. .R The pairing of Delete notifications effectively constitutes an acknowledged Delete, which is highly desirable. .NH 2 Outages and Reboots .P Tunnels sometimes go down because the other end crashes, or disconnects, or has a network link break, and there is no notice of this in the general case. (Even in the event of a crash and successful reboot, other SGs don't hear about it unless the rebooted SG has specific reason to talk to them immediately.) Over-quick response to temporary network outages is undesirable... but note that a tunnel can be torn down and then re-established without any user-visible effect except a pause in traffic, whereas if one end does reboot, the other end can't get packets to it \fIat all\fR (except via IKE) until the situation is noticed. So a bias toward quick response is appropriate, even at the cost of occasional false alarms. .P Heartbeat mechanisms are somewhat unsatisfactory for this. Unless they are very frequent, which causes other problems, they do not detect the problem promptly. .A What is really wanted is authenticated ICMP. This might be a case where public-key encryption/authentication of network packets is the right thing to do, despite the expense. .P In the absence of that, a two-part approach seems warranted. .P First, when an SG receives an IPsec packet that is addressed to it, and otherwise appears healthy, but specifies an unknown SA and is from a host that the receiver currently has no keying channel to, the receiver must attempt to inform the sender via an IKE Initial-Contact notification (necessarily sent in plaintext, since there is no suitable keying channel). This must be severely rate-limited on \fIboth\fR ends; one notification per SG pair per minute seems ample. .P Second, there is an obvious difficulty with this: the Initial-Contact notification is unauthenticated and cannot be trusted. So it must be taken as a hint only: there must be a way to confirm it. .P What is needed here is something that's desirable for debugging and testing anyway: an IKE-level ping mechanism. Pinging direct at the IP level instead will not tell us about a crash/reboot event. Sending pings through tunnels has various complications (they should stop at the far mouth of the tunnel instead of going on to a subnet; they should not count against idle timers; etc.). What is needed is a continuity check on a keying channel. (This could also be used as a heartbeat, should that seem useful.) .P IKE Ping delivery need not be reliable, since the whole point of a ping is simply to provoke an acknowledgement. They should preferably be authenticated, but it is not clear that this is absolutely necessary, although if they are not they need encryption plus a timestamp or a nonce, to foil replay mischief. How they are implemented is a secondary issue, and a separate design proposal will be prepared. .A Some existing implementations are already using (private) notify value 30000 (``LIKE_HELLO'') as ping and (private) notify value 30002 (``SHUT_UP'') as ping reply. .P If an IKE Ping gets no response, try some (say 8) IP pings, spaced a few seconds apart, to check IP connectivity; if one comes back, try another IKE Ping; if that gets no response, the other end probably has rebooted, or otherwise been re-initialized, and its tunnels and keying channel(s) should be torn down. .P In a similar vein, giving limited rekeying persistence, a short network outage could take some tunnels down without disrupting others. On receiving a packet for an unknown SA from a host that a keying channel is currently open to, send that host a Invalid-SPI notification for that SA. xxx that's not what Invalid-SPI is for. The other host can then tear down the half-torn-down tunnel, and negotiate a new tunnel for the traffic it presumably still wants to send. .P Finally, it would be helpful if SGs made some attempt to deal intelligently with crashes and reboots. A deliberate shutdown should include an attempt to notify all other SGs currently connected by keying channels, using Deletes, that communication is about to fail. (Again, these will be taken as teardowns; attempts by the other SGs to negotiate new tunnels as replacements should be ignored at this point.) And when possible, SGs should attempt to preserve information about currently-connected SGs in non-volatile storage, so that after a crash, an Initial-Contact can be sent to previous partners to indicate loss of all previously-established connections. .NH 1 Conclusions .P This design appears to achieve the objective of setting up encryption with strangers. The authentication aspects also seem adequately addressed if the destination controls its reverse-map DNS entries and the DNS data itself can be reliably authenticated as having originated from the legitimate administrators of that subnet/FQDN. The authentication situation is less satisfactory when DNS is less helpful, but it is difficult to see what else could be done about it. .NH 1 References .P [TBW] .NH 1 Appendix: Separate Design Proposals TBW .IP \(bu \w'\(bu'u+2n How can we build a web of trust with DNSSEC? (See section 2.3.4.) .IP \(bu How can we extend DNS reverse lookups to permit reverse lookup on a subnet? (Both address and mask must appear in the name to be looked up.) (See section 2.6.) .IP \(bu How can rekeying be done as robustly as possible? (At least partly, this is just documenting current FreeS/WAN practice.) (See section 2.7.) .IP \(bu How should IKE Pings be implemented? (See section 3.3.) libreswan-3.32/docs/pluto-internals.txt000066400000000000000000000347461365625662500203160ustar00rootroot00000000000000Routing and Erouting in Pluto ============================= This is meant as internal documentation for Pluto. As such, it presumes some understanding of Pluto's code. It also describes KLIPS 1 erouting, including details not otherwise documented. KLIPS 1 documentation would be better included in KLIPS. Routing and erouting are complicated enough that the Pluto code needs a guide. This document is meant to be that guide. Mechanisms available to Pluto ----------------------------- All outbound packets that are to be processed by KLIPS 1 must be routed to an ipsecN network interface. Pluto only uses normal routing (as opposed to "Advanced Routing"), so the selection of packets is made solely on the basis of the destination address. (Since the actual routing commands are in the updown script, they could be changed by the administrator, but Pluto needs to understand what is going on, and it currently assumes normal routing is used.) When an outbound packet hits an ipsecN interface, KLIPS figures out how to process it by finding an eroute that applies to the source and destination addresses. Eroutes are global: they are not specific to a particular ipsecN interface (routing needs to get the packets to any ipsecN interface; erouting takes it from there, ignoring issues of source IP address and nexthop (because nobody knows!)). If multiple eroutes apply to the packet, among the ones with the most specific source subnet, the one with the most specific destination subset is chosen (RGB thinks). If no eroute is discovered, KLIPS acts as if it was covered by a DROP eroute (this is the default behaviour; it can be changed). At most one eroute can exist for a particular pair of client subnets. There are fundamentally two kinds of eroutes: "shunt" eroutes and ones that specify that a packet is to be processed by a group of IPSEC SAs. Shunt eroutes specify what is to be done with the packet. Remember that these only apply to outbound packets. - TRAP: notify Pluto of the packet (presumably to attempt to negotiate an appropriate group of IPSEC SAs). At the same time, KLIPS installs a HOLD shunt (see below) for the specific source and destination addresses from the packet and retains the packet for later reprocessing (KLIPS does not yet implement retention). Beware: if the TRAP's subnets both contained a single IP address then installing the HOLD would actually delete the TRAP. - PASS: let the packet through in the clear - DROP: discard the packet - REJECT: discard the packet and notify the sender - HOLD: (automatically created by KLIPS when a TRAP fires) block the packet, but retain it. If there is already a retained packet, drop the old one and retain the new. When the HOLD shunt is deleted or replaced, the retained packet is reinjected -- there might now be a tunnel. Note that KLIPS doesn't yet implement the retention part, so HOLD is really like a DROP. One consequence of there being only one eroute for a pair of clients is that KLIPS will only use one SA group for output for this pair, even though there could be several SA groups that are authorised and live. Pluto chooses to make this the youngest such group. KLIPS lets through in the clear outbound UDP/500 packets that would otherwise be processed if they originate on this host and meet certain other conditions. The actual test is source == me && (no_eroute || dest == eroute.dest || isanyaddr(eroute.dest)) && port == UDP/500 The idea is that IKE packets between us and a peer should not be sent through an IPSEC tunnel negotiated between us. Furthermore, our shunt eroutes should not apply to our IKE packets (shunt eroutes will generally have an eroute.dest of 0.0.0.0 or its IPv6 equivalent). Inbound behaviour is controlled in a quite different way. KLIPS processes only those inbound packets of ESP or AH protocol, with a destination address for this machine's ipsecN interfaces. The processing is as dictated by the SAs involved. Unfortunately, the decapsulated packet's source and destination address are not checked (part of "inbound policy checking"). To prevent clear packets being accepted, firewall rules must be put in place. This has nothing to do with KLIPS, but is nonetheless in important part of security. It isn't clear what firewalling makes sense when Opportunism is allowed. For routing and firewalling, Pluto invokes the updown script. Pluto installs eroutes via extended PF_KEY messages. Current Pluto Behaviour ----------------------- Data Structures: Routes and most eroutes are associated with connections (struct connection, a potential connection description). The enum routing_t field "routing" in struct connection records the state of routing and erouting for that connection. The values are: RT_UNROUTED, /* unrouted */ RT_UNROUTED_HOLD, /* unrouted, but HOLD shunt installed */ RT_ROUTED_PROSPECTIVE, /* routed, and TRAP shunt installed */ RT_ROUTED_HOLD, /* routed, and HOLD shunt installed */ RT_ROUTED_FAILURE, /* routed, and failure-context shunt installed */ RT_ROUTED_TUNNEL /* routed, and erouted to an IPSEC SA group */ Notice that the routing and erouting are not independent: erouting (except for HOLD) implies that the connection is routed. Several struct connections may have the same destination subnet. If they agree on what the route should be, they can share it -- any of them may have routing >= RT_ROUTED_PROSPECTIVE. If they disagree, they cannot simultaneously be routed. invariant: for all struct connections c, d: (c.that.client == d.that.client && c.routing >= RT_ROUTED_PROSPECTIVE && d.routing >= RT_ROUTED_PROSPECTIVE) => c.interface == d.interface && c.this.nexthop == d.this.nexthop There are two kinds of eroutes: shunt eroutes and ones for an IPSEC SA Group. Most eroutes are associated with and are represeented in a connection. The exception is that some HOLD and PASS shunts do not correspond to connections; those are represented in the bare_shunt table. An eroute for an IPSEC SA Group is associated with the state object for that Group. The existence of such an eroute is also represented by the "so_serial_t eroute_owner" field in the struct connection. The value is the serial number of the state object for the Group. The special value SOS_NOBODY means that there is no owner associated with this connection for the eroute and hence no normal eroute. At most one eroute owner may exist for a particular (source subnet, destination subnet) pair. A Pluto-managed eroute cannot be associated with an RT_UNROUTED connection. invariant: for all struct connection c: c.routing == RT_EROUTED_TUNNEL || c.eroute_owner == SOS_NOBODY invariant: for all struct connections c, d: c.this.client == d.this.client && c.that.client == d.that.client && &c != &d => c.routing == RT_UNROUTED || d.routing == RT_UNROUTED If no normal eroute is set for a particular (source subnet, destination subnet) pair for which a connection is routed, then a shunt eroute would have been installed. This specifies what should happen to packets snared by the route. When Pluto is notified by KLIPS of a packet that has been TRAPped, there is no connection with which to associate the HOLD. It is temporarily held in the "bare_shunt table". If Opportunism is attempted but DNS doesn't provide Security Gateway information, Pluto will replace the HOLD with a PASS shunt. Since this PASS isn't associated with a connection, it too will reside in the bare_shunt table. If the HOLD can be associated with a connection, it will be removed from the bare_shunt table and represented in the connection. There are two contexts for which shunt eroutes are installed by Pluto for a particular connection. The first context is with the prospect of dealing with packets before any negotiation has been attempted. I call this context "prospective". Currently is a TRAP shunt, used to catch packets for initiate opportunistic negotiation. In the future, it might also be used to implement preordained PASS, DROP, or REJECT rules. The second context is after a failed negotiation. I call this context "failure". At this point a different kind of shunt eroute is appropriate. Depending on policy, it could be PASS, DROP, or REJECT, but it is unlikely to be TRAP. The shunt eroute should have a lifetime (this isn't yet implemented). When the lifetime expires, the failure shunt eroute should be replaced by the prospective shunt eroute. The kind and duration of a failure shunt eroute should perhaps depend on the nature of the failure, at least as imperfectly detected by Pluto. We haven't looked at this. In particular, the mapping from observations to robust response isn't obvious. The shunt eroute policies should be a function of the potential connection. The failure shunt eroute can be specified for a particular connection with the flags --pass and --drop in a connection definition. There are four combinations, and each has a distinct meaning. The failure shunt eroute is incompletely implemented and cannot be represented in /etc/ipsec.conf. There is as yet no control over the prospective shunt eroute: it is always TRAP as far as Pluto is concerned. This is probably reasonable: any other fate suggests that no negotiation will be done, and so a connection definition is inappropriate. These should be implemented as manual conns. There remains the issue of whether Pluto should be aware of them -- currently it is not. Routines: [in kernel.c] bool do_command(struct connection *c, const char *verb) Run the updown script to perform such tasks as installing a route and adjust the firewall. bool could_route(struct connection *c) Check to see whether we could route and eroute the connection. <- shunt_eroute_connection (to check if --route can be performed) <- install_inbound_ipsec_sa (to see if it will be possible to (later) install route and eroute the corresponding outbound SA) <- install_ipsec_sa (to see if the outbound SA can be routed and erouted) bool trap_connection(struct connection *c) Install a TRAP shunt eroute for this connection. This implements "whack --route", the way an admin can specify that packets for a connection should be caught without first bringing it up. void unroute_connection(struct connection *c) Delete any eroute for a connection and unroute it if route isn't shared. <- release_connection <- whack_handle (for "whack --unroute) bool eroute_connection(struct connection *c , ipsec_spi_t spi, unsigned int proto, unsigned int satype , unsigned int op, const char *opname UNUSED) Issue PF_KEY commands to KLIPS to add, replace, or delete an eroute. The verb is specified by op and described (for logging) by opname. <- assign_hold <- sag_eroute <- shunt_eroute bool assign_hold(struct connection *c , const ip_address *src, const ip_address *dst) Take a HOLD from the bare_shunt table and assign it to a connection. If the HOLD is broadened (i.e. the connection's source or destination subnets contain more than one IP address), this will involve replacing the HOLD with a different one. bool sag_eroute(struct state *st, unsigned op, const char *opname) SA Group eroute manipulation. The SA Group concerned is identified with a state object. <- route_and_eroute several times bool shunt_eroute(struct connection *c, unsigned int op, const char *opname) shunt eroute manipulation. Shunt eroutes are associated with connections. <- unroute_connection <- route_and_eroute <- delete_ipsec_sa bool route_and_eroute(struct connection *c, struct state *st) Install a route and then a prospective shunt eroute or an SA group eroute. The code assumes that could_route had previously given the go-ahead. Any SA group to be erouted must already exist. <- shunt_eroute_connection <- install_ipsec_sa void scan_proc_shunts(void) Every SHUNT_SCAN_INTERVAL scan /proc/net/ipsec_eroute. Delete any PASS eroute in the bare_shunt table that hasn't been used within the last SHUNT_PATIENCE seconds. For any HOLD for which Pluto hasn't received an ACQUIRE (possibly lost due to congestion), act as if an ACQUIRE were received. [in connection.c] struct connection *route_owner(struct connection *c, struct connection **erop) Find the connection to connection c's peer's client with the largest value of .routing. All other things being equal, preference is given to c. Return NULL if no connection is routed at all. If erop is non-null, sets it to a connection sharing both our client subnet and peer's client subnet with the largest value of .routing. The return value is used to find other connections sharing a route. The value of *erop is used to find other connections sharing an eroute. <- could_route (to find any conflicting routes or eroutes) <- unroute_connection (to find out if our route is still in use after this connection is finished with it) <- install_inbound_ipsec_sa (to find other IPSEC SAs for the same peer clients; when we find them WE KILL THEM; a kludge to deal with road warriors reconnecting) <- route_and_eroute (to find all the connections from which the route or eroute is being stolen) Uses: - setting up route & shunt eroute to TRAP packets for opportunism (whack --route). Perhaps also manually designating DROP, REJECT, or PASS for certain packets. whack_handle() responds to --route; calls route_connection() - removing same (whack --unroute) whack_handle() responds to --unroute; calls unroute_connection() - installing route & normal eroute for a newly negotiated group of outbound IPSEC SAs + perhaps an (additional) route is not needed: if the negotiation was initiated by a TRAPped outgoing packet, then there must already have been a route that got the packet to ipsecN. Mind you, it could have been the wrong N! install_ipsec_sa() - updating a normal eroute when a new group of IPSEC SAs replaces an old one due to rekeying. install_ipsec_sa() - replacing an old eroute when a negotiation fails. But this is tricky. If this was a rekeying, we should just leave the old normal eroute be -- it might still work. Otherwise, this was an initial negotiation: we should replace the shunt eroute with one appropriate for the failure context. - when a group of IPSEC SAs dies or is killed, and it had the eroute, its normal eroute should be replaced by a shunt eroute. If there was an attempt to replace the group, the replacement is in the failure context; otherwise the replacement is in the prospective context. libreswan-3.32/docs/testing/000077500000000000000000000000001365625662500160545ustar00rootroot00000000000000libreswan-3.32/docs/testing/testnet.fig000066400000000000000000000120121365625662500202250ustar00rootroot00000000000000#FIG 3.2 Landscape Center Metric A4 107.00 Single -2 1200 2 6 2430 5355 3420 6120 2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 2475 5400 3375 5400 3375 6075 2475 6075 2475 5400 4 1 0 50 0 18 14 0.0000 4 165 735 2925 5850 JAPAN\001 -6 6 2430 3780 3645 4545 2 4 0 2 0 7 50 0 -1 0.000 0 0 7 0 0 5 3600 4500 3600 3825 2475 3825 2475 4500 3600 4500 4 1 0 50 0 18 14 0.0000 4 150 705 3015 4275 sunset\001 -6 6 4230 4500 5220 5265 2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 4275 4545 5175 4545 5175 5220 4275 5220 4275 4545 4 1 0 50 0 18 14 0.0000 4 165 615 4725 4995 WEST\001 -6 6 9855 4500 10845 5265 2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 9900 4545 10800 4545 10800 5220 9900 5220 9900 4545 4 1 0 50 0 18 14 0.0000 4 165 555 10350 4995 EAST\001 -6 6 11700 3915 12915 4680 2 4 0 2 0 7 50 0 -1 0.000 0 0 7 0 0 5 12870 4635 12870 3960 11745 3960 11745 4635 12870 4635 4 1 0 50 0 18 14 0.0000 4 165 780 12285 4410 sunrise\001 -6 6 6930 5355 8145 6120 2 4 0 2 0 7 50 0 -1 0.000 0 0 7 0 0 5 8100 6075 8100 5400 6975 5400 6975 6075 8100 6075 4 1 0 50 0 18 14 0.0000 4 165 315 7515 5850 nic\001 -6 6 7110 1530 8325 2295 2 4 0 2 0 7 50 0 -1 0.000 0 0 7 0 0 5 8280 2250 8280 1575 7155 1575 7155 2250 8280 2250 4 1 0 50 0 18 14 0.0000 4 210 450 7695 2025 pole\001 -6 6 7110 8505 8325 9270 2 4 0 2 0 7 50 0 -1 0.000 0 0 7 0 0 5 8280 9225 8280 8550 7155 8550 7155 9225 8280 9225 4 1 0 50 0 18 14 0.0000 4 210 465 7695 9000 park\001 -6 6 10395 270 11025 815 2 3 0 1 0 7 50 0 -1 0.000 0 0 0 0 0 7 11004 543 10857 288 10563 288 10416 543 10563 797 10857 797 11004 543 4 1 0 50 0 18 7 0.0000 4 75 210 10710 584 beet\001 -6 6 10440 900 11025 1352 2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 10467 927 10998 927 10998 1325 10467 1325 10467 927 4 1 0 50 0 18 8 0.0000 4 90 435 10732 1192 JAPAN\001 -6 6 10440 1485 11083 1890 2 4 0 1 0 7 50 0 -1 0.000 0 0 4 0 0 5 11059 1866 11059 1509 10464 1509 10464 1866 11059 1866 4 1 0 50 0 18 7 0.0000 4 75 330 10750 1747 sunset\001 -6 6 4950 5715 6795 7110 2 3 0 2 0 7 50 0 -1 0.000 0 0 0 0 0 7 6255 6525 5940 5979 5310 5979 4995 6525 5310 7071 5940 7071 6255 6525 4 0 0 50 0 18 14 0.0000 4 150 1140 5625 5895 192.1.2.129\001 4 1 0 50 0 18 14 0.0000 4 165 450 5625 6615 beet\001 -6 6 9045 5715 10890 7110 2 3 0 2 0 7 50 0 -1 0.000 0 0 0 0 0 7 10350 6525 10035 5979 9405 5979 9090 6525 9405 7071 10035 7071 10350 6525 4 0 0 50 0 18 14 0.0000 4 150 1140 9720 5895 192.1.2.130\001 4 1 0 50 0 18 14 0.0000 4 150 630 9720 6615 carrot\001 -6 6 7200 6750 8865 7875 2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 7245 7020 8145 7020 8145 7695 7245 7695 7245 7020 4 0 0 50 0 18 14 0.0000 4 150 1140 7695 7875 192.0.4.254\001 4 0 0 50 0 18 14 0.0000 4 150 1020 7695 6930 192.1.4.44\001 4 1 0 50 0 18 14 0.0000 4 165 765 7695 7470 SOUTH\001 -6 6 7200 2925 8865 4050 2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 7245 3150 8145 3150 8145 3825 7245 3825 7245 3150 4 0 0 50 0 18 14 0.0000 4 150 1020 7695 4050 192.1.3.33\001 4 0 0 50 0 18 14 0.0000 4 150 1140 7695 3105 192.0.3.254\001 4 1 0 50 0 18 14 0.0000 4 165 780 7695 3600 NORTH\001 -6 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 7650 6975 7650 6075 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 3825 3375 3825 6300 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 3375 5625 3825 5625 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 11250 3375 11250 6300 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 7650 8550 7650 7695 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 10800 4860 11250 4860 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 3600 4185 3825 4185 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 7200 5355 7200 4905 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 5175 4905 9900 4905 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 3825 4860 4275 4860 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 11745 4185 11250 4185 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 7650 3825 7650 5400 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 7650 2250 7650 3150 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 9675 5985 9675 4905 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 5625 5940 5625 4905 4 0 0 50 0 18 14 0.0000 4 150 900 3870 4275 192.0.1.1\001 4 0 0 50 0 18 14 0.0000 4 150 900 3870 5715 192.0.1.2\001 4 2 0 50 0 18 14 0.0000 4 150 1140 3735 4950 192.0.1.254\001 4 0 0 50 0 18 14 0.0000 4 150 1140 11385 4950 192.0.2.254\001 4 2 0 50 0 18 14 0.0000 4 150 900 11115 4275 192.0.2.1\001 4 2 0 50 0 18 14 0.0000 4 150 1140 7200 5310 192.1.2.254\001 4 2 0 50 0 18 14 0.0000 4 150 1020 9855 4860 192.1.2.23\001 4 0 0 50 0 18 14 0.0000 4 150 1020 5310 4860 192.1.2.45\001 4 0 0 50 0 18 14 0.0000 4 150 900 7695 2475 192.0.3.1\001 4 0 0 50 0 18 14 0.0000 4 150 1140 7695 6300 192.1.4.254\001 4 0 0 50 0 18 14 0.0000 4 150 1140 7695 5355 192.1.3.254\001 4 0 0 50 0 18 14 0.0000 4 150 900 7695 8505 192.0.4.1\001 4 0 0 50 0 18 14 0.0000 4 165 1440 11160 675 DNS SERVER\001 4 0 0 50 0 18 14 0.0000 4 165 1245 11160 1170 FREESWAN\001 4 0 0 50 0 18 14 0.0000 4 165 1350 11250 1800 PLAIN NODE\001 4 0 0 50 0 18 14 0.0000 4 210 3300 4275 675 FreeSWAN testing network map\001 4 2 0 50 0 18 8 0.0000 4 120 3045 13230 9315 $Id: testnet.fig,v 1.6 2002/11/12 04:11:52 mcr Exp $\001 4 2 0 50 0 18 8 0.0000 4 120 1935 13230 9045 freeswan/testing/doc/testnet.fig\001 libreswan-3.32/docs/testing/testnet.png000066400000000000000000000275261365625662500202640ustar00rootroot00000000000000‰PNG  IHDR'¨âZG pHYs M MÒέNtEXtSoftwareGNU Ghostscript 6.53nGuÀ IDATxœíÝQÛc<ÛÐúŽùÿÙ·á¯!"ˆHd­9æn5h+=]‚aÇûóö@u†a¸ßˆº+Rüc†,)W;|Æÿ½½]ºà2¨ÆqÌr¤’Ϻà?Ž ò(© ž¢ÜÅ’Ô¿ßc….Á‹™ÔP‚ÔÏŽèRîb"u” uл§.*wñ“ºèœ«EPŒÔ%(w!uЯ….Á«sR@ RzeD—rWϤ.ˆ’ÈEê GOºó™rW·þ¼½ìÚÛ&ËtËNažcÊ#{Æ'®Tä©t«F²´™E™%©g}¡*g#×rSZveÁÿçuø[صîuõé3]­þµ â?ñ·1qj¦ÖÕž¼v–ÖNm·¹f PÌ6âü6]Ù©Ÿüû)mûòHƒ§æõhÙÇîZWíÊ$÷íþд#ß‚ÏæÚxævîTk²4ò„·¬¶÷Þ2õo—·…eÑårït6¥-_›«‘H ñ‰ç»w¬cùÈjšåŸ÷Û¯“ÔÕªU16XwÔ–·ß×ȶ´L`ÓÒ7õ½)¯õw—W0¥µí«'¸ÖN¼‘`ožò)¿ñåLyj»ÌÁ8uðš³:’¸êe¿í‘]âx×z*6š˜DRWíâ¿è‘Z÷o±Í¤ìd,§¹¿E:…ĺú6=\XÁH Z¾-wöœâí¬RlðåÛ)ã­E&X=~s¿<å»”ò¼.½Ü•^’¹¹;šnÛ‘&v­§ºúÈÄöZ÷5ñ°I£Å­ãºÚ6þµüMÌÓDžú¥Õ]—aû”×^g\‹åL§§Ò{´xƒéMÛI\씹l?¸`°;\ŒôUØ[æÄzzo$½ðÙ7NŸ8ݶÙì{û7[(@­«vg¿FŽ"¼û…ô-0xð~%ØHâ|³ïýÌîfËylŒ ïðÅçøâ‚Áã½Ñ]µ‰w­§ºúÉOí(‡…Å»ˆ›íWK­ëãCØa™d9qúzë°'×¶1/Ø^u§Néá8ïŠÜomU½»½DЗ\ÉàT™ê—ÜÕ_˜ø¦Êûê줮¯Ù$Š<5¯”êEð‘íÞÆÓ‚+¸Ì^y{‡Ë5¹•È粜f5}|©Ò,ûÛrس÷Ö“Ò®ë²g‡i¦tõ×&Î¥Ÿ]8G?"RXNyjûìm ±ð›ØÙ͉jo-R‚ÑÙZÝöµ×KM\°`VÞ>›"Ë®vb­®Ÿž”¦;Îxg.‡£Ë—GÚvõ‰§Ûÿ ¸ß~Ôº¾#R”:õÔÞƒqg÷½²L<¿qæÚ¼ãÅÂû ¦·V¸Ãú@ÿÕŠo_‰ÝN$·cÜüÚ‡êgO·ŸQCÏ wªe=ðþк§Ú@Pë‚°å°†ú÷Ÿ€š‰\L¤.ˆ)<¤xK‹ÃêiŽÔaÛóþìª(t1óU€ÿ<‘¤.fj]ðŸìÇE.–¤.€¤.øŸŒå.….V¤.ÈOäbËà®"ÁC$q€a(Aê(Aê(Aê(Aê(Aê(Aê(Aê(ÁµéèÚ[—¡w•òI]ô®|rÇ¡>9ÂP‚ÔP‚ÔP‚ÔP‚ÔP‚s ^{g;Nç]FÎ…|t‚ÕSóI ×™ŸšüÆ…6Ôº =e®=‘k.ÁÌiü«WÖPë€ÚÅ+=«g·‘å°P”ÞþÔø0 ã8ŽãGÛg¿§©u1˨4þµ`y(01]õVîRë€ÚÅËW‡å°úuj‚ûC¬âE²ÃZ»Ôºàkr=?•2£í8úÄ~/{©u@À4tiþÿï(=lOµ[µp' ]w•øòøÁµNYôƒŒÛ¦ær×Ç‚—Z$ÙoúmbAüÏæŽèZM™˜,‡a8|g¾q©ˆ© .úöa²¹Ú_…`¥jûÿv߇Œa€˜¹Š¹BdšD®tŸ`µ‚Áמux<4¸ß Öÿ“xª¹¹ÀúülÉè·¶´†Î¶¹ý…h—ZK)öVŒ.8u}Ôíƒ7¯š2ApšÕ#{¤Lö¥à%uÀÿ¬BRäìÅSÓÀï÷»u"+´îæ5š)¯3®  ©  ©  ©  ©  ©  ©  ©  צ w®&O® P‚#Œ%H]%H]%H]%H]%H]%H]%H]%H]%H]%H]%H]%üy{  Ã0”Ÿé8ŽågÊ[Ÿ7›òVùÄ9çù-î„Z]†× Ó|_©±ñ ãºàMã8 ^ºJp„HÒþ¸±5zñð"’º€c«Èõ±_©yíÞR tBê|þ4«y½¦5Uüb\3—z"«ø—Ôìêðˆ[W+ &uüÃ%”€‡×Ĩý@…öö –û ‡ïÞÍÕ˃“íÍ"}âà*åOPs¯¥Ö„)ö@s®m¶‰¯:Õx|âËÝKëý’ZÀšk…“ÑsgÅnëIé^ü†Gêa«÷*¸‚Ëij.k©uaÍugݰð[$ƒÕ³Á)—psƒ-_î:ë=’Ôö~ò·¯ ¥Å²Âµˆ“¾x§V$eâÕ4^òû7ݖ̸—I]–~ ·àØó§#×6m$ÎñN.|±ÜõÆu@Ø64ìňUŽ™“PÉãb÷2Æ[˜Ëx)YêÔÄ—5wØQꀰøQ°éÏå¿Á)ŸK÷[>‰NhŸxòRšý@åÌFèH=ÙåÚÁÊæê[Kj]ðAÛL)È/Üt¿Üµ|põìá•TO]jµBj]Ћ,£ûç3¦?xy¾uzêÒmÀyÉáÄÅ&;,b©rAWÔº€zEÍT ŠæÿÇ3Ͳ…ȬOµœL ˜¨uíɘcöššÏ2£á¯íã¹f4A­ ¨Tb‘)ø’S¯J_€`BJŸ©Á[Ð9µ. =×rØÓóÚ›é8ŽÛ§ÐRëZ2ŽãÞ(ûY¼4uaŽ¿d‡3]ý_ä‚Ωu‰‡•Œ‘k잘éj¼—óáó¤. 1s¡hq.¤Ÿø9Œ)Iho¦B•àßæ#Ð’`ˆ‰Ä¯ß¿‡G¾/#]$x®fl!xj¤ŽÐ µ. %ÛhróTǽG'K¼ˆWd.@?œÆ ÔÂ…€oSë(Aê(A=8ác'Ù钜Üó™¤ò± ÔÏF€¤.€¤.€¤.€¤.€¤.€¤.€¤.€¤.€¤.€¤.€¤.€¤.€¤.€¤.€¤®Ó†ax{è”ß ¦I]%H]%H]%H]%H]%üy{€/˜Ï«Çqõàö‘•y‚ÈÉYÓ4)gog·|à-j]@N‘`äŒw sj]@ ‘bØ0 ËWu©eV»PH¨‡Z™ô¤Öd3Žcꕨª[Ž·vmQõáíº{„q.b¥GŸÃ/Ù²ÍUA8òªËΆ¶³ÛFbû ðÚõV·œ·Æ–«©C^^wSןÇÙ!uš#cÊá|‘ àiå»e<+Ïaœð-ÉRMo³‰–ržðádäR²[Öɳu}\×2$eÉ@ñ6÷Fë×,r&Á…­±‰  P³bݲÈEЕԕr}‘³a¯Íô‚pmßìÕ…-&Û…\=›rM¿åƒ.ˆ èÑny¯³ÝÎK·Ü³+Gƒß•ùÁkߤH›Û§šø²F;=’6ºî*Ö-;4ñœaš~{ÿ;O°Ûßò ëÞóÛ²qÁ¡Â›Im[eáJaöÕwG €¾#P 7­Ù¾*8e¤Ä¹{M…7¶QëîÚ;Ãà~S§.#¼~òP\àÊ @výަ(Iêv}{ÄQÄ+îÚô•úÒ·Ü1k âKÝÝOG”ÔU¯olºëO'|£»û}±Ç›o#MŽ01¯‡.¥.uº ^Ï­¬ÔìZ^DýÝ%)ãÑK©K]@L?Áëé»×Mèç~ÍžÛ!uI>s¶éÊ0 eVÍF kÅÒ¤ÔP‚ÔP‚ÔP‚Ô}þDòr# Þanö.s8òðö§œ&^ö²Ía_=߇òNmñ§OœÑË_¥ÖÅûæ³÷TÊãñ)ëRé î=¥ôÅ.lÁ§"-äÚ:"“Ú¾àÃÔº¨B¼Ÿ¯Î÷û·¼”x¹äôþýþõ—íÁ“ݵ­ã—ö}ξul'Û^ì[ä¢[j]Ô®¶?3üUv¡èTm[GдM,*çÝ:RFq=}“;¨œZW€BEU?Žìx°ÁÃAÇã8:ŒB1×vTîKl->öîkîKu¥ÖõЉfÅθ‰ŸhÁ+ÆqŒö;ßo0þ­[§i®/ -‡[Ç/÷’ØZd²È4òîïuöS_ƒÏ¶õ]:Që*p¢Ùá”÷ϸÉ5ìš2R6û2‘k9Ùrä–ï o¹œ~.¸¹–›IC?íªç÷úÎdŸü½>WëzôD³U §–!ÒZð%6ûV,wÔ–Ÿã[‘+þÚ_Úw²ØÛ:~¹7,‘«­‚ÄÔð{Þ`?¿×ÙFÓg|_  ösæ'³Á=žÃ}èãÏËn'[5¸œ,8ëUgaŸž2R¶Ží³y·Ž½)W“¥ ¥$¿×/:‘º=Ñ,ï2¤Ï÷ÚîW óö‹$²Ìñwõðký\¶ØÎú¡JR®/§ÈE1{[Ç/÷’ØÚa/‘>fèÚ\ö’_<;®^ž¥¯«á¢ªßëxƒOÿ^×&[­+ñíxë-[Íw[\MÜ ¶ö„ŒÛm‹=E䑽Ÿ ~<õÔzª•þ}»ð}¾¶u,Ÿ=üò¿µu G·íÊîé5½¿ oý^_û…½ù{]› ©ë°zœ}N¢à|Wÿ_.y[áa *²?ovÕB°Ïjë½¾$ñib ËŽîó}]ùßë;ƒ?ó{½”§ÖIUE®Ä—Ì6ñ¹®²ÿ0 w–<8¬òþfi‡ø¶Ý¶K|¢£kEÉßë›ça¤¼dþ³•Ï1OêZfÏå{qí#ÌR> Î7xúF¼V>ÈD)§‡dœTæ€ìÇ>©Ú”y‡}ŽpáC<Ûç§ôc¿£ÝŽÂ,ö{}3r}õ÷:Cêšß‹È—øÂ™/ËGëɇ"X\Ý{UýŸßáAÆß™µ¶ÖÊ÷`²êÞ·£ø{îè^ù½~"½ý^ÏrŽëZ>ò;¹û²×ȇ'¡ô°‹³÷&$Œ]í}õ]Zt¡G Rì°£+ö{Ø`‡¿×WR×vÍ÷ª»Ï5<Ç!e¾Y&¨M–°Ø+4$Ø}õÖѽõ{i°óßkw¿n[|c8;2q‰ŸkÙ K9³[GÇ‹²]¯‹&ì]NbYÈÍu¨à {ýØÞŸËkCèèx—Zÿ¹Pv¨GÊIs::Þ¥ÖÕ¼,‡íóNð„³Ã‚'vbú:ž ÖP‚ÔP‚ÔP‚ÔP‚ÔP‚ÔP‚ÔP‚ÔP‚ÔP‚ÔP‚Ôì Þf€k܇.šÉêfm«˜²|6òTbã‰3º¶<ÛF¦ †apC:€,Ôºàœ9‹ì=yÕáÄ‘Æ/·|äÂ,¸I­ N‹Gœ©2,Íÿ?•Ïö¤´ŸL  $µ.È©­3üµ}ü×Úº4Me:¡ÖU/q+L{¯Š¿ðlù*±µÃ+¼µMÆÏ}ŒîŽNH]•ê¹ÿmZúogÞøÚLƒCë)tM‹”8ˆmï©à'²×òåÖö&3~.E _6(Cê‚<æ_ñ”Låg&±µàd«ÿ¯FÙ×ó+‰\OŸÛ¾oÆÏ7×Ù\H?—݉\)/Ç{UX)c¦Yäú°ŒŸ~j]ÑòGtõ[Uä –‹*taÝCãçâoøgÆÏO“º `e(>èÔ8ªÃ‹²FZ[M<,íÌ­Õ–ÌJŽŸ»°îmŸŠq„òØþ|^;ÛñPbkégAnÿ¬Ùò]Ý[Çù©,ë5åÔ¹å½É‚3]¾v[kèm²Pë‚‹"1+ññȳ‘Æ[;üEOùɯ3Äkoæ.+jOÌt{ºÎ7ÈE­ hÌ\(ŠÀÍu`1¥²?wö¤„ÚŽäy©u-)6~.~)‡ÆÏÅ— hZÐ’bãçâóš}uüðÃN3ö¢B>”oð9~€ñiÞᦩu” uÿ1”àQ~Ÿëj•^!ÝÞ5ôßòÐè€üwãgº¤×3 !yïST­¼M¸ÌFèTäªWóÜIާH]УÞj?ý¬)P3© èÂòZ©¯º ;½ºf®2P© è‹rð©  © zÔó±¶ž×x—ÔP‚ÔP‚ÔP‚ÔPŸ·à;‚×@Z£¾|6òTb ‰Ëp¹5 #µ®»¦¼Pä²@Û§[ˆLvx¢ÄÖ€'¨ueLËû ð,/%Þ”7åN&éùÉ€àL]U…‰Œ‡ðÆq¬jÕ€S>˜ºž«´74êT$Š ðºàTÍ,×L€SŒëzÖ…%MÅ|°ÖU‰ù€`ʘú’éç•™j]J¹ÊÃády‰\ð©ëAóÕ³¶çBú¹?Kä€9Âø”9â,ÓR$~ý%ã—Z]>x˜Ÿ”À Œ©+þûÏKZØž|WVØ^èáÂÙŽ‘FÎrÒ"¯keãxH¶Z×êúŸ¦Œ´Þø‹¶K¸·Ì‘u¹ÙHäåõ¿ðm·RWJù$~( 9ÇuV¤¯®Þz¹‹JldÝ¿ ù^ËÁ î´–kQß²ÝÆÝŽßÃßv&­Èpãý³ð³Úée¢K{HËuò\÷?uÇôàimÙ[rÅïœú¶GžjhÃô5&âz­+xò]|²yâS-,›’Àˆ‹ô€7oCž÷þâ‰÷nÚö쑵¨Jú¹#nÇþyñSÿ†¹=¯kïwÍw˜Cµ®³ß¡ôöT úenª6œòµØ¼²ßÖÄ'>-dÊ¢6±:¼ë¸Öu¸?¸×~¹…¹‘‹¸k׿˜ÿyUÞû‹î1§Ì špmŸ¹Ú 3r©#Hqq\×ýß¿(”t-‡Ýw¿µÏç°åQÔO® mm˜¾ŸÜ—4®+eç`žììX“ô”»¸ ümÈï·¶m!e-ÚõÉ•"®Å ³•Q•Ôì\­k5`0ãÊ©€S‘WÒ³ïµð½/ú5ù¤†6ÌÕ¹_÷—‡nÔº/€|üÔØÓ[ðç¬åÕwV;ÖUõìñ"kQ•ÈV,f±Ôʆ™^ܪyäî~ÍÇ/«³—i–Ï.Û\PñTk{-$®´âÚ†™¾eÜ0O …¸ WI…šEê+y;ÊGO1Q%âcÚ0Ñ¥µmrÊ0¥øÏ|K ¬Ë—Þ®Ïð¡œÒóÛÕóº—á~šw¸ij]%H]%H]%H]|QÔOê(ÁõºxS…¹é¤lÖóiP=¯{¢›æÛµŒoºxÍÙ ‡0Ý€¹ªE";Ÿo\m¦ûò%Ž0½¨°¶Z› ß"a‹/‘ºxGmûÓ“úïr˜E'«Ée6LxˆÔôï¬æ¤Î _o¯­}!hÔE!:wšöhø–ìO±;D»Ü‡‘Ú\] «¯Ööû³úÅM|*¥åÈd‘¯Aúòlg÷â}ÛÝ0¡Qj]@¥ö.i)r$N|êb‡“EfzᵤPî¢Qj]<®õýiå®EÍêbcËO'åÊûÙ°#3­ó›Óú†9±aÒµ. =Å~h³D“å%ò³7~y‘Þšu.M/<Ý’ºxÖ:÷ŸÃ/ÿ:û’éÿ‘ÏëBË÷gzø,gÙ0iŽÔIôïUIÿ îD«Ëû «—c™BtHêâA:w²K¹i÷òŽ×—gt¶Ä!®ôÓIDAT…àL—yk{b£Mã>»C´Eêâ)ßû]Ñ¿W"åb‡“%Z ÉŠä¼ 3Ml<¯ïm˜Ð© hÌœ¶Ñ!oäŠÌ=e¦BÕÓÁë“û v‡hˆ+Gðˆ¯îO»ŠÄë‚!&¿~ÿþ*'^uéV/¶¶šéôm .L¼ñ§}ïÛkäj]p…ë·lVÏ|H|¦Ûaõ/NÌW÷… !ö N³;uèóûçWð-6®G}þ{ûùœØLš¦Öuš¯{\E ãHhN'‰¤>ĦI]5w¸ã8>Ú¿— È^躰¡í={8AÉíÞ¢ÖEí¶9fþÿÜ)o ¶O•ÑúñšöPQgokŠleÁˆ<8µ ÅçI]\T¦h¿Üñï[§?õ%.¾m¹±7ÉË fim}!êá#ßQIÓ¹ó¢bǸ—ueßyH$uq]þ=2ˆä÷·»_î.§<õûÓT%ã†9¯ðæ>¾gaä*Ž0R»ewûwûÓ4Á† •º>«Ãä!rQ3©‹lz+wéÜiBo&ÔLê"'ý;ð"ûBTNê‚+tî4ÄîTBê"³úw‘ *dä~RÀ÷}~wèëƗH]ä÷íþÝþ4úö†9±aR9©‹}»§+‰_æÈd6‡çØ¢î5ËS>Ù~r¥ê±w÷ëíÛ¾J0‰O¥´™,±µàd‰-ðÉïð'WŠORëâ)ß;œñ¥uiÂô†oßöSõ¤àÄ{-'¶yv2ßœG‰\4Dê‚stî%ERÔ8Žóg±­o-ŸMl¹ßÛ‚†H]<èKý»ýéªû N‚L<L­ Èf[g†az0XvZMs¶q, -RÍ2?‰D+RÓò0â6x­9­usªb\A°²%,©uy¬NEœÿ_øPcÊY“¯Pë2XXœÄ'Ûþ ðmRp×|*b–ëG¬Je7—  Ž0w-ůrÒò”Æôi„-à“Ôº€ ‚Ç·g,f™ Q¥ºM+?:þ9_Z  j]%H]%H]%H]%H]%H]%H]%H]%H]%H]%H]%H]%H]%H]%H]%üy{€Æ Ãðö"4iÇñíeøý~¿aÐ#_æ#À±G+|ʇРGÚM¡dY[Ŕħ¶mN¶œ8RŠK_ží¼>C­ ¨ÔG‚G^r8ñÍ6Ó[»ðZàÃÔº€zEÍT ŠæÿÇ3Ͳ…û"3UÄ&j]@{2昔c‹7g7üõDã@CÔº€J%–¬‚/9õª›ÒgjðtN­ hϵvm.ZX½dÇm‚Tè‚©u-Çqo”ýl5öëš³©(8ÓÕÿE.èœÔ4f_¶²D®mkóŸÁf¯Í4±qà3a3жåBú9;üëð´ÊåãËAô)3r! ø6µ. %Á‰_¿¯q8ò}/Ò­^a~σ󒺀r"¹~gž gЭò[Ê0 { ö¦Ÿþ“¸¨sû×ììR]˜rZ¼àB:µ:°¸÷Ô©%0Øš+.«³€W)'òçò$âÕŸÁ—ü64WAgoódÛ±{íÿö+^ÛA¢7—joyVSnÛß.¿ZðŽûQIØ‚ˆ`Åe¿RÒØêxYð2.Ûòó<÷ø,‚ ¹l-8»íãÛ¹Dæ{v©ö–'8åjiW˩֔³—“ÒöìÀ¡”*ÑòÏàÁ¸U\K·7‹”×®¢ÒÞãÛÉ"Gún.Õ©Õ_.˜Ô}Ù«$-ŠíUŒÛÚ;â™ÅáÒ.'ÛûpÖÁ#‰Y–êìI?óôŽ0@/öŽ-.CÕaÉ'½ÖµJ3{³ˆ´¶W]‹¬È²Ä\—;K\žÕAØÈôF¡»÷D›ú5u@0㺗ÇQ5d ›[ ˜ž»ˆž×ª9DØ„åò×ԫѰ5[.¿q]%H]%H]@ØÙëñ'u¬IœÀ¤. ¬õ¬µ‘º€U€\¤.€4wAW R°+r·µ¯êjeÂ\|8Ðú…¡Óõ³¦À+¤.àØ²ô½N#xW]€ì¤. I‡Þô‡Ÿ·´·ºÛæ[7ßœ—ªþ»&.aý+rÁåݳå·Î}$ßëCéÍü«yö„‰ìQc;åôçå­,8ë`‰zuýìŸ)uúÿöx}|!ƒs<;Y|Áî»ÐÔê['uЋ¹ž´L$Û:î*Cüv’ÄòÏàd‡SnÛߞ²Z’¹…m ®op½æ™Î ®–p9‹àûùsÛòê=Ù›lµË+¸Ø{ëY°àƒ‘ĉYÛc/ .WÄ9Œôb•x~;?®Ë?ç*T0ˆ¬Š@ó Çq Î"8åo“!¶‹´²]½5ÊŒ,Ld"oW¼åÄÉ‚nÕ6å¤,XpúxÊ\Ít;ñªÁ`ø›>z© €.l“Ðüøï(åÌ‚?¨‰ÇO-ê¶ÙS‡·Æ…í2§7•÷Ý}ó\µS‚oïòK ©Û âÓê['uÐ…Ã1C)–¿÷ójJ «ìÄE=õÔj²½ãkÛºÚjìÑòÏebH —Ë÷äpiã °\—ôwïš`u0ñ%‡Óüþ~ë¤.º0nÆTý‡„–¿ÁJÛ)W›‚/ŒÏ"qúÕ/w<|¬Žm§î#[ýy!…lW!¾´ñØ[—ñïÀ¯ag8׉ <ükõÂßæ ÿmÇüUU9€GÕvÈlkõs>¶pE ~ѯÖÿ¢ª²w0”š¥„c©  „ÿZ ÕþIEND®B`‚libreswan-3.32/docs/win2k-notes.txt000066400000000000000000000061341365625662500173240ustar00rootroot00000000000000The Libreswan IKE daemon has been ported to work on CYGWIN32. It presently has no kernel component, so it is useful only to those who want to do some kind of testing using IKE using a Windows 2000/XP platform. It assumed that a CYGWIN32 compiler environment exists. The code cross compiles, and has passed approximately 90% of our test cases as of this time. The major change is that the IKE daemon ("pluto") normally discovers it's list of interfaces and local IP addresses automatically. That code does not port well, so for the moment, we require manual configuration in ipsec.conf. See the "ipsec.win2k.conf" file in the programs/_confread/ipsec.win2k.conf in the source tree. You may need to do: mount -f -u -b "C:/cygwin/local" "/usr/local" to mark the /usr/local area as executable for cygwin. You need to install GNU AWK, GNU SED, to run. You will need a program, "logger" installed into /bin: bash-3.00$ cat /bin/logger #!/bin/sh while [ $# -gt 0 ] do opt=$1; shift; case $opt in -s) ;; -p) shift;; -t) shift;; esac done if [ $# -gt 0 ] then echo "$@" else cat - fi exit 0 bash-3.00$ chmod +x /bin/logger To start up libreswan, you can do: bash-3.00% ipsec setup start note that "ipsec setup stop" does not quite function as yet. The "ps" program does not quite behave. To BUILD ======== Extract the tar.gz file in some place that is convenient. Type "make programs" Type "make install" You will need appropriate tools installed on cygwin: Package Version Status bash 3.0-11 OK binutils 20050610-1 OK bison 20030307-1 OK bzip2 1.0.3-1 OK crypt 1.1-1 OK findutils 20041227-1 OK flex 2.5.4a-3 OK gawk 3.1.5-1 OK gcc 3.4.4-1 OK gcc-core 3.4.4-1 OK gcc-g++ 3.4.4-1 OK gdb 20041228-3 OK gmp 4.1.4-2 OK grep 2.5.1a-2 OK groff 1.18.1-2 OK gzip 1.3.5-1 OK make 3.80-1 OK man 1.5p-1 OK minires 1.00-1 OK minires-devel 1.00-1 OK sed 4.1.4-1 OK sharutils 4.3.80-1 OK swig 1.3.24-1 OK tar 1.13.25-7 OK tcltk 20030901-1 OK zip 2.3-6 OK zlib 1.2.2-2 OK TESTING ======= To run the tests: 0) add the following IP aliases: 128.95.7.1 128.95.7.2 128.95.7.3 128.95.7.4 (On Linux we added 127... but Windows won't let us do that) You will only to do this once. 1) start up a cygwin bash shell set MYBOX to source tree cd /0g/sandboxes/win2k MYBOX=`pwd` export MYBOX 2) sh $MYBOX/testing/pluto/pluto-unit-01/pluto_unit_tests.sh libreswan-3.32/docs/windows-cross-compile.txt000066400000000000000000000076501365625662500214170ustar00rootroot00000000000000WHAT I DID. {In the course of this, I think that cygwin copied binutils CVS into the winsup CVS. Maybe I'm crazy. The CVS logs shows a full history, so... But, binutils isn't needed anymore} Pick a directory to build in. In my case /0g/sandboxes 0) download, ./configure, make and install cocom from http://cocom.sourceforge.net/ (They have an RPM, but I didn't find a .deb) This gets you the "shakli" program. It is a program to help create fast parsers. I think it is used for the fs emulation layer. a) extract gcc-4.0.1 b) check out winsup as told on: http://cygwin.com/cvs.html d) cd winsup ln -s ../gcc-4.0.1/fixincludes . ln -s ../gcc-4.0.1/gcc . ln -s ../gcc-4.0.1/libcpp . ln -s ../gcc-4.0.1/libstdc++-v3 . rm -rf winsup/mingw # has CC_FOR_TARGET/CC mixups rm -rf sid # has some problem,and we don't need it rm -rf rda # has dependency on intl, which # doesn't get built. MAKE SURE THAT "." is not in your PATH. Some symlinks are made by the name "as" which can screw things up. e) cd .. mkdir build cd build ../../winsup/configure --prefix=/xelerance/cross/win2k --target=i686-pc-cygwin --without-headers --with-newlib --disable-shared --enable-languages=c,c++ make mkdir -p /xelerance/cross/win2k/lib/gcc/i686-pc-cygwin/4.0.1/install-tools/include make install f) cat hello/hello.c #include main(int argc, char *argv[]) { printf("hello there\n"); } cd hello PATH=/xelerance/cross/win2k/bin:$PATH export PATH make CC=i686-pc-cygwin-gcc hello scp hello win2kmachine: ssh win2kmachine ./hello g) build your favorite stuff, e.g: extract libgmp4, mkdir build/gmp4 cd build/gmp4 PATH=/xelerance/cross/win2k/bin:$PATH export PATH CC=i686-pc-cygwin-gcc ../../gmp-4.1.2/configure --prefix=/xelerance/cross/win2k/i686-pc-cygwin/include --host=i686-pc-cygwin --with-pic (--with-pic gets rid of some issues that I had with the assembly, at a cost of some performance) WHAT I FIXED ============ CC and CC_FOR_TARGET are confused a lot in the winsup makefiles. CC is only when building stuff you need to run on the local machine. The patch is attached against CVS from 2005-08-03. I had an issue with cp-demangle.c. I never resolved it. I don't get it. I later found that it was because I had linked libstdc++ to the gcc-3.4.3 version rather than the gcc-4.0.1 version. I "fixed" it by doing: In winsup/cygwin/Makefile.in, the build of cygwin0.dll (aka ${TEST_DLL_NAME}), has to reference -lcygwin, which hasn't been built/installed yet. (it is in . as libcygwin.a) I actually don't think we should -lcygwin at all. Two possible solutions are: a) -nostdlib -lstdc++ -luser32 -lkernel32 -ladvapi32 -lshell32 -lgcc b) -L. I prefer (a), because we shouldn't be referencing it all. I was not able to build mingw, which is why I move it aside in (d). I did not investigate this deeply, since I don't care about native code for the moment. WHAT I DID WRONG ================ The first time, I tried building binutils separately. This failed when building GCC 3.x. The problem is that the AR_FOR_TARGET macros used in the makefiles for gcc are, it seems expanded a variable number of times in different paths, and the t=/echo $$t stuff got expanded by MAKE rather than by the shell script. I rebuilt again with the ln-s for binutils, and this didn't happen, because one never gets to that part of the condition for AR_FOR_TARGET. So there is still a bug there, but I didn't manage to fix it. -- ] Michael Richardson Xelerance Corporation, Ottawa, ON | firewalls [ ] mcr @ xelerance.com Now doing IPsec training, see |net architect[ ] http://www.sandelman.ca/mcr/ www.xelerance.com/training/ |device driver[ ] I'm a dad: http://www.sandelman.ca/lrmr/ [ libreswan-3.32/include/000077500000000000000000000000001365625662500150725ustar00rootroot00000000000000libreswan-3.32/include/addr_lookup.h000066400000000000000000000002231365625662500175430ustar00rootroot00000000000000#include struct starter_end; int resolve_defaultroute_one(struct starter_end *host, struct starter_end *peer, bool verbose); libreswan-3.32/include/alg_byname.h000066400000000000000000000027251365625662500173470ustar00rootroot00000000000000/* * Algorithm parser name lookup, for libreswan * * Copyright (C) 2017 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef ALG_BYNAME_H #define ALG_BYNAME_H #include struct ike_alg; struct proposal_parser; struct ike_alg_type; /* * Filter function to accept/reject an algorithm. * * NAME should contain the string used to find ALG. It, rather than * ALG->NAME, is used when reporting errors into ERR_BUF so that the * messages better align with the input files. */ bool alg_byname_ok(struct proposal_parser *parser, const struct ike_alg *alg, shunk_t print_name); /* * Helper functions to implement most of the lookup. */ const struct ike_alg *encrypt_alg_byname(struct proposal_parser *parser, shunk_t name, size_t key_bit_length, shunk_t print_name); const struct ike_alg *alg_byname(struct proposal_parser *parser, const struct ike_alg_type *type, shunk_t name, shunk_t print_name); #endif libreswan-3.32/include/asn1.h000066400000000000000000000056571365625662500161220ustar00rootroot00000000000000/* Simple ASN.1 parser * Copyright (C) 2000-2004 Andreas Steffen, Zuercher Hochschule Winterthur * Copyright (C) 2005 Michael Richardson * Copyright (C) 2009 Paul Wouters * Copyright (C) 2013 D. Hugh Redelmeier * Copyright (C) 2013 Paul Wouters * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include "realtime.h" #include "chunk.h" /* Defines some primitive ASN1 types */ typedef enum { ASN1_EOC = 0x00, ASN1_BOOLEAN = 0x01, ASN1_INTEGER = 0x02, ASN1_BIT_STRING = 0x03, ASN1_OCTET_STRING = 0x04, ASN1_NULL = 0x05, ASN1_OID = 0x06, ASN1_ENUMERATED = 0x0A, ASN1_UTF8STRING = 0x0C, ASN1_NUMERICSTRING = 0x12, ASN1_PRINTABLESTRING = 0x13, ASN1_T61STRING = 0x14, ASN1_VIDEOTEXSTRING = 0x15, ASN1_IA5STRING = 0x16, ASN1_UTCTIME = 0x17, ASN1_GENERALIZEDTIME = 0x18, ASN1_GRAPHICSTRING = 0x19, ASN1_VISIBLESTRING = 0x1A, ASN1_GENERALSTRING = 0x1B, ASN1_UNIVERSALSTRING = 0x1C, ASN1_BMPSTRING = 0x1E, ASN1_CONSTRUCTED = 0x20, ASN1_SEQUENCE = 0x30, ASN1_SET = 0x31, ASN1_CONTEXT_S_0 = 0x80, ASN1_CONTEXT_S_1 = 0x81, ASN1_CONTEXT_S_2 = 0x82, ASN1_CONTEXT_S_3 = 0x83, ASN1_CONTEXT_S_4 = 0x84, ASN1_CONTEXT_S_5 = 0x85, ASN1_CONTEXT_S_6 = 0x86, ASN1_CONTEXT_S_7 = 0x87, ASN1_CONTEXT_S_8 = 0x88, ASN1_CONTEXT_C_0 = 0xA0, ASN1_CONTEXT_C_1 = 0xA1, ASN1_CONTEXT_C_2 = 0xA2, ASN1_CONTEXT_C_3 = 0xA3, ASN1_CONTEXT_C_4 = 0xA4, ASN1_CONTEXT_C_5 = 0xA5 } asn1_t; #define ASN1_INVALID_LENGTH (~(size_t) 0) /* largest size_t */ #define ASN1_MAX_LEN_LEN 4 /* no coded length takes more than 4 bytes. */ extern int known_oid(chunk_t object); extern size_t asn1_length(chunk_t *blob); extern void code_asn1_length(size_t length, chunk_t *code); extern bool is_printablestring(chunk_t str); extern bool is_asn1(chunk_t blob); /* ??? asn1_length_signature and is_asn1_der_encoded_signature are not yet used */ extern size_t asn1_length_signature(chunk_t *blob , chunk_t *sig_val); extern bool is_asn1_der_encoded_signature(chunk_t blob, chunk_t *sig_val); libreswan-3.32/include/certs.h000066400000000000000000000046271365625662500163740ustar00rootroot00000000000000/* Certificate support for IKE authentication * Copyright (C) 2002-2004 Andreas Steffen, Zuercher Hochschule Winterthur * Copyright (C) 2003-2006 Michael Richardson * Copyright (C) 2009 Paul Wouters * Copyright (C) 2009 Avesh Agarwal * Copyright (C) 2012-2013 Paul Wouters * Copyright (C) 2017 Paul Wouters * Copyright (C) 2013 Tuomo Soini * Copyright (C) 2013 Matt Rogers * Copyright (C) 2019 Andrew Cagney * Copyright (C) 2019 D. Hugh Redelmeier * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #ifndef CERTS_H #define CERTS_H /* workaround for NSS/NSPR bug on MIPS with cert.h */ #ifndef _ABIO32 # define _ABIO32 1 #endif #ifndef _ABIN32 # define _ABIN32 2 #endif #ifndef _ABI64 # define _ABI64 3 #endif #include /* NSS */ #include "x509.h" /* advance warning of imminent expiry of * cacerts, public keys, and crls * unused: OCSP_CERT_WARNING_INTERVAL (30 * secs_per_day) * unused: ACERT_WARNING_INTERVAL (1 * secs_per_day) * unused: CA_CERT_WARNING_INTERVAL (30 * secs_per_day) * unused: CRL_WARNING_INTERVAL (7 * secs_per_day) */ #define PUBKEY_WARNING_INTERVAL (14 * secs_per_day) /* certificate access structure * currently X.509 certificates are supported */ typedef struct { enum ike_cert_type ty; union { /* some day we may support more */ CERTCertificate *nss_cert; /* CERT_X509_SIGNATURE */ } u; } cert_t; const char *cert_nickname(const cert_t *cert); extern void list_certs(struct fd *whackfd); /* * Maintain a list of certificates. */ struct certs { CERTCertificate *cert; /* never NULL */ struct certs *next; }; void release_certs(struct certs **head); void add_cert(struct certs **head, CERTCertificate *cert); CERTCertificate *make_end_cert_first(struct certs **head); #endif libreswan-3.32/include/chunk.h000066400000000000000000000066561365625662500163700ustar00rootroot00000000000000/* * memory chunks, for libreswan * * Copyright (C) 1997 Angelos D. Keromytis. * Copyright (C) 1998-2001, 2013 D. Hugh Redelmeier * Copyright (C) 2012 Paul Wouters * Copyright (C) 2013 Tuomo Soini * Copyright (C) 2018 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef CHUNK_H #define CHUNK_H #include /* bool */ #include /* size_t */ #include /* uint8_t */ #include "lswalloc.h" /* for freeanychunk() refering to pfree() which can go away */ /* * chunk is a simple pointer-and-size abstraction * * It's for dealing with raw bytes, for strings see shunk_t. * * Where possible, implement using non-inline functions. This way all * code is found in chunk.c. And debugging doesn't run into grief * with either macros or badly inlined functions. */ typedef struct /*chunk*/ { uint8_t *ptr; size_t len; } chunk_t; chunk_t chunk(void *ptr, size_t len); /* * Convert writeable THING to a writeable CHUNK. When compiled with * GCC (at least) and THING is read-only, a warning will be generated. * * This works because GCC doesn't like implictly converting a 'const' * &THING actual parameter to the non-const 'void*' formal parameter. * Using an explicit cast (such as in a static initializer) suppresses * this warning. * * For a read-only CHUNK like object, see THING_AS_SHUNK(). */ #define THING_AS_CHUNK(THING) chunk(&(THING), sizeof(THING)) chunk_t alloc_chunk(size_t count, const char *name); /* result is always a WRITEABLE chunk; NULL->NULL */ #define clone_hunk(HUNK, NAME) ({ \ typeof(HUNK) hunk_ = HUNK; /* evaluate once */ \ clone_bytes_as_chunk(hunk_.ptr, hunk_.len, NAME); \ }) /* clone(first+second) */ chunk_t clone_chunk_chunk(chunk_t first, chunk_t second, const char *name); /* always NUL terminated; NULL is NULL */ char *clone_chunk_as_string(chunk_t chunk, const char *name); /* BYTES==NULL => NULL_CHUNK */ chunk_t clone_bytes_as_chunk(const void *bytes, size_t sizeof_bytes, const char *name); /* * Free contents of chunk (if any) and blat chunk. */ void free_chunk_content(chunk_t *chunk); /* blats *CHUNK */ /* * misc ops. */ bool chunk_eq(chunk_t a, chunk_t b); #define memcpy_hunk(DST, HUNK, SIZE) \ ({ \ typeof(HUNK) hunk_ = HUNK; /* evaluate once */ \ passert(hunk_.len == SIZE); \ memcpy(DST, hunk_.ptr, SIZE); \ }) extern const chunk_t empty_chunk; #define EMPTY_CHUNK ((const chunk_t) { .ptr = NULL, .len = 0 }) #define PRI_CHUNK "%p@%zu" #define pri_chunk(CHUNK) (CHUNK).ptr, (CHUNK).len chunk_t chunk_from_hex(const char *hex, const char *name); /* * Old stuff that can go away. */ /* replaced by free_chunk_contents()? */ #define freeanychunk(CH) { \ chunk_t *chp_ = &(CH); /*eval once */ \ pfreeany(chp_->ptr); \ *chp_ = EMPTY_CHUNK; \ } /* replaced by chunk() */ #define setchunk(ch, addr, size) { (ch).ptr = (addr); (ch).len = (size); } #endif libreswan-3.32/include/ckaid.h000066400000000000000000000027021365625662500163170ustar00rootroot00000000000000/* * NSS boilerplate stuff, for libreswan. * * Copyright (C) 2016, Andrew Cagney * Copyright (C) 2018 Sahana Prasad * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef CKAID_H #define CKAID_H #include /* for bool */ #include /* for SECItem */ #include "err.h" #include "chunk.h" /* * For rationale behind *_t? Blame chunk_t. * * XXX: Can ckaid be changed to bytes[]+length? The length is * determined by the hash algorithm(s) used to generate the ckaid? */ typedef struct { SECItem *nss; } ckaid_t; bool ckaid_starts_with(ckaid_t ckaid, const char *start); char *ckaid_as_string(ckaid_t ckaid); err_t form_ckaid_rsa(chunk_t modulus, ckaid_t *ckaid); err_t form_ckaid_ecdsa(chunk_t pub_value, ckaid_t *ckaid); err_t form_ckaid_nss(const SECItem *const nss_ckaid, ckaid_t *ckaid); void freeanyckaid(ckaid_t *ckaid); void DBG_log_ckaid(const char *prefix, ckaid_t ckaid); #endif libreswan-3.32/include/constants.h000066400000000000000000000265561365625662500172750ustar00rootroot00000000000000/* * * Copyright (C) 1997 Angelos D. Keromytis. * Copyright (C) 1998-2002,2013 D. Hugh Redelmeier * Copyright (C) 2004-2008 Michael Richardson * Copyright (C) 2004-2009 Paul Wouters * Copyright (C) 2008 Antony Antony * Copyright (C) 2009 Avesh Agarwal * Copyright (C) 2012 Paul Wouters * Copyright (C) 2013 Tuomo Soini * Copyright (C) 2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #ifndef _CONSTANTS_H_ #define _CONSTANTS_H_ #include /* for size_t */ #include /* for strcmp() */ #include "shunk.h" struct lswlog; /* Some constants code likes to use. Useful? */ enum { secs_per_minute = 60, secs_per_hour = 60 * secs_per_minute, secs_per_day = 24 * secs_per_hour }; /* * This file was split into internal contants (Libreswan/pluto related), * and external constants (defined by IETF, etc.) * * Constants that are kernel/IPsec related are in appropriate * libreswan / *.h files. * */ /* * NOTE:For debugging purposes, constants.c has tables to map * numbers back to names. * Any changes here should be reflected there. */ /* * min()/max() macros that also do * strict type-checking.. See the * "unnecessary" pointer comparison. * Note: re-evaluation is avoided. * Copied from include/linux/kernel.h * Copyright Torvalds et al. */ #define min(x, y) ({ \ typeof(x) _min1 = (x); \ typeof(y) _min2 = (y); \ (void) (&_min1 == &_min2); \ _min1 < _min2 ? _min1 : _min2; }) #define max(x, y) ({ \ typeof(x) _max1 = (x); \ typeof(y) _max2 = (y); \ (void) (&_max1 == &_max2); \ _max1 > _max2 ? _max1 : _max2; }) /* * Alternate MIN/MAX implementation. * * These have more macro-like behaviour (hence NAMING): * - if the arguments are compile-time constants, then so is the result * so this can be used (for example) in array bound calculation. * - one of the arguments will be evaluated twice. * - type errors are probably not detected. * - does not depend on GCC extensions to C language * * The P prefix is required because defines MIN and MAX */ #define PMIN(x,y) ((x) <= (y) ? (x) : (y)) #define PMAX(x,y) ((x) >= (y) ? (x) : (y)) /* * Libreswan was written before was standardized. * We continue to use TRUE and FALSE because we think that they are clearer * than true or false. */ #include /* for 'bool' */ #ifndef TRUE # define TRUE true #endif #ifndef FALSE # define FALSE false #endif #define NULL_FD (-1) /* NULL file descriptor */ #include #include /* from nspr4 devel */ #ifndef BITS_PER_BYTE # define BITS_PER_BYTE 8 #endif #define BYTES_FOR_BITS(b) (((b) + BITS_PER_BYTE - 1) / BITS_PER_BYTE) /* clearer shorthand for *cmp functions */ #define streq(a, b) (strcmp((a), (b)) == 0) #define strneq(a, b, c) (strncmp((a), (b), (c)) == 0) #define startswith(a, b) strneq((a), (b), strlen(b)) #define eat(a, b) (startswith((a), (b))? ((a) += sizeof(b) - 1), TRUE : FALSE) #define strcaseeq(a, b) (strcasecmp((a), (b)) == 0) #define strncaseeq(a, b, n) (strncasecmp((a), (b), (n)) == 0) #define memeq(a, b, n) (memcmp((a), (b), (n)) == 0) /* * Fill a string field, ensuring that it is padded and terminated with NUL * If termination isn't required, strncpy would do. * If filling isn't required, jam_str would do. */ #define fill_and_terminate(dest, src, len) { \ strncpy((dest), (src), (len)-1); \ (dest)[(len)-1] = '\0'; \ } /* * zero an object given a pointer to it. * * Note: this won't work on a pointer to the first element of an * array since sizeof() will only give the length of the first element. * Unfortunately, no compiler diagnostic will flag this. * Any array will have to be prefixed with an & to yield a pointer * to the whole array. The normal representation for a string or pointer * to a raw buffer is a pointer to the first element, so they cannot be zeroed. * * Simple form of this rule: * The argument to zero must be prefixed by & unless it is a pointer * to the object you wish to zero. A pointer to an object must be * a pointer to the whole object, not just the first element. * * Note also that zeroing a pointer is not guaranteed to make it NULL * (read the C standard). This problem is mostly theoretical since * on almost all real architectures it works. * ??? there are many calls that are intended to set pointers to NULL. * ??? there are many calls to zero that are not needed and thus confusing. * Often we would be better served if calls to messup were used: * actual bugs might be detected. */ #define zero(x) memset((x), '\0', sizeof(*(x))) /* zero all bytes */ /* * messup: set memory to a deterministic useless value * * Like zero macro, but sets object to likely wrong value. * The intent is that memory that is supposed to not be used * without further initialization will not accidentally have a * plausible value (eg. zero, or the previous value, or some * secret that might be leaked). */ #define messupn(x, n) memset((x), 0xFB, (n)) /* set n bytes to wrong value */ #define messup(x) messupn((x), sizeof(*(x))) /* set all bytes to wrong value */ extern const char *bool_str(bool b); /* bool -> string */ /* routines to copy C strings to fixed-length buffers */ extern char *jam_str(char *dest, size_t size, const char *src); extern char *add_str(char *buf, size_t size, char *hint, const char *src); /* Routines to check and display values. * * WARNING: Some of these routines are not re-entrant because * they use a static buffer. * When a non-re-entrant version is called, the buffer holding the result * may be overwritten by the next call. Among other things, this means that * at most one call should appear in the argument list to a function call * (e.g. a call to a log function). */ /* Printing Enums: * * An enum_names table describes an enumeration (a correspondence * between integer values and names). * * enum_name() returns the name of an enum value, or NULL if unnamed. * enum_show() is like enum_name, except it formats a numeric representation * for any unnamed value (in a static area -- NOT RE-ENTRANT) * enum_showb() is like enum_show() but uses a caller-supplied buffer * for any unnamed value and thus is re-entrant. * * lswlog_enum() appends the name of an enum value; if unnamed, append * a mashup of the standard prefix and the numeric value. * * lswlog_enum_short() appends the name of an enum value with any * standard prefix removed; if unnamed, append a mashup of the * standard prefix and the numeric value. */ typedef const struct enum_names enum_names; extern const char *enum_name(enum_names *ed, unsigned long val); extern const char *enum_short_name(enum_names *ed, unsigned long val); /* old names */ size_t lswlog_enum(struct lswlog *, enum_names *en, unsigned long val); size_t lswlog_enum_short(struct lswlog *, enum_names *en, unsigned long val); /* new names */ #define jam_enum lswlog_enum #define jam_enum_short lswlog_enum /* caller-allocated buffer for enum_showb */ struct esb_buf { /* enough space for decimal rep of any unsigned long + "??" * sizeof yields log-base-256 of maximum value. * Multiplying by 241/100 converts this to the number of decimal digits * (the common log), rounded up a little (instead of 2.40654...). * The addition of 99 ensures that the division rounds up to an integer * rather than truncates. */ char buf[(sizeof(unsigned long) * 241 + 99) / 100 + sizeof("??")]; }; extern const char *enum_showb(enum_names *ed, unsigned long val, struct esb_buf *); extern const char *enum_show_shortb(enum_names *ed, unsigned long val, struct esb_buf *); extern const char *enum_show(enum_names *ed, unsigned long val); /* NOT RE-ENTRANT */ /* * iterator * * start with -1 -- we hope more immune to rounding * ??? how are integers subject to rounding? */ extern long next_enum(enum_names *en, long last); /* sometimes the prefix gets annoying */ extern const char *strip_prefix(const char *s, const char *prefix); extern int enum_search(enum_names *ed, const char *string); /* * Search ED for an enum matching STRING. Return -1 if no match is * found. * * Unlike enum_search() this compares strings both with and without * any prefix or suffix. For instance, given the enum_name entry * "ESP_BLOWFISH(OBSOLETE)" with prefix "ESP_", any of * "esp_blowfish(obsolete)", "esp_blowfish" and "blowfish" will match. */ extern int enum_match(enum_names *ed, shunk_t string); /* * Printing enum enums. * * An enum_enum_names table describes an enumeration first identified * by a TYPE and then identified by a VALUE. * * Like above: * * enum_enum_table() returns TABLE's enum_names, or NULL. * enum_enum_name() returns TABLE VAL's enum, or NULL. * enum_enum_showb() returns TABLE VAL's enum or %ld using BUF. * * lswlog_enum_enum() appends TABLE VAL's enum name; if unnamed, * append a mashup of the standard prefix and the numeric value. * * lswlog_enum_enum_short() appends TABLE VAL's enum name with any * standard prefix removed; if unnamed, append a mashup of the * standard prefix and the numeric value. */ typedef const struct enum_enum_names enum_enum_names; enum_names *enum_enum_table(enum_enum_names *e, unsigned long table); const char *enum_enum_name(enum_enum_names *e, unsigned long table, unsigned long val); const char *enum_enum_showb(enum_enum_names *e, unsigned long table, unsigned long val, struct esb_buf *buf); /* old */ size_t lswlog_enum_enum(struct lswlog *log, enum_enum_names *een, unsigned long table, unsigned long val); size_t lswlog_enum_enum_short(struct lswlog *log, enum_enum_names *een, unsigned long table, unsigned long val); /* new */ #define jam_enum_enum lswlog_enum_enum #define jam_enum_enum_short lswlog_enum_enum_short /* * The sparser_name should be transformed into keyword_enum_value * * keyword_enum_value is used by starter() * */ #define LOOSE_ENUM_OTHER 255 struct keyword_enum_value { const char *name; unsigned int value; }; struct keyword_enum_values { const struct keyword_enum_value *values; size_t valuesize; }; /* sparse_names is much like enum_names, except values are * not known to be contiguous or ordered. * The array of names is ended with one with the name sparse_end * (this avoids having to reserve a value to signify the end). * Often appropriate for enums defined by others. */ struct sparse_name { unsigned long val; const char *const name; }; typedef const struct sparse_name sparse_names[]; extern const char *sparse_name(sparse_names sd, unsigned long val); extern const char *sparse_val_show(sparse_names sd, unsigned long val); /* uses static buffer -- NOT RE-ENTRANT */ extern const char sparse_end[]; #define FULL_INET_ADDRESS_SIZE 6 extern void init_constants(void); #include "ietf_constants.h" #include "pluto_constants.h" #include "names_constant.h" #endif /* _CONSTANTS_H_ */ libreswan-3.32/include/crypt_hash.h000066400000000000000000000037621365625662500174170ustar00rootroot00000000000000/* Hash algorithms, for libreswan * * Copyright (C) 2016-2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef crypt_hash_h #define crypt_hash_h #include #include "chunk.h" #include "crypt_mac.h" struct hash_desc; struct crypt_hash; /* * Initialization. */ struct crypt_hash *crypt_hash_init(const char *hash_name, const struct hash_desc *hash_desc); /* * Digest the body */ void crypt_hash_digest_symkey(struct crypt_hash *hash, const char *symkey_name, PK11SymKey *symkey); void crypt_hash_digest_byte(struct crypt_hash *hash, const char *byte_name, uint8_t byte); void crypt_hash_digest_bytes(struct crypt_hash *hash, const char *bytes_name, const void *bytes, size_t sizeof_bytes); #define crypt_hash_digest_hunk(HASH, NAME, HUNK) \ { \ typeof(HUNK) hunk_ = HUNK; /* evaluate once */ \ crypt_hash_digest_bytes(HASH, NAME, \ hunk_.ptr, hunk_.len); \ } #define crypt_hash_digest_thing(HASH, NAME, THING) crypt_hash_digest_bytes(HASH, NAME, &THING, sizeof(THING)) /* * Finally ... * * This will free HASH and blat the pointer. */ void crypt_hash_final_bytes(struct crypt_hash **hashp, uint8_t *bytes, size_t sizeof_bytes); struct crypt_mac crypt_hash_final_mac(struct crypt_hash **hashp); /* * Short cut for symkeys. */ PK11SymKey *crypt_hash_symkey(const char *hash_name, const struct hash_desc *hash_desc, const char *symkey_name, PK11SymKey *symkey); #endif libreswan-3.32/include/crypt_mac.h000066400000000000000000000025251365625662500172300ustar00rootroot00000000000000/* mac result from PRF and HASH functions, for libreswan * * Copyright (C) 2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef CRYPT_MAC_H #define CRYPT_MAC_H #include /* for size_t */ #include /* for uint8_t */ /* * Structure big enough for all MAC results (returned by PRF and HASH * functions) returned by crypt_{prf,hash}_final_mac(). * * See also ike_alg_init() for runtime check that the array is big * enough. * * XXX: the field names (noteably the counter intuitive .ptr) are * chosen so that this structure is "hunk" like and works with hunk() * macros. * */ struct crypt_mac { /* size of the mac in bytes */ size_t len; /* XXX: see note above about why this is called .ptr */ uint8_t ptr[64/*see ike_alg_init() for size check*/]; }; extern const struct crypt_mac empty_mac; #endif libreswan-3.32/include/crypt_prf.h000066400000000000000000000063371365625662500172640ustar00rootroot00000000000000/* prf and keying material helper functions, for libreswan * * Copyright (C) 2007 Michael C. Richardson * Copyright (C) 2010 Paul Wouters * Copyright (C) 2013 D. Hugh Redelmeier * Copyright (C) 2015-2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef crypt_prf_h #define crypt_prf_h #include #include "chunk.h" #include "crypt_mac.h" struct hash_desc; struct crypt_prf; /* * FIPS requires a minimum key size. In FIPS mode, when the key is * less than this, the init will fail. Here the "floor" is the * minimum of all the fips algorithms so failing this is really bad. */ size_t crypt_prf_fips_key_size_min(const struct prf_desc *prf_desc); size_t crypt_prf_fips_key_size_floor(void); /* * Primitives implementing IKE PRFs. * * Some PRFs are implemented using the HMAC algorithm (described in * rfc2104) and an underlying MAC (hash) function. Others are (at * least in theory) implemented directly. * * This implementation tries to keep all the input and output material * secure inside SymKeys. To that end, it should be good for * generating keying material. * * The slightly clunky, interface is described in-line below. */ /* * Using KEY, create a PRF. */ struct crypt_prf *crypt_prf_init_symkey(const char *prf_name, const struct prf_desc *prf_desc, const char *key_name, PK11SymKey *key); struct crypt_prf *crypt_prf_init_bytes(const char *prf_name, const struct prf_desc *prf_desc, const char *key_name, const void *key, size_t sizeof_key); #define crypt_prf_init_hunk(PRF_NAME, PRF, KEY_NAME, KEY) \ crypt_prf_init_bytes(PRF_NAME, PRF, KEY_NAME, (KEY).ptr, (KEY).len) /* * Call these to accumulate the seed/data/text. */ void crypt_prf_update_symkey(struct crypt_prf *prf, const char *update_name, PK11SymKey *update); void crypt_prf_update_byte(struct crypt_prf *prf, const char *update_name, uint8_t update); void crypt_prf_update_bytes(struct crypt_prf *prf, const char *update_name, const void *update, size_t update_size); #define crypt_prf_update_hunk(PRF, UPDATE_NAME, HUNK) \ { \ typeof(HUNK) hunk_ = HUNK; /* evaluate once */ \ crypt_prf_update_bytes(PRF, UPDATE_NAME, \ hunk_.ptr, hunk_.len); \ } #define crypt_prf_update_thing(PRF, NAME, THING) \ crypt_prf_update_bytes(PRF, NAME, &(THING), sizeof(THING)) /* * Finally ... * * This will free PRF and blat the pointer. */ PK11SymKey *crypt_prf_final_symkey(struct crypt_prf **prfp); void crypt_prf_final_bytes(struct crypt_prf **prfp, void *bytes, size_t sizeof_bytes); struct crypt_mac crypt_prf_final_mac(struct crypt_prf **prfp, const struct integ_desc *integ); #endif libreswan-3.32/include/crypt_symkey.h000066400000000000000000000126041365625662500200100ustar00rootroot00000000000000/* * SYMKEY manipulation functions, for libreswan * * Copyright (C) 2015, 2016 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef crypt_symkey_h #define crypt_symkey_h #include #include #include "chunk.h" #include "where.h" #include "jambuf.h" struct ike_alg; struct hash_desc; struct encrypt_desc; struct prf_desc; /* * Log some information on a SYMKEY. * * The format is : -key@... */ void DBG_symkey(const char *prefix, const char *name, PK11SymKey *key); void jam_symkey(jambuf_t *buf, const char *name, PK11SymKey *key); /* * Add/delete references to a reference-countered PK11SymKey. */ void release_symkey(const char *prefix, const char *name, PK11SymKey **key); PK11SymKey *reference_symkey(const char *prefix, const char *name, PK11SymKey *key); /* * Length of a symkey in bytes. * * If KEY is NULL, return 0 (and we hope not dump core). (If we're * not allowed to know the length of the key then this will also * return 0). */ size_t sizeof_symkey(PK11SymKey *key); /* * Append new keying material to an existing key forming a new key; * unreference the old key, replacing it with the new one. * * Use this to chain a series of concat operations. */ void append_symkey_symkey(PK11SymKey **lhs, PK11SymKey *rhs); void append_symkey_bytes(const char *result, PK11SymKey **lhs, const void *rhs, size_t sizeof_rhs); #define append_symkey_hunk(NAME, LHS, RHS) \ append_symkey_bytes(NAME, LHS, (RHS).ptr, (RHS).len) void prepend_bytes_to_symkey(const char *result, const void *lhs, size_t sizeof_lhs, PK11SymKey **rhs); #define prepend_hunk_to_symkey(NAME, LHS, RHS) \ append_bytes_symkey(NAME, (LHS).ptr, (LHS).len, RHS) void append_symkey_byte(PK11SymKey **lhs, uint8_t rhs); void append_chunk_bytes(const char *name, chunk_t *lhs, const void *rhs, size_t sizeof_rhs); #define append_chunk_hunk(NAME, LHS, RHS) \ append_chunk_bytes(NAME, LHS, (RHS).ptr, (RHS).len) void append_chunk_symkey(const char *name, chunk_t *lhs, PK11SymKey *rhs); /* * Extract SIZEOF_SYMKEY bytes of keying material as an ALG key (i.e., * can be used to implement ALG). * * For instance, an encryption key needs to have a type matching the * NSS encryption algorithm. * * Offset into the SYMKEY is in BYTES. */ PK11SymKey *prf_key_from_symkey_bytes(const char *name, const struct prf_desc *prf, size_t symkey_start_byte, size_t sizeof_symkey, PK11SymKey *source_key, where_t where); /* * Extract SIZEOF_SYMKEY bytes of keying material as an ALG key (i.e., * can be used to implement ALG). * * For instance, an encryption key needs to have a type matching the * NSS encryption algorithm. * * Offset into the SYMKEY is in BYTES. */ PK11SymKey *encrypt_key_from_symkey_bytes(const char *name, const struct encrypt_desc *encrypt, size_t symkey_start_byte, size_t sizeof_symkey, PK11SymKey *source_key, where_t where); /* * Extract wire material from a symkey. * * Used to avoid interface issues with NSS. If ALG is null then the * key has a generic mechanism type. */ chunk_t chunk_from_symkey(const char *prefix, PK11SymKey *symkey); chunk_t chunk_from_symkey_bytes(const char *prefix, PK11SymKey *symkey, size_t chunk_start, size_t sizeof_chunk); /* * Create a key suitable for ALG. * * Used to avoid interface issues with NSS. */ PK11SymKey *symkey_from_bytes(const char *name, const uint8_t *bytes, size_t sizeof_bytes); #define symkey_from_hunk(NAME, HUNK) \ symkey_from_bytes(NAME, (HUNK).ptr, (HUNK).len) PK11SymKey *encrypt_key_from_bytes(const char *name, const struct encrypt_desc *encrypt, const uint8_t *bytes, size_t sizeof_bytes, where_t where); /* XXX: can't pass HERE aka '{,}' to macros */ #define encrypt_key_from_hunk(NAME, ENCRYPT, HUNK) \ encrypt_key_from_bytes(NAME, ENCRYPT, (HUNK).ptr, (HUNK).len, HERE) PK11SymKey *prf_key_from_bytes(const char *name, const struct prf_desc *prf, const uint8_t *bytes, size_t sizeof_bytes, where_t where); /* XXX: can't pass HERE aka '{,}' to macros */ #define prf_key_from_hunk(NAME, PRF, HUNK) \ prf_key_from_bytes(NAME, PRF, (HUNK).ptr, (HUNK).len, HERE) /* * Extract SIZEOF_KEY bytes of keying material as a KEY. * * Good for extracting hash or other keys that don't yet have an NSS * type. * * Offset into the SYMKEY is in BYTES. */ PK11SymKey *key_from_symkey_bytes(PK11SymKey *source_key, size_t next_byte, size_t sizeof_key, where_t where); /* * XOR a symkey with a chunk. */ PK11SymKey *xor_symkey_chunk(PK11SymKey *lhs, chunk_t rhs); /* * Generic operation. */ PK11SymKey *crypt_derive(PK11SymKey *base_key, CK_MECHANISM_TYPE derive, SECItem *params, const char *target_name, CK_MECHANISM_TYPE target_mechanism, CK_ATTRIBUTE_TYPE operation, int key_size, CK_FLAGS flags, where_t where); #endif libreswan-3.32/include/deltatime.h000066400000000000000000000063711365625662500172220ustar00rootroot00000000000000/* time difference objects and functions, for libreswan * * Copyright (C) 1998, 1999, 2000 Henry Spencer. * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs * Copyright (C) 2018 Andrew Cagney * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. * */ #ifndef DELTATIME_H #define DELTATIME_H /* seen it, no need to see it again */ #include /* for time_t */ #include /* for struct timeval */ #include /* for intmax_t */ #include /* for bool */ #include "jambuf.h" /* * XXX: This value isn't typed so what is it really the max of? * * XXX: One use, the intent seems to be to set a bound on * --crlcheckinterval . Because deltatime_t, when converted * to milliseconds, needs to be representable as a intmax_t the below * is two big. */ #define TIME_T_MAX ((time_t) ((1ull << (sizeof(time_t) * BITS_PER_BYTE - 1)) - 1)) /* * deltatime_t: relative time between events. Presumed continuous. * * A struct initializer for an object of static storage duration * cannot include a compound literal (or a function call). * DELTATIME_INIT is suitable for a struct initializer. * It's optional in an initializer for an object of automatic storage duration. * Because it lacks the cast, this macro should not be used in other contexts. * Sigh. */ typedef struct { struct timeval dt; } deltatime_t; #define DELTATIME_INIT(S) { .dt = { .tv_sec = (S), } } deltatime_t deltatime(time_t secs); deltatime_t deltatime_ms(intmax_t ms); deltatime_t deltatime_timevals_diff(struct timeval l, struct timeval r); /* sign(a - b) */ int deltatime_cmp(deltatime_t a, deltatime_t b); /* max(a, b) */ deltatime_t deltatime_max(deltatime_t a, deltatime_t b); /* a+b */ deltatime_t deltatime_add(deltatime_t a, deltatime_t b); /* a*s */ deltatime_t deltatime_mulu(deltatime_t a, unsigned scalar); /* a/s */ deltatime_t deltatime_divu(deltatime_t a, unsigned scalar); intmax_t deltamillisecs(deltatime_t d); intmax_t deltasecs(deltatime_t d); deltatime_t deltatimescale(int num, int denom, deltatime_t d); bool deltaless(deltatime_t a, deltatime_t b); bool deltaless_tv_dt(const struct timeval a, const deltatime_t b); /* Convert to struct timeval. */ struct timeval deltatimeval(deltatime_t); /* output as "smart" seconds */ typedef struct { /* slightly over size */ char buf[sizeof("-18446744073709551615.1000000")+1/*canary*/]; /* true length ???? */ } deltatime_buf; const char *str_deltatime(deltatime_t d, deltatime_buf *buf); size_t jam_deltatime(jambuf_t *buf, deltatime_t d); #define lswlog_deltatime jam_deltatime /* XXX: TBD */ /* jam_deltatime() */ /* * legacy. */ /* But what about -ve? */ #define PRI_DELTATIME "%jd.%03jd" #define pri_deltatime(D) (deltamillisecs(D) / 1000), (deltamillisecs(D) % 1000) #endif libreswan-3.32/include/dnssec.h000066400000000000000000000020001365625662500165120ustar00rootroot00000000000000#ifndef _DNSSEC_H # define _DNSSEC_H #include #include #include #include "ip_address.h" extern void unbound_ctx_free(void); extern void unbound_sync_init(bool do_dnssec, const char *rootfile, const char *trusted); extern bool unbound_event_init(struct event_base *eb, bool do_dnssec, const char *rootfile, const char *trusted); extern bool unbound_resolve(char *src, size_t srclen, int af, ip_address *ipaddr); extern struct ub_ctx *get_unbound_ctx(void); /* * returned in callback of ub_resolve_event * with sec: 0 if insecure, 1 if bogus, 2 if DNSSEC secure. * Note these constants are only for ub_resolve_event. * Other resolve functions may have different values for secure. * Pluto locally use DNSSEC_SECURE et el.. * * Separate from this is ub_result.secure, which is true or false, * returned by ub_resolve or ub_resove_async */ enum lswub_resolve_event_secure_kind { UB_EVENT_INSECURE = 0, UB_EVENT_BOGUS = 1, UB_EVNET_SECURE = 2, }; #endif libreswan-3.32/include/enum_names.h000066400000000000000000000021501365625662500173700ustar00rootroot00000000000000/* table structure used by enum_name() and friends. * * Note: this structure is opaque to all files that don't * define tables for enum_name() and friends. * * To simplify initializing * en_names, en_checklen * een_enum_names, een_checklen * use ARRAY_REF() */ struct enum_names { unsigned long en_first; /* first value in range */ unsigned long en_last; /* last value in range (inclusive) */ const char *const *en_names; size_t en_checklen; /* for checking: elemsof(en_names) == en_last-enfirst+1 */ const char *const en_prefix; /* what to remove for short name */ const enum_names *en_next_range; /* descriptor of next range */ }; struct enum_enum_names { unsigned long een_first; /* first value in range */ unsigned long een_last; /* last value in range (inclusive) */ const enum_names *const *const een_enum_name; /* actual table to use, subscripted by previous enum */ size_t een_checklen; /* for checking: elemsof(een_names) == een_last-enfirst+1 */ }; /* to check that enum_names are consistent */ extern void check_enum_names(enum_names *checklist[], size_t tl); libreswan-3.32/include/err.h000066400000000000000000000025001365625662500160300ustar00rootroot00000000000000/* error return type, for libreswan * * Copyright (C) 1998, 1999, 2000 Henry Spencer. * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef ERR_H #define ERR_H /* * Many routines return only success or failure, but wish to describe * the failure in a message. We use the convention that they return a * NULL on success and a pointer to constant string on failure. The * fact that the string is a constant is limiting, but it avoids * storage management issues: the recipient is allowed to assume that * the string will live "long enough" (usually forever). * * XXX: Since the above was written pluto has become multi-threaded * so, only when on the main thread, can this be true. */ typedef const char *err_t; /* error message, or NULL for success */ #endif libreswan-3.32/include/fd.h000066400000000000000000000042071365625662500156370ustar00rootroot00000000000000/* file descriptor functions * * Copyright (C) 1997 Angelos D. Keromytis. * Copyright (C) 1998-2002,2013 D. Hugh Redelmeier * Copyright (C) 2004-2008 Michael Richardson * Copyright (C) 2004-2009 Paul Wouters * Copyright (C) 2008 Antony Antony * Copyright (C) 2009 Avesh Agarwal * Copyright (C) 2012 Paul Wouters * Copyright (C) 2013 Tuomo Soini * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #ifndef FD_H #define FD_H #include #include "where.h" struct msghdr; /* opaque and reference counted */ struct fd; /* * A magic value such that: fd_p(null_fd)==false */ #define null_fd ((struct fd *) NULL) struct fd *fd_accept(int socket, where_t where); #define dup_any(FD) dup_any_fd((FD), HERE) struct fd *dup_any_fd(struct fd *fd, where_t where); #define close_any(FD) close_any_fd((FD), HERE) void close_any_fd(struct fd **fd, where_t where); void fd_leak(struct fd **fd, where_t where); ssize_t fd_sendmsg(struct fd *fd, const struct msghdr *msg, int flags, where_t where); ssize_t fd_read(struct fd *fd, void *buf, size_t nbytes, where_t where); /* * Is FD valid (as in something non-negative)? * * Use fd_p() to check the wrapped return value from functions like * open(2) (which return -1 on failure). */ bool fd_p(struct fd *fd); bool same_fd(struct fd *l, struct fd *r); /* * dbg("fd "PRI_FD, pri_fd(whackfd)) * * PRI_... names are consistent with shunk_t and hopefully avoid * clashes with reserved PRI* names. */ #define PRI_FD "fd-fd@%p" #define pri_fd(FD) (FD) #endif libreswan-3.32/include/id.h000066400000000000000000000052401365625662500156400ustar00rootroot00000000000000/* identity representation, as in IKE ID Payloads (RFC 2407 DOI 4.6.2.1) * Copyright (C) 1999-2001 D. Hugh Redelmeier * Copyright (C) 2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef ID_H #define ID_H #include "ietf_constants.h" /* for enum ike_id_type */ #include "chunk.h" #include "err.h" #include "ip_address.h" #include "jambuf.h" struct id { enum ike_id_type kind; /* used for ID_IPV4_ADDR, ID_IPV6_ADDR */ ip_address ip_addr; /* used for ID_FQDN, ID_USER_FQDN, ID_KEY_ID, ID_DER_ASN_DN */ chunk_t name; }; struct id_list { struct id id; struct id_list *next; }; extern const struct id empty_id; /* ID_NONE */ /* * parsing. */ extern err_t atoid(char *src, struct id *id, bool oe_only); /* * Formattting. * * jam_id() only emits printable ASCII. Non-printable characters, for * instance, are escaped using the RFC compliant sequence \. * * While good for logging, it isn't good for shell commands. Use * JAM_BYTES to apply additional escaping. */ void jam_id(struct lswlog *buf, const struct id *id, jam_bytes_fn *jam_bytes); typedef struct { char buf[512]; } id_buf; #define IDTOA_BUF sizeof(id_buf) const char *str_id(const struct id *id, id_buf *buf); /* * Operations. */ struct id clone_id(const struct id *id, const char *why); extern void free_id_content(struct id *id); /* also blats ID */ extern bool any_id(const struct id *a); extern bool same_id(const struct id *a, const struct id *b); #define MAX_WILDCARDS 15 extern bool match_dn_any_order_wild(chunk_t a, chunk_t b, int *wildcards); extern bool match_id(const struct id *a, const struct id *b, int *wildcards); extern int id_count_wildcards(const struct id *id); #define id_is_ipaddr(id) ((id)->kind == ID_IPV4_ADDR || (id)->kind == \ ID_IPV6_ADDR) extern bool same_dn_any_order(chunk_t a, chunk_t b); /* returns ID Type; and points body at Identification Data */ enum ike_id_type id_to_payload(const struct id *id, const ip_address *host, shunk_t *body); /* * Old stuff. */ void unshare_id_content(struct id *id); /* use clone_id() */ void duplicate_id(struct id *dst, const struct id *src); /* use free_id_content; clone_id() */ #endif libreswan-3.32/include/ietf_constants.h000066400000000000000000002035621365625662500202760ustar00rootroot00000000000000/* * manifest constants * * Copyright (C) 1997 Angelos D. Keromytis. * Copyright (C) 1998-2002,2013 D. Hugh Redelmeier * Copyright (C) 2004 Michael Richardson * Copyright (C) 2012 Avesh Agarwal * Copyright (C) 2012 Paul Wouters * Copyright (C) 2012-2015 Paul Wouters * Copyright (C) 2013 Tuomo Soini * Copyright (C) 2016 Andrew Cagney * Copyright (C) 2017 Sahana Prasad * Copyright (C) 2017 Vukasin Karadzic * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #ifndef _IETF_CONSTANTS_H #define _IETF_CONSTANTS_H #include #include /* XXX: needed but should it? */ /* Group parameters from draft-ietf-ike-01.txt section 6 */ #define MODP_GENERATOR "02" /* HEX! */ /* Diffie-Hellman group 22 generator (RFC 5114) */ #define MODP_GENERATOR_DH22 \ "A4D1CBD5 C3FD3412 6765A442 EFB99905 F8104DD2 58AC507F " \ "D6406CFF 14266D31 266FEA1E 5C41564B 777E690F 5504F213 " \ "160217B4 B01B886A 5E91547F 9E2749F4 D7FBD7D3 B9A92EE1 " \ "909D0D22 63F80A76 A6A24C08 7A091F53 1DBF0A01 69B6A28A " \ "D662A4D1 8E73AFA3 2D779D59 18D08BC8 858F4DCE F97C2A24 " \ "855E6EEB 22B3B2E5" /* Diffie-Hellman group 23 generator (RFC 5114) */ #define MODP_GENERATOR_DH23 \ "AC4032EF 4F2D9AE3 9DF30B5C 8FFDAC50 6CDEBE7B 89998CAF " \ "74866A08 CFE4FFE3 A6824A4E 10B9A6F0 DD921F01 A70C4AFA " \ "AB739D77 00C29F52 C57DB17C 620A8652 BE5E9001 A8D66AD7 " \ "C1766910 1999024A F4D02727 5AC1348B B8A762D0 521BC98A " \ "E2471504 22EA1ED4 09939D54 DA7460CD B5F6C6B2 50717CBE " \ "F180EB34 118E98D1 19529A45 D6F83456 6E3025E3 16A330EF " \ "BB77A86F 0C1AB15B 051AE3D4 28C8F8AC B70A8137 150B8EEB " \ "10E183ED D19963DD D9E263E4 770589EF 6AA21E7F 5F2FF381 " \ "B539CCE3 409D13CD 566AFBB4 8D6C0191 81E1BCFE 94B30269 " \ "EDFE72FE 9B6AA4BD 7B5A0F1C 71CFFF4C 19C418E1 F6EC0179 " \ "81BC087F 2A7065B3 84B890D3 191F2BFA" /* Diffie-Hellman group 24 generator (RFC 5114) */ #define MODP_GENERATOR_DH24 \ "3FB32C9B 73134D0B 2E775066 60EDBD48 4CA7B18F 21EF2054 " \ "07F4793A 1A0BA125 10DBC150 77BE463F FF4FED4A AC0BB555 " \ "BE3A6C1B 0C6B47B1 BC3773BF 7E8C6F62 901228F8 C28CBB18 " \ "A55AE313 41000A65 0196F931 C77A57F2 DDF463E5 E9EC144B " \ "777DE62A AAB8A862 8AC376D2 82D6ED38 64E67982 428EBC83 " \ "1D14348F 6F2F9193 B5045AF2 767164E1 DFC967C1 FB3F2E55 " \ "A4BD1BFF E83B9C80 D052B985 D182EA0A DB2A3B73 13D3FE14 " \ "C8484B1E 052588B9 B7D2BBD2 DF016199 ECD06E15 57CD0915 " \ "B3353BBB 64E0EC37 7FD02837 0DF92B52 C7891428 CDC67EB6 " \ "184B523D 1DB246C3 2F630784 90F00EF8 D647D148 D4795451 " \ "5E2327CF EF98C582 664B4C0F 6CC41659" #if 0 /* too weak - left only as reference */ /* RFC-2049 */ #define MODP768_MODULUS \ "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 " \ "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD " \ "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 " \ "E485B576 625E7EC6 F44C42E9 A63A3620 FFFFFFFF FFFFFFFF" #endif /* RFC-2049 */ /* getting on the weak side now */ #define MODP1024_MODULUS \ "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 " \ "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD " \ "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 " \ "E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED " \ "EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381 " \ "FFFFFFFF FFFFFFFF" /* RFC-3526 DH5 */ #define MODP1536_MODULUS \ "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 " \ "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD " \ "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 " \ "E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED " \ "EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D " \ "C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F " \ "83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D " \ "670C354E 4ABC9804 F1746C08 CA237327 FFFFFFFF FFFFFFFF " /* RFC-3526 DH14 */ #define MODP2048_MODULUS \ "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1" \ "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD" \ "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245" \ "E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED" \ "EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D" \ "C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F" \ "83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" \ "670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B" \ "E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9" \ "DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510" \ "15728E5A 8AACAA68 FFFFFFFF FFFFFFFF" /* RFC-3526 DH15 */ #define MODP3072_MODULUS \ "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1" \ "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD" \ "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245" \ "E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED" \ "EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D" \ "C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F" \ "83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" \ "670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B" \ "E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9" \ "DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510" \ "15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64" \ "ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7" \ "ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B" \ "F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C" \ "BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31" \ "43DB5BFC E0FD108E 4B82D120 A93AD2CA FFFFFFFF FFFFFFFF" /* RFC-3526 DH16 */ #define MODP4096_MODULUS \ "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1" \ "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD" \ "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245" \ "E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED" \ "EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D" \ "C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F" \ "83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" \ "670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B" \ "E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9" \ "DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510" \ "15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64" \ "ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7" \ "ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B" \ "F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C" \ "BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31" \ "43DB5BFC E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7" \ "88719A10 BDBA5B26 99C32718 6AF4E23C 1A946834 B6150BDA" \ "2583E9CA 2AD44CE8 DBBBC2DB 04DE8EF9 2E8EFC14 1FBECAA6" \ "287C5947 4E6BC05D 99B2964F A090C3A2 233BA186 515BE7ED" \ "1F612970 CEE2D7AF B81BDD76 2170481C D0069127 D5B05AA9" \ "93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34063199" \ "FFFFFFFF FFFFFFFF" /* RFC-3526 DH17 */ #define MODP6144_MODULUS \ "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 29024E08" \ "8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD EF9519B3 CD3A431B" \ "302B0A6D F25F1437 4FE1356D 6D51C245 E485B576 625E7EC6 F44C42E9" \ "A637ED6B 0BFF5CB6 F406B7ED EE386BFB 5A899FA5 AE9F2411 7C4B1FE6" \ "49286651 ECE45B3D C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8" \ "FD24CF5F 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" \ "670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B E39E772C" \ "180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 DE2BCBF6 95581718" \ "3995497C EA956AE5 15D22618 98FA0510 15728E5A 8AAAC42D AD33170D" \ "04507A33 A85521AB DF1CBA64 ECFB8504 58DBEF0A 8AEA7157 5D060C7D" \ "B3970F85 A6E1E4C7 ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226" \ "1AD2EE6B F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C" \ "BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31 43DB5BFC" \ "E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7 88719A10 BDBA5B26" \ "99C32718 6AF4E23C 1A946834 B6150BDA 2583E9CA 2AD44CE8 DBBBC2DB" \ "04DE8EF9 2E8EFC14 1FBECAA6 287C5947 4E6BC05D 99B2964F A090C3A2" \ "233BA186 515BE7ED 1F612970 CEE2D7AF B81BDD76 2170481C D0069127" \ "D5B05AA9 93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34028492" \ "36C3FAB4 D27C7026 C1D4DCB2 602646DE C9751E76 3DBA37BD F8FF9406" \ "AD9E530E E5DB382F 413001AE B06A53ED 9027D831 179727B0 865A8918" \ "DA3EDBEB CF9B14ED 44CE6CBA CED4BB1B DB7F1447 E6CC254B 33205151" \ "2BD7AF42 6FB8F401 378CD2BF 5983CA01 C64B92EC F032EA15 D1721D03" \ "F482D7CE 6E74FEF6 D55E702F 46980C82 B5A84031 900B1C9E 59E7C97F" \ "BEC7E8F3 23A97A7E 36CC88BE 0F1D45B7 FF585AC5 4BD407B2 2B4154AA" \ "CC8F6D7E BF48E1D8 14CC5ED2 0F8037E0 A79715EE F29BE328 06A1D58B" \ "B7C5DA76 F550AA3D 8A1FBFF0 EB19CCB1 A313D55C DA56C9EC 2EF29632" \ "387FE8D7 6E3C0468 043E8F66 3F4860EE 12BF2D5B 0B7474D6 E694F91E" \ "6DCC4024 FFFFFFFF FFFFFFFF" /* RFC-3526 DH18 */ #define MODP8192_MODULUS \ "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1" \ "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD" \ "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245" \ "E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED" \ "EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D" \ "C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F" \ "83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" \ "670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B" \ "E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9" \ "DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510" \ "15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64" \ "ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7" \ "ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B" \ "F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C" \ "BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31" \ "43DB5BFC E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7" \ "88719A10 BDBA5B26 99C32718 6AF4E23C 1A946834 B6150BDA" \ "2583E9CA 2AD44CE8 DBBBC2DB 04DE8EF9 2E8EFC14 1FBECAA6" \ "287C5947 4E6BC05D 99B2964F A090C3A2 233BA186 515BE7ED" \ "1F612970 CEE2D7AF B81BDD76 2170481C D0069127 D5B05AA9" \ "93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34028492" \ "36C3FAB4 D27C7026 C1D4DCB2 602646DE C9751E76 3DBA37BD" \ "F8FF9406 AD9E530E E5DB382F 413001AE B06A53ED 9027D831" \ "179727B0 865A8918 DA3EDBEB CF9B14ED 44CE6CBA CED4BB1B" \ "DB7F1447 E6CC254B 33205151 2BD7AF42 6FB8F401 378CD2BF" \ "5983CA01 C64B92EC F032EA15 D1721D03 F482D7CE 6E74FEF6" \ "D55E702F 46980C82 B5A84031 900B1C9E 59E7C97F BEC7E8F3" \ "23A97A7E 36CC88BE 0F1D45B7 FF585AC5 4BD407B2 2B4154AA" \ "CC8F6D7E BF48E1D8 14CC5ED2 0F8037E0 A79715EE F29BE328" \ "06A1D58B B7C5DA76 F550AA3D 8A1FBFF0 EB19CCB1 A313D55C" \ "DA56C9EC 2EF29632 387FE8D7 6E3C0468 043E8F66 3F4860EE" \ "12BF2D5B 0B7474D6 E694F91E 6DBE1159 74A3926F 12FEE5E4" \ "38777CB6 A932DF8C D8BEC4D0 73B931BA 3BC832B6 8D9DD300" \ "741FA7BF 8AFC47ED 2576F693 6BA42466 3AAB639C 5AE4F568" \ "3423B474 2BF1C978 238F16CB E39D652D E3FDB8BE FC848AD9" \ "22222E04 A4037C07 13EB57A8 1A23F0C7 3473FC64 6CEA306B" \ "4BCBC886 2F8385DD FA9D4B7F A2C087E8 79683303 ED5BDD3A" \ "062B3CF5 B3A278A6 6D2A13F8 3F44F82D DF310EE0 74AB6A36" \ "4597E899 A0255DC1 64F31CC5 0846851D F9AB4819 5DED7EA1" \ "B1D510BD 7EE74D73 FAF36BC3 1ECFA268 359046F4 EB879F92" \ "4009438B 481C6CD7 889A002E D5EE382B C9190DA6 FC026E47" \ "9558E447 5677E9AA 9E3050E2 765694DF C81F56E8 80B96E71" \ "60C980DD 98EDD3DF FFFFFFFF FFFFFFFF" /* Diffie-Hellman group 22 prime (RFC 5114) */ #define MODP1024_MODULUS_DH22 \ "B10B8F96 A080E01D DE92DE5E AE5D54EC 52C99FBC FB06A3C6 " \ "9A6A9DCA 52D23B61 6073E286 75A23D18 9838EF1E 2EE652C0 " \ "13ECB4AE A9061123 24975C3C D49B83BF ACCBDD7D 90C4BD70 " \ "98488E9C 219A7372 4EFFD6FA E5644738 FAA31A4F F55BCCC0 " \ "A151AF5F 0DC8B4BD 45BF37DF 365C1A65 E68CFDA7 6D4DA708 " \ "DF1FB2BC 2E4A4371" /* Diffie-Hellman group 23 prime (RFC 5114) */ #define MODP2048_MODULUS_DH23 \ "AD107E1E 9123A9D0 D660FAA7 9559C51F A20D64E5 683B9FD1 " \ "B54B1597 B61D0A75 E6FA141D F95A56DB AF9A3C40 7BA1DF15 " \ "EB3D688A 309C180E 1DE6B85A 1274A0A6 6D3F8152 AD6AC212 " \ "9037C9ED EFDA4DF8 D91E8FEF 55B7394B 7AD5B7D0 B6C12207 " \ "C9F98D11 ED34DBF6 C6BA0B2C 8BBC27BE 6A00E0A0 B9C49708 " \ "B3BF8A31 70918836 81286130 BC8985DB 1602E714 415D9330 " \ "278273C7 DE31EFDC 7310F712 1FD5A074 15987D9A DC0A486D " \ "CDF93ACC 44328387 315D75E1 98C641A4 80CD86A1 B9E587E8 " \ "BE60E69C C928B2B9 C52172E4 13042E9B 23F10B0E 16E79763 " \ "C9B53DCF 4BA80A29 E3FB73C1 6B8E75B9 7EF363E2 FFA31F71 " \ "CF9DE538 4E71B81C 0AC4DFFE 0C10E64F" /* Diffie-Hellman group 24 prime (RFC 5114) */ #define MODP2048_MODULUS_DH24 \ "87A8E61D B4B6663C FFBBD19C 65195999 8CEEF608 660DD0F2 " \ "5D2CEED4 435E3B00 E00DF8F1 D61957D4 FAF7DF45 61B2AA30 " \ "16C3D911 34096FAA 3BF4296D 830E9A7C 209E0C64 97517ABD " \ "5A8A9D30 6BCF67ED 91F9E672 5B4758C0 22E0B1EF 4275BF7B " \ "6C5BFC11 D45F9088 B941F54E B1E59BB8 BC39A0BF 12307F5C " \ "4FDB70C5 81B23F76 B63ACAE1 CAA6B790 2D525267 35488A0E " \ "F13C6D9A 51BFA4AB 3AD83477 96524D8E F6A167B5 A41825D9 " \ "67E144E5 14056425 1CCACB83 E6B486F6 B3CA3F79 71506026 " \ "C0B857F6 89962856 DED4010A BD0BE621 C3A3960A 54E710C3 " \ "75F26375 D7014103 A4B54330 C198AF12 6116D227 6E11715F " \ "693877FA D7EF09CA DB094AE9 1E1A1597" #define LOCALSECRETSIZE BYTES_FOR_BITS(256) /* Limits on nonce sizes */ /* * IKEv1 RFC-2409: * The length of nonce payload MUST be between 8 and 256 bytes inclusive. */ #define IKEv1_MINIMUM_NONCE_SIZE 8 /* bytes */ #define IKEv1_MAXIMUM_NONCE_SIZE 256 /* bytes */ /* * IKEv2 RFC-7296: * Nonces used in IKEv2 MUST be randomly chosen, MUST be at least 128 bits * in size, and MUST be at least half the key size of the negotiated * pseudorandom function (PRF). However, the initiator chooses the nonce * before the outcome of the negotiation is known. Because of that, the * nonce has to be long enough for all the PRFs being proposed. */ #define IKEv2_MINIMUM_NONCE_SIZE 16 /* bytes */ #define IKEv2_MAXIMUM_NONCE_SIZE 256 /* bytes */ /* Default is based on minimum IKEv2 requirement */ #define DEFAULT_NONCE_SIZE 32 /* bytes */ /* * Security Parameter Index (SPI): * * The IKE SA's SPI, which is a fixed part of the IKEv1/IKEv2 message * header, is 8 bytes long. * * The CHILD SA's SPI is 4 bytes (IKEv2: 3.3.1. Proposal * Substructure). * * XXX: * * IKEv1, presumably as a way to ensure maximum confusion, used the * term "cookie" when describing the IKE SA's SPI in the message * header, and the term SPI when describing IKE SPIs (yes, one or two) * within a payload (the term "cookie" is included as a parenthetical * clarification). * * IKEv1, instead consistently uses SPI for both the IKE and CHILD * SAs, that is both when describing the message header and the * contents of payloads. Unfortunately, IKEv2 then went on to use * term "cookie" when describing its new cookie mechanism (implemented * with notifications). * * This would have all been ok if FreeS/WAN had used the term SPI in * its code. * * It didn't. * * Instead it choose to use the word "cookie". Hence lingering * presence of things like [ir]cookie, the macro COOKIE_SIZE (below), * and IKEv1 centric types such as ipsec_spi_t in the code. */ #define IKE_SA_SPI_SIZE 8 #define CHILD_SA_SPI_SIZE 4 #define MAX_SPI_SIZE IKE_SA_SPI_SIZE #define COOKIE_SIZE IKE_SA_SPI_SIZE #define INTERNAL_IP6_ADDRESS_SIZE 17 #define INTERNL_IP6_PREFIX_LEN_SIZE 1 #define INTERNL_IP6_PREFIX_LEN 128 #define INTERNL_IP4_PREFIX_LEN 32 /* * XXX: * * For IKEv1, the maximum number of SPI bytes in some payloads. For * instance: rfc2408: 4.6.3.1 RESPONDER-LIFETIME: either sixteen (16) * (two eight-octet ISAKMP cookies) or four (4) (one IPSEC SPI) * * XXX: this desperately needs a better name. In IKEv2 SPI size * always refers to the size of one SPI and never a pair. */ #define MAX_ISAKMP_SPI_SIZE (2 * IKE_SA_SPI_SIZE) /* IKEv2 DOS COOKIE */ #define IKEv2_MAX_COOKIE_SIZE 64 /* Various IETF defined key lengths */ /* AES-CBC RFC 3602 The _only_ valid values are 128, 192 and 256 bits */ #define AES_KEY_MIN_LEN 128 /* bits */ #define AES_KEY_DEF_LEN 128 /* bits */ #define AES_KEY_MAX_LEN 256 /* bits */ /* * https://tools.ietf.org/html/rfc3566#section-4.1 */ #define AES_XCBC_DIGEST_SIZE BYTES_FOR_BITS(128) #define AES_XCBC_DIGEST_SIZE_TRUNC BYTES_FOR_BITS(96) /* AES-CTR RFC 3686 The _only_ valid values are 128, 192 and 256 bits */ #define AES_CTR_SALT_BYTES 4 #define AES_CTR_KEY_MIN_LEN 128 /* bits */ #define AES_CTR_KEY_DEF_LEN 128 /* bits */ #define AES_CTR_KEY_MAX_LEN 256 /* bits */ /* * RFC 4106 AES GCM * https://tools.ietf.org/html/rfc4106#section-8.1 */ #define AES_GCM_SALT_BYTES 4 #define AES_GCM_KEY_MIN_LEN 128 /* bits */ #define AES_GCM_KEY_DEF_LEN 128 /* bits */ #define AES_GCM_KEY_MAX_LEN 256 /* bits */ /* * RFC 4309 AES CCM * https://tools.ietf.org/html/rfc4309#section-7.1 */ #define AES_CCM_SALT_BYTES 3 #define AES_CCM_KEY_MIN_LEN 128 /* bits */ #define AES_CCM_KEY_DEF_LEN 128 /* bits */ #define AES_CCM_KEY_MAX_LEN 256 /* bits */ /* The _only_ valid values are 128, 192 and 256 bits */ #define AEAD_AES_KEY_MIN_LEN 128 /* bits */ #define AEAD_AES_KEY_DEF_LEN 128 /* bits */ #define AEAD_AES_KEY_MAX_LEN 256 /* bits */ /* AES-GMAC RFC 4543 The _only_ valid values are 128, 192 and 256 bits */ #define AES_GMAC_KEY_MIN_LEN 128 /* bits */ #define AES_GMAC_KEY_DEF_LEN 128 /* bits */ #define AES_GMAC_KEY_MAX_LEN 256 /* bits */ /* SEED-CBC RFC 4196 The _only_ valid value is 128 */ #define SEED_KEY_MIN_LEN 128 /* bits */ #define SEED_KEY_DEF_LEN 128 /* bits */ #define SEED_KEY_MAX_LEN 128 /* bits */ /* * https://tools.ietf.org/html/rfc2451#section-2.2 * ESP_CAST is the cast5 algorithm, not cast6 * We avoid cast-128 padding by enforcing a minimum of 128 */ #define CAST_KEY_DEF_LEN 128 /* bits */ /* * RFC 2451 - Blowfish accepts key sizes 40-448, default is 128 * 128,192 and 256 are the only commonly used ones */ /* * TWOFISH-CBC is a 128-bit block cipher with variable-length key up to 256 bits * default is 128. 128, 192 and 256 are the only commonly used ones */ #define TWOFISH_KEY_MIN_LEN 128 /* bits */ #define TWOFISH_KEY_DEF_LEN 128 /* bits */ #define TWOFISH_KEY_MAX_LEN 256 /* bits */ /* * SERPENT default 128, 128, 192 and 256 are the only commonly used ones */ #define SERPENT_KEY_MIN_LEN 128 /* bits */ #define SERPENT_KEY_DEF_LEN 128 /* bits */ #define SERPENT_KEY_MAX_LEN 256 /* bits */ /* * Camellia CBC and CTR - RFC 5529 * 128 (default), 192 and 256 */ #define CAMELLIA_KEY_MIN_LEN 128 /* bits */ #define CAMELLIA_KEY_DEF_LEN 128 /* bits */ #define CAMELLIA_KEY_MAX_LEN 256 /* bits */ #define CAMELLIA_CTR_KEY_MIN_LEN 128 /* bits */ #define CAMELLIA_CTR_KEY_DEF_LEN 128 /* bits */ #define CAMELLIA_CTR_KEY_MAX_LEN 256 /* bits */ /* ought to be supplied by md5.h */ #define MD5_DIGEST_SIZE BYTES_FOR_BITS(128) /* IKEV2 integrity algorithms */ #define MD5_DIGEST_SIZE_96 BYTES_FOR_BITS(96) /* ought to be supplied by sha1.h */ #define SHA1_DIGEST_SIZE BYTES_FOR_BITS(160) #define SHA1_BLOCK_SIZE BYTES_FOR_BITS(512) /* IKEV2 integrity algorithms */ #define SHA1_DIGEST_SIZE_96 BYTES_FOR_BITS(96) #define SHA2_256_DIGEST_SIZE BYTES_FOR_BITS(256) /* sha2.h */ #define SHA2_384_DIGEST_SIZE BYTES_FOR_BITS(384) #define SHA2_512_DIGEST_SIZE BYTES_FOR_BITS(512) /* not in blapit.h */ #define DES_CBC_BLOCK_SIZE BYTES_FOR_BITS(64) #define AES_CBC_BLOCK_SIZE BYTES_FOR_BITS(128) #define TWOFISH_CBC_BLOCK_SIZE BYTES_FOR_BITS(128) /* SERPENT_CBC_BLOCK_SIZE: BYTES_FOR_BITS(128) */ /* * hand-computed max of *_CBC_BLOCK_SIZE * Needs to be a compile-time constant for array allocation. */ #define MAX_CBC_BLOCK_SIZE BYTES_FOR_BITS(128) #define DSS_QBITS 160 /* bits in DSS's "q" (FIPS 186-1) */ /* RFC 2404 "HMAC-SHA-1-96" section 3 */ #define HMAC_SHA1_KEY_LEN SHA1_DIGEST_SIZE /* bytes */ /* RFC 2403 "HMAC-MD5-96" section 3 */ #define HMAC_MD5_KEY_LEN MD5_DIGEST_SIZE /* bytes */ #define IKE_UDP_PORT 500 #define NAT_IKE_UDP_PORT 4500 /* RFC-3947 */ /* RFC3948: bytes of zeros, same size as ESP SPI */ #define NON_ESP_MARKER_SIZE 4 /* ICMP type number for neighbor discovery */ #define ICMP_NEIGHBOR_DISCOVERY 34816 #define ICMP_NEIGHBOR_SOLICITATION 34560 /* Version numbers - IKEv1 */ #define ISAKMP_MAJOR_VERSION 0x1 #define ISAKMP_MINOR_VERSION 0x0 /* version numbers - IKEv2 */ #define IKEv2_MAJOR_VERSION 0x2 #define IKEv2_MINOR_VERSION 0x0 /* Domain of Interpretation */ #define ISAKMP_DOI_ISAKMP 0 #define ISAKMP_DOI_IPSEC 1 /* IPsec DOI things */ #define IPSEC_DOI_SITUATION_LENGTH 4 #define IPSEC_DOI_LDI_LENGTH 4 #define IPSEC_DOI_SPI_SIZE 4 /* * SPI value 0 is invalid and values 1-255 are reserved to IANA. * ESP: RFC 2402 2.4; AH: RFC 2406 2.1 * IPComp RFC 2393 substitutes a CPI in the place of an SPI. * see also draft-shacham-ippcp-rfc2393bis-05.txt. * We (Libreswan) reserve 0x100 to 0xFFF for manual keying, so * Pluto won't generate these values. */ #define IPSEC_DOI_SPI_MIN 0x100 #define IPSEC_DOI_SPI_OUR_MIN 0x1000 /* * Payload types * RFC2408 Internet Security Association and Key Management Protocol (ISAKMP) * section 3.1 * * RESERVED 14-127 * Private USE 128-255 */ enum next_payload_types_ikev1 { ISAKMP_NEXT_NONE = 0, /* No other payload following - See also v2_PROPOSAL_LAST */ ISAKMP_NEXT_SA = 1, /* Security Association */ ISAKMP_NEXT_P = 2, /* Proposal - See also v2_PROPOSAL_NON_LAST */ ISAKMP_NEXT_T = 3, /* Transform */ ISAKMP_NEXT_KE = 4, /* Key Exchange */ ISAKMP_NEXT_ID = 5, /* Identification */ ISAKMP_NEXT_CERT = 6, /* Certificate */ ISAKMP_NEXT_CR = 7, /* Certificate Request */ ISAKMP_NEXT_HASH = 8, /* Hash */ ISAKMP_NEXT_SIG = 9, /* Signature */ ISAKMP_NEXT_NONCE = 10, /* Nonce */ ISAKMP_NEXT_N = 11, /* Notification */ ISAKMP_NEXT_D = 12, /* Delete */ ISAKMP_NEXT_VID = 13, /* Vendor ID */ ISAKMP_NEXT_MCFG_ATTR = 14, /* Mode config Attribute */ /* NAT-Traversal: NAT-D (bad drafts) Conflicts with RFC 3547 (not 3947!) and RFC 6407 */ /* old value: ISAKMP_NEXT_NATD_BADDRAFTS = 15 */ ISAKMP_NEXT_SAK = 15, /* SA KEK Payload - RFC 6407 */ ISAKMP_NEXT_TEK = 16, /* SA TEK Payload - RFC 6407 */ ISAKMP_NEXT_KD = 17, /* Key Download - RFC 3547 */ ISAKMP_NEXT_SEQ = 18, /* Sequence Number - RFC 3547 */ ISAKMP_NEXT_POP = 19, /* Proof of Possession - RFC 3547 */ ISAKMP_NEXT_NATD_RFC = 20, /* NAT-Traversal: NAT-D RFC 3947 */ ISAKMP_NEXT_NATOA_RFC = 21, /* NAT-Traversal: NAT-OA RFC 3947 */ ISAKMP_NEXT_GAP = 22, /* Group Associated Policy = RFC 6407 */ /* 23-127 Unassigned */ /* 128 - 255 Private Use */ ISAKMP_NEXT_NATD_DRAFTS = 130, /* NAT-Traversal: NAT-D (drafts) */ ISAKMP_NEXT_NATOA_DRAFTS = 131, /* NAT-Traversal: NAT-OA (drafts) */ /* Cisco/Microsoft proprietary IKE fragmentation */ ISAKMP_NEXT_IKE_FRAGMENTATION = 132, ISAKMP_NEXT_ROOF /* roof on payload types */ }; enum ikev2_last_proposal { /* if there is a next proposal, then the lp needs to be set right */ v2_PROPOSAL_LAST = 0, /* matches IKEv1 ISAKMP_NEXT_NONE by design */ v2_PROPOSAL_NON_LAST = 2 /* matches IKEv1 ISAKMP_NEXT_P by design */ }; enum ikev2_last_transform { /* if there is a next transform, then the lt needs to be set right */ v2_TRANSFORM_LAST = 0, /* matches IKEv1 ISAKMP_NEXT_NONE by design */ v2_TRANSFORM_NON_LAST = 3 /* matches IKEv1 ISAKMP_NEXT_T by design */ }; enum next_payload_types_ikev2 { ISAKMP_NEXT_v2NONE = 0, /* 1 - 32 Reserved for IKEv1 */ ISAKMP_NEXT_v2SA = 33, /* Security Association */ ISAKMP_NEXT_v2KE = 34, /* Key Exchange payload */ ISAKMP_NEXT_v2IDi = 35, /* ID payload - initiator */ ISAKMP_NEXT_v2IDr = 36, /* ID payload - responder */ ISAKMP_NEXT_v2CERT = 37, /* CERTificate */ ISAKMP_NEXT_v2CERTREQ = 38, /* CERTificate REQuest */ ISAKMP_NEXT_v2AUTH = 39, /* AUTHentication */ ISAKMP_NEXT_v2Ni = 40, /* Nonce - initiator */ ISAKMP_NEXT_v2Nr = ISAKMP_NEXT_v2Ni, /* Nonce - responder */ ISAKMP_NEXT_v2N = 41, /* Notify */ ISAKMP_NEXT_v2D = 42, /* Delete */ ISAKMP_NEXT_v2V = 43, /* Vendor ID */ ISAKMP_NEXT_v2TSi = 44, /* Traffic Selector - initiator */ ISAKMP_NEXT_v2TSr = 45, /* Traffic Selector - responder */ ISAKMP_NEXT_v2SK = 46, /* Encrypted payload */ ISAKMP_NEXT_v2CP = 47, /* Configuration Payload (MODECFG) */ ISAKMP_NEXT_v2EAP = 48, /* Extensible Authentication Payload */ ISAKMP_NEXT_v2GSPM = 49, /* RFC-6467 Generic Secure Password Method */ ISAKMP_NEXT_v2IDG = 50, /* Group Identification draft-yeung-g-ikev2 */ ISAKMP_NEXT_v2GSA = 51, /* Group Security Association draft-yeung-g-ikev2 */ ISAKMP_NEXT_v2KD = 52, /* Key Download draft-yeung-g-ikev2 */ ISAKMP_NEXT_v2SKF = 53, /* Encrypted and Authenticated Fragment fragment */ /* 54-127 Unassigned */ /* 128 - 255 Private Use */ /* Cisco/Microsoft proprietary IKE fragmentation - private use for libreswan */ ISAKMP_NEXT_v2IKE_FRAGMENTATION = 132, ISAKMP_NEXT_v2ROOF, /* roof on payload types */ }; #define ISAKMP_v2PAYLOAD_TYPE_BASE ISAKMP_NEXT_v2SA /* lowest value of a v2 payload type */ /* * Value to use when emitting a payload that the other end won't * recognize forcing it down the unknown (and not just unsupported) * payload code path: * * - fills the entire 8-bit field (so signed vs unsigned overflows) * * - too big to fit in an lset_t (so would overflow that code) * * - not "known" by pluto (so enum name lookups fail) * * - since it isn't known, it is also, by definition unsupported */ #define ISAKMP_NEXT_v2UNKNOWN 255 /* * These values are to be used within the Type field of an Attribute (14) * ISAKMP payload. */ #define ISAKMP_CFG_REQUEST 1 #define ISAKMP_CFG_REPLY 2 #define ISAKMP_CFG_SET 3 #define ISAKMP_CFG_ACK 4 /* Mode Config attribute values */ #define INTERNAL_IP4_ADDRESS 1 #define INTERNAL_IP4_NETMASK 2 #define INTERNAL_IP4_DNS 3 #define INTERNAL_IP4_NBNS 4 /* unused by us, WINS is long dead */ #define INTERNAL_ADDRESS_EXPIRY 5 #define INTERNAL_IP4_DHCP 6 #define APPLICATION_VERSION 7 #define INTERNAL_IP6_ADDRESS 8 #define INTERNAL_IP6_NETMASK 9 #define INTERNAL_IP6_DNS 10 #define INTERNAL_IP6_NBNS 11 #define INTERNAL_IP6_DHCP 12 #define INTERNAL_IP4_SUBNET 13 #define SUPPORTED_ATTRIBUTES 14 #define INTERNAL_IP6_SUBNET 15 #define MIP6_HOME_PREFIX 16 #define INTERNAL_IP6_LINK 17 #define INTERNAL_IP6_PREFIX 18 #define HOME_AGENT_ADDRESS 19 /* 65001 - 65535 Private Use */ #define FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I 65500 /* 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 /* * GSS mode - should only be allowed after receiving vendorids: * MD5("A GSS-API Authentication Method for IKE") * MD5("GSSAPI") (recognized by Windows 2000) * MD5("MS NT5 ISAKMPOAKLEY") (sent by Windows 2000) */ /* * Note: OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB conflicts * with XAUTH_AUTH_INIT_PSK */ #define OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB 65001 #define OAKLEY_ATTR_GSS_ID 16384 #define MAXPADLWORD 20 /* 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 /* XAUTH attribute values (draft-ietf-ipsec-isakmp-xauth-06 4.2) */ #define XAUTH_TYPE 16520 #define XAUTH_USER_NAME 16521 #define XAUTH_USER_PASSWORD 16522 #define XAUTH_PASSCODE 16523 #define XAUTH_MESSAGE 16524 #define XAUTH_CHALLENGE 16525 #define XAUTH_DOMAIN 16526 #define XAUTH_STATUS 16527 #define XAUTH_NEXT_PIN 16528 #define XAUTH_ANSWER 16529 /* Values of XAUTH_STATUS attribute (draft-ietf-ipsec-isakmp-xauth-06 4.2) */ #define XAUTH_STATUS_FAIL 0 #define XAUTH_STATUS_OK 1 /* Values of XAUTH_TYPE attributes */ #define XAUTH_TYPE_GENERIC 0 #define XAUTH_TYPE_CHAP 1 #define XAUTH_TYPE_OTP 2 #define XAUTH_TYPE_SKEY 3 /* proprietary Microsoft attributes */ #define INTERNAL_IP4_SERVER 23456 #define INTERNAL_IP6_SERVER 23457 /* Unity (Cisco) Mode Config attribute values */ #define MODECFG_BANNER 28672 #define CISCO_SAVE_PW 28673 #define MODECFG_DOMAIN 28674 #define CISCO_SPLIT_DNS 28675 #define CISCO_SPLIT_INC 28676 #define CISCO_UDP_ENCAP_PORT 28677 #define CISCO_SPLIT_EXCLUDE 28678 #define CISCO_DO_PFS 28679 #define CISCO_FW_TYPE 28680 #define CISCO_BACKUP_SERVER 28681 #define CISCO_DDNS_HOSTNAME 28682 #define CISCO_UNKNOWN_SEEN_ON_IPHONE 28683 /* 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 /* * Exchange types * RFC2408 "Internet Security Association and Key Management Protocol (ISAKMP)" * section 3.1 * * ISAKMP Future Use 6 - 31 * DOI Specific Use 32 - 239 * Private Use 240 - 255 * * Note: draft-ietf-ipsec-dhless-enc-mode-00.txt Appendix A * defines "DHless RSA Encryption" as 6. */ enum isakmp_xchg_types { ISAKMP_XCHG_NONE = 0, ISAKMP_XCHG_BASE = 1, ISAKMP_XCHG_IDPROT = 2, /* ID Protection */ ISAKMP_XCHG_AO = 3, /* Authentication Only */ ISAKMP_XCHG_AGGR = 4, /* Aggressive */ ISAKMP_XCHG_INFO = 5, /* Informational */ ISAKMP_XCHG_MODE_CFG = 6, /* Mode Config */ /* Private exchanges to pluto -- openswan mistakenly uses these */ ISAKMP_XCHG_STOLEN_BY_OPENSWAN_FOR_ECHOREQUEST = 30, /* Echo Request */ ISAKMP_XCHG_STOLEN_BY_OPENSWAN_FOR_ECHOREPLY = 31, /* Echo Reply */ /* Extra exchange types, defined by Oakley * RFC2409 "The Internet Key Exchange (IKE)", near end of Appendix A */ ISAKMP_XCHG_QUICK = 32, /* Oakley Quick Mode */ ISAKMP_XCHG_NGRP = 33, /* Oakley New Group Mode */ /* IKEv2 things */ ISAKMP_v2_IKE_SA_INIT = 34, ISAKMP_v2_IKE_AUTH = 35, ISAKMP_v2_CREATE_CHILD_SA = 36, ISAKMP_v2_INFORMATIONAL = 37, ISAKMP_v2_IKE_SESSION_RESUME = 38, /* RFC 5723 */ ISAKMP_v2_GSA_AUTH = 39, /* draft-yeung-g-ikev2 */ ISAKMP_v2_GSA_REGISTRATION = 40, /* draft-yeung-g-ikev2 */ ISAKMP_v2_GSA_REKEY = 41, /* draft-yeung-g-ikev2 */ /* 42 - 239 Unassigned */ /* 240 - 255 Private Use */ /* libreswan private use */ ISAKMP_XCHG_ECHOREQUEST_PRIVATE = 244, /* Private Echo Request */ ISAKMP_XCHG_ECHOREPLY_PRIVATE = 245, /* Private Echo Reply */ }; /* ISAKMP header flag bits */ #define ISAKMP_FLAGS_v1_ENCRYPTION (1 << 0) /* bit 0 of flags - IKEv1 encrypt */ #define ISAKMP_FLAGS_v1_COMMIT (1 << 1) /* bit 1 of flags - IKEv1 commit - unused */ #define ISAKMP_FLAGS_v1_AUTH (1 << 2) /* bit 2 of flags - IKEv1 authonly - unused */ #define ISAKMP_FLAGS_v2_IKE_I (1 << 3) /* bit 3 of flags - IKEv2 Original Initiator */ #define ISAKMP_FLAGS_v2_VER (1 << 4) /* bit 4 of flags - IKEv2 Version flag */ #define ISAKMP_FLAGS_v2_MSG_R (1 << 5) /* bit 5 of flags - IKEv2 Message response */ #define ISAKMP_FLAGS_RESERVED_BIT6 (1 << 6) /* RESERVED */ #define ISAKMP_FLAGS_RESERVED_BIT7 (1 << 7) /* RESERVED */ extern const char *const isakmp_flag_names[]; /* Situation definition for IPsec DOI */ extern const char *const sit_bit_names[]; #define SIT_IDENTITY_ONLY 0x01 #define SIT_SECRECY 0x02 #define SIT_INTEGRITY 0x04 /* * See https://tools.ietf.org/html/rfc5996#section-3.2 * Critical bit in each payload */ extern const char *const critical_names[]; #define ISAKMP_PAYLOAD_NONCRITICAL 0x00 #define ISAKMP_PAYLOAD_CRITICAL 0x80 /* These are followed by 7 more bits, currently RESERVED */ /* Note we use 1 of those bits for IMPAIR-SEND-BOGUS-ISAKMP-FLAG */ #define ISAKMP_PAYLOAD_LIBRESWAN_BOGUS 0x01 /* * Protocol IDs * RFC2407 The Internet IP security Domain of Interpretation for ISAKMP 4.4.1 */ /* * extern enum_names protocol_names; */ #define PROTO_RESERVED 0 #define PROTO_ISAKMP 1 #define PROTO_IPSEC_AH 2 #define PROTO_IPSEC_ESP 3 #define PROTO_IPCOMP 4 /* only in IKEv1 */ /* * IKEv2 Security Protocol Identifiers - RFC 5996 * * https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xhtml#ikev2-parameters-18 * * According to the IKEv2 RFC, these values are stored in 'Protocol * ID' field of a payload (see: 3.3.1. Proposal Substructure; 3.10. * Notify Payload; 3.11. Delete Payload). * * The value '0' is a little odd. While IANA lists it as Reserved, a * notify payload must use that value for notifications that do not * include an SPI. Hence 'NONE' is used. */ enum ikev2_sec_proto_id { IKEv2_SEC_PROTO_NONE = 0, #define PROTO_v2_RESERVED IKEv2_SEC_PROTO_NONE IKEv2_SEC_PROTO_IKE = 1, IKEv2_SEC_PROTO_AH = 2, #define PROTO_v2_AH IKEv2_SEC_PROTO_AH IKEv2_SEC_PROTO_ESP = 3, #define PROTO_v2_ESP IKEv2_SEC_PROTO_ESP IKEv2_SEC_FC_ESP_HEADER = 4, /* RFC 4595 */ IKEv2_SEC_FC_CT_AUTHENTICATION = 5, /* RFC 4595 */ /* 6 - 200 Unassigned */ /* 201 - 255 Private use */ }; /* * IKEv2 proposal * See https://www.iana.org/assignments/ikev2-parameters * Assume indexing is [1..IKEv2_TRANS_TYPE_ROOF) */ enum ikev2_trans_type { IKEv2_TRANS_TYPE_ENCR = 1, IKEv2_TRANS_TYPE_PRF = 2, IKEv2_TRANS_TYPE_INTEG = 3, IKEv2_TRANS_TYPE_DH = 4, /* same as in IKEv1 */ IKEv2_TRANS_TYPE_ESN = 5, IKEv2_TRANS_TYPE_ROOF }; /* * IKE and ESP encryption algorithms (note iana lists two table columns for these) * https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xhtml#ikev2-parameters-5 * (TODO: rename this to ikev2_encr_esp_ike) */ enum ikev2_trans_type_encr { IKEv2_ENCR_reserved = 0, IKEv2_ENCR_DES_IV64 = 1, IKEv2_ENCR_DES = 2, IKEv2_ENCR_3DES = 3, IKEv2_ENCR_RC5 = 4, IKEv2_ENCR_IDEA = 5, IKEv2_ENCR_CAST = 6, IKEv2_ENCR_BLOWFISH = 7, IKEv2_ENCR_3IDEA = 8, IKEv2_ENCR_DES_IV32 = 9, IKEv2_ENCR_RES10 = 10, IKEv2_ENCR_NULL = 11, IKEv2_ENCR_AES_CBC = 12, IKEv2_ENCR_AES_CTR = 13, IKEv2_ENCR_AES_CCM_8 = 14, IKEv2_ENCR_AES_CCM_12 = 15, IKEv2_ENCR_AES_CCM_16 = 16, IKEv2_UNUSED_17 = 17, IKEv2_ENCR_AES_GCM_8 = 18, IKEv2_ENCR_AES_GCM_12 = 19, IKEv2_ENCR_AES_GCM_16 = 20, IKEv2_ENCR_NULL_AUTH_AES_GMAC = 21, IKEv2_RESERVED_IEEE_P1619_XTS_AES = 22, IKEv2_ENCR_CAMELLIA_CBC = 23, IKEv2_ENCR_CAMELLIA_CTR = 24, IKEv2_ENCR_CAMELLIA_CCM_A = 25, /* CAMELLIA_CCM_8 RFC 5529 */ IKEv2_ENCR_CAMELLIA_CCM_B = 26, /* CAMELLIA_CCM_12 RFC 5529 */ IKEv2_ENCR_CAMELLIA_CCM_C = 27, /* CAMELLIA_CCM_16 RFC 5529 */ IKEv2_ENCR_CHACHA20_POLY1305 = 28, /* RFC7634 */ IKEv2_ENCR_PSTATS_ROOF, /* 29 - 1023 Reserved to IANA */ /* 1024 - 65535 Private Use */ IKEv2_ENCR_SERPENT_CBC = 65004, IKEv2_ENCR_TWOFISH_CBC = 65005, IKEv2_ENCR_TWOFISH_CBC_SSH = 65289, IKEv2_ENCR_INVALID = 65536, }; enum ikev2_trans_type_prf { IKEv2_PRF_HMAC_MD5 = 1, /* RFC2104 */ IKEv2_PRF_HMAC_SHA1 = 2, /* RFC2104 */ IKEv2_PRF_HMAC_TIGER = 3, /* RFC2104 */ IKEv2_PRF_AES128_XCBC = 4, /* RFC4434 */ IKEv2_PRF_HMAC_SHA2_256 = 5, /* RFC4868 */ IKEv2_PRF_HMAC_SHA2_384 = 6, /* RFC4868 */ IKEv2_PRF_HMAC_SHA2_512 = 7, /* RFC4868 */ IKEv2_PRF_AES128_CMAC = 8, /* RFC4615 */ IKEv2_PRF_9_INVALID = 9, IKEv2_PRF_PSTATS_ROOF, /* 9 - 1023 Reserved to IANA RFC4306 */ /* 1024 - 65535 Private Use RFC4306 */ IKEv2_PRF_INVALID = 65536 }; enum ikev2_trans_type_integ { IKEv2_AUTH_NONE = 0, /* RFC4306 */ IKEv2_AUTH_HMAC_MD5_96 = 1, /* RFC2403 */ IKEv2_AUTH_HMAC_SHA1_96 = 2, /* RFC2404 */ IKEv2_AUTH_DES_MAC = 3, /* RFC4306 */ IKEv2_AUTH_KPDK_MD5 = 4, /* RFC1826 */ IKEv2_AUTH_AES_XCBC_96 = 5, /* RFC3566 */ IKEv2_AUTH_HMAC_MD5_128 = 6, /* RFC4595 */ IKEv2_AUTH_HMAC_SHA1_160 = 7, /* RFC4595 */ IKEv2_AUTH_AES_CMAC_96 = 8, /* RFC4494 */ IKEv2_AUTH_AES_128_GMAC = 9, /* RFC4543 */ IKEv2_AUTH_AES_192_GMAC = 10, /* RFC4543 */ IKEv2_AUTH_AES_256_GMAC = 11, /* RFC4543 */ IKEv2_AUTH_HMAC_SHA2_256_128 = 12, /* RFC4595 */ IKEv2_AUTH_HMAC_SHA2_384_192 = 13, /* RFC4306 */ IKEv2_AUTH_HMAC_SHA2_512_256 = 14, /* RFC4306 */ IKEv2_AUTH_PSTATS_ROOF, /* 15 - 1023 Reserved to IANA RFC4306 */ /* 1024 - 65535 Private Use RFC4306 */ IKEv2_AUTH_INVALID = 65536 }; enum ikev2_trans_type_esn { IKEv2_ESN_DISABLED = 0, IKEv2_ESN_ENABLED = 1, }; /* * RFC 4306 Section 3.3.5 * Interestingly, there is only one attribute defined. */ enum ikev2_trans_attr_type { IKEv2_KEY_LENGTH = 14, /* note: == OAKLEY_KEY_LENGTH */ }; /* RFC 5966 Section 3.13.1 */ enum ikev2_ts_type { /* 0-6 RESERVED */ IKEv2_TS_IPV4_ADDR_RANGE = 7, IKEv2_TS_IPV6_ADDR_RANGE = 8, IKEv2_TS_FC_ADDR_RANGE = 9, /* RFC4595, not implemented */ /* 10-240 Unassigned */ /* 241-255 Private use */ }; #define KEY_IKE 1 /* the following are from RFC 2393/draft-shacham-ippcp-rfc2393bis-05.txt 3.3 */ typedef uint16_t cpi_t; #define IPCOMP_CPI_SIZE 2 #define IPCOMP_FIRST_NEGOTIATED 256 #define IPCOMP_LAST_NEGOTIATED 61439 /* * Oakley transform attributes * draft-ietf-ipsec-ike-01.txt appendix A * https://www.iana.org/assignments/ipsec-registry/ipsec-registry.xhtml#ipsec-registry-2 */ enum ikev1_oakley_attr { OAKLEY_ATTR_undefined = 0, /* not in standard */ OAKLEY_ENCRYPTION_ALGORITHM = 1, OAKLEY_HASH_ALGORITHM = 2, OAKLEY_AUTHENTICATION_METHOD = 3, OAKLEY_GROUP_DESCRIPTION = 4, OAKLEY_GROUP_TYPE = 5, OAKLEY_GROUP_PRIME = 6, /* B/V */ OAKLEY_GROUP_GENERATOR_ONE = 7, /* B/V */ OAKLEY_GROUP_GENERATOR_TWO = 8, /* B/V */ OAKLEY_GROUP_CURVE_A = 9, /* B/V */ OAKLEY_GROUP_CURVE_B = 10, /* B/V */ OAKLEY_LIFE_TYPE = 11, OAKLEY_LIFE_DURATION = 12, /* B/V */ OAKLEY_PRF = 13, OAKLEY_KEY_LENGTH = 14, OAKLEY_FIELD_SIZE = 15, OAKLEY_GROUP_ORDER = 16, /* B/V */ /* OAKLEY_BLOCK_SIZE = 17, */ /* ??? where does this come from? */ /* 17-16383 Unassigned */ /* 16384-32767 Reserved for private use */ }; /* * IPsec DOI attributes * RFC2407 The Internet IP security Domain of Interpretation for ISAKMP 4.5 */ enum ikev1_ipsec_attr { SA_LIFE_TYPE = 1, SA_LIFE_DURATION = 2, /* B/V */ GROUP_DESCRIPTION = 3, ENCAPSULATION_MODE = 4, AUTH_ALGORITHM = 5, KEY_LENGTH = 6, KEY_ROUNDS = 7, COMPRESS_DICT_SIZE = 8, COMPRESS_PRIVATE_ALG = 9, /* B/V */ ECN_TUNNEL = 10, /*B*/ /*RFC 3168*/ /* Originally mistakenly grabbed for SECCTX */ ECN_TUNNEL_or_old_SECCTX = ECN_TUNNEL, SECCTX = 32001, /* B/V */ /* chosen from private range as in RFC 2407 */ }; /* * SA Lifetime Type attribute * RFC2407 The Internet IP security Domain of Interpretation for ISAKMP 4.5 * Default time specified in 4.5 * * There are two defaults for IPSEC SA lifetime, SA_LIFE_DURATION_DEFAULT, * and PLUTO_SA_LIFE_DURATION_DEFAULT. * SA_LIFE_DURATION_DEFAULT is specified in RFC2407 "The Internet IP * Security Domain of Interpretation for ISAKMP" 4.5. It applies when * an ISAKMP negotiation does not explicitly specify a life duration. */ #define SA_LIFE_TYPE_SECONDS 1 #define SA_LIFE_TYPE_KBYTES 2 /* Encapsulation Mode attribute */ #define ENCAPSULATION_MODE_UNSPECIFIED 0 /* not legal -- used internally */ #define ENCAPSULATION_MODE_TUNNEL 1 #define ENCAPSULATION_MODE_TRANSPORT 2 #define ENCAPSULATION_MODE_UDP_TUNNEL_RFC 3 #define ENCAPSULATION_MODE_UDP_TRANSPORT_RFC 4 #define ENCAPSULATION_MODE_UDP_TUNNEL_DRAFTS 61443 #define ENCAPSULATION_MODE_UDP_TRANSPORT_DRAFTS 61444 /* Auth Algorithm attribute */ /* https://www.iana.org/assignments/isakmp-registry/isakmp-registry.xml#isakmp-registry-20 */ enum ikev1_auth_attribute { AUTH_ALGORITHM_NONE = 0, /* our private designation */ AUTH_ALGORITHM_HMAC_MD5 = 1, AUTH_ALGORITHM_HMAC_SHA1 = 2, AUTH_ALGORITHM_DES_MAC = 3, AUTH_ALGORITHM_KPDK = 4, AUTH_ALGORITHM_HMAC_SHA2_256 = 5, /* not in an rfc? */ AUTH_ALGORITHM_HMAC_SHA2_384 = 6, /* not in an rfc? */ AUTH_ALGORITHM_HMAC_SHA2_512 = 7, /* not in an rfc? */ AUTH_ALGORITHM_HMAC_RIPEMD = 8, /* RFC 2857 */ AUTH_ALGORITHM_AES_XCBC = 9, /* RFC 3566 */ AUTH_ALGORITHM_SIG_RSA = 10, /* RFC 4359 */ AUTH_ALGORITHM_AES_128_GMAC = 11, /* RFC 4542 */ AUTH_ALGORITHM_AES_192_GMAC = 12, /* RFC 4542 */ AUTH_ALGORITHM_AES_256_GMAC = 13, /* RFC 4542 */ AUTH_ALGORITHM_PSTATS_ROOF, /* 14-61439 Unassigned */ /* 61440-65535 Reserved for private use */ AUTH_ALGORITHM_AES_CMAC_96 = 250, /* IKEv2==8 */ AUTH_ALGORITHM_NULL_KAME = 251, /* why do we load this ? */ AUTH_ALGORITHM_HMAC_SHA2_256_TRUNCBUG = 252, }; typedef uint16_t ipsec_auth_t; /* * Oakley Lifetime Type attribute * draft-ietf-ipsec-ike-01.txt appendix A * As far as I can see, there is no specification for * OAKLEY_ISAKMP_SA_LIFETIME_DEFAULT. This could lead to interop problems! * For no particular reason, we chose one hour. * The value of OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM is our local policy. */ #define OAKLEY_LIFE_SECONDS 1 #define OAKLEY_LIFE_KILOBYTES 2 /* * Oakley PRF attribute (none defined) * draft-ietf-ipsec-ike-01.txt appendix A */ /* * HMAC * - see RFC 2104 for the definition of the HMAC procedure for early hash algorithms * - see RFC 4868 for how to construct HMAC for SHA2 functions */ #define HMAC_IPAD 0x36 #define HMAC_OPAD 0x5C /* * Largest HMAC hash function blocksize ("B" in RFC 2104). * * Needs to be a compile-time constant for array allocation. * Must be as large as the largest value that appears in a * struct hash_desc's hash_block_size field. */ #define MAX_HMAC_BLOCKSIZE 128 /* RFC 4868 specifies this for SHA512 */ /* * IKEv1 Oakley Encryption Algorithm attribute * https://www.iana.org/assignments/ipsec-registry/ipsec-registry.xhtml#ipsec-registry-4 */ enum ikev1_encr_attribute { OAKLEY_DES_CBC = 1, OAKLEY_IDEA_CBC = 2, OAKLEY_BLOWFISH_CBC = 3, OAKLEY_RC5_R16_B64_CBC = 4, OAKLEY_3DES_CBC = 5, OAKLEY_CAST_CBC = 6, OAKLEY_AES_CBC = 7, OAKLEY_CAMELLIA_CBC = 8, /* remainder until private use are NOT official IKEv1 entries */ OAKLEY_AES_CTR = 13, /* taken from IKEv2 */ OAKLEY_AES_CCM_8 = 14, OAKLEY_AES_CCM_12 = 15, OAKLEY_AES_CCM_16 = 16, OAKLEY_AES_GCM_8 = 18, OAKLEY_AES_GCM_12 = 19, OAKLEY_AES_GCM_16 = 20, OAKLEY_CAMELLIA_CTR = 24, OAKLEY_CAMELLIA_CCM_A = 25, OAKLEY_CAMELLIA_CCM_B = 26, OAKLEY_CAMELLIA_CCM_C = 27, OAKLEY_ENCR_PSTATS_ROOF, /* private user numbers */ OAKLEY_MARS_CBC = 65001, OAKLEY_RC6_CBC = 65002, OAKLEY_ID_65003 = 65003, /* unused - make enums easier */ OAKLEY_SERPENT_CBC = 65004, OAKLEY_TWOFISH_CBC = 65005, OAKLEY_TWOFISH_CBC_SSH = 65289, }; #define OAKLEY_ENCRYPT_MAX 65535 /* pretty useless :) */ /* * IKEv1 Oakley Hash Algorithm attribute * https://www.iana.org/assignments/ipsec-registry/ipsec-registry.xhtml#ipsec-registry-6 */ typedef uint16_t oakley_hash_t; enum ikev1_hash_attribute { /* 0 reserved */ OAKLEY_MD5 = 1, OAKLEY_SHA1 = 2, OAKLEY_TIGER = 3, OAKLEY_SHA2_256 = 4, OAKLEY_SHA2_384 = 5, OAKLEY_SHA2_512 = 6, OAKLEY_HASH_PSTATS_ROOF, }; #define OAKLEY_HASH_MAX 9 /* * Oakley Authentication Method attribute * IANA: https://www.iana.org/assignments/ipsec-registry/ipsec-registry.xhtml#ipsec-registry-8 * XAUTH: https://tools.ietf.org/html/draft-ietf-ipsec-isakmp-xauth-06 * Hybrid: https://tools.ietf.org/html/draft-ietf-ipsec-isakmp-hybrid-auth-05 */ enum ikev1_auth_method { OAKLEY_PRESHARED_KEY = 1, OAKLEY_DSS_SIG = 2, OAKLEY_RSA_SIG = 3, OAKLEY_RSA_ENC = 4, OAKLEY_AUTH_ROOF, OAKLEY_AUTH_PSTATS_ROOF = OAKLEY_AUTH_ROOF, /* we only support methods above */ OAKLEY_RSA_REVISED_MODE = 5, /* Not implemented */ /* 6 - 8 Reserved */ OAKLEY_ECDSA_P256 = 9, /* RFC 4754 */ OAKLEY_ECDSA_P384 = 10, /* RFC 4754 */ OAKLEY_ECDSA_P521 = 11, /* RFC 4754 */ /* 12 - 65000 Unassigned */ OAKLEY_AUTH_NULL = 13, /* draft-ietf-ipsecme-ikev2-null-auth */ /* * Note: the below xauth names are mapped via xauth_calcbaseauth() * to the base functions 1-4 */ HybridInitRSA = 64221, HybridRespRSA = 64222, HybridInitDSS = 64223, HybridRespDSS = 64224, /* For XAUTH. Don't actually store in st->st_oakley.auth (???) */ XAUTHInitPreShared = 65001, XAUTHRespPreShared = 65002, XAUTHInitDSS = 65003, XAUTHRespDSS = 65004, XAUTHInitRSA = 65005, XAUTHRespRSA = 65006, XAUTHInitRSAEncryption = 65007, XAUTHRespRSAEncryption = 65008, XAUTHInitRSARevisedEncryption = 65009, XAUTHRespRSARevisedEncryption = 65010, }; /* typedef to make our life easier */ typedef uint16_t oakley_auth_t; enum ikev2_cp_attribute_type { /* * IKEv2 CP Attribute types * https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xhtml#ikev2-parameters-21 */ IKEv2_CP_ATTR_RESERVED = 0, IKEv2_INTERNAL_IP4_ADDRESS = 1, IKEv2_INTERNAL_IP4_NETMASK = 2, IKEv2_INTERNAL_IP4_DNS = 3, IKEv2_INTERNAL_IP4_NBNS = 4 /* unused by us, WINS is long dead */, IKEv2_RESERVED_5 = 5, IKEv2_INTERNAL_IP4_DHCP = 6, IKEv2_APPLICATION_VERSION = 7, IKEv2_INTERNAL_IP6_ADDRESS = 8, IKEv2_RESERVED_9 = 9, IKEv2_INTERNAL_IP6_DNS = 10, IKEv2_RESERVED_11 = 11, IKEv2_INTERNAL_IP6_DHCP =12, IKEv2_INTERNAL_IP4_SUBNET = 13, IKEv2_SUPPORTED_ATTRIBUTES = 14, IKEv2_INTERNAL_IP6_SUBNET = 15, IKEv2_MIP6_HOME_PREFIX = 16, IKEv2_INTERNAL_IP6_LINK = 17, IKEv2_INTERNAL_IP6_PREFIX = 18, IKEv2_HOME_AGENT_ADDRESS = 19, IKEv2_P_CSCF_IP4_ADDRESS = 20, IKEv2_P_CSCF_IP6_ADDRESS = 21, IKEv2_FTT_KAT = 22, IKEv2_EXTERNAL_SOURCE_IP4_NAT_INFO = 23, IKEv2_TIMEOUT_PERIOD_FOR_LIVENESS_CHECK = 24, IKEv2_INTERNAL_DNS_DOMAIN = 25, IKEv2_INTERNAL_DNSSEC_TA = 26 }; /* extern enum_names ikev2_cp_names; */ enum ikev2_cp_type { IKEv2_CP_CFG_REQUEST = 1, IKEv2_CP_CFG_REPLY = 2, IKEv2_CP_CFG_SET = 3, IKEv2_CP_CFG_ACK = 4 }; /* * extern enum_names ikev2_auth_names; * https://www.iana.nl/assignments/ikev2-parameters/ikev2-parameters.xhtml * IKEv2 Authentication Method */ enum ikev2_auth_method { IKEv2_AUTH_RESERVED = 0, IKEv2_AUTH_RSA = 1, IKEv2_AUTH_PSK = 2, IKEv2_AUTH_DSA = 3, /* 4 - 8 unassigned */ IKEv2_AUTH_P256 = 9, /* RFC 4754 */ IKEv2_AUTH_P384 = 10, /* RFC 4754 */ IKEv2_AUTH_P521 = 11, /* RFC 4754 */ IKEv2_AUTH_GSPM = 12, /* RFC 6467 */ IKEv2_AUTH_NULL = 13, /* draft-ietf-ipsecme-ikev2-null-auth */ IKEv2_AUTH_DIGSIG = 14, /* RFC 7427 */ /* 15 - 200 unassigned */ /* 201 - 255 private use */ }; /* * Oakley Group Description attribute * draft-ietf-ipsec-ike-01.txt appendix A */ typedef enum ike_trans_type_dh oakley_group_t; /* you must also touch: constants.c, crypto.c */ /* https://www.iana.org/assignments/ipsec-registry/ipsec-registry.xhtml#ipsec-registry-10 */ /* https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xhtml#ikev2-parameters-8 */ enum ike_trans_type_dh { OAKLEY_GROUP_NONE = 0, /* RFC 7296 */ OAKLEY_GROUP_MODP768 = 1, OAKLEY_GROUP_MODP1024 = 2, OAKLEY_GROUP_GP155 = 3, /* IKEv2 reserved */ OAKLEY_GROUP_GP185 = 4, /* IKEv2 reserved */ OAKLEY_GROUP_MODP1536 = 5, /* RFC 3526 */ OAKLEY_GROUP_EC2N_2_1 = 6, /* draft-ietf-ipsec-ike-ecc-groups - IKEv2 reserved */ OAKLEY_GROUP_EC2N_2_2 = 7, /* draft-ietf-ipsec-ike-ecc-groups - IKEv2 reserved */ OAKLEY_GROUP_EC2N_2_3 = 8, /* draft-ietf-ipsec-ike-ecc-groups - IKEv2 reserved */ OAKLEY_GROUP_EC2N_2_4 = 9, /* draft-ietf-ipsec-ike-ecc-groups - IKEv2 reserved */ OAKLEY_GROUP_EC2N_2_5 = 10, /* draft-ietf-ipsec-ike-ecc-groups - IKEv2 reserved */ OAKLEY_GROUP_EC2N_2_6 = 11, /* draft-ietf-ipsec-ike-ecc-groups - IKEv2 reserved */ OAKLEY_GROUP_EC2N_2_7 = 12, /* draft-ietf-ipsec-ike-ecc-groups - IKEv2 reserved */ OAKLEY_GROUP_EC2N_2_8 = 13, /* draft-ietf-ipsec-ike-ecc-groups - IKEv2 reserved */ OAKLEY_GROUP_MODP2048 = 14, /* RFC 3526 */ OAKLEY_GROUP_MODP3072 = 15, /* RFC 3526 */ OAKLEY_GROUP_MODP4096 = 16, /* RFC 3526 */ OAKLEY_GROUP_MODP6144 = 17, /* RFC 3526 */ OAKLEY_GROUP_MODP8192 = 18, /* RFC 3526 */ OAKLEY_GROUP_ECP_256 = 19, /* RFC 5903 */ OAKLEY_GROUP_ECP_384 = 20, /* RFC 5903 */ OAKLEY_GROUP_ECP_521 = 21, /* RFC 5903 */ OAKLEY_GROUP_DH22 = 22, /* RFC 5114 */ OAKLEY_GROUP_DH23 = 23, /* RFC 5114 */ OAKLEY_GROUP_DH24 = 24, /* RFC 5114 */ OAKLEY_GROUP_ECP_192 = 25, /* RFC 5114 */ OAKLEY_GROUP_ECP_224 = 26, /* RFC 5114 */ /* From here on, values are only valid for IKEv2 */ OAKLEY_GROUP_BRAINPOOL_P224R1 = 27, /* RFC 6932 */ OAKLEY_GROUP_BRAINPOOL_P256R1 = 28, /* RFC 6932 */ OAKLEY_GROUP_BRAINPOOL_P384R1 = 29, /* RFC 6932 */ OAKLEY_GROUP_BRAINPOOL_P512R1 = 30, /* RFC 6932 */ OAKLEY_GROUP_CURVE25519 = 31, /* RFC-ietf-ipsecme-safecurves-05 */ OAKLEY_GROUP_CURVE448 = 32, /* RFC-ietf-ipsecme-safecurves-05 */ OAKLEY_GROUP_PSTATS_ROOF /* 33 - 32767 Unassigned */ /* 32768 - 65535 Reserved for private use */ }; /* * Oakley Group Type attribute * draft-ietf-ipsec-ike-01.txt appendix A */ #define OAKLEY_GROUP_TYPE_MODP 1 #define OAKLEY_GROUP_TYPE_ECP 2 #define OAKLEY_GROUP_TYPE_EC2N 3 /* * Notify messages -- error types * See RFC2408 ISAKMP 3.14.1 */ /* * IKEv1 RFC2408 https://www.iana.org/assignments/ipsec-registry * extern enum_names notification_names; * extern enum_names ipsec_notification_names; */ typedef enum { NOTHING_WRONG = 0, /* Unofficial! Must be zero to match default C initial value. */ INVALID_PAYLOAD_TYPE = 1, DOI_NOT_SUPPORTED = 2, SITUATION_NOT_SUPPORTED = 3, INVALID_COOKIE = 4, INVALID_MAJOR_VERSION = 5, INVALID_MINOR_VERSION = 6, INVALID_EXCHANGE_TYPE = 7, INVALID_FLAGS = 8, INVALID_MESSAGE_ID = 9, INVALID_PROTOCOL_ID = 10, INVALID_SPI = 11, INVALID_TRANSFORM_ID = 12, ATTRIBUTES_NOT_SUPPORTED = 13, NO_PROPOSAL_CHOSEN = 14, BAD_PROPOSAL_SYNTAX = 15, PAYLOAD_MALFORMED = 16, INVALID_KEY_INFORMATION = 17, INVALID_ID_INFORMATION = 18, INVALID_CERT_ENCODING = 19, INVALID_CERTIFICATE = 20, CERT_TYPE_UNSUPPORTED = 21, INVALID_CERT_AUTHORITY = 22, INVALID_HASH_INFORMATION = 23, AUTHENTICATION_FAILED = 24, INVALID_SIGNATURE = 25, ADDRESS_NOTIFICATION = 26, NOTIFY_SA_LIFETIME = 27, CERTIFICATE_UNAVAILABLE = 28, UNSUPPORTED_EXCHANGE_TYPE = 29, UNEQUAL_PAYLOAD_LENGTHS = 30, v1N_ERROR_PSTATS_ROOF, /* used to cap statistics array */ /* 31-8191 RESERVED (Future Use) */ /* * Sub-Registry: Notify Messages - Status Types (16384-24575) */ CONNECTED = 16384, /* INITIAL_CONTACT */ /* * IPSEC DOI additions; status types (RFC2407 IPSEC DOI 4.6.3) * These must be sent under the protection of an ISAKMP SA. */ IPSEC_RESPONDER_LIFETIME = 24576, IPSEC_REPLAY_STATUS = 24577, IPSEC_INITIAL_CONTACT = 24578, /* Cisco specific messages */ ISAKMP_N_CISCO_HELLO = 30000, ISAKMP_N_CISCO_WWTEBR = 30001, ISAKMP_N_CISCO_SHUT_UP = 30002, ISAKMP_N_IOS_KEEP_ALIVE_REQ = 32768, ISAKMP_N_IOS_KEEP_ALIVE_ACK = 32769, ISAKMP_N_CISCO_LOAD_BALANCE = 40501, ISAKMP_N_CISCO_UNKNOWN_40502 = 40502, ISAKMP_N_CISCO_PRESHARED_KEY_HASH = 40503, /* RFC 3706 DPD */ R_U_THERE = 36136, R_U_THERE_ACK = 36137, /* * Netscreen / Juniper private use - notification contains * internal ip */ NETSCREEN_NHTB_INFORM = 40001, } notification_t; /* * https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xml#ikev2-parameters-13 * IKEv2 is very similar, but different. Let's not re-use and confuse **/ typedef enum { /* IKEv2 */ /* 0-8191 Reserved, ExpertReview */ v2N_NOTHING_WRONG = 0, /* Unofficial! Must be zero to match default C initial value. */ /* * Error notifications. */ v2N_ERROR_FLOOR = 1, v2N_UNSUPPORTED_CRITICAL_PAYLOAD = 1, /* Reserved = 2, */ /* Reserved = 3, */ v2N_INVALID_IKE_SPI = 4, v2N_INVALID_MAJOR_VERSION = 5, /* same as ikev1 */ /* Reserved = 6, */ v2N_INVALID_SYNTAX = 7, /* Reserved = 8, */ v2N_INVALID_MESSAGE_ID = 9, /* same as ikev1 */ /* Reserved = 10, */ v2N_INVALID_SPI = 11, /* same as ikev1 */ /* Reserved = 12, */ /* Reserved = 13, */ v2N_NO_PROPOSAL_CHOSEN = 14, /* same as ikev1 */ /* Reserved = 15, */ /* Reserved = 16, */ v2N_INVALID_KE_PAYLOAD = 17, /* Reserved = 18 to 23, */ v2N_AUTHENTICATION_FAILED = 24, /* same as ikev1 */ /* Reserved = 25 to 33, */ v2N_SINGLE_PAIR_REQUIRED = 34, v2N_NO_ADDITIONAL_SAS = 35, v2N_INTERNAL_ADDRESS_FAILURE = 36, v2N_FAILED_CP_REQUIRED = 37, v2N_TS_UNACCEPTABLE = 38, v2N_INVALID_SELECTORS = 39, v2N_UNACCEPTABLE_ADDRESSES = 40, v2N_UNEXPECTED_NAT_DETECTED = 41, v2N_USE_ASSIGNED_HoA = 42, /* RFC 5026 */ v2N_TEMPORARY_FAILURE = 43, /* RFC 7296 */ v2N_CHILD_SA_NOT_FOUND = 44, /* RFC 7296 */ v2N_INVALID_GROUP_ID = 45, /* draft-yeung-g-ikev2 */ v2N_AUTHORIZATION_FAILED = 46, /* draft-yeung-g-ikev2 */ v2N_ERROR_PSTATS_ROOF, /* used to cap error statistics array */ /* * Status notifications. */ v2N_STATUS_FLOOR = 16384, /* old IKEv1 entries - might be in private use for IKEv2N */ v2N_INITIAL_CONTACT = 16384, v2N_SET_WINDOW_SIZE = 16385, v2N_ADDITIONAL_TS_POSSIBLE = 16386, v2N_IPCOMP_SUPPORTED = 16387, v2N_NAT_DETECTION_SOURCE_IP = 16388, v2N_NAT_DETECTION_DESTINATION_IP = 16389, v2N_COOKIE = 16390, v2N_USE_TRANSPORT_MODE = 16391, v2N_HTTP_CERT_LOOKUP_SUPPORTED = 16392, v2N_REKEY_SA = 16393, v2N_ESP_TFC_PADDING_NOT_SUPPORTED = 16394, v2N_NON_FIRST_FRAGMENTS_ALSO = 16395, /* IKEv2N extensions */ v2N_MOBIKE_SUPPORTED = 16396, /* RFC-4555 */ v2N_ADDITIONAL_IP4_ADDRESS = 16397, /* RFC-4555 */ v2N_ADDITIONAL_IP6_ADDRESS = 16398, /* RFC-4555 */ v2N_NO_ADDITIONAL_ADDRESSES = 16399, /* RFC-4555 */ v2N_UPDATE_SA_ADDRESSES = 16400, /* RFC-4555 */ v2N_COOKIE2 = 16401, /* RFC-4555 */ v2N_NO_NATS_ALLOWED = 16402, /* RFC-4555 */ v2N_AUTH_LIFETIME = 16403, /* RFC-4478 */ v2N_MULTIPLE_AUTH_SUPPORTED = 16404, /* RFC-4739 */ v2N_ANOTHER_AUTH_FOLLOWS = 16405, /* RFC-4739 */ v2N_REDIRECT_SUPPORTED = 16406, /* RFC-5685 */ v2N_REDIRECT = 16407, /* RFC-5685 */ v2N_REDIRECTED_FROM = 16408, /* RFC-5685 */ v2N_TICKET_LT_OPAQUE = 16409, /* RFC-5723 */ v2N_TICKET_REQUEST = 16410, /* RFC-5723 */ v2N_TICKET_ACK = 16411, /* RFC-5723 */ v2N_TICKET_NACK = 16412, /* RFC-5723 */ v2N_TICKET_OPAQUE = 16413, /* RFC-5723 */ v2N_LINK_ID = 16414, /* RFC-5739 */ v2N_USE_WESP_MODE = 16415, /* RFC-5840 */ v2N_ROHC_SUPPORTED = 16416, /* RFC-5857 */ v2N_EAP_ONLY_AUTHENTICATION = 16417, /* RFC-5998 */ v2N_CHILDLESS_IKEV2_SUPPORTED = 16418, /* RFC-6023 */ v2N_QUICK_CRASH_DETECTION = 16419, /* RFC-6290 */ v2N_IKEV2_MESSAGE_ID_SYNC_SUPPORTED = 16420, /* RFC-6311 */ v2N_IPSEC_REPLAY_COUNTER_SYNC_SUPPORTED = 16421, /* RFC-6311 */ v2N_IKEV2_MESSAGE_ID_SYNC = 16422, /* RFC-6311 */ v2N_IPSEC_REPLAY_COUNTER_SYNC = 16423, /* RFC-6311 */ v2N_SECURE_PASSWORD_METHODS = 16424, /* RFC-6467 */ v2N_PSK_PERSIST = 16425, /* RFC-6631 */ v2N_PSK_CONFIRM = 16426, /* RFC-6631 */ v2N_ERX_SUPPORTED = 16427, /* RFC-6867 */ v2N_IFOM_CAPABILITY = 16428, /* 3GPP TS 24.303 v10.6.0 annex B.2 */ v2N_SENDER_REQUEST_ID = 16429, /* draft-yeung-g-ikev2 */ v2N_IKEV2_FRAGMENTATION_SUPPORTED = 16430, /* RFC-7383 */ v2N_SIGNATURE_HASH_ALGORITHMS = 16431, /* RFC-7427 */ v2N_CLONE_IKE_SA_SUPPORTED = 16432, /* RFC-7791 */ v2N_CLONE_IKE_SA = 16433, /* RFC-7791 */ v2N_PUZZLE = 16434, /* RFC-8019 */ v2N_USE_PPK = 16435, /* draft-ietf-ipsecme-qr-ikev2 */ v2N_PPK_IDENTITY = 16436, /* draft-ietf-ipsecme-qr-ikev2 */ v2N_NO_PPK_AUTH = 16437, /* draft-ietf-ipsecme-qr-ikev2 */ v2N_STATUS_PSTATS_ROOF, /* used to cap status statistics array */ /* 16438 - 40969 Unassigned */ v2N_NULL_AUTH = 40960, /* 40961 - 65535 Private Use */ } v2_notification_t; /* draft-ietf-ipsecme-qr-ikev2-01 created registry */ enum ppk_id_type { PPK_ID_OPAQUE = 1, PPK_ID_FIXED = 2, /* 3 - 127 Reserved for IANA */ /* 128 - 255 Private Use */ }; /* IKEv2 Redirect Mechanism - RFC 5685 */ enum gw_identity_type { /* 0 - reserved */ GW_IPV4 = 1, GW_IPV6 = 2, GW_FQDN = 3, /* 4 - 240 Unassigned */ /* 241 - 255 Private Use */ }; #define MAX_REDIRECTS 5 #define REDIRECT_LOOP_DETECT_PERIOD 300 /* Public key algorithm number in IPSECKEY DNS RR. See RFC 4025 2.4 */ enum pubkey_alg { PUBKEY_ALG_DSA = 1, PUBKEY_ALG_RSA = 2, PUBKEY_ALG_ECDSA = 3, }; /* * IKEv1 Identification type values * RFC 2407 The Internet IP security Domain of Interpretation for * ISAKMP 4.6.2.1 * https://www.iana.org/assignments/isakmp-registry/isakmp-registry.xhtml#isakmp-registry-31 * * IKEv2 Identification type values * RFC 5996 * https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xhtml#ikev2-parameters-10 */ enum ike_id_type { ID_FROMCERT = -1, /* taken from certificate - private to Pluto */ ID_NONE = 0, /* private to Pluto */ ID_IPV4_ADDR = 1, ID_FQDN = 2, ID_USER_FQDN = 3, ID_RFC822_ADDR = ID_USER_FQDN, /* alias */ ID_IPV4_ADDR_SUBNET = 4, /* XXX IKEv1 only but we use it */ ID_IPV6_ADDR = 5, ID_IPV6_ADDR_SUBNET = 6, /* XXX IKEv1 only but we use it */ ID_IPV4_ADDR_RANGE = 7, /* XXX IKEv1 only but we use it */ ID_IPV6_ADDR_RANGE = 8, /* XXX IKEv1 only but we use it */ ID_DER_ASN1_DN = 9, ID_DER_ASN1_GN = 10, ID_KEY_ID = 11, ID_FC_NAME = 12, /* RFC 4595 */ ID_NULL = 13, /* RFC 7619 */ /* In IKEv1 registry, non-IKE value ID_LIST = 12 as per RFC 3554 */ /* 14-248 Unassigned */ /* 249-255 Reserved for private use */ }; /* * Certificate type values * RFC 2408 ISAKMP, chapter 3.9 * https://tools.ietf.org/html/rfc2408#section-3.9 * (no corresponding IANA registry?) * * IKEv2 Certificate Encodings * https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xhtml#ikev2-parameters-11 */ enum ike_cert_type { CERT_NONE = 0, /* (non-RFC) none, or guess from file contents */ CERT_PKCS7_WRAPPED_X509 = 1, /* self-signed certificate from disk */ CERT_PGP = 2, CERT_DNS_SIGNED_KEY = 3, /* KEY RR from DNS */ CERT_X509_SIGNATURE = 4, CERT_X509_KEY_EXCHANGE = 5, /* v1 only */ CERT_KERBEROS_TOKENS = 6, CERT_CRL = 7, CERT_ARL = 8, CERT_SPKI = 9, CERT_X509_ATTRIBUTE = 10, /* IKEv2 only from here */ CERT_RAW_RSA = 11, /* raw RSA from config file */ CERT_X509_CERT_URL = 12, CERT_X509_BUNDLE_URL = 13, CERT_OCSP_CONTENT = 14, /* RFC 4806 */ CERT_RAW_PUBLIC_KEY = 15, /* RFC 7670 */ /* 16 - 200 Unassigned */ /* 201 - 255 Private use */ }; /* * (IKEv1) IPsec AH transform values * * IKEv1: https://www.iana.org/assignments/isakmp-registry/isakmp-registry.xhtml#isakmp-registry-7 * IKEv2: https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xhtml#ikev2-parameters-7 * * IKEv1 and IKEv2 versions are very different :( * See: ikev2_trans_type_integ */ enum ipsec_authentication_algo { AH_NONE = 0, /* Internal use - IKEv1 is reserved */ /* 1 IKEv1 RESERVED, IKEv2 AUTH_HMAC_MD5_96 */ AH_MD5 = 2, /* IKEv2 AUTH_HMAC_SHA1_96 */ AH_SHA = 3, /* IKEv2 AUTH_DES_MAC */ AH_DES = 4, /* IKEv2 AUTH_KPDK_MD5 */ AH_SHA2_256 = 5, /* IKEv2 AUTH_AES_XCBC_96 */ AH_SHA2_384 = 6, /* IKEv2 AUTH_HMAC_MD5_128 */ AH_SHA2_512 = 7, /* IKEv2 AUTH_HMAC_SHA1_160 */ AH_RIPEMD = 8, /* IKEv2 AUTH_AES_CMAC_96 */ AH_AES_XCBC_MAC = 9, /* IKEv2 AUTH_AES_128_GMAC */ AH_RSA = 10, /* IKEv2 AUTH_AES_192_GMAC */ AH_AES_128_GMAC = 11, /* IKEv2 AUTH_AES_256_GMAC */ AH_AES_192_GMAC = 12, /* IKEv2 AUTH_HMAC_SHA2_256_128 */ AH_AES_256_GMAC = 13, /* IKEv2 AUTH_HMAC_SHA2_384_192 */ AH_PSTATS_ROOF, /* 14 IKEv1 unassigned, IKEv2 AUTH_HMAC_SHA2_512_256 */ /* IKEv1 14-248 Unassigned */ /* IKEv1 249 - 255 Reserved for private use */ /* IKEv2 15-1023 Unassigned */ /* IKEv2 1024 - 65535 Reserved for private use */ AH_AES_CMAC_96 = 250, /* IKEv2=8 */ AH_NULL = 251, /* comes from kame? */ AH_SHA2_256_TRUNCBUG = 252, /* our own stolen value */ }; /* * IKEv1 IPsec ESP transform values * IKEv1: https://www.iana.org/assignments/isakmp-registry/isakmp-registry.xhtml#isakmp-registry-9 * IKEv2: https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xhtml#ikev2-parameters-5 * * Up to id=20 IKEv1 and IKEv2 match, after that things get messy. * This is because pluto and the kernel keep trying to use the IKEv1 * ESP value when dealing with IKEv2-only algorithms. * * Where there is a conflict between IKEv1 and IKEv2, the IKEv1 value * is included. If there's no IKEv1 value then the IKEv2 value is * used (should these be dropped). */ enum ipsec_cipher_algo { ESP_reserved = 0, ESP_DES_IV64 = 1, ESP_DES = 2, /* obsoleted */ ESP_3DES = 3, ESP_RC5 = 4, ESP_IDEA = 5, ESP_CAST = 6, ESP_BLOWFISH = 7, /* obsoleyed */ ESP_3IDEA = 8, ESP_DES_IV32 = 9, ESP_RC4 = 10, ESP_NULL = 11, ESP_AES = 12, /* CBC 128 bit AES */ ESP_AES_CTR = 13, ESP_AES_CCM_8 = 14, ESP_AES_CCM_12 = 15, ESP_AES_CCM_16 = 16, ESP_ID17 = 17, /* unassigned=17 */ ESP_AES_GCM_8 = 18, ESP_AES_GCM_12 = 19, ESP_AES_GCM_16 = 20, ESP_SEED_CBC = 21, /* IKEv1, IKEv2 is NULL_AUTH_AES_GMAC */ ESP_CAMELLIA = 22, /* IKEv1, IKEv2 is ESP_RESERVED_FOR_IEEE_P1619_XTS_AES */ ESP_NULL_AUTH_AES_GMAC = 23, /* IKEv1, IKEv2 is CAMELLIA_CBC */ ESP_PSTATS_ROOF, ESP_CAMELLIA_CTR = 24, /* not assigned in/for IKEv1 */ ESP_CAMELLIA_CCM_8 = 25, /* not assigned in/for IKEv1 */ ESP_CAMELLIA_CCM_12 = 26, /* not assigned in/for IKEv1 */ ESP_CAMELLIA_CCM_16 = 27, /* not assigned in/for IKEv1 */ /* IKEv1: 24-248 Unassigned */ /* IKEv1: 249-255 reserved for private use */ /* IKEv2: 28-1023 Unassigned */ /* IKEv2: 1024-65535 reserved for private use */ ESP_MARS = 249, ESP_RC6 = 250, ESP_KAME_NULL = 251, /* kame? */ ESP_SERPENT = 252, ESP_TWOFISH = 253, ESP_ID254 = 254, ESP_ID255 = 255, }; /* * IPCOMP transform values are (currently) identical for IKEv1 and IKEv2 * IKEv1: RFC2407 The Internet IP security Domain of Interpretation for ISAKMP 4.4.5 * IKEv2: https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xhtml#ikev2-parameters-17 */ enum ipsec_comp_algo { IPCOMP_NONE=0, IPCOMP_OUI=1, /* unspecified */ IPCOMP_DEFLATE=2, IPCOMP_LZS=3, /* RFC 2395 */ IPCOMP_LZJH=4, /* RFC 3051 */ /* 5-47 Reserved for approved algorithms */ /* 48-63 Reserved for private use */ /* 64-255 Unassigned */ }; /* * RFC 7427 Signature Authentication in the Internet Key Exchange Version 2 (IKEv2) * Section 7: IANA Considerations * https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xhtml#hash-algorithms */ enum notify_payload_hash_algorithms { IKEv2_AUTH_HASH_RESERVED = 0, IKEv2_AUTH_HASH_SHA1 = 1, IKEv2_AUTH_HASH_SHA2_256 = 2, IKEv2_AUTH_HASH_SHA2_384 = 3, IKEv2_AUTH_HASH_SHA2_512 = 4, IKEv2_AUTH_HASH_IDENTITY = 5, /* RFC 4307-bis */ /* 6-1023 Unassigned */ /* 1024-65535 Reserved for private use */ IKEv2_AUTH_HASH_ROOF }; /* * RFC 7427: 4. Hash Algorithm Notification * * The Notification Data field contains the list of 16-bit hash * algorithm identifiers from the Hash Algorithm Identifiers of IANA's * "Internet Key Exchange Version 2 (IKEv2) Parameters" registry. * There is no padding between the hash algorithm identifiers. */ #define RFC_7427_HASH_ALGORITHM_IDENTIFIER_SIZE 2 /* * RFC 7427 , section 3 describes the Authentication data format for * Digital Signatures. * ASN.1 Length (1 octet): length of ASN.1-encoded AlgorithmIdentifier object * Algorithm Identifier (variable length): The AlgorithmIdentifier ASN.1 object. */ /* * Size of algorithm RSASSA-PSS with SHA2 is 67 bytes for all its variants */ #define ASN1_SHA2_RSA_PSS_SIZE 67 /* length of ASN.1 Algorithm Identifier(variable length) is 1 byte */ #define ASN1_LEN_ALGO_IDENTIFIER 1 #define RSA_PSS_SHA256_BLOB \ 0x30, 0x41, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0a, 0x30, 0x34, 0xa0,\ 0x0f, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00,\ 0xa1, 0x1c, 0x30, 0x1a, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x08, 0x30,\ 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0xa2, 0x03,\ 0x02, 0x01, 0x20 #define RSA_PSS_SHA384_BLOB \ 0x30, 0x41, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0A, 0x30, 0x34, 0xA0,\ 0x0F, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00,\ 0xA1, 0x1C, 0x30, 0x1A, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x08, 0x30,\ 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0xA2, 0x03,\ 0x02, 0x01, 0x30 #define RSA_PSS_SHA512_BLOB \ 0x30, 0x41, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0A, 0x30, 0x34, 0xA0,\ 0x0F, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00,\ 0xA1, 0x1C, 0x30, 0x1A, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x08, 0x30,\ 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0xA2, 0x03,\ 0x02, 0x01, 0x40 #define LEN_RSA_PSS_SHA2_BLOB ASN1_SHA2_RSA_PSS_SIZE /* RFC 7427 Appendix A.1 */ #define ASN1_SHA2_RSA_v15_SIZE 16 /* including one length byte prefix */ /* sha256WithRSAEncryption */ #define RSA_v15_SHA256_BLOB \ 0x0f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00 /* sha384WithRSAEncryption */ #define RSA_v15_SHA384_BLOB \ 0x0f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0c, 0x05, 0x00 /* sha512WithRSAEncryption */ #define RSA_v15_SHA512_BLOB \ 0x0f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d, 0x05, 0x00 /* ECDSA */ #define ASN1_SHA1_ECDSA_SIZE 11 #define ASN1_SHA2_ECDSA_SIZE 12 #define ECDSA_SHA1_BLOB \ 0x30, 0x09, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x01 #define ECDSA_SHA256_BLOB \ 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02 #define ECDSA_SHA384_BLOB \ 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03 #define ECDSA_SHA512_BLOB \ 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x04 #define LEN_ECDSA_SHA1_BLOB ASN1_SHA1_ECDSA_SIZE #define LEN_ECDSA_SHA2_BLOB ASN1_SHA2_ECDSA_SIZE /* Limits on size of RSA moduli. * The upper bound matches that of DNSSEC (see RFC 2537). * The lower bound must be more than 11 octets for certain * the encoding to work, but it must be much larger for any * real security. For now, we require 512 bits. */ #define RSA_MIN_OCTETS_RFC 12 #define RSA_MIN_OCTETS BYTES_FOR_BITS(512) #define RSA_MIN_OCTETS_UGH \ "RSA modulus too small for security: less than 512 bits" #define RSA_MAX_OCTETS BYTES_FOR_BITS(8192) #define RSA_MAX_OCTETS_UGH "RSA modulus too large: more than 8192 bits" /* Note: RFC 2537 encoding adds a few bytes. If you use a small * modulus like 3, the overhead is only 2 bytes */ #define RSA_MAX_ENCODING_BYTES (RSA_MAX_OCTETS + 2) #define ISA_MAJ_SHIFT 4 #define ISA_MIN_MASK (~((~0u) << ISA_MAJ_SHIFT)) /* ISAKMP attributes are encoded with the Attribute Format field * and the Attribute Type field encoded in one pair of octets. * The AF is the high-order bit and the Type is the next 15 bits. * See RFC 2408 "ISAKMP" section 3.3. * The following definitions are used to pack and unpack these. */ #define ISAKMP_ATTR_AF_MASK 0x8000 #define ISAKMP_ATTR_AF_TV ISAKMP_ATTR_AF_MASK /* value in lv */ #define ISAKMP_ATTR_AF_TLV 0 /* length in lv; value follows */ #define ISAKMP_ATTR_RTYPE_MASK 0x7FFF #endif /* _IETF_CONSTANTS_H */ libreswan-3.32/include/ike_alg.h000066400000000000000000000601751365625662500166470ustar00rootroot00000000000000/* * Copyright (C) 2019 Andrew Cagney * Copyright (C) 2019 D. Hugh Redelmeier * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef _IKE_ALG_H #define _IKE_ALG_H #include /* for bool */ #include #include #include "shunk.h" #include "ietf_constants.h" struct ike_alg; struct lswlog; enum ike_alg_key; /* * More meaningful passert. * * Do not wrap ASSERTION in parentheses as it will suppress the * warning for 'foo = bar'. */ #define PRI_IKE_ALG "IKE_ALG %s algorithm '%s'" #define pri_ike_alg(ALG) \ ike_alg_type_name((ALG)->algo_type), \ ((ALG)->fqn != NULL ? (ALG)->fqn \ : (ALG)->name != NULL ? (ALG)->name \ : "NULL") #define pexpect_ike_alg(ALG, ASSERTION) \ { \ /* wrapping ASSERTION in parens suppresses -Wparen */ \ bool assertion__ = ASSERTION; /* no paren */ \ if (!assertion__) { \ log_pexpect(HERE, \ PRI_IKE_ALG" fails: " #ASSERTION, \ pri_ike_alg(ALG)); \ } \ } #define pexpect_ike_alg_streq(ALG, LHS, RHS) \ { \ /* wrapping ASSERTION in parens suppresses -Wparen */ \ const char *lhs = LHS; \ const char *rhs = RHS; \ if (lhs == NULL || rhs == NULL || !streq(LHS, RHS)) { \ log_pexpect(HERE, \ PRI_IKE_ALG" fails: %s != %s (%s != %s)", \ pri_ike_alg(ALG), \ lhs, rhs, #LHS, #RHS); \ } \ } #define pexpect_ike_alg_strcaseeq(ALG, LHS, RHS) \ { \ /* wrapping ASSERTION in parens suppresses -Wparen */ \ const char *lhs = LHS; \ const char *rhs = RHS; \ if (lhs == NULL || rhs == NULL || !strcaseeq(LHS, RHS)) { \ log_pexpect(HERE, \ PRI_IKE_ALG" fails: %s != %s (%s != %s)", \ pri_ike_alg(ALG), \ ike_alg_type_name((ALG)->algo_type), \ (ALG)->fqn, lhs, rhs, #RHS, #LHS); \ } \ } /* * Different algorithm classes used by IKEv1/IKEv2 protocols. */ struct ike_alg_type; extern const struct ike_alg_type ike_alg_encrypt; extern const struct ike_alg_type ike_alg_hash; extern const struct ike_alg_type ike_alg_prf; extern const struct ike_alg_type ike_alg_integ; extern const struct ike_alg_type ike_alg_dh; /* keep old code working */ #define IKE_ALG_ENCRYPT &ike_alg_encrypt #define IKE_ALG_HASH &ike_alg_hash #define IKE_ALG_PRF &ike_alg_prf #define IKE_ALG_INTEG &ike_alg_integ #define IKE_ALG_DH &ike_alg_dh /* * User frendly string representing the algorithm type (family). * "...Name()" returns the capitalized name. */ const char *ike_alg_type_name(const struct ike_alg_type *type); const char *ike_alg_type_Name(const struct ike_alg_type *type); /* * Different lookup KEYs used by IKEv1/IKEv2 */ enum ike_alg_key { IKEv1_OAKLEY_ID, IKEv1_ESP_ID, IKEv2_ALG_ID, IKE_ALG_KEY_ROOF, IKE_ALG_KEY_FLOOR = IKEv1_OAKLEY_ID }; /* * User friendly string representing the key (protocol family). */ const char *ike_alg_key_name(enum ike_alg_key key); /* * Look for NAME within TYPE algorithms. * * The first version uses the "ike_alg" tables only. * * The second variant uses the ietf_constant.h enum tables and is only * intended as a way to identify algorithms defined by IETF but not * supported here. */ const struct ike_alg *ike_alg_byname(const struct ike_alg_type *type, shunk_t name); int ike_alg_enum_match(const struct ike_alg_type *type, enum ike_alg_key key, shunk_t name); /* * Common prefix for struct encrypt_desc and struct hash_desc (struct * prf_desc and struct integ_desc). * * These tables use the following numeric indexes: * * TYPE ENUM ENUM->STRING PREFIX * * * id[IKEv2_ALG_ID]: * * Used by: IKEv2 IKE, IKEv2 ESP, IKEv2 AH, IKEv2 DH * * Almost no confusion. While IKEv2 DH uses the the IKEv1 * OAKLEY_GROUP enum, there are no conflicts so things work. * * ENCRYPT: ikev2_trans_type_encr ikev2_trans_type_encr_names IKEv2_ENCR * PRF: ikev2_trans_type_prf ikev2_trans_type_prf_names IKEv2_AUTH * INTEG: ikev2_trans_type_integ ikev2_trans_type_integ_names IKEv2_INTEG * DH: ike_trans_type_dh oakley_group_name OAKLEY * * * id[IKEv1_OAKLEY_ID]: * * Used by: IKEv1 IKE a.k.a. phase 1 * * The only querk here is the use of the HASH (PRF) to select INTEG. * The suffix "oakley_id", rather than "ike_id" or "id", is used since * it is consistent with the enum values this field contains * (apparently IKEv1 IKE (phase 1) is based on the OAKLEY protocol). * See ealg_getbyname_ike() and aalg_getbyname_ike(). * * ENCRYPT: ikev1_encr_attribute oakley_enc_names OAKLEY * PRF: ikev1_hash_attribute oakley_hash_names OAKLEY * INTEG: ikev1_hash_attribute oakley_hash_names OAKLEY * DH: ike_trans_type_dh oakley_group_name OAKLEY * * * id[IKEv1_ESP_ID]: * * Used by: ESP and AH; struct esp_info.transid; struct esp_info.auth: * * Here be trouble. While the obvious problem is that struct esp_info * is using both IKEv1 (INTEG) and IPSEC (ENCRYPT) enum types, that is * of no real importance. The real issue here is with INTEG where * things have badly convoluted IKEv1 and IKEv2 ESP numbers and names. * For instance, while the enum ipsec_cipher_algo contained * ESP_CAMELLIA=23 (IKEv2), the name table esp_transformid_names * returns 22 (IKEv1) for the string "ESP_CAMELLIA" (the camellia case * is fixed, others remain). See ealg_getbyname_esp() and * aalg_getbyname_esp(). * * ENCRYPT: ipsec_cipher_algo esp_transformid_names ESP * INTEG: ikev1_auth_attribute auth_alg_names AUTH_ALGORITHM * * * (not yet if ever) ikev[12]_ipsec_id: * * While these values started out being consistent with IKEv1 and (I * suspect) SADB/KLIPS, the've gone off the rails. Over time they've * picked up IKEv2 values making for general confusion. Worse, as * noted above, CAMELLIA had the IKEv2 value 23 (IKEv1 is 22) * resulting in code never being sure of which it is dealing with. * * These values are not included in this table. * * ENCRYPT: ipsec_cipher_algo esp_transformid_names ESP * INTEG: ipsec_authentication_algo ah_transformid_names AH * * * id[IKE_ALG_SADB_ID] aka SADB/PFKEY (never?): * * See: https://tools.ietf.org/html/rfc2367#page-12 * * These values are used when interacting with the SADB/PFKEY kernel * interface. Any symbol named SADB_X_... indicates something local, * either to this OS or this system. * * ENCRYPT: (1) (2) SADB[_X]_AALG_ * INTEG: (3) (4) SADB[_X]_EALG_ * * (1) The linux centric header libreswan/pfkeyv2 tries to define the * enum sadb_ealg with the names K_SADB[_X]_AALG_... but the code * is broken - it doesn't accomodate missing algorithms (more * generally, the header defines all sorts of stuff that conflicts * with ) * * (2) Legacy broken code tries to use esp_transformid_names when * printing the encryption algorithm's name * * (3) The linux centric header libreswan/pfkeyv2 tries to define the * enum sadb_aalg with the names K_SADB[_X]_AALG_ but the code is * broken - it doesn't handle missing algorithms and (more * generally, the header defines all sorts of stuff that conflicts * with ) * * (4) Legacy code tries to map the integrity value onto * ikev1_auth_attribute and then use auth_alg_names to print the * name * * * (not yet if ever) XFRM names: * * The XFRM interface uses strings to identify algorithms. * * It might be useful to add these names to the table. * * Notes: * * For ESP/AH, since the PRF is not negotiated (the IKE SA's PRF is * used) the field "PRF.id[IKEv1_ESP_ID]" should be left blank. * Since, for IKEv2, "PRF.id[IKEv2_ALG_ID]" is used by IKE, it should * be defined. * * XXX: Still missing is a name/alias lookup letting some of alg_info * be eliminated. */ struct ike_alg { /* * Name to print when logging. FQN = fully-qualified-name. */ const char *name; const char *fqn; /* * String containing a comma separated list of all names that * might be used to specify this algorithm. * * Must include NAME (above), FQN, and the enum_names table * name. * * Easier to just require that this contain everything then * poke around in multiple places. * * If this compact string is ever found to be a performance * bottleneck (unlikely as it is only searched during a * connection load and our problem is DH and signing), then it * can be parsed once and turned into a lookup table. */ const char *names; /* * See above. * * Macros provide short term aliases for the slightly longer * index references (tacky, unixish, and delay churning the * code). * * -1 indicates not valid (annoyingly 0 is used by IKEv2 for * NULL integrity). */ const struct ike_alg_type *algo_type; #define ikev1_oakley_id id[IKEv1_OAKLEY_ID] #define ikev1_esp_id id[IKEv1_ESP_ID] #define ikev2_alg_id id[IKEv2_ALG_ID] int id[IKE_ALG_KEY_ROOF]; /* * Is this algorithm FIPS approved (i.e., can be enabled in * FIPS mode)? */ const bool fips; }; struct encrypt_desc { struct ike_alg common; /* MUST BE FIRST */ /* * The block size of the encryption algorithm in bytes. */ const size_t enc_blocksize; /* * Does this algorithm require padding to the above * ENC_BLOCKSIZE bytes? * * This shouldn't be confused with the need to pad payloads to * 4-bytes (ESP) or not at all (IKE). */ const bool pad_to_blocksize; /* * For stream and AEAD ciphers, bytes in addition to the KEY, * that need to be extracted from initial shared-secret * (PRF+). It is concatenated to other material to form an * ENC_BLOCKSIZE sized "starting variable". * * Note: the term "starting variable" comes from Wikipedia. * The more common term Initialization Vector (IV) has * conflicting definitions - the RFCs seem to use it to * describe the chunk of starting variable sent over the wire. * Another common term is "counter block". * * For CTR mode this is called the "nuance value in the * counter block" (AES-CTR - RFC 3686). It, the [wire] IV, * and block counter are concatenated to form the "starting * variable". * * For AEAD, this is called the "salt" (RFC 5282, RFC-4309 - * AES-CCM-ESP, RFC-4106 - AES-GCM-ESP). It, and the [wire] * IV are concatenated to form the "nunce"; the block counter * and the "nunce" are then concatenated to form the "starting * variable". */ const size_t salt_size; /* * The IV sent across the wire; this is random material. * * The WIRE-IV which will be sent across the wire in public. * The SALT, WIRE-IV, and who-knows what else are concatenated * to form a ENC_BLOCKSIZE-byte starting-variable (aka IV). */ const size_t wire_iv_size; /* * Should the key-length attribute be omitted when * constructing the proposal's encrypt transform? * * Conversely, should a proposal be accepted when the encrypt * transform contains no key-length? */ const bool keylen_omitted; /* * Array of valid key lengths in bits. * * - must be zero terminated; makes iterating easier. * * - must contain at least one entry; else what is going on. * * - must be in descending order; so max value is first. * * If a key-length is required (!keylen_omitted) but omitted * from the {ike,esp}= line, then both KEYDEFLEN and (if * different) key_bit_lengths[0] are used in proposals. * * The selected keylen bits of keying material are extracted * from the initial shared-secret (PRF+). */ const unsigned key_bit_lengths[4]; /* * The default key length. * * XXX: this is not the _prefered_ key length. IKEv2 IKE * prefers key_bit_lengths[0], while IKEv2 ESP/AH prefer * KEYDEFLEN. Weird. */ const unsigned keydeflen; /* * For Authenticated Encryption with Associated Data (AEAD), * the size (in 8-bit bytes) of the authentication tag * appended to the end of the encrypted data. */ const size_t aead_tag_size; /* * For NSS. */ struct { /* * The NSS mechanism both used to implement this * algorithm and the type of the key expected by the * algorithm. * * Note that if the SYMKEY object passed to NSS does * not have this type, the operation fails. * * For non-NSS algorithms, leave this blank (i.e., 0). While, * technically, 0 is CKM_RSA_PKCS_KEY_PAIR_GEN, that mechanism * has no meaning in this context so it is safe. */ CK_MECHANISM_TYPE mechanism; } nss; /* * This encryption algorithm's SADB (pfkeyv2) value (>0 when * defined for this OS). * * XXX: The linux centric header libreswan/pfkeyv2 tries to * define "enum sadb_ealg" with the names * K_SADB[_X]_EALG_... but the code is broken - it doesn't * accomodate missing algorithms. Hence it is not used here. */ unsigned encrypt_sadb_ealg_id; /* * This encryption algorithm's NETLINK_XFRM name, if known. */ const char *encrypt_netlink_xfrm_name; /* * Name that should be parsable by tcpdump -E. It isn't clear * how true this is. See ikev2.c:ikev2_log_parentSA(). */ const char *encrypt_tcpdump_name; /* * Name used when generating a linux audit record. Allow an * IKE SA and CHILD (IPSEC kernel) SA to use different names. * * XXX: At one point the CHILD SA's audit name was the IKEv1 * ESP enum_name table but that forced all kernel algorithms * to have an IKEv1 name/number (even when it was bogus). */ const char *encrypt_ike_audit_name; const char *encrypt_kernel_audit_name; const struct encrypt_ops *encrypt_ops; }; /* * A "hash" algorithm is used to compute a simple message * authentication code. */ struct hash_desc { struct ike_alg common; /* MUST BE FIRST */ /* * Size of the output digest in bytes. */ const size_t hash_digest_size; /* * Size of an input block, in bytes. */ const size_t hash_block_size; /* * For NSS. * * This is all somewhat redundant. Unfortunately there isn't * a way to map between them. */ struct { /* * The NSS_OID_TAG identifies the the PK11 digest * (hash) context that should created when using * PL11_Digest*(). */ SECOidTag oid_tag; /* * The DERIVE_MECHANISM specifies the derivation * (algorithm) to use when using PK11_Derive(). */ CK_MECHANISM_TYPE derivation_mechanism; } nss; const struct hash_ops *hash_ops; }; /* * ASN.1 blobs specific to a particular hash algorithm are sent in the * Auth payload as part of Digital signature authentication as per RFC7427 */ struct asn1_hash_blob { enum notify_payload_hash_algorithms hash_algo; const uint8_t *blob; size_t blob_sz; }; /* * Pseudo Random Function: * * PRF(, ) -> digest * * While some PRFs are implemented using HMAC (for instance, * HMAC_SHA1), some are not (for instance, AES_CMAC). */ struct prf_desc { struct ike_alg common; /* MUST BE FIRST */ /* * Preferred key size of the PRF. * * IKEv2 2.13: It is assumed that PRFs accept keys of any * length, but have a preferred key size. The preferred key * size MUST be used as the length of SK_d, SK_pi, and SK_pr. * For PRFs based on the HMAC construction, the preferred key * size is equal to the length of the output of the underlying * hash function. Other types of PRFs MUST specify their * preferred key size. */ size_t prf_key_size; /* * Number of pseudo-random bytes returned by the PRF. * * IKEv2 2.13: Keying material will always be derived as the * output of the negotiated PRF algorithm. Since the amount * of keying material needed may be greater than the size of * the output of the PRF, the PRF is used iteratively. The * term "prf+" describes a function that outputs a * pseudorandom stream based on the inputs to a pseudorandom * function called "prf". */ size_t prf_output_size; /* * For NSS. */ struct { /* * The NSS mechanism both used to implement this * algorithm and the type of the key expected by the * algorithm. * * Note that if the SYMKEY object passed to NSS does * not have this type, the operation fails. * * For non-NSS algorithms, leave this blank (i.e., 0). While, * technically, 0 is CKM_RSA_PKCS_KEY_PAIR_GEN, that mechanism * has no meaning in this context so it is safe. */ CK_MECHANISM_TYPE mechanism; } nss; /* * For native-IKE. The HASHER used by the HMAC construction. * * Non-NULL IFF there is a native implementation. * * If non-NULL its values must be consistent with the above. */ const struct hash_desc *hasher; /* * FIPS controlled native implementation. */ const struct prf_mac_ops *prf_mac_ops; const struct prf_ikev1_ops *prf_ikev1_ops; const struct prf_ikev2_ops *prf_ikev2_ops; /* * Name used when generating a linux audit record for an IKE * SA. */ const char *prf_ike_audit_name; }; /* * Data Integrity. * * Currently all implementations use: * * sizeof() == integ->integ_key_size * TRUNC(integ->prf(,), integ->integ_output_size) * * However only IKE needs the PRF definition. ESP/AH leave it to the * kernel. */ struct integ_desc { struct ike_alg common; /* MUST BE FIRST */ /* * Size, in bytes (octets), of the keying material needed to * prime the integrity algorithm. * * If there's an IKE PRF implementation, then these values * need to be consistent with the PRF. */ const size_t integ_keymat_size; /* * The size of the output from the integrity algorithm. This * is put on the wire as "Integrity Checksum Data". * * If there's an IKE PRF implementation, then this must be <= * the PRF's output size and if that is implemented using a * HMAC construction, then it matches the HASH digest size. * * But none of that can be assumed. */ const size_t integ_output_size; /* * IKEv1 IPsec AH transform values * https://www.iana.org/assignments/isakmp-registry/isakmp-registry.xhtml#isakmp-registry-7 * * An IKEv1 AH proposal is structured as: * * Transform: ikev1_ah_transform * Attribute: ikev1_auth_attribute * * Where the attrid and transid need to match. Other than for * an MD5 edge case, this is entirely redundant. */ enum ipsec_authentication_algo integ_ikev1_ah_transform; /* * This integrity algorithm's SADB (pfkeyv2) value (>0 when * defined for this OS). * * The linux centric header libreswan/pfkeyv2 tries to define * "enum sadb_aalg" with the names K_SADB[_X]_AALG_... but the * code is broken - it doesn't accomodate missing algorithms. * Hence it is not used here. */ unsigned integ_sadb_aalg_id; /* * This integrity algorithm's NETLINK_XFRM name if known. */ const char *integ_netlink_xfrm_name; /* * Name that should be parsable by tcpdump -E. It isn't clear * how true this is. See ikev2.c:ikev2_log_parentSA(). */ const char *integ_tcpdump_name; /* * Name used when generating a linux audit record. Allow an * IKE SA and CHILD (IPSEC kernel) SA to use different names. * * XXX: At one point the CHILD SA's audit name was the IKEv1 * ESP enum_name table but that forced all kernel algorithms * to have an IKEv1 name/number (even when it was bogus). */ const char *integ_ike_audit_name; const char *integ_kernel_audit_name; /* * For IKE. The PRF implementing integrity. The output is * truncated down to INTEG_HASH_LEN. * * Non-NULL IFF there is a native implementation. */ const struct prf_desc *prf; }; /* * Is the encryption algorithm AEAD (Authenticated Encryption with * Associated Data)? * * Since AEAD algorithms have integrity built in, separate integrity * is redundant. * * Note that the converse (non-AEAD algorithm always require * integrity) is not true. For instance, with ESP, integrity is * optional. */ extern bool encrypt_desc_is_aead(const struct encrypt_desc *enc_desc); void init_ike_alg(void); void test_ike_alg(void); /* * Iterate over all enabled algorithms. */ const struct encrypt_desc **next_encrypt_desc(const struct encrypt_desc **last); const struct prf_desc **next_prf_desc(const struct prf_desc **last); const struct integ_desc **next_integ_desc(const struct integ_desc **last); const struct dh_desc **next_dh_desc(const struct dh_desc **last); /* * Is the algorithm suitable for IKE (i.e., native)? * * Code should also filter on ikev1_oakley_id and/or ikev2_id. */ bool ike_alg_is_ike(const struct ike_alg *alg); /* * Is the algorithm valid (or did FIPS, say, disable it)? */ bool ike_alg_is_valid(const struct ike_alg *alg); /* * Is the key valid for the encryption algorithm? * * For the case of null encryption, 0 is considered valid. */ bool encrypt_has_key_bit_length(const struct encrypt_desc *encrypt_desc, unsigned keylen); /* * The largest and smallest key bit length allowed. */ unsigned encrypt_min_key_bit_length(const struct encrypt_desc *encrypt_desc); unsigned encrypt_max_key_bit_length(const struct encrypt_desc *encrypt_desc); /* * DHMKE: Diffie–Hellman–Merkle key exchange. * * The naming follows Hellman's suggestion; besides "dh" is too short * and "oakley_group" is too long. */ struct dh_desc { struct ike_alg common; /* must be first */ uint16_t group; size_t bytes; /* * For MODP groups, the base and prime used when generating * the KE. */ const char *gen; const char *modp; /* * For ECP groups, the NSS ASN.1 OID that identifies the ECP. */ SECOidTag nss_oid; const struct dh_ops *dh_ops; }; extern const struct dh_desc unset_group; /* magic signifier */ /* * Robustly cast struct ike_alg to underlying object. * * Could be reduced to a macro, but only if passert() returned * something. */ const struct hash_desc *hash_desc(const struct ike_alg *alg); const struct prf_desc *prf_desc(const struct ike_alg *alg); const struct integ_desc *integ_desc(const struct ike_alg *alg); const struct encrypt_desc *encrypt_desc(const struct ike_alg *alg); const struct dh_desc *dh_desc(const struct ike_alg *alg); /* * Find the ENCRYPT / PRF / INTEG / DH algorithm using the IKEv2 wire * value. * * Use ike_alg_is_ike() to confirm that the algorithm has a native * implementation (as needed by IKE and ESP/AH PFS). Use a kernel * query to confirm that the algorithm has kernel support (XXX: what? * who knows). */ const struct encrypt_desc *ikev2_get_encrypt_desc(enum ikev2_trans_type_encr); const struct prf_desc *ikev2_get_prf_desc(enum ikev2_trans_type_prf); const struct integ_desc *ikev2_get_integ_desc(enum ikev2_trans_type_integ); const struct dh_desc *ikev2_get_dh_desc(enum ike_trans_type_dh); /* * Find the ENCRYPT / PRF / DH algorithm using IKEv1 IKE (aka OAKLEY) * wire value. * * Unlike IKEv2, IKEv1 uses different wire-values for IKE, ESP, and * AH. This just deals with IKE (well, ok, in the case of DH, it also * deals with ESP/AH as the value is the same). */ const struct encrypt_desc *ikev1_get_ike_encrypt_desc(enum ikev1_encr_attribute); const struct prf_desc *ikev1_get_ike_prf_desc(enum ikev1_auth_attribute); const struct dh_desc *ikev1_get_ike_dh_desc(enum ike_trans_type_dh); /* * Find the IKEv1 ENCRYPT / INTEG algorithm that will be fed into the * kernel to provide an IPSEC tunnel. */ const struct encrypt_desc *ikev1_get_kernel_encrypt_desc(enum ipsec_cipher_algo); const struct integ_desc *ikev1_get_kernel_integ_desc(enum ikev1_auth_attribute); /* * Find the ENCRYPT / INTEG algorithm using the SADB defined value. * * Note that these functions take an unsigned and _not_ an enum * parameter. See above. */ const struct encrypt_desc *encrypt_desc_by_sadb_ealg_id(unsigned id); const struct integ_desc *integ_desc_by_sadb_aalg_id(unsigned id); /* * Pretty print the algorithm to the standard log. The logged line is * very wide. */ void libreswan_log_ike_alg(const char *prefix, const struct ike_alg *alg); #endif /* _IKE_ALG_H */ libreswan-3.32/include/ike_alg_dh.h000066400000000000000000000031401365625662500173070ustar00rootroot00000000000000/* * IKE modular algorithm handling interface, for libreswan * * Copyright (C) 2016 Andrew Cagney * Copyright (C) 2018 Paul Woutets * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifdef USE_DH2 extern const struct dh_desc ike_alg_dh_modp1024; #endif extern const struct dh_desc ike_alg_dh_modp1536; extern const struct dh_desc ike_alg_dh_modp2048; extern const struct dh_desc ike_alg_dh_modp3072; extern const struct dh_desc ike_alg_dh_modp4096; extern const struct dh_desc ike_alg_dh_modp6144; extern const struct dh_desc ike_alg_dh_modp8192; extern const struct dh_desc ike_alg_dh_dh19; extern const struct dh_desc ike_alg_dh_dh20; extern const struct dh_desc ike_alg_dh_dh21; #ifdef USE_DH22 extern const struct dh_desc ike_alg_dh_dh22; #endif #ifdef USE_DH23 extern const struct dh_desc ike_alg_dh_dh23; #endif #ifdef USE_DH24 extern const struct dh_desc ike_alg_dh_dh24; #endif #ifdef USE_DH31 extern const struct dh_desc ike_alg_dh_dh31; #endif /* * IKEv2 RFC 7296 uses the term "NONE" when referring to no DH * algorithm. */ extern const struct dh_desc ike_alg_dh_none; libreswan-3.32/include/ike_alg_dh_ops.h000066400000000000000000000031541365625662500201750ustar00rootroot00000000000000/* * Copyright (C) 2017 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef IKE_ALG_DH_OPS_H #define IKE_ALG_DH_OPS_H struct dh_ops { const char *backend; /* * Delegate responsibility for checking OPS specific fields. */ void (*const check)(const struct dh_desc *alg); /* * Create the local secret and KE for remote. * * The LOCAL_PUBK parameter is arguably redundant - just the * KE bytes and private key are needed - however MODP's * CALC_G_IR() uses LOCAL_PUBK to fudge up the remote's public * key. * * SIZEOF_KE == .BYTES from above, but pass it in so both ends * can perform a sanity check. */ void (*calc_secret)(const struct dh_desc *group, SECKEYPrivateKey **local_privk, SECKEYPublicKey **locak_pubk, uint8_t *ke, size_t sizeof_ke); PK11SymKey *(*calc_shared)(const struct dh_desc *group, SECKEYPrivateKey *local_privk, const SECKEYPublicKey *local_pubk, uint8_t *remote_ke, size_t sizeof_remote_ke); }; extern const struct dh_ops ike_alg_dh_nss_ecp_ops; extern const struct dh_ops ike_alg_dh_nss_modp_ops; #endif libreswan-3.32/include/ike_alg_encrypt.h000066400000000000000000000036261365625662500204110ustar00rootroot00000000000000/* encryption algorithms, for libreswan * * Copyright (C) 2016 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifdef USE_AES extern const struct encrypt_desc ike_alg_encrypt_aes_cbc; extern const struct encrypt_desc ike_alg_encrypt_aes_ctr; extern const struct encrypt_desc ike_alg_encrypt_aes_gcm_8; extern const struct encrypt_desc ike_alg_encrypt_aes_gcm_12; extern const struct encrypt_desc ike_alg_encrypt_aes_gcm_16; extern const struct encrypt_desc ike_alg_encrypt_aes_ccm_8; extern const struct encrypt_desc ike_alg_encrypt_aes_ccm_12; extern const struct encrypt_desc ike_alg_encrypt_aes_ccm_16; extern const struct encrypt_desc ike_alg_encrypt_null_integ_aes_gmac; #endif #ifdef USE_CAMELLIA extern const struct encrypt_desc ike_alg_encrypt_camellia_cbc; extern const struct encrypt_desc ike_alg_encrypt_camellia_ctr; #endif #ifdef USE_TWOFISH extern const struct encrypt_desc ike_alg_encrypt_twofish_ssh; extern const struct encrypt_desc ike_alg_encrypt_twofish_cbc; #endif #ifdef USE_3DES extern const struct encrypt_desc ike_alg_encrypt_3des_cbc; #endif #ifdef USE_SERPENT extern const struct encrypt_desc ike_alg_encrypt_serpent_cbc; #endif extern const struct encrypt_desc ike_alg_encrypt_null; #ifdef USE_CAST extern const struct encrypt_desc ike_alg_encrypt_cast_cbc; #endif #ifdef USE_CHACHA extern const struct encrypt_desc ike_alg_encrypt_chacha20_poly1305; #endif libreswan-3.32/include/ike_alg_encrypt_ops.h000066400000000000000000000040511365625662500212630ustar00rootroot00000000000000/* NSS AEAD, for libreswan * * Copyright (C) 2018 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef IKE_ALG_ENCRYPT_OPS_H #define IKE_ALG_ENCRYPT_OPS_H struct encrypt_ops { const char *backend; /* * Delegate responsibility for checking OPS specific fields. */ void (*const check)(const struct encrypt_desc *alg); /* * Perform simple encryption. * * Presumably something else is implementing the integrity. */ void (*const do_crypt)(const struct encrypt_desc *alg, uint8_t *dat, size_t datasize, PK11SymKey *key, uint8_t *iv, bool enc); /* * Perform Authenticated Encryption with Associated Data * (AEAD). * * The salt and wire-IV are concatenated to form the NONCE * (aka. counter variable; IV; ...). * * The Additional Authentication Data (AAD) and the * cipher-text are concatenated when generating/validating the * tag (which is appended to the text). * * All sizes are in 8-bit bytes. */ bool (*const do_aead)(const struct encrypt_desc *alg, uint8_t *salt, size_t salt_size, uint8_t *wire_iv, size_t wire_iv_size, uint8_t *aad, size_t aad_size, uint8_t *text_and_tag, size_t text_size, size_t tag_size, PK11SymKey *key, bool enc); }; extern const struct encrypt_ops ike_alg_encrypt_nss_aead_ops; extern const struct encrypt_ops ike_alg_encrypt_nss_cbc_ops; extern const struct encrypt_ops ike_alg_encrypt_nss_ctr_ops; extern const struct encrypt_ops ike_alg_encrypt_nss_gcm_ops; #endif libreswan-3.32/include/ike_alg_hash.h000066400000000000000000000031731365625662500176450ustar00rootroot00000000000000/* hash algorithms, for libreswan * * Copyright (C) 2016 Andrew Cagney * Copyright (C) 2018 Sahana Prasad * Copyright (C) 2019 D. Hugh Redelmeier * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #ifdef USE_SHA1 extern const struct hash_desc ike_alg_hash_sha1; #endif extern const struct hash_desc ike_alg_hash_sha2_256; /* also used for cookies */ #ifdef USE_SHA2 extern const struct hash_desc ike_alg_hash_sha2_384; extern const struct hash_desc ike_alg_hash_sha2_512; #endif #ifdef USE_MD5 extern const struct hash_desc ike_alg_hash_md5; #endif extern const CK_RSA_PKCS_PSS_PARAMS rsa_pss_sha2_256; extern const CK_RSA_PKCS_PSS_PARAMS rsa_pss_sha2_384; extern const CK_RSA_PKCS_PSS_PARAMS rsa_pss_sha2_512; extern const struct asn1_hash_blob asn1_rsa_pss_sha2_256; extern const struct asn1_hash_blob asn1_rsa_pss_sha2_384; extern const struct asn1_hash_blob asn1_rsa_pss_sha2_512; extern const struct asn1_hash_blob asn1_ecdsa_sha2_256; extern const struct asn1_hash_blob asn1_ecdsa_sha2_384; extern const struct asn1_hash_blob asn1_ecdsa_sha2_512; libreswan-3.32/include/ike_alg_hash_ops.h000066400000000000000000000025311365625662500205230ustar00rootroot00000000000000/* * Copyright (C) 2016 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef IKE_ALG_HASH_OPS_H #define IKE_ALG_HASH_OPS_H /* * Generic implementation of HASH_DESC. */ struct hash_context; struct hash_ops { const char *backend; /* * Delegate responsibility for checking OPS specific fields. */ void (*const check)(const struct hash_desc *alg); struct hash_context *(*init)(const struct hash_desc *hash_desc, const char *name); void (*digest_symkey)(struct hash_context *hash, const char *name, PK11SymKey *symkey); void (*digest_bytes)(struct hash_context *hash, const char *name, const uint8_t *bytes, size_t sizeof_bytes); void (*final_bytes)(struct hash_context**, uint8_t *bytes, size_t sizeof_bytes); }; extern const struct hash_ops ike_alg_hash_nss_ops; #endif libreswan-3.32/include/ike_alg_integ.h000066400000000000000000000027711365625662500200330ustar00rootroot00000000000000/* integ algorithms, for libreswan * * Copyright (C) 2016 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifdef USE_AES extern const struct integ_desc ike_alg_integ_aes_xcbc; extern const struct integ_desc ike_alg_integ_aes_cmac; #endif #ifdef USE_SHA1 extern const struct integ_desc ike_alg_integ_sha1; #endif #ifdef USE_SHA2 extern const struct integ_desc ike_alg_integ_sha2_256; extern const struct integ_desc ike_alg_integ_sha2_384; extern const struct integ_desc ike_alg_integ_sha2_512; extern const struct integ_desc ike_alg_integ_hmac_sha2_256_truncbug; #endif #ifdef USE_MD5 extern const struct integ_desc ike_alg_integ_hmac_md5_96; #endif #ifdef USE_RIPEMD extern const struct integ_desc ike_alg_integ_hmac_ripemd_160_96; #endif /* * IKEv2 RFC 7296 uses the term "NONE" when referring to no integrity. * For instance: ... MUST either offer no integrity algorithm or a * single integrity algorithm of "NONE" */ extern const struct integ_desc ike_alg_integ_none; libreswan-3.32/include/ike_alg_prf.h000066400000000000000000000020411365625662500175020ustar00rootroot00000000000000/* PRF algorithms, for libreswan * * Copyright (C) 2016 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifdef USE_PRF_AES_XCBC extern const struct prf_desc ike_alg_prf_aes_xcbc; #endif #ifdef USE_SHA1 extern const struct prf_desc ike_alg_prf_sha1; #endif #ifdef USE_SHA2 extern const struct prf_desc ike_alg_prf_sha2_256; extern const struct prf_desc ike_alg_prf_sha2_384; extern const struct prf_desc ike_alg_prf_sha2_512; #endif #ifdef USE_MD5 extern const struct prf_desc ike_alg_prf_hmac_md5; #endif libreswan-3.32/include/ike_alg_prf_ikev1_ops.h000066400000000000000000000124701365625662500214710ustar00rootroot00000000000000/* IKEv1 specific PRF operations, for libreswan. * * Copyright (C) 2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef IKE_ALG_PRF_IKEv1_OPS_H #define IKE_ALG_PRF_IKEv1_OPS_H #include "chunk.h" struct prf_ikev1_ops { const char *backend; /* * SKEYID is a string derived from secret material known only * to the active players in the exchange (from 3.2 Notation). * * For signatures: * SKEYID = prf(Ni_b | Nr_b, g^xy) * * For pre-shared keys: * SKEYID = prf(pre-shared-key, Ni_b | Nr_b) * * For public key encryption (NOT IMPLEMENTED?): * SKEYID = prf(hash(Ni_b | Nr_b), CKY-I | CKY-R) * * (see 5. Exchanges) */ PK11SymKey *(*signature_skeyid)(const struct prf_desc *prf_desc, const chunk_t Ni_b, const chunk_t Nr_b, PK11SymKey *dh_secret); PK11SymKey *(*pre_shared_key_skeyid)(const struct prf_desc *prf_desc, chunk_t pre_shared_key, chunk_t Ni_b, chunk_t Nr_b); /* * SKEYID_d is the keying material used to derive keys for * non-ISAKMP security associations (from 3.2 Notation) (for * instance SKEYID_a). * * 5. Exchanges: * * SKEYID_d = prf(SKEYID, g^xy | CKY-I | CKY-R | 0) * * If SKEYID_d's size is too small to be fed back into the PRF * then, per Appendix B, it is expanded using: * * BLOCK1-8 = prf(SKEYID, g^xy | CKY-I | CKY-R | 0) * BLOCK9-16 = prf(SKEYID, BLOCK1-8 | g^xy | CKY-I | CKY-R | 0) * BLOCK17-24 = prf(SKEYID, BLOCK9-16 | g^xy | CKY-I | CKY-R | 0) * * and: * * SKEYID_d = BLOCK1-8 | BLOCK9-16 | BLOCK17-24 */ PK11SymKey *(*skeyid_d)(const struct prf_desc *prf_desc, PK11SymKey *skeyid, PK11SymKey *dh_secret, chunk_t cky_i, chunk_t cky_r); /* * SKEYID_a is the keying material used by the ISAKMP SA to * authenticate its messages (from 3.2 Notation). * * 5. Exchanges: * * SKEYID_a = prf(SKEYID, SKEYID_d | g^xy | CKY-I | CKY-R | 1) * * See also Appendix B and expanding for PRF. */ PK11SymKey *(*skeyid_a)(const struct prf_desc *prf_desc, PK11SymKey *skeyid, PK11SymKey *skeyid_d, PK11SymKey *dh_secret, chunk_t cky_i, chunk_t cky_r); /* * SKEYID_e is the keying material used by the ISAKMP SA to * protect the confidentiality of its messages (from 3.2 * Notation). * * 5. Exchanges: * * SKEYID_e = prf(SKEYID, SKEYID_a | g^xy | CKY-I | CKY-R | 2) * * See also Appendix B and expanding for PRF. */ PK11SymKey *(*skeyid_e)(const struct prf_desc *prf_desc, PK11SymKey *skeyid, PK11SymKey *skeyid_a, PK11SymKey *dh_secret, chunk_t cky_i, chunk_t cky_r); /* * Appendix B - IKE (ISAKMP) SA keys * * Encryption keys used to protect the ISAKMP SA are derived * from SKEYID_e in an algorithm-specific manner. When * SKEYID_e is not long enough to supply all the necessary * keying material an algorithm requires, the key is derived * from feeding the results of a pseudo-random function into * itself, concatenating the results, and taking the highest * necessary bits. * * KEYMAT_e = prf(SKEYID_e, 0) ... see RFC * * Ka = K1 | K2 | K3 | ... * * where: * * K1 = prf(SKEYID_e, 0) * K2 = prf(SKEYID_e, K1) * K3 = prf(SKEYID_e, K2) * etc. */ PK11SymKey *(*appendix_b_keymat_e)(const struct prf_desc *prf_desc, const struct encrypt_desc *encrypter, PK11SymKey *skeyid_e, unsigned required_keymat); /* * Setion 5.5 - CHILD (IPSEC) SA keys & Quick Mode * * If PFS is not needed, and KE payloads are not exchanged, * the new keying material is defined as * * KEYMAT = prf(SKEYID_d, protocol | SPI | Ni_b | Nr_b). * * If PFS is desired and KE payloads were exchanged, the new * keying material is defined as * * KEYMAT = prf(SKEYID_d, g(qm)^xy | protocol | SPI | Ni_b | Nr_b) * * where g(qm)^xy is the shared secret from the ephemeral * Diffie-Hellman exchange of this Quick Mode. * * For situations where the amount of keying material desired * is greater than that supplied by the prf, KEYMAT is * expanded by feeding the results of the prf back into itself * and concatenating results until the required keying * material has been reached. In other words, * * KEYMAT = K1 | K2 | K3 | ... * * where * * 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) * etc. */ chunk_t (*section_5_keymat)(const struct prf_desc *prf_desc, PK11SymKey *SKEYID_d, PK11SymKey *g_xy, uint8_t protocol, shunk_t SPI, chunk_t NI_b, chunk_t Nr_b, unsigned required_keymat); }; extern const struct prf_ikev1_ops ike_alg_prf_ikev1_mac_ops; #ifdef USE_NSS_PRF extern const struct prf_ikev1_ops ike_alg_prf_ikev1_nss_ops; #endif #endif libreswan-3.32/include/ike_alg_prf_ikev2_ops.h000066400000000000000000000045631365625662500214760ustar00rootroot00000000000000/* IKEv1 PRF specific operations, for libreswan * * Copyright (C) 2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef IKE_ALG_PRF_IKEv2_OPS_H #define IKE_ALG_PRF_IKEv2_OPS_H #include "chunk.h" #include "shunk.h" #include "crypt_mac.h" struct prf_ikev2_ops { const char *backend; /* * IKEv2 - RFC4306 2.14 SKEYSEED - calculation. */ PK11SymKey *(*prfplus)(const struct prf_desc *prf_desc, PK11SymKey *key, PK11SymKey *seed, size_t required_keymat); /* SKEYSEED = prf(Ni | Nr, g^ir) */ PK11SymKey *(*ike_sa_skeyseed)(const struct prf_desc *prf_desc, const chunk_t Ni, const chunk_t Nr, PK11SymKey *dh_secret); /* SKEYSEED = prf(SK_d (old), g^ir (new) | Ni | Nr) */ PK11SymKey *(*ike_sa_rekey_skeyseed)(const struct prf_desc *prf_desc, PK11SymKey *old_SK_d, PK11SymKey *new_dh_secret, const chunk_t Ni, const chunk_t Nr); /* KEYMAT = prf+ (SKEYSEED, Ni | Nr | SPIi | SPIr) */ PK11SymKey *(*ike_sa_keymat)(const struct prf_desc *prf_desc, PK11SymKey *skeyseed, const chunk_t Ni, const chunk_t Nr, const shunk_t SPIi, const shunk_t SPIr, size_t required_bytes); /* KEYMAT = prf+(SK_d, [ g^ir (new) | ] Ni | Nr) */ PK11SymKey *(*child_sa_keymat)(const struct prf_desc *prf_desc, PK11SymKey *SK_d, PK11SymKey *new_dh_secret, const chunk_t Ni, const chunk_t Nr, size_t required_bytes); /* AUTH = prf( prf(Shared Secret, "Key Pad for IKEv2"), <{Initiator,Responder}SignedOctets>) */ struct crypt_mac (*psk_auth)(const struct prf_desc *prf_desc, chunk_t pss, chunk_t first_packet, chunk_t nonce, const struct crypt_mac *id_hash); }; extern const struct prf_ikev2_ops ike_alg_prf_ikev2_mac_ops; #ifdef USE_NSS_PRF extern const struct prf_ikev2_ops ike_alg_prf_ikev2_nss_ops; #endif #endif libreswan-3.32/include/ike_alg_prf_mac_ops.h000066400000000000000000000032411365625662500212060ustar00rootroot00000000000000/* * Copyright (C) 2016 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef IKE_ALG_PRF_MAC_OPS_H #define IKE_ALG_PRF_MAC_OPS_H struct prf_mac_ops { const char *backend; /* * Delegate responsibility for checking OPS specific fields. */ void (*const check)(const struct prf_desc *alg); struct prf_context *(*init_symkey)(const struct prf_desc *prf_desc, const char *name, const char *key_name, PK11SymKey *key); struct prf_context *(*init_bytes)(const struct prf_desc *prf_desc, const char *name, const char *key_name, const uint8_t *bytes, size_t sizeof_bytes); void (*digest_symkey)(struct prf_context *prf, const char *name, PK11SymKey *symkey); void (*digest_bytes)(struct prf_context *prf, const char *name, const uint8_t *bytes, size_t sizeof_bytes); PK11SymKey *(*final_symkey)(struct prf_context **prf); void (*final_bytes)(struct prf_context **prf, uint8_t *bytes, size_t sizeof_bytes); }; extern const struct prf_mac_ops ike_alg_prf_mac_hmac_ops; extern const struct prf_mac_ops ike_alg_prf_mac_nss_ops; extern const struct prf_mac_ops ike_alg_prf_mac_nss_xcbc_ops; #endif libreswan-3.32/include/ike_alg_test_cbc.h000066400000000000000000000020201365625662500204760ustar00rootroot00000000000000/* * Copyright (C) 2014,2016 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ struct cbc_test_vector { const char *description; /* mumble something about algorithm setting here. */ const char *key; const char *iv; const char *plaintext; const char *ciphertext; }; extern const struct cbc_test_vector *const aes_cbc_tests; extern const struct cbc_test_vector *const camellia_cbc_tests; bool test_cbc_vectors(const struct encrypt_desc *encrypt_desc, const struct cbc_test_vector *tests); libreswan-3.32/include/ike_alg_test_ctr.h000066400000000000000000000020101365625662500205360ustar00rootroot00000000000000/* * Copyright (C) 2014,2016 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ struct ctr_test_vector { /* CK_MECHANISM_TYPE cipher_mechanism; */ /* struct encrypt_desc *encrypt_desc; */ const char *description; const char *key; const char *cb; const char *plaintext; const char *ciphertext; const char *output_cb; }; extern const struct ctr_test_vector *const aes_ctr_tests; bool test_ctr_vectors(const struct encrypt_desc *encrypt_desc, const struct ctr_test_vector *tests); libreswan-3.32/include/ike_alg_test_gcm.h000066400000000000000000000021531365625662500205240ustar00rootroot00000000000000/* * Copyright (C) 2015-2016 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ struct gcm_test_vector { const char *description; const char *key; /* * NIST provides a simple IV, while we require a separate SALT * and wire-IV. The value gets split before being passed to * the do_crypt_hash method. */ const char *salted_iv; const char *aad; const char *plaintext; const char *ciphertext; const char *tag; }; extern const struct gcm_test_vector *const aes_gcm_tests; bool test_gcm_vectors(const struct encrypt_desc *encrypt_desc, const struct gcm_test_vector *tests); libreswan-3.32/include/ike_alg_test_prf.h000066400000000000000000000017261365625662500205520ustar00rootroot00000000000000/* * Copyright (C) 2014,2016-2017 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ struct prf_test_vector { const char *description; const char *key; unsigned key_size; const char *message; unsigned message_size; const char *prf_output; }; extern const struct prf_test_vector aes_xcbc_prf_tests[]; extern const struct prf_test_vector hmac_md5_prf_tests[]; bool test_prf_vectors(const struct prf_desc *desc, const struct prf_test_vector *tests); libreswan-3.32/include/impair.h000066400000000000000000000040061365625662500165240ustar00rootroot00000000000000/* impair operation, for libreswan * * Copyright (C) 2018-2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #ifndef IMPAIR_H #define IMPAIR_H #include #include "lswcdefs.h" /* * Meddle with the contents of a payload. */ enum send_impairment { SEND_NORMAL = 0, SEND_OMIT, SEND_EMPTY, SEND_DUPLICATE, SEND_ROOF, /* >= ROOF -> */ }; /* * Meddle with a specific exchange. */ enum exchange_impairment { NO_EXCHANGE = 0, NOTIFICATION_EXCHANGE, QUICK_EXCHANGE, XAUTH_EXCHANGE, DELETE_EXCHANGE, }; /* * add more here */ #if 0 enum xxx_impair ...; #endif /* * What can be impaired. * * See impair.c for documentation. * * XXX: make this a structure so it can be copied? */ extern bool impair_revival; extern bool impair_emitting; extern enum send_impairment impair_ke_payload; extern enum send_impairment impair_ike_key_length_attribute; extern enum send_impairment impair_child_key_length_attribute; extern unsigned impair_log_rate_limit; extern enum send_impairment impair_v1_hash_payload; extern enum exchange_impairment impair_v1_hash_exchange; extern bool impair_v1_hash_check; /* * What whack sends across the wire for a impair. */ struct whack_impair { unsigned what; unsigned how; }; bool parse_impair(const char *optarg, struct whack_impair *whack_impair, bool enable); void process_impair(const struct whack_impair *whack_impair); void help_impair(const char *prefix); void lswlog_impairments(struct lswlog *buf, const char *prefix, const char *sep); #endif libreswan-3.32/include/ip_address.h000066400000000000000000000150611365625662500173630ustar00rootroot00000000000000/* ip address type, for libreswan * * Copyright (C) 1998, 1999, 2000 Henry Spencer. * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs * Copyright (C) 2019 Andrew Cagney * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. * */ #ifndef IP_ADDRESS_H #define IP_ADDRESS_H #include "lswcdefs.h" /* for MUST_USE_RESULT */ #include "shunk.h" #include "chunk.h" #include "err.h" struct lswlog; struct ip_info; extern bool log_ip; /* false -> redact (aka sanitize) ip addresses */ /* * Basic data types for the address-handling functions. * * ip_address et.al. are supposed to be opaque types; do not use their * definitions directly, they are subject to change! * * Because whack sends raw ip_addresses to pluto using a byte * stream, this structure needs to be stream friendly - it * must not contain pointers (such as a pointer to struct * ip_info). so instead it contains an index. */ typedef struct { /* * Index into the struct ip_info array; must be stream * friendly. */ unsigned version; /* 0, 4, 6 */ /* * We need something that makes static IPv4 initializers possible * (struct in_addr requires htonl() which is run-time only). */ uint8_t bytes[16]; #ifndef ENDPOINT_TYPE /* * XXX: An address abstraction - type+bytes - should not * contain a port. If a port is required, the abstraction * ip_endpoint should be used. * * In pluto, port "0" is reserved and indicates all ports (but * does it also denote no port?). Hopefully it is only paired * with the zero (any) address. * * XXX: Would separate and incompatible ip_hport and ip_nport * types help stop host <-> network port conversion screwups? * For instance, using ntohs() when using htons() is needed - * while wrong they have the same effect. * */ uint16_t hport; #endif } ip_address; /* * Constructors. */ ip_address address_from_in_addr(const struct in_addr *in); ip_address address_from_in6_addr(const struct in6_addr *sin6); err_t data_to_address(const void *data, size_t sizeof_data, const struct ip_info *af, ip_address *dst) MUST_USE_RESULT; ip_address address_from_shunk(const struct ip_info *afi, const shunk_t bytes); /* either SHUNK or CHUNK */ #define hunk_to_address(HUNK, AF, DST) data_to_address(HUNK.ptr, HUNK.len, AF, DST) /* assumes dotted / colon notation */ err_t numeric_to_address(shunk_t src, const struct ip_info *type, ip_address *dst); /* if numeric lookup fails, try a DNS lookup */ err_t domain_to_address(shunk_t src, const struct ip_info *type, ip_address *dst); /* * Convert an address to a string: * * This implements https://tools.ietf.org/html/rfc5952 where zeros in * the middle of an IPv6 address are suppressed. If the IP address is * "sensitive" use *_address_sensitive(). */ typedef struct { char buf[(4+1)*8/*0000:...*/ + 1/*\0*/ + 1/*CANARY*/]; } address_buf; void jam_address(struct lswlog *buf, const ip_address *src); const char *str_address(const ip_address *src, address_buf *dst); /* * sensitive: don't print address when !log_ip * * reversed: in-addr format. * raw: This is not the format function you are looking for. For IPv6 * include all zeros, vis :0:..:0:; when SEPC != '\0' use it as the * separator instead of '.' (IPv4) or ':' (IPv6). */ typedef struct { /* string includes NUL, add 1 for canary */ char buf[sizeof("4.0.0.0.3.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.0.1.0.0.0.IP6.ARPA.") + 1]; } address_reversed_buf; void jam_address_sensitive(struct lswlog *buf, const ip_address *src); void jam_address_reversed(struct lswlog *buf, const ip_address *src); void jam_address_raw(struct lswlog *buf, const ip_address *src, char sepc); const char *str_address_sensitive(const ip_address *src, address_buf *dst); const char *str_address_reversed(const ip_address *src, address_reversed_buf *buf); const char *str_address_raw(const ip_address *src, char sepc, address_buf *dst); typedef address_buf ipstr_buf; const char *ipstr(const ip_address *src, ipstr_buf *b); const char *sensitive_ipstr(const ip_address *src, ipstr_buf *b); /* * Magic values. * * XXX: While the headers call the all-zero address "ANY" (INADDR_ANY, * IN6ADDR_ANY_INIT), the headers also refer to the IPv6 value as * unspecified (for instance IN6_IS_ADDR_UNSPECIFIED()) leaving the * term "unspecified" underspecified. * * Consequently to identify an AF_UNSPEC address (i.e., * uninitialized), see if *_type() returns NULL. There's an * address_is_invalid() wrapper for completeness. */ /* AF=AF_UNSPEC, ADDR = 0; aka all zeros */ extern const ip_address address_invalid; /* returns NULL when address_invalid */ const struct ip_info *address_type(const ip_address *address); /* AF={INET,INET6}, ADDR = 0; aka %any? */ ip_address address_any(const struct ip_info *info); /* mutually exclusive */ #define address_is_invalid(A) (address_type(A) == NULL) bool address_is_any(const ip_address *address); bool address_is_specified(const ip_address *address); /* implies specified */ bool address_is_loopback(const ip_address *address); /* * Raw address bytes, both read-only and read-write. */ shunk_t address_as_shunk(const ip_address *address); chunk_t address_as_chunk(ip_address *address); /* * XXX: prop up IPv4 centric code that just isn't worth the effort. */ uint32_t ntohl_address(const ip_address *address); /* * Old style. */ /* looks up names in DNS */ extern err_t ttoaddr(const char *src, size_t srclen, int af, ip_address *dst); /* does not look up names in DNS */ extern err_t ttoaddr_num(const char *src, size_t srclen, int af, ip_address *dst); /* RFC 1886 old IPv6 reverse-lookup format is the bulkiest */ #define ADDRTOT_BUF sizeof(address_reversed_buf) extern err_t tnatoaddr(const char *src, size_t srclen, int af, ip_address *dst); /* misc. conversions and related */ extern int addrtypeof(const ip_address *src); extern int masktocount(const ip_address *src); /* tests */ extern bool sameaddr(const ip_address *a, const ip_address *b); extern int addrcmp(const ip_address *a, const ip_address *b); /* XXX: use address_is_{invalid,any,specified}() instead */ extern bool isanyaddr(const ip_address *src); #endif libreswan-3.32/include/ip_endpoint.h000066400000000000000000000076171365625662500175660ustar00rootroot00000000000000/* ip endpoint (address + port), for libreswan * * Copyright (C) 2019 Andrew Cagney * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. * */ #ifndef IP_ENDPOINT_H #define IP_ENDPOINT_H #include #include "chunk.h" #include "err.h" #include "ip_address.h" #include "ip_sockaddr.h" struct lswlog; /* * ip_endpoint and ip_address should be distinct types where the * latter consists of ADDRESS:PORT. Unfortunately separating them is * going to be slow. * * Defining ENDPOINT_TYPE causes the the types to become distinct. */ #ifdef ENDPOINT_TYPE typedef struct { ip_address address; /* * In pluto "0" denotes all ports (or, in the context of an * endpoint, is that none?). */ int hport; } ip_endpoint; #else typedef ip_address ip_endpoint; #endif /* * Constructors. */ ip_endpoint endpoint(const ip_address *address, int port); /* * Formatting * * Endpoint formatting is always "cooked". For instance, the address * "::1" is printed as "[::1]:PORT" (raw would print it as * "[0:0....:0]:PORT" */ typedef struct { char buf[1/*[*/ + sizeof(address_buf) + 1/*]*/ + 5/*:65535*/]; } endpoint_buf; const char *str_endpoint(const ip_endpoint *, endpoint_buf *); void jam_endpoint(struct lswlog *, const ip_endpoint*); const char *str_sensitive_endpoint(const ip_endpoint *, endpoint_buf *); void jam_sensitive_endpoint(struct lswlog *, const ip_endpoint*); /* * Logic */ bool endpoint_eq(const ip_endpoint l, ip_endpoint r); /* * Magic values. * * XXX: While the headers call the all-zero address "ANY" (INADDR_ANY, * IN6ADDR_ANY_INIT), the headers also refer to the IPv6 value as * unspecified (for instance IN6_IS_ADDR_UNSPECIFIED()) leaving the * term "unspecified" underspecified. * * Consequently to identify an AF_UNSPEC (i.e., uninitialized) * address, see if *_type() returns NULL. */ /* AF_UNSPEC(==0); ADDR = 0; PORT = 0, */ #ifdef ENDPOINT_TYPE extern const ip_endpoint endpoint_invalid; #else #define endpoint_invalid address_invalid #endif /* mutually exclusive */ #if 0 #define endpoint_is_invalid(A) (endpoint_type(A) == NULL) bool endpoint_is_any(const ip_endpoint *endpoint); #endif bool endpoint_is_specified(const ip_endpoint *endpoint); /* returns NULL when address_invalid */ const struct ip_info *endpoint_type(const ip_endpoint *endpoint); /* Host or Network byte order */ int endpoint_hport(const ip_endpoint *endpoint); int endpoint_nport(const ip_endpoint *endpoint); ip_endpoint set_endpoint_hport(const ip_endpoint *endpoint, int hport) MUST_USE_RESULT; #define update_endpoint_hport(ENDPOINT, HPORT) \ { *(ENDPOINT) = set_endpoint_hport(ENDPOINT, HPORT); } #define update_endpoint_nport(ENDPOINT, NPORT) \ { *(ENDPOINT) = set_endpoint_hport(ENDPOINT, ntohs(NPORT)); } /* currently forces port to zero */ ip_address endpoint_address(const ip_endpoint *endpoint); /* * conversions */ /* convert the endpoint to a sockaddr; return true size */ size_t endpoint_to_sockaddr(const ip_endpoint *endpoint, ip_sockaddr *sa); /* convert sockaddr to an endpoint */ err_t sockaddr_to_endpoint(const ip_sockaddr *sa, socklen_t sa_len, ip_endpoint *endpoint); /* * Old style. */ /* * XXX: compatibility. * * setportof() should be replaced by update_{subnet,endpoint}_nport(); * code is assuming ip_subnet.addr is an endpoint. */ #define portof(SRC) endpoint_nport((SRC)) #define setportof(PORT, DST) update_endpoint_nport(DST, PORT) #endif libreswan-3.32/include/ip_info.h000066400000000000000000000024201365625662500166640ustar00rootroot00000000000000/* XXX: header from name_constant.h */ #ifndef IP_INFO_H #define IP_INFO_H /* socket address family info */ #include "ip_address.h" #include "ip_subnet.h" struct ip_info { /* * ip_address */ unsigned ip_version; /* 4 or 6 */ const char *ip_name; size_t ip_size; /* 4 or 16 */ /* 0.0.0.0 or :: */ const ip_address any_address; /* 127.0.0.1 or ::1 */ const ip_address loopback_address; /* * ip_endpoint */ /* 0.0.0.0:0 or [::]:0 */ const ip_endpoint any_endpoint; /* * ip_subnet. */ int mask_cnt; /* 32 or 128 */ /* unspecified address - ::/128 or 0.0.0.0/32 - matches no addresses */ const ip_subnet no_addresses; /* default route - ::/0 or 0.0.0.0/0 - matches all addresses */ const ip_subnet all_addresses; /* * ike */ /* IPv4 and IPv6 have different fragment sizes */ unsigned ikev1_max_fragment_size; unsigned ikev2_max_fragment_size; /* * Sockaddr. */ int af; /* AF_INET or AF_INET6 */ const char *af_name; size_t sockaddr_size; /* sizeof(sockaddr_in) | sizeof(sockaddr_in6)? */ /* * ID stuff. */ uint8_t id_addr, id_subnet, id_range; }; extern const struct ip_info ipv4_info; extern const struct ip_info ipv6_info; extern const struct ip_info *aftoinfo(int af); const struct ip_info *ip_version_info(unsigned version); #endif libreswan-3.32/include/ip_protocol.h000066400000000000000000000050351365625662500175770ustar00rootroot00000000000000/* ip-protocols, for libreswan * * Copyright (C) 1998, 1999, 2000 Henry Spencer. * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. * */ #ifndef IP_PROTOCOL_H #define IP_PROTOCOL_H /* * What's being encapsulated using DST IP packets. * * See: * https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml * * Also see socket(IPPROTO_RAW). */ struct ip_protocol { const char *description; const char *prefix; const char *name; unsigned ikev1; #if 0 /* IKEv2 Security Protocol Identifiers */ /* https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xhtml#ikev2-parameters-18 */ unsigned ikev2; #endif /* https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml */ unsigned protoid; }; extern const struct ip_protocol ip_protocol_icmp; /* Internet Control Message */ extern const struct ip_protocol ip_protocol_ipip; /* IPv4 encapsulation */ extern const struct ip_protocol ip_protocol_esp; /* Encapsulated Security Payload */ extern const struct ip_protocol ip_protocol_ah; /* Authentication Header */ extern const struct ip_protocol ip_protocol_comp; /* IP Payload Compression Protocol */ extern const struct ip_protocol ip_protocol_int; /* any host internal protocol */ #if 0 # define SA_ESP 50 /* IPPROTO_ESP */ # define SA_AH 51 /* IPPROTO_AH */ # define SA_IPIP 4 /* IPPROTO_IPIP */ # define SA_COMP 108 /* IPPROTO_COMP */ # define SA_INT 61 /* IANA reserved for internal use */ #endif #if 0 enum eroute_type { ET_UNSPEC = 0, ET_AH = SA_AH, /* (51) authentication */ ET_ESP = SA_ESP, /* (50) encryption/auth */ ET_IPCOMP= SA_COMP, /* (108) compression */ ET_INT = SA_INT, /* (61) internal type */ ET_IPIP = SA_IPIP, /* (4) turn on tunnel type */ }; #endif const struct ip_protocol *protocol_by_prefix(const char *prefix); const struct ip_protocol *protocol_by_protoid(unsigned protoid); #endif libreswan-3.32/include/ip_range.h000066400000000000000000000035431365625662500170340ustar00rootroot00000000000000/* * header file for Libreswan library functions * Copyright (C) 1998, 1999, 2000 Henry Spencer. * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. * */ #ifndef IP_RANGE_H #define IP_RANGE_H #include "err.h" #include "ip_address.h" #include "ip_subnet.h" typedef struct { ip_address start; ip_address end; bool is_subnet; /* hint for jam_range */ } ip_range; /* caller knows best */ ip_range range(const ip_address *start, const ip_address *end); ip_range range_from_subnet(const ip_subnet *subnet); extern err_t ttorange(const char *src, const struct ip_info *afi, ip_range *dst); /* * Formatting */ typedef struct { char buf[sizeof(address_buf) + 1/*"-"*/ + sizeof(address_buf)]; } range_buf; void jam_range(struct lswlog *buf, const ip_range *range); const char *str_range(const ip_range *range, range_buf *buf); /* * Extract internals. */ const struct ip_info *range_type(const ip_range *r); #define range_is_invalid(R) (range_type(R) == NULL) bool range_is_specified(const ip_range *r); /* * Calculate the number of significant bits in the size of the range. * floor(lg(|high-low| + 1)) * * ??? this really should use ip_range rather than a pair of ip_address values */ int iprange_bits(ip_address low, ip_address high); extern bool range_size(ip_range *r, uint32_t *size); #endif libreswan-3.32/include/ip_said.h000066400000000000000000000055331365625662500166610ustar00rootroot00000000000000/* IP SAID (?), for libreswan * * Copyright (C) 1998, 1999, 2000 Henry Spencer. * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. * */ #ifndef IP_SAID_H #define IP_SAID_H #include "err.h" #include "ip_endpoint.h" #include "libreswan.h" /* for ipsec_spi_t */ #include "jambuf.h" #include "ip_protocol.h" /* * to identify an SA, we need */ typedef struct { /* * destination host; no port * * Per rfc2367, 2.3.3 Address Extension: The zeroing of ports * (e.g. sin_port and sin6_port) MUST be done for all messages * except for originating SADB_ACQUIRE messages, which SHOULD * fill them in with ports from the relevant TCP or UDP * session which generates the ACQUIRE message. */ ip_address dst; /* * 32-bit SPI, assigned by the destination host; or one of the * below magic values. * * This is in network order (but is manipulated like an int. * * XXX: Does this mean it is the SPI that the remote end * expects to see on its incomming packets? */ # define SPI_PASS 256 /* magic values... */ # define SPI_DROP 257 /* ...for use... */ # define SPI_REJECT 258 /* ...with SA_INT */ # define SPI_HOLD 259 # define SPI_TRAP 260 # define SPI_TRAPSUBNET 261 ipsec_spi_t spi; /* * protocol * * Don't confuse this with the IP version of the above * address. */ #define SA_ICMP &ip_protocol_unspec #define SA_IPIP &ip_protocol_ipip #define SA_ESP &ip_protocol_esp #define SA_AH &ip_protocol_ah #define SA_COMP &ip_protocol_comp #define SA_INT &ip_protocol_int const struct ip_protocol *proto; } ip_said; /* * Constructors */ ip_said said3(const ip_address *address, ipsec_spi_t spi/*network-byte-order*/, const struct ip_protocol *proto); /* * Formatting */ typedef struct { char buf[5 + ULTOT_BUF + 1 + sizeof(address_buf)]; } said_buf; void jam_said(jambuf_t *buf, const ip_said *said, int format); const char *str_said(const ip_said *said, int format, said_buf *buf); /* * Details. */ const struct ip_info *said_type(const ip_said *said); ip_address said_address(const ip_said *said); /* * old stype */ extern err_t ttosa(const char *src, size_t srclen, ip_said *dst); #define SATOT_BUF sizeof(said_buf) #endif libreswan-3.32/include/ip_sockaddr.h000066400000000000000000000023711365625662500175300ustar00rootroot00000000000000/* unix socaddr mashup, for libreswan * Copyright (C) 2019 Andrew Cagney * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. * */ #ifndef IP_SOCKADDR_H #define IP_SOCKADDR_H #include /* for struct sockaddr_in */ #ifdef HAVE_INET6_IN6_H #include /* for struct sockaddr_in6 */ #endif /* * Size the socaddr buffer big enough for all known * alternatives. On linux, at least, this isn't true: * * passert(sizeof(struct sockaddr) >= sizeof(struct sockaddr_in)); * passert(sizeof(struct sockaddr) >= sizeof(struct sockaddr_in6)); */ typedef union { /* sa.sa_* */ struct sockaddr sa; /* sin.sin_* */ struct sockaddr_in sin; /* sin6.sin6_* */ struct sockaddr_in6 sin6; } ip_sockaddr; #endif libreswan-3.32/include/ip_subnet.h000066400000000000000000000117061365625662500172400ustar00rootroot00000000000000/* ip subnet, for libreswan * * Copyright (C) 1998, 1999, 2000 Henry Spencer. * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs * Copyright (C) 2019 Andrew Cagney * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. * */ #ifndef IP_SUBNET_H #define IP_SUBNET_H /* * This is not the subnet you're looking for. * * In libreswan ip_subnet is used to store client routing information. * IKEv2 calls this traffic selectors and it allows the negotiation * of: * * LO_ADDRESS..HI_ADDRESS : LO_PORT..HI_PORT * * The structures below can only handle a limited subset of this, * namely: * * NETWORK_PREFIX | 0 / MASK : PORT * * where PORT==0 imples 0..65535, and (presumably) port can only be * non-zero when the NETWORK_PREFIX/MASK is for a single address. */ #ifdef SUBNET_TYPE #include "ip_address.h" #else #include "ip_endpoint.h" #endif #include "where.h" /* used by endtosubnet() */ struct lswlog; typedef struct { #ifdef SUBNET_TYPE /* * XXX: Data structure sufficient for IKEv2 */ ip_address lo_address, hi_address; uint16_t lo_hport, hi_hport; #else /* (routing)prefix|host(id):port */ ip_endpoint addr; /* (routing prefix) bits */ int maskbits; #endif } ip_subnet; /* * Constructors */ /* ADDRESS..ADDRESS:0..65535 */ ip_subnet subnet_from_address(const ip_address *address); /* ENDPOINT.ADDRESS..ENDPOINT.ADDRESS:ENDPOINT.PORT..ENDPOINT.PORT */ /* XXX: what hapens if ENDPOINT.PORT==0 */ ip_subnet subnet_from_endpoint(const ip_endpoint *endpoint); /* * Format as a string. */ typedef struct { char buf[sizeof(address_buf) + 4/*/NNN*/ + 6/*:65535*/]; } subnet_buf; extern const char *str_subnet(const ip_subnet *subnet, subnet_buf *out); extern const char *str_subnet_port(const ip_subnet *subnet, subnet_buf *out); extern void jam_subnet(struct lswlog *buf, const ip_subnet *subnet); extern void jam_subnet_port(struct lswlog *buf, const ip_subnet *subnet); /* * Extract details */ const struct ip_info *subnet_type(const ip_subnet *subnet); /* mutually exclusive */ /* not very well defined, is no_addresses "specified" */ extern const ip_subnet subnet_invalid; #if 0 #define subnet_is_invalid(S) (subnet_type(S) == NULL) #endif bool subnet_is_specified(const ip_subnet *subnet); /* default route - ::/0 or 0.0.0.0/0 - matches all addresses */ bool subnet_contains_all_addresses(const ip_subnet *subnet); /* unspecified address - ::/128 or 0.0.0.0/32 - matches no addresses */ bool subnet_contains_no_addresses(const ip_subnet *subnet); #if 0 /* ADDRESS..ADDRESS:0..65535 in SUBNET */ bool subnet_contains_address(const ip_subnet *subnet, const ip_address *address); /* ADDRESS..ADDRESS:PORT..PORT in SUBNET */ bool subnet_contains_endpoint(const ip_subnet *subnet, const ip_address *address); #endif /* h(ost) or n(etwork) ordered */ int subnet_hport(const ip_subnet *subnet); int subnet_nport(const ip_subnet *subnet); ip_subnet set_subnet_hport(const ip_subnet *subnet, int hport) MUST_USE_RESULT; #define update_subnet_hport(SUBNET, HPORT) \ { *(SUBNET) = set_subnet_hport(SUBNET, HPORT); } #define update_subnet_nport(SUBNET, NPORT) \ { *(SUBNET) = set_subnet_hport(SUBNET, ntohs(NPORT)); } /* when applied to an address, leaves just the routing prefix */ extern ip_address subnet_mask(const ip_subnet *subnet); /* Given ROUTING_PREFIX|HOST_ID return ROUTING_PREFIX|0 */ ip_address subnet_prefix(const ip_subnet *subnet); extern const struct ip_blit set_bits; extern const struct ip_blit clear_bits; extern const struct ip_blit keep_bits; ip_address subnet_blit(const ip_subnet *in, const struct ip_blit *network, const struct ip_blit *host); /* * old */ #include "err.h" extern err_t ttosubnet(const char *src, size_t srclen, int af, int clash, ip_subnet *dst); #define SUBNETTOT_BUF sizeof(subnet_buf) extern err_t initsubnet(const ip_address *addr, int maskbits, int clash, ip_subnet *dst); extern err_t endtosubnet(const ip_endpoint *end, ip_subnet *dst, where_t where); #define addrtosubnet(ADDR, DST) endtosubnet(ADDR, DST, HERE) /* misc. conversions and related */ extern err_t rangetosubnet(const ip_address *from, const ip_address *to, ip_subnet *dst); /* tests */ extern bool samesubnet(const ip_subnet *a, const ip_subnet *b); extern bool addrinsubnet(const ip_address *a, const ip_subnet *s); extern bool subnetinsubnet(const ip_subnet *a, const ip_subnet *b); extern bool subnetishost(const ip_subnet *s); #define subnetisaddr(sn, a) (subnetishost(sn) && addrinsubnet((a), (sn))) #endif libreswan-3.32/include/ipsec_saref.h000066400000000000000000000006141365625662500175270ustar00rootroot00000000000000/* Older patches used 22/23, but the kernel started using those, so we * bumped it to 30/31. Make sure you use the same number in the kernel * SAref patches and in the xl2tpd 'saref refinfo ' option */ #ifndef IP_IPSEC_REFINFO /* #define IP_IPSEC_REFINFO 22 */ #define IP_IPSEC_REFINFO 30 #endif #ifndef IP_IPSEC_BINDREF /* #define IP_IPSEC_BINDREF 23 */ #define IP_IPSEC_BINDREF 31 #endif libreswan-3.32/include/ipsecconf/000077500000000000000000000000001365625662500170435ustar00rootroot00000000000000libreswan-3.32/include/ipsecconf/confread.h000066400000000000000000000106511365625662500210000ustar00rootroot00000000000000/* Libreswan config file parser (confread.h) * * Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security * Copyright (C) 2009 Jose Quaresma * Copyright (C) 2003-2006 Michael Richardson * Copyright (C) 2012-2013 Paul Wouters * Copyright (C) 2013 Antony Antony * Coprright (C) 2016, Andrew Cagney * Copyright (C) 2019 D. Hugh Redelmeier * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef _IPSEC_CONFREAD_H_ #define _IPSEC_CONFREAD_H_ #include "ipsecconf/keywords.h" # define DEFAULT_UPDOWN "ipsec _updown" #include "lset.h" #include "err.h" #include "ip_range.h" #include "ip_subnet.h" #include "lswcdefs.h" #ifndef _LIBRESWAN_H #include #include "constants.h" #endif /* define an upper limit to number of times also= can be used */ #define ALSO_LIMIT 32 enum keyword_set { k_unset = FALSE, k_set = TRUE, k_default = 2 }; typedef char *ksf[KEY_STRINGS_ROOF]; typedef int knf[KEY_NUMERIC_ROOF]; typedef enum keyword_set str_set[KEY_STRINGS_ROOF]; typedef enum keyword_set int_set[KEY_NUMERIC_ROOF]; /* * Note: string fields in struct starter_end and struct starter_conn * should correspond to STR_FIELD calls in copy_conn_default() and confread_free_conn. */ struct starter_end { sa_family_t addr_family; enum keyword_host addrtype; enum keyword_host nexttype; ip_address addr, nexthop, sourceip; bool has_client; ip_subnet subnet, vti_ip; ip_subnet ifaceip; char *iface; char *id; enum keyword_authby authby; enum keyword_pubkey rsakey1_type, rsakey2_type; char *rsakey1; char *rsakey2; uint16_t port; uint8_t protocol; bool has_client_wildcard; bool key_from_DNS_on_demand; bool has_port_wildcard; char *virt; char *certx; char *ckaid; char *ca; char *updown; ip_range pool_range; /* store start of v4 addresspool */ ksf strings; knf options; str_set strings_set; int_set options_set; }; /* * Note: string fields in struct starter_end and struct starter_conn * should correspond to STR_FIELD calls in copy_conn_default() and confread_free_conn. */ struct starter_conn { TAILQ_ENTRY(starter_conn) link; struct starter_comments_list comments; char *name; char *connalias; ksf strings; knf options; str_set strings_set; int_set options_set; lset_t policy; lset_t sighash_policy; char **alsos; /* pointer to NULL-terminated array of strings */ struct starter_end left, right; unsigned long id; enum keyword_auto desired_state; enum { STATE_INVALID, STATE_LOADED, STATE_INCOMPLETE, STATE_ADDED, STATE_FAILED, } state; char *ike_crypto; char *esp; char *modecfg_dns; char *modecfg_domains; char *modecfg_banner; char *policy_label; char *conn_mark_both; char *conn_mark_in; char *conn_mark_out; char *vti_iface; char *redirect_to; char *accept_redirect_to; bool vti_routing; bool vti_shared; uint32_t xfrm_if_id; }; struct starter_config { struct { ksf strings; knf options; str_set strings_set; int_set options_set; } setup; /* conn %default */ struct starter_conn conn_default; char *ctlsocket; /* location of pluto control socket */ /* connections list (without %default) */ TAILQ_HEAD(, starter_conn) conns; }; /* * accumulate errors in this struct. * This is a string with newlines separating messages. * The string is heap-allocated so the caller is responsible * for freeing it. */ typedef struct { char *errors; } starter_errors_t; extern void starter_error_append(starter_errors_t *perrl, const char *fmt, ...) PRINTF_LIKE(2); extern struct config_parsed *parser_load_conf(const char *file, starter_errors_t *perr); extern void parser_free_conf(struct config_parsed *cfg); extern struct starter_config *confread_load(const char *file, starter_errors_t *perrl, const char *ctlsocket, bool setuponly); extern void confread_free(struct starter_config *cfg); #endif /* _IPSEC_CONFREAD_H_ */ libreswan-3.32/include/ipsecconf/confwrite.h000066400000000000000000000021531365625662500212150ustar00rootroot00000000000000/* Libreswan config file writer (confwrite.h) * * Copyright (C) 2004 Xelerance Corporation * Copyright (C) 2012 Paul Wouters * Copyright (C) 2013 D. Hugh Redelmeier * Copyright (C) 2016, Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef _IPSEC_CONFWRITE_H_ #define _IPSEC_CONFWRITE_H_ struct keyword_def; struct starter_config; void confwrite_list(FILE *out, char *prefix, int val, const struct keyword_def *k); void confwrite(struct starter_config *cfg, FILE *out, bool setup, char *conn, bool verbose); #endif /* _IPSEC_CONFWRITE_H_ */ libreswan-3.32/include/ipsecconf/exec.h000066400000000000000000000014241365625662500201410ustar00rootroot00000000000000/* Libreswan exec helper function (exec.h) * Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef _STARTER_EXEC_H_ #define _STARTER_EXEC_H_ int starter_exec(const char *fmt, ...); #endif /* _STARTER_EXEC_H_ */ libreswan-3.32/include/ipsecconf/interfaces.h000066400000000000000000000017601365625662500213430ustar00rootroot00000000000000/* Libreswan interfaces management (interfaces.h) * Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security * Copyright (C) 2005 Michael Richardson * Copyright (C) 2012 Paul Wouters * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef _STARTER_INTERFACES_H_ #define _STARTER_INTERFACES_H_ #include "ip_address.h" bool starter_iface_find(const char *iface, int af, ip_address *dst, ip_address *nh); #endif /* _STARTER_INTERFACES_H_ */ libreswan-3.32/include/ipsecconf/keywords.h000066400000000000000000000300601365625662500210620ustar00rootroot00000000000000/* Libreswan config file parser keywords processor * * Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security * Copyright (C) 2003-2007 Michael Richardson * Copyright (C) 2007-2008 Paul Wouters * Copyright (C) 2012-2013 Paul Wouters * Copyright (C) 2012 Kim B. Heino * Copyright (C) 2012 Philippe Vouters * Copyright (C) 2013 David McCullough * Copyright (C) 2013-2019 D. Hugh Redelmeier * Copyright (C) 2013-2018 Paul Wouters * Copyright (C) 2013-2016 Antony Antony * Copyright (C) 2016, Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #ifndef _KEYWORDS_H_ #define _KEYWORDS_H_ #include "lset.h" #ifndef _LIBRESWAN_H #include "libreswan.h" #include "constants.h" #endif #include /* * These are global configuration strings. * They only appear in "config setup" section. * Indices for .setup.strings[], .setup.strings_set[] */ enum keyword_string_config_field { KSF_INTERFACES, /* loose_enum eventually */ KSF_CURLIFACE, KSF_VIRTUALPRIVATE, KSF_SYSLOG, KSF_DUMPDIR, KSF_STATSBINARY, KSF_IPSECDIR, KSF_NSSDIR, KSF_SECRETSFILE, KSF_PERPEERDIR, KSF_MYVENDORID, KSF_LOGFILE, KSF_PLUTO_DNSSEC_ROOTKEY_FILE, KSF_PLUTO_DNSSEC_ANCHORS, KSF_PROTOSTACK, KSF_GLOBAL_REDIRECT, KSF_GLOBAL_REDIRECT_TO, KSF_LISTEN, KSF_OCSP_URI, KSF_OCSP_TRUSTNAME, KSF_ROOF }; /* * These are global config Bools (or numbers). * They only appear in "config setup" section. * Indices for .setup.option[], .setup.options_set[] */ enum keyword_numeric_config_field { KBF_FRAGICMP, KBF_HIDETOS, KBF_UNIQUEIDS, KBF_DO_DNSSEC, KBF_LOGTIME, KBF_LOGAPPEND, KBF_LOGIP, KBF_AUDIT_LOG, KBF_IKEPORT, KBF_IKEBUF, KBF_IKE_ERRQUEUE, KBF_PERPEERLOG, KBF_OVERRIDEMTU, KBF_XFRMLIFETIME, KBF_CRL_STRICT, KBF_CRL_CHECKINTERVAL, KBF_OCSP_STRICT, KBF_OCSP_ENABLE, KBF_OCSP_TIMEOUT, KBF_OCSP_CACHE_SIZE, KBF_OCSP_CACHE_MIN, KBF_OCSP_CACHE_MAX, KBF_OCSP_METHOD, KBF_CURLTIMEOUT, KBF_NATIKEPORT, KBF_SEEDBITS, KBF_DROP_OPPO_NULL, KBF_KEEPALIVE, KBF_KLIPSDEBUG, KBF_PLUTODEBUG, KBF_NHELPERS, KBF_SHUNTLIFETIME, KBF_FORCEBUSY, /* obsoleted for KBF_DDOS_MODE */ KBF_DDOS_IKE_THRESHOLD, KBF_MAX_HALFOPEN_IKE, KBF_SECCTX, /* security context attribute value for labeled ipsec */ KBF_NFLOG_ALL, /* Enable global nflog device */ KBF_DDOS_MODE, /* set DDOS mode */ KBF_SECCOMP, /* set SECCOMP mode */ KBF_ROOF }; /* * These are conn strings. * The initial ones come in left/right variants. * * NOTE: loose_enum values have both string and integer types * WITH THE SAME INDEX! They come in left and right= variants. * * Indices for .strings[], .strings_set[] * or .{left|right}.strings[], .{left|right}.strings_set[] */ enum keyword_string_conn_field { KSCF_IP, /* loose_enum */ /* left/right */ KSCF_NEXTHOP, /* loose_enum */ /* left/right */ KSCF_RSAKEY1, /* loose_enum */ /* left/right */ KSCF_RSAKEY2, /* loose_enum */ /* left/right */ KSCF_XFRM_IF_ID, KSCF_last_loose = KSCF_XFRM_IF_ID, KSCF_UPDOWN, /* left/right */ KSCF_ID, /* left/right */ KSCF_CERT, /* left/right */ KSCF_CKAID, /* left/right */ KSCF_CA, /* left/right */ KSCF_PROTOPORT, /* left/right */ KSCF_SOURCEIP, /* left/right */ KSCF_VTI_IP, /* left/right */ KSCF_INTERFACE_IP, /* left/right */ KSCF_USERNAME, /* left/right */ KSCF_ADDRESSPOOL, /* left/right */ KSCF_SUBNET, /* left/right */ KSCF_SUBNETS, /* left/right */ KSCF_last_leftright = KSCF_SUBNETS, KSCF_AUTHBY, KSCF_MODECFGDNS, KSCF_MODECFGDOMAINS, KSCF_IKE, KSCF_MODECFGBANNER, KSCF_ESP, KSCF_ALSO, KSCF_ALSOFLIP, KSCF_REDIRECT_TO, KSCF_ACCEPT_REDIRECT_TO, KSCF_CONNALIAS, KSCF_POLICY_LABEL, KSCF_CONN_MARK_BOTH, KSCF_CONN_MARK_IN, KSCF_CONN_MARK_OUT, KSCF_VTI_IFACE, KSCF_ROOF }; /* * conn numbers (or bool). * The initial ones come in left/right variants. * * NOTE: loose_enum values have both string and integer types * WITH THE SAME INDEX! They come in left and right= variants. * * Indices for .option[], .options_set[] * or .{left|right}.option[], .{left|right}.options_set[] */ enum keyword_numeric_conn_field { KNCF_IP = KSCF_IP, /* loose_enum */ /* left/right */ KNCF_NEXTHOP = KSCF_NEXTHOP, /* loose_enum */ /* left/right */ KNCF_RSAKEY1 = KSCF_RSAKEY1, /* loose_enum */ /* left/right */ KNCF_RSAKEY2 = KSCF_RSAKEY2, /* loose_enum */ /* left/right */ KNCF_XFRM_IF_ID = KSCF_XFRM_IF_ID, KNCF_XAUTHSERVER, /* left/right */ KNCF_XAUTHCLIENT, /* left/right */ KNCF_MODECONFIGSERVER, /* left/right */ KNCF_MODECONFIGCLIENT, /* left/right */ KNCF_CAT, /* left/right */ KNCF_SENDCERT, /* left/right */ KNCF_AUTH, /* left/right */ KNCF_last_leftright = KNCF_AUTH, KNCF_FIREWALL, KNCF_IDTYPE, KNCF_SPIBASE, KNCF_SPI, KNCF_ESPREPLAYWINDOW, /* ??? these were once in keyword_numeric_config_field (KBF prefix) */ KNCF_DPDACTION, KNCF_FAILURESHUNT, KNCF_NEGOTIATIONSHUNT, KNCF_TYPE, KNCF_MOBIKE, KNCF_CONNMTU, KNCF_PRIORITY, KNCF_TFCPAD, KNCF_REQID, KNCF_SEND_CA, KNCF_DPDDELAY, KNCF_DPDTIMEOUT, KNCF_METRIC, KNCF_PHASE2, KNCF_KEYEXCHANGE, KNCF_AUTO, KNCF_PFS, KNCF_SHA2_TRUNCBUG, KNCF_MSDH_DOWNGRADE, KNCF_SAN_ON_CERT, KNCF_DNS_MATCH_ID, KNCF_SALIFETIME, KNCF_REKEY, KNCF_REAUTH, KNCF_REKEYMARGIN, KNCF_REKEYFUZZ, KNCF_COMPRESS, KNCF_KEYINGTRIES, KNCF_REPLAY_WINDOW, KNCF_ARRIVALCHECK, KNCF_IKELIFETIME, KNCF_RETRANSMIT_TIMEOUT, KNCF_RETRANSMIT_INTERVAL_MS, KNCF_AGGRMODE, KNCF_MODECONFIGPULL, KNCF_ENCAPS, KNCF_IKEv2, KNCF_PPK, KNCF_ESN, KNCF_DECAP_DSCP, KNCF_NOPMTUDISC, KNCF_IKEv2_ALLOW_NARROWING, KNCF_IKEv2_PAM_AUTHORIZE, KNCF_SEND_REDIRECT, /* this and next word are used for IKEv2 Redirect Mechanism */ KNCF_ACCEPT_REDIRECT, /* see RFC 5685 for more details */ KNCF_HOSTADDRFAMILY, KNCF_CLIENTADDRFAMILY, KNCF_OVERLAPIP, /* Allow overlapping IPsec policies */ KNCF_REMOTEPEERTYPE, /* Cisco interop: remote peer type */ KNCF_NMCONFIGURED, /* Network Manager support */ KNCF_SAREFTRACK, /* saref tracking parameter for _updown */ KNCF_WARNIGNORE, /* to ignore obsoleted keywords */ KNCF_XAUTHBY, /* method of xauth user auth - file, pam or alwaysok */ KNCF_XAUTHFAIL, /* method of failing, soft or hard */ KNCF_IKE_FRAG, /* Enable support for IKE fragmentation */ KNCF_NAT_KEEPALIVE, /* per conn enabling/disabling of sending keep-alives */ KNCF_INITIAL_CONTACT, /* send initial contact VID */ KNCF_CISCO_UNITY, /* send cisco unity VID */ KNCF_NO_ESP_TFC, /* send ESP_TFC_PADDING_NOT_SUPPORTED */ KNCF_VID_STRONGSWAN, /* send strongswan VID (required for twofish/serpent) */ KNCF_SEND_VENDORID, /* per conn sending of our own libreswan vendorid */ KNCF_IKEPAD, /* pad IKE packets to 4 bytes */ KNCF_IKEV1_NATT, /* ikev1 NAT-T payloads to send/process */ KNCF_NFLOG_CONN, /* Enable per-conn nflog device */ KNCF_VTI_ROUTING, /* let updown do routing into VTI device */ KNCF_VTI_SHARED, /* VTI device is shared - enable checks and disable cleanup */ KNCF_NIC_OFFLOAD, /* xfrm offload to network device */ KNCF_ROOF }; /* * comparing members of two different enums draws warnings from GCC * so we cast one to int */ #define KEY_STRINGS_ROOF ((int)KSF_ROOF > KSCF_ROOF ? \ KSF_ROOF : KSCF_ROOF) #define KEY_NUMERIC_ROOF ((int)KBF_ROOF > KNCF_ROOF ? \ KBF_ROOF : KNCF_ROOF) /* these are bits set in a word */ enum keyword_valid { kv_config = LELEM(0), /* may be present in config section */ kv_conn = LELEM(1), /* may be present in conn section */ kv_leftright = LELEM(2), /* comes in leftFOO and rightFOO varients */ kv_alias = LELEM(5), /* is an alias for another keyword */ kv_policy = LELEM(6), /* is a policy affecting verb, processed specially */ kv_processed = LELEM(7), /* is processed, do not output literal string */ kv_duplicateok = LELEM(8), /* it is okay if also= items are duplicated */ }; #define KV_CONTEXT_MASK (kv_config | kv_conn | kv_leftright) /* values keyexchange= */ enum keyword_keyexchange { KE_NONE = 0, KE_IKE = 1, }; /* values for auto={add,start,route,ignore} */ enum keyword_auto { STARTUP_IGNORE = 0, STARTUP_POLICY = 1, STARTUP_ADD = 2, STARTUP_ONDEMAND = 3, STARTUP_START = 4 }; /* * Potential keyword values for fields like {left,right}rsasigkey=. * * This is internal to the config parser and doesn't belong in whack * or on the wire. */ enum keyword_pubkey { PUBKEY_NOTSET = 0, PUBKEY_DNSONDEMAND = 1, PUBKEY_CERTIFICATE = 2, PUBKEY_PREEXCHANGED = LOOSE_ENUM_OTHER, }; enum keyword_satype { KS_TUNNEL = 0, KS_TRANSPORT = 1, KS_PASSTHROUGH=2, KS_DROP = 3, KS_REJECT = 4, }; enum keyword_failure_shunt { KFS_FAIL_NONE, KFS_FAIL_PASS, KFS_FAIL_DROP, KFS_FAIL_REJECT }; enum keyword_negotiation_shunt { KNS_FAIL_PASS, KNS_FAIL_DROP }; enum keyword_type { kt_string, /* value is some string */ kt_appendstring, /* value is some string, append duplicates */ kt_appendlist, /* value is some list, append duplicates */ kt_filename, /* value is a filename string */ kt_dirname, /* value is a dir name string */ kt_bool, /* value is an on/off type */ kt_invertbool, /* value is an off/on type ("disable") */ kt_enum, /* value is from a set of key words */ kt_list, /* a set of values from a set of key words */ kt_lset, /* a set of values from an enum name */ kt_loose_enum, /* either a string, or a %-prefixed enum */ kt_rsakey, /* a key, or set of values */ kt_number, /* an integer */ kt_time, /* a number representing time */ kt_percent, /* a number representing percentage */ kt_range, /* ip address range 1.2.3.4-1.2.3.10 */ kt_ipaddr, /* an IP address */ kt_subnet, /* an IP address subnet */ kt_idtype, /* an ID type */ kt_bitstring, /* an encryption/authentication key */ kt_comment, /* a value that is a cooked comment */ kt_obsolete, /* option that is obsoleted, allow keyword but warn and ignore */ kt_obsolete_quiet, /* option that is obsoleted, allow keyword but don't bother warning */ }; struct keyword_def { const char *keyname; unsigned int validity; /* has bits from enum keyword_valid (kv_*) */ enum keyword_type type; unsigned int field; /* one of keyword_*_field */ const struct keyword_enum_values *validenum; const struct lmod_info *info; }; struct keyword { const struct keyword_def *keydef; bool keyleft; char *string; }; /* note: these lists are dynamic */ struct kw_list { struct kw_list *next; struct keyword keyword; char *string; unsigned int number; }; struct starter_comments { TAILQ_ENTRY(starter_comments) link; char *x_comment; char *commentvalue; }; TAILQ_HEAD(starter_comments_list, starter_comments); struct section_list { TAILQ_ENTRY(section_list) link; char *name; struct kw_list *kw; struct starter_comments_list comments; bool beenhere; }; struct config_parsed { struct kw_list *config_setup; TAILQ_HEAD(sectionhead, section_list) sections; int ipsec_conf_version; struct starter_comments_list comments; struct section_list conn_default; }; extern const struct keyword_def ipsec_conf_keywords[]; extern lset_t parser_lset(const struct keyword_def *kd, const char *s); extern unsigned int parser_enum_list(const struct keyword_def *kd, const char *s, bool list); extern unsigned int parser_loose_enum(struct keyword *k, const char *s); #endif /* _KEYWORDS_H_ */ libreswan-3.32/include/ipsecconf/klips.h000066400000000000000000000016051365625662500203400ustar00rootroot00000000000000/* Libreswan klips init/cleanup (klips.h) * Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef _STARTER_KLIPS_H_ #define _STARTER_KLIPS_H_ void starter_klips_cleanup(void); void starter_klips_clear(void); int starter_klips_init(void); int starter_klips_set_config(struct starter_config *); #endif /* _STARTER_KLIPS_H_ */ libreswan-3.32/include/ipsecconf/netkey.h000066400000000000000000000015671365625662500205240ustar00rootroot00000000000000/* Libreswan netkey init/cleanup (netkey.h) * Copyright (C) 2004 Xelerance Corporation * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef _STARTER_NETKEY_H_ #define _STARTER_NETKEY_H_ void starter_netkey_cleanup(void); void starter_netkey_clear(void); int starter_netkey_init(void); int starter_netkey_set_config(struct starter_config *); #endif /* _STARTER_NETKEY_H_ */ libreswan-3.32/include/ipsecconf/parser-controls.h000066400000000000000000000030231365625662500223470ustar00rootroot00000000000000/* Libreswan config file parser controls * This header is for code using libipsecconf. * * Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ /* things from parser.l */ #include /* for PATH_MAX */ extern int lex_verbosity; /* how much tracing output to show */ extern char rootdir[PATH_MAX]; /* when evaluating paths, prefix this to them */ extern char rootdir2[PATH_MAX]; /* when evaluating paths, alternatively prefix this to them */ /* things from parser.y */ extern void yyerror(const char *); /* defined in parser.y */ /* Dirty trick to dodge bison version differences. * Old bison (2.5) produces parser.tab.h without yydebug decl and no * multiple-inclusion protection. * New bison (2.6) is the opposite. * So: if the wrapper symbol is missing, do the declarations here. * Note: this header is sometimes included without parser.tab.h. */ #ifndef YY_YY_PARSER_TAB_H_INCLUDED extern int yydebug; /* declared in bison 2.6 parser.tab.h but not 2.5 */ #endif libreswan-3.32/include/ipsecconf/parser-flex.h000066400000000000000000000015001365625662500214400ustar00rootroot00000000000000/* exports from code generated by lex from parser.l * The generated code already declares these so it shouldn't include this header. * * Copyright (C) 2013 D. Hugh Redelmeier * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ /* declared and defined in lex.yy.c (output of flex) */ extern FILE *yyin; extern int yylex(void); libreswan-3.32/include/ipsecconf/parser.h000066400000000000000000000023041365625662500205070ustar00rootroot00000000000000/* Libreswan config file parser * This header is only for use by code within libipsecconf. * * Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef _IPSEC_PARSER_H_ #define _IPSEC_PARSER_H_ #include "constants.h" #include "libreswan.h" #include "parser.tab.h" /* generated by bison */ #include "parser-controls.h" #include "err.h" extern char *parser_cur_filename(void); extern int parser_cur_lineno(void); extern void parser_y_error(char *b, int size, const char *s); extern void parser_y_init(const char *name, FILE *f ); extern int parser_y_include(const char *filename); #define THIS_IPSEC_CONF_VERSION 2 #endif /* _IPSEC_PARSER_H_ */ libreswan-3.32/include/ipsecconf/parserlast.h000066400000000000000000000017161365625662500214010ustar00rootroot00000000000000/* Libreswan config file parser (parserlast.h) * Copyright (C) 2004 Michael Richardson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef _IPSEC_PARSERLAST_H_ #define _IPSEC_PARSERLAST_H_ /* this file depends upon YYSTYPE from parser.tab.h, which * means that it can't go into parser.h, which gets includes * before that file. */ extern int parser_find_keyword(const char *s, YYSTYPE *lval); #endif /* _IPSEC_PARSERLAST_H_ */ libreswan-3.32/include/ipsecconf/pluto.h000066400000000000000000000016611365625662500203630ustar00rootroot00000000000000/* Libreswan Pluto launcher (pluto.h) * Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef _STARTER_PLUTO_H_ #define _STARTER_PLUTO_H_ #define PLUTO_RESTART_DELAY 5 void starter_pluto_sigchild(pid_t pid); pid_t starter_pluto_pid(void); int starter_stop_pluto(void); int starter_start_pluto(struct starter_config *cfg, int debug); #endif /* _STARTER_PLUTO_H_ */ libreswan-3.32/include/ipsecconf/starterlog.h000066400000000000000000000022461365625662500214060ustar00rootroot00000000000000/* libipsecconf log and memory allocation functions * definitions: lib/libipsecconf/starterlog.c, lib/libipsecconf/alloc.c * * Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef _STARTER_LOG_H_ #define _STARTER_LOG_H_ #include "lswcdefs.h" #define LOG_LEVEL_INFO 1 #define LOG_LEVEL_ERR 2 #define LOG_LEVEL_DEBUG 3 extern void starter_log(int level, const char *fmt, ...) PRINTF_LIKE(2); extern void starter_use_log(bool debug, bool console, bool mysyslog); extern void *xmalloc(size_t s); extern char *xstrdup(const char *s); extern void *xrealloc(void *o, size_t s); #endif /* _STARTER_LOG_H_ */ libreswan-3.32/include/ipsecconf/starterwhack.h000066400000000000000000000022121365625662500217130ustar00rootroot00000000000000/* Libreswan whack functions to communicate with pluto (whack.h) * Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #ifndef _STARTER_WHACK_H_ #define _STARTER_WHACK_H_ struct starter_conn; struct starter_config; int starter_whack_add_conn(struct starter_config *cfg, const struct starter_conn *conn); int starter_whack_route_conn(struct starter_config *cfg, struct starter_conn *conn); int starter_whack_initiate_conn(struct starter_config *cfg, struct starter_conn *conn); extern int starter_whack_listen(struct starter_config *cfg); #endif /* _STARTER_WHACK_H_ */ libreswan-3.32/include/jambuf.h000066400000000000000000000143351365625662500165150ustar00rootroot00000000000000/* buffer for jamming strings into, for libreswan * * Copyright (C) 2017-2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #ifndef JAMBUF_H #define JAMBUF_H #include #include /* for va_list */ #include /* for uint8_t */ #include /* for size_t */ #include "lswcdefs.h" /* for PRINTF_LIKE */ #include "shunk.h" /* * jambuf_t provides a mechanism for accumulating formatted strings * into a string buffer, vis: * * jambuf_t buf = ...() -- see below * if (string != NULL) * jam(&buf, " string: %s", string); * if (i > 100) * jam(&buf, " large i: %d", i); * * Should there be too much output then it is truncated (leaving * "..."). */ /* * The jam buffer: * * ARRAY, a previously allocated array, containing the accumulated * NUL-terminated + CANARY-terminated output. * * ROOF: * * The offset of the the last character in the array. It contains a * canary intended to catch overflows. When sizeof(ARRAY) is needed, * ROOF should be used as otherwise the canary may be corrupted. * * ROOF < sizeof(ARRAY) * ARRAY[ROOF-0] = CANARY * ARRAY[ROOF-1] == '\0' * * TOTAL: * * The number of characters that should have been written to the * ARRAY. * * When TOTAL ARRAY[TOTAL] == '\0' * * When TOTAL>=ROOF, overflow has occured and no futher characters are * written. * * When TOTAL==ROOF-1 the buffer is full. Technically there is still * space for a string of length 0. However any larger string will * trigger the overflow code and the last few characters will be * overwritten with DOTS. */ typedef struct lswlog { char *array; size_t total; size_t roof; const char *dots; } jambuf_t; bool jambuf_ok(jambuf_t *buf); /* * Wrap a character array up in a jambuf_t so that it can be used to * accumulate strings. Simplify the common use: * * typedef struct { char buf[SIZE]; } TYPE_buf; * const char *str_TYPE(TYPE_t *t, TYPE_buf *out) { * jambuf_t buf = ARRAY_AS_JAMBUF(out->buf); * jam_...(&buf, ...); * return out->buf; * } */ jambuf_t array_as_jambuf(char *array, size_t sizeof_array); #define ARRAY_AS_JAMBUF(ARRAY) array_as_jambuf((ARRAY), sizeof(ARRAY)) /* * Assuming the jambuf is an array, poke around in the jambuf's * internal buffer. * * _as_shunk() returns the buffer contents (not including the trailing * '\0') so is useful for calls like fwrite(). * * _cursor() returns the current cursor position (where the next * string will be jammed); *cursor is always '\0'. */ shunk_t jambuf_as_shunk(jambuf_t *buf); const char *jambuf_cursor(jambuf_t *buf); /* * Assuming the jambuf is an array, save/restore the 'cursor'. * * See x509 code, where part way through scribbing all over the buf it * detects and error and throws everything away. */ typedef struct { size_t total; } jampos_t; jampos_t jambuf_get_pos(jambuf_t *buf); void jambuf_set_pos(jambuf_t *buf, const jampos_t *pos); /* * Routines for accumulating output in the jambuf buffer. * * If there is insufficient space, the output is truncated and "..." * is appended. * * Similar to C99 snprintf() et.al., these functions return the * untruncated size of output that the call would append (the value * can never be negative). * * While typically not useful, the return value does get used when * trying to pretty-print a table of values. */ size_t jam_va_list(jambuf_t *buf, const char *format, va_list ap); size_t jam_raw_bytes(jambuf_t *buf, const void *bytes, size_t nr_bytes); /* wrap above */ size_t jam(jambuf_t *buf, const char *format, ...) PRINTF_LIKE(2); size_t jam_char(jambuf_t *buf, char c); size_t jam_string(jambuf_t *buf, const char *string); size_t jam_jambuf(jambuf_t *buf, jambuf_t *in); /* * Utilities. */ /* _(in FUNC() at FILE:LINE) */ size_t jam_source_line(jambuf_t *buf, const char *func, const char *file, unsigned long line); /* _Errno E: */ size_t jam_errno(jambuf_t *buf, int e); /* * Jam a string of bytes formatted in some way. */ typedef size_t (jam_bytes_fn)(jambuf_t *buf, const void *bytes, size_t size); /* bytes as hex ... */ /* upper case hex - B1B2... */ jam_bytes_fn jam_HEX_bytes; /* lower case hex - b1b2... */ jam_bytes_fn jam_hex_bytes; /* hex bytes - b1 b2 b3 b4 b6 b6 b7 b8 - like DBG_dump */ jam_bytes_fn jam_dump_bytes; /* bytes as a string */ /* (isprint(b1) ? \NNN : b1)... */ jam_bytes_fn jam_sanitized_bytes; /* (ismeta(b1)) ? \NNN : b1)... */ jam_bytes_fn jam_meta_escaped_bytes; /* * Code wrappers that cover up the details of allocating, * initializing, de-allocating (and possibly logging) a 'struct * jambuf' buffer. * * BUF (a C variable name) is declared locally as a pointer to a * per-thread 'struct jambuf' buffer. * * Implementation notes: * * This implementation stores the output in an array on the thread's * stack. It could just as easily use the heap (but that would * involve memory overheads) or even a per-thread static variable. * Since the BUF variable is a pointer the specifics of the * implementation are hidden. * * This implementation, unlike DBG(), does not have a code block * parameter. Instead it uses a sequence of for-loops to set things * up for a code block. This avoids problems with "," within macro * parameters confusing the parser. It also permits a simple * consistent indentation style. * * The stack array is left largely uninitialized (just a few strategic * entries are set). This avoids the need to zero LOG_WITH bytes. * * Apparently chaining void function calls using a comma is valid C? */ /* * To debug, set this to printf or similar. */ extern int (*jambuf_debugf)(const char *format, ...) PRINTF_LIKE(1); #endif libreswan-3.32/include/kernel_alg.h000066400000000000000000000061521365625662500173520ustar00rootroot00000000000000/* Kernel algorithm DB, for libreswan * * Author: JuanJo Ciarlante * Copyright (C) 2013 Paul Wouters * Copyright (C) 2013 D. Hugh Redelmeier * Copyright (C) 2017-2018 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef KERNEL_ALG_H #define KERNEL_ALG_H /* * This is a database of algorithms supported by the kernel and, * hence, can be negotiated for ESP and AH. For instance, using * PF_KEY (rfc2367), it is theoretically possible to query the kernel * for supported algorithms and key sizes and use that to populate * this database. * * Of course reality steps in: * * - there's a race between the kernel loading a crypto module and * this database being populated (suspect it gets populated when the * first connection is initiated?) * * - there's often a gap between what PF_KEY returns and what the * kernel can support (linux works around this by hardwiring * entries) * * - there's often a gap between what the PF_KEY headers say is * supported and what the kernel supports (linux works around this * by having pluto local headers) * * - is there an XFRM way to query what the kernel supports? I * suspect linux still uses PF_KEY. * * - while PF_KEY returns key sizes (minbits, maxbits), the * information is ignored and instead the ike_alg DB is consulted * for this information (suspect that while PF_KEY was written to * support variable length keys only fix sized keys have ever been * used - 128 192 256 - and PF_KEY can't describe that * */ #include "libreswan/pfkeyv2.h" struct ike_alg; /* forward declaration */ struct alg_info; /* forward declaration */ struct esp_info; /* forward declaration */ struct alg_info_ike; /* forward declaration */ struct alg_info_esp; /* forward declaration */ struct dh_desc; struct encrypt_desc; struct integ_desc; extern bool kernel_alg_is_ok(const struct ike_alg *alg); extern bool kernel_alg_dh_ok(const struct dh_desc *dh); extern bool kernel_alg_encrypt_ok(const struct encrypt_desc *encrypt); extern bool kernel_alg_integ_ok(const struct integ_desc *integ); bool kernel_alg_encrypt_key_size(const struct encrypt_desc *encrypt, int keylen, size_t *key_size); int kernel_alg_encrypt_count(void); int kernel_alg_integ_count(void); const struct encrypt_desc **next_kernel_encrypt_desc(const struct encrypt_desc **last); const struct integ_desc **next_kernel_integ_desc(const struct integ_desc **last); extern void kernel_alg_init(void); void kernel_integ_add(const struct integ_desc *integ); void kernel_encrypt_add(const struct encrypt_desc *encrypt); #endif libreswan-3.32/include/kernel_sadb.h000066400000000000000000000027501365625662500175200ustar00rootroot00000000000000/* Kernel specific RFC 2367 - SADB algorithm routines, for libreswan * * Copyright (C) 2018 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef KERNEL_SADB_H #define KERNEL_SADB_H #include /* for size_t */ struct sadb_msg; struct sadb_alg; /* * Helper routines for code following RFC 2367 - PF_KEY - when * manipulating the kernel. * * This file is deliberately called ..._sadb and _not_ PF_KEY because: * * - all relevant structures have SADB as a prefix * * - PF_KEY can mean many things - the BSDs ship with a library while * linux seems to use code bundled with pluto * * - kernel_pfkey.[hc] is already taken */ /* * Multiplier for converting .sadb_msg_len (in 64-bit words) to * size_t. */ #define KERNEL_SADB_WORD_SIZE (64/8) /* Registration messages from pluto */ extern void kernel_add_sadb_algs(const struct sadb_msg *msg, size_t sizeof_msg); extern void kernel_add_sadb_alg(int satype, int exttype, const struct sadb_alg *sadb_alg); #endif libreswan-3.32/include/kernel_xfrm_reply.h000066400000000000000000000017411365625662500207750ustar00rootroot00000000000000/* * generic netlink receive message, for libreswan * * Copyright (C) 2012-2013 Kim B. Heino * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ ssize_t netlink_read_reply(int sock, char **pbuf, size_t bufsize, unsigned int seqnum, __u32 pid); /* * When reading data from netlink the final packet in each recvfrom() * will be truncated if it doesn't fit to buffer. Netlink returns up * to 32KiB of data so always keep that much free. */ #define NL_BUFMARGIN 32768 libreswan-3.32/include/keywords.h000066400000000000000000000074261365625662500171230ustar00rootroot00000000000000/* manifest constants * * Copyright (C) 1997 Angelos D. Keromytis. * Copyright (C) 1998-2002,2013 D. Hugh Redelmeier * Copyright (C) 2004-2008 Michael Richardson * Copyright (C) 2004-2009 Paul Wouters * Copyright (C) 2008 Antony Antony * Copyright (C) 2009 Avesh Agarwal * Copyright (C) 2012 Paul Wouters * Copyright (C) 2013 Tuomo Soini * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #ifndef KEYWORDS_H #define KEYWORDS_H #include /* for size_t */ #include "lswcdefs.h" /* for elemsof() */ #include "shunk.h" struct lswlog; /* * NAME<>VALUE map (but with bonus .details) * * We've already got enum_names, struct keyword_enum_values, and * sparse_name so why yet another another one? * * The two key differences are: * * - the new .details field * * - lookups return the map * * This way code listing values can easily include additional * information. For instance, a short description of each --impair * flag in help output. * * Once the dust has settled, this code can be merged with the other * name tables. * * For keyword_enum_values and sparse_names while things are straight * forward, it will churn the code - trying to add the new field to * the existing code resulted in lots of uninitialized field errors. * * For enum_names, things get more complex. But again, there really * shouldn't be so many NAME<>VALUE maps. */ struct keyword { const char *name; const char *sname; unsigned value; const char *details; }; struct keywords; const struct keyword *keyword_by_value(const struct keywords *keywords, unsigned value); const struct keyword *keyword_by_name(const struct keywords *keywords, shunk_t name); const struct keyword *keyword_by_sname(const struct keywords *keywords, shunk_t name); /* * logging short-cuts */ size_t lswlog_keyname(struct lswlog *buf, const struct keywords *keywords, unsigned value); size_t lswlog_keysname(struct lswlog *buf, const struct keywords *keywords, unsigned value); /* * "private" */ typedef const struct keyword *(keyword_by_value_fn)(const struct keywords *, unsigned); struct keywords { const struct keyword *values; size_t nr_values; keyword_by_value_fn *by_value; const char *name; }; /* * direct map: values[I].value == I IFF values[I].name!=NULL * * Can contain holes where .name==NULL. For instance, with an enum * starting at 1, values[0].name==NULL. */ keyword_by_value_fn keyword_by_value_direct; #define DIRECT_KEYWORDS(NAME, VALUES) { \ .values = VALUES, \ .nr_values = elemsof(VALUES), \ .by_value = keyword_by_value_direct, \ .name = (NAME), \ } /* * sorted map: binary search possible */ keyword_by_value_fn keyword_by_value_binary; #define SORTED_KEYWORDS(NAME, VALUES) { \ .values = VALUES, \ .nr_values = elemsof(VALUES), \ .by_value = keyword_by_value_binary, \ .name = (NAME), \ } /* * sparse map: linear search required */ keyword_by_value_fn keyword_by_value_linear; #define SPARSE_KEYWORDS(NAME, VALUES) { \ .values = VALUES, \ .nr_values = elemsof(VALUES), \ .by_value = keyword_by_value_linear, \ .name = (NAME), \ } #endif libreswan-3.32/include/klips-crypto/000077500000000000000000000000001365625662500175325ustar00rootroot00000000000000libreswan-3.32/include/klips-crypto/aes.h000066400000000000000000000071311365625662500204550ustar00rootroot00000000000000// I retain copyright in this code but I encourage its free use provided // that I don't carry any responsibility for the results. I am especially // happy to see it used in free and open source software. If you do use // it I would appreciate an acknowledgement of its origin in the code or // the product that results and I would also appreciate knowing a little // about the use to which it is being put. I am grateful to Frank Yellin // for some ideas that are used in this implementation. // // Dr B. R. Gladman 6th April 2001. // // This is an implementation of the AES encryption algorithm (Rijndael) // designed by Joan Daemen and Vincent Rijmen. This version is designed // to provide both fixed and dynamic block and key lengths and can also // run with either big or little endian internal byte order (see aes.h). // It inputs block and key lengths in bytes with the legal values being // 16, 24 and 32. /* * Modified by Jari Ruusu, May 1 2001 * - Fixed some compile warnings, code was ok but gcc warned anyway. * - Changed basic types: byte -> unsigned char, word -> u_int32_t * - Major name space cleanup: Names visible to outside now begin * with "aes_" or "AES_". A lot of stuff moved from aes.h to aes.c * - Removed C++ and DLL support as part of name space cleanup. * - Eliminated unnecessary recomputation of tables. (actual bug fix) * - Merged precomputed constant tables to aes.c file. * - Removed data alignment restrictions for portability reasons. * - Made block and key lengths accept bit count (128/192/256) * as well byte count (16/24/32). * - Removed all error checks. This change also eliminated the need * to preinitialize the context struct to zero. * - Removed some totally unused constants. */ #ifndef _AES_H #define _AES_H #if defined(__linux__) && defined(__KERNEL__) # include #else # include #endif // CONFIGURATION OPTIONS (see also aes.c) // // Define AES_BLOCK_SIZE to set the cipher block size (16, 24 or 32) or // leave this undefined for dynamically variable block size (this will // result in much slower code). // IMPORTANT NOTE: AES_BLOCK_SIZE is in BYTES (16, 24, 32 or undefined). If // left undefined a slower version providing variable block length is compiled #ifndef AES_BLOCK_SIZE #define AES_BLOCK_SIZE 16 #endif // The number of key schedule words for different block and key lengths // allowing for method of computation which requires the length to be a // multiple of the key length // // Nk = 4 6 8 // ------------- // Nb = 4 | 60 60 64 // 6 | 96 90 96 // 8 | 120 120 120 #define AES_KS_LENGTH (4 * AES_BLOCK_SIZE) #define AES_RC_LENGTH ((9 * AES_BLOCK_SIZE) / 8 - 8) typedef struct { u_int32_t aes_Nkey; // the number of words in the key input block u_int32_t aes_Nrnd; // the number of cipher rounds u_int32_t aes_e_key[AES_KS_LENGTH]; // the encryption key schedule u_int32_t aes_d_key[AES_KS_LENGTH]; // the decryption key schedule } aes_context; // THE CIPHER INTERFACE extern void aes_set_key(aes_context *, const unsigned char [], const int, const int); extern void aes_encrypt(const aes_context *, const unsigned char [], unsigned char []); extern void aes_decrypt(const aes_context *, const unsigned char [], unsigned char []); // The block length inputs to aes_set_block and aes_set_key are in numbers // of bytes or bits. The calls to subroutines must be made in the above // order but multiple calls can be made without repeating earlier calls // if their parameters have not changed. #endif // _AES_H libreswan-3.32/include/klips-crypto/aes_cbc.h000066400000000000000000000003531365625662500212630ustar00rootroot00000000000000/* Glue header */ #include "aes.h" int AES_set_key(aes_context *aes_ctx, const u_int8_t * key, int keysize); int AES_cbc_encrypt(aes_context *ctx, const u_int8_t * in, u_int8_t * out, int ilen, const u_int8_t * iv, int encrypt); libreswan-3.32/include/klips-crypto/des.h000066400000000000000000000261531365625662500204650ustar00rootroot00000000000000/* crypto/des/des.org */ /* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@cryptsoft.com). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are adhered to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@cryptsoft.com). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * 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 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@cryptsoft.com)" * The word 'cryptographic' can be left out if the routines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ /* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING * * Always modify des.org since des.h is automatically generated from * it during SSLeay configuration. * * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING */ #ifndef HEADER_DES_H #define HEADER_DES_H #ifdef __cplusplus extern "C" { #endif /* If this is set to 'unsigned int' on a DEC Alpha, this gives about a * %20 speed up (longs are 8 bytes, int's are 4). */ /* Must be unsigned int on ia64/Itanium or DES breaks badly */ #ifdef __KERNEL__ #include #else #include #endif #ifndef DES_LONG #define DES_LONG u_int32_t #endif typedef unsigned char des_cblock[8]; typedef struct { des_cblock ks; } des_key_schedule[16]; #define DES_KEY_SZ (sizeof(des_cblock)) #define DES_SCHEDULE_SZ (sizeof(des_key_schedule)) #define DES_ENCRYPT 1 #define DES_DECRYPT 0 #define DES_CBC_MODE 0 #define DES_PCBC_MODE 1 #define des_ecb2_encrypt(i, o, k1, k2, e) \ des_ecb3_encrypt((i), (o), (k1), (k2), (k1), (e)) #define des_ede2_cbc_encrypt(i, o, l, k1, k2, iv, e) \ des_ede3_cbc_encrypt((i), (o), (l), (k1), (k2), (k1), (iv), (e)) #define des_ede2_cfb64_encrypt(i, o, l, k1, k2, iv, n, e) \ des_ede3_cfb64_encrypt((i), (o), (l), (k1), (k2), (k1), (iv), (n), (e)) #define des_ede2_ofb64_encrypt(i, o, l, k1, k2, iv, n) \ des_ede3_ofb64_encrypt((i), (o), (l), (k1), (k2), (k1), (iv), (n)) #define C_Block des_cblock #define Key_schedule des_key_schedule #ifdef KERBEROS #define ENCRYPT DES_ENCRYPT #define DECRYPT DES_DECRYPT #endif #define KEY_SZ DES_KEY_SZ #define string_to_key des_string_to_key #define read_pw_string des_read_pw_string #define random_key des_random_key #define pcbc_encrypt des_pcbc_encrypt #define set_key des_set_key #define key_sched des_key_sched #define ecb_encrypt des_ecb_encrypt #define cbc_encrypt des_cbc_encrypt #define ncbc_encrypt des_ncbc_encrypt #define xcbc_encrypt des_xcbc_encrypt #define cbc_cksum des_cbc_cksum #define quad_cksum des_quad_cksum /* For compatibility with the MIT lib - eay 20/05/92 */ typedef des_key_schedule bit_64; #define des_fixup_key_parity des_set_odd_parity #define des_check_key_parity check_parity extern int des_check_key; /* defaults to false */ extern int des_rw_mode; /* defaults to DES_PCBC_MODE */ /* The next line is used to disable full ANSI prototypes, if your * compiler has problems with the prototypes, make sure this line always * evaluates to true :-) */ #if defined(MSDOS) || defined(__STDC__) #undef NOPROTO #endif #ifndef NOPROTO char *des_options(void); void des_ecb3_encrypt(des_cblock *input, des_cblock *output, des_key_schedule ks1, des_key_schedule ks2, des_key_schedule ks3, int enc); DES_LONG des_cbc_cksum(des_cblock *input, des_cblock *output, long length, des_key_schedule schedule, des_cblock *ivec); void des_cbc_encrypt(des_cblock *input, des_cblock *output, long length, des_key_schedule schedule, des_cblock *ivec, int enc); void des_ncbc_encrypt(des_cblock *input, des_cblock *output, long length, des_key_schedule schedule, des_cblock *ivec, int enc); void des_xcbc_encrypt(des_cblock *input, des_cblock *output, long length, des_key_schedule schedule, des_cblock *ivec, des_cblock *inw, des_cblock *outw, int enc); void des_cfb_encrypt(unsigned char *in, unsigned char *out, int numbits, long length, des_key_schedule schedule, des_cblock *ivec, int enc); void des_ecb_encrypt(des_cblock *input, des_cblock *output, des_key_schedule ks, int enc); void des_encrypt(DES_LONG *data, des_key_schedule ks, int enc); void des_encrypt2(DES_LONG *data, des_key_schedule ks, int enc); void des_encrypt3(DES_LONG *data, des_key_schedule ks1, des_key_schedule ks2, des_key_schedule ks3); void des_decrypt3(DES_LONG *data, des_key_schedule ks1, des_key_schedule ks2, des_key_schedule ks3); void des_ede3_cbc_encrypt(des_cblock *input, des_cblock *output, long length, des_key_schedule ks1, des_key_schedule ks2, des_key_schedule ks3, des_cblock *ivec, int enc); void des_ede3_cfb64_encrypt(unsigned char *in, unsigned char *out, long length, des_key_schedule ks1, des_key_schedule ks2, des_key_schedule ks3, des_cblock *ivec, int *num, int enc); void des_ede3_ofb64_encrypt(unsigned char *in, unsigned char *out, long length, des_key_schedule ks1, des_key_schedule ks2, des_key_schedule ks3, des_cblock *ivec, int *num); void des_xwhite_in2out(des_cblock (*des_key), des_cblock (*in_white), des_cblock (*out_white)); int des_enc_read(int fd, char *buf, int len, des_key_schedule sched, des_cblock *iv); int des_enc_write(int fd, char *buf, int len, des_key_schedule sched, des_cblock *iv); char *des_fcrypt(const char *buf, const char *salt, char *ret); void des_ofb_encrypt(unsigned char *in, unsigned char *out, int numbits, long length, des_key_schedule schedule, des_cblock *ivec); void des_pcbc_encrypt(des_cblock *input, des_cblock *output, long length, des_key_schedule schedule, des_cblock *ivec, int enc); DES_LONG des_quad_cksum(des_cblock *input, des_cblock *output, long length, int out_count, des_cblock *seed); void des_random_seed(des_cblock key); void des_random_key(des_cblock ret); int des_read_password(des_cblock *key, char *prompt, int verify); int des_read_2passwords(des_cblock *key1, des_cblock *key2, char *prompt, int verify); int des_read_pw_string(char *buf, int length, char *prompt, int verify); void des_set_odd_parity(des_cblock *key); int des_is_weak_key(des_cblock *key); int des_set_key(des_cblock *key, des_key_schedule schedule); int des_key_sched(des_cblock *key, des_key_schedule schedule); void des_string_to_key(char *str, des_cblock *key); void des_string_to_2keys(char *str, des_cblock *key1, des_cblock *key2); void des_cfb64_encrypt(unsigned char *in, unsigned char *out, long length, des_key_schedule schedule, des_cblock *ivec, int *num, int enc); void des_ofb64_encrypt(unsigned char *in, unsigned char *out, long length, des_key_schedule schedule, des_cblock *ivec, int *num); int des_read_pw(char *buf, char *buff, int size, char *prompt, int verify); /* Extra functions from Mark Murray */ /* The following functions are not in the normal unix build or the * SSLeay build. When using the SSLeay build, use RAND_seed() * and RAND_bytes() instead. */ int des_new_random_key(des_cblock *key); void des_init_random_number_generator(des_cblock *key); void des_set_random_generator_seed(des_cblock *key); void des_set_sequence_number(des_cblock new_sequence_number); void des_generate_random_block(des_cblock *block); #else char *des_options(); void des_ecb3_encrypt(); DES_LONG des_cbc_cksum(); void des_cbc_encrypt(); void des_ncbc_encrypt(); void des_xcbc_encrypt(); void des_cfb_encrypt(); void des_ede3_cfb64_encrypt(); void des_ede3_ofb64_encrypt(); void des_ecb_encrypt(); void des_encrypt(); void des_encrypt2(); void des_encrypt3(); void des_decrypt3(); void des_ede3_cbc_encrypt(); int des_enc_read(); int des_enc_write(); char *des_fcrypt(); #ifdef PERL5 char *des_crypt(); #else char *crypt(); #endif void des_ofb_encrypt(); void des_pcbc_encrypt(); DES_LONG des_quad_cksum(); void des_random_seed(); void des_random_key(); int des_read_password(); int des_read_2passwords(); int des_read_pw_string(); void des_set_odd_parity(); int des_is_weak_key(); int des_set_key(); int des_key_sched(); void des_string_to_key(); void des_string_to_2keys(); void des_cfb64_encrypt(); void des_ofb64_encrypt(); int des_read_pw(); void des_xwhite_in2out(); /* Extra functions from Mark Murray */ /* The following functions are not in the normal unix build or the * SSLeay build. When using the SSLeay build, use RAND_seed() * and RAND_bytes() instead. */ #ifdef FreeBSD int des_new_random_key(); void des_init_random_number_generator(); void des_set_random_generator_seed(); void des_set_sequence_number(); void des_generate_random_block(); #endif #endif #ifdef __cplusplus } #endif #endif libreswan-3.32/include/lex.h000066400000000000000000000026651365625662500160440ustar00rootroot00000000000000/* lexer (lexical analyzer) for control files * Copyright (C) 1998-2001 D. Hugh Redelmeier. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #define MAX_TOK_LEN 2048 /* includes terminal '\0' */ struct file_lex_position { int depth; /* how deeply we are nested */ const char *filename; FILE *fp; enum { B_none, B_record, B_file } bdry; /* current boundary */ int lino; /* line number in file */ char buffer[MAX_TOK_LEN + 1]; /* note: one extra char for our use (jamming '"') */ char *cur; /* cursor */ char under; /* except in shift(): character originally at *cur */ char *tok; struct file_lex_position *previous; }; extern struct file_lex_position *flp; extern bool lexopen(struct file_lex_position *new_flp, const char *name, bool optional); extern void lexclose(void); #define tokeq(s) (streq(flp->tok, (s))) #define tokeqword(s) strcaseeq(flp->tok, (s)) extern bool shift(void); extern bool flushline(const char *m); libreswan-3.32/include/libbsdkame/000077500000000000000000000000001365625662500171675ustar00rootroot00000000000000libreswan-3.32/include/libbsdkame/libpfkey.h000066400000000000000000000116661365625662500211570ustar00rootroot00000000000000/* I do not understand why this is not installed into /usr/include on FreeBSD */ /* $FreeBSD: src/lib/libipsec/libpfkey.h,v 1.4 2002/03/22 09:18:36 obrien Exp $ */ /* $KAME: libpfkey.h,v 1.6 2001/03/05 18:22:17 thorpej Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * 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. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #define K_SADB_EXT_MAX 24 struct sadb_msg; extern void pfkey_sadump(struct sadb_msg *); extern void pfkey_spdump(struct sadb_msg *); struct sockaddr; struct sadb_alg; int ipsec_check_keylen(unsigned, unsigned, unsigned); int ipsec_check_keylen2(unsigned, unsigned, unsigned); int ipsec_get_keylen(unsigned, unsigned, struct sadb_alg *); unsigned pfkey_set_softrate(unsigned, unsigned); unsigned pfkey_get_softrate(unsigned); int pfkey_send_getspi(int, unsigned, unsigned, struct sockaddr *, struct sockaddr *, uint32_t, uint32_t, uint32_t, uint32_t); int pfkey_send_update(int, unsigned, unsigned, struct sockaddr *, struct sockaddr *, uint32_t, uint32_t, unsigned, caddr_t, unsigned, unsigned, unsigned, unsigned, unsigned, uint32_t, uint64_t, uint64_t, uint64_t, uint32_t); int pfkey_send_add(int, unsigned, unsigned, struct sockaddr *, struct sockaddr *, uint32_t, uint32_t, unsigned, caddr_t, unsigned, unsigned, unsigned, unsigned, unsigned, uint32_t, uint64_t, uint64_t, uint64_t, uint32_t); int pfkey_send_delete(int, unsigned, unsigned, struct sockaddr *, struct sockaddr *, uint32_t); int pfkey_send_delete_all(int, unsigned, unsigned, struct sockaddr *, struct sockaddr *); int pfkey_send_get(int, unsigned, unsigned, struct sockaddr *, struct sockaddr *, uint32_t); int pfkey_send_register(int, unsigned); int pfkey_recv_register(int); int pfkey_set_supported(const struct sadb_msg *, int); int pfkey_send_flush(int, unsigned); int pfkey_send_dump(int, unsigned); int pfkey_send_promisc_toggle(int, int); int pfkey_send_spdadd(int, const struct sockaddr *, unsigned, const struct sockaddr *, unsigned, unsigned, caddr_t, int, uint32_t); int pfkey_send_spdadd2(int, struct sockaddr *, unsigned, struct sockaddr *, unsigned, unsigned, uint64_t, uint64_t, caddr_t, int, uint32_t); int pfkey_send_spdupdate(int, struct sockaddr *, unsigned, struct sockaddr *, unsigned, unsigned, caddr_t, int, uint32_t); int pfkey_send_spdupdate2(int, struct sockaddr *, unsigned, struct sockaddr *, unsigned, unsigned, uint64_t, uint64_t, caddr_t, int, uint32_t); int pfkey_send_spddelete(int, const struct sockaddr *, unsigned, const struct sockaddr *, unsigned, unsigned, caddr_t, int, uint32_t); int pfkey_send_spddelete2(int, uint32_t); int pfkey_send_spdget(int, uint32_t); int pfkey_send_spdsetidx(int, struct sockaddr *, unsigned, struct sockaddr *, unsigned, unsigned, caddr_t, int, uint32_t); int pfkey_send_spdflush(int); int pfkey_send_spddump(int); int pfkey_open(void); void pfkey_close(int); struct sadb_msg *pfkey_recv(int); int pfkey_send(int, struct sadb_msg *, int); int pfkey_align(struct sadb_msg *, caddr_t *); int pfkey_check(caddr_t *); /* like pfkey_send_add/update, but lets one specify the operation */ int pfkey_send_x1(int, unsigned, unsigned, unsigned, const struct sockaddr *, const struct sockaddr *, uint32_t, uint32_t, unsigned, caddr_t, unsigned, unsigned, unsigned, unsigned, unsigned, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t); extern void foreach_supported_alg(void (*algregister)(int satype, int extype, struct sadb_alg *alg)); libreswan-3.32/include/libreswan.h000066400000000000000000000133671365625662500172430ustar00rootroot00000000000000/* * header file for Libreswan library functions * Copyright (C) 1998, 1999, 2000 Henry Spencer. * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs * Copyright (C) 2019 Andrew Cagney * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. * */ #ifndef _LIBRESWAN_H #define _LIBRESWAN_H /* seen it, no need to see it again */ #include "err.h" #include #include #include /* * When using uclibc, malloc(0) returns NULL instead of success. This is * to make it use the inbuilt work-around. * See: http://osdir.com/ml/network.freeswan.devel/2003-11/msg00009.html */ #ifdef __UCLIBC__ # if !defined(__MALLOC_GLIBC_COMPAT__) && !defined(MALLOC_GLIBC_COMPAT) # warning Please compile uclibc with GLIBC_COMPATIBILITY defined # endif #endif #define DEBUG_NO_STATIC static #ifndef IPPROTO_COMP # define IPPROTO_COMP 108 #endif /* !IPPROTO_COMP */ #ifndef IPPROTO_INT # define IPPROTO_INT 61 #endif /* !IPPROTO_INT */ #if !defined(ESPINUDP_WITH_NON_IKE) #define ESPINUDP_WITH_NON_IKE 1 /* draft-ietf-ipsec-nat-t-ike-00/01 */ #define ESPINUDP_WITH_NON_ESP 2 /* draft-ietf-ipsec-nat-t-ike-02 */ #endif /* and the SA ID stuff */ typedef uint32_t ipsec_spi_t; /* * definitions for user space, taken linux/include/libreswan/ipsec_sa.h */ typedef uint32_t IPsecSAref_t; /* Translation to/from nfmark. * * use bits 16-31. Leave bit 32 as a indicate that IPsec processing * has already been done. */ #define IPSEC_SA_REF_TABLE_IDX_WIDTH 15 #define IPSEC_SA_REF_TABLE_OFFSET 16 #define IPSEC_SA_REF_MASK ((1u << IPSEC_SA_REF_TABLE_IDX_WIDTH) - 1u) #define IPSEC_NFMARK_IS_SAREF_BIT 0x80000000u #define IPsecSAref2NFmark(x) \ (((x) & IPSEC_SA_REF_MASK) << IPSEC_SA_REF_TABLE_OFFSET) #define NFmark2IPsecSAref(x) \ (((x) >> IPSEC_SA_REF_TABLE_OFFSET) & IPSEC_SA_REF_MASK) #define IPSEC_SAREF_NULL ((IPsecSAref_t)0u) /* Not representable as an nfmark */ #define IPSEC_SAREF_NA ((IPsecSAref_t)0xffff0001) /* * new IPv6-compatible functions */ /* text conversions */ extern err_t ttoul(const char *src, size_t srclen, int format, unsigned long *dst); extern err_t ttoulb(const char *src, size_t srclen, int format, unsigned long upb, unsigned long *dst); extern size_t ultot(unsigned long src, int format, char *buf, size_t buflen); #define ULTOT_BUF (22 + 1) /* holds 64 bits in octal */ extern size_t sin_addrtot(const void *sin, int format, char *dst, size_t dstlen); #define SAMIGTOT_BUF (16 + SATOT_BUF + ADDRTOT_BUF) extern err_t ttodata(const char *src, size_t srclen, int base, char *buf, size_t buflen, size_t *needed); extern err_t ttodatav(const char *src, size_t srclen, int base, char *buf, size_t buflen, size_t *needed, char *errp, size_t errlen, unsigned int flags); #define TTODATAV_BUF 40 /* ttodatav's largest non-literal message */ #define TTODATAV_IGNORESPACE (1 << 1) /* ignore spaces in base64 encodings */ #define TTODATAV_SPACECOUNTS 0 /* do not ignore spaces in base64 */ extern size_t datatot(const unsigned char *src, size_t srclen, int format, char *buf, size_t buflen); extern size_t keyblobtoid(const unsigned char *src, size_t srclen, char *dst, size_t dstlen); extern size_t splitkeytoid(const unsigned char *e, size_t elen, const unsigned char *m, size_t mlen, char *dst, size_t dstlen); #define KEYID_BUF 10 /* up to 9 text digits plus NUL */ extern err_t ttoprotoport(char *src, size_t src_len, u_int8_t *proto, u_int16_t *port, bool *has_port_wildcard); /* odds and ends */ extern const char *ipsec_version_code(void); extern const char *ipsec_version_vendorid(void); extern const char *ipsec_version_string(void); extern const char libreswan_vendorid[]; /* end of obsolete functions */ /* data types for SA conversion functions */ /* part extraction and special addresses */ extern struct in_addr subnetof(struct in_addr addr, struct in_addr mask ); extern struct in_addr hostof(struct in_addr addr, struct in_addr mask ); extern struct in_addr broadcastof(struct in_addr addr, struct in_addr mask ); /* * ENUM of klips debugging values. Not currently used in klips. * debug flag is actually 32 -bits, but only one bit is ever used, * so we can actually pack it all into a single 32-bit word. */ enum klips_debug_flags { KDF_VERBOSE = 0, KDF_XMIT = 1, KDF_NETLINK = 2, /* obsolete */ KDF_XFORM = 3, KDF_EROUTE = 4, KDF_SPI = 5, KDF_RADIJ = 6, KDF_ESP = 7, KDF_AH = 8, /* obsolete */ KDF_RCV = 9, KDF_TUNNEL = 10, KDF_PFKEY = 11, KDF_COMP = 12, KDF_NATT = 13, }; /* * pluto and lwdnsq need to know the maximum size of the commands to, * and replies from lwdnsq. */ #define LWDNSQ_CMDBUF_LEN 1024 #define LWDNSQ_RESULT_LEN_MAX 4096 /* syntax for passthrough SA */ #ifndef PASSTHROUGHNAME #define PASSTHROUGHNAME "%passthrough" #define PASSTHROUGH4NAME "%passthrough4" #define PASSTHROUGH6NAME "%passthrough6" #define PASSTHROUGHIS "tun0@0.0.0.0" #define PASSTHROUGH4IS "tun0@0.0.0.0" #define PASSTHROUGH6IS "tun0@::" #define PASSTHROUGHTYPE "tun" #define PASSTHROUGHSPI 0 #define PASSTHROUGHDST 0 #endif #endif /* _LIBRESWAN_H */ libreswan-3.32/include/libreswan/000077500000000000000000000000001365625662500170605ustar00rootroot00000000000000libreswan-3.32/include/libreswan/ipsec_ah.h000066400000000000000000000032621365625662500210070ustar00rootroot00000000000000/* * Authentication Header declarations * Copyright (C) 1996, 1997 John Ioannidis. * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include "ipsec_md5h.h" #include "ipsec_sha1.h" #ifndef IPPROTO_AH #define IPPROTO_AH 51 #endif /* IPPROTO_AH */ #include "ipsec_auth.h" #ifdef __KERNEL__ #ifndef CONFIG_XFRM_ALTERNATE_STACK extern struct inet_protocol ah_protocol; #endif /* CONFIG_XFRM_ALTERNATE_STACK */ struct options; struct ahhdr /* Generic AH header */ { __u8 ah_nh; /* Next header (protocol) */ __u8 ah_hl; /* AH length, in 32-bit words */ __u16 ah_rv; /* reserved, must be 0 */ __u32 ah_spi; /* Security Parameters Index */ __u32 ah_rpl; /* Replay prevention */ __u8 ah_data[AHHMAC_HASHLEN]; /* Authentication hash */ }; #define AH_BASIC_LEN 8 /* basic AH header is 8 bytes, nh,hl,rv,spi * and the ah_hl, says how many bytes after that * to cover. */ extern struct xform_functions ah_xform_funcs[]; #include "libreswan/ipsec_sysctl.h" #endif /* __KERNEL__ */ libreswan-3.32/include/libreswan/ipsec_auth.h000066400000000000000000000056221365625662500213620ustar00rootroot00000000000000/* * Authentication Header declarations * Copyright (C) 2003 Michael Richardson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include "ipsec_md5h.h" #include "ipsec_sha1.h" #ifndef IPSEC_AUTH_H #define IPSEC_AUTH_H #define AH_FLENGTH 12 /* size of fixed part */ #define AHMD5_KMAX 64 /* MD5 max 512 bits key */ #define AHMD5_AMAX 12 /* MD5 96 bits of authenticator */ #define AHMD596_KLEN 16 /* MD5 128 bits key */ #define AHSHA196_KLEN 20 /* SHA1 160 bits key */ #define AHMD596_ALEN 16 /* MD5 128 bits authentication length */ #define AHSHA196_ALEN 20 /* SHA1 160 bits authentication length */ #define AHMD596_BLKLEN 64 /* MD5 block length */ #define AHSHA196_BLKLEN 64 /* SHA1 block length */ #define AHSHA2_256_BLKLEN 64 /* SHA2-256 block length */ #define AHSHA2_384_BLKLEN 128 /* SHA2-384 block length (?) */ #define AHSHA2_512_BLKLEN 128 /* SHA2-512 block length */ #define AH_BLKLEN_MAX 128 /* keep up to date! */ #define AH_AMAX 64 /* increased for sha2_512 * keep up to date! */ #define AHHMAC_HASHLEN 12 /* authenticator length of 96bits */ #define AHHMAC_RPLLEN 4 /* 32 bit replay counter */ #define DB_AH_PKTRX 0x0001 #define DB_AH_PKTRX2 0x0002 #define DB_AH_DMP 0x0004 #define DB_AH_IPSA 0x0010 #define DB_AH_XF 0x0020 #define DB_AH_INAU 0x0040 #define DB_AH_REPLAY 0x0100 #ifdef __KERNEL__ /* General HMAC algorithm is described in RFC 2104 */ #define HMAC_IPAD 0x36 #define HMAC_OPAD 0x5C struct md5_ctx { MD5_CTX ictx; /* context after H(K XOR ipad) */ MD5_CTX octx; /* context after H(K XOR opad) */ }; struct sha1_ctx { SHA1_CTX ictx; /* context after H(K XOR ipad) */ SHA1_CTX octx; /* context after H(K XOR opad) */ }; struct auth_alg { void (*init)(void *ctx); void (*update)(void *ctx, unsigned char *bytes, __u32 len); void (*final)(unsigned char *hash, void *ctx); int hashlen; }; struct options; #endif /* __KERNEL__ */ #endif /* IPSEC_AUTH_H */ libreswan-3.32/include/libreswan/ipsec_encap.h000066400000000000000000000035541365625662500215110ustar00rootroot00000000000000/* * declarations relevant to encapsulation-like operations * Copyright (C) 1996, 1997 John Ioannidis. * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef _IPSEC_ENCAP_H_ #define SENT_IP4 0x01 /* match OpenBSD for what it's worth */ #define SENT_IP6 0x02 /* match OpenBSD for what it's worth */ struct sockaddr_encap { __u8 sen_len; /* length */ __u8 sen_family; /* AF_ENCAP */ __u16 sen_type; /* see SENT_* */ union { struct /* SENT_IP4 */ { struct in_addr Src; struct in_addr Dst; __u8 Proto; __u16 Sport; __u16 Dport; } Sip4; struct /* SENT_IP6 */ { struct in6_addr Src; struct in6_addr Dst; __u8 Proto; __u16 Sport; __u16 Dport; } Sip6; } Sen; } __attribute__((packed)); #define sen_ip_src Sen.Sip4.Src #define sen_ip_dst Sen.Sip4.Dst #define sen_proto Sen.Sip4.Proto #define sen_sport Sen.Sip4.Sport #define sen_dport Sen.Sip4.Dport #define sen_ip6_src Sen.Sip6.Src #define sen_ip6_dst Sen.Sip6.Dst #define sen_proto6 Sen.Sip6.Proto #define sen_sport6 Sen.Sip6.Sport #define sen_dport6 Sen.Sip6.Dport #ifndef AF_ENCAP #define AF_ENCAP 26 #endif /* AF_ENCAP */ #define _IPSEC_ENCAP_H_ #endif /* _IPSEC_ENCAP_H_ */ libreswan-3.32/include/libreswan/ipsec_esp.h000066400000000000000000000045241365625662500212100ustar00rootroot00000000000000/* * Copyright (C) 1996, 1997 John Ioannidis. * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include "libreswan/ipsec_md5h.h" #include "libreswan/ipsec_sha1.h" #include "klips-crypto/des.h" #ifndef IPPROTO_ESP #define IPPROTO_ESP 50 #endif /* IPPROTO_ESP */ #define ESP_HEADER_LEN 8 /* 64 bits header (spi+rpl)*/ #define EMT_ESPDESCBC_ULEN 20 /* coming from user mode */ #define EMT_ESPDES_KMAX 64 /* 512 bit secret key enough? */ #define EMT_ESPDES_KEY_SZ 8 /* 56 bit secret key with parity = 64 bits */ #define EMT_ESP3DES_KEY_SZ 24 /* 168 bit secret key with parity = 192 bits */ #define EMT_ESPDES_IV_SZ 8 /* IV size */ #define ESP_DESCBC_BLKLEN 8 /* DES-CBC block size */ #define ESP_IV_MAXSZ 16 /* This is _critical_ */ #define ESP_IV_MAXSZ_INT (ESP_IV_MAXSZ / sizeof(int)) #define DB_ES_PKTRX 0x0001 #define DB_ES_PKTRX2 0x0002 #define DB_ES_IPSA 0x0010 #define DB_ES_XF 0x0020 #define DB_ES_IPAD 0x0040 #define DB_ES_INAU 0x0080 #define DB_ES_OINFO 0x0100 #define DB_ES_OINFO2 0x0200 #define DB_ES_OH 0x0400 #define DB_ES_REPLAY 0x0800 #ifdef __KERNEL__ struct des_eks { des_key_schedule ks; }; #ifndef CONFIG_XFRM_ALTERNATE_STACK extern struct inet_protocol esp_protocol; extern struct inet6_protocol esp6_protocol; #endif /* CONFIG_XFRM_ALTERNATE_STACK */ struct options; struct esphdr { __u32 esp_spi; /* Security Parameters Index */ __u32 esp_rpl; /* Replay counter */ __u8 esp_iv[8]; /* iv */ }; extern struct xform_functions esp_xform_funcs[]; extern enum ipsec_rcv_value ipsec_rcv_esp_post_decrypt( struct ipsec_rcv_state *irs); extern int debug_esp; #endif /* __KERNEL__ */ libreswan-3.32/include/libreswan/ipsec_ipe4.h000066400000000000000000000016271365625662500212630ustar00rootroot00000000000000/* * IP-in-IP Header declarations * Copyright (C) 1996, 1997 John Ioannidis. * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ /* The packet header is an IP header! */ struct ipe4_xdata /* transform table data */ { struct in_addr i4_src; struct in_addr i4_dst; }; #define EMT_IPE4_ULEN 8 /* coming from user mode */ libreswan-3.32/include/libreswan/ipsec_md5h.h000066400000000000000000000015511365625662500212530ustar00rootroot00000000000000/* * The rest of this file is Copyright RSA DSI. See the following comments * for the full Copyright notice. */ #ifndef _IPSEC_MD5H_H_ #define _IPSEC_MD5H_H_ /* GLOBAL.H - RSAREF types and constants */ /* POINTER defines a generic pointer type */ typedef __u8 *POINTER; /* UINT4 defines a four byte word */ typedef __u32 UINT4; /* MD5.H - header file for MD5C.C */ /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. * * http://www.ietf.org/ietf-ftp/IPR/RSA-MD-all */ /* MD5 context. */ typedef struct { UINT4 state[4]; /* state (ABCD) */ UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ unsigned char buffer[64]; /* input buffer */ } MD5_CTX; void osMD5Init(void *); void osMD5Update(void *, unsigned char *, __u32); void osMD5Final(unsigned char [16], void *); #endif /* _IPSEC_MD5H_H_ */ libreswan-3.32/include/libreswan/ipsec_param.h000066400000000000000000000035261365625662500215220ustar00rootroot00000000000000/* * @(#) Libreswan tunable paramaters * * Copyright (C) 2001 Richard Guy Briggs * and Michael Richardson * Copyright (C) 2004 Michael Richardson * Copyright (C) 2012 Paul Wouters * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * */ /* * This file provides a set of #defines that may be tuned by various * people/configurations. It keeps all compile-time tunables in one place. * * This file should be included before all other IPsec kernel-only files. * */ #ifndef _IPSEC_PARAM_H_ /* * This is for the SA reference table. This number is related to the * maximum number of SAs that KLIPS can concurrently deal with, plus enough * space for keeping expired SAs around. * * TABLE_IDX_WIDTH is the number of bits that we will use. * MAIN_TABLE_WIDTH is the number of bits used for the primary index table. * */ #ifndef IPSEC_SA_REF_MAINTABLE_IDX_WIDTH # define IPSEC_SA_REF_MAINTABLE_IDX_WIDTH 4 #endif #ifndef IPSEC_SA_REF_FREELIST_NUM_ENTRIES # define IPSEC_SA_REF_FREELIST_NUM_ENTRIES 256 #endif #ifndef IPSEC_SA_REF_CODE # define IPSEC_SA_REF_CODE 1 #endif #ifdef NEED_INET_PROTOCOL #define inet_protocol net_protocol #endif #ifndef IPSEC_DEFAULT_TTL #define IPSEC_DEFAULT_TTL 64 #endif #define _IPSEC_PARAM_H_ #endif /* _IPSEC_PARAM_H_ */ libreswan-3.32/include/libreswan/ipsec_sa.h000066400000000000000000000264331365625662500210270ustar00rootroot00000000000000/* * @(#) Definitions of IPsec Security Association (ipsec_sa) * * Copyright (C) 2001, 2002, 2003 * Richard Guy Briggs * and Michael Richardson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * This file derived from ipsec_xform.h on 2001/9/18 by mcr. * */ /* * This file describes the IPsec Security Association Structure. * * This structure keeps track of a single transform that may be done * to a set of packets. It can describe applying the transform or * apply the reverse. (e.g. compression vs expansion). However, it * only describes one at a time. To describe both, two structures would * be used, but since the sides of the transform are performed * on different machines typically it is usual to have only one side * of each association. * */ #ifndef _IPSEC_SA_H_ #ifdef __KERNEL__ #include "libreswan/ipsec_stats.h" #include "libreswan/ipsec_life.h" #include "libreswan/ipsec_eroute.h" #endif /* __KERNEL__ */ #include "libreswan/ipsec_param.h" #include "libreswan/pfkeyv2.h" /* SAs are held in a table. * Entries in this table are referenced by IPsecSAref_t values. * IPsecSAref_t values are conceptually subscripts. Because * we want to allocate the table piece-meal, the subscripting * is implemented with two levels, a bit like paged virtual memory. * This representation mechanism is known as an Iliffe Vector. * * The Main table (AKA the refTable) consists of 2^IPSEC_SA_REF_MAINTABLE_IDX_WIDTH * pointers to subtables. * Each subtable has 2^IPSEC_SA_REF_SUBTABLE_IDX_WIDTH entries, each of which * is a pointer to an SA. * * An IPsecSAref_t contains either an exceptional value (signified by the * high-order bit being on) or a reference to a table entry. A table entry * reference has the subtable subscript in the low-order * IPSEC_SA_REF_SUBTABLE_IDX_WIDTH bits and the Main table subscript * in the next lowest IPSEC_SA_REF_MAINTABLE_IDX_WIDTH bits. * * The Maintable entry for an IPsecSAref_t x, a pointer to its subtable, is * IPsecSAref2table(x). It is of type struct IPsecSArefSubTable *. * * The pointer to the SA for x is IPsecSAref2SA(x). It is of type * struct ipsec_sa*. The macro definition clearly shows the two-level * access needed to find the SA pointer. * * The Maintable is allocated when IPsec is initialized. * Each subtable is allocated when needed, but the first is allocated * when IPsec is initialized. * * IPsecSAref_t is designed to be smaller than an NFmark so that * they can be stored in NFmarks and still leave a few bits for other * purposes. The spare bits are in the low order of the NFmark * but in the high order of the IPsecSAref_t, so conversion is required. * We pick the upper bits of NFmark on the theory that they are less likely to * interfere with more pedestrian uses of nfmark. */ typedef unsigned short int IPsecRefTableUnusedCount; #define IPSEC_SA_REF_TABLE_NUM_ENTRIES (1 << IPSEC_SA_REF_TABLE_IDX_WIDTH) #ifdef __KERNEL__ #define IPSEC_SA_REF_SUBTABLE_IDX_WIDTH \ (IPSEC_SA_REF_TABLE_IDX_WIDTH - IPSEC_SA_REF_MAINTABLE_IDX_WIDTH) #if IPSEC_SA_REF_SUBTABLE_IDX_WIDTH <= 0 #error "IPSEC_SA_REF_TABLE_IDX_WIDTH("IPSEC_SA_REF_TABLE_IDX_WIDTH") MUST be > IPSEC_SA_REF_MAINTABLE_IDX_WIDTH("IPSEC_SA_REF_MAINTABLE_IDX_WIDTH")" #endif #define IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES \ (1 << IPSEC_SA_REF_MAINTABLE_IDX_WIDTH) #define IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES \ (1 << IPSEC_SA_REF_SUBTABLE_IDX_WIDTH) #define IPSEC_SA_REF_SUBTABLE_SIZE \ (IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES * sizeof(struct ipsec_sa *)) #ifdef CONFIG_NETFILTER #define IPSEC_SA_REF_HOST_FIELD(x) ((struct sk_buff*)(x))->nfmark /* ??? typeof is a GCCism */ #define IPSEC_SA_REF_HOST_FIELD_TYPE typeof(IPSEC_SA_REF_HOST_FIELD(NULL)) #else /* CONFIG_NETFILTER */ /* just make it work for now, it doesn't matter, since there is no nfmark */ #define IPSEC_SA_REF_HOST_FIELD_TYPE unsigned long #endif /* CONFIG_NETFILTER */ #define IPSEC_SA_REF_HOST_FIELD_WIDTH \ (8 * sizeof(IPSEC_SA_REF_HOST_FIELD_TYPE)) #define IPSEC_SA_REF_FIELD_WIDTH (8 * sizeof(IPsecSAref_t)) #define IPSEC_SA_REF_MAX (~IPSEC_SAREF_NULL) #define IPSEC_SAREF_FIRST 1 /* from libreswan.h #define IPSEC_SA_REF_MASK (IPSEC_SA_REF_MAX >> (IPSEC_SA_REF_FIELD_WIDTH - IPSEC_SA_REF_TABLE_IDX_WIDTH)) */ #define IPSEC_SA_REF_TABLE_MASK \ (IPSEC_SA_REF_MAX \ >> (IPSEC_SA_REF_FIELD_WIDTH - IPSEC_SA_REF_MAINTABLE_IDX_WIDTH) \ << IPSEC_SA_REF_SUBTABLE_IDX_WIDTH) #define IPSEC_SA_REF_ENTRY_MASK \ (IPSEC_SA_REF_MAX \ >> (IPSEC_SA_REF_FIELD_WIDTH - IPSEC_SA_REF_SUBTABLE_IDX_WIDTH)) #define IPsecSAref2table(x) \ (((x) & IPSEC_SA_REF_TABLE_MASK) >> IPSEC_SA_REF_SUBTABLE_IDX_WIDTH) #define IPsecSAref2entry(x) ((x) & IPSEC_SA_REF_ENTRY_MASK) #define IPsecSArefBuild(x, y) (((x) << IPSEC_SA_REF_SUBTABLE_IDX_WIDTH) + (y)) #define IPsecSAref2SA(x) (ipsec_sadb.refTable[IPsecSAref2table(x)]->entry[ \ IPsecSAref2entry(x)]) #define IPsecSA2SAref(x) ((x)->ips_ref) #define IPsecSA2SArefhim(x) ((x)->ips_refhim) #define EMT_INBOUND 0x01 /* SA direction, 1=inbound */ /* 'struct ipsec_sa' should be 64bit aligned when allocated. */ struct ipsec_sa { atomic_t ips_refcount; /* reference count for this struct */ int ips_marked_deleted; /* used with reference counting */ IPsecSAref_t ips_ref; /* reference table entry number */ IPsecSAref_t ips_refhim; /* ref of paired SA, if any */ struct ipsec_sa *ips_next; /* pointer to next xform */ struct ipsec_sa *ips_prev; /* pointer to prev xform */ struct ipsec_sa *ips_hnext; /* next in hash chain */ struct ifnet *ips_rcvif; /* related rcv encap interface */ struct xform_functions *ips_xformfuncs; /* pointer to routines to process this SA */ struct net_device *ips_out; /* what interface to emerge on */ __u8 ips_transport_direct; /* if true, punt directly to * the protocol layer */ struct socket *ips_sock; /* cache of transport socket */ ip_said ips_said; /* SA ID */ __u32 ips_seq; /* seq num of msg that initiated this SA */ __u32 ips_pid; /* PID of process that initiated this SA */ __u8 ips_authalg; /* auth algorithm for this SA */ __u8 ips_encalg; /* enc algorithm for this SA */ struct ipsec_stats ips_errs; __u8 ips_replaywin; /* replay window size */ enum sadb_sastate ips_state; /* state of SA */ __u32 ips_replaywin_lastseq; /* last pkt sequence num */ __u64 ips_replaywin_bitmap; /* bitmap of received pkts */ __u32 ips_replaywin_maxdiff; /* max pkt sequence difference */ __u32 ips_flags; /* generic xform flags */ struct ipsec_lifetimes ips_life; /* lifetime records */ /* selector information */ __u8 ips_transport_protocol; /* protocol for this SA, if ports are involved */ struct sockaddr *ips_addr_s; /* src sockaddr */ struct sockaddr *ips_addr_d; /* dst sockaddr */ struct sockaddr *ips_addr_p; /* proxy sockaddr */ __u16 ips_addr_s_size; __u16 ips_addr_d_size; __u16 ips_addr_p_size; ip_address ips_flow_s; ip_address ips_flow_d; ip_address ips_mask_s; ip_address ips_mask_d; __u16 ips_key_bits_a; /* size of authkey in bits */ __u16 ips_auth_bits; /* size of authenticator in bits */ __u16 ips_key_bits_e; /* size of enckey in bits */ __u16 ips_iv_bits; /* size of IV in bits */ __u8 ips_iv_size; __u16 ips_key_a_size; __u16 ips_key_e_size; caddr_t ips_key_a; /* authentication key */ caddr_t ips_key_e; /* encryption key */ caddr_t ips_iv; /* Initialisation Vector */ struct ident ips_ident_s; /* identity src */ struct ident ips_ident_d; /* identity dst */ /* these are included even if CONFIG_KLIPS_IPCOMP is off */ __u16 ips_comp_adapt_tries; /* ipcomp self-adaption tries */ __u16 ips_comp_adapt_skip; /* ipcomp self-adaption to-skip */ __u64 ips_comp_ratio_cbytes; /* compressed bytes */ __u64 ips_comp_ratio_dbytes; /* decompressed (or uncompressed) bytes */ __u8 ips_natt_type; __u8 ips_natt_reserved[3]; __u16 ips_natt_sport; __u16 ips_natt_dport; struct sockaddr *ips_natt_oa; __u16 ips_natt_oa_size; __u16 ips_natt_reserved2; #if 0 __u32 ips_sens_dpd; __u8 ips_sens_sens_level; __u8 ips_sens_sens_len; __u64 *ips_sens_sens_bitmap; __u8 ips_sens_integ_level; __u8 ips_sens_integ_len; __u64 *ips_sens_integ_bitmap; #endif struct ipsec_alg_enc *ips_alg_enc; struct ipsec_alg_auth *ips_alg_auth; int ocf_in_use; int64_t ocf_cryptoid; # define IPSEC_REFALLOC 0 # define IPSEC_REFINTERN 1 # define IPSEC_REFSAADD 2 # define IPSEC_REFOTHER 3 # define IPSEC_REFPROC 4 # define IPSEC_REFTX 5 # define IPSEC_REFRX 6 # define IPSEC_REFSA 7 #if 0 /* IPSEC_SA_RECOUNT_DEBUG */ /* * define IPSEC_SA_RECOUNT_DEBUG to track recounts by use, makes * it a lot easier to determine problems with refcount and SA freeing */ # define IPSEC_SA_RECOUNT_DEBUG 1 unsigned char ips_track[IPSEC_REFSA + 1]; struct ipsec_sa *ips_raw; #endif }; struct IPsecSArefSubTable { struct ipsec_sa *entry[IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES]; }; struct ipsec_sadb { struct IPsecSArefSubTable *refTable[IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES]; IPsecSAref_t refFreeList[IPSEC_SA_REF_FREELIST_NUM_ENTRIES]; int refFreeListHead; int refFreeListTail; IPsecSAref_t refFreeListCont; IPsecSAref_t said_hash[SADB_HASHMOD]; spinlock_t sadb_lock; }; extern struct ipsec_sadb ipsec_sadb; extern int ipsec_sadb_init(void); extern struct ipsec_sa *ipsec_sa_alloc(int *error); /* pass in error var by pointer */ extern int ipsec_sa_free(struct ipsec_sa *ips); #define ipsec_sa_get(ips, type) __ipsec_sa_get(ips, __func__, __LINE__, \ type) extern struct ipsec_sa * __ipsec_sa_get(struct ipsec_sa *ips, const char *func, int line, int type); #define ipsec_sa_put(ips, type) __ipsec_sa_put(ips, __func__, __LINE__, \ type) extern void __ipsec_sa_put(struct ipsec_sa *ips, const char *func, int line, int type); extern int ipsec_sa_add(struct ipsec_sa *ips); extern void ipsec_sa_rm(struct ipsec_sa *ips); extern int ipsec_sadb_cleanup(__u8 proto); extern int ipsec_sadb_free(void); extern int ipsec_sa_wipe(struct ipsec_sa *ips); extern int ipsec_sa_intern(struct ipsec_sa *ips); extern struct ipsec_sa *ipsec_sa_getbyref(IPsecSAref_t ref, int type); extern void ipsec_sa_untern(struct ipsec_sa *ips); #endif /* __KERNEL__ */ enum ipsec_direction { ipsec_incoming = 1, ipsec_outgoing = 2 }; #define _IPSEC_SA_H_ #endif /* _IPSEC_SA_H_ */ libreswan-3.32/include/libreswan/ipsec_sha1.h000066400000000000000000000012311365625662500212450ustar00rootroot00000000000000/* * Here is the original comment from the distribution: SHA-1 in C By Steve Reid 100% Public Domain * Adapted for use by the IPSEC code by John Ioannidis */ #ifndef _IPSEC_SHA1_H_ #define _IPSEC_SHA1_H_ #ifdef __KERNEL__ # include #endif typedef struct { __u32 state[SHA1_DIGEST_SIZE / 4]; __u32 count[2]; __u8 buffer[SHA1_BLOCK_SIZE]; } SHA1_CTX; void SHA1Transform(__u32 state[5], __u8 buffer[SHA1_BLOCK_SIZE]); void SHA1Init(void *context); void SHA1Update(void *context, unsigned char *data, __u32 len); void SHA1Final(unsigned char digest[SHA1_DIGEST_SIZE], void *context); #endif /* _IPSEC_SHA1_H_ */ libreswan-3.32/include/libreswan/ipsec_tunnel.h000066400000000000000000000111771365625662500217300ustar00rootroot00000000000000/* * IPSEC tunneling code * Copyright (C) 1996, 1997 John Ioannidis. * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Richard Guy Briggs. * Copyright (C) 2006 Michael Richardson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ # define DEV_QUEUE_XMIT(skb, device, pri) { \ (skb)->dev = (device); \ neigh_compat_output(skb); \ /* (skb)->dst->output(skb); */ \ } # define ICMP_SEND(skb_in, type, code, info, dev) \ icmp_send((skb_in), (type), (code), htonl(info)) # define IP_SEND(skb, dev) \ ip_send(skb); #if defined(KLIPS) #define lsw_ip_hdr_version(ixirs) (((struct iphdr *) (ixirs)->iph)->version) #define lsw_ip4_hdr(ixirs) ((struct iphdr *) (ixirs)->iph) #define lsw_ip6_hdr(ixirs) ((struct ipv6hdr *) (ixirs)->iph) /* * Heavily based on drivers/net/new_tunnel.c. Lots * of ideas also taken from the 2.1.x version of drivers/net/shaper.c */ struct ipsectunnelconf { uint32_t cf_cmd; union { char cfu_name[12]; } cf_u; #define cf_name cf_u.cfu_name }; #define IPSEC_SET_DEV (SIOCDEVPRIVATE) #define IPSEC_DEL_DEV (SIOCDEVPRIVATE + 1) #define IPSEC_CLR_DEV (SIOCDEVPRIVATE + 2) #endif /* This is used for KLIPS as well as NETKEY */ #define IPSEC_UDP_ENCAP_CONVERT (SIOCDEVPRIVATE + 3) #ifdef __KERNEL__ #include #ifndef KERNEL_VERSION # define KERNEL_VERSION(x, y, z) (((x) << 16) + ((y) << 8) + (z)) #endif #define IPSECPRIV_MAGIC 0x15ECC0DE struct ipsecpriv { uint32_t magic; struct sk_buff_head sendq; struct net_device *dev; struct wait_queue *wait_queue; int vifnum; char locked; int (*hard_start_xmit) (struct sk_buff *skb, struct net_device *dev); #ifdef HAVE_NETDEV_HEADER_OPS const struct header_ops *header_ops; #else int (*hard_header) (struct sk_buff *skb, struct net_device *dev, unsigned short type, void *daddr, void *saddr, unsigned len); int (*rebuild_header)(struct sk_buff *skb); void (*header_cache_update)(struct hh_cache *hh, struct net_device *dev, unsigned char * haddr); #endif #ifdef USE_NETDEV_OPS const struct net_device_ops *saved_netdev_ops; struct net_device_ops netdev_ops; #endif int (*set_mac_address)(struct net_device *dev, void *addr); struct net_device_stats *(*get_stats)(struct net_device *dev); struct net_device_stats mystats; int mtu; /* What is the desired MTU? */ }; static inline struct ipsecpriv *netdev_to_ipsecpriv( const struct net_device *dev) { struct ipsecpriv *iprv = netdev_priv(dev); BUG_ON(!iprv); BUG_ON(iprv->magic != IPSECPRIV_MAGIC); return iprv; } extern char ipsec_tunnel_c_version[]; extern struct net_device *ipsecdevices[IPSEC_NUM_IFMAX]; extern int ipsecdevices_max; int ipsec_tunnel_init_devices(void); /* void */ int ipsec_tunnel_cleanup_devices(void); extern /* void */ int ipsec_init(void); extern int ipsec_tunnel_start_xmit(struct sk_buff *skb, struct net_device *dev); extern struct net_device *ipsec_get_device(int inst); extern int debug_tunnel; extern int sysctl_ipsec_debug_verbose; extern int lsw_ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, int target, unsigned short *fragoff); #ifdef CONFIG_KLIPS_IPV6 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34) # define ICMP6_SEND(skb_in, type, code, info, dev) \ icmpv6_send((skb_in), (type), (code), htonl(info), (dev)) #else # define ICMP6_SEND(skb_in, type, code, info, dev) \ icmpv6_send((skb_in), (type), (code), htonl(info)) #endif #endif /* CONFIG_KLIPS_IPV6 */ #endif /* __KERNEL__ */ #define DB_TN_INIT 0x0001 #define DB_TN_PROCFS 0x0002 #define DB_TN_XMIT 0x0010 #define DB_TN_OHDR 0x0020 #define DB_TN_CROUT 0x0040 #define DB_TN_OXFS 0x0080 #define DB_TN_REVEC 0x0100 #define DB_TN_ENCAP 0x0200 extern int ipsec_tunnel_deletenum(int vifnum); extern int ipsec_tunnel_createnum(int vifnum); extern struct net_device *ipsec_tunnel_get_device(int vifnum); /* manage ipsec xmit state objects */ extern int ipsec_xmit_state_cache_init(void); extern void ipsec_xmit_state_cache_cleanup(void); struct ipsec_xmit_state *ipsec_xmit_state_new(struct net_device *dev); void ipsec_xmit_state_delete(struct ipsec_xmit_state *ixs); libreswan-3.32/include/libreswan/ipsec_xform.h000066400000000000000000000167621365625662500215630ustar00rootroot00000000000000/* * Definitions relevant to IPSEC transformations * Copyright (C) 1996, 1997 John Ioannidis. * Copyright (C) 1998, 1999, 2000, 2001, 2017 Richard Guy Briggs * COpyright (C) 2003 Michael Richardson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #ifndef _IPSEC_XFORM_H_ #include #define XF_NONE 0 /* No transform set */ #define XF_IP4 1 /* IPv4 inside IPv4 */ #define XF_AHMD5 2 /* AH MD5 */ #define XF_AHSHA 3 /* AH SHA */ #define XF_ESP3DES 5 /* ESP DES3-CBC */ #define XF_AHHMACMD5 6 /* AH-HMAC-MD5 with opt replay prot */ #define XF_AHHMACSHA1 7 /* AH-HMAC-SHA1 with opt replay prot */ #define XF_ESP3DESMD5 9 /* triple DES, HMAC-MD-5, 128-bits of authentication */ #define XF_ESP3DESMD596 10 /* triple DES, HMAC-MD-5, 96-bits of authentication */ #define XF_ESPNULLMD596 12 /* NULL, HMAC-MD-5 with 96-bits of authentication */ #define XF_ESPNULLSHA196 13 /* NULL, HMAC-SHA-1 with 96-bits of authentication */ #define XF_ESP3DESSHA196 14 /* triple DES, HMAC-SHA-1, 96-bits of authentication */ #define XF_IP6 15 /* IPv6 inside IPv6 */ #define XF_COMPDEFLATE 16 /* IPCOMP deflate */ #define XF_COMPLZS 17 /* IPCOMP LZS */ #define XF_GET 124 /* Get SA current lifetimes */ /* * Manual connection support for modular algos (ipsec_alg) --Juanjo. */ #define XF_OTHER_ALG 125 /* define magic XF_ symbol for alg_infos */ #define XF_CLR 126 /* Clear SA table */ #define XF_DEL 127 /* Delete SA */ /* IPsec AH transform values * RFC 2407 * draft-ietf-ipsec-doi-tc-mib-02.txt */ /* why are these hardcoded here? See ipsec_policy.h for their enums -- Paul*/ /* ---------- These really need to go from here ------------------ */ #define AH_NONE 0 #define AH_MD5 2 #define AH_SHA 3 /* draft-ietf-ipsec-ciph-aes-cbc-03.txt */ #define AH_SHA2_256 5 #define AH_SHA2_384 6 #define AH_SHA2_512 7 #define AH_RIPEMD 8 #define AH_AES 9 #define AH_RSA 10 /* RFC4359 */ #define AH_AES_128_GMAC 11 /* RFC4543 [Errata1821] */ #define AH_AES_192_GMAC 12 /* RFC4543 [Errata1821] */ #define AH_AES_256_GMAC 13 /* RFC4543 [Errata1821] */ #define AH_NULL 251 #define AH_SHA2_256_TRUNC 252 /* used for broken linux kernel behaviour */ #define AH_MAX 255 /* note Authentication Algorithm (Value 5) Reference: [RFC2407] has * two octets but IPSEC AH Transform Identifiers has one octet! */ /* IPsec ESP transform values */ #define ESP_NONE 0 #define ESP_DES_IV64 1 #define ESP_DES 2 /* obsoleted */ #define ESP_3DES 3 #define ESP_RC5 4 #define ESP_IDEA 5 #define ESP_CAST 6 #define ESP_BLOWFISH 7 /* obsoleted */ #define ESP_3IDEA 8 #define ESP_DES_IV32 9 #define ESP_RC4 10 #define ESP_NULL 11 #define ESP_AES 12 /* was draft-ietf-ipsec-ciph-aes-cbc-02.txt, now RFC-3602 */ #define ESP_AES_CTR 13 #define ESP_AES_CCM_A 14 #define ESP_AES_CCM_B 15 #define ESP_AES_CCM_C 16 #define ESP_ID17_UNASSIGNED 17 #define ESP_AES_GCM_A 18 #define ESP_AES_GCM_B 19 #define ESP_AES_GCM_C 20 #define ESP_SEED_CBC 21 #define ESP_CAMELLIA 22 #define ESP_NULL_AUTH_AES_GMAC 23 /* [RFC4543][Errata1821] */ /* 24 - 248 Unassigned */ #define ESP_MARS 249 #define ESP_RC6 250 #define ESP_SERPENT 252 #define ESP_TWOFISH 253 #define ESP_MAX 255 /* one octet, not two */ /* IPCOMP transform values */ #define IPCOMP_NONE 0 #define IPCOMP_OUI 1 #define IPCOMP_DEFLATE 2 #define IPCOMP_LZS 3 #define IPCOMP_V42BIS 4 #define XFT_AUTH 0x0001 #define XFT_CONF 0x0100 #define PROTO2TXT(x) \ (x) == IPPROTO_AH ? "AH" : \ (x) == IPPROTO_ESP ? "ESP" : \ (x) == IPPROTO_IPIP ? "IPIP" : \ (x) == IPPROTO_COMP ? "COMP" : \ "UNKNOWN_proto" /* BEWARE: result may be in a static buffer */ static inline const char *enc_name_id(unsigned id) { static char buf[16]; snprintf(buf, sizeof(buf), "_ID%d", id); return buf; } /* BEWARE: result may be in a static buffer */ static inline const char *auth_name_id(unsigned id) { static char buf[16]; snprintf(buf, sizeof(buf), "_ID%d", id); return buf; } #define IPS_XFORM_NAME(x) \ PROTO2TXT((x)->ips_said.proto), \ (x)->ips_said.proto == IPPROTO_COMP ? \ ((x)->ips_encalg == SADB_X_CALG_NONE ? "_NONE" : \ (x)->ips_encalg == SADB_X_CALG_DEFLATE ? "_DEFLATE" : \ (x)->ips_encalg == SADB_X_CALG_LZS ? "_LZS" : \ "_UNKNOWN_comp") : \ (x)->ips_encalg == ESP_NONE ? "" : \ (x)->ips_encalg == ESP_NULL ? "_NULL" : \ /* ESP_DES left out on purpose */ \ (x)->ips_encalg == ESP_3DES ? "_3DES" : \ (x)->ips_encalg == ESP_AES ? "_AES" : \ (x)->ips_encalg == ESP_SERPENT ? "_SERPENT" : \ (x)->ips_encalg == ESP_TWOFISH ? "_TWOFISH" : \ enc_name_id((x)->ips_encalg) /* "_UNKNOWN_encr" */, \ (x)->ips_authalg == AH_NONE ? "" : \ (x)->ips_authalg == AH_MD5 ? "_HMAC_MD5" : \ (x)->ips_authalg == AH_SHA ? "_HMAC_SHA1" : \ (x)->ips_authalg == AH_SHA2_256 ? "_HMAC_SHA2_256" : \ (x)->ips_authalg == AH_SHA2_384 ? "_HMAC_SHA2_384" : \ (x)->ips_authalg == AH_SHA2_512 ? "_HMAC_SHA2_512" : \ auth_name_id((x)->ips_authalg) /* "_UNKNOWN_auth" */ \ #ifdef __KERNEL__ #include struct ipsec_rcv_state; struct ipsec_xmit_state; struct xform_functions { u8 protocol; enum ipsec_rcv_value (*rcv_checks)(struct ipsec_rcv_state *irs, struct sk_buff *skb); enum ipsec_rcv_value (*rcv_decrypt)(struct ipsec_rcv_state *irs); enum ipsec_rcv_value (*rcv_setup_auth)(struct ipsec_rcv_state *irs, struct sk_buff *skb, __u32 *replay, unsigned char **authenticator); enum ipsec_rcv_value (*rcv_calc_auth)(struct ipsec_rcv_state *irs, struct sk_buff *skb); enum ipsec_xmit_value (*xmit_setup)(struct ipsec_xmit_state *ixs); enum ipsec_xmit_value (*xmit_encrypt)(struct ipsec_xmit_state *ixs); enum ipsec_xmit_value (*xmit_setup_auth)(struct ipsec_xmit_state *ixs, struct sk_buff *skb, __u32 *replay, unsigned char **authenticator); enum ipsec_xmit_value (*xmit_calc_auth)(struct ipsec_xmit_state *ixs, struct sk_buff *skb); int xmit_headroom; int xmit_needtailroom; }; #endif /* __KERNEL__ */ extern void ipsec_dmp(char *s, caddr_t bb, int len); #define _IPSEC_XFORM_H_ #endif /* _IPSEC_XFORM_H_ */ libreswan-3.32/include/libreswan/passert.h000066400000000000000000000033021365625662500207100ustar00rootroot00000000000000/* * Panic, for libreswan. * * Copyright (C) 1998-2002 D. Hugh Redelmeier. * Copyright (C) 2003 Michael Richardson * Copyright (C) 2013 Paul Wouters * Copyright (C) 2015-2016 Andrew Cagney * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. */ #ifndef _LIBRESWAN_PASSERT_H #define _LIBRESWAN_PASSERT_H #include /* for strrchr() */ #include #include "err.h" /* for err_t */ #include "lswcdefs.h" /* for NEVER_RETURNS PRINTF_LIKE() */ #include "where.h" /* our versions of assert: log result */ extern void lsw_passert_fail(where_t where, const char *fmt, ...) NEVER_RETURNS PRINTF_LIKE(2); #define PASSERT_FAIL(FMT, ...) \ lsw_passert_fail(HERE, FMT, __VA_ARGS__) #define passert(ASSERTION) { \ /* wrapping ASSERTION in parens suppresses -Wparen */ \ bool assertion__ = ASSERTION; /* no parens */ \ if (!assertion__) { \ PASSERT_FAIL("%s", #ASSERTION); \ } \ } /* evaluate x exactly once; assert that err_t result is NULL; */ #define happy(x) { \ err_t ugh = x; \ if (ugh != NULL) { \ PASSERT_FAIL("%s", ugh); \ } \ } #endif /* _LIBRESWAN_PASSERT_H */ libreswan-3.32/include/libreswan/pfkey.h000066400000000000000000000234051365625662500203530ustar00rootroot00000000000000/* * Libreswan specific PF_KEY headers * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs. * Copyright (C) 2006-2007 Michael Richardson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef __NET_IPSEC_PF_KEY_H #define __NET_IPSEC_PF_KEY_H #include "pfkeyv2.h" #include #include "libreswan.h" /* for IPsecSAref_t */ #ifdef __KERNEL__ extern struct proto_ops pfkey_proto_ops; typedef struct sock pfkey_sock; extern int debug_pfkey; extern /* void */ int pfkey_init(void); extern /* void */ int pfkey_cleanup(void); extern int pfkey_registered_show(struct seq_file *seq, void *offset); extern int pfkey_supported_show(struct seq_file *seq, void *offset); extern int pfkey_show(struct seq_file *seq, void *offset); #ifdef HAVE_USER_NS extern uint32_t pfkey_kuid_to_uid(kuid_t kuid); #endif struct socket_list { struct socket *socketp; struct socket_list *next; }; extern int pfkey_list_insert_socket(struct socket *, struct socket_list **); extern struct socket_list *pfkey_open_sockets; extern struct socket_list *pfkey_registered_sockets[]; struct ipsec_alg_supported { uint16_t ias_exttype; uint8_t ias_id; uint8_t ias_ivlen; uint16_t ias_keyminbits; uint16_t ias_keymaxbits; const char *ias_name; }; extern struct supported_list *pfkey_supported_list[]; struct supported_list { struct ipsec_alg_supported *supportedp; struct supported_list *next; }; extern int pfkey_list_insert_supported(struct ipsec_alg_supported *, struct supported_list **); extern int pfkey_list_remove_supported(struct ipsec_alg_supported *, struct supported_list **); struct sockaddr_key { uint16_t key_family; /* PF_KEY */ uint16_t key_pad; /* not used */ uint32_t key_pid; /* process ID */ }; struct pfkey_extracted_data { struct ipsec_sa *ips; struct ipsec_sa *ips2; struct eroute *eroute; int outif; IPsecSAref_t sarefme; IPsecSAref_t sarefhim; }; /* forward reference */ struct sadb_ext; struct sadb_msg; struct sockaddr; struct sadb_comb; struct sadb_sadb; struct sadb_alg; extern int pfkey_alloc_eroute(struct eroute **eroute); extern int pfkey_sa_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr); extern int pfkey_lifetime_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr); extern int pfkey_address_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr); extern int pfkey_key_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr); extern int pfkey_ident_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr); extern int pfkey_sens_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr); extern int pfkey_prop_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr); extern int pfkey_supported_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr); extern int pfkey_spirange_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr); extern int pfkey_x_kmprivate_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr); extern int pfkey_x_satype_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr); extern int pfkey_x_debug_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr); extern int pfkey_upmsg(struct socket *, struct sadb_msg *); extern int pfkey_upmsgsk(struct sock *, struct sadb_msg *); extern int pfkey_expire(struct ipsec_sa *, int); extern int pfkey_acquire(struct ipsec_sa *); #endif /* __KERNEL__ */ extern const struct ip_protocol *satype2proto(uint8_t satype); extern uint8_t proto2satype(const struct ip_protocol *proto); extern char *satype2name(uint8_t satype); struct key_opt { uint32_t key_pid; /* process ID */ struct sock *sk; }; #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) # define key_pid(sk) ((struct key_opt*)&((sk)->sk_user_data))->key_pid #else # define key_pid(sk) ((struct key_opt*)&((sk)->sk_protinfo))->key_pid #endif /* XXX-mcr this is not an alignment, this is because the count is in 64-bit * words. */ #define IPSEC_PFKEYv2_ALIGN (sizeof(uint64_t) / sizeof(uint8_t)) #define BITS_PER_OCTET 8 #define OCTETBITS 8 #define PFKEYBITS 64 #define DIVUP(x, y) (((x) + (y) - 1) / (y)) /* divide, rounding upwards */ #define ALIGN_N(x, y) (DIVUP((x), (y)) * (y)) /* align on y boundary */ #define IPSEC_PFKEYv2_LEN(x) ((x) * IPSEC_PFKEYv2_ALIGN) #define IPSEC_PFKEYv2_WORDS(x) (DIVUP((x), IPSEC_PFKEYv2_ALIGN)) #define PFKEYv2_MAX_MSGSIZE 4096 /* * PF_KEYv2 permitted and required extensions in and out bitmaps */ struct pf_key_ext_parsers_def { int (*parser)(struct sadb_ext*); char *parser_name; }; enum pfkey_ext_required { EXT_BITS_IN=0, EXT_BITS_OUT=1 }; enum pfkey_ext_perm { EXT_BITS_PERM=0, EXT_BITS_REQ=1 }; typedef uint64_t pfkey_ext_track; static inline void pfkey_mark_extension(enum sadb_extension_t exttype, pfkey_ext_track *exten_track) { *exten_track |= (1 << exttype); } extern int pfkey_extensions_missing(enum pfkey_ext_required inout, enum sadb_msg_t sadb_operation, pfkey_ext_track extensions_seen); extern int pfkey_required_extension(enum pfkey_ext_required inout, enum sadb_msg_t sadb_operation, enum sadb_extension_t exttype); extern int pfkey_permitted_extension(enum pfkey_ext_required inout, enum sadb_msg_t sadb_operation, enum sadb_extension_t exttype); extern void pfkey_extensions_init(struct sadb_ext *extensions[]); extern void pfkey_extensions_free(struct sadb_ext *extensions[]); extern void pfkey_msg_free(struct sadb_msg **pfkey_msg); extern int pfkey_msg_parse(struct sadb_msg *pfkey_msg, struct pf_key_ext_parsers_def *ext_parsers[], struct sadb_ext **extensions, int dir); extern int pfkey_register_reply(int satype, struct sadb_msg *sadb_msg); /* * PF_KEYv2 build function prototypes */ int pfkey_msg_hdr_build(struct sadb_ext **pfkey_ext, uint8_t msg_type, uint8_t satype, uint8_t msg_errno, uint32_t seq, uint32_t pid); int pfkey_sa_ref_build(struct sadb_ext ** pfkey_ext, uint16_t exttype, uint32_t spi, /* in network order */ uint8_t replay_window, uint8_t sa_state, uint8_t auth, uint8_t encrypt, uint32_t flags, uint32_t /*IPsecSAref_t*/ ref); int pfkey_sa_build(struct sadb_ext ** pfkey_ext, uint16_t exttype, uint32_t spi, /* in network order */ uint8_t replay_window, uint8_t sa_state, uint8_t auth, uint8_t encrypt, uint32_t flags); extern int pfkey_saref_build(struct sadb_ext **pfkey_ext, IPsecSAref_t in, IPsecSAref_t out); int pfkey_lifetime_build(struct sadb_ext ** pfkey_ext, uint16_t exttype, uint32_t allocations, uint64_t bytes, uint64_t addtime, uint64_t usetime, uint32_t packets); int pfkey_address_build(struct sadb_ext **pfkey_ext, uint16_t exttype, uint8_t proto, uint8_t prefixlen, struct sockaddr *address); int pfkey_key_build(struct sadb_ext **pfkey_ext, uint16_t exttype, uint16_t key_bits, unsigned char *key); int pfkey_ident_build(struct sadb_ext **pfkey_ext, uint16_t exttype, uint16_t ident_type, uint64_t ident_id, uint8_t ident_len, char *ident_string); #ifdef __KERNEL__ extern int pfkey_nat_t_new_mapping(struct ipsec_sa *, struct sockaddr *, __u16); extern int pfkey_x_nat_t_type_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr); extern int pfkey_x_nat_t_port_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr); #endif /* __KERNEL__ */ int pfkey_x_nat_t_type_build(struct sadb_ext **pfkey_ext, uint8_t type); int pfkey_x_nat_t_port_build(struct sadb_ext **pfkey_ext, uint16_t exttype, uint16_t port); int pfkey_sens_build(struct sadb_ext **pfkey_ext, uint32_t dpd, uint8_t sens_level, uint8_t sens_len, uint64_t *sens_bitmap, uint8_t integ_level, uint8_t integ_len, uint64_t *integ_bitmap); int pfkey_x_protocol_build(struct sadb_ext **, uint8_t); int pfkey_prop_build(struct sadb_ext **pfkey_ext, uint8_t replay, unsigned int comb_num, struct sadb_comb *comb); int pfkey_supported_build(struct sadb_ext **pfkey_ext, uint16_t exttype, unsigned int alg_num, struct sadb_alg *alg); int pfkey_x_satype_build(struct sadb_ext **pfkey_ext, uint8_t satype); int pfkey_x_debug_build(struct sadb_ext **pfkey_ext, uint32_t tunnel, uint32_t netlink, uint32_t xform, uint32_t eroute, uint32_t spi, uint32_t radij, uint32_t esp, uint32_t ah, uint32_t rcv, uint32_t pfkey, uint32_t ipcomp, uint32_t verbose); int pfkey_msg_build(struct sadb_msg **pfkey_msg, struct sadb_ext *extensions[], int dir); /* in pfkey_v2_debug.c - routines to decode numbers -> strings */ const char *pfkey_v2_sadb_ext_string(int extnum); const char *pfkey_v2_sadb_type_string(unsigned sadb_type); struct sadb_builds { struct k_sadb_sa sa_base; }; int pfkey_sa_builds(struct sadb_ext **pfkey_ext, struct sadb_builds sab); extern int pfkey_outif_build(struct sadb_ext **pfkey_ext, uint16_t outif); #endif /* __NET_IPSEC_PF_KEY_H */ libreswan-3.32/include/libreswan/pfkey_debug.h000066400000000000000000000026201365625662500215150ustar00rootroot00000000000000/* pf_key debugging facility * definitions: linux/net/ipsec/pfkey_v2_parse.c, lib/libbsdpfkey/pfkey.c * * Copyright (C) 1998-2002 D. Hugh Redelmeier. * Copyright (C) 2003 Michael Richardson * Copyright (C) 2019 Andrew Cagney * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. */ #ifndef _FREESWAN_PFKEY_DEBUG_H #define _FREESWAN_PFKEY_DEBUG_H #include "lswlog.h" #include "lswalloc.h" /* * Debugging levels for pfkey_lib_debug */ #define PF_KEY_DEBUG_PARSE_NONE 0 #define PF_KEY_DEBUG_PARSE_PROBLEM 1 #define PF_KEY_DEBUG_PARSE_STRUCT 2 #define PF_KEY_DEBUG_PARSE_FLOW 4 #define PF_KEY_DEBUG_BUILD 8 #define PF_KEY_DEBUG_PARSE_MAX 15 #define DEBUGGING(level, args ...) dbg(args) #define ERROR(args ...) libreswan_log("pfkey_lib_debug:" args) # define MALLOC(size) alloc_bytes(size, __func__) # define FREE(obj) pfree(obj) #endif libreswan-3.32/include/libreswan/pfkeyv2.h000066400000000000000000000265211365625662500206250ustar00rootroot00000000000000/* RFC 2367 PF_KEY Key Management API July 1998 Appendix D: Sample Header File This file defines structures and symbols for the PF_KEY Version 2 key management interface. It was written at the U.S. Naval Research Laboratory. This file is in the public domain. The authors ask that you leave this credit intact on any copies of this file. */ #ifndef __PFKEY_V2_H #define __PFKEY_V2_H 1 #include #define PF_KEY_V2 2 #define PFKEYV2_REVISION 199806L enum sadb_msg_t { K_SADB_RESERVED=SADB_RESERVED, K_SADB_GETSPI=SADB_GETSPI, K_SADB_UPDATE=SADB_UPDATE, K_SADB_ADD=SADB_ADD, K_SADB_DELETE=SADB_DELETE, K_SADB_GET=SADB_GET, K_SADB_ACQUIRE=SADB_ACQUIRE, K_SADB_REGISTER=SADB_REGISTER, K_SADB_EXPIRE=SADB_EXPIRE, K_SADB_FLUSH=SADB_FLUSH, K_SADB_DUMP=SADB_DUMP, K_SADB_X_PROMISC=SADB_X_PROMISC, K_SADB_X_PCHANGE=SADB_X_PCHANGE, K_SADB_X_GRPSA=13, K_SADB_X_ADDFLOW=14, K_SADB_X_DELFLOW=15, K_SADB_X_DEBUG=16, K_SADB_X_NAT_T_NEW_MAPPING=17, K_SADB_X_PLUMBIF=18, K_SADB_X_UNPLUMBIF=19, K_SADB_MAX=19 }; #define SADB_X_GRPSA K_SADB_X_GRPSA #define SADB_X_ADDFLOW K_SADB_X_ADDFLOW #define SADB_X_DELFLOW K_SADB_X_DELFLOW #define SADB_X_DEBUG K_SADB_X_DEBUG #define SADB_X_PLUMBIF K_SADB_X_PLUMBIF #define SADB_X_UNPLUMBIF K_SADB_X_UNPLUMBIF struct k_sadb_sa { uint16_t sadb_sa_len; uint16_t sadb_sa_exttype; uint32_t sadb_sa_spi; uint8_t sadb_sa_replay; uint8_t sadb_sa_state; uint8_t sadb_sa_auth; uint8_t sadb_sa_encrypt; uint32_t sadb_sa_flags; uint32_t /*IPsecSAref_t*/ sadb_x_sa_ref; /* 32 bits */ uint8_t sadb_x_reserved[4]; } __attribute__((packed)); struct sadb_sa_v1 { uint16_t sadb_sa_len; uint16_t sadb_sa_exttype; uint32_t sadb_sa_spi; uint8_t sadb_sa_replay; uint8_t sadb_sa_state; uint8_t sadb_sa_auth; uint8_t sadb_sa_encrypt; uint32_t sadb_sa_flags; } __attribute__((packed)); struct sadb_x_satype { uint16_t sadb_x_satype_len; uint16_t sadb_x_satype_exttype; uint8_t sadb_x_satype_satype; uint8_t sadb_x_satype_reserved[3]; } __attribute__((packed)); struct sadb_x_debug { uint16_t sadb_x_debug_len; uint16_t sadb_x_debug_exttype; uint32_t sadb_x_debug_tunnel; uint32_t sadb_x_debug_netlink; uint32_t sadb_x_debug_xform; uint32_t sadb_x_debug_eroute; uint32_t sadb_x_debug_spi; uint32_t sadb_x_debug_radij; uint32_t sadb_x_debug_esp; uint32_t sadb_x_debug_ah; uint32_t sadb_x_debug_rcv; uint32_t sadb_x_debug_pfkey; uint32_t sadb_x_debug_ipcomp; uint32_t sadb_x_debug_verbose; uint8_t sadb_x_debug_reserved[4]; } __attribute__((packed)); /* * a plumbif extension can appear in * - a plumbif message to create the interface. * - a unplumbif message to delete the interface. * - a sadb add/replace to indicate which interface * a decrypted packet should emerge on. * * the create/delete part could/should be replaced with netlink equivalents, * or better yet, FORCES versions of same. * */ struct sadb_x_plumbif { uint16_t sadb_x_outif_len; uint16_t sadb_x_outif_exttype; uint16_t sadb_x_outif_ifnum; } __attribute__((packed)); /* * the ifnum describes a device that you wish to create refer to. * * devices 0-40959 are mastXXX devices. * devices 40960-49141 are mastXXX devices with transport set. * devices 49152-65536 are deprecated ipsecXXX devices. */ #define IPSECDEV_OFFSET (48 * 1024) #define MASTTRANSPORT_OFFSET (40 * 1024) /* * an saref extension sets the SA's reference number, and * may also set the paired SA's reference number. * */ struct sadb_x_saref { uint16_t sadb_x_saref_len; uint16_t sadb_x_saref_exttype; uint32_t sadb_x_saref_me; uint32_t sadb_x_saref_him; } __attribute__((packed)); /* * A protocol structure for passing through the transport level * protocol. It contains more fields than are actually used/needed * but it is this way to be compatible with the structure used in * OpenBSD (http://www.openbsd.org/cgi-bin/cvsweb/src/sys/net/pfkeyv2.h) */ struct sadb_protocol { uint16_t sadb_protocol_len; uint16_t sadb_protocol_exttype; uint8_t sadb_protocol_proto; uint8_t sadb_protocol_direction; uint8_t sadb_protocol_flags; uint8_t sadb_protocol_reserved2; } __attribute__((packed)); /* * NOTE that there is a limit of 31 extension types due to current * implementation in pfkeyv2_ext_bits.c */ enum sadb_extension_t { K_SADB_EXT_RESERVED= SADB_EXT_RESERVED, K_SADB_EXT_SA= SADB_EXT_SA, K_SADB_EXT_LIFETIME_CURRENT= SADB_EXT_LIFETIME_CURRENT, K_SADB_EXT_LIFETIME_HARD= SADB_EXT_LIFETIME_HARD, K_SADB_EXT_LIFETIME_SOFT= SADB_EXT_LIFETIME_SOFT, K_SADB_EXT_ADDRESS_SRC= SADB_EXT_ADDRESS_SRC, K_SADB_EXT_ADDRESS_DST= SADB_EXT_ADDRESS_DST, K_SADB_EXT_ADDRESS_PROXY= SADB_EXT_ADDRESS_PROXY, K_SADB_EXT_KEY_AUTH= SADB_EXT_KEY_AUTH, K_SADB_EXT_KEY_ENCRYPT= SADB_EXT_KEY_ENCRYPT, K_SADB_EXT_IDENTITY_SRC= SADB_EXT_IDENTITY_SRC, K_SADB_EXT_IDENTITY_DST= SADB_EXT_IDENTITY_DST, K_SADB_EXT_SENSITIVITY= SADB_EXT_SENSITIVITY, K_SADB_EXT_PROPOSAL= SADB_EXT_PROPOSAL, K_SADB_EXT_SUPPORTED_AUTH= SADB_EXT_SUPPORTED_AUTH, K_SADB_EXT_SUPPORTED_ENCRYPT= SADB_EXT_SUPPORTED_ENCRYPT, K_SADB_EXT_SPIRANGE= SADB_EXT_SPIRANGE, K_SADB_X_EXT_KMPRIVATE= SADB_X_EXT_KMPRIVATE, K_SADB_X_EXT_SATYPE2= 18, K_SADB_X_EXT_POLICY= SADB_X_EXT_POLICY, K_SADB_X_EXT_SA2= SADB_X_EXT_SA2, K_SADB_X_EXT_ADDRESS_DST2= 20, K_SADB_X_EXT_ADDRESS_SRC_FLOW= 21, K_SADB_X_EXT_ADDRESS_DST_FLOW= 22, K_SADB_X_EXT_ADDRESS_SRC_MASK= 23, K_SADB_X_EXT_ADDRESS_DST_MASK= 24, K_SADB_X_EXT_DEBUG= 25, K_SADB_X_EXT_PROTOCOL= 26, K_SADB_X_EXT_NAT_T_TYPE= 27, K_SADB_X_EXT_NAT_T_SPORT= 28, K_SADB_X_EXT_NAT_T_DPORT= 29, K_SADB_X_EXT_NAT_T_OA= 30, K_SADB_X_EXT_PLUMBIF= 31, K_SADB_X_EXT_SAREF= 32, K_SADB_EXT_MAX= 32, }; #define SADB_X_EXT_SATYPE2 K_SADB_X_EXT_SATYPE2 #define SADB_X_EXT_ADDRESS_DST2 K_SADB_X_EXT_ADDRESS_DST2 #define SADB_X_EXT_ADDRESS_SRC_FLOW K_SADB_X_EXT_ADDRESS_SRC_FLOW #define SADB_X_EXT_ADDRESS_DST_FLOW K_SADB_X_EXT_ADDRESS_DST_FLOW #define SADB_X_EXT_ADDRESS_SRC_MASK K_SADB_X_EXT_ADDRESS_SRC_MASK #define SADB_X_EXT_ADDRESS_DST_MASK K_SADB_X_EXT_ADDRESS_DST_MASK #define SADB_X_EXT_DEBUG K_SADB_X_EXT_DEBUG #define SADB_X_EXT_PROTOCOL K_SADB_X_EXT_PROTOCOL #undef SADB_X_EXT_NAT_T_TYPE #undef SADB_X_EXT_NAT_T_SPORT #undef SADB_X_EXT_NAT_T_DPORT #undef SADB_X_EXT_NAT_T_OA #define SADB_X_EXT_PLUMBIF K_SADB_X_EXT_PLUMBIF /* K_SADB_X_DELFLOW required over and above K_SADB_X_SAFLAGS_CLEARFLOW */ #define K_SADB_X_EXT_ADDRESS_DELFLOW \ ( (1ULL << K_SADB_X_EXT_ADDRESS_SRC_FLOW) \ | (1ULL << K_SADB_X_EXT_ADDRESS_DST_FLOW) \ | (1ULL << K_SADB_X_EXT_ADDRESS_SRC_MASK) \ | (1ULL << K_SADB_X_EXT_ADDRESS_DST_MASK)) enum sadb_satype { K_SADB_SATYPE_UNSPEC=SADB_SATYPE_UNSPEC, K_SADB_SATYPE_AH=SADB_SATYPE_AH, K_SADB_SATYPE_ESP=SADB_SATYPE_ESP, K_SADB_SATYPE_RSVP=SADB_SATYPE_RSVP, K_SADB_SATYPE_OSPFV2=SADB_SATYPE_OSPFV2, K_SADB_SATYPE_RIPV2=SADB_SATYPE_RIPV2, K_SADB_SATYPE_MIP=SADB_SATYPE_MIP, K_SADB_X_SATYPE_IPIP=9, K_SADB_X_SATYPE_COMP=10, K_SADB_X_SATYPE_INT=11 }; #define K_SADB_SATYPE_MAX 11 enum sadb_sastate { K_SADB_SASTATE_LARVAL=0, K_SADB_SASTATE_MATURE=1, K_SADB_SASTATE_DYING=2, K_SADB_SASTATE_DEAD=3 }; #undef SADB_SASTATE_LARVAL #undef SADB_SASTATE_MATURE #undef SADB_SASTATE_DYING #undef SADB_SASTATE_DEAD #define K_SADB_SASTATE_MAX 3 #define SADB_SAFLAGS_PFS 1 #define SADB_X_SAFLAGS_REPLACEFLOW 2 #define SADB_X_SAFLAGS_CLEARFLOW 4 #define SADB_X_SAFLAGS_INFLOW 8 #define SADB_X_SAFLAGS_POLICYONLY 16 /* suppress eroute creation */ /* not obvious, but these are the same values as used in isakmp, * and in include/ietf_constants.h. If you need to add any, they * should be added as according to * http://www.iana.org/assignments/isakmp-registry * * and if not, then please try to use a private-use value, and * consider asking IANA to assign a value. */ #define SADB_AALG_NONE 0 #define SADB_AALG_MD5HMAC 2 #define SADB_AALG_SHA1HMAC 3 #define SADB_X_AALG_SHA2_256HMAC 5 #define SADB_X_AALG_SHA2_384HMAC 6 #define SADB_X_AALG_SHA2_512HMAC 7 #define SADB_X_AALG_RIPEMD160HMAC 8 #define SADB_X_AALG_AES_XCBC_MAC 9 #define SADB_X_AALG_RSA 10 #define SADB_X_AALG_AH_AES_128_GMAC 11 #define SADB_X_AALG_AH_AES_192_GMAC 12 #define SADB_X_AALG_AH_AES_256_GMAC 13 #define SADB_X_AALG_AES_CMAC_96 250 /* used internally */ #define SADB_X_AALG_NULL 251 /* kame */ #define SADB_X_AALG_SHA2_256HMAC_TRUNCBUG 252 /* used internally to signal for broken linux kernel behaviour */ enum sadb_aalg { K_SADB_AALG_NONE= SADB_AALG_NONE, K_SADB_AALG_MD5HMAC= SADB_AALG_MD5HMAC, K_SADB_AALG_SHA1HMAC= SADB_AALG_SHA1HMAC, K_SADB_X_AALG_SHA2_256HMAC= SADB_X_AALG_SHA2_256HMAC, K_SADB_X_AALG_SHA2_256HMAC_TRUNCBUG= SADB_X_AALG_SHA2_256HMAC_TRUNCBUG, K_SADB_X_AALG_SHA2_384HMAC= SADB_X_AALG_SHA2_384HMAC, K_SADB_X_AALG_SHA2_512HMAC= SADB_X_AALG_SHA2_512HMAC, K_SADB_X_AALG_RIPEMD160HMAC= SADB_X_AALG_RIPEMD160HMAC, K_SADB_X_AALG_AES_XCBC_MAC= SADB_X_AALG_AES_XCBC_MAC, K_SADB_X_AALG_RSA= SADB_X_AALG_RSA, K_SADB_X_AALG_AH_AES_128_GMAC= SADB_X_AALG_AH_AES_128_GMAC, K_SADB_X_AALG_AH_AES_192_GMAC= SADB_X_AALG_AH_AES_192_GMAC, K_SADB_X_AALG_AH_AES_256_GMAC= SADB_X_AALG_AH_AES_256_GMAC, /* 13 */ K_SADB_X_AALG_AES_CMAC_96= SADB_X_AALG_AES_CMAC_96, K_SADB_X_AALG_NULL= SADB_X_AALG_NULL, /* 251 */ }; #define K_SADB_AALG_MAX 255 /* Is this really one octets, not two? */ /* gets mapped into AUTH_ALGORITHM which is two octets */ #define SADB_EALG_NONE 0 /* #define SADB_EALG_DESCBC 2 obsoleted */ #define SADB_EALG_3DESCBC 3 #define SADB_X_EALG_CASTCBC 6 /* #define SADB_X_EALG_BLOWFISHCBC 7 obsoleted */ #define SADB_EALG_NULL 11 #define SADB_X_EALG_AESCBC 12 #define SADB_X_EALG_AESCTR 13 #define SADB_X_EALG_AES_CCM_ICV8 14 #define SADB_X_EALG_AES_CCM_ICV12 15 #define SADB_X_EALG_AES_CCM_ICV16 16 #define SADB_X_EALG_AES_GCM_ICV8 18 #define SADB_X_EALG_AES_GCM_ICV12 19 #define SADB_X_EALG_AES_GCM_ICV16 20 #define SADB_X_EALG_SEEDCBC 21 #define SADB_X_EALG_CAMELLIACBC 22 #define SADB_X_EALG_NULL_AES_GMAC 23 enum sadb_ealg { K_SADB_EALG_NONE=SADB_EALG_NONE, /* K_SADB_EALG_DESCBC=SADB_EALG_DESCBC, obsoleted */ K_SADB_EALG_3DESCBC=SADB_EALG_3DESCBC, K_SADB_X_EALG_CASTCBC=SADB_X_EALG_CASTCBC, /* K_SADB_X_EALG_BLOWFISHCBC=SADB_X_EALG_BLOWFISHCBC, obsoleted */ K_SADB_EALG_NULL=SADB_EALG_NULL, K_SADB_X_EALG_AESCBC=SADB_X_EALG_AESCBC, K_SADB_X_EALG_AESCTR=SADB_X_EALG_AESCTR, K_SADB_X_EALG_AES_CCM_ICV8=SADB_X_EALG_AES_CCM_ICV8, K_SADB_X_EALG_AES_CCM_ICV12=SADB_X_EALG_AES_CCM_ICV12, K_SADB_X_EALG_AES_CCM_ICV16=SADB_X_EALG_AES_CCM_ICV16, K_SADB_X_EALG_AES_GCM_ICV8=SADB_X_EALG_AES_GCM_ICV8, K_SADB_X_EALG_AES_GCM_ICV12=SADB_X_EALG_AES_GCM_ICV12, K_SADB_X_EALG_AES_GCM_ICV16=SADB_X_EALG_AES_GCM_ICV16, K_SADB_X_EALG_SEEDCBC=SADB_X_EALG_SEEDCBC, K_SADB_X_EALG_CAMELLIACBC=SADB_X_EALG_CAMELLIACBC, K_SADB_X_EALG_NULL_AES_GMAC=SADB_X_EALG_NULL_AES_GMAC }; #undef SADB_EALG_MAX #define K_SADB_EALG_MAX 255 #define SADB_X_CALG_NONE 0 #define SADB_X_CALG_OUI 1 #define SADB_X_CALG_DEFLATE 2 #define SADB_X_CALG_LZS 3 #define SADB_X_CALG_LZJH 4 #define SADB_X_CALG_MAX 4 enum sadb_talg { K_SADB_X_TALG_NONE=0, K_SADB_X_TALG_IPv4_in_IPv4=1, K_SADB_X_TALG_IPv6_in_IPv4=2, K_SADB_X_TALG_IPv4_in_IPv6=3, K_SADB_X_TALG_IPv6_in_IPv6=4, }; #define SADB_X_TALG_MAX 4 #define SADB_IDENTTYPE_RESERVED 0 #define SADB_IDENTTYPE_PREFIX 1 #define SADB_IDENTTYPE_FQDN 2 #define SADB_IDENTTYPE_USERFQDN 3 #define SADB_X_IDENTTYPE_CONNECTION 4 #define K_SADB_IDENTTYPE_MAX 4 #define K_SADB_KEY_FLAGS_MAX 0 #endif /* __PFKEY_V2_H */ libreswan-3.32/include/libreswan/radij.h000066400000000000000000000174571365625662500203400ustar00rootroot00000000000000/* * This file is defived from ${SRC}/sys/net/radix.h of BSD 4.4lite * * Variable and procedure names have been modified so that they don't * conflict with the original BSD code, as a small number of modifications * have been introduced and we may want to reuse this code in BSD. * * The `j' in `radij' is pronounced as a voiceless guttural (like a Greek * chi or a German ch sound (as `doch', not as in `milch'), or even a * spanish j as in Juan. It is not as far back in the throat like * the corresponding Hebrew sound, nor is it a soft breath like the English h. * It has nothing to do with the Dutch ij sound. * * Here is the appropriate copyright notice: */ /* * Copyright (c) 1988, 1989, 1993 * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)radix.h 8.1 (Berkeley) 6/10/93 */ #ifndef _RADIJ_H_ #define _RADIJ_H_ /* #define RJ_DEBUG */ #ifdef __KERNEL__ #ifndef __P #ifdef __STDC__ #define __P(x) x #else #define __P(x) () #endif #endif /* * Radix search tree node layout. */ struct radij_node { struct radij_mask *rj_mklist; /* list of masks contained in subtree */ struct radij_node *rj_p; /* parent */ short rj_b; /* bit offset; -1-index(netmask) */ char rj_bmask; /* node: mask for bit test */ u_char rj_flags; /* enumerated next */ #define RJF_NORMAL 1 /* leaf contains normal route */ #define RJF_ROOT 2 /* leaf is root leaf for tree */ #define RJF_ACTIVE 4 /* This node is alive (for rtfree) */ union { struct { /* leaf only data: */ caddr_t rj_Key; /* object of search */ caddr_t rj_Mask; /* netmask, if present */ struct radij_node *rj_Dupedkey; } rj_leaf; struct { /* node only data: */ int rj_Off; /* where to start compare */ struct radij_node *rj_L; /* progeny */ struct radij_node *rj_R; /* progeny */ } rj_node; } rj_u; #ifdef RJ_DEBUG int rj_info; struct radij_node *rj_twin; struct radij_node *rj_ybro; #endif }; #define rj_dupedkey rj_u.rj_leaf.rj_Dupedkey #define rj_key rj_u.rj_leaf.rj_Key #define rj_mask rj_u.rj_leaf.rj_Mask #define rj_off rj_u.rj_node.rj_Off #define rj_l rj_u.rj_node.rj_L #define rj_r rj_u.rj_node.rj_R /* * Annotations to tree concerning potential routes applying to subtrees. */ extern struct radij_mask { short rm_b; /* bit offset; -1-index(netmask) */ char rm_unused; /* cf. rj_bmask */ u_char rm_flags; /* cf. rj_flags */ struct radij_mask *rm_mklist; /* more masks to try */ caddr_t rm_mask; /* the mask */ int rm_refs; /* # of references to this struct */ } *rj_mkfreelist; #define MKGet(m) { \ if (rj_mkfreelist) { \ m = rj_mkfreelist; \ rj_mkfreelist = (m)->rm_mklist; \ } else { \ R_Malloc(m, struct radij_mask *, sizeof(*(m))); } } \ #define MKFree(m) { (m)->rm_mklist = rj_mkfreelist; rj_mkfreelist = (m); } struct radij_node_head { struct radij_node *rnh_treetop; int rnh_addrsize; /* permit, but not require fixed keys */ int rnh_pktsize; /* permit, but not require fixed keys */ #if 0 struct radij_node *(*rnh_addaddr) /* add based on sockaddr */ __P((void *v, void *mask, struct radij_node_head *head, struct radij_node nodes[])); #endif int (*rnh_addaddr) /* add based on sockaddr */ __P((void *v, void *mask, struct radij_node_head *head, struct radij_node nodes[])); struct radij_node *(*rnh_addpkt) /* add based on packet hdr */ __P((void *v, void *mask, struct radij_node_head *head, struct radij_node nodes[])); #if 0 struct radij_node *(*rnh_deladdr) /* remove based on sockaddr */ __P((void *v, void *mask, struct radij_node_head *head)); #endif int (*rnh_deladdr) /* remove based on sockaddr */ __P((void *v, void *mask, struct radij_node_head *head, struct radij_node **node)); struct radij_node *(*rnh_delpkt) /* remove based on packet hdr */ __P((void *v, void *mask, struct radij_node_head *head)); struct radij_node *(*rnh_matchaddr) /* locate based on sockaddr */ __P((void *v, struct radij_node_head *head)); struct radij_node *(*rnh_matchpkt) /* locate based on packet hdr */ __P((void *v, struct radij_node_head *head)); int (*rnh_walktree) /* traverse tree */ __P((struct radij_node_head *head, int (*f)(struct radij_node *rn, void *w), void *w)); struct radij_node rnh_nodes[3]; /* empty tree for common case */ }; #define Bcmp(a, b, n) memcmp(((caddr_t)(b)), ((caddr_t)(a)), (unsigned)(n)) #define Bcopy(a, b, n) memmove(((caddr_t)(b)), ((caddr_t)(a)), (unsigned)(n)) #define Bzero(p, n) memset((caddr_t)(p), 0, (unsigned)(n)) #define R_Malloc(p, t, n) (((p) = \ (t) kmalloc((size_t)(n), \ GFP_ATOMIC)), Bzero((p), (n))) #define Free(p) kfree((caddr_t)(p)); void rj_init __P((void)); int rj_inithead __P((void **, int)); int rj_refines __P((void *, void *)); int rj_walktree __P((struct radij_node_head *head, int (*f)( struct radij_node *rn, void *w), void *w)); struct radij_node *rj_addmask __P((void *, int, int)) /* , rgb */; int /* * */ rj_addroute __P((void *, void *, struct radij_node_head *, struct radij_node [2])) /* , rgb */; int /* * */ rj_delete __P((void *, void *, struct radij_node_head *, struct radij_node **)) /* , rgb */; struct radij_node /* rgb */ *rj_insert __P((void *, struct radij_node_head *, int *, struct radij_node [2])), *rj_match __P((void *, struct radij_node_head *)), *rj_newpair __P((void *, int, struct radij_node[2])), *rj_search __P((void *, struct radij_node *)), *rj_search_m __P((void *, struct radij_node *, void *)); void rj_deltree(struct radij_node_head *); void rj_delnodes(struct radij_node *); void rj_free_mkfreelist(void); int radijcleartree(void); int radijcleanup(void); extern struct radij_node_head *mask_rjhead; extern int maj_keylen; #endif /* __KERNEL__ */ #endif /* _RADIJ_H_ */ libreswan-3.32/include/linux/000077500000000000000000000000001365625662500162315ustar00rootroot00000000000000libreswan-3.32/include/linux/pfkeyv2.h000066400000000000000000000241611365625662500177740ustar00rootroot00000000000000/* PF_KEY user interface, this is defined by rfc2367 so * do not make arbitrary modifications or else this header * file will not be compliant. */ #ifndef _LINUX_PFKEY2_H #define _LINUX_PFKEY2_H #include #define PF_KEY_V2 2 #define PFKEYV2_REVISION 199806L struct sadb_msg { uint8_t sadb_msg_version; uint8_t sadb_msg_type; uint8_t sadb_msg_errno; uint8_t sadb_msg_satype; uint16_t sadb_msg_len; uint16_t sadb_msg_reserved; uint32_t sadb_msg_seq; uint32_t sadb_msg_pid; } __attribute__((packed)); /* sizeof(struct sadb_msg) == 16 */ struct sadb_ext { uint16_t sadb_ext_len; uint16_t sadb_ext_type; } __attribute__((packed)); /* sizeof(struct sadb_ext) == 4 */ struct sadb_sa { uint16_t sadb_sa_len; uint16_t sadb_sa_exttype; uint32_t sadb_sa_spi; uint8_t sadb_sa_replay; uint8_t sadb_sa_state; uint8_t sadb_sa_auth; uint8_t sadb_sa_encrypt; uint32_t sadb_sa_flags; } __attribute__((packed)); /* sizeof(struct sadb_sa) == 16 */ struct sadb_lifetime { uint16_t sadb_lifetime_len; uint16_t sadb_lifetime_exttype; uint32_t sadb_lifetime_allocations; uint64_t sadb_lifetime_bytes; uint64_t sadb_lifetime_addtime; uint64_t sadb_lifetime_usetime; #ifdef NOT_YET uint32_t sadb_x_lifetime_packets; uint32_t sadb_x_lifetime_reserved; #endif /* NOT_YET */ } __attribute__((packed)); /* sizeof(struct sadb_lifetime) == 32 */ struct sadb_address { uint16_t sadb_address_len; uint16_t sadb_address_exttype; uint8_t sadb_address_proto; uint8_t sadb_address_prefixlen; uint16_t sadb_address_reserved; } __attribute__((packed)); /* sizeof(struct sadb_address) == 8 */ struct sadb_key { uint16_t sadb_key_len; uint16_t sadb_key_exttype; uint16_t sadb_key_bits; uint16_t sadb_key_reserved; } __attribute__((packed)); /* sizeof(struct sadb_key) == 8 */ struct sadb_ident { uint16_t sadb_ident_len; uint16_t sadb_ident_exttype; uint16_t sadb_ident_type; uint16_t sadb_ident_reserved; uint64_t sadb_ident_id; } __attribute__((packed)); /* sizeof(struct sadb_ident) == 16 */ struct sadb_sens { uint16_t sadb_sens_len; uint16_t sadb_sens_exttype; uint32_t sadb_sens_dpd; uint8_t sadb_sens_sens_level; uint8_t sadb_sens_sens_len; uint8_t sadb_sens_integ_level; uint8_t sadb_sens_integ_len; uint32_t sadb_sens_reserved; } __attribute__((packed)); /* sizeof(struct sadb_sens) == 16 */ /* followed by: uint64_t sadb_sens_bitmap[sens_len]; uint64_t sadb_integ_bitmap[integ_len]; */ struct sadb_prop { uint16_t sadb_prop_len; uint16_t sadb_prop_exttype; uint8_t sadb_prop_replay; uint8_t sadb_prop_reserved[3]; } __attribute__((packed)); /* sizeof(struct sadb_prop) == 8 */ /* followed by: struct sadb_comb sadb_combs[(sadb_prop_len + sizeof(uint64_t) - sizeof(struct sadb_prop)) / sizeof(strut sadb_comb)]; */ struct sadb_comb { uint8_t sadb_comb_auth; uint8_t sadb_comb_encrypt; uint16_t sadb_comb_flags; uint16_t sadb_comb_auth_minbits; uint16_t sadb_comb_auth_maxbits; uint16_t sadb_comb_encrypt_minbits; uint16_t sadb_comb_encrypt_maxbits; uint32_t sadb_comb_reserved; uint32_t sadb_comb_soft_allocations; uint32_t sadb_comb_hard_allocations; uint64_t sadb_comb_soft_bytes; uint64_t sadb_comb_hard_bytes; uint64_t sadb_comb_soft_addtime; uint64_t sadb_comb_hard_addtime; uint64_t sadb_comb_soft_usetime; uint64_t sadb_comb_hard_usetime; } __attribute__((packed)); /* sizeof(struct sadb_comb) == 72 */ struct sadb_supported { uint16_t sadb_supported_len; uint16_t sadb_supported_exttype; uint32_t sadb_supported_reserved; } __attribute__((packed)); /* sizeof(struct sadb_supported) == 8 */ /* followed by: struct sadb_alg sadb_algs[(sadb_supported_len + sizeof(uint64_t) - sizeof(struct sadb_supported)) / sizeof(struct sadb_alg)]; */ struct sadb_alg { uint8_t sadb_alg_id; uint8_t sadb_alg_ivlen; uint16_t sadb_alg_minbits; uint16_t sadb_alg_maxbits; uint16_t sadb_alg_reserved; } __attribute__((packed)); /* sizeof(struct sadb_alg) == 8 */ struct sadb_spirange { uint16_t sadb_spirange_len; uint16_t sadb_spirange_exttype; uint32_t sadb_spirange_min; uint32_t sadb_spirange_max; uint32_t sadb_spirange_reserved; } __attribute__((packed)); /* sizeof(struct sadb_spirange) == 16 */ struct sadb_x_kmprivate { uint16_t sadb_x_kmprivate_len; uint16_t sadb_x_kmprivate_exttype; uint32_t sadb_x_kmprivate_reserved; } __attribute__((packed)); /* sizeof(struct sadb_x_kmprivate) == 8 */ struct sadb_x_sa2 { uint16_t sadb_x_sa2_len; uint16_t sadb_x_sa2_exttype; uint8_t sadb_x_sa2_mode; uint8_t sadb_x_sa2_reserved1; uint16_t sadb_x_sa2_reserved2; uint32_t sadb_x_sa2_sequence; uint32_t sadb_x_sa2_reqid; } __attribute__((packed)); /* sizeof(struct sadb_x_sa2) == 16 */ struct sadb_x_policy { uint16_t sadb_x_policy_len; uint16_t sadb_x_policy_exttype; uint16_t sadb_x_policy_type; uint8_t sadb_x_policy_dir; uint8_t sadb_x_policy_reserved; uint32_t sadb_x_policy_id; uint32_t sadb_x_policy_priority; } __attribute__((packed)); /* sizeof(struct sadb_x_policy) == 16 */ struct sadb_x_ipsecrequest { uint16_t sadb_x_ipsecrequest_len; uint16_t sadb_x_ipsecrequest_proto; uint8_t sadb_x_ipsecrequest_mode; uint8_t sadb_x_ipsecrequest_level; uint16_t sadb_x_ipsecrequest_reserved1; uint32_t sadb_x_ipsecrequest_reqid; uint32_t sadb_x_ipsecrequest_reserved2; } __attribute__((packed)); /* sizeof(struct sadb_x_ipsecrequest) == 16 */ /* This defines the TYPE of Nat Traversal in use. Currently only one * type of NAT-T is supported, draft-ietf-ipsec-udp-encaps-06 */ struct sadb_x_nat_t_type { uint16_t sadb_x_nat_t_type_len; uint16_t sadb_x_nat_t_type_exttype; uint8_t sadb_x_nat_t_type_type; uint8_t sadb_x_nat_t_type_reserved[3]; } __attribute__((packed)); /* sizeof(struct sadb_x_nat_t_type) == 8 */ /* Pass a NAT Traversal port (Source or Dest port) */ struct sadb_x_nat_t_port { uint16_t sadb_x_nat_t_port_len; uint16_t sadb_x_nat_t_port_exttype; uint16_t sadb_x_nat_t_port_port; uint16_t sadb_x_nat_t_port_reserved; } __attribute__((packed)); /* sizeof(struct sadb_x_nat_t_port) == 8 */ /* Message types */ #define SADB_RESERVED 0 #define SADB_GETSPI 1 #define SADB_UPDATE 2 #define SADB_ADD 3 #define SADB_DELETE 4 #define SADB_GET 5 #define SADB_ACQUIRE 6 #define SADB_REGISTER 7 #define SADB_EXPIRE 8 #define SADB_FLUSH 9 #define SADB_DUMP 10 #define SADB_X_PROMISC 11 #define SADB_X_PCHANGE 12 #define SADB_X_SPDUPDATE 13 #define SADB_X_SPDADD 14 #define SADB_X_SPDDELETE 15 #define SADB_X_SPDGET 16 #define SADB_X_SPDACQUIRE 17 #define SADB_X_SPDDUMP 18 #define SADB_X_SPDFLUSH 19 #define SADB_X_SPDSETIDX 20 #define SADB_X_SPDEXPIRE 21 #define SADB_X_SPDDELETE2 22 #define SADB_X_NAT_T_NEW_MAPPING 23 #define SADB_MAX 23 /* Security Association flags */ #define SADB_SAFLAGS_PFS 1 #define SADB_SAFLAGS_DECAP_DSCP 0x40000000 #define SADB_SAFLAGS_NOECN 0x80000000 /* Security Association states */ #define SADB_SASTATE_LARVAL 0 #define SADB_SASTATE_MATURE 1 #define SADB_SASTATE_DYING 2 #define SADB_SASTATE_DEAD 3 #define SADB_SASTATE_MAX 3 /* Security Association types */ #define SADB_SATYPE_UNSPEC 0 #define SADB_SATYPE_AH 2 #define SADB_SATYPE_ESP 3 #define SADB_SATYPE_RSVP 5 #define SADB_SATYPE_OSPFV2 6 #define SADB_SATYPE_RIPV2 7 #define SADB_SATYPE_MIP 8 #define SADB_X_SATYPE_IPCOMP 9 #define SADB_SATYPE_MAX 9 /* Authentication algorithms */ #define SADB_AALG_NONE 0 #define SADB_AALG_MD5HMAC 2 #define SADB_AALG_SHA1HMAC 3 #define SADB_X_AALG_SHA2_256HMAC 5 #define SADB_X_AALG_SHA2_384HMAC 6 #define SADB_X_AALG_SHA2_512HMAC 7 #define SADB_X_AALG_RIPEMD160HMAC 8 #define SADB_X_AALG_AES_XCBC_MAC 9 #define SADB_X_AALG_RSA 10 #define SADB_X_AALG_AH_AES_128_GMAC 11 #define SADB_X_AALG_AH_AES_192_GMAC 12 #define SADB_X_AALG_AH_AES_256_GMAC 13 #define SADB_X_AALG_AES_CMAC_96 250 /* used internally */ #define SADB_X_AALG_NULL 251 /* kame */ #define SADB_X_AALG_SHA2_256HMAC_TRUNCBUG 252 #define SADB_AALG_MAX 255 /* while the AUTH_ALGORITHM is two octets, what is the SADB_AALG? */ /* Encryption algorithms */ #define SADB_EALG_NONE 0 /* #define SADB_EALG_DESCBC 2 obsoleted */ #define SADB_EALG_3DESCBC 3 #define SADB_X_EALG_CASTCBC 6 /* #define SADB_X_EALG_BLOWFISHCBC 7 obsoleted */ #define SADB_EALG_NULL 11 #define SADB_X_EALG_AESCBC 12 #define SADB_X_EALG_AESCTR 13 #define SADB_X_EALG_AES_CCM_ICV8 14 #define SADB_X_EALG_AES_CCM_ICV12 15 #define SADB_X_EALG_AES_CCM_ICV16 16 #define SADB_UNASSIGNED_EALG 17 #define SADB_X_EALG_AES_GCM_ICV8 18 #define SADB_X_EALG_AES_GCM_ICV12 19 #define SADB_X_EALG_AES_GCM_ICV16 20 #define SADB_X_EALG_CAMELLIACBC 22 #define SADB_X_EALG_NULL_AUTH_AES_GMAC 23 #define SADB_X_EALG_CHACHA20_POLY1305 28 #define SADB_EALG_MAX 255 /* last EALG */ /* private allocations should use 249-255 (RFC2407) */ /* but private allocations should use 1024-65535 (RFC4306) */ #define SADB_X_EALG_SERPENTCBC 252 /* draft-ietf-ipsec-ciph-aes-cbc-00 */ #define SADB_X_EALG_TWOFISHCBC 253 /* draft-ietf-ipsec-ciph-aes-cbc-00 */ /* Compression algorithms */ #define SADB_X_CALG_NONE 0 #define SADB_X_CALG_OUI 1 #define SADB_X_CALG_DEFLATE 2 #define SADB_X_CALG_LZS 3 #define SADB_X_CALG_LZJH 4 #define SADB_X_CALG_MAX 4 /* Extension Header values */ #define SADB_EXT_RESERVED 0 #define SADB_EXT_SA 1 #define SADB_EXT_LIFETIME_CURRENT 2 #define SADB_EXT_LIFETIME_HARD 3 #define SADB_EXT_LIFETIME_SOFT 4 #define SADB_EXT_ADDRESS_SRC 5 #define SADB_EXT_ADDRESS_DST 6 #define SADB_EXT_ADDRESS_PROXY 7 #define SADB_EXT_KEY_AUTH 8 #define SADB_EXT_KEY_ENCRYPT 9 #define SADB_EXT_IDENTITY_SRC 10 #define SADB_EXT_IDENTITY_DST 11 #define SADB_EXT_SENSITIVITY 12 #define SADB_EXT_PROPOSAL 13 #define SADB_EXT_SUPPORTED_AUTH 14 #define SADB_EXT_SUPPORTED_ENCRYPT 15 #define SADB_EXT_SPIRANGE 16 #define SADB_X_EXT_KMPRIVATE 17 #define SADB_X_EXT_POLICY 18 #define SADB_X_EXT_SA2 19 /* The next four entries are for setting up NAT Traversal */ #define SADB_X_EXT_NAT_T_TYPE 20 #define SADB_X_EXT_NAT_T_SPORT 21 #define SADB_X_EXT_NAT_T_DPORT 22 #define SADB_X_EXT_NAT_T_OA 23 #define SADB_EXT_MAX 23 /* Identity Extension values */ #define SADB_IDENTTYPE_RESERVED 0 #define SADB_IDENTTYPE_PREFIX 1 #define SADB_IDENTTYPE_FQDN 2 #define SADB_IDENTTYPE_USERFQDN 3 #define SADB_IDENTTYPE_MAX 3 #endif /* !(_LINUX_PFKEY2_H) */ libreswan-3.32/include/lmod.h000066400000000000000000000027501365625662500162020ustar00rootroot00000000000000/* lset modifiers, for libreswan * * Copyright (C) 2017-2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef _LMOD_H_ #define _LMOD_H_ #include "lset.h" /* * lmod_t is for modifying an lset_t. * * It needs a better name. */ typedef struct { lset_t set; lset_t clr; } lmod_t; extern const lmod_t empty_lmod; lset_t lmod(lset_t set, lmod_t mod); lmod_t lmod_set(lmod_t lhs, lset_t set); lmod_t lmod_clr(lmod_t lhs, lset_t set); bool lmod_is_set(lmod_t lhs, lset_t set); bool lmod_is_clr(lmod_t lhs, lset_t set); bool lmod_empty(lmod_t mod); void lmod_merge(lmod_t *lhs, lmod_t rhs); struct lmod_compat { const char *name; lset_t bit; }; struct lmod_info { const enum_names *names; lset_t all; lset_t mask; struct lmod_compat *compat; }; bool lmod_arg(lmod_t *mod, const struct lmod_info *info, const char *optarg, bool enable); void lswlog_lmod(struct lswlog *buf, const enum_names *names, const char *separator, lmod_t mod); #endif libreswan-3.32/include/lset.h000066400000000000000000000050561365625662500162200ustar00rootroot00000000000000/* long set constants * * Copyright (C) 1998-2002,2013 D. Hugh Redelmeier * Copyright (C) 2004-2008 Michael Richardson * Copyright (C) 2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #ifndef LSET_H #define LSET_H #include /* for size_t */ #include /* for uint_fast64_t */ #include struct enum_names; struct lswlog; /* * set type with room for at least 64 elements for ALG opts (was 32 in * stock FS) */ typedef uint_fast64_t lset_t; #define PRI_LSET "%"PRIxLSET #define PRIxLSET PRIxFAST64 #define LELEM_ROOF 64 /* all elements must be less than this */ #define LEMPTY ((lset_t)0) #define LELEM(opt) ((lset_t)1 << (opt)) #define LRANGE(lwb, upb) LRANGES(LELEM(lwb), LELEM(upb)) #define LRANGES(first, last) (last - first + last) #define LHAS(set, elem) (((set) & LELEM(elem)) != LEMPTY) #define LIN(subset, set) (((subset) & (set)) == (subset)) #define LDISJOINT(a, b) (((a) & (b)) == LEMPTY) /* LFIRST: find first element of a set (tricky use of twos complement) */ #define LFIRST(s) ((s) & -(s)) #define LSINGLETON(s) ((s) != LEMPTY && LFIRST(s) == (s)) /* Printing lset_t values: * * These routines require a name table which is a NULL-terminated * sequence of strings. That means that each bit in the set must * have a name. * * bitnamesof() formats a display of a set of named bits (in a static area -- NOT RE-ENTRANT) * bitnamesofb() formats into a caller-supplied buffer (re-entrant) * * jam_enum_lset_short() formats into a caller-supplied buffer -- only form */ extern bool testset(const char *const table[], lset_t val); extern const char *bitnamesof(const char *const table[], lset_t val); /* NOT RE-ENTRANT */ extern const char *bitnamesofb(const char *const table[], lset_t val, char *buf, size_t blen); /* old */ size_t lswlog_enum_lset_short(struct lswlog *, const struct enum_names *sd, const char *separator, lset_t val); /* new */ #define jam_enum_lset_short lswlog_enum_lset_short #endif /* CONSTANTS_H */ libreswan-3.32/include/lsw_select.h000066400000000000000000000025271365625662500174150ustar00rootroot00000000000000#ifndef _LSW_SELECT_H_ #define _LSW_SELECT_H_ 1 /* * Overlay the system select call to handle many more FD's than * an fd_set can hold. * David McCullough */ #include #include #include #include /* * allow build system to override the limit easily */ #ifndef LSW_FD_SETSIZE #define LSW_FD_SETSIZE 8192 #endif #define LSW_NFDBITS (8 * sizeof(long int)) #define LSW_FDELT(d) ((d) / LSW_NFDBITS) #define LSW_FDMASK(d) ((long int) (1UL << ((d) % LSW_NFDBITS))) #define LSW_FD_SETCOUNT ((LSW_FD_SETSIZE + LSW_NFDBITS - 1) / LSW_NFDBITS) typedef struct { long int __osfds_bits[LSW_FD_SETCOUNT]; } lsw_fd_set; #define LSW_FDS_BITS(set) ((set)->__osfds_bits) #define LSW_FD_ZERO(set) \ do { \ unsigned int __i; \ lsw_fd_set *__arr = (set); \ for (__i = 0; __i < LSW_FD_SETCOUNT; __i++) \ LSW_FDS_BITS(__arr)[__i] = 0; \ } while (0) #define LSW_FD_SET(d, s) (LSW_FDS_BITS(s)[LSW_FDELT(d)] |= LSW_FDMASK(d)) #define LSW_FD_CLR(d, s) (LSW_FDS_BITS(s)[LSW_FDELT(d)] &= ~LSW_FDMASK(d)) #define LSW_FD_ISSET(d, \ s) ((LSW_FDS_BITS(s)[LSW_FDELT(d)] & LSW_FDMASK(d)) != \ 0) #define lsw_select(max, r, f, e, t) \ select(max, (fd_set *)(void *)(r), (fd_set *)(void *)(f), \ (fd_set *)(void *)(e), t) #endif /* _LSW_SELECT_H_ */ libreswan-3.32/include/lswalloc.h000066400000000000000000000067761365625662500171030ustar00rootroot00000000000000/* * Misc. universal things * * Copyright (C) 1997 Angelos D. Keromytis. * Copyright (C) 1998-2001, 2013 D. Hugh Redelmeier * Copyright (C) 2012 Paul Wouters * Copyright (C) 2013 Tuomo Soini * Copyright (C) 2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef _LSW_ALLOC_H_ #define _LSW_ALLOC_H_ #include "constants.h" #include /* memory allocation */ extern void pfree(void *ptr); extern void *alloc_bytes(size_t size, const char *name); extern void *clone_bytes(const void *orig, size_t size, const char *name); void realloc_bytes(void **ptr, size_t old_size, size_t new_size, const char *name); extern bool leak_detective; extern void report_leaks(void); /* * Notes on __typeof__(). * * The macro clone_thing(), for instance, uses __typeof__(THING) to * ensure that the type of the original THING and the returned clone * match. Enforcing this flushed out a weird bug in the config * parser. * * While __typeof__() is a non-standard extension, it is widely * supported - GCC, LLVM, and even PCC include the feature. MSVC * provides the alternative decltype(), and when someone tries to use * that compiler adding suitable #ifdefs should be straight forward. * * There is, however, one limitation. If THING has the const * qualifier then the clone can't be assigned to a non-const variable. * For instance, this code gets a warning: * * const char *p = ...; * char *q = clone_thing(*p, "copy of p"); * * One way round it would be to use another GCC extension ({}) and * change the macro to: * * #define clone_thing(TYPE,THING,NAME) ({ * const (TYPE) *p = &(THING); * (TYPE*) clone_bytes(p, sizeof(TYPE), (NAME); * )} * * Another would be to use, er, C++'s remove_const<>. */ #define alloc_thing(thing, name) ((thing*) alloc_bytes(sizeof(thing), (name))) #define alloc_things(THING, COUNT, NAME) ((THING*) alloc_bytes(sizeof(THING) * (COUNT), (NAME))) #define realloc_things(THINGS, OLD_COUNT, NEW_COUNT, NAME) \ { \ void *things_ = THINGS; \ realloc_bytes(&things_, \ OLD_COUNT * sizeof((THINGS)[0]), \ NEW_COUNT * sizeof((THINGS)[0]), \ NAME); \ THINGS = things_; \ } #define clone_thing(orig, name) \ ((__typeof__(&(orig))) clone_bytes((const void *)&(orig), \ sizeof(orig), (name))) #define clone_const_thing(orig, name) clone_bytes((const void *)&(orig), \ sizeof(orig), (name)) #define clone_str(str, name) \ ((str) == NULL ? NULL : clone_bytes((str), strlen((str)) + 1, (name))) #define pfreeany(P) { \ typeof(P) *pp_ = &(P); \ if (*pp_ != NULL) { \ pfree(*pp_); \ *pp_ = NULL; \ } \ } #define replace(p, q) { pfreeany(p); (p) = (q); } /* * Memory primitives, should only be used by libevent. */ void *uninitialized_malloc(size_t size, const char *name); void *uninitialized_realloc(void *ptr, size_t size, const char *name); #endif /* _LSW_ALLOC_H_ */ libreswan-3.32/include/lswcdefs.h000066400000000000000000000035721365625662500170640ustar00rootroot00000000000000/* sys/cdefs.h like compiler macros, for libreswan * * Copyright (C) 1998, 1999, 2000 Henry Spencer. * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. * */ #ifndef LSWCDEFS_H #define LSWCDEFS_H /* * elemsof() returns the unsigned size_t. */ #define elemsof(array) (sizeof(array) / sizeof(*(array))) /* * NOTE: this is by nature a scary macro because it * is used to initialized two fields. * This has a hacky advantage: * if you don't wish to count the last element of * the array (say, because it is a NULL there for * bitnamesof), just use ARRAY_REF()-1! */ #define ARRAY_REF(p) (p), elemsof(p) /* GCC magic for use in function definitions! */ #ifdef GCC_LINT # define PRINTF_LIKE(n) __attribute__ ((format(printf, n, n + 1))) # define STRFTIME_LIKE(n) __attribute__ ((format (strftime, n, 0))) # define NEVER_RETURNS __attribute__ ((noreturn)) # define UNUSED __attribute__ ((unused)) # define MUST_USE_RESULT __attribute__ ((warn_unused_result)) #else # define PRINTF_LIKE(n) /* ignore */ # define STRFTIME_LIKE(n) /* ignore */ # define NEVER_RETURNS /* ignore */ # define UNUSED /* ignore */ # define MUST_USE_RESULT /* ignore */ #endif #ifdef COMPILER_HAS_NO_PRINTF_LIKE # undef PRINTF_LIKE # define PRINTF_LIKE(n) /* ignore */ # undef STRFTIME_LIKE # define STRFTIME_LIKE(n) /* ignore */ #endif #endif libreswan-3.32/include/lswconf.h000066400000000000000000000040771365625662500167260ustar00rootroot00000000000000/* misc functions to get compile time and runtime options * Copyright (C) 2005 Michael Richardson * Copyright (C) 2009 Paul Wouters * Copyright (C) 2009 Avesh Agarwal * Copyright (C) 2012-2013 Paul Wouters * Copyright (C) 2013 D. Hugh Redelmeier * Copyright (C) 2016 Tuomo Soini * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #ifndef _LSW_CONF_H #define _LSW_CONF_H #include "constants.h" # include # include /* from nss3 devel */ struct lsw_conf_options { char *rootdir; /* default is "" --- used for testing */ char *confdir; /* "/etc" */ char *conffile; /* "/etc/ipsec.conf" */ char *secretsfile; /* "/etc/ipsec.secrets" */ char *ppkdir; /* "/etc/ipsec.d" , for now */ char *vardir; /* "/var/run/pluto" */ char *confddir; /* "/etc/ipsec.d" */ char *policies_dir; /* "/etc/ipsec.d/policies" */ char *cacerts_dir; /* "/etc/ipsec.d/cacerts" */ char *crls_dir; /* "/etc/ipsec.d/crls" */ char *nsspassword_file; /* "/etc/ipsec.d/nsspassword" */ char *nsspassword; /* overrides ^ */ char *nssdir; /* "/var/lib/ipsec" */ }; const struct lsw_conf_options *lsw_init_options(void); void lsw_conf_free_oco(void); void lsw_conf_rootdir(const char *root_dir); void lsw_conf_secretsfile(const char *secretsfile); void lsw_conf_confddir(const char *confddir); void lsw_conf_nssdir(const char *nssdir); void lsw_conf_nsspassword(const char *nsspassword); extern int libreswan_selinux(void); #endif /* _LSW_ALLOC_H_ */ libreswan-3.32/include/lswendian.h000066400000000000000000000037411365625662500172340ustar00rootroot00000000000000/* byte-order stuff * Copyright (C) 1998, 1999 D. Hugh Redelmeier. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ /* sets BYTE_ORDER, LITTLE_ENDIAN, and BIG_ENDIAN */ #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) # include #elif defined(linux) # if defined(i386) && !defined(__i386__) # define __i386__ 1 # define MYHACKFORTHIS 1 # endif # include # if 0 /* kernel's clashes with glibc's */ /* The problem (in RedHat 5.0) is the typing of the "longs" (32-bit values) * in the [nh]to[hn]l functions: * - uses unsigned long * - uses uint32_t which is unsigned int * Since 64-bit machines are supported, should be changed. * For now, we simply don't use . */ # include # endif # ifdef MYHACKFORTHIS # undef __i386__ # undef MYHACKFORTHIS # endif #elif !(defined(BIG_ENDIAN) && defined(LITTLE_ENDIAN) && defined(BYTE_ORDER)) /* we don't know how to do this, so we require the macros to be defined * with compiler flags: * -DBIG_ENDIAN=4321 -DLITTLE_ENDIAN=1234 -DBYTE_ORDER=BIG_ENDIAN * or -DBIG_ENDIAN=4321 -DLITTLE_ENDIAN=1234 -DBYTE_ORDER=LITTLE_ENDIAN * Thse match the GNU definitions */ # include #endif #ifndef BIG_ENDIAN # error BIG_ENDIAN must be defined #endif #ifndef LITTLE_ENDIAN # error LITTLE_ENDIAN must be defined #endif #ifndef BYTE_ORDER # error BYTE_ORDER must be defined #endif libreswan-3.32/include/lswfips.h000066400000000000000000000023661365625662500167410ustar00rootroot00000000000000/* FIPS functions to determine FIPS status * * Copyright (C) 2005 Michael Richardson * Copyright (C) 2009 Paul Wouters * Copyright (C) 2009 Avesh Agarwal * Copyright (C) 2012-2013 Paul Wouters * Copyright (C) 2013 D. Hugh Redelmeier * Copyright (C) 2016 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef LSWFIPS_H #define LSWFIPS_H #include /* for bool */ enum lsw_fips_mode { LSW_FIPS_UNSET = 0, LSW_FIPS_UNKNOWN, LSW_FIPS_OFF, LSW_FIPS_ON }; extern void lsw_set_fips_mode(enum lsw_fips_mode fips); extern enum lsw_fips_mode lsw_get_fips_mode(void); extern bool libreswan_fipsmode(void); #endif libreswan-3.32/include/lswlog.h000066400000000000000000000430231365625662500165540ustar00rootroot00000000000000/* logging declaratons * * Copyright (C) 1998-2001,2013 D. Hugh Redelmeier * Copyright (C) 2004 Michael Richardson * Copyright (C) 2012-2013 Paul Wouters * Copyright (C) 2017-2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #ifndef _LSWLOG_H_ #define _LSWLOG_H_ #include #include /* for FILE */ #include /* for size_t */ #include "lset.h" #include "lswcdefs.h" #include "jambuf.h" #include "libreswan/passert.h" #include "constants.h" /* for DBG_... */ #include "where.h" /* used by macros */ #include "fd.h" /* for null_fd */ /* Build up a diagnostic in a static buffer -- NOT RE-ENTRANT. * Although this would be a generally useful function, it is very * hard to come up with a discipline that prevents different uses * from interfering. It is intended that by limiting it to building * diagnostics, we will avoid this problem. * Juggling is performed to allow an argument to be a previous * result: the new string may safely depend on the old one. This * restriction is not checked in any way: violators will produce * confusing results (without crashing!). */ #define LOG_WIDTH ((size_t)1024) /* roof of number of chars in log line */ extern err_t builddiag(const char *fmt, ...) PRINTF_LIKE(1); /* NOT RE-ENTRANT */ extern bool log_to_stderr; /* should log go to stderr? */ /* * Codes for status messages returned to whack. * * These are 3 digit decimal numerals. The structure is inspired by * section 4.2 of RFC959 (FTP). Since these will end up as the exit * status of whack, they must be less than 256. * * NOTE: ipsec_auto(8) knows about some of these numbers -- change * carefully. */ enum rc_type { RC_COMMENT, /* non-commital utterance (does not affect exit status) */ RC_PRINT, /* ditto, but also suppresses the '[0-9]* ' prefix */ RC_LOG, /* message aimed at log (does not affect exit status) */ RC_LOG_SERIOUS, /* serious message aimed at log (does not affect exit status) */ RC_SUCCESS, /* success (exit status 0) */ RC_INFORMATIONAL, /* should get relayed to user - if there is one */ RC_INFORMATIONAL_TRAFFIC, /* status of an established IPSEC (aka Phase 2) state */ /* failure, but not definitive */ RC_RETRANSMISSION = 10, /* improper request */ RC_EXIT_FLOOR = 20, RC_DUPNAME = RC_EXIT_FLOOR, /* attempt to reuse a connection name */ RC_UNKNOWN_NAME, /* connection name unknown or state number */ RC_ORIENT, /* cannot orient connection: neither end is us */ RC_CLASH, /* clash between two Road Warrior connections OVERLOADED */ RC_DEAF, /* need --listen before --initiate */ RC_ROUTE, /* cannot route */ RC_RTBUSY, /* cannot unroute: route busy */ RC_BADID, /* malformed --id */ RC_NOKEY, /* no key found through DNS */ RC_NOPEERIP, /* cannot initiate when peer IP is unknown */ RC_INITSHUNT, /* cannot initiate a shunt-oly connection */ RC_WILDCARD, /* cannot initiate when ID has wildcards */ RC_CRLERROR, /* CRL fetching disabled or obsolete reread cmd */ RC_WHACK_PROBLEM, /* whack-detected problem */ /* permanent failure */ RC_BADWHACKMESSAGE = 30, RC_NORETRANSMISSION, RC_INTERNALERR, RC_OPPOFAILURE, /* Opportunism failed */ RC_CRYPTOFAILED, /* system too busy to perform required * cryptographic operations */ RC_AGGRALGO, /* multiple algorithms requested in phase 1 aggressive */ RC_FATAL, /* fatal error encountered, and negotiation aborted */ /* entry of secrets */ RC_ENTERSECRET = 40, RC_USERPROMPT = 41, RC_EXIT_ROOF = 100, /* * progress: start of range for successful state transition. * Actual value is RC_NEW_V[12]_STATE plus the new state code. */ RC_NEW_V1_STATE = RC_EXIT_ROOF, RC_NEW_V2_STATE = 150, /* * Start of range for notification. * * Actual value is RC_NOTIFICATION plus code for notification * that should be generated by this Pluto. RC_NOTIFICATION. * Since notifications are two octets, that's 64435+200 which * overflows the 3-digit prefix, oops. */ RC_NOTIFICATION = 200, /* as per IKE notification messages */ }; /* * A generic buffer for accumulating unbounded output. * * The buffer's contents can be directed to various logging streams. */ struct lswlog; /* * The logging streams used by libreswan. * * So far three^D^D^D^D^D four^D^D^D^D five^D^D^D^D six^D^D^D * seven^D^D^D^D^D five.five streams have been identified; and let's * not forget that code writes to STDOUT and STDERR directly. * * The streams differ in the syslog severity and what PREFIX is * assumed to be present and the tool being run. * * PLUTO * SEVERITY WHACK PREFIX TOOLS PREFIX * default WARNING yes state -v * log WARNING - state -v * debug DEBUG - "| " debug? * error ERR - ERROR STDERR PROG:_... * whack - yes NNN STDOUT ... * file - - - - * * The streams will then add additional prefixes as required. For * instance, the log_whack stream will prefix a timestamp when sending * to a file (optional), and will prefix NNN(RC) when sending to * whack. * * For tools, the default and log streams go to STDERR when enabled; * and the debug stream goes to STDERR conditional on debug flags. * Should the whack stream go to stdout? * * As needed, return size_t - the number of bytes written - so that * implementations have somewhere to send values that should not be * ignored; for instance fwrite() :-/ */ /* * By default messages are broadcast (to both log files and whack), * mix-in one of these options to limit this. */ enum stream { /* * This means that a simple RC_* code will go to both whack * and and the log files. */ /* Mask the whack RC; max value is 64435+200 */ RC_MASK = 0x0fffff, /* Severity Whack Prefix */ ALL_STREAMS = 0x000000, /* LOG_WARNING yes */ LOG_STREAM = 0x100000, /* LOG_WARNING no */ DEBUG_STREAM = 0x200000, /* LOG_DEBUG no "| " */ WHACK_STREAM = 0x300000, /* N/A yes */ ERROR_STREAM = 0x400000, /* LOG_ERR no */ NO_STREAM = 0xf00000, /* n/a */ }; void log_jambuf(lset_t rc_flags, struct fd *object_fd, jambuf_t *buf); size_t lswlog_to_file_stream(struct lswlog *buf, FILE *file); /* * XXX: since the following all use the global CUR_STATE to get * OBJECT_FD, they can't be implemented using log_jambuf(). */ void lswlog_to_default_streams(struct lswlog *buf, enum rc_type rc); void lswlog_to_error_stream(struct lswlog *buf); /* * Log to the default stream(s): * * - for pluto this means 'syslog', and when connected, whack. * * - for standalone tools, this means stderr, but only when enabled. * * There are two variants, the first specify the RC (prefix sent to * whack), while the second default RC to RC_LOG. * * XXX: even though the the name loglog() gives the impression that * it, and not libreswan_log(), needs to be used when double logging * (i.e., to both 'syslog' and whack), it does not - both functions * double log! Hence LSWLOG_RC(). */ void lswlog_log_prefix(struct lswlog *buf); extern void libreswan_log_rc(enum rc_type, const char *fmt, ...) PRINTF_LIKE(2); #define loglog libreswan_log_rc #define LSWLOG_RC(RC, BUF) \ LSWLOG_(true, BUF, \ lswlog_log_prefix(BUF), \ lswlog_to_default_streams(BUF, RC)) /* signature needs to match printf() */ extern int libreswan_log(const char *fmt, ...) PRINTF_LIKE(1); #define LSWLOG(BUF) LSWLOG_RC(RC_LOG, BUF) /* * Log, at level RC, to the whack log (if attached). * * XXX: See programs/pluto/log.h for interface; should only be used in * pluto. This code assumes that it is being called from the main * thread. * * LSWLOG_INFO() sends stuff just to "whack" (or for a tool STDERR?). * XXX: there is no prefix, bug? Should it send stuff out with level * RC_COMMENT? */ #define LSWLOG_WHACK(RC, BUF) \ LSWLOG_(true, BUF, \ lswlog_log_prefix(BUF), \ log_jambuf(WHACK_STREAM|RC, null_fd, BUF)) /* XXX: should be stdout?!? */ #define LSWLOG_INFO(BUF) \ LSWLOG_(true, BUF, , log_jambuf(WHACK_STREAM|RC_PRINT, null_fd, buf)) /* * Wrap in a prefix and suffix where the suffix contains * errno and message. * * Notes: * * Because __VA_ARGS__ may contain function calls that modify ERRNO, * errno's value is first saved. * * While these common-case macros could be implemented directly using * LSWLOG_ERRNO_() et.al. they are not, instead they are implemented * as wrapper functions. This is so that a crash will include the * below functions _including_ the with MESSAGE parameter - makes * debugging much easier. */ void libreswan_exit(enum pluto_exit_code rc) NEVER_RETURNS; void libreswan_log_errno(int e, const char *message, ...) PRINTF_LIKE(2); void libreswan_exit_log_errno(int e, const char *message, ...) PRINTF_LIKE(2) NEVER_RETURNS; #define LOG_ERRNO(ERRNO, ...) { \ int log_errno = ERRNO; /* save value across va args */ \ libreswan_log_errno(log_errno, __VA_ARGS__); \ } #define EXIT_LOG_ERRNO(ERRNO, ...) { \ int exit_log_errno = ERRNO; /* save value across va args */ \ libreswan_exit_log_errno(exit_log_errno, __VA_ARGS__); \ } /* * E must have been saved! Assume it is used as "... "PRI_ERRNO. * * _Errno E: */ #define PRI_ERRNO "Errno %d: %s" #define pri_errno(E) (E), strerror(E) /* * Log debug messages to the main log stream, but not the WHACK log * stream. * * NOTE: DBG's action can be a { } block, but that block must not * contain commas that are outside quotes or parenthesis. * If it does, they will be interpreted by the C preprocesser * as macro argument separators. This happens accidentally if * multiple variables are declared in one declaration. * * Naming: All DBG_*() prefixed functions send stuff to the debug * stream unconditionally. Hence they should be wrapped in DBGP(). */ extern lset_t cur_debugging; /* current debugging level */ #define DBGP(cond) (cur_debugging & (cond)) #define DEBUG_PREFIX "| " #define DBG(cond, action) { if (DBGP(cond)) { action; } } #define DBGF(COND, MESSAGE, ...) { if (DBGP(COND)) { DBG_log(MESSAGE,##__VA_ARGS__); } } #define dbg(MESSAGE, ...) { if (DBGP(DBG_BASE)) { DBG_log(MESSAGE,##__VA_ARGS__); } } /* DBG_*() are unconditional */ void DBG_log(const char *message, ...) PRINTF_LIKE(1); void DBG_dump(const char *label, const void *p, size_t len); #define DBG_dump_hunk(LABEL, HUNK) \ { \ typeof(HUNK) hunk_ = HUNK; /* evaluate once */ \ DBG_dump(LABEL, hunk_.ptr, hunk_.len); \ } #define DBG_dump_thing(LABEL, THING) DBG_dump(LABEL, &(THING), sizeof(THING)) #define LSWDBG_(PREDICATE, BUF) \ LSWLOG_(PREDICATE, BUF, \ /*no-prefix*/, \ log_jambuf(DEBUG_STREAM, null_fd, BUF)) #define LSWDBGP(DEBUG, BUF) LSWDBG_(DBGP(DEBUG), BUF) #define LSWLOG_DEBUG(BUF) LSWDBG_(true, BUF) /* * Impair pluto's behaviour. * * IMPAIR currently uses the same lset_t as DBG. Define a separate * macro so that, one day, that can change. */ #define IMPAIR(BEHAVIOUR) (cur_debugging & (IMPAIR_##BEHAVIOUR)) /* * Routines for accumulating output in the lswlog buffer. * * If there is insufficient space, the output is truncated and "..." * is appended. * * Similar to C99 snprintf() et.al., these functions return the * untruncated size of output that the call would append (the value * can never be negative). * * While probably not directly useful, it provides a sink for code * that needs to consume an otherwise ignored return value (the * compiler attribute warn_unused_result can't be suppressed using a * (void) cast). */ size_t lswlogvf(struct lswlog *log, const char *format, va_list ap); size_t lswlogf(struct lswlog *log, const char *format, ...) PRINTF_LIKE(2); size_t lswlogs(struct lswlog *log, const char *string); size_t lswlogl(struct lswlog *log, struct lswlog *buf); /* * Code wrappers that cover up the details of allocating, * initializing, de-allocating (and possibly logging) a 'struct * lswlog' buffer. * * BUF (a C variable name) is declared locally as a pointer to a * per-thread 'struct lswlog' buffer. * * Implementation notes: * * This implementation stores the output in an array on the thread's * stack. It could just as easily use the heap (but that would * involve memory overheads) or even a per-thread static variable. * Since the BUF variable is a pointer the specifics of the * implementation are hidden. * * This implementation, unlike DBG(), does not have a code block * parameter. Instead it uses a sequence of for-loops to set things * up for a code block. This avoids problems with "," within macro * parameters confusing the parser. It also permits a simple * consistent indentation style. * * The stack array is left largely uninitialized (just a few strategic * entries are set). This avoids the need to zero LOG_WITH bytes. * * Apparently chaining void function calls using a comma is valid C? */ /* * Scratch buffer for accumulating extra output. * * XXX: case should be expanded to illustrate how to stuff a truncated * version of the output into the LOG buffer. * * For instance: */ #if 0 void lswbuf(struct lswlog *log) { LSWBUF(buf) { lswlogf(buf, "written to buf"); lswlogl(log, buf); /* add to calling array */ } } #endif /* primitive to construct an LSWBUF on the stack. */ #define LSWBUF(BUF) \ /* create the buffer */ \ for (char lswbuf[LOG_WIDTH], \ *lswbuf_ = lswbuf; \ lswbuf_ != NULL; lswbuf_ = NULL) \ /* create the jambuf */ \ for (jambuf_t jambuf = ARRAY_AS_JAMBUF(lswbuf), \ *BUF = &jambuf; \ BUF != NULL; BUF = NULL) #define LSWBUF_ LSWBUF /* * Template for constructing logging output intended for a logger * stream. * * The code is equivlaent to: * * if (PREDICATE) { * LSWBUF(BUF) { * PREFIX; * BLOCK; * SUFFIX; * } */ #define LSWLOG_(PREDICATE, BUF, PREFIX, SUFFIX) \ for (bool lswlog_p = PREDICATE; lswlog_p; lswlog_p = false) \ LSWBUF_(BUF) \ for (PREFIX; lswlog_p; lswlog_p = false, SUFFIX) /* * Write a line of output to the FILE stream as a single block; * includes an implicit new-line. * * For instance: */ #if 0 void lswlog_file(FILE f) { LSWLOG_FILE(f, buf) { lswlogf(buf, "written to file"); } } #endif #define LSWLOG_FILE(FILE, BUF) \ LSWLOG_(true, BUF, \ , \ lswlog_to_file_stream(BUF, FILE)) /* * Log an expectation failure message to the error streams. That is * the main log (level LOG_ERR) and whack log (level RC_LOG_SERIOUS). * * When evaluating ASSERTION, do not wrap it in parentheses as it will * suppress the warning for 'foo = bar'. * * Because static analizer tools are easily confused, explicitly * return the assertion result. */ #ifdef EXAMPLE void lswlog_pexpect_example(void *p) { if (!pexpect(p != NULL)) { return; } } #endif #define pexpect(ASSERTION) \ ({ \ bool assertion__ = ASSERTION; \ if (!assertion__) { \ log_pexpect(HERE, "%s", #ASSERTION); \ } \ assertion__; /* result */ \ }) void log_pexpect(where_t where, const char *message, ...) PRINTF_LIKE(2); void lswlog_pexpect_prefix(struct lswlog *buf); void lswlog_pexpect_suffix(struct lswlog *buf, where_t where); #define LSWLOG_PEXPECT_WHERE(WHERE, BUF) \ LSWLOG_(true, BUF, \ lswlog_pexpect_prefix(BUF), \ lswlog_pexpect_suffix(BUF, WHERE)) #define LSWLOG_PEXPECT(BUF) \ LSWLOG_PEXPECT_WHERE(HERE, BUF) #define LOG_PEXPECT(FMT, ...) \ log_pexpect(HERE, FMT,##__VA_ARGS__) #define PEXPECT_LOG(FMT, ...) \ log_pexpect(HERE, FMT,##__VA_ARGS__) /* * Log an assertion failure to the main log, and the whack log; and * then call abort(). */ void lswlog_passert_prefix(struct lswlog *buf); void lswlog_passert_suffix(struct lswlog *buf, where_t where) NEVER_RETURNS; #define LSWLOG_PASSERT(BUF) \ LSWLOG_(true, BUF, \ lswlog_passert_prefix(BUF), \ lswlog_passert_suffix(BUF, HERE)) /* for a switch statement */ void libreswan_bad_case(const char *expression, long value, where_t where) NEVER_RETURNS; #define bad_case(N) libreswan_bad_case(#N, (N), HERE) #define impaired_passert(BEHAVIOUR, ASSERTION) { \ if (IMPAIR(BEHAVIOUR)) { \ bool assertion_ = ASSERTION; \ if (!assertion_) { \ libreswan_log("IMPAIR: assertion '%s' failed", #ASSERTION); \ } \ } else { \ passert(ASSERTION); \ } \ } /* * Wrap in a prefix and suffix where the suffix contains * errno and message. Since calls may alter ERRNO, it needs to be * saved. * * XXX: Is error stream really the right place for this? * * LSWLOG_ERROR() sends an arbitrary message to the error stream (in * tools that's STDERR). XXX: Should LSWLOG_ERRNO() and LSWERR() be * merged. XXX: should LSWLOG_ERROR() use a different prefix? */ void lswlog_errno_prefix(struct lswlog *buf, const char *prefix); void lswlog_errno_suffix(struct lswlog *buf, int e); #define LSWLOG_ERROR(BUF) \ LSWLOG_(true, BUF, \ lswlog_log_prefix(BUF), \ lswlog_to_error_stream(buf)) #endif /* _LSWLOG_H_ */ libreswan-3.32/include/lswnss.h000066400000000000000000000036271365625662500166040ustar00rootroot00000000000000/* * NSS boilerplate stuff, for libreswan. * * Copyright (C) 2016, Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef _LSWNSS_H_ #define _LSWNSS_H_ #include #include "lswalloc.h" #include "secrets.h" enum lsw_nss_flags { LSW_NSS_READONLY = 1, /* * Should shutdown call PR_CLEANUP. */ LSW_NSS_SKIP_PR_CLEANUP = 2, }; /* * If something goes wrong, the error gets dumped into this null * terminated buffer. */ typedef char lsw_nss_buf_t[100]; bool lsw_nss_setup(const char *config_dir, unsigned flags, PK11PasswordFunc get_nss_password, lsw_nss_buf_t err); void lsw_nss_shutdown(void); struct private_key_stuff *lsw_nss_foreach_private_key_stuff(secret_eval func, void *uservoid, lsw_nss_buf_t err); /* * Just in case, at some point passing a parameter becomes somehow * useful. */ #define lsw_return_nss_password_file_info() NULL char *lsw_nss_get_password(PK11SlotInfo *slot, PRBool retry, void *arg); PK11SlotInfo *lsw_nss_get_authenticated_slot(lsw_nss_buf_t err); /* _(SECERR: N (0xX): ) */ size_t lswlog_nss_error(struct lswlog *log); size_t lswlog_nss_ckm(struct lswlog *buf, CK_MECHANISM_TYPE mechanism); size_t lswlog_nss_ckf(struct lswlog *buf, CK_FLAGS flags); size_t lswlog_nss_cka(struct lswlog *buf, CK_ATTRIBUTE_TYPE attribute); size_t lswlog_nss_secitem(struct lswlog *buf, const SECItem *secitem); #endif libreswan-3.32/include/lswseccomp.h000066400000000000000000000033121365625662500174210ustar00rootroot00000000000000/* * seccomp wrappers, for libreswan * * Copyright (c) 2018 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef LSWSECCOMP_H #define LSWSECCOMP_H #ifndef LSW_SECCOMP_EXIT_FAIL #error "need to define LSW_SECCOMP_EXIT_FAIL" #endif #include #include "lswlog.h" /* for libreswan_exit() et.al. refered to by macro */ /* * Add system call NAME to seccomp. * * Needs to be a macro so that SCMP_SYS(NAME) expands correctly. * * XXX: Should use EXIT_LOG_ERRNO() but that doesn't take a custom * exit code. * * XXX: seccomp_release() isn't technically needed - the context * hasn't been loaded so can be dropped on the floor. */ #define LSW_SECCOMP_ADD(CTX, NAME) { \ /* returns 0 or -ve errno */ \ int rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, \ SCMP_SYS(NAME), 0); \ if (rc != 0) { \ if (rc < 0) { \ LOG_ERRNO(-rc, "seccomp_rule_add() failed for system call '%s'", \ #NAME); \ } else { \ libreswan_log("seccomp_rule_add() failed for system call '%s' with unexpected error %d", \ #NAME, rc); \ } \ seccomp_release(CTX); /* XXX: needed? */ \ libreswan_exit(LSW_SECCOMP_EXIT_FAIL); \ } \ } #endif libreswan-3.32/include/lswtool.h000066400000000000000000000003111365625662500167410ustar00rootroot00000000000000 /* * For stand-alone tools. * * XXX: can "progname" be made private to lswlog.c? */ extern const char *progname; extern void tool_init_log(const char *progname); extern void tool_close_log(void); libreswan-3.32/include/monotime.h000066400000000000000000000045541365625662500171020ustar00rootroot00000000000000/* monotonic time object and functions, for libreswan * * Copyright (C) 1998, 1999, 2000 Henry Spencer. * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs * Copyright (C) 2017-2019 Andrew Cagney * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. * */ #ifndef MONOTIME_H #define MONOTIME_H /* seen it, no need to see it again */ #include /* for struct timeval */ #include /* for bool */ #include "deltatime.h" /* * The time objects are wrapped so that dimensional analysis will be * enforced by the compiler. */ /* * monotime_t: absolute monotonic time. No discontinuities (except * for machine sleep?) * * - various clocks can jump backwards on UNIX/LINUX; for instance * when the machine's UTC clock is corrected * * - this causes all kinds of problems with timeouts observable in the * Real World * * - this code detects backward jumps and compensates by refusing to * go backwards * * - unfortunately there is no way to detect forward jumps * */ typedef struct { struct timeval mt; } monotime_t; monotime_t monotime(intmax_t seconds); #define MONOTIME_EPOCH { { 0, 0 } } extern const monotime_t monotime_epoch; bool is_monotime_epoch(monotime_t t); monotime_t mononow(void); monotime_t monotimesum(monotime_t t, deltatime_t d); bool monobefore(monotime_t a, monotime_t b); deltatime_t monotimediff(monotime_t a, monotime_t b); intmax_t monosecs(monotime_t m); /* for pthread_cond_timedwait() */ clockid_t monotime_clockid(void); struct timespec monotime_as_timespec(monotime_t); typedef struct { /* slightly over size */ char buf[sizeof("-18446744073709551615.1000000")+1/*canary*/]; /* true length ???? */ } monotime_buf; const char *str_monotime(monotime_t d, monotime_buf *buf); size_t jam_monotime(jambuf_t *buf, monotime_t d); #define lswlog_monotime jam_monotime /* XXX: TBD */ #endif libreswan-3.32/include/names_constant.h000066400000000000000000000105251365625662500202620ustar00rootroot00000000000000/* * names_constant.h */ #include #include extern enum_names kern_interface_names; extern enum_names timer_event_names; extern enum_names dpd_action_names; #ifdef NETKEY_SUPPORT extern enum_names netkey_sa_dir_names; #endif extern enum_names sd_action_names; extern enum_names stf_status_names; extern enum_names ikev2_asym_auth_name; extern const enum_names debug_names; extern const enum_names debug_help; extern const struct lmod_info debug_lmod_info; extern const enum_names impair_names; extern const enum_names impair_help; extern const struct lmod_info impair_lmod_info; extern enum_names connection_kind_names; extern enum_names routing_story; extern enum_names certpolicy_type_names; extern const char *const sa_policy_bit_names[]; extern const char *const sighash_policy_bit_names[]; extern enum_names oakley_attr_names; extern const char *const oakley_attr_bit_names[]; extern enum_names *const oakley_attr_val_descs[]; extern const unsigned int oakley_attr_val_descs_roof; extern enum_names ipsec_attr_names; extern enum_names *const ipsec_attr_val_descs[]; extern const unsigned int ipsec_attr_val_descs_roof; extern enum_names sa_lifetime_names; extern enum_names enc_mode_names; extern enum_names auth_alg_names; extern enum_names oakley_lifetime_names; extern enum_names ike_version_names; extern enum_names ike_version_liveness_names; extern enum_names ike_version_ike_names; extern enum_names ike_version_child_names; extern enum_names version_names; extern enum_names doi_names; extern enum_names ikev1_payload_names; extern enum_names ikev2_payload_names; extern enum_enum_names payload_type_names; extern enum_names ikev2_last_proposal_desc; extern enum_names ikev2_last_transform_desc; extern enum_names payload_names_ikev1orv2; extern const char *const payload_name_ikev1[]; /* suitable for bitnamesof() */ extern enum_names attr_msg_type_names; extern enum_names modecfg_attr_names; extern enum_names xauth_type_names; extern enum_names xauth_attr_names; extern enum_names ikev1_exchange_names; extern enum_names ikev2_exchange_names; extern enum_names exchange_names_ikev1orv2; extern enum_enum_names exchange_type_names; extern enum_names ikev1_protocol_names; extern enum_names ikev2_protocol_names; extern enum_names ikev2_del_protocol_names; /* subset of protocol names accepted by IKEv2 Delete */ extern enum_names isakmp_transformid_names; extern enum_names ah_transformid_names; extern enum_names esp_transformid_names; extern enum_names ipcomp_transformid_names; extern enum_names notify_hash_algo_names; extern enum_names ike_idtype_names_extended0; extern enum_names ike_idtype_names_extended; extern enum_names ike_idtype_names; extern enum_names ike_cert_type_names; extern enum_names oakley_enc_names; extern enum_names oakley_hash_names; extern enum_names oakley_auth_names; extern enum_names oakley_group_names; extern enum_names ikev1_notify_names; /* IKEv2 */ extern enum_names ikev2_auth_names; extern enum_names ikev2_sec_proto_id_names; extern enum_names ikev2_trans_type_names; extern enum_names ikev2_trans_type_encr_names; extern enum_names ikev2_trans_type_prf_names; extern enum_names ikev2_trans_type_integ_names; extern enum_names ikev2_trans_type_esn_names; extern enum_names ikev2_trans_attr_descs; extern enum_enum_names v2_transform_ID_enums; extern enum_names ikev2_idtype_names; extern enum_names ikev2_cert_type_names; extern enum_names ikev2_notify_names; extern enum_names ikev2_ts_type_names; extern enum_names ikev2_cp_type_names; extern enum_names ikev2_cp_attribute_type_names; extern enum_names ikev2_redirect_gw_names; extern enum_names allow_global_redirect_names; extern enum_names dns_auth_level_names; /* * Attribute Type "constant" for Security Context * * Originally, we assigned the value 10, but that properly belongs to ECN_TUNNEL. * We then assigned 32001 which is in the private range RFC 2407. * Unfortunately, we feel we have to support 10 as an option for backward * compatibility. * This variable specifies (globally!!) which we support: 10 or 32001. * ??? surely that makes migration to 32001 all or nothing. */ extern uint16_t secctx_attr_type; extern const char *const natt_bit_names[]; extern enum_names natt_method_names; extern enum_names pkk_names; extern enum_names ikev2_ppk_id_type_names; extern enum_names spi_names; /* natt traversal types */ extern const char *const natt_type_bitnames[]; libreswan-3.32/include/netlink_attrib.h000066400000000000000000000022231365625662500202530ustar00rootroot00000000000000#ifndef _NETLINK_H # define _NETLINK_H /* work around weird combo's of glibc and kernel header conflicts */ #ifndef GLIBC_KERN_FLIP_HEADERS # include "linux/xfrm.h" /* local (if configured) or system copy */ # include "libreswan.h" #else # include "libreswan.h" # include "linux/xfrm.h" /* local (if configured) or system copy */ #endif #include #define NETLINK_REQ_DATA_SIZE 8192 struct nlm_resp { struct nlmsghdr n; union { struct nlmsgerr e; struct xfrm_userpolicy_info pol; /* netlink_policy_expire */ struct xfrm_usersa_info sa; /* netlink_get_spi */ struct xfrm_usersa_info info; /* netlink_get_sa */ char data[NETLINK_REQ_DATA_SIZE]; } u; }; bool nl_addattr_l(struct nlmsghdr *n, const unsigned short maxlen, const unsigned short type, const void *data, int alen); struct rtattr *nl_addattr_nest(struct nlmsghdr *n, int maxlen, int type); bool nl_addattr_nest_end(struct nlmsghdr *n, struct rtattr *nest); bool nl_addattrstrz(struct nlmsghdr *n, int maxlen, int type, const char *str); bool nl_addattr32(struct nlmsghdr *n, int maxlen, int type, const uint32_t data); #endif libreswan-3.32/include/nss_cert_load.h000066400000000000000000000021651365625662500200660ustar00rootroot00000000000000/* * NSS certificate loading routines for libreswan, the ipsec daemon * * Copyright (C) 2015 Matt Rogers * Copyright (C) 2016 Andrew Cagney * Copyright (C) 2016 Paul Wouters * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef _NSS_CERT_LOAD_H #define _NSS_CERT_LOAD_H #include #include extern CERTCertificate *get_cert_by_nickname_from_nss(const char *nickname); extern CERTCertificate *get_cert_by_ckaid_from_nss(const char *ckaid); extern CERTCertificate *get_cert_by_ckaid_t_from_nss(ckaid_t ckaid); #endif /* _NSS_CERT_LOAD_H */ libreswan-3.32/include/oid.h000066400000000000000000000032111365625662500160130ustar00rootroot00000000000000/* * Object identifiers (OIDs) used by Libreswan * * Copyright (C) 2003-2004 Andreas Steffen, Zuercher Hochschule Winterthur * Copyright (C) 2014 Tuomo Soini * * This file has been generated by the script lib/libswan/oid.pl * Do not edit manually! */ typedef struct { unsigned char octet; unsigned char down; /* bool */ unsigned short next; const char *name; } oid_t; extern const oid_t oid_names[]; #define OID_UNKNOWN (-1) #define OID_ROLE 35 #define OID_SUBJECT_KEY_ID 38 #define OID_SUBJECT_ALT_NAME 41 #define OID_BASIC_CONSTRAINTS 43 #define OID_CRL_DISTRIBUTION_POINTS 45 #define OID_AUTHORITY_KEY_ID 47 #define OID_EXTENDED_KEY_USAGE 48 #define OID_TARGET_INFORMATION 49 #define OID_NO_REV_AVAIL 50 #define OID_RSA_ENCRYPTION 59 #define OID_MD2_WITH_RSA 60 #define OID_MD5_WITH_RSA 61 #define OID_SHA1_WITH_RSA 62 #define OID_SHA256_WITH_RSA 63 #define OID_SHA384_WITH_RSA 64 #define OID_SHA512_WITH_RSA 65 #define OID_SHA224_WITH_RSA 66 #define OID_PKCS7_DATA 68 #define OID_PKCS7_SIGNED_DATA 69 #define OID_PKCS9_EMAIL 75 #define OID_MD2 78 #define OID_MD5 79 #define OID_AUTHORITY_INFO_ACCESS 96 #define OID_OCSP_SIGNING 106 #define OID_AUTHENTICATION_INFO 108 #define OID_ACCESS_IDENTITY 109 #define OID_CHARGING_IDENTITY 110 #define OID_GROUP 111 #define OID_OCSP 113 #define OID_BASIC 114 #define OID_NONCE 115 #define OID_CRL 116 #define OID_RESPONSE 117 #define OID_NO_CHECK 118 #define OID_ARCHIVE_CUTOFF 119 #define OID_SERVICE_LOCATOR 120 #define OID_SHA1 124 #define OID_SHA1_WITH_RSA_OIW 125 #define OID_SHA256 141 #define OID_SHA384 142 #define OID_SHA512 143 libreswan-3.32/include/pfkey_help.h000066400000000000000000000004221365625662500173670ustar00rootroot00000000000000/* two pfkey I/O routines * definitions: lib/libswan/pfkey_sock.c, lib/libswan/pfkey_error.c */ /* opens a pfkey socket, or dumps to stderr the reason why it failed */ extern int pfkey_open_sock_with_error(void); extern void pfkey_write_error(int writeerror, int err); libreswan-3.32/include/pluto_constants.h000066400000000000000000001317071365625662500205130ustar00rootroot00000000000000/* manifest constants * * Copyright (C) 1997 Angelos D. Keromytis. * Copyright (C) 1998-2002,2013 D. Hugh Redelmeier * Copyright (C) 2012-2019 Paul Wouters * Copyright (C) 2012 Philippe Vouters * Copyright (C) 2013 David McCullough * Copyright (C) 2013 Matt Rogers * Copyright (C) 2016-2019 Andrew Cagney * Copyright (C) 2017-2018 Sahana Prasad * Copyright (C) 2017 Vukasin Karadzic * Copyright (C) 2019-2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include "lset.h" /* * Size of hash tables; a prime. * * Mumble something about modifying hash_table.[hc] so it can grow. */ #define STATE_TABLE_SIZE 499 # ifndef DEFAULT_DNSSEC_ROOTKEY_FILE # define DEFAULT_DNSSEC_ROOTKEY_FILE "" # endif enum ike_version { /* 0 reserved */ #define IKE_VERSION_FLOOR 1 IKEv1 = 1, IKEv2 = 2, #define IKE_VERSION_ROOF 3 }; /* * IETF has no recommendations * FIPS SP800-77 sayas IKE max is 24h, IPsec max is 8h * We say maximum for either is 1d */ #define IKE_SA_LIFETIME_DEFAULT secs_per_hour #define IKE_SA_LIFETIME_MAXIMUM secs_per_day #define IPSEC_SA_LIFETIME_DEFAULT secs_per_hour * 8 #define IPSEC_SA_LIFETIME_MAXIMUM secs_per_day #define FIPS_IPSEC_SA_LIFETIME_MAXIMUM secs_per_hour * 8 #define FIPS_IKE_SA_LIFETIME_MAXIMUM secs_per_hour * 24 #define FIPS_MIN_RSA_KEY_SIZE 2048 /* 112 bits, see SP800-131A */ #define PLUTO_SHUNT_LIFE_DURATION_DEFAULT (15 * secs_per_minute) #define PLUTO_HALFOPEN_SA_LIFE (secs_per_minute ) #define SA_REPLACEMENT_MARGIN_DEFAULT (9 * secs_per_minute) /* IPSEC & IKE */ #define SA_REPLACEMENT_FUZZ_DEFAULT 100 /* (IPSEC & IKE) 100% of MARGIN */ #define SA_REPLACEMENT_RETRIES_DEFAULT 0 /* (IPSEC & IKE) */ #define SA_LIFE_DURATION_K_DEFAULT 0xFFFFFFFFlu #define IKE_BUF_AUTO 0 /* use system values for IKE socket buffer size */ #define DEFAULT_XFRM_IF_NAME "ipsec1" enum kernel_interface { NO_KERNEL = 1, USE_KLIPS = 2, USE_NETKEY= 3, USE_WIN2K = 4, USE_BSDKAME = 6, }; /* RFC 3706 Dead Peer Detection */ enum dpd_action { DPD_ACTION_DISABLED, /* happens for type=passthrough */ DPD_ACTION_CLEAR, DPD_ACTION_HOLD, DPD_ACTION_RESTART }; enum send_ca_policy { CA_SEND_NONE = 0, CA_SEND_ISSUER = 1, CA_SEND_ALL = 2, }; /* Cisco interop: values remote_peer_type= */ enum keyword_remotepeertype { NON_CISCO = 0, CISCO = 1, }; /* keep in sync with ikev2_asym_auth_names */ enum keyword_authby { AUTH_UNSET = 0, AUTH_NEVER = 1, AUTH_PSK = 2, AUTH_RSASIG = 3, AUTH_ECDSA = 4, AUTH_NULL = 5, }; enum keyword_xauthby { XAUTHBY_FILE = 0, XAUTHBY_PAM = 1, XAUTHBY_ALWAYSOK = 2, }; enum allow_global_redirect { GLOBAL_REDIRECT_NO, GLOBAL_REDIRECT_YES, GLOBAL_REDIRECT_AUTO, }; enum keyword_xauthfail { XAUTHFAIL_HARD = 0, XAUTHFAIL_SOFT = 1, }; /* OCSP related constants - defaults picked from NSS defaults */ #define OCSP_DEFAULT_CACHE_SIZE 1000 #define OCSP_DEFAULT_CACHE_MIN_AGE 3600 #define OCSP_DEFAULT_CACHE_MAX_AGE 24 * 3600 #define OCSP_DEFAULT_TIMEOUT 2 enum keyword_ocsp_method { OCSP_METHOD_GET = 0, /* really GET plus POST - see NSS code */ OCSP_METHOD_POST = 1, /* only POST */ }; /* corresponding name table is sd_action_names */ enum sd_actions { PLUTO_SD_EXIT = 1, PLUTO_SD_START = 2, PLUTO_SD_WATCHDOG = 3, PLUTO_SD_RELOADING = 4, PLUTO_SD_READY = 5, PLUTO_SD_STOPPING = 6, }; /* * NAT-Traversal defines for nat_traveral type from nat_traversal.h * * Elements for a set. * The first members are used to specify the type of NAT Traversal. * The second part says which ends are doing NAT. * ??? perhaps these ought to be partitioned into separate sets. */ enum natt_method { NAT_TRAVERSAL_METHOD_none, /* unknown or unspecified */ NAT_TRAVERSAL_METHOD_IETF_02_03, NAT_TRAVERSAL_METHOD_IETF_05, /* same as RFC */ NAT_TRAVERSAL_METHOD_IETF_RFC, NATED_HOST, /* we are behind NAT */ NATED_PEER /* peer is behind NAT */ }; /* Timer events */ enum event_type { EVENT_NULL, /* non-event */ /* * Timer events not associated with states (aka global * timers). */ EVENT_REINIT_SECRET, /* Refresh cookie secret */ EVENT_SHUNT_SCAN, /* scan shunt eroutes known to kernel */ EVENT_PENDING_DDNS, /* try to start connections where DNS failed at init */ EVENT_SD_WATCHDOG, /* update systemd's watchdog interval */ EVENT_PENDING_PHASE2, /* do not make pending phase2 wait forever */ EVENT_CHECK_CRLS, /* check/update CRLS */ EVENT_REVIVE_CONNS, EVENT_FREE_ROOT_CERTS, #define FREE_ROOT_CERTS_TIMEOUT deltatime(5 * secs_per_minute) EVENT_RESET_LOG_RATE_LIMIT, /* set nr. rate limited log messages back to 0 */ #define RESET_LOG_RATE_LIMIT deltatime(secs_per_hour) EVENT_NAT_T_KEEPALIVE, /* NAT Traversal Keepalive */ EVENT_PROCESS_KERNEL_QUEUE, /* non-netkey */ GLOBAL_TIMERS_ROOF, /* events associated with connections */ /* events associated with states */ EVENT_SO_DISCARD, /* v1/v2 discard unfinished state object */ EVENT_RETRANSMIT, /* v1/v2 retransmit IKE packet */ /* * For IKEv2 'replace' is really either a re-key a full * replace, or expire. IKEv1 should be the same but isn't. */ EVENT_SA_REKEY, /* v2 SA rekey event */ EVENT_SA_REPLACE, /* v1/v2 SA replacement event */ EVENT_SA_EXPIRE, /* v1/v2 SA expiration event */ EVENT_v1_SEND_XAUTH, /* v1 send xauth request */ EVENT_v1_SA_REPLACE_IF_USED, /* v1 SA replacement event */ EVENT_DPD, /* v1 dead peer detection */ EVENT_DPD_TIMEOUT, /* v1 dead peer detection timeout */ EVENT_CRYPTO_TIMEOUT, /* v1/v2 after some time, give up on crypto helper */ EVENT_PAM_TIMEOUT, /* v1/v2 give up on PAM helper */ EVENT_v2_LIVENESS, /* for dead peer detection */ EVENT_v2_RELEASE_WHACK, /* release the whack fd */ EVENT_v2_INITIATE_CHILD, /* initiate a IPsec child */ EVENT_v2_ADDR_CHANGE, /* process IP address deletion */ EVENT_v2_REDIRECT, /* initiate new IKE exchange on new address */ EVENT_RETAIN, /* don't change the previous event */ }; #define EVENT_REINIT_SECRET_DELAY secs_per_hour #define EVENT_GIVEUP_ON_DNS_DELAY (5 * secs_per_minute) #define EVENT_RELEASE_WHACK_DELAY 10 /* seconds */ #define RTM_NEWADDR_ROUTE_DELAY 3 /* seconds */ #define PARENT_MIN_LIFE 1 /* second */ #define EXPIRE_OLD_SA 1 /* second */ #define REPLACE_ORPHAN 1 /* second */ /* * an arbitrary milliseconds delay for responder. A workaround for iOS, iPhone. * If xauth message arrive before main mode response iPhone may abort. */ #define EVENT_v1_SEND_XAUTH_DELAY_MS 80 /* milliseconds */ #define RETRANSMIT_TIMEOUT_DEFAULT 60 /* seconds */ #ifndef RETRANSMIT_INTERVAL_DEFAULT_MS # define RETRANSMIT_INTERVAL_DEFAULT_MS 500 /* wait time doubled each retransmit - in milliseconds */ #endif #define DELETE_SA_DELAY RETRANSMIT_TIMEOUT_DEFAULT /* wait until the other side giveup on us */ #define EVENT_CRYPTO_TIMEOUT_DELAY RETRANSMIT_TIMEOUT_DEFAULT /* wait till the other side give up on us */ #define EVENT_PAM_TIMEOUT_DELAY RETRANSMIT_TIMEOUT_DEFAULT /* wait until this side give up on PAM */ #define REVIVE_CONN_DELAY 5 /* seconds */ #define REVIVE_CONN_DELAY_MAX 300 /* Do not delay more than 5 minutes per attempt */ /* is pluto automatically switching busy state or set manually */ enum ddos_mode { DDOS_undefined, DDOS_AUTO, DDOS_FORCE_BUSY, DDOS_FORCE_UNLIMITED }; /* * seccomp mode * on syscall violation, enabled kills pluto, tolerant ignores syscall */ enum seccomp_mode { SECCOMP_undefined, SECCOMP_ENABLED, SECCOMP_TOLERANT, SECCOMP_DISABLED }; /* * status for state-transition-function * * Note: STF_FAIL + ( is either * notification_t or v2_notification_t) means fail with that * notification. Since is a uint16_t, it is limited to * 65535 possible values (0 isn't valid). * * tbd? means someone needs to look at the IKEv1/IKEv2 code and figure * it out. * * delete 'if state': delete state is known - the post processing * function function complete_*_state_transition() assumes there is a * message and if it contains a state (*MDP)->ST delete it. XXX: This * is messed up - a state transition function, which by definition is * operating on a state, should require a state and not the message. * * delete 'maybe?': For IKEv2, delete the IKE_SA_INIT responder state * but only when STF_FAIL+. IKEv1? XXX: With no * clear / fast rule, this just creates confusion; perhaps the intent * is for it to delete larval response states, who knows? * * respond 'message?': if the state transition says a message should * be sent (hopefully there is one). * * respond 'maybe?': For instance, with IKEv2 when a responder and * STF_FAIL+, a notification is sent as the only content * in a response. XXX: for IKEv2 this is broken: KE responses can't * use it - need to suggest KE; AUTH responses can't use it - need to * send other stuff (but they do breaking auth). */ typedef enum { /* * XXX: Upon the state transition function's return do not * call complete_v[12]_state_transition(), do not pass go, and * do not collect $200. * * This is a hack so that (old) state transitions functions * that directly directly call complete*() (or other scary * stuff) can signal the common code that the normal sequence * of: call state transition function; call complete() should * be bypassed. For instance, the IKEv1 crypto continuation * functions. */ STF_SKIP_COMPLETE_STATE_TRANSITION, /* TRANSITION DELETE RESPOND LOG */ STF_IGNORE, /* no no no tbd? */ STF_SUSPEND, /* suspend no no tbd? */ STF_OK, /* yes no message? tbd? */ STF_INTERNAL_ERROR, /* no no never tbd? */ STF_FATAL, /* no always never fail */ STF_FAIL, /* no maybe? maybe? fail */ STF_ROOF = STF_FAIL + 65536 /* see RFC and above */ } stf_status; /* Misc. stuff */ #define MAXIMUM_v1_ACCEPTED_DUPLICATES 2 /* * maximum retransmits per exchange, for IKEv1 (initiator and responder), * IKEv2 initiator */ #define MAXIMUM_RETRANSMITS_PER_EXCHANGE 12 #define MAXIMUM_RESPONDER_WAIT 200 /* seconds before responder giveup */ #define MAXIMUM_INVALID_KE_RETRANS 3 #define MAXIMUM_MALFORMED_NOTIFY 16 #define MAX_INPUT_UDP_SIZE 65536 #define MIN_OUTPUT_UDP_SIZE 1024 #define MAX_OUTPUT_UDP_SIZE 65536 #define MAX_IKE_FRAGMENTS 32 /* Windows has been observed to send 29 fragments :/ */ #define KERNEL_PROCESS_Q_PERIOD 1 /* seconds */ #define DEFAULT_MAXIMUM_HALFOPEN_IKE_SA 50000 /* fairly arbitrary */ #define DEFAULT_IKE_SA_DDOS_THRESHOLD 25000 /* fairly arbitrary */ #define IPSEC_SA_DEFAULT_REPLAY_WINDOW 32 #define IKE_V2_OVERLAPPING_WINDOW_SIZE 1 /* our default for rfc 7296 # 2.3 */ #define PPK_ID_MAXLEN 64 /* fairly arbitrary */ /* could overflow size uint32_t */ #define IPV6_MIN_POOL_PREFIX_LEN 96 /* * debugging settings: a set of selections for reporting These would * be more naturally situated in log.h, but they are shared with * whack. * * IMPAIR_* actually change behaviour, usually badly, to aid in * testing. Naturally, these are not included in ALL. * * NOTE: A change to WHACK_MAGIC in whack.h will be required too. */ /* * Index of DBG set elements. * * Note: these are NOT sets: use LELEM to turn these into singletons. * Used by whack and pluto. * * NOTE: when updating/adding x_IX, do so to x in the next table too! */ enum { DBG_floor_IX = 0, DBG_BASE_IX = DBG_floor_IX, /* below are also enabled by debug=all */ DBG_CPU_USAGE_IX, /* below are excluded from debug=base */ DBG_TMI_IX, DBG_CRYPT_IX, DBG_PRIVATE_IX, DBG_WHACKWATCH_IX, DBG_ADD_PREFIX_IX, DBG_roof_IX, /* first unassigned DBG is assigned to IMPAIR! */ }; /* Sets of Debug items */ #define DBG_MASK LRANGE(DBG_floor_IX, DBG_roof_IX - 1) #define DBG_NONE 0 /* no options on, including impairments */ #define DBG_BASE LELEM(DBG_BASE_IX) #define DBG_CPU_USAGE LELEM(DBG_CPU_USAGE_IX) #define DBG_ALL (DBG_BASE | DBG_CPU_USAGE) /* singleton sets: must be kept in sync with the items! */ /* so things don't break */ #define DBG_RAW DBG_BASE #define DBG_PARSING DBG_BASE #define DBG_EMITTING DBG_BASE #define DBG_CONTROL DBG_BASE #define DBG_LIFECYCLE DBG_BASE #define DBG_KERNEL DBG_BASE #define DBG_DNS DBG_BASE #define DBG_OPPO DBG_BASE #define DBG_CONTROLMORE DBG_BASE #define DBG_NATT DBG_BASE #define DBG_X509 DBG_BASE #define DBG_DPD DBG_BASE #define DBG_XAUTH DBG_BASE #define DBG_RETRANSMITS DBG_BASE #define DBG_OPPOINFO DBG_BASE /* These are not part of "base" debugging */ #define DBG_TMI LELEM(DBG_TMI_IX) #define DBG_CRYPT LELEM(DBG_CRYPT_IX) #define DBG_PRIVATE LELEM(DBG_PRIVATE_IX) /* so things don't break */ #define DBG_PROPOSAL_PARSER DBG_TMI #define DBG_WHACKWATCH LELEM(DBG_WHACKWATCH_IX) #define DBG_ADD_PREFIX LELEM(DBG_ADD_PREFIX_IX) /* * Index of IMPAIR set elements. * * see impair.c (libswan) for a definition of each of these fields. * * XXX: For now, these share the same lset_t as the DBG elements * above. */ enum { IMPAIR_floor_IX = DBG_roof_IX, IMPAIR_BUST_MI2_IX = IMPAIR_floor_IX, IMPAIR_BUST_MR2_IX, IMPAIR_DROP_I2_IX, IMPAIR_SA_CREATION_IX, IMPAIR_JACOB_TWO_TWO_IX, IMPAIR_ALLOW_NULL_NONE_IX, IMPAIR_MAJOR_VERSION_BUMP_IX, IMPAIR_MINOR_VERSION_BUMP_IX, IMPAIR_TIMEOUT_ON_RETRANSMIT_IX, IMPAIR_DELETE_ON_RETRANSMIT_IX, IMPAIR_SUPPRESS_RETRANSMITS_IX, IMPAIR_SEND_BOGUS_PAYLOAD_FLAG_IX, IMPAIR_SEND_BOGUS_ISAKMP_FLAG_IX, IMPAIR_SEND_NO_DELETE_IX, IMPAIR_SEND_NO_IKEV2_AUTH_IX, IMPAIR_SEND_NO_XAUTH_R0_IX, IMPAIR_DROP_XAUTH_R0_IX, IMPAIR_SEND_NO_MAIN_R2_IX, IMPAIR_FORCE_FIPS_IX, IMPAIR_SEND_KEY_SIZE_CHECK_IX, IMPAIR_SEND_BOGUS_DCOOKIE_IX, IMPAIR_OMIT_HASH_NOTIFY_REQUEST_IX, IMPAIR_IGNORE_HASH_NOTIFY_REQUEST_IX, IMPAIR_IGNORE_HASH_NOTIFY_RESPONSE_IX, IMPAIR_IKEv2_EXCLUDE_INTEG_NONE_IX, IMPAIR_IKEv2_INCLUDE_INTEG_NONE_IX, IMPAIR_REPLAY_DUPLICATES_IX, IMPAIR_REPLAY_FORWARD_IX, IMPAIR_REPLAY_BACKWARD_IX, IMPAIR_REPLAY_ENCRYPTED_IX, IMPAIR_CORRUPT_ENCRYPTED_IX, IMPAIR_PROPOSAL_PARSER_IX, IMPAIR_ADD_UNKNOWN_PAYLOAD_TO_SA_INIT_IX, IMPAIR_ADD_UNKNOWN_PAYLOAD_TO_AUTH_IX, IMPAIR_ADD_UNKNOWN_PAYLOAD_TO_AUTH_SK_IX, IMPAIR_UNKNOWN_PAYLOAD_CRITICAL_IX, IMPAIR_ALLOW_DNS_INSECURE_IX, IMPAIR_SEND_PKCS7_THINGIE_IX, IMPAIR_IKEv1_DEL_WITH_NOTIFY_IX, IMPAIR_BAD_IKE_AUTH_XCHG_IX, IMPAIR_REKEY_INITIATOR_SUPERNET_IX, IMPAIR_REKEY_RESPOND_SUPERNET_IX, IMPAIR_REKEY_RESPOND_SUBNET_IX, IMPAIR_roof_IX /* first unassigned IMPAIR */ }; /* Sets of Impair items */ #define IMPAIR_MASK LRANGE(IMPAIR_floor_IX, IMPAIR_roof_IX - 1) /* singleton sets: must be kept in sync with the items! */ #define IMPAIR_BUST_MI2 LELEM(IMPAIR_BUST_MI2_IX) #define IMPAIR_BUST_MR2 LELEM(IMPAIR_BUST_MR2_IX) #define IMPAIR_DROP_I2 LELEM(IMPAIR_DROP_I2_IX) #define IMPAIR_SA_CREATION LELEM(IMPAIR_SA_CREATION_IX) #define IMPAIR_JACOB_TWO_TWO LELEM(IMPAIR_JACOB_TWO_TWO_IX) #define IMPAIR_ALLOW_NULL_NONE LELEM(IMPAIR_ALLOW_NULL_NONE_IX) #define IMPAIR_MAJOR_VERSION_BUMP LELEM(IMPAIR_MAJOR_VERSION_BUMP_IX) #define IMPAIR_MINOR_VERSION_BUMP LELEM(IMPAIR_MINOR_VERSION_BUMP_IX) #define IMPAIR_TIMEOUT_ON_RETRANSMIT LELEM(IMPAIR_TIMEOUT_ON_RETRANSMIT_IX) #define IMPAIR_DELETE_ON_RETRANSMIT LELEM(IMPAIR_DELETE_ON_RETRANSMIT_IX) #define IMPAIR_SUPPRESS_RETRANSMITS LELEM(IMPAIR_SUPPRESS_RETRANSMITS_IX) #define IMPAIR_SEND_BOGUS_PAYLOAD_FLAG LELEM(IMPAIR_SEND_BOGUS_PAYLOAD_FLAG_IX) #define IMPAIR_SEND_BOGUS_ISAKMP_FLAG LELEM(IMPAIR_SEND_BOGUS_ISAKMP_FLAG_IX) #define IMPAIR_SEND_NO_DELETE LELEM(IMPAIR_SEND_NO_DELETE_IX) #define IMPAIR_SEND_NO_IKEV2_AUTH LELEM(IMPAIR_SEND_NO_IKEV2_AUTH_IX) #define IMPAIR_SEND_NO_XAUTH_R0 LELEM(IMPAIR_SEND_NO_XAUTH_R0_IX) #define IMPAIR_DROP_XAUTH_R0 LELEM(IMPAIR_DROP_XAUTH_R0_IX) #define IMPAIR_SEND_NO_MAIN_R2 LELEM(IMPAIR_SEND_NO_MAIN_R2_IX) #define IMPAIR_FORCE_FIPS LELEM(IMPAIR_FORCE_FIPS_IX) #define IMPAIR_SEND_KEY_SIZE_CHECK LELEM(IMPAIR_SEND_KEY_SIZE_CHECK_IX) #define IMPAIR_SEND_BOGUS_DCOOKIE LELEM(IMPAIR_SEND_BOGUS_DCOOKIE_IX) #define IMPAIR_OMIT_HASH_NOTIFY_REQUEST LELEM(IMPAIR_OMIT_HASH_NOTIFY_REQUEST_IX) #define IMPAIR_IGNORE_HASH_NOTIFY_REQUEST LELEM(IMPAIR_IGNORE_HASH_NOTIFY_REQUEST_IX) #define IMPAIR_IGNORE_HASH_NOTIFY_RESPONSE LELEM(IMPAIR_IGNORE_HASH_NOTIFY_RESPONSE_IX) #define IMPAIR_IKEv2_EXCLUDE_INTEG_NONE LELEM(IMPAIR_IKEv2_EXCLUDE_INTEG_NONE_IX) #define IMPAIR_IKEv2_INCLUDE_INTEG_NONE LELEM(IMPAIR_IKEv2_INCLUDE_INTEG_NONE_IX) #define IMPAIR_REPLAY_DUPLICATES LELEM(IMPAIR_REPLAY_DUPLICATES_IX) #define IMPAIR_REPLAY_FORWARD LELEM(IMPAIR_REPLAY_FORWARD_IX) #define IMPAIR_REPLAY_BACKWARD LELEM(IMPAIR_REPLAY_BACKWARD_IX) #define IMPAIR_REPLAY_ENCRYPTED LELEM(IMPAIR_REPLAY_ENCRYPTED_IX) #define IMPAIR_CORRUPT_ENCRYPTED LELEM(IMPAIR_CORRUPT_ENCRYPTED_IX) #define IMPAIR_PROPOSAL_PARSER LELEM(IMPAIR_PROPOSAL_PARSER_IX) #define IMPAIR_ADD_UNKNOWN_PAYLOAD_TO_SA_INIT LELEM(IMPAIR_ADD_UNKNOWN_PAYLOAD_TO_SA_INIT_IX) #define IMPAIR_ADD_UNKNOWN_PAYLOAD_TO_AUTH LELEM(IMPAIR_ADD_UNKNOWN_PAYLOAD_TO_AUTH_IX) #define IMPAIR_ADD_UNKNOWN_PAYLOAD_TO_AUTH_SK LELEM(IMPAIR_ADD_UNKNOWN_PAYLOAD_TO_AUTH_SK_IX) #define IMPAIR_UNKNOWN_PAYLOAD_CRITICAL LELEM(IMPAIR_UNKNOWN_PAYLOAD_CRITICAL_IX) #define IMPAIR_ALLOW_DNS_INSECURE LELEM(IMPAIR_ALLOW_DNS_INSECURE_IX) #define IMPAIR_SEND_PKCS7_THINGIE LELEM(IMPAIR_SEND_PKCS7_THINGIE_IX) #define IMPAIR_IKEv1_DEL_WITH_NOTIFY LELEM(IMPAIR_IKEv1_DEL_WITH_NOTIFY_IX) #define IMPAIR_BAD_IKE_AUTH_XCHG LELEM(IMPAIR_BAD_IKE_AUTH_XCHG_IX) #define IMPAIR_REKEY_INITIATOR_SUPERNET LELEM(IMPAIR_REKEY_INITIATOR_SUPERNET_IX) #define IMPAIR_REKEY_RESPOND_SUPERNET LELEM(IMPAIR_REKEY_RESPOND_SUPERNET_IX) #define IMPAIR_REKEY_RESPOND_SUBNET LELEM(IMPAIR_REKEY_RESPOND_SUBNET_IX) /* State of exchanges * * The name of the state describes the last message sent, not the * message currently being input or output (except during retry). * In effect, the state represents the last completed action. * All routines are about transitioning to the next state * (which might actually be the same state). * * IKE V1 messages are sometimes called [MAQ][IR]n where * - M stands for Main Mode (Phase 1); * A stands for Aggressive Mode (Phase 1); * Q stands for Quick Mode (Phase 2) * - I stands for Initiator; * R stands for Responder * - n, a digit, stands for the number of the message from this role * within this exchange * * It would be more convenient if each state accepted a message * and produced one. This is not the case for states at the start * or end of an exchange. To fix this, we pretend that there are * MR0 and QR0 messages before the MI1 and QR1 messages. * * STATE_MAIN_R0 and STATE_QUICK_R0 are ephemeral states (not * retained between messages) representing the state that accepts the * first message of an exchange that has been read but not yet processed * and accepted. * * v1_state_microcode_table in ikev1.c and * v2_state_microcode_table in ikev2.c describe * other important details. */ enum state_kind { STATE_UNDEFINED, /* IKE states */ STATE_IKEv1_FLOOR, STATE_MAIN_R0 = STATE_IKEv1_FLOOR, STATE_MAIN_I1, STATE_MAIN_R1, STATE_MAIN_I2, STATE_MAIN_R2, STATE_MAIN_I3, STATE_MAIN_R3, STATE_MAIN_I4, STATE_AGGR_R0, STATE_AGGR_I1, STATE_AGGR_R1, STATE_AGGR_I2, STATE_AGGR_R2, STATE_QUICK_R0, STATE_QUICK_I1, STATE_QUICK_R1, STATE_QUICK_I2, STATE_QUICK_R2, STATE_INFO, STATE_INFO_PROTECTED, /* Xauth states */ STATE_XAUTH_R0, /* server state has sent request, awaiting reply */ STATE_XAUTH_R1, /* server state has sent success/fail, awaiting reply */ STATE_MODE_CFG_R0, /* these states are used on the responder */ STATE_MODE_CFG_R1, STATE_MODE_CFG_R2, STATE_MODE_CFG_I1, /* this is used on the initiator */ STATE_XAUTH_I0, /* client state is awaiting request */ STATE_XAUTH_I1, /* client state is awaiting result code */ STATE_IKEv1_ROOF, /* not a state! */ /* * IKEv2 states. * * Note that message reliably sending is done by initiator * only, unlike with IKEv1. */ STATE_IKEv2_FLOOR, /* INITIATOR states */ STATE_PARENT_I0 = STATE_IKEv2_FLOOR, /* waiting for KE to finish */ STATE_PARENT_I1, /* IKE_SA_INIT: sent initial message, waiting for reply */ STATE_PARENT_I2, /* IKE_AUTH: sent auth message, waiting for reply */ STATE_PARENT_I3, /* IKE_AUTH done: received auth response */ /* * RESPONDER states * No real actions, initiator is responsible * for all work states. * ??? what does that mean? */ STATE_PARENT_R0, /* just starting */ STATE_PARENT_R1, /* IKE_SA_INIT: sent response */ STATE_PARENT_R2, /* IKE_AUTH: sent response */ /* IKEv2 CREATE_CHILD_SA INITIATOR states */ STATE_V2_CREATE_I0, /* ephemeral: sent nothing yet */ STATE_V2_CREATE_I, /* sent first message of CREATE_CHILD new IPsec */ STATE_V2_REKEY_IKE_I0, /* ephemeral: sent nothing yet */ STATE_V2_REKEY_IKE_I, /* sent first message (via parrenti) to rekey parent */ STATE_V2_REKEY_CHILD_I0, STATE_V2_REKEY_CHILD_I, /* sent first message (via parent to rekey child sa. */ /* IKEv2 CREATE_CHILD_SA Responder states */ STATE_V2_CREATE_R, /* ephemeral: sent nothing yet. */ STATE_V2_REKEY_IKE_R, /* ephemeral: sent nothing yet terminal state STATE_PARENT_R2 */ STATE_V2_REKEY_CHILD_R, STATE_V2_IPSEC_I, /* IPsec SA final state - CREATE_CHILD & AUTH */ STATE_V2_IPSEC_R, /* IKEv2 Delete States */ STATE_IKESA_DEL, STATE_CHILDSA_DEL, STATE_IKEv2_ROOF /* not a state! */ }; /* STATE_IKEv2_ROOF lurks in the code so leave space for it */ #define STATE_IKE_ROOF (STATE_IKEv2_ROOF+1) /* not a state! */ /* * The IKEv2 (RFC 7296) original role. Either the "original * initiator" or the "original responder" as identified by the I * (Initiator flag). * * The "original initiator" will set the I (Initiator) flag * (ISAKMP_FLAGS_v2_IKE_I) when sending either the initial SA_INIT * packet or CREATE_CHILD_SA rekey-ike request. The original * responder will see the I flag set in all packets it receives from * the original initiator. * * The IKEv1 equivalent is the phase1 role. It is identified by the * IKEv1 IS_PHASE1_INIT() macro. * * The values are chosen such that no role has values that overlap. * * XXX: If IKEv2 code correctly uses CHILD_SA and IKE_SA then the, is * probably be redundant - An IKE SA's SA_ROLE should be consistent * with its ORIGINAL_ROLE. Currently code isn't consistent, so both * are used/defined. */ enum original_role { /* values follow after enum message_role */ ORIGINAL_INITIATOR = 5, /* IKE_I present */ ORIGINAL_RESPONDER = 6, /* IKE_I missing */ }; /* * The IKEv2 message role. Is this message a request or a response * (to a request) as determined by the IKEv2 "R (Response)" flag. * * Since either end can initiate a request either end can set the * R(Repsonse) flag. * * During a CHILD_SA exchange it is the request initiator (receives * the MESSAGE_RESPONSE) and request responder (receives the * MESSAGE_REQUEST), and not the original (IKE SA) initiator / * responder that determine how crypto material is carved up. * * The values are chosen such that no role has values that overlap. */ enum message_role { NO_MESSAGE = 0, /* values follow after enum sa_role */ MESSAGE_REQUEST = 3, /* MSG_R missing */ MESSAGE_RESPONSE = 4, /* MSR_R present */ /* followed by enum original_role */ }; extern struct keywords message_role_names; /* * The SA role determined by who initiated the SA. * * For all IKEv2 exchanges establishing or rekeying an SA it is * determined by who initiated that SA exchange. During the exchange, * the SA_INITIATOR will always have the R(esponse) bit clear and the * SA_RESPONDER will always have the R(esponse) bit set. * * The IKE SA's role is used to identify which SPI (cookie) to use in * the header by setting or clearing the I(Initiator) flag. * * The IKE or CHILD SA role is used when assigning keying material. * * The IKEv1 equivalent is the phase1 role. It is identified by the * IKEv1 IS_PHASE1_INIT() macro. * * The values are chosen such that no role has values that overlap. */ enum sa_role { SA_INITIATOR = 1, SA_RESPONDER = 2, /* followed by enum message_role */ }; extern struct keywords sa_role_names; #define PHASE1_INITIATOR_STATES (LELEM(STATE_MAIN_I1) | \ LELEM(STATE_MAIN_I2) | \ LELEM(STATE_MAIN_I3) | \ LELEM(STATE_MAIN_I4) | \ LELEM(STATE_AGGR_I1) | \ LELEM(STATE_AGGR_I2) | \ LELEM(STATE_XAUTH_I0) | \ LELEM(STATE_XAUTH_I1) | \ LELEM(STATE_MODE_CFG_I1)) #define IS_PHASE1_INIT(s) ((LELEM(s->kind) & PHASE1_INITIATOR_STATES) != LEMPTY) #define IS_PHASE1(s) (STATE_MAIN_R0 <= (s) && (s) <= STATE_AGGR_R2) #define IS_PHASE15(s) (STATE_XAUTH_R0 <= (s) && (s) <= STATE_XAUTH_I1) #define IS_QUICK(s) (STATE_QUICK_R0 <= (s) && (s) <= STATE_QUICK_R2) #define ISAKMP_ENCRYPTED_STATES (LRANGE(STATE_MAIN_R2, STATE_MAIN_I4) | \ LRANGE(STATE_AGGR_R1, STATE_AGGR_R2) | \ LRANGE(STATE_QUICK_R0, STATE_QUICK_R2) | \ LELEM(STATE_INFO_PROTECTED) | \ LRANGE(STATE_XAUTH_R0, STATE_XAUTH_I1)) #define IS_ISAKMP_ENCRYPTED(s) ((LELEM(s) & ISAKMP_ENCRYPTED_STATES) != LEMPTY) /* ??? Is this really authenticate? Even in xauth case? In STATE_INFO case? */ #define IS_ISAKMP_AUTHENTICATED(s) (STATE_MAIN_R3 <= (s->kind) && \ STATE_AGGR_R0 != (s->kind) && \ STATE_AGGR_I1 != (s->kind)) #define IKEV2_ISAKMP_INITIATOR_STATES (LELEM(STATE_PARENT_I0) | \ LELEM(STATE_PARENT_I1) | \ LELEM(STATE_PARENT_I2)) #define ISAKMP_SA_ESTABLISHED_STATES (LELEM(STATE_MAIN_R3) | \ LELEM(STATE_MAIN_I4) | \ LELEM(STATE_AGGR_I2) | \ LELEM(STATE_AGGR_R2) | \ LELEM(STATE_XAUTH_R0) | \ LELEM(STATE_XAUTH_R1) | \ LELEM(STATE_MODE_CFG_R0) | \ LELEM(STATE_MODE_CFG_R1) | \ LELEM(STATE_MODE_CFG_R2) | \ LELEM(STATE_MODE_CFG_I1) | \ LELEM(STATE_XAUTH_I0) | \ LELEM(STATE_XAUTH_I1) | \ LELEM(STATE_PARENT_I3) | \ LELEM(STATE_PARENT_R2)) #define IS_ISAKMP_SA_ESTABLISHED(s) ((LELEM(s->kind) & ISAKMP_SA_ESTABLISHED_STATES) != LEMPTY) #define IPSECSA_PENDING_STATES (LELEM(STATE_V2_CREATE_I) | \ LELEM(STATE_V2_CREATE_I0) | \ LELEM(STATE_V2_CREATE_R) | \ /* due to a quirk in initiator duplication next one is also needed */ \ LELEM(STATE_PARENT_I2)) /* IKEv1 or IKEv2 */ #define IS_IPSEC_SA_ESTABLISHED(s) (IS_CHILD_SA(s) && \ ((s->st_state->kind) == STATE_QUICK_I2 || \ (s->st_state->kind) == STATE_QUICK_R1 || \ (s->st_state->kind) == STATE_QUICK_R2 || \ (s->st_state->kind) == STATE_V2_IPSEC_I || \ (s->st_state->kind) == STATE_V2_IPSEC_R)) #define IS_MODE_CFG_ESTABLISHED(s) ((s->kind) == STATE_MODE_CFG_R2) /* Only relevant to IKEv2 */ /* adding for just a R2 or I3 check. Will need to be changed when parent/child discerning is fixed */ #define IS_V2_ESTABLISHED(s) ((s->kind) == STATE_PARENT_R2 || \ (s->kind) == STATE_PARENT_I3 || (s->kind) == STATE_V2_IPSEC_I || \ (s->kind) == STATE_V2_IPSEC_R) #define IS_IKE_SA_ESTABLISHED(st) \ ( IS_ISAKMP_SA_ESTABLISHED(st->st_state) || \ (IS_PARENT_SA_ESTABLISHED(st) && \ (st->st_clonedfrom == SOS_NOBODY))) /* * ??? Issue here is that our child SA appears as a * STATE_PARENT_I3/STATE_PARENT_R2 state which it should not. * So we fall back to checking if it is cloned, and therefore really a child. */ #define IS_CHILD_SA_ESTABLISHED(st) \ ((st->st_state->kind == STATE_V2_IPSEC_I || st->st_state->kind == STATE_V2_IPSEC_R) && \ IS_CHILD_SA(st)) #define IS_PARENT_SA_ESTABLISHED(st) \ (((st)->st_state->kind == STATE_PARENT_I3 || (st)->st_state->kind == STATE_PARENT_R2) && \ !IS_CHILD_SA(st)) #define IS_CHILD_SA(st) ((st)->st_clonedfrom != SOS_NOBODY) #define IS_IKE_SA(st) ((st)->st_clonedfrom == SOS_NOBODY) /* kind of struct connection * Ordered (mostly) by concreteness. Order is exploited. */ enum connection_kind { CK_INVALID = 0, /* better name? */ CK_GROUP, /* policy group: instantiates to template */ CK_TEMPLATE, /* abstract connection, with wildcard */ CK_PERMANENT, /* normal connection */ CK_INSTANCE, /* instance of template, created for a particular attempt */ CK_GOING_AWAY /* instance being deleted -- don't delete again */ }; /* routing status. * Note: routing ignores source address, but erouting does not! * Note: a connection can only be routed if it is NEVER_NEGOTIATE * or HAS_IPSEC_POLICY. */ /* note that this is assumed to be ordered! */ enum routing_t { RT_UNROUTED, /* unrouted */ RT_UNROUTED_HOLD, /* unrouted, but HOLD shunt installed */ RT_ROUTED_ECLIPSED, /* RT_ROUTED_PROSPECTIVE except bare HOLD or instance has eroute */ RT_ROUTED_PROSPECTIVE, /* routed, and prospective shunt installed */ RT_ROUTED_HOLD, /* routed, and HOLD shunt installed */ RT_ROUTED_FAILURE, /* routed, and failure-context shunt installed */ RT_ROUTED_TUNNEL, /* routed, and erouted to an IPSEC SA group */ RT_UNROUTED_KEYED, /* keyed, but not routed, on purpose */ }; #define routed(rs) ((rs) > RT_UNROUTED_HOLD) #define erouted(rs) ((rs) != RT_UNROUTED) #define shunt_erouted(rs) (erouted(rs) && (rs) != RT_ROUTED_TUNNEL) enum certpolicy { CERT_NEVERSEND = 1, CERT_SENDIFASKED = 2, /* the default */ CERT_ALWAYSSEND = 3, }; /* this is the default setting. */ #define cert_defaultcertpolicy CERT_ALWAYSSEND enum ikev1_natt_policy { NATT_BOTH = 0, /* the default */ NATT_RFC = 1, NATT_DRAFTS = 2, /* Workaround for Cisco NAT-T bug */ NATT_NONE = 3 /* Workaround for forcing non-encaps */ }; enum four_options { fo_never = 0, /* do not propose, do not permit */ fo_permit = 1, /* do not propose, but permit peer to propose */ fo_propose = 2, /* propose, and permit, but do not insist */ fo_insist = 3 /* propose, and only accept if peer agrees */ }; enum ynf_options { ynf_no = 0, ynf_yes = 1, ynf_force = 2, }; enum yn_options { yn_no = 0, yn_yes = 1, }; enum yna_options { yna_auto = 1, /* default */ yna_no = 2, yna_yes = 3, }; enum esn_options { ESN_NO = 1, /* default */ ESN_YES = 2, ESN_EITHER = 3, }; enum saref_tracking { SAT_YES = 0, /* SAref tracking via _updown - the default */ SAT_NO = 1, /* no SAref tracking - third party will handle this */ SAT_CONNTRACK = 2, /* Saref tracking using connmark optimizations */ }; /* Policies for establishing an SA * * These are used to specify attributes (eg. encryption) and techniques * (eg PFS) for an SA. * Note: certain CD_ definitions in whack.c parallel these -- keep them * in sync! */ extern const char *prettypolicy(lset_t policy); /* * ISAKMP policy elements. * * A pluto policy is stored in a lset_t so we could have up to 64 elements. * Certain policies are more than present/absent and take more than one bit. * * We need both the bit number (*_IX) and the singleton set for each. * The bit numbers are assigned automatically in enum sa_policy_bits. * * The singleton set version is potentially too big for an enum * so these are exhausively defined as macros. As are derived values. * * Changes to sa_policy_bits must be reflected in #defines below it and * in sa_policy_bit_names. */ enum sa_policy_bits { /* * XXX: Do not re-order or re-number the following pair. Bad * things happen. * * (They are used to index an array in spdb.c when determining * default IKEv1 proposals; arguably the array should be * deleted but that is another story). */ POLICY_PSK_IX = 0, POLICY_RSASIG_IX = 1, POLICY_ECDSA_IX = 2, POLICY_AUTH_NEVER_IX, POLICY_AUTH_NULL_IX, #define POLICY_ID_AUTH_MASK LRANGE(POLICY_PSK_IX, POLICY_AUTH_NULL_IX) POLICY_ENCRYPT_IX, /* must be first of IPSEC policies */ POLICY_AUTHENTICATE_IX, /* must be second */ POLICY_COMPRESS_IX, /* must be third */ POLICY_TUNNEL_IX, POLICY_PFS_IX, POLICY_DISABLEARRIVALCHECK_IX, /* suppress tunnel egress address checking */ POLICY_DECAP_DSCP_IX, /* decapsulate ToS/DSCP bits */ POLICY_NOPMTUDISC_IX, POLICY_MSDH_DOWNGRADE_IX, /* allow IKEv2 rekey to downgrade DH group - Microsoft bug */ POLICY_ALLOW_NO_SAN_IX, /* allow a certificate conn to not have IKE ID on cert SAN */ POLICY_DNS_MATCH_ID_IX, /* perform reverse DNS lookup on IP to confirm ID */ POLICY_SHA2_TRUNCBUG_IX, /* workaround old Linux kernel (android 4.x) */ #define POLICY_IPSEC_SHIFT POLICY_ENCRYPT_IX #define POLICY_IPSEC_MASK LRANGE(POLICY_ENCRYPT_IX, POLICY_DISABLEARRIVALCHECK_IX) /* shunt attributes: what to do when routed without tunnel (2 bits) */ POLICY_SHUNT0_IX, POLICY_SHUNT1_IX, #define POLICY_SHUNT_SHIFT POLICY_SHUNT0_IX #define POLICY_SHUNT_MASK LRANGE(POLICY_SHUNT0_IX, POLICY_SHUNT1_IX) #define POLICY_SHUNT_TRAP (0 * LELEM(POLICY_SHUNT0_IX)) /* default: negotiate */ #define POLICY_SHUNT_PASS (1 * LELEM(POLICY_SHUNT0_IX)) #define POLICY_SHUNT_DROP (2 * LELEM(POLICY_SHUNT0_IX)) #define POLICY_SHUNT_REJECT (3 * LELEM(POLICY_SHUNT0_IX)) /* fail attributes: what to do with failed negotiation (2 bits) */ POLICY_FAIL0_IX, POLICY_FAIL1_IX, #define POLICY_FAIL_SHIFT POLICY_FAIL0_IX #define POLICY_FAIL_MASK LRANGE(POLICY_FAIL0_IX, POLICY_FAIL1_IX) #define POLICY_FAIL_NONE (0 * LELEM(POLICY_FAIL0_IX)) /* default */ #define POLICY_FAIL_PASS (1 * LELEM(POLICY_FAIL0_IX)) #define POLICY_FAIL_DROP (2 * LELEM(POLICY_FAIL0_IX)) #define POLICY_FAIL_REJECT (3 * LELEM(POLICY_FAIL0_IX)) /* connection policy * Other policies could vary per state object. These live in connection. */ POLICY_NEGO_PASS_IX, /* install %pass instead of %hold during initial IKE */ POLICY_DONT_REKEY_IX, /* don't rekey state either Phase */ POLICY_REAUTH_IX, /* IKEv2 only initiate re-authentication */ POLICY_OPPORTUNISTIC_IX, /* is this opportunistic? */ POLICY_GROUP_IX, /* is this a group template? */ POLICY_GROUTED_IX, /* do we want this group routed? */ POLICY_GROUPINSTANCE_IX, /* is this a group template instance? */ POLICY_UP_IX, /* do we want this up? */ POLICY_XAUTH_IX, /* do we offer XAUTH? */ POLICY_MODECFG_PULL_IX, /* is modecfg pulled by client? */ POLICY_AGGRESSIVE_IX, /* do we do aggressive mode? */ POLICY_OVERLAPIP_IX, /* can two conns that have subnet=vhost: declare the same IP? */ /* * this is mapped by parser's ikev2={four_state}. It is a bit richer * in that we can actually turn off everything, but it expands more * sensibly to an IKEv3 and other methods. */ POLICY_IKEV1_ALLOW_IX, /* !accept IKEv1? 0x0100 0000 */ POLICY_IKEV2_ALLOW_IX, /* accept IKEv2? 0x0200 0000 */ POLICY_IKEV2_ALLOW_NARROWING_IX, /* Allow RFC-5669 section 2.9? 0x0800 0000 */ POLICY_IKEV2_PAM_AUTHORIZE_IX, POLICY_SEND_REDIRECT_ALWAYS_IX, /* next three policies are for RFC 5685 */ POLICY_SEND_REDIRECT_NEVER_IX, #define POLICY_SEND_REDIRECT_MASK \ LRANGE(POLICY_SEND_REDIRECT_ALWAYS_IX, POLICY_SEND_REDIRECT_NEVER_IX) POLICY_ACCEPT_REDIRECT_YES_IX, POLICY_SAREF_TRACK_IX, /* Saref tracking via _updown */ POLICY_SAREF_TRACK_CONNTRACK_IX, /* use conntrack optimization */ POLICY_IKE_FRAG_ALLOW_IX, POLICY_IKE_FRAG_FORCE_IX, #define POLICY_IKE_FRAG_MASK LRANGE(POLICY_IKE_FRAG_ALLOW_IX,POLICY_IKE_FRAG_FORCE_IX) POLICY_NO_IKEPAD_IX, /* pad ike packets to 4 bytes or not */ POLICY_MOBIKE_IX, /* allow MOBIKE */ POLICY_PPK_ALLOW_IX, POLICY_PPK_INSIST_IX, POLICY_ESN_NO_IX, /* send/accept ESNno */ POLICY_ESN_YES_IX, /* send/accept ESNyes */ POLICY_RSASIG_v1_5_IX, #define POLICY_IX_LAST POLICY_RSASIG_v1_5_IX }; #define POLICY_PSK LELEM(POLICY_PSK_IX) #define POLICY_RSASIG LELEM(POLICY_RSASIG_IX) #define POLICY_ECDSA LELEM(POLICY_ECDSA_IX) #define POLICY_AUTH_NEVER LELEM(POLICY_AUTH_NEVER_IX) #define POLICY_AUTH_NULL LELEM(POLICY_AUTH_NULL_IX) #define POLICY_ENCRYPT LELEM(POLICY_ENCRYPT_IX) /* must be first of IPSEC policies */ #define POLICY_AUTHENTICATE LELEM(POLICY_AUTHENTICATE_IX) /* must be second */ #define POLICY_COMPRESS LELEM(POLICY_COMPRESS_IX) /* must be third */ #define POLICY_TUNNEL LELEM(POLICY_TUNNEL_IX) #define POLICY_PFS LELEM(POLICY_PFS_IX) #define POLICY_DISABLEARRIVALCHECK LELEM(POLICY_DISABLEARRIVALCHECK_IX) /* suppress tunnel egress address checking */ #define POLICY_DECAP_DSCP LELEM(POLICY_DECAP_DSCP_IX) /* decap ToS/DSCP bits */ #define POLICY_NOPMTUDISC LELEM(POLICY_NOPMTUDISC_IX) #define POLICY_MSDH_DOWNGRADE LELEM(POLICY_MSDH_DOWNGRADE_IX) #define POLICY_ALLOW_NO_SAN LELEM(POLICY_ALLOW_NO_SAN_IX) #define POLICY_DNS_MATCH_ID LELEM(POLICY_DNS_MATCH_ID_IX) #define POLICY_SHA2_TRUNCBUG LELEM(POLICY_SHA2_TRUNCBUG_IX) #define POLICY_SHUNT0 LELEM(POLICY_SHUNT0_IX) #define POLICY_SHUNT1 LELEM(POLICY_SHUNT1_IX) #define POLICY_FAIL0 LELEM(POLICY_FAIL0_IX) #define POLICY_FAIL1 LELEM(POLICY_FAIL1_IX) #define POLICY_NEGO_PASS LELEM(POLICY_NEGO_PASS_IX) /* install %pass during initial IKE */ #define POLICY_DONT_REKEY LELEM(POLICY_DONT_REKEY_IX) /* don't rekey state either Phase */ #define POLICY_REAUTH LELEM(POLICY_REAUTH_IX) /* IKEv2 initiate reauthentication instead of rekey */ #define POLICY_OPPORTUNISTIC LELEM(POLICY_OPPORTUNISTIC_IX) /* is this opportunistic? */ #define POLICY_GROUP LELEM(POLICY_GROUP_IX) /* is this a group template? */ #define POLICY_GROUTED LELEM(POLICY_GROUTED_IX) /* do we want this group routed? */ #define POLICY_GROUPINSTANCE LELEM(POLICY_GROUPINSTANCE_IX) /* is this a group template instance? */ #define POLICY_UP LELEM(POLICY_UP_IX) /* do we want this up? */ #define POLICY_XAUTH LELEM(POLICY_XAUTH_IX) /* do we offer XAUTH? */ #define POLICY_MODECFG_PULL LELEM(POLICY_MODECFG_PULL_IX) /* is modecfg pulled by client? */ #define POLICY_AGGRESSIVE LELEM(POLICY_AGGRESSIVE_IX) /* do we do aggressive mode? */ #define POLICY_OVERLAPIP LELEM(POLICY_OVERLAPIP_IX) /* can two conns that have subnet=vhost: declare the same IP? */ #define POLICY_IKEV1_ALLOW LELEM(POLICY_IKEV1_ALLOW_IX) /* !accept IKEv1? 0x0100 0000 */ #define POLICY_IKEV2_ALLOW LELEM(POLICY_IKEV2_ALLOW_IX) /* accept IKEv2? 0x0200 0000 */ #define POLICY_IKEV2_ALLOW_NARROWING LELEM(POLICY_IKEV2_ALLOW_NARROWING_IX) /* Allow RFC-5669 section 2.9? 0x0800 0000 */ #define POLICY_IKEV2_PAM_AUTHORIZE LELEM(POLICY_IKEV2_PAM_AUTHORIZE_IX) /* non-standard, custom PAM authorize call on ID */ #define POLICY_SEND_REDIRECT_ALWAYS LELEM(POLICY_SEND_REDIRECT_ALWAYS_IX) #define POLICY_SEND_REDIRECT_NEVER LELEM(POLICY_SEND_REDIRECT_NEVER_IX) #define POLICY_ACCEPT_REDIRECT_YES LELEM(POLICY_ACCEPT_REDIRECT_YES_IX) #define POLICY_SAREF_TRACK LELEM(POLICY_SAREF_TRACK_IX) /* Saref tracking via _updown */ #define POLICY_SAREF_TRACK_CONNTRACK LELEM(POLICY_SAREF_TRACK_CONNTRACK_IX) /* use conntrack optimization */ #define POLICY_IKE_FRAG_ALLOW LELEM(POLICY_IKE_FRAG_ALLOW_IX) #define POLICY_IKE_FRAG_FORCE LELEM(POLICY_IKE_FRAG_FORCE_IX) #define POLICY_NO_IKEPAD LELEM(POLICY_NO_IKEPAD_IX) /* pad ike packets to 4 bytes or not */ #define POLICY_MOBIKE LELEM(POLICY_MOBIKE_IX) /* allow MOBIKE */ #define POLICY_PPK_ALLOW LELEM(POLICY_PPK_ALLOW_IX) #define POLICY_PPK_INSIST LELEM(POLICY_PPK_INSIST_IX) #define POLICY_ESN_NO LELEM(POLICY_ESN_NO_IX) /* accept or request ESNno */ #define POLICY_ESN_YES LELEM(POLICY_ESN_YES_IX) /* accept or request ESNyes */ #define POLICY_RSASIG_v1_5 LELEM(POLICY_RSASIG_v1_5_IX) #define NEGOTIATE_AUTH_HASH_SHA1 LELEM(IKEv2_AUTH_HASH_SHA1) /* rfc7427 does responder support SHA1? */ #define NEGOTIATE_AUTH_HASH_SHA2_256 LELEM(IKEv2_AUTH_HASH_SHA2_256) /* rfc7427 does responder support SHA2-256? */ #define NEGOTIATE_AUTH_HASH_SHA2_384 LELEM(IKEv2_AUTH_HASH_SHA2_384) /* rfc7427 does responder support SHA2-384? */ #define NEGOTIATE_AUTH_HASH_SHA2_512 LELEM(IKEv2_AUTH_HASH_SHA2_512) /* rfc7427 does responder support SHA2-512? */ #define NEGOTIATE_AUTH_HASH_IDENTITY LELEM(IKEv2_AUTH_HASH_IDENTITY) /* rfc4307-bis does responder support IDENTITY? */ enum sighash_policy_bits { POL_SIGHASH_SHA2_256_IX, POL_SIGHASH_SHA2_384_IX, POL_SIGHASH_SHA2_512_IX, }; #define POL_SIGHASH_SHA2_256 LELEM(POL_SIGHASH_SHA2_256_IX) #define POL_SIGHASH_SHA2_384 LELEM(POL_SIGHASH_SHA2_384_IX) #define POL_SIGHASH_SHA2_512 LELEM(POL_SIGHASH_SHA2_512_IX) /* Default policy for now is using RSA - this might change to ECC */ #define POLICY_DEFAULT POLICY_RSASIG /* These policy bits must match exactly: POLICY_XAUTH, POLICY_AGGRESSIVE, POLICY_IKEV1_ALLOW */ /* Any IPsec policy? If not, a connection description * is only for ISAKMP SA, not IPSEC SA. (A pun, I admit.) * Note: a connection can only be routed if it is NEVER_NEGOTIATE * or HAS_IPSEC_POLICY. */ #define HAS_IPSEC_POLICY(p) (((p) & POLICY_IPSEC_MASK) != 0) #define NEVER_NEGOTIATE(p) (LDISJOINT((p), POLICY_ENCRYPT | POLICY_AUTHENTICATE)) /* values for right=/left= */ enum keyword_host { KH_NOTSET = 0, KH_DEFAULTROUTE = 1, KH_ANY = 2, KH_IFACE = 3, KH_OPPO = 4, KH_OPPOGROUP = 5, KH_GROUP = 6, KH_IPHOSTNAME = 7, /* host_addr invalid, only string */ KH_IPADDR = LOOSE_ENUM_OTHER, }; /* * related(???) libunbound enumerated types * * How authenticated is info that might have come from DNS? * In order of increasing confidence. */ enum dns_auth_level { /* 0 is reserved so uninitialized values are meaningless */ PUBKEY_LOCAL = 1, /* came from local source, whack, plugin etc */ DNSSEC_INSECURE, /* UB returned INSECURE */ DNSSEC_SECURE, /* UB returned SECURE */ DNSSEC_ROOF }; /* * private key types for keys.h */ enum PrivateKeyKind { /* start at one so accidental 0 will not match */ PKK_PSK = 1, PKK_RSA, PKK_XAUTH, PKK_PPK, PKK_ECDSA, /* should not be needed */ PKK_NULL, PKK_INVALID, }; #define XAUTH_PROMPT_TRIES 3 #define MAX_XAUTH_USERNAME_LEN 128 #define XAUTH_MAX_PASS_LENGTH 128 #define MIN_LIVENESS 1 enum pluto_exit_code { PLUTO_EXIT_OK = 0, PLUTO_EXIT_FAIL = 1, PLUTO_EXIT_SOCKET_FAIL = 2, PLUTO_EXIT_FORK_FAIL = 3, PLUTO_EXIT_FIPS_FAIL = 4, PLUTO_EXIT_KERNEL_FAIL = 5, PLUTO_EXIT_NSS_FAIL = 6, PLUTO_EXIT_AUDIT_FAIL = 7, PLUTO_EXIT_SECCOMP_FAIL = 8, PLUTO_EXIT_UNBOUND_FAIL = 9, PLUTO_EXIT_LOCK_FAIL = 10, /* historic value */ }; #define SWAN_MAX_DOMAIN_LEN 256 /* includes nul termination */ extern void init_pluto_constants(void); /* * IPsec SA SPD policy priorities. * A smaller value is a higher priority. * The bands we use must have 2<<20 distinct values. * manual by user [0 * 1<<20, 1 * 1<<20) * static conn [1 * 1<<20, 2 * 1<<20) * opportunistic [2 * 1<<20, 3 * 1<<20) * oe-anonymous [3 * 1<<20, 4 * 1<<20) */ #define PLUTO_SPD_MANUAL_MAX (1u * (1u << 20) - 1u) /* not yet used */ #define PLUTO_SPD_STATIC_MAX (2u * (1u << 20) - 1u) #define PLUTO_SPD_OPPO_MAX (3u * (1u << 20) - 1u) #define PLUTO_SPD_OPPO_ANON_MAX (4u * (1u << 20) - 1u) /* * Maximum data (inluding IKE HDR) allowed in a packet. * * v1 fragmentation is non-IETF magic voodoo we need to consider for interop: * - www.cisco.com/en/US/docs/ios/sec_secure_connectivity/configuration/guide/sec_fragment_ike_pack.html * - www.cisco.com/en/US/docs/ios-xml/ios/sec_conn_ikevpn/configuration/15-mt/sec-fragment-ike-pack.pdf * - msdn.microsoft.com/en-us/library/cc233452.aspx * - iOS/Apple racoon source ipsec-164.9 at www.opensource.apple.com (frak length 1280) * - stock racoon source (frak length 552) * * v2 fragmentation is RFC7383. * * What is a sane and safe value? iOS/Apple uses 1280, stock racoon uses 552. * Why is there no RFC to guide interop people here :/ * * UDP packet overhead: the number of bytes of header and pseudo header * - v4 UDP: 20 source addr, dest addr, protocol, length, source port, destination port, length, checksum * - v6 UDP: 48 (similar) * * Other considerations: * - optional non-ESP Marker: 4 NON_ESP_MARKER_SIZE * - ISAKMP header * - encryption representation overhead */ #define MIN_MAX_UDP_DATA_v4 (576 - 20) /* this length must work */ #define MIN_MAX_UDP_DATA_v6 (1280 - 48) /* this length must work */ // #define OVERHEAD_NON_FRAG_v1 (2*4 + 16) /* ??? what is this number? */ // #define OVERHEAD_NON_FRAG_v2 (2*4 + 16) /* ??? what is this number? */ /* * ??? perhaps all current uses are not about fragment size, but how large * the content of a packet (ie. excluding UDP headers) can be allowed before * fragmentation must be considered. */ #define ISAKMP_V1_FRAG_OVERHEAD_IPv4 (2*4 + 16) /* ??? */ #define ISAKMP_V1_FRAG_MAXLEN_IPv4 (MIN_MAX_UDP_DATA_v4 - ISAKMP_V1_FRAG_OVERHEAD_IPv4) #define ISAKMP_V1_FRAG_OVERHEAD_IPv6 40 /* ??? */ #define ISAKMP_V1_FRAG_MAXLEN_IPv6 (MIN_MAX_UDP_DATA_v6 - ISAKMP_V1_FRAG_OVERHEAD_IPv6) /* ??? it is unlikely that the v2 numbers should match the v1 numbers */ #define ISAKMP_V2_FRAG_OVERHEAD_IPv4 (2*4 + 16) /* ??? !!! */ #define ISAKMP_V2_FRAG_MAXLEN_IPv4 (MIN_MAX_UDP_DATA_v4 - ISAKMP_V2_FRAG_OVERHEAD_IPv4) #define ISAKMP_V2_FRAG_OVERHEAD_IPv6 40 /* ??? !!! */ #define ISAKMP_V2_FRAG_MAXLEN_IPv6 (MIN_MAX_UDP_DATA_v6 - ISAKMP_V1_FRAG_OVERHEAD_IPv6) libreswan-3.32/include/proposals.h000066400000000000000000000171751365625662500173000ustar00rootroot00000000000000/* Proposals, for libreswan * * Author: JuanJo Ciarlante * Copyright (C) 2007 Michael Richardson * Copyright (C) 2012-2013 Paul Wouters * Copyright (C) 2013 D. Hugh Redelmeier * Copyright (C) 2013 Paul Wouters * Copyright (C) 2015-2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef PROPOSALS_H #define PROPOSALS_H /* * XXX: rename v[23]_proposal to proposal_v[12]. */ #include "lswcdefs.h" #include "constants.h" #include "ike_alg.h" #include "shunk.h" struct alg_info; struct proposal_protocol; struct proposal; struct proposals; struct proposal_policy; struct proposal_parser; /* * XXX: needs to be merged with IKE_ALG_TYPE. */ enum proposal_algorithm { PROPOSAL_encrypt, PROPOSAL_prf, PROPOSAL_integ, PROPOSAL_dh, PROPOSAL_ALGORITHM_ROOF, }; /* * Everything combined. */ struct proposal_parser { const struct proposal_protocol *protocol; const struct proposal_param *param; const struct proposal_policy *policy; /* need to eliminate hardwired size */ char error[200]; }; /* * Parameters to tune the parser. */ struct proposal_policy { enum ike_version version; unsigned parser_version; bool pfs; /* For CHILD SA, use DH from IKE SA */ bool check_pfs_vs_dh; bool ignore_parser_errors; /* * According to current policy, is the algorithm ok * (supported)? If it isn't return FALSE. * * For instance, an IKE algorithm requires in-process support; * while an ESP/AH algorithm requires kernel support. */ bool (*alg_is_ok)(const struct ike_alg *alg); /* * Print a warning. Signature needs to match libreswan_log. */ int (*warning)(const char *fmt, ...) PRINTF_LIKE(1); }; /* * Defaults the parser uses to fill things in. */ struct proposal_defaults { /* * Proposals to parse when the parser is called with a NULL * proposals string. */ const char *proposals; /* * Algorithms to add to the proposal when they were not * specified by the proposal string. */ const struct ike_alg **dh; const struct ike_alg **prf; const struct ike_alg **integ; const struct ike_alg **encrypt; }; /* * The protocol - ESP/AH/IKE - the parser is processing. */ typedef const struct ike_alg *(alg_byname_fn)(struct proposal_parser *parser, shunk_t name, size_t key_bit_length, shunk_t print_name); struct proposal_protocol { const char *name; enum ike_alg_key ikev1_alg_id; /* * Lists of defaults for both IKE version. */ const struct proposal_defaults *defaults[IKE_VERSION_ROOF]; /* * Is the proposal OK? * * This is the final check, if this succeeds then the proposal * is added. */ bool (*proposal_ok)(struct proposal_parser *parser, const struct proposal *proposal); /* * What algorithms are expected? */ bool encrypt; bool prf; bool integ; bool dh; }; /* * A proposal as decoded by the parser. */ struct algorithm { const struct ike_alg *desc; /* * Because struct encrypt_desc still specifies multiple key * lengths, ENCKEYLEN is still required. */ int enckeylen; /* only one! */ struct algorithm *next; }; /* return counts of encrypt=aead and integ=none */ bool proposal_encrypt_aead(const struct proposal *proposal); bool proposal_encrypt_norm(const struct proposal *proposal); bool proposal_integ_none(const struct proposal *proposal); unsigned nr_proposals(struct proposals *proposals); bool default_proposals(struct proposals *proposals); extern void proposals_addref(struct proposals **proposals); extern void proposals_delref(struct proposals **proposals); extern struct proposal *alloc_proposal(struct proposal_parser *parser); extern void free_proposal(struct proposal **proposal); void free_algorithms(struct proposal *proposal, enum proposal_algorithm algorithm); void append_proposal(struct proposals *proposals, struct proposal **proposal); void append_algorithm(struct proposal_parser *parser, struct proposal *proposal, const struct ike_alg *alg, int enckeylen); struct proposal_parser *alloc_proposal_parser(const struct proposal_policy *policy, const struct proposal_protocol *protocol); void free_proposal_parser(struct proposal_parser **parser); struct proposal_parser *ike_proposal_parser(const struct proposal_policy *policy); struct proposal_parser *esp_proposal_parser(const struct proposal_policy *policy); struct proposal_parser *ah_proposal_parser(const struct proposal_policy *policy); /* * XXX: useful? */ struct ike_proposals { struct proposals *p; }; struct child_proposals { struct proposals *p; }; void fmt_proposal(struct lswlog *log, const struct proposal *proposal); void fmt_proposals(struct lswlog *log, const struct proposals *proposals); /* * Iterate through all the proposals and the proposal's algorithms. * * Use __typeof__ instead of const to get around ALG_INFO some times * being const and sometimes not. */ struct proposal *next_proposal(const struct proposals *proposals, struct proposal *last_proposal); #define FOR_EACH_PROPOSAL(PROPOSALS, PROPOSAL) \ for (struct proposal *PROPOSAL = next_proposal(PROPOSALS, NULL); \ PROPOSAL != NULL; \ PROPOSAL = next_proposal(PROPOSALS, PROPOSAL)) struct algorithm *next_algorithm(const struct proposal *proposal, enum proposal_algorithm algorithm, struct algorithm *last); #define FOR_EACH_ALGORITHM(PROPOSAL, TYPE, ALGORITHM) \ for (struct algorithm *ALGORITHM = next_algorithm(PROPOSAL, PROPOSAL_##TYPE, NULL); \ ALGORITHM != NULL; ALGORITHM = next_algorithm(PROPOSAL, PROPOSAL_##TYPE, ALGORITHM)) /* * Error indicated by err_buf[0] != '\0'. * * POLICY should be used to guard algorithm supported checks. For * instance: if POLICY=IKEV1, then IKEv1 support is required (IKEv2 is * don't care); and if POLICY=IKEV1|IKEV2, then both IKEv1 and IKEv2 * support is required. * * Parsing with POLICY=IKEV1, but then proposing the result using * IKEv2 is a program error. The IKEv2 should complain loudly and, * we hope, not crash. * * Parsing with POLICY='0' is allowed. It will accept the algorithms * unconditionally (spi.c seems to need this). */ struct proposals *proposals_from_str(struct proposal_parser *parser, const char *str); bool v1_proposals_parse_str(struct proposal_parser *parser, struct proposals *proposals, shunk_t alg_str); bool v2_proposals_parse_str(struct proposal_parser *parser, struct proposals *proposals, shunk_t alg_str); /* * Check that encrypt==AEAD and/or integ==none don't contradict. */ bool proposal_aead_none_ok(struct proposal_parser *parser, const struct proposal *proposal); void proposal_error(struct proposal_parser *parser, const char *message, ...) PRINTF_LIKE(2); bool impair_proposal_errors(struct proposal_parser *parser); /* * Convert a generic proposal back into something the IKEv1 code can * digest. */ struct v1_proposal { int enckeylen; const struct encrypt_desc *encrypt; const struct prf_desc *prf; const struct integ_desc *integ; const struct dh_desc *dh; const struct proposal_protocol *protocol; }; struct v1_proposal v1_proposal(const struct proposal *proposal); #endif /* PROPOSALS_H */ libreswan-3.32/include/realtime.h000066400000000000000000000047261365625662500170560ustar00rootroot00000000000000/* realtime objects and functions, for libreswan * * Copyright (C) 1998, 1999, 2000 Henry Spencer. * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs * Copyright (C) 2017, 2018 Andrew Cagney * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. * */ #ifndef REALTIME_H #define REALTIME_H /* seen it, no need to see it again */ #include /* for struct timeval */ #include /* for time_t and struct tm */ #include /* for bool */ #include "deltatime.h" /* for deltatime_t */ struct lswlog; /* * The time objects are wrapped so that dimensional analysis will be * enforced by the compiler. */ /* * realtime_t: absolute UTC time. Might be discontinuous due to clock * adjustment. * * Use struct timeval as that has the supporting macros timeradd(3) * et.al. for performing arithmetic. * * According to the gettimeofday(2) man mage, struct timespec and * clock_gettime(2) are, techncially, a far better choice but they * lack pre-defined operators. */ typedef struct { struct timeval rt; } realtime_t; #define REALTIME_EPOCH {{ 0, 0, }} extern const realtime_t realtime_epoch; realtime_t realtime(time_t time); /* * Formatting. */ typedef struct { char buf[sizeof("--- -- --:--:-- UTC ----")+1/*canary*/]; } realtime_buf; const char *str_realtime(realtime_t r, bool utc, realtime_buf *buf); size_t jam_realtime(jambuf_t *buf, realtime_t r, bool utc); #define lswlog_realtime jam_realtime /* XXX: TBD */ /* * math */ realtime_t realtimesum(realtime_t t, deltatime_t d); bool is_realtime_epoch(realtime_t t); bool realbefore(realtime_t a, realtime_t b); deltatime_t realtimediff(realtime_t a, realtime_t b); realtime_t realnow(void); struct realtm { struct tm tm; long microsec; /* 1 000 000 per second */ }; struct realtm local_realtime(realtime_t t); struct realtm utc_realtime(realtime_t t); /* for pthread_cond_timedwait() */ clockid_t realtime_clockid(void); struct timespec realtime_as_timespec(realtime_t); #endif libreswan-3.32/include/refcnt.h000066400000000000000000000055161365625662500165330ustar00rootroot00000000000000/* reference counting macros * * Copyright (C) 2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #ifndef REFCNT_H #define REFCNT_H #include #include "lswlog.h" /* for pexpect(), for dbg() */ #include "lswcdefs.h" /* for MUST_USE_RESULT */ #include "where.h" typedef struct { unsigned count; } refcnt_t; /* * Initialize the refcnt. * * Note that ref_init(O,HERE) breaks as HERE contains braces. */ void refcnt_init(const char *what, const void *pointer, refcnt_t *refcnt, where_t where); #define ref_init(O, WHERE) \ refcnt_init(#O, O, &(O)->refcnt, WHERE) #define init_ref(O) \ { \ where_t here_ = HERE; \ ref_init(O, here_); \ } void refcnt_add(const char *what, const void *pointer, refcnt_t *refcnt, where_t where); /* * Add a reference. * * Note that ref_add(O,HERE) breaks as HERE contains braces. */ #define ref_add(O, WHERE) \ ({ \ if ((O) == NULL) { \ dbg("addref "#O"@NULL "PRI_WHERE"", pri_where(WHERE)); \ } else { \ refcnt_add(#O, O, &(O)->refcnt, WHERE); \ } \ (O); /* result */ \ }) #define add_ref(O) \ ({ \ where_t here_ = HERE; \ ref_add(O, here_); \ }) /* * Delete a reference. * * Note that ref_delete(O,FREE,HERE) breaks as HERE contains braces. */ bool refcnt_delete(const char *what, const void *pointer, refcnt_t *refcnt, where_t where) MUST_USE_RESULT; #define ref_delete(O, FREE, WHERE) \ { \ if (*(O) == NULL) { \ dbg("delref "#O"@NULL "PRI_WHERE"", pri_where(WHERE)); \ } else if (refcnt_delete(#O, *(O), &(*(O))->refcnt, \ WHERE)) { \ FREE(O, WHERE); \ passert(*(O) == NULL); \ } else { \ *(O) = NULL; /* kill pointer */ \ } \ } #define delete_ref(O, FREE) \ { \ where_t here_ = HERE; \ ref_delete(O, FREE, here_); \ } /* * Replace an existing reference. * * Note that ref_replace(O,NEW,FREE,HERE) breaks as HERE contains * braces. */ #define ref_replace(O, NEW, FREE, WHERE) \ { \ /* add new before deleting old */ \ ref_add(NEW, WHERE); \ ref_delete(O, FREE, WHERE); \ *(O) = NEW; \ } #define replace_ref(O, NEW, FREE) \ { \ where_t here_ = HERE; \ /* add new before deleting old */ \ ref_replace(O, NEW, FREE, here_); \ } #endif libreswan-3.32/include/reqid.h000066400000000000000000000032651365625662500163550ustar00rootroot00000000000000/* reqid definitions, for libreswan * * Copyright (C) 2014 D. Hugh Redelmeier * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. */ #ifndef REQID_H #define REQID_H #include /* for uint32_t */ /* * reqid definitions * * A reqid is a numerical identifier used to match IPsec SAs using * iptables with NETKEY/XFRM. This identifier is normally * automatically allocated. It is exported to the _updown script as * REQID. On Linux, reqids are supported with IP Connection Tracking * and NAT (iptables). Automatically generated values use the range * 16384 and higher. Manually specified reqid values therefore must * be between 1 and 16383. * * Automatically generated reqids are allocated in groups of four, one * for each potential SA and pseudo SA in an SA bundle. Their number * will be above 16380. The base number will be a multiple of four. * * Manually assigned reqids are all identical for a particular connection * and its instantiations. */ typedef uint32_t reqid_t; #define IPSEC_MANUAL_REQID_MAX 0x3fff reqid_t gen_reqid(void); reqid_t reqid_ah(reqid_t r); reqid_t reqid_esp(reqid_t r); reqid_t reqid_ipcomp(reqid_t r); #endif libreswan-3.32/include/sadb.h000066400000000000000000000025001365625662500161510ustar00rootroot00000000000000/* Wrapper for , for libreswan * * Copyright (C) 2018 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef LSW_SADB_H #define LSW_SADB_H /* * See: https://tools.ietf.org/html/rfc2367 * * This header pulls in all the SADB_* and sadb_* declarations * described by RFC 2368 (along with any extensions which use the * prefix SADB_X_... or sadb_x_...). * * Typically this just involves including , but on * linux it needs to pull in the local hacked up version of the same * file (Why?. * * What this header does not do is include the broken * linux/include/libreswan/pfkeyv2.h et.al. These don't correctly * handle optional defintions and extensions. */ #ifdef linux #include "linux/pfkeyv2.h" /* include/linux/pfkeyv2.h why? */ #else #include #endif #endif libreswan-3.32/include/secrets.h000066400000000000000000000201561365625662500167170ustar00rootroot00000000000000/* mechanisms for preshared keys (public, private, and preshared secrets) * definitions: lib/libswan/secrets.c * * Copyright (C) 1998-2002,2013 D. Hugh Redelmeier * Copyright (C) 2003-2008 Michael Richardson * Copyright (C) 2009 Paul Wouters * Copyright (C) 2009 Avesh Agarwal * Copyright (C) 2012 Paul Wouters * Copyright (C) 2016 Andrew Cagney * Copyright (C) 2017 Vukasin Karadzic * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef _SECRETS_H #define _SECRETS_H #include #include #include "lswcdefs.h" #include "x509.h" #include "id.h" #include "err.h" #include "realtime.h" #include "ckaid.h" struct state; /* forward declaration */ struct secret; /* opaque definition, private to secrets.c */ struct pubkey; /* forward */ union pubkey_content; /* forward */ struct pubkey_type; /* forward */ struct RSA_public_key { char keyid[KEYID_BUF]; /* see ipsec_keyblobtoid(3) */ /* * The "adjusted" length of modulus n in octets: * [RSA_MIN_OCTETS, RSA_MAX_OCTETS]. * * According to form_keyid() this is the modulus length less * any leading byte added by DER encoding. * * The adjusted length is used in sign_hash() as the signature * length - wouldn't PK11_SignatureLen be better? * * The adjusted length is used in same_RSA_public_key() as * part of comparing two keys - but wouldn't that be * redundant? The direct n==n test would pick up the * difference. */ unsigned k; /* * NSS's(?) idea of a unique ID for a public private key pair. * For RSA it is something like the SHA1 of the modulus. It * replaces KEYID. * * This is the value returned by * PK11_GetLowLevelKeyIDForCert() or * PK11_GetLowLevelKeyIDForPrivateKey() (see * form_ckaid_nss()), or computed by brute force from the * modulus (see form_ckaid_rsa()). * * XXX: When support for ECC is added this may need to be * moved to "pubkey"; or ECC will need its own value. Think * of moving it here from RSA_private_key as a first step. */ ckaid_t ckaid; /* public: */ chunk_t n; /* modulus: p * q */ chunk_t e; /* exponent: relatively prime to (p-1) * (q-1) [probably small] */ }; struct RSA_private_key { struct RSA_public_key pub; }; struct ECDSA_public_key { char keyid[KEYID_BUF]; unsigned int k; chunk_t ecParams; chunk_t pub; /* publicValue */ ckaid_t ckaid; }; struct ECDSA_private_key { struct ECDSA_public_key pub; chunk_t ecParams; chunk_t pub_val; /* publicValue */ chunk_t privateValue; chunk_t version; }; err_t rsa_pubkey_to_base64(chunk_t exponent, chunk_t modulus, char **rr); err_t unpack_RSA_public_key(struct RSA_public_key *rsa, const chunk_t *pubkey); err_t unpack_ECDSA_public_key(struct ECDSA_public_key *ecdsa, const chunk_t *pubkey); /* ASKK */ struct private_key_stuff { enum PrivateKeyKind kind; /* * Was this allocated on the heap and hence, should it be * freed (along with all members)? * * The old secrets file stuff passes around a pointer to a * cached structure so it shouldn't be freed. */ bool on_heap; /* * This replaced "int lsw_secretlineno()", which assumes only * one file (no includes) and isn't applicable to NSS. For * NSS it's the entry number. */ int line; union { chunk_t preshared_secret; struct RSA_private_key RSA_private_key; struct ECDSA_private_key ECDSA_private_key; /* struct smartcard *smartcard; */ } u; chunk_t ppk; chunk_t ppk_id; }; extern struct private_key_stuff *lsw_get_pks(struct secret *s); extern struct id_list *lsw_get_idlist(const struct secret *s); /* * return 1 to continue to next, * return 0 to return current secret * return -1 to return NULL */ typedef int (*secret_eval)(struct secret *secret, struct private_key_stuff *pks, void *uservoid); extern struct secret *lsw_foreach_secret(struct secret *secrets, secret_eval func, void *uservoid); union pubkey_content { struct RSA_public_key rsa; struct ECDSA_public_key ecdsa; }; struct pubkey_type { const char *name; enum pubkey_alg alg; enum PrivateKeyKind private_key_kind; void (*free_pubkey_content)(union pubkey_content *pkc); err_t (*unpack_pubkey_content)(union pubkey_content *pkc, chunk_t key); }; extern const struct pubkey_type pubkey_type_rsa; extern const struct pubkey_type pubkey_type_ecdsa; const struct pubkey_type *pubkey_alg_type(enum pubkey_alg alg); /* public key machinery */ struct pubkey { struct id id; unsigned refcnt; /* reference counted! */ enum dns_auth_level dns_auth_level; realtime_t installed_time; realtime_t until_time; uint32_t dns_ttl; /* from wire. until_time is derived using this */ chunk_t issuer; const struct pubkey_type *type; union pubkey_content u; }; /* * XXX: While these fields seem to really belong in 'struct pubkey', * moving them isn't so easy - code assumes the fields are also found * in {RSA,ECDSA}_private_key's .pub. Perhaps that structure have its * own copy. * * All pointers are references into the underlying PK structure. */ const char *pubkey_keyid(const struct pubkey *pk); const ckaid_t *pubkey_ckaid(const struct pubkey *pk); unsigned pubkey_size(const struct pubkey *pk); struct pubkey_list { struct pubkey *key; struct pubkey_list *next; }; extern struct pubkey_list *pubkeys; /* keys from ipsec.conf */ extern struct pubkey_list *free_public_keyentry(struct pubkey_list *p); extern void free_public_keys(struct pubkey_list **keys); extern void free_remembered_public_keys(void); extern void delete_public_keys(struct pubkey_list **head, const struct id *id, const struct pubkey_type *type); extern void form_keyid(chunk_t e, chunk_t n, char *keyid, unsigned *keysize); extern struct pubkey *reference_key(struct pubkey *pk); extern void unreference_key(struct pubkey **pkp); extern err_t add_public_key(const struct id *id, enum dns_auth_level dns_auth_level, const struct pubkey_type *type, const chunk_t *key, struct pubkey_list **head); extern err_t add_ipseckey(const struct id *id, enum dns_auth_level dns_auth_level, const struct pubkey_type *type, uint32_t ttl, uint32_t ttl_used, const chunk_t *key, struct pubkey_list **head); extern bool same_RSA_public_key(const struct RSA_public_key *a, const struct RSA_public_key *b); extern void install_public_key(struct pubkey *pk, struct pubkey_list **head); extern void free_public_key(struct pubkey *pk); extern void lsw_load_preshared_secrets(struct secret **psecrets, const char *secrets_file); extern void lsw_free_preshared_secrets(struct secret **psecrets); extern bool lsw_has_private_rawkey(const struct secret *secrets, const struct pubkey *pk); extern struct secret *lsw_find_secret_by_public_key(struct secret *secrets, const struct pubkey *my_public_key, enum PrivateKeyKind kind); extern struct secret *lsw_find_secret_by_id(struct secret *secrets, enum PrivateKeyKind kind, const struct id *my_id, const struct id *his_id, bool asym); extern struct secret *lsw_get_ppk_by_id(struct secret *secrets, chunk_t ppk_id); extern err_t lsw_add_rsa_secret(struct secret **secrets, CERTCertificate *cert); extern err_t lsw_add_ecdsa_secret(struct secret **secrets, CERTCertificate *cert); extern struct pubkey *allocate_RSA_public_key_nss(CERTCertificate *cert); extern struct pubkey *allocate_ECDSA_public_key_nss(CERTCertificate *cert); /* these do not clone */ chunk_t same_secitem_as_chunk(SECItem si); SECItem same_chunk_as_secitem(chunk_t chunk, SECItemType type); chunk_t clone_secitem_as_chunk(SECItem si, const char *name); #endif /* _SECRETS_H */ libreswan-3.32/include/shunk.h000066400000000000000000000115621365625662500164000ustar00rootroot00000000000000/* constant string (octet) fragments, for libreswan * * Copyright (C) 2018-2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef SHUNK_H #define SHUNK_H #include #include /* size_t */ #include /* uint8_t */ /* * Think of shunk_t and shunk_t as opposite solutions to the same * problem - carving up streams of octets: * * shunk_t's buffer is constant making it good for manipulating static * constant data (such as "a string"), chunk_t's is not. */ struct shunk { const void *ptr; size_t len; }; typedef struct shunk shunk_t; /* * Just like for strings, an empty or zero length shunk such as * {.ptr="",.len = 0} should not be confused with the NULL shunk * (i.e., {.ptr=NULL,.len=0}). * * Use 'null_shunk' in initialisers. The only exception is static * initializers - which will get a compiler error - and NULL_SHUNK can * be used. */ #define NULL_SHUNK { .ptr = NULL, .len = 0, } extern const shunk_t null_shunk; extern const shunk_t empty_shunk; shunk_t shunk1(const char *ptr); /* strlen() implied */ shunk_t shunk2(const void *ptr, int len); #define THING_AS_SHUNK(THING) shunk2(&(THING), sizeof(THING)) /* shunk[START..END) */ shunk_t shunk_slice(shunk_t s, size_t start, size_t stop); /* * A shunk version of strsep() / strtok(): split off from INPUT a * possibly empty TOKEN containing characters not found in DELIMS and * the delimiting character (or NUL). * * Return the TOKEN (or the NULL_TOKEN if INPUT is exhausted); if * DELIM is non-NULL, set *DELIM to the delimiting character or NUL; * and update *INPUT. * * For the final token, *DELIM is set to NUL, and INPUT is marked as * being exhausted by setting it to the NULL_SHUNK. * * When called with exhausted INPUT (aka the NULL_SHUNK), the * NULL_SHUNK is returned as the token and *DELIM is set to NUL. * * One way to implement a simple parser is to use TOKEN.ptr==NULL as * an end-of-input indicator: * * char sep; * shunk_t token = shunk_token(&input, &sep, ","); * while (token.ptr != NULL) { * ... process token ... * token = shunk_token(&input, &sep, ","); * } * */ shunk_t shunk_token(shunk_t *input, char *delim, const char *delims); /* * Return the sequence of charcters in ACCEPT, update INPUT. * * When input is exhausted the NULL_SHUNK is returned (rather than the * EMPTY_SHUNK). * * edge cases (these might change a little): * * span("", "accept"): returns the token EMPTY_SHUNK and sets input to * NULL_SHUNK so the next call returns the NULL_SHUNK. * * span("a", "accept"): returns the token "a" and sets input to * NULL_SHUNK so the next call returns the NULL_SHUNK. */ shunk_t shunk_span(shunk_t *input, const char *accept); /* * shunk version of compare functions (or at least libreswan's * versions). * * (Confusingly and just like POSIX, *case* ignores case). * * Just like a NULL and EMPTY ("") string, a NULL (uninitialized) and * EMPTY (pointing somewhere but no bytes) are considered different. */ /* XXX: move to constants.h? */ bool bytes_eq(const void *l_ptr, size_t l_len, const void *r_ptr, size_t r_len); #define hunk_eq(L,R) \ ({ \ typeof(L) l_ = L; /* evaluate once */ \ typeof(R) r_ = R; /* evaluate once */ \ bytes_eq(l_.ptr, l_.len, r_.ptr, r_.len); \ }) #define hunk_streq(HUNK, STRING) hunk_eq(HUNK, shunk1(STRING)) #define hunk_memeq(HUNK, MEM, SIZE) hunk_eq(HUNK, shunk2(MEM, SIZE)) #define hunk_thingeq(SHUNK, THING) hunk_memeq(SHUNK, &(THING), sizeof(THING)) bool shunk_caseeq(shunk_t lhs, shunk_t rhs); bool shunk_strcaseeq(shunk_t shunk, const char *string); bool shunk_caseeat(shunk_t *lhs, shunk_t rhs); bool shunk_strcaseeat(shunk_t *lhs, const char *string); bool shunk_isdigit(shunk_t s, size_t offset); bool shunk_ischar(shunk_t s, size_t offset, const char *chars); /* * Number conversion. like strtoul() et.al. */ bool shunk_tou(shunk_t lhs, unsigned *value, int base); /* * To print, use: printf(PRI_SHUNK, pri_shunk(shunk)); * * XXX: I suspect ISO-C reserves the PRIabc (no underscore) name * space, so throw in an underscore so that it is clear that this has * nothing to do with ISO-C. While the name PRI_shunk() is tacky, it * does have some upper case letters (all macros shall be upper case, * right?). */ #define PRI_SHUNK "%.*s" #define pri_shunk(SHUNK) ((int) (SHUNK).len), (const char *) ((SHUNK).ptr) #endif libreswan-3.32/include/socketwrapper.h000066400000000000000000000012741365625662500201400ustar00rootroot00000000000000#ifndef _SOCKET_WRAPPER_H_ #define _SOCKET_WRAPPER_H_ #include #include #include #include #include /* * This wrapper ensures that we close all file descriptors on exec. */ #ifdef FD_CLOEXEC static inline int safe_socket(int domain, int type, int protocol) { int fd = socket(domain, type, protocol); if (fd >= 0) { int arg = fcntl(fd, F_GETFD); if (arg < 0 || fcntl(fd, F_SETFD, arg | FD_CLOEXEC) < 0) { /* fcntl failure: close fd without disturbing errno */ int saved_errno = errno; close(fd); fd = -1; errno = saved_errno; } } return fd; } #else #define safe_socket(d, t, p) socket(d, t, p) #endif #endif libreswan-3.32/include/sysdep.h000066400000000000000000000006441365625662500165560ustar00rootroot00000000000000/* * Placeholder. Please do not put #defines here! * * At one point ports defined macros in both both * ports/$(PORT)/include/sysdep.h and mk/defaults/$(PORT).mk. That's * all gone. Instead all macros are defined in mk/defaults/$(PORT).mk * and then passed in via the command line. * * This file remains as a placeholder. At some point in the future, * it can be replaced with a generated sysdep.h file. */ libreswan-3.32/include/unbound/000077500000000000000000000000001365625662500165445ustar00rootroot00000000000000libreswan-3.32/include/unbound/README000066400000000000000000000007541365625662500174320ustar00rootroot00000000000000 This directory is only picked up by make if compiled with USE_UNBOUND_EVENT_H_COPY=true A bug in "make install" in unbound when compiled with libevent support results in the file unbound-event.h not getting installed. This bug is present in unbound up to at least 1.6.0. The required functions are properly exposed in the shared library. Setting USE_UNBOUND_EVENT_H_COPY=true results in this include file being used to work around this bug. It has only been tested against unbound 1.6.x libreswan-3.32/include/unbound/unbound-event.h000066400000000000000000000253461365625662500215200ustar00rootroot00000000000000/* * unbound-event.h - unbound validating resolver public API with events * * Copyright (c) 2007, NLnet Labs. All rights reserved. * * This software is open source. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 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. * * Neither the name of the NLNET LABS nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * \file * * This file contains the unbound interface for use with user defined * pluggable event bases. * * Use ub_ctx_create_event_ub_base() to create an unbound context that uses * the user provided event base API. Then, use the ub_resolve_event call * to add DNS resolve queries to the context. Those then run with the * provided event_base, and when they are done you get a function callback. * * This method does not fork another process or create a thread, the effort * is done by the unbound state machines that are connected to the event base. * * It is also possible to provide a libevent based event base by using * ub_ctx_create_event_base(). But you have to use the same libevent that * unbound was compiled with, otherwise it wouldn't work, the event and * event_base structures would be different. */ #ifndef _UB_UNBOUND_EVENT_H #define _UB_UNBOUND_EVENT_H #ifdef __cplusplus extern "C" { #endif struct ub_ctx; struct ub_result; struct event_base; /** event timeout */ #define UB_EV_TIMEOUT 0x01 /** event fd readable */ #define UB_EV_READ 0x02 /** event fd writable */ #define UB_EV_WRITE 0x04 /** event signal */ #define UB_EV_SIGNAL 0x08 /** event must persist */ #define UB_EV_PERSIST 0x10 /** magic number to identify this version of the pluggable event api */ #define UB_EVENT_MAGIC 0x44d74d78 struct ub_event; struct ub_event_base; struct timeval; /** * The Virtual Method Table for and ub_event_base "object" */ struct ub_event_base_vmt { /** Destructor for the ub_event_base object, * (not called by libunbound) */ void (*free)(struct ub_event_base*); /** Run the event loop * (not called by libunbound when using ub_resolve_event) */ int (*dispatch)(struct ub_event_base*); /** Exit the given event loop */ int (*loopexit)(struct ub_event_base*, struct timeval*); /** Instantiate a new ub_event associated with this event base */ struct ub_event* (*new_event)(struct ub_event_base*, int fd, short bits, void (*cb)(int, short, void*), void* arg); /** Instantiate a new signal associated with this event base, * (not called by libunbound) */ struct ub_event* (*new_signal)(struct ub_event_base*, int fd, void (*cb)(int, short, void*), void* arg); /** Create a new ub_event associated with the given wsaevent, * (not called by libunbound) */ struct ub_event* (*winsock_register_wsaevent)(struct ub_event_base*, void* wsaevent, void (*cb)(int, short, void*), void* arg); }; /** * A user defined pluggable event base is registered by providing a * ub_event_base "object" with the ub_ctx_create_ub_event() function. * The magic number must be correct and the Virtual Method Table must be * fully equipped providing the event base API to be used by libunbound. */ struct ub_event_base { /** magic must be UB_EVENT_MAGIC (0x44d74d78) */ unsigned long magic; /** Virtual Method Table for ub_event_base */ struct ub_event_base_vmt* vmt; }; /** * The Virtual Method Table for and ub_event "object" */ struct ub_event_vmt { /** Add event bits for this event to fire on. * The event will be deactivated before this function is called. */ void (*add_bits)(struct ub_event*, short); /** Configure the event so it will not longer fire on given bits * The event will be deactivated before this function is called. */ void (*del_bits)(struct ub_event*, short); /** Change or set the file descriptor on the event * The event will be deactivated before this function is called. */ void (*set_fd)(struct ub_event*, int); /** Destructor for the ub_event object */ void (*free)(struct ub_event*); /** Activate the event. The given timeval is an timeout value. */ int (*add)(struct ub_event*, struct timeval*); /** Deactivate the event */ int (*del)(struct ub_event*); /** Reconfigure and activate a timeout event */ int (*add_timer)(struct ub_event*, struct ub_event_base*, void (*cb)(int, short, void*), void* arg, struct timeval*); /** Deactivate the timeout event */ int (*del_timer)(struct ub_event*); /** Activate a signal event (not called by libunbound). */ int (*add_signal)(struct ub_event*, struct timeval*); /** Deactivate a signal event (not called by libunbound). */ int (*del_signal)(struct ub_event*); /** Destructor for a ub_event associated with a wsaevent, * (not called by libunbound) */ void (*winsock_unregister_wsaevent)(struct ub_event* ev); /** Libunbound will signal the eventloop when a TCP windows socket * will block on next read or write (given by the eventbits), to work * around edge trigger event behaviour of select on windows with TCP. */ void (*winsock_tcp_wouldblock)(struct ub_event*, int eventbit); }; /** * An "object" comprising a user defined pluggable event. * The magic number must be correct and the Virtual Method Table must be * fully equipped providing the ub_event API to be used by libunbound. */ struct ub_event { /** magic must be UB_EVENT_MAGIC (0x44d74d78) */ unsigned long magic; /** Virtual Method Table for ub_event */ struct ub_event_vmt* vmt; }; typedef void (*ub_event_callback_t)(void*, int, void*, int, int, char*); /** * Create a resolving and validation context. * The information from /etc/resolv.conf and /etc/hosts is not utilised by * default. Use ub_ctx_resolvconf and ub_ctx_hosts to read them. * @param base: the pluggable event base that the caller has created. * The unbound context uses this event base. * @return a new context. default initialisation. * returns NULL on error. * You must use ub_resolve_event with this context. * Do not call ub_ctx_async, ub_poll, ub_wait, ub_process, this is all done * with the event_base. Setup the options you like with the other functions. */ struct ub_ctx* ub_ctx_create_ub_event(struct ub_event_base* base); /** * Create a resolving and validation context. * The information from /etc/resolv.conf and /etc/hosts is not utilised by * default. Use ub_ctx_resolvconf and ub_ctx_hosts to read them. * You have to use the same libevent that unbound was compiled with, * otherwise it wouldn't work, the event and event_base structures would * be different. * @param base: the event base that the caller has created. The unbound * context uses this event base. * @return a new context. default initialisation. * returns NULL on error. * You must use ub_resolve_event with this context. * Do not call ub_ctx_async, ub_poll, ub_wait, ub_process, this is all done * with the event_base. Setup the options you like with the other functions. */ struct ub_ctx* ub_ctx_create_event(struct event_base* base); /** * Set a new libevent event_base on a context created with ub_ctx_create_event. * You have to use the same libevent that unbound was compiled with, * otherwise it wouldn't work, the event and event_base structures would * be different. * Any outbound queries will be canceled. * @param ctx the ub_ctx to update. Must have been created with ub_ctx_create_event * @param base the new event_base to attach to the ctx * @return 0 if OK, else error */ int ub_ctx_set_event(struct ub_ctx* ctx, struct event_base* base); /** * Perform resolution and validation of the target name. * Asynchronous, after a while, the callback will be called with your * data and the result. Uses the event_base user installed by creating the * context with ub_ctx_create_event(). * @param ctx: context with event_base in it. * The context is finalized, and can no longer accept all config changes. * @param name: domain name in text format (a string). * @param rrtype: type of RR in host order, 1 is A. * @param rrclass: class of RR in host order, 1 is IN (for internet). * @param mydata: this data is your own data (you can pass NULL), * and is passed on to the callback function. * @param callback: this is called on completion of the resolution. * It is called as: * void callback(void* mydata, int rcode, void* packet, int packet_len, * int sec, char* why_bogus) * with mydata: the same as passed here, you may pass NULL, * with rcode: 0 on no error, nonzero for mostly SERVFAIL situations, * this is a DNS rcode. * with packet: a buffer with DNS wireformat packet with the answer. * do not inspect if rcode != 0. * do not write or free the packet buffer, it is used internally * in unbound (for other callbacks that want the same data). * with packet_len: length in bytes of the packet buffer. * with sec: 0 if insecure, 1 if bogus, 2 if DNSSEC secure. * with why_bogus: text string explaining why it is bogus (or NULL). * These point to buffers inside unbound; do not deallocate the packet or * error string. * * If an error happens during processing, your callback will be called * with error set to a nonzero value (and result==NULL). * For localdata (etc/hosts) the callback is called immediately, before * resolve_event returns, async_id=0 is returned. * @param async_id: if you pass a non-NULL value, an identifier number is * returned for the query as it is in progress. It can be used to * cancel the query. * @return 0 if OK, else error. */ int ub_resolve_event(struct ub_ctx* ctx, const char* name, int rrtype, int rrclass, void* mydata, ub_event_callback_t callback, int* async_id); #ifdef __cplusplus } #endif #endif /* _UB_UNBOUND_H */ libreswan-3.32/include/whack.h000066400000000000000000000274361365625662500163540ustar00rootroot00000000000000/* Structure of messages from whack to Pluto proper. * * Copyright (C) 1998-2001,2015-2017 D. Hugh Redelmeier. * Copyright (C) 2012-2019 Paul Wouters * Copyright (C) 2011 Mika Ilmaranta * Copyright (C) 2012 Paul Wouters * Copyright (C) 2012 Philippe Vouters * Copyright (C) 2013,2016 Antony Antony * Copyright (C) 2016,2018 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #ifndef _WHACK_H #define _WHACK_H #include "ietf_constants.h" #include "lset.h" #include "lmod.h" #include "deltatime.h" #include "chunk.h" #include "reqid.h" #include "err.h" #include "impair.h" #include "ip_range.h" #include "ip_subnet.h" #ifndef DEFAULT_RUNDIR # define DEFAULT_RUNDIR "/run/pluto/" #endif #ifndef DEFAULT_CTL_SOCKET # define DEFAULT_CTL_SOCKET DEFAULT_RUNDIR "/pluto.ctl" #endif /* Since the message remains on one host, native representation is used. * Think of this as horizontal microcode: all selected operations are * to be done (in the order declared here). * * MAGIC is used to help detect version mismatches between whack and Pluto. * Whenever the interface (i.e. this struct) changes in form or * meaning, change this value (probably by changing the last number). * * If the command only requires basic actions (status or shutdown), * it is likely that the relevant part of the message changes less frequently. * Whack uses WHACK_BASIC_MAGIC in those cases. * * When you increment WHACK_BASIC_MAGIC, reset WHACK_MAGIC's last number to 0. * This allows for more WHACK_BASIC_MAGIC values. * * NOTE: no value of WHACK_BASIC_MAGIC may equal any value of WHACK_MAGIC. * Otherwise certain version mismatches will not be detected. */ #define WHACK_BASIC_MAGIC (((((('w' << 8) + 'h') << 8) + 'k') << 8) + 25) #define WHACK_MAGIC (((((('o' << 8) + 'h') << 8) + 'k') << 8) + 47) /* * Where, if any, is the pubkey coming from. * * This goes across the wire so re-ordering this means bumping whack's * version number. */ enum whack_pubkey_type { WHACK_PUBKEY_NONE = 0, /* must be zero (to make it default) */ WHACK_PUBKEY_CERTIFICATE_NICKNAME, WHACK_PUBKEY_CKAID, }; /* struct whack_end is a lot like connection.h's struct end * It differs because it is going to be shipped down a socket * and because whack is a separate program from pluto. */ struct whack_end { char *id; /* id string (if any) -- decoded by pluto */ char *pubkey; /* PUBKEY_TYPE string (if any) -- decoded by pluto */ char *ca; /* distinguished name string (if any) -- parsed by pluto */ char *groups; /* access control groups (if any) -- parsed by pluto */ enum keyword_authby authby; enum keyword_host host_type; ip_address host_addr, host_nexthop, host_srcip; ip_subnet client, host_vtiip, ifaceip; bool key_from_DNS_on_demand; enum whack_pubkey_type pubkey_type; bool has_client; bool has_client_wildcard; bool has_port_wildcard; char *updown; /* string */ uint16_t host_port; /* host order (for IKE communications) */ uint16_t port; /* host order */ uint8_t protocol; char *virt; ip_range pool_range; /* store start of v4 addresspool */ bool xauth_server; /* for XAUTH */ bool xauth_client; char *xauth_username; bool modecfg_server; /* for MODECFG */ bool modecfg_client; bool cat; /* IPv4 Client Address Translation */ unsigned int tundev; enum certpolicy sendcert; bool send_ca; enum ike_cert_type certtype; char *host_addr_name; /* DNS name for host, of hosttype==IPHOSTNAME * pluto will convert to IP address again, * if this is non-NULL when conn fails. */ }; enum whack_opt_set { WHACK_ADJUSTOPTIONS=0, /* normal case */ WHACK_SETDUMPDIR=1, /* string1 contains new dumpdir */ }; struct whack_message { unsigned int magic; bool whack_status; bool whack_global_status; bool whack_clear_stats; bool whack_traffic_status; bool whack_shunt_status; bool whack_fips_status; bool whack_brief_status; bool whack_seccomp_crashtest; bool whack_shutdown; /* END OF BASIC COMMANDS * If you change anything earlier in this struct, update WHACK_BASIC_MAGIC. */ /* name is used in connection and initiate */ size_t name_len; /* string 1 */ char *name; /* for WHACK_OPTIONS: */ bool whack_options; lmod_t debugging; lmod_t impairing; /* what to impair and how */ struct whack_impair impairment; /* for WHACK_CONNECTION */ bool whack_connection; bool whack_async; lset_t policy; lset_t sighash_policy; deltatime_t sa_ike_life_seconds; deltatime_t sa_ipsec_life_seconds; deltatime_t sa_rekey_margin; unsigned long sa_rekey_fuzz; unsigned long sa_keying_tries; unsigned long sa_replay_window; deltatime_t r_timeout; /* in secs */ deltatime_t r_interval; /* in msec */ enum yna_options nic_offload; uint32_t xfrm_if_id; /* For IKEv1 RFC 3706 - Dead Peer Detection */ deltatime_t dpd_delay; deltatime_t dpd_timeout; enum dpd_action dpd_action; int dpd_count; /* Cisco interop: remote peer type */ enum keyword_remotepeertype remotepeertype; /* Force the use of NAT-T on a connection */ enum yna_options encaps; /* Option to allow per-conn setting of sending of NAT-T keepalives - default is enabled */ bool nat_keepalive; /* Option to tweak sending NATT drafts, rfc or both */ enum ikev1_natt_policy ikev1_natt; /* Option to allow sending INITIAL-CONTACT payload - default is disabled */ bool initial_contact; /* * Option to just send the Cisco VID - the other end will behave * differently (ModeCFG + RSA?) */ bool cisco_unity; /* Option to send strongswan VID to allow better interop */ bool fake_strongswan; /* send our own libreswan vendorid or not */ bool send_vendorid; /* Checking if this connection is configured by Network Manager */ bool nmconfigured; /* XAUTH Authentication can be file (default) PAM or 'alwaysok' */ enum keyword_xauthby xauthby; /* XAUTH failure mode can be hard (default) or soft */ enum keyword_xauthfail xauthfail; enum send_ca_policy send_ca; /* Force the MTU for this connection */ int connmtu; uint32_t sa_priority; uint32_t sa_tfcpad; bool send_no_esp_tfc; reqid_t sa_reqid; int nflog_group; bool labeled_ipsec; char *policy_label; /* note that each end contains string 2/5.id, string 3/6 cert, * and string 4/7 updown */ struct whack_end left; struct whack_end right; /* note: if the client is the gateway, the following must be equal */ sa_family_t addr_family; /* between gateways */ sa_family_t tunnel_addr_family; /* between clients */ char *ike; /* ike algo string (separated by commas) */ char *pfsgroup; /* pfsgroup will be "encapsulated" in esp string for pluto */ char *esp; /* esp algo string (separated by commas) */ /* for WHACK_KEY: */ bool whack_key; bool whack_addkey; char *keyid; /* string 8 */ enum pubkey_alg pubkey_alg; chunk_t keyval; /* chunk */ /* for REMOTE_HOST */ char *remote_host; /* for WHACK_ROUTE: */ bool whack_route; /* for WHACK_UNROUTE: */ bool whack_unroute; /* for WHACK_INITIATE: */ bool whack_initiate; /* for WHACK_OPINITIATE */ bool whack_oppo_initiate; ip_address oppo_my_client, oppo_peer_client; int oppo_proto, oppo_dport; /* for WHACK_TERMINATE: */ bool whack_terminate; /* for WHACK_DELETE: */ bool whack_delete; /* for WHACK_DELETESTATE: */ bool whack_deletestate; long unsigned int whack_deletestateno; /* rekey now */ bool whack_rekey_ike; /* rekey the latest ike now */ bool whack_rekey_ipsec; /* rekey latest ipsec now */ /* for WHACK_NFLOG_GROUP: */ long unsigned int whack_nfloggroup; /* for WHACK_DELETEUSER: */ bool whack_deleteuser; bool whack_deleteuser_name; /* for WHACK_DELETEUSER: */ bool whack_deleteid; bool whack_deleteid_name; /* for WHACK_PURGEOCSP */ bool whack_purgeocsp; /* for WHACK_LISTEN: */ bool whack_listen, whack_unlisten; long unsigned int ike_buf_size; /* IKE socket recv/snd buffer size */ bool ike_sock_err_toggle; /* toggle MSG_ERRQUEUE on IKE socket */ /* for DDOS modes */ enum ddos_mode whack_ddos; /* force EVENT_PENDING_DDNS */ bool whack_ddns; /* for WHACK_CRASH - note if a remote peer is known to have rebooted */ bool whack_crash; ip_address whack_crash_peer; /* for WHACK_LIST */ bool whack_utc; bool whack_check_pub_keys; lset_t whack_list; /* for WHACK_REREAD */ u_char whack_reread; /* for connalias string */ char *connalias; /* for IKEv1 MODECFG and IKEv2 CP */ char *modecfg_dns; char *modecfg_domains; char *modecfg_banner; char *conn_mark_both; char *conn_mark_in; char *conn_mark_out; char *vti_iface; bool vti_routing; /* perform routing into vti device or not */ bool vti_shared; /* use remote %any and skip cleanup on down? */ /* for RFC 5685 - IKEv2 Redirect mechanism */ char *redirect_to; char *accept_redirect_to; bool active_redirect; ip_address active_redirect_peer; ip_address active_redirect_gw; /* what metric to put on ipsec routes */ int metric; char *dnshostname; /* for use with general option adjustments */ enum whack_opt_set opt_set; char *string1; char *string2; char *string3; /* space for strings (hope there is enough room): * Note that pointers don't travel on wire. * 1 connection name [name_len] * 2 left's name [left.host.name.len] * 3 left's cert * 4 left's ca * 5 left's groups * 6 left's updown * 7 left's virt * 8 right's name [left.host.name.len] * 9 right's cert * 10 right's ca * 11 right's groups * 12 right's updown * 13 right's virt * 14 keyid * 15 unused (was myid) * 16 ike * 17 esp * 18 left.xauth_username * 19 right.xauth_username * 20 connalias * 21 left.host_addr_name * 22 right.host_addr_name * 23 genstring1 - used with opt_set * 24 genstring2 * 25 genstring3 * 26 dnshostname * 27 policy_label if compiled with with LABELED_IPSEC * 28 remote_host * 29 redirect_to * 30 accept_redirect_to * plus keyval (limit: 8K bits + overhead), a chunk. */ size_t str_size; unsigned char string[4096]; }; /* options of whack --list*** command * these should be kept in order of option_enums LST_ values */ #define LIST_NONE 0x0000 /* don't list anything */ #define LIST_PUBKEYS 0x0001 /* list all public keys */ #define LIST_CERTS 0x0002 /* list all host/user certs */ #define LIST_CACERTS 0x0004 /* list all ca certs */ #define LIST_CRLS 0x0008 /* list all crls */ #define LIST_PSKS 0x0010 /* list all preshared keys (by name) */ #define LIST_EVENTS 0x0020 /* list all queued events */ /* omit events from listing options */ #define LIST_ALL LRANGES(LIST_PUBKEYS, LIST_PSKS) /* all list options */ /* options of whack --reread*** command */ #define REREAD_NONE 0x00 /* don't reread anything */ #define REREAD_SECRETS 0x01 /* reread /etc/ipsec.secrets */ #define REREAD_CRLS 0x02 /* obsoleted - just gives a warning */ #define REREAD_FETCH 0x04 /* update CRL from distribution point(s) */ #define REREAD_ALL LRANGES(REREAD_SECRETS, REREAD_FETCH) /* all reread options */ struct whackpacker { struct whack_message *msg; unsigned char *str_roof; unsigned char *str_next; int n; }; extern err_t pack_whack_msg(struct whackpacker *wp); extern err_t unpack_whack_msg(struct whackpacker *wp); extern void clear_end(struct whack_end *e); extern size_t whack_get_secret(char *buf, size_t bufsize); extern int whack_get_value(char *buf, size_t bufsize); extern bool lsw_alias_cmp(const char *name, const char *aliases); #endif /* _WHACK_H */ libreswan-3.32/include/where.h000066400000000000000000000026301365625662500163560ustar00rootroot00000000000000/* source code location (where), for libreswan * * Copyright (C) 2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #ifndef WHERE_H #define WHERE_H /* * http://stackoverflow.com/questions/8487986/file-macro-shows-full-path#8488201 * * It is tempting to tweak the .c.o line so that it passes in the * required value. */ #ifndef HERE_BASENAME #define HERE_BASENAME (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) #endif /* * For appending: (in FUNC() at FILE:LINE) */ typedef const struct { const char *func; const char *basename; long line; } where_t; #define HERE (where_t) { .func = __func__, .basename = HERE_BASENAME , .line = __LINE__} #define PRI_WHERE "(in %s() at %s:%lu)" #define pri_where(SC) (SC).func, (SC).basename, (SC).line /* XXX: hack for old code passing around parameters */ #define WHERE(FUNC, BASENAME, LINE) (where_t) {FUNC, BASENAME, LINE} #endif libreswan-3.32/include/x509.h000066400000000000000000000106551365625662500157570ustar00rootroot00000000000000/* Support of X.509 certificates and CRLs * Copyright (C) 2000 Andreas Hess, Patric Lichtsteiner, Roger Wegmann * Copyright (C) 2001 Marco Bertossa, Andreas Schleiss * Copyright (C) 2002 Mario Strasser * Copyright (C) 2000-2004 Andreas Steffen, Zuercher Hochschule Winterthur * Copyright (C) 2012 Paul Wouters * Copyright (C) 2007 Michael Richardson * Copyright (C) 2009 Paul Wouters * Copyright (C) 2012-2013 Paul Wouters * Copyright (C) 2013 D. Hugh Redelmeier * Copyright (C) 2015 Matt Rogers * Copyright (C) 2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef _X509_H #define _X509_H #include #include #include "deltatime.h" #include "chunk.h" #include "err.h" #include "constants.h" #include "jambuf.h" struct pubkey_list; struct fd; typedef enum { LSW_CERT_NONE = 0, LSW_CERT_BAD = 1, LSW_CERT_MISMATCHED_ID = 2, LSW_CERT_ID_OK = 3 } lsw_cert_ret; /* * NSS can actually support a much larger path length */ #define MAX_CA_PATH_LEN 7 /* Definition of generalNames kinds */ typedef enum { GN_OTHER_NAME = 0, GN_RFC822_NAME = 1, GN_DNS_NAME = 2, GN_X400_ADDRESS = 3, GN_DIRECTORY_NAME = 4, GN_EDI_PARTY_NAME = 5, GN_URI = 6, GN_IP_ADDRESS = 7, GN_REGISTERED_ID = 8 } generalNames_t; /* access structure for a GeneralName */ typedef struct generalName generalName_t; struct generalName { generalName_t *next; generalNames_t kind; chunk_t name; }; /* forward declaration */ struct id; /* * check periodically for expired crls */ extern deltatime_t crl_check_interval; extern bool same_dn(chunk_t a, chunk_t b); extern bool match_dn(chunk_t a, chunk_t b, int *wildcards); extern int dn_count_wildcards(chunk_t dn); extern err_t atodn(const char *src, chunk_t *dn); extern void free_generalNames(generalName_t *gn, bool free_name); extern void load_crls(void); extern void list_authcerts(struct fd *whackfd); extern void list_crls(struct fd *whackfd); extern void clear_ocsp_cache(void); /* * New NSS x509 converted functions */ extern SECItem same_chunk_as_dercert_secitem(chunk_t chunk); extern chunk_t get_dercert_from_nss_cert(CERTCertificate *cert); extern generalName_t *gndp_from_nss_cert(CERTCertificate *cert); extern void select_nss_cert_id(CERTCertificate *cert, struct id *end_id); extern bool add_pubkey_from_nss_cert(struct pubkey_list **pubkey_db, const struct id *keyid, CERTCertificate *cert); extern bool trusted_ca_nss(chunk_t a, chunk_t b, int *pathlen); extern CERTCertList *get_all_certificates(void); /* * Formatting. * * jam_dn() converts the ASN.1 DN into a "standards compliant" * distinguised name (aka DN). * * XXX: Where "standards compliant" presumably means RFC-1485 et.al. - * the raw output is passed to CERT_AsciiToName() and that expects * RFC-1485. However, it looks like a different excaping schema is * used. * * The JAM_BYTES_FN parameter controls additional escaping (after * RFC-1485) that should be applied to UTF-8 strings. For instance: * jam_sanitized_bytes() makes the string suitable for logging; and * jam_meta_escaped_bytes() makes the string suitable for shell * scripts. * * The str_*() wrappers are hardwired to jam_sanitized_bytes() and, * hence, are only suitable for logging. */ typedef struct { /* Maximum length of ASN.1 distinquished name */ /* XXX: where did 512 come from? */ char buf[512/*includes NUL and SENTINEL*/]; } dn_buf; #define ASN1_BUF_LEN sizeof(dn_buf) const char *str_dn(chunk_t dn, dn_buf *buf); const char *str_dn_or_null(chunk_t dn, const char *null_dn, dn_buf *buf); void jam_dn_or_null(struct lswlog *buf, chunk_t dn, const char *null_dn, jam_bytes_fn *jam_bytes); void jam_dn(struct lswlog *buf, chunk_t dn, jam_bytes_fn *jam_bytes); void jam_raw_dn(struct lswlog *buf, chunk_t dn, jam_bytes_fn *jam_bytes, bool nss_compatible); #endif /* _X509_H */ libreswan-3.32/initsystems/000077500000000000000000000000001365625662500160425ustar00rootroot00000000000000libreswan-3.32/initsystems/Makefile000066400000000000000000000016041365625662500175030ustar00rootroot00000000000000# Makefile for init systems, for libreswan. # # Copyright (C) 2015, 2017 Andrew Cagney # Copyright (C) 2015-2016 Tuomo Soini # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. ifndef top_srcdir include ../mk/dirs.mk endif # this file uses ifeq, so need config early include $(top_srcdir)/mk/config.mk ifneq ($(INITSYSTEM),) SUBDIRS += $(INITSYSTEM) endif include $(top_srcdir)/mk/subdirs.mk libreswan-3.32/initsystems/docker/000077500000000000000000000000001365625662500173115ustar00rootroot00000000000000libreswan-3.32/initsystems/docker/Makefile000066400000000000000000000035011365625662500207500ustar00rootroot00000000000000ifndef top_srcdir include ../../mk/dirs.mk endif LIBRESWANSRCDIR?=$(shell cd ../..; pwd) SRCDIR?=${LIBRESWANSRCDIR}/initsystems/docker/ INITDFILE=$(builddir)/ipsec.init SYSCONFIGFILE=$(builddir)/sysconfig.pluto SUBDIRS= INITDDIR=$(RCDIR) SYSCONFIGDIR=$(SYSCONFDIR)/sysconfig SYSVINIT_DEFAULT_START?= include ${LIBRESWANSRCDIR}/Makefile.inc # Use dependencies to force the order. # # (Without this, since local-install-base depends local-base, rules # like local-base and installinitfiles and checkenabled are allowed to # run in parallel) local-base: $(INITDFILE) $(SYSCONFIGFILE) local-install-base: installinitfiles installsysconfig checkenabled installinitfiles: local-base mkdir -p $(INITDDIR) $(INSTALL) $(INITDFILE) $(INITDDIR)/ipsec installsysconfig: local-base mkdir -p $(SYSCONFIGDIR) if test ! -f $(SYSCONFIGDIR)/pluto ; then \ $(INSTALL) $(INSTCONFFLAGS) $(SYSCONFIGFILE) $(SYSCONFIGDIR)/pluto ; \ fi checkenabled: installinitfiles installsysconfig @count=0 ; \ for dir in $(DESTDIR)/etc/rc?.d ; do \ if test -f $$dir/S??ipsec.init ; then \ count=1 ; \ fi ; \ done ; \ if test $$count = 0 ; then \ echo "************************** WARNING ***********************************" ; \ echo "** The ipsec service is not enabled." ; \ echo "** Enable it using 'chkconfig ipsec on' or another similar method." ; \ echo "**********************************************************************" ; \ fi # XXX: identical to program.mk? $(builddir)/%: $(srcdir)/%.in $(top_srcdir)/Makefile.inc $(top_srcdir)/Makefile.ver | $(builddir) @echo 'IN' $< '->' $@ ${TRANSFORM_VARIABLES} < $< | sed -e "s:@SYSVINIT_DEFAULT_START@:${SYSVINIT_DEFAULT_START}:g" > $@ @if [ -x $< ]; then chmod +x $@; fi @if [ "${PROGRAM}.in" = $< ]; then chmod +x $@; fi include ${top_srcdir}/mk/targets.mk include ${top_srcdir}/mk/builddir.mk libreswan-3.32/initsystems/docker/ipsec.init.in000077500000000000000000000143011365625662500217100ustar00rootroot00000000000000#!@SHELL_BINARY@ # IPsec startup and shutdown script # ### BEGIN INIT INFO # Provides: ipsec # Required-Start: $network $remote_fs $syslog $named # Required-Stop: $syslog $remote_fs # Default-Start: # Default-Stop: 0 1 6 # Short-Description: Start Libreswan IPsec at boot time # Description: Enable automatic key management for IPsec (XFRM ### END INIT INFO # ### see https://bugzilla.redhat.com/show_bug.cgi?id=636572 ### Debian and Fedora interpret the LSB differently for Default-Start: # Copyright (C) 1998, 1999, 2001 Henry Spencer. # Copyright (C) 2002 Michael Richardson # Copyright (C) 2006 Michael Richardson # Copyright (C) 2008 Michael Richardson # Copyright (C) 2008-2015 Tuomo Soini # Copyright (C) 2012 Paul Wouters # Copyright (C) 2016 Kim B. Heino # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # # ipsec sysv style init.d script for starting and stopping # the IPsec security subsystem (XFRM and Pluto). # # This script becomes /etc/init.d/ipsec # and is also accessible as "ipsec setup" # # The startup and shutdown times are a difficult compromise (in particular, # it is almost impossible to reconcile them with the insanely early/late # times of NFS filesystem startup/shutdown). Startup is after startup of # syslog and pcmcia support; shutdown is just before shutdown of syslog. # # chkconfig: - 47 76 # description: IPsec provides encrypted and authenticated communications; \ # XFRM is the kernel half of it, Pluto is the user-level management daemon. test ${IPSEC_INIT_SCRIPT_DEBUG} && set -v -x # Check that networking is up. [ "${NETWORKING}" = "no" ] && exit 6 if [ ! -f /etc/sysconfig/network ]; then exit 6 fi if [ $(id -u) -ne 0 ]; then echo "permission denied (must be superuser)" | \ logger -s -p daemon.error -t ipsec_setup 2>&1 exit 4 fi if [ $(ip addr list | grep -c cipsec) -ne 0 ]; then echo "Cisco IPsec client is already loaded, aborting! (cipsec# device found)" exit 1 fi # where the private directory and the config files are IPSEC_CONF="${IPSEC_CONF:-@FINALCONFFILE@}" IPSEC_EXECDIR="${IPSEC_EXECDIR:-@IPSEC_EXECDIR@}" IPSEC_SBINDIR="${IPSEC_SBINDIR:-@IPSEC_SBINDIR@}" unset PLUTO_OPTIONS rundir=@IPSEC_RUNDIR@ plutopid=${rundir}/pluto.pid plutoctl=${rundir}/pluto.ctl lockdir=/run/lock/subsys lockfile=ipsec lockpath=${lockdir}/${lockfile} nofork=@DOCKER_PLUTONOFORK@ if [ -n "${nofork}" ]; then nofork="--nofork " else nofork='' fi # /etc/resolv.conf related paths LIBRESWAN_RESOLV_CONF=${rundir}/libreswan-resolv-conf-backup ORIG_RESOLV_CONF=/etc/resolv.conf # there is some confusion over the name - just do both [ -f /etc/sysconfig/ipsec ] && . /etc/sysconfig/ipsec [ -f /etc/sysconfig/pluto ] && . /etc/sysconfig/pluto # misc setup umask 022 # standardize PATH, and export it for everything else's benefit PATH="${IPSEC_SBINDIR}:/sbin:/usr/sbin:/usr/local/bin:/bin:/usr/bin" export PATH mkdir -p ${rundir} chmod 700 ${rundir} verify_config() { [ -f ${IPSEC_CONF} ] || exit 6 config_error=$(ipsec addconn --config ${IPSEC_CONF} --checkconfig 2>&1) RETVAL=$? if [ ${RETVAL} -gt 0 ]; then echo "Configuration error - the following error occurred:" echo ${config_error} echo "IKE daemon status was not modified" exit ${RETVAL} fi } start() { echo $"Starting pluto IKE daemon for IPsec: " verify_config ipsec _stackmanager start # pluto searches the current directory, so this is required for making it selinux compliant cd / # Enable nflog if configured ipsec --checknflog > /dev/null # Create lockfile [ -d ${lockdir} ] || mkdir -p ${lockdir} touch ${lockpath} # Start pluto on foreground, blocking here until it's killed. ${IPSEC_EXECDIR}/pluto --config ${IPSEC_CONF} @DOCKER_PLUTONOFORK@ ${PLUTO_OPTIONS} if [ "${nofork}" = "--nofork " ]; then # Pluto was killed, remove lockfile rm -f ${lockpath} fi return 0 } stop() { if [ ! -e ${plutoctl} ]; then echo "Missing control file ${plutoctl} - is pluto running?" else echo $"Shutting down pluto IKE daemon" ipsec whack --shutdown # don't use seq, might not exist on embedded for waitsec in 1 2 3 4 5 6 7 8 9 10; do if [ -s ${plutopid} ]; then echo -n "." sleep 1 else break fi done echo rm -f ${plutoctl} # we won't be using this anymore fi if [ -s ${plutopid} ]; then # pluto did not die peacefully echo "Attempt to shut Pluto down failed! Trying kill" kill -p ${plutopid} ${IPSEC_EXECDIR}/pluto RETVAL=$? [ ${RETVAL} -eq 0 ] && rm -f ${plutopid} fi ipsec _stackmanager stop ipsec --stopnflog > /dev/null # cleaning up backup resolv.conf if [ -e ${LIBRESWAN_RESOLV_CONF} ]; then if grep 'Libreswan' ${ORIG_RESOLV_CONF} > /dev/null 2>&1; then cp ${LIBRESWAN_RESOLV_CONF} ${ORIG_RESOLV_CONF} fi rm -f ${LIBRESWAN_RESOLV_CONF} fi rm -f ${lockpath} return ${RETVAL} } restart() { verify_config stop start return $? } condrestart() { if [ -f ${lockpath} ]; then restart return $? fi } version() { ipsec version return $? } # do it case "$1" in start) start RETVAL=$? ;; stop) stop RETVAL=$? ;; restart) restart RETVAL=$? ;; reload|force-reload) restart RETVAL=$? ;; condrestart|try-restart) condrestart RETVAL=$? ;; status) status -p ${plutopid} -l ${lockfile} ${IPSEC_EXECDIR}/pluto RETVAL=$? ${IPSEC_EXECDIR}/whack --status | grep Total | sed 's/^000\ Total\ //' ;; version) version RETVAL=$? ;; *) echo "Usage: $0 {start|stop|restart|reload|force-reload|condrestart|try-restart|status|version}" RETVAL=2 esac exit ${RETVAL} libreswan-3.32/initsystems/docker/sysconfig.pluto.in000066400000000000000000000001061365625662500230040ustar00rootroot00000000000000# Put extra pluto command line options you want here PLUTO_OPTIONS="" libreswan-3.32/initsystems/openrc/000077500000000000000000000000001365625662500173305ustar00rootroot00000000000000libreswan-3.32/initsystems/openrc/Makefile000066400000000000000000000020171365625662500207700ustar00rootroot00000000000000ifndef top_srcdir include ../../mk/dirs.mk endif LIBRESWANSRCDIR?=$(shell cd ../..; pwd) SRCDIR?=${LIBRESWANSRCDIR}/initsystems/openrc/ INITDFILE=$(builddir)/ipsec.init SUBDIRS= INITDDIR=$(RCDIR) include ${LIBRESWANSRCDIR}/Makefile.inc # Use dependencies to force the order. # # (Without this, since local-install-base depends local-base, rules # like local-base and installinitfiles and checkenabled are allowed to # run in parallel) local-base: $(INITDFILE) local-install-base: installinitfiles checkenabled installinitfiles: local-base mkdir -p $(INITDDIR) $(INSTALL) $(INITDFILE) $(INITDDIR)/ipsec checkenabled: installinitfiles @echo checkenabled not yet implemented # XXX: identical to program.mk? $(builddir)/%: $(srcdir)/%.in $(top_srcdir)/Makefile.inc $(top_srcdir)/Makefile.ver | $(builddir) @echo 'IN' $< '->' $@ ${TRANSFORM_VARIABLES} < $< > $@ @if [ -x $< ]; then chmod +x $@; fi @if [ "${PROGRAM}.in" = $< ]; then chmod +x $@; fi include ${top_srcdir}/mk/targets.mk include ${top_srcdir}/mk/builddir.mk libreswan-3.32/initsystems/openrc/ipsec.init.in000077500000000000000000000030471365625662500217340ustar00rootroot00000000000000#!/sbin/runscript name="ipsec pluto daemon" extra_commands="configtest" extra_started_commands="reload" description="pluto is an IKE daemon that is used to setup IPSEC VPN connections." description_configtest="Run syntax tests for configuration files only." description_reload="reloads the configuration - does not affect existing connections" PLUTO_BINARY=${PLUTO_BINARY:-@FINALLIBEXECDIR@/pluto} PLUTO_CONFFILE=${PLUTO_CONFFILE:-@FINALCONFFILE@} IPSEC_BINARY=${IPSEC_BINARY:-@FINALSBINDIR@/ipsec} PLUTO_PIDFILE=${PLUTO_PIDFILE:-/var/run/pluto/pluto.pid} depend() { need net use logger dns provide ipsec } checkconfig() { checkpath --directory /var/run/pluto ${IPSEC_BINARY} addconn --checkconfig || return 1 } configtest() { ebegin "Checking ${SVCNAME} configuration" checkconfig eend $? } start() { checkconfig || return 1 ebegin "Starting ${SVCNAME}" ${IPSEC_BINARY} --checknss ${IPSEC_BINARY} --checknflog ${IPSEC_BINARY} _stackmanager start start-stop-daemon --start --pidfile "${PLUTO_PIDFILE}" \ --exec "${PLUTO_BINARY}" -- --config "${PLUTO_CONFFILE}" \ -- ${PLUTO_OPTS} if [ -f @FINALLIBEXECDIR@/portexcludes ] ; then @FINALLIBEXECDIR@/portexcludes fi eend $? } stop() { if [ "${RC_CMD}" = "restart" ] ; then checkconfig || return 1 fi ebegin "Stopping ${SVCNAME}" start-stop-daemon --stop --pidfile "${PLUTO_PIDFILE}" RETVAL=$? ${IPSEC_BINARY} _stackmanager stop ${IPSEC_BINARY} --stopnflog eend $RETVAL } reload() { checkconfig || return $? ebegin "Reloading ${SVCNAME}" ${IPSEC_BINARY} auto --rereadall eend $? } libreswan-3.32/initsystems/systemd/000077500000000000000000000000001365625662500175325ustar00rootroot00000000000000libreswan-3.32/initsystems/systemd/Makefile000066400000000000000000000073731365625662500212040ustar00rootroot00000000000000ifndef top_srcdir include ../../mk/dirs.mk endif SYSTEMUNITDIR=$(shell pkg-config systemd --variable=systemdsystemunitdir) UNITFILE=ipsec.service UNITDIR=$(DESTDIR)$(SYSTEMUNITDIR) SYSTEMTMPFILESDIR=$(shell pkg-config systemd --variable=tmpfilesdir) TMPFILESCONFIG=libreswan.conf TMPFILESDIR=$(DESTDIR)$(SYSTEMTMPFILESDIR) include $(top_srcdir)/Makefile.inc # Use dependencies to force the order: LOCAL-BASE, # INSTALLSYSTEMDSERVICE, OLDINITDCHECK, POSTCHECK. # # (Without this, since local-install-base depends local-base, rules # like local-base and installsystemdservice are allowed to run in # parallel) local-base: $(builddir)/$(UNITFILE) $(builddir)/$(TMPFILESCONFIG) local-install-base: installsystemdservice oldinitdcheck postcheck installtmpfilesconfig: local-base | $(TMPFILESDIR) $(INSTALL) $(INSTCONFFLAGS) $(builddir)/$(TMPFILESCONFIG) $(TMPFILESDIR) @if test $(TMPFILESDIR) = $(SYSTEMTMPFILESDIR) ; then \ echo running: systemd-tmpfiles --create $(TMPFILESDIR)/$(TMPFILESCONFIG); \ systemd-tmpfiles --create $(TMPFILESDIR)/$(TMPFILESCONFIG); \ fi installsystemdservice: local-base | $(UNITDIR) $(INSTALL) $(INSTCONFFLAGS) $(builddir)/$(UNITFILE) $(UNITDIR) @if test $(UNITDIR) = $(SYSTEMUNITDIR) ; then \ echo running: systemctl --system daemon-reload; \ systemctl --system daemon-reload || echo "failed restart" ; \ fi @if test -f $(DESTDIR)/$(FINALLIBEXECDIR)/portexcludes; then \ echo fixing port excludes ; \ sed -Ei 's@^# (.*/portexcludes)$$@\1@' $(UNITDIR)/$(UNITFILE); \ fi $(UNITDIR): mkdir -p $(UNITDIR) $(TMPFILESDIR): mkdir -p $(TMPFILESDIR) oldinitdcheck: installsystemdservice @if test -f $(DESTDIR)/etc/init.d/ipsec* ; then \ if grep -E -i '(openswan|libreswan)' $(DESTDIR)/etc/init.d/ipsec* > /dev/null 2>&1 ; then \ echo "WARNING: removing older SYSV style init files" ; \ echo "removing: " $(DESTDIR)/etc/init.d/ipsec* $(DESTDIR)/etc/rc*.d/[KS][0-9][0-9]ipsec* ; \ rm -f $(DESTDIR)/etc/init.d/ipsec* $(DESTDIR)/etc/rc*.d/[KS][0-9][0-9]ipsec* ; \ else \ echo "************************** WARNING ***********************************" ; \ echo "old " $(DESTDIR)/etc/init.d/ipsec* " files were found; these should be removed" ; \ echo "**********************************************************************" ; \ fi ; \ fi postcheck: installsystemdservice installtmpfilesconfig oldinitdcheck @if test -z "$(DESTDIR)" -a $(UNITDIR) = $(SYSTEMUNITDIR) -a $(shell systemctl is-enabled ipsec.service) = "disabled" ; then \ echo "DESTDIR='$(DESTDIR)'" ; \ echo "************************** WARNING ***********************************" ; \ echo "The ipsec service is currently disabled. To enable this service issue:" ; \ echo " systemctl enable ipsec.service" ; \ echo "**********************************************************************" ; \ fi ; \ if test -z "$(DESTDIR)" -a $(shell systemctl is-active ipsec.service) = "disabled" ; then \ echo "The ipsec service is currently disabled. To enable this service on boot issue:" ; \ echo " systemctl enable ipsec.service" ; \ fi ; \ if test -z "$(DESTDIR)" -a $(shell systemctl is-active ipsec.service) = "active" ; then \ echo "************************** WARNING ***********************************" ; \ echo "The ipsec service is currently running. You need to restart the service using:" ; \ echo " systemctl restart ipsec.service" ; \ echo "**********************************************************************" ; \ fi # XXX: identical to program.mk? $(builddir)/%: $(srcdir)/%.in $(top_srcdir)/Makefile.inc $(top_srcdir)/Makefile.ver | $(builddir) @echo 'IN' $< '->' $@ $(TRANSFORM_VARIABLES) < $< > $@ @if [ -x $< ]; then chmod +x $@; fi @if [ "$(PROGRAM).in" = $< ]; then chmod +x $@; fi include ${top_srcdir}/mk/targets.mk include ${top_srcdir}/mk/builddir.mk libreswan-3.32/initsystems/systemd/ipsec.service.in000066400000000000000000000025461365625662500226330ustar00rootroot00000000000000[Unit] Description=Internet Key Exchange (IKE) Protocol Daemon for IPsec Wants=network-online.target After=network-online.target Documentation=man:ipsec(8) man:pluto(8) man:ipsec.conf(5) [Service] Type=@SD_TYPE@ Restart=@SD_RESTART_TYPE@ #RestartPreventExitStatus=137 143 SIGTERM SIGKILL # Set WatchdogSec to the amount of time (in seconds) that systemd will wait # before restarting an unresponsive pluto. # EVENT_SD_WATCHDOG updates the heartbeat every 15 seconds, recommended values # are 60, 90, 120. WatchdogSec=0 disables the action NotifyAccess=all WatchdogSec=@SD_WATCHDOGSEC@ # Check configuration file ExecStartPre=@FINALLIBEXECDIR@/addconn --config @FINALCONFFILE@ --checkconfig # Check for kernel modules ExecStartPre=@FINALLIBEXECDIR@/_stackmanager start # Check for nss database status and migration ExecStartPre=@FINALSBINDIR@/ipsec --checknss # Check for nflog setup ExecStartPre=@FINALSBINDIR@/ipsec --checknflog # Start the actual IKE daemon ExecStart=@FINALLIBEXECDIR@/pluto @SD_PLUTO_OPTIONS@ --config @FINALCONFFILE@ --nofork # Enable for portexcludes support # ExecStartPost=@FINALLIBEXECDIR@/portexcludes ExecStop=@FINALLIBEXECDIR@/whack --shutdown ExecStopPost=/sbin/ip xfrm policy flush ExecStopPost=/sbin/ip xfrm state flush ExecStopPost=@FINALSBINDIR@/ipsec --stopnflog ExecReload=@FINALLIBEXECDIR@/whack --listen [Install] WantedBy=multi-user.target libreswan-3.32/initsystems/systemd/libreswan.conf.in000066400000000000000000000000411365625662500227670ustar00rootroot00000000000000d @IPSEC_RUNDIR@ 755 root root - libreswan-3.32/initsystems/systemd/test.sh000077500000000000000000000003271365625662500210520ustar00rootroot00000000000000#!/bin/sh SYSTEMD=`pkg-config systemd --variable=systemdsystemunitdir` if [ -z "$SYSTEMD" ] then echo "no systemd found, installing sysv init system" else echo "Installing systemd ipsec.service in $SYSTEMD" fi libreswan-3.32/initsystems/sysvinit/000077500000000000000000000000001365625662500177325ustar00rootroot00000000000000libreswan-3.32/initsystems/sysvinit/Makefile000066400000000000000000000035061365625662500213760ustar00rootroot00000000000000ifndef top_srcdir include ../../mk/dirs.mk endif LIBRESWANSRCDIR?=$(shell cd ../..; pwd) SRCDIR?=${LIBRESWANSRCDIR}/initsystems/sysvinit/ INITDFILE=$(builddir)/ipsec.init SYSCONFIGFILE=$(builddir)/sysconfig.pluto SUBDIRS= INITDDIR=$(RCDIR) SYSCONFIGDIR=$(SYSCONFDIR)/sysconfig SYSVINIT_DEFAULT_START?= include ${LIBRESWANSRCDIR}/Makefile.inc # Use dependencies to force the order. # # (Without this, since local-install-base depends local-base, rules # like local-base and installinitfiles and checkenabled are allowed to # run in parallel) local-base: $(INITDFILE) $(SYSCONFIGFILE) local-install-base: installinitfiles installsysconfig checkenabled installinitfiles: local-base mkdir -p $(INITDDIR) $(INSTALL) $(INITDFILE) $(INITDDIR)/ipsec installsysconfig: local-base mkdir -p $(SYSCONFIGDIR) if test ! -f $(SYSCONFIGDIR)/pluto ; then \ $(INSTALL) $(INSTCONFFLAGS) $(SYSCONFIGFILE) $(SYSCONFIGDIR)/pluto ; \ fi checkenabled: installinitfiles installsysconfig @count=0 ; \ for dir in $(DESTDIR)/etc/rc?.d ; do \ if test -f $$dir/S??ipsec.init ; then \ count=1 ; \ fi ; \ done ; \ if test $$count = 0 ; then \ echo "************************** WARNING ***********************************" ; \ echo "** The ipsec service is not enabled." ; \ echo "** Enable it using 'chkconfig ipsec on' or another similar method." ; \ echo "**********************************************************************" ; \ fi # XXX: identical to program.mk? $(builddir)/%: $(srcdir)/%.in $(top_srcdir)/Makefile.inc $(top_srcdir)/Makefile.ver | $(builddir) @echo 'IN' $< '->' $@ ${TRANSFORM_VARIABLES} < $< | sed -e "s:@SYSVINIT_DEFAULT_START@:${SYSVINIT_DEFAULT_START}:g" > $@ @if [ -x $< ]; then chmod +x $@; fi @if [ "${PROGRAM}.in" = $< ]; then chmod +x $@; fi include ${top_srcdir}/mk/targets.mk include ${top_srcdir}/mk/builddir.mk libreswan-3.32/initsystems/sysvinit/init.debian.in000066400000000000000000000122231365625662500224460ustar00rootroot00000000000000 FIXME #!@SHELL_BINARY@ # IPsec startup and shutdown script # ### BEGIN INIT INFO # Provides: ipsec # Required-Start: $network $remote_fs $syslog $named # Required-Stop: $syslog $remote_fs # Default-Start: # Default-Stop: 0 1 6 # Short-Description: Start Libreswan IPsec at boot time # Description: Enable automatic key management for IPsec (KLIPS and NETKEY) ### END INIT INFO # ### see https://bugzilla.redhat.com/show_bug.cgi?id=636572 ### Debian and Fedora interpret the LSB differently ### Default-Start: 2 3 4 5 # # Copyright (C) 1998, 1999, 2001 Henry Spencer. # Copyright (C) 2002 Michael Richardson # Copyright (C) 2006 Michael Richardson # Copyright (C) 2008 Michael Richardson # Copyright (C) 2008-2011, 2013 Tuomo Soini # Copyright (C) 2012 Paul Wouters # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # # # ipsec init.d script for starting and stopping # the IPsec security subsystem (KLIPS and Pluto). # # This script becomes /etc/rc.d/init.d/ipsec (or possibly /etc/init.d/ipsec) # and is also accessible as "ipsec setup" (the preferred route for human # invocation). # # The startup and shutdown times are a difficult compromise (in particular, # it is almost impossible to reconcile them with the insanely early/late # times of NFS filesystem startup/shutdown). Startup is after startup of # syslog and pcmcia support; shutdown is just before shutdown of syslog. # # chkconfig: - 47 76 # description: IPsec provides encrypted and authenticated communications; \ # NETKEY/KLIPS is the kernel half of it, Pluto is the user-level management daemon. # Source function library. . /etc/init.d/functions # Check that networking is up. [ "${NETWORKING}" = "no" ] && exit 6 if [ ! -f /etc/sysconfig/network ]; then exit 6 fi if [ `id -u` -ne 0 ] then echo "permission denied (must be superuser)" | \ logger -s -p daemon.error -t ipsec_setup 2>&1 exit 4 fi # where the private directory and the config files are IPSEC_CONF="${IPSEC_CONF:-@FINALCONFFILE@}" IPSEC_EXECDIR="${IPSEC_EXECDIR:-@IPSEC_EXECDIR@}" IPSEC_SBINDIR="${IPSEC_SBINDIR:-@IPSEC_SBINDIR@}" # Does not make any sense at all to continue without the main binary # But before we can quit we should check if we are on a Debian based # system as their policy demands a graceful exit code test -f /etc/debian_version && BINARY_ERROR=0 || BINARY_ERROR=5 test -x $IPSEC_SBINDIR/ipsec || exit $BINARY_ERROR if [ -f /etc/sysconfig/ipsec ]; then . /etc/sysconfig/ipsec elif [ -f /etc/default/ipsec ]; then . /etc/default/ipsec fi # misc setup umask 022 mkdir -p /var/run/pluto chmod 700 /var/run/pluto if test `ip addr list|grep -c cipsec` -ne 0 then echo "Cisco IPsec client is already loaded, aborting! (cipsec# device found)" exit 1 fi # which kernel are we using? IPSECprotostack=`ipsec addconn --config $IPSEC_CONF --liststack` verify_config() { test -f $IPSEC_CONF || exit 6 config_error=`ipsec addconn --config $IPSEC_CONF --checkconfig 2>&1` RETVAL=$? if [ $RETVAL != 0 ] then echo "Configuration error - the following error occurred:" echo $config_error echo "IKE daemon status was not modified" exit $RETVAL fi # Create nss db or convert from old format to new sql format ipsec --checknss # Enable nflog if configured ipsec --checknflog > /dev/null } start() { # starting a stack will unload any loaded stack first (same or different stack) case $IPSECprotostack in netkey) ipsec _startnetkey start ;; none|nostack) ipsec _startklips stop ipsec _startnetkey stop ;; mast|klips) ipsec _startklips start ;; *) echo "unexpected stack $IPSECprotostack" exit ;; esac echo -n "Starting pluto IKE daemon for IPsec: " ipsec _plutorun --config ${IPSEC_CONF} --nofork ${PLUTO_OPTIONS} & RETVAL=$? sleep 2 if [ -f @FINALLIBEXECDIR@/portexcludes ] ; then @FINALLIBEXECDIR@/portexcludes fi return $RETVAL } stop() { ipsec --stopnflog > /dev/null ipsec whack --shutdown } restart() { verify_config stop start } condrestart() { verify_config /etc/init.d/ipsec status || exit 0 restart } status() { RETVAL=$? return $RETVAL } version() { ipsec version RETVAL=$? return $RETVAL } # do it case "$1" in start) start ;; stop) stop ;; restart) restart ;; reload|force-reload) restart ;; condrestart|try-restart) condrestart ;; status) status ;; version) version ;; *) echo "Usage: $0 {start|stop|restart|reload|force-reload|condrestart|try-restart|status|version}" RETVAL=2 esac exit $RETVAL libreswan-3.32/initsystems/sysvinit/init.rhel000077500000000000000000000147241365625662500215640ustar00rootroot00000000000000#!/bin/sh # IPsec startup and shutdown script # ### BEGIN INIT INFO # Provides: ipsec # Required-Start: $network $remote_fs $syslog $named # Required-Stop: $syslog $remote_fs # Default-Start: # Default-Stop: 0 1 6 # Short-Description: Start Libreswan IPsec at boot time # Description: Enable automatic key management for IPsec (KLIPS and NETKEY) ### END INIT INFO # ### see https://bugzilla.redhat.com/show_bug.cgi?id=636572 ### Debian and Fedora interpret the LSB differently for Default-Start: # Copyright (C) 1998, 1999, 2001 Henry Spencer. # Copyright (C) 2002 Michael Richardson # Copyright (C) 2006 Michael Richardson # Copyright (C) 2008 Michael Richardson # Copyright (C) 2008-2015 Tuomo Soini # Copyright (C) 2012 Paul Wouters # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # # ipsec sysv style init.d script for starting and stopping # the IPsec security subsystem (KLIPS and Pluto). # # This script becomes /etc/rc.d/init.d/ipsec # and is also accessible as "ipsec setup" # # The startup and shutdown times are a difficult compromise (in particular, # it is almost impossible to reconcile them with the insanely early/late # times of NFS filesystem startup/shutdown). Startup is after startup of # syslog and pcmcia support; shutdown is just before shutdown of syslog. # # chkconfig: - 47 76 # description: IPsec provides encrypted and authenticated communications; \ # NETKEY/KLIPS is the kernel half of it, Pluto is the user-level management daemon. test ${IPSEC_INIT_SCRIPT_DEBUG} && set -v -x # Source function library. . /etc/rc.d/init.d/functions # Check that networking is up. [ "${NETWORKING}" = "no" ] && exit 6 if [ ! -f /etc/sysconfig/network ]; then exit 6 fi if [ $(id -u) -ne 0 ]; then echo "permission denied (must be superuser)" | \ logger -s -p daemon.error -t ipsec_setup 2>&1 exit 4 fi if [ $(ip addr list | grep -c cipsec) -ne 0 ]; then echo "Cisco IPsec client is already loaded, aborting! (cipsec# device found)" exit 1 fi # where the private directory and the config files are IPSEC_CONF="${IPSEC_CONF:-/etc/ipsec.conf}" IPSEC_EXECDIR="${IPSEC_EXECDIR:-/usr/libexec/ipsec}" IPSEC_SBINDIR="${IPSEC_SBINDIR:-/usr/sbin}" unset PLUTO_OPTIONS rundir=/var/run/pluto plutopid=${rundir}/pluto.pid plutoctl=${rundir}/pluto.ctl lockdir=/var/lock/subsys lockfile=ipsec lockpath=${lockdir}/${lockfile} # /etc/resolv.conf related paths LIBRESWAN_RESOLV_CONF=${rundir}/libreswan-resolv-conf-backup ORIG_RESOLV_CONF=/etc/resolv.conf # there is some confusion over the name - just do both [ -f /etc/sysconfig/ipsec ] && . /etc/sysconfig/ipsec [ -f /etc/sysconfig/pluto ] && . /etc/sysconfig/pluto # misc setup umask 022 # standardize PATH, and export it for everything else's benefit PATH="${IPSEC_SBINDIR}:/sbin:/usr/sbin:/usr/local/bin:/bin:/usr/bin" export PATH mkdir -p ${rundir} chmod 700 ${rundir} verify_config() { [ -f ${IPSEC_CONF} ] || exit 6 config_error=$(ipsec addconn --config ${IPSEC_CONF} --checkconfig 2>&1) RETVAL=$? if [ ${RETVAL} -gt 0 ]; then echo "Configuration error - the following error occurred:" echo ${config_error} echo "IKE daemon status was not modified" exit ${RETVAL} fi } start() { echo -n $"Starting pluto IKE daemon for IPsec: " ipsec _stackmanager start # pluto searches the current directory, so this is required for making it selinux compliant cd / # Create nss db or convert from old format to new sql format ipsec --checknss # Enable nflog if configured ipsec --checknflog > /dev/null # This script will enter an endless loop to ensure pluto restarts on crash ipsec _plutorun --config ${IPSEC_CONF} --nofork ${PLUTO_OPTIONS} & [ -d ${lockdir} ] || mkdir -p ${lockdir} touch ${lockpath} # Because _plutorun starts pluto at background we need to make sure pluto is started # before we know if start was successful or not for waitsec in 1 2 3 4 5; do if status -p ${plutopid} -l ${lockfile} ${IPSEC_EXECDIR}/pluto >/dev/null; then RETVAL=0 break else echo -n "." sleep 1 RETVAL=1 fi done if [ ${RETVAL} -eq 0 ]; then success else rm -f ${lockpath} failure fi echo if [ -f @FINALLIBEXECDIR@/portexcludes ] ; then @FINALLIBEXECDIR@/portexcludes fi return ${RETVAL} } stop() { if [ -e ${plutoctl} ]; then echo $"Shutting down pluto IKE daemon" ipsec whack --shutdown 2>/dev/null # don't use seq, might not exist on embedded for waitsec in 1 2 3 4 5 6 7 8 9 10; do if [ -s ${plutopid} ]; then echo -n "." sleep 1 else break fi done echo rm -f ${plutoctl} # we won't be using this anymore fi if [ -s ${plutopid} ]; then # pluto did not die peacefully killproc -p ${plutopid} ${IPSEC_EXECDIR}/pluto RETVAL=$? [ ${RETVAL} -eq 0 ] && rm -f ${plutopid} fi ipsec _stackmanager stop ipsec --stopnflog > /dev/null # cleaning up backup resolv.conf if [ -e ${LIBRESWAN_RESOLV_CONF} ]; then if grep 'Libreswan' ${ORIG_RESOLV_CONF} > /dev/null 2>&1; then cp ${LIBRESWAN_RESOLV_CONF} ${ORIG_RESOLV_CONF} fi rm -f ${LIBRESWAN_RESOLV_CONF} fi rm -f ${lockpath} return ${RETVAL} } restart() { verify_config stop start return $? } condrestart() { if [ -f ${lockpath} ]; then restart return $? fi } version() { ipsec version return $? } # do it case "$1" in start) start RETVAL=$? ;; stop) stop RETVAL=$? ;; restart) restart RETVAL=$? ;; reload|force-reload) restart RETVAL=$? ;; condrestart|try-restart) condrestart RETVAL=$? ;; status) status -p ${plutopid} -l ${lockfile} ${IPSEC_EXECDIR}/pluto RETVAL=$? ${IPSEC_EXECDIR}/whack --status 2>/dev/null | grep Total | sed 's/^000\ Total\ //' ;; version) version RETVAL=$? ;; *) echo "Usage: $0 {start|stop|restart|reload|force-reload|condrestart|try-restart|status|version}" RETVAL=2 esac exit ${RETVAL} libreswan-3.32/initsystems/sysvinit/ipsec.init.in000077500000000000000000000170411365625662500223350ustar00rootroot00000000000000#!@SHELL_BINARY@ # IPsec startup and shutdown script # ### BEGIN INIT INFO # Provides: ipsec # Required-Start: $network $remote_fs $syslog $named # Required-Stop: $syslog $remote_fs # Default-Start: @SYSVINIT_DEFAULT_START@ # Default-Stop: 0 1 6 # Short-Description: Start Libreswan IPsec at boot time # Description: Enable automatic key management for IPsec (KLIPS and NETKEY) ### END INIT INFO # ### see https://bugzilla.redhat.com/show_bug.cgi?id=636572 ### Debian and Fedora interpret the LSB differently for Default-Start: # Copyright (C) 1998, 1999, 2001 Henry Spencer. # Copyright (C) 2002 Michael Richardson # Copyright (C) 2006 Michael Richardson # Copyright (C) 2008 Michael Richardson # Copyright (C) 2008-2015 Tuomo Soini # Copyright (C) 2012 Paul Wouters # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # # ipsec sysv style init.d script for starting and stopping # the IPsec security subsystem (KLIPS and Pluto). # # This script becomes @FINALRCDIR@/ipsec # and is also accessible as "ipsec setup" # # The startup and shutdown times are a difficult compromise (in particular, # it is almost impossible to reconcile them with the insanely early/late # times of NFS filesystem startup/shutdown). Startup is after startup of # syslog and pcmcia support; shutdown is just before shutdown of syslog. # # chkconfig: - 47 76 # description: IPsec provides encrypted and authenticated communications; \ # NETKEY/KLIPS is the kernel half of it, Pluto is the user-level management daemon. test ${IPSEC_INIT_SCRIPT_DEBUG} && set -v -x # Source function library. if [ -f @FINALRCDIR@/functions ]; then . @FINALRCDIR@/functions elif [ -f /lib/lsb/init-functions ]; then . /lib/lsb/init-functions fi # Check that networking is up. [ "${NETWORKING}" = "no" ] && exit 6 if [ $(id -u) -ne 0 ]; then echo "permission denied (must be superuser)" | \ logger -s -p daemon.error -t ipsec_setup 2>&1 exit 4 fi if [ $(ip addr list | grep -c cipsec) -ne 0 ]; then echo "Cisco IPsec client is already loaded, aborting! (cipsec# device found)" exit 1 fi # where the private directory and the config files are IPSEC_CONF="${IPSEC_CONF:-@FINALCONFFILE@}" IPSEC_EXECDIR="${IPSEC_EXECDIR:-@IPSEC_EXECDIR@}" IPSEC_SBINDIR="${IPSEC_SBINDIR:-@IPSEC_SBINDIR@}" unset PLUTO_OPTIONS rundir=@IPSEC_RUNDIR@ plutopid=${rundir}/pluto.pid plutoctl=${rundir}/pluto.ctl lockdir=@FINALVARDIR@/lock/subsys lockfile=${lockdir}/ipsec # @FINALSYSCONFDIR@/resolv.conf related paths LIBRESWAN_RESOLV_CONF=${rundir}/libreswan-resolv-conf-backup ORIG_RESOLV_CONF=@FINALSYSCONFDIR@/resolv.conf # there is some confusion over the name - just do both [ -f @FINALSYSCONFDIR@/sysconfig/ipsec ] && . @FINALSYSCONFDIR@/sysconfig/ipsec [ -f @FINALSYSCONFDIR@/sysconfig/pluto ] && . @FINALSYSCONFDIR@/sysconfig/pluto # misc setup umask 022 # standardize PATH, and export it for everything else's benefit PATH="${IPSEC_SBINDIR}:/sbin:/usr/sbin:/usr/local/bin:/bin:/usr/bin" export PATH mkdir -p ${rundir} chmod 700 ${rundir} verify_config() { [ -f ${IPSEC_CONF} ] || exit 6 config_error=$(ipsec addconn --config ${IPSEC_CONF} --checkconfig 2>&1) RETVAL=$? if [ ${RETVAL} -gt 0 ]; then echo "Configuration error - the following error occurred:" echo ${config_error} echo "IKE daemon status was not modified" exit ${RETVAL} fi } start() { echo -n "Starting pluto IKE daemon for IPsec: " ipsec _stackmanager start # pluto searches the current directory, so this is required for making it selinux compliant cd / # Create nss db or convert from old format to new sql format ipsec --checknss # Enable nflog if configured ipsec --checknflog > /dev/null # This script will enter an endless loop to ensure pluto restarts on crash ipsec _plutorun --config ${IPSEC_CONF} --nofork ${PLUTO_OPTIONS} & [ -d ${lockdir} ] || mkdir -p ${lockdir} touch ${lockfile} # Because _plutorun starts pluto at background we need to make sure pluto is started # before we know if start was successful or not for waitsec in 1 2 3 4 5; do if status >/dev/null; then RETVAL=0 break else echo -n "." sleep 1 RETVAL=1 fi done if [ ${RETVAL} -ge 1 ]; then rm -f ${lockfile} fi echo if [ -f @FINALLIBEXECDIR@/portexcludes ] ; then @FINALLIBEXECDIR@/portexcludes fi return ${RETVAL} } stop() { if [ -e ${plutoctl} ]; then echo "Shutting down pluto IKE daemon" ipsec whack --shutdown 2>/dev/null # don't use seq, might not exist on embedded for waitsec in 1 2 3 4 5 6 7 8 9 10; do if [ -s ${plutopid} ]; then echo -n "." sleep 1 else break fi done echo rm -f ${plutoctl} # we won't be using this anymore fi if [ -s ${plutopid} ]; then # pluto did not die peacefully pid=$(cat ${plutopid}) if [ -d /proc/${pid} ]; then kill -TERM ${pid} RETVAL=$? sleep 5; if [ -d /proc/${pid} ]; then kill -KILL ${pid} RETVAL=$? fi if [ ${RETVAL} -ne 0 ]; then echo "Kill failed - removing orphaned ${plutopid}" fi else echo "Removing orphaned ${plutopid}" fi rm -f ${plutopid} fi ipsec _stackmanager stop ipsec --stopnflog > /dev/null # cleaning up backup resolv.conf if [ -e ${LIBRESWAN_RESOLV_CONF} ]; then if grep 'Libreswan' ${ORIG_RESOLV_CONF} > /dev/null 2>&1; then cp ${LIBRESWAN_RESOLV_CONF} ${ORIG_RESOLV_CONF} fi rm -f ${LIBRESWAN_RESOLV_CONF} fi rm -f ${lockfile} return ${RETVAL} } restart() { verify_config stop start return $? } status() { local RC if [ -f ${plutopid} ]; then if [ -r ${plutopid} ]; then pid=$(cat ${plutopid}) if [ -n "$pid" -a -d /proc/${pid} ]; then RC=0 # running else RC=1 # not running but pid exists fi else RC=4 # insufficient privileges fi fi if [ -z "${RC}" ]; then if [ -f ${lockfile} ]; then RC=2 else RC=3 fi fi case "${RC}" in 0) echo "ipsec: pluto (pid ${pid}) is running..." return 0 ;; 1) echo "ipsec: pluto dead but pid file exits" return 1 ;; 2) echo "ipsec: pluto dead but subsys locked" return 2 ;; 4) echo "ipsec: pluto status unknown due to insufficient privileges." return 4 ;; esac echo "ipsec: pluto is stopped" return 3 } condrestart() { verify_config RETVAL=$? if [ -f ${lockfile} ]; then restart RETVAL=$? fi return ${RETVAL} } version() { ipsec version return $? } # do it case "$1" in start) start RETVAL=$? ;; stop) stop RETVAL=$? ;; restart) restart RETVAL=$? ;; reload|force-reload) restart RETVAL=$? ;; condrestart|try-restart) condrestart RETVAL=$? ;; status) status RETVAL=$? ${IPSEC_EXECDIR}/whack --status 2>/dev/null | grep Total | sed 's/^000\ Total\ //' ;; version) version RETVAL=$? ;; *) echo "Usage: $0 {start|stop|restart|reload|force-reload|condrestart|try-restart|status|version}" RETVAL=2 esac exit ${RETVAL} libreswan-3.32/initsystems/sysvinit/sysconfig.pluto.in000066400000000000000000000001071365625662500234260ustar00rootroot00000000000000# Put extra pluto command line options you want here PLUTO_OPTIONS=" " libreswan-3.32/initsystems/upstart/000077500000000000000000000000001365625662500175445ustar00rootroot00000000000000libreswan-3.32/initsystems/upstart/Makefile000066400000000000000000000023111365625662500212010ustar00rootroot00000000000000ifndef top_srcdir include ../../mk/dirs.mk endif LIBRESWANSRCDIR?=$(shell cd ../..; pwd) SRCDIR?=${LIBRESWANSRCDIR}/initsystems/systemd/ UPSTARTFILE=$(builddir)/ipsec.conf DEFAULTFILE=$(builddir)/default.pluto SUBDIRS= UPSTARTDIR=$(SYSCONFDIR)/init DEFAULTDIR=$(SYSCONFDIR)/default include ${LIBRESWANSRCDIR}/Makefile.inc # Use dependencies to force the order. # # (Without this, since local-install-base depends local-base, rules # like local-base and installinitfiles and checkenabled are allowed to # run in parallel) local-base: $(UPSTARTFILE) $(DEFAULTFILE) local-install-base: installupstartconf installdefault installupstartconf: local-base @mkdir -p $(UPSTARTDIR) $(INSTALL) $(UPSTARTFILE) $(UPSTARTDIR); installdefault: local-base mkdir -p $(DEFAULTDIR) if test ! -f $(DEFAULTDIR)/pluto ; then \ $(INSTALL) $(DEFAULTFILE) $(DEFAULTDIR)/pluto ; \ fi # XXX: identical to program.mk? $(builddir)/%: $(srcdir)/%.in $(top_srcdir)/Makefile.inc $(top_srcdir)/Makefile.ver | $(builddir) @echo 'IN' $< '->' $@ ${TRANSFORM_VARIABLES} < $< > $@ @if [ -x $< ]; then chmod +x $@; fi @if [ "${PROGRAM}.in" = $< ]; then chmod +x $@; fi include ${top_srcdir}/mk/targets.mk include ${top_srcdir}/mk/builddir.mk libreswan-3.32/initsystems/upstart/default.pluto.in000066400000000000000000000001061365625662500226570ustar00rootroot00000000000000# Put extra pluto command line options you want here PLUTO_OPTIONS="" libreswan-3.32/initsystems/upstart/ipsec.conf.in000066400000000000000000000017501365625662500221260ustar00rootroot00000000000000# ipsec - ipsec services and ike demon (pluto) # # IPsec provides encrypted and authenticated communications; # NETKEY/KLIPS is the kernel half of it, Pluto is the user-level # management daemon. description "libreswan ipsec services" start on runlevel [2345] stop on runlevel [!2345] respawn pre-start script cd / . /etc/default/pluto @FINALSBINDIR@/ipsec addconn --config @FINALCONFFILE@ --checkconfig end script script . /etc/default/pluto @FINALSBINDIR@/ipsec --checknss @FINALSBINDIR@/ipsec --checknflog @FINALSBINDIR@/ipsec _stackmanager start @FINALLIBEXECDIR@/pluto --config @FINALCONFFILE@ --nofork $PLUTO_OPTIONS if [ -f @FINALLIBEXECDIR@/portexcludes ] ; then @FINALLIBEXECDIR@/portexcludes fi end script pre-stop script # do not run whack --shutdown in pre-stop, it confused stop into restarting # @FINALSBINDIR@/ipsec whack --shutdown @FINALSBINDIR@/ipsec --stopnflog ip xfrm policy flush ip xfrm state flush end script libreswan-3.32/lib/000077500000000000000000000000001365625662500142155ustar00rootroot00000000000000libreswan-3.32/lib/COPYING.LIB000066400000000000000000000614471365625662500156710ustar00rootroot00000000000000 GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Library General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! libreswan-3.32/lib/Makefile000066400000000000000000000017251365625662500156620ustar00rootroot00000000000000# Makefile for the KLIPS interface utilities # # Copyright (C) 1998, 1999 Henry Spencer. # Copyright (C) 1999, 2000, 2001 Richard Guy Briggs # Copyright (C) 2015 Andrew Cagney # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. ifndef top_srcdir include ../mk/dirs.mk endif include $(top_srcdir)/Makefile.inc SUBDIRS=libswan libcrypto libwhack libipsecconf SUBDIRS += liblswtool ifeq ($(USE_BSDKAME),true) SUBDIRS+=libbsdpfkey endif include $(top_srcdir)/mk/subdirs.mk libreswan-3.32/lib/Makefile.kernel000066400000000000000000000026401365625662500171360ustar00rootroot00000000000000# FreeS/WAN library # Copyright (C) 1998-2002 Henry Spencer. # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. include ../Makefile.inc include ../Makefile.ver ifndef TOPDIR TOPDIR := /usr/src/linux endif L_TARGET := libkernel.a obj-y := addrtoa.o datatot.o goodmask.o \ pfkey_v2_build.o pfkey_v2_debug.o pfkey_v2_ext_bits.o pfkey_v2_parse.o \ prng.o rangetoa.o satoa.o \ subnetof.o subnettoa.o version.o HDRS=freeswan.h internal.h EXTRA_CFLAGS += -I. $(KLIPSCOMPILE) EXTRA_CFLAGS += ${WERROR} active-objs := $(sort $(obj-y) $(obj-m)) L_OBJS := $(obj-y) M_OBJS := $(obj-m) MIX_OBJS := $(filter $(export-objs), $(active-objs)) include $(TOPDIR)/Rules.make $(obj-y): $(HDRS) # build version.c using version number from Makefile.ver version.c: version.in.c sed '/"/s/@IPSECVERSION@/$(IPSECVERSION)/' version.in.c >$@ clean: rm -f $(L_TARGET) *.o try* core *.core version.c ( cd des && $(MAKE) clean ) libreswan-3.32/lib/libbsdpfkey/000077500000000000000000000000001365625662500165135ustar00rootroot00000000000000libreswan-3.32/lib/libbsdpfkey/Makefile000066400000000000000000000001761365625662500201570ustar00rootroot00000000000000LIB=libbsdpfkey.a OBJS = pfkey.o ifdef top_srcdir include $(top_srcdir)/mk/library.mk else include ../../mk/library.mk endif libreswan-3.32/lib/libbsdpfkey/ipsec_dump_policy.c000066400000000000000000000166221365625662500223750ustar00rootroot00000000000000/* $KAME: ipsec_dump_policy.c,v 1.13 2002/06/27 14:35:11 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. * 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. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include "ipsec_strerror.h" static const char *ipsp_dir_strs[] = { "any", "in", "out", }; static const char *ipsp_policy_strs[] = { "discard", "none", "ipsec", "entrust", "bypass", }; static char *ipsec_dump_ipsecrequest(char *, size_t, struct sadb_x_ipsecrequest *, size_t); static int set_addresses(char *, size_t, struct sockaddr *, struct sockaddr *); static char *set_address(char *, size_t, struct sockaddr *); /* * policy is sadb_x_policy buffer. * Must call free() later. * When delimiter == NULL, alternatively ' '(space) is applied. */ char *ipsec_dump_policy(policy, delimiter) caddr_t policy; char *delimiter; { struct sadb_x_policy *xpl = (struct sadb_x_policy *)policy; struct sadb_x_ipsecrequest *xisr; size_t off, buflen; char *buf; char isrbuf[1024]; char *newbuf; /* sanity check */ if (policy == NULL) return NULL; if (xpl->sadb_x_policy_exttype != SADB_X_EXT_POLICY) { __ipsec_errcode = EIPSEC_INVAL_EXTTYPE; return NULL; } /* set delimiter */ if (delimiter == NULL) delimiter = " "; switch (xpl->sadb_x_policy_dir) { case IPSEC_DIR_ANY: case IPSEC_DIR_INBOUND: case IPSEC_DIR_OUTBOUND: break; default: __ipsec_errcode = EIPSEC_INVAL_DIR; return NULL; } switch (xpl->sadb_x_policy_type) { case IPSEC_POLICY_DISCARD: case IPSEC_POLICY_NONE: case IPSEC_POLICY_IPSEC: case IPSEC_POLICY_BYPASS: case IPSEC_POLICY_ENTRUST: break; default: __ipsec_errcode = EIPSEC_INVAL_POLICY; return NULL; } buflen = strlen(ipsp_dir_strs[xpl->sadb_x_policy_dir]) + 1 + /* space */ strlen(ipsp_policy_strs[xpl->sadb_x_policy_type]) + 1; /* NUL */ if ((buf = malloc(buflen)) == NULL) { __ipsec_errcode = EIPSEC_NO_BUFS; return NULL; } snprintf(buf, buflen, "%s %s", ipsp_dir_strs[xpl->sadb_x_policy_dir], ipsp_policy_strs[xpl->sadb_x_policy_type]); if (xpl->sadb_x_policy_type != IPSEC_POLICY_IPSEC) { __ipsec_errcode = EIPSEC_NO_ERROR; return buf; } /* count length of buffer for use */ off = sizeof(*xpl); while (off < PFKEY_EXTLEN(xpl)) { xisr = (struct sadb_x_ipsecrequest *)((caddr_t)xpl + off); off += xisr->sadb_x_ipsecrequest_len; } /* validity check */ if (off != PFKEY_EXTLEN(xpl)) { __ipsec_errcode = EIPSEC_INVAL_SADBMSG; free(buf); return NULL; } off = sizeof(*xpl); while (off < PFKEY_EXTLEN(xpl)) { xisr = (struct sadb_x_ipsecrequest *)((caddr_t)xpl + off); if (ipsec_dump_ipsecrequest(isrbuf, sizeof(isrbuf), xisr, PFKEY_EXTLEN(xpl) - off) == NULL) { free(buf); return NULL; } buflen = strlen(buf) + strlen(delimiter) + strlen(isrbuf) + 1; newbuf = (char *)realloc(buf, buflen); if (newbuf == NULL) { __ipsec_errcode = EIPSEC_NO_BUFS; free(buf); return NULL; } buf = newbuf; snprintf(buf, buflen, "%s%s%s", buf, delimiter, isrbuf); off += xisr->sadb_x_ipsecrequest_len; } __ipsec_errcode = EIPSEC_NO_ERROR; return buf; } static char *ipsec_dump_ipsecrequest(buf, len, xisr, bound) char *buf; size_t len; struct sadb_x_ipsecrequest *xisr; size_t bound; /* boundary */ { const char *proto, *mode, *level; char abuf[NI_MAXHOST * 2 + 2]; if (xisr->sadb_x_ipsecrequest_len > bound) { __ipsec_errcode = EIPSEC_INVAL_PROTO; return NULL; } switch (xisr->sadb_x_ipsecrequest_proto) { case IPPROTO_ESP: proto = "esp"; break; case IPPROTO_AH: proto = "ah"; break; case IPPROTO_IPCOMP: proto = "ipcomp"; break; case IPPROTO_TCP: proto = "tcp"; default: __ipsec_errcode = EIPSEC_INVAL_PROTO; return NULL; } switch (xisr->sadb_x_ipsecrequest_mode) { case IPSEC_MODE_ANY: mode = "any"; break; case IPSEC_MODE_TRANSPORT: mode = "transport"; break; case IPSEC_MODE_TUNNEL: mode = "tunnel"; break; default: __ipsec_errcode = EIPSEC_INVAL_MODE; return NULL; } abuf[0] = '\0'; if (xisr->sadb_x_ipsecrequest_len > sizeof(*xisr)) { struct sockaddr *sa1, *sa2; caddr_t p; p = (caddr_t)(xisr + 1); sa1 = (struct sockaddr *)p; sa2 = (struct sockaddr *)(p + sa1->sa_len); if (sizeof(*xisr) + sa1->sa_len + sa2->sa_len != xisr->sadb_x_ipsecrequest_len) { __ipsec_errcode = EIPSEC_INVAL_ADDRESS; return NULL; } if (set_addresses(abuf, sizeof(abuf), sa1, sa2) != 0) { __ipsec_errcode = EIPSEC_INVAL_ADDRESS; return NULL; } } switch (xisr->sadb_x_ipsecrequest_level) { case IPSEC_LEVEL_DEFAULT: level = "default"; break; case IPSEC_LEVEL_USE: level = "use"; break; case IPSEC_LEVEL_REQUIRE: level = "require"; break; case IPSEC_LEVEL_UNIQUE: level = "unique"; break; default: __ipsec_errcode = EIPSEC_INVAL_LEVEL; return NULL; } if (xisr->sadb_x_ipsecrequest_reqid == 0) { snprintf(buf, len, "%s/%s/%s/%s", proto, mode, abuf, level); } else { snprintf(buf, len, "%s/%s/%s/%s%c%u", proto, mode, abuf, level, xisr->sadb_x_ipsecrequest_reqid > IPSEC_MANUAL_REQID_MAX ? '#' : ':', xisr->sadb_x_ipsecrequest_reqid); } return buf; } static int set_addresses(buf, len, sa1, sa2) char *buf; size_t len; struct sockaddr *sa1; struct sockaddr *sa2; { char tmp1[NI_MAXHOST], tmp2[NI_MAXHOST]; if (set_address(tmp1, sizeof(tmp1), sa1) == NULL || set_address(tmp2, sizeof(tmp2), sa2) == NULL) return -1; if (strlen(tmp1) + 1 + strlen(tmp2) + 1 > len) return -1; snprintf(buf, len, "%s-%s", tmp1, tmp2); return 0; } static char *set_address(buf, len, sa) char *buf; size_t len; struct sockaddr *sa; { const int niflags = NI_NUMERICHOST; if (len < 1) return NULL; buf[0] = '\0'; if (getnameinfo(sa, sa->sa_len, buf, len, NULL, 0, niflags) != 0) return NULL; return buf; } libreswan-3.32/lib/libbsdpfkey/ipsec_get_policylen.c000066400000000000000000000036131365625662500227020ustar00rootroot00000000000000/* $KAME: ipsec_get_policylen.c,v 1.5 2000/05/07 05:25:03 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. * 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. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include "ipsec_strerror.h" int ipsec_get_policylen(policy) caddr_t policy; { return policy ? PFKEY_EXTLEN(policy) : -1; } libreswan-3.32/lib/libbsdpfkey/ipsec_set_policy.3000066400000000000000000000171701365625662500221420ustar00rootroot00000000000000'\" t .\" Title: IPSEC_SET_POLICY .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.75.2 .\" Date: 02/25/2010 .\" Manual: [FIXME: manual] .\" Source: [FIXME: source] .\" Language: English .\" .TH "IPSEC_SET_POLICY" "3" "02/25/2010" "[FIXME: source]" "[FIXME: manual]" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" _ipsec_set_policy \- create an IPsec policy structure from a human readable string .SH "SYNOPSIS" .sp .ft B .nf #include .fi .ft .HP \w'char\ *ipsec_set_policy('u .BI "char *ipsec_set_policy(char\ *\ " "policy" ", int\ " "len" ");" .HP \w'int\ ipsec_get_policylen('u .BI "int ipsec_get_policylen(char\ *\ " "buf" ");" .HP \w'char\ *ipsec_dump_policy('u .BI "char *ipsec_dump_policy(char\ *\ " "buf" ", char\ *\ " "delim" ");" .SH "LIBRARY" .PP IPsec Policy Control Library (libipsec, \-lipsec) .SH "DESCRIPTION" .PP The ipsec_set_policy(); function generates an IPsec policy specification structure, struct sadb_x_policy and/or struct sadb_x_ipsecrequest from a human\-readable policy specification\&. The policy specification must be given as a C string, passed in the \fIpolicy\fR argument and the length of the string, given as \fIlen\fR\&. The ipsec_set_policy(); function returns pointer to a buffer that contains a properly formed IPsec policy specification structure\&. The buffer is dynamically allocated, and must be freed by using the \fBfree\fR(3) library function\&. .PP The ipsec_get_policylen(); function will returns the address of the buffer that is needed when passing the specification structure to the \fBsetsockopt\fR(2) system call\&. .PP The ipsec_dump_policy(); function converts an IPsec policy structure into a human readable form\&. The \fIbuf\fR argument points to an IPsec policy structure, struct sadb_x_policy\&. \fIdelim\fR is a delimiter string, which is usually a blank character\&. If you set \fIdelim\fR to \fBNULL\fR, a single white space is assumed\&. The ipsec_dump_policy(); function returns a pointer to dynamically allocated string\&. It is the caller\'s responsibility to free the returned pointer using the \fBfree\fR(3) library call\&. .PP A \fIpolicy\fR is given in the following way: .PP \fIdirection\fR discard .RS 4 The \fIdirection\fR must be in or out and specifies which direction the policy needs to be applied, either on inbound or outbound packets\&. When the discard policy is selected, packets will be dropped if they match the policy\&. .RE .PP \fIdirection\fR entrust .RS 4 entrust means to consult the security policy database (SPD) in the kernel, as controlled by \fBsetkey\fR(8)\&. .RE .PP \fIdirection\fR bypass .RS 4 A direction of bypass indicates that IPsec processing should not occur and that the packet will be transmitted in clear\&. The bypass option is only available to privileged sockets\&. .RE .PP \fIdirection\fR \fI \fR ipsec \fIrequest\fR \fI\&.\&.\fR \fI \fR .RS 4 A direction of ipsec means that matching packets are processed by IPsec\&. ipsec can be followed by one or more \fIrequest\fR strings, each formatted as: .PP \fIprotocol\fR \fI \fR / \fImode\fR \fI \fR / \fIsrc\fR \fI \fR \- \fIdst\fR \fI \fR \fI/level\fR \fI \fR .RS 4 The \fIprotocol\fR is one of: ah, esp or ipcomp indicating Authentication Header, Encapsulating Security Protocol or IP Compression protocol is used\&. .sp The \fImode\fR is either transport or tunnel the meanings of both modes are described in \fBipsec\fR(4)\&. .sp The \fIsrc\fR and \fIdst\fR specify the IP address, either v4 or v6, of the source and destination systems\&. The \fIsrc\fR always stands for the \(lqsending node\(rq and \fIdst\fR always stands for the \(lqreceiving node\(rq\&. When \fIdirection\fR is in, \fIdst\fR is this local node and \fIsrc\fR is the remote node or peer\&. If \fImode\fR is transport, both \fIsrc\fR and \fIdst\fR can be omitted\&. .sp The \fIlevel\fR must be set to one of the following: default, use, require or unique\&. default means that the kernel should consult the default security policies as defined by a set of \fBsysctl\fR(8), variables\&. The relevant \fBsysctl\fR(8) variables are described in \fBipsec\fR(4)\&. .sp When use is selected a relevant security association (SA) can be used when available but is not necessary\&. If the SA is available then packets will be handled by IPsec, i\&.e\&. encrypted and/or authenticated but if an SA is not available then packets will be transmitted in the clear\&. The use option is not recommended because it allows for accidental mis\-configurations where encrypted or authenticated link becomes unencrypted or unauthenticated, the require keyword is recommended instead of use where possible\&. Using the require keyword means that a relevant SA is required, and that the kernel must perform IPsec processing on all matching packets\&. .sp The unique keyword has the same effect as require, but adds the restriction that the SA for outbound traffic is used only for this policy\&. You may need the identifier in order to relate the policy and the SA when you define the SA by manual keying using \fBsetkey\fR(8)\&. Put the decimal number as the identifier after the unique keyword in this way: unique : number, where number must be between 1 and 32767\&. .sp If the \fIrequest\fR string is kept unambiguous, \fIlevel\fR and the slash prior to \fIlevel\fR can be omitted but you are encouraged to specify them explicitly to avoid unintended behaviors\&. If \fIlevel\fR is omitted, it will be interpreted as default\&. .RE .RE .PP Note that there is a difference between the specification allowed here and in \fBsetkey\fR(8)\&. When specifying security policies with \fBsetkey\fR(8), neither entrust nor bypass are used\&. Refer to \fBsetkey\fR(8) for details\&. .SH "EXAMPLES" .PP Set a policy that all inbound packets are discarded\&. .sp .if n \{\ .RS 4 .\} .nf in discard .fi .if n \{\ .RE .\} .PP All outbound packets are required to be processed by IPsec and transported using ESP\&. .sp .if n \{\ .RS 4 .\} .nf .sp .if n \{\ .RS 4 .\} .nf out ipsec esp/transport//require .fi .if n \{\ .RE .\} .sp .fi .if n \{\ .RE .\} .PP All inbound packets are required to be authenticated using the AH protocol\&. .sp .if n \{\ .RS 4 .\} .nf .sp .if n \{\ .RS 4 .\} .nf in ipsec ah/transport//require .fi .if n \{\ .RE .\} .sp .fi .if n \{\ .RE .\} .PP Tunnel packets outbound through the endpoints at 10\&.1\&.1\&.2 and 10\&.1\&.1\&.1\&. .sp .if n \{\ .RS 4 .\} .nf out ipsec esp/tunnel/10\&.1\&.1\&.2\-10\&.1\&.1\&.1/require .fi .if n \{\ .RE .\} .SH "RETURN VALUES" .PP The ipsec_set_policy(); function returns a pointer to the allocated buffer containing a the policy specification if successful; otherwise a NULL pointer is returned\&. .PP The ipsec_get_policylen(); function returns a positive value, indicating the buffer size, on success, and a negative value on error\&. .PP The ipsec_dump_policy(); function returns a pointer to a dynamically allocated region containing a human readable security policy on success, and \fBNULL\fR on error\&. .SH "SEE ALSO" .PP \fBipsec_strerror\fR(3), \fBipsec\fR(4), \fBsetkey\fR(8) .SH "HISTORY" .PP These functions first appeared in WIDE/KAME IPv6 protocol stack kit\&. .PP IPv6 and IPsec support based on the KAME Project (http://www\&.kame\&.net/) stack was initially integrated into FreeBSD 4\&.0(TM) libreswan-3.32/lib/libbsdpfkey/ipsec_set_policy.3.xml000066400000000000000000000323621365625662500227410ustar00rootroot00000000000000 IPSEC_SET_POLICY 3 ipsec_set_policy create an IPsec policy structure from a human readable string #include <netinet6/ipsec.h> char *ipsec_set_policy char * policy int len int ipsec_get_policylen char * buf char *ipsec_dump_policy char * buf char * delim LIBRARY IPsec Policy Control Library (libipsec, -lipsec) DESCRIPTION The ipsec_set_policy(); function generates an IPsec policy specification structure, struct sadb_x_policy and/or struct sadb_x_ipsecrequest from a human-readable policy specification. The policy specification must be given as a C string, passed in the policy argument and the length of the string, given as len. The ipsec_set_policy(); function returns pointer to a buffer that contains a properly formed IPsec policy specification structure. The buffer is dynamically allocated, and must be freed by using the free3 library function. The ipsec_get_policylen(); function will returns the address of the buffer that is needed when passing the specification structure to the setsockopt2 system call. The ipsec_dump_policy(); function converts an IPsec policy structure into a human readable form. The buf argument points to an IPsec policy structure, struct sadb_x_policy. delim is a delimiter string, which is usually a blank character. If you set delim to NULL, a single white space is assumed. The ipsec_dump_policy(); function returns a pointer to dynamically allocated string. It is the caller's responsibility to free the returned pointer using the free3 library call. A policy is given in the following way: direction discard The direction must be in or out and specifies which direction the policy needs to be applied, either on inbound or outbound packets. When the discard policy is selected, packets will be dropped if they match the policy. direction entrust entrust means to consult the security policy database (SPD) in the kernel, as controlled by setkey8. direction bypass A direction of bypass indicates that IPsec processing should not occur and that the packet will be transmitted in clear. The bypass option is only available to privileged sockets. direction ipsec request .. A direction of ipsec means that matching packets are processed by IPsec. ipsec can be followed by one or more request strings, each formatted as: protocol / mode / src - dst /level The protocol is one of: ah, esp or ipcomp indicating Authentication Header, Encapsulating Security Protocol or IP Compression protocol is used. The mode is either transport or tunnel the meanings of both modes are described in ipsec4. The src and dst specify the IP address, either v4 or v6, of the source and destination systems. The src always stands for the “sending node” and dst always stands for the “receiving node”. When direction is in, dst is this local node and src is the remote node or peer. If mode is transport, both src and dst can be omitted. The level must be set to one of the following: default, use, require or unique. default means that the kernel should consult the default security policies as defined by a set of sysctl8, variables. The relevant sysctl8 variables are described in ipsec4. When use is selected a relevant security association (SA) can be used when available but is not necessary. If the SA is available then packets will be handled by IPsec, i.e. encrypted and/or authenticated but if an SA is not available then packets will be transmitted in the clear. The use option is not recommended because it allows for accidental mis-configurations where encrypted or authenticated link becomes unencrypted or unauthenticated, the require keyword is recommended instead of use where possible. Using the require keyword means that a relevant SA is required, and that the kernel must perform IPsec processing on all matching packets. The unique keyword has the same effect as require, but adds the restriction that the SA for outbound traffic is used only for this policy. You may need the identifier in order to relate the policy and the SA when you define the SA by manual keying using setkey8. Put the decimal number as the identifier after the unique keyword in this way: unique : number, where number must be between 1 and 32767. If the request string is kept unambiguous, level and the slash prior to level can be omitted but you are encouraged to specify them explicitly to avoid unintended behaviors. If level is omitted, it will be interpreted as default. Note that there is a difference between the specification allowed here and in setkey8. When specifying security policies with setkey8, neither entrust nor bypass are used. Refer to setkey8 for details. EXAMPLES Set a policy that all inbound packets are discarded. in discard All outbound packets are required to be processed by IPsec and transported using ESP. out ipsec esp/transport//require All inbound packets are required to be authenticated using the AH protocol. in ipsec ah/transport//require Tunnel packets outbound through the endpoints at 10.1.1.2 and 10.1.1.1. out ipsec esp/tunnel/10.1.1.2-10.1.1.1/require RETURN VALUES The ipsec_set_policy(); function returns a pointer to the allocated buffer containing a the policy specification if successful; otherwise a NULL pointer is returned. The ipsec_get_policylen(); function returns a positive value, indicating the buffer size, on success, and a negative value on error. The ipsec_dump_policy(); function returns a pointer to a dynamically allocated region containing a human readable security policy on success, and NULL on error. SEE ALSO ipsec_strerror3, ipsec4, setkey8 HISTORY These functions first appeared in WIDE/KAME IPv6 protocol stack kit. IPv6 and IPsec support based on the KAME Project (http://www.kame.net/) stack was initially integrated into FreeBSD 4.0 libreswan-3.32/lib/libbsdpfkey/ipsec_strerror.3000066400000000000000000000040131365625662500216420ustar00rootroot00000000000000'\" t .\" Title: IPSEC_STRERROR .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.75.2 .\" Date: 02/25/2010 .\" Manual: [FIXME: manual] .\" Source: [FIXME: source] .\" Language: English .\" .TH "IPSEC_STRERROR" "3" "02/25/2010" "[FIXME: source]" "[FIXME: manual]" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" _ipsec_strerror \- error messages for the IPsec policy manipulation library .SH "SYNOPSIS" .sp .ft B .nf #include .fi .ft .HP \w'const\ char\ *ipsec_strerror('u .BI "const char *ipsec_strerror(void);" .SH "DESCRIPTION" .PP #include declares .PP extern int ipsec_errcode; .PP which is used to pass an error code from IPsec policy manipulation library to a user program\&. The ipsec_strerror(); function can be used to obtain the error message string for the error code\&. .PP The array pointed to is not to be modified by the program\&. Since ipsec_strerror(); uses \fBstrerror\fR(3) as an underlying function, calling \fBstrerror\fR(3) after ipsec_strerror(); would overwrite the the return value from ipsec_strerror(); and make it invalid\&. .SH "RETURN VALUES" .PP The ipsec_strerror(); function always returns a pointer to C string\&. The C string must not be overwritten by the caller\&. .SH "SEE ALSO" .PP \fBipsec_set_policy\fR(3) .SH "HISTORY" .PP The ipsec_strerror(); function first appeared in WIDE/KAME IPv6 protocol stack kit\&. .SH "BUGS" .PP The ipsec_strerror(); function will return its result which may be overwritten by subsequent calls\&. .PP \fIipsec_errcode\fR is not thread safe\&. libreswan-3.32/lib/libbsdpfkey/ipsec_strerror.3.xml000066400000000000000000000101751365625662500224470ustar00rootroot00000000000000 IPSEC_STRERROR 3 ipsec_strerror error messages for the IPsec policy manipulation library #include <netinet6/ipsec.h> const char *ipsec_strerror DESCRIPTION #include <netinet6/ipsec.h> declares extern int ipsec_errcode; which is used to pass an error code from IPsec policy manipulation library to a user program. The ipsec_strerror(); function can be used to obtain the error message string for the error code. The array pointed to is not to be modified by the program. Since ipsec_strerror(); uses strerror3 as an underlying function, calling strerror3 after ipsec_strerror(); would overwrite the the return value from ipsec_strerror(); and make it invalid. RETURN VALUES The ipsec_strerror(); function always returns a pointer to C string. The C string must not be overwritten by the caller. SEE ALSO ipsec_set_policy3 HISTORY The ipsec_strerror(); function first appeared in WIDE/KAME IPv6 protocol stack kit. BUGS The ipsec_strerror(); function will return its result which may be overwritten by subsequent calls. ipsec_errcode is not thread safe. libreswan-3.32/lib/libbsdpfkey/ipsec_strerror.c000066400000000000000000000102271365625662500217260ustar00rootroot00000000000000/* $KAME: ipsec_strerror.c,v 1.7 2000/07/30 00:45:12 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. * 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. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #include #include #include #include "ipsec_strerror.h" int __ipsec_errcode; static const char *ipsec_errlist[] = { "Success", /* EIPSEC_NO_ERROR */ "Not supported", /* EIPSEC_NOT_SUPPORTED */ "Invalid argument", /* EIPSEC_INVAL_ARGUMENT */ "Invalid sadb message", /* EIPSEC_INVAL_SADBMSG */ "Invalid version", /* EIPSEC_INVAL_VERSION */ "Invalid security policy", /* EIPSEC_INVAL_POLICY */ "Invalid address specification", /* EIPSEC_INVAL_ADDRESS */ "Invalid ipsec protocol", /* EIPSEC_INVAL_PROTO */ "Invalid ipsec mode", /* EIPSEC_INVAL_MODE */ "Invalid ipsec level", /* EIPSEC_INVAL_LEVEL */ "Invalid SA type", /* EIPSEC_INVAL_SATYPE */ "Invalid message type", /* EIPSEC_INVAL_MSGTYPE */ "Invalid extension type", /* EIPSEC_INVAL_EXTTYPE */ "Invalid algorithm type", /* EIPSEC_INVAL_ALGS */ "Invalid key length", /* EIPSEC_INVAL_KEYLEN */ "Invalid address family", /* EIPSEC_INVAL_FAMILY */ "Invalid prefix length", /* EIPSEC_INVAL_PREFIXLEN */ "Invalid direciton", /* EIPSEC_INVAL_DIR */ "SPI range violation", /* EIPSEC_INVAL_SPI */ "No protocol specified", /* EIPSEC_NO_PROTO */ "No algorithm specified", /* EIPSEC_NO_ALGS */ "No buffers available", /* EIPSEC_NO_BUFS */ "Must get supported algorithms list first", /* EIPSEC_DO_GET_SUPP_LIST */ "Protocol mismatch", /* EIPSEC_PROTO_MISMATCH */ "Family mismatch", /* EIPSEC_FAMILY_MISMATCH */ "Too few arguments", /* EIPSEC_FEW_ARGUMENTS */ NULL, /* EIPSEC_SYSTEM_ERROR */ "Unknown error", /* EIPSEC_MAX */ }; const char *ipsec_strerror(void) { if (__ipsec_errcode < 0 || __ipsec_errcode > EIPSEC_MAX) __ipsec_errcode = EIPSEC_MAX; return ipsec_errlist[__ipsec_errcode]; } void __ipsec_set_strerror(const char *str) { __ipsec_errcode = EIPSEC_SYSTEM_ERROR; ipsec_errlist[EIPSEC_SYSTEM_ERROR] = str; } libreswan-3.32/lib/libbsdpfkey/ipsec_strerror.h000066400000000000000000000067121365625662500217370ustar00rootroot00000000000000/* $FreeBSD$ */ /* $KAME: ipsec_strerror.h,v 1.8 2000/07/30 00:45:12 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. * 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. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ extern int __ipsec_errcode; extern void __ipsec_set_strerror(const char *); #define EIPSEC_NO_ERROR 0 /*success*/ #define EIPSEC_NOT_SUPPORTED 1 /*not supported*/ #define EIPSEC_INVAL_ARGUMENT 2 /*invalid argument*/ #define EIPSEC_INVAL_SADBMSG 3 /*invalid sadb message*/ #define EIPSEC_INVAL_VERSION 4 /*invalid version*/ #define EIPSEC_INVAL_POLICY 5 /*invalid security policy*/ #define EIPSEC_INVAL_ADDRESS 6 /*invalid address specification*/ #define EIPSEC_INVAL_PROTO 7 /*invalid ipsec protocol*/ #define EIPSEC_INVAL_MODE 8 /*Invalid ipsec mode*/ #define EIPSEC_INVAL_LEVEL 9 /*invalid ipsec level*/ #define EIPSEC_INVAL_SATYPE 10 /*invalid SA type*/ #define EIPSEC_INVAL_MSGTYPE 11 /*invalid message type*/ #define EIPSEC_INVAL_EXTTYPE 12 /*invalid extension type*/ #define EIPSEC_INVAL_ALGS 13 /*Invalid algorithm type*/ #define EIPSEC_INVAL_KEYLEN 14 /*invalid key length*/ #define EIPSEC_INVAL_FAMILY 15 /*invalid address family*/ #define EIPSEC_INVAL_PREFIXLEN 16 /*SPI range violation*/ #define EIPSEC_INVAL_DIR 17 /*Invalid direciton*/ #define EIPSEC_INVAL_SPI 18 /*invalid prefixlen*/ #define EIPSEC_NO_PROTO 19 /*no protocol specified*/ #define EIPSEC_NO_ALGS 20 /*No algorithm specified*/ #define EIPSEC_NO_BUFS 21 /*no buffers available*/ #define EIPSEC_DO_GET_SUPP_LIST 22 /*must get supported algorithm first*/ #define EIPSEC_PROTO_MISMATCH 23 /*protocol mismatch*/ #define EIPSEC_FAMILY_MISMATCH 24 /*family mismatch*/ #define EIPSEC_FEW_ARGUMENTS 25 /*Too few arguments*/ #define EIPSEC_SYSTEM_ERROR 26 /*system error*/ #define EIPSEC_MAX 27 /*unknown error*/ libreswan-3.32/lib/libbsdpfkey/pfkey.c000066400000000000000000001353531365625662500200070ustar00rootroot00000000000000/* $KAME: pfkey.c,v 1.46 2003/08/26 03:37:06 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. * 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. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "lswlog.h" #include "reqid.h" #include "ipsec_strerror.h" #include "libbsdkame/libpfkey.h" #define CALLOC(size, cast) (cast)calloc(1, (size)) #define PFKEY_DEBUG(args...) DBGF(DBG_KERNEL, args) static int findsupportedmap(int); static int setsupportedmap(const struct sadb_supported *sup, int properlen); static struct sadb_alg *findsupportedalg(unsigned, unsigned); static int pfkey_send_x2(int, unsigned, unsigned, unsigned, struct sockaddr *, struct sockaddr *, uint32_t); static int pfkey_send_x3(int, unsigned, unsigned); static int pfkey_send_x4(int, unsigned, const struct sockaddr *, unsigned, const struct sockaddr *, unsigned, unsigned, uint64_t, uint64_t, char *, int, uint32_t); static int pfkey_send_x5(int, unsigned, uint32_t); static caddr_t pfkey_setsadbmsg(caddr_t, caddr_t, unsigned, unsigned, unsigned, uint32_t, pid_t); static caddr_t pfkey_setsadbsa(caddr_t, caddr_t, uint32_t, unsigned, unsigned, unsigned, uint32_t); static caddr_t pfkey_setsadbaddr(caddr_t, caddr_t, unsigned, const struct sockaddr *, unsigned, unsigned); static caddr_t pfkey_setsadbkey(caddr_t, caddr_t, unsigned, caddr_t, unsigned); static caddr_t pfkey_setsadblifetime(caddr_t, caddr_t, unsigned, uint32_t, uint32_t, uint32_t, uint32_t); static caddr_t pfkey_setsadbxsa2(caddr_t, caddr_t, uint32_t, uint32_t); #undef PFKEY_EXTLEN #define PFKEY_EXTLEN(msg) \ PFKEY_UNUNIT64(((const struct sadb_ext *)(msg))->sadb_ext_len) /* * make and search supported algorithm structure. */ static struct sadb_supported *ipsec_supported[] = { NULL, NULL, NULL, NULL }; static int supported_map[] = { SADB_SATYPE_AH, SADB_SATYPE_ESP, SADB_X_SATYPE_IPCOMP, SADB_X_SATYPE_TCPSIGNATURE }; static int findsupportedmap(satype) int satype; { for (unsigned i = 0; i < sizeof(supported_map) / sizeof(supported_map[0]); i++) if (supported_map[i] == satype) return i; return -1; } static struct sadb_alg *findsupportedalg(satype, alg_id) unsigned satype, alg_id; { int algno; caddr_t p; /* validity check */ algno = findsupportedmap(satype); if (algno == -1) { __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; return NULL; } if (ipsec_supported[algno] == NULL) { __ipsec_errcode = EIPSEC_DO_GET_SUPP_LIST; return NULL; } ssize_t tlen = ipsec_supported[algno]->sadb_supported_len - sizeof(struct sadb_supported); p = (caddr_t)(ipsec_supported[algno] + 1); while (tlen > 0) { if ((unsigned) tlen < sizeof(struct sadb_alg)) { /* invalid format */ break; } if (((struct sadb_alg *)p)->sadb_alg_id == alg_id) return (struct sadb_alg *)p; tlen -= sizeof(struct sadb_alg); p += sizeof(struct sadb_alg); } __ipsec_errcode = EIPSEC_NOT_SUPPORTED; return NULL; } void foreach_supported_alg(void (*algregister)(int satype, int extype, struct sadb_alg *alg)) { int algno; int tlen; int satype, supported_exttype; caddr_t p; for (unsigned i = 0; i < sizeof(supported_map) / sizeof(supported_map[0]); i++) { satype = supported_map[i]; algno = i; if (ipsec_supported[algno] == NULL) continue; tlen = ipsec_supported[algno]->sadb_supported_len - sizeof(struct sadb_supported); supported_exttype = ipsec_supported[algno]->sadb_supported_exttype; p = (caddr_t)(ipsec_supported[algno] + 1); while (tlen > 0) { struct sadb_alg *a = ((struct sadb_alg *)p); if ((unsigned) tlen < sizeof(struct sadb_alg)) { /* invalid format */ break; } algregister(satype, supported_exttype, a); tlen -= sizeof(struct sadb_alg); p += sizeof(struct sadb_alg); } } } static int setsupportedmap(const struct sadb_supported *sup, int properlen) { struct sadb_supported **ipsup; switch (sup->sadb_supported_exttype) { case SADB_EXT_SUPPORTED_AUTH: ipsup = &ipsec_supported[findsupportedmap(SADB_SATYPE_AH)]; break; case SADB_EXT_SUPPORTED_ENCRYPT: ipsup = &ipsec_supported[findsupportedmap(SADB_SATYPE_ESP)]; break; default: __ipsec_errcode = EIPSEC_INVAL_SATYPE; return -1; } if (*ipsup) free(*ipsup); *ipsup = malloc(properlen); DBG_log("recv_register 4 %d = %p ", sup->sadb_supported_exttype, *ipsup); if (!*ipsup) { __ipsec_set_strerror(strerror(errno)); return -1; } memcpy(*ipsup, sup, properlen); (*ipsup)->sadb_supported_len = properlen; return 0; } /* * check key length against algorithm specified. * This function is called with SADB_EXT_SUPPORTED_{AUTH,ENCRYPT} as the * augument, and only calls to ipsec_check_keylen2(); * keylen is the unit of bit. * OUT: * -1: invalid. * 0: valid. */ int ipsec_check_keylen(supported, alg_id, keylen) unsigned supported; unsigned alg_id; unsigned keylen; { int satype; /* validity check */ switch (supported) { case SADB_EXT_SUPPORTED_AUTH: satype = SADB_SATYPE_AH; break; case SADB_EXT_SUPPORTED_ENCRYPT: satype = SADB_SATYPE_ESP; break; default: __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; return -1; } return ipsec_check_keylen2(satype, alg_id, keylen); } /* * check key length against algorithm specified. * satype is one of satype defined at pfkeyv2.h. * keylen is the unit of bit. * OUT: * -1: invalid. * 0: valid. */ int ipsec_check_keylen2(satype, alg_id, keylen) unsigned satype; unsigned alg_id; unsigned keylen; { struct sadb_alg *alg; alg = findsupportedalg(satype, alg_id); if (!alg) return -1; if (keylen < alg->sadb_alg_minbits || keylen > alg->sadb_alg_maxbits) { __ipsec_errcode = EIPSEC_INVAL_KEYLEN; return -1; } __ipsec_errcode = EIPSEC_NO_ERROR; return 0; } /* * get max/min key length against algorithm specified. * satype is one of satype defined at pfkeyv2.h. * keylen is the unit of bit. * OUT: * -1: invalid. * 0: valid. */ int ipsec_get_keylen(supported, alg_id, alg0) unsigned supported, alg_id; struct sadb_alg *alg0; { struct sadb_alg *alg; unsigned satype; /* validity check */ if (!alg0) { __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; return -1; } switch (supported) { case SADB_EXT_SUPPORTED_AUTH: satype = SADB_SATYPE_AH; break; case SADB_EXT_SUPPORTED_ENCRYPT: satype = SADB_SATYPE_ESP; break; default: __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; return -1; } alg = findsupportedalg(satype, alg_id); if (!alg) return -1; memcpy(alg0, alg, sizeof(*alg0)); __ipsec_errcode = EIPSEC_NO_ERROR; return 0; } /* * set the rate for SOFT lifetime against HARD one. * If rate is more than 100 or equal to zero, then set to 100. */ static unsigned soft_lifetime_allocations_rate = PFKEY_SOFT_LIFETIME_RATE; static unsigned soft_lifetime_bytes_rate = PFKEY_SOFT_LIFETIME_RATE; static unsigned soft_lifetime_addtime_rate = PFKEY_SOFT_LIFETIME_RATE; static unsigned soft_lifetime_usetime_rate = PFKEY_SOFT_LIFETIME_RATE; unsigned pfkey_set_softrate(type, rate) unsigned type, rate; { __ipsec_errcode = EIPSEC_NO_ERROR; if (rate > 100 || rate == 0) rate = 100; switch (type) { case SADB_X_LIFETIME_ALLOCATIONS: soft_lifetime_allocations_rate = rate; return 0; case SADB_X_LIFETIME_BYTES: soft_lifetime_bytes_rate = rate; return 0; case SADB_X_LIFETIME_ADDTIME: soft_lifetime_addtime_rate = rate; return 0; case SADB_X_LIFETIME_USETIME: soft_lifetime_usetime_rate = rate; return 0; } __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; return 1; } /* * get current rate for SOFT lifetime against HARD one. * ATTENTION: ~0 is returned if invalid type was passed. */ unsigned pfkey_get_softrate(type) unsigned type; { switch (type) { case SADB_X_LIFETIME_ALLOCATIONS: return soft_lifetime_allocations_rate; case SADB_X_LIFETIME_BYTES: return soft_lifetime_bytes_rate; case SADB_X_LIFETIME_ADDTIME: return soft_lifetime_addtime_rate; case SADB_X_LIFETIME_USETIME: return soft_lifetime_usetime_rate; } return ~0; } /* * sending SADB_GETSPI message to the kernel. * OUT: * positive: success and return length sent. * -1 : error occurred, and set errno. */ int pfkey_send_getspi( int so, unsigned satype, unsigned mode, struct sockaddr *src, struct sockaddr *dst, uint32_t min, uint32_t max, reqid_t reqid, uint32_t seq) { struct sadb_msg *newmsg; caddr_t ep; int len; int need_spirange = 0; caddr_t p; int plen; /* validity check */ if (src == NULL || dst == NULL) { __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; return -1; } if (src->sa_family != dst->sa_family) { __ipsec_errcode = EIPSEC_FAMILY_MISMATCH; return -1; } if (min > max || (min > 0 && min <= 255)) { __ipsec_errcode = EIPSEC_INVAL_SPI; return -1; } switch (src->sa_family) { case AF_INET: plen = sizeof(struct in_addr) << 3; break; case AF_INET6: plen = sizeof(struct in6_addr) << 3; break; default: __ipsec_errcode = EIPSEC_INVAL_FAMILY; return -1; } /* create new sadb_msg to send. */ len = sizeof(struct sadb_msg) + sizeof(struct sadb_x_sa2) + sizeof(struct sadb_address) + PFKEY_ALIGN8(src->sa_len) + sizeof(struct sadb_address) + PFKEY_ALIGN8(dst->sa_len); if (min > (uint32_t)255 && max < ~(uint32_t)0) { need_spirange++; len += sizeof(struct sadb_spirange); } if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) { __ipsec_set_strerror(strerror(errno)); return -1; } ep = ((caddr_t)newmsg) + len; p = pfkey_setsadbmsg((caddr_t)newmsg, ep, SADB_GETSPI, len, satype, seq, getpid()); if (!p) { free(newmsg); return -1; } p = pfkey_setsadbxsa2(p, ep, mode, reqid); if (!p) { free(newmsg); return -1; } /* set sadb_address for source */ p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, plen, IPSEC_ULPROTO_ANY); if (!p) { free(newmsg); return -1; } /* set sadb_address for destination */ p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, plen, IPSEC_ULPROTO_ANY); if (!p) { free(newmsg); return -1; } /* processing spi range */ if (need_spirange) { struct sadb_spirange spirange; if (p + sizeof(spirange) > ep) { free(newmsg); return -1; } zero(&spirange); /* no pointer fields */ spirange.sadb_spirange_len = PFKEY_UNIT64(sizeof(spirange)); spirange.sadb_spirange_exttype = SADB_EXT_SPIRANGE; spirange.sadb_spirange_min = min; spirange.sadb_spirange_max = max; memcpy(p, &spirange, sizeof(spirange)); p += sizeof(spirange); } if (p != ep) { free(newmsg); return -1; } /* send message */ len = pfkey_send(so, newmsg, len); free(newmsg); if (len < 0) return -1; __ipsec_errcode = EIPSEC_NO_ERROR; return len; } /* * sending SADB_UPDATE message to the kernel. * The length of key material is a_keylen + e_keylen. * OUT: * positive: success and return length sent. * -1 : error occurred, and set errno. */ int pfkey_send_update( int so, unsigned satype, unsigned mode, struct sockaddr *src, struct sockaddr *dst, uint32_t spi, reqid_t reqid, unsigned wsize, caddr_t keymat, unsigned e_type, unsigned e_keylen, unsigned a_type, unsigned a_keylen, unsigned flags, uint32_t l_alloc, uint64_t l_bytes, uint64_t l_addtime, uint64_t l_usetime, uint32_t seq) { int len; if ((len = pfkey_send_x1(so, SADB_UPDATE, satype, mode, src, dst, spi, reqid, wsize, keymat, e_type, e_keylen, a_type, a_keylen, flags, l_alloc, l_bytes, l_addtime, l_usetime, seq)) < 0) return -1; return len; } /* * sending SADB_ADD message to the kernel. * The length of key material is a_keylen + e_keylen. * OUT: * positive: success and return length sent. * -1 : error occurred, and set errno. */ int pfkey_send_add( int so, unsigned satype, unsigned mode, struct sockaddr *src, struct sockaddr *dst, uint32_t spi, reqid_t reqid, unsigned wsize, caddr_t keymat, unsigned e_type, unsigned e_keylen, unsigned a_type, unsigned a_keylen, unsigned flags, uint32_t l_alloc, uint64_t l_bytes, uint64_t l_addtime, uint64_t l_usetime, uint32_t seq) { int len = pfkey_send_x1(so, SADB_ADD, satype, mode, src, dst, spi, reqid, wsize, keymat, e_type, e_keylen, a_type, a_keylen, flags, l_alloc, l_bytes, l_addtime, l_usetime, seq); if (len < 0) return -1; return len; } /* * sending SADB_DELETE message to the kernel. * OUT: * positive: success and return length sent. * -1 : error occurred, and set errno. */ int pfkey_send_delete(so, satype, mode, src, dst, spi) int so; unsigned satype, mode; struct sockaddr *src, *dst; uint32_t spi; { int len; if ((len = pfkey_send_x2(so, SADB_DELETE, satype, mode, src, dst, spi)) < 0) return -1; return len; } /* * sending SADB_DELETE without spi to the kernel. This is * the "delete all" request (an extension also present in * Solaris). * * OUT: * positive: success and return length sent * -1 : error occurred, and set errno */ int pfkey_send_delete_all(int so, unsigned satype, unsigned mode UNUSED, struct sockaddr *src, struct sockaddr *dst) { struct sadb_msg *newmsg; int len; caddr_t p; int plen; caddr_t ep; /* validity check */ if (src == NULL || dst == NULL) { __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; return -1; } if (src->sa_family != dst->sa_family) { __ipsec_errcode = EIPSEC_FAMILY_MISMATCH; return -1; } switch (src->sa_family) { case AF_INET: plen = sizeof(struct in_addr) << 3; break; case AF_INET6: plen = sizeof(struct in6_addr) << 3; break; default: __ipsec_errcode = EIPSEC_INVAL_FAMILY; return -1; } /* create new sadb_msg to reply. */ len = sizeof(struct sadb_msg) + sizeof(struct sadb_address) + PFKEY_ALIGN8(src->sa_len) + sizeof(struct sadb_address) + PFKEY_ALIGN8(dst->sa_len); if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) { __ipsec_set_strerror(strerror(errno)); return -1; } ep = ((caddr_t)newmsg) + len; p = pfkey_setsadbmsg((caddr_t)newmsg, ep, SADB_DELETE, len, satype, 0, getpid()); if (!p) { free(newmsg); return -1; } p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, plen, IPSEC_ULPROTO_ANY); if (!p) { free(newmsg); return -1; } p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, plen, IPSEC_ULPROTO_ANY); if (!p || p != ep) { free(newmsg); return -1; } /* send message */ len = pfkey_send(so, newmsg, len); free(newmsg); if (len < 0) return -1; __ipsec_errcode = EIPSEC_NO_ERROR; return len; } /* * sending SADB_GET message to the kernel. * OUT: * positive: success and return length sent. * -1 : error occurred, and set errno. */ int pfkey_send_get(so, satype, mode, src, dst, spi) int so; unsigned satype, mode; struct sockaddr *src, *dst; uint32_t spi; { int len; if ((len = pfkey_send_x2(so, SADB_GET, satype, mode, src, dst, spi)) < 0) return -1; return len; } /* * sending SADB_REGISTER message to the kernel. * OUT: * positive: success and return length sent. * -1 : error occurred, and set errno. */ int pfkey_send_register(int so, unsigned satype) { int len; if (satype == PF_UNSPEC) { for (unsigned algno = 0; algno < sizeof(supported_map) / sizeof(supported_map[0]); algno++) { if (ipsec_supported[algno]) { free(ipsec_supported[algno]); ipsec_supported[algno] = NULL; } } } else { int algno = findsupportedmap(satype); if (algno == -1) { __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; return -1; } if (ipsec_supported[algno]) { free(ipsec_supported[algno]); ipsec_supported[algno] = NULL; } } if ((len = pfkey_send_x3(so, SADB_REGISTER, satype)) < 0) return -1; return len; } /* * receiving SADB_REGISTER message from the kernel, and copy buffer for * sadb_supported returned into ipsec_supported. * OUT: * 0: success and return length sent. * -1: error occurred, and set errno. */ int pfkey_recv_register(so) int so; { pid_t pid = getpid(); struct sadb_msg *newmsg; int error = -1; DBG_log("recv_register"); /* receive message */ for (;; ) { if ((newmsg = pfkey_recv(so)) == NULL) return -1; if (newmsg->sadb_msg_type == SADB_REGISTER && (pid_t)newmsg->sadb_msg_pid == pid) break; free(newmsg); } /* check and fix */ newmsg->sadb_msg_len = PFKEY_UNUNIT64(newmsg->sadb_msg_len); error = pfkey_set_supported(newmsg, newmsg->sadb_msg_len); free(newmsg); if (error == 0) __ipsec_errcode = EIPSEC_NO_ERROR; return error; } /* * receiving SADB_REGISTER message from the kernel, and copy buffer for * sadb_supported returned into ipsec_supported. * NOTE: sadb_msg_len must be host order. * IN: * tlen: msg length (for checking) * OUT: * 0: success and return length sent. * -1: error occurred, and set errno. */ int pfkey_set_supported(const struct sadb_msg *msg, int tlen) { const struct sadb_supported *sup; const unsigned char *p, *ep; int properlen; DBG_log("recv_register 2"); /* validity */ if (msg->sadb_msg_len != tlen) { __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; return -1; } p = (const unsigned char *)msg; ep = p + tlen; p += sizeof(struct sadb_msg); DBG_log("recv_register 2c"); while (p < ep) { sup = (const struct sadb_supported *)p; if (ep < p + sizeof(*sup) || (unsigned)PFKEY_EXTLEN(sup) < sizeof(*sup) || ep < p + sup->sadb_supported_len) { /* invalid format */ break; } DBG_log("recv_register 2b"); switch (sup->sadb_supported_exttype) { case SADB_EXT_SUPPORTED_AUTH: case SADB_EXT_SUPPORTED_ENCRYPT: break; default: __ipsec_errcode = EIPSEC_INVAL_SATYPE; return -1; } /* fixed length */ properlen = PFKEY_EXTLEN(sup); /* set supported map */ if (setsupportedmap(sup, properlen) != 0) return -1; p += properlen; } if (p != ep) { __ipsec_errcode = EIPSEC_INVAL_SATYPE; return -1; } __ipsec_errcode = EIPSEC_NO_ERROR; return 0; } /* * sending SADB_FLUSH message to the kernel. * OUT: * positive: success and return length sent. * -1 : error occurred, and set errno. */ int pfkey_send_flush(so, satype) int so; unsigned satype; { int len; if ((len = pfkey_send_x3(so, SADB_FLUSH, satype)) < 0) return -1; return len; } /* * sending SADB_DUMP message to the kernel. * OUT: * positive: success and return length sent. * -1 : error occurred, and set errno. */ int pfkey_send_dump(so, satype) int so; unsigned satype; { int len; if ((len = pfkey_send_x3(so, SADB_DUMP, satype)) < 0) return -1; return len; } /* * sending SADB_X_PROMISC message to the kernel. * NOTE that this function handles promisc mode toggle only. * IN: * flag: set promisc off if zero, set promisc on if non-zero. * OUT: * positive: success and return length sent. * -1: error occurred, and set errno. * 0: error occurred, and set errno. * others: a pointer to new allocated buffer in which supported * algorithms is. */ int pfkey_send_promisc_toggle(so, flag) int so; int flag; { int len; if ((len = pfkey_send_x3(so, SADB_X_PROMISC, (flag ? 1 : 0))) < 0) return -1; return len; } /* * sending SADB_X_SPDADD message to the kernel. * OUT: * positive: success and return length sent. * -1 : error occurred, and set errno. */ int pfkey_send_spdadd(so, src, prefs, dst, prefd, proto, policy, policylen, seq) int so; const struct sockaddr *src, *dst; unsigned prefs, prefd, proto; caddr_t policy; int policylen; uint32_t seq; { int len; if ((len = pfkey_send_x4(so, SADB_X_SPDADD, src, prefs, dst, prefd, proto, 0, 0, policy, policylen, seq)) < 0) return -1; return len; } /* * sending SADB_X_SPDADD message to the kernel. * OUT: * positive: success and return length sent. * -1 : error occurred, and set errno. */ int pfkey_send_spdadd2(so, src, prefs, dst, prefd, proto, ltime, vtime, policy, policylen, seq) int so; struct sockaddr *src, *dst; unsigned prefs, prefd, proto; uint64_t ltime, vtime; caddr_t policy; int policylen; uint32_t seq; { int len; if ((len = pfkey_send_x4(so, SADB_X_SPDADD, src, prefs, dst, prefd, proto, ltime, vtime, policy, policylen, seq)) < 0) return -1; return len; } /* * sending SADB_X_SPDUPDATE message to the kernel. * OUT: * positive: success and return length sent. * -1 : error occurred, and set errno. */ int pfkey_send_spdupdate(so, src, prefs, dst, prefd, proto, policy, policylen, seq) int so; struct sockaddr *src, *dst; unsigned prefs, prefd, proto; caddr_t policy; int policylen; uint32_t seq; { int len; if ((len = pfkey_send_x4(so, SADB_X_SPDUPDATE, src, prefs, dst, prefd, proto, 0, 0, policy, policylen, seq)) < 0) return -1; return len; } /* * sending SADB_X_SPDUPDATE message to the kernel. * OUT: * positive: success and return length sent. * -1 : error occurred, and set errno. */ int pfkey_send_spdupdate2(so, src, prefs, dst, prefd, proto, ltime, vtime, policy, policylen, seq) int so; struct sockaddr *src, *dst; unsigned prefs, prefd, proto; uint64_t ltime, vtime; caddr_t policy; int policylen; uint32_t seq; { int len; if ((len = pfkey_send_x4(so, SADB_X_SPDUPDATE, src, prefs, dst, prefd, proto, ltime, vtime, policy, policylen, seq)) < 0) return -1; return len; } /* * sending SADB_X_SPDDELETE message to the kernel. * OUT: * positive: success and return length sent. * -1 : error occurred, and set errno. */ int pfkey_send_spddelete(so, src, prefs, dst, prefd, proto, policy, policylen, seq) int so; const struct sockaddr *src, *dst; unsigned prefs, prefd, proto; caddr_t policy; int policylen; uint32_t seq; { int len; if (policylen != sizeof(struct sadb_x_policy)) { __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; return -1; } if ((len = pfkey_send_x4(so, SADB_X_SPDDELETE, src, prefs, dst, prefd, proto, 0, 0, policy, policylen, seq)) < 0) return -1; return len; } /* * sending SADB_X_SPDDELETE message to the kernel. * OUT: * positive: success and return length sent. * -1 : error occurred, and set errno. */ int pfkey_send_spddelete2(so, spid) int so; uint32_t spid; { int len; if ((len = pfkey_send_x5(so, SADB_X_SPDDELETE2, spid)) < 0) return -1; return len; } /* * sending SADB_X_SPDGET message to the kernel. * OUT: * positive: success and return length sent. * -1 : error occurred, and set errno. */ int pfkey_send_spdget(so, spid) int so; uint32_t spid; { int len; if ((len = pfkey_send_x5(so, SADB_X_SPDGET, spid)) < 0) return -1; return len; } /* * sending SADB_X_SPDSETIDX message to the kernel. * OUT: * positive: success and return length sent. * -1 : error occurred, and set errno. */ int pfkey_send_spdsetidx(so, src, prefs, dst, prefd, proto, policy, policylen, seq) int so; struct sockaddr *src, *dst; unsigned prefs, prefd, proto; caddr_t policy; int policylen; uint32_t seq; { int len; if (policylen != sizeof(struct sadb_x_policy)) { __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; return -1; } if ((len = pfkey_send_x4(so, SADB_X_SPDSETIDX, src, prefs, dst, prefd, proto, 0, 0, policy, policylen, seq)) < 0) return -1; return len; } /* * sending SADB_SPDFLUSH message to the kernel. * OUT: * positive: success and return length sent. * -1 : error occurred, and set errno. */ int pfkey_send_spdflush(so) int so; { int len; if ((len = pfkey_send_x3(so, SADB_X_SPDFLUSH, SADB_SATYPE_UNSPEC)) < 0) return -1; return len; } /* * sending SADB_SPDDUMP message to the kernel. * OUT: * positive: success and return length sent. * -1 : error occurred, and set errno. */ int pfkey_send_spddump(so) int so; { int len; if ((len = pfkey_send_x3(so, SADB_X_SPDDUMP, SADB_SATYPE_UNSPEC)) < 0) return -1; return len; } /* sending SADB_ADD or SADB_UPDATE message to the kernel */ int pfkey_send_x1( int so, unsigned type, unsigned satype, unsigned mode, const struct sockaddr *src, const struct sockaddr *dst, uint32_t spi, reqid_t reqid, unsigned wsize, caddr_t keymat, unsigned e_type, unsigned e_keylen, unsigned a_type, unsigned a_keylen, unsigned flags, uint32_t l_alloc, uint32_t l_bytes, uint32_t l_addtime, uint32_t l_usetime, uint32_t seq) { struct sadb_msg *newmsg; int len; caddr_t p; int plen; caddr_t ep; /* validity check */ if (src == NULL || dst == NULL) { __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; return -1; } if (src->sa_family != dst->sa_family) { __ipsec_errcode = EIPSEC_FAMILY_MISMATCH; return -1; } switch (src->sa_family) { case AF_INET: plen = sizeof(struct in_addr) << 3; break; case AF_INET6: plen = sizeof(struct in6_addr) << 3; break; default: __ipsec_errcode = EIPSEC_INVAL_FAMILY; return -1; } switch (satype) { case SADB_SATYPE_ESP: if (e_type == SADB_EALG_NONE) { __ipsec_errcode = EIPSEC_NO_ALGS; return -1; } break; case SADB_SATYPE_AH: if (e_type != SADB_EALG_NONE) { __ipsec_errcode = EIPSEC_INVAL_ALGS; return -1; } if (a_type == SADB_AALG_NONE) { __ipsec_errcode = EIPSEC_NO_ALGS; return -1; } break; case SADB_X_SATYPE_IPCOMP: if (e_type == SADB_X_CALG_NONE) { __ipsec_errcode = EIPSEC_INVAL_ALGS; return -1; } if (a_type != SADB_AALG_NONE) { __ipsec_errcode = EIPSEC_NO_ALGS; return -1; } break; case SADB_X_SATYPE_TCPSIGNATURE: if (e_type != SADB_EALG_NONE) { __ipsec_errcode = EIPSEC_INVAL_ALGS; return -1; } if (a_type != SADB_X_AALG_TCP_MD5) { __ipsec_errcode = EIPSEC_INVAL_ALGS; return -1; } break; default: __ipsec_errcode = EIPSEC_INVAL_SATYPE; return -1; } /* create new sadb_msg to reply. */ len = sizeof(struct sadb_msg) + sizeof(struct sadb_sa) + sizeof(struct sadb_x_sa2) + sizeof(struct sadb_address) + PFKEY_ALIGN8(src->sa_len) + sizeof(struct sadb_address) + PFKEY_ALIGN8(dst->sa_len) + sizeof(struct sadb_lifetime) + sizeof(struct sadb_lifetime); if (e_type != SADB_EALG_NONE) len += (sizeof(struct sadb_key) + PFKEY_ALIGN8(e_keylen)); if (a_type != SADB_AALG_NONE) len += (sizeof(struct sadb_key) + PFKEY_ALIGN8(a_keylen)); if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) { __ipsec_set_strerror(strerror(errno)); return -1; } ep = ((caddr_t)newmsg) + len; p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len, satype, seq, getpid()); if (!p) { free(newmsg); return -1; } p = pfkey_setsadbsa(p, ep, spi, wsize, a_type, e_type, flags); if (!p) { free(newmsg); return -1; } p = pfkey_setsadbxsa2(p, ep, mode, reqid); if (!p) { free(newmsg); return -1; } p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, plen, IPSEC_ULPROTO_ANY); if (!p) { free(newmsg); return -1; } p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, plen, IPSEC_ULPROTO_ANY); if (!p) { free(newmsg); return -1; } if (e_type != SADB_EALG_NONE) { p = pfkey_setsadbkey(p, ep, SADB_EXT_KEY_ENCRYPT, keymat, e_keylen); if (!p) { free(newmsg); return -1; } } if (a_type != SADB_AALG_NONE) { p = pfkey_setsadbkey(p, ep, SADB_EXT_KEY_AUTH, keymat + e_keylen, a_keylen); if (!p) { free(newmsg); return -1; } } /* set sadb_lifetime for destination */ p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_HARD, l_alloc, l_bytes, l_addtime, l_usetime); if (!p) { free(newmsg); return -1; } p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_SOFT, l_alloc, l_bytes, l_addtime, l_usetime); if (!p || p != ep) { free(newmsg); return -1; } /* send message */ len = pfkey_send(so, newmsg, len); free(newmsg); if (len < 0) return -1; __ipsec_errcode = EIPSEC_NO_ERROR; return len; } /* sending SADB_DELETE or SADB_GET message to the kernel */ static int pfkey_send_x2(int so, unsigned type, unsigned satype, unsigned mode UNUSED, struct sockaddr *src, struct sockaddr *dst, uint32_t spi) { struct sadb_msg *newmsg; int len; caddr_t p; int plen; caddr_t ep; /* validity check */ if (src == NULL || dst == NULL) { __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; return -1; } if (src->sa_family != dst->sa_family) { __ipsec_errcode = EIPSEC_FAMILY_MISMATCH; return -1; } switch (src->sa_family) { case AF_INET: plen = sizeof(struct in_addr) << 3; break; case AF_INET6: plen = sizeof(struct in6_addr) << 3; break; default: __ipsec_errcode = EIPSEC_INVAL_FAMILY; return -1; } /* create new sadb_msg to reply. */ len = sizeof(struct sadb_msg) + sizeof(struct sadb_sa) + sizeof(struct sadb_address) + PFKEY_ALIGN8(src->sa_len) + sizeof(struct sadb_address) + PFKEY_ALIGN8(dst->sa_len); if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) { __ipsec_set_strerror(strerror(errno)); return -1; } ep = ((caddr_t)newmsg) + len; p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len, satype, 0, getpid()); if (!p) { free(newmsg); return -1; } p = pfkey_setsadbsa(p, ep, spi, 0, 0, 0, 0); if (!p) { free(newmsg); return -1; } p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, plen, IPSEC_ULPROTO_ANY); if (!p) { free(newmsg); return -1; } p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, plen, IPSEC_ULPROTO_ANY); if (!p || p != ep) { free(newmsg); return -1; } /* send message */ len = pfkey_send(so, newmsg, len); free(newmsg); if (len < 0) return -1; __ipsec_errcode = EIPSEC_NO_ERROR; return len; } /* * sending SADB_REGISTER, SADB_FLUSH, SADB_DUMP or SADB_X_PROMISC message * to the kernel */ static int pfkey_send_x3(so, type, satype) int so; unsigned type, satype; { struct sadb_msg *newmsg; int len; caddr_t p; caddr_t ep; /* validity check */ switch (type) { case SADB_X_PROMISC: if (satype != 0 && satype != 1) { __ipsec_errcode = EIPSEC_INVAL_SATYPE; return -1; } break; default: switch (satype) { case SADB_SATYPE_UNSPEC: case SADB_SATYPE_AH: case SADB_SATYPE_ESP: case SADB_X_SATYPE_IPCOMP: case SADB_X_SATYPE_TCPSIGNATURE: break; default: __ipsec_errcode = EIPSEC_INVAL_SATYPE; return -1; } } /* create new sadb_msg to send. */ len = sizeof(struct sadb_msg); if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) { __ipsec_set_strerror(strerror(errno)); return -1; } ep = ((caddr_t)newmsg) + len; p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len, satype, 0, getpid()); if (!p || p != ep) { free(newmsg); return -1; } /* send message */ len = pfkey_send(so, newmsg, len); free(newmsg); if (len < 0) return -1; __ipsec_errcode = EIPSEC_NO_ERROR; return len; } /* sending SADB_X_SPDADD message to the kernel */ static int pfkey_send_x4(int so, unsigned type, const struct sockaddr *src, unsigned prefs, const struct sockaddr *dst, unsigned prefd, unsigned proto, uint64_t ltime, uint64_t vtime, char *policy, int policylen, uint32_t seq) { struct sadb_msg *newmsg; int len; caddr_t p; unsigned plen; caddr_t ep; __ipsec_errcode = EIPSEC_NO_ERROR; /* validity check */ if (src == NULL || dst == NULL) { __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; PFKEY_DEBUG( "src=%p dst=%p\n", src, dst); return -1; } if (src->sa_family != dst->sa_family) { __ipsec_errcode = EIPSEC_FAMILY_MISMATCH; return -1; } switch (src->sa_family) { case AF_INET: plen = sizeof(struct in_addr) << 3; break; case AF_INET6: plen = sizeof(struct in6_addr) << 3; break; default: __ipsec_errcode = EIPSEC_INVAL_FAMILY; return -1; } if (prefs > plen || prefd > plen) { __ipsec_errcode = EIPSEC_INVAL_PREFIXLEN; return -1; } /* create new sadb_msg to reply. */ len = sizeof(struct sadb_msg) + sizeof(struct sadb_address) + PFKEY_ALIGN8(src->sa_len) + sizeof(struct sadb_address) + PFKEY_ALIGN8(src->sa_len) + sizeof(struct sadb_lifetime) + policylen; if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) { __ipsec_set_strerror(strerror(errno)); return -1; } ep = ((caddr_t)newmsg) + len; p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len, SADB_SATYPE_UNSPEC, seq, getpid()); if (!p) { PFKEY_DEBUG( "setting sadbmsg\n"); free(newmsg); return -1; } p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, prefs, proto); if (!p) { PFKEY_DEBUG( "setting sadbaddr-src\n"); free(newmsg); return -1; } p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, prefd, proto); if (!p) { PFKEY_DEBUG( "setting sadbaddr-dst\n"); free(newmsg); return -1; } p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_HARD, 0, 0, ltime, vtime); if (!p || p + policylen != ep) { PFKEY_DEBUG( "failed on setting sadblifetime\n"); free(newmsg); return -1; } memcpy(p, policy, policylen); /* send message */ len = pfkey_send(so, newmsg, len); free(newmsg); if (len < 0) { PFKEY_DEBUG( "len = %d\n", len); return -1; } __ipsec_errcode = EIPSEC_NO_ERROR; return len; } /* sending SADB_X_SPDGET or SADB_X_SPDDELETE message to the kernel */ static int pfkey_send_x5(so, type, spid) int so; unsigned type; uint32_t spid; { struct sadb_msg *newmsg; struct sadb_x_policy xpl; int len; caddr_t p; caddr_t ep; /* create new sadb_msg to reply. */ len = sizeof(struct sadb_msg) + sizeof(xpl); if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) { __ipsec_set_strerror(strerror(errno)); return -1; } ep = ((caddr_t)newmsg) + len; p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len, SADB_SATYPE_UNSPEC, 0, getpid()); if (!p) { free(newmsg); return -1; } if (p + sizeof(xpl) != ep) { free(newmsg); return -1; } zero(&xpl); /* no pointer fields */ xpl.sadb_x_policy_len = PFKEY_UNIT64(sizeof(xpl)); xpl.sadb_x_policy_exttype = SADB_X_EXT_POLICY; xpl.sadb_x_policy_id = spid; memcpy(p, &xpl, sizeof(xpl)); /* send message */ len = pfkey_send(so, newmsg, len); free(newmsg); if (len < 0) return -1; __ipsec_errcode = EIPSEC_NO_ERROR; return len; } /* * open a socket. * OUT: * -1: fail. * others : success and return value of socket. */ int pfkey_open(void) { int so; const int bufsiz = 128 * 1024; /*is 128K enough?*/ if ((so = socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) < 0) { __ipsec_set_strerror(strerror(errno)); return -1; } /* * This is a temporary workaround for KAME PR 154. * Don't really care even if it fails. */ (void)setsockopt(so, SOL_SOCKET, SO_SNDBUF, &bufsiz, sizeof(bufsiz)); (void)setsockopt(so, SOL_SOCKET, SO_RCVBUF, &bufsiz, sizeof(bufsiz)); __ipsec_errcode = EIPSEC_NO_ERROR; return so; } /* * close a socket. * OUT: * 0: success. * -1: fail. */ void pfkey_close(so) int so; { (void)close(so); __ipsec_errcode = EIPSEC_NO_ERROR; } /* * receive sadb_msg data, and return pointer to new buffer allocated. * Must free this buffer later. * OUT: * NULL : error occurred. * others : a pointer to sadb_msg structure. * * XXX should be rewritten to pass length explicitly */ struct sadb_msg *pfkey_recv(int so) { struct sadb_msg buf, *newmsg; int reallen; int len; while ((len = recv(so, (caddr_t)&buf, sizeof(buf), MSG_PEEK)) < 0) { #if 0 if (errno == EINTR) continue; #endif __ipsec_set_strerror(strerror(errno)); return NULL; } if ((unsigned) len < sizeof(buf)) { recv(so, (caddr_t)&buf, sizeof(buf), 0); __ipsec_errcode = EIPSEC_MAX; return NULL; } /* read real message */ reallen = PFKEY_UNUNIT64(buf.sadb_msg_len); if ((newmsg = CALLOC(reallen, struct sadb_msg *)) == 0) { __ipsec_set_strerror(strerror(errno)); return NULL; } while ((len = recv(so, (caddr_t)newmsg, reallen, 0)) < 0) { if (errno == EINTR) continue; __ipsec_set_strerror(strerror(errno)); free(newmsg); return NULL; } if (len != reallen) { __ipsec_errcode = EIPSEC_SYSTEM_ERROR; free(newmsg); return NULL; } /* don't trust what the kernel says, validate! */ if (PFKEY_UNUNIT64(newmsg->sadb_msg_len) != len) { __ipsec_errcode = EIPSEC_SYSTEM_ERROR; free(newmsg); return NULL; } __ipsec_errcode = EIPSEC_NO_ERROR; return newmsg; } /* * send message to a socket. * OUT: * others: success and return length sent. * -1 : fail. */ int pfkey_send(so, msg, len) int so; struct sadb_msg *msg; int len; { if ((len = send(so, (caddr_t)msg, len, 0)) < 0) { PFKEY_DEBUG( "send failed len=%d error=%d(%s)\n", len, errno, strerror(errno)); __ipsec_set_strerror(strerror(errno)); return -1; } __ipsec_errcode = EIPSEC_NO_ERROR; return len; } /* * %%% Utilities * NOTE: These functions are derived from netkey/key.c in KAME. */ /* * set the pointer to each header in this message buffer. * IN: msg: pointer to message buffer. * mhp: pointer to the buffer initialized like below: * caddr_t mhp[K_SADB_EXT_MAX + 1]; * OUT: -1: invalid. * 0: valid. * * XXX should be rewritten to obtain length explicitly */ int pfkey_align(msg, mhp) struct sadb_msg *msg; caddr_t *mhp; { struct sadb_ext *ext; int i; caddr_t p; caddr_t ep; /* XXX should be passed from upper layer */ /* validity check */ if (msg == NULL || mhp == NULL) { __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; return -1; } /* initialize */ for (i = 0; i < K_SADB_EXT_MAX + 1; i++) mhp[i] = NULL; mhp[0] = (caddr_t)msg; /* initialize */ p = (caddr_t) msg; ep = p + PFKEY_UNUNIT64(msg->sadb_msg_len); /* skip base header */ p += sizeof(struct sadb_msg); while (p < ep) { ext = (struct sadb_ext *)p; if (ep < p + sizeof(*ext) || (unsigned) PFKEY_EXTLEN(ext) < sizeof(*ext) || ep < p + PFKEY_EXTLEN(ext)) { /* invalid format */ break; } /* duplicate check */ /* XXX Are there duplication either KEY_AUTH or KEY_ENCRYPT ?*/ if (mhp[ext->sadb_ext_type] != NULL) { __ipsec_errcode = EIPSEC_INVAL_EXTTYPE; return -1; } /* set pointer */ switch (ext->sadb_ext_type) { case SADB_EXT_SA: case SADB_EXT_LIFETIME_CURRENT: case SADB_EXT_LIFETIME_HARD: case SADB_EXT_LIFETIME_SOFT: case SADB_EXT_ADDRESS_SRC: case SADB_EXT_ADDRESS_DST: case SADB_EXT_ADDRESS_PROXY: case SADB_EXT_KEY_AUTH: /* XXX should to be check weak keys. */ case SADB_EXT_KEY_ENCRYPT: /* XXX should to be check weak keys. */ case SADB_EXT_IDENTITY_SRC: case SADB_EXT_IDENTITY_DST: case SADB_EXT_SENSITIVITY: case SADB_EXT_PROPOSAL: case SADB_EXT_SUPPORTED_AUTH: case SADB_EXT_SUPPORTED_ENCRYPT: case SADB_EXT_SPIRANGE: case SADB_X_EXT_POLICY: case SADB_X_EXT_SA2: mhp[ext->sadb_ext_type] = (caddr_t)ext; break; default: __ipsec_errcode = EIPSEC_INVAL_EXTTYPE; return -1; } p += PFKEY_EXTLEN(ext); } if (p != ep) { __ipsec_errcode = EIPSEC_INVAL_SADBMSG; return -1; } __ipsec_errcode = EIPSEC_NO_ERROR; return 0; } /* * check basic usage for sadb_msg, * NOTE: This routine is derived from netkey/key.c in KAME. * IN: msg: pointer to message buffer. * mhp: pointer to the buffer initialized like below: * * caddr_t mhp[K_SADB_EXT_MAX + 1]; * * OUT: -1: invalid. * 0: valid. */ int pfkey_check(mhp) caddr_t * mhp; { struct sadb_msg *msg; /* validity check */ if (mhp == NULL || mhp[0] == NULL) { __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; return -1; } msg = (struct sadb_msg *)mhp[0]; /* check version */ if (msg->sadb_msg_version != PF_KEY_V2) { __ipsec_errcode = EIPSEC_INVAL_VERSION; return -1; } /* check type */ if (msg->sadb_msg_type > SADB_MAX) { __ipsec_errcode = EIPSEC_INVAL_MSGTYPE; return -1; } /* check SA type */ switch (msg->sadb_msg_satype) { case SADB_SATYPE_UNSPEC: switch (msg->sadb_msg_type) { case SADB_GETSPI: case SADB_UPDATE: case SADB_ADD: case SADB_DELETE: case SADB_GET: case SADB_ACQUIRE: case SADB_EXPIRE: __ipsec_errcode = EIPSEC_INVAL_SATYPE; return -1; } break; case SADB_SATYPE_ESP: case SADB_SATYPE_AH: case SADB_X_SATYPE_IPCOMP: case SADB_X_SATYPE_TCPSIGNATURE: switch (msg->sadb_msg_type) { case SADB_X_SPDADD: case SADB_X_SPDDELETE: case SADB_X_SPDGET: case SADB_X_SPDDUMP: case SADB_X_SPDFLUSH: __ipsec_errcode = EIPSEC_INVAL_SATYPE; return -1; } break; case SADB_SATYPE_RSVP: case SADB_SATYPE_OSPFV2: case SADB_SATYPE_RIPV2: case SADB_SATYPE_MIP: __ipsec_errcode = EIPSEC_NOT_SUPPORTED; return -1; case 1: /* XXX: What does it do ? */ if (msg->sadb_msg_type == SADB_X_PROMISC) break; /*FALLTHROUGH*/ default: __ipsec_errcode = EIPSEC_INVAL_SATYPE; return -1; } /* check field of upper layer protocol and address family */ if (mhp[SADB_EXT_ADDRESS_SRC] != NULL && mhp[SADB_EXT_ADDRESS_DST] != NULL) { struct sadb_address *src0, *dst0; src0 = (struct sadb_address *)(mhp[SADB_EXT_ADDRESS_SRC]); dst0 = (struct sadb_address *)(mhp[SADB_EXT_ADDRESS_DST]); if (src0->sadb_address_proto != dst0->sadb_address_proto) { __ipsec_errcode = EIPSEC_PROTO_MISMATCH; return -1; } if (PFKEY_ADDR_SADDR(src0)->sa_family != PFKEY_ADDR_SADDR(dst0)->sa_family) { __ipsec_errcode = EIPSEC_FAMILY_MISMATCH; return -1; } switch (PFKEY_ADDR_SADDR(src0)->sa_family) { case AF_INET: case AF_INET6: break; default: __ipsec_errcode = EIPSEC_INVAL_FAMILY; return -1; } /* * prefixlen == 0 is valid because there must be the case * all addresses are matched. */ } __ipsec_errcode = EIPSEC_NO_ERROR; return 0; } /* * set data into sadb_msg. * `buf' must has been allocated sufficiently. */ static caddr_t pfkey_setsadbmsg(buf, lim, type, tlen, satype, seq, pid) caddr_t buf; caddr_t lim; unsigned type, satype; unsigned tlen; uint32_t seq; pid_t pid; { struct sadb_msg *p = (struct sadb_msg *)buf; unsigned len = sizeof(struct sadb_msg); if (buf + len > lim) { PFKEY_DEBUG( "sadbmsg: %p+%d>%p fails\n", buf, len, lim); return NULL; } zero(p); /* no pointer fields */ p->sadb_msg_version = PF_KEY_V2; p->sadb_msg_type = type; p->sadb_msg_errno = 0; p->sadb_msg_satype = satype; p->sadb_msg_len = PFKEY_UNIT64(tlen); p->sadb_msg_reserved = 0; p->sadb_msg_seq = seq; p->sadb_msg_pid = (uint32_t)pid; return buf + len; } /* * copy secasvar data into sadb_address. * `buf' must has been allocated sufficiently. */ static caddr_t pfkey_setsadbsa(buf, lim, spi, wsize, auth, enc, flags) caddr_t buf; caddr_t lim; uint32_t spi, flags; unsigned wsize, auth, enc; { struct sadb_sa *p = (struct sadb_sa *)buf; unsigned len = sizeof(struct sadb_sa); if (buf + len > lim) { PFKEY_DEBUG( "sadbsa: %p+%d>%p fails\n", buf, len, lim); return NULL; } zero(p); /* no pointer fields */ p->sadb_sa_len = PFKEY_UNIT64(len); p->sadb_sa_exttype = SADB_EXT_SA; p->sadb_sa_spi = spi; p->sadb_sa_replay = wsize; p->sadb_sa_state = SADB_SASTATE_LARVAL; p->sadb_sa_auth = auth; p->sadb_sa_encrypt = enc; p->sadb_sa_flags = flags; return buf + len; } /* * set data into sadb_address. * `buf' must has been allocated sufficiently. * prefixlen is in bits. */ static caddr_t pfkey_setsadbaddr(buf, lim, exttype, saddr, prefixlen, ul_proto) caddr_t buf; caddr_t lim; unsigned exttype; const struct sockaddr *saddr; unsigned prefixlen; unsigned ul_proto; { struct sadb_address *p = (struct sadb_address *)buf; unsigned len = sizeof(struct sadb_address) + PFKEY_ALIGN8(saddr->sa_len); if (buf + len > lim) { PFKEY_DEBUG( "sadbaddr: %p+%d>%p fails\n", buf, len, lim); return NULL; } memset(p, 0, len); p->sadb_address_len = PFKEY_UNIT64(len); p->sadb_address_exttype = exttype & 0xffff; p->sadb_address_proto = ul_proto & 0xff; p->sadb_address_prefixlen = prefixlen; p->sadb_address_reserved = 0; memcpy(p + 1, saddr, saddr->sa_len); return buf + len; } /* * set sadb_key structure after clearing buffer with zero. * OUT: the pointer of buf + len. */ static caddr_t pfkey_setsadbkey(buf, lim, type, key, keylen) caddr_t buf; caddr_t lim; caddr_t key; unsigned type, keylen; { struct sadb_key *p = (struct sadb_key *)buf; unsigned len = sizeof(struct sadb_key) + PFKEY_ALIGN8(keylen); if (buf + len > lim) { PFKEY_DEBUG( "sadbkey: %p+%d>%p fails\n", buf, len, lim); return NULL; } memset(p, 0, len); p->sadb_key_len = PFKEY_UNIT64(len); p->sadb_key_exttype = type; p->sadb_key_bits = keylen << 3; p->sadb_key_reserved = 0; memcpy(p + 1, key, keylen); return buf + len; } /* * set sadb_lifetime structure after clearing buffer with zero. * OUT: the pointer of buf + len. */ static caddr_t pfkey_setsadblifetime(buf, lim, type, l_alloc, l_bytes, l_addtime, l_usetime) caddr_t buf; caddr_t lim; unsigned type; uint32_t l_alloc, l_bytes, l_addtime, l_usetime; { struct sadb_lifetime *p = (struct sadb_lifetime *)buf; unsigned len = sizeof(struct sadb_lifetime); if (buf + len > lim) { PFKEY_DEBUG( "sadblifetime: %p+%d>%p fails\n", buf, len, lim); return NULL; } zero(p); /* no pointer fields */ p->sadb_lifetime_len = PFKEY_UNIT64(len); p->sadb_lifetime_exttype = type; switch (type) { case SADB_EXT_LIFETIME_SOFT: p->sadb_lifetime_allocations = (l_alloc * soft_lifetime_allocations_rate) / 100; p->sadb_lifetime_bytes = (l_bytes * soft_lifetime_bytes_rate) / 100; p->sadb_lifetime_addtime = (l_addtime * soft_lifetime_addtime_rate) / 100; p->sadb_lifetime_usetime = (l_usetime * soft_lifetime_usetime_rate) / 100; break; case SADB_EXT_LIFETIME_HARD: p->sadb_lifetime_allocations = l_alloc; p->sadb_lifetime_bytes = l_bytes; p->sadb_lifetime_addtime = l_addtime; p->sadb_lifetime_usetime = l_usetime; break; } return buf + len; } /* * copy secasvar data into sadb_address. * `buf' must has been allocated sufficiently. */ static caddr_t pfkey_setsadbxsa2( caddr_t buf, caddr_t lim, uint32_t mode0, reqid_t reqid) { uint8_t mode = mode0 & 0xff; struct sadb_x_sa2 *p = (struct sadb_x_sa2 *)buf; unsigned len = sizeof(struct sadb_x_sa2); if (buf + len > lim) { PFKEY_DEBUG( "sadbxsa2: %p+%d>%p fails\n", buf, len, lim); return NULL; } zero(p); /* no pointer fields */ p->sadb_x_sa2_len = PFKEY_UNIT64(len); p->sadb_x_sa2_exttype = SADB_X_EXT_SA2; p->sadb_x_sa2_mode = mode; p->sadb_x_sa2_reqid = reqid; return buf + len; } libreswan-3.32/lib/libbsdpfkey/pfkey_dump.c000066400000000000000000000373241365625662500210330ustar00rootroot00000000000000/* $KAME: pfkey_dump.c,v 1.45 2003/09/08 10:14:56 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. * 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. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "lswlog.h" #include "ipsec_strerror.h" #include "libbsdkame/libpfkey.h" /* cope with old kame headers - ugly */ #ifndef SADB_X_AALG_MD5 #define SADB_X_AALG_MD5 SADB_AALG_MD5 #endif #ifndef SADB_X_AALG_SHA #define SADB_X_AALG_SHA SADB_AALG_SHA #endif #ifndef SADB_X_AALG_NULL #define SADB_X_AALG_NULL SADB_AALG_NULL #endif #ifndef SADB_X_EALG_BLOWFISHCBC #define SADB_X_EALG_BLOWFISHCBC SADB_EALG_BLOWFISHCBC #endif #ifndef SADB_X_EALG_CAST128CBC #define SADB_X_EALG_CAST128CBC SADB_EALG_CAST128CBC #endif #ifndef SADB_X_EALG_RC5CBC #ifdef SADB_EALG_RC5CBC #define SADB_X_EALG_RC5CBC SADB_EALG_RC5CBC #endif #endif #define GETMSGSTR(str, num) \ do { \ if (sizeof((str)[0]) == 0 \ || num >= sizeof(str) / sizeof((str)[0])) \ printf("%u ", (num)); \ else if ((str)[(num)][0] == '\0') \ printf("%u ", (num)); \ else \ printf("%s ", (str)[(num)]); \ } while (0) #define GETMSGV2S(v2s, num) \ do { \ struct val2str *p; \ for (p = (v2s); p && p->str; p ++) { \ if (p->val == (num)) \ break; \ } \ if (p && p->str) \ printf("%s ", p->str); \ else \ printf("%u ", (num)); \ } while (0) static char *str_ipaddr(struct sockaddr *); static char *str_prefport(unsigned, unsigned, unsigned, unsigned); static void str_upperspec(unsigned, unsigned, unsigned); static char *str_mono_time(monotime_t); static char *str_time(deltime_t); static void str_lifetime_byte(struct sadb_lifetime *, char *); struct val2str { int val; const char *str; }; /* * Must to be re-written about following strings. */ static char *str_satype[] = { "unspec", "unknown", "ah", "esp", "unknown", "rsvp", "ospfv2", "ripv2", "mip", "ipcomp", "policy", "tcp" }; static char *str_mode[] = { "any", "transport", "tunnel", }; static char *str_state[] = { "larval", "mature", "dying", "dead", }; static struct val2str str_alg_auth[] = { { SADB_AALG_NONE, "none", }, { SADB_AALG_MD5HMAC, "hmac-md5", }, { SADB_AALG_SHA1HMAC, "hmac-sha1", }, { SADB_X_AALG_MD5, "md5", }, { SADB_X_AALG_SHA, "sha", }, { SADB_X_AALG_NULL, "null", }, { SADB_X_AALG_TCP_MD5, "tcp-md5", }, #ifdef SADB_X_AALG_SHA2_256 { SADB_X_AALG_SHA2_256, "hmac-sha2-256", }, #endif #ifdef SADB_X_AALG_SHA2_384 { SADB_X_AALG_SHA2_384, "hmac-sha2-384", }, #endif #ifdef SADB_X_AALG_SHA2_512 { SADB_X_AALG_SHA2_512, "hmac-sha2-512", }, #endif #ifdef SADB_X_AALG_RIPEMD160HMAC { SADB_X_AALG_RIPEMD160HMAC, "hmac-ripemd160", }, #endif #ifdef SADB_X_AALG_AES_XCBC_MAC { SADB_X_AALG_AES_XCBC_MAC, "aes-xcbc-mac", }, #endif { -1, NULL, }, }; static struct val2str str_alg_enc[] = { { SADB_EALG_NONE, "none", }, { SADB_EALG_DESCBC, "des-cbc", }, { SADB_EALG_3DESCBC, "3des-cbc", }, { SADB_EALG_NULL, "null", }, #ifdef SADB_X_EALG_RC5CBC { SADB_X_EALG_RC5CBC, "rc5-cbc", }, #endif { SADB_X_EALG_CAST128CBC, "cast128-cbc", }, { SADB_X_EALG_BLOWFISHCBC, "blowfish-cbc", }, #ifdef SADB_X_EALG_RIJNDAELCBC { SADB_X_EALG_RIJNDAELCBC, "rijndael-cbc", }, #endif #ifdef SADB_X_EALG_TWOFISHCBC { SADB_X_EALG_TWOFISHCBC, "twofish-cbc", }, #endif #ifdef SADB_X_EALG_AESCTR { SADB_X_EALG_AESCTR, "aes-ctr", }, #endif { -1, NULL, }, }; static struct val2str str_alg_comp[] = { { SADB_X_CALG_NONE, "none", }, { SADB_X_CALG_OUI, "oui", }, { SADB_X_CALG_DEFLATE, "deflate", }, { SADB_X_CALG_LZS, "lzs", }, { -1, NULL, }, }; /* * dump SADB_MSG formatted. For debugging, you should use kdebug_sadb(). */ void pfkey_sadump(m) struct sadb_msg *m; { caddr_t mhp[K_SADB_EXT_MAX + 1]; struct sadb_sa *m_sa; struct sadb_x_sa2 *m_sa2; struct sadb_lifetime *m_lftc, *m_lfth, *m_lfts; struct sadb_address *m_saddr, *m_daddr, *m_paddr; struct sadb_key *m_auth, *m_enc; struct sadb_ident *m_sid, *m_did; struct sadb_sens *m_sens; /* check pfkey message. */ if (pfkey_align(m, mhp)) { printf("%s\n", ipsec_strerror()); return; } if (pfkey_check(mhp)) { printf("%s\n", ipsec_strerror()); return; } m_sa = (struct sadb_sa *)mhp[SADB_EXT_SA]; m_sa2 = (struct sadb_x_sa2 *)mhp[SADB_X_EXT_SA2]; m_lftc = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_CURRENT]; m_lfth = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_HARD]; m_lfts = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_SOFT]; m_saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]; m_daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]; m_paddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_PROXY]; m_auth = (struct sadb_key *)mhp[SADB_EXT_KEY_AUTH]; m_enc = (struct sadb_key *)mhp[SADB_EXT_KEY_ENCRYPT]; m_sid = (struct sadb_ident *)mhp[SADB_EXT_IDENTITY_SRC]; m_did = (struct sadb_ident *)mhp[SADB_EXT_IDENTITY_DST]; m_sens = (struct sadb_sens *)mhp[SADB_EXT_SENSITIVITY]; /* source address */ if (m_saddr == NULL) { printf("no ADDRESS_SRC extension.\n"); return; } printf("%s ", str_ipaddr((struct sockaddr *)(m_saddr + 1))); /* destination address */ if (m_daddr == NULL) { printf("no ADDRESS_DST extension.\n"); return; } printf("%s ", str_ipaddr((struct sockaddr *)(m_daddr + 1))); /* SA type */ if (m_sa == NULL) { printf("no SA extension.\n"); return; } if (m_sa2 == NULL) { printf("no SA2 extension.\n"); return; } printf("\n\t"); GETMSGSTR(str_satype, m->sadb_msg_satype); printf("mode="); GETMSGSTR(str_mode, m_sa2->sadb_x_sa2_mode); printf("spi=%u(0x%08x) reqid=%u(0x%08x)\n", (uint32_t)ntohl(m_sa->sadb_sa_spi), (uint32_t)ntohl(m_sa->sadb_sa_spi), (uint32_t)m_sa2->sadb_x_sa2_reqid, (uint32_t)m_sa2->sadb_x_sa2_reqid); /* encryption key */ if (m->sadb_msg_satype == SADB_X_SATYPE_IPCOMP) { printf("\tC: "); GETMSGV2S(str_alg_comp, m_sa->sadb_sa_encrypt); } else if (m->sadb_msg_satype == SADB_SATYPE_ESP) { if (m_enc != NULL) { printf("\tE: "); GETMSGV2S(str_alg_enc, m_sa->sadb_sa_encrypt); ipsec_hexdump((caddr_t)m_enc + sizeof(*m_enc), m_enc->sadb_key_bits / 8); printf("\n"); } } /* authentication key */ if (m_auth != NULL) { printf("\tA: "); GETMSGV2S(str_alg_auth, m_sa->sadb_sa_auth); ipsec_hexdump((caddr_t)m_auth + sizeof(*m_auth), m_auth->sadb_key_bits / 8); printf("\n"); } /* replay windoe size & flags */ printf("\tseq=0x%08x replay=%u flags=0x%08x ", m_sa2->sadb_x_sa2_sequence, m_sa->sadb_sa_replay, m_sa->sadb_sa_flags); /* state */ printf("state="); GETMSGSTR(str_state, m_sa->sadb_sa_state); printf("\n"); /* lifetime */ if (m_lftc != NULL) { realtime_t nw = realnow(); printf("\tcreated: %s", str_time(m_lftc->sadb_lifetime_addtime)); printf("\tcurrent: %s\n", str_time(nw)); printf("\tdiff: %lu(s)", (u_long)(m_lftc->sadb_lifetime_addtime == 0 ? 0 : (nw - m_lftc->sadb_lifetime_addtime))); printf("\thard: %lu(s)", (u_long)(m_lfth == NULL ? 0 : m_lfth->sadb_lifetime_addtime)); printf("\tsoft: %lu(s)\n", (u_long)(m_lfts == NULL ? 0 : m_lfts->sadb_lifetime_addtime)); printf("\tlast: %s", str_mon_time(m_lftc->sadb_lifetime_usetime)); printf("\thard: %lu(s)", (u_long)(m_lfth == NULL ? 0 : m_lfth->sadb_lifetime_usetime)); printf("\tsoft: %lu(s)\n", (u_long)(m_lfts == NULL ? 0 : m_lfts->sadb_lifetime_usetime)); str_lifetime_byte(m_lftc, "current"); str_lifetime_byte(m_lfth, "hard"); str_lifetime_byte(m_lfts, "soft"); printf("\n"); printf("\tallocated: %lu", (unsigned long)m_lftc->sadb_lifetime_allocations); printf("\thard: %lu", (u_long)(m_lfth == NULL ? 0 : m_lfth->sadb_lifetime_allocations)); printf("\tsoft: %lu\n", (u_long)(m_lfts == NULL ? 0 : m_lfts->sadb_lifetime_allocations)); } printf("\tsadb_seq=%lu pid=%lu ", (u_long)m->sadb_msg_seq, (u_long)m->sadb_msg_pid); /* XXX DEBUG */ printf("refcnt=%u\n", m->sadb_msg_reserved); } void pfkey_spdump(m) struct sadb_msg *m; { char pbuf[NI_MAXSERV]; caddr_t mhp[K_SADB_EXT_MAX + 1]; struct sadb_address *m_saddr, *m_daddr; struct sadb_x_policy *m_xpl; struct sadb_lifetime *m_lftc = NULL, *m_lfth = NULL; struct sockaddr *sa; uint16_t sport = 0, dport = 0; /* check pfkey message. */ if (pfkey_align(m, mhp)) { printf("%s\n", ipsec_strerror()); return; } if (pfkey_check(mhp)) { printf("%s\n", ipsec_strerror()); return; } m_saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]; m_daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]; m_xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY]; m_lftc = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_CURRENT]; m_lfth = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_HARD]; if (m_saddr && m_daddr) { /* source address */ sa = (struct sockaddr *)(m_saddr + 1); switch (sa->sa_family) { case AF_INET: case AF_INET6: if (getnameinfo(sa, sa->sa_len, NULL, 0, pbuf, sizeof(pbuf), NI_NUMERICSERV) != 0) { sport = 0; /*XXX*/ } else { unsigned long u = 0; err_t ugh = ttoulb(pbuf, 0, 0, 0xFFFF, &u); if (ugh != NULL) { printf("source port: %s\n", ugh); return; } sport = u; } printf("%s%s ", str_ipaddr(sa), str_prefport(sa->sa_family, m_saddr->sadb_address_prefixlen, sport, m_saddr->sadb_address_proto)); break; default: printf("unknown-af "); break; } /* destination address */ sa = (struct sockaddr *)(m_daddr + 1); switch (sa->sa_family) { case AF_INET: case AF_INET6: if (getnameinfo(sa, sa->sa_len, NULL, 0, pbuf, sizeof(pbuf), NI_NUMERICSERV) != 0) { dport = 0; /*XXX*/ } else { unsigned long u = 0; err_t ugh = ttoulb(pbuf, 0, 0, 0xFFFF, &u); if (ugh != NULL) { printf("destination port: %s\n", ugh); return; } dport = u; } printf("%s%s ", str_ipaddr(sa), str_prefport(sa->sa_family, m_daddr->sadb_address_prefixlen, dport, m_saddr->sadb_address_proto)); break; default: printf("unknown-af "); break; } /* upper layer protocol */ if (m_saddr->sadb_address_proto != m_daddr->sadb_address_proto) { printf("upper layer protocol mismatched.\n"); return; } str_upperspec(m_saddr->sadb_address_proto, sport, dport); } else { printf("(no selector, probably per-socket policy) "); } /* policy */ { char *d_xpl; if (m_xpl == NULL) { printf("no X_POLICY extension.\n"); return; } d_xpl = ipsec_dump_policy((char *)m_xpl, "\n\t"); /* dump SPD */ printf("\n\t%s\n", d_xpl); free(d_xpl); } /* lifetime */ if (m_lftc != NULL) { printf("\tcreated: %s ", str_mono_time(m_lftc->sadb_lifetime_addtime)); printf("lastused: %s\n", str_mono_time(m_lftc->sadb_lifetime_usetime)); } if (m_lfth != NULL) { printf("\tlifetime: %lu(s) ", (u_long)m_lfth->sadb_lifetime_addtime); printf("validtime: %lu(s)\n", (u_long)m_lfth->sadb_lifetime_usetime); } printf("\tspid=%ld seq=%ld pid=%ld\n", (u_long)m_xpl->sadb_x_policy_id, (u_long)m->sadb_msg_seq, (u_long)m->sadb_msg_pid); /* XXX TEST */ printf("\trefcnt=%u\n", m->sadb_msg_reserved); } /* * return string for IP address * BEWARE: uses a static buffer. */ static const char *str_ipaddr(sa) struct sockaddr *sa; { static char buf[NI_MAXHOST]; const int niflag = NI_NUMERICHOST; if (sa == NULL) return ""; if (getnameinfo(sa, sa->sa_len, buf, sizeof(buf), NULL, 0, niflag) == 0) return buf; return NULL; } /* * set "/prefix[port number]" to buffer. * BEWARE: result may be in a single static buffer. */ static const char *str_prefport(family, pref, port, ulp) unsigned family, pref, port, ulp; { static char buf[128]; char prefbuf[128]; char portbuf[128]; int plen; switch (family) { case AF_INET: plen = sizeof(struct in_addr) << 3; break; case AF_INET6: plen = sizeof(struct in6_addr) << 3; break; default: return "?"; } if (pref == plen) prefbuf[0] = '\0'; else snprintf(prefbuf, sizeof(prefbuf), "/%u", pref); if (ulp == IPPROTO_ICMPV6) { zero(&portbuf); } else { if (port == IPSEC_PORT_ANY) snprintf(portbuf, sizeof(portbuf), "[%s]", "any"); else snprintf(portbuf, sizeof(portbuf), "[%u]", port); } snprintf(buf, sizeof(buf), "%s%s", prefbuf, portbuf); return buf; } static void str_upperspec(ulp, p1, p2) unsigned ulp, p1, p2; { if (ulp == IPSEC_ULPROTO_ANY) { printf("any"); } else if (ulp == IPPROTO_ICMPV6) { printf("icmp6"); if (!(p1 == IPSEC_PORT_ANY && p2 == IPSEC_PORT_ANY)) printf(" %u,%u", p1, p2); } else { struct protoent *ent; switch (ulp) { case IPPROTO_IPV4: printf("ip4"); break; default: ent = getprotobynumber(ulp); if (ent != NULL) printf("%s", ent->p_name); else printf("%u", ulp); endprotoent(); break; } } } /* * set "Mon Day Time Year" to buffer * NOT RE-ENTRANT because it returns a pointer to a static buffer. */ static const char *str_real_time(realtime_t t) { /* ??? What's 20? What's 128? What's 4? */ static char buf[128]; if (t == 0) { memset(buf, ' ', 20); } else { char *t0 = ctime(&t.real_secs); memcpy(buf, t0 + 4, 20); } buf[20] = '\0'; return buf; } /* * print a monotonic clock time converted to real timebase * uses str_real_time which is NOT RE-ENTRANT */ static const char *str_mono_time(monotime_t t) { return str_real_time(realtimesum(realnow(), diffmonotime(t, mononow()))); } static void str_lifetime_byte(struct sadb_lifetime *x, char *str) { double y; char *unit; int w; if (x == NULL) { printf("\t%s: 0(bytes)", str); return; } #if 0 if ((x->sadb_lifetime_bytes) / 1024 / 1024) { y = (x->sadb_lifetime_bytes) * 1.0 / 1024 / 1024; unit = "M"; w = 1; } else if ((x->sadb_lifetime_bytes) / 1024) { y = (x->sadb_lifetime_bytes) * 1.0 / 1024; unit = "K"; w = 1; } else { y = (x->sadb_lifetime_bytes) * 1.0; unit = ""; w = 0; } #else y = (x->sadb_lifetime_bytes) * 1.0; unit = ""; w = 0; #endif printf("\t%s: %.*f(%sbytes)", str, w, y, unit); } libreswan-3.32/lib/libbsdpfkey/policy_parse.y000066400000000000000000000224431365625662500214030ustar00rootroot00000000000000/* $KAME: policy_parse.y,v 1.14 2003/06/27 03:39:20 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. * 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. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * IN/OUT bound policy configuration take place such below: * in * out * * is one of following: * "discard", "none", "ipsec ", "entrust", "bypass", * * The following requests are accepted as : * * protocol/mode/src-dst/level * protocol/mode/src-dst parsed as protocol/mode/src-dst/default * protocol/mode/src-dst/ parsed as protocol/mode/src-dst/default * protocol/transport parsed as protocol/mode/any-any/default * protocol/transport//level parsed as protocol/mode/any-any/level * * You can concatenate these requests with either ' '(single space) or '\n'. */ %{ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include "ipsec_strerror.h" #define ATOX(c) \ (isdigit(c) ? (c - '0') : (isupper(c) ? (c - 'A' + 10) : (c - 'a' + 10) )) static caddr_t pbuf = NULL; /* sadb_x_policy buffer */ static int tlen = 0; /* total length of pbuf */ static int offset = 0; /* offset of pbuf */ static int p_dir, p_type, p_protocol, p_mode, p_level, p_reqid; static struct sockaddr *p_src = NULL; static struct sockaddr *p_dst = NULL; struct _val; extern void yyerror(char *msg); static struct sockaddr *parse_sockaddr(struct _val *buf); static int rule_check(void); static int init_x_policy(void); static int set_x_request(struct sockaddr *src, struct sockaddr *dst); static int set_sockaddr(struct sockaddr *addr); static void policy_parse_request_init(void); static caddr_t policy_parse(char *msg, int msglen); extern void __policy__strbuffer__init__(char *msg); extern void __policy__strbuffer__free__(void); extern int yyparse(void); extern int yylex(void); extern char *__libipsecyytext; /*XXX*/ %} %union { u_int num; struct _val { int len; char *buf; } val; } %token DIR ACTION PROTOCOL MODE LEVEL LEVEL_SPECIFY %token IPADDRESS %token ME ANY %token SLASH HYPHEN %type DIR ACTION PROTOCOL MODE LEVEL %type IPADDRESS LEVEL_SPECIFY %% policy_spec : DIR ACTION { p_dir = $1; p_type = $2; if (init_x_policy()) return -1; } rules | DIR { p_dir = $1; p_type = 0; /* ignored it by kernel */ if (init_x_policy()) return -1; } ; rules : /*NOTHING*/ | rules rule { if (rule_check() < 0) return -1; if (set_x_request(p_src, p_dst) < 0) return -1; policy_parse_request_init(); } ; rule : protocol SLASH mode SLASH addresses SLASH level | protocol SLASH mode SLASH addresses SLASH | protocol SLASH mode SLASH addresses | protocol SLASH mode SLASH | protocol SLASH mode SLASH SLASH level | protocol SLASH mode | protocol SLASH { __ipsec_errcode = EIPSEC_FEW_ARGUMENTS; return -1; } | protocol { __ipsec_errcode = EIPSEC_FEW_ARGUMENTS; return -1; } ; protocol : PROTOCOL { p_protocol = $1; } ; mode : MODE { p_mode = $1; } ; level : LEVEL { p_level = $1; p_reqid = 0; } | LEVEL_SPECIFY { p_level = IPSEC_LEVEL_UNIQUE; p_reqid = atol($1.buf); /* atol() is good. */ } ; addresses : IPADDRESS { p_src = parse_sockaddr(&$1); if (p_src == NULL) return -1; } HYPHEN IPADDRESS { p_dst = parse_sockaddr(&$4); if (p_dst == NULL) return -1; } | ME HYPHEN ANY { if (p_dir != IPSEC_DIR_OUTBOUND) { __ipsec_errcode = EIPSEC_INVAL_DIR; return -1; } } | ANY HYPHEN ME { if (p_dir != IPSEC_DIR_INBOUND) { __ipsec_errcode = EIPSEC_INVAL_DIR; return -1; } } /* | ME HYPHEN ME */ ; %% void yyerror(msg) char *msg; { fprintf(stderr, "libipsec: %s while parsing \"%s\"\n", msg, __libipsecyytext); } static struct sockaddr * parse_sockaddr(buf) struct _val *buf; { struct addrinfo hints, *res; char *serv = NULL; int error; struct sockaddr *newaddr = NULL; memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_flags = AI_NUMERICHOST; error = getaddrinfo(buf->buf, serv, &hints, &res); if (error != 0) { yyerror("invalid IP address"); __ipsec_set_strerror(gai_strerror(error)); return NULL; } if (res->ai_addr == NULL) { yyerror("invalid IP address"); __ipsec_set_strerror(gai_strerror(error)); return NULL; } newaddr = malloc(res->ai_addr->sa_len); if (newaddr == NULL) { __ipsec_errcode = EIPSEC_NO_BUFS; freeaddrinfo(res); return NULL; } memcpy(newaddr, res->ai_addr, res->ai_addr->sa_len); freeaddrinfo(res); __ipsec_errcode = EIPSEC_NO_ERROR; return newaddr; } static int rule_check(void) { if (p_type == IPSEC_POLICY_IPSEC) { if (p_protocol == IPPROTO_IP) { __ipsec_errcode = EIPSEC_NO_PROTO; return -1; } if (p_mode != IPSEC_MODE_TRANSPORT && p_mode != IPSEC_MODE_TUNNEL) { __ipsec_errcode = EIPSEC_INVAL_MODE; return -1; } if (p_src == NULL && p_dst == NULL) { if (p_mode != IPSEC_MODE_TRANSPORT) { __ipsec_errcode = EIPSEC_INVAL_ADDRESS; return -1; } } else if (p_src->sa_family != p_dst->sa_family) { __ipsec_errcode = EIPSEC_FAMILY_MISMATCH; return -1; } } __ipsec_errcode = EIPSEC_NO_ERROR; return 0; } static int init_x_policy(void) { struct sadb_x_policy *p; tlen = sizeof(struct sadb_x_policy); pbuf = malloc(tlen); if (pbuf == NULL) { __ipsec_errcode = EIPSEC_NO_BUFS; return -1; } memset(pbuf, 0, tlen); p = (struct sadb_x_policy *)pbuf; p->sadb_x_policy_len = 0; /* must update later */ p->sadb_x_policy_exttype = SADB_X_EXT_POLICY; p->sadb_x_policy_type = p_type; p->sadb_x_policy_dir = p_dir; p->sadb_x_policy_id = 0; offset = tlen; __ipsec_errcode = EIPSEC_NO_ERROR; return 0; } static int set_x_request(src, dst) struct sockaddr *src, *dst; { struct sadb_x_ipsecrequest *p; int reqlen; reqlen = sizeof(*p) + (src ? src->sa_len : 0) + (dst ? dst->sa_len : 0); tlen += reqlen; /* increment to total length */ caddr_t t = realloc(pbuf, tlen); if (t == NULL) { __ipsec_errcode = EIPSEC_NO_BUFS; return -1; } pbuf = t; p = (struct sadb_x_ipsecrequest *)&pbuf[offset]; p->sadb_x_ipsecrequest_len = reqlen; p->sadb_x_ipsecrequest_proto = p_protocol; p->sadb_x_ipsecrequest_mode = p_mode; p->sadb_x_ipsecrequest_level = p_level; p->sadb_x_ipsecrequest_reqid = p_reqid; offset += sizeof(*p); if (set_sockaddr(src) || set_sockaddr(dst)) return -1; __ipsec_errcode = EIPSEC_NO_ERROR; return 0; } static int set_sockaddr(addr) struct sockaddr *addr; { if (addr == NULL) { __ipsec_errcode = EIPSEC_NO_ERROR; return 0; } /* tlen has already incremented */ memcpy(&pbuf[offset], addr, addr->sa_len); offset += addr->sa_len; __ipsec_errcode = EIPSEC_NO_ERROR; return 0; } static void policy_parse_request_init(void) { p_protocol = IPPROTO_IP; p_mode = IPSEC_MODE_ANY; p_level = IPSEC_LEVEL_DEFAULT; p_reqid = 0; if (p_src != NULL) { free(p_src); p_src = NULL; } if (p_dst != NULL) { free(p_dst); p_dst = NULL; } } static caddr_t policy_parse(msg, msglen) char *msg; int msglen; { int error; pbuf = NULL; tlen = 0; /* initialize */ p_dir = IPSEC_DIR_INVALID; p_type = IPSEC_POLICY_DISCARD; policy_parse_request_init(); __policy__strbuffer__init__(msg); error = yyparse(); /* it must be set errcode. */ __policy__strbuffer__free__(); if (error) { if (pbuf != NULL) free(pbuf); return NULL; } /* update total length */ ((struct sadb_x_policy *)pbuf)->sadb_x_policy_len = PFKEY_UNIT64(tlen); __ipsec_errcode = EIPSEC_NO_ERROR; return pbuf; } caddr_t ipsec_set_policy(msg, msglen) char *msg; int msglen; { caddr_t policy; policy = policy_parse(msg, msglen); if (policy == NULL) { if (__ipsec_errcode == EIPSEC_NO_ERROR) __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; return NULL; } __ipsec_errcode = EIPSEC_NO_ERROR; return policy; } libreswan-3.32/lib/libbsdpfkey/policy_token.l000066400000000000000000000103211365625662500213640ustar00rootroot00000000000000/* $FreeBSD$ */ /* $KAME: policy_token.l,v 1.13 2003/05/09 05:19:55 sakane Exp $ */ /* * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. * 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. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ %{ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "y.tab.h" #define yylval __libipsecyylval /* XXX */ int yylex(void); %} %option noyywrap %option nounput /* common section */ nl \n ws [ \t]+ digit [0-9] hexdigit [0-9A-Fa-f] special [()+\|\?\*,] dot \. comma \, hyphen \- colon \: slash \/ bcl \{ ecl \} blcl \[ elcl \] percent \% semi \; usec {dot}{digit}{1,6} comment \#.* ccomment "/*" bracketstring \<[^>]*\> quotedstring \"[^"]*\" decstring {digit}+ hexpair {hexdigit}{hexdigit} hexstring 0[xX]{hexdigit}+ octetstring {octet}({dot}{octet})+ ipaddress [a-zA-Z0-9:\._][a-zA-Z0-9:\._]*(%[a-zA-Z0-9]+)? %% in { yylval.num = IPSEC_DIR_INBOUND; return(DIR); } out { yylval.num = IPSEC_DIR_OUTBOUND; return(DIR); } discard { yylval.num = IPSEC_POLICY_DISCARD; return(ACTION); } none { yylval.num = IPSEC_POLICY_NONE; return(ACTION); } ipsec { yylval.num = IPSEC_POLICY_IPSEC; return(ACTION); } bypass { yylval.num = IPSEC_POLICY_BYPASS; return(ACTION); } entrust { yylval.num = IPSEC_POLICY_ENTRUST; return(ACTION); } esp { yylval.num = IPPROTO_ESP; return(PROTOCOL); } ah { yylval.num = IPPROTO_AH; return(PROTOCOL); } ipcomp { yylval.num = IPPROTO_IPCOMP; return(PROTOCOL); } tcp { yylval.num = IPPROTO_TCP; return(PROTOCOL); } transport { yylval.num = IPSEC_MODE_TRANSPORT; return(MODE); } tunnel { yylval.num = IPSEC_MODE_TUNNEL; return(MODE); } me { return(ME); } any { return(ANY); } default { yylval.num = IPSEC_LEVEL_DEFAULT; return(LEVEL); } use { yylval.num = IPSEC_LEVEL_USE; return(LEVEL); } require { yylval.num = IPSEC_LEVEL_REQUIRE; return(LEVEL); } unique{colon}{decstring} { yylval.val.len = strlen(yytext + 7); yylval.val.buf = yytext + 7; return(LEVEL_SPECIFY); } unique { yylval.num = IPSEC_LEVEL_UNIQUE; return(LEVEL); } {slash} { return(SLASH); } {ipaddress} { yylval.val.len = strlen(yytext); yylval.val.buf = yytext; return(IPADDRESS); } {hyphen} { return(HYPHEN); } {ws} { ; } {nl} { ; } %% void __policy__strbuffer__init__(char *); void __policy__strbuffer__free__(void); static YY_BUFFER_STATE strbuffer; void __policy__strbuffer__init__(msg) char *msg; { if (yy_current_buffer) yy_delete_buffer(yy_current_buffer); strbuffer = (YY_BUFFER_STATE)yy_scan_string(msg); yy_switch_to_buffer(strbuffer); } void __policy__strbuffer__free__() { yy_delete_buffer(strbuffer); } libreswan-3.32/lib/libbsdpfkey/test-policy.c000066400000000000000000000200741365625662500211360ustar00rootroot00000000000000/* $KAME: test-policy.c,v 1.16 2003/08/26 03:24:08 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. * 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. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include "libpfkey.h" struct req_t { int result; /* expected result; 0:ok 1:ng */ char *str; } reqs[] = { { 0, "out ipsec" }, { 1, "must_error" }, { 1, "in ipsec must_error" }, { 1, "out ipsec esp/must_error" }, { 1, "out discard" }, { 1, "out none" }, { 0, "in entrust" }, { 0, "out entrust" }, { 1, "out ipsec esp" }, { 0, "in ipsec ah/transport" }, { 1, "in ipsec ah/tunnel" }, { 0, "out ipsec ah/transport/" }, { 1, "out ipsec ah/tunnel/" }, { 0, "in ipsec esp / transport / 10.0.0.1-10.0.0.2" }, { 0, "in ipsec esp/tunnel/::1-::2" }, { 1, "in ipsec esp/tunnel/10.0.0.1-::2" }, { 0, "in ipsec esp/tunnel/::1-::2/require" }, { 0, "out ipsec ah/transport//use" }, { 1, "out ipsec ah/transport esp/use" }, { 1, "in ipsec ah/transport esp/tunnel" }, { 0, "in ipsec ah/transport esp/tunnel/::1-::1" }, { 0, "in ipsec ah / transport esp / tunnel / ::1-::2" }, { 0, "out ipsec ah/transport/::1-::2 esp/tunnel/::3-::4/use ah/transport/::5-::6/require ah/transport/::1-::2 esp/tunnel/::3-::4/use ah/transport/::5-::6/require ah/transport/::1-::2 esp/tunnel/::3-::4/use ah/transport/::5-::6/require " }, { 0, "out ipsec esp/transport/fec0::10-fec0::11/use" }, }; int test1(void); int test1sub1(struct req_t *); int test1sub2(char *, int); int test2(void); int test2sub(int); int main(ac, av) int ac; char **av; { test1(); test2(); exit(0); } int test1(void) { int i; int result; printf("TEST1\n"); for (i = 0; i < sizeof(reqs) / sizeof(reqs[0]); i++) { printf("#%d [%s]\n", i + 1, reqs[i].str); result = test1sub1(&reqs[i]); if (result == 0 && reqs[i].result == 1) warnx("ERROR: expecting failure."); else if (result == 1 && reqs[i].result == 0) warnx("ERROR: expecting success."); } return 0; } int test1sub1(req) struct req_t *req; { char *buf; buf = ipsec_set_policy(req->str, strlen(req->str)); if (buf == NULL) { printf("ipsec_set_policy: %s\n", ipsec_strerror()); return 1; } if (test1sub2(buf, PF_INET) != 0 || test1sub2(buf, PF_INET6) != 0) { free(buf); return 1; } #if 0 kdebug_sadb_x_policy((struct sadb_ext *)buf); #endif free(buf); return 0; } int test1sub2(policy, family) char *policy; int family; { int so; int proto = 0, optname = 0; int len; char getbuf[1024]; switch (family) { case PF_INET: proto = IPPROTO_IP; optname = IP_IPSEC_POLICY; break; case PF_INET6: proto = IPPROTO_IPV6; optname = IPV6_IPSEC_POLICY; break; } if ((so = socket(family, SOCK_DGRAM, 0)) < 0) err(1, "socket"); len = ipsec_get_policylen(policy); #if 0 printf("\tsetlen:%d\n", len); #endif if (setsockopt(so, proto, optname, policy, len) < 0) { printf("fail to set sockopt; %s\n", strerror(errno)); close(so); return 1; } zero(&getbuf); memcpy(getbuf, policy, sizeof(struct sadb_x_policy)); if (getsockopt(so, proto, optname, getbuf, &len) < 0) { printf("fail to get sockopt; %s\n", strerror(errno)); close(so); return 1; } { char *buf = NULL; #if 0 printf("\tgetlen:%d\n", len); #endif if ((buf = ipsec_dump_policy(getbuf, NULL)) == NULL) { printf("%s\n", ipsec_strerror()); close(so); return 1; } #if 0 printf("\t[%s]\n", buf); #endif free(buf); } close(so); return 0; } char addr[] = { 28, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, }; int test2(void) { int so; char *pol1 = "out ipsec"; char *pol2 = "out ipsec ah/transport//use"; char *sp1, *sp2; int splen1, splen2; int spid; struct sadb_msg *m; printf("TEST2\n"); if (getuid() != 0) errx(1, "root privilege required."); sp1 = ipsec_set_policy(pol1, strlen(pol1)); splen1 = ipsec_get_policylen(sp1); sp2 = ipsec_set_policy(pol2, strlen(pol2)); splen2 = ipsec_get_policylen(sp2); if ((so = pfkey_open()) < 0) errx(1, "ERROR: %s", ipsec_strerror()); printf("spdflush()\n"); if (pfkey_send_spdflush(so) < 0) errx(1, "ERROR: %s", ipsec_strerror()); m = pfkey_recv(so); free(m); printf("spdsetidx()\n"); if (pfkey_send_spdsetidx(so, (struct sockaddr *)addr, 128, (struct sockaddr *)addr, 128, 255, sp1, splen1, 0) < 0) errx(1, "ERROR: %s", ipsec_strerror()); m = pfkey_recv(so); free(m); printf("spdupdate()\n"); if (pfkey_send_spdupdate(so, (struct sockaddr *)addr, 128, (struct sockaddr *)addr, 128, 255, sp2, splen2, 0) < 0) errx(1, "ERROR: %s", ipsec_strerror()); m = pfkey_recv(so); free(m); printf("sleep(4)\n"); sleep(4); printf("spddelete()\n"); if (pfkey_send_spddelete(so, (struct sockaddr *)addr, 128, (struct sockaddr *)addr, 128, 255, sp1, splen1, 0) < 0) errx(1, "ERROR: %s", ipsec_strerror()); m = pfkey_recv(so); free(m); printf("spdadd()\n"); if (pfkey_send_spdadd(so, (struct sockaddr *)addr, 128, (struct sockaddr *)addr, 128, 255, sp2, splen2, 0) < 0) errx(1, "ERROR: %s", ipsec_strerror()); spid = test2sub(so); printf("spdget(%u)\n", spid); if (pfkey_send_spdget(so, spid) < 0) errx(1, "ERROR: %s", ipsec_strerror()); m = pfkey_recv(so); free(m); printf("sleep(4)\n"); sleep(4); printf("spddelete2()\n"); if (pfkey_send_spddelete2(so, spid) < 0) errx(1, "ERROR: %s", ipsec_strerror()); m = pfkey_recv(so); free(m); printf("spdadd() with lifetime's 10(s)\n"); if (pfkey_send_spdadd2(so, (struct sockaddr *)addr, 128, (struct sockaddr *)addr, 128, 255, 0, 10, sp2, splen2, 0) < 0) errx(1, "ERROR: %s", ipsec_strerror()); spid = test2sub(so); /* expecting failure */ printf("spdupdate()\n"); if (pfkey_send_spdupdate(so, (struct sockaddr *)addr, 128, (struct sockaddr *)addr, 128, 255, sp2, splen2, 0) == 0) warnx("ERROR: expecting failure."); return 0; } int test2sub(so) int so; { struct sadb_msg *msg; caddr_t mhp[K_SADB_EXT_MAX + 1]; if ((msg = pfkey_recv(so)) == NULL) errx(1, "ERROR: pfkey_recv failure."); if (pfkey_align(msg, mhp) < 0) errx(1, "ERROR: pfkey_align failure."); return ((struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY])-> sadb_x_policy_id; } libreswan-3.32/lib/libcrypto/000077500000000000000000000000001365625662500162245ustar00rootroot00000000000000libreswan-3.32/lib/libcrypto/Makefile000066400000000000000000000017331365625662500176700ustar00rootroot00000000000000# Makefile for pluto/userspace crypto libraries # # Copyright (C) 2005 Michael Richardson # Copyright (C) 2012 Paul Wouters # Copyright (C) 2015 Andrew Cagney # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. ifndef top_srcdir include ../../mk/dirs.mk endif include $(top_srcdir)/Makefile.inc ifeq ($(USE_SERPENT),true) SUBDIRS+=libserpent endif ifeq ($(USE_TWOFISH),true) SUBDIRS+=libtwofish endif include $(top_srcdir)/mk/subdirs.mk libreswan-3.32/lib/libcrypto/README000066400000000000000000000001241365625662500171010ustar00rootroot00000000000000 serpent and twofish are NOT provided by NSS - full implementations are found here. libreswan-3.32/lib/libcrypto/include/000077500000000000000000000000001365625662500176475ustar00rootroot00000000000000libreswan-3.32/lib/libcrypto/include/cbc_generic.h000066400000000000000000000043371365625662500222520ustar00rootroot00000000000000#ifndef _CBC_GENERIC_H #define _CBC_GENERIC_H /* * CBC macro helpers * * Author: JuanJo Ciarlante * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ /* * Heavily inspired in loop_AES */ #define CBC_IMPL_BLK16(name, ctx_type, addr_type, enc_func, dec_func) \ int name(ctx_type * ctx, const u_int8_t * in, u_int8_t * out, int ilen, \ const u_int8_t * iv, int encrypt) { \ int ret = ilen, pos; \ const u_int32_t *iv_i; \ if ((ilen) % 16) \ return 0; \ if (encrypt) { \ pos = 0; \ while (pos < ilen) { \ if (pos == 0) \ iv_i = (const u_int32_t*) iv; \ else \ iv_i = (const u_int32_t*) (out - 16); \ *((u_int32_t *)(&out[ 0])) = iv_i[0] ^ \ *((const u_int32_t \ *)(&in[ 0])); \ *((u_int32_t *)(&out[ 4])) = iv_i[1] ^ \ *((const u_int32_t \ *)(&in[ 4])); \ *((u_int32_t *)(&out[ 8])) = iv_i[2] ^ \ *((const u_int32_t \ *)(&in[ 8])); \ *((u_int32_t *)(&out[12])) = iv_i[3] ^ \ *((const u_int32_t \ *)(&in[12])); \ enc_func(ctx, (addr_type) out, \ (addr_type) out); \ in += 16; \ out += 16; \ pos += 16; \ } \ } else { \ pos = ilen - 16; \ in += pos; \ out += pos; \ while (pos >= 0) { \ dec_func(ctx, (const addr_type) in, \ (addr_type) out); \ if (pos == 0) \ iv_i = (const u_int32_t*) (iv); \ else \ iv_i = (const u_int32_t*) (in - 16); \ *((u_int32_t *)(&out[ 0])) ^= iv_i[0]; \ *((u_int32_t *)(&out[ 4])) ^= iv_i[1]; \ *((u_int32_t *)(&out[ 8])) ^= iv_i[2]; \ *((u_int32_t *)(&out[12])) ^= iv_i[3]; \ in -= 16; \ out -= 16; \ pos -= 16; \ } \ } \ return ret; \ } #endif /* _CBC_GENERIC_H */ libreswan-3.32/lib/libcrypto/libserpent/000077500000000000000000000000001365625662500203735ustar00rootroot00000000000000libreswan-3.32/lib/libcrypto/libserpent/Makefile000066400000000000000000000003321365625662500220310ustar00rootroot00000000000000OBJS=serpent.o serpent_cbc.o LIBRARY=crypto/libserpent LIB=libserpent.a ONEFILE=serpent.h INCLUDES+=-I${SRCDIR}../include ifdef top_srcdir include $(top_srcdir)/mk/library.mk else include ../../../mk/library.mk endif libreswan-3.32/lib/libcrypto/libserpent/serpent.c000066400000000000000000000472061365625662500222300ustar00rootroot00000000000000 /* Optimized implementation of the Serpent AES candidate algorithm * Designed by Anderson, Biham and Knudsen and Implemented by * Gisle Sælensminde 2000. * * The implementation is based on the pentium optimised sboxes of * Dag Arne Osvik. Even these sboxes are designed to be optimal for x86 * processors they are efficient on other processors as well, but the speedup * isn't so impressive compared to other implementations. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. */ #ifdef __KERNEL__ #include #include #include #else #include #include "lswendian.h" #endif #include "serpent.h" #define rotl(reg, val) ((reg << val) | (reg >> (32 - val))) #define rotr(reg, val) ((reg >> val) | (reg << (32 - val))) #ifdef __cpu_to_be32 #define BLOCK_SWAP #define io_swap(x) __cpu_to_be32(x) #else #undef BLOCK_SWAP #endif /* The sbox functions. The first four parameters is the input bits, and * the last is a tempoary. These parameters are also used for output, but * the bit order is permuted. The output bit order from S0 is * (1 4 2 0 3), where 3 is the (now useless) tempoary. */ #define S0(r0, r1, r2, r3, r4) \ r3 = r3 ^ r0; \ r4 = r1; \ r1 = r1 & r3; \ r4 = r4 ^ r2; \ r1 = r1 ^ r0; \ r0 = r0 | r3; \ r0 = r0 ^ r4; \ r4 = r4 ^ r3; \ r3 = r3 ^ r2; \ r2 = r2 | r1; \ r2 = r2 ^ r4; \ r4 = -1 ^ r4; \ r4 = r4 | r1; \ r1 = r1 ^ r3; \ r1 = r1 ^ r4; \ r3 = r3 | r0; \ r1 = r1 ^ r3; \ r4 = r4 ^ r3; #define S1(r0, r1, r2, r3, r4) \ r1 = -1 ^ r1; \ r4 = r0; \ r0 = r0 ^ r1; \ r4 = r4 | r1; \ r4 = r4 ^ r3; \ r3 = r3 & r0; \ r2 = r2 ^ r4; \ r3 = r3 ^ r1; \ r3 = r3 | r2; \ r0 = r0 ^ r4; \ r3 = r3 ^ r0; \ r1 = r1 & r2; \ r0 = r0 | r1; \ r1 = r1 ^ r4; \ r0 = r0 ^ r2; \ r4 = r4 | r3; \ r0 = r0 ^ r4; \ r4 = -1 ^ r4; \ r1 = r1 ^ r3; \ r4 = r4 & r2; \ r1 = -1 ^ r1; \ r4 = r4 ^ r0; \ r1 = r1 ^ r4; #define S2(r0, r1, r2, r3, r4) \ r4 = r0; \ r0 = r0 & r2; \ r0 = r0 ^ r3; \ r2 = r2 ^ r1; \ r2 = r2 ^ r0; \ r3 = r3 | r4; \ r3 = r3 ^ r1; \ r4 = r4 ^ r2; \ r1 = r3; \ r3 = r3 | r4; \ r3 = r3 ^ r0; \ r0 = r0 & r1; \ r4 = r4 ^ r0; \ r1 = r1 ^ r3; \ r1 = r1 ^ r4; \ r4 = -1 ^ r4; #define S3(r0, r1, r2, r3, r4) \ r4 = r0; \ r0 = r0 | r3; \ r3 = r3 ^ r1; \ r1 = r1 & r4; \ r4 = r4 ^ r2; \ r2 = r2 ^ r3; \ r3 = r3 & r0; \ r4 = r4 | r1; \ r3 = r3 ^ r4; \ r0 = r0 ^ r1; \ r4 = r4 & r0; \ r1 = r1 ^ r3; \ r4 = r4 ^ r2; \ r1 = r1 | r0; \ r1 = r1 ^ r2; \ r0 = r0 ^ r3; \ r2 = r1; \ r1 = r1 | r3; \ r1 = r1 ^ r0; #define S4(r0, r1, r2, r3, r4) \ r1 = r1 ^ r3; \ r3 = -1 ^ r3; \ r2 = r2 ^ r3; \ r3 = r3 ^ r0; \ r4 = r1; \ r1 = r1 & r3; \ r1 = r1 ^ r2; \ r4 = r4 ^ r3; \ r0 = r0 ^ r4; \ r2 = r2 & r4; \ r2 = r2 ^ r0; \ r0 = r0 & r1; \ r3 = r3 ^ r0; \ r4 = r4 | r1; \ r4 = r4 ^ r0; \ r0 = r0 | r3; \ r0 = r0 ^ r2; \ r2 = r2 & r3; \ r0 = -1 ^ r0; \ r4 = r4 ^ r2; #define S5(r0, r1, r2, r3, r4) \ r0 = r0 ^ r1; \ r1 = r1 ^ r3; \ r3 = -1 ^ r3; \ r4 = r1; \ r1 = r1 & r0; \ r2 = r2 ^ r3; \ r1 = r1 ^ r2; \ r2 = r2 | r4; \ r4 = r4 ^ r3; \ r3 = r3 & r1; \ r3 = r3 ^ r0; \ r4 = r4 ^ r1; \ r4 = r4 ^ r2; \ r2 = r2 ^ r0; \ r0 = r0 & r3; \ r2 = -1 ^ r2; \ r0 = r0 ^ r4; \ r4 = r4 | r3; \ r2 = r2 ^ r4; #define S6(r0, r1, r2, r3, r4) \ r2 = -1 ^ r2; \ r4 = r3; \ r3 = r3 & r0; \ r0 = r0 ^ r4; \ r3 = r3 ^ r2; \ r2 = r2 | r4; \ r1 = r1 ^ r3; \ r2 = r2 ^ r0; \ r0 = r0 | r1; \ r2 = r2 ^ r1; \ r4 = r4 ^ r0; \ r0 = r0 | r3; \ r0 = r0 ^ r2; \ r4 = r4 ^ r3; \ r4 = r4 ^ r0; \ r3 = -1 ^ r3; \ r2 = r2 & r4; \ r2 = r2 ^ r3; #define S7(r0, r1, r2, r3, r4) \ r4 = r2; \ r2 = r2 & r1; \ r2 = r2 ^ r3; \ r3 = r3 & r1; \ r4 = r4 ^ r2; \ r2 = r2 ^ r1; \ r1 = r1 ^ r0; \ r0 = r0 | r4; \ r0 = r0 ^ r2; \ r3 = r3 ^ r1; \ r2 = r2 ^ r3; \ r3 = r3 & r0; \ r3 = r3 ^ r4; \ r4 = r4 ^ r2; \ r2 = r2 & r0; \ r4 = -1 ^ r4; \ r2 = r2 ^ r4; \ r4 = r4 & r0; \ r1 = r1 ^ r3; \ r4 = r4 ^ r1; /* The inverse sboxes */ #define I0(r0, r1, r2, r3, r4) \ r2 = r2 ^ -1; \ r4 = r1; \ r1 = r1 | r0; \ r4 = r4 ^ -1; \ r1 = r1 ^ r2; \ r2 = r2 | r4; \ r1 = r1 ^ r3; \ r0 = r0 ^ r4; \ r2 = r2 ^ r0; \ r0 = r0 & r3; \ r4 = r4 ^ r0; \ r0 = r0 | r1; \ r0 = r0 ^ r2; \ r3 = r3 ^ r4; \ r2 = r2 ^ r1; \ r3 = r3 ^ r0; \ r3 = r3 ^ r1; \ r2 = r2 & r3; \ r4 = r4 ^ r2; #define I1(r0, r1, r2, r3, r4) \ r4 = r1; \ r1 = r1 ^ r3; \ r3 = r3 & r1; \ r4 = r4 ^ r2; \ r3 = r3 ^ r0; \ r0 = r0 | r1; \ r2 = r2 ^ r3; \ r0 = r0 ^ r4; \ r0 = r0 | r2; \ r1 = r1 ^ r3; \ r0 = r0 ^ r1; \ r1 = r1 | r3; \ r1 = r1 ^ r0; \ r4 = r4 ^ -1; \ r4 = r4 ^ r1; \ r1 = r1 | r0; \ r1 = r1 ^ r0; \ r1 = r1 | r4; \ r3 = r3 ^ r1; #define I2(r0, r1, r2, r3, r4) \ r2 = r2 ^ r3; \ r3 = r3 ^ r0; \ r4 = r3; \ r3 = r3 & r2; \ r3 = r3 ^ r1; \ r1 = r1 | r2; \ r1 = r1 ^ r4; \ r4 = r4 & r3; \ r2 = r2 ^ r3; \ r4 = r4 & r0; \ r4 = r4 ^ r2; \ r2 = r2 & r1; \ r2 = r2 | r0; \ r3 = r3 ^ -1; \ r2 = r2 ^ r3; \ r0 = r0 ^ r3; \ r0 = r0 & r1; \ r3 = r3 ^ r4; \ r3 = r3 ^ r0; #define I3(r0, r1, r2, r3, r4) \ r4 = r2; \ r2 = r2 ^ r1; \ r0 = r0 ^ r2; \ r4 = r4 & r2; \ r4 = r4 ^ r0; \ r0 = r0 & r1; \ r1 = r1 ^ r3; \ r3 = r3 | r4; \ r2 = r2 ^ r3; \ r0 = r0 ^ r3; \ r1 = r1 ^ r4; \ r3 = r3 & r2; \ r3 = r3 ^ r1; \ r1 = r1 ^ r0; \ r1 = r1 | r2; \ r0 = r0 ^ r3; \ r1 = r1 ^ r4; \ r0 = r0 ^ r1; #define I4(r0, r1, r2, r3, r4) \ r4 = r2; \ r2 = r2 & r3; \ r2 = r2 ^ r1; \ r1 = r1 | r3; \ r1 = r1 & r0; \ r4 = r4 ^ r2; \ r4 = r4 ^ r1; \ r1 = r1 & r2; \ r0 = r0 ^ -1; \ r3 = r3 ^ r4; \ r1 = r1 ^ r3; \ r3 = r3 & r0; \ r3 = r3 ^ r2; \ r0 = r0 ^ r1; \ r2 = r2 & r0; \ r3 = r3 ^ r0; \ r2 = r2 ^ r4; \ r2 = r2 | r3; \ r3 = r3 ^ r0; \ r2 = r2 ^ r1; #define I5(r0, r1, r2, r3, r4) \ r1 = r1 ^ -1; \ r4 = r3; \ r2 = r2 ^ r1; \ r3 = r3 | r0; \ r3 = r3 ^ r2; \ r2 = r2 | r1; \ r2 = r2 & r0; \ r4 = r4 ^ r3; \ r2 = r2 ^ r4; \ r4 = r4 | r0; \ r4 = r4 ^ r1; \ r1 = r1 & r2; \ r1 = r1 ^ r3; \ r4 = r4 ^ r2; \ r3 = r3 & r4; \ r4 = r4 ^ r1; \ r3 = r3 ^ r0; \ r3 = r3 ^ r4; \ r4 = r4 ^ -1; #define I6(r0, r1, r2, r3, r4) \ r0 = r0 ^ r2; \ r4 = r2; \ r2 = r2 & r0; \ r4 = r4 ^ r3; \ r2 = r2 ^ -1; \ r3 = r3 ^ r1; \ r2 = r2 ^ r3; \ r4 = r4 | r0; \ r0 = r0 ^ r2; \ r3 = r3 ^ r4; \ r4 = r4 ^ r1; \ r1 = r1 & r3; \ r1 = r1 ^ r0; \ r0 = r0 ^ r3; \ r0 = r0 | r2; \ r3 = r3 ^ r1; \ r4 = r4 ^ r0; #define I7(r0, r1, r2, r3, r4) \ r4 = r2; \ r2 = r2 ^ r0; \ r0 = r0 & r3; \ r4 = r4 | r3; \ r2 = r2 ^ -1; \ r3 = r3 ^ r1; \ r1 = r1 | r0; \ r0 = r0 ^ r2; \ r2 = r2 & r4; \ r3 = r3 & r4; \ r1 = r1 ^ r2; \ r2 = r2 ^ r0; \ r0 = r0 | r2; \ r4 = r4 ^ r1; \ r0 = r0 ^ r3; \ r3 = r3 ^ r4; \ r4 = r4 | r0; \ r3 = r3 ^ r2; \ r4 = r4 ^ r2; /* forward and inverse linear transformations */ #define LINTRANS(r0, r1, r2, r3, r4) \ r0 = rotl(r0, 13); \ r2 = rotl(r2, 3); \ r3 = r3 ^ r2; \ r4 = r0 << 3; \ r1 = r1 ^ r0; \ r3 = r3 ^ r4; \ r1 = r1 ^ r2; \ r3 = rotl(r3, 7); \ r1 = rotl(r1, 1); \ r2 = r2 ^ r3; \ r4 = r1 << 7; \ r0 = r0 ^ r1; \ r2 = r2 ^ r4; \ r0 = r0 ^ r3; \ r2 = rotl(r2, 22); \ r0 = rotl(r0, 5); #define ILINTRANS(r0, r1, r2, r3, r4) \ r2 = rotr(r2, 22); \ r0 = rotr(r0, 5); \ r2 = r2 ^ r3; \ r4 = r1 << 7; \ r0 = r0 ^ r1; \ r2 = r2 ^ r4; \ r0 = r0 ^ r3; \ r3 = rotr(r3, 7); \ r1 = rotr(r1, 1); \ r3 = r3 ^ r2; \ r4 = r0 << 3; \ r1 = r1 ^ r0; \ r3 = r3 ^ r4; \ r1 = r1 ^ r2; \ r2 = rotr(r2, 3); \ r0 = rotr(r0, 13); #define KEYMIX(r0, r1, r2, r3, r4, IN) \ r0 = r0 ^ l_key[IN + 8]; \ r1 = r1 ^ l_key[IN + 9]; \ r2 = r2 ^ l_key[IN + 10]; \ r3 = r3 ^ l_key[IN + 11]; #define GETKEY(r0, r1, r2, r3, IN) \ r0 = l_key[IN + 8]; \ r1 = l_key[IN + 9]; \ r2 = l_key[IN + 10]; \ r3 = l_key[IN + 11]; #define SETKEY(r0, r1, r2, r3, IN) \ l_key[IN + 8] = r0; \ l_key[IN + 9] = r1; \ l_key[IN + 10] = r2; \ l_key[IN + 11] = r3; /* initialise the key schedule from the user supplied key */ int serpent_set_key(serpent_context *cx, const unsigned char *key, int key_len) { const u32 *in_key = (const u32 *)key; /* l_key - storage for the key schedule */ u32 *l_key = cx->keyinfo; u32 i, lk, r0, r1, r2, r3, r4; if (key_len != 16 && key_len != 24 && key_len != 32) return -1; /* unsupported key length */ key_len *= 8; i = 0; lk = (key_len + 31) / 32; while (i < lk) { #ifdef BLOCK_SWAP l_key[i] = io_swap(in_key[lk - i - 1]); #else l_key[i] = in_key[i]; #endif i++; } if (key_len < 256) { while (i < 8) l_key[i++] = 0; i = key_len / 32; lk = 1 << key_len % 32; l_key[i] &= lk - 1; l_key[i] |= lk; } for (i = 0; i < 132; ++i) { lk = l_key[i] ^ l_key[i + 3] ^ l_key[i + 5] ^ l_key[i + 7] ^ 0x9e3779b9 ^ i; l_key[i + 8] = (lk << 11) | (lk >> 21); } GETKEY(r0, r1, r2, r3, 0); S3(r0, r1, r2, r3, r4); SETKEY(r1, r2, r3, r4, 0) GETKEY(r0, r1, r2, r3, 4); S2(r0, r1, r2, r3, r4); SETKEY(r2, r3, r1, r4, 4) GETKEY(r0, r1, r2, r3, 8); S1(r0, r1, r2, r3, r4); SETKEY(r3, r1, r2, r0, 8) GETKEY(r0, r1, r2, r3, 12); S0(r0, r1, r2, r3, r4); SETKEY(r1, r4, r2, r0, 12) GETKEY(r0, r1, r2, r3, 16); S7(r0, r1, r2, r3, r4); SETKEY(r2, r4, r3, r0, 16) GETKEY(r0, r1, r2, r3, 20); S6(r0, r1, r2, r3, r4) SETKEY(r0, r1, r4, r2, 20) GETKEY(r0, r1, r2, r3, 24); S5(r0, r1, r2, r3, r4); SETKEY(r1, r3, r0, r2, 24) GETKEY(r0, r1, r2, r3, 28); S4(r0, r1, r2, r3, r4) SETKEY(r1, r4, r0, r3, 28) GETKEY(r0, r1, r2, r3, 32); S3(r0, r1, r2, r3, r4); SETKEY(r1, r2, r3, r4, 32) GETKEY(r0, r1, r2, r3, 36); S2(r0, r1, r2, r3, r4); SETKEY(r2, r3, r1, r4, 36) GETKEY(r0, r1, r2, r3, 40); S1(r0, r1, r2, r3, r4); SETKEY(r3, r1, r2, r0, 40) GETKEY(r0, r1, r2, r3, 44); S0(r0, r1, r2, r3, r4); SETKEY(r1, r4, r2, r0, 44) GETKEY(r0, r1, r2, r3, 48); S7(r0, r1, r2, r3, r4); SETKEY(r2, r4, r3, r0, 48) GETKEY(r0, r1, r2, r3, 52); S6(r0, r1, r2, r3, r4) SETKEY(r0, r1, r4, r2, 52) GETKEY(r0, r1, r2, r3, 56); S5(r0, r1, r2, r3, r4); SETKEY(r1, r3, r0, r2, 56) GETKEY(r0, r1, r2, r3, 60); S4(r0, r1, r2, r3, r4) SETKEY(r1, r4, r0, r3, 60) GETKEY(r0, r1, r2, r3, 64); S3(r0, r1, r2, r3, r4); SETKEY(r1, r2, r3, r4, 64) GETKEY(r0, r1, r2, r3, 68); S2(r0, r1, r2, r3, r4); SETKEY(r2, r3, r1, r4, 68) GETKEY(r0, r1, r2, r3, 72); S1(r0, r1, r2, r3, r4); SETKEY(r3, r1, r2, r0, 72) GETKEY(r0, r1, r2, r3, 76); S0(r0, r1, r2, r3, r4); SETKEY(r1, r4, r2, r0, 76) GETKEY(r0, r1, r2, r3, 80); S7(r0, r1, r2, r3, r4); SETKEY(r2, r4, r3, r0, 80) GETKEY(r0, r1, r2, r3, 84); S6(r0, r1, r2, r3, r4) SETKEY(r0, r1, r4, r2, 84) GETKEY(r0, r1, r2, r3, 88); S5(r0, r1, r2, r3, r4); SETKEY(r1, r3, r0, r2, 88) GETKEY(r0, r1, r2, r3, 92); S4(r0, r1, r2, r3, r4) SETKEY(r1, r4, r0, r3, 92) GETKEY(r0, r1, r2, r3, 96); S3(r0, r1, r2, r3, r4); SETKEY(r1, r2, r3, r4, 96) GETKEY(r0, r1, r2, r3, 100); S2(r0, r1, r2, r3, r4); SETKEY(r2, r3, r1, r4, 100) GETKEY(r0, r1, r2, r3, 104); S1(r0, r1, r2, r3, r4); SETKEY(r3, r1, r2, r0, 104) GETKEY(r0, r1, r2, r3, 108); S0(r0, r1, r2, r3, r4); SETKEY(r1, r4, r2, r0, 108) GETKEY(r0, r1, r2, r3, 112); S7(r0, r1, r2, r3, r4); SETKEY(r2, r4, r3, r0, 112) GETKEY(r0, r1, r2, r3, 116); S6(r0, r1, r2, r3, r4) SETKEY(r0, r1, r4, r2, 116) GETKEY(r0, r1, r2, r3, 120); S5(r0, r1, r2, r3, r4); SETKEY(r1, r3, r0, r2, 120) GETKEY(r0, r1, r2, r3, 124); S4(r0, r1, r2, r3, r4) SETKEY(r1, r4, r0, r3, 124) GETKEY(r0, r1, r2, r3, 128); S3(r0, r1, r2, r3, r4); SETKEY(r1, r2, r3, r4, 128) return 0; }; /* Encryption and decryption functions. The rounds are fully inlined. * The sboxes alters the bit order of the output, and the altered * bit ordrer is used progressivly. */ /* encrypt a block of text */ int serpent_encrypt(serpent_context *cx, const u8 *in, u8 *out) { u32 *l_key = cx->keyinfo; const u32 *in_blk = (const u32 *) in; u32 *out_blk = (u32 *) out; u32 r0, r1, r2, r3, r4; #ifdef BLOCK_SWAP r0 = io_swap(in_blk[3]); r1 = io_swap(in_blk[2]); r2 = io_swap(in_blk[1]); r3 = io_swap(in_blk[0]); #else r0 = in_blk[0]; r1 = in_blk[1]; r2 = in_blk[2]; r3 = in_blk[3]; #endif /* round 1 */ KEYMIX(r0, r1, r2, r3, r4, 0); S0(r0, r1, r2, r3, r4); LINTRANS(r1, r4, r2, r0, r3); /* round 2 */ KEYMIX(r1, r4, r2, r0, r3, 4); S1(r1, r4, r2, r0, r3); LINTRANS(r0, r4, r2, r1, r3); /* round 3 */ KEYMIX(r0, r4, r2, r1, r3, 8); S2(r0, r4, r2, r1, r3); LINTRANS(r2, r1, r4, r3, r0); /* round 4 */ KEYMIX(r2, r1, r4, r3, r0, 12); S3(r2, r1, r4, r3, r0); LINTRANS(r1, r4, r3, r0, r2); /* round 5 */ KEYMIX(r1, r4, r3, r0, r2, 16); S4(r1, r4, r3, r0, r2) LINTRANS(r4, r2, r1, r0, r3); /* round 6 */ KEYMIX(r4, r2, r1, r0, r3, 20); S5(r4, r2, r1, r0, r3); LINTRANS(r2, r0, r4, r1, r3); /* round 7 */ KEYMIX(r2, r0, r4, r1, r3, 24); S6(r2, r0, r4, r1, r3) LINTRANS(r2, r0, r3, r4, r1); /* round 8 */ KEYMIX(r2, r0, r3, r4, r1, 28); S7(r2, r0, r3, r4, r1); LINTRANS(r3, r1, r4, r2, r0); /* round 9 */ KEYMIX(r3, r1, r4, r2, r0, 32); S0(r3, r1, r4, r2, r0); LINTRANS(r1, r0, r4, r3, r2); /* round 10 */ KEYMIX(r1, r0, r4, r3, r2, 36); S1(r1, r0, r4, r3, r2); LINTRANS(r3, r0, r4, r1, r2); /* round 11 */ KEYMIX(r3, r0, r4, r1, r2, 40); S2(r3, r0, r4, r1, r2); LINTRANS(r4, r1, r0, r2, r3); /* round 12 */ KEYMIX(r4, r1, r0, r2, r3, 44); S3(r4, r1, r0, r2, r3); LINTRANS(r1, r0, r2, r3, r4); /* round 13 */ KEYMIX(r1, r0, r2, r3, r4, 48); S4(r1, r0, r2, r3, r4) LINTRANS(r0, r4, r1, r3, r2); /* round 14 */ KEYMIX(r0, r4, r1, r3, r2, 52); S5(r0, r4, r1, r3, r2); LINTRANS(r4, r3, r0, r1, r2); /* round 15 */ KEYMIX(r4, r3, r0, r1, r2, 56); S6(r4, r3, r0, r1, r2) LINTRANS(r4, r3, r2, r0, r1); /* round 16 */ KEYMIX(r4, r3, r2, r0, r1, 60); S7(r4, r3, r2, r0, r1); LINTRANS(r2, r1, r0, r4, r3); /* round 17 */ KEYMIX(r2, r1, r0, r4, r3, 64); S0(r2, r1, r0, r4, r3); LINTRANS(r1, r3, r0, r2, r4); /* round 18 */ KEYMIX(r1, r3, r0, r2, r4, 68); S1(r1, r3, r0, r2, r4); LINTRANS(r2, r3, r0, r1, r4); /* round 19 */ KEYMIX(r2, r3, r0, r1, r4, 72); S2(r2, r3, r0, r1, r4); LINTRANS(r0, r1, r3, r4, r2); /* round 20 */ KEYMIX(r0, r1, r3, r4, r2, 76); S3(r0, r1, r3, r4, r2); LINTRANS(r1, r3, r4, r2, r0); /* round 21 */ KEYMIX(r1, r3, r4, r2, r0, 80); S4(r1, r3, r4, r2, r0) LINTRANS(r3, r0, r1, r2, r4); /* round 22 */ KEYMIX(r3, r0, r1, r2, r4, 84); S5(r3, r0, r1, r2, r4); LINTRANS(r0, r2, r3, r1, r4); /* round 23 */ KEYMIX(r0, r2, r3, r1, r4, 88); S6(r0, r2, r3, r1, r4) LINTRANS(r0, r2, r4, r3, r1); /* round 24 */ KEYMIX(r0, r2, r4, r3, r1, 92); S7(r0, r2, r4, r3, r1); LINTRANS(r4, r1, r3, r0, r2); /* round 25 */ KEYMIX(r4, r1, r3, r0, r2, 96); S0(r4, r1, r3, r0, r2); LINTRANS(r1, r2, r3, r4, r0); /* round 26 */ KEYMIX(r1, r2, r3, r4, r0, 100); S1(r1, r2, r3, r4, r0); LINTRANS(r4, r2, r3, r1, r0); /* round 27 */ KEYMIX(r4, r2, r3, r1, r0, 104); S2(r4, r2, r3, r1, r0); LINTRANS(r3, r1, r2, r0, r4); /* round 28 */ KEYMIX(r3, r1, r2, r0, r4, 108); S3(r3, r1, r2, r0, r4); LINTRANS(r1, r2, r0, r4, r3); /* round 29 */ KEYMIX(r1, r2, r0, r4, r3, 112); S4(r1, r2, r0, r4, r3) LINTRANS(r2, r3, r1, r4, r0); /* round 30 */ KEYMIX(r2, r3, r1, r4, r0, 116); S5(r2, r3, r1, r4, r0); LINTRANS(r3, r4, r2, r1, r0); /* round 31 */ KEYMIX(r3, r4, r2, r1, r0, 120); S6(r3, r4, r2, r1, r0) LINTRANS(r3, r4, r0, r2, r1); /* round 32 */ KEYMIX(r3, r4, r0, r2, r1, 124); S7(r3, r4, r0, r2, r1); KEYMIX(r0, r1, r2, r3, r4, 128); #ifdef BLOCK_SWAP out_blk[3] = io_swap(r0); out_blk[2] = io_swap(r1); out_blk[1] = io_swap(r2); out_blk[0] = io_swap(r3); #else out_blk[0] = r0; out_blk[1] = r1; out_blk[2] = r2; out_blk[3] = r3; #endif return 0; }; /* decrypt a block of text */ int serpent_decrypt(serpent_context *cx, const u8 *in, u8 *out) { u32 *l_key = cx->keyinfo; const u32 *in_blk = (const u32 *)in; u32 *out_blk = (u32 *)out; u32 r0, r1, r2, r3, r4; #ifdef BLOCK_SWAP r0 = io_swap(in_blk[3]); r1 = io_swap(in_blk[2]); r2 = io_swap(in_blk[1]); r3 = io_swap(in_blk[0]); #else r0 = in_blk[0]; r1 = in_blk[1]; r2 = in_blk[2]; r3 = in_blk[3]; #endif /* round 1 */ KEYMIX(r0, r1, r2, r3, r4, 128); I7(r0, r1, r2, r3, r4); KEYMIX(r3, r0, r1, r4, r2, 124); /* round 2 */ ILINTRANS(r3, r0, r1, r4, r2); I6(r3, r0, r1, r4, r2); KEYMIX(r0, r1, r2, r4, r3, 120); /* round 3 */ ILINTRANS(r0, r1, r2, r4, r3); I5(r0, r1, r2, r4, r3); KEYMIX(r1, r3, r4, r2, r0, 116); /* round 4 */ ILINTRANS(r1, r3, r4, r2, r0); I4(r1, r3, r4, r2, r0); KEYMIX(r1, r2, r4, r0, r3, 112); /* round 5 */ ILINTRANS(r1, r2, r4, r0, r3); I3(r1, r2, r4, r0, r3); KEYMIX(r4, r2, r0, r1, r3, 108); /* round 6 */ ILINTRANS(r4, r2, r0, r1, r3); I2(r4, r2, r0, r1, r3); KEYMIX(r2, r3, r0, r1, r4, 104); /* round 7 */ ILINTRANS(r2, r3, r0, r1, r4); I1(r2, r3, r0, r1, r4); KEYMIX(r4, r2, r1, r0, r3, 100); /* round 8 */ ILINTRANS(r4, r2, r1, r0, r3); I0(r4, r2, r1, r0, r3); KEYMIX(r4, r3, r2, r0, r1, 96); /* round 9 */ ILINTRANS(r4, r3, r2, r0, r1); I7(r4, r3, r2, r0, r1); KEYMIX(r0, r4, r3, r1, r2, 92); /* round 10 */ ILINTRANS(r0, r4, r3, r1, r2); I6(r0, r4, r3, r1, r2); KEYMIX(r4, r3, r2, r1, r0, 88); /* round 11 */ ILINTRANS(r4, r3, r2, r1, r0); I5(r4, r3, r2, r1, r0); KEYMIX(r3, r0, r1, r2, r4, 84); /* round 12 */ ILINTRANS(r3, r0, r1, r2, r4); I4(r3, r0, r1, r2, r4); KEYMIX(r3, r2, r1, r4, r0, 80); /* round 13 */ ILINTRANS(r3, r2, r1, r4, r0); I3(r3, r2, r1, r4, r0); KEYMIX(r1, r2, r4, r3, r0, 76); /* round 14 */ ILINTRANS(r1, r2, r4, r3, r0); I2(r1, r2, r4, r3, r0); KEYMIX(r2, r0, r4, r3, r1, 72); /* round 15 */ ILINTRANS(r2, r0, r4, r3, r1); I1(r2, r0, r4, r3, r1); KEYMIX(r1, r2, r3, r4, r0, 68); /* round 16 */ ILINTRANS(r1, r2, r3, r4, r0); I0(r1, r2, r3, r4, r0); KEYMIX(r1, r0, r2, r4, r3, 64); /* round 17 */ ILINTRANS(r1, r0, r2, r4, r3); I7(r1, r0, r2, r4, r3); KEYMIX(r4, r1, r0, r3, r2, 60); /* round 18 */ ILINTRANS(r4, r1, r0, r3, r2); I6(r4, r1, r0, r3, r2); KEYMIX(r1, r0, r2, r3, r4, 56); /* round 19 */ ILINTRANS(r1, r0, r2, r3, r4); I5(r1, r0, r2, r3, r4); KEYMIX(r0, r4, r3, r2, r1, 52); /* round 20 */ ILINTRANS(r0, r4, r3, r2, r1); I4(r0, r4, r3, r2, r1); KEYMIX(r0, r2, r3, r1, r4, 48); /* round 21 */ ILINTRANS(r0, r2, r3, r1, r4); I3(r0, r2, r3, r1, r4); KEYMIX(r3, r2, r1, r0, r4, 44); /* round 22 */ ILINTRANS(r3, r2, r1, r0, r4); I2(r3, r2, r1, r0, r4); KEYMIX(r2, r4, r1, r0, r3, 40); /* round 23 */ ILINTRANS(r2, r4, r1, r0, r3); I1(r2, r4, r1, r0, r3); KEYMIX(r3, r2, r0, r1, r4, 36); /* round 24 */ ILINTRANS(r3, r2, r0, r1, r4); I0(r3, r2, r0, r1, r4); KEYMIX(r3, r4, r2, r1, r0, 32); /* round 25 */ ILINTRANS(r3, r4, r2, r1, r0); I7(r3, r4, r2, r1, r0); KEYMIX(r1, r3, r4, r0, r2, 28); /* round 26 */ ILINTRANS(r1, r3, r4, r0, r2); I6(r1, r3, r4, r0, r2); KEYMIX(r3, r4, r2, r0, r1, 24); /* round 27 */ ILINTRANS(r3, r4, r2, r0, r1); I5(r3, r4, r2, r0, r1); KEYMIX(r4, r1, r0, r2, r3, 20); /* round 28 */ ILINTRANS(r4, r1, r0, r2, r3); I4(r4, r1, r0, r2, r3); KEYMIX(r4, r2, r0, r3, r1, 16); /* round 29 */ ILINTRANS(r4, r2, r0, r3, r1); I3(r4, r2, r0, r3, r1); KEYMIX(r0, r2, r3, r4, r1, 12); /* round 30 */ ILINTRANS(r0, r2, r3, r4, r1); I2(r0, r2, r3, r4, r1); KEYMIX(r2, r1, r3, r4, r0, 8); /* round 31 */ ILINTRANS(r2, r1, r3, r4, r0); I1(r2, r1, r3, r4, r0); KEYMIX(r0, r2, r4, r3, r1, 4); /* round 32 */ ILINTRANS(r0, r2, r4, r3, r1); I0(r0, r2, r4, r3, r1); KEYMIX(r0, r1, r2, r3, r4, 0); #ifdef BLOCK_SWAP out_blk[3] = io_swap(r0); out_blk[2] = io_swap(r1); out_blk[1] = io_swap(r2); out_blk[0] = io_swap(r3); #else out_blk[0] = r0; out_blk[1] = r1; out_blk[2] = r2; out_blk[3] = r3; #endif return 0; }; libreswan-3.32/lib/libcrypto/libserpent/serpent.h000066400000000000000000000010351365625662500222230ustar00rootroot00000000000000#ifndef SERPENT_H #define SERPENT_H #ifdef __KERNEL__ #include #else #include #define u32 uint32_t #define u8 uint8_t #endif struct serpent_context { u32 keyinfo[140]; /* storage for the key schedule */ }; typedef struct serpent_context serpent_context; int serpent_set_key(serpent_context *ctx, const u8 * in_key, int key_len); int serpent_decrypt(serpent_context *ctx, const u8 * in_blk, u8 * out_blk); int serpent_encrypt(serpent_context *ctx, const u8 * in_blk, u8 * out_blk); #endif /* SERPENT_H */ libreswan-3.32/lib/libcrypto/libserpent/serpent_cbc.c000066400000000000000000000003551365625662500230310ustar00rootroot00000000000000#ifdef __KERNEL__ #include #else #include #endif #include "serpent_cbc.h" #include "cbc_generic.h" CBC_IMPL_BLK16(serpent_cbc_encrypt, serpent_context, u_int8_t *, serpent_encrypt, serpent_decrypt); libreswan-3.32/lib/libcrypto/libserpent/serpent_cbc.h000066400000000000000000000002521365625662500230320ustar00rootroot00000000000000/* Glue header */ #include "serpent.h" int serpent_cbc_encrypt(serpent_context *ctx, const uint8_t * in, uint8_t * out, int ilen, const uint8_t * iv, int encrypt); libreswan-3.32/lib/libcrypto/libserpent/test_main.c000066400000000000000000000017641365625662500225320ustar00rootroot00000000000000#include #include #include "serpent_cbc.h" #define BLOCK_SIZE 16 #define KEY_SIZE 128 /* bits */ #define KEY "1234567890123456" #define STR "hola guaso como estaisss ... 012" #define STRSZ (sizeof(STR) - 1) #define BLKLEN BLOCK_SIZE #define CONTEXT_T serpent_context static int pretty_print(const unsigned char *buf, int count) { int i = 0; for (; i < count; i++) printf("%02hhx ", buf[i]); putchar('\n'); return i; } //#define SIZE STRSZ/2 #define SIZE STRSZ int main() { int ret; char buf0[SIZE + 1], buf1[SIZE + 1]; char IV[BLOCK_SIZE]; CONTEXT_T ac; serpent_set_key(&ac, (void *)KEY, KEY_SIZE); memset(buf0, 0, sizeof(buf0)); memset(buf1, 0, sizeof(buf1)); serpent_cbc_encrypt(&ac, STR, buf0, SIZE, IV, 1); pretty_print(buf0, SIZE); printf("size=%d ret=%d\n%s\n", SIZE, ret, buf0); ret = serpent_cbc_encrypt(&ac, buf0, buf1, SIZE, IV, 0); printf("size=%d ret=%d\n%s\n", SIZE, ret, buf1); return 0; } libreswan-3.32/lib/libcrypto/libtwofish/000077500000000000000000000000001365625662500203765ustar00rootroot00000000000000libreswan-3.32/lib/libcrypto/libtwofish/Makefile000066400000000000000000000003371365625662500220410ustar00rootroot00000000000000 OBJS := twofish.o twofish_cbc.o ONEFILE=twofish.c LIBRARY=crypto/libtwofish LIB=libtwofish.a INCLUDES+=-I${SRCDIR}../include ifdef top_srcdir include $(top_srcdir)/mk/library.mk else include ../../../mk/library.mk endif libreswan-3.32/lib/libcrypto/libtwofish/test_main.c000066400000000000000000000017641365625662500225350ustar00rootroot00000000000000#include #include #include "twofish_cbc.h" #define BLOCK_SIZE 16 #define KEY_SIZE 128 /* bits */ #define KEY "1234567890123456" #define STR "hola guaso como estaisss ... 012" #define STRSZ (sizeof(STR) - 1) #define BLKLEN BLOCK_SIZE #define CONTEXT_T twofish_context static int pretty_print(const unsigned char *buf, int count) { int i = 0; for (; i < count; i++) printf("%02hhx ", buf[i]); putchar('\n'); return i; } //#define SIZE STRSZ/2 #define SIZE STRSZ int main() { int ret; char buf0[SIZE + 1], buf1[SIZE + 1]; char IV[BLOCK_SIZE]; CONTEXT_T ac; twofish_set_key(&ac, (void *)KEY, KEY_SIZE); memset(buf0, 0, sizeof(buf0)); memset(buf1, 0, sizeof(buf1)); twofish_cbc_encrypt(&ac, STR, buf0, SIZE, IV, 1); pretty_print(buf0, SIZE); printf("size=%d ret=%d\n%s\n", SIZE, ret, buf0); ret = twofish_cbc_encrypt(&ac, buf0, buf1, SIZE, IV, 0); printf("size=%d ret=%d\n%s\n", SIZE, ret, buf1); return 0; } libreswan-3.32/lib/libcrypto/libtwofish/twofish.c000066400000000000000000001262771365625662500222440ustar00rootroot00000000000000/* NOTE: This implementation has been changed from the original * source. See ChangeLog for more information. * Maintained by Marc Mutz */ /* Twofish for GPG * By Matthew Skala , July 26, 1998 * 256-bit key length added March 20, 1999 * Some modifications to reduce the text size by Werner Koch, April, 1998 * * The original author has disclaimed all copyright interest in this * code and thus putting it in the public domain. * * This code is a "clean room" implementation, written from the paper * _Twofish: A 128-Bit Block Cipher_ by Bruce Schneier, John Kelsey, * Doug Whiting, David Wagner, Chris Hall, and Niels Ferguson, available * through http://www.counterpane.com/twofish.html * * For background information on multiplication in finite fields, used for * the matrix operations in the key schedule, see the book _Contemporary * Abstract Algebra_ by Joseph A. Gallian, especially chapter 22 in the * Third Edition. * * Only the 128- and 256-bit key sizes are supported. This code is intended * for GNU C on a 32-bit system, but it should work almost anywhere. Loops * are unrolled, precomputation tables are used, etc., for maximum speed at * some cost in memory consumption. */ #ifdef __KERNEL__ #include #include #else #include #define u8 uint8_t #define u32 uint32_t #endif #define rotl generic_rotl32 #define rotr generic_rotr32 #include "twofish.h" /* The large precomputed tables for the Twofish cipher (twofish.c) * Taken from the same source as twofish.c * Marc Mutz */ /* These two tables are the q0 and q1 permutations, exactly as described in * the Twofish paper. */ static const u8 q0[256] = { 0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76, 0x9A, 0x92, 0x80, 0x78, 0xE4, 0xDD, 0xD1, 0x38, 0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C, 0x43, 0x75, 0x37, 0x26, 0xFA, 0x13, 0x94, 0x48, 0xF2, 0xD0, 0x8B, 0x30, 0x84, 0x54, 0xDF, 0x23, 0x19, 0x5B, 0x3D, 0x59, 0xF3, 0xAE, 0xA2, 0x82, 0x63, 0x01, 0x83, 0x2E, 0xD9, 0x51, 0x9B, 0x7C, 0xA6, 0xEB, 0xA5, 0xBE, 0x16, 0x0C, 0xE3, 0x61, 0xC0, 0x8C, 0x3A, 0xF5, 0x73, 0x2C, 0x25, 0x0B, 0xBB, 0x4E, 0x89, 0x6B, 0x53, 0x6A, 0xB4, 0xF1, 0xE1, 0xE6, 0xBD, 0x45, 0xE2, 0xF4, 0xB6, 0x66, 0xCC, 0x95, 0x03, 0x56, 0xD4, 0x1C, 0x1E, 0xD7, 0xFB, 0xC3, 0x8E, 0xB5, 0xE9, 0xCF, 0xBF, 0xBA, 0xEA, 0x77, 0x39, 0xAF, 0x33, 0xC9, 0x62, 0x71, 0x81, 0x79, 0x09, 0xAD, 0x24, 0xCD, 0xF9, 0xD8, 0xE5, 0xC5, 0xB9, 0x4D, 0x44, 0x08, 0x86, 0xE7, 0xA1, 0x1D, 0xAA, 0xED, 0x06, 0x70, 0xB2, 0xD2, 0x41, 0x7B, 0xA0, 0x11, 0x31, 0xC2, 0x27, 0x90, 0x20, 0xF6, 0x60, 0xFF, 0x96, 0x5C, 0xB1, 0xAB, 0x9E, 0x9C, 0x52, 0x1B, 0x5F, 0x93, 0x0A, 0xEF, 0x91, 0x85, 0x49, 0xEE, 0x2D, 0x4F, 0x8F, 0x3B, 0x47, 0x87, 0x6D, 0x46, 0xD6, 0x3E, 0x69, 0x64, 0x2A, 0xCE, 0xCB, 0x2F, 0xFC, 0x97, 0x05, 0x7A, 0xAC, 0x7F, 0xD5, 0x1A, 0x4B, 0x0E, 0xA7, 0x5A, 0x28, 0x14, 0x3F, 0x29, 0x88, 0x3C, 0x4C, 0x02, 0xB8, 0xDA, 0xB0, 0x17, 0x55, 0x1F, 0x8A, 0x7D, 0x57, 0xC7, 0x8D, 0x74, 0xB7, 0xC4, 0x9F, 0x72, 0x7E, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34, 0x6E, 0x50, 0xDE, 0x68, 0x65, 0xBC, 0xDB, 0xF8, 0xC8, 0xA8, 0x2B, 0x40, 0xDC, 0xFE, 0x32, 0xA4, 0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00, 0x6F, 0x9D, 0x36, 0x42, 0x4A, 0x5E, 0xC1, 0xE0 }; static const u8 q1[256] = { 0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8, 0x4A, 0xD3, 0xE6, 0x6B, 0x45, 0x7D, 0xE8, 0x4B, 0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1, 0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F, 0x5E, 0xBA, 0xAE, 0x5B, 0x8A, 0x00, 0xBC, 0x9D, 0x6D, 0xC1, 0xB1, 0x0E, 0x80, 0x5D, 0xD2, 0xD5, 0xA0, 0x84, 0x07, 0x14, 0xB5, 0x90, 0x2C, 0xA3, 0xB2, 0x73, 0x4C, 0x54, 0x92, 0x74, 0x36, 0x51, 0x38, 0xB0, 0xBD, 0x5A, 0xFC, 0x60, 0x62, 0x96, 0x6C, 0x42, 0xF7, 0x10, 0x7C, 0x28, 0x27, 0x8C, 0x13, 0x95, 0x9C, 0xC7, 0x24, 0x46, 0x3B, 0x70, 0xCA, 0xE3, 0x85, 0xCB, 0x11, 0xD0, 0x93, 0xB8, 0xA6, 0x83, 0x20, 0xFF, 0x9F, 0x77, 0xC3, 0xCC, 0x03, 0x6F, 0x08, 0xBF, 0x40, 0xE7, 0x2B, 0xE2, 0x79, 0x0C, 0xAA, 0x82, 0x41, 0x3A, 0xEA, 0xB9, 0xE4, 0x9A, 0xA4, 0x97, 0x7E, 0xDA, 0x7A, 0x17, 0x66, 0x94, 0xA1, 0x1D, 0x3D, 0xF0, 0xDE, 0xB3, 0x0B, 0x72, 0xA7, 0x1C, 0xEF, 0xD1, 0x53, 0x3E, 0x8F, 0x33, 0x26, 0x5F, 0xEC, 0x76, 0x2A, 0x49, 0x81, 0x88, 0xEE, 0x21, 0xC4, 0x1A, 0xEB, 0xD9, 0xC5, 0x39, 0x99, 0xCD, 0xAD, 0x31, 0x8B, 0x01, 0x18, 0x23, 0xDD, 0x1F, 0x4E, 0x2D, 0xF9, 0x48, 0x4F, 0xF2, 0x65, 0x8E, 0x78, 0x5C, 0x58, 0x19, 0x8D, 0xE5, 0x98, 0x57, 0x67, 0x7F, 0x05, 0x64, 0xAF, 0x63, 0xB6, 0xFE, 0xF5, 0xB7, 0x3C, 0xA5, 0xCE, 0xE9, 0x68, 0x44, 0xE0, 0x4D, 0x43, 0x69, 0x29, 0x2E, 0xAC, 0x15, 0x59, 0xA8, 0x0A, 0x9E, 0x6E, 0x47, 0xDF, 0x34, 0x35, 0x6A, 0xCF, 0xDC, 0x22, 0xC9, 0xC0, 0x9B, 0x89, 0xD4, 0xED, 0xAB, 0x12, 0xA2, 0x0D, 0x52, 0xBB, 0x02, 0x2F, 0xA9, 0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2, 0x16, 0x25, 0x86, 0x56, 0x55, 0x09, 0xBE, 0x91 }; /* These MDS tables are actually tables of MDS composed with q0 and q1, * because it is only ever used that way and we can save some time by * precomputing. Of course the main saving comes from precomputing the * GF(2^8) multiplication involved in the MDS matrix multiply; by looking * things up in these tables we reduce the matrix multiply to four lookups * and three XORs. Semi-formally, the definition of these tables is: * mds[0][i] = MDS (q1[i] 0 0 0)^T mds[1][i] = MDS (0 q0[i] 0 0)^T * mds[2][i] = MDS (0 0 q1[i] 0)^T mds[3][i] = MDS (0 0 0 q0[i])^T * where ^T means "transpose", the matrix multiply is performed in GF(2^8) * represented as GF(2)[x]/v(x) where v(x)=x^8+x^6+x^5+x^3+1 as described * by Schneier et al, and I'm casually glossing over the byte/word * conversion issues. */ static const u32 mds[4][256] = { { 0xBCBC3275, 0xECEC21F3, 0x202043C6, 0xB3B3C9F4, 0xDADA03DB, 0x02028B7B, 0xE2E22BFB, 0x9E9EFAC8, 0xC9C9EC4A, 0xD4D409D3, 0x18186BE6, 0x1E1E9F6B, 0x98980E45, 0xB2B2387D, 0xA6A6D2E8, 0x2626B74B, 0x3C3C57D6, 0x93938A32, 0x8282EED8, 0x525298FD, 0x7B7BD437, 0xBBBB3771, 0x5B5B97F1, 0x474783E1, 0x24243C30, 0x5151E20F, 0xBABAC6F8, 0x4A4AF31B, 0xBFBF4887, 0x0D0D70FA, 0xB0B0B306, 0x7575DE3F, 0xD2D2FD5E, 0x7D7D20BA, 0x666631AE, 0x3A3AA35B, 0x59591C8A, 0x00000000, 0xCDCD93BC, 0x1A1AE09D, 0xAEAE2C6D, 0x7F7FABC1, 0x2B2BC7B1, 0xBEBEB90E, 0xE0E0A080, 0x8A8A105D, 0x3B3B52D2, 0x6464BAD5, 0xD8D888A0, 0xE7E7A584, 0x5F5FE807, 0x1B1B1114, 0x2C2CC2B5, 0xFCFCB490, 0x3131272C, 0x808065A3, 0x73732AB2, 0x0C0C8173, 0x79795F4C, 0x6B6B4154, 0x4B4B0292, 0x53536974, 0x94948F36, 0x83831F51, 0x2A2A3638, 0xC4C49CB0, 0x2222C8BD, 0xD5D5F85A, 0xBDBDC3FC, 0x48487860, 0xFFFFCE62, 0x4C4C0796, 0x4141776C, 0xC7C7E642, 0xEBEB24F7, 0x1C1C1410, 0x5D5D637C, 0x36362228, 0x6767C027, 0xE9E9AF8C, 0x4444F913, 0x1414EA95, 0xF5F5BB9C, 0xCFCF18C7, 0x3F3F2D24, 0xC0C0E346, 0x7272DB3B, 0x54546C70, 0x29294CCA, 0xF0F035E3, 0x0808FE85, 0xC6C617CB, 0xF3F34F11, 0x8C8CE4D0, 0xA4A45993, 0xCACA96B8, 0x68683BA6, 0xB8B84D83, 0x38382820, 0xE5E52EFF, 0xADAD569F, 0x0B0B8477, 0xC8C81DC3, 0x9999FFCC, 0x5858ED03, 0x19199A6F, 0x0E0E0A08, 0x95957EBF, 0x70705040, 0xF7F730E7, 0x6E6ECF2B, 0x1F1F6EE2, 0xB5B53D79, 0x09090F0C, 0x616134AA, 0x57571682, 0x9F9F0B41, 0x9D9D803A, 0x111164EA, 0x2525CDB9, 0xAFAFDDE4, 0x4545089A, 0xDFDF8DA4, 0xA3A35C97, 0xEAEAD57E, 0x353558DA, 0xEDEDD07A, 0x4343FC17, 0xF8F8CB66, 0xFBFBB194, 0x3737D3A1, 0xFAFA401D, 0xC2C2683D, 0xB4B4CCF0, 0x32325DDE, 0x9C9C71B3, 0x5656E70B, 0xE3E3DA72, 0x878760A7, 0x15151B1C, 0xF9F93AEF, 0x6363BFD1, 0x3434A953, 0x9A9A853E, 0xB1B1428F, 0x7C7CD133, 0x88889B26, 0x3D3DA65F, 0xA1A1D7EC, 0xE4E4DF76, 0x8181942A, 0x91910149, 0x0F0FFB81, 0xEEEEAA88, 0x161661EE, 0xD7D77321, 0x9797F5C4, 0xA5A5A81A, 0xFEFE3FEB, 0x6D6DB5D9, 0x7878AEC5, 0xC5C56D39, 0x1D1DE599, 0x7676A4CD, 0x3E3EDCAD, 0xCBCB6731, 0xB6B6478B, 0xEFEF5B01, 0x12121E18, 0x6060C523, 0x6A6AB0DD, 0x4D4DF61F, 0xCECEE94E, 0xDEDE7C2D, 0x55559DF9, 0x7E7E5A48, 0x2121B24F, 0x03037AF2, 0xA0A02665, 0x5E5E198E, 0x5A5A6678, 0x65654B5C, 0x62624E58, 0xFDFD4519, 0x0606F48D, 0x404086E5, 0xF2F2BE98, 0x3333AC57, 0x17179067, 0x05058E7F, 0xE8E85E05, 0x4F4F7D64, 0x89896AAF, 0x10109563, 0x74742FB6, 0x0A0A75FE, 0x5C5C92F5, 0x9B9B74B7, 0x2D2D333C, 0x3030D6A5, 0x2E2E49CE, 0x494989E9, 0x46467268, 0x77775544, 0xA8A8D8E0, 0x9696044D, 0x2828BD43, 0xA9A92969, 0xD9D97929, 0x8686912E, 0xD1D187AC, 0xF4F44A15, 0x8D8D1559, 0xD6D682A8, 0xB9B9BC0A, 0x42420D9E, 0xF6F6C16E, 0x2F2FB847, 0xDDDD06DF, 0x23233934, 0xCCCC6235, 0xF1F1C46A, 0xC1C112CF, 0x8585EBDC, 0x8F8F9E22, 0x7171A1C9, 0x9090F0C0, 0xAAAA539B, 0x0101F189, 0x8B8BE1D4, 0x4E4E8CED, 0x8E8E6FAB, 0xABABA212, 0x6F6F3EA2, 0xE6E6540D, 0xDBDBF252, 0x92927BBB, 0xB7B7B602, 0x6969CA2F, 0x3939D9A9, 0xD3D30CD7, 0xA7A72361, 0xA2A2AD1E, 0xC3C399B4, 0x6C6C4450, 0x07070504, 0x04047FF6, 0x272746C2, 0xACACA716, 0xD0D07625, 0x50501386, 0xDCDCF756, 0x84841A55, 0xE1E15109, 0x7A7A25BE, 0x1313EF91 }, { 0xA9D93939, 0x67901717, 0xB3719C9C, 0xE8D2A6A6, 0x04050707, 0xFD985252, 0xA3658080, 0x76DFE4E4, 0x9A084545, 0x92024B4B, 0x80A0E0E0, 0x78665A5A, 0xE4DDAFAF, 0xDDB06A6A, 0xD1BF6363, 0x38362A2A, 0x0D54E6E6, 0xC6432020, 0x3562CCCC, 0x98BEF2F2, 0x181E1212, 0xF724EBEB, 0xECD7A1A1, 0x6C774141, 0x43BD2828, 0x7532BCBC, 0x37D47B7B, 0x269B8888, 0xFA700D0D, 0x13F94444, 0x94B1FBFB, 0x485A7E7E, 0xF27A0303, 0xD0E48C8C, 0x8B47B6B6, 0x303C2424, 0x84A5E7E7, 0x54416B6B, 0xDF06DDDD, 0x23C56060, 0x1945FDFD, 0x5BA33A3A, 0x3D68C2C2, 0x59158D8D, 0xF321ECEC, 0xAE316666, 0xA23E6F6F, 0x82165757, 0x63951010, 0x015BEFEF, 0x834DB8B8, 0x2E918686, 0xD9B56D6D, 0x511F8383, 0x9B53AAAA, 0x7C635D5D, 0xA63B6868, 0xEB3FFEFE, 0xA5D63030, 0xBE257A7A, 0x16A7ACAC, 0x0C0F0909, 0xE335F0F0, 0x6123A7A7, 0xC0F09090, 0x8CAFE9E9, 0x3A809D9D, 0xF5925C5C, 0x73810C0C, 0x2C273131, 0x2576D0D0, 0x0BE75656, 0xBB7B9292, 0x4EE9CECE, 0x89F10101, 0x6B9F1E1E, 0x53A93434, 0x6AC4F1F1, 0xB499C3C3, 0xF1975B5B, 0xE1834747, 0xE66B1818, 0xBDC82222, 0x450E9898, 0xE26E1F1F, 0xF4C9B3B3, 0xB62F7474, 0x66CBF8F8, 0xCCFF9999, 0x95EA1414, 0x03ED5858, 0x56F7DCDC, 0xD4E18B8B, 0x1C1B1515, 0x1EADA2A2, 0xD70CD3D3, 0xFB2BE2E2, 0xC31DC8C8, 0x8E195E5E, 0xB5C22C2C, 0xE9894949, 0xCF12C1C1, 0xBF7E9595, 0xBA207D7D, 0xEA641111, 0x77840B0B, 0x396DC5C5, 0xAF6A8989, 0x33D17C7C, 0xC9A17171, 0x62CEFFFF, 0x7137BBBB, 0x81FB0F0F, 0x793DB5B5, 0x0951E1E1, 0xADDC3E3E, 0x242D3F3F, 0xCDA47676, 0xF99D5555, 0xD8EE8282, 0xE5864040, 0xC5AE7878, 0xB9CD2525, 0x4D049696, 0x44557777, 0x080A0E0E, 0x86135050, 0xE730F7F7, 0xA1D33737, 0x1D40FAFA, 0xAA346161, 0xED8C4E4E, 0x06B3B0B0, 0x706C5454, 0xB22A7373, 0xD2523B3B, 0x410B9F9F, 0x7B8B0202, 0xA088D8D8, 0x114FF3F3, 0x3167CBCB, 0xC2462727, 0x27C06767, 0x90B4FCFC, 0x20283838, 0xF67F0404, 0x60784848, 0xFF2EE5E5, 0x96074C4C, 0x5C4B6565, 0xB1C72B2B, 0xAB6F8E8E, 0x9E0D4242, 0x9CBBF5F5, 0x52F2DBDB, 0x1BF34A4A, 0x5FA63D3D, 0x9359A4A4, 0x0ABCB9B9, 0xEF3AF9F9, 0x91EF1313, 0x85FE0808, 0x49019191, 0xEE611616, 0x2D7CDEDE, 0x4FB22121, 0x8F42B1B1, 0x3BDB7272, 0x47B82F2F, 0x8748BFBF, 0x6D2CAEAE, 0x46E3C0C0, 0xD6573C3C, 0x3E859A9A, 0x6929A9A9, 0x647D4F4F, 0x2A948181, 0xCE492E2E, 0xCB17C6C6, 0x2FCA6969, 0xFCC3BDBD, 0x975CA3A3, 0x055EE8E8, 0x7AD0EDED, 0xAC87D1D1, 0x7F8E0505, 0xD5BA6464, 0x1AA8A5A5, 0x4BB72626, 0x0EB9BEBE, 0xA7608787, 0x5AF8D5D5, 0x28223636, 0x14111B1B, 0x3FDE7575, 0x2979D9D9, 0x88AAEEEE, 0x3C332D2D, 0x4C5F7979, 0x02B6B7B7, 0xB896CACA, 0xDA583535, 0xB09CC4C4, 0x17FC4343, 0x551A8484, 0x1FF64D4D, 0x8A1C5959, 0x7D38B2B2, 0x57AC3333, 0xC718CFCF, 0x8DF40606, 0x74695353, 0xB7749B9B, 0xC4F59797, 0x9F56ADAD, 0x72DAE3E3, 0x7ED5EAEA, 0x154AF4F4, 0x229E8F8F, 0x12A2ABAB, 0x584E6262, 0x07E85F5F, 0x99E51D1D, 0x34392323, 0x6EC1F6F6, 0x50446C6C, 0xDE5D3232, 0x68724646, 0x6526A0A0, 0xBC93CDCD, 0xDB03DADA, 0xF8C6BABA, 0xC8FA9E9E, 0xA882D6D6, 0x2BCF6E6E, 0x40507070, 0xDCEB8585, 0xFE750A0A, 0x328A9393, 0xA48DDFDF, 0xCA4C2929, 0x10141C1C, 0x2173D7D7, 0xF0CCB4B4, 0xD309D4D4, 0x5D108A8A, 0x0FE25151, 0x00000000, 0x6F9A1919, 0x9DE01A1A, 0x368F9494, 0x42E6C7C7, 0x4AECC9C9, 0x5EFDD2D2, 0xC1AB7F7F, 0xE0D8A8A8 }, { 0xBC75BC32, 0xECF3EC21, 0x20C62043, 0xB3F4B3C9, 0xDADBDA03, 0x027B028B, 0xE2FBE22B, 0x9EC89EFA, 0xC94AC9EC, 0xD4D3D409, 0x18E6186B, 0x1E6B1E9F, 0x9845980E, 0xB27DB238, 0xA6E8A6D2, 0x264B26B7, 0x3CD63C57, 0x9332938A, 0x82D882EE, 0x52FD5298, 0x7B377BD4, 0xBB71BB37, 0x5BF15B97, 0x47E14783, 0x2430243C, 0x510F51E2, 0xBAF8BAC6, 0x4A1B4AF3, 0xBF87BF48, 0x0DFA0D70, 0xB006B0B3, 0x753F75DE, 0xD25ED2FD, 0x7DBA7D20, 0x66AE6631, 0x3A5B3AA3, 0x598A591C, 0x00000000, 0xCDBCCD93, 0x1A9D1AE0, 0xAE6DAE2C, 0x7FC17FAB, 0x2BB12BC7, 0xBE0EBEB9, 0xE080E0A0, 0x8A5D8A10, 0x3BD23B52, 0x64D564BA, 0xD8A0D888, 0xE784E7A5, 0x5F075FE8, 0x1B141B11, 0x2CB52CC2, 0xFC90FCB4, 0x312C3127, 0x80A38065, 0x73B2732A, 0x0C730C81, 0x794C795F, 0x6B546B41, 0x4B924B02, 0x53745369, 0x9436948F, 0x8351831F, 0x2A382A36, 0xC4B0C49C, 0x22BD22C8, 0xD55AD5F8, 0xBDFCBDC3, 0x48604878, 0xFF62FFCE, 0x4C964C07, 0x416C4177, 0xC742C7E6, 0xEBF7EB24, 0x1C101C14, 0x5D7C5D63, 0x36283622, 0x672767C0, 0xE98CE9AF, 0x441344F9, 0x149514EA, 0xF59CF5BB, 0xCFC7CF18, 0x3F243F2D, 0xC046C0E3, 0x723B72DB, 0x5470546C, 0x29CA294C, 0xF0E3F035, 0x088508FE, 0xC6CBC617, 0xF311F34F, 0x8CD08CE4, 0xA493A459, 0xCAB8CA96, 0x68A6683B, 0xB883B84D, 0x38203828, 0xE5FFE52E, 0xAD9FAD56, 0x0B770B84, 0xC8C3C81D, 0x99CC99FF, 0x580358ED, 0x196F199A, 0x0E080E0A, 0x95BF957E, 0x70407050, 0xF7E7F730, 0x6E2B6ECF, 0x1FE21F6E, 0xB579B53D, 0x090C090F, 0x61AA6134, 0x57825716, 0x9F419F0B, 0x9D3A9D80, 0x11EA1164, 0x25B925CD, 0xAFE4AFDD, 0x459A4508, 0xDFA4DF8D, 0xA397A35C, 0xEA7EEAD5, 0x35DA3558, 0xED7AEDD0, 0x431743FC, 0xF866F8CB, 0xFB94FBB1, 0x37A137D3, 0xFA1DFA40, 0xC23DC268, 0xB4F0B4CC, 0x32DE325D, 0x9CB39C71, 0x560B56E7, 0xE372E3DA, 0x87A78760, 0x151C151B, 0xF9EFF93A, 0x63D163BF, 0x345334A9, 0x9A3E9A85, 0xB18FB142, 0x7C337CD1, 0x8826889B, 0x3D5F3DA6, 0xA1ECA1D7, 0xE476E4DF, 0x812A8194, 0x91499101, 0x0F810FFB, 0xEE88EEAA, 0x16EE1661, 0xD721D773, 0x97C497F5, 0xA51AA5A8, 0xFEEBFE3F, 0x6DD96DB5, 0x78C578AE, 0xC539C56D, 0x1D991DE5, 0x76CD76A4, 0x3EAD3EDC, 0xCB31CB67, 0xB68BB647, 0xEF01EF5B, 0x1218121E, 0x602360C5, 0x6ADD6AB0, 0x4D1F4DF6, 0xCE4ECEE9, 0xDE2DDE7C, 0x55F9559D, 0x7E487E5A, 0x214F21B2, 0x03F2037A, 0xA065A026, 0x5E8E5E19, 0x5A785A66, 0x655C654B, 0x6258624E, 0xFD19FD45, 0x068D06F4, 0x40E54086, 0xF298F2BE, 0x335733AC, 0x17671790, 0x057F058E, 0xE805E85E, 0x4F644F7D, 0x89AF896A, 0x10631095, 0x74B6742F, 0x0AFE0A75, 0x5CF55C92, 0x9BB79B74, 0x2D3C2D33, 0x30A530D6, 0x2ECE2E49, 0x49E94989, 0x46684672, 0x77447755, 0xA8E0A8D8, 0x964D9604, 0x284328BD, 0xA969A929, 0xD929D979, 0x862E8691, 0xD1ACD187, 0xF415F44A, 0x8D598D15, 0xD6A8D682, 0xB90AB9BC, 0x429E420D, 0xF66EF6C1, 0x2F472FB8, 0xDDDFDD06, 0x23342339, 0xCC35CC62, 0xF16AF1C4, 0xC1CFC112, 0x85DC85EB, 0x8F228F9E, 0x71C971A1, 0x90C090F0, 0xAA9BAA53, 0x018901F1, 0x8BD48BE1, 0x4EED4E8C, 0x8EAB8E6F, 0xAB12ABA2, 0x6FA26F3E, 0xE60DE654, 0xDB52DBF2, 0x92BB927B, 0xB702B7B6, 0x692F69CA, 0x39A939D9, 0xD3D7D30C, 0xA761A723, 0xA21EA2AD, 0xC3B4C399, 0x6C506C44, 0x07040705, 0x04F6047F, 0x27C22746, 0xAC16ACA7, 0xD025D076, 0x50865013, 0xDC56DCF7, 0x8455841A, 0xE109E151, 0x7ABE7A25, 0x139113EF }, { 0xD939A9D9, 0x90176790, 0x719CB371, 0xD2A6E8D2, 0x05070405, 0x9852FD98, 0x6580A365, 0xDFE476DF, 0x08459A08, 0x024B9202, 0xA0E080A0, 0x665A7866, 0xDDAFE4DD, 0xB06ADDB0, 0xBF63D1BF, 0x362A3836, 0x54E60D54, 0x4320C643, 0x62CC3562, 0xBEF298BE, 0x1E12181E, 0x24EBF724, 0xD7A1ECD7, 0x77416C77, 0xBD2843BD, 0x32BC7532, 0xD47B37D4, 0x9B88269B, 0x700DFA70, 0xF94413F9, 0xB1FB94B1, 0x5A7E485A, 0x7A03F27A, 0xE48CD0E4, 0x47B68B47, 0x3C24303C, 0xA5E784A5, 0x416B5441, 0x06DDDF06, 0xC56023C5, 0x45FD1945, 0xA33A5BA3, 0x68C23D68, 0x158D5915, 0x21ECF321, 0x3166AE31, 0x3E6FA23E, 0x16578216, 0x95106395, 0x5BEF015B, 0x4DB8834D, 0x91862E91, 0xB56DD9B5, 0x1F83511F, 0x53AA9B53, 0x635D7C63, 0x3B68A63B, 0x3FFEEB3F, 0xD630A5D6, 0x257ABE25, 0xA7AC16A7, 0x0F090C0F, 0x35F0E335, 0x23A76123, 0xF090C0F0, 0xAFE98CAF, 0x809D3A80, 0x925CF592, 0x810C7381, 0x27312C27, 0x76D02576, 0xE7560BE7, 0x7B92BB7B, 0xE9CE4EE9, 0xF10189F1, 0x9F1E6B9F, 0xA93453A9, 0xC4F16AC4, 0x99C3B499, 0x975BF197, 0x8347E183, 0x6B18E66B, 0xC822BDC8, 0x0E98450E, 0x6E1FE26E, 0xC9B3F4C9, 0x2F74B62F, 0xCBF866CB, 0xFF99CCFF, 0xEA1495EA, 0xED5803ED, 0xF7DC56F7, 0xE18BD4E1, 0x1B151C1B, 0xADA21EAD, 0x0CD3D70C, 0x2BE2FB2B, 0x1DC8C31D, 0x195E8E19, 0xC22CB5C2, 0x8949E989, 0x12C1CF12, 0x7E95BF7E, 0x207DBA20, 0x6411EA64, 0x840B7784, 0x6DC5396D, 0x6A89AF6A, 0xD17C33D1, 0xA171C9A1, 0xCEFF62CE, 0x37BB7137, 0xFB0F81FB, 0x3DB5793D, 0x51E10951, 0xDC3EADDC, 0x2D3F242D, 0xA476CDA4, 0x9D55F99D, 0xEE82D8EE, 0x8640E586, 0xAE78C5AE, 0xCD25B9CD, 0x04964D04, 0x55774455, 0x0A0E080A, 0x13508613, 0x30F7E730, 0xD337A1D3, 0x40FA1D40, 0x3461AA34, 0x8C4EED8C, 0xB3B006B3, 0x6C54706C, 0x2A73B22A, 0x523BD252, 0x0B9F410B, 0x8B027B8B, 0x88D8A088, 0x4FF3114F, 0x67CB3167, 0x4627C246, 0xC06727C0, 0xB4FC90B4, 0x28382028, 0x7F04F67F, 0x78486078, 0x2EE5FF2E, 0x074C9607, 0x4B655C4B, 0xC72BB1C7, 0x6F8EAB6F, 0x0D429E0D, 0xBBF59CBB, 0xF2DB52F2, 0xF34A1BF3, 0xA63D5FA6, 0x59A49359, 0xBCB90ABC, 0x3AF9EF3A, 0xEF1391EF, 0xFE0885FE, 0x01914901, 0x6116EE61, 0x7CDE2D7C, 0xB2214FB2, 0x42B18F42, 0xDB723BDB, 0xB82F47B8, 0x48BF8748, 0x2CAE6D2C, 0xE3C046E3, 0x573CD657, 0x859A3E85, 0x29A96929, 0x7D4F647D, 0x94812A94, 0x492ECE49, 0x17C6CB17, 0xCA692FCA, 0xC3BDFCC3, 0x5CA3975C, 0x5EE8055E, 0xD0ED7AD0, 0x87D1AC87, 0x8E057F8E, 0xBA64D5BA, 0xA8A51AA8, 0xB7264BB7, 0xB9BE0EB9, 0x6087A760, 0xF8D55AF8, 0x22362822, 0x111B1411, 0xDE753FDE, 0x79D92979, 0xAAEE88AA, 0x332D3C33, 0x5F794C5F, 0xB6B702B6, 0x96CAB896, 0x5835DA58, 0x9CC4B09C, 0xFC4317FC, 0x1A84551A, 0xF64D1FF6, 0x1C598A1C, 0x38B27D38, 0xAC3357AC, 0x18CFC718, 0xF4068DF4, 0x69537469, 0x749BB774, 0xF597C4F5, 0x56AD9F56, 0xDAE372DA, 0xD5EA7ED5, 0x4AF4154A, 0x9E8F229E, 0xA2AB12A2, 0x4E62584E, 0xE85F07E8, 0xE51D99E5, 0x39233439, 0xC1F66EC1, 0x446C5044, 0x5D32DE5D, 0x72466872, 0x26A06526, 0x93CDBC93, 0x03DADB03, 0xC6BAF8C6, 0xFA9EC8FA, 0x82D6A882, 0xCF6E2BCF, 0x50704050, 0xEB85DCEB, 0x750AFE75, 0x8A93328A, 0x8DDFA48D, 0x4C29CA4C, 0x141C1014, 0x73D72173, 0xCCB4F0CC, 0x09D4D309, 0x108A5D10, 0xE2510FE2, 0x00000000, 0x9A196F9A, 0xE01A9DE0, 0x8F94368F, 0xE6C742E6, 0xECC94AEC, 0xFDD25EFD, 0xAB7FC1AB, 0xD8A8E0D8 } }; /* The exp_to_poly and poly_to_exp tables are used to perform efficient * operations in GF(2^8) represented as GF(2)[x]/w(x) where * w(x)=x^8+x^6+x^3+x^2+1. We care about doing that because it's part of the * definition of the RS matrix in the key schedule. Elements of that field * are polynomials of degree not greater than 7 and all coefficients 0 or 1, * which can be represented naturally by bytes (just substitute x=2). In that * form, GF(2^8) addition is the same as bitwise XOR, but GF(2^8) * multiplication is inefficient without hardware support. To multiply * faster, I make use of the fact x is a generator for the nonzero elements, * so that every element p of GF(2)[x]/w(x) is either 0 or equal to (x)^n for * some n in 0..254. Note that that caret is exponentiation in GF(2^8), * *not* polynomial notation. So if I want to compute pq where p and q are * in GF(2^8), I can just say: * 1. if p=0 or q=0 then pq=0 * 2. otherwise, find m and n such that p=x^m and q=x^n * 3. pq=(x^m)(x^n)=x^(m+n), so add m and n and find pq * The translations in steps 2 and 3 are looked up in the tables * poly_to_exp (for step 2) and exp_to_poly (for step 3). To see this * in action, look at the CALC_S macro. As additional wrinkles, note that * one of my operands is always a constant, so the poly_to_exp lookup on it * is done in advance; I included the original values in the comments so * readers can have some chance of recognizing that this *is* the RS matrix * from the Twofish paper. I've only included the table entries I actually * need; I never do a lookup on a variable input of zero and the biggest * exponents I'll ever see are 254 (variable) and 237 (constant), so they'll * never sum to more than 491. I'm repeating part of the exp_to_poly table * so that I don't have to do mod-255 reduction in the exponent arithmetic. * Since I know my constant operands are never zero, I only have to worry * about zero values in the variable operand, and I do it with a simple * conditional branch. I know conditionals are expensive, but I couldn't * see a non-horrible way of avoiding them, and I did manage to group the * statements so that each if covers four group multiplications. */ static const u8 poly_to_exp[255] = { 0x00, 0x01, 0x17, 0x02, 0x2E, 0x18, 0x53, 0x03, 0x6A, 0x2F, 0x93, 0x19, 0x34, 0x54, 0x45, 0x04, 0x5C, 0x6B, 0xB6, 0x30, 0xA6, 0x94, 0x4B, 0x1A, 0x8C, 0x35, 0x81, 0x55, 0xAA, 0x46, 0x0D, 0x05, 0x24, 0x5D, 0x87, 0x6C, 0x9B, 0xB7, 0xC1, 0x31, 0x2B, 0xA7, 0xA3, 0x95, 0x98, 0x4C, 0xCA, 0x1B, 0xE6, 0x8D, 0x73, 0x36, 0xCD, 0x82, 0x12, 0x56, 0x62, 0xAB, 0xF0, 0x47, 0x4F, 0x0E, 0xBD, 0x06, 0xD4, 0x25, 0xD2, 0x5E, 0x27, 0x88, 0x66, 0x6D, 0xD6, 0x9C, 0x79, 0xB8, 0x08, 0xC2, 0xDF, 0x32, 0x68, 0x2C, 0xFD, 0xA8, 0x8A, 0xA4, 0x5A, 0x96, 0x29, 0x99, 0x22, 0x4D, 0x60, 0xCB, 0xE4, 0x1C, 0x7B, 0xE7, 0x3B, 0x8E, 0x9E, 0x74, 0xF4, 0x37, 0xD8, 0xCE, 0xF9, 0x83, 0x6F, 0x13, 0xB2, 0x57, 0xE1, 0x63, 0xDC, 0xAC, 0xC4, 0xF1, 0xAF, 0x48, 0x0A, 0x50, 0x42, 0x0F, 0xBA, 0xBE, 0xC7, 0x07, 0xDE, 0xD5, 0x78, 0x26, 0x65, 0xD3, 0xD1, 0x5F, 0xE3, 0x28, 0x21, 0x89, 0x59, 0x67, 0xFC, 0x6E, 0xB1, 0xD7, 0xF8, 0x9D, 0xF3, 0x7A, 0x3A, 0xB9, 0xC6, 0x09, 0x41, 0xC3, 0xAE, 0xE0, 0xDB, 0x33, 0x44, 0x69, 0x92, 0x2D, 0x52, 0xFE, 0x16, 0xA9, 0x0C, 0x8B, 0x80, 0xA5, 0x4A, 0x5B, 0xB5, 0x97, 0xC9, 0x2A, 0xA2, 0x9A, 0xC0, 0x23, 0x86, 0x4E, 0xBC, 0x61, 0xEF, 0xCC, 0x11, 0xE5, 0x72, 0x1D, 0x3D, 0x7C, 0xEB, 0xE8, 0xE9, 0x3C, 0xEA, 0x8F, 0x7D, 0x9F, 0xEC, 0x75, 0x1E, 0xF5, 0x3E, 0x38, 0xF6, 0xD9, 0x3F, 0xCF, 0x76, 0xFA, 0x1F, 0x84, 0xA0, 0x70, 0xED, 0x14, 0x90, 0xB3, 0x7E, 0x58, 0xFB, 0xE2, 0x20, 0x64, 0xD0, 0xDD, 0x77, 0xAD, 0xDA, 0xC5, 0x40, 0xF2, 0x39, 0xB0, 0xF7, 0x49, 0xB4, 0x0B, 0x7F, 0x51, 0x15, 0x43, 0x91, 0x10, 0x71, 0xBB, 0xEE, 0xBF, 0x85, 0xC8, 0xA1 }; static const u8 exp_to_poly[492] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x4D, 0x9A, 0x79, 0xF2, 0xA9, 0x1F, 0x3E, 0x7C, 0xF8, 0xBD, 0x37, 0x6E, 0xDC, 0xF5, 0xA7, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xCD, 0xD7, 0xE3, 0x8B, 0x5B, 0xB6, 0x21, 0x42, 0x84, 0x45, 0x8A, 0x59, 0xB2, 0x29, 0x52, 0xA4, 0x05, 0x0A, 0x14, 0x28, 0x50, 0xA0, 0x0D, 0x1A, 0x34, 0x68, 0xD0, 0xED, 0x97, 0x63, 0xC6, 0xC1, 0xCF, 0xD3, 0xEB, 0x9B, 0x7B, 0xF6, 0xA1, 0x0F, 0x1E, 0x3C, 0x78, 0xF0, 0xAD, 0x17, 0x2E, 0x5C, 0xB8, 0x3D, 0x7A, 0xF4, 0xA5, 0x07, 0x0E, 0x1C, 0x38, 0x70, 0xE0, 0x8D, 0x57, 0xAE, 0x11, 0x22, 0x44, 0x88, 0x5D, 0xBA, 0x39, 0x72, 0xE4, 0x85, 0x47, 0x8E, 0x51, 0xA2, 0x09, 0x12, 0x24, 0x48, 0x90, 0x6D, 0xDA, 0xF9, 0xBF, 0x33, 0x66, 0xCC, 0xD5, 0xE7, 0x83, 0x4B, 0x96, 0x61, 0xC2, 0xC9, 0xDF, 0xF3, 0xAB, 0x1B, 0x36, 0x6C, 0xD8, 0xFD, 0xB7, 0x23, 0x46, 0x8C, 0x55, 0xAA, 0x19, 0x32, 0x64, 0xC8, 0xDD, 0xF7, 0xA3, 0x0B, 0x16, 0x2C, 0x58, 0xB0, 0x2D, 0x5A, 0xB4, 0x25, 0x4A, 0x94, 0x65, 0xCA, 0xD9, 0xFF, 0xB3, 0x2B, 0x56, 0xAC, 0x15, 0x2A, 0x54, 0xA8, 0x1D, 0x3A, 0x74, 0xE8, 0x9D, 0x77, 0xEE, 0x91, 0x6F, 0xDE, 0xF1, 0xAF, 0x13, 0x26, 0x4C, 0x98, 0x7D, 0xFA, 0xB9, 0x3F, 0x7E, 0xFC, 0xB5, 0x27, 0x4E, 0x9C, 0x75, 0xEA, 0x99, 0x7F, 0xFE, 0xB1, 0x2F, 0x5E, 0xBC, 0x35, 0x6A, 0xD4, 0xE5, 0x87, 0x43, 0x86, 0x41, 0x82, 0x49, 0x92, 0x69, 0xD2, 0xE9, 0x9F, 0x73, 0xE6, 0x81, 0x4F, 0x9E, 0x71, 0xE2, 0x89, 0x5F, 0xBE, 0x31, 0x62, 0xC4, 0xC5, 0xC7, 0xC3, 0xCB, 0xDB, 0xFB, 0xBB, 0x3B, 0x76, 0xEC, 0x95, 0x67, 0xCE, 0xD1, 0xEF, 0x93, 0x6B, 0xD6, 0xE1, 0x8F, 0x53, 0xA6, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x4D, 0x9A, 0x79, 0xF2, 0xA9, 0x1F, 0x3E, 0x7C, 0xF8, 0xBD, 0x37, 0x6E, 0xDC, 0xF5, 0xA7, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xCD, 0xD7, 0xE3, 0x8B, 0x5B, 0xB6, 0x21, 0x42, 0x84, 0x45, 0x8A, 0x59, 0xB2, 0x29, 0x52, 0xA4, 0x05, 0x0A, 0x14, 0x28, 0x50, 0xA0, 0x0D, 0x1A, 0x34, 0x68, 0xD0, 0xED, 0x97, 0x63, 0xC6, 0xC1, 0xCF, 0xD3, 0xEB, 0x9B, 0x7B, 0xF6, 0xA1, 0x0F, 0x1E, 0x3C, 0x78, 0xF0, 0xAD, 0x17, 0x2E, 0x5C, 0xB8, 0x3D, 0x7A, 0xF4, 0xA5, 0x07, 0x0E, 0x1C, 0x38, 0x70, 0xE0, 0x8D, 0x57, 0xAE, 0x11, 0x22, 0x44, 0x88, 0x5D, 0xBA, 0x39, 0x72, 0xE4, 0x85, 0x47, 0x8E, 0x51, 0xA2, 0x09, 0x12, 0x24, 0x48, 0x90, 0x6D, 0xDA, 0xF9, 0xBF, 0x33, 0x66, 0xCC, 0xD5, 0xE7, 0x83, 0x4B, 0x96, 0x61, 0xC2, 0xC9, 0xDF, 0xF3, 0xAB, 0x1B, 0x36, 0x6C, 0xD8, 0xFD, 0xB7, 0x23, 0x46, 0x8C, 0x55, 0xAA, 0x19, 0x32, 0x64, 0xC8, 0xDD, 0xF7, 0xA3, 0x0B, 0x16, 0x2C, 0x58, 0xB0, 0x2D, 0x5A, 0xB4, 0x25, 0x4A, 0x94, 0x65, 0xCA, 0xD9, 0xFF, 0xB3, 0x2B, 0x56, 0xAC, 0x15, 0x2A, 0x54, 0xA8, 0x1D, 0x3A, 0x74, 0xE8, 0x9D, 0x77, 0xEE, 0x91, 0x6F, 0xDE, 0xF1, 0xAF, 0x13, 0x26, 0x4C, 0x98, 0x7D, 0xFA, 0xB9, 0x3F, 0x7E, 0xFC, 0xB5, 0x27, 0x4E, 0x9C, 0x75, 0xEA, 0x99, 0x7F, 0xFE, 0xB1, 0x2F, 0x5E, 0xBC, 0x35, 0x6A, 0xD4, 0xE5, 0x87, 0x43, 0x86, 0x41, 0x82, 0x49, 0x92, 0x69, 0xD2, 0xE9, 0x9F, 0x73, 0xE6, 0x81, 0x4F, 0x9E, 0x71, 0xE2, 0x89, 0x5F, 0xBE, 0x31, 0x62, 0xC4, 0xC5, 0xC7, 0xC3, 0xCB }; /* The table constants are indices of * S-box entries, preprocessed through q0 and q1. */ static const u8 calc_sb_tbl[512] = { 0xA9, 0x75, 0x67, 0xF3, 0xB3, 0xC6, 0xE8, 0xF4, 0x04, 0xDB, 0xFD, 0x7B, 0xA3, 0xFB, 0x76, 0xC8, 0x9A, 0x4A, 0x92, 0xD3, 0x80, 0xE6, 0x78, 0x6B, 0xE4, 0x45, 0xDD, 0x7D, 0xD1, 0xE8, 0x38, 0x4B, 0x0D, 0xD6, 0xC6, 0x32, 0x35, 0xD8, 0x98, 0xFD, 0x18, 0x37, 0xF7, 0x71, 0xEC, 0xF1, 0x6C, 0xE1, 0x43, 0x30, 0x75, 0x0F, 0x37, 0xF8, 0x26, 0x1B, 0xFA, 0x87, 0x13, 0xFA, 0x94, 0x06, 0x48, 0x3F, 0xF2, 0x5E, 0xD0, 0xBA, 0x8B, 0xAE, 0x30, 0x5B, 0x84, 0x8A, 0x54, 0x00, 0xDF, 0xBC, 0x23, 0x9D, 0x19, 0x6D, 0x5B, 0xC1, 0x3D, 0xB1, 0x59, 0x0E, 0xF3, 0x80, 0xAE, 0x5D, 0xA2, 0xD2, 0x82, 0xD5, 0x63, 0xA0, 0x01, 0x84, 0x83, 0x07, 0x2E, 0x14, 0xD9, 0xB5, 0x51, 0x90, 0x9B, 0x2C, 0x7C, 0xA3, 0xA6, 0xB2, 0xEB, 0x73, 0xA5, 0x4C, 0xBE, 0x54, 0x16, 0x92, 0x0C, 0x74, 0xE3, 0x36, 0x61, 0x51, 0xC0, 0x38, 0x8C, 0xB0, 0x3A, 0xBD, 0xF5, 0x5A, 0x73, 0xFC, 0x2C, 0x60, 0x25, 0x62, 0x0B, 0x96, 0xBB, 0x6C, 0x4E, 0x42, 0x89, 0xF7, 0x6B, 0x10, 0x53, 0x7C, 0x6A, 0x28, 0xB4, 0x27, 0xF1, 0x8C, 0xE1, 0x13, 0xE6, 0x95, 0xBD, 0x9C, 0x45, 0xC7, 0xE2, 0x24, 0xF4, 0x46, 0xB6, 0x3B, 0x66, 0x70, 0xCC, 0xCA, 0x95, 0xE3, 0x03, 0x85, 0x56, 0xCB, 0xD4, 0x11, 0x1C, 0xD0, 0x1E, 0x93, 0xD7, 0xB8, 0xFB, 0xA6, 0xC3, 0x83, 0x8E, 0x20, 0xB5, 0xFF, 0xE9, 0x9F, 0xCF, 0x77, 0xBF, 0xC3, 0xBA, 0xCC, 0xEA, 0x03, 0x77, 0x6F, 0x39, 0x08, 0xAF, 0xBF, 0x33, 0x40, 0xC9, 0xE7, 0x62, 0x2B, 0x71, 0xE2, 0x81, 0x79, 0x79, 0x0C, 0x09, 0xAA, 0xAD, 0x82, 0x24, 0x41, 0xCD, 0x3A, 0xF9, 0xEA, 0xD8, 0xB9, 0xE5, 0xE4, 0xC5, 0x9A, 0xB9, 0xA4, 0x4D, 0x97, 0x44, 0x7E, 0x08, 0xDA, 0x86, 0x7A, 0xE7, 0x17, 0xA1, 0x66, 0x1D, 0x94, 0xAA, 0xA1, 0xED, 0x1D, 0x06, 0x3D, 0x70, 0xF0, 0xB2, 0xDE, 0xD2, 0xB3, 0x41, 0x0B, 0x7B, 0x72, 0xA0, 0xA7, 0x11, 0x1C, 0x31, 0xEF, 0xC2, 0xD1, 0x27, 0x53, 0x90, 0x3E, 0x20, 0x8F, 0xF6, 0x33, 0x60, 0x26, 0xFF, 0x5F, 0x96, 0xEC, 0x5C, 0x76, 0xB1, 0x2A, 0xAB, 0x49, 0x9E, 0x81, 0x9C, 0x88, 0x52, 0xEE, 0x1B, 0x21, 0x5F, 0xC4, 0x93, 0x1A, 0x0A, 0xEB, 0xEF, 0xD9, 0x91, 0xC5, 0x85, 0x39, 0x49, 0x99, 0xEE, 0xCD, 0x2D, 0xAD, 0x4F, 0x31, 0x8F, 0x8B, 0x3B, 0x01, 0x47, 0x18, 0x87, 0x23, 0x6D, 0xDD, 0x46, 0x1F, 0xD6, 0x4E, 0x3E, 0x2D, 0x69, 0xF9, 0x64, 0x48, 0x2A, 0x4F, 0xCE, 0xF2, 0xCB, 0x65, 0x2F, 0x8E, 0xFC, 0x78, 0x97, 0x5C, 0x05, 0x58, 0x7A, 0x19, 0xAC, 0x8D, 0x7F, 0xE5, 0xD5, 0x98, 0x1A, 0x57, 0x4B, 0x67, 0x0E, 0x7F, 0xA7, 0x05, 0x5A, 0x64, 0x28, 0xAF, 0x14, 0x63, 0x3F, 0xB6, 0x29, 0xFE, 0x88, 0xF5, 0x3C, 0xB7, 0x4C, 0x3C, 0x02, 0xA5, 0xB8, 0xCE, 0xDA, 0xE9, 0xB0, 0x68, 0x17, 0x44, 0x55, 0xE0, 0x1F, 0x4D, 0x8A, 0x43, 0x7D, 0x69, 0x57, 0x29, 0xC7, 0x2E, 0x8D, 0xAC, 0x74, 0x15, 0xB7, 0x59, 0xC4, 0xA8, 0x9F, 0x0A, 0x72, 0x9E, 0x7E, 0x6E, 0x15, 0x47, 0x22, 0xDF, 0x12, 0x34, 0x58, 0x35, 0x07, 0x6A, 0x99, 0xCF, 0x34, 0xDC, 0x6E, 0x22, 0x50, 0xC9, 0xDE, 0xC0, 0x68, 0x9B, 0x65, 0x89, 0xBC, 0xD4, 0xDB, 0xED, 0xF8, 0xAB, 0xC8, 0x12, 0xA8, 0xA2, 0x2B, 0x0D, 0x40, 0x52, 0xDC, 0xBB, 0xFE, 0x02, 0x32, 0x2F, 0xA4, 0xA9, 0xCA, 0xD7, 0x10, 0x61, 0x21, 0x1E, 0xF0, 0xB4, 0xD3, 0x50, 0x5D, 0x04, 0x0F, 0xF6, 0x00, 0xC2, 0x6F, 0x16, 0x9D, 0x25, 0x36, 0x86, 0x42, 0x56, 0x4A, 0x55, 0x5E, 0x09, 0xC1, 0xBE, 0xE0, 0x91 }; /* Macro to perform one column of the RS matrix multiplication. The * parameters a, b, c, and d are the four bytes of output; i is the index * of the key bytes, and w, x, y, and z, are the column of constants from * the RS matrix, preprocessed through the poly_to_exp table. */ #define CALC_S(a, b, c, d, i, w, x, y, z) \ if (key[i]) { \ tmp = poly_to_exp[key[i] - 1]; \ (a) ^= exp_to_poly[tmp + (w)]; \ (b) ^= exp_to_poly[tmp + (x)]; \ (c) ^= exp_to_poly[tmp + (y)]; \ (d) ^= exp_to_poly[tmp + (z)]; \ } /* Macros to calculate the key-dependent S-boxes for a 128-bit key using * the S vector from CALC_S. CALC_SB_2 computes a single entry in all * four S-boxes, where i is the index of the entry to compute, and a and b * are the index numbers preprocessed through the q0 and q1 tables * respectively. */ #define CALC_SB_2(i, a, b) \ do { \ ctx->s[0][i] = mds[0][q0[(a) ^ sa] ^ se]; \ ctx->s[1][i] = mds[1][q0[(b) ^ sb] ^ sf]; \ ctx->s[2][i] = mds[2][q1[(a) ^ sc] ^ sg]; \ ctx->s[3][i] = mds[3][q1[(b) ^ sd] ^ sh]; \ } while (0) /* Macro exactly like CALC_SB_2, but for 192-bit keys. */ #define CALC_SB192_2(i, a, b) \ do { \ ctx->s[0][i] = mds[0][q0[q0[(b) ^ sa] ^ se] ^ si]; \ ctx->s[1][i] = mds[1][q0[q1[(b) ^ sb] ^ sf] ^ sj]; \ ctx->s[2][i] = mds[2][q1[q0[(a) ^ sc] ^ sg] ^ sk]; \ ctx->s[3][i] = mds[3][q1[q1[(a) ^ sd] ^ sh] ^ sl]; \ } while (0) /* Macro exactly like CALC_SB_2, but for 256-bit keys. */ #define CALC_SB256_2(i, a, b) \ do { \ ctx->s[0][i] = mds[0][q0[q0[q1[(b) ^ sa] ^ se] ^ si] ^ sm]; \ ctx->s[1][i] = mds[1][q0[q1[q1[(a) ^ sb] ^ sf] ^ sj] ^ sn]; \ ctx->s[2][i] = mds[2][q1[q0[q0[(a) ^ sc] ^ sg] ^ sk] ^ so]; \ ctx->s[3][i] = mds[3][q1[q1[q0[(b) ^ sd] ^ sh] ^ sl] ^ sp]; \ } while (0) /* Macros to calculate the whitening and round subkeys. CALC_K_2 computes the * last two stages of the h() function for a given index (either 2i or 2i+1). * a, b, c, and d are the four bytes going into the last two stages. For * 128-bit keys, this is the entire h() function and a and c are the index * preprocessed through q0 and q1 respectively; for longer keys they are the * output of previous stages. j is the index of the first key byte to use. * CALC_K computes a pair of subkeys for 128-bit Twofish, by calling CALC_K_2 * twice, doing the Psuedo-Hadamard Transform, and doing the necessary * rotations. Its parameters are: a, the array to write the results into, * j, the index of the first output entry, k and l, the preprocessed indices * for index 2i, and m and n, the preprocessed indices for index 2i+1. * CALC_K192_2 expands CALC_K_2 to handle 192-bit keys, by doing an * additional lookup-and-XOR stage. The parameters a, b, c and d are the * four bytes going into the last three stages. For 192-bit keys, c = d * are the index preprocessed through q0, and a = b are the index * preprocessed through q1; j is the index of the first key byte to use. * CALC_K192 is identical to CALC_K but for using the CALC_K192_2 macro * instead of CALC_K_2. * CALC_K256_2 expands CALC_K192_2 to handle 256-bit keys, by doing an * additional lookup-and-XOR stage. The parameters a and b are the index * preprocessed through q0 and q1 respectively; j is the index of the first * key byte to use. CALC_K256 is identical to CALC_K but for using the * CALC_K256_2 macro instead of CALC_K_2. */ #define CALC_K_2(a, b, c, d, j) \ mds[0][q0[a ^ key[(j) + 8]] ^ key[j]] \ ^ mds[1][q0[b ^ key[(j) + 9]] ^ key[(j) + 1]] \ ^ mds[2][q1[c ^ key[(j) + 10]] ^ key[(j) + 2]] \ ^ mds[3][q1[d ^ key[(j) + 11]] ^ key[(j) + 3]] #define CALC_K(a, j, k, l, m, n) \ x = CALC_K_2(k, l, k, l, 0); \ y = CALC_K_2(m, n, m, n, 4); \ y = (y << 8) + (y >> 24); \ x += y; y += x; ctx->a[j] = x; \ ctx->a[(j) + 1] = (y << 9) + (y >> 23) #define CALC_K192_2(a, b, c, d, j) \ CALC_K_2(q0[a ^ key[(j) + 16]], \ q1[b ^ key[(j) + 17]], \ q0[c ^ key[(j) + 18]], \ q1[d ^ key[(j) + 19]], j) #define CALC_K192(a, j, k, l, m, n) \ x = CALC_K192_2(l, l, k, k, 0); \ y = CALC_K192_2(n, n, m, m, 4); \ y = (y << 8) + (y >> 24); \ x += y; y += x; ctx->a[j] = x; \ ctx->a[(j) + 1] = (y << 9) + (y >> 23) #define CALC_K256_2(a, b, j) \ CALC_K192_2(q1[b ^ key[(j) + 24]], \ q1[a ^ key[(j) + 25]], \ q0[a ^ key[(j) + 26]], \ q0[b ^ key[(j) + 27]], j) #define CALC_K256(a, j, k, l, m, n) \ x = CALC_K256_2(k, l, 0); \ y = CALC_K256_2(m, n, 4); \ y = (y << 8) + (y >> 24); \ x += y; y += x; ctx->a[j] = x; \ ctx->a[(j) + 1] = (y << 9) + (y >> 23) /* Perform the key setup. */ int twofish_set_key(TWOFISH_context *ctx, const unsigned char *key, int key_len) { int i, j, k; /* Temporaries for CALC_K. */ u32 x, y; /* The S vector used to key the S-boxes, split up into individual bytes. * 128-bit keys use only sa through sh; 256-bit use all of them. */ u8 sa = 0, sb = 0, sc = 0, sd = 0, se = 0, sf = 0, sg = 0, sh = 0; u8 si = 0, sj = 0, sk = 0, sl = 0, sm = 0, sn = 0, so = 0, sp = 0; /* Temporary for CALC_S. */ u8 tmp; /* Check key length. */ if (key_len != 16 && key_len != 24 && key_len != 32) return -1; /* unsupported key length */ /* Compute the first two words of the S vector. The magic numbers are * the entries of the RS matrix, preprocessed through poly_to_exp. The * numbers in the comments are the original (polynomial form) matrix * entries. */ CALC_S(sa, sb, sc, sd, 0, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ CALC_S(sa, sb, sc, sd, 1, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ CALC_S(sa, sb, sc, sd, 2, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ CALC_S(sa, sb, sc, sd, 3, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ CALC_S(sa, sb, sc, sd, 4, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ CALC_S(sa, sb, sc, sd, 5, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ CALC_S(sa, sb, sc, sd, 6, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ CALC_S(sa, sb, sc, sd, 7, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ CALC_S(se, sf, sg, sh, 8, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ CALC_S(se, sf, sg, sh, 9, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ CALC_S(se, sf, sg, sh, 10, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ CALC_S(se, sf, sg, sh, 11, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ CALC_S(se, sf, sg, sh, 12, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ CALC_S(se, sf, sg, sh, 13, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ CALC_S(se, sf, sg, sh, 14, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ CALC_S(se, sf, sg, sh, 15, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ if (key_len == 24 || key_len == 32) { /* 192- or 256-bit key */ /* Calculate the third word of the S vector */ CALC_S(si, sj, sk, sl, 16, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ CALC_S(si, sj, sk, sl, 17, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ CALC_S(si, sj, sk, sl, 18, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ CALC_S(si, sj, sk, sl, 19, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ CALC_S(si, sj, sk, sl, 20, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ CALC_S(si, sj, sk, sl, 21, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ CALC_S(si, sj, sk, sl, 22, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ CALC_S(si, sj, sk, sl, 23, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ } if (key_len == 32) { /* 256-bit key */ /* Calculate the fourth word of the S vector */ CALC_S(sm, sn, so, sp, 24, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ CALC_S(sm, sn, so, sp, 25, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ CALC_S(sm, sn, so, sp, 26, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ CALC_S(sm, sn, so, sp, 27, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ CALC_S(sm, sn, so, sp, 28, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ CALC_S(sm, sn, so, sp, 29, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ CALC_S(sm, sn, so, sp, 30, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ CALC_S(sm, sn, so, sp, 31, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ /* Compute the S-boxes. */ for ( i = j = 0, k = 1; i < 256; i++, j += 2, k += 2 ) CALC_SB256_2( i, calc_sb_tbl[j], calc_sb_tbl[k] ); /* Calculate whitening and round subkeys. The constants are * indices of subkeys, preprocessed through q0 and q1. */ CALC_K256(w, 0, 0xA9, 0x75, 0x67, 0xF3); CALC_K256(w, 2, 0xB3, 0xC6, 0xE8, 0xF4); CALC_K256(w, 4, 0x04, 0xDB, 0xFD, 0x7B); CALC_K256(w, 6, 0xA3, 0xFB, 0x76, 0xC8); CALC_K256(k, 0, 0x9A, 0x4A, 0x92, 0xD3); CALC_K256(k, 2, 0x80, 0xE6, 0x78, 0x6B); CALC_K256(k, 4, 0xE4, 0x45, 0xDD, 0x7D); CALC_K256(k, 6, 0xD1, 0xE8, 0x38, 0x4B); CALC_K256(k, 8, 0x0D, 0xD6, 0xC6, 0x32); CALC_K256(k, 10, 0x35, 0xD8, 0x98, 0xFD); CALC_K256(k, 12, 0x18, 0x37, 0xF7, 0x71); CALC_K256(k, 14, 0xEC, 0xF1, 0x6C, 0xE1); CALC_K256(k, 16, 0x43, 0x30, 0x75, 0x0F); CALC_K256(k, 18, 0x37, 0xF8, 0x26, 0x1B); CALC_K256(k, 20, 0xFA, 0x87, 0x13, 0xFA); CALC_K256(k, 22, 0x94, 0x06, 0x48, 0x3F); CALC_K256(k, 24, 0xF2, 0x5E, 0xD0, 0xBA); CALC_K256(k, 26, 0x8B, 0xAE, 0x30, 0x5B); CALC_K256(k, 28, 0x84, 0x8A, 0x54, 0x00); CALC_K256(k, 30, 0xDF, 0xBC, 0x23, 0x9D); } else if (key_len == 24) { /* 192-bit key */ /* Compute the S-boxes. */ for ( i = j = 0, k = 1; i < 256; i++, j += 2, k += 2 ) CALC_SB192_2( i, calc_sb_tbl[j], calc_sb_tbl[k] ); /* Calculate whitening and round subkeys. The constants are * indices of subkeys, preprocessed through q0 and q1. */ CALC_K192(w, 0, 0xA9, 0x75, 0x67, 0xF3); CALC_K192(w, 2, 0xB3, 0xC6, 0xE8, 0xF4); CALC_K192(w, 4, 0x04, 0xDB, 0xFD, 0x7B); CALC_K192(w, 6, 0xA3, 0xFB, 0x76, 0xC8); CALC_K192(k, 0, 0x9A, 0x4A, 0x92, 0xD3); CALC_K192(k, 2, 0x80, 0xE6, 0x78, 0x6B); CALC_K192(k, 4, 0xE4, 0x45, 0xDD, 0x7D); CALC_K192(k, 6, 0xD1, 0xE8, 0x38, 0x4B); CALC_K192(k, 8, 0x0D, 0xD6, 0xC6, 0x32); CALC_K192(k, 10, 0x35, 0xD8, 0x98, 0xFD); CALC_K192(k, 12, 0x18, 0x37, 0xF7, 0x71); CALC_K192(k, 14, 0xEC, 0xF1, 0x6C, 0xE1); CALC_K192(k, 16, 0x43, 0x30, 0x75, 0x0F); CALC_K192(k, 18, 0x37, 0xF8, 0x26, 0x1B); CALC_K192(k, 20, 0xFA, 0x87, 0x13, 0xFA); CALC_K192(k, 22, 0x94, 0x06, 0x48, 0x3F); CALC_K192(k, 24, 0xF2, 0x5E, 0xD0, 0xBA); CALC_K192(k, 26, 0x8B, 0xAE, 0x30, 0x5B); CALC_K192(k, 28, 0x84, 0x8A, 0x54, 0x00); CALC_K192(k, 30, 0xDF, 0xBC, 0x23, 0x9D); } else { /* 128-bit key */ /* Compute the S-boxes. */ for ( i = j = 0, k = 1; i < 256; i++, j += 2, k += 2 ) CALC_SB_2( i, calc_sb_tbl[j], calc_sb_tbl[k] ); /* Calculate whitening and round subkeys. The constants are * indices of subkeys, preprocessed through q0 and q1. */ CALC_K(w, 0, 0xA9, 0x75, 0x67, 0xF3); CALC_K(w, 2, 0xB3, 0xC6, 0xE8, 0xF4); CALC_K(w, 4, 0x04, 0xDB, 0xFD, 0x7B); CALC_K(w, 6, 0xA3, 0xFB, 0x76, 0xC8); CALC_K(k, 0, 0x9A, 0x4A, 0x92, 0xD3); CALC_K(k, 2, 0x80, 0xE6, 0x78, 0x6B); CALC_K(k, 4, 0xE4, 0x45, 0xDD, 0x7D); CALC_K(k, 6, 0xD1, 0xE8, 0x38, 0x4B); CALC_K(k, 8, 0x0D, 0xD6, 0xC6, 0x32); CALC_K(k, 10, 0x35, 0xD8, 0x98, 0xFD); CALC_K(k, 12, 0x18, 0x37, 0xF7, 0x71); CALC_K(k, 14, 0xEC, 0xF1, 0x6C, 0xE1); CALC_K(k, 16, 0x43, 0x30, 0x75, 0x0F); CALC_K(k, 18, 0x37, 0xF8, 0x26, 0x1B); CALC_K(k, 20, 0xFA, 0x87, 0x13, 0xFA); CALC_K(k, 22, 0x94, 0x06, 0x48, 0x3F); CALC_K(k, 24, 0xF2, 0x5E, 0xD0, 0xBA); CALC_K(k, 26, 0x8B, 0xAE, 0x30, 0x5B); CALC_K(k, 28, 0x84, 0x8A, 0x54, 0x00); CALC_K(k, 30, 0xDF, 0xBC, 0x23, 0x9D); } return 0; } /* Macros to compute the g() function in the encryption and decryption * rounds. G1 is the straight g() function; G2 includes the 8-bit * rotation for the high 32-bit word. */ #define G1(a) \ (ctx->s[0][(a) & 0xFF]) ^ (ctx->s[1][((a) >> 8) & 0xFF]) \ ^ (ctx->s[2][((a) >> 16) & 0xFF]) ^ (ctx->s[3][(a) >> 24]) #define G2(b) \ (ctx->s[1][(b) & 0xFF]) ^ (ctx->s[2][((b) >> 8) & 0xFF]) \ ^ (ctx->s[3][((b) >> 16) & 0xFF]) ^ (ctx->s[0][(b) >> 24]) /* Encryption and decryption Feistel rounds. Each one calls the two g() * macros, does the PHT, and performs the XOR and the appropriate bit * rotations. The parameters are the round number (used to select subkeys), * and the four 32-bit chunks of the text. */ #define ENCROUND(n, a, b, c, d) \ x = G1(a); y = G2(b); \ x += y; y += x + ctx->k[2 * (n) + 1]; \ (c) ^= x + ctx->k[2 * (n)]; \ (c) = ((c) >> 1) + ((c) << 31); \ (d) = (((d) << 1) + ((d) >> 31)) ^ y #define DECROUND(n, a, b, c, d) \ x = G1(a); y = G2(b); \ x += y; y += x; \ (d) ^= y + ctx->k[2 * (n) + 1]; \ (d) = ((d) >> 1) + ((d) << 31); \ (c) = (((c) << 1) + ((c) >> 31)); \ (c) ^= (x + ctx->k[2 * (n)]) /* Encryption and decryption cycles; each one is simply two Feistel rounds * with the 32-bit chunks re-ordered to simulate the "swap" */ #define ENCCYCLE(n) \ ENCROUND(2 * (n), a, b, c, d); \ ENCROUND(2 * (n) + 1, c, d, a, b) #define DECCYCLE(n) \ DECROUND(2 * (n) + 1, c, d, a, b); \ DECROUND(2 * (n), a, b, c, d) /* Macros to convert the input and output bytes into 32-bit words, * and simultaneously perform the whitening step. INPACK packs word * number n into the variable named by x, using whitening subkey number m. * OUTUNPACK unpacks word number n from the variable named by x, using * whitening subkey number m. */ #define INPACK(n, x, m) \ x = in[4 * (n)] ^ (in[4 * (n) + 1] << 8) \ ^ (in[4 * (n) + 2] << 16) ^ (in[4 * (n) + 3] << 24) ^ ctx->w[m] #define OUTUNPACK(n, x, m) \ x ^= ctx->w[m]; \ out[4 * (n)] = x; out[4 * (n) + 1] = x >> 8; \ out[4 * (n) + 2] = x >> 16; out[4 * (n) + 3] = x >> 24 /* Encrypt one block. in and out may be the same. */ int twofish_encrypt(TWOFISH_context *ctx, const u8 *in, u8 *out) { /* The four 32-bit chunks of the text. */ u32 a, b, c, d; /* Temporaries used by the round function. */ u32 x, y; /* Input whitening and packing. */ INPACK(0, a, 0); INPACK(1, b, 1); INPACK(2, c, 2); INPACK(3, d, 3); /* Encryption Feistel cycles. */ ENCCYCLE(0); ENCCYCLE(1); ENCCYCLE(2); ENCCYCLE(3); ENCCYCLE(4); ENCCYCLE(5); ENCCYCLE(6); ENCCYCLE(7); /* Output whitening and unpacking. */ OUTUNPACK(0, c, 4); OUTUNPACK(1, d, 5); OUTUNPACK(2, a, 6); OUTUNPACK(3, b, 7); return 0; } /* Decrypt one block. in and out may be the same. */ int twofish_decrypt(TWOFISH_context *ctx, const u8 *in, u8 *out) { /* The four 32-bit chunks of the text. */ u32 a, b, c, d; /* Temporaries used by the round function. */ u32 x, y; /* Input whitening and packing. */ INPACK(0, c, 4); INPACK(1, d, 5); INPACK(2, a, 6); INPACK(3, b, 7); /* Encryption Feistel cycles. */ DECCYCLE(7); DECCYCLE(6); DECCYCLE(5); DECCYCLE(4); DECCYCLE(3); DECCYCLE(2); DECCYCLE(1); DECCYCLE(0); /* Output whitening and unpacking. */ OUTUNPACK(0, a, 0); OUTUNPACK(1, b, 1); OUTUNPACK(2, c, 2); OUTUNPACK(3, d, 3); return 0; } /* eof */ libreswan-3.32/lib/libcrypto/libtwofish/twofish.h000066400000000000000000000014531365625662500222350ustar00rootroot00000000000000#ifndef TWOFISH_H #define TWOFISH_H #ifdef __KERNEL__ #include #else #include #endif /* Structure for an expanded Twofish key. s contains the key-dependent * S-boxes composed with the MDS matrix; w contains the eight "whitening" * subkeys, K[0] through K[7]. k holds the remaining, "round" subkeys. Note * that k[i] corresponds to what the Twofish paper calls K[i+8]. */ typedef struct { u_int32_t s[4][256], w[8], k[32]; } TWOFISH_context; typedef TWOFISH_context twofish_context; int twofish_set_key(twofish_context *tf_ctx, const u_int8_t * in_key, int key_len); int twofish_encrypt(twofish_context *tf_ctx, const u_int8_t * in, u_int8_t * out); int twofish_decrypt(twofish_context * tf_ctx, const u_int8_t * in, u_int8_t * out); #endif /* TWOFISH_H */ libreswan-3.32/lib/libcrypto/libtwofish/twofish_cbc.c000066400000000000000000000003551365625662500230370ustar00rootroot00000000000000#ifdef __KERNEL__ #include #else #include #endif #include "twofish_cbc.h" #include "cbc_generic.h" CBC_IMPL_BLK16(twofish_cbc_encrypt, twofish_context, u_int8_t *, twofish_encrypt, twofish_decrypt); libreswan-3.32/lib/libcrypto/libtwofish/twofish_cbc.h000066400000000000000000000002521365625662500230400ustar00rootroot00000000000000/* Glue header */ #include "twofish.h" int twofish_cbc_encrypt(twofish_context *ctx, const u_int8_t *in, u_int8_t *out, int ilen, const u_int8_t *iv, int encrypt); libreswan-3.32/lib/libipsecconf/000077500000000000000000000000001365625662500166555ustar00rootroot00000000000000libreswan-3.32/lib/libipsecconf/Makefile000066400000000000000000000077111365625662500203230ustar00rootroot00000000000000# Libreswan library for parsing configuration files # # Copyright (C) 2005 Michael Richardson Xelerance Corporation # Copyright (C) 2012 Paul Wouters # Copyright (C) 2015 Andrew Cagney # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. LIBRARY=ipsecconf LIB=lib${LIBRARY}.a MANDIR=$(MANTREE)/man3 CFLAGS += -DXFRM_LIFETIME_DEFAULT=$(XFRM_LIFETIME_DEFAULT) SRCS=confread.c confwrite.c starterwhack.c starterlog.c SRCS+=parser.tab.c lex.yy.c keywords.c SRCS+=interfaces.c OBJS=${SRCS:.c=.o} # pick up generated LEX/YACC files INCLUDES += -I$(builddir) ifdef top_srcdir include ${top_srcdir}/mk/library.mk else include ../../mk/library.mk endif # Hack to force the generated files to be built first. Not too bad # since all the $(OBJS) indirectly depend on the header anyway. $(OBJS): $(builddir)/parser.tab.h # Avoid flex bugs: # # - flex 3.5.4 (centos 5) doesn't allow a space between the '-o' # option and the file name. # # Fortunately later versions of flex seem to handle this. # # - flex < 2.5.35 generates an invalid extern # # Use sed to strip this out. # # - flex on RHEL 7 generates code that provokes GCC to warn # about comparing a signed value with an unsigned value # (Combination of a new GCC and an old flex). # # Adding one cast makes RHEL 6's GCC unhappy, so we add two. # On RHEL 6, i is int and _yybytes_len is int. # On RHEL 7, i is int and _yybytes_len is yy_size_t # On Fedora 21, i is yy_size_t and _yybytes_len is yy_size_t # On some architectures, yy_size_t is wider than int; # which makes a mixed comparison OK. # # - flex 2.6.0-11 and gcc 4:5.3.1-3 on debian testing (2016-06-18) # also warns about comparisons of different kinds, so we add a third # fix. # # - avoid sed -i which somehow causes unwritable files on fedora 20 # with 9p filesystem mount. LEX = flex $(builddir)/lex.yy.c: parser.l : no space between -o and scratch output file $(LEX) -o$@.tmp $< sed -e 's/for ( i = 0; i < _yybytes_len; ++i )$$/for ( i = 0; (yy_size_t)i < (yy_size_t)_yybytes_len; ++i )/' \ -e '/^extern int isatty.*$$/d' \ -e 's/if ((int) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {$$/if (((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {/' \ < $@.tmp > $@.sedtmp rm $@.tmp : install result mv $@.sedtmp $@ # Use wild card rule so that GNU Make knows that both are output from # a single recipe. # - sed command for workaround for older bison vs GCC warning # - avoid sed -i which somehow causes unwritable files # on fedora 20 with 9p filesystem mount # - avoid creating the target file until it is done # - $* matches % # # - run bison from the builddir so that parser.tab.h defines # YY_YY_PARSER_TAB_H_INCLUDED and not a macro containing the # buildpath. See parser-controls.h for why. ifeq ($(USE_YACC),true) BISON=yacc -b parser else BISON=bison endif $(builddir)/%.tab.h $(builddir)/%.tab.c: %.y cd $(builddir) && $(BISON) ${BISONOSFLAGS} -v --defines=$*.tab.h -o $*.tab.c.tmp $(abs_srcdir)/$*.y sed -e '/^ *#/s/if YYENABLE_NLS/if defined(YYENABLE_NLS) \&\& YYENABLE_NLS/' \ -e '/^ *#/s/if YYLTYPE_IS_TRIVIAL/if defined(YYLTYPE_IS_TRIVIAL) \&\& YYLTYPE_IS_TRIVIAL/' \ < $(builddir)/$*.tab.c.tmp > $(builddir)/$*.tab.c.sedtmp rm $(builddir)/$*.tab.c.tmp mv $(builddir)/$*.tab.c.sedtmp $(builddir)/$*.tab.c clean: parser-clean .PHONY: parser-clean parser-clean: cd $(builddir) && $(RM) -f *.tab.[cdho] *.dot *.output lex.yy.[cdho] *tmp libreswan-3.32/lib/libipsecconf/confread.c000066400000000000000000001403611365625662500206070ustar00rootroot00000000000000/* Libreswan config file parser (confread.c) * Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security * Copyright (C) 2004 Xelerance Corporation * Copyright (C) 2006-2008 Michael Richardson * Copyright (C) 2007 Ken Bantoft * Copyright (C) 2006-2012 Paul Wouters * Copyright (C) 2010 Michael Smith * Copyright (C) 2010 Tuomo Soini * Copyright (C) 2012-2019 Paul Wouters * Copyright (C) 2012 Avesh Agarwal * Copyright (C) 2012 Antony Antony * Copyright (C) 2013 Florian Weimer * Copyright (C) 2013 David McCullough * Copyright (C) 2013-2019 D. Hugh Redelmeier * Copyright (C) 2016 Andrew Cagney * Copyright (C) 2017-2018 Vukasin Karadzic * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include #include #include #include #include #include "lswalloc.h" #include "ip_address.h" #include "ip_info.h" #include "ipsecconf/confread.h" #include "ipsecconf/starterlog.h" #include "ipsecconf/interfaces.h" #include "ipsecconf/keywords.h" #include "ipsecconf/parser.h" /* includes parser.tab.h generated by bison; requires keywords.h */ #include "whack.h" /* for DEFAULT_CTL_SOCKET */ #ifdef USE_DNSSEC # include # include /* for inet_ntop */ # include "dnssec.h" #endif /* USE_DNSSEC */ /** * Set up hardcoded defaults, from data in programs/pluto/constants.h * * @param cfg starter_config struct * @return void */ static void ipsecconf_default_values(struct starter_config *cfg) { static const struct starter_config empty_starter_config; /* zero or null everywhere */ *cfg = empty_starter_config; TAILQ_INIT(&cfg->conns); /* ==== config setup ==== */ # define SOPT(kbf, v) { cfg->setup.options[kbf] = (v) ; } SOPT(KBF_FRAGICMP, FALSE); /* see sysctl_ipsec_icmp in ipsec_proc.c */ SOPT(KBF_HIDETOS, TRUE); SOPT(KBF_LOGTIME, TRUE); SOPT(KBF_LOGAPPEND, TRUE); SOPT(KBF_LOGIP, TRUE); SOPT(KBF_AUDIT_LOG, TRUE); SOPT(KBF_UNIQUEIDS, TRUE); SOPT(KBF_DO_DNSSEC, TRUE); SOPT(KBF_PERPEERLOG, FALSE); SOPT(KBF_IKEPORT, IKE_UDP_PORT); SOPT(KBF_IKEBUF, IKE_BUF_AUTO); SOPT(KBF_IKE_ERRQUEUE, TRUE); SOPT(KBF_NFLOG_ALL, 0); /* disabled per default */ SOPT(KBF_XFRMLIFETIME, XFRM_LIFETIME_DEFAULT); /* not used by pluto itself */ SOPT(KBF_NHELPERS, -1); /* see also plutomain.c */ SOPT(KBF_KEEPALIVE, 0); /* config setup */ SOPT(KBF_NATIKEPORT, NAT_IKE_UDP_PORT); SOPT(KBF_DDOS_IKE_THRESHOLD, DEFAULT_IKE_SA_DDOS_THRESHOLD); SOPT(KBF_MAX_HALFOPEN_IKE, DEFAULT_MAXIMUM_HALFOPEN_IKE_SA); SOPT(KBF_SHUNTLIFETIME, PLUTO_SHUNT_LIFE_DURATION_DEFAULT); /* Don't inflict BSI requirements on everyone */ SOPT(KBF_SEEDBITS, 0); SOPT(KBF_DROP_OPPO_NULL, FALSE); #ifdef HAVE_LABELED_IPSEC SOPT(KBF_SECCTX, SECCTX); #endif SOPT(KBF_DDOS_MODE, DDOS_AUTO); SOPT(KBF_OCSP_CACHE_SIZE, OCSP_DEFAULT_CACHE_SIZE); SOPT(KBF_OCSP_CACHE_MIN, OCSP_DEFAULT_CACHE_MIN_AGE); SOPT(KBF_OCSP_CACHE_MAX, OCSP_DEFAULT_CACHE_MAX_AGE); SOPT(KBF_OCSP_METHOD, OCSP_METHOD_GET); SOPT(KBF_OCSP_TIMEOUT, OCSP_DEFAULT_TIMEOUT); SOPT(KBF_SECCOMP, SECCOMP_DISABLED); /* will be enabled in the future */ # undef SOPT cfg->setup.strings[KSF_PLUTO_DNSSEC_ROOTKEY_FILE] = clone_str(DEFAULT_DNSSEC_ROOTKEY_FILE, "dnssec rootkey file"); /* ==== end of config setup ==== */ cfg->ctlsocket = clone_str(DEFAULT_CTL_SOCKET, "default control socket"); /* ==== conn %default ==== */ struct starter_conn *d = &cfg->conn_default; # define DOPT(kbf, v) { d->options[kbf] = (v); } DOPT(KNCF_NAT_KEEPALIVE, TRUE); /* per conn */ DOPT(KNCF_TYPE, KS_TUNNEL); DOPT(KNCF_INITIAL_CONTACT, FALSE); DOPT(KNCF_CISCO_UNITY, FALSE); DOPT(KNCF_NO_ESP_TFC, FALSE); DOPT(KNCF_VID_STRONGSWAN, FALSE); DOPT(KNCF_SEND_VENDORID, FALSE); DOPT(KNCF_REMOTEPEERTYPE, NON_CISCO); DOPT(KNCF_IKEPAD, TRUE); DOPT(KNCF_IKEV1_NATT, NATT_BOTH); DOPT(KNCF_ENCAPS, yna_auto); /* Network Manager support */ #ifdef HAVE_NM DOPT(KNCF_NMCONFIGURED, FALSE); #endif DOPT(KNCF_XAUTHBY, XAUTHBY_FILE); DOPT(KNCF_XAUTHFAIL, XAUTHFAIL_HARD); DOPT(KNCF_NIC_OFFLOAD, yna_auto); DOPT(KNCF_IKELIFETIME, IKE_SA_LIFETIME_DEFAULT); DOPT(KNCF_REPLAY_WINDOW, IPSEC_SA_DEFAULT_REPLAY_WINDOW); DOPT(KNCF_RETRANSMIT_TIMEOUT, RETRANSMIT_TIMEOUT_DEFAULT); DOPT(KNCF_RETRANSMIT_INTERVAL_MS, RETRANSMIT_INTERVAL_DEFAULT_MS); DOPT(KNCF_SALIFETIME, IPSEC_SA_LIFETIME_DEFAULT); DOPT(KNCF_REKEYMARGIN, SA_REPLACEMENT_MARGIN_DEFAULT); DOPT(KNCF_REKEYFUZZ, SA_REPLACEMENT_FUZZ_DEFAULT); DOPT(KNCF_KEYINGTRIES, SA_REPLACEMENT_RETRIES_DEFAULT); DOPT(KNCF_HOSTADDRFAMILY, AF_UNSPEC); DOPT(KNCF_CLIENTADDRFAMILY, AF_UNSPEC); DOPT(KNCF_AUTO, STARTUP_IGNORE); DOPT(KNCF_XFRM_IF_ID, yn_no); # undef DOPT d->policy = POLICY_TUNNEL | POLICY_ECDSA | POLICY_RSASIG | POLICY_RSASIG_v1_5 | /* authby= */ POLICY_ENCRYPT | POLICY_PFS | POLICY_IKEV2_ALLOW | POLICY_SAREF_TRACK | /* sareftrack=yes */ POLICY_IKE_FRAG_ALLOW | /* ike_frag=yes */ POLICY_ESN_NO; /* esn=no */ d->sighash_policy = POL_SIGHASH_SHA2_256 | POL_SIGHASH_SHA2_384 | POL_SIGHASH_SHA2_512; d->left.addr_family = AF_INET; d->left.addr = address_any(&ipv4_info); d->left.nexttype = KH_NOTSET; d->left.nexthop = address_any(&ipv4_info); d->right.addr_family = AF_INET; d->right.addr = address_any(&ipv4_info); d->right.nexttype = KH_NOTSET; d->right.nexthop = address_any(&ipv4_info); /* default is NOT to look in DNS */ d->left.key_from_DNS_on_demand = FALSE; d->right.key_from_DNS_on_demand = FALSE; d->state = STATE_LOADED; d->left.authby = AUTH_UNSET; d->right.authby = AUTH_UNSET; d->left.updown = clone_str(DEFAULT_UPDOWN, "conn default left updown"); d->right.updown = clone_str(DEFAULT_UPDOWN, "conn default right updown"); /* ==== end of conn %default ==== */ } /* * format error, and append to string of errors * The messages are separated by newline: not perfect. */ void starter_error_append(starter_errors_t *perrl, const char *fmt, ...) { va_list args; char tmp_err[512]; va_start(args, fmt); vsnprintf(tmp_err, sizeof(tmp_err) - 1, fmt, args); va_end(args); if (perrl->errors == NULL) { /* first error */ perrl->errors = clone_str(tmp_err, "starter error"); } else { /* subsequent error: append to previous messages */ size_t ol = strlen(perrl->errors); size_t al = strlen(tmp_err); char *nerr = alloc_bytes(ol + al + 2, "starter errors"); memcpy(nerr, perrl->errors, ol); nerr[ol] = '\n'; memcpy(&nerr[ol + 1], tmp_err, al + 1); pfree(perrl->errors); perrl->errors = nerr; } } #define KW_POLICY_FLAG(val, fl) { \ if (conn->options_set[val]) \ conn->policy = (conn->policy & ~(fl)) | \ (conn->options[val] ? (fl) : LEMPTY); \ } #define KW_POLICY_NEGATIVE_FLAG(val, fl) { \ if (conn->options_set[val]) { \ conn->policy = (conn->policy & ~(fl)) | \ (!conn->options[val] ? (fl) : LEMPTY); \ } \ } /** * Create a NULL-terminated array of tokens from a string of whitespace-separated tokens. * * @param value string to be broken up at blanks, creating strings for list * @param n where to place element count (excluding terminating NULL) * @return tokens_from_string (NULL or pointer to NULL-terminated array of pointers to strings) */ static char **tokens_from_string(const char *value, int *n) { *n = 0; /* in case of early exit */ if (value == NULL) return NULL; /* avoid damaging original string */ char *const val = clone_str(value, "tokens_from_string value"); if (val == NULL) return NULL; /* cannot happen -- silence a coverity warning */ char *const end = val + strlen(val); /* count number of items in string and terminate each with NUL */ int count = 0; for (char *b = val; b < end; ) { char *e; for (e = b; *e != '\0' && !isblank(*e); e++) ; *e = '\0'; if (e != b) count++; b = e + 1; } *n = count; if (count == 0) { pfree(val); return NULL; } char **const nlist = (char **)alloc_bytes((count + 1) * sizeof(char *), "tokens_from_string nlist"); count = 0; for (char *b = val; b < end; ) { char *e = b + strlen(b); if (e != b) nlist[count++] = clone_str(b, "tokens_from_string item"); b = e + 1; } nlist[count] = NULL; pfree(val); return nlist; } /** * Load a parsed config * * @param cfg starter_config structure * @param cfgp config_parsed (ie: valid) struct * @param perr pointer to store errors in * @return bool TRUE if unsuccessful */ static bool load_setup(struct starter_config *cfg, const struct config_parsed *cfgp) { bool err = FALSE; const struct kw_list *kw; for (kw = cfgp->config_setup; kw != NULL; kw = kw->next) { /** * the parser already made sure that only config keywords were used, * but we double check! */ assert(kw->keyword.keydef->validity & kv_config); unsigned f = kw->keyword.keydef->field; switch (kw->keyword.keydef->type) { case kt_string: case kt_filename: case kt_dirname: case kt_loose_enum: /* all treated as strings for now */ assert(f < elemsof(cfg->setup.strings)); pfreeany(cfg->setup.strings[f]); cfg->setup.strings[f] = clone_str(kw->string, "kt_loose_enum kw->string"); cfg->setup.strings_set[f] = TRUE; break; case kt_list: case kt_lset: case kt_bool: case kt_invertbool: case kt_enum: case kt_number: case kt_time: case kt_percent: /* all treated as a number for now */ assert(f < elemsof(cfg->setup.options)); cfg->setup.options[f] = kw->number; cfg->setup.options_set[f] = TRUE; break; case kt_bitstring: case kt_rsakey: case kt_ipaddr: case kt_subnet: case kt_range: case kt_idtype: err = TRUE; break; case kt_comment: break; case kt_obsolete: starter_log(LOG_LEVEL_INFO, "Warning: ignored obsolete keyword '%s'", kw->keyword.keydef->keyname); break; case kt_obsolete_quiet: starter_log(LOG_LEVEL_ERR, "Warning: ignored obsolete keyword '%s'", kw->keyword.keydef->keyname); break; default: /* NEVER HAPPENS */ break; } } return err; } static bool validate_ip_cider(const char *value, ip_subnet *ip, const char *leftright, char *err_p, starter_errors_t *perrl) { bool err = FALSE; # define ERR_FOUND(...) { starter_error_append(perrl, __VA_ARGS__); err = TRUE; } if (strchr(value, '/') == NULL) { ERR_FOUND("%s%s=%s needs address/prefix length", leftright, err_p, value); } else { /* * ttosubnet() helpfully sets the IP address to the lowest IP * in the subnet. Which is great for subnets but we want to * retain the specific IP in this case. * So we subsequently overwrite the IP address of the subnet. */ err_t er = ttosubnet(value, 0, AF_UNSPEC, '0' /* allow host bits */, ip); if (er != NULL) { ERR_FOUND("bad addr %s%s=%s [%s]", leftright, err_p, value, er); } else { if (ip->addr.hport != 0) ERR_FOUND("bad ip address port is not allowed %sinterface-ip=%s", leftright, value) er = tnatoaddr(value, strchr(value, '/') - value, AF_UNSPEC, &ip->addr); if (er != NULL) { ERR_FOUND("bad ip address in %s%s=%s [%s]", leftright, err_p, value, er); } } } return err; # undef ERR_FOUND } /** * Validate that yes in fact we are one side of the tunnel * * The function checks that IP addresses are valid, nexthops are * present (if needed) as well as policies, and sets the leftID * from the left= if it isn't set. * * @param conn_st a connection definition * @param end a connection end * @param leftright const char * "left" or "right" * @param perrl pointer to starter_errors_t * @return bool TRUE if failed */ static bool validate_end(struct starter_conn *conn_st, struct starter_end *end, const char *leftright, starter_errors_t *perrl) { err_t er = NULL; int hostfam = conn_st->options[KNCF_HOSTADDRFAMILY]; bool err = FALSE; /* * TODO: * The address family default should come in either via * a config setup option, or via gai.conf / RFC3484 * For now, %defaultroute and %any means IPv4 only */ if (hostfam == AF_UNSPEC) { const char *ips = end->strings[KNCF_IP]; hostfam = AF_INET; if (ips != NULL && (strchr(ips, ':') != NULL || streq(ips, "%defaultroute6") || streq(ips, "%any6"))) { hostfam = AF_INET6; } } # define ERR_FOUND(...) { starter_error_append(perrl, __VA_ARGS__); err = TRUE; } if (!end->options_set[KNCF_IP]) conn_st->state = STATE_INCOMPLETE; end->addrtype = end->options[KNCF_IP]; end->addr_family = hostfam; /* validate the KSCF_IP/KNCF_IP */ switch (end->addrtype) { case KH_ANY: end->addr = address_any(aftoinfo(hostfam)); break; case KH_IFACE: /* generally, this doesn't show up at this stage */ starter_log(LOG_LEVEL_DEBUG, "starter: %s is KH_IFACE", leftright); break; case KH_IPADDR: assert(end->strings[KSCF_IP] != NULL); if (end->strings[KSCF_IP][0] == '%') { pfree(end->iface); end->iface = clone_str(end->strings[KSCF_IP] + 1, "KH_IPADDR end->iface"); if (!starter_iface_find(end->iface, hostfam, &end->addr, &end->nexthop)) conn_st->state = STATE_INVALID; /* not numeric, so set the type to the iface type */ end->addrtype = KH_IFACE; break; } er = ttoaddr_num(end->strings[KNCF_IP], 0, hostfam, &end->addr); if (er != NULL) { /* not an IP address, so set the type to the string */ end->addrtype = KH_IPHOSTNAME; } else { hostfam = end->addr_family = addrtypeof(&end->addr); } if (end->id == NULL) { ipstr_buf b; end->id = clone_str(ipstr(&end->addr, &b), "end if"); } break; case KH_OPPO: conn_st->policy |= POLICY_OPPORTUNISTIC; break; case KH_OPPOGROUP: conn_st->policy |= POLICY_OPPORTUNISTIC | POLICY_GROUP; break; case KH_GROUP: conn_st->policy |= POLICY_GROUP; break; case KH_IPHOSTNAME: /* generally, this doesn't show up at this stage */ starter_log(LOG_LEVEL_DEBUG, "starter: %s is KH_IPHOSTNAME", leftright); break; case KH_DEFAULTROUTE: end->addr_family = hostfam; starter_log(LOG_LEVEL_DEBUG, "starter: %s is KH_DEFAULTROUTE", leftright); break; case KH_NOTSET: starter_log(LOG_LEVEL_DEBUG, "starter: %s is KH_NOTSET", leftright); break; } if (end->strings_set[KSCF_VTI_IP]) { err = validate_ip_cider(end->strings[KSCF_VTI_IP], &end->vti_ip, leftright, "vti", perrl); } /* validate the KSCF_SUBNET */ if (end->strings_set[KSCF_SUBNET]) { char *value = end->strings[KSCF_SUBNET]; if (end->strings_set[KSCF_ADDRESSPOOL]) { ERR_FOUND("cannot specify both %ssubnet= and %saddresspool=", leftright, leftright); } if (startswith(value, "vhost:") || startswith(value, "vnet:")) { er = NULL; end->virt = clone_str(value, "validate_end item"); } else { end->has_client = TRUE; er = ttosubnet(value, 0, AF_UNSPEC, '0', &end->subnet); } if (er != NULL) ERR_FOUND("bad subnet %ssubnet=%s [%s]", leftright, value, er); } /* set nexthop address to something consistent, by default */ end->nexthop = address_any(address_type(&end->addr)); /* validate the KSCF_NEXTHOP */ if (end->strings_set[KSCF_NEXTHOP]) { char *value = end->strings[KSCF_NEXTHOP]; if (strcaseeq(value, "%defaultroute")) { end->nexttype = KH_DEFAULTROUTE; } else { if (tnatoaddr(value, strlen(value), AF_UNSPEC, &end->nexthop) != NULL) { #ifdef USE_DNSSEC starter_log(LOG_LEVEL_DEBUG, "Calling unbound_resolve() for %snexthop value", leftright); if (!unbound_resolve(value, strlen(value), AF_INET, &end->nexthop) && !unbound_resolve(value, strlen(value), AF_INET6, &end->nexthop)) ERR_FOUND("bad value for %snexthop=%s\n", leftright, value); #else er = ttoaddr(value, 0, AF_UNSPEC, &end->nexthop); if (er != NULL) ERR_FOUND("bad value for %snexthop=%s [%s]", leftright, value, er); #endif } end->nexttype = KH_IPADDR; } } else { end->nexthop = address_any(aftoinfo(hostfam)); if (end->addrtype == KH_DEFAULTROUTE) { end->nexttype = KH_DEFAULTROUTE; } } /* validate the KSCF_ID */ if (end->strings_set[KSCF_ID]) { char *value = end->strings[KSCF_ID]; pfreeany(end->id); end->id = clone_str(value, "end->id"); /* fixup old ",," in a ID_DER_ASN1_DN to proper backslash comma */ if ((end->id[0] != '@') && (strstr(end->id, ",,") != NULL) && strstr(end->id, "=") != NULL) { char *cc; while ((cc = strstr(end->id, ",,")) != NULL) { cc[0] = '\\'; } } } if (end->options_set[KSCF_RSAKEY1]) { end->rsakey1_type = end->options[KSCF_RSAKEY1]; end->rsakey2_type = end->options[KSCF_RSAKEY2]; switch (end->options[KSCF_RSAKEY1]) { case PUBKEY_DNSONDEMAND: end->key_from_DNS_on_demand = TRUE; break; default: end->key_from_DNS_on_demand = FALSE; /* validate the KSCF_RSAKEY1/RSAKEY2 */ if (end->strings[KSCF_RSAKEY1] != NULL) { char *value = end->strings[KSCF_RSAKEY1]; pfreeany(end->rsakey1); end->rsakey1 = clone_str(value, "end->rsakey1"); } if (end->strings[KSCF_RSAKEY2] != NULL) { char *value = end->strings[KSCF_RSAKEY2]; pfreeany(end->rsakey2); end->rsakey2 = clone_str(value, "end->rsakey2"); } } } /* validate the KSCF_SOURCEIP, if any, and if set, * set the subnet to same value, if not set. */ if (end->strings_set[KSCF_SOURCEIP]) { char *value = end->strings[KSCF_SOURCEIP]; if (tnatoaddr(value, strlen(value), AF_UNSPEC, &end->sourceip) != NULL) { #ifdef USE_DNSSEC starter_log(LOG_LEVEL_DEBUG, "Calling unbound_resolve() for %ssourceip value", leftright); if (!unbound_resolve(value, strlen(value), AF_INET, &end->sourceip) && !unbound_resolve(value, strlen(value), AF_INET6, &end->sourceip)) ERR_FOUND("bad value for %ssourceip=%s\n", leftright, value); #else er = ttoaddr(value, 0, AF_UNSPEC, &end->sourceip); if (er != NULL) ERR_FOUND("bad addr %ssourceip=%s [%s]", leftright, value, er); #endif } else { er = tnatoaddr(value, 0, AF_UNSPEC, &end->sourceip); if (er != NULL) ERR_FOUND("bad numerical addr %ssourceip=%s [%s]", leftright, value, er); } if (!end->has_client) { er = addrtosubnet(&end->sourceip, &end->subnet); if (er != NULL) { ERR_FOUND("attempt to default %ssubnet from %s failed: %s", leftright, value, er); } end->has_client = TRUE; end->has_client_wildcard = FALSE; } if (end->strings_set[KSCF_INTERFACE_IP]) { ERR_FOUND("can not specify %sinterface-ip=%s and %sssourceip=%s", leftright, end->strings[KSCF_INTERFACE_IP], leftright, end->strings[KSCF_SOURCEIP]); } } /* copy certificate path name */ if (end->strings_set[KSCF_CERT] && end->strings_set[KSCF_CKAID]) { ERR_FOUND("only one of %scert and %sckaid can be specified", leftright, leftright); } if (end->strings_set[KSCF_CERT]) { end->certx = clone_str(end->strings[KSCF_CERT], "KSCF_CERT"); } if (end->strings_set[KSCF_CKAID]) { const char *ckaid = end->strings[KSCF_CKAID]; /* try parsing it */ const char *ugh = ttodata(ckaid, 0, 16, NULL, 0, NULL); if (ugh != NULL) { ERR_FOUND("invalid %sckaid: %s", leftright, ugh); } end->ckaid = clone_str(ckaid, "KSCF_CKAID"); } if (end->strings_set[KSCF_CA]) end->ca = clone_str(end->strings[KSCF_CA], "KSCF_CA"); if (end->strings_set[KSCF_UPDOWN]) { pfreeany(end->updown); end->updown = clone_str(end->strings[KSCF_UPDOWN], "KSCF_UPDOWN"); } if (end->strings_set[KSCF_PROTOPORT]) { err_t ugh; char *value = end->strings[KSCF_PROTOPORT]; ugh = ttoprotoport(value, 0, &end->protocol, &end->port, &end->has_port_wildcard); if (ugh != NULL) ERR_FOUND("bad %sprotoport=%s [%s]", leftright, value, ugh); } if (end->strings_set[KSCF_ADDRESSPOOL]) { char *addresspool = end->strings[KSCF_ADDRESSPOOL]; if (end->strings_set[KSCF_SUBNET]) ERR_FOUND("cannot specify both %ssubnet= and %saddresspool=", leftright, leftright); starter_log(LOG_LEVEL_DEBUG, "connection's %saddresspool set to: %s", leftright, end->strings[KSCF_ADDRESSPOOL] ); er = ttorange(addresspool, NULL, &end->pool_range); if (er != NULL) ERR_FOUND("bad %saddresspool=%s [%s]", leftright, addresspool, er); if (address_type(&end->pool_range.start) == &ipv6_info && !end->pool_range.is_subnet) { ERR_FOUND("bad IPv6 %saddresspool=%s not subnet", leftright, addresspool); } } if (end->strings_set[KSCF_INTERFACE_IP]) { err = validate_ip_cider(end->strings[KSCF_INTERFACE_IP], &end->ifaceip, leftright, "interface-ip", perrl); if (end->strings_set[KSCF_SOURCEIP]) { ERR_FOUND("can not specify %sinterface-ip=%s and %sssourceip=%s", leftright, end->strings[KSCF_INTERFACE_IP], leftright, end->strings[KSCF_SOURCEIP]); } } if (end->options_set[KNCF_XAUTHSERVER] || end->options_set[KNCF_XAUTHCLIENT]) conn_st->policy |= POLICY_XAUTH; return err; # undef ERR_FOUND } /** * Take keywords from ipsec.conf syntax and load into a conn struct * * @param conn a connection definition * @param sl a section_list * @param assigned_value is set to either k_set, or k_default. * k_default is used when we are loading a conn that should be * considered to be a "default" value, and that replacing this * value is considered acceptable. * @return bool TRUE if unsuccessful */ static bool translate_conn(struct starter_conn *conn, const struct section_list *sl, enum keyword_set assigned_value, starter_errors_t *perrl) { /* note: not all errors are considered serious */ bool serious_err = FALSE; for (const struct kw_list *kw = sl->kw; kw != NULL; kw = kw->next) { if ((kw->keyword.keydef->validity & kv_conn) == 0) { /* this isn't valid in a conn! */ char tmp_err[512]; snprintf(tmp_err, sizeof(tmp_err), "keyword '%s' is not valid in a conn (%s)\n", kw->keyword.keydef->keyname, sl->name); starter_log(LOG_LEVEL_INFO, "%s", tmp_err); starter_error_append(perrl, "%s", tmp_err); continue; } ksf *the_strings; str_set *set_strings; unsigned str_floor, str_roof; knf *the_options; int_set *set_options; unsigned opt_floor, opt_roof; if (kw->keyword.keydef->validity & kv_leftright) { struct starter_end *this = kw->keyword.keyleft ? &conn->left : &conn->right; the_strings = &this->strings; set_strings = &this->strings_set; str_floor = KSCF_last_loose + 1; str_roof = KSCF_last_leftright + 1; the_options = &this->options; set_options = &this->options_set; opt_floor = KSCF_last_loose + 1; opt_roof = KNCF_last_leftright + 1; } else { the_strings = &conn->strings; set_strings = &conn->strings_set; str_floor = KSCF_last_leftright + 1; str_roof = KSCF_ROOF; the_options = &conn->options; set_options = &conn->options_set; opt_floor = KNCF_last_leftright + 1; opt_roof = KNCF_ROOF; } unsigned int field = kw->keyword.keydef->field; assert(kw->keyword.keydef != NULL); switch (kw->keyword.keydef->type) { case kt_string: case kt_filename: case kt_dirname: case kt_bitstring: case kt_ipaddr: case kt_range: case kt_subnet: case kt_idtype: /* all treated as strings for now, even loose enums */ assert(field < str_roof); if ((*set_strings)[field] == k_set) { char tmp_err[512]; snprintf(tmp_err, sizeof(tmp_err), "duplicate key '%s' in conn %s while processing def %s", kw->keyword.keydef->keyname, conn->name, sl->name); starter_log(LOG_LEVEL_INFO, "%s", tmp_err); starter_error_append(perrl, "%s", tmp_err); /* only fatal if we try to change values */ if (kw->keyword.string == NULL || (*the_strings)[field] == NULL || !streq(kw->keyword.string, (*the_strings)[field])) { serious_err = TRUE; break; } } pfreeany((*the_strings)[field]); if (kw->string == NULL) { starter_error_append(perrl, "Invalid %s value", kw->keyword.keydef->keyname); serious_err = TRUE; break; } (*the_strings)[field] = clone_str(kw->string, "kt_idtype kw->string"); (*set_strings)[field] = assigned_value; break; case kt_appendstring: case kt_appendlist: /* implicitly, this field can have multiple values */ assert(str_floor <= field && field < str_roof); if ((*the_strings)[field] == NULL) { (*the_strings)[field] = clone_str(kw->string, "kt_appendlist kw->string"); } else { char *s = (*the_strings)[field]; size_t old_len = strlen(s); /* excludes '\0' */ size_t new_len = strlen(kw->string); char *n = alloc_bytes(old_len + 1 + new_len + 1, "kt_appendlist"); memcpy(n, s, old_len); n[old_len] = ' '; memcpy(n + old_len + 1, kw->string, new_len + 1); /* includes '\0' */ (*the_strings)[field] = n; pfree(s); } (*set_strings)[field] = TRUE; break; case kt_rsakey: case kt_loose_enum: assert(field <= KSCF_last_loose); if ((*set_options)[field] == k_set) { char tmp_err[512]; snprintf(tmp_err, sizeof(tmp_err), "duplicate key '%s' in conn %s while processing def %s", kw->keyword.keydef->keyname, conn->name, sl->name); starter_log(LOG_LEVEL_INFO, "%s", tmp_err); starter_error_append(perrl, "%s", tmp_err); /* only fatal if we try to change values */ if ((*the_options)[field] != (int)kw->number || !((*the_options)[field] == LOOSE_ENUM_OTHER && kw->number == LOOSE_ENUM_OTHER && kw->keyword.string != NULL && (*the_strings)[field] != NULL && streq(kw->keyword.string, (*the_strings)[field]))) { serious_err = TRUE; break; } } (*the_options)[field] = kw->number; if (kw->number == LOOSE_ENUM_OTHER) { assert(kw->keyword.string != NULL); pfreeany((*the_strings)[field]); (*the_strings)[field] = clone_str( kw->keyword.string, "kt_loose_enum kw->keyword.string"); } (*set_options)[field] = assigned_value; break; case kt_list: case kt_lset: case kt_bool: case kt_invertbool: case kt_enum: case kt_number: case kt_time: case kt_percent: /* all treated as a number for now */ assert(opt_floor <= field && field < opt_roof); if ((*set_options)[field] == k_set) { char tmp_err[512]; snprintf(tmp_err, sizeof(tmp_err), "duplicate key '%s' in conn %s while processing def %s", kw->keyword.keydef->keyname, conn->name, sl->name); starter_log(LOG_LEVEL_INFO, "%s", tmp_err); starter_error_append(perrl, "%s", tmp_err); /* only fatal if we try to change values */ if ((*the_options)[field] != (int)kw->number) { serious_err = TRUE; break; } } (*the_options)[field] = kw->number; (*set_options)[field] = assigned_value; break; case kt_comment: break; case kt_obsolete: starter_log(LOG_LEVEL_INFO, "Warning: obsolete keyword '%s' ignored", kw->keyword.keydef->keyname); break; case kt_obsolete_quiet: starter_log(LOG_LEVEL_ERR, "Warning: obsolete keyword '%s' ignored", kw->keyword.keydef->keyname); break; } } return serious_err; } static void move_comment_list(struct starter_comments_list *to, struct starter_comments_list *from) { struct starter_comments *sc, *scnext; for (sc = from->tqh_first; sc != NULL; sc = scnext) { scnext = sc->link.tqe_next; TAILQ_REMOVE(from, sc, link); TAILQ_INSERT_TAIL(to, sc, link); } } static bool load_conn( struct starter_conn *conn, const struct config_parsed *cfgp, struct section_list *sl, bool alsoprocessing, bool defaultconn, starter_errors_t *perrl) { bool err; /* turn all of the keyword/value pairs into options/strings in left/right */ err = translate_conn(conn, sl, defaultconn ? k_default : k_set, perrl); move_comment_list(&conn->comments, &sl->comments); if (err) return err; if (conn->strings[KSCF_ALSO] != NULL && !alsoprocessing) { starter_log(LOG_LEVEL_INFO, "also= is not valid in section '%s'", sl->name); starter_error_append(perrl, "also= is not valid in section '%s'", sl->name); return TRUE; /* error */ } /* * Process the also list * * Note: conn->alsos will be NULL until we finish * and the appropriate list will be in local variable alsos. */ /* free any residual alsos list */ if (conn->alsos != NULL) { for (char **s = conn->alsos; *s != NULL; s++) pfreeany(*s); pfree(conn->alsos); conn->alsos = NULL; } int alsosize; char **alsos = tokens_from_string(conn->strings[KSCF_ALSO], &alsosize); if (alsoprocessing && alsos != NULL) { /* reset all of the "beenhere" flags */ for (struct section_list *s = cfgp->sections.tqh_first; s != NULL; s = s->link.tqe_next) s->beenhere = FALSE; sl->beenhere = TRUE; for (int alsoplace = 0; alsoplace < alsosize; alsoplace++) { /* * Check for too many alsos. * Inside the loop because of indirect alsos. */ if (alsosize >= ALSO_LIMIT) { starter_log(LOG_LEVEL_INFO, "while loading conn '%s', too many also= used at section %s. Limit is %d", conn->name, alsos[alsosize], ALSO_LIMIT); starter_error_append(perrl, "while loading conn '%s', too many also= used at section %s. Limit is %d", conn->name, alsos[alsosize], ALSO_LIMIT); return TRUE; /* error */ } /* * for each also= listed, go find this section's keyword list, and * load it as well. This may extend the also= list (and the end), * which we handle by zeroing the also list, and adding to it after * checking for duplicates. */ struct section_list *addin; for (addin = cfgp->sections.tqh_first; addin != NULL && !streq(alsos[alsoplace], addin->name); addin = addin->link.tqe_next) ; if (addin == NULL) { starter_log(LOG_LEVEL_ERR, "cannot find conn '%s' needed by conn '%s'", alsos[alsoplace], conn->name); starter_error_append(perrl, "cannot find conn '%s' needed by conn '%s'", alsos[alsoplace], conn->name); err = TRUE; continue; /* allowing further error detection */ } if (addin->beenhere) continue; /* already handled */ starter_log(LOG_LEVEL_DEBUG, "\twhile loading conn '%s' also including '%s'", conn->name, alsos[alsoplace]); conn->strings_set[KSCF_ALSO] = FALSE; pfreeany(conn->strings[KSCF_ALSO]); conn->strings[KSCF_ALSO] = NULL; addin->beenhere = TRUE; /* translate things, but do not replace earlier settings! */ err |= translate_conn(conn, addin, k_set, perrl); if (conn->strings[KSCF_ALSO] != NULL) { /* add this guy's alsos too */ int newalsosize; char **newalsos = tokens_from_string( conn->strings[KSCF_ALSO], &newalsosize); if (newalsos != NULL) { /* * Append newalsos onto alsos. * Requires a re-allocation. * Copying is shallow: the lists * are copied and freed but * the underlying strings are unchanged. */ char **ra = alloc_bytes((alsosize + newalsosize + 1) * sizeof(char *), "conn->alsos"); memcpy(ra, alsos, alsosize * sizeof(char *)); pfree(alsos); alsos = ra; memcpy(ra + alsosize, newalsos, (newalsosize + 1) * sizeof(char *)); pfree(newalsos); alsosize += newalsosize; } } } } /* * Migrate alsos back to conn->alsos. * Note that this is the transitive closure. */ conn->alsos = alsos; if (conn->options_set[KNCF_TYPE]) { switch ((enum keyword_satype)conn->options[KNCF_TYPE]) { case KS_TUNNEL: conn->policy &= ~POLICY_SHUNT_MASK; conn->policy |= POLICY_TUNNEL | POLICY_SHUNT_TRAP; break; case KS_TRANSPORT: conn->policy &= ~POLICY_TUNNEL & ~POLICY_SHUNT_MASK; conn->policy |= POLICY_SHUNT_TRAP; break; case KS_PASSTHROUGH: conn->policy &= ~(POLICY_ENCRYPT | POLICY_AUTHENTICATE | POLICY_TUNNEL | POLICY_RSASIG | POLICY_SHUNT_MASK); conn->policy |= POLICY_SHUNT_PASS; break; case KS_DROP: conn->policy &= ~(POLICY_ENCRYPT | POLICY_AUTHENTICATE | POLICY_TUNNEL | POLICY_RSASIG | POLICY_SHUNT_MASK); conn->policy |= POLICY_SHUNT_DROP; break; case KS_REJECT: conn->policy &= ~(POLICY_ENCRYPT | POLICY_AUTHENTICATE | POLICY_TUNNEL | POLICY_RSASIG | POLICY_SHUNT_MASK); conn->policy |= POLICY_SHUNT_REJECT; break; } } if (conn->options_set[KNCF_FAILURESHUNT]) { conn->policy &= ~POLICY_FAIL_MASK; switch (conn->options[KNCF_FAILURESHUNT]) { case KFS_FAIL_NONE: conn->policy |= POLICY_FAIL_NONE; break; case KFS_FAIL_PASS: conn->policy |= POLICY_FAIL_PASS; break; case KFS_FAIL_DROP: conn->policy |= POLICY_FAIL_DROP; break; case KFS_FAIL_REJECT: conn->policy |= POLICY_FAIL_REJECT; break; } } if (conn->options_set[KNCF_NEGOTIATIONSHUNT]) { switch (conn->options[KNCF_NEGOTIATIONSHUNT]) { case KNS_FAIL_PASS: conn->policy |= POLICY_NEGO_PASS; break; case KNS_FAIL_DROP: conn->policy &= ~POLICY_NEGO_PASS; break; } } KW_POLICY_FLAG(KNCF_COMPRESS, POLICY_COMPRESS); KW_POLICY_FLAG(KNCF_PFS, POLICY_PFS); /* reset authby= flags */ if (conn->strings_set[KSCF_AUTHBY]) { conn->policy &= ~POLICY_ID_AUTH_MASK; conn->sighash_policy = LEMPTY; } KW_POLICY_NEGATIVE_FLAG(KNCF_IKEPAD, POLICY_NO_IKEPAD); KW_POLICY_NEGATIVE_FLAG(KNCF_REKEY, POLICY_DONT_REKEY); KW_POLICY_FLAG(KNCF_REAUTH, POLICY_REAUTH); KW_POLICY_FLAG(KNCF_AGGRMODE, POLICY_AGGRESSIVE); KW_POLICY_FLAG(KNCF_MODECONFIGPULL, POLICY_MODECFG_PULL); KW_POLICY_FLAG(KNCF_OVERLAPIP, POLICY_OVERLAPIP); KW_POLICY_FLAG(KNCF_IKEv2_ALLOW_NARROWING, POLICY_IKEV2_ALLOW_NARROWING); KW_POLICY_FLAG(KNCF_MOBIKE, POLICY_MOBIKE); KW_POLICY_FLAG(KNCF_IKEv2_PAM_AUTHORIZE, POLICY_IKEV2_PAM_AUTHORIZE); KW_POLICY_FLAG(KNCF_DECAP_DSCP, POLICY_DECAP_DSCP); KW_POLICY_FLAG(KNCF_NOPMTUDISC, POLICY_NOPMTUDISC); KW_POLICY_FLAG(KNCF_MSDH_DOWNGRADE, POLICY_MSDH_DOWNGRADE); KW_POLICY_FLAG(KNCF_DNS_MATCH_ID, POLICY_DNS_MATCH_ID); KW_POLICY_FLAG(KNCF_SHA2_TRUNCBUG, POLICY_SHA2_TRUNCBUG); if (conn->options_set[KNCF_SAN_ON_CERT]) { if (!conn->options[KNCF_SAN_ON_CERT]) conn->policy |= POLICY_ALLOW_NO_SAN; } /* ??? sometimes (when? why?) the member is already set */ # define str_to_conn(member, kscf) { \ if (conn->strings_set[kscf]) { \ pfreeany(conn->member); \ conn->member = clone_str(conn->strings[kscf], #kscf); \ } \ } str_to_conn(connalias, KSCF_CONNALIAS); str_to_conn(ike_crypto, KSCF_IKE); str_to_conn(esp, KSCF_ESP); str_to_conn(modecfg_dns, KSCF_MODECFGDNS); str_to_conn(modecfg_domains, KSCF_MODECFGDOMAINS); str_to_conn(modecfg_banner, KSCF_MODECFGBANNER); #ifdef HAVE_LABELED_IPSEC str_to_conn(policy_label, KSCF_POLICY_LABEL); if (conn->policy_label != NULL) starter_log(LOG_LEVEL_DEBUG, "connection's policy label: %s", conn->policy_label); #endif str_to_conn(conn_mark_both, KSCF_CONN_MARK_BOTH); str_to_conn(conn_mark_in, KSCF_CONN_MARK_IN); str_to_conn(conn_mark_out, KSCF_CONN_MARK_OUT); str_to_conn(vti_iface, KSCF_VTI_IFACE); str_to_conn(redirect_to, KSCF_REDIRECT_TO); str_to_conn(accept_redirect_to, KSCF_ACCEPT_REDIRECT_TO); # undef str_to_conn if (conn->options_set[KNCF_PHASE2]) { conn->policy &= ~(POLICY_AUTHENTICATE | POLICY_ENCRYPT); conn->policy |= conn->options[KNCF_PHASE2]; } /* * This option has really been turned into a boolean, but * we need the keywords for backwards compatibility for now */ if (conn->options_set[KNCF_IKEv2]) { switch (conn->options[KNCF_IKEv2]) { case fo_never: case fo_permit: conn->policy |= POLICY_IKEV1_ALLOW; /* clear any inherited default */ conn->policy &= ~POLICY_IKEV2_ALLOW; break; case fo_propose: case fo_insist: conn->policy |= POLICY_IKEV2_ALLOW; /* clear any inherited default */ conn->policy &= ~POLICY_IKEV1_ALLOW; break; } } if (conn->options_set[KNCF_SEND_REDIRECT]) { if (!LIN(POLICY_IKEV1_ALLOW, conn->policy)) { switch (conn->options[KNCF_SEND_REDIRECT]) { case yna_yes: conn->policy |= POLICY_SEND_REDIRECT_ALWAYS; if (conn->redirect_to == NULL) { starter_log(LOG_LEVEL_INFO, "redirect-to is not specified, although send-redirect is set to yes"); } break; case yna_no: conn->policy |= POLICY_SEND_REDIRECT_NEVER; break; case yna_auto: break; } } } if (conn->options_set[KNCF_ACCEPT_REDIRECT]) { if (!LIN(POLICY_IKEV1_ALLOW, conn->policy)) { switch (conn->options[KNCF_ACCEPT_REDIRECT]) { case yna_yes: conn->policy |= POLICY_ACCEPT_REDIRECT_YES; break; /* default policy is no, so there is no POLICY_ACCEPT_REDIRECT_YES * in policy. * * technically the values for this option are yes/no, * although we use yna option set (we do not want to * make new yes-no enum) */ case yna_auto: case yna_no: break; } } } if (conn->options_set[KNCF_PPK]) { lset_t ppk = LEMPTY; if (!(conn->policy & POLICY_IKEV1_ALLOW)) { switch (conn->options[KNCF_PPK]) { case fo_propose: ppk = POLICY_PPK_ALLOW; break; case fo_permit: ppk = POLICY_PPK_ALLOW; break; case fo_insist: ppk = POLICY_PPK_ALLOW | POLICY_PPK_INSIST; break; case fo_never: break; } } conn->policy = conn->policy | ppk; } if (conn->options_set[KNCF_ESN]) { conn->policy &= ~(POLICY_ESN_NO | POLICY_ESN_YES); switch (conn->options[KNCF_ESN]) { case ESN_YES: conn->policy |= POLICY_ESN_YES; break; case ESN_NO: /* this is the default for now */ conn->policy |= POLICY_ESN_NO; break; case ESN_EITHER: conn->policy |= POLICY_ESN_NO | POLICY_ESN_YES; break; } } if (conn->options_set[KNCF_IKE_FRAG]) { conn->policy &= ~(POLICY_IKE_FRAG_ALLOW | POLICY_IKE_FRAG_FORCE); switch (conn->options[KNCF_IKE_FRAG]) { case ynf_no: break; case ynf_yes: /* this is the default */ conn->policy |= POLICY_IKE_FRAG_ALLOW; break; case ynf_force: conn->policy |= POLICY_IKE_FRAG_ALLOW | POLICY_IKE_FRAG_FORCE; break; } } if (conn->options_set[KNCF_SAREFTRACK]) { conn->policy &= ~(POLICY_SAREF_TRACK | POLICY_SAREF_TRACK_CONNTRACK); switch (conn->options[KNCF_SAREFTRACK]) { case SAT_YES: /* this is the default */ conn->policy |= POLICY_SAREF_TRACK; break; case SAT_CONNTRACK: conn->policy |= POLICY_SAREF_TRACK | POLICY_SAREF_TRACK_CONNTRACK; break; case SAT_NO: break; } } /* read in the authby string and translate to policy bits * this is the symmetric (left+right) version * there is also leftauthby/rightauthby version stored in 'end' * * authby=secret|rsasig|null|never|rsa-HASH * * using authby=rsasig results in legacy POLICY_RSASIG_v1_5 and RSA_PSS * * HASH needs to use full syntax - eg sha2_256 and not sha256, to avoid * confusion with sha3_256 */ if (conn->strings_set[KSCF_AUTHBY]) { char *val = strtok(conn->strings[KSCF_AUTHBY], ", "); conn->sighash_policy = LEMPTY; conn->policy &= ~POLICY_ID_AUTH_MASK; conn->policy &= ~POLICY_RSASIG_v1_5; while (val != NULL) { /* Supported for IKEv1 and IKEv2 */ if (streq(val, "secret")) { conn->policy |= POLICY_PSK; } else if (streq(val, "rsasig") || streq(val, "rsa")) { conn->policy |= POLICY_RSASIG; conn->policy |= POLICY_RSASIG_v1_5; conn->sighash_policy |= POL_SIGHASH_SHA2_256; conn->sighash_policy |= POL_SIGHASH_SHA2_384; conn->sighash_policy |= POL_SIGHASH_SHA2_512; } else if (streq(val, "never")) { conn->policy |= POLICY_AUTH_NEVER; /* everything else is only supported for IKEv2 */ } else if (conn->policy & POLICY_IKEV1_ALLOW) { starter_error_append(perrl, "ikev1 connection must use authby= of rsasig, secret or never"); return TRUE; } else if (streq(val, "null")) { conn->policy |= POLICY_AUTH_NULL; } else if (streq(val, "rsa-sha1")) { conn->policy |= POLICY_RSASIG; conn->policy |= POLICY_RSASIG_v1_5; } else if (streq(val, "rsa-sha2")) { conn->policy |= POLICY_RSASIG; conn->sighash_policy |= POL_SIGHASH_SHA2_256; conn->sighash_policy |= POL_SIGHASH_SHA2_384; conn->sighash_policy |= POL_SIGHASH_SHA2_512; } else if (streq(val, "rsa-sha2_256")) { conn->sighash_policy |= POL_SIGHASH_SHA2_256; } else if (streq(val, "rsa-sha2_384")) { conn->policy |= POLICY_RSASIG; conn->sighash_policy |= POL_SIGHASH_SHA2_384; } else if (streq(val, "rsa-sha2_512")) { conn->policy |= POLICY_RSASIG; conn->sighash_policy |= POL_SIGHASH_SHA2_512; } else if (streq(val, "ecdsa") || streq(val, "ecdsa-sha2")) { conn->policy |= POLICY_ECDSA; conn->sighash_policy |= POL_SIGHASH_SHA2_256; conn->sighash_policy |= POL_SIGHASH_SHA2_384; conn->sighash_policy |= POL_SIGHASH_SHA2_512; } else if (streq(val, "ecdsa-sha2_256")) { conn->policy |= POLICY_ECDSA; conn->sighash_policy |= POL_SIGHASH_SHA2_256; } else if (streq(val, "ecdsa-sha2_384")) { conn->policy |= POLICY_ECDSA; conn->sighash_policy |= POL_SIGHASH_SHA2_384; } else if (streq(val, "ecdsa-sha2_512")) { conn->policy |= POLICY_ECDSA; conn->sighash_policy |= POL_SIGHASH_SHA2_512; } else if (streq(val, "ecdsa-sha1")) { starter_error_append(perrl, "authby=ecdsa cannot use sha1, only sha2"); return TRUE; } else { starter_error_append(perrl, "connection authby= value is unknown"); return TRUE; } val = strtok(NULL, ", "); } } /* * some options are set as part of our default, but * some make no sense for shunts, so remove those again */ if (NEVER_NEGOTIATE(conn->policy)) { /* remove IPsec related options */ conn->policy &= ~(POLICY_PFS | POLICY_COMPRESS | POLICY_ESN_NO | POLICY_ESN_YES | POLICY_SAREF_TRACK | POLICY_DECAP_DSCP | POLICY_NOPMTUDISC | POLICY_SAREF_TRACK_CONNTRACK) & /* remove IKE related options */ ~(POLICY_IKEV1_ALLOW | POLICY_IKEV2_ALLOW | POLICY_IKE_FRAG_ALLOW | POLICY_IKE_FRAG_FORCE); } err |= validate_end(conn, &conn->left, "left", perrl); err |= validate_end(conn, &conn->right, "right", perrl); /* * TODO: * verify both ends are using the same inet family, if one end * is "%any" or "%defaultroute", then perhaps adjust it. * ensource this for left,leftnexthop,right,rightnexthop */ if (conn->options_set[KNCF_AUTO]) conn->desired_state = conn->options[KNCF_AUTO]; return err; } static void copy_conn_default(struct starter_conn *conn, const struct starter_conn *def) { /* structure copy to start */ *conn = *def; /* unlink it */ conn->link.tqe_next = NULL; conn->link.tqe_prev = NULL; /* Unshare all strings */ /* * Note: string fields in struct starter_end and struct starter_conn * should correspond to STR_FIELD calls in copy_conn_default() and confread_free_conn. */ assert(conn->connalias == NULL); # define STR_FIELD(f) { conn->f = clone_str(conn->f, #f); } STR_FIELD(name); STR_FIELD(connalias); STR_FIELD(ike_crypto); STR_FIELD(esp); STR_FIELD(modecfg_dns); STR_FIELD(modecfg_domains); STR_FIELD(modecfg_banner); STR_FIELD(conn_mark_both); STR_FIELD(conn_mark_in); STR_FIELD(conn_mark_out); STR_FIELD(policy_label); STR_FIELD(conn_mark_both); STR_FIELD(conn_mark_in); STR_FIELD(conn_mark_out); STR_FIELD(vti_iface); STR_FIELD(redirect_to); STR_FIELD(accept_redirect_to); for (unsigned i = 0; i < elemsof(conn->strings); i++) STR_FIELD(strings[i]); /* handle starter_end strings */ # define STR_FIELD_END(f) { STR_FIELD(left.f); STR_FIELD(right.f); } STR_FIELD_END(iface); STR_FIELD_END(id); STR_FIELD_END(rsakey1); STR_FIELD_END(rsakey2); STR_FIELD_END(virt); STR_FIELD_END(certx); STR_FIELD_END(ckaid); STR_FIELD_END(ca); STR_FIELD_END(updown); for (unsigned i = 0; i < elemsof(conn->left.strings); i++) STR_FIELD_END(strings[i]); # undef STR_FIELD_END # undef STR_FIELD } static struct starter_conn *alloc_add_conn(struct starter_config *cfg, const char *name) { struct starter_conn *conn = alloc_thing(struct starter_conn, "add_conn starter_conn"); copy_conn_default(conn, &cfg->conn_default); assert(conn->name == NULL); conn->name = clone_str(name, "add conn name"); conn->desired_state = STARTUP_IGNORE; conn->state = STATE_FAILED; TAILQ_INIT(&conn->comments); TAILQ_INSERT_TAIL(&cfg->conns, conn, link); return conn; } static bool init_load_conn(struct starter_config *cfg, const struct config_parsed *cfgp, struct section_list *sconn, bool defaultconn, starter_errors_t *perrl) { starter_log(LOG_LEVEL_DEBUG, "Loading conn %s", sconn->name); struct starter_conn *conn = alloc_add_conn(cfg, sconn->name); bool connerr = load_conn(conn, cfgp, sconn, TRUE, defaultconn, perrl); if (connerr) { starter_log(LOG_LEVEL_INFO, "while loading '%s': %s", sconn->name, perrl->errors); /* ??? should caller not log perrl? */ } else { conn->state = STATE_LOADED; } return connerr; } struct starter_config *confread_load(const char *file, starter_errors_t *perrl, const char *ctlsocket, bool setuponly) { bool err = FALSE; /** * Load file */ struct config_parsed *cfgp = parser_load_conf(file, perrl); if (cfgp == NULL) return NULL; struct starter_config *cfg = alloc_thing(struct starter_config, "starter_config cfg"); /** * Set default values */ ipsecconf_default_values(cfg); if (ctlsocket != NULL) { pfree(cfg->ctlsocket); cfg->ctlsocket = clone_str(ctlsocket, "default ctlsocket"); } /** * Load setup */ err |= load_setup(cfg, cfgp); if (err) { parser_free_conf(cfgp); confread_free(cfg); return NULL; } if (!setuponly) { #ifdef USE_DNSSEC unbound_sync_init(cfg->setup.options[KBF_DO_DNSSEC], cfg->setup.strings[KSF_PLUTO_DNSSEC_ROOTKEY_FILE], cfg->setup.strings[KSF_PLUTO_DNSSEC_ANCHORS]); #endif /* * Load %default conn * ??? is it correct to accept multiple %default conns? */ for (struct section_list *sconn = cfgp->sections.tqh_first; (!err) && sconn != NULL; sconn = sconn->link.tqe_next) { if (streq(sconn->name, "%default")) { starter_log(LOG_LEVEL_DEBUG, "Loading default conn"); err |= load_conn(&cfg->conn_default, cfgp, sconn, FALSE, /*default conn*/ TRUE, perrl); } } /* * Load other conns */ for (struct section_list *sconn = cfgp->sections.tqh_first; sconn != NULL; sconn = sconn->link.tqe_next) { if (!streq(sconn->name, "%default")) err |= init_load_conn(cfg, cfgp, sconn, FALSE, perrl); } } parser_free_conf(cfgp); #ifdef USE_DNSSEC unbound_ctx_free(); #endif return cfg; } static void confread_free_conn(struct starter_conn *conn) { /* Free all strings */ /* * Note: string fields in struct starter_end and struct starter_conn * should correspond to STR_FIELD calls in copy_conn_default() and confread_free_conn. */ # define STR_FIELD(f) { pfreeany(conn->f); } STR_FIELD(name); STR_FIELD(connalias); STR_FIELD(ike_crypto); STR_FIELD(esp); STR_FIELD(modecfg_dns); STR_FIELD(modecfg_domains); STR_FIELD(modecfg_banner); STR_FIELD(conn_mark_both); STR_FIELD(conn_mark_in); STR_FIELD(conn_mark_out); STR_FIELD(policy_label); STR_FIELD(conn_mark_both); STR_FIELD(conn_mark_in); STR_FIELD(conn_mark_out); STR_FIELD(vti_iface); STR_FIELD(redirect_to); STR_FIELD(accept_redirect_to); for (unsigned i = 0; i < elemsof(conn->strings); i++) STR_FIELD(strings[i]); /* handle starter_end strings */ # define STR_FIELD_END(f) { STR_FIELD(left.f); STR_FIELD(right.f); } STR_FIELD_END(iface); STR_FIELD_END(id); STR_FIELD_END(rsakey1); STR_FIELD_END(rsakey2); STR_FIELD_END(virt); STR_FIELD_END(certx); STR_FIELD_END(ckaid); STR_FIELD_END(ca); STR_FIELD_END(updown); for (unsigned i = 0; i < elemsof(conn->left.strings); i++) STR_FIELD_END(strings[i]); # undef STR_FIELD_END # undef STR_FIELD } void confread_free(struct starter_config *cfg) { pfree(cfg->ctlsocket); for (unsigned i = 0; i < elemsof(cfg->setup.strings); i++) pfreeany(cfg->setup.strings[i]); confread_free_conn(&cfg->conn_default); for (struct starter_conn *conn = cfg->conns.tqh_first; conn != NULL; ) { struct starter_conn *c = conn; conn = conn->link.tqe_next; confread_free_conn(c); pfree(c); } pfree(cfg); } libreswan-3.32/lib/libipsecconf/confwrite.c000066400000000000000000000342401365625662500210240ustar00rootroot00000000000000/* * Libreswan config file writer (confwrite.c) * Copyright (C) 2004-2006 Michael Richardson * Copyright (C) 2012-2019 Paul Wouters * Copyright (C) 2013-2015 Antony Antony * Copyright (C) 2013-2019 D. Hugh Redelmeier * Copyright (C) 2013 David McCullough * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include #include #include #include #include #include "constants.h" #include "lswlog.h" #include "lmod.h" #include "ip_address.h" #include "ipsecconf/confread.h" #include "ipsecconf/confwrite.h" #include "ipsecconf/keywords.h" #include "ipsecconf/keywords.h" #include "ipsecconf/parser.h" /* includes parser.tab.h generated by bison; requires keywords.h */ void confwrite_list(FILE *out, char *prefix, int val, const struct keyword_def *k) { const struct keyword_enum_values *kevs = k->validenum; const struct keyword_enum_value *kev = kevs->values; int i; char *sep = ""; for (i = 0; i < (int)kevs->valuesize; i++) { unsigned int mask = kev[i].value; if (mask != 0 && (val & mask) == mask) { fprintf(out, "%s%s%s", sep, prefix, kev[i].name); sep = " "; } } } static void confwrite_int(FILE *out, char *side, unsigned int context, knf options, int_set options_set, ksf strings) { const struct keyword_def *k; for (k = ipsec_conf_keywords; k->keyname != NULL; k++) { if ((k->validity & KV_CONTEXT_MASK) != context) continue; /* do not output aliases or things handled elsewhere */ if (k->validity & (kv_alias | kv_policy | kv_processed)) continue; #if 0 printf("#side: %s %s validity: %08x & %08x=%08x vs %08x\n", side, k->keyname, k->validity, KV_CONTEXT_MASK, k->validity & KV_CONTEXT_MASK, context); #endif switch (k->type) { case kt_string: case kt_appendstring: case kt_appendlist: case kt_filename: case kt_dirname: case kt_rsakey: case kt_percent: case kt_ipaddr: case kt_subnet: case kt_range: case kt_idtype: case kt_bitstring: /* none of these are valid number types */ break; case kt_bool: case kt_invertbool: /* special enumeration */ if (options_set[k->field]) { fprintf(out, "\t%s%s=%s\n", side, k->keyname, options[k->field] ? "yes" : "no"); } break; case kt_enum: case kt_loose_enum: /* special enumeration */ if (options_set[k->field]) { int val = options[k->field]; fprintf(out, "\t%s%s=", side, k->keyname); if (k->type == kt_loose_enum && val == LOOSE_ENUM_OTHER) { fprintf(out, "%s\n", strings[k->field]); } else { const struct keyword_enum_values *kevs = k->validenum; const struct keyword_enum_value *kev = kevs->values; int i = 0; while (i < (int)kevs->valuesize) { if ((int)kev[i].value == val) { fprintf(out, "%s", kev[i].name); break; } i++; } fprintf(out, "\n"); } } break; case kt_list: /* special enumeration */ if (options_set[k->field]) { int val = options[k->field]; if (val != 0) { fprintf(out, "\t%s%s=\"", side, k->keyname); confwrite_list(out, "", val, k); fprintf(out, "\"\n"); } } break; case kt_lset: if (options_set[k->field]) { unsigned long val = options[k->field]; if (val != 0) { LSWLOG_FILE(out, buf) { lswlogf(buf, "\t%s%s=\"", side, k->keyname); lswlog_enum_lset_short(buf, k->info->names, ",", val); lswlogf(buf, "\""); } } } break; case kt_comment: break; case kt_obsolete: case kt_obsolete_quiet: break; case kt_time: /* special number, but do work later XXX */ case kt_number: if (options_set[k->field]) fprintf(out, "\t%s%s=%d\n", side, k->keyname, options[k->field]); } } } static void confwrite_str(FILE *out, char *side, unsigned int context, ksf strings, str_set strings_set) { const struct keyword_def *k; for (k = ipsec_conf_keywords; k->keyname != NULL; k++) { if ((k->validity & KV_CONTEXT_MASK) != context) continue; /* do not output aliases or settings handled elsewhere */ if (k->validity & (kv_alias | kv_policy | kv_processed)) continue; switch (k->type) { case kt_appendlist: if (strings_set[k->field]) fprintf(out, "\t%s%s={%s}\n", side, k->keyname, strings[k->field]); break; case kt_string: case kt_appendstring: case kt_filename: case kt_dirname: /* these are strings */ if (strings_set[k->field]) { const char *quote = strchr(strings[k->field], ' ') == NULL ? "" : "\""; fprintf(out, "\t%s%s=%s%s%s\n", side, k->keyname, quote, strings[k->field], quote); } break; case kt_rsakey: case kt_ipaddr: case kt_range: case kt_subnet: case kt_idtype: case kt_bitstring: break; case kt_bool: case kt_invertbool: case kt_enum: case kt_list: case kt_lset: case kt_loose_enum: /* special enumeration */ break; case kt_time: /* special number, not a string */ break; case kt_percent: case kt_number: break; case kt_comment: break; case kt_obsolete: case kt_obsolete_quiet: break; } } } static void confwrite_side(FILE *out, struct starter_end *end, char *side) { switch (end->addrtype) { case KH_NOTSET: /* nothing! */ break; case KH_DEFAULTROUTE: fprintf(out, "\t%s=%%defaultroute\n", side); break; case KH_ANY: fprintf(out, "\t%s=%%any\n", side); break; case KH_IFACE: if (end->strings_set[KSCF_IP]) fprintf(out, "\t%s=%s\n", side, end->strings[KSCF_IP]); break; case KH_OPPO: fprintf(out, "\t%s=%%opportunistic\n", side); break; case KH_OPPOGROUP: fprintf(out, "\t%s=%%opportunisticgroup\n", side); break; case KH_GROUP: fprintf(out, "\t%s=%%group\n", side); break; case KH_IPHOSTNAME: fprintf(out, "\t%s=%s\n", side, end->strings[KSCF_IP]); break; case KH_IPADDR: { ipstr_buf as; fprintf(out, "\t%s=%s\n", side, ipstr(&end->addr, &as)); } break; } if (end->strings_set[KSCF_ID] && end->id) fprintf(out, "\t%sid=\"%s\"\n", side, end->id); switch (end->nexttype) { case KH_NOTSET: /* nothing! */ break; case KH_DEFAULTROUTE: fprintf(out, "\t%snexthop=%%defaultroute\n", side); break; case KH_IPADDR: { ipstr_buf as; fprintf(out, "\t%snexthop=%s\n", side, ipstr(&end->nexthop, &as)); } break; default: break; } if (end->has_client) { if (!subnetishost(&end->subnet) || !addrinsubnet(&end->addr, &end->subnet)) { subnet_buf as; fprintf(out, "\t%ssubnet=%s\n", side, str_subnet(&end->subnet, &as)); } } if (subnet_is_specified(&end->vti_ip)) { subnet_buf as; fprintf(out, "\t%svti=%s\n", side, str_subnet(&end->vti_ip, &as)); } if (subnet_is_specified(&end->ifaceip)) { subnet_buf as; fprintf(out, "\t%sinterface-ip=%s\n", side, str_subnet(&end->ifaceip, &as)); } if (end->rsakey1 != NULL && end->rsakey1[0] != '\0') fprintf(out, "\t%srsasigkey=%s\n", side, end->rsakey1); if (end->rsakey2 != NULL && end->rsakey2[0] != '\0') fprintf(out, "\t%srsasigkey2=%s\n", side, end->rsakey2); if (end->port != 0 || end->protocol != 0) { /* it is hoped that any number fits within 32 characters */ char portstr[32] = "%any"; char protostr[32] = "%any"; if (end->port != 0) snprintf(portstr, sizeof(portstr), "%u", end->port); if (end->protocol != 0) snprintf(protostr, sizeof(protostr), "%u", end->protocol); fprintf(out, "\t%sprotoport=%s/%s\n", side, protostr, portstr); } if (end->certx != NULL) fprintf(out, "\t%scert=%s\n", side, end->certx); if (address_is_specified(&end->sourceip)) { ipstr_buf as; fprintf(out, "\t%ssourceip=%s\n", side, ipstr(&end->sourceip, &as)); } confwrite_int(out, side, kv_conn | kv_leftright, end->options, end->options_set, end->strings); confwrite_str(out, side, kv_conn | kv_leftright, end->strings, end->strings_set); } static void confwrite_comments(FILE *out, struct starter_conn *conn) { struct starter_comments *sc, *scnext; for (sc = conn->comments.tqh_first; sc != NULL; sc = scnext) { scnext = sc->link.tqe_next; fprintf(out, "\t%s=%s\n", sc->x_comment, sc->commentvalue); } } static void confwrite_conn(FILE *out, struct starter_conn *conn, bool verbose) { /* short-cut for writing out a field (string-valued, indented, on its own line) */ # define cwf(name, value) { fprintf(out, "\t" name "=%s\n", (value)); } if (verbose) fprintf(out, "# begin conn %s\n", conn->name); fprintf(out, "conn %s\n", conn->name); if (conn->alsos != NULL) { /* handle also= as a comment */ int alsoplace = 0; fprintf(out, "\t#also ="); while (conn->alsos[alsoplace] != NULL) { fprintf(out, " %s", conn->alsos[alsoplace]); alsoplace++; } fprintf(out, "\n"); } confwrite_side(out, &conn->left, "left"); confwrite_side(out, &conn->right, "right"); /* fprintf(out, "# confwrite_int:\n"); */ confwrite_int(out, "", kv_conn, conn->options, conn->options_set, conn->strings); /* fprintf(out, "# confwrite_str:\n"); */ confwrite_str(out, "", kv_conn, conn->strings, conn->strings_set); /* fprintf(out, "# confwrite_comments:\n"); */ confwrite_comments(out, conn); if (conn->connalias != NULL) cwf("connalias", conn->connalias); { const char *dsn = "UNKNOWN"; switch (conn->desired_state) { case STARTUP_IGNORE: dsn = "ignore"; break; case STARTUP_POLICY: dsn = "policy"; /* ??? no keyword for this */ break; case STARTUP_ADD: dsn = "add"; break; case STARTUP_ONDEMAND: dsn = "ondemand"; break; case STARTUP_START: dsn = "start"; break; } cwf("auto", dsn); } if (conn->policy != LEMPTY) { lset_t phase2_policy = (conn->policy & (POLICY_AUTHENTICATE | POLICY_ENCRYPT)); lset_t shunt_policy = (conn->policy & POLICY_SHUNT_MASK); lset_t ppk_policy = (conn->policy & (POLICY_PPK_ALLOW | POLICY_PPK_INSIST)); lset_t ike_frag_policy = (conn->policy & POLICY_IKE_FRAG_MASK); static const char *const noyes[2 /*bool*/] = {"no", "yes"}; /* short-cuts for writing out a field that is a policy bit. * cwpbf flips the sense of the bit. */ # define cwpb(name, p) { cwf(name, noyes[(conn->policy & (p)) != LEMPTY]); } # define cwpbf(name, p) { cwf(name, noyes[(conn->policy & (p)) == LEMPTY]); } switch (shunt_policy) { case POLICY_SHUNT_TRAP: cwf("type", conn->policy & POLICY_TUNNEL? "tunnel" : "transport"); cwpb("compress", POLICY_COMPRESS); cwpb("pfs", POLICY_PFS); cwpbf("ikepad", POLICY_NO_IKEPAD); { const char *abs = "UNKNOWN"; switch (conn->policy & POLICY_ID_AUTH_MASK) { case POLICY_PSK: abs = "secret"; break; case POLICY_RSASIG: abs = "rsasig"; break; case POLICY_PSK | POLICY_RSASIG: abs = "secret|rsasig"; break; case POLICY_AUTH_NULL: abs = "null"; break; default: abs = "never"; break; } if (conn->left.options[KNCF_AUTH] == k_unset || conn->right.options[KNCF_AUTH] == k_unset) { cwf("authby", abs); } } { const char *p2ps = "UNKNOWN"; switch (phase2_policy) { case POLICY_AUTHENTICATE: p2ps = "ah"; break; case POLICY_ENCRYPT: p2ps = "esp"; break; case POLICY_ENCRYPT | POLICY_AUTHENTICATE: p2ps = "ah+esp"; break; default: break; } cwf("phase2", p2ps); } /* ikev2= */ { const char *v2ps = "UNKNOWN"; if (conn->policy & POLICY_IKEV2_ALLOW) v2ps = "yes"; if (conn->policy & POLICY_IKEV1_ALLOW) v2ps = "no"; cwf("ikev2", v2ps); } /* ppk= */ { const char *p_ppk = "UNKNOWN"; switch (ppk_policy) { case LEMPTY: p_ppk = "no"; break; case POLICY_PPK_ALLOW: p_ppk = "permit"; break; case POLICY_PPK_INSIST: p_ppk = "insist"; break; } cwf("ppk", p_ppk); } /* esn= */ { const char *esn = "UNKNOWN"; if ((conn->policy & POLICY_ESN_NO)) { if ((conn->policy & POLICY_ESN_YES) == LEMPTY) esn = "no"; else esn = "either"; } else { /* both cannot be unset */ esn = "yes"; } cwf("esn", esn); } { const char *ifp = "UNKNOWN"; switch (ike_frag_policy) { case LEMPTY: ifp = "never"; break; case POLICY_IKE_FRAG_ALLOW: /* it's the default, do not print anything */ ifp = NULL; break; case POLICY_IKE_FRAG_ALLOW | POLICY_IKE_FRAG_FORCE: ifp = "force"; break; } if (ifp != NULL) cwf("ike_frag", ifp); } break; /* end of case POLICY_SHUNT_TRAP */ case POLICY_SHUNT_PASS: cwf("type", "passthrough"); break; case POLICY_SHUNT_DROP: cwf("type", "drop"); break; case POLICY_SHUNT_REJECT: cwf("type", "reject"); break; } # undef cwpb # undef cwpbf } if (verbose) fprintf(out, "# end conn %s\n\n", conn->name); # undef cwf } void confwrite(struct starter_config *cfg, FILE *out, bool setup, char *name, bool verbose) { struct starter_conn *conn; /* output version number */ /* fprintf(out, "\nversion 2.0\n\n"); */ /* output config setup section */ if (setup) { fprintf(out, "config setup\n"); confwrite_int(out, "", kv_config, cfg->setup.options, cfg->setup.options_set, cfg->setup.strings); confwrite_str(out, "", kv_config, cfg->setup.strings, cfg->setup.strings_set); fprintf(out, "\n"); } /* output connections */ for (conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) if (name == NULL || streq(name, conn->name)) confwrite_conn(out, conn, verbose); if (verbose) fprintf(out, "# end of config\n"); } libreswan-3.32/lib/libipsecconf/interfaces.c000066400000000000000000000053301365625662500211450ustar00rootroot00000000000000/* Libreswan interfaces management (interfaces.c) * Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security * Copyright (C) 2012 Paul Wouters * Copyright (C) 2013 D. Hugh Redelmeier * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include #include #include #include #include #include #include #include #include "sysdep.h" #include "constants.h" #include "ip_endpoint.h" #include "ip_address.h" #include "socketwrapper.h" #include "libreswan/ipsec_tunnel.h" #include "libreswan/passert.h" #include "ipsecconf/interfaces.h" #include "ipsecconf/exec.h" #include "ipsecconf/starterlog.h" #include "lswlog.h" /* for pexpect() */ bool starter_iface_find(const char *iface, int af, ip_address *dst, ip_address *nh) { /* XXX: danger REQ is recycled by ioctl() callss */ struct ifreq req; if (iface == NULL) return false; /* ??? can this ever happen? */ int sock = safe_socket(af, SOCK_DGRAM, 0); if (sock < 0) return false; fill_and_terminate(req.ifr_name, iface, IFNAMSIZ); /* UP? */ if (ioctl(sock, SIOCGIFFLAGS, &req) != 0 || (req.ifr_flags & IFF_UP) == 0x0) { close(sock); return false; } /* * convert the sockaddr to an endpoint (ADDRESS:PORT, but * expect PORT==0)) and then extract just the address */ /* get NH */ if ((req.ifr_flags & IFF_POINTOPOINT) != 0x0 && nh != NULL && (ioctl(sock, SIOCGIFDSTADDR, &req) == 0)) { const ip_sockaddr *sa = (const ip_sockaddr *)&req.ifr_addr; passert(&sa->sa == &req.ifr_addr); if (sa->sa.sa_family == af) { /* XXX: sizeof right? */ ip_endpoint nhe; happy(sockaddr_to_endpoint(sa, sizeof(*sa), &nhe)); pexpect(endpoint_hport(&nhe) == 0); *nh = endpoint_address(&nhe); } } /* get DST */ if (dst != NULL && ioctl(sock, SIOCGIFADDR, &req) == 0) { const ip_sockaddr *sa = (const ip_sockaddr *)&req.ifr_addr; passert(&sa->sa == &req.ifr_addr); if (sa->sa.sa_family == af) { /* XXX: sizeof right? */ ip_endpoint dste; happy(sockaddr_to_endpoint(sa, sizeof(*sa), &dste)); pexpect(endpoint_hport(&dste) == 0); *dst = endpoint_address(&dste); } } close(sock); return true; } libreswan-3.32/lib/libipsecconf/keywords.c000066400000000000000000001076551365625662500207060ustar00rootroot00000000000000/* * Libreswan config file parser (keywords.c) * Copyright (C) 2003-2006 Michael Richardson * Copyright (C) 2007-2010 Paul Wouters * Copyright (C) 2012 Paul Wouters * Copyright (C) 2013-2019 Paul Wouters * Copyright (C) 2013-2019 D. Hugh Redelmeier * Copyright (C) 2013 David McCullough * Copyright (C) 2013-2016 Antony Antony * Copyright (C) 2016-2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include #include #include #include #include #include #include #include "constants.h" #include "lmod.h" #include "lswcdefs.h" /* for elemsof() */ #include "ipsecconf/keywords.h" #include "ipsecconf/parser.h" /* includes parser.tab.h generated by bison; requires keywords.h */ #include "ipsecconf/parserlast.h" #define VALUES_INITIALIZER(t) { (t), elemsof(t) } /* * Values for failureshunt={passthrough, drop, reject, none} */ static const struct keyword_enum_value kw_failureshunt_values[] = { { "none", KFS_FAIL_NONE }, { "passthrough", KFS_FAIL_PASS }, { "drop", KFS_FAIL_DROP }, { "hold", KFS_FAIL_DROP }, /* alias */ { "reject", KFS_FAIL_REJECT }, }; static const struct keyword_enum_values kw_failureshunt_list = VALUES_INITIALIZER(kw_failureshunt_values); /* * Values for negotiationshunt={passthrough, drop} */ static const struct keyword_enum_value kw_negotiationshunt_values[] = { { "passthrough", KNS_FAIL_PASS }, { "drop", KNS_FAIL_DROP }, { "hold", KNS_FAIL_DROP }, /* alias */ }; static const struct keyword_enum_values kw_negotiationshunt_list = VALUES_INITIALIZER(kw_negotiationshunt_values); /* * Values for keyexchange= */ static const struct keyword_enum_value kw_keyexchange_values[] = { { "ike", KE_IKE }, }; static const struct keyword_enum_values kw_keyexchange_list = VALUES_INITIALIZER(kw_keyexchange_values); /* * Values for Four-State options, used for ppk= */ static const struct keyword_enum_value kw_fourvalued_values[] = { { "never", fo_never }, { "permit", fo_permit }, { "propose", fo_propose }, { "insist", fo_insist }, { "yes", fo_propose }, { "always", fo_insist }, { "no", fo_never } }; static const struct keyword_enum_values kw_fourvalued_list = VALUES_INITIALIZER(kw_fourvalued_values); /* * Values for yes/no/force, used by fragmentation= */ static const struct keyword_enum_value kw_ynf_values[] = { { "never", ynf_no }, { "no", ynf_no }, { "yes", ynf_yes }, { "insist", ynf_force }, { "force", ynf_force }, }; static const struct keyword_enum_values kw_ynf_list = VALUES_INITIALIZER(kw_ynf_values); #ifdef USE_XFRM_INTERFACE /* Values for no/yes, used by ipsec-interface */ static const struct keyword_enum_value kw_yn_values[] = { { "yes", yn_yes }, { "no", yn_no }, }; static const struct keyword_enum_values kw_yn_list = VALUES_INITIALIZER(kw_yn_values); #endif /* Values for yes/no/auto, used by encapsulation and nic-offload */ static const struct keyword_enum_value kw_yna_values[] = { { "yes", yna_yes }, { "no", yna_no }, { "auto", yna_auto }, }; static const struct keyword_enum_values kw_yna_list = VALUES_INITIALIZER(kw_yna_values); static const struct keyword_enum_value kw_esn_values[] = { { "yes", ESN_YES }, { "no", ESN_NO }, { "either", ESN_EITHER }, }; static const struct keyword_enum_values kw_esn_list = VALUES_INITIALIZER(kw_esn_values); static const struct keyword_enum_value kw_ddos_values[] = { { "auto", DDOS_AUTO }, { "busy", DDOS_FORCE_BUSY }, { "unlimited", DDOS_FORCE_UNLIMITED }, }; static const struct keyword_enum_values kw_ddos_list = VALUES_INITIALIZER(kw_ddos_values); #ifdef HAVE_SECCOMP static const struct keyword_enum_value kw_seccomp_values[] = { { "enabled", SECCOMP_ENABLED }, { "disabled", SECCOMP_DISABLED }, { "tolerant", SECCOMP_TOLERANT }, }; static const struct keyword_enum_values kw_seccomp_list = VALUES_INITIALIZER(kw_seccomp_values); #endif static const struct keyword_enum_value kw_auth_lr_values[] = { { "never", AUTH_NEVER }, { "secret", AUTH_PSK }, { "rsasig", AUTH_RSASIG }, { "null", AUTH_NULL }, }; static const struct keyword_enum_values kw_auth_lr_list = VALUES_INITIALIZER(kw_auth_lr_values); /* * Values for dpdaction={hold,clear,restart} */ static const struct keyword_enum_value kw_dpdaction_values[] = { { "hold", DPD_ACTION_HOLD }, { "clear", DPD_ACTION_CLEAR }, { "restart", DPD_ACTION_RESTART }, /* obsoleted keyword - functionality moved into "restart" */ { "restart_by_peer", DPD_ACTION_RESTART }, }; static const struct keyword_enum_values kw_dpdaction_list = VALUES_INITIALIZER(kw_dpdaction_values); /* * Values for sendca={none,issuer,all} */ static const struct keyword_enum_value kw_sendca_values[] = { { "none", CA_SEND_NONE }, { "issuer", CA_SEND_ISSUER }, { "all", CA_SEND_ALL }, }; static const struct keyword_enum_values kw_sendca_list = VALUES_INITIALIZER(kw_sendca_values); /* * Values for auto={add,start,route,ignore} */ static const struct keyword_enum_value kw_auto_values[] = { { "ignore", STARTUP_IGNORE }, /* no keyword for STARTUP_POLICY */ { "add", STARTUP_ADD }, { "ondemand", STARTUP_ONDEMAND }, { "route", STARTUP_ONDEMAND }, /* backwards compatibility alias */ { "start", STARTUP_START }, { "up", STARTUP_START }, /* alias */ }; static const struct keyword_enum_values kw_auto_list = VALUES_INITIALIZER(kw_auto_values); /* * Values for addrfamily={ipv4,ipv6} */ static const struct keyword_enum_value kw_addrfamily_values[] = { { "ipv4", AF_INET }, { "ipv6", AF_INET6 }, /* aliases - undocumented on purpose */ { "v4", AF_INET }, { "inet", AF_INET }, { "v6", AF_INET6 }, { "inet6", AF_INET6 }, }; static const struct keyword_enum_values kw_addrfamily_list = VALUES_INITIALIZER(kw_addrfamily_values); /* * Values for type={tunnel,transport,etc} */ static const struct keyword_enum_value kw_type_values[] = { { "tunnel", KS_TUNNEL }, { "transport", KS_TRANSPORT }, { "pass", KS_PASSTHROUGH }, { "passthrough", KS_PASSTHROUGH }, { "reject", KS_REJECT }, { "drop", KS_DROP }, }; static const struct keyword_enum_values kw_type_list = VALUES_INITIALIZER(kw_type_values); /* * Values for rsasigkey={ %cert, %dnsondemand, %dns, literal } */ static const struct keyword_enum_value kw_rsasigkey_values[] = { { "", PUBKEY_PREEXCHANGED }, { "%cert", PUBKEY_CERTIFICATE }, #ifdef USE_DNSSEC { "%dns", PUBKEY_DNSONDEMAND }, { "%dnsondemand", PUBKEY_DNSONDEMAND }, #endif }; static const struct keyword_enum_values kw_rsasigkey_list = VALUES_INITIALIZER(kw_rsasigkey_values); /* * Values for protostack={netkey, klips, mast or none } */ static const struct keyword_enum_value kw_proto_stack_list[] = { { "none", NO_KERNEL }, { "klips", USE_KLIPS }, { "auto", USE_NETKEY }, /* auto now means netkey */ { "netkey", USE_NETKEY }, { "native", USE_NETKEY }, { "bsd", USE_BSDKAME }, { "kame", USE_BSDKAME }, { "bsdkame", USE_BSDKAME }, { "win2k", USE_WIN2K }, }; static const struct keyword_enum_values kw_proto_stack = VALUES_INITIALIZER(kw_proto_stack_list); /* * Values for sareftrack={yes, no, conntrack } */ static const struct keyword_enum_value kw_sareftrack_values[] = { { "yes", SAT_YES }, { "no", SAT_NO }, { "conntrack", SAT_CONNTRACK }, }; static const struct keyword_enum_values kw_sareftrack_list = VALUES_INITIALIZER(kw_sareftrack_values); /* * Cisco interop: remote peer type */ static const struct keyword_enum_value kw_remote_peer_type_list[] = { { "cisco", CISCO }, }; static const struct keyword_enum_values kw_remote_peer_type = VALUES_INITIALIZER(kw_remote_peer_type_list); static const struct keyword_enum_value kw_xauthby_list[] = { { "file", XAUTHBY_FILE }, #ifdef XAUTH_HAVE_PAM { "pam", XAUTHBY_PAM }, #endif { "alwaysok", XAUTHBY_ALWAYSOK }, }; static const struct keyword_enum_values kw_xauthby = VALUES_INITIALIZER(kw_xauthby_list); static const struct keyword_enum_value kw_xauthfail_list[] = { { "hard", XAUTHFAIL_HARD }, { "soft", XAUTHFAIL_SOFT }, }; static const struct keyword_enum_values kw_xauthfail = VALUES_INITIALIZER(kw_xauthfail_list); /* * Values for right= and left= */ static struct keyword_enum_value kw_host_values[] = { { "%defaultroute", KH_DEFAULTROUTE }, { "%any", KH_ANY }, { "%", KH_IFACE }, { "%oppo", KH_OPPO }, { "%opportunistic", KH_OPPO }, { "%opportunisticgroup", KH_OPPOGROUP }, { "%oppogroup", KH_OPPOGROUP }, { "%group", KH_GROUP }, { "%hostname", KH_IPHOSTNAME }, /* makes no sense on input */ }; static struct keyword_enum_values kw_host_list = { kw_host_values, elemsof(kw_host_values) }; static const struct keyword_enum_value kw_klipsdebug_values[] = { { "all", LRANGE(KDF_XMIT, KDF_COMP) }, { "none", 0 }, { "verbose", LELEM(KDF_VERBOSE) }, { "xmit", LELEM(KDF_XMIT) }, { "tunnel-xmit", LELEM(KDF_XMIT) }, { "netlink", LELEM(KDF_NETLINK) }, { "xform", LELEM(KDF_XFORM) }, { "eroute", LELEM(KDF_EROUTE) }, { "spi", LELEM(KDF_SPI) }, { "radij", LELEM(KDF_RADIJ) }, { "esp", LELEM(KDF_ESP) }, { "ah", LELEM(KDF_AH) }, { "rcv", LELEM(KDF_RCV) }, { "tunnel", LELEM(KDF_TUNNEL) }, { "pfkey", LELEM(KDF_PFKEY) }, { "comp", LELEM(KDF_COMP) }, { "nat-traversal", LELEM(KDF_NATT) }, { "nattraversal", LELEM(KDF_NATT) }, { "natt", LELEM(KDF_NATT) }, }; static const struct keyword_enum_values kw_klipsdebug_list = VALUES_INITIALIZER(kw_klipsdebug_values); static const struct keyword_enum_value kw_phase2types_values[] = { /* note: these POLICY bits happen to fit in an unsigned int */ /* note2: ah+esp is no longer supported as per RFC-8221 Section 4 */ { "esp", POLICY_ENCRYPT }, { "ah", POLICY_AUTHENTICATE }, { "default", POLICY_ENCRYPT }, /* alias, find it last */ }; static const struct keyword_enum_values kw_phase2types_list = VALUES_INITIALIZER(kw_phase2types_values); /* * Values for {left/right}sendcert={never,sendifasked,always,forcedtype} */ static const struct keyword_enum_value kw_sendcert_values[] = { { "never", CERT_NEVERSEND}, { "sendifasked", CERT_SENDIFASKED }, { "alwayssend", CERT_ALWAYSSEND }, { "always", CERT_ALWAYSSEND }, }; static const struct keyword_enum_values kw_sendcert_list = VALUES_INITIALIZER(kw_sendcert_values); /* * Values for nat-ikev1-method={drafts,rfc,both,none} */ static const struct keyword_enum_value kw_ikev1natt_values[] = { { "both", NATT_BOTH }, { "rfc", NATT_RFC }, { "drafts", NATT_DRAFTS }, { "none", NATT_NONE }, }; static const struct keyword_enum_values kw_ikev1natt_list = VALUES_INITIALIZER(kw_ikev1natt_values); /* * Values for ocsp-method={get|post} * * This sets the NSS forcePost option for the OCSP request. * If forcePost is set, OCSP requests will only be sent using the HTTP POST * method. When forcePost is not set, OCSP requests will be sent using the * HTTP GET method, with a fallback to POST when we fail to receive a response * and/or when we receive an uncacheable response like "Unknown". */ static const struct keyword_enum_value kw_ocsp_method_values[] = { { "get", OCSP_METHOD_GET }, { "post", OCSP_METHOD_POST }, }; static const struct keyword_enum_values kw_ocsp_method_list = VALUES_INITIALIZER(kw_ocsp_method_values); /* MASTER KEYWORD LIST * Note: this table is terminated by an entry with keyname == NULL. */ const struct keyword_def ipsec_conf_keywords[] = { { "interfaces", kv_config, kt_string, KSF_INTERFACES, NULL, NULL, }, { "curl-iface", kv_config, kt_string, KSF_CURLIFACE, NULL, NULL, }, { "curl-timeout", kv_config, kt_time, KBF_CURLTIMEOUT, NULL, NULL, }, /* * These two aliases are needed because "-" versions could not work * on openswan shell scripts. They only exist on rhel openwan 6.7+ * So they are needed to support RHEL openswan -> libreswan migration. */ { "curl_iface", kv_config | kv_alias, kt_string, KSF_CURLIFACE, NULL, NULL, }, /* obsolete _ */ { "curl_timeout", kv_config | kv_alias, kt_time, KBF_CURLTIMEOUT, NULL, NULL, }, /* obsolete _ */ { "myvendorid", kv_config, kt_string, KSF_MYVENDORID, NULL, NULL, }, { "syslog", kv_config, kt_string, KSF_SYSLOG, NULL, NULL, }, { "klipsdebug", kv_config, kt_list, KBF_KLIPSDEBUG, &kw_klipsdebug_list, NULL, }, { "plutodebug", kv_config, kt_lset, KBF_PLUTODEBUG, NULL, &debug_lmod_info, }, { "logfile", kv_config, kt_filename, KSF_LOGFILE, NULL, NULL, }, { "plutostderrlog", kv_config | kv_alias, kt_filename, KSF_LOGFILE, NULL, NULL, }, /* obsolete */ { "logtime", kv_config, kt_bool, KBF_LOGTIME, NULL, NULL, }, { "plutostderrlogtime", kv_config | kv_alias, kt_bool, KBF_LOGTIME, NULL, NULL, }, /* obsolete */ { "logappend", kv_config, kt_bool, KBF_LOGAPPEND, NULL, NULL, }, { "logip", kv_config, kt_bool, KBF_LOGIP, NULL, NULL, }, { "audit-log", kv_config, kt_bool, KBF_AUDIT_LOG, NULL, NULL, }, #ifdef USE_DNSSEC { "dnssec-enable", kv_config, kt_bool, KBF_DO_DNSSEC, NULL, NULL, }, { "dnssec-rootkey-file", kv_config, kt_filename, KSF_PLUTO_DNSSEC_ROOTKEY_FILE, NULL, NULL, }, { "dnssec-anchors", kv_config, kt_filename, KSF_PLUTO_DNSSEC_ANCHORS, NULL, NULL, }, #endif { "dumpdir", kv_config, kt_dirname, KSF_DUMPDIR, NULL, NULL, }, { "ipsecdir", kv_config, kt_dirname, KSF_IPSECDIR, NULL, NULL, }, { "nssdir", kv_config, kt_dirname, KSF_NSSDIR, NULL, NULL, }, { "secretsfile", kv_config, kt_dirname, KSF_SECRETSFILE, NULL, NULL, }, { "statsbin", kv_config, kt_dirname, KSF_STATSBINARY, NULL, NULL, }, { "perpeerlog", kv_config, kt_bool, KBF_PERPEERLOG, NULL, NULL, }, { "perpeerlogdir", kv_config, kt_dirname, KSF_PERPEERDIR, NULL, NULL, }, { "fragicmp", kv_config, kt_bool, KBF_FRAGICMP, NULL, NULL, }, { "hidetos", kv_config, kt_bool, KBF_HIDETOS, NULL, NULL, }, { "uniqueids", kv_config, kt_bool, KBF_UNIQUEIDS, NULL, NULL, }, { "shuntlifetime", kv_config, kt_time, KBF_SHUNTLIFETIME, NULL, NULL, }, { "overridemtu", kv_config, kt_number, KBF_OVERRIDEMTU, NULL, NULL, }, { "global-redirect", kv_config, kt_string, KSF_GLOBAL_REDIRECT, NULL, NULL }, { "global-redirect-to", kv_config, kt_string, KSF_GLOBAL_REDIRECT_TO, NULL, NULL, }, { "crl-strict", kv_config, kt_bool, KBF_CRL_STRICT, NULL, NULL, }, { "crl_strict", kv_config | kv_alias, kt_bool, KBF_CRL_STRICT, NULL, NULL, }, /* obsolete _ */ { "crlcheckinterval", kv_config, kt_time, KBF_CRL_CHECKINTERVAL, NULL, NULL, }, { "strictcrlpolicy", kv_config | kv_alias, kt_bool, KBF_CRL_STRICT, NULL, NULL, }, /* obsolete; used on openswan */ { "ocsp-strict", kv_config, kt_bool, KBF_OCSP_STRICT, NULL, NULL, }, { "ocsp_strict", kv_config | kv_alias, kt_bool, KBF_OCSP_STRICT, NULL, NULL, }, /* obsolete _ */ { "ocsp-enable", kv_config, kt_bool, KBF_OCSP_ENABLE, NULL, NULL, }, { "ocsp_enable", kv_config | kv_alias, kt_bool, KBF_OCSP_ENABLE, NULL, NULL, }, /* obsolete _ */ { "ocsp-uri", kv_config, kt_string, KSF_OCSP_URI, NULL, NULL, }, { "ocsp_uri", kv_config | kv_alias, kt_string, KSF_OCSP_URI, NULL, NULL, }, /* obsolete _ */ { "ocsp-timeout", kv_config, kt_number, KBF_OCSP_TIMEOUT, NULL, NULL, }, { "ocsp_timeout", kv_config | kv_alias, kt_number, KBF_OCSP_TIMEOUT, NULL, NULL, }, /* obsolete _ */ { "ocsp-trustname", kv_config, kt_string, KSF_OCSP_TRUSTNAME, NULL, NULL, }, { "ocsp_trust_name", kv_config | kv_alias, kt_string, KSF_OCSP_TRUSTNAME, NULL, NULL, }, /* obsolete _ */ { "ocsp-cache-size", kv_config, kt_number, KBF_OCSP_CACHE_SIZE, NULL, NULL, }, { "ocsp-cache-min-age", kv_config, kt_time, KBF_OCSP_CACHE_MIN, NULL, NULL, }, { "ocsp-cache-max-age", kv_config, kt_time, KBF_OCSP_CACHE_MAX, NULL, NULL, }, { "ocsp-method", kv_config | kv_processed, kt_enum, KBF_OCSP_METHOD, &kw_ocsp_method_list, NULL, }, { "ddos-mode", kv_config | kv_processed , kt_enum, KBF_DDOS_MODE, &kw_ddos_list, NULL, }, #ifdef HAVE_SECCOMP { "seccomp", kv_config | kv_processed , kt_enum, KBF_SECCOMP, &kw_seccomp_list, NULL, }, #endif { "ddos-ike-threshold", kv_config, kt_number, KBF_DDOS_IKE_THRESHOLD, NULL, NULL, }, { "max-halfopen-ike", kv_config, kt_number, KBF_MAX_HALFOPEN_IKE, NULL, NULL, }, { "ikeport", kv_config, kt_number, KBF_IKEPORT, NULL, NULL, }, { "ike-socket-bufsize", kv_config, kt_number, KBF_IKEBUF, NULL, NULL, }, { "ike-socket-errqueue", kv_config, kt_bool, KBF_IKE_ERRQUEUE, NULL, NULL, }, { "nflog-all", kv_config, kt_number, KBF_NFLOG_ALL, NULL, NULL, }, { "xfrmlifetime", kv_config, kt_number, KBF_XFRMLIFETIME, NULL, NULL, }, { "virtual_private", kv_config | kv_alias, kt_string, KSF_VIRTUALPRIVATE, NULL, NULL, }, /* obsolete _ */ { "virtual-private", kv_config, kt_string, KSF_VIRTUALPRIVATE, NULL, NULL, }, { "nat_ikeport", kv_config | kv_alias, kt_number, KBF_NATIKEPORT, NULL, NULL, }, /* obsolete _ */ { "nat-ikeport", kv_config, kt_number, KBF_NATIKEPORT, NULL, NULL, }, { "seedbits", kv_config, kt_number, KBF_SEEDBITS, NULL, NULL, }, { "keep_alive", kv_config | kv_alias, kt_number, KBF_KEEPALIVE, NULL, NULL, }, /* obsolete _ */ { "keep-alive", kv_config, kt_number, KBF_KEEPALIVE, NULL, NULL, }, { "listen", kv_config, kt_string, KSF_LISTEN, NULL, NULL, }, { "protostack", kv_config, kt_string, KSF_PROTOSTACK, &kw_proto_stack, NULL, }, { "nhelpers", kv_config, kt_number, KBF_NHELPERS, NULL, NULL, }, { "drop-oppo-null", kv_config, kt_bool, KBF_DROP_OPPO_NULL, NULL, NULL, }, #ifdef HAVE_LABELED_IPSEC /* It is really an attribute type, not a value */ { "secctx_attr_value", kv_config | kv_alias, kt_number, KBF_SECCTX, NULL, NULL, }, /* obsolete _ */ { "secctx-attr-value", kv_config, kt_number, KBF_SECCTX, NULL, NULL, }, /* obsolete: not a value, a type */ { "secctx-attr-type", kv_config, kt_number, KBF_SECCTX, NULL, NULL, }, #endif /* these options are obsoleted (and not old aliases) */ { "plutorestartoncrash", kv_config, kt_obsolete, KNCF_WARNIGNORE, NULL, NULL, }, { "forwardcontrol", kv_config, kt_obsolete, KNCF_WARNIGNORE, NULL, NULL, }, { "rp_filter", kv_config, kt_obsolete, KNCF_WARNIGNORE, NULL, NULL, }, { "pluto", kv_config, kt_obsolete, KNCF_WARNIGNORE, NULL, NULL, }, { "prepluto", kv_config, kt_obsolete, KNCF_WARNIGNORE, NULL, NULL, }, { "postpluto", kv_config, kt_obsolete, KNCF_WARNIGNORE, NULL, NULL, }, { "plutoopts", kv_config, kt_obsolete, KNCF_WARNIGNORE, NULL, NULL, }, { "plutowait", kv_config, kt_obsolete, KNCF_WARNIGNORE, NULL, NULL, }, { "nocrsend", kv_config, kt_obsolete, KNCF_WARNIGNORE, NULL, NULL, }, { "nat_traversal", kv_config, kt_obsolete, KNCF_WARNIGNORE, NULL, NULL, }, { "disable_port_floating", kv_config, kt_obsolete, KNCF_WARNIGNORE, NULL, NULL, }, { "force_keepalive", kv_config, kt_obsolete, KNCF_WARNIGNORE, NULL, NULL, }, { "plutofork", kv_config | kv_alias, kt_obsolete, KNCF_WARNIGNORE, NULL, NULL, }, /* obsolete */ { "force-busy", kv_config, kt_obsolete, KNCF_WARNIGNORE, NULL, NULL, }, /* obsoleted for ddos-mode=busy */ { "oe", kv_config, kt_obsolete, KNCF_WARNIGNORE, NULL, NULL, }, /* * This is "left=" and "right=" */ { "", kv_conn | kv_leftright| kv_processed, kt_loose_enum, KSCF_IP, &kw_host_list, NULL, }, { "subnet", kv_conn | kv_leftright | kv_processed, kt_subnet, KSCF_SUBNET, NULL, NULL, }, { "subnets", kv_conn | kv_leftright, kt_appendlist, KSCF_SUBNETS, NULL, NULL, }, { "sourceip", kv_conn | kv_leftright, kt_ipaddr, KSCF_SOURCEIP, NULL, NULL, }, { "interface-ip", kv_conn | kv_leftright, kt_subnet, KSCF_INTERFACE_IP, NULL, NULL, }, { "vti", kv_conn | kv_leftright | kv_processed, kt_subnet, KSCF_VTI_IP, NULL, NULL, }, { "nexthop", kv_conn | kv_leftright, kt_ipaddr, KSCF_NEXTHOP, NULL, NULL, }, { "updown", kv_conn | kv_leftright, kt_filename, KSCF_UPDOWN, NULL, NULL, }, { "id", kv_conn | kv_leftright, kt_idtype, KSCF_ID, NULL, NULL, }, { "rsasigkey", kv_conn | kv_leftright, kt_rsakey, KSCF_RSAKEY1, &kw_rsasigkey_list, NULL, }, { "rsasigkey2", kv_conn | kv_leftright, kt_rsakey, KSCF_RSAKEY2, &kw_rsasigkey_list, NULL, }, { "cert", kv_conn | kv_leftright, kt_filename, KSCF_CERT, NULL, NULL, }, { "ckaid", kv_conn | kv_leftright, kt_string, KSCF_CKAID, NULL, NULL, }, { "sendcert", kv_conn | kv_leftright, kt_enum, KNCF_SENDCERT, &kw_sendcert_list, NULL, }, { "ca", kv_conn | kv_leftright, kt_string, KSCF_CA, NULL, NULL, }, { "xauthserver", kv_conn | kv_leftright, kt_bool, KNCF_XAUTHSERVER, NULL, NULL, }, { "xauthclient", kv_conn | kv_leftright, kt_bool, KNCF_XAUTHCLIENT, NULL, NULL, }, { "modecfgserver", kv_conn | kv_leftright, kt_bool, KNCF_MODECONFIGSERVER, NULL, NULL, }, { "modecfgclient", kv_conn | kv_leftright, kt_bool, KNCF_MODECONFIGCLIENT, NULL, NULL, }, { "username", kv_conn | kv_leftright, kt_string, KSCF_USERNAME, NULL, NULL, }, { "xauthusername", kv_conn | kv_leftright | kv_alias, kt_string, KSCF_USERNAME, NULL, NULL, }, /* obsolete name */ { "xauthname", kv_conn | kv_leftright | kv_alias, kt_string, KSCF_USERNAME, NULL, NULL, }, /* obsolete name */ { "addresspool", kv_conn | kv_leftright, kt_range, KSCF_ADDRESSPOOL, NULL, NULL, }, { "auth", kv_conn | kv_leftright, kt_enum, KNCF_AUTH, &kw_auth_lr_list, NULL, }, { "cat", kv_conn | kv_leftright, kt_bool, KNCF_CAT, NULL, NULL, }, { "protoport", kv_conn | kv_leftright | kv_processed, kt_string, KSCF_PROTOPORT, NULL, NULL, }, /* these are conn statements which are not left/right */ { "auto", kv_conn | kv_duplicateok, kt_enum, KNCF_AUTO, &kw_auto_list, NULL, }, { "also", kv_conn, kt_appendstring, KSCF_ALSO, NULL, NULL, }, { "alsoflip", kv_conn, kt_string, KSCF_ALSOFLIP, NULL, NULL, }, { "ike", kv_conn, kt_string, KSCF_IKE, NULL, NULL, }, { "hostaddrfamily", kv_conn, kt_enum, KNCF_HOSTADDRFAMILY, &kw_addrfamily_list, NULL, }, { "clientaddrfamily", kv_conn, kt_enum, KNCF_CLIENTADDRFAMILY, &kw_addrfamily_list, NULL, }, { "connaddrfamily", kv_conn, kt_obsolete, KNCF_WARNIGNORE, NULL, NULL, }, /* obsolete */ { "type", kv_conn, kt_enum, KNCF_TYPE, &kw_type_list, NULL, }, { "authby", kv_conn, kt_string, KSCF_AUTHBY, NULL, NULL, }, { "keyexchange", kv_conn, kt_enum, KNCF_KEYEXCHANGE, &kw_keyexchange_list, NULL, }, { "ikev2", kv_conn | kv_processed, kt_enum, KNCF_IKEv2, &kw_fourvalued_list, NULL, }, { "ppk", kv_conn | kv_processed, kt_enum, KNCF_PPK, &kw_fourvalued_list, NULL, }, { "esn", kv_conn | kv_processed, kt_enum, KNCF_ESN, &kw_esn_list, NULL, }, { "decap-dscp", kv_conn | kv_processed, kt_bool, KNCF_DECAP_DSCP, NULL, NULL, }, { "nopmtudisc", kv_conn | kv_processed, kt_bool, KNCF_NOPMTUDISC, NULL, NULL, }, { "ike_frag", kv_conn | kv_processed | kv_alias, kt_enum, KNCF_IKE_FRAG, &kw_ynf_list, NULL, }, /* obsolete _ */ { "ike-frag", kv_conn | kv_processed | kv_alias, kt_enum, KNCF_IKE_FRAG, &kw_ynf_list, NULL, }, /* obsolete name */ { "fragmentation", kv_conn | kv_processed, kt_enum, KNCF_IKE_FRAG, &kw_ynf_list, NULL, }, { "mobike", kv_conn, kt_bool, KNCF_MOBIKE, NULL, NULL, }, { "narrowing", kv_conn, kt_bool, KNCF_IKEv2_ALLOW_NARROWING, NULL, NULL, }, { "pam-authorize", kv_conn, kt_bool, KNCF_IKEv2_PAM_AUTHORIZE, NULL, NULL, }, { "send-redirect", kv_conn, kt_enum, KNCF_SEND_REDIRECT, &kw_yna_list, NULL, }, { "redirect-to", kv_conn, kt_string, KSCF_REDIRECT_TO, NULL, NULL, }, { "accept-redirect", kv_conn, kt_enum, KNCF_ACCEPT_REDIRECT, &kw_yna_list, NULL, }, { "accept-redirect-to", kv_conn, kt_string, KSCF_ACCEPT_REDIRECT_TO, NULL, NULL, }, { "sareftrack", kv_conn | kv_processed, kt_enum, KNCF_SAREFTRACK, &kw_sareftrack_list, NULL, }, { "pfs", kv_conn, kt_bool, KNCF_PFS, NULL, NULL, }, { "nat_keepalive", kv_conn | kv_alias, kt_bool, KNCF_NAT_KEEPALIVE, NULL, NULL, }, /* obsolete _ */ { "nat-keepalive", kv_conn, kt_bool, KNCF_NAT_KEEPALIVE, NULL, NULL, }, { "initial_contact", kv_conn | kv_alias, kt_bool, KNCF_INITIAL_CONTACT, NULL, NULL, }, /* obsolete _ */ { "initial-contact", kv_conn, kt_bool, KNCF_INITIAL_CONTACT, NULL, NULL, }, { "cisco_unity", kv_conn | kv_alias, kt_bool, KNCF_CISCO_UNITY, NULL, NULL, }, /* obsolete _ */ { "cisco-unity", kv_conn, kt_bool, KNCF_CISCO_UNITY, NULL, NULL, }, { "send-no-esp-tfc", kv_conn, kt_bool, KNCF_NO_ESP_TFC, NULL, NULL, }, { "fake-strongswan", kv_conn, kt_bool, KNCF_VID_STRONGSWAN, NULL, NULL, }, { "send_vendorid", kv_conn | kv_alias, kt_bool, KNCF_SEND_VENDORID, NULL, NULL, }, /* obsolete _ */ { "send-vendorid", kv_conn, kt_bool, KNCF_SEND_VENDORID, NULL, NULL, }, { "sha2_truncbug", kv_conn | kv_alias, kt_bool, KNCF_SHA2_TRUNCBUG, NULL, NULL, }, /* obsolete _ */ { "sha2-truncbug", kv_conn, kt_bool, KNCF_SHA2_TRUNCBUG, NULL, NULL, }, { "ms-dh-downgrade", kv_conn, kt_bool, KNCF_MSDH_DOWNGRADE, NULL, NULL, }, { "require-id-on-certificate", kv_conn, kt_bool, KNCF_SAN_ON_CERT, NULL, NULL, }, { "dns-match-id,", kv_conn, kt_bool, KNCF_DNS_MATCH_ID, NULL, NULL, }, { "keylife", kv_conn | kv_alias, kt_time, KNCF_SALIFETIME, NULL, NULL, }, { "lifetime", kv_conn | kv_alias, kt_time, KNCF_SALIFETIME, NULL, NULL, }, { "salifetime", kv_conn, kt_time, KNCF_SALIFETIME, NULL, NULL, }, { "retransmit-timeout", kv_conn, kt_time, KNCF_RETRANSMIT_TIMEOUT, NULL, NULL, }, { "retransmit-interval", kv_conn, kt_number, KNCF_RETRANSMIT_INTERVAL_MS, NULL, NULL, }, {"ikepad", kv_conn, kt_bool, KNCF_IKEPAD, NULL, NULL, }, { "nat-ikev1-method", kv_conn | kv_processed, kt_enum, KNCF_IKEV1_NATT, &kw_ikev1natt_list, NULL, }, #ifdef HAVE_LABELED_IPSEC /* only policy label is used, non-zero means wanting labeled IPsec */ { "labeled_ipsec", kv_conn, kt_obsolete, KNCF_WARNIGNORE, NULL, NULL, }, /* obsolete */ { "labeled-ipsec", kv_conn, kt_obsolete, KNCF_WARNIGNORE, NULL, NULL, }, /* obsolete */ { "policy_label", kv_conn | kv_alias, kt_string, KSCF_POLICY_LABEL, NULL, NULL, }, /* obsolete _ */ { "policy-label", kv_conn, kt_string, KSCF_POLICY_LABEL, NULL, NULL, }, #endif /* Cisco interop: remote peer type */ { "remote_peer_type", kv_conn | kv_alias, kt_enum, KNCF_REMOTEPEERTYPE, &kw_remote_peer_type, NULL, }, /* obsolete _ */ { "remote-peer-type", kv_conn, kt_enum, KNCF_REMOTEPEERTYPE, &kw_remote_peer_type, NULL, }, /* Network Manager support */ #ifdef HAVE_NM { "nm_configured", kv_conn | kv_alias, kt_bool, KNCF_NMCONFIGURED, NULL, NULL, }, /* obsolete _ */ { "nm-configured", kv_conn, kt_bool, KNCF_NMCONFIGURED, NULL, NULL, }, #endif { "xauthby", kv_conn, kt_enum, KNCF_XAUTHBY, &kw_xauthby, NULL, }, { "xauthfail", kv_conn, kt_enum, KNCF_XAUTHFAIL, &kw_xauthfail, NULL, }, { "modecfgpull", kv_conn, kt_invertbool, KNCF_MODECONFIGPULL, NULL, NULL, }, { "modecfgdns", kv_conn, kt_string, KSCF_MODECFGDNS, NULL, NULL, }, { "modecfgdns1", kv_conn | kv_alias, kt_string, KSCF_MODECFGDNS, NULL, NULL, }, /* obsolete */ { "modecfgdns2", kv_conn, kt_obsolete, KNCF_WARNIGNORE, NULL, NULL, }, /* obsolete */ { "modecfgdomains", kv_conn, kt_string, KSCF_MODECFGDOMAINS, NULL, NULL, }, { "modecfgdomain", kv_conn | kv_alias, kt_string, KSCF_MODECFGDOMAINS, NULL, NULL, }, /* obsolete */ { "modecfgbanner", kv_conn, kt_string, KSCF_MODECFGBANNER, NULL, NULL, }, { "mark", kv_conn, kt_string, KSCF_CONN_MARK_BOTH, NULL, NULL, }, { "mark-in", kv_conn, kt_string, KSCF_CONN_MARK_IN, NULL, NULL, }, { "mark-out", kv_conn, kt_string, KSCF_CONN_MARK_OUT, NULL, NULL, }, { "vti-interface", kv_conn, kt_string, KSCF_VTI_IFACE, NULL, NULL, }, { "vti-routing", kv_conn, kt_bool, KNCF_VTI_ROUTING, NULL, NULL, }, { "vti-shared", kv_conn, kt_bool, KNCF_VTI_SHARED, NULL, NULL, }, #ifdef USE_XFRM_INTERFACE { "ipsec-interface", kv_conn, kt_loose_enum, KNCF_XFRM_IF_ID, &kw_yn_list, NULL, }, #endif { "modecfgwins1", kv_conn, kt_obsolete, KNCF_WARNIGNORE, NULL, NULL, }, { "modecfgwins2", kv_conn, kt_obsolete, KNCF_WARNIGNORE, NULL, NULL, }, { "nic-offload", kv_conn, kt_enum, KNCF_NIC_OFFLOAD, &kw_yna_list, NULL, }, { "encapsulation", kv_conn, kt_enum, KNCF_ENCAPS, &kw_yna_list, NULL, }, { "forceencaps", kv_conn, kt_obsolete, KNCF_WARNIGNORE, NULL, NULL, }, { "overlapip", kv_conn, kt_bool, KNCF_OVERLAPIP, NULL, NULL, }, { "reauth", kv_conn, kt_bool, KNCF_REAUTH, NULL, NULL, }, { "rekey", kv_conn, kt_bool, KNCF_REKEY, NULL, NULL, }, { "rekeymargin", kv_conn, kt_time, KNCF_REKEYMARGIN, NULL, NULL, }, { "rekeyfuzz", kv_conn, kt_percent, KNCF_REKEYFUZZ, NULL, NULL, }, { "keyingtries", kv_conn, kt_number, KNCF_KEYINGTRIES, NULL, NULL, }, { "replay-window", kv_conn, kt_number, KNCF_REPLAY_WINDOW, NULL, NULL, }, { "ikelifetime", kv_conn, kt_time, KNCF_IKELIFETIME, NULL, NULL, }, { "disablearrivalcheck", kv_conn, kt_invertbool, KNCF_ARRIVALCHECK, NULL, NULL, }, { "failureshunt", kv_conn, kt_enum, KNCF_FAILURESHUNT, &kw_failureshunt_list, NULL, }, { "negotiationshunt", kv_conn, kt_enum, KNCF_NEGOTIATIONSHUNT, &kw_negotiationshunt_list, NULL, }, { "connalias", kv_conn | kv_processed, kt_appendstring, KSCF_CONNALIAS, NULL, NULL, }, /* attributes of the phase2 policy */ { "phase2alg", kv_conn, kt_string, KSCF_ESP, NULL, NULL, }, /* synonyms: phase2alg, esp, ah */ { "esp", kv_conn | kv_alias, kt_string, KSCF_ESP, NULL, NULL, }, /* synonyms: phase2alg, esp, ah */ { "ah", kv_conn | kv_alias, kt_string, KSCF_ESP, NULL, NULL, }, /* synonyms: phase2alg, esp, ah */ { "phase2", kv_conn | kv_policy, kt_enum, KNCF_PHASE2, &kw_phase2types_list, NULL, }, { "compress", kv_conn, kt_bool, KNCF_COMPRESS, NULL, NULL, }, /* route metric */ { "metric", kv_conn, kt_number, KNCF_METRIC, NULL, NULL, }, /* DPD */ { "dpddelay", kv_conn, kt_time, KNCF_DPDDELAY, NULL, NULL, }, { "dpdtimeout", kv_conn, kt_time, KNCF_DPDTIMEOUT, NULL, NULL, }, { "dpdaction", kv_conn, kt_enum, KNCF_DPDACTION, &kw_dpdaction_list, NULL, }, { "sendca", kv_conn, kt_enum, KNCF_SEND_CA, &kw_sendca_list, NULL, }, { "mtu", kv_conn, kt_number, KNCF_CONNMTU, NULL, NULL, }, { "priority", kv_conn, kt_number, KNCF_PRIORITY, NULL, NULL, }, { "tfc", kv_conn, kt_number, KNCF_TFCPAD, NULL, NULL, }, { "reqid", kv_conn, kt_number, KNCF_REQID, NULL, NULL, }, { "nflog", kv_conn, kt_number, KNCF_NFLOG_CONN, NULL, NULL, }, { "aggressive", kv_conn, kt_invertbool, KNCF_AGGRMODE, NULL, NULL, }, /* alias for compatibility - undocumented on purpose */ { "aggrmode", kv_conn | kv_alias, kt_invertbool, KNCF_AGGRMODE, NULL, NULL, }, { NULL, 0, 0, 0, NULL, NULL, } }; /* distinguished keyword */ static const struct keyword_def ipsec_conf_keyword_comment = { "x-comment", kv_conn, kt_comment, 0, NULL, NULL, }; /* * look for one of the above tokens, and set the value up right. * * if we don't find it, then strdup() the string and return a string * */ /* type is really "token" type, which is actually int */ int parser_find_keyword(const char *s, YYSTYPE *lval) { const struct keyword_def *k; bool keyleft; int keywordtype; keyleft = FALSE; k = ipsec_conf_keywords; while (k->keyname != NULL) { if (strcaseeq(s, k->keyname)) break; if (k->validity & kv_leftright) { if (strncaseeq(s, "left", 4) && strcaseeq(s + 4, k->keyname)) { keyleft = TRUE; break; } else if (strncaseeq(s, "right", 5) && strcaseeq(s + 5, k->keyname)) { keyleft = FALSE; break; } } k++; } lval->s = NULL; /* if we found nothing */ if (k->keyname == NULL && (s[0] == 'x' || s[0] == 'X') && (s[1] == '-' || s[1] == '_')) { k = &ipsec_conf_keyword_comment; lval->k.string = strdup(s); } /* if we still found nothing */ if (k->keyname == NULL) { lval->s = strdup(s); return STRING; } switch (k->type) { case kt_percent: keywordtype = PERCENTWORD; break; case kt_time: keywordtype = TIMEWORD; break; case kt_comment: keywordtype = COMMENT; break; case kt_bool: case kt_invertbool: keywordtype = BOOLWORD; break; default: keywordtype = KEYWORD; break; } /* else, set up llval.k to point, and return KEYWORD */ lval->k.keydef = k; lval->k.keyleft = keyleft; return keywordtype; } unsigned int parser_enum_list(const struct keyword_def *kd, const char *s, bool list) { char complaintbuf[80]; assert(kd->type == kt_list || kd->type == kt_enum); /* strsep(3) is destructive, so give it a safe-to-munge copy of s */ char *scopy = strdup(s); char *scursor = scopy; unsigned int valresult = 0; /* * split up the string into comma separated pieces, and look each piece up in the * value list provided in the definition. */ int numfound = 0; char *piece; while ((piece = strsep(&scursor, ":, \t")) != NULL) { /* discard empty strings */ if (piece[0] == '\0') continue; assert(kd->validenum != NULL); int kevcount = kd->validenum->valuesize; const struct keyword_enum_value *kev = kd->validenum->values; for ( ; ; kev++, kevcount--) { if (kevcount == 0) { /* we didn't find anything, complain */ snprintf(complaintbuf, sizeof(complaintbuf), "%s: %d: keyword %s, invalid value: %s", parser_cur_filename(), parser_cur_lineno(), kd->keyname, piece); fprintf(stderr, "ERROR: %s\n", complaintbuf); free(scopy); exit(1); } if (strcaseeq(piece, kev->name)) { /* found it: count it */ numfound++; valresult |= kev->value; break; } } } if (numfound > 1 && !list) { snprintf(complaintbuf, sizeof(complaintbuf), "%s: %d: keyword %s accepts only one value, not %s", parser_cur_filename(), parser_cur_lineno(), kd->keyname, scopy); fprintf(stderr, "ERROR: %s\n", complaintbuf); free(scopy); exit(1); } free(scopy); return valresult; } lset_t parser_lset(const struct keyword_def *kd, const char *value) { assert(kd->type == kt_lset); lmod_t result; zero(&result); /* * Use lmod_args() since it both knows how to parse a comma * separated list and can handle no-XXX (ex: all,no-xauth). * The final set of enabled bits is returned in .set. */ if (!lmod_arg(&result, kd->info, value, true/*enable*/)) { /* * If the lookup failed, complain (and exit!). * * XXX: the error diagnostic is a little vague - * should lmod_arg() instead return the error? */ fprintf(stderr, "ERROR: %s: %d: keyword %s, invalid value: %s\n", parser_cur_filename(), parser_cur_lineno(), kd->keyname, value); exit(1); } return result.set; } unsigned int parser_loose_enum(struct keyword *k, const char *s) { const struct keyword_def *kd = k->keydef; int kevcount; const struct keyword_enum_value *kev; unsigned int valresult; assert(kd->type == kt_loose_enum || kd->type == kt_rsakey); assert(kd->validenum != NULL && kd->validenum->values != NULL); for (kevcount = kd->validenum->valuesize, kev = kd->validenum->values; kevcount > 0 && !strcaseeq(s, kev->name); kev++, kevcount--) ; /* if we found something */ if (kevcount != 0) { /* * Unfortunately, "ipsec-interface" takes numbers and a string, * so the number 0 is valid and we need to skip the assert */ if (!streq(kd->keyname,"ipsec-interface")) { assert(kev->value != 0); } valresult = kev->value; k->string = NULL; return valresult; } k->string = strdup(s); /* ??? why not xstrdup? */ return 255; } libreswan-3.32/lib/libipsecconf/parser.l000066400000000000000000000305171365625662500203340ustar00rootroot00000000000000/* -*- flex-mode -*- */ %option nounput %option noinput %{ /* Libreswan config file parser (parser.l) * Copyright (C) 2001 Mathieu Lafon - Arkoon Network Security * Copyright (C) 2003-2007 Michael Richardson * Copyright (C) 2008, 2014 D. Hugh Redelmeier * Copyright (C) 2012 Wes Hardaker * Copyright (C) 2013 Philippe Vouters * Copyright (C) 2013 Paul Wouters * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ /* * The generation of this code tends to always give us an unsigned vs signed * warning on one of our many OS + compiler + flex + arch combinations. * I'm just fed up with them... Paul */ #pragma GCC diagnostic ignored "-Wsign-compare" #include #include #include #include #include #include #include #include #include "ipsecconf/keywords.h" #define YYDEBUG 1 /* HACK! for ipsecconf/parser.h AND parser.tab.h */ #include "ipsecconf/parser.h" /* includes parser.tab.h */ #include "ipsecconf/parserlast.h" #include "ipsecconf/starterlog.h" #define MAX_INCLUDE_DEPTH 10 int lex_verbosity = 0; /* how much tracing output to show */ char rootdir[PATH_MAX]; /* when evaluating paths, prefix this to them */ char rootdir2[PATH_MAX]; /* or... try this one too */ static int parser_y_eof(void); /* we want no actual output! */ #define ECHO struct ic_inputsource { YY_BUFFER_STATE state; FILE *file; unsigned int line; bool once; char *filename; int fileglobcnt; glob_t fileglob; }; static struct { int stack_ptr; struct ic_inputsource stack[MAX_INCLUDE_DEPTH]; } ic_private; static struct ic_inputsource *stacktop; char *parser_cur_filename(void) { return stacktop->filename; } int parser_cur_lineno(void) { return stacktop->line; } void parser_y_error(char *b, int size, const char *s) { #if defined(SOMETHING_FOR_SOME_ARCH) extern char *yytext; #endif snprintf(b, size, "%s:%u: %s [%s]", stacktop->filename == NULL ? "" : stacktop->filename, stacktop->line, s, yytext); } void parser_y_init (const char *name, FILE *f) { memset(&ic_private, 0, sizeof(ic_private)); ic_private.stack[0].line = 1; ic_private.stack[0].once = TRUE; ic_private.stack[0].file = f; ic_private.stack[0].filename = strdup(name); stacktop = &ic_private.stack[0]; ic_private.stack_ptr = 0; } static void parser_y_close(struct ic_inputsource *iis) { if (iis->filename != NULL) { free(iis->filename); iis->filename = NULL; } if (iis->file != NULL) { fclose(iis->file); iis->file = NULL; } if (iis->fileglob.gl_pathv != NULL) { globfree(&iis->fileglob); iis->fileglob.gl_pathv = NULL; } } static int parser_y_nextglobfile(struct ic_inputsource *iis) { FILE *f; int fcnt; #if 0 printf("fileglobcnt: %d pathc: %d cmp: %u\n", iis->fileglobcnt, stacktop->fileglob.gl_pathc, (iis->fileglobcnt >= (int)stacktop->fileglob.gl_pathc)); #endif if ((int)iis->fileglobcnt >= (int)stacktop->fileglob.gl_pathc) { /* EOFiles */ return -1; } /* increment for next time */ fcnt = iis->fileglobcnt++; if (iis->file != NULL) { fclose(iis->file); iis->file = NULL; } if (iis->filename != NULL) { free(iis->filename); iis->filename = NULL; } iis->line = 1; iis->once = TRUE; iis->filename = strdup(iis->fileglob.gl_pathv[fcnt]); /* open the file */ f = fopen(iis->filename, "r"); if (f == NULL) { char ebuf[128]; snprintf(ebuf, sizeof(ebuf), (strstr(iis->filename, "crypto-policies/back-ends/libreswan.config") == NULL) ? "cannot open include filename: '%s': %s" : "ignored loading default system-wide crypto-policies file '%s': %s", iis->fileglob.gl_pathv[fcnt], strerror(errno)); yyerror(ebuf); return -1; } iis->file = f; yy_switch_to_buffer(yy_create_buffer(f, YY_BUF_SIZE)); return 0; } static int globugh_include(const char *epath, int eerrno) { starter_log(LOG_LEVEL_ERR, "problem with include filename '%s': %s", epath, strerror(eerrno)); return 1; /* stop glob */ } int parser_y_include (const char *filename) { const char *try; char newname[PATH_MAX]; char newname2[PATH_MAX]; glob_t globbuf; int globresult; globbuf.gl_offs = 0; /* * If the filename starts with /, we try to find it prefixed with * rootdir or rootdir2. * * glob() returns a match if that file exists, even without * having to do any globbing. * * Use GNU GLOB_BRACE extension to glob(3) if available. */ #ifdef GLOB_BRACE # define GB GLOB_BRACE #else # define GB 0 #endif /* * If there is no rootdir, but there is a rootdir2, swap them. * This reduces the number of cases to be handled. */ if (rootdir[0] == '\0' && rootdir2[0] != '\0') { strcpy(rootdir, rootdir2); rootdir2[0] = '\0'; } if (filename[0] != '/' || rootdir[0] == '\0') { /* try plain name, with no rootdirs */ try = filename; globresult = glob(try, GB, globugh_include, &globbuf); if (globresult == GLOB_NOMATCH) { if (strchr(filename,'*') == NULL) { /* not a wildcard, throw error */ starter_log(LOG_LEVEL_ERR, "warning: could not open include filename: '%s'", filename); } else { /* don't throw an error, just log a warning */ starter_log(LOG_LEVEL_DEBUG, "could not open include wildcard filename(s): '%s'", filename); } } } else { /* try prefixing with rootdir */ snprintf(newname, sizeof(newname), "%s%s", rootdir, filename); try = newname; globresult = glob(try, GB, globugh_include, &globbuf); if (globresult == GLOB_NOMATCH) { if (rootdir2[0] == '\0') { if (strchr(filename,'*') == NULL) { /* not a wildcard, throw error */ starter_log(LOG_LEVEL_ERR, "warning: could not open include filename '%s' (tried '%s')", filename, newname); } else { /* don't throw an error, just log a warning */ starter_log(LOG_LEVEL_DEBUG, "could not open include wildcard filename(s) '%s' (tried '%s')", filename, newname); } } else { /* try again, prefixing with rootdir2 */ globfree(&globbuf); snprintf(newname2, sizeof(newname2), "%s%s", rootdir2, filename); try = newname2; globresult = glob(try, GB, globugh_include, &globbuf); if (globresult == GLOB_NOMATCH) { starter_log(LOG_LEVEL_ERR, "warning: could not open include filename: '%s' (tried '%s' and '%s')", filename, newname, newname2); } } } } #undef GB switch (globresult) { case 0: /* success */ if (ic_private.stack_ptr >= MAX_INCLUDE_DEPTH - 1) { yyerror("max inclusion depth reached"); return 1; } if (lex_verbosity > 0) { starter_log(LOG_LEVEL_DEBUG, "including file '%s' ('%s') from %s:%u" , filename, try , stacktop->filename , stacktop->line); } ++ic_private.stack_ptr; stacktop = &ic_private.stack[ic_private.stack_ptr]; stacktop->state = YY_CURRENT_BUFFER; stacktop->fileglob = globbuf; stacktop->fileglobcnt = 0; stacktop->file = NULL; stacktop->filename = NULL; return parser_y_eof(); case GLOB_NOSPACE: starter_log(LOG_LEVEL_ERR, "out of space processing include filename \"%s\"", try); break; case GLOB_ABORTED: /* already logged by globugh_include() */ case GLOB_NOMATCH: /* already logged above */ break; default: starter_log(LOG_LEVEL_ERR, "unknown glob error %d", globresult); break; } /* error happened, but we ignore it */ globfree(&globbuf); return 0; } static int parser_y_eof(void) { if (stacktop->state != YY_CURRENT_BUFFER) { yy_delete_buffer(YY_CURRENT_BUFFER); } if (parser_y_nextglobfile(stacktop) == -1) { /* no more glob'ed files to process */ if (lex_verbosity > 0) { int stackp = ic_private.stack_ptr; starter_log(LOG_LEVEL_DEBUG, "end of file %s", stacktop->filename); if (stackp > 0) { starter_log(LOG_LEVEL_DEBUG, "resuming %s:%u" , ic_private.stack[stackp-1].filename , ic_private.stack[stackp-1].line); } } if (stacktop->state != YY_CURRENT_BUFFER) { yy_switch_to_buffer(stacktop->state); } parser_y_close(stacktop); if (--ic_private.stack_ptr < 0) { return 1; } stacktop = &ic_private.stack[ic_private.stack_ptr]; } return 0; } %} /* lexical states: * * INITIAL * USERDEF: after "=" or "conn"; returns to INITIAL after next token (integer or string) * BOOLEAN: after keyword with BOOLWORD attribute; followed by '='; returns to INITIAL after next token (bool) * COMMENTEQUAL: after keyword "x-comment"; followed by = and then switches to COMMENTSTRING * COMMENTSTRING: after = in COMMENTEQUAL state; everything up to \n is a string; then returns to INITIAL */ %x USERDEF BOOLEAN COMMENTEQUAL COMMENTSTRING %% <> { #if 0 printf("EOF: stacktop->filename = %s\n", stacktop->filename == NULL ? "NULL" : stacktop->filename); #endif /* * Add a newline at the end of the file in case one was missing. * This code assumes that EOF is sticky: * that it can be detected repeatedly. */ if (stacktop->once) { stacktop->once = FALSE; return EOL; } /* * we've finished this file: * continue with the file it was included from (if any) */ if (parser_y_eof()) { yyterminate(); } } ^[\t ]*#.*\n { /* eat comment lines */ stacktop->line++; } ^[\t ]*\n { /* eat blank lines */ stacktop->line++; } ^[\t ]+ return FIRST_SPACES; [\t ]+ /* ignore spaces in line */ ; [0-9]+ { /* process a number */ unsigned long val = (errno = 0, strtoul(yytext, NULL, 10)); if (errno != 0 || val > UINT_MAX) { char ebuf[128]; snprintf(ebuf, sizeof(ebuf), "number too large: %s", yytext); yyerror(ebuf); } yylval.num = val; BEGIN INITIAL; return INTEGER; } %forever { /* a number, really 0 */ yylval.num = 0; BEGIN INITIAL; return INTEGER; } y | yes | true | on { /* process a boolean */ yylval.num = 1; BEGIN INITIAL; return BOOL; } n | no | false | off { /* process a boolean */ yylval.num = 0; BEGIN INITIAL; return BOOL; } = return EQUAL; \n { stacktop->line++; BEGIN INITIAL; return EOL; } = { BEGIN COMMENTSTRING; return EQUAL; } [^\n]* { yylval.s = strdup(yytext); BEGIN INITIAL; return STRING; } \"[^\"\n]*\" { /* "string" */ char *s = yytext + 1; int len = strlen(s); assert(len>0); /* remove trailing " */ s[len-1] = '\0'; if (yydebug) fprintf(stderr, "STRING: \"%s\"\n", s); yylval.s = strdup(s); BEGIN INITIAL; return STRING; } \{[^\"\n]*\} { /* { string-without-quotes } */ char *s = yytext + 1; int len = strlen(s); assert(len > 0); /* remove trailing } */ s[len-1] = '\0'; if (yydebug) fprintf(stderr, "STRING{}: {%s}\n", s); yylval.s = strdup(s); BEGIN INITIAL; return STRING; } [^\" \t\n]+ { /* string-without-quotes-or-whitespace */ yylval.s = strdup(yytext); BEGIN INITIAL; return STRING; } [^\{} \t\n]+ { /* string-without-braces-or-whitespace */ yylval.s = strdup(yytext); BEGIN INITIAL; return STRING; } \n { stacktop->line++; return EOL; } = { BEGIN USERDEF; return EQUAL; } version return VERSION; config return CONFIG; setup return SETUP; conn { BEGIN USERDEF; return CONN; } include return INCLUDE; [^\"= \t\n]+ { int tok; if (yydebug) fprintf(stderr, "STR/KEY: %s\n", yytext); tok = parser_find_keyword(yytext, &yylval); switch (tok) { case BOOLWORD: BEGIN BOOLEAN; break; case COMMENT: BEGIN COMMENTEQUAL; break; default: break; } return tok; } #.* { /* eat comment to end of line */ } . yyerror(yytext); %% int yywrap(void) { return 1; } libreswan-3.32/lib/libipsecconf/parser.y000066400000000000000000000262571365625662500203570ustar00rootroot00000000000000%{ /* -*- bison-mode -*- */ /* Libreswan config file parser (parser.y) * Copyright (C) 2001 Mathieu Lafon - Arkoon Network Security * Copyright (C) 2004 Michael Richardson * Copyright (C) 2013 Paul Wouters * Copyright (C) 2013 Philippe Vouters * Copyright (C) 2013 Antony Antony * Copyright (C) 2013 D. Hugh Redelmeier * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include #include #include #include #include #include #include #include #define YYDEBUG 1 #include "ipsecconf/keywords.h" #include "ipsecconf/parser.h" /* includes parser.tab.h" */ #include "ipsecconf/parser-flex.h" #include "ipsecconf/confread.h" #define YYERROR_VERBOSE #define ERRSTRING_LEN 256 /** * Bison */ static char parser_errstring[ERRSTRING_LEN+1]; /** * Static Globals */ static bool save_errors; static struct config_parsed *parser_cfg; static struct kw_list **parser_kw, *parser_kw_last; static void new_parser_kw(struct keyword *keyword, char *string, unsigned int number); /* forward */ static struct starter_comments_list *parser_comments; /** * Functions */ %} %union { char *s; unsigned int num; struct keyword k; } %token EQUAL FIRST_SPACES EOL CONFIG SETUP CONN INCLUDE VERSION %token STRING %token INTEGER %token BOOL %token KEYWORD %token TIMEWORD %token BOOLWORD %token PERCENTWORD %token COMMENT %type duration %% /* * Config file */ config_file: blanklines versionstmt sections ; /* check out the version number - this is optional (and we're phasing out its use) */ /* we have configs shipped with version 2 (INTEGER) and with version 2.0 (STRING, now NUMBER/float was removed */ versionstmt: /* NULL */ | VERSION STRING EOL blanklines | VERSION INTEGER EOL blanklines ; blanklines: /* NULL */ | blanklines EOL ; sections: /* NULL */ | sections section_or_include blanklines ; section_or_include: CONFIG SETUP EOL { parser_kw = &parser_cfg->config_setup; parser_kw_last = NULL; parser_comments = &parser_cfg->comments; if (yydebug) fprintf(stderr, "\nconfig setup read\n"); } kw_sections | CONN STRING EOL { struct section_list *section = malloc(sizeof(struct section_list)); if (section == NULL) { parser_kw = NULL; parser_kw_last = NULL; yyerror("can't allocate memory in section_or_include/conn"); } else { section->name = $2; section->kw = NULL; TAILQ_INSERT_TAIL(&parser_cfg->sections, section, link); /* setup keyword section to record values */ parser_kw = §ion->kw; parser_kw_last = NULL; /* and comments */ TAILQ_INIT(§ion->comments); parser_comments = §ion->comments; if (yydebug) fprintf(stderr, "\nread conn %s\n", section->name); } } kw_sections | INCLUDE STRING EOL { parser_y_include($2); } ; kw_sections: /* NULL */ | kw_sections kw_section ; kw_section: FIRST_SPACES statement_kw EOL | FIRST_SPACES EOL; /* kludge to ignore whitespace (without newline) at EOF */ statement_kw: KEYWORD EQUAL KEYWORD { struct keyword kw = $1; /* because the third argument was also a keyword, we dig up the string representation. */ const char *value = $3.keydef->keyname; char *string = NULL; /* neutral placeholding value */ unsigned int number = 0; /* neutral placeholding value */ switch (kw.keydef->type) { case kt_list: number = parser_enum_list(kw.keydef, value, TRUE); break; case kt_lset: number = parser_lset(kw.keydef, value); /* XXX: truncates! */ break; case kt_enum: number = parser_enum_list(kw.keydef, value, FALSE); break; case kt_rsakey: case kt_loose_enum: number = parser_loose_enum(&kw, value); break; case kt_string: case kt_appendstring: case kt_appendlist: case kt_filename: case kt_dirname: case kt_ipaddr: case kt_bitstring: case kt_idtype: case kt_range: case kt_subnet: string = strdup(value); break; case kt_bool: case kt_invertbool: case kt_number: case kt_time: case kt_percent: yyerror("keyword value is a keyword, but type not a string"); assert(kw.keydef->type != kt_bool); break; case kt_comment: break; case kt_obsolete: case kt_obsolete_quiet: break; } new_parser_kw(&kw, string, number); } | COMMENT EQUAL STRING { struct starter_comments *new = malloc(sizeof(struct starter_comments)); if (new == NULL) { yyerror("can't allocate memory in statement_kw"); } else { new->x_comment = strdup($1.string); new->commentvalue = strdup($3); TAILQ_INSERT_TAIL(parser_comments, new, link); } } | KEYWORD EQUAL STRING { struct keyword kw = $1; char *string = NULL; /* neutral placeholding value */ unsigned int number = 0; /* neutral placeholding value */ switch (kw.keydef->type) { case kt_list: number = parser_enum_list(kw.keydef, $3, TRUE); break; case kt_lset: number = parser_lset(kw.keydef, $3); /* XXX: truncates! */ break; case kt_enum: number = parser_enum_list(kw.keydef, $3, FALSE); break; case kt_rsakey: case kt_loose_enum: number = parser_loose_enum(&kw, $3); break; case kt_string: case kt_appendstring: case kt_appendlist: case kt_filename: case kt_dirname: case kt_ipaddr: case kt_bitstring: case kt_idtype: case kt_range: case kt_subnet: string = $3; break; case kt_bool: case kt_invertbool: case kt_number: case kt_time: case kt_percent: yyerror("valid keyword, but value is not a number"); assert(kw.keydef->type != kt_bool); break; case kt_comment: break; case kt_obsolete: case kt_obsolete_quiet: break; } new_parser_kw(&kw, string, number); } | BOOLWORD EQUAL BOOL { new_parser_kw(&$1, NULL, $3); } | KEYWORD EQUAL INTEGER { new_parser_kw(&$1, NULL, $3); } | TIMEWORD EQUAL duration { new_parser_kw(&$1, NULL, $3); } | PERCENTWORD EQUAL STRING { struct keyword kw = $1; const char *const str = $3; /*const*/ char *endptr; char buf[80]; unsigned long val = (errno = 0, strtoul(str, &endptr, 10)); if (endptr == str) { snprintf(buf, sizeof(buf), "malformed percentage %s=%s", kw.keydef->keyname, str); yyerror(buf); } else if (*endptr != '%' || endptr[1] != '\0') { snprintf(buf, sizeof(buf), "bad percentage multiplier \"%s\" on %s", endptr, str); yyerror(buf); } else if (errno != 0 || val > UINT_MAX) { snprintf(buf, sizeof(buf), "percentage way too large \"%s\"", str); yyerror(buf); } else { new_parser_kw(&kw, NULL, (unsigned int)val); } } | KEYWORD EQUAL BOOL { new_parser_kw(&$1, NULL, $3); } | KEYWORD EQUAL { /* this is meaningless, we ignore it */ } ; duration: INTEGER { $$ = $1; } | STRING { const char *const str = $1; /*const*/ char *endptr; char buf[80]; unsigned long val = (errno = 0, strtoul(str, &endptr, 10)); int strtoul_errno = errno; if (endptr == str) { snprintf(buf, sizeof(buf), "bad duration value \"%s\"", str); yyerror(buf); } else { bool bad_suffix = FALSE; unsigned scale; if (*endptr == '\0') { /* seconds: no scaling */ scale = 1; } else if (endptr[1] == '\0') { /* single character suffix */ switch (*endptr) { case 's': scale = 1; break; case 'm': scale = secs_per_minute; break; case 'h': scale = secs_per_hour; break; case 'd': scale = secs_per_day; break; case 'w': scale = 7*secs_per_day; break; default: bad_suffix = TRUE; } } else { bad_suffix = TRUE; } if (bad_suffix) { snprintf(buf, sizeof(buf), "bad duration multiplier \"%s\" on %s", endptr, str); yyerror(buf); } else if (strtoul_errno != 0 || UINT_MAX / scale < val) { snprintf(buf, sizeof(buf), "duration too large: \"%s\" is more than %u seconds", str, UINT_MAX); yyerror(buf); } else { $$ = val * scale; } } }; %% void yyerror(const char *s) { if (save_errors) parser_y_error(parser_errstring, ERRSTRING_LEN, s); } struct config_parsed *parser_load_conf(const char *file, starter_errors_t *perrl) { parser_errstring[0] = '\0'; struct config_parsed *cfg = malloc(sizeof(struct config_parsed)); if (cfg == NULL) { snprintf(parser_errstring, ERRSTRING_LEN, "can't allocate memory"); goto err; } static const struct config_parsed empty_config_parsed; /* zero or null everywhere */ *cfg = empty_config_parsed; FILE *f = streq(file, "-") ? fdopen(STDIN_FILENO, "r") : fopen(file, "r"); if (f == NULL) { snprintf(parser_errstring, ERRSTRING_LEN, "can't load file '%s'", file); goto err; } yyin = f; parser_y_init(file, f); save_errors = TRUE; TAILQ_INIT(&cfg->sections); TAILQ_INIT(&cfg->comments); parser_cfg = cfg; if (yyparse() != 0) { if (parser_errstring[0] == '\0') { snprintf(parser_errstring, ERRSTRING_LEN, "Unknown error..."); } save_errors = FALSE; do {} while (yyparse() != 0); goto err; } /* check all are kv_config */ for (const struct kw_list *kw = parser_cfg->config_setup; kw != NULL; kw = kw->next) { if (!(kw->keyword.keydef->validity & kv_config)) { snprintf(parser_errstring, sizeof(parser_errstring), "unexpected keyword '%s' in section 'config setup'", kw->keyword.keydef->keyname); goto err; } } /** * Config valid */ return cfg; err: starter_error_append(perrl, "%s", parser_errstring); if (cfg != NULL) parser_free_conf(cfg); return NULL; } static void parser_free_kwlist(struct kw_list *list) { while (list != NULL) { struct kw_list *elt = list; list = list->next; if (elt->string != NULL) free(elt->string); free(elt); } } void parser_free_conf(struct config_parsed *cfg) { if (cfg != NULL) { struct section_list *seci; parser_free_kwlist(cfg->config_setup); for (seci = cfg->sections.tqh_first; seci != NULL; ) { struct section_list *sec = seci; seci = seci->link.tqe_next; if (sec->name != NULL) free(sec->name); parser_free_kwlist(sec->kw); free(sec); } free(cfg); } } static void new_parser_kw(struct keyword *keyword, char *string, unsigned int number) { struct kw_list *new = malloc(sizeof(struct kw_list)); if (new == NULL) { yyerror("cannot allocate memory for a kw_list"); } else { /* * fill the values into new * (either string or number might have a placeholder value */ new->keyword = *keyword; new->string = string; new->number = number; new->next = NULL; /* link the new kw_list into the list */ if (*parser_kw == NULL) *parser_kw = new; /* first in (some) list */ /* connect to previous last on list */ if (parser_kw_last != NULL) parser_kw_last->next = new; /* new is new last on list */ parser_kw_last = new; } } libreswan-3.32/lib/libipsecconf/starterlog.c000066400000000000000000000045061365625662500212140ustar00rootroot00000000000000/* Libreswan IPsec starter (starter.c) * Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security * Copyright (C) 2006-2007 Michael Richardson * Copyright (C) 2007 Paul Wouters * Copyright (C) 2012 Kim B. Heino * Copyright (C) 2013 D. Hugh Redelmeier * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include #include #include #include #include "libreswan.h" #include "constants.h" #include "ipsecconf/starterlog.h" #define BUFF_SIZE 16384 /** * TODO: * o use syslog option in config file */ static bool log_debugging = FALSE; static bool log_to_console = FALSE; static bool log_to_syslog = FALSE; static void log_one_line(int level, const char *buff) { if (log_to_console) fprintf(stderr, "%s\n", buff); if (log_to_syslog) { if (level == LOG_LEVEL_ERR) syslog(LOG_ERR, "%s\n", buff); else syslog(LOG_INFO, "%s\n", buff); } } void starter_log(int level, const char *fmt, ...) { va_list args; char buff[BUFF_SIZE]; char *b; if (!log_debugging && level == LOG_LEVEL_DEBUG) return; va_start(args, fmt); vsnprintf(buff, BUFF_SIZE - 1, fmt, args); buff[BUFF_SIZE - 1] = '\0'; /* log each '\n'-terminated segment separately */ for (b = buff;;) { char *p = strchr(b, '\n'); if (p == NULL) break; *p = '\0'; log_one_line(level, b); b = p + 1; } /* log the '\0'- terminated segment */ log_one_line(level, b); va_end(args); } void starter_use_log(bool debug, bool console, bool mysyslog) { log_debugging = debug; log_to_console = console; if (mysyslog != log_to_syslog) { if (mysyslog) openlog("libipsecconf", LOG_PID, LOG_USER); else closelog(); log_to_syslog = mysyslog; } if (log_debugging) starter_log(LOG_LEVEL_ERR, "debugging mode enabled"); } libreswan-3.32/lib/libipsecconf/starterwhack.c000066400000000000000000000576411365625662500215400ustar00rootroot00000000000000/* * Libreswan whack functions to communicate with pluto (whack.c) * * Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security * Copyright (C) 2004-2006 Michael Richardson * Copyright (C) 2010-2019 D. Hugh Redelmeier * Copyright (C) 2011 Mattias Walström * Copyright (C) 2012-2017 Paul Wouters * Copyright (C) 2012 Philippe Vouters * Copyright (C) 2013 Antony Antony * Copyright (C) 2013 Matt Rogers * Copyright (C) 2016, Andrew Cagney * Copyright (C) 2017 Paul Wouters * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include #include #include #include #include #include #include #include #include #include "sysdep.h" #include "ipsecconf/starterwhack.h" #include "ipsecconf/confread.h" #include "ipsecconf/starterlog.h" #include "socketwrapper.h" #ifndef _LIBRESWAN_H #include /* FIXME: ugly include lines */ #include "constants.h" #endif #include "lswalloc.h" #include "lswlog.h" #include "whack.h" #include "id.h" #include "ip_address.h" #include "ip_info.h" static void update_ports(struct whack_message * m) { int port; if (m->left.port != 0) { port = htons(m->left.port); setportof(port, &m->left.host_addr); setportof(port, &m->left.client.addr); } if (m->right.port != 0) { port = htons(m->right.port); setportof(port, &m->right.host_addr); setportof(port, &m->right.client.addr); } } static int send_reply(int sock, char *buf, ssize_t len) { /* send the secret to pluto */ if (write(sock, buf, len) != len) { int e = errno; starter_log(LOG_LEVEL_ERR, "whack: write() failed (%d %s)", e, strerror(e)); return RC_WHACK_PROBLEM; } return 0; } static int starter_whack_read_reply(int sock, char xauthusername[MAX_XAUTH_USERNAME_LEN], char xauthpass[XAUTH_MAX_PASS_LENGTH], int usernamelen, int xauthpasslen) { char buf[4097]; /* arbitrary limit on log line length */ char *be = buf; int ret = 0; for (;; ) { char *ls = buf; ssize_t rl = read(sock, be, (buf + sizeof(buf) - 1) - be); if (rl < 0) { int e = errno; fprintf(stderr, "whack: read() failed (%d %s)\n", e, strerror(e)); return RC_WHACK_PROBLEM; } if (rl == 0) { if (be != buf) fprintf(stderr, "whack: last line from pluto too long or unterminated\n"); break; } be += rl; *be = '\0'; for (;; ) { char *le = strchr(ls, '\n'); if (le == NULL) { /* move last, partial line to start of buffer */ memmove(buf, ls, be - ls); be -= ls - buf; break; } le++; /* include NL in line */ if (isatty(STDOUT_FILENO) && write(STDOUT_FILENO, ls, le - ls) == -1) { int e = errno; starter_log(LOG_LEVEL_ERR, "whack: write() starterwhack.c:124 failed (%d %s), and ignored.", e, strerror(e)); } /* * figure out prefix number and how it should affect * our exit status */ { /* * we don't generally use strtoul but * in this case, its failure mode * (0 for nonsense) is probably OK. */ unsigned long s = strtoul(ls, NULL, 10); switch (s) { case RC_COMMENT: case RC_LOG: /* ignore */ break; case RC_SUCCESS: /* be happy */ ret = 0; break; case RC_ENTERSECRET: if (xauthpasslen == 0) { xauthpasslen = whack_get_secret( xauthpass, XAUTH_MAX_PASS_LENGTH); } if (xauthpasslen > XAUTH_MAX_PASS_LENGTH) { /* * for input >= 128, * xauthpasslen would be 129 */ xauthpasslen = XAUTH_MAX_PASS_LENGTH; starter_log(LOG_LEVEL_ERR, "xauth password cannot be >= %d chars", XAUTH_MAX_PASS_LENGTH); } ret = send_reply(sock, xauthpass, xauthpasslen); if (ret != 0) return ret; break; case RC_USERPROMPT: if (usernamelen == 0) { usernamelen = whack_get_value( xauthusername, MAX_XAUTH_USERNAME_LEN); } if (usernamelen > MAX_XAUTH_USERNAME_LEN) { /* * for input >= 128, * useramelen would be 129 */ usernamelen = MAX_XAUTH_USERNAME_LEN; starter_log(LOG_LEVEL_ERR, "username cannot be >= %d chars", MAX_XAUTH_USERNAME_LEN); } ret = send_reply(sock, xauthusername, usernamelen); if (ret != 0) return ret; break; default: /* pass through */ ret = s; break; } } ls = le; } } return ret; } static int send_whack_msg(struct whack_message *msg, char *ctlsocket) { struct sockaddr_un ctl_addr = { .sun_family = AF_UNIX }; int sock; ssize_t len; struct whackpacker wp; err_t ugh; int ret; /* copy socket location */ fill_and_terminate(ctl_addr.sun_path, ctlsocket, sizeof(ctl_addr.sun_path)); /* Pack strings */ wp.msg = msg; wp.str_next = (unsigned char *)msg->string; wp.str_roof = (unsigned char *)&msg->string[sizeof(msg->string)]; ugh = pack_whack_msg(&wp); if (ugh != NULL) { starter_log(LOG_LEVEL_ERR, "send_wack_msg(): can't pack strings: %s", ugh); return -1; } len = wp.str_next - (unsigned char *)msg; /* Connect to pluto ctl */ sock = safe_socket(AF_UNIX, SOCK_STREAM, 0); if (sock < 0) { starter_log(LOG_LEVEL_ERR, "socket() failed: %s", strerror(errno)); return -1; } if (connect(sock, (struct sockaddr *)&ctl_addr, offsetof(struct sockaddr_un, sun_path) + strlen(ctl_addr.sun_path)) < 0) { starter_log(LOG_LEVEL_ERR, "connect(pluto_ctl) failed: %s", strerror(errno)); close(sock); return -1; } /* Send message */ if (write(sock, msg, len) != len) { starter_log(LOG_LEVEL_ERR, "write(pluto_ctl) failed: %s", strerror(errno)); close(sock); return -1; } /* read reply */ { char xauthusername[MAX_XAUTH_USERNAME_LEN]; char xauthpass[XAUTH_MAX_PASS_LENGTH]; ret = starter_whack_read_reply(sock, xauthusername, xauthpass, 0, 0); close(sock); } return ret; } static void init_whack_msg(struct whack_message *msg) { /* properly initializes pointers to NULL */ static const struct whack_message zwm; *msg = zwm; msg->magic = WHACK_MAGIC; } /* NOT RE-ENTRANT: uses a static buffer */ static char *connection_name(const struct starter_conn *conn) { /* If connection name is '%auto', create a new name like conn_xxxxx */ static char buf[32]; if (streq(conn->name, "%auto")) { snprintf(buf, sizeof(buf), "conn_%ld", conn->id); return buf; } else { return conn->name; } } static void set_whack_end(char *lr, struct whack_end *w, const struct starter_end *l) { w->id = l->id; w->host_type = l->addrtype; switch (l->addrtype) { case KH_IPADDR: case KH_IFACE: w->host_addr = l->addr; break; case KH_DEFAULTROUTE: case KH_IPHOSTNAME: /* note: we always copy the name string below */ w->host_addr = address_any(aftoinfo(l->addr_family)); break; case KH_OPPO: case KH_GROUP: case KH_OPPOGROUP: /* policy should have been set to OPPO */ w->host_addr = address_any(aftoinfo(l->addr_family)); break; case KH_ANY: w->host_addr = address_any(aftoinfo(l->addr_family)); break; default: printf("%s: do something with host case: %d\n", lr, l->addrtype); break; } w->host_addr_name = l->strings[KSCF_IP]; switch (l->nexttype) { case KH_IPADDR: w->host_nexthop = l->nexthop; break; case KH_DEFAULTROUTE: /* acceptable to set nexthop to %defaultroute */ case KH_NOTSET: /* acceptable to not set nexthop */ /* * but, get the family set up right * XXX the nexthop type has to get into the whack message! */ w->host_nexthop = address_any(address_type(&l->addr)); break; default: printf("%s: do something with nexthop case: %d\n", lr, l->nexttype); break; } if (address_is_specified(&l->sourceip)) w->host_srcip = l->sourceip; if (subnet_is_specified(&l->vti_ip)) w->host_vtiip = l->vti_ip; if (!isanyaddr(&l->ifaceip.addr)) w->ifaceip = l->ifaceip; w->has_client = l->has_client; if (l->has_client) { w->client = l->subnet; } else { w->client = (aftoinfo(l->addr_family)->all_addresses); } w->host_port = IKE_UDP_PORT; /* XXX starter should support (nat)-ike-port */ w->has_client_wildcard = l->has_client_wildcard; w->has_port_wildcard = l->has_port_wildcard; if (l->certx != NULL) { w->pubkey = l->certx; w->pubkey_type = WHACK_PUBKEY_CERTIFICATE_NICKNAME; } if (l->ckaid != NULL) { w->pubkey = l->ckaid; w->pubkey_type = WHACK_PUBKEY_CKAID; } w->ca = l->ca; if (l->options_set[KNCF_SENDCERT]) w->sendcert = l->options[KNCF_SENDCERT]; else w->sendcert = CERT_ALWAYSSEND; if (l->options_set[KNCF_AUTH]) w->authby = l->options[KNCF_AUTH]; w->updown = l->updown; w->virt = NULL; w->protocol = l->protocol; w->port = l->port; w->virt = l->virt; w->key_from_DNS_on_demand = l->key_from_DNS_on_demand; if (l->options_set[KNCF_XAUTHSERVER]) w->xauth_server = l->options[KNCF_XAUTHSERVER]; if (l->options_set[KNCF_XAUTHCLIENT]) w->xauth_client = l->options[KNCF_XAUTHCLIENT]; if (l->strings_set[KSCF_USERNAME]) w->xauth_username = l->strings[KSCF_USERNAME]; if (l->options_set[KNCF_MODECONFIGSERVER]) w->modecfg_server = l->options[KNCF_MODECONFIGSERVER]; if (l->options_set[KNCF_MODECONFIGCLIENT]) w->modecfg_client = l->options[KNCF_MODECONFIGCLIENT]; if (l->options_set[KNCF_CAT]) w->cat = l->options[KNCF_CAT]; w->pool_range = l->pool_range; } static int starter_whack_add_pubkey(struct starter_config *cfg, const struct starter_conn *conn, const struct starter_end *end, const char *lr) { const char *err; char err_buf[TTODATAV_BUF]; char keyspace[1024 + 4]; struct whack_message msg; int ret; ret = 0; init_whack_msg(&msg); msg.whack_key = TRUE; msg.pubkey_alg = PUBKEY_ALG_RSA; if (end->id && end->rsakey1) { msg.keyid = end->id; switch (end->rsakey1_type) { case PUBKEY_DNSONDEMAND: starter_log(LOG_LEVEL_DEBUG, "conn %s/%s has key from DNS", connection_name(conn), lr); break; case PUBKEY_CERTIFICATE: starter_log(LOG_LEVEL_DEBUG, "conn %s/%s has key from certificate", connection_name(conn), lr); break; case PUBKEY_NOTSET: break; case PUBKEY_PREEXCHANGED: err = ttodatav(end->rsakey1, 0, 0, keyspace, sizeof(keyspace), &msg.keyval.len, err_buf, sizeof(err_buf), 0); if (err) { starter_log(LOG_LEVEL_ERR, "conn %s/%s: rsakey malformed [%s]", connection_name(conn), lr, err); return 1; } else { starter_log(LOG_LEVEL_DEBUG, "\tsending %s %srsasigkey=%s", connection_name(conn), lr, end->rsakey1); msg.keyval.ptr = (unsigned char *)keyspace; ret = send_whack_msg(&msg, cfg->ctlsocket); } } } if (ret < 0) return ret; init_whack_msg(&msg); msg.whack_key = TRUE; msg.pubkey_alg = PUBKEY_ALG_RSA; if (end->id && end->rsakey2) { /* printf("addkey2: %s\n", lr); */ msg.keyid = end->id; switch (end->rsakey2_type) { case PUBKEY_NOTSET: case PUBKEY_DNSONDEMAND: case PUBKEY_CERTIFICATE: break; case PUBKEY_PREEXCHANGED: err = ttodatav(end->rsakey2, 0, 0, keyspace, sizeof(keyspace), &msg.keyval.len, err_buf, sizeof(err_buf), 0); if (err) { starter_log(LOG_LEVEL_ERR, "conn %s/%s: rsakey malformed [%s]", connection_name(conn), lr, err); return 1; } else { starter_log(LOG_LEVEL_DEBUG, "\tsending %s %srsasigkey2=%s", connection_name(conn), lr, end->rsakey1); msg.keyval.ptr = (unsigned char *)keyspace; return send_whack_msg(&msg, cfg->ctlsocket); } } } return 0; } static void conn_log_val(const struct starter_conn *conn, const char *name, const char *value) { starter_log(LOG_LEVEL_DEBUG, "conn: \"%s\" %s=%s", conn->name, name, value == NULL ? "" : value); } static int starter_whack_basic_add_conn(struct starter_config *cfg, const struct starter_conn *conn) { struct whack_message msg; int r; init_whack_msg(&msg); msg.whack_connection = TRUE; msg.whack_delete = TRUE; /* always do replace for now */ msg.name = connection_name(conn); msg.addr_family = conn->left.addr_family; msg.tunnel_addr_family = conn->left.addr_family; if (conn->right.addrtype == KH_IPHOSTNAME) msg.dnshostname = conn->right.strings[KSCF_IP]; msg.nic_offload = conn->options[KNCF_NIC_OFFLOAD]; msg.sa_ike_life_seconds = deltatime(conn->options[KNCF_IKELIFETIME]); msg.sa_ipsec_life_seconds = deltatime(conn->options[KNCF_SALIFETIME]); msg.sa_rekey_margin = deltatime(conn->options[KNCF_REKEYMARGIN]); msg.sa_rekey_fuzz = conn->options[KNCF_REKEYFUZZ]; msg.sa_keying_tries = conn->options[KNCF_KEYINGTRIES]; msg.sa_replay_window = conn->options[KNCF_REPLAY_WINDOW]; msg.xfrm_if_id = conn->options[KNCF_XFRM_IF_ID]; msg.r_interval = deltatime_ms(conn->options[KNCF_RETRANSMIT_INTERVAL_MS]); msg.r_timeout = deltatime(conn->options[KNCF_RETRANSMIT_TIMEOUT]); msg.policy = conn->policy; msg.sighash_policy = conn->sighash_policy; msg.connalias = conn->connalias; msg.metric = conn->options[KNCF_METRIC]; if (conn->options_set[KNCF_CONNMTU]) msg.connmtu = conn->options[KNCF_CONNMTU]; if (conn->options_set[KNCF_PRIORITY]) msg.sa_priority = conn->options[KNCF_PRIORITY]; if (conn->options_set[KNCF_TFCPAD]) msg.sa_tfcpad = conn->options[KNCF_TFCPAD]; if (conn->options_set[KNCF_NO_ESP_TFC]) msg.send_no_esp_tfc = conn->options[KNCF_NO_ESP_TFC]; if (conn->options_set[KNCF_NFLOG_CONN]) msg.nflog_group = conn->options[KNCF_NFLOG_CONN]; if (conn->options_set[KNCF_REQID]) { if (conn->options[KNCF_REQID] <= 0 || conn->options[KNCF_REQID] > IPSEC_MANUAL_REQID_MAX) { starter_log(LOG_LEVEL_ERR, "Ignoring reqid value - range must be 1-%u", IPSEC_MANUAL_REQID_MAX); } else { msg.sa_reqid = conn->options[KNCF_REQID]; } } /* default to HOLD */ msg.dpd_action = DPD_ACTION_HOLD; if (conn->options_set[KNCF_DPDDELAY] && conn->options_set[KNCF_DPDTIMEOUT]) { msg.dpd_delay = deltatime(conn->options[KNCF_DPDDELAY]); msg.dpd_timeout = deltatime(conn->options[KNCF_DPDTIMEOUT]); if (conn->options_set[KNCF_DPDACTION]) msg.dpd_action = conn->options[KNCF_DPDACTION]; if (conn->options_set[KNCF_REKEY] && !conn->options[KNCF_REKEY]) { if (conn->options[KNCF_DPDACTION] == DPD_ACTION_RESTART) { starter_log(LOG_LEVEL_ERR, "conn: \"%s\" warning dpdaction cannot be 'restart' when rekey=no - defaulting to 'hold'", conn->name); msg.dpd_action = DPD_ACTION_HOLD; } } } else { if (conn->options_set[KNCF_DPDDELAY] || conn->options_set[KNCF_DPDTIMEOUT] || conn->options_set[KNCF_DPDACTION]) { starter_log(LOG_LEVEL_ERR, "conn: \"%s\" warning dpd settings are ignored unless both dpdtimeout= and dpddelay= are set", conn->name); } } if (conn->options_set[KNCF_SEND_CA]) msg.send_ca = conn->options[KNCF_SEND_CA]; else msg.send_ca = CA_SEND_NONE; if (conn->options_set[KNCF_ENCAPS]) msg.encaps = conn->options[KNCF_ENCAPS]; else msg.encaps = yna_auto; if (conn->options_set[KNCF_NAT_KEEPALIVE]) msg.nat_keepalive = conn->options[KNCF_NAT_KEEPALIVE]; else msg.nat_keepalive = TRUE; if (conn->options_set[KNCF_IKEV1_NATT]) msg.ikev1_natt = conn->options[KNCF_IKEV1_NATT]; else msg.ikev1_natt = NATT_BOTH; /* Activate sending out own vendorid */ if (conn->options_set[KNCF_SEND_VENDORID]) msg.send_vendorid = conn->options[KNCF_SEND_VENDORID]; /* Activate Cisco quircky behaviour not replacing old IPsec SA's */ if (conn->options_set[KNCF_INITIAL_CONTACT]) msg.initial_contact = conn->options[KNCF_INITIAL_CONTACT]; /* Activate their quircky behaviour - rumored to be needed for ModeCfg and RSA */ if (conn->options_set[KNCF_CISCO_UNITY]) msg.cisco_unity = conn->options[KNCF_CISCO_UNITY]; if (conn->options_set[KNCF_VID_STRONGSWAN]) msg.fake_strongswan = conn->options[KNCF_VID_STRONGSWAN]; /* Active our Cisco interop code if set */ if (conn->options_set[KNCF_REMOTEPEERTYPE]) msg.remotepeertype = conn->options[KNCF_REMOTEPEERTYPE]; #ifdef HAVE_NM /* Network Manager support */ if (conn->options_set[KNCF_NMCONFIGURED]) msg.nmconfigured = conn->options[KNCF_NMCONFIGURED]; #endif #ifdef HAVE_LABELED_IPSEC if (conn->options_set[KSCF_POLICY_LABEL]) { msg.policy_label = conn->policy_label; starter_log(LOG_LEVEL_DEBUG, "conn: \"%s\" policy_label=%s", conn->name, msg.policy_label); } #endif msg.modecfg_dns = conn->modecfg_dns; conn_log_val(conn, "modecfgdns", msg.modecfg_dns); msg.modecfg_domains = conn->modecfg_domains; conn_log_val(conn, "modecfgdomains", msg.modecfg_domains); msg.modecfg_banner = conn->modecfg_banner; conn_log_val(conn, "modecfgbanner", msg.modecfg_banner); msg.conn_mark_both = conn->conn_mark_both; conn_log_val(conn, "mark", msg.conn_mark_both); msg.conn_mark_in = conn->conn_mark_in; conn_log_val(conn, "mark-in", msg.conn_mark_in); msg.conn_mark_out = conn->conn_mark_out; conn_log_val(conn, "mark-out", msg.conn_mark_out); msg.vti_iface = conn->vti_iface; conn_log_val(conn, "vti_iface", msg.vti_iface); if (conn->options_set[KNCF_VTI_ROUTING]) msg.vti_routing = conn->options[KNCF_VTI_ROUTING]; if (conn->options_set[KNCF_VTI_SHARED]) msg.vti_shared = conn->options[KNCF_VTI_SHARED]; msg.redirect_to = conn->redirect_to; conn_log_val(conn, "redirect-to", msg.redirect_to); msg.accept_redirect_to = conn->accept_redirect_to; conn_log_val(conn, "accept-redirect-to", msg.accept_redirect_to); if (conn->options_set[KNCF_XAUTHBY]) msg.xauthby = conn->options[KNCF_XAUTHBY]; if (conn->options_set[KNCF_XAUTHFAIL]) msg.xauthfail = conn->options[KNCF_XAUTHFAIL]; set_whack_end("left", &msg.left, &conn->left); set_whack_end("right", &msg.right, &conn->right); /* for bug #1004 */ update_ports(&msg); msg.esp = conn->esp; conn_log_val(conn, "esp", msg.esp); msg.ike = conn->ike_crypto; conn_log_val(conn, "ike", msg.ike); r = send_whack_msg(&msg, cfg->ctlsocket); if (r != 0) return r; if (conn->left.rsakey1 != NULL || conn->left.rsakey2 != NULL) { r = starter_whack_add_pubkey(cfg, conn, &conn->left, "left"); if (r != 0) return r; } if (conn->right.rsakey1 != NULL || conn->right.rsakey2 != NULL) { r = starter_whack_add_pubkey(cfg, conn, &conn->right, "right"); if (r != 0) return r; } return 0; } static bool one_subnet_from_string(const struct starter_conn *conn, char **psubnets, int af, ip_subnet *sn, char *lr) { char *eln; char *subnets = *psubnets; err_t e; if (subnets == NULL) return FALSE; /* find first non-space item */ while (*subnets != '\0' && (isspace(*subnets) || *subnets == ',')) subnets++; /* did we find something? */ if (*subnets == '\0') return FALSE; /* no */ eln = subnets; /* find end of this item */ while (*subnets != '\0' && !(isspace(*subnets) || *subnets == ',')) subnets++; e = ttosubnet(eln, subnets - eln, af, '6', sn); if (e != NULL) { starter_log(LOG_LEVEL_ERR, "conn: \"%s\" warning '%s' is not a subnet declaration. (%ssubnets)", conn->name, eln, lr); } *psubnets = subnets; return TRUE; } /* * permutate_conns - generate all combinations of subnets={} * * @operation - the function to apply to each generated conn * @cfg - the base configuration * @conn - the conn to permute * * This function goes through the set of N x M combinations of the subnets * defined in conn's "subnets=" declarations and synthesizes conns with * the proper left/right subnet settings, and then calls operation(), * (which is usually add/delete/route/etc.) * */ static int starter_permutate_conns(int (*operation)(struct starter_config *cfg, const struct starter_conn *conn), struct starter_config *cfg, const struct starter_conn *conn) { struct starter_conn sc; int lc, rc; char *leftnets, *rightnets; char tmpconnname[256]; ip_subnet lnet, rnet; leftnets = ""; if (conn->left.strings_set[KSCF_SUBNETS]) leftnets = conn->left.strings[KSCF_SUBNETS]; rightnets = ""; if (conn->right.strings_set[KSCF_SUBNETS]) rightnets = conn->right.strings[KSCF_SUBNETS]; /* * the first combination is the current leftsubnet/rightsubnet * value, and then each iteration of rightsubnets, and then * each permutation of leftsubnets X rightsubnets. * * If both subnet= is set and subnets=, then it is as if an extra * element of subnets= has been added, so subnets= for only one * side will do the right thing, as will some combinations of also= * */ if (conn->left.strings_set[KSCF_SUBNET]) { lnet = conn->left.subnet; lc = 0; } else { one_subnet_from_string(conn, &leftnets, conn->left.addr_family, &lnet, "left"); lc = 1; } if (conn->right.strings_set[KSCF_SUBNET]) { rnet = conn->right.subnet; rc = 0; } else { one_subnet_from_string(conn, &rightnets, conn->right.addr_family, &rnet, "right"); rc = 1; } for (;;) { int success; /* copy conn --- we can borrow all pointers, since this * is a temporary copy */ sc = *conn; /* fix up leftsubnet/rightsubnet properly, make sure * that has_client is set. */ sc.left.subnet = lnet; sc.left.has_client = TRUE; sc.right.subnet = rnet; sc.right.has_client = TRUE; snprintf(tmpconnname, sizeof(tmpconnname), "%s/%ux%u", conn->name, lc, rc); sc.name = tmpconnname; sc.connalias = conn->name; success = (*operation)(cfg, &sc); if (success != 0) { /* Fail at first failure? I think so. */ return success; } /* * okay, advance right first, and if it is out, then do * left. */ rc++; if (!one_subnet_from_string(conn, &rightnets, conn->right.addr_family, &rnet, "right")) { /* reset right, and advance left! */ rightnets = ""; if (conn->right.strings_set[KSCF_SUBNETS]) rightnets = conn->right.strings[KSCF_SUBNETS]; /* should rightsubnet= be the first item ? */ if (conn->right.strings_set[KSCF_SUBNET]) { rnet = conn->right.subnet; rc = 0; } else { one_subnet_from_string(conn, &rightnets, conn->right.addr_family, &rnet, "right"); rc = 1; } /* left */ lc++; if (!one_subnet_from_string(conn, &leftnets, conn->left.addr_family, &lnet, "left")) break; } } return 0; /* success. */ } int starter_whack_add_conn(struct starter_config *cfg, const struct starter_conn *conn) { /* basic case, nothing special to synthize! */ if (!conn->left.strings_set[KSCF_SUBNETS] && !conn->right.strings_set[KSCF_SUBNETS]) return starter_whack_basic_add_conn(cfg, conn); return starter_permutate_conns(starter_whack_basic_add_conn, cfg, conn); } static int starter_whack_basic_route_conn(struct starter_config *cfg, const struct starter_conn *conn) { struct whack_message msg; init_whack_msg(&msg); msg.whack_route = TRUE; msg.name = connection_name(conn); return send_whack_msg(&msg, cfg->ctlsocket); } int starter_whack_route_conn(struct starter_config *cfg, struct starter_conn *conn) { /* basic case, nothing special to synthize! */ if (!conn->left.strings_set[KSCF_SUBNETS] && !conn->right.strings_set[KSCF_SUBNETS]) return starter_whack_basic_route_conn(cfg, conn); return starter_permutate_conns(starter_whack_basic_route_conn, cfg, conn); } int starter_whack_initiate_conn(struct starter_config *cfg, struct starter_conn *conn) { struct whack_message msg; init_whack_msg(&msg); msg.whack_initiate = TRUE; msg.whack_async = TRUE; msg.name = connection_name(conn); return send_whack_msg(&msg, cfg->ctlsocket); } int starter_whack_listen(struct starter_config *cfg) { struct whack_message msg; init_whack_msg(&msg); msg.whack_listen = TRUE; return send_whack_msg(&msg, cfg->ctlsocket); } libreswan-3.32/lib/liblswtool/000077500000000000000000000000001365625662500164075ustar00rootroot00000000000000libreswan-3.32/lib/liblswtool/Makefile000066400000000000000000000014311365625662500200460ustar00rootroot00000000000000# Libreswan library for standalone logging # # Copyright (C) 2017 Andrew Cagney # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. LIB = liblswtool.a OBJS += lswlog.o OBJS += libreswan_exit.o ifdef top_srcdir include ${top_srcdir}/mk/library.mk else include ../../mk/library.mk endif libreswan-3.32/lib/liblswtool/libreswan_exit.c000066400000000000000000000013301365625662500215670ustar00rootroot00000000000000/* * Exit the program cleanly. * * Copyright (C) 2017 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include "lswlog.h" void libreswan_exit(enum pluto_exit_code rc) { exit(rc); } libreswan-3.32/lib/liblswtool/lswlog.c000066400000000000000000000056021365625662500200650ustar00rootroot00000000000000/* * error logging functions * * Copyright (C) 1997 Angelos D. Keromytis. * Copyright (C) 1998-2001 D. Hugh Redelmeier. * Copyright (C) 2007-2010 Paul Wouters * Copyright (C) 2012-2013 Paul Wouters * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include #include #include #include #include #include #include #include /* used only if MSG_NOSIGNAL not defined */ #include #include #include #include #include #include "constants.h" #include "lswtool.h" #include "lswlog.h" bool log_to_stderr = TRUE; /* should log go to stderr? */ const char *progname; static const char *prog_suffix = ""; void tool_init_log(const char *name) { const char *last_slash = strrchr(name, '/'); progname = last_slash == NULL ? name : last_slash + 1; prog_suffix = ": "; if (log_to_stderr) setbuf(stderr, NULL); } /* : . Errno N: */ void lswlog_errno_prefix(struct lswlog *buf, const char *prefix) { lswlogs(buf, prefix); lswlogs(buf, progname); lswlogs(buf, prog_suffix); } void lswlog_errno_suffix(struct lswlog *buf, int e) { lswlogs(buf, "."); jam(buf, " "PRI_ERRNO, pri_errno(e)); if (log_to_stderr) { lswlog_to_file_stream(buf, stderr); } } void lswlog_log_prefix(struct lswlog *buf) { lswlogf(buf, "%s%s", progname, prog_suffix); } void log_jambuf(lset_t rc_flags, struct fd *unused_object_fd UNUSED, jambuf_t *buf) { enum stream only = rc_flags & ~RC_MASK; switch (only) { case DEBUG_STREAM: fprintf(stderr, "%s%s\n", DEBUG_PREFIX, buf->array); break; case ALL_STREAMS: case LOG_STREAM: if (log_to_stderr) { fprintf(stderr, "%s\n", buf->array); } break; case WHACK_STREAM: fprintf(stderr, "%s\n", buf->array); break; case ERROR_STREAM: fprintf(stderr, "%s\n", buf->array); break; case NO_STREAM: /* * XXX: Like writing to /dev/null - go through the * motions but with no result. Code really really * should not call this function with this flag. */ break; default: bad_case(only); } } void lswlog_to_error_stream(struct lswlog *buf) { fprintf(stderr, "%s\n", buf->array); } void lswlog_to_default_streams(struct lswlog *buf, enum rc_type rc UNUSED) { if (log_to_stderr) { fprintf(stderr, "%s\n", buf->array); } } libreswan-3.32/lib/libswan/000077500000000000000000000000001365625662500156545ustar00rootroot00000000000000libreswan-3.32/lib/libswan/DBG_dump.c000066400000000000000000000034631365625662500174470ustar00rootroot00000000000000/* error logging functions * Copyright (C) 1997 Angelos D. Keromytis. * Copyright (C) 1998-2001,2013 D. Hugh Redelmeier * Copyright (C) 2005-2007 Michael Richardson * Copyright (C) 2006-2010 Bart Trojanowski * Copyright (C) 2008-2012 Paul Wouters * Copyright (C) 2008-2010 David McCullough. * Copyright (C) 2012 Paul Wouters * Copyright (C) 2013,2015 Paul Wouters * Copyright (C) 2013 Tuomo Soini * Copyright (C) 2017 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include #include "lswlog.h" /* * dump raw bytes; when LABEL is non-NULL prefix the dump with a log * line containing the label. */ void DBG_dump(const char *label, const void *p, size_t len) { if (label != NULL) { DBG_log("%s", label); } const uint8_t *cp = p; do { /* 4 * ' xx xx xx xx' + '\0' */ char buf[4 * (1 + 4 * 3) + 1]; char *bp = buf; for (int i = 0; len != 0 && i != 4; i++) { *bp++ = ' '; for (int j = 0; len != 0 && j != 4; len--, j++) { static const char hexdig[] = "0123456789abcdef"; *bp++ = ' '; *bp++ = hexdig[(*cp >> 4) & 0xF]; *bp++ = hexdig[*cp & 0xF]; cp++; } } *bp = '\0'; passert(bp < buf + elemsof(buf)); DBG_log("%s", buf); } while (len != 0); } libreswan-3.32/lib/libswan/DBG_log.c000066400000000000000000000017661365625662500172670ustar00rootroot00000000000000/* Output a formatted debug string, for libreswan * * Copyright (C) 2017 Paul Wouters * Copyright (C) 2017-2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include #include #include "lswlog.h" lset_t cur_debugging = DBG_NONE; /* default to reporting nothing */ void DBG_log(const char *message, ...) { LSWLOG_DEBUG(buf) { va_list args; va_start(args, message); lswlogvf(buf, message, args); va_end(args); } } libreswan-3.32/lib/libswan/Makefile000066400000000000000000000122731365625662500173210ustar00rootroot00000000000000# Libreswan library # Copyright (C) 1998-2001 Henry Spencer. # Copyright (C) 2003, 2004 Xelerance Corporation # Copyright (C) 2012 Paul Wouters # Copyright (C) 2012-2013 Paul Wouters # Copyright (C) 2015-2019 Andrew Cagney # Copyright (C) 2019 Tuomo Soini # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # # XXX: # # Because libswan's Makefile tests USE_... variables, defined in # config.mk, using "ifeq", it needs to include that file early. # # Instead: # # - replace the code with '$(call if-enabled)'. # # - move the optional files to their own library? # ifndef top_srcdir include ../../mk/dirs.mk endif include $(top_srcdir)/mk/config.mk LIB = libswan.a OBJS += x509dn.o asn1.o oid.o OBJS += constants.o \ alloc.o diag.o \ id.o initaddr.o initsubnet.o \ keyblobtoid.o \ lex.o \ lswconf.o \ lswfips.o \ rangetosubnet.o sameaddr.o \ secrets.o \ subnettypeof.o ttoaddr.o ttodata.o ttoprotoport.o \ ttosa.o ttosubnet.o ttoul.o \ secitem_chunk.o \ base64_pubkey.o \ lswnss.o \ lsw_passert_fail.o \ alg_byname.o OBJS += nss_cert_load.o OBJS += certs.o OBJS += reqid.o ifeq ($(USE_NETKEY),true) OBJS += addr_lookup.o OBJS += kernel_xfrm_reply.o ifeq ($(USE_XFRM_INTERFACE), true) OBJS += netlink_attrib.o endif endif OBJS += log_ip.o OBJS += fd.o OBJS += kernel_alg.o OBJS += kernel_sadb.o OBJS += role.o OBJS += addrtot.o OBJS += addrtypeof.o OBJS += anyaddr.o OBJS += datatot.o OBJS += ultot.o OBJS += proposals.o OBJS += v1_proposals.o OBJS += v2_proposals.o OBJS += esp_info.o OBJS += ah_info.o OBJS += ike_info.o OBJS += ckaid.o OBJS += chunk.o OBJS += shunk.o OBJS += ip_address.o OBJS += ip_endpoint.o OBJS += ip_info.o OBJS += ip_protocol.o OBJS += ip_range.o OBJS += ip_said.o OBJS += ip_subnet.o OBJS += lmod.o OBJS += lset.o OBJS += deltatime.o OBJS += realtime.o OBJS += monotime.o OBJS += refcnt.o OBJS += debug.o OBJS += impair.o OBJS += keywords.o OBJS += DBG_dump.o OBJS += DBG_log.o OBJS += libreswan_exit_log_errno.o OBJS += libreswan_log_errno.o OBJS += libreswan_bad_case.o OBJS += libreswan_log.o OBJS += libreswan_log_rc.o OBJS += log_pexpect.o OBJS += jambuf.o OBJS += jam_bytes.o OBJS += lswlog.o OBJS += lswlog_nss_error.o OBJS += lswlog_nss_ckm.o OBJS += lswlog_nss_ckf.o OBJS += lswlog_nss_cka.o OBJS += lswlog_nss_secitem.o OBJS += lswlog_enum_lset_short.o OBJS += lswlog_to_file_stream.o OBJS += lswlog_pexpect.o OBJS += lswlog_passert.o # Crypto code: # # XXX: More is coming as it gets cleaned up and made more library # like. # not much left using this CFLAGS += -I$(top_srcdir)/lib/libcrypto OBJS += ike_alg.o OBJS += ike_alg_test.o OBJS += ike_alg_dh_nss_ecp_ops.o OBJS += ike_alg_dh_nss_modp_ops.o OBJS += ike_alg_hash_nss_ops.o OBJS += ike_alg_prf_mac_hmac_ops.o OBJS += ike_alg_prf_mac_nss_ops.o OBJS += ike_alg_prf_mac_xcbc_ops.o OBJS += ike_alg_prf_ikev1_mac_ops.o OBJS += ike_alg_prf_ikev2_mac_ops.o ifeq ($(USE_NSS_PRF),true) OBJS += ike_alg_prf_ikev1_nss_ops.o OBJS += ike_alg_prf_ikev2_nss_ops.o endif OBJS += ike_alg_encrypt_chacha20_poly1305.o OBJS += ike_alg_encrypt_nss_aead_ops.o OBJS += ike_alg_encrypt_nss_cbc_ops.o OBJS += ike_alg_encrypt_nss_ctr_ops.o OBJS += ike_alg_encrypt_nss_gcm_ops.o OBJS += ike_alg_desc.o ifeq ($(USE_3DES),true) OBJS += ike_alg_3des.o endif OBJS += ike_alg_aes.o OBJS += ike_alg_camellia.o ifeq ($(USE_CAST),true) OBJS += ike_alg_cast.o endif OBJS += ike_alg_dh.o OBJS += ike_alg_md5.o OBJS += ike_alg_none.o ifeq ($(USE_RIPEMD),true) OBJS += ike_alg_ripemd.o endif ifeq ($(USE_SERPENT),true) OBJS += ike_alg_serpent.o endif OBJS += ike_alg_sha1.o OBJS += ike_alg_sha2.o ifeq ($(USE_TWOFISH),true) OBJS += ike_alg_twofish.o endif OBJS += crypt_mac.o ifeq ($(USE_NSS_AVA_COPY),true) OBJS += nss_copies.o endif ifeq ($(USE_UNBOUND_EVENT_H_COPY),true) CFLAGS+=-I${LIBRESWANSRCDIR}/include/unbound endif ifeq ($(USE_DNSSEC),true) OBJS += unbound.o endif ifeq ($(USE_KLIPS),true) CFLAGS += -DKLIPS endif ifeq ($(USE_KLIPS),true) CFLAGS += -DPFKEYV2 OBJS += pfkey_sock.o pfkey_error.o OBJS += pfkey_v2_build.o pfkey_v2_ext_bits.o pfkey_v2_parse.o OBJS += pfkey_v2_debug.o endif # Original flags; this is a mess. CFLAGS+=${PORTINCLUDE} -I. CFLAGS+=-I${LIBRESWANSRCDIR} CFLAGS+= $(NSSFLAGS) CFLAGS+=-I${LIBRESWANSRCDIR}/include ${PORTINCLUDE} # XXX: hack until everything uses a consistent .c.o rule CFLAGS+=$(USERLAND_CFLAGS) CFLAGS+=${CROSSFLAGS} OBJS += $(abs_builddir)/version.o # build version.c using version number from Makefile.ver $(abs_builddir)/version.c: $(srcdir)/version.in.c $(top_srcdir)/Makefile.ver rm -f $@.tmp sed -e '/"/s/@IPSECVERSION@/$(IPSECVERSION)/' \ -e '/"/s/@IPSECVIDVERSION@/$(IPSECVIDVERSION)/' \ $(srcdir)/version.in.c \ > $@.tmp mv $@.tmp $@ include $(top_srcdir)/mk/library.mk libreswan-3.32/lib/libswan/addr_lookup.c000066400000000000000000000265731365625662500203400ustar00rootroot00000000000000/* * addr_lookup: resolve_defaultroute_one() -- attempt to resolve a default route * Copyright (C) 2005 Michael Richardson * Copyright (C) 2012-2014 Paul Wouters * Copyright (C) 2014 D. Hugh Redelmeier * Copyright (C) 2012-2013 Kim B. Heino * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include #include #include #include #include #include #include "constants.h" #include "lswalloc.h" #include "ipsecconf/confread.h" #include "kernel_xfrm_reply.h" #include "addr_lookup.h" #ifdef USE_DNSSEC # include "dnssec.h" #else # include #endif static void resolve_point_to_point_peer( const char *interface, sa_family_t family, char peer[ADDRTOT_BUF], /* result, if any */ bool verbose) { struct ifaddrs *ifap; /* Get info about all interfaces */ if (getifaddrs(&ifap) != 0) return; /* Find the right interface, if any */ for (const struct ifaddrs *ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { if ((ifa->ifa_flags & IFF_POINTOPOINT) != 0 && streq(ifa->ifa_name, interface)) { struct sockaddr *sa = ifa->ifa_ifu.ifu_dstaddr; if (sa != NULL && sa->sa_family == family && getnameinfo(sa, sa->sa_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6), peer, ADDRTOT_BUF, NULL, 0, NI_NUMERICHOST) == 0) { if (verbose) { printf("found peer %s to interface %s\n", peer, interface); } break; } /* in case failing getnameinfo set peer */ *peer = '\0'; } } freeifaddrs(ifap); } /* * Buffer size for netlink query (~100 bytes) and replies. * More memory will be allocated dynamically when needed for replies. * If DST is specified, reply will be ~100 bytes. * If DST is not specified, full route table will be returned. * On 64bit systems 100 route entries requires about 6KiB. * * When reading data from netlink the final packet in each recvfrom() * will be truncated if it doesn't fit to buffer. Netlink returns up * to 16KiB of data so always keep that much free. */ #define RTNL_BUFSIZE (NL_BUFMARGIN + 8192) /* * Initialize netlink query message. */ static void netlink_query_init(char *msgbuf, sa_family_t family) { struct nlmsghdr *nlmsg; struct rtmsg *rtmsg; /* Create request for route */ nlmsg = (struct nlmsghdr *)msgbuf; nlmsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); nlmsg->nlmsg_flags = NLM_F_REQUEST; nlmsg->nlmsg_type = RTM_GETROUTE; nlmsg->nlmsg_seq = 0; nlmsg->nlmsg_pid = getpid(); rtmsg = (struct rtmsg *)NLMSG_DATA(nlmsg); rtmsg->rtm_family = family; rtmsg->rtm_table = 0; rtmsg->rtm_protocol = 0; rtmsg->rtm_scope = 0; rtmsg->rtm_type = 0; rtmsg->rtm_src_len = 0; rtmsg->rtm_dst_len = 0; rtmsg->rtm_tos = 0; } /* * Add RTA_SRC or RTA_DST attribute to netlink query message. */ static void netlink_query_add(char *msgbuf, int rta_type, const ip_address *addr) { struct nlmsghdr *nlmsg; struct rtmsg *rtmsg; struct rtattr *rtattr; int rtlen; nlmsg = (struct nlmsghdr *)msgbuf; rtmsg = (struct rtmsg *)NLMSG_DATA(nlmsg); /* Find first empty attribute slot */ rtlen = RTM_PAYLOAD(nlmsg); rtattr = (struct rtattr *)RTM_RTA(rtmsg); while (RTA_OK(rtattr, rtlen)) rtattr = RTA_NEXT(rtattr, rtlen); /* Add attribute */ shunk_t bytes = address_as_shunk(addr); rtattr->rta_type = rta_type; rtattr->rta_len = sizeof(struct rtattr) + bytes.len; /* bytes */ memmove(RTA_DATA(rtattr), bytes.ptr, bytes.len); if (rta_type == RTA_SRC) rtmsg->rtm_src_len = bytes.len * 8; /* bits */ else rtmsg->rtm_dst_len = bytes.len * 8; nlmsg->nlmsg_len += rtattr->rta_len; } /* * Send netlink query message and read reply. */ static ssize_t netlink_query(char **pmsgbuf, size_t bufsize) { int sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); if (sock < 0) { int e = errno; printf("create netlink socket failure: (%d: %s)\n", e, strerror(e)); return -1; } /* Send request */ struct nlmsghdr *nlmsg = (struct nlmsghdr *)*pmsgbuf; if (send(sock, nlmsg, nlmsg->nlmsg_len, 0) < 0) { int e = errno; printf("write netlink socket failure: (%d: %s)\n", e, strerror(e)); close(sock); return -1; } /* Read response */ errno = 0; /* in case failure does not set it */ ssize_t len = netlink_read_reply(sock, pmsgbuf, bufsize, 1, getpid()); if (len < 0) printf("read netlink socket failure: (%d: %s)\n", errno, strerror(errno)); close(sock); return len; } /* * See if left->addr or left->next is %defaultroute and change it to IP. * * Returns: * -1: failure * 0: success * 1: please call again: more to do */ int resolve_defaultroute_one(struct starter_end *host, struct starter_end *peer, bool verbose) { /* * "left=" == host->addrtype and host->addr * "leftnexthop=" == host->nexttype and host->nexthop */ /* What kind of result are we seeking? */ bool seeking_src = (host->addrtype == KH_DEFAULTROUTE); bool seeking_gateway = (host->nexttype == KH_DEFAULTROUTE); bool has_peer = (peer->addrtype == KH_IPADDR || peer->addrtype == KH_IPHOSTNAME); if (verbose) printf("\nseeking_src = %d, seeking_gateway = %d, has_peer = %d\n", seeking_src, seeking_gateway, has_peer); if (!seeking_src && !seeking_gateway) return 0; /* this end already figured out */ /* msgbuf is dynamically allocated since the buffer may need to be grown */ char *msgbuf = alloc_bytes(RTNL_BUFSIZE, "netlink query"); bool has_dst = FALSE; int query_again = 0; /* Fill netlink request */ netlink_query_init(msgbuf, host->addr_family); if (host->nexttype == KH_IPADDR && peer->addr_family == AF_INET) { /* * My nexthop (gateway) is specified. * We need to figure out our source IP to get there. */ /* * AA_2019 Why use nexthop and not peer->addr to look up src address * the lore is there is (old) bug when looking up IPv4 src * IPv6 with gateway link local address will return link local * address and not the global address */ netlink_query_add(msgbuf, RTA_DST, &host->nexthop); has_dst = TRUE; } else if (has_peer) { /* * Peer IP is specified. * We may need to figure out source IP * and gateway IP to get there. */ if (peer->addrtype == KH_IPHOSTNAME) { #ifdef USE_DNSSEC err_t er = ttoaddr_num(peer->strings[KSCF_IP], 0, AF_UNSPEC, &peer->addr); if (er != NULL) { /* not numeric, so resolve it */ if (!unbound_resolve(peer->strings[KSCF_IP], 0, AF_INET, &peer->addr)) { if (!unbound_resolve( peer->strings[KSCF_IP], 0, AF_INET6, &peer->addr)) { pfree(msgbuf); return -1; } } } #else err_t er = ttoaddr(peer->strings[KSCF_IP], 0, AF_UNSPEC, &peer->addr); if (er != NULL) { pfree(msgbuf); return -1; } #endif } netlink_query_add(msgbuf, RTA_DST, &peer->addr); has_dst = TRUE; if (seeking_src && seeking_gateway) { /* * If we have only peer IP and no gateway/src we must * do two queries: * 1) find out gateway for dst * 2) find out src for that gateway * Doing both in one query returns src for dst. */ seeking_src = FALSE; query_again = 1; } } if (has_dst && host->addrtype == KH_IPADDR) { /* SRC works only with DST */ netlink_query_add(msgbuf, RTA_SRC, &host->addr); } /* * If we have for example host=%defaultroute + peer=%any * (no destination) the netlink reply will be full routing table. * We must do two queries: * 1) find out default gateway * 2) find out src for that default gateway */ if (!has_dst && seeking_src && seeking_gateway) { seeking_src = FALSE; query_again = 1; } if (seeking_gateway) { struct nlmsghdr *nlmsg = (struct nlmsghdr *)msgbuf; nlmsg->nlmsg_flags |= NLM_F_DUMP; } if (verbose) printf("seeking_src = %d, seeking_gateway = %d, has_dst = %d\n", seeking_src, seeking_gateway, has_dst); /* Send netlink get_route request */ ssize_t len = netlink_query(&msgbuf, RTNL_BUFSIZE); if (len < 0) { pfree(msgbuf); return -1; } /* Parse reply */ struct nlmsghdr *nlmsg = (struct nlmsghdr *)msgbuf; for (; NLMSG_OK(nlmsg, (size_t)len); nlmsg = NLMSG_NEXT(nlmsg, len)) { char r_interface[IF_NAMESIZE+1]; char r_source[ADDRTOT_BUF]; char r_gateway[ADDRTOT_BUF]; char r_destination[ADDRTOT_BUF]; if (nlmsg->nlmsg_type == NLMSG_DONE) break; if (nlmsg->nlmsg_type == NLMSG_ERROR) { printf("netlink error\n"); pfree(msgbuf); return -1; } /* ignore all but IPv4 and IPv6 */ struct rtmsg *rtmsg = (struct rtmsg *) NLMSG_DATA(nlmsg); if (rtmsg->rtm_family != AF_INET && rtmsg->rtm_family != AF_INET6) continue; /* Parse one route entry */ zero(&r_interface); r_source[0] = r_gateway[0] = r_destination[0] = '\0'; struct rtattr *rtattr = (struct rtattr *) RTM_RTA(rtmsg); int rtlen = RTM_PAYLOAD(nlmsg); while (RTA_OK(rtattr, rtlen)) { switch (rtattr->rta_type) { case RTA_OIF: if_indextoname(*(int *)RTA_DATA(rtattr), r_interface); break; case RTA_PREFSRC: inet_ntop(rtmsg->rtm_family, RTA_DATA(rtattr), r_source, sizeof(r_source)); break; case RTA_GATEWAY: inet_ntop(rtmsg->rtm_family, RTA_DATA(rtattr), r_gateway, sizeof(r_gateway)); break; case RTA_DST: inet_ntop(rtmsg->rtm_family, RTA_DATA(rtattr), r_destination, sizeof(r_destination)); break; } rtattr = RTA_NEXT(rtattr, rtlen); } /* * Ignore if not main table. * Ignore ipsecX or mastX interfaces. */ bool ignore = rtmsg->rtm_table != RT_TABLE_MAIN || startswith(r_interface, "ipsec") || startswith(r_interface, "mast"); if (verbose) { printf("dst %s via %s dev %s src %s table %d%s\n", r_destination, r_gateway, r_interface, r_source, rtmsg->rtm_table, ignore ? " (ignored)" : ""); } if (ignore) continue; if (seeking_src && r_source[0] != '\0') { err_t err = tnatoaddr(r_source, 0, rtmsg->rtm_family, &host->addr); if (err == NULL) { host->addrtype = KH_IPADDR; seeking_src = FALSE; if (verbose) printf("set addr: %s\n", r_source); } else if (verbose) { printf("unknown source results from kernel (%s): %s\n", r_source, err); } } if (seeking_gateway && r_destination[0] == '\0') { if (r_gateway[0] == '\0' && r_interface[0] != '\0') { /* * Point-to-Point default gw without "via IP" * Attempt to find r_gateway as the IP address * on the interface. */ resolve_point_to_point_peer( r_interface, host->addr_family, r_gateway, verbose); } if (r_gateway[0] != '\0') { err_t err = tnatoaddr(r_gateway, 0, rtmsg->rtm_family, &host->nexthop); if (err != NULL) { printf("unknown gateway results from kernel: %s\n", err); } else { /* Note: Use first even if multiple */ host->nexttype = KH_IPADDR; seeking_gateway = FALSE; if (verbose) printf("set nexthop: %s\n", r_gateway); } } } } pfree(msgbuf); return query_again; } libreswan-3.32/lib/libswan/addrtot.c000066400000000000000000000152201365625662500174610ustar00rootroot00000000000000/* * addresses to text * Copyright (C) 2000 Henry Spencer. * Copyright (C) 2012 Paul Wouters * Copyright (C) 2019 Andrew Cagney * Copyright (C) 2019 D. Hugh Redelmeier * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. * */ #include #include "ip_address.h" #include "libreswan.h" /* for inet_addrtot() */ #define IP4BYTES 4 /* bytes in an IPv4 address */ #define PERBYTE 4 /* three digits plus a dot or NUL */ #define IP6BYTES 16 /* bytes in an IPv6 address */ /* forwards */ static size_t normal4(const unsigned char *s, size_t len, char *b, const char **dp); static size_t normal6(const unsigned char *s, size_t len, char *b, const char **dp, int squish); static size_t reverse4(const unsigned char *s, size_t len, char *b, const char **dp); static size_t reverse6(const unsigned char *s, size_t len, char *b, const char **dp); /* - inet_addrtot - convert binary inet address to text (dotted decimal or IPv6 string) */ static size_t /* space needed for full conversion */ inet_addrtot(t, src, format, dst, dstlen) int t; /* AF_INET/AF_INET6 */ const void *src; int format; /* character */ char *dst; /* need not be valid if dstlen is 0 */ size_t dstlen; { char buf[1 + ADDRTOT_BUF + 1]; /* :address: */ /* initialize for cases not handled */ const char *p = ""; size_t n = sizeof("") - 1; switch (t) { case AF_INET: switch (format) { case 0: case 'Q': n = normal4(src, IP4BYTES, buf, &p); break; case 'r': n = reverse4(src, IP4BYTES, buf, &p); break; } break; case AF_INET6: switch (format) { case 0: n = normal6(src, IP6BYTES, buf, &p, 1); break; case 'Q': n = normal6(src, IP6BYTES, buf, &p, 0); break; case 'r': n = reverse6(src, IP6BYTES, buf, &p); break; } break; } if (dstlen > 0) { /* make dstlen actual result length, including NUL */ if (dstlen > n) dstlen = n + 1; memcpy(dst, p, dstlen - 1); dst[dstlen - 1] = '\0'; } return n; /* strlen(untruncated result) */ } /* * sin_addrtot - convert binary sockaddr_in/sockaddr_in6 address to text * (dotted decimal or IPv6 string) */ size_t /* space needed for full conversion */ sin_addrtot(src, format, dst, dstlen) const void *src; int format; /* character */ char *dst; /* need not be valid if dstlen is 0 */ size_t dstlen; { const union SINSIN6 { struct sockaddr_in sin; struct sockaddr_in6 sin6; } *sinp = (const union SINSIN6 *) src; switch (sinp->sin.sin_family) { case AF_INET: return inet_addrtot(AF_INET, &sinp->sin.sin_addr, format, dst, dstlen); case AF_INET6: return inet_addrtot(AF_INET6, &sinp->sin6.sin6_addr, format, dst, dstlen); default: dst[0] = '\0'; strncat(dst, "", dstlen - 1); /* we hope possible truncation does not cause problems */ return sizeof(""); } } /* - normal4 - normal IPv4 address-text conversion */ static size_t /* size of text, including NUL */ normal4(srcp, srclen, buf, dstp) const unsigned char *srcp; size_t srclen; char *buf; /* guaranteed large enough */ const char **dstp; /* where to put result pointer */ { int i; char *p; if (srclen != IP4BYTES) /* "can't happen" */ return 0; p = buf; for (i = 0; i < IP4BYTES; i++) { p += ultot(srcp[i], 10, p, PERBYTE); if (i != IP4BYTES - 1) *(p - 1) = '.'; /* overwrites the NUL */ } *dstp = buf; return p - buf; } /* - normal6 - normal IPv6 address-text conversion */ static size_t /* size of text, including NUL */ normal6(srcp, srclen, buf, dstp, squish) const unsigned char *srcp; size_t srclen; char *buf; /* guaranteed large enough, plus 2 */ const char **dstp; /* where to put result pointer */ int squish; /* whether to squish out 0:0 */ { int i; unsigned long piece; char *p; char *q; if (srclen != IP6BYTES) /* "can't happen" */ return 0; p = buf; *p++ = ':'; for (i = 0; i < IP6BYTES / 2; i++) { piece = (srcp[2 * i] << 8) + srcp[2 * i + 1]; p += ultot(piece, 16, p, 5); /* 5 = abcd + NUL */ *(p - 1) = ':'; /* overwrites the NUL */ } *p = '\0'; q = strstr(buf, ":0:0:"); if (squish && q != NULL) { /* zero squishing is possible */ p = q + 1; while (*p == '0' && *(p + 1) == ':') p += 2; q++; *q++ = ':'; /* overwrite first 0 */ while (*p != '\0') *q++ = *p++; *q = '\0'; if (!(*(q - 1) == ':' && *(q - 2) == ':')) *--q = '\0'; /* strip final : unless :: */ p = buf; if (!(*p == ':' && *(p + 1) == ':')) p++; /* skip initial : unless :: */ } else { q = p; *--q = '\0'; /* strip final : */ p = buf + 1; /* skip initial : */ } *dstp = p; return q - p + 1; } /* - reverse4 - IPv4 reverse-lookup conversion */ static size_t /* size of text, including NUL */ reverse4(srcp, srclen, buf, dstp) const unsigned char *srcp; size_t srclen; char *buf; /* guaranteed large enough */ const char **dstp; /* where to put result pointer */ { int i; char *p; if (srclen != IP4BYTES) /* "can't happen" */ return 0; p = buf; for (i = IP4BYTES - 1; i >= 0; i--) { p += ultot(srcp[i], 10, p, PERBYTE); *(p - 1) = '.'; /* overwrites the NUL */ } strcpy(p, "IN-ADDR.ARPA."); *dstp = buf; return strlen(buf) + 1; } /* - reverse6 - IPv6 reverse-lookup conversion (RFC 1886) * A trifle inefficient, really shouldn't use ultot... */ static size_t /* size of text, including NUL */ reverse6(srcp, srclen, buf, dstp) const unsigned char *srcp; size_t srclen; char *buf; /* guaranteed large enough */ const char **dstp; /* where to put result pointer */ { int i; unsigned long piece; char *p; if (srclen != IP6BYTES) /* "can't happen" */ return 0; p = buf; for (i = IP6BYTES - 1; i >= 0; i--) { piece = srcp[i]; p += ultot(piece & 0xf, 16, p, 2); *(p - 1) = '.'; p += ultot(piece >> 4, 16, p, 2); *(p - 1) = '.'; } strcpy(p, "IP6.ARPA."); *dstp = buf; return strlen(buf) + 1; } libreswan-3.32/lib/libswan/addrtypeof.c000066400000000000000000000016031365625662500201610ustar00rootroot00000000000000/* * extract parts of an ip_address * Copyright (C) 2000 Henry Spencer. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. */ #include #include "ip_address.h" #include "ip_info.h" /* - addrtypeof - get the type of an ip_address */ int addrtypeof(const ip_address *src) { const struct ip_info *t = address_type(src); return t == NULL ? AF_UNSPEC : t->af; } libreswan-3.32/lib/libswan/ah_info.c000066400000000000000000000066151365625662500174330ustar00rootroot00000000000000/* * Algorithm info parsing and creation functions * Author: JuanJo Ciarlante * * Copyright (C) 2012 Paul Wouters * Copyright (C) 2015-2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include #include #include "lswalloc.h" #include "lswlog.h" #include "proposals.h" #include "alg_byname.h" #include "lswfips.h" #include "ike_alg.h" #include "ike_alg_integ.h" static bool ah_proposal_ok(struct proposal_parser *parser, const struct proposal *proposal) { impaired_passert(PROPOSAL_PARSER, next_algorithm(proposal, PROPOSAL_encrypt, NULL) == NULL); impaired_passert(PROPOSAL_PARSER, next_algorithm(proposal, PROPOSAL_prf, NULL) == NULL); impaired_passert(PROPOSAL_PARSER, next_algorithm(proposal, PROPOSAL_integ, NULL) != NULL); /* ah=null is invalid */ if (!IMPAIR(ALLOW_NULL_NONE)) { FOR_EACH_ALGORITHM(proposal, integ, alg) { /* passerts */ const struct integ_desc *integ = integ_desc(alg->desc); if (integ == &ike_alg_integ_none) { proposal_error(parser, "AH cannot have 'none' as the integrity algorithm"); if (!impair_proposal_errors(parser)) { return false; } } } } return true; } /* * IKEv1: */ static const char default_v1_ah_proposals[] = "SHA1_96" /*???*/ ; const struct proposal_defaults v1_ah_defaults = { .proposals = default_v1_ah_proposals, }; /* * IKEv2: */ static const char default_v2_ah_proposals[] = "SHA2_512_256" "," "SHA2_256_128" "," /* * something strongswan might accept; bottom of the preference * list */ "SHA1_96" ; static const struct ike_alg *default_v2_ah_integ[] = { #ifdef USE_SHA2 &ike_alg_integ_sha2_512.common, &ike_alg_integ_sha2_256.common, #endif NULL, }; const struct proposal_defaults v2_ah_defaults = { .proposals = default_v2_ah_proposals, .integ = default_v2_ah_integ, }; /* * All together now ... */ const struct proposal_protocol ah_proposal_protocol = { .name = "AH", .ikev1_alg_id = IKEv1_ESP_ID, .defaults = { [IKEv1] = &v1_ah_defaults, [IKEv2] = &v2_ah_defaults, }, .proposal_ok = ah_proposal_ok, .integ = true, .dh = true, }; /* * ??? why is this called _ah_ when almost everything refers to esp? * XXX: Because it is parsing an "ah" line which requires a different * parser configuration - encryption isn't allowed. * * ??? the only difference between * ah_proposals_create_from_str and alg_info_esp_create_from_str * is in the second argument to proposal_parser. * * XXX: On the other hand, since "struct ike_info" and "struct * esp_info" are effectively the same, they can be merged. Doing * that, would eliminate the AH using ESP confusion. */ /* This function is tested in testing/algparse/algparse.c */ struct proposal_parser *ah_proposal_parser(const struct proposal_policy *policy) { return alloc_proposal_parser(policy, &ah_proposal_protocol); } libreswan-3.32/lib/libswan/alg_byname.c000066400000000000000000000116061365625662500201220ustar00rootroot00000000000000/* * Algorithm lookup, for libreswan * * Copyright (C) 2017-2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include "lswlog.h" #include "proposals.h" #include "alg_byname.h" #include "ike_alg.h" bool alg_byname_ok(struct proposal_parser *parser, const struct ike_alg *alg, shunk_t print_name) { const struct proposal_protocol *protocol = parser->protocol; const struct proposal_policy *policy = parser->policy; /* * If the connection is IKEv1|IKEv2 then this code will * exclude anything not supported by both protocols. */ switch (policy->version) { case IKEv1: /* IKEv1 has different IDs for ESP/IKE/AH */ if (alg->id[protocol->ikev1_alg_id] < 0) { proposal_error(parser, "%s %s algorithm '"PRI_SHUNK"' is not supported by IKEv1", protocol->name, ike_alg_type_name(alg->algo_type), pri_shunk(print_name)); return false; } break; case IKEv2: if (alg->id[IKEv2_ALG_ID] < 0) { proposal_error(parser, "%s %s algorithm '"PRI_SHUNK"' is not supported by IKEv2", protocol->name, ike_alg_type_name(alg->algo_type), pri_shunk(print_name)); return false; } break; default: /* ignore */ break; } /* * According to parser policy, is the algorithm "implemented"? * * For IKE, this checks things like an in-process * implementation being present. For ESP/AH this checks that * it is is implemented in the kernel (well except for DH * which is still requires an in-process implementation). */ passert(policy->alg_is_ok != NULL); if (!policy->alg_is_ok(alg)) { proposal_error(parser, "%s %s algorithm '"PRI_SHUNK"' is not supported", protocol->name, ike_alg_type_name(alg->algo_type), pri_shunk(print_name)); return false; } /* * Check that the algorithm is valid. * * FIPS, for instance, will invalidate some algorithms during * startup. * * Since it likely involves a lookup, it is left until last. */ if (!ike_alg_is_valid(alg)) { proposal_error(parser, "%s %s algorithm '"PRI_SHUNK"' is not valid", protocol->name, ike_alg_type_name(alg->algo_type), pri_shunk(print_name)); return false; } return true; } const struct ike_alg *alg_byname(struct proposal_parser *parser, const struct ike_alg_type *type, shunk_t name, shunk_t print_name) { const struct proposal_protocol *protocol = parser->protocol; const struct ike_alg *alg = ike_alg_byname(type, name); if (alg == NULL) { /* * Known at all? Poke around in the enum tables to * see if it turns up. */ if (ike_alg_enum_match(type, protocol->ikev1_alg_id, name) >= 0 || ike_alg_enum_match(type, IKEv2_ALG_ID, name) >= 0) { proposal_error(parser, "%s %s algorithm '"PRI_SHUNK"' is not supported", protocol->name, ike_alg_type_name(type), pri_shunk(print_name)); } else { proposal_error(parser, "%s %s algorithm '"PRI_SHUNK"' is not recognized", protocol->name, ike_alg_type_name(type), pri_shunk(print_name)); } passert(parser->error[0] != '\0'); DBGF(DBG_PROPOSAL_PARSER, "ike_alg_byname() failed: %s", parser->error); return NULL; } /* * Does it pass muster? */ if (!alg_byname_ok(parser, alg, print_name)) { passert(parser->error[0] != '\0'); DBGF(DBG_PROPOSAL_PARSER, "alg_byname_ok() failed: %s", parser->error); return NULL; } return alg; } const struct ike_alg *encrypt_alg_byname(struct proposal_parser *parser, shunk_t name, size_t key_bit_length, shunk_t print_name) { const struct ike_alg *alg = alg_byname(parser, IKE_ALG_ENCRYPT, name, print_name); if (alg == NULL) { return NULL; } const struct encrypt_desc *encrypt = encrypt_desc(alg); if (!IMPAIR(SEND_KEY_SIZE_CHECK) && key_bit_length > 0) { if (encrypt->keylen_omitted) { proposal_error(parser, "%s does not take variable key lengths", enum_short_name(&ikev2_trans_type_encr_names, encrypt->common.id[IKEv2_ALG_ID])); if (!impair_proposal_errors(parser)) { return NULL; } } if (!encrypt_has_key_bit_length(encrypt, key_bit_length)) { /* * XXX: make list up to keep tests happy; * should instead generate a real list from * encrypt. */ proposal_error(parser, "wrong encryption key length - key size must be 128 (default), 192 or 256"); if (!impair_proposal_errors(parser)) { return NULL; } } } return alg; } libreswan-3.32/lib/libswan/alloc.c000066400000000000000000000153201365625662500171130ustar00rootroot00000000000000/* * Memory allocation routines * Header: "lswalloc.h" * * Copyright (C) 1998-2001 D. Hugh Redelmeier. * Copyright (C) 2017-2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include /* pthread.h must be first include file */ #include #include #include #include #include #include #include #include "constants.h" #include "lswlog.h" #include "lswalloc.h" bool leak_detective = FALSE; /* must not change after first alloc! */ /* * memory allocation * * --leak_detective puts a wrapper around each allocation and maintains * a list of live ones. If a dead one is freed, an assertion MIGHT fail. * If the live list is corrupted, that will often be detected. * In the end, report_leaks() is called, and the names of remaining * live allocations are printed. At the moment, it is hoped, not that * the list is empty, but that there will be no surprises. * * Accepted Leaks: * - "struct iface" and "device name" (for "discovered" net interfaces) * - "struct pluto_event in event_schedule()" (events not associated with states) * - "Pluto lock name" (one only, needed until end -- why bother?) */ /* this magic number is 3671129837 decimal (623837458 complemented) */ #define LEAK_MAGIC 0xDAD0FEEDul union mhdr { struct { const char *name; union mhdr *older, *newer; unsigned long magic; unsigned long size; } i; /* info */ unsigned long long junk; /* force maximal alignment */ }; /* protects updates to the leak-detective linked list */ static pthread_mutex_t leak_detective_mutex = PTHREAD_MUTEX_INITIALIZER; static union mhdr *allocs = NULL; static void install_allocation(union mhdr *p, size_t size, const char *name) { p->i.name = name; p->i.size = size; p->i.magic = LEAK_MAGIC; p->i.newer = NULL; { pthread_mutex_lock(&leak_detective_mutex); p->i.older = allocs; if (allocs != NULL) allocs->i.newer = p; allocs = p; pthread_mutex_unlock(&leak_detective_mutex); } } static void remove_allocation(union mhdr *p) { pthread_mutex_lock(&leak_detective_mutex); if (p->i.older != NULL) { passert(p->i.older->i.newer == p); p->i.older->i.newer = p->i.newer; } if (p->i.newer == NULL) { passert(p == allocs); allocs = p->i.older; } else { passert(p->i.newer->i.older == p); p->i.newer->i.older = p->i.older; } pthread_mutex_unlock(&leak_detective_mutex); p->i.magic = ~LEAK_MAGIC; } static void *allocate(void *(*alloc)(size_t), size_t size, const char *name) { union mhdr *p; if (size == 0) { /* uclibc returns NULL on malloc(0) */ size = 1; } if (leak_detective) { /* fail on overflow */ if (sizeof(union mhdr) + size < size) return NULL; p = alloc(sizeof(union mhdr) + size); } else { p = alloc(size); } if (p == NULL) { PASSERT_FAIL("unable to allocate %zu bytes for %s", size, name); } if (leak_detective) { install_allocation(p, size, name); return p + 1; } else { return p; } } void *uninitialized_malloc(size_t size, const char *name) { return allocate(malloc, size, name); } void pfree(void *ptr) { if (leak_detective) { union mhdr *p; passert(ptr != NULL); p = ((union mhdr *)ptr) - 1; if (p->i.magic == ~LEAK_MAGIC) { PASSERT_FAIL("pointer %p invalid, possible double free (magic == ~LEAK_MAGIC)", ptr); } else if (p->i.magic != LEAK_MAGIC) { PASSERT_FAIL("pointer %p invalid, possible heap corruption or bad pointer (magic != LEAK_MAGIC or ~LEAK_MAGIC})", ptr); } remove_allocation(p); /* stomp on memory! Is another byte value better? */ memset(p, 0xEF, sizeof(union mhdr) + p->i.size); /* put back magic */ p->i.magic = ~LEAK_MAGIC; free(p); } else { free(ptr); } } void report_leaks(void) { union mhdr *p, *pprev = NULL; unsigned long n = 0; unsigned long numleaks = 0; unsigned long total = 0; pthread_mutex_lock(&leak_detective_mutex); p = allocs; while (p != NULL) { passert(p->i.magic == LEAK_MAGIC); passert(pprev == p->i.newer); pprev = p; p = p->i.older; n++; if (p == NULL || pprev->i.name != p->i.name || pprev->i.size != p->i.size) { /* filter out one-time leaks we prefer to not fix */ if (strstr(pprev->i.name, "(ignore)") == NULL) { if (n != 1) libreswan_log("leak: %lu * %s, item size: %lu", n, pprev->i.name, pprev->i.size); else libreswan_log("leak: %s, item size: %lu", pprev->i.name, pprev->i.size); numleaks += n; total += pprev->i.size; n = 0; } else { n = 0; } } } pthread_mutex_unlock(&leak_detective_mutex); if (numleaks != 0) libreswan_log("leak detective found %lu leaks, total size %lu", numleaks, total); else libreswan_log("leak detective found no leaks"); } static void *zalloc(size_t size) { return calloc(1, size); } void *alloc_bytes(size_t size, const char *name) { return allocate(zalloc, size, name); } void *clone_bytes(const void *orig, size_t size, const char *name) { void *p = uninitialized_malloc(size, name); memcpy(p, orig, size); return p; } /* * Re-size something on the HEAP. * * Unlike the more traditional realloc() this code doesn't allow a * NULL pointer. The caller, which is presumably implementing some * sort of realloc() wrapper, gets to handle this. So as to avoid any * confusion, give this a different name and function signature. */ void *uninitialized_realloc(void *ptr, size_t new_size, const char *name) { if (ptr == NULL) { return uninitialized_malloc(new_size, name); } else if (leak_detective) { union mhdr *p = ((union mhdr *)ptr) - 1; passert(p->i.magic == LEAK_MAGIC); remove_allocation(p); p = realloc(p, sizeof(union mhdr) + new_size); if (p == NULL) { } install_allocation(p, new_size, name); return p+1; } else { return realloc(ptr, new_size); } } void realloc_bytes(void **ptr, size_t old_size, size_t new_size, const char *name) { if (*ptr == NULL) { passert(old_size == 0); } else if (leak_detective) { union mhdr *p = ((union mhdr *)*ptr) - 1; passert(p->i.magic == LEAK_MAGIC); passert(p->i.size == old_size); } *ptr = uninitialized_realloc(*ptr, new_size, name); /* XXX: old_size..new_size still uninitialized */ if (new_size > old_size) { uint8_t *b = *ptr; memset(b + old_size, '\0', new_size - old_size); } } libreswan-3.32/lib/libswan/anyaddr.3.xml000066400000000000000000000105571365625662500201710ustar00rootroot00000000000000 PaulWoutersplaceholder to suppress warning IPSEC_ANYADDR 3 25 February 2008 libreswan Executable programs ipsec anyaddr ipsec isanyaddr ipsec unspecaddr ipsec isunspecaddr ipsec loopbackaddr ipsec isloopbackaddr get and test for addresses of type "any", "unspecified" and loopback get "any" address #include <libreswan.h> const char *anyaddr int af ip_address * dst int isanyaddr const ip_address * src const char *unspecaddr int af ip_address * dst int isunspecaddr const ip_address * src const char *loopbackaddr int af ip_address * dst int isloopbackaddr const ip_address * src DESCRIPTION These functions fill in, and test for, special values of the ip_address type. Anyaddr fills in the destination *dst with the “any” address of address family af (normally AF_INET or AF_INET6). The IPv4 “any” address is the one embodied in the old INADDR_ANY macro. Isanyaddr returns 1 if the src address equals the “any” address, and 0 otherwise. Similarly, unspecaddr supplies, and isunspecaddr tests for, the “unspecified” address, which may be the same as the “any” address. Similarly, loopbackaddr supplies, and islookbackaddr tests for, the loopback address. Anyaddr, unspecaddr, and loopbackaddr return NULL for success and a pointer to a string-literal error message for failure; see DIAGNOSTICS. SEE ALSO inet3, ipsec_addrtot3, ipsec_sameaddr3 DIAGNOSTICS Fatal errors in the address-supplying functions are: unknown address family. HISTORY Written for the FreeS/WAN project by Henry Spencer. libreswan-3.32/lib/libswan/anyaddr.c000066400000000000000000000021461365625662500174450ustar00rootroot00000000000000/* * special addresses * Copyright (C) 2000 Henry Spencer. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. */ #include #include /* for ntohl() */ #include "ip_address.h" /* * Test for the any-address value (IPv6 calls this the unspecified * address). Make it obvious that this version consideres an invalid * (presumably zeroed) ip_address structure to be 'any'. * * XXX: callers seem to be using this as a proxy for * address_is_invalid() (i.e., not updated). */ bool isanyaddr(const ip_address * src) { return address_is_invalid(src) || address_is_any(src); } libreswan-3.32/lib/libswan/asn1.c000066400000000000000000000174371365625662500166760ustar00rootroot00000000000000/* * Simple ASN.1 parser * Copyright (C) 2000-2004 Andreas Steffen, Zuercher Hochschule Winterthur * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include #include #include #include "sysdep.h" #include "constants.h" #include "lswlog.h" #include "lswalloc.h" #include "realtime.h" #include "asn1.h" #include "oid.h" /* * If the oid is listed in the oid_names table then the corresponding * position in the oid_names table is returned otherwise -1 is returned */ int known_oid(chunk_t object) { int oid = 0; while (object.len > 0) { if (oid_names[oid].octet == *object.ptr) { object.len--; object.ptr++; if (object.len == 0) { /* at end of object */ if (oid_names[oid].down == 0) return oid; /* found terminal symbol */ else return OID_UNKNOWN; /* end of object but not terminal */ } else { /* object continues */ if (oid_names[oid].down == 0) { return OID_UNKNOWN; /* terminal but not end of object */ } else { /* advance to next hex octet in table * so we can match next octet of OID */ oid++; } } } else { if (oid_names[oid].next != 0) oid = oid_names[oid].next; else return OID_UNKNOWN; } } return OID_UNKNOWN; } /* * Skip tag and decode the length in bytes of an ASN.1 object. * Blob is updated to reflect the tag and length have been consumed */ size_t asn1_length(chunk_t *blob) { u_char n; size_t len; if (blob->len < 2) { DBG(DBG_PARSING, DBG_log( "insufficient number of octets to parse ASN.1 length")); return ASN1_INVALID_LENGTH; } /* advance from tag field on to length field */ blob->ptr++; blob->len--; /* read first octet of length field */ n = *blob->ptr++; blob->len--; if ((n & 0x80) == 0) { /* single length octet */ if (n > blob->len) { DBG(DBG_PARSING, DBG_log("number of length octets is larger than ASN.1 object")); return ASN1_INVALID_LENGTH; } return n; } /* composite length, determine number of length octets */ n &= 0x7f; if (n > blob->len) { DBG(DBG_PARSING, DBG_log("number of length octets is larger than ASN.1 object")); return ASN1_INVALID_LENGTH; } if (n > sizeof(len)) { DBG(DBG_PARSING, DBG_log("number of length octets is larger than limit of %d octets", (int) sizeof(len))); return ASN1_INVALID_LENGTH; } len = 0; while (n-- > 0) { len = 256 * len + *blob->ptr++; blob->len--; } if (len > blob->len) { DBG(DBG_PARSING, DBG_log("length is larger than remaining blob size")); return ASN1_INVALID_LENGTH; } return len; } size_t asn1_length_signature(chunk_t *blob , chunk_t *sig_val) { u_char n; u_char type_r,type_s; int len_r,len_s; if (blob->len < 2) { DBG(DBG_PARSING, DBG_log( "insufficient number of octets to parse DER Signature length")); return ASN1_INVALID_LENGTH; } /* advance from tag field on to length field */ blob->ptr++; blob->len--; /* read first octet of length field */ n = *blob->ptr++; /* advance from length field to type field of integer r 0x02*/ type_r = *blob->ptr++; if (type_r == 0x02) { /* single length octet */ /* find the length of integer r*/ len_r = *blob->ptr++; if (len_r%2 != 0) { len_r = len_r-1; /* advance to the next octet as the current octet is 0 */ blob->ptr++; } sig_val->len = len_r; /* XXX: need to check len_r and len_s fits in this */ sig_val->ptr = alloc_bytes(len_r * 2, "ec points"); DBG(DBG_PARSING, DBG_log(" sig_val len is %zu",sig_val->len)); /* copy the values of r into signature */ memcpy(sig_val->ptr,blob->ptr,len_r); /* advance from length field of integer r to type field of integer s 0x02*/ blob->ptr += len_r; type_s = *(blob->ptr); DBG(DBG_PARSING, DBG_log(" type_s is %d",type_s)); if (type_s == 0x02) { /* find the length of integer r*/ blob->ptr++; len_s = *blob->ptr++; if (len_s%2 !=0) { len_s = len_s-1; /* advance to the next octet as the current octet is 0 */ blob->ptr++; } DBG(DBG_PARSING, DBG_log(" len_s is %d",len_s)); sig_val->len += len_s; DBG(DBG_PARSING, DBG_log(" sig_val total len is %zu",sig_val->len)); /* copy the values of r into signature */ memcpy(sig_val->ptr+len_r,blob->ptr,len_s); } } else { DBG(DBG_PARSING, DBG_log("Invalid DER encoded signature")); } if (n > blob->len) { DBG(DBG_PARSING, DBG_log("number of length octets is larger than ASN.1 object")); return ASN1_INVALID_LENGTH; } return (sig_val->len); } /* * codes ASN.1 lengths up to a size of 16'777'215 bytes */ void code_asn1_length(size_t length, chunk_t *code) { if (length < 128) { code->ptr[0] = length; code->len = 1; } else if (length < 256) { code->ptr[0] = 0x81; code->ptr[1] = (u_char) length; code->len = 2; } else if (length < 65536) { code->ptr[0] = 0x82; code->ptr[1] = length >> 8; code->ptr[2] = length & 0x00ff; code->len = 3; } else { code->ptr[0] = 0x83; code->ptr[1] = length >> 16; code->ptr[2] = (length >> 8) & 0x00ff; code->ptr[3] = length & 0x0000ff; code->len = 4; } } /* * Determines if a character string is of type ASN.1 printableString. * See https://en.wikipedia.org/w/index.php?title=PrintableString */ bool is_printablestring(chunk_t str) { /* * printable string character set: * "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 '()+,-./:=?" */ static const unsigned char printable_set[] = { 0201u, /* 0x20 ' (first is the real SPACE) */ 0373u, /* 0x28 () +,-./ */ 0377u, /* 0x30 01234567 */ 0247u, /* 0x38 89: = ? */ 0376u, /* 0x40 ABCDEFG */ 0377u, /* 0x48 HIJKLMNO */ 0377u, /* 0x50 PQRSTUVW */ 0007u, /* 0x58 XYZ */ 0376u, /* 0x60 abcdefg */ 0377u, /* 0x68 hijklmno */ 0377u, /* 0x70 pqrstuvw */ 0007u, /* 0x78 xyz */ }; for (unsigned i = 0; i < str.len; i++) { /* * Tricky test. * The first part checks if the current character is * within the range of graphical characters (0x20 - 0x7f). * It saves a branch instruction by exploiting the way * underflow of unsigned subtraction yields a large number. * If the character is in range, we check it by subscripting * its bit within printable_set[]. */ unsigned u = (unsigned)str.ptr[i] - 0x20u; if (!(u <= 0x7fU - 0x20u && (printable_set[u / 8u] & 1u << (u % 8u)))) return FALSE; } return TRUE; } /* * tests if a blob contains a valid ASN.1 set or sequence */ bool is_asn1(chunk_t blob) { unsigned len; if (blob.len < 1) { DBG(DBG_PARSING, DBG_log(" cert blob is empty: not binary ASN.1")); return FALSE; } switch (blob.ptr[0]) { case ASN1_SEQUENCE: case ASN1_SET: break; /* looks OK */ default: DBG(DBG_PARSING, DBG_log(" cert blob content is not binary ASN.1")); return FALSE; } len = asn1_length(&blob); if (len != blob.len) { DBG(DBG_PARSING, DBG_log(" cert blob size (%zu) does not match ASN.1 coded length (%u)", blob.len, len)); return FALSE; } return TRUE; } bool is_asn1_der_encoded_signature(chunk_t blob, chunk_t *sig_val) { if (blob.len < 1) { DBG(DBG_PARSING, DBG_log(" Signature is empty: not binary ASN.1 DER encoded Signature")); return FALSE; } switch (blob.ptr[0]) { case ASN1_SEQUENCE: break; /* looks OK */ default: DBG(DBG_PARSING, DBG_log(" Signature blob content is not binary ASN.1")); return FALSE; } asn1_length_signature(&blob , sig_val); return TRUE; } libreswan-3.32/lib/libswan/atoaddr.3.xml000066400000000000000000000277461365625662500201750ustar00rootroot00000000000000 PaulWoutersplaceholder to suppress warning IPSEC_ATOADDR 3 25 February 2008 libreswan Executable programs ipsec atoaddr ipsec addrtoa ipsec atosubnet ipsec subnettoa convert Internet addresses and Subnet masks to and from ASCII #include <libreswan.h> const char *atoaddr const char * src size_t srclen struct in_addr * addr size_t addrtoa struct in_addr addr int format char * dst size_t dstlen const char *atosubnet const char * src size_t srclen struct in_addr * addr struct in_addr * mask size_t subnettoa struct in_addr addr struct in_addr mask int format char * dst size_t dstlen DESCRIPTION These functions are obsolete; see ipsec_ttoaddr3 for their replacements. atoaddr and atosubnet have already been deleted. Atoaddr converts an ASCII name or dotted-decimal address into a binary address (in network byte order). Addrtoa does the reverse conversion, back to an ASCII dotted-decimal address. Atosubnet and subnettoa do likewise for the “address/mask” ASCII form used to write a specification of a subnet. An address is specified in ASCII as a dotted-decimal address (e.g. 1.2.3.4), an eight-digit network-order hexadecimal number with the usual C prefix (e.g. 0x01020304, which is synonymous with 1.2.3.4), an eight-digit host-order hexadecimal number with a 0h prefix (e.g. 0h01020304, which is synonymous with 1.2.3.4 on a big-endian host and 4.3.2.1 on a little-endian host), a DNS name to be looked up via gethostbyname3, or an old-style network name to be looked up via getnetbyname3. A dotted-decimal address may be incomplete, in which case ASCII-to-binary conversion implicitly appends as many instances of .0 as necessary to bring it up to four components. The components of a dotted-decimal address are always taken as decimal, and leading zeros are ignored. For example, 10 is synonymous with 10.0.0.0, and 128.009.000.032 is synonymous with 128.9.0.32 (the latter example is verbatim from RFC 1166). The result of addrtoa is always complete and does not contain leading zeros. The letters in a hexadecimal address may be uppercase or lowercase or any mixture thereof. Use of hexadecimal addresses is strongly discouraged; they are included only to save hassles when dealing with the handful of perverted programs that already print network addresses in hexadecimal. DNS names may be complete (optionally terminated with a “.”) or incomplete, and are looked up as specified by local system configuration (see resolver5). The h_addr value returned by gethostbyname3 is used, so with current DNS implementations, the result when the name corresponds to more than one address is difficult to predict. Name lookup resorts to getnetbyname3 only if gethostbyname3 fails. A subnet specification is of the form network/mask. The network and mask can be any form acceptable to atoaddr. In addition, the mask can be a decimal integer (leading zeros ignored) giving a bit count, in which case it stands for a mask with that number of high bits on and all others off (e.g., 24 means 255.255.255.0). In any case, the mask must be contiguous (a sequence of high bits on and all remaining low bits off). As a special case, the subnet specification %default is a synonym for 0.0.0.0/0. Atosubnet ANDs the mask with the address before returning, so that any non-network bits in the address are turned off (e.g., 10.1.2.3/24 is synonymous with 10.1.2.0/24). Subnettoa generates the decimal-integer-bit-count form of the mask, with no leading zeros, unless the mask is non-contiguous. The srclen parameter of atoaddr and atosubnet specifies the length of the ASCII string pointed to by src; it is an error for there to be anything else (e.g., a terminating NUL) within that length. As a convenience for cases where an entire NUL-terminated string is to be converted, a srclen value of 0 is taken to mean strlen(src). The dstlen parameter of addrtoa and subnettoa specifies the size of the dst parameter; under no circumstances are more than dstlen bytes written to dst. A result that will not fit is truncated. Dstlen can be zero, in which case dst need not be valid and no result is written, but the return value is unaffected; in all other cases, the (possibly truncated) result is NUL-terminated. The libreswan.h header file defines constants, ADDRTOA_BUF and SUBNETTOA_BUF, that are the sizes of buffers just large enough for worst-case results. The format parameter of addrtoa and subnettoa specifies what format is to be used for the conversion. The value 0 (not the ASCII character '0', but a zero value) specifies a reasonable default, and is in fact the only format currently available. This parameter is a hedge against future needs. The ASCII-to-binary functions return NULL for success and a pointer to a string-literal error message for failure; see DIAGNOSTICS. The binary-to-ASCII functions return 0 for a failure, and otherwise always return the size of buffer that would be needed to accommodate the full conversion result, including terminating NUL; it is the caller's responsibility to check this against the size of the provided buffer to determine whether truncation has occurred. SEE ALSO inet3 DIAGNOSTICS Fatal errors in atoaddr are: empty input; attempt to allocate temporary storage for a very long name failed; name lookup failed; syntax error in dotted-decimal form; dotted-decimal component too large to fit in 8 bits. Fatal errors in atosubnet are: no / in src; atoaddr error in conversion of network or mask; bit-count mask too big; mask non-contiguous. Fatal errors in addrtoa and subnettoa are: unknown format. HISTORY Written for the FreeS/WAN project by Henry Spencer. BUGS The interpretation of incomplete dotted-decimal addresses (e.g. 10/24 means 10.0.0.0/24) differs from that of some older conversion functions, e.g. those of inet3. The behavior of the older functions has never been particularly consistent or particularly useful. Ignoring leading zeros in dotted-decimal components and bit counts is arguably the most useful behavior in this application, but it might occasionally cause confusion with the historical use of leading zeros to denote octal numbers. It is barely possible that somebody, somewhere, might have a legitimate use for non-contiguous subnet masks. Getnetbyname3 is a historical dreg. The restriction of ASCII-to-binary error reports to literal strings (so that callers don't need to worry about freeing them or copying them) does limit the precision of error reporting. The ASCII-to-binary error-reporting convention lends itself to slightly obscure code, because many readers will not think of NULL as signifying success. A good way to make it clearer is to write something like: const char *error; error = atoaddr( /* ... */ ); if (error != NULL) { /* something went wrong */ libreswan-3.32/lib/libswan/atoasr.3000066400000000000000000000104221365625662500172300ustar00rootroot00000000000000.TH "IPSEC_ATOASR" 3 "11 June 2001" .SH NAME ipsec_atoasr, ipsec_rangetoa \- convert ASCII to Internet address, subnet, or range, convert Internet address range to ASCII .SH SYNOPSIS .B "#include .sp .B "const char *atoasr(const char *src, size_t srclen," .ti +1c .B "char *type, struct in_addr *addrs);" .br .B "size_t rangetoa(struct in_addr *addrs, int format, .ti +1c .B "char *dst, size_t dstlen);" .SH DESCRIPTION These functions are obsolete; there is no current equivalent, because so far they have not proved useful. .PP .I Atoasr converts an ASCII address, subnet, or address range into a suitable combination of binary addresses (in network byte order). .I Rangetoa converts an address range back into ASCII, using dotted-decimal form for the addresses (the other reverse conversions are handled by .IR ipsec_addrtoa (3) and .IR ipsec_subnettoa (3)). .PP A single address can be any form acceptable to .IR ipsec_atoaddr (3): dotted decimal, DNS name, or hexadecimal number. A subnet specification uses the form \fInetwork\fB/\fImask\fR interpreted by .IR ipsec_atosubnet (3). .PP An address range is two .IR ipsec_atoaddr (3) addresses separated by a .B ... delimiter. If there are four dots rather than three, the first is taken as part of the begin address, e.g. for a complete DNS name that ends with .B . to suppress completion attempts. The begin address of a range must be less than or equal to the end address. .PP The .I srclen parameter of .I atoasr specifies the length of the ASCII string pointed to by .IR src ; it is an error for there to be anything else (e.g., a terminating NUL) within that length. As a convenience for cases where an entire NUL-terminated string is to be converted, a .I srclen value of .B 0 is taken to mean .BR strlen(src) . .PP The .I type parameter of .I atoasr must point to a .B char variable used to record which form was found. The .I addrs parameter must point to a two-element array of .B "struct in_addr" that receives the results. The values stored into .BR *type , and the corresponding values in the array, are: .PP .ta 3c +2c +3c *type addrs[0] addrs[1] .sp 0.8 address \&\fB'a'\fR address - .br subnet \&\fB's'\fR network mask .br range \&\fB'r'\fR begin end .PP The .I dstlen parameter of .I rangetoa specifies the size of the .I dst parameter; under no circumstances are more than .I dstlen bytes written to .IR dst . A result that will not fit is truncated. .I Dstlen can be zero, in which case .I dst need not be valid and no result is written, but the return value is unaffected; in all other cases, the (possibly truncated) result is NUL-terminated. The .I libreswan.h header file defines a constant, .BR RANGETOA_BUF , which is the size of a buffer just large enough for worst-case results. .PP The .I format parameter of .I rangetoa specifies what format is to be used for the conversion. The value .B 0 (not the ASCII character .BR '0' , but a zero value) specifies a reasonable default, and is in fact the only format currently available. This parameter is a hedge against future needs. .PP .I Atoasr returns NULL for success and a pointer to a string-literal error message for failure; see DIAGNOSTICS. .I Rangetoa returns .B 0 for a failure, and otherwise returns the size of buffer that would be needed to accommodate the full conversion result, including terminating NUL; it is the caller's responsibility to check this against the size of the provided buffer to determine whether truncation has occurred. .SH SEE ALSO ipsec_atoaddr(3), ipsec_atosubnet(3) .SH DIAGNOSTICS Fatal errors in .I atoasr are: empty input; error in .IR ipsec_atoaddr (3) or .IR ipsec_atosubnet (3) during conversion; begin address of range exceeds end address. .PP Fatal errors in .I rangetoa are: unknown format. .SH HISTORY Written for the FreeS/WAN project by Henry Spencer. .SH BUGS The restriction of error reports to literal strings (so that callers don't need to worry about freeing them or copying them) does limit the precision of error reporting. .PP The error-reporting convention lends itself to slightly obscure code, because many readers will not think of NULL as signifying success. A good way to make it clearer is to write something like: .PP .RS .nf .B "const char *error;" .sp .B "error = atoasr( /* ... */ );" .B "if (error != NULL) {" .B " /* something went wrong */" .fi .RE libreswan-3.32/lib/libswan/base64_pubkey.c000066400000000000000000000143501365625662500204660ustar00rootroot00000000000000/* * convert rsa pubkeys to/from RFC2537/RFC3110 resource records, for libreswan * * Copyright (C) 1998-2004 D. Hugh Redelmeier. * Copyright (C) 2005 Michael Richardson * Copyright (C) 2009-2012 Avesh Agarwal * Copyright (C) 2012-2015 Paul Wouters * Copyright (C) 2016 Andrew Cagney * Copyright (C) 2018 Sahana Prasad * Copyright (C) 2019 D. Hugh Redelmeier * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include "lswalloc.h" #include "lswlog.h" #include "secrets.h" /* * Deal with RFC Resource Records as defined in rfc3110 (nee rfc2537). */ static err_t rsa_pubkey_to_rfc_resource_record(chunk_t exponent, chunk_t modulus, chunk_t *rr) { *rr = EMPTY_CHUNK; /* * Since exponent length field is either 1 or 3 bytes in size, * just allocate 3 extra bytes. */ size_t rrlen = exponent.len + modulus.len + 3; u_char *buf = alloc_bytes(rrlen, "buffer for rfc3110"); u_char *p = buf; if (exponent.len <= 255) { *p++ = exponent.len; } else if (exponent.len <= 0xffff) { *p++ = 0; *p++ = (exponent.len >> 8) & 0xff; *p++ = exponent.len & 0xff; } else { pfree(buf); return "RSA public key exponent too long for resource record"; } memcpy(p, exponent.ptr, exponent.len); p += exponent.len; memcpy(p, modulus.ptr, modulus.len); p += modulus.len; *rr = (chunk_t) { .ptr = buf, .len = p - buf, }; return NULL; } /* Note: e and n will point int rr */ static err_t rfc_resource_record_to_rsa_pubkey(chunk_t rr, chunk_t *e, chunk_t *n) { *e = EMPTY_CHUNK; *n = EMPTY_CHUNK; /* * Step 1: find the bounds of the exponent and modulus within * the resource record and verify that they are sane. */ chunk_t exponent; if (rr.len >= 2 && rr.ptr[0] != 0x00) { /* * Exponent length is one-byte, followed by that many * exponent bytes */ exponent = (chunk_t) { .ptr = rr.ptr + 1, .len = rr.ptr[0] }; } else if (rr.len >= 3 && rr.ptr[0] == 0x00) { /* * Exponent length is 0x00 followed by 2 bytes of * length (big-endian), followed by that many exponent * bytes */ exponent = (chunk_t) { .ptr = rr.ptr + 3, .len = (rr.ptr[1] << BITS_PER_BYTE) + rr.ptr[2], }; } else { /* not even room for length! */ return "RSA public key resource record way too short"; } /* * Does the exponent fall off the end of the resource record? */ u_char *const exponent_end = exponent.ptr + exponent.len; u_char *const rr_end = rr.ptr + rr.len; if (exponent_end > rr_end) { return "truncated RSA public key resource record exponent"; } /* * What is left over forms the modulus. */ chunk_t modulus = { .ptr = exponent_end, .len = rr_end - exponent_end, }; if (modulus.len < RSA_MIN_OCTETS_RFC) { return "RSA public key resource record modulus too short"; } if (modulus.len < RSA_MIN_OCTETS) { return RSA_MIN_OCTETS_UGH; } if (modulus.len > RSA_MAX_OCTETS) { return RSA_MAX_OCTETS_UGH; } /* * Step 2: all looks good, export the slices */ *e = exponent; *n = modulus; return NULL; } err_t rsa_pubkey_to_base64(chunk_t exponent, chunk_t modulus, char **base64_rr) { *base64_rr = NULL; chunk_t rr_chunk; err_t err = rsa_pubkey_to_rfc_resource_record(exponent, modulus, &rr_chunk); if (err != NULL) { return err; } /* * A byte is 8-bits, base64 uses 6-bits (2^6=64). Plus some * for 0s. Plus some for \0. Plus some extra for rounding. */ size_t rr_len = rr_chunk.len * 8 / 6 + 2 + 1 + 10; char *rr = alloc_bytes(rr_len, "base64 resource record"); size_t n = datatot(rr_chunk.ptr, rr_chunk.len, 's', rr, rr_len); if (n >= rr_len) { freeanychunk(rr_chunk); pfreeany(rr); return "base64 encoded RSA public key resource record larger than expected"; } *base64_rr = rr; freeanychunk(rr_chunk); return NULL; } #if 0 /* not used (yet?). Good thing since it isn't implemented. */ err_t base64_to_rsa_pubkey(const char *rr, chunk_t *exponent, chunk_t *modulus) { return "not implemented"; } #endif #if 0 /* not used (yet?) */ err_t pack_RSA_public_key(const struct RSA_public_key *rsa, chunk_t *rr) { return rsa_pubkey_to_rfc_resource_record(rsa->e, rsa->n, rr); } #endif err_t unpack_RSA_public_key(struct RSA_public_key *rsa, const chunk_t *pubkey) { /* unpack */ chunk_t exponent; chunk_t modulus; err_t rrerr = rfc_resource_record_to_rsa_pubkey(*pubkey, &exponent, &modulus); if (rrerr != NULL) { return rrerr; } ckaid_t ckaid; err_t ckerr = form_ckaid_rsa(modulus, &ckaid); if (ckerr != NULL) { return ckerr; } keyblobtoid(pubkey->ptr, pubkey->len, rsa->keyid, sizeof(rsa->keyid)); rsa->k = modulus.len; rsa->e = clone_hunk(exponent, "e"); rsa->n = clone_hunk(modulus, "n"); rsa->ckaid = ckaid; /* generate the CKAID */ if (DBGP(DBG_BASE)) { /* pubkey information isn't DBG_PRIVATE */ DBG_log("keyid: *%s", rsa->keyid); DBG_dump_hunk(" n", rsa->n); DBG_dump_hunk(" e", rsa->e); DBG_log_ckaid(" CKAID", rsa->ckaid); } return NULL; } err_t unpack_ECDSA_public_key(struct ECDSA_public_key *ecdsa, const chunk_t *pubkey) { /* ??? can this be cloned later, after form_ckaid_ecdsa has succeeded? */ ecdsa->pub = clone_hunk(*pubkey, "public value"); ckaid_t ckaid; err_t err = form_ckaid_ecdsa(ecdsa->pub, &ckaid); if (err != NULL) { freeanychunk(ecdsa->pub); return err; } memcpy(ecdsa->keyid, pubkey->ptr, KEYID_BUF-1); ecdsa->keyid[KEYID_BUF-1] = '\0'; ecdsa->k = pubkey->len; ecdsa->ckaid = ckaid; /* generate the CKAID */ /* ??? really? Not done above? */ if (DBGP(DBG_BASE)) { /* pubkey information isn't DBG_PRIVATE */ DBG_log("keyid: *%s", ecdsa->keyid); DBG_log(" key size: *%s", ecdsa->keyid); DBG_dump_hunk(" pub", ecdsa->pub); DBG_log_ckaid(" CKAID", ecdsa->ckaid); } return NULL; } libreswan-3.32/lib/libswan/certs.c000066400000000000000000000040261365625662500171420ustar00rootroot00000000000000/* Certificate support for IKE authentication * Copyright (C) 2002-2004 Andreas Steffen, Zuercher Hochschule Winterthur * Copyright (C) 2003-2006 Michael Richardson * Copyright (C) 2009 Paul Wouters * Copyright (C) 2009 Avesh Agarwal * Copyright (C) 2012-2013 Paul Wouters * Copyright (C) 2017 Paul Wouters * Copyright (C) 2013 Tuomo Soini * Copyright (C) 2013 Matt Rogers * Copyright (C) 2019 Andrew Cagney * Copyright (C) 2019 D. Hugh Redelmeier * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include "certs.h" #include "lswalloc.h" #include "libreswan/passert.h" void release_certs(struct certs **head) { while (*head != NULL) { struct certs *old = *head; *head = old->next; CERT_DestroyCertificate(old->cert); pfree(old); } } void add_cert(struct certs **head, CERTCertificate *cert) { passert(cert != NULL); struct certs *new = alloc_thing(struct certs, __func__); new->cert = cert; new->next = *head; *head = new; } CERTCertificate *make_end_cert_first(struct certs **head) { for (struct certs *entry = *head; entry != NULL; entry = entry->next) { if (!CERT_IsCACert(entry->cert, NULL)) { /* * Swap .cert values of entry and *head. * This will work even if entry == *head. */ CERTCertificate *end_cert = entry->cert; entry->cert = (*head)->cert; (*head)->cert = end_cert; return end_cert; } } return NULL; } libreswan-3.32/lib/libswan/chunk.c000066400000000000000000000065221365625662500171350ustar00rootroot00000000000000/* memory chunks, for libreswan * * Copyright (C) 2018 Andrew Cagney * Copyright (C) 2019 D. Hugh Redelmeier * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include "chunk.h" #include "lswalloc.h" #include "lswlog.h" /* for DBG_dump() */ #include "ctype.h" /* for isxdigit() */ #include /* for strtoul() */ /* * Compiler note: some older versions of GCC claim that EMPTY_CHUNK * isn't a constant so we cannot use it as an initializer for empty_chunk. */ const chunk_t empty_chunk = { .ptr = NULL, .len = 0 }; chunk_t chunk(void *ptr, size_t len) { return (chunk_t) { .ptr = ptr, .len = len, }; } chunk_t alloc_chunk(size_t count, const char *name) { uint8_t *ptr = alloc_things(uint8_t, count, name); return chunk(ptr, count); } void free_chunk_content(chunk_t *chunk) { pfreeany(chunk->ptr); *chunk = EMPTY_CHUNK; } chunk_t clone_chunk_chunk(chunk_t lhs, chunk_t rhs, const char *name) { size_t len = lhs.len + rhs.len; chunk_t cat = { .len = len, .ptr = alloc_things(uint8_t, len, name), }; memcpy(cat.ptr, lhs.ptr, lhs.len); memcpy(cat.ptr + lhs.len, rhs.ptr, rhs.len); return cat; } char *clone_chunk_as_string(chunk_t chunk, const char *name) { if (chunk.ptr == NULL) { return NULL; } else if (chunk.len > 0 && chunk.ptr[chunk.len - 1] == '\0') { return clone_bytes(chunk.ptr, chunk.len, name); } else { char *string = alloc_things(char, chunk.len + 1, name); memcpy(string, chunk.ptr, chunk.len); return string; } } chunk_t clone_bytes_as_chunk(const void *bytes, size_t sizeof_bytes, const char *name) { if (bytes == NULL) { return empty_chunk; } else { return chunk(clone_bytes(bytes, sizeof_bytes, name), sizeof_bytes); } } bool chunk_eq(chunk_t a, chunk_t b) { return a.len == b.len && memeq(a.ptr, b.ptr, b.len); } /* * Given a HEX encoded string (there is no leading 0x prefix, but * there may be embedded spaces), decode it into a freshly allocated * chunk. * * If this function fails, crash and burn - it is fed static data so * should never ever have a problem. * * The caller must free the chunk. */ chunk_t chunk_from_hex(const char *hex, const char *name) { /* * The decoded buffer (consiting of can't be bigger than half the encoded * string. */ chunk_t chunk = alloc_chunk((strlen(hex)+1)/2, name); chunk.len = 0; const char *pos = hex; for (;;) { /* skip leading/trailing space */ while (*pos == ' ') { pos++; } if (*pos == '\0') { break; } /* Expecting */ if (!isxdigit(pos[0]) || !isxdigit(pos[1])) { /* friendly barf for debugging */ PASSERT_FAIL("expected hex digit at offset %tu in hex buffer \"%s\" but found \"%.1s\"", pos - hex, hex, pos); } char buf[3] = { pos[0], pos[1], '\0' }; char *end; chunk.ptr[chunk.len] = strtoul(buf, &end, 16); passert(*end == '\0'); chunk.len++; pos += 2; } return chunk; } libreswan-3.32/lib/libswan/ckaid.c000066400000000000000000000070551365625662500171020ustar00rootroot00000000000000/* * mechanisms for preshared keys (public, private, and preshared secrets) * * this is the library for reading (and later, writing!) the ipsec.secrets * files. * * Copyright (C) 1998-2004 D. Hugh Redelmeier. * Copyright (C) 2005 Michael Richardson * Copyright (C) 2009-2012 Avesh Agarwal * Copyright (C) 2012-2015 Paul Wouters * Copyright (C) 2016 Andrew Cagney * Copyright (C) 2017 Vukasin Karadzic * Copyright (C) 2018 Sahana Prasad * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include "ckaid.h" #include "lswalloc.h" #include "secrets.h" #include "lswlog.h" /* * Return true IFF CKAID starts with all of START (which is in HEX). */ bool ckaid_starts_with(ckaid_t ckaid, const char *start) { if (strlen(start) > ckaid.nss->len * 2) { return false; } for (int i = 0; start[i] != '\0'; i++) { const char *p = start + i; unsigned byte = ckaid.nss->data[i / 2]; /* high or low */ unsigned nibble = (i & 1) ? (byte & 0xf) : (byte >> 4); char n[2] = { *p, }; char *end; unsigned long ni = strtoul(n, &end, 16); if (*end != '\0') { return false; } if (ni != nibble) { return false; } } return true; } char *ckaid_as_string(ckaid_t ckaid) { size_t string_len = ckaid.nss->len * 2 + 1; char *string = alloc_bytes(string_len, "ckaid-string"); datatot(ckaid.nss->data, ckaid.nss->len, 16, string, string_len); return string; } err_t form_ckaid_nss(const SECItem *const nss_ckaid, ckaid_t *ckaid) { SECItem *dup = SECITEM_DupItem(nss_ckaid); if (dup == NULL) { return "problem saving CKAID"; } ckaid->nss = dup; return NULL; } err_t form_ckaid_rsa(chunk_t modulus, ckaid_t *ckaid) { /* * Compute the CKAID directly using the modulus. - keep old * configurations hobbling along. */ SECItem nss_modulus = same_chunk_as_secitem(modulus, siBuffer); SECItem *nss_ckaid = PK11_MakeIDFromPubKey(&nss_modulus); if (nss_ckaid == NULL) { return "unable to compute 'CKAID' from modulus"; } DBG(DBG_CONTROLMORE, DBG_dump("computed rsa CKAID", nss_ckaid->data, nss_ckaid->len)); err_t err = form_ckaid_nss(nss_ckaid, ckaid); SECITEM_FreeItem(nss_ckaid, PR_TRUE); return err; } err_t form_ckaid_ecdsa(chunk_t pub_value, ckaid_t *ckaid) { /* * Compute the CKAID directly using the public value. - keep old * configurations hobbling along. */ SECItem nss_pub_value = same_chunk_as_secitem(pub_value, siBuffer); SECItem *nss_ckaid = PK11_MakeIDFromPubKey(&nss_pub_value); if (nss_ckaid == NULL) { return "unable to compute 'CKAID' from public value"; } DBG(DBG_CONTROLMORE, DBG_dump("computed ecdsa CKAID", nss_ckaid->data, nss_ckaid->len)); err_t err = form_ckaid_nss(nss_ckaid, ckaid); SECITEM_FreeItem(nss_ckaid, PR_TRUE); return err; } void freeanyckaid(ckaid_t *ckaid) { if (ckaid != NULL && ckaid->nss) { SECITEM_FreeItem(ckaid->nss, PR_TRUE); ckaid->nss = NULL; } } void DBG_log_ckaid(const char *prefix, ckaid_t ckaid) { DBG_dump(prefix, ckaid.nss->data, ckaid.nss->len); } libreswan-3.32/lib/libswan/constants.c000066400000000000000000001742131365625662500200440ustar00rootroot00000000000000/* * tables of names for values defined in constants.h * Copyright (C) 2012-2017 Paul Wouters * Copyright (C) 2012 Avesh Agarwal * Copyright (C) 1998-2002,2015 D. Hugh Redelmeier. * Copyright (C) 2016-2017 Andrew Cagney * Copyright (C) 2017 Vukasin Karadzic * Copyright (C) 2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ /* * Note that the array sizes are all specified; this is to enable range * checking by code that only includes constants.h. */ #include #include #include #include #include #include #include #include "constants.h" #include "enum_names.h" #include "lswlog.h" #include "ip_said.h" /* for SPI_PASS et.al. */ const char *bool_str(bool b) { return b ? "yes" : "no"; } /* * Jam a string into a buffer of limited size. * * This does something like what people mistakenly think strncpy does * but the parameter order is like snprintf. * OpenBSD's strlcpy serves the same purpose. * * The buffer bound (size) must be greater than 0. * That allows a guarantee that the result is NUL-terminated. * * The result is a pointer to the NUL at the end of the string in dest. * * Warning: no indication of truncation is returned. * An earlier version did indicate truncation, but that feature was never used. * This version is more robust and has a simpler contract. */ char *jam_str(char *dest, size_t size, const char *src) { passert(size > 0); /* need space for at least NUL */ { size_t full_len = strlen(src); size_t copy_len = size - 1 < full_len ? size - 1 : full_len; memcpy(dest, src, copy_len); dest[copy_len] = '\0'; return dest + copy_len; } } /* * Add a string to a partially filled buffer of limited size * * This is similar to what people mistakenly think strncat does * but add_str matches jam_str so the arguments are quite different. * OpenBSD's strlcat serves the same purpose. * * The buffer bound (size) must be greater than 0. * That allows a guarantee that the result is NUL-terminated. * * The hint argument allows code that knows the end of the * The string in dest to be more efficient. If it is unknown, * just pass a pointer to a character within the string such as * the first one. * * The result is a pointer: * if the string fits, to the NUL at the end of the string in dest; * if the string was truncated, to the roof of dest. * * The results of jam_str and add_str provide suitable values for hint * for subsequent calls. * * If the hint points at the roof of dest, add_str does nothing and * returns that as the result (thus overflow will be sticky). * * For example * (void)add_str(buf, sizeof(buf), jam_str(buf, sizeof(buf), "first"), * " second"); * That is slightly more efficient than * (void)jam_str(buf, sizeof(buf), "first"); * (void)add_str(buf, sizeof(buf), buf, " second"); * * Warning: strncat's bound is NOT on the whole buffer! * strncat(dest, src, n) adds at most n+1 bytes after the contents of dest. * Many people think that the limit is n bytes. * * Warning: Is it really wise to silently truncate? Only the caller knows. * The caller SHOULD check by seeing if the result equals dest's roof. * Overflow at any point in a chain of jam_str and add_str calls will * be reflected in the final return result so checking of intermediate * return values is not required. */ char *add_str(char *buf, size_t size, char *hint, const char *src) { passert(size > 0 && buf <= hint && hint <= buf + size); if (hint == buf + size) return hint; /* already full */ /* * skip to end of existing string (if we're not already there) */ hint += strlen(hint); passert(hint < buf + size); /* must be within buffer */ return jam_str(hint, size - (hint-buf), src); } /* version */ static const char *const version_name_1[] = { "ISAKMP Version 1.0 (rfc2407)", }; static const char *const version_name_2[] = { "IKEv2 version 2.0 (rfc4306/rfc5996)", }; static enum_names version_names_1 = { ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION, ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION, ARRAY_REF(version_name_1), NULL, /* prefix */ NULL }; enum_names version_names = { IKEv2_MAJOR_VERSION << ISA_MAJ_SHIFT | IKEv2_MINOR_VERSION, IKEv2_MAJOR_VERSION << ISA_MAJ_SHIFT | IKEv2_MINOR_VERSION, ARRAY_REF(version_name_2), NULL, /* prefix */ &version_names_1 }; /* * IKEv1 vs IKEv2 language. */ static const char *const ike_version_name[] = { "IKEv1", "IKEv2", }; enum_names ike_version_names = { IKEv1, IKEv2, ARRAY_REF(ike_version_name), "IKE", /* prefix */ NULL, }; static const char *const ike_version_liveness_name[] = { "DPD", "liveness", }; enum_names ike_version_liveness_names = { IKEv1, IKEv2, ARRAY_REF(ike_version_liveness_name), NULL, /* prefix */ NULL, }; static const char *const ike_version_child_name[] = { "IPsec", "CHILD", }; enum_names ike_version_child_names = { IKEv1, IKEv2, ARRAY_REF(ike_version_child_name), NULL, /* prefix */ NULL, }; static const char *const ike_version_ike_name[] = { "IKE", "ISAKMP", }; enum_names ike_version_ike_names = { IKEv1, IKEv2, ARRAY_REF(ike_version_ike_name), NULL, /* prefix */ NULL, }; /* Domain of Interpretation */ static const char *const doi_name[] = { "ISAKMP_DOI_ISAKMP", "ISAKMP_DOI_IPSEC", }; enum_names doi_names = { ISAKMP_DOI_ISAKMP, ISAKMP_DOI_IPSEC, ARRAY_REF(doi_name), NULL, /* prefix */ NULL }; /* kind of struct connection */ static const char *const connection_kind_name[] = { "CK_INVALID", "CK_GROUP", /* policy group: instantiates to template */ "CK_TEMPLATE", /* abstract connection, with wildcard */ "CK_PERMANENT", /* normal connection */ "CK_INSTANCE", /* instance of template */ "CK_GOING_AWAY" /* instance being deleted -- don't delete again */ }; enum_names connection_kind_names = { CK_INVALID, CK_GOING_AWAY, ARRAY_REF(connection_kind_name), NULL, /* prefix */ NULL }; /* Payload types (RFC 2408 "ISAKMP" section 3.1) */ const char *const payload_name_ikev1[] = { "ISAKMP_NEXT_NONE", "ISAKMP_NEXT_SA", /* 1 */ "ISAKMP_NEXT_P", "ISAKMP_NEXT_T", "ISAKMP_NEXT_KE", "ISAKMP_NEXT_ID", /* 5 */ "ISAKMP_NEXT_CERT", "ISAKMP_NEXT_CR", "ISAKMP_NEXT_HASH", "ISAKMP_NEXT_SIG", "ISAKMP_NEXT_NONCE", /* 10 */ "ISAKMP_NEXT_N", "ISAKMP_NEXT_D", "ISAKMP_NEXT_VID", "ISAKMP_NEXT_MODECFG", /* 14 */ "ISAKMP_NEXT_SAK", /* 15 was ISAKMP_NEXT_NATD_BADDRAFTS */ "ISAKMP_NEXT_TEK", "ISAKMP_NEXT_KD", "ISAKMP_NEXT_SEQ", "ISAKMP_NEXT_POP", "ISAKMP_NEXT_NATD_RFC", "ISAKMP_NEXT_NATOA_RFC", "ISAKMP_NEXT_GAP", NULL /* termination for bitnamesof() */ }; static const char *const payload_name_ikev1_private_use[] = { "ISAKMP_NEXT_NATD_DRAFTS", "ISAKMP_NEXT_NATOA_DRAFTS", "ISAKMP_NEXT_IKE_FRAGMENTATION", /* * proprietary Cisco/Microsoft * IKE fragmented payload */ }; static enum_names payload_names_ikev1_private_use = { ISAKMP_NEXT_NATD_DRAFTS, ISAKMP_NEXT_IKE_FRAGMENTATION, ARRAY_REF(payload_name_ikev1_private_use), NULL, /* prefix */ NULL }; enum_names ikev1_payload_names = { ISAKMP_NEXT_NONE, ISAKMP_NEXT_GAP, ARRAY_REF(payload_name_ikev1)-1, /* don't count NULL */ NULL, /* prefix */ &payload_names_ikev1_private_use }; static const char *const payload_name_ikev2[] = { "ISAKMP_NEXT_v2NONE", /* same for IKEv1 */ }; /* https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xhtml#ikev2-parameters-2 */ /* dual-use: for enum_name and for bitnamesof */ static const char *const payload_name_ikev2_main[] = { "ISAKMP_NEXT_v2SA", /* 33 */ "ISAKMP_NEXT_v2KE", "ISAKMP_NEXT_v2IDi", "ISAKMP_NEXT_v2IDr", "ISAKMP_NEXT_v2CERT", "ISAKMP_NEXT_v2CERTREQ", "ISAKMP_NEXT_v2AUTH", "ISAKMP_NEXT_v2Ni", "ISAKMP_NEXT_v2N", "ISAKMP_NEXT_v2D", "ISAKMP_NEXT_v2V", "ISAKMP_NEXT_v2TSi", "ISAKMP_NEXT_v2TSr", "ISAKMP_NEXT_v2SK", "ISAKMP_NEXT_v2CP", "ISAKMP_NEXT_v2EAP", "ISAKMP_NEXT_v2GSPM", /* RFC 6467 */ "ISAKMP_NEXT_v2IDG", /* [draft-yeung-g-ikev2] */ "ISAKMP_NEXT_v2GSA", /* [draft-yeung-g-ikev2] */ "ISAKMP_NEXT_v2KD", /* [draft-yeung-g-ikev2] */ "ISAKMP_NEXT_v2SKF", /* RFC 7383 */ NULL /* termination for bitnamesof() */ }; /* * Old IKEv1 method applied to IKEv2, different from IKEv2's RFC7383 * Can be removed */ static const char *const payload_name_ikev2_private_use[] = { "ISAKMP_NEXT_v2IKE_FRAGMENTATION", }; static enum_names payload_names_ikev2_private_use = { ISAKMP_NEXT_v2IKE_FRAGMENTATION, ISAKMP_NEXT_v2IKE_FRAGMENTATION, ARRAY_REF(payload_name_ikev2_private_use), NULL, /* prefix */ NULL }; static enum_names payload_names_ikev2_main = { ISAKMP_NEXT_v2SA, ISAKMP_NEXT_v2SKF, ARRAY_REF(payload_name_ikev2_main)-1, NULL, /* prefix */ &payload_names_ikev2_private_use }; enum_names ikev2_payload_names = { ISAKMP_NEXT_v2NONE, ISAKMP_NEXT_v2NONE, ARRAY_REF(payload_name_ikev2), "ISAKMP_NEXT_v2", /* prefix */ &payload_names_ikev2_main }; /* either V1 or V2 payload kind */ static enum_names payload_names_ikev2copy_main = { ISAKMP_NEXT_v2SA, ISAKMP_NEXT_v2SKF, ARRAY_REF(payload_name_ikev2_main)-1, NULL, /* prefix */ &payload_names_ikev1_private_use }; enum_names payload_names_ikev1orv2 = { ISAKMP_NEXT_NONE, ISAKMP_NEXT_GAP, ARRAY_REF(payload_name_ikev1)-1, NULL, /* prefix */ &payload_names_ikev2copy_main }; static enum_names *const payload_type_names_table[] = { [IKEv1 - IKEv1] = &ikev1_payload_names, [IKEv2 - IKEv1] = &ikev2_payload_names, }; enum_enum_names payload_type_names = { IKEv1, IKEv2, ARRAY_REF(payload_type_names_table) }; static const char *const ikev2_last_proposal_names[] = { "v2_PROPOSAL_LAST", NULL, "v2_PROPOSAL_NON_LAST", }; enum_names ikev2_last_proposal_desc = { v2_PROPOSAL_LAST, v2_PROPOSAL_NON_LAST, ARRAY_REF(ikev2_last_proposal_names), NULL, /* prefix */ NULL }; static const char *const ikev2_last_transform_names[] = { "v2_TRANSFORM_LAST", NULL, NULL, "v2_TRANSFORM_NON_LAST", }; enum_names ikev2_last_transform_desc = { v2_TRANSFORM_LAST, v2_TRANSFORM_NON_LAST, ARRAY_REF(ikev2_last_transform_names), NULL, /* prefix */ NULL }; /* Exchange types (note: two discontinuous ranges) */ static const char *const exchange_name_ikev1[] = { "ISAKMP_XCHG_NONE", "ISAKMP_XCHG_BASE", "ISAKMP_XCHG_IDPROT", "ISAKMP_XCHG_AO", "ISAKMP_XCHG_AGGR", "ISAKMP_XCHG_INFO", "ISAKMP_XCHG_MODE_CFG", /* 6 - draft, not RFC */ }; static const char *const exchange_name_doi[] = { /* 30 - Echo request */ "ISAKMP_XCHG_STOLEN_BY_OPENSWAN_FOR_ECHOREQUEST", "ISAKMP_XCHG_STOLEN_BY_OPENSWAN_FOR_ECHOREPLY", /* 31 - Echo reply */ "ISAKMP_XCHG_QUICK", /* 32 */ "ISAKMP_XCHG_NGRP", }; /* https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xhtml#ikev2-parameters-1 */ static const char *const exchange_name_ikev2[] = { "ISAKMP_v2_IKE_SA_INIT", /* RFC 7296 */ "ISAKMP_v2_IKE_AUTH", "ISAKMP_v2_CREATE_CHILD_SA", "ISAKMP_v2_INFORMATIONAL", "ISAKMP_v2_IKE_SESSION_RESUME", /* RFC 5753 */ #if 0 /* we don't recognize these yet */ "ISAKMP_v2_GSA_AUTH", /* draft-yeung-g-ikev2 */ "ISAKMP_v2_GSA_REGISTRATION", /* draft-yeung-g-ikev2 */ "ISAKMP_v2_GSA_REKEY", /* draft-yeung-g-ikev2 */ #endif }; static const char *const exchange_name_private_use[] = { "ISAKMP_XCHG_ECHOREQUEST_PRIVATE", /* 244 - Used by libreswan */ "ISAKMP_XCHG_ECHOREPLY_PRIVATE", /* 245 - Used by libreswan */ }; static enum_names exchange_names_private_use = { ISAKMP_XCHG_ECHOREQUEST_PRIVATE, ISAKMP_XCHG_ECHOREPLY_PRIVATE, ARRAY_REF(exchange_name_private_use), NULL, /* prefix */ NULL }; static enum_names exchange_names_doi = { ISAKMP_XCHG_STOLEN_BY_OPENSWAN_FOR_ECHOREQUEST, ISAKMP_XCHG_NGRP, ARRAY_REF(exchange_name_doi), NULL, /* prefix */ &exchange_names_private_use }; enum_names ikev1_exchange_names = { ISAKMP_XCHG_NONE, ISAKMP_XCHG_MODE_CFG, ARRAY_REF(exchange_name_ikev1), "ISAKMP_XCHG_", /* prefix */ &exchange_names_doi }; enum_names ikev2_exchange_names = { ISAKMP_v2_IKE_SA_INIT, ISAKMP_v2_IKE_SESSION_RESUME, ARRAY_REF(exchange_name_ikev2), "ISAKMP_v2_", /* prefix */ &exchange_names_private_use }; static enum_names exchange_names_doi_and_v2 = { ISAKMP_XCHG_STOLEN_BY_OPENSWAN_FOR_ECHOREQUEST, ISAKMP_XCHG_NGRP, ARRAY_REF(exchange_name_doi), NULL, /* prefix */ &ikev2_exchange_names }; enum_names exchange_names_ikev1orv2 = { ISAKMP_XCHG_NONE, ISAKMP_XCHG_MODE_CFG, ARRAY_REF(exchange_name_ikev1), NULL, /* prefix */ &exchange_names_doi_and_v2 }; static enum_names *const exchange_type_names_table[] = { [IKEv1 - IKEv1] = &ikev1_exchange_names, [IKEv2 - IKEv1] = &ikev2_exchange_names, }; enum_enum_names exchange_type_names = { IKEv1, IKEv2, ARRAY_REF(exchange_type_names_table), }; /* Flag BITS */ const char *const isakmp_flag_names[] = { "ISAKMP_FLAG_v1_ENCRYPTION", /* IKEv1 only bit 0 */ "ISAKMP_FLAG_v1_COMMIT", /* IKEv1 only bit 1 */ "ISAKMP_FLAG_v1_AUTHONLY", /* IKEv1 only bit 2 */ "ISAKMP_FLAG_v2_IKE_INIT", /* IKEv2 only bit 3 */ "ISAKMP_FLAG_v2_VERSION", /* IKEv2 only bit 4 */ "ISAKMP_FLAG_v2_MSG_RESPONSE", /* IKEv2 only bit 5 */ "ISAKMP_FLAG_MSG_RESERVED_BIT6", "ISAKMP_FLAG_MSG_RESERVED_BIT7", NULL /* termination for bitnamesof() */ }; /* Situation BITS definition for IPsec DOI */ const char *const sit_bit_names[] = { "SIT_IDENTITY_ONLY", "SIT_SECRECY", "SIT_INTEGRITY", NULL /* termination for bitnamesof() */ }; /* Protocol IDs (RFC 2407 "IPsec DOI" section 4.4.1) */ static const char *const ikev1_protocol_name[] = { "PROTO_RESERVED", "PROTO_ISAKMP", "PROTO_IPSEC_AH", "PROTO_IPSEC_ESP", "PROTO_IPCOMP", }; enum_names ikev1_protocol_names = { PROTO_RESERVED, PROTO_IPCOMP, ARRAY_REF(ikev1_protocol_name), NULL, /* prefix */ NULL }; static const char *const ikev2_protocol_name[] = { "PROTO_v2_RESERVED", "PROTO_v2_IKE", "PROTO_v2_AH", "PROTO_v2_ESP", }; enum_names ikev2_protocol_names = { PROTO_v2_RESERVED, PROTO_v2_ESP, ARRAY_REF(ikev2_protocol_name), NULL, /* prefix */ NULL }; /* subset of protocol names accepted by IKEv2 Delete */ enum_names ikev2_del_protocol_names = { PROTO_ISAKMP, PROTO_IPSEC_ESP, &ikev2_protocol_name[PROTO_ISAKMP], elemsof(ikev2_protocol_name) - PROTO_ISAKMP, NULL, /* prefix */ NULL }; /* IPsec ISAKMP transform values */ static const char *const isakmp_transform_name[] = { "KEY_IKE", }; enum_names isakmp_transformid_names = { KEY_IKE, KEY_IKE, ARRAY_REF(isakmp_transform_name), NULL, /* prefix */ NULL }; /* IPsec AH transform values */ static const char *const ah_transform_name_private_use[] = { "AH_AES_CMAC_96", "AH_NULL", /* verify with kame source? 251 */ "AH_SHA2_256_TRUNC", /* our own to signal bad truncation to kernel */ }; static enum_names ah_transformid_names_private_use = { AH_AES_CMAC_96, AH_SHA2_256_TRUNCBUG, ARRAY_REF(ah_transform_name_private_use), NULL, /* prefix */ NULL }; static const char *const ah_transform_name[] = { /* 0-1 RESERVED */ "AH_MD5", "AH_SHA", "AH_DES(UNUSED)", "AH_SHA2_256", "AH_SHA2_384", "AH_SHA2_512", "AH_RIPEMD", "AH_AES_XCBC_MAC", "AH_RSA(UNUSED)", "AH_AES_128_GMAC", /* RFC4543 Errata1821 */ "AH_AES_192_GMAC", /* RFC4543 Errata1821 */ "AH_AES_256_GMAC", /* RFC4543 Errata1821 */ /* 14-248 Unassigned */ /* 249-255 Reserved for private use */ }; enum_names ah_transformid_names = { AH_MD5, AH_AES_256_GMAC, ARRAY_REF(ah_transform_name), "AH_", /* prefix */ &ah_transformid_names_private_use }; /* * IPsec ESP transform values * * ipsec drafts suggest "high" ESP ids values for testing, * assign generic ESP_ID if not officially defined */ static const char *const esp_transform_name_private_use[] = { /* id=249 */ "ESP_MARS", "ESP_RC6(UNUSED)", "ESP_KAME_NULL", "ESP_SERPENT", "ESP_TWOFISH", "ESP_ID254(UNUSED)", "ESP_ID255(UNUSED)", }; static enum_names esp_transformid_names_private_use = { ESP_MARS, ESP_ID255, ARRAY_REF(esp_transform_name_private_use), NULL, /* prefix */ NULL }; /* This tracks the IKEv2 registry now! see ietf_constants.h */ static const char *const esp_transform_name[] = { "ESP_DES_IV64(UNUSED)", /* 1 - old DES */ "ESP_DES(UNUSED)", /* obsoleted */ "ESP_3DES", "ESP_RC5(UNUSED)", "ESP_IDEA(UNUSED)", "ESP_CAST", "ESP_BLOWFISH(UNUSED)", /* obsoleted */ "ESP_3IDEA(UNUSED)", "ESP_DES_IV32(UNUSED)", "ESP_RC4(UNUSED)", "ESP_NULL", "ESP_AES", "ESP_AES_CTR", "ESP_AES_CCM_A", "ESP_AES_CCM_B", "ESP_AES_CCM_C", "ESP_UNUSED_ID17", "ESP_AES_GCM_A", "ESP_AES_GCM_B", "ESP_AES_GCM_C", "ESP_SEED_CBC", /* IKEv2 is NULL_AUTH_AES_GMAC */ "ESP_CAMELLIA", "ESP_NULL_AUTH_AES_GMAC", /* IKEv2 is CAMELLIA_CBC */ "ESP_CAMELLIA_CTR", /* not assigned in/for IKEv1 */ "ESP_CAMELLIA_CCM_A", /* not assigned in/for IKEv1 */ "ESP_CAMELLIA_CCM_B", /* not assigned in/for IKEv1 */ "ESP_CAMELLIA_CCM_C", /* not assigned in/for IKEv1 */ /* IKEv1: 24-248 Unassigned */ /* IKEv1: 249-255 reserved for private use */ /* IKEv2: 28-1023 Unassigned */ /* IKEv2: 1024-65535 reserved for private use */ }; enum_names esp_transformid_names = { ESP_DES_IV64, ESP_CAMELLIA_CCM_16, ARRAY_REF(esp_transform_name), "ESP_", /* prefix */ &esp_transformid_names_private_use }; /* IPCOMP transform values */ static const char *const ipcomp_transform_name[] = { "IPCOMP_OUI", "IPCOMP_DEFLAT", "IPCOMP_LZS", "IPCOMP_LZJH", /* 5-47 Reserved for approved algorithms */ /* 48-63 Reserved for private use */ /* 64-255 Unassigned */ }; enum_names ipcomp_transformid_names = { IPCOMP_OUI, IPCOMP_LZJH, ARRAY_REF(ipcomp_transform_name), NULL, /* prefix */ NULL }; /* * IANA IKEv2 Hash Algorithms * https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xhtml#hash-algorithms */ static const char *const notify_hash_algo_name[] = { "IKEv2_AUTH_HASH_RESERVED", "IKEv2_AUTH_HASH_SHA1", "IKEv2_AUTH_HASH_SHA2_256", "IKEv2_AUTH_HASH_SHA2_384", "IKEv2_AUTH_HASH_SHA2_512", "IKEv2_AUTH_HASH_IDENTITY" /* 6-1023 Unassigned */ }; enum_names notify_hash_algo_names = { IKEv2_AUTH_HASH_RESERVED, IKEv2_AUTH_HASH_IDENTITY, ARRAY_REF(notify_hash_algo_name), "IKEv2_AUTH_HASH_", /* prefix */ NULL }; /* Identification type values */ static const char *const ike_idtype_name[] = { /* private to Pluto */ "%fromcert", /* -1, ID_FROMCERT:taken from certificate */ "%none", /* 0, ID_NONE */ /* standardized */ "ID_IPV4_ADDR", /* 1 */ "ID_FQDN", "ID_USER_FQDN", "ID_IPV4_ADDR_SUBNET", /* v1 only */ "ID_IPV6_ADDR", "ID_IPV6_ADDR_SUBNET", /* v1 only */ "ID_IPV4_ADDR_RANGE", /* v1 only */ "ID_IPV6_ADDR_RANGE", /* v1 only */ "ID_DER_ASN1_DN", "ID_DER_ASN1_GN", "ID_KEY_ID", "ID_FC_NAME", /* RFC 3554 */ "ID_NULL", /* draft-ietf-ipsecme-ikev2-null-auth */ }; /* * Local boilerplate macro for idtype name range initializer. * - macro is undef'ed very shortly * - not function-like since it expands to a struct initializer * - first entry in ike_idtype_name corresponds to ID_FROMCERT */ #define ID_NR(from,to,next) { \ (from), (to), \ &ike_idtype_name[(from)-ID_FROMCERT], (to)-(from) + 1, \ NULL, /* prefix */ \ next \ } /* IKEv1 */ enum_names ike_idtype_names = ID_NR(ID_IPV4_ADDR, ID_NULL, NULL); /* * all names, including private-to-pluto * Tricky: lower bound and uppers bound are treated as unsigned long * so we have to tack two ranges onto ike_idtype_names. */ enum_names ike_idtype_names_extended0 = ID_NR(ID_NONE, ID_NONE, &ike_idtype_names); enum_names ike_idtype_names_extended = ID_NR(ID_FROMCERT, ID_FROMCERT, &ike_idtype_names_extended0); /* IKEv2 names exclude ID_IPV4_ADDR_SUBNET, ID_IPV6_ADDR_SUBNET-ID_IPV6_ADDR_RANGE */ static enum_names ikev2_idtype_names_3 = ID_NR(ID_DER_ASN1_DN, ID_NULL, NULL); static enum_names ikev2_idtype_names_2 = ID_NR(ID_IPV6_ADDR, ID_IPV6_ADDR, &ikev2_idtype_names_3); enum_names ikev2_idtype_names = ID_NR(ID_IPV4_ADDR, ID_RFC822_ADDR, &ikev2_idtype_names_2); #undef ID_NR /* Certificate type values */ static const char *const ike_cert_type_name[] = { "CERT_PKCS7_WRAPPED_X509", "CERT_PGP", "CERT_DNS_SIGNED_KEY", "CERT_X509_SIGNATURE", "CERT_X509_KEY_EXCHANGE", /* v1 only */ "CERT_KERBEROS_TOKENS", "CERT_CRL", "CERT_ARL", "CERT_SPKI", "CERT_X509_ATTRIBUTE", /* IKEv2 only from here */ "CERT_RAW_RSA", "CERT_X509_CERT_URL", "CERT_X509_BUNDLE_URL", "CERT_OCSP_CONTENT", /* 14 */ "CERT_RAW_PUBLIC_KEY", /* 16 - 200 Reserved */ /* 201 - 255 Private use */ }; enum_names ike_cert_type_names = { CERT_PKCS7_WRAPPED_X509, CERT_X509_ATTRIBUTE, /* only first part of ike_cert_type_name */ ike_cert_type_name, CERT_X509_ATTRIBUTE - CERT_PKCS7_WRAPPED_X509 + 1, "CERT_", /* prefix */ NULL }; static enum_names ikev2_cert_type_names_2 = { CERT_KERBEROS_TOKENS, CERT_RAW_PUBLIC_KEY, &ike_cert_type_name[CERT_KERBEROS_TOKENS-CERT_PKCS7_WRAPPED_X509], CERT_RAW_PUBLIC_KEY-CERT_KERBEROS_TOKENS+1, "CERT_", /* prefix */ NULL }; enum_names ikev2_cert_type_names = { CERT_PKCS7_WRAPPED_X509, CERT_X509_SIGNATURE, ike_cert_type_name, CERT_X509_SIGNATURE-CERT_PKCS7_WRAPPED_X509+1, "CERT_", /* prefix */ &ikev2_cert_type_names_2 }; /* * certificate request payload policy */ static const char *const certpolicy_type_name[] = { "CERT_NEVERSEND", "CERT_SENDIFASKED", "CERT_ALWAYSSEND", }; enum_names certpolicy_type_names = { CERT_NEVERSEND, CERT_ALWAYSSEND, ARRAY_REF(certpolicy_type_name), "CERT_", /* prefix */ NULL }; /* * Oakley transform attributes * oakley_attr_bit_names does double duty: it is used for enum names * and bit names. * https://www.iana.org/assignments/ipsec-registry/ipsec-registry.xhtml#ipsec-registry-2 */ const char *const oakley_attr_bit_names[] = { "OAKLEY_ENCRYPTION_ALGORITHM", "OAKLEY_HASH_ALGORITHM", "OAKLEY_AUTHENTICATION_METHOD", "OAKLEY_GROUP_DESCRIPTION", "OAKLEY_GROUP_TYPE", "OAKLEY_GROUP_PRIME", "OAKLEY_GROUP_GENERATOR_ONE", "OAKLEY_GROUP_GENERATOR_TWO", "OAKLEY_GROUP_CURVE_A", "OAKLEY_GROUP_CURVE_B", "OAKLEY_LIFE_TYPE", "OAKLEY_LIFE_DURATION", "OAKLEY_PRF", "OAKLEY_KEY_LENGTH", "OAKLEY_FIELD_SIZE", "OAKLEY_GROUP_ORDER", NULL /* termination for bitnamesof() */ }; static const char *const oakley_var_attr_name[] = { "OAKLEY_GROUP_PRIME (variable length)", "OAKLEY_GROUP_GENERATOR_ONE (variable length)", "OAKLEY_GROUP_GENERATOR_TWO (variable length)", "OAKLEY_GROUP_CURVE_A (variable length)", "OAKLEY_GROUP_CURVE_B (variable length)", NULL, "OAKLEY_LIFE_DURATION (variable length)", NULL, NULL, NULL, "OAKLEY_GROUP_ORDER (variable length)", }; static enum_names oakley_attr_desc_tv = { OAKLEY_ENCRYPTION_ALGORITHM + ISAKMP_ATTR_AF_TV, OAKLEY_GROUP_ORDER + ISAKMP_ATTR_AF_TV, ARRAY_REF(oakley_attr_bit_names)-1, NULL, /* prefix */ NULL }; enum_names oakley_attr_names = { OAKLEY_GROUP_PRIME, OAKLEY_GROUP_ORDER, ARRAY_REF(oakley_var_attr_name), NULL, /* prefix */ &oakley_attr_desc_tv }; /* for each Oakley attribute, which enum_names describes its values? */ static enum_names oakley_prf_names; /* forward declaration */ static enum_names oakley_group_type_names; /* forward declaration */ enum_names *const oakley_attr_val_descs[] = { NULL, /* (none) */ &oakley_enc_names, /* OAKLEY_ENCRYPTION_ALGORITHM */ &oakley_hash_names, /* OAKLEY_HASH_ALGORITHM */ &oakley_auth_names, /* OAKLEY_AUTHENTICATION_METHOD */ &oakley_group_names, /* OAKLEY_GROUP_DESCRIPTION */ &oakley_group_type_names, /* OAKLEY_GROUP_TYPE */ NULL, /* OAKLEY_GROUP_PRIME */ NULL, /* OAKLEY_GROUP_GENERATOR_ONE */ NULL, /* OAKLEY_GROUP_GENERATOR_TWO */ NULL, /* OAKLEY_GROUP_CURVE_A */ NULL, /* OAKLEY_GROUP_CURVE_B */ &oakley_lifetime_names, /* OAKLEY_LIFE_TYPE */ NULL, /* OAKLEY_LIFE_DURATION */ &oakley_prf_names, /* OAKLEY_PRF */ NULL, /* OAKLEY_KEY_LENGTH */ NULL, /* OAKLEY_FIELD_SIZE */ NULL, /* OAKLEY_GROUP_ORDER */ }; const unsigned int oakley_attr_val_descs_roof = elemsof(oakley_attr_val_descs); /* IPsec DOI attributes (RFC 2407 "IPsec DOI" section 4.5) */ static const char *const ipsec_attr_name[] = { "SA_LIFE_TYPE", "SA_LIFE_DURATION", "GROUP_DESCRIPTION", "ENCAPSULATION_MODE", "AUTH_ALGORITHM", "KEY_LENGTH", "KEY_ROUNDS", "COMPRESS_DICT_SIZE", "COMPRESS_PRIVATE_ALG", #ifdef HAVE_LABELED_IPSEC "ECN_TUNNEL or old SECCTX", #endif }; /* * These are attributes with variable length values (TLV). * The ones we actually support have non-NULL entries. */ static const char *const ipsec_var_attr_name[] = { NULL, /* SA_LIFE_TYPE */ "SA_LIFE_DURATION (variable length)", NULL, /* GROUP_DESCRIPTION */ NULL, /* ENCAPSULATION_MODE */ NULL, /* AUTH_ALGORITHM */ NULL, /* KEY_LENGTH */ NULL, /* KEY_ROUNDS */ NULL, /* COMPRESS_DICT_SIZE */ "COMPRESS_PRIVATE_ALG (variable length)", #ifdef HAVE_LABELED_IPSEC "NULL", /* ECN_TUNNEL_or_old_SECCTX */ #endif }; #ifdef HAVE_LABELED_IPSEC static const char *const ipsec_private_attr_name[] = { "SECCTX" /* 32001 */ }; static enum_names ipsec_private_attr_names_tv = { SECCTX + ISAKMP_ATTR_AF_TV, SECCTX + ISAKMP_ATTR_AF_TV, ARRAY_REF(ipsec_private_attr_name), NULL, /* prefix */ NULL }; static enum_names ipsec_private_attr_names = { SECCTX, SECCTX, ARRAY_REF(ipsec_private_attr_name), NULL, /* prefix */ &ipsec_private_attr_names_tv }; #endif static enum_names ipsec_attr_desc_tv = { SA_LIFE_TYPE + ISAKMP_ATTR_AF_TV, #ifdef HAVE_LABELED_IPSEC ECN_TUNNEL_or_old_SECCTX + ISAKMP_ATTR_AF_TV, #else COMPRESS_PRIVATE_ALG + ISAKMP_ATTR_AF_TV, #endif ARRAY_REF(ipsec_attr_name), NULL, /* prefix */ #ifdef HAVE_LABELED_IPSEC &ipsec_private_attr_names #else NULL #endif }; enum_names ipsec_attr_names = { SA_LIFE_TYPE, #ifdef HAVE_LABELED_IPSEC ECN_TUNNEL_or_old_SECCTX, #else COMPRESS_PRIVATE_ALG, #endif ARRAY_REF(ipsec_var_attr_name), NULL, /* prefix */ &ipsec_attr_desc_tv }; /* for each IPsec attribute, which enum_names describes its values? */ enum_names *const ipsec_attr_val_descs[] = { NULL, /* (none) */ &sa_lifetime_names, /* SA_LIFE_TYPE */ NULL, /* SA_LIFE_DURATION */ &oakley_group_names, /* GROUP_DESCRIPTION */ &enc_mode_names, /* ENCAPSULATION_MODE */ &auth_alg_names, /* AUTH_ALGORITHM */ NULL, /* KEY_LENGTH */ NULL, /* KEY_ROUNDS */ NULL, /* COMPRESS_DICT_SIZE */ NULL, /* COMPRESS_PRIVATE_ALG */ #ifdef HAVE_LABELED_IPSEC NULL, /* ECN_TUNNEL_or_old_SECCTX */ #endif }; const unsigned int ipsec_attr_val_descs_roof = elemsof(ipsec_attr_val_descs); /* SA Lifetime Type attribute */ static const char *const sa_lifetime_name[] = { "SA_LIFE_TYPE_SECONDS", "SA_LIFE_TYPE_KBYTES", }; enum_names sa_lifetime_names = { SA_LIFE_TYPE_SECONDS, SA_LIFE_TYPE_KBYTES, ARRAY_REF(sa_lifetime_name), NULL, /* prefix */ NULL }; /* Encapsulation Mode attribute */ static const char *const enc_rfc_mode_name[] = { "ENCAPSULATION_MODE_TUNNEL", "ENCAPSULATION_MODE_TRANSPORT", "ENCAPSULATION_MODE_UDP_TUNNEL_RFC", "ENCAPSULATION_MODE_UDP_TRANSPORT_RFC", }; static const char *const enc_draft_mode_name[] = { "ENCAPSULATION_MODE_UDP_TUNNEL_DRAFTS", "ENCAPSULATION_MODE_UDP_TRANSPORT_DRAFTS", }; static enum_names enc_rfc_mode_names = { ENCAPSULATION_MODE_TUNNEL, ENCAPSULATION_MODE_UDP_TRANSPORT_RFC, ARRAY_REF(enc_rfc_mode_name), NULL, /* prefix */ NULL }; enum_names enc_mode_names = { ENCAPSULATION_MODE_UDP_TUNNEL_DRAFTS, ENCAPSULATION_MODE_UDP_TRANSPORT_DRAFTS, ARRAY_REF(enc_draft_mode_name), NULL, /* prefix */ &enc_rfc_mode_names }; /* Auth Algorithm attribute */ static const char *const auth_alg_name_stolen_use[] = { "AUTH_ALGORITHM_AES_CMAC_96", "AUTH_ALGORITHM_NULL_KAME", /* * according to our source code * comments from jjo, needs * verification */ "AUTH_ALGORITHM_HMAC_SHA2_256_TRUNCBUG", }; static enum_names auth_alg_names_stolen_use = { AUTH_ALGORITHM_AES_CMAC_96, AUTH_ALGORITHM_HMAC_SHA2_256_TRUNCBUG, ARRAY_REF(auth_alg_name_stolen_use), NULL, /* prefix */ NULL }; /* these string names map via a lookup function to configuration sttrings */ static const char *const auth_alg_name[] = { "AUTH_ALGORITHM_NONE", /* our own value, not standard */ "AUTH_ALGORITHM_HMAC_MD5", "AUTH_ALGORITHM_HMAC_SHA1", "AUTH_ALGORITHM_DES_MAC(UNUSED)", "AUTH_ALGORITHM_KPDK(UNUSED)", "AUTH_ALGORITHM_HMAC_SHA2_256", "AUTH_ALGORITHM_HMAC_SHA2_384", "AUTH_ALGORITHM_HMAC_SHA2_512", "AUTH_ALGORITHM_HMAC_RIPEMD", "AUTH_ALGORITHM_AES_XCBC", "AUTH_ALGORITHM_SIG_RSA(UNUSED)", /* RFC4359 */ "AUTH_ALGORITHM_AES_128_GMAC", /* RFC4543 [Errata1821] */ "AUTH_ALGORITHM_AES_192_GMAC", /* RFC4543 [Errata1821] */ "AUTH_ALGORITHM_AES_256_GMAC", /* RFC4543 [Errata1821] */ /* 14-61439 Unassigned */ /* 61440-65535 Reserved for private use */ }; enum_names auth_alg_names = { AUTH_ALGORITHM_NONE, AUTH_ALGORITHM_AES_256_GMAC, ARRAY_REF(auth_alg_name), "AUTH_ALGORITHM_", /* prefix */ &auth_alg_names_stolen_use }; /* * From https://tools.ietf.org/html/draft-ietf-ipsec-isakmp-xauth-06 * The draft did not make it to an RFC */ /* for XAUTH-TYPE attribute */ static const char *const xauth_type_name[] = { "Generic", "RADIUS-CHAP", "OTP", "S/KEY", }; enum_names xauth_type_names = { XAUTH_TYPE_GENERIC, XAUTH_TYPE_SKEY, ARRAY_REF(xauth_type_name), NULL, /* prefix */ NULL }; /* IKEv1 XAUTH-STATUS attribute names */ static const char *const modecfg_attr_name_draft[] = { "INTERNAL_IP4_ADDRESS", /* 1 */ "INTERNAL_IP4_NETMASK", "INTERNAL_IP4_DNS", "INTERNAL_IP4_NBNS", "INTERNAL_ADDRESS_EXPIRY", "INTERNAL_IP4_DHCP", "APPLICATION_VERSION", "INTERNAL_IP6_ADDRESS", "INTERNAL_IP6_NETMASK", "INTERNAL_IP6_DNS", "INTERNAL_IP6_NBNS", "INTERNAL_IP6_DHCP", "INTERNAL_IP4_SUBNET", /* 13 */ "SUPPORTED_ATTRIBUTES", "INTERNAL_IP6_SUBNET", "MIP6_HOME_PREFIX", "INTERNAL_IP6_LINK", "INTERNAL_IP6_PREFIX", "HOME_AGENT_ADDRESS", /* 19 */ }; #if 0 /* this is not used - which is a little strange */ static enum_names modecfg_attr_names_draft = { INTERNAL_IP4_ADDRESS, HOME_AGENT_ADDRESS, modecfg_attr_name_draft, NULL }; #endif static const char *const modecfg_cisco_attr_name[] = { "MODECFG_BANNER", /* 28672 */ "CISCO_SAVE_PW", "MODECFG_DOMAIN", "CISCO_SPLIT_DNS", "CISCO_SPLIT_INC", "CISCO_UDP_ENCAP_PORT", "CISCO_SPLIT_EXCLUDE", "CISCO_DO_PFS", "CISCO_FW_TYPE", "CISCO_BACKUP_SERVER", "CISCO_DDNS_HOSTNAME", "CISCO_UNKNOWN_SEEN_ON_IPHONE", /* 28683 */ }; static enum_names modecfg_cisco_attr_names = { MODECFG_BANNER, CISCO_UNKNOWN_SEEN_ON_IPHONE, ARRAY_REF(modecfg_cisco_attr_name), NULL, /* prefix */ NULL }; static const char *const modecfg_microsoft_attr_name[] = { "INTERNAL_IP4_SERVER", /* 23456 */ "INTERNAL_IP6_SERVER", }; static enum_names modecfg_microsoft_attr_names = { INTERNAL_IP4_SERVER, INTERNAL_IP6_SERVER, ARRAY_REF(modecfg_microsoft_attr_name), NULL, /* prefix */ &modecfg_cisco_attr_names }; enum_names modecfg_attr_names = { INTERNAL_IP4_ADDRESS, HOME_AGENT_ADDRESS, ARRAY_REF(modecfg_attr_name_draft), NULL, /* prefix */ &xauth_attr_names }; static const char *const xauth_attr_name[] = { "XAUTH-TYPE", /* 16520 */ "XAUTH-USER-NAME", "XAUTH-USER-PASSWORD", "XAUTH-PASSCODE", "XAUTH-MESSAGE", "XAUTH-CHALLENGE", "XAUTH-DOMAIN", "XAUTH-STATUS", "XAUTH-NEXT-PIN", "XAUTH-ANSWER", /* 16529 */ }; /* * Note XAUTH and MODECFG are the same xauth attribute list in the registry * but we treat these as two completely separate lists */ enum_names xauth_attr_names = { XAUTH_TYPE, XAUTH_ANSWER, ARRAY_REF(xauth_attr_name), NULL, /* prefix */ &modecfg_microsoft_attr_names }; /* Oakley Lifetime Type attribute */ static const char *const oakley_lifetime_name[] = { "OAKLEY_LIFE_SECONDS", "OAKLEY_LIFE_KILOBYTES", }; enum_names oakley_lifetime_names = { OAKLEY_LIFE_SECONDS, OAKLEY_LIFE_KILOBYTES, ARRAY_REF(oakley_lifetime_name), NULL, /* prefix */ NULL }; /* Oakley PRF attribute (none defined) */ static enum_names oakley_prf_names = { 1, 0, NULL, 0, NULL, /* prefix */ NULL }; /* * IKEv1 Oakley Encryption Algorithm attribute * www.iana.org/assignments/ipsec-registry/ipsec-registry.xhtml#ipsec-registry-4 */ static const char *const oakley_enc_name[] = { "OAKLEY_DES_CBC(UNUSED)", /* obsoleted */ "OAKLEY_IDEA_CBC(UNUSED)", "OAKLEY_BLOWFISH_CBC(UNUSED)", /* obsoleted */ "OAKLEY_RC5_R16_B64_CBC(UNUSED)", "OAKLEY_3DES_CBC", "OAKLEY_CAST_CBC", "OAKLEY_AES_CBC", "OAKLEY_CAMELLIA_CBC", /* 8 */ "UNUSED_9", "UNUSED_10", "UNUSED_11", "UNUSED_12", "OAKLEY_AES_CTR", /* stolen from IKEv2 */ "OAKLEY_AES_CCM_A", "OAKLEY_AES_CCM_B", "OAKLEY_AES_CCM_16", "UNUSED_17", "OAKLEY_AES_GCM_A", "OAKLEY_AES_GCM_B", "OAKLEY_AES_GCM_C", "UNUSED_21", "UNUSED_22", "UNUSED_23", "OAKLEY_CAMELLIA_CTR", "OAKLEY_CAMELLIA_CCM_A", "OAKLEY_CAMELLIA_CCM_B", "OAKLEY_CAMELLIA_CCM_C", /* 9-65000 Unassigned */ /* 65001-65535 Reserved for private use */ }; static const char *const oakley_enc_name_private_use[] = { "OAKLEY_MARS_CBC" /* 65001 */, "OAKLEY_RC6_CBC" /* 65002 */, "OAKLEY_ID_65003" /* 65003 */, "OAKLEY_SERPENT_CBC" /* 65004 */, "OAKLEY_TWOFISH_CBC" /* 65005 */, }; static const char *const oakley_enc_name_private_use_ssh[] = { "OAKLEY_TWOFISH_CBC_SSH", /* 65289 */ }; static enum_names oakley_enc_names_private_use_ssh = { OAKLEY_TWOFISH_CBC_SSH, OAKLEY_TWOFISH_CBC_SSH, ARRAY_REF(oakley_enc_name_private_use_ssh), NULL, /* prefix */ NULL }; static enum_names oakley_enc_names_private_use = { OAKLEY_MARS_CBC, OAKLEY_TWOFISH_CBC, ARRAY_REF(oakley_enc_name_private_use), NULL, /* prefix */ &oakley_enc_names_private_use_ssh }; enum_names oakley_enc_names = { OAKLEY_DES_CBC, OAKLEY_CAMELLIA_CCM_C, ARRAY_REF(oakley_enc_name), "OAKLEY_", /* prefix */ &oakley_enc_names_private_use }; /* * Oakley Hash Algorithm attribute * https://www.iana.org/assignments/ipsec-registry/ipsec-registry.xhtml#ipsec-registry-6 */ /* these string names map via a lookup function to configuration sttrings */ static const char *const oakley_hash_name[] = { /* 0 - RESERVED */ "OAKLEY_MD5", "OAKLEY_SHA1", "OAKLEY_TIGER(UNUSED)", "OAKLEY_SHA2_256", /* RFC 4878 */ "OAKLEY_SHA2_384", /* RFC 4878 */ "OAKLEY_SHA2_512", /* RFC 4878 */ /* 7-65000 Unassigned */ /* 65001-65535 Reserved for private use */ }; enum_names oakley_hash_names = { OAKLEY_MD5, OAKLEY_SHA2_512, ARRAY_REF(oakley_hash_name), "OAKLEY_", /* prefix */ NULL }; /* Oakley Authentication Method attribute */ static const char *const oakley_auth_name[] = { "OAKLEY_PRESHARED_KEY", "OAKLEY_DSS_SIG", "OAKLEY_RSA_SIG", "OAKLEY_RSA_ENC", "OAKLEY_RSA_REVISED_MODE", "OAKLEY_RESERVED_6", "OAKLEY_RESERVED_7", "OAKLEY_RESERVED_8", "OAKLEY_ECDSA_P256", /* RFC 4754 */ "OAKLEY_ECDSA_P384", /* RFC 4754 */ "OAKLEY_ECDSA_P521", /* RFC 4754 */ }; static const char *const oakley_auth_name_private_use2[] = { "HybridInitRSA", /* 64221 */ "HybridRespRSA", "HybridInitDSS", "HybridRespDSS", }; static const char *const oakley_auth_name_private_use[] = { "XAUTHInitPreShared", /* 65001 */ "XAUTHRespPreShared", "XAUTHInitDSS", "XAUTHRespDSS", "XAUTHInitRSA", "XAUTHRespRSA", "XAUTHInitRSAEncryption", "XAUTHRespRSAEncryption", "XAUTHInitRSARevisedEncryption", "XAUTHRespRSARevisedEncryption", /* 65010 */ }; static enum_names oakley_auth_names_private_use2 = { HybridInitRSA, HybridRespDSS, ARRAY_REF(oakley_auth_name_private_use2), NULL, /* prefix */ NULL }; static enum_names oakley_auth_names_private_use = { XAUTHInitPreShared, XAUTHRespRSARevisedEncryption, ARRAY_REF(oakley_auth_name_private_use), NULL, /* prefix */ &oakley_auth_names_private_use2 }; enum_names oakley_auth_names = { OAKLEY_PRESHARED_KEY, OAKLEY_ECDSA_P521, ARRAY_REF(oakley_auth_name), "OAKLEY_", /* prefix */ &oakley_auth_names_private_use }; /* * IKEv2 CP attribute name. Some of them are shared with XAUTH Attrib names. * https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xhtml#ikev2-parameters-21 */ static const char *const ikev2_cp_attribute_type_name[] = { "IKEv2_CP_ATTR_RESERVED", "IKEv2_INTERNAL_IP4_ADDRESS", /* 1 */ "IKEv2_INTERNAL_IP4_NETMASK", "IKEv2_INTERNAL_IP4_DNS", "IKEv2_INTERNAL_IP4_NBNS", "IKEv2_CP_ATTRIBUTE_RESERVED_5", "IKEv2_INTERNAL_IP4_DHCP", "IKEv2_APPLICATION_VERSION", "IKEv2_INTERNAL_IP6_ADDRESS", "IKEv2_CP_ATTRIBUTE_RESERVED_9", "IKEv2_INTERNAL_IP6_DNS", "IKEv2_CP_ATTRIBUTE_RESERVED_11", "IKEv2_INTERNAL_IP6_DHCP", "IKEv2_INTERNAL_IP4_SUBNET", /* 13 */ "IKEv2_SUPPORTED_ATTRIBUTES", "IKEv2_INTERNAL_IP6_SUBNET", "IKEv2_MIP6_HOME_PREFIX", "IKEv2_INTERNAL_IP6_LINK", "IKEv2_INTERNAL_IP6_PREFIX", "IKEv2_HOME_AGENT_ADDRESS", "IKEv2_P_CSCF_IP4_ADDRESS", /* 20 */ "IKEv2_P_CSCF_IP6_ADDRESS", "IKEv2_FTT_KAT", "IKEv2_EXTERNAL_SOURCE_IP4_NAT_INFO", /* 3gpp */ "IKEv2_TIMEOUT_PERIOD_FOR_LIVENESS_CHECK", /* 3gpp */ "IKEv2_INTERNAL_DNS_DOMAIN", /* draft-ietf-ipsecme-split-dns */ "IKEv2_INTERNAL_DNSSEC_TA", /* draft-ietf-ipsecme-split-dns */ }; enum_names ikev2_cp_attribute_type_names = { IKEv2_CP_ATTR_RESERVED, IKEv2_INTERNAL_DNSSEC_TA, ARRAY_REF(ikev2_cp_attribute_type_name), NULL, /* prefix */ NULL }; static const char *const ikev2_cp_type_name[] = { "IKEv2_CP_CFG_REQUEST" , /* 1 */ "IKEv2_CP_CFG_REPLY" , "IKEv2_CP_CFG_SET" , "IKEv2_CP_CFG_ACK" }; enum_names ikev2_cp_type_names = { IKEv2_CP_CFG_REQUEST, IKEv2_CP_CFG_ACK, ARRAY_REF(ikev2_cp_type_name), NULL, /* prefix */ NULL }; /* ikev2 auth methods */ static const char *const ikev2_auth_name[] = { "IKEv2_AUTH_RESERVED", /* 0 */ "IKEv2_AUTH_RSA", /* 1 */ "IKEv2_AUTH_SHARED", "IKEv2_AUTH_DSA(UNUSED)", "IKEv2_AUTH_UNUSED_4", "IKEv2_AUTH_UNUSED_5", "IKEv2_AUTH_UNUSED_6", "IKEv2_AUTH_UNUSED_7", "IKEv2_AUTH_UNUSED_8", "IKEv2_AUTH_ECDSA_P256", "IKEv2_AUTH_ECDSA_P384", "IKEv2_AUTH_ECDSA_P521", "IKEv2_AUTH_GSPM", /* 12 - RFC 6467 */ "IKEv2_AUTH_NULL", "IKEv2_AUTH_DIGSIG", /* 14 - RFC 7427 */ }; enum_names ikev2_auth_names = { IKEv2_AUTH_RESERVED, IKEv2_AUTH_DIGSIG, ARRAY_REF(ikev2_auth_name), NULL, /* prefix */ NULL }; /* * Oakley Group Description attribute * XXX: Shared for IKEv1 and IKEv2 (although technically there could * be differences we need to care about) */ /* these string names map via a lookup function to configuration sttrings */ static const char *const oakley_group_name[] = { "OAKLEY_GROUP_NONE", /* 0! RFC 7296 */ "OAKLEY_GROUP_MODP768", "OAKLEY_GROUP_MODP1024", "OAKLEY_GROUP_GP155(UNUSED)", "OAKLEY_GROUP_GP185(UNUSED)", "OAKLEY_GROUP_MODP1536", /* RFC 3526 */ "OAKLEY_GROUP_EC2N_2_1(UNUSED)", /* draft-ietf-ipsec-ike-ecc-groups */ "OAKLEY_GROUP_EC2N_2_2(UNUSED)", /* draft-ietf-ipsec-ike-ecc-groups */ "OAKLEY_GROUP_EC2N_2_3(UNUSED)", /* draft-ietf-ipsec-ike-ecc-groups */ "OAKLEY_GROUP_EC2N_2_4(UNUSED)", /* draft-ietf-ipsec-ike-ecc-groups */ "OAKLEY_GROUP_EC2N_2_5(UNUSED)", /* draft-ietf-ipsec-ike-ecc-groups */ "OAKLEY_GROUP_EC2N_2_6(UNUSED)", /* draft-ietf-ipsec-ike-ecc-groups */ "OAKLEY_GROUP_EC2N_2_7(UNUSED)", /* draft-ietf-ipsec-ike-ecc-groups */ "OAKLEY_GROUP_EC2N_2_8(UNUSED)", /* draft-ietf-ipsec-ike-ecc-groups */ "OAKLEY_GROUP_MODP2048", /* RFC 3526 */ "OAKLEY_GROUP_MODP3072", /* RFC 3526 */ "OAKLEY_GROUP_MODP4096", /* RFC 3526 */ "OAKLEY_GROUP_MODP6144", /* RFC 3526 */ "OAKLEY_GROUP_MODP8192", /* RFC 3526 */ "OAKLEY_GROUP_ECP_256", /* RFC 5903 */ "OAKLEY_GROUP_ECP_384", /* RFC 5903 */ "OAKLEY_GROUP_ECP_521", /* RFC 5903 */ "OAKLEY_GROUP_DH22", /* RFC 5114 */ "OAKLEY_GROUP_DH23", /* RFC 5114 */ "OAKLEY_GROUP_DH24", /* RFC 5114 */ "OAKLEY_GROUP_ECP_192", /* RFC 5114 */ "OAKLEY_GROUP_ECP_224", /* RFC 5114 */ "OAKLEY_GROUP_BRAINPOOL_P224R1", /* RFC 6932 */ "OAKLEY_GROUP_BRAINPOOL_P256R1", /* RFC 6932 */ "OAKLEY_GROUP_BRAINPOOL_P384R1", /* RFC 6932 */ "OAKLEY_GROUP_BRAINPOOL_P512R1", /* RFC 6932 */ "OAKLEY_GROUP_CURVE25519", /* RFC-ietf-ipsecme-safecurves-05 */ "OAKLEY_GROUP_CURVE448", /* RFC-ietf-ipsecme-safecurves-05 */ /* 33 - 32767 Unassigned */ /* 32768 - 65535 Reserved for private use */ }; enum_names oakley_group_names = { OAKLEY_GROUP_NONE, OAKLEY_GROUP_CURVE448, ARRAY_REF(oakley_group_name), "OAKLEY_GROUP_", /* prefix */ NULL }; /* Oakley Group Type attribute */ static const char *const oakley_group_type_name[] = { "OAKLEY_GROUP_TYPE_MODP", "OAKLEY_GROUP_TYPE_ECP", "OAKLEY_GROUP_TYPE_EC2N", }; static enum_names oakley_group_type_names = { OAKLEY_GROUP_TYPE_MODP, OAKLEY_GROUP_TYPE_EC2N, ARRAY_REF(oakley_group_type_name), NULL, /* prefix */ NULL }; /* Notify message type -- RFC2408 3.14.1 */ static const char *const ikev1_notify_name[] = { "INVALID_PAYLOAD_TYPE", /* 1 */ "DOI_NOT_SUPPORTED", "SITUATION_NOT_SUPPORTED", "INVALID_COOKIE", "INVALID_MAJOR_VERSION", "INVALID_MINOR_VERSION", "INVALID_EXCHANGE_TYPE", "INVALID_FLAGS", "INVALID_MESSAGE_ID", "INVALID_PROTOCOL_ID", "INVALID_SPI", "INVALID_TRANSFORM_ID", "ATTRIBUTES_NOT_SUPPORTED", "NO_PROPOSAL_CHOSEN", "BAD_PROPOSAL_SYNTAX", "PAYLOAD_MALFORMED", "INVALID_KEY_INFORMATION", "INVALID_ID_INFORMATION", "INVALID_CERT_ENCODING", "INVALID_CERTIFICATE", "CERT_TYPE_UNSUPPORTED", "INVALID_CERT_AUTHORITY", "INVALID_HASH_INFORMATION", "AUTHENTICATION_FAILED", "INVALID_SIGNATURE", "ADDRESS_NOTIFICATION", "NOTIFY_SA_LIFETIME", "CERTIFICATE_UNAVAILABLE", "UNSUPPORTED_EXCHANGE_TYPE", "UNEQUAL_PAYLOAD_LENGTHS", }; static const char *const ikev1_notify_status_name[] = { "CONNECTED", /* 16384 */ }; static const char *const ikev1_ipsec_notify_name[] = { "IPSEC_RESPONDER_LIFETIME", /* 24576 */ "IPSEC_REPLAY_STATUS", "IPSEC_INITIAL_CONTACT", }; static const char *const ikev1_notify_cisco_chatter_name[] = { "ISAKMP_N_CISCO_HELLO", /* 30000 */ "ISAKMP_N_CISCO_WWTEBR", "ISAKMP_N_CISCO_SHUT_UP", }; static const char *const ikev1_notify_ios_alives_name[] = { "ISAKMP_N_IOS_KEEP_ALIVE_REQ", /* 32768 */ "ISAKMP_N_IOS_KEEP_ALIVE_ACK", }; static const char *const ikev1_notify_dpd_name[] = { "R_U_THERE", /* 36136 */ "R_U_THERE_ACK", }; static const char *const ikev1_notify_juniper_name[] = { /* Next Hop Tunnel Binding */ "NETSCREEN_NHTB_INFORM", /* 40001 */ }; static const char *const ikev1_notify_cisco_more_name[] = { "ISAKMP_N_CISCO_LOAD_BALANCE", /* 40501 */ "ISAKMP_N_CISCO_UNKNOWN_40502", "ISAKMP_N_CISCO_PRESHARED_KEY_HASH", }; static enum_names ikev1_notify_cisco_more_names = { ISAKMP_N_CISCO_LOAD_BALANCE, ISAKMP_N_CISCO_PRESHARED_KEY_HASH, ARRAY_REF(ikev1_notify_cisco_more_name), NULL, /* prefix */ NULL }; static enum_names ikev1_notify_juniper_names = { NETSCREEN_NHTB_INFORM, NETSCREEN_NHTB_INFORM, ARRAY_REF(ikev1_notify_juniper_name), NULL, /* prefix */ &ikev1_notify_cisco_more_names }; static enum_names ikev1_notify_dpd_names = { R_U_THERE, R_U_THERE_ACK, ARRAY_REF(ikev1_notify_dpd_name), NULL, /* prefix */ &ikev1_notify_juniper_names }; static enum_names ikev1_notify_ios_alives_names = { ISAKMP_N_IOS_KEEP_ALIVE_REQ, ISAKMP_N_IOS_KEEP_ALIVE_ACK, ARRAY_REF(ikev1_notify_ios_alives_name), NULL, /* prefix */ &ikev1_notify_dpd_names }; static enum_names ikev1_notify_cisco_chatter_names = { ISAKMP_N_CISCO_HELLO, ISAKMP_N_CISCO_SHUT_UP, ARRAY_REF(ikev1_notify_cisco_chatter_name), NULL, /* prefix */ &ikev1_notify_ios_alives_names }; static enum_names ikev1_ipsec_notify_names = { IPSEC_RESPONDER_LIFETIME, IPSEC_INITIAL_CONTACT, ARRAY_REF(ikev1_ipsec_notify_name), NULL, /* prefix */ &ikev1_notify_cisco_chatter_names }; static enum_names ikev1_notify_status_names = { CONNECTED, CONNECTED, ARRAY_REF(ikev1_notify_status_name), NULL, /* prefix */ &ikev1_ipsec_notify_names }; enum_names ikev1_notify_names = { INVALID_PAYLOAD_TYPE, UNEQUAL_PAYLOAD_LENGTHS, ARRAY_REF(ikev1_notify_name), NULL, /* prefix */ &ikev1_notify_status_names }; static const char *const ikev2_notify_name_private[] = { "v2N_NULL_AUTH", /* 40960, used for mixed OE */ }; static enum_names ikev2_notify_names_private = { v2N_NULL_AUTH, v2N_NULL_AUTH, ARRAY_REF(ikev2_notify_name_private), "v2N_", /* prefix */ NULL }; /* https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xml#ikev2-parameters-13 */ static const char *const ikev2_notify_name_16384[] = { "v2N_INITIAL_CONTACT", /* 16384 */ "v2N_SET_WINDOW_SIZE", "v2N_ADDITIONAL_TS_POSSIBLE", "v2N_IPCOMP_SUPPORTED", "v2N_NAT_DETECTION_SOURCE_IP", "v2N_NAT_DETECTION_DESTINATION_IP", "v2N_COOKIE", "v2N_USE_TRANSPORT_MODE", "v2N_HTTP_CERT_LOOKUP_SUPPORTED", "v2N_REKEY_SA", "v2N_ESP_TFC_PADDING_NOT_SUPPORTED", "v2N_NON_FIRST_FRAGMENTS_ALSO", "v2N_MOBIKE_SUPPORTED", "v2N_ADDITIONAL_IP4_ADDRESS", "v2N_ADDITIONAL_IP6_ADDRESS", "v2N_NO_ADDITIONAL_ADDRESSES", "v2N_UPDATE_SA_ADDRESSES", "v2N_COOKIE2", "v2N_NO_NATS_ALLOWED", "v2N_AUTH_LIFETIME", "v2N_MULTIPLE_AUTH_SUPPORTED", "v2N_ANOTHER_AUTH_FOLLOWS", "v2N_REDIRECT_SUPPORTED", "v2N_REDIRECT", "v2N_REDIRECTED_FROM", "v2N_TICKET_LT_OPAQUE", "v2N_TICKET_REQUEST", "v2N_TICKET_ACK", "v2N_TICKET_NACK", "v2N_TICKET_OPAQUE", "v2N_LINK_ID", "v2N_USE_WESP_MODE", "v2N_ROHC_SUPPORTED", "v2N_EAP_ONLY_AUTHENTICATION", "v2N_CHILDLESS_IKEV2_SUPPORTED", "v2N_QUICK_CRASH_DETECTION", "v2N_IKEV2_MESSAGE_ID_SYNC_SUPPORTED", "v2N_IPSEC_REPLAY_COUNTER_SYNC_SUPPORTED", "v2N_IKEV2_MESSAGE_ID_SYNC", "v2N_IPSEC_REPLAY_COUNTER_SYNC", "v2N_SECURE_PASSWORD_METHODS", "v2N_PSK_PERSIST", "v2N_PSK_CONFIRM", "v2N_ERX_SUPPORTED", "v2N_IFOM_CAPABILITY", "v2N_SENDER_REQUEST_ID", "v2N_IKEV2_FRAGMENTATION_SUPPORTED", /* 16430 */ "v2N_SIGNATURE_HASH_ALGORITHMS", "v2N_CLONE_IKE_SA_SUPPORTED", "v2N_CLONE_IKE_SA", "v2N_PUZZLE", "v2N_USE_PPK", /* 16435 */ "v2N_PPK_IDENTITY", "v2N_NO_PPK_AUTH", }; static enum_names ikev2_notify_names_16384 = { v2N_INITIAL_CONTACT, v2N_NO_PPK_AUTH, ARRAY_REF(ikev2_notify_name_16384), "v2N_", /* prefix */ &ikev2_notify_names_private }; static const char *const ikev2_notify_name[] = { "v2N_RESERVED", /* unofficial "OK" */ "v2N_UNSUPPORTED_CRITICAL_PAYLOAD", "v2N_UNUSED_2", "v2N_UNUSED_3", "v2N_INVALID_IKE_SPI", "v2N_INVALID_MAJOR_VERSION", "v2N_UNUSED_6", "v2N_INVALID_SYNTAX", "v2N_UNUSED_8", "v2N_INVALID_MESSAGE_ID", "v2N_UNUSED_10", "v2N_INVALID_SPI", "v2N_UNUSED_12", "v2N_UNUSED_13", "v2N_NO_PROPOSAL_CHOSEN", "v2N_UNUSED_15", "v2N_UNUSED_16", "v2N_INVALID_KE_PAYLOAD", "v2N_UNUSED_18", "v2N_UNUSED_19", "v2N_UNUSED_20", "v2N_UNUSED_21", "v2N_UNUSED_22", "v2N_UNUSED_23", "v2N_AUTHENTICATION_FAILED", "v2N_UNUSED_25", "v2N_UNUSED_26", "v2N_UNUSED_27", "v2N_UNUSED_28", "v2N_UNUSED_29", "v2N_UNUSED_30", "v2N_UNUSED_31", "v2N_UNUSED_32", "v2N_UNUSED_33", "v2N_SINGLE_PAIR_REQUIRED", "v2N_NO_ADDITIONAL_SAS", "v2N_INTERNAL_ADDRESS_FAILURE", "v2N_FAILED_CP_REQUIRED", "v2N_TS_UNACCEPTABLE", "v2N_INVALID_SELECTORS", "v2N_UNACCEPTABLE_ADDRESSES", "v2N_UNEXPECTED_NAT_DETECTED", "v2N_USE_ASSIGNED_HoA", "v2N_TEMPORARY_FAILURE", "v2N_CHILD_SA_NOT_FOUND", "v2N_INVALID_GROUP_ID", /* 45 draft-yeung-g-ikev2 */ "v2N_AUTHORIZATION_FAILED", }; enum_names ikev2_notify_names = { v2N_NOTHING_WRONG, v2N_AUTHORIZATION_FAILED, ARRAY_REF(ikev2_notify_name), "v2N_", /* prefix */ &ikev2_notify_names_16384 }; /* https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xml#ikev2-parameters-19 */ static const char *const ikev2_ts_type_name[] = { "IKEv2_TS_IPV4_ADDR_RANGE", "IKEv2_TS_IPV6_ADDR_RANGE", "IKEv2_TS_FC_ADDR_RANGE", /* not implemented */ }; enum_names ikev2_ts_type_names = { IKEv2_TS_IPV4_ADDR_RANGE, IKEv2_TS_FC_ADDR_RANGE, ARRAY_REF(ikev2_ts_type_name), NULL, /* prefix */ NULL }; /* * MODECFG * * From draft-dukes-ike-mode-cfg */ static const char *const attr_msg_type_name[] = { "ISAKMP_CFG_REQUEST", /* 1 */ "ISAKMP_CFG_REPLY", "ISAKMP_CFG_SET", "ISAKMP_CFG_ACK", }; enum_names attr_msg_type_names = { ISAKMP_CFG_REQUEST, ISAKMP_CFG_ACK, ARRAY_REF(attr_msg_type_name), NULL, /* prefix */ NULL }; /* * IKEv2 Critical bit and RESERVED (7) bits */ const char *const critical_names[] = { "RESERVED bit 0", /* bit 0 */ "RESERVED bit 1", /* bit 1 */ "RESERVED bit 2", /* bit 2 */ "RESERVED bit 3", /* bit 3 */ "RESERVED bit 4", /* bit 4 */ "RESERVED bit 5", /* bit 5 */ "RESERVED bit 6", /* bit 6 */ "PAYLOAD_CRITICAL", /* bit 7 */ }; /* * IKEv2 Security Protocol Identifiers */ static const char *const ikev2_sec_proto_id_name[] = { /* 0 - Reserved */ "IKEv2_SEC_PROTO_IKE", "IKEv2_SEC_PROTO_AH", "IKEv2_SEC_PROTO_ESP", "IKEv2_SEC_FC_ESP_HEADER", /* RFC 4595 */ "IKEv2_SEC_FC_CT_AUTHENTICATION", /* RFC 4595 */ /* 6 - 200 Unassigned */ /* 201 - 255 Private use */ }; enum_names ikev2_sec_proto_id_names = { IKEv2_SEC_PROTO_IKE, IKEv2_SEC_FC_CT_AUTHENTICATION, ARRAY_REF(ikev2_sec_proto_id_name), "IKEv2_SEC_PROTO_", /* prefix */ NULL }; /* Transform-type Encryption */ static const char *const ikev2_trans_type_encr_name_private_use2[] = { "TWOFISH_CBC_SSH", /* 65289 */ }; static const char *const ikev2_trans_type_encr_name_private_use1[] = { "SERPENT_CBC", /* 65004 */ "TWOFISH_CBC", }; static const char *const ikev2_trans_type_encr_name[] = { "DES_IV64(UNUSED)", /* 1 */ "DES(UNUSED)", "3DES", "RC5(UNUSED)", "IDEA(UNUSED)", "CAST", "BLOWFISH(UNUSED)", "3IDEA(UNUSED)", "DES_IV32(UNUSED)", "RES10(UNUSED)", "NULL", "AES_CBC", "AES_CTR", "AES_CCM_A", /* AES-CCM_8 RFC 4309 */ "AES_CCM_B", /* AES-CCM_12 */ "AES_CCM_C", /* AES-CCM_16 */ "UNASSIGNED(UNUSED)", "AES_GCM_A", /* AES-GCM_8 RFC 4106 */ "AES_GCM_B", /* AES-GCM_12 */ "AES_GCM_C", /* AES-GCM_16 */ "NULL_AUTH_AES_GMAC", /* RFC 4543 */ "RESERVED_FOR_IEEE_P1619_XTS_AES(UNUSED)", "CAMELLIA_CBC", /* RFC 5529 */ "CAMELLIA_CTR", /* RFC 5529 */ "CAMELLIA_CCM_A", /* CAMELLIA_CCM_8 RFC 5529 */ "CAMELLIA_CCM_B", /* CAMELLIA_CCM_12 RFC 5529 */ "CAMELLIA_CCM_C", /* CAMELLIA_CCM_16 RFC 5529 */ "CHACHA20_POLY1305", /* RFC 7634 */ /* 29 - 1023 Unassigned */ /* 1024 - 65535 Private use */ }; static enum_names ikev2_trans_type_encr_names_private_use2 = { OAKLEY_TWOFISH_CBC_SSH, OAKLEY_TWOFISH_CBC_SSH, ARRAY_REF(ikev2_trans_type_encr_name_private_use2), NULL, /* prefix */ NULL }; static enum_names ikev2_trans_type_encr_names_private_use1 = { OAKLEY_SERPENT_CBC, OAKLEY_TWOFISH_CBC, ARRAY_REF(ikev2_trans_type_encr_name_private_use1), NULL, /* prefix */ &ikev2_trans_type_encr_names_private_use2 }; enum_names ikev2_trans_type_encr_names = { IKEv2_ENCR_DES_IV64, IKEv2_ENCR_CHACHA20_POLY1305, ARRAY_REF(ikev2_trans_type_encr_name), NULL, /* prefix */ &ikev2_trans_type_encr_names_private_use1 }; /* Transform-type PRF */ static const char *const ikev2_trans_type_prf_name[] = { "PRF_HMAC_MD5", "PRF_HMAC_SHA1", "PRF_HMAC_TIGER", "PRF_AES128_XCBC", /* RFC 4868 Section 4 */ "PRF_HMAC_SHA2_256", "PRF_HMAC_SHA2_384", "PRF_HMAC_SHA2_512", "PRF_AES128_CMAC" }; enum_names ikev2_trans_type_prf_names = { IKEv2_PRF_HMAC_MD5, IKEv2_PRF_AES128_CMAC, ARRAY_REF(ikev2_trans_type_prf_name), "PRF_", /* prefix */ NULL }; /* Transform-type Integrity */ static const char *const ikev2_trans_type_integ_name[] = { "AUTH_NONE", "AUTH_HMAC_MD5_96", "AUTH_HMAC_SHA1_96", "AUTH_DES_MAC(UNUSED)", "AUTH_KPDK_MD5(UNUSED)", "AUTH_AES_XCBC_96", "AUTH_HMAC_MD5_128", "AUTH_HMAC_SHA1_160", "AUTH_AES_CMAC_96", "AUTH_AES_128_GMAC", "AUTH_AES_192_GMAC", "AUTH_AES_256_GMAC", "AUTH_HMAC_SHA2_256_128", "AUTH_HMAC_SHA2_384_192", "AUTH_HMAC_SHA2_512_256", }; enum_names ikev2_trans_type_integ_names = { IKEv2_AUTH_NONE, IKEv2_AUTH_HMAC_SHA2_512_256, ARRAY_REF(ikev2_trans_type_integ_name), "AUTH_", /* prefix */ NULL }; /* Transform-type Integrity */ static const char *const ikev2_trans_type_esn_name[] = { "ESN_DISABLED", "ESN_ENABLED", }; enum_names ikev2_trans_type_esn_names = { IKEv2_ESN_DISABLED, IKEv2_ESN_ENABLED, ARRAY_REF(ikev2_trans_type_esn_name), "ESN_", /* prefix */ NULL }; /* Transform Type */ static const char *const ikev2_trans_type_name[] = { "TRANS_TYPE_ENCR", "TRANS_TYPE_PRF", "TRANS_TYPE_INTEG", "TRANS_TYPE_DH", "TRANS_TYPE_ESN" }; enum_names ikev2_trans_type_names = { IKEv2_TRANS_TYPE_ENCR, IKEv2_TRANS_TYPE_ESN, ARRAY_REF(ikev2_trans_type_name), "TRANS_TYPE_", /* prefix */ NULL }; /* for each IKEv2 transform attribute, which enum_names describes its values? */ static enum_names *const ikev2_transid_val_descs[] = { &ikev2_trans_type_encr_names, /* 1 */ &ikev2_trans_type_prf_names, /* 2 */ &ikev2_trans_type_integ_names, /* 3 */ &oakley_group_names, /* 4 */ &ikev2_trans_type_esn_names, /* 5 */ }; enum_enum_names v2_transform_ID_enums = { IKEv2_TRANS_TYPE_ENCR, IKEv2_TRANS_TYPE_ESN, ARRAY_REF(ikev2_transid_val_descs) }; /* Transform Attributes */ static const char *const ikev2_trans_attr_name[] = { "IKEv2_KEY_LENGTH", }; enum_names ikev2_trans_attr_descs = { IKEv2_KEY_LENGTH + ISAKMP_ATTR_AF_TV, IKEv2_KEY_LENGTH + ISAKMP_ATTR_AF_TV, ARRAY_REF(ikev2_trans_attr_name), NULL, /* prefix */ NULL }; static const char *const pkk_name[] = { "PKK_PSK", "PKK_RSA", "PKK_XAUTH", "PKK_PPK", "PKK_ECDSA", "PKK_NULL", "PKK_INVALID", }; enum_names pkk_names = { PKK_PSK, PKK_INVALID, ARRAY_REF(pkk_name), NULL, /* prefix */ NULL }; /* * IKEv2 PPK ID types - draft-ietf-ipsecme-qr-ikev2-01 */ static const char *const ikev2_ppk_id_type_name[] = { /* 0 - Reserved */ "PPK_ID_OPAQUE", "PPK_ID_FIXED", /* 3 - 127 Unassigned */ /* 128 - 255 Private Use */ }; enum_names ikev2_ppk_id_type_names = { PPK_ID_OPAQUE, PPK_ID_FIXED, ARRAY_REF(ikev2_ppk_id_type_name), "PPK_ID_", /* prefix */ NULL }; /* IKEv2 Redirect Mechanism - RFC 5685 */ static const char *const ikev2_redirect_gw_name[] = { /* 0 - Reserved */ "GW_IPv4", "GW_IPv6", "GW_FQDN", /* 4 - 240 Unassigned */ /* 241 - 255 Private Use */ }; enum_names ikev2_redirect_gw_names = { GW_IPV4, GW_FQDN, ARRAY_REF(ikev2_redirect_gw_name), "GW_", /* prefix */ NULL }; /* magic SPI values (specific to Libreswan: see ) */ static const char *const spi_name[] = { "%pass", "%drop", "%reject", "%hold", "%trap", "%trapsubnet", }; enum_names spi_names = { SPI_PASS, SPI_TRAPSUBNET, ARRAY_REF(spi_name), "%", /* prefix */ NULL }; /* * Iterate over the enum_names returning all the valid indexes. * * Use -1 as the starting point / sentinel. * * XXX: Works fine provided we ignore the enum_names object that * contains negative values stored in unsigned fields! */ long next_enum(enum_names *en, long l) { enum_names *p = en; unsigned long e; if (l < 0) { e = en->en_first; if (en->en_names[e - p->en_first] != NULL) { return e; } } else { e = l; } while (true) { while (true) { if (p == NULL) { return -1; } passert(p->en_last - p->en_first + 1 == p->en_checklen); if (p->en_first <= e && e < p->en_last) { e++; break; } else if (e == p->en_last && p->en_next_range != NULL) { p = p->en_next_range; e = p->en_first; break; } else { p = p->en_next_range; } } if (p->en_names[e - p->en_first] != NULL) { return e; } } } /* look up enum names in an enum_names */ const char *enum_name(enum_names *ed, unsigned long val) { enum_names *p; for (p = ed; p != NULL; p = p->en_next_range) { passert(p->en_last - p->en_first + 1 == p->en_checklen); if (p->en_first <= val && val <= p->en_last) return p->en_names[val - p->en_first]; } return NULL; } const char *enum_short_name(enum_names *ed, unsigned long val) { const char *p = enum_name(ed, val); return p == NULL || ed->en_prefix == NULL ? p : strip_prefix(p, ed->en_prefix); } size_t lswlog_enum(struct lswlog *buf, enum_names *en, unsigned long val) { const char *name = enum_name(en, val); if (name == NULL) { if (en->en_prefix != NULL) { lswlogs(buf, en->en_prefix); lswlogs(buf, "_"); } return lswlogf(buf, "%lu??", val); } return lswlogs(buf, name); } size_t lswlog_enum_short(struct lswlog *buf, enum_names *en, unsigned long val) { const char *name = enum_short_name(en, val); if (name == NULL) { if (en->en_prefix != NULL) { lswlogs(buf, en->en_prefix); lswlogs(buf, "_"); } return lswlogf(buf, "%lu??", val); } return lswlogs(buf, name); } /* * find or construct a string to describe an enum value * * Note: result may or may not be in b. */ const char *enum_showb(enum_names *ed, unsigned long val, struct esb_buf *b) { const char *p = enum_name(ed, val); if (p == NULL) { snprintf(b->buf, sizeof(b->buf), "%lu??", val); p = b->buf; } return p; } const char *enum_show_shortb(enum_names *ed, unsigned long val, struct esb_buf *b) { const char *p = enum_showb(ed, val, b); return ed->en_prefix == NULL ? p : strip_prefix(p, ed->en_prefix); } /* * find or construct a string to describe an enum value * Result may be in STATIC buffer -- NOT RE-ENTRANT! * * One consequence is that you cannot have two or more calls * as arguments in a single logging call. Use enum_name instead. * (Of course that means that unnamed values will be shown * badly.) */ const char *enum_show(enum_names *ed, unsigned long val) { static struct esb_buf buf; /* only one! NON-RE-ENTRANT */ return enum_showb(ed, val, &buf); } /* sometimes the prefix gets annoying */ const char *strip_prefix(const char *s, const char *prefix) { size_t pl = strlen(prefix); return strneq(s, prefix, pl) ? s + pl : s; } /* * Find the value for a name in an enum_names table. If not found, returns -1. * * Strings are compared without regard to case. * * ??? the table contains unsigned long values BUT the function returns an * int so there is some potential for overflow. */ int enum_search(enum_names *ed, const char *str) { for (enum_names *p = ed; p != NULL; p = p->en_next_range) { passert(p->en_last - p->en_first + 1 == p->en_checklen); for (unsigned long en = p->en_first; en <= p->en_last; en++) { const char *ptr = p->en_names[en - p->en_first]; if (ptr != NULL && strcaseeq(ptr, str)) { passert(en <= INT_MAX); return en; } } } return -1; } int enum_match(enum_names *ed, shunk_t string) { for (enum_names *p = ed; p != NULL; p = p->en_next_range) { passert(p->en_last - p->en_first + 1 == p->en_checklen); for (unsigned long en = p->en_first; en <= p->en_last; en++) { const char *name = p->en_names[en - p->en_first]; if (name == NULL) { continue; } passert(en <= INT_MAX); /* * try matching all four variants of name: * with and without prefix en->en_prefix and * with and without suffix '(...)' */ size_t name_len = strlen(name); /* pl: prefix length */ size_t pl = ed->en_prefix == NULL ? 0 : strip_prefix(name, ed->en_prefix) - name; /* suffix must not and will not overlap prefix */ const char *suffix = strchr(name + pl, '('); /* sl: suffix length */ size_t sl = suffix != NULL && name[name_len - 1] == ')' ? &name[name_len] - suffix : 0; # define try(guard, f, b) ( \ (guard) && \ name_len - ((f) + (b)) == string.len && \ strncaseeq(name + (f), string.ptr, string.len)) if (try(true, 0, 0) || try(sl > 0, 0, sl) || try(pl > 0, pl, 0) || try(pl > 0 && sl > 0, pl, sl)) { return en; } # undef try } } return -1; } /* choose table from struct enum_enum_names */ enum_names *enum_enum_table(enum_enum_names *een, unsigned long table) { passert(een->een_last - een->een_first + 1 == een->een_checklen); if (een->een_first <= table && table <= een->een_last) { return een->een_enum_name[table - een->een_first]; } else { return NULL; } } const char *enum_enum_name(enum_enum_names *een, unsigned long table, unsigned long val) { enum_names *en = enum_enum_table(een, table); return en == NULL ? NULL : enum_name(en, val); } const char *enum_enum_showb(enum_enum_names *een, unsigned long table, unsigned long val, struct esb_buf *b) { const char *name = enum_enum_name(een, table, val); if (name != NULL) { return name; } snprintf(b->buf, sizeof(b->buf), "%lu??", val); return b->buf; } size_t lswlog_enum_enum(struct lswlog *buf, enum_enum_names *een, unsigned long table, unsigned long val) { enum_names *en = enum_enum_table(een, table); if (en == NULL) { /* XXX: dump something more meaningful */ return lswlogf(buf, "%lu??%lu??", table, val); } return lswlog_enum(buf, en, val); } size_t lswlog_enum_enum_short(struct lswlog *buf, enum_enum_names *een, unsigned long table, unsigned long val) { enum_names *en = enum_enum_table(een, table); if (en == NULL) { /* XXX: dump something more meaningful */ return lswlogf(buf, "%lu??%lu??", table, val); } return lswlog_enum_short(buf, en, val); } const char sparse_end[] = "end of sparse names"; /* look up enum names in a sparse_names */ const char *sparse_name(sparse_names sd, unsigned long val) { const struct sparse_name *p; for (p = sd; p->name != sparse_end; p++) if (p->val == val) return p->name; return NULL; } /* * find or construct a string to describe an sparse value * * Result may be in STATIC buffer -- NOT RE-ENTRANT! */ const char *sparse_val_show(sparse_names sd, unsigned long val) { const char *p = sparse_name(sd, val); if (p == NULL) { static struct esb_buf b; /* STATIC!! */ snprintf(b.buf, sizeof(b.buf), "%lu??", val); p = b.buf; } return p; } /* registry of enum_names: allows consistency checking at startup */ static const enum_names *en_checklist[] = { &version_names, &doi_names, &connection_kind_names, &ikev1_payload_names, &ikev2_payload_names, &payload_names_ikev1orv2, &ikev2_last_proposal_desc, &ikev1_exchange_names, &exchange_names_ikev1orv2, &ikev1_protocol_names, &ikev2_protocol_names, &ikev2_del_protocol_names, &isakmp_transformid_names, &ah_transformid_names, &esp_transformid_names, &ipcomp_transformid_names, &ike_idtype_names, &ikev2_idtype_names, &ike_cert_type_names, &ikev2_cert_type_names, &certpolicy_type_names, &oakley_attr_names, &ipsec_attr_names, &sa_lifetime_names, &enc_mode_names, &auth_alg_names, &xauth_type_names, &modecfg_attr_names, &oakley_lifetime_names, &oakley_prf_names, &oakley_enc_names, &oakley_hash_names, &oakley_auth_names, &ikev2_cp_attribute_type_names, &ikev2_cp_type_names, &ikev2_auth_names, &oakley_group_names, &oakley_group_type_names, &ikev1_notify_names, &ikev2_notify_names, &ikev2_ts_type_names, &attr_msg_type_names, &ikev2_sec_proto_id_names, &ikev2_trans_type_encr_names, &ikev2_trans_type_prf_names, &ikev2_trans_type_integ_names, &ikev2_trans_type_esn_names, &ikev2_trans_type_names, &ikev2_trans_attr_descs, &pkk_names, &ikev2_ppk_id_type_names, &ikev2_redirect_gw_names, }; void check_enum_names(enum_names *checklist[], size_t tl) { /* check that enum_names are well-formed */ size_t i; for (i = 0; i != tl; i++) { /* * enum_name will check all linked enum_names * if given a value that isn't covered. * -42 is probably not covered. */ (void) enum_name(checklist[i], -42UL); } } void init_constants(void) { check_enum_names(ARRAY_REF(en_checklist)); /* check v2_transform_ID_enums, the only enum_enum_names */ (void) enum_enum_table(&v2_transform_ID_enums, -42UL); } libreswan-3.32/lib/libswan/crypt_mac.c000066400000000000000000000013201365625662500177750ustar00rootroot00000000000000/* mac result from PRF and HASH functions, for libreswan * * Copyright (C) 2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include "crypt_mac.h" const struct crypt_mac empty_mac; /* zero */ libreswan-3.32/lib/libswan/datatot.c000066400000000000000000000122741365625662500174660ustar00rootroot00000000000000/* * convert from binary data (e.g. key) to text form * Copyright (C) 2000 Henry Spencer. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. */ #include #include "libreswan/passert.h" #include "libreswan.h" static void convert(const char *src, size_t nreal, int format, char *out); /* - datatot - convert data bytes to text */ size_t /* true length (with NUL) for success */ datatot(src, srclen, format, dst, dstlen) const unsigned char *src; size_t srclen; int format; /* character indicating what format */ char *dst; /* need not be valid if dstlen is 0 */ size_t dstlen; { size_t inblocksize; /* process this many bytes at a time */ size_t outblocksize; /* producing this many */ size_t breakevery; /* add a _ every this many (0 means don't) */ size_t sincebreak; /* output bytes since last _ */ char breakchar; /* character used to break between groups */ unsigned char inblock[10]; /* enough for any format */ char outblock[10]; /* enough for any format */ char fake[1]; /* fake output area for dstlen == 0 */ size_t needed; /* return value */ char *stop; /* where the terminating NUL will go */ size_t ntodo; /* remaining input */ size_t nreal; char *out; char *prefix; breakevery = 0; breakchar = '_'; switch (format) { case 0: case 'h': format = 'x'; breakevery = 8; /* FALLTHROUGH */ case 'x': inblocksize = 1; outblocksize = 2; prefix = "0x"; break; case ':': breakevery = 2; breakchar = ':'; /* FALLTHROUGH */ case 16: inblocksize = 1; outblocksize = 2; prefix = ""; format = 'x'; break; case 's': inblocksize = 3; outblocksize = 4; prefix = "0s"; break; case 64: /* beware, equals ' ' */ inblocksize = 3; outblocksize = 4; prefix = ""; format = 's'; break; default: return 0; break; } passert(inblocksize < sizeof(inblock)); passert(outblocksize < sizeof(outblock)); passert(breakevery % outblocksize == 0); if (srclen == 0) return 0; ntodo = srclen; if (dstlen == 0) { /* dispose of awkward special case */ dst = fake; dstlen = 1; } stop = dst + dstlen - 1; nreal = strlen(prefix); needed = nreal; /* for starters */ if (dstlen <= nreal) { /* prefix won't fit */ /* fill_and_terminate */ strncpy(dst, prefix, dstlen-1); dst[dstlen-1] = '\0'; dst += dstlen - 1; } else { strcpy(dst, prefix); dst += nreal; } passert(dst <= stop); sincebreak = 0; while (ntodo > 0) { if (ntodo < inblocksize) { /* incomplete input */ memset(inblock, 0, sizeof(inblock)); memcpy(inblock, src, ntodo); src = inblock; nreal = ntodo; ntodo = inblocksize; } else { nreal = inblocksize; } out = ((ptrdiff_t)outblocksize > stop - dst) ? outblock : dst; convert((const char *)src, nreal, format, out); needed += outblocksize; sincebreak += outblocksize; if (dst < stop) { if (out != dst) { passert( (ptrdiff_t)outblocksize > stop - dst); memcpy(dst, out, stop - dst); dst = stop; } else { dst += outblocksize; } } src += inblocksize; ntodo -= inblocksize; if (breakevery != 0 && sincebreak >= breakevery && ntodo > 0) { if (dst < stop) *dst++ = breakchar; needed++; sincebreak = 0; } } passert(dst <= stop); *dst++ = '\0'; needed++; return needed; } /* - convert - convert one input block to one output block */ static void convert(src, nreal, format, out) const char *src; size_t nreal; /* how much of the input block is real */ int format; char *out; { static char hex[] = "0123456789abcdef"; static char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; unsigned char c; unsigned char c1, c2, c3; passert(nreal > 0); switch (format) { case 'x': passert(nreal == 1); c = (unsigned char)*src; *out++ = hex[c >> 4]; *out++ = hex[c & 0xf]; break; case 's': c1 = (unsigned char)*src++; c2 = (unsigned char)*src++; c3 = (unsigned char)*src++; *out++ = base64[c1 >> 2]; /* top 6 bits of c1 */ c = (c1 & 0x3) << 4; /* bottom 2 of c1... */ c |= c2 >> 4; /* ...top 4 of c2 */ *out++ = base64[c]; if (nreal == 1) { *out++ = '='; } else { c = (c2 & 0xf) << 2; /* bottom 4 of c2... */ c |= c3 >> 6; /* ...top 2 of c3 */ *out++ = base64[c]; } if (nreal <= 2) *out++ = '='; else *out++ = base64[c3 & 0x3f]; /* bottom 6 of c3 */ break; default: passert(nreal == 0); /* unknown format */ break; } } libreswan-3.32/lib/libswan/debug.c000066400000000000000000000055061365625662500171140ustar00rootroot00000000000000/* debug set constants, for libreswan * * Copyright (C) 2017-2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include "constants.h" #include "enum_names.h" #include "lmod.h" #include "lswcdefs.h" /* for ARRAY_REF() */ /* * Initialize both the .name and .help arrays. * * See plutomain.c why the name has an extra "\0" appended (hint it is * a hack for encoding what to do with flags). * * XXX: since only the --debug ... form is supported, has this all * become redundant. * * So that grepping for DBG. finds this file, the N parameter is * the full enum name (DBG_...) and not just the truncated suffix. */ struct double_double { const char *name[DBG_roof_IX - DBG_floor_IX]; const char *help[DBG_roof_IX - DBG_floor_IX]; }; static struct double_double debug = { #define D(N,A,H) \ .name[N##_IX - DBG_floor_IX] = A "\0", \ .help[N##_IX - DBG_floor_IX] = H D(DBG_BASE, "debug-base", "enable detailed debug logging"), D(DBG_CPU_USAGE, "debug-cpu-usage", "estimate cpu used"), D(DBG_CRYPT, "debug-crypt", "encryption/decryption of messages: DANGER!"), D(DBG_PRIVATE, "debug-private", "displays private information: DANGER!"), D(DBG_WHACKWATCH, "debug-whackwatch", "never let WHACK go"), D(DBG_ADD_PREFIX, "debug-add-prefix", "add the log+state prefix to debug lines"), D(DBG_TMI, "debug-tmi", "far too much information"), #undef D }; const enum_names debug_names = { DBG_floor_IX, DBG_roof_IX - 1, ARRAY_REF(debug.name), "debug-", NULL, }; struct lmod_compat debug_compat[] = { { "klips", DBG_KERNEL }, { "netkey", DBG_KERNEL }, { "control", DBG_BASE, }, { "controlmore", DBG_BASE, }, { "dns", DBG_BASE, }, { "dpd", DBG_BASE, }, { "emitting", DBG_BASE, }, { "kernel", DBG_BASE, }, { "lifecycle", DBG_BASE, }, { "nattraversal", DBG_BASE, }, { "oppo", DBG_BASE, }, { "oppoinfo", DBG_BASE, }, { "parsing", DBG_BASE, }, { "proposal-parser", DBG_BASE, }, { "raw", DBG_BASE, }, { "retransmits", DBG_BASE, }, { "x509", DBG_BASE, }, { "xauth", DBG_BASE, }, { "crypt-low", DBG_CRYPT, }, { NULL, LEMPTY, }, }; const struct lmod_info debug_lmod_info = { .names = &debug_names, .all = DBG_ALL, .mask = DBG_MASK, .compat = debug_compat, }; const struct enum_names debug_help = { DBG_floor_IX, DBG_roof_IX - 1, ARRAY_REF(debug.help), NULL, NULL, }; libreswan-3.32/lib/libswan/deltatime.c000066400000000000000000000073671365625662500200050ustar00rootroot00000000000000/* time objects and functions, for libreswan * * Copyright (C) 1998, 1999, 2000 Henry Spencer. * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs * Copyright (C) 2019 Andrew Cagney * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. * */ #include /* for imaxabs() */ #include "deltatime.h" #include "lswlog.h" static const deltatime_t deltatime_zero; /* * Rather than deal with the 'bias' in a -ve timeval, this code * convers everything into +ve timevals. */ static deltatime_t negate_deltatime(deltatime_t d) { deltatime_t res; timersub(&deltatime_zero.dt, &d.dt, &res.dt); return res; } deltatime_t deltatime(time_t secs) { return (deltatime_t) DELTATIME_INIT(secs); } deltatime_t deltatime_ms(intmax_t ms) { /* * C99 defines '%' thus: * * [...] the result of the % operator is the remainder. [...] * If the quotient a/b is representable, the expression (a/b)*b * + a%b shall equal a. */ intmax_t ams = imaxabs(ms); deltatime_t res = { .dt = { .tv_sec = ams / 1000, .tv_usec = ams % 1000 * 1000, }, }; if (ms < 0) { res = negate_deltatime(res); } return res; } deltatime_t deltatime_timevals_diff(struct timeval a, struct timeval b) { deltatime_t res; timersub(&a, &b, &res.dt); return res; } int deltatime_cmp(deltatime_t a, deltatime_t b) { /* sign(l - r) */ if (timercmp(&a.dt, &b.dt, <)) { return -1; } else if (timercmp(&a.dt, &b.dt, >)) { return 1; } else { return 0; } } deltatime_t deltatime_max(deltatime_t a, deltatime_t b) { if (timercmp(&a.dt, &b.dt, >)) { return a; } else { return b; } } deltatime_t deltatime_add(deltatime_t a, deltatime_t b) { deltatime_t res; timeradd(&a.dt, &b.dt, &res.dt); return res; } deltatime_t deltatime_mulu(deltatime_t a, unsigned scalar) { return deltatime_ms(deltamillisecs(a) * scalar); } deltatime_t deltatime_divu(deltatime_t a, unsigned scalar) { return deltatime_ms(deltamillisecs(a) / scalar); } intmax_t deltamillisecs(deltatime_t d) { return ((intmax_t) d.dt.tv_sec) * 1000 + d.dt.tv_usec / 1000; } intmax_t deltasecs(deltatime_t d) { /* XXX: ignore .tv_usec's bias, don't round */ return d.dt.tv_sec; } deltatime_t deltatimescale(int num, int denom, deltatime_t d) { /* ??? should check for overflow */ return deltatime(deltasecs(d) * num / denom); } bool deltaless(deltatime_t a, deltatime_t b) { return timercmp(&a.dt, &b.dt, <); } bool deltaless_tv_dt(const struct timeval a, const deltatime_t b) { return timercmp(&a, &b.dt, <); } struct timeval deltatimeval(deltatime_t d) { return d.dt; } /* * Try to be smart by only printing the precision necessary. For * instance 1, 0.5, ... */ static size_t frac(struct lswlog *buf, intmax_t usec) { int precision = 6; while (usec % 10 == 0 && precision > 1) { precision--; usec = usec / 10; } return lswlogf(buf, ".%0*jd", precision, usec); } size_t jam_deltatime(jambuf_t *buf, deltatime_t d) { size_t s = 0; if (d.dt.tv_sec < 0) { s += lswlogf(buf, "-"); d = negate_deltatime(d); } s += lswlogf(buf, "%jd", (intmax_t)d.dt.tv_sec); if (d.dt.tv_usec != 0) { frac(buf, d.dt.tv_usec); } return s; } const char *str_deltatime(deltatime_t d, deltatime_buf *out) { jambuf_t buf = ARRAY_AS_JAMBUF(out->buf); lswlog_deltatime(&buf, d); return out->buf; } libreswan-3.32/lib/libswan/diag.c000066400000000000000000000034471365625662500167340ustar00rootroot00000000000000/* * Diagnostic builder * Copyright (C) 1998-2003 D. Hugh Redelmeier * Copyright (C) 2004 Michael Richardson * * alg_info.c,v 1.1.2.1 2003/11/21 18:12:23 jjo Exp * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include #include "constants.h" #include "lswlog.h" /* * Build up a diagnostic in a static buffer -- NOT RE-ENTRANT. * * Although this would be a generally useful function, it is very * hard to come up with a discipline that prevents different uses * from interfering. It is intended that by limiting it to building * diagnostics, we will avoid this problem. * Juggling is performed to allow an argument to be a previous * result: the new string may safely depend on the old one. This * restriction is not checked in any way: violators will produce * confusing results (without crashing!). * * @param fmt String format * @param ... strings * @return err_t */ err_t builddiag(const char *fmt, ...) { /* longer messages will be truncated */ static char mydiag_space[LOG_WIDTH]; char t[sizeof(mydiag_space)]; /* build result here first */ va_list args; va_start(args, fmt); t[0] = '\0'; /* in case nothing terminates string */ vsnprintf(t, sizeof(t), fmt, args); va_end(args); strcpy(mydiag_space, t); return mydiag_space; } libreswan-3.32/lib/libswan/esp_info.c000066400000000000000000000063751365625662500176350ustar00rootroot00000000000000/* ESP parsing and creation functions, for libreswan * * Author: JuanJo Ciarlante * * Copyright (C) 2012 Paul Wouters * Copyright (C) 2015-2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include #include #include "lswalloc.h" #include "lswlog.h" #include "proposals.h" #include "alg_byname.h" #include "lswfips.h" #include "ike_alg.h" #include "ike_alg_encrypt.h" #include "ike_alg_integ.h" /* * Add ESP alg info _with_ logic (policy): */ static bool esp_proposal_ok(struct proposal_parser *parser, const struct proposal *proposal) { if (!proposal_aead_none_ok(parser, proposal)) { if (!impair_proposal_errors(parser)) { return false; } } impaired_passert(PROPOSAL_PARSER, next_algorithm(proposal, PROPOSAL_encrypt, NULL) != NULL); impaired_passert(PROPOSAL_PARSER, next_algorithm(proposal, PROPOSAL_prf, NULL) == NULL); impaired_passert(PROPOSAL_PARSER, next_algorithm(proposal, PROPOSAL_integ, NULL) != NULL); return true; } /* * IKEv1: * * since esp= must have an encryption algorithm this is normally * ignored. */ static const char default_v1_esp_proposals[] = "AES_CBC" /*????*/ ; static const struct ike_alg *default_v1_esp_integ[] = { #ifdef USE_SHA1 &ike_alg_integ_sha1.common, #endif NULL, }; static const struct proposal_defaults v1_esp_defaults = { .proposals = default_v1_esp_proposals, .integ = default_v1_esp_integ, }; /* * IKEv2: */ static const char default_v2_esp_proposals[] = "AES_GCM_16_256" "," "AES_GCM_16_128" "," "AES_CBC_256" "," "AES_CBC_128" ; static const struct ike_alg *default_v2_esp_integ[] = { #ifdef USE_SHA2 &ike_alg_integ_sha2_512.common, &ike_alg_integ_sha2_256.common, #endif NULL, }; static const struct proposal_defaults v2_esp_defaults = { .proposals = default_v2_esp_proposals, .integ = default_v2_esp_integ, }; /* * All together now ... */ static const struct proposal_protocol esp_proposal_protocol = { .name = "ESP", .ikev1_alg_id = IKEv1_ESP_ID, .defaults = { [IKEv1] = &v1_esp_defaults, [IKEv2] = &v2_esp_defaults, }, .proposal_ok = esp_proposal_ok, .encrypt = true, .integ = true, .dh = true, }; /* * ??? the only difference between * alg_info_ah_create_from_str and esp_proposals_create_from_str * is in the second argument to proposal_parser. * * XXX: On the other hand, since "struct ike_info" and "struct * esp_info" are effectively the same, they can be merged. Doing * that, would eliminate the AH using ESP confusion. */ /* This function is tested in testing/algparse/algparse.c */ struct proposal_parser *esp_proposal_parser(const struct proposal_policy *policy) { return alloc_proposal_parser(policy, &esp_proposal_protocol); } libreswan-3.32/lib/libswan/fd.c000066400000000000000000000073421365625662500164170ustar00rootroot00000000000000/* file descriptors, for libreswan * * Copyright (C) 2018 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include /* for close() */ #include #include #include #include #include #include "fd.h" #include "lswalloc.h" #include "refcnt.h" struct fd { #define FD_MAGIC 0xf00d1e unsigned magic; int fd; refcnt_t refcnt; }; struct fd *dup_any_fd(struct fd *fd, where_t where) { pexpect(fd == NULL || fd->magic == FD_MAGIC); ref_add(fd, where); return fd; } static void free_fd(struct fd **fdp, where_t where) { struct fd *fd = *fdp; *fdp = NULL; pexpect(fd->magic == FD_MAGIC); if (close(fd->fd) != 0) { dbg("freeref "PRI_FD" close(%d) failed: "PRI_ERRNO" "PRI_WHERE"", pri_fd(fd), fd->fd, pri_errno(errno), pri_where(where)); } else { dbg("freeref "PRI_FD" "PRI_WHERE"", pri_fd(fd), pri_where(where)); } fd->magic = ~FD_MAGIC; pfree(fd); } void close_any_fd(struct fd **fdp, where_t where) { ref_delete(fdp, free_fd, where); } void fd_leak(struct fd **fdp, where_t where) { dbg("leaking "PRI_FD"'s FD; will be closed when pluto exits "PRI_WHERE"", pri_fd(*fdp), pri_where(where)); /* leave the old fd hanging */ (*fdp)->fd = dup((*fdp)->fd); ref_delete(fdp, free_fd, where); } ssize_t fd_sendmsg(struct fd *fd, const struct msghdr *msg, int flags, where_t where) { if (fd == NULL) { /* * XXX: passert() / pexpect() / ... would be recursive * - they write to whack using fd_sendsmg(), fake it. */ LSWBUF(buf) { jam(buf, "EXPECTATION FAILED: fd is NULL "PRI_WHERE"", pri_where(where)); log_jambuf(LOG_STREAM, null_fd, buf); } return -1; } if (fd->magic != FD_MAGIC) { /* * XXX: passert() / pexpect() / ... would be recursive * - they write to whack using fd_sendmsg(), fake it. */ LSWBUF(buf) { jam(buf, "EXPECTATION FAILED: fd is not magic "PRI_WHERE"", pri_where(where)); log_jambuf(LOG_STREAM, null_fd, buf); } return -1; } return sendmsg(fd->fd, msg, flags); } struct fd *fd_accept(int socket, where_t where) { struct sockaddr_un addr; socklen_t addrlen = sizeof(addr); int fd = accept(socket, (struct sockaddr *)&addr, &addrlen); if (fd < 0) { LOG_ERRNO(errno, "accept() failed in "PRI_WHERE"", pri_where(where)); return NULL; } if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) { LOG_ERRNO(errno, "failed to set CLOEXEC in "PRI_WHERE"", pri_where(where)); close(fd); return NULL; } struct fd *fdt = alloc_thing(struct fd, where.func); fdt->fd = fd; fdt->magic = FD_MAGIC; ref_init(fdt, where); dbg("%s: new "PRI_FD" "PRI_WHERE"", __func__, pri_fd(fdt), pri_where(where)); return fdt; } ssize_t fd_read(struct fd *fd, void *buf, size_t nbytes, where_t where) { if (fd == NULL) { log_pexpect(where, "null "PRI_FD"", pri_fd(fd)); return -1; } if (fd->magic != FD_MAGIC) { log_pexpect(where, "wrong magic for "PRI_FD"", pri_fd(fd)); return -1; } return read(fd->fd, buf, nbytes); } bool fd_p(struct fd *fd) { if (fd == NULL) { return false; } if (fd->magic != FD_MAGIC) { log_pexpect(HERE, "wrong magic for "PRI_FD"", pri_fd(fd)); return false; } return true; } bool same_fd(struct fd *l, struct fd *r) { return fd_p(l) && fd_p(r) && l == r; } libreswan-3.32/lib/libswan/goodmask.3.xml000066400000000000000000000064471365625662500203560ustar00rootroot00000000000000 PaulWoutersplaceholder to suppress warning IPSEC_GOODMASK 3 11 June 2001 libreswan Executable programs ipsec goodmask ipsec masktobits ipsec bitstomask check if Internet subnet mask is valid, convert Internet subnet mask to bit count, convert bit count to Internet subnet mask #include <libreswan.h> int goodmask struct in_addr mask int masktobits struct in_addr mask struct in_addr bitstomask int n DESCRIPTION These functions are obsolete; see ipsec_masktocount3 for a partial replacement. Goodmask reports whether the subnet mask is a valid one, i.e. consists of a (possibly empty) sequence of 1s followed by a (possibly empty) sequence of 0s. Masktobits takes a (valid) subnet mask and returns the number of 1 bits in it. Bitstomask reverses this, returning the subnet mask corresponding to bit count n. All masks are in network byte order. SEE ALSO inet3, ipsec_atosubnet3 DIAGNOSTICS Masktobits returns for an invalid mask. Bitstomask returns an all-zeros mask for a negative or out-of-range n. HISTORY Written for the FreeS/WAN project by Henry Spencer. BUGS The error-reporting convention of bitstomask is less than ideal; zero is sometimes a legitimate mask. libreswan-3.32/lib/libswan/id.c000066400000000000000000000337021365625662500164210ustar00rootroot00000000000000/* * identity representation, as in IKE ID Payloads (RFC 2407 DOI 4.6.2.1) * * Copyright (C) 1999-2001,2013-2017 D. Hugh Redelmeier * Copyright (C) 2006 Michael Richardson * Copyright (C) 2008,2012-2017 Paul Wouters * Copyright (C) 2008-2009 David McCullough * Copyright (C) 2012 Wes Hardaker * Copyright (C) 2013 Florian Weimer * Copyright (C) 2013-2015 Matt Rogers, * Copyright (C) 2013-2017 Antony Antony * Copyright (C) 2015 Valeriu Goldberger * Copyright (C) 2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include #include #include #include #include #include #include "sysdep.h" #include "constants.h" #include "libreswan/passert.h" #include "lswalloc.h" #include "lswlog.h" #include "sysdep.h" #include "id.h" #include "x509.h" #include #include "certs.h" #include "ip_info.h" /* * Convert textual form of id into a (temporary) struct id. * * Note that if the id is to be kept, unshare_id_content will be necessary. * This function should be split into parts so the boolean arguments can be * removed -- Paul * * XXX: since caller is almost immediately calling * unshare_id_content() why not merge it. */ err_t atoid(char *src, struct id *id, bool oe_only) { err_t ugh = NULL; *id = empty_id; if (!oe_only && streq("%fromcert", src)) { id->kind = ID_FROMCERT; } else if (!oe_only && streq("%none", src)) { id->kind = ID_NONE; } else if (!oe_only && streq("%null", src)) { id->kind = ID_NULL; } else if (!oe_only && strchr(src, '=') != NULL) { /* we interpret this as an ASCII X.501 ID_DER_ASN1_DN */ id->kind = ID_DER_ASN1_DN; /* * convert from LDAP style or openssl x509 -subject style * to ASN.1 DN * discard optional @ character in front of DN */ ugh = atodn((*src == '@') ? src + 1 : src, &id->name); } else if (strchr(src, '@') == NULL) { if (streq(src, "%any") || streq(src, "0.0.0.0")) { /* any ID will be accepted */ id->kind = ID_NONE; } else { /* * !!! this test is not sufficient for distinguishing * address families. * We need a notation to specify that a FQDN is to be * resolved to IPv6. */ const struct ip_info *afi = strchr(src, ':') == NULL ? &ipv4_info : &ipv6_info; id->kind = afi->id_addr; ugh = ttoaddr(src, 0, afi->af, &id->ip_addr); } } else { if (*src == '@') { if (!oe_only && *(src + 1) == '#') { /* * if there is a second specifier (#) on the * line we interpret this as ID_KEY_ID */ id->kind = ID_KEY_ID; id->name.ptr = (unsigned char *)src; /* discard @~, convert from hex to bin */ ugh = ttodata(src + 2, 0, 16, (char *)id->name.ptr, strlen(src), &id->name.len); } else if (!oe_only && *(src + 1) == '~') { /* * if there is a second specifier (~) on the * line we interpret this as a binary * ID_DER_ASN1_DN */ id->kind = ID_DER_ASN1_DN; id->name.ptr = (unsigned char *)src; /* discard @~, convert from hex to bin */ ugh = ttodata(src + 2, 0, 16, (char *)id->name.ptr, strlen(src), &id->name.len); } else if (!oe_only && *(src + 1) == '[') { /* * if there is a second specifier ([) on the * line we interpret this as a text ID_KEY_ID, * and we remove a trailing ", if there is one. */ int len = strlen(src + 2); id->kind = ID_KEY_ID; id->name.ptr = (unsigned char *)src + 2; /* * Start of name.ptr is srv+2 so len is 2 * smaller than the length of src and the * terminator character is at src[len+2]. * Therefore, the last character is src[len+1] */ if (src[len + 1] == ']') { src[len + 1] = '\0'; len--; } id->name.len = len; } else { id->kind = ID_FQDN; /* discard @ */ id->name.ptr = (unsigned char *)src + 1; id->name.len = strlen(src) - 1; } } else { /* * We leave in @, as per DOI 4.6.2.4 * (but DNS wants . instead). */ id->kind = ID_USER_FQDN; id->name.ptr = (unsigned char *)src; id->name.len = strlen(src); } } return ugh; } void jam_id(jambuf_t *buf, const struct id *id, jam_bytes_fn *jam_bytes) { switch (id->kind) { case ID_FROMCERT: jam(buf, "%%fromcert"); break; case ID_NONE: jam(buf, "(none)"); break; case ID_NULL: jam(buf, "ID_NULL"); break; case ID_IPV4_ADDR: case ID_IPV6_ADDR: if (isanyaddr(&id->ip_addr)) { jam(buf, "%%any"); } else { jam_address(buf, &id->ip_addr); } break; case ID_FQDN: jam(buf, "@"); jam_bytes(buf, id->name.ptr, id->name.len); break; case ID_USER_FQDN: jam_bytes(buf, id->name.ptr, id->name.len); break; case ID_DER_ASN1_DN: jam_dn(buf, id->name, jam_bytes); break; case ID_KEY_ID: jam(buf, "@#0x"); jam_hex_bytes(buf, id->name.ptr, id->name.len); break; default: jam(buf, "unknown id kind %d", id->kind); break; } } const char *str_id(const struct id *id, id_buf *dst) { jambuf_t buf = ARRAY_AS_JAMBUF(dst->buf); /* JAM_ID() only emits printable ASCII */ jam_id(&buf, id, jam_raw_bytes); return dst->buf; } /* * Make private copy of string in struct id. * This is needed if the result of atoid is to be kept. */ void unshare_id_content(struct id *id) { switch (id->kind) { case ID_FQDN: case ID_USER_FQDN: case ID_DER_ASN1_DN: case ID_KEY_ID: id->name.ptr = clone_bytes(id->name.ptr, id->name.len, "keep id name"); /* Somehow assert we have a valid id here? */ break; case ID_FROMCERT: case ID_NONE: case ID_NULL: case ID_IPV4_ADDR: case ID_IPV6_ADDR: break; default: bad_case(id->kind); } } struct id clone_id(const struct id *src, const char *name) { struct id dst = { .kind = src->kind, .ip_addr = src->ip_addr, .name = clone_hunk(src->name, name), }; return dst; } void free_id_content(struct id *id) { switch (id->kind) { case ID_FQDN: case ID_USER_FQDN: case ID_DER_ASN1_DN: case ID_KEY_ID: free_chunk_content(&id->name); break; case ID_FROMCERT: case ID_NONE: case ID_NULL: case ID_IPV4_ADDR: case ID_IPV6_ADDR: pexpect(id->name.ptr == NULL); break; default: bad_case(id->kind); } } /* is this a "match anything" id */ bool any_id(const struct id *a) { switch (a->kind) { case ID_NONE: return TRUE; /* wildcard */ case ID_IPV4_ADDR: case ID_IPV6_ADDR: return isanyaddr(&a->ip_addr); case ID_FQDN: case ID_USER_FQDN: case ID_DER_ASN1_DN: case ID_KEY_ID: case ID_NULL: return FALSE; default: bad_case(a->kind); } } /* compare two struct id values */ bool same_id(const struct id *a, const struct id *b) { if (b->kind == ID_NONE || a->kind == ID_NONE) { DBG(DBG_PARSING, DBG_log("id type with ID_NONE means wildcard match")); return TRUE; /* it's the wildcard */ } if (a->kind != b->kind) { return FALSE; } switch (a->kind) { case ID_NONE: return TRUE; /* repeat of above for completeness */ case ID_NULL: if (a->kind == b->kind) { DBG(DBG_PARSING, DBG_log("ID_NULL: id kind matches")); return TRUE; } return FALSE; case ID_IPV4_ADDR: case ID_IPV6_ADDR: return sameaddr(&a->ip_addr, &b->ip_addr); case ID_FQDN: case ID_USER_FQDN: /* * assumptions: * - case should be ignored * - trailing "." should be ignored * (even if the only character?) */ { size_t al = a->name.len, bl = b->name.len; /* strip trailing dots */ while (al > 0 && a->name.ptr[al - 1] == '.') al--; while (bl > 0 && b->name.ptr[bl - 1] == '.') bl--; return al == bl && strncaseeq((char *)a->name.ptr, (char *)b->name.ptr, al); } case ID_FROMCERT: DBG(DBG_CONTROL, DBG_log("same_id() received ID_FROMCERT - unexpected")); /* FALLTHROUGH */ case ID_DER_ASN1_DN: return same_dn(a->name, b->name); case ID_KEY_ID: return chunk_eq(a->name, b->name); default: bad_case(a->kind); } } /* compare two struct id values, DNs can contain wildcards */ bool match_id(const struct id *a, const struct id *b, int *wildcards) { bool match; *wildcards = 0; if (b->kind == ID_NONE) { *wildcards = MAX_WILDCARDS; match = TRUE; } else if (a->kind != b->kind) { match = FALSE; } else if (a->kind == ID_DER_ASN1_DN) { match = match_dn_any_order_wild(a->name, b->name, wildcards); } else { match = same_id(a, b); } DBG(DBG_CONTROLMORE, { id_buf buf; DBG_log(" match_id a=%s", str_id(a, &buf)); DBG_log(" b=%s", str_id(b, &buf)); DBG_log(" results %s", match ? "matched" : "fail"); }); return match; } /* count the number of wildcards in an id */ int id_count_wildcards(const struct id *id) { int count = 0; switch (id->kind) { case ID_NONE: count = MAX_WILDCARDS; break; case ID_DER_ASN1_DN: count = dn_count_wildcards(id->name); break; default: break; } DBG(DBG_CONTROL, { id_buf b; DBG_log("counting wild cards for %s is %d", str_id(id, &b), count); }); return count; } void duplicate_id(struct id *dst, const struct id *src) { passert(dst->name.ptr == NULL || dst->name.ptr != src->name.ptr); free_id_content(dst); *dst = clone_id(src, "copy of id"); } static bool match_rdn(const CERTRDN *const rdn_a, const CERTRDN *const rdn_b, bool *const has_wild) { if (rdn_a == NULL || rdn_b == NULL) return FALSE; int matched = 0; int ava_num = 0; CERTAVA *const *avas_b; for (avas_b = rdn_b->avas; *avas_b != NULL; avas_b++) { CERTAVA *const ava_b = *avas_b; const SECOidTag tag_b = CERT_GetAVATag(ava_b); ava_num++; CERTAVA *const *avas_a; for (avas_a = rdn_a->avas; *avas_a != NULL; avas_a++) { CERTAVA *const ava_a = *avas_a; if (CERT_GetAVATag(ava_a) == tag_b) { SECItem *val_b = CERT_DecodeAVAValue(&ava_b->value); /* XXX Can CERT_DecodeAVAValue() return NULL? No man page :( */ if (val_b != NULL) { if (has_wild != NULL && val_b->len == 1 && val_b->data[0] == '*') { *has_wild = TRUE; matched++; SECITEM_FreeItem(val_b, PR_TRUE); break; } SECITEM_FreeItem(val_b, PR_TRUE); } if (CERT_CompareAVA(ava_a, ava_b) == SECEqual) { matched++; break; } } } } return matched > 0 && matched == ava_num; } /* * match an equal number of RDNs, in any order * if wildcards != NULL, wildcard matches are enabled */ static bool match_dn_unordered(const chunk_t a, const chunk_t b, int *const wildcards) { dn_buf a_dnbuf = { "", }; dn_buf b_dnbuf = { "", }; /* * Escape the ASN.1 into RFC-1485 (actually RFC-4514 and * printable ASCII) so that that it is suitable for NSS's * CERT_AsciiToName(). */ const char *abuf = str_dn(a, &a_dnbuf); /* RFC1485 for NSS */ const char *bbuf = str_dn(b, &b_dnbuf); /* RFC1485 for NSS */ /* * ABUF and BBUF, set by dntoa(), contain an RFC 1485(?) * encoded string and that can contain UTF-8 (i.e., * !isprint()). Strip that out before logging. */ dbg("matching unordered DNs A: '%s' B: '%s'", abuf, bbuf); CERTName *const a_name = CERT_AsciiToName(abuf); CERTName *const b_name = CERT_AsciiToName(bbuf); if (a_name == NULL || b_name == NULL) { /* NULL is ignored; see NSS commit 206 */ CERT_DestroyName(a_name); CERT_DestroyName(b_name); return false; } int rdn_num = 0; int matched = 0; CERTRDN *const *rdns_b; for (rdns_b = b_name->rdns; *rdns_b != NULL; rdns_b++) { CERTRDN *const rdn_b = *rdns_b; rdn_num++; CERTRDN *const *rdns_a; for (rdns_a = a_name->rdns; *rdns_a != NULL; rdns_a++) { CERTRDN *const rdn_a = *rdns_a; bool has_wild = FALSE; if (match_rdn(rdn_a, rdn_b, wildcards != NULL ? &has_wild : NULL)) { matched++; if (wildcards != NULL && has_wild) (*wildcards)++; break; } } } CERT_DestroyName(a_name); CERT_DestroyName(b_name); dbg("%s matched: %d, rdn_num: %d, wc %d", __func__, matched, rdn_num, wildcards ? *wildcards : 0); return matched > 0 && rdn_num > 0 && matched == rdn_num; } bool same_dn_any_order(chunk_t a, chunk_t b) { bool ret = same_dn(a, b); if (!ret) { DBG(DBG_CONTROL, { DBG_log("%s: not an exact match, now checking any RDN order", __func__); // DBG_dump_hunk("a", a); // DBG_dump_hunk("b", b); }); ret = match_dn_unordered(a, b, NULL); } return ret; } bool match_dn_any_order_wild(chunk_t a, chunk_t b, int *wildcards) { bool ret = match_dn(a, b, wildcards); if (!ret) { DBG(DBG_CONTROL, DBG_log("%s: not an exact match, now checking any RDN order with %d wildcards", __func__, *wildcards)); /* recount wildcards */ *wildcards = 0; ret = match_dn_unordered(a, b, wildcards); } return ret; } /* * Build an ID payload * Note: no memory is allocated for the body of the payload (tl->ptr). * We assume it will end up being a pointer into a sufficiently * stable datastructure. It only needs to last a short time. */ enum ike_id_type id_to_payload(const struct id *id, const ip_address *host, shunk_t *body) { int type; shunk_t tl; switch (id->kind) { case ID_NONE: type = address_type(host)->id_addr; tl = address_as_shunk(host); break; case ID_FROMCERT: type = ID_DER_ASN1_DN; tl = shunk2(id->name.ptr, id->name.len); break; case ID_FQDN: case ID_USER_FQDN: case ID_DER_ASN1_DN: case ID_KEY_ID: type = id->kind; tl = shunk2(id->name.ptr, id->name.len); break; case ID_IPV4_ADDR: case ID_IPV6_ADDR: type = id->kind; tl = address_as_shunk(&id->ip_addr); break; case ID_NULL: type = id->kind; tl = empty_shunk; break; default: bad_case(id->kind); } *body = tl; return type; } libreswan-3.32/lib/libswan/ike_alg.c000066400000000000000000001011041365625662500174100ustar00rootroot00000000000000/* * IKE modular algorithm handling interface, for libreswan * * Author: JuanJo Ciarlante * Copyright (C) 2003 Mathieu Lafon * Copyright (C) 2005-2007 Michael Richardson * Copyright (C) 2007 Ken Bantoft * Copyright (C) 2011-2012 Paul Wouters * Copyright (C) 2012 Paul Wouters * Copyright (C) 2013-2019 D. Hugh Redelmeier * Copyright (C) 2013-2014 Paul Wouters * Copyright (C) 2016-2018 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include #include #include #include "sysdep.h" #include "constants.h" #include "lswfips.h" #include "lswlog.h" #include "lswalloc.h" #include "proposals.h" #include "ike_alg.h" #include "ike_alg_integ.h" #include "ike_alg_encrypt.h" #include "ike_alg_encrypt_ops.h" #include "ike_alg_prf.h" #include "ike_alg_prf_mac_ops.h" #include "ike_alg_prf_ikev1_ops.h" #include "ike_alg_prf_ikev2_ops.h" #include "ike_alg_hash.h" #include "ike_alg_hash_ops.h" #include "ike_alg_dh.h" #include "ike_alg_dh_ops.h" /*========================================================== * * IKE algo list handling * * - registration des* - lookup *=========================================================*/ #define FOR_EACH_IKE_ALGP(TYPE,A) \ for (const struct ike_alg **(A) = (TYPE)->algorithms->start; \ (A) < (TYPE)->algorithms->end; \ (A)++) #define FOR_EACH_IKE_ALG_NAME(ALG, NAME) \ for (shunk_t NAME##input = shunk1((ALG)->names), \ NAME = shunk_token(&NAME##input, NULL, ","); \ NAME.len > 0; NAME = shunk_token(&NAME##input, NULL, ",")) struct algorithm_table { const struct ike_alg **start; const struct ike_alg **end; }; #define ALGORITHM_TABLE(TABLE) { \ .start = (const struct ike_alg **)(TABLE), \ .end = (const struct ike_alg **)(TABLE) + elemsof(TABLE), \ } struct ike_alg_type { /* * Having the full capitalized name might make localization * easier. */ const char *name; const char *Name; /* capitalized */ struct algorithm_table *algorithms; enum_names *const enum_names[IKE_ALG_KEY_ROOF]; void (*desc_check)(const struct ike_alg*); bool (*desc_is_ike)(const struct ike_alg*); }; #define FOR_EACH_IKE_ALG_TYPEP(TYPEP) \ for (const struct ike_alg_type *const *TYPEP = ike_alg_types; \ TYPEP < ike_alg_types + elemsof(ike_alg_types); \ TYPEP++) static const struct ike_alg_type *const ike_alg_types[] = { &ike_alg_encrypt, &ike_alg_hash, &ike_alg_prf, &ike_alg_integ, &ike_alg_dh, }; const char *ike_alg_key_name(enum ike_alg_key key) { static const char *names[IKE_ALG_KEY_ROOF] = { [IKEv1_OAKLEY_ID] = "IKEv1 OAKLEY ID", [IKEv1_ESP_ID] = "IKEv1 ESP ID", [IKEv2_ALG_ID] = "IKEv2 ID", }; passert(key < elemsof(names)); return names[key]; } static const struct ike_alg **next_alg(const struct ike_alg_type *type, const struct ike_alg **last) { struct algorithm_table *table = type->algorithms; if (last == NULL) { return table->start; } passert(last >= table->start); passert(last < table->end); last++; if (last >= table->end) { return NULL; } return last; } const struct encrypt_desc **next_encrypt_desc(const struct encrypt_desc **last) { return (const struct encrypt_desc**)next_alg(&ike_alg_encrypt, (const struct ike_alg**)last); } const struct prf_desc **next_prf_desc(const struct prf_desc **last) { return (const struct prf_desc**)next_alg(&ike_alg_prf, (const struct ike_alg**)last); } const struct integ_desc **next_integ_desc(const struct integ_desc **last) { return (const struct integ_desc**)next_alg(&ike_alg_integ, (const struct ike_alg**)last); } const struct dh_desc **next_dh_desc(const struct dh_desc **last) { return (const struct dh_desc**)next_alg(&ike_alg_dh, (const struct ike_alg**)last); } const struct ike_alg *ike_alg_byname(const struct ike_alg_type *type, shunk_t name) { passert(type != NULL); for (const struct ike_alg **alg = next_alg(type, NULL); alg != NULL; alg = next_alg(type, alg)) { FOR_EACH_IKE_ALG_NAME(*alg, alg_name) { if (shunk_caseeq(alg_name, name)) { return *alg; } } } return NULL; } int ike_alg_enum_match(const struct ike_alg_type *type, enum ike_alg_key key, shunk_t name) { passert(type != NULL); passert(key < IKE_ALG_KEY_ROOF); return enum_match(type->enum_names[key], name); } bool ike_alg_is_valid(const struct ike_alg *alg) { FOR_EACH_IKE_ALGP(alg->algo_type, algp) { if (*algp == alg) { return TRUE; } } return FALSE; } bool ike_alg_is_ike(const struct ike_alg *alg) { return alg->algo_type->desc_is_ike(alg); } const char *ike_alg_type_name(const struct ike_alg_type *type) { passert(type != NULL); return type->name; } const char *ike_alg_type_Name(const struct ike_alg_type *type) { passert(type != NULL); return type->Name; } bool encrypt_desc_is_aead(const struct encrypt_desc *enc_desc) { return enc_desc != NULL && enc_desc->aead_tag_size > 0; } /* * return ike_alg object by {type, key, id} */ static const struct ike_alg *lookup_by_id(const struct ike_alg_type *type, enum ike_alg_key key, int id, lset_t debug) { FOR_EACH_IKE_ALGP(type, algp) { const struct ike_alg *alg = *algp; if (alg->id[key] == id) { DBG(debug, const char *name = enum_short_name(type->enum_names[key], id); DBG_log("%s ike_alg_lookup_by_id id: %s=%u, found %s\n", type->name, name ? name : "???", id, alg->fqn)); return alg; } } DBG(debug, const char *name = enum_short_name(type->enum_names[key], id); DBG_log("%s ike_alg_lookup_by_id id: %s=%u, not found\n", type->name, name ? name : "???", id)); return NULL; } static const struct ike_alg *ikev1_oakley_lookup(const struct ike_alg_type *algorithms, unsigned id) { const struct ike_alg *alg = lookup_by_id(algorithms, IKEv1_OAKLEY_ID, id, DBG_CRYPT); if (alg == NULL || !ike_alg_is_ike(alg)) { return NULL; } return alg; } const struct encrypt_desc *ikev1_get_ike_encrypt_desc(enum ikev1_encr_attribute id) { return encrypt_desc(ikev1_oakley_lookup(&ike_alg_encrypt, id)); } const struct prf_desc *ikev1_get_ike_prf_desc(enum ikev1_auth_attribute id) { return prf_desc(ikev1_oakley_lookup(&ike_alg_prf, id)); } const struct dh_desc *ikev1_get_ike_dh_desc(enum ike_trans_type_dh id) { return dh_desc(ikev1_oakley_lookup(&ike_alg_dh, id)); } const struct encrypt_desc *ikev1_get_kernel_encrypt_desc(enum ipsec_cipher_algo id) { return encrypt_desc(lookup_by_id(&ike_alg_encrypt, IKEv1_ESP_ID, id, DBG_CRYPT)); } const struct integ_desc *ikev1_get_kernel_integ_desc(enum ikev1_auth_attribute id) { return integ_desc(lookup_by_id(&ike_alg_integ, IKEv1_ESP_ID, id, DBG_CRYPT)); } static const struct ike_alg *ikev2_lookup(const struct ike_alg_type *algorithms, int id) { return lookup_by_id(algorithms, IKEv2_ALG_ID, id, DBG_CRYPT); } const struct encrypt_desc *ikev2_get_encrypt_desc(enum ikev2_trans_type_encr id) { return encrypt_desc(ikev2_lookup(&ike_alg_encrypt, id)); } const struct prf_desc *ikev2_get_prf_desc(enum ikev2_trans_type_prf id) { return prf_desc(ikev2_lookup(&ike_alg_prf, id)); } const struct integ_desc *ikev2_get_integ_desc(enum ikev2_trans_type_integ id) { return integ_desc(ikev2_lookup(&ike_alg_integ, id)); } const struct dh_desc *ikev2_get_dh_desc(enum ike_trans_type_dh id) { return dh_desc(ikev2_lookup(&ike_alg_dh, id)); } #define LOOKUP(TYPE, FIELD, VALUE) \ { \ for (const struct TYPE **algp = next_##TYPE(NULL); \ algp != NULL; algp = next_##TYPE(algp)) { \ const struct TYPE *alg = *algp; \ if (alg->FIELD == VALUE) { \ return alg; \ } \ } \ return NULL; \ } const struct encrypt_desc *encrypt_desc_by_sadb_ealg_id(unsigned id) { LOOKUP(encrypt_desc, encrypt_sadb_ealg_id, id); } const struct integ_desc *integ_desc_by_sadb_aalg_id(unsigned id) { LOOKUP(integ_desc, integ_sadb_aalg_id, id); } /* * Validate and register IKE algorithm objects * * Order the array so that, when listed, the algorithms are in the * order expected by test scripts. */ static bool ike_alg_in_table(const struct ike_alg *alg) { const struct ike_alg_type *alg_type = alg->algo_type; FOR_EACH_IKE_ALGP(alg_type, algp) { if (alg == *algp) { return true; } } return false; } static void pexpect_ike_alg_base_in_table(where_t where, const struct ike_alg *alg, const struct ike_alg *base_alg) { if (!ike_alg_in_table(base_alg)) { log_pexpect(where, PRI_IKE_ALG" base "PRI_IKE_ALG" missing from algorithm table", pri_ike_alg(alg), pri_ike_alg(base_alg)); } } /* * Check that name appears in alg->names */ static bool ike_alg_has_name(const struct ike_alg *alg, shunk_t name) { FOR_EACH_IKE_ALG_NAME(alg, alg_name) { if (shunk_caseeq(alg_name, name)) { return true; } } return false; } static bool pexpect_ike_alg_has_name(where_t where, const struct ike_alg *alg, const char *name, const char *description) { if (name == NULL) { log_pexpect(where, PRI_IKE_ALG" %s name is NULL", pri_ike_alg(alg), description); return false; } else if (!ike_alg_has_name(alg, shunk1(name))) { log_pexpect(where, PRI_IKE_ALG" missing %s name %s", pri_ike_alg(alg), description, name); return false; } return true; } /* * Check that BASE_ALG's names also appear in ALG's names. * * For instance, a PRF implemented using a HASH must have all the * shorter HASH names in the PRF name table. */ static void pexpect_ike_alg_has_base_names(where_t where, const struct ike_alg *alg, const struct ike_alg *base_alg) { FOR_EACH_IKE_ALG_NAME(base_alg, alg_name) { if (!ike_alg_has_name(alg, alg_name)) { log_pexpect(where, PRI_IKE_ALG" missing name "PRI_SHUNK" in base "PRI_IKE_ALG, pri_ike_alg(alg), pri_shunk(alg_name), pri_ike_alg(base_alg)); } } } /* * Simple hash functions. */ static const struct hash_desc *hash_descriptors[] = { #ifdef USE_MD5 &ike_alg_hash_md5, #endif #ifdef USE_SHA1 &ike_alg_hash_sha1, #endif #ifdef USE_SHA2 &ike_alg_hash_sha2_256, &ike_alg_hash_sha2_384, &ike_alg_hash_sha2_512, #endif }; static void hash_desc_check(const struct ike_alg *alg) { const struct hash_desc *hash = hash_desc(alg); pexpect_ike_alg(alg, hash->hash_digest_size > 0); struct crypt_mac mac; pexpect_ike_alg(alg, hash->hash_digest_size <= sizeof(mac.ptr/*an array*/)); pexpect_ike_alg(alg, hash->hash_block_size > 0); if (hash->hash_ops != NULL) { pexpect_ike_alg(alg, hash->hash_ops->backend != NULL); pexpect_ike_alg(alg, hash->hash_ops->check != NULL); pexpect_ike_alg(alg, hash->hash_ops->digest_symkey != NULL); pexpect_ike_alg(alg, hash->hash_ops->digest_bytes != NULL); pexpect_ike_alg(alg, hash->hash_ops->final_bytes != NULL); hash->hash_ops->check(hash); } } static bool hash_desc_is_ike(const struct ike_alg *alg) { const struct hash_desc *hash = hash_desc(alg); return hash->hash_ops != NULL; } static struct algorithm_table hash_algorithms = ALGORITHM_TABLE(hash_descriptors); const struct ike_alg_type ike_alg_hash = { .name = "hash", .Name = "Hash", .algorithms = &hash_algorithms, .enum_names = { [IKEv1_OAKLEY_ID] = &oakley_hash_names, }, .desc_check = hash_desc_check, .desc_is_ike = hash_desc_is_ike, }; /* * PRF function. * * Sometimes, but not always, built on a HASH function using the HMAC * construct. */ static const struct prf_desc *prf_descriptors[] = { #ifdef USE_MD5 &ike_alg_prf_hmac_md5, #endif #ifdef USE_SHA1 &ike_alg_prf_sha1, #endif #ifdef USE_SHA2 &ike_alg_prf_sha2_256, &ike_alg_prf_sha2_384, &ike_alg_prf_sha2_512, #endif #ifdef USE_PRF_AES_XCBC &ike_alg_prf_aes_xcbc, #endif }; static void prf_desc_check(const struct ike_alg *alg) { const struct prf_desc *prf = prf_desc(alg); pexpect_ike_alg(alg, prf->prf_key_size > 0); pexpect_ike_alg(alg, prf->prf_output_size > 0); struct crypt_mac mac; pexpect_ike_alg(alg, prf->prf_output_size <= sizeof(mac.ptr/*an array*/)); pexpect_ike_alg_has_name(HERE, alg, prf->prf_ike_audit_name, ".prf_ike_audit_name"); /* all or none */ pexpect_ike_alg(alg, (prf->prf_mac_ops != NULL) == (prf->prf_ikev1_ops != NULL)); pexpect_ike_alg(alg, (prf->prf_mac_ops != NULL) == (prf->prf_ikev2_ops != NULL)); if (prf->prf_mac_ops != NULL) { pexpect_ike_alg(alg, prf->prf_mac_ops->backend != NULL); pexpect_ike_alg(alg, prf->prf_mac_ops->check != NULL); pexpect_ike_alg(alg, prf->prf_mac_ops->init_symkey != NULL); pexpect_ike_alg(alg, prf->prf_mac_ops->init_bytes != NULL); pexpect_ike_alg(alg, prf->prf_mac_ops->digest_symkey != NULL); pexpect_ike_alg(alg, prf->prf_mac_ops->digest_bytes != NULL); pexpect_ike_alg(alg, prf->prf_mac_ops->final_symkey != NULL); pexpect_ike_alg(alg, prf->prf_mac_ops->final_bytes != NULL); /* * IKEv1 IKE algorithms must have a hasher - used for * things like computing IV. */ pexpect_ike_alg(alg, prf->common.id[IKEv1_OAKLEY_ID] < 0 || prf->hasher != NULL); prf->prf_mac_ops->check(prf); } if (prf->prf_ikev1_ops != NULL) { pexpect_ike_alg(alg, prf->prf_ikev1_ops->backend != NULL); pexpect_ike_alg(alg, prf->prf_ikev1_ops->signature_skeyid != NULL); pexpect_ike_alg(alg, prf->prf_ikev1_ops->pre_shared_key_skeyid != NULL); pexpect_ike_alg(alg, prf->prf_ikev1_ops->skeyid_d != NULL); pexpect_ike_alg(alg, prf->prf_ikev1_ops->skeyid_a != NULL); pexpect_ike_alg(alg, prf->prf_ikev1_ops->skeyid_e != NULL); pexpect_ike_alg(alg, prf->prf_ikev1_ops->appendix_b_keymat_e != NULL); } if (prf->prf_ikev2_ops != NULL) { pexpect_ike_alg(alg, prf->prf_ikev2_ops->backend != NULL); pexpect_ike_alg(alg, prf->prf_ikev2_ops->prfplus != NULL); pexpect_ike_alg(alg, prf->prf_ikev2_ops->ike_sa_skeyseed != NULL); pexpect_ike_alg(alg, prf->prf_ikev2_ops->ike_sa_rekey_skeyseed != NULL); pexpect_ike_alg(alg, prf->prf_ikev2_ops->ike_sa_keymat != NULL); pexpect_ike_alg(alg, prf->prf_ikev2_ops->child_sa_keymat != NULL); pexpect_ike_alg(alg, prf->prf_ikev2_ops->psk_auth != NULL); } if (prf->hasher != NULL) { /* * Check for dangling pointer. */ pexpect_ike_alg_base_in_table(HERE, &prf->common, &prf->hasher->common); pexpect_ike_alg(alg, prf->prf_output_size == prf->hasher->hash_digest_size); pexpect_ike_alg_has_base_names(HERE, &prf->common, &prf->hasher->common); } } static bool prf_desc_is_ike(const struct ike_alg *alg) { const struct prf_desc *prf = prf_desc(alg); return prf->prf_mac_ops != NULL; } static struct algorithm_table prf_algorithms = ALGORITHM_TABLE(prf_descriptors); const struct ike_alg_type ike_alg_prf = { .name = "PRF", .Name = "PRF", .algorithms = &prf_algorithms, .enum_names = { [IKEv1_OAKLEY_ID] = &oakley_hash_names, [IKEv1_ESP_ID] = NULL, /* ESP/AH uses IKE PRF */ [IKEv2_ALG_ID] = &ikev2_trans_type_prf_names, }, .desc_check = prf_desc_check, .desc_is_ike = prf_desc_is_ike, }; /* * Integrity. */ static const struct integ_desc *integ_descriptors[] = { #ifdef USE_MD5 &ike_alg_integ_hmac_md5_96, #endif #ifdef USE_SHA1 &ike_alg_integ_sha1, #endif #ifdef USE_SHA2 &ike_alg_integ_sha2_512, &ike_alg_integ_sha2_384, &ike_alg_integ_sha2_256, &ike_alg_integ_hmac_sha2_256_truncbug, #endif #ifdef USE_AES &ike_alg_integ_aes_xcbc, &ike_alg_integ_aes_cmac, #endif #ifdef USE_RIPEMD &ike_alg_integ_hmac_ripemd_160_96, #endif &ike_alg_integ_none, }; static void integ_desc_check(const struct ike_alg *alg) { const struct integ_desc *integ = integ_desc(alg); pexpect_ike_alg(alg, integ->integ_keymat_size > 0); pexpect_ike_alg(alg, integ->integ_output_size > 0); struct crypt_mac mac; pexpect_ike_alg(alg, integ->integ_output_size <= sizeof(mac.ptr/*an array*/)); pexpect_ike_alg_has_name(HERE, alg, integ->integ_tcpdump_name, ".integ_tcpdump_name"); pexpect_ike_alg_has_name(HERE, alg, integ->integ_ike_audit_name, ".integ_ike_audit_name"); pexpect_ike_alg_has_name(HERE, alg, integ->integ_kernel_audit_name, ".integ_kernel_audit_name"); if (integ->common.id[IKEv1_ESP_ID] >= 0) { struct esb_buf esb; pexpect_ike_alg_streq(alg, integ->integ_kernel_audit_name, enum_show_shortb(&auth_alg_names, integ->common.id[IKEv1_ESP_ID], &esb)); } if (integ->prf != NULL) { pexpect_ike_alg(alg, integ->integ_keymat_size == integ->prf->prf_key_size); pexpect_ike_alg(alg, integ->integ_output_size <= integ->prf->prf_output_size); pexpect_ike_alg(alg, prf_desc_is_ike(&integ->prf->common)); pexpect_ike_alg_has_base_names(HERE, &integ->common, &integ->prf->common); } } static bool integ_desc_is_ike(const struct ike_alg *alg) { const struct integ_desc *integ = integ_desc(alg); return integ->prf != NULL || integ == &ike_alg_integ_none; } static struct algorithm_table integ_algorithms = ALGORITHM_TABLE(integ_descriptors); const struct ike_alg_type ike_alg_integ = { .name = "integrity", .Name = "Integrity", .algorithms = &integ_algorithms, .enum_names = { [IKEv1_OAKLEY_ID] = &oakley_hash_names, [IKEv1_ESP_ID] = &auth_alg_names, [IKEv2_ALG_ID] = &ikev2_trans_type_integ_names, }, .desc_check = integ_desc_check, .desc_is_ike = integ_desc_is_ike, }; /* * Encryption */ static const struct encrypt_desc *encrypt_descriptors[] = { #ifdef USE_AES &ike_alg_encrypt_aes_ccm_16, &ike_alg_encrypt_aes_ccm_12, &ike_alg_encrypt_aes_ccm_8, /* see note above */ #endif #ifdef USE_3DES &ike_alg_encrypt_3des_cbc, #endif #ifdef USE_CAMELLIA &ike_alg_encrypt_camellia_ctr, &ike_alg_encrypt_camellia_cbc, #endif #ifdef USE_AES &ike_alg_encrypt_aes_gcm_16, &ike_alg_encrypt_aes_gcm_12, &ike_alg_encrypt_aes_gcm_8, &ike_alg_encrypt_aes_ctr, &ike_alg_encrypt_aes_cbc, #endif #ifdef USE_SERPENT &ike_alg_encrypt_serpent_cbc, #endif #ifdef USE_TWOFISH &ike_alg_encrypt_twofish_cbc, &ike_alg_encrypt_twofish_ssh, #endif #ifdef USE_CAST &ike_alg_encrypt_cast_cbc, #endif &ike_alg_encrypt_null_integ_aes_gmac, &ike_alg_encrypt_null, #ifdef USE_CHACHA &ike_alg_encrypt_chacha20_poly1305, #endif }; bool encrypt_has_key_bit_length(const struct encrypt_desc *encrypt, unsigned keylen) { /* * This loop is written so that KEYLEN is always compared * against the first entry in .key_bit_lengths - even when * that entry is zero. This happens when encryption is 'none' * and the KEYLEN really is zero. */ const unsigned *p = encrypt->key_bit_lengths; do { if (*p == keylen) { return true; } p++; } while (*p != 0); return false; } unsigned encrypt_max_key_bit_length(const struct encrypt_desc *encrypt) { /* by definition: largest is first */ return encrypt->key_bit_lengths[0]; } unsigned encrypt_min_key_bit_length(const struct encrypt_desc *encrypt) { /* by definition: smallest is last */ unsigned smallest = 0; for (const unsigned *keyp = encrypt->key_bit_lengths; *keyp; keyp++) { smallest = *keyp; } return smallest; } static void encrypt_desc_check(const struct ike_alg *alg) { const struct encrypt_desc *encrypt = encrypt_desc(alg); /* * AES_GCM is a screwup. AES_GCM_16 has the name "aes_gcm" * but when logging tcp or audit, that is assigned to * AES_GCM_8. */ if (encrypt == &ike_alg_encrypt_aes_gcm_8) { pexpect_ike_alg_streq(alg, encrypt->encrypt_tcpdump_name, "aes_gcm"); pexpect_ike_alg_streq(alg, encrypt->encrypt_ike_audit_name, "aes_gcm"); } else { pexpect_ike_alg_has_name(HERE, alg, encrypt->encrypt_tcpdump_name, ".encrypt_tcpdump_name"); pexpect_ike_alg_has_name(HERE, alg, encrypt->encrypt_ike_audit_name, ".encrypt_ike_audit_name"); } pexpect_ike_alg_has_name(HERE, alg, encrypt->encrypt_kernel_audit_name, ".encrypt_kernel_audit_name"); if (encrypt->common.id[IKEv1_ESP_ID] >= 0) { struct esb_buf esb; pexpect_ike_alg_streq(alg, encrypt->encrypt_kernel_audit_name, enum_show_shortb(&esp_transformid_names, encrypt->common.id[IKEv1_ESP_ID], &esb)); } /* * Only implemented one way, if at all. */ if (encrypt->encrypt_ops != NULL) { pexpect_ike_alg(alg, encrypt->encrypt_ops->backend != NULL); pexpect_ike_alg(alg, encrypt->encrypt_ops->check != NULL); pexpect_ike_alg(alg, ((encrypt->encrypt_ops->do_crypt == NULL) != (encrypt->encrypt_ops->do_aead == NULL))); } /* * AEAD implementation implies a valid AEAD tag size. * Converse for non-AEAD implementation. */ if (encrypt->encrypt_ops != NULL) { pexpect_ike_alg(alg, encrypt->encrypt_ops->do_aead == NULL || encrypt->aead_tag_size > 0); pexpect_ike_alg(alg, encrypt->encrypt_ops->do_crypt == NULL || encrypt->aead_tag_size == 0); } /* * Key length checks. * * Either the algorithm is 'null', or there is a non-zero * KEYDEFLEN. */ if (encrypt == &ike_alg_encrypt_null) { pexpect_ike_alg(alg, encrypt->keydeflen == 0); pexpect_ike_alg(alg, encrypt->common.id[IKEv1_ESP_ID] == ESP_NULL); pexpect_ike_alg(alg, encrypt->common.id[IKEv2_ALG_ID] == IKEv2_ENCR_NULL); pexpect_ike_alg(alg, encrypt->enc_blocksize == 1); pexpect_ike_alg(alg, encrypt->wire_iv_size == 0); pexpect_ike_alg(alg, encrypt->key_bit_lengths[0] == 0); } else { pexpect_ike_alg(alg, encrypt->keydeflen > 0); pexpect_ike_alg(alg, encrypt->key_bit_lengths[0] > 0); } /* Key lengths are in descending order and 0 terminated. */ { const unsigned *keylenp = encrypt->key_bit_lengths; unsigned last_key_len = *keylenp; keylenp++; pexpect_ike_alg(alg, encrypt->key_bit_lengths[elemsof(encrypt->key_bit_lengths) - 1] == 0); for (; *keylenp != 0; keylenp++) { pexpect_ike_alg(alg, last_key_len > *keylenp); } } /* * The default (even when 0) is always valid. */ pexpect_ike_alg(alg, encrypt_has_key_bit_length(encrypt, encrypt->keydeflen)); } static bool encrypt_desc_is_ike(const struct ike_alg *alg) { const struct encrypt_desc *encrypt = encrypt_desc(alg); return encrypt->encrypt_ops != NULL; } static struct algorithm_table encrypt_algorithms = ALGORITHM_TABLE(encrypt_descriptors); const struct ike_alg_type ike_alg_encrypt = { .name = "encryption", .Name = "Encryption", .algorithms = &encrypt_algorithms, .enum_names = { [IKEv1_OAKLEY_ID] = &oakley_enc_names, [IKEv1_ESP_ID] = &esp_transformid_names, [IKEv2_ALG_ID] = &ikev2_trans_type_encr_names, }, .desc_check = encrypt_desc_check, .desc_is_ike = encrypt_desc_is_ike, }; /* * DH group */ static const struct dh_desc *dh_descriptors[] = { &ike_alg_dh_none, #ifdef USE_DH2 &ike_alg_dh_modp1024, #endif &ike_alg_dh_modp1536, &ike_alg_dh_modp2048, &ike_alg_dh_modp3072, &ike_alg_dh_modp4096, &ike_alg_dh_modp6144, &ike_alg_dh_modp8192, &ike_alg_dh_dh19, &ike_alg_dh_dh20, &ike_alg_dh_dh21, #ifdef USE_DH22 &ike_alg_dh_dh22, #endif #ifdef USE_DH23 &ike_alg_dh_dh23, #endif #ifdef USE_DH24 &ike_alg_dh_dh24, #endif #ifdef USE_DH31 &ike_alg_dh_dh31, #endif }; static void dh_desc_check(const struct ike_alg *alg) { const struct dh_desc *dh = dh_desc(alg); pexpect_ike_alg(alg, dh->group > 0); pexpect_ike_alg(alg, dh->bytes > 0); pexpect_ike_alg(alg, dh->common.id[IKEv2_ALG_ID] == dh->group); pexpect_ike_alg(alg, dh->common.id[IKEv1_OAKLEY_ID] == dh->group); /* always implemented */ pexpect_ike_alg(alg, dh->dh_ops != NULL); if (dh->dh_ops != NULL) { pexpect_ike_alg(alg, dh->dh_ops->backend != NULL); pexpect_ike_alg(alg, dh->dh_ops->check != NULL); pexpect_ike_alg(alg, dh->dh_ops->calc_secret != NULL); pexpect_ike_alg(alg, dh->dh_ops->calc_shared != NULL); /* more? */ dh->dh_ops->check(dh); /* IKEv1 supports MODP groups but not ECC. */ pexpect_ike_alg(alg, (dh->dh_ops == &ike_alg_dh_nss_modp_ops ? dh->common.id[IKEv1_ESP_ID] == dh->group : dh->dh_ops == &ike_alg_dh_nss_ecp_ops ? dh->common.id[IKEv1_ESP_ID] < 0 : FALSE)); } } static bool dh_desc_is_ike(const struct ike_alg *alg) { const struct dh_desc *dh = dh_desc(alg); return dh->dh_ops != NULL; } static struct algorithm_table dh_algorithms = ALGORITHM_TABLE(dh_descriptors); const struct ike_alg_type ike_alg_dh = { .name = "DH", .Name = "DH", .algorithms = &dh_algorithms, .enum_names = { [IKEv1_OAKLEY_ID] = &oakley_group_names, [IKEv1_ESP_ID] = &oakley_group_names, [IKEv2_ALG_ID] = &oakley_group_names, }, .desc_check = dh_desc_check, .desc_is_ike = dh_desc_is_ike, }; /* * Check mapping between enums and names. */ static void check_enum_name(const char *what, const struct ike_alg *alg, int id, enum_names *enum_names) { if (id >= 0) { if (enum_names == NULL) { PASSERT_FAIL("%s %s %s has no enum names", alg->algo_type->name, alg->fqn, what); } const char *enum_name = enum_short_name(enum_names, id); DBG(DBG_CRYPT, DBG_log("%s id: %d enum name: %s", what, id, enum_name)); pexpect_ike_alg_has_name(HERE, alg, enum_name, "enum table name"); } else { DBG(DBG_CRYPT, DBG_log("%s id: %d enum name: N/A", what, id)); } } /* * Verify an algorithm table, pruning anything that isn't supported. */ static void check_algorithm_table(const struct ike_alg_type *type) { /* * Sanity check the raw algorithm table. * * Anything going wrong here results in an abort. */ passert(type->name != NULL); passert(type->Name != NULL); passert(strcasecmp(type->name, type->Name) == 0); DBG(DBG_CRYPT, DBG_log("%s algorithm assertion checks", type->name)); FOR_EACH_IKE_ALGP(type, algp) { const struct ike_alg *alg = *algp; DBGF(DBG_CRYPT, "%s algorithm %s, IKEv1 OAKLEY id: %d, IKEv1 ESP_INFO id: %d, IKEv2 id: %d", type->name, alg->fqn, alg->id[IKEv1_OAKLEY_ID], alg->id[IKEv1_ESP_ID], alg->id[IKEv2_ALG_ID]); /* * Check the FQN first; and require upper case. If * this one fails abort as things are really broken. */ passert(pexpect_ike_alg_has_name(HERE, alg, alg->fqn, ".fqn")); pexpect_ike_alg(alg, (strlen(alg->fqn) == strspn(alg->fqn, "ABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789"))); /* * Validate the other .common names. * * Requiring this is easier than trying to ensure that * changes to NAME don't break NAMES. */ pexpect_ike_alg_has_name(HERE, alg, alg->name, ".name"); /* * Don't allow 0 as an algorithm ID. * * Don't even try to check 'none' algorithms. */ if (alg != &ike_alg_integ_none.common && alg != &ike_alg_dh_none.common) { for (enum ike_alg_key key = IKE_ALG_KEY_FLOOR; key < IKE_ALG_KEY_ROOF; key++) { pexpect_ike_alg(alg, alg->id[key] != 0); } } /* * Check the IDs have all been set. * * Don't even try to check 'none' algorithms. */ if (alg != &ike_alg_integ_none.common && alg != &ike_alg_dh_none.common) { pexpect_ike_alg(alg, alg->id[IKEv1_OAKLEY_ID] != 0); pexpect_ike_alg(alg, alg->id[IKEv1_ESP_ID] != 0); pexpect_ike_alg(alg, alg->id[IKEv2_ALG_ID] != 0); for (enum ike_alg_key key = IKE_ALG_KEY_FLOOR; key < IKE_ALG_KEY_ROOF; key++) { pexpect_ike_alg(alg, alg->id[key] != 0); } } /* * Validate an IKE_ALG's IKEv1 and IKEv2 enum_name * entries. * * struct ike_alg_encrypt_aes_ccm_8 et.al. do not * define the IKEv1 field "common.id[IKEv1_OAKLEY_ID]" * so need to handle that. */ bool at_least_one_valid_id = FALSE; for (enum ike_alg_key key = IKE_ALG_KEY_FLOOR; key < IKE_ALG_KEY_ROOF; key++) { int id = alg->id[key]; if (id >= 0) { at_least_one_valid_id = TRUE; check_enum_name(ike_alg_key_name(key), alg, id, type->enum_names[key]); } } pexpect_ike_alg(alg, at_least_one_valid_id); /* * Algorithm can't appear twice. * * Search the previously validated algorithms using a * fudged up ALL array that only contain the * previously verified algorithms. */ struct algorithm_table table = *type->algorithms; table.end = algp; struct ike_alg_type scratch = *type; scratch.algorithms = &table; for (enum ike_alg_key key = IKE_ALG_KEY_FLOOR; key < IKE_ALG_KEY_ROOF; key++) { int id = alg->id[key]; pexpect_ike_alg(alg, id < 0 || lookup_by_id(&scratch, key, id, LEMPTY) == NULL); } /* * Extra algorithm specific checks. * * Don't even try to check 'none' algorithms. */ if (alg != &ike_alg_integ_none.common && alg != &ike_alg_dh_none.common) { pexpect_ike_alg(alg, type->desc_check != NULL); type->desc_check(alg); } } /* * Log the final list as a pretty table. * * If FIPS, scream about. This way grepping for FIPS shows up * more information. */ libreswan_log("%s%s algorithms:", libreswan_fipsmode() ? "FIPS " : "", type->Name); FOR_EACH_IKE_ALGP(type, algp) { libreswan_log_ike_alg(" ", *algp); } } static void lswlog_ike_alg_details(struct lswlog *buf, const struct ike_alg *alg) { /* * TYPE NAME: */ { /* * Guess a suitable column width by guessing what the longest * name is. If the pexpect fails then someone has added an even * longer name! */ #if defined(USE_SHA2) size_t cw = strlen(ike_alg_integ_hmac_sha2_256_truncbug.common.fqn); #elif defined(USE_AES) size_t cw = strlen(ike_alg_encrypt_null_integ_aes_gmac.common.fqn); #else size_t cw = 20; /* stab in dark */ #endif pexpect_ike_alg(alg, cw >= strlen(alg->fqn)); lswlogf(buf, "%-*s", (int) cw, alg->fqn); } /* * IKEv1: IKE ESP AH IKEv2: IKE ESP AH */ bool v1_ike; bool v2_ike; if (ike_alg_is_ike(alg)) { v1_ike = alg->id[IKEv1_OAKLEY_ID] >= 0; v2_ike = alg->id[IKEv2_ALG_ID] >= 0; } else { v1_ike = FALSE; v2_ike = FALSE; } bool v1_esp; bool v2_esp; bool v1_ah; bool v2_ah; if (alg->algo_type == &ike_alg_hash || alg->algo_type == &ike_alg_prf) { v1_esp = v2_esp = v1_ah = v2_ah = FALSE; } else if (alg->algo_type == &ike_alg_encrypt) { v1_esp = alg->id[IKEv1_ESP_ID] >= 0; v2_esp = alg->id[IKEv2_ALG_ID] >= 0; v1_ah = FALSE; v2_ah = FALSE; } else if (alg->algo_type == &ike_alg_integ) { v1_esp = alg->id[IKEv1_ESP_ID] >= 0; v2_esp = alg->id[IKEv2_ALG_ID] >= 0; /* NULL not allowed for AH */ v1_ah = v2_ah = integ_desc(alg)->integ_ikev1_ah_transform > 0; } else if (alg->algo_type == &ike_alg_dh) { v1_esp = v1_ah = alg->id[IKEv1_ESP_ID] >= 0; v2_esp = v2_ah = alg->id[IKEv2_ALG_ID] >= 0; } else { bad_case(0); } lswlogs(buf, " IKEv1:"); lswlogs(buf, (v1_ike ? " IKE" : " ")); lswlogs(buf, (v1_esp ? " ESP" : " ")); lswlogs(buf, (v1_ah ? " AH" : " ")); lswlogs(buf, " IKEv2:"); lswlogs(buf, (v2_ike ? " IKE" : " ")); lswlogs(buf, (v2_esp ? " ESP" : " ")); lswlogs(buf, (v2_ah ? " AH" : " ")); lswlogs(buf, (alg->fips ? " FIPS" : " ")); /* * Concatenate [key,...] or {key,...} with default * marked with '*'. */ if (alg->algo_type == IKE_ALG_ENCRYPT) { const struct encrypt_desc *encr = encrypt_desc(alg); lswlogs(buf, encr->keylen_omitted ? " [" : " {"); const char *sep = ""; for (const unsigned *keyp = encr->key_bit_lengths; *keyp; keyp++) { lswlogs(buf, sep); if (*keyp == encr->keydeflen) { lswlogs(buf, "*"); } lswlogf(buf, "%d", *keyp); sep = ","; } lswlogs(buf, encr->keylen_omitted ? "]" : "}"); /* did fit */ } /* * Concatenate: alias ... */ { const char *sep = " "; FOR_EACH_IKE_ALG_NAME(alg, alg_name) { /* filter out NAME */ if (!shunk_strcaseeq(alg_name, alg->fqn)) { jam(buf, "%s"PRI_SHUNK, sep, pri_shunk(alg_name)); sep = ", "; } } } } void libreswan_log_ike_alg(const char *prefix, const struct ike_alg *alg) { LSWLOG(buf) { lswlogs(buf, prefix); lswlog_ike_alg_details(buf, alg); } } /* * Strip out any non-FIPS algorithms. * * This prevents checks being performed on algorithms that are. */ static void strip_nonfips(const struct ike_alg_type *type) { const struct ike_alg **end = type->algorithms->start; FOR_EACH_IKE_ALGP(type, algp) { const struct ike_alg *alg = *algp; /* * Check FIPS before trying to run any tests. */ if (!alg->fips) { libreswan_log("%s algorithm %s disabled; not FIPS compliant", type->Name, alg->fqn); continue; } *end++ = alg; } type->algorithms->end = end; } void init_ike_alg(void) { bool fips = libreswan_fipsmode(); /* * If needed, completely strip out non-FIPS algorithms. * Prevents inconsistency where a non-FIPS algorithm is * referring to something that's been disabled. */ if (fips) { FOR_EACH_IKE_ALG_TYPEP(typep) { strip_nonfips(*typep); } } /* * Now verify what is left. */ FOR_EACH_IKE_ALG_TYPEP(typep) { check_algorithm_table(*typep); } } libreswan-3.32/lib/libswan/ike_alg_3des.c000066400000000000000000000032731365625662500203360ustar00rootroot00000000000000/* 3des, for libreswan * * Copyright (C) 2016-2017 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include "constants.h" /* for BYTES_FOR_BITS() */ #include "ietf_constants.h" #include "ike_alg.h" #include "ike_alg_encrypt.h" #include "ike_alg_encrypt_ops.h" #include "sadb.h" const struct encrypt_desc ike_alg_encrypt_3des_cbc = { .common = { .name = "3des_cbc", .fqn = "3DES_CBC", .names = "3des,3des_cbc", .algo_type = IKE_ALG_ENCRYPT, .id = { [IKEv1_OAKLEY_ID] = OAKLEY_3DES_CBC, [IKEv1_ESP_ID] = ESP_3DES, [IKEv2_ALG_ID] = IKEv2_ENCR_3DES, }, .fips = true, }, .nss = { .mechanism = CKM_DES3_CBC, }, .enc_blocksize = DES_CBC_BLOCK_SIZE, .pad_to_blocksize = TRUE, .wire_iv_size = DES_CBC_BLOCK_SIZE, .keylen_omitted = TRUE, .keydeflen = DES_CBC_BLOCK_SIZE * 3 * BITS_PER_BYTE, .key_bit_lengths = { DES_CBC_BLOCK_SIZE * 3 * BITS_PER_BYTE, }, .encrypt_ops = &ike_alg_encrypt_nss_cbc_ops, #ifdef SADB_EALG_3DESCBC .encrypt_sadb_ealg_id = SADB_EALG_3DESCBC, #endif .encrypt_netlink_xfrm_name = "des3_ede", .encrypt_tcpdump_name = "3des", .encrypt_ike_audit_name = "3des", .encrypt_kernel_audit_name = "3DES", }; libreswan-3.32/lib/libswan/ike_alg_aes.c000066400000000000000000000275211365625662500202520ustar00rootroot00000000000000/* * Copyright (C) 2005-2007 Michael Richardson * Copyright (C) 2008-2009 Paul Wouters * Copyright (C) 2009 Avesh Agarwal * Copyright (C) 2012-2014 Paul Wouters * Copyright (C) 2013 Florian Weimer * Copyright (C) 2013 D. Hugh Redelmeier * Copyright (C) 2014-2018 Andrew Cagney * Copyright (C) 2019 Paul Wouters * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include /* for AES_BLOCK_SIZE */ #include "constants.h" /* for BYTES_FOR_BITS() */ #include "ietf_constants.h" #include "ike_alg.h" #include "ike_alg_prf_mac_ops.h" #include "ike_alg_prf_ikev1_ops.h" #include "ike_alg_prf_ikev2_ops.h" #include "ike_alg_encrypt.h" #include "ike_alg_encrypt_ops.h" #include "ike_alg_integ.h" #include "ike_alg_prf.h" #include "sadb.h" const struct encrypt_desc ike_alg_encrypt_aes_cbc = { .common = { .name = "aes", .fqn = "AES_CBC", .names = "aes,aes_cbc", .algo_type = IKE_ALG_ENCRYPT, .id = { [IKEv1_OAKLEY_ID] = OAKLEY_AES_CBC, [IKEv1_ESP_ID] = ESP_AES, [IKEv2_ALG_ID] = IKEv2_ENCR_AES_CBC, }, .fips = true, }, .nss = { .mechanism = CKM_AES_CBC, }, .enc_blocksize = AES_CBC_BLOCK_SIZE, .pad_to_blocksize = TRUE, .wire_iv_size = AES_CBC_BLOCK_SIZE, .keydeflen = AES_KEY_DEF_LEN, .key_bit_lengths = { 256, 192, 128, }, .encrypt_ops = &ike_alg_encrypt_nss_cbc_ops, #ifdef SADB_X_EALG_AESCBC .encrypt_sadb_ealg_id = SADB_X_EALG_AESCBC, #endif #ifdef SADB_X_EALG_AES .encrypt_sadb_ealg_id = SADB_X_EALG_AES, #endif .encrypt_netlink_xfrm_name = "aes", .encrypt_tcpdump_name = "aes", .encrypt_ike_audit_name = "aes", .encrypt_kernel_audit_name = "AES", }; const struct encrypt_desc ike_alg_encrypt_aes_ctr = { .common = { .name = "aes_ctr", .fqn = "AES_CTR", .names = "aesctr,aes_ctr", .algo_type = IKE_ALG_ENCRYPT, .id = { [IKEv1_OAKLEY_ID] = OAKLEY_AES_CTR, [IKEv1_ESP_ID] = ESP_AES_CTR, [IKEv2_ALG_ID] = IKEv2_ENCR_AES_CTR, }, .fips = true, }, .nss = { .mechanism = CKM_AES_CTR, }, .enc_blocksize = AES_BLOCK_SIZE, .pad_to_blocksize = FALSE, .wire_iv_size = 8, .salt_size = 4, .keydeflen = AES_KEY_DEF_LEN, .key_bit_lengths = { 256, 192, 128, }, .encrypt_ops = &ike_alg_encrypt_nss_ctr_ops, #ifdef SADB_X_EALG_AESCTR .encrypt_sadb_ealg_id = SADB_X_EALG_AESCTR, #endif .encrypt_netlink_xfrm_name = "rfc3686(ctr(aes))", .encrypt_tcpdump_name = "aes_ctr", .encrypt_ike_audit_name = "aes_ctr", .encrypt_kernel_audit_name = "AES_CTR", }; const struct encrypt_desc ike_alg_encrypt_aes_gcm_8 = { .common = { .name = "aes_gcm_8", .fqn = "AES_GCM_8", .names = "aes_gcm_8,aes_gcm_a", /* XXX: aes_gcm_16 has aes_gcm as alias */ .algo_type = IKE_ALG_ENCRYPT, .id = { [IKEv1_OAKLEY_ID] = -1, [IKEv1_ESP_ID] = ESP_AES_GCM_8, [IKEv2_ALG_ID] = IKEv2_ENCR_AES_GCM_8, }, .fips = true, }, .nss = { .mechanism = CKM_AES_GCM, }, .enc_blocksize = AES_BLOCK_SIZE, .pad_to_blocksize = FALSE, .wire_iv_size = 8, .salt_size = AES_GCM_SALT_BYTES, .keydeflen = AES_GCM_KEY_DEF_LEN, .key_bit_lengths = { 256, 192, 128, }, .aead_tag_size = 8, .encrypt_ops = &ike_alg_encrypt_nss_gcm_ops, #ifdef SADB_X_EALG_AES_GCM_ICV8 .encrypt_sadb_ealg_id = SADB_X_EALG_AES_GCM_ICV8, #endif #ifdef SADB_X_EALG_AES_GCM8 .encrypt_sadb_ealg_id = SADB_X_EALG_AES_GCM8, #endif .encrypt_netlink_xfrm_name = "rfc4106(gcm(aes))", .encrypt_tcpdump_name = "aes_gcm", .encrypt_ike_audit_name = "aes_gcm", .encrypt_kernel_audit_name = "AES_GCM_A", }; const struct encrypt_desc ike_alg_encrypt_aes_gcm_12 = { .common = { .name = "aes_gcm_12", .fqn = "AES_GCM_12", .names = "aes_gcm_12,aes_gcm_b", .algo_type = IKE_ALG_ENCRYPT, .id = { [IKEv1_OAKLEY_ID] = -1, [IKEv1_ESP_ID] = ESP_AES_GCM_12, [IKEv2_ALG_ID] = IKEv2_ENCR_AES_GCM_12, }, .fips = true, }, .nss = { .mechanism = CKM_AES_GCM, }, .enc_blocksize = AES_BLOCK_SIZE, .wire_iv_size = 8, .pad_to_blocksize = FALSE, .salt_size = AES_GCM_SALT_BYTES, .keydeflen = AEAD_AES_KEY_DEF_LEN, .key_bit_lengths = { 256, 192, 128, }, .aead_tag_size = 12, .encrypt_ops = &ike_alg_encrypt_nss_gcm_ops, #ifdef SADB_X_EALG_AES_GCM_ICV12 .encrypt_sadb_ealg_id = SADB_X_EALG_AES_GCM_ICV12, #endif #ifdef SADB_X_EALG_AES_GCM12 .encrypt_sadb_ealg_id = SADB_X_EALG_AES_GCM12, #endif .encrypt_netlink_xfrm_name = "rfc4106(gcm(aes))", .encrypt_tcpdump_name = "aes_gcm_12", .encrypt_ike_audit_name = "aes_gcm_12", .encrypt_kernel_audit_name = "AES_GCM_B", }; const struct encrypt_desc ike_alg_encrypt_aes_gcm_16 = { .common = { .name = "aes_gcm_16", .fqn = "AES_GCM_16", /* aes_gcm_8 has aes_gcm as officname */ .names = "aes_gcm,aes_gcm_16,aes_gcm_c", .algo_type = IKE_ALG_ENCRYPT, .id = { [IKEv1_OAKLEY_ID] = -1, [IKEv1_ESP_ID] = ESP_AES_GCM_16, [IKEv2_ALG_ID] = IKEv2_ENCR_AES_GCM_16, }, .fips = true, }, .nss = { .mechanism = CKM_AES_GCM, }, .enc_blocksize = AES_BLOCK_SIZE, .wire_iv_size = 8, .pad_to_blocksize = FALSE, .salt_size = AES_GCM_SALT_BYTES, .keydeflen = AEAD_AES_KEY_DEF_LEN, .key_bit_lengths = { 256, 192, 128, }, .aead_tag_size = 16, .encrypt_ops = &ike_alg_encrypt_nss_gcm_ops, #ifdef SADB_X_EALG_AES_GCM_ICV16 .encrypt_sadb_ealg_id = SADB_X_EALG_AES_GCM_ICV16, #endif #ifdef SADB_X_EALG_AES_GCM16 .encrypt_sadb_ealg_id = SADB_X_EALG_AES_GCM16, #endif .encrypt_netlink_xfrm_name = "rfc4106(gcm(aes))", .encrypt_tcpdump_name = "aes_gcm_16", .encrypt_ike_audit_name = "aes_gcm_16", .encrypt_kernel_audit_name = "AES_GCM_C", }; /* * References for AES_CCM. * * https://en.wikipedia.org/wiki/CCM_mode * https://tools.ietf.org/html/rfc4309#section-7.1 */ const struct encrypt_desc ike_alg_encrypt_aes_ccm_8 = { .common = { .name = "aes_ccm_8", .fqn = "AES_CCM_8", .names = "aes_ccm_8,aes_ccm_a", .algo_type = IKE_ALG_ENCRYPT, .id = { [IKEv1_OAKLEY_ID] = -1, [IKEv1_ESP_ID] = ESP_AES_CCM_8, [IKEv2_ALG_ID] = IKEv2_ENCR_AES_CCM_8, }, .fips = true, }, .enc_blocksize = AES_BLOCK_SIZE, .salt_size = 3, .wire_iv_size = 8, .pad_to_blocksize = FALSE, /* Only 128, 192 and 256 are supported (24 bits KEYMAT for salt not included) */ .keydeflen = AEAD_AES_KEY_DEF_LEN, .key_bit_lengths = { 256, 192, 128, }, .aead_tag_size = 8, #ifdef SADB_X_EALG_AES_CCM_ICV8 .encrypt_sadb_ealg_id = SADB_X_EALG_AES_CCM_ICV8, #endif .encrypt_netlink_xfrm_name = "rfc4309(ccm(aes))", .encrypt_tcpdump_name = "aes_ccm_8", .encrypt_ike_audit_name = "aes_ccm_8", .encrypt_kernel_audit_name = "AES_CCM_A", }; const struct encrypt_desc ike_alg_encrypt_aes_ccm_12 = { .common = { .name = "aes_ccm_12", .fqn = "AES_CCM_12", .names = "aes_ccm_12,aes_ccm_b", .algo_type = IKE_ALG_ENCRYPT, .id = { [IKEv1_OAKLEY_ID] = -1, [IKEv1_ESP_ID] = ESP_AES_CCM_12, [IKEv2_ALG_ID] = IKEv2_ENCR_AES_CCM_12, }, .fips = true, }, .enc_blocksize = AES_BLOCK_SIZE, .salt_size = 3, .wire_iv_size = 8, .pad_to_blocksize = FALSE, /* Only 128, 192 and 256 are supported (24 bits KEYMAT for salt not included) */ .keydeflen = AEAD_AES_KEY_DEF_LEN, .key_bit_lengths = { 256, 192, 128, }, .aead_tag_size = 12, #ifdef SADB_X_EALG_AES_CCM_ICV12 .encrypt_sadb_ealg_id = SADB_X_EALG_AES_CCM_ICV12, #endif .encrypt_netlink_xfrm_name = "rfc4309(ccm(aes))", .encrypt_tcpdump_name = "aes_ccm_12", .encrypt_ike_audit_name = "aes_ccm_12", .encrypt_kernel_audit_name = "AES_CCM_B", }; const struct encrypt_desc ike_alg_encrypt_aes_ccm_16 = { .common = { .name = "aes_ccm_16", .fqn = "AES_CCM_16", .names = "aes_ccm,aes_ccm_16,aes_ccm_c", .algo_type = IKE_ALG_ENCRYPT, .id = { [IKEv1_OAKLEY_ID] = -1, [IKEv1_ESP_ID] = ESP_AES_CCM_16, [IKEv2_ALG_ID] = IKEv2_ENCR_AES_CCM_16, }, .fips = true, }, .enc_blocksize = AES_BLOCK_SIZE, .salt_size = 3, .wire_iv_size = 8, .pad_to_blocksize = FALSE, /* Only 128, 192 and 256 are supported (24 bits KEYMAT for salt not included) */ .keydeflen = AEAD_AES_KEY_DEF_LEN, .key_bit_lengths = { 256, 192, 128, }, .aead_tag_size = 16, #ifdef SADB_X_EALG_AES_CCM_ICV16 .encrypt_sadb_ealg_id = SADB_X_EALG_AES_CCM_ICV16, #endif .encrypt_netlink_xfrm_name = "rfc4309(ccm(aes))", .encrypt_tcpdump_name = "aes_ccm_16", .encrypt_ike_audit_name = "aes_ccm_16", .encrypt_kernel_audit_name = "AES_CCM_C", }; #ifdef USE_PRF_AES_XCBC const struct prf_desc ike_alg_prf_aes_xcbc = { .common = { .name = "aes_xcbc", .fqn = "AES_XCBC", .names = "aes128_xcbc,aes_xcbc", .algo_type = IKE_ALG_PRF, .id = { [IKEv1_OAKLEY_ID] = -1, [IKEv1_ESP_ID] = -1, [IKEv2_ALG_ID] = IKEv2_PRF_AES128_XCBC, }, .fips = false, }, .nss = { .mechanism = CKM_AES_ECB, }, .prf_key_size = BYTES_FOR_BITS(128), .prf_output_size = BYTES_FOR_BITS(128), .prf_mac_ops = &ike_alg_prf_mac_nss_xcbc_ops, .prf_ikev1_ops = &ike_alg_prf_ikev1_mac_ops, .prf_ikev2_ops = &ike_alg_prf_ikev2_mac_ops, .prf_ike_audit_name = "aes_xcbc", }; #endif const struct integ_desc ike_alg_integ_aes_xcbc = { .common = { .name = "aes_xcbc", .fqn = "AES_XCBC_96", .names = "aes_xcbc,aes128_xcbc,aes_xcbc_96,aes128_xcbc_96", .algo_type = IKE_ALG_INTEG, .id = { [IKEv1_OAKLEY_ID] = -1, [IKEv1_ESP_ID] = AUTH_ALGORITHM_AES_XCBC, [IKEv2_ALG_ID] = IKEv2_AUTH_AES_XCBC_96, }, .fips = false, }, .integ_keymat_size = AES_XCBC_DIGEST_SIZE, .integ_output_size = AES_XCBC_DIGEST_SIZE_TRUNC, /* XXX 96 */ .integ_ikev1_ah_transform = AH_AES_XCBC_MAC, #ifdef USE_PRF_AES_XCBC .prf = &ike_alg_prf_aes_xcbc, #endif #ifdef SADB_X_AALG_AES_XCBC_MAC .integ_sadb_aalg_id = SADB_X_AALG_AES_XCBC_MAC, #endif .integ_netlink_xfrm_name = "xcbc(aes)", .integ_tcpdump_name = "aes_xcbc", .integ_ike_audit_name = "aes_xcbc", .integ_kernel_audit_name = "AES_XCBC", }; const struct integ_desc ike_alg_integ_aes_cmac = { .common = { .name = "aes_cmac", .fqn = "AES_CMAC_96", .names = "aes_cmac,aes_cmac_96", .algo_type = IKE_ALG_INTEG, .id = { [IKEv1_OAKLEY_ID] = -1, [IKEv1_ESP_ID] = AUTH_ALGORITHM_AES_CMAC_96, [IKEv2_ALG_ID] = IKEv2_AUTH_AES_CMAC_96, }, .fips = true, }, .integ_keymat_size = BYTES_FOR_BITS(128), .integ_output_size = BYTES_FOR_BITS(96), /* truncated */ .integ_ikev1_ah_transform = AH_AES_CMAC_96, #ifdef SADB_X_AALG_AES_CMAC_96 .integ_sadb_aalg_id = SADB_X_AALG_AES_CMAC_96, #endif .integ_netlink_xfrm_name = "cmac(aes)", .integ_tcpdump_name = "aes_cmac", .integ_ike_audit_name = "aes_cmac", .integ_kernel_audit_name = "AES_CMAC_96", }; /* * See: https://tools.ietf.org/html/rfc4543 */ const struct encrypt_desc ike_alg_encrypt_null_integ_aes_gmac = { .common = { .name = "aes_gmac", .fqn = "NULL_AUTH_AES_GMAC", .names = "null_auth_aes_gmac,aes_gmac", .algo_type = IKE_ALG_ENCRYPT, .id = { [IKEv1_OAKLEY_ID] = -1, [IKEv1_ESP_ID] = ESP_NULL_AUTH_AES_GMAC, [IKEv2_ALG_ID] = IKEv2_ENCR_NULL_AUTH_AES_GMAC, }, .fips = true, }, .enc_blocksize = AES_BLOCK_SIZE, .wire_iv_size = 8, .pad_to_blocksize = FALSE, .salt_size = AES_GCM_SALT_BYTES, .keydeflen = AEAD_AES_KEY_DEF_LEN, .key_bit_lengths = { 256, 192, 128, }, .aead_tag_size = 16, #ifdef SADB_X_EALG_NULL_AUTH_AES_GMAC .encrypt_sadb_ealg_id = SADB_X_EALG_NULL_AUTH_AES_GMAC, #endif #ifdef SADB_X_EALG_AESGMAC .encrypt_sadb_ealg_id = SADB_X_EALG_AESGMAC, #endif .encrypt_netlink_xfrm_name = "rfc4543(gcm(aes))", .encrypt_tcpdump_name = "NULL_AUTH_AES_GMAC", .encrypt_ike_audit_name = "NULL_AUTH_AES_GMAC", .encrypt_kernel_audit_name = "NULL_AUTH_AES_GMAC", }; libreswan-3.32/lib/libswan/ike_alg_camellia.c000066400000000000000000000057761365625662500212610ustar00rootroot00000000000000/* * Copyright (C) 2014 Paul Wouters * Copyright (C) 2016 Paul Wouters * * Based on ike_alg_camellia.c * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include "ike_alg.h" #include "ike_alg_encrypt.h" #include "ike_alg_encrypt_ops.h" #include "sadb.h" /* Camellia is a drop-in replacement for AES */ #ifndef CAMELLIA_BLOCK_SIZE # define CAMELLIA_BLOCK_SIZE 16 #endif #if CAMELLIA_BLOCK_SIZE == 32 #define CAMELLIA_KS_LENGTH 120 #define CAMELLIA_RC_LENGTH 29 #else #define CAMELLIA_KS_LENGTH (4 * CAMELLIA_BLOCK_SIZE) #define CAMELLIA_RC_LENGTH ((9 * CAMELLIA_BLOCK_SIZE) / 8 - 8) #endif typedef struct { uint32_t camellia_Nkey; // the number of words in the key input block uint32_t camellia_Nrnd; // the number of cipher rounds uint32_t camellia_e_key[CAMELLIA_KS_LENGTH]; // the encryption key schedule uint32_t camellia_d_key[CAMELLIA_KS_LENGTH]; // the decryption key schedule } camellia_context; const struct encrypt_desc ike_alg_encrypt_camellia_cbc = { .common = { .name = "camellia", .fqn = "CAMELLIA_CBC", .names = "camellia,camellia_cbc", .algo_type = IKE_ALG_ENCRYPT, .id = { [IKEv1_OAKLEY_ID] = OAKLEY_CAMELLIA_CBC, [IKEv1_ESP_ID] = ESP_CAMELLIA, [IKEv2_ALG_ID] = IKEv2_ENCR_CAMELLIA_CBC, }, }, .nss = { .mechanism = CKM_CAMELLIA_CBC, }, .enc_blocksize = CAMELLIA_BLOCK_SIZE, .pad_to_blocksize = true, .wire_iv_size = CAMELLIA_BLOCK_SIZE, .keydeflen = CAMELLIA_KEY_DEF_LEN, .key_bit_lengths = { 256, 192, 128, }, .encrypt_ops = &ike_alg_encrypt_nss_cbc_ops, #ifdef SADB_X_EALG_CAMELLIACBC .encrypt_sadb_ealg_id = SADB_X_EALG_CAMELLIACBC, #endif .encrypt_netlink_xfrm_name = "cbc(camellia)", .encrypt_tcpdump_name = "camellia", .encrypt_ike_audit_name = "camellia", .encrypt_kernel_audit_name = "CAMELLIA", }; const struct encrypt_desc ike_alg_encrypt_camellia_ctr = { .common = { .name = "camellia_ctr", .fqn = "CAMELLIA_CTR", .names = "camellia_ctr", .algo_type = IKE_ALG_ENCRYPT, .id = { [IKEv1_OAKLEY_ID] = OAKLEY_CAMELLIA_CTR, [IKEv1_ESP_ID] = ESP_CAMELLIA_CTR, /* not assigned in/for IKEv1 */ [IKEv2_ALG_ID] = IKEv2_ENCR_CAMELLIA_CTR, }, }, .enc_blocksize = CAMELLIA_BLOCK_SIZE, .pad_to_blocksize = false, .wire_iv_size = CAMELLIA_BLOCK_SIZE, .keydeflen = CAMELLIA_KEY_DEF_LEN, .key_bit_lengths = { 256, 192, 128, }, .encrypt_tcpdump_name = "camellia_ctr", .encrypt_ike_audit_name = "camellia_ctr", .encrypt_kernel_audit_name = "CAMELLIA_CTR", }; libreswan-3.32/lib/libswan/ike_alg_cast.c000066400000000000000000000032461365625662500204320ustar00rootroot00000000000000/* * Copyright (C) 2017 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include "ietf_constants.h" #include "ike_alg.h" #include "ike_alg_encrypt.h" #include "sadb.h" /* * https://tools.ietf.org/html/rfc2144.html * https://tools.ietf.org/html/rfc2451#section-2.2 * https://en.wikipedia.org/wiki/CAST-128 * * ESP_CAST is the cast5 algorithm, not cast6. Avoid padding by only * allowing 128-bit keys. */ const struct encrypt_desc ike_alg_encrypt_cast_cbc = { .common = { .name = "cast", .fqn = "CAST_CBC", .names = "cast,cast_cbc", .algo_type = IKE_ALG_ENCRYPT, .id = { [IKEv1_OAKLEY_ID] = OAKLEY_CAST_CBC, [IKEv1_ESP_ID] = ESP_CAST, [IKEv2_ALG_ID] = IKEv2_ENCR_CAST, }, }, .enc_blocksize = 8, .pad_to_blocksize = true, .wire_iv_size = 8, .keydeflen = CAST_KEY_DEF_LEN, .key_bit_lengths = { CAST_KEY_DEF_LEN, }, #ifdef SADB_X_EALG_CASTCBC .encrypt_sadb_ealg_id = SADB_X_EALG_CASTCBC, #endif #ifdef SADB_X_EALG_CAST128CBC .encrypt_sadb_ealg_id = SADB_X_EALG_CAST128CBC, #endif .encrypt_netlink_xfrm_name = "cast5", .encrypt_tcpdump_name = "cast", .encrypt_ike_audit_name = "cast", .encrypt_kernel_audit_name = "CAST", }; libreswan-3.32/lib/libswan/ike_alg_desc.c000066400000000000000000000030451365625662500204130ustar00rootroot00000000000000/* * IKE modular algorithm handling interface, for libreswan * * Copyright (C) 2017 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include "constants.h" #include "lswlog.h" #include "ike_alg.h" /* * Casts */ const struct hash_desc *hash_desc(const struct ike_alg *alg) { passert(alg == NULL || alg->algo_type == IKE_ALG_HASH); return (const struct hash_desc *)alg; } const struct prf_desc *prf_desc(const struct ike_alg *alg) { passert(alg == NULL || alg->algo_type == IKE_ALG_PRF); return (const struct prf_desc *)alg; } const struct integ_desc *integ_desc(const struct ike_alg *alg) { passert(alg == NULL || alg->algo_type == IKE_ALG_INTEG); return (const struct integ_desc *)alg; } const struct encrypt_desc *encrypt_desc(const struct ike_alg *alg) { passert(alg == NULL || alg->algo_type == IKE_ALG_ENCRYPT); return (const struct encrypt_desc *)alg; } const struct dh_desc *dh_desc(const struct ike_alg *alg) { passert(alg == NULL || alg->algo_type == IKE_ALG_DH); return (const struct dh_desc *)alg; } libreswan-3.32/lib/libswan/ike_alg_dh.c000066400000000000000000000170601365625662500200720ustar00rootroot00000000000000/* * IKE modular algorithm handling interface, for libreswan * * Copyright (C) 2016-2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include #include #include #include "constants.h" #include "lswlog.h" #include "ike_alg.h" #include "ike_alg_dh.h" #include "ike_alg_dh_ops.h" /* * Oakley group description * * See: * RFC-2409 "The Internet key exchange (IKE)" Section 6 * RFC-3526 "More Modular Exponential (MODP) Diffie-Hellman groups" */ /* magic signifier */ const struct dh_desc unset_group = { .group = 65535, /* Reserved for private use */ }; #ifdef USE_DH2 const struct dh_desc ike_alg_dh_modp1024 = { .common = { .algo_type = IKE_ALG_DH, .name = "MODP1024", .fqn = "MODP1024", .names = "modp1024,dh2", .id = { [IKEv1_OAKLEY_ID] = OAKLEY_GROUP_MODP1024, [IKEv1_ESP_ID] = OAKLEY_GROUP_MODP1024, [IKEv2_ALG_ID] = OAKLEY_GROUP_MODP1024, }, }, .group = OAKLEY_GROUP_MODP1024, .gen = MODP_GENERATOR, .modp = MODP1024_MODULUS, .bytes = BYTES_FOR_BITS(1024), .dh_ops = &ike_alg_dh_nss_modp_ops, }; #endif const struct dh_desc ike_alg_dh_modp1536 = { .common = { .algo_type = IKE_ALG_DH, .name = "MODP1536", .fqn = "MODP1536", .names = "modp1536,dh5", .id = { [IKEv1_OAKLEY_ID] = OAKLEY_GROUP_MODP1536, [IKEv1_ESP_ID] = OAKLEY_GROUP_MODP1536, [IKEv2_ALG_ID] = OAKLEY_GROUP_MODP1536, }, }, .group = OAKLEY_GROUP_MODP1536, .gen = MODP_GENERATOR, .modp = MODP1536_MODULUS, .bytes = BYTES_FOR_BITS(1536), .dh_ops = &ike_alg_dh_nss_modp_ops, }; const struct dh_desc ike_alg_dh_modp2048 = { .common = { .algo_type = IKE_ALG_DH, .name = "MODP2048", .fqn = "MODP2048", .names = "modp2048,dh14", .id = { [IKEv1_OAKLEY_ID] = OAKLEY_GROUP_MODP2048, [IKEv1_ESP_ID] = OAKLEY_GROUP_MODP2048, [IKEv2_ALG_ID] = OAKLEY_GROUP_MODP2048, }, .fips = TRUE, }, .group = OAKLEY_GROUP_MODP2048, .gen = MODP_GENERATOR, .modp = MODP2048_MODULUS, .bytes = BYTES_FOR_BITS(2048), .dh_ops = &ike_alg_dh_nss_modp_ops, }; const struct dh_desc ike_alg_dh_modp3072 = { .common = { .algo_type = IKE_ALG_DH, .name = "MODP3072", .fqn = "MODP3072", .names = "modp3072,dh15", .id = { [IKEv1_OAKLEY_ID] = OAKLEY_GROUP_MODP3072, [IKEv1_ESP_ID] = OAKLEY_GROUP_MODP3072, [IKEv2_ALG_ID] = OAKLEY_GROUP_MODP3072, }, .fips = TRUE, }, .group = OAKLEY_GROUP_MODP3072, .gen = MODP_GENERATOR, .modp = MODP3072_MODULUS, .bytes = BYTES_FOR_BITS(3072), .dh_ops = &ike_alg_dh_nss_modp_ops, }; const struct dh_desc ike_alg_dh_modp4096 = { .common = { .algo_type = IKE_ALG_DH, .name = "MODP4096", .fqn = "MODP4096", .names = "modp4096,dh16", .id = { [IKEv1_OAKLEY_ID] = OAKLEY_GROUP_MODP4096, [IKEv1_ESP_ID] = OAKLEY_GROUP_MODP4096, [IKEv2_ALG_ID] = OAKLEY_GROUP_MODP4096, }, .fips = TRUE, }, .group = OAKLEY_GROUP_MODP4096, .gen = MODP_GENERATOR, .modp = MODP4096_MODULUS, .bytes = BYTES_FOR_BITS(4096), .dh_ops = &ike_alg_dh_nss_modp_ops, }; const struct dh_desc ike_alg_dh_modp6144 = { .common = { .algo_type = IKE_ALG_DH, .name = "MODP6144", .fqn = "MODP6144", .names = "modp6144,dh17", .id = { [IKEv1_OAKLEY_ID] = OAKLEY_GROUP_MODP6144, [IKEv1_ESP_ID] = OAKLEY_GROUP_MODP6144, [IKEv2_ALG_ID] = OAKLEY_GROUP_MODP6144, }, .fips = TRUE, }, .group = OAKLEY_GROUP_MODP6144, .gen = MODP_GENERATOR, .modp = MODP6144_MODULUS, .bytes = BYTES_FOR_BITS(6144), .dh_ops = &ike_alg_dh_nss_modp_ops, }; const struct dh_desc ike_alg_dh_modp8192 = { .common = { .algo_type = IKE_ALG_DH, .name = "MODP8192", .fqn = "MODP8192", .names = "modp8192,dh18", .id = { [IKEv1_OAKLEY_ID] = OAKLEY_GROUP_MODP8192, [IKEv1_ESP_ID] = OAKLEY_GROUP_MODP8192, [IKEv2_ALG_ID] = OAKLEY_GROUP_MODP8192, }, .fips = TRUE, }, .group = OAKLEY_GROUP_MODP8192, .gen = MODP_GENERATOR, .modp = MODP8192_MODULUS, .bytes = BYTES_FOR_BITS(8192), .dh_ops = &ike_alg_dh_nss_modp_ops, }; const struct dh_desc ike_alg_dh_dh19 = { .common = { .algo_type = IKE_ALG_DH, .name = "DH19", .fqn = "DH19", .names = "dh19,ecp_256,ecp256", .id = { [IKEv1_OAKLEY_ID] = OAKLEY_GROUP_ECP_256, [IKEv1_ESP_ID] = -1, [IKEv2_ALG_ID] = OAKLEY_GROUP_ECP_256, }, .fips = TRUE, }, .group = OAKLEY_GROUP_ECP_256, .bytes = BYTES_FOR_BITS(256) * 2, .nss_oid = SEC_OID_SECG_EC_SECP256R1, .dh_ops = &ike_alg_dh_nss_ecp_ops, }; const struct dh_desc ike_alg_dh_dh20 = { .common = { .algo_type = IKE_ALG_DH, .name = "DH20", .fqn = "DH20", .names = "dh20,ecp_384,ecp384", .id = { [IKEv1_OAKLEY_ID] = OAKLEY_GROUP_ECP_384, [IKEv1_ESP_ID] = -1, [IKEv2_ALG_ID] = OAKLEY_GROUP_ECP_384, }, .fips = TRUE, }, .group = OAKLEY_GROUP_ECP_384, .bytes = BYTES_FOR_BITS(384) * 2, .nss_oid = SEC_OID_SECG_EC_SECP384R1, .dh_ops = &ike_alg_dh_nss_ecp_ops, }; const struct dh_desc ike_alg_dh_dh21 = { .common = { .algo_type = IKE_ALG_DH, .name = "DH21", .fqn = "DH21", .names = "dh21,ecp_521,ecp521", .id = { [IKEv1_OAKLEY_ID] = OAKLEY_GROUP_ECP_521, [IKEv1_ESP_ID] = -1, [IKEv2_ALG_ID] = OAKLEY_GROUP_ECP_521, }, .fips = TRUE, }, .group = OAKLEY_GROUP_ECP_521, .bytes = BYTES_FOR_BITS(521) * 2, .nss_oid = SEC_OID_SECG_EC_SECP521R1, .dh_ops = &ike_alg_dh_nss_ecp_ops, }; #ifdef USE_DH22 const struct dh_desc ike_alg_dh_dh22 = { .common = { .algo_type = IKE_ALG_DH, .name = "DH22", .fqn = "DH22", .names = "dh22", .id = { [IKEv1_OAKLEY_ID] = OAKLEY_GROUP_DH22, [IKEv1_ESP_ID] = OAKLEY_GROUP_DH22, [IKEv2_ALG_ID] = OAKLEY_GROUP_DH22, }, }, .group = OAKLEY_GROUP_DH22, .gen = MODP_GENERATOR_DH22, .modp = MODP1024_MODULUS_DH22, .bytes = BYTES_FOR_BITS(1024), .dh_ops = &ike_alg_dh_nss_modp_ops, }; #endif #ifdef USE_DH23 const struct dh_desc ike_alg_dh_dh23 = { .common = { .algo_type = IKE_ALG_DH, .name = "DH23", .fqn = "DH23", .names = "dh23", .id = { [IKEv1_OAKLEY_ID] = OAKLEY_GROUP_DH23, [IKEv1_ESP_ID] = OAKLEY_GROUP_DH23, [IKEv2_ALG_ID] = OAKLEY_GROUP_DH23, }, .fips = TRUE, }, .group = OAKLEY_GROUP_DH23, .gen = MODP_GENERATOR_DH23, .modp = MODP2048_MODULUS_DH23, .bytes = BYTES_FOR_BITS(2048), .dh_ops = &ike_alg_dh_nss_modp_ops, }; #endif #ifdef USE_DH24 const struct dh_desc ike_alg_dh_dh24 = { .common = { .algo_type = IKE_ALG_DH, .name = "DH24", .fqn = "DH24", .names = "dh24", .id = { [IKEv1_OAKLEY_ID] = OAKLEY_GROUP_DH24, [IKEv1_ESP_ID] = OAKLEY_GROUP_DH24, [IKEv2_ALG_ID] = OAKLEY_GROUP_DH24, }, .fips = TRUE, }, .group = OAKLEY_GROUP_DH24, .gen = MODP_GENERATOR_DH24, .modp = MODP2048_MODULUS_DH24, .bytes = BYTES_FOR_BITS(2048), .dh_ops = &ike_alg_dh_nss_modp_ops, }; #endif /* https://tools.ietf.org/html/rfc8031 */ #ifdef USE_DH31 const struct dh_desc ike_alg_dh_dh31 = { .common = { .algo_type = IKE_ALG_DH, .name = "DH31", .fqn = "DH31", .names = "dh31,curve25519", .id = { [IKEv1_OAKLEY_ID] = OAKLEY_GROUP_CURVE25519, [IKEv1_ESP_ID] = -1, [IKEv2_ALG_ID] = OAKLEY_GROUP_CURVE25519, }, }, .group = OAKLEY_GROUP_CURVE25519, .bytes = 32 /* octets */, .nss_oid = SEC_OID_CURVE25519, .dh_ops = &ike_alg_dh_nss_ecp_ops, }; #endif libreswan-3.32/lib/libswan/ike_alg_dh_nss_ecp_ops.c000066400000000000000000000150011365625662500224560ustar00rootroot00000000000000/* * Copyright (C) 2017 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include #include "nspr.h" #include "nss.h" #include "pk11pub.h" #include "keyhi.h" /* * In addition to EC_POINT_FORM_UNCOMPRESSED, "blapit.h" things like * AES_BLOCK_SIZE which conflicts with "ietf_constants.h". */ #if 0 #include "blapit.h" #else #define EC_POINT_FORM_UNCOMPRESSED 0x04 #endif #include "constants.h" #include "lswalloc.h" #include "lswnss.h" #include "lswlog.h" #include "ike_alg.h" #include "ike_alg_dh_ops.h" #include "crypt_symkey.h" static void nss_ecp_calc_secret(const struct dh_desc *group, SECKEYPrivateKey **privk, SECKEYPublicKey **pubk, uint8_t *ke, size_t sizeof_ke) { passert(sizeof_ke == group->bytes); /* * Get the PK11 formatted EC parameters (stored in static * data) from NSS. */ DBG(DBG_CRYPT, DBG_log("oid %d %x", group->nss_oid, group->nss_oid)); SECOidData *pk11_data = SECOID_FindOIDByTag(group->nss_oid); if (pk11_data == NULL) { PASSERT_FAIL("Lookup of OID %d for EC group %s parameters failed", group->nss_oid, group->common.name); } LSWDBGP(DBG_CRYPT, buf) { lswlogs(buf, "pk11_data->oid: "); lswlog_nss_secitem(buf, &pk11_data->oid); } /* * Need to prepend the param with its size; for moment assume * the returned value is small. If it ever gets too big will * need to re-encode the length some how. */ passert(pk11_data->oid.len < 256); SECKEYECParams *pk11_param = SECITEM_AllocItem(NULL, NULL, (2 + pk11_data->oid.len)); pk11_param->type = siBuffer, pk11_param->data[0] = SEC_ASN1_OBJECT_ID; pk11_param->data[1] = pk11_data->oid.len; memcpy(pk11_param->data + 2, pk11_data->oid.data, pk11_data->oid.len); LSWDBGP(DBG_CRYPT, buf) { lswlogs(buf, "pk11_param"); lswlog_nss_secitem(buf, pk11_param); } *privk = SECKEY_CreateECPrivateKey(pk11_param, pubk, lsw_return_nss_password_file_info()); SECITEM_FreeItem(pk11_param, PR_TRUE); if (*pubk == NULL || *privk == NULL) { LSWLOG_PASSERT(buf) { lswlogs(buf, "NSS: DH ECP private key creation failed"); lswlog_nss_error(buf); } } LSWDBGP(DBG_CRYPT, buf) { lswlogf(buf, "public keyType %d size %d publicValue@%p %d bytes public key: ", (*pubk)->keyType, (*pubk)->u.ec.size, (*pubk)->u.ec.publicValue.data, (*pubk)->u.ec.publicValue.len); lswlog_nss_secitem(buf, &(*pubk)->u.ec.publicValue); } #ifdef USE_DH31 if (group->nss_oid == SEC_OID_CURVE25519) { /* * NSS returns the plain EC X-point (see documentation * in pk11_get_EC_PointLenInBytes(), and that is what * needs to go over the wire. */ passert((*pubk)->u.ec.publicValue.len == group->bytes); DBG_log("putting NSS raw CURVE25519 public key blob on wire"); memcpy(ke, (*pubk)->u.ec.publicValue.data, group->bytes); } else { #endif passert((*pubk)->u.ec.publicValue.data[0] == EC_POINT_FORM_UNCOMPRESSED); passert((*pubk)->u.ec.publicValue.len == group->bytes + 1); memcpy(ke, (*pubk)->u.ec.publicValue.data + 1, group->bytes); #ifdef USE_DH31 } #endif } static PK11SymKey *nss_ecp_calc_shared(const struct dh_desc *group, SECKEYPrivateKey *local_privk, const SECKEYPublicKey *local_pubk, uint8_t *remote_ke, size_t sizeof_remote_ke) { SECKEYPublicKey remote_pubk = { .keyType = ecKey, .u.ec = { .DEREncodedParams = local_pubk->u.ec.DEREncodedParams, #if 0 /* * NSS, at one point, added the field * .encoding and then removed it. Building * against one version and executing against * the next will be 'bad'. */ .encoding = local_pubk->u.ec.encoding, #endif }, }; /* Allocate same space for remote key as local key */ passert(sizeof_remote_ke == group->bytes); SECITEM_AllocItem(NULL, &remote_pubk.u.ec.publicValue, local_pubk->u.ec.publicValue.len); #ifdef USE_DH31 if (group->nss_oid == SEC_OID_CURVE25519) { /* * NSS returns the plain EC X-point (see documentation * in pk11_get_EC_PointLenInBytes(), and that is what * needs to go over the wire. */ passert(sizeof_remote_ke == local_pubk->u.ec.publicValue.len); DBG_log("passing raw CURVE25519 public key blob to NSS"); memcpy(remote_pubk.u.ec.publicValue.data, remote_ke, sizeof_remote_ke); } else { #endif /* local has same keysize as remote */ passert(sizeof_remote_ke + 1 == local_pubk->u.ec.publicValue.len); remote_pubk.u.ec.publicValue.data[0] = EC_POINT_FORM_UNCOMPRESSED; memcpy(remote_pubk.u.ec.publicValue.data + 1, remote_ke, sizeof_remote_ke); #ifdef USE_DH31 } #endif /* * XXX: The "result type" can be nearly everything. Use * CKM_ECDH1_DERIVE as a marker so it is easy to spot this key * type. * * Like all calls in the NSS source code, leave KDF=CKD_NULL. * The raw key is also what CAVP tests expect. */ PK11SymKey *temp = PK11_PubDeriveWithKDF(local_privk, &remote_pubk, /* is sender */ PR_FALSE, /* secrets */ NULL, NULL, /* Operation */ CKM_ECDH1_DERIVE, /* result type */ CKM_ECDH1_DERIVE, /* operation */ CKA_DERIVE, /* key size */ 0, /* KDF */ CKD_NULL, /* shared data */ NULL, /* ctx */ lsw_return_nss_password_file_info()); DBG(DBG_CRYPT, DBG_symkey("g_ir ", "temp", temp)); /* * The key returned above doesn't play well with PK11_Derive() * - "softokn" fails to extract its value when trying to * CKM_CONCATENATE_BASE_AND_KEY - work around this by * returning a copy of the key. */ PK11SymKey *g_ir = key_from_symkey_bytes(temp, 0, sizeof_symkey(temp), HERE); DBG(DBG_CRYPT, DBG_log("NSS: extracted-key@%p from ECDH temp-key@%p (CKM_CONCATENATE_BASE_AND_KEY hack)", g_ir, temp)); release_symkey(__func__, "temp", &temp); SECITEM_FreeItem(&remote_pubk.u.ec.publicValue, PR_FALSE); return g_ir; } static void nss_ecp_check(const struct dh_desc *dhmke) { const struct ike_alg *alg = &dhmke->common; pexpect_ike_alg(alg, dhmke->nss_oid > 0); } const struct dh_ops ike_alg_dh_nss_ecp_ops = { .backend = "NSS(ECP)", .check = nss_ecp_check, .calc_secret = nss_ecp_calc_secret, .calc_shared = nss_ecp_calc_shared, }; libreswan-3.32/lib/libswan/ike_alg_dh_nss_modp_ops.c000066400000000000000000000070601365625662500226540ustar00rootroot00000000000000/* * Copyright (C) 2017 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include #include "nspr.h" #include "nss.h" #include "pk11pub.h" #include "keyhi.h" #include "constants.h" #include "lswalloc.h" #include "lswnss.h" #include "lswlog.h" #include "ike_alg.h" #include "ike_alg_dh_ops.h" #include "crypt_symkey.h" static void nss_modp_calc_secret(const struct dh_desc *group, SECKEYPrivateKey **privk, SECKEYPublicKey **pubk, uint8_t *ke, size_t sizeof_ke) { passert(sizeof_ke == group->bytes); chunk_t prime = chunk_from_hex(group->modp, group->modp); chunk_t base = chunk_from_hex(group->gen, group->gen); DBG(DBG_CRYPT, DBG_dump_hunk("NSS: Value of Prime:", prime)); DBG(DBG_CRYPT, DBG_dump_hunk("NSS: Value of base:", base)); SECKEYDHParams dh_params = { .prime = { .data = prime.ptr, .len = prime.len, }, .base = { .data = base.ptr, .len = base.len, }, }; /* * Keep trying until enough bytes are generated. Should this * be limited, and why? */ *privk = NULL; do { if (*privk != NULL) { DBG(DBG_CRYPT, DBG_log("NSS: re-generating dh keys (pubkey %d did not match %zu)", (*pubk)->u.dh.publicValue.len, group->bytes)); SECKEY_DestroyPrivateKey(*privk); SECKEY_DestroyPublicKey(*pubk); } *privk = SECKEY_CreateDHPrivateKey(&dh_params, pubk, lsw_return_nss_password_file_info()); if (*pubk == NULL || *privk == NULL) { LSWLOG_PASSERT(buf) { lswlogs(buf, "NSS: DH MODP private key creation failed"); lswlog_nss_error(buf); } } } while (group->bytes != (*pubk)->u.dh.publicValue.len); freeanychunk(prime); freeanychunk(base); memcpy(ke, (*pubk)->u.dh.publicValue.data, group->bytes); } static PK11SymKey *nss_modp_calc_shared(const struct dh_desc *group, SECKEYPrivateKey *local_privk, const SECKEYPublicKey *local_pubk, uint8_t *remote_ke, size_t sizeof_remote_ke) { DBG(DBG_CRYPT, DBG_log("Started DH shared-secret computation in NSS:")); /* * See NSS's SSL code for how this gets constructed on the * stack. */ SECKEYPublicKey remote_pubk = { .keyType = dhKey, .u.dh = { .prime = local_pubk->u.dh.prime, .base = local_pubk->u.dh.base, .publicValue = { .data = remote_ke, .len = sizeof_remote_ke, .type = siBuffer }, }, }; PK11SymKey *g_ir = PK11_PubDerive(local_privk, &remote_pubk, PR_FALSE, NULL, NULL, /* what to do */ CKM_DH_PKCS_DERIVE, /* type of result (anything) */ CKM_CONCATENATE_DATA_AND_BASE, CKA_DERIVE, group->bytes, lsw_return_nss_password_file_info()); DBG(DBG_CRYPT, DBG_symkey("newref ", "g_ir", g_ir)); return g_ir; } static void nss_modp_check(const struct dh_desc *dhmke) { const struct ike_alg *alg = &dhmke->common; pexpect_ike_alg(alg, dhmke->gen != NULL); pexpect_ike_alg(alg, dhmke->modp != NULL); } const struct dh_ops ike_alg_dh_nss_modp_ops = { .backend = "NSS(MODP)", .check = nss_modp_check, .calc_secret = nss_modp_calc_secret, .calc_shared = nss_modp_calc_shared, }; libreswan-3.32/lib/libswan/ike_alg_encrypt_chacha20_poly1305.c000066400000000000000000000032621365625662500241670ustar00rootroot00000000000000/* chacha20 poly1305 for libreswan * * Copyright (C) 2018 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include "ike_alg.h" #include "ike_alg_encrypt.h" #include "ike_alg_encrypt_ops.h" /* * See: https://tools.ietf.org/html/rfc7634#section-2 */ const struct encrypt_desc ike_alg_encrypt_chacha20_poly1305 = { .common = { .name = "chacha20_poly1305", .fqn = "CHACHA20_POLY1305", .names = "chacha20_poly1305,chacha20poly1305", .algo_type = IKE_ALG_ENCRYPT, .id = { [IKEv1_OAKLEY_ID] = -1, [IKEv1_ESP_ID] = -1, [IKEv2_ALG_ID] = IKEv2_ENCR_CHACHA20_POLY1305, }, }, .keylen_omitted = true, .enc_blocksize = 16, .pad_to_blocksize = false, .wire_iv_size = 64/*bits*/ / 8, .salt_size = 32/*bits*/ / 8, .keydeflen = 256, .key_bit_lengths = { 256, }, .aead_tag_size = 128 /*bits*/ / 8, .encrypt_netlink_xfrm_name = "rfc7539esp(chacha20,poly1305)", .encrypt_tcpdump_name = "chacha20_poly1305", .encrypt_ike_audit_name = "chacha20_poly1305", .encrypt_kernel_audit_name = "chacha20_poly1305", #ifdef CKM_NSS_CHACHA20_POLY1305 .nss = { .mechanism = CKM_NSS_CHACHA20_POLY1305, }, .encrypt_ops = &ike_alg_encrypt_nss_aead_ops, #endif }; libreswan-3.32/lib/libswan/ike_alg_encrypt_nss_aead_ops.c000066400000000000000000000073761365625662500237120ustar00rootroot00000000000000/* NSS AEAD for libreswan * * Copyright (C) 2018 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include #include "lswlog.h" #include "lswnss.h" #include "prmem.h" #include "prerror.h" #include "constants.h" #include "ike_alg.h" #include "ike_alg_encrypt_ops.h" #if defined(CKM_NSS_CHACHA20_POLY1305) static bool ike_alg_nss_aead(const struct encrypt_desc *alg, uint8_t *salt, size_t salt_size, uint8_t *wire_iv, size_t wire_iv_size, uint8_t *aad, size_t aad_size, uint8_t *text_and_tag, size_t text_size, size_t tag_size, PK11SymKey *sym_key, bool enc) { /* See pk11aeadtest.c */ bool ok = true; chunk_t salt_chunk = { .ptr = salt, .len = salt_size, }; chunk_t wire_iv_chunk = { .ptr = wire_iv, .len = wire_iv_size, }; chunk_t iv = clone_chunk_chunk(salt_chunk, wire_iv_chunk, "IV"); CK_NSS_AEAD_PARAMS aead_params = { .pNonce = iv.ptr, .ulNonceLen = iv.len, .pAAD = aad, .ulAADLen = aad_size, .ulTagLen = alg->aead_tag_size, }; SECItem param = { .type = siBuffer, .data = (void*)&aead_params, .len = sizeof aead_params, }; /* Output buffer for transformed data. */ size_t text_and_tag_size = text_size + tag_size; uint8_t *out_buf = PR_Malloc(text_and_tag_size); unsigned int out_len = 0; if (enc) { SECStatus rv = PK11_Encrypt(sym_key, alg->nss.mechanism, ¶m, out_buf, &out_len, text_and_tag_size, text_and_tag, text_size); if (rv != SECSuccess) { LSWLOG(buf) { lswlogf(buf, "NSS: AEAD encryption using %s_%u and PK11_Encrypt() failed", alg->common.fqn, PK11_GetKeyLength(sym_key) * BITS_PER_BYTE); lswlog_nss_error(buf); } ok = false; } else if (out_len != text_and_tag_size) { /* should this be a pexpect fail? */ LSWLOG_RC(RC_LOG_SERIOUS, buf) { lswlogf(buf, "NSS: AEAD encryption using %s_%u and PK11_Encrypt() failed (output length of %u not the expected %zd)", alg->common.fqn, PK11_GetKeyLength(sym_key) * BITS_PER_BYTE, out_len, text_and_tag_size); lswlog_nss_error(buf); } ok = false; } } else { SECStatus rv = PK11_Decrypt(sym_key, alg->nss.mechanism, ¶m, out_buf, &out_len, text_and_tag_size, text_and_tag, text_and_tag_size); if (rv != SECSuccess) { LSWLOG(buf) { lswlogf(buf, "NSS: AEAD decryption using %s_%u and PK11_Decrypt() failed", alg->common.fqn, PK11_GetKeyLength(sym_key) * BITS_PER_BYTE); lswlog_nss_error(buf); } ok = false; } else if (out_len != text_size) { /* should this be a pexpect fail? */ LSWLOG_RC(RC_LOG_SERIOUS, buf) { lswlogf(buf, "NSS: AEAD decryption using %s_%u and PK11_Decrypt() failed (output length of %u not the expected %zd)", alg->common.fqn, PK11_GetKeyLength(sym_key) * BITS_PER_BYTE, out_len, text_size); lswlog_nss_error(buf); } ok = false; } } memcpy(text_and_tag, out_buf, out_len); PR_Free(out_buf); freeanychunk(iv); return ok; } static void nss_aead_check(const struct encrypt_desc *encrypt) { const struct ike_alg *alg = &encrypt->common; pexpect_ike_alg(alg, encrypt->nss.mechanism > 0); } const struct encrypt_ops ike_alg_encrypt_nss_aead_ops = { .backend = "NSS(AEAD)", .check = nss_aead_check, .do_aead = ike_alg_nss_aead, }; #endif libreswan-3.32/lib/libswan/ike_alg_encrypt_nss_cbc_ops.c000066400000000000000000000067361365625662500235460ustar00rootroot00000000000000/* * Copyright (C) 2009 Avesh Agarwal * Copyright (C) 2012-2014 Paul Wouters * Copyright (C) 2013 Florian Weimer * Copyright (C) 2013 D. Hugh Redelmeier * Copyright (C) 2014 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include #include "lswlog.h" #include "prmem.h" #include "prerror.h" #include "constants.h" #include "ike_alg.h" #include "ike_alg_encrypt_ops.h" #include "lswnss.h" /* for lswlog_nss_error() */ static void ike_alg_nss_cbc(const struct encrypt_desc *alg, uint8_t *in_buf, size_t in_buf_len, PK11SymKey *symkey, uint8_t *iv, bool enc) { DBG(DBG_CRYPT, DBG_log("NSS ike_alg_nss_cbc: %s - enter", alg->common.name)); if (symkey == NULL) { PASSERT_FAIL("%s - NSS derived enc key in NULL", alg->common.name); } SECItem ivitem; ivitem.type = siBuffer; ivitem.data = iv; ivitem.len = alg->enc_blocksize; SECItem *secparam = PK11_ParamFromIV(alg->nss.mechanism, &ivitem); if (secparam == NULL) { PASSERT_FAIL("%s - Failure to set up PKCS11 param (err %d)", alg->common.name, PR_GetError()); } PK11Context *enccontext; enccontext = PK11_CreateContextBySymKey(alg->nss.mechanism, enc ? CKA_ENCRYPT : CKA_DECRYPT, symkey, secparam); if (enccontext == NULL) { LSWLOG_PASSERT(buf) { lswlogf(buf, "NSS: %s: PKCS11 context creation failure", alg->common.name); lswlog_nss_error(buf); } } /* Output buffer for transformed data. */ uint8_t *out_buf = PR_Malloc((PRUint32)in_buf_len); int out_buf_len = 0; SECStatus rv = PK11_CipherOp(enccontext, out_buf, &out_buf_len, in_buf_len, in_buf, in_buf_len); if (rv != SECSuccess) { LSWLOG_PASSERT(buf) { lswlogf(buf, "NSS: %s: PKCS11 operation failure", alg->common.name); lswlog_nss_error(buf); } } PK11_DestroyContext(enccontext, PR_TRUE); /* * Update the IV ready for the next call to this function. */ uint8_t *new_iv; if (enc) { /* * The IV for the next encryption call is the last * block of encrypted output data. */ new_iv = out_buf + out_buf_len - alg->enc_blocksize; } else { /* * The IV for the next decryption call is the last * block of the encrypted input data. */ new_iv = in_buf + in_buf_len - alg->enc_blocksize; } memcpy(iv, new_iv, alg->enc_blocksize); /* * Finally, copy the transformed data back to the buffer. Do * this after extracting the IV. */ memcpy(in_buf, out_buf, in_buf_len); PR_Free(out_buf); if (secparam != NULL) SECITEM_FreeItem(secparam, PR_TRUE); DBG(DBG_CRYPT, DBG_log("NSS ike_alg_nss_cbc: %s - exit", alg->common.name)); } static void nss_cbc_check(const struct encrypt_desc *encrypt) { const struct ike_alg *alg = &encrypt->common; pexpect_ike_alg(alg, encrypt->nss.mechanism > 0); } const struct encrypt_ops ike_alg_encrypt_nss_cbc_ops = { .backend = "NSS(CBC)", .check = nss_cbc_check, .do_crypt = ike_alg_nss_cbc, }; libreswan-3.32/lib/libswan/ike_alg_encrypt_nss_ctr_ops.c000066400000000000000000000070711365625662500236000ustar00rootroot00000000000000/* * Copyright (C) 2005-2007 Michael Richardson * Copyright (C) 2008-2009 Paul Wouters * Copyright (C) 2009 Avesh Agarwal * Copyright (C) 2012-2014 Paul Wouters * Copyright (C) 2013 Florian Weimer * Copyright (C) 2013 D. Hugh Redelmeier * Copyright (C) 2014-2016 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include #include #include #include "constants.h" #include "klips-crypto/aes_cbc.h" #include "lswlog.h" #include "ike_alg.h" #include #include #include #include #include "ike_alg_encrypt_ops.h" static void do_nss_ctr(const struct encrypt_desc *alg UNUSED, uint8_t *buf, size_t buf_len, PK11SymKey *sym_key, uint8_t *counter_block, bool encrypt) { DBG(DBG_CRYPT, DBG_log("do_aes_ctr: enter")); passert(sym_key); if (sym_key == NULL) { PASSERT_FAIL("%s", "NSS derived enc key in NULL"); } CK_AES_CTR_PARAMS counter_param; counter_param.ulCounterBits = sizeof(uint32_t) * 8;/* Per RFC 3686 */ memcpy(counter_param.cb, counter_block, sizeof(counter_param.cb)); SECItem param; param.type = siBuffer; param.data = (void*)&counter_param; param.len = sizeof(counter_param); /* Output buffer for transformed data. */ uint8_t *out_buf = PR_Malloc((PRUint32)buf_len); unsigned int out_len = 0; if (encrypt) { SECStatus rv = PK11_Encrypt(sym_key, CKM_AES_CTR, ¶m, out_buf, &out_len, buf_len, buf, buf_len); if (rv != SECSuccess) { PASSERT_FAIL("PK11_Encrypt failure (err %d)", PR_GetError()); } } else { SECStatus rv = PK11_Decrypt(sym_key, CKM_AES_CTR, ¶m, out_buf, &out_len, buf_len, buf, buf_len); if (rv != SECSuccess) { PASSERT_FAIL("PK11_Decrypt failure (err %d)", PR_GetError()); } } memcpy(buf, out_buf, buf_len); PR_Free(out_buf); /* * Finally update the counter located at the end of the * counter_block. It is incremented by 1 for every full or * partial block encoded/decoded. * * There's a portability assumption here that the IV buffer is * at least sizeof(uint32_t) (4-byte) aligned. */ uint32_t *counter = (uint32_t*)(counter_block + AES_BLOCK_SIZE - sizeof(uint32_t)); uint32_t old_counter = ntohl(*counter); size_t increment = (buf_len + AES_BLOCK_SIZE - 1) / AES_BLOCK_SIZE; uint32_t new_counter = old_counter + increment; DBG(DBG_CRYPT, DBG_log("do_aes_ctr: counter-block updated from 0x%" PRIx32 " to 0x%" PRIx32 " for %zd bytes", old_counter, new_counter, buf_len)); if (new_counter < old_counter) { /* Wrap ... */ loglog(RC_LOG_SERIOUS, "do_aes_ctr: counter wrapped"); /* what next??? */ } *counter = htonl(new_counter); DBG(DBG_CRYPT, DBG_log("do_aes_ctr: exit")); } static void nss_ctr_check(const struct encrypt_desc *alg UNUSED) { } const struct encrypt_ops ike_alg_encrypt_nss_ctr_ops = { .backend = "NSS(CTR)", .check = nss_ctr_check, .do_crypt = do_nss_ctr, }; libreswan-3.32/lib/libswan/ike_alg_encrypt_nss_gcm_ops.c000066400000000000000000000073421365625662500235570ustar00rootroot00000000000000/* NSS GCM for libreswan * * Copyright (C) 2014,2016,2018 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include #include "lswlog.h" #include "lswnss.h" #include "prmem.h" #include "prerror.h" #include "constants.h" #include "ike_alg.h" #include "ike_alg_encrypt_ops.h" static bool ike_alg_nss_gcm(const struct encrypt_desc *alg, uint8_t *salt, size_t salt_size, uint8_t *wire_iv, size_t wire_iv_size, uint8_t *aad, size_t aad_size, uint8_t *text_and_tag, size_t text_size, size_t tag_size, PK11SymKey *sym_key, bool enc) { /* See pk11gcmtest.c */ bool ok = true; chunk_t salt_chunk = { .ptr = salt, .len = salt_size, }; chunk_t wire_iv_chunk = { .ptr = wire_iv, .len = wire_iv_size, }; chunk_t iv = clone_chunk_chunk(salt_chunk, wire_iv_chunk, "IV"); CK_GCM_PARAMS gcm_params; gcm_params.pIv = iv.ptr; gcm_params.ulIvLen = iv.len; gcm_params.pAAD = aad; gcm_params.ulAADLen = aad_size; gcm_params.ulTagBits = tag_size * 8; SECItem param; param.type = siBuffer; param.data = (void*)&gcm_params; param.len = sizeof gcm_params; /* Output buffer for transformed data. */ size_t text_and_tag_size = text_size + tag_size; uint8_t *out_buf = PR_Malloc(text_and_tag_size); unsigned int out_len = 0; if (enc) { SECStatus rv = PK11_Encrypt(sym_key, alg->nss.mechanism, ¶m, out_buf, &out_len, text_and_tag_size, text_and_tag, text_size); if (rv != SECSuccess) { LSWLOG(buf) { lswlogf(buf, "NSS: AEAD encryption using %s_%u and PK11_Encrypt() failed", alg->common.fqn, PK11_GetKeyLength(sym_key) * BITS_PER_BYTE); lswlog_nss_error(buf); } ok = false; } else if (out_len != text_and_tag_size) { /* should this be a pexpect fail? */ LSWLOG_RC(RC_LOG_SERIOUS, buf) { lswlogf(buf, "NSS: AEAD encryption using %s_%u and PK11_Encrypt() failed (output length of %u not the expected %zd)", alg->common.fqn, PK11_GetKeyLength(sym_key) * BITS_PER_BYTE, out_len, text_and_tag_size); lswlog_nss_error(buf); } ok = false; } } else { SECStatus rv = PK11_Decrypt(sym_key, alg->nss.mechanism, ¶m, out_buf, &out_len, text_and_tag_size, text_and_tag, text_and_tag_size); if (rv != SECSuccess) { LSWLOG(buf) { lswlogf(buf, "NSS: AEAD decryption using %s_%u and PK11_Decrypt() failed", alg->common.fqn, PK11_GetKeyLength(sym_key) * BITS_PER_BYTE); lswlog_nss_error(buf); } ok = false; } else if (out_len != text_size) { /* should this be a pexpect fail? */ LSWLOG_RC(RC_LOG_SERIOUS, buf) { lswlogf(buf, "NSS: AEAD decryption using %s_%u and PK11_Decrypt() failed (output length of %u not the expected %zd)", alg->common.fqn, PK11_GetKeyLength(sym_key) * BITS_PER_BYTE, out_len, text_size); lswlog_nss_error(buf); } ok = false; } } memcpy(text_and_tag, out_buf, out_len); PR_Free(out_buf); freeanychunk(iv); return ok; } static void nss_gcm_check(const struct encrypt_desc *encrypt) { const struct ike_alg *alg = &encrypt->common; pexpect_ike_alg(alg, encrypt->nss.mechanism > 0); } const struct encrypt_ops ike_alg_encrypt_nss_gcm_ops = { .backend = "NSS(GCM)", .check = nss_gcm_check, .do_aead = ike_alg_nss_gcm, }; libreswan-3.32/lib/libswan/ike_alg_hash_nss_ops.c000066400000000000000000000053771365625662500221760ustar00rootroot00000000000000/* * Copyright (C) 2016-2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include "lswalloc.h" #include "lswlog.h" #include "ike_alg.h" #include "ike_alg_hash.h" #include "ike_alg_hash_ops.h" #include "crypt_symkey.h" #include "lswfips.h" #include "lswnss.h" /* * These probably fail in FIPS mode. */ struct hash_context { const char *name; PK11Context *context; const struct hash_desc *desc; }; static struct hash_context *init(const struct hash_desc *hash_desc, const char *name) { struct hash_context *hash = alloc_thing(struct hash_context, "hasher"); *hash = (struct hash_context) { .context = PK11_CreateDigestContext(hash_desc->nss.oid_tag), .name = name, .desc = hash_desc, }; passert(hash->context); SECStatus rc = PK11_DigestBegin(hash->context); passert(rc == SECSuccess); return hash; } static void digest_symkey(struct hash_context *hash, const char *name UNUSED, PK11SymKey *symkey) { passert(digest_symkey == hash->desc->hash_ops->digest_symkey); SECStatus rc = PK11_DigestKey(hash->context, symkey); passert(rc == SECSuccess); } static void digest_bytes(struct hash_context *hash, const char *name UNUSED, const uint8_t *bytes, size_t sizeof_bytes) { passert(digest_bytes == hash->desc->hash_ops->digest_bytes); SECStatus rc = PK11_DigestOp(hash->context, bytes, sizeof_bytes); passert(rc == SECSuccess); } static void final_bytes(struct hash_context **hashp, uint8_t *bytes, size_t sizeof_bytes) { passert(final_bytes == (*hashp)->desc->hash_ops->final_bytes); unsigned out_len = 0; passert(sizeof_bytes == (*hashp)->desc->hash_digest_size); SECStatus rc = PK11_DigestFinal((*hashp)->context, bytes, &out_len, sizeof_bytes); passert(rc == SECSuccess); passert(out_len <= sizeof_bytes); PK11_DestroyContext((*hashp)->context, PR_TRUE); pfree(*hashp); *hashp = NULL; } static void nss_hash_check(const struct hash_desc *hash) { const struct ike_alg *alg = &hash->common; // pexpect_ike_alg(alg, hash->common.nss_mechanism == 0); pexpect_ike_alg(alg, hash->nss.oid_tag > 0); pexpect_ike_alg(alg, hash->nss.derivation_mechanism > 0); } const struct hash_ops ike_alg_hash_nss_ops = { "NSS", nss_hash_check, init, digest_symkey, digest_bytes, final_bytes, }; libreswan-3.32/lib/libswan/ike_alg_md5.c000066400000000000000000000056671365625662500201760ustar00rootroot00000000000000/* MD5, for libreswan. * * Copyright (C) 1998-2001,2013 D. Hugh Redelmeier * Copyright (C) 2003-2008 Michael C. Richardson * Copyright (C) 2003-2010 Paul Wouters * Copyright (C) 2009-2012 Avesh Agarwal * Copyright (C) 2012-2013 Paul Wouters * Copyright (C) 2013 Florian Weimer * Copyright (C) 2016 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include "constants.h" /* for BYTES_FOR_BITS() */ #include "ietf_constants.h" #include "ike_alg.h" #include "ike_alg_hash.h" #include "ike_alg_prf.h" #include "ike_alg_hash_ops.h" #include "ike_alg_prf_mac_ops.h" #include "ike_alg_prf_ikev1_ops.h" #include "ike_alg_prf_ikev2_ops.h" #include "sadb.h" const struct hash_desc ike_alg_hash_md5 = { .common = { .name = "md5", .fqn = "MD5", .names = "md5", .algo_type = IKE_ALG_HASH, .id = { [IKEv1_OAKLEY_ID] = OAKLEY_MD5, [IKEv1_ESP_ID] = -1, [IKEv2_ALG_ID] = -1, }, }, .nss = { .oid_tag = SEC_OID_MD5, .derivation_mechanism = CKM_MD5_KEY_DERIVATION, }, .hash_digest_size = MD5_DIGEST_SIZE, .hash_block_size = 64, /* B from RFC 2104 */ .hash_ops = &ike_alg_hash_nss_ops, }; const struct prf_desc ike_alg_prf_hmac_md5 = { .common = { .name = "md5", .fqn = "HMAC_MD5", .names = "md5,hmac_md5", .algo_type = IKE_ALG_PRF, .id = { [IKEv1_OAKLEY_ID] = OAKLEY_MD5, [IKEv1_ESP_ID] = -1, [IKEv2_ALG_ID] = IKEv2_PRF_HMAC_MD5, }, }, .prf_key_size = MD5_DIGEST_SIZE, .prf_output_size = MD5_DIGEST_SIZE, .hasher = &ike_alg_hash_md5, .prf_mac_ops = &ike_alg_prf_mac_hmac_ops, .prf_ikev1_ops = &ike_alg_prf_ikev1_mac_ops, .prf_ikev2_ops = &ike_alg_prf_ikev2_mac_ops, .prf_ike_audit_name = "md5", }; const struct integ_desc ike_alg_integ_hmac_md5_96 = { .common = { .name = "md5", .fqn = "HMAC_MD5_96", .names = "md5,hmac_md5,hmac_md5_96", .algo_type = IKE_ALG_INTEG, .id = { [IKEv1_OAKLEY_ID] = OAKLEY_MD5, [IKEv1_ESP_ID] = AUTH_ALGORITHM_HMAC_MD5, [IKEv2_ALG_ID] = IKEv2_AUTH_HMAC_MD5_96, }, }, .integ_keymat_size = MD5_DIGEST_SIZE, .integ_output_size = MD5_DIGEST_SIZE_96, .integ_ikev1_ah_transform = AH_MD5, .prf = &ike_alg_prf_hmac_md5, #ifdef SADB_AALG_MD5HMAC .integ_sadb_aalg_id = SADB_AALG_MD5HMAC, #endif .integ_netlink_xfrm_name = "md5", .integ_tcpdump_name = "md5", .integ_ike_audit_name = "md5", .integ_kernel_audit_name = "HMAC_MD5", }; libreswan-3.32/lib/libswan/ike_alg_none.c000066400000000000000000000064041365625662500204360ustar00rootroot00000000000000/* * Copyright (C) 2017 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include "ietf_constants.h" #include "ike_alg.h" #include "ike_alg_encrypt.h" #include "ike_alg_integ.h" #include "ike_alg_dh.h" #include "ike_alg_dh_ops.h" #include "sadb.h" /* * References for NULL. * * https://tools.ietf.org/html/rfc2410 */ const struct encrypt_desc ike_alg_encrypt_null = { .common = { .name = "null", .fqn = "NULL", .names = "null", .algo_type = IKE_ALG_ENCRYPT, .id = { [IKEv1_OAKLEY_ID] = -1, [IKEv1_ESP_ID] = ESP_NULL, [IKEv2_ALG_ID] = IKEv2_ENCR_NULL, }, }, .enc_blocksize = 1, .wire_iv_size = 0, .pad_to_blocksize = false, .keylen_omitted = true, .keydeflen = 0, .key_bit_lengths = { 0, }, #ifdef SADB_EALG_NULL .encrypt_sadb_ealg_id = SADB_EALG_NULL, #endif .encrypt_netlink_xfrm_name = "cipher_null", .encrypt_tcpdump_name = "null", .encrypt_ike_audit_name = "null", .encrypt_kernel_audit_name = "NULL", }; /* * This gets negotiated and can ever go across the wire. */ const struct integ_desc ike_alg_integ_none = { .common = { .name = "none", .fqn = "NONE", .names = "none,null", .algo_type = IKE_ALG_INTEG, .id = { /* * Not [IKEv1_OAKLEY_ID] = AUTH_ALGORITHM_NONE * or AUTH_ALGORITHM_NULL_KAME? */ [IKEv1_OAKLEY_ID] = -1, /* * Not ESP_KAME_NULL=251? * * XXX: enabling this for ESP also enables it * for AH which isn't valid. It gets rejected * down the track. One fix would be to * finally add IKEv1_AH_ID. */ [IKEv1_ESP_ID] = AUTH_ALGORITHM_NONE, /* not NULL_KAME? */ [IKEv2_ALG_ID] = IKEv2_AUTH_NONE, }, /* * Because aes_gcm-null is valid in FIPS mode, "none" * integrity is an allowed FIPS algorithm. * * Other code gets the job of rejecting "none" when not * AEAD. */ .fips = true, }, #ifdef SADB_X_AALG_NULL /* This is from BSD's KAME */ .integ_sadb_aalg_id = SADB_X_AALG_NULL, #endif .integ_netlink_xfrm_name = "digest_null", .integ_tcpdump_name = "none", .integ_ike_audit_name = "none", .integ_kernel_audit_name = "NONE", }; /* * Blame RFC7296! */ const struct dh_desc ike_alg_dh_none = { .common = { .name = "NONE", .fqn = "NONE", .names = "none,null,dh0", .algo_type = IKE_ALG_DH, .id = { [IKEv1_OAKLEY_ID] = -1, [IKEv1_ESP_ID] = -1, [IKEv2_ALG_ID] = OAKLEY_GROUP_NONE, }, /* * IKEv2, during the initial exchanges, negotiates a * child SA without DH (or if screwing with the RFC, * DH=NONE). Either way, the result is a child state * with .ta_dh == &ike_alg_dh_none. * * Other code gets the job of rejecting "none". */ .fips = true, }, .group = OAKLEY_GROUP_NONE, /* * While patently untrue, this does keep things happy. */ .dh_ops = &ike_alg_dh_nss_modp_ops, }; libreswan-3.32/lib/libswan/ike_alg_prf_ikev1_mac_ops.c000066400000000000000000000150461365625662500230700ustar00rootroot00000000000000/* * Calculate IKEv1 prf and keying material, for libreswan * * Copyright (C) 2007 Michael C. Richardson * Copyright (C) 2010 Paul Wouters * Copyright (C) 2013 D. Hugh Redelmeier * Copyright (C) 2015-2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include "ike_alg.h" #include "ike_alg_prf_ikev1_ops.h" #include "crypt_prf.h" #include "crypt_symkey.h" /* * Compute: SKEYID = prf(Ni_b | Nr_b, g^xy) * * MUST BE THREAD-SAFE */ static PK11SymKey *signature_skeyid(const struct prf_desc *prf_desc, const chunk_t Ni, const chunk_t Nr, /*const*/ PK11SymKey *dh_secret /* NSS doesn't do const */) { /* key = Ni|Nr */ chunk_t key = clone_chunk_chunk(Ni, Nr, "key = Ni|Nr"); struct crypt_prf *prf = crypt_prf_init_hunk("SKEYID sig", prf_desc, "Ni|Nr", key); freeanychunk(key); /* seed = g^xy */ crypt_prf_update_symkey(prf, "g^xy", dh_secret); /* generate */ return crypt_prf_final_symkey(&prf); } /* * Compute: SKEYID = prf(pre-shared-key, Ni_b | Nr_b) */ static PK11SymKey *pre_shared_key_skeyid(const struct prf_desc *prf_desc, chunk_t pre_shared_key, chunk_t Ni, chunk_t Nr) { /* key = pre-shared-key */ struct crypt_prf *prf = crypt_prf_init_hunk("SKEYID psk", prf_desc, "psk", pre_shared_key); /* seed = Ni_b | Nr_b */ crypt_prf_update_hunk(prf, "Ni", Ni); crypt_prf_update_hunk(prf, "Nr", Nr); /* generate */ return crypt_prf_final_symkey(&prf); } /* * SKEYID_d = prf(SKEYID, g^xy | CKY-I | CKY-R | 0) */ static PK11SymKey *skeyid_d(const struct prf_desc *prf_desc, PK11SymKey *skeyid, PK11SymKey *dh_secret, chunk_t cky_i, chunk_t cky_r) { /* key = SKEYID */ struct crypt_prf *prf = crypt_prf_init_symkey("SKEYID_d", prf_desc, "SKEYID", skeyid); /* seed = g^xy | CKY-I | CKY-R | 0 */ crypt_prf_update_symkey(prf, "g^xy", dh_secret); crypt_prf_update_hunk(prf, "CKI_i", cky_i); crypt_prf_update_hunk(prf, "CKI_r", cky_r); crypt_prf_update_byte(prf, "0", 0); /* generate */ return crypt_prf_final_symkey(&prf); } /* * SKEYID_a = prf(SKEYID, SKEYID_d | g^xy | CKY-I | CKY-R | 1) */ static PK11SymKey *skeyid_a(const struct prf_desc *prf_desc, PK11SymKey *skeyid, PK11SymKey *skeyid_d, PK11SymKey *dh_secret, chunk_t cky_i, chunk_t cky_r) { /* key = SKEYID */ struct crypt_prf *prf = crypt_prf_init_symkey("SKEYID_a", prf_desc, "SKEYID", skeyid); /* seed = SKEYID_d | g^xy | CKY-I | CKY-R | 1 */ crypt_prf_update_symkey(prf, "SKEYID_d", skeyid_d); crypt_prf_update_symkey(prf, "g^xy", dh_secret); crypt_prf_update_hunk(prf, "CKI_i", cky_i); crypt_prf_update_hunk(prf, "CKI_r", cky_r); crypt_prf_update_byte(prf, "1", 1); /* generate */ return crypt_prf_final_symkey(&prf); } /* * SKEYID_e = prf(SKEYID, SKEYID_a | g^xy | CKY-I | CKY-R | 2) */ static PK11SymKey *skeyid_e(const struct prf_desc *prf_desc, PK11SymKey *skeyid, PK11SymKey *skeyid_a, PK11SymKey *dh_secret, chunk_t cky_i, chunk_t cky_r) { /* key = SKEYID */ struct crypt_prf *prf = crypt_prf_init_symkey("SKEYID_e", prf_desc, "SKEYID", skeyid); /* seed = SKEYID_a | g^xy | CKY-I | CKY-R | 2 */ crypt_prf_update_symkey(prf, "SKEYID_a", skeyid_a); crypt_prf_update_symkey(prf, "g^xy", dh_secret); crypt_prf_update_hunk(prf, "CKI_i", cky_i); crypt_prf_update_hunk(prf, "CKI_r", cky_r); crypt_prf_update_byte(prf, "2", 2); /* generate */ return crypt_prf_final_symkey(&prf); } static PK11SymKey *appendix_b_keymat_e(const struct prf_desc *prf_desc, const struct encrypt_desc *encrypter, PK11SymKey *skeyid_e, unsigned required_keymat) { if (sizeof_symkey(skeyid_e) >= required_keymat) { return encrypt_key_from_symkey_bytes("keymat", encrypter, 0, required_keymat, skeyid_e, HERE); } /* K1 = prf(skeyid_e, 0) */ PK11SymKey *keymat; { struct crypt_prf *prf = crypt_prf_init_symkey("appendix_b", prf_desc, "SKEYID_e", skeyid_e); crypt_prf_update_byte(prf, "0", 0); keymat = crypt_prf_final_symkey(&prf); } /* make a reference to keep things easy */ PK11SymKey *old_k = reference_symkey(__func__, "old_k:1", keymat); while (sizeof_symkey(keymat) < required_keymat) { /* Kn = prf(skeyid_e, Kn-1) */ struct crypt_prf *prf = crypt_prf_init_symkey("Kn", prf_desc, "SKEYID_e", skeyid_e); crypt_prf_update_symkey(prf, "old_k", old_k); PK11SymKey *new_k = crypt_prf_final_symkey(&prf); append_symkey_symkey(&keymat, new_k); release_symkey(__func__, "old_k:N", &old_k); old_k = new_k; } release_symkey(__func__, "old_k:final", &old_k); PK11SymKey *cryptkey = encrypt_key_from_symkey_bytes("cryptkey", encrypter, 0, required_keymat, keymat, HERE); release_symkey(__func__, "keymat", &keymat); return cryptkey; } static chunk_t section_5_keymat(const struct prf_desc *prf, PK11SymKey *SKEYID_d, PK11SymKey *g_xy, uint8_t protocol, shunk_t SPI, chunk_t Ni_b, chunk_t Nr_b, unsigned required_keymat) { chunk_t keymat = empty_chunk; struct crypt_mac keymat_n = empty_mac; do { struct crypt_prf *ctx = crypt_prf_init_symkey("KEYMAT K+1", prf, "SKEYID_d", SKEYID_d); if (keymat_n.len != 0) { crypt_prf_update_hunk(ctx, "Kn", keymat_n); } /* this could be pre-computed */ if (g_xy != NULL) { crypt_prf_update_symkey(ctx, "g^xy", g_xy); } crypt_prf_update_thing(ctx, "protocol", protocol); crypt_prf_update_hunk(ctx, "SPI", SPI); crypt_prf_update_hunk(ctx, "Ni", Ni_b); crypt_prf_update_hunk(ctx, "Nr", Nr_b); /* finally */ keymat_n = crypt_prf_final_mac(&ctx, NULL); /* gro */ append_chunk_hunk("KEYMAT += KEYMAT_n", &keymat, keymat_n); } while (keymat.len < required_keymat); return keymat; } const struct prf_ikev1_ops ike_alg_prf_ikev1_mac_ops = { .backend = "native", .signature_skeyid = signature_skeyid, .pre_shared_key_skeyid = pre_shared_key_skeyid, .skeyid_d = skeyid_d, .skeyid_a = skeyid_a, .skeyid_e = skeyid_e, .appendix_b_keymat_e = appendix_b_keymat_e, .section_5_keymat = section_5_keymat, }; libreswan-3.32/lib/libswan/ike_alg_prf_ikev1_nss_ops.c000066400000000000000000000177221365625662500231360ustar00rootroot00000000000000/* * Calculate IKEv1 prf and keying material, for libreswan * * Copyright (C) 2007 Michael C. Richardson * Copyright (C) 2010 Paul Wouters * Copyright (C) 2013 D. Hugh Redelmeier * Copyright (C) 2015-2019 Andrew Cagney * Copyright (C) 2015-2020 Andrew Cagney * Copyright (C) 2020 Paul Wouters * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include "ike_alg.h" #include "ike_alg_prf_ikev1_ops.h" #include "crypt_symkey.h" #include "lswlog.h" /* * Compute: SKEYID = prf(Ni_b | Nr_b, g^xy) * * MUST BE THREAD-SAFE */ static PK11SymKey *signature_skeyid(const struct prf_desc *prf_desc, const chunk_t Ni, const chunk_t Nr, /*const*/ PK11SymKey *dh_secret /* NSS doesn't do const */) { CK_NSS_IKE_PRF_DERIVE_PARAMS ike_prf_params = { .prfMechanism = prf_desc->nss.mechanism, .bDataAsKey = CK_TRUE, .bRekey = CK_FALSE, .pNi = Ni.ptr, .ulNiLen = Ni.len, .pNr = Nr.ptr, .ulNrLen = Nr.len, }; SECItem params = { .data = (unsigned char *)&ike_prf_params, .len = sizeof(ike_prf_params), }; return crypt_derive(dh_secret, CKM_NSS_IKE_PRF_DERIVE, ¶ms, "skeyid", CKM_NSS_IKE1_PRF_DERIVE, CKA_DERIVE, /*key,flags*/ 0, 0, HERE); } /* * Compute: SKEYID = prf(pre-shared-key, Ni_b | Nr_b) */ static PK11SymKey *pre_shared_key_skeyid(const struct prf_desc *prf_desc, chunk_t pre_shared_key, chunk_t Ni, chunk_t Nr) { PK11SymKey *psk = prf_key_from_hunk("psk", prf_desc, pre_shared_key); PK11SymKey *skeyid; if (psk == NULL) { return NULL; } CK_NSS_IKE_PRF_DERIVE_PARAMS ike_prf_params = { .prfMechanism = prf_desc->nss.mechanism, .bDataAsKey = CK_FALSE, .bRekey = CK_FALSE, .pNi = Ni.ptr, .ulNiLen = Ni.len, .pNr = Nr.ptr, .ulNrLen = Nr.len, }; SECItem params = { .data = (unsigned char *)&ike_prf_params, .len = sizeof(ike_prf_params), }; skeyid = crypt_derive(psk, CKM_NSS_IKE_PRF_DERIVE, ¶ms, "skeyid", CKM_NSS_IKE1_PRF_DERIVE, CKA_DERIVE, /*key_size*/0, /*flags*/0, HERE); release_symkey("SKEYID psk", "psk", &psk); return skeyid; } /* * SKEYID_d = prf(SKEYID, g^xy | CKY-I | CKY-R | 0) */ static PK11SymKey *skeyid_d(const struct prf_desc *prf_desc, PK11SymKey *skeyid, PK11SymKey *dh_secret, chunk_t cky_i, chunk_t cky_r) { CK_NSS_IKE1_PRF_DERIVE_PARAMS ike1_prf_params = { .prfMechanism = prf_desc->nss.mechanism, .bHasPrevKey = CK_FALSE, .hKeygxy = PK11_GetSymKeyHandle(dh_secret), .pCKYi = cky_i.ptr, .ulCKYiLen = cky_i.len, .pCKYr = cky_r.ptr, .ulCKYrLen = cky_r.len, .keyNumber = 0, }; SECItem params = { .data = (unsigned char *)&ike1_prf_params, .len = sizeof(ike1_prf_params), }; return crypt_derive(skeyid, CKM_NSS_IKE1_PRF_DERIVE, ¶ms, "skeyid_d", CKM_EXTRACT_KEY_FROM_KEY, CKA_DERIVE, /*key-size*/0, /*flags*/0, HERE); } /* * SKEYID_a = prf(SKEYID, SKEYID_d | g^xy | CKY-I | CKY-R | 1) */ static PK11SymKey *skeyid_a(const struct prf_desc *prf_desc, PK11SymKey *skeyid, PK11SymKey *skeyid_d, PK11SymKey *dh_secret, chunk_t cky_i, chunk_t cky_r) { CK_NSS_IKE1_PRF_DERIVE_PARAMS ike1_prf_params = { .prfMechanism = prf_desc->nss.mechanism, .bHasPrevKey = CK_TRUE, .hKeygxy = PK11_GetSymKeyHandle(dh_secret), .hPrevKey = PK11_GetSymKeyHandle(skeyid_d), .pCKYi = cky_i.ptr, .ulCKYiLen = cky_i.len, .pCKYr = cky_r.ptr, .ulCKYrLen = cky_r.len, .keyNumber = 1, }; SECItem params = { .data = (unsigned char *)&ike1_prf_params, .len = sizeof(ike1_prf_params), }; return crypt_derive(skeyid, CKM_NSS_IKE1_PRF_DERIVE, ¶ms, "skeyid_a", CKM_EXTRACT_KEY_FROM_KEY, CKA_DERIVE, /*key-size*/0, /*flags*/0, HERE); } /* * SKEYID_e = prf(SKEYID, SKEYID_a | g^xy | CKY-I | CKY-R | 2) */ static PK11SymKey *skeyid_e(const struct prf_desc *prf_desc, PK11SymKey *skeyid, PK11SymKey *skeyid_a, PK11SymKey *dh_secret, chunk_t cky_i, chunk_t cky_r) { CK_NSS_IKE1_PRF_DERIVE_PARAMS ike1_prf_params = { .prfMechanism = prf_desc->nss.mechanism, .bHasPrevKey = CK_TRUE, .hKeygxy = PK11_GetSymKeyHandle(dh_secret), .hPrevKey = PK11_GetSymKeyHandle(skeyid_a), .pCKYi = cky_i.ptr, .ulCKYiLen = cky_i.len, .pCKYr = cky_r.ptr, .ulCKYrLen = cky_r.len, .keyNumber = 2, }; SECItem params = { .data = (unsigned char *)&ike1_prf_params, .len = sizeof(ike1_prf_params), }; return crypt_derive(skeyid, CKM_NSS_IKE1_PRF_DERIVE, ¶ms, "skeyid_e", CKM_EXTRACT_KEY_FROM_KEY, CKA_DERIVE, /*key-size*/0, /*flags*/0, HERE); } static PK11SymKey *appendix_b_keymat_e(const struct prf_desc *prf, const struct encrypt_desc *encrypter, PK11SymKey *skeyid_e, unsigned required_keymat) { #ifdef USE_NSS_PRF CK_MECHANISM_TYPE mechanism = prf->nss.mechanism; CK_MECHANISM_TYPE target = encrypter->nss.mechanism; SECItem params = { .data = (unsigned char *)&mechanism, .len = sizeof(mechanism), }; /* for when ENCRYPTER isn't NSS */ if (target == 0) target = CKM_EXTRACT_KEY_FROM_KEY; return crypt_derive(skeyid_e, CKM_NSS_IKE1_APP_B_PRF_DERIVE, ¶ms, "keymat_e", target, CKA_ENCRYPT, /*key-size*/required_keymat, /*flags*/CKF_DECRYPT|CKF_ENCRYPT, HERE); #else DBG_log("using MAC ops for %s", __func__); return ike_alg_prf_ikev1_mac_ops.appendix_b_keymat_e(prf, encrypter, skeyid_e, required_keymat); #endif } static chunk_t section_5_keymat(const struct prf_desc *prf, PK11SymKey *SKEYID_d, PK11SymKey *g_xy, uint8_t protocol, shunk_t SPI, chunk_t Ni_b, chunk_t Nr_b, unsigned required_keymat) { #ifdef USE_NSS_PRF size_t extra_size = (1/* protocol*/ + SPI.len + Ni_b.len + Nr_b.len); uint8_t *extra = alloc_things(uint8_t, extra_size, "protocol | SPI | Ni_b | Nr_b"); uint8_t *p = extra; *p++ = protocol; memcpy(p, SPI.ptr, SPI.len); p += SPI.len; memcpy(p, Ni_b.ptr, Ni_b.len); p += Ni_b.len; memcpy(p, Nr_b.ptr, Nr_b.len); p += Nr_b.len; passert(extra + extra_size == p); /* * If this fails to compile, a newer nss version is needed. * Alternatively compile with USE_NSS_PRF=false. * But then for FIPS, compiling with USE_FIPSCHECK is needed again. */ CK_NSS_IKE1_APP_B_PRF_DERIVE_PARAMS dparams = { .prfMechanism = prf->nss.mechanism, .bHasKeygxy = g_xy != NULL, .hKeygxy = g_xy != NULL ? PK11_GetSymKeyHandle(g_xy) : 0, .pExtraData = extra, /* protocol | SPI | Ni_b | Nr_b */ .ulExtraDataLen = extra_size, }; SECItem params = { .data = (unsigned char *)&dparams, .len = sizeof(dparams), }; PK11SymKey *key = crypt_derive(SKEYID_d, CKM_NSS_IKE1_APP_B_PRF_DERIVE, ¶ms, "section_5_keymat", CKM_EXTRACT_KEY_FROM_KEY, CKA_ENCRYPT, /*key-size*/required_keymat, /*flags*/CKF_DECRYPT|CKF_ENCRYPT, HERE); chunk_t keymat = chunk_from_symkey("section 5 keymat", key); release_symkey("section 5 keymat", "keymat", &key); pfree(extra); return keymat; #else DBG_log("using MAC ops for %s", __func__); return ike_alg_prf_ikev1_mac_ops.section_5_keymat(prf, SKEYID_d, g_xy, protocol, SPI, Ni_b, Nr_b, required_keymat); #endif } const struct prf_ikev1_ops ike_alg_prf_ikev1_nss_ops = { #ifdef USE_NSS_PRF .backend = "NSS", #else .backend = "NSS+native", #endif .signature_skeyid = signature_skeyid, .pre_shared_key_skeyid = pre_shared_key_skeyid, .skeyid_d = skeyid_d, .skeyid_a = skeyid_a, .skeyid_e = skeyid_e, .appendix_b_keymat_e = appendix_b_keymat_e, .section_5_keymat = section_5_keymat, }; libreswan-3.32/lib/libswan/ike_alg_prf_ikev2_mac_ops.c000066400000000000000000000204421365625662500230650ustar00rootroot00000000000000/* * Calculate IKEv2 prf and keying material, for libreswan * * Copyright (C) 2007 Michael C. Richardson * Copyright (C) 2010 Paul Wouters * Copyright (C) 2013-2019 D. Hugh Redelmeier * Copyright (C) 2015-2019 Andrew Cagney * Copyright (C) 2019 Paul Wouters * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * This code was developed with the support of Redhat corporation. * */ #include "ike_alg.h" #include "ike_alg_prf_ikev2_ops.h" #include "lswlog.h" #include "crypt_prf.h" #include "crypt_symkey.h" #include "lswfips.h" /* * IKEv2 - RFC4306 2.14 SKEYSEED - calculation. */ static PK11SymKey *prfplus(const struct prf_desc *prf_desc, PK11SymKey *key, PK11SymKey *seed, size_t required_keymat) { uint8_t count = 1; /* T1(prfplus) = prf(KEY, SEED|1) */ PK11SymKey *result; { struct crypt_prf *prf = crypt_prf_init_symkey("prf+0", prf_desc, "key", key); crypt_prf_update_symkey(prf, "seed", seed); crypt_prf_update_byte(prf, "1++", count++); result = crypt_prf_final_symkey(&prf); } /* make a copy to keep things easy */ PK11SymKey *old_t = reference_symkey(__func__, "old_t[1]", result); while (sizeof_symkey(result) < required_keymat) { /* Tn = prf(KEY, Tn-1|SEED|n) */ struct crypt_prf *prf = crypt_prf_init_symkey("prf+N", prf_desc, "key", key); crypt_prf_update_symkey(prf, "old_t", old_t); crypt_prf_update_symkey(prf, "seed", seed); crypt_prf_update_byte(prf, "N++", count++); PK11SymKey *new_t = crypt_prf_final_symkey(&prf); append_symkey_symkey(&result, new_t); release_symkey(__func__, "old_t[N]", &old_t); old_t = new_t; } release_symkey(__func__, "old_t[final]", &old_t); return result; } /* * SKEYSEED = prf(Ni | Nr, g^ir) * * */ static PK11SymKey *ike_sa_skeyseed(const struct prf_desc *prf_desc, const chunk_t Ni, const chunk_t Nr, PK11SymKey *dh_secret) { /* * 2.14. Generating Keying Material for the IKE SA * * Ni and Nr are the nonces, stripped of any headers. For * historical backward-compatibility reasons, there are two PRFs that * are treated specially in this calculation. If the negotiated PRF is * AES-XCBC-PRF-128 [AESXCBCPRF128] or AES-CMAC-PRF-128 [AESCMACPRF128], * only the first 64 bits of Ni and the first 64 bits of Nr are used in * calculating SKEYSEED, but all the bits are used for input to the prf+ * function. */ chunk_t key; const char *key_name; switch (prf_desc->common.id[IKEv2_ALG_ID]) { case IKEv2_PRF_AES128_CMAC: case IKEv2_PRF_AES128_XCBC: { chunk_t Ni64 = chunk(Ni.ptr, BYTES_FOR_BITS(64)); chunk_t Nr64 = chunk(Nr.ptr, BYTES_FOR_BITS(64)); key = clone_chunk_chunk(Ni64, Nr64, "key = Ni|Nr"); key_name = "Ni[0:63] | Nr[0:63]"; break; } default: key = clone_chunk_chunk(Ni, Nr, "key = Ni|Nr"); key_name = "Ni | Nr"; break; } struct crypt_prf *prf = crypt_prf_init_hunk("SKEYSEED = prf(Ni | Nr, g^ir)", prf_desc, key_name, key); freeanychunk(key); if (prf == NULL) { libreswan_log("failed to create IKEv2 PRF for computing SKEYSEED = prf(Ni | Nr, g^ir)"); return NULL; } /* seed = g^ir */ crypt_prf_update_symkey(prf, "g^ir", dh_secret); /* generate */ return crypt_prf_final_symkey(&prf); } /* * SKEYSEED = prf(SK_d (old), g^ir (new) | Ni | Nr) */ static PK11SymKey *ike_sa_rekey_skeyseed(const struct prf_desc *prf_desc, PK11SymKey *SK_d_old, PK11SymKey *new_dh_secret, const chunk_t Ni, const chunk_t Nr) { /* key = SK_d (old) */ struct crypt_prf *prf = crypt_prf_init_symkey("ike sa rekey skeyseed", prf_desc, "SK_d (old)", SK_d_old); if (prf == NULL) { libreswan_log("failed to create IKEv2 PRF for computing SKEYSEED = prf(SK_d (old), g^ir (new) | Ni | Nr)"); return NULL; } /* seed: g^ir (new) | Ni | Nr) */ crypt_prf_update_symkey(prf, "g^ir (new)", new_dh_secret); crypt_prf_update_hunk(prf, "Ni", Ni); crypt_prf_update_hunk(prf, "Nr", Nr); /* generate */ return crypt_prf_final_symkey(&prf); } /* * Compute: prf+ (SKEYSEED, Ni | Nr | SPIi | SPIr) */ static PK11SymKey *ike_sa_keymat(const struct prf_desc *prf_desc, PK11SymKey *skeyseed, const chunk_t Ni, const chunk_t Nr, shunk_t SPIi, shunk_t SPIr, size_t required_bytes) { PK11SymKey *data = symkey_from_hunk("data=Ni", Ni); append_symkey_hunk("data+=Nr", &data, Nr); append_symkey_hunk("data+=SPIi", &data, SPIi); append_symkey_hunk("data+=SPIr", &data, SPIr); PK11SymKey *result = prfplus(prf_desc, skeyseed, data, required_bytes); release_symkey(__func__, "data", &data); return result; } /* * Compute: prf+(SK_d, [ g^ir (new) | ] Ni | Nr) */ static PK11SymKey *child_sa_keymat(const struct prf_desc *prf_desc, PK11SymKey *SK_d, PK11SymKey *new_dh_secret, const chunk_t Ni, const chunk_t Nr, size_t required_bytes) { if (required_bytes == 0) { /* * For instance esp=null-none. Caller should * interpret NULL to mean empty (NSS doesn't create * zero length keys). */ dbg("No CHILD SA KEMAT is required"); return NULL; } PK11SymKey *data; if (new_dh_secret == NULL) { data = symkey_from_hunk("data=Ni", Ni); append_symkey_hunk("data+=Nr", &data, Nr); } else { /* make a local "readonly copy" and manipulate that */ data = reference_symkey("prf", "data", new_dh_secret); append_symkey_hunk("data+=Ni", &data, Ni); append_symkey_hunk("data+=Nr", &data, Nr); } PK11SymKey *result = prfplus(prf_desc, SK_d, data, required_bytes); release_symkey(__func__, "data", &data); return result; } static struct crypt_mac psk_auth(const struct prf_desc *prf_desc, chunk_t pss, chunk_t first_packet, chunk_t nonce, const struct crypt_mac *id_hash) { /* calculate inner prf */ PK11SymKey *prf_psk; { struct crypt_prf *prf = crypt_prf_init_hunk(" = prf(,\"Key Pad for IKEv2\")", prf_desc, "shared secret", pss); if (prf == NULL) { if (libreswan_fipsmode()) { PASSERT_FAIL("FIPS: failure creating %s PRF context for digesting PSK", prf_desc->common.name); } loglog(RC_LOG_SERIOUS, "failure creating %s PRF context for digesting PSK", prf_desc->common.name); return empty_mac; } static const char psk_key_pad_str[] = "Key Pad for IKEv2"; /* RFC 4306 2:15 */ crypt_prf_update_bytes(prf, psk_key_pad_str, /* name */ psk_key_pad_str, sizeof(psk_key_pad_str) - 1); prf_psk = crypt_prf_final_symkey(&prf); } /* calculate outer prf */ struct crypt_mac signed_octets; { struct crypt_prf *prf = crypt_prf_init_symkey(" = prf(, )", prf_desc, "", prf_psk); /* * For the responder, the octets to be signed start * with the first octet of the first SPI in the header * of the second message and end with the last octet * of the last payload in the second message. * Appended to this (for purposes of computing the * signature) are the initiator's nonce Ni (just the * value, not the payload containing it), and the * value prf(SK_pr,IDr') where IDr' is the responder's * ID payload excluding the fixed header. Note that * neither the nonce Ni nor the value prf(SK_pr,IDr') * are transmitted. */ crypt_prf_update_hunk(prf, "first-packet", first_packet); crypt_prf_update_hunk(prf, "nonce", nonce); crypt_prf_update_hunk(prf, "hash", *id_hash); signed_octets = crypt_prf_final_mac(&prf, NULL); } release_symkey(__func__, "prf-psk", &prf_psk); return signed_octets; } const struct prf_ikev2_ops ike_alg_prf_ikev2_mac_ops = { .backend = "native", .prfplus = prfplus, .ike_sa_skeyseed = ike_sa_skeyseed, .ike_sa_rekey_skeyseed = ike_sa_rekey_skeyseed, .ike_sa_keymat = ike_sa_keymat, .child_sa_keymat = child_sa_keymat, .psk_auth = psk_auth, }; libreswan-3.32/lib/libswan/ike_alg_prf_ikev2_nss_ops.c000066400000000000000000000171421365625662500231330ustar00rootroot00000000000000/* * Calculate IKEv2 prf and keying material, for libreswan * * Copyright (C) 2007 Michael C. Richardson * Copyright (C) 2010 Paul Wouters * Copyright (C) 2013-2019 D. Hugh Redelmeier * Copyright (C) 2015-2019 Andrew Cagney * Copyright (C) 2019 Paul Wouters * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * This code was developed with the support of Redhat corporation. * */ #include "ike_alg.h" #include "ike_alg_prf_ikev2_ops.h" #include "lswlog.h" #include "crypt_prf.h" #include "crypt_symkey.h" #include "lswfips.h" /* * IKEv2 - RFC4306 2.14 SKEYSEED - calculation. */ static PK11SymKey *prfplus_key_data(const char *target_name, const struct prf_desc *prf_desc, PK11SymKey *key, PK11SymKey *seed_key, chunk_t seed_data, size_t required_keymat) { CK_NSS_IKE_PRF_PLUS_DERIVE_PARAMS ike_prf_plus_params = { .pSeedData = seed_data.ptr, .ulSeedDataLen = seed_data.len, .prfMechanism = prf_desc->nss.mechanism, }; if (seed_key == NULL) { ike_prf_plus_params.bHasSeedKey = CK_FALSE; } else { ike_prf_plus_params.bHasSeedKey = CK_TRUE; ike_prf_plus_params.hSeedKey = PK11_GetSymKeyHandle(seed_key); } SECItem params = { .data = (unsigned char *)&ike_prf_plus_params, .len = sizeof(ike_prf_plus_params), }; return crypt_derive(key, CKM_NSS_IKE_PRF_PLUS_DERIVE, ¶ms, target_name, CKM_EXTRACT_KEY_FROM_KEY, CKA_DERIVE, /*keysize*/required_keymat, /*flags*/0, HERE); } static PK11SymKey *prfplus(const struct prf_desc *prf_desc, PK11SymKey *key, PK11SymKey *seed, size_t required_keymat) { return prfplus_key_data("prfplus", prf_desc, key, seed, empty_chunk, required_keymat); } /* * SKEYSEED = prf(Ni | Nr, g^ir) * * */ static PK11SymKey *ike_sa_skeyseed(const struct prf_desc *prf_desc, const chunk_t Ni, const chunk_t Nr, PK11SymKey *dh_secret) { int is_aes_prf = 0; switch (prf_desc->common.id[IKEv2_ALG_ID]) { case IKEv2_PRF_AES128_CMAC: case IKEv2_PRF_AES128_XCBC: is_aes_prf = 1; } CK_NSS_IKE_PRF_DERIVE_PARAMS ike_prf_params = { .prfMechanism = prf_desc->nss.mechanism, .bDataAsKey = CK_TRUE, .bRekey = CK_FALSE, .pNi = Ni.ptr, .ulNiLen = is_aes_prf ? BYTES_FOR_BITS(64) : Ni.len, .pNr = Nr.ptr, .ulNrLen = is_aes_prf ? BYTES_FOR_BITS(64) : Nr.len, }; SECItem params = { .data = (unsigned char *)&ike_prf_params, .len = sizeof(ike_prf_params), }; return crypt_derive(dh_secret, CKM_NSS_IKE_PRF_DERIVE, ¶ms, "skeyseed", CKM_NSS_IKE_PRF_PLUS_DERIVE, CKA_DERIVE, /*keysize*/0, /*flags*/0, HERE); } /* * SKEYSEED = prf(SK_d (old), g^ir (new) | Ni | Nr) */ static PK11SymKey *ike_sa_rekey_skeyseed(const struct prf_desc *prf_desc, PK11SymKey *SK_d_old, PK11SymKey *new_dh_secret, const chunk_t Ni, const chunk_t Nr) { CK_NSS_IKE_PRF_DERIVE_PARAMS ike_prf_params = { .prfMechanism = prf_desc->nss.mechanism, .bDataAsKey = CK_FALSE, .bRekey = CK_TRUE, .hNewKey = PK11_GetSymKeyHandle(new_dh_secret), .pNi = Ni.ptr, .ulNiLen = Ni.len, .pNr = Nr.ptr, .ulNrLen = Nr.len, }; SECItem params = { .data = (unsigned char *)&ike_prf_params, .len = sizeof(ike_prf_params), }; return crypt_derive(SK_d_old, CKM_NSS_IKE_PRF_DERIVE, ¶ms, "skeyseed", CKM_NSS_IKE_PRF_PLUS_DERIVE, CKA_DERIVE, /*key-size*/0, /*flags*/0, HERE); } /* * Compute: prf+ (SKEYSEED, Ni | Nr | SPIi | SPIr) */ static PK11SymKey *ike_sa_keymat(const struct prf_desc *prf_desc, PK11SymKey *skeyseed, const chunk_t Ni, const chunk_t Nr, shunk_t SPIi, shunk_t SPIr, size_t required_bytes) { PK11SymKey *prf_plus; chunk_t seed_data = clone_chunk_chunk(Ni, Nr, "seed_data = Ni || Nr"); append_chunk_hunk("seed_data = Nir || SPIi", &seed_data, SPIi); append_chunk_hunk("seed_data = Nir || SPIir", &seed_data, SPIr); prf_plus = prfplus_key_data("keymat", prf_desc, skeyseed, NULL, seed_data, required_bytes); freeanychunk(seed_data); return prf_plus; } /* * Compute: prf+(SK_d, [ g^ir (new) | ] Ni | Nr) */ static PK11SymKey *child_sa_keymat(const struct prf_desc *prf_desc, PK11SymKey *SK_d, PK11SymKey *new_dh_secret, const chunk_t Ni, const chunk_t Nr, size_t required_bytes) { chunk_t seed_data; PK11SymKey *prf_plus; seed_data = clone_chunk_chunk(Ni, Nr, "seed_data = Ni || Nr"); prf_plus = prfplus_key_data("keymat", prf_desc, SK_d, new_dh_secret, seed_data, required_bytes); freeanychunk(seed_data); return prf_plus; } static struct crypt_mac psk_auth(const struct prf_desc *prf_desc, chunk_t pss, chunk_t first_packet, chunk_t nonce, const struct crypt_mac *id_hash) { PK11SymKey *prf_psk; { static const char psk_key_pad_str[] = "Key Pad for IKEv2"; /* RFC 4306 2:15 */ CK_MECHANISM_TYPE prf_mech = prf_desc->nss.mechanism; PK11SymKey *pss_key = prf_key_from_hunk("pss", prf_desc, pss); if (pss_key == NULL) { if (libreswan_fipsmode()) { PASSERT_FAIL("FIPS: failure creating %s PRF context for digesting PSK", prf_desc->common.name); } loglog(RC_LOG_SERIOUS, "failure creating %s PRF context for digesting PSK", prf_desc->common.name); return empty_mac; } CK_NSS_IKE_PRF_DERIVE_PARAMS ike_prf_params = { .prfMechanism = prf_mech, .bDataAsKey = CK_FALSE, .bRekey = CK_FALSE, .pNi = (CK_BYTE_PTR) psk_key_pad_str, .ulNiLen = sizeof(psk_key_pad_str) - 1, .pNr = NULL, .ulNrLen = 0, }; SECItem params = { .data = (unsigned char *)&ike_prf_params, .len = sizeof(ike_prf_params), }; prf_psk = crypt_derive(pss_key, CKM_NSS_IKE_PRF_DERIVE, ¶ms, "prf(Shared Secret, \"Key Pad for IKEv2\")", prf_mech, CKA_SIGN, 0/*key-size*/, 0/*flags*/, HERE); release_symkey("psk pss_key", "pss_key", &pss_key); } /* calculate outer prf */ struct crypt_mac signed_octets; { struct crypt_prf *prf = crypt_prf_init_symkey(" = prf(, )", prf_desc, "", prf_psk); /* * For the responder, the octets to be signed start * with the first octet of the first SPI in the header * of the second message and end with the last octet * of the last payload in the second message. * Appended to this (for purposes of computing the * signature) are the initiator's nonce Ni (just the * value, not the payload containing it), and the * value prf(SK_pr,IDr') where IDr' is the responder's * ID payload excluding the fixed header. Note that * neither the nonce Ni nor the value prf(SK_pr,IDr') * are transmitted. */ crypt_prf_update_hunk(prf, "first-packet", first_packet); crypt_prf_update_hunk(prf, "nonce", nonce); crypt_prf_update_hunk(prf, "hash", *id_hash); signed_octets = crypt_prf_final_mac(&prf, NULL); } release_symkey(__func__, "prf-psk", &prf_psk); return signed_octets; } const struct prf_ikev2_ops ike_alg_prf_ikev2_nss_ops = { .backend = "NSS", .prfplus = prfplus, .ike_sa_skeyseed = ike_sa_skeyseed, .ike_sa_rekey_skeyseed = ike_sa_rekey_skeyseed, .ike_sa_keymat = ike_sa_keymat, .child_sa_keymat = child_sa_keymat, .psk_auth = psk_auth, }; libreswan-3.32/lib/libswan/ike_alg_prf_mac_hmac_ops.c000066400000000000000000000134371365625662500227630ustar00rootroot00000000000000/* * Copyright (C) 2016-2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include "lswalloc.h" #include "lswlog.h" #include "ike_alg.h" #include "crypt_prf.h" #include "crypt_symkey.h" #include "crypt_hash.h" #include "ike_alg_prf_mac_ops.h" struct prf_context { const char *name; const struct prf_desc *desc; /* intermediate values */ PK11SymKey *key; PK11SymKey *inner; }; static void prf_update(struct prf_context *prf); /* * Create a PRF ready to consume data. */ static struct prf_context *prf_init(const struct prf_desc *prf_desc, const char *name) { struct prf_context *prf = alloc_thing(struct prf_context, name); *prf = (struct prf_context) { .name = name, .desc = prf_desc, }; return prf; } static struct prf_context *init_bytes(const struct prf_desc *prf_desc, const char *name, const char *key_name UNUSED, const uint8_t *key, size_t sizeof_key) { struct prf_context *prf = prf_init(prf_desc, name); /* XXX: use an untyped key */ prf->key = symkey_from_bytes(name, key, sizeof_key); prf_update(prf); return prf; } static struct prf_context *init_symkey(const struct prf_desc *prf_desc, const char *name, const char *key_name UNUSED, PK11SymKey *key) { struct prf_context *prf = prf_init(prf_desc, name); prf->key = reference_symkey(name, "key", key); prf_update(prf); return prf; } /* * Prepare for update phase (accumulate seed material). */ static void prf_update(struct prf_context *prf) { /* create the prf key from KEY. */ passert(prf->key != NULL); passert(prf->desc->hasher->hash_block_size <= MAX_HMAC_BLOCKSIZE); if (sizeof_symkey(prf->key) > prf->desc->hasher->hash_block_size) { /* * The key is too big, hash it down to size using the * HASH that the PRF's HMAC is built from. */ PK11SymKey *new = crypt_hash_symkey("prf hash to size:", prf->desc->hasher, "raw key", prf->key); release_symkey(prf->name, "key", &prf->key); prf->key = new; } else if (sizeof_symkey(prf->key) < prf->desc->hasher->hash_block_size) { /* * The key is too small, pad it with zeros to block * size. */ static /*const*/ unsigned char z[MAX_HMAC_BLOCKSIZE] = { 0 }; append_symkey_bytes("trimed key", &prf->key, z, prf->desc->hasher->hash_block_size - sizeof_symkey(prf->key)); } passert(prf->key != NULL); /* Start forming the inner hash input: (key^IPAD)|... */ passert(prf->inner == NULL); unsigned char ip[MAX_HMAC_BLOCKSIZE]; memset(ip, HMAC_IPAD, prf->desc->hasher->hash_block_size); chunk_t hmac_ipad = { ip, prf->desc->hasher->hash_block_size }; prf->inner = xor_symkey_chunk(prf->key, hmac_ipad); } /* * Accumulate data. */ static void digest_symkey(struct prf_context *prf, const char *name UNUSED, PK11SymKey *update) { passert(digest_symkey == prf->desc->prf_mac_ops->digest_symkey); append_symkey_symkey(&(prf->inner), update); } static void digest_bytes(struct prf_context *prf, const char *name, const uint8_t *bytes, size_t sizeof_bytes) { passert(digest_bytes == prf->desc->prf_mac_ops->digest_bytes); append_symkey_bytes(name, &(prf->inner), bytes, sizeof_bytes); } /* * Finally. */ static PK11SymKey *compute_outer(struct prf_context *prf) { passert(prf->inner != NULL); /* run that through hasher */ PK11SymKey *hashed_inner = crypt_hash_symkey("PRF HMAC inner hash", prf->desc->hasher, "inner", prf->inner); release_symkey(prf->name, "inner", &prf->inner); /* Input to outer hash: (key^OPAD)|hashed_inner. */ passert(prf->desc->hasher->hash_block_size <= MAX_HMAC_BLOCKSIZE); unsigned char op[MAX_HMAC_BLOCKSIZE]; memset(op, HMAC_OPAD, prf->desc->hasher->hash_block_size); chunk_t hmac_opad = { op, prf->desc->hasher->hash_block_size }; PK11SymKey *outer = xor_symkey_chunk(prf->key, hmac_opad); append_symkey_symkey(&outer, hashed_inner); release_symkey(prf->name, "hashed-inner", &hashed_inner); release_symkey(prf->name, "key", &prf->key); return outer; } static PK11SymKey *final_symkey(struct prf_context **prfp) { passert(final_symkey == (*prfp)->desc->prf_mac_ops->final_symkey); PK11SymKey *outer = compute_outer(*prfp); /* Finally hash that */ PK11SymKey *hashed_outer = crypt_hash_symkey("PRF HMAC outer hash", (*prfp)->desc->hasher, "outer", outer); release_symkey((*prfp)->name, "outer", &outer); if (DBGP(DBG_CRYPT)) { DBG_symkey(" ", " hashed-outer", hashed_outer); } pfree(*prfp); *prfp = NULL; return hashed_outer; } static void final_bytes(struct prf_context **prfp, uint8_t *bytes, size_t sizeof_bytes) { passert(final_bytes == (*prfp)->desc->prf_mac_ops->final_bytes); PK11SymKey *outer = compute_outer(*prfp); /* Finally hash that */ struct crypt_hash *hash = crypt_hash_init("PRF HMAC outer hash", (*prfp)->desc->hasher); crypt_hash_digest_symkey(hash, "outer", outer); crypt_hash_final_bytes(&hash, bytes, sizeof_bytes); release_symkey((*prfp)->name, "outer", &outer); pfree(*prfp); *prfp = NULL; } static void hmac_prf_check(const struct prf_desc *prf) { const struct ike_alg *alg = &prf->common; pexpect_ike_alg(alg, prf->hasher != NULL); } const struct prf_mac_ops ike_alg_prf_mac_hmac_ops = { "native(HMAC)", hmac_prf_check, init_symkey, init_bytes, digest_symkey, digest_bytes, final_symkey, final_bytes, }; libreswan-3.32/lib/libswan/ike_alg_prf_mac_nss_ops.c000066400000000000000000000122001365625662500226410ustar00rootroot00000000000000/* * Copyright (C) 2016-2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include #include #include #include "lswlog.h" #include "lswalloc.h" #include "lswnss.h" #include "constants.h" #include "ike_alg.h" #include "ike_alg_prf_mac_ops.h" #include "crypt_symkey.h" struct prf_context { const char *name; const struct prf_desc *desc; PK11Context *context; }; /* * Create a PRF ready to consume data. */ static struct prf_context *init(const struct prf_desc *prf_desc, const char *name, const char *key_name, PK11SymKey *key) { passert(prf_desc->nss.mechanism > 0); /* lame, screwed up old compilers what this */ SECItem ignore = { .len = 0, }; PK11Context *context = PK11_CreateContextBySymKey(prf_desc->nss.mechanism, CKA_SIGN, key, &ignore); if (context == NULL) { LSWLOG(buf) { lswlogf(buf, "NSS: %s create %s context from key %s(%p) failed", name, prf_desc->common.name, key_name, key); lswlog_nss_error(buf); } return NULL; } DBGF(DBG_CRYPT, "%s prf: created %s context %p from %s-key@%p", name, prf_desc->common.name, context, key_name, key); SECStatus rc = PK11_DigestBegin(context); if (rc) { libreswan_log("NSS: %s digest begin failed for %s (%x)\n", name, prf_desc->common.name, rc); PK11_DestroyContext(context, PR_TRUE); return NULL; } DBGF(DBG_CRYPT, "%s prf: begin %s with context %p from %s-key@%p", name, prf_desc->common.name, context, key_name, key); struct prf_context *prf = alloc_thing(struct prf_context, name); *prf = (struct prf_context) { .name = name, .desc = prf_desc, .context = context, }; return prf; } static struct prf_context *init_symkey(const struct prf_desc *prf_desc, const char *name, const char *key_name, PK11SymKey *key) { /* * Need a key of the correct type. * * This key has both the mechanism and flags set. */ PK11SymKey *clone = prf_key_from_symkey_bytes("clone", prf_desc, 0, sizeof_symkey(key), key, HERE); struct prf_context *prf = init(prf_desc, name, key_name, clone); release_symkey(name, "clone", &clone); return prf; } static struct prf_context *init_bytes(const struct prf_desc *prf_desc, const char *name, const char *key_name, const uint8_t *key, size_t sizeof_key) { /* * Need a key of the correct type. * * This key has both the mechanism and flags set. */ PK11SymKey *clone = prf_key_from_bytes(key_name, prf_desc, key, sizeof_key, HERE); struct prf_context *prf = init(prf_desc, name, key_name, clone); release_symkey(name, "clone", &clone); return prf ; } /* * Accumulate data. */ static void digest_symkey(struct prf_context *prf, const char *symkey_name UNUSED, PK11SymKey *symkey) { /* * Feed the key's raw bytes to the digest function. NSS's * PK11_DigestKey() doesn't work with HMAC (only simple MAC), * and there is no NSS HMAC Derive mechansism. */ #if 0 SECStatus rc = PK11_DigestKey(prf->context, symkey); fprintf(stderr, "symkey update %x\n", rc); #endif chunk_t chunk = chunk_from_symkey("nss hmac digest hack", symkey); SECStatus rc = PK11_DigestOp(prf->context, chunk.ptr, chunk.len); freeanychunk(chunk); passert(rc == SECSuccess); } static void digest_bytes(struct prf_context *prf, const char *name UNUSED, const uint8_t *bytes, size_t sizeof_bytes) { SECStatus rc = PK11_DigestOp(prf->context, bytes, sizeof_bytes); passert(rc == SECSuccess); } static void final(struct prf_context *prf, void *bytes, size_t sizeof_bytes) { unsigned bytes_out; SECStatus rc = PK11_DigestFinal(prf->context, bytes, &bytes_out, sizeof_bytes); passert(rc == SECSuccess); pexpect(bytes_out == sizeof_bytes); PK11_DestroyContext(prf->context, PR_TRUE); prf->context = NULL; } static void final_bytes(struct prf_context **prf, uint8_t *bytes, size_t sizeof_bytes) { final(*prf, bytes, sizeof_bytes); pfree(*prf); *prf = NULL; } static PK11SymKey *final_symkey(struct prf_context **prf) { size_t sizeof_bytes = (*prf)->desc->prf_output_size; uint8_t *bytes = alloc_things(uint8_t, sizeof_bytes, "bytes"); final(*prf, bytes, sizeof_bytes); PK11SymKey *final = symkey_from_bytes("final", bytes, sizeof_bytes); pfree(bytes); pfree(*prf); *prf = NULL; return final; } static void nss_prf_check(const struct prf_desc *prf) { const struct ike_alg *alg = &prf->common; pexpect_ike_alg(alg, prf->nss.mechanism > 0); } const struct prf_mac_ops ike_alg_prf_mac_nss_ops = { "NSS", nss_prf_check, init_symkey, init_bytes, digest_symkey, digest_bytes, final_symkey, final_bytes, }; libreswan-3.32/lib/libswan/ike_alg_prf_mac_xcbc_ops.c000066400000000000000000000215171365625662500227700ustar00rootroot00000000000000/* * Copyright (C) 2016-2019 Andrew Cagney * Copyright (C) 2019 Paul Wouters * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include #include #include #include "chunk.h" #include "lswlog.h" #include "lswalloc.h" #include "constants.h" #include "ike_alg.h" #include "ike_alg_prf_mac_ops.h" #include "crypt_symkey.h" #include "lswnss.h" struct prf_context { const char *name; const struct prf_desc *desc; PK11SymKey *key; chunk_t bytes; }; static void encrypt(const char *name, chunk_t out, chunk_t in, const struct prf_desc *prf, PK11SymKey *key) { unsigned int out_size = 0; SECStatus status = PK11_Encrypt(key, prf->nss.mechanism, NULL, out.ptr, &out_size, out.len, in.ptr, in.len); if (status != SECSuccess) { LSWLOG_PASSERT(buf) { lswlogf(buf, "encryption %s failed: ", name); lswlog_nss_error(buf); } } } static chunk_t derive_ki(const struct prf_desc *prf, PK11SymKey *key, int ki) { chunk_t in = alloc_chunk(prf->prf_key_size, "ki in"); chunk_t out = alloc_chunk(prf->prf_key_size, "ki out"); for (unsigned i = 0; i < prf->prf_key_size; i++) { in.ptr[i] = ki; } encrypt("K([123])", out, in, prf, key); freeanychunk(in); return out; } static chunk_t xcbc_mac(const struct prf_desc *prf, PK11SymKey *key, chunk_t bytes) { if (DBGP(DBG_CRYPT)) { DBG_dump_hunk("XCBC: data", bytes); chunk_t k = chunk_from_symkey("K", key); DBG_dump_hunk("XCBC: K:", k); freeanychunk(k); } chunk_t k1t = derive_ki(prf, key, 1); if (DBGP(DBG_CRYPT)) { DBG_dump_hunk("XCBC: K1", k1t); } PK11SymKey *k1 = prf_key_from_hunk("k1", prf, k1t); freeanychunk(k1t); /* * (2) Define E[0] = 0x00000000000000000000000000000000 */ chunk_t e = alloc_chunk(prf->prf_key_size, "e"); /* * (3) For each block M[i], where i = 1 ... n-1: * XOR M[i] with E[i-1], then encrypt the result with Key K1, * yielding E[i]. */ chunk_t t = alloc_chunk(prf->prf_key_size, "t"); int n = (bytes.len + prf->prf_key_size - 1) / prf->prf_key_size; chunk_t m = chunk(bytes.ptr, prf->prf_key_size); for (int i = 1; i <= n - 1; i++) { for (unsigned j = 0; j < prf->prf_key_size; j++) { t.ptr[j] = m.ptr[j] ^ e.ptr[j]; } encrypt("XCBC: K1(M[i]^E[i-1])", e, t, prf, k1); m.ptr += prf->prf_key_size; } /* * (4) For block M[n]: * * NOTE1: If M is the empty string, pad and encrypt as in (4)(b) to * create M[1] and E[1]. This will never be the case for ESP or AH, but * is included for completeness sake. */ m.len = bytes.ptr + bytes.len - m.ptr; if (m.len == prf->prf_key_size) { chunk_t k2 = derive_ki(prf, key, 2); if (DBGP(DBG_CRYPT)) { DBG_log("XCBC: Computing E[%d] using K2", n); DBG_dump_hunk("XCBC: K2", k2); DBG_dump_hunk("XCBC: E[n-1]", e); DBG_dump_hunk("XCBC: M[n]", m); } /* * a) If the blocksize of M[n] is 128 bits: * XOR M[n] with E[n-1] and Key K2, then encrypt the result with * Key K1, yielding E[n]. */ for (unsigned j = 0; j < prf->prf_key_size; j++) { t.ptr[j] = m.ptr[j] ^ e.ptr[j] ^ k2.ptr[j]; } if (DBGP(DBG_CRYPT)) { DBG_dump_hunk("XCBC: M[n]^E[n-1]^K2", t); } freeanychunk(k2); } else { chunk_t k3 = derive_ki(prf, key, 3); if (DBGP(DBG_CRYPT)) { DBG_log("Computing E[%d] using K3", n); DBG_dump_hunk("XCBC: K3", k3); DBG_dump_hunk("XCBC: E[n-1]", e); DBG_dump_hunk("XCBC: M[n]", m); } /* * b) If the blocksize of M[n] is less than 128 bits: * * i) Pad M[n] with a single "1" bit, followed by the number of * "0" bits (possibly none) required to increase M[n]'s * blocksize to 128 bits. * ii) XOR M[n] with E[n-1] and Key K3, then encrypt the result * with Key K1, yielding E[n]. */ unsigned j = 0; for (; j < m.len; j++) { t.ptr[j] = m.ptr[j] ^ e.ptr[j] ^ k3.ptr[j]; } t.ptr[j] = 0x80 ^ e.ptr[j] ^ k3.ptr[j]; j++; for (; j < prf->prf_key_size; j++) { t.ptr[j] = 0x00 ^ e.ptr[j] ^ k3.ptr[j]; } if (DBGP(DBG_CRYPT)) { DBG_dump_hunk("XCBC: M[n]", m); DBG_dump_hunk("XCBC: M[n]:80...^E[n-1]^K3", t); } freeanychunk(k3); } encrypt("K1(M[n]^E[n-1]^K2)", e, t, prf, k1); if (DBGP(DBG_CRYPT)) { DBG_dump_hunk("XCBC: MAC", e); } release_symkey("xcbc", "k1", &k1); freeanychunk(t); return e; } /* * Create a PRF ready to consume data. */ static struct prf_context *nss_xcbc_init_symkey(const struct prf_desc *prf_desc, const char *name, const char *key_name, PK11SymKey *draft_key) { /* * Need to turn the key into something of the right size. */ PK11SymKey *key; size_t dkey_sz = sizeof_symkey(draft_key); if (dkey_sz < prf_desc->prf_key_size) { DBGF(DBG_CRYPT, "XCBC: Key %zd<%zd too small, padding with zeros", dkey_sz, prf_desc->prf_key_size); /* * right pad with zeros * * make a local reference to the the (read-only) * draft_key and manipulate that */ chunk_t zeros = alloc_chunk(prf_desc->prf_key_size - dkey_sz, "zeros"); PK11SymKey *local_draft_key = reference_symkey("xcbc", "local_draft_key", draft_key); append_symkey_hunk("local_draft_key+=0", &local_draft_key, zeros); key = prf_key_from_symkey_bytes(name, prf_desc, 0, prf_desc->prf_key_size, local_draft_key, HERE); /* free all in reverse order */ release_symkey(name, "local_draft_key", &local_draft_key); freeanychunk(zeros); } else if (dkey_sz > prf_desc->prf_key_size) { DBGF(DBG_CRYPT, "XCBC: Key %zd>%zd too big, rehashing to size", dkey_sz, prf_desc->prf_key_size); /* * put the key through the mac with a zero key */ chunk_t zeros = alloc_chunk(prf_desc->prf_key_size, "zeros"); PK11SymKey *zero_key = prf_key_from_hunk("zero_key", prf_desc, zeros); chunk_t draft_chunk = chunk_from_symkey("draft_chunk", draft_key); chunk_t key_chunk = xcbc_mac(prf_desc, zero_key, draft_chunk); key = prf_key_from_hunk(key_name, prf_desc, key_chunk); /* free all in reverse order */ freeanychunk(key_chunk); freeanychunk(draft_chunk); release_symkey(name, "zero_key", &zero_key); freeanychunk(zeros); } else { DBGF(DBG_CRYPT, "XCBC: Key %zd=%zd just right", dkey_sz, prf_desc->prf_key_size); key = prf_key_from_symkey_bytes(key_name, prf_desc, 0, prf_desc->prf_key_size, draft_key, HERE); } struct prf_context *prf = alloc_thing(struct prf_context, "prf context"); *prf = (struct prf_context) { .key = key, .name = name, .desc = prf_desc, }; return prf; } static struct prf_context *nss_xcbc_init_bytes(const struct prf_desc *prf_desc, const char *name, const char *key_name, const uint8_t *key, size_t sizeof_key) { /* * Need a key of the correct type. * * This key has both the mechanism and flags set. */ PK11SymKey *clone = symkey_from_bytes(key_name, key, sizeof_key); struct prf_context *context = nss_xcbc_init_symkey(prf_desc, name, key_name, clone); release_symkey(name, "clone", &clone); return context; } /* * Accumulate data. */ static void nss_xcbc_digest_symkey(struct prf_context *prf, const char *symkey_name, PK11SymKey *symkey) { append_chunk_symkey(symkey_name, &prf->bytes, symkey); } static void nss_xcbc_digest_bytes(struct prf_context *prf, const char *name, const uint8_t *bytes, size_t sizeof_bytes) { append_chunk_bytes(name, &prf->bytes, bytes, sizeof_bytes); } static void nss_xcbc_final_bytes(struct prf_context **prf, uint8_t *bytes, size_t sizeof_bytes) { chunk_t mac = xcbc_mac((*prf)->desc, (*prf)->key, (*prf)->bytes); memcpy(bytes, mac.ptr, sizeof_bytes); freeanychunk(mac); freeanychunk((*prf)->bytes); release_symkey((*prf)->name, "key", &(*prf)->key); pfree(*prf); } static PK11SymKey *nss_xcbc_final_symkey(struct prf_context **prf) { chunk_t mac = xcbc_mac((*prf)->desc, (*prf)->key, (*prf)->bytes); PK11SymKey *key = symkey_from_hunk("xcbc", mac); freeanychunk(mac); freeanychunk((*prf)->bytes); release_symkey((*prf)->name, "key", &(*prf)->key); pfree(*prf); return key; } static void nss_xcbc_check(const struct prf_desc *prf) { const struct ike_alg *alg = &prf->common; pexpect_ike_alg(alg, prf->nss.mechanism > 0); } const struct prf_mac_ops ike_alg_prf_mac_nss_xcbc_ops = { "native(XCBC)", nss_xcbc_check, nss_xcbc_init_symkey, nss_xcbc_init_bytes, nss_xcbc_digest_symkey, nss_xcbc_digest_bytes, nss_xcbc_final_symkey, nss_xcbc_final_bytes, }; libreswan-3.32/lib/libswan/ike_alg_ripemd.c000066400000000000000000000031021365625662500207470ustar00rootroot00000000000000/* RIPEMD, for libreswan. * * Copyright (C) 2017 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include "constants.h" /* for BYTES_FOR_BITS() */ #include "ietf_constants.h" #include "ike_alg.h" #include "ike_alg_integ.h" #include "sadb.h" /* * See: https://tools.ietf.org/html/rfc2857 * * While NSS seemingly supports RIPEMD160, let's not go there. */ const struct integ_desc ike_alg_integ_hmac_ripemd_160_96 = { .common = { .name = "ripemd", .fqn = "HMAC_RIPEMD_160_96", .names = "ripemd,hmac_ripemd,hmac_ripemd_160_96", .algo_type = IKE_ALG_INTEG, .id = { [IKEv1_OAKLEY_ID] = -1, [IKEv1_ESP_ID] = AUTH_ALGORITHM_HMAC_RIPEMD, [IKEv2_ALG_ID] = -1, }, }, .integ_keymat_size = BYTES_FOR_BITS(160), .integ_output_size = BYTES_FOR_BITS(96), .integ_ikev1_ah_transform = AH_RIPEMD, #ifdef SADB_X_AALG_RIPEMD160HMAC .integ_sadb_aalg_id = SADB_X_AALG_RIPEMD160HMAC, #endif .integ_netlink_xfrm_name = "hmac(rmd160)", .integ_tcpdump_name = "ripemd", .integ_ike_audit_name = "ripemd", .integ_kernel_audit_name = "HMAC_RIPEMD", }; libreswan-3.32/lib/libswan/ike_alg_serpent.c000066400000000000000000000063101365625662500211530ustar00rootroot00000000000000/* * IKE modular algorithm handling interface * Author: JuanJo Ciarlante * Copyright (C) 2005-2007 Michael Richardson * Copyright (C) 2012 Paul Wouters * Copyright (C) 2013 D. Hugh Redelmeier * Copyright (C) 2013 Paul Wouters * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include "libserpent/serpent_cbc.h" #include "lswcdefs.h" /* for UNUSED */ #include "lswlog.h" #include "ike_alg.h" #include "ike_alg_encrypt.h" #include "ike_alg_encrypt_ops.h" #include "sadb.h" #define SERPENT_CBC_BLOCK_SIZE (128 / BITS_PER_BYTE) #define SERPENT_KEY_MIN_LEN 128 #define SERPENT_KEY_DEF_LEN 128 #define SERPENT_KEY_MAX_LEN 256 static void do_serpent(const struct encrypt_desc *alg UNUSED, uint8_t *buf, size_t buf_size, PK11SymKey *key, uint8_t *iv, bool enc) { serpent_context serpent_ctx; uint8_t iv_bak[SERPENT_CBC_BLOCK_SIZE]; uint8_t *new_iv = buf + buf_size - SERPENT_CBC_BLOCK_SIZE; uint8_t *bare_key_ptr; size_t bare_key_len; /* unpack key from PK11SymKey (or crash!) */ { SECStatus status = PK11_ExtractKeyValue(key); SECItem *keydata; passert(status == SECSuccess); keydata = PK11_GetKeyData(key); bare_key_ptr = keydata->data; bare_key_len = keydata->len; // SECITEM_FreeItem(keydata, PR_TRUE); } serpent_set_key(&serpent_ctx, bare_key_ptr, bare_key_len); /* * my SERPENT cbc does not touch passed IV (optimization for * ESP handling), so I must "emulate" des-like IV * crunching */ if (!enc) { memcpy(iv_bak, new_iv, SERPENT_CBC_BLOCK_SIZE); new_iv = iv_bak; } serpent_cbc_encrypt(&serpent_ctx, buf, buf, buf_size, iv, enc); memcpy(iv, new_iv, SERPENT_CBC_BLOCK_SIZE); } static void serpent_check(const struct encrypt_desc *encrypt UNUSED) { } static const struct encrypt_ops serpent_encrypt_ops = { .backend = "serpent", .check = serpent_check, .do_crypt = do_serpent, }; const struct encrypt_desc ike_alg_encrypt_serpent_cbc = { .common = { .name = "serpent", .fqn = "SERPENT_CBC", .names = "serpent,serpent_cbc", .algo_type = IKE_ALG_ENCRYPT, .id = { [IKEv1_OAKLEY_ID] = OAKLEY_SERPENT_CBC, [IKEv1_ESP_ID] = ESP_SERPENT, [IKEv2_ALG_ID] = IKEv2_ENCR_SERPENT_CBC, }, }, .enc_blocksize = SERPENT_CBC_BLOCK_SIZE, .pad_to_blocksize = true, .wire_iv_size = SERPENT_CBC_BLOCK_SIZE, .keydeflen = SERPENT_KEY_DEF_LEN, .key_bit_lengths = { 256, 192, 128, }, .encrypt_ops = &serpent_encrypt_ops, #ifdef SADB_X_EALG_SERPENTCBC .encrypt_sadb_ealg_id = SADB_X_EALG_SERPENTCBC, #endif .encrypt_netlink_xfrm_name = "serpent", .encrypt_tcpdump_name = "serpent", .encrypt_ike_audit_name = "serpent", .encrypt_kernel_audit_name = "SERPENT", }; libreswan-3.32/lib/libswan/ike_alg_sha1.c000066400000000000000000000070641365625662500203360ustar00rootroot00000000000000/* crypto interfaces * * Copyright (C) 1998-2001,2013 D. Hugh Redelmeier * Copyright (C) 2003-2008 Michael C. Richardson * Copyright (C) 2003-2010 Paul Wouters * Copyright (C) 2009-2012 Avesh Agarwal * Copyright (C) 2012-2013 Paul Wouters * Copyright (C) 2013 Florian Weimer * Copyright (C) 2016 Andrew Cagney * Copyright (C) 2018 Sahana Prasad * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include "constants.h" /* for BYTES_FOR_BITS() */ #include "ietf_constants.h" #include "ike_alg.h" #include "ike_alg_hash.h" #include "ike_alg_prf.h" #include "ike_alg_integ.h" #include "ike_alg_hash_ops.h" #include "ike_alg_prf_mac_ops.h" #include "ike_alg_prf_ikev1_ops.h" #include "ike_alg_prf_ikev2_ops.h" #include "sadb.h" const struct hash_desc ike_alg_hash_sha1 = { .common = { .name = "sha", .fqn = "SHA1", .names = "sha,sha1", .algo_type = IKE_ALG_HASH, .id = { [IKEv1_OAKLEY_ID] = OAKLEY_SHA1, [IKEv1_ESP_ID] = -1, [IKEv2_ALG_ID] = -1, }, .fips = true, }, .nss = { .oid_tag = SEC_OID_SHA1, .derivation_mechanism = CKM_SHA1_KEY_DERIVATION, }, .hash_digest_size = SHA1_DIGEST_SIZE, .hash_block_size = 64, /* B from RFC 2104 */ .hash_ops = &ike_alg_hash_nss_ops, }; const struct prf_desc ike_alg_prf_sha1 = { .common = { .name = "sha", .fqn = "HMAC_SHA1", .names = "sha,sha1,hmac_sha1", .algo_type = IKE_ALG_PRF, .id = { [IKEv1_OAKLEY_ID] = OAKLEY_SHA1, [IKEv1_ESP_ID] = -1, [IKEv2_ALG_ID] = IKEv2_PRF_HMAC_SHA1, }, .fips = true, }, .nss = { .mechanism = CKM_SHA_1_HMAC, }, .prf_key_size = SHA1_DIGEST_SIZE, .prf_output_size = SHA1_DIGEST_SIZE, .hasher = &ike_alg_hash_sha1, .prf_mac_ops = &ike_alg_prf_mac_nss_ops, #ifdef USE_NSS_PRF .prf_ikev1_ops = &ike_alg_prf_ikev1_nss_ops, .prf_ikev2_ops = &ike_alg_prf_ikev2_nss_ops, #else .prf_ikev1_ops = &ike_alg_prf_ikev1_mac_ops, .prf_ikev2_ops = &ike_alg_prf_ikev2_mac_ops, #endif .prf_ike_audit_name = "sha1", }; const struct integ_desc ike_alg_integ_sha1 = { .common = { .name = "sha", .fqn = "HMAC_SHA1_96", .names = "sha,sha1,sha1_96,hmac_sha1,hmac_sha1_96", .algo_type = IKE_ALG_INTEG, .id = { [IKEv1_OAKLEY_ID] = OAKLEY_SHA1, [IKEv1_ESP_ID] = AUTH_ALGORITHM_HMAC_SHA1, [IKEv2_ALG_ID] = IKEv2_AUTH_HMAC_SHA1_96, }, .fips = true, }, .integ_keymat_size = SHA1_DIGEST_SIZE, .integ_output_size = SHA1_DIGEST_SIZE_96, .integ_ikev1_ah_transform = AH_SHA, .prf = &ike_alg_prf_sha1, #ifdef SADB_AALG_SHA1HMAC .integ_sadb_aalg_id = SADB_AALG_SHA1HMAC, #endif .integ_netlink_xfrm_name = "sha1", .integ_tcpdump_name = "sha1", .integ_ike_audit_name = "sha1", .integ_kernel_audit_name = "HMAC_SHA1", }; static const uint8_t asn1_blob_ecdsa_sha1[ASN1_LEN_ALGO_IDENTIFIER + ASN1_SHA1_ECDSA_SIZE] = { LEN_ECDSA_SHA1_BLOB, ECDSA_SHA1_BLOB }; const struct asn1_hash_blob asn1_ecdsa_sha1 = { .hash_algo = IKEv2_AUTH_HASH_SHA1, .blob = asn1_blob_ecdsa_sha1, .blob_sz = sizeof(asn1_blob_ecdsa_sha1) }; libreswan-3.32/lib/libswan/ike_alg_sha2.c000066400000000000000000000251371365625662500203400ustar00rootroot00000000000000/* * Copyright (C) 2010-2012 Avesh Agarwal * Copyright (C) 2010-2013 Paul Wouters * Copyright (C) 2013 Florian Weimer * Copyright (C) 2013-2019 D. Hugh Redelmeier * Copyright (C) 2016-2019 Andrew Cagney * Copyright (C) 2016-2018 Sahana Prasad * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include "constants.h" /* for BYTES_FOR_BITS() */ #include "ietf_constants.h" #include "ike_alg.h" #include "ike_alg_hash.h" #include "ike_alg_prf.h" #include "ike_alg_integ.h" #include "ike_alg_hash_ops.h" #include "ike_alg_prf_mac_ops.h" #include "ike_alg_prf_ikev1_ops.h" #include "ike_alg_prf_ikev2_ops.h" #include "sadb.h" #include const struct hash_desc ike_alg_hash_sha2_256 = { .common = { .name = "sha2_256", .fqn = "SHA2_256", .names = "sha2,sha256,sha2_256", .algo_type = IKE_ALG_HASH, .id = { [IKEv1_OAKLEY_ID] = OAKLEY_SHA2_256, [IKEv1_ESP_ID] = -1, [IKEv2_ALG_ID] = -1, }, .fips = true, }, .nss = { .oid_tag = SEC_OID_SHA256, .derivation_mechanism = CKM_SHA256_KEY_DERIVATION, }, .hash_digest_size = SHA2_256_DIGEST_SIZE, .hash_block_size = 64, /* from RFC 4868 */ .hash_ops = &ike_alg_hash_nss_ops, }; const struct prf_desc ike_alg_prf_sha2_256 = { .common = { .name = "sha2_256", .fqn = "HMAC_SHA2_256", .names = "sha2,sha256,sha2_256,hmac_sha2_256", .algo_type = IKE_ALG_PRF, .id = { [IKEv1_OAKLEY_ID] = OAKLEY_SHA2_256, [IKEv1_ESP_ID] = -1, [IKEv2_ALG_ID] = IKEv2_PRF_HMAC_SHA2_256, }, .fips = true, }, .nss = { .mechanism = CKM_SHA256_HMAC, }, .prf_key_size = SHA2_256_DIGEST_SIZE, .prf_output_size = SHA2_256_DIGEST_SIZE, .hasher = &ike_alg_hash_sha2_256, .prf_mac_ops = &ike_alg_prf_mac_nss_ops, #ifdef USE_NSS_PRF .prf_ikev1_ops = &ike_alg_prf_ikev1_nss_ops, .prf_ikev2_ops = &ike_alg_prf_ikev2_nss_ops, #else .prf_ikev1_ops = &ike_alg_prf_ikev1_mac_ops, .prf_ikev2_ops = &ike_alg_prf_ikev2_mac_ops, #endif .prf_ike_audit_name = "sha256", }; const struct integ_desc ike_alg_integ_sha2_256 = { .common = { .name = "sha2_256", .fqn = "HMAC_SHA2_256_128", .names = "sha2,sha256,sha2_256,sha2_256_128,hmac_sha2_256,hmac_sha2_256_128", .algo_type = IKE_ALG_INTEG, .id = { [IKEv1_OAKLEY_ID] = OAKLEY_SHA2_256, [IKEv1_ESP_ID] = AUTH_ALGORITHM_HMAC_SHA2_256, [IKEv2_ALG_ID] = IKEv2_AUTH_HMAC_SHA2_256_128, }, .fips = true, }, .integ_keymat_size = SHA2_256_DIGEST_SIZE, .integ_output_size = SHA2_256_DIGEST_SIZE / 2, .integ_ikev1_ah_transform = AH_SHA2_256, .prf = &ike_alg_prf_sha2_256, #ifdef SADB_X_AALG_SHA2_256HMAC .integ_sadb_aalg_id = SADB_X_AALG_SHA2_256HMAC, #endif #ifdef SADB_X_AALG_SHA2_256 .integ_sadb_aalg_id = SADB_X_AALG_SHA2_256, #endif .integ_netlink_xfrm_name = "hmac(sha256)", .integ_tcpdump_name = "sha256", .integ_ike_audit_name = "sha256", .integ_kernel_audit_name = "HMAC_SHA2_256", }; const struct integ_desc ike_alg_integ_hmac_sha2_256_truncbug = { .common = { .name = "hmac_sha2_256_truncbug", .fqn = "HMAC_SHA2_256_TRUNCBUG", .names = "hmac_sha2_256_truncbug", .algo_type = IKE_ALG_INTEG, .id = { [IKEv1_OAKLEY_ID] = -1, [IKEv1_ESP_ID] = AUTH_ALGORITHM_HMAC_SHA2_256_TRUNCBUG, [IKEv2_ALG_ID] = -1, }, .fips = false, }, .integ_keymat_size = SHA2_256_DIGEST_SIZE, .integ_output_size = BYTES_FOR_BITS(96), .integ_ikev1_ah_transform = AH_SHA2_256_TRUNCBUG, #ifdef SADB_X_AALG_SHA2_256HMAC_TRUNCBUG .integ_sadb_aalg_id = SADB_X_AALG_SHA2_256HMAC_TRUNCBUG, #endif .integ_netlink_xfrm_name = "hmac(sha256)", .integ_tcpdump_name = "hmac_sha2_256_truncbug", .integ_ike_audit_name = "hmac_sha2_256_truncbug", .integ_kernel_audit_name = "HMAC_SHA2_256_TRUNCBUG", }; const CK_RSA_PKCS_PSS_PARAMS rsa_pss_sha2_256 = { .hashAlg = CKM_SHA256, .mgf = CKG_MGF1_SHA256, .sLen = SHA2_256_DIGEST_SIZE, }; static const uint8_t asn1_blob_256[ASN1_LEN_ALGO_IDENTIFIER + ASN1_SHA2_RSA_PSS_SIZE] = { LEN_RSA_PSS_SHA2_BLOB, RSA_PSS_SHA256_BLOB }; const struct asn1_hash_blob asn1_rsa_pss_sha2_256 = { .hash_algo = IKEv2_AUTH_HASH_SHA2_256, .blob = asn1_blob_256, .blob_sz = sizeof(asn1_blob_256) }; static const uint8_t asn1_blob_ecdsa_256[ASN1_LEN_ALGO_IDENTIFIER + ASN1_SHA2_ECDSA_SIZE] = { LEN_ECDSA_SHA2_BLOB, ECDSA_SHA256_BLOB }; const struct asn1_hash_blob asn1_ecdsa_sha2_256 = { .hash_algo = IKEv2_AUTH_HASH_SHA2_256, .blob = asn1_blob_ecdsa_256, .blob_sz = sizeof(asn1_blob_ecdsa_256) }; const struct hash_desc ike_alg_hash_sha2_384 = { .common = { .name = "sha2_384", .fqn = "SHA2_384", .names = "sha384,sha2_384", .algo_type = IKE_ALG_HASH, .id = { [IKEv1_OAKLEY_ID] = OAKLEY_SHA2_384, [IKEv1_ESP_ID] = -1, [IKEv2_ALG_ID] = -1, }, .fips = true, }, .nss = { .oid_tag = SEC_OID_SHA384, .derivation_mechanism = CKM_SHA384_KEY_DERIVATION, }, .hash_digest_size = SHA2_384_DIGEST_SIZE, .hash_block_size = 128, /* from RFC 4868 */ .hash_ops = &ike_alg_hash_nss_ops, }; const struct prf_desc ike_alg_prf_sha2_384 = { .common = { .name = "sha2_384", .fqn = "HMAC_SHA2_384", .names = "sha384,sha2_384,hmac_sha2_384", .algo_type = IKE_ALG_PRF, .id = { [IKEv1_OAKLEY_ID] = OAKLEY_SHA2_384, [IKEv1_ESP_ID] = -1, [IKEv2_ALG_ID] = IKEv2_PRF_HMAC_SHA2_384, }, .fips = true, }, .nss = { .mechanism = CKM_SHA384_HMAC, }, .prf_key_size = SHA2_384_DIGEST_SIZE, .prf_output_size = SHA2_384_DIGEST_SIZE, .hasher = &ike_alg_hash_sha2_384, .prf_mac_ops = &ike_alg_prf_mac_nss_ops, #ifdef USE_NSS_PRF .prf_ikev1_ops = &ike_alg_prf_ikev1_nss_ops, .prf_ikev2_ops = &ike_alg_prf_ikev2_nss_ops, #else .prf_ikev1_ops = &ike_alg_prf_ikev1_mac_ops, .prf_ikev2_ops = &ike_alg_prf_ikev2_mac_ops, #endif .prf_ike_audit_name = "sha384", }; const struct integ_desc ike_alg_integ_sha2_384 = { .common = { .name = "sha2_384", .fqn = "HMAC_SHA2_384_192", .names = "sha384,sha2_384,sha2_384_192,hmac_sha2_384,hmac_sha2_384_192", .algo_type = IKE_ALG_INTEG, .id = { [IKEv1_OAKLEY_ID] = OAKLEY_SHA2_384, [IKEv1_ESP_ID] = AUTH_ALGORITHM_HMAC_SHA2_384, [IKEv2_ALG_ID] = IKEv2_AUTH_HMAC_SHA2_384_192, }, .fips = true, }, .integ_keymat_size = SHA2_384_DIGEST_SIZE, .integ_output_size = SHA2_384_DIGEST_SIZE / 2, .integ_ikev1_ah_transform = AH_SHA2_384, .prf = &ike_alg_prf_sha2_384, #ifdef SADB_X_AALG_SHA2_384HMAC .integ_sadb_aalg_id = SADB_X_AALG_SHA2_384HMAC, #endif #ifdef SADB_X_AALG_SHA2_384 .integ_sadb_aalg_id = SADB_X_AALG_SHA2_384, #endif .integ_netlink_xfrm_name = "hmac(sha384)", .integ_tcpdump_name = "sha384", .integ_ike_audit_name = "sha384", .integ_kernel_audit_name = "HMAC_SHA2_384", }; const CK_RSA_PKCS_PSS_PARAMS rsa_pss_sha2_384 = { .hashAlg = CKM_SHA384, .mgf = CKG_MGF1_SHA384, .sLen = SHA2_384_DIGEST_SIZE, }; static const uint8_t asn1_blob_384[ASN1_LEN_ALGO_IDENTIFIER + ASN1_SHA2_RSA_PSS_SIZE] = { LEN_RSA_PSS_SHA2_BLOB, RSA_PSS_SHA384_BLOB }; const struct asn1_hash_blob asn1_rsa_pss_sha2_384 = { .hash_algo = IKEv2_AUTH_HASH_SHA2_384, .blob = asn1_blob_384, .blob_sz = sizeof(asn1_blob_384) }; static const uint8_t asn1_blob_ecdsa_384[ASN1_LEN_ALGO_IDENTIFIER + ASN1_SHA2_ECDSA_SIZE] = { LEN_ECDSA_SHA2_BLOB, ECDSA_SHA384_BLOB }; const struct asn1_hash_blob asn1_ecdsa_sha2_384 = { .hash_algo = IKEv2_AUTH_HASH_SHA2_384, .blob = asn1_blob_ecdsa_384, .blob_sz = sizeof(asn1_blob_ecdsa_384), }; const struct hash_desc ike_alg_hash_sha2_512 = { .common = { .name = "sha2_512", .fqn = "SHA2_512", .names = "sha512,sha2_512", .algo_type = IKE_ALG_HASH, .id = { [IKEv1_OAKLEY_ID] = OAKLEY_SHA2_512, [IKEv1_ESP_ID] = -1, [IKEv2_ALG_ID] = -1, }, .fips = true, }, .nss = { .oid_tag = SEC_OID_SHA512, .derivation_mechanism = CKM_SHA512_KEY_DERIVATION, }, .hash_digest_size = SHA2_512_DIGEST_SIZE, .hash_block_size = 128, /* from RFC 4868 */ .hash_ops = &ike_alg_hash_nss_ops, }; const struct prf_desc ike_alg_prf_sha2_512 = { .common = { .name = "sha2_512", .fqn = "HMAC_SHA2_512", .names = "sha512,sha2_512,hmac_sha2_512", .algo_type = IKE_ALG_PRF, .id = { [IKEv1_OAKLEY_ID] = OAKLEY_SHA2_512, [IKEv1_ESP_ID] = -1, [IKEv2_ALG_ID] = IKEv2_PRF_HMAC_SHA2_512, }, .fips = true, }, .nss = { .mechanism = CKM_SHA512_HMAC, }, .prf_key_size = SHA2_512_DIGEST_SIZE, .prf_output_size = SHA2_512_DIGEST_SIZE, .hasher = &ike_alg_hash_sha2_512, .prf_mac_ops = &ike_alg_prf_mac_nss_ops, #ifdef USE_NSS_PRF .prf_ikev1_ops = &ike_alg_prf_ikev1_nss_ops, .prf_ikev2_ops = &ike_alg_prf_ikev2_nss_ops, #else .prf_ikev1_ops = &ike_alg_prf_ikev1_mac_ops, .prf_ikev2_ops = &ike_alg_prf_ikev2_mac_ops, #endif .prf_ike_audit_name = "sha512", }; const struct integ_desc ike_alg_integ_sha2_512 = { .common = { .name = "sha2_512", .fqn = "HMAC_SHA2_512_256", .names = "sha512,sha2_512,sha2_512_256,hmac_sha2_512,hmac_sha2_512_256", .algo_type = IKE_ALG_INTEG, .id = { [IKEv1_OAKLEY_ID] = OAKLEY_SHA2_512, [IKEv1_ESP_ID] = AUTH_ALGORITHM_HMAC_SHA2_512, [IKEv2_ALG_ID] = IKEv2_AUTH_HMAC_SHA2_512_256, }, .fips = true, }, .integ_keymat_size = SHA2_512_DIGEST_SIZE, .integ_output_size = SHA2_512_DIGEST_SIZE / 2, .integ_ikev1_ah_transform = AH_SHA2_512, .prf = &ike_alg_prf_sha2_512, #ifdef SADB_X_AALG_SHA2_512HMAC .integ_sadb_aalg_id = SADB_X_AALG_SHA2_512HMAC, #endif #ifdef SADB_X_AALG_SHA2_512 .integ_sadb_aalg_id = SADB_X_AALG_SHA2_512, #endif .integ_netlink_xfrm_name = "hmac(sha512)", .integ_tcpdump_name = "sha512", .integ_ike_audit_name = "sha512", .integ_kernel_audit_name = "HMAC_SHA2_512", }; const CK_RSA_PKCS_PSS_PARAMS rsa_pss_sha2_512 = { .hashAlg = CKM_SHA512, .mgf = CKG_MGF1_SHA512, .sLen = SHA2_512_DIGEST_SIZE, }; static const uint8_t asn1_blob_512[ASN1_LEN_ALGO_IDENTIFIER + ASN1_SHA2_RSA_PSS_SIZE] = { LEN_RSA_PSS_SHA2_BLOB, RSA_PSS_SHA512_BLOB }; const struct asn1_hash_blob asn1_rsa_pss_sha2_512 = { .hash_algo = IKEv2_AUTH_HASH_SHA2_512, .blob = asn1_blob_512, .blob_sz = sizeof(asn1_blob_512), }; static const uint8_t asn1_blob_ecdsa_512[ASN1_LEN_ALGO_IDENTIFIER + ASN1_SHA2_ECDSA_SIZE] = { LEN_ECDSA_SHA2_BLOB, ECDSA_SHA512_BLOB }; const struct asn1_hash_blob asn1_ecdsa_sha2_512 = { .hash_algo = IKEv2_AUTH_HASH_SHA2_512, .blob = asn1_blob_ecdsa_512, .blob_sz = sizeof(asn1_blob_ecdsa_512) }; libreswan-3.32/lib/libswan/ike_alg_test.c000066400000000000000000000032541365625662500204560ustar00rootroot00000000000000/* Test algorithms, for libreswan * * Copyright (C) 2018 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include "lswlog.h" #include "ike_alg.h" #include "ike_alg_encrypt.h" #include "ike_alg_prf.h" #include "ike_alg_test_ctr.h" #include "ike_alg_test_cbc.h" #include "ike_alg_test_gcm.h" #include "ike_alg_test_prf.h" #define TEST(TESTER, ALG, TESTS) \ if (!ike_alg_is_valid(&(ALG).common)) { \ libreswan_log("skipping tests for disabled %s algorithm", \ (ALG).common.fqn); \ } else { \ libreswan_log("testing %s:", (ALG).common.fqn); \ passert(TESTER(&ALG, TESTS)); \ } void test_ike_alg(void) { #ifdef USE_CAMELLIA TEST(test_cbc_vectors, ike_alg_encrypt_camellia_cbc, camellia_cbc_tests); #endif #ifdef USE_AES TEST(test_gcm_vectors, ike_alg_encrypt_aes_gcm_16, aes_gcm_tests); TEST(test_ctr_vectors, ike_alg_encrypt_aes_ctr, aes_ctr_tests); TEST(test_cbc_vectors, ike_alg_encrypt_aes_cbc, aes_cbc_tests); #endif #ifdef USE_PRF_AES_XCBC TEST(test_prf_vectors, ike_alg_prf_aes_xcbc, aes_xcbc_prf_tests); #endif #ifdef USE_MD5 TEST(test_prf_vectors, ike_alg_prf_hmac_md5, hmac_md5_prf_tests); #endif } libreswan-3.32/lib/libswan/ike_alg_twofish.c000066400000000000000000000102141365625662500211540ustar00rootroot00000000000000/* * IKE modular algorithm handling interface * Author: JuanJo Ciarlante * Copyright (C) 2005-2007 Michael Richardson * Copyright (C) 2011-2012 Paul Wouters * Copyright (C) 2013 D. Hugh Redelmeier * Copyright (C) 2013 Paul Wouters * Copyright (C) 2016-2017 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include "libtwofish/twofish_cbc.h" #include "constants.h" /* for BYTES_FOR_BITS() */ #include "lswcdefs.h" /* for UNUSED */ #include "lswlog.h" #include "ike_alg.h" #include "ike_alg_encrypt.h" #include "ike_alg_encrypt_ops.h" #include "ietf_constants.h" #include "sadb.h" static void do_twofish(const struct encrypt_desc *alg UNUSED, uint8_t *buf, size_t buf_size, PK11SymKey *key, uint8_t *iv, bool enc) { twofish_context twofish_ctx; char iv_bak[TWOFISH_CBC_BLOCK_SIZE]; char *new_iv = NULL; /* logic will avoid copy to NULL */ uint8_t *bare_key_ptr; size_t bare_key_len; /* unpack key from PK11SymKey (or crash!) */ { SECStatus status = PK11_ExtractKeyValue(key); SECItem *keydata; passert(status == SECSuccess); keydata = PK11_GetKeyData(key); bare_key_ptr = keydata->data; bare_key_len = keydata->len; // SECITEM_FreeItem(keydata, PR_TRUE); } twofish_set_key(&twofish_ctx, bare_key_ptr, bare_key_len); /* * my TWOFISH cbc does not touch passed IV (optimization for * ESP handling), so I must "emulate" des-like IV * crunching */ if (!enc) { memcpy(new_iv = iv_bak, (char*) buf + buf_size - TWOFISH_CBC_BLOCK_SIZE, TWOFISH_CBC_BLOCK_SIZE); } twofish_cbc_encrypt(&twofish_ctx, buf, buf, buf_size, iv, enc); if (enc) new_iv = (char*) buf + buf_size - TWOFISH_CBC_BLOCK_SIZE; memcpy(iv, new_iv, TWOFISH_CBC_BLOCK_SIZE); } static void twofish_check(const struct encrypt_desc *alg UNUSED) { } static const struct encrypt_ops twofish_encrypt_ops = { .backend = "twofish", .check = twofish_check, .do_crypt = do_twofish, }; const struct encrypt_desc ike_alg_encrypt_twofish_cbc = { .common = { .name = "twofish", .fqn = "TWOFISH_CBC", .names = "twofish,twofish_cbc", .algo_type = IKE_ALG_ENCRYPT, .id = { [IKEv1_OAKLEY_ID] = OAKLEY_TWOFISH_CBC, [IKEv1_ESP_ID] = ESP_TWOFISH, [IKEv2_ALG_ID] = IKEv2_ENCR_TWOFISH_CBC, }, }, .enc_blocksize = TWOFISH_CBC_BLOCK_SIZE, .pad_to_blocksize = true, .wire_iv_size = TWOFISH_CBC_BLOCK_SIZE, .keydeflen = TWOFISH_KEY_DEF_LEN, .key_bit_lengths = { 256, 192, 128, }, .encrypt_ops = &twofish_encrypt_ops, #ifdef SADB_X_EALG_TWOFISHCBC .encrypt_sadb_ealg_id = SADB_X_EALG_TWOFISHCBC, #endif .encrypt_netlink_xfrm_name = "twofish", .encrypt_tcpdump_name = "twofish", .encrypt_ike_audit_name = "twofish", .encrypt_kernel_audit_name = "TWOFISH", }; const struct encrypt_desc ike_alg_encrypt_twofish_ssh = { .common = { .name = "twofish_ssh", /* We don't know if this is right */ .fqn = "TWOFISH_SSH", /* We don't know if this is right */ .names = "twofish_ssh,twofish_cbc_ssh", .algo_type = IKE_ALG_ENCRYPT, .id = { [IKEv1_OAKLEY_ID] = OAKLEY_TWOFISH_CBC_SSH, [IKEv1_ESP_ID] = -1, [IKEv2_ALG_ID] = IKEv2_ENCR_TWOFISH_CBC_SSH, }, }, .enc_blocksize = TWOFISH_CBC_BLOCK_SIZE, .pad_to_blocksize = true, .wire_iv_size = TWOFISH_CBC_BLOCK_SIZE, .keydeflen = TWOFISH_KEY_DEF_LEN, .key_bit_lengths = { 256, 192, 128, }, .encrypt_ops = &twofish_encrypt_ops, .encrypt_tcpdump_name = "twofish_ssh", /* We don't know if this is right */ .encrypt_ike_audit_name = "twofish_ssh", /* We don't know if this is right */ .encrypt_kernel_audit_name = "TWOFISH_SSH", /* We don't know if this is right */ }; libreswan-3.32/lib/libswan/ike_info.c000066400000000000000000000123561365625662500176120ustar00rootroot00000000000000/* * Algorithm info parsing and creation functions * Author: JuanJo Ciarlante * * Copyright (C) 2012 Paul Wouters * Copyright (C) 2015-2019 Andrew Cagney * Copyright (C) 2019 Paul Wouters * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include "lswlog.h" #include "lswalloc.h" #include "alg_byname.h" #include "ike_alg.h" #include "ike_alg_encrypt.h" #include "ike_alg_integ.h" #include "ike_alg_prf.h" #include "ike_alg_dh.h" #include "proposals.h" static bool ike_proposal_ok(struct proposal_parser *parser, const struct proposal *proposal) { if (!proposal_aead_none_ok(parser, proposal)) { if (!impair_proposal_errors(parser)) { return false; } } /* * Check that the ALG_INFO spec is implemented. */ impaired_passert(PROPOSAL_PARSER, next_algorithm(proposal, PROPOSAL_encrypt, NULL) != NULL); FOR_EACH_ALGORITHM(proposal, encrypt, alg) { const struct encrypt_desc *encrypt = encrypt_desc(alg->desc); passert(ike_alg_is_ike(&encrypt->common)); passert(IMPAIR(PROPOSAL_PARSER) || alg->enckeylen == 0 || encrypt_has_key_bit_length(encrypt, alg->enckeylen)); } impaired_passert(PROPOSAL_PARSER, next_algorithm(proposal, PROPOSAL_prf, NULL) != NULL); FOR_EACH_ALGORITHM(proposal, prf, alg) { const struct prf_desc *prf = prf_desc(alg->desc); passert(ike_alg_is_ike(&prf->common)); } impaired_passert(PROPOSAL_PARSER, next_algorithm(proposal, PROPOSAL_integ, NULL) != NULL); FOR_EACH_ALGORITHM(proposal, integ, alg) { const struct integ_desc *integ = integ_desc(alg->desc); passert(integ == &ike_alg_integ_none || ike_alg_is_ike(&integ->common)); } impaired_passert(PROPOSAL_PARSER, next_algorithm(proposal, PROPOSAL_dh, NULL) != NULL); FOR_EACH_ALGORITHM(proposal, dh, alg) { const struct dh_desc *dh = dh_desc(alg->desc); passert(ike_alg_is_ike(&dh->common)); if (dh == &ike_alg_dh_none) { proposal_error(parser, "IKE DH algorithm 'none' not permitted"); if (!impair_proposal_errors(parser)) { return false; } } } return true; } /* * IKEv1: * * since ike= must have an encryption algorithm this is normally * ignored. * * "ike_info" proposals are built built by first parsing the ike= * line, and second merging it with the below defaults when an * algorithm wasn't specified. * * Do not assume that these hard wired algorithms are actually valid. */ const char default_v1_ike_proposals[] = "AES_CBC" "," "3DES" ; static const struct ike_alg *default_v1_ike_prfs[] = { #ifdef USE_SHA2 &ike_alg_prf_sha2_256.common, &ike_alg_prf_sha2_512.common, #endif #ifdef USE_SHA1 &ike_alg_prf_sha1.common, #endif NULL, }; static const struct ike_alg *default_v1_groups[] = { &ike_alg_dh_modp2048.common, &ike_alg_dh_modp1536.common, NULL, }; const struct proposal_defaults v1_ike_defaults = { .proposals = default_v1_ike_proposals, .dh = default_v1_groups, .prf = default_v1_ike_prfs, }; /* * IKEv2: * * since ike= must have an encryption algorithm this is normally * ignored. * * "ike_info" proposals are built built by first parsing the ike= * line, and second merging it with the below defaults when an * algorithm wasn't specified. * * Do not assume that these hard wired algorithms are actually valid. * * The proposals expanded using the default algorithms. * * Note: Strongswan cherry-picks proposals (for instance will * pick AES_128 over AES_256 when both are in the same * proposal) so, for moment, don't merge things. */ static const char default_v2_ike_proposals[] = "AES_GCM_16_256" "," "AES_GCM_16_128" "," "AES_CBC_256" "," "AES_CBC_128" ; static const struct ike_alg *default_v2_ike_prfs[] = { #ifdef USE_SHA2 &ike_alg_prf_sha2_512.common, &ike_alg_prf_sha2_256.common, #endif NULL, }; static const struct ike_alg *default_v2_groups[] = { &ike_alg_dh_modp2048.common, &ike_alg_dh_modp3072.common, &ike_alg_dh_modp4096.common, &ike_alg_dh_modp8192.common, &ike_alg_dh_dh19.common, &ike_alg_dh_dh20.common, &ike_alg_dh_dh21.common, #ifdef USE_DH31 &ike_alg_dh_dh31.common, #endif NULL, }; const struct proposal_defaults v2_ike_defaults = { .proposals = default_v2_ike_proposals, .prf = default_v2_ike_prfs, /* INTEG is derived from PRF when applicable */ .dh = default_v2_groups, }; /* * All together now ... */ const struct proposal_protocol ike_proposal_protocol = { .name = "IKE", .ikev1_alg_id = IKEv1_OAKLEY_ID, .defaults = { [IKEv1] = &v1_ike_defaults, [IKEv2] = &v2_ike_defaults, }, .proposal_ok = ike_proposal_ok, .encrypt = true, .prf = true, .integ = true, .dh = true, }; struct proposal_parser *ike_proposal_parser(const struct proposal_policy *policy) { return alloc_proposal_parser(policy, &ike_proposal_protocol); } libreswan-3.32/lib/libswan/impair.c000066400000000000000000000461671365625662500173170ustar00rootroot00000000000000/* impair constants, for libreswan * * Copyright (C) 2017-2019 Andrew Cagney * Copyright (C) 2019-2019 Paul Wouters * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include #include "constants.h" #include "enum_names.h" #include "lmod.h" #include "keywords.h" #include "impair.h" #include "lswlog.h" /* * Initialize both the .name and .help arrays. * * See plutomain.c why the name has an extra "\0" appended (hint it is * a hack for encoding what to do with flags). * * XXX: since only the --impair ... form is supported, has this all * become redundant. * * So that grepping for IMPAIR. finds this file, the N parameter * is the full enum name (IMPAIR_...) and not just the truncated * suffix. */ struct double_double { const char *name[IMPAIR_roof_IX - IMPAIR_floor_IX]; const char *help[IMPAIR_roof_IX - IMPAIR_floor_IX]; }; static struct double_double impair = { #define S(N,A,H) \ .name[N##_IX - IMPAIR_floor_IX] = A "\0", \ .help[N##_IX - IMPAIR_floor_IX] = H S(IMPAIR_ADD_UNKNOWN_PAYLOAD_TO_AUTH, "impair-add-unknown-payload-to-auth", "add a payload with an unknown type to AUTH"), S(IMPAIR_ADD_UNKNOWN_PAYLOAD_TO_AUTH_SK, "impair-add-unknown-payload-to-auth-sk", "add a payload with an unknown type to AUTH's SK payload"), S(IMPAIR_ADD_UNKNOWN_PAYLOAD_TO_SA_INIT, "impair-add-unknown-payload-to-sa-init", "add a payload with an unknown type to SA_INIT"), S(IMPAIR_ALLOW_DNS_INSECURE, "impair-allow-dns-insecure", "allow IPSECKEY lookups without DNSSEC protection"), S(IMPAIR_ALLOW_NULL_NONE, "impair-allow-null-none", "cause pluto to allow esp=null-none and ah=none for testing"), S(IMPAIR_BUST_MI2, "impair-bust-mi2", "make MI2 really large"), S(IMPAIR_BUST_MR2, "impair-bust-mr2", "make MR2 really large"), S(IMPAIR_CORRUPT_ENCRYPTED, "impair-corrupt-encrypted", "corrupts the encrypted packet so that the decryption fails"), S(IMPAIR_DELETE_ON_RETRANSMIT, "impair-delete-on-retransmit", "causes pluto to fail on the first retransmit"), S(IMPAIR_DROP_I2, "impair-drop-i2", "drop second initiator packet"), S(IMPAIR_DROP_XAUTH_R0, "impair-drop-xauth-r0", "causes pluto to drop an XAUTH user/passwd request on IKE initiator"), S(IMPAIR_FORCE_FIPS, "impair-force-fips", "causes pluto to believe we are in fips mode, NSS needs its own hack"), S(IMPAIR_IGNORE_HASH_NOTIFY_REQUEST, "impair-ignore-hash-notify", "causes pluto to ignore incoming hash notify from IKE_SA_INIT Request"), S(IMPAIR_IGNORE_HASH_NOTIFY_RESPONSE, "impair-ignore-hash-notify-resp", "causes pluto to ignore incoming hash notify from IKE_SA_INIT Response"), S(IMPAIR_IKEv2_EXCLUDE_INTEG_NONE, "impair-ikev2-exclude-integ-none", "lets pluto exclude integrity 'none' in proposals"), S(IMPAIR_IKEv2_INCLUDE_INTEG_NONE, "impair-ikev2-include-integ-none", "lets pluto include integrity 'none' in proposals"), S(IMPAIR_JACOB_TWO_TWO, "impair-jacob-two-two", "cause pluto to send all messages twice."), S(IMPAIR_MAJOR_VERSION_BUMP, "impair-major-version-bump", "cause pluto to send an IKE major version that's higher then we support."), S(IMPAIR_MINOR_VERSION_BUMP, "impair-minor-version-bump", "cause pluto to send an IKE minor version that's higher then we support."), S(IMPAIR_OMIT_HASH_NOTIFY_REQUEST, "impair-omit-hash-notify", "causes pluto to omit sending hash notify in IKE_SA_INIT Request"), S(IMPAIR_PROPOSAL_PARSER, "impair-proposal-parser", "impair algorithm parser - what you see is what you get"), S(IMPAIR_REPLAY_BACKWARD, "impair-replay-backward", "replay all earlier packets new-to-old"), S(IMPAIR_REPLAY_DUPLICATES, "impair-replay-duplicates", "replay duplicates of each incoming packet"), S(IMPAIR_REPLAY_ENCRYPTED, "impair-replay-encrypted", "replay encrypted packets"), S(IMPAIR_REPLAY_FORWARD, "impair-replay-forward", "replay all earlier packets old-to-new"), S(IMPAIR_SA_CREATION, "impair-sa-creation", "fail all SA creation"), S(IMPAIR_SEND_BOGUS_DCOOKIE, "impair-send-bogus-dcookie", "causes pluto to send a a bogus IKEv2 DCOOKIE"), S(IMPAIR_SEND_BOGUS_ISAKMP_FLAG, "impair-send-bogus-isakmp-flag", "causes pluto to set a RESERVED ISAKMP flag to test ignoring/zeroing it"), S(IMPAIR_SEND_BOGUS_PAYLOAD_FLAG, "impair-send-bogus-payload-flag", "causes pluto to set a RESERVED PAYLOAD flag to test ignoring/zeroing it"), S(IMPAIR_SEND_KEY_SIZE_CHECK, "impair-send-key-size-check", "causes pluto to omit checking configured ESP key sizes for testing"), S(IMPAIR_SEND_NO_DELETE, "impair-send-no-delete", "causes pluto to omit sending Notify/Delete messages"), S(IMPAIR_SEND_NO_IKEV2_AUTH, "impair-send-no-ikev2-auth", "causes pluto to omit sending an IKEv2 IKE_AUTH packet"), S(IMPAIR_SEND_NO_MAIN_R2, "impair-send-no-main-r2", "causes pluto to omit sending an last Main Mode response packet"), S(IMPAIR_SEND_NO_XAUTH_R0, "impair-send-no-xauth-r0", "causes pluto to omit sending an XAUTH user/passwd request"), S(IMPAIR_SEND_PKCS7_THINGIE, "impair-send-pkcs7-thingie", "send certificates as a PKCS7 thingie"), S(IMPAIR_SUPPRESS_RETRANSMITS, "impair-suppress-retransmits", "causes pluto to never send retransmits (wait the full timeout)"), S(IMPAIR_TIMEOUT_ON_RETRANSMIT, "impair-timeout-on-retransmit", "causes pluto to 'retry' (switch protocol) on the first retransmit"), S(IMPAIR_UNKNOWN_PAYLOAD_CRITICAL, "impair-unknown-payload-critical", "mark the unknown payload as critical"), S(IMPAIR_IKEv1_DEL_WITH_NOTIFY, "impair-ikev1-del-with-notify", "causes pluto to send IKE Delete with additional bogus Notify payload"), S(IMPAIR_BAD_IKE_AUTH_XCHG, "impair-bad-ikev2-auth-xchg", "causes pluto to send IKE_AUTH replies with wrong exchange type"), S(IMPAIR_REKEY_INITIATOR_SUPERNET, "impair-rekey-initiate-supernet", "cause pluto to send IPsec SA rekey on initiator with TSi and TSR to 0/0 ::0, to emulate Windows client"), S(IMPAIR_REKEY_RESPOND_SUPERNET, "impair-rekey-respond-supernet", "cause pluto to send IPsec SA rekey responder TSi and TSR to 0/0 ::0"), S(IMPAIR_REKEY_RESPOND_SUBNET, "impair-rekey-respond-subnet", "cause pluto to send IPsec SA rekey responder TSi and TSR to X/32 X/128"), #undef S }; const enum_names impair_names = { IMPAIR_floor_IX, IMPAIR_roof_IX - 1, ARRAY_REF(impair.name), "impair-", NULL, }; const struct lmod_info impair_lmod_info = { .names = &impair_names, .all = IMPAIR_MASK, .mask = IMPAIR_MASK, }; const struct enum_names impair_help = { IMPAIR_floor_IX, IMPAIR_roof_IX - 1, ARRAY_REF(impair.help), NULL, NULL, }; static const struct keyword send_impairment_value[] = { #define S(E, H) [SEND_##E] = { .name = "SEND_" #E, .sname = #E, .value = SEND_##E, .details = H, } S(NORMAL, "send normal content"), S(OMIT, "do not send content"), S(EMPTY, "send zero length content"), S(DUPLICATE, "duplicate content"), #undef S }; static const struct keywords send_impairment_keywords = DIRECT_KEYWORDS("send impaired content", send_impairment_value); static const struct keyword exchange_impairment_value[] = { #define S(E, H) [E##_EXCHANGE] = { .name = "SEND_" #E, .sname = #E, .value = E##_EXCHANGE, .details = H, } S(NO, "do not modify exchanges"), S(QUICK, "modify IKEv1 QUICK exchanges"), S(XAUTH, "modify IKEv1 XAUTH exchanges"), S(NOTIFICATION, "modify notification (informational) exchanges"), S(DELETE, "modify delete exchanges"), #undef S }; static const struct keywords exchange_impairment_keywords = DIRECT_KEYWORDS("impaire exchange content", exchange_impairment_value); struct impairment { const char *what; const char *help; /* * If non-NULL, HOW is either a keyword or an (unsigned) * number encoded as keywords.nr_keywords+NUMBER. * * If NULL, HOW is assumed to be a boolean. */ const struct keywords *how_keynum; void *value; /* size_t offsetof_value; */ size_t sizeof_value; }; struct impairment impairments[] = { { .what = NULL, }, #define V(V) .value = &V, .sizeof_value = sizeof(V) { .what = "revival", .help = "disable code that revives a connection that is supposed to stay up", V(impair_revival), }, { .what = "emitting", .help = "disable correctness-checks when emitting a payload (let anything out)", V(impair_emitting), }, { .what = "ke-payload", .help = "corrupt the outgoing KE payload", .how_keynum = &send_impairment_keywords, V(impair_ke_payload), }, /* * IKEv1: the key-length attribute is at the same level as * other attributes such as encryption. Just need to know if * the IKE, or CHILD proposal set should be manipulated. * * IKEv2: the key-length attribute is nested within an * encryption transform. Hence, also need to know which * transform to screw with. */ { .what = "ike-key-length-attribute", .help = "corrupt the outgoing IKE proposal's key length attribute", .how_keynum = &send_impairment_keywords, V(impair_ike_key_length_attribute), }, { .what = "child-key-length-attribute", .help = "corrupt the outgoing CHILD proposal's key length attribute", .how_keynum = &send_impairment_keywords, V(impair_child_key_length_attribute), }, { .what = "log-rate-limit", .help = "set the per-hour(?) cap on rate-limited log messages", V(impair_log_rate_limit), }, /* * IKEv1: hash payloads */ { .what = "v1-hash-check", .help = "disable check of incoming IKEv1 hash payload", V(impair_emitting), }, { .what = "v1-hash-payload", .help = "corrupt the outgoing HASH payload", .how_keynum = &send_impairment_keywords, V(impair_v1_hash_payload), }, { .what = "v1-hash-exchange", .help = "the outgoing exchange that should contain the corrupted HASH payload", .how_keynum = &exchange_impairment_keywords, V(impair_v1_hash_exchange), }, }; static void help(const char *prefix, const struct impairment *cr) { LSWLOG_INFO(buf) { lswlogf(buf, "%s%s: %s", prefix, cr->what, cr->help); } if (cr->how_keynum != NULL) { const struct keywords *kw = cr->how_keynum; for (unsigned ki = 0; ki < kw->nr_values; ki++) { const struct keyword *kv = &kw->values[ki]; if (kv->name != NULL) { LSWLOG_INFO(buf) { lswlogf(buf, "%s %s: %s", prefix, kv->sname, kv->details); } } } LSWLOG_INFO(buf) { lswlogf(buf, "%s %s: %s", prefix, "", "use the unsigned value"); } } } void help_impair(const char *prefix) { for (unsigned ci = 1; ci < elemsof(impairments); ci++) { const struct impairment *cr = &impairments[ci]; help(prefix, cr); } } /* * Return the long value in STRING, but with +ve values adjusted by * BIAS. */ static bool parse_biased_unsigned(shunk_t string, unsigned *dest, unsigned bias) { unsigned u; if (shunk_tou(string, &u, 0)) { if (u <= UINT_MAX - bias) { *dest = u + bias; return true; } else { return false; } } else { return false; } } #define IMPAIR_DISABLE (elemsof(impairments) + 0) #define IMPAIR_LIST (elemsof(impairments) + 1) bool parse_impair(const char *optarg, struct whack_impair *whack_impair, bool enable) { if (streq(optarg, "help")) { help_impair(""); return false; } else if (whack_impair->what != 0) { LSWLOG_ERROR(buf) { lswlogf(buf, "ignoring option '--impair %s'", optarg); } return true; } else if (enable && streq(optarg, "none")) { *whack_impair = (struct whack_impair) { .what = IMPAIR_DISABLE, .how = 0, }; return true; } else if (enable && streq(optarg, "list")) { *whack_impair = (struct whack_impair) { .what = IMPAIR_LIST, .how = 0, }; return true; } /* Break OPTARG into WHAT[=HOW] */ shunk_t arg = shunk1(optarg); shunk_t what = shunk_token(&arg, NULL, ":="); shunk_t how = arg; /* * look for both WHAT and for compatibility with the old * lset_t impair flags, no-WHAT. */ unsigned ci = 1; shunk_t nowhat = what; /* reject --no-impair no-... */ bool no = enable ? shunk_strcaseeat(&nowhat, "no-") : true; while (true) { if (ci >= elemsof(impairments)) { LSWLOG_ERROR(buf) { lswlogf(buf, "ignoring unrecognized option '-%s-impair "PRI_SHUNK"'", enable ? "" : "-no", pri_shunk(what)); } return false; } else if (shunk_strcaseeq(nowhat, impairments[ci].what)) { break; } ci++; } const struct impairment *cr = &impairments[ci]; /* --{,no-}impair WHAT:help always works */ if (shunk_strcaseeq(how, "help")) { help("", cr); return false; } /* * Ensure that --no-impair WHAT, --impair no-WHAT, --impair * WHAT:no, all always work. */ if (no || shunk_strcaseeq(how, "no")) { /* reject --no-impair WHAT:no and --impair no-WHAT:no */ if (no && how.len > 0) { LSWLOG_ERROR(buf) { lswlogf(buf, "ignoring option '-%s-impair "PRI_SHUNK":"PRI_SHUNK"' with unexpected parameter '"PRI_SHUNK"'", enable ? "" : "-no", pri_shunk(what), pri_shunk(how), pri_shunk(how)); } return false; } *whack_impair = (struct whack_impair) { .what = ci, .how = 0, }; return true; } if (cr->how_keynum != NULL) { /* * parse --impair WHAT:HOW */ if (how.len == 0) { LSWLOG_ERROR(buf) { lswlogf(buf, "ignoring option '--impair "PRI_SHUNK"' with missing parameter", pri_shunk(what)); } return false; } /* try the keyword. */ const struct keyword *kw = keyword_by_sname(cr->how_keynum, how); if (kw != NULL) { *whack_impair = (struct whack_impair) { .what = ci, .how = kw->value, }; return true; } unsigned biased_value; if (parse_biased_unsigned(how, &biased_value, cr->how_keynum->nr_values)) { *whack_impair = (struct whack_impair) { .what = ci, .how = biased_value, }; return true; } LSWLOG_ERROR(buf) { lswlogf(buf, "ignoring option '--impair "PRI_SHUNK":"PRI_SHUNK"' with unknown parameter '"PRI_SHUNK"'", pri_shunk(what), pri_shunk(how), pri_shunk(how)); } return false; } else { /* * Only allow simple booleans for now (it could call * parse_piased_unsigned). * * Accept some common terms, and assume an empty WHAT * implies 'yes'. * * XXX: Yes, "no" was already handled above. It's * also here so that the two if() clauses look * consistent. */ if (shunk_strcaseeq(how, "false") || shunk_strcaseeq(how, "off") || shunk_strcaseeq(how, "no")) { /* --impair WHAT:nope */ *whack_impair = (struct whack_impair) { .what = ci, .how = 0, }; return true; } else if (how.len == 0 || shunk_strcaseeq(how, "true") || shunk_strcaseeq(how, "on") || shunk_strcaseeq(how, "yes")) { /* --impair WHAT:yes */ *whack_impair = (struct whack_impair) { .what = ci, .how = 1, }; return true; } else { unsigned value = 0; if (parse_biased_unsigned(how, &value, 0)) { *whack_impair = (struct whack_impair) { .what = ci, .how = value, }; return true; } /* XXX: ignores "WHAT:" */ LSWLOG_ERROR(buf) { lswlogf(buf, "ignoring option '--impair "PRI_SHUNK":"PRI_SHUNK"' with unexpected parameter '"PRI_SHUNK"'", pri_shunk(what), pri_shunk(how), pri_shunk(how)); } return false; } } } /* * Print something that can be fed back into --impair ARG. */ static uintmax_t value_of(const struct impairment *cr) { switch (cr->sizeof_value) { #define L(T) case sizeof(uint##T##_t): return *(uint##T##_t*)cr->value L(8); L(16); L(32); L(64); #undef L default: bad_case(cr->sizeof_value); } } static void lswlog_impairment(struct lswlog *buf, const struct impairment *cr) { if (cr->how_keynum != NULL) { lswlogf(buf, "%s:", cr->what); unsigned value = value_of(cr); const struct keyword *kw = keyword_by_value(cr->how_keynum, value); if (kw != NULL) { lswlogs(buf, kw->sname); } else if (value >= cr->how_keynum->nr_values) { lswlogf(buf, "%zu", value - cr->how_keynum->nr_values); } else { lswlogf(buf, "?%u?", value); } } else { /* only bool for now */ uintmax_t value = value_of(cr); if (value == 0) { /* parser accepts this */ jam(buf, "%s:no", cr->what); } else if (value == 1) { /* parser accepts this */ jam(buf, "%s", cr->what); } else { jam(buf, "%s:%ju", cr->what, value); } } } void lswlog_impairments(struct lswlog *buf, const char *prefix, const char *sep) { /* is there anything enabled? */ lset_t cur_impairing = (cur_debugging & IMPAIR_MASK); bool enabled = false; for (unsigned ci = 1; ci < elemsof(impairments); ci++) { const struct impairment *cr = &impairments[ci]; if (value_of(cr) != 0) { enabled = true; break; } } if (!enabled && cur_impairing == LEMPTY) { return; } lswlogs(buf, prefix); if (cur_impairing != LEMPTY) { /* avoid LEMPTY being printed as "none" */ lswlog_enum_lset_short(buf, &impair_names, sep, cur_impairing); } const char *s = ""; for (unsigned ci = 1; ci < elemsof(impairments); ci++) { const struct impairment *cr = &impairments[ci]; if (value_of(cr) != 0) { lswlogs(buf, s); s = sep; lswlog_impairment(buf, cr); } } } void process_impair(const struct whack_impair *wc) { if (wc->what == 0) { /* ignore; silently */ return; } else if (wc->what == IMPAIR_DISABLE) { for (unsigned ci = 1; ci < elemsof(impairments); ci++) { const struct impairment *cr = &impairments[ci]; if (value_of(cr) != 0) { LSWDBGP(DBG_BASE, buf) { lswlogf(buf, "%s: ", cr->what); lswlogs(buf, " disabled"); } memset(cr->value, 0, cr->sizeof_value); } } return; } else if (wc->what == IMPAIR_LIST) { for (unsigned ci = 1; ci < elemsof(impairments); ci++) { const struct impairment *cr = &impairments[ci]; if (value_of(cr) != 0) { /* XXX: should be whack log? */ LSWLOG_INFO(buf) { lswlog_impairment(buf, cr); } } } return; } else if (wc->what >= elemsof(impairments)) { LSWLOG_ERROR(buf) { lswlogf(buf, "impairment %u out-of-range", wc->what); } return; } const struct impairment *cr = &impairments[wc->what]; if (cr->how_keynum != NULL) { passert(cr->sizeof_value == sizeof(unsigned)); *(unsigned*)cr->value = wc->how; /* do not un-bias */ } else switch (cr->sizeof_value) { #define L(T) case sizeof(uint##T##_t): *(uint##T##_t*)cr->value = wc->how; break; L(8); L(16); L(32); L(64); #undef L default: bad_case(cr->sizeof_value); } LSWDBGP(DBG_BASE, buf) { lswlog_impairment(buf, cr); } } /* * XXX: define these at the end of the file so that all references are * forced to use the declaration in the header (help stop code * referring to the wrong variable?). */ bool impair_revival; bool impair_emitting; enum send_impairment impair_ke_payload; enum send_impairment impair_ike_key_length_attribute; enum send_impairment impair_child_key_length_attribute; unsigned impair_log_rate_limit; bool impair_v1_hash_check; enum send_impairment impair_v1_hash_payload; enum exchange_impairment impair_v1_hash_exchange; libreswan-3.32/lib/libswan/initaddr.3.xml000066400000000000000000000142221365625662500203360ustar00rootroot00000000000000 PaulWoutersplaceholder to suppress warning IPSEC_INITADDR 3 11 Sept 2000 libreswan Executable programs ipsec initaddr ipsec addrtypeof ipsec addrlenof ipsec addrbytesof ipsec addrbytesptr_read ipsec addrbytesptr_write initialize an ip_address, get address type of an ip_address, get length of address within an ip_address, get copy of address within an ip_address, get pointer to address within an ip_address #include <libreswan.h> const char *initaddr const char * src size_t srclen int af ip_address * dst int addrtypeof const ip_address * src size_t addrlenof const ip_address * src size_t addrbytesof const ip_address * src unsigned char * dst size_t dstlen size_t addrbytesptr_read const ip_address * src const unsigned char ** dst size_t addrbytesptr_write ip_address * src unsigned char ** dst DESCRIPTION The <libreswan.h> library uses an internal type ip_address to contain one of the (currently two) types of IP address. These functions provide basic tools for creating and examining this type. initaddr initializes a variable *dst of type ip_address from an address (in network byte order, indicated by a pointer src and a length srclen) and an address family af (typically AF_INET or AF_INET6). The length must be consistent with the address family. addrtypeof returns the address type of an address, normally AF_INET or AF_INET6. (The <libreswan.h> header file arranges to include the necessary headers for these names to be known.) addrlenof returns the size (in bytes) of the address within an ip_address, to permit storage allocation etc. addrbytesof copies the address within the ip_address src to the buffer indicated by the pointer dst and the length dstlen, and returns the address length (in bytes). If the address will not fit, as many bytes as will fit are copied; the returned length is still the full length. It is the caller's responsibility to check the returned value to ensure that there was enough room. addrbytesptr_read and addrbytesptr_write and set *dst to a pointer to the internal address within the ip_address, and returns the address length (in bytes). If dst is NULL, it just returns the address length. initaddr returns NULL for success and a pointer to a string-literal error message for failure; see DIAGNOSTICS. The functions which return size_t return 0 for a failure. SEE ALSO inet3, ipsec_ttoaddr3 DIAGNOSTICS An unknown address family is a fatal error for any of these functions except addrtypeof. An address-size mismatch is a fatal error for initaddr. HISTORY Written for the FreeS/WAN project by Henry Spencer. BUGS addrtypeof should probably have been named addrfamilyof. libreswan-3.32/lib/libswan/initaddr.c000066400000000000000000000032661365625662500176250ustar00rootroot00000000000000/* * initialize address structure * Copyright (C) 2000 Henry Spencer. * Copyroght (C) 2009 Paul Wouters * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. * */ #include #include "ip_info.h" #include "ip_address.h" #include "libreswan/passert.h" #include "lswlog.h" /* for bad_case() */ /* - initaddr - initialize ip_address from bytes */ err_t data_to_address(const void *data, size_t sizeof_data, const struct ip_info *afi, ip_address *dst) { if (afi == NULL) { *dst = address_invalid; return "unknown address family"; } switch (afi->af) { case AF_INET: if (sizeof_data != 4) return "IPv4 address must be exactly 4 bytes"; passert(sizeof_data == sizeof(struct in_addr)); struct in_addr in; /* force alignment of data */ memcpy(&in, data, sizeof_data); *dst = address_from_in_addr(&in); break; case AF_INET6: if (sizeof_data != 16) return "IPv6 address must be exactly 16 bytes"; passert(sizeof_data == sizeof(struct in6_addr)); struct in6_addr in6; /* force alignment of data */ memcpy(&in6, data, sizeof_data); *dst = address_from_in6_addr(&in6); break; default: bad_case(afi->af); } return NULL; } libreswan-3.32/lib/libswan/initsubnet.3.xml000066400000000000000000000144121365625662500207250ustar00rootroot00000000000000 PaulWoutersplaceholder to suppress warning IPSEC_INITSUBNET 3 12 March 2002 libreswan Library functions ipsec initsubnet ipsec addrtosubnet ipsec subnettypeof ipsec masktocount ipsec networkof ipsec maskof initialize an ip_subnet, initialize a singleton ip_subnet, get address type of an ip_subnet, convert subnet mask to bit count, get base address of an ip_subnet, get subnet mask of an ip_subnet #include <libreswan.h> const char *initsubnet const ip_address * addr int maskbits int clash ip_subnet * dst const char *addrtosubnet const ip_address * addr ip_subnet * dst int subnettypeof const ip_subnet * src int masktocount const ip_address * src void networkof const ip_subnet * src ip_address * dst void maskof const ip_subnet * src ip_address * dst DESCRIPTION The <libreswan.h> library uses an internal type ip_subnet to contain a description of an IP subnet (base address plus mask). These functions provide basic tools for creating and examining this type. Initsubnet initializes a variable *dst of type ip_subnet from a base address and a count of mask bits. The clash parameter specifies what to do if the base address includes 1 bits outside the prefix specified by the mask (that is, in the “host number” part of the address):

'0' zero out host-number bits 'x' non-zero host-number bits are an error
Initsubnet returns NULL for success and a pointer to a string-literal error message for failure; see DIAGNOSTICS. Addrtosubnet initializes an ip_subnet variable *dst to a “singleton subnet” containing the single address *addr. It returns NULL for success and a pointer to a string-literal error message for failure. Subnettypeof returns the address type of a subnet, normally AF_INET or AF_INET6. (The <libreswan.h> header file arranges to include the necessary headers for these names to be known.) Masktocount converts a subnet mask, expressed as an address, to a bit count suitable for use with initsubnet. It returns for error; see DIAGNOSTICS. Networkof fills in *dst with the base address of subnet src. Maskof fills in *dst with the subnet mask of subnet src, expressed as an address. SEE ALSO inet3, ipsec_ttosubnet3, ipsec_rangetosubnet3 DIAGNOSTICS Fatal errors in initsubnet are: unknown address family; unknown clash value; impossible mask bit count; non-zero host-number bits and clash is 'x'. Fatal errors in addrtosubnet are: unknown address family. Fatal errors in masktocount are: unknown address family; mask bits not contiguous. HISTORY Written for the FreeS/WAN project by Henry Spencer. libreswan-3.32/lib/libswan/initsubnet.c000066400000000000000000000065551365625662500202170ustar00rootroot00000000000000/* * initialize subnet structure * Copyright (C) 2000, 2002 Henry Spencer. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. */ #include "ip_subnet.h" #include "ip_info.h" /* ipv6_info */ #include "lswlog.h" /* for dbg() */ /* * initsubnet - initialize ip_subnet from address and count * * The only hard part is checking for host-part bits turned on. */ err_t /* NULL for success, else string literal */ initsubnet(addr, count, clash, dst) const ip_address * addr; int count; int clash; /* '0' zero host-part bits, 'x' die on them */ ip_subnet *dst; { unsigned char *p; int n; int c; unsigned m; bool die = false; bool warn = 0; dst->addr = *addr; chunk_t addr_chunk = address_as_chunk(&dst->addr); n = addr_chunk.len; p = addr_chunk.ptr; /* cast void* */ if (n == 0) return "unknown address family"; switch (clash) { case '0': die = 0; break; case 'x': die = 1; break; case '6': if (address_type(addr) == &ipv6_info) die = 1; warn = 1; break; default: return "unknown clash-control value in initsubnet"; } c = count / 8; if (c > n) return "impossible mask count"; p += c; n -= c; m = 0xff; c = count % 8; if (n > 0 && c != 0) /* partial byte */ m >>= c; bool warning = false; for (; n > 0; n--) { if ((*p & m) != 0) { if (die) return "improper subnet, host-part bits on"; if (warn && !warning) warning = true; *p &= ~m; } m = 0xff; p++; } dst->maskbits = count; if (warning) { LSWLOG(buf) { jam(buf, "WARNING:improper subnet mask, host-part bits on input "); jam_address(buf, addr); jam(buf, "/%d ", count); jam(buf, " extracted subnet "); jam_subnet(buf, dst); } } return NULL; } /* * addrtosubnet - initialize ip_subnet from an address:port * * XXX: yes, address:port; not address * * The [old] code copied END directly into .addr and because that was * a sockaddr underneath it would include the port. This means that * code creating the client's subnet from the end's .host_addr is * (intentional or otherwise) creating a subnet for address:port. It * might help explain why code keeps stuffing the client's port into * .host_addr. * * NULL for success, else string literal */ err_t endtosubnet(const ip_endpoint *endpoint, ip_subnet *dst, where_t where) { const struct ip_info *afi = endpoint_type(endpoint); if (afi == NULL) { /* actually AF_UNSPEC */ *dst = subnet_invalid; return "unknown address family"; } ip_subnet s; if (endpoint_hport(endpoint) == 0) { endpoint_buf eb_; dbg("subnet from address %s "PRI_WHERE, str_endpoint(endpoint, &eb_), pri_where(where)); ip_address a = endpoint_address(endpoint); s = subnet_from_address(&a); } else { endpoint_buf eb_; dbg("subnet from endpoint %s "PRI_WHERE, str_endpoint(endpoint, &eb_), pri_where(where)); s = subnet_from_endpoint(endpoint); } *dst = s; return NULL; } libreswan-3.32/lib/libswan/ip_address.c000066400000000000000000000201671365625662500201430ustar00rootroot00000000000000/* * low-level ip_address ugliness * * Copyright (C) 2000 Henry Spencer. * Copyright (C) 2018 Andrew Cagney. * Copyright (C) 2019 D. Hugh Redelmeier * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. */ #include "jambuf.h" #include "ip_address.h" #include "lswlog.h" /* for libreswan_log() */ #include "ip_info.h" ip_address address_from_shunk(const struct ip_info *afi, const shunk_t bytes) { passert(afi != NULL); ip_address address = { .version = afi->ip_version, }; passert(afi->ip_size == bytes.len); memcpy(address.bytes, bytes.ptr, bytes.len); return address; } ip_address address_from_in_addr(const struct in_addr *in) { return address_from_shunk(&ipv4_info, THING_AS_SHUNK(*in)); } uint32_t ntohl_address(const ip_address *a) { uint32_t u; shunk_t s = address_as_shunk(a); if (address_type(a) == &ipv4_info) { memcpy(&u, s.ptr, s.len); } else { /* IPv6 take bits 96 - 128 to compute size */ s.ptr += (s.len - sizeof(u)); memcpy(&u, s.ptr, sizeof(u)); } return ntohl(u); } ip_address address_from_in6_addr(const struct in6_addr *in6) { return address_from_shunk(&ipv6_info, THING_AS_SHUNK(*in6)); } const struct ip_info *address_type(const ip_address *address) { return ip_version_info(address->version); } /* * simplified interface to addrtot() * * Caller should allocate a buffer to hold the result as long * as the resulting string is needed. Usually just long enough * to output. */ const char *ipstr(const ip_address *src, ipstr_buf *b) { return str_address(src, b); } const char *sensitive_ipstr(const ip_address *src, ipstr_buf *b) { return str_address_sensitive(src, b); } shunk_t address_as_shunk(const ip_address *address) { if (address == NULL) { return null_shunk; } const struct ip_info *afi = address_type(address); if (afi == NULL) { return null_shunk; } return shunk2(address->bytes, afi->ip_size); } chunk_t address_as_chunk(ip_address *address) { if (address == NULL) { return empty_chunk; } const struct ip_info *afi = address_type(address); if (afi == NULL) { return empty_chunk; } return chunk(address->bytes, afi->ip_size); } /* * Implement https://tools.ietf.org/html/rfc5952 */ static void jam_raw_ipv4_address(jambuf_t *buf, shunk_t a, char sepc) { const char seps[2] = { sepc == 0 ? '.' : sepc, 0, }; const char *sep = ""; for (size_t i = 0; i < a.len; i++) { const uint8_t *bytes = a.ptr; jam(buf, "%s%"PRIu8, sep, bytes[i]); sep = seps; } } static void jam_raw_ipv6_address(jambuf_t *buf, shunk_t a, char sepc, shunk_t skip) { const char seps[2] = { sepc == 0 ? ':' : sepc, 0, }; const void *ptr = a.ptr; const char *sep = ""; const void *last = a.ptr + a.len - 2; while (ptr <= last) { if (ptr == skip.ptr) { /* skip zero run */ jam(buf, "%s%s", seps, seps); sep = ""; ptr += skip.len; } else { /* * suppress leading zeros in two-byte * big-endian hex value, need to cast away * ptr's sign */ const uint8_t *p = (const uint8_t*)ptr; unsigned ia = (p[0] << 8) + p[1]; jam(buf, "%s%x", sep, ia); sep = seps; ptr += 2; } } } void jam_address_raw(jambuf_t *buf, const ip_address *address, char sepc) { if (address == NULL) { jam(buf, ""); return; } shunk_t a = address_as_shunk(address); int type = addrtypeof(address); switch (type) { case AF_INET: /* N.N.N.N */ jam_raw_ipv4_address(buf, a, sepc); break; case AF_INET6: /* N:N:...:N */ jam_raw_ipv6_address(buf, a, sepc, null_shunk); break; case AF_UNSPEC: jam(buf, ""); break; default: jam(buf, ""); break; } } /* * Find longest run of zero pairs that should be suppressed (need at * least two). */ static shunk_t zeros_to_skip(shunk_t a) { shunk_t zero = null_shunk; const char *ptr = a.ptr; const char *last = a.ptr + a.len - 2; while (ptr <= last) { unsigned l = 0; for (l = 0; ptr + l <= last; l += 2) { /* ptr is probably signed */ if (ptr[l+0] != 0 || ptr[l+1] != 0) { break; } } if (l > 2 && l > zero.len) { zero = shunk2(ptr, l); ptr += l; } else { ptr += 2; } } return zero; } static void format_address_cooked(jambuf_t *buf, bool sensitive, const ip_address *address) { /* * A NULL address can't be sensitive. */ if (address == NULL) { jam(buf, ""); return; } if (sensitive) { jam(buf, ""); return; } shunk_t a = address_as_shunk(address); int type = addrtypeof(address); switch (type) { case AF_INET: /* N.N.N.N */ jam_raw_ipv4_address(buf, a, 0); break; case AF_INET6: /* N:N:...:N */ jam_raw_ipv6_address(buf, a, 0, zeros_to_skip(a)); break; case AF_UNSPEC: jam(buf, ""); break; default: jam(buf, ""); break; } } void jam_address(jambuf_t *buf, const ip_address *address) { format_address_cooked(buf, false, address); } void jam_address_sensitive(jambuf_t *buf, const ip_address *address) { format_address_cooked(buf, !log_ip, address); } void jam_address_reversed(jambuf_t *buf, const ip_address *address) { shunk_t bytes = address_as_shunk(address); int type = addrtypeof(address); switch (type) { case AF_INET: { for (int i = bytes.len - 1; i >= 0; i--) { const uint8_t *byte = bytes.ptr; jam(buf, "%d.", byte[i]); } jam(buf, "IN-ADDR.ARPA."); break; } case AF_INET6: { for (int i = bytes.len - 1; i >= 0; i--) { const uint8_t *byte = bytes.ptr; jam(buf, "%x.%x.", byte[i] & 0xf, byte[i] >> 4); } jam(buf, "IP6.ARPA."); break; } case AF_UNSPEC: jam(buf, ""); break; default: jam(buf, ""); break; } } const char *str_address_raw(const ip_address *src, char sep, address_buf *dst) { jambuf_t buf = ARRAY_AS_JAMBUF(dst->buf); jam_address_raw(&buf, src, sep); return dst->buf; } const char *str_address(const ip_address *src, address_buf *dst) { jambuf_t buf = ARRAY_AS_JAMBUF(dst->buf); jam_address(&buf, src); return dst->buf; } const char *str_address_sensitive(const ip_address *src, address_buf *dst) { jambuf_t buf = ARRAY_AS_JAMBUF(dst->buf); jam_address_sensitive(&buf, src); return dst->buf; } const char *str_address_reversed(const ip_address *src, address_reversed_buf *dst) { jambuf_t buf = ARRAY_AS_JAMBUF(dst->buf); jam_address_reversed(&buf, src); return dst->buf; } const ip_address address_invalid = { .version = 0, }; ip_address address_any(const struct ip_info *info) { if (info == NULL) { /* * XXX: Loudly reject AF_UNSPEC, but don't crash. * Callers know the protocol of the "any" (IPv[46] * term) or "unspecified" (alternative IPv6 term) * address required. * * If there's a need for a function that also allows * AF_UNSPEC, then call that function * address_unspecified(). */ PEXPECT_LOG("AF_UNSPEC unexpected"); return address_invalid; } else { return info->any_address; } } bool address_is_any(const ip_address *address) { const struct ip_info *type = address_type(address); if (type == NULL) { return false; } else { shunk_t addr = address_as_shunk(address); shunk_t any = address_as_shunk(&type->any_address); return hunk_eq(addr, any); } } bool address_is_specified(const ip_address *address) { const struct ip_info *type = address_type(address); if (type == NULL) { return false; } else { shunk_t addr = address_as_shunk(address); shunk_t any = address_as_shunk(&type->any_address); return !hunk_eq(addr, any); } } bool address_is_loopback(const ip_address *address) { const struct ip_info *type = address_type(address); if (type == NULL) { return false; } else { shunk_t addr = address_as_shunk(address); shunk_t loopback = address_as_shunk(&type->loopback_address); return hunk_eq(addr, loopback); } } libreswan-3.32/lib/libswan/ip_endpoint.c000066400000000000000000000162571365625662500203430ustar00rootroot00000000000000/* ip endpoint (address + port), for libreswan * * Copyright (C) 2018-2019 Andrew Cagney * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. * */ #include "jambuf.h" #include "ip_endpoint.h" #include "constants.h" /* for memeq() */ #include "ip_info.h" #include "lswlog.h" /* for bad_case() */ ip_endpoint endpoint(const ip_address *address, int hport) { #if defined(ENDPOINT_TYPE) ip_endpoint endpoint = { .address = *address, .hport = hport, }; return endpoint; #else return set_endpoint_hport(address, hport); #endif } err_t sockaddr_to_endpoint(const ip_sockaddr *sa, socklen_t sa_len, ip_endpoint *e) { /* paranoia from demux.c */ if (sa_len < (socklen_t) (offsetof(ip_sockaddr, sa.sa_family) + sizeof(sa->sa.sa_family))) { zero(e); /* something better? this is AF_UNSPEC */ return "truncated"; } /* * The text used in the below errors originated in demux.c. * * XXX: While af_info seems useful, trying to make it work * here resulted in convoluted over-engineering. Instead * ensure these code paths work using testing. */ ip_address address; int port; switch (sa->sa.sa_family) { case AF_INET: { /* XXX: to strict? */ if (sa_len != sizeof(sa->sin)) { return "wrong length"; } address = address_from_in_addr(&sa->sin.sin_addr); port = ntohs(sa->sin.sin_port); break; } case AF_INET6: { /* XXX: to strict? */ if (sa_len != sizeof(sa->sin6)) { return "wrong length"; } address = address_from_in6_addr(&sa->sin6.sin6_addr); port = ntohs(sa->sin6.sin6_port); break; } case AF_UNSPEC: return "unspecified"; default: return "unexpected Address Family"; } *e = endpoint(&address, port); return NULL; } ip_address endpoint_address(const ip_endpoint *endpoint) { #if defined(ENDPOINT_TYPE) const struct ip_info *afi = endpoint_type(endpoint); if (afi == NULL) { /* not asserting, who knows what nonsense a user can generate */ libreswan_log("endpoint has unspecified type"); return address_invalid; } return endpoint->address; #else if (address_type(endpoint) != NULL) { return set_endpoint_hport(endpoint, 0); /* scrub the port */ } else { return *endpoint; /* empty_address? */ } #endif } int endpoint_hport(const ip_endpoint *endpoint) { const struct ip_info *afi = endpoint_type(endpoint); if (afi == NULL) { /* not asserting, who knows what nonsense a user can generate */ libreswan_log("%s has unspecified type", __func__); return -1; } return endpoint->hport; } int endpoint_nport(const ip_endpoint *endpoint) { const struct ip_info *afi = endpoint_type(endpoint); if (afi == NULL) { /* not asserting, who knows what nonsense a user can generate */ libreswan_log("%s has unspecified type", __func__); return -1; } return htons(endpoint->hport); } ip_endpoint set_endpoint_hport(const ip_endpoint *endpoint, int hport) { const struct ip_info *afi = endpoint_type(endpoint); if (afi == NULL) { /* not asserting, who knows what nonsense a user can generate */ libreswan_log("endpoint has unspecified type"); return endpoint_invalid; } #ifdef ENDPOINT_TYPE ip_endpoint dst = { .address = endpoint->address, .hport = hport, }; return dst; #else ip_endpoint dst = *endpoint; dst.hport = hport; return dst; #endif } const struct ip_info *endpoint_type(const ip_endpoint *endpoint) { /* * Avoid endpoint*() functions as things quickly get * recursive. */ #if defined(ENDPOINT_TYPE) return address_type(&endpoint->address); #else return address_type(endpoint); #endif } bool endpoint_is_specified(const ip_endpoint *e) { #ifdef ENDPOINT_TYPE return address_is_specified(&e->address); #else return address_is_specified(e); #endif } /* * Format an endpoint. * * Either ADDRESS:PORT (IPv4) or [ADDRESS]:PORT, but when PORT is * invalid, just the ADDRESS is formatted. * * From wikipedia: For TCP, port number 0 is reserved and * cannot be used, while for UDP, the source port is optional * and a value of zero means no port. */ static void format_endpoint(jambuf_t *buf, bool sensitive, const ip_endpoint *endpoint) { /* * A NULL endpoint can't be sensitive so always log it. */ if (endpoint == NULL) { jam(buf, ""); return; } /* * An endpoint with no type (i.e., uninitialized) can't be * sensitive so always log it. */ const struct ip_info *afi = endpoint_type(endpoint); if (afi == NULL) { jam(buf, ""); return; } if (sensitive) { jam(buf, ""); return; } ip_address address = endpoint_address(endpoint); int hport = endpoint_hport(endpoint); switch (afi->af) { case AF_INET: /* N.N.N.N[:PORT] */ jam_address(buf, &address); if (hport > 0) { jam(buf, ":%d", hport); } break; case AF_INET6: /* [N:..:N]:PORT or N:..:N */ if (hport > 0) { jam(buf, "["); jam_address(buf, &address); jam(buf, "]"); jam(buf, ":%d", hport); } else { jam_address(buf, &address); } break; default: bad_case(afi->af); } } void jam_endpoint(jambuf_t *buf, const ip_endpoint *endpoint) { format_endpoint(buf, false, endpoint); } const char *str_endpoint(const ip_endpoint *endpoint, endpoint_buf *dst) { jambuf_t buf = ARRAY_AS_JAMBUF(dst->buf); jam_endpoint(&buf, endpoint); return dst->buf; } void jam_sensitive_endpoint(jambuf_t *buf, const ip_endpoint *endpoint) { format_endpoint(buf, !log_ip, endpoint); } const char *str_sensitive_endpoint(const ip_endpoint *endpoint, endpoint_buf *dst) { jambuf_t buf = ARRAY_AS_JAMBUF(dst->buf); jam_sensitive_endpoint(&buf, endpoint); return dst->buf; } bool endpoint_eq(const ip_endpoint l, ip_endpoint r) { return memeq(&l, &r, sizeof(l)); } #ifdef ENDPOINT_TYPE const ip_endpoint endpoint_invalid = { .address = { .af = AF_UNSPEC, }, }; #endif /* * Construct and return a sockaddr structure. */ size_t endpoint_to_sockaddr(const ip_endpoint *endpoint, ip_sockaddr *sa) { zero(sa); const struct ip_info *afi = endpoint_type(endpoint); if (afi == NULL) { return 0; } ip_address address = endpoint_address(endpoint); int hport = endpoint_hport(endpoint); shunk_t src_addr = address_as_shunk(&address); chunk_t dst_addr; switch (afi->af) { case AF_INET: sa->sin.sin_family = afi->af; sa->sin.sin_port = htons(hport); dst_addr = THING_AS_CHUNK(sa->sin.sin_addr); #ifdef NEED_SIN_LEN sa->sin.sin_len = sizeof(struct sockaddr_in); #endif break; case AF_INET6: sa->sin6.sin6_family = afi->af; sa->sin6.sin6_port = htons(hport); dst_addr = THING_AS_CHUNK(sa->sin6.sin6_addr); #ifdef NEED_SIN_LEN sa->sin6.sin6_len = sizeof(struct sockaddr_in6); #endif break; default: bad_case(afi->af); } passert(src_addr.len == afi->ip_size); passert(dst_addr.len == afi->ip_size); memcpy(dst_addr.ptr, src_addr.ptr, src_addr.len); return afi->sockaddr_size; } libreswan-3.32/lib/libswan/ip_info.c000066400000000000000000000067421365625662500174540ustar00rootroot00000000000000/* AF Information, for libreswan * * Copyright (C) 2012-2017 Paul Wouters * Copyright (C) 2012 Avesh Agarwal * Copyright (C) 1998-2002,2015 D. Hugh Redelmeier. * Copyright (C) 2016-2017 Andrew Cagney * Copyright (C) 2017 Vukasin Karadzic * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include "ietf_constants.h" #include "ip_info.h" #include "libreswan/passert.h" #include "lswlog.h" /* for bad_case() */ /* * Construct well known addresses. */ #define ANY_IPv4_ADDRESS { .version = 4, .bytes = { 0, }, } #define ANY_IPv6_ADDRESS { .version = 6, .bytes = { 0, }, } #ifdef ENDPOINT_TYPE #define ANY_IPv4_ENDPOINT { .address = ANY_IPv4_ADDRESS, .hport = 0, } #define ANY_IPv6_ENDPOINT { .address = ANY_IPv6_ADDRESS, .hport = 0, } #else #define ANY_IPv4_ENDPOINT ANY_IPv4_ADDRESS #define ANY_IPv6_ENDPOINT ANY_IPv6_ADDRESS #endif const struct ip_info ipv4_info = { /* ip_address */ .ip_version = 4, .ip_size = sizeof(struct in_addr), .ip_name = "IPv4", .any_address = ANY_IPv4_ADDRESS, /* 0.0.0.0 */ .loopback_address = { .version = 4, .bytes = { 127, 0, 0, 1, }, }, /* 127.0.0.1 */ /* ip_endpoint */ .any_endpoint = ANY_IPv4_ENDPOINT, /* 0.0.0.0:0 */ /* ip_subnet */ .mask_cnt = 32, .no_addresses = { .addr = ANY_IPv4_ENDPOINT, .maskbits = 32, }, /* 0.0.0.0/32 */ .all_addresses = { .addr = ANY_IPv4_ENDPOINT, .maskbits = 0, }, /* 0.0.0.0/32 */ /* ike */ .ikev1_max_fragment_size = ISAKMP_V1_FRAG_MAXLEN_IPv4, .ikev2_max_fragment_size = ISAKMP_V2_FRAG_MAXLEN_IPv4, /* sockaddr */ .af = AF_INET, .af_name = "AF_INET", .sockaddr_size = sizeof(struct sockaddr_in), /* id */ .id_addr = ID_IPV4_ADDR, .id_subnet = ID_IPV4_ADDR_SUBNET, .id_range = ID_IPV4_ADDR_RANGE, }; const struct ip_info ipv6_info = { /* ip_address */ .ip_version = 6, .ip_size = sizeof(struct in6_addr), .ip_name = "IPv6", .any_address = ANY_IPv6_ADDRESS, /* :: */ .loopback_address = { .version = 6, .bytes = { [15] = 1, }, }, /* ::1 */ /* ip_endpoint */ .any_endpoint = ANY_IPv6_ENDPOINT, /* [::]:0 */ /* ip_subnet */ .mask_cnt = 128, .no_addresses = { .addr = ANY_IPv6_ENDPOINT, .maskbits = 128, }, /* ::/128 */ .all_addresses = { .addr = ANY_IPv6_ENDPOINT, .maskbits = 0, }, /* ::/0 */ /* ike */ .ikev1_max_fragment_size = ISAKMP_V1_FRAG_MAXLEN_IPv6, .ikev2_max_fragment_size = ISAKMP_V2_FRAG_MAXLEN_IPv6, /* sockaddr */ .af = AF_INET6, .af_name = "AF_INET6", .sockaddr_size = sizeof(struct sockaddr_in6), /* id */ .id_addr = ID_IPV6_ADDR, .id_subnet = ID_IPV6_ADDR_SUBNET, .id_range = ID_IPV6_ADDR_RANGE, }; const struct ip_info *aftoinfo(int af) { switch (af) { case AF_INET: return &ipv4_info; case AF_INET6: return &ipv6_info; case AF_UNSPEC: return NULL; default: bad_case(af); } } const struct ip_info *ip_version_info(unsigned version) { static const struct ip_info *ip_types[] = { [0] = NULL, [4] = &ipv4_info, [6] = &ipv6_info, }; passert(version < elemsof(ip_types)); return ip_types[version]; } libreswan-3.32/lib/libswan/ip_protocol.c000066400000000000000000000047671365625662500203670ustar00rootroot00000000000000/* ip_protocol, for libreswan * * Copyright (C) 2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include "ip_protocol.h" #include "ietf_constants.h" #include "lswcdefs.h" /* for elemsof() */ #include "constants.h" /* for strncaseeq() */ #include "libreswan/pfkeyv2.h" #if 0 const struct ip_protocol ip_protocol_unspec = { .prefix = "unk", .description = "unknown", .name = "UNKNOWN", }; #endif const struct ip_protocol ip_protocol_icmp = { .prefix = "icmp", .description = "Internet Control Message", .protoid = 1, }; const struct ip_protocol ip_protocol_ipip = { .description = "IPv4 encapsulation", .prefix = "tun", .protoid = 4, .name = "IPIP", }; const struct ip_protocol ip_protocol_esp = { .description = "Encapsulated Security Payload", .prefix = "esp", .ikev1 = PROTO_IPSEC_ESP, .protoid = 50, .name = "ESP", }; const struct ip_protocol ip_protocol_ah = { .description = "Authentication Header", .prefix = "ah", .ikev1 = PROTO_IPSEC_AH, .protoid = 51, .name = "AH", }; const struct ip_protocol ip_protocol_comp = { .description = "IP Payload Compression Protocol", .prefix = "comp", .ikev1 = PROTO_IPCOMP, .protoid = 108, .name = "COMP", }; const struct ip_protocol ip_protocol_int = { .description = "any host internal protocol", .prefix = "int", .protoid = 61, .name = "INT", }; static const struct ip_protocol *ip_protocols[] = { &ip_protocol_icmp, &ip_protocol_ipip, &ip_protocol_esp, &ip_protocol_ah, &ip_protocol_comp, &ip_protocol_int, }; const struct ip_protocol *protocol_by_prefix(const char *prefix) { for (unsigned u = 0; u < elemsof(ip_protocols); u++) { const struct ip_protocol *p = ip_protocols[u]; if (strncaseeq(prefix, p->prefix, strlen(p->prefix))) { return p; } } return NULL; } const struct ip_protocol *protocol_by_protoid(unsigned protoid) { for (unsigned u = 0; u < elemsof(ip_protocols); u++) { const struct ip_protocol *p = ip_protocols[u]; if (p->protoid == protoid) { return p; } } return NULL; } libreswan-3.32/lib/libswan/ip_range.c000066400000000000000000000151151365625662500176070ustar00rootroot00000000000000/* ip_range type, for libreswan * * Copyright (C) 2007 Michael Richardson * Copyright (C) 2000 Henry Spencer. * Copyright (C) 2013 Antony Antony * Copyright (C) 2019 Andrew Cagney * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. */ /* * convert from text form of IP address range specification to binary; * and more minor utilities for mask length calculations for IKEv2 */ #include #include /* for ntohl() */ #include "jambuf.h" #include "ip_range.h" #include "ip_info.h" #include "libreswan/passert.h" #include "lswlog.h" /* for pexpect() */ ip_range range(const ip_address *start, const ip_address *end) { /* does the caller know best? */ const struct ip_info *st = address_type(start); const struct ip_info *et = address_type(end); passert(st == et); bool ss = address_is_specified(start); bool es = address_is_specified(end); passert(ss == es); ip_range r = { .start = *start, .end = *end, }; return r; } /* * Calculate the number of significant bits in the size of the range. * floor(lg(|high-low| + 1)) * * ??? this really should use ip_range rather than a pair of ip_address values */ int iprange_bits(ip_address low, ip_address high) { const struct ip_info *ht = address_type(&high); const struct ip_info *lt = address_type(&low); if (ht == NULL || lt == NULL) { /* either invalid */ return -1; } if (ht != lt) { return -1; } shunk_t hs = address_as_shunk(&high); const uint8_t *hp = hs.ptr; /* cast const void * */ passert(hs.len > 0); size_t n = hs.len; shunk_t ls = address_as_shunk(&low); const uint8_t *lp = ls.ptr; /* cast const void * */ passert(hs.len == ls.len); ip_address diff = low; /* initialize all the contents to sensible values */ unsigned char *dp; chunk_t diff_chunk = address_as_chunk(&diff); dp = diff_chunk.ptr; /* cast void* */ unsigned lastnz = n; /* subtract: d = h - l */ int carry = 0; unsigned j; for (j = n; j > 0; ) { j--; int val = hp[j] - lp[j] - carry; if (val < 0) { val += 0x100u; carry = 1; } else { carry = 0; } dp[j] = val; if (val != 0) lastnz = j; } /* if the answer was negative, complement it */ if (carry != 0) { lastnz = n; /* redundant, but not obviously so */ for (j = n; j > 0; ) { j--; int val = 0xFFu - dp[j] + carry; if (val >= 0x100) { val -= 0x100; carry = 1; /* redundant, but not obviously so */ } else { carry = 0; } dp[j] = val; if (val != 0) lastnz = j; } } /* find leftmost bit in dp[lastnz] */ unsigned bo = 0; if (lastnz != n) { bo = 0; for (unsigned m = 0x80u; (m & dp[lastnz]) == 0; m >>=1) bo++; } return (n - lastnz) * 8 - bo; } static err_t extract_ends(const char *src, const struct ip_info *afi, ip_range *dst) { const char *dash; const char *high; size_t hlen; const char *oops; size_t srclen = strlen(src); dash = memchr(src, '-', srclen); if (dash == NULL) return "not ipv4 address range with '-' or ipv6 subnet"; high = dash + 1; hlen = srclen - (high - src); /* extract start ip address */ oops = ttoaddr_num(src, dash - src, afi->af, &dst->start); if (oops != NULL) return oops; /* extract end ip address */ oops = ttoaddr_num(high, hlen, afi->af, &dst->end); if (oops != NULL) return oops; return NULL; } /* * ttorange - convert text v4 "addr1-addr2" to address_start address_end * v6 allows "subnet/mask" to address_start address_end */ err_t ttorange(const char *src, const struct ip_info *afi, ip_range *dst) { err_t er = NULL; zero(dst); ip_range tmp = *dst; /* clear it */ ip_subnet v6_subnet; er = ttosubnet(src, 0, AF_INET6, '6', &v6_subnet); if (er == NULL) { if (v6_subnet.addr.hport != 0) return "port must be zero for IPv6 addresspool"; tmp = range_from_subnet(&v6_subnet); tmp.is_subnet = true; afi = &ipv6_info; } else { if (afi == NULL) { afi = &ipv4_info; if (extract_ends(src, afi, &tmp) != NULL) { afi = &ipv6_info; er = extract_ends(src, afi, &tmp); if (er != NULL) return er; /* v4 error is ignored */ } } else { er = extract_ends(src, afi, &tmp); if (er != NULL) return er; } } if (addrcmp(&tmp.start, &tmp.end) > 0) { return "start of range must not be greater than end"; } if (address_is_any(&tmp.start) || address_is_any(&tmp.end)) { return "'0.0.0.0 or ::0' not allowed in range"; } /* We have validated the range. Now put bounds in dst. */ *dst = tmp; return NULL; } void jam_range(jambuf_t *buf, const ip_range *range) { jam_address(buf, &range->start); if (range_type(range) == &ipv6_info && range->is_subnet) { ip_subnet tmp_subnet; rangetosubnet(&range->start, &range->end, &tmp_subnet); jam(buf, "/%u", tmp_subnet.maskbits); } else { jam(buf, "-"); jam_address(buf, &range->end); } } const char *str_range(const ip_range *range, range_buf *out) { jambuf_t buf = ARRAY_AS_JAMBUF(out->buf); jam_range(&buf, range); return out->buf; } ip_range range_from_subnet(const ip_subnet *subnet) { ip_range r = { .start = subnet_blit(subnet, &keep_bits, &clear_bits), .end = subnet_blit(subnet, &keep_bits, &set_bits), }; return r; } const struct ip_info *range_type(const ip_range *range) { const struct ip_info *start = address_type(&range->start); const struct ip_info *end = address_type(&range->end); if (!pexpect(start == end)) { return NULL; } return start; } bool range_is_specified(const ip_range *r) { bool start = address_is_specified(&r->start); bool end = address_is_specified(&r->end); if (!pexpect(start == end)) { return false; } return start; } bool range_size(ip_range *r, uint32_t *size) { bool truncated = false; uint32_t n = *size = 0; n = (ntohl_address(&r->end) - ntohl_address(&r->start)); if (address_type(&r->start) == &ipv6_info) { int prefix_len = ipv6_info.mask_cnt - iprange_bits(r->start, r->end); if (prefix_len < IPV6_MIN_POOL_PREFIX_LEN) { truncated = true; uint32_t s = ntohl_address(&r->start); n = UINT32_MAX - s; } if (n < UINT32_MAX) n++; else truncated = true; } else { /* IPv4 */ n++; } *size = n; return truncated; } libreswan-3.32/lib/libswan/ip_said.c000066400000000000000000000077771365625662500174520ustar00rootroot00000000000000/* SA ID, for libreswan * * Copyright (C) 2019 Andrew Cagney * Copyright (C) 2000, 2001 Henry Spencer. * Copyright (C) 2012 David McCullough * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include "ip_said.h" #include #include #include "ip_said.h" #include "ip_info.h" #include "jambuf.h" #include "libreswan/passert.h" ip_said said3(const ip_address *address, ipsec_spi_t spi, const struct ip_protocol *proto) { ip_said said = { .dst = *address, .spi = spi, .proto = proto, }; return said; } /* - satot - convert SA to text "ah507@1.2.3.4" */ static size_t /* space needed for full conversion */ satot(sa, format, dst, dstlen) const ip_said * sa; int format; /* character */ char *dst; /* need not be valid if dstlen is 0 */ size_t dstlen; { size_t len = 0; /* 0 means "not recognized yet" */ int base; int showversion; /* use delimiter to show IP version? */ char *p; char buf[10 + 1 + ULTOT_BUF + ADDRTOT_BUF]; switch (format) { case 0: base = 16; showversion = 1; break; case 'f': base = 17; showversion = 1; break; case 'x': base = 'x'; showversion = 0; break; case 'd': base = 10; showversion = 0; break; default: if (dstlen > 0) { strncpy(dst, "(error)", dstlen-1); dst[dstlen-1] = '\0'; } return 0; break; } memset(buf, 0, sizeof(buf)); /* const ip_protocol *proto = sa->proto; */ const struct ip_protocol *proto = sa->proto; const char *pre = (proto == NULL ? "unk" : proto->prefix); if (strcmp(pre, PASSTHROUGHTYPE) == 0 && sa->spi == PASSTHROUGHSPI && isanyaddr(&sa->dst)) { strcpy(buf, (said_type(sa) == &ipv4_info) ? PASSTHROUGH4NAME : PASSTHROUGH6NAME); len = strlen(buf); } if (sa->proto == SA_INT) { char intunk[10]; switch (ntohl(sa->spi)) { case SPI_PASS: p = "%pass"; break; case SPI_DROP: p = "%drop"; break; case SPI_REJECT: p = "%reject"; break; case SPI_HOLD: p = "%hold"; break; case SPI_TRAP: p = "%trap"; break; case SPI_TRAPSUBNET: p = "%trapsubnet"; break; default: snprintf(intunk, sizeof(intunk), "%%unk-%d", ntohl(sa->spi)); p = intunk; break; } if (p != NULL) { strcpy(buf, p); len = strlen(buf); } } if (len == 0) { /* general case needed */ strcpy(buf, pre); len = strlen(buf); if (showversion) { *(buf + len) = (said_type(sa) == &ipv4_info) ? '.' : ':'; len++; *(buf + len) = '\0'; } len += ultot(ntohl(sa->spi), base, buf + len, sizeof(buf) - len); *(buf + len - 1) = '@'; /* jambuf's are always '\0' terminated */ jambuf_t b = array_as_jambuf(buf + len, sizeof(buf) - len); jam_address(&b, &sa->dst); /* "pos" is always '\0' */ const char *end = jambuf_cursor(&b); passert(*end == '\0'); /* *tot() functions lengh includes the NULL */ len = end-buf+1; } if (dst != NULL) { if (len > dstlen) *(buf + dstlen - 1) = '\0'; strcpy(dst, buf); } return len; } void jam_said(jambuf_t *buf, const ip_said *said, int format) { char t[SATOT_BUF]; satot(said, format, t, sizeof(t)); jam_string(buf, t); } const char *str_said(const ip_said *said, int format, said_buf *buf) { jambuf_t b = ARRAY_AS_JAMBUF(buf->buf); jam_said(&b, said, format); return buf->buf; } const struct ip_info *said_type(const ip_said *said) { return address_type(&said->dst); } ip_address said_address(const ip_said *said) { return said->dst; } libreswan-3.32/lib/libswan/ip_subnet.c000066400000000000000000000144711365625662500200170ustar00rootroot00000000000000/* ip subnet, for libreswan * * Copyright (C) 2012-2017 Paul Wouters * Copyright (C) 2012 Avesh Agarwal * Copyright (C) 1998-2002,2015 D. Hugh Redelmeier. * Copyright (C) 2016-2019 Andrew Cagney * Copyright (C) 2017 Vukasin Karadzic * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include "jambuf.h" #include "ip_subnet.h" #include "libreswan/passert.h" #include "lswlog.h" /* for pexpect() */ #include "ip_info.h" const ip_subnet subnet_invalid; /* all zeros */ static ip_subnet subnet3(const ip_address *address, int maskbits, int port) { ip_endpoint e = endpoint(address, port); ip_subnet s = { .addr = e, .maskbits = maskbits, }; return s; } #ifdef SUBNET_TYPE static ip_subnet subnet4(const ip_address *lo_address, const ip_address *hi_address, int lo_hport, int hi_hport) { ip_subnet s = { .lo_address = *lo_address, .hi_address = *hi_address, .lo_port = lo_port, .hi_port = hi_port, }; } #endif ip_subnet subnet_from_address(const ip_address *address) { const struct ip_info *afi = address_type(address); if (!pexpect(afi != NULL)) { return subnet_invalid; } return subnet3(address, afi->mask_cnt, 0); } ip_subnet subnet_from_endpoint(const ip_endpoint *endpoint) { const struct ip_info *afi = endpoint_type(endpoint); if (!pexpect(afi != NULL)) { return subnet_invalid; } ip_address address = endpoint_address(endpoint); int hport = endpoint_hport(endpoint); pexpect(hport != 0); return subnet3(&address, afi->mask_cnt, hport); } ip_address subnet_prefix(const ip_subnet *src) { return subnet_blit(src, /*routing-prefix*/&keep_bits, /*host-id*/&clear_bits); } const struct ip_info *subnet_type(const ip_subnet *src) { return endpoint_type(&src->addr); } int subnet_hport(const ip_subnet *s) { #ifdef SUBNET_TYPE const struct ip_info *afi = subnet_type(s); if (afi == NULL) { /* not asserting, who knows what nonsense a user can generate */ libreswan_log("%s has unspecified type", __func__); return -1; } return s->hport; #else return endpoint_hport(&s->addr); #endif } int subnet_nport(const ip_subnet *s) { #ifdef SUBNET_TYPE const struct ip_info *afi = subnet_type(s); if (afi == NULL) { /* not asserting, who knows what nonsense a user can generate */ libreswan_log("%s has unspecified type", __func__); return -1; } return htons(s->hport); #else return endpoint_nport(&s->addr); #endif } ip_subnet set_subnet_hport(const ip_subnet *subnet, int hport) { ip_subnet s = *subnet; #ifdef SUBNET_TYPE s.port = hport; #else s.addr = set_endpoint_hport(&subnet->addr, hport); #endif return s; } bool subnet_is_specified(const ip_subnet *s) { return endpoint_is_specified(&s->addr); } bool subnet_contains_all_addresses(const ip_subnet *s) { const struct ip_info *afi = subnet_type(s); if (!pexpect(afi != NULL) || s->maskbits != 0) { return false; } ip_address network = subnet_prefix(s); return (address_is_any(&network) && subnet_hport(s) == 0); } bool subnet_contains_no_addresses(const ip_subnet *s) { const struct ip_info *afi = subnet_type(s); if (!pexpect(afi != NULL) || s->maskbits != afi->mask_cnt) { return false; } ip_address network = subnet_prefix(s); return (address_is_any(&network) && subnet_hport(s) == 0); } /* * mashup() notes: * - mashup operates on network-order IP addresses */ struct ip_blit { uint8_t and; uint8_t or; }; const struct ip_blit clear_bits = { .and = 0x00, .or = 0x00, }; const struct ip_blit set_bits = { .and = 0x00/*don't care*/, .or = 0xff, }; const struct ip_blit keep_bits = { .and = 0xff, .or = 0x00, }; ip_address subnet_blit(const ip_subnet *src, const struct ip_blit *prefix, const struct ip_blit *host) { /* strip port; copy type */ ip_address mask = endpoint_address(&src->addr); chunk_t raw = address_as_chunk(&mask); if (!pexpect((size_t)src->maskbits <= raw.len * 8)) { return address_invalid; /* "can't happen" */ } uint8_t *p = raw.ptr; /* cast void* */ /* the cross over byte */ size_t xbyte = src->maskbits / BITS_PER_BYTE; unsigned xbit = src->maskbits % BITS_PER_BYTE; /* leading bytes: & PREFIX->AND | PREFIX->OR */ unsigned b = 0; for (; b < xbyte; b++) { p[b] &= prefix->and; p[b] |= prefix->or; } /* * cross over: & {PREFIX,HOST}_AND | {PREFIX,HOST}_OR * * tricky logic: * - b == xbyte * - if xbyte == raw.len we must not access p[xbyte] * - if xbyte == raw.len, xbit will be 0 * - if xbit == 0, the loop for trailing bytes will * perform the required operation slightly more efficiently * So we guard this step with xbit != 0 instead of b < raw.len */ if (xbit != 0) { uint8_t hmask = 0xFF >> xbit; p[b] &= (prefix->and & ~hmask) | (host->and & hmask); p[b] |= (prefix->or & ~hmask) | (host->or & hmask); b++; } /* trailing bytes: & HOST->AND | HOST->OR */ for (; b < raw.len; b++) { p[b] &= host->and; p[b] |= host->or; } return mask; } /* * subnet mask - get the mask of a subnet, as an address * * For instance 1.2.3.4/24 -> 255.255.255.0. */ ip_address subnet_mask(const ip_subnet *src) { return subnet_blit(src, /*prefix*/ &set_bits, /*host*/ &clear_bits); } void jam_subnet(jambuf_t *buf, const ip_subnet *subnet) { jam_address(buf, &subnet->addr); /* sensitive? */ jam(buf, "/%u", subnet->maskbits); } const char *str_subnet(const ip_subnet *subnet, subnet_buf *out) { jambuf_t buf = ARRAY_AS_JAMBUF(out->buf); jam_subnet(&buf, subnet); return out->buf; } void jam_subnet_port(jambuf_t *buf, const ip_subnet *subnet) { jam_address(buf, &subnet->addr); /* sensitive? */ jam(buf, "/%u", subnet->maskbits); int port = subnet_hport(subnet); if (port >= 0) { jam(buf, ":%d", port); } } const char *str_subnet_port(const ip_subnet *subnet, subnet_buf *out) { jambuf_t buf = ARRAY_AS_JAMBUF(out->buf); jam_subnet_port(&buf, subnet); return out->buf; } libreswan-3.32/lib/libswan/ipsec_addrbytesof.3000066400000000000000000000000321365625662500214240ustar00rootroot00000000000000.so man3/ipsec_initaddr.3 libreswan-3.32/lib/libswan/ipsec_addrbytesptr.3000066400000000000000000000000321365625662500216250ustar00rootroot00000000000000.so man3/ipsec_initaddr.3 libreswan-3.32/lib/libswan/ipsec_addrcmp.3000066400000000000000000000000321365625662500205300ustar00rootroot00000000000000.so man3/ipsec_sameaddr.3 libreswan-3.32/lib/libswan/ipsec_addrinsubnet.3000066400000000000000000000000321365625662500216000ustar00rootroot00000000000000.so man3/ipsec_sameaddr.3 libreswan-3.32/lib/libswan/ipsec_addrlenof.3000066400000000000000000000000321365625662500210540ustar00rootroot00000000000000.so man3/ipsec_initaddr.3 libreswan-3.32/lib/libswan/ipsec_addrtoa.3000066400000000000000000000000311365625662500205330ustar00rootroot00000000000000.so man3/ipsec_atoaddr.3 libreswan-3.32/lib/libswan/ipsec_addrtosubnet.3000066400000000000000000000000341365625662500216160ustar00rootroot00000000000000.so man3/ipsec_initsubnet.3 libreswan-3.32/lib/libswan/ipsec_addrtot.3000066400000000000000000000000311365625662500205560ustar00rootroot00000000000000.so man3/ipsec_ttoaddr.3 libreswan-3.32/lib/libswan/ipsec_addrtypeof.3000066400000000000000000000000321365625662500212570ustar00rootroot00000000000000.so man3/ipsec_initaddr.3 libreswan-3.32/lib/libswan/ipsec_atoasr.3000066400000000000000000000135431365625662500204220ustar00rootroot00000000000000'\" t .\" Title: IPSEC_ATOASR .\" Author: Paul Wouters .\" Generator: DocBook XSL Stylesheets v1.77.1 .\" Date: 12/16/2012 .\" Manual: Executable programs .\" Source: libreswan .\" Language: English .\" .TH "IPSEC_ATOASR" "3" "12/16/2012" "libreswan" "Executable programs" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" https://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" ipsec_atoasr, ipsec_rangetoa \- convert ASCII to Internet address, subnet, or range, convert Internet address range to ASCII .SH "SYNOPSIS" .sp .ft B .nf #include .fi .ft .HP \w'const\ char\ *atoasr('u .BI "const char *atoasr(const\ char\ *\ " "src" ", size_t\ " "srclen" ", char\ *\ " "type" ", struct\ in_addr\ *\ " "addrs" ");" .HP \w'size_t\ rangetoa('u .BI "size_t rangetoa(struct\ in_addr\ *\ " "addrs" ", int\ " "format" ", char\ *\ " "dst" ", size_t\ " "dstlen" ");" .SH "DESCRIPTION" .PP These functions are obsolete; there is no current equivalent, because so far they have not proved useful\&. .PP \fIAtoasr\fR converts an ASCII address, subnet, or address range into a suitable combination of binary addresses (in network byte order)\&. \fIRangetoa\fR converts an address range back into ASCII, using dotted\-decimal form for the addresses (the other reverse conversions are handled by \fBipsec_addrtoa\fR(3) and \fBipsec_subnettoa\fR(3))\&. .PP A single address can be any form acceptable to \fBipsec_atoaddr\fR(3): dotted decimal, DNS name, or hexadecimal number\&. A subnet specification uses the form \fInetwork\fR\fB/\fR\fImask\fR interpreted by \fBipsec_atosubnet\fR(3)\&. .PP An address range is two \fBipsec_atoaddr\fR(3) addresses separated by a \&.\&.\&. delimiter\&. If there are four dots rather than three, the first is taken as part of the begin address, e\&.g\&. for a complete DNS name which ends with \&. to suppress completion attempts\&. The begin address of a range must be less than or equal to the end address\&. .PP The \fIsrclen\fR parameter of \fBatoasr\fR specifies the length of the ASCII string pointed to by \fIsrc\fR; it is an error for there to be anything else (e\&.g\&., a terminating NUL) within that length\&. As a convenience for cases where an entire NUL\-terminated string is to be converted, a \fIsrclen\fR value of 0 is taken to mean \fBstrlen(src)\fR\&. .PP The \fItype\fR parameter of \fBatoasr\fR must point to a \fBchar\fR variable used to record which form was found\&. The \fIaddrs\fR parameter must point to a two\-element array of \fBstruct in_addr\fR which receives the results\&. The values stored into \fB*type\fR, and the corresponding values in the array, are: .PP *type addrs[0] addrs[1] .PP address \fB\*(Aqa\*(Aq\fR address \- subnet \fB\*(Aqs\*(Aq\fR network mask range \fB\*(Aqr\*(Aq\fR begin end .PP The \fIdstlen\fR parameter of \fBrangetoa\fR specifies the size of the \fIdst\fR parameter; under no circumstances are more than \fIdstlen\fR bytes written to \fIdst\fR\&. A result that will not fit is truncated\&. \fIDstlen\fR can be zero, in which case \fIdst\fR need not be valid and no result is written, but the return value is unaffected; in all other cases, the (possibly truncated) result is NUL\-terminated\&. The \fIlibreswan\&.h\fR header file defines a constant, \fBRANGETOA_BUF\fR, which is the size of a buffer just large enough for worst\-case results\&. .PP The \fIformat\fR parameter of \fBrangetoa\fR specifies what format is to be used for the conversion\&. The value 0 (not the ASCII character \fB\*(Aq0\*(Aq\fR, but a zero value) specifies a reasonable default, and is in fact the only format currently available\&. This parameter is a hedge against future needs\&. .PP \fIAtoasr\fR returns NULL for success and a pointer to a string\-literal error message for failure; see DIAGNOSTICS\&. \fIRangetoa\fR returns 0 for a failure, and otherwise always returns the size of buffer that would be needed to accommodate the full conversion result, including terminating NUL; it is the caller\*(Aqs responsibility to check this against the size of the provided buffer to determine whether truncation has occurred\&. .SH "SEE ALSO" .PP \fBipsec_atoaddr\fR(3), \fBipsec_atosubnet\fR(3) .SH "DIAGNOSTICS" .PP Fatal errors in \fBatoasr\fR are: empty input; error in \fBipsec_atoaddr\fR(3) or \fBipsec_atosubnet\fR(3) during conversion; begin address of range exceeds end address\&. .PP Fatal errors in \fBrangetoa\fR are: unknown format\&. .SH "HISTORY" .PP Written for the FreeS/WAN project by Henry Spencer\&. .SH "BUGS" .PP The restriction of error reports to literal strings (so that callers don\*(Aqt need to worry about freeing them or copying them) does limit the precision of error reporting\&. .PP The error\-reporting convention lends itself to slightly obscure code, because many readers will not think of NULL as signifying success\&. A good way to make it clearer is to write something like: .sp .if n \{\ .RS 4 .\} .nf \fBconst char *error;\fR \fBerror = atoasr( /* \&.\&.\&. */ );\fR \fBif (error != NULL) {\fR \fB /* something went wrong */\fR .fi .if n \{\ .RE .\} .SH "AUTHOR" .PP \fBPaul Wouters\fR .RS 4 placeholder to suppress warning .RE libreswan-3.32/lib/libswan/ipsec_atosubnet.3000066400000000000000000000000311365625662500211210ustar00rootroot00000000000000.so man3/ipsec_atoaddr.3 libreswan-3.32/lib/libswan/ipsec_bitstomask.3000066400000000000000000000000321365625662500212760ustar00rootroot00000000000000.so man3/ipsec_goodmask.3 libreswan-3.32/lib/libswan/ipsec_broadcastof.3000066400000000000000000000000321365625662500214050ustar00rootroot00000000000000.so man3/ipsec_subnetof.3 libreswan-3.32/lib/libswan/ipsec_datatot.3000066400000000000000000000000311365625662500205550ustar00rootroot00000000000000.so man3/ipsec_ttodata.3 libreswan-3.32/lib/libswan/ipsec_hostof.3000066400000000000000000000000321365625662500204200ustar00rootroot00000000000000.so man3/ipsec_subnetof.3 libreswan-3.32/lib/libswan/ipsec_initsaid.3000066400000000000000000000000271365625662500207260ustar00rootroot00000000000000.so man3/ipsec_ttosa.3 libreswan-3.32/lib/libswan/ipsec_isanyaddr.3000066400000000000000000000000311365625662500210730ustar00rootroot00000000000000.so man3/ipsec_anyaddr.3 libreswan-3.32/lib/libswan/ipsec_isloopbackaddr.3000066400000000000000000000000311365625662500220760ustar00rootroot00000000000000.so man3/ipsec_anyaddr.3 libreswan-3.32/lib/libswan/ipsec_isunspecaddr.3000066400000000000000000000000311365625662500216010ustar00rootroot00000000000000.so man3/ipsec_anyaddr.3 libreswan-3.32/lib/libswan/ipsec_loopbackaddr.3000066400000000000000000000000311365625662500215420ustar00rootroot00000000000000.so man3/ipsec_anyaddr.3 libreswan-3.32/lib/libswan/ipsec_maskof.3000066400000000000000000000000341365625662500204000ustar00rootroot00000000000000.so man3/ipsec_initsubnet.3 libreswan-3.32/lib/libswan/ipsec_masktobits.3000066400000000000000000000000321365625662500212760ustar00rootroot00000000000000.so man3/ipsec_goodmask.3 libreswan-3.32/lib/libswan/ipsec_masktocount.3000066400000000000000000000000341365625662500214670ustar00rootroot00000000000000.so man3/ipsec_initsubnet.3 libreswan-3.32/lib/libswan/ipsec_networkof.3000066400000000000000000000000341365625662500211360ustar00rootroot00000000000000.so man3/ipsec_initsubnet.3 libreswan-3.32/lib/libswan/ipsec_prng_bytes.3000066400000000000000000000000331365625662500212730ustar00rootroot00000000000000.so man3/ipsec_prng_init.3 libreswan-3.32/lib/libswan/ipsec_prng_final.3000066400000000000000000000000331365625662500212360ustar00rootroot00000000000000.so man3/ipsec_prng_init.3 libreswan-3.32/lib/libswan/ipsec_prng_init.3000066400000000000000000000120061365625662500211130ustar00rootroot00000000000000'\" t .\" Title: IPSEC_PRNG_INIT .\" Author: Paul Wouters .\" Generator: DocBook XSL Stylesheets v1.77.1 .\" Date: 12/16/2012 .\" Manual: Executable programs .\" Source: libreswan .\" Language: English .\" .TH "IPSEC_PRNG_INIT" "3" "12/16/2012" "libreswan" "Executable programs" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" https://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" ipsec_prng_init, ipsec_prng_bytes, ipsec_prng_final \- initialize IPsec pseudorandom\-number generator, get bytes from IPsec pseudorandom\-number generator, close down IPsec pseudorandom\-number generator .SH "SYNOPSIS" .sp .ft B .nf #include .fi .ft .HP \w'void\ prng_init('u .BI "void prng_init(struct\ prng\ *\ " "prng" ", const\ unsigned\ char\ *\ " "key" ", size_t\ " "keylen" ");" .HP \w'void\ prng_bytes('u .BI "void prng_bytes(struct\ prng\ *\ " "prng" ", char\ *\ " "dst" ", size_t\ " "dstlen" ");" .HP \w'unsigned\ long\ prng_count('u .BI "unsigned long prng_count(struct\ prng\ *\ " "prng" ");" .HP \w'void\ prng_final('u .BI "void prng_final(struct\ prng\ *\ " "prng" ");" .SH "DESCRIPTION" .PP \fIPrng_init\fR initializes a crypto\-quality pseudo\-random\-number generator from a key; \fBprng_bytes\fR obtains pseudo\-random bytes from it; \fBprng_count\fR reports the number of bytes extracted from it to date; \fBprng_final\fR closes it down\&. It is the user\*(Aqs responsibility to initialize a PRNG before using it, and not to use it again after it is closed down\&. .PP \fIPrng_init\fR initializes, or re\-initializes, the specified \fIprng\fR from the \fIkey\fR, whose length is given by \fIkeylen\fR\&. The user must allocate the \fBstruct prng\fR pointed to by \fIprng\fR\&. There is no particular constraint on the length of the key, although a key longer than 256 bytes is unnecessary because only the first 256 would be used\&. Initialization requires on the order of 3000 integer operations, independent of key length\&. .PP \fIPrng_bytes\fR obtains \fIdstlen\fR pseudo\-random bytes from the PRNG and puts them in \fIbuf\fR\&. This is quite fast, on the order of 10 integer operations per byte\&. .PP \fIPrng_count\fR reports the number of bytes obtained from the PRNG since it was (last) initialized\&. .PP \fIPrng_final\fR closes down a PRNG by zeroing its internal memory, obliterating all trace of the state used to generate its previous output\&. This requires on the order of 250 integer operations\&. .PP The \fB\fR header file supplies the definition of the \fIprng\fR structure\&. Examination of its innards is discouraged, as they may change\&. .PP The PRNG algorithm used by these functions is currently identical to that of RC4(TM)\&. This algorithm is cryptographically strong, sufficiently unpredictable that even a hostile observer will have difficulty determining the next byte of output from past history, provided it is initialized from a reasonably large key composed of highly random bytes (see \fBrandom\fR(4))\&. The usual run of software pseudo\-random\-number generators (e\&.g\&. \fBrandom\fR(3)) are \fInot\fR cryptographically strong\&. .PP The well\-known attacks against RC4(TM), e\&.g\&. as found in 802\&.11b\*(Aqs WEP encryption system, apply only if multiple PRNGs are initialized with closely\-related keys (e\&.g\&., using a counter appended to a base key)\&. If such keys are used, the first few hundred pseudo\-random bytes from each PRNG should be discarded, to give the PRNGs a chance to randomize their innards properly\&. No useful attacks are known if the key is well randomized to begin with\&. .SH "SEE ALSO" .PP \fBrandom\fR(3), \fBrandom\fR(4) Bruce Schneier, \fIApplied Cryptography\fR, 2nd ed\&., 1996, ISBN 0\-471\-11709\-9, pp\&. 397\-8\&. .SH "HISTORY" .PP Written for the FreeS/WAN project by Henry Spencer\&. .SH "BUGS" .PP If an attempt is made to obtain more than 4e9 bytes between initializations, the PRNG will continue to work but \fBprng_count\fR\*(Aqs output will stick at 4000000000\&. Fixing this would require a longer integer type and does not seem worth the trouble, since you should probably re\-initialize before then anyway\&.\&.\&. .PP \(lqRC4\(rq is a trademark of RSA Data Security, Inc\&. .SH "AUTHOR" .PP \fBPaul Wouters\fR .RS 4 placeholder to suppress warning .RE libreswan-3.32/lib/libswan/ipsec_rangetoa.3000066400000000000000000000000301365625662500207140ustar00rootroot00000000000000.so man3/ipsec_atoasr.3 libreswan-3.32/lib/libswan/ipsec_sameaddrtype.3000066400000000000000000000000321365625662500216000ustar00rootroot00000000000000.so man3/ipsec_sameaddr.3 libreswan-3.32/lib/libswan/ipsec_samesaid.3000066400000000000000000000000321365625662500207040ustar00rootroot00000000000000.so man3/ipsec_sameaddr.3 libreswan-3.32/lib/libswan/ipsec_samesubnet.3000066400000000000000000000000321365625662500212640ustar00rootroot00000000000000.so man3/ipsec_sameaddr.3 libreswan-3.32/lib/libswan/ipsec_samesubnettype.3000066400000000000000000000000321365625662500221660ustar00rootroot00000000000000.so man3/ipsec_sameaddr.3 libreswan-3.32/lib/libswan/ipsec_satot.3000066400000000000000000000000271365625662500202540ustar00rootroot00000000000000.so man3/ipsec_ttosa.3 libreswan-3.32/lib/libswan/ipsec_setportof.3000066400000000000000000000000301365625662500211410ustar00rootroot00000000000000.so man3/ipsec_portof.3 libreswan-3.32/lib/libswan/ipsec_sockaddrlenof.3000066400000000000000000000000301365625662500217320ustar00rootroot00000000000000.so man3/ipsec_portof.3 libreswan-3.32/lib/libswan/ipsec_sockaddrof.3000066400000000000000000000000301365625662500212330ustar00rootroot00000000000000.so man3/ipsec_portof.3 libreswan-3.32/lib/libswan/ipsec_splitkeytoid.3000066400000000000000000000000351365625662500216450ustar00rootroot00000000000000.so man3/ipsec_keyblobtoid.3 libreswan-3.32/lib/libswan/ipsec_subnetinsubnet.3000066400000000000000000000000321365625662500221660ustar00rootroot00000000000000.so man3/ipsec_sameaddr.3 libreswan-3.32/lib/libswan/ipsec_subnetishost.3000066400000000000000000000000321365625662500216500ustar00rootroot00000000000000.so man3/ipsec_sameaddr.3 libreswan-3.32/lib/libswan/ipsec_subnettoa.3000066400000000000000000000000311365625662500211210ustar00rootroot00000000000000.so man3/ipsec_atoaddr.3 libreswan-3.32/lib/libswan/ipsec_subnettot.3000066400000000000000000000000311365625662500211440ustar00rootroot00000000000000.so man3/ipsec_ttoaddr.3 libreswan-3.32/lib/libswan/ipsec_subnettypeof.3000066400000000000000000000000341365625662500216470ustar00rootroot00000000000000.so man3/ipsec_initsubnet.3 libreswan-3.32/lib/libswan/ipsec_tnatoaddr.3000066400000000000000000000000311365625662500210750ustar00rootroot00000000000000.so man3/ipsec_ttoaddr.3 libreswan-3.32/lib/libswan/ipsec_ttosubnet.3000066400000000000000000000000311365625662500211440ustar00rootroot00000000000000.so man3/ipsec_ttoaddr.3 libreswan-3.32/lib/libswan/ipsec_ultot.3000066400000000000000000000000271365625662500202710ustar00rootroot00000000000000.so man3/ipsec_ttoul.3 libreswan-3.32/lib/libswan/ipsec_unspecaddr.3000066400000000000000000000000311365625662500212450ustar00rootroot00000000000000.so man3/ipsec_anyaddr.3 libreswan-3.32/lib/libswan/ipsec_version_code.3000066400000000000000000000044011365625662500216010ustar00rootroot00000000000000'\" t .\" Title: IPSEC_VERSION_CODE .\" Author: Paul Wouters .\" Generator: DocBook XSL Stylesheets v1.77.1 .\" Date: 12/16/2012 .\" Manual: Library functions .\" Source: libreswan .\" Language: English .\" .TH "IPSEC_VERSION_CODE" "3" "12/16/2012" "libreswan" "Library functions" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" https://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" ipsec_version_code, ipsec_version_string \- get IPsec version code, full version string, copyright notice .SH "SYNOPSIS" .sp .ft B .nf #include .fi .ft .HP \w'const\ char\ *ipsec_version_code('u .BI "const char *ipsec_version_code(" "void" ");" .HP \w'const\ char\ *ipsec_version_string('u .BI "const char *ipsec_version_string(" "void" ");" .SH "DESCRIPTION" .PP These functions provide information on version numbering and copyright of the Linux FreeS/WAN IPsec implementation\&. .PP \fIIpsec_version_code\fR returns a pointer to a string constant containing the current IPsec version code, such as \(lq1\&.92\(rq or \(lqsnap2001Nov19b\(rq\&. .PP \fIIpsec_version_string\fR returns a pointer to a string constant giving a full version identification, consisting of the version code preceded by a prefix identifying the software, e\&.g\&. \(lqLinux FreeS/WAN 1\&.92\(rq\&. .SH "SEE ALSO" .PP \fBipsec\fR(8) .SH "HISTORY" .PP Written for the FreeS/WAN project by Henry Spencer\&. .SH "AUTHOR" .PP \fBPaul Wouters\fR .RS 4 placeholder to suppress warning .RE libreswan-3.32/lib/libswan/ipsec_version_string.3000066400000000000000000000000361365625662500221750ustar00rootroot00000000000000.so man3/ipsec_version_code.3 libreswan-3.32/lib/libswan/jam_bytes.c000066400000000000000000000055761365625662500200120ustar00rootroot00000000000000/* Output raw bytes, for libreswan * * Copyright (C) 2017, 2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include /* for isprint() */ #include "jambuf.h" size_t jam_hex_bytes(jambuf_t *buf, const void *ptr, size_t size) { size_t n = 0; const uint8_t *bytes = ptr; for (unsigned i = 0; i < size; i++) { uint8_t b = bytes[i]; n += jam(buf, "%02x", b); } return n; } size_t jam_HEX_bytes(jambuf_t *buf, const void *ptr, size_t size) { size_t n = 0; const uint8_t *bytes = ptr; for (unsigned i = 0; i < size; i++) { uint8_t b = bytes[i]; n += jam(buf, "%02X", b); } return n; } /* * Roughly mimic DBG_dump(): use a space separator; and after the 4th * byte, a double space separator. * * This is so that values dumped by DBG_dump() and lswlog_bytes() have * the same 'look' - make searching and grepping easier. */ size_t jam_dump_bytes(jambuf_t *buf, const void *bytes, size_t size) { if (size == 0) { return 0; } else if (bytes == NULL) { /* will inject "(null)" or error */ return jam_string(buf, NULL); } size_t n = 0; const uint8_t *byte = bytes; const uint8_t *end = byte + size; const char *sep = ""; while (byte < end) { for (unsigned b = 0; b < 4 && byte < end; b++) { n += jam(buf, "%s%02x", sep, *byte++); sep = " "; } sep = " "; } return n; } /* * For logging - output the string but convert any unprintable * characters into an equivalent escape code. * * XXX: bonus points for anyone encoding \r \n ... correctly? */ size_t jam_sanitized_bytes(jambuf_t *buf, const void *ptr, size_t size) { size_t n = 0; const char *chars = ptr; for (unsigned i = 0; i < size; i++) { char c = chars[i]; if (isprint(c)) { n += jam_char(buf, c); } else { n += jam(buf, "\\%03o", c & 0xFF); } } return n; } /* * For shell variables - output the string but (assuming text is * enclosed in single quotes) convert any shell meta characters into * equivalent escape codes. */ size_t jam_meta_escaped_bytes(jambuf_t *buf, const void *ptr, size_t size) { size_t n = 0; const char *chars = ptr; for (unsigned i = 0; i < size; i++) { char c = chars[i]; if (isprint(c)) { switch (c) { case '\'': case '\\': case '"': case '`': case '$': n += jam(buf, "\\%03o", c & 0xFF); break; default: n += jam_char(buf, c); } } else { n += jam(buf, "\\%03o", c & 0xFF); } } return n; } libreswan-3.32/lib/libswan/jambuf.c000066400000000000000000000156501365625662500172730ustar00rootroot00000000000000/* string format buffer, for libreswan * * Copyright (C) 2017-2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include #include #include #include "jambuf.h" #include "lswalloc.h" #include "lswlog.h" /* for passert() */ /* * Since 'char' can be unsigned need to cast -2 onto a char sized * value. * * The octal equivalent would be something like '\376' but who uses * octal :-) */ #define JAMBUF_CANARY ((char) -2) /* * This is the one place where PASSERT() can't be used - it will * recursively end up back here! */ static void assert_jambuf(jambuf_t *buf) { #define A(ASSERTION) if (!(ASSERTION)) abort() A(buf->dots != NULL); /* termination */ A(buf->total >= buf->roof || buf->array[buf->total] == '\0'); A(buf->array[buf->roof-1] == '\0'); A(buf->array[buf->roof-0] == JAMBUF_CANARY); #undef A } static int jambuf_debugf_nop(const char *format UNUSED, ...) { return 0; } int (*jambuf_debugf)(const char *format, ...) = jambuf_debugf_nop; /* * Constructor */ jambuf_t array_as_jambuf(char *array, size_t sizeof_array) { jambuf_debugf("%s(array=%p,sizeof_array=%zu)\n", __func__, array, sizeof_array); /* pointers back at buf */ jambuf_t buf = { .array = array, .total = 0, .roof = sizeof_array - 1, .dots = "...", }; buf.array[buf.roof-1] = buf.array[buf.total] = '\0'; buf.array[buf.roof-0] = JAMBUF_CANARY; assert_jambuf(&buf); jambuf_debugf("\t->{.array=%p,.total=%zu,.roof=%zu,.dots='%s'}\n", buf.array, buf.total, buf.roof, buf.dots); return buf; } /* * Determine where, within LOG's message buffer, to write the string. */ struct dest { /* next character position (always points at '\0') */ char *cursor; /* free space */ size_t size; }; static struct dest dest(jambuf_t *buf) { /* * Where will the next message be written? */ struct dest d = { .cursor = NULL, .size = 0, }; if (buf->total < buf->roof) { d.cursor = buf->array + buf->total; d.size = buf->roof - buf->total; } else { /* point start at terminating '\0' */ d.cursor = buf->array + buf->roof - 1; d.size = 0; } passert(d.cursor[0] == '\0'); jambuf_debugf("%s(buf=%p)->{.cursor=%p,.size=%zd}\n", __func__, buf, d.cursor, d.size); return d; } /* * The output needs to be truncated, overwrite the end of the buffer * with DOTS. */ static void truncate_buf(jambuf_t *buf) { jambuf_debugf("truncate_buf(.buf=%p)\n", buf); jambuf_debugf("\tlength=%zu\n", buf->total); jambuf_debugf("\tdots=%s\n", buf->dots); /* * buffer is full to overflowing */ passert(buf->total >= buf->roof); passert(buf->array[buf->roof - 1] == '\0'); passert(buf->array[buf->roof - 2] != '\0'); /* * Backfill with DOTS. */ passert(buf->roof > strlen(buf->dots)); char *dest = buf->array + buf->roof - strlen(buf->dots) - 1; jambuf_debugf("\tdest=%p\n", dest); memcpy(dest, buf->dots, strlen(buf->dots) + 1); } /* * Try to append STRING[0..N) to BUF. Don't assume STRING is NUL * terminated. * * N (the return value) is the number of characters, not including the * trailing NUL, that should have been written to the buffer. */ size_t jam_raw_bytes(jambuf_t *buf, const void *string, size_t n) { assert_jambuf(buf); struct dest d = dest(buf); buf->total += n; if (d.size > n) { /* * There is space for all N characters and a trailing * NUL, copy the string and add a NULL (remember can't * assume STRING contains a NUL). */ memcpy(d.cursor, string, n); d.cursor[n] = '\0'; } else if (d.size > 0) { /* * Not enough space, perform a partial copy of the * string ... */ memcpy(d.cursor, string, d.size - 1); d.cursor[d.size - 1] = '\0'; /* * ... and then go back and blat the end with DOTS. */ truncate_buf(buf); } assert_jambuf(buf); return n; } size_t jam_va_list(jambuf_t *buf, const char *format, va_list ap) { assert_jambuf(buf); struct dest d = dest(buf); /* * N (the return value) is the number of characters, not * including the trailing NUL, that should have been written * to the buffer. */ int sn = vsnprintf(d.cursor, d.size, format, ap); if (sn < 0) { /* * A negative return value indicates an "output * error", but there is no output so it can't happen * (that or a very old, non-compliant, s*printf() * implementation that returns -1 instead of the * required size). */ abort(); } size_t n = sn; buf->total += n; if (d.size > 0 && n >= d.size) { /* * There was some space but the entire message didn't * fit - d.size-1 characters were written. Truncate * the buffer. */ truncate_buf(buf); } assert_jambuf(buf); return n; } size_t jam(jambuf_t *buf, const char *format, ...) { /* jam_va_list does assert */ va_list ap; va_start(ap, format); size_t n = jam_va_list(buf, format, ap); va_end(ap); return n; } size_t jam_char(jambuf_t *buf, char c) { return jam_raw_bytes(buf, &c, 1); } size_t jam_string(jambuf_t *buf, const char *string) { /* * Just in case a NULL ends up here. This has the side effect * of returning "6" for a NULL string. */ if (string == NULL) { string = "(null)"; } return jam_raw_bytes(buf, string, strlen(string)); } size_t jam_jambuf(jambuf_t *buf, jambuf_t *jambuf) { shunk_t s = jambuf_as_shunk(jambuf); return jam_raw_bytes(buf, s.ptr, s.len); } bool jambuf_ok(jambuf_t *buf) { assert_jambuf(buf); return buf->total < buf->roof; } const char *jambuf_cursor(jambuf_t *buf) { assert_jambuf(buf); struct dest d = dest(buf); return d.cursor; } shunk_t jambuf_as_shunk(jambuf_t *buf) { assert_jambuf(buf); struct dest d = dest(buf); return shunk2(buf->array, d.cursor - buf->array); } jampos_t jambuf_get_pos(jambuf_t *buf) { assert_jambuf(buf); jampos_t pos = { .total = buf->total, }; return pos; } void jambuf_set_pos(jambuf_t *buf, const jampos_t *pos) { assert_jambuf(buf); if (pos->total >= buf->roof) { /* "set" was already overflowed */ buf->total = pos->total; } else if (/* no overflow at all */ buf->total < buf->roof || /* overflowed post "set" but space to restore */ pos->total + strlen(buf->dots) < buf->roof) { /* * Either no overflow, or there's space to recover * from an overflow (can't recover when pos->total has * been scribbled on with dots). */ buf->array[pos->total] = '\0'; buf->total = pos->total; } else { /* * Can't recover from overflow (pos->total was * scribbed on with dots) so leave things overflowing. */ buf->total = buf->roof; } assert_jambuf(buf); } libreswan-3.32/lib/libswan/kernel_alg.c000066400000000000000000000120631365625662500201250ustar00rootroot00000000000000/* Kernel runtime algorithm, for libreswan * * Author: JuanJo Ciarlante * Copyright (C) 2018 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * Fixes by: * ML: Mathieu Lafon * */ #include #include "constants.h" #include "kernel_alg.h" #include "lswlog.h" #include "ike_alg.h" #include "ike_alg_encrypt.h" /* * ALG storage. Maintain several arrays. * * These arrays are sorted by alg's FQN. * * XXX: These arrays are grosely oversized. */ #define MAX_ALGS 32 static const struct integ_desc *integ_by_fqn[MAX_ALGS]; static const struct encrypt_desc *encrypt_by_fqn[MAX_ALGS]; static size_t integ_num = 0; static size_t encrypt_num = 0; /* * Forget previous registration * * XXX: Needed???? */ void kernel_alg_init(void) { dbg("kernel_alg_init()"); /* ??? do these zero calls do anything useful? */ zero(&integ_by_fqn); zero(&encrypt_by_fqn); encrypt_num = integ_num = 0; } /* * Make use of the fact that the table is kept sorted. */ #define ADD(ALG, DESC) \ dbg("adding %s to kernel algorithm db", \ alg->common.fqn); \ size_t i; \ for (i = 0; i < DESC##_num; i++) { \ int cmp = strcmp(DESC##_by_fqn[i]->common.fqn, \ alg->common.fqn); \ if (cmp == 0) { \ dbg("dropping %s kernel algorithm db duplicate found at %zu", \ alg->common.fqn, i); \ return; \ } else if (cmp > 0) { \ break; /* insertion point found */ \ } \ } \ passert(DESC##_num < elemsof(DESC##_by_fqn)); \ /* make space by moving the overlapping tail */ \ memmove(&DESC##_by_fqn[i+1], &DESC##_by_fqn[i], \ (DESC##_num - i) * sizeof(DESC##_by_fqn[0])); \ DESC##_num++; \ /* insert */ \ DESC##_by_fqn[i] = ALG; void kernel_integ_add(const struct integ_desc *alg) { ADD(alg, integ); } void kernel_encrypt_add(const struct encrypt_desc *alg) { ADD(alg, encrypt); } bool kernel_alg_dh_ok(const struct dh_desc *dh) { if (dh == NULL) { PEXPECT_LOG("%s", "DH needs to be valid (non-NULL)"); return false; } /* require an in-process/ike implementation of DH */ return ike_alg_is_ike(&dh->common); } #define KERNEL_ALG_OK(ALG, DESC)\ if (!pexpect(ALG != NULL)) { \ return false; \ } \ for (unsigned i = 0; i < DESC##_num; i++) { \ if (DESC##_by_fqn[i] == ALG) { \ return true; \ } \ } \ return false; bool kernel_alg_encrypt_ok(const struct encrypt_desc *alg) { KERNEL_ALG_OK(alg, encrypt); } bool kernel_alg_integ_ok(const struct integ_desc *alg) { KERNEL_ALG_OK(alg, integ); } bool kernel_alg_is_ok(const struct ike_alg *alg) { if (alg == NULL) { PEXPECT_LOG("%s", "algorithm needs to be valid (non-NULL)"); return false; } else if (alg->algo_type == &ike_alg_dh) { return kernel_alg_dh_ok(dh_desc(alg)); } else if (alg->algo_type == &ike_alg_encrypt) { return kernel_alg_encrypt_ok(encrypt_desc(alg)); } else if (alg->algo_type == &ike_alg_integ) { return kernel_alg_integ_ok(integ_desc(alg)); } else { PASSERT_FAIL("algorithm %s of type %s is not valid in the kernel", alg->fqn, ike_alg_type_name(alg->algo_type)); } } bool kernel_alg_encrypt_key_size(const struct encrypt_desc *encrypt, int keylen, size_t *key_size) { /* * Assume the two ENUMs are the same! */ enum ipsec_cipher_algo transid = encrypt->common.id[IKEv1_ESP_ID]; int sadb_ealg = transid; /* * XXX: Is KEYLEN ever zero for any case other than 'null' * encryption? If it is, patch it up and then log it to find * out. */ if (keylen == 0) { if (encrypt != &ike_alg_encrypt_null) { keylen = encrypt_min_key_bit_length(encrypt); DBG(DBG_KERNEL, DBG_log("XXX: %s has key length of 0, adjusting to %d", encrypt->common.fqn, keylen)); } } /* * This is all this function should be doing, which isn't * much. */ *key_size = keylen / BITS_PER_BYTE; DBG(DBG_PARSING, DBG_log("encrypt %s keylen=%d transid=%d, key_size=%zu, encryptalg=%d", encrypt->common.fqn, keylen, transid, *key_size, sadb_ealg)); return true; } #define NEXT(LAST, DESC) \ if (LAST == NULL) { \ return &DESC##_by_fqn[0]; \ } else if (LAST < &DESC##_by_fqn[DESC##_num-1]) { \ return LAST+1; \ } else { \ return NULL; \ } const struct encrypt_desc **next_kernel_encrypt_desc(const struct encrypt_desc **last) { NEXT(last, encrypt) } const struct integ_desc **next_kernel_integ_desc(const struct integ_desc **last) { NEXT(last, integ) } int kernel_alg_encrypt_count(void) { return encrypt_num; } int kernel_alg_integ_count(void) { return integ_num; } libreswan-3.32/lib/libswan/kernel_sadb.c000066400000000000000000000075071365625662500203020ustar00rootroot00000000000000/* SADB algorithm handling, for libreswan * * Author: JuanJo Ciarlante * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * Fixes by: * ML: Mathieu Lafon * */ #include #include "lswlog.h" #include "kernel_sadb.h" #include "kernel_alg.h" #include "ike_alg.h" /* used by kernel_netlink.c and kernel_bsdkame.c */ void kernel_add_sadb_alg(int satype, int exttype, const struct sadb_alg *sadb_alg) { uint8_t alg_id = sadb_alg->sadb_alg_id; const struct encrypt_desc *encrypt = NULL; const struct integ_desc *integ = NULL; bool combo_ok = false; switch (exttype) { case SADB_EXT_SUPPORTED_ENCRYPT: switch (satype) { case SADB_SATYPE_ESP: encrypt = encrypt_desc_by_sadb_ealg_id(alg_id); combo_ok = true; break; } break; case SADB_EXT_SUPPORTED_AUTH: switch (satype) { case SADB_SATYPE_ESP: case SADB_SATYPE_AH: integ = integ_desc_by_sadb_aalg_id(alg_id); combo_ok = true; break; } break; } LSWDBGP(DBG_KERNEL|DBG_CRYPT, buf) { lswlogs(buf, __func__); lswlogs(buf, ":"); lswlogf(buf, " satype=%d(%s)", satype, satype == SADB_SATYPE_ESP ? "SADB_SATYPE_ESP" : satype == SADB_SATYPE_AH ? "SADB_SATYPE_AH" : "SADB_SATYPE_???"); lswlogf(buf, " exttype=%d(%s)", exttype, exttype == SADB_EXT_SUPPORTED_AUTH ? "SADB_EXT_SUPPORTED_AUTH" : exttype == SADB_EXT_SUPPORTED_ENCRYPT ? "SADB_EXT_SUPPORTED_ENCRYPT" : "SADB_EXT_SUPPORTED_???"); DBG_log(" alg_id=%d(%s)", alg_id, integ != NULL ? integ->common.fqn : encrypt != NULL ? encrypt->common.fqn : "???"); lswlogf(buf, " alg_ivlen=%d, alg_minbits=%d, alg_maxbits=%d", sadb_alg->sadb_alg_ivlen, sadb_alg->sadb_alg_minbits, sadb_alg->sadb_alg_maxbits); if (integ == NULL && encrypt == NULL) { lswlogs(buf, ", not supported"); } if (!combo_ok) { lswlogs(buf, ", invalid combo"); } } if (encrypt != NULL) { kernel_encrypt_add(encrypt); } if (integ != NULL) { kernel_integ_add(integ); } } /* * Load kernel_alg arrays pluto's SADB_REGISTER * Used by programs/pluto/kernel_pfkey.c and programs/pluto/kernel_netlink.c */ void kernel_add_sadb_algs(const struct sadb_msg *const msg, size_t sizeof_msg) { uint8_t satype = msg->sadb_msg_satype; size_t msg_size = msg->sadb_msg_len * KERNEL_SADB_WORD_SIZE; passert(msg_size <= sizeof_msg); const void *p = msg + 1; /* cursor through message: start after header */ size_t msg_left = msg_size - sizeof(struct sadb_msg); while (msg_left >= sizeof(struct sadb_supported)) { const struct sadb_supported *supp = p; uint16_t supp_exttype = supp->sadb_supported_exttype; size_t supp_size = supp->sadb_supported_len * KERNEL_SADB_WORD_SIZE; dbg("kernel_alg_register_pfkey(): SADB_SATYPE_%s: sadb_msg_len=%u sadb_supported_len=%zd", (satype == SADB_SATYPE_ESP ? "ESP" : satype == SADB_SATYPE_AH ? "AH" : "???"), msg->sadb_msg_len, supp_size); passert(supp_size >= sizeof(struct sadb_supported)); passert(msg_left >= supp_size); p = supp + 1; /* after header */ msg_left -= supp_size; for (supp_size -= sizeof(struct sadb_supported); supp_size >= sizeof(struct sadb_alg); supp_size -= sizeof(struct sadb_alg)) { const struct sadb_alg *alg = p; kernel_add_sadb_alg(satype, supp_exttype, alg); p = alg + 1; /* after alg */ } passert(supp_size == 0); } passert(msg_left == 0); } libreswan-3.32/lib/libswan/kernel_xfrm_reply.c000066400000000000000000000041411365625662500215470ustar00rootroot00000000000000/* * netlink_read_reply generic netlink response, for libreswan * * Copyright (C) 2012-2013 Kim B. Heino * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include #include #include #include #include "lswalloc.h" #include "kernel_xfrm_reply.h" ssize_t netlink_read_reply(int sock, char **pbuf, size_t bufsize, unsigned int seqnum, __u32 pid) { size_t msglen = 0; for (;;) { struct sockaddr_nl sa; ssize_t readlen; /* Read netlink message, verifying kernel origin. */ do { socklen_t salen = sizeof(sa); readlen = recvfrom(sock, *pbuf + msglen, bufsize - msglen, 0, (struct sockaddr *)&sa, &salen); if (readlen <= 0 || salen != sizeof(sa)) return -1; } while (sa.nl_pid != 0); /* Verify it's valid */ struct nlmsghdr *nlhdr = (struct nlmsghdr *)(*pbuf + msglen); if (!NLMSG_OK(nlhdr, (size_t)readlen) || nlhdr->nlmsg_type == NLMSG_ERROR) return -1; /* Move read pointer */ msglen += readlen; /* Check if it is the last message */ if (nlhdr->nlmsg_type == NLMSG_DONE) break; /* all done if it's not a multi part */ if ((nlhdr->nlmsg_flags & NLM_F_MULTI) == 0) break; /* all done if this is the one we were searching for */ if (nlhdr->nlmsg_seq == seqnum && nlhdr->nlmsg_pid == pid) break; /* Allocate more memory for buffer if needed. */ if (msglen >= bufsize - NL_BUFMARGIN) { bufsize = bufsize * 2; char *newbuf = alloc_bytes(bufsize, "netlink query"); memcpy(newbuf, *pbuf, msglen); pfree(*pbuf); *pbuf = newbuf; } } return msglen; } libreswan-3.32/lib/libswan/keyblobtoid.3.xml000066400000000000000000000123461365625662500210540ustar00rootroot00000000000000 PaulWoutersplaceholder to suppress warning IPSEC_KEYBLOBTOID 3 25 March 2002 libreswan Library functions ipsec keyblobtoid ipsec splitkeytoid generate key IDs from RSA keys #include <libreswan.h> size_t keyblobtoid const unsigned char * blob size_t bloblen char * dst size_t dstlen size_t splitkeytoid const unsigned char * e size_t elen const unsigned char * m size_t mlen char * dst size_t dstlen DESCRIPTION Keyblobtoid and splitkeytoid generate key IDs from RSA keys, for use in messages and reporting, writing the result to dst. A key ID is a short ASCII string identifying a key; currently it is just the first nine characters of the base64 encoding of the RFC 2537/3110 “byte blob” representation of the key. (Beware that no finite key ID can be collision-proof: there is always some small chance of two random keys having the same ID.) Keyblobtoid generates a key ID from a key which is already in the form of an RFC 2537/3110 binary key blob (encoded exponent length, exponent, modulus). Splitkeytoid generates a key ID from a key given in the form of a separate (binary) exponent e and modulus m. The dstlen parameter of either specifies the size of the dst parameter; under no circumstances are more than dstlen bytes written to dst. A result that will not fit is truncated. Dstlen can be zero, in which case dst need not be valid and no result is written, but the return value is unaffected; in all other cases, the (possibly truncated) result is NUL-terminated. The libreswan.h header file defines a constant KEYID_BUF which is the size of a buffer large enough for worst-case results. Both functions return 0 for a failure, and otherwise always return the size of buffer that would be needed to accommodate the full conversion result, including terminating NUL; it is the caller's responsibility to check this against the size of the provided buffer to determine whether truncation has occurred. With keys generated by ipsec_rsasigkey3, the first two base64 digits are always the same, and the third carries only about one bit of information. It's worse with keys using longer fixed exponents, e.g. the 24-bit exponent that's common in X.509 certificates. However, being able to relate key IDs to the full base64 text form of keys by eye is sufficiently useful that this waste of space seems justifiable. The choice of nine digits is a compromise between bulk and probability of collision. SEE ALSO RFC 3110, RSA/SHA-1 SIGs and RSA KEYs in the Domain Name System (DNS), Eastlake, 2001 (superseding the older but better-known RFC 2537). DIAGNOSTICS Fatal errors are: key too short to supply enough bits to construct a complete key ID (almost certainly indicating a garbage key); exponent too long for its length to be representable. HISTORY Written for the FreeS/WAN project by Henry Spencer. libreswan-3.32/lib/libswan/keyblobtoid.c000066400000000000000000000066121365625662500203340ustar00rootroot00000000000000/* * generate printable key IDs * Copyright (C) 2002 Henry Spencer. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. */ #include #include "libreswan.h" /* * keyblobtoid - generate a printable key ID from an RFC 2537/3110 key blob * * Current algorithm is just to use first nine base64 digits. */ size_t keyblobtoid(src, srclen, dst, dstlen) const unsigned char *src; size_t srclen; char *dst; /* need not be valid if dstlen is 0 */ size_t dstlen; { char buf[KEYID_BUF]; size_t ret; # define NDIG 9 if (srclen < (NDIG * 6 + 7) / 8) { strcpy(buf, "?len= ?"); buf[5] = '0' + srclen; ret = 0; } else { (void) datatot(src, srclen, 64, buf, NDIG + 1); ret = NDIG + 1; } if (dstlen > 0) { if (strlen(buf) + 1 > dstlen) *(buf + dstlen - 1) = '\0'; strcpy(dst, buf); } return ret; } /* * splitkeytoid - generate a printable key ID from exponent/modulus pair * * Just constructs the beginnings of a key blob and calls keyblobtoid(). */ size_t splitkeytoid(e, elen, m, mlen, dst, dstlen) const unsigned char *e; size_t elen; const unsigned char *m; size_t mlen; char *dst; /* need not be valid if dstlen is 0 */ size_t dstlen; { unsigned char buf[KEYID_BUF]; /* ample room */ unsigned char *bufend = buf + sizeof(buf); unsigned char *p; p = buf; /* start with length of e; assume that it fits */ if (elen <= 255) { *p++ = elen; } else if ((elen & ~0xffff) == 0) { *p++ = 0; *p++ = (elen >> 8) & 0xff; *p++ = elen & 0xff; } else { return 0; /* unrepresentable exponent length */ } /* append as much of e as fits */ { size_t n = bufend - p; if (elen < n) n = elen; memcpy(p, e, n); p += n; } /* append as much of m as fits */ { size_t n = bufend - p; if (mlen < n) n = mlen; memcpy(p, m, n); p += n; } return keyblobtoid(buf, p - buf, dst, dstlen); } #ifdef KEYBLOBTOID_MAIN #include void regress(void); int main(argc, argv) int argc; char *argv[]; { typedef unsigned char uc; uc hexblob[] = "\x01\x03\x85\xf2\xd6\x76\x9b\x03\x59\xb6\x21\x52"; uc hexe[] = "\x03"; uc hexm[] = "\x85\xf2\xd6\x76\x9b\x03\x59\xb6\x21\x52\xef\x85"; char b64nine[] = "AQOF8tZ2m"; char b64six[] = "AQOF8t"; char buf[100]; size_t n; char *b = b64nine; size_t bl = strlen(b) + 1; int st = 0; n = keyblobtoid(hexblob, strlen(hexblob), buf, sizeof(buf)); if (n != bl) { fprintf(stderr, "%s: keyblobtoid returned %d not %d\n", argv[0], n, bl); st = 1; } if (!streq(buf, b)) { fprintf(stderr, "%s: keyblobtoid generated `%s' not `%s'\n", argv[0], buf, b); st = 1; } n = splitkeytoid(hexe, strlen(hexe), hexm, strlen(hexm), buf, sizeof(buf)); if (n != bl) { fprintf(stderr, "%s: splitkeytoid returned %d not %d\n", argv[0], n, bl); st = 1; } if (!streq(buf, b)) { fprintf(stderr, "%s: splitkeytoid generated `%s' not `%s'\n", argv[0], buf, b); st = 1; } exit(st); } #endif /* KEYBLOBTOID_MAIN */ libreswan-3.32/lib/libswan/keywords.c000066400000000000000000000052541365625662500176750ustar00rootroot00000000000000/* keywords, for libreswan * * Copyright (C) 2018 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include "keywords.h" #include "lswlog.h" const struct keyword *keyword_by_name(const struct keywords *keywords, shunk_t name) { for (unsigned ki = 0; ki < keywords->nr_values; ki++) { const struct keyword *kv = &keywords->values[ki]; if (kv->name != NULL && shunk_strcaseeq(name, kv->name)) { return kv; } } return NULL; } const struct keyword *keyword_by_sname(const struct keywords *keywords, shunk_t name) { for (unsigned ki = 0; ki < keywords->nr_values; ki++) { const struct keyword *kv = &keywords->values[ki]; if (kv->sname != NULL && shunk_strcaseeq(name, kv->sname)) { return kv; } } return NULL; } const struct keyword *keyword_by_value_direct(const struct keywords *keywords, unsigned value) { if (value >= keywords->nr_values) { return NULL; } const struct keyword *kw = &keywords->values[value]; if (kw->name == NULL) { return NULL; } passert(kw->value == value); return kw; } #if 0 const struct keyword *keyword_by_value_binary(const struct keywords *keywords, unsigned value) { } #endif const struct keyword *keyword_by_value_linear(const struct keywords *keywords, unsigned value) { for (unsigned ki = 0; ki < keywords->nr_values; ki++) { const struct keyword *kv = &keywords->values[ki]; if (kv->value == value) { return kv; } } return NULL; } const struct keyword *keyword_by_value(const struct keywords *keywords, unsigned value) { return keywords->by_value(keywords, value); } size_t lswlog_keyname(struct lswlog *buf, const struct keywords *keywords, unsigned value) { const struct keyword *keyword = keyword_by_value(keywords, value); if (keyword == NULL) { return lswlogf(buf, "'%s %u'", keywords->name, value); } else { return lswlogs(buf, keyword->name); } } size_t lswlog_keysname(struct lswlog *buf, const struct keywords *keywords, unsigned value) { const struct keyword *keyword = keyword_by_value(keywords, value); if (keyword == NULL) { return lswlogf(buf, "'%s %u'", keywords->name, value); } else { return lswlogs(buf, keyword->sname); } } libreswan-3.32/lib/libswan/lex.c000066400000000000000000000116421365625662500166140ustar00rootroot00000000000000/* * lexer (lexical analyzer) for control files * * Copyright (C) 1998-2001 D. Hugh Redelmeier. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include #include #include #include #include #include #include "sysdep.h" #include "constants.h" #include "lswlog.h" #include "lex.h" struct file_lex_position *flp = NULL; /* * Open a file for lexical processing. * * new_flp and name must point into storage and will live * at least until the file is closed. * * @param new_flp file position * @param name filename * @param bool optional * @return bool True if successful */ bool lexopen(struct file_lex_position *new_flp, const char *name, bool optional) { FILE *f = fopen(name, "r"); if (f == NULL) { if (!optional || errno != ENOENT) LOG_ERRNO(errno, "could not open \"%s\"", name); return FALSE; } else { new_flp->previous = flp; flp = new_flp; flp->filename = name; flp->fp = f; flp->lino = 0; flp->bdry = B_none; flp->cur = flp->buffer; /* nothing loaded yet */ flp->under = *flp->cur = '\0'; (void) shift(); /* prime tok */ return TRUE; } } /* * Close filehandle */ void lexclose(void) { fclose(flp->fp); flp = flp->previous; } /* * Token decoding: shift() loads the next token into tok. * If a token starts at the left margin, it is considered * to be the first in a record. We create a special condition, * Record Boundary (analogous to EOF), just before such a token. * We are unwilling to shift through a record boundary: * it must be overridden first. * Returns FALSE if Record Boundary or EOF (i.e. no token); * tok will then be NULL. */ /* * shift - load next token into tok * * @return bool True if successful */ bool shift(void) { char *p = flp->cur; char *sor = NULL; /* start of record for any new lines */ passert(flp->bdry == B_none); *p = flp->under; flp->under = '\0'; for (;;) { switch (*p) { case '\0': /* end of line */ case '#': /* * comment to end of line: treat as end of * line */ /* get the next line */ if (fgets(flp->buffer, sizeof(flp->buffer) - 1, flp->fp) == NULL) { flp->bdry = B_file; flp->tok = flp->cur = NULL; return FALSE; } else { /* strip trailing whitespace, including \n */ for (p = flp->buffer + strlen(flp->buffer); p > flp->buffer && isspace(p[-1]); p--) ; *p = '\0'; flp->lino++; sor = p = flp->buffer; } break; /* try again for a token */ case ' ': /* whitespace */ case '\t': p++; break; /* try again for a token */ case '"': /* quoted token */ case '\'': case '`': /* or execute quotes */ if (p != sor) { /* * we have a quoted token: * note and advance to its end */ flp->tok = p; p = strchr(p + 1, *p); if (p == NULL) { loglog(RC_LOG_SERIOUS, "\"%s\" line %d: unterminated string", flp->filename, flp->lino); p = flp->tok + strlen(flp->tok); } else { p++; /* include delimiter in token */ } /* * remember token delimiter and replace * with '\0' */ flp->under = *p; *p = '\0'; flp->cur = p; return TRUE; } /* FALL THROUGH */ default: if (p != sor) { /* * we seem to have a token: * note and advance to its end */ flp->tok = p; if (p[0] == '0' && p[1] == 't') { /* 0t... token goes to end of line */ p += strlen(p); } else { /* * "ordinary" token: * up to whitespace or end of line */ do { p++; } while (*p != '\0' && !isspace(*p)); /* * fudge to separate ':' from * a preceding adjacent token */ if (p - 1 > flp->tok && p[-1] == ':') p--; } /* * remember token delimiter and replace * with '\0' */ flp->under = *p; *p = '\0'; flp->cur = p; return TRUE; } /* * we have a start-of-record: * return it, deferring "real" token */ flp->bdry = B_record; flp->tok = NULL; flp->under = *p; flp->cur = p; return FALSE; } } } /* * ensures we are at a Record (or File) boundary, optionally warning if not * * @param m string * @return bool True if everything is ok */ bool flushline(const char *m) { if (flp->bdry != B_none) { return TRUE; } else { if (m != NULL) loglog(RC_LOG_SERIOUS, "\"%s\" line %d: %s", flp->filename, flp->lino, m); do {} while (shift()); return FALSE; } } libreswan-3.32/lib/libswan/libreswan_bad_case.c000066400000000000000000000015751365625662500216170ustar00rootroot00000000000000/* bad_case() wrapper, for libreswan * * Copyright (C) 2018 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include #include #include #include "lswlog.h" void libreswan_bad_case(const char *expression, long value, where_t where) { lsw_passert_fail(where, "switch (%s) case %ld (0x%lx) unexpected", expression, value, value); } libreswan-3.32/lib/libswan/libreswan_exit_log_errno.c000066400000000000000000000016721365625662500231130ustar00rootroot00000000000000/* log wrapper, for libreswan * * Copyright (C) 2018 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include #include #include "lswlog.h" void libreswan_exit_log_errno(int e, const char *fmt, ...) { LSWBUF(buf) { lswlog_errno_prefix(buf, "FATAL ERROR: "); va_list ap; va_start(ap, fmt); lswlogvf(buf, fmt, ap); va_end(ap); lswlog_errno_suffix(buf, e); } libreswan_exit(PLUTO_EXIT_FAIL); } libreswan-3.32/lib/libswan/libreswan_log.c000066400000000000000000000015041365625662500206470ustar00rootroot00000000000000/* log wrapper, for libreswan * * Copyright (C) 2017 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include #include #include "lswlog.h" int libreswan_log(const char *fmt, ...) { LSWLOG(buf) { va_list ap; va_start(ap, fmt); lswlogvf(buf, fmt, ap); va_end(ap); } return 0; } libreswan-3.32/lib/libswan/libreswan_log_errno.c000066400000000000000000000016151365625662500220570ustar00rootroot00000000000000/* log wrapper, for libreswan * * Copyright (C) 2018 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include #include #include "lswlog.h" void libreswan_log_errno(int e, const char *fmt, ...) { LSWBUF(buf) { lswlog_errno_prefix(buf, "ERROR: "); va_list ap; va_start(ap, fmt); lswlogvf(buf, fmt, ap); va_end(ap); lswlog_errno_suffix(buf, e); } } libreswan-3.32/lib/libswan/libreswan_log_rc.c000066400000000000000000000015251365625662500213360ustar00rootroot00000000000000/* log wrapper, for libreswan * * Copyright (C) 2017 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include #include #include "lswlog.h" void libreswan_log_rc(enum rc_type rc, const char *fmt, ...) { LSWLOG_RC(rc, buf) { va_list ap; va_start(ap, fmt); lswlogvf(buf, fmt, ap); va_end(ap); } } libreswan-3.32/lib/libswan/lmod.c000066400000000000000000000056301365625662500167570ustar00rootroot00000000000000/* lset modifiers, for libreswan * * Copyright (C) 2017-2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include #include #include "constants.h" #include "lmod.h" #include "lswlog.h" #include "lswalloc.h" const lmod_t empty_lmod = { LEMPTY, LEMPTY, }; bool lmod_empty(lmod_t mod) { return mod.set == LEMPTY && mod.clr == LEMPTY; } void lmod_merge(lmod_t *lhs, lmod_t rhs) { lhs->set = (lhs->set & ~rhs.clr) | rhs.set; lhs->clr = (lhs->clr & ~rhs.set) | rhs.clr; } lset_t lmod(lset_t set, lmod_t mod) { return (set & ~mod.clr ) | mod.set; } lmod_t lmod_set(lmod_t mod, lset_t set) { mod.set |= set; mod.clr &= ~set; return mod; } lmod_t lmod_clr(lmod_t mod, lset_t clr) { mod.clr |= clr; mod.set &= ~clr; return mod; } bool lmod_is_set(lmod_t mod, lset_t set) { return LIN(set, mod.set); } bool lmod_is_clr(lmod_t mod, lset_t clr) { return LIN(clr, mod.clr); } bool lmod_arg(lmod_t *mod, const struct lmod_info *info, const char *args, bool enable) { char *list = clone_str(args, "list"); /* must free */ bool ok = true; const char *delim = "+, \t"; for (char *tmp = list, *elem = strsep(&tmp, delim); elem != NULL; elem = strsep(&tmp, delim)) { if (enable && streq(elem, "all")) { /* excludes --no-... all */ mod->clr = LEMPTY; mod->set = info->all; } else if (enable && streq(elem, "none")) { /* excludes --no-... none */ mod->clr = info->mask; mod->set = LEMPTY; } else if (*elem != '\0') { /* non-empty */ const char *arg = elem; /* excludes --no-... no-... */ bool no = enable ? eat(arg, "no-") : true; int ix = enum_match(info->names, shunk1(arg)); lset_t bit = LEMPTY; if (ix >= 0) { bit = LELEM(ix); } else if (info->compat != NULL) { for (struct lmod_compat *c = info->compat; c->name != NULL; c++) { if (streq(c->name, arg)) { bit = c->bit; break; } } } if (bit == LEMPTY) { ok = false; break; } if (no) { mod->clr |= bit; mod->set &= ~bit; } else { mod->set |= bit; mod->clr &= ~bit; } } /* else ignore empty ... */ } pfree(list); return ok; } void lswlog_lmod(struct lswlog *buf, enum_names *names, const char *separator, lmod_t mod) { lswlog_enum_lset_short(buf, names, separator, mod.set); if (mod.clr != LEMPTY) { lswlogs(buf, " - "); lswlog_enum_lset_short(buf, names, separator, mod.clr); } } libreswan-3.32/lib/libswan/log_ip.c000066400000000000000000000012651365625662500172750ustar00rootroot00000000000000/* enable ip logging, for libreswan * * Copyright (C) 2018 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include "ip_address.h" /* for log_ip */ bool log_ip = true; libreswan-3.32/lib/libswan/log_pexpect.c000066400000000000000000000015601365625662500203330ustar00rootroot00000000000000/* log wrapper, for libreswan * * Copyright (C) 2018 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include #include #include "lswlog.h" void log_pexpect(where_t where, const char *message, ...) { LSWLOG_PEXPECT_WHERE(where, buf) { va_list args; va_start(args, message); lswlogvf(buf, message, args); va_end(args); } } libreswan-3.32/lib/libswan/lset.c000066400000000000000000000053451365625662500167760ustar00rootroot00000000000000/* lset_t routines, for libreswan * * Copyright (C) 2012-2017 Paul Wouters * Copyright (C) 2012 Avesh Agarwal * Copyright (C) 1998-2002,2015 D. Hugh Redelmeier. * Copyright (C) 2016-2017 Andrew Cagney * Copyright (C) 2017 Vukasin Karadzic * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include "lset.h" #include "lswlog.h" /* for passert() */ /* * NOT RE-ENTRANT! */ const char *bitnamesof(const char *const table[], lset_t val) { static char bitnamesbuf[8192]; /* I hope that it is big enough! */ return bitnamesofb(table, val, bitnamesbuf, sizeof(bitnamesbuf)); } /* test a set by seeing if all bits have names */ bool testset(const char *const table[], lset_t val) { lset_t bit; const char *const *tp; for (tp = table, bit = 01; val != 0; bit <<= 1, tp++) { const char *n = *tp; if (n == NULL || ((val & bit) && *n == '\0')) return false; val &= ~bit; } return true; } /* * construct a string to name the bits on in a set * * Result of bitnamesof may be in STATIC buffer -- NOT RE-ENTRANT! * Note: prettypolicy depends on internal details of bitnamesofb. * binamesofb is re-entrant since the caller provides the buffer. */ const char *bitnamesofb(const char *const table[], lset_t val, char *b, size_t blen) { char *const roof = b + blen; char *p = b; lset_t bit; const char *const *tp; passert(blen != 0); /* need room for NUL */ /* if nothing gets filled in, default to "none" rather than "" */ (void) jam_str(b, blen, "none"); for (tp = table, bit = 01; val != 0; bit <<= 1) { if (val & bit) { const char *n = *tp; if (p != b) p = jam_str(p, (size_t)(roof - p), "+"); if (n == NULL || *n == '\0') { /* * No name for this bit, so use hex. * if snprintf returns a different value from * strlen, truncation happened */ (void)snprintf(p, (size_t)(roof - p), "0x%" PRIxLSET, bit); p += strlen(p); } else { p = jam_str(p, (size_t)(roof - p), n); } val -= bit; } /* * Move on in the table, but not past end. * This is a bit of a trick: while we are at stuck the end, * the loop will print out the remaining bits in hex. */ if (*tp != NULL) tp++; } return b; } libreswan-3.32/lib/libswan/lsw_passert_fail.c000066400000000000000000000017741365625662500213720ustar00rootroot00000000000000/* * abort log function, for libreswan * * Copyright (C) 2017 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include #include #include "lswlog.h" void lsw_passert_fail(where_t where, const char *fmt, ...) { LSWBUF(buf) { lswlog_passert_prefix(buf); va_list ap; va_start(ap, fmt); lswlogvf(buf, fmt, ap); va_end(ap); lswlog_passert_suffix(buf, where); } /* above will panic but compiler doesn't know this */ abort(); } libreswan-3.32/lib/libswan/lswconf.3.xml000066400000000000000000000226361365625662500202230ustar00rootroot00000000000000 PaulWoutersplaceholder to suppress warning IPSEC_LSW_INIT_OPTIONS 3 4 December 2005 libreswan Library functions ipsec_lsw_init_options initialize and return a structure of relevant pathnames #include <lswconf.h> const struct lsw_conf_options *lsw_init_options void DESCRIPTION lsw_init_options, Examines Currently supported formats are hexadecimal, base64, and characters. A hexadecimal text value begins with a 0x (or 0X) prefix and continues with two-digit groups of hexadecimal digits (0-9, and a-f or A-F), each group encoding the value of one binary byte, high-order digit first. A single _ (underscore) between consecutive groups is ignored, permitting punctuation to improve readability; doing this every eight digits seems about right. A base64 text value begins with a 0s (or 0S) prefix and continues with four-digit groups of base64 digits (A-Z, a-z, 0-9, +, and /), each group encoding the value of three binary bytes as described in section 6.8 of RFC 2045. If flags has the TTODATAV_IGNORESPACE bit on, blanks are ignore (after the prefix). Note that the last one or two digits of a base64 group can be = to indicate that fewer than three binary bytes are encoded. A character text value begins with a 0t (or 0T) prefix and continues with text characters, each being the value of one binary byte. All these functions basically copy data from src (whose size is specified by srclen) to dst (whose size is specified by dstlen), doing the conversion en route. If the result will not fit in dst, it is truncated; under no circumstances are more than dstlen bytes of result written to dst. Dstlen can be zero, in which case dst need not be valid and no result bytes are written at all. The base parameter of ttodata and ttodatav specifies what format the input is in; normally it should be 0 to signify that this gets figured out from the prefix. Values of 16, 64, and 256 respectively signify hexadecimal, base64, and character-text formats without prefixes. The format parameter of datatot, a single character used as a type code, specifies which text format is wanted. The value 0 (not ASCII '0', but a zero value) specifies a reasonable default. Other currently-supported values are: 'x' continuous lower-case hexadecimal with a 0x prefix 'h' lower-case hexadecimal with a 0x prefix and a _ every eight digits ':' lower-case hexadecimal with no prefix and a : (colon) every two digits 16 lower-case hexadecimal with no prefix or _ 's' continuous base64 with a 0s prefix 64 continuous base64 with no prefix The default format is currently 'h'. Ttodata returns NULL for success and a pointer to a string-literal error message for failure; see DIAGNOSTICS. On success, if and only if lenp is non-NULL, *lenp is set to the number of bytes required to contain the full untruncated result. It is the caller's responsibility to check this against dstlen to determine whether he has obtained a complete result. The *lenp value is correct even if dstlen is zero, which offers a way to determine how much space would be needed before having to allocate any. Ttodatav is just like ttodata except that in certain cases, if errp is non-NULL, the buffer pointed to by errp (whose length is given by errlen) is used to hold a more detailed error message. The return value is NULL for success, and is either errp or a pointer to a string literal for failure. If the size of the error-message buffer is inadequate for the desired message, ttodatav will fall back on returning a pointer to a literal string instead. The libreswan.h header file defines a constant TTODATAV_BUF which is the size of a buffer large enough for worst-case results. The normal return value of datatot is the number of bytes required to contain the full untruncated result. It is the caller's responsibility to check this against dstlen to determine whether he has obtained a complete result. The return value is correct even if dstlen is zero, which offers a way to determine how much space would be needed before having to allocate any. A return value of 0 signals a fatal error of some kind (see DIAGNOSTICS). A zero value for srclen in ttodata (but not datatot!) is synonymous with strlen(src). A non-zero srclen in ttodata must not include the terminating NUL. Unless dstlen is zero, the result supplied by datatot is always NUL-terminated, and its needed-size return value includes space for the terminating NUL. SEE ALSO sprintf3, ipsec_atoaddr3 DIAGNOSTICS Fatal errors in ttodata and ttodatav are: unknown characters in the input; unknown or missing prefix; unknown base; incomplete digit group; non-zero padding in a base64 less-than-three-bytes digit group; zero-length input. Fatal errors in datatot are: unknown format code; zero-length input. HISTORY Written for the FreeS/WAN project by Henry Spencer. BUGS Datatot should have a format code to produce character-text output. The 0s and 0t prefixes are the author's inventions and are not a standard of any kind. They have been chosen to avoid collisions with existing practice (some C implementations use 0b for binary) and possible confusion with unprefixed hexadecimal. libreswan-3.32/lib/libswan/lswconf.c000066400000000000000000000122631365625662500174770ustar00rootroot00000000000000/* * misc functions to get compile time and runtime options * * Copyright (C) 2005 Michael Richardson * Copyright (C) 2009 Avesh Agarwal * Copyright (C) 2012 Paul Wouters * Copyright (C) 2013 Tuomo Soini * Copyright (C) 2016, Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include #include #include #include "lswlog.h" #include "lswconf.h" #include "lswalloc.h" #include #include #include #include #include static struct lsw_conf_options global_oco; #ifdef SINGLE_CONF_DIR #define SUBDIRNAME(X) "" #else #define SUBDIRNAME(X) X #endif /* * Fill in the basics, return true, of lsw_conf_calculate should be * called. */ static bool lsw_conf_setdefault(void) { if (global_oco.rootdir != NULL) { return FALSE; } /* copy everything to the heap for consistency. */ global_oco.rootdir = clone_str("", "rootdir"); global_oco.confdir = clone_str(IPSEC_CONFDIR, "default conf ipsec_conf_dir"); global_oco.conffile = clone_str(IPSEC_CONF, "default conf conffile"); global_oco.secretsfile = clone_str(IPSEC_SECRETS_FILE, "default ipsec.secrets"); global_oco.vardir = clone_str(IPSEC_VARDIR, "default vardir"); global_oco.confddir = clone_str(IPSEC_CONFDDIR, "default conf ipsecd_dir"); global_oco.nssdir = clone_str(IPSEC_NSSDIR, "default nssdir"); /* see also lsw_conf_calculate() below */ return TRUE; } static void subst(char **field, const char *value, const char *name) { pfreeany(*field); *field = clone_str(value, name); } /* * Some things are rooted under CONFDDIR, re-compute them. */ static void lsw_conf_calculate(void) { char buf[PATH_MAX]; /* will be phased out for NSS in the near future */ snprintf(buf, sizeof(buf), "%s" SUBDIRNAME("/cacerts"), global_oco.confddir); subst(&global_oco.cacerts_dir, buf, "cacert path"); snprintf(buf, sizeof(buf), "%s" SUBDIRNAME("/crls"), global_oco.confddir); subst(&global_oco.crls_dir, buf, "crls path"); /* old OE policies - might get re-used in the near future */ snprintf(buf, sizeof(buf), "%s/policies", global_oco.confddir); subst(&global_oco.policies_dir, buf, "policies path"); snprintf(buf, sizeof(buf), "%s/nsspassword", global_oco.confddir); subst(&global_oco.nsspassword_file, buf, "nsspassword file"); } void lsw_conf_free_oco(void) { /* * Must be a nicer way to loop over this? * * for (char *p = (char*)&global_oco; p < (char*)(&global_oco + 1); p++) */ pfreeany(global_oco.rootdir); pfreeany(global_oco.confdir); pfreeany(global_oco.conffile); pfreeany(global_oco.secretsfile); pfreeany(global_oco.vardir); pfreeany(global_oco.confddir); pfreeany(global_oco.policies_dir); pfreeany(global_oco.cacerts_dir); pfreeany(global_oco.crls_dir); pfreeany(global_oco.nsspassword_file); pfreeany(global_oco.nsspassword); pfreeany(global_oco.nssdir); messup(&global_oco); } const struct lsw_conf_options *lsw_init_options(void) { if (lsw_conf_setdefault()) { lsw_conf_calculate(); } return &global_oco; } /* This is only used in testing/crypto (and formerly in testing/lib/libpluto) */ void lsw_conf_rootdir(const char *root_dir) { lsw_conf_setdefault(); subst(&global_oco.rootdir, root_dir, "override /"); lsw_conf_calculate(); } void lsw_conf_confddir(const char *confddir) { lsw_conf_setdefault(); subst(&global_oco.confddir, confddir, "override ipsec.d"); lsw_conf_calculate(); libreswan_log("adjusting ipsec.d to %s", global_oco.confddir); } void lsw_conf_nssdir(const char *nssdir) { lsw_conf_setdefault(); subst(&global_oco.nssdir, nssdir, "override nssdir"); lsw_conf_calculate(); libreswan_log("adjusting nssdir to %s", global_oco.nssdir); } void lsw_conf_secretsfile(const char *secretsfile) { lsw_conf_setdefault(); subst(&global_oco.secretsfile, secretsfile, "secretsfile"); lsw_conf_calculate(); } void lsw_conf_nsspassword(const char *nsspassword) { lsw_conf_setdefault(); subst(&global_oco.nsspassword, nsspassword, "nsspassword"); lsw_conf_calculate(); } /* * 0 disabled * 1 enabled * 2 indeterminate */ int libreswan_selinux(void) { char selinux_flag[1]; int n; FILE *fd = fopen("/sys/fs/selinux/enforce", "r"); if (fd == NULL) { /* try new location first, then old location */ fd = fopen("/selinux/enforce", "r"); if (fd == NULL) { DBGF(DBG_CONTROL, "SElinux: disabled, could not open /sys/fs/selinux/enforce or /selinux/enforce"); return 0; } } n = fread((void *)selinux_flag, 1, 1, fd); fclose(fd); if (n != 1) { libreswan_log("SElinux: could not read 1 byte from the selinux enforce file"); return 2; } if (selinux_flag[0] == '1') return 1; else return 0; } libreswan-3.32/lib/libswan/lswfips.c000066400000000000000000000067541365625662500175230ustar00rootroot00000000000000/* * misc functions to get compile time and runtime options * * Copyright (C) 2005 Michael Richardson * Copyright (C) 2009 Avesh Agarwal * Copyright (C) 2012,2020 Paul Wouters * Copyright (C) 2013 Tuomo Soini * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include #include #include "lswlog.h" #include "lswnss.h" #include "lswfips.h" #define LSW_FIPS_DEFAULT LSW_FIPS_UNSET /* * Is the machine running in FIPS kernel mode (fips=1 kernel argument) * We no longer check this ourselves, but depend solely on NSS, as * the mechanisms are expected to change in the future. */ static enum lsw_fips_mode lsw_fips_system(void) { return PK11_IsFIPS() ? LSW_FIPS_ON : LSW_FIPS_OFF; } /* * Legacy FIPS product test. This is only used for RHEL6 to RHEL8 * * Return TRUE if we are a fips product. * This is irrespective of whether we are running in FIPS mode * yes (1), no (0), unknown(-1) */ #ifdef FIPS_CHECK static enum lsw_fips_mode lsw_fipsproduct(void) { if (access(FIPSPRODUCTCHECK, F_OK) != 0) { if (errno == ENOENT || errno == ENOTDIR) { return LSW_FIPS_OFF; } else { loglog(RC_LOG_SERIOUS, "FIPS ABORT: FIPS product check failed to determine status for %s: %d: %s", FIPSPRODUCTCHECK, errno, strerror(errno)); return LSW_FIPS_UNKNOWN; } } return LSW_FIPS_ON; } #endif static enum lsw_fips_mode fips_mode = LSW_FIPS_DEFAULT; /* * Should only be called directly by plutomain.c */ enum lsw_fips_mode lsw_get_fips_mode(void) { /* * Fips mode as set by the below. * * Otherwise determine value using fipsproduct and fips_system. * The problem here is that confread.c calls this (from * addconn) without first calling set_fipsmode. */ if (fips_mode > LSW_FIPS_UNSET) { return fips_mode; } #ifdef FIPS_CHECK enum lsw_fips_mode product = lsw_fipsproduct(); #endif enum lsw_fips_mode system = lsw_fips_system(); fips_mode = system; #ifdef FIPS_CHECK if (product == LSW_FIPS_UNKNOWN) fips_mode = LSW_FIPS_UNKNOWN; if (product == LSW_FIPS_OFF && system == LSW_FIPS_ON) fips_mode = LSW_FIPS_OFF; libreswan_log("FIPS Product: %s", product == LSW_FIPS_UNKNOWN ? "UNKNOWN" : product == LSW_FIPS_ON ? "YES" : "NO"); libreswan_log("FIPS System: %s", system == LSW_FIPS_UNKNOWN ? "UNKNOWN" : system == LSW_FIPS_ON ? "YES" : "NO"); #endif libreswan_log("FIPS Mode: %s", fips_mode == LSW_FIPS_ON ? "YES" : fips_mode == LSW_FIPS_OFF ? "NO" : "UNKNOWN"); return fips_mode; } /* * Is the machine running in FIPS mode (fips product AND fips system (kernel) mode) * Only pluto needs to know UNKNOWN, so it can abort. Every other caller can * just check for fips mode using: if (libreswan_fipsmode()) */ bool libreswan_fipsmode(void) { if (fips_mode == LSW_FIPS_UNSET) fips_mode = lsw_get_fips_mode(); return fips_mode == LSW_FIPS_ON; } /* * used only for debugging with --impair-force-fips */ void lsw_set_fips_mode(enum lsw_fips_mode fips) { fips_mode = fips; } libreswan-3.32/lib/libswan/lswlog.c000066400000000000000000000023051365625662500173270ustar00rootroot00000000000000/* expectation failure, for libreswan * * Copyright (C) 2017 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include #include #include #include "lswlog.h" #include "lswalloc.h" /* * Constructor */ size_t lswlogvf(struct lswlog *log, const char *format, va_list ap) { return jam_va_list(log, format, ap); } size_t lswlogf(struct lswlog *log, const char *format, ...) { va_list ap; va_start(ap, format); size_t n = jam_va_list(log, format, ap); va_end(ap); return n; } size_t lswlogs(struct lswlog *log, const char *string) { return jam_string(log, string); } size_t lswlogl(struct lswlog *log, struct lswlog *buf) { return jam_jambuf(log, buf); } libreswan-3.32/lib/libswan/lswlog_enum_lset_short.c000066400000000000000000000021701365625662500226210ustar00rootroot00000000000000/* * logging, for libreswan * * Copyright (C) 2017 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include "lswlog.h" size_t lswlog_enum_lset_short(struct lswlog *buf, enum_names *en, const char *separator, lset_t val) { unsigned int e; /* if nothing gets filled in, default to "none" rather than "" */ if (val == LEMPTY) { return lswlogs(buf, "none"); } size_t size = 0; const char *sep = ""; for (e = 0; val != 0; e++) { lset_t bit = LELEM(e); if (val & bit) { size += lswlogs(buf, sep); sep = separator; size += lswlog_enum_short(buf, en, e); val -= bit; } } return size; } libreswan-3.32/lib/libswan/lswlog_nss_cka.c000066400000000000000000000020251365625662500210270ustar00rootroot00000000000000/* Output the decoded NSS CK_ATTRIBUTE, for libreswan * * Copyright (C) 2017 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ /* * XXX: Is there an NSS version of this? */ #include "lswlog.h" #include "lswnss.h" size_t lswlog_nss_cka(struct lswlog *buf, CK_ATTRIBUTE_TYPE attribute) { switch (attribute) { #define CASE(T) case T: return lswlogs(buf, #T + strlen("CKA_")) CASE(CKA_DERIVE); CASE(CKA_FLAGS_ONLY); CASE(CKA_UNWRAP); #undef CASE default: return lswlogf(buf, "CKA_%08lx", (long)attribute); } } libreswan-3.32/lib/libswan/lswlog_nss_ckf.c000066400000000000000000000022421365625662500210350ustar00rootroot00000000000000/* Output the decoded NSS CK_FLAG, for libreswan * * Copyright (C) 2017 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ /* * XXX: Is there an NSS version of this? */ #include "lswlog.h" #include "lswnss.h" size_t lswlog_nss_ckf(struct lswlog *buf, CK_FLAGS flags) { const char *sep = ""; size_t size = 0; /* nothing smart about this */ #define FLAG(F) \ if (flags & F) { \ size += lswlogs(buf, sep); \ size += lswlogs(buf, #F + strlen("CKF_")); \ sep = "+"; \ flags ^= F; \ } FLAG(CKF_SIGN); FLAG(CKF_ENCRYPT); FLAG(CKF_DECRYPT); if (flags != 0) { size += lswlogf(buf, "%sCKF_%08lx", sep, (long) flags); } return size; } libreswan-3.32/lib/libswan/lswlog_nss_ckm.c000066400000000000000000000042131365625662500210440ustar00rootroot00000000000000/* Output the decoded NSS CK_MECHANISM_TYPE, for libreswan * * Copyright (C) 2017 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ /* * XXX: Is there an NSS version of this? */ #include "lswlog.h" #include "lswnss.h" size_t lswlog_nss_ckm(struct lswlog *buf, CK_MECHANISM_TYPE mechanism) { switch (mechanism) { #define CASE(T) case T: return lswlogs(buf, #T + strlen("CKM_")) CASE(CKM_CONCATENATE_BASE_AND_DATA); CASE(CKM_CONCATENATE_BASE_AND_KEY); CASE(CKM_CONCATENATE_DATA_AND_BASE); CASE(CKM_XOR_BASE_AND_DATA); CASE(CKM_EXTRACT_KEY_FROM_KEY); CASE(CKM_AES_CBC); CASE(CKM_DES3_CBC); CASE(CKM_CAMELLIA_CBC); CASE(CKM_AES_CTR); CASE(CKM_AES_GCM); CASE(CKM_AES_MAC); CASE(CKM_AES_ECB); #ifdef CKM_AES_XCBC_MAC CASE(CKM_AES_XCBC_MAC); #endif CASE(CKM_AES_KEY_GEN); CASE(CKM_MD5); CASE(CKM_SHA_1); CASE(CKM_SHA256); CASE(CKM_SHA384); CASE(CKM_SHA512); CASE(CKM_MD5_KEY_DERIVATION); CASE(CKM_SHA1_KEY_DERIVATION); CASE(CKM_SHA256_KEY_DERIVATION); CASE(CKM_SHA384_KEY_DERIVATION); CASE(CKM_SHA512_KEY_DERIVATION); CASE(CKM_MD5_HMAC); CASE(CKM_SHA_1_HMAC); CASE(CKM_SHA256_HMAC); CASE(CKM_SHA384_HMAC); CASE(CKM_SHA512_HMAC); CASE(CKM_DH_PKCS_DERIVE); CASE(CKM_ECDH1_DERIVE); #ifdef CKM_NSS_IKE_PRF_DERIVE CASE(CKM_NSS_IKE_PRF_DERIVE); #endif #ifdef CKM_NSS_IKE1_PRF_DERIVE CASE(CKM_NSS_IKE1_PRF_DERIVE); #endif #ifdef CKM_NSS_IKE_PRF_PLUS_DERIVE CASE(CKM_NSS_IKE_PRF_PLUS_DERIVE); #endif #ifdef CKM_NSS_IKE1_APP_B_PRF_DERIVE CASE(CKM_NSS_IKE1_APP_B_PRF_DERIVE); #endif CASE(CKM_VENDOR_DEFINED); #undef CASE default: return lswlogf(buf, "CKM_%08lx", (long)mechanism); } } libreswan-3.32/lib/libswan/lswlog_nss_error.c000066400000000000000000000037431365625662500214320ustar00rootroot00000000000000/* Output an (NS)PR error, for libreswan * * Copyright (C) 2017 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include #include #include #include #include "lswlog.h" #include "lswalloc.h" #include "lswnss.h" /* * See https://bugzilla.mozilla.org/show_bug.cgi?id=172051 */ size_t lswlog_nss_error(struct lswlog *buf) { size_t size = 0; int error = PR_GetError(); /* at least 32-bits */ size += lswlogs(buf, " ("); /* the number */ if (IS_SEC_ERROR(error)) { size += lswlogf(buf, "SECERR: %d (0x%x): ", error - SEC_ERROR_BASE, error - SEC_ERROR_BASE); } else { size += lswlogf(buf, "NSS: %d (0x%x): ", error, error); } /* * NSPR should contain string tables for all known error * classes. Query that first. Should this specify the * english language? */ const char *text = PR_ErrorToString(error, PR_LANGUAGE_I_DEFAULT); if (text != NULL) { size += lswlogs(buf, text); } else { /* * Try NSPR directly, is this redundant? Sometimes * NSS forgets to set the actual error and this * handles that case. */ PRInt32 length = PR_GetErrorTextLength(); if (length != 0) { char *text = alloc_things(char, length, "error message"); PR_GetErrorText(text); size += lswlogs(buf, text); pfree(text); } else { size += lswlogs(buf, "unknown error"); } } if (error == 0) { size += lswlogs(buf, "; 0 indicates NSS lost the error code"); } size += lswlogs(buf, ")"); return size; } libreswan-3.32/lib/libswan/lswlog_nss_secitem.c000066400000000000000000000030201365625662500217160ustar00rootroot00000000000000/* Output a secitem * * Copyright (C) 2018 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ /* * XXX: Is there an NSS version of this? */ #include "lswlog.h" #include "lswnss.h" static size_t lswlog_nss_secitemtype(struct lswlog *buf, SECItemType type) { #define C(T) case T: return lswlogs(buf, #T) switch (type) { C(siBuffer); C(siClearDataBuffer); C(siCipherDataBuffer); C(siDERCertBuffer); C(siEncodedCertBuffer); C(siDERNameBuffer); C(siEncodedNameBuffer); C(siAsciiNameString); C(siAsciiString); C(siDEROID); C(siUnsignedInteger); C(siUTCTime); C(siGeneralizedTime); C(siVisibleString); C(siUTF8String); C(siBMPString); default: return lswlogf(buf, "(SECItemType)%d", type); } } size_t lswlog_nss_secitem(struct lswlog *buf, const SECItem *secitem) { size_t size = 0; if (secitem == NULL) { size = lswlogs(buf, "(SECItem*)NULL"); } else { lswlog_nss_secitemtype(buf, secitem->type); jam(buf, ": "); jam_dump_bytes(buf, secitem->data, secitem->len); } return size; } libreswan-3.32/lib/libswan/lswlog_passert.c000066400000000000000000000017261365625662500210760ustar00rootroot00000000000000/* Output an assertion failure, for libreswan * * Copyright (C) 2017 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include #include "lswlog.h" void lswlog_passert_prefix(struct lswlog *buf) { lswlog_log_prefix(buf); lswlogs(buf, "ABORT: ASSERTION FAILED: "); } void lswlog_passert_suffix(struct lswlog *buf, where_t where) { jam(buf, " "PRI_WHERE, pri_where(where)); lswlog_to_error_stream(buf); /* this needs to panic */ abort(); } libreswan-3.32/lib/libswan/lswlog_pexpect.c000066400000000000000000000016311365625662500210600ustar00rootroot00000000000000/* Output an expectation failure, for libreswan * * Copyright (C) 2017 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include "lswlog.h" void lswlog_pexpect_prefix(struct lswlog *buf) { lswlog_log_prefix(buf); lswlogs(buf, "EXPECTATION FAILED: "); } void lswlog_pexpect_suffix(struct lswlog *buf, where_t where) { jam(buf, " "PRI_WHERE, pri_where(where)); lswlog_to_error_stream(buf); } libreswan-3.32/lib/libswan/lswlog_to_file_stream.c000066400000000000000000000015371365625662500224110ustar00rootroot00000000000000/* Send LSWLOG to a file with implicit '\n', for libreswan * * Copyright (C) 2017 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include #include "lswlog.h" size_t lswlog_to_file_stream(struct lswlog *buf, FILE *file) { lswlogs(buf, "\n"); shunk_t out = jambuf_as_shunk(buf); return fwrite(out.ptr, out.len, 1, file); } libreswan-3.32/lib/libswan/lswnss.c000066400000000000000000000224061365625662500173550ustar00rootroot00000000000000/* * NSS boilerplate stuff, for libreswan. * * Copyright (C) 2016, Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include #include #include #include #include "lswconf.h" #include "lswnss.h" #include "lswalloc.h" #include "lswlog.h" #include "lswfips.h" static unsigned flags; bool lsw_nss_setup(const char *configdir, unsigned setup_flags, PK11PasswordFunc get_password, lsw_nss_buf_t err) { /* * save for cleanup */ flags = setup_flags; /* * According to the manual, not needed, and all parameters are * ignored. Does no harm? */ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 1); libreswan_log("Initializing NSS"); if (configdir != NULL) { const char sql[] = "sql:"; char *nssdir; if (strncmp(sql, configdir, strlen(sql)) == 0) { nssdir = strdup(configdir); } else { nssdir = alloc_bytes(strlen(configdir) + strlen(sql) + 1, "(ignore) nssdir"); strcpy(nssdir, sql); strcat(nssdir, configdir); } libreswan_log("Opening NSS database \"%s\" %s", nssdir, (flags & LSW_NSS_READONLY) ? "read-only" : "read-write"); SECStatus rv = NSS_Initialize(nssdir, "", "", SECMOD_DB, (flags & LSW_NSS_READONLY) ? NSS_INIT_READONLY : 0); if (rv != SECSuccess) { snprintf(err, sizeof(lsw_nss_buf_t), "Initialization of NSS with %s database \"%s\" failed (%d)", (flags & LSW_NSS_READONLY) ? "read-only" : "read-write", nssdir, PR_GetError()); pfree(nssdir); return FALSE; } } else { NSS_NoDB_Init("."); if (libreswan_fipsmode() && !PK11_IsFIPS()) { SECMODModule *internal = SECMOD_GetInternalModule(); if (internal == NULL) { snprintf(err, sizeof(lsw_nss_buf_t), "SECMOD_GetInternalModule() failed"); return false; } if (SECMOD_DeleteInternalModule(internal->commonName) != SECSuccess) { snprintf(err, sizeof(lsw_nss_buf_t), "SECMOD_DeleteInternalModule(%s) failed", internal->commonName); return false; } if (!PK11_IsFIPS()) { snprintf(err, sizeof(lsw_nss_buf_t), "NSS FIPS mode toggle failed"); return false; } } } if (PK11_IsFIPS() && configdir != NULL && get_password == NULL) { snprintf(err, sizeof(lsw_nss_buf_t), "in FIPS mode a password is required"); return FALSE; } if (get_password != NULL) { PK11_SetPasswordFunc(get_password); } if (configdir != NULL) { PK11SlotInfo *slot = lsw_nss_get_authenticated_slot(err); if (slot == NULL) { return FALSE; } PK11_FreeSlot(slot); } return TRUE; } void lsw_nss_shutdown(void) { NSS_Shutdown(); /* this flag is never set anywhere */ if (!(flags & LSW_NSS_SKIP_PR_CLEANUP)) { PR_Cleanup(); } } static void fill_RSA_public_key(struct RSA_public_key *rsa, SECKEYPublicKey *pubkey) { passert(SECKEY_GetPublicKeyType(pubkey) == rsaKey); rsa->e = clone_secitem_as_chunk(pubkey->u.rsa.publicExponent, "e"); rsa->n = clone_secitem_as_chunk(pubkey->u.rsa.modulus, "n"); form_keyid(rsa->e, rsa->n, rsa->keyid, &rsa->k); } PK11SlotInfo *lsw_nss_get_authenticated_slot(lsw_nss_buf_t err) { PK11SlotInfo *slot = PK11_GetInternalKeySlot(); if (slot == NULL) { snprintf(err, sizeof(lsw_nss_buf_t), "no internal key slot"); return NULL; } if (PK11_IsFIPS() || PK11_NeedLogin(slot)) { SECStatus status = PK11_Authenticate(slot, PR_FALSE, lsw_return_nss_password_file_info()); if (status != SECSuccess) { const char *token = PK11_GetTokenName(slot); snprintf(err, sizeof(lsw_nss_buf_t), "authentication of \"%s\" failed", token); PK11_FreeSlot(slot); return NULL; } } return slot; } struct private_key_stuff *lsw_nss_foreach_private_key_stuff(secret_eval func, void *uservoid, lsw_nss_buf_t err) { /* * So test for error with "if (err[0]) ..." works. */ err[0] = '\0'; PK11SlotInfo *slot = lsw_nss_get_authenticated_slot(err); if (slot == NULL) { return NULL; } SECKEYPrivateKeyList *list = PK11_ListPrivateKeysInSlot(slot); if (list == NULL) { snprintf(err, sizeof(lsw_nss_buf_t), "no list"); PK11_FreeSlot(slot); return NULL; } int line = 1; struct private_key_stuff *result = NULL; SECKEYPrivateKeyListNode *node; for (node = PRIVKEY_LIST_HEAD(list); !PRIVKEY_LIST_END(node, list); node = PRIVKEY_LIST_NEXT(node)) { if (SECKEY_GetPrivateKeyType(node->key) != rsaKey) { /* only rsa for now */ continue; } struct private_key_stuff pks = { .kind = PKK_RSA, .on_heap = TRUE, }; { SECItem *nss_ckaid = PK11_GetLowLevelKeyIDForPrivateKey(node->key); if (nss_ckaid == NULL) { // fprintf(stderr, "ckaid not found\n"); continue; } const char *err = form_ckaid_nss(nss_ckaid, &pks.u.RSA_private_key.pub.ckaid); SECITEM_FreeItem(nss_ckaid, PR_TRUE); if (err) { // fprintf(stderr, "ckaid not found\n"); continue; } } { SECKEYPublicKey *pubkey = SECKEY_ConvertToPublicKey(node->key); if (pubkey != NULL) { fill_RSA_public_key(&pks.u.RSA_private_key.pub, pubkey); SECKEY_DestroyPublicKey(pubkey); } } /* * Only count private keys that get processed. */ pks.line = line++; int ret = func(NULL, &pks, uservoid); if (ret == 0) { /* * save/return the result. * * XXX: Potential Memory leak. * * lsw_foreach_secret() + lsw_get_pks() * returns an object that must not be freed * BUT lsw_nss_foreach_private_key_stuff() * returns an object that must be freed. * * For moment ignore this - as only caller is * showhostkey.c which quickly exits. */ result = clone_thing(pks, "pks"); break; } freeanyckaid(&pks.u.RSA_private_key.pub.ckaid); freeanychunk(pks.u.RSA_private_key.pub.e); freeanychunk(pks.u.RSA_private_key.pub.n); if (ret < 0) { break; } } SECKEY_DestroyPrivateKeyList(list); PK11_FreeSlot(slot); return result; } char *lsw_nss_get_password(PK11SlotInfo *slot, PRBool retry, void *arg UNUSED) { if (retry) { /* nothing changed */ return NULL; } if (slot == NULL) { /* nothing to secure */ return NULL; } /* * Get a name. * * TOKEN tied to slot so does not need to be freed. */ const char *token = PK11_GetTokenName(slot); if (token == NULL) { libreswan_log("NSS Password slot has no token name"); return NULL; } if (PK11_ProtectedAuthenticationPath(slot)) { libreswan_log("NSS Password for token \"%s\" failed, slot has protected authentication path", token); return NULL; } const struct lsw_conf_options *oco = lsw_init_options(); /* * Easy case, passsword specified on the command line. */ if (oco->nsspassword != NULL) { char *password = PORT_Strdup(oco->nsspassword); libreswan_log("NSS Password for token \"%s\" with length %zu passed to NSS", token, strlen(password)); return password; } /* * Hard case, password in a file. Look for TOKEN:password. * * Do not free the TOKEN. */ const int max_password_file_size = 4096; char *passwords = PORT_ZAlloc(max_password_file_size); if (passwords == NULL) { libreswan_log("NSS Password file \"%s\" for token \"%s\" could not be loaded, NSS memory allocate failed", oco->nsspassword_file, token); return NULL; } /* * From here on, every return must be preceded by * PORT_Free(passwords). */ size_t passwords_len; { PRFileDesc *fd = PR_Open(oco->nsspassword_file, PR_RDONLY, 0); if (fd == NULL) { libreswan_log("NSS Password file \"%s\" for token \"%s\" could not be opened for reading", oco->nsspassword_file, token); PORT_Free(passwords); return NULL; } passwords_len = PR_Read(fd, passwords, max_password_file_size); PR_Close(fd); } size_t i; for (i = 0; i < passwords_len; ) { /* * examine a line of the password file * token_name:password */ int start = i; char *p; /* find end of line */ while (i < passwords_len && (passwords[i] != '\0' && passwords[i] != '\r' && passwords[i] != '\n')) i++; if (i == passwords_len) { libreswan_log("NSS Password file \"%s\" for token \"%s\" ends with a partial line (ignored)", oco->nsspassword_file, token); break; /* no match found */ } size_t linelen = i - start; /* turn delimiter into NUL and skip over it */ passwords[i++] = '\0'; p = &passwords[start]; size_t toklen = PORT_Strlen(token); if (linelen >= toklen + 1 && PORT_Strncmp(p, token, toklen) == 0 && p[toklen] == ':') { /* we have a winner! */ p = PORT_Strdup(&p[toklen + 1]); libreswan_log("NSS Password from file \"%s\" for token \"%s\" with length %zu passed to NSS", oco->nsspassword_file, token, PORT_Strlen(p)); PORT_Free(passwords); return p; } } /* no match found in password file */ libreswan_log("NSS Password file \"%s\" does not contain token \"%s\"", oco->nsspassword_file, token); PORT_Free(passwords); return NULL; } libreswan-3.32/lib/libswan/monotime.c000066400000000000000000000052111365625662500176460ustar00rootroot00000000000000/* monotonic time, for libreswan * * Copyright (C) 1998-2001 D. Hugh Redelmeier. * Copyright (C) 2014 D. Hugh Redelmeier. * Copyright (C) 2015 Paul Wouters * Copyright (C) 2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include /* for clock_*() + clockid_t */ #include "constants.h" /* for memeq() which is clearly not a constant */ #include "lswlog.h" /* for libreswan_exit_log_errno() */ #include "monotime.h" monotime_t monotime(intmax_t seconds) { return (monotime_t) { .mt = { .tv_sec = seconds, }, }; } const monotime_t monotime_epoch = MONOTIME_EPOCH; bool is_monotime_epoch(monotime_t t) { return memeq(&t, &monotime_epoch, sizeof(monotime_t)); } clockid_t monotime_clockid(void) { #ifdef CLOCK_BOOTTIME return CLOCK_BOOTTIME; /* best */ #else return CLOCK_MONOTONIC; /* second best */ #endif } monotime_t mononow(void) { struct timespec t; int e = clock_gettime(monotime_clockid(), &t); if (e != 0) { libreswan_exit_log_errno(e, "clock_gettime(%d,...) in mononow() failed", monotime_clockid()); } /* OK */ return (monotime_t) { .mt = { .tv_sec = t.tv_sec, .tv_usec = t.tv_nsec / 1000, }, }; } struct timespec monotime_as_timespec(monotime_t t) { struct timespec ts = { .tv_sec = t.mt.tv_sec, .tv_nsec = t.mt.tv_usec * 1000, }; return ts; } intmax_t monosecs(monotime_t m) { return m.mt.tv_sec; } monotime_t monotimesum(monotime_t t, deltatime_t d) { intmax_t d_ms = deltamillisecs(d); struct timeval dt = { d_ms / 1000, d_ms % 1000 }; monotime_t s = MONOTIME_EPOCH; timeradd(&t.mt, &dt, &s.mt); return s; } bool monobefore(monotime_t a, monotime_t b) { return timercmp(&a.mt, &b.mt, <); } deltatime_t monotimediff(monotime_t a, monotime_t b) { return deltatime_timevals_diff(a.mt, b.mt); } size_t jam_monotime(jambuf_t *buf, monotime_t m) { /* convert it to time-since-epoch and log that */ return lswlog_deltatime(buf, monotimediff(m, monotime_epoch)); } const char *str_monotime(monotime_t m, monotime_buf *buf) { jambuf_t jambuf = ARRAY_AS_JAMBUF(buf->buf); jam_monotime(&jambuf, m); return buf->buf; } libreswan-3.32/lib/libswan/netlink_attrib.c000066400000000000000000000043441365625662500210360ustar00rootroot00000000000000/* * netlink atrributes to message, for libreswan * * Copyright (C) 2018-2020 Antony Antony * A part of this came from iproute2 lib/libnetlink.c * Authors: Alexey Kuznetsov, * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include #include #include "lswlog.h" #include "netlink_attrib.h" #define RTA_TAIL(rta) ((struct rtattr *) (((void *) (rta)) + \ RTA_ALIGN((rta)->rta_len))) #define NLMSG_TAIL(nmsg) \ ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) bool nl_addattr_l(struct nlmsghdr *n, const unsigned short maxlen, const unsigned short type, const void *data, int alen) { unsigned short len = RTA_LENGTH(alen); struct rtattr *rta; if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) { loglog(RC_LOG_SERIOUS, "ERROR: addattr_l: message exceeded bound %hu / %hu", n->nlmsg_len, maxlen); } rta = NLMSG_TAIL(n); rta->rta_type = type; rta->rta_len = len; if (alen) memcpy(RTA_DATA(rta), data, alen); n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len); return NULL; } struct rtattr *nl_addattr_nest(struct nlmsghdr *n, int maxlen, int type) { struct rtattr *nest = NLMSG_TAIL(n); nl_addattr_l(n, maxlen, type, NULL, 0); return nest; } bool nl_addattr_nest_end(struct nlmsghdr *n, struct rtattr *nest) { nest->rta_len = (void *)NLMSG_TAIL(n) - (void *)nest; return n->nlmsg_len; } bool nl_addattrstrz(struct nlmsghdr *n, int maxlen, int type, const char *str) { return nl_addattr_l(n, maxlen, type, str, strlen(str)+1); } bool nl_addattr32(struct nlmsghdr *n, int maxlen, int type, const uint32_t data) { return nl_addattr_l(n, maxlen, type, &data, sizeof(uint32_t)); } libreswan-3.32/lib/libswan/nss_cert_load.c000066400000000000000000000052671365625662500206510ustar00rootroot00000000000000/* * NSS certificate loading routines, for libreswan * * Copyright (C) 2015 Matt Rogers * Copyright (C) 2016, Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include "lswnss.h" #include "lswlog.h" #include "nss_cert_load.h" CERTCertificate *get_cert_by_nickname_from_nss(const char *nickname) { return nickname == NULL ? NULL : PK11_FindCertFromNickname(nickname, lsw_return_nss_password_file_info()); } struct ckaid_match_arg { SECItem ckaid; CERTCertificate *cert; }; static SECStatus ckaid_match(CERTCertificate *cert, SECItem *ignore1 UNUSED, void *arg) { struct ckaid_match_arg *ckaid_match_arg = arg; if (ckaid_match_arg->cert != NULL) { return SECSuccess; } SECItem *ckaid = PK11_GetLowLevelKeyIDForCert(NULL, cert, lsw_return_nss_password_file_info()); if (ckaid == NULL) { DBG(DBG_CONTROL, DBG_log("GetLowLevelID for cert %s failed", cert->nickname)); return SECSuccess; } if (SECITEM_ItemsAreEqual(ckaid, &ckaid_match_arg->ckaid)) { DBG(DBG_CONTROLMORE, DBG_log("CKAID matched cert %s", cert->nickname)); ckaid_match_arg->cert = CERT_DupCertificate(cert); /* bail early, but how? */ } SECITEM_FreeItem(ckaid, PR_TRUE); return SECSuccess; } CERTCertificate *get_cert_by_ckaid_t_from_nss(ckaid_t ckaid) { struct ckaid_match_arg ckaid_match_arg = { .cert = NULL, .ckaid = *ckaid.nss, }; PK11_TraverseSlotCerts(ckaid_match, &ckaid_match_arg, lsw_return_nss_password_file_info()); return ckaid_match_arg.cert; } CERTCertificate *get_cert_by_ckaid_from_nss(const char *ckaid) { if (ckaid == NULL) { return NULL; } /* convert hex string ckaid to binary bin */ size_t binlen = (strlen(ckaid) + 1) / 2; char *bin = alloc_bytes(binlen, "ckaid"); const char *ugh = ttodata(ckaid, 0, 16, bin, binlen, &binlen); if (ugh != NULL) { pfree(bin); /* should have been rejected by whack? */ libreswan_log("invalid hex CKAID '%s': %s", ckaid, ugh); return NULL; } SECItem ckaid_nss = { .type = siBuffer, .data = (void*) bin, .len = binlen, }; ckaid_t ckaid_buf = { .nss = &ckaid_nss, }; CERTCertificate *cert = get_cert_by_ckaid_t_from_nss(ckaid_buf); pfree(bin); return cert; } libreswan-3.32/lib/libswan/nss_copies.c000066400000000000000000000065621365625662500201760ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifdef _MIPS_SIM # include #endif #include #include /* * The NSS function CERT_CompareAVA() appears in the NSS header files, * but the library does not actually export the function. This is a copy * of that function until upstream NSS is fixed and the fix available in * the common Linux distributions. This workaround is enabled using * NSS_REQ_AVA_COPY=true * * See also: * https://bugzilla.mozilla.org/show_bug.cgi?id=1336487 * https://bugzilla.mozilla.org/show_bug.cgi?id=294538 */ static void _NSSCPY_canonicalize(SECItem * foo) { int ch, lastch, len, src, dest; /* strip trailing whitespace. */ len = foo->len; while (len > 0 && ((ch = foo->data[len - 1]) == ' ' || ch == '\t' || ch == '\r' || ch == '\n')) { len--; } src = 0; /* strip leading whitespace. */ while (src < len && ((ch = foo->data[src]) == ' ' || ch == '\t' || ch == '\r' || ch == '\n')) { src++; } dest = 0; lastch = ' '; while (src < len) { ch = foo->data[src++]; if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') { ch = ' '; if (ch == lastch) continue; } else if (ch >= 'A' && ch <= 'Z') { ch |= 0x20; /* downshift */ } foo->data[dest++] = lastch = ch; } foo->len = dest; } /* SECItems a and b contain DER-encoded printable strings. */ static SECComparison _NSSCPY_CERT_CompareDERPrintableStrings(const SECItem *a, const SECItem *b) { SECComparison rv = SECLessThan; SECItem * aVal = CERT_DecodeAVAValue(a); SECItem * bVal = CERT_DecodeAVAValue(b); if (aVal && aVal->len && aVal->data && bVal && bVal->len && bVal->data) { _NSSCPY_canonicalize(aVal); _NSSCPY_canonicalize(bVal); rv = SECITEM_CompareItem(aVal, bVal); } SECITEM_FreeItem(aVal, PR_TRUE); SECITEM_FreeItem(bVal, PR_TRUE); return rv; } static SECComparison _NSSCPY_CERT_CompareAVA(const CERTAVA *a, const CERTAVA *b) { SECComparison rv; rv = SECITEM_CompareItem(&a->type, &b->type); if (SECEqual != rv) return rv; /* Attribute types don't match. */ /* Let's be optimistic. Maybe the values will just compare equal. */ rv = SECITEM_CompareItem(&a->value, &b->value); if (SECEqual == rv) return rv; /* values compared exactly. */ if (a->value.len && a->value.data && b->value.len && b->value.data) { /* Here, the values did not match. ** If the values had different encodings, convert them to the same ** encoding and compare that way. */ if (a->value.data[0] != b->value.data[0]) { /* encodings differ. Convert both to UTF-8 and compare. */ SECItem * aVal = CERT_DecodeAVAValue(&a->value); SECItem * bVal = CERT_DecodeAVAValue(&b->value); if (aVal && aVal->len && aVal->data && bVal && bVal->len && bVal->data) { rv = SECITEM_CompareItem(aVal, bVal); } SECITEM_FreeItem(aVal, PR_TRUE); SECITEM_FreeItem(bVal, PR_TRUE); } else if (a->value.data[0] == 0x13) { /* both are printable strings. */ /* printable strings */ rv = _NSSCPY_CERT_CompareDERPrintableStrings(&a->value, &b->value); } } return rv; } SECComparison CERT_CompareAVA(const CERTAVA *a, const CERTAVA *b) { return _NSSCPY_CERT_CompareAVA(a, b); } libreswan-3.32/lib/libswan/oid.c000066400000000000000000000277761365625662500166160ustar00rootroot00000000000000/* * List of some useful object identifiers (OIDs) * * Copyright (C) 2003-2004 Andreas Steffen, Zuercher Hochschule Winterthur * Copyright (C) 2014 Tuomo Soini * * This file has been generated by the script lib/libswan/oid.pl * Do not edit manually! */ #include "oid.h" const oid_t oid_names[] = { /* octet, down, next, name */ { 0x02, 1, 7, "ITU-T Administration" }, /* 0 */ { 0x82, 1, 0, "" }, /* 1 */ { 0x06, 1, 0, "Germany ITU-T member" }, /* 2 */ { 0x01, 1, 0, "Deutsche Telekom AG" }, /* 3 */ { 0x0A, 1, 0, "" }, /* 4 */ { 0x07, 1, 0, "" }, /* 5 */ { 0x14, 0, 0, "ND" }, /* 6 */ { 0x09, 1, 18, "data" }, /* 7 */ { 0x92, 1, 0, "" }, /* 8 */ { 0x26, 1, 0, "" }, /* 9 */ { 0x89, 1, 0, "" }, /* 10 */ { 0x93, 1, 0, "" }, /* 11 */ { 0xF2, 1, 0, "" }, /* 12 */ { 0x2C, 1, 0, "" }, /* 13 */ { 0x64, 1, 0, "pilot" }, /* 14 */ { 0x01, 1, 0, "pilotAttributeType" }, /* 15 */ { 0x01, 0, 17, "UID" }, /* 16 */ { 0x19, 0, 0, "DC" }, /* 17 */ { 0x55, 1, 51, "X.500" }, /* 18 */ { 0x04, 1, 36, "X.509" }, /* 19 */ { 0x03, 0, 21, "CN" }, /* 20 */ { 0x04, 0, 22, "S" }, /* 21 */ { 0x05, 0, 23, "SN" }, /* 22 */ { 0x06, 0, 24, "C" }, /* 23 */ { 0x07, 0, 25, "L" }, /* 24 */ { 0x08, 0, 26, "ST" }, /* 25 */ { 0x0A, 0, 27, "O" }, /* 26 */ { 0x0B, 0, 28, "OU" }, /* 27 */ { 0x0C, 0, 29, "T" }, /* 28 */ { 0x0D, 0, 30, "D" }, /* 29 */ { 0x24, 0, 31, "userCertificate" }, /* 30 */ { 0x29, 0, 32, "N" }, /* 31 */ { 0x2A, 0, 33, "G" }, /* 32 */ { 0x2B, 0, 34, "I" }, /* 33 */ { 0x2D, 0, 35, "ID" }, /* 34 */ { 0x48, 0, 0, "role" }, /* 35 */ { 0x1d, 1, 0, "id-ce" }, /* 36 */ { 0x09, 0, 38, "subjectDirectoryAttrs" }, /* 37 */ { 0x0E, 0, 39, "subjectKeyIdentifier" }, /* 38 */ { 0x0F, 0, 40, "keyUsage" }, /* 39 */ { 0x10, 0, 41, "privateKeyUsagePeriod" }, /* 40 */ { 0x11, 0, 42, "subjectAltName" }, /* 41 */ { 0x12, 0, 43, "issuerAltName" }, /* 42 */ { 0x13, 0, 44, "basicConstraints" }, /* 43 */ { 0x15, 0, 45, "reasonCode" }, /* 44 */ { 0x1F, 0, 46, "crlDistributionPoints" }, /* 45 */ { 0x20, 0, 47, "certificatePolicies" }, /* 46 */ { 0x23, 0, 48, "authorityKeyIdentifier" }, /* 47 */ { 0x25, 0, 49, "extendedKeyUsage" }, /* 48 */ { 0x37, 0, 50, "targetInformation" }, /* 49 */ { 0x38, 0, 0, "noRevAvail" }, /* 50 */ { 0x2A, 1, 80, "" }, /* 51 */ { 0x86, 1, 0, "" }, /* 52 */ { 0x48, 1, 0, "" }, /* 53 */ { 0x86, 1, 0, "" }, /* 54 */ { 0xF7, 1, 0, "" }, /* 55 */ { 0x0D, 1, 0, "RSADSI" }, /* 56 */ { 0x01, 1, 77, "PKCS" }, /* 57 */ { 0x01, 1, 67, "PKCS-1" }, /* 58 */ { 0x01, 0, 60, "rsaEncryption" }, /* 59 */ { 0x02, 0, 61, "md2WithRSAEncryption" }, /* 60 */ { 0x04, 0, 62, "md5WithRSAEncryption" }, /* 61 */ { 0x05, 0, 63, "sha-1WithRSAEncryption" }, /* 62 */ { 0x0B, 0, 64, "sha256WithRSAEncryption" }, /* 63 */ { 0x0C, 0, 65, "sha384WithRSAEncryption" }, /* 64 */ { 0x0D, 0, 66, "sha512WithRSAEncryption" }, /* 65 */ { 0x0E, 0, 0, "sha224WithRSAEncryption" }, /* 66 */ { 0x07, 1, 74, "PKCS-7" }, /* 67 */ { 0x01, 0, 69, "data" }, /* 68 */ { 0x02, 0, 70, "signedData" }, /* 69 */ { 0x03, 0, 71, "envelopedData" }, /* 70 */ { 0x04, 0, 72, "signedAndEnvelopedData" }, /* 71 */ { 0x05, 0, 73, "digestedData" }, /* 72 */ { 0x06, 0, 0, "encryptedData" }, /* 73 */ { 0x09, 1, 0, "PKCS-9" }, /* 74 */ { 0x01, 0, 76, "E" }, /* 75 */ { 0x02, 0, 0, "unstructuredName" }, /* 76 */ { 0x02, 1, 0, "digestAlgorithm" }, /* 77 */ { 0x02, 0, 79, "md2" }, /* 78 */ { 0x05, 0, 0, "md5" }, /* 79 */ { 0x2B, 1, 133, "" }, /* 80 */ { 0x06, 1, 121, "dod" }, /* 81 */ { 0x01, 1, 0, "internet" }, /* 82 */ { 0x04, 1, 92, "private" }, /* 83 */ { 0x01, 1, 0, "enterprise" }, /* 84 */ { 0x89, 1, 0, "" }, /* 85 */ { 0x31, 1, 0, "" }, /* 86 */ { 0x01, 1, 0, "" }, /* 87 */ { 0x01, 1, 0, "" }, /* 88 */ { 0x02, 1, 0, "" }, /* 89 */ { 0x02, 1, 0, "" }, /* 90 */ { 0x4B, 0, 0, "TCGID" }, /* 91 */ { 0x05, 1, 0, "security" }, /* 92 */ { 0x05, 1, 0, "mechanisms" }, /* 93 */ { 0x07, 1, 0, "id-pkix" }, /* 94 */ { 0x01, 1, 97, "id-pe" }, /* 95 */ { 0x01, 0, 0, "authorityInfoAccess" }, /* 96 */ { 0x03, 1, 107, "id-kp" }, /* 97 */ { 0x01, 0, 99, "serverAuth" }, /* 98 */ { 0x02, 0, 100, "clientAuth" }, /* 99 */ { 0x03, 0, 101, "codeSigning" }, /* 100 */ { 0x04, 0, 102, "emailProtection" }, /* 101 */ { 0x05, 0, 103, "ipsecEndSystem" }, /* 102 */ { 0x06, 0, 104, "ipsecTunnel" }, /* 103 */ { 0x07, 0, 105, "ipsecUser" }, /* 104 */ { 0x08, 0, 106, "timeStamping" }, /* 105 */ { 0x09, 0, 0, "ocspSigning" }, /* 106 */ { 0x0A, 1, 112, "id-aca" }, /* 107 */ { 0x01, 0, 109, "authenticationInfo" }, /* 108 */ { 0x02, 0, 110, "accessIdentity" }, /* 109 */ { 0x03, 0, 111, "chargingIdentity" }, /* 110 */ { 0x04, 0, 0, "group" }, /* 111 */ { 0x30, 1, 0, "id-ad" }, /* 112 */ { 0x01, 1, 0, "ocsp" }, /* 113 */ { 0x01, 0, 115, "basic" }, /* 114 */ { 0x02, 0, 116, "nonce" }, /* 115 */ { 0x03, 0, 117, "crl" }, /* 116 */ { 0x04, 0, 118, "response" }, /* 117 */ { 0x05, 0, 119, "noCheck" }, /* 118 */ { 0x06, 0, 120, "archiveCutoff" }, /* 119 */ { 0x07, 0, 0, "serviceLocator" }, /* 120 */ { 0x0E, 1, 126, "oiw" }, /* 121 */ { 0x03, 1, 0, "secsig" }, /* 122 */ { 0x02, 1, 0, "algorithms" }, /* 123 */ { 0x1A, 0, 125, "sha-1" }, /* 124 */ { 0x1D, 0, 0, "sha-1WithRSASignature" }, /* 125 */ { 0x24, 1, 0, "TeleTrusT" }, /* 126 */ { 0x03, 1, 0, "algorithm" }, /* 127 */ { 0x03, 1, 0, "signatureAlgorithm" }, /* 128 */ { 0x01, 1, 0, "rsaSignature" }, /* 129 */ { 0x02, 0, 131, "rsaSigWithripemd160" }, /* 130 */ { 0x03, 0, 132, "rsaSigWithripemd128" }, /* 131 */ { 0x04, 0, 0, "rsaSigWithripemd256" }, /* 132 */ { 0x60, 1, 0, "" }, /* 133 */ { 0x86, 1, 0, "" }, /* 134 */ { 0x48, 1, 0, "" }, /* 135 */ { 0x01, 1, 0, "organization" }, /* 136 */ { 0x65, 1, 144, "gov" }, /* 137 */ { 0x03, 1, 0, "csor" }, /* 138 */ { 0x04, 1, 0, "nistalgorithm" }, /* 139 */ { 0x02, 1, 0, "hashalgs" }, /* 140 */ { 0x01, 0, 142, "id-SHA-256" }, /* 141 */ { 0x02, 0, 143, "id-SHA-384" }, /* 142 */ { 0x03, 0, 0, "id-SHA-512" }, /* 143 */ { 0x86, 1, 0, "" }, /* 144 */ { 0xf8, 1, 0, "" }, /* 145 */ { 0x42, 1, 0, "" }, /* 146 */ { 0x01, 1, 0, "" }, /* 147 */ { 0x01, 0, 149, "nsCertType" }, /* 148 */ { 0x03, 0, 150, "nsRevocationUrl" }, /* 149 */ { 0x0d, 0, 0, "nsComment" } /* 150 */ }; libreswan-3.32/lib/libswan/oid.pl000066400000000000000000000066121365625662500167710ustar00rootroot00000000000000#!/usr/bin/perl # # Generates oid.h and oid.c out of oid.txt # # Copyright (C) 2003-2004 Andreas Steffen, Zuercher Hochschule Winterthur # Copyright (C) 2014 Tuomo Soini # Copyright (C) 2014 D. Hugh Redelmeier # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # $fswancopy="Copyright (C) 2003-2004 Andreas Steffen, Zuercher Hochschule Winterthur"; $copyright="Copyright (C) 2014 Tuomo Soini "; $automatic="This file has been generated by the script lib/libswan/oid.pl"; $warning="Do not edit manually!"; print "oid.pl generating ../../include/oid.h and oid.c\n"; # Generate oid.h open(OID_H, ">../../include/oid.h") or die "could not open '../../include/oid.h': $!"; print OID_H "/*\n", " * Object identifiers (OIDs) used by Libreswan\n", " *\n", " * ", $fswancopy, "\n", " * ", $copyright, "\n", " *\n", " * ", $automatic, "\n", " * ", $warning, "\n", " */\n\n", "typedef struct {\n", "\tunsigned char octet;\n", "\tunsigned char down;\t/* bool */\n", "\tunsigned short next;\n", "\tconst char *name;\n", "} oid_t;\n", "\n", "extern const oid_t oid_names[];\n", "\n", "#define OID_UNKNOWN\t\t\t(-1)\n"; # parse oid.txt open(SRC, ") { next if ($line =~ m/^\h*$/); # ignore empty line next if ($line =~ m/^#/); # ignore comment line $line =~ m/^( *?)(0x[0-9a-fA-F]{2})\s+(".*?")[ \t]*?([\w_]*?)\Z/ or die "malformed line: $line"; @order[$counter] = length($1); @octet[$counter] = $2; @name[$counter] = $3; if (length($1) > $max_order) { $max_order = length($1); } if (length($3) > $max_name) { $max_name = length($3); } if (length($4) > 0) { printf OID_H "#define %s%s%d\n", $4, "\t" x ((39-length($4))/8), $counter; } $counter++; } close SRC; close OID_H; # Generate oid.c open(OID_C, ">oid.c") or die "could not open 'oid.c': $!"; print OID_C "/*\n", " * List of some useful object identifiers (OIDs)\n", " *\n", " * ", $fswancopy, "\n", " * ", $copyright, "\n", " *\n", " * ", $automatic, "\n", " * ", $warning, "\n", " */\n", "#include \"oid.h\"\n", "\n", "const oid_t oid_names[] = {\n", "\t/* octet, down, next, name */\n"; for ($c = 0; $c < $counter; $c++) { $next = 0; for ($d = $c+1; $d < $counter && @order[$d] >= @order[$c]; $d++) { if (@order[$d] == @order[$c]) { @next[$c] = $d; last; } } printf OID_C "\t{ %s%s,%s%d, %3d, %s%s }%s /* %3d */\n" ,' ' x @order[$c] , @octet[$c] , ' ' x (1 + $max_order - @order[$c]) , @order[$c+1] > @order[$c] , @next[$c] , @name[$c] , ' ' x ($max_name - length(@name[$c])) , $c != $counter-1 ? "," : " " , $c; } print OID_C "};\n" ; close OID_C; libreswan-3.32/lib/libswan/oid.txt000066400000000000000000000153431365625662500171760ustar00rootroot00000000000000# Copyright (C) 2003-2004 Andreas Steffen, Zuercher Hochschule Winterthur 0x02 "ITU-T Administration" 0x82 "" 0x06 "Germany ITU-T member" 0x01 "Deutsche Telekom AG" 0x0A "" 0x07 "" 0x14 "ND" 0x09 "data" 0x92 "" 0x26 "" 0x89 "" 0x93 "" 0xF2 "" 0x2C "" 0x64 "pilot" 0x01 "pilotAttributeType" 0x01 "UID" 0x19 "DC" 0x55 "X.500" 0x04 "X.509" 0x03 "CN" 0x04 "S" 0x05 "SN" 0x06 "C" 0x07 "L" 0x08 "ST" 0x0A "O" 0x0B "OU" 0x0C "T" 0x0D "D" 0x24 "userCertificate" 0x29 "N" 0x2A "G" 0x2B "I" 0x2D "ID" 0x48 "role" OID_ROLE 0x1d "id-ce" 0x09 "subjectDirectoryAttrs" 0x0E "subjectKeyIdentifier" OID_SUBJECT_KEY_ID 0x0F "keyUsage" 0x10 "privateKeyUsagePeriod" 0x11 "subjectAltName" OID_SUBJECT_ALT_NAME 0x12 "issuerAltName" 0x13 "basicConstraints" OID_BASIC_CONSTRAINTS 0x15 "reasonCode" 0x1F "crlDistributionPoints" OID_CRL_DISTRIBUTION_POINTS 0x20 "certificatePolicies" 0x23 "authorityKeyIdentifier" OID_AUTHORITY_KEY_ID 0x25 "extendedKeyUsage" OID_EXTENDED_KEY_USAGE 0x37 "targetInformation" OID_TARGET_INFORMATION 0x38 "noRevAvail" OID_NO_REV_AVAIL 0x2A "" 0x86 "" 0x48 "" 0x86 "" 0xF7 "" 0x0D "RSADSI" 0x01 "PKCS" 0x01 "PKCS-1" 0x01 "rsaEncryption" OID_RSA_ENCRYPTION 0x02 "md2WithRSAEncryption" OID_MD2_WITH_RSA 0x04 "md5WithRSAEncryption" OID_MD5_WITH_RSA 0x05 "sha-1WithRSAEncryption" OID_SHA1_WITH_RSA 0x0B "sha256WithRSAEncryption" OID_SHA256_WITH_RSA 0x0C "sha384WithRSAEncryption" OID_SHA384_WITH_RSA 0x0D "sha512WithRSAEncryption" OID_SHA512_WITH_RSA 0x0E "sha224WithRSAEncryption" OID_SHA224_WITH_RSA 0x07 "PKCS-7" 0x01 "data" OID_PKCS7_DATA 0x02 "signedData" OID_PKCS7_SIGNED_DATA 0x03 "envelopedData" 0x04 "signedAndEnvelopedData" 0x05 "digestedData" 0x06 "encryptedData" 0x09 "PKCS-9" 0x01 "E" OID_PKCS9_EMAIL 0x02 "unstructuredName" 0x02 "digestAlgorithm" 0x02 "md2" OID_MD2 0x05 "md5" OID_MD5 0x2B "" 0x06 "dod" 0x01 "internet" 0x04 "private" 0x01 "enterprise" 0x89 "" 0x31 "" 0x01 "" 0x01 "" 0x02 "" 0x02 "" 0x4B "TCGID" 0x05 "security" 0x05 "mechanisms" 0x07 "id-pkix" 0x01 "id-pe" 0x01 "authorityInfoAccess" OID_AUTHORITY_INFO_ACCESS 0x03 "id-kp" 0x01 "serverAuth" 0x02 "clientAuth" 0x03 "codeSigning" 0x04 "emailProtection" 0x05 "ipsecEndSystem" 0x06 "ipsecTunnel" 0x07 "ipsecUser" 0x08 "timeStamping" 0x09 "ocspSigning" OID_OCSP_SIGNING 0x0A "id-aca" 0x01 "authenticationInfo" OID_AUTHENTICATION_INFO 0x02 "accessIdentity" OID_ACCESS_IDENTITY 0x03 "chargingIdentity" OID_CHARGING_IDENTITY 0x04 "group" OID_GROUP 0x30 "id-ad" 0x01 "ocsp" OID_OCSP 0x01 "basic" OID_BASIC 0x02 "nonce" OID_NONCE 0x03 "crl" OID_CRL 0x04 "response" OID_RESPONSE 0x05 "noCheck" OID_NO_CHECK 0x06 "archiveCutoff" OID_ARCHIVE_CUTOFF 0x07 "serviceLocator" OID_SERVICE_LOCATOR 0x0E "oiw" 0x03 "secsig" 0x02 "algorithms" 0x1A "sha-1" OID_SHA1 0x1D "sha-1WithRSASignature" OID_SHA1_WITH_RSA_OIW 0x24 "TeleTrusT" 0x03 "algorithm" 0x03 "signatureAlgorithm" 0x01 "rsaSignature" 0x02 "rsaSigWithripemd160" 0x03 "rsaSigWithripemd128" 0x04 "rsaSigWithripemd256" 0x60 "" 0x86 "" 0x48 "" 0x01 "organization" 0x65 "gov" 0x03 "csor" 0x04 "nistalgorithm" 0x02 "hashalgs" 0x01 "id-SHA-256" OID_SHA256 0x02 "id-SHA-384" OID_SHA384 0x03 "id-SHA-512" OID_SHA512 0x86 "" 0xf8 "" 0x42 "" 0x01 "" 0x01 "nsCertType" 0x03 "nsRevocationUrl" 0x0d "nsComment" libreswan-3.32/lib/libswan/pfkey_error.c000066400000000000000000000051531365625662500203530ustar00rootroot00000000000000/* * open a pfkey socket or dump a reason why it failed. * * Copyright (C) 2006 Michael Richardson * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. */ #include #include #include #include #include #include #include "pfkey_help.h" extern char *progname; void pfkey_write_error(int writeerror, int err) { fprintf(stderr, "%s: pfkey write failed, returning %d with errno=%d.\n", progname, writeerror, err); switch (err) { case EACCES: fprintf(stderr, "access denied. "); if (getuid() == 0) fprintf(stderr, "Check permissions. Should be 600.\n"); else fprintf(stderr, "You must be root to open this file.\n"); break; #ifdef EUNATCH case EUNATCH: fprintf(stderr, "Netlink not enabled OR KLIPS not loaded.\n"); break; #endif case EBUSY: fprintf(stderr, "KLIPS is busy. Most likely a serious internal error occurred in a previous command. Please report as much detail as possible to development team.\n"); break; case EINVAL: fprintf(stderr, "Invalid argument, check kernel log messages for specifics.\n"); break; case ENODEV: fprintf(stderr, "KLIPS not loaded or enabled.\n"); fprintf(stderr, "No device?!?\n"); break; case ENOBUFS: fprintf(stderr, "No kernel memory to allocate SA.\n"); break; case ESOCKTNOSUPPORT: fprintf(stderr, "Algorithm support not available in the kernel. Please compile in support.\n"); break; case EEXIST: fprintf(stderr, "SA already in use. Delete old one first.\n"); break; case ENOENT: fprintf(stderr, "device does not exist. See Libreswan installation procedure.\n"); break; case ENXIO: fprintf(stderr, "SA does not exist. Cannot delete.\n"); break; case ENOSPC: fprintf(stderr, "no room in kernel SAref table. Cannot process request.\n"); break; case ESPIPE: fprintf(stderr, "kernel SAref table internal error. Cannot process request.\n"); break; default: fprintf(stderr, "Unknown socket write error %d. Please report as much detail as possible to development team.\n", errno); } exit(1); } libreswan-3.32/lib/libswan/pfkey_sock.c000066400000000000000000000051741365625662500201640ustar00rootroot00000000000000/* * open a pfkey socket or dump a reason why it failed. * * Copyright (C) 2006 Michael Richardson * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. */ #include #include #include #include #include #include #include "socketwrapper.h" #include "pfkey_help.h" extern char *progname; int pfkey_open_sock_with_error(void) { int pfkey_sock = safe_socket(PF_KEY, SOCK_RAW, PF_KEY_V2); if (pfkey_sock < 0) { fprintf(stderr, "%s: Trouble opening PF_KEY family socket with error: ", progname); switch (errno) { case ENOENT: fprintf(stderr, "device does not exist. See Libreswan installation procedure.\n"); break; case EACCES: fprintf(stderr, "access denied. "); if (getuid() == 0) fprintf(stderr, "Check permissions. Should be 600.\n"); else fprintf(stderr, "You must be root to open this file.\n"); break; #ifdef EUNATCH case EUNATCH: fprintf(stderr, "Netlink not enabled OR KLIPS not loaded.\n"); break; #endif case ENODEV: fprintf(stderr, "KLIPS not loaded or enabled.\n"); break; case EBUSY: fprintf(stderr, "KLIPS is busy. Most likely a serious internal error occurred in a previous command. Please report as much detail as possible to development team.\n"); break; case EINVAL: fprintf(stderr, "Invalid argument, KLIPS not loaded or check kernel log messages for specifics.\n"); break; case ENOBUFS: fprintf(stderr, "No kernel memory to allocate SA.\n"); break; case ESOCKTNOSUPPORT: fprintf(stderr, "Algorithm support not available in the kernel. Please compile in support.\n"); break; case EEXIST: fprintf(stderr, "SA already in use. Delete old one first.\n"); break; case ENXIO: fprintf(stderr, "SA does not exist. Cannot delete.\n"); break; case EAFNOSUPPORT: fprintf(stderr, "KLIPS not loaded or enabled.\n"); break; default: fprintf(stderr, "Unknown file open error %d. Please report as much detail as possible to development team.\n", errno); } exit(1); } return pfkey_sock; } libreswan-3.32/lib/libswan/pfkey_v2_build.c000066400000000000000000001136121365625662500207300ustar00rootroot00000000000000/* * RFC2367 PF_KEYv2 Key management API message parser * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs. * Copyright (C) 2012 Paul Wouters * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ /* * Template from klips/net/ipsec/ipsec/ipsec_parser.c. */ /* * Some ugly stuff to allow consistent debugging code for use in the * kernel and in user space */ #if defined(__KERNEL__) && (defined(linux) || defined(__linux__)) # include /* for printk */ # include "libreswan/ipsec_kversion.h" /* for malloc switch */ # include /* kmalloc() */ # include /* error codes */ # include /* size_t */ # include /* mark_bh */ # include /* struct device, and other headers */ # include /* eth_type_trans */ # include /* struct iphdr */ # if defined(CONFIG_KLIPS_IPV6) # include /* struct ipv6hdr */ # endif /* if defined(CONFIG_KLIPS_IPV6) */ # define MALLOC(size) kmalloc(size, GFP_ATOMIC) # define FREE(obj) kfree(obj) # include #else /* __KERNEL__ */ # include # include # include # include # include # include /* memset */ # include #endif /* __KERNEL__ */ #include #include #ifdef __KERNEL__ #include "libreswan/radij.h" /* rd_nodes */ #include "libreswan/ipsec_encap.h" /* sockaddr_encap */ #endif /* __KERNEL__ */ #include "libreswan/ipsec_sa.h" /* IPSEC_SAREF_NULL, IPSEC_SA_REF_TABLE_IDX_WIDTH */ #include "libreswan/pfkey_debug.h" #include "ip_address.h" /* for ADDRTOT_BUF */ #define SENDERR(_x) { error = -(_x); goto errlab; } void pfkey_extensions_init(struct sadb_ext *extensions[K_SADB_EXT_MAX + 1]) { int i; for (i = 0; i != K_SADB_EXT_MAX + 1; i++) extensions[i] = NULL; } void pfkey_extensions_free(struct sadb_ext *extensions[K_SADB_EXT_MAX + 1]) { int i; if (!extensions) return; if (extensions[0]) { DEBUGGING(PF_KEY_DEBUG_BUILD, "%s:Free extension %d (%zu)\n", "pfkey_extensions_free", 0, sizeof(struct sadb_msg)); memset(extensions[0], 0, sizeof(struct sadb_msg)); FREE(extensions[0]); extensions[0] = NULL; } for (i = 1; i != K_SADB_EXT_MAX + 1; i++) { if (extensions[i]) { DEBUGGING(PF_KEY_DEBUG_BUILD, "%s:Free extension %d (%zu)\n", "pfkey_extensions_free", i, extensions[i]->sadb_ext_len * IPSEC_PFKEYv2_ALIGN); memset(extensions[i], 0, extensions[i]->sadb_ext_len * IPSEC_PFKEYv2_ALIGN); FREE(extensions[i]); extensions[i] = NULL; } } } void pfkey_msg_free(struct sadb_msg **pfkey_msg) { if (*pfkey_msg) { memset(*pfkey_msg, 0, (*pfkey_msg)->sadb_msg_len * IPSEC_PFKEYv2_ALIGN); FREE(*pfkey_msg); *pfkey_msg = NULL; } } /* Default extension builders taken from the KLIPS code */ int pfkey_msg_hdr_build(struct sadb_ext **pfkey_ext, uint8_t msg_type, uint8_t satype, uint8_t msg_errno, uint32_t seq, uint32_t pid) { int error = 0; struct sadb_msg *pfkey_msg = (struct sadb_msg *)*pfkey_ext; DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_msg_hdr_build:\n"); DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_msg_hdr_build: " "on_entry &pfkey_ext=0p%p pfkey_ext=0p%p *pfkey_ext=0p%p.\n", &pfkey_ext, pfkey_ext, *pfkey_ext); /* sanity checks... */ if (pfkey_msg) { ERROR("pfkey_msg_hdr_build: " "why is pfkey_msg already pointing to something?\n"); SENDERR(EINVAL); } if (!msg_type) { ERROR("pfkey_msg_hdr_build: " "msg type not set, must be non-zero..\n"); SENDERR(EINVAL); } if (msg_type > K_SADB_MAX) { ERROR("pfkey_msg_hdr_build: " "msg type too large:%d.\n", msg_type); SENDERR(EINVAL); } if (satype > K_SADB_SATYPE_MAX) { ERROR("pfkey_msg_hdr_build: " "satype %d > max %d\n", satype, SADB_SATYPE_MAX); SENDERR(EINVAL); } pfkey_msg = (struct sadb_msg*)MALLOC(sizeof(struct sadb_msg)); *pfkey_ext = (struct sadb_ext*)pfkey_msg; if (pfkey_msg == NULL) { ERROR("pfkey_msg_hdr_build: " "memory allocation failed\n"); SENDERR(ENOMEM); } memset(pfkey_msg, 0, sizeof(struct sadb_msg)); pfkey_msg->sadb_msg_len = sizeof(struct sadb_msg) / IPSEC_PFKEYv2_ALIGN; pfkey_msg->sadb_msg_type = msg_type; pfkey_msg->sadb_msg_satype = satype; pfkey_msg->sadb_msg_version = PF_KEY_V2; pfkey_msg->sadb_msg_errno = msg_errno; pfkey_msg->sadb_msg_reserved = 0; pfkey_msg->sadb_msg_seq = seq; pfkey_msg->sadb_msg_pid = pid; DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_msg_hdr_build: " "on_exit &pfkey_ext=0p%p pfkey_ext=0p%p *pfkey_ext=0p%p.\n", &pfkey_ext, pfkey_ext, *pfkey_ext); errlab: return error; } int pfkey_sa_builds(struct sadb_ext **pfkey_ext, struct sadb_builds sab) { int error = 0; struct k_sadb_sa *pfkey_sa = (struct k_sadb_sa *)*pfkey_ext; DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_sa_build: " "spi=%08x replay=%d sa_state=%d auth=%d encrypt=%d flags=%d\n", ntohl(sab.sa_base.sadb_sa_spi), /* in network order */ sab.sa_base.sadb_sa_replay, sab.sa_base.sadb_sa_state, sab.sa_base.sadb_sa_auth, sab.sa_base.sadb_sa_encrypt, sab.sa_base.sadb_sa_flags); /* sanity checks... */ if (pfkey_sa) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_sa_build: " "why is pfkey_sa already pointing to something?\n"); SENDERR(EINVAL); } if (sab.sa_base.sadb_sa_exttype != SADB_EXT_SA && sab.sa_base.sadb_sa_exttype != K_SADB_X_EXT_SA2) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_sa_build: " "invalid exttype=%d.\n", sab.sa_base.sadb_sa_exttype); SENDERR(EINVAL); } if (sab.sa_base.sadb_sa_replay > 64) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_sa_build: " "replay window size: %d -- must be 0 <= size <= 64\n", sab.sa_base.sadb_sa_replay); SENDERR(EINVAL); } #if K_SADB_AALG_MAX < 255 if (sab.sa_base.sadb_sa_auth > K_SADB_AALG_MAX) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_sa_build: " "auth=%d > K_SADB_AALG_MAX=%d.\n", sab.sa_base.sadb_sa_auth, K_SADB_AALG_MAX); SENDERR(EINVAL); } #endif #if K_SADB_EALG_MAX < 255 if (sab.sa_base.sadb_sa_encrypt > K_SADB_EALG_MAX) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_sa_build: " "encrypt=%d > K_SADB_EALG_MAX=%d.\n", sab.sa_base.sadb_sa_encrypt, K_SADB_EALG_MAX); SENDERR(EINVAL); } #endif if (sab.sa_base.sadb_sa_state > K_SADB_SASTATE_MAX) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_sa_build: " "sa_state=%d exceeds MAX=%d.\n", sab.sa_base.sadb_sa_state, K_SADB_SASTATE_MAX); SENDERR(EINVAL); } if (sab.sa_base.sadb_sa_state == K_SADB_SASTATE_DEAD) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_sa_build: " "sa_state=%d is DEAD=%d is not allowed.\n", sab.sa_base.sadb_sa_state, K_SADB_SASTATE_DEAD); SENDERR(EINVAL); } if (IPSEC_SAREF_NULL != sab.sa_base.sadb_x_sa_ref && sab.sa_base.sadb_x_sa_ref >= (1 << IPSEC_SA_REF_TABLE_IDX_WIDTH)) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_sa_build: " "SAref=%d must be (SAref == IPSEC_SAREF_NULL(%d) || SAref < IPSEC_SA_REF_TABLE_NUM_ENTRIES(%d)).\n", sab.sa_base.sadb_x_sa_ref, IPSEC_SAREF_NULL, IPSEC_SA_REF_TABLE_NUM_ENTRIES); SENDERR(EINVAL); } pfkey_sa = (struct k_sadb_sa*)MALLOC(sizeof(struct k_sadb_sa)); *pfkey_ext = (struct sadb_ext*)pfkey_sa; if (pfkey_sa == NULL) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_sa_build: " "memory allocation failed\n"); SENDERR(ENOMEM); } memset(pfkey_sa, 0, sizeof(struct k_sadb_sa)); *pfkey_sa = sab.sa_base; pfkey_sa->sadb_sa_len = sizeof(*pfkey_sa) / IPSEC_PFKEYv2_ALIGN; errlab: return error; } int pfkey_sa_build(struct sadb_ext **pfkey_ext, uint16_t exttype, uint32_t spi, uint8_t replay_window, uint8_t sa_state, uint8_t auth, uint8_t encrypt, uint32_t flags) { struct sadb_builds sab; memset(&sab, 0, sizeof(sab)); sab.sa_base.sadb_sa_exttype = exttype; sab.sa_base.sadb_sa_spi = spi; sab.sa_base.sadb_sa_replay = replay_window; sab.sa_base.sadb_sa_state = sa_state; sab.sa_base.sadb_sa_auth = auth; sab.sa_base.sadb_sa_encrypt = encrypt; sab.sa_base.sadb_sa_flags = flags; sab.sa_base.sadb_x_sa_ref = IPSEC_SAREF_NULL; return pfkey_sa_builds(pfkey_ext, sab); } int pfkey_lifetime_build(struct sadb_ext ** pfkey_ext, uint16_t exttype, uint32_t allocations, uint64_t bytes, uint64_t addtime, uint64_t usetime, uint32_t packets UNUSED) { int error = 0; struct sadb_lifetime *pfkey_lifetime = (struct sadb_lifetime *)*pfkey_ext; DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_lifetime_build:\n"); /* sanity checks... */ if (pfkey_lifetime) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_lifetime_build: " "why is pfkey_lifetime already pointing to something?\n"); SENDERR(EINVAL); } if (exttype != SADB_EXT_LIFETIME_CURRENT && exttype != SADB_EXT_LIFETIME_HARD && exttype != SADB_EXT_LIFETIME_SOFT) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_lifetime_build: " "invalid exttype=%d.\n", exttype); SENDERR(EINVAL); } pfkey_lifetime = (struct sadb_lifetime*)MALLOC(sizeof(struct sadb_lifetime)); *pfkey_ext = (struct sadb_ext*) pfkey_lifetime; if (pfkey_lifetime == NULL) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_lifetime_build: " "memory allocation failed\n"); SENDERR(ENOMEM); } memset(pfkey_lifetime, 0, sizeof(struct sadb_lifetime)); pfkey_lifetime->sadb_lifetime_len = sizeof(struct sadb_lifetime) / IPSEC_PFKEYv2_ALIGN; pfkey_lifetime->sadb_lifetime_exttype = exttype; pfkey_lifetime->sadb_lifetime_allocations = allocations; pfkey_lifetime->sadb_lifetime_bytes = bytes; pfkey_lifetime->sadb_lifetime_addtime = addtime; pfkey_lifetime->sadb_lifetime_usetime = usetime; #ifdef NOT_YET /* XXX it is defined in struct sadb_lifetime, but not found?? */ pfkey_lifetime->sadb_x_lifetime_packets = packets; #endif errlab: return error; } int pfkey_address_build(struct sadb_ext **pfkey_ext, uint16_t exttype, uint8_t proto, uint8_t prefixlen, struct sockaddr *address) { int error = 0; int saddr_len = 0; int len; char ipaddr_txt[ADDRTOT_BUF + 6 /*extra for port number*/]; struct sadb_address *pfkey_address = (struct sadb_address *)*pfkey_ext; DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_address_build: " "exttype=%d proto=%d prefixlen=%d\n", exttype, proto, prefixlen); /* sanity checks... */ if (pfkey_address) { ERROR("pfkey_address_build: " "why is pfkey_address already pointing to something?\n"); SENDERR(EINVAL); } if (!address) { ERROR("pfkey_address_build: " "address is NULL\n"); SENDERR(EINVAL); } switch (exttype) { case SADB_EXT_ADDRESS_SRC: case SADB_EXT_ADDRESS_DST: case SADB_EXT_ADDRESS_PROXY: case K_SADB_X_EXT_ADDRESS_DST2: case K_SADB_X_EXT_ADDRESS_SRC_FLOW: case K_SADB_X_EXT_ADDRESS_DST_FLOW: case K_SADB_X_EXT_ADDRESS_SRC_MASK: case K_SADB_X_EXT_ADDRESS_DST_MASK: case K_SADB_X_EXT_NAT_T_OA: break; default: ERROR("pfkey_address_build: " "unrecognised ext_type=%d.\n", exttype); SENDERR(EINVAL); } switch (address->sa_family) { case AF_INET: DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_address_build: " "found address family AF_INET.\n"); saddr_len = sizeof(struct sockaddr_in); len = sin_addrtot(address, 0, ipaddr_txt, sizeof(ipaddr_txt)); if (len > 0 && len < (int)sizeof(ipaddr_txt)) { snprintf(&ipaddr_txt[len - 1], sizeof(ipaddr_txt) - len, ":%d", ntohs(((struct sockaddr_in*)address)-> sin_port)); } break; case AF_INET6: DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_address_build: " "found address family AF_INET6.\n"); saddr_len = sizeof(struct sockaddr_in6); /* IPv6 convention with a port is [addr]:port */ len = sin_addrtot(address, 0, &ipaddr_txt[1], sizeof(ipaddr_txt) - 2); if (len > 0) { ipaddr_txt[0] = '['; snprintf(&ipaddr_txt[len], sizeof(ipaddr_txt) - len, "]:%d", ntohs(((struct sockaddr_in6*)address)-> sin6_port)); } break; default: ERROR("pfkey_address_build: " "address->sa_family=%d not supported.\n", address->sa_family); SENDERR(EPFNOSUPPORT); } DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_address_build: " "found address=%s.\n", ipaddr_txt); if (prefixlen != 0) { ERROR("pfkey_address_build: " "address prefixes not supported yet.\n"); SENDERR(EAFNOSUPPORT); /* not supported yet */ } /* allocate some memory for the extension */ pfkey_address = (struct sadb_address*) MALLOC(ALIGN_N(sizeof(struct sadb_address) + saddr_len, IPSEC_PFKEYv2_ALIGN)); *pfkey_ext = (struct sadb_ext*)pfkey_address; if (pfkey_address == NULL ) { ERROR("pfkey_lifetime_build: " "memory allocation failed\n"); SENDERR(ENOMEM); } memset(pfkey_address, 0, ALIGN_N(sizeof(struct sadb_address) + saddr_len, IPSEC_PFKEYv2_ALIGN)); pfkey_address->sadb_address_len = DIVUP( sizeof(struct sadb_address) + saddr_len, IPSEC_PFKEYv2_ALIGN); pfkey_address->sadb_address_exttype = exttype; pfkey_address->sadb_address_proto = proto; pfkey_address->sadb_address_prefixlen = prefixlen; pfkey_address->sadb_address_reserved = 0; memcpy((char*)pfkey_address + sizeof(struct sadb_address), address, saddr_len); #if 0 for (i = 0; i < sizeof(struct sockaddr_in) - offsetof(struct sockaddr_in, sin_zero); i++) pfkey_address_s_ska.sin_zero[i] = 0; #endif DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_address_build: " "successful created len: %d.\n", pfkey_address->sadb_address_len); errlab: return error; } int pfkey_key_build(struct sadb_ext **pfkey_ext, uint16_t exttype, uint16_t key_bits, unsigned char * key) { int error = 0; struct sadb_key *pfkey_key = (struct sadb_key *)*pfkey_ext; DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_key_build:\n"); /* sanity checks... */ if (pfkey_key) { ERROR("pfkey_key_build: " "why is pfkey_key already pointing to something?\n"); SENDERR(EINVAL); } if (!key_bits) { ERROR("pfkey_key_build: " "key_bits is zero, it must be non-zero.\n"); SENDERR(EINVAL); } if ( !((exttype == SADB_EXT_KEY_AUTH) || (exttype == SADB_EXT_KEY_ENCRYPT))) { ERROR("pfkey_key_build: " "unsupported extension type=%d.\n", exttype); SENDERR(EINVAL); } pfkey_key = (struct sadb_key*) MALLOC(sizeof(struct sadb_key) + DIVUP(key_bits, 64) * IPSEC_PFKEYv2_ALIGN); *pfkey_ext = (struct sadb_ext*)pfkey_key; if (pfkey_key == NULL) { ERROR("pfkey_key_build: " "memory allocation failed\n"); SENDERR(ENOMEM); } memset(pfkey_key, 0, sizeof(struct sadb_key) + DIVUP(key_bits, 64) * IPSEC_PFKEYv2_ALIGN); pfkey_key->sadb_key_len = DIVUP( sizeof(struct sadb_key) * IPSEC_PFKEYv2_ALIGN + key_bits, 64); pfkey_key->sadb_key_exttype = exttype; pfkey_key->sadb_key_bits = key_bits; pfkey_key->sadb_key_reserved = 0; memcpy((char*)pfkey_key + sizeof(struct sadb_key), key, DIVUP(key_bits, 8)); errlab: return error; } int pfkey_ident_build(struct sadb_ext **pfkey_ext, uint16_t exttype, uint16_t ident_type, uint64_t ident_id, uint8_t ident_len, char *ident_string) { int error = 0; struct sadb_ident *pfkey_ident = (struct sadb_ident *)*pfkey_ext; int data_len = ident_len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident); DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_ident_build:\n"); /* sanity checks... */ if (pfkey_ident) { ERROR("pfkey_ident_build: " "why is pfkey_ident already pointing to something?\n"); SENDERR(EINVAL); } if ( !((exttype == SADB_EXT_IDENTITY_SRC) || (exttype == SADB_EXT_IDENTITY_DST))) { ERROR("pfkey_ident_build: " "unsupported extension type=%d.\n", exttype); SENDERR(EINVAL); } if (ident_type == SADB_IDENTTYPE_RESERVED) { ERROR("pfkey_ident_build: " "ident_type must be non-zero.\n"); SENDERR(EINVAL); } if (ident_type > SADB_IDENTTYPE_MAX) { ERROR("pfkey_ident_build: " "identtype=%d out of range.\n", ident_type); SENDERR(EINVAL); } if (((ident_type == SADB_IDENTTYPE_PREFIX) || (ident_type == SADB_IDENTTYPE_FQDN)) && !ident_string) { ERROR("pfkey_ident_build: " "string required to allocate size of extension.\n"); SENDERR(EINVAL); } #if 0 if ((ident_type == SADB_IDENTTYPE_USERFQDN) ) { } #endif pfkey_ident = (struct sadb_ident*) MALLOC(ident_len * IPSEC_PFKEYv2_ALIGN); *pfkey_ext = (struct sadb_ext*)pfkey_ident; if (pfkey_ident == NULL) { ERROR("pfkey_ident_build: " "memory allocation failed\n"); SENDERR(ENOMEM); } memset(pfkey_ident, 0, ident_len * IPSEC_PFKEYv2_ALIGN); pfkey_ident->sadb_ident_len = ident_len; pfkey_ident->sadb_ident_exttype = exttype; pfkey_ident->sadb_ident_type = ident_type; pfkey_ident->sadb_ident_reserved = 0; pfkey_ident->sadb_ident_id = ident_id; memcpy((char*)pfkey_ident + sizeof(struct sadb_ident), ident_string, data_len); errlab: return error; } #if 0 /* ??? not yet used or working */ int pfkey_sens_build(struct sadb_ext **pfkey_ext, uint32_t dpd, uint8_t sens_level, uint8_t sens_len, uint64_t *sens_bitmap, uint8_t integ_level, uint8_t integ_len, uint64_t *integ_bitmap) { int error = 0; struct sadb_sens *pfkey_sens = (struct sadb_sens *)*pfkey_ext; int i; uint64_t *bitmap; DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_sens_build:\n"); /* sanity checks... */ if (pfkey_sens != NULL) { ERROR("pfkey_sens_build: " "why is pfkey_sens already pointing to something?\n"); SENDERR(EINVAL); } /* * ??? we've just determined that *pfkey_ext == NULL, why are we dereferencing it? * I guess that this is an insanity check. */ DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_sens_build: " "Sorry, I can't build exttype=%d yet.\n", (*pfkey_ext)->sadb_ext_type); SENDERR(EINVAL); /* don't process these yet */ pfkey_sens = (struct sadb_sens*) MALLOC(sizeof(struct sadb_sens) + (sens_len + integ_len) * sizeof(uint64_t)); *pfkey_ext = (struct sadb_ext*)pfkey_sens; if (pfkey_sens == NULL) { ERROR("pfkey_sens_build: " "memory allocation failed\n"); SENDERR(ENOMEM); } memset(pfkey_sens, 0, sizeof(struct sadb_sens) + (sens_len + integ_len) * sizeof(uint64_t)); pfkey_sens->sadb_sens_len = (sizeof(struct sadb_sens) + (sens_len + integ_len) * sizeof(uint64_t)) / IPSEC_PFKEYv2_ALIGN; pfkey_sens->sadb_sens_exttype = SADB_EXT_SENSITIVITY; pfkey_sens->sadb_sens_dpd = dpd; pfkey_sens->sadb_sens_sens_level = sens_level; pfkey_sens->sadb_sens_sens_len = sens_len; pfkey_sens->sadb_sens_integ_level = integ_level; pfkey_sens->sadb_sens_integ_len = integ_len; pfkey_sens->sadb_sens_reserved = 0; bitmap = (uint64_t*)((char*)pfkey_ext + sizeof(struct sadb_sens)); for (i = 0; i < sens_len; i++) { *bitmap = sens_bitmap[i]; bitmap++; } for (i = 0; i < integ_len; i++) { *bitmap = integ_bitmap[i]; bitmap++; } errlab: return error; } #endif int pfkey_prop_build(struct sadb_ext **pfkey_ext, uint8_t replay, unsigned int comb_num, struct sadb_comb *comb) { int error = 0; int i; struct sadb_prop *pfkey_prop = (struct sadb_prop *)*pfkey_ext; struct sadb_comb *combp; DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_prop_build:\n"); /* sanity checks... */ if (pfkey_prop) { ERROR("pfkey_prop_build: " "why is pfkey_prop already pointing to something?\n"); SENDERR(EINVAL); } pfkey_prop = (struct sadb_prop*) MALLOC(sizeof(struct sadb_prop) + comb_num * sizeof(struct sadb_comb)); *pfkey_ext = (struct sadb_ext*)pfkey_prop; if (pfkey_prop == NULL) { ERROR("pfkey_prop_build: " "memory allocation failed\n"); SENDERR(ENOMEM); } memset(pfkey_prop, 0, sizeof(struct sadb_prop) + comb_num * sizeof(struct sadb_comb)); pfkey_prop->sadb_prop_len = (sizeof(struct sadb_prop) + comb_num * sizeof(struct sadb_comb)) / IPSEC_PFKEYv2_ALIGN; pfkey_prop->sadb_prop_exttype = SADB_EXT_PROPOSAL; pfkey_prop->sadb_prop_replay = replay; for (i = 0; i < 3; i++) pfkey_prop->sadb_prop_reserved[i] = 0; combp = (struct sadb_comb*) ((char*)*pfkey_ext + sizeof(struct sadb_prop)); for (i = 0; i < (int)comb_num; i++) { memcpy(combp, &(comb[i]), sizeof(struct sadb_comb)); combp++; } #if 0 uint8_t sadb_comb_auth; uint8_t sadb_comb_encrypt; uint16_t sadb_comb_flags; uint16_t sadb_comb_auth_minbits; uint16_t sadb_comb_auth_maxbits; uint16_t sadb_comb_encrypt_minbits; uint16_t sadb_comb_encrypt_maxbits; uint32_t sadb_comb_reserved; uint32_t sadb_comb_soft_allocations; uint32_t sadb_comb_hard_allocations; uint64_t sadb_comb_soft_bytes; uint64_t sadb_comb_hard_bytes; uint64_t sadb_comb_soft_addtime; uint64_t sadb_comb_hard_addtime; uint64_t sadb_comb_soft_usetime; uint64_t sadb_comb_hard_usetime; uint32_t sadb_comb_soft_packets; uint32_t sadb_comb_hard_packets; #endif errlab: return error; } int pfkey_supported_build(struct sadb_ext **pfkey_ext, uint16_t exttype, unsigned int alg_num, struct sadb_alg *alg) { int error = 0; unsigned int i; struct sadb_supported *pfkey_supported = (struct sadb_supported *)*pfkey_ext; struct sadb_alg *pfkey_alg; /* sanity checks... */ if (pfkey_supported) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_supported_build: " "why is pfkey_supported already pointing to something?\n"); SENDERR(EINVAL); } if ( !((exttype == SADB_EXT_SUPPORTED_AUTH) || (exttype == SADB_EXT_SUPPORTED_ENCRYPT))) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_supported_build: " "unsupported extension type=%d.\n", exttype); SENDERR(EINVAL); } pfkey_supported = (struct sadb_supported*) MALLOC(sizeof(struct sadb_supported) + alg_num * sizeof(struct sadb_alg)); *pfkey_ext = (struct sadb_ext*)pfkey_supported; if (pfkey_supported == NULL) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_supported_build: " "memory allocation failed\n"); SENDERR(ENOMEM); } memset(pfkey_supported, 0, sizeof(struct sadb_supported) + alg_num * sizeof(struct sadb_alg)); pfkey_supported->sadb_supported_len = (sizeof(struct sadb_supported) + alg_num * sizeof(struct sadb_alg)) / IPSEC_PFKEYv2_ALIGN; pfkey_supported->sadb_supported_exttype = exttype; pfkey_supported->sadb_supported_reserved = 0; pfkey_alg = (struct sadb_alg*) ((char*)pfkey_supported + sizeof(struct sadb_supported)); for (i = 0; i < alg_num; i++) { memcpy(pfkey_alg, &(alg[i]), sizeof(struct sadb_alg)); pfkey_alg->sadb_alg_reserved = 0; pfkey_alg++; } #if 0 DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_supported_build: " "Sorry, I can't build exttype=%d yet.\n", (*pfkey_ext)->sadb_ext_type); SENDERR(EINVAL); /* don't process these yet */ uint8_t sadb_alg_id; uint8_t sadb_alg_ivlen; uint16_t sadb_alg_minbits; uint16_t sadb_alg_maxbits; uint16_t sadb_alg_reserved; #endif errlab: return error; } #if 0 static int pfkey_spirange_build(struct sadb_ext **pfkey_ext, uint16_t exttype UNUSED, uint32_t min, /* in network order */ uint32_t max) /* in network order */ { int error = 0; struct sadb_spirange *pfkey_spirange = (struct sadb_spirange *)*pfkey_ext; /* sanity checks... */ if (pfkey_spirange) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_spirange_build: " "why is pfkey_spirange already pointing to something?\n"); SENDERR(EINVAL); } if (ntohl(max) < ntohl(min)) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_spirange_build: " "minspi=%08x must be < maxspi=%08x.\n", ntohl(min), ntohl(max)); SENDERR(EINVAL); } if (ntohl(min) <= 255) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_spirange_build: " "minspi=%08x must be > 255.\n", ntohl(min)); SENDERR(EEXIST); } pfkey_spirange = (struct sadb_spirange*) MALLOC(sizeof(struct sadb_spirange)); *pfkey_ext = (struct sadb_ext*)pfkey_spirange; if (pfkey_spirange == NULL) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_spirange_build: " "memory allocation failed\n"); SENDERR(ENOMEM); } memset(pfkey_spirange, 0, sizeof(struct sadb_spirange)); pfkey_spirange->sadb_spirange_len = sizeof(struct sadb_spirange) / IPSEC_PFKEYv2_ALIGN; pfkey_spirange->sadb_spirange_exttype = SADB_EXT_SPIRANGE; pfkey_spirange->sadb_spirange_min = min; pfkey_spirange->sadb_spirange_max = max; pfkey_spirange->sadb_spirange_reserved = 0; errlab: return error; } static int pfkey_x_kmprivate_build(struct sadb_ext **pfkey_ext) { int error = 0; struct sadb_x_kmprivate *pfkey_x_kmprivate = (struct sadb_x_kmprivate *)*pfkey_ext; /* sanity checks... */ if (pfkey_x_kmprivate) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_x_kmprivate_build: " "why is pfkey_x_kmprivate already pointing to something?\n"); SENDERR(EINVAL); } pfkey_x_kmprivate->sadb_x_kmprivate_reserved = 0; DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_x_kmprivate_build: " "Sorry, I can't build exttype=%d yet.\n", (*pfkey_ext)->sadb_ext_type); SENDERR(EINVAL); /* don't process these yet */ pfkey_x_kmprivate = (struct sadb_x_kmprivate*) MALLOC(sizeof(struct sadb_x_kmprivate)); *pfkey_ext = (struct sadb_ext*)pfkey_x_kmprivate; if (pfkey_x_kmprivate == NULL) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_x_kmprivate_build: " "memory allocation failed\n"); SENDERR(ENOMEM); } memset(pfkey_x_kmprivate, 0, sizeof(struct sadb_x_kmprivate)); pfkey_x_kmprivate->sadb_x_kmprivate_len = sizeof(struct sadb_x_kmprivate) / IPSEC_PFKEYv2_ALIGN; pfkey_x_kmprivate->sadb_x_kmprivate_exttype = K_SADB_X_EXT_KMPRIVATE; pfkey_x_kmprivate->sadb_x_kmprivate_reserved = 0; errlab: return error; } #endif int pfkey_x_satype_build(struct sadb_ext **pfkey_ext, uint8_t satype) { int error = 0; int i; struct sadb_x_satype *pfkey_x_satype = (struct sadb_x_satype *)*pfkey_ext; DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_x_satype_build:\n"); /* sanity checks... */ if (pfkey_x_satype) { ERROR("pfkey_x_satype_build: " "why is pfkey_x_satype already pointing to something?\n"); SENDERR(EINVAL); } if (!satype) { ERROR("pfkey_x_satype_build: " "SA type not set, must be non-zero.\n"); SENDERR(EINVAL); } if (satype > K_SADB_SATYPE_MAX) { ERROR("pfkey_x_satype_build: " "satype %d > max %d\n", satype, K_SADB_SATYPE_MAX); SENDERR(EINVAL); } pfkey_x_satype = (struct sadb_x_satype*) MALLOC(sizeof(struct sadb_x_satype)); *pfkey_ext = (struct sadb_ext*)pfkey_x_satype; if (pfkey_x_satype == NULL) { ERROR("pfkey_x_satype_build: " "memory allocation failed\n"); SENDERR(ENOMEM); } memset(pfkey_x_satype, 0, sizeof(struct sadb_x_satype)); pfkey_x_satype->sadb_x_satype_len = sizeof(struct sadb_x_satype) / IPSEC_PFKEYv2_ALIGN; pfkey_x_satype->sadb_x_satype_exttype = K_SADB_X_EXT_SATYPE2; pfkey_x_satype->sadb_x_satype_satype = satype; for (i = 0; i < 3; i++) pfkey_x_satype->sadb_x_satype_reserved[i] = 0; errlab: return error; } int pfkey_x_debug_build(struct sadb_ext **pfkey_ext, uint32_t tunnel, uint32_t netlink, uint32_t xform, uint32_t eroute, uint32_t spi, uint32_t radij, uint32_t esp, uint32_t ah, uint32_t rcv, uint32_t pfkey, uint32_t ipcomp, uint32_t verbose) { int error = 0; int i; struct sadb_x_debug *pfkey_x_debug = (struct sadb_x_debug *)*pfkey_ext; DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_x_debug_build:\n"); /* sanity checks... */ if (pfkey_x_debug) { ERROR("pfkey_x_debug_build: " "why is pfkey_x_debug already pointing to something?\n"); SENDERR(EINVAL); } DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_x_debug_build: " "tunnel=%x netlink=%x xform=%x eroute=%x spi=%x radij=%x esp=%x ah=%x rcv=%x pfkey=%x ipcomp=%x verbose=%x?\n", tunnel, netlink, xform, eroute, spi, radij, esp, ah, rcv, pfkey, ipcomp, verbose); pfkey_x_debug = (struct sadb_x_debug*) MALLOC(sizeof(struct sadb_x_debug)); *pfkey_ext = (struct sadb_ext*)pfkey_x_debug; if (pfkey_x_debug == NULL) { ERROR("pfkey_x_debug_build: " "memory allocation failed\n"); SENDERR(ENOMEM); } #if 0 memset(pfkey_x_debug, 0, sizeof(struct sadb_x_debug)); #endif pfkey_x_debug->sadb_x_debug_len = sizeof(struct sadb_x_debug) / IPSEC_PFKEYv2_ALIGN; pfkey_x_debug->sadb_x_debug_exttype = K_SADB_X_EXT_DEBUG; pfkey_x_debug->sadb_x_debug_tunnel = tunnel; pfkey_x_debug->sadb_x_debug_netlink = netlink; pfkey_x_debug->sadb_x_debug_xform = xform; pfkey_x_debug->sadb_x_debug_eroute = eroute; pfkey_x_debug->sadb_x_debug_spi = spi; pfkey_x_debug->sadb_x_debug_radij = radij; pfkey_x_debug->sadb_x_debug_esp = esp; pfkey_x_debug->sadb_x_debug_ah = ah; pfkey_x_debug->sadb_x_debug_rcv = rcv; pfkey_x_debug->sadb_x_debug_pfkey = pfkey; pfkey_x_debug->sadb_x_debug_ipcomp = ipcomp; pfkey_x_debug->sadb_x_debug_verbose = verbose; for (i = 0; i < 4; i++) pfkey_x_debug->sadb_x_debug_reserved[i] = 0; errlab: return error; } int pfkey_x_nat_t_type_build(struct sadb_ext **pfkey_ext, uint8_t type) { int error = 0; int i; struct sadb_x_nat_t_type *pfkey_x_nat_t_type = (struct sadb_x_nat_t_type *)*pfkey_ext; DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_x_nat_t_type_build:\n"); /* sanity checks... */ if (pfkey_x_nat_t_type) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_x_nat_t_type_build: " "why is pfkey_x_nat_t_type already pointing to something?\n"); SENDERR(EINVAL); } DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_x_nat_t_type_build: " "type=%d\n", type); pfkey_x_nat_t_type = (struct sadb_x_nat_t_type*) MALLOC(sizeof(struct sadb_x_nat_t_type)); *pfkey_ext = (struct sadb_ext*)pfkey_x_nat_t_type; if (pfkey_x_nat_t_type == NULL) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_x_nat_t_type_build: " "memory allocation failed\n"); SENDERR(ENOMEM); } pfkey_x_nat_t_type->sadb_x_nat_t_type_len = sizeof(struct sadb_x_nat_t_type) / IPSEC_PFKEYv2_ALIGN; pfkey_x_nat_t_type->sadb_x_nat_t_type_exttype = K_SADB_X_EXT_NAT_T_TYPE; pfkey_x_nat_t_type->sadb_x_nat_t_type_type = type; for (i = 0; i < 3; i++) pfkey_x_nat_t_type->sadb_x_nat_t_type_reserved[i] = 0; errlab: return error; } int pfkey_x_nat_t_port_build(struct sadb_ext **pfkey_ext, uint16_t exttype, uint16_t port) { int error = 0; struct sadb_x_nat_t_port *pfkey_x_nat_t_port = (struct sadb_x_nat_t_port *)*pfkey_ext; DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_x_nat_t_port_build:\n"); /* sanity checks... */ if (pfkey_x_nat_t_port) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_x_nat_t_port_build: " "why is pfkey_x_nat_t_port already pointing to something?\n"); SENDERR(EINVAL); } switch (exttype) { case K_SADB_X_EXT_NAT_T_SPORT: case K_SADB_X_EXT_NAT_T_DPORT: break; default: DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_nat_t_port_build: " "unrecognised ext_type=%d.\n", exttype); SENDERR(EINVAL); } DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_x_nat_t_port_build: " "ext=%d, port=%d\n", exttype, port); pfkey_x_nat_t_port = (struct sadb_x_nat_t_port*) MALLOC(sizeof(struct sadb_x_nat_t_port)); *pfkey_ext = (struct sadb_ext*)pfkey_x_nat_t_port; if (pfkey_x_nat_t_port == NULL) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_x_nat_t_port_build: " "memory allocation failed\n"); SENDERR(ENOMEM); } pfkey_x_nat_t_port->sadb_x_nat_t_port_len = sizeof(struct sadb_x_nat_t_port) / IPSEC_PFKEYv2_ALIGN; pfkey_x_nat_t_port->sadb_x_nat_t_port_exttype = exttype; pfkey_x_nat_t_port->sadb_x_nat_t_port_port = port; pfkey_x_nat_t_port->sadb_x_nat_t_port_reserved = 0; errlab: return error; } int pfkey_x_protocol_build(struct sadb_ext **pfkey_ext, uint8_t protocol) { int error = 0; struct sadb_protocol * p = (struct sadb_protocol *)*pfkey_ext; DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_x_protocol_build: protocol=%u\n", protocol); /* sanity checks... */ if (p != 0) { ERROR("pfkey_x_protocol_build: bogus protocol pointer\n"); SENDERR(EINVAL); } if ((p = (struct sadb_protocol*)MALLOC(sizeof(*p))) == 0) { ERROR("pfkey_build: memory allocation failed\n"); SENDERR(ENOMEM); } *pfkey_ext = (struct sadb_ext *)p; p->sadb_protocol_len = sizeof(*p) / IPSEC_PFKEYv2_ALIGN; p->sadb_protocol_exttype = K_SADB_X_EXT_PROTOCOL; p->sadb_protocol_proto = protocol; p->sadb_protocol_flags = 0; p->sadb_protocol_reserved2 = 0; errlab: return error; } int pfkey_outif_build(struct sadb_ext **pfkey_ext, uint16_t outif) { int error = 0; struct sadb_x_plumbif *p; if ((p = (struct sadb_x_plumbif*)MALLOC(sizeof(*p))) == 0) { ERROR("pfkey_build: memory allocation failed\n"); SENDERR(ENOMEM); } *pfkey_ext = (struct sadb_ext *)p; p->sadb_x_outif_len = IPSEC_PFKEYv2_WORDS(sizeof(*p)); p->sadb_x_outif_exttype = K_SADB_X_EXT_PLUMBIF; p->sadb_x_outif_ifnum = outif; errlab: return error; } int pfkey_saref_build(struct sadb_ext **pfkey_ext, IPsecSAref_t in, IPsecSAref_t out) { int error = 0; struct sadb_x_saref *s; /* +4 because sadb_x_saref is not a multiple of 8 bytes */ if ((s = (struct sadb_x_saref*)MALLOC(sizeof(*s) + 4)) == 0) { ERROR("pfkey_build: memory allocation failed\n"); SENDERR(ENOMEM); } *pfkey_ext = (struct sadb_ext *)s; s->sadb_x_saref_len = IPSEC_PFKEYv2_WORDS(sizeof(*s)); s->sadb_x_saref_exttype = K_SADB_X_EXT_SAREF; s->sadb_x_saref_me = in; s->sadb_x_saref_him = out; errlab: return error; } #if defined(I_DONT_THINK_THIS_WILL_BE_USEFUL) && \ I_DONT_THINK_THIS_WILL_BE_USEFUL int(*ext_default_builders[K_SADB_EXT_MAX + 1])(struct sadb_msg*, struct sadb_ext*) = { NULL, /* pfkey_msg_build, */ pfkey_sa_build, pfkey_lifetime_build, pfkey_lifetime_build, pfkey_lifetime_build, pfkey_address_build, pfkey_address_build, pfkey_address_build, pfkey_key_build, pfkey_key_build, pfkey_ident_build, pfkey_ident_build, pfkey_sens_build, pfkey_prop_build, pfkey_supported_build, pfkey_supported_build, pfkey_spirange_build, pfkey_x_kmprivate_build, pfkey_x_satype_build, pfkey_sa_build, pfkey_address_build, pfkey_address_build, pfkey_address_build, pfkey_address_build, pfkey_address_build, pfkey_x_ext_debug_build }; #endif int pfkey_msg_build(struct sadb_msg **pfkey_msg, struct sadb_ext *extensions[], int dir) { int error = 0; unsigned ext; unsigned total_size; struct sadb_ext *pfkey_ext; pfkey_ext_track extensions_seen = 0; #ifndef __KERNEL__ struct sadb_ext *extensions_check[K_SADB_EXT_MAX + 1]; #endif if (!extensions[0]) { ERROR("pfkey_msg_build: " "extensions[0] must be specified (struct sadb_msg).\n"); SENDERR(EINVAL); } /* figure out the total size for all the requested extensions */ total_size = IPSEC_PFKEYv2_WORDS(sizeof(struct sadb_msg)); DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_msg_build: extensions[%d] needs %zu bytes\n", 0, total_size * IPSEC_PFKEYv2_ALIGN); for (ext = 1; ext <= K_SADB_EXT_MAX; ext++) { if (extensions[ext]) { total_size += (extensions[ext])->sadb_ext_len; DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_msg_build: extensions[%d] needs %zu bytes\n", ext, (extensions[ext])->sadb_ext_len * IPSEC_PFKEYv2_ALIGN); } } /* allocate that much space */ *pfkey_msg = (struct sadb_msg*)MALLOC(total_size * IPSEC_PFKEYv2_ALIGN); if (*pfkey_msg == NULL) { ERROR("pfkey_msg_build: " "memory allocation failed\n"); SENDERR(ENOMEM); } DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_msg_build: " "pfkey_msg=0p%p allocated %zu bytes, &(extensions[0])=0p%p\n", *pfkey_msg, total_size * IPSEC_PFKEYv2_ALIGN, &(extensions[0])); memcpy(*pfkey_msg, extensions[0], sizeof(struct sadb_msg)); (*pfkey_msg)->sadb_msg_len = total_size; (*pfkey_msg)->sadb_msg_reserved = 0; extensions_seen = 1; /* * point pfkey_ext to immediately after the space for the header, * i.e. at the first extension location. */ pfkey_ext = (struct sadb_ext*) (((char*)(*pfkey_msg)) + sizeof(struct sadb_msg)); for (ext = 1; ext <= K_SADB_EXT_MAX; ext++) { /* copy from extension[ext] to buffer */ if (extensions[ext]) { size_t el; /* Is this type of extension permitted for this type of message? */ if (!pfkey_permitted_extension(dir, (*pfkey_msg)-> sadb_msg_type, ext)) { ERROR("ext type %d not permitted for %d/%d (build)\n", ext, dir, (*pfkey_msg)->sadb_msg_type); SENDERR(EINVAL); } el = extensions[ext]->sadb_ext_len * IPSEC_PFKEYv2_ALIGN; DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_msg_build: " "copying %zu bytes from extensions[%u] (type=%d)\n", el, ext, extensions[ext]->sadb_ext_type); memcpy(pfkey_ext, extensions[ext], el); pfkey_ext = (struct sadb_ext *) ((unsigned char *)pfkey_ext + el); /* Mark that we have seen this extension */ pfkey_mark_extension(ext, &extensions_seen); } } #if 0 /* check required extensions */ DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_msg_build: " "extensions permitted=%08x, seen=%08x, required=%08x.\n", extensions_bitmaps[dir][EXT_BITS_PERM][(*pfkey_msg)-> sadb_msg_type], extensions_seen, extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)-> sadb_msg_type]); #endif #ifndef __KERNEL__ /* * this is silly, there is no need to reparse the message that we just built. * */ if ((error = pfkey_msg_parse(*pfkey_msg, NULL, extensions_check, dir))) { ERROR("pfkey_msg_build: " "Trouble parsing newly built pfkey message, error=%d.\n", error); SENDERR(-error); } #endif errlab: return error; } libreswan-3.32/lib/libswan/pfkey_v2_debug.c000066400000000000000000000130441365625662500207150ustar00rootroot00000000000000/* * @(#) pfkey version 2 debugging messages * * Copyright (C) 2001 Richard Guy Briggs * and Michael Richardson * Copyright (C) 2012 Paul Wouters * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include # include #if defined(linux) # include # include #endif #include "libreswan.h" #include "libreswan/pfkeyv2.h" #include "libreswan/pfkey.h" /* * This file provides ASCII translations of PF_KEY magic numbers. * */ static char *pfkey_sadb_ext_strings[] = { "reserved", /* K_SADB_EXT_RESERVED 0 */ "security-association", /* K_SADB_EXT_SA 1 */ "lifetime-current", /* K_SADB_EXT_LIFETIME_CURRENT 2 */ "lifetime-hard", /* K_SADB_EXT_LIFETIME_HARD 3 */ "lifetime-soft", /* K_SADB_EXT_LIFETIME_SOFT 4 */ "source-address", /* K_SADB_EXT_ADDRESS_SRC 5 */ "destination-address", /* K_SADB_EXT_ADDRESS_DST 6 */ "proxy-address", /* K_SADB_EXT_ADDRESS_PROXY 7 */ "authentication-key", /* K_SADB_EXT_KEY_AUTH 8 */ "cipher-key", /* K_SADB_EXT_KEY_ENCRYPT 9 */ "source-identity", /* K_SADB_EXT_IDENTITY_SRC 10 */ "destination-identity", /* K_SADB_EXT_IDENTITY_DST 11 */ "sensitivity-label", /* K_SADB_EXT_SENSITIVITY 12 */ "proposal", /* K_SADB_EXT_PROPOSAL 13 */ "supported-auth", /* K_SADB_EXT_SUPPORTED_AUTH 14 */ "supported-cipher", /* K_SADB_EXT_SUPPORTED_ENCRYPT 15 */ "spi-range", /* K_SADB_EXT_SPIRANGE 16 */ "X-kmpprivate", /* K_SADB_X_EXT_KMPRIVATE 17 */ "X-satype2", /* K_SADB_X_EXT_SATYPE2 18 */ "X-security-association", /* K_SADB_X_EXT_SA2 19 */ "X-destination-address2", /* K_SADB_X_EXT_ADDRESS_DST2 20 */ "X-source-flow-address", /* K_SADB_X_EXT_ADDRESS_SRC_FLOW 21 */ "X-dest-flow-address", /* K_SADB_X_EXT_ADDRESS_DST_FLOW 22 */ "X-source-mask", /* K_SADB_X_EXT_ADDRESS_SRC_MASK 23 */ "X-dest-mask", /* K_SADB_X_EXT_ADDRESS_DST_MASK 24 */ "X-set-debug", /* K_SADB_X_EXT_DEBUG 25 */ "X-ext-protocol", /* K_SADB_X_EXT_PROTOCOL 26 */ "X-NAT-T-type", /* K_SADB_X_EXT_NAT_T_TYPE 27 */ "X-NAT-T-sport", /* K_SADB_X_EXT_NAT_T_SPORT 28 */ "X-NAT-T-dport", /* K_SADB_X_EXT_NAT_T_DPORT 29 */ "X-NAT-T-OA", /* K_SADB_X_EXT_NAT_T_OA 30 */ "X-plumbif", /* K_SADB_X_EXT_PLUMBIF 31 */ "X-saref", /* K_SADB_X_EXT_SAREF 32 */ }; const char *pfkey_v2_sadb_ext_string(int ext) { if (ext <= K_SADB_EXT_MAX) return pfkey_sadb_ext_strings[ext]; else return "unknown-ext"; } static char *pfkey_sadb_type_strings[K_SADB_MAX + 1] = { [K_SADB_RESERVED] = "reserved", /* K_SADB_RESERVED */ [K_SADB_GETSPI] = "getspi", /* K_SADB_GETSPI */ [K_SADB_UPDATE] = "update", /* K_SADB_UPDATE */ [K_SADB_ADD] = "add", /* K_SADB_ADD */ [K_SADB_DELETE] = "delete", /* K_SADB_DELETE */ [K_SADB_GET] = "get", /* K_SADB_GET */ [K_SADB_ACQUIRE] = "acquire", /* K_SADB_ACQUIRE */ [K_SADB_REGISTER] = "register", /* K_SADB_REGISTER */ [K_SADB_EXPIRE] = "expire", /* K_SADB_EXPIRE */ [K_SADB_FLUSH] = "flush", /* K_SADB_FLUSH */ [K_SADB_DUMP] = "dump", /* K_SADB_DUMP */ [K_SADB_X_PROMISC] = "x-promisc", /* K_SADB_X_PROMISC */ [K_SADB_X_PCHANGE] = "x-pchange", /* K_SADB_X_PCHANGE */ [K_SADB_X_GRPSA] = "x-groupsa", /* K_SADB_X_GRPSA */ [K_SADB_X_ADDFLOW] = "x-addflow(eroute)", /* K_SADB_X_ADDFLOW */ [K_SADB_X_DELFLOW] = "x-delflow(eroute)", /* K_SADB_X_DELFLOW */ [K_SADB_X_DEBUG] = "x-debug", /* K_SADB_X_DEBUG */ [K_SADB_X_NAT_T_NEW_MAPPING] = "x-natt-new-mapping", /* K_SADB_X_NAT_T_NEW_MAPPING */ [K_SADB_X_PLUMBIF] = "x-plumbif", /* K_SADB_X_PLUMBIF */ [K_SADB_X_UNPLUMBIF] = "x-unplumbif", /* K_SADB_X_UNPLUMBIF */ }; const char *pfkey_v2_sadb_type_string(unsigned sadb_type) { if (sadb_type <= K_SADB_MAX && pfkey_sadb_type_strings[sadb_type] != NULL) return pfkey_sadb_type_strings[sadb_type]; else return "unknown-sadb-type"; } libreswan-3.32/lib/libswan/pfkey_v2_ext_bits.c000066400000000000000000000546401365625662500214570ustar00rootroot00000000000000/* * RFC2367 PF_KEYv2 Key management API message parser * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs. * Copyright (C) 2012 Paul Wouters * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ /* * Template from klips/net/ipsec/ipsec/ipsec_parse.c. */ /* * Some ugly stuff to allow consistent debugging code for use in the * kernel and in user space */ #if defined(__KERNEL__) && (defined(linux) || defined(__linux__)) # include /* for printk */ # include "libreswan/ipsec_kversion.h" /* for malloc switch */ # include /* kmalloc() */ # include /* error codes */ # include /* size_t */ # include /* mark_bh */ # include /* struct device, and other headers */ # include /* eth_type_trans */ # include /* struct iphdr */ # if defined(CONFIG_KLIPS_IPV6) # include # endif /* defined(CONFIG_KLIPS_IPV6) */ #else /* __KERNEL__ */ # include # include # include #endif #include #include #include #include "libreswan/pfkey_debug.h" /* array of bitmaps to specify payloads for extensions */ /* ??? why does each bitmap include 1ULL << SADB_EXT_RESERVED? */ pfkey_ext_track extensions_bitmaps [2 /* inbound, outbound */] [2 /* permitted, required */] [K_SADB_MAX + 1] = { /* INBOUND EXTENSIONS */ { /* PERMITTED IN */ { /* K_SADB_RESERVED */ 0 , /* SADB_GETSPI */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << SADB_EXT_ADDRESS_PROXY | 1ULL << SADB_EXT_SPIRANGE , /* SADB_UPDATE */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_LIFETIME_CURRENT | 1ULL << SADB_EXT_LIFETIME_HARD | 1ULL << SADB_EXT_LIFETIME_SOFT | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << SADB_EXT_ADDRESS_PROXY | 1ULL << SADB_EXT_KEY_AUTH | 1ULL << SADB_EXT_KEY_ENCRYPT | 1ULL << SADB_EXT_IDENTITY_SRC | 1ULL << SADB_EXT_IDENTITY_DST | 1ULL << SADB_EXT_SENSITIVITY | 1ULL << K_SADB_X_EXT_NAT_T_SPORT | 1ULL << K_SADB_X_EXT_NAT_T_DPORT , /* SADB_ADD */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_LIFETIME_HARD | 1ULL << SADB_EXT_LIFETIME_SOFT | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << SADB_EXT_ADDRESS_PROXY | 1ULL << SADB_EXT_KEY_AUTH | 1ULL << SADB_EXT_KEY_ENCRYPT | 1ULL << SADB_EXT_IDENTITY_SRC | 1ULL << SADB_EXT_IDENTITY_DST | 1ULL << SADB_EXT_SENSITIVITY | 1ULL << K_SADB_X_EXT_NAT_T_TYPE | 1ULL << K_SADB_X_EXT_NAT_T_SPORT | 1ULL << K_SADB_X_EXT_NAT_T_DPORT | 1ULL << K_SADB_X_EXT_NAT_T_OA | 1ULL << K_SADB_X_EXT_PLUMBIF | 1ULL << K_SADB_X_EXT_SAREF , /* SADB_DELETE */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST , /* SADB_GET */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << SADB_EXT_LIFETIME_CURRENT , /* SADB_ACQUIRE */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << SADB_EXT_ADDRESS_PROXY | 1ULL << SADB_EXT_IDENTITY_SRC | 1ULL << SADB_EXT_IDENTITY_DST | 1ULL << SADB_EXT_SENSITIVITY | 1ULL << SADB_EXT_PROPOSAL , /* K_SADB_REGISTER */ 1ULL << K_SADB_EXT_RESERVED , /* K_SADB_EXPIRE */ 0 , /* K_SADB_FLUSH */ 1ULL << K_SADB_EXT_RESERVED , /* K_SADB_DUMP */ 1ULL << K_SADB_EXT_RESERVED , /* SADB_X_PROMISC */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_LIFETIME_CURRENT | 1ULL << SADB_EXT_LIFETIME_HARD | 1ULL << SADB_EXT_LIFETIME_SOFT | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << SADB_EXT_ADDRESS_PROXY | 1ULL << SADB_EXT_KEY_AUTH | 1ULL << SADB_EXT_KEY_ENCRYPT | 1ULL << SADB_EXT_IDENTITY_SRC | 1ULL << SADB_EXT_IDENTITY_DST | 1ULL << SADB_EXT_SENSITIVITY | 1ULL << SADB_EXT_PROPOSAL | 1ULL << SADB_EXT_SUPPORTED_AUTH | 1ULL << SADB_EXT_SUPPORTED_ENCRYPT | 1ULL << SADB_EXT_SPIRANGE | 1ULL << K_SADB_X_EXT_KMPRIVATE | 1ULL << K_SADB_X_EXT_SATYPE2 | 1ULL << K_SADB_X_EXT_SA2 | 1ULL << K_SADB_X_EXT_ADDRESS_DST2 , /* SADB_X_PCHANGE */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_LIFETIME_CURRENT | 1ULL << SADB_EXT_LIFETIME_HARD | 1ULL << SADB_EXT_LIFETIME_SOFT | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << SADB_EXT_ADDRESS_PROXY | 1ULL << SADB_EXT_KEY_AUTH | 1ULL << SADB_EXT_KEY_ENCRYPT | 1ULL << SADB_EXT_IDENTITY_SRC | 1ULL << SADB_EXT_IDENTITY_DST | 1ULL << SADB_EXT_SENSITIVITY | 1ULL << SADB_EXT_PROPOSAL | 1ULL << SADB_EXT_SUPPORTED_AUTH | 1ULL << SADB_EXT_SUPPORTED_ENCRYPT | 1ULL << SADB_EXT_SPIRANGE | 1ULL << K_SADB_X_EXT_KMPRIVATE | 1ULL << K_SADB_X_EXT_SATYPE2 | 1ULL << K_SADB_X_EXT_SA2 | 1ULL << K_SADB_X_EXT_ADDRESS_DST2 , /* SADB_X_GRPSA */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << K_SADB_X_EXT_SATYPE2 | 1ULL << K_SADB_X_EXT_SA2 | 1ULL << K_SADB_X_EXT_ADDRESS_DST2 , /* SADB_X_ADDFLOW */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << K_SADB_X_EXT_ADDRESS_SRC_FLOW | 1ULL << K_SADB_X_EXT_ADDRESS_DST_FLOW | 1ULL << K_SADB_X_EXT_ADDRESS_SRC_MASK | 1ULL << K_SADB_X_EXT_ADDRESS_DST_MASK | 1ULL << SADB_EXT_IDENTITY_SRC | 1ULL << SADB_EXT_IDENTITY_DST | 1ULL << K_SADB_X_EXT_PROTOCOL , /* SADB_X_DELFLOW */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << K_SADB_X_EXT_ADDRESS_SRC_FLOW | 1ULL << K_SADB_X_EXT_ADDRESS_DST_FLOW | 1ULL << K_SADB_X_EXT_ADDRESS_SRC_MASK | 1ULL << K_SADB_X_EXT_ADDRESS_DST_MASK | 1ULL << SADB_EXT_IDENTITY_SRC | 1ULL << SADB_EXT_IDENTITY_DST | 1ULL << K_SADB_X_EXT_PROTOCOL , /* SADB_X_DEBUG */ 1ULL << SADB_EXT_RESERVED | 1ULL << K_SADB_X_EXT_DEBUG , /* SADB_X_NAT_T_NEW_MAPPING */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << K_SADB_X_EXT_NAT_T_SPORT | 1ULL << K_SADB_X_EXT_NAT_T_DPORT , /* SADB_X_PLUMBIF */ 1ULL << SADB_EXT_RESERVED | 1ULL << K_SADB_X_EXT_PLUMBIF , /* SADB_X_UNPLUMBIF */ 1ULL << SADB_EXT_RESERVED | 1ULL << K_SADB_X_EXT_PLUMBIF }, /* REQUIRED IN */ { /* K_SADB_RESERVED */ 0 , /* K_SADB_GETSPI */ 1ULL << K_SADB_EXT_RESERVED | 1ULL << K_SADB_EXT_ADDRESS_SRC | 1ULL << K_SADB_EXT_ADDRESS_DST | 1ULL << K_SADB_EXT_SPIRANGE , /* K_SADB_UPDATE */ 1ULL << K_SADB_EXT_RESERVED | 1ULL << K_SADB_EXT_SA | 1ULL << K_SADB_EXT_ADDRESS_SRC | 1ULL << K_SADB_EXT_ADDRESS_DST , /* K_SADB_ADD */ 1ULL << K_SADB_EXT_RESERVED | 1ULL << K_SADB_EXT_SA | 1ULL << K_SADB_EXT_ADDRESS_SRC | 1ULL << K_SADB_EXT_ADDRESS_DST , /* K_SADB_DELETE */ 1ULL << K_SADB_EXT_RESERVED | 1ULL << K_SADB_EXT_SA | 1ULL << K_SADB_EXT_ADDRESS_SRC | 1ULL << K_SADB_EXT_ADDRESS_DST , /* K_SADB_GET */ 1ULL << K_SADB_EXT_RESERVED | 1ULL << K_SADB_EXT_SA | 1ULL << K_SADB_EXT_ADDRESS_SRC | 1ULL << K_SADB_EXT_ADDRESS_DST , /* K_SADB_ACQUIRE */ 1ULL << K_SADB_EXT_RESERVED | 1ULL << K_SADB_EXT_ADDRESS_SRC | 1ULL << K_SADB_EXT_ADDRESS_DST | 1ULL << K_SADB_EXT_PROPOSAL , /* K_SADB_REGISTER */ 1ULL << K_SADB_EXT_RESERVED , /* K_SADB_EXPIRE */ 0 , /* K_SADB_FLUSH */ 1ULL << K_SADB_EXT_RESERVED , /* K_SADB_DUMP */ 1ULL << K_SADB_EXT_RESERVED , /* SADB_X_PROMISC */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_LIFETIME_CURRENT | 1ULL << SADB_EXT_LIFETIME_HARD | 1ULL << SADB_EXT_LIFETIME_SOFT | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << SADB_EXT_ADDRESS_PROXY | 1ULL << SADB_EXT_KEY_AUTH | 1ULL << SADB_EXT_KEY_ENCRYPT | 1ULL << SADB_EXT_IDENTITY_SRC | 1ULL << SADB_EXT_IDENTITY_DST | 1ULL << SADB_EXT_SENSITIVITY | 1ULL << SADB_EXT_PROPOSAL | 1ULL << SADB_EXT_SUPPORTED_AUTH | 1ULL << SADB_EXT_SUPPORTED_ENCRYPT | 1ULL << SADB_EXT_SPIRANGE | 1ULL << K_SADB_X_EXT_KMPRIVATE | 1ULL << K_SADB_X_EXT_SATYPE2 | 1ULL << K_SADB_X_EXT_SA2 | 1ULL << K_SADB_X_EXT_ADDRESS_DST2 , /* SADB_X_PCHANGE */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_LIFETIME_CURRENT | 1ULL << SADB_EXT_LIFETIME_HARD | 1ULL << SADB_EXT_LIFETIME_SOFT | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << SADB_EXT_ADDRESS_PROXY | 1ULL << SADB_EXT_KEY_AUTH | 1ULL << SADB_EXT_KEY_ENCRYPT | 1ULL << SADB_EXT_IDENTITY_SRC | 1ULL << SADB_EXT_IDENTITY_DST | 1ULL << SADB_EXT_SENSITIVITY | 1ULL << SADB_EXT_PROPOSAL | 1ULL << SADB_EXT_SUPPORTED_AUTH | 1ULL << SADB_EXT_SUPPORTED_ENCRYPT | 1ULL << SADB_EXT_SPIRANGE | 1ULL << K_SADB_X_EXT_KMPRIVATE | 1ULL << K_SADB_X_EXT_SATYPE2 | 1ULL << K_SADB_X_EXT_SA2 | 1ULL << K_SADB_X_EXT_ADDRESS_DST2 , /* SADB_X_GRPSA */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_ADDRESS_DST , /* SADB_X_ADDFLOW */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << K_SADB_X_EXT_ADDRESS_SRC_FLOW | 1ULL << K_SADB_X_EXT_ADDRESS_DST_FLOW | 1ULL << K_SADB_X_EXT_ADDRESS_SRC_MASK | 1ULL << K_SADB_X_EXT_ADDRESS_DST_MASK , /* SADB_X_DELFLOW */ 1ULL << SADB_EXT_RESERVED #if 0 /* SADB_X_CLREROUTE doesn't need all these... */ | 1ULL << K_SADB_X_EXT_ADDRESS_SRC_FLOW | 1ULL << K_SADB_X_EXT_ADDRESS_DST_FLOW | 1ULL << K_SADB_X_EXT_ADDRESS_SRC_MASK | 1ULL << K_SADB_X_EXT_ADDRESS_DST_MASK #endif , /* SADB_X_DEBUG */ 1ULL << SADB_EXT_RESERVED | 1ULL << K_SADB_X_EXT_DEBUG , /* SADB_X_NAT_T_NEW_MAPPING */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << K_SADB_X_EXT_NAT_T_SPORT | 1ULL << K_SADB_X_EXT_NAT_T_DPORT , /* SADB_X_PLUMBIF */ 1ULL << SADB_EXT_RESERVED | 1ULL << K_SADB_X_EXT_PLUMBIF , /* SADB_X_UNPLUMBIF */ 1ULL << SADB_EXT_RESERVED | 1ULL << K_SADB_X_EXT_PLUMBIF } }, /* OUTBOUND EXTENSIONS */ { /* PERMITTED OUT */ { /* K_SADB_RESERVED */ 0 , /* SADB_GETSPI */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST , /* SADB_UPDATE */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_LIFETIME_CURRENT | 1ULL << SADB_EXT_LIFETIME_HARD | 1ULL << SADB_EXT_LIFETIME_SOFT | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << SADB_EXT_ADDRESS_PROXY | 1ULL << SADB_EXT_IDENTITY_SRC | 1ULL << SADB_EXT_IDENTITY_DST | 1ULL << SADB_EXT_SENSITIVITY | 1ULL << K_SADB_X_EXT_NAT_T_SPORT | 1ULL << K_SADB_X_EXT_NAT_T_DPORT , /* SADB_ADD */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_LIFETIME_HARD | 1ULL << SADB_EXT_LIFETIME_SOFT | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << SADB_EXT_IDENTITY_SRC | 1ULL << SADB_EXT_IDENTITY_DST | 1ULL << SADB_EXT_SENSITIVITY | 1ULL << K_SADB_X_EXT_NAT_T_TYPE | 1ULL << K_SADB_X_EXT_NAT_T_SPORT | 1ULL << K_SADB_X_EXT_NAT_T_DPORT | 1ULL << K_SADB_X_EXT_NAT_T_OA | 1ULL << K_SADB_X_EXT_PLUMBIF | 1ULL << K_SADB_X_EXT_SAREF , /* SADB_DELETE */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST , /* SADB_GET */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_LIFETIME_CURRENT | 1ULL << SADB_EXT_LIFETIME_HARD | 1ULL << SADB_EXT_LIFETIME_SOFT | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << SADB_EXT_ADDRESS_PROXY | 1ULL << SADB_EXT_KEY_AUTH | 1ULL << SADB_EXT_KEY_ENCRYPT | 1ULL << SADB_EXT_IDENTITY_SRC | 1ULL << SADB_EXT_IDENTITY_DST | 1ULL << SADB_EXT_SENSITIVITY | 1ULL << K_SADB_X_EXT_NAT_T_TYPE | 1ULL << K_SADB_X_EXT_NAT_T_SPORT | 1ULL << K_SADB_X_EXT_NAT_T_DPORT | 1ULL << K_SADB_X_EXT_NAT_T_OA , /* SADB_ACQUIRE */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << SADB_EXT_ADDRESS_PROXY | 1ULL << SADB_EXT_IDENTITY_SRC | 1ULL << SADB_EXT_IDENTITY_DST | 1ULL << SADB_EXT_SENSITIVITY | 1ULL << SADB_EXT_PROPOSAL , /* SADB_REGISTER */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SUPPORTED_AUTH | 1ULL << SADB_EXT_SUPPORTED_ENCRYPT , /* SADB_EXPIRE */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_LIFETIME_CURRENT | 1ULL << SADB_EXT_LIFETIME_HARD | 1ULL << SADB_EXT_LIFETIME_SOFT | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST , /* SADB_FLUSH */ 1ULL << SADB_EXT_RESERVED , /* SADB_DUMP */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_LIFETIME_CURRENT | 1ULL << SADB_EXT_LIFETIME_HARD | 1ULL << SADB_EXT_LIFETIME_SOFT | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << SADB_EXT_ADDRESS_PROXY | 1ULL << SADB_EXT_KEY_AUTH | 1ULL << SADB_EXT_KEY_ENCRYPT | 1ULL << SADB_EXT_IDENTITY_SRC | 1ULL << SADB_EXT_IDENTITY_DST | 1ULL << SADB_EXT_SENSITIVITY | 1ULL << K_SADB_X_EXT_NAT_T_TYPE | 1ULL << K_SADB_X_EXT_NAT_T_SPORT | 1ULL << K_SADB_X_EXT_NAT_T_DPORT | 1ULL << K_SADB_X_EXT_NAT_T_OA , /* SADB_X_PROMISC */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_LIFETIME_CURRENT | 1ULL << SADB_EXT_LIFETIME_HARD | 1ULL << SADB_EXT_LIFETIME_SOFT | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << SADB_EXT_ADDRESS_PROXY | 1ULL << SADB_EXT_KEY_AUTH | 1ULL << SADB_EXT_KEY_ENCRYPT | 1ULL << SADB_EXT_IDENTITY_SRC | 1ULL << SADB_EXT_IDENTITY_DST | 1ULL << SADB_EXT_SENSITIVITY | 1ULL << SADB_EXT_PROPOSAL | 1ULL << SADB_EXT_SUPPORTED_AUTH | 1ULL << SADB_EXT_SUPPORTED_ENCRYPT | 1ULL << SADB_EXT_SPIRANGE | 1ULL << K_SADB_X_EXT_KMPRIVATE | 1ULL << K_SADB_X_EXT_SATYPE2 | 1ULL << K_SADB_X_EXT_SA2 | 1ULL << K_SADB_X_EXT_ADDRESS_DST2 , /* SADB_X_PCHANGE */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_LIFETIME_CURRENT | 1ULL << SADB_EXT_LIFETIME_HARD | 1ULL << SADB_EXT_LIFETIME_SOFT | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << SADB_EXT_ADDRESS_PROXY | 1ULL << SADB_EXT_KEY_AUTH | 1ULL << SADB_EXT_KEY_ENCRYPT | 1ULL << SADB_EXT_IDENTITY_SRC | 1ULL << SADB_EXT_IDENTITY_DST | 1ULL << SADB_EXT_SENSITIVITY | 1ULL << SADB_EXT_PROPOSAL | 1ULL << SADB_EXT_SUPPORTED_AUTH | 1ULL << SADB_EXT_SUPPORTED_ENCRYPT | 1ULL << SADB_EXT_SPIRANGE | 1ULL << K_SADB_X_EXT_KMPRIVATE | 1ULL << K_SADB_X_EXT_SATYPE2 | 1ULL << K_SADB_X_EXT_SA2 | 1ULL << K_SADB_X_EXT_ADDRESS_DST2 , /* SADB_X_GRPSA */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << K_SADB_X_EXT_SATYPE2 | 1ULL << K_SADB_X_EXT_SA2 | 1ULL << K_SADB_X_EXT_ADDRESS_DST2 , /* SADB_X_ADDFLOW */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << K_SADB_X_EXT_ADDRESS_SRC_FLOW | 1ULL << K_SADB_X_EXT_ADDRESS_DST_FLOW | 1ULL << K_SADB_X_EXT_ADDRESS_SRC_MASK | 1ULL << K_SADB_X_EXT_ADDRESS_DST_MASK | 1ULL << K_SADB_X_EXT_PROTOCOL , /* SADB_X_DELFLOW */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << K_SADB_X_EXT_ADDRESS_SRC_FLOW | 1ULL << K_SADB_X_EXT_ADDRESS_DST_FLOW | 1ULL << K_SADB_X_EXT_ADDRESS_SRC_MASK | 1ULL << K_SADB_X_EXT_ADDRESS_DST_MASK | 1ULL << K_SADB_X_EXT_PROTOCOL , /* SADB_X_DEBUG */ 1ULL << SADB_EXT_RESERVED | 1ULL << K_SADB_X_EXT_DEBUG , /* SADB_X_NAT_T_NEW_MAPPING */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << K_SADB_X_EXT_NAT_T_SPORT | 1ULL << K_SADB_X_EXT_NAT_T_DPORT , /* SADB_X_PLUMBIF */ 1ULL << SADB_EXT_RESERVED | 1ULL << K_SADB_X_EXT_PLUMBIF , /* SADB_X_UNPLUMBIF */ 1ULL << SADB_EXT_RESERVED | 1ULL << K_SADB_X_EXT_PLUMBIF }, /* REQUIRED OUT */ { /* K_SADB_RESERVED */ 0 , /* SADB_GETSPI */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST , /* SADB_UPDATE */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST , /* SADB_ADD */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST , /* SADB_DELETE */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST , /* SADB_GET */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST /* | 1ULL< * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ /* * Template from klips/net/ipsec/ipsec/ipsec_parser.c. */ /* * Some ugly stuff to allow consistent debugging code for use in the * kernel and in user space */ #ifdef __KERNEL__ # include /* for printk */ # include "libreswan/ipsec_kversion.h" /* for malloc switch */ # include /* kmalloc() */ # include /* error codes */ # include /* size_t */ # include /* mark_bh */ # include /* struct device, and other headers */ # include /* eth_type_trans */ # include /* struct iphdr */ # if defined(CONFIG_KLIPS_IPV6) # include /* struct ipv6hdr */ # endif /* if defined(CONFIG_KLIPS_IPV6) */ extern int debug_pfkey; # include #include "libreswan/ipsec_encap.h" #else /* __KERNEL__ */ # include # include # include # include # include "constants.h" # include "ip_said.h" #endif /* __KERNEL__ */ #include #include #include "libreswan/ipsec_sa.h" /* IPSEC_SAREF_NULL, IPSEC_SA_REF_TABLE_IDX_WIDTH */ /* * how to handle debugging for pfkey. */ #include #define SENDERR(_x) do { error = -(_x); goto errlab; } while (0) static struct satype_tbl { const struct ip_protocol *proto; uint8_t satype; char *name; } satype_tbl[] = { #ifdef __KERNEL__ { IPPROTO_ESP, K_SADB_SATYPE_ESP, "ESP" }, { IPPROTO_AH, K_SADB_SATYPE_AH, "AH" }, { IPPROTO_IPIP, K_SADB_X_SATYPE_IPIP, "IPIP" }, #ifdef CONFIG_KLIPS_IPCOMP { IPPROTO_COMP, K_SADB_X_SATYPE_COMP, "COMP" }, #endif /* CONFIG_KLIPS_IPCOMP */ { IPPROTO_INT, K_SADB_X_SATYPE_INT, "INT" }, #else /* __KERNEL__ */ { SA_ESP, K_SADB_SATYPE_ESP, "ESP" }, { SA_AH, K_SADB_SATYPE_AH, "AH" }, { SA_IPIP, K_SADB_X_SATYPE_IPIP, "IPIP" }, { SA_COMP, K_SADB_X_SATYPE_COMP, "COMP" }, { SA_INT, K_SADB_X_SATYPE_INT, "INT" }, #endif /* __KERNEL__ */ { 0, 0, "UNKNOWN" } }; const struct ip_protocol *satype2proto(uint8_t satype) { int i = 0; while (satype_tbl[i].satype != satype && satype_tbl[i].satype != 0) i++; return satype_tbl[i].proto; } uint8_t proto2satype(const struct ip_protocol *proto) { int i = 0; while (satype_tbl[i].proto != proto && satype_tbl[i].proto != 0) i++; return satype_tbl[i].satype; } char *satype2name(uint8_t satype) { int i = 0; while (satype_tbl[i].satype != satype && satype_tbl[i].satype != 0) i++; return satype_tbl[i].name; } /* Default extension parsers taken from the KLIPS code */ DEBUG_NO_STATIC int pfkey_sa_parse(struct sadb_ext *pfkey_ext) { int error = 0; struct k_sadb_sa *pfkey_sa = (struct k_sadb_sa *)pfkey_ext; /* sanity checks... */ if (!pfkey_sa) { ERROR("pfkey_sa_parse: " "NULL pointer passed in.\n"); SENDERR(EINVAL); } if (pfkey_sa->sadb_sa_len != sizeof(struct k_sadb_sa) / IPSEC_PFKEYv2_ALIGN && pfkey_sa->sadb_sa_len != sizeof(struct sadb_sa) / IPSEC_PFKEYv2_ALIGN) { ERROR("pfkey_sa_parse: " "size wrong pfkey_sa->sadb_sa_len=%d sizeof(struct sadb_sa)=%d.\n", pfkey_sa->sadb_sa_len, (int)sizeof(struct k_sadb_sa)); SENDERR(EINVAL); } #if K_SADB_EALG_MAX < 255 /* probably to silence a gcc warning */ if (pfkey_sa->sadb_sa_encrypt > K_SADB_EALG_MAX) { ERROR("pfkey_sa_parse: " "pfkey_sa->sadb_sa_encrypt=%d > K_SADB_EALG_MAX=%d.\n", pfkey_sa->sadb_sa_encrypt, K_SADB_EALG_MAX); SENDERR(EINVAL); } #endif #if K_SADB_AALG_MAX < 255 if (pfkey_sa->sadb_sa_auth > K_SADB_AALG_MAX) { ERROR("pfkey_sa_parse: " "pfkey_sa->sadb_sa_auth=%d > K_SADB_AALG_MAX=%d.\n", pfkey_sa->sadb_sa_auth, K_SADB_AALG_MAX); SENDERR(EINVAL); } #endif #if K_SADB_SASTATE_MAX < 255 if (pfkey_sa->sadb_sa_state > K_SADB_SASTATE_MAX) { ERROR("pfkey_sa_parse: " "state=%d exceeds MAX=%d.\n", pfkey_sa->sadb_sa_state, K_SADB_SASTATE_MAX); SENDERR(EINVAL); } #endif if (pfkey_sa->sadb_sa_state == K_SADB_SASTATE_DEAD) { ERROR("pfkey_sa_parse: " "state=%d is DEAD=%d.\n", pfkey_sa->sadb_sa_state, K_SADB_SASTATE_DEAD); SENDERR(EINVAL); } if (pfkey_sa->sadb_sa_replay > 64) { ERROR("pfkey_sa_parse: " "replay window size: %d -- must be 0 <= size <= 64\n", pfkey_sa->sadb_sa_replay); SENDERR(EINVAL); } if (pfkey_sa->sadb_sa_exttype != K_SADB_EXT_SA && pfkey_sa->sadb_sa_exttype != K_SADB_X_EXT_SA2) { ERROR("pfkey_sa_parse: " "unknown exttype=%d, expecting K_SADB_EXT_SA=%d or K_SADB_X_EXT_SA2=%d.\n", pfkey_sa->sadb_sa_exttype, K_SADB_EXT_SA, K_SADB_X_EXT_SA2); SENDERR(EINVAL); } if (pfkey_sa->sadb_sa_len > sizeof(struct sadb_sa) / IPSEC_PFKEYv2_ALIGN) { if (pfkey_sa->sadb_x_sa_ref == IPSEC_SAREF_NULL || pfkey_sa->sadb_x_sa_ref == ~IPSEC_SAREF_NULL) pfkey_sa->sadb_x_sa_ref = IPSEC_SAREF_NULL; } if (IPSEC_SAREF_NULL != pfkey_sa->sadb_x_sa_ref && pfkey_sa->sadb_x_sa_ref >= (1 << IPSEC_SA_REF_TABLE_IDX_WIDTH)) { ERROR("pfkey_sa_parse: " "SAref=%d must be (SAref == IPSEC_SAREF_NULL(%d) || SAref < IPSEC_SA_REF_TABLE_NUM_ENTRIES(%d)).\n", pfkey_sa->sadb_x_sa_ref, IPSEC_SAREF_NULL, IPSEC_SA_REF_TABLE_NUM_ENTRIES); SENDERR(EINVAL); } DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, "pfkey_sa_parse: " "successfully found len=%d exttype=%d(%s) spi=%08lx replay=%d state=%d auth=%d encrypt=%d flags=%d ref=%d.\n", pfkey_sa->sadb_sa_len, pfkey_sa->sadb_sa_exttype, pfkey_v2_sadb_ext_string(pfkey_sa->sadb_sa_exttype), (long unsigned int)ntohl(pfkey_sa->sadb_sa_spi), pfkey_sa->sadb_sa_replay, pfkey_sa->sadb_sa_state, pfkey_sa->sadb_sa_auth, pfkey_sa->sadb_sa_encrypt, pfkey_sa->sadb_sa_flags, pfkey_sa->sadb_x_sa_ref); errlab: return error; } DEBUG_NO_STATIC int pfkey_lifetime_parse(struct sadb_ext *pfkey_ext) { int error = 0; struct sadb_lifetime *pfkey_lifetime = (struct sadb_lifetime *)pfkey_ext; DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW, "pfkey_lifetime_parse:enter\n"); /* sanity checks... */ if (!pfkey_lifetime) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_lifetime_parse: " "NULL pointer passed in.\n"); SENDERR(EINVAL); } if (pfkey_lifetime->sadb_lifetime_len != sizeof(struct sadb_lifetime) / IPSEC_PFKEYv2_ALIGN) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_lifetime_parse: " "size wrong pfkey_lifetime->sadb_lifetime_len=%d (*sizeof(u64)=%zu) sizeof(struct sadb_lifetime)=%d.\n", pfkey_lifetime->sadb_lifetime_len, pfkey_lifetime->sadb_lifetime_len * IPSEC_PFKEYv2_ALIGN, (int)sizeof(struct sadb_lifetime)); SENDERR(EINVAL); } switch (pfkey_lifetime->sadb_lifetime_exttype) { case K_SADB_EXT_LIFETIME_HARD: case K_SADB_EXT_LIFETIME_SOFT: case K_SADB_EXT_LIFETIME_CURRENT: break; /* OK */ default: DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_lifetime_parse: " "unexpected ext_type=%d.\n", pfkey_lifetime->sadb_lifetime_exttype); SENDERR(EINVAL); } DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, "pfkey_lifetime_parse: " "life_type=%d(%s) alloc=%u bytes=%u add=%u use=%u.\n", pfkey_lifetime->sadb_lifetime_exttype, pfkey_v2_sadb_ext_string(pfkey_lifetime-> sadb_lifetime_exttype), pfkey_lifetime->sadb_lifetime_allocations, (unsigned)pfkey_lifetime->sadb_lifetime_bytes, (unsigned)pfkey_lifetime->sadb_lifetime_addtime, (unsigned)pfkey_lifetime->sadb_lifetime_usetime); errlab: return error; } DEBUG_NO_STATIC int pfkey_address_parse(struct sadb_ext *pfkey_ext) { int error = 0; int saddr_len = 0; struct sadb_address *pfkey_address = (struct sadb_address *)pfkey_ext; struct sockaddr *s = (struct sockaddr*)((char*)pfkey_address + sizeof(*pfkey_address)); char ipaddr_txt[ADDRTOT_BUF]; /* sanity checks... */ if (!pfkey_address) { ERROR("pfkey_address_parse: " "NULL pointer passed in.\n"); SENDERR(EINVAL); } if (pfkey_address->sadb_address_len < (sizeof(struct sadb_address) + sizeof(struct sockaddr)) / IPSEC_PFKEYv2_ALIGN) { ERROR("pfkey_address_parse: " "size wrong 1 ext_len=%d, adr_ext_len=%d, saddr_len=%d.\n", pfkey_address->sadb_address_len, (int)sizeof(struct sadb_address), (int)sizeof(struct sockaddr)); SENDERR(EINVAL); } if (pfkey_address->sadb_address_reserved) { ERROR("pfkey_address_parse: " "res=%d, must be zero.\n", pfkey_address->sadb_address_reserved); SENDERR(EINVAL); } switch (pfkey_address->sadb_address_exttype) { case K_SADB_EXT_ADDRESS_SRC: case K_SADB_EXT_ADDRESS_DST: case K_SADB_EXT_ADDRESS_PROXY: case K_SADB_X_EXT_ADDRESS_DST2: case K_SADB_X_EXT_ADDRESS_SRC_FLOW: case K_SADB_X_EXT_ADDRESS_DST_FLOW: case K_SADB_X_EXT_ADDRESS_SRC_MASK: case K_SADB_X_EXT_ADDRESS_DST_MASK: case K_SADB_X_EXT_NAT_T_OA: break; default: ERROR("pfkey_address_parse: " "unexpected ext_type=%d.\n", pfkey_address->sadb_address_exttype); SENDERR(ENODEV); } switch (s->sa_family) { case AF_INET: saddr_len = sizeof(struct sockaddr_in); sin_addrtot(s, 0, ipaddr_txt, sizeof(ipaddr_txt)); DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, "pfkey_address_parse: " "found exttype=%u(%s) family=%d(AF_INET) address=%s proto=%u port=%u.\n", pfkey_address->sadb_address_exttype, pfkey_v2_sadb_ext_string(pfkey_address-> sadb_address_exttype), s->sa_family, ipaddr_txt, pfkey_address->sadb_address_proto, ntohs(((struct sockaddr_in*)s)->sin_port)); break; case AF_INET6: saddr_len = sizeof(struct sockaddr_in6); sin_addrtot(s, 0, ipaddr_txt, sizeof(ipaddr_txt)); DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, "pfkey_address_parse: " "found exttype=%u(%s) family=%d(AF_INET6) address=%s proto=%u port=%u.\n", pfkey_address->sadb_address_exttype, pfkey_v2_sadb_ext_string(pfkey_address-> sadb_address_exttype), s->sa_family, ipaddr_txt, pfkey_address->sadb_address_proto, ((struct sockaddr_in6*)s)->sin6_port); break; default: ERROR("pfkey_address_parse: " "s->sa_family=%d not supported.\n", s->sa_family); SENDERR(EPFNOSUPPORT); } if (pfkey_address->sadb_address_len != DIVUP(sizeof(struct sadb_address) + saddr_len, IPSEC_PFKEYv2_ALIGN)) { ERROR("pfkey_address_parse: " "size wrong 2 ext_len=%d, adr_ext_len=%d, saddr_len=%d.\n", pfkey_address->sadb_address_len, (int)sizeof(struct sadb_address), saddr_len); SENDERR(EINVAL); } if (pfkey_address->sadb_address_prefixlen != 0) { ERROR("pfkey_address_parse: " "address prefixes not supported yet.\n"); SENDERR(EAFNOSUPPORT); /* not supported yet */ } /* XXX check if port!=0 */ DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW, "pfkey_address_parse: successful.\n"); errlab: return error; } DEBUG_NO_STATIC int pfkey_key_parse(struct sadb_ext *pfkey_ext) { int error = 0; struct sadb_key *pfkey_key = (struct sadb_key *)pfkey_ext; /* sanity checks... */ if (!pfkey_key) { ERROR("pfkey_key_parse: " "NULL pointer passed in.\n"); SENDERR(EINVAL); } if (pfkey_key->sadb_key_len < sizeof(struct sadb_key) / IPSEC_PFKEYv2_ALIGN) { ERROR("pfkey_key_parse: " "size wrong ext_len=%d, key_ext_len=%d.\n", pfkey_key->sadb_key_len, (int)sizeof(struct sadb_key)); SENDERR(EINVAL); } if (!pfkey_key->sadb_key_bits) { ERROR("pfkey_key_parse: " "key length set to zero, must be non-zero.\n"); SENDERR(EINVAL); } if (pfkey_key->sadb_key_len != DIVUP(sizeof(struct sadb_key) * OCTETBITS + pfkey_key->sadb_key_bits, PFKEYBITS)) { ERROR("pfkey_key_parse: " "key length=%d does not agree with extension length=%d.\n", pfkey_key->sadb_key_bits, pfkey_key->sadb_key_len); SENDERR(EINVAL); } if (pfkey_key->sadb_key_reserved) { ERROR("pfkey_key_parse: " "res=%d, must be zero.\n", pfkey_key->sadb_key_reserved); SENDERR(EINVAL); } if (!( (pfkey_key->sadb_key_exttype == K_SADB_EXT_KEY_AUTH) || (pfkey_key->sadb_key_exttype == K_SADB_EXT_KEY_ENCRYPT))) { ERROR("pfkey_key_parse: " "expecting extension type AUTH or ENCRYPT, got %d.\n", pfkey_key->sadb_key_exttype); SENDERR(EINVAL); } DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, "pfkey_key_parse: " "success, found len=%d exttype=%d(%s) bits=%d reserved=%d.\n", pfkey_key->sadb_key_len, pfkey_key->sadb_key_exttype, pfkey_v2_sadb_ext_string(pfkey_key->sadb_key_exttype), pfkey_key->sadb_key_bits, pfkey_key->sadb_key_reserved); errlab: return error; } DEBUG_NO_STATIC int pfkey_ident_parse(struct sadb_ext *pfkey_ext) { int error = 0; struct sadb_ident *pfkey_ident = (struct sadb_ident *)pfkey_ext; /* sanity checks... */ if (pfkey_ident->sadb_ident_len < sizeof(struct sadb_ident) / IPSEC_PFKEYv2_ALIGN) { ERROR("pfkey_ident_parse: " "size wrong ext_len=%d, key_ext_len=%d.\n", pfkey_ident->sadb_ident_len, (int)sizeof(struct sadb_ident)); SENDERR(EINVAL); } if (pfkey_ident->sadb_ident_type > K_SADB_IDENTTYPE_MAX) { ERROR("pfkey_ident_parse: " "ident_type=%d out of range, must be less than %d.\n", pfkey_ident->sadb_ident_type, K_SADB_IDENTTYPE_MAX); SENDERR(EINVAL); } if (pfkey_ident->sadb_ident_reserved) { ERROR("pfkey_ident_parse: " "res=%d, must be zero.\n", pfkey_ident->sadb_ident_reserved); SENDERR(EINVAL); } /* string terminator/padding must be zero */ if (pfkey_ident->sadb_ident_len > sizeof(struct sadb_ident) / IPSEC_PFKEYv2_ALIGN) { if (*((char*)pfkey_ident + pfkey_ident->sadb_ident_len * IPSEC_PFKEYv2_ALIGN - 1)) { ERROR("pfkey_ident_parse: " "string padding must be zero, last is 0x%02x.\n", *((char*)pfkey_ident + pfkey_ident->sadb_ident_len * IPSEC_PFKEYv2_ALIGN - 1)); SENDERR(EINVAL); } } if ( !((pfkey_ident->sadb_ident_exttype == K_SADB_EXT_IDENTITY_SRC) || (pfkey_ident->sadb_ident_exttype == K_SADB_EXT_IDENTITY_DST))) { ERROR("pfkey_key_parse: " "expecting extension type IDENTITY_SRC or IDENTITY_DST, got %d.\n", pfkey_ident->sadb_ident_exttype); SENDERR(EINVAL); } errlab: return error; } DEBUG_NO_STATIC int pfkey_sens_parse(struct sadb_ext *pfkey_ext) { int error = 0; struct sadb_sens *pfkey_sens = (struct sadb_sens *)pfkey_ext; /* sanity checks... */ if (pfkey_sens->sadb_sens_len < sizeof(struct sadb_sens) / IPSEC_PFKEYv2_ALIGN) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_sens_parse: " "size wrong ext_len=%d, key_ext_len=%d.\n", pfkey_sens->sadb_sens_len, (int)sizeof(struct sadb_sens)); SENDERR(EINVAL); } DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_sens_parse: " "Sorry, I can't parse exttype=%d yet.\n", pfkey_ext->sadb_ext_type); #if 0 SENDERR(EINVAL); /* don't process these yet */ #endif errlab: return error; } DEBUG_NO_STATIC int pfkey_prop_parse(struct sadb_ext *pfkey_ext) { int error = 0; int i, num_comb; struct sadb_prop *pfkey_prop = (struct sadb_prop *)pfkey_ext; struct k_sadb_comb *k_pfkey_comb = (struct k_sadb_comb *) ((char*)pfkey_ext + sizeof(struct sadb_prop)); /* sanity checks... */ if ((pfkey_prop->sadb_prop_len < sizeof(struct sadb_prop) / IPSEC_PFKEYv2_ALIGN) || (((pfkey_prop->sadb_prop_len * IPSEC_PFKEYv2_ALIGN) - sizeof(struct sadb_prop)) % sizeof(struct sadb_comb))) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_prop_parse: " "size wrong ext_len=%d, prop_ext_len=%d comb_ext_len=%d.\n", pfkey_prop->sadb_prop_len, (int)sizeof(struct sadb_prop), (int)sizeof(struct sadb_comb)); SENDERR(EINVAL); } if (pfkey_prop->sadb_prop_replay > 64) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_prop_parse: " "replay window size: %d -- must be 0 <= size <= 64\n", pfkey_prop->sadb_prop_replay); SENDERR(EINVAL); } for (i = 0; i < 3; i++) { if (pfkey_prop->sadb_prop_reserved[i]) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_prop_parse: " "res[%d]=%d, must be zero.\n", i, pfkey_prop->sadb_prop_reserved[i]); SENDERR(EINVAL); } } num_comb = ((pfkey_prop->sadb_prop_len * IPSEC_PFKEYv2_ALIGN) - sizeof(struct sadb_prop)) / sizeof(struct sadb_comb); for (i = 0; i < num_comb; i++) { struct sadb_comb *pfkey_comb = (struct sadb_comb *)k_pfkey_comb; #if K_SADB_AALG_MAX < 255 if (pfkey_comb->sadb_comb_auth > K_SADB_AALG_MAX) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_prop_parse: " "pfkey_comb[%d]->sadb_comb_auth=%d > K_SADB_AALG_MAX=%d.\n", i, pfkey_comb->sadb_comb_auth, K_SADB_AALG_MAX); SENDERR(EINVAL); } #endif if (pfkey_comb->sadb_comb_auth) { if (!pfkey_comb->sadb_comb_auth_minbits) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_prop_parse: " "pfkey_comb[%d]->sadb_comb_auth_minbits=0, fatal.\n", i); SENDERR(EINVAL); } if (!pfkey_comb->sadb_comb_auth_maxbits) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_prop_parse: " "pfkey_comb[%d]->sadb_comb_auth_maxbits=0, fatal.\n", i); SENDERR(EINVAL); } if (pfkey_comb->sadb_comb_auth_minbits > pfkey_comb->sadb_comb_auth_maxbits) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_prop_parse: " "pfkey_comb[%d]->sadb_comb_auth_minbits=%d > maxbits=%d, fatal.\n", i, pfkey_comb->sadb_comb_auth_minbits, pfkey_comb->sadb_comb_auth_maxbits); SENDERR(EINVAL); } } else { if (pfkey_comb->sadb_comb_auth_minbits) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_prop_parse: " "pfkey_comb[%d]->sadb_comb_auth_minbits=%d != 0, fatal.\n", i, pfkey_comb->sadb_comb_auth_minbits); SENDERR(EINVAL); } if (pfkey_comb->sadb_comb_auth_maxbits) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_prop_parse: " "pfkey_comb[%d]->sadb_comb_auth_maxbits=%d != 0, fatal.\n", i, pfkey_comb->sadb_comb_auth_maxbits); SENDERR(EINVAL); } } #if K_SADB_EALG_MAX < 255 if (pfkey_comb->sadb_comb_encrypt > K_SADB_EALG_MAX) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_comb_parse: " "pfkey_comb[%d]->sadb_comb_encrypt=%d > K_SADB_EALG_MAX=%d.\n", i, pfkey_comb->sadb_comb_encrypt, K_SADB_EALG_MAX); SENDERR(EINVAL); } #endif if (pfkey_comb->sadb_comb_encrypt) { if (!pfkey_comb->sadb_comb_encrypt_minbits) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_prop_parse: " "pfkey_comb[%d]->sadb_comb_encrypt_minbits=0, fatal.\n", i); SENDERR(EINVAL); } if (!pfkey_comb->sadb_comb_encrypt_maxbits) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_prop_parse: " "pfkey_comb[%d]->sadb_comb_encrypt_maxbits=0, fatal.\n", i); SENDERR(EINVAL); } if (pfkey_comb->sadb_comb_encrypt_minbits > pfkey_comb->sadb_comb_encrypt_maxbits) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_prop_parse: " "pfkey_comb[%d]->sadb_comb_encrypt_minbits=%d > maxbits=%d, fatal.\n", i, pfkey_comb->sadb_comb_encrypt_minbits, pfkey_comb->sadb_comb_encrypt_maxbits); SENDERR(EINVAL); } } else { if (pfkey_comb->sadb_comb_encrypt_minbits) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_prop_parse: " "pfkey_comb[%d]->sadb_comb_encrypt_minbits=%d != 0, fatal.\n", i, pfkey_comb->sadb_comb_encrypt_minbits); SENDERR(EINVAL); } if (pfkey_comb->sadb_comb_encrypt_maxbits) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_prop_parse: " "pfkey_comb[%d]->sadb_comb_encrypt_maxbits=%d != 0, fatal.\n", i, pfkey_comb->sadb_comb_encrypt_maxbits); SENDERR(EINVAL); } } /* XXX do sanity check on flags */ if (pfkey_comb->sadb_comb_hard_allocations && pfkey_comb->sadb_comb_soft_allocations > pfkey_comb->sadb_comb_hard_allocations) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_prop_parse: " "pfkey_comb[%d]->sadb_comb_soft_allocations=%d > hard_allocations=%d, fatal.\n", i, pfkey_comb->sadb_comb_soft_allocations, pfkey_comb->sadb_comb_hard_allocations); SENDERR(EINVAL); } if (pfkey_comb->sadb_comb_hard_bytes && pfkey_comb->sadb_comb_soft_bytes > pfkey_comb->sadb_comb_hard_bytes) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_prop_parse: " "pfkey_comb[%d]->sadb_comb_soft_bytes=%Ld > hard_bytes=%Ld, fatal.\n", i, (unsigned long long int)pfkey_comb->sadb_comb_soft_bytes, (unsigned long long int)pfkey_comb->sadb_comb_hard_bytes); SENDERR(EINVAL); } if (pfkey_comb->sadb_comb_hard_addtime && pfkey_comb->sadb_comb_soft_addtime > pfkey_comb->sadb_comb_hard_addtime) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_prop_parse: " "pfkey_comb[%d]->sadb_comb_soft_addtime=%Ld > hard_addtime=%Ld, fatal.\n", i, (unsigned long long int)pfkey_comb->sadb_comb_soft_addtime, (unsigned long long int)pfkey_comb->sadb_comb_hard_addtime); SENDERR(EINVAL); } if (pfkey_comb->sadb_comb_hard_usetime && pfkey_comb->sadb_comb_soft_usetime > pfkey_comb->sadb_comb_hard_usetime) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_prop_parse: " "pfkey_comb[%d]->sadb_comb_soft_usetime=%Ld > hard_usetime=%Ld, fatal.\n", i, (unsigned long long int)pfkey_comb->sadb_comb_soft_usetime, (unsigned long long int)pfkey_comb->sadb_comb_hard_usetime); SENDERR(EINVAL); } #ifdef COMB_PACKETS if (pfkey_comb->sadb_x_comb_hard_packets && pfkey_comb->sadb_x_comb_soft_packets > pfkey_comb->sadb_x_comb_hard_packets) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_prop_parse: " "pfkey_comb[%d]->sadb_x_comb_soft_packets=%d > hard_packets=%d, fatal.\n", i, k_pfkey_comb->sadb_x_comb_soft_packets, k_pfkey_comb->sadb_x_comb_hard_packets); SENDERR(EINVAL); } #endif pfkey_comb++; } errlab: return error; } DEBUG_NO_STATIC int pfkey_supported_parse(struct sadb_ext *pfkey_ext) { int error = 0; unsigned int i, num_alg; struct sadb_supported *pfkey_supported = (struct sadb_supported *)pfkey_ext; struct sadb_alg *pfkey_alg = (struct sadb_alg*) ((char*)pfkey_ext + sizeof(struct sadb_supported)); /* sanity checks... */ if ((pfkey_supported->sadb_supported_len < sizeof(struct sadb_supported) / IPSEC_PFKEYv2_ALIGN) || (((pfkey_supported->sadb_supported_len * IPSEC_PFKEYv2_ALIGN) - sizeof(struct sadb_supported)) % sizeof(struct sadb_alg))) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_supported_parse: " "size wrong ext_len=%d, supported_ext_len=%d alg_ext_len=%d.\n", pfkey_supported->sadb_supported_len, (int)sizeof(struct sadb_supported), (int)sizeof(struct sadb_alg)); SENDERR(EINVAL); } if (pfkey_supported->sadb_supported_reserved) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_supported_parse: " "res=%d, must be zero.\n", pfkey_supported->sadb_supported_reserved); SENDERR(EINVAL); } num_alg = ((pfkey_supported->sadb_supported_len * IPSEC_PFKEYv2_ALIGN) - sizeof(struct sadb_supported)) / sizeof(struct sadb_alg); for (i = 0; i < num_alg; i++) { /* process algo description */ if (pfkey_alg->sadb_alg_reserved) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_supported_parse: " "alg[%d], id=%d, ivlen=%d, minbits=%d, maxbits=%d, res=%d, must be zero.\n", i, pfkey_alg->sadb_alg_id, pfkey_alg->sadb_alg_ivlen, pfkey_alg->sadb_alg_minbits, pfkey_alg->sadb_alg_maxbits, pfkey_alg->sadb_alg_reserved); SENDERR(EINVAL); } /* XXX can alg_id auth/enc be determined from info given? Yes, but OpenBSD's method does not iteroperate with rfc2367. rgb, 2000-04-06 */ switch (pfkey_supported->sadb_supported_exttype) { case K_SADB_EXT_SUPPORTED_AUTH: #if K_SADB_AALG_MAX < 255 if (pfkey_alg->sadb_alg_id > K_SADB_AALG_MAX) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_supported_parse: " "alg[%d], alg_id=%d > K_SADB_AALG_MAX=%d, fatal.\n", i, pfkey_alg->sadb_alg_id, K_SADB_AALG_MAX); SENDERR(EINVAL); } #endif break; case SADB_EXT_SUPPORTED_ENCRYPT: #if K_SADB_EALG_MAX < 255 if (pfkey_alg->sadb_alg_id > K_SADB_EALG_MAX) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_supported_parse: " "alg[%d], alg_id=%d > K_SADB_EALG_MAX=%d, fatal.\n", i, pfkey_alg->sadb_alg_id, K_SADB_EALG_MAX); SENDERR(EINVAL); } #endif break; default: DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_supported_parse: " "alg[%d], alg_id=%d > K_SADB_EALG_MAX=%d, fatal.\n", i, pfkey_alg->sadb_alg_id, K_SADB_EALG_MAX); SENDERR(EINVAL); } pfkey_alg++; } errlab: return error; } DEBUG_NO_STATIC int pfkey_spirange_parse(struct sadb_ext *pfkey_ext) { int error = 0; struct sadb_spirange *pfkey_spirange = (struct sadb_spirange *)pfkey_ext; /* sanity checks... */ if (pfkey_spirange->sadb_spirange_len != sizeof(struct sadb_spirange) / IPSEC_PFKEYv2_ALIGN) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_spirange_parse: " "size wrong ext_len=%d, key_ext_len=%d.\n", pfkey_spirange->sadb_spirange_len, (int)sizeof(struct sadb_spirange)); SENDERR(EINVAL); } if (pfkey_spirange->sadb_spirange_reserved) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_spirange_parse: " "reserved=%d must be set to zero.\n", pfkey_spirange->sadb_spirange_reserved); SENDERR(EINVAL); } if (ntohl(pfkey_spirange->sadb_spirange_max) < ntohl(pfkey_spirange->sadb_spirange_min)) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_spirange_parse: " "minspi=%08x must be < maxspi=%08x.\n", ntohl(pfkey_spirange->sadb_spirange_min), ntohl(pfkey_spirange->sadb_spirange_max)); SENDERR(EINVAL); } if (ntohl(pfkey_spirange->sadb_spirange_min) <= 255) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_spirange_parse: " "minspi=%08x must be > 255.\n", ntohl(pfkey_spirange->sadb_spirange_min)); SENDERR(EEXIST); } DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, "pfkey_spirange_parse: " "ext_len=%u ext_type=%u(%s) min=%u max=%u res=%u.\n", pfkey_spirange->sadb_spirange_len, pfkey_spirange->sadb_spirange_exttype, pfkey_v2_sadb_ext_string(pfkey_spirange-> sadb_spirange_exttype), pfkey_spirange->sadb_spirange_min, pfkey_spirange->sadb_spirange_max, pfkey_spirange->sadb_spirange_reserved); errlab: return error; } DEBUG_NO_STATIC int pfkey_x_kmprivate_parse(struct sadb_ext *pfkey_ext) { int error = 0; struct sadb_x_kmprivate *pfkey_x_kmprivate = (struct sadb_x_kmprivate *)pfkey_ext; /* sanity checks... */ if (pfkey_x_kmprivate->sadb_x_kmprivate_len < sizeof(struct sadb_x_kmprivate) / IPSEC_PFKEYv2_ALIGN) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_kmprivate_parse: " "size wrong ext_len=%d, key_ext_len=%d.\n", pfkey_x_kmprivate->sadb_x_kmprivate_len, (int)sizeof(struct sadb_x_kmprivate)); SENDERR(EINVAL); } if (pfkey_x_kmprivate->sadb_x_kmprivate_reserved) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_kmprivate_parse: " "reserved=%d must be set to zero.\n", pfkey_x_kmprivate->sadb_x_kmprivate_reserved); SENDERR(EINVAL); } DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_kmprivate_parse: " "Sorry, I can't parse exttype=%d yet.\n", pfkey_ext->sadb_ext_type); SENDERR(EINVAL); /* don't process these yet */ errlab: return error; } DEBUG_NO_STATIC int pfkey_x_satype_parse(struct sadb_ext *pfkey_ext) { int error = 0; int i; struct sadb_x_satype *pfkey_x_satype = (struct sadb_x_satype *)pfkey_ext; DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW, "pfkey_x_satype_parse: enter\n"); /* sanity checks... */ if (pfkey_x_satype->sadb_x_satype_len != sizeof(struct sadb_x_satype) / IPSEC_PFKEYv2_ALIGN) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_satype_parse: " "size wrong ext_len=%d, key_ext_len=%d.\n", pfkey_x_satype->sadb_x_satype_len, (int)sizeof(struct sadb_x_satype)); SENDERR(EINVAL); } if (!pfkey_x_satype->sadb_x_satype_satype) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_satype_parse: " "satype is zero, must be non-zero.\n"); SENDERR(EINVAL); } if (pfkey_x_satype->sadb_x_satype_satype > K_SADB_SATYPE_MAX) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_satype_parse: " "satype %d > max %d, invalid.\n", pfkey_x_satype->sadb_x_satype_satype, K_SADB_SATYPE_MAX); SENDERR(EINVAL); } if (!(satype2proto(pfkey_x_satype->sadb_x_satype_satype))) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_satype_parse: " "proto lookup from satype=%d failed.\n", pfkey_x_satype->sadb_x_satype_satype); SENDERR(EINVAL); } for (i = 0; i < 3; i++) { if (pfkey_x_satype->sadb_x_satype_reserved[i]) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_satype_parse: " "reserved[%d]=%d must be set to zero.\n", i, pfkey_x_satype->sadb_x_satype_reserved[i]); SENDERR(EINVAL); } } DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, "pfkey_x_satype_parse: " "len=%u ext=%u(%s) satype=%u(%s) res=%u,%u,%u.\n", pfkey_x_satype->sadb_x_satype_len, pfkey_x_satype->sadb_x_satype_exttype, pfkey_v2_sadb_ext_string(pfkey_x_satype-> sadb_x_satype_exttype), pfkey_x_satype->sadb_x_satype_satype, satype2name(pfkey_x_satype->sadb_x_satype_satype), pfkey_x_satype->sadb_x_satype_reserved[0], pfkey_x_satype->sadb_x_satype_reserved[1], pfkey_x_satype->sadb_x_satype_reserved[2]); errlab: return error; } DEBUG_NO_STATIC int pfkey_x_ext_debug_parse(struct sadb_ext *pfkey_ext) { int error = 0; int i; struct sadb_x_debug *pfkey_x_debug = (struct sadb_x_debug *)pfkey_ext; DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW, "pfkey_x_debug_parse: enter\n"); /* sanity checks... */ if (pfkey_x_debug->sadb_x_debug_len != sizeof(struct sadb_x_debug) / IPSEC_PFKEYv2_ALIGN) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_debug_parse: " "size wrong ext_len=%d, key_ext_len=%d.\n", pfkey_x_debug->sadb_x_debug_len, (int)sizeof(struct sadb_x_debug)); SENDERR(EINVAL); } for (i = 0; i < 4; i++) { if (pfkey_x_debug->sadb_x_debug_reserved[i]) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_debug_parse: " "reserved[%d]=%d must be set to zero.\n", i, pfkey_x_debug->sadb_x_debug_reserved[i]); SENDERR(EINVAL); } } errlab: return error; } DEBUG_NO_STATIC int pfkey_x_ext_protocol_parse(struct sadb_ext *pfkey_ext) { int error = 0; struct sadb_protocol *p = (struct sadb_protocol *)pfkey_ext; DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_protocol_parse:\n"); /* sanity checks... */ if (p->sadb_protocol_len != sizeof(*p) / IPSEC_PFKEYv2_ALIGN) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_protocol_parse: size wrong ext_len=%d, key_ext_len=%d.\n", p->sadb_protocol_len, (int)sizeof(*p)); SENDERR(EINVAL); } if (p->sadb_protocol_reserved2 != 0) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_protocol_parse: res=%d, must be zero.\n", p->sadb_protocol_reserved2); SENDERR(EINVAL); } errlab: return error; } DEBUG_NO_STATIC int pfkey_x_ext_nat_t_type_parse( struct sadb_ext *pfkey_ext UNUSED) { return 0; } DEBUG_NO_STATIC int pfkey_x_ext_nat_t_port_parse( struct sadb_ext *pfkey_ext UNUSED) { return 0; } DEBUG_NO_STATIC int pfkey_x_ext_outif_parse(struct sadb_ext *pfkey_ext) { int error = 0; struct sadb_x_plumbif *p = (struct sadb_x_plumbif *)pfkey_ext; DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_outif_parse:\n"); /* sanity checks... */ if (p->sadb_x_outif_len != IPSEC_PFKEYv2_WORDS(sizeof(*p))) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_outif_parse: size wrong ext_len=%d, key_ext_len=%d.\n", p->sadb_x_outif_len, (int)sizeof(*p)); SENDERR(EINVAL); } errlab: return error; } DEBUG_NO_STATIC int pfkey_x_ext_saref_parse(struct sadb_ext *pfkey_ext) { int error = 0; struct sadb_x_saref *p = (struct sadb_x_saref *)pfkey_ext; DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_saref_parse:\n"); /* sanity checks... */ if (p->sadb_x_saref_len != IPSEC_PFKEYv2_WORDS(sizeof(*p))) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_saref_parse: size wrong ext_len=%d, key_ext_len=%d.\n", p->sadb_x_saref_len, (int)sizeof(*p)); SENDERR(EINVAL); } errlab: return error; } #define DEFINEPARSER(NAME) static struct pf_key_ext_parsers_def NAME ## _def = \ { NAME, #NAME }; DEFINEPARSER(pfkey_sa_parse); DEFINEPARSER(pfkey_lifetime_parse); DEFINEPARSER(pfkey_address_parse); DEFINEPARSER(pfkey_key_parse); DEFINEPARSER(pfkey_ident_parse); DEFINEPARSER(pfkey_sens_parse); DEFINEPARSER(pfkey_prop_parse); DEFINEPARSER(pfkey_supported_parse); DEFINEPARSER(pfkey_spirange_parse); DEFINEPARSER(pfkey_x_kmprivate_parse); DEFINEPARSER(pfkey_x_satype_parse); DEFINEPARSER(pfkey_x_ext_debug_parse); DEFINEPARSER(pfkey_x_ext_protocol_parse); DEFINEPARSER(pfkey_x_ext_nat_t_type_parse); DEFINEPARSER(pfkey_x_ext_nat_t_port_parse); DEFINEPARSER(pfkey_x_ext_outif_parse); DEFINEPARSER(pfkey_x_ext_saref_parse); static struct pf_key_ext_parsers_def *ext_default_parsers[] = { NULL, /* pfkey_msg_parse, */ &pfkey_sa_parse_def, &pfkey_lifetime_parse_def, &pfkey_lifetime_parse_def, &pfkey_lifetime_parse_def, &pfkey_address_parse_def, &pfkey_address_parse_def, &pfkey_address_parse_def, &pfkey_key_parse_def, &pfkey_key_parse_def, &pfkey_ident_parse_def, &pfkey_ident_parse_def, &pfkey_sens_parse_def, &pfkey_prop_parse_def, &pfkey_supported_parse_def, &pfkey_supported_parse_def, &pfkey_spirange_parse_def, &pfkey_x_kmprivate_parse_def, &pfkey_x_satype_parse_def, &pfkey_sa_parse_def, &pfkey_address_parse_def, &pfkey_address_parse_def, &pfkey_address_parse_def, &pfkey_address_parse_def, &pfkey_address_parse_def, &pfkey_x_ext_debug_parse_def, &pfkey_x_ext_protocol_parse_def, &pfkey_x_ext_nat_t_type_parse_def, &pfkey_x_ext_nat_t_port_parse_def, &pfkey_x_ext_nat_t_port_parse_def, &pfkey_address_parse_def, &pfkey_x_ext_outif_parse_def, &pfkey_x_ext_saref_parse_def, }; int pfkey_msg_parse(struct sadb_msg *pfkey_msg, struct pf_key_ext_parsers_def *ext_parsers[], struct sadb_ext *extensions[], int dir) { int error = 0; int remain; struct sadb_ext *pfkey_ext; pfkey_ext_track extensions_seen; DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, "pfkey_msg_parse: " "parsing message ver=%d, type=%d(%s), errno=%d, satype=%d(%s), len=%d, res=%d, seq=%d, pid=%d.\n", pfkey_msg->sadb_msg_version, pfkey_msg->sadb_msg_type, pfkey_v2_sadb_type_string(pfkey_msg->sadb_msg_type), pfkey_msg->sadb_msg_errno, pfkey_msg->sadb_msg_satype, satype2name(pfkey_msg->sadb_msg_satype), pfkey_msg->sadb_msg_len, pfkey_msg->sadb_msg_reserved, pfkey_msg->sadb_msg_seq, pfkey_msg->sadb_msg_pid); if (ext_parsers == NULL) ext_parsers = ext_default_parsers; pfkey_extensions_init(extensions); remain = pfkey_msg->sadb_msg_len; remain -= IPSEC_PFKEYv2_WORDS(sizeof(struct sadb_msg)); pfkey_ext = (struct sadb_ext*)((char*)pfkey_msg + sizeof(struct sadb_msg)); extensions[0] = (struct sadb_ext *) pfkey_msg; if (pfkey_msg->sadb_msg_version != PF_KEY_V2) { ERROR("pfkey_msg_parse: " "not PF_KEY_V2 msg, found %d, should be %d.\n", pfkey_msg->sadb_msg_version, PF_KEY_V2); SENDERR(EINVAL); } if (!pfkey_msg->sadb_msg_type) { ERROR("pfkey_msg_parse: " "msg type not set, must be non-zero..\n"); SENDERR(EINVAL); } if (pfkey_msg->sadb_msg_type > K_SADB_MAX) { ERROR("pfkey_msg_parse: " "msg type=%d > max=%d.\n", pfkey_msg->sadb_msg_type, K_SADB_MAX); SENDERR(EINVAL); } switch (pfkey_msg->sadb_msg_type) { case K_SADB_GETSPI: case K_SADB_UPDATE: case K_SADB_ADD: case K_SADB_DELETE: case K_SADB_GET: case K_SADB_X_GRPSA: case K_SADB_X_ADDFLOW: if (!satype2proto(pfkey_msg->sadb_msg_satype)) { ERROR("pfkey_msg_parse: " "satype %d conversion to proto failed for msg_type %d (%s).\n", pfkey_msg->sadb_msg_satype, pfkey_msg->sadb_msg_type, pfkey_v2_sadb_type_string(pfkey_msg-> sadb_msg_type)); SENDERR(EINVAL); } else { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_msg_parse: " "satype %d(%s) conversion to proto gives %s for msg_type %d(%s).\n", pfkey_msg->sadb_msg_satype, satype2name(pfkey_msg->sadb_msg_satype), satype2proto(pfkey_msg->sadb_msg_satype)->name, pfkey_msg->sadb_msg_type, pfkey_v2_sadb_type_string(pfkey_msg-> sadb_msg_type)); } /* FALLTHROUGH */ case K_SADB_ACQUIRE: case K_SADB_REGISTER: case K_SADB_EXPIRE: if (!pfkey_msg->sadb_msg_satype) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_msg_parse: " "satype is zero, must be non-zero for msg_type %d(%s).\n", pfkey_msg->sadb_msg_type, pfkey_v2_sadb_type_string(pfkey_msg-> sadb_msg_type)); SENDERR(EINVAL); } break; default: break; } /* errno must not be set in downward messages */ /* this is not entirely true... a response to an ACQUIRE could return an error */ if ((dir == EXT_BITS_IN) && (pfkey_msg->sadb_msg_type != K_SADB_ACQUIRE) && pfkey_msg->sadb_msg_errno) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_msg_parse: " "errno set to %d.\n", pfkey_msg->sadb_msg_errno); SENDERR(EINVAL); } DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW, "pfkey_msg_parse: " "remain=%d\n", remain ); extensions_seen = 1ULL << SADB_EXT_RESERVED; while ( (remain * IPSEC_PFKEYv2_ALIGN) >= sizeof(struct sadb_ext) ) { /* Is there enough message left to support another extension header? */ if (remain < pfkey_ext->sadb_ext_len) { ERROR("pfkey_msg_parse: " "remain %d less than ext len %d.\n", remain, pfkey_ext->sadb_ext_len); SENDERR(EINVAL); } DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW, "pfkey_msg_parse: " "parsing ext type=%d(%s) remain=%d.\n", pfkey_ext->sadb_ext_type, pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type), remain); /* Is the extension header type valid? */ if ((pfkey_ext->sadb_ext_type > K_SADB_EXT_MAX) || (!pfkey_ext->sadb_ext_type)) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_msg_parse: " "ext type %d(%s) invalid, K_SADB_EXT_MAX=%d.\n", pfkey_ext->sadb_ext_type, pfkey_v2_sadb_ext_string(pfkey_ext-> sadb_ext_type), K_SADB_EXT_MAX); SENDERR(EINVAL); } /* Have we already seen this type of extension? */ if (extensions[pfkey_ext->sadb_ext_type] != NULL) { ERROR("pfkey_msg_parse: " "ext type %d(%s) already seen.\n", pfkey_ext->sadb_ext_type, pfkey_v2_sadb_ext_string( pfkey_ext->sadb_ext_type)); SENDERR(EINVAL); } /* Do I even know about this type of extension? */ if (ext_parsers[pfkey_ext->sadb_ext_type] == NULL) { ERROR("pfkey_msg_parse: " "ext type %d(%s) unknown, ignoring.\n", pfkey_ext->sadb_ext_type, pfkey_v2_sadb_ext_string( pfkey_ext->sadb_ext_type)); goto next_ext; } /* Is this type of extension permitted for this type of message? */ if (!pfkey_permitted_extension(dir, pfkey_msg->sadb_msg_type, pfkey_ext->sadb_ext_type)) { ERROR("ext type %d(%s) not permitted (parse)\n", pfkey_ext->sadb_ext_type, pfkey_v2_sadb_ext_string( pfkey_ext->sadb_ext_type)); SENDERR(EINVAL); } DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, "pfkey_msg_parse: " "remain=%d ext_type=%d(%s) ext_len=%d parsing ext 0p%p with parser %s.\n", remain, pfkey_ext->sadb_ext_type, pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type), pfkey_ext->sadb_ext_len, pfkey_ext, ext_parsers[pfkey_ext->sadb_ext_type]->parser_name); /* Parse the extension */ if ((error = (*ext_parsers[pfkey_ext->sadb_ext_type]->parser)( pfkey_ext))) { ERROR("pfkey_msg_parse: " "extension parsing for type %d(%s) failed with error %d.\n", pfkey_ext->sadb_ext_type, pfkey_v2_sadb_ext_string( pfkey_ext->sadb_ext_type), error); SENDERR(-error); } DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW, "pfkey_msg_parse: " "Extension %d(%s) parsed.\n", pfkey_ext->sadb_ext_type, pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type)); /* Mark that we have seen this extension and remember the header location */ extensions[pfkey_ext->sadb_ext_type] = pfkey_ext; pfkey_mark_extension(pfkey_ext->sadb_ext_type, &extensions_seen); next_ext: /* Calculate how much message remains */ remain -= pfkey_ext->sadb_ext_len; if (!remain) break; /* Find the next extension header */ pfkey_ext = (struct sadb_ext*)((char*)pfkey_ext + pfkey_ext->sadb_ext_len * IPSEC_PFKEYv2_ALIGN); } if (remain) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_msg_parse: " "unexpected remainder of %d.\n", remain); /* why is there still something remaining? */ SENDERR(EINVAL); } /* don't check further if it is an error return message since it may not have a body */ if (pfkey_msg->sadb_msg_errno) SENDERR(-error); if (pfkey_extensions_missing(dir, pfkey_msg->sadb_msg_type, extensions_seen)) { ERROR("required extensions missing; seen=%08llx.\n", (unsigned long long)extensions_seen); SENDERR(EINVAL); } if (dir == EXT_BITS_IN && pfkey_msg->sadb_msg_type == K_SADB_X_DELFLOW && (extensions_seen & K_SADB_X_EXT_ADDRESS_DELFLOW) != K_SADB_X_EXT_ADDRESS_DELFLOW && ((extensions_seen & (1ULL << SADB_EXT_SA)) == 0 || (((struct k_sadb_sa *)extensions[SADB_EXT_SA])->sadb_sa_flags & SADB_X_SAFLAGS_CLEARFLOW) == 0)) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_msg_parse: " "required SADB_X_DELFLOW extensions missing: either %16llx must be present or %16llx must be present with SADB_X_SAFLAGS_CLEARFLOW set.\n", K_SADB_X_EXT_ADDRESS_DELFLOW & ~extensions_seen, (1ULL << SADB_EXT_SA) & ~extensions_seen); SENDERR(EINVAL); } switch (pfkey_msg->sadb_msg_type) { case K_SADB_ADD: case K_SADB_UPDATE: /* check maturity */ if (((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state != K_SADB_SASTATE_MATURE) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_msg_parse: " "state=%d for add or update should be MATURE=%d.\n", ((struct k_sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state, K_SADB_SASTATE_MATURE); SENDERR(EINVAL); } /* check AH and ESP */ switch (((struct sadb_msg*)extensions[SADB_EXT_RESERVED])-> sadb_msg_satype) { case SADB_SATYPE_AH: if ((struct k_sadb_sa*)extensions[SADB_EXT_SA] == NULL || ((struct k_sadb_sa*)extensions[SADB_EXT_SA])-> sadb_sa_auth == SADB_AALG_NONE) { ERROR("pfkey_msg_parse: " "auth alg is zero; must be non-zero for AH SAs.\n"); SENDERR(EINVAL); } if (((struct k_sadb_sa*)(extensions[SADB_EXT_SA]))-> sadb_sa_encrypt != SADB_EALG_NONE) { ERROR("pfkey_msg_parse: " "AH handed encalg=%d; must be zero.\n", ((struct k_sadb_sa*)(extensions[ SADB_EXT_SA]))->sadb_sa_encrypt); SENDERR(EINVAL); } break; case SADB_SATYPE_ESP: if ((struct k_sadb_sa*)extensions[SADB_EXT_SA] == NULL || ((struct k_sadb_sa*)extensions[SADB_EXT_SA])-> sadb_sa_encrypt == SADB_EALG_NONE) { ERROR("pfkey_msg_parse: " "encrypt alg=%d is zero; must be non-zero for ESP=%d SAs.\n", ((struct k_sadb_sa*)extensions[ SADB_EXT_SA])->sadb_sa_encrypt, ((struct sadb_msg*)extensions[ SADB_EXT_RESERVED])->sadb_msg_satype); SENDERR(EINVAL); } if ((((struct k_sadb_sa*)(extensions[SADB_EXT_SA]))-> sadb_sa_encrypt == SADB_EALG_NULL) && (((struct k_sadb_sa*)(extensions[SADB_EXT_SA]))-> sadb_sa_auth == SADB_AALG_NONE) ) { ERROR("pfkey_msg_parse: " "ESP handed encNULL+authNONE, illegal combination.\n"); SENDERR(EINVAL); } break; case K_SADB_X_SATYPE_COMP: if (!(((struct k_sadb_sa*)extensions[SADB_EXT_SA]) && ((struct k_sadb_sa*)extensions[SADB_EXT_SA])-> sadb_sa_encrypt != SADB_EALG_NONE)) { ERROR("pfkey_msg_parse: " "encrypt alg=%d is zero, must be non-zero for COMP=%d SAs.\n", ((struct k_sadb_sa*)extensions[ SADB_EXT_SA])->sadb_sa_encrypt, ((struct sadb_msg*)extensions[ SADB_EXT_RESERVED])->sadb_msg_satype); SENDERR(EINVAL); } if (((struct k_sadb_sa*)(extensions[SADB_EXT_SA]))-> sadb_sa_auth != SADB_AALG_NONE) { ERROR("pfkey_msg_parse: " "COMP handed auth=%d, must be zero.\n", ((struct k_sadb_sa*)(extensions[ SADB_EXT_SA]))->sadb_sa_auth); SENDERR(EINVAL); } break; default: break; } if (ntohl(((struct k_sadb_sa*)(extensions[SADB_EXT_SA]))-> sadb_sa_spi) <= 255) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_msg_parse: " "spi=%08x must be > 255.\n", ntohl(((struct k_sadb_sa*)(extensions[ SADB_EXT_SA ]))->sadb_sa_spi)); SENDERR(EINVAL); } default: break; } errlab: return error; } libreswan-3.32/lib/libswan/portof.3.xml000066400000000000000000000075331365625662500200600ustar00rootroot00000000000000 PaulWoutersplaceholder to suppress warning IPSEC_PORTOF 3 8 Sept 2000 libreswan Executable programs ipsec portof ipsec setportof ipsec sockaddrof ipsec sockaddrlenof get port field of an ip_address, set port field of an ip_address, get pointer to internal sockaddr of an ip_address, get length of internal sockaddr of an ip_address #include <libreswan.h> int portof const ip_address * src void setportof int port ip_address * dst struct sockaddr *sockaddrof ip_address * src size_t sockaddrlenof const ip_address * src DESCRIPTION The <libreswan.h> internal type ip_address contains one of the sockaddr types internally. Reliance on this feature is discouraged, but it may occasionally be necessary. These functions provide low-level tools for this purpose. Portof and setportof respectively read and write the port-number field of the internal sockaddr. The values are in network byte order. Sockaddrof returns a pointer to the internal sockaddr, for passing to other functions. Sockaddrlenof reports the size of the internal sockaddr, for use in storage allocation. SEE ALSO inet3, ipsec_initaddr3 DIAGNOSTICS Portof returns , sockaddrof returns NULL, and sockaddrlenof returns 0 if an unknown address family is found within the ip_address. HISTORY Written for the FreeS/WAN project by Henry Spencer. BUGS These functions all depend on low-level details of the ip_address type, which are in principle subject to change. Avoid using them unless really necessary. libreswan-3.32/lib/libswan/proposals.c000066400000000000000000000402421365625662500200440ustar00rootroot00000000000000/* * Algorithm info parsing and creation functions * Author: JuanJo Ciarlante * * Copyright (C) 2012 Paul Wouters * Copyright (C) 2015-2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include #include #include "lswlog.h" #include "lswalloc.h" #include "constants.h" #include "proposals.h" #include "ike_alg.h" #include "ike_alg_integ.h" #include "ike_alg_dh.h" #include "alg_byname.h" struct proposal { /* * The algorithm entries. */ struct algorithm *algorithms[PROPOSAL_ALGORITHM_ROOF]; /* * Which protocol is this proposal intended for? */ const struct proposal_protocol *protocol; struct proposal *next; }; struct proposals { bool defaulted; int ref_cnt; struct proposal *proposals; }; struct proposal_parser *alloc_proposal_parser(const struct proposal_policy *policy, const struct proposal_protocol *protocol) { struct proposal_parser *parser = alloc_thing(struct proposal_parser, "parser"); parser->policy = policy; parser->protocol = protocol; parser->error[0] = '\0'; return parser; } void free_proposal_parser(struct proposal_parser **parser) { pfree(*parser); *parser = NULL; } bool proposal_encrypt_aead(const struct proposal *proposal) { if (proposal->algorithms[PROPOSAL_encrypt] == NULL) { return false; } FOR_EACH_ALGORITHM(proposal, encrypt, alg) { const struct encrypt_desc *encrypt = encrypt_desc(alg->desc); if (!encrypt_desc_is_aead(encrypt)) { return false; } } return true; } bool proposal_encrypt_norm(const struct proposal *proposal) { if (proposal->algorithms[PROPOSAL_encrypt] == NULL) { return false; } FOR_EACH_ALGORITHM(proposal, encrypt, alg) { const struct encrypt_desc *encrypt = encrypt_desc(alg->desc); if (encrypt_desc_is_aead(encrypt)) { return false; } } return true; } bool proposal_integ_none(const struct proposal *proposal) { /* interpret NULL as NONE */ FOR_EACH_ALGORITHM(proposal, integ, alg) { const struct integ_desc *integ = integ_desc(alg->desc); if (integ != &ike_alg_integ_none) { return false; } } return true; } bool proposal_aead_none_ok(struct proposal_parser *parser, const struct proposal *proposal) { if (IMPAIR(ALLOW_NULL_NONE)) { return true; } if (proposal->algorithms[PROPOSAL_encrypt] == NULL) { return true; } /* are any and all encrypt algorithms AEAD? */ bool aead = proposal_encrypt_aead(proposal); bool norm = proposal_encrypt_norm(proposal); if (!aead && !norm) { proposal_error(parser, "AEAD and non-AEAD %s encryption algorithm can not be combined", proposal->protocol->name); return false; } /* are any and all integ algorithms NONE? */ bool none = proposal_integ_none(proposal); if (aead && !none) { const struct ike_alg *encrypt = proposal->algorithms[PROPOSAL_encrypt]->desc; /* * At least one of the integrity algorithms wasn't * NONE. For instance, esp=aes_gcm-sha1" is invalid. */ proposal_error(parser, "AEAD %s encryption algorithm '%s' must have 'none' as the integrity algorithm", proposal->protocol->name, encrypt->name); return false; } if (norm && none) { const struct ike_alg *encrypt = proposal->algorithms[PROPOSAL_encrypt]->desc; /* * Not AEAD and either there was no integrity * algorithm (implying NONE) or at least one integrity * algorithm was NONE. For instance, * esp=aes_cbc-none" is invalid. */ proposal_error(parser, "non-AEAD %s encryption algorithm '%s' cannot have 'none' as the integrity algorithm", proposal->protocol->name, encrypt->name); return false; } return true; } /* * proposals struct can be shared by several connections instances, * handle free() with ref_cnts. */ void proposals_addref(struct proposals **proposals) { if ((*proposals) != NULL) { (*proposals)->ref_cnt++; } } void proposals_delref(struct proposals **proposals) { if ((*proposals) != NULL) { if ((*proposals)->ref_cnt == 0) { free_proposal(&(*proposals)->proposals); pfree((*proposals)); } else { (*proposals)->ref_cnt--; } *proposals = NULL; } } struct proposal *next_proposal(const struct proposals *proposals, struct proposal *last) { if (last == NULL) { return proposals->proposals; } else { return last->next; } } unsigned nr_proposals(struct proposals *proposals) { unsigned nr = 0; FOR_EACH_PROPOSAL(proposals, proposal) { nr++; } return nr; } void append_proposal(struct proposals *proposals, struct proposal **proposal) { struct proposal **end = &proposals->proposals; /* check for duplicates */ while ((*end) != NULL) { bool same = true; for (enum proposal_algorithm pa = 0; same && pa < PROPOSAL_ALGORITHM_ROOF; pa++) { struct algorithm *old = (*end)->algorithms[pa]; struct algorithm *new = (*proposal)->algorithms[pa]; while (same) { if (new == NULL && old == NULL) { break; } if (new == NULL || old == NULL) { same = false; break; } if (new->desc != old->desc) { same = false; break; } /* * If list already contains encryption * with ENCKEYLEN=0 then new is a * duplicate as 0 generates all keys. * Ignore reverse vis aes128,aes. */ if (old->desc->algo_type == IKE_ALG_ENCRYPT && (old->enckeylen != 0 && new->enckeylen != old->enckeylen)) { same = false; break; } new = new->next; old = old->next; } } if (same) { dbg("discarding duplicate proposal"); free_proposal(proposal); return; } end = &(*end)->next; } *end = *proposal; *proposal = NULL; } struct v1_proposal v1_proposal(const struct proposal *proposal) { struct v1_proposal v1 = { .protocol = proposal->protocol, #define D(ALG) .ALG = proposal->algorithms[PROPOSAL_##ALG] != NULL ? ALG##_desc(proposal->algorithms[PROPOSAL_##ALG]->desc) : NULL D(encrypt), D(prf), D(integ), D(dh), #undef D }; v1.enckeylen = proposal->algorithms[PROPOSAL_encrypt] != NULL ? proposal->algorithms[PROPOSAL_encrypt]->enckeylen : 0; return v1; } struct algorithm *next_algorithm(const struct proposal *proposal, enum proposal_algorithm algorithm, struct algorithm *last) { if (last == NULL) { /* * Hack, there should there a way to index algorithm * types; however the old enum proved very dangerous. */ passert(algorithm < elemsof(proposal->algorithms)); return proposal->algorithms[algorithm]; } else { return last->next; } } void free_algorithms(struct proposal *proposal, enum proposal_algorithm algorithm) { passert(algorithm < elemsof(proposal->algorithms)); struct algorithm *alg = proposal->algorithms[algorithm]; while (alg != NULL) { struct algorithm *del = alg; alg = alg->next; pfree(del); } proposal->algorithms[algorithm] = NULL; } struct proposal *alloc_proposal(struct proposal_parser *parser) { struct proposal *proposal = alloc_thing(struct proposal, "proposal"); proposal->protocol = parser->protocol; return proposal; } void free_proposal(struct proposal **proposals) { struct proposal *proposal = *proposals; while (proposal != NULL) { struct proposal *del = proposal; proposal = proposal->next; for (enum proposal_algorithm algorithm = 0; algorithm < PROPOSAL_ALGORITHM_ROOF; algorithm++) { free_algorithms(del, algorithm); } pfree(del); } *proposals = NULL; } /* * XXX: hack, need to come up with a type safe way of mapping an * ike_alg onto an index. */ static enum proposal_algorithm ike_to_proposal_algorithm(const struct ike_alg *alg) { if (alg->algo_type == IKE_ALG_ENCRYPT) { return PROPOSAL_encrypt; } else if (alg->algo_type == IKE_ALG_PRF) { return PROPOSAL_prf; } else if (alg->algo_type == IKE_ALG_INTEG) { return PROPOSAL_integ; } else if (alg->algo_type == IKE_ALG_DH) { return PROPOSAL_dh; } else { PASSERT_FAIL("unexpected algorithm type %s", ike_alg_type_name(alg->algo_type)); } } void append_algorithm(struct proposal_parser *parser, struct proposal *proposal, const struct ike_alg *alg, int enckeylen) { enum proposal_algorithm algorithm = ike_to_proposal_algorithm(alg); passert(algorithm < elemsof(proposal->algorithms)); struct algorithm **end = &proposal->algorithms[algorithm]; /* find end, and check for duplicates */ while ((*end) != NULL) { /* * enckeylen=0 acts as a wildcard */ if (alg == (*end)->desc && (alg->algo_type != IKE_ALG_ENCRYPT || ((*end)->enckeylen == 0 || enckeylen == (*end)->enckeylen))) { parser->policy->warning("discarding duplicate algorithm '%s'", alg->name); return; } end = &(*end)->next; } struct algorithm new_algorithm = { .desc = alg, .enckeylen = enckeylen, }; DBGF(DBG_PROPOSAL_PARSER, "appending %s algorithm %s[_%d]", ike_alg_type_name(alg->algo_type), alg->name, enckeylen); *end = clone_thing(new_algorithm, "alg"); } void fmt_proposal(struct lswlog *log, const struct proposal *proposal) { const char *ps = ""; const char *as = ""; as = ps; FOR_EACH_ALGORITHM(proposal, encrypt, alg) { const struct encrypt_desc *encrypt = encrypt_desc(alg->desc); lswlogs(log, as); ps = "-"; as = "+"; lswlogs(log, encrypt->common.fqn); if (alg->enckeylen != 0) { lswlogf(log, "_%d", alg->enckeylen); } } as = ps; FOR_EACH_ALGORITHM(proposal, prf, alg) { const struct prf_desc *prf = prf_desc(alg->desc); lswlogs(log, as); ps = "-"; as = "+"; lswlogs(log, prf->common.fqn); } bool print_integ = (IMPAIR(PROPOSAL_PARSER) || /* no PRF */ next_algorithm(proposal, PROPOSAL_prf, NULL) == NULL || /* AEAD should have NONE */ (proposal_encrypt_aead(proposal) && !proposal_integ_none(proposal))); if (!print_integ && proposal_encrypt_norm(proposal)) { /* non-AEAD should have matching PRF and INTEG */ for (struct algorithm *integ = next_algorithm(proposal, PROPOSAL_integ, NULL), *prf = next_algorithm(proposal, PROPOSAL_prf, NULL); !print_integ && (integ != NULL || prf != NULL); integ = next_algorithm(proposal, PROPOSAL_integ, integ), prf = next_algorithm(proposal, PROPOSAL_prf, prf)) { print_integ = (integ == NULL || prf == NULL || &integ_desc(integ->desc)->prf->common != prf->desc); } } as = ps; if (print_integ) { FOR_EACH_ALGORITHM(proposal, integ, alg) { const struct integ_desc *integ = integ_desc(alg->desc); lswlogs(log, as); ps = "-"; as = "+"; lswlogs(log, integ->common.fqn); } } as = ps; FOR_EACH_ALGORITHM(proposal, dh, alg) { const struct dh_desc *dh = dh_desc(alg->desc); lswlogs(log, as); ps = "-"; as = "+"; lswlogs(log, dh->common.fqn); } } void fmt_proposals(struct lswlog *log, const struct proposals *proposals) { const char *sep = ""; FOR_EACH_PROPOSAL(proposals, proposal) { lswlogs(log, sep); fmt_proposal(log, proposal); sep = ", "; } } /* * When PFS=no ignore any DH algorithms, and when PFS=yes reject * mixing implicit and explicit DH. */ static bool proposals_pfs_vs_dh_check(struct proposal_parser *parser, struct proposals *proposals) { /* scrape the proposals for dh algorithms */ const struct proposal *first_null = NULL; const struct proposal *first_none = NULL; const struct ike_alg *first_dh = NULL; const struct ike_alg *second_dh = NULL; FOR_EACH_PROPOSAL(proposals, proposal) { if (proposal->algorithms[PROPOSAL_dh] == NULL) { if (first_null == NULL) { first_null = proposal; } } else if (proposal->algorithms[PROPOSAL_dh]->desc == &ike_alg_dh_none.common) { if (first_none == NULL) { first_none = proposal; } } else if (first_dh == NULL) { first_dh = proposal->algorithms[PROPOSAL_dh]->desc; } else if (second_dh == NULL && first_dh != proposal->algorithms[PROPOSAL_dh]->desc) { second_dh = proposal->algorithms[PROPOSAL_dh]->desc; } } if (first_dh == NULL && first_none == NULL) { /* no DH is always ok */ return true; } /* * Try to generate very specific errors first. For instance, * given PFS=no esp=aes,aes;dh21, an error stating that dh21 * is not valid because of PFS is more helpful than an error * saying that all or no proposals need PFS. */ /* * Since PFS=NO overrides any DH, don't silently ignore it. * Check this early so that a conflict with PFS=no code gets * reported before anything else. */ if (!parser->policy->pfs && (first_dh != NULL || first_none != NULL)) { FOR_EACH_PROPOSAL(proposals, proposal) { const struct ike_alg *dh = NULL; if (proposal->algorithms[PROPOSAL_dh] != NULL) { dh = proposal->algorithms[PROPOSAL_dh]->desc; } if (dh == &ike_alg_dh_none.common) { parser->policy->warning("ignoring redundant %s DH algorithm NONE as PFS policy is disabled", parser->protocol->name); } else if (dh != NULL) { parser->policy->warning("ignoring %s DH algorithm %s as PFS policy is disabled", parser->protocol->name, dh->fqn); } free_algorithms(proposal, PROPOSAL_dh); } return true; } /* * Since at least one proposal included DH, all proposals * should. A proposal without DH is an error. * * (The converse, no proposals including DH was handled right * at the start). */ if (first_null != NULL) { /* DH was specified */ proposal_error(parser, "either all or no %s proposals should specify DH", parser->protocol->name); if (!impair_proposal_errors(parser)) { return false; } } switch (parser->policy->version) { case IKEv1: /* * IKEv1 only allows one DH algorithm. */ if (first_dh != NULL && second_dh != NULL) { proposal_error(parser, "more than one IKEv1 %s DH algorithm (%s, %s) is not allowed in quick mode", parser->protocol->name, first_dh->fqn, second_dh->fqn); if (!impair_proposal_errors(parser)) { return false; } } break; case IKEv2: /* * IKEv2, only implements one DH algorithm. */ if (first_dh != NULL && second_dh != NULL) { proposal_error(parser, "more than one IKEv2 %s DH algorithm (%s, %s) requires unimplemented CHILD_SA INVALID_KE", parser->protocol->name, first_dh->fqn, second_dh->fqn); if (!impair_proposal_errors(parser)) { return false; } } break; default: /* ignore */ break; } return true; } void proposal_error(struct proposal_parser *parser, const char *fmt, ...) { va_list ap; va_start(ap, fmt); vsnprintf(parser->error, sizeof(parser->error), fmt, ap); va_end(ap); } bool impair_proposal_errors(struct proposal_parser *parser) { pexpect(parser->error[0] != '\0'); if (IMPAIR(PROPOSAL_PARSER)) { libreswan_log("IMPAIR: ignoring proposal error: %s", parser->error); parser->error[0] = '\0'; return true; } else { return false; } } struct proposals *proposals_from_str(struct proposal_parser *parser, const char *str) { struct proposals *proposals = alloc_thing(struct proposals, "proposals"); unsigned parser_version = parser->policy->parser_version; if (parser_version == 0) { parser_version = parser->policy->version; } if (str == NULL) { proposals->defaulted = true; /* may still be null */ str = parser->protocol->defaults[parser->policy->version]->proposals; } bool ok; switch (parser_version) { case 2: ok = v2_proposals_parse_str(parser, proposals, shunk1(str)); break; default: ok = v1_proposals_parse_str(parser, proposals, shunk1(str)); break; } if (!ok) { proposals_delref(&proposals); return NULL; } if (proposals->proposals == NULL) { proposals_delref(&proposals); return NULL; } if (parser->policy->check_pfs_vs_dh && !proposals_pfs_vs_dh_check(parser, proposals)) { pexpect(parser->error[0] != '\0'); proposals_delref(&proposals); return NULL; } return proposals; } bool default_proposals(struct proposals *proposals) { return proposals == NULL || proposals->defaulted; } libreswan-3.32/lib/libswan/rangetosubnet.3.xml000066400000000000000000000064341365625662500214260ustar00rootroot00000000000000 PaulWoutersplaceholder to suppress warning IPSEC_RANGETOSUBNET 3 8 Sept 2000 libreswan Executable programs ipsec rangetosubnet convert address range to subnet #include <libreswan.h> const char *rangetosubnet const ip_address * start const ip_address * stop ip_subnet * dst DESCRIPTION Rangetosubnet accepts a pair of IP addresses to specify an address range, from start to stop inclusive, and converts this to a subnet if possible. The addresses must both be IPv4 or both be IPv6, and the address family of the resulting subnet is the same. Rangetosubnet returns NULL for success and a pointer to a string-literal error message for failure; see DIAGNOSTICS. SEE ALSO ipsec_initsubnet3, ipsec_ttosubnet3 DIAGNOSTICS Fatal errors in rangetosubnet are: mixed address families; unknown address family; start and stop do not define a subnet. HISTORY Written for the FreeS/WAN project by Henry Spencer. BUGS The restriction of error reports to literal strings (so that callers don't need to worry about freeing them or copying them) does limit the precision of error reporting. The error-reporting convention lends itself to slightly obscure code, because many readers will not think of NULL as signifying success. A good way to make it clearer is to write something like: const char *error; error = rangetosubnet( /* ... */ ); if (error != NULL) { /* something went wrong */ libreswan-3.32/lib/libswan/rangetosubnet.c000066400000000000000000000044351365625662500207060ustar00rootroot00000000000000/* * express an address range as a subnet (if possible) * * Copyright (C) 2000 Henry Spencer. * Copyright (C) 2019 Andrew Cagney * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. */ #include "ip_subnet.h" #include "libreswan/passert.h" /* * rangetosubnet - turn an address range into a subnet, if possible * * A range which is a valid subnet will have a network part which is the * same in the from value and the to value, followed by a host part which * is all 0 in the from value and all 1 in the to value. * * ??? this really should use ip_range rather than a pair of ip_address values */ err_t rangetosubnet(from, to, dst) const ip_address *from; const ip_address *to; ip_subnet *dst; { const struct ip_info *ft = address_type(from); const struct ip_info *tt = address_type(to); if (ft == NULL || tt == NULL) { return "unknown address type"; } if (ft != tt) { return "mismatched address types"; } unsigned fb; unsigned tb; const unsigned char *f; const unsigned char *t; int i; int nnet; unsigned m; shunk_t fs = address_as_shunk(from); const uint8_t *fp = fs.ptr; /* cast cast void * */ passert(fs.len > 0); size_t n = fs.len; shunk_t ts = address_as_shunk(to); const uint8_t *tp = ts.ptr; /* cast const void * */ passert(fs.len == ts.len); f = fp; t = tp; nnet = 0; for (i = n; i > 0 && *f == *t; i--, f++, t++) nnet += 8; if (i > 0 && !(*f == 0x00 && *t == 0xff)) { /* mid-byte bdry. */ fb = *f++; tb = *t++; i--; m = 0x80; while ((fb & m) == (tb & m)) { fb &= ~m; tb |= m; m >>= 1; nnet++; } if (fb != 0x00 || tb != 0xff) return "not a valid subnet"; } for (; i > 0 && *f == 0x00 && *t == 0xff; i--, f++, t++) continue; if (i != 0) return "invalid subnet"; return initsubnet(from, nnet, 'x', dst); } libreswan-3.32/lib/libswan/realtime.c000066400000000000000000000062121365625662500176230ustar00rootroot00000000000000/* time objects and functions, for libreswan * * Copyright (C) 1998, 1999, 2000 Henry Spencer. * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. * */ #include /* for clock_*() + clockid_t */ #include "constants.h" /* for memeq() which is clearly not a constant */ #include "lswlog.h" /* for libreswan_exit_log_errno() */ #include "realtime.h" const realtime_t realtime_epoch = REALTIME_EPOCH; realtime_t realtime(time_t time) { return (realtime_t) { { time, 0, }, }; } realtime_t realtimesum(realtime_t t, deltatime_t d) { struct timeval dv = deltatimeval(d); realtime_t s; timeradd(&t.rt, &dv, &s.rt); return s; } bool is_realtime_epoch(realtime_t t) { return !timerisset(&t.rt); } bool realbefore(realtime_t a, realtime_t b) { return timercmp(&a.rt, &b.rt, <); } deltatime_t realtimediff(realtime_t a, realtime_t b) { return deltatime_timevals_diff(a.rt, b.rt); } clockid_t realtime_clockid(void) { return CLOCK_REALTIME; } realtime_t realnow(void) { struct timespec ts; int e = clock_gettime(realtime_clockid(), &ts); if (e != 0) { libreswan_exit_log_errno(e, "clock_gettime(%d,...) call in realnow() failed", realtime_clockid()); } realtime_t t = { .rt = { .tv_sec = ts.tv_sec, .tv_usec = ts.tv_nsec / 1000, }, }; return t; } struct timespec realtime_as_timespec(realtime_t t) { struct timespec ts = { .tv_sec = t.rt.tv_sec, .tv_nsec = t.rt.tv_usec * 1000, }; return ts; } struct realtm local_realtime(realtime_t t) { struct realtm tm; zero(&tm); localtime_r(&t.rt.tv_sec, &tm.tm); /* 1 000 000 microseconds to a second. */ tm.microsec = t.rt.tv_usec; return tm; } struct realtm utc_realtime(realtime_t t) { struct realtm tm; zero(&tm); gmtime_r(&t.rt.tv_sec, &tm.tm); /* 1 000 000 microseconds to a second. */ tm.microsec = t.rt.tv_usec; return tm; } /* * Display a date either in local or UTC time */ size_t jam_realtime(jambuf_t *buf, const realtime_t rtm, bool utc) { static const char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; size_t s = 0; if (is_realtime_epoch(rtm)) { s += jam(buf, "--- -- --:--:--%s----", (utc) ? " UTC " : " "); } else { struct realtm t = (utc ? utc_realtime : local_realtime)(rtm); s += jam(buf, "%s %02d %02d:%02d:%02d%s%04d", months[t.tm.tm_mon], t.tm.tm_mday, t.tm.tm_hour, t.tm.tm_min, t.tm.tm_sec, (utc) ? " UTC " : " ", t.tm.tm_year + 1900); } return s; } const char *str_realtime(realtime_t r, bool utc, realtime_buf *buf) { jambuf_t jambuf = ARRAY_AS_JAMBUF(buf->buf); jam_realtime(&jambuf, r, utc); return buf->buf; } libreswan-3.32/lib/libswan/refcnt.c000066400000000000000000000033721365625662500173060ustar00rootroot00000000000000/* reference counting, for libreswan * * Copyright (C) 2015-2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include "refcnt.h" #define DEBUG_LOG(OLD_COUNT, WHAT) \ dbg("%s %s@%p(%u->%u) "PRI_WHERE"", \ WHAT, what, pointer, OLD_COUNT, refcnt->count, \ pri_where(where)) void refcnt_init(const char *what, const void *pointer, refcnt_t *refcnt, where_t where) { /* on main thread */ if (refcnt->count != 0) { log_pexpect(where, "refcnt for %s@%p should have been 0 initialized", what, pointer); } unsigned old = refcnt->count++; DEBUG_LOG(old, "newref"); } void refcnt_add(const char *what, const void *pointer, refcnt_t *refcnt, where_t where) { /* on main thread */ if (refcnt->count == 0) { log_pexpect(where, "refcnt for %s@%p should have been non-0", what, pointer); } unsigned old = refcnt->count++; DEBUG_LOG(old, "addref"); } bool refcnt_delete(const char *what, const void *pointer, refcnt_t *refcnt, where_t where) { /* on main thread */ unsigned old; if (refcnt->count == 0) { log_pexpect(where, "refcnt for %s@%p should have been non-0", what, pointer); old = 0; } else { old = refcnt->count--; } DEBUG_LOG(old, "delref"); return refcnt->count == 0; } libreswan-3.32/lib/libswan/reqid.c000066400000000000000000000035611365625662500171310ustar00rootroot00000000000000/* reqids, for libreswan * * Copyright (C) 2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include "reqid.h" #include "libreswan/passert.h" /* * generate a base reqid for automatic keying * * We are actually allocating a group of four contiguous * numbers: one is used for each SA in an SA bundle. * * - must not be in range 0 to IPSEC_MANUAL_REQID_MAX * * - is a multiple of 4 (we are actually allocating four requids: see * requid_ah, reqid_esp, reqid_ipcomp) * * - does not duplicate any currently in use (its assumed that pluto * will crash before the 24-bit integer - one million connections - * rolls over). * * NOTE: comments seems to lie, we use same reqid for the * ESP inbound and outbound. * * XXX: Could just as easily return: * * IPSEC_MANUAL_REQID_ROOF + connection.nr * 4 */ reqid_t gen_reqid(void) { /* 0x3fff+1==16384 is the first reqid we will use when not specified manually */ static reqid_t global_reqids = IPSEC_MANUAL_REQID_MAX+1; global_reqids += 4; passert(global_reqids != 0); /* 16 000 000 roll over */ passert(global_reqids % 4 == 0); /* allocate 4 at a time */ return global_reqids; } reqid_t reqid_ah(reqid_t r) { return r; } reqid_t reqid_esp(reqid_t r) { return r <= IPSEC_MANUAL_REQID_MAX ? r : (r + 1); } reqid_t reqid_ipcomp(reqid_t r) { return r <= IPSEC_MANUAL_REQID_MAX ? r : (r + 2); } libreswan-3.32/lib/libswan/role.c000066400000000000000000000024021365625662500167570ustar00rootroot00000000000000/* sa_role names, for libreswan * * Copyright (C) 2018 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include "keywords.h" #include "constants.h" struct keyword sa_role_keywords[] = { #define S(E, H) [SA_##E] = { .name = "SA_" #E, .sname = #E, .value = SA_##E, .details = H, } S(INITIATOR, "SA initiator"), S(RESPONDER, "SA responder"), #undef S }; struct keywords sa_role_names = SPARSE_KEYWORDS("SA role", sa_role_keywords); struct keyword message_role_keywords[] = { #define S(E, H) [MESSAGE_##E] = { .name = "MESSAGE_" #E, .sname = #E, .value = MESSAGE_##E, .details = H, } S(REQUEST, "message request"), S(RESPONSE, "message response"), #undef S }; struct keywords message_role_names = SPARSE_KEYWORDS("message role", message_role_keywords); libreswan-3.32/lib/libswan/sameaddr.3.xml000066400000000000000000000143701365625662500203240ustar00rootroot00000000000000 PaulWoutersplaceholder to suppress warning IPSEC_SAMEADDR 3 28 Nov 2000 libreswan Executable programs ipsec sameaddr ipsec addrcmp ipsec samesubnet ipsec addrinsubnet ipsec subnetinsubnet ipsec subnetishost ipsec samesaid ipsec sameaddrtype ipsec samesubnettype do comparisons for addresses, subnets, SA IDs and address families #include <libreswan.h> int sameaddr const ip_address * a const ip_address * b int addrcmp const ip_address * a const ip_address * b int samesubnet const ip_subnet * a const ip_subnet * b int addrinsubnet const ip_address * a const ip_subnet * s int subnetinsubnet const ip_subnet * a const ip_subnet * b int subnetishost const ip_subnet * s int samesaid const ip_said * a const ip_said * b int sameaddrtype const ip_address * a const ip_address * b int samesubnettype const ip_subnet * a const ip_subnet * b DESCRIPTION These functions do various comparisons and tests on the ip_address type and ip_subnet types. Sameaddr returns non-zero if addresses a and b are identical, and 0 otherwise. Addresses of different families are never identical. Addrcmp returns , 0, or 1 respectively if address a is less than, equal to, or greater than b. If they are not of the same address family, they are never equal; the ordering reported in this case is arbitrary (and probably not useful) but consistent. Samesubnet returns non-zero if subnets a and b are identical, and 0 otherwise. Subnets of different address families are never identical. Addrinsubnet returns non-zero if address a is within subnet s and 0 otherwise. An address is never within a subnet of a different address family. Subnetinsubnet returns non-zero if subnet a is a subset of subnet b and 0 otherwise. A subnet is deemed to be a subset of itself. A subnet is never a subset of another subnet if their address families differ. Subnetishost returns non-zero if subnet s is in fact only a single host, and 0 otherwise. Samesaid returns non-zero if SA IDs a and b are identical, and 0 otherwise. Sameaddrtype returns non-zero if addresses a and b are of the same address family, and 0 otherwise. Samesubnettype returns non-zero if subnets a and b are of the same address family, and 0 otherwise. SEE ALSO inet3, ipsec_initaddr3 HISTORY Written for the FreeS/WAN project by Henry Spencer. libreswan-3.32/lib/libswan/sameaddr.c000066400000000000000000000064631365625662500176110ustar00rootroot00000000000000/* * comparisons * * Copyright (C) 2000 Henry Spencer. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. */ #include /* for memcmp() */ #include "ip_address.h" #include "ip_said.h" #include "ip_subnet.h" #include "ip_info.h" #include "libreswan/passert.h" static bool samenbits(const ip_address *a, const ip_address *b, int n); /* * addrcmp - compare two addresses * Caution, the order of the tests is subtle: doing type test before * size test can yield cases where ac. */ int /* like memcmp */ addrcmp(const ip_address *a, const ip_address *b) { const struct ip_info *at = address_type(a); const struct ip_info *bt = address_type(b); if (at == NULL && bt == NULL) { /* XXX: see old code */ return 0; } else if (at == NULL) { /* AF_UNSPECaf < bt->af) ? -1 : 1; } else { shunk_t as = address_as_shunk(a); shunk_t bs = address_as_shunk(b); passert(as.len == bs.len); int c = memcmp(as.ptr, bs.ptr, as.len); if (c != 0) return (c < 0) ? -1 : 1; return 0; } } /* * sameaddr - are two addresses the same? */ bool sameaddr(const ip_address *a, const ip_address *b) { return addrcmp(a, b) == 0; } /* * samesubnet - are two subnets the same? */ bool samesubnet(const ip_subnet * a, const ip_subnet *b) { return sameaddr(&a->addr, &b->addr) && /* also does type check */ a->maskbits == b->maskbits; } /* * subnetishost - is a subnet in fact a single host? */ bool subnetishost(const ip_subnet *a) { const struct ip_info *afi = subnet_type(a); return a->maskbits == afi->mask_cnt; } /* * addrinsubnet - is this address in this subnet? */ bool addrinsubnet(const ip_address *a, const ip_subnet *s) { return address_type(a) == subnet_type(s) && samenbits(a, &s->addr, s->maskbits); } /* * subnetinsubnet - is one subnet within another? */ bool subnetinsubnet(const ip_subnet *a, const ip_subnet *b) { return addrinsubnet(&a->addr, b) && a->maskbits >= b->maskbits; /* a is not bigger than b */ } /* * samenbits - do two addresses have the same first n bits? */ static bool samenbits(const ip_address *a, const ip_address *b, int nbits) { const struct ip_info *at = address_type(a); const struct ip_info *bt = address_type(b); if (at == NULL || bt == NULL) { return false; } if (at != bt) { return false; } shunk_t as = address_as_shunk(a); const uint8_t *ap = as.ptr; /* cast const void * */ passert(as.len > 0); int n = as.len; shunk_t bs = address_as_shunk(b); const uint8_t *bp = bs.ptr; /* cast const void * */ passert(as.len == bs.len); if (nbits > (int)n * 8) return false; /* "can't happen" */ for (; nbits >= 8 && *ap == *bp; nbits -= 8, ap++, bp++) continue; return nbits < 8 && (*ap ^ *bp) >> (8 - nbits) == 0x00; } libreswan-3.32/lib/libswan/secitem_chunk.c000066400000000000000000000025731365625662500206500ustar00rootroot00000000000000/* * SECItem<>chunk conversions, for libreswan * * Copyright (C) 2016 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include "nss.h" #include "secrets.h" SECItem same_chunk_as_secitem(chunk_t chunk, SECItemType type) { SECItem si = { .type = type, .data = chunk.ptr, .len = chunk.len, }; return si; } chunk_t same_secitem_as_chunk(SECItem si) { chunk_t chunk = { .ptr = si.data, .len = si.len, }; return chunk; } chunk_t clone_secitem_as_chunk(SECItem si, const char *name) { chunk_t chunk = { .len = si.len, .ptr = clone_bytes(si.data, si.len, name), }; return chunk; } #if 0 /* not used (yet?) */ SECItem clone_chunk_as_secitem(chunk_t chunk, SECItemType type, const char *name) { SECItem si = { .type = type, .len = chunk.len, .data = clone_bytes(chunk.ptr, chunk.len, name), }; return si; } #endif libreswan-3.32/lib/libswan/secrets.c000066400000000000000000001307361365625662500175020ustar00rootroot00000000000000/* * mechanisms for preshared keys (public, private, and preshared secrets) * * this is the library for reading (and later, writing!) the ipsec.secrets * files. * * Copyright (C) 1998-2004 D. Hugh Redelmeier. * Copyright (C) 2005 Michael Richardson * Copyright (C) 2009-2012 Avesh Agarwal * Copyright (C) 2012-2015 Paul Wouters * Copyright (C) 2016-2019 Andrew Cagney * Copyright (C) 2017 Vukasin Karadzic * Copyright (C) 2018 Sahana Prasad * Copyright (C) 2019 Paul Wouters * Copyright (C) 2019 D. Hugh Redelmeier * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include /* pthread.h must be first include file */ #include #include #include #include #include #include #include #include #include #include #include /* missing from on old systems */ #include #ifndef GLOB_ABORTED #define GLOB_ABORTED GLOB_ABEND /* fix for old versions */ #endif #include "sysdep.h" #include "lswlog.h" #include "constants.h" #include "lswalloc.h" #include "id.h" #include "x509.h" #include "secrets.h" #include "certs.h" #include "lex.h" #include #include #include #include #include #include "lswconf.h" #include "lswnss.h" #include "ip_info.h" /* this does not belong here, but leave it here for now */ const struct id empty_id; /* ID_NONE */ struct fld { const char *name; ssize_t offset; }; static const struct fld RSA_private_field[] = { { .name = "Modulus", .offset = offsetof(struct RSA_private_key, pub.n), }, { .name = "PublicExponent", .offset = offsetof(struct RSA_private_key, pub.e), }, { .name = "PrivateExponent", .offset = -1, }, { .name = "Prime1", .offset = -1, }, { .name = "Prime2", .offset = -1, }, { .name = "Exponent1", .offset = -1, }, { .name = "Exponent2", .offset = -1, }, { .name = "Coefficient", .offset = -1, }, { .name = "CKAIDNSS", .offset = -1, }, }; static void lsw_process_secrets_file(struct secret **psecrets, const char *file_pat); static err_t RSA_public_key_sanity(const struct RSA_private_key *k) { /* * PKCS#1 1.5 section 6 requires modulus to have at least 12 octets. * * We actually require more (for security). */ if (k->pub.k < RSA_MIN_OCTETS) return RSA_MIN_OCTETS_UGH; /* we picked a max modulus size to simplify buffer allocation */ if (k->pub.k > RSA_MAX_OCTETS) return RSA_MAX_OCTETS_UGH; return NULL; } struct secret { struct secret *next; struct id_list *ids; struct private_key_stuff pks; }; struct private_key_stuff *lsw_get_pks(struct secret *s) { return &s->pks; } struct id_list *lsw_get_idlist(const struct secret *s) { return s->ids; } /* * forms the keyid from the public exponent e and modulus n */ void form_keyid(chunk_t e, chunk_t n, char *keyid, unsigned *keysize) { /* eliminate leading zero byte in modulus from ASN.1 coding */ if (*n.ptr == 0x00) { /* * The "adjusted" length of modulus n in octets: * [RSA_MIN_OCTETS, RSA_MAX_OCTETS]. * * According to form_keyid() this is the modulus length * less any leading byte added by DER encoding. * * The adjusted length is used in sign_hash() as the * signature length - wouldn't PK11_SignatureLen be * better? * * The adjusted length is used in * same_RSA_public_key() as part of comparing two keys * - but wouldn't that be redundant? The direct n==n * test would pick up the difference. */ DBG(DBG_CRYPT, DBG_log("XXX: adjusted modulus length %zu->%zu", n.len, n.len - 1)); n.ptr++; n.len--; } /* form the Libreswan keyid */ keyid[0] = '\0'; /* in case of splitkeytoid failure */ splitkeytoid(e.ptr, e.len, n.ptr, n.len, keyid, KEYID_BUF); /* return the RSA modulus size in octets */ *keysize = n.len; } static void form_keyid_from_nss(SECItem e, SECItem n, char *keyid, unsigned *keysize) { /* eliminate leading zero byte in modulus from ASN.1 coding */ if (*n.data == 0x00) { /* * The "adjusted" length of modulus n in octets: * [RSA_MIN_OCTETS, RSA_MAX_OCTETS]. * * According to form_keyid() this is the modulus length * less any leading byte added by DER encoding. * * The adjusted length is used in sign_hash() as the * signature length - wouldn't PK11_SignatureLen be * better? * * The adjusted length is used in * same_RSA_public_key() as part of comparing two keys * - but wouldn't that be redundant? The direct n==n * test would pick up the difference. */ DBG(DBG_CRYPT, DBG_log("XXX: adjusted modulus length %u->%u", n.len, n.len - 1)); n.data++; n.len--; } /* form the Libreswan keyid */ keyid[0] = '\0'; /* in case of splitkeytoid failure */ splitkeytoid(e.data, e.len, n.data, n.len, keyid, KEYID_BUF); /* return the RSA modulus size in octets */ *keysize = n.len; } static void free_RSA_public_content(struct RSA_public_key *rsa) { freeanychunk(rsa->n); freeanychunk(rsa->e); freeanyckaid(&rsa->ckaid); } static void free_RSA_pubkey_content(union pubkey_content *u) { free_RSA_public_content(&u->rsa); } static err_t unpack_RSA_pubkey_content(union pubkey_content *u, chunk_t pubkey) { return unpack_RSA_public_key(&u->rsa, &pubkey); } const struct pubkey_type pubkey_type_rsa = { .alg = PUBKEY_ALG_RSA, .name = "RSA", .private_key_kind = PKK_RSA, .free_pubkey_content = free_RSA_pubkey_content, .unpack_pubkey_content = unpack_RSA_pubkey_content, }; static void free_ECDSA_public_content(struct ECDSA_public_key *ecdsa) { freeanychunk(ecdsa->pub); /* ??? what about ecdsa->pub.{ecParams,version,ckaid}? */ } static void free_ECDSA_pubkey_content(union pubkey_content *u) { free_ECDSA_public_content(&u->ecdsa); } static err_t unpack_ECDSA_pubkey_content(union pubkey_content *u, chunk_t pubkey) { return unpack_ECDSA_public_key(&u->ecdsa, &pubkey); } const struct pubkey_type pubkey_type_ecdsa = { .alg = PUBKEY_ALG_ECDSA, .name = "ECDSA", .private_key_kind = PKK_ECDSA, .free_pubkey_content = free_ECDSA_pubkey_content, .unpack_pubkey_content = unpack_ECDSA_pubkey_content, }; const struct pubkey_type *pubkey_alg_type(enum pubkey_alg alg) { static const struct pubkey_type *pubkey_types[] = { [PUBKEY_ALG_RSA] = &pubkey_type_rsa, [PUBKEY_ALG_ECDSA] = &pubkey_type_ecdsa, }; passert(alg < elemsof(pubkey_types)); const struct pubkey_type *type = pubkey_types[alg]; pexpect(type != NULL); return type; } /* * XXX: Go for a simplicity - a switch is easier than adding to * pubkey_type - especially when the fields could end up moving to * struct pubkey proper (we can but dream). */ const char *pubkey_keyid(const struct pubkey *pk) { switch (pk->type->alg) { case PUBKEY_ALG_RSA: return pk->u.rsa.keyid; case PUBKEY_ALG_ECDSA: return pk->u.ecdsa.keyid; default: bad_case(pk->type->alg); } } const ckaid_t *pubkey_ckaid(const struct pubkey *pk) { switch (pk->type->alg) { case PUBKEY_ALG_RSA: return &pk->u.rsa.ckaid; case PUBKEY_ALG_ECDSA: return &pk->u.ecdsa.ckaid; default: bad_case(pk->type->alg); } } unsigned pubkey_size(const struct pubkey *pk) { switch (pk->type->alg) { case PUBKEY_ALG_RSA: return pk->u.rsa.k; case PUBKEY_ALG_ECDSA: return pk->u.ecdsa.k; default: bad_case(pk->type->alg); } } /* * free a public key struct */ void free_public_key(struct pubkey *pk) { free_id_content(&pk->id); freeanychunk(pk->issuer); /* algorithm-specific freeing */ pk->type->free_pubkey_content(&pk->u); pfree(pk); } struct secret *lsw_foreach_secret(struct secret *secrets, secret_eval func, void *uservoid) { for (struct secret *s = secrets; s != NULL; s = s->next) { struct private_key_stuff *pks = &s->pks; int result = (*func)(s, pks, uservoid); if (result == 0) return s; if (result == -1) break; } return NULL; } struct secret_byid { enum PrivateKeyKind kind; const struct pubkey *my_public_key; }; static int lsw_check_secret_byid(struct secret *secret UNUSED, struct private_key_stuff *pks, void *uservoid) { struct secret_byid *sb = (struct secret_byid *)uservoid; DBG(DBG_CONTROL, DBG_log("searching for certificate %s:%s vs %s:%s", enum_name(&pkk_names, pks->kind), (pks->kind == PKK_RSA ? pks->u.RSA_private_key.pub.keyid : pks->kind == PKK_ECDSA ? pks->u.ECDSA_private_key.pub.keyid : "N/A"), enum_name(&pkk_names, sb->kind), pks->kind == PKK_RSA ? sb->my_public_key->u.rsa.keyid : pks->kind == PKK_ECDSA ? sb->my_public_key->u.ecdsa.keyid : "unknown public key algorithm"); ); if (pks->kind == sb->kind) { if (pks->kind == PKK_RSA && same_RSA_public_key(&pks->u.RSA_private_key.pub, &sb->my_public_key->u.rsa)) return 0; /* TODO */ if (pks->kind == PKK_ECDSA /* && placerholder for ECDSA */) return 0; } return 1; } struct secret *lsw_find_secret_by_public_key(struct secret *secrets, const struct pubkey *my_public_key, enum PrivateKeyKind kind) { struct secret_byid sb; sb.kind = kind; sb.my_public_key = my_public_key; return lsw_foreach_secret(secrets, lsw_check_secret_byid, &sb); } struct secret *lsw_find_secret_by_id(struct secret *secrets, enum PrivateKeyKind kind, const struct id *local_id, const struct id *remote_id, bool asym) { enum { match_none = 000, /* bits */ match_default = 001, match_any = 002, match_remote = 004, match_local = 010 }; unsigned int best_match = match_none; struct secret *best = NULL; for (struct secret *s = secrets; s != NULL; s = s->next) { if (DBGP(DBG_BASE)) { id_buf idl; DBG_log("line %d: key type %s(%s) to type %s", s->pks.line, enum_name(&pkk_names, kind), str_id(local_id, &idl), enum_name(&pkk_names, s->pks.kind)); } if (s->pks.kind == kind) { unsigned int match = match_none; if (s->ids == NULL) { /* * a default (signified by lack of ids): * accept if no more specific match found */ match = match_default; } else { /* check if both ends match ids */ struct id_list *i; int idnum = 0; for (i = s->ids; i != NULL; i = i->next) { idnum++; if (any_id(&i->id)) { /* * match any will * automatically match * local and remote so * treat it as its own * match type so that * specific matches * get a higher * "match" value and * are used in * preference to "any" * matches. */ match |= match_any; } else { if (same_id(&i->id, local_id)) { match |= match_local; } if (remote_id != NULL && same_id(&i->id, remote_id)) { match |= match_remote; } } if (DBGP(DBG_BASE)) { id_buf idi; id_buf idl; id_buf idr; DBG_log("%d: compared key %s to %s / %s -> 0%02o", idnum, str_id(&i->id, &idi), str_id(local_id, &idl), (remote_id == NULL ? "" : str_id(remote_id, &idr)), match); } } /* * If our end matched the only id in the list, * default to matching any peer. * A more specific match will trump this. */ if (match == match_local && s->ids->next == NULL) match |= match_default; } DBG(DBG_CONTROL, DBG_log("line %d: match=0%02o", s->pks.line, match); ); switch (match) { case match_local: /* * if this is an asymmetric * (eg. public key) system, allow * this-side-only match to count, even * if there are other ids in the list. */ if (!asym) break; /* FALLTHROUGH */ case match_default: /* default all */ case match_any: /* a wildcard */ case match_local | match_default: /* default peer */ case match_local | match_any: /* %any/0.0.0.0 and local */ case match_remote | match_any: /* %any/0.0.0.0 and remote */ case match_local | match_remote: /* explicit */ if (match == best_match) { /* * two good matches are equally good: * do they agree? */ bool same = FALSE; switch (kind) { case PKK_NULL: same = TRUE; break; case PKK_PSK: same = chunk_eq(s->pks.u.preshared_secret, best->pks.u.preshared_secret); break; case PKK_RSA: /* * Dirty trick: since we have * code to compare RSA public * keys, but not private keys, * we make the assumption that * equal public keys mean equal * private keys. This ought to * work. */ same = same_RSA_public_key( &s->pks.u.RSA_private_key.pub, &best->pks.u.RSA_private_key.pub); break; case PKK_ECDSA: /* there are no ECDSA kind of secrets */ /* ??? this seems not to be the case */ break; case PKK_XAUTH: /* * We don't support this yet, * but no need to die */ break; case PKK_PPK: same = chunk_eq(s->pks.ppk, best->pks.ppk); break; default: bad_case(kind); } if (!same) { DBG(DBG_CONTROL, DBG_log("multiple ipsec.secrets entries with distinct secrets match endpoints: first secret used")); /* * list is backwards: * take latest in list */ best = s; } } else if (match > best_match) { DBG(DBG_CONTROL, DBG_log("match 0%02o beats previous best_match 0%02o match=%p (line=%d)", match, best_match, s, s->pks.line); ); /* this is the best match so far */ best_match = match; best = s; } else { DBG(DBG_CONTROL, DBG_log("match 0%02o loses to best_match 0%02o", match, best_match); ); } } } } DBG(DBG_CONTROL, DBG_log("concluding with best_match=0%02o best=%p (lineno=%d)", best_match, best, best == NULL ? -1 : best->pks.line); ); return best; } /* * check the existence of an RSA private key matching an RSA public */ bool lsw_has_private_rawkey(const struct secret *secrets, const struct pubkey *pk) { for (const struct secret *s = secrets; s != NULL; s = s->next) { if (s->pks.kind == PKK_RSA && same_RSA_public_key(&s->pks.u.RSA_private_key.pub, &pk->u.rsa)) { return TRUE; } } return FALSE; } /* * digest a secrets file * * The file is a sequence of records. A record is a maximal sequence of * tokens such that the first, and only the first, is in the first column * of a line. * * Tokens are generally separated by whitespace and are key words, ids, * strings, or data suitable for ttodata(3). As a nod to convention, * a trailing ":" on what would otherwise be a token is taken as a * separate token. If preceded by whitespace, a "#" is taken as starting * a comment: it and the rest of the line are ignored. * * One kind of record is an include directive. It starts with "include". * The filename is the only other token in the record. * If the filename does not start with /, it is taken to * be relative to the directory containing the current file. * * The other kind of record describes a key. It starts with a * sequence of ids and ends with key information. Each id * is an IP address, a Fully Qualified Domain Name (which will immediately * be resolved), or @FQDN which will be left as a name. * * The form starts the key part with a ":". * * For Preshared Key, use the "PSK" keyword, and follow it by a string * or a data token suitable for ttodata(3). * * For raw RSA Keys in NSS, use the "RSA" keyword, followed by a * brace-enclosed list of key field keywords and data values. * The data values are large integers to be decoded by ttodata(3). * The fields are a subset of those used by BIND 8.2 and have the * same names. * * For XAUTH passwords, use @username followed by ":XAUTH" followed by the password * * For Post-Quantum Preshared Keys, use the "PPKS" keyword if the PPK is static. * * PIN for smartcard is no longer supported - use NSS with smartcards */ /* parse PSK from file */ static err_t lsw_process_psk_secret(chunk_t *psk) { err_t ugh = NULL; if (*flp->tok == '"' || *flp->tok == '\'') { size_t len = flp->cur - flp->tok - 2; if (len < 8) { loglog(RC_LOG_SERIOUS, "WARNING: using a weak secret (PSK)"); } *psk = clone_bytes_as_chunk(flp->tok + 1, len, "PSK"); (void) shift(); } else { char buf[RSA_MAX_ENCODING_BYTES]; /* * limit on size of * binary * representation * of key */ size_t sz; char diag_space[TTODATAV_BUF]; ugh = ttodatav(flp->tok, flp->cur - flp->tok, 0, buf, sizeof(buf), &sz, diag_space, sizeof(diag_space), TTODATAV_SPACECOUNTS); if (ugh != NULL) { /* ttodata didn't like PSK data */ ugh = builddiag("PSK data malformed (%s): %s", ugh, flp->tok); } else { *psk = clone_bytes_as_chunk(buf, sz, "PSK"); (void) shift(); } } DBG(DBG_CONTROL, DBG_log("Processing PSK at line %d: %s", flp->lino, ugh == NULL ? "passed" : ugh); ); return ugh; } /* parse XAUTH secret from file */ static err_t lsw_process_xauth_secret(chunk_t *xauth) { err_t ugh = NULL; if (*flp->tok == '"' || *flp->tok == '\'') { *xauth = clone_bytes_as_chunk(flp->tok + 1, flp->cur - flp->tok - 2, "XAUTH"); (void) shift(); } else { char buf[RSA_MAX_ENCODING_BYTES]; /* * limit on size of * binary * representation * of key */ size_t sz; char diag_space[TTODATAV_BUF]; ugh = ttodatav(flp->tok, flp->cur - flp->tok, 0, buf, sizeof(buf), &sz, diag_space, sizeof(diag_space), TTODATAV_SPACECOUNTS); if (ugh != NULL) { /* ttodata didn't like PSK data */ ugh = builddiag("PSK data malformed (%s): %s", ugh, flp->tok); } else { *xauth = clone_bytes_as_chunk(buf, sz, "XAUTH"); (void) shift(); } } DBG(DBG_CONTROL, DBG_log("Processing XAUTH at line %d: %s", flp->lino, ugh == NULL ? "passed" : ugh); ); return ugh; } /* parse static PPK */ static err_t lsw_process_ppk_static_secret(chunk_t *ppk, chunk_t *ppk_id) { err_t ugh = NULL; if (*flp->tok == '"' || *flp->tok == '\'') { size_t len = flp->cur - flp->tok - 2; *ppk_id = clone_bytes_as_chunk(flp->tok + 1, len, "PPK ID"); } else { ugh = "No quotation marks found. PPK ID should be in quotation marks"; return ugh; } if (!shift()) { ugh = "No PPK found. PPK should be specified after PPK ID"; freeanychunk(*ppk_id); return ugh; } if (*flp->tok == '"' || *flp->tok == '\'') { size_t len = flp->cur - flp->tok - 2; *ppk = clone_bytes_as_chunk(flp->tok + 1, len, "PPK"); (void) shift(); } else { char buf[RSA_MAX_ENCODING_BYTES]; /* * limit on size of * binary * representation * of key */ size_t sz; char diag_space[TTODATAV_BUF]; ugh = ttodatav(flp->tok, flp->cur - flp->tok, 0, buf, sizeof(buf), &sz, diag_space, sizeof(diag_space), TTODATAV_SPACECOUNTS); if (ugh != NULL) { /* ttodata didn't like PPK data */ ugh = builddiag("PPK data malformed (%s): %s", ugh, flp->tok); freeanychunk(*ppk_id); } else { *ppk = clone_bytes_as_chunk(buf, sz, "PPK"); (void) shift(); } } DBG(DBG_CONTROL, DBG_log("Processing PPK at line %d: %s", flp->lino, ugh == NULL ? "passed" : ugh); ); return ugh; } struct secret *lsw_get_ppk_by_id(struct secret *s, chunk_t ppk_id) { while (s != NULL) { struct private_key_stuff pks = s->pks; if (pks.kind == PKK_PPK && chunk_eq(pks.ppk_id, ppk_id)) return s; s = s->next; } return NULL; } /* * Parse fields of RSA private key. * * A braced list of keyword and value pairs. * At the moment, each field is required, in order. * The fields come from BIND 8.2's representation */ static err_t lsw_process_rsa_secret(struct RSA_private_key *rsak) { passert(tokeq("{")); while (1) { if (!shift()) { return "premature end of RSA key"; } if (tokeq("}")) { break; } const struct fld *p = NULL; const struct fld *f; for (f = RSA_private_field; f < RSA_private_field + elemsof(RSA_private_field); f++) { if (tokeqword(f->name)) { p = f; break; } } if (p == NULL) { return builddiag("RSA keyword '%s' not recognised", flp->tok); } if (!shift()) { return "premature end of RSA key"; } /* skip optional ':' */ if (tokeq(":") && !shift()) { return "premature end of RSA key"; } /* Binary Value of key field */ unsigned char bv[RSA_MAX_ENCODING_BYTES]; size_t bvlen; char diag_space[TTODATAV_BUF]; err_t ugh = ttodatav(flp->tok, flp->cur - flp->tok, 0, (char *)bv, sizeof(bv), &bvlen, diag_space, sizeof(diag_space), TTODATAV_SPACECOUNTS); if (ugh != NULL) { /* in RSA key, ttodata didn't like */ return builddiag("RSA data malformed (%s): %s", ugh, flp->tok); } passert(sizeof(bv) >= bvlen); /* dispose of the data */ if (p->offset >= 0) { DBG(DBG_CONTROLMORE, DBG_log("saving %s", p->name)); DBG(DBG_PRIVATE, DBG_dump(p->name, bv, bvlen)); chunk_t *n = (chunk_t*) ((char *)rsak + p->offset); *n = clone_bytes_as_chunk(bv, bvlen, p->name); DBG(DBG_PRIVATE, DBG_dump_hunk(p->name, *n)); } else { DBG(DBG_CONTROL, DBG_log("ignoring %s", p->name)); } } passert(tokeq("}")); if (shift()) { return "malformed end of RSA private key -- unexpected token after '}'"; } /* * Check that all required fields are present. */ const struct fld *p; for (p = RSA_private_field; p < &RSA_private_field[elemsof(RSA_private_field)]; p++) { if (p->offset >= 0) { chunk_t *n = (chunk_t*) ((char *)rsak + p->offset); if (n->len == 0) { return builddiag("field '%s' either missing or empty", p->name); } } } rsak->pub.k = rsak->pub.n.len; rsak->pub.keyid[0] = '\0'; /* in case of failure */ if (rsak->pub.e.len > 0 || rsak->pub.n.len >0) { splitkeytoid(rsak->pub.e.ptr, rsak->pub.e.len, rsak->pub.n.ptr, rsak->pub.n.len, rsak->pub.keyid, sizeof(rsak->pub.keyid)); } /* Finally, the CKAID */ err_t err = form_ckaid_rsa(rsak->pub.n, &rsak->pub.ckaid); if (err) { /* let caller recover from mess */ return err; } return RSA_public_key_sanity(rsak); } static pthread_mutex_t certs_and_keys_mutex = PTHREAD_MUTEX_INITIALIZER; /* * lock access to my certs and keys */ static void lock_certs_and_keys(const char *who) { pthread_mutex_lock(&certs_and_keys_mutex); dbg("certs and keys locked by '%s'", who); } /* * unlock access to my certs and keys */ static void unlock_certs_and_keys(const char *who) { dbg("certs and keys unlocked by '%s'", who); pthread_mutex_unlock(&certs_and_keys_mutex); } static void add_secret(struct secret **slist, struct secret *s, const char *story) { /* if the id list is empty, add two empty ids */ if (s->ids == NULL) { struct id_list *idl = alloc_bytes(sizeof(struct id_list), "id list"); idl->next = NULL; idl->id = empty_id; idl->id.kind = ID_NONE; idl->id.ip_addr = address_any(&ipv4_info); struct id_list *idl2 = alloc_bytes(sizeof(struct id_list), "id list"); idl2->next = idl; idl2->id = empty_id; idl2->id.kind = ID_NONE; idl2->id.ip_addr = address_any(&ipv4_info); s->ids = idl2; } lock_certs_and_keys(story); s->next = *slist; *slist = s; unlock_certs_and_keys(story); } static void process_secret(struct secret **psecrets, struct secret *s) { err_t ugh = NULL; if (tokeqword("psk")) { s->pks.kind = PKK_PSK; /* preshared key: quoted string or ttodata format */ ugh = !shift() ? "ERROR: unexpected end of record in PSK" : lsw_process_psk_secret(&s->pks.u.preshared_secret); } else if (tokeqword("xauth")) { /* xauth key: quoted string or ttodata format */ s->pks.kind = PKK_XAUTH; ugh = !shift() ? "ERROR: unexpected end of record in PSK" : lsw_process_xauth_secret(&s->pks.u.preshared_secret); } else if (tokeqword("rsa")) { /* * RSA key: the fun begins. * A braced list of keyword and value pairs. */ s->pks.kind = PKK_RSA; if (!shift()) { ugh = "ERROR: bad RSA key syntax"; } else if (tokeq("{")) { /* raw RSA key in NSS */ ugh = lsw_process_rsa_secret(&s->pks.u.RSA_private_key); } else { /* RSA key in certificate in NSS */ ugh = "WARNING: The :RSA secrets entries for X.509 certificates are no longer needed"; } if (ugh == NULL) { libreswan_log("loaded private key for keyid: %s:%s", enum_name(&pkk_names, s->pks.kind), s->pks.u.RSA_private_key.pub.keyid); } } else if (tokeqword("ppks")) { s->pks.kind = PKK_PPK; ugh = !shift() ? "ERROR: unexpected end of record in static PPK" : lsw_process_ppk_static_secret(&s->pks.ppk, &s->pks.ppk_id); } else if (tokeqword("pin")) { ugh = "ERROR: keyword 'pin' obsoleted, please use NSS for smartcard support"; } else { ugh = builddiag("ERROR: unrecognized key format: %s", flp->tok); } if (ugh != NULL) { loglog(RC_LOG_SERIOUS, "\"%s\" line %d: %s", flp->filename, flp->lino, ugh); /* free id's that should have been allocated */ if (s->ids != NULL) { struct id_list *i, *ni; for (i = s->ids; i != NULL; i = ni) { ni = i->next; /* grab before freeing i */ free_id_content(&i->id); pfree(i); } } /* finally free s */ pfree(s); } else if (flushline("expected record boundary in key")) { /* gauntlet has been run: install new secret */ add_secret(psecrets, s, "process_secret"); } } static void lsw_process_secret_records(struct secret **psecrets) { /* const struct secret *secret = *psecrets; */ /* read records from ipsec.secrets and load them into our table */ for (;; ) { (void)flushline(NULL); /* silently ditch leftovers, if any */ if (flp->bdry == B_file) break; flp->bdry = B_none; /* eat the Record Boundary */ (void)shift(); /* get real first token */ if (tokeqword("include")) { /* an include directive */ char fn[MAX_TOK_LEN]; /* * space for filename * (I hope) */ char *p = fn; char *end_prefix = strrchr(flp->filename, '/'); if (!shift()) { loglog(RC_LOG_SERIOUS, "\"%s\" line %d: unexpected end of include directive", flp->filename, flp->lino); continue; /* abandon this record */ } /* * if path is relative and including file's pathname has * a non-empty dirname, prefix this path with that * dirname. */ if (flp->tok[0] != '/' && end_prefix != NULL) { size_t pl = end_prefix - flp->filename + 1; /* * "clamp" length to prevent problems now; * will be rediscovered and reported later. */ if (pl > sizeof(fn)) pl = sizeof(fn); memcpy(fn, flp->filename, pl); p += pl; } if (flp->cur - flp->tok >= &fn[sizeof(fn)] - p) { loglog(RC_LOG_SERIOUS, "\"%s\" line %d: include pathname too long", flp->filename, flp->lino); continue; /* abandon this record */ } /* * The above test checks that there is enough space for strcpy * but clang 3.4 thinks the destination will overflow. * strcpy(p, flp->tok); * Rewrite as a memcpy in the hope of calming it. */ memcpy(p, flp->tok, flp->cur - flp->tok + 1); (void) shift(); /* move to Record Boundary, we hope */ if (flushline("ignoring malformed INCLUDE -- expected Record Boundary after filename")) { lsw_process_secrets_file(psecrets, fn); flp->tok = NULL; /* redundant? */ } } else { /* expecting a list of indices and then the key info */ struct secret *s = alloc_thing(struct secret, "secret"); s->ids = NULL; s->pks.kind = PKK_PSK; /* default */ s->pks.u.preshared_secret = EMPTY_CHUNK; s->pks.line = flp->lino; s->next = NULL; for (;;) { struct id id; err_t ugh; if (tokeq(":")) { /* found key part */ (void) shift(); /* eat ":" */ process_secret(psecrets, s); break; } /* * an id * See RFC2407 IPsec Domain of * Interpretation 4.6.2 */ if (tokeq("%any")) { id = empty_id; id.kind = ID_IPV4_ADDR; id.ip_addr = address_any(&ipv4_info); ugh = NULL; } else if (tokeq("%any6")) { id = empty_id; id.kind = ID_IPV6_ADDR; id.ip_addr = address_any(&ipv6_info); ugh = NULL; } else { ugh = atoid(flp->tok, &id, FALSE); } if (ugh != NULL) { loglog(RC_LOG_SERIOUS, "ERROR \"%s\" line %d: index \"%s\" %s", flp->filename, flp->lino, flp->tok, ugh); } else { struct id_list *i = alloc_thing( struct id_list, "id_list"); i->id = clone_id(&id, "parsed id"); i->next = s->ids; s->ids = i; DBG(DBG_CONTROL, { id_buf b; DBG_log("id type added to secret(%p) %s: %s", s, enum_name(&pkk_names, s->pks.kind), str_id(&id, &b)); }); } if (!shift()) { /* unexpected Record Boundary or EOF */ loglog(RC_LOG_SERIOUS, "\"%s\" line %d: unexpected end of id list", flp->filename, flp->lino); pfree(s); break; } } } } } static int globugh_secrets(const char *epath, int eerrno) { LOG_ERRNO(eerrno, "problem with secrets file \"%s\"", epath); return 1; /* stop glob */ } static void lsw_process_secrets_file(struct secret **psecrets, const char *file_pat) { struct file_lex_position pos; char **fnp; glob_t globbuf; pos.depth = flp == NULL ? 0 : flp->depth + 1; if (pos.depth > 10) { loglog(RC_LOG_SERIOUS, "preshared secrets file \"%s\" nested too deeply", file_pat); return; } /* do globbing */ int r = glob(file_pat, GLOB_ERR, globugh_secrets, &globbuf); switch (r) { case 0: /* success */ /* for each file... */ for (fnp = globbuf.gl_pathv; fnp != NULL && *fnp != NULL; fnp++) { if (lexopen(&pos, *fnp, FALSE)) { libreswan_log("loading secrets from \"%s\"", *fnp); (void) flushline( "file starts with indentation (continuation notation)"); lsw_process_secret_records(psecrets); lexclose(); } } break; case GLOB_NOSPACE: loglog(RC_LOG_SERIOUS, "out of space processing secrets filename \"%s\"", file_pat); break; case GLOB_ABORTED: /* already logged by globugh_secrets() */ break; case GLOB_NOMATCH: libreswan_log("no secrets filename matched \"%s\"", file_pat); break; default: loglog(RC_LOG_SERIOUS, "unknown glob error %d", r); break; } globfree(&globbuf); } void lsw_free_preshared_secrets(struct secret **psecrets) { lock_certs_and_keys("free_preshared_secrets"); if (*psecrets != NULL) { struct secret *s, *ns; libreswan_log("forgetting secrets"); for (s = *psecrets; s != NULL; s = ns) { struct id_list *i, *ni; ns = s->next; /* grab before freeing s */ for (i = s->ids; i != NULL; i = ni) { ni = i->next; /* grab before freeing i */ free_id_content(&i->id); pfree(i); } switch (s->pks.kind) { case PKK_PSK: pfree(s->pks.u.preshared_secret.ptr); break; case PKK_PPK: pfree(s->pks.ppk.ptr); pfree(s->pks.ppk_id.ptr); break; case PKK_XAUTH: pfree(s->pks.u.preshared_secret.ptr); break; case PKK_RSA: /* Note: pub is all there is */ free_RSA_public_content( &s->pks.u.RSA_private_key.pub); break; case PKK_ECDSA: /* ??? what about freeing the rest of the key? */ free_ECDSA_public_content( &s->pks.u.ECDSA_private_key.pub); break; default: bad_case(s->pks.kind); } pfree(s); } *psecrets = NULL; } unlock_certs_and_keys("free_preshared_secrets"); } void lsw_load_preshared_secrets(struct secret **psecrets, const char *secrets_file) { lsw_free_preshared_secrets(psecrets); (void) lsw_process_secrets_file(psecrets, secrets_file); } struct pubkey *reference_key(struct pubkey *pk) { pk->refcnt++; return pk; } void unreference_key(struct pubkey **pkp) { struct pubkey *pk = *pkp; if (pk == NULL) return; /* print stuff */ DBG(DBG_CONTROLMORE, { id_buf b; DBG_log("unreference key: %p %s cnt %d--", pk, str_id(&pk->id, &b), pk->refcnt); }); /* cancel out the pointer */ *pkp = NULL; passert(pk->refcnt != 0); pk->refcnt--; /* we are going to free the key as the refcount will hit zero */ if (pk->refcnt == 0) free_public_key(pk); } /* * Free a public key record. * As a convenience, this returns a pointer to next. */ struct pubkey_list *free_public_keyentry(struct pubkey_list *p) { struct pubkey_list *nxt = p->next; if (p->key != NULL) unreference_key(&p->key); pfree(p); return nxt; } void free_public_keys(struct pubkey_list **keys) { while (*keys != NULL) *keys = free_public_keyentry(*keys); } bool same_RSA_public_key(const struct RSA_public_key *a, const struct RSA_public_key *b) { /* * The "adjusted" length of modulus n in octets: * [RSA_MIN_OCTETS, RSA_MAX_OCTETS]. * * According to form_keyid() this is the modulus length less * any leading byte added by DER encoding. * * The adjusted length is used in sign_hash() as the signature * length - wouldn't PK11_SignatureLen be better? * * The adjusted length is used in same_RSA_public_key() as * part of comparing two keys - but wouldn't that be * redundant? The direct n==n test would pick up the * difference. */ DBG(DBG_CRYPT, if (a->k != b->k && chunk_eq(a->e, b->e)) { DBG_log("XXX: different modulus k (%u vs %u) modulus (%zu vs %zu) caused a mismatch", a->k, b->k, a->n.len, b->n.len); }); DBG(DBG_CRYPT, DBG_log("k did %smatch", (a->k == b->k) ? "" : "NOT "); ); DBG(DBG_CRYPT, DBG_log("n did %smatch", chunk_eq(a->n, b->n) ? "" : "NOT "); ); DBG(DBG_CRYPT, DBG_log("e did %smatch", chunk_eq(a->e, b->e) ? "" : "NOT "); ); return a == b || (a->k == b->k && chunk_eq(a->n, b->n) && chunk_eq(a->e, b->e)); } void install_public_key(struct pubkey *pk, struct pubkey_list **head) { struct pubkey_list *p = alloc_thing(struct pubkey_list, "pubkey entry"); /* XXX: how screwed up is this? */ pk->id = clone_id(&pk->id, "install public key id"); /* copy issuer dn; XXX: how screwed up is this? */ pk->issuer = clone_hunk(pk->issuer, "install public key issuer"); /* store the time the public key was installed */ pk->installed_time = realnow(); /* install new key at front */ p->key = reference_key(pk); p->next = *head; *head = p; } void delete_public_keys(struct pubkey_list **head, const struct id *id, const struct pubkey_type *type) { struct pubkey_list **pp, *p; for (pp = head; (p = *pp) != NULL; ) { struct pubkey *pk = p->key; if (same_id(id, &pk->id) && pk->type == type) *pp = free_public_keyentry(p); else pp = &p->next; } } /* * Relocated from x509.c for convenience */ struct pubkey *allocate_RSA_public_key_nss(CERTCertificate *cert) { ckaid_t ckaid; { SECItem *nss_ckaid = PK11_GetLowLevelKeyIDForCert(NULL, cert, lsw_return_nss_password_file_info()); if (nss_ckaid == NULL) { /* someone deleted CERT from the NSS DB */ libreswan_log("NSS: could not extract CKAID from RSA certificate '%s'", cert->nickname); return NULL; } err_t err = form_ckaid_nss(nss_ckaid, &ckaid); SECITEM_FreeItem(nss_ckaid, PR_TRUE); if (err) { /* XXX: What to do with the error? */ return NULL; } } /* free: ckaid */ chunk_t e; chunk_t n; { SECKEYPublicKey *nsspk = SECKEY_ExtractPublicKey(&cert->subjectPublicKeyInfo); if (nsspk == NULL) { /* someone deleted CERT from the NSS DB */ libreswan_log("NSS: could not extract public key from RSA certificate '%s'", cert->nickname); freeanyckaid(&ckaid); return NULL; } e = clone_secitem_as_chunk(nsspk->u.rsa.publicExponent, "RSA e"); n = clone_secitem_as_chunk(nsspk->u.rsa.modulus, "RSA n"); SECKEY_DestroyPublicKey(nsspk); } /* free: ckaid, n, e */ struct pubkey *pk = alloc_thing(struct pubkey, "RSA pubkey"); pk->u.rsa.e = e; pk->u.rsa.n = n; pk->u.rsa.ckaid = ckaid; /* * based on comments in form_keyid, the modulus length * returned by NSS might contain a leading zero and this * ignores that when generating the keyid. */ form_keyid(e, n, pk->u.rsa.keyid, &pk->u.rsa.k); /* DBG(DBG_PRIVATE, RSA_show_public_key(&pk->u.rsa)); */ pk->type = &pubkey_type_rsa; pk->id = empty_id; pk->issuer = EMPTY_CHUNK; return pk; } struct pubkey *allocate_ECDSA_public_key_nss(CERTCertificate *cert) { ckaid_t ckaid; chunk_t pub; chunk_t ecParams; unsigned int k; char keyid[KEYID_BUF]; { SECKEYPublicKey *nsspk = SECKEY_ExtractPublicKey(&cert->subjectPublicKeyInfo); if (nsspk == NULL) { /* someone deleted CERT from the NSS DB */ libreswan_log("NSS: could not extract public key from ECDSA certificate '%s'", cert->nickname); freeanyckaid(&ckaid); return NULL; } pub = clone_secitem_as_chunk(nsspk->u.ec.publicValue, "ECDSA pub"); ecParams = clone_secitem_as_chunk(nsspk->u.ec.DEREncodedParams, "ECDSA ecParams"); DBG_dump("pub", nsspk->u.ec.publicValue.data, nsspk->u.ec.publicValue.len); DBG_dump("ecParams", nsspk->u.ec.DEREncodedParams.data, nsspk->u.ec.DEREncodedParams.len); memcpy(keyid, nsspk->u.ec.publicValue.data, KEYID_BUF-1); DBG_dump("keyid", keyid, KEYID_BUF-1); k = nsspk->u.ec.publicValue.len; SECKEY_DestroyPublicKey(nsspk); } struct pubkey *pk = alloc_thing(struct pubkey, "ECDSA pubkey"); pk->u.ecdsa.pub = pub; pk->u.ecdsa.k = k; pk->u.ecdsa.ecParams = ecParams; /* keyid */ keyblobtoid((const unsigned char *)keyid, KEYID_BUF, pk->u.ecdsa.keyid, KEYID_BUF); /* ckaid */ err_t err = form_ckaid_ecdsa(pub, &ckaid); if (err != NULL) { pfree(pk); return NULL; } pk->u.ecdsa.ckaid = ckaid; /* * based on comments in form_keyid, the modulus length * returned by NSS might contain a leading zero and this * ignores that when generating the keyid. */ //form_keyid(e, n, pk->u.rsa.keyid, &pk->u.rsa.k); /* DBG(DBG_PRIVATE, RSA_show_public_key(&pk->u.rsa)); */ pk->type = &pubkey_type_ecdsa; pk->id = empty_id; pk->issuer = EMPTY_CHUNK; return pk; } static err_t add_ckaid_to_rsa_privkey(struct RSA_private_key *rsak, CERTCertificate *cert) { SECKEYPublicKey *pubk = CERT_ExtractPublicKey(cert); if (pubk == NULL) { loglog(RC_LOG_SERIOUS, "%s: should not happen: cert public key not found [%d]", __func__, PR_GetError()); return "NSS: cert public key not found"; } /* only a check */ SECKEYPrivateKey *privk = PK11_FindKeyByAnyCert(cert, lsw_return_nss_password_file_info()); SECKEY_DestroyPrivateKey(privk); if (privk == NULL) return "NSS: cert private key not found"; SECItem *certCKAID = PK11_GetLowLevelKeyIDForCert(NULL, cert, lsw_return_nss_password_file_info()); err_t ugh; if (certCKAID == NULL) { loglog(RC_LOG_SERIOUS, "%s: no key ID - slot or DB error [%d]", __func__, PR_GetError()); ugh = "NSS: key ID not found"; goto out; } /* * Getting a SECItem ptr from PK11_GetLowLevelKeyID doesn't mean * that the private key exists. The data may be empty if there's no * private key. * * Update: I don't think this is true anymore, hence the search for the private * key above */ if (certCKAID->data == NULL || certCKAID->len < 1) { ugh = "NSS: no CKAID data"; goto out; } rsak->pub.e = clone_bytes_as_chunk(pubk->u.rsa.publicExponent.data, pubk->u.rsa.publicExponent.len, "e"); rsak->pub.n = clone_bytes_as_chunk(pubk->u.rsa.modulus.data, pubk->u.rsa.modulus.len, "n"); ugh = form_ckaid_nss(certCKAID, &rsak->pub.ckaid); if (ugh != NULL) { /* let caller clean up mess */ goto out; } form_keyid_from_nss(pubk->u.rsa.publicExponent, pubk->u.rsa.modulus, rsak->pub.keyid, &rsak->pub.k); out: if (certCKAID != NULL) { SECITEM_FreeItem(certCKAID, PR_TRUE); } if (pubk != NULL) { SECKEY_DestroyPublicKey(pubk); } return ugh; } static err_t add_ckaid_to_ecdsa_privkey(struct ECDSA_private_key *ecdsak, CERTCertificate *cert) { err_t ugh; SECKEYPublicKey *pubk = CERT_ExtractPublicKey(cert); if (pubk == NULL) { loglog(RC_LOG_SERIOUS, "%s: should not happen: cert public key not found [%d]", __func__, PR_GetError()); return "NSS: cert public key not found"; } /* only a check */ SECKEYPrivateKey *privk = PK11_FindKeyByAnyCert(cert, lsw_return_nss_password_file_info()); if (privk == NULL) { SECKEY_DestroyPublicKey(pubk); return "NSS: cert private key not found"; } SECKEY_DestroyPrivateKey(privk); SECItem *certCKAID = PK11_GetLowLevelKeyIDForCert(NULL, cert, lsw_return_nss_password_file_info()); if (certCKAID == NULL) { loglog(RC_LOG_SERIOUS, "%s: no key ID - slot or DB error [%d]", __func__, PR_GetError()); ugh = "NSS: key ID not found"; goto out; } /* * Getting a SECItem ptr from PK11_GetLowLevelKeyID doesn't mean * that the private key exists. The data may be empty if there's no * private key. * * Update: I don't think this is true anymore, hence the search for the private * key above */ if (certCKAID->data == NULL || certCKAID->len < 1) { ugh = "NSS: no CKAID data"; goto out; } ecdsak->pub.pub = clone_bytes_as_chunk(pubk->u.ec.publicValue.data, pubk->u.ec.publicValue.len, "pub"); ugh = form_ckaid_nss(certCKAID, &ecdsak->pub.ckaid); if (ugh != NULL) { /* let caller clean up mess */ goto out; } /* keyid */ char keyid[KEYID_BUF]; memset(keyid, 0, KEYID_BUF); memcpy(keyid, pubk->u.ec.publicValue.data, KEYID_BUF-1); memset(ecdsak->pub.keyid, 0, KEYID_BUF); keyblobtoid((const unsigned char *)keyid, KEYID_BUF, ecdsak->pub.keyid, KEYID_BUF); /*size */ ecdsak->pub.k = pubk->u.ec.size; out: if (certCKAID != NULL) { SECITEM_FreeItem(certCKAID, PR_TRUE); } if (pubk != NULL) { SECKEY_DestroyPublicKey(pubk); } return ugh; } static err_t lsw_extract_nss_cert_privkey_RSA(struct RSA_private_key *rsak, CERTCertificate *cert) { dbg("extracting the RSA private key for %s", cert->nickname); err_t ugh = add_ckaid_to_rsa_privkey(rsak, cert); if (ugh == NULL) { ugh = RSA_public_key_sanity(rsak); } return ugh; } static err_t lsw_extract_nss_cert_privkey_ECDSA(struct ECDSA_private_key *ecdsak, CERTCertificate *cert) { DBG(DBG_CRYPT, DBG_log("extracting the ECDSA private key for %s", cert->nickname)); err_t ugh = add_ckaid_to_ecdsa_privkey(ecdsak, cert); if (ugh == NULL) { /* ??? we should check the sanity of ecdsak */ } return ugh; } static const struct RSA_private_key *get_nss_cert_privkey_RSA(struct secret *secrets, CERTCertificate *cert) { struct pubkey *pub = allocate_RSA_public_key_nss(cert); if (pub == NULL) { return NULL; } const struct RSA_private_key *priv = NULL; for (struct secret *s = secrets; s != NULL; s = s->next) { if (s->pks.kind == PKK_RSA && same_RSA_public_key(&s->pks.u.RSA_private_key.pub, &pub->u.rsa)) { priv = &s->pks.u.RSA_private_key; break; } } free_public_key(pub); return priv; } static const struct ECDSA_private_key *get_nss_cert_privkey_ECDSA(struct secret *secrets, CERTCertificate *cert) { struct pubkey *pub = allocate_ECDSA_public_key_nss(cert); if (pub == NULL) { return NULL; } const struct ECDSA_private_key *priv = NULL; for (struct secret *s = secrets; s != NULL; s = s->next) { if (s->pks.kind == PKK_ECDSA) { /* same_RSA_public_key(&s->pks.u.RSA_private_key.pub, &pub->u.rsa)) {*/ priv = &s->pks.u.ECDSA_private_key; break; } } free_public_key(pub); return priv; } err_t lsw_add_rsa_secret(struct secret **secrets, CERTCertificate *cert) { if (get_nss_cert_privkey_RSA(*secrets, cert) != NULL) { dbg("secrets entry for certificate already exists: %s", cert->nickname); return NULL; } dbg("adding RSA secret for certificate: %s", cert->nickname); struct secret *s = alloc_thing(struct secret, "RSA secret"); s->pks.kind = PKK_RSA; s->pks.line = 0; err_t ugh = lsw_extract_nss_cert_privkey_RSA(&s->pks.u.RSA_private_key, cert); if (ugh != NULL) { pfree(s); } else { add_secret(secrets, s, "lsw_add_rsa_secret"); } return ugh; } err_t lsw_add_ecdsa_secret(struct secret **secrets, CERTCertificate *cert) { if (get_nss_cert_privkey_ECDSA(*secrets, cert) != NULL) { DBG(DBG_CONTROL, DBG_log("secrets entry for %s already exists", cert->nickname)); return NULL; } struct secret *s = alloc_thing(struct secret, "ECDSA secret"); s->pks.kind = PKK_ECDSA; s->pks.line = 0; err_t ugh = lsw_extract_nss_cert_privkey_ECDSA(&s->pks.u.ECDSA_private_key, cert); if (ugh != NULL) { pfree(s); } else { add_secret(secrets, s, "lsw_add_ecdsa_secret"); } return ugh; } libreswan-3.32/lib/libswan/shunk.c000066400000000000000000000121721365625662500171530ustar00rootroot00000000000000/* Constant string (octet) fragments, for libreswan * * Copyright (C) 2018-2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include #include /* for strtoul() */ #include #include #include "shunk.h" #include "lswlog.h" /* for pexpect() */ /* * Don't mistake a NULL_SHUNK for an EMPTY_SHUNK - just like when * manipulating strings they are different. */ const shunk_t null_shunk = NULL_SHUNK; const shunk_t empty_shunk = { .ptr = "", .len = 0, }; shunk_t shunk1(const char *ptr) { if (ptr == NULL) { return null_shunk; } else { return shunk2(ptr, strlen(ptr)); } } shunk_t shunk2(const void *ptr, int len) { /* * Since a zero length string is not the same as a NULL * string, don't try to be smart and convert the former into * the latter. */ return (shunk_t) { .ptr = ptr, .len = len, }; } shunk_t shunk_slice(shunk_t s, size_t start, size_t stop) { pexpect(start <= stop); pexpect(stop <= s.len); const char *c = s.ptr; return shunk2(c + start, stop - start); } shunk_t shunk_token(shunk_t *input, char *delim, const char *delims) { /* * If INPUT is either empty, or the NULL_SHUNK, the loop is * skipped. */ const char *const start = input->ptr; const char *pos = start; while (pos < start + input->len) { if (strchr(delims, *pos) != NULL) { /* save the token and stop character */ shunk_t token = shunk2(start, pos-start); if (delim != NULL) { *delim = *pos; } /* skip over TOKEN+DELIM */ *input = shunk_slice(*input, pos-start+1, input->len); return token; } pos++; } /* * The last token is all of INPUT. Flag that INPUT has been * exhausted by setting INPUT to the NULL_SHUNK; the next call * will return that NULL_SHUNK. */ shunk_t token = *input; *input = null_shunk; if (delim != NULL) { *delim = '\0'; } return token; } shunk_t shunk_span(shunk_t *input, const char *accept) { /* * If INPUT is either empty, or the NULL_SHUNK, the loop is * skipped. */ const char *const start = input->ptr; const char *pos = start; while (pos < start + input->len) { if (strchr(accept, *pos) == NULL) { /* save the token and stop character */ shunk_t token = shunk2(start, pos - start); /* skip over TOKEN+DELIM */ *input = shunk_slice(*input, pos - start, input->len); return token; } pos++; } /* * The last token is all of INPUT. Flag that INPUT has been * exhausted by setting INPUT to the NULL_SHUNK; the next call * will return that NULL_SHUNK. */ shunk_t token = *input; *input = null_shunk; return token; } bool shunk_caseeq(shunk_t lhs, shunk_t rhs) { /* NULL and EMPTY("") are not the same */ if (lhs.ptr == NULL || rhs.ptr == NULL) { return lhs.ptr == rhs.ptr; } if (lhs.len != rhs.len) { return false; } return strncasecmp(lhs.ptr, rhs.ptr, lhs.len) == 0; } bool shunk_strcaseeq(shunk_t shunk, const char *str) { return shunk_caseeq(shunk, shunk1(str)); } bool bytes_eq(const void *l_ptr, size_t l_len, const void *r_ptr, size_t r_len) { /* NULL and EMPTY("") are not the same */ if (l_ptr == NULL || r_ptr == NULL) { return l_ptr == r_ptr; } if (l_len != r_len) { return false; } return memcmp(l_ptr, r_ptr, r_len) == 0; } bool shunk_caseeat(shunk_t *shunk, shunk_t dinner) { if (shunk->ptr == NULL || dinner.ptr == NULL) { return false; } if (shunk->len < dinner.len) { return false; } if (strncasecmp(shunk->ptr, dinner.ptr, dinner.len) != 0) { return false; } *shunk = shunk_slice(*shunk, dinner.len, shunk->len); return true; } bool shunk_strcaseeat(shunk_t *shunk, const char *dinner) { return shunk_caseeat(shunk, shunk1(dinner)); } /* * Convert the entire shunk to an unsigned. * * Since strtou() expects a NUL terminated string (which a SHUNK is * not) fudge one up. XXX: must be code to do this somewhere? */ bool shunk_tou(shunk_t shunk, unsigned *dest, int base) { /* copy SHUNK into a NUL terminated STRING */ char string[64] = ""; /* NUL fill */ if (shunk.len + 1 >= sizeof(string)) { /* no-space for trailing NUL */ return false; } strncpy(string, shunk.ptr, shunk.len); /* convert the string, expect entire shunk to be consumed */ char *end = NULL; unsigned long ul = strtoul(string, &end, base); if (string + shunk.len > end) { return false; } if (ul > UINT_MAX) { return false; } *dest = (unsigned)ul; return true; } bool shunk_isdigit(shunk_t s, size_t i) { pexpect(s.len > 0); pexpect(i < s.len); const char *c = s.ptr; return isdigit(c[i]); } bool shunk_ischar(shunk_t s, size_t i, const char *chars) { pexpect(s.len > 0); pexpect(i < s.len); const char *c = s.ptr; return strchr(chars, c[i]) != NULL; } libreswan-3.32/lib/libswan/subnetof.3.xml000066400000000000000000000061141365625662500203660ustar00rootroot00000000000000 PaulWoutersplaceholder to suppress warning IPSEC_SUBNETOF 3 11 June 2001 libreswan Executable programs ipsec subnetof ipsec hostof ipsec broadcastof given Internet address and subnet mask return subnet number, host part, broadcast address #include <libreswan.h> struct in_addr subnetof struct in_addr addr struct in_addr mask struct in_addr hostof struct in_addr addr struct in_addr mask struct in_addr broadcastof struct in_addr addr struct in_addr mask DESCRIPTION These functions are obsolete; see ipsec_networkof3 for their replacements. Subnetof takes an Internet address and a subnet mask and returns the network part of the address (all in network byte order). Hostof similarly returns the host part, and broadcastof returns the broadcast address (all-1s convention) for the network. These functions are provided to hide the Internet bit-munging inside an API, in hopes of easing the eventual transition to IPv6. SEE ALSO inet3, ipsec_atosubnet3 HISTORY Written for the FreeS/WAN project by Henry Spencer. BUGS Calling functions for this is more costly than doing it yourself. libreswan-3.32/lib/libswan/subnettypeof.c000066400000000000000000000025541365625662500205550ustar00rootroot00000000000000/* * extract parts of an ip_subnet, and related * * Copyright (C) 2000 Henry Spencer. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. */ #include "ip_subnet.h" /* * masktocount - convert a mask, expressed as an address, to a bit count */ int /* -1 if not valid mask */ masktocount(src) const ip_address * src; { int b; const unsigned char *p; const unsigned char *stop; shunk_t sc = address_as_shunk(src); const uint8_t *bp = sc.ptr; /* cast const void * */ size_t n = sc.len; if (n == 0) return -1; p = bp; stop = bp + n; n = 0; while (p < stop && *p == 0xff) { p++; n += 8; } if (p < stop && *p != 0) { /* boundary in mid-byte */ b = *p++; while (b & 0x80) { b <<= 1; n++; } if ((b & 0xff) != 0) return -1; /* bits not contiguous */ } while (p < stop && *p == 0) p++; if (p != stop) return -1; return n; } libreswan-3.32/lib/libswan/ttoaddr.3.xml000066400000000000000000000360021365625662500202010ustar00rootroot00000000000000 PaulWoutersplaceholder to suppress warning IPSEC_TTOADDR 3 28 Sept 2001 libreswan Executable programs ipsec ttoaddr ipsec tnatoaddr ipsec addrtot ipsec ttosubnet ipsec subnettot convert Internet addresses and Subnet masks to and from text #include <libreswan.h> const char *ttoaddr const char * src size_t srclen int af ip_address * addr const char *tnatoaddr const char * src size_t srclen int af ip_address * addr size_t addrtot const ip_address * addr int format char * dst size_t dstlen const char *ttosubnet const char * src size_t srclen int af ip_subnet * dst size_t subnettot const ip_subnet * sub int format char * dst size_t dstlen DESCRIPTION Ttoaddr converts a text-string name or numeric address into a binary address (in network byte order). Tnatoaddr does the same conversion, but the only text forms it accepts are the “official” forms of numeric address (dotted-decimal for IPv4, colon-hex for IPv6). Addrtot does the reverse conversion, from binary address back to a text form. Ttosubnet and subnettot do likewise for the “address/mask” form used to write a specification of a subnet. An IPv4 address is specified in text as a dotted-decimal address (e.g. 1.2.3.4), an eight-digit network-order hexadecimal number with the usual C prefix (e.g. 0x01020304, which is synonymous with 1.2.3.4), an eight-digit host-order hexadecimal number with a 0h prefix (e.g. 0h01020304, which is synonymous with 1.2.3.4 on a big-endian host and 4.3.2.1 on a little-endian host), a DNS name to be looked up via gethostbyname3, or an old-style network name to be looked up via getnetbyname3. A dotted-decimal address may be incomplete, in which case text-to-binary conversion implicitly appends as many instances of .0 as necessary to bring it up to four components. The components of a dotted-decimal address are always taken as decimal, and leading zeros are ignored. For example, 10 is synonymous with 10.0.0.0, and 128.009.000.032 is synonymous with 128.9.0.32 (the latter example is verbatim from RFC 1166). The result of applying addrtot to an IPv4 address is always complete and does not contain leading zeros. Use of hexadecimal addresses is strongly discouraged; they are included only to save hassles when dealing with the handful of perverted programs that print network addresses in hexadecimal. An IPv6 address is specified in text with colon-hex notation (e.g. 0:56:78ab:22:33:44:55:66), colon-hex with :: abbreviating at most one subsequence of multiple zeros (e.g. 99:ab::54:068, which is synonymous with 99:ab:0:0:0:0:54:68), or a DNS name to be looked up via gethostbyname3. The result of applying addrtot to an IPv6 address will use :: abbreviation if possible, and will not contain leading zeros. The letters in hexadecimal may be uppercase or lowercase or any mixture thereof. DNS names may be complete (optionally terminated with a “.”) or incomplete, and are looked up as specified by local system configuration (see resolver5). The h_addr value returned by gethostbyname23 is used, so with current DNS implementations, the result when the name corresponds to more than one address is difficult to predict. IPv4 name lookup resorts to getnetbyname3 only if gethostbyname23 fails. A subnet specification is of the form network/mask. The network and mask can be any form acceptable to ttoaddr. In addition, and preferably, the mask can be a decimal integer (leading zeros ignored) giving a bit count, in which case it stands for a mask with that number of high bits on and all others off (e.g., 24 in IPv4 means 255.255.255.0). In any case, the mask must be contiguous (a sequence of high bits on and all remaining low bits off). As a special case, the subnet specification %default is a synonym for 0.0.0.0/0 or ::/0 in IPv4 or IPv6 respectively. Ttosubnet ANDs the mask with the address before returning, so that any non-network bits in the address are turned off (e.g., 10.1.2.3/24 is synonymous with 10.1.2.0/24). Subnettot always generates the decimal-integer-bit-count form of the mask, with no leading zeros. The srclen parameter of ttoaddr and ttosubnet specifies the length of the text string pointed to by src; it is an error for there to be anything else (e.g., a terminating NUL) within that length. As a convenience for cases where an entire NUL-terminated string is to be converted, a srclen value of 0 is taken to mean strlen(src). The af parameter of ttoaddr and ttosubnet specifies the address family of interest. It should be either AF_INET, AF_INET6, or AF_UNSPEC. If it is AF_UNSPEC, the family will be based on the string. The dstlen parameter of addrtot and subnettot specifies the size of the dst parameter; under no circumstances are more than dstlen bytes written to dst. A result that will not fit is truncated. Dstlen can be zero, in which case dst need not be valid and no result is written, but the return value is unaffected; in all other cases, the (possibly truncated) result is NUL-terminated. The libreswan.h header file defines constants, ADDRTOT_BUF and SUBNETTOT_BUF, which are the sizes of buffers just large enough for worst-case results. The format parameter of addrtot and subnettot specifies what format is to be used for the conversion. The value 0 (not the character '0', but a zero value) specifies a reasonable default, and is in fact the only format currently available in subnettot. Addrtot also accepts format values 'r' (signifying a text form suitable for DNS reverse lookups, e.g. 4.3.2.1.IN-ADDR.ARPA. for IPv4 and RFC 2874 format for IPv6), and 'R' (signifying an alternate reverse-lookup form, an error for IPv4 and RFC 1886 format for IPv6). Reverse-lookup names always end with a “.”. The text-to-binary functions return NULL for success and a pointer to a string-literal error message for failure; see DIAGNOSTICS. The binary-to-text functions return 0 for a failure, and otherwise always return the size of buffer that would be needed to accommodate the full conversion result, including terminating NUL; it is the caller's responsibility to check this against the size of the provided buffer to determine whether truncation has occurred. SEE ALSO inet3 DIAGNOSTICS Fatal errors in ttoaddr are: empty input; unknown address family; attempt to allocate temporary storage for a very long name failed; name lookup failed; syntax error in dotted-decimal or colon-hex form; dotted-decimal or colon-hex component too large. Fatal errors in ttosubnet are: no / in src; ttoaddr error in conversion of network or mask; bit-count mask too big; mask non-contiguous. Fatal errors in addrtot and subnettot are: unknown format. HISTORY Written for the FreeS/WAN project by Henry Spencer. BUGS The interpretation of incomplete dotted-decimal addresses (e.g. 10/24 means 10.0.0.0/24) differs from that of some older conversion functions, e.g. those of inet3. The behavior of the older functions has never been particularly consistent or particularly useful. Ignoring leading zeros in dotted-decimal components and bit counts is arguably the most useful behavior in this application, but it might occasionally cause confusion with the historical use of leading zeros to denote octal numbers. Ttoaddr does not support the mixed colon-hex-dotted-decimal convention used to embed an IPv4 address in an IPv6 address. Addrtot always uses the :: abbreviation (which can appear only once in an address) for the first sequence of multiple zeros in an IPv6 address. One can construct addresses (unlikely ones) in which this is suboptimal. Addrtot 'r' conversion of an IPv6 address uses lowercase hexadecimal, not the uppercase used in RFC 2874's examples. It takes careful reading of RFCs 2874, 2673, and 2234 to realize that lowercase is technically legitimate here, and there may be software that botches this and hence would have trouble with lowercase hex. Possibly subnettot ought to recognize the %default case and generate that string as its output. Currently it doesn't. It is barely possible that somebody, somewhere, might have a legitimate use for non-contiguous subnet masks. Getnetbyname3 is a historical dreg. Tnatoaddr probably should enforce completeness of dotted-decimal addresses. The restriction of text-to-binary error reports to literal strings (so that callers don't need to worry about freeing them or copying them) does limit the precision of error reporting. The text-to-binary error-reporting convention lends itself to slightly obscure code, because many readers will not think of NULL as signifying success. A good way to make it clearer is to write something like: const char *error; error = ttoaddr( /* ... */ ); if (error != NULL) { /* something went wrong */ libreswan-3.32/lib/libswan/ttoaddr.c000066400000000000000000000311651365625662500174670ustar00rootroot00000000000000/* * conversion from text forms of addresses to internal ones * * Copyright (C) 2000 Henry Spencer. * Copyright (C) 2019 Andrew Cagney * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. * */ #include #include /* for gethostbyname2() */ #include /* for isxdigit() */ #include "ip_address.h" #include "ip_info.h" #include "lswalloc.h" /* for alloc_things(), pfree() */ #include "lswlog.h" /* for pexpect() */ /* * Legal ASCII characters in a domain name. Underscore technically is not, * but is a common misunderstanding. Non-ASCII characters are simply * exempted from checking at the moment, to allow for UTF-8 encoded stuff; * the purpose of this check is merely to catch blatant errors. */ static const char namechars[] = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-_."; #define ISASCII(c) (((c) & 0x80) == 0) static err_t tryhex(const char *, size_t, int, ip_address *); static err_t trydotted(const char *, size_t, ip_address *); static err_t getbyte(const char **, const char *, int *); static err_t colon(const char *, size_t, ip_address *); static err_t getpiece(const char **, const char *, unsigned *); /* * ttoaddr - convert text name or dotted-decimal address to binary address */ static err_t /* NULL for success, else string literal */ ttoaddr_base(const char *src, size_t srclen, /* 0 means "apply strlen" */ int af, /* address family */ int *allnumericfailed, ip_address *dst) { err_t oops; #define HEXLEN 10 /* strlen("0x11223344") */ switch (af) { case AF_INET: case AF_INET6: case AF_UNSPEC: /* guess */ break; default: return "invalid address family"; } if (af == AF_INET && srclen == HEXLEN && *src == '0') { switch (*(src + 1)) { case 'x': case 'X': return tryhex(src + 2, srclen - 2, 'x', dst); case 'h': case 'H': return tryhex(src + 2, srclen - 2, 'h', dst); } } if (memchr(src, ':', srclen) != NULL) { if (af == AF_INET) return "IPv4 address may not contain `:'"; return colon(src, srclen, dst); } if (af == AF_UNSPEC || af == AF_INET) { oops = trydotted(src, srclen, dst); if (oops == NULL) return NULL; /* it worked */ if (*oops != '?') return oops; /* probably meant as d-d */ } *allnumericfailed = 1; return "not numeric"; } /* * tnatoaddr - convert text numeric address (only) to binary address */ err_t /* NULL for success, else string literal */ tnatoaddr(src, srclen, af, dst) const char *src; size_t srclen; /* 0 means "apply strlen" */ int af; /* address family */ ip_address *dst; { err_t oops; if (srclen == 0) { srclen = strlen(src); if (srclen == 0) return "empty string"; } switch (af) { case AF_UNSPEC: /* guess */ oops = colon(src, srclen, dst); if (oops == NULL) return NULL; oops = trydotted(src, srclen, dst); if (oops == NULL) return NULL; return "does not appear to be either IPv4 or IPv6 numeric address"; case AF_INET6: return colon(src, srclen, dst); case AF_INET: oops = trydotted(src, srclen, dst); if (oops == NULL) return NULL; /* it worked */ if (*oops != '?') return oops; /* probably meant as d-d */ return "does not appear to be numeric address"; default: return "unknown address family in tnatoaddr"; } } /* * tryname - try it as a name * * Slightly complicated by lack of reliable NUL termination in source. */ static err_t tryname( const char *src, size_t srclen, int nultermd, /* is it known to be NUL-terminated? */ int af, int tried_af, /* kind(s) of numeric addressing tried */ ip_address *dst) { struct hostent *h; struct netent *ne = NULL; char namebuf[100]; /* enough for most DNS names */ const char *cp; char *p = namebuf; size_t n; for (cp = src, n = srclen; n > 0; cp++, n--) if (ISASCII(*cp) && strchr(namechars, *cp) == NULL) return "illegal (non-DNS-name) character in name"; if (nultermd) { cp = src; } else { if (srclen + 1 > sizeof(namebuf)) { p = alloc_things(char, srclen + 1, "p"); if (p == NULL) return "unable to get temporary space for name"; } p[0] = '\0'; /* strncpy semantics are wrong */ strncat(p, src, srclen); cp = (const char *)p; } h = gethostbyname2(cp, af); /* like, windows even has an /etc/networks? */ if (h == NULL && af == AF_INET) ne = getnetbyname(cp); if (p != namebuf) pfree(p); if (h == NULL && ne == NULL) { /* intricate because we cannot compose a static string */ switch (tried_af) { case AF_INET: return "not a numeric IPv4 address and name lookup failed (no validation performed)"; case AF_INET6: return "not a numeric IPv6 address and name lookup failed (no validation performed)"; case AF_UNSPEC: /* guess */ return "not a numeric IPv4 or IPv6 address and name lookup failed (no validation performed)"; } } if (h != NULL) { if (h->h_addrtype != af) return "address-type mismatch from gethostbyname2!!!"; return data_to_address(h->h_addr, h->h_length, aftoinfo(af), dst); } else { if (ne->n_addrtype != af) return "address-type mismatch from getnetbyname!!!"; if (!pexpect(af == AF_INET)) { return "address-type mismatch by convoluted logic!!!"; } /* apparently .n_net is in host order */ struct in_addr in = { htonl(ne->n_net), }; *dst = address_from_in_addr(&in); return NULL; } } /* * tryhex - try conversion as an eight-digit hex number (AF_INET only) */ static err_t tryhex(const char *src, size_t srclen, /* should be 8 */ int flavour, /* 'x' for network order, 'h' for host order */ ip_address *dst) { err_t oops; unsigned long ul; if (srclen != 8) return "internal error, tryhex called with bad length"; oops = ttoul(src, srclen, 16, &ul); if (oops != NULL) return oops; struct in_addr addr = { (flavour == 'h') ? ul : htonl(ul), }; *dst = address_from_in_addr(&addr); return NULL; } /* * trydotted - try conversion as dotted decimal (AF_INET only) * * If the first char of a complaint is '?', that means "didn't look like * dotted decimal at all". */ static err_t trydotted(const char *src, size_t srclen, ip_address *dst) { const char *stop = src + srclen; /* just past end */ err_t oops; /* start with blank IPv4 address */ union { struct in_addr addr; uint8_t bytes[sizeof(struct in_addr)]; } u = { .bytes = { 0, }, }; for (size_t i = 0; i < sizeof(u) && src < stop; i++) { int byte; oops = getbyte(&src, stop, &byte); if (oops != NULL) { if (*oops != '?') return oops; /* bad number */ if (i > 1) return oops + 1; /* failed number */ return oops; /* with leading '?' */ } u.bytes[i] = byte; if (i < 3 && src < stop && *src++ != '.') { if (i == 0) return "?syntax error in dotted-decimal address"; else return "syntax error in dotted-decimal address"; } } if (src != stop) return "extra garbage on end of dotted-decimal address"; *dst = address_from_in_addr(&u.addr); return NULL; } /* * getbyte - try to scan a byte in dotted decimal * * A subtlety here is that all this arithmetic on ASCII digits really is * highly portable -- ANSI C guarantees that digits 0-9 are contiguous. * It's easier to just do it ourselves than set up for a call to ttoul(). * * If the first char of a complaint is '?', that means "didn't look like a * number at all". */ err_t getbyte(srcp, stop, retp) const char **srcp; /* *srcp is updated */ const char *stop; /* first untouchable char */ int *retp; /* return-value pointer */ { char c; const char *p; int no; if (*srcp >= stop) return "?empty number in dotted-decimal address"; no = 0; p = *srcp; while (p < stop && no <= 255 && (c = *p) >= '0' && c <= '9') { no = no * 10 + (c - '0'); p++; } if (p == *srcp) return "?non-numeric component in dotted-decimal address"; *srcp = p; if (no > 255) return "byte overflow in dotted-decimal address"; *retp = no; return NULL; } /* * colon - convert IPv6 "numeric" address */ static err_t colon(const char *src, size_t srclen, /* known to be >0 */ ip_address *dst) { const char *stop = src + srclen; /* just past end */ unsigned piece; int gapat; /* where was empty piece seen */ err_t oops; # define NPIECES 8 union { struct in6_addr in6; uint8_t bytes[sizeof(struct in6_addr)]; } u = { .bytes = { 0, }, }; int i; int j; # define IT "IPv6 numeric address" int naftergap; /* leading or trailing :: becomes single empty field */ if (*src == ':') { /* legal only if leading :: */ if (srclen == 1 || *(src + 1) != ':') return "illegal leading `:' in " IT; if (srclen == 2) { *dst = address_any(&ipv6_info); return NULL; } src++; /* past first but not second */ srclen--; } if (*(stop - 1) == ':') { /* legal only if trailing :: */ if (srclen == 1 || *(stop - 2) != ':') return "illegal trailing `:' in " IT; srclen--; /* leave one */ } gapat = -1; piece = 0; for (i = 0; i < NPIECES && src < stop; i++) { oops = getpiece(&src, stop, &piece); if (oops != NULL && *oops == ':') { /* empty field */ if (gapat >= 0) return "more than one :: in " IT; gapat = i; } else if (oops != NULL) { return oops; } u.bytes[2 * i] = piece >> 8; u.bytes[2 * i + 1] = piece & 0xff; if (i < NPIECES - 1) { /* there should be more input */ if (src == stop && gapat < 0) return IT " ends prematurely"; if (src != stop && *src++ != ':') return "syntax error in " IT; } } if (src != stop) return "extra garbage on end of " IT; if (gapat < 0 && i < NPIECES) /* should have been caught earlier */ return "incomplete " IT " (internal error)"; if (gapat >= 0 && i == NPIECES) return "non-abbreviating empty field in " IT; if (gapat >= 0) { naftergap = i - (gapat + 1); for (i--, j = NPIECES - 1; naftergap > 0; i--, j--, naftergap--) { u.bytes[2 * j] = u.bytes[2 * i]; u.bytes[2 * j + 1] = u.bytes[2 * i + 1]; } for (; j >= gapat; j--) u.bytes[2 * j] = u.bytes[2 * j + 1] = 0; } *dst = address_from_in6_addr(&u.in6); return NULL; } /* * getpiece - try to scan one 16-bit piece of an IPv6 address */ err_t /* ":" means "empty field seen" */ getpiece(srcp, stop, retp) const char **srcp; /* *srcp is updated */ const char *stop; /* first untouchable char */ unsigned *retp; /* return-value pointer */ { const char *p; # define NDIG 4 int d; unsigned long ret; err_t oops; if (*srcp >= stop || **srcp == ':') { /* empty field */ *retp = 0; return ":"; } p = *srcp; d = 0; while (p < stop && d < NDIG && isxdigit(*p)) { p++; d++; } if (d == 0) return "non-hex field in IPv6 numeric address"; if (p < stop && d == NDIG && isxdigit(*p)) return "field in IPv6 numeric address longer than 4 hex digits"; oops = ttoul(*srcp, d, 16, &ret); if (oops != NULL) /* shouldn't happen, really... */ return oops; *srcp = p; *retp = ret; return NULL; } err_t /* NULL for success, else string literal */ ttoaddr(const char *src, size_t srclen, /* 0 means "apply strlen" */ int af, /* address family */ ip_address *dst) { int nultermd; int numfailed = 0; err_t err; if (srclen == 0) { srclen = strlen(src); if (srclen == 0) return "empty string"; nultermd = 1; } else { nultermd = 0; /* at least, not *known* to be terminated */ } err = ttoaddr_base(src, srclen, af, &numfailed, dst); if (numfailed) { if (err && af != AF_INET) err = tryname(src, srclen, nultermd, AF_INET6, af, dst); if (err && af != AF_INET6) err = tryname(src, srclen, nultermd, AF_INET, af, dst); } return err; } err_t domain_to_address(shunk_t src, const struct ip_info *type, ip_address *dst) { *dst = address_invalid; if (src.len == 0) { return "empty string"; } return ttoaddr(src.ptr, src.len, type == NULL ? AF_UNSPEC : type->af, dst); } err_t /* NULL for success, else string literal */ ttoaddr_num(const char *src, size_t srclen, /* 0 means "apply strlen" */ int af, /* address family */ ip_address *dst) { int numfailed = 0; if (srclen == 0) { srclen = strlen(src); if (srclen == 0) return "empty string"; } return ttoaddr_base(src, srclen, af, &numfailed, dst); } err_t numeric_to_address(shunk_t src, const struct ip_info *type, ip_address *dst) { *dst = address_invalid; if (src.len == 0) { return "empty string"; } return ttoaddr_num(src.ptr, src.len, type == NULL ? AF_UNSPEC : type->af, dst); } libreswan-3.32/lib/libswan/ttodata.3.xml000066400000000000000000000257601365625662500202110ustar00rootroot00000000000000 PaulWoutersplaceholder to suppress warning IPSEC_TTODATA 3 16 August 2003 libreswan Library functions ipsec ttodata ipsec datatot convert binary data bytes from and to text formats #include <libreswan.h> const char *ttodata const char * src size_t srclen int base char * dst size_t dstlen size_t * lenp const char *ttodatav const char * src size_t srclen int base char * dst size_t dstlen size_t * lenp char * errp size_t errlen int flags size_t datatot const char * src size_t srclen int format char * dst size_t dstlen DESCRIPTION Ttodata, ttodatav, and datatot convert arbitrary binary data (e.g. encryption or authentication keys) from and to more-or-less human-readable text formats. Currently supported formats are hexadecimal, base64, and characters. A hexadecimal text value begins with a 0x (or 0X) prefix and continues with two-digit groups of hexadecimal digits (0-9, and a-f or A-F), each group encoding the value of one binary byte, high-order digit first. A single _ (underscore) between consecutive groups is ignored, permitting punctuation to improve readability; doing this every eight digits seems about right. A base64 text value begins with a 0s (or 0S) prefix and continues with four-digit groups of base64 digits (A-Z, a-z, 0-9, +, and /), each group encoding the value of three binary bytes as described in section 6.8 of RFC 2045. If flags has the TTODATAV_IGNORESPACE bit on, blanks are ignore (after the prefix). Note that the last one or two digits of a base64 group can be = to indicate that fewer than three binary bytes are encoded. A character text value begins with a 0t (or 0T) prefix and continues with text characters, each being the value of one binary byte. All these functions basically copy data from src (whose size is specified by srclen) to dst (whose size is specified by dstlen), doing the conversion en route. If the result will not fit in dst, it is truncated; under no circumstances are more than dstlen bytes of result written to dst. Dstlen can be zero, in which case dst need not be valid and no result bytes are written at all. The base parameter of ttodata and ttodatav specifies what format the input is in; normally it should be 0 to signify that this gets figured out from the prefix. Values of 16, 64, and 256 respectively signify hexadecimal, base64, and character-text formats without prefixes. The format parameter of datatot, a single character used as a type code, specifies which text format is wanted. The value 0 (not ASCII '0', but a zero value) specifies a reasonable default. Other currently-supported values are: 'x' continuous lower-case hexadecimal with a 0x prefix 'h' lower-case hexadecimal with a 0x prefix and a _ every eight digits ':' lower-case hexadecimal with no prefix and a : (colon) every two digits 16 lower-case hexadecimal with no prefix or _ 's' continuous base64 with a 0s prefix 64 continuous base64 with no prefix The default format is currently 'h'. Ttodata returns NULL for success and a pointer to a string-literal error message for failure; see DIAGNOSTICS. On success, if and only if lenp is non-NULL, *lenp is set to the number of bytes required to contain the full untruncated result. It is the caller's responsibility to check this against dstlen to determine whether he has obtained a complete result. The *lenp value is correct even if dstlen is zero, which offers a way to determine how much space would be needed before having to allocate any. Ttodatav is just like ttodata except that in certain cases, if errp is non-NULL, the buffer pointed to by errp (whose length is given by errlen) is used to hold a more detailed error message. The return value is NULL for success, and is either errp or a pointer to a string literal for failure. If the size of the error-message buffer is inadequate for the desired message, ttodatav will fall back on returning a pointer to a literal string instead. The libreswan.h header file defines a constant TTODATAV_BUF which is the size of a buffer large enough for worst-case results. The normal return value of datatot is the number of bytes required to contain the full untruncated result. It is the caller's responsibility to check this against dstlen to determine whether he has obtained a complete result. The return value is correct even if dstlen is zero, which offers a way to determine how much space would be needed before having to allocate any. A return value of 0 signals a fatal error of some kind (see DIAGNOSTICS). A zero value for srclen in ttodata (but not datatot!) is synonymous with strlen(src). A non-zero srclen in ttodata must not include the terminating NUL. Unless dstlen is zero, the result supplied by datatot is always NUL-terminated, and its needed-size return value includes space for the terminating NUL. SEE ALSO sprintf3, ipsec_atoaddr3 DIAGNOSTICS Fatal errors in ttodata and ttodatav are: unknown characters in the input; unknown or missing prefix; unknown base; incomplete digit group; non-zero padding in a base64 less-than-three-bytes digit group; zero-length input. Fatal errors in datatot are: unknown format code; zero-length input. HISTORY Written for the FreeS/WAN project by Henry Spencer. BUGS Datatot should have a format code to produce character-text output. The 0s and 0t prefixes are the author's inventions and are not a standard of any kind. They have been chosen to avoid collisions with existing practice (some C implementations use 0b for binary) and possible confusion with unprefixed hexadecimal. libreswan-3.32/lib/libswan/ttodata.c000066400000000000000000000445151365625662500174710ustar00rootroot00000000000000/* * convert from text form of arbitrary data (e.g., keys) to binary * * Copyright (C) 2000 Henry Spencer. * Copyright (C) 2016, Andrew Cagney * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. */ #include #include /* for tolower() */ #include "libreswan.h" /* converters and misc */ static int unhex(const char *, char *, size_t); static int unb64(const char *, char *, size_t); static int untext(const char *, char *, size_t); static const char *badch(const char *, int, char *, size_t); /* internal error codes for converters */ #define SHORT (-2) /* internal buffer too short */ #define BADPAD (-3) /* bad base64 padding */ #define BADCH0 (-4) /* invalid character 0 */ #define BADCH1 (-5) /* invalid character 1 */ #define BADCH2 (-6) /* invalid character 2 */ #define BADCH3 (-7) /* invalid character 3 */ #define BADOFF(code) (BADCH0 - (code)) /* * ttodatav - convert text to data, with verbose error reports * * If some of this looks slightly odd, it's because it has changed * repeatedly (from the original atodata()) without a major rewrite. * * Return NULL on success, else literal or errp */ const char *ttodatav(const char *src, size_t srclen, /* 0 means apply strlen() */ int base, /* 0 means figure it out */ char *dst, /* need not be valid if dstlen is 0 */ size_t dstlen, size_t *lenp, /* where to record length (NULL is nowhere) */ char *errp, /* error buffer */ size_t errlen, unsigned int flags) { size_t ingroup; /* number of input bytes converted at once */ char buf[4]; /* output from conversion */ int nbytes; /* size of output */ int (*decode)(const char *, char *, size_t); char *stop; int ndone; int i; int underscoreok; int skipSpace = 0; if (srclen == 0) srclen = strlen(src); if (dstlen == 0) dst = buf; /* point it somewhere valid */ stop = dst + dstlen; if (base == 0) { if (srclen < 2) return "input too short to be valid"; if (*src++ != '0') return "input does not begin with format prefix"; switch (*src++) { case 'x': case 'X': base = 16; break; case 's': case 'S': base = 64; break; case 't': case 'T': base = 256; break; default: return "unknown format prefix"; } srclen -= 2; } switch (base) { case 16: decode = unhex; underscoreok = 1; ingroup = 2; break; case 64: decode = unb64; underscoreok = 0; ingroup = 4; if (flags & TTODATAV_IGNORESPACE) skipSpace = 1; break; case 256: decode = untext; ingroup = 1; underscoreok = 0; break; default: return "unknown base"; } /* proceed */ ndone = 0; while (srclen > 0) { char stage[4]; /* staging area for group */ size_t sl = 0; /* * Grab ingroup characters into stage, * squeezing out blanks if we are supposed to ignore them. */ for (sl = 0; sl < ingroup; src++, srclen--) { if (srclen == 0) return "input ends in mid-byte, perhaps truncated"; else if (!(skipSpace && (*src == ' ' || *src == '\t'))) stage[sl++] = *src; } nbytes = (*decode)(stage, buf, sizeof(buf)); switch (nbytes) { case BADCH0: case BADCH1: case BADCH2: case BADCH3: return badch(stage, nbytes, errp, errlen); case SHORT: return "internal buffer too short (\"can't happen\")"; case BADPAD: return "bad (non-zero) padding at end of base64 input"; } if (nbytes <= 0) return "unknown internal error"; for (i = 0; i < nbytes; i++) { if (dst < stop) *dst++ = buf[i]; ndone++; } while (srclen >= 1 && skipSpace && (*src == ' ' || *src == '\t')) { src++; srclen--; } if (underscoreok && srclen > 1 && *src == '_') { /* srclen > 1 means not last character */ src++; srclen--; } } if (ndone == 0) return "no data bytes specified by input"; if (lenp != NULL) *lenp = ndone; return NULL; } /* * ttodata - convert text to data * * Return NULL on success, else literal */ const char *ttodata(const char *src, size_t srclen, /* 0 means apply strlen() */ int base, /* 0 means figure it out */ char *dst, /* need not be valid if dstlen is 0 */ size_t dstlen, size_t *lenp) /* where to record length (NULL is nowhere) */ { return ttodatav(src, srclen, base, dst, dstlen, lenp, (char *)NULL, (size_t)0, TTODATAV_SPACECOUNTS); } /* * unhex - convert two ASCII hex digits to byte * * Return number of result bytes, or error code */ static int unhex(const char *src, /* known to be full length */ char *dst, size_t dstlen) /* not large enough is a failure */ { const char *p; unsigned byte; static const char hex[] = "0123456789abcdef"; if (dstlen < 1) return SHORT; p = strchr(hex, *src); if (p == NULL) p = strchr(hex, tolower(*src)); if (p == NULL) return BADCH0; byte = (p - hex) << 4; src++; p = strchr(hex, *src); if (p == NULL) p = strchr(hex, tolower(*src)); if (p == NULL) return BADCH1; byte |= (p - hex); *dst = byte; return 1; } /* * unb64 - convert four ASCII base64 digits to three bytes * * Note that a base64 digit group is padded out with '=' if it represents * less than three bytes: one byte is dd==, two is ddd=, three is dddd. * * Return number of result bytes, or error code */ static int unb64(const char *src, /* known to be full length */ char *dst, size_t dstlen) { const char *p; unsigned byte1; unsigned byte2; static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; if (dstlen < 3) return SHORT; p = strchr(base64, *src++); if (p == NULL) return BADCH0; byte1 = (p - base64) << 2; /* first six bits */ p = strchr(base64, *src++); if (p == NULL) return BADCH1; byte2 = p - base64; /* next six: two plus four */ *dst++ = byte1 | (byte2 >> 4); byte1 = (byte2 & 0xf) << 4; p = strchr(base64, *src++); if (p == NULL) { if (*(src - 1) == '=' && *src == '=') { if (byte1 != 0) /* bad padding */ return BADPAD; return 1; } return BADCH2; } byte2 = p - base64; /* next six: four plus two */ *dst++ = byte1 | (byte2 >> 2); byte1 = (byte2 & 0x3) << 6; p = strchr(base64, *src++); if (p == NULL) { if (*(src - 1) == '=') { if (byte1 != 0) /* bad padding */ return BADPAD; return 2; } return BADCH3; } byte2 = p - base64; /* last six */ *dst++ = byte1 | byte2; return 3; } /* * untext - convert one ASCII character to byte * * Return number of result bytes, or error code */ static int untext(const char *src, /* known to be full length */ char *dst, size_t dstlen) /* not large enough is a failure */ { if (dstlen < 1) return SHORT; *dst = *src; return 1; } /* * badch - produce a nice complaint about an unknown character * * If the compiler complains that the array bigenough[] has a negative * size, that means the TTODATAV_BUF constant has been set too small. * * Return literal or errp */ static const char *badch(const char *src, int errcode, char *errp, /* might be NULL */ size_t errlen) { static const char pre[] = "unknown character (`"; static const char suf[] = "') in input"; char buf[5]; /* it would be a VERY good idea if REQD <= TTODATAV_BUF */ # define REQD (sizeof(pre) - 1 + sizeof(buf) - 1 + sizeof(suf)) struct sizecheck { char bigenough[TTODATAV_BUF - REQD]; /* see above */ }; char ch; if (errp == NULL || errlen < REQD) return "unknown character in input"; strcpy(errp, pre); /* * clang 3.4 says "warning: Assigned value is garbage or undefined". * This does not seem to be correct. */ ch = *(src + BADOFF(errcode)); if (isprint(ch)) { buf[0] = ch; buf[1] = '\0'; } else { buf[0] = '\\'; buf[1] = ((ch & 0700) >> 6) + '0'; buf[2] = ((ch & 0070) >> 3) + '0'; buf[3] = ((ch & 0007) >> 0) + '0'; buf[4] = '\0'; } strcat(errp, buf); strcat(errp, suf); return (const char *)errp; } #ifdef TTODATA_MAIN #include #define memeq(a, b, n) (memcmp((a), (b), (n)) == 0) #define streq(a, b) (strcmp((a), (b)) == 0) struct artab; static void check(struct artab *r, char *buf, size_t n, err_t oops, int *status); static void regress(char *pgm); static void hexout(const char *s, size_t len, FILE *f); /* * main - convert first argument to hex, or run regression */ int main(int argc, char *argv[]) { char buf[1024]; char buf2[1024]; char err[512]; size_t n; size_t i; char *p = buf; char *p2 = buf2; char *pgm = argv[0]; const char *oops; if (argc < 2) { fprintf(stderr, "Usage: %s {0x|0s|-r}\n", pgm); exit(2); } if (streq(argv[1], "-r")) { regress(pgm); /* should not return */ fprintf(stderr, "%s: regress() returned?!?\n", pgm); exit(1); } oops = ttodatav(argv[1], 0, 0, buf, sizeof(buf), &n, err, sizeof(err), TTODATAV_IGNORESPACE); if (oops != NULL) { fprintf(stderr, "%s: ttodata error `%s' in `%s'\n", pgm, oops, argv[1]); exit(1); } if (n > sizeof(buf)) { p = (char *)malloc((size_t)n); if (p == NULL) { fprintf(stderr, "%s: unable to malloc %lu bytes for result\n", pgm, n); exit(1); } oops = ttodata(argv[1], 0, 0, p, n, &n); if (oops != NULL) { fprintf(stderr, "%s: error `%s' in ttodata retry?!?\n", pgm, oops); exit(1); } } hexout(p, n, stdout); printf("\n"); i = datatot(buf, n, 'h', buf2, sizeof(buf2)); if (i == 0) { fprintf(stderr, "%s: datatot reports error in `%s'\n", pgm, argv[1]); exit(1); } if (i > sizeof(buf2)) { p2 = (char *)malloc((size_t)i); if (p == NULL) { fprintf(stderr, "%s: unable to malloc %lu bytes for result\n", pgm, i); exit(1); } i = datatot(buf, n, 'h', p2, i); if (i == 0) { fprintf(stderr, "%s: error in datatot retry?!?\n", pgm); exit(1); } } printf("%s\n", p2); exit(0); } /* * hexout - output an arbitrary-length string in hex */ static void hexout(s, len, f) const char *s; size_t len; FILE *f; { size_t i; fprintf(f, "0x"); for (i = 0; i < len; i++) fprintf(f, "%02x", (unsigned char)s[i]); } struct artab { int base; #define IGNORESPACE_BIAS 1000 char *ascii; /* NULL for end */ char *data; /* NULL for error expected */ } atodatatab[] = { { 0, "", NULL, }, { 0, "0", NULL, }, { 0, "0x", NULL, }, { 0, "0xa", NULL, }, { 0, "0xab", "\xab", }, { 0, "0xabc", NULL, }, { 0, "0xabcd", "\xab\xcd", }, { 0, "0x0123456789", "\x01\x23\x45\x67\x89", }, { 0, "0x01x", NULL, }, { 0, "0xabcdef", "\xab\xcd\xef", }, { 0, "0xABCDEF", "\xab\xcd\xef", }, { 0, "0XaBc0eEd81f", "\xab\xc0\xee\xd8\x1f", }, { 0, "0XaBc0_eEd8", "\xab\xc0\xee\xd8", }, { 0, "0XaBc0_", NULL, }, { 0, "0X_aBc0", NULL, }, { 0, "0Xa_Bc0", NULL, }, { 16, "aBc0eEd8", "\xab\xc0\xee\xd8", }, { 0, "0s", NULL, }, { 0, "0sA", NULL, }, { 0, "0sBA", NULL, }, { 0, "0sCBA", NULL, }, { 0, "0sDCBA", "\x0c\x20\x40", }, { 0, "0SDCBA", "\x0c\x20\x40", }, { 0, "0sDA==", "\x0c", }, { 0, "0sDC==", NULL, }, { 0, "0sDCA=", "\x0c\x20", }, { 0, "0sDCB=", NULL, }, { 0, "0sDCAZ", "\x0c\x20\x19", }, { 0, "0sDCAa", "\x0c\x20\x1a", }, { 0, "0sDCAz", "\x0c\x20\x33", }, { 0, "0sDCA0", "\x0c\x20\x34", }, { 0, "0sDCA9", "\x0c\x20\x3d", }, { 0, "0sDCA+", "\x0c\x20\x3e", }, { 0, "0sDCA/", "\x0c\x20\x3f", }, { 0, "0sAbraCadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", }, { IGNORESPACE_BIAS + 0, "0s AbraCadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", }, { IGNORESPACE_BIAS + 0, "0sA braCadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", }, { IGNORESPACE_BIAS + 0, "0sAb raCadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", }, { IGNORESPACE_BIAS + 0, "0sAbr aCadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", }, { IGNORESPACE_BIAS + 0, "0sAbra Cadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", }, { IGNORESPACE_BIAS + 0, "0sAbraC adabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", }, { IGNORESPACE_BIAS + 0, "0sAbraCa dabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", }, { IGNORESPACE_BIAS + 0, "0sAbraCad abra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", }, { IGNORESPACE_BIAS + 0, "0sAbraCada bra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", }, { IGNORESPACE_BIAS + 0, "0sAbraCadab ra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", }, { IGNORESPACE_BIAS + 0, "0sAbraCadabr a+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", }, { IGNORESPACE_BIAS + 0, "0sAbraCadabra +", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", }, { IGNORESPACE_BIAS + 0, "0sAbraCadabra+ ", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", }, { 0, "0t", NULL, }, { 0, "0tabc_xyz", "abc_xyz", }, { 256, "abc_xyz", "abc_xyz", }, { 0, NULL, NULL, }, }; struct drtab { char *data; /* input; NULL for end */ char format; int buflen; /* -1 means big buffer */ int outlen; /* -1 means strlen(ascii)+1 */ char *ascii; /* NULL for error expected */ } datatoatab[] = { { "", 'x', -1, -1, NULL, }, { "", 'X', -1, -1, NULL, }, { "", 'n', -1, -1, NULL, }, { "0", 'x', -1, -1, "0x30", }, { "0", 'x', 0, 5, "---", }, { "0", 'x', 1, 5, "", }, { "0", 'x', 2, 5, "0", }, { "0", 'x', 3, 5, "0x", }, { "0", 'x', 4, 5, "0x3", }, { "0", 'x', 5, 5, "0x30", }, { "0", 'x', 6, 5, "0x30", }, { "\xab\xcd", 'x', -1, -1, "0xabcd", }, { "\x01\x23\x45\x67\x89", 'x', -1, -1, "0x0123456789", }, { "\xab\xcd\xef", 'x', -1, -1, "0xabcdef", }, { "\xab\xc0\xee\xd8\x1f", 'x', -1, -1, "0xabc0eed81f", }, { "\x01\x02", 'h', -1, -1, "0x0102", }, { "\x01\x02\x03\x04\x05\x06", 'h', -1, -1, "0x01020304_0506", }, { "\xab\xc0\xee\xd8\x1f", 16, -1, -1, "abc0eed81f", }, { "\x0c\x20\x40", 's', -1, -1, "0sDCBA", }, { "\x0c\x20\x40", 's', 0, 7, "---", }, { "\x0c\x20\x40", 's', 1, 7, "", }, { "\x0c\x20\x40", 's', 2, 7, "0", }, { "\x0c\x20\x40", 's', 3, 7, "0s", }, { "\x0c\x20\x40", 's', 4, 7, "0sD", }, { "\x0c\x20\x40", 's', 5, 7, "0sDC", }, { "\x0c\x20\x40", 's', 6, 7, "0sDCB", }, { "\x0c\x20\x40", 's', 7, 7, "0sDCBA", }, { "\x0c\x20\x40", 's', 8, 7, "0sDCBA", }, { "\x0c", 's', -1, -1, "0sDA==", }, { "\x0c\x20", 's', -1, -1, "0sDCA=", }, { "\x0c\x20\x19", 's', -1, -1, "0sDCAZ", }, { "\x0c\x20\x1a", 's', -1, -1, "0sDCAa", }, { "\x0c\x20\x33", 's', -1, -1, "0sDCAz", }, { "\x0c\x20\x34", 's', -1, -1, "0sDCA0", }, { "\x0c\x20\x3d", 's', -1, -1, "0sDCA9", }, { "\x0c\x20\x3e", 's', -1, -1, "0sDCA+", }, { "\x0c\x20\x3f", 's', -1, -1, "0sDCA/", }, { "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", 's', -1, -1, "0sAbraCadabra+", }, { "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", 64, -1, -1, "AbraCadabra+", }, { NULL, 'x', -1, -1, NULL, }, }; /* * regress - regression-test ttodata() and datatot() */ static void check(r, buf, n, oops, status) struct artab *r; char *buf; size_t n; err_t oops; int *status; { if (oops != NULL && r->data == NULL) { /* error expected */ } else if (oops != NULL) { printf("`%s' gave error `%s', expecting %lu `", r->ascii, oops, strlen(r->data)); hexout(r->data, strlen(r->data), stdout); printf("'\n"); *status = 1; } else if (r->data == NULL) { printf("`%s' gave %lu `", r->ascii, n); hexout(buf, n, stdout); printf("', expecting error\n"); *status = 1; } else if (n != strlen(r->data)) { printf("length wrong in `%s': got %lu `", r->ascii, n); hexout(buf, n, stdout); printf("', expecting %lu `", strlen(r->data)); hexout(r->data, strlen(r->data), stdout); printf("'\n"); *status = 1; } else if (!memeq(buf, r->data, n)) { printf("`%s' gave %lu `", r->ascii, n); hexout(buf, n, stdout); printf("', expecting %lu `", strlen(r->data)); hexout(r->data, strlen(r->data), stdout); printf("'\n"); *status = 1; } fflush(stdout); } static void /* should not return at all, in fact */ regress(pgm) char *pgm; { struct artab *r; struct drtab *dr; char buf[100]; size_t n; int status = 0; for (r = atodatatab; r->ascii != NULL; r++) { int base = r->base; int xbase = 0; if ((base == 0 || base == IGNORESPACE_BIAS + 0) && r->ascii[0] == '0') { switch (r->ascii[1]) { case 'x': case 'X': xbase = 16; break; case 's': case 'S': xbase = 64; break; case 't': case 'T': xbase = 256; break; } } if (base >= IGNORESPACE_BIAS) { base = base - IGNORESPACE_BIAS; check(r, buf, n, ttodatav(r->ascii, 0, base, buf, sizeof(buf), &n, NULL, 0, TTODATAV_IGNORESPACE), &status); if (xbase != 0) check(r, buf, n, ttodatav(r->ascii + 2, 0, xbase, buf, sizeof(buf), &n, NULL, 0, TTODATAV_IGNORESPACE), &status); } else { check(r, buf, n, ttodata(r->ascii, 0, base, buf, sizeof(buf), &n), &status); if (base == 64 || xbase == 64) check(r, buf, n, ttodatav(r->ascii, 0, base, buf, sizeof(buf), &n, NULL, 0, TTODATAV_IGNORESPACE), &status); if (xbase != 0) { check(r, buf, n, ttodata(r->ascii + 2, 0, xbase, buf, sizeof(buf), &n), &status); if (base == 64 || xbase == 64) check(r, buf, n, ttodatav(r->ascii + 2, 0, xbase, buf, sizeof(buf), &n, NULL, 0, TTODATAV_IGNORESPACE), &status); } } } for (dr = datatoatab; dr->data != NULL; dr++) { size_t should; strcpy(buf, "---"); n = datatot(dr->data, strlen(dr->data), dr->format, buf, (dr->buflen == -1) ? sizeof(buf) : dr->buflen); should = (dr->ascii == NULL) ? 0 : strlen(dr->ascii) + 1; if (dr->outlen != -1) should = dr->outlen; if (n == 0 && dr->ascii == NULL) { /* error expected */ } else if (n == 0) { printf("`"); hexout(dr->data, strlen(dr->data), stdout); printf("' %c gave error, expecting %lu `%s'\n", dr->format, should, dr->ascii); status = 1; } else if (dr->ascii == NULL) { printf("`"); hexout(dr->data, strlen(dr->data), stdout); printf("' %c gave %lu `%.*s', expecting error\n", dr->format, n, (int)n, buf); status = 1; } else if (n != should) { printf("length wrong in `"); hexout(dr->data, strlen(dr->data), stdout); printf("': got %lu `%s'", n, buf); printf(", expecting %lu `%s'\n", should, dr->ascii); status = 1; } else if (!streq(buf, dr->ascii)) { printf("`"); hexout(dr->data, strlen(dr->data), stdout); printf("' gave %lu `%s'", n, buf); printf(", expecting %lu `%s'\n", should, dr->ascii); status = 1; } fflush(stdout); } exit(status); } #endif /* TTODATA_MAIN */ libreswan-3.32/lib/libswan/ttoprotoport.c000066400000000000000000000116221365625662500206210ustar00rootroot00000000000000/* * conversion from protocol/port string to protocol and port * * Copyright (C) 2002 Mario Strasser , * Zuercher Hochschule Winterthur, * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include /* for gethostbyname2() */ #include /* for strchr() */ #include "libreswan.h" /* * ttoprotoport - converts from protocol/port string to protocol and port */ err_t ttoprotoport(src, src_len, proto, port, has_port_wildcard) char *src; /* input string */ size_t src_len; /* length of input string, use strlen() if 0 */ uint8_t *proto; /* extracted protocol number */ uint16_t *port; /* extracted port number if it exists */ bool *has_port_wildcard; /* set if port is %any */ { char *end, *service_name; char proto_name[16]; int proto_len; long int l; struct protoent *protocol; struct servent *service; bool wildcard; /* get the length of the string */ if (!src_len) src_len = strlen(src); /* locate delimiter '/' between protocol and port */ end = strchr(src, '/'); if (end != NULL) { proto_len = end - src; service_name = end + 1; } else { proto_len = src_len; service_name = src + src_len; } /* copy protocol name */ memset(proto_name, '\0', sizeof(proto_name)); memcpy(proto_name, src, proto_len); /* extract protocol by trying to resolve it by name */ protocol = getprotobyname(proto_name); if (protocol != NULL) { *proto = protocol->p_proto; } else { /* failed, now try it by number */ l = strtol(proto_name, &end, 0); if (*proto_name && *end) return " is neither a number nor a valid name"; if (l < 0 || l > 0xff) return " must be between 0 and 255"; *proto = (uint8_t)l; } /* is there a port wildcard? */ wildcard = (strcmp(service_name, "%any") == 0); if (has_port_wildcard) *has_port_wildcard = wildcard; if (wildcard) { *port = 0; return NULL; } /* extract port by trying to resolve it by name */ service = getservbyname(service_name, NULL); if (service != NULL) { *port = ntohs(service->s_port); } else { /* failed, now try it by number */ l = strtol(service_name, &end, 0); if (*service_name && *end) /* * set port to 0, this is needed for protocols without * port in the proposal, such as with GRE (protoport=47) */ l = 0; else if (l < 0 || l > 0xffff) return " must be between 0 and 65535"; *port = (uint16_t)l; } return NULL; } #ifdef TTOPROTOPORT_MAIN #include struct artab; static void regress(char *pgm); /* * main - convert first argument to hex, or run regression */ int main(int argc, char *argv[]) { char *pgm = argv[0]; const char *oops; uint8_t proto; uint16_t port; bool has_port_wildcard; if (argc < 2) { fprintf(stderr, "Usage: %s {0x|0s|-r}\n", pgm); exit(2); } if (strcmp(argv[1], "-r") == 0) { regress(pgm); /* should not return */ fprintf(stderr, "%s: regress() returned?!?\n", pgm); exit(1); } oops = ttoprotoport(argv[1], strlen(argv[1]), &proto, &port, &has_port_wildcard); if (oops != NULL) { fprintf(stderr, "%s: ttodata error `%s' in `%s'\n", pgm, oops, argv[1]); exit(1); } printf("%s -> %d/%d with %d\n", argv[1], proto, port, has_port_wildcard); exit(0); } struct artab { char *ascii; /* NULL for end */ int proto, port, wild; } atodatatab[] = { /* { "", 0, 0, -1 }, */ { "tcp/%any", 6, 0, 1, }, { NULL, 0, 0, 0, }, }; static void /* should not return at all, in fact */ regress(pgm) char *pgm; { struct artab *r; int status = 0; for (r = atodatatab; r->ascii != NULL; r++) { uint8_t proto; uint16_t port; bool has_port_wildcard; err_t err = ttoprotoport(r->ascii, strlen(r->ascii), &proto, &port, &has_port_wildcard); if (r->wild == -1) { if (err == NULL) { printf("%s expected error, got none.\n", r->ascii); status = 1; } continue; } if (err != NULL) { printf("%s got error: %s\n", r->ascii, err); status = 1; continue; } if (proto != r->proto) { printf("%s expected proto %d, got %d\n", r->ascii, proto, r->proto); status = 1; continue; } if (port != r->port) { printf("%s expected port %d, got %d\n", r->ascii, port, r->port); status = 1; continue; } if (has_port_wildcard != r->wild) { printf("%s expected wild %d, got %d\n", r->ascii, has_port_wildcard, r->wild); status = 1; continue; } fflush(stdout); } exit(status); } #endif /* TTODATA_MAIN */ libreswan-3.32/lib/libswan/ttosa.3.xml000066400000000000000000000256541365625662500177050ustar00rootroot00000000000000 PaulWoutersplaceholder to suppress warning IPSEC_TTOSA 3 26 Nov 2001 libreswan Library functions ipsec ttosa ipsec satot ipsec initsaid convert IPsec Security Association IDs to and from text, initialize an SA ID #include <libreswan.h> typedef struct { ip_address dst; ipsec_spi_t spi; int proto; } ip_said; const char *ttosa const char * src size_t srclen ip_said * sa size_t satot const ip_said * sa int format char * dst size_t dstlen void initsaid const ip_address * addr ipsec_spi_t spi int proto ip_said * dst DESCRIPTION Ttosa converts an ASCII Security Association (SA) specifier into an ip_said structure (containing a destination-host address in network byte order, an SPI number in network byte order, and a protocol code). Satot does the reverse conversion, back to a text SA specifier. Initsaid initializes an ip_said from separate items of information. An SA is specified in text with a mail-like syntax, e.g. esp.5a7@1.2.3.4. An SA specifier contains a protocol prefix (currently ah, esp, tun, comp, or int), a single character indicating the address family (. for IPv4, : for IPv6), an unsigned integer SPI number in hexadecimal (with no 0x prefix), and an IP address. The IP address can be any form accepted by ipsec_ttoaddr3, e.g. dotted-decimal IPv4 address, colon-hex IPv6 address, or DNS name. As a special case, the SA specifier %passthrough4 or %passthrough6 signifies the special SA used to indicate that packets should be passed through unaltered. (At present, these are synonyms for tun.0@0.0.0.0 and tun:0@:: respectively, but that is subject to change without notice.) %passthrough is a historical synonym for %passthrough4. These forms are known to both ttosa and satot, so the internal representation is never visible. Similarly, the SA specifiers %pass, %drop, %reject, %hold, %trap, and %trapsubnet signify special “magic” SAs used to indicate that packets should be passed, dropped, rejected (dropped with ICMP notification), held, and trapped (sent up to ipsec_pluto8, with either of two forms of %hold automatically installed) respectively. These forms too are known to both routines, so the internal representation of the magic SAs should never be visible. The <libreswan.h> header file supplies the ip_said structure, as well as a data type ipsec_spi_t which is an unsigned 32-bit integer. (There is no consistency between kernel and user on what such a type is called, hence the header hides the differences.) The protocol code uses the same numbers that IP does. For user convenience, given the difficulty in acquiring the exact set of protocol names used by the kernel, <libreswan.h> defines the names SA_ESP, SA_AH, SA_IPIP, and SA_COMP to have the same values as the kernel names IPPROTO_ESP, IPPROTO_AH, IPPROTO_IPIP, and IPPROTO_COMP. <libreswan.h> also defines SA_INT to have the value 61 (reserved by IANA for “any host internal protocol”) and SPI_PASS, SPI_DROP, SPI_REJECT, SPI_HOLD, and SPI_TRAP to have the values 256-260 (in host byte order) respectively. These are used in constructing the magic SAs (which always have address 0.0.0.0). If satot encounters an unknown protocol code, e.g. 77, it yields output using a prefix showing the code numerically, e.g. “unk77”. This form is not recognized by ttosa. The srclen parameter of ttosa specifies the length of the string pointed to by src; it is an error for there to be anything else (e.g., a terminating NUL) within that length. As a convenience for cases where an entire NUL-terminated string is to be converted, a srclen value of 0 is taken to mean strlen(src). The dstlen parameter of satot specifies the size of the dst parameter; under no circumstances are more than dstlen bytes written to dst. A result that will not fit is truncated. Dstlen can be zero, in which case dst need not be valid and no result is written, but the return value is unaffected; in all other cases, the (possibly truncated) result is NUL-terminated. The <libreswan.h> header file defines a constant, SATOT_BUF, which is the size of a buffer just large enough for worst-case results. The format parameter of satot specifies what format is to be used for the conversion. The value 0 (not the ASCII character '0', but a zero value) specifies a reasonable default (currently lowercase protocol prefix, lowercase hexadecimal SPI, dotted-decimal or colon-hex address). The value 'f' is similar except that the SPI is padded with 0s to a fixed 32-bit width, to ease aligning displayed tables. Ttosa returns NULL for success and a pointer to a string-literal error message for failure; see DIAGNOSTICS. Satot returns 0 for a failure, and otherwise always returns the size of buffer that would be needed to accommodate the full conversion result, including terminating NUL; it is the caller's responsibility to check this against the size of the provided buffer to determine whether truncation has occurred. There is also, temporarily, support for some obsolete forms of SA specifier that lack the address-family indicator. SEE ALSO ipsec_ttoul3, ipsec_ttoaddr3, ipsec_samesaid3, inet3 DIAGNOSTICS Fatal errors in ttosa are: empty input; input too small to be a legal SA specifier; no @ in input; unknown protocol prefix; conversion error in ttoul or ttoaddr. Fatal errors in satot are: unknown format. HISTORY Written for the FreeS/WAN project by Henry Spencer. BUGS The restriction of text-to-binary error reports to literal strings (so that callers don't need to worry about freeing them or copying them) does limit the precision of error reporting. The text-to-binary error-reporting convention lends itself to slightly obscure code, because many readers will not think of NULL as signifying success. A good way to make it clearer is to write something like: const char *error; error = ttosa( /* ... */ ); if (error != NULL) { /* something went wrong */ libreswan-3.32/lib/libswan/ttosa.c000066400000000000000000000055211365625662500171550ustar00rootroot00000000000000/* * convert from text form of SA ID to binary * * Copyright (C) 2000, 2001 Henry Spencer. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. */ #include #include "ip_said.h" static struct magic { char *name; char *really; } magic[] = { { PASSTHROUGHNAME, PASSTHROUGH4IS }, { PASSTHROUGH4NAME, PASSTHROUGH4IS }, { PASSTHROUGH6NAME, PASSTHROUGH6IS }, { "%pass", "int256@0.0.0.0" }, { "%drop", "int257@0.0.0.0" }, { "%reject", "int258@0.0.0.0" }, { "%hold", "int259@0.0.0.0" }, { "%trap", "int260@0.0.0.0" }, { "%trapsubnet", "int261@0.0.0.0" }, { NULL, NULL } }; /* * ttosa - convert text "ah507@10.0.0.1" to SA identifier */ err_t /* NULL for success, else string literal */ ttosa(src, srclen, sa) const char *src; size_t srclen; /* 0 means "apply strlen" */ ip_said *sa; { const char *at; const char *addr; size_t alen; const char *spi = NULL; unsigned long ul; const char *oops; struct magic *mp; size_t nlen; # define MINLEN 5 /* ah0@0 is as short as it can get */ int af; int base; if (srclen == 0) srclen = strlen(src); if (srclen == 0) return "empty string"; if (srclen < MINLEN) return "string too short to be SA identifier"; if (*src == '%') { for (mp = magic; mp->name != NULL; mp++) { nlen = strlen(mp->name); if (srclen == nlen && memcmp(src, mp->name, nlen) == 0) break; } if (mp->name == NULL) return "unknown % keyword"; src = mp->really; srclen = strlen(src); } at = memchr(src, '@', srclen); if (at == NULL) return "no @ in SA specifier"; const struct ip_protocol *sat = protocol_by_prefix(src); if (sat == NULL) return "SA specifier lacks valid protocol prefix"; sa->proto = sat; spi = src + strlen(sat->prefix); if (spi >= at) return "no SPI in SA specifier"; switch (*spi) { case '.': af = AF_INET; spi++; base = 16; break; case ':': af = AF_INET6; spi++; base = 16; break; default: af = AF_UNSPEC; /* not known yet */ base = 0; break; } if (spi >= at) return "no SPI found in SA specifier"; oops = ttoul(spi, at - spi, base, &ul); if (oops != NULL) return oops; sa->spi = htonl(ul); addr = at + 1; alen = srclen - (addr - src); if (af == AF_UNSPEC) af = (memchr(addr, ':', alen) != NULL) ? AF_INET6 : AF_INET; oops = ttoaddr_num(addr, alen, af, &sa->dst); if (oops != NULL) return oops; return NULL; } libreswan-3.32/lib/libswan/ttosubnet.c000066400000000000000000000064611365625662500200560ustar00rootroot00000000000000/* * convert from text form of subnet specification to binary * * Copyright (C) 2000 Henry Spencer. * Copyright (C) 2019 Andrew Cagney * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. */ #include #include "ip_subnet.h" #include "libreswan.h" /* for ttoulb() */ #ifndef DEFAULTSUBNET #define DEFAULTSUBNET "%default" #endif /* * ttosubnet - convert text "addr/mask" to address and mask * Mask can be integer bit count. */ err_t ttosubnet(src, srclen, af, clash, dst) const char *src; size_t srclen; /* 0 means "apply strlen" */ int af; /* AF_INET or AF_INET6 */ int clash; /* '0' zero host-part bits, 'x' die on them, '6' die on IPv6 and warn on IPv4 */ ip_subnet *dst; { const char *slash; const char *colon; const char *mask; size_t mlen; const char *oops; unsigned long bc; static const char def[] = DEFAULTSUBNET; #define DEFLEN (sizeof(def) - 1) /* -1 for NUL */ static const char defis4[] = "0/0"; #define DEFIS4LEN (sizeof(defis4) - 1) static const char defis6[] = "::/0"; #define DEFIS6LEN (sizeof(defis6) - 1) ip_address addrtmp; ip_address masktmp; int nbits; int i; if (srclen == 0) { srclen = strlen(src); if (srclen == 0) return "empty string"; } /* * you cannot use af==AF_UNSPEC and src=0/0, * makes no sense as will it be AF_INET */ if (srclen == DEFLEN && strncmp(src, def, srclen) == 0) { switch (af) { case AF_INET: src = defis4; srclen = DEFIS4LEN; break; case AF_INET6: src = defis6; srclen = DEFIS6LEN; break; default: return "unknown address family with " DEFAULTSUBNET " subnet not allowed."; } } slash = memchr(src, '/', srclen); if (slash == NULL) return "no / in subnet specification"; mask = slash + 1; mlen = srclen - (mask - src); oops = ttoaddr_num(src, slash - src, af, &addrtmp); if (oops != NULL) return oops; if (af == AF_UNSPEC) af = addrtypeof(&addrtmp); switch (af) { case AF_INET: nbits = 32; break; case AF_INET6: nbits = 128; break; default: return "unknown address family in ttosubnet"; } /* extract port, as last : */ colon = memchr(mask, ':', mlen); if (colon == 0) { setportof(0, &addrtmp); } else { unsigned long port; oops = ttoulb(colon + 1, mlen - (colon - mask + 1), 0, 0xFFFF, &port); if (oops != NULL) return oops; setportof(htons(port), &addrtmp); mlen = colon - mask; } /* extract mask */ oops = ttoulb(mask, mlen, 10, nbits, &bc); if (oops == NULL) { /* ttoul succeeded, it's a bit-count mask */ i = bc; } else if (af == AF_INET) { oops = ttoaddr_num(mask, mlen, af, &masktmp); if (oops != NULL) return oops; i = masktocount(&masktmp); if (i < 0) return "non-contiguous or otherwise erroneous mask"; } else { return "masks are not permitted for IPv6 addresses"; } return initsubnet(&addrtmp, i, clash, dst); } libreswan-3.32/lib/libswan/ttoul.3.xml000066400000000000000000000207361365625662500177160ustar00rootroot00000000000000 PaulWoutersplaceholder to suppress warning IPSEC_TTOUL 3 16 Aug 2000 libreswan Library functions ipsec ttoul ipsec ttoulb ipsec ultot convert unsigned-long numbers to and from text #include <libreswan.h> err_t ttoul const char * src size_t srclen int base unsigned long * n err_t ttoulb const char * src size_t srclen int base unsigned long upb unsigned long * n size_t ultot unsigned long n int format char * dst size_t dstlen DESCRIPTION Ttoul converts a text-string number into a binary unsigned long value. Ttoulb does the same as Ttoul with the addition of a bounds check. converts a text-string number into a binary unsigned long value. Ultot does the reverse conversion, back to a text version. Numbers are specified in text as decimal (e.g. 123), octal with a leading zero (e.g. 012, which has value 10), or hexadecimal with a leading 0x (e.g. 0x1f, which has value 31) in either upper or lower case. The srclen parameter of ttoul specifies the length of the string pointed to by src; it is an error for there to be anything else (e.g., a terminating NUL) within that length. As a convenience for cases where an entire NUL-terminated string is to be converted, a srclen value of 0 is taken to mean strlen(src). The base parameter of ttoul can be 8, 10, or 16, in which case the number supplied is assumed to be of that form (and in the case of 16, to lack any 0x prefix). It can also be 0, in which case the number is examined for a leading zero or a leading 0x to determine its base. The dstlen parameter of ultot specifies the size of the dst parameter; under no circumstances are more than dstlen bytes written to dst. A result that will not fit is truncated. Dstlen can be zero, in which case dst need not be valid and no result is written, but the return value is unaffected; in all other cases, the (possibly truncated) result is NUL-terminated. The libreswan.h header file defines a constant, ULTOT_BUF, which is the size of a buffer just large enough for worst-case results. The format parameter of ultot must be one of: 'o' octal conversion with leading 0  8 octal conversion with no leading 0 'd' decimal conversion 10 same as d 'x' hexadecimal conversion, including leading 0x 16 hexadecimal conversion with no leading 0x 17 like 16 except padded on left with 0s to eight digits (full width of a 32-bit number) Ttoul returns NULL for success and a pointer to a string-literal error message for failure; see DIAGNOSTICS. Ultot returns 0 for a failure, and otherwise returns the size of buffer that would be needed to accommodate the full conversion result, including terminating NUL (it is the caller's responsibility to check this against the size of the provided buffer to determine whether truncation has occurred). SEE ALSO atol3, strtoul3 DIAGNOSTICS Fatal errors in ttoul are: empty input; unknown base; non-digit character found; number too large for an unsigned long. Ttoulb adds an error for exceeding the upper bound. Fatal errors in ultot are: unknown format. HISTORY Written for the FreeS/WAN project by Henry Spencer. BUGS Conversion of 0 with format o yields 00. Ultot format 17 is a bit of a kludge. The restriction of error reports to literal strings (so that callers don't need to worry about freeing them or copying them) does limit the precision of error reporting. The error-reporting convention lends itself to slightly obscure code, because many readers will not think of NULL as signifying success. A good way to make it clearer is to write something like: const char *error; error = ttoul( /* ... */ ); if (error != NULL) { /* something went wrong */ libreswan-3.32/lib/libswan/ttoul.c000066400000000000000000000054131365625662500171720ustar00rootroot00000000000000/* * convert from text form of unsigned long to binary * * Copyright (C) 2000 Henry Spencer. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. */ #include /* for ULONG_MAX */ #include #include "libreswan.h" /* * ttoul - convert text substring to unsigned long number */ err_t /* NULL for success, else string literal */ ttoul(src, srclen, base, resultp) const char *src; size_t srclen; /* 0 means strlen(src) */ int base; /* 0 means figure it out */ unsigned long *resultp; { const char *stop; static const char hex[] = "0123456789abcdef"; static const char uchex[] = "0123456789ABCDEF"; int d; char c; const char *p; unsigned long r; unsigned long rlimit; int dlimit; if (srclen == 0) srclen = strlen(src); if (srclen == 0) return "empty string"; if (base == 0) { if (srclen > 2 && *src == '0' && (*(src + 1) == 'x' || *(src + 1) == 'X')) return ttoul(src + 2, srclen - 2, 16, resultp); if (srclen > 1 && *src == '0') return ttoul(src + 1, srclen - 1, 8, resultp); return ttoul(src, srclen, 10, resultp); } if (base != 8 && base != 10 && base != 16) return "unsupported number base"; r = 0; stop = src + srclen; if (base == 16) { while (src < stop) { c = *src++; p = strchr(hex, c); if (p != NULL) { d = p - hex; } else { p = strchr(uchex, c); if (p == NULL) return "non-hex digit in hex number"; d = p - uchex; } r = (r << 4) | d; } /* defer length check to catch invalid digits first */ if (srclen > sizeof(unsigned long) * 2) return "hex number too long"; } else { rlimit = ULONG_MAX / base; dlimit = (int)(ULONG_MAX - rlimit * base); while (src < stop) { c = *src++; d = c - '0'; if (d < 0 || d >= base) return "non-digit in number"; if (r > rlimit || (r == rlimit && d > dlimit)) return "unsigned-long overflow"; r = r * base + d; } } *resultp = r; return NULL; } err_t /* NULL for success, else string literal */ ttoulb(src, srclen, base, upb, resultp) const char *src; size_t srclen; /* 0 means strlen(src) */ int base; /* 0 means figure it out */ unsigned long upb; /* upper bound */ unsigned long *resultp; { const char *ugh = ttoul(src, srclen, base, resultp); return ugh != NULL ? ugh : *resultp > upb ? "too large" : NULL; } libreswan-3.32/lib/libswan/ultot.c000066400000000000000000000034001365625662500171640ustar00rootroot00000000000000/* * convert unsigned long to text * Copyright (C) 2000 Henry Spencer. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. */ #include #include "libreswan.h" /* - ultot - convert unsigned long to text */ size_t /* length required for full conversion */ ultot(n, base, dst, dstlen) unsigned long n; int base; char *dst; /* need not be valid if dstlen is 0 */ size_t dstlen; { char buf[3 * sizeof(unsigned long) + 1]; char *bufend = buf + sizeof(buf); size_t len; char *p; static const char hex[] = "0123456789abcdef"; # define HEX32 (32 / 4) p = bufend; *--p = '\0'; switch (base) { case 10: case 'd': do { *--p = n % 10 + '0'; n /= 10; } while (n != 0); break; case 16: case 17: case 'x': do { *--p = hex[n & 0xf]; n >>= 4; } while (n != 0); if (base == 17) while (bufend - p < HEX32 + 1) *--p = '0'; if (base == 'x') { *--p = 'x'; *--p = '0'; } break; case 8: case 'o': do { *--p = (n & 07) + '0'; n >>= 3; } while (n != 0); if (base == 'o') *--p = '0'; break; default: return 0; break; } len = bufend - p; if (dstlen > 0) { if (len > dstlen) *(p + dstlen - 1) = '\0'; strcpy(dst, p); } return len; } libreswan-3.32/lib/libswan/unbound.c000066400000000000000000000215531365625662500175000ustar00rootroot00000000000000/* * Use libunbound to use DNSSEC supported resolving. * * Copyright (C) 2012 Paul Wouters * Copyright (C) 2017-2019 Paul Wouters * Copyright (C) 2017 Antony Antony * Copyright (C) 2019-2019 Stepan Broz * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef USE_DNSSEC # error this file should only be compiled when using DNSSEC #endif #include #include #include #include #include #include #include #include #include #include #include #include /* from unbound devel */ #include /* from unbound devel */ #include "dnssec.h" #include "constants.h" #include "lswlog.h" static struct ub_ctx *dns_ctx = NULL; void unbound_ctx_free(void) { if (dns_ctx != NULL) { ub_ctx_delete(dns_ctx); dns_ctx = NULL; } } static int globugh_ta(const char *epath, int eerrno) { LOG_ERRNO(eerrno, "problem with trusted anchor file \"%s\"", epath); return 1; /* stop glob */ } static void unbound_ctx_config(bool do_dnssec, const char *rootfile, const char *trusted) { int ugh; if (DBGP(DBG_DNS)) { ub_ctx_debuglevel(dns_ctx, 5); DBG_log("unbound context created - setting debug level to 5"); }; /* lookup from /etc/hosts before DNS lookups as people expect that */ ugh = ub_ctx_hosts(dns_ctx, "/etc/hosts"); if (ugh != 0) { loglog(RC_LOG_SERIOUS, "error reading hosts: %s: %s", ub_strerror(ugh), strerror(errno)); } else { DBGF(DBG_DNS, "/etc/hosts lookups activated"); } /* * Use /etc/resolv.conf as forwarding cache - we expect people * to reconfigure this file if they need to work around DHCP DNS * obtained servers. */ /* * ??? ub_ctx_resolvconf is not currently documented to set errno. * Private communications with W.C.A. Wijngaards 2017 October: * "Is errno is meaningful after a failed call to libunbound?" * "Yes it is. Specifically for the error-to-read-file case. * Not other cases (eg. socket errors happen too far away in the code)." */ errno = 0; ugh = ub_ctx_resolvconf(dns_ctx, "/etc/resolv.conf"); if (ugh != 0) { int e = errno; /* protect value from ub_strerror */ loglog(RC_LOG_SERIOUS, "error reading /etc/resolv.conf: %s: [errno: %s]", ub_strerror(ugh), strerror(e)); } else { DBGF(DBG_DNS, "/etc/resolv.conf usage activated"); } /* * Limit outgoing ports to those allowed by common SELinux policy */ errno = 0; ugh = ub_ctx_set_option(dns_ctx, "outgoing-port-avoid:", "0-65535"); if (ugh != 0) { loglog(RC_LOG_SERIOUS, "error setting outgoing-port-avoid: %s: %s", ub_strerror(ugh), strerror(errno)); } else { DBGF(DBG_DNS, "outgoing-port-avoid set 0-65535"); } errno = 0; ugh = ub_ctx_set_option(dns_ctx, "outgoing-port-permit:", "32768-60999"); if (ugh != 0) { loglog(RC_LOG_SERIOUS, "error setting outgoing-port-permit: %s: %s", ub_strerror(ugh), strerror(errno)); } else { DBGF(DBG_DNS, "outgoing-port-permit set 32768-60999"); } if (!do_dnssec) { /* No DNSSEC - nothing more to configure */ DBGF(DBG_DNS, "dnssec validation disabled by configuration"); return; } /* Only DNSSEC related configuration from here */ if (rootfile == NULL) { if (trusted == NULL) { loglog(RC_LOG_SERIOUS, "dnssec-enable=yes but no dnssec-rootkey-file or trust anchors specified."); loglog(RC_LOG_SERIOUS, "WARNING: DNSSEC validation disabled"); return; } else { loglog(RC_LOG_SERIOUS, "dnssec-enable=yes but no dnssec-rootkey-file specified. Additional trust anchor file MUST include a root trust anchor or DNSSEC validation will be disabled"); } } else { DBGF(DBG_DNS, "Loading dnssec root key from:%s", rootfile); errno = 0; ugh = ub_ctx_add_ta_file(dns_ctx, rootfile); if (ugh != 0) { int e = errno; /* protect value from ub_strerror */ loglog(RC_LOG_SERIOUS, "error adding dnssec root key: %s [errno: %s]", ub_strerror(ugh), strerror(e)); loglog(RC_LOG_SERIOUS, "WARNING: DNSSEC validation disabled"); } } if (trusted == NULL) { DBGF(DBG_DNS, "No additional dnssec trust anchors defined via dnssec-trusted= option"); } else { glob_t globbuf; char **fnp; int r = glob(trusted, GLOB_ERR, globugh_ta, &globbuf); switch (r) { case 0: /* success */ for (fnp = globbuf.gl_pathv; fnp != NULL && *fnp != NULL; fnp++) { ugh = ub_ctx_add_ta_file(dns_ctx, *fnp); if (ugh != 0) { loglog(RC_LOG_SERIOUS, "Ignored trusted key file %s: %s", *fnp, ub_strerror(ugh)); } else { DBGF(DBG_DNS, "Added contents of trusted key file %s to unbound resolver context", *fnp); } } break; case GLOB_NOSPACE: loglog(RC_LOG_SERIOUS, "out of space processing dnssec-trusted= argument: %s", trusted); break; case GLOB_ABORTED: /* already logged by globugh_ta */ break; case GLOB_NOMATCH: loglog(RC_LOG_SERIOUS, "no trust anchor files matched '%s'", trusted); break; default: loglog(RC_LOG_SERIOUS, "trusted key file '%s': unknown glob error %d", trusted, r); break; } globfree(&globbuf); } } /* * initialize a ub_ctx for asynchronous calls using libevent from pluto. * only call once */ bool unbound_event_init(struct event_base *eb, bool do_dnssec, const char *rootfile, const char *trusted) { passert(dns_ctx == NULL); /* block re-entry to the function */ dns_ctx = ub_ctx_create_event(eb); if (dns_ctx == NULL) { loglog(RC_LOG_SERIOUS, "Failed to initialize unbound libevent ABI, please recompile libunbound with libevent support or recompile libreswan without USE_DNSSEC"); return FALSE; } unbound_ctx_config(do_dnssec, rootfile, trusted); return TRUE; } /* * initialize a ub_ct for blocking dns calls. Do not call from pluto. * Call this function once directly, such as addconn. * dns_ctx is static in this file. call unbound_ctx_free() to free it. */ void unbound_sync_init(bool do_dnssec, const char *rootfile, const char *trusted) { passert(dns_ctx == NULL); /* block re-entry to the function */ dns_ctx = ub_ctx_create(); passert(dns_ctx != NULL); unbound_ctx_config(do_dnssec, rootfile, trusted); } /* * synchronous blocking resolving - simple replacement of ttoaddr() * src_len == 0 means "apply strlen" * af == AF_UNSPEC means "try both families" */ bool unbound_resolve(char *src, size_t srclen, int af, ip_address *ipaddr) { /* 28 = AAAA record, 1 = A record */ const int qtype = (af == AF_INET6) ? 28 : 1; struct ub_result *result; passert(dns_ctx != NULL); if (srclen == 0) { srclen = strlen(src); if (srclen == 0) { libreswan_log("empty hostname in host lookup"); return FALSE; } } { int ugh = ub_resolve(dns_ctx, src, qtype, 1 /* CLASS IN */, &result); if (ugh != 0) { libreswan_log("unbound error: %s", ub_strerror(ugh)); ub_resolve_free(result); return FALSE; } } if (result->bogus) { libreswan_log("ERROR: %s failed DNSSEC validation!", result->qname); ub_resolve_free(result); return FALSE; } if (!result->havedata) { if (result->secure) { DBGF(DBG_DNS, "Validated reply proves '%s' does not exist", src); } else { DBGF(DBG_DNS, "Failed to resolve '%s' (%s)", src, result->bogus ? "BOGUS" : "insecure"); } ub_resolve_free(result); return FALSE; } else if (!result->bogus) { if (!result->secure) { DBGF(DBG_DNS, "warning: %s lookup was not protected by DNSSEC!", result->qname); } } #if 0 { int i = 0; DBG_log("The result has:"); DBG_log("qname: %s", result->qname); DBG_log("qtype: %d", result->qtype); DBG_log("qclass: %d", result->qclass); if (result->canonname) DBG_log("canonical name: %s", result->canonname); DBG_log("DNS rcode: %d", result->rcode); for (i = 0; result->data[i] != NULL; i++) { DBG_log("result data element %d has length %d", i, result->len[i]); } DBG_log("result has %d data element(s)", i); } #endif /* XXX: for now pick the first one and return that */ passert(result->data[0] != NULL); { char dst[INET6_ADDRSTRLEN]; err_t err = tnatoaddr( inet_ntop(af, result->data[0], dst, (af == AF_INET) ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN), 0, af, ipaddr); ub_resolve_free(result); if (err == NULL) { DBGF(DBG_DNS, "success for %s lookup", (af == AF_INET) ? "IPv4" : "IPv6"); return TRUE; } else { libreswan_log("tnatoaddr failed in unbound_resolve()"); return FALSE; } } } struct ub_ctx * get_unbound_ctx(void) { return dns_ctx; } libreswan-3.32/lib/libswan/v1_proposals.c000066400000000000000000000360311365625662500204530ustar00rootroot00000000000000/* V1 algorithm proposal parsing, for libreswan * * Copyright (C) 2012 Paul Wouters * Copyright (C) 2015-2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include #include #include "lswlog.h" #include "lswalloc.h" #include "constants.h" #include "proposals.h" #include "ike_alg.h" #include "ike_alg_integ.h" #include "ike_alg_dh.h" #include "alg_byname.h" /* * Add the proposal defaults for the specific algorithm. */ typedef struct v1_proposal merge_alg_default_t(struct v1_proposal proposal, const struct ike_alg *default_alg); static struct v1_proposal merge_dh_default(struct v1_proposal proposal, const struct ike_alg *default_alg) { proposal.dh = dh_desc(default_alg); return proposal; } static struct v1_proposal merge_encrypt_default(struct v1_proposal proposal, const struct ike_alg *default_alg) { proposal.encrypt = encrypt_desc(default_alg); return proposal; } static struct v1_proposal merge_prf_default(struct v1_proposal proposal, const struct ike_alg *default_alg) { proposal.prf = prf_desc(default_alg); return proposal; } static struct v1_proposal merge_integ_default(struct v1_proposal proposal, const struct ike_alg *default_alg) { proposal.integ = integ_desc(default_alg); return proposal; } static bool add_proposal_defaults(struct proposal_parser *parser, const struct proposal_defaults *defaults, struct proposals *proposals, const struct v1_proposal *proposal); static bool add_alg_defaults(struct proposal_parser *parser, const struct proposal_defaults *defaults, struct proposals *proposals, const struct v1_proposal *proposal, const struct ike_alg_type *type, const struct ike_alg **default_algs, merge_alg_default_t *merge_alg_default) { /* * Use VALID_ALG to add the valid algorithms into VALID_ALGS. */ for (const struct ike_alg **default_alg = default_algs; *default_alg; default_alg++) { const struct ike_alg *alg = *default_alg; if (!alg_byname_ok(parser, alg, shunk1(alg->name))) { DBG(DBG_PROPOSAL_PARSER, DBG_log("skipping default %s", parser->error)); parser->error[0] = '\0'; continue; } /* add it */ DBG(DBG_PROPOSAL_PARSER, DBG_log("adding default %s %s", ike_alg_type_name(type), alg->name)); struct v1_proposal merged_proposal = merge_alg_default(*proposal, *default_alg); if (!add_proposal_defaults(parser, defaults, proposals, &merged_proposal)) { passert(parser->error[0] != '\0'); return false; } } return true; } /* * Validate the proposal and, suppressing duplicates, add it to the * proposal list. */ static bool add_proposal(struct proposal_parser *parser, struct proposals *proposals, const struct v1_proposal *proposal) { struct proposal *new = alloc_proposal(parser); if (proposal->encrypt != NULL) { append_algorithm(parser, new, &proposal->encrypt->common, proposal->enckeylen); } #define A(NAME) \ if (proposal->NAME != NULL) { \ append_algorithm(parser, new, &proposal->NAME->common, \ 0/*enckeylen*/); \ } A(prf); A(integ); A(dh); #undef A /* back end? */ if (!proposal->protocol->proposal_ok(parser, new)) { free_proposal(&new); return false; } append_proposal(proposals, &new); return true; } /* * For all the algorithms, when an algorithm is missing (NULL), and * there are defaults, add them. */ static bool add_proposal_defaults(struct proposal_parser *parser, const struct proposal_defaults *defaults, struct proposals *proposals, const struct v1_proposal *proposal) { /* * Note that the order in which things are recursively added - * MODP, ENCR, PRF/HASH - affects test results. It determines * things like the order of proposals. */ if (proposal->dh == NULL && defaults != NULL && defaults->dh != NULL) { return add_alg_defaults(parser, defaults, proposals, proposal, &ike_alg_dh, defaults->dh, merge_dh_default); } else if (proposal->encrypt == NULL && defaults != NULL && defaults->encrypt != NULL) { return add_alg_defaults(parser, defaults, proposals, proposal, &ike_alg_encrypt, defaults->encrypt, merge_encrypt_default); } else if (proposal->prf == NULL && defaults != NULL && defaults->prf != NULL) { return add_alg_defaults(parser, defaults, proposals, proposal, &ike_alg_prf, defaults->prf, merge_prf_default); } else if (proposal->integ == NULL && proposal->encrypt != NULL && encrypt_desc_is_aead(proposal->encrypt)) { /* * Since AEAD, integrity is always 'none'. */ struct v1_proposal merged_proposal = *proposal; merged_proposal.integ = &ike_alg_integ_none; return add_proposal_defaults(parser, defaults, proposals, &merged_proposal); } else if (proposal->integ == NULL && defaults != NULL && defaults->integ != NULL) { return add_alg_defaults(parser, defaults, proposals, proposal, &ike_alg_integ, defaults->integ, merge_integ_default); } else if (proposal->integ == NULL && proposal->prf != NULL && proposal->encrypt != NULL && !encrypt_desc_is_aead(proposal->encrypt)) { /* * Since non-AEAD, use an integrity algorithm that is * implemented using the PRF. */ struct v1_proposal merged_proposal = *proposal; for (const struct integ_desc **algp = next_integ_desc(NULL); algp != NULL; algp = next_integ_desc(algp)) { const struct integ_desc *alg = *algp; if (alg->prf == proposal->prf) { merged_proposal.integ = alg; break; } } if (merged_proposal.integ == NULL) { proposal_error(parser, "%s integrity derived from PRF '%s' is not supported", proposal->protocol->name, proposal->prf->common.name); return false; } return add_proposal_defaults(parser, defaults, proposals, &merged_proposal); } else { return add_proposal(parser, proposals, proposal); } } static bool merge_default_proposals(struct proposal_parser *parser, struct proposals *proposals, const struct v1_proposal *proposal) { /* * If there's a hint of IKEv1 being enabled then prefer its * larger set of defaults. * * This should increase the odds of both ends interoperating. * * For instance, the IKEv2 defaults were preferred and one end * has ikev2=never then, in aggressive mode, things don't * work. */ passert(parser->policy->version < elemsof(proposal->protocol->defaults)); const struct proposal_defaults *defaults = proposal->protocol->defaults[parser->policy->version]; return add_proposal_defaults(parser, defaults, proposals, proposal); } static int parse_eklen(struct proposal_parser *parser, shunk_t buf) { /* convert - if present */ char *end = NULL; long eklen = strtol(buf.ptr, &end, 10); if (buf.ptr + buf.len != end) { proposal_error(parser, "encryption key length '"PRI_SHUNK"' contains a non-numeric character", pri_shunk(buf)); return 0; } if (eklen >= INT_MAX) { proposal_error(parser, "encryption key length '"PRI_SHUNK"' WAY too big", pri_shunk(buf)); return 0; } if (eklen == 0) { proposal_error(parser, "encryption key length is zero"); return 0; } return eklen; } /* * Try to parse any of -, _, * , or . Strings like aes_gcm_16 and * aes_gcm_16_256 end up in alg[0], while strings like aes_gcm_16-256 * end up in alg[0]-alg[1]. */ struct token { char sep; shunk_t alg; }; static bool parse_encrypt(struct proposal_parser *parser, struct token **tokens, struct v1_proposal *proposal) { shunk_t ealg = (*tokens)[0].alg; shunk_t eklen = (*tokens)[1].alg; if (eklen.len > 0 && shunk_isdigit(eklen, 0)) { /* assume - */ int enckeylen = parse_eklen(parser, eklen); if (enckeylen <= 0) { passert(parser->error[0] != '\0'); return false; } /* print - */ shunk_t print_name = shunk2(ealg.ptr, eklen.ptr + eklen.len - ealg.ptr); proposal->enckeylen = enckeylen; proposal->encrypt = encrypt_desc(encrypt_alg_byname(parser, ealg, proposal->enckeylen, print_name)); /* Was - rejected? */ if (parser->error[0] != '\0') { return false; } *tokens += 2; /* consume both tokens */ return true; } /* try */ shunk_t print_name = ealg; proposal->encrypt = encrypt_desc(encrypt_alg_byname(parser, ealg, proposal->enckeylen, print_name)); if (parser->error[0] != '\0') { /* * Could it be or _? Work * backwards skipping any digits. */ size_t end = ealg.len; while (end > 0 && shunk_isdigit(ealg, end-1)) { end--; } if (end == ealg.len) { /* * no trailing digits and was * rejected by above); error still contains * message from not finding just . */ passert(parser->error[0] != '\0'); return false; } /* try to convert */ shunk_t eklen = shunk_slice(ealg, end, ealg.len); int enckeylen = parse_eklen(parser, eklen); if (enckeylen <= 0) { passert(parser->error[0] != '\0'); return false; } proposal->enckeylen = enckeylen; /* * trim from ; and then trim any * trailing '_' */ ealg = shunk_slice(ealg, 0, end); if (shunk_ischar(ealg, ealg.len-1, "_")) { ealg = shunk_slice(ealg, 0, end-1); } /* try again */ parser->error[0] = '\0'; proposal->encrypt = encrypt_desc(encrypt_alg_byname(parser, ealg, proposal->enckeylen, print_name)); if (parser->error[0] != '\0') { return false; } } *tokens += 1; /* consume one token */ return true; } static bool parser_proposals_add(struct proposal_parser *parser, struct token *tokens, struct v1_proposal proposal, struct proposals *proposals) { LSWDBGP(DBG_PROPOSAL_PARSER, buf) { lswlogs(buf, "algs:"); for (struct token *token = tokens; token->alg.ptr != NULL; token++) { lswlogf(buf, " algs[%tu] = '"PRI_SHUNK"'", token - tokens, pri_shunk(token->alg)); } } bool lookup_encrypt = parser->protocol->encrypt; if (!lookup_encrypt && IMPAIR(PROPOSAL_PARSER)) { /* Force lookup, will discard any error. */ lookup_encrypt = true; } if (lookup_encrypt && tokens->alg.ptr != NULL && tokens->sep != ';') { if (!parse_encrypt(parser, &tokens, &proposal)) { if (IMPAIR(PROPOSAL_PARSER)) { /* ignore the lookup and stumble on */ parser->error[0] = '\0'; } else { passert(parser->error[0] != '\0'); return false; } } } bool lookup_prf = parser->protocol->prf; if (!lookup_prf && IMPAIR(PROPOSAL_PARSER)) { /* * When impaired, only force PRF lookup when the the * token after this one is a valid INTEG algorithm. * Otherwise something like ah=sha1 gets parsed as * ah=[encr]-sha1-[integ]-[dh] instead of * ah=[encr]-[prf]-sha1-[dh]. */ shunk_t prf = tokens[0].alg; shunk_t integ = tokens[1].alg; if (prf.ptr != NULL && integ.ptr != NULL) { lookup_prf = (alg_byname(parser, IKE_ALG_INTEG, integ, integ) != NULL); parser->error[0] = '\0'; } } if (lookup_prf && tokens->alg.ptr != NULL && tokens->sep != ';') { shunk_t prf = tokens[0].alg; proposal.prf = prf_desc(alg_byname(parser, IKE_ALG_PRF, prf, prf)); if (parser->error[0] != '\0') { return false; } tokens += 1; /* consume one arg */ } /* * By default, don't allow IKE's [...]---[....]. * Instead fill in integrity using the above PRF. * * XXX: The parser and output isn't consistent in that for ESP * it parses - but for IKE it parses * -. This seems to lead to confusion when * printing proposals - ike=aes_gcm-sha1 gets mis-read as as * using sha1 as integrity. ike-aes_gcm-none-sha1 would * clarify this but that makes for a fun parse. */ bool lookup_integ = (!parser->protocol->prf && parser->protocol->integ); if (!lookup_integ && IMPAIR(PROPOSAL_PARSER)) { /* force things */ lookup_integ = true; } if (lookup_integ && tokens->alg.ptr != NULL && tokens->sep != ';') { shunk_t integ = tokens[0].alg; proposal.integ = integ_desc(alg_byname(parser, IKE_ALG_INTEG, integ, integ)); if (parser->error[0] != '\0') { if (tokens[1].alg.ptr != NULL) { /* * This alg should have been * integrity, since the next would be * DH; error applies. */ passert(parser->error[0] != '\0'); return false; } if (tokens[1].alg.ptr == NULL && !parser->protocol->prf) { /* * Only one arg, integrity is preferred * to DH (and no PRF); error applies. */ passert(parser->error[0] != '\0'); return false; } /* let DH try */ parser->error[0] = '\0'; } else { tokens += 1; /* consume one arg */ } } bool lookup_dh = parser->protocol->dh || IMPAIR(PROPOSAL_PARSER); if (lookup_dh && tokens->alg.ptr != NULL) { shunk_t dh = tokens[0].alg; proposal.dh = dh_desc(alg_byname(parser, IKE_ALG_DH, dh, dh)); if (parser->error[0] != '\0') { return false; } tokens += 1; /* consume one arg */ } if (tokens->alg.ptr != NULL) { proposal_error(parser, "'"PRI_SHUNK"' unexpected", pri_shunk(tokens[0].alg)); return false; } if (IMPAIR(PROPOSAL_PARSER)) { return add_proposal(parser, proposals, &proposal); } else { return merge_default_proposals(parser, proposals, &proposal); } } bool v1_proposals_parse_str(struct proposal_parser *parser, struct proposals *proposals, shunk_t alg_str) { DBG(DBG_PROPOSAL_PARSER, DBG_log("parsing '"PRI_SHUNK"' for %s", pri_shunk(alg_str), parser->protocol->name)); if (alg_str.len == 0) { /* XXX: hack to keep testsuite happy */ proposal_error(parser, "String ended with invalid char, just after \"\""); return false; } shunk_t prop_ptr = alg_str; do { /* find the next proposal */ shunk_t prop = shunk_token(&prop_ptr, NULL, ","); /* parse it */ struct token tokens[8]; zero(&tokens); struct token *token = tokens; shunk_t alg_ptr = prop; char last_sep = '\0'; do { if (token + 1 >= tokens+elemsof(tokens)) { /* space for NULL? */ proposal_error(parser, "proposal too long"); return false; } /* find the next alg */ char alg_sep; shunk_t alg = shunk_token(&alg_ptr, &alg_sep, "-;,"); *token++ = (struct token) { .alg = alg, .sep = last_sep, }; last_sep = alg_sep; /* separator before this token */ } while (alg_ptr.len > 0); struct v1_proposal proposal = { .protocol = parser->protocol, }; if (!parser_proposals_add(parser, tokens, proposal, proposals)) { passert(parser->error[0] != '\0'); return false; } } while (prop_ptr.len > 0); return true; } libreswan-3.32/lib/libswan/v2_proposals.c000066400000000000000000000320111365625662500204460ustar00rootroot00000000000000/* V2 algorithm proposal parsing, for libreswan * * Copyright (C) 2019 Andrew Cagney * Copyright (C) 2019 D. Hugh Redelmeier * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include #include #include "lswlog.h" #include "lswalloc.h" #include "constants.h" #include "proposals.h" #include "ike_alg.h" #include "ike_alg_integ.h" #include "ike_alg_dh.h" #include "alg_byname.h" /* * No questions hack to either return 'false' for parsing token * failed, or 'true' and warn because forced parsing is enabled. */ static bool warning_or_false(struct proposal_parser *parser, const char *what, shunk_t print) { pexpect(parser->error[0] != '\0'); bool result; if (parser->policy->ignore_parser_errors) { /* * XXX: the algorithm might be unknown, or might be * known but not enabled due to FIPS or KLIPS, or ...? */ parser->policy->warning("ignoring %s %s %s algorithm '"PRI_SHUNK"'", enum_name(&ike_version_names, parser->policy->version), parser->protocol->name, /* ESP|IKE|AH */ what, pri_shunk(print)); result = true; } else { DBGF(DBG_PROPOSAL_PARSER, "lookup for %s algorithm '"PRI_SHUNK"' failed", what, pri_shunk(print)); result = false; } return result; } /* * For all the algorithms, when an algorithm is missing (NULL), and * there are defaults, add them. */ static void merge_algorithms(struct proposal_parser *parser, struct proposal *proposal, enum proposal_algorithm algorithm, const struct ike_alg **defaults) { if (defaults == NULL) { return; } if (next_algorithm(proposal, algorithm, NULL) != NULL) { return; } for (const struct ike_alg **alg = defaults; (*alg) != NULL; alg++) { append_algorithm(parser, proposal, *alg, 0); } } static bool merge_defaults(struct proposal_parser *parser, struct proposal *proposal) { pexpect(parser->policy->version < elemsof(parser->protocol->defaults)); const struct proposal_defaults *defaults = parser->protocol->defaults[parser->policy->version]; merge_algorithms(parser, proposal, PROPOSAL_encrypt, defaults->encrypt); merge_algorithms(parser, proposal, PROPOSAL_prf, defaults->prf); if (next_algorithm(proposal, PROPOSAL_integ, NULL) == NULL) { if (proposal_encrypt_aead(proposal)) { /* * Since AEAD, integrity is always 'none'. */ append_algorithm(parser, proposal, &ike_alg_integ_none.common, 0); } else if (defaults->integ != NULL) { /* * Merge in the defaults. */ merge_algorithms(parser, proposal, PROPOSAL_integ, defaults->integ); } else if (next_algorithm(proposal, PROPOSAL_prf, NULL) != NULL && proposal_encrypt_norm(proposal)) { /* * Since non-AEAD, use integrity algorithms * that are implemented using the PRFs. */ FOR_EACH_ALGORITHM(proposal, prf, prf) { const struct integ_desc *integ = NULL; for (const struct integ_desc **integp = next_integ_desc(NULL); integp != NULL; integp = next_integ_desc(integp)) { if ((*integp)->prf != NULL && &(*integp)->prf->common == prf->desc) { integ = *integp; break; } } if (integ == NULL) { proposal_error(parser, "%s integrity derived from PRF '%s' is not supported", parser->protocol->name, prf->desc->name); return false; } append_algorithm(parser, proposal, &integ->common, 0); } } } merge_algorithms(parser, proposal, PROPOSAL_dh, defaults->dh); return true; } static bool parse_alg(struct proposal_parser *parser, struct proposal *proposal, const struct ike_alg_type *alg_type, shunk_t token) { if (token.len == 0) { /* will error at end */ return false; } const struct ike_alg *alg = alg_byname(parser, alg_type, token, token/*print*/); if (alg == NULL) { return warning_or_false(parser, ike_alg_type_name(alg_type), token); } append_algorithm(parser, proposal, alg, 0/*enckeylen*/); return true; } /* * tokenize into */ struct token { char delim; char next_delim; shunk_t alg; shunk_t input; }; static void next(struct token *token) { token->delim = token->next_delim; token->alg = shunk_token(&token->input, &token->next_delim, "-;+"); if (DBGP(DBG_PROPOSAL_PARSER)) { if (token->alg.ptr == NULL) { DBG_log("delim: n/a alg: end-of-input"); } else { DBG_log("delim: '%c' alg: '"PRI_SHUNK"'", token->delim, pri_shunk(token->alg)); } } } /* * Try to parse any of -, _, * , or using some look-ahead. */ static int parse_eklen(struct proposal_parser *parser, shunk_t buf) { /* convert - if present */ char *end = NULL; long eklen = strtol(buf.ptr, &end, 10); if (buf.ptr + buf.len != end) { proposal_error(parser, "encryption key length '"PRI_SHUNK"' contains a non-numeric character", pri_shunk(buf)); return 0; } if (eklen >= INT_MAX) { proposal_error(parser, "encryption key length '"PRI_SHUNK"' WAY too big", pri_shunk(buf)); return 0; } if (eklen == 0) { proposal_error(parser, "encryption key length is zero"); return 0; } return eklen; } static bool parse_encrypt(struct proposal_parser *parser, struct proposal *proposal, struct token *token) { if (token->alg.len == 0) { return false; } /* * Does it match -? * * Use lookahead to check first. If it starts with a * digit then just assume - and error out if it is * not so. */ { shunk_t ealg = token->alg; struct token lookahead = *token; next(&lookahead); if (lookahead.delim == '-' && lookahead.alg.len > 0 && shunk_isdigit(lookahead.alg, 0)) { shunk_t eklen = lookahead.alg; /* assume - */ int enckeylen = parse_eklen(parser, eklen); if (enckeylen <= 0) { pexpect(parser->error[0] != '\0'); return false; } /* print "-" in errors */ shunk_t print = shunk2(ealg.ptr, eklen.ptr + eklen.len - ealg.ptr); const struct ike_alg *alg = encrypt_alg_byname(parser, ealg, enckeylen, print); if (alg == NULL) { DBGF(DBG_PROPOSAL_PARSER, "byname('"PRI_SHUNK"') with ='"PRI_SHUNK"' failed: %s", pri_shunk(ealg), pri_shunk(eklen), parser->error); return false; } *token = lookahead; append_algorithm(parser, proposal, alg, enckeylen); return true; } } /* * Does it match (without any _ suffix?) */ const shunk_t print = token->alg; { shunk_t ealg = token->alg; const struct ike_alg *alg = encrypt_alg_byname(parser, ealg, 0/*enckeylen*/, print); if (alg != NULL) { append_algorithm(parser, proposal, alg, 0/*enckeylen*/); return true; } } /* buffer still contains error from lookup */ pexpect(parser->error[0] != '\0'); /* * Does it match or _? Strip * trailing digits from to form and then try * doing a lookup. */ { shunk_t ealg = token->alg; size_t end = ealg.len; while (end > 0 && shunk_isdigit(ealg, end-1)) { end--; } if (end == ealg.len) { /* * no trailing digits and was * rejected by above); error still contains * message from not finding just . */ return warning_or_false(parser, "encryption", print); } /* try to convert */ shunk_t eklen = shunk_slice(ealg, end, ealg.len); int enckeylen = parse_eklen(parser, eklen); if (enckeylen <= 0) { pexpect(parser->error[0] != '\0'); return false; } /* * trim from ; and then trim any * trailing '_' */ ealg = shunk_slice(ealg, 0, end); if (shunk_ischar(ealg, ealg.len-1, "_")) { ealg = shunk_slice(ealg, 0, ealg.len-1); } /* try again */ const struct ike_alg *alg = encrypt_alg_byname(parser, ealg, enckeylen, print); if (alg != NULL) { append_algorithm(parser, proposal, alg, enckeylen); return true; } } return warning_or_false(parser, "encryption", print); } static bool parse_proposal(struct proposal_parser *parser, struct proposals *proposals, shunk_t input) { if (DBGP(DBG_PROPOSAL_PARSER)) { DBG_log("proposal: '"PRI_SHUNK"'", pri_shunk(input)); } char error[sizeof(parser->error)] = ""; struct proposal *proposal = alloc_proposal(parser); struct token token = { .input = input, }; next(&token); /* * Encryption. * * When encryption is part of the proposal, at least one * (encryption algorithm) token should be present, further * tokens are optional. * * Each token is then converted to an encryption algorithm and * added to the proposal, and any invalid algorithm causing * the whole proposal to be rejected. * * However, when either ignore IGNORE_PARSER_ERRORS or IMPAIR, * invalid algorithms are instead skipped and this can result * in a proposal with no encryption algorithm. * * For instance, the encryption algorithm "AES_GCM" will be * invalid when ESP and KLIPS. Normally this proposal will be * rejected, but when IGNORE_PARSER_ERRORS (for default * proposals) the code will instead stumble on. */ if (parser->protocol->encrypt) { /* first encryption algorithm token is expected */ if (!parse_encrypt(parser, proposal, &token)) { free_proposal(&proposal); return false; } error[0] = parser->error[0] = '\0'; next(&token); /* further encryption algorithm tokens are optional */ while (token.delim == '+' && parse_encrypt(parser, proposal, &token)) { error[0] = parser->error[0] = '\0'; next(&token); } /* deal with all encryption algorithm tokens being skipped */ if (next_algorithm(proposal, PROPOSAL_encrypt, NULL) == NULL) { if (parser->policy->ignore_parser_errors) { DBGF(DBG_PROPOSAL_PARSER, "all encryption algorithms skipped; stumbling on"); free_proposal(&proposal); return true; } if (!IMPAIR(PROPOSAL_PARSER)) { PEXPECT_LOG("all encryption algorithms skipped"); free_proposal(&proposal); return false; } } } #define PARSE_ALG(STOP, ALG) \ if (error[0] == '\0' && parser->error[0] != '\0') { \ strcpy(error, parser->error); \ DBGF(DBG_PROPOSAL_PARSER, "saved first error: %s", error); \ } \ if (token.delim != STOP && \ parser->protocol->ALG && \ parse_alg(parser, proposal, &ike_alg_##ALG, token.alg)) { \ error[0] = parser->error[0] = '\0'; \ next(&token); \ while (token.delim == '+' && \ parse_alg(parser, proposal, &ike_alg_##ALG, token.alg)) { \ error[0] = parser->error[0] = '\0'; \ next(&token); \ } \ } PARSE_ALG(';', prf); /* * By default, don't allow ike=...---... but do * allow esp=...-. In the case of IKE, when integrity * is required, it is filled in using the PRF. * * XXX: The parser and output isn't consistent in that for ESP * it parses - but for IKE it parses * -. This seems to lead to confusion when * printing proposals - ike=aes_gcm-sha1 gets mis-read as as * using sha1 as integrity. ike-aes_gcm-none-sha1 would * clarify this but that makes for a fun parse. */ if (!parser->protocol->prf || IMPAIR(PROPOSAL_PARSER)) { PARSE_ALG(';', integ); } PARSE_ALG('\0', dh); if (error[0] != '\0') { DBGF(DBG_PROPOSAL_PARSER, "return first error: %s", error); free_proposal(&proposal); strcpy(parser->error, error); return false; } if (parser->error[0] != '\0') { DBGF(DBG_PROPOSAL_PARSER, "return last error: %s", parser->error); free_proposal(&proposal); return false; } if (token.alg.ptr != NULL) { proposal_error(parser, "'"PRI_SHUNK"' unexpected", pri_shunk(token.alg)); free_proposal(&proposal); return false; } if (!IMPAIR(PROPOSAL_PARSER) && !merge_defaults(parser, proposal)) { free_proposal(&proposal); return false; } /* back end? */ if (!parser->protocol->proposal_ok(parser, proposal)) { free_proposal(&proposal); return false; } append_proposal(proposals, &proposal); return true; } bool v2_proposals_parse_str(struct proposal_parser *parser, struct proposals *proposals, shunk_t input) { DBG(DBG_PROPOSAL_PARSER, DBG_log("parsing '"PRI_SHUNK"' for %s", pri_shunk(input), parser->protocol->name)); if (input.len == 0) { /* XXX: hack to keep testsuite happy */ proposal_error(parser, "String ended with invalid char, just after \"\""); return false; } do { /* find the next proposal */ shunk_t proposal = shunk_token(&input, NULL, ","); if (!parse_proposal(parser, proposals, proposal)) { pexpect(parser->error[0] != '\0'); return false; } } while (input.len > 0); return true; } libreswan-3.32/lib/libswan/version.in.c000066400000000000000000000034101365625662500201100ustar00rootroot00000000000000/* * return IPsec version information * Copyright (C) 2001 Henry Spencer. * Copyright (C) 2013 Paul Wouters * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. * */ #ifdef __KERNEL__ # include #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38) && \ !defined(AUTOCONF_INCLUDED) # include # endif # define __NO_VERSION__ # include # if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) && LINUX_VERSION_CODE >= \ KERNEL_VERSION(2, 4, 26) # include # endif #endif #include "libreswan.h" #define V "@IPSECVERSION@" /* substituted in by Makefile */ #define VID "@IPSECVIDVERSION@" /* substituted in by Makefile */ #define OUR_VENDOR_VID "OE-Libreswan-@IPSECVIDVERSION@" /* substituted in by Makefile */ static const char libreswan_number[] = V; static const char libreswan_string[] = "Libreswan " V; #ifdef __KERNEL__ static #endif const char libreswan_vendorid[] = OUR_VENDOR_VID; /* * pass version to modinfo */ #ifdef MODULE_VERSION MODULE_VERSION(V); #endif const char *ipsec_version_code(void) { return libreswan_number; } const char *ipsec_version_string(void) { return libreswan_string; } const char *ipsec_version_vendorid(void) { return libreswan_vendorid; } libreswan-3.32/lib/libswan/x509dn.c000066400000000000000000000667441365625662500170700ustar00rootroot00000000000000/* * Support of X.509 certificates and CRLs * * Copyright (C) 2000 Andreas Hess, Patric Lichtsteiner, Roger Wegmann * Copyright (C) 2001 Marco Bertossa, Andreas Schleiss * Copyright (C) 2002 Mario Strasser * Copyright (C) 2000-2004 Andreas Steffen, Zuercher Hochschule Winterthur * Copyright (C) 2003-2008 Michael C Richardson * Copyright (C) 2008 Antony Antony * Copyright (C) 2003-2010 Paul Wouters * Copyright (C) 2009 Avesh Agarwal * Copyright (C) 2012 Paul Wouters * Copyright (C) 2013-2019 D. Hugh Redelmeier * Copyright (C) 2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include #include #include "constants.h" #include "lswlog.h" #include "lswalloc.h" #include "id.h" #include "asn1.h" #include "oid.h" #include "x509.h" #include "lswconf.h" #include "ctype.h" /* coding of X.501 distinguished name */ typedef const struct { const char *name; const unsigned char *oid_ptr; size_t oid_len; asn1_t type; } x501rdn_t; /* X.501 acronyms for well known object identifiers (OIDs) */ static const unsigned char oid_ND[] = { 0x02, 0x82, 0x06, 0x01, 0x0A, 0x07, 0x14 }; static const unsigned char oid_UID[] = { 0x09, 0x92, 0x26, 0x89, 0x93, 0xF2, 0x2C, 0x64, 0x01, 0x01 }; static const unsigned char oid_DC[] = { 0x09, 0x92, 0x26, 0x89, 0x93, 0xF2, 0x2C, 0x64, 0x01, 0x19 }; static const unsigned char oid_CN[] = { 0x55, 0x04, 0x03 }; static const unsigned char oid_S[] = { 0x55, 0x04, 0x04 }; static const unsigned char oid_SN[] = { 0x55, 0x04, 0x05 }; static const unsigned char oid_C[] = { 0x55, 0x04, 0x06 }; static const unsigned char oid_L[] = { 0x55, 0x04, 0x07 }; static const unsigned char oid_ST[] = { 0x55, 0x04, 0x08 }; static const unsigned char oid_O[] = { 0x55, 0x04, 0x0A }; static const unsigned char oid_OU[] = { 0x55, 0x04, 0x0B }; static const unsigned char oid_T[] = { 0x55, 0x04, 0x0C }; static const unsigned char oid_D[] = { 0x55, 0x04, 0x0D }; static const unsigned char oid_N[] = { 0x55, 0x04, 0x29 }; static const unsigned char oid_G[] = { 0x55, 0x04, 0x2A }; static const unsigned char oid_I[] = { 0x55, 0x04, 0x2B }; static const unsigned char oid_ID[] = { 0x55, 0x04, 0x2D }; static const unsigned char oid_E[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01 }; static const unsigned char oid_UN[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x02 }; static const unsigned char oid_TCGID[] = { 0x2B, 0x06, 0x01, 0x04, 0x01, 0x89, 0x31, 0x01, 0x01, 0x02, 0x02, 0x4B }; static const x501rdn_t x501rdns[] = { # define OC(oid) oid, sizeof(oid) { "ND", OC(oid_ND), ASN1_PRINTABLESTRING }, { "UID", OC(oid_UID), ASN1_PRINTABLESTRING }, { "DC", OC(oid_DC), ASN1_PRINTABLESTRING }, { "CN", OC(oid_CN), ASN1_PRINTABLESTRING }, { "S", OC(oid_S), ASN1_PRINTABLESTRING }, { "SN", OC(oid_SN), ASN1_PRINTABLESTRING }, { "serialNumber", OC(oid_SN), ASN1_PRINTABLESTRING }, { "C", OC(oid_C), ASN1_PRINTABLESTRING }, { "L", OC(oid_L), ASN1_PRINTABLESTRING }, { "ST", OC(oid_ST), ASN1_PRINTABLESTRING }, { "O", OC(oid_O), ASN1_PRINTABLESTRING }, { "OU", OC(oid_OU), ASN1_PRINTABLESTRING }, { "T", OC(oid_T), ASN1_PRINTABLESTRING }, { "D", OC(oid_D), ASN1_PRINTABLESTRING }, { "N", OC(oid_N), ASN1_PRINTABLESTRING }, { "G", OC(oid_G), ASN1_PRINTABLESTRING }, { "I", OC(oid_I), ASN1_PRINTABLESTRING }, { "ID", OC(oid_ID), ASN1_PRINTABLESTRING }, { "E", OC(oid_E), ASN1_IA5STRING }, { "Email", OC(oid_E), ASN1_IA5STRING }, { "emailAddress", OC(oid_E), ASN1_IA5STRING }, { "UN", OC(oid_UN), ASN1_IA5STRING }, { "unstructuredName", OC(oid_UN), ASN1_IA5STRING }, { "TCGID", OC(oid_TCGID), ASN1_PRINTABLESTRING } # undef OC }; /* * Routines to iterate through a DN. * rdn: remainder of the sequence of RDNs * attribute: remainder of the current RDN. */ /* Structure of the DN: * * ASN_SEQUENCE { * for each Relative DN { * ASN1_SET { * ASN1_SEQUENCE { * ASN1_OID { * oid * } * ASN1_*STRING* { * value * } * } * } * } * } */ #define RETURN_IF_ERR(f) { err_t ugh = (f); if (ugh != NULL) return ugh; } static err_t unwrap(asn1_t ty, chunk_t *container, chunk_t *contents) { if (container->len == 0) return "missing ASN1 type"; if (container->ptr[0] != ty) return "unexpected ASN1 type"; size_t sz = asn1_length(container); if (sz == ASN1_INVALID_LENGTH) return "invalid ASN1 length"; if (sz > container->len) return "ASN1 length larger than space"; contents->ptr = container->ptr; contents->len = sz; container->ptr += sz; container->len -= sz; return NULL; } static err_t init_rdn(chunk_t dn, /* input (copy) */ chunk_t *rdn, /* output */ chunk_t *attribute, /* output */ bool *more) /* output */ { *attribute = EMPTY_CHUNK; /* a DN is a SEQUENCE OF RDNs */ RETURN_IF_ERR(unwrap(ASN1_SEQUENCE, &dn, rdn)); /* the whole DN should be this ASN1_SEQUENCE */ if (dn.len != 0) return "DN has crud after ASN1_SEQUENCE"; *more = rdn->len != 0; return NULL; } /* * Fetches the next RDN in a DN */ static err_t get_next_rdn(chunk_t *rdn, /* input/output */ chunk_t *attribute, /* input/output */ chunk_t *oid /* output */, chunk_t *value_ber, /* output */ asn1_t *value_type, /* output */ chunk_t *value_content, /* output */ bool *more) /* output */ { /* if all attributes have been parsed, get next rdn */ if (attribute->len == 0) { /* * An RDN is a SET OF attributeTypeAndValue. * Strip off the ASN1_set wrapper. */ RETURN_IF_ERR(unwrap(ASN1_SET, rdn, attribute)); } /* An attributeTypeAndValue is a SEQUENCE */ chunk_t body; RETURN_IF_ERR(unwrap(ASN1_SEQUENCE, attribute, &body)); /* extract oid from body */ RETURN_IF_ERR(unwrap(ASN1_OID, &body, oid)); /* extract string value and its type from body */ if (body.len == 0) return "no room for string's type"; *value_ber = body; *value_type = body.ptr[0]; /* ??? what types of string are legitimate? */ switch(*value_type) { case ASN1_PRINTABLESTRING: case ASN1_T61STRING: case ASN1_IA5STRING: case ASN1_UTF8STRING: case ASN1_BMPSTRING: break; default: dbg("unexpected ASN1 string type 0x%x", *value_type); return "unexpected ASN1 string type"; } RETURN_IF_ERR(unwrap(*value_type, &body, value_content)); if (body.len != 0) return "crap after OID and value pair of RDN"; /* are there any RDNs left? */ *more = rdn->len > 0 || attribute->len > 0; return NULL; } /* * Count the number of wildcard RDNs in a distinguished name; -1 signifies error. */ int dn_count_wildcards(chunk_t dn) { chunk_t rdn; chunk_t attribute; bool more; int wildcards = 0; err_t ugh = init_rdn(dn, &rdn, &attribute, &more); if (ugh != NULL) return -1; while (more) { chunk_t oid; chunk_t value_ber; asn1_t value_type; chunk_t value_content; ugh = get_next_rdn(&rdn, &attribute, &oid, &value_ber, &value_type, &value_content, &more); if (ugh != NULL) return -1; if (value_content.len == 1 && value_content.ptr[0] == '*') wildcards++; /* we have found a wildcard RDN */ } return wildcards; } /* * Formats an ASN.1 Distinguished Name into an ASCII string of * OID/value pairs. If there's a problem, return err_t (buf's * contents should be ignored). * * Since the raw output is fed to CERT_AsciiToName() and that, * according to the comments, expects RFC-1485 (1993) (A String * Representation of Distinguished Names (OSI-DS 23 (v5))) and * successors, this function should be emitting the same. * * RFC-1485 was obsoleted by RFC-1779 - A String Representation of * Distinguished Names - in 1995. * * XXX: added OID.N.N.N; added '#' prefix; added \ escape; according * to NSS bug 210584 this was all added to NSS 2019-12 years ago. * RFC-1779 was obsoleted by RFC-2253 - Lightweight Directory Access * Protocol (v3): UTF-8 String Representation of Distinguished Names - * in 1997. * * XXX: deprecated OID.N.N.N; according to NSS bug 1342137 this was * fixed 2019-2 years ago. * * RFC-2253 was obsoleted by RFC-4514 - Lightweight Directory Access * Protocol (v3): UTF-8 String Representation of Distinguished Names - * in 2006. * * Hence this tries to implement https://tools.ietf.org/html/rfc4514 * using \ for printable and \XX for non-printable. */ static err_t format_dn(jambuf_t *buf, chunk_t dn, jam_bytes_fn *jam_bytes, bool nss_compatible) { chunk_t rdn; chunk_t attribute; bool more; RETURN_IF_ERR(init_rdn(dn, &rdn, &attribute, &more)); for (bool first = TRUE; more; first = FALSE) { chunk_t oid; chunk_t value_ber; asn1_t value_type; chunk_t value_content; RETURN_IF_ERR(get_next_rdn(&rdn, &attribute, &oid, &value_ber, &value_type, &value_content, &more)); if (!first) jam(buf, ", "); /* * 2.3. Converting AttributeTypeAndValue * * The AttributeTypeAndValue is encoded as the string * representation of the AttributeType, followed by an * equals sign ('=' U+003D) character, followed by the * string representation of the AttributeValue. The * encoding of the AttributeValue is given in Section * 2.4. * * If the AttributeType is defined to have a short * name (descriptor) [RFC4512] and that short name is * known to be registered [REGISTRY] [RFC4520] as * identifying the AttributeType, that short name, a * , is used. Otherwise the AttributeType is * encoded as the dotted-decimal encoding, a * , of its OBJECT IDENTIFIER. The * and are defined in [RFC4512]. * * XXX: An early RFC defined this as OID.N.N.N but * later the OID prefix was dropped. */ /* print OID */ int oid_code = known_oid(oid); if (oid_code == OID_UNKNOWN) { /* * 2.4. Converting an AttributeValue from * ASN.1 to a String * * If the AttributeType is of the * dotted-decimal form, the AttributeValue is * represented by an number sign ('#' U+0023) * character followed by the hexadecimal * encoding of each of the octets of the BER * encoding of the X.500 AttributeValue. This * form is also used when the syntax of the * AttributeValue does not have an LDAP- * specific ([RFC4517], Section 3.1) string * encoding defined for it, or the * LDAP-specific string encoding is not * restricted to UTF-8-encoded Unicode * characters. This form may also be used in * other cases, such as when a reversible * string representation is desired (see * Section 5.2). * * XXX: i.e., N.M#BER */ const uint8_t *p = oid.ptr; /* cast void* */ const uint8_t *end = p + oid.len; /* handled above? */ if (!pexpect(p < end)) { return "OID length is zero"; } /* first two nodes encoded in single byte */ /* ??? where does 40 come from? */ jam(buf, "%d.%d", *p / 40, *p % 40); p++; /* runs of 1xxxxxxx+ 0xxxxxxx */ while (p < end) { uintmax_t n = 0; for (;;) { uint8_t b = *p++; if (n > UINTMAX_MAX >> 7) return "OID too large"; n = (n << 7) | (b & 0x7f); /* stop at 0xxxxxxx */ if (b < 0x80) break; if (p >= end) return "corrupt OID run encoding"; } jam(buf, ".%ju", n); } } else { jam(buf, "%s", oid_names[oid_code].name); } jam(buf, "="); if (oid_code == OID_UNKNOWN || /* * NSS totally screws up a leading '#' - stripping * of the escape and then interpreting it as a * #BER. */ (nss_compatible && ((const char*)value_content.ptr)[0] == '#')) { /* BER */ jam(buf, "#"); for (unsigned i = 0; i < value_ber.len; i++) { uint8_t byte = ((const uint8_t*)value_ber.ptr)[i]; jam(buf, "%02X", byte); } } else { const char *p = (void*) value_content.ptr; /* cast void */ const char *end = p + value_content.len; /* * - a space (' ' U+0020) or number sign ('#' * U+0023) occurring at the beginning of the * string; * * Per below, can be escaped using * . * * Note the singuar - a space - presumably * only the first of these needs to be escaped * as after that everything must be part of * the string until either ',' or '+' or ';' * is hit? */ if (p < end && (*p == ' ' || *p == '#')) { jam_bytes(buf, "\\", 1); jam_bytes(buf, p, 1); p++; } /* * - a space (' ' U+0020) character occurring * at the end of the string; * * Again note the singlar - a space - I guess * the parser tosses a run of un-escaped * spaces before a separator. */ unsigned trailing = 0; if (p < end && end[-1] == ' ') { trailing++; end--; } /* * Emit the body: * * - one of the characters '"', '+', ',', ';', * '<', '>', or '\' (U+0022, U+002B, U+002C, * U+003B, U+003C, U+003E, or U+005C, * respectively); * * - the null (U+0000) character. * * Other characters may be escaped. * * [...] * * Each octet of the character to be escaped * is replaced by a backslash and two hex * digits, which form a single octet in the * code of the character. Alternatively, if * and only if the character to be escaped is * one of * * ' ', '"', '#', '+', ',', ';', '<', '=', * '>', or '\' (U+0020, U+0022, U+0023, * U+002B, U+002C, U+003B, U+003C, U+003D, * U+003E, U+005C, respectively) * * it can be prefixed by a backslash ('\' * U+005C). * * XXX: the below uses \XX to encode any * character outside of [U+0020..U+007E]. * Since all bytes of a UTF-8 encoded code * point have the top-bit set this works for * UTF-8. * * XXX: following earlier code, the below * tries to micro-optimize calls to * jam_bytes() - runs of un-escaped characters * are accumulated and then written using a * single call. * * XXX: isprint() is affected by locale, and * isascii() isn't considered portable; so use * a simple compare. */ unsigned run = 0; while (p + run < end) { uint8_t c = p[run]; /* byte */ bool needs_prefix = (c == '\\' || c == '\"' || c == '+' || c == ',' || c == ';' || c == '<' || c == '>'); if (nss_compatible) { /* * XXX: Old versions of NSS * also wants these special * characters escaped * everywhere. */ needs_prefix = (needs_prefix || c == '#' || c == '='); } bool printable = (c >= 0x20 && c <= 0x7e && !needs_prefix); if (printable) { /* * add to run of characters that don't * need to be escaped */ run++; } else { /* emit previous run */ jam_bytes(buf, p, run); if (needs_prefix) { /* */ jam_bytes(buf, "\\", 1); jam_bytes(buf, &c, 1); } else { /* */ jam_bytes(buf, "\\", 1); jam(buf, "%02X", c); } /* advance past this escaped character */ p += run + 1; run = 0; } } /* emit final run */ jam_bytes(buf, p, run); /* * Escape any trailing ' ' characters; using \ * is ok; remember END had these stripped. */ for (unsigned i = 0; i < trailing; i++) { jam_bytes(buf, "\\", 1); jam_bytes(buf, &end[i], 1); } } } return NULL; } /* * Converts a binary DER-encoded ASN.1 distinguished name * into LDAP-style human-readable ASCII format */ void jam_raw_dn(jambuf_t *buf, chunk_t dn, jam_bytes_fn *jam_bytes, bool nss_compatible) { /* save start in case things screw up */ jampos_t pos = jambuf_get_pos(buf); err_t ugh = format_dn(buf, dn, jam_bytes, nss_compatible); if (ugh != NULL) { /* error: print DN as hex string */ libreswan_log("error in DN parsing: %s", ugh); DBG_dump_hunk("Bad DN:", dn); /* reset the buffer */ jambuf_set_pos(buf, &pos); jam(buf, "0x"); jam_HEX_bytes(buf, dn.ptr, dn.len); } } void jam_dn_or_null(jambuf_t *buf, chunk_t dn, const char *null_dn, jam_bytes_fn *jam_bytes) { if (dn.ptr == NULL) { jam(buf, "%s", null_dn); } else { jam_raw_dn(buf, dn, jam_bytes, true/*nss_compatible*/); } } const char *str_dn_or_null(chunk_t dn, const char *null_dn, dn_buf *dst) { jambuf_t buf = ARRAY_AS_JAMBUF(dst->buf); jam_dn_or_null(&buf, dn, null_dn, jam_sanitized_bytes); return dst->buf; } void jam_dn(jambuf_t *buf, chunk_t dn, jam_bytes_fn *jam_bytes) { jam_dn_or_null(buf, dn, "(empty)", jam_bytes); } const char *str_dn(chunk_t dn, dn_buf *dst) { jambuf_t buf = ARRAY_AS_JAMBUF(dst->buf); jam_dn(&buf, dn, jam_sanitized_bytes); return dst->buf; } /* * Note that there may be as many as six IDs that are temporary at * one time before unsharing the two ends of a connection. So we need * at least six temporary buffers for DER_ASN1_DN IDs. * We rotate them. Be careful! */ #define MAX_BUF 6 static unsigned char *temporary_cyclic_buffer(void) { /* MAX_BUF internal buffers */ static unsigned char buf[MAX_BUF][IDTOA_BUF]; static int counter; /* cyclic counter */ if (++counter == MAX_BUF) counter = 0; /* next internal buffer */ return buf[counter]; /* assign temporary buffer */ } /* * Converts an LDAP-style human-readable ASCII-encoded * ASN.1 distinguished name into binary DER-encoded format. * * (*DN) is the result, and points at static data allocated by * temporary_cyclic_buffer. * * XXX: since caller is almost immediately calling clone_chunk() (or * unshare_id_content()) why not do it here. * * Structure of the output: * * ASN_SEQUENCE { * for each Relative DN { * ASN1_SET { * ASN1_SEQUENCE { * ASN1_OID { * op->oid * } * op->type|ASN1_PRINTABLESTRING { * name * } * } * } * } * } */ err_t atodn(const char *src, chunk_t *dn) { dbg("ASCII to DN <= \"%s\"", src); /* stack of unfilled lengths */ unsigned char *(patchpoint[5]); /* only 4 are actually needed */ unsigned char **ppp = patchpoint; /* space for result */ dn->ptr = temporary_cyclic_buffer(); /* nasty! */ unsigned char *dn_ptr = dn->ptr; /* growth point */ unsigned char *dn_redline = dn_ptr + IDTOA_BUF; # define START_OBJ() { *ppp++ = dn_ptr; } /* note: on buffer overflow this returns from atodn */ /* ??? all but one call has len==1 so we could simplify */ # define EXTEND_OBJ(ptr, len) { \ if (dn_redline - dn_ptr < (ptrdiff_t)(len)) \ return "DN too big"; \ memcpy(dn_ptr, (ptr), (len)); \ dn_ptr += (len); \ } /* * insert type and operand length before the operand already in the buffer * Note: on buffer overflow this returns from atodn */ # define END_OBJ(ty) { \ size_t len = dn_ptr - *--ppp; \ unsigned char len_buf[ASN1_MAX_LEN_LEN + 1] = { ty }; \ chunk_t obj_len = { len_buf + 1, 0 }; \ code_asn1_length(len, &obj_len); \ if (dn_redline - dn_ptr < (ptrdiff_t)obj_len.len + 1) \ return "DN overflow"; \ memmove(*ppp + obj_len.len + 1, *ppp, len); \ memcpy(*ppp, len_buf, obj_len.len + 1); \ dn_ptr += obj_len.len + 1; \ } START_OBJ(); /* 0 ASN1_SEQUENCE */ for (;;) { /* for each Relative DN */ src += strspn(src, " /,"); /* skip any separators */ if (*src == '\0') break; /* finished! */ /* parse OID */ START_OBJ(); /* 1 ASN1_SET */ START_OBJ(); /* 2 ASN1_SEQUENCE */ START_OBJ(); /* 3 ASN1_OID */ x501rdn_t *op; /* OID description */ if (*src >= '0' && *src <= '9') { op = NULL; /* so #BER is expected */ char *end; uint8_t byte; /* B1.B2 */ unsigned long b0a = strtoul(src, &end, 10); /* ??? where does 40 come from? */ if (src == end || b0a > UINT8_MAX / 40) { return "numeric OID has invalid first digit"; } src = end; if (src[0] != '.') { return "numeric OID missing first '.'"; } src++; unsigned long b0b = strtoul(src, &end, 10); if (src == end || b0b >= 40) { return "numeric OID has invalid second digit"; } src = end; byte = b0a * 40 + b0b; EXTEND_OBJ(&byte, 1); /* .B ... */ while (src[0] == '.') { src++; unsigned long b = strtoul(src, &end, 10); if (src == end) { return "numeric OID has invalid second digit"; } src = end; /* XXX: this is neither smart nor efficient */ while (b >= 128) { unsigned long l = b; unsigned shifts = 0; while (l >= 128) { l >>= 7; shifts += 7; } byte = l | 0x80; EXTEND_OBJ(&byte, 1); b -= l << shifts; } byte = b; EXTEND_OBJ(&byte, 1); } } else { size_t ol = strcspn(src, " ="); /* length of OID name */ for (op = x501rdns; ; op++) { if (op == &x501rdns[elemsof(x501rdns)]) { dbg("unknown OID: \"%.*s\"", (int)ol, src); return "unknown OID in ID_DER_ASN1_DN"; } if (strlen(op->name) == ol && strncaseeq(op->name, src, ol)) { break; /* found */ } } EXTEND_OBJ(op->oid_ptr, op->oid_len); src += ol; } END_OBJ(ASN1_OID); /* 3 */ /* = */ src += strspn(src, " "); /* skip white space */ if (*src != '=') { return "missing '='"; } src++; src += strspn(src, " "); /* skip white space */ if (src[0] == '#') { /* dump the raw hex assuming it is a BER */ src++; while (isxdigit(src[0]) && isxdigit(src[1])) { char hex[3] = { src[0], src[1], }; uint8_t byte = strtol(hex, NULL, 16); EXTEND_OBJ(&byte, 1); src += 2; } } else if (*src == '"') { return "obsolete rfc1779 quoting using '\"' not supported"; } else { if (op == NULL) { return "numeric OID requires #HEXPAIR BER"; } /* parse value */ START_OBJ(); /* 3 op->type or ASN1_T61STRING */ uint8_t *escape_stop = dn_ptr; while (src[0] != '\0' && src[0] != ',' && /* XXX: where did '/' come from? */ src[0] != '/') { /* assume nul termination */ if (src[0] == '\\' && isxdigit(src[1]) && isxdigit(src[2])) { char hex[3] = { src[1], src[2], }; uint8_t byte = strtol(hex, NULL, 16); EXTEND_OBJ(&byte, 1); src += 3; escape_stop = dn_ptr; } else if (src[0] == '\\' && src[1] != '\0') { EXTEND_OBJ(&src[1], 1); src += 2; escape_stop = dn_ptr; } else if ((src[0] == ',' || src[0] == '/') && src[0] == src[1]) { /* * doubled: a form of escape. Insert * a single copy of the char. * * XXX: ',,' came from rhbz#868986; * '//' was added shortly after; both * are bogus. */ EXTEND_OBJ(src, 1); src += 2; /* skip both copies */ escape_stop = dn_ptr; } else { EXTEND_OBJ(src, 1); src++; } } /* remove trailing SPaces from name operand */ /* XXX: but not escaped */ while (dn_ptr > escape_stop && dn_ptr[-1] == ' ') dn_ptr--; unsigned char *ns = ppp[-1]; /* name operand start */ asn1_t t = op->type == ASN1_PRINTABLESTRING && !is_printablestring(chunk(ns, dn_ptr - ns)) ? ASN1_T61STRING : op->type; END_OBJ(t); /* 3 value */ } END_OBJ(ASN1_SEQUENCE); /* 2 */ END_OBJ(ASN1_SET); /* 1 */ } END_OBJ(ASN1_SEQUENCE); /* 0 */ dn->len = dn_ptr - dn->ptr; if (DBGP(DBG_BASE)) { DBG_dump_hunk("ASCII to DN =>", *dn); } return NULL; # undef START_OBJ # undef EXTEND_OBJ # undef END_OBJ } /* * compare two distinguished names by * comparing the individual RDNs */ bool same_dn(chunk_t a, chunk_t b) { return match_dn(a, b, NULL); /* degenerate case of match_dn() */ } /* * compare two distinguished names by comparing the individual RDNs. * A single '*' character designates a wildcard RDN in DN b. * If wildcards is NULL, exact match is required. */ bool match_dn(chunk_t a, chunk_t b, int *wildcards) { chunk_t rdn_a, rdn_b; chunk_t attribute_a, attribute_b; bool more_a, more_b; if (wildcards != NULL) { /* initialize wildcard counter */ *wildcards = 0; } else { /* fast checks possible without wildcards */ /* same lengths for the DNs */ if (a.len != b.len) return FALSE; /* try a binary comparison first */ if (memeq(a.ptr, b.ptr, b.len)) return TRUE; } /* * initialize DN parsing. Stop (silently) on errors. */ { err_t ua = init_rdn(a, &rdn_a, &attribute_a, &more_a); if (ua != NULL) { dbg("match_dn bad a: %s", ua); return FALSE; } err_t ub = init_rdn(b, &rdn_b, &attribute_b, &more_b); if (ub != NULL) { dbg("match_dn bad b: %s", ub); return FALSE; } } /* fetch next RDN pair */ for (int n = 1; more_a && more_b; n++) { /* * Parse next RDNs and check for errors * but don't report errors. */ chunk_t oid_a, oid_b; chunk_t value_ber_a, value_ber_b; asn1_t value_type_a, value_type_b; chunk_t value_content_a, value_content_b; { err_t ua = get_next_rdn(&rdn_a, &attribute_a, &oid_a, &value_ber_a, &value_type_a, &value_content_a, &more_a); if (ua != NULL) { dbg("match_dn bad a[%d]: %s", n, ua); return FALSE; } err_t ub = get_next_rdn(&rdn_b, &attribute_b, &oid_b, &value_ber_b, &value_type_b, &value_content_b, &more_b); if (ub != NULL) { dbg("match_dn bad b[%d]: %s", n, ub); return FALSE; } } /* OIDs must agree */ if (!chunk_eq(oid_a, oid_b)) return FALSE; /* does rdn_b contain a wildcard? */ /* ??? this does not care whether types match. Should it? */ if (wildcards != NULL && value_content_b.len == 1 && value_content_b.ptr[0] == '*') { (*wildcards)++; continue; } if (value_content_a.len != value_content_b.len) return FALSE; /* lengths must match */ /* * If the two types treat the high bit differently * or if ASN1_PRINTABLESTRING is involved, * we must forbid the high bit. */ if (value_type_a != value_type_b || value_type_a == ASN1_PRINTABLESTRING) { unsigned char or = 0x00; for (size_t i = 0; i != value_content_a.len; i++) or |= value_content_a.ptr[i] | value_content_b.ptr[i]; if (or & 0x80) return FALSE; } /* * even though the types may differ, we assume that * their bits can be compared. */ /* cheap match, as if case matters */ if (memeq(value_content_a.ptr, value_content_b.ptr, value_content_a.len)) continue; /* * printableStrings and email RDNs require comparison * ignoring case. * We do require that the types match. * Forbid NUL in such strings. */ if ((value_type_a == ASN1_PRINTABLESTRING || (value_type_a == ASN1_IA5STRING && known_oid(oid_a) == OID_PKCS9_EMAIL)) && strncaseeq((char *)value_content_a.ptr, (char *)value_content_b.ptr, value_content_b.len) && memchr(value_content_a.ptr, '\0', a.len) == NULL) { continue; /* component match */ } return FALSE; /* not a match */ } /* both DNs must have same number of RDNs */ if (more_a || more_b) { if (wildcards != NULL && *wildcards != 0) { /* ??? for some reason we think a failure with wildcards is worth logging */ dn_buf abuf; dn_buf bbuf; libreswan_log("while comparing A='%s'<=>'%s'=B with a wildcard count of %d, %s had too few RDNs", str_dn(a, &abuf), str_dn(b, &bbuf), *wildcards, (more_a ? "B" : "A")); } return FALSE; } /* the two DNs match! */ return TRUE; } /* * free the dynamic memory used to store generalNames */ void free_generalNames(generalName_t *gn, bool free_name) { while (gn != NULL) { generalName_t *gn_top = gn; if (free_name) pfree(gn->name.ptr); gn = gn->next; pfree(gn_top); } } libreswan-3.32/lib/libwhack/000077500000000000000000000000001365625662500160015ustar00rootroot00000000000000libreswan-3.32/lib/libwhack/Makefile000066400000000000000000000016241365625662500174440ustar00rootroot00000000000000# Libreswan library # # Copyright (C) 1998-2001 Henry Spencer. # Copyright (C) 2003, 2004 Xelerance Corporation # Copyright (C) 2012-2013 Paul Wouters # Copyright (C) 2015 Andrew Cagney # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. LIB = libwhack.a OBJS += whacklib.o OBJS += aliascomp.o ifdef top_srcdir include ${top_srcdir}/mk/library.mk else include ../../mk/library.mk endif libreswan-3.32/lib/libwhack/aliascomp.c000066400000000000000000000027161365625662500201230ustar00rootroot00000000000000/* functions to compare a string/list * Copyright (C) 2006 Michael Richardson * Copyright (C) 2012 Paul Wouters * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include #include #include #include #include "sysdep.h" #include "constants.h" #include "lswalloc.h" #include "whack.h" /* * lsw_alias_cmp: is name found in aliases? * * aliases is a string of whitespace-separated names (or a NULL pointer). * Assumption: names do not contain whitespace. */ bool lsw_alias_cmp(const char *name, const char *aliases) { if (aliases == NULL) return FALSE; size_t nlen = strlen(name); for (const char *s = aliases;;) { s += strspn(s, " \t"); /* skip whitespace */ if (*s == '\0') return FALSE; /* string exhausted */ size_t aw = strcspn(s, " \t"); /* alias width */ if (aw == nlen && strneq(s, name, nlen)) return TRUE; /* found */ s += aw; /* skip this alias */ } } libreswan-3.32/lib/libwhack/whacklib.c000066400000000000000000000230361365625662500177350ustar00rootroot00000000000000/* Libreswan command interface to Pluto * Copyright (C) 1997 Angelos D. Keromytis. * Copyright (C) 1998-2001 D. Hugh Redelmeier. * Copyright (C) 2004-2006 Michael Richardson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "sysdep.h" #include "constants.h" #include "lswalloc.h" #include "lswlog.h" #include "whack.h" #include "lswlog.h" /** * Pack a string to a whack messages * * @param wp * @param p a string * @return bool True if operation was successful */ static bool pack_str(struct whackpacker *wp, char **p) { const char *s = (*p == NULL ? "" : *p); /* note: NULL becomes ""! */ size_t len = strlen(s) + 1; if (wp->str_roof - wp->str_next < (ptrdiff_t)len) { return FALSE; /* fishy: no end found */ } else { strcpy((char *)wp->str_next, s); wp->str_next += len; *p = NULL; /* don't send pointers on the wire! */ return TRUE; } } /** * Unpack the next string from a whack message * * @param wp Whack Message * @param p pointer to a string pointer; the string pointer will point to the next string in *wp. * @return bool TRUE if operation successful * * Note that the string still resides in the whach message. */ static bool unpack_str(struct whackpacker *wp, char **p) { unsigned char *end; end = memchr(wp->str_next, '\0', (wp->str_roof - wp->str_next) ); if (end == NULL) { return FALSE; /* fishy: no end found */ } else { unsigned char *s = (wp->str_next == end ? NULL : wp->str_next); *p = (char *)s; wp->str_next = end + 1; return TRUE; } } /** * Pack a message to be sent to whack * * @param wp The whack message * @return err_t */ err_t pack_whack_msg(struct whackpacker *wp) { /* Pack strings */ wp->str_next = wp->msg->string; wp->str_roof = &wp->msg->string[sizeof(wp->msg->string)]; if (!pack_str(wp, &wp->msg->name) || /* string 1 */ !pack_str(wp, &wp->msg->left.id) || /* string 2 */ !pack_str(wp, &wp->msg->left.pubkey) || /* string 3 */ !pack_str(wp, &wp->msg->left.ca) || /* string 4 */ !pack_str(wp, &wp->msg->left.groups) || /* string 5 */ !pack_str(wp, &wp->msg->left.updown) || /* string 6 */ !pack_str(wp, &wp->msg->left.virt) || /* string 7 */ !pack_str(wp, &wp->msg->right.id) || /* string 8 */ !pack_str(wp, &wp->msg->right.pubkey) || /* string 9 */ !pack_str(wp, &wp->msg->right.ca) || /* string 10 */ !pack_str(wp, &wp->msg->right.groups) || /* string 11 */ !pack_str(wp, &wp->msg->right.updown) || /* string 12 */ !pack_str(wp, &wp->msg->right.virt) || /* string 13 */ !pack_str(wp, &wp->msg->keyid) || /* string 14 */ !pack_str(wp, &wp->msg->ike) || /* string 16 */ !pack_str(wp, &wp->msg->esp) || /* string 17 */ !pack_str(wp, &wp->msg->left.xauth_username) || /* string 18 */ !pack_str(wp, &wp->msg->right.xauth_username) || /* string 19 */ !pack_str(wp, &wp->msg->connalias) || /* string 20 */ !pack_str(wp, &wp->msg->left.host_addr_name) || /* string 21 */ !pack_str(wp, &wp->msg->right.host_addr_name) || /* string 22 */ !pack_str(wp, &wp->msg->string1) || /* string 23 */ !pack_str(wp, &wp->msg->string2) || /* string 24 */ !pack_str(wp, &wp->msg->string3) || /* string 25 */ !pack_str(wp, &wp->msg->dnshostname) || /* string 26 */ #ifdef HAVE_LABELED_IPSEC !pack_str(wp, &wp->msg->policy_label) || /* string 27 */ #endif !pack_str(wp, &wp->msg->modecfg_dns) || /* string 28 */ !pack_str(wp, &wp->msg->modecfg_domains) || /* string 28 */ !pack_str(wp, &wp->msg->modecfg_banner) || /* string 29 */ !pack_str(wp, &wp->msg->conn_mark_both) || /* string 30 */ !pack_str(wp, &wp->msg->conn_mark_in) || /* string 31 */ !pack_str(wp, &wp->msg->conn_mark_out) || /* string 32 */ !pack_str(wp, &wp->msg->vti_iface) || /* string 33 */ !pack_str(wp, &wp->msg->remote_host) || /* string 33 */ !pack_str(wp, &wp->msg->redirect_to) || /* string 34 */ !pack_str(wp, &wp->msg->accept_redirect_to) || /* string 35 */ wp->str_roof - wp->str_next < (ptrdiff_t)wp->msg->keyval.len) /* key */ { return "too many bytes of strings or key to fit in message to pluto"; } /* * Like pack_str, but for the keyval chunk. * - already checked that there is room for the chunk * - memcpy wants valid pointers, even if the length is 0. */ if (wp->msg->keyval.len != 0) memcpy(wp->str_next, wp->msg->keyval.ptr, wp->msg->keyval.len); wp->msg->keyval.ptr = NULL; /* don't send pointers on the wire! */ wp->str_next += wp->msg->keyval.len; return NULL; } /** * Unpack a message whack received * * @param wp The whack message * @return err_t */ err_t unpack_whack_msg(struct whackpacker *wp) { err_t ugh = NULL; if (wp->str_next > wp->str_roof) { ugh = builddiag( "ignoring truncated message from whack: got %d bytes; expected %u", (int) wp->n, (unsigned) sizeof(wp->msg)); } else if (!unpack_str(wp, &wp->msg->name) || /* string 1 */ !unpack_str(wp, &wp->msg->left.id) || /* string 2 */ !unpack_str(wp, &wp->msg->left.pubkey) || /* string 3 */ !unpack_str(wp, &wp->msg->left.ca) || /* string 4 */ !unpack_str(wp, &wp->msg->left.groups) || /* string 5 */ !unpack_str(wp, &wp->msg->left.updown) || /* string 6 */ !unpack_str(wp, &wp->msg->left.virt) || /* string 7 */ !unpack_str(wp, &wp->msg->right.id) || /* string 8 */ !unpack_str(wp, &wp->msg->right.pubkey) || /* string 9 */ !unpack_str(wp, &wp->msg->right.ca) || /* string 10 */ !unpack_str(wp, &wp->msg->right.groups) || /* string 11 */ !unpack_str(wp, &wp->msg->right.updown) || /* string 12 */ !unpack_str(wp, &wp->msg->right.virt) || /* string 13 */ !unpack_str(wp, &wp->msg->keyid) || /* string 14 */ !unpack_str(wp, &wp->msg->ike) || /* string 16 */ !unpack_str(wp, &wp->msg->esp) || /* string 17 */ !unpack_str(wp, &wp->msg->left.xauth_username) || /* string 18 */ !unpack_str(wp, &wp->msg->right.xauth_username) || /* string 19 */ !unpack_str(wp, &wp->msg->connalias) || /* string 20 */ !unpack_str(wp, &wp->msg->left.host_addr_name) || /* string 21 */ !unpack_str(wp, &wp->msg->right.host_addr_name) || /* string 22 */ !unpack_str(wp, &wp->msg->string1) || /* string 23 */ !unpack_str(wp, &wp->msg->string2) || /* string 24 */ !unpack_str(wp, &wp->msg->string3) || /* string 25 */ !unpack_str(wp, &wp->msg->dnshostname) || /* string 26 */ #ifdef HAVE_LABELED_IPSEC !unpack_str(wp, &wp->msg->policy_label) || /* string 27 */ #endif !unpack_str(wp, &wp->msg->modecfg_dns) || /* string 28 */ !unpack_str(wp, &wp->msg->modecfg_domains) || /* string 28 */ !unpack_str(wp, &wp->msg->modecfg_banner) || /* string 29 */ !unpack_str(wp, &wp->msg->conn_mark_both) || /* string 30 */ !unpack_str(wp, &wp->msg->conn_mark_in) || /* string 31 */ !unpack_str(wp, &wp->msg->conn_mark_out) || /* string 32 */ !unpack_str(wp, &wp->msg->vti_iface) || /* string 33 */ !unpack_str(wp, &wp->msg->remote_host) || /* string 33 */ !unpack_str(wp, &wp->msg->redirect_to) || /* string 34 */ !unpack_str(wp, &wp->msg->accept_redirect_to) || /* string 35 */ wp->str_roof - wp->str_next != (ptrdiff_t)wp->msg->keyval.len) { ugh = "message from whack contains bad string or key"; } else { wp->msg->keyval.ptr = wp->str_next; } return ugh; } void clear_end(struct whack_end *e) { static const struct whack_end zero_end; /* zeros and NULL pointers */ *e = zero_end; e->host_port = IKE_UDP_PORT; /* XXX should really use ike_port ? */ } int whack_get_value(char *buf, size_t bufsize) { int len; int try; fflush(stdout); try = 3; len = 0; while (try > 0 && len == 0) { fprintf(stderr, "Enter username: "); memset(buf, 0, bufsize); if (fgets(buf, bufsize, stdin) != buf) { if (errno == 0) { fprintf(stderr, "Cannot read username from standard in\n"); exit(RC_WHACK_PROBLEM); } else { perror("fgets value"); exit(RC_WHACK_PROBLEM); } } /* send the value to pluto, including \0, but fgets adds \n */ len = strlen(buf); if (len == 0) fprintf(stderr, "answer was empty, retry\n"); try--; } if (len == 0) exit(RC_WHACK_PROBLEM); return len; } /* Get password from user. Truncate it to fit in buf. */ /* ??? the function getpass(3) is obsolete! */ size_t whack_get_secret(char *buf, size_t bufsize) { fflush(stdout); assert(bufsize > 0); /* room for terminal NUL */ char *secret = getpass("Enter passphrase: "); /* jam_str would be good but it requires too much library */ size_t len = strlen(secret) + 1; size_t trunc_len = len <= bufsize ? len : bufsize; memcpy(buf, secret, trunc_len); buf[trunc_len-1] = '\0'; /* force NUL termination */ memset(secret, 0, len); /* scrub secret from RAM */ return trunc_len; } libreswan-3.32/linux/000077500000000000000000000000001365625662500146065ustar00rootroot00000000000000libreswan-3.32/linux/Documentation/000077500000000000000000000000001365625662500174175ustar00rootroot00000000000000libreswan-3.32/linux/Documentation/Configure.help.fs2_0.patch000066400000000000000000000050761365625662500242300ustar00rootroot00000000000000--- linux/Documentation/Configure.help.orig Tue Jan 9 16:29:20 2001 +++ linux/Documentation/Configure.help Fri Aug 9 14:47:14 2002 @@ -4979,2 +4979,62 @@ +IP Security Protocol (IPSEC) (EXPERIMENTAL) +CONFIG_IPSEC + This unit is experimental code. + Pick 'y' for static linking, 'm' for module support or 'n' for none. + This option adds support for network layer packet encryption and/or + authentication with participating hosts. The standards start with: + RFCs 2411, 2407 and 2401. Others are mentioned where they refer to + specific features below. There are more pending which can be + found at: ftp://ftp.ietf.org/internet-drafts/draft-ietf-ipsec-*. + A description of each document can also be found at: + http://ietf.org/ids.by.wg/ipsec.html. + Their charter can be found at: + http://www.ietf.org/html.charters/ipsec-charter.html + Snapshots and releases of the current work can be found at: + http://www.freeswan.org/ + +IPSEC: IP-in-IP encapsulation +CONFIG_IPSEC_IPIP + This option provides support for tunnel mode IPSEC. It is recommended + to enable this. + +IPSEC: Authentication Header +CONFIG_IPSEC_AH + This option provides support for the IPSEC Authentication Header + (IP protocol 51) which provides packet layer sender and content + authentication. It is recommended to enable this. RFC2402 + +HMAC-MD5 algorithm +CONFIG_IPSEC_AUTH_HMAC_MD5 + Provides support for authentication using the HMAC MD5 + algorithm with 96 bits of hash used as the authenticator. RFC2403 + +HMAC-SHA1 algorithm +CONFIG_IPSEC_AUTH_HMAC_SHA1 + Provides support for Authentication Header using the HMAC SHA1 + algorithm with 96 bits of hash used as the authenticator. RFC2404 + +IPSEC: Encapsulating Security Payload +CONFIG_IPSEC_ESP + This option provides support for the IPSEC Encapsulation Security + Payload (IP protocol 50) which provides packet layer content + hiding. It is recommended to enable this. RFC2406 + +3DES algorithm +CONFIG_IPSEC_ENC_3DES + Provides support for Encapsulation Security Payload protocol, using + the triple DES encryption algorithm. RFC2451 + +IPSEC Debugging Option +CONFIG_IPSEC_DEBUG + Enables IPSEC kernel debugging. It is further controlled by the + user space utility 'klipsdebug'. + +IPSEC Regression Testing option +CONFIG_IPSEC_REGRESS + Enables IPSEC regression testing. Creates a number of switches in + /proc/sys/net/ipsec which cause various failure modes in KLIPS. + For more details see Libreswan source under + testing/doc/regression_options.txt. + # need an empty line after last entry, for sed script in Configure. libreswan-3.32/linux/Documentation/Configure.help.fs2_2.patch000066400000000000000000000053201365625662500242220ustar00rootroot00000000000000--- /a3/kernel_sources/linux-2.2.20/Documentation/Configure.help Fri Nov 2 11:39:05 2001 +++ linux2.2/Documentation/Configure.help Mon Jul 29 15:42:26 2002 @@ -15237,5 +15237,66 @@ -# + +IP Security Protocol (IPSEC) (EXPERIMENTAL) +CONFIG_IPSEC + This unit is experimental code. + Pick 'y' for static linking, 'm' for module support or 'n' for none. + This option adds support for network layer packet encryption and/or + authentication with participating hosts. The standards start with: + RFCs 2411, 2407 and 2401. Others are mentioned where they refer to + specific features below. There are more pending which can be found + at: ftp://ftp.ietf.org/internet-drafts/draft-ietf-ipsec-*. + A description of each document can also be found at: + http://ietf.org/ids.by.wg/ipsec.html. + Their charter can be found at: + http://www.ietf.org/html.charters/ipsec-charter.html + Snapshots and releases of the current work can be found at: + http://www.freeswan.org/ + +IPSEC: IP-in-IP encapsulation +CONFIG_IPSEC_IPIP + This option provides support for tunnel mode IPSEC. It is recommended + to enable this. + +IPSEC: Authentication Header +CONFIG_IPSEC_AH + This option provides support for the IPSEC Authentication Header + (IP protocol 51) which provides packet layer sender and content + authentication. It is recommended to enable this. RFC2402 + +HMAC-MD5 algorithm +CONFIG_IPSEC_AUTH_HMAC_MD5 + Provides support for authentication using the HMAC MD5 + algorithm with 96 bits of hash used as the authenticator. RFC2403 + +HMAC-SHA1 algorithm +CONFIG_IPSEC_AUTH_HMAC_SHA1 + Provides support for Authentication Header using the HMAC SHA1 + algorithm with 96 bits of hash used as the authenticator. RFC2404 + +IPSEC: Encapsulating Security Payload +CONFIG_IPSEC_ESP + This option provides support for the IPSEC Encapsulation Security + Payload (IP protocol 50) which provides packet layer content + hiding. It is recommended to enable this. RFC2406 + +3DES algorithm +CONFIG_IPSEC_ENC_3DES + Provides support for Encapsulation Security Payload protocol, using + the triple DES encryption algorithm. RFC2451 + +IPSEC Debugging Option +CONFIG_IPSEC_DEBUG + Enables IPSEC kernel debugging. It is further controlled by the + user space utility 'klipsdebug'. + +IPSEC Regression Testing option +CONFIG_IPSEC_REGRESS + Enables IPSEC regression testing. Creates a number of switches in + /proc/sys/net/ipsec which cause various failure modes in KLIPS. + For more details see Libreswan source under + testing/doc/regression_options.txt. + +# # A couple of things I keep forgetting: # capitalize: AppleTalk, Ethernet, DOS, DMA, FAT, FTP, Internet, # Intel, IRQ, Linux, MSDOS, NetWare, NetWinder, NFS, libreswan-3.32/linux/Documentation/Configure.help.fs2_4.patch000066400000000000000000000052611365625662500242300ustar00rootroot00000000000000--- linux/Documentation/Configure.help.orig Fri Dec 21 12:41:53 2001 +++ linux/Documentation/Configure.help Mon Jul 29 16:35:32 2002 @@ -24237,5 +24237,65 @@ -# +IP Security Protocol (IPSEC) (EXPERIMENTAL) +CONFIG_IPSEC + This unit is experimental code. + Pick 'y' for static linking, 'm' for module support or 'n' for none. + This option adds support for network layer packet encryption and/or + authentication with participating hosts. The standards start with: + RFCs 2411, 2407 and 2401. Others are mentioned where they refer to + specific features below. There are more pending which can be found + at: ftp://ftp.ietf.org/internet-drafts/draft-ietf-ipsec-*. + A description of each document can also be found at: + http://ietf.org/ids.by.wg/ipsec.html. + Their charter can be found at: + http://www.ietf.org/html.charters/ipsec-charter.html + Snapshots and releases of the current work can be found at: + http://www.freeswan.org/ + +IPSEC: IP-in-IP encapsulation +CONFIG_IPSEC_IPIP + This option provides support for tunnel mode IPSEC. It is recommended + to enable this. + +IPSEC: Authentication Header +CONFIG_IPSEC_AH + This option provides support for the IPSEC Authentication Header + (IP protocol 51) which provides packet layer sender and content + authentication. It is recommended to enable this. RFC2402 + +HMAC-MD5 algorithm +CONFIG_IPSEC_AUTH_HMAC_MD5 + Provides support for authentication using the HMAC MD5 + algorithm with 96 bits of hash used as the authenticator. RFC2403 + +HMAC-SHA1 algorithm +CONFIG_IPSEC_AUTH_HMAC_SHA1 + Provides support for Authentication Header using the HMAC SHA1 + algorithm with 96 bits of hash used as the authenticator. RFC2404 + +IPSEC: Encapsulating Security Payload +CONFIG_IPSEC_ESP + This option provides support for the IPSEC Encapsulation Security + Payload (IP protocol 50) which provides packet layer content + hiding. It is recommended to enable this. RFC2406 + +3DES algorithm +CONFIG_IPSEC_ENC_3DES + Provides support for Encapsulation Security Payload protocol, using + the triple DES encryption algorithm. RFC2451 + +IPSEC Debugging Option +CONFIG_IPSEC_DEBUG + Enables IPSEC kernel debugging. It is further controlled by the + user space utility 'klipsdebug'. + +IPSEC Regression Testing option +CONFIG_IPSEC_REGRESS + Enables IPSEC regression testing. Creates a number of switches in + /proc/sys/net/ipsec which cause various failure modes in KLIPS. + For more details see Libreswan source under + testing/doc/regression_options.txt. + +# # A couple of things I keep forgetting: # capitalize: AppleTalk, Ethernet, DOS, DMA, FAT, FTP, Internet, # Intel, IRQ, ISDN, Linux, MSDOS, NetWare, NetWinder, libreswan-3.32/linux/Makefile000066400000000000000000000017611365625662500162530ustar00rootroot00000000000000# FreeS/WAN subdir makefile # Copyright (C) 1998-2001 Henry Spencer. # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. LIBRESWANSRCDIR?=$(shell cd .. && pwd) #SUBDIRS=net/ipsec include $(LIBRESWANSRCDIR)/Makefile.inc def: @echo "Please read doc/intro.html or INSTALL before running make" @false cleanall install programs man check clean modules install_file_list: @true # @for d in $(SUBDIRS); \ # do \ # (cd $$d && $(MAKE) TOPDIR=${KERNELSRC} LIBRESWANSRCDIR=$(LIBRESWANSRCDIR)/.. $@ ) || exit 1 ; \ # done libreswan-3.32/linux/include/000077500000000000000000000000001365625662500162315ustar00rootroot00000000000000libreswan-3.32/linux/include/cryptodev.h000066400000000000000000000470141365625662500204270ustar00rootroot00000000000000/* $FreeBSD: src/sys/opencrypto/cryptodev.h,v 1.25 2007/05/09 19:37:02 gnn Exp $ */ /* $OpenBSD: cryptodev.h,v 1.31 2002/06/11 11:14:29 beck Exp $ */ /*- * Linux port done by David McCullough * Copyright (C) 2006-2010 David McCullough * Copyright (C) 2004-2005 Intel Corporation. * The license and original author are listed below. * * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu) * Copyright (c) 2002-2006 Sam Leffler, Errno Consulting * * This code was written by Angelos D. Keromytis in Athens, Greece, in * February 2000. Network Security Technologies Inc. (NSTI) kindly * supported the development of this code. * * Copyright (c) 2000 Angelos D. Keromytis * * Permission to use, copy, and modify this software with or without fee * is hereby granted, provided that this entire notice is included in * all source code copies of any software which is or includes a copy or * modification of this software. * * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR * PURPOSE. * * Copyright (c) 2001 Theo de Raadt * * 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. * * Effort sponsored in part by the Defense Advanced Research Projects * Agency (DARPA) and Air Force Research Laboratory, Air Force * Materiel Command, USAF, under agreement number F30602-01-2-0537. * */ #ifndef _CRYPTO_CRYPTO_H_ #define _CRYPTO_CRYPTO_H_ /* Some initial values */ #define CRYPTO_DRIVERS_INITIAL 4 #define CRYPTO_SW_SESSIONS 32 /* Hash values */ #define NULL_HASH_LEN 0 #define MD5_HASH_LEN 16 #define SHA1_HASH_LEN 20 #define RIPEMD160_HASH_LEN 20 #define SHA2_256_HASH_LEN 32 #define SHA2_384_HASH_LEN 48 #define SHA2_512_HASH_LEN 64 #define MD5_KPDK_HASH_LEN 16 #define SHA1_KPDK_HASH_LEN 20 /* Maximum hash algorithm result length */ #define HASH_MAX_LEN SHA2_512_HASH_LEN /* Keep this updated */ /* HMAC values */ #define NULL_HMAC_BLOCK_LEN 1 #define MD5_HMAC_BLOCK_LEN 64 #define SHA1_HMAC_BLOCK_LEN 64 #define RIPEMD160_HMAC_BLOCK_LEN 64 #define SHA2_256_HMAC_BLOCK_LEN 64 #define SHA2_384_HMAC_BLOCK_LEN 128 #define SHA2_512_HMAC_BLOCK_LEN 128 /* Maximum HMAC block length */ #define HMAC_MAX_BLOCK_LEN SHA2_512_HMAC_BLOCK_LEN /* Keep this updated */ #define HMAC_IPAD_VAL 0x36 #define HMAC_OPAD_VAL 0x5C /* Encryption algorithm block sizes */ #define NULL_BLOCK_LEN 1 /* #define DES_BLOCK_LEN 8 obsoleted */ #define DES3_BLOCK_LEN 8 /* #define BLOWFISH_BLOCK_LEN 8 obsoleted */ #define SKIPJACK_BLOCK_LEN 8 #define CAST128_BLOCK_LEN 8 #define RIJNDAEL128_BLOCK_LEN 16 #define AES_BLOCK_LEN RIJNDAEL128_BLOCK_LEN #define CAMELLIA_BLOCK_LEN 16 #define ARC4_BLOCK_LEN 1 #define EALG_MAX_BLOCK_LEN AES_BLOCK_LEN /* Keep this updated */ /* Encryption algorithm min and max key sizes */ #define NULL_MIN_KEY_LEN 0 #define NULL_MAX_KEY_LEN 0 /* #define DES_MIN_KEY_LEN 8 obsoleted */ /* #define DES_MAX_KEY_LEN 8 obsoleted */ #define DES3_MIN_KEY_LEN 24 #define DES3_MAX_KEY_LEN 24 /* #define BLOWFISH_MIN_KEY_LEN 4 obsoleted */ /* #define BLOWFISH_MAX_KEY_LEN 56 obsoleted */ #define SKIPJACK_MIN_KEY_LEN 10 #define SKIPJACK_MAX_KEY_LEN 10 #define CAST128_MIN_KEY_LEN 5 #define CAST128_MAX_KEY_LEN 16 #define RIJNDAEL128_MIN_KEY_LEN 16 #define RIJNDAEL128_MAX_KEY_LEN 32 #define AES_MIN_KEY_LEN RIJNDAEL128_MIN_KEY_LEN #define AES_MAX_KEY_LEN RIJNDAEL128_MAX_KEY_LEN #define CAMELLIA_MIN_KEY_LEN 16 #define CAMELLIA_MAX_KEY_LEN 32 #define ARC4_MIN_KEY_LEN 1 #define ARC4_MAX_KEY_LEN 256 /* Max size of data that can be processed */ #define CRYPTO_MAX_DATA_LEN (64 * 1024 - 1) #define CRYPTO_ALGORITHM_MIN 1 /* #define CRYPTO_DES_CBC 1 */ #define CRYPTO_3DES_CBC 2 #define CRYPTO_BLF_CBC 3 #define CRYPTO_CAST_CBC 4 #define CRYPTO_SKIPJACK_CBC 5 #define CRYPTO_MD5_HMAC 6 #define CRYPTO_SHA1_HMAC 7 #define CRYPTO_RIPEMD160_HMAC 8 #define CRYPTO_MD5_KPDK 9 #define CRYPTO_SHA1_KPDK 10 #define CRYPTO_RIJNDAEL128_CBC 11 /* 128 bit blocksize */ #define CRYPTO_AES_CBC 11 /* 128 bit blocksize -- the same as above */ #define CRYPTO_ARC4 12 #define CRYPTO_MD5 13 #define CRYPTO_SHA1 14 #define CRYPTO_NULL_HMAC 15 #define CRYPTO_NULL_CBC 16 #define CRYPTO_DEFLATE_COMP 17 /* Deflate compression algorithm */ #define CRYPTO_SHA2_256_HMAC 18 #define CRYPTO_SHA2_384_HMAC 19 #define CRYPTO_SHA2_512_HMAC 20 #define CRYPTO_CAMELLIA_CBC 21 #define CRYPTO_SHA2_256 22 #define CRYPTO_SHA2_384 23 #define CRYPTO_SHA2_512 24 #define CRYPTO_RIPEMD160 25 #define CRYPTO_LZS_COMP 26 #define CRYPTO_ALGORITHM_MAX 26 /* Keep updated - see above */ /* Algorithm flags */ #define CRYPTO_ALG_FLAG_SUPPORTED 0x01 /* Algorithm is supported */ #define CRYPTO_ALG_FLAG_RNG_ENABLE 0x02 /* Has HW RNG for DH/DSA */ #define CRYPTO_ALG_FLAG_DSA_SHA 0x04 /* Can do SHA on msg */ /* * Crypto driver/device flags. They can set in the crid * parameter when creating a session or submitting a key * op to affect the device/driver assigned. If neither * of these are specified then the crid is assumed to hold * the driver id of an existing (and suitable) device that * must be used to satisfy the request. */ #define CRYPTO_FLAG_HARDWARE 0x01000000 /* hardware accelerated */ #define CRYPTO_FLAG_SOFTWARE 0x02000000 /* software implementation */ /* NB: deprecated */ struct session_op { u_int32_t cipher; /* ie. CRYPTO_DES_CBC */ u_int32_t mac; /* ie. CRYPTO_MD5_HMAC */ u_int32_t keylen; /* cipher key */ caddr_t key; int mackeylen; /* mac key */ caddr_t mackey; u_int32_t ses; /* returns: session # */ }; struct session2_op { u_int32_t cipher; /* ie. CRYPTO_DES_CBC */ u_int32_t mac; /* ie. CRYPTO_MD5_HMAC */ u_int32_t keylen; /* cipher key */ caddr_t key; int mackeylen; /* mac key */ caddr_t mackey; u_int32_t ses; /* returns: session # */ int crid; /* driver id + flags (rw) */ int pad[4]; /* for future expansion */ }; struct crypt_op { u_int32_t ses; u_int16_t op; /* i.e. COP_ENCRYPT */ #define COP_NONE 0 #define COP_ENCRYPT 1 #define COP_DECRYPT 2 u_int16_t flags; #define COP_F_BATCH 0x0008 /* Batch op if possible */ u_int len; caddr_t src, dst; /* become iov[] inside kernel */ caddr_t mac; /* must be big enough for chosen MAC */ caddr_t iv; }; /* * Parameters for looking up a crypto driver/device by * device name or by id. The latter are returned for * created sessions (crid) and completed key operations. */ struct crypt_find_op { int crid; /* driver id + flags */ char name[32]; /* device/driver name */ }; /* bignum parameter, in packed bytes, ... */ struct crparam { caddr_t crp_p; u_int crp_nbits; }; #define CRK_MAXPARAM 8 struct crypt_kop { u_int crk_op; /* ie. CRK_MOD_EXP or other */ u_int crk_status; /* return status */ u_short crk_iparams; /* # of input parameters */ u_short crk_oparams; /* # of output parameters */ u_int crk_crid; /* NB: only used by CIOCKEY2 (rw) */ struct crparam crk_param[CRK_MAXPARAM]; }; #define CRK_ALGORITM_MIN 0 #define CRK_MOD_EXP 0 #define CRK_MOD_EXP_CRT 1 #define CRK_DSA_SIGN 2 #define CRK_DSA_VERIFY 3 #define CRK_DH_COMPUTE_KEY 4 #define CRK_ALGORITHM_MAX 4 /* Keep updated - see below */ #define CRF_MOD_EXP (1 << CRK_MOD_EXP) #define CRF_MOD_EXP_CRT (1 << CRK_MOD_EXP_CRT) #define CRF_DSA_SIGN (1 << CRK_DSA_SIGN) #define CRF_DSA_VERIFY (1 << CRK_DSA_VERIFY) #define CRF_DH_COMPUTE_KEY (1 << CRK_DH_COMPUTE_KEY) /* * done against open of /dev/crypto, to get a cloned descriptor. * Please use F_SETFD against the cloned descriptor. */ #define CRIOGET _IOWR('c', 100, u_int32_t) #define CRIOASYMFEAT CIOCASYMFEAT #define CRIOFINDDEV CIOCFINDDEV /* the following are done against the cloned descriptor */ #define CIOCGSESSION _IOWR('c', 101, struct session_op) #define CIOCFSESSION _IOW('c', 102, u_int32_t) #define CIOCCRYPT _IOWR('c', 103, struct crypt_op) #define CIOCKEY _IOWR('c', 104, struct crypt_kop) #define CIOCASYMFEAT _IOR('c', 105, u_int32_t) #define CIOCGSESSION2 _IOWR('c', 106, struct session2_op) #define CIOCKEY2 _IOWR('c', 107, struct crypt_kop) #define CIOCFINDDEV _IOWR('c', 108, struct crypt_find_op) struct cryptotstat { struct timespec acc; /* total accumulated time */ struct timespec min; /* min time */ struct timespec max; /* max time */ u_int32_t count; /* number of observations */ }; struct cryptostats { u_int32_t cs_ops; /* symmetric crypto ops submitted */ u_int32_t cs_errs; /* symmetric crypto ops that failed */ u_int32_t cs_kops; /* asymetric/key ops submitted */ u_int32_t cs_kerrs; /* asymetric/key ops that failed */ u_int32_t cs_intrs; /* crypto swi thread activations */ u_int32_t cs_rets; /* crypto return thread activations */ u_int32_t cs_blocks; /* symmetric op driver block */ u_int32_t cs_kblocks; /* symmetric op driver block */ /* * When CRYPTO_TIMING is defined at compile time and the * sysctl debug.crypto is set to 1, the crypto system will * accumulate statistics about how long it takes to process * crypto requests at various points during processing. */ struct cryptotstat cs_invoke; /* crypto_dipsatch -> crypto_invoke */ struct cryptotstat cs_done; /* crypto_invoke -> crypto_done */ struct cryptotstat cs_cb; /* crypto_done -> callback */ struct cryptotstat cs_finis; /* callback -> callback return */ u_int32_t cs_drops; /* crypto ops dropped due to congestion */ }; #ifdef __KERNEL__ /* Standard initialization structure beginning */ struct cryptoini { int cri_alg; /* Algorithm to use */ int cri_klen; /* Key length, in bits */ int cri_mlen; /* Number of bytes we want from the entire hash. 0 means all. */ caddr_t cri_key; /* key to use */ u_int8_t cri_iv[EALG_MAX_BLOCK_LEN]; /* IV to use */ struct cryptoini *cri_next; }; /* Describe boundaries of a single crypto operation */ struct cryptodesc { int crd_skip; /* How many bytes to ignore from start */ int crd_len; /* How many bytes to process */ int crd_inject; /* Where to inject results, if applicable */ int crd_flags; #define CRD_F_ENCRYPT 0x01 /* Set when doing encryption */ #define CRD_F_IV_PRESENT 0x02 /* When encrypting, IV is already in place, so don't copy. */ #define CRD_F_IV_EXPLICIT 0x04 /* IV explicitly provided */ #define CRD_F_DSA_SHA_NEEDED 0x08 /* Compute SHA-1 of buffer for DSA */ #define CRD_F_KEY_EXPLICIT 0x10 /* Key explicitly provided */ #define CRD_F_COMP 0x0f /* Set when doing compression */ struct cryptoini CRD_INI; /* Initialization/context data */ #define crd_iv CRD_INI.cri_iv #define crd_key CRD_INI.cri_key #define crd_alg CRD_INI.cri_alg #define crd_klen CRD_INI.cri_klen #define crd_mlen CRD_INI.cri_mlen struct cryptodesc *crd_next; }; /* Structure describing complete operation */ struct cryptop { struct list_head crp_next; wait_queue_head_t crp_waitq; u_int64_t crp_sid; /* Session ID */ int crp_ilen; /* Input data total length */ int crp_olen; /* Result total length */ int crp_etype; /* * Error type (zero means no error). * All error codes except EAGAIN * indicate possible data corruption (as in, * the data have been touched). On all * errors, the crp_sid may have changed * (reset to a new one), so the caller * should always check and use the new * value on future requests. */ int crp_flags; #define CRYPTO_F_SKBUF 0x0001 /* Input/output are skbuf chains */ #define CRYPTO_F_IOV 0x0002 /* Input/output are uio */ #define CRYPTO_F_REL 0x0004 /* Must return data in same place */ #define CRYPTO_F_BATCH 0x0008 /* Batch op if possible */ #define CRYPTO_F_CBIMM 0x0010 /* Do callback immediately */ #define CRYPTO_F_DONE 0x0020 /* Operation completed */ #define CRYPTO_F_CBIFSYNC 0x0040 /* Do CBIMM if op is synchronous */ caddr_t crp_buf; /* Data to be processed */ caddr_t crp_opaque; /* Opaque pointer, passed along */ struct cryptodesc *crp_desc; /* Linked list of processing descriptors */ int (*crp_callback)(struct cryptop *); /* Callback function */ }; #define CRYPTO_BUF_CONTIG 0x0 #define CRYPTO_BUF_IOV 0x1 #define CRYPTO_BUF_SKBUF 0x2 #define CRYPTO_OP_DECRYPT 0x0 #define CRYPTO_OP_ENCRYPT 0x1 /* * Hints passed to process methods. */ #define CRYPTO_HINT_MORE 0x1 /* more ops coming shortly */ struct cryptkop { struct list_head krp_next; wait_queue_head_t krp_waitq; int krp_flags; #define CRYPTO_KF_DONE 0x0001 /* Operation completed */ #define CRYPTO_KF_CBIMM 0x0002 /* Do callback immediately */ u_int krp_op; /* ie. CRK_MOD_EXP or other */ u_int krp_status; /* return status */ u_short krp_iparams; /* # of input parameters */ u_short krp_oparams; /* # of output parameters */ u_int krp_crid; /* desired device, etc. */ u_int32_t krp_hid; struct crparam krp_param[CRK_MAXPARAM]; /* kvm */ int (*krp_callback)(struct cryptkop *); }; #include /* * Session ids are 64 bits. The lower 32 bits contain a "local id" which * is a driver-private session identifier. The upper 32 bits contain a * "hardware id" used by the core crypto code to identify the driver and * a copy of the driver's capabilities that can be used by client code to * optimize operation. */ #define CRYPTO_SESID2HID(_sid) (((_sid) >> 32) & 0x00ffffff) #define CRYPTO_SESID2CAPS(_sid) (((_sid) >> 32) & 0xff000000) #define CRYPTO_SESID2LID(_sid) (((u_int32_t) (_sid)) & 0xffffffff) extern int crypto_newsession(u_int64_t *sid, struct cryptoini *cri, int hard); extern int crypto_freesession(u_int64_t sid); #define CRYPTOCAP_F_HARDWARE CRYPTO_FLAG_HARDWARE #define CRYPTOCAP_F_SOFTWARE CRYPTO_FLAG_SOFTWARE #define CRYPTOCAP_F_SYNC 0x04000000 /* operates synchronously */ extern int32_t crypto_get_driverid(device_t dev, int flags); extern int crypto_find_driver(const char *); extern device_t crypto_find_device_byhid(int hid); extern int crypto_getcaps(int hid); extern int crypto_register(u_int32_t driverid, int alg, u_int16_t maxoplen, u_int32_t flags); extern int crypto_kregister(u_int32_t, int, u_int32_t); extern int crypto_unregister(u_int32_t driverid, int alg); extern int crypto_unregister_all(u_int32_t driverid); extern int crypto_dispatch(struct cryptop *crp); extern int crypto_kdispatch(struct cryptkop *); #define CRYPTO_SYMQ 0x1 #define CRYPTO_ASYMQ 0x2 extern int crypto_unblock(u_int32_t, int); extern void crypto_done(struct cryptop *crp); extern void crypto_kdone(struct cryptkop *); extern int crypto_getfeat(int *); extern void crypto_freereq(struct cryptop *crp); extern struct cryptop *crypto_getreq(int num); extern int crypto_usercrypto; /* userland may do crypto requests */ extern int crypto_userasymcrypto; /* userland may do asym crypto reqs */ extern int crypto_devallowsoft; /* only use hardware crypto */ /* * random number support, crypto_unregister_all will unregister */ extern int crypto_rregister(u_int32_t driverid, int (*read_random)(void *arg, u_int32_t *buf, int len), void *arg); extern int crypto_runregister_all(u_int32_t driverid); /* * Crypto-related utility routines used mainly by drivers. * * XXX these don't really belong here; but for now they're * kept apart from the rest of the system. */ struct uio; extern void cuio_copydata(struct uio *uio, int off, int len, caddr_t cp); extern void cuio_copyback(struct uio *uio, int off, int len, caddr_t cp); extern struct iovec *cuio_getptr(struct uio *uio, int loc, int *off); extern void crypto_copyback(int flags, caddr_t buf, int off, int size, caddr_t in); extern void crypto_copydata(int flags, caddr_t buf, int off, int size, caddr_t out); extern int crypto_apply(int flags, caddr_t buf, int off, int len, int (*f)(void *, void *, u_int), void *arg); #endif /* __KERNEL__ */ #endif /* _CRYPTO_CRYPTO_H_ */ libreswan-3.32/linux/include/des/000077500000000000000000000000001365625662500170045ustar00rootroot00000000000000libreswan-3.32/linux/include/des/des_locl.h000066400000000000000000000407661365625662500207560ustar00rootroot00000000000000/* crypto/des/des_locl.org */ /* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@cryptsoft.com). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are adhered to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@cryptsoft.com). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * 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 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@cryptsoft.com)" * The word 'cryptographic' can be left out if the routines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ /* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING * * Always modify des_locl.org since des_locl.h is automatically generated from * it during SSLeay configuration. * * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING */ #ifndef HEADER_DES_LOCL_H #define HEADER_DES_LOCL_H #if defined(WIN32) || defined(WIN16) #ifndef MSDOS #define MSDOS #endif #endif #include "klips-crypto/des.h" #ifndef DES_DEFAULT_OPTIONS /* the following is tweaked from a config script, that is why it is a * protected undef/define */ #ifndef DES_PTR #define DES_PTR #endif /* This helps C compiler generate the correct code for multiple functional * units. It reduces register dependencies at the expense of 2 more * registers */ #ifndef DES_RISC1 #define DES_RISC1 #endif #ifndef DES_RISC2 #undef DES_RISC2 #endif #if defined(DES_RISC1) && defined(DES_RISC2) YOU SHOULD NOT HAVE BOTH DES_RISC1 AND DES_RISC2 DEFINED !!!!! #endif /* Unroll the inner loop, this sometimes helps, sometimes hinders. * Very mucy CPU dependent */ #ifndef DES_UNROLL #define DES_UNROLL #endif /* These default values were supplied by * Peter Gutman * They are only used if nothing else has been defined */ #if !defined(DES_PTR) && !defined(DES_RISC1) && !defined(DES_RISC2) && \ !defined(DES_UNROLL) /* Special defines that change the way the code is built depending on the CPU and OS. For SGI machines you can use _MIPS_SZLONG (32 or 64) to find even newer MIPS CPU's, but at the moment one size fits all for optimization options. Older Sparc's work better with only UNROLL, but there's no way to tell at compile time what it is you're running on */ #if defined( sun ) /* Newer Sparc's */ # define DES_PTR # define DES_RISC1 # define DES_UNROLL #elif defined( __ultrix ) /* Older MIPS */ # define DES_PTR # define DES_RISC2 # define DES_UNROLL #elif defined( __osf1__ ) /* Alpha */ # define DES_PTR # define DES_RISC2 #elif defined ( _AIX ) /* RS6000 */ /* Unknown */ #elif defined( __hpux ) /* HP-PA */ /* Unknown */ #elif defined( __aux ) /* 68K */ /* Unknown */ #elif defined( __dgux ) /* 88K (but P6 in latest boxes) */ # define DES_UNROLL #elif defined( __sgi ) /* Newer MIPS */ # define DES_PTR # define DES_RISC2 # define DES_UNROLL #elif defined( i386 ) /* x86 boxes, should be gcc */ # define DES_PTR # define DES_RISC1 # define DES_UNROLL #endif /* Systems-specific speed defines */ #endif #endif /* DES_DEFAULT_OPTIONS */ #ifdef MSDOS /* Visual C++ 2.1 (Windows NT/95) */ #include #include #include #include #ifndef RAND #define RAND #endif #undef NOPROTO #endif #if defined(__STDC__) || defined(VMS) || defined(M_XENIX) || defined(MSDOS) #ifndef __KERNEL__ #include #else #include #endif #endif #ifndef RAND #define RAND #endif #ifdef linux #undef RAND #endif #ifdef MSDOS #define getpid() 2 #define RAND #undef NOPROTO #endif #if defined(NOCONST) #define const #endif #ifdef __STDC__ #undef NOPROTO #endif #define ITERATIONS 16 #define HALF_ITERATIONS 8 /* used in des_read and des_write */ #define MAXWRITE (1024 * 16) #define BSIZE (MAXWRITE + 4) #define c2l(c, l) (l = ((DES_LONG)(*((c)++))), \ l |= ((DES_LONG)(*((c)++))) << 8L, \ l |= ((DES_LONG)(*((c)++))) << 16L, \ l |= ((DES_LONG)(*((c)++))) << 24L) /* NOTE - c is not incremented as per c2l */ #define c2ln(c, l1, l2, n) { \ c += n; \ l1 = l2 = 0; \ switch (n) { \ case 8: l2 = ((DES_LONG)(*(--(c)))) << 24L; \ case 7: l2 |= ((DES_LONG)(*(--(c)))) << 16L; \ case 6: l2 |= ((DES_LONG)(*(--(c)))) << 8L; \ case 5: l2 |= ((DES_LONG)(*(--(c)))); \ case 4: l1 = ((DES_LONG)(*(--(c)))) << 24L; \ case 3: l1 |= ((DES_LONG)(*(--(c)))) << 16L; \ case 2: l1 |= ((DES_LONG)(*(--(c)))) << 8L; \ case 1: l1 |= ((DES_LONG)(*(--(c)))); \ } \ } #define l2c(l, c) (*((c)++) = (unsigned char)(((l) ) & 0xff), \ *((c)++) = (unsigned char)(((l) >> 8L) & 0xff), \ *((c)++) = (unsigned char)(((l) >> 16L) & 0xff), \ *((c)++) = (unsigned char)(((l) >> 24L) & 0xff)) /* replacements for htonl and ntohl since I have no idea what to do * when faced with machines with 8 byte longs. */ #define HDRSIZE 4 #define n2l(c, l) (l = ((DES_LONG)(*((c)++))) << 24L, \ l |= ((DES_LONG)(*((c)++))) << 16L, \ l |= ((DES_LONG)(*((c)++))) << 8L, \ l |= ((DES_LONG)(*((c)++)))) #define l2n(l, c) (*((c)++) = (unsigned char)(((l) >> 24L) & 0xff), \ *((c)++) = (unsigned char)(((l) >> 16L) & 0xff), \ *((c)++) = (unsigned char)(((l) >> 8L) & 0xff), \ *((c)++) = (unsigned char)(((l) ) & 0xff)) /* NOTE - c is not incremented as per l2c */ #define l2cn(l1, l2, c, n) { \ c += n; \ switch (n) { \ case 8: *(--(c)) = (unsigned char)(((l2) >> 24L) & 0xff); \ case 7: *(--(c)) = (unsigned char)(((l2) >> 16L) & 0xff); \ case 6: *(--(c)) = (unsigned char)(((l2) >> 8L) & 0xff); \ case 5: *(--(c)) = (unsigned char)(((l2) ) & 0xff); \ case 4: *(--(c)) = (unsigned char)(((l1) >> 24L) & 0xff); \ case 3: *(--(c)) = (unsigned char)(((l1) >> 16L) & 0xff); \ case 2: *(--(c)) = (unsigned char)(((l1) >> 8L) & 0xff); \ case 1: *(--(c)) = (unsigned char)(((l1) ) & 0xff); \ } \ } #define ROTATE(a, n) (((a) >> (n)) + ((a) << (32 - (n)))) /* Don't worry about the LOAD_DATA() stuff, that is used by * fcrypt() to add its little bit to the front */ #ifdef DES_FCRYPT #define LOAD_DATA_tmp(R, S, u, t, E0, E1) \ { DES_LONG tmp; LOAD_DATA(R, S, u, t, E0, E1, tmp); } #define LOAD_DATA(R, S, u, t, E0, E1, tmp) \ t = R ^ (R >> 16L); \ u = t & E0; t &= E1; \ tmp = (u << 16); u ^= R ^ s[S ]; u ^= tmp; \ tmp = (t << 16); t ^= R ^ s[S + 1]; t ^= tmp #else #define LOAD_DATA_tmp(a, b, c, d, e, f) LOAD_DATA(a, b, c, d, e, f, g) #define LOAD_DATA(R, S, u, t, E0, E1, tmp) \ u = R ^ s[S ]; \ t = R ^ s[S + 1] #endif /* The changes to this macro may help or hinder, depending on the * compiler and the achitecture. gcc2 always seems to do well :-). * Inspired by Dana How * DO NOT use the alternative version on machines with 8 byte longs. * It does not seem to work on the Alpha, even when DES_LONG is 4 * bytes, probably an issue of accessing non-word aligned objects :-( */ #ifdef DES_PTR /* It recently occurred to me that 0^0^0^0^0^0^0 == 0, so there * is no reason to not xor all the sub items together. This potentially * saves a register since things can be xored directly into L */ #if defined(DES_RISC1) || defined(DES_RISC2) #ifdef DES_RISC1 #define D_ENCRYPT(LL, R, S) { \ unsigned int u1, u2, u3; \ LOAD_DATA(R, S, u, t, E0, E1, u1); \ u2 = (int)u >> 8L; \ u1 = (int)u & 0xfc; \ u2 &= 0xfc; \ t = ROTATE(t, 4); \ u >>= 16L; \ LL ^= *(DES_LONG *)((unsigned char *)des_SP + u1); \ LL ^= *(DES_LONG *)((unsigned char *)des_SP + 0x200 + u2); \ u3 = (int)(u >> 8L); \ u1 = (int)u & 0xfc; \ u3 &= 0xfc; \ LL ^= *(DES_LONG *)((unsigned char *)des_SP + 0x400 + u1); \ LL ^= *(DES_LONG *)((unsigned char *)des_SP + 0x600 + u3); \ u2 = (int)t >> 8L; \ u1 = (int)t & 0xfc; \ u2 &= 0xfc; \ t >>= 16L; \ LL ^= *(DES_LONG *)((unsigned char *)des_SP + 0x100 + u1); \ LL ^= *(DES_LONG *)((unsigned char *)des_SP + 0x300 + u2); \ u3 = (int)t >> 8L; \ u1 = (int)t & 0xfc; \ u3 &= 0xfc; \ LL ^= *(DES_LONG *)((unsigned char *)des_SP + 0x500 + u1); \ LL ^= *(DES_LONG *)((unsigned char *)des_SP + 0x700 + u3); } #endif #ifdef DES_RISC2 #define D_ENCRYPT(LL, R, S) { \ unsigned int u1, u2, s1, s2; \ LOAD_DATA(R, S, u, t, E0, E1, u1); \ u2 = (int)u >> 8L; \ u1 = (int)u & 0xfc; \ u2 &= 0xfc; \ t = ROTATE(t, 4); \ LL ^= *(DES_LONG *)((unsigned char *)des_SP + u1); \ LL ^= *(DES_LONG *)((unsigned char *)des_SP + 0x200 + u2); \ s1 = (int)(u >> 16L); \ s2 = (int)(u >> 24L); \ s1 &= 0xfc; \ s2 &= 0xfc; \ LL ^= *(DES_LONG *)((unsigned char *)des_SP + 0x400 + s1); \ LL ^= *(DES_LONG *)((unsigned char *)des_SP + 0x600 + s2); \ u2 = (int)t >> 8L; \ u1 = (int)t & 0xfc; \ u2 &= 0xfc; \ LL ^= *(DES_LONG *)((unsigned char *)des_SP + 0x100 + u1); \ LL ^= *(DES_LONG *)((unsigned char *)des_SP + 0x300 + u2); \ s1 = (int)(t >> 16L); \ s2 = (int)(t >> 24L); \ s1 &= 0xfc; \ s2 &= 0xfc; \ LL ^= *(DES_LONG *)((unsigned char *)des_SP + 0x500 + s1); \ LL ^= *(DES_LONG *)((unsigned char *)des_SP + 0x700 + s2); } #endif #else #define D_ENCRYPT(LL, R, S) { \ LOAD_DATA_tmp(R, S, u, t, E0, E1); \ t = ROTATE(t, 4); \ LL ^= \ *(DES_LONG *)((unsigned char *)des_SP + \ ((u ) & 0xfc)) ^ \ *(DES_LONG *)((unsigned char *)des_SP + 0x200 + \ ((u >> 8L) & 0xfc)) ^ \ *(DES_LONG *)((unsigned char *)des_SP + 0x400 + \ ((u >> 16L) & 0xfc)) ^ \ *(DES_LONG *)((unsigned char *)des_SP + 0x600 + \ ((u >> 24L) & 0xfc)) ^ \ *(DES_LONG *)((unsigned char *)des_SP + 0x100 + \ ((t ) & 0xfc)) ^ \ *(DES_LONG *)((unsigned char *)des_SP + 0x300 + \ ((t >> 8L) & 0xfc)) ^ \ *(DES_LONG *)((unsigned char *)des_SP + 0x500 + \ ((t >> 16L) & 0xfc)) ^ \ *(DES_LONG *)((unsigned char *)des_SP + 0x700 + \ ((t >> 24L) & 0xfc)); } #endif #else /* original version */ #if defined(DES_RISC1) || defined(DES_RISC2) #ifdef DES_RISC1 #define D_ENCRYPT(LL, R, S) { \ unsigned int u1, u2, u3; \ LOAD_DATA(R, S, u, t, E0, E1, u1); \ u >>= 2L; \ t = ROTATE(t, 6); \ u2 = (int)u >> 8L; \ u1 = (int)u & 0x3f; \ u2 &= 0x3f; \ u >>= 16L; \ LL ^= des_SPtrans[0][u1]; \ LL ^= des_SPtrans[2][u2]; \ u3 = (int)u >> 8L; \ u1 = (int)u & 0x3f; \ u3 &= 0x3f; \ LL ^= des_SPtrans[4][u1]; \ LL ^= des_SPtrans[6][u3]; \ u2 = (int)t >> 8L; \ u1 = (int)t & 0x3f; \ u2 &= 0x3f; \ t >>= 16L; \ LL ^= des_SPtrans[1][u1]; \ LL ^= des_SPtrans[3][u2]; \ u3 = (int)t >> 8L; \ u1 = (int)t & 0x3f; \ u3 &= 0x3f; \ LL ^= des_SPtrans[5][u1]; \ LL ^= des_SPtrans[7][u3]; } #endif #ifdef DES_RISC2 #define D_ENCRYPT(LL, R, S) { \ unsigned int u1, u2, s1, s2; \ LOAD_DATA(R, S, u, t, E0, E1, u1); \ u >>= 2L; \ t = ROTATE(t, 6); \ u2 = (int)u >> 8L; \ u1 = (int)u & 0x3f; \ u2 &= 0x3f; \ LL ^= des_SPtrans[0][u1]; \ LL ^= des_SPtrans[2][u2]; \ s1 = (int)u >> 16L; \ s2 = (int)u >> 24L; \ s1 &= 0x3f; \ s2 &= 0x3f; \ LL ^= des_SPtrans[4][s1]; \ LL ^= des_SPtrans[6][s2]; \ u2 = (int)t >> 8L; \ u1 = (int)t & 0x3f; \ u2 &= 0x3f; \ LL ^= des_SPtrans[1][u1]; \ LL ^= des_SPtrans[3][u2]; \ s1 = (int)t >> 16; \ s2 = (int)t >> 24L; \ s1 &= 0x3f; \ s2 &= 0x3f; \ LL ^= des_SPtrans[5][s1]; \ LL ^= des_SPtrans[7][s2]; } #endif #else #define D_ENCRYPT(LL, R, S) { \ LOAD_DATA_tmp(R, S, u, t, E0, E1); \ t = ROTATE(t, 4); \ LL ^= \ des_SPtrans[0][(u >> 2L) & 0x3f] ^ \ des_SPtrans[2][(u >> 10L) & 0x3f] ^ \ des_SPtrans[4][(u >> 18L) & 0x3f] ^ \ des_SPtrans[6][(u >> 26L) & 0x3f] ^ \ des_SPtrans[1][(t >> 2L) & 0x3f] ^ \ des_SPtrans[3][(t >> 10L) & 0x3f] ^ \ des_SPtrans[5][(t >> 18L) & 0x3f] ^ \ des_SPtrans[7][(t >> 26L) & 0x3f]; } #endif #endif /* IP and FP * The problem is more of a geometric problem that random bit fiddling. 0 1 2 3 4 5 6 7 62 54 46 38 30 22 14 6 8 9 10 11 12 13 14 15 60 52 44 36 28 20 12 4 16 17 18 19 20 21 22 23 58 50 42 34 26 18 10 2 24 25 26 27 28 29 30 31 to 56 48 40 32 24 16 8 0 32 33 34 35 36 37 38 39 63 55 47 39 31 23 15 7 40 41 42 43 44 45 46 47 61 53 45 37 29 21 13 5 48 49 50 51 52 53 54 55 59 51 43 35 27 19 11 3 56 57 58 59 60 61 62 63 57 49 41 33 25 17 9 1 The output has been subject to swaps of the form 0 1 -> 3 1 but the odd and even bits have been put into 2 3 2 0 different words. The main trick is to remember that t=((l>>size)^r)&(mask); r^=t; l^=(t<> (n)) ^ (b)) & (m)), \ (b) ^= (t), \ (a) ^= ((t) << (n))) #define IP(l, r) \ { \ register DES_LONG tt; \ PERM_OP(r, l, tt, 4, 0x0f0f0f0fL); \ PERM_OP(l, r, tt, 16, 0x0000ffffL); \ PERM_OP(r, l, tt, 2, 0x33333333L); \ PERM_OP(l, r, tt, 8, 0x00ff00ffL); \ PERM_OP(r, l, tt, 1, 0x55555555L); \ } #define FP(l, r) \ { \ register DES_LONG tt; \ PERM_OP(l, r, tt, 1, 0x55555555L); \ PERM_OP(r, l, tt, 8, 0x00ff00ffL); \ PERM_OP(l, r, tt, 2, 0x33333333L); \ PERM_OP(r, l, tt, 16, 0x0000ffffL); \ PERM_OP(l, r, tt, 4, 0x0f0f0f0fL); \ } extern const DES_LONG des_SPtrans[8][64]; #ifndef NO_FCRYPT #ifndef NOPROTO void fcrypt_body(DES_LONG *out, des_key_schedule ks, DES_LONG Eswap0, DES_LONG Eswap1); #else void fcrypt_body(void); #endif #endif /* NO_FCRYPT */ #endif libreswan-3.32/linux/include/des/des_ver.h000066400000000000000000000063641365625662500206150ustar00rootroot00000000000000/* crypto/des/des_ver.h */ /* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@cryptsoft.com). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are adhered to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@cryptsoft.com). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * 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 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@cryptsoft.com)" * The word 'cryptographic' can be left out if the routines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ extern char *DES_version; /* SSLeay version string */ extern char *libdes_version; /* old libdes version string */ libreswan-3.32/linux/include/des/podd.h000066400000000000000000000105331365625662500201050ustar00rootroot00000000000000/* crypto/des/podd.h */ /* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@cryptsoft.com). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are adhered to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@cryptsoft.com). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * 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 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@cryptsoft.com)" * The word 'cryptographic' can be left out if the routines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ static const unsigned char odd_parity[256] = { 1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14, 16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31, 32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47, 49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62, 64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79, 81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94, 97, 97, 98, 98, 100, 100, 103, 103, 104, 104, 107, 107, 109, 109, 110, 110, 112, 112, 115, 115, 117, 117, 118, 118, 121, 121, 122, 122, 124, 124, 127, 127, 128, 128, 131, 131, 133, 133, 134, 134, 137, 137, 138, 138, 140, 140, 143, 143, 145, 145, 146, 146, 148, 148, 151, 151, 152, 152, 155, 155, 157, 157, 158, 158, 161, 161, 162, 162, 164, 164, 167, 167, 168, 168, 171, 171, 173, 173, 174, 174, 176, 176, 179, 179, 181, 181, 182, 182, 185, 185, 186, 186, 188, 188, 191, 191, 193, 193, 194, 194, 196, 196, 199, 199, 200, 200, 203, 203, 205, 205, 206, 206, 208, 208, 211, 211, 213, 213, 214, 214, 217, 217, 218, 218, 220, 220, 223, 223, 224, 224, 227, 227, 229, 229, 230, 230, 233, 233, 234, 234, 236, 236, 239, 239, 241, 241, 242, 242, 244, 244, 247, 247, 248, 248, 251, 251, 253, 253, 254, 254 }; libreswan-3.32/linux/include/des/sk.h000066400000000000000000000246471365625662500176070ustar00rootroot00000000000000/* crypto/des/sk.h */ /* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@cryptsoft.com). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are adhered to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@cryptsoft.com). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * 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 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@cryptsoft.com)" * The word 'cryptographic' can be left out if the routines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ static const DES_LONG des_skb[8][64] = { { /* for C bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ 0x00000000L, 0x00000010L, 0x20000000L, 0x20000010L, 0x00010000L, 0x00010010L, 0x20010000L, 0x20010010L, 0x00000800L, 0x00000810L, 0x20000800L, 0x20000810L, 0x00010800L, 0x00010810L, 0x20010800L, 0x20010810L, 0x00000020L, 0x00000030L, 0x20000020L, 0x20000030L, 0x00010020L, 0x00010030L, 0x20010020L, 0x20010030L, 0x00000820L, 0x00000830L, 0x20000820L, 0x20000830L, 0x00010820L, 0x00010830L, 0x20010820L, 0x20010830L, 0x00080000L, 0x00080010L, 0x20080000L, 0x20080010L, 0x00090000L, 0x00090010L, 0x20090000L, 0x20090010L, 0x00080800L, 0x00080810L, 0x20080800L, 0x20080810L, 0x00090800L, 0x00090810L, 0x20090800L, 0x20090810L, 0x00080020L, 0x00080030L, 0x20080020L, 0x20080030L, 0x00090020L, 0x00090030L, 0x20090020L, 0x20090030L, 0x00080820L, 0x00080830L, 0x20080820L, 0x20080830L, 0x00090820L, 0x00090830L, 0x20090820L, 0x20090830L, }, { /* for C bits (numbered as per FIPS 46) 7 8 10 11 12 13 */ 0x00000000L, 0x02000000L, 0x00002000L, 0x02002000L, 0x00200000L, 0x02200000L, 0x00202000L, 0x02202000L, 0x00000004L, 0x02000004L, 0x00002004L, 0x02002004L, 0x00200004L, 0x02200004L, 0x00202004L, 0x02202004L, 0x00000400L, 0x02000400L, 0x00002400L, 0x02002400L, 0x00200400L, 0x02200400L, 0x00202400L, 0x02202400L, 0x00000404L, 0x02000404L, 0x00002404L, 0x02002404L, 0x00200404L, 0x02200404L, 0x00202404L, 0x02202404L, 0x10000000L, 0x12000000L, 0x10002000L, 0x12002000L, 0x10200000L, 0x12200000L, 0x10202000L, 0x12202000L, 0x10000004L, 0x12000004L, 0x10002004L, 0x12002004L, 0x10200004L, 0x12200004L, 0x10202004L, 0x12202004L, 0x10000400L, 0x12000400L, 0x10002400L, 0x12002400L, 0x10200400L, 0x12200400L, 0x10202400L, 0x12202400L, 0x10000404L, 0x12000404L, 0x10002404L, 0x12002404L, 0x10200404L, 0x12200404L, 0x10202404L, 0x12202404L, }, { /* for C bits (numbered as per FIPS 46) 14 15 16 17 19 20 */ 0x00000000L, 0x00000001L, 0x00040000L, 0x00040001L, 0x01000000L, 0x01000001L, 0x01040000L, 0x01040001L, 0x00000002L, 0x00000003L, 0x00040002L, 0x00040003L, 0x01000002L, 0x01000003L, 0x01040002L, 0x01040003L, 0x00000200L, 0x00000201L, 0x00040200L, 0x00040201L, 0x01000200L, 0x01000201L, 0x01040200L, 0x01040201L, 0x00000202L, 0x00000203L, 0x00040202L, 0x00040203L, 0x01000202L, 0x01000203L, 0x01040202L, 0x01040203L, 0x08000000L, 0x08000001L, 0x08040000L, 0x08040001L, 0x09000000L, 0x09000001L, 0x09040000L, 0x09040001L, 0x08000002L, 0x08000003L, 0x08040002L, 0x08040003L, 0x09000002L, 0x09000003L, 0x09040002L, 0x09040003L, 0x08000200L, 0x08000201L, 0x08040200L, 0x08040201L, 0x09000200L, 0x09000201L, 0x09040200L, 0x09040201L, 0x08000202L, 0x08000203L, 0x08040202L, 0x08040203L, 0x09000202L, 0x09000203L, 0x09040202L, 0x09040203L, }, { /* for C bits (numbered as per FIPS 46) 21 23 24 26 27 28 */ 0x00000000L, 0x00100000L, 0x00000100L, 0x00100100L, 0x00000008L, 0x00100008L, 0x00000108L, 0x00100108L, 0x00001000L, 0x00101000L, 0x00001100L, 0x00101100L, 0x00001008L, 0x00101008L, 0x00001108L, 0x00101108L, 0x04000000L, 0x04100000L, 0x04000100L, 0x04100100L, 0x04000008L, 0x04100008L, 0x04000108L, 0x04100108L, 0x04001000L, 0x04101000L, 0x04001100L, 0x04101100L, 0x04001008L, 0x04101008L, 0x04001108L, 0x04101108L, 0x00020000L, 0x00120000L, 0x00020100L, 0x00120100L, 0x00020008L, 0x00120008L, 0x00020108L, 0x00120108L, 0x00021000L, 0x00121000L, 0x00021100L, 0x00121100L, 0x00021008L, 0x00121008L, 0x00021108L, 0x00121108L, 0x04020000L, 0x04120000L, 0x04020100L, 0x04120100L, 0x04020008L, 0x04120008L, 0x04020108L, 0x04120108L, 0x04021000L, 0x04121000L, 0x04021100L, 0x04121100L, 0x04021008L, 0x04121008L, 0x04021108L, 0x04121108L, }, { /* for D bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ 0x00000000L, 0x10000000L, 0x00010000L, 0x10010000L, 0x00000004L, 0x10000004L, 0x00010004L, 0x10010004L, 0x20000000L, 0x30000000L, 0x20010000L, 0x30010000L, 0x20000004L, 0x30000004L, 0x20010004L, 0x30010004L, 0x00100000L, 0x10100000L, 0x00110000L, 0x10110000L, 0x00100004L, 0x10100004L, 0x00110004L, 0x10110004L, 0x20100000L, 0x30100000L, 0x20110000L, 0x30110000L, 0x20100004L, 0x30100004L, 0x20110004L, 0x30110004L, 0x00001000L, 0x10001000L, 0x00011000L, 0x10011000L, 0x00001004L, 0x10001004L, 0x00011004L, 0x10011004L, 0x20001000L, 0x30001000L, 0x20011000L, 0x30011000L, 0x20001004L, 0x30001004L, 0x20011004L, 0x30011004L, 0x00101000L, 0x10101000L, 0x00111000L, 0x10111000L, 0x00101004L, 0x10101004L, 0x00111004L, 0x10111004L, 0x20101000L, 0x30101000L, 0x20111000L, 0x30111000L, 0x20101004L, 0x30101004L, 0x20111004L, 0x30111004L, }, { /* for D bits (numbered as per FIPS 46) 8 9 11 12 13 14 */ 0x00000000L, 0x08000000L, 0x00000008L, 0x08000008L, 0x00000400L, 0x08000400L, 0x00000408L, 0x08000408L, 0x00020000L, 0x08020000L, 0x00020008L, 0x08020008L, 0x00020400L, 0x08020400L, 0x00020408L, 0x08020408L, 0x00000001L, 0x08000001L, 0x00000009L, 0x08000009L, 0x00000401L, 0x08000401L, 0x00000409L, 0x08000409L, 0x00020001L, 0x08020001L, 0x00020009L, 0x08020009L, 0x00020401L, 0x08020401L, 0x00020409L, 0x08020409L, 0x02000000L, 0x0A000000L, 0x02000008L, 0x0A000008L, 0x02000400L, 0x0A000400L, 0x02000408L, 0x0A000408L, 0x02020000L, 0x0A020000L, 0x02020008L, 0x0A020008L, 0x02020400L, 0x0A020400L, 0x02020408L, 0x0A020408L, 0x02000001L, 0x0A000001L, 0x02000009L, 0x0A000009L, 0x02000401L, 0x0A000401L, 0x02000409L, 0x0A000409L, 0x02020001L, 0x0A020001L, 0x02020009L, 0x0A020009L, 0x02020401L, 0x0A020401L, 0x02020409L, 0x0A020409L, }, { /* for D bits (numbered as per FIPS 46) 16 17 18 19 20 21 */ 0x00000000L, 0x00000100L, 0x00080000L, 0x00080100L, 0x01000000L, 0x01000100L, 0x01080000L, 0x01080100L, 0x00000010L, 0x00000110L, 0x00080010L, 0x00080110L, 0x01000010L, 0x01000110L, 0x01080010L, 0x01080110L, 0x00200000L, 0x00200100L, 0x00280000L, 0x00280100L, 0x01200000L, 0x01200100L, 0x01280000L, 0x01280100L, 0x00200010L, 0x00200110L, 0x00280010L, 0x00280110L, 0x01200010L, 0x01200110L, 0x01280010L, 0x01280110L, 0x00000200L, 0x00000300L, 0x00080200L, 0x00080300L, 0x01000200L, 0x01000300L, 0x01080200L, 0x01080300L, 0x00000210L, 0x00000310L, 0x00080210L, 0x00080310L, 0x01000210L, 0x01000310L, 0x01080210L, 0x01080310L, 0x00200200L, 0x00200300L, 0x00280200L, 0x00280300L, 0x01200200L, 0x01200300L, 0x01280200L, 0x01280300L, 0x00200210L, 0x00200310L, 0x00280210L, 0x00280310L, 0x01200210L, 0x01200310L, 0x01280210L, 0x01280310L, }, { /* for D bits (numbered as per FIPS 46) 22 23 24 25 27 28 */ 0x00000000L, 0x04000000L, 0x00040000L, 0x04040000L, 0x00000002L, 0x04000002L, 0x00040002L, 0x04040002L, 0x00002000L, 0x04002000L, 0x00042000L, 0x04042000L, 0x00002002L, 0x04002002L, 0x00042002L, 0x04042002L, 0x00000020L, 0x04000020L, 0x00040020L, 0x04040020L, 0x00000022L, 0x04000022L, 0x00040022L, 0x04040022L, 0x00002020L, 0x04002020L, 0x00042020L, 0x04042020L, 0x00002022L, 0x04002022L, 0x00042022L, 0x04042022L, 0x00000800L, 0x04000800L, 0x00040800L, 0x04040800L, 0x00000802L, 0x04000802L, 0x00040802L, 0x04040802L, 0x00002800L, 0x04002800L, 0x00042800L, 0x04042800L, 0x00002802L, 0x04002802L, 0x00042802L, 0x04042802L, 0x00000820L, 0x04000820L, 0x00040820L, 0x04040820L, 0x00000822L, 0x04000822L, 0x00040822L, 0x04040822L, 0x00002820L, 0x04002820L, 0x00042820L, 0x04042820L, 0x00002822L, 0x04002822L, 0x00042822L, 0x04042822L, } }; libreswan-3.32/linux/include/des/spr.h000066400000000000000000000241051365625662500177630ustar00rootroot00000000000000/* crypto/des/spr.h */ /* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@cryptsoft.com). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are adhered to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@cryptsoft.com). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * 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 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@cryptsoft.com)" * The word 'cryptographic' can be left out if the routines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ const DES_LONG des_SPtrans[8][64] = { { /* nibble 0 */ 0x02080800L, 0x00080000L, 0x02000002L, 0x02080802L, 0x02000000L, 0x00080802L, 0x00080002L, 0x02000002L, 0x00080802L, 0x02080800L, 0x02080000L, 0x00000802L, 0x02000802L, 0x02000000L, 0x00000000L, 0x00080002L, 0x00080000L, 0x00000002L, 0x02000800L, 0x00080800L, 0x02080802L, 0x02080000L, 0x00000802L, 0x02000800L, 0x00000002L, 0x00000800L, 0x00080800L, 0x02080002L, 0x00000800L, 0x02000802L, 0x02080002L, 0x00000000L, 0x00000000L, 0x02080802L, 0x02000800L, 0x00080002L, 0x02080800L, 0x00080000L, 0x00000802L, 0x02000800L, 0x02080002L, 0x00000800L, 0x00080800L, 0x02000002L, 0x00080802L, 0x00000002L, 0x02000002L, 0x02080000L, 0x02080802L, 0x00080800L, 0x02080000L, 0x02000802L, 0x02000000L, 0x00000802L, 0x00080002L, 0x00000000L, 0x00080000L, 0x02000000L, 0x02000802L, 0x02080800L, 0x00000002L, 0x02080002L, 0x00000800L, 0x00080802L, }, { /* nibble 1 */ 0x40108010L, 0x00000000L, 0x00108000L, 0x40100000L, 0x40000010L, 0x00008010L, 0x40008000L, 0x00108000L, 0x00008000L, 0x40100010L, 0x00000010L, 0x40008000L, 0x00100010L, 0x40108000L, 0x40100000L, 0x00000010L, 0x00100000L, 0x40008010L, 0x40100010L, 0x00008000L, 0x00108010L, 0x40000000L, 0x00000000L, 0x00100010L, 0x40008010L, 0x00108010L, 0x40108000L, 0x40000010L, 0x40000000L, 0x00100000L, 0x00008010L, 0x40108010L, 0x00100010L, 0x40108000L, 0x40008000L, 0x00108010L, 0x40108010L, 0x00100010L, 0x40000010L, 0x00000000L, 0x40000000L, 0x00008010L, 0x00100000L, 0x40100010L, 0x00008000L, 0x40000000L, 0x00108010L, 0x40008010L, 0x40108000L, 0x00008000L, 0x00000000L, 0x40000010L, 0x00000010L, 0x40108010L, 0x00108000L, 0x40100000L, 0x40100010L, 0x00100000L, 0x00008010L, 0x40008000L, 0x40008010L, 0x00000010L, 0x40100000L, 0x00108000L, }, { /* nibble 2 */ 0x04000001L, 0x04040100L, 0x00000100L, 0x04000101L, 0x00040001L, 0x04000000L, 0x04000101L, 0x00040100L, 0x04000100L, 0x00040000L, 0x04040000L, 0x00000001L, 0x04040101L, 0x00000101L, 0x00000001L, 0x04040001L, 0x00000000L, 0x00040001L, 0x04040100L, 0x00000100L, 0x00000101L, 0x04040101L, 0x00040000L, 0x04000001L, 0x04040001L, 0x04000100L, 0x00040101L, 0x04040000L, 0x00040100L, 0x00000000L, 0x04000000L, 0x00040101L, 0x04040100L, 0x00000100L, 0x00000001L, 0x00040000L, 0x00000101L, 0x00040001L, 0x04040000L, 0x04000101L, 0x00000000L, 0x04040100L, 0x00040100L, 0x04040001L, 0x00040001L, 0x04000000L, 0x04040101L, 0x00000001L, 0x00040101L, 0x04000001L, 0x04000000L, 0x04040101L, 0x00040000L, 0x04000100L, 0x04000101L, 0x00040100L, 0x04000100L, 0x00000000L, 0x04040001L, 0x00000101L, 0x04000001L, 0x00040101L, 0x00000100L, 0x04040000L, }, { /* nibble 3 */ 0x00401008L, 0x10001000L, 0x00000008L, 0x10401008L, 0x00000000L, 0x10400000L, 0x10001008L, 0x00400008L, 0x10401000L, 0x10000008L, 0x10000000L, 0x00001008L, 0x10000008L, 0x00401008L, 0x00400000L, 0x10000000L, 0x10400008L, 0x00401000L, 0x00001000L, 0x00000008L, 0x00401000L, 0x10001008L, 0x10400000L, 0x00001000L, 0x00001008L, 0x00000000L, 0x00400008L, 0x10401000L, 0x10001000L, 0x10400008L, 0x10401008L, 0x00400000L, 0x10400008L, 0x00001008L, 0x00400000L, 0x10000008L, 0x00401000L, 0x10001000L, 0x00000008L, 0x10400000L, 0x10001008L, 0x00000000L, 0x00001000L, 0x00400008L, 0x00000000L, 0x10400008L, 0x10401000L, 0x00001000L, 0x10000000L, 0x10401008L, 0x00401008L, 0x00400000L, 0x10401008L, 0x00000008L, 0x10001000L, 0x00401008L, 0x00400008L, 0x00401000L, 0x10400000L, 0x10001008L, 0x00001008L, 0x10000000L, 0x10000008L, 0x10401000L, }, { /* nibble 4 */ 0x08000000L, 0x00010000L, 0x00000400L, 0x08010420L, 0x08010020L, 0x08000400L, 0x00010420L, 0x08010000L, 0x00010000L, 0x00000020L, 0x08000020L, 0x00010400L, 0x08000420L, 0x08010020L, 0x08010400L, 0x00000000L, 0x00010400L, 0x08000000L, 0x00010020L, 0x00000420L, 0x08000400L, 0x00010420L, 0x00000000L, 0x08000020L, 0x00000020L, 0x08000420L, 0x08010420L, 0x00010020L, 0x08010000L, 0x00000400L, 0x00000420L, 0x08010400L, 0x08010400L, 0x08000420L, 0x00010020L, 0x08010000L, 0x00010000L, 0x00000020L, 0x08000020L, 0x08000400L, 0x08000000L, 0x00010400L, 0x08010420L, 0x00000000L, 0x00010420L, 0x08000000L, 0x00000400L, 0x00010020L, 0x08000420L, 0x00000400L, 0x00000000L, 0x08010420L, 0x08010020L, 0x08010400L, 0x00000420L, 0x00010000L, 0x00010400L, 0x08010020L, 0x08000400L, 0x00000420L, 0x00000020L, 0x00010420L, 0x08010000L, 0x08000020L, }, { /* nibble 5 */ 0x80000040L, 0x00200040L, 0x00000000L, 0x80202000L, 0x00200040L, 0x00002000L, 0x80002040L, 0x00200000L, 0x00002040L, 0x80202040L, 0x00202000L, 0x80000000L, 0x80002000L, 0x80000040L, 0x80200000L, 0x00202040L, 0x00200000L, 0x80002040L, 0x80200040L, 0x00000000L, 0x00002000L, 0x00000040L, 0x80202000L, 0x80200040L, 0x80202040L, 0x80200000L, 0x80000000L, 0x00002040L, 0x00000040L, 0x00202000L, 0x00202040L, 0x80002000L, 0x00002040L, 0x80000000L, 0x80002000L, 0x00202040L, 0x80202000L, 0x00200040L, 0x00000000L, 0x80002000L, 0x80000000L, 0x00002000L, 0x80200040L, 0x00200000L, 0x00200040L, 0x80202040L, 0x00202000L, 0x00000040L, 0x80202040L, 0x00202000L, 0x00200000L, 0x80002040L, 0x80000040L, 0x80200000L, 0x00202040L, 0x00000000L, 0x00002000L, 0x80000040L, 0x80002040L, 0x80202000L, 0x80200000L, 0x00002040L, 0x00000040L, 0x80200040L, }, { /* nibble 6 */ 0x00004000L, 0x00000200L, 0x01000200L, 0x01000004L, 0x01004204L, 0x00004004L, 0x00004200L, 0x00000000L, 0x01000000L, 0x01000204L, 0x00000204L, 0x01004000L, 0x00000004L, 0x01004200L, 0x01004000L, 0x00000204L, 0x01000204L, 0x00004000L, 0x00004004L, 0x01004204L, 0x00000000L, 0x01000200L, 0x01000004L, 0x00004200L, 0x01004004L, 0x00004204L, 0x01004200L, 0x00000004L, 0x00004204L, 0x01004004L, 0x00000200L, 0x01000000L, 0x00004204L, 0x01004000L, 0x01004004L, 0x00000204L, 0x00004000L, 0x00000200L, 0x01000000L, 0x01004004L, 0x01000204L, 0x00004204L, 0x00004200L, 0x00000000L, 0x00000200L, 0x01000004L, 0x00000004L, 0x01000200L, 0x00000000L, 0x01000204L, 0x01000200L, 0x00004200L, 0x00000204L, 0x00004000L, 0x01004204L, 0x01000000L, 0x01004200L, 0x00000004L, 0x00004004L, 0x01004204L, 0x01000004L, 0x01004200L, 0x01004000L, 0x00004004L, }, { /* nibble 7 */ 0x20800080L, 0x20820000L, 0x00020080L, 0x00000000L, 0x20020000L, 0x00800080L, 0x20800000L, 0x20820080L, 0x00000080L, 0x20000000L, 0x00820000L, 0x00020080L, 0x00820080L, 0x20020080L, 0x20000080L, 0x20800000L, 0x00020000L, 0x00820080L, 0x00800080L, 0x20020000L, 0x20820080L, 0x20000080L, 0x00000000L, 0x00820000L, 0x20000000L, 0x00800000L, 0x20020080L, 0x20800080L, 0x00800000L, 0x00020000L, 0x20820000L, 0x00000080L, 0x00800000L, 0x00020000L, 0x20000080L, 0x20820080L, 0x00020080L, 0x20000000L, 0x00000000L, 0x00820000L, 0x20800080L, 0x20020080L, 0x20020000L, 0x00800080L, 0x20820000L, 0x00000080L, 0x00800080L, 0x20020000L, 0x20820080L, 0x00800000L, 0x20800000L, 0x20000080L, 0x00820000L, 0x00020080L, 0x20020080L, 0x20800000L, 0x00000080L, 0x20820000L, 0x00820080L, 0x00000000L, 0x20000000L, 0x20800080L, 0x00020000L, 0x00820080L, } }; libreswan-3.32/linux/include/err.h000066400000000000000000000025001365625662500171670ustar00rootroot00000000000000/* error return type, for libreswan * * Copyright (C) 1998, 1999, 2000 Henry Spencer. * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef ERR_H #define ERR_H /* * Many routines return only success or failure, but wish to describe * the failure in a message. We use the convention that they return a * NULL on success and a pointer to constant string on failure. The * fact that the string is a constant is limiting, but it avoids * storage management issues: the recipient is allowed to assume that * the string will live "long enough" (usually forever). * * XXX: Since the above was written pluto has become multi-threaded * so, only when on the main thread, can this be true. */ typedef const char *err_t; /* error message, or NULL for success */ #endif libreswan-3.32/linux/include/ip_address.h000066400000000000000000000065251365625662500205270ustar00rootroot00000000000000/* * header file for Libreswan library functions * Copyright (C) 1998, 1999, 2000 Henry Spencer. * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. * */ #ifndef IP_ADDRESS_H #define IP_ADDRESS_H #if !defined(__KERNEL__) #include "chunk.h" #endif /* * Hack around this file being sucked into linux kernel module builds. */ #if !defined(__KERNEL__) #include /* for struct sockaddr_in */ #ifdef HAVE_INET6_IN6_H #include /* for struct sockaddr_in6 */ #endif #endif struct lswlog; /* * The type IP_ADDRESS is shared between KLIPS (kernel module) and * PLUTO. Its definition is buried in the common include file * "libreswan.h". * * This header contains declarations for userland specific extensions. * Their implementation is found in libswan.a. * * When KLIPS goes away, the definition of IP_ADDRESS et.al., can be * moved here. */ /* * Basic data types for the address-handling functions. * ip_address and ip_subnet are supposed to be opaque types; do not * use their definitions directly, they are subject to change! */ typedef struct { union { struct sockaddr_in v4; struct sockaddr_in6 v6; } u; } ip_address; /* network byte ordered */ int nportof(const ip_address *src); ip_address nsetportof(int port, ip_address dst); /* host byte ordered */ int hportof(const ip_address *src); ip_address hsetportof(int port, const ip_address dst); /* XXX: compatibility */ #define portof(SRC) nportof((SRC)) #define setportof(PORT, DST) { *(DST) = nsetportof(PORT, *(DST)); } struct sockaddr *sockaddrof(const ip_address *src); size_t sockaddrlenof(const ip_address *src); /* RFC 1886 old IPv6 reverse-lookup format is the bulkiest */ #define ADDRTOT_BUF (32 * 2 + 3 + 1 + 3 + 1 + 1) typedef struct { char private_buf[ADDRTOT_BUF]; /* defined in libreswan.h */ } ipstr_buf; const char *ipstr(const ip_address *src, ipstr_buf *b); const char *sensitive_ipstr(const ip_address *src, ipstr_buf *b); /* See: ipstr() / sensitive_ipstr() */ size_t lswlog_ip(struct lswlog *buf, const ip_address *ip); size_t lswlog_sensitive_ip(struct lswlog *buf, const ip_address *ip); /* * isvalidaddr(): true when ADDR contains some sort of IPv4 or IPv6 * address. * * The relationship !isvalidaddr() IFF ipstr()=="" is ment to * hold. Both the *addrtot() (used by ipstr()) and *portof() seem to * use the same check. hportof() just happens to be an easy way to * access it. * * The routine isanyaddr() isn't used as, in addition to "" * it includes magic "any" IPv4 and IPv6 addresses. */ #define isvalidaddr(ADDR) (hportof(ADDR) >= 0) /* * address as a chunk * * XXX: chunk_t doesn't do const so this strips off the constiness of * address :-( */ #if !defined(__KERNEL__) chunk_t same_ip_address_as_chunk(const ip_address *address); #endif #endif libreswan-3.32/linux/include/klips-crypto/000077500000000000000000000000001365625662500206715ustar00rootroot00000000000000libreswan-3.32/linux/include/klips-crypto/aes.h000066400000000000000000000071311365625662500216140ustar00rootroot00000000000000// I retain copyright in this code but I encourage its free use provided // that I don't carry any responsibility for the results. I am especially // happy to see it used in free and open source software. If you do use // it I would appreciate an acknowledgement of its origin in the code or // the product that results and I would also appreciate knowing a little // about the use to which it is being put. I am grateful to Frank Yellin // for some ideas that are used in this implementation. // // Dr B. R. Gladman 6th April 2001. // // This is an implementation of the AES encryption algorithm (Rijndael) // designed by Joan Daemen and Vincent Rijmen. This version is designed // to provide both fixed and dynamic block and key lengths and can also // run with either big or little endian internal byte order (see aes.h). // It inputs block and key lengths in bytes with the legal values being // 16, 24 and 32. /* * Modified by Jari Ruusu, May 1 2001 * - Fixed some compile warnings, code was ok but gcc warned anyway. * - Changed basic types: byte -> unsigned char, word -> u_int32_t * - Major name space cleanup: Names visible to outside now begin * with "aes_" or "AES_". A lot of stuff moved from aes.h to aes.c * - Removed C++ and DLL support as part of name space cleanup. * - Eliminated unnecessary recomputation of tables. (actual bug fix) * - Merged precomputed constant tables to aes.c file. * - Removed data alignment restrictions for portability reasons. * - Made block and key lengths accept bit count (128/192/256) * as well byte count (16/24/32). * - Removed all error checks. This change also eliminated the need * to preinitialize the context struct to zero. * - Removed some totally unused constants. */ #ifndef _AES_H #define _AES_H #if defined(__linux__) && defined(__KERNEL__) # include #else # include #endif // CONFIGURATION OPTIONS (see also aes.c) // // Define AES_BLOCK_SIZE to set the cipher block size (16, 24 or 32) or // leave this undefined for dynamically variable block size (this will // result in much slower code). // IMPORTANT NOTE: AES_BLOCK_SIZE is in BYTES (16, 24, 32 or undefined). If // left undefined a slower version providing variable block length is compiled #ifndef AES_BLOCK_SIZE #define AES_BLOCK_SIZE 16 #endif // The number of key schedule words for different block and key lengths // allowing for method of computation which requires the length to be a // multiple of the key length // // Nk = 4 6 8 // ------------- // Nb = 4 | 60 60 64 // 6 | 96 90 96 // 8 | 120 120 120 #define AES_KS_LENGTH (4 * AES_BLOCK_SIZE) #define AES_RC_LENGTH ((9 * AES_BLOCK_SIZE) / 8 - 8) typedef struct { u_int32_t aes_Nkey; // the number of words in the key input block u_int32_t aes_Nrnd; // the number of cipher rounds u_int32_t aes_e_key[AES_KS_LENGTH]; // the encryption key schedule u_int32_t aes_d_key[AES_KS_LENGTH]; // the decryption key schedule } aes_context; // THE CIPHER INTERFACE extern void aes_set_key(aes_context *, const unsigned char [], const int, const int); extern void aes_encrypt(const aes_context *, const unsigned char [], unsigned char []); extern void aes_decrypt(const aes_context *, const unsigned char [], unsigned char []); // The block length inputs to aes_set_block and aes_set_key are in numbers // of bytes or bits. The calls to subroutines must be made in the above // order but multiple calls can be made without repeating earlier calls // if their parameters have not changed. #endif // _AES_H libreswan-3.32/linux/include/klips-crypto/aes_cbc.h000066400000000000000000000003531365625662500224220ustar00rootroot00000000000000/* Glue header */ #include "aes.h" int AES_set_key(aes_context *aes_ctx, const u_int8_t * key, int keysize); int AES_cbc_encrypt(aes_context *ctx, const u_int8_t * in, u_int8_t * out, int ilen, const u_int8_t * iv, int encrypt); libreswan-3.32/linux/include/klips-crypto/aes_xcbc_mac.h000066400000000000000000000006111365625662500234270ustar00rootroot00000000000000#ifndef _AES_XCBC_MAC_H #define _AES_XCBC_MAC_H typedef u_int32_t aes_block[4]; typedef struct { aes_context ctx_k1; aes_block k2; aes_block k3; } aes_context_mac; int AES_xcbc_mac_set_key(aes_context_mac *ctxm, const u_int8_t *key, int keylen); int AES_xcbc_mac_hash(const aes_context_mac *ctxm, const u_int8_t * in, int ilen, u_int8_t hash[16]); #endif /* _AES_XCBC_MAC_H */ libreswan-3.32/linux/include/klips-crypto/cbc_generic.h000066400000000000000000000072421365625662500232720ustar00rootroot00000000000000#ifndef _CBC_GENERIC_H #define _CBC_GENERIC_H /* * CBC macro helpers * * Author: JuanJo Ciarlante * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ /* * Heavily inspired in loop_AES */ #define CBC_IMPL_BLK16(name, ctx_type, addr_type, enc_func, dec_func) \ int name(ctx_type * ctx, const u_int8_t * in, u_int8_t * out, int ilen, \ const u_int8_t * iv, int encrypt) { \ int ret = ilen, pos; \ const u_int32_t *iv_i; \ if ((ilen) % 16) \ return 0; \ if (encrypt) { \ pos = 0; \ while (pos < ilen) { \ if (pos == 0) \ iv_i = (const u_int32_t*) iv; \ else \ iv_i = (const u_int32_t*) (out - 16); \ *((u_int32_t *)(&out[ 0])) = iv_i[0] ^ \ *((const u_int32_t \ *)(&in[ 0])); \ *((u_int32_t *)(&out[ 4])) = iv_i[1] ^ \ *((const u_int32_t \ *)(&in[ 4])); \ *((u_int32_t *)(&out[ 8])) = iv_i[2] ^ \ *((const u_int32_t \ *)(&in[ 8])); \ *((u_int32_t *)(&out[12])) = iv_i[3] ^ \ *((const u_int32_t \ *)(&in[12])); \ enc_func(ctx, (addr_type) out, \ (addr_type) out); \ in += 16; \ out += 16; \ pos += 16; \ } \ } else { \ pos = ilen - 16; \ in += pos; \ out += pos; \ while (pos >= 0) { \ dec_func(ctx, (const addr_type) in, \ (addr_type) out); \ if (pos == 0) \ iv_i = (const u_int32_t*) (iv); \ else \ iv_i = (const u_int32_t*) (in - 16); \ *((u_int32_t *)(&out[ 0])) ^= iv_i[0]; \ *((u_int32_t *)(&out[ 4])) ^= iv_i[1]; \ *((u_int32_t *)(&out[ 8])) ^= iv_i[2]; \ *((u_int32_t *)(&out[12])) ^= iv_i[3]; \ in -= 16; \ out -= 16; \ pos -= 16; \ } \ } \ return ret; \ } #define CBC_IMPL_BLK8(name, ctx_type, addr_type, enc_func, dec_func) \ int name(ctx_type * ctx, u_int8_t * in, u_int8_t * out, int ilen, \ const u_int8_t * iv, int encrypt) { \ int ret = ilen, pos; \ const u_int32_t *iv_i; \ if ((ilen) % 8) \ return 0; \ if (encrypt) { \ pos = 0; \ while (pos < ilen) { \ if (pos == 0) \ iv_i = (const u_int32_t*) iv; \ else \ iv_i = (const u_int32_t*) (out - 8); \ *((u_int32_t *)(&out[ 0])) = iv_i[0] ^ \ *((const u_int32_t \ *)(&in[ 0])); \ *((u_int32_t *)(&out[ 4])) = iv_i[1] ^ \ *((const u_int32_t \ *)(&in[ 4])); \ enc_func(ctx, (addr_type)out, (addr_type)out); \ in += 8; \ out += 8; \ pos += 8; \ } \ } else { \ pos = ilen - 8; \ in += pos; \ out += pos; \ while (pos >= 0) { \ dec_func(ctx, (const addr_type)in, \ (addr_type)out); \ if (pos == 0) \ iv_i = (const u_int32_t*) (iv); \ else \ iv_i = (const u_int32_t*) (in - 8); \ *((u_int32_t *)(&out[ 0])) ^= iv_i[0]; \ *((u_int32_t *)(&out[ 4])) ^= iv_i[1]; \ in -= 8; \ out -= 8; \ pos -= 8; \ } \ } \ return ret; \ } #define CBC_DECL(name, ctx_type) \ int name(ctx_type * ctx, u_int8_t * in, u_int8_t * out, int ilen, \ const u_int8_t * iv, int encrypt) /* Eg.: CBC_IMPL_BLK16(AES_cbc_encrypt, aes_context, u_int8_t *, aes_encrypt, aes_decrypt); CBC_DECL(AES_cbc_encrypt, aes_context); */ #endif /* _CBC_GENERIC_H */ libreswan-3.32/linux/include/klips-crypto/des.h000066400000000000000000000261531365625662500216240ustar00rootroot00000000000000/* crypto/des/des.org */ /* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@cryptsoft.com). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are adhered to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@cryptsoft.com). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * 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 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@cryptsoft.com)" * The word 'cryptographic' can be left out if the routines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ /* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING * * Always modify des.org since des.h is automatically generated from * it during SSLeay configuration. * * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING */ #ifndef HEADER_DES_H #define HEADER_DES_H #ifdef __cplusplus extern "C" { #endif /* If this is set to 'unsigned int' on a DEC Alpha, this gives about a * %20 speed up (longs are 8 bytes, int's are 4). */ /* Must be unsigned int on ia64/Itanium or DES breaks badly */ #ifdef __KERNEL__ #include #else #include #endif #ifndef DES_LONG #define DES_LONG u_int32_t #endif typedef unsigned char des_cblock[8]; typedef struct { des_cblock ks; } des_key_schedule[16]; #define DES_KEY_SZ (sizeof(des_cblock)) #define DES_SCHEDULE_SZ (sizeof(des_key_schedule)) #define DES_ENCRYPT 1 #define DES_DECRYPT 0 #define DES_CBC_MODE 0 #define DES_PCBC_MODE 1 #define des_ecb2_encrypt(i, o, k1, k2, e) \ des_ecb3_encrypt((i), (o), (k1), (k2), (k1), (e)) #define des_ede2_cbc_encrypt(i, o, l, k1, k2, iv, e) \ des_ede3_cbc_encrypt((i), (o), (l), (k1), (k2), (k1), (iv), (e)) #define des_ede2_cfb64_encrypt(i, o, l, k1, k2, iv, n, e) \ des_ede3_cfb64_encrypt((i), (o), (l), (k1), (k2), (k1), (iv), (n), (e)) #define des_ede2_ofb64_encrypt(i, o, l, k1, k2, iv, n) \ des_ede3_ofb64_encrypt((i), (o), (l), (k1), (k2), (k1), (iv), (n)) #define C_Block des_cblock #define Key_schedule des_key_schedule #ifdef KERBEROS #define ENCRYPT DES_ENCRYPT #define DECRYPT DES_DECRYPT #endif #define KEY_SZ DES_KEY_SZ #define string_to_key des_string_to_key #define read_pw_string des_read_pw_string #define random_key des_random_key #define pcbc_encrypt des_pcbc_encrypt #define set_key des_set_key #define key_sched des_key_sched #define ecb_encrypt des_ecb_encrypt #define cbc_encrypt des_cbc_encrypt #define ncbc_encrypt des_ncbc_encrypt #define xcbc_encrypt des_xcbc_encrypt #define cbc_cksum des_cbc_cksum #define quad_cksum des_quad_cksum /* For compatibility with the MIT lib - eay 20/05/92 */ typedef des_key_schedule bit_64; #define des_fixup_key_parity des_set_odd_parity #define des_check_key_parity check_parity extern int des_check_key; /* defaults to false */ extern int des_rw_mode; /* defaults to DES_PCBC_MODE */ /* The next line is used to disable full ANSI prototypes, if your * compiler has problems with the prototypes, make sure this line always * evaluates to true :-) */ #if defined(MSDOS) || defined(__STDC__) #undef NOPROTO #endif #ifndef NOPROTO char *des_options(void); void des_ecb3_encrypt(des_cblock *input, des_cblock *output, des_key_schedule ks1, des_key_schedule ks2, des_key_schedule ks3, int enc); DES_LONG des_cbc_cksum(des_cblock *input, des_cblock *output, long length, des_key_schedule schedule, des_cblock *ivec); void des_cbc_encrypt(des_cblock *input, des_cblock *output, long length, des_key_schedule schedule, des_cblock *ivec, int enc); void des_ncbc_encrypt(des_cblock *input, des_cblock *output, long length, des_key_schedule schedule, des_cblock *ivec, int enc); void des_xcbc_encrypt(des_cblock *input, des_cblock *output, long length, des_key_schedule schedule, des_cblock *ivec, des_cblock *inw, des_cblock *outw, int enc); void des_cfb_encrypt(unsigned char *in, unsigned char *out, int numbits, long length, des_key_schedule schedule, des_cblock *ivec, int enc); void des_ecb_encrypt(des_cblock *input, des_cblock *output, des_key_schedule ks, int enc); void des_encrypt(DES_LONG *data, des_key_schedule ks, int enc); void des_encrypt2(DES_LONG *data, des_key_schedule ks, int enc); void des_encrypt3(DES_LONG *data, des_key_schedule ks1, des_key_schedule ks2, des_key_schedule ks3); void des_decrypt3(DES_LONG *data, des_key_schedule ks1, des_key_schedule ks2, des_key_schedule ks3); void des_ede3_cbc_encrypt(des_cblock *input, des_cblock *output, long length, des_key_schedule ks1, des_key_schedule ks2, des_key_schedule ks3, des_cblock *ivec, int enc); void des_ede3_cfb64_encrypt(unsigned char *in, unsigned char *out, long length, des_key_schedule ks1, des_key_schedule ks2, des_key_schedule ks3, des_cblock *ivec, int *num, int enc); void des_ede3_ofb64_encrypt(unsigned char *in, unsigned char *out, long length, des_key_schedule ks1, des_key_schedule ks2, des_key_schedule ks3, des_cblock *ivec, int *num); void des_xwhite_in2out(des_cblock (*des_key), des_cblock (*in_white), des_cblock (*out_white)); int des_enc_read(int fd, char *buf, int len, des_key_schedule sched, des_cblock *iv); int des_enc_write(int fd, char *buf, int len, des_key_schedule sched, des_cblock *iv); char *des_fcrypt(const char *buf, const char *salt, char *ret); void des_ofb_encrypt(unsigned char *in, unsigned char *out, int numbits, long length, des_key_schedule schedule, des_cblock *ivec); void des_pcbc_encrypt(des_cblock *input, des_cblock *output, long length, des_key_schedule schedule, des_cblock *ivec, int enc); DES_LONG des_quad_cksum(des_cblock *input, des_cblock *output, long length, int out_count, des_cblock *seed); void des_random_seed(des_cblock key); void des_random_key(des_cblock ret); int des_read_password(des_cblock *key, char *prompt, int verify); int des_read_2passwords(des_cblock *key1, des_cblock *key2, char *prompt, int verify); int des_read_pw_string(char *buf, int length, char *prompt, int verify); void des_set_odd_parity(des_cblock *key); int des_is_weak_key(des_cblock *key); int des_set_key(des_cblock *key, des_key_schedule schedule); int des_key_sched(des_cblock *key, des_key_schedule schedule); void des_string_to_key(char *str, des_cblock *key); void des_string_to_2keys(char *str, des_cblock *key1, des_cblock *key2); void des_cfb64_encrypt(unsigned char *in, unsigned char *out, long length, des_key_schedule schedule, des_cblock *ivec, int *num, int enc); void des_ofb64_encrypt(unsigned char *in, unsigned char *out, long length, des_key_schedule schedule, des_cblock *ivec, int *num); int des_read_pw(char *buf, char *buff, int size, char *prompt, int verify); /* Extra functions from Mark Murray */ /* The following functions are not in the normal unix build or the * SSLeay build. When using the SSLeay build, use RAND_seed() * and RAND_bytes() instead. */ int des_new_random_key(des_cblock *key); void des_init_random_number_generator(des_cblock *key); void des_set_random_generator_seed(des_cblock *key); void des_set_sequence_number(des_cblock new_sequence_number); void des_generate_random_block(des_cblock *block); #else char *des_options(); void des_ecb3_encrypt(); DES_LONG des_cbc_cksum(); void des_cbc_encrypt(); void des_ncbc_encrypt(); void des_xcbc_encrypt(); void des_cfb_encrypt(); void des_ede3_cfb64_encrypt(); void des_ede3_ofb64_encrypt(); void des_ecb_encrypt(); void des_encrypt(); void des_encrypt2(); void des_encrypt3(); void des_decrypt3(); void des_ede3_cbc_encrypt(); int des_enc_read(); int des_enc_write(); char *des_fcrypt(); #ifdef PERL5 char *des_crypt(); #else char *crypt(); #endif void des_ofb_encrypt(); void des_pcbc_encrypt(); DES_LONG des_quad_cksum(); void des_random_seed(); void des_random_key(); int des_read_password(); int des_read_2passwords(); int des_read_pw_string(); void des_set_odd_parity(); int des_is_weak_key(); int des_set_key(); int des_key_sched(); void des_string_to_key(); void des_string_to_2keys(); void des_cfb64_encrypt(); void des_ofb64_encrypt(); int des_read_pw(); void des_xwhite_in2out(); /* Extra functions from Mark Murray */ /* The following functions are not in the normal unix build or the * SSLeay build. When using the SSLeay build, use RAND_seed() * and RAND_bytes() instead. */ #ifdef FreeBSD int des_new_random_key(); void des_init_random_number_generator(); void des_set_random_generator_seed(); void des_set_sequence_number(); void des_generate_random_block(); #endif #endif #ifdef __cplusplus } #endif #endif libreswan-3.32/linux/include/libreswan.h000066400000000000000000000344571365625662500204050ustar00rootroot00000000000000/* * header file for Libreswan library functions * Copyright (C) 1998, 1999, 2000 Henry Spencer. * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. * */ #ifndef _LIBRESWAN_H #define _LIBRESWAN_H /* seen it, no need to see it again */ #include "err.h" /* * Libreswan was written before was standardized. * We continue to use TRUE and FALSE because we think that they are clearer * than true or false. */ #ifndef __KERNEL__ # include /* for 'bool' */ #endif #ifndef TRUE # define TRUE true #endif #ifndef FALSE # define FALSE false #endif #include /* Some constants code likes to use. Useful? */ enum { secs_per_minute = 60, secs_per_hour = 60 * secs_per_minute, secs_per_day = 24 * secs_per_hour }; /* * When using uclibc, malloc(0) returns NULL instead of success. This is * to make it use the inbuilt work-around. * See: http://osdir.com/ml/network.freeswan.devel/2003-11/msg00009.html */ #ifdef __UCLIBC__ # if !defined(__MALLOC_GLIBC_COMPAT__) && !defined(MALLOC_GLIBC_COMPAT) # warning Please compile uclibc with GLIBC_COMPATIBILITY defined # endif #endif /* * We've just got to have some datatypes defined... And annoyingly, just * where we get them depends on whether we're in userland or not. */ /* things that need to come from one place or the other, depending */ #if defined(__KERNEL__) #include #include #include #include #include #include #include #include #define user_assert(foo) { } /* nothing */ #else /* NOT in (linux) kernel */ #include #include #include #include #include #define user_assert(foo) assert(foo) #include #include #endif /* (linux) kernel */ #define DEBUG_NO_STATIC static #ifndef IPPROTO_COMP # define IPPROTO_COMP 108 #endif /* !IPPROTO_COMP */ #ifndef IPPROTO_INT # define IPPROTO_INT 61 #endif /* !IPPROTO_INT */ #if !defined(ESPINUDP_WITH_NON_IKE) #define ESPINUDP_WITH_NON_IKE 1 /* draft-ietf-ipsec-nat-t-ike-00/01 */ #define ESPINUDP_WITH_NON_ESP 2 /* draft-ietf-ipsec-nat-t-ike-02 */ #endif #include "ip_address.h" #ifdef NEED_SIN_LEN #define SET_V4(a) { (a).u.v4.sin_family = AF_INET; (a).u.v4.sin_len = sizeof(struct sockaddr_in); } #define SET_V6(a) { (a).u.v6.sin6_family = AF_INET6; (a).u.v6.sin6_len = sizeof(struct sockaddr_in6); } #else #define SET_V4(a) { (a).u.v4.sin_family = AF_INET; } #define SET_V6(a) { (a).u.v6.sin6_family = AF_INET6; } #endif /* then the main types */ typedef struct { ip_address addr; int maskbits; } ip_subnet; typedef struct { ip_address start; ip_address end; } ip_range; /* for use in KLIPS. Userland should use addrtypeof() */ #define ip_address_family(a) ((a)->u.v4.sin_family) /* * ip_address_eq: test two ip_address values for equality. * * For use in KLIPS. Userland should use sameaddr(). */ #define ip_address_eq(a, b) \ (ip_address_family((a)) == ip_address_family((b)) && \ (ip_address_family((a)) == AF_INET ? \ ((a)->u.v4.sin_addr.s_addr == (b)->u.v4.sin_addr.s_addr) : \ (0 == memcmp((a)->u.v6.sin6_addr.s6_addr32, \ (b)->u.v6.sin6_addr.s6_addr32, sizeof(u_int32_t) * 4)) \ )) /* For use in KLIPS. Userland should use isanyaddr() */ #define ip_address_isany(a) \ (ip_address_family((a)) == AF_INET6 ? \ ((a)->u.v6.sin6_addr.s6_addr[0] == 0 && \ (a)->u.v6.sin6_addr.s6_addr[1] == 0 && \ (a)->u.v6.sin6_addr.s6_addr[2] == 0 && \ (a)->u.v6.sin6_addr.s6_addr[3] == 0) : \ ((a)->u.v4.sin_addr.s_addr == 0)) /* and the SA ID stuff */ #ifdef __KERNEL__ typedef __u32 ipsec_spi_t; #else typedef u_int32_t ipsec_spi_t; #endif typedef struct { /* to identify an SA, we need: */ ip_address dst; /* A. destination host */ ipsec_spi_t spi; /* B. 32-bit SPI, assigned by dest. host */ # define SPI_PASS 256 /* magic values... */ # define SPI_DROP 257 /* ...for use... */ # define SPI_REJECT 258 /* ...with SA_INT */ # define SPI_HOLD 259 # define SPI_TRAP 260 # define SPI_TRAPSUBNET 261 int proto; /* C. protocol */ # define SA_ESP 50 /* IPPROTO_ESP */ # define SA_AH 51 /* IPPROTO_AH */ # define SA_IPIP 4 /* IPPROTO_IPIP */ # define SA_COMP 108 /* IPPROTO_COMP */ # define SA_INT 61 /* IANA reserved for internal use */ } ip_said; /* misc */ struct prng { /* pseudo-random-number-generator guts */ unsigned char sbox[256]; int i, j; unsigned long count; }; /* * definitions for user space, taken linux/include/libreswan/ipsec_sa.h */ typedef uint32_t IPsecSAref_t; /* Translation to/from nfmark. * * use bits 16-31. Leave bit 32 as a indicate that IPsec processing * has already been done. */ #define IPSEC_SA_REF_TABLE_IDX_WIDTH 15 #define IPSEC_SA_REF_TABLE_OFFSET 16 #define IPSEC_SA_REF_MASK ((1u << IPSEC_SA_REF_TABLE_IDX_WIDTH) - 1u) #define IPSEC_NFMARK_IS_SAREF_BIT 0x80000000u #define IPsecSAref2NFmark(x) \ (((x) & IPSEC_SA_REF_MASK) << IPSEC_SA_REF_TABLE_OFFSET) #define NFmark2IPsecSAref(x) \ (((x) >> IPSEC_SA_REF_TABLE_OFFSET) & IPSEC_SA_REF_MASK) #define IPSEC_SAREF_NULL ((IPsecSAref_t)0u) /* Not representable as an nfmark */ #define IPSEC_SAREF_NA ((IPsecSAref_t)0xffff0001) #include "lswcdefs.h" /* * function to log stuff from libraries that may be used in multiple * places. */ typedef int (*libreswan_keying_debug_func_t)(const char *message, ...) PRINTF_LIKE(1); /* * new IPv6-compatible functions */ /* text conversions */ extern err_t ttoul(const char *src, size_t srclen, int format, unsigned long *dst); extern err_t ttoulb(const char *src, size_t srclen, int format, unsigned long upb, unsigned long *dst); extern size_t ultot(unsigned long src, int format, char *buf, size_t buflen); #define ULTOT_BUF (22 + 1) /* holds 64 bits in octal */ /* looks up names in DNS */ extern err_t ttoaddr(const char *src, size_t srclen, int af, ip_address *dst); /* does not look up names in DNS */ extern err_t ttoaddr_num(const char *src, size_t srclen, int af, ip_address *dst); extern err_t tnatoaddr(const char *src, size_t srclen, int af, ip_address *dst); extern size_t addrtot(const ip_address *src, int format, char *buf, size_t buflen); extern size_t inet_addrtot(int type, const void *src, int format, char *buf, size_t buflen); extern size_t sin_addrtot(const void *sin, int format, char *dst, size_t dstlen); extern err_t ttorange(const char *src, size_t srclen, int af, ip_range *dst, bool non_zero); extern size_t rangetot(const ip_range *src, char format, char *dst, size_t dstlen); #define RANGETOT_BUF (ADDRTOT_BUF * 2 + 1) extern err_t ttosubnet(const char *src, size_t srclen, int af, ip_subnet *dst); extern size_t subnettot(const ip_subnet *src, int format, char *buf, size_t buflen); #define SUBNETTOT_BUF (ADDRTOT_BUF + 1 + 3) extern size_t subnetporttot(const ip_subnet *src, int format, char *buf, size_t buflen); #define SUBNETPROTOTOT_BUF (SUBNETTOTO_BUF + ULTOT_BUF) extern err_t ttosa(const char *src, size_t srclen, ip_said *dst); extern size_t satot(const ip_said *src, int format, char *bufptr, size_t buflen); #define SATOT_BUF (5 + ULTOT_BUF + 1 + ADDRTOT_BUF) #define SAMIGTOT_BUF (16 + SATOT_BUF + ADDRTOT_BUF) extern err_t ttodata(const char *src, size_t srclen, int base, char *buf, size_t buflen, size_t *needed); extern err_t ttodatav(const char *src, size_t srclen, int base, char *buf, size_t buflen, size_t *needed, char *errp, size_t errlen, unsigned int flags); #define TTODATAV_BUF 40 /* ttodatav's largest non-literal message */ #define TTODATAV_IGNORESPACE (1 << 1) /* ignore spaces in base64 encodings */ #define TTODATAV_SPACECOUNTS 0 /* do not ignore spaces in base64 */ extern size_t datatot(const unsigned char *src, size_t srclen, int format, char *buf, size_t buflen); extern size_t keyblobtoid(const unsigned char *src, size_t srclen, char *dst, size_t dstlen); extern size_t splitkeytoid(const unsigned char *e, size_t elen, const unsigned char *m, size_t mlen, char *dst, size_t dstlen); #define KEYID_BUF 10 /* up to 9 text digits plus NUL */ extern err_t ttoprotoport(char *src, size_t src_len, u_int8_t *proto, u_int16_t *port, bool *has_port_wildcard); /* initializations */ extern void initsaid(const ip_address *addr, ipsec_spi_t spi, int proto, ip_said *dst); extern err_t loopbackaddr(int af, ip_address *dst); extern err_t unspecaddr(int af, ip_address *dst); extern err_t anyaddr(int af, ip_address *dst); extern err_t initaddr(const unsigned char *src, size_t srclen, int af, ip_address *dst); extern err_t add_port(int af, ip_address *addr, unsigned short port); extern err_t initsubnet(const ip_address *addr, int maskbits, int clash, ip_subnet *dst); extern err_t addrtosubnet(const ip_address *addr, ip_subnet *dst); /* misc. conversions and related */ extern err_t rangetosubnet(const ip_address *from, const ip_address *to, ip_subnet *dst); extern int addrtypeof(const ip_address *src); extern int subnettypeof(const ip_subnet *src); extern size_t addrlenof(const ip_address *src); extern size_t addrbytesptr_read(const ip_address *src, const unsigned char **dst); extern size_t addrbytesptr_write(ip_address *src, unsigned char **dst); extern size_t addrbytesof(const ip_address *src, unsigned char *dst, size_t dstlen); extern int masktocount(const ip_address *src); extern void networkof(const ip_subnet *src, ip_address *dst); extern void maskof(const ip_subnet *src, ip_address *dst); /* tests */ extern bool sameaddr(const ip_address *a, const ip_address *b); extern int addrcmp(const ip_address *a, const ip_address *b); extern bool samesubnet(const ip_subnet *a, const ip_subnet *b); extern bool addrinsubnet(const ip_address *a, const ip_subnet *s); extern bool subnetinsubnet(const ip_subnet *a, const ip_subnet *b); extern bool subnetishost(const ip_subnet *s); extern bool samesaid(const ip_said *a, const ip_said *b); extern bool sameaddrtype(const ip_address *a, const ip_address *b); extern bool samesubnettype(const ip_subnet *a, const ip_subnet *b); extern int isanyaddr(const ip_address *src); extern int isunspecaddr(const ip_address *src); extern int isloopbackaddr(const ip_address *src); /* PRNG */ extern void prng_init(struct prng *prng, const unsigned char *key, size_t keylen); extern void prng_bytes(struct prng *prng, unsigned char *dst, size_t dstlen); extern unsigned long prng_count(struct prng *prng); extern void prng_final(struct prng *prng); /* odds and ends */ extern const char *ipsec_version_code(void); extern const char *ipsec_version_vendorid(void); extern const char *ipsec_version_string(void); #ifndef __KERNEL__ extern const char libreswan_vendorid[]; #endif /* * obsolete functions, to be deleted eventually */ /* Internet addresses */ /* obsolete (replaced by addrtot) but still in use */ extern size_t /* space needed for full conversion */ addrtoa(struct in_addr addr, int format, /* character; 0 means default */ char *dst, size_t dstlen ); #define ADDRTOA_BUF ADDRTOT_BUF /* subnets */ /* obsolete (replaced by subnettot) but still in use */ extern size_t /* space needed for full conversion */ subnettoa(struct in_addr addr, struct in_addr mask, int format, /* character; 0 means default */ char *dst, size_t dstlen ); /* obsolete (replaced by subnettot) but still in use; no manpage */ extern size_t /* space needed for full conversion */ subnet6toa(struct in6_addr *addr, struct in6_addr *mask, int format, /* character; 0 means default */ char *dst, size_t dstlen ); #define SUBNETTOA_BUF SUBNETTOT_BUF /* large enough for worst case result */ /* end of obsolete functions */ /* data types for SA conversion functions */ /* part extraction and special addresses */ extern struct in_addr subnetof(struct in_addr addr, struct in_addr mask ); extern struct in_addr hostof(struct in_addr addr, struct in_addr mask ); extern struct in_addr broadcastof(struct in_addr addr, struct in_addr mask ); /* mask handling */ extern int goodmask(struct in_addr mask); extern int masktobits(struct in_addr mask); extern int mask6tobits(struct in6_addr *mask); extern struct in_addr bitstomask(int n); extern struct in6_addr bitstomask6(int n); /* * ENUM of klips debugging values. Not currently used in klips. * debug flag is actually 32 -bits, but only one bit is ever used, * so we can actually pack it all into a single 32-bit word. */ enum klips_debug_flags { KDF_VERBOSE = 0, KDF_XMIT = 1, KDF_NETLINK = 2, /* obsolete */ KDF_XFORM = 3, KDF_EROUTE = 4, KDF_SPI = 5, KDF_RADIJ = 6, KDF_ESP = 7, KDF_AH = 8, /* obsolete */ KDF_RCV = 9, KDF_TUNNEL = 10, KDF_PFKEY = 11, KDF_COMP = 12, KDF_NATT = 13, }; /* * pluto and lwdnsq need to know the maximum size of the commands to, * and replies from lwdnsq. */ #define LWDNSQ_CMDBUF_LEN 1024 #define LWDNSQ_RESULT_LEN_MAX 4096 /* syntax for passthrough SA */ #ifndef PASSTHROUGHNAME #define PASSTHROUGHNAME "%passthrough" #define PASSTHROUGH4NAME "%passthrough4" #define PASSTHROUGH6NAME "%passthrough6" #define PASSTHROUGHIS "tun0@0.0.0.0" #define PASSTHROUGH4IS "tun0@0.0.0.0" #define PASSTHROUGH6IS "tun0@::" #define PASSTHROUGHTYPE "tun" #define PASSTHROUGHSPI 0 #define PASSTHROUGHDST 0 #endif #endif /* _LIBRESWAN_H */ libreswan-3.32/linux/include/libreswan/000077500000000000000000000000001365625662500202175ustar00rootroot00000000000000libreswan-3.32/linux/include/libreswan/ipcomp.h000066400000000000000000000036251365625662500216650ustar00rootroot00000000000000/* * IPCOMP zlib interface code. * Copyright (C) 2000 Svenning Soerensen * Copyright (C) 2000, 2001 Richard Guy Briggs * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ /* SSS */ #ifndef _IPCOMP_H #define _IPCOMP_H /* Prefix all global deflate symbols with "ipcomp_" to avoid collisions with ppp_deflate & ext2comp */ #ifndef IPCOMP_PREFIX #define IPCOMP_PREFIX #endif /* IPCOMP_PREFIX */ #ifndef IPPROTO_COMP #define IPPROTO_COMP 108 #endif /* IPPROTO_COMP */ #include "libreswan/ipsec_sysctl.h" struct ipcomphdr { /* IPCOMP header */ __u8 ipcomp_nh; /* Next header (protocol) */ __u8 ipcomp_flags; /* Reserved, must be 0 */ __u16 ipcomp_cpi; /* Compression Parameter Index */ }; extern struct inet_protocol comp_protocol; #define IPCOMP_UNCOMPRESSABLE 0x000000001 #define IPCOMP_COMPRESSIONERROR 0x000000002 #define IPCOMP_PARMERROR 0x000000004 #define IPCOMP_DECOMPRESSIONERROR 0x000000008 #define IPCOMP_ADAPT_INITIAL_TRIES 8 #define IPCOMP_ADAPT_INITIAL_SKIP 4 #define IPCOMP_ADAPT_SUBSEQ_TRIES 2 #define IPCOMP_ADAPT_SUBSEQ_SKIP 8 /* Function prototypes */ struct sk_buff *skb_compress(struct sk_buff *skb, struct ipsec_sa *ips, unsigned int *flags); struct sk_buff *skb_decompress(struct sk_buff *skb, struct ipsec_sa *ips, unsigned int *flags); #endif /* _IPCOMP_H */ libreswan-3.32/linux/include/libreswan/ipsec_ah.h000066400000000000000000000032621365625662500221460ustar00rootroot00000000000000/* * Authentication Header declarations * Copyright (C) 1996, 1997 John Ioannidis. * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include "ipsec_md5h.h" #include "ipsec_sha1.h" #ifndef IPPROTO_AH #define IPPROTO_AH 51 #endif /* IPPROTO_AH */ #include "ipsec_auth.h" #ifdef __KERNEL__ #ifndef CONFIG_XFRM_ALTERNATE_STACK extern struct inet_protocol ah_protocol; #endif /* CONFIG_XFRM_ALTERNATE_STACK */ struct options; struct ahhdr /* Generic AH header */ { __u8 ah_nh; /* Next header (protocol) */ __u8 ah_hl; /* AH length, in 32-bit words */ __u16 ah_rv; /* reserved, must be 0 */ __u32 ah_spi; /* Security Parameters Index */ __u32 ah_rpl; /* Replay prevention */ __u8 ah_data[AHHMAC_HASHLEN]; /* Authentication hash */ }; #define AH_BASIC_LEN 8 /* basic AH header is 8 bytes, nh,hl,rv,spi * and the ah_hl, says how many bytes after that * to cover. */ extern struct xform_functions ah_xform_funcs[]; #include "libreswan/ipsec_sysctl.h" #endif /* __KERNEL__ */ libreswan-3.32/linux/include/libreswan/ipsec_alg.h000066400000000000000000000216371365625662500223270ustar00rootroot00000000000000/* * Modular extensions service and registration functions interface * * Author: JuanJo Ciarlante * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #ifndef IPSEC_ALG_H #define IPSEC_ALG_H /* * gcc >= 3.2 has removed __FUNCTION__, replaced by C99 __func__ * *BUT* its a compiler variable. */ #if (__GNUC__ >= 3) #ifndef __FUNCTION__ #define __FUNCTION__ __func__ #endif #endif /* Version 0.8.1-0 */ #define IPSEC_ALG_VERSION 0x00080100 #include #include #include #include /* * The following structs are used via pointers in ipsec_alg object to * avoid ipsec_alg.h coupling with Libreswan headers, thus simplifying * module development */ struct ipsec_sa; struct esp; /************************************** * * Main registration object * *************************************/ #define IPSEC_ALG_VERSION_QUAD(v) \ ((v) >> 24), (((v) >> 16) & 0xff), (((v) >> 8) & 0xff), ((v) & 0xff) /* * Main ipsec_alg objects: "OOPrograming wannabe" * Hierarchy (carefully handled with _minimal_ cast'ing): * * ipsec_alg+ * +->ipsec_alg_enc (ixt_alg_type=SADB_EXT_SUPPORTED_ENCRYPT) * +->ipsec_alg_auth (ixt_alg_type=SADB_EXT_SUPPORTED_AUTH) */ /*************************************************************** * * INTERFACE object: struct ipsec_alg * ***************************************************************/ #define ixt_alg_type ixt_support.ias_exttype #define ixt_alg_id ixt_support.ias_id #define IPSEC_ALG_ST_SUPP 0x01 #define IPSEC_ALG_ST_REGISTERED 0x02 #define IPSEC_ALG_ST_EXCL 0x04 struct ipsec_alg { unsigned ixt_version; /* only allow this version (or 'near')*/ \ struct list_head ixt_list; /* dlinked list */ \ struct module *ixt_module; /* THIS_MODULE */ \ unsigned ixt_state; /* state flags */ \ atomic_t ixt_refcnt; /* ref. count when pointed from ipsec_sa */ \ char ixt_name[16]; /* descriptive short name, eg. "3des" */ \ void *ixt_data; /* private for algo implementation */ \ uint8_t ixt_blocksize; /* blocksize in bytes */ \ struct ipsec_alg_supported ixt_support; }; /* * Note the const in cbc_encrypt IV arg: * some ciphers like to toast passed IV (eg. 3DES): make a local IV copy */ struct ipsec_alg_enc { struct ipsec_alg ixt_common; unsigned ixt_e_keylen; /* raw key length in bytes */ unsigned ixt_e_ctx_size; /* sa_p->key_e_size */ int (*ixt_e_set_key)(struct ipsec_alg_enc *alg, __u8 *key_e, const __u8 *key, size_t keysize); __u8 *(*ixt_e_new_key)(struct ipsec_alg_enc *alg, const __u8 *key, size_t keysize); void (*ixt_e_destroy_key)(struct ipsec_alg_enc *alg, __u8 *key_e); int (*ixt_e_cbc_encrypt)(struct ipsec_alg_enc *alg, __u8 *key_e, __u8 *in, int ilen, __u8 *iv, int encrypt); }; struct ipsec_alg_auth { struct ipsec_alg ixt_common; unsigned ixt_a_keylen; /* raw key length in bytes */ unsigned ixt_a_ctx_size; /* sa_p->key_a_size */ unsigned ixt_a_authlen; /* 'natural' auth. hash len (bytes) */ int (*ixt_a_hmac_set_key)(struct ipsec_alg_auth *alg, __u8 *key_a, const __u8 *key, int keylen); int (*ixt_a_hmac_hash)(struct ipsec_alg_auth *alg, __u8 *key_a, const __u8 *dat, int len, __u8 *hash, int hashlen); __u8 *(*ixt_a_hmac_new_key)(struct ipsec_alg_auth *alg, const __u8 *key, int keylen); void (*ixt_a_destroy_key)(struct ipsec_alg_auth *alg, __u8 *key_a); }; /* * These are _copies_ of SADB_EXT_SUPPORTED_{AUTH,ENCRYPT}, * to avoid header coupling for true constants * about headers ... "cp is your friend" --Linus */ #define IPSEC_ALG_TYPE_AUTH 14 #define IPSEC_ALG_TYPE_ENCRYPT 15 /*************************************************************** * * INTERFACE for module loading, testing, and unloading * ***************************************************************/ /* - registration calls */ int register_ipsec_alg(struct ipsec_alg *); int unregister_ipsec_alg(struct ipsec_alg *); /* - optional (simple test) for algos */ int ipsec_alg_test(unsigned alg_type, unsigned alg_id, int testparm); /* inline wrappers (useful for type validation */ static inline int register_ipsec_alg_enc(struct ipsec_alg_enc *ixt) { return register_ipsec_alg((struct ipsec_alg*)ixt); } static inline int unregister_ipsec_alg_enc(struct ipsec_alg_enc *ixt) { return unregister_ipsec_alg((struct ipsec_alg*)ixt); } static inline int register_ipsec_alg_auth(struct ipsec_alg_auth *ixt) { return register_ipsec_alg((struct ipsec_alg*)ixt); } static inline int unregister_ipsec_alg_auth(struct ipsec_alg_auth *ixt) { return unregister_ipsec_alg((struct ipsec_alg*)ixt); } /***************************************************************** * * INTERFACE for ENC services: key creation, encrypt function * *****************************************************************/ #define IPSEC_ALG_ENCRYPT 1 #define IPSEC_ALG_DECRYPT 0 /* encryption key context creation function */ int ipsec_alg_enc_key_create(struct ipsec_sa *sa_p); /* * ipsec_alg_esp_encrypt(): encrypt ilen bytes in idat returns * 0 or ERR<0 */ int ipsec_alg_esp_encrypt(struct ipsec_sa *sa_p, __u8 *idat, int ilen, __u8 *iv, int action); /*************************************************************** * * INTERFACE for AUTH services: key creation, hash functions * ***************************************************************/ int ipsec_alg_auth_key_create(struct ipsec_sa *sa_p); int ipsec_alg_sa_esp_hash(const struct ipsec_sa *sa_p, const __u8 *espp, int len, __u8 *hash, int hashlen); #define ipsec_alg_sa_esp_update(c, k, l) \ ipsec_alg_sa_esp_hash(c, k, l, NULL, 0) int ipsec_alg_sa_ah_hash(const struct ipsec_sa *sa_p, const __u8 *ahp, int len, __u8 *hash, int hashlen); #define ipsec_alg_sa_ah_update(c, k, l) \ ipsec_alg_sa_ah_hash(c, k, l, NULL, 0) /* only called from ipsec_init.c */ int ipsec_alg_init(void); /* algo module glue for static algos */ void ipsec_alg_static_init(void); typedef int (*ipsec_alg_init_func_t)(void); /********************************************** * * INTERFACE for ipsec_sa init and wipe * **********************************************/ /* returns true if ipsec_sa has ipsec_alg obj attached */ /* * Initializes ipsec_sa's ipsec_alg object, using already loaded * proto, authalg, encalg.; links ipsec_alg objects (enc, auth) */ int ipsec_alg_sa_init(struct ipsec_sa *sa_p); /* * Destroys ipsec_sa's ipsec_alg object * unlinking ipsec_alg objects */ int ipsec_alg_sa_wipe(struct ipsec_sa *sa_p); #define IPSEC_ALG_MODULE_INIT_MOD(func_name ) \ static int func_name(void); \ module_init(func_name); \ static int __init func_name(void) #define IPSEC_ALG_MODULE_EXIT_MOD(func_name ) \ static void func_name(void); \ module_exit(func_name); \ static void __exit func_name(void) #define IPSEC_ALG_MODULE_INIT_STATIC(func_name ) \ extern int func_name(void); \ int func_name(void) #define IPSEC_ALG_MODULE_EXIT_STATIC(func_name ) \ extern void func_name(void); \ void func_name(void) /********************************************** * * 2.2 backport for some 2.4 useful module stuff * **********************************************/ #ifdef MODULE #ifndef THIS_MODULE #define THIS_MODULE (&__this_module) #endif #ifndef module_init typedef int (*__init_module_func_t)(void); typedef void (*__cleanup_module_func_t)(void); #define module_init(x) \ int init_module(void) __attribute__((alias(#x))); \ static inline __init_module_func_t __init_module_inline(void) \ { return x; } #define module_exit(x) \ void cleanup_module(void) __attribute__((alias(#x))); \ static inline __cleanup_module_func_t __cleanup_module_inline(void) \ { return x; } #endif #define IPSEC_ALG_MODULE_INIT(func_name) \ IPSEC_ALG_MODULE_INIT_MOD(func_name) #define IPSEC_ALG_MODULE_EXIT(func_name) \ IPSEC_ALG_MODULE_EXIT_MOD(func_name) #else /* not MODULE */ #ifndef THIS_MODULE #define THIS_MODULE NULL #endif /* * I only want module_init() magic * when algo.c file *is THE MODULE*, in all other * cases, initialization is called explicitely from ipsec_alg_init() */ #define IPSEC_ALG_MODULE_INIT(func_name) \ IPSEC_ALG_MODULE_INIT_STATIC(func_name) #define IPSEC_ALG_MODULE_EXIT(func_name) \ IPSEC_ALG_MODULE_EXIT_STATIC(func_name) #endif #endif /* IPSEC_ALG_H */ libreswan-3.32/linux/include/libreswan/ipsec_alg_3des.h000066400000000000000000000003611365625662500232340ustar00rootroot00000000000000struct TripleDES_context { des_key_schedule s1; des_key_schedule s2; des_key_schedule s3; }; typedef struct TripleDES_context TripleDES_context; #define ESP_3DES_KEY_SZ (3 * sizeof(des_cblock)) #define ESP_3DES_CBC_BLK_LEN 8 libreswan-3.32/linux/include/libreswan/ipsec_auth.h000066400000000000000000000056221365625662500225210ustar00rootroot00000000000000/* * Authentication Header declarations * Copyright (C) 2003 Michael Richardson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include "ipsec_md5h.h" #include "ipsec_sha1.h" #ifndef IPSEC_AUTH_H #define IPSEC_AUTH_H #define AH_FLENGTH 12 /* size of fixed part */ #define AHMD5_KMAX 64 /* MD5 max 512 bits key */ #define AHMD5_AMAX 12 /* MD5 96 bits of authenticator */ #define AHMD596_KLEN 16 /* MD5 128 bits key */ #define AHSHA196_KLEN 20 /* SHA1 160 bits key */ #define AHMD596_ALEN 16 /* MD5 128 bits authentication length */ #define AHSHA196_ALEN 20 /* SHA1 160 bits authentication length */ #define AHMD596_BLKLEN 64 /* MD5 block length */ #define AHSHA196_BLKLEN 64 /* SHA1 block length */ #define AHSHA2_256_BLKLEN 64 /* SHA2-256 block length */ #define AHSHA2_384_BLKLEN 128 /* SHA2-384 block length (?) */ #define AHSHA2_512_BLKLEN 128 /* SHA2-512 block length */ #define AH_BLKLEN_MAX 128 /* keep up to date! */ #define AH_AMAX 64 /* increased for sha2_512 * keep up to date! */ #define AHHMAC_HASHLEN 12 /* authenticator length of 96bits */ #define AHHMAC_RPLLEN 4 /* 32 bit replay counter */ #define DB_AH_PKTRX 0x0001 #define DB_AH_PKTRX2 0x0002 #define DB_AH_DMP 0x0004 #define DB_AH_IPSA 0x0010 #define DB_AH_XF 0x0020 #define DB_AH_INAU 0x0040 #define DB_AH_REPLAY 0x0100 #ifdef __KERNEL__ /* General HMAC algorithm is described in RFC 2104 */ #define HMAC_IPAD 0x36 #define HMAC_OPAD 0x5C struct md5_ctx { MD5_CTX ictx; /* context after H(K XOR ipad) */ MD5_CTX octx; /* context after H(K XOR opad) */ }; struct sha1_ctx { SHA1_CTX ictx; /* context after H(K XOR ipad) */ SHA1_CTX octx; /* context after H(K XOR opad) */ }; struct auth_alg { void (*init)(void *ctx); void (*update)(void *ctx, unsigned char *bytes, __u32 len); void (*final)(unsigned char *hash, void *ctx); int hashlen; }; struct options; #endif /* __KERNEL__ */ #endif /* IPSEC_AUTH_H */ libreswan-3.32/linux/include/libreswan/ipsec_encap.h000066400000000000000000000035541365625662500226500ustar00rootroot00000000000000/* * declarations relevant to encapsulation-like operations * Copyright (C) 1996, 1997 John Ioannidis. * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef _IPSEC_ENCAP_H_ #define SENT_IP4 0x01 /* match OpenBSD for what it's worth */ #define SENT_IP6 0x02 /* match OpenBSD for what it's worth */ struct sockaddr_encap { __u8 sen_len; /* length */ __u8 sen_family; /* AF_ENCAP */ __u16 sen_type; /* see SENT_* */ union { struct /* SENT_IP4 */ { struct in_addr Src; struct in_addr Dst; __u8 Proto; __u16 Sport; __u16 Dport; } Sip4; struct /* SENT_IP6 */ { struct in6_addr Src; struct in6_addr Dst; __u8 Proto; __u16 Sport; __u16 Dport; } Sip6; } Sen; } __attribute__((packed)); #define sen_ip_src Sen.Sip4.Src #define sen_ip_dst Sen.Sip4.Dst #define sen_proto Sen.Sip4.Proto #define sen_sport Sen.Sip4.Sport #define sen_dport Sen.Sip4.Dport #define sen_ip6_src Sen.Sip6.Src #define sen_ip6_dst Sen.Sip6.Dst #define sen_proto6 Sen.Sip6.Proto #define sen_sport6 Sen.Sip6.Sport #define sen_dport6 Sen.Sip6.Dport #ifndef AF_ENCAP #define AF_ENCAP 26 #endif /* AF_ENCAP */ #define _IPSEC_ENCAP_H_ #endif /* _IPSEC_ENCAP_H_ */ libreswan-3.32/linux/include/libreswan/ipsec_eroute.h000066400000000000000000000043641365625662500230650ustar00rootroot00000000000000/* * @(#) declarations of eroute structures * * Copyright (C) 1996, 1997 John Ioannidis. * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs * Copyright (C) 2001 Michael Richardson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * derived from ipsec_encap.h 1.15 on 2001/9/18 by mcr. * */ #ifndef _IPSEC_EROUTE_H_ #include "radij.h" #include "ipsec_encap.h" #include "ipsec_radij.h" /* * The "type" is really part of the address as far as the routing * system is concerned. By using only one bit in the type field * for each type, we sort-of make sure that different types of * encapsulation addresses won't be matched against the wrong type. */ /* * An entry in the radix tree */ struct rjtentry { struct radij_node rd_nodes[2]; /* tree glue, and other values */ #define rd_key(r) ((struct sockaddr_encap *)((r)->rd_nodes->rj_key)) #define rd_mask(r) ((struct sockaddr_encap *)((r)->rd_nodes->rj_mask)) short rd_flags; short rd_count; }; struct ident { __u16 type; /* identity type */ __u64 id; /* identity id */ __u8 len; /* identity len */ caddr_t data; /* identity data */ }; /* * An encapsulation route consists of a pointer to a * radix tree entry and a SAID (a destination_address/SPI/protocol triple). */ struct eroute { struct rjtentry er_rjt; ip_said er_said; uint32_t er_pid; uint32_t er_count; uint64_t er_lasttime; struct sockaddr_encap er_eaddr; /* MCR get rid of _encap, it is silly */ struct sockaddr_encap er_emask; struct ident er_ident_s; struct ident er_ident_d; struct sk_buff *er_first; struct sk_buff *er_last; }; #define er_dst er_said.dst #define er_spi er_said.spi #define _IPSEC_EROUTE_H_ #endif /* _IPSEC_EROUTE_H_ */ libreswan-3.32/linux/include/libreswan/ipsec_errs.h000066400000000000000000000021421365625662500225250ustar00rootroot00000000000000/* * @(#) definition of ipsec_errs structure * * Copyright (C) 2001 Richard Guy Briggs * and Michael Richardson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ /* * This file describes the errors/statistics that Libreswan collects. * */ struct ipsec_errs { __u32 ips_alg_errs; /* number of algorithm errors */ __u32 ips_auth_errs; /* # of authentication errors */ __u32 ips_encsize_errs; /* # of encryption size errors */ __u32 ips_encpad_errs; /* # of encryption pad errors */ __u32 ips_replaywin_errs; /* # of pkt sequence errors */ }; libreswan-3.32/linux/include/libreswan/ipsec_esp.h000066400000000000000000000045241365625662500223470ustar00rootroot00000000000000/* * Copyright (C) 1996, 1997 John Ioannidis. * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include "libreswan/ipsec_md5h.h" #include "libreswan/ipsec_sha1.h" #include "klips-crypto/des.h" #ifndef IPPROTO_ESP #define IPPROTO_ESP 50 #endif /* IPPROTO_ESP */ #define ESP_HEADER_LEN 8 /* 64 bits header (spi+rpl)*/ #define EMT_ESPDESCBC_ULEN 20 /* coming from user mode */ #define EMT_ESPDES_KMAX 64 /* 512 bit secret key enough? */ #define EMT_ESPDES_KEY_SZ 8 /* 56 bit secret key with parity = 64 bits */ #define EMT_ESP3DES_KEY_SZ 24 /* 168 bit secret key with parity = 192 bits */ #define EMT_ESPDES_IV_SZ 8 /* IV size */ #define ESP_DESCBC_BLKLEN 8 /* DES-CBC block size */ #define ESP_IV_MAXSZ 16 /* This is _critical_ */ #define ESP_IV_MAXSZ_INT (ESP_IV_MAXSZ / sizeof(int)) #define DB_ES_PKTRX 0x0001 #define DB_ES_PKTRX2 0x0002 #define DB_ES_IPSA 0x0010 #define DB_ES_XF 0x0020 #define DB_ES_IPAD 0x0040 #define DB_ES_INAU 0x0080 #define DB_ES_OINFO 0x0100 #define DB_ES_OINFO2 0x0200 #define DB_ES_OH 0x0400 #define DB_ES_REPLAY 0x0800 #ifdef __KERNEL__ struct des_eks { des_key_schedule ks; }; #ifndef CONFIG_XFRM_ALTERNATE_STACK extern struct inet_protocol esp_protocol; extern struct inet6_protocol esp6_protocol; #endif /* CONFIG_XFRM_ALTERNATE_STACK */ struct options; struct esphdr { __u32 esp_spi; /* Security Parameters Index */ __u32 esp_rpl; /* Replay counter */ __u8 esp_iv[8]; /* iv */ }; extern struct xform_functions esp_xform_funcs[]; extern enum ipsec_rcv_value ipsec_rcv_esp_post_decrypt( struct ipsec_rcv_state *irs); extern int debug_esp; #endif /* __KERNEL__ */ libreswan-3.32/linux/include/libreswan/ipsec_ipcomp.h000066400000000000000000000040461365625662500230460ustar00rootroot00000000000000/* * IP compression header declations * * Copyright (C) 2003 Michael Richardson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef IPSEC_IPCOMP_H #define IPSEC_IPCOMP_H #include "libreswan/ipsec_auth.h" /* Prefix all global deflate symbols with "ipcomp_" to avoid collisions with ppp_deflate & ext2comp */ #ifndef IPCOMP_PREFIX #define IPCOMP_PREFIX #endif /* IPCOMP_PREFIX */ #ifndef IPPROTO_COMP #define IPPROTO_COMP 108 #endif /* IPPROTO_COMP */ extern int sysctl_ipsec_debug_ipcomp; struct ipcomphdr { /* IPCOMP header */ __u8 ipcomp_nh; /* Next header (protocol) */ __u8 ipcomp_flags; /* Reserved, must be 0 */ __u16 ipcomp_cpi; /* Compression Parameter Index */ }; #ifndef CONFIG_XFRM_ALTERNATE_STACK extern struct inet_protocol comp_protocol; #endif /* CONFIG_XFRM_ALTERNATE_STACK */ extern int sysctl_ipsec_debug_ipcomp; #define IPCOMP_UNCOMPRESSABLE 0x000000001 #define IPCOMP_COMPRESSIONERROR 0x000000002 #define IPCOMP_PARMERROR 0x000000004 #define IPCOMP_DECOMPRESSIONERROR 0x000000008 #define IPCOMP_ADAPT_INITIAL_TRIES 8 #define IPCOMP_ADAPT_INITIAL_SKIP 4 #define IPCOMP_ADAPT_SUBSEQ_TRIES 2 #define IPCOMP_ADAPT_SUBSEQ_SKIP 8 /* Function prototypes */ struct sk_buff *skb_compress(struct sk_buff *skb, struct ipsec_sa *ips, unsigned int *flags); struct sk_buff *skb_decompress(struct sk_buff *skb, struct ipsec_sa *ips, unsigned int *flags); extern struct xform_functions ipcomp_xform_funcs[]; #endif /* IPSEC_IPCOMP_H */ libreswan-3.32/linux/include/libreswan/ipsec_ipe4.h000066400000000000000000000016271365625662500224220ustar00rootroot00000000000000/* * IP-in-IP Header declarations * Copyright (C) 1996, 1997 John Ioannidis. * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ /* The packet header is an IP header! */ struct ipe4_xdata /* transform table data */ { struct in_addr i4_src; struct in_addr i4_dst; }; #define EMT_IPE4_ULEN 8 /* coming from user mode */ libreswan-3.32/linux/include/libreswan/ipsec_ipip.h000066400000000000000000000014711365625662500225170ustar00rootroot00000000000000/* * Copyright (C) 2003 Michael Richardson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef _IPSEC_IPIP_H_ #ifndef IPPROTO_IPIP #define IPPROTO_IPIP 4 #endif /* IPPROTO_ESP */ extern struct xform_functions ipip_xform_funcs[]; #define _IPSEC_IPIP_H_ #endif /* _IPSEC_IPIP_H_ */ libreswan-3.32/linux/include/libreswan/ipsec_kern24.h000066400000000000000000000052331365625662500226630ustar00rootroot00000000000000/* * @(#) routines to makes kernel 2.4 compatible with 2.6 usage. * * Copyright (C) 2004 Michael Richardson * Copyright (C) 2005 - 2008 Paul Wouters * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #ifndef _IPSEC_KERN24_H #include #include static inline void random_ether_addr(u8 *addr) { get_random_bytes(addr, ETH_ALEN); addr[0] &= 0xfe; addr[0] |= 0x02; } #define ip_hdr(skb) ((skb)->nh.iph) #ifdef NET_26 #error \ "ipsec_kern24.h should not be included directly or at all on 2.6 kernels" #endif #define sk_receive_queue receive_queue #define sk_destruct destruct #define sk_reuse reuse #define sk_zapped zapped #define sk_family family #define sk_protocol protocol #define sk_protinfo protinfo #define sk_sleep sleep #define sk_state_change state_change #define sk_shutdown shutdown #define sk_err err #define sk_stamp stamp #define sk_socket socket #define sk_sndbuf sndbuf #define sock_flag(sk, flag) ((sk)->dead) #define sk_for_each(sk, node, plist) \ for ((sk) = *(plist); (sk) != NULL; (sk) = (sk)->next) /* deal with 2.4 vs 2.6 issues with module counts */ /* in 2.6, all refcounts are maintained *outside* of the * module to deal with race conditions. */ #define KLIPS_INC_USE MOD_INC_USE_COUNT #define KLIPS_DEC_USE MOD_DEC_USE_COUNT #ifndef printk_ratelimit extern int printk_ratelimit(void); #endif #include static inline void *skb_header_pointer(const struct sk_buff *skb, int offset, int len, void *buffer) { int hlen = skb_headlen(skb); if (offset + len <= hlen) return skb->data + offset; if (skb_copy_bits(skb, offset, buffer, len) < 0) return NULL; return buffer; } static inline struct ethhdr *eth_hdr(const struct sk_buff *skb) { return (struct ethhdr *)skb_mac_header(skb); } #define _IPSEC_KERN24_H 1 #define proc_create_data(n,m,p,o,a) \ ({ \ struct proc_dir_entry *_p = create_proc_entry((n),(m),(p)); \ if (_p) { \ _p->proc_fops = (o); \ _p->data = (void *) (a); \ } \ (_p); \ }) #endif /* _IPSEC_KERN24_H */ libreswan-3.32/linux/include/libreswan/ipsec_kversion.h000066400000000000000000000454161365625662500234250ustar00rootroot00000000000000#ifndef _LIBRESWAN_KVERSIONS_H /* * header file for Libreswan library functions * Copyright (C) 1998, 1999, 2000 Henry Spencer. * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs * Copyright (C) 2003 - 2011 Paul Wouters * Copyright (C) 2008 - 2011 David McCullough * Copyright (C) 2012-2014 David McCullough * Copyright (C) 2012-2017 Paul Wouters * Copyright (C) 2012 Paul Wouters * Copyright (C) 2015 Greg Ungerer * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. * */ #define _LIBRESWAN_KVERSIONS_H /* seen it, no need to see it again */ /* * this file contains a series of atomic defines that depend upon * kernel version numbers. The kernel versions are arranged * in version-order number (which is often not chronological) * and each clause enables or disables a feature. */ /* * First, assorted kernel-version-dependent trickery. */ #include #ifndef KERNEL_VERSION # define KERNEL_VERSION(x, y, z) (((x) << 16) + ((y) << 8) + (z)) #endif #if __KERNEL__ # if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 0) # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0) # include "libreswan/ipsec_kern24.h" # else # error "kernels before 2.4 are not supported at this time" # endif # else # define KLIPS_INC_USE /* nothing */ # define KLIPS_DEC_USE /* nothing */ # endif #endif /* * We use a lot of config defines, on older kernels that means we * need to include config.h */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38) && \ !defined(AUTOCONF_INCLUDED) # include #endif #if !defined(RHEL_RELEASE_CODE) # define RHEL_RELEASE_CODE 0 # define RHEL_RELEASE_VERSION(x, y) 10 #endif /* these seem debian/ubuntu specific and do not match fedora/rhel kernels */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,10) # define IP_SELECT_IDENT_NEW #elif LINUX_VERSION_CODE < KERNEL_VERSION(3,15,0) && LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,17) # define IP_SELECT_IDENT_NEW #elif LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0) && LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,11) # define IP_SELECT_IDENT_NEW #elif LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0) && LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,0) # define IP_SELECT_IDENT_NEW #elif LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0) && LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,53) # define IP_SELECT_IDENT_NEW #elif LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) && LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,103) # define IP_SELECT_IDENT_NEW #elif LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) && LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,63) # define IP_SELECT_IDENT_NEW #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) # define SK_FOR_EACH(a,c) sk_for_each(a,c) # define ipsec_proc_net_remove(a) remove_proc_entry(a, init_net.proc_net) #else # define SK_FOR_EACH_NEED_NODE # define SK_FOR_EACH(a,c) sk_for_each(a,node,c) # define remove_proc_subtree(a,b) remove_proc_entry(a,b) # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) # define ipsec_proc_net_remove(a) proc_net_remove(&init_net, a) # else # define ipsec_proc_net_remove(a) proc_net_remove(a) # endif #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) # define NEED_UDP_ENCAP_ENABLE #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0) # define ipsec_ipv6_skip_exthdr ipv6_skip_exthdr # define IPSEC_FRAG_OFF_DECL(x) __be16 x; #else # define ipsec_ipv6_skip_exthdr(a, b, c, d) ipv6_skip_exthdr(a, b, c) # define IPSEC_FRAG_OFF_DECL(x) #endif /* * try to handle time wraps in a nicer manner */ #define ipsec_jiffies_elapsed(now, last) \ ((last) <= \ (now) ? ((now) - (last)) : (((typeof(jiffies)) ~0) - (last) + (now))) #define ipsec_jiffieshz_elapsed(now, last) \ ((last) <= \ (now) ? ((now) - \ (last)) : ((((typeof(jiffies)) ~0) / HZ) - (last) + (now))) /* * Kernel version specific defines, in order from oldest to newest kernel * If possible, use the latest native writing, and write macro's to port back * the new code to older kernels. */ #ifndef CONFIG_IP_ALIAS # define CONFIG_IP_ALIAS #endif /* API changes are documented at: http://lwn.net/Articles/2.6-kernel-api/ */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) # define HAVE_NETDEV_PRINTK 1 # define NET_26 # define NEED_SPINLOCK_TYPES /* Only enable IPv6 support on newer kernels with IPv6 enabled */ # if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) # define CONFIG_KLIPS_IPV6 1 # endif #else /* The obsolete MODULE_PARM() macro is gone forevermore [in 2.6.17+] It was introduced in 2.6.0 Zero-filled memory can now be allocated from slab caches with kmem_cache_zalloc(). There is also a new slab debugging option to produce a /proc/slab_allocators file with detailed allocation information. */ # ifndef module_param # define module_param(a, b, c) MODULE_PARM(#a, "i") # endif /* note below is only true for our current calls to module_param_array */ # define module_param_array(a, b, c, d) MODULE_PARM(#a, "1-2i") #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8) # define NEED_INET_PROTOCOL #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 12) # define HAVE_SOCK_ZAPPED # if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) # define NET_44_SKALLOC # elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) # define NET_26_24_SKALLOC # else # define NET_26_12_SKALLOC # endif #endif /* see */ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 13)) && \ defined(CONFIG_NETFILTER_DEBUG) # define HAVE_SOCK_SECURITY /* skb->nf_debug disappared completely in 2.6.13 */ # define ipsec_nf_debug_reset(skb) ((skb)->nf_debug = 0) #else # define ipsec_nf_debug_reset(skb) #endif /* skb->stamp changed to skb->tstamp in 2.6.14 */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14) # define HAVE_TSTAMP # define HAVE_INET_SK_SPORT #else # define HAVE_SKB_LIST #endif /* it seems 2.6.14 accidentally removed sysctl_ip_default_ttl */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14) # define SYSCTL_IPSEC_DEFAULT_TTL IPSEC_DEFAULT_TTL #else # define SYSCTL_IPSEC_DEFAULT_TTL sysctl_ip_default_ttl #endif /* how to reset an skb we are reusing after encrpytion/decryption etc */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17) # define ipsec_nf_reset(skb) nf_reset((skb)) #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 50) && \ defined(CONFIG_NETFILTER) # define ipsec_nf_reset(skb) do { \ nf_conntrack_put((skb)->nfct); \ (skb)->nfct = NULL; \ ipsec_nf_debug_reset(skb); \ } while (0) #else # define ipsec_nf_reset(skb) /**/ #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) /* The skb_linearize() function has been reworked, and no longer has a GFP flags argument. There is also a new skb_linearize_cow() function which ensures that the resulting SKB is writable. Network drivers should no longer manipulate the xmit_lock spinlock in the net_device structure; instead, the following new functions should be used: int netif_tx_lock(struct net_device *dev); int netif_tx_lock_bh(struct net_device *dev); void netif_tx_unlock(struct net_device *dev); void netif_tx_unlock_bh(struct net_device *dev); int netif_tx_trylock(struct net_device *dev); A number of crypto API changes have been merged, the biggest being a change to most algorithm-specific functions to take a pointer to the crypto_tfm structure, rather than the old "context" pointer. This change was necessary to support parameterized algorithms. */ # define HAVE_NEW_SKB_LINEARIZE #elif defined(CONFIG_XEN) /* this is the best we can do to detect XEN, which makes * patches to linux/skbuff.h, making it look like 2.6.18+ version */ # define HAVE_NEW_SKB_LINEARIZE #elif defined(SLE_VERSION_CODE) /* And the same for SuSe kernels who have it before it got into the * linus kernel. */ # if SLE_VERSION_CODE >= 655616 # define HAVE_NEW_SKB_LINEARIZE # else # warning \ "A Suse kernel was detected, but we are unsure if it requires HAVE_NEW_SKB_LINEARIZE" # endif #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) # define VOID_SOCK_UNREGISTER #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) /* skb->nfmark changed to skb->mark in 2.6.20 */ # define nfmark mark #else # define HAVE_KMEM_CACHE_T # if defined(RHEL_RELEASE_CODE) # if RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(5, 0) # define FLOW_HAS_NO_MARK # endif # elif defined(CONFIG_SLE_VERSION) && defined(CONFIG_SLE_SP) && \ (CONFIG_SLE_VERSION == 10) # define FLOW_HAS_NO_MARK # endif #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 21) /* Significant changes have been made to the crypto support interface. The sysctl code has been heavily reworked, leading to a number of internal API changes. */ # define ipsec_register_sysctl_table(a, b) register_sysctl_table(a) # define CTL_TABLE_PARENT #else # define ipsec_register_sysctl_table(a, b) register_sysctl_table(a, b) #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) # define HAVE_KERNEL_TSTAMP # define grab_socket_timeval(tv, sock) { (tv) = ktime_to_timeval( \ (sock).sk_stamp); } #else # define grab_socket_timeval(tv, sock) { (tv) = (sock).sk_stamp; } #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) || (RHEL_RELEASE_CODE >= \ RHEL_RELEASE_VERSION(5, 2)) /* need to include ip.h early, no longer pick it up in skbuff.h */ #include /* type of sock.sk_stamp changed from timeval to ktime */ #else /* internals of struct skbuff changed */ /* but RedHat/SUSE ported some of this back to their RHEL kernel, so check for that */ # if !defined(RHEL_MAJOR) || !defined(RHEL_MINOR) || !(RHEL_MAJOR == 5 && \ RHEL_MINOR >= 2) # define HAVE_DEV_NEXT # if defined(CONFIG_SLE_VERSION) && defined(CONFIG_SLE_SP) && \ (CONFIG_SLE_VERSION == 10 && CONFIG_SLE_SP <= 2) # define ip_hdr(skb) ((skb)->nh.iph) # endif # define skb_tail_pointer(skb) ((skb)->tail) # define skb_end_pointer(skb) ((skb)->end) # define skb_network_header(skb) ((skb)->nh.raw) # define skb_set_network_header(skb, off) ((skb)->nh.raw = (skb)->data + \ (off)) # define tcp_hdr(skb) ((skb)->h.th) # define udp_hdr(skb) ((skb)->h.uh) # define skb_transport_header(skb) ((skb)->h.raw) # define skb_network_offset(skb) ((skb)->nh.raw - (skb)->data) # define skb_set_transport_header(skb, off) ((skb)->h.raw = (skb)->data + \ (off)) # define skb_reset_transport_header(skb) ((skb)->h.raw = (skb)->data - \ (skb)->head) # define skb_mac_header(skb) ((skb)->mac.raw) # define skb_set_mac_header(skb, off) ((skb)->mac.raw = (skb)->data + (off)) # endif # if defined(CONFIG_SLE_VERSION) && defined(CONFIG_SLE_SP) && \ (CONFIG_SLE_VERSION == 10 && CONFIG_SLE_SP == 2) # define ip_hdr(skb) ((skb)->nh.iph) # endif #endif /* turn a pointer into an offset for above macros */ #define ipsec_skb_offset(skb, ptr) (((unsigned char *)(ptr)) - (skb)->data) #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) /* * The macro got introduced in 2,6,22 but it does not work properly, and * still uses the old number of arguments. */ /* The destructor argument has been removed from kmem_cache_create(), as destructors are no longer supported. All in-kernel callers have been updated */ # define HAVE_KMEM_CACHE_MACRO /* Try using the new klips encaps hook for nat-t, instead of udp.c */ # define HAVE_UDP_ENCAP_CONVERT 1 #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) # define HAVE_NETDEV_HEADER_OPS 1 /* * We can switch on earlier kernels, but from here on we have no choice * but to abandon the old style proc_net and use seq_file * The hard_header() method has been removed from struct net_device; it has been replaced by a per-protocol header_ops structure pointer. The prototype for slab constructor callbacks has changed to: void (*ctor)(struct kmem_cache *cache, void *object); The unused flags argument has been removed and the order of the other two arguments has been reversed to match other slab functions. */ # define HAVE_PROC_DIR_ENTRY # define PROC_NET init_net.proc_net # define PROC_EOF_DATA # define __ipsec_dev_get(x) __dev_get_by_name(&init_net, x) # define ipsec_dev_get(x) dev_get_by_name(&init_net, x) #else # define PROC_NET proc_net # define ipsec_dev_get(x) dev_get_by_name(x) # define __ipsec_dev_get(x) __dev_get_by_name(x) #endif #if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 9, 0) # define PDE_DATA(inode) PDE(inode)->data #endif /* * We do not use CONFIG_NAMSPACES due to a kernel bug * that checks for namespaces in inet_add_protocol() * even when compiled without CONFIG_NAMSPACES */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0) # define HAVE_NAMESPACES #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) # define ip_chk_addr(a) inet_addr_type(&init_net, a) # define l_inet_addr_type(a) inet_addr_type(&init_net, a) #else # define ip_chk_addr inet_addr_type # define l_inet_addr_type inet_addr_type #endif #include #include #include #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) # define ip6_chk_addr(a) (ipv6_chk_addr(&init_net, a, NULL, 1) ? IS_MYADDR : 0) #else # define ip6_chk_addr(a) (ipv6_chk_addr(a, NULL, 1) ? IS_MYADDR : 0) #endif #define l_ipv6_addr_type(a) ip6_chk_addr(a) /* not sure when network name spaces got introduced, but it is in 2.6.26 */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) # define HAVE_NETWORK_NAMESPACE 1 #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) # define HAVE_CURRENT_UID #endif #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 31) # ifndef NETDEV_TX_BUSY # ifdef NETDEV_XMIT_CN # define NETDEV_TX_BUSY NETDEV_XMIT_CN # else # define NETDEV_TX_BUSY 1 # endif # endif #endif #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 30) # ifndef CONFIG_COMPAT_NET_DEV_OPS # define USE_NETDEV_OPS # endif #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31) # define USE_NETDEV_OPS #else # define skb_dst_drop(s) ({ \ if ((s)->dst) \ dst_release((s)->dst); \ (s)->dst = NULL; \ }) # define skb_dst_set(s, p) ((s)->dst = (p)) # define skb_dst(s) ((s)->dst) #endif /* The SLES10 kernel is known to not have these defines */ #ifdef CONFIG_KLIPS_IPV6 # ifndef IN6ADDR_ANY_INIT # define IN6ADDR_ANY_INIT { { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 0 } } } # endif # ifndef IN6ADDR_LINKLOCAL_ALLNODES_INIT # define IN6ADDR_LINKLOCAL_ALLNODES_INIT { { { 0xff, 2, 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 1 } } } # endif #endif #if !defined(HAVE_CURRENT_UID) # define current_uid() (current->uid) #endif #define ipsec_kfree_skb(a) kfree_skb(a) #ifndef HAVE_NETDEV_PRINTK # define netdev_printk(sevlevel, netdev, msglevel, format, arg ...) \ printk(sevlevel "%s: " format, netdev->name, ## arg) #endif #define ipsec_dev_put(x) dev_put(x) #define __ipsec_dev_put(x) __dev_put(x) #define ipsec_dev_hold(x) dev_hold(x) #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) # ifndef late_initcall # include # ifndef late_initcall # define late_initcall(x) module_init(x) # endif # endif #endif #include #include #include #include #ifdef NF_IP_LOCAL_OUT # define LSW_NF_INET_LOCAL_OUT NF_IP_LOCAL_OUT #endif #ifndef LSW_NF_INET_LOCAL_OUT # define LSW_NF_INET_LOCAL_OUT NF_INET_LOCAL_OUT #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33) # define inet_sport sport # define inet_dport dport # define CTL_NAME(n) .ctl_name = n, #else # define CTL_NAME(n) #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) # define HAVE_SOCKET_WQ #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) # define ipsec_route_dst(x) (x)->dst #else # define ipsec_route_dst(x) (x)->u.dst #endif #if defined(CONFIG_SLE_VERSION) && defined(CONFIG_SLE_SP) && \ (CONFIG_SLE_VERSION == 10 && CONFIG_SLE_SP >= 3) # define HAVE_BACKPORTED_NEW_CRYPTOAPI 1 #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37) # define PRIVATE_ARP_BROKEN_OPS #endif #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 38) # ifndef DEFINE_SPINLOCK # define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED # endif # define flowi_tos nl_u.ip4_u.tos # define flowi_proto proto # define flowi_mark mark # define flowi_oif oif #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39) # define nl_u u # define ip4_u ip4 # define ip6_u ip6 #endif /* * Note that kernel 3.x maps to 2.6.40+x with the UNAME26 patch */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0) || (LINUX_VERSION_CODE >= \ KERNEL_VERSION(2, 6, 41)) # define HAVE_NETDEV_PRIV # define HAVE_NET_DEVICE_OPS # define HAVE_NETIF_QUEUE #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0) /* just define for old kernels so we can catch it on new kernels */ # define NETDEV_UNREGISTER_FINAL 0x0011 #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0) || \ (RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7, 0) && \ LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)) # define HAVE_NETDEV_INFO #endif #ifdef alloc_netdev # if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0) # define ipsec_alloc_netdev(a,b,c,d) alloc_netdev(a,b,c,d) typedef struct ctl_table ctl_table; # else # define ipsec_alloc_netdev(a,b,c,d) alloc_netdev(a,b,d) # endif #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0) # define memcpy_from_msg(a,b,c) memcpy_fromiovec(a,(b)->msg_iov,c) # define skb_copy_datagram_msg(a,b,c,d) skb_copy_datagram_iovec(a,b,(c)->msg_iov,d) #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0) # define HAVE_REBUILD_HEADER #endif #if !defined(DEFINE_RWLOCK) # define DEFINE_RWLOCK(x) rwlock_t x = RW_LOCK_UNLOCKED #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) # define HAVE_USER_NS /* CONFIG_USER_NS is now on in Fedora 20 kernels */ #elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) # if defined(CONFIG_USER_NS) # define HAVE_USER_NS # endif #endif #if LINUX_VERSION_CODE > KERNEL_VERSION(4, 6, 0) # define HAS_AHASH # define HAS_SKCIPHER #endif /* seems to have been backported to as far back as 4.1.4 though */ #if LINUX_VERSION_CODE > KERNEL_VERSION(4, 11, 9) # define HAS_PRIV_DESTRUCTOR #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 20, 0) # define SYNC_SKCIPHER_REQUEST_ON_STACK(a,b) SKCIPHER_REQUEST_ON_STACK(a,b) #endif #endif /* _LIBRESWAN_KVERSIONS_H */ libreswan-3.32/linux/include/libreswan/ipsec_life.h000066400000000000000000000047121365625662500224760ustar00rootroot00000000000000/* * Definitions relevant to IPSEC lifetimes * Copyright (C) 2001 Richard Guy Briggs * and Michael Richardson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * This file derived from ipsec_xform.h on 2001/9/18 by mcr. */ /* * This file describes the book keeping fields for the * IPsec Security Association Structure. ("ipsec_sa") * * This structure is never allocated directly by kernel code, * (it is always a static/auto or is part of a structure) * so it does not have a reference count. * */ #ifndef _IPSEC_LIFE_H_ /* * _count is total count. * _hard is hard limit (kill SA after this number) * _soft is soft limit (try to renew SA after this number) * _last is used in some special cases. * */ struct ipsec_lifetime64 { __u64 ipl_count; __u64 ipl_soft; __u64 ipl_hard; __u64 ipl_last; }; struct ipsec_lifetimes { /* number of bytes processed */ struct ipsec_lifetime64 ipl_bytes; /* number of packets processed */ struct ipsec_lifetime64 ipl_packets; /* time since SA was added */ struct ipsec_lifetime64 ipl_addtime; /* time since SA was first used */ struct ipsec_lifetime64 ipl_usetime; /* from rfc2367: * For CURRENT, the number of different connections, * endpoints, or flows that the association has been * allocated towards. For HARD and SOFT, the number of * these the association may be allocated towards * before it expires. The concept of a connection, * flow, or endpoint is system specific. * * mcr(2001-9-18) it is unclear what purpose these serve for Libreswan * They are maintained for PF_KEY compatibility. */ struct ipsec_lifetime64 ipl_allocations; }; enum ipsec_life_alive { ipsec_life_harddied = -1, ipsec_life_softdied = 0, ipsec_life_okay = 1 }; enum ipsec_life_type { ipsec_life_timebased = 1, ipsec_life_countbased= 0 }; #define _IPSEC_LIFE_H_ #endif /* _IPSEC_LIFE_H_ */ libreswan-3.32/linux/include/libreswan/ipsec_mast.h000066400000000000000000000025601365625662500225220ustar00rootroot00000000000000#ifndef _IPSEC_MAST_H #define _IPSEC_MAST_H struct net_device; #define DB_MAST_INIT 0x0001 #define DB_MAST_PROCFS 0x0002 #define DB_MAST_XMIT 0x0010 #define DB_MAST_OHDR 0x0020 #define DB_MAST_CROUT 0x0040 #define DB_MAST_OXFS 0x0080 #define DB_MAST_REVEC 0x0100 #define DB_MAST_ENCAP 0x0200 struct ipsecmastconf { __u32 cf_cmd; union { char cfu_name[12]; } cf_u; #define cf_name cf_u.cfu_name }; #define MASTPRIV_MAGIC 0x4A57C0DE struct mastpriv { uint32_t magic; struct sk_buff_head sendq; struct wait_queue *wait_queue; int (*hard_header) (struct sk_buff *skb, struct net_device *dev, unsigned short type, void *daddr, void *saddr, unsigned len); struct net_device_stats mystats; int mtu; /* What is the desired MTU? */ }; static inline struct mastpriv *netdev_to_mastpriv(const struct net_device *dev) { struct mastpriv *mprv = netdev_priv(dev); BUG_ON(!mprv); BUG_ON(mprv->magic != MASTPRIV_MAGIC); return mprv; } extern int ipsec_mast_init_devices(void); extern int ipsec_mast_cleanup_devices(void); extern int ipsec_mast_deletenum(int vifnum); extern int ipsec_mast_createnum(int vifnum); extern struct net_device *ipsec_mast_get_device(int vifnum); extern unsigned int ipsec_mast_is_transport(int vifnum); extern int ipsec_mast_init_saref(void); extern void ipsec_mast_cleanup_saref(void); #endif libreswan-3.32/linux/include/libreswan/ipsec_md5h.h000066400000000000000000000015511365625662500224120ustar00rootroot00000000000000/* * The rest of this file is Copyright RSA DSI. See the following comments * for the full Copyright notice. */ #ifndef _IPSEC_MD5H_H_ #define _IPSEC_MD5H_H_ /* GLOBAL.H - RSAREF types and constants */ /* POINTER defines a generic pointer type */ typedef __u8 *POINTER; /* UINT4 defines a four byte word */ typedef __u32 UINT4; /* MD5.H - header file for MD5C.C */ /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. * * http://www.ietf.org/ietf-ftp/IPR/RSA-MD-all */ /* MD5 context. */ typedef struct { UINT4 state[4]; /* state (ABCD) */ UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ unsigned char buffer[64]; /* input buffer */ } MD5_CTX; void osMD5Init(void *); void osMD5Update(void *, unsigned char *, __u32); void osMD5Final(unsigned char [16], void *); #endif /* _IPSEC_MD5H_H_ */ libreswan-3.32/linux/include/libreswan/ipsec_param.h000066400000000000000000000134241365625662500226570ustar00rootroot00000000000000/* * @(#) Libreswan tunable paramaters * * Copyright (C) 2001 Richard Guy Briggs * and Michael Richardson * Copyright (C) 2004 Michael Richardson * Copyright (C) 2012 Paul Wouters * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * */ /* * This file provides a set of #defines that may be tuned by various * people/configurations. It keeps all compile-time tunables in one place. * * This file should be included before all other IPsec kernel-only files. * */ #ifndef _IPSEC_PARAM_H_ #ifdef __KERNEL__ #include "libreswan/ipsec_kversion.h" /* Set number of ipsecX virtual devices here. */ /* This must be < exp(field width of IPSEC_DEV_FORMAT) */ /* It must also be reasonable so as not to overload the memory and CPU */ /* constraints of the host. */ #ifdef CONFIG_KLIPS_IF_MAX #define IPSEC_NUM_IFMAX CONFIG_KLIPS_IF_MAX #endif #ifndef IPSEC_NUM_IFMAX #define IPSEC_NUM_IFMAX 64 #endif /* default number of ipsecX devices to create */ #ifdef CONFIG_KLIPS_IF_NUM #define IPSEC_NUM_IF CONFIG_KLIPS_IF_NUM #else #define IPSEC_NUM_IF 2 #endif /* The field width must be < IF_NAM_SIZ - strlen("ipsec") - 1. */ /* With "ipsec" being 5 characters, that means 10 is the max field width */ /* but machine memory and CPU constraints are not likely to tolerate */ /* more than 3 digits. The default is one digit. */ /* Update: userland scripts get upset if they can't find "ipsec0", so */ /* for now, no "0"-padding should be used (which would have been helpful) */ /* to make text-searches work */ #define IPSEC_DEV_FORMAT "ipsec%d" #define MAST_DEV_FORMAT "mast%d" /* For, say, 500 virtual ipsec devices, I would recommend: */ /* #define IPSEC_NUM_IF 500 */ /* #define IPSEC_DEV_FORMAT "ipsec%03d" */ /* Note that the "interfaces=" line in /etc/ipsec.conf would be, um, challenging. */ /* use dynamic ipsecX device allocation */ #ifndef CONFIG_KLIPS_DYNDEV #define CONFIG_KLIPS_DYNDEV 1 #endif /* CONFIG_KLIPS_DYNDEV */ # define SADB_HASHMOD 257 #endif /* __KERNEL__ */ /* * This is for the SA reference table. This number is related to the * maximum number of SAs that KLIPS can concurrently deal with, plus enough * space for keeping expired SAs around. * * TABLE_IDX_WIDTH is the number of bits that we will use. * MAIN_TABLE_WIDTH is the number of bits used for the primary index table. * */ #ifndef IPSEC_SA_REF_MAINTABLE_IDX_WIDTH # define IPSEC_SA_REF_MAINTABLE_IDX_WIDTH 4 #endif #ifndef IPSEC_SA_REF_FREELIST_NUM_ENTRIES # define IPSEC_SA_REF_FREELIST_NUM_ENTRIES 256 #endif #ifndef IPSEC_SA_REF_CODE # define IPSEC_SA_REF_CODE 1 #endif #ifdef __KERNEL__ /* This is defined for 2.4, but not 2.2.... */ #ifndef ARPHRD_VOID # define ARPHRD_VOID 0xFFFF #endif /* always turn on IPIP mode */ #ifndef CONFIG_KLIPS_IPIP #define CONFIG_KLIPS_IPIP 1 #endif /* * Worry about PROC_FS stuff */ /* kernel 2.4 */ # define IPSEC_PROC_LAST_ARG , int *eof, void *data # define IPSEC_PROCFS_DEBUG_NO_STATIC # define IPSEC_PROC_SUBDIRS # include /* *lock* */ #ifndef KLIPS_FIXES_DES_PARITY # define KLIPS_FIXES_DES_PARITY 1 #endif /* !KLIPS_FIXES_DES_PARITY */ /* we don't really want to print these unless there are really big problems */ #ifndef KLIPS_DIVULGE_CYPHER_KEY # define KLIPS_DIVULGE_CYPHER_KEY 0 #endif /* !KLIPS_DIVULGE_CYPHER_KEY */ #ifndef KLIPS_DIVULGE_HMAC_KEY # define KLIPS_DIVULGE_HMAC_KEY 0 #endif /* !KLIPS_DIVULGE_HMAC_KEY */ #ifndef IPSEC_DISALLOW_IPOPTIONS # define IPSEC_DISALLOW_IPOPTIONS 1 #endif /* !KLIPS_DIVULGE_HMAC_KEY */ /* extra toggles for regression testing */ #ifdef CONFIG_KLIPS_REGRESS /* * should pfkey_acquire() become 100% lossy? * */ extern int sysctl_ipsec_regress_pfkey_lossage; #ifndef KLIPS_PFKEY_ACQUIRE_LOSSAGE # ifdef CONFIG_KLIPS_PFKEY_ACQUIRE_LOSSAGE # define KLIPS_PFKEY_ACQUIRE_LOSSAGE 100 # else /* CONFIG_KLIPS_PFKEY_ACQUIRE_LOSSAGE */ /* not by default! */ # define KLIPS_PFKEY_ACQUIRE_LOSSAGE 0 # endif /* CONFIG_KLIPS_PFKEY_ACQUIRE_LOSSAGE */ #endif /* KLIPS_PFKEY_ACQUIRE_LOSSAGE */ #endif /* CONFIG_KLIPS_REGRESS */ /* * debugging routines. */ #define KLIPS_ERROR(flag, format, args ...) { \ if (printk_ratelimit() || (flag)) \ printk(KERN_ERR "KLIPS " format, ## args); \ } #define KLIPS_PRINT(flag, format, args ...) \ ((flag) ? printk(KERN_INFO format, ## args) : 0) #define KLIPS_PRINTMORE(flag, format, args ...) \ ((flag) ? printk(format, ## args) : 0) #define KLIPS_IP_PRINT(flag, ip) \ ((flag) ? ipsec_print_ip(ip) : 0) #define KLIPS_SATOT(flag, sa, format, dst, dstlen) \ ((flag) ? satot(sa, format, dst, dstlen) : 0) #if 0 /* not CONFIG_KLIPS_DEBUG */ #define KLIPS_ERROR(flag, format, args ...) { \ if (printk_ratelimit()) \ printk(KERN_ERR "KLIPS " format, ## args); \ } #define KLIPS_PRINT(flag, format, args ...) { } #define KLIPS_PRINTMORE(flag, format, args ...) { } #define KLIPS_IP_PRINT(flag, ip) { } #define KLIPS_SATOT(flag, sa, format, dst, dstlen) (0) #endif /* CONFIG_KLIPS_DEBUG */ /* * make klips fail test:east-espiv-01. * exploit is at testing/attacks/espiv * */ #define KLIPS_IMPAIRMENT_ESPIV_CBC_ATTACK 0 #endif /* __KERNEL__ */ #ifdef NEED_INET_PROTOCOL #define inet_protocol net_protocol #endif #ifndef IPSEC_DEFAULT_TTL #define IPSEC_DEFAULT_TTL 64 #endif #define _IPSEC_PARAM_H_ #endif /* _IPSEC_PARAM_H_ */ libreswan-3.32/linux/include/libreswan/ipsec_param2.h000066400000000000000000000025411365625662500227370ustar00rootroot00000000000000/* * header file for Libreswan kernel compat * Copyright (C) 2009 Michael Richardson * Copyright (C) 2012 Paul Wouters * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. * */ #ifndef _IPSEC_PARAM2_H_ #define _IPSEC_PARAM2_H_ /* nicely, latest netdevice.h includes this define */ #ifndef HAVE_NETDEV_PRIV #define netdev_priv(dev) ((dev)->priv) #endif #if defined(IP_SELECT_IDENT_NEW) # if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) # define KLIPS_IP_SELECT_IDENT(iph, skb) __ip_select_ident(iph, 1) # else # define KLIPS_IP_SELECT_IDENT(iph, skb) __ip_select_ident(dev_net(skb->dev), iph, 1) # endif #else # define KLIPS_IP_SELECT_IDENT(iph, skb) __ip_select_ident(iph, skb_dst(skb), 0) #endif #if !defined(HAVE_CURRENT_UID) #define current_uid() (current->uid) #endif #endif /* _LIBRESWAN_PARAM2_H */ libreswan-3.32/linux/include/libreswan/ipsec_proto.h000066400000000000000000000067761365625662500227360ustar00rootroot00000000000000/* * @(#) prototypes for Libreswan functions * * Copyright (C) 2001 Richard Guy Briggs * and Michael Richardson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #ifndef _IPSEC_PROTO_H_ #include "ipsec_param.h" /* * This file is a kernel only file that declares prototypes for * all intra-module function calls and global data structures. * * Include this file last. * */ /* forward references */ enum ipsec_direction; enum ipsec_life_type; struct ipsec_lifetime64; struct ident; struct sockaddr_encap; struct ipsec_sa; /* ipsec_init.c */ extern struct prng ipsec_prng; /* ipsec_sa.c */ extern struct ipsec_sa *ipsec_sadb_hash[SADB_HASHMOD]; extern spinlock_t tdb_lock; extern int ipsec_sadb_init(void); extern int ipsec_sadb_cleanup(__u8); extern struct ipsec_sa *ipsec_sa_alloc(int *error); extern struct ipsec_sa *ipsec_sa_getbyid(ip_said *, int type); extern /* void */ int ipsec_sa_add(struct ipsec_sa *); extern int ipsec_sa_init(struct ipsec_sa *ipsp); /* debug declarations */ /* ipsec_proc.c */ extern int ipsec_proc_init(void); extern void ipsec_proc_cleanup(void); /* ipsec_rcv.c */ extern int ipsec_rcv(struct sk_buff *skb); extern int klips26_rcv_encap(struct sk_buff *skb, __u16 encap_type); /* ipsec_xmit.c */ struct ipsec_xmit_state; extern enum ipsec_xmit_value ipsec_xmit_sanity_check_ipsec_dev( struct ipsec_xmit_state *ixs); extern enum ipsec_xmit_value ipsec_xmit_sanity_check_mast_dev( struct ipsec_xmit_state *ixs); extern enum ipsec_xmit_value ipsec_xmit_sanity_check_skb( struct ipsec_xmit_state *ixs); extern void ipsec_print_ip(void *ip); /* ipsec_radij.c */ extern int ipsec_makeroute(struct sockaddr_encap *ea, struct sockaddr_encap *em, ip_said said, uint32_t pid, struct sk_buff *skb, struct ident *ident_s, struct ident *ident_d); extern int ipsec_breakroute(struct sockaddr_encap *ea, struct sockaddr_encap *em, struct sk_buff **first, struct sk_buff **last); int ipsec_radijinit(void); int ipsec_cleareroutes(void); int ipsec_radijcleanup(void); /* ipsec_life.c */ extern enum ipsec_life_alive ipsec_lifetime_check( struct ipsec_lifetime64 *il64, const char *lifename, const char *saname, enum ipsec_life_type ilt, enum ipsec_direction idir, struct ipsec_sa *ips); extern int ipsec_lifetime_format(struct seq_file *seq, char *lifename, enum ipsec_life_type timebaselife, struct ipsec_lifetime64 *lifetime); extern void ipsec_lifetime_update_hard(struct ipsec_lifetime64 *lifetime, __u64 newvalue); extern void ipsec_lifetime_update_soft(struct ipsec_lifetime64 *lifetime, __u64 newvalue); /* ipsec_snprintf.c */ extern int ipsec_snprintf(char * buf, ssize_t size, const char *fmt, ...); extern void ipsec_dmp_block(char *s, caddr_t bb, int len); /* ipsec_alg.c */ extern int ipsec_alg_init(void); extern int debug_xform; extern int debug_eroute; extern int debug_spi; extern int debug_netlink; #define _IPSEC_PROTO_H #endif /* _IPSEC_PROTO_H_ */ libreswan-3.32/linux/include/libreswan/ipsec_radij.h000066400000000000000000000025441365625662500226510ustar00rootroot00000000000000/* * @(#) Definitions relevant to the IPSEC <> radij tree interfacing * Copyright (C) 1996, 1997 John Ioannidis. * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #ifndef _IPSEC_RADIJ_H #include extern int ipsec_walk(char *); extern int ipsec_rj_walker_show(struct radij_node *, void *); extern int ipsec_rj_walker_delete(struct radij_node *, void *); extern struct radij_node_head *rnh; extern spinlock_t eroute_lock; extern struct eroute * ipsec_findroute(struct sockaddr_encap *); #define O1(x) (int)(((x) >> 24) & 0xff) #define O2(x) (int)(((x) >> 16) & 0xff) #define O3(x) (int)(((x) >> 8) & 0xff) #define O4(x) (int)(((x)) & 0xff) extern int debug_radij; extern void rj_dumptrees(void); #define DB_RJ_DUMPTREES 0x0001 #define DB_RJ_FINDROUTE 0x0002 #define _IPSEC_RADIJ_H #endif libreswan-3.32/linux/include/libreswan/ipsec_rcv.h000066400000000000000000000123521365625662500223500ustar00rootroot00000000000000/* * * Copyright (C) 1996, 1997 John Ioannidis. * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. * Copyright (C) 2012 Paul Wouters * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #ifndef IPSEC_RCV_H #define IPSEC_RCV_H #include "libreswan/ipsec_auth.h" #define DB_RX_PKTRX 0x0001 #define DB_RX_PKTRX2 0x0002 #define DB_RX_DMP 0x0004 #define DB_RX_IPSA 0x0010 #define DB_RX_XF 0x0020 #define DB_RX_IPAD 0x0040 #define DB_RX_INAU 0x0080 #define DB_RX_OINFO 0x0100 #define DB_RX_OINFO2 0x0200 #define DB_RX_OH 0x0400 #define DB_RX_REPLAY 0x0800 #ifdef __KERNEL__ /* struct options; */ #define __NO_VERSION__ #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38) && \ !defined(AUTOCONF_INCLUDED) #include #endif /* for CONFIG_IP_FORWARD */ #ifdef CONFIG_MODULES #include #endif #include #ifdef CONFIG_KLIPS_OCF #include #endif #define IPSEC_BIRTH_TEMPLATE_MAXLEN 256 struct ipsec_birth_reply { int packet_template_len; unsigned char packet_template[IPSEC_BIRTH_TEMPLATE_MAXLEN]; }; extern struct ipsec_birth_reply ipsec_ipv4_birth_packet; extern struct ipsec_birth_reply ipsec_ipv6_birth_packet; enum ipsec_rcv_value { IPSEC_RCV_PENDING=2, IPSEC_RCV_LASTPROTO=1, IPSEC_RCV_OK=0, IPSEC_RCV_BADPROTO=-1, IPSEC_RCV_BADLEN=-2, IPSEC_RCV_ESP_BADALG=-3, IPSEC_RCV_3DES_BADBLOCKING=-4, IPSEC_RCV_ESP_DECAPFAIL=-5, IPSEC_RCV_DECAPFAIL=-6, IPSEC_RCV_SAIDNOTFOUND=-7, IPSEC_RCV_IPCOMPALONE=-8, IPSEC_RCV_IPCOMPFAILED=-10, IPSEC_RCV_SAIDNOTLIVE=-11, IPSEC_RCV_FAILEDINBOUND=-12, IPSEC_RCV_LIFETIMEFAILED=-13, IPSEC_RCV_BADAUTH=-14, IPSEC_RCV_REPLAYFAILED=-15, IPSEC_RCV_AUTHFAILED=-16, IPSEC_RCV_REPLAYROLLED=-17, IPSEC_RCV_BAD_DECRYPT=-18, IPSEC_RCV_REALLYBAD=-19, IPSEC_RCV_ERRMEMALLOC=-20 }; /* * state machine states */ #define IPSEC_RSM_INIT 0 /* make it easy, starting state is 0 */ #define IPSEC_RSM_DECAP_INIT 1 #define IPSEC_RSM_DECAP_LOOKUP 2 #define IPSEC_RSM_AUTH_INIT 3 #define IPSEC_RSM_AUTH_DECAP 4 #define IPSEC_RSM_AUTH_CALC 5 #define IPSEC_RSM_AUTH_CHK 6 #define IPSEC_RSM_DECRYPT 7 #define IPSEC_RSM_DECAP_CONT 8 /* do we restart at IPSEC_RSM_DECAP_INIT */ #define IPSEC_RSM_CLEANUP 9 #define IPSEC_RSM_IPCOMP 10 #define IPSEC_RSM_COMPLETE 11 #define IPSEC_RSM_DONE 100 struct ipsec_rcv_state { struct sk_buff *skb; struct sk_buff *pre_ipcomp_skb; /* skb before ipcomp was attempted */ struct net_device_stats *stats; void *iph; /* the IP header */ struct ipsec_sa *ipsp; /* current SA being processed */ struct ipsec_sa *lastipsp; /* last SA that was processed */ int len; /* length of packet */ int ilen; /* length of inner payload (-authlen) */ int authlen; /* how big is the auth data at end */ int hard_header_len; /* layer 2 size */ int iphlen; /* how big is IP header */ unsigned int transport_direct : 1; struct auth_alg *authfuncs; ip_said said; char sa[SATOT_BUF]; size_t sa_len; __u8 next_header; __u8 hash[AH_AMAX]; char ipsaddr_txt[ADDRTOA_BUF]; char ipdaddr_txt[ADDRTOA_BUF]; __u8 *octx; __u8 *ictx; int ictx_len; int octx_len; union { struct { struct esphdr *espp; } espstuff; struct { struct ahhdr *ahp; } ahstuff; struct { struct ipcomphdr *compp; } ipcompstuff; } protostuff; __u8 natt_type; __u16 natt_sport; __u16 natt_dport; int natt_len; /* * rcv state machine use */ int state; int next_state; int auth_checked; struct xform_functions *proto_funcs; __u8 proto; int replay; unsigned char *authenticator; int esphlen; #ifdef CONFIG_KLIPS_ALG struct ipsec_alg_auth *ixt_a; #endif __u8 ttl, tos; __u16 frag_off, check; }; extern void ipsec_rsm(struct ipsec_rcv_state *irs); #ifdef HAVE_KMEM_CACHE_T extern kmem_cache_t *ipsec_irs_cache; #else extern struct kmem_cache *ipsec_irs_cache; #endif extern int ipsec_irs_max; extern atomic_t ipsec_irs_cnt; extern int ipsec_rcv(struct sk_buff *skb); extern int sysctl_ipsec_inbound_policy_check; extern int debug_rcv; #define ipsec_rcv_dmp(_x, _y, _z) { \ if (debug_rcv && sysctl_ipsec_debug_verbose) \ ipsec_dmp_block((_x), (_y), (_z)); \ } #else #define ipsec_rcv_dmp(_x, _y, _z) { } #endif /* __KERNEL__ */ extern int klips26_udp_encap_rcv(struct sock *sk, struct sk_buff *skb); extern int klips26_rcv_encap(struct sk_buff *skb, __u16 encap_type); // manage ipsec rcv state objects extern int ipsec_rcv_state_cache_init(void); extern void ipsec_rcv_state_cache_cleanup(void); #endif /* IPSEC_RCV_H */ libreswan-3.32/linux/include/libreswan/ipsec_sa.h000066400000000000000000000264431365625662500221670ustar00rootroot00000000000000/* * @(#) Definitions of IPsec Security Association (ipsec_sa) * * Copyright (C) 2001, 2002, 2003 * Richard Guy Briggs * and Michael Richardson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * This file derived from ipsec_xform.h on 2001/9/18 by mcr. * */ /* * This file describes the IPsec Security Association Structure. * * This structure keeps track of a single transform that may be done * to a set of packets. It can describe applying the transform or * apply the reverse. (e.g. compression vs expansion). However, it * only describes one at a time. To describe both, two structures would * be used, but since the sides of the transform are performed * on different machines typically it is usual to have only one side * of each association. * */ #ifndef _IPSEC_SA_H_ #ifdef __KERNEL__ #include "libreswan/ipsec_stats.h" #include "libreswan/ipsec_life.h" #include "libreswan/ipsec_eroute.h" #endif /* __KERNEL__ */ #include "libreswan/ipsec_param.h" #include "libreswan/pfkeyv2.h" /* SAs are held in a table. * Entries in this table are referenced by IPsecSAref_t values. * IPsecSAref_t values are conceptually subscripts. Because * we want to allocate the table piece-meal, the subscripting * is implemented with two levels, a bit like paged virtual memory. * This representation mechanism is known as an Iliffe Vector. * * The Main table (AKA the refTable) consists of 2^IPSEC_SA_REF_MAINTABLE_IDX_WIDTH * pointers to subtables. * Each subtable has 2^IPSEC_SA_REF_SUBTABLE_IDX_WIDTH entries, each of which * is a pointer to an SA. * * An IPsecSAref_t contains either an exceptional value (signified by the * high-order bit being on) or a reference to a table entry. A table entry * reference has the subtable subscript in the low-order * IPSEC_SA_REF_SUBTABLE_IDX_WIDTH bits and the Main table subscript * in the next lowest IPSEC_SA_REF_MAINTABLE_IDX_WIDTH bits. * * The Maintable entry for an IPsecSAref_t x, a pointer to its subtable, is * IPsecSAref2table(x). It is of type struct IPsecSArefSubTable *. * * The pointer to the SA for x is IPsecSAref2SA(x). It is of type * struct ipsec_sa*. The macro definition clearly shows the two-level * access needed to find the SA pointer. * * The Maintable is allocated when IPsec is initialized. * Each subtable is allocated when needed, but the first is allocated * when IPsec is initialized. * * IPsecSAref_t is designed to be smaller than an NFmark so that * they can be stored in NFmarks and still leave a few bits for other * purposes. The spare bits are in the low order of the NFmark * but in the high order of the IPsecSAref_t, so conversion is required. * We pick the upper bits of NFmark on the theory that they are less likely to * interfere with more pedestrian uses of nfmark. */ typedef unsigned short int IPsecRefTableUnusedCount; #define IPSEC_SA_REF_TABLE_NUM_ENTRIES (1 << IPSEC_SA_REF_TABLE_IDX_WIDTH) #ifdef __KERNEL__ #define IPSEC_SA_REF_SUBTABLE_IDX_WIDTH \ (IPSEC_SA_REF_TABLE_IDX_WIDTH - IPSEC_SA_REF_MAINTABLE_IDX_WIDTH) #if IPSEC_SA_REF_SUBTABLE_IDX_WIDTH <= 0 #error "IPSEC_SA_REF_TABLE_IDX_WIDTH("IPSEC_SA_REF_TABLE_IDX_WIDTH") MUST be > IPSEC_SA_REF_MAINTABLE_IDX_WIDTH("IPSEC_SA_REF_MAINTABLE_IDX_WIDTH")" #endif #define IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES \ (1 << IPSEC_SA_REF_MAINTABLE_IDX_WIDTH) #define IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES \ (1 << IPSEC_SA_REF_SUBTABLE_IDX_WIDTH) #define IPSEC_SA_REF_SUBTABLE_SIZE \ (IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES * sizeof(struct ipsec_sa *)) #ifdef CONFIG_NETFILTER #define IPSEC_SA_REF_HOST_FIELD(x) ((struct sk_buff*)(x))->nfmark /* ??? typeof is a GCCism */ #define IPSEC_SA_REF_HOST_FIELD_TYPE typeof(IPSEC_SA_REF_HOST_FIELD(NULL)) #else /* CONFIG_NETFILTER */ /* just make it work for now, it doesn't matter, since there is no nfmark */ #define IPSEC_SA_REF_HOST_FIELD_TYPE unsigned long #endif /* CONFIG_NETFILTER */ #define IPSEC_SA_REF_HOST_FIELD_WIDTH \ (8 * sizeof(IPSEC_SA_REF_HOST_FIELD_TYPE)) #define IPSEC_SA_REF_FIELD_WIDTH (8 * sizeof(IPsecSAref_t)) #define IPSEC_SA_REF_MAX (~IPSEC_SAREF_NULL) #define IPSEC_SAREF_FIRST 1 /* from libreswan.h #define IPSEC_SA_REF_MASK (IPSEC_SA_REF_MAX >> (IPSEC_SA_REF_FIELD_WIDTH - IPSEC_SA_REF_TABLE_IDX_WIDTH)) */ #define IPSEC_SA_REF_TABLE_MASK \ (IPSEC_SA_REF_MAX \ >> (IPSEC_SA_REF_FIELD_WIDTH - IPSEC_SA_REF_MAINTABLE_IDX_WIDTH) \ << IPSEC_SA_REF_SUBTABLE_IDX_WIDTH) #define IPSEC_SA_REF_ENTRY_MASK \ (IPSEC_SA_REF_MAX \ >> (IPSEC_SA_REF_FIELD_WIDTH - IPSEC_SA_REF_SUBTABLE_IDX_WIDTH)) #define IPsecSAref2table(x) \ (((x) & IPSEC_SA_REF_TABLE_MASK) >> IPSEC_SA_REF_SUBTABLE_IDX_WIDTH) #define IPsecSAref2entry(x) ((x) & IPSEC_SA_REF_ENTRY_MASK) #define IPsecSArefBuild(x, y) (((x) << IPSEC_SA_REF_SUBTABLE_IDX_WIDTH) + (y)) #define IPsecSAref2SA(x) (ipsec_sadb.refTable[IPsecSAref2table(x)]->entry[ \ IPsecSAref2entry(x)]) #define IPsecSA2SAref(x) ((x)->ips_ref) #define IPsecSA2SArefhim(x) ((x)->ips_refhim) #define EMT_INBOUND 0x01 /* SA direction, 1=inbound */ /* 'struct ipsec_sa' should be 64bit aligned when allocated. */ struct ipsec_sa { atomic_t ips_refcount; /* reference count for this struct */ int ips_marked_deleted; /* used with reference counting */ IPsecSAref_t ips_ref; /* reference table entry number */ IPsecSAref_t ips_refhim; /* ref of paired SA, if any */ struct ipsec_sa *ips_next; /* pointer to next xform */ struct ipsec_sa *ips_prev; /* pointer to prev xform */ struct ipsec_sa *ips_hnext; /* next in hash chain */ struct ifnet *ips_rcvif; /* related rcv encap interface */ struct xform_functions *ips_xformfuncs; /* pointer to routines to process this SA */ struct net_device *ips_out; /* what interface to emerge on */ __u8 ips_transport_direct; /* if true, punt directly to * the protocol layer */ struct socket *ips_sock; /* cache of transport socket */ ip_said ips_said; /* SA ID */ __u32 ips_seq; /* seq num of msg that initiated this SA */ __u32 ips_pid; /* PID of process that initiated this SA */ __u8 ips_authalg; /* auth algorithm for this SA */ __u8 ips_encalg; /* enc algorithm for this SA */ struct ipsec_stats ips_errs; __u8 ips_replaywin; /* replay window size */ enum sadb_sastate ips_state; /* state of SA */ __u32 ips_replaywin_lastseq; /* last pkt sequence num */ __u64 ips_replaywin_bitmap; /* bitmap of received pkts */ __u32 ips_replaywin_maxdiff; /* max pkt sequence difference */ __u32 ips_flags; /* generic xform flags */ struct ipsec_lifetimes ips_life; /* lifetime records */ /* selector information */ __u8 ips_transport_protocol; /* protocol for this SA, if ports are involved */ struct sockaddr *ips_addr_s; /* src sockaddr */ struct sockaddr *ips_addr_d; /* dst sockaddr */ struct sockaddr *ips_addr_p; /* proxy sockaddr */ __u16 ips_addr_s_size; __u16 ips_addr_d_size; __u16 ips_addr_p_size; ip_address ips_flow_s; ip_address ips_flow_d; ip_address ips_mask_s; ip_address ips_mask_d; __u16 ips_key_bits_a; /* size of authkey in bits */ __u16 ips_auth_bits; /* size of authenticator in bits */ __u16 ips_key_bits_e; /* size of enckey in bits */ __u16 ips_iv_bits; /* size of IV in bits */ __u8 ips_iv_size; __u16 ips_key_a_size; __u16 ips_key_e_size; caddr_t ips_key_a; /* authentication key */ caddr_t ips_key_e; /* encryption key */ caddr_t ips_iv; /* Initialisation Vector */ struct ident ips_ident_s; /* identity src */ struct ident ips_ident_d; /* identity dst */ /* these are included even if CONFIG_KLIPS_IPCOMP is off */ __u16 ips_comp_adapt_tries; /* ipcomp self-adaption tries */ __u16 ips_comp_adapt_skip; /* ipcomp self-adaption to-skip */ __u64 ips_comp_ratio_cbytes; /* compressed bytes */ __u64 ips_comp_ratio_dbytes; /* decompressed (or uncompressed) bytes */ __u8 ips_natt_type; __u8 ips_natt_reserved[3]; __u16 ips_natt_sport; __u16 ips_natt_dport; struct sockaddr *ips_natt_oa; __u16 ips_natt_oa_size; __u16 ips_natt_reserved2; #if 0 __u32 ips_sens_dpd; __u8 ips_sens_sens_level; __u8 ips_sens_sens_len; __u64 *ips_sens_sens_bitmap; __u8 ips_sens_integ_level; __u8 ips_sens_integ_len; __u64 *ips_sens_integ_bitmap; #endif struct ipsec_alg_enc *ips_alg_enc; struct ipsec_alg_auth *ips_alg_auth; int ocf_in_use; int64_t ocf_cryptoid; # define IPSEC_REFALLOC 0 # define IPSEC_REFINTERN 1 # define IPSEC_REFSAADD 2 # define IPSEC_REFOTHER 3 # define IPSEC_REFPROC 4 # define IPSEC_REFTX 5 # define IPSEC_REFRX 6 # define IPSEC_REFSA 7 #if 0 /* IPSEC_SA_RECOUNT_DEBUG */ /* * define IPSEC_SA_RECOUNT_DEBUG to track recounts by use, makes * it a lot easier to determine problems with refcount and SA freeing */ # define IPSEC_SA_RECOUNT_DEBUG 1 unsigned char ips_track[IPSEC_REFSA + 1]; struct ipsec_sa *ips_raw; #endif }; struct IPsecSArefSubTable { struct ipsec_sa *entry[IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES]; }; struct ipsec_sadb { struct IPsecSArefSubTable *refTable[IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES]; IPsecSAref_t refFreeList[IPSEC_SA_REF_FREELIST_NUM_ENTRIES]; int refFreeListHead; int refFreeListTail; IPsecSAref_t refFreeListCont; IPsecSAref_t said_hash[SADB_HASHMOD]; spinlock_t sadb_lock; }; extern struct ipsec_sadb ipsec_sadb; extern int ipsec_sadb_init(void); extern struct ipsec_sa *ipsec_sa_alloc(int *error); /* pass in error var by pointer */ extern int ipsec_sa_free(struct ipsec_sa *ips); #define ipsec_sa_get(ips, type) __ipsec_sa_get(ips, __FUNCTION__, __LINE__, \ type) extern struct ipsec_sa * __ipsec_sa_get(struct ipsec_sa *ips, const char *func, int line, int type); #define ipsec_sa_put(ips, type) __ipsec_sa_put(ips, __FUNCTION__, __LINE__, \ type) extern void __ipsec_sa_put(struct ipsec_sa *ips, const char *func, int line, int type); extern int ipsec_sa_add(struct ipsec_sa *ips); extern void ipsec_sa_rm(struct ipsec_sa *ips); extern int ipsec_sadb_cleanup(__u8 proto); extern int ipsec_sadb_free(void); extern int ipsec_sa_wipe(struct ipsec_sa *ips); extern int ipsec_sa_intern(struct ipsec_sa *ips); extern struct ipsec_sa *ipsec_sa_getbyref(IPsecSAref_t ref, int type); extern void ipsec_sa_untern(struct ipsec_sa *ips); #endif /* __KERNEL__ */ enum ipsec_direction { ipsec_incoming = 1, ipsec_outgoing = 2 }; #define _IPSEC_SA_H_ #endif /* _IPSEC_SA_H_ */ libreswan-3.32/linux/include/libreswan/ipsec_sha1.h000066400000000000000000000012311365625662500224040ustar00rootroot00000000000000/* * Here is the original comment from the distribution: SHA-1 in C By Steve Reid 100% Public Domain * Adapted for use by the IPSEC code by John Ioannidis */ #ifndef _IPSEC_SHA1_H_ #define _IPSEC_SHA1_H_ #ifdef __KERNEL__ # include #endif typedef struct { __u32 state[SHA1_DIGEST_SIZE / 4]; __u32 count[2]; __u8 buffer[SHA1_BLOCK_SIZE]; } SHA1_CTX; void SHA1Transform(__u32 state[5], __u8 buffer[SHA1_BLOCK_SIZE]); void SHA1Init(void *context); void SHA1Update(void *context, unsigned char *data, __u32 len); void SHA1Final(unsigned char digest[SHA1_DIGEST_SIZE], void *context); #endif /* _IPSEC_SHA1_H_ */ libreswan-3.32/linux/include/libreswan/ipsec_stats.h000066400000000000000000000023761365625662500227210ustar00rootroot00000000000000/* * @(#) definition of ipsec_stats structure * * Copyright (C) 2001 Richard Guy Briggs * and Michael Richardson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ /* * This file describes the errors/statistics that Libreswan collects. */ #ifndef _IPSEC_STATS_H_ struct ipsec_stats { __u32 ips_alg_errs; /* number of algorithm errors */ __u32 ips_auth_errs; /* # of authentication errors */ __u32 ips_encsize_errs; /* # of encryption size errors*/ __u32 ips_encpad_errs; /* # of encryption pad errors*/ __u32 ips_replaywin_errs; /* # of pkt sequence errors */ }; #define _IPSEC_STATS_H_ #endif /* _IPSEC_STATS_H_ */ libreswan-3.32/linux/include/libreswan/ipsec_sysctl.h000066400000000000000000000007351365625662500231010ustar00rootroot00000000000000#ifndef LIBRESWAN_SYSCTL_H #define LIBRESWAN_SYSCTL_H extern int debug_ah; extern int debug_esp; extern int debug_xform; extern int debug_eroute; extern int debug_spi; extern int debug_netlink; extern int debug_radij; extern int debug_rcv; extern int debug_tunnel; extern int debug_xmit; extern int debug_mast; extern int sysctl_ip_default_ttl; extern int sysctl_ipsec_inbound_policy_check; extern int sysctl_ipsec_debug_ipcomp; extern int sysctl_ipsec_debug_verbose; #endif libreswan-3.32/linux/include/libreswan/ipsec_tunnel.h000066400000000000000000000111771365625662500230670ustar00rootroot00000000000000/* * IPSEC tunneling code * Copyright (C) 1996, 1997 John Ioannidis. * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Richard Guy Briggs. * Copyright (C) 2006 Michael Richardson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ # define DEV_QUEUE_XMIT(skb, device, pri) { \ (skb)->dev = (device); \ neigh_compat_output(skb); \ /* (skb)->dst->output(skb); */ \ } # define ICMP_SEND(skb_in, type, code, info, dev) \ icmp_send((skb_in), (type), (code), htonl(info)) # define IP_SEND(skb, dev) \ ip_send(skb); #if defined(KLIPS) #define lsw_ip_hdr_version(ixirs) (((struct iphdr *) (ixirs)->iph)->version) #define lsw_ip4_hdr(ixirs) ((struct iphdr *) (ixirs)->iph) #define lsw_ip6_hdr(ixirs) ((struct ipv6hdr *) (ixirs)->iph) /* * Heavily based on drivers/net/new_tunnel.c. Lots * of ideas also taken from the 2.1.x version of drivers/net/shaper.c */ struct ipsectunnelconf { uint32_t cf_cmd; union { char cfu_name[12]; } cf_u; #define cf_name cf_u.cfu_name }; #define IPSEC_SET_DEV (SIOCDEVPRIVATE) #define IPSEC_DEL_DEV (SIOCDEVPRIVATE + 1) #define IPSEC_CLR_DEV (SIOCDEVPRIVATE + 2) #endif /* This is used for KLIPS as well as NETKEY */ #define IPSEC_UDP_ENCAP_CONVERT (SIOCDEVPRIVATE + 3) #ifdef __KERNEL__ #include #ifndef KERNEL_VERSION # define KERNEL_VERSION(x, y, z) (((x) << 16) + ((y) << 8) + (z)) #endif #define IPSECPRIV_MAGIC 0x15ECC0DE struct ipsecpriv { uint32_t magic; struct sk_buff_head sendq; struct net_device *dev; struct wait_queue *wait_queue; int vifnum; char locked; int (*hard_start_xmit) (struct sk_buff *skb, struct net_device *dev); #ifdef HAVE_NETDEV_HEADER_OPS const struct header_ops *header_ops; #else int (*hard_header) (struct sk_buff *skb, struct net_device *dev, unsigned short type, void *daddr, void *saddr, unsigned len); int (*rebuild_header)(struct sk_buff *skb); void (*header_cache_update)(struct hh_cache *hh, struct net_device *dev, unsigned char * haddr); #endif #ifdef USE_NETDEV_OPS const struct net_device_ops *saved_netdev_ops; struct net_device_ops netdev_ops; #endif int (*set_mac_address)(struct net_device *dev, void *addr); struct net_device_stats *(*get_stats)(struct net_device *dev); struct net_device_stats mystats; int mtu; /* What is the desired MTU? */ }; static inline struct ipsecpriv *netdev_to_ipsecpriv( const struct net_device *dev) { struct ipsecpriv *iprv = netdev_priv(dev); BUG_ON(!iprv); BUG_ON(iprv->magic != IPSECPRIV_MAGIC); return iprv; } extern char ipsec_tunnel_c_version[]; extern struct net_device *ipsecdevices[IPSEC_NUM_IFMAX]; extern int ipsecdevices_max; int ipsec_tunnel_init_devices(void); /* void */ int ipsec_tunnel_cleanup_devices(void); extern /* void */ int ipsec_init(void); extern int ipsec_tunnel_start_xmit(struct sk_buff *skb, struct net_device *dev); extern struct net_device *ipsec_get_device(int inst); extern int debug_tunnel; extern int sysctl_ipsec_debug_verbose; extern int lsw_ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, int target, unsigned short *fragoff); #ifdef CONFIG_KLIPS_IPV6 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34) # define ICMP6_SEND(skb_in, type, code, info, dev) \ icmpv6_send((skb_in), (type), (code), htonl(info), (dev)) #else # define ICMP6_SEND(skb_in, type, code, info, dev) \ icmpv6_send((skb_in), (type), (code), htonl(info)) #endif #endif /* CONFIG_KLIPS_IPV6 */ #endif /* __KERNEL__ */ #define DB_TN_INIT 0x0001 #define DB_TN_PROCFS 0x0002 #define DB_TN_XMIT 0x0010 #define DB_TN_OHDR 0x0020 #define DB_TN_CROUT 0x0040 #define DB_TN_OXFS 0x0080 #define DB_TN_REVEC 0x0100 #define DB_TN_ENCAP 0x0200 extern int ipsec_tunnel_deletenum(int vifnum); extern int ipsec_tunnel_createnum(int vifnum); extern struct net_device *ipsec_tunnel_get_device(int vifnum); /* manage ipsec xmit state objects */ extern int ipsec_xmit_state_cache_init(void); extern void ipsec_xmit_state_cache_cleanup(void); struct ipsec_xmit_state *ipsec_xmit_state_new(struct net_device *dev); void ipsec_xmit_state_delete(struct ipsec_xmit_state *ixs); libreswan-3.32/linux/include/libreswan/ipsec_xform.h000066400000000000000000000167621365625662500227220ustar00rootroot00000000000000/* * Definitions relevant to IPSEC transformations * Copyright (C) 1996, 1997 John Ioannidis. * Copyright (C) 1998, 1999, 2000, 2001, 2017 Richard Guy Briggs * COpyright (C) 2003 Michael Richardson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #ifndef _IPSEC_XFORM_H_ #include #define XF_NONE 0 /* No transform set */ #define XF_IP4 1 /* IPv4 inside IPv4 */ #define XF_AHMD5 2 /* AH MD5 */ #define XF_AHSHA 3 /* AH SHA */ #define XF_ESP3DES 5 /* ESP DES3-CBC */ #define XF_AHHMACMD5 6 /* AH-HMAC-MD5 with opt replay prot */ #define XF_AHHMACSHA1 7 /* AH-HMAC-SHA1 with opt replay prot */ #define XF_ESP3DESMD5 9 /* triple DES, HMAC-MD-5, 128-bits of authentication */ #define XF_ESP3DESMD596 10 /* triple DES, HMAC-MD-5, 96-bits of authentication */ #define XF_ESPNULLMD596 12 /* NULL, HMAC-MD-5 with 96-bits of authentication */ #define XF_ESPNULLSHA196 13 /* NULL, HMAC-SHA-1 with 96-bits of authentication */ #define XF_ESP3DESSHA196 14 /* triple DES, HMAC-SHA-1, 96-bits of authentication */ #define XF_IP6 15 /* IPv6 inside IPv6 */ #define XF_COMPDEFLATE 16 /* IPCOMP deflate */ #define XF_COMPLZS 17 /* IPCOMP LZS */ #define XF_GET 124 /* Get SA current lifetimes */ /* * Manual connection support for modular algos (ipsec_alg) --Juanjo. */ #define XF_OTHER_ALG 125 /* define magic XF_ symbol for alg_infos */ #define XF_CLR 126 /* Clear SA table */ #define XF_DEL 127 /* Delete SA */ /* IPsec AH transform values * RFC 2407 * draft-ietf-ipsec-doi-tc-mib-02.txt */ /* why are these hardcoded here? See ipsec_policy.h for their enums -- Paul*/ /* ---------- These really need to go from here ------------------ */ #define AH_NONE 0 #define AH_MD5 2 #define AH_SHA 3 /* draft-ietf-ipsec-ciph-aes-cbc-03.txt */ #define AH_SHA2_256 5 #define AH_SHA2_384 6 #define AH_SHA2_512 7 #define AH_RIPEMD 8 #define AH_AES 9 #define AH_RSA 10 /* RFC4359 */ #define AH_AES_128_GMAC 11 /* RFC4543 [Errata1821] */ #define AH_AES_192_GMAC 12 /* RFC4543 [Errata1821] */ #define AH_AES_256_GMAC 13 /* RFC4543 [Errata1821] */ #define AH_NULL 251 #define AH_SHA2_256_TRUNC 252 /* used for broken linux kernel behaviour */ #define AH_MAX 255 /* note Authentication Algorithm (Value 5) Reference: [RFC2407] has * two octets but IPSEC AH Transform Identifiers has one octet! */ /* IPsec ESP transform values */ #define ESP_NONE 0 #define ESP_DES_IV64 1 #define ESP_DES 2 /* obsoleted */ #define ESP_3DES 3 #define ESP_RC5 4 #define ESP_IDEA 5 #define ESP_CAST 6 #define ESP_BLOWFISH 7 /* obsoleted */ #define ESP_3IDEA 8 #define ESP_DES_IV32 9 #define ESP_RC4 10 #define ESP_NULL 11 #define ESP_AES 12 /* was draft-ietf-ipsec-ciph-aes-cbc-02.txt, now RFC-3602 */ #define ESP_AES_CTR 13 #define ESP_AES_CCM_A 14 #define ESP_AES_CCM_B 15 #define ESP_AES_CCM_C 16 #define ESP_ID17_UNASSIGNED 17 #define ESP_AES_GCM_A 18 #define ESP_AES_GCM_B 19 #define ESP_AES_GCM_C 20 #define ESP_SEED_CBC 21 #define ESP_CAMELLIA 22 #define ESP_NULL_AUTH_AES_GMAC 23 /* [RFC4543][Errata1821] */ /* 24 - 248 Unassigned */ #define ESP_MARS 249 #define ESP_RC6 250 #define ESP_SERPENT 252 #define ESP_TWOFISH 253 #define ESP_MAX 255 /* one octet, not two */ /* IPCOMP transform values */ #define IPCOMP_NONE 0 #define IPCOMP_OUI 1 #define IPCOMP_DEFLATE 2 #define IPCOMP_LZS 3 #define IPCOMP_V42BIS 4 #define XFT_AUTH 0x0001 #define XFT_CONF 0x0100 #define PROTO2TXT(x) \ (x) == IPPROTO_AH ? "AH" : \ (x) == IPPROTO_ESP ? "ESP" : \ (x) == IPPROTO_IPIP ? "IPIP" : \ (x) == IPPROTO_COMP ? "COMP" : \ "UNKNOWN_proto" /* BEWARE: result may be in a static buffer */ static inline const char *enc_name_id(unsigned id) { static char buf[16]; snprintf(buf, sizeof(buf), "_ID%d", id); return buf; } /* BEWARE: result may be in a static buffer */ static inline const char *auth_name_id(unsigned id) { static char buf[16]; snprintf(buf, sizeof(buf), "_ID%d", id); return buf; } #define IPS_XFORM_NAME(x) \ PROTO2TXT((x)->ips_said.proto), \ (x)->ips_said.proto == IPPROTO_COMP ? \ ((x)->ips_encalg == SADB_X_CALG_NONE ? "_NONE" : \ (x)->ips_encalg == SADB_X_CALG_DEFLATE ? "_DEFLATE" : \ (x)->ips_encalg == SADB_X_CALG_LZS ? "_LZS" : \ "_UNKNOWN_comp") : \ (x)->ips_encalg == ESP_NONE ? "" : \ (x)->ips_encalg == ESP_NULL ? "_NULL" : \ /* ESP_DES left out on purpose */ \ (x)->ips_encalg == ESP_3DES ? "_3DES" : \ (x)->ips_encalg == ESP_AES ? "_AES" : \ (x)->ips_encalg == ESP_SERPENT ? "_SERPENT" : \ (x)->ips_encalg == ESP_TWOFISH ? "_TWOFISH" : \ enc_name_id((x)->ips_encalg) /* "_UNKNOWN_encr" */, \ (x)->ips_authalg == AH_NONE ? "" : \ (x)->ips_authalg == AH_MD5 ? "_HMAC_MD5" : \ (x)->ips_authalg == AH_SHA ? "_HMAC_SHA1" : \ (x)->ips_authalg == AH_SHA2_256 ? "_HMAC_SHA2_256" : \ (x)->ips_authalg == AH_SHA2_384 ? "_HMAC_SHA2_384" : \ (x)->ips_authalg == AH_SHA2_512 ? "_HMAC_SHA2_512" : \ auth_name_id((x)->ips_authalg) /* "_UNKNOWN_auth" */ \ #ifdef __KERNEL__ #include struct ipsec_rcv_state; struct ipsec_xmit_state; struct xform_functions { u8 protocol; enum ipsec_rcv_value (*rcv_checks)(struct ipsec_rcv_state *irs, struct sk_buff *skb); enum ipsec_rcv_value (*rcv_decrypt)(struct ipsec_rcv_state *irs); enum ipsec_rcv_value (*rcv_setup_auth)(struct ipsec_rcv_state *irs, struct sk_buff *skb, __u32 *replay, unsigned char **authenticator); enum ipsec_rcv_value (*rcv_calc_auth)(struct ipsec_rcv_state *irs, struct sk_buff *skb); enum ipsec_xmit_value (*xmit_setup)(struct ipsec_xmit_state *ixs); enum ipsec_xmit_value (*xmit_encrypt)(struct ipsec_xmit_state *ixs); enum ipsec_xmit_value (*xmit_setup_auth)(struct ipsec_xmit_state *ixs, struct sk_buff *skb, __u32 *replay, unsigned char **authenticator); enum ipsec_xmit_value (*xmit_calc_auth)(struct ipsec_xmit_state *ixs, struct sk_buff *skb); int xmit_headroom; int xmit_needtailroom; }; #endif /* __KERNEL__ */ extern void ipsec_dmp(char *s, caddr_t bb, int len); #define _IPSEC_XFORM_H_ #endif /* _IPSEC_XFORM_H_ */ libreswan-3.32/linux/include/libreswan/ipsec_xmit.h000066400000000000000000000135401365625662500225370ustar00rootroot00000000000000/* * IPSEC tunneling code * Copyright (C) 1996, 1997 John Ioannidis. * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Richard Guy Briggs. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include "libreswan/ipsec_sa.h" #ifdef CONFIG_KLIPS_OCF #include #endif enum ipsec_xmit_value { IPSEC_XMIT_STOLEN=2, IPSEC_XMIT_PASS=1, IPSEC_XMIT_OK=0, IPSEC_XMIT_ERRMEMALLOC=-1, IPSEC_XMIT_ESP_BADALG=-2, IPSEC_XMIT_BADPROTO=-3, IPSEC_XMIT_ESP_PUSHPULLERR=-4, IPSEC_XMIT_BADLEN=-5, IPSEC_XMIT_AH_BADALG=-6, IPSEC_XMIT_SAIDNOTFOUND=-7, IPSEC_XMIT_SAIDNOTLIVE=-8, IPSEC_XMIT_REPLAYROLLED=-9, IPSEC_XMIT_LIFETIMEFAILED=-10, IPSEC_XMIT_CANNOTFRAG=-11, IPSEC_XMIT_MSSERR=-12, IPSEC_XMIT_ERRSKBALLOC=-13, IPSEC_XMIT_ENCAPFAIL=-14, IPSEC_XMIT_NODEV=-15, IPSEC_XMIT_NOPRIVDEV=-16, IPSEC_XMIT_NOPHYSDEV=-17, IPSEC_XMIT_NOSKB=-18, IPSEC_XMIT_NOIPV6=-19, IPSEC_XMIT_NOIPOPTIONS=-20, IPSEC_XMIT_TTLEXPIRED=-21, IPSEC_XMIT_BADHHLEN=-22, IPSEC_XMIT_PUSHPULLERR=-23, IPSEC_XMIT_ROUTEERR=-24, IPSEC_XMIT_RECURSDETECT=-25, IPSEC_XMIT_IPSENDFAILURE=-26, IPSEC_XMIT_ESPUDP=-27, IPSEC_XMIT_ESPUDP_BADTYPE=-28, IPSEC_XMIT_PENDING=-29, }; /* * state machine states */ #define IPSEC_XSM_INIT1 0 /* make it easy, starting state is 0 */ #define IPSEC_XSM_INIT2 1 #define IPSEC_XSM_ENCAP_INIT 2 #define IPSEC_XSM_ENCAP_SELECT 3 #define IPSEC_XSM_ESP 4 #define IPSEC_XSM_ESP_AH 5 #define IPSEC_XSM_AH 6 #define IPSEC_XSM_IPIP 7 #define IPSEC_XSM_IPCOMP 8 #define IPSEC_XSM_CONT 9 #define IPSEC_XSM_DONE 100 struct ipsec_xmit_state { struct sk_buff *skb; /* working skb pointer */ struct sk_buff *pre_ipcomp_skb; /* skb before ipcomp was attempted */ struct net_device *dev; /* working dev pointer */ struct ipsecpriv *iprv; /* Our device' private space */ struct mastpriv *mprv; struct sk_buff *oskb; /* Original skb pointer */ struct net_device_stats *stats; /* This device's statistics */ void *iph; /* Our new IP header */ ip_address orgedst; /* 1st SG's IP address */ int iphlen; /* IP header length */ int pyldsz; /* upper protocol payload size */ int headroom; int tailroom; int authlen; int max_headroom; /* The extra header space needed */ int max_tailroom; /* The extra stuffing needed */ int ll_headroom; /* The extra link layer hard_header space needed */ int tot_headroom; /* The total header space needed */ int tot_tailroom; /* The totalstuffing needed */ __u8 *saved_header; /* saved copy of the hard header */ unsigned short sport, dport; struct sockaddr_encap matcher; /* eroute search key */ struct eroute *eroute; struct ipsec_sa *ipsp; /* ipsec_sa pointers */ char sa_txt[SATOT_BUF]; size_t sa_len; int hard_header_stripped; /* has the hard header been removed yet? */ int hard_header_len; struct net_device *physdev; short physmtu; short cur_mtu; /* copy of prv->mtu, cause prv may == NULL */ short mtudiff; __u8 next_header; /* protocol of the nested header */ struct rtable *route; ip_said outgoing_said; int pass; uint32_t eroute_pid; struct ipsec_sa ips; uint8_t natt_type; uint8_t natt_head; uint16_t natt_sport; uint16_t natt_dport; /* * xmit flags */ uint16_t mast_mode : 1; uint16_t set_dst : 1; /* if carrying IPv6, IPPROTO_IPV6, else IPPROTO_IPIP */ uint8_t ipip_proto; /* * xmit state machine use */ void (*xsm_complete)(struct ipsec_xmit_state *ixs, enum ipsec_xmit_value stat); int state; int next_state; #ifdef CONFIG_KLIPS_ALG struct ipsec_alg_auth *ixt_a; struct ipsec_alg_enc *ixt_e; #endif #ifdef CONFIG_KLIPS_ESP struct esphdr *espp; unsigned char *idat; #endif /* !CONFIG_KLIPS_ESP */ int blocksize; int ilen, len; unsigned char *dat; __u8 frag_off, tos; __u16 ttl, check; }; extern enum ipsec_xmit_value ipsec_xmit_sanity_check_ipsec_dev( struct ipsec_xmit_state *ixs); extern enum ipsec_xmit_value ipsec_xmit_sanity_check_mast_dev( struct ipsec_xmit_state *ixs); extern enum ipsec_xmit_value ipsec_xmit_sanity_check_skb( struct ipsec_xmit_state *ixs); extern enum ipsec_xmit_value ipsec_xmit_encap_bundle( struct ipsec_xmit_state *ixs); extern void ipsec_xsm(struct ipsec_xmit_state *ixs); #ifdef HAVE_KMEM_CACHE_T extern kmem_cache_t *ipsec_ixs_cache; #else extern struct kmem_cache *ipsec_ixs_cache; #endif extern int ipsec_ixs_max; extern atomic_t ipsec_ixs_cnt; extern void ipsec_extract_ports(struct sk_buff *skb, unsigned char nexthdr, int nexthdroff, struct sockaddr_encap * er); extern enum ipsec_xmit_value ipsec_xmit_send(struct ipsec_xmit_state *ixs); extern enum ipsec_xmit_value ipsec_nat_encap(struct ipsec_xmit_state *ixs); extern enum ipsec_xmit_value ipsec_tunnel_send(struct ipsec_xmit_state *ixs); extern void ipsec_xmit_cleanup(struct ipsec_xmit_state *ixs); extern int ipsec_xmit_trap_count; extern int ipsec_xmit_trap_sendcount; extern int debug_xmit; extern int debug_mast; #define ipsec_xmit_dmp(_x, _y, _z) { \ if (debug_xmit && sysctl_ipsec_debug_verbose) \ ipsec_dmp_block(_x, _y, _z); \ } extern int sysctl_ipsec_debug_verbose; extern int sysctl_ipsec_icmp; extern int sysctl_ipsec_tos; libreswan-3.32/linux/include/libreswan/mast.h000066400000000000000000000015631365625662500213410ustar00rootroot00000000000000struct mast_callbacks { int (*packet_encap)(struct device *mast, void *context, struct sk_buff *skb, int flowref); int (*link_inquire)(struct device *mast, void *context); }; struct device *mast_init(int family, struct mast_callbacks *callbacks, unsigned int flags, unsigned int desired_unit, unsigned int max_flowref, void *context); int mast_destroy(struct device *mast); int mast_recv(struct device *mast, struct sk_buff *skb, int flowref); /* free this skb as being useless, increment failure count. */ int mast_toast(struct device *mast, struct sk_buff *skb, int flowref); int mast_linkstat(struct device *mast, int flowref, int status); int mast_setreference(struct device *mast, int defaultSA); int mast_setneighbor(struct device *mast, struct sockaddr *source, struct sockaddr *destination, int flowref); libreswan-3.32/linux/include/libreswan/passert.h000066400000000000000000000040011365625662500220440ustar00rootroot00000000000000/* * Panic, for libreswan. * * Copyright (C) 1998-2002 D. Hugh Redelmeier. * Copyright (C) 2003 Michael Richardson * Copyright (C) 2013 Paul Wouters * Copyright (C) 2015-2016 Andrew Cagney * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. */ #include /* for sig_atomic_t */ #include "err.h" #include "libreswan.h" #ifndef _LIBRESWAN_PASSERT_H #define _LIBRESWAN_PASSERT_H /* our versions of assert: log result */ extern void lsw_passert_fail(const char *file_str, unsigned long line_no, const char *func_str, const char *fmt, ...) NEVER_RETURNS PRINTF_LIKE(4); /* * http://stackoverflow.com/questions/8487986/file-macro-shows-full-path#8488201 * * It is tempting to tweak the .c.o line so that it passes in the * required value. */ #ifndef PASSERT_BASENAME #define PASSERT_BASENAME (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) #endif #define PASSERT_FAIL(FMT, ...) \ lsw_passert_fail(PASSERT_BASENAME, __LINE__, \ __func__, FMT, __VA_ARGS__) #define passert(ASSERTION) { \ /* wrapping ASSERTION in parens suppresses -Wparen */ \ bool assertion__ = ASSERTION; /* no parens */ \ if (!assertion__) { \ PASSERT_FAIL("%s", #ASSERTION); \ } \ } /* evaluate x exactly once; assert that err_t result is NULL; */ #define happy(x) { \ err_t ugh = x; \ if (ugh != NULL) { \ PASSERT_FAIL("%s", ugh); \ } \ } #endif /* _LIBRESWAN_PASSERT_H */ libreswan-3.32/linux/include/libreswan/pfkey.h000066400000000000000000000232631365625662500215140ustar00rootroot00000000000000/* * Libreswan specific PF_KEY headers * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs. * Copyright (C) 2006-2007 Michael Richardson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef __NET_IPSEC_PF_KEY_H #define __NET_IPSEC_PF_KEY_H #include "pfkeyv2.h" #include #ifdef __KERNEL__ extern struct proto_ops pfkey_proto_ops; typedef struct sock pfkey_sock; extern int debug_pfkey; extern /* void */ int pfkey_init(void); extern /* void */ int pfkey_cleanup(void); extern int pfkey_registered_show(struct seq_file *seq, void *offset); extern int pfkey_supported_show(struct seq_file *seq, void *offset); extern int pfkey_show(struct seq_file *seq, void *offset); #ifdef HAVE_USER_NS extern uint32_t pfkey_kuid_to_uid(kuid_t kuid); #endif struct socket_list { struct socket *socketp; struct socket_list *next; }; extern int pfkey_list_insert_socket(struct socket *, struct socket_list **); extern struct socket_list *pfkey_open_sockets; extern struct socket_list *pfkey_registered_sockets[]; struct ipsec_alg_supported { uint16_t ias_exttype; uint8_t ias_id; uint8_t ias_ivlen; uint16_t ias_keyminbits; uint16_t ias_keymaxbits; const char *ias_name; }; extern struct supported_list *pfkey_supported_list[]; struct supported_list { struct ipsec_alg_supported *supportedp; struct supported_list *next; }; extern int pfkey_list_insert_supported(struct ipsec_alg_supported *, struct supported_list **); extern int pfkey_list_remove_supported(struct ipsec_alg_supported *, struct supported_list **); struct sockaddr_key { uint16_t key_family; /* PF_KEY */ uint16_t key_pad; /* not used */ uint32_t key_pid; /* process ID */ }; struct pfkey_extracted_data { struct ipsec_sa *ips; struct ipsec_sa *ips2; struct eroute *eroute; int outif; IPsecSAref_t sarefme; IPsecSAref_t sarefhim; }; /* forward reference */ struct sadb_ext; struct sadb_msg; struct sockaddr; struct sadb_comb; struct sadb_sadb; struct sadb_alg; extern int pfkey_alloc_eroute(struct eroute **eroute); extern int pfkey_sa_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr); extern int pfkey_lifetime_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr); extern int pfkey_address_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr); extern int pfkey_key_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr); extern int pfkey_ident_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr); extern int pfkey_sens_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr); extern int pfkey_prop_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr); extern int pfkey_supported_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr); extern int pfkey_spirange_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr); extern int pfkey_x_kmprivate_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr); extern int pfkey_x_satype_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr); extern int pfkey_x_debug_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr); extern int pfkey_upmsg(struct socket *, struct sadb_msg *); extern int pfkey_upmsgsk(struct sock *, struct sadb_msg *); extern int pfkey_expire(struct ipsec_sa *, int); extern int pfkey_acquire(struct ipsec_sa *); #endif /* __KERNEL__ */ extern uint8_t satype2proto(uint8_t satype); extern uint8_t proto2satype(uint8_t proto); extern char *satype2name(uint8_t satype); struct key_opt { uint32_t key_pid; /* process ID */ struct sock *sk; }; #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) # define key_pid(sk) ((struct key_opt*)&((sk)->sk_user_data))->key_pid #else # define key_pid(sk) ((struct key_opt*)&((sk)->sk_protinfo))->key_pid #endif /* XXX-mcr this is not an alignment, this is because the count is in 64-bit * words. */ #define IPSEC_PFKEYv2_ALIGN (sizeof(uint64_t) / sizeof(uint8_t)) #define BITS_PER_OCTET 8 #define OCTETBITS 8 #define PFKEYBITS 64 #define DIVUP(x, y) (((x) + (y) - 1) / (y)) /* divide, rounding upwards */ #define ALIGN_N(x, y) (DIVUP((x), (y)) * (y)) /* align on y boundary */ #define IPSEC_PFKEYv2_LEN(x) ((x) * IPSEC_PFKEYv2_ALIGN) #define IPSEC_PFKEYv2_WORDS(x) (DIVUP((x), IPSEC_PFKEYv2_ALIGN)) #define PFKEYv2_MAX_MSGSIZE 4096 /* * PF_KEYv2 permitted and required extensions in and out bitmaps */ struct pf_key_ext_parsers_def { int (*parser)(struct sadb_ext*); char *parser_name; }; enum pfkey_ext_required { EXT_BITS_IN=0, EXT_BITS_OUT=1 }; enum pfkey_ext_perm { EXT_BITS_PERM=0, EXT_BITS_REQ=1 }; typedef uint64_t pfkey_ext_track; static inline void pfkey_mark_extension(enum sadb_extension_t exttype, pfkey_ext_track *exten_track) { *exten_track |= (1 << exttype); } extern int pfkey_extensions_missing(enum pfkey_ext_required inout, enum sadb_msg_t sadb_operation, pfkey_ext_track extensions_seen); extern int pfkey_required_extension(enum pfkey_ext_required inout, enum sadb_msg_t sadb_operation, enum sadb_extension_t exttype); extern int pfkey_permitted_extension(enum pfkey_ext_required inout, enum sadb_msg_t sadb_operation, enum sadb_extension_t exttype); extern void pfkey_extensions_init(struct sadb_ext *extensions[]); extern void pfkey_extensions_free(struct sadb_ext *extensions[]); extern void pfkey_msg_free(struct sadb_msg **pfkey_msg); extern int pfkey_msg_parse(struct sadb_msg *pfkey_msg, struct pf_key_ext_parsers_def *ext_parsers[], struct sadb_ext **extensions, int dir); extern int pfkey_register_reply(int satype, struct sadb_msg *sadb_msg); /* * PF_KEYv2 build function prototypes */ int pfkey_msg_hdr_build(struct sadb_ext **pfkey_ext, uint8_t msg_type, uint8_t satype, uint8_t msg_errno, uint32_t seq, uint32_t pid); int pfkey_sa_ref_build(struct sadb_ext ** pfkey_ext, uint16_t exttype, uint32_t spi, /* in network order */ uint8_t replay_window, uint8_t sa_state, uint8_t auth, uint8_t encrypt, uint32_t flags, uint32_t /*IPsecSAref_t*/ ref); int pfkey_sa_build(struct sadb_ext ** pfkey_ext, uint16_t exttype, uint32_t spi, /* in network order */ uint8_t replay_window, uint8_t sa_state, uint8_t auth, uint8_t encrypt, uint32_t flags); extern int pfkey_saref_build(struct sadb_ext **pfkey_ext, IPsecSAref_t in, IPsecSAref_t out); int pfkey_lifetime_build(struct sadb_ext ** pfkey_ext, uint16_t exttype, uint32_t allocations, uint64_t bytes, uint64_t addtime, uint64_t usetime, uint32_t packets); int pfkey_address_build(struct sadb_ext **pfkey_ext, uint16_t exttype, uint8_t proto, uint8_t prefixlen, struct sockaddr *address); int pfkey_key_build(struct sadb_ext **pfkey_ext, uint16_t exttype, uint16_t key_bits, unsigned char *key); int pfkey_ident_build(struct sadb_ext **pfkey_ext, uint16_t exttype, uint16_t ident_type, uint64_t ident_id, uint8_t ident_len, char *ident_string); #ifdef __KERNEL__ extern int pfkey_nat_t_new_mapping(struct ipsec_sa *, struct sockaddr *, __u16); extern int pfkey_x_nat_t_type_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr); extern int pfkey_x_nat_t_port_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr); #endif /* __KERNEL__ */ int pfkey_x_nat_t_type_build(struct sadb_ext **pfkey_ext, uint8_t type); int pfkey_x_nat_t_port_build(struct sadb_ext **pfkey_ext, uint16_t exttype, uint16_t port); int pfkey_sens_build(struct sadb_ext **pfkey_ext, uint32_t dpd, uint8_t sens_level, uint8_t sens_len, uint64_t *sens_bitmap, uint8_t integ_level, uint8_t integ_len, uint64_t *integ_bitmap); int pfkey_x_protocol_build(struct sadb_ext **, uint8_t); int pfkey_prop_build(struct sadb_ext **pfkey_ext, uint8_t replay, unsigned int comb_num, struct sadb_comb *comb); int pfkey_supported_build(struct sadb_ext **pfkey_ext, uint16_t exttype, unsigned int alg_num, struct sadb_alg *alg); int pfkey_x_satype_build(struct sadb_ext **pfkey_ext, uint8_t satype); int pfkey_x_debug_build(struct sadb_ext **pfkey_ext, uint32_t tunnel, uint32_t netlink, uint32_t xform, uint32_t eroute, uint32_t spi, uint32_t radij, uint32_t esp, uint32_t ah, uint32_t rcv, uint32_t pfkey, uint32_t ipcomp, uint32_t verbose); int pfkey_msg_build(struct sadb_msg **pfkey_msg, struct sadb_ext *extensions[], int dir); /* in pfkey_v2_debug.c - routines to decode numbers -> strings */ const char *pfkey_v2_sadb_ext_string(int extnum); const char *pfkey_v2_sadb_type_string(unsigned sadb_type); struct sadb_builds { struct k_sadb_sa sa_base; }; int pfkey_sa_builds(struct sadb_ext **pfkey_ext, struct sadb_builds sab); extern int pfkey_outif_build(struct sadb_ext **pfkey_ext, uint16_t outif); #endif /* __NET_IPSEC_PF_KEY_H */ libreswan-3.32/linux/include/libreswan/pfkey_debug.h000066400000000000000000000036361365625662500226640ustar00rootroot00000000000000/* pf_key debugging facility * definitions: linux/net/ipsec/pfkey_v2_parse.c, lib/libbsdpfkey/pfkey.c * * Copyright (C) 1998-2002 D. Hugh Redelmeier. * Copyright (C) 2003 Michael Richardson * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. */ #ifndef _FREESWAN_PFKEY_DEBUG_H #define _FREESWAN_PFKEY_DEBUG_H /* * Debugging levels for pfkey_lib_debug */ #define PF_KEY_DEBUG_PARSE_NONE 0 #define PF_KEY_DEBUG_PARSE_PROBLEM 1 #define PF_KEY_DEBUG_PARSE_STRUCT 2 #define PF_KEY_DEBUG_PARSE_FLOW 4 #define PF_KEY_DEBUG_BUILD 8 #define PF_KEY_DEBUG_PARSE_MAX 15 extern unsigned int pfkey_lib_debug; /* bits selecting what to report */ #ifdef __KERNEL__ /* note, kernel version ignores pfkey levels */ # define DEBUGGING(level, args ...) \ KLIPS_PRINT(debug_pfkey, "klips_debug:" args) # define ERROR(args ...) printk(KERN_ERR "klips:" args) #else extern libreswan_keying_debug_func_t pfkey_debug_func; extern libreswan_keying_debug_func_t pfkey_error_func; #define DEBUGGING(level, args ...) { if (pfkey_lib_debug & (level)) { \ if (pfkey_debug_func != NULL) { \ (*pfkey_debug_func)("pfkey_lib_debug:" args); \ } else { \ printf("pfkey_lib_debug:" args); \ } } } #define ERROR(args ...) { \ if (pfkey_error_func != NULL) \ (*pfkey_error_func)("pfkey_lib_debug:" args); \ } # define MALLOC(size) malloc(size) # define FREE(obj) free(obj) #endif #endif libreswan-3.32/linux/include/libreswan/pfkeyv2.h000066400000000000000000000265211365625662500217640ustar00rootroot00000000000000/* RFC 2367 PF_KEY Key Management API July 1998 Appendix D: Sample Header File This file defines structures and symbols for the PF_KEY Version 2 key management interface. It was written at the U.S. Naval Research Laboratory. This file is in the public domain. The authors ask that you leave this credit intact on any copies of this file. */ #ifndef __PFKEY_V2_H #define __PFKEY_V2_H 1 #include #define PF_KEY_V2 2 #define PFKEYV2_REVISION 199806L enum sadb_msg_t { K_SADB_RESERVED=SADB_RESERVED, K_SADB_GETSPI=SADB_GETSPI, K_SADB_UPDATE=SADB_UPDATE, K_SADB_ADD=SADB_ADD, K_SADB_DELETE=SADB_DELETE, K_SADB_GET=SADB_GET, K_SADB_ACQUIRE=SADB_ACQUIRE, K_SADB_REGISTER=SADB_REGISTER, K_SADB_EXPIRE=SADB_EXPIRE, K_SADB_FLUSH=SADB_FLUSH, K_SADB_DUMP=SADB_DUMP, K_SADB_X_PROMISC=SADB_X_PROMISC, K_SADB_X_PCHANGE=SADB_X_PCHANGE, K_SADB_X_GRPSA=13, K_SADB_X_ADDFLOW=14, K_SADB_X_DELFLOW=15, K_SADB_X_DEBUG=16, K_SADB_X_NAT_T_NEW_MAPPING=17, K_SADB_X_PLUMBIF=18, K_SADB_X_UNPLUMBIF=19, K_SADB_MAX=19 }; #define SADB_X_GRPSA K_SADB_X_GRPSA #define SADB_X_ADDFLOW K_SADB_X_ADDFLOW #define SADB_X_DELFLOW K_SADB_X_DELFLOW #define SADB_X_DEBUG K_SADB_X_DEBUG #define SADB_X_PLUMBIF K_SADB_X_PLUMBIF #define SADB_X_UNPLUMBIF K_SADB_X_UNPLUMBIF struct k_sadb_sa { uint16_t sadb_sa_len; uint16_t sadb_sa_exttype; uint32_t sadb_sa_spi; uint8_t sadb_sa_replay; uint8_t sadb_sa_state; uint8_t sadb_sa_auth; uint8_t sadb_sa_encrypt; uint32_t sadb_sa_flags; uint32_t /*IPsecSAref_t*/ sadb_x_sa_ref; /* 32 bits */ uint8_t sadb_x_reserved[4]; } __attribute__((packed)); struct sadb_sa_v1 { uint16_t sadb_sa_len; uint16_t sadb_sa_exttype; uint32_t sadb_sa_spi; uint8_t sadb_sa_replay; uint8_t sadb_sa_state; uint8_t sadb_sa_auth; uint8_t sadb_sa_encrypt; uint32_t sadb_sa_flags; } __attribute__((packed)); struct sadb_x_satype { uint16_t sadb_x_satype_len; uint16_t sadb_x_satype_exttype; uint8_t sadb_x_satype_satype; uint8_t sadb_x_satype_reserved[3]; } __attribute__((packed)); struct sadb_x_debug { uint16_t sadb_x_debug_len; uint16_t sadb_x_debug_exttype; uint32_t sadb_x_debug_tunnel; uint32_t sadb_x_debug_netlink; uint32_t sadb_x_debug_xform; uint32_t sadb_x_debug_eroute; uint32_t sadb_x_debug_spi; uint32_t sadb_x_debug_radij; uint32_t sadb_x_debug_esp; uint32_t sadb_x_debug_ah; uint32_t sadb_x_debug_rcv; uint32_t sadb_x_debug_pfkey; uint32_t sadb_x_debug_ipcomp; uint32_t sadb_x_debug_verbose; uint8_t sadb_x_debug_reserved[4]; } __attribute__((packed)); /* * a plumbif extension can appear in * - a plumbif message to create the interface. * - a unplumbif message to delete the interface. * - a sadb add/replace to indicate which interface * a decrypted packet should emerge on. * * the create/delete part could/should be replaced with netlink equivalents, * or better yet, FORCES versions of same. * */ struct sadb_x_plumbif { uint16_t sadb_x_outif_len; uint16_t sadb_x_outif_exttype; uint16_t sadb_x_outif_ifnum; } __attribute__((packed)); /* * the ifnum describes a device that you wish to create refer to. * * devices 0-40959 are mastXXX devices. * devices 40960-49141 are mastXXX devices with transport set. * devices 49152-65536 are deprecated ipsecXXX devices. */ #define IPSECDEV_OFFSET (48 * 1024) #define MASTTRANSPORT_OFFSET (40 * 1024) /* * an saref extension sets the SA's reference number, and * may also set the paired SA's reference number. * */ struct sadb_x_saref { uint16_t sadb_x_saref_len; uint16_t sadb_x_saref_exttype; uint32_t sadb_x_saref_me; uint32_t sadb_x_saref_him; } __attribute__((packed)); /* * A protocol structure for passing through the transport level * protocol. It contains more fields than are actually used/needed * but it is this way to be compatible with the structure used in * OpenBSD (http://www.openbsd.org/cgi-bin/cvsweb/src/sys/net/pfkeyv2.h) */ struct sadb_protocol { uint16_t sadb_protocol_len; uint16_t sadb_protocol_exttype; uint8_t sadb_protocol_proto; uint8_t sadb_protocol_direction; uint8_t sadb_protocol_flags; uint8_t sadb_protocol_reserved2; } __attribute__((packed)); /* * NOTE that there is a limit of 31 extension types due to current * implementation in pfkeyv2_ext_bits.c */ enum sadb_extension_t { K_SADB_EXT_RESERVED= SADB_EXT_RESERVED, K_SADB_EXT_SA= SADB_EXT_SA, K_SADB_EXT_LIFETIME_CURRENT= SADB_EXT_LIFETIME_CURRENT, K_SADB_EXT_LIFETIME_HARD= SADB_EXT_LIFETIME_HARD, K_SADB_EXT_LIFETIME_SOFT= SADB_EXT_LIFETIME_SOFT, K_SADB_EXT_ADDRESS_SRC= SADB_EXT_ADDRESS_SRC, K_SADB_EXT_ADDRESS_DST= SADB_EXT_ADDRESS_DST, K_SADB_EXT_ADDRESS_PROXY= SADB_EXT_ADDRESS_PROXY, K_SADB_EXT_KEY_AUTH= SADB_EXT_KEY_AUTH, K_SADB_EXT_KEY_ENCRYPT= SADB_EXT_KEY_ENCRYPT, K_SADB_EXT_IDENTITY_SRC= SADB_EXT_IDENTITY_SRC, K_SADB_EXT_IDENTITY_DST= SADB_EXT_IDENTITY_DST, K_SADB_EXT_SENSITIVITY= SADB_EXT_SENSITIVITY, K_SADB_EXT_PROPOSAL= SADB_EXT_PROPOSAL, K_SADB_EXT_SUPPORTED_AUTH= SADB_EXT_SUPPORTED_AUTH, K_SADB_EXT_SUPPORTED_ENCRYPT= SADB_EXT_SUPPORTED_ENCRYPT, K_SADB_EXT_SPIRANGE= SADB_EXT_SPIRANGE, K_SADB_X_EXT_KMPRIVATE= SADB_X_EXT_KMPRIVATE, K_SADB_X_EXT_SATYPE2= 18, K_SADB_X_EXT_POLICY= SADB_X_EXT_POLICY, K_SADB_X_EXT_SA2= SADB_X_EXT_SA2, K_SADB_X_EXT_ADDRESS_DST2= 20, K_SADB_X_EXT_ADDRESS_SRC_FLOW= 21, K_SADB_X_EXT_ADDRESS_DST_FLOW= 22, K_SADB_X_EXT_ADDRESS_SRC_MASK= 23, K_SADB_X_EXT_ADDRESS_DST_MASK= 24, K_SADB_X_EXT_DEBUG= 25, K_SADB_X_EXT_PROTOCOL= 26, K_SADB_X_EXT_NAT_T_TYPE= 27, K_SADB_X_EXT_NAT_T_SPORT= 28, K_SADB_X_EXT_NAT_T_DPORT= 29, K_SADB_X_EXT_NAT_T_OA= 30, K_SADB_X_EXT_PLUMBIF= 31, K_SADB_X_EXT_SAREF= 32, K_SADB_EXT_MAX= 32, }; #define SADB_X_EXT_SATYPE2 K_SADB_X_EXT_SATYPE2 #define SADB_X_EXT_ADDRESS_DST2 K_SADB_X_EXT_ADDRESS_DST2 #define SADB_X_EXT_ADDRESS_SRC_FLOW K_SADB_X_EXT_ADDRESS_SRC_FLOW #define SADB_X_EXT_ADDRESS_DST_FLOW K_SADB_X_EXT_ADDRESS_DST_FLOW #define SADB_X_EXT_ADDRESS_SRC_MASK K_SADB_X_EXT_ADDRESS_SRC_MASK #define SADB_X_EXT_ADDRESS_DST_MASK K_SADB_X_EXT_ADDRESS_DST_MASK #define SADB_X_EXT_DEBUG K_SADB_X_EXT_DEBUG #define SADB_X_EXT_PROTOCOL K_SADB_X_EXT_PROTOCOL #undef SADB_X_EXT_NAT_T_TYPE #undef SADB_X_EXT_NAT_T_SPORT #undef SADB_X_EXT_NAT_T_DPORT #undef SADB_X_EXT_NAT_T_OA #define SADB_X_EXT_PLUMBIF K_SADB_X_EXT_PLUMBIF /* K_SADB_X_DELFLOW required over and above K_SADB_X_SAFLAGS_CLEARFLOW */ #define K_SADB_X_EXT_ADDRESS_DELFLOW \ ( (1ULL << K_SADB_X_EXT_ADDRESS_SRC_FLOW) \ | (1ULL << K_SADB_X_EXT_ADDRESS_DST_FLOW) \ | (1ULL << K_SADB_X_EXT_ADDRESS_SRC_MASK) \ | (1ULL << K_SADB_X_EXT_ADDRESS_DST_MASK)) enum sadb_satype { K_SADB_SATYPE_UNSPEC=SADB_SATYPE_UNSPEC, K_SADB_SATYPE_AH=SADB_SATYPE_AH, K_SADB_SATYPE_ESP=SADB_SATYPE_ESP, K_SADB_SATYPE_RSVP=SADB_SATYPE_RSVP, K_SADB_SATYPE_OSPFV2=SADB_SATYPE_OSPFV2, K_SADB_SATYPE_RIPV2=SADB_SATYPE_RIPV2, K_SADB_SATYPE_MIP=SADB_SATYPE_MIP, K_SADB_X_SATYPE_IPIP=9, K_SADB_X_SATYPE_COMP=10, K_SADB_X_SATYPE_INT=11 }; #define K_SADB_SATYPE_MAX 11 enum sadb_sastate { K_SADB_SASTATE_LARVAL=0, K_SADB_SASTATE_MATURE=1, K_SADB_SASTATE_DYING=2, K_SADB_SASTATE_DEAD=3 }; #undef SADB_SASTATE_LARVAL #undef SADB_SASTATE_MATURE #undef SADB_SASTATE_DYING #undef SADB_SASTATE_DEAD #define K_SADB_SASTATE_MAX 3 #define SADB_SAFLAGS_PFS 1 #define SADB_X_SAFLAGS_REPLACEFLOW 2 #define SADB_X_SAFLAGS_CLEARFLOW 4 #define SADB_X_SAFLAGS_INFLOW 8 #define SADB_X_SAFLAGS_POLICYONLY 16 /* suppress eroute creation */ /* not obvious, but these are the same values as used in isakmp, * and in include/ietf_constants.h. If you need to add any, they * should be added as according to * http://www.iana.org/assignments/isakmp-registry * * and if not, then please try to use a private-use value, and * consider asking IANA to assign a value. */ #define SADB_AALG_NONE 0 #define SADB_AALG_MD5HMAC 2 #define SADB_AALG_SHA1HMAC 3 #define SADB_X_AALG_SHA2_256HMAC 5 #define SADB_X_AALG_SHA2_384HMAC 6 #define SADB_X_AALG_SHA2_512HMAC 7 #define SADB_X_AALG_RIPEMD160HMAC 8 #define SADB_X_AALG_AES_XCBC_MAC 9 #define SADB_X_AALG_RSA 10 #define SADB_X_AALG_AH_AES_128_GMAC 11 #define SADB_X_AALG_AH_AES_192_GMAC 12 #define SADB_X_AALG_AH_AES_256_GMAC 13 #define SADB_X_AALG_AES_CMAC_96 250 /* used internally */ #define SADB_X_AALG_NULL 251 /* kame */ #define SADB_X_AALG_SHA2_256HMAC_TRUNCBUG 252 /* used internally to signal for broken linux kernel behaviour */ enum sadb_aalg { K_SADB_AALG_NONE= SADB_AALG_NONE, K_SADB_AALG_MD5HMAC= SADB_AALG_MD5HMAC, K_SADB_AALG_SHA1HMAC= SADB_AALG_SHA1HMAC, K_SADB_X_AALG_SHA2_256HMAC= SADB_X_AALG_SHA2_256HMAC, K_SADB_X_AALG_SHA2_256HMAC_TRUNCBUG= SADB_X_AALG_SHA2_256HMAC_TRUNCBUG, K_SADB_X_AALG_SHA2_384HMAC= SADB_X_AALG_SHA2_384HMAC, K_SADB_X_AALG_SHA2_512HMAC= SADB_X_AALG_SHA2_512HMAC, K_SADB_X_AALG_RIPEMD160HMAC= SADB_X_AALG_RIPEMD160HMAC, K_SADB_X_AALG_AES_XCBC_MAC= SADB_X_AALG_AES_XCBC_MAC, K_SADB_X_AALG_RSA= SADB_X_AALG_RSA, K_SADB_X_AALG_AH_AES_128_GMAC= SADB_X_AALG_AH_AES_128_GMAC, K_SADB_X_AALG_AH_AES_192_GMAC= SADB_X_AALG_AH_AES_192_GMAC, K_SADB_X_AALG_AH_AES_256_GMAC= SADB_X_AALG_AH_AES_256_GMAC, /* 13 */ K_SADB_X_AALG_AES_CMAC_96= SADB_X_AALG_AES_CMAC_96, K_SADB_X_AALG_NULL= SADB_X_AALG_NULL, /* 251 */ }; #define K_SADB_AALG_MAX 255 /* Is this really one octets, not two? */ /* gets mapped into AUTH_ALGORITHM which is two octets */ #define SADB_EALG_NONE 0 /* #define SADB_EALG_DESCBC 2 obsoleted */ #define SADB_EALG_3DESCBC 3 #define SADB_X_EALG_CASTCBC 6 /* #define SADB_X_EALG_BLOWFISHCBC 7 obsoleted */ #define SADB_EALG_NULL 11 #define SADB_X_EALG_AESCBC 12 #define SADB_X_EALG_AESCTR 13 #define SADB_X_EALG_AES_CCM_ICV8 14 #define SADB_X_EALG_AES_CCM_ICV12 15 #define SADB_X_EALG_AES_CCM_ICV16 16 #define SADB_X_EALG_AES_GCM_ICV8 18 #define SADB_X_EALG_AES_GCM_ICV12 19 #define SADB_X_EALG_AES_GCM_ICV16 20 #define SADB_X_EALG_SEEDCBC 21 #define SADB_X_EALG_CAMELLIACBC 22 #define SADB_X_EALG_NULL_AES_GMAC 23 enum sadb_ealg { K_SADB_EALG_NONE=SADB_EALG_NONE, /* K_SADB_EALG_DESCBC=SADB_EALG_DESCBC, obsoleted */ K_SADB_EALG_3DESCBC=SADB_EALG_3DESCBC, K_SADB_X_EALG_CASTCBC=SADB_X_EALG_CASTCBC, /* K_SADB_X_EALG_BLOWFISHCBC=SADB_X_EALG_BLOWFISHCBC, obsoleted */ K_SADB_EALG_NULL=SADB_EALG_NULL, K_SADB_X_EALG_AESCBC=SADB_X_EALG_AESCBC, K_SADB_X_EALG_AESCTR=SADB_X_EALG_AESCTR, K_SADB_X_EALG_AES_CCM_ICV8=SADB_X_EALG_AES_CCM_ICV8, K_SADB_X_EALG_AES_CCM_ICV12=SADB_X_EALG_AES_CCM_ICV12, K_SADB_X_EALG_AES_CCM_ICV16=SADB_X_EALG_AES_CCM_ICV16, K_SADB_X_EALG_AES_GCM_ICV8=SADB_X_EALG_AES_GCM_ICV8, K_SADB_X_EALG_AES_GCM_ICV12=SADB_X_EALG_AES_GCM_ICV12, K_SADB_X_EALG_AES_GCM_ICV16=SADB_X_EALG_AES_GCM_ICV16, K_SADB_X_EALG_SEEDCBC=SADB_X_EALG_SEEDCBC, K_SADB_X_EALG_CAMELLIACBC=SADB_X_EALG_CAMELLIACBC, K_SADB_X_EALG_NULL_AES_GMAC=SADB_X_EALG_NULL_AES_GMAC }; #undef SADB_EALG_MAX #define K_SADB_EALG_MAX 255 #define SADB_X_CALG_NONE 0 #define SADB_X_CALG_OUI 1 #define SADB_X_CALG_DEFLATE 2 #define SADB_X_CALG_LZS 3 #define SADB_X_CALG_LZJH 4 #define SADB_X_CALG_MAX 4 enum sadb_talg { K_SADB_X_TALG_NONE=0, K_SADB_X_TALG_IPv4_in_IPv4=1, K_SADB_X_TALG_IPv6_in_IPv4=2, K_SADB_X_TALG_IPv4_in_IPv6=3, K_SADB_X_TALG_IPv6_in_IPv6=4, }; #define SADB_X_TALG_MAX 4 #define SADB_IDENTTYPE_RESERVED 0 #define SADB_IDENTTYPE_PREFIX 1 #define SADB_IDENTTYPE_FQDN 2 #define SADB_IDENTTYPE_USERFQDN 3 #define SADB_X_IDENTTYPE_CONNECTION 4 #define K_SADB_IDENTTYPE_MAX 4 #define K_SADB_KEY_FLAGS_MAX 0 #endif /* __PFKEY_V2_H */ libreswan-3.32/linux/include/libreswan/radij.h000066400000000000000000000174571365625662500214770ustar00rootroot00000000000000/* * This file is defived from ${SRC}/sys/net/radix.h of BSD 4.4lite * * Variable and procedure names have been modified so that they don't * conflict with the original BSD code, as a small number of modifications * have been introduced and we may want to reuse this code in BSD. * * The `j' in `radij' is pronounced as a voiceless guttural (like a Greek * chi or a German ch sound (as `doch', not as in `milch'), or even a * spanish j as in Juan. It is not as far back in the throat like * the corresponding Hebrew sound, nor is it a soft breath like the English h. * It has nothing to do with the Dutch ij sound. * * Here is the appropriate copyright notice: */ /* * Copyright (c) 1988, 1989, 1993 * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)radix.h 8.1 (Berkeley) 6/10/93 */ #ifndef _RADIJ_H_ #define _RADIJ_H_ /* #define RJ_DEBUG */ #ifdef __KERNEL__ #ifndef __P #ifdef __STDC__ #define __P(x) x #else #define __P(x) () #endif #endif /* * Radix search tree node layout. */ struct radij_node { struct radij_mask *rj_mklist; /* list of masks contained in subtree */ struct radij_node *rj_p; /* parent */ short rj_b; /* bit offset; -1-index(netmask) */ char rj_bmask; /* node: mask for bit test */ u_char rj_flags; /* enumerated next */ #define RJF_NORMAL 1 /* leaf contains normal route */ #define RJF_ROOT 2 /* leaf is root leaf for tree */ #define RJF_ACTIVE 4 /* This node is alive (for rtfree) */ union { struct { /* leaf only data: */ caddr_t rj_Key; /* object of search */ caddr_t rj_Mask; /* netmask, if present */ struct radij_node *rj_Dupedkey; } rj_leaf; struct { /* node only data: */ int rj_Off; /* where to start compare */ struct radij_node *rj_L; /* progeny */ struct radij_node *rj_R; /* progeny */ } rj_node; } rj_u; #ifdef RJ_DEBUG int rj_info; struct radij_node *rj_twin; struct radij_node *rj_ybro; #endif }; #define rj_dupedkey rj_u.rj_leaf.rj_Dupedkey #define rj_key rj_u.rj_leaf.rj_Key #define rj_mask rj_u.rj_leaf.rj_Mask #define rj_off rj_u.rj_node.rj_Off #define rj_l rj_u.rj_node.rj_L #define rj_r rj_u.rj_node.rj_R /* * Annotations to tree concerning potential routes applying to subtrees. */ extern struct radij_mask { short rm_b; /* bit offset; -1-index(netmask) */ char rm_unused; /* cf. rj_bmask */ u_char rm_flags; /* cf. rj_flags */ struct radij_mask *rm_mklist; /* more masks to try */ caddr_t rm_mask; /* the mask */ int rm_refs; /* # of references to this struct */ } *rj_mkfreelist; #define MKGet(m) { \ if (rj_mkfreelist) { \ m = rj_mkfreelist; \ rj_mkfreelist = (m)->rm_mklist; \ } else { \ R_Malloc(m, struct radij_mask *, sizeof(*(m))); } } \ #define MKFree(m) { (m)->rm_mklist = rj_mkfreelist; rj_mkfreelist = (m); } struct radij_node_head { struct radij_node *rnh_treetop; int rnh_addrsize; /* permit, but not require fixed keys */ int rnh_pktsize; /* permit, but not require fixed keys */ #if 0 struct radij_node *(*rnh_addaddr) /* add based on sockaddr */ __P((void *v, void *mask, struct radij_node_head *head, struct radij_node nodes[])); #endif int (*rnh_addaddr) /* add based on sockaddr */ __P((void *v, void *mask, struct radij_node_head *head, struct radij_node nodes[])); struct radij_node *(*rnh_addpkt) /* add based on packet hdr */ __P((void *v, void *mask, struct radij_node_head *head, struct radij_node nodes[])); #if 0 struct radij_node *(*rnh_deladdr) /* remove based on sockaddr */ __P((void *v, void *mask, struct radij_node_head *head)); #endif int (*rnh_deladdr) /* remove based on sockaddr */ __P((void *v, void *mask, struct radij_node_head *head, struct radij_node **node)); struct radij_node *(*rnh_delpkt) /* remove based on packet hdr */ __P((void *v, void *mask, struct radij_node_head *head)); struct radij_node *(*rnh_matchaddr) /* locate based on sockaddr */ __P((void *v, struct radij_node_head *head)); struct radij_node *(*rnh_matchpkt) /* locate based on packet hdr */ __P((void *v, struct radij_node_head *head)); int (*rnh_walktree) /* traverse tree */ __P((struct radij_node_head *head, int (*f)(struct radij_node *rn, void *w), void *w)); struct radij_node rnh_nodes[3]; /* empty tree for common case */ }; #define Bcmp(a, b, n) memcmp(((caddr_t)(b)), ((caddr_t)(a)), (unsigned)(n)) #define Bcopy(a, b, n) memmove(((caddr_t)(b)), ((caddr_t)(a)), (unsigned)(n)) #define Bzero(p, n) memset((caddr_t)(p), 0, (unsigned)(n)) #define R_Malloc(p, t, n) (((p) = \ (t) kmalloc((size_t)(n), \ GFP_ATOMIC)), Bzero((p), (n))) #define Free(p) kfree((caddr_t)(p)); void rj_init __P((void)); int rj_inithead __P((void **, int)); int rj_refines __P((void *, void *)); int rj_walktree __P((struct radij_node_head *head, int (*f)( struct radij_node *rn, void *w), void *w)); struct radij_node *rj_addmask __P((void *, int, int)) /* , rgb */; int /* * */ rj_addroute __P((void *, void *, struct radij_node_head *, struct radij_node [2])) /* , rgb */; int /* * */ rj_delete __P((void *, void *, struct radij_node_head *, struct radij_node **)) /* , rgb */; struct radij_node /* rgb */ *rj_insert __P((void *, struct radij_node_head *, int *, struct radij_node [2])), *rj_match __P((void *, struct radij_node_head *)), *rj_newpair __P((void *, int, struct radij_node[2])), *rj_search __P((void *, struct radij_node *)), *rj_search_m __P((void *, struct radij_node *, void *)); void rj_deltree(struct radij_node_head *); void rj_delnodes(struct radij_node *); void rj_free_mkfreelist(void); int radijcleartree(void); int radijcleanup(void); extern struct radij_node_head *mask_rjhead; extern int maj_keylen; #endif /* __KERNEL__ */ #endif /* _RADIJ_H_ */ libreswan-3.32/linux/include/lswcdefs.h000066400000000000000000000027331365625662500202210ustar00rootroot00000000000000/* sys/cdefs.h like compiler macros, for libreswan * * Copyright (C) 1998, 1999, 2000 Henry Spencer. * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. * */ #ifndef LSWCDEFS_H #define LSWCDEFS_H /* GCC magic for use in function definitions! */ #ifdef GCC_LINT # define PRINTF_LIKE(n) __attribute__ ((format(printf, n, n + 1))) # define STRFTIME_LIKE(n) __attribute__ ((format (strftime, n, 0))) # define NEVER_RETURNS __attribute__ ((noreturn)) # define UNUSED __attribute__ ((unused)) # define MUST_USE_RESULT __attribute__ ((warn_unused_result)) #else # define PRINTF_LIKE(n) /* ignore */ # define STRFTIME_LIKE(n) /* ignore */ # define NEVER_RETURNS /* ignore */ # define UNUSED /* ignore */ # define MUST_USE_RESULT /* ignore */ #endif #ifdef COMPILER_HAS_NO_PRINTF_LIKE # undef PRINTF_LIKE # define PRINTF_LIKE(n) /* ignore */ # undef STRFTIME_LIKE # define STRFTIME_LIKE(n) /* ignore */ #endif #endif libreswan-3.32/linux/include/ocf-compat.h000066400000000000000000000241631365625662500204400ustar00rootroot00000000000000#ifndef _BSD_COMPAT_H_ #define _BSD_COMPAT_H_ 1 /****************************************************************************/ /* * Provide compat routines for older linux kernels and BSD kernels * * Written by David McCullough * Copyright (C) 2010 David McCullough * * LICENSE TERMS * * The free distribution and use of this software in both source and binary * form is allowed (with or without changes) provided that: * * 1. distributions of this source code include the above copyright * notice, this list of conditions and the following disclaimer; * * 2. distributions in binary form include the above copyright * notice, this list of conditions and the following disclaimer * in the documentation and/or other associated materials; * * 3. the copyright holder's name is not used to endorse products * built using this software without specific written permission. * * ALTERNATIVELY, provided that this notice is retained in full, this file * may be distributed under the terms of the GNU General Public License (GPL), * in which case the provisions of the GPL apply INSTEAD OF those given above. * * DISCLAIMER * * This software is provided 'as is' with no explicit or implied warranties * in respect of its properties, including, but not limited to, correctness * and/or fitness for purpose. */ /****************************************************************************/ #ifdef __KERNEL__ #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38) && \ !defined(AUTOCONF_INCLUDED) #include #endif /* * fake some BSD driver interface stuff specifically for OCF use */ typedef struct ocf_device *device_t; typedef struct { int (*cryptodev_newsession)(device_t dev, u_int32_t *sidp, struct cryptoini *cri); int (*cryptodev_freesession)(device_t dev, u_int64_t tid); int (*cryptodev_process)(device_t dev, struct cryptop *crp, int hint); int (*cryptodev_kprocess)(device_t dev, struct cryptkop *krp, int hint); } device_method_t; /* ??? DEVMETHOD isn't used in our code base. And it looks funny. */ #define DEVMETHOD(id, func) id : func struct ocf_device { char name[32]; /* the driver name */ char nameunit[32]; /* the driver name + HW instance */ int unit; device_method_t methods; void *softc; }; #define CRYPTODEV_NEWSESSION(dev, sid, cri) \ ((*(dev)->methods.cryptodev_newsession)(dev, sid, cri)) #define CRYPTODEV_FREESESSION(dev, sid) \ ((*(dev)->methods.cryptodev_freesession)(dev, sid)) #define CRYPTODEV_PROCESS(dev, crp, hint) \ ((*(dev)->methods.cryptodev_process)(dev, crp, hint)) #define CRYPTODEV_KPROCESS(dev, krp, hint) \ ((*(dev)->methods.cryptodev_kprocess)(dev, krp, hint)) #define device_get_name(dev) ((dev)->name) #define device_get_nameunit(dev) ((dev)->nameunit) #define device_get_unit(dev) ((dev)->unit) #define device_get_softc(dev) ((dev)->softc) #define softc_device_decl \ struct ocf_device _device; \ device_t /* ??? softc_device_init's definition sure looks funny. Not used in our code base. * - why is wrapper "if...else" rather than converntional "do ... while (0)"? * - why is _device.name neither properly NUL-terminated nor NUL-padded? */ #define softc_device_init(_sc, _name, _unit, _methods) \ if (1) { \ strncpy((_sc)->_device.name, _name, \ sizeof((_sc)->_device.name) - 1); \ snprintf((_sc)->_device.nameunit, sizeof((_sc)->_device.name), \ "%s%d", _name, _unit); \ (_sc)->_device.unit = _unit; \ (_sc)->_device.methods = _methods; \ (_sc)->_device.softc = (void *) _sc; \ *(device_t *)((softc_get_device(_sc)) + 1) = &(_sc)->_device; \ } else #define softc_get_device(_sc) (&(_sc)->_device) /* * iomem support for 2.4 and 2.6 kernels */ #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) #define ocf_iomem_t unsigned long /* * implement simple workqueue like support for older kernels */ #include #define work_struct tq_struct #define INIT_WORK(wp, fp, ap) \ do { \ (wp)->sync = 0; \ (wp)->routine = (fp); \ (wp)->data = (ap); \ } while (0) #define schedule_work(wp) \ do { \ queue_task((wp), &tq_immediate); \ mark_bh(IMMEDIATE_BH); \ } while (0) #define flush_scheduled_work() run_task_queue(&tq_immediate) #else #define ocf_iomem_t void __iomem * #include #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) #include #elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11) #define files_fdtable(files) (files) #endif #ifdef MODULE_PARM #undef module_param /* just in case */ #define module_param(a, b, c) MODULE_PARM(a, "i") #endif #define bzero(s, l) memset(s, 0, l) #define bcopy(s, d, l) memcpy(d, s, l) #define bcmp(x, y, l) memcmp(x, y, l) #define MIN(x, y) ((x) < (y) ? (x) : (y)) #define device_printf(dev, a ...) ({ \ printk("%s: ", \ device_get_nameunit(dev)); \ printk(a); \ }) #undef printf #define printf(fmt ...) printk(fmt) /* ??? what's with the dangling else? */ #define KASSERT(c, p) if (!(c)) { printk p; } else #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) #define ocf_daemonize(str) \ daemonize(); \ spin_lock_irq(¤t->sigmask_lock); \ sigemptyset(¤t->blocked); \ recalc_sigpending(current); \ spin_unlock_irq(¤t->sigmask_lock); \ sprintf(current->comm, str); #else #define ocf_daemonize(str) daemonize(str); #endif #define TAILQ_INSERT_TAIL(q, d, m) list_add_tail(&(d)->m, (q)) #define TAILQ_EMPTY(q) list_empty(q) #define TAILQ_FOREACH(v, q, m) list_for_each_entry(v, q, m) #define read_random(p, l) get_random_bytes(p, l) #define DELAY(x) ((x) > 2000 ? mdelay((x) / 1000) : udelay(x)) #define strtoul simple_strtoul #define pci_get_vendor(dev) ((dev)->vendor) #define pci_get_device(dev) ((dev)->device) #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) #define pci_set_consistent_dma_mask(dev, mask) (0) #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10) #define pci_dma_sync_single_for_cpu pci_dma_sync_single #endif #ifndef DMA_32BIT_MASK #define DMA_32BIT_MASK 0x00000000ffffffffULL #endif #ifndef htole32 #define htole32(x) cpu_to_le32(x) #endif #ifndef htobe32 #define htobe32(x) cpu_to_be32(x) #endif #ifndef htole16 #define htole16(x) cpu_to_le16(x) #endif #ifndef htobe16 #define htobe16(x) cpu_to_be16(x) #endif /* older kernels don't have these */ #include #if !defined(IRQ_NONE) && !defined(IRQ_RETVAL) #define IRQ_NONE #define IRQ_HANDLED #define IRQ_WAKE_THREAD #define IRQ_RETVAL #define irqreturn_t void typedef irqreturn_t (*irq_handler_t)(int irq, void *arg, struct pt_regs *regs); #endif #ifndef IRQF_SHARED #define IRQF_SHARED SA_SHIRQ #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) # define strlcpy(dest, src, len) \ ({ strncpy(dest, src, (len) - 1); ((char *)dest)[(len) - 1] = '\0'; }) #endif #ifndef MAX_ERRNO #define MAX_ERRNO 4095 #endif #ifndef IS_ERR_VALUE #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 5) #include #endif #ifndef IS_ERR_VALUE #define IS_ERR_VALUE(x) ((unsigned long)(x) >= (unsigned long)-MAX_ERRNO) #endif #endif /* * common debug for all */ #if 1 #define dprintk(a ...) do { if (debug) \ printk(a); } while (0) #else #define dprintk(a ...) #endif #ifndef SLAB_ATOMIC /* Changed in 2.6.20, must use GFP_ATOMIC now */ #define SLAB_ATOMIC GFP_ATOMIC #endif /* * need some additional support for older kernels */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 2) #define pci_register_driver_compat(driver, rc) \ do { \ if ((rc) > 0) { \ (rc) = 0; \ } else if (rc == 0) { \ (rc) = -ENODEV; \ } else { \ pci_unregister_driver(driver); \ } \ } while (0) #elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10) #define pci_register_driver_compat(driver, rc) ((rc) = (rc) < 0 ? (rc) : 0) #else #define pci_register_driver_compat(driver, rc) #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24) #include #include static inline void sg_set_page(struct scatterlist *sg, struct page *page, unsigned int len, unsigned int offset) { sg->page = page; sg->offset = offset; sg->length = len; } static inline void *sg_virt(struct scatterlist *sg) { return page_address(sg->page) + sg->offset; } #define sg_init_table(sg, n) #endif #ifndef late_initcall #define late_initcall(init) module_init(init) #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 4) || !defined(CONFIG_SMP) #define ocf_for_each_cpu(cpu) for ((cpu) = 0; (cpu) == 0; (cpu)++) #else #define ocf_for_each_cpu(cpu) for_each_cpu(cpu, cpu_present_mask) #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) #include #define kill_proc(p, s, v) send_sig(s, find_task_by_vpid(p), 0) #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 4) struct ocf_thread { struct task_struct *task; int (*func)(void *arg); void *arg; }; /* thread startup helper func */ static inline int ocf_run_thread(void *arg) { struct ocf_thread *t = (struct ocf_thread *) arg; if (!t) return -1; /* very bad */ t->task = current; daemonize(); spin_lock_irq(¤t->sigmask_lock); sigemptyset(¤t->blocked); recalc_sigpending(current); spin_unlock_irq(¤t->sigmask_lock); return (*t->func)(t->arg); } #define kthread_create(f, a, fmt ...) \ ({ \ struct ocf_thread t; \ pid_t p; \ t.task = NULL; \ t.func = (f); \ t.arg = (a); \ p = kernel_thread(ocf_run_thread, &t, CLONE_FS | CLONE_FILES); \ while (p != (pid_t) -1 && t.task == NULL) \ schedule(); \ if (t.task) \ snprintf(t.task->comm, sizeof(t.task->comm), fmt); \ (t.task); \ }) #define kthread_bind(t, cpu) /**/ #define kthread_should_stop() streq(current->comm, "stopping") #define kthread_stop(t) \ ({ \ strcpy((t)->comm, "stopping"); \ kill_proc((t)->pid, SIGTERM, 1); \ do { \ schedule(); \ } while (kill_proc((t)->pid, SIGTERM, 1) == 0); \ }) #else #include #endif #endif /* __KERNEL__ */ /****************************************************************************/ #endif /* _BSD_COMPAT_H_ */ libreswan-3.32/linux/include/zlib/000077500000000000000000000000001365625662500171715ustar00rootroot00000000000000libreswan-3.32/linux/include/zlib/zconf.h000066400000000000000000000221151365625662500204620ustar00rootroot00000000000000/* zconf.h -- configuration of the zlib compression library * Copyright (C) 1995-2002 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id: zconf.h,v 1.4 2004/07/10 07:48:40 mcr Exp $ */ #ifndef _ZCONF_H #define _ZCONF_H /* * If you *really* need a unique prefix for all types and library functions, * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. */ #ifdef IPCOMP_PREFIX # define deflateInit_ ipcomp_deflateInit_ # define deflate ipcomp_deflate # define deflateEnd ipcomp_deflateEnd # define inflateInit_ ipcomp_inflateInit_ # define inflate ipcomp_inflate # define inflateEnd ipcomp_inflateEnd # define deflateInit2_ ipcomp_deflateInit2_ # define deflateSetDictionary ipcomp_deflateSetDictionary # define deflateCopy ipcomp_deflateCopy # define deflateReset ipcomp_deflateReset # define deflateParams ipcomp_deflateParams # define inflateInit2_ ipcomp_inflateInit2_ # define inflateSetDictionary ipcomp_inflateSetDictionary # define inflateSync ipcomp_inflateSync # define inflateSyncPoint ipcomp_inflateSyncPoint # define inflateReset ipcomp_inflateReset # define compress ipcomp_compress # define compress2 ipcomp_compress2 # define uncompress ipcomp_uncompress # define adler32 ipcomp_adler32 # define crc32 ipcomp_crc32 # define get_crc_table ipcomp_get_crc_table /* SSS: these also need to be prefixed to avoid clash with ppp_deflate and ext2compression */ # define inflate_blocks ipcomp_deflate_blocks # define inflate_blocks_free ipcomp_deflate_blocks_free # define inflate_blocks_new ipcomp_inflate_blocks_new # define inflate_blocks_reset ipcomp_inflate_blocks_reset # define inflate_blocks_sync_point ipcomp_inflate_blocks_sync_point # define inflate_set_dictionary ipcomp_inflate_set_dictionary # define inflate_codes ipcomp_inflate_codes # define inflate_codes_free ipcomp_inflate_codes_free # define inflate_codes_new ipcomp_inflate_codes_new # define inflate_fast ipcomp_inflate_fast # define inflate_trees_bits ipcomp_inflate_trees_bits # define inflate_trees_dynamic ipcomp_inflate_trees_dynamic # define inflate_trees_fixed ipcomp_inflate_trees_fixed # define inflate_flush ipcomp_inflate_flush # define inflate_mask ipcomp_inflate_mask # define _dist_code _ipcomp_dist_code # define _length_code _ipcomp_length_code # define _tr_align _ipcomp_tr_align # define _tr_flush_block _ipcomp_tr_flush_block # define _tr_init _ipcomp_tr_init # define _tr_stored_block _ipcomp_tr_stored_block # define _tr_tally _ipcomp_tr_tally # define zError ipcomp_zError # define z_errmsg ipcomp_z_errmsg # define zlibVersion ipcomp_zlibVersion # define match_init ipcomp_match_init # define longest_match ipcomp_longest_match #endif #ifdef Z_PREFIX # define Byte z_Byte # define uInt z_uInt # define uLong z_uLong # define Bytef z_Bytef # define charf z_charf # define intf z_intf # define uIntf z_uIntf # define uLongf z_uLongf # define voidpf z_voidpf # define voidp z_voidp #endif #if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) # define WIN32 #endif #if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386) # ifndef __32BIT__ # define __32BIT__ # endif #endif #if defined(__MSDOS__) && !defined(MSDOS) # define MSDOS #endif /* * Compile with -DMAXSEG_64K if the alloc function cannot allocate more * than 64k bytes at a time (needed on systems with 16-bit int). */ #if defined(MSDOS) && !defined(__32BIT__) # define MAXSEG_64K #endif #ifdef MSDOS # define UNALIGNED_OK #endif #if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32)) && !defined(STDC) # define STDC #endif #if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__) # ifndef STDC # define STDC # endif #endif #ifndef STDC # ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ # define const # endif #endif /* Some Mac compilers merge all .h files incorrectly: */ #if defined(__MWERKS__) || defined(applec) || defined(THINK_C) || \ defined(__SC__) # define NO_DUMMY_DECL #endif /* Old Borland C incorrectly complains about missing returns: */ #if defined(__BORLANDC__) && (__BORLANDC__ < 0x500) # define NEED_DUMMY_RETURN #endif /* Maximum value for memLevel in deflateInit2 */ #ifndef MAX_MEM_LEVEL # ifdef MAXSEG_64K # define MAX_MEM_LEVEL 8 # else # define MAX_MEM_LEVEL 9 # endif #endif /* Maximum value for windowBits in deflateInit2 and inflateInit2. * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files * created by gzip. (Files created by minigzip can still be extracted by * gzip.) */ #ifndef MAX_WBITS # define MAX_WBITS 15 /* 32K LZ77 window */ #endif /* The memory requirements for deflate are (in bytes): (1 << (windowBits+2)) + (1 << (memLevel+9)) that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) plus a few kilobytes for small objects. For example, if you want to reduce the default memory requirements from 256K to 128K, compile with make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" Of course this will generally degrade compression (there's no free lunch). The memory requirements for inflate are (in bytes) 1 << windowBits that is, 32K for windowBits=15 (default value) plus a few kilobytes for small objects. */ /* Type declarations */ #ifndef OF /* function prototypes */ # ifdef STDC # define OF(args) args # else # define OF(args) () # endif #endif /* The following definitions for FAR are needed only for MSDOS mixed * model programming (small or medium model with some far allocations). * This was tested only with MSC; for other MSDOS compilers you may have * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, * just define FAR to be empty. */ #if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__) /* MSC small or medium model */ # define SMALL_MEDIUM # ifdef _MSC_VER # define FAR _far # else # define FAR far # endif #endif #if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__)) # ifndef __32BIT__ # define SMALL_MEDIUM # define FAR _far # endif #endif /* Compile with -DZLIB_DLL for Windows DLL support */ #if defined(ZLIB_DLL) # if defined(_WINDOWS) || defined(WINDOWS) # ifdef FAR # undef FAR # endif # include # define ZEXPORT WINAPI # ifdef WIN32 # define ZEXPORTVA WINAPIV # else # define ZEXPORTVA FAR _cdecl _export # endif # endif # if defined (__BORLANDC__) # if (__BORLANDC__ >= 0x0500) && defined (WIN32) # include # define ZEXPORT __declspec(dllexport) WINAPI # define ZEXPORTRVA __declspec(dllexport) WINAPIV # else # if defined (_Windows) && defined (__DLL__) # define ZEXPORT _export # define ZEXPORTVA _export # endif # endif # endif #endif #if defined (__BEOS__) # if defined (ZLIB_DLL) # define ZEXTERN extern __declspec(dllexport) # else # define ZEXTERN extern __declspec(dllimport) # endif #endif #ifndef ZEXPORT # define ZEXPORT #endif #ifndef ZEXPORTVA # define ZEXPORTVA #endif #ifndef ZEXTERN # define ZEXTERN extern #endif #ifndef FAR # define FAR #endif #if !defined(MACOS) && !defined(TARGET_OS_MAC) typedef unsigned char Byte; /* 8 bits */ #endif typedef unsigned int uInt; /* 16 bits or more */ typedef unsigned long uLong; /* 32 bits or more */ #ifdef SMALL_MEDIUM /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ # define Bytef Byte FAR #else typedef Byte FAR Bytef; #endif typedef char FAR charf; typedef int FAR intf; typedef uInt FAR uIntf; typedef uLong FAR uLongf; #ifdef STDC typedef void FAR *voidpf; typedef void *voidp; #else typedef Byte FAR *voidpf; typedef Byte *voidp; #endif #ifdef HAVE_UNISTD_H # include /* for off_t */ # include /* for SEEK_* and off_t */ # define z_off_t off_t #endif #ifndef SEEK_SET # define SEEK_SET 0 /* Seek from beginning of file. */ # define SEEK_CUR 1 /* Seek from current position. */ # define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ #endif #ifndef z_off_t # define z_off_t long #endif /* MVS linker does not support external names larger than 8 bytes */ #if defined(__MVS__) # pragma map(deflateInit_,"DEIN") # pragma map(deflateInit2_,"DEIN2") # pragma map(deflateEnd,"DEEND") # pragma map(inflateInit_,"ININ") # pragma map(inflateInit2_,"ININ2") # pragma map(inflateEnd,"INEND") # pragma map(inflateSync,"INSY") # pragma map(inflateSetDictionary,"INSEDI") # pragma map(inflate_blocks,"INBL") # pragma map(inflate_blocks_new,"INBLNE") # pragma map(inflate_blocks_free,"INBLFR") # pragma map(inflate_blocks_reset,"INBLRE") # pragma map(inflate_codes_free,"INCOFR") # pragma map(inflate_codes,"INCO") # pragma map(inflate_fast,"INFA") # pragma map(inflate_flush,"INFLU") # pragma map(inflate_mask,"INMA") # pragma map(inflate_set_dictionary,"INSEDI2") # pragma map(ipcomp_inflate_copyright,"INCOPY") # pragma map(inflate_trees_bits,"INTRBI") # pragma map(inflate_trees_dynamic,"INTRDY") # pragma map(inflate_trees_fixed,"INTRFI") # pragma map(inflate_trees_free,"INTRFR") #endif #endif /* _ZCONF_H */ libreswan-3.32/linux/include/zlib/zlib.h000066400000000000000000001170111365625662500203030ustar00rootroot00000000000000/* zlib.h -- interface of the 'zlib' general purpose compression library version 1.1.4, March 11th, 2002 Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Jean-loup Gailly Mark Adler jloup@gzip.org madler@alumni.caltech.edu The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). */ #ifndef _ZLIB_H #define _ZLIB_H #include "zconf.h" #ifdef __cplusplus extern "C" { #endif #define ZLIB_VERSION "1.1.4" /* The 'zlib' compression library provides in-memory compression and decompression functions, including integrity checks of the uncompressed data. This version of the library supports only one compression method (deflation) but other algorithms will be added later and will have the same stream interface. Compression can be done in a single step if the buffers are large enough (for example if an input file is mmap'ed), or can be done by repeated calls of the compression function. In the latter case, the application must provide more input and/or consume the output (providing more output space) before each call. The library also supports reading and writing files in gzip (.gz) format with an interface similar to that of stdio. The library does not install any signal handler. The decoder checks the consistency of the compressed data, so the library should never crash even in case of corrupted input. */ typedef voidpf (*alloc_func) OF ((voidpf opaque, uInt items, uInt size)); typedef void (*free_func) OF ((voidpf opaque, voidpf address)); struct internal_state; typedef struct z_stream_s { Bytef *next_in; /* next input byte */ uInt avail_in; /* number of bytes available at next_in */ uLong total_in; /* total nb of input bytes read so far */ Bytef *next_out; /* next output byte should be put there */ uInt avail_out; /* remaining free space at next_out */ uLong total_out; /* total nb of bytes output so far */ const char *msg; /* last error message, NULL if no error */ struct internal_state FAR *state; /* not visible by applications */ alloc_func zalloc; /* used to allocate the internal state */ free_func zfree; /* used to free the internal state */ voidpf opaque; /* private data object passed to zalloc and zfree */ int data_type; /* best guess about the data type: ascii or binary */ uLong adler; /* adler32 value of the uncompressed data */ uLong reserved; /* reserved for future use */ } z_stream; typedef z_stream FAR *z_streamp; /* The application must update next_in and avail_in when avail_in has dropped to zero. It must update next_out and avail_out when avail_out has dropped to zero. The application must initialize zalloc, zfree and opaque before calling the init function. All other fields are set by the compression library and must not be updated by the application. The opaque value provided by the application will be passed as the first parameter for calls of zalloc and zfree. This can be useful for custom memory management. The compression library attaches no meaning to the opaque value. zalloc must return Z_NULL if there is not enough memory for the object. If zlib is used in a multi-threaded application, zalloc and zfree must be thread safe. On 16-bit systems, the functions zalloc and zfree must be able to allocate exactly 65536 bytes, but will not be required to allocate more than this if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers returned by zalloc for objects of exactly 65536 bytes *must* have their offset normalized to zero. The default allocation function provided by this library ensures this (see zutil.c). To reduce memory requirements and avoid any allocation of 64K objects, at the expense of compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). The fields total_in and total_out can be used for statistics or progress reports. After compression, total_in holds the total size of the uncompressed data and may be saved for use in the decompressor (particularly if the decompressor wants to decompress everything in a single step). */ /* constants */ #define Z_NO_FLUSH 0 #define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ #define Z_SYNC_FLUSH 2 #define Z_FULL_FLUSH 3 #define Z_FINISH 4 /* Allowed flush values; see deflate() below for details */ #define Z_OK 0 #define Z_STREAM_END 1 #define Z_NEED_DICT 2 #define Z_ERRNO (-1) #define Z_STREAM_ERROR (-2) #define Z_DATA_ERROR (-3) #define Z_MEM_ERROR (-4) #define Z_BUF_ERROR (-5) #define Z_VERSION_ERROR (-6) /* Return codes for the compression/decompression functions. Negative * values are errors, positive values are used for special but normal events. */ #define Z_NO_COMPRESSION 0 #define Z_BEST_SPEED 1 #define Z_BEST_COMPRESSION 9 #define Z_DEFAULT_COMPRESSION (-1) /* compression levels */ #define Z_FILTERED 1 #define Z_HUFFMAN_ONLY 2 #define Z_DEFAULT_STRATEGY 0 /* compression strategy; see deflateInit2() below for details */ #define Z_BINARY 0 #define Z_ASCII 1 #define Z_UNKNOWN 2 /* Possible values of the data_type field */ #define Z_DEFLATED 8 /* The deflate compression method (the only one supported in this version) */ #define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ #define zlib_version zlibVersion() /* for compatibility with versions < 1.0.2 */ /* basic functions */ ZEXTERN const char * ZEXPORT zlibVersion OF((void)); /* The application can compare zlibVersion and ZLIB_VERSION for consistency. If the first character differs, the library code actually used is not compatible with the zlib.h header file used by the application. This check is automatically made by deflateInit and inflateInit. */ /* ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); Initializes the internal stream state for compression. The fields zalloc, zfree and opaque must be initialized before by the caller. If zalloc and zfree are set to Z_NULL, deflateInit updates them to use default allocation functions. The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: 1 gives best speed, 9 gives best compression, 0 gives no compression at all (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION requests a default compromise between speed and compression (currently equivalent to level 6). deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if level is not a valid compression level, Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible with the version assumed by the caller (ZLIB_VERSION). msg is set to null if there is no error message. deflateInit does not perform any compression: this will be done by deflate(). */ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); /* deflate compresses as much data as possible, and stops when the input buffer becomes empty or the output buffer becomes full. It may introduce some output latency (reading input without producing any output) except when forced to flush. The detailed semantics are as follows. deflate performs one or both of the following actions: - Compress more input starting at next_in and update next_in and avail_in accordingly. If not all input can be processed (because there is not enough room in the output buffer), next_in and avail_in are updated and processing will resume at this point for the next call of deflate(). - Provide more output starting at next_out and update next_out and avail_out accordingly. This action is forced if the parameter flush is non zero. Forcing flush frequently degrades the compression ratio, so this parameter should be set only when necessary (in interactive applications). Some output may be provided even if flush is not set. Before the call of deflate(), the application should ensure that at least one of the actions is possible, by providing more input and/or consuming more output, and updating avail_in or avail_out accordingly; avail_out should never be zero before the call. The application can consume the compressed output when it wants, for example when the output buffer is full (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK and with zero avail_out, it must be called again after making room in the output buffer because there might be more output pending. If the parameter flush is set to Z_SYNC_FLUSH, all pending output is flushed to the output buffer and the output is aligned on a byte boundary, so that the decompressor can get all input data available so far. (In particular avail_in is zero after the call if enough output space has been provided before the call.) Flushing may degrade compression for some compression algorithms and so it should be used only when necessary. If flush is set to Z_FULL_FLUSH, all output is flushed as with Z_SYNC_FLUSH, and the compression state is reset so that decompression can restart from this point if previous compressed data has been damaged or if random access is desired. Using Z_FULL_FLUSH too often can seriously degrade the compression. If deflate returns with avail_out == 0, this function must be called again with the same value of the flush parameter and more output space (updated avail_out), until the flush is complete (deflate returns with non-zero avail_out). If the parameter flush is set to Z_FINISH, pending input is processed, pending output is flushed and deflate returns with Z_STREAM_END if there was enough output space; if deflate returns with Z_OK, this function must be called again with Z_FINISH and more output space (updated avail_out) but no more input data, until it returns with Z_STREAM_END or an error. After deflate has returned Z_STREAM_END, the only possible operations on the stream are deflateReset or deflateEnd. Z_FINISH can be used immediately after deflateInit if all the compression is to be done in a single step. In this case, avail_out must be at least 0.1% larger than avail_in plus 12 bytes. If deflate does not return Z_STREAM_END, then it must be called again as described above. deflate() sets strm->adler to the adler32 checksum of all input read so far (that is, total_in bytes). deflate() may update data_type if it can make a good guess about the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered binary. This field is only for information purposes and does not affect the compression algorithm in any manner. deflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if all input has been consumed and all output has been produced (only when flush is set to Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible (for example avail_in or avail_out was zero). */ ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); /* All dynamically allocated data structures for this stream are freed. This function discards any unprocessed input and does not flush any pending output. deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state was inconsistent, Z_DATA_ERROR if the stream was freed prematurely (some input or output was discarded). In the error case, msg may be set but then points to a static string (which must not be deallocated). */ /* ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); Initializes the internal stream state for decompression. The fields next_in, avail_in, zalloc, zfree and opaque must be initialized before by the caller. If next_in is not Z_NULL and avail_in is large enough (the exact value depends on the compression method), inflateInit determines the compression method from the zlib header and allocates all data structures accordingly; otherwise the allocation will be deferred to the first call of inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to use default allocation functions. inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_VERSION_ERROR if the zlib library version is incompatible with the version assumed by the caller. msg is set to null if there is no error message. inflateInit does not perform any decompression apart from reading the zlib header if present: this will be done by inflate(). (So next_in and avail_in may be modified, but next_out and avail_out are unchanged.) */ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); /* inflate decompresses as much data as possible, and stops when the input buffer becomes empty or the output buffer becomes full. It may some introduce some output latency (reading input without producing any output) except when forced to flush. The detailed semantics are as follows. inflate performs one or both of the following actions: - Decompress more input starting at next_in and update next_in and avail_in accordingly. If not all input can be processed (because there is not enough room in the output buffer), next_in is updated and processing will resume at this point for the next call of inflate(). - Provide more output starting at next_out and update next_out and avail_out accordingly. inflate() provides as much output as possible, until there is no more input data or no more space in the output buffer (see below about the flush parameter). Before the call of inflate(), the application should ensure that at least one of the actions is possible, by providing more input and/or consuming more output, and updating the next_* and avail_* values accordingly. The application can consume the uncompressed output when it wants, for example when the output buffer is full (avail_out == 0), or after each call of inflate(). If inflate returns Z_OK and with zero avail_out, it must be called again after making room in the output buffer because there might be more output pending. If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much output as possible to the output buffer. The flushing behavior of inflate is not specified for values of the flush parameter other than Z_SYNC_FLUSH and Z_FINISH, but the current implementation actually flushes as much output as possible anyway. inflate() should normally be called until it returns Z_STREAM_END or an error. However if all decompression is to be performed in a single step (a single call of inflate), the parameter flush should be set to Z_FINISH. In this case all pending input is processed and all pending output is flushed; avail_out must be large enough to hold all the uncompressed data. (The size of the uncompressed data may have been saved by the compressor for this purpose.) The next operation on this stream must be inflateEnd to deallocate the decompression state. The use of Z_FINISH is never required, but can be used to inform inflate that a faster routine may be used for the single inflate() call. If a preset dictionary is needed at this point (see inflateSetDictionary below), inflate sets strm-adler to the adler32 checksum of the dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise it sets strm->adler to the adler32 checksum of all output produced so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described below. At the end of the stream, inflate() checks that its computed adler32 checksum is equal to that saved by the compressor and returns Z_STREAM_END only if the checksum is correct. inflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if the end of the compressed data has been reached and all uncompressed output has been produced, Z_NEED_DICT if a preset dictionary is needed at this point, Z_DATA_ERROR if the input data was corrupted (input stream not conforming to the zlib format or incorrect adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if no progress is possible or if there was not enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR case, the application may then call inflateSync to look for a good compression block. */ ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); /* All dynamically allocated data structures for this stream are freed. This function discards any unprocessed input and does not flush any pending output. inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state was inconsistent. In the error case, msg may be set but then points to a static string (which must not be deallocated). */ /* Advanced functions */ /* The following functions are needed only in some special applications. */ /* ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, int level, int method, int windowBits, int memLevel, int strategy)); This is another version of deflateInit with more compression options. The fields next_in, zalloc, zfree and opaque must be initialized before by the caller. The method parameter is the compression method. It must be Z_DEFLATED in this version of the library. The windowBits parameter is the base two logarithm of the window size (the size of the history buffer). It should be in the range 8..15 for this version of the library. Larger values of this parameter result in better compression at the expense of memory usage. The default value is 15 if deflateInit is used instead. The memLevel parameter specifies how much memory should be allocated for the internal compression state. memLevel=1 uses minimum memory but is slow and reduces compression ratio; memLevel=9 uses maximum memory for optimal speed. The default value is 8. See zconf.h for total memory usage as a function of windowBits and memLevel. The strategy parameter is used to tune the compression algorithm. Use the value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no string match). Filtered data consists mostly of small values with a somewhat random distribution. In this case, the compression algorithm is tuned to compress them better. The effect of Z_FILTERED is to force more Huffman coding and less string matching; it is somewhat intermediate between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects the compression ratio but not the correctness of the compressed output even if it is not set appropriately. deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid method). msg is set to null if there is no error message. deflateInit2 does not perform any compression: this will be done by deflate(). */ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, const Bytef * dictionary, uInt dictLength)); /* Initializes the compression dictionary from the given byte sequence without producing any compressed output. This function must be called immediately after deflateInit, deflateInit2 or deflateReset, before any call of deflate. The compressor and decompressor must use exactly the same dictionary (see inflateSetDictionary). The dictionary should consist of strings (byte sequences) that are likely to be encountered later in the data to be compressed, with the most commonly used strings preferably put towards the end of the dictionary. Using a dictionary is most useful when the data to be compressed is short and can be predicted with good accuracy; the data can then be compressed better than with the default empty dictionary. Depending on the size of the compression data structures selected by deflateInit or deflateInit2, a part of the dictionary may in effect be discarded, for example if the dictionary is larger than the window size in deflate or deflate2. Thus the strings most likely to be useful should be put at the end of the dictionary, not at the front. Upon return of this function, strm->adler is set to the Adler32 value of the dictionary; the decompressor may later use this value to determine which dictionary has been used by the compressor. (The Adler32 value applies to the whole dictionary even if only a subset of the dictionary is actually used by the compressor.) deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a parameter is invalid (such as NULL dictionary) or the stream state is inconsistent (for example if deflate has already been called for this stream or if the compression method is bsort). deflateSetDictionary does not perform any compression: this will be done by deflate(). */ ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, z_streamp source)); /* Sets the destination stream as a complete copy of the source stream. This function can be useful when several compression strategies will be tried, for example when there are several ways of pre-processing the input data with a filter. The streams that will be discarded should then be freed by calling deflateEnd. Note that deflateCopy duplicates the internal compression state which can be quite large, so this strategy is slow and can consume lots of memory. deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc being NULL). msg is left unchanged in both source and destination. */ ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); /* This function is equivalent to deflateEnd followed by deflateInit, but does not free and reallocate all the internal compression state. The stream will keep the same compression level and any other attributes that may have been set by deflateInit2. deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being NULL). */ ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, int level, int strategy)); /* Dynamically update the compression level and compression strategy. The interpretation of level and strategy is as in deflateInit2. This can be used to switch between compression and straight copy of the input data, or to switch to a different kind of input data requiring a different strategy. If the compression level is changed, the input available so far is compressed with the old level (and may be flushed); the new level will take effect only at the next call of deflate(). Before the call of deflateParams, the stream state must be set as for a call of deflate(), since the currently available input may have to be compressed and flushed. In particular, strm->avail_out must be non-zero. deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if strm->avail_out was zero. */ /* ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, int windowBits)); This is another version of inflateInit with an extra parameter. The fields next_in, avail_in, zalloc, zfree and opaque must be initialized before by the caller. The windowBits parameter is the base two logarithm of the maximum window size (the size of the history buffer). It should be in the range 8..15 for this version of the library. The default value is 15 if inflateInit is used instead. If a compressed stream with a larger window size is given as input, inflate() will return with the error code Z_DATA_ERROR instead of trying to allocate a larger window. inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative memLevel). msg is set to null if there is no error message. inflateInit2 does not perform any decompression apart from reading the zlib header if present: this will be done by inflate(). (So next_in and avail_in may be modified, but next_out and avail_out are unchanged.) */ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, const Bytef * dictionary, uInt dictLength)); /* Initializes the decompression dictionary from the given uncompressed byte sequence. This function must be called immediately after a call of inflate if this call returned Z_NEED_DICT. The dictionary chosen by the compressor can be determined from the Adler32 value returned by this call of inflate. The compressor and decompressor must use exactly the same dictionary (see deflateSetDictionary). inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a parameter is invalid (such as NULL dictionary) or the stream state is inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the expected one (incorrect Adler32 value). inflateSetDictionary does not perform any decompression: this will be done by subsequent calls of inflate(). */ ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); /* Skips invalid compressed data until a full flush point (see above the description of deflate with Z_FULL_FLUSH) can be found, or until all available input is skipped. No output is provided. inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. In the success case, the application may save the current current value of total_in which indicates where valid compressed data was found. In the error case, the application may repeatedly call inflateSync, providing more input each time, until success or end of the input data. */ ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); /* This function is equivalent to inflateEnd followed by inflateInit, but does not free and reallocate all the internal decompression state. The stream will keep attributes that may have been set by inflateInit2. inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being NULL). */ /* utility functions */ /* The following utility functions are implemented on top of the basic stream-oriented functions. To simplify the interface, some default options are assumed (compression level and memory usage, standard memory allocation functions). The source code of these utility functions can easily be modified if you need special options. */ ZEXTERN int ZEXPORT compress OF((Bytef * dest, uLongf * destLen, const Bytef * source, uLong sourceLen)); /* Compresses the source buffer into the destination buffer. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be at least 0.1% larger than sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. This function can be used to compress a whole file at once if the input file is mmap'ed. compress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer. */ ZEXTERN int ZEXPORT compress2 OF((Bytef * dest, uLongf * destLen, const Bytef * source, uLong sourceLen, int level)); /* Compresses the source buffer into the destination buffer. The level parameter has the same meaning as in deflateInit. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be at least 0.1% larger than sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, Z_STREAM_ERROR if the level parameter is invalid. */ ZEXTERN int ZEXPORT uncompress OF((Bytef * dest, uLongf * destLen, const Bytef * source, uLong sourceLen)); /* Decompresses the source buffer into the destination buffer. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be large enough to hold the entire uncompressed data. (The size of the uncompressed data must have been saved previously by the compressor and transmitted to the decompressor by some mechanism outside the scope of this compression library.) Upon exit, destLen is the actual size of the compressed buffer. This function can be used to decompress a whole file at once if the input file is mmap'ed. uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, or Z_DATA_ERROR if the input data was corrupted. */ typedef voidp gzFile; ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); /* Opens a gzip (.gz) file for reading or writing. The mode parameter is as in fopen ("rb" or "wb") but can also include a compression level ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman only compression as in "wb1h". (See the description of deflateInit2 for more information about the strategy parameter.) gzopen can be used to read a file which is not in gzip format; in this case gzread will directly read from the file without decompression. gzopen returns NULL if the file could not be opened or if there was insufficient memory to allocate the (de)compression state; errno can be checked to distinguish the two cases (if errno is zero, the zlib error is Z_MEM_ERROR). */ ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); /* gzdopen() associates a gzFile with the file descriptor fd. File descriptors are obtained from calls like open, dup, creat, pipe or fileno (in the file has been previously opened with fopen). The mode parameter is as in gzopen. The next call of gzclose on the returned gzFile will also close the file descriptor fd, just like fclose(fdopen(fd), mode) closes the file descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). gzdopen returns NULL if there was insufficient memory to allocate the (de)compression state. */ ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); /* Dynamically update the compression level or strategy. See the description of deflateInit2 for the meaning of these parameters. gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not opened for writing. */ ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); /* Reads the given number of uncompressed bytes from the compressed file. If the input file was not in gzip format, gzread copies the given number of bytes into the buffer. gzread returns the number of uncompressed bytes actually read (0 for end of file, -1 for error). */ ZEXTERN int ZEXPORT gzwrite OF((gzFile file, const voidp buf, unsigned len)); /* Writes the given number of uncompressed bytes into the compressed file. gzwrite returns the number of uncompressed bytes actually written (0 in case of error). */ ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); /* Converts, formats, and writes the args to the compressed file under control of the format string, as in fprintf. gzprintf returns the number of uncompressed bytes actually written (0 in case of error). */ ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); /* Writes the given null-terminated string to the compressed file, excluding the terminating null character. gzputs returns the number of characters written, or -1 in case of error. */ ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); /* Reads bytes from the compressed file until len-1 characters are read, or a newline character is read and transferred to buf, or an end-of-file condition is encountered. The string is then terminated with a null character. gzgets returns buf, or Z_NULL in case of error. */ ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); /* Writes c, converted to an unsigned char, into the compressed file. gzputc returns the value that was written, or -1 in case of error. */ ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); /* Reads one byte from the compressed file. gzgetc returns this byte or -1 in case of end of file or error. */ ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); /* Flushes all pending output into the compressed file. The parameter flush is as in the deflate() function. The return value is the zlib error number (see function gzerror below). gzflush returns Z_OK if the flush parameter is Z_FINISH and all output could be flushed. gzflush should be called only when strictly necessary because it can degrade compression. */ ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, z_off_t offset, int whence)); /* Sets the starting position for the next gzread or gzwrite on the given compressed file. The offset represents a number of bytes in the uncompressed data stream. The whence parameter is defined as in lseek(2); the value SEEK_END is not supported. If the file is opened for reading, this function is emulated but can be extremely slow. If the file is opened for writing, only forward seeks are supported; gzseek then compresses a sequence of zeroes up to the new starting position. gzseek returns the resulting offset location as measured in bytes from the beginning of the uncompressed stream, or -1 in case of error, in particular if the file is opened for writing and the new starting position would be before the current position. */ ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); /* Rewinds the given file. This function is supported only for reading. gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) */ ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); /* Returns the starting position for the next gzread or gzwrite on the given compressed file. This position represents a number of bytes in the uncompressed data stream. gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) */ ZEXTERN int ZEXPORT gzeof OF((gzFile file)); /* Returns 1 when EOF has previously been detected reading the given input stream, otherwise zero. */ ZEXTERN int ZEXPORT gzclose OF((gzFile file)); /* Flushes all pending output if necessary, closes the compressed file and deallocates all the (de)compression state. The return value is the zlib error number (see function gzerror below). */ ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); /* Returns the error message for the last error which occurred on the given compressed file. errnum is set to zlib error number. If an error occurred in the file system and not in the compression library, errnum is set to Z_ERRNO and the application may consult errno to get the exact error code. */ /* checksum functions */ /* These functions are not related to compression but are exported anyway because they might be useful in applications using the compression library. */ ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef * buf, uInt len)); /* Update a running Adler-32 checksum with the bytes buf[0..len-1] and return the updated checksum. If buf is NULL, this function returns the required initial value for the checksum. An Adler-32 checksum is almost as reliable as a CRC32 but can be computed much faster. Usage example: uLong adler = adler32(0L, Z_NULL, 0); while (read_buffer(buffer, length) != EOF) { adler = adler32(adler, buffer, length); } if (adler != original_adler) error(); */ ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef * buf, uInt len)); /* Update a running crc with the bytes buf[0..len-1] and return the updated crc. If buf is NULL, this function returns the required initial value for the crc. Pre- and post-conditioning (one's complement) is performed within this function so it shouldn't be done by the application. Usage example: uLong crc = crc32(0L, Z_NULL, 0); while (read_buffer(buffer, length) != EOF) { crc = crc32(crc, buffer, length); } if (crc != original_crc) error(); */ /* various hacks, don't look :) */ /* deflateInit and inflateInit are macros to allow checking the zlib version * and the compiler's view of z_stream: */ ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, const char *version, int stream_size)); ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, const char *version, int stream_size)); ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, int windowBits, int memLevel, int strategy, const char *version, int stream_size)); ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, const char *version, int stream_size)); #define deflateInit(strm, level) \ deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) #define inflateInit(strm) \ inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) #define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ deflateInit2_((strm), (level), (method), (windowBits), (memLevel), \ (strategy), ZLIB_VERSION, sizeof(z_stream)) #define inflateInit2(strm, windowBits) \ inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) #if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL) struct internal_state { int dummy; }; /* hack for buggy compilers */ #endif ZEXTERN const char * ZEXPORT zError OF((int err)); ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); #ifdef __cplusplus } #endif #endif /* _ZLIB_H */ libreswan-3.32/linux/include/zlib/zutil.h000066400000000000000000000120401365625662500205060ustar00rootroot00000000000000/* zutil.h -- internal interface and configuration of the compression library * Copyright (C) 1995-2002 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ /* @(#) $Id: zutil.h,v 1.4 2002/04/24 07:36:48 mcr Exp $ */ #ifndef _Z_UTIL_H #define _Z_UTIL_H #include "zlib.h" #include #define HAVE_MEMCPY #if 0 // #ifdef STDC # include # include # include #endif #ifndef __KERNEL__ #ifdef NO_ERRNO_H extern int errno; #else # include #endif #endif #ifndef local # define local static #endif /* compile with -Dlocal if your debugger can't find static symbols */ typedef unsigned char uch; typedef uch FAR uchf; typedef unsigned short ush; typedef ush FAR ushf; typedef unsigned long ulg; extern const char *z_errmsg[10]; /* indexed by 2-zlib_error */ /* (size given to avoid silly warnings with Visual C++) */ #define ERR_MSG(err) z_errmsg[Z_NEED_DICT - (err)] #define ERR_RETURN(strm, err) \ return (strm->msg = ERR_MSG(err), (err)) /* To be used only when the state is known to be valid */ /* common constants */ #ifndef DEF_WBITS # define DEF_WBITS MAX_WBITS #endif /* default windowBits for decompression. MAX_WBITS is for compression only */ #if MAX_MEM_LEVEL >= 8 # define DEF_MEM_LEVEL 8 #else # define DEF_MEM_LEVEL MAX_MEM_LEVEL #endif /* default memLevel */ #define STORED_BLOCK 0 #define STATIC_TREES 1 #define DYN_TREES 2 /* The three kinds of block type */ #define MIN_MATCH 3 #define MAX_MATCH 258 /* The minimum and maximum match lengths */ #define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ /* target dependencies */ #ifdef MSDOS # define OS_CODE 0x00 # if defined(__TURBOC__) || defined(__BORLANDC__) # if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) /* Allow compilation with ANSI keywords only enabled */ void _Cdecl farfree( void *block ); void *_Cdecl farmalloc( unsigned long nbytes ); # else # include # endif # else /* MSC or DJGPP */ # include # endif #endif #ifdef OS2 # define OS_CODE 0x06 #endif #ifdef WIN32 /* Window 95 & Windows NT */ # define OS_CODE 0x0b #endif #if defined(VAXC) || defined(VMS) # define OS_CODE 0x02 # define F_OPEN(name, mode) \ fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") #endif #ifdef AMIGA # define OS_CODE 0x01 #endif #if defined(ATARI) || defined(atarist) # define OS_CODE 0x05 #endif #if defined(MACOS) || defined(TARGET_OS_MAC) # define OS_CODE 0x07 # if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os # include /* for fdopen */ # else # ifndef fdopen # define fdopen(fd, mode) NULL /* No fdopen() */ # endif # endif #endif #ifdef __50SERIES /* Prime/PRIMOS */ # define OS_CODE 0x0F #endif #ifdef TOPS20 # define OS_CODE 0x0a #endif #if defined(_BEOS_) || defined(RISCOS) # define fdopen(fd, mode) NULL /* No fdopen() */ #endif #if (defined(_MSC_VER) && (_MSC_VER > 600)) # define fdopen(fd, type) _fdopen(fd, type) #endif /* Common defaults */ #ifndef OS_CODE # define OS_CODE 0x03 /* assume Unix */ #endif #ifndef F_OPEN # define F_OPEN(name, mode) fopen((name), (mode)) #endif /* functions */ #ifdef HAVE_STRERROR extern char *strerror OF((int)); # define zstrerror(errnum) strerror(errnum) #else # define zstrerror(errnum) "" #endif #if defined(pyr) # define NO_MEMCPY #endif #if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) /* Use our own functions for small and medium model with MSC <= 5.0. * You may have to use the same strategy for Borland C (untested). * The __SC__ check is for Symantec. */ # define NO_MEMCPY #endif #if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) # define HAVE_MEMCPY #endif #ifdef HAVE_MEMCPY # ifdef SMALL_MEDIUM /* MSDOS small or medium model */ # define zmemcpy _fmemcpy # define zmemcmp _fmemcmp # define zmemzero(dest, len) _fmemset(dest, 0, len) # else # define zmemcpy memcpy # define zmemcmp memcmp # define zmemzero(dest, len) memset(dest, 0, len) # endif #else extern void zmemcpy OF((Bytef * dest, const Bytef * source, uInt len)); extern int zmemcmp OF((const Bytef * s1, const Bytef * s2, uInt len)); extern void zmemzero OF((Bytef * dest, uInt len)); #endif /* Diagnostic functions */ #define Assert(cond, msg) #define Trace(x) #define Tracev(x) #define Tracevv(x) #define Tracec(c, x) #define Tracecv(c, x) typedef uLong (ZEXPORT * check_func) OF ((uLong check, const Bytef * buf, uInt len)); voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); void zcfree OF((voidpf opaque, voidpf ptr)); #define ZALLOC(strm, items, size) \ (*((strm)->zalloc))((strm)->opaque, (items), (size)) #define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) #define TRY_FREE(s, p) { if (p) \ ZFREE(s, p); } #endif /* _Z_UTIL_H */ libreswan-3.32/linux/net/000077500000000000000000000000001365625662500153745ustar00rootroot00000000000000libreswan-3.32/linux/net/Config.in.fs2_4.patch000066400000000000000000000005101365625662500211370ustar00rootroot00000000000000--- linux/net/Config.in.orig Fri Feb 9 14:34:13 2001 +++ linux/net/Config.in Thu Feb 22 19:40:08 2001 @@ -88,4 +88,9 @@ #bool 'Network code profiler' CONFIG_NET_PROFILE endmenu +tristate 'IP Security Protocol (Libreswan IPSEC)' CONFIG_KLIPS +if [ "$CONFIG_KLIPS" != "n" ]; then + source net/ipsec/Config.in +fi + endmenu libreswan-3.32/linux/net/Kconfig.fs2_6.patch000066400000000000000000000003371365625662500207160ustar00rootroot00000000000000--- swan26/net/Kconfig.preipsec 2005-09-01 18:15:19.000000000 -0400 +++ swan26/net/Kconfig 2005-09-03 16:51:17.000000000 -0400 @@ -215,2 +215,6 @@ +if INET +source "net/ipsec/Kconfig" +endif # if INET + endif # if NET libreswan-3.32/linux/net/Makefile.fs2_4.patch000066400000000000000000000005211365625662500210440ustar00rootroot00000000000000--- linux/net/Makefile.preipsec Mon Jun 11 22:15:27 2001 +++ linux/net/Makefile Tue Nov 6 21:07:43 2001 @@ -17,6 +17,7 @@ subdir-$(CONFIG_NET) += 802 sched subdir-$(CONFIG_INET) += ipv4 subdir-$(CONFIG_NETFILTER) += ipv4/netfilter +subdir-$(CONFIG_KLIPS) += ipsec subdir-$(CONFIG_UNIX) += unix subdir-$(CONFIG_IPV6) += ipv6 libreswan-3.32/linux/net/Makefile.fs2_6.patch000066400000000000000000000006771365625662500210620ustar00rootroot00000000000000--- /distros/kernel/linux-2.6.35/net/Makefile 2010-12-01 16:57:05.368652908 -0600 +++ ref26/net/Makefile 2010-12-01 17:42:56.828648131 -0600 @@ -18,6 +18,7 @@ obj-$(CONFIG_NETFILTER) += netfilter/ obj-$(CONFIG_INET) += ipv4/ obj-$(CONFIG_XFRM) += xfrm/ +obj-$(CONFIG_KLIPS) += ipsec/ obj-$(CONFIG_UNIX) += unix/ ifneq ($(CONFIG_IPV6),) obj-y += ipv6/ libreswan-3.32/linux/net/ipsec/000077500000000000000000000000001365625662500164775ustar00rootroot00000000000000libreswan-3.32/linux/net/ipsec/Config.in.os2_4000066400000000000000000000033421365625662500211630ustar00rootroot00000000000000# # IPSEC configuration # Copyright (C) 1998, 1999, 2000,2001 Richard Guy Briggs. # Copyright (C) 2004 Michael Richardson # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. comment 'IPsec options (Libreswan)' bool ' IPsec: IP-in-IP encapsulation (tunnel mode)' CONFIG_KLIPS_IPIP bool ' IPsec: Authentication Header' CONFIG_KLIPS_AH bool ' IPsec: Encapsulating Security Payload' CONFIG_KLIPS_ESP comment ' IPsec algorithms to include' if [ "$CONFIG_KLIPS_ESP" = "y" ]; then bool ' 3DES encryption algorithm' CONFIG_KLIPS_ENC_3DES bool ' AES encryption algorithm' CONFIG_KLIPS_ENC_AES fi if [ "$CONFIG_KLIPS_AH" = "y" -o "$CONFIG_KLIPS_ESP" = "y" ]; then bool ' HMAC-MD5 authentication algorithm' CONFIG_KLIPS_AUTH_HMAC_MD5 bool ' HMAC-SHA1 authentication algorithm' CONFIG_KLIPS_AUTH_HMAC_SHA1 fi bool ' IPsec Modular Extensions' CONFIG_KLIPS_ALG if [ "$CONFIG_KLIPS_ALG" != "n" ]; then bool ' CryptoAPI algorithm interface' CONFIG_KLIPS_ENC_CRYPTOAPI fi bool ' IPsec: IP Compression' CONFIG_KLIPS_IPCOMP bool ' IPsec Debugging Option' CONFIG_KLIPS_DEBUG bool ' IPsec: OCF HW Acceleration support' CONFIG_KLIPS_OCF bool ' IPsec: Backwards compatible NAT NFMARK' CONFIG_KLIPS_COMPAT_NAT_NFMARK libreswan-3.32/linux/net/ipsec/Kconfig000066400000000000000000000121441365625662500200040ustar00rootroot00000000000000# # IPSEC configuration # Copyright (C) 2004 Michael Richardson # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # config KLIPS tristate "Libreswan IPsec (KLIPS)" default n # depends on NF_CONNTRACK && NETFILTER help KLIPS is the Libreswan (www.libreswan.org) Kernel Level IP Security system. It is extensively tested, and has interoperated with many other systems. It provides "ipsecX" devices on which one can do firewalling. The Libreswan userland, is compatible with both KLIPS and NETKEY You cannot build KLIPS and NETKEY inline into the kernel. menu "KLIPS options" depends on KLIPS config KLIPS_ESP bool 'Encapsulating Security Payload - ESP ("VPN")' default y help This option provides support for the IPSEC Encapsulation Security Payload (IP protocol 50) which provides packet layer content hiding, and content authentication. It is recommended to enable this. RFC2406 config KLIPS_AH bool 'Authentication Header - AH' default n help This option provides support for the IPSEC Authentication Header (IP protocol 51) which provides packet layer sender and content authentication. It does not provide for confidentiality. It is not recommended to enable this. RFC2402 config KLIPS_AUTH_HMAC_MD5 bool 'HMAC-MD5 authentication algorithm' default y help The HMAC-MD5 algorithm is used by ESP (and AH) to guarantee packet integrity. There is little reason not to include it. config KLIPS_AUTH_HMAC_SHA1 bool 'HMAC-SHA1 authentication algorithm' default y help The HMAC-SHA1 algorithm is used by ESP (and AH) to guarantee packet integrity. SHA1 is a little slower than MD5, but is said to be a bit more secure. There is little reason not to include it. config KLIPS_ALG bool 'KLIPS_ALG software encryption' default y help This option provides support for loading new algorithms into the kernel for crypto use. You may disable this if using the CONFIG_KLIPS_OCF option for hardware offload. config KLIPS_ENC_CRYPTOAPI bool 'CryptoAPI algorithm interface' default y depends on KLIPS_ALG help Enable the algorithm interface to make all CryptoAPI 1.0 algorithms available to KLIPS. config KLIPS_ENC_3DES bool '3DES encryption algorithm' default y help The 3DES algorithm is used by ESP to provide for packet privacy. 3DES is 3-repeats of the DES algorithm. 3DES is widely supported, and analyzed and is considered very secure. 1DES is not supported. config KLIPS_ENC_AES bool 'AES encryption algorithm' default y depends on KLIPS_ALG help The AES algorithm is used by ESP to provide for packet privacy. AES the NIST replacement for DES. AES is being widely analyzed, and is very fast. config KLIPS_IPCOMP bool 'IP compression' default y help The IPcomp protocol is used prior to ESP to make the packet smaller. Once encrypted, compression will fail, so any link layer efforts (e.g. PPP) will not work. config KLIPS_OCF bool 'IPsec OCF Acceleration Support' default n help OCF provides Asynchronous crypto acceleration for kernel and user applications. It supports various HW accelerators. If you have OCF support enabled and wish IPsec to utilise the hardware managed by OCF, then enable this option. OCF is a kernel patch, see http://ocf-linux.sourceforge.net/ config KLIPS_COMPAT_NAT_NFMARK bool 'IPsec: Backwards compatible NAT NFMARK' default n help Pre-2.6.23 kernels requiring the NAT-Traversal patch use the NFmark feature to mark packets for UDP decapsulation. Kernels since 2.6.23 have native support and do not need to place this nfmark - leaving all nfmark space available to other kernel modules or userland applications. Leave this off when using kernels > 2.6.23 config KLIPS_DEBUG bool 'IPsec debugging' default y help KLIPS includes a lot of debugging code. Unless there is a real tangible benefit to removing this code, it should be left in place. Debugging connections without access to kernel level debugging is essentially impossible. Leave this on. config KLIPS_IF_MAX int 'Maximum number of virtual interfaces' default 64 range 4 256 help KLIPS creates virtual interfaces for tunnel purposes. At present it keeps track of certain items in an array (FIX ME), and needs to preallocate this array. Only a pointer is used per item. config KLIPS_IF_NUM int 'Number of virtual interfaces to auto create' default 2 range 0 256 help KLIPS will auto create a number of interfaces, any further interfaces need to be created with tncfg. endmenu libreswan-3.32/linux/net/ipsec/Makefile.fs2_4000066400000000000000000000153101365625662500210530ustar00rootroot00000000000000# Makefile for KLIPS kernel code as a module for 2.4 kernels # # Makefile for KLIPS kernel code as a module # Copyright (C) 1998, 1999, 2000,2001 Richard Guy Briggs. # Copyright (C) 2002,2003 Michael Richardson # Copyright (C) 2004 Michael Richardson # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # # Note! Dependencies are done automagically by 'make dep', which also # removes any old dependencies. DON'T put your own dependencies here # unless it's something special (ie not a .c file). # ifeq ($(strip $(KLIPSMODULE)),) LIBRESWANSRCDIR=. else LIBRESWANSRCDIR=../../.. endif -include ${LIBRESWANSRCDIR}/Makefile.ver ifeq ($(strip $(KLIPS_TOP)),) KLIPS_TOP=../.. endif ifneq ($(strip $(KLIPSMODULE)),) ifndef TOPDIR TOPDIR:=/usr/src/linux endif export TOPDIR endif subdir- := subdir-n := subdir-y := subdir-m := export-objs := exportobj-y := MOD_DESTDIR:=net/ipsec export TOPDIR all: ipsec.o foo: echo KERNEL: ${KERNEL_CFLAGS} echo MODULE: ${MODULE_CFLAGS} ipsec.o: foo # always force it on CONFIG_KLIPS_ESP:=y CONFIG_KLIPS_IPIP:=y O_TARGET := ipsec.o obj-y := ipsec_init.o ipsec_sa.o ipsec_radij.o radij.o obj-y += ipsec_life.o ipsec_proc.o ipsec_mast.o obj-y += ipsec_tunnel.o ipsec_xmit.o ipsec_rcv.o ipsec_ipip.o obj-y += sysctl_net_ipsec.o obj-y += ipsec_snprintf.o ipsec_kern24.o obj-y += pfkey_v2.o pfkey_v2_parser.o pfkey_v2_ext_process.o obj-y += version.o obj-$(CONFIG_KLIPS_ESP) += ipsec_esp.o obj-$(CONFIG_KLIPS_OCF) += ipsec_ocf.o obj-$(CONFIG_KLIPS_IPCOMP) += ipsec_ipcomp.o # AH, if you really think you need it. obj-$(CONFIG_KLIPS_AH) += ipsec_ah.o CFLAGS_ipsec_alg.o += -DEXPORT_SYMTAB obj-$(CONFIG_KLIPS_ALG) += ipsec_alg.o obj-$(CONFIG_KLIPS_ENC_AES) += ipsec_alg_aes.o obj-$(CONFIG_KLIPS_ENC_CRYPTOAPI) += ipsec_alg_cryptoapi.o VPATH+=${KLIPS_TOP}/net/ipsec/des obj-$(CONFIG_KLIPS_ENC_3DES) += ipsec_alg_3des.o obj-$(CONFIG_KLIPS_ENC_3DES) += cbc_enc.o obj-$(CONFIG_KLIPS_ENC_3DES) += ecb_enc.o obj-$(CONFIG_KLIPS_ENC_3DES) += set_key.o VPATH+=${KLIPS_TOP}/net/ipsec/aes ASM-$(ARCH_ASM):=1 ASM_X86:=$(ASM-i586)$(ASM-i686) ifneq ($(strip $(ASM_X86)),) obj-$(CONFIG_KLIPS_ENC_AES) += aes-i586.o # and use assembly version of zlib code. CFLAGS+=-DASMV else obj-$(CONFIG_KLIPS_ENC_AES) += aes.o endif obj-$(CONFIG_KLIPS_ENC_AES) += aes_cbc.o obj-$(CONFIG_KLIPS_ENC_AES) += aes_xcbc_mac.o ifeq ($(strip ${SUBARCH}),) SUBARCH:=${ARCH} endif ifeq (${SUBARCH},i386) obj-$(CONFIG_KLIPS_ENC_3DES) += dx86unix.o else obj-$(CONFIG_KLIPS_ENC_3DES) += des_enc.o endif obj-y += satot.o obj-y += addrtot.o obj-y += ultot.o obj-y += addrtypeof.o obj-y += anyaddr.o obj-y += initaddr.o obj-y += addrtoa.o obj-y += subnettoa.o obj-y += subnetof.o obj-y += goodmask.o obj-y += datatot.o obj-y += prng.o obj-y += pfkey_v2_parse.o obj-y += pfkey_v2_build.o obj-y += pfkey_v2_debug.o obj-y += pfkey_v2_ext_bits.o # IPcomp stuff obj-$(CONFIG_KLIPS_IPCOMP) += ipcomp.o obj-$(CONFIG_KLIPS_IPCOMP) += adler32.o obj-$(CONFIG_KLIPS_IPCOMP) += deflate.o obj-$(CONFIG_KLIPS_IPCOMP) += infblock.o obj-$(CONFIG_KLIPS_IPCOMP) += infcodes.o obj-$(CONFIG_KLIPS_IPCOMP) += inffast.o obj-$(CONFIG_KLIPS_IPCOMP) += inflate.o obj-$(CONFIG_KLIPS_IPCOMP) += inftrees.o obj-$(CONFIG_KLIPS_IPCOMP) += infutil.o obj-$(CONFIG_KLIPS_IPCOMP) += trees.o obj-$(CONFIG_KLIPS_IPCOMP) += zutil.o asm-obj-$(CONFIG_M586) += match586.o asm-obj-$(CONFIG_M586TSC) += match586.o asm-obj-$(CONFIG_M586MMX) += match586.o asm-obj-$(CONFIG_M686) += match686.o asm-obj-$(CONFIG_MPENTIUMIII) += match686.o asm-obj-$(CONFIG_MPENTIUM4) += match686.o asm-obj-$(CONFIG_MK6) += match586.o asm-obj-$(CONFIG_MK7) += match686.o asm-obj-$(CONFIG_MCRUSOE) += match586.o asm-obj-$(CONFIG_MWINCHIPC6) += match586.o asm-obj-$(CONFIG_MWINCHIP2) += match686.o asm-obj-$(CONFIG_MWINCHIP3D) += match686.o obj-m += $(O_TARGET) #ifeq ($(CONFIG_KLIPS_DEBUG),y) #EXTRA_CFLAGS += -g #endif # MOST of these flags are in KERNEL_CFLAGS already! # cannot use both -Wpointer-arith and -Werror with CONFIG_HIGHMEM # include/linux/highmem.h has an inline function definition that uses void* arithmetic. ifeq ($(CONFIG_NOHIGHMEM),y) #EXTRA_CFLAGS += -Wpointer-arith endif #EXTRA_CFLAGS += -Wcast-qual #EXTRA_CFLAGS += -Wmissing-declarations #EXTRA_CFLAGS += -Wstrict-prototypes #EXTRA_CFLAGS += -pedantic #EXTRA_CFLAGS += -O3 #EXTRA_CFLAGS += -W #EXTRA_CFLAGS += -Wwrite-strings #EXTRA_CFLAGS += -Wbad-function-cast EXTRA_CFLAGS += -DIPCOMP_PREFIX ifneq ($(wildcard ${TOPDIR}/crypto/ocf),) EXTRA_CFLAGS += -I${TOPDIR}/crypto/ocf endif EXTRA_CFLAGS += -DKLIPS=1 ifneq ($(strip $(KLIPSMODULE)),) # for when we aren't building in the kernel tree EXTRA_CFLAGS += -DARCH=${ARCH} EXTRA_CFLAGS += -DMODVERSIONS EXTRA_CFLAGS += -include ${TOPDIR}/include/linux/modversions.h EXTRA_CFLAGS += ${MODULE_CFLAGS} endif # GCC 3.2 (and we presume any other 3.x) wants -falign-functions # in place of the traditional -malign-functions. Getting this # wrong leads to a warning, which is fatal due to our use of -Werror. ifeq ($(patsubst 3.%,3,$(shell $(CC) -dumpversion)),3) override CFLAGS:=$(subst -malign-functions=,-falign-functions=,$(CFLAGS)) endif obj-$(CONFIG_KLIPS_AUTH_HMAC_MD5) += ipsec_md5c.o obj-$(CONFIG_KLIPS_AUTH_HMAC_SHA1) += ipsec_sha1.o # These rules translate from new to old makefile rules # Translate to Rules.make lists. multi-used := $(filter $(list-multi), $(obj-y) $(obj-m)) multi-objs := $(foreach m, $(multi-used), $($(basename $(m))-objs)) active-objs := $(sort $(multi-objs) $(obj-y) $(obj-m)) O_OBJS := $(filter-out $(export-objs), $(obj-y)) OX_OBJS := $(filter $(export-objs), $(obj-y)) M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m))) MX_OBJS := $(sort $(filter $(export-objs), $(obj-m))) SUB_DIRS := $(subdir-y) ALL_SUB_DIRS := $(subdir-y) $(subdir-m) MOD_SUB_DIRS := $(subdir-m) include $(TOPDIR)/Rules.make $(obj-y) $(obj-m): $(TOPDIR)/include/linux/config.h $(TOPDIR)/include/linux/autoconf.h USE_STANDARD_AS_RULE=true tags TAGS: *.c *.h libfreeswan/*.c libfreeswan/*.h etags *.c ../../include/*.h ../../include/freeswan/*.h ctags *.c ../../include/*.h ../../include/freeswan/*.h baz: @echo OX: ${OX_OBJS} @echo MIX: ${MIX_OBJS} @echo O: ${O_OBJS} @echo M: ${M_OBJS} tar: tar -cvf /dev/f1 . libreswan-3.32/linux/net/ipsec/Makefile.fs2_6000066400000000000000000000111051365625662500210530ustar00rootroot00000000000000# Makefile for KLIPS kernel code as a module for 2.6 kernels # # Makefile for KLIPS kernel code as a module # Copyright (C) 1998, 1999, 2000,2001 Richard Guy Briggs. # Copyright (C) 2002-2004 Michael Richardson # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # # Note! Dependencies are done automagically by 'make dep', which also # removes any old dependencies. DON'T put your own dependencies here # unless it's something special (ie not a .c file). # LIBRESWANSRCDIR?=. KLIPS_TOP?=. -include ${LIBRESWANSRCDIR}/Makefile.ver base-klips-objs := base-klips-objs+= ipsec_init.o ipsec_sa.o ipsec_radij.o radij.o base-klips-objs+= ipsec_life.o ipsec_proc.o base-klips-objs+= ipsec_tunnel.o ipsec_xmit.o ipsec_rcv.o ipsec_ipip.o base-klips-objs+= ipsec_snprintf.o base-klips-objs+= ipsec_mast.o base-klips-objs+= sysctl_net_ipsec.o base-klips-objs+= pfkey_v2.o pfkey_v2_parser.o pfkey_v2_ext_process.o base-klips-objs+= version.o base-klips-objs+= satot.o base-klips-objs+= addrtot.o base-klips-objs+= ultot.o base-klips-objs+= addrtypeof.o base-klips-objs+= anyaddr.o base-klips-objs+= initaddr.o base-klips-objs+= addrtoa.o base-klips-objs+= subnettoa.o base-klips-objs+= subnetof.o base-klips-objs+= goodmask.o base-klips-objs+= datatot.o base-klips-objs+= prng.o base-klips-objs+= pfkey_v2_parse.o base-klips-objs+= pfkey_v2_build.o base-klips-objs+= pfkey_v2_debug.o base-klips-objs+= pfkey_v2_ext_bits.o base-klips-objs+= version.o obj-${CONFIG_KLIPS} += ipsec.o ipsec-objs += ${base-klips-objs} ipsec-$(CONFIG_KLIPS_ESP) += ipsec_esp.o ipsec-$(CONFIG_KLIPS_OCF) += ipsec_ocf.o ipsec-$(CONFIG_KLIPS_IPCOMP) += ipsec_ipcomp.o ipsec-$(CONFIG_KLIPS_AUTH_HMAC_MD5) += ipsec_md5c.o ipsec-$(CONFIG_KLIPS_AUTH_HMAC_SHA1) += ipsec_sha1.o # AH, if you really think you need it. ipsec-$(CONFIG_KLIPS_AH) += ipsec_ah.o ipsec-$(CONFIG_KLIPS_ALG) += ipsec_alg.o # include code from DES subdir crypto-$(CONFIG_KLIPS_ENC_3DES) += des/ipsec_alg_3des.o crypto-$(CONFIG_KLIPS_ENC_3DES) += des/cbc_enc.o crypto-$(CONFIG_KLIPS_ENC_3DES) += des/ecb_enc.o crypto-$(CONFIG_KLIPS_ENC_3DES) += des/set_key.o ifeq ($(strip ${SUBARCH}),) SUBARCH:=${ARCH} endif # the assembly version expects frame pointers, which are # optional in many kernel builds. If you want speed, you should # probably use cryptoapi code instead. #USEASSEMBLY=${SUBARCH}${CONFIG_FRAME_POINTER} #ifeq (${USEASSEMBLY},i386y) #crypto-$(CONFIG_KLIPS_ENC_3DES) += des/dx86unix.o #else crypto-$(CONFIG_KLIPS_ENC_3DES) += des/des_enc.o #endif # include code from AES subdir crypto-$(CONFIG_KLIPS_ENC_AES) += aes/ipsec_alg_aes.o crypto-$(CONFIG_KLIPS_ENC_AES) += aes/aes_xcbc_mac.o crypto-$(CONFIG_KLIPS_ENC_AES) += aes/aes_cbc.o ifeq ($(strip ${SUBARCH}),) SUBARCH:=${ARCH} endif #USEASSEMBLY=${SUBARCH}${CONFIG_FRAME_POINTER} #ifeq (${USEASSEMBLY},i386y) #crypto-$(CONFIG_KLIPS_ENC_AES) += aes/aes-i586.o #else crypto-$(CONFIG_KLIPS_ENC_AES) += aes/aes.o #endif ipsec-y += ${crypto-y} ipsec-$(CONFIG_KLIPS_ENC_CRYPTOAPI) += ipsec_alg_cryptoapi.o # IPcomp stuff base-ipcomp-objs := ipcomp.o base-ipcomp-objs += adler32.o base-ipcomp-objs += deflate.o base-ipcomp-objs += infblock.o base-ipcomp-objs += infcodes.o base-ipcomp-objs += inffast.o base-ipcomp-objs += inflate.o base-ipcomp-objs += inftrees.o base-ipcomp-objs += infutil.o base-ipcomp-objs += trees.o base-ipcomp-objs += zutil.o asm-ipcomp-obj-$(CONFIG_M586) += match586.o asm-ipcomp-obj-$(CONFIG_M586TSC) += match586.o asm-ipcomp-obj-$(CONFIG_M586MMX) += match586.o asm-ipcomp-obj-$(CONFIG_M686) += match686.o asm-ipcomp-obj-$(CONFIG_MPENTIUMIII) += match686.o asm-ipcomp-obj-$(CONFIG_MPENTIUM4) += match686.o asm-ipcomp-obj-$(CONFIG_MK6) += match586.o asm-ipcomp-obj-$(CONFIG_MK7) += match686.o asm-ipcomp-obj-$(CONFIG_MCRUSOE) += match586.o asm-ipcomp-obj-$(CONFIG_MWINCHIPC6) += match586.o asm-ipcomp-obj-$(CONFIG_MWINCHIP2) += match686.o asm-ipcomp-obj-$(CONFIG_MWINCHIP3D) += match686.o base-ipcomp-objs += ${asm-ipcomp-obj-y} ipsec-$(CONFIG_KLIPS_IPCOMP) += ${base-ipcomp-objs} EXTRA_CFLAGS += -DIPCOMP_PREFIX -DKLIPS EXTRA_CFLAGS += -Icrypto/ocf libreswan-3.32/linux/net/ipsec/README-zlib000066400000000000000000000153311365625662500203200ustar00rootroot00000000000000zlib 1.1.4 is a general purpose data compression library. All the code is thread safe. The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). These documents are also available in other formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html All functions of the compression library are documented in the file zlib.h (volunteer to write man pages welcome, contact jloup@gzip.org). A usage example of the library is given in the file example.c which also tests that the library is working correctly. Another example is given in the file minigzip.c. The compression library itself is composed of all source files except example.c and minigzip.c. To compile all files and run the test program, follow the instructions given at the top of Makefile. In short "make test; make install" should work for most machines. For Unix: "./configure; make test; make install" For MSDOS, use one of the special makefiles such as Makefile.msc. For VMS, use Make_vms.com or descrip.mms. Questions about zlib should be sent to , or to Gilles Vollant for the Windows DLL version. The zlib home page is http://www.zlib.org or http://www.gzip.org/zlib/ Before reporting a problem, please check this site to verify that you have the latest version of zlib; otherwise get the latest version and check whether the problem still exists or not. PLEASE read the zlib FAQ http://www.gzip.org/zlib/zlib_faq.html before asking for help. Mark Nelson wrote an article about zlib for the Jan. 1997 issue of Dr. Dobb's Journal; a copy of the article is available in http://dogma.net/markn/articles/zlibtool/zlibtool.htm The changes made in version 1.1.4 are documented in the file ChangeLog. The only changes made since 1.1.3 are bug corrections: - ZFREE was repeated on same allocation on some error conditions. This creates a security problem described in http://www.zlib.org/advisory-2002-03-11.txt - Returned incorrect error (Z_MEM_ERROR) on some invalid data - Avoid accesses before window for invalid distances with inflate window less than 32K. - force windowBits > 8 to avoid a bug in the encoder for a window size of 256 bytes. (A complete fix will be available in 1.1.5). The beta version 1.1.5beta includes many more changes. A new official version 1.1.5 will be released as soon as extensive testing has been completed on it. Unsupported third party contributions are provided in directory "contrib". A Java implementation of zlib is available in the Java Development Kit http://www.javasoft.com/products/JDK/1.1/docs/api/Package-java.util.zip.html See the zlib home page http://www.zlib.org for details. A Perl interface to zlib written by Paul Marquess is in the CPAN (Comprehensive Perl Archive Network) sites http://www.cpan.org/modules/by-module/Compress/ A Python interface to zlib written by A.M. Kuchling is available in Python 1.5 and later versions, see http://www.python.org/doc/lib/module-zlib.html A zlib binding for TCL written by Andreas Kupries is availlable at http://www.westend.com/~kupries/doc/trf/man/man.html An experimental package to read and write files in .zip format, written on top of zlib by Gilles Vollant , is available at http://www.winimage.com/zLibDll/unzip.html and also in the contrib/minizip directory of zlib. Notes for some targets: - To build a Windows DLL version, include in a DLL project zlib.def, zlib.rc and all .c files except example.c and minigzip.c; compile with -DZLIB_DLL The zlib DLL support was initially done by Alessandro Iacopetti and is now maintained by Gilles Vollant . Check the zlib DLL home page at http://www.winimage.com/zLibDll From Visual Basic, you can call the DLL functions which do not take a structure as argument: compress, uncompress and all gz* functions. See contrib/visual-basic.txt for more information, or get http://www.tcfb.com/dowseware/cmp-z-it.zip - For 64-bit Irix, deflate.c must be compiled without any optimization. With -O, one libpng test fails. The test works in 32 bit mode (with the -n32 compiler flag). The compiler bug has been reported to SGI. - zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works when compiled with cc. - on Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is necessary to get gzprintf working correctly. This is done by configure. - zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with other compilers. Use "make test" to check your compiler. - gzdopen is not supported on RISCOS, BEOS and by some Mac compilers. - For Turbo C the small model is supported only with reduced performance to avoid any far allocation; it was tested with -DMAX_WBITS=11 -DMAX_MEM_LEVEL=3 - For PalmOs, see http://www.cs.uit.no/~perm/PASTA/pilot/software.html Per Harald Myrvang Acknowledgments: The deflate format used by zlib was defined by Phil Katz. The deflate and zlib specifications were written by L. Peter Deutsch. Thanks to all the people who reported problems and suggested various improvements in zlib; they are too numerous to cite here. Copyright notice: (C) 1995-2002 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Jean-loup Gailly Mark Adler jloup@gzip.org madler@alumni.caltech.edu If you use the zlib library in a product, we would appreciate *not* receiving lengthy legal documents to sign. The sources are provided for free but without warranty of any kind. The library has been entirely written by Jean-loup Gailly and Mark Adler; it does not include third-party code. If you redistribute modified sources, we would appreciate that you include in the file ChangeLog history information documenting your changes. libreswan-3.32/linux/net/ipsec/README-zlib.freeswan000066400000000000000000000007331365625662500221310ustar00rootroot00000000000000The only changes made to these files for use in FreeS/WAN are: - In zconf.h, macros are defined to prefix global symbols with "ipcomp_" (or "_ipcomp"), when compiled with -DIPCOMP_PREFIX. - The copyright strings are defined local (static) The above changes are made to avoid name collisions with ppp_deflate and ext2compr. - Files not needed for FreeS/WAN have been removed See the "README" file for information about where to obtain the complete zlib package. libreswan-3.32/linux/net/ipsec/addrtoa.c000066400000000000000000000032641365625662500202660ustar00rootroot00000000000000/* * addresses to ASCII * Copyright (C) 1998, 1999 Henry Spencer. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. * */ #include "libreswan.h" #define NBYTES 4 /* bytes in an address */ #define PERBYTE 4 /* three digits plus a dot or NUL */ #define BUFLEN (NBYTES * PERBYTE) #if ADDRTOA_BUF < BUFLEN #error "ADDRTOA_BUF in libreswan.h inconsistent with addrtoa() code" #endif /* - addrtoa - convert binary address to ASCII dotted decimal */ size_t /* space needed for full conversion */ addrtoa(addr, format, dst, dstlen) struct in_addr addr; int format; /* character */ char *dst; /* need not be valid if dstlen is 0 */ size_t dstlen; { unsigned long a = ntohl(addr.s_addr); int i; size_t n; unsigned long byte; char buf[BUFLEN]; char *p; switch (format) { case 0: break; default: return 0; break; } p = buf; for (i = NBYTES - 1; i >= 0; i--) { byte = (a >> (i * 8)) & 0xff; p += ultot(byte, 10, p, PERBYTE); if (i != 0) *(p - 1) = '.'; } n = p - buf; if (dstlen > 0) { if (n > dstlen) buf[dstlen - 1] = '\0'; strcpy(dst, buf); } return n; } libreswan-3.32/linux/net/ipsec/addrtot.c000066400000000000000000000260551365625662500203140ustar00rootroot00000000000000/* * addresses to text * Copyright (C) 2000 Henry Spencer. * Copyright (C) 2012 Paul Wouters * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. * */ #if defined(__KERNEL__) && defined(__HAVE_ARCH_STRSTR) #include #endif #if !defined(__KERNEL__) # include #endif #include "libreswan.h" #define IP4BYTES 4 /* bytes in an IPv4 address */ #define PERBYTE 4 /* three digits plus a dot or NUL */ #define IP6BYTES 16 /* bytes in an IPv6 address */ /* forwards */ static size_t normal4(const unsigned char *s, size_t len, char *b, char **dp); static size_t normal6(const unsigned char *s, size_t len, char *b, char **dp, int squish); static size_t reverse4(const unsigned char *s, size_t len, char *b, char **dp); static size_t reverse6(const unsigned char *s, size_t len, char *b, char **dp); #if defined(__KERNEL__) && !defined(__HAVE_ARCH_STRSTR) #define strstr ipsec_strstr /* * Find the first occurrence of find in s. * (from NetBSD 1.6's /src/lib/libc/string/strstr.c) */ static char *ipsec_strstr(const char *s, const char *find) { char c, sc; size_t len; if ((c = *find++) != 0) { len = strlen(find); do { do { if ((sc = *s++) == 0) return NULL; } while (sc != c); } while (strncmp(s, find, len) != 0); s--; } /* LINTED interface specification */ return (char *)s; } #endif /* - addrtot - convert binary address to text (dotted decimal or IPv6 string) */ size_t /* space needed for full conversion */ addrtot(src, format, dst, dstlen) const ip_address * src; int format; /* character */ char *dst; /* need not be valid if dstlen is 0 */ size_t dstlen; { const unsigned char *b; size_t n; char buf[1 + ADDRTOT_BUF + 1]; /* :address: */ char *p; int t = addrtypeof(src); # define TF(t, f) (((t) << 8) | (f)) n = addrbytesptr_read(src, &b); if (n == 0) { dst[0] = '\0'; strncat(dst, "", dstlen - 1); /* we hope possible truncation does not cause problems */ return sizeof(""); } switch (TF(t, format)) { case TF(AF_INET, 0): n = normal4(b, n, buf, &p); break; case TF(AF_INET6, 0): n = normal6(b, n, buf, &p, 1); break; case TF(AF_INET, 'Q'): n = normal4(b, n, buf, &p); break; case TF(AF_INET6, 'Q'): n = normal6(b, n, buf, &p, 0); break; case TF(AF_INET, 'r'): n = reverse4(b, n, buf, &p); break; case TF(AF_INET6, 'r'): n = reverse6(b, n, buf, &p); break; default: /* including (AF_INET, 'R') */ dst[0] = '\0'; strncat(dst, "", dstlen - 1); /* we hope possible truncation does not cause problems */ return sizeof(""); } if (dstlen > 0) { if (dstlen < n) p[dstlen - 1] = '\0'; /* * clang 3.4 thinks dst or p are uninitialized. * I don't see how -- DHR */ strcpy(dst, p); } return n; } /* - inet_addrtot - convert binary inet address to text (dotted decimal or IPv6 string) */ size_t /* space needed for full conversion */ inet_addrtot(t, src, format, dst, dstlen) int t; /* AF_INET/AF_INET6 */ const void *src; int format; /* character */ char *dst; /* need not be valid if dstlen is 0 */ size_t dstlen; { size_t n; char buf[1 + ADDRTOT_BUF + 1]; /* :address: */ char *p; # define TF(t, f) (((t) << 8) | (f)) switch (t) { case AF_INET: n = IP4BYTES; break; case AF_INET6: n = IP6BYTES; break; default: dst[0] = '\0'; strncat(dst, "", dstlen - 1); /* we hope possible truncation does not cause problems */ return sizeof(""); } switch (TF(t, format)) { case TF(AF_INET, 0): n = normal4(src, n, buf, &p); break; case TF(AF_INET6, 0): n = normal6(src, n, buf, &p, 1); break; case TF(AF_INET, 'Q'): n = normal4(src, n, buf, &p); break; case TF(AF_INET6, 'Q'): n = normal6(src, n, buf, &p, 0); break; case TF(AF_INET, 'r'): n = reverse4(src, n, buf, &p); break; case TF(AF_INET6, 'r'): n = reverse6(src, n, buf, &p); break; default: /* including (AF_INET, 'R') */ dst[0] = '\0'; strncat(dst, "", dstlen - 1); /* we hope possible truncation does not cause problems */ return sizeof(""); } if (dstlen > 0) { if (dstlen < n) p[dstlen - 1] = '\0'; strcpy(dst, p); /* clang 6.0.0 mistakenly thinks p is undefined */ } return n; } /* * sin_addrtot - convert binary sockaddr_in/sockaddr_in6 address to text * (dotted decimal or IPv6 string) */ size_t /* space needed for full conversion */ sin_addrtot(src, format, dst, dstlen) const void *src; int format; /* character */ char *dst; /* need not be valid if dstlen is 0 */ size_t dstlen; { const union SINSIN6 { struct sockaddr_in sin; struct sockaddr_in6 sin6; } *sinp = (const union SINSIN6 *) src; switch (sinp->sin.sin_family) { case AF_INET: return inet_addrtot(AF_INET, &sinp->sin.sin_addr, format, dst, dstlen); case AF_INET6: return inet_addrtot(AF_INET6, &sinp->sin6.sin6_addr, format, dst, dstlen); default: dst[0] = '\0'; strncat(dst, "", dstlen - 1); /* we hope possible truncation does not cause problems */ return sizeof(""); } } /* - normal4 - normal IPv4 address-text conversion */ static size_t /* size of text, including NUL */ normal4(srcp, srclen, buf, dstp) const unsigned char *srcp; size_t srclen; char *buf; /* guaranteed large enough */ char **dstp; /* where to put result pointer */ { int i; char *p; if (srclen != IP4BYTES) /* "can't happen" */ return 0; p = buf; for (i = 0; i < IP4BYTES; i++) { p += ultot(srcp[i], 10, p, PERBYTE); if (i != IP4BYTES - 1) *(p - 1) = '.'; /* overwrites the NUL */ } *dstp = buf; return p - buf; } /* - normal6 - normal IPv6 address-text conversion */ static size_t /* size of text, including NUL */ normal6(srcp, srclen, buf, dstp, squish) const unsigned char *srcp; size_t srclen; char *buf; /* guaranteed large enough, plus 2 */ char **dstp; /* where to put result pointer */ int squish; /* whether to squish out 0:0 */ { int i; unsigned long piece; char *p; char *q; if (srclen != IP6BYTES) /* "can't happen" */ return 0; p = buf; *p++ = ':'; for (i = 0; i < IP6BYTES / 2; i++) { piece = (srcp[2 * i] << 8) + srcp[2 * i + 1]; p += ultot(piece, 16, p, 5); /* 5 = abcd + NUL */ *(p - 1) = ':'; /* overwrites the NUL */ } *p = '\0'; q = strstr(buf, ":0:0:"); if (squish && q != NULL) { /* zero squishing is possible */ p = q + 1; while (*p == '0' && *(p + 1) == ':') p += 2; q++; *q++ = ':'; /* overwrite first 0 */ while (*p != '\0') *q++ = *p++; *q = '\0'; if (!(*(q - 1) == ':' && *(q - 2) == ':')) *--q = '\0'; /* strip final : unless :: */ p = buf; if (!(*p == ':' && *(p + 1) == ':')) p++; /* skip initial : unless :: */ } else { q = p; *--q = '\0'; /* strip final : */ p = buf + 1; /* skip initial : */ } *dstp = p; return q - p + 1; } /* - reverse4 - IPv4 reverse-lookup conversion */ static size_t /* size of text, including NUL */ reverse4(srcp, srclen, buf, dstp) const unsigned char *srcp; size_t srclen; char *buf; /* guaranteed large enough */ char **dstp; /* where to put result pointer */ { int i; char *p; if (srclen != IP4BYTES) /* "can't happen" */ return 0; p = buf; for (i = IP4BYTES - 1; i >= 0; i--) { p += ultot(srcp[i], 10, p, PERBYTE); *(p - 1) = '.'; /* overwrites the NUL */ } strcpy(p, "IN-ADDR.ARPA."); *dstp = buf; return strlen(buf) + 1; } /* - reverse6 - IPv6 reverse-lookup conversion (RFC 1886) * A trifle inefficient, really shouldn't use ultot... */ static size_t /* size of text, including NUL */ reverse6(srcp, srclen, buf, dstp) const unsigned char *srcp; size_t srclen; char *buf; /* guaranteed large enough */ char **dstp; /* where to put result pointer */ { int i; unsigned long piece; char *p; if (srclen != IP6BYTES) /* "can't happen" */ return 0; p = buf; for (i = IP6BYTES - 1; i >= 0; i--) { piece = srcp[i]; p += ultot(piece & 0xf, 16, p, 2); *(p - 1) = '.'; p += ultot(piece >> 4, 16, p, 2); *(p - 1) = '.'; } strcpy(p, "IP6.ARPA."); *dstp = buf; return strlen(buf) + 1; } /* - reverse6 - modern IPv6 reverse-lookup conversion (RFC 2874) * this version removed as it was obsoleted in the end. */ #ifdef ADDRTOT_MAIN #include #include #include #include void regress(void); int main(int argc, char *argv[]) { if (argc < 2) { fprintf(stderr, "Usage: %s {addr|net/mask|begin...end|-r}\n", argv[0]); exit(2); } if (streq(argv[1], "-r")) { regress(); fprintf(stderr, "regress() returned?!?\n"); exit(1); } exit(0); } struct rtab { char *input; char format; char *output; /* NULL means error expected */ } rtab[] = { { "1.2.3.0", 0, "1.2.3.0" }, { "1:2::3:4", 0, "1:2::3:4" }, { "1:2::3:4", 'Q', "1:2:0:0:0:0:3:4" }, { "1:2:0:0:3:4:0:0", 0, "1:2::3:4:0:0" }, { "1.2.3.4", 'r', "4.3.2.1.IN-ADDR.ARPA." }, /* 0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7 8 9 a b c d e f */ { "1:2::3:4", 'r', "4.0.0.0.3.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.0.1.0.0.0.IP6.ARPA." }, { NULL, 0, NULL } }; void regress(void) { struct rtab *r; int status = 0; ip_address a; char in[100]; char buf[100]; const char *oops; size_t n; for (r = rtab; r->input != NULL; r++) { strcpy(in, r->input); /* convert it *to* internal format */ oops = ttoaddr(in, strlen(in), AF_UNSPEC, &a); /* now convert it back */ n = addrtot(&a, r->format, buf, sizeof(buf)); if (n == 0 && r->output == NULL) { } /* okay, error expected */ else if (n == 0) { printf("`%s' addrtot failed\n", r->input); status = 1; } else if (r->output == NULL) { printf("`%s' addrtot succeeded unexpectedly '%c'\n", r->input, r->format); status = 1; } else { if (!strcaseeq(r->output, buf)) { printf("`%s' '%c' gave `%s', expected `%s'\n", r->input, r->format, buf, r->output); status = 1; } } } exit(status); } #endif /* ADDRTOT_MAIN */ libreswan-3.32/linux/net/ipsec/addrtypeof.c000066400000000000000000000050371365625662500210110ustar00rootroot00000000000000/* * extract parts of an ip_address * Copyright (C) 2000 Henry Spencer. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. */ #include "libreswan.h" /* - addrtypeof - get the type of an ip_address */ int addrtypeof(src) const ip_address * src; { return src->u.v4.sin_family; } /* - addrbytesptr_read - get pointer to the address bytes of an ip_address for reading */ size_t /* 0 for error */ addrbytesptr_read(src, dstp) const ip_address * src; const unsigned char **dstp; /* NULL means just a size query */ { const unsigned char *p; size_t n; switch (src->u.v4.sin_family) { case AF_INET: p = (const unsigned char *) &src->u.v4.sin_addr.s_addr; n = 4; break; case AF_INET6: p = (const unsigned char *) &src->u.v6.sin6_addr; n = 16; break; default: return 0; } if (dstp != NULL) *dstp = p; return n; } /* - addrbytesptr_write - get pointer to the address bytes of an ip_address for writing */ size_t /* 0 for error */ addrbytesptr_write(src, dstp) ip_address * src; unsigned char **dstp; /* NULL means just a size query */ { unsigned char *p; size_t n; switch (src->u.v4.sin_family) { case AF_INET: p = (unsigned char *)&src->u.v4.sin_addr.s_addr; n = 4; break; case AF_INET6: p = (unsigned char *)&src->u.v6.sin6_addr; n = 16; break; default: return 0; break; } if (dstp != NULL) *dstp = p; return n; } /* - addrlenof - get length of the address bytes of an ip_address */ size_t /* 0 for error */ addrlenof(src) const ip_address * src; { return addrbytesptr_read(src, NULL); } /* - addrbytesof - get the address bytes of an ip_address */ size_t /* 0 for error */ addrbytesof(src, dst, dstlen) const ip_address * src; unsigned char *dst; size_t dstlen; { const unsigned char *p; size_t n; size_t ncopy; n = addrbytesptr_read(src, &p); if (n == 0) return 0; if (dstlen > 0) { ncopy = n; if (ncopy > dstlen) ncopy = dstlen; memcpy(dst, p, ncopy); } return n; } libreswan-3.32/linux/net/ipsec/adler32.c000066400000000000000000000024471365625662500201060ustar00rootroot00000000000000/* adler32.c -- compute the Adler-32 checksum of a data stream * Copyright (C) 1995-2002 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id: adler32.c,v 1.6 2004/07/10 19:11:18 mcr Exp $ */ #include #include #define BASE 65521L /* largest prime smaller than 65536 */ #define NMAX 5552 /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ #define DO1(buf,i) {s1 += buf[i]; s2 += s1;} #define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); #define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); #define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); #define DO16(buf) DO8(buf,0); DO8(buf,8); /* ========================================================================= */ uLong ZEXPORT adler32(adler, buf, len) uLong adler; const Bytef *buf; uInt len; { unsigned long s1 = adler & 0xffff; unsigned long s2 = (adler >> 16) & 0xffff; int k; if (buf == Z_NULL) return 1L; while (len > 0) { k = len < NMAX ? len : NMAX; len -= k; while (k >= 16) { DO16(buf); buf += 16; k -= 16; } if (k != 0) do { s1 += *buf++; s2 += s1; } while (--k); s1 %= BASE; s2 %= BASE; } return (s2 << 16) | s1; } libreswan-3.32/linux/net/ipsec/aes/000077500000000000000000000000001365625662500172475ustar00rootroot00000000000000libreswan-3.32/linux/net/ipsec/aes/Makefile.fs2_6000066400000000000000000000026311365625662500216270ustar00rootroot00000000000000# Makefile for KLIPS 3DES kernel code as a module for 2.6 kernels # # Makefile for KLIPS kernel code as a module # Copyright (C) 2002-2004 Michael Richardson # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # # Note! Dependencies are done automagically by 'make dep', which also # removes any old dependencies. DON'T put your own dependencies here # unless it's something special (ie not a .c file). # obj-$(CONFIG_KLIPS_ENC_AES) += ipsec_alg_aes.o obj-$(CONFIG_KLIPS_ENC_AES) += aes_xcbc_mac.o obj-$(CONFIG_KLIPS_ENC_AES) += aes_cbc.o ifeq ($(strip ${SUBARCH}),) SUBARCH:=${ARCH} endif # the assembly version expects frame pointers, which are # optional in many kernel builds. If you want speed, you should # probably use cryptoapi code instead. #USEASSEMBLY=${SUBARCH}${CONFIG_FRAME_POINTER} #ifeq (${USEASSEMBLY},i386y) #obj-$(CONFIG_KLIPS_ENC_AES) += aes-i586.o #else obj-$(CONFIG_KLIPS_ENC_AES) += aes.o #endif libreswan-3.32/linux/net/ipsec/aes/aes-i586.S000066400000000000000000000603061365625662500206410ustar00rootroot00000000000000// // Copyright (c) 2001, Dr Brian Gladman , Worcester, UK. // All rights reserved. // // TERMS // // Redistribution and use in source and binary forms, with or without // modification, are permitted subject to the following conditions: // // 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 copyright holder's name must not be used to endorse or promote // any products derived from this software without his specific prior // written permission. // // This software is provided 'as is' with no express or implied warranties // of correctness or fitness for purpose. // Modified by Jari Ruusu, December 24 2001 // - Converted syntax to GNU CPP/assembler syntax // - C programming interface converted back to "old" API // - Minor portability cleanups and speed optimizations // An AES (Rijndael) implementation for the Pentium. This version only // implements the standard AES block length (128 bits, 16 bytes). This code // does not preserve the eax, ecx or edx registers or the arithmetic status // flags. However, the ebx, esi, edi, and ebp registers are preserved across // calls. // void aes_set_key(aes_context *cx, const unsigned char key[], const int key_len, const int f) // void aes_encrypt(const aes_context *cx, const unsigned char in_blk[], unsigned char out_blk[]) // void aes_decrypt(const aes_context *cx, const unsigned char in_blk[], unsigned char out_blk[]) #if defined(USE_UNDERLINE) # define aes_set_key _aes_set_key # define aes_encrypt _aes_encrypt # define aes_decrypt _aes_decrypt #endif #if !defined(ALIGN32BYTES) # define ALIGN32BYTES 32 #endif .file "aes-i586.S" .globl aes_set_key .globl aes_encrypt .globl aes_decrypt #define tlen 1024 // length of each of 4 'xor' arrays (256 32-bit words) // offsets to parameters with one register pushed onto stack #define ctx 8 // AES context structure #define in_blk 12 // input byte array address parameter #define out_blk 16 // output byte array address parameter // offsets in context structure #define nkey 0 // key length, size 4 #define nrnd 4 // number of rounds, size 4 #define ekey 8 // encryption key schedule base address, size 256 #define dkey 264 // decryption key schedule base address, size 256 // This macro performs a forward encryption cycle. It is entered with // the first previous round column values in %eax, %ebx, %esi and %edi and // exits with the final values in the same registers. #define fwd_rnd(p1,p2) \ mov %ebx,(%esp) ;\ movzbl %al,%edx ;\ mov %eax,%ecx ;\ mov p2(%ebp),%eax ;\ mov %edi,4(%esp) ;\ mov p2+12(%ebp),%edi ;\ xor p1(,%edx,4),%eax ;\ movzbl %ch,%edx ;\ shr $16,%ecx ;\ mov p2+4(%ebp),%ebx ;\ xor p1+tlen(,%edx,4),%edi ;\ movzbl %cl,%edx ;\ movzbl %ch,%ecx ;\ xor p1+3*tlen(,%ecx,4),%ebx ;\ mov %esi,%ecx ;\ mov p1+2*tlen(,%edx,4),%esi ;\ movzbl %cl,%edx ;\ xor p1(,%edx,4),%esi ;\ movzbl %ch,%edx ;\ shr $16,%ecx ;\ xor p1+tlen(,%edx,4),%ebx ;\ movzbl %cl,%edx ;\ movzbl %ch,%ecx ;\ xor p1+2*tlen(,%edx,4),%eax ;\ mov (%esp),%edx ;\ xor p1+3*tlen(,%ecx,4),%edi ;\ movzbl %dl,%ecx ;\ xor p2+8(%ebp),%esi ;\ xor p1(,%ecx,4),%ebx ;\ movzbl %dh,%ecx ;\ shr $16,%edx ;\ xor p1+tlen(,%ecx,4),%eax ;\ movzbl %dl,%ecx ;\ movzbl %dh,%edx ;\ xor p1+2*tlen(,%ecx,4),%edi ;\ mov 4(%esp),%ecx ;\ xor p1+3*tlen(,%edx,4),%esi ;\ movzbl %cl,%edx ;\ xor p1(,%edx,4),%edi ;\ movzbl %ch,%edx ;\ shr $16,%ecx ;\ xor p1+tlen(,%edx,4),%esi ;\ movzbl %cl,%edx ;\ movzbl %ch,%ecx ;\ xor p1+2*tlen(,%edx,4),%ebx ;\ xor p1+3*tlen(,%ecx,4),%eax // This macro performs an inverse encryption cycle. It is entered with // the first previous round column values in %eax, %ebx, %esi and %edi and // exits with the final values in the same registers. #define inv_rnd(p1,p2) \ movzbl %al,%edx ;\ mov %ebx,(%esp) ;\ mov %eax,%ecx ;\ mov p2(%ebp),%eax ;\ mov %edi,4(%esp) ;\ mov p2+4(%ebp),%ebx ;\ xor p1(,%edx,4),%eax ;\ movzbl %ch,%edx ;\ shr $16,%ecx ;\ mov p2+12(%ebp),%edi ;\ xor p1+tlen(,%edx,4),%ebx ;\ movzbl %cl,%edx ;\ movzbl %ch,%ecx ;\ xor p1+3*tlen(,%ecx,4),%edi ;\ mov %esi,%ecx ;\ mov p1+2*tlen(,%edx,4),%esi ;\ movzbl %cl,%edx ;\ xor p1(,%edx,4),%esi ;\ movzbl %ch,%edx ;\ shr $16,%ecx ;\ xor p1+tlen(,%edx,4),%edi ;\ movzbl %cl,%edx ;\ movzbl %ch,%ecx ;\ xor p1+2*tlen(,%edx,4),%eax ;\ mov (%esp),%edx ;\ xor p1+3*tlen(,%ecx,4),%ebx ;\ movzbl %dl,%ecx ;\ xor p2+8(%ebp),%esi ;\ xor p1(,%ecx,4),%ebx ;\ movzbl %dh,%ecx ;\ shr $16,%edx ;\ xor p1+tlen(,%ecx,4),%esi ;\ movzbl %dl,%ecx ;\ movzbl %dh,%edx ;\ xor p1+2*tlen(,%ecx,4),%edi ;\ mov 4(%esp),%ecx ;\ xor p1+3*tlen(,%edx,4),%eax ;\ movzbl %cl,%edx ;\ xor p1(,%edx,4),%edi ;\ movzbl %ch,%edx ;\ shr $16,%ecx ;\ xor p1+tlen(,%edx,4),%eax ;\ movzbl %cl,%edx ;\ movzbl %ch,%ecx ;\ xor p1+2*tlen(,%edx,4),%ebx ;\ xor p1+3*tlen(,%ecx,4),%esi // AES (Rijndael) Encryption Subroutine .text .align ALIGN32BYTES aes_encrypt: push %ebp mov ctx(%esp),%ebp // pointer to context mov in_blk(%esp),%ecx push %ebx push %esi push %edi mov nrnd(%ebp),%edx // number of rounds lea ekey+16(%ebp),%ebp // key pointer // input four columns and xor in first round key mov (%ecx),%eax mov 4(%ecx),%ebx mov 8(%ecx),%esi mov 12(%ecx),%edi xor -16(%ebp),%eax xor -12(%ebp),%ebx xor -8(%ebp),%esi xor -4(%ebp),%edi sub $8,%esp // space for register saves on stack sub $10,%edx je aes_15 add $32,%ebp sub $2,%edx je aes_13 add $32,%ebp fwd_rnd(aes_ft_tab,-64) // 14 rounds for 256-bit key fwd_rnd(aes_ft_tab,-48) aes_13: fwd_rnd(aes_ft_tab,-32) // 12 rounds for 192-bit key fwd_rnd(aes_ft_tab,-16) aes_15: fwd_rnd(aes_ft_tab,0) // 10 rounds for 128-bit key fwd_rnd(aes_ft_tab,16) fwd_rnd(aes_ft_tab,32) fwd_rnd(aes_ft_tab,48) fwd_rnd(aes_ft_tab,64) fwd_rnd(aes_ft_tab,80) fwd_rnd(aes_ft_tab,96) fwd_rnd(aes_ft_tab,112) fwd_rnd(aes_ft_tab,128) fwd_rnd(aes_fl_tab,144) // last round uses a different table // move final values to the output array. mov out_blk+20(%esp),%ebp add $8,%esp mov %eax,(%ebp) mov %ebx,4(%ebp) mov %esi,8(%ebp) mov %edi,12(%ebp) pop %edi pop %esi pop %ebx pop %ebp ret // AES (Rijndael) Decryption Subroutine .align ALIGN32BYTES aes_decrypt: push %ebp mov ctx(%esp),%ebp // pointer to context mov in_blk(%esp),%ecx push %ebx push %esi push %edi mov nrnd(%ebp),%edx // number of rounds lea dkey+16(%ebp),%ebp // key pointer // input four columns and xor in first round key mov (%ecx),%eax mov 4(%ecx),%ebx mov 8(%ecx),%esi mov 12(%ecx),%edi xor -16(%ebp),%eax xor -12(%ebp),%ebx xor -8(%ebp),%esi xor -4(%ebp),%edi sub $8,%esp // space for register saves on stack sub $10,%edx je aes_25 add $32,%ebp sub $2,%edx je aes_23 add $32,%ebp inv_rnd(aes_it_tab,-64) // 14 rounds for 256-bit key inv_rnd(aes_it_tab,-48) aes_23: inv_rnd(aes_it_tab,-32) // 12 rounds for 192-bit key inv_rnd(aes_it_tab,-16) aes_25: inv_rnd(aes_it_tab,0) // 10 rounds for 128-bit key inv_rnd(aes_it_tab,16) inv_rnd(aes_it_tab,32) inv_rnd(aes_it_tab,48) inv_rnd(aes_it_tab,64) inv_rnd(aes_it_tab,80) inv_rnd(aes_it_tab,96) inv_rnd(aes_it_tab,112) inv_rnd(aes_it_tab,128) inv_rnd(aes_il_tab,144) // last round uses a different table // move final values to the output array. mov out_blk+20(%esp),%ebp add $8,%esp mov %eax,(%ebp) mov %ebx,4(%ebp) mov %esi,8(%ebp) mov %edi,12(%ebp) pop %edi pop %esi pop %ebx pop %ebp ret // AES (Rijndael) Key Schedule Subroutine // input/output parameters #define aes_cx 12 // AES context #define in_key 16 // key input array address #define key_ln 20 // key length, bytes (16,24,32) or bits (128,192,256) #define ed_flg 24 // 0=create both encr/decr keys, 1=create encr key only // offsets for locals #define cnt -4 #define kpf -8 #define slen 8 // This macro performs a column mixing operation on an input 32-bit // word to give a 32-bit result. It uses each of the 4 bytes in the // the input column to index 4 different tables of 256 32-bit words // that are xored together to form the output value. #define mix_col(p1) \ movzbl %bl,%ecx ;\ mov p1(,%ecx,4),%eax ;\ movzbl %bh,%ecx ;\ ror $16,%ebx ;\ xor p1+tlen(,%ecx,4),%eax ;\ movzbl %bl,%ecx ;\ xor p1+2*tlen(,%ecx,4),%eax ;\ movzbl %bh,%ecx ;\ xor p1+3*tlen(,%ecx,4),%eax // Key Schedule Macros #define ksc4(p1) \ rol $24,%ebx ;\ mix_col(aes_fl_tab) ;\ ror $8,%ebx ;\ xor 4*p1+aes_rcon_tab,%eax ;\ xor %eax,%esi ;\ xor %esi,%ebp ;\ mov %esi,16*p1(%edi) ;\ mov %ebp,16*p1+4(%edi) ;\ xor %ebp,%edx ;\ xor %edx,%ebx ;\ mov %edx,16*p1+8(%edi) ;\ mov %ebx,16*p1+12(%edi) #define ksc6(p1) \ rol $24,%ebx ;\ mix_col(aes_fl_tab) ;\ ror $8,%ebx ;\ xor 4*p1+aes_rcon_tab,%eax ;\ xor 24*p1-24(%edi),%eax ;\ mov %eax,24*p1(%edi) ;\ xor 24*p1-20(%edi),%eax ;\ mov %eax,24*p1+4(%edi) ;\ xor %eax,%esi ;\ xor %esi,%ebp ;\ mov %esi,24*p1+8(%edi) ;\ mov %ebp,24*p1+12(%edi) ;\ xor %ebp,%edx ;\ xor %edx,%ebx ;\ mov %edx,24*p1+16(%edi) ;\ mov %ebx,24*p1+20(%edi) #define ksc8(p1) \ rol $24,%ebx ;\ mix_col(aes_fl_tab) ;\ ror $8,%ebx ;\ xor 4*p1+aes_rcon_tab,%eax ;\ xor 32*p1-32(%edi),%eax ;\ mov %eax,32*p1(%edi) ;\ xor 32*p1-28(%edi),%eax ;\ mov %eax,32*p1+4(%edi) ;\ xor 32*p1-24(%edi),%eax ;\ mov %eax,32*p1+8(%edi) ;\ xor 32*p1-20(%edi),%eax ;\ mov %eax,32*p1+12(%edi) ;\ push %ebx ;\ mov %eax,%ebx ;\ mix_col(aes_fl_tab) ;\ pop %ebx ;\ xor %eax,%esi ;\ xor %esi,%ebp ;\ mov %esi,32*p1+16(%edi) ;\ mov %ebp,32*p1+20(%edi) ;\ xor %ebp,%edx ;\ xor %edx,%ebx ;\ mov %edx,32*p1+24(%edi) ;\ mov %ebx,32*p1+28(%edi) .align ALIGN32BYTES aes_set_key: pushfl push %ebp mov %esp,%ebp sub $slen,%esp push %ebx push %esi push %edi mov aes_cx(%ebp),%edx // edx -> AES context mov key_ln(%ebp),%ecx // key length cmpl $128,%ecx jb aes_30 shr $3,%ecx aes_30: cmpl $32,%ecx je aes_32 cmpl $24,%ecx je aes_32 mov $16,%ecx aes_32: shr $2,%ecx mov %ecx,nkey(%edx) lea 6(%ecx),%eax // 10/12/14 for 4/6/8 32-bit key length mov %eax,nrnd(%edx) mov in_key(%ebp),%esi // key input array lea ekey(%edx),%edi // key position in AES context cld push %ebp mov %ecx,%eax // save key length in eax rep ; movsl // words in the key schedule mov -4(%esi),%ebx // put some values in registers mov -8(%esi),%edx // to allow faster code mov -12(%esi),%ebp mov -16(%esi),%esi cmpl $4,%eax // jump on key size je aes_36 cmpl $6,%eax je aes_35 ksc8(0) ksc8(1) ksc8(2) ksc8(3) ksc8(4) ksc8(5) ksc8(6) jmp aes_37 aes_35: ksc6(0) ksc6(1) ksc6(2) ksc6(3) ksc6(4) ksc6(5) ksc6(6) ksc6(7) jmp aes_37 aes_36: ksc4(0) ksc4(1) ksc4(2) ksc4(3) ksc4(4) ksc4(5) ksc4(6) ksc4(7) ksc4(8) ksc4(9) aes_37: pop %ebp mov aes_cx(%ebp),%edx // edx -> AES context cmpl $0,ed_flg(%ebp) jne aes_39 // compile decryption key schedule from encryption schedule - reverse // order and do mix_column operation on round keys except first and last mov nrnd(%edx),%eax // kt = cx->d_key + nc * cx->Nrnd shl $2,%eax lea dkey(%edx,%eax,4),%edi lea ekey(%edx),%esi // kf = cx->e_key movsl // copy first round key (unmodified) movsl movsl movsl sub $32,%edi movl $1,cnt(%ebp) aes_38: // do mix column on each column of lodsl // each round key mov %eax,%ebx mix_col(aes_im_tab) stosl lodsl mov %eax,%ebx mix_col(aes_im_tab) stosl lodsl mov %eax,%ebx mix_col(aes_im_tab) stosl lodsl mov %eax,%ebx mix_col(aes_im_tab) stosl sub $32,%edi incl cnt(%ebp) mov cnt(%ebp),%eax cmp nrnd(%edx),%eax jb aes_38 movsl // copy last round key (unmodified) movsl movsl movsl aes_39: pop %edi pop %esi pop %ebx mov %ebp,%esp pop %ebp popfl ret // finite field multiplies by {02}, {04} and {08} #define f2(x) ((x<<1)^(((x>>7)&1)*0x11b)) #define f4(x) ((x<<2)^(((x>>6)&1)*0x11b)^(((x>>6)&2)*0x11b)) #define f8(x) ((x<<3)^(((x>>5)&1)*0x11b)^(((x>>5)&2)*0x11b)^(((x>>5)&4)*0x11b)) // finite field multiplies required in table generation #define f3(x) (f2(x) ^ x) #define f9(x) (f8(x) ^ x) #define fb(x) (f8(x) ^ f2(x) ^ x) #define fd(x) (f8(x) ^ f4(x) ^ x) #define fe(x) (f8(x) ^ f4(x) ^ f2(x)) // These defines generate the forward table entries #define u0(x) ((f3(x) << 24) | (x << 16) | (x << 8) | f2(x)) #define u1(x) ((x << 24) | (x << 16) | (f2(x) << 8) | f3(x)) #define u2(x) ((x << 24) | (f2(x) << 16) | (f3(x) << 8) | x) #define u3(x) ((f2(x) << 24) | (f3(x) << 16) | (x << 8) | x) // These defines generate the inverse table entries #define v0(x) ((fb(x) << 24) | (fd(x) << 16) | (f9(x) << 8) | fe(x)) #define v1(x) ((fd(x) << 24) | (f9(x) << 16) | (fe(x) << 8) | fb(x)) #define v2(x) ((f9(x) << 24) | (fe(x) << 16) | (fb(x) << 8) | fd(x)) #define v3(x) ((fe(x) << 24) | (fb(x) << 16) | (fd(x) << 8) | f9(x)) // These defines generate entries for the last round tables #define w0(x) (x) #define w1(x) (x << 8) #define w2(x) (x << 16) #define w3(x) (x << 24) // macro to generate inverse mix column tables (needed for the key schedule) #define im_data0(p1) \ .long p1(0x00),p1(0x01),p1(0x02),p1(0x03),p1(0x04),p1(0x05),p1(0x06),p1(0x07) ;\ .long p1(0x08),p1(0x09),p1(0x0a),p1(0x0b),p1(0x0c),p1(0x0d),p1(0x0e),p1(0x0f) ;\ .long p1(0x10),p1(0x11),p1(0x12),p1(0x13),p1(0x14),p1(0x15),p1(0x16),p1(0x17) ;\ .long p1(0x18),p1(0x19),p1(0x1a),p1(0x1b),p1(0x1c),p1(0x1d),p1(0x1e),p1(0x1f) #define im_data1(p1) \ .long p1(0x20),p1(0x21),p1(0x22),p1(0x23),p1(0x24),p1(0x25),p1(0x26),p1(0x27) ;\ .long p1(0x28),p1(0x29),p1(0x2a),p1(0x2b),p1(0x2c),p1(0x2d),p1(0x2e),p1(0x2f) ;\ .long p1(0x30),p1(0x31),p1(0x32),p1(0x33),p1(0x34),p1(0x35),p1(0x36),p1(0x37) ;\ .long p1(0x38),p1(0x39),p1(0x3a),p1(0x3b),p1(0x3c),p1(0x3d),p1(0x3e),p1(0x3f) #define im_data2(p1) \ .long p1(0x40),p1(0x41),p1(0x42),p1(0x43),p1(0x44),p1(0x45),p1(0x46),p1(0x47) ;\ .long p1(0x48),p1(0x49),p1(0x4a),p1(0x4b),p1(0x4c),p1(0x4d),p1(0x4e),p1(0x4f) ;\ .long p1(0x50),p1(0x51),p1(0x52),p1(0x53),p1(0x54),p1(0x55),p1(0x56),p1(0x57) ;\ .long p1(0x58),p1(0x59),p1(0x5a),p1(0x5b),p1(0x5c),p1(0x5d),p1(0x5e),p1(0x5f) #define im_data3(p1) \ .long p1(0x60),p1(0x61),p1(0x62),p1(0x63),p1(0x64),p1(0x65),p1(0x66),p1(0x67) ;\ .long p1(0x68),p1(0x69),p1(0x6a),p1(0x6b),p1(0x6c),p1(0x6d),p1(0x6e),p1(0x6f) ;\ .long p1(0x70),p1(0x71),p1(0x72),p1(0x73),p1(0x74),p1(0x75),p1(0x76),p1(0x77) ;\ .long p1(0x78),p1(0x79),p1(0x7a),p1(0x7b),p1(0x7c),p1(0x7d),p1(0x7e),p1(0x7f) #define im_data4(p1) \ .long p1(0x80),p1(0x81),p1(0x82),p1(0x83),p1(0x84),p1(0x85),p1(0x86),p1(0x87) ;\ .long p1(0x88),p1(0x89),p1(0x8a),p1(0x8b),p1(0x8c),p1(0x8d),p1(0x8e),p1(0x8f) ;\ .long p1(0x90),p1(0x91),p1(0x92),p1(0x93),p1(0x94),p1(0x95),p1(0x96),p1(0x97) ;\ .long p1(0x98),p1(0x99),p1(0x9a),p1(0x9b),p1(0x9c),p1(0x9d),p1(0x9e),p1(0x9f) #define im_data5(p1) \ .long p1(0xa0),p1(0xa1),p1(0xa2),p1(0xa3),p1(0xa4),p1(0xa5),p1(0xa6),p1(0xa7) ;\ .long p1(0xa8),p1(0xa9),p1(0xaa),p1(0xab),p1(0xac),p1(0xad),p1(0xae),p1(0xaf) ;\ .long p1(0xb0),p1(0xb1),p1(0xb2),p1(0xb3),p1(0xb4),p1(0xb5),p1(0xb6),p1(0xb7) ;\ .long p1(0xb8),p1(0xb9),p1(0xba),p1(0xbb),p1(0xbc),p1(0xbd),p1(0xbe),p1(0xbf) #define im_data6(p1) \ .long p1(0xc0),p1(0xc1),p1(0xc2),p1(0xc3),p1(0xc4),p1(0xc5),p1(0xc6),p1(0xc7) ;\ .long p1(0xc8),p1(0xc9),p1(0xca),p1(0xcb),p1(0xcc),p1(0xcd),p1(0xce),p1(0xcf) ;\ .long p1(0xd0),p1(0xd1),p1(0xd2),p1(0xd3),p1(0xd4),p1(0xd5),p1(0xd6),p1(0xd7) ;\ .long p1(0xd8),p1(0xd9),p1(0xda),p1(0xdb),p1(0xdc),p1(0xdd),p1(0xde),p1(0xdf) #define im_data7(p1) \ .long p1(0xe0),p1(0xe1),p1(0xe2),p1(0xe3),p1(0xe4),p1(0xe5),p1(0xe6),p1(0xe7) ;\ .long p1(0xe8),p1(0xe9),p1(0xea),p1(0xeb),p1(0xec),p1(0xed),p1(0xee),p1(0xef) ;\ .long p1(0xf0),p1(0xf1),p1(0xf2),p1(0xf3),p1(0xf4),p1(0xf5),p1(0xf6),p1(0xf7) ;\ .long p1(0xf8),p1(0xf9),p1(0xfa),p1(0xfb),p1(0xfc),p1(0xfd),p1(0xfe),p1(0xff) // S-box data - 256 entries #define sb_data0(p1) \ .long p1(0x63),p1(0x7c),p1(0x77),p1(0x7b),p1(0xf2),p1(0x6b),p1(0x6f),p1(0xc5) ;\ .long p1(0x30),p1(0x01),p1(0x67),p1(0x2b),p1(0xfe),p1(0xd7),p1(0xab),p1(0x76) ;\ .long p1(0xca),p1(0x82),p1(0xc9),p1(0x7d),p1(0xfa),p1(0x59),p1(0x47),p1(0xf0) ;\ .long p1(0xad),p1(0xd4),p1(0xa2),p1(0xaf),p1(0x9c),p1(0xa4),p1(0x72),p1(0xc0) #define sb_data1(p1) \ .long p1(0xb7),p1(0xfd),p1(0x93),p1(0x26),p1(0x36),p1(0x3f),p1(0xf7),p1(0xcc) ;\ .long p1(0x34),p1(0xa5),p1(0xe5),p1(0xf1),p1(0x71),p1(0xd8),p1(0x31),p1(0x15) ;\ .long p1(0x04),p1(0xc7),p1(0x23),p1(0xc3),p1(0x18),p1(0x96),p1(0x05),p1(0x9a) ;\ .long p1(0x07),p1(0x12),p1(0x80),p1(0xe2),p1(0xeb),p1(0x27),p1(0xb2),p1(0x75) #define sb_data2(p1) \ .long p1(0x09),p1(0x83),p1(0x2c),p1(0x1a),p1(0x1b),p1(0x6e),p1(0x5a),p1(0xa0) ;\ .long p1(0x52),p1(0x3b),p1(0xd6),p1(0xb3),p1(0x29),p1(0xe3),p1(0x2f),p1(0x84) ;\ .long p1(0x53),p1(0xd1),p1(0x00),p1(0xed),p1(0x20),p1(0xfc),p1(0xb1),p1(0x5b) ;\ .long p1(0x6a),p1(0xcb),p1(0xbe),p1(0x39),p1(0x4a),p1(0x4c),p1(0x58),p1(0xcf) #define sb_data3(p1) \ .long p1(0xd0),p1(0xef),p1(0xaa),p1(0xfb),p1(0x43),p1(0x4d),p1(0x33),p1(0x85) ;\ .long p1(0x45),p1(0xf9),p1(0x02),p1(0x7f),p1(0x50),p1(0x3c),p1(0x9f),p1(0xa8) ;\ .long p1(0x51),p1(0xa3),p1(0x40),p1(0x8f),p1(0x92),p1(0x9d),p1(0x38),p1(0xf5) ;\ .long p1(0xbc),p1(0xb6),p1(0xda),p1(0x21),p1(0x10),p1(0xff),p1(0xf3),p1(0xd2) #define sb_data4(p1) \ .long p1(0xcd),p1(0x0c),p1(0x13),p1(0xec),p1(0x5f),p1(0x97),p1(0x44),p1(0x17) ;\ .long p1(0xc4),p1(0xa7),p1(0x7e),p1(0x3d),p1(0x64),p1(0x5d),p1(0x19),p1(0x73) ;\ .long p1(0x60),p1(0x81),p1(0x4f),p1(0xdc),p1(0x22),p1(0x2a),p1(0x90),p1(0x88) ;\ .long p1(0x46),p1(0xee),p1(0xb8),p1(0x14),p1(0xde),p1(0x5e),p1(0x0b),p1(0xdb) #define sb_data5(p1) \ .long p1(0xe0),p1(0x32),p1(0x3a),p1(0x0a),p1(0x49),p1(0x06),p1(0x24),p1(0x5c) ;\ .long p1(0xc2),p1(0xd3),p1(0xac),p1(0x62),p1(0x91),p1(0x95),p1(0xe4),p1(0x79) ;\ .long p1(0xe7),p1(0xc8),p1(0x37),p1(0x6d),p1(0x8d),p1(0xd5),p1(0x4e),p1(0xa9) ;\ .long p1(0x6c),p1(0x56),p1(0xf4),p1(0xea),p1(0x65),p1(0x7a),p1(0xae),p1(0x08) #define sb_data6(p1) \ .long p1(0xba),p1(0x78),p1(0x25),p1(0x2e),p1(0x1c),p1(0xa6),p1(0xb4),p1(0xc6) ;\ .long p1(0xe8),p1(0xdd),p1(0x74),p1(0x1f),p1(0x4b),p1(0xbd),p1(0x8b),p1(0x8a) ;\ .long p1(0x70),p1(0x3e),p1(0xb5),p1(0x66),p1(0x48),p1(0x03),p1(0xf6),p1(0x0e) ;\ .long p1(0x61),p1(0x35),p1(0x57),p1(0xb9),p1(0x86),p1(0xc1),p1(0x1d),p1(0x9e) #define sb_data7(p1) \ .long p1(0xe1),p1(0xf8),p1(0x98),p1(0x11),p1(0x69),p1(0xd9),p1(0x8e),p1(0x94) ;\ .long p1(0x9b),p1(0x1e),p1(0x87),p1(0xe9),p1(0xce),p1(0x55),p1(0x28),p1(0xdf) ;\ .long p1(0x8c),p1(0xa1),p1(0x89),p1(0x0d),p1(0xbf),p1(0xe6),p1(0x42),p1(0x68) ;\ .long p1(0x41),p1(0x99),p1(0x2d),p1(0x0f),p1(0xb0),p1(0x54),p1(0xbb),p1(0x16) // Inverse S-box data - 256 entries #define ib_data0(p1) \ .long p1(0x52),p1(0x09),p1(0x6a),p1(0xd5),p1(0x30),p1(0x36),p1(0xa5),p1(0x38) ;\ .long p1(0xbf),p1(0x40),p1(0xa3),p1(0x9e),p1(0x81),p1(0xf3),p1(0xd7),p1(0xfb) ;\ .long p1(0x7c),p1(0xe3),p1(0x39),p1(0x82),p1(0x9b),p1(0x2f),p1(0xff),p1(0x87) ;\ .long p1(0x34),p1(0x8e),p1(0x43),p1(0x44),p1(0xc4),p1(0xde),p1(0xe9),p1(0xcb) #define ib_data1(p1) \ .long p1(0x54),p1(0x7b),p1(0x94),p1(0x32),p1(0xa6),p1(0xc2),p1(0x23),p1(0x3d) ;\ .long p1(0xee),p1(0x4c),p1(0x95),p1(0x0b),p1(0x42),p1(0xfa),p1(0xc3),p1(0x4e) ;\ .long p1(0x08),p1(0x2e),p1(0xa1),p1(0x66),p1(0x28),p1(0xd9),p1(0x24),p1(0xb2) ;\ .long p1(0x76),p1(0x5b),p1(0xa2),p1(0x49),p1(0x6d),p1(0x8b),p1(0xd1),p1(0x25) #define ib_data2(p1) \ .long p1(0x72),p1(0xf8),p1(0xf6),p1(0x64),p1(0x86),p1(0x68),p1(0x98),p1(0x16) ;\ .long p1(0xd4),p1(0xa4),p1(0x5c),p1(0xcc),p1(0x5d),p1(0x65),p1(0xb6),p1(0x92) ;\ .long p1(0x6c),p1(0x70),p1(0x48),p1(0x50),p1(0xfd),p1(0xed),p1(0xb9),p1(0xda) ;\ .long p1(0x5e),p1(0x15),p1(0x46),p1(0x57),p1(0xa7),p1(0x8d),p1(0x9d),p1(0x84) #define ib_data3(p1) \ .long p1(0x90),p1(0xd8),p1(0xab),p1(0x00),p1(0x8c),p1(0xbc),p1(0xd3),p1(0x0a) ;\ .long p1(0xf7),p1(0xe4),p1(0x58),p1(0x05),p1(0xb8),p1(0xb3),p1(0x45),p1(0x06) ;\ .long p1(0xd0),p1(0x2c),p1(0x1e),p1(0x8f),p1(0xca),p1(0x3f),p1(0x0f),p1(0x02) ;\ .long p1(0xc1),p1(0xaf),p1(0xbd),p1(0x03),p1(0x01),p1(0x13),p1(0x8a),p1(0x6b) #define ib_data4(p1) \ .long p1(0x3a),p1(0x91),p1(0x11),p1(0x41),p1(0x4f),p1(0x67),p1(0xdc),p1(0xea) ;\ .long p1(0x97),p1(0xf2),p1(0xcf),p1(0xce),p1(0xf0),p1(0xb4),p1(0xe6),p1(0x73) ;\ .long p1(0x96),p1(0xac),p1(0x74),p1(0x22),p1(0xe7),p1(0xad),p1(0x35),p1(0x85) ;\ .long p1(0xe2),p1(0xf9),p1(0x37),p1(0xe8),p1(0x1c),p1(0x75),p1(0xdf),p1(0x6e) #define ib_data5(p1) \ .long p1(0x47),p1(0xf1),p1(0x1a),p1(0x71),p1(0x1d),p1(0x29),p1(0xc5),p1(0x89) ;\ .long p1(0x6f),p1(0xb7),p1(0x62),p1(0x0e),p1(0xaa),p1(0x18),p1(0xbe),p1(0x1b) ;\ .long p1(0xfc),p1(0x56),p1(0x3e),p1(0x4b),p1(0xc6),p1(0xd2),p1(0x79),p1(0x20) ;\ .long p1(0x9a),p1(0xdb),p1(0xc0),p1(0xfe),p1(0x78),p1(0xcd),p1(0x5a),p1(0xf4) #define ib_data6(p1) \ .long p1(0x1f),p1(0xdd),p1(0xa8),p1(0x33),p1(0x88),p1(0x07),p1(0xc7),p1(0x31) ;\ .long p1(0xb1),p1(0x12),p1(0x10),p1(0x59),p1(0x27),p1(0x80),p1(0xec),p1(0x5f) ;\ .long p1(0x60),p1(0x51),p1(0x7f),p1(0xa9),p1(0x19),p1(0xb5),p1(0x4a),p1(0x0d) ;\ .long p1(0x2d),p1(0xe5),p1(0x7a),p1(0x9f),p1(0x93),p1(0xc9),p1(0x9c),p1(0xef) #define ib_data7(p1) \ .long p1(0xa0),p1(0xe0),p1(0x3b),p1(0x4d),p1(0xae),p1(0x2a),p1(0xf5),p1(0xb0) ;\ .long p1(0xc8),p1(0xeb),p1(0xbb),p1(0x3c),p1(0x83),p1(0x53),p1(0x99),p1(0x61) ;\ .long p1(0x17),p1(0x2b),p1(0x04),p1(0x7e),p1(0xba),p1(0x77),p1(0xd6),p1(0x26) ;\ .long p1(0xe1),p1(0x69),p1(0x14),p1(0x63),p1(0x55),p1(0x21),p1(0x0c),p1(0x7d) // The rcon_table (needed for the key schedule) // // Here is original Dr Brian Gladman's source code: // _rcon_tab: // %assign x 1 // %rep 29 // dd x // %assign x f2(x) // %endrep // // Here is precomputed output (it's more portable this way): .align ALIGN32BYTES aes_rcon_tab: .long 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80 .long 0x1b,0x36,0x6c,0xd8,0xab,0x4d,0x9a,0x2f .long 0x5e,0xbc,0x63,0xc6,0x97,0x35,0x6a,0xd4 .long 0xb3,0x7d,0xfa,0xef,0xc5 // The forward xor tables .align ALIGN32BYTES aes_ft_tab: sb_data0(u0) sb_data1(u0) sb_data2(u0) sb_data3(u0) sb_data4(u0) sb_data5(u0) sb_data6(u0) sb_data7(u0) sb_data0(u1) sb_data1(u1) sb_data2(u1) sb_data3(u1) sb_data4(u1) sb_data5(u1) sb_data6(u1) sb_data7(u1) sb_data0(u2) sb_data1(u2) sb_data2(u2) sb_data3(u2) sb_data4(u2) sb_data5(u2) sb_data6(u2) sb_data7(u2) sb_data0(u3) sb_data1(u3) sb_data2(u3) sb_data3(u3) sb_data4(u3) sb_data5(u3) sb_data6(u3) sb_data7(u3) .align ALIGN32BYTES aes_fl_tab: sb_data0(w0) sb_data1(w0) sb_data2(w0) sb_data3(w0) sb_data4(w0) sb_data5(w0) sb_data6(w0) sb_data7(w0) sb_data0(w1) sb_data1(w1) sb_data2(w1) sb_data3(w1) sb_data4(w1) sb_data5(w1) sb_data6(w1) sb_data7(w1) sb_data0(w2) sb_data1(w2) sb_data2(w2) sb_data3(w2) sb_data4(w2) sb_data5(w2) sb_data6(w2) sb_data7(w2) sb_data0(w3) sb_data1(w3) sb_data2(w3) sb_data3(w3) sb_data4(w3) sb_data5(w3) sb_data6(w3) sb_data7(w3) // The inverse xor tables .align ALIGN32BYTES aes_it_tab: ib_data0(v0) ib_data1(v0) ib_data2(v0) ib_data3(v0) ib_data4(v0) ib_data5(v0) ib_data6(v0) ib_data7(v0) ib_data0(v1) ib_data1(v1) ib_data2(v1) ib_data3(v1) ib_data4(v1) ib_data5(v1) ib_data6(v1) ib_data7(v1) ib_data0(v2) ib_data1(v2) ib_data2(v2) ib_data3(v2) ib_data4(v2) ib_data5(v2) ib_data6(v2) ib_data7(v2) ib_data0(v3) ib_data1(v3) ib_data2(v3) ib_data3(v3) ib_data4(v3) ib_data5(v3) ib_data6(v3) ib_data7(v3) .align ALIGN32BYTES aes_il_tab: ib_data0(w0) ib_data1(w0) ib_data2(w0) ib_data3(w0) ib_data4(w0) ib_data5(w0) ib_data6(w0) ib_data7(w0) ib_data0(w1) ib_data1(w1) ib_data2(w1) ib_data3(w1) ib_data4(w1) ib_data5(w1) ib_data6(w1) ib_data7(w1) ib_data0(w2) ib_data1(w2) ib_data2(w2) ib_data3(w2) ib_data4(w2) ib_data5(w2) ib_data6(w2) ib_data7(w2) ib_data0(w3) ib_data1(w3) ib_data2(w3) ib_data3(w3) ib_data4(w3) ib_data5(w3) ib_data6(w3) ib_data7(w3) // The inverse mix column tables .align ALIGN32BYTES aes_im_tab: im_data0(v0) im_data1(v0) im_data2(v0) im_data3(v0) im_data4(v0) im_data5(v0) im_data6(v0) im_data7(v0) im_data0(v1) im_data1(v1) im_data2(v1) im_data3(v1) im_data4(v1) im_data5(v1) im_data6(v1) im_data7(v1) im_data0(v2) im_data1(v2) im_data2(v2) im_data3(v2) im_data4(v2) im_data5(v2) im_data6(v2) im_data7(v2) im_data0(v3) im_data1(v3) im_data2(v3) im_data3(v3) im_data4(v3) im_data5(v3) im_data6(v3) im_data7(v3) libreswan-3.32/linux/net/ipsec/aes/aes.c000066400000000000000000001554131365625662500201740ustar00rootroot00000000000000// I retain copyright in this code but I encourage its free use provided // that I don't carry any responsibility for the results. I am especially // happy to see it used in free and open source software. If you do use // it I would appreciate an acknowledgement of its origin in the code or // the product that results and I would also appreciate knowing a little // about the use to which it is being put. I am grateful to Frank Yellin // for some ideas that are used in this implementation. // // Dr B. R. Gladman 6th April 2001. // // This is an implementation of the AES encryption algorithm (Rijndael) // designed by Joan Daemen and Vincent Rijmen. This version is designed // to provide both fixed and dynamic block and key lengths and can also // run with either big or little endian internal byte order (see aes.h). // It inputs block and key lengths in bytes with the legal values being // 16, 24 and 32. /* * Modified by Jari Ruusu, May 1 2001 * - Fixed some compile warnings, code was ok but gcc warned anyway. * - Changed basic types: byte -> unsigned char, word -> u_int32_t * - Major name space cleanup: Names visible to outside now begin * with "aes_" or "AES_". A lot of stuff moved from aes.h to aes.c * - Removed C++ and DLL support as part of name space cleanup. * - Eliminated unnecessary recomputation of tables. (actual bug fix) * - Merged precomputed constant tables to aes.c file. * - Removed data alignment restrictions for portability reasons. * - Made block and key lengths accept bit count (128/192/256) * as well byte count (16/24/32). * - Removed all error checks. This change also eliminated the need * to preinitialize the context struct to zero. * - Removed some totally unused constants. */ #include "klips-crypto/aes.h" // CONFIGURATION OPTIONS (see also aes.h) // // 1. Define UNROLL for full loop unrolling in encryption and decryption. // 2. Define PARTIAL_UNROLL to unroll two loops in encryption and decryption. // 3. Define FIXED_TABLES for compiled rather than dynamic tables. // 4. Define FF_TABLES to use tables for field multiplies and inverses. // Do not enable this without understanding stack space requirements. // 5. Define ARRAYS to use arrays to hold the local state block. If this // is not defined, individually declared 32-bit words are used. // 6. Define FAST_VARIABLE if a high speed variable block implementation // is needed (essentially three separate fixed block size code sequences) // 7. Define either ONE_TABLE or FOUR_TABLES for a fast table driven // version using 1 table (2 kbytes of table space) or 4 tables (8 // kbytes of table space) for higher speed. // 8. Define either ONE_LR_TABLE or FOUR_LR_TABLES for a further speed // increase by using tables for the last rounds but with more table // space (2 or 8 kbytes extra). // 9. If neither ONE_TABLE nor FOUR_TABLES is defined, a compact but // slower version is provided. // 10. If fast decryption key scheduling is needed define ONE_IM_TABLE // or FOUR_IM_TABLES for higher speed (2 or 8 kbytes extra). #define UNROLL //#define PARTIAL_UNROLL #define FIXED_TABLES //#define FF_TABLES //#define ARRAYS #define FAST_VARIABLE //#define ONE_TABLE #define FOUR_TABLES //#define ONE_LR_TABLE #define FOUR_LR_TABLES //#define ONE_IM_TABLE #define FOUR_IM_TABLES #if defined(UNROLL) && defined (PARTIAL_UNROLL) #error both UNROLL and PARTIAL_UNROLL are defined #endif #if defined(ONE_TABLE) && defined (FOUR_TABLES) #error both ONE_TABLE and FOUR_TABLES are defined #endif #if defined(ONE_LR_TABLE) && defined (FOUR_LR_TABLES) #error both ONE_LR_TABLE and FOUR_LR_TABLES are defined #endif #if defined(ONE_IM_TABLE) && defined (FOUR_IM_TABLES) #error both ONE_IM_TABLE and FOUR_IM_TABLES are defined #endif #if defined(AES_BLOCK_SIZE) && AES_BLOCK_SIZE != 16 && AES_BLOCK_SIZE != 24 && \ AES_BLOCK_SIZE != 32 #error an illegal block size has been specified #endif // upr(x,n): rotates bytes within words by n positions, moving bytes // to higher index positions with wrap around into low positions // ups(x,n): moves bytes by n positions to higher index positions in // words but without wrap around // bval(x,n): extracts a byte from a word #define upr(x, n) (((x) << 8 * (n)) | ((x) >> (32 - 8 * (n)))) #define ups(x, n) ((x) << 8 * (n)) #define bval(x, n) ((unsigned char)((x) >> 8 * (n))) #define bytes2word(b0, b1, b2, b3) \ ((u_int32_t)(b3) << 24 | (u_int32_t)(b2) << 16 | (u_int32_t)(b1) << 8 | \ (b0)) /* little endian processor without data alignment restrictions: AES_LE_OK */ /* original code: i386 */ #if defined(i386) || defined(_I386) || defined(__i386__) || defined(__i386) #define AES_LE_OK 1 /* added (tested): alpha --jjo */ #elif defined(__alpha__) || defined (__alpha) #define AES_LE_OK 1 /* added (tested): ia64 --jjo */ #elif defined(__ia64__) || defined (__ia64) #define AES_LE_OK 1 #endif #ifdef AES_LE_OK /* little endian processor without data alignment restrictions */ #define word_in(x) *(u_int32_t*)(x) #define const_word_in(x) *(const u_int32_t*)(x) #define word_out(x, v) *(u_int32_t*)(x) = (v) #define const_word_out(x, v) *(const u_int32_t*)(x) = (v) #else /* slower but generic big endian or with data alignment restrictions */ /* some additional "const" touches to stop "gcc -Wcast-qual" complains --jjo */ #define word_in(x) ((u_int32_t)(((unsigned char *)(x))[0]) | \ ((u_int32_t)(((unsigned char *)(x))[1]) << \ 8) | \ ((u_int32_t)(((unsigned char *)(x))[2]) << \ 16) | ((u_int32_t)(((unsigned char *)(x))[3]) << 24)) #define const_word_in(x) ((const u_int32_t)(((const unsigned char *)(x))[0 \ ]) | \ ((const u_int32_t)(((const unsigned char *)(x))[ \ 1]) << \ 8) | \ ((const u_int32_t)(((const unsigned char *)(x))[ \ 2]) << \ 16) | \ ((const u_int32_t)(((const unsigned char *)(x))[ \ 3]) << 24)) #define word_out(x, \ v) ((unsigned char *)(x))[0] = (v), \ ((unsigned char *)(x))[1] = \ ((v) >> 8), ((unsigned char *)(x))[2] = ((v) >> 16), \ ((unsigned char *)(x))[3] = ((v) >> 24) #define const_word_out(x, \ v) ((const unsigned char *)(x))[0] = (v), \ ((const unsigned char *)(x))[1] = ((v) >> 8), \ ((const unsigned char *)(x))[2] = ((v) >> 16), \ ((const unsigned char *)(x))[3] = ((v) >> 24) #endif // Disable at least some poor combinations of options #if !defined(ONE_TABLE) && !defined(FOUR_TABLES) #define FIXED_TABLES #undef UNROLL #undef ONE_LR_TABLE #undef FOUR_LR_TABLES #undef ONE_IM_TABLE #undef FOUR_IM_TABLES #elif !defined(FOUR_TABLES) #ifdef FOUR_LR_TABLES #undef FOUR_LR_TABLES #define ONE_LR_TABLE #endif #ifdef FOUR_IM_TABLES #undef FOUR_IM_TABLES #define ONE_IM_TABLE #endif #elif !defined(AES_BLOCK_SIZE) #if defined(UNROLL) #define PARTIAL_UNROLL #undef UNROLL #endif #endif // the finite field modular polynomial and elements #define ff_poly 0x011b #define ff_hi 0x80 // multiply four bytes in GF(2^8) by 'x' {02} in parallel #define m1 0x80808080 #define m2 0x7f7f7f7f #define m3 0x0000001b #define FFmulX(x) ((((x) & m2) << 1) ^ ((((x) & m1) >> 7) * m3)) // The following defines provide alternative definitions of FFmulX that might // give improved performance if a fast 32-bit multiply is not available. Note // that a temporary variable u needs to be defined where FFmulX is used. // #define FFmulX(x) (u = (x) & m1, u |= (u >> 1), ((x) & m2) << 1) ^ ((u >> 3) | (u >> 6)) // #define m4 0x1b1b1b1b // #define FFmulX(x) (u = (x) & m1, ((x) & m2) << 1) ^ ((u - (u >> 7)) & m4) // perform column mix operation on four bytes in parallel #define fwd_mcol(x) (f2 = FFmulX(x), f2 ^ \ upr(x ^ f2, 3) ^ upr(x, 2) ^ upr(x, 1)) #if defined(FIXED_TABLES) // the S-Box table static const unsigned char s_box[256] = { 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; // the inverse S-Box table static const unsigned char inv_s_box[256] = { 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d }; #define w0(p) 0x000000 ## p // Number of elements required in this table for different // block and key lengths is: // // Nk = 4 6 8 // ---------- // Nb = 4 | 10 8 7 // 6 | 19 12 11 // 8 | 29 19 14 // // this table can be a table of bytes if the key schedule // code is adjusted accordingly static const u_int32_t rcon_tab[29] = { w0(01), w0(02), w0(04), w0(08), w0(10), w0(20), w0(40), w0(80), w0(1b), w0(36), w0(6c), w0(d8), w0(ab), w0(4d), w0(9a), w0(2f), w0(5e), w0(bc), w0(63), w0(c6), w0(97), w0(35), w0(6a), w0(d4), w0(b3), w0(7d), w0(fa), w0(ef), w0(c5) }; #undef w0 #define r0(p, q, r, s) 0x ## p ## q ## r ## s #define r1(p, q, r, s) 0x ## q ## r ## s ## p #define r2(p, q, r, s) 0x ## r ## s ## p ## q #define r3(p, q, r, s) 0x ## s ## p ## q ## r #define w0(p) 0x000000 ## p #define w1(p) 0x0000 ## p ## 00 #define w2(p) 0x00 ## p ## 0000 #define w3(p) 0x ## p ## 000000 #if defined(FIXED_TABLES) && (defined(ONE_TABLE) || defined(FOUR_TABLES)) // data for forward tables (other than last round) #define f_table \ r(a5, 63, 63, c6), r(84, 7c, 7c, f8), r(99, 77, 77, ee), r(8d, 7b, 7b, \ f6), \ r(0d, f2, f2, ff), r(bd, 6b, 6b, d6), r(b1, 6f, 6f, de), r(54, c5, c5, \ 91), \ r(50, 30, 30, 60), r(03, 01, 01, 02), r(a9, 67, 67, ce), r(7d, 2b, 2b, \ 56), \ r(19, fe, fe, e7), r(62, d7, d7, b5), r(e6, ab, ab, 4d), r(9a, 76, 76, \ ec), \ r(45, ca, ca, 8f), r(9d, 82, 82, 1f), r(40, c9, c9, 89), r(87, 7d, 7d, \ fa), \ r(15, fa, fa, ef), r(eb, 59, 59, b2), r(c9, 47, 47, 8e), r(0b, f0, f0, \ fb), \ r(ec, ad, ad, 41), r(67, d4, d4, b3), r(fd, a2, a2, 5f), r(ea, af, af, \ 45), \ r(bf, 9c, 9c, 23), r(f7, a4, a4, 53), r(96, 72, 72, e4), r(5b, c0, c0, \ 9b), \ r(c2, b7, b7, 75), r(1c, fd, fd, e1), r(ae, 93, 93, 3d), r(6a, 26, 26, \ 4c), \ r(5a, 36, 36, 6c), r(41, 3f, 3f, 7e), r(02, f7, f7, f5), r(4f, cc, cc, \ 83), \ r(5c, 34, 34, 68), r(f4, a5, a5, 51), r(34, e5, e5, d1), r(08, f1, f1, \ f9), \ r(93, 71, 71, e2), r(73, d8, d8, ab), r(53, 31, 31, 62), r(3f, 15, 15, \ 2a), \ r(0c, 04, 04, 08), r(52, c7, c7, 95), r(65, 23, 23, 46), r(5e, c3, c3, \ 9d), \ r(28, 18, 18, 30), r(a1, 96, 96, 37), r(0f, 05, 05, 0a), r(b5, 9a, 9a, \ 2f), \ r(09, 07, 07, 0e), r(36, 12, 12, 24), r(9b, 80, 80, 1b), r(3d, e2, e2, \ df), \ r(26, eb, eb, cd), r(69, 27, 27, 4e), r(cd, b2, b2, 7f), r(9f, 75, 75, \ ea), \ r(1b, 09, 09, 12), r(9e, 83, 83, 1d), r(74, 2c, 2c, 58), r(2e, 1a, 1a, \ 34), \ r(2d, 1b, 1b, 36), r(b2, 6e, 6e, dc), r(ee, 5a, 5a, b4), r(fb, a0, a0, \ 5b), \ r(f6, 52, 52, a4), r(4d, 3b, 3b, 76), r(61, d6, d6, b7), r(ce, b3, b3, \ 7d), \ r(7b, 29, 29, 52), r(3e, e3, e3, dd), r(71, 2f, 2f, 5e), r(97, 84, 84, \ 13), \ r(f5, 53, 53, a6), r(68, d1, d1, b9), r(00, 00, 00, 00), r(2c, ed, ed, \ c1), \ r(60, 20, 20, 40), r(1f, fc, fc, e3), r(c8, b1, b1, 79), r(ed, 5b, 5b, \ b6), \ r(be, 6a, 6a, d4), r(46, cb, cb, 8d), r(d9, be, be, 67), r(4b, 39, 39, \ 72), \ r(de, 4a, 4a, 94), r(d4, 4c, 4c, 98), r(e8, 58, 58, b0), r(4a, cf, cf, \ 85), \ r(6b, d0, d0, bb), r(2a, ef, ef, c5), r(e5, aa, aa, 4f), r(16, fb, fb, \ ed), \ r(c5, 43, 43, 86), r(d7, 4d, 4d, 9a), r(55, 33, 33, 66), r(94, 85, 85, \ 11), \ r(cf, 45, 45, 8a), r(10, f9, f9, e9), r(06, 02, 02, 04), r(81, 7f, 7f, \ fe), \ r(f0, 50, 50, a0), r(44, 3c, 3c, 78), r(ba, 9f, 9f, 25), r(e3, a8, a8, \ 4b), \ r(f3, 51, 51, a2), r(fe, a3, a3, 5d), r(c0, 40, 40, 80), r(8a, 8f, 8f, \ 05), \ r(ad, 92, 92, 3f), r(bc, 9d, 9d, 21), r(48, 38, 38, 70), r(04, f5, f5, \ f1), \ r(df, bc, bc, 63), r(c1, b6, b6, 77), r(75, da, da, af), r(63, 21, 21, \ 42), \ r(30, 10, 10, 20), r(1a, ff, ff, e5), r(0e, f3, f3, fd), r(6d, d2, d2, \ bf), \ r(4c, cd, cd, 81), r(14, 0c, 0c, 18), r(35, 13, 13, 26), r(2f, ec, ec, \ c3), \ r(e1, 5f, 5f, be), r(a2, 97, 97, 35), r(cc, 44, 44, 88), r(39, 17, 17, \ 2e), \ r(57, c4, c4, 93), r(f2, a7, a7, 55), r(82, 7e, 7e, fc), r(47, 3d, 3d, \ 7a), \ r(ac, 64, 64, c8), r(e7, 5d, 5d, ba), r(2b, 19, 19, 32), r(95, 73, 73, \ e6), \ r(a0, 60, 60, c0), r(98, 81, 81, 19), r(d1, 4f, 4f, 9e), r(7f, dc, dc, \ a3), \ r(66, 22, 22, 44), r(7e, 2a, 2a, 54), r(ab, 90, 90, 3b), r(83, 88, 88, \ 0b), \ r(ca, 46, 46, 8c), r(29, ee, ee, c7), r(d3, b8, b8, 6b), r(3c, 14, 14, \ 28), \ r(79, de, de, a7), r(e2, 5e, 5e, bc), r(1d, 0b, 0b, 16), r(76, db, db, \ ad), \ r(3b, e0, e0, db), r(56, 32, 32, 64), r(4e, 3a, 3a, 74), r(1e, 0a, 0a, \ 14), \ r(db, 49, 49, 92), r(0a, 06, 06, 0c), r(6c, 24, 24, 48), r(e4, 5c, 5c, \ b8), \ r(5d, c2, c2, 9f), r(6e, d3, d3, bd), r(ef, ac, ac, 43), r(a6, 62, 62, \ c4), \ r(a8, 91, 91, 39), r(a4, 95, 95, 31), r(37, e4, e4, d3), r(8b, 79, 79, \ f2), \ r(32, e7, e7, d5), r(43, c8, c8, 8b), r(59, 37, 37, 6e), r(b7, 6d, 6d, \ da), \ r(8c, 8d, 8d, 01), r(64, d5, d5, b1), r(d2, 4e, 4e, 9c), r(e0, a9, a9, \ 49), \ r(b4, 6c, 6c, d8), r(fa, 56, 56, ac), r(07, f4, f4, f3), r(25, ea, ea, \ cf), \ r(af, 65, 65, ca), r(8e, 7a, 7a, f4), r(e9, ae, ae, 47), r(18, 08, 08, \ 10), \ r(d5, ba, ba, 6f), r(88, 78, 78, f0), r(6f, 25, 25, 4a), r(72, 2e, 2e, \ 5c), \ r(24, 1c, 1c, 38), r(f1, a6, a6, 57), r(c7, b4, b4, 73), r(51, c6, c6, \ 97), \ r(23, e8, e8, cb), r(7c, dd, dd, a1), r(9c, 74, 74, e8), r(21, 1f, 1f, \ 3e), \ r(dd, 4b, 4b, 96), r(dc, bd, bd, 61), r(86, 8b, 8b, 0d), r(85, 8a, 8a, \ 0f), \ r(90, 70, 70, e0), r(42, 3e, 3e, 7c), r(c4, b5, b5, 71), r(aa, 66, 66, \ cc), \ r(d8, 48, 48, 90), r(05, 03, 03, 06), r(01, f6, f6, f7), r(12, 0e, 0e, \ 1c), \ r(a3, 61, 61, c2), r(5f, 35, 35, 6a), r(f9, 57, 57, ae), r(d0, b9, b9, \ 69), \ r(91, 86, 86, 17), r(58, c1, c1, 99), r(27, 1d, 1d, 3a), r(b9, 9e, 9e, \ 27), \ r(38, e1, e1, d9), r(13, f8, f8, eb), r(b3, 98, 98, 2b), r(33, 11, 11, \ 22), \ r(bb, 69, 69, d2), r(70, d9, d9, a9), r(89, 8e, 8e, 07), r(a7, 94, 94, \ 33), \ r(b6, 9b, 9b, 2d), r(22, 1e, 1e, 3c), r(92, 87, 87, 15), r(20, e9, e9, \ c9), \ r(49, ce, ce, 87), r(ff, 55, 55, aa), r(78, 28, 28, 50), r(7a, df, df, \ a5), \ r(8f, 8c, 8c, 03), r(f8, a1, a1, 59), r(80, 89, 89, 09), r(17, 0d, 0d, \ 1a), \ r(da, bf, bf, 65), r(31, e6, e6, d7), r(c6, 42, 42, 84), r(b8, 68, 68, \ d0), \ r(c3, 41, 41, 82), r(b0, 99, 99, 29), r(77, 2d, 2d, 5a), r(11, 0f, 0f, \ 1e), \ r(cb, b0, b0, 7b), r(fc, 54, 54, a8), r(d6, bb, bb, 6d), r(3a, 16, 16, \ 2c) // data for inverse tables (other than last round) #define i_table \ r(50, a7, f4, 51), r(53, 65, 41, 7e), r(c3, a4, 17, 1a), r(96, 5e, 27, \ 3a), \ r(cb, 6b, ab, 3b), r(f1, 45, 9d, 1f), r(ab, 58, fa, ac), r(93, 03, e3, \ 4b), \ r(55, fa, 30, 20), r(f6, 6d, 76, ad), r(91, 76, cc, 88), r(25, 4c, 02, \ f5), \ r(fc, d7, e5, 4f), r(d7, cb, 2a, c5), r(80, 44, 35, 26), r(8f, a3, 62, \ b5), \ r(49, 5a, b1, de), r(67, 1b, ba, 25), r(98, 0e, ea, 45), r(e1, c0, fe, \ 5d), \ r(02, 75, 2f, c3), r(12, f0, 4c, 81), r(a3, 97, 46, 8d), r(c6, f9, d3, \ 6b), \ r(e7, 5f, 8f, 03), r(95, 9c, 92, 15), r(eb, 7a, 6d, bf), r(da, 59, 52, \ 95), \ r(2d, 83, be, d4), r(d3, 21, 74, 58), r(29, 69, e0, 49), r(44, c8, c9, \ 8e), \ r(6a, 89, c2, 75), r(78, 79, 8e, f4), r(6b, 3e, 58, 99), r(dd, 71, b9, \ 27), \ r(b6, 4f, e1, be), r(17, ad, 88, f0), r(66, ac, 20, c9), r(b4, 3a, ce, \ 7d), \ r(18, 4a, df, 63), r(82, 31, 1a, e5), r(60, 33, 51, 97), r(45, 7f, 53, \ 62), \ r(e0, 77, 64, b1), r(84, ae, 6b, bb), r(1c, a0, 81, fe), r(94, 2b, 08, \ f9), \ r(58, 68, 48, 70), r(19, fd, 45, 8f), r(87, 6c, de, 94), r(b7, f8, 7b, \ 52), \ r(23, d3, 73, ab), r(e2, 02, 4b, 72), r(57, 8f, 1f, e3), r(2a, ab, 55, \ 66), \ r(07, 28, eb, b2), r(03, c2, b5, 2f), r(9a, 7b, c5, 86), r(a5, 08, 37, \ d3), \ r(f2, 87, 28, 30), r(b2, a5, bf, 23), r(ba, 6a, 03, 02), r(5c, 82, 16, \ ed), \ r(2b, 1c, cf, 8a), r(92, b4, 79, a7), r(f0, f2, 07, f3), r(a1, e2, 69, \ 4e), \ r(cd, f4, da, 65), r(d5, be, 05, 06), r(1f, 62, 34, d1), r(8a, fe, a6, \ c4), \ r(9d, 53, 2e, 34), r(a0, 55, f3, a2), r(32, e1, 8a, 05), r(75, eb, f6, \ a4), \ r(39, ec, 83, 0b), r(aa, ef, 60, 40), r(06, 9f, 71, 5e), r(51, 10, 6e, \ bd), \ r(f9, 8a, 21, 3e), r(3d, 06, dd, 96), r(ae, 05, 3e, dd), r(46, bd, e6, \ 4d), \ r(b5, 8d, 54, 91), r(05, 5d, c4, 71), r(6f, d4, 06, 04), r(ff, 15, 50, \ 60), \ r(24, fb, 98, 19), r(97, e9, bd, d6), r(cc, 43, 40, 89), r(77, 9e, d9, \ 67), \ r(bd, 42, e8, b0), r(88, 8b, 89, 07), r(38, 5b, 19, e7), r(db, ee, c8, \ 79), \ r(47, 0a, 7c, a1), r(e9, 0f, 42, 7c), r(c9, 1e, 84, f8), r(00, 00, 00, \ 00), \ r(83, 86, 80, 09), r(48, ed, 2b, 32), r(ac, 70, 11, 1e), r(4e, 72, 5a, \ 6c), \ r(fb, ff, 0e, fd), r(56, 38, 85, 0f), r(1e, d5, ae, 3d), r(27, 39, 2d, \ 36), \ r(64, d9, 0f, 0a), r(21, a6, 5c, 68), r(d1, 54, 5b, 9b), r(3a, 2e, 36, \ 24), \ r(b1, 67, 0a, 0c), r(0f, e7, 57, 93), r(d2, 96, ee, b4), r(9e, 91, 9b, \ 1b), \ r(4f, c5, c0, 80), r(a2, 20, dc, 61), r(69, 4b, 77, 5a), r(16, 1a, 12, \ 1c), \ r(0a, ba, 93, e2), r(e5, 2a, a0, c0), r(43, e0, 22, 3c), r(1d, 17, 1b, \ 12), \ r(0b, 0d, 09, 0e), r(ad, c7, 8b, f2), r(b9, a8, b6, 2d), r(c8, a9, 1e, \ 14), \ r(85, 19, f1, 57), r(4c, 07, 75, af), r(bb, dd, 99, ee), r(fd, 60, 7f, \ a3), \ r(9f, 26, 01, f7), r(bc, f5, 72, 5c), r(c5, 3b, 66, 44), r(34, 7e, fb, \ 5b), \ r(76, 29, 43, 8b), r(dc, c6, 23, cb), r(68, fc, ed, b6), r(63, f1, e4, \ b8), \ r(ca, dc, 31, d7), r(10, 85, 63, 42), r(40, 22, 97, 13), r(20, 11, c6, \ 84), \ r(7d, 24, 4a, 85), r(f8, 3d, bb, d2), r(11, 32, f9, ae), r(6d, a1, 29, \ c7), \ r(4b, 2f, 9e, 1d), r(f3, 30, b2, dc), r(ec, 52, 86, 0d), r(d0, e3, c1, \ 77), \ r(6c, 16, b3, 2b), r(99, b9, 70, a9), r(fa, 48, 94, 11), r(22, 64, e9, \ 47), \ r(c4, 8c, fc, a8), r(1a, 3f, f0, a0), r(d8, 2c, 7d, 56), r(ef, 90, 33, \ 22), \ r(c7, 4e, 49, 87), r(c1, d1, 38, d9), r(fe, a2, ca, 8c), r(36, 0b, d4, \ 98), \ r(cf, 81, f5, a6), r(28, de, 7a, a5), r(26, 8e, b7, da), r(a4, bf, ad, \ 3f), \ r(e4, 9d, 3a, 2c), r(0d, 92, 78, 50), r(9b, cc, 5f, 6a), r(62, 46, 7e, \ 54), \ r(c2, 13, 8d, f6), r(e8, b8, d8, 90), r(5e, f7, 39, 2e), r(f5, af, c3, \ 82), \ r(be, 80, 5d, 9f), r(7c, 93, d0, 69), r(a9, 2d, d5, 6f), r(b3, 12, 25, \ cf), \ r(3b, 99, ac, c8), r(a7, 7d, 18, 10), r(6e, 63, 9c, e8), r(7b, bb, 3b, \ db), \ r(09, 78, 26, cd), r(f4, 18, 59, 6e), r(01, b7, 9a, ec), r(a8, 9a, 4f, \ 83), \ r(65, 6e, 95, e6), r(7e, e6, ff, aa), r(08, cf, bc, 21), r(e6, e8, 15, \ ef), \ r(d9, 9b, e7, ba), r(ce, 36, 6f, 4a), r(d4, 09, 9f, ea), r(d6, 7c, b0, \ 29), \ r(af, b2, a4, 31), r(31, 23, 3f, 2a), r(30, 94, a5, c6), r(c0, 66, a2, \ 35), \ r(37, bc, 4e, 74), r(a6, ca, 82, fc), r(b0, d0, 90, e0), r(15, d8, a7, \ 33), \ r(4a, 98, 04, f1), r(f7, da, ec, 41), r(0e, 50, cd, 7f), r(2f, f6, 91, \ 17), \ r(8d, d6, 4d, 76), r(4d, b0, ef, 43), r(54, 4d, aa, cc), r(df, 04, 96, \ e4), \ r(e3, b5, d1, 9e), r(1b, 88, 6a, 4c), r(b8, 1f, 2c, c1), r(7f, 51, 65, \ 46), \ r(04, ea, 5e, 9d), r(5d, 35, 8c, 01), r(73, 74, 87, fa), r(2e, 41, 0b, \ fb), \ r(5a, 1d, 67, b3), r(52, d2, db, 92), r(33, 56, 10, e9), r(13, 47, d6, \ 6d), \ r(8c, 61, d7, 9a), r(7a, 0c, a1, 37), r(8e, 14, f8, 59), r(89, 3c, 13, \ eb), \ r(ee, 27, a9, ce), r(35, c9, 61, b7), r(ed, e5, 1c, e1), r(3c, b1, 47, \ 7a), \ r(59, df, d2, 9c), r(3f, 73, f2, 55), r(79, ce, 14, 18), r(bf, 37, c7, \ 73), \ r(ea, cd, f7, 53), r(5b, aa, fd, 5f), r(14, 6f, 3d, df), r(86, db, 44, \ 78), \ r(81, f3, af, ca), r(3e, c4, 68, b9), r(2c, 34, 24, 38), r(5f, 40, a3, \ c2), \ r(72, c3, 1d, 16), r(0c, 25, e2, bc), r(8b, 49, 3c, 28), r(41, 95, 0d, \ ff), \ r(71, 01, a8, 39), r(de, b3, 0c, 08), r(9c, e4, b4, d8), r(90, c1, 56, \ 64), \ r(61, 84, cb, 7b), r(70, b6, 32, d5), r(74, 5c, 6c, 48), r(42, 57, b8, \ d0) // generate the required tables in the desired endian format #undef r #define r r0 #if defined(ONE_TABLE) static const u_int32_t ft_tab[256] = { f_table }; #elif defined(FOUR_TABLES) static const u_int32_t ft_tab[4][256] = { { f_table }, #undef r #define r r1 { f_table }, #undef r #define r r2 { f_table }, #undef r #define r r3 { f_table } }; #endif #undef r #define r r0 #if defined(ONE_TABLE) static const u_int32_t it_tab[256] = { i_table }; #elif defined(FOUR_TABLES) static const u_int32_t it_tab[4][256] = { { i_table }, #undef r #define r r1 { i_table }, #undef r #define r r2 { i_table }, #undef r #define r r3 { i_table } }; #endif #endif #if defined(FIXED_TABLES) && (defined(ONE_LR_TABLE) || defined(FOUR_LR_TABLES)) // data for inverse tables (last round) #define li_table \ w(52), w(09), w(6a), w(d5), w(30), w(36), w(a5), w(38), \ w(bf), w(40), w(a3), w(9e), w(81), w(f3), w(d7), w(fb), \ w(7c), w(e3), w(39), w(82), w(9b), w(2f), w(ff), w(87), \ w(34), w(8e), w(43), w(44), w(c4), w(de), w(e9), w(cb), \ w(54), w(7b), w(94), w(32), w(a6), w(c2), w(23), w(3d), \ w(ee), w(4c), w(95), w(0b), w(42), w(fa), w(c3), w(4e), \ w(08), w(2e), w(a1), w(66), w(28), w(d9), w(24), w(b2), \ w(76), w(5b), w(a2), w(49), w(6d), w(8b), w(d1), w(25), \ w(72), w(f8), w(f6), w(64), w(86), w(68), w(98), w(16), \ w(d4), w(a4), w(5c), w(cc), w(5d), w(65), w(b6), w(92), \ w(6c), w(70), w(48), w(50), w(fd), w(ed), w(b9), w(da), \ w(5e), w(15), w(46), w(57), w(a7), w(8d), w(9d), w(84), \ w(90), w(d8), w(ab), w(00), w(8c), w(bc), w(d3), w(0a), \ w(f7), w(e4), w(58), w(05), w(b8), w(b3), w(45), w(06), \ w(d0), w(2c), w(1e), w(8f), w(ca), w(3f), w(0f), w(02), \ w(c1), w(af), w(bd), w(03), w(01), w(13), w(8a), w(6b), \ w(3a), w(91), w(11), w(41), w(4f), w(67), w(dc), w(ea), \ w(97), w(f2), w(cf), w(ce), w(f0), w(b4), w(e6), w(73), \ w(96), w(ac), w(74), w(22), w(e7), w(ad), w(35), w(85), \ w(e2), w(f9), w(37), w(e8), w(1c), w(75), w(df), w(6e), \ w(47), w(f1), w(1a), w(71), w(1d), w(29), w(c5), w(89), \ w(6f), w(b7), w(62), w(0e), w(aa), w(18), w(be), w(1b), \ w(fc), w(56), w(3e), w(4b), w(c6), w(d2), w(79), w(20), \ w(9a), w(db), w(c0), w(fe), w(78), w(cd), w(5a), w(f4), \ w(1f), w(dd), w(a8), w(33), w(88), w(07), w(c7), w(31), \ w(b1), w(12), w(10), w(59), w(27), w(80), w(ec), w(5f), \ w(60), w(51), w(7f), w(a9), w(19), w(b5), w(4a), w(0d), \ w(2d), w(e5), w(7a), w(9f), w(93), w(c9), w(9c), w(ef), \ w(a0), w(e0), w(3b), w(4d), w(ae), w(2a), w(f5), w(b0), \ w(c8), w(eb), w(bb), w(3c), w(83), w(53), w(99), w(61), \ w(17), w(2b), w(04), w(7e), w(ba), w(77), w(d6), w(26), \ w(e1), w(69), w(14), w(63), w(55), w(21), w(0c), w(7d), // generate the required tables in the desired endian format #undef r #define r(p, q, r, s) w0(q) #if defined(ONE_LR_TABLE) static const u_int32_t fl_tab[256] = { f_table }; #elif defined(FOUR_LR_TABLES) static const u_int32_t fl_tab[4][256] = { { f_table }, #undef r #define r(p, q, r, s) w1(q) { f_table }, #undef r #define r(p, q, r, s) w2(q) { f_table }, #undef r #define r(p, q, r, s) w3(q) { f_table } }; #endif #undef w #define w w0 #if defined(ONE_LR_TABLE) static const u_int32_t il_tab[256] = { li_table }; #elif defined(FOUR_LR_TABLES) static const u_int32_t il_tab[4][256] = { { li_table }, #undef w #define w w1 { li_table }, #undef w #define w w2 { li_table }, #undef w #define w w3 { li_table } }; #endif #endif #if defined(FIXED_TABLES) && (defined(ONE_IM_TABLE) || defined(FOUR_IM_TABLES)) #define m_table \ r(00, 00, 00, 00), r(0b, 0d, 09, 0e), r(16, 1a, 12, 1c), r(1d, 17, 1b, \ 12), \ r(2c, 34, 24, 38), r(27, 39, 2d, 36), r(3a, 2e, 36, 24), r(31, 23, 3f, \ 2a), \ r(58, 68, 48, 70), r(53, 65, 41, 7e), r(4e, 72, 5a, 6c), r(45, 7f, 53, \ 62), \ r(74, 5c, 6c, 48), r(7f, 51, 65, 46), r(62, 46, 7e, 54), r(69, 4b, 77, \ 5a), \ r(b0, d0, 90, e0), r(bb, dd, 99, ee), r(a6, ca, 82, fc), r(ad, c7, 8b, \ f2), \ r(9c, e4, b4, d8), r(97, e9, bd, d6), r(8a, fe, a6, c4), r(81, f3, af, \ ca), \ r(e8, b8, d8, 90), r(e3, b5, d1, 9e), r(fe, a2, ca, 8c), r(f5, af, c3, \ 82), \ r(c4, 8c, fc, a8), r(cf, 81, f5, a6), r(d2, 96, ee, b4), r(d9, 9b, e7, \ ba), \ r(7b, bb, 3b, db), r(70, b6, 32, d5), r(6d, a1, 29, c7), r(66, ac, 20, \ c9), \ r(57, 8f, 1f, e3), r(5c, 82, 16, ed), r(41, 95, 0d, ff), r(4a, 98, 04, \ f1), \ r(23, d3, 73, ab), r(28, de, 7a, a5), r(35, c9, 61, b7), r(3e, c4, 68, \ b9), \ r(0f, e7, 57, 93), r(04, ea, 5e, 9d), r(19, fd, 45, 8f), r(12, f0, 4c, \ 81), \ r(cb, 6b, ab, 3b), r(c0, 66, a2, 35), r(dd, 71, b9, 27), r(d6, 7c, b0, \ 29), \ r(e7, 5f, 8f, 03), r(ec, 52, 86, 0d), r(f1, 45, 9d, 1f), r(fa, 48, 94, \ 11), \ r(93, 03, e3, 4b), r(98, 0e, ea, 45), r(85, 19, f1, 57), r(8e, 14, f8, \ 59), \ r(bf, 37, c7, 73), r(b4, 3a, ce, 7d), r(a9, 2d, d5, 6f), r(a2, 20, dc, \ 61), \ r(f6, 6d, 76, ad), r(fd, 60, 7f, a3), r(e0, 77, 64, b1), r(eb, 7a, 6d, \ bf), \ r(da, 59, 52, 95), r(d1, 54, 5b, 9b), r(cc, 43, 40, 89), r(c7, 4e, 49, \ 87), \ r(ae, 05, 3e, dd), r(a5, 08, 37, d3), r(b8, 1f, 2c, c1), r(b3, 12, 25, \ cf), \ r(82, 31, 1a, e5), r(89, 3c, 13, eb), r(94, 2b, 08, f9), r(9f, 26, 01, \ f7), \ r(46, bd, e6, 4d), r(4d, b0, ef, 43), r(50, a7, f4, 51), r(5b, aa, fd, \ 5f), \ r(6a, 89, c2, 75), r(61, 84, cb, 7b), r(7c, 93, d0, 69), r(77, 9e, d9, \ 67), \ r(1e, d5, ae, 3d), r(15, d8, a7, 33), r(08, cf, bc, 21), r(03, c2, b5, \ 2f), \ r(32, e1, 8a, 05), r(39, ec, 83, 0b), r(24, fb, 98, 19), r(2f, f6, 91, \ 17), \ r(8d, d6, 4d, 76), r(86, db, 44, 78), r(9b, cc, 5f, 6a), r(90, c1, 56, \ 64), \ r(a1, e2, 69, 4e), r(aa, ef, 60, 40), r(b7, f8, 7b, 52), r(bc, f5, 72, \ 5c), \ r(d5, be, 05, 06), r(de, b3, 0c, 08), r(c3, a4, 17, 1a), r(c8, a9, 1e, \ 14), \ r(f9, 8a, 21, 3e), r(f2, 87, 28, 30), r(ef, 90, 33, 22), r(e4, 9d, 3a, \ 2c), \ r(3d, 06, dd, 96), r(36, 0b, d4, 98), r(2b, 1c, cf, 8a), r(20, 11, c6, \ 84), \ r(11, 32, f9, ae), r(1a, 3f, f0, a0), r(07, 28, eb, b2), r(0c, 25, e2, \ bc), \ r(65, 6e, 95, e6), r(6e, 63, 9c, e8), r(73, 74, 87, fa), r(78, 79, 8e, \ f4), \ r(49, 5a, b1, de), r(42, 57, b8, d0), r(5f, 40, a3, c2), r(54, 4d, aa, \ cc), \ r(f7, da, ec, 41), r(fc, d7, e5, 4f), r(e1, c0, fe, 5d), r(ea, cd, f7, \ 53), \ r(db, ee, c8, 79), r(d0, e3, c1, 77), r(cd, f4, da, 65), r(c6, f9, d3, \ 6b), \ r(af, b2, a4, 31), r(a4, bf, ad, 3f), r(b9, a8, b6, 2d), r(b2, a5, bf, \ 23), \ r(83, 86, 80, 09), r(88, 8b, 89, 07), r(95, 9c, 92, 15), r(9e, 91, 9b, \ 1b), \ r(47, 0a, 7c, a1), r(4c, 07, 75, af), r(51, 10, 6e, bd), r(5a, 1d, 67, \ b3), \ r(6b, 3e, 58, 99), r(60, 33, 51, 97), r(7d, 24, 4a, 85), r(76, 29, 43, \ 8b), \ r(1f, 62, 34, d1), r(14, 6f, 3d, df), r(09, 78, 26, cd), r(02, 75, 2f, \ c3), \ r(33, 56, 10, e9), r(38, 5b, 19, e7), r(25, 4c, 02, f5), r(2e, 41, 0b, \ fb), \ r(8c, 61, d7, 9a), r(87, 6c, de, 94), r(9a, 7b, c5, 86), r(91, 76, cc, \ 88), \ r(a0, 55, f3, a2), r(ab, 58, fa, ac), r(b6, 4f, e1, be), r(bd, 42, e8, \ b0), \ r(d4, 09, 9f, ea), r(df, 04, 96, e4), r(c2, 13, 8d, f6), r(c9, 1e, 84, \ f8), \ r(f8, 3d, bb, d2), r(f3, 30, b2, dc), r(ee, 27, a9, ce), r(e5, 2a, a0, \ c0), \ r(3c, b1, 47, 7a), r(37, bc, 4e, 74), r(2a, ab, 55, 66), r(21, a6, 5c, \ 68), \ r(10, 85, 63, 42), r(1b, 88, 6a, 4c), r(06, 9f, 71, 5e), r(0d, 92, 78, \ 50), \ r(64, d9, 0f, 0a), r(6f, d4, 06, 04), r(72, c3, 1d, 16), r(79, ce, 14, \ 18), \ r(48, ed, 2b, 32), r(43, e0, 22, 3c), r(5e, f7, 39, 2e), r(55, fa, 30, \ 20), \ r(01, b7, 9a, ec), r(0a, ba, 93, e2), r(17, ad, 88, f0), r(1c, a0, 81, \ fe), \ r(2d, 83, be, d4), r(26, 8e, b7, da), r(3b, 99, ac, c8), r(30, 94, a5, \ c6), \ r(59, df, d2, 9c), r(52, d2, db, 92), r(4f, c5, c0, 80), r(44, c8, c9, \ 8e), \ r(75, eb, f6, a4), r(7e, e6, ff, aa), r(63, f1, e4, b8), r(68, fc, ed, \ b6), \ r(b1, 67, 0a, 0c), r(ba, 6a, 03, 02), r(a7, 7d, 18, 10), r(ac, 70, 11, \ 1e), \ r(9d, 53, 2e, 34), r(96, 5e, 27, 3a), r(8b, 49, 3c, 28), r(80, 44, 35, \ 26), \ r(e9, 0f, 42, 7c), r(e2, 02, 4b, 72), r(ff, 15, 50, 60), r(f4, 18, 59, \ 6e), \ r(c5, 3b, 66, 44), r(ce, 36, 6f, 4a), r(d3, 21, 74, 58), r(d8, 2c, 7d, \ 56), \ r(7a, 0c, a1, 37), r(71, 01, a8, 39), r(6c, 16, b3, 2b), r(67, 1b, ba, \ 25), \ r(56, 38, 85, 0f), r(5d, 35, 8c, 01), r(40, 22, 97, 13), r(4b, 2f, 9e, \ 1d), \ r(22, 64, e9, 47), r(29, 69, e0, 49), r(34, 7e, fb, 5b), r(3f, 73, f2, \ 55), \ r(0e, 50, cd, 7f), r(05, 5d, c4, 71), r(18, 4a, df, 63), r(13, 47, d6, \ 6d), \ r(ca, dc, 31, d7), r(c1, d1, 38, d9), r(dc, c6, 23, cb), r(d7, cb, 2a, \ c5), \ r(e6, e8, 15, ef), r(ed, e5, 1c, e1), r(f0, f2, 07, f3), r(fb, ff, 0e, \ fd), \ r(92, b4, 79, a7), r(99, b9, 70, a9), r(84, ae, 6b, bb), r(8f, a3, 62, \ b5), \ r(be, 80, 5d, 9f), r(b5, 8d, 54, 91), r(a8, 9a, 4f, 83), r(a3, 97, 46, \ 8d) #undef r #define r r0 #if defined(ONE_IM_TABLE) static const u_int32_t im_tab[256] = { m_table }; #elif defined(FOUR_IM_TABLES) static const u_int32_t im_tab[4][256] = { { m_table }, #undef r #define r r1 { m_table }, #undef r #define r r2 { m_table }, #undef r #define r r3 { m_table } }; #endif #endif #else static int tab_gen = 0; static unsigned char s_box[256]; // the S box static unsigned char inv_s_box[256]; // the inverse S box static u_int32_t rcon_tab[AES_RC_LENGTH]; // table of round constants #if defined(ONE_TABLE) static u_int32_t ft_tab[256]; static u_int32_t it_tab[256]; #elif defined(FOUR_TABLES) static u_int32_t ft_tab[4][256]; static u_int32_t it_tab[4][256]; #endif #if defined(ONE_LR_TABLE) static u_int32_t fl_tab[256]; static u_int32_t il_tab[256]; #elif defined(FOUR_LR_TABLES) static u_int32_t fl_tab[4][256]; static u_int32_t il_tab[4][256]; #endif #if defined(ONE_IM_TABLE) static u_int32_t im_tab[256]; #elif defined(FOUR_IM_TABLES) static u_int32_t im_tab[4][256]; #endif // Generate the tables for the dynamic table option #if !defined(FF_TABLES) // It will generally be sensible to use tables to compute finite // field multiplies and inverses but where memory is scarse this // code might sometimes be better. // return 2 ^ (n - 1) where n is the bit number of the highest bit // set in x with x in the range 1 < x < 0x00000200. This form is // used so that locals within FFinv can be bytes rather than words static unsigned char hibit(const u_int32_t x) { unsigned char r = (unsigned char)((x >> 1) | (x >> 2)); r |= (r >> 2); r |= (r >> 4); return (r + 1) >> 1; } // return the inverse of the finite field element x static unsigned char FFinv(const unsigned char x) { unsigned char p1 = x, p2 = 0x1b, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0; if (x < 2) return x; for (;; ) { if (!n1) return v1; while (n2 >= n1) { n2 /= n1; p2 ^= p1 * n2; v2 ^= v1 * n2; n2 = hibit(p2); } if (!n2) return v2; while (n1 >= n2) { n1 /= n2; p1 ^= p2 * n1; v1 ^= v2 * n1; n1 = hibit(p1); } } } // define the finite field multiplies required for Rijndael #define FFmul02(x) ((((x) & 0x7f) << 1) ^ ((x) & 0x80 ? 0x1b : 0)) #define FFmul03(x) ((x) ^ FFmul02(x)) #define FFmul09(x) ((x) ^ FFmul02(FFmul02(FFmul02(x)))) #define FFmul0b(x) ((x) ^ FFmul02((x) ^ FFmul02(FFmul02(x)))) #define FFmul0d(x) ((x) ^ FFmul02(FFmul02((x) ^ FFmul02(x)))) #define FFmul0e(x) FFmul02((x) ^ FFmul02((x) ^ FFmul02(x))) #else #define FFinv(x) ((x) ? pow[255 - log[x]] : 0) #define FFmul02(x) (x ? pow[log[x] + 0x19] : 0) #define FFmul03(x) (x ? pow[log[x] + 0x01] : 0) #define FFmul09(x) (x ? pow[log[x] + 0xc7] : 0) #define FFmul0b(x) (x ? pow[log[x] + 0x68] : 0) #define FFmul0d(x) (x ? pow[log[x] + 0xee] : 0) #define FFmul0e(x) (x ? pow[log[x] + 0xdf] : 0) #endif // The forward and inverse affine transformations used in the S-box #define fwd_affine(x) \ (w = (u_int32_t)x, w ^= (w << 1) ^ (w << 2) ^ (w << 3) ^ (w << 4), \ 0x63 ^ (unsigned char)(w ^ (w >> 8))) #define inv_affine(x) \ (w = (u_int32_t)x, w = \ (w << \ 1) ^ \ (w << 3) ^ (w << 6), 0x05 ^ (unsigned char)(w ^ (w >> 8))) static void gen_tabs(void) { u_int32_t i, w; #if defined(FF_TABLES) unsigned char pow[512], log[256]; // log and power tables for GF(2^8) finite field with // 0x011b as modular polynomial - the simplest primitive // root is 0x03, used here to generate the tables i = 0; w = 1; do { pow[i] = (unsigned char)w; pow[i + 255] = (unsigned char)w; log[w] = (unsigned char)i++; w ^= (w << 1) ^ (w & ff_hi ? ff_poly : 0); } while (w != 1); #endif for (i = 0, w = 1; i < AES_RC_LENGTH; ++i) { rcon_tab[i] = bytes2word(w, 0, 0, 0); w = (w << 1) ^ (w & ff_hi ? ff_poly : 0); } for (i = 0; i < 256; ++i) { unsigned char b; s_box[i] = b = fwd_affine(FFinv((unsigned char)i)); w = bytes2word(b, 0, 0, 0); #if defined(ONE_LR_TABLE) fl_tab[i] = w; #elif defined(FOUR_LR_TABLES) fl_tab[0][i] = w; fl_tab[1][i] = upr(w, 1); fl_tab[2][i] = upr(w, 2); fl_tab[3][i] = upr(w, 3); #endif w = bytes2word(FFmul02(b), b, b, FFmul03(b)); #if defined(ONE_TABLE) ft_tab[i] = w; #elif defined(FOUR_TABLES) ft_tab[0][i] = w; ft_tab[1][i] = upr(w, 1); ft_tab[2][i] = upr(w, 2); ft_tab[3][i] = upr(w, 3); #endif inv_s_box[i] = b = FFinv(inv_affine((unsigned char)i)); w = bytes2word(b, 0, 0, 0); #if defined(ONE_LR_TABLE) il_tab[i] = w; #elif defined(FOUR_LR_TABLES) il_tab[0][i] = w; il_tab[1][i] = upr(w, 1); il_tab[2][i] = upr(w, 2); il_tab[3][i] = upr(w, 3); #endif w = bytes2word(FFmul0e(b), FFmul09(b), FFmul0d(b), FFmul0b(b)); #if defined(ONE_TABLE) it_tab[i] = w; #elif defined(FOUR_TABLES) it_tab[0][i] = w; it_tab[1][i] = upr(w, 1); it_tab[2][i] = upr(w, 2); it_tab[3][i] = upr(w, 3); #endif #if defined(ONE_IM_TABLE) im_tab[b] = w; #elif defined(FOUR_IM_TABLES) im_tab[0][b] = w; im_tab[1][b] = upr(w, 1); im_tab[2][b] = upr(w, 2); im_tab[3][b] = upr(w, 3); #endif } } #endif #define no_table(x, box, vf, rf, c) bytes2word( \ box[bval(vf(x, 0, c), rf(0, c))], \ box[bval(vf(x, 1, c), rf(1, c))], \ box[bval(vf(x, 2, c), rf(2, c))], \ box[bval(vf(x, 3, c), rf(3, c))]) #define one_table(x, op, tab, vf, rf, c) \ ( tab[bval(vf(x, 0, c), rf(0, c))] \ ^ op(tab[bval(vf(x, 1, c), rf(1, c))], 1) \ ^ op(tab[bval(vf(x, 2, c), rf(2, c))], 2) \ ^ op(tab[bval(vf(x, 3, c), rf(3, c))], 3)) #define four_tables(x, tab, vf, rf, c) \ ( tab[0][bval(vf(x, 0, c), rf(0, c))] \ ^ tab[1][bval(vf(x, 1, c), rf(1, c))] \ ^ tab[2][bval(vf(x, 2, c), rf(2, c))] \ ^ tab[3][bval(vf(x, 3, c), rf(3, c))]) #define vf1(x, r, c) (x) #define rf1(r, c) (r) #define rf2(r, c) ((r - c) & 3) #if defined(FOUR_LR_TABLES) #define ls_box(x, c) four_tables(x, fl_tab, vf1, rf2, c) #elif defined(ONE_LR_TABLE) #define ls_box(x, c) one_table(x, upr, fl_tab, vf1, rf2, c) #else #define ls_box(x, c) no_table(x, s_box, vf1, rf2, c) #endif #if defined(FOUR_IM_TABLES) #define inv_mcol(x) four_tables(x, im_tab, vf1, rf1, 0) #elif defined(ONE_IM_TABLE) #define inv_mcol(x) one_table(x, upr, im_tab, vf1, rf1, 0) #else #define inv_mcol(x) \ (f9 = (x), f2 = FFmulX(f9), f4 = FFmulX(f2), f8 = FFmulX(f4), f9 ^= f8, \ f2 ^= f4 ^ f8 ^ upr(f2 ^ f9, 3) ^ upr(f4 ^ f9, 2) ^ upr(f9, 1)) #endif // Subroutine to set the block size (if variable) in bytes, legal // values being 16, 24 and 32. #if defined(AES_BLOCK_SIZE) #define nc (AES_BLOCK_SIZE / 4) #else #define nc (cx->aes_Ncol) void aes_set_blk(aes_context *cx, int n_bytes) { #if !defined(FIXED_TABLES) if (!tab_gen) { gen_tabs(); tab_gen = 1; } #endif switch (n_bytes) { case 32: /* bytes */ case 256: /* bits */ nc = 8; break; case 24: /* bytes */ case 192: /* bits */ nc = 6; break; case 16: /* bytes */ case 128: /* bits */ default: nc = 4; break; } } #endif // Initialise the key schedule from the user supplied key. The key // length is now specified in bytes - 16, 24 or 32 as appropriate. // This corresponds to bit lengths of 128, 192 and 256 bits, and // to Nk values of 4, 6 and 8 respectively. #define mx(t, f) (*t++ = inv_mcol(*f), f++) #define cp(t, f) *t++ = *f++ #if AES_BLOCK_SIZE == 16 #define cpy(d, s) cp(d, s); cp(d, s); cp(d, s); cp(d, s) #define mix(d, s) mx(d, s); mx(d, s); mx(d, s); mx(d, s) #elif AES_BLOCK_SIZE == 24 #define cpy(d, s) cp(d, s); cp(d, s); cp(d, s); cp(d, s); \ cp(d, s); cp(d, s) #define mix(d, s) mx(d, s); mx(d, s); mx(d, s); mx(d, s); \ mx(d, s); mx(d, s) #elif AES_BLOCK_SIZE == 32 #define cpy(d, s) cp(d, s); cp(d, s); cp(d, s); cp(d, s); \ cp(d, s); cp(d, s); cp(d, s); cp(d, s) #define mix(d, s) mx(d, s); mx(d, s); mx(d, s); mx(d, s); \ mx(d, s); mx(d, s); mx(d, s); mx(d, s) #else #define cpy(d, s) \ switch (nc) \ { case 8: cp(d, s); cp(d, s); \ case 6: cp(d, s); cp(d, s); \ case 4: cp(d, s); cp(d, s); \ cp(d, s); cp(d, s); \ } #define mix(d, s) \ switch (nc) \ { case 8: mx(d, s); mx(d, s); \ case 6: mx(d, s); mx(d, s); \ case 4: mx(d, s); mx(d, s); \ mx(d, s); mx(d, s); \ } #endif void aes_set_key(aes_context *cx, const unsigned char in_key[], int n_bytes, const int f) { u_int32_t *kf, *kt, rci; #if !defined(FIXED_TABLES) if (!tab_gen) { gen_tabs(); tab_gen = 1; } #endif switch (n_bytes) { case 32: /* bytes */ case 256: /* bits */ cx->aes_Nkey = 8; break; case 24: /* bytes */ case 192: /* bits */ cx->aes_Nkey = 6; break; case 16: /* bytes */ case 128: /* bits */ default: cx->aes_Nkey = 4; break; } cx->aes_Nrnd = (cx->aes_Nkey > nc ? cx->aes_Nkey : nc) + 6; cx->aes_e_key[0] = const_word_in(in_key ); cx->aes_e_key[1] = const_word_in(in_key + 4); cx->aes_e_key[2] = const_word_in(in_key + 8); cx->aes_e_key[3] = const_word_in(in_key + 12); kf = cx->aes_e_key; kt = kf + nc * (cx->aes_Nrnd + 1) - cx->aes_Nkey; rci = 0; switch (cx->aes_Nkey) { case 4: do { kf[4] = kf[0] ^ ls_box(kf[3], 3) ^ rcon_tab[rci++]; kf[5] = kf[1] ^ kf[4]; kf[6] = kf[2] ^ kf[5]; kf[7] = kf[3] ^ kf[6]; kf += 4; } while (kf < kt); break; case 6: cx->aes_e_key[4] = const_word_in(in_key + 16); cx->aes_e_key[5] = const_word_in(in_key + 20); do { kf[ 6] = kf[0] ^ ls_box(kf[5], 3) ^ rcon_tab[rci++]; kf[ 7] = kf[1] ^ kf[ 6]; kf[ 8] = kf[2] ^ kf[ 7]; kf[ 9] = kf[3] ^ kf[ 8]; kf[10] = kf[4] ^ kf[ 9]; kf[11] = kf[5] ^ kf[10]; kf += 6; } while (kf < kt); break; case 8: cx->aes_e_key[4] = const_word_in(in_key + 16); cx->aes_e_key[5] = const_word_in(in_key + 20); cx->aes_e_key[6] = const_word_in(in_key + 24); cx->aes_e_key[7] = const_word_in(in_key + 28); do { kf[ 8] = kf[0] ^ ls_box(kf[7], 3) ^ rcon_tab[rci++]; kf[ 9] = kf[1] ^ kf[ 8]; kf[10] = kf[2] ^ kf[ 9]; kf[11] = kf[3] ^ kf[10]; kf[12] = kf[4] ^ ls_box(kf[11], 0); kf[13] = kf[5] ^ kf[12]; kf[14] = kf[6] ^ kf[13]; kf[15] = kf[7] ^ kf[14]; kf += 8; } while (kf < kt); break; } if (!f) { u_int32_t i; kt = cx->aes_d_key + nc * cx->aes_Nrnd; kf = cx->aes_e_key; cpy(kt, kf); kt -= 2 * nc; for (i = 1; i < cx->aes_Nrnd; ++i) { #if defined(ONE_TABLE) || defined(FOUR_TABLES) #if !defined(ONE_IM_TABLE) && !defined(FOUR_IM_TABLES) u_int32_t f2, f4, f8, f9; #endif mix(kt, kf); #else cpy(kt, kf); #endif kt -= 2 * nc; } cpy(kt, kf); } } // y = output word, x = input word, r = row, c = column // for r = 0, 1, 2 and 3 = column accessed for row r #if defined(ARRAYS) #define s(x, c) x[c] #else #define s(x, c) x ## c #endif // I am grateful to Frank Yellin for the following constructions // which, given the column (c) of the output state variable that // is being computed, return the input state variables which are // needed for each row (r) of the state // For the fixed block size options, compilers reduce these two // expressions to fixed variable references. For variable block // size code conditional clauses will sometimes be returned #define unused 77 // Sunset Strip #define fwd_var(x, r, c) \ ( r == 0 ? \ ( c == 0 ? s(x, 0) \ : c == 1 ? s(x, 1) \ : c == 2 ? s(x, 2) \ : c == 3 ? s(x, 3) \ : c == 4 ? s(x, 4) \ : c == 5 ? s(x, 5) \ : c == 6 ? s(x, 6) \ : s(x, 7)) \ : r == 1 ? \ ( c == 0 ? s(x, 1) \ : c == 1 ? s(x, 2) \ : c == 2 ? s(x, 3) \ : c == 3 ? nc == 4 ? s(x, 0) : s(x, 4) \ : c == 4 ? s(x, 5) \ : c == 5 ? nc == 8 ? s(x, 6) : s(x, 0) \ : c == 6 ? s(x, 7) \ : s(x, 0)) \ : r == 2 ? \ ( c == 0 ? nc == 8 ? s(x, 3) : s(x, 2) \ : c == 1 ? nc == 8 ? s(x, 4) : s(x, 3) \ : c == 2 ? nc == 4 ? s(x, 0) : nc == 8 ? s(x, 5) : s(x, 4) \ : c == 3 ? nc == 4 ? s(x, 1) : nc == 8 ? s(x, 6) : s(x, 5) \ : c == 4 ? nc == 8 ? s(x, 7) : s(x, 0) \ : c == 5 ? nc == 8 ? s(x, 0) : s(x, 1) \ : c == 6 ? s(x, 1) \ : s(x, 2)) \ : \ ( c == 0 ? nc == 8 ? s(x, 4) : s(x, 3) \ : c == 1 ? nc == 4 ? s(x, 0) : nc == 8 ? s(x, 5) : s(x, 4) \ : c == 2 ? nc == 4 ? s(x, 1) : nc == 8 ? s(x, 6) : s(x, 5) \ : c == 3 ? nc == 4 ? s(x, 2) : nc == 8 ? s(x, 7) : s(x, 0) \ : c == 4 ? nc == 8 ? s(x, 0) : s(x, 1) \ : c == 5 ? nc == 8 ? s(x, 1) : s(x, 2) \ : c == 6 ? s(x, 2) \ : s(x, 3))) #define inv_var(x, r, c) \ ( r == 0 ? \ ( c == 0 ? s(x, 0) \ : c == 1 ? s(x, 1) \ : c == 2 ? s(x, 2) \ : c == 3 ? s(x, 3) \ : c == 4 ? s(x, 4) \ : c == 5 ? s(x, 5) \ : c == 6 ? s(x, 6) \ : s(x, 7)) \ : r == 1 ? \ ( c == 0 ? nc == 4 ? s(x, 3) : nc == 8 ? s(x, 7) : s(x, 5) \ : c == 1 ? s(x, 0) \ : c == 2 ? s(x, 1) \ : c == 3 ? s(x, 2) \ : c == 4 ? s(x, 3) \ : c == 5 ? s(x, 4) \ : c == 6 ? s(x, 5) \ : s(x, 6)) \ : r == 2 ? \ ( c == 0 ? nc == 4 ? s(x, 2) : nc == 8 ? s(x, 5) : s(x, 4) \ : c == 1 ? nc == 4 ? s(x, 3) : nc == 8 ? s(x, 6) : s(x, 5) \ : c == 2 ? nc == 8 ? s(x, 7) : s(x, 0) \ : c == 3 ? nc == 8 ? s(x, 0) : s(x, 1) \ : c == 4 ? nc == 8 ? s(x, 1) : s(x, 2) \ : c == 5 ? nc == 8 ? s(x, 2) : s(x, 3) \ : c == 6 ? s(x, 3) \ : s(x, 4)) \ : \ ( c == 0 ? nc == 4 ? s(x, 1) : nc == 8 ? s(x, 4) : s(x, 3) \ : c == 1 ? nc == 4 ? s(x, 2) : nc == 8 ? s(x, 5) : s(x, 4) \ : c == 2 ? nc == 4 ? s(x, 3) : nc == 8 ? s(x, 6) : s(x, 5) \ : c == 3 ? nc == 8 ? s(x, 7) : s(x, 0) \ : c == 4 ? nc == 8 ? s(x, 0) : s(x, 1) \ : c == 5 ? nc == 8 ? s(x, 1) : s(x, 2) \ : c == 6 ? s(x, 2) \ : s(x, 3))) #define si(y, x, k, c) s(y, c) = const_word_in(x + 4 * c) ^ k[c] #define so(y, x, c) word_out(y + 4 * c, s(x, c)) #if defined(FOUR_TABLES) #define fwd_rnd(y, x, k, c) s(y, c) = (k)[c] ^ four_tables(x, ft_tab, \ fwd_var, rf1, c) #define inv_rnd(y, x, k, c) s(y, c) = (k)[c] ^ four_tables(x, it_tab, \ inv_var, rf1, c) #elif defined(ONE_TABLE) #define fwd_rnd(y, x, k, c) s(y, c) = (k)[c] ^ one_table(x, upr, ft_tab, \ fwd_var, rf1, c) #define inv_rnd(y, x, k, c) s(y, c) = (k)[c] ^ one_table(x, upr, it_tab, \ inv_var, rf1, c) #else #define fwd_rnd(y, x, k, c) s(y, \ c) = \ fwd_mcol(no_table(x, s_box, fwd_var, rf1, c)) ^ (k)[c] #define inv_rnd(y, x, k, c) s(y, \ c) = \ inv_mcol(no_table(x, inv_s_box, inv_var, rf1, c) ^ (k)[c]) #endif #if defined(FOUR_LR_TABLES) #define fwd_lrnd(y, x, k, c) s(y, c) = (k)[c] ^ four_tables(x, fl_tab, \ fwd_var, rf1, c) #define inv_lrnd(y, x, k, c) s(y, c) = (k)[c] ^ four_tables(x, il_tab, \ inv_var, rf1, c) #elif defined(ONE_LR_TABLE) #define fwd_lrnd(y, x, k, c) s(y, c) = (k)[c] ^ one_table(x, ups, fl_tab, \ fwd_var, rf1, c) #define inv_lrnd(y, x, k, c) s(y, c) = (k)[c] ^ one_table(x, ups, il_tab, \ inv_var, rf1, c) #else #define fwd_lrnd(y, x, k, c) s(y, \ c) = \ no_table(x, s_box, fwd_var, rf1, c) ^ (k)[c] #define inv_lrnd(y, x, k, c) s(y, \ c) = \ no_table(x, inv_s_box, inv_var, rf1, c) ^ (k)[c] #endif #if AES_BLOCK_SIZE == 16 #if defined(ARRAYS) #define locals(y, x) x[4], y[4] #else #define locals(y, \ x) x ## 0, x ## 1, x ## 2, x ## 3, y ## 0, y ## 1, y ## 2, \ y ## 3 // the following defines prevent the compiler requiring the declaration // of generated but unused variables in the fwd_var and inv_var macros #define b04 unused #define b05 unused #define b06 unused #define b07 unused #define b14 unused #define b15 unused #define b16 unused #define b17 unused #endif #define l_copy(y, x) s(y, 0) = s(x, 0); s(y, 1) = s(x, 1); \ s(y, 2) = s(x, 2); s(y, 3) = s(x, 3); #define state_in(y, x, k) si(y, x, k, 0); si(y, x, k, 1); si(y, x, k, 2); si(y, \ x, \ k, \ 3) #define state_out(y, x) so(y, x, 0); so(y, x, 1); so(y, x, 2); so(y, x, 3) #define round(rm, y, x, k) rm(y, x, k, 0); rm(y, x, k, 1); rm(y, x, k, 2); rm( \ y, x, k, 3) #elif AES_BLOCK_SIZE == 24 #if defined(ARRAYS) #define locals(y, x) x[6], y[6] #else #define locals(y, x) x ## 0, x ## 1, x ## 2, x ## 3, x ## 4, x ## 5, \ y ## 0, y ## 1, y ## 2, y ## 3, y ## 4, y ## 5 #define b06 unused #define b07 unused #define b16 unused #define b17 unused #endif #define l_copy(y, x) s(y, 0) = s(x, 0); s(y, 1) = s(x, 1); \ s(y, 2) = s(x, 2); s(y, 3) = s(x, 3); \ s(y, 4) = s(x, 4); s(y, 5) = s(x, 5); #define state_in(y, x, k) si(y, x, k, 0); si(y, x, k, 1); si(y, x, k, 2); \ si(y, x, k, 3); si(y, x, k, 4); si(y, x, k, 5) #define state_out(y, x) so(y, x, 0); so(y, x, 1); so(y, x, 2); \ so(y, x, 3); so(y, x, 4); so(y, x, 5) #define round(rm, y, x, k) rm(y, x, k, 0); rm(y, x, k, 1); rm(y, x, k, 2); \ rm(y, x, k, 3); rm(y, x, k, 4); rm(y, x, k, 5) #else #if defined(ARRAYS) #define locals(y, x) x[8], y[8] #else #define locals(y, \ x) x ## 0, x ## 1, x ## 2, x ## 3, x ## 4, x ## 5, x ## 6, \ x ## 7, \ y ## 0, y ## 1, y ## 2, y ## 3, y ## 4, y ## 5, y ## 6, y ## 7 #endif #define l_copy(y, x) s(y, 0) = s(x, 0); s(y, 1) = s(x, 1); \ s(y, 2) = s(x, 2); s(y, 3) = s(x, 3); \ s(y, 4) = s(x, 4); s(y, 5) = s(x, 5); \ s(y, 6) = s(x, 6); s(y, 7) = s(x, 7); #if AES_BLOCK_SIZE == 32 #define state_in(y, x, k) si(y, x, k, 0); si(y, x, k, 1); si(y, x, k, 2); si(y, \ x, \ k, \ 3); \ si(y, x, k, 4); si(y, x, k, 5); si(y, x, k, 6); si(y, x, k, 7) #define state_out(y, x) so(y, x, 0); so(y, x, 1); so(y, x, 2); so(y, x, 3); \ so(y, x, 4); so(y, x, 5); so(y, x, 6); so(y, x, 7) #define round(rm, y, x, k) rm(y, x, k, 0); rm(y, x, k, 1); rm(y, x, k, 2); rm( \ y, x, k, 3); \ rm(y, x, k, 4); rm(y, x, k, 5); rm(y, x, k, 6); rm(y, x, k, 7) #else #define state_in(y, x, k) \ switch (nc) \ { case 8: si(y, x, k, 7); si(y, x, k, 6); \ case 6: si(y, x, k, 5); si(y, x, k, 4); \ case 4: si(y, x, k, 3); si(y, x, k, 2); \ si(y, x, k, 1); si(y, x, k, 0); \ } #define state_out(y, x) \ switch (nc) \ { case 8: so(y, x, 7); so(y, x, 6); \ case 6: so(y, x, 5); so(y, x, 4); \ case 4: so(y, x, 3); so(y, x, 2); \ so(y, x, 1); so(y, x, 0); \ } #if defined(FAST_VARIABLE) #define round(rm, y, x, k) \ switch (nc) \ { case 8: rm(y, x, k, 7); rm(y, x, k, 6); \ rm(y, x, k, 5); rm(y, x, k, 4); \ rm(y, x, k, 3); rm(y, x, k, 2); \ rm(y, x, k, 1); rm(y, x, k, 0); \ break; \ case 6: rm(y, x, k, 5); rm(y, x, k, 4); \ rm(y, x, k, 3); rm(y, x, k, 2); \ rm(y, x, k, 1); rm(y, x, k, 0); \ break; \ case 4: rm(y, x, k, 3); rm(y, x, k, 2); \ rm(y, x, k, 1); rm(y, x, k, 0); \ break; \ } #else #define round(rm, y, x, k) \ switch (nc) \ { case 8: rm(y, x, k, 7); rm(y, x, k, 6); \ case 6: rm(y, x, k, 5); rm(y, x, k, 4); \ case 4: rm(y, x, k, 3); rm(y, x, k, 2); \ rm(y, x, k, 1); rm(y, x, k, 0); \ } #endif #endif #endif void aes_encrypt(const aes_context *cx, const unsigned char in_blk[], unsigned char out_blk[]) { u_int32_t locals(b0, b1); const u_int32_t *kp = cx->aes_e_key; #if !defined(ONE_TABLE) && !defined(FOUR_TABLES) u_int32_t f2; #endif state_in(b0, in_blk, kp); kp += nc; #if defined(UNROLL) switch (cx->aes_Nrnd) { case 14: round(fwd_rnd, b1, b0, kp ); round(fwd_rnd, b0, b1, kp + nc ); kp += 2 * nc; case 12: round(fwd_rnd, b1, b0, kp ); round(fwd_rnd, b0, b1, kp + nc ); kp += 2 * nc; case 10: round(fwd_rnd, b1, b0, kp ); round(fwd_rnd, b0, b1, kp + nc); round(fwd_rnd, b1, b0, kp + 2 * nc); round(fwd_rnd, b0, b1, kp + 3 * nc); round(fwd_rnd, b1, b0, kp + 4 * nc); round(fwd_rnd, b0, b1, kp + 5 * nc); round(fwd_rnd, b1, b0, kp + 6 * nc); round(fwd_rnd, b0, b1, kp + 7 * nc); round(fwd_rnd, b1, b0, kp + 8 * nc); round(fwd_lrnd, b0, b1, kp + 9 * nc); } #elif defined(PARTIAL_UNROLL) { u_int32_t rnd; for (rnd = 0; rnd < (cx->aes_Nrnd >> 1) - 1; ++rnd) { round(fwd_rnd, b1, b0, kp); round(fwd_rnd, b0, b1, kp + nc); kp += 2 * nc; } round(fwd_rnd, b1, b0, kp); round(fwd_lrnd, b0, b1, kp + nc); } #else { u_int32_t rnd; for (rnd = 0; rnd < cx->aes_Nrnd - 1; ++rnd) { round(fwd_rnd, b1, b0, kp); l_copy(b0, b1); kp += nc; } round(fwd_lrnd, b0, b1, kp); } #endif state_out(out_blk, b0); } void aes_decrypt(const aes_context *cx, const unsigned char in_blk[], unsigned char out_blk[]) { u_int32_t locals(b0, b1); const u_int32_t *kp = cx->aes_d_key; #if !defined(ONE_TABLE) && !defined(FOUR_TABLES) u_int32_t f2, f4, f8, f9; #endif state_in(b0, in_blk, kp); kp += nc; #if defined(UNROLL) switch (cx->aes_Nrnd) { case 14: round(inv_rnd, b1, b0, kp ); round(inv_rnd, b0, b1, kp + nc ); kp += 2 * nc; case 12: round(inv_rnd, b1, b0, kp ); round(inv_rnd, b0, b1, kp + nc ); kp += 2 * nc; case 10: round(inv_rnd, b1, b0, kp ); round(inv_rnd, b0, b1, kp + nc); round(inv_rnd, b1, b0, kp + 2 * nc); round(inv_rnd, b0, b1, kp + 3 * nc); round(inv_rnd, b1, b0, kp + 4 * nc); round(inv_rnd, b0, b1, kp + 5 * nc); round(inv_rnd, b1, b0, kp + 6 * nc); round(inv_rnd, b0, b1, kp + 7 * nc); round(inv_rnd, b1, b0, kp + 8 * nc); round(inv_lrnd, b0, b1, kp + 9 * nc); } #elif defined(PARTIAL_UNROLL) { u_int32_t rnd; for (rnd = 0; rnd < (cx->aes_Nrnd >> 1) - 1; ++rnd) { round(inv_rnd, b1, b0, kp); round(inv_rnd, b0, b1, kp + nc); kp += 2 * nc; } round(inv_rnd, b1, b0, kp); round(inv_lrnd, b0, b1, kp + nc); } #else { u_int32_t rnd; for (rnd = 0; rnd < cx->aes_Nrnd - 1; ++rnd) { round(inv_rnd, b1, b0, kp); l_copy(b0, b1); kp += nc; } round(inv_lrnd, b0, b1, kp); } #endif state_out(out_blk, b0); } libreswan-3.32/linux/net/ipsec/aes/aes_cbc.c000066400000000000000000000031171365625662500207740ustar00rootroot00000000000000/* // I retain copyright in this code but I encourage its free use provided // that I don't carry any responsibility for the results. I am especially // happy to see it used in free and open source software. If you do use // it I would appreciate an acknowledgement of its origin in the code or // the product that results and I would also appreciate knowing a little // about the use to which it is being put. I am grateful to Frank Yellin // for some ideas that are used in this implementation. // // Dr B. R. Gladman 6th April 2001. // // This is an implementation of the AES encryption algorithm (Rijndael) // designed by Joan Daemen and Vincent Rijmen. This version is designed // to provide both fixed and dynamic block and key lengths and can also // run with either big or little endian internal byte order (see aes.h). // It inputs block and key lengths in bytes with the legal values being // 16, 24 and 32. * */ #ifdef __KERNEL__ #include #else #include #endif #include "klips-crypto/aes_cbc.h" #include "klips-crypto/cbc_generic.h" /* returns bool success */ int AES_set_key(aes_context *aes_ctx, const u_int8_t *key, int keysize) { aes_set_key(aes_ctx, key, keysize, 0); return 1; } CBC_IMPL_BLK16(AES_cbc_encrypt, aes_context, u_int8_t *, aes_encrypt, aes_decrypt); /* * $Log: aes_cbc.c,v $ * Revision 1.2 2004/07/10 07:48:40 mcr * Moved from linux/crypto/ciphers/aes/aes_cbc.c,v * * Revision 1.1 2004/04/06 02:48:12 mcr * pullup of AES cipher from alg-branch. * * */ libreswan-3.32/linux/net/ipsec/aes/aes_xcbc_mac.c000066400000000000000000000034611365625662500220060ustar00rootroot00000000000000#ifdef __KERNEL__ #include #include #define AES_DEBUG(x) #else #include #include #define AES_DEBUG(x) x #endif #include "klips-crypto/aes.h" #include "klips-crypto/aes_xcbc_mac.h" int AES_xcbc_mac_set_key(aes_context_mac *ctxm, const u_int8_t *key, int keylen) { int ret = 1; aes_block kn[3] = { { 0x01010101, 0x01010101, 0x01010101, 0x01010101 }, { 0x02020202, 0x02020202, 0x02020202, 0x02020202 }, { 0x03030303, 0x03030303, 0x03030303, 0x03030303 }, }; aes_set_key(&ctxm->ctx_k1, key, keylen, 0); aes_encrypt(&ctxm->ctx_k1, (u_int8_t *) kn[0], (u_int8_t *) kn[0]); aes_encrypt(&ctxm->ctx_k1, (u_int8_t *) kn[1], (u_int8_t *) ctxm->k2); aes_encrypt(&ctxm->ctx_k1, (u_int8_t *) kn[2], (u_int8_t *) ctxm->k3); aes_set_key(&ctxm->ctx_k1, (u_int8_t *) kn[0], 16, 0); return ret; } static void do_pad_xor(u_int8_t *out, const u_int8_t *in, int len) { int pos = 0; for (pos = 1; pos <= 16; pos++, in++, out++) { if (pos <= len) *out ^= *in; if (pos > len) { AES_DEBUG(printf("put 0x80 at pos=%d\n", pos)); *out ^= 0x80; break; } } } static void xor_block(aes_block res, const aes_block op) { res[0] ^= op[0]; res[1] ^= op[1]; res[2] ^= op[2]; res[3] ^= op[3]; } int AES_xcbc_mac_hash(const aes_context_mac *ctxm, const u_int8_t * in, int ilen, u_int8_t hash[16]) { int ret = ilen; u_int32_t out[4] = { 0, 0, 0, 0 }; for (; ilen > 16; ilen -= 16) { xor_block(out, (const u_int32_t*) &in[0]); aes_encrypt(&ctxm->ctx_k1, in, (u_int8_t *)&out[0]); in += 16; } do_pad_xor((u_int8_t *)&out, in, ilen); if (ilen == 16) { AES_DEBUG(printf("using k3\n")); xor_block(out, ctxm->k3); } else { AES_DEBUG(printf("using k2\n")); xor_block(out, ctxm->k2); } aes_encrypt(&ctxm->ctx_k1, (u_int8_t *)out, hash); return ret; } libreswan-3.32/linux/net/ipsec/aes/ipsec_alg_aes.c000066400000000000000000000220431365625662500221720ustar00rootroot00000000000000/* * ipsec_alg AES cipher stubs * * Author: JuanJo Ciarlante * * ipsec_alg_aes.c,v 1.1.2.1 2003/11/21 18:12:23 jjo Exp * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * Fixes by: * PK: Pawel Krawczyk * Fixes list: * PK: make XCBC comply with latest draft (keylength) * */ #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38) && \ !defined(AUTOCONF_INCLUDED) #include #endif #include /* * special case: ipsec core modular with this static algo inside: * must avoid MODULE magic for this file */ #if defined(CONFIG_KLIPS_MODULE) && defined(CONFIG_KLIPS_ENC_AES) #undef MODULE #endif #include #include #include /* printk() */ #include /* error codes */ #include /* size_t */ #include /* Check if __exit is defined, if not null it */ #ifndef __exit #define __exit #endif /* Low Libreswan header coupling */ #include #include "libreswan/ipsec_alg.h" #include "klips-crypto/aes_cbc.h" #define CONFIG_KLIPS_ENC_AES_MAC 1 #define AES_CONTEXT_T aes_context static int debug_aes = 0; static int test_aes = 0; static int excl_aes = 0; static int keyminbits = 0; static int keymaxbits = 0; #if defined(CONFIG_KLIPS_ENC_AES_MODULE) MODULE_AUTHOR("JuanJo Ciarlante "); #ifdef module_param module_param(debug_aes, int, 0664); module_param(test_aes, int, 0664); module_param(excl_aes, int, 0664); module_param(keyminbits, int, 0664); module_param(keymaxbits, int, 0664); #else MODULE_PARM(debug_aes, "i"); MODULE_PARM(test_aes, "i"); MODULE_PARM(excl_aes, "i"); MODULE_PARM(keyminbits, "i"); MODULE_PARM(keymaxbits, "i"); #endif #endif #if CONFIG_KLIPS_ENC_AES_MAC #include "klips-crypto/aes_xcbc_mac.h" /* * Not IANA number yet (draft-ietf-ipsec-ciph-aes-xcbc-mac-00.txt). * We use 9 for non-modular algorithm and none for modular, thus * forcing user to specify one on module load. -kravietz */ #ifdef MODULE static int auth_id = 0; #else static int auth_id = 9; #endif #if 0 #ifdef MODULE_PARM MODULE_PARM(auth_id, "i"); #else module_param(auth_id, int, 0664); #endif #endif #endif #define ESP_AES 12 /* truly _constant_ :) */ /* 128, 192 or 256 */ #define ESP_AES_KEY_SZ_MIN 16 /* 128 bit secret key */ #define ESP_AES_KEY_SZ_MAX 32 /* 256 bit secret key */ #define ESP_AES_CBC_BLK_LEN 16 /* AES-CBC block size */ /* Values according to draft-ietf-ipsec-ciph-aes-xcbc-mac-02.txt * -kravietz */ #define ESP_AES_MAC_KEY_SZ 16 /* 128 bit MAC key */ #define ESP_AES_MAC_BLK_LEN 16 /* 128 bit block */ static int _aes_set_key(struct ipsec_alg_enc *alg, __u8 * key_e, const __u8 * key, size_t keysize) { int ret; AES_CONTEXT_T *ctx = (AES_CONTEXT_T*)key_e; ret = AES_set_key(ctx, key, keysize) != 0 ? 0 : -EINVAL; if (debug_aes > 0) { printk(KERN_DEBUG "klips_debug:_aes_set_key:" "ret=%d key_e=%p key=%p keysize=%ld\n", ret, key_e, key, (unsigned long int) keysize); } return ret; } static int _aes_cbc_encrypt(struct ipsec_alg_enc *alg, __u8 * key_e, __u8 * in, int ilen, __u8 * iv, int encrypt) { AES_CONTEXT_T *ctx = (AES_CONTEXT_T*)key_e; if (debug_aes > 0) { printk(KERN_DEBUG "klips_debug:_aes_cbc_encrypt:" "key_e=%p in=%p ilen=%d iv=%p encrypt=%d\n", key_e, in, ilen, iv, encrypt); } return AES_cbc_encrypt(ctx, in, in, ilen, iv, encrypt); } #if CONFIG_KLIPS_ENC_AES_MAC static int _aes_mac_set_key(struct ipsec_alg_auth *alg, __u8 * key_a, const __u8 * key, int keylen) { aes_context_mac *ctxm = (aes_context_mac *)key_a; return AES_xcbc_mac_set_key(ctxm, key, keylen) ? 0 : -EINVAL; } static int _aes_mac_hash(struct ipsec_alg_auth *alg, __u8 * key_a, const __u8 * dat, int len, __u8 * hash, int hashlen) { int ret; char hash_buf[16]; aes_context_mac *ctxm = (aes_context_mac *)key_a; ret = AES_xcbc_mac_hash(ctxm, dat, len, hash_buf); memcpy(hash, hash_buf, hashlen); return ret; } static struct ipsec_alg_auth ipsec_alg_AES_MAC = { ixt_common: { ixt_version: IPSEC_ALG_VERSION, ixt_refcnt: ATOMIC_INIT(0), ixt_name: "aes_mac", ixt_blocksize: ESP_AES_MAC_BLK_LEN, ixt_support: { ias_exttype: IPSEC_ALG_TYPE_AUTH, ias_id: 0, ias_keyminbits: ESP_AES_MAC_KEY_SZ * 8, ias_keymaxbits: ESP_AES_MAC_KEY_SZ * 8, }, }, #if defined(CONFIG_KLIPS_ENC_AES_MODULE) ixt_module: THIS_MODULE, #endif ixt_a_keylen: ESP_AES_MAC_KEY_SZ, ixt_a_ctx_size: sizeof(aes_context_mac), ixt_a_hmac_set_key: _aes_mac_set_key, ixt_a_hmac_hash:_aes_mac_hash, }; #endif /* CONFIG_KLIPS_ENC_AES_MAC */ static struct ipsec_alg_enc ipsec_alg_AES = { ixt_common: { ixt_version: IPSEC_ALG_VERSION, ixt_refcnt: ATOMIC_INIT(0), ixt_name: "aes", ixt_blocksize: ESP_AES_CBC_BLK_LEN, ixt_support: { ias_exttype: IPSEC_ALG_TYPE_ENCRYPT, //ias_ivlen: 128, ias_id: ESP_AES, ias_keyminbits: ESP_AES_KEY_SZ_MIN * 8, ias_keymaxbits: ESP_AES_KEY_SZ_MAX * 8, }, }, #if defined(CONFIG_KLIPS_ENC_AES_MODULE) ixt_module: THIS_MODULE, #endif ixt_e_keylen: ESP_AES_KEY_SZ_MAX, ixt_e_ctx_size: sizeof(AES_CONTEXT_T), ixt_e_set_key: _aes_set_key, ixt_e_cbc_encrypt:_aes_cbc_encrypt, }; #if defined(CONFIG_KLIPS_ENC_AES_MODULE) IPSEC_ALG_MODULE_INIT_MOD( ipsec_aes_init ) #else IPSEC_ALG_MODULE_INIT_STATIC( ipsec_aes_init ) #endif { int ret, test_ret; if (keyminbits) ipsec_alg_AES.ixt_common.ixt_support.ias_keyminbits = keyminbits; if (keymaxbits) { ipsec_alg_AES.ixt_common.ixt_support.ias_keymaxbits = keymaxbits; if (keymaxbits * 8 > ipsec_alg_AES.ixt_common.ixt_support.ias_keymaxbits) ipsec_alg_AES.ixt_e_keylen = keymaxbits * 8; } if (excl_aes) ipsec_alg_AES.ixt_common.ixt_state |= IPSEC_ALG_ST_EXCL; ret = register_ipsec_alg_enc(&ipsec_alg_AES); printk("ipsec_aes_init(alg_type=%d alg_id=%d name=%s): ret=%d\n", ipsec_alg_AES.ixt_common.ixt_support.ias_exttype, ipsec_alg_AES.ixt_common.ixt_support.ias_id, ipsec_alg_AES.ixt_common.ixt_name, ret); if (ret == 0 && test_aes) { test_ret = ipsec_alg_test( ipsec_alg_AES.ixt_common.ixt_support.ias_exttype, ipsec_alg_AES.ixt_common.ixt_support.ias_id, test_aes); printk("ipsec_aes_init(alg_type=%d alg_id=%d): test_ret=%d\n", ipsec_alg_AES.ixt_common.ixt_support.ias_exttype, ipsec_alg_AES.ixt_common.ixt_support.ias_id, test_ret); } #if CONFIG_KLIPS_ENC_AES_MAC if (auth_id != 0) { int ret; ipsec_alg_AES_MAC.ixt_common.ixt_support.ias_id = auth_id; ret = register_ipsec_alg_auth(&ipsec_alg_AES_MAC); printk("ipsec_aes_init(alg_type=%d alg_id=%d name=%s): ret=%d\n", ipsec_alg_AES_MAC.ixt_common.ixt_support.ias_exttype, ipsec_alg_AES_MAC.ixt_common.ixt_support.ias_id, ipsec_alg_AES_MAC.ixt_common.ixt_name, ret); if (ret == 0 && test_aes) { test_ret = ipsec_alg_test( ipsec_alg_AES_MAC.ixt_common.ixt_support.ias_exttype, ipsec_alg_AES_MAC.ixt_common.ixt_support.ias_id, test_aes); printk("ipsec_aes_init(alg_type=%d alg_id=%d): test_ret=%d\n", ipsec_alg_AES_MAC.ixt_common.ixt_support.ias_exttype, ipsec_alg_AES_MAC.ixt_common.ixt_support.ias_id, test_ret); } } else { printk(KERN_DEBUG "klips_debug: experimental ipsec_alg_AES_MAC not registered [Ok] (auth_id=%d)\n", auth_id); } #endif /* CONFIG_KLIPS_ENC_AES_MAC */ return ret; } #if defined(CONFIG_KLIPS_ENC_AES_MODULE) IPSEC_ALG_MODULE_EXIT_MOD( ipsec_aes_fini ) #else IPSEC_ALG_MODULE_EXIT_STATIC( ipsec_aes_fini ) #endif { #if CONFIG_KLIPS_ENC_AES_MAC if (auth_id) unregister_ipsec_alg_auth(&ipsec_alg_AES_MAC); #endif /* CONFIG_KLIPS_ENC_AES_MAC */ unregister_ipsec_alg_enc(&ipsec_alg_AES); } #ifdef MODULE_LICENSE MODULE_LICENSE("GPL"); #endif #if 0 /* +NOT_YET */ #ifndef MODULE /* * This is intended for static module setups, currently * doesn't work for modular ipsec.o with static algos inside */ static int setup_keybits(const char *str) { unsigned aux; char *end; aux = simple_strtoul(str, &end, 0); if (aux != 128 && aux != 192 && aux != 256) return 0; keyminbits = aux; if (*end == 0 || *end != ',') return 1; str = end + 1; aux = simple_strtoul(str, NULL, 0); if (aux != 128 && aux != 192 && aux != 256) return 0; if (aux >= keyminbits) keymaxbits = aux; return 1; } __setup("ipsec_aes_keybits=", setup_keybits); #endif #endif libreswan-3.32/linux/net/ipsec/alg/000077500000000000000000000000001365625662500172425ustar00rootroot00000000000000libreswan-3.32/linux/net/ipsec/alg/Config.alg_aes.in000066400000000000000000000001551365625662500223720ustar00rootroot00000000000000if [ "$CONFIG_IPSEC_ALG" = "y" ]; then tristate ' AES encryption algorithm' CONFIG_IPSEC_ENC_AES fi libreswan-3.32/linux/net/ipsec/alg/Config.alg_cryptoapi.in000066400000000000000000000004471365625662500236400ustar00rootroot00000000000000if [ "$CONFIG_IPSEC_ALG" = "y" ]; then dep_tristate ' CRYPTOAPI ciphers support (needs cryptoapi patch)' CONFIG_IPSEC_ALG_CRYPTOAPI $CONFIG_CRYPTO if [ "$CONFIG_IPSEC_ALG_CRYPTOAPI" != "n" ]; then bool ' CRYPTOAPI proprietary ciphers ' CONFIG_IPSEC_ALG_NON_LIBRE fi fi libreswan-3.32/linux/net/ipsec/alg/Config.in000066400000000000000000000001411365625662500207730ustar00rootroot00000000000000#Placeholder source net/ipsec/alg/Config.alg_aes.in source net/ipsec/alg/Config.alg_cryptoapi.in libreswan-3.32/linux/net/ipsec/alg/Makefile.alg_aes000066400000000000000000000007661365625662500223050ustar00rootroot00000000000000MOD_AES := ipsec_aes.o ALG_MODULES += $(MOD_AES) ALG_SUBDIRS += libaes obj-$(CONFIG_IPSEC_ALG_AES) += $(MOD_AES) static_init-func-$(CONFIG_IPSEC_ALG_AES)+= ipsec_aes_init alg_obj-$(CONFIG_IPSEC_ALG_AES) += ipsec_alg_aes.o AES_OBJS := ipsec_alg_aes.o $(LIBCRYPTO)/libaes/libaes.a $(MOD_AES): $(AES_OBJS) $(LD) $(EXTRA_LDFLAGS) -r $(AES_OBJS) -o $@ $(LIBCRYPTO)/libaes/libaes.a: $(MAKE) -C $(LIBCRYPTO)/libaes CC='$(CC)' 'ARCH_ASM=$(ARCH_ASM)' CFLAGS='$(CFLAGS) $(EXTRA_CFLAGS)' libaes.a libreswan-3.32/linux/net/ipsec/alg/Makefile.alg_cryptoapi000066400000000000000000000010111365625662500235270ustar00rootroot00000000000000MOD_CRYPTOAPI := ipsec_cryptoapi.o ifneq ($(wildcard $(TOPDIR)/include/linux/crypto.h),) ALG_MODULES += $(MOD_CRYPTOAPI) obj-$(CONFIG_IPSEC_ALG_CRYPTOAPI) += $(MOD_CRYPTOAPI) static_init-func-$(CONFIG_IPSEC_ALG_CRYPTOAPI)+= ipsec_cryptoapi_init alg_obj-$(CONFIG_IPSEC_ALG_CRYPTOAPI) += ipsec_alg_cryptoapi.o else $(warning "Linux CryptoAPI (2.4.22+ or 2.6.x) not found, not building ipsec_cryptoapi.o") endif CRYPTOAPI_OBJS := ipsec_alg_cryptoapi.o $(MOD_CRYPTOAPI): $(CRYPTOAPI_OBJS) $(LD) -r $(CRYPTOAPI_OBJS) -o $@ libreswan-3.32/linux/net/ipsec/alg/ipsec_alg_cryptoapi.c000066400000000000000000000320541365625662500234320ustar00rootroot00000000000000/* * ipsec_alg to linux cryptoapi GLUE * * Authors: CODE.ar TEAM * Harpo MAxx * JuanJo Ciarlante * Luciano Ruete * * ipsec_alg_cryptoapi.c,v 1.1.2.1 2003/11/21 18:12:23 jjo Exp * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * Example usage: * modinfo -p ipsec_cryptoapi (quite useful info, including supported algos) * modprobe ipsec_cryptoapi * modprobe ipsec_cryptoapi test=1 * modprobe ipsec_cryptoapi excl=1 (exclusive cipher/algo) * modprobe ipsec_cryptoapi noauto=1 aes=1 twofish=1 (only these ciphers) * modprobe ipsec_cryptoapi aes=128,128 (force these keylens) * modprobe ipsec_cryptoapi des_ede3=0 (everything but 3DES) */ #ifndef AUTOCONF_INCLUDED #include #endif #include /* * special case: ipsec core modular with this static algo inside: * must avoid MODULE magic for this file */ #if CONFIG_IPSEC_MODULE && CONFIG_IPSEC_ALG_CRYPTOAPI #undef MODULE #endif #include #include #include /* printk() */ #include /* error codes */ #include /* size_t */ #include /* Check if __exit is defined, if not null it */ #ifndef __exit #define __exit #endif /* warn the innocent */ #if !defined (CONFIG_CRYPTO) && !defined (CONFIG_CRYPTO_MODULE) #warning "No linux CryptoAPI found, install 2.4.22+ or 2.6.x" #define NO_CRYPTOAPI_SUPPORT #endif /* Low Libreswan header coupling */ #include "libreswan/ipsec_alg.h" #include #ifdef CRYPTO_API_VERSION_CODE #warning \ "Old CryptoAPI is not supported. Only linux-2.4.22+ or linux-2.6.x are supported" #define NO_CRYPTOAPI_SUPPORT #endif #ifdef NO_CRYPTOAPI_SUPPORT #warning "Building an unusable module :P" /* Catch old CryptoAPI by not allowing module to load */ IPSEC_ALG_MODULE_INIT( ipsec_cryptoapi_init ){ printk(KERN_WARNING "ipsec_cryptoapi.o was not built on stock Linux CryptoAPI (2.4.22+ or 2.6.x), not loading.\n"); return -EINVAL; } #else #include #include #include #define CIPHERNAME_AES "aes" #define CIPHERNAME_3DES "des3_ede" #define CIPHERNAME_CAST "cast5" #define CIPHERNAME_SERPENT "serpent" #define CIPHERNAME_TWOFISH "twofish" #define ESP_3DES 3 #define ESP_AES 12 #define ESP_CAST 6 /* quite constant :) */ #define ESP_SERPENT 252 /* from ipsec drafts */ #define ESP_TWOFISH 253 /* from ipsec drafts */ #define AH_MD5 2 #define AH_SHA 3 #define DIGESTNAME_MD5 "md5" #define DIGESTNAME_SHA1 "sha1" MODULE_AUTHOR("Juanjo Ciarlante, Harpo MAxx, Luciano Ruete"); static int debug = 0; static int test = 0; static int excl = 0; #ifdef module_param module_param(debug, int, 0664); module_param(test, int, 0664); module_param(excl, int, 0664); #else MODULE_PARM(debug, "i"); MODULE_PARM(test, "i"); MODULE_PARM(excl, "i"); #endif static int noauto = 0; #ifdef module_param module_param(noauto, int, 0664); #else MODULE_PARM(noauto, "i"); #endif MODULE_PARM_DESC(noauto, "Don't try all known algos, just setup enabled ones"); static int des_ede3[] = { -1, -1 }; static int aes[] = { -1, -1 }; static int cast[] = { -1, -1 }; static int serpent[] = { -1, -1 }; static int twofish[] = { -1, -1 }; #ifdef module_param_array module_param_array(des_ede3, int, NULL, 0); module_param_array(aes, int, NULL, 0); module_param_array(cast, int, NULL, 0); module_param_array(serpent, int, NULL, 0); module_param_array(twofish, int, NULL, 0); #else MODULE_PARM(des_ede3, "1-2i"); MODULE_PARM(aes, "1-2i"); MODULE_PARM(cast, "1-2i"); MODULE_PARM(serpent, "1-2i"); MODULE_PARM(twofish, "1-2i"); #endif MODULE_PARM_DESC(des_ede3, "0: disable | 1: force_enable | min,max: dontuse"); MODULE_PARM_DESC(aes, "0: disable | 1: force_enable | min,max: keybitlens"); MODULE_PARM_DESC(cast, "0: disable | 1: force_enable | min,max: keybitlens"); MODULE_PARM_DESC(serpent, "0: disable | 1: force_enable | min,max: keybitlens"); MODULE_PARM_DESC(twofish, "0: disable | 1: force_enable | min,max: keybitlens"); struct ipsec_alg_capi_cipher { const char *ciphername; /* cryptoapi's ciphername */ unsigned blocksize; unsigned short minbits; unsigned short maxbits; int *parm; /* lkm param for this cipher */ struct ipsec_alg_enc alg; /* note it's not a pointer */ }; static struct ipsec_alg_capi_cipher alg_capi_carray[] = { { CIPHERNAME_AES, 16, 128, 256, aes, { ixt_alg_id: ESP_AES, } }, { CIPHERNAME_TWOFISH, 16, 128, 256, twofish, { ixt_alg_id: ESP_TWOFISH, } }, { CIPHERNAME_SERPENT, 16, 128, 256, serpent, { ixt_alg_id: ESP_SERPENT, } }, { CIPHERNAME_CAST, 8, 128, 128, cast, { ixt_alg_id: ESP_CAST, } }, { CIPHERNAME_3DES, 8, 192, 192, des_ede3, { ixt_alg_id: ESP_3DES, } }, { NULL, 0, 0, 0, NULL, {} } }; #ifdef NOT_YET struct ipsec_alg_capi_digest { const char *digestname; /* cryptoapi's digestname */ struct digest_implementation *di; struct ipsec_alg_auth alg; /* note it's not a pointer */ }; static struct ipsec_alg_capi_cipher alg_capi_darray[] = { { DIGESTNAME_MD5, NULL, { ixt_alg_id: AH_MD5, } }, { DIGESTNAME_SHA1, NULL, { ixt_alg_id: AH_SHA, } }, { NULL, NULL, {} } }; #endif /* * "generic" linux cryptoapi setup_cipher() function */ int setup_cipher(const char *ciphername) { return crypto_alg_available(ciphername, 0); } /* * setups ipsec_alg_capi_cipher "hyper" struct components, calling * register_ipsec_alg for cointaned ipsec_alg object */ static void _capi_destroy_key(struct ipsec_alg_enc *alg, __u8 *key_e); static __u8 * _capi_new_key(struct ipsec_alg_enc *alg, const __u8 *key, size_t keylen); static int _capi_cbc_encrypt(struct ipsec_alg_enc *alg, __u8 * key_e, __u8 * in, int ilen, const __u8 * iv, int encrypt); static int setup_ipsec_alg_capi_cipher(struct ipsec_alg_capi_cipher *cptr) { int ret; cptr->alg.ixt_version = IPSEC_ALG_VERSION; cptr->alg.ixt_module = THIS_MODULE; atomic_set(&cptr->alg.ixt_refcnt, 0); fill_and_terminate(cptr->alg.ixt_name, cptr->ciphername, sizeof(cptr->alg.ixt_name)); cptr->alg.ixt_blocksize = cptr->blocksize; cptr->alg.ixt_keyminbits = cptr->minbits; cptr->alg.ixt_keymaxbits = cptr->maxbits; cptr->alg.ixt_state = 0; if (excl) cptr->alg.ixt_state |= IPSEC_ALG_ST_EXCL; cptr->alg.ixt_e_keylen = cptr->alg.ixt_keymaxbits / 8; cptr->alg.ixt_e_ctx_size = 0; cptr->alg.ixt_alg_type = IPSEC_ALG_TYPE_ENCRYPT; cptr->alg.ixt_e_new_key = _capi_new_key; cptr->alg.ixt_e_destroy_key = _capi_destroy_key; cptr->alg.ixt_e_cbc_encrypt = _capi_cbc_encrypt; cptr->alg.ixt_data = cptr; ret = register_ipsec_alg_enc(&cptr->alg); printk("setup_ipsec_alg_capi_cipher(): " "alg_type=%d alg_id=%d name=%s " "keyminbits=%d keymaxbits=%d, ret=%d\n", cptr->alg.ixt_alg_type, cptr->alg.ixt_alg_id, cptr->alg.ixt_name, cptr->alg.ixt_keyminbits, cptr->alg.ixt_keymaxbits, ret); return ret; } /* * called in ipsec_sa_wipe() time, will destroy key contexts * and do 1 unbind() */ static void _capi_destroy_key(struct ipsec_alg_enc *alg, __u8 *key_e) { struct crypto_tfm *tfm = (struct crypto_tfm*)key_e; if (debug > 0) printk(KERN_DEBUG "klips_debug: _capi_destroy_key:" "name=%s key_e=%p\n", alg->ixt_name, key_e); if (!key_e) { printk(KERN_ERR "klips_debug: _capi_destroy_key:" "name=%s NULL key_e!\n", alg->ixt_name); return; } crypto_free_tfm(tfm); } /* * create new key context, need alg->ixt_data to know which * (of many) cipher inside this module is the target */ static __u8 *_capi_new_key(struct ipsec_alg_enc *alg, const __u8 *key, size_t keylen) { struct ipsec_alg_capi_cipher *cptr; struct crypto_tfm *tfm = NULL; cptr = alg->ixt_data; if (!cptr) { printk(KERN_ERR "_capi_new_key(): " "NULL ixt_data (?!) for \"%s\" algo\n", alg->ixt_name); goto err; } if (debug > 0) printk(KERN_DEBUG "klips_debug:_capi_new_key:" "name=%s cptr=%p key=%p keysize=%d\n", alg->ixt_name, cptr, key, keylen); /* * alloc tfm */ tfm = crypto_alloc_tfm(cptr->ciphername, CRYPTO_TFM_MODE_CBC); if (!tfm) { printk(KERN_ERR "_capi_new_key(): " "NULL tfm for \"%s\" cryptoapi (\"%s\") algo\n", alg->ixt_name, cptr->ciphername); goto err; } if (crypto_cipher_setkey(tfm, key, keylen) < 0) { printk(KERN_ERR "_capi_new_key(): " "failed new_key() for \"%s\" cryptoapi algo (keylen=%d)\n", alg->ixt_name, keylen); crypto_free_tfm(tfm); tfm = NULL; } err: if (debug > 0) printk(KERN_DEBUG "klips_debug:_capi_new_key:" "name=%s key=%p keylen=%d tfm=%p\n", alg->ixt_name, key, keylen, tfm); return (__u8 *) tfm; } /* * core encryption function: will use cx->ci to call actual cipher's * cbc function */ static int _capi_cbc_encrypt(struct ipsec_alg_enc *alg, __u8 *key_e, __u8 *in, int ilen, const __u8 *iv, int encrypt) { int error = 0; struct crypto_tfm *tfm = (struct crypto_tfm *)key_e; struct scatterlist sg = { .page = virt_to_page(in), .offset = (unsigned long)in % PAGE_SIZE, .length = ilen, }; if (debug > 1) printk(KERN_DEBUG "klips_debug:_capi_cbc_encrypt:" "key_e=%p " "in=%p out=%p ilen=%d iv=%p encrypt=%d\n", key_e, in, in, ilen, iv, encrypt); crypto_cipher_set_iv(tfm, iv, crypto_tfm_alg_ivsize(tfm)); if (encrypt) error = crypto_cipher_encrypt(tfm, &sg, &sg, ilen); else error = crypto_cipher_decrypt(tfm, &sg, &sg, ilen); if (debug > 1) printk(KERN_DEBUG "klips_debug:_capi_cbc_encrypt:" "error=%d\n", error); return (error < 0) ? error : ilen; } /* * main initialization loop: for each cipher in list, do * 1) setup cryptoapi cipher else continue * 2) register ipsec_alg object */ static int setup_cipher_list(struct ipsec_alg_capi_cipher *clist) { struct ipsec_alg_capi_cipher *cptr; /* foreach cipher in list ... */ for (cptr = clist; cptr->ciphername; cptr++) { /* * see if cipher has been disabled (0) or * if noauto set and not enabled (1) */ if (cptr->parm[0] == 0 || (noauto && cptr->parm[0] < 0)) { if (debug > 0) printk(KERN_INFO "setup_cipher_list(): " "ciphername=%s skipped at user request: " "noauto=%d parm[0]=%d parm[1]=%d\n", cptr->ciphername, noauto, cptr->parm[0], cptr->parm[1]); continue; } /* * use a local ci to avoid touching cptr->ci, * if register ipsec_alg success then bind cipher */ if (setup_cipher(cptr->ciphername)) { if (debug > 0) printk(KERN_DEBUG "klips_debug:" "setup_cipher_list():" "ciphername=%s found\n", cptr->ciphername); if (setup_ipsec_alg_capi_cipher(cptr) != 0) { printk(KERN_ERR "klips_debug:" "setup_cipher_list():" "ciphername=%s failed ipsec_alg_register\n", cptr->ciphername); } } else { if (debug > 0) printk(KERN_INFO "setup_cipher_list(): lookup for ciphername=%s: not found\n", cptr->ciphername); } } return 0; } /* * deregister ipsec_alg objects and unbind ciphers */ static int unsetup_cipher_list(struct ipsec_alg_capi_cipher *clist) { struct ipsec_alg_capi_cipher *cptr; /* foreach cipher in list ... */ for (cptr = clist; cptr->ciphername; cptr++) { if (cptr->alg.ixt_state & IPSEC_ALG_ST_REGISTERED) unregister_ipsec_alg_enc(&cptr->alg); } return 0; } /* * test loop for registered algos */ static int test_cipher_list(struct ipsec_alg_capi_cipher *clist) { int test_ret; struct ipsec_alg_capi_cipher *cptr; /* foreach cipher in list ... */ for (cptr = clist; cptr->ciphername; cptr++) { if (cptr->alg.ixt_state & IPSEC_ALG_ST_REGISTERED) { test_ret = ipsec_alg_test( cptr->alg.ixt_alg_type, cptr->alg.ixt_alg_id, test); printk("test_cipher_list(alg_type=%d alg_id=%d): test_ret=%d\n", cptr->alg.ixt_alg_type, cptr->alg.ixt_alg_id, test_ret); } } return 0; } IPSEC_ALG_MODULE_INIT( ipsec_cryptoapi_init ){ int ret, test_ret; if ((ret = setup_cipher_list(alg_capi_carray)) < 0) return -EPROTONOSUPPORT; if (ret == 0 && test) test_ret = test_cipher_list(alg_capi_carray); return ret; } IPSEC_ALG_MODULE_EXIT( ipsec_cryptoapi_fini ){ unsetup_cipher_list(alg_capi_carray); } #ifdef MODULE_LICENSE MODULE_LICENSE("GPL"); #endif EXPORT_NO_SYMBOLS; #endif /* NO_CRYPTOAPI_SUPPORT */ libreswan-3.32/linux/net/ipsec/alg/scripts/000077500000000000000000000000001365625662500207315ustar00rootroot00000000000000libreswan-3.32/linux/net/ipsec/alg/scripts/mk-static_init.c.sh000077500000000000000000000006001365625662500244240ustar00rootroot00000000000000#!/bin/sh cat << EOF #include #include #include "freeswan/ipsec_alg.h" $(for i; do test -z "$i" && continue echo "extern int $i(void);" done) void ipsec_alg_static_init(void){ int __attribute__ ((unused)) err=0; $(for i; do test -z "$i" && continue echo " if ((err=$i()) < 0)" echo " printk(KERN_WARNING \"$i() returned %d\", err);" done) } EOF libreswan-3.32/linux/net/ipsec/anyaddr.c000066400000000000000000000067201365625662500202720ustar00rootroot00000000000000/* * special addresses * Copyright (C) 2000 Henry Spencer. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. */ #include "libreswan.h" /* these are mostly fallbacks for the no-IPv6-support-in-library case */ #ifndef IN6ADDR_ANY_INIT #define IN6ADDR_ANY_INIT { { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0 } } } #endif #ifndef IN6ADDR_LOOPBACK_INIT #define IN6ADDR_LOOPBACK_INIT { { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 0, 1 } } } #endif static struct in6_addr v6any = IN6ADDR_ANY_INIT; static struct in6_addr v6loop = IN6ADDR_LOOPBACK_INIT; /* - anyaddr - initialize to the any-address value */ err_t /* NULL for success, else string literal */ anyaddr(af, dst) int af; /* address family */ ip_address *dst; { uint32_t v4any = htonl(INADDR_ANY); switch (af) { case AF_INET: return initaddr((unsigned char *)&v4any, sizeof(v4any), af, dst); case AF_INET6: return initaddr((unsigned char *)&v6any, sizeof(v6any), af, dst); default: return "unknown address family in anyaddr/unspecaddr"; } } /* - unspecaddr - initialize to the unspecified-address value */ err_t /* NULL for success, else string literal */ unspecaddr(af, dst) int af; /* address family */ ip_address *dst; { return anyaddr(af, dst); } /* - loopbackaddr - initialize to the loopback-address value */ err_t /* NULL for success, else string literal */ loopbackaddr(af, dst) int af; /* address family */ ip_address *dst; { uint32_t v4loop = htonl(INADDR_LOOPBACK); switch (af) { case AF_INET: return initaddr((unsigned char *)&v4loop, sizeof(v4loop), af, dst); case AF_INET6: return initaddr((unsigned char *)&v6loop, sizeof(v6loop), af, dst); default: return "unknown address family in loopbackaddr"; } } /* - isanyaddr - test for the any-address value */ int isanyaddr(src) const ip_address * src; { uint32_t v4any = htonl(INADDR_ANY); int cmp; switch (src->u.v4.sin_family) { case AF_INET: cmp = memcmp(&src->u.v4.sin_addr.s_addr, &v4any, sizeof(v4any)); break; case AF_INET6: cmp = memcmp(&src->u.v6.sin6_addr, &v6any, sizeof(v6any)); break; case 0: /* a zeroed structure is considered any address */ return 1; default: return 0; } return (cmp == 0) ? 1 : 0; } /* - isunspecaddr - test for the unspecified-address value */ int isunspecaddr(src) const ip_address * src; { return isanyaddr(src); } /* - isloopbackaddr - test for the loopback-address value */ int isloopbackaddr(src) const ip_address * src; { uint32_t v4loop = htonl(INADDR_LOOPBACK); int cmp; switch (src->u.v4.sin_family) { case AF_INET: cmp = memcmp(&src->u.v4.sin_addr.s_addr, &v4loop, sizeof(v4loop)); break; case AF_INET6: cmp = memcmp(&src->u.v6.sin6_addr, &v6loop, sizeof(v6loop)); break; default: return 0; } return (cmp == 0) ? 1 : 0; } libreswan-3.32/linux/net/ipsec/datatot.c000066400000000000000000000122531365625662500203060ustar00rootroot00000000000000/* * convert from binary data (e.g. key) to text form * Copyright (C) 2000 Henry Spencer. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. */ #include "libreswan.h" static void convert(const char *src, size_t nreal, int format, char *out); /* - datatot - convert data bytes to text */ size_t /* true length (with NUL) for success */ datatot(src, srclen, format, dst, dstlen) const unsigned char *src; size_t srclen; int format; /* character indicating what format */ char *dst; /* need not be valid if dstlen is 0 */ size_t dstlen; { size_t inblocksize; /* process this many bytes at a time */ size_t outblocksize; /* producing this many */ size_t breakevery; /* add a _ every this many (0 means don't) */ size_t sincebreak; /* output bytes since last _ */ char breakchar; /* character used to break between groups */ unsigned char inblock[10]; /* enough for any format */ char outblock[10]; /* enough for any format */ char fake[1]; /* fake output area for dstlen == 0 */ size_t needed; /* return value */ char *stop; /* where the terminating NUL will go */ size_t ntodo; /* remaining input */ size_t nreal; char *out; char *prefix; breakevery = 0; breakchar = '_'; switch (format) { case 0: case 'h': format = 'x'; breakevery = 8; /* FALLTHROUGH */ case 'x': inblocksize = 1; outblocksize = 2; prefix = "0x"; break; case ':': breakevery = 2; breakchar = ':'; /* FALLTHROUGH */ case 16: inblocksize = 1; outblocksize = 2; prefix = ""; format = 'x'; break; case 's': inblocksize = 3; outblocksize = 4; prefix = "0s"; break; case 64: /* beware, equals ' ' */ inblocksize = 3; outblocksize = 4; prefix = ""; format = 's'; break; default: return 0; break; } user_assert(inblocksize < sizeof(inblock)); user_assert(outblocksize < sizeof(outblock)); user_assert(breakevery % outblocksize == 0); if (srclen == 0) return 0; ntodo = srclen; if (dstlen == 0) { /* dispose of awkward special case */ dst = fake; dstlen = 1; } stop = dst + dstlen - 1; nreal = strlen(prefix); needed = nreal; /* for starters */ if (dstlen <= nreal) { /* prefix won't fit */ /* fill_and_terminate */ strncpy(dst, prefix, dstlen-1); dst[dstlen-1] = '\0'; dst += dstlen - 1; } else { strcpy(dst, prefix); dst += nreal; } user_assert(dst <= stop); sincebreak = 0; while (ntodo > 0) { if (ntodo < inblocksize) { /* incomplete input */ memset(inblock, 0, sizeof(inblock)); memcpy(inblock, src, ntodo); src = inblock; nreal = ntodo; ntodo = inblocksize; } else { nreal = inblocksize; } out = ((ptrdiff_t)outblocksize > stop - dst) ? outblock : dst; convert((const char *)src, nreal, format, out); needed += outblocksize; sincebreak += outblocksize; if (dst < stop) { if (out != dst) { user_assert( (ptrdiff_t)outblocksize > stop - dst); memcpy(dst, out, stop - dst); dst = stop; } else { dst += outblocksize; } } src += inblocksize; ntodo -= inblocksize; if (breakevery != 0 && sincebreak >= breakevery && ntodo > 0) { if (dst < stop) *dst++ = breakchar; needed++; sincebreak = 0; } } user_assert(dst <= stop); *dst++ = '\0'; needed++; return needed; } /* - convert - convert one input block to one output block */ static void convert(src, nreal, format, out) const char *src; size_t nreal; /* how much of the input block is real */ int format; char *out; { static char hex[] = "0123456789abcdef"; static char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; unsigned char c; unsigned char c1, c2, c3; user_assert(nreal > 0); switch (format) { case 'x': user_assert(nreal == 1); c = (unsigned char)*src; *out++ = hex[c >> 4]; *out++ = hex[c & 0xf]; break; case 's': c1 = (unsigned char)*src++; c2 = (unsigned char)*src++; c3 = (unsigned char)*src++; *out++ = base64[c1 >> 2]; /* top 6 bits of c1 */ c = (c1 & 0x3) << 4; /* bottom 2 of c1... */ c |= c2 >> 4; /* ...top 4 of c2 */ *out++ = base64[c]; if (nreal == 1) { *out++ = '='; } else { c = (c2 & 0xf) << 2; /* bottom 4 of c2... */ c |= c3 >> 6; /* ...top 2 of c3 */ *out++ = base64[c]; } if (nreal <= 2) *out++ = '='; else *out++ = base64[c3 & 0x3f]; /* bottom 6 of c3 */ break; default: user_assert(nreal == 0); /* unknown format */ break; } } libreswan-3.32/linux/net/ipsec/defconfig000066400000000000000000000027711365625662500203550ustar00rootroot00000000000000 # # Libreswan IPsec implementation, KLIPS kernel config defaults # # # First, let's override stuff already set or not in the kernel config. # # We can't even think about leaving this off... CONFIG_INET=y # # This must be on for subnet protection. CONFIG_IP_FORWARD=y # Shut off IPSEC masquerading if it has been enabled, since it will # break the compile. IPPROTO_ESP and IPPROTO_AH were included in # net/ipv4/ip_masq.c when they should have gone into include/linux/in.h. CONFIG_IP_MASQUERADE_IPSEC=n # # Next, let's set the recommended FreeS/WAN configuration. # # To config as static (preferred), 'y'. To config as module, 'm'. CONFIG_KLIPS=m # To do tunnel mode IPsec, this must be enabled. CONFIG_KLIPS_IPIP=y # To enable authentication, say 'y'. (Highly recommended) CONFIG_KLIPS_AH=y # Authentication algorithm(s): CONFIG_KLIPS_AUTH_HMAC_MD5=y CONFIG_KLIPS_AUTH_HMAC_SHA1=y # To enable encryption, say 'y'. (Highly recommended) CONFIG_KLIPS_ESP=y # modular algo extensions (and new ALGOs) CONFIG_KLIPS_ALG=y # Encryption algorithm(s): CONFIG_KLIPS_ENC_3DES=y CONFIG_KLIPS_ENC_AES=y # Use CryptoAPI for ALG - by default, yes. CONFIG_KLIPS_ENC_CRYPTOAPI=y CONFIG_KLIPS_ENC_NULL=y # IP Compression: new, probably still has minor bugs. CONFIG_KLIPS_IPCOMP=y # To enable userspace-switchable KLIPS debugging, say 'y'. CONFIG_KLIPS_DEBUG=y # OCF HW offloading, requires kernel patch # CONFIG_KLIPS_OCF is not set # NFMARK for old-style NAT-T UDP-decapsulation # CONFIG_KLIPS_COMPAT_NAT_NFMARK is not set libreswan-3.32/linux/net/ipsec/deflate.c000066400000000000000000001376431365625662500202650ustar00rootroot00000000000000/* deflate.c -- compress data using the deflation algorithm * Copyright (C) 1995-2002 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ /* * ALGORITHM * * The "deflation" process depends on being able to identify portions * of the input text which are identical to earlier input (within a * sliding window trailing behind the input currently being processed). * * The most straightforward technique turns out to be the fastest for * most input files: try all possible matches and select the longest. * The key feature of this algorithm is that insertions into the string * dictionary are very simple and thus fast, and deletions are avoided * completely. Insertions are performed at each input character, whereas * string matches are performed only when the previous match ends. So it * is preferable to spend more time in matches to allow very fast string * insertions and avoid deletions. The matching algorithm for small * strings is inspired from that of Rabin & Karp. A brute force approach * is used to find longer strings when a small match has been found. * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze * (by Leonid Broukhis). * A previous version of this file used a more sophisticated algorithm * (by Fiala and Greene) which is guaranteed to run in linear amortized * time, but has a larger average cost, uses more memory and is patented. * However the F&G algorithm may be faster for some highly redundant * files if the parameter max_chain_length (described below) is too large. * * ACKNOWLEDGEMENTS * * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and * I found it in 'freeze' written by Leonid Broukhis. * Thanks to many people for bug reports and testing. * * REFERENCES * * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". * Available in ftp://ds.internic.net/rfc/rfc1951.txt * * A description of the Rabin and Karp algorithm is given in the book * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. * * Fiala,E.R., and Greene,D.H. * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 * */ /* @(#) $Id: deflate.c,v 1.4 2004/07/10 07:48:37 mcr Exp $ */ #include "deflate.h" local const char deflate_copyright[] = " deflate 1.1.4 Copyright 1995-2002 Jean-loup Gailly "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot include such an acknowledgment, I would appreciate that you keep this copyright string in the executable of your product. */ /* =========================================================================== * Function prototypes. */ typedef enum { need_more, /* block not completed, need more input or more output */ block_done, /* block flush performed */ finish_started, /* finish started, need only more output at next deflate */ finish_done /* finish done, accept no more input or output */ } block_state; typedef block_state (*compress_func) OF((deflate_state *s, int flush)); /* Compression function. Returns the block state after the call. */ local void fill_window OF((deflate_state *s)); local block_state deflate_stored OF((deflate_state *s, int flush)); local block_state deflate_fast OF((deflate_state *s, int flush)); local block_state deflate_slow OF((deflate_state *s, int flush)); local void lm_init OF((deflate_state *s)); local void putShortMSB OF((deflate_state *s, uInt b)); local void flush_pending OF((z_streamp strm)); local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); #ifdef ASMV void match_init OF((void)); /* asm code initialization */ uInt longest_match OF((deflate_state *s, IPos cur_match)); #else local uInt longest_match OF((deflate_state *s, IPos cur_match)); #endif #if 0 local void check_match OF((deflate_state *s, IPos start, IPos match, int length)); #endif /* =========================================================================== * Local data */ #define NIL 0 /* Tail of hash chains */ #ifndef TOO_FAR # define TOO_FAR 4096 #endif /* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ #define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) /* Minimum amount of lookahead, except at the end of the input file. * See deflate.c for comments about the MIN_MATCH+1. */ /* Values for max_lazy_match, good_match and max_chain_length, depending on * the desired pack level (0..9). The values given below have been tuned to * exclude worst case performance for pathological files. Better values may be * found for specific files. */ typedef struct config_s { ush good_length; /* reduce lazy search above this match length */ ush max_lazy; /* do not perform lazy search above this match length */ ush nice_length; /* quit search above this match length */ ush max_chain; compress_func func; } config; local const config configuration_table[10] = { /* good lazy nice chain */ /* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ /* 1 */ {4, 4, 8, 4, deflate_fast}, /* maximum speed, no lazy matches */ /* 2 */ {4, 5, 16, 8, deflate_fast}, /* 3 */ {4, 6, 32, 32, deflate_fast}, /* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ /* 5 */ {8, 16, 32, 32, deflate_slow}, /* 6 */ {8, 16, 128, 128, deflate_slow}, /* 7 */ {8, 32, 128, 256, deflate_slow}, /* 8 */ {32, 128, 258, 1024, deflate_slow}, /* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* maximum compression */ /* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 * For deflate_fast() (levels <= 3) good is ignored and lazy has a different * meaning. */ #define EQUAL 0 /* result of memcmp for equal strings */ struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ /* =========================================================================== * Update a hash value with the given input byte * IN assertion: all calls to UPDATE_HASH are made with consecutive * input characters, so that a running hash key can be computed from the * previous key instead of complete recalculation each time. */ #define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) /* =========================================================================== * Insert string str in the dictionary and set match_head to the previous head * of the hash chain (the most recent string with same hash key). Return * the previous length of the hash chain. * If this file is compiled with -DFASTEST, the compression level is forced * to 1, and no hash chains are maintained. * IN assertion: all calls to INSERT_STRING are made with consecutive * input characters and the first MIN_MATCH bytes of str are valid * (except for the last MIN_MATCH-1 bytes of the input file). */ #ifdef FASTEST #define INSERT_STRING(s, str, match_head) \ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ match_head = s->head[s->ins_h], \ s->head[s->ins_h] = (Pos)(str)) #else #define INSERT_STRING(s, str, match_head) \ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ s->prev[(str) & s->w_mask] = match_head = s->head[s->ins_h], \ s->head[s->ins_h] = (Pos)(str)) #endif /* =========================================================================== * Initialize the hash table (avoiding 64K overflow for 16 bit systems). * prev[] will be initialized on the fly. */ #define CLEAR_HASH(s) \ s->head[s->hash_size-1] = NIL; \ zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); /* ========================================================================= */ int ZEXPORT deflateInit_(strm, level, version, stream_size) z_streamp strm; int level; const char *version; int stream_size; { return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, version, stream_size); /* To do: ignore strm->next_in if we use it as window */ } /* ========================================================================= */ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, version, stream_size) z_streamp strm; int level; int method; int windowBits; int memLevel; int strategy; const char *version; int stream_size; { deflate_state *s; int noheader = 0; static const char* my_version = ZLIB_VERSION; ushf *overlay; /* We overlay pending_buf and d_buf+l_buf. This works since the average * output size for (length,distance) codes is <= 24 bits. */ if (version == Z_NULL || version[0] != my_version[0] || stream_size != sizeof(z_stream)) { return Z_VERSION_ERROR; } if (strm == Z_NULL) return Z_STREAM_ERROR; strm->msg = Z_NULL; if (strm->zalloc == Z_NULL) { return Z_STREAM_ERROR; /* strm->zalloc = zcalloc; strm->opaque = (voidpf)0;*/ } if (strm->zfree == Z_NULL) return Z_STREAM_ERROR; /* strm->zfree = zcfree; */ if (level == Z_DEFAULT_COMPRESSION) level = 6; #ifdef FASTEST level = 1; #endif if (windowBits < 0) { /* undocumented feature: suppress zlib header */ noheader = 1; windowBits = -windowBits; } if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || windowBits < 9 || windowBits > 15 || level < 0 || level > 9 || strategy < 0 || strategy > Z_HUFFMAN_ONLY) { return Z_STREAM_ERROR; } s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); if (s == Z_NULL) return Z_MEM_ERROR; strm->state = (struct internal_state FAR *)s; s->strm = strm; s->noheader = noheader; s->w_bits = windowBits; s->w_size = 1 << s->w_bits; s->w_mask = s->w_size - 1; s->hash_bits = memLevel + 7; s->hash_size = 1 << s->hash_bits; s->hash_mask = s->hash_size - 1; s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); s->pending_buf = (uchf *) overlay; s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || s->pending_buf == Z_NULL) { strm->msg = ERR_MSG(Z_MEM_ERROR); deflateEnd (strm); return Z_MEM_ERROR; } s->d_buf = overlay + s->lit_bufsize/sizeof(ush); s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; s->level = level; s->strategy = strategy; s->method = (Byte)method; return deflateReset(strm); } /* ========================================================================= */ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) z_streamp strm; const Bytef *dictionary; uInt dictLength; { deflate_state *s; uInt length = dictLength; uInt n; IPos hash_head = 0; if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || strm->state->status != INIT_STATE) return Z_STREAM_ERROR; s = strm->state; strm->adler = adler32(strm->adler, dictionary, dictLength); if (length < MIN_MATCH) return Z_OK; if (length > MAX_DIST(s)) { length = MAX_DIST(s); #ifndef USE_DICT_HEAD dictionary += dictLength - length; /* use the tail of the dictionary */ #endif } zmemcpy(s->window, dictionary, length); s->strstart = length; s->block_start = (long)length; /* Insert all strings in the hash table (except for the last two bytes). * s->lookahead stays null, so s->ins_h will be recomputed at the next * call of fill_window. */ s->ins_h = s->window[0]; UPDATE_HASH(s, s->ins_h, s->window[1]); for (n = 0; n <= length - MIN_MATCH; n++) { INSERT_STRING(s, n, hash_head); } if (hash_head) hash_head = 0; /* to make compiler happy */ return Z_OK; } /* ========================================================================= */ int ZEXPORT deflateReset (strm) z_streamp strm; { deflate_state *s; if (strm == Z_NULL || strm->state == Z_NULL || strm->zalloc == Z_NULL || strm->zfree == Z_NULL) return Z_STREAM_ERROR; strm->total_in = strm->total_out = 0; strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ strm->data_type = Z_UNKNOWN; s = (deflate_state *)strm->state; s->pending = 0; s->pending_out = s->pending_buf; if (s->noheader < 0) { s->noheader = 0; /* was set to -1 by deflate(..., Z_FINISH); */ } s->status = s->noheader ? BUSY_STATE : INIT_STATE; strm->adler = 1; s->last_flush = Z_NO_FLUSH; _tr_init(s); lm_init(s); return Z_OK; } /* ========================================================================= */ int ZEXPORT deflateParams(strm, level, strategy) z_streamp strm; int level; int strategy; { deflate_state *s; compress_func func; int err = Z_OK; if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; s = strm->state; if (level == Z_DEFAULT_COMPRESSION) { level = 6; } if (level < 0 || level > 9 || strategy < 0 || strategy > Z_HUFFMAN_ONLY) { return Z_STREAM_ERROR; } func = configuration_table[s->level].func; if (func != configuration_table[level].func && strm->total_in != 0) { /* Flush the last buffer: */ err = deflate(strm, Z_PARTIAL_FLUSH); } if (s->level != level) { s->level = level; s->max_lazy_match = configuration_table[level].max_lazy; s->good_match = configuration_table[level].good_length; s->nice_match = configuration_table[level].nice_length; s->max_chain_length = configuration_table[level].max_chain; } s->strategy = strategy; return err; } /* ========================================================================= * Put a short in the pending buffer. The 16-bit value is put in MSB order. * IN assertion: the stream state is correct and there is enough room in * pending_buf. */ local void putShortMSB (s, b) deflate_state *s; uInt b; { put_byte(s, (Byte)(b >> 8)); put_byte(s, (Byte)(b & 0xff)); } /* ========================================================================= * Flush as much pending output as possible. All deflate() output goes * through this function so some applications may wish to modify it * to avoid allocating a large strm->next_out buffer and copying into it. * (See also read_buf()). */ local void flush_pending(strm) z_streamp strm; { unsigned len = strm->state->pending; if (len > strm->avail_out) len = strm->avail_out; if (len == 0) return; zmemcpy(strm->next_out, strm->state->pending_out, len); strm->next_out += len; strm->state->pending_out += len; strm->total_out += len; strm->avail_out -= len; strm->state->pending -= len; if (strm->state->pending == 0) { strm->state->pending_out = strm->state->pending_buf; } } /* ========================================================================= */ int ZEXPORT deflate (strm, flush) z_streamp strm; int flush; { int old_flush; /* value of flush param for previous deflate call */ deflate_state *s; if (strm == Z_NULL || strm->state == Z_NULL || flush > Z_FINISH || flush < 0) { return Z_STREAM_ERROR; } s = strm->state; if (strm->next_out == Z_NULL || (strm->next_in == Z_NULL && strm->avail_in != 0) || (s->status == FINISH_STATE && flush != Z_FINISH)) { ERR_RETURN(strm, Z_STREAM_ERROR); } if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); s->strm = strm; /* just in case */ old_flush = s->last_flush; s->last_flush = flush; /* Write the zlib header */ if (s->status == INIT_STATE) { uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; uInt level_flags = (s->level-1) >> 1; if (level_flags > 3) level_flags = 3; header |= (level_flags << 6); if (s->strstart != 0) header |= PRESET_DICT; header += 31 - (header % 31); s->status = BUSY_STATE; putShortMSB(s, header); /* Save the adler32 of the preset dictionary: */ if (s->strstart != 0) { putShortMSB(s, (uInt)(strm->adler >> 16)); putShortMSB(s, (uInt)(strm->adler & 0xffff)); } strm->adler = 1L; } /* Flush as much pending output as possible */ if (s->pending != 0) { flush_pending(strm); if (strm->avail_out == 0) { /* Since avail_out is 0, deflate will be called again with * more output space, but possibly with both pending and * avail_in equal to zero. There won't be anything to do, * but this is not an error situation so make sure we * return OK instead of BUF_ERROR at next call of deflate: */ s->last_flush = -1; return Z_OK; } /* Make sure there is something to do and avoid duplicate consecutive * flushes. For repeated and useless calls with Z_FINISH, we keep * returning Z_STREAM_END instead of Z_BUFF_ERROR. */ } else if (strm->avail_in == 0 && flush <= old_flush && flush != Z_FINISH) { ERR_RETURN(strm, Z_BUF_ERROR); } /* User must not provide more input after the first FINISH: */ if (s->status == FINISH_STATE && strm->avail_in != 0) { ERR_RETURN(strm, Z_BUF_ERROR); } /* Start a new block or continue the current one. */ if (strm->avail_in != 0 || s->lookahead != 0 || (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { block_state bstate; bstate = (*(configuration_table[s->level].func))(s, flush); if (bstate == finish_started || bstate == finish_done) { s->status = FINISH_STATE; } if (bstate == need_more || bstate == finish_started) { if (strm->avail_out == 0) { s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ } return Z_OK; /* If flush != Z_NO_FLUSH && avail_out == 0, the next call * of deflate should use the same flush parameter to make sure * that the flush is complete. So we don't have to output an * empty block here, this will be done at next call. This also * ensures that for a very small output buffer, we emit at most * one empty block. */ } if (bstate == block_done) { if (flush == Z_PARTIAL_FLUSH) { _tr_align(s); } else { /* FULL_FLUSH or SYNC_FLUSH */ _tr_stored_block(s, (char*)0, 0L, 0); /* For a full flush, this empty block will be recognized * as a special marker by inflate_sync(). */ if (flush == Z_FULL_FLUSH) { CLEAR_HASH(s); /* forget history */ } } flush_pending(strm); if (strm->avail_out == 0) { s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ return Z_OK; } } } Assert(strm->avail_out > 0, "bug2"); if (flush != Z_FINISH) return Z_OK; if (s->noheader) return Z_STREAM_END; /* Write the zlib trailer (adler32) */ putShortMSB(s, (uInt)(strm->adler >> 16)); putShortMSB(s, (uInt)(strm->adler & 0xffff)); flush_pending(strm); /* If avail_out is zero, the application will call deflate again * to flush the rest. */ s->noheader = -1; /* write the trailer only once! */ return s->pending != 0 ? Z_OK : Z_STREAM_END; } /* ========================================================================= */ int ZEXPORT deflateEnd (strm) z_streamp strm; { int status; if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; status = strm->state->status; if (status != INIT_STATE && status != BUSY_STATE && status != FINISH_STATE) { return Z_STREAM_ERROR; } /* Deallocate in reverse order of allocations: */ TRY_FREE(strm, strm->state->pending_buf); TRY_FREE(strm, strm->state->head); TRY_FREE(strm, strm->state->prev); TRY_FREE(strm, strm->state->window); ZFREE(strm, strm->state); strm->state = Z_NULL; return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; } /* ========================================================================= * Copy the source state to the destination state. * To simplify the source, this is not supported for 16-bit MSDOS (which * doesn't have enough memory anyway to duplicate compression states). */ int ZEXPORT deflateCopy (dest, source) z_streamp dest; z_streamp source; { #ifdef MAXSEG_64K return Z_STREAM_ERROR; #else deflate_state *ds; deflate_state *ss; ushf *overlay; if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { return Z_STREAM_ERROR; } ss = source->state; *dest = *source; ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); if (ds == Z_NULL) return Z_MEM_ERROR; dest->state = (struct internal_state FAR *) ds; *ds = *ss; ds->strm = dest; ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); ds->pending_buf = (uchf *) overlay; if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || ds->pending_buf == Z_NULL) { deflateEnd (dest); return Z_MEM_ERROR; } /* following zmemcpy do not work for 16-bit MSDOS */ zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; ds->l_desc.dyn_tree = ds->dyn_ltree; ds->d_desc.dyn_tree = ds->dyn_dtree; ds->bl_desc.dyn_tree = ds->bl_tree; return Z_OK; #endif } /* =========================================================================== * Read a new buffer from the current input stream, update the adler32 * and total number of bytes read. All deflate() input goes through * this function so some applications may wish to modify it to avoid * allocating a large strm->next_in buffer and copying from it. * (See also flush_pending()). */ local int read_buf(strm, buf, size) z_streamp strm; Bytef *buf; unsigned size; { unsigned len = strm->avail_in; if (len > size) len = size; if (len == 0) return 0; strm->avail_in -= len; if (!strm->state->noheader) { strm->adler = adler32(strm->adler, strm->next_in, len); } zmemcpy(buf, strm->next_in, len); strm->next_in += len; strm->total_in += len; return (int)len; } /* =========================================================================== * Initialize the "longest match" routines for a new zlib stream */ local void lm_init (s) deflate_state *s; { s->window_size = (ulg)2L*s->w_size; CLEAR_HASH(s); /* Set the default configuration parameters: */ s->max_lazy_match = configuration_table[s->level].max_lazy; s->good_match = configuration_table[s->level].good_length; s->nice_match = configuration_table[s->level].nice_length; s->max_chain_length = configuration_table[s->level].max_chain; s->strstart = 0; s->block_start = 0L; s->lookahead = 0; s->match_length = s->prev_length = MIN_MATCH-1; s->match_available = 0; s->ins_h = 0; #ifdef ASMV match_init(); /* initialize the asm code */ #endif } /* =========================================================================== * Set match_start to the longest match starting at the given string and * return its length. Matches shorter or equal to prev_length are discarded, * in which case the result is equal to prev_length and match_start is * garbage. * IN assertions: cur_match is the head of the hash chain for the current * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 * OUT assertion: the match length is not greater than s->lookahead. */ #ifndef ASMV /* For 80x86 and 680x0, an optimized version will be provided in match.asm or * match.S. The code will be functionally equivalent. */ #ifndef FASTEST local uInt longest_match(s, cur_match) deflate_state *s; IPos cur_match; /* current match */ { unsigned chain_length = s->max_chain_length;/* max hash chain length */ register Bytef *scan = s->window + s->strstart; /* current string */ register Bytef *match; /* matched string */ register int len; /* length of current match */ int best_len = s->prev_length; /* best match length so far */ int nice_match = s->nice_match; /* stop if match long enough */ IPos limit = s->strstart > (IPos)MAX_DIST(s) ? s->strstart - (IPos)MAX_DIST(s) : NIL; /* Stop when cur_match becomes <= limit. To simplify the code, * we prevent matches with the string of window index 0. */ Posf *prev = s->prev; uInt wmask = s->w_mask; #ifdef UNALIGNED_OK /* Compare two bytes at a time. Note: this is not always beneficial. * Try with and without -DUNALIGNED_OK to check. */ register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; register ush scan_start = *(ushf*)scan; register ush scan_end = *(ushf*)(scan+best_len-1); #else register Bytef *strend = s->window + s->strstart + MAX_MATCH; register Byte scan_end1 = scan[best_len-1]; register Byte scan_end = scan[best_len]; #endif /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. * It is easy to get rid of this optimization if necessary. */ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); /* Do not waste too much time if we already have a good match: */ if (s->prev_length >= s->good_match) { chain_length >>= 2; } /* Do not look for matches beyond the end of the input. This is necessary * to make deflate deterministic. */ if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); do { Assert(cur_match < s->strstart, "no future"); match = s->window + cur_match; /* Skip to next match if the match length cannot increase * or if the match length is less than 2: */ #if (defined(UNALIGNED_OK) && MAX_MATCH == 258) /* This code assumes sizeof(unsigned short) == 2. Do not use * UNALIGNED_OK if your compiler uses a different size. */ if (*(ushf*)(match+best_len-1) != scan_end || *(ushf*)match != scan_start) continue; /* It is not necessary to compare scan[2] and match[2] since they are * always equal when the other bytes match, given that the hash keys * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at * strstart+3, +5, ... up to strstart+257. We check for insufficient * lookahead only every 4th comparison; the 128th check will be made * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is * necessary to put more guard bytes at the end of the window, or * to check more often for insufficient lookahead. */ Assert(scan[2] == match[2], "scan[2]?"); scan++, match++; do { } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && *(ushf*)(scan+=2) == *(ushf*)(match+=2) && *(ushf*)(scan+=2) == *(ushf*)(match+=2) && *(ushf*)(scan+=2) == *(ushf*)(match+=2) && scan < strend); /* The funny "do {}" generates better code on most compilers */ /* Here, scan <= window+strstart+257 */ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); if (*scan == *match) scan++; len = (MAX_MATCH - 1) - (int)(strend-scan); scan = strend - (MAX_MATCH-1); #else /* UNALIGNED_OK */ if (match[best_len] != scan_end || match[best_len-1] != scan_end1 || *match != *scan || *++match != scan[1]) continue; /* The check at best_len-1 can be removed because it will be made * again later. (This heuristic is not always a win.) * It is not necessary to compare scan[2] and match[2] since they * are always equal when the other bytes match, given that * the hash keys are equal and that HASH_BITS >= 8. */ scan += 2, match++; Assert(*scan == *match, "match[2]?"); /* We check for insufficient lookahead only every 8th comparison; * the 256th check will be made at strstart+258. */ do { } while (*++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && scan < strend); Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); len = MAX_MATCH - (int)(strend - scan); scan = strend - MAX_MATCH; #endif /* UNALIGNED_OK */ if (len > best_len) { s->match_start = cur_match; best_len = len; if (len >= nice_match) break; #ifdef UNALIGNED_OK scan_end = *(ushf*)(scan+best_len-1); #else scan_end1 = scan[best_len-1]; scan_end = scan[best_len]; #endif } } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length != 0); if ((uInt)best_len <= s->lookahead) return (uInt)best_len; return s->lookahead; } #else /* FASTEST */ /* --------------------------------------------------------------------------- * Optimized version for level == 1 only */ local uInt longest_match(s, cur_match) deflate_state *s; IPos cur_match; /* current match */ { register Bytef *scan = s->window + s->strstart; /* current string */ register Bytef *match; /* matched string */ register int len; /* length of current match */ register Bytef *strend = s->window + s->strstart + MAX_MATCH; /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. * It is easy to get rid of this optimization if necessary. */ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); Assert(cur_match < s->strstart, "no future"); match = s->window + cur_match; /* Return failure if the match length is less than 2: */ if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; /* The check at best_len-1 can be removed because it will be made * again later. (This heuristic is not always a win.) * It is not necessary to compare scan[2] and match[2] since they * are always equal when the other bytes match, given that * the hash keys are equal and that HASH_BITS >= 8. */ scan += 2, match += 2; Assert(*scan == *match, "match[2]?"); /* We check for insufficient lookahead only every 8th comparison; * the 256th check will be made at strstart+258. */ do { } while (*++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && scan < strend); Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); len = MAX_MATCH - (int)(strend - scan); if (len < MIN_MATCH) return MIN_MATCH - 1; s->match_start = cur_match; return len <= s->lookahead ? len : s->lookahead; } #endif /* FASTEST */ #endif /* ASMV */ #if 0 /* =========================================================================== * Check that the match at match_start is indeed a match. */ local void check_match(s, start, match, length) deflate_state *s; IPos start, match; int length; { /* check that the match is indeed a match */ if (zmemcmp(s->window + match, s->window + start, length) != EQUAL) { fprintf(stderr, " start %u, match %u, length %d\n", start, match, length); do { fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); } while (--length != 0); z_error("invalid match"); } if (z_verbose > 1) { fprintf(stderr,"\\[%d,%d]", start-match, length); do { putc(s->window[start++], stderr); } while (--length != 0); } } #else # define check_match(s, start, match, length) #endif /* =========================================================================== * Fill the window when the lookahead becomes insufficient. * Updates strstart and lookahead. * * IN assertion: lookahead < MIN_LOOKAHEAD * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD * At least one byte has been read, or avail_in == 0; reads are * performed for at least two bytes (required for the zip translate_eol * option -- not supported here). */ local void fill_window(s) deflate_state *s; { register unsigned n, m; register Posf *p; unsigned more; /* Amount of free space at the end of the window. */ uInt wsize = s->w_size; do { more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); /* Deal with !@#$% 64K limit: */ if (more == 0 && s->strstart == 0 && s->lookahead == 0) { more = wsize; } else if (more == (unsigned)(-1)) { /* Very unlikely, but possible on 16 bit machine if strstart == 0 * and lookahead == 1 (input done one byte at time) */ more--; /* If the window is almost full and there is insufficient lookahead, * move the upper half to the lower one to make room in the upper half. */ } else if (s->strstart >= wsize+MAX_DIST(s)) { zmemcpy(s->window, s->window+wsize, (unsigned)wsize); s->match_start -= wsize; s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ s->block_start -= (long) wsize; /* Slide the hash table (could be avoided with 32 bit values at the expense of memory usage). We slide even when level == 0 to keep the hash table consistent if we switch back to level > 0 later. (Using level 0 permanently is not an optimal usage of zlib, so we don't care about this pathological case.) */ n = s->hash_size; p = &s->head[n]; do { m = *--p; *p = (Pos)(m >= wsize ? m-wsize : NIL); } while (--n); n = wsize; #ifndef FASTEST p = &s->prev[n]; do { m = *--p; *p = (Pos)(m >= wsize ? m-wsize : NIL); /* If n is not on any hash chain, prev[n] is garbage but * its value will never be used. */ } while (--n); #endif more += wsize; } if (s->strm->avail_in == 0) return; /* If there was no sliding: * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && * more == window_size - lookahead - strstart * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) * => more >= window_size - 2*WSIZE + 2 * In the BIG_MEM or MMAP case (not yet supported), * window_size == input_size + MIN_LOOKAHEAD && * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. * Otherwise, window_size == 2*WSIZE so more >= 2. * If there was sliding, more >= WSIZE. So in all cases, more >= 2. */ Assert(more >= 2, "more < 2"); n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); s->lookahead += n; /* Initialize the hash value now that we have some input: */ if (s->lookahead >= MIN_MATCH) { s->ins_h = s->window[s->strstart]; UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); #if MIN_MATCH != 3 Call UPDATE_HASH() MIN_MATCH-3 more times #endif } /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, * but this is not important since only literal bytes will be emitted. */ } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); } /* =========================================================================== * Flush the current block, with given end-of-file flag. * IN assertion: strstart is set to the end of the current match. */ #define FLUSH_BLOCK_ONLY(s, eof) { \ _tr_flush_block(s, (s->block_start >= 0L ? \ (charf *)&s->window[(unsigned)s->block_start] : \ (charf *)Z_NULL), \ (ulg)((long)s->strstart - s->block_start), \ (eof)); \ s->block_start = s->strstart; \ flush_pending(s->strm); \ Tracev((stderr,"[FLUSH]")); \ } /* Same but force premature exit if necessary. */ #define FLUSH_BLOCK(s, eof) { \ FLUSH_BLOCK_ONLY(s, eof); \ if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \ } /* =========================================================================== * Copy without compression as much as possible from the input stream, return * the current block state. * This function does not insert new strings in the dictionary since * uncompressible data is probably not useful. This function is used * only for the level=0 compression option. * NOTE: this function should be optimized to avoid extra copying from * window to pending_buf. */ local block_state deflate_stored(s, flush) deflate_state *s; int flush; { /* Stored blocks are limited to 0xffff bytes, pending_buf is limited * to pending_buf_size, and each stored block has a 5 byte header: */ ulg max_block_size = 0xffff; ulg max_start; if (max_block_size > s->pending_buf_size - 5) { max_block_size = s->pending_buf_size - 5; } /* Copy as much as possible from input to output: */ for (;;) { /* Fill the window as much as possible: */ if (s->lookahead <= 1) { Assert(s->strstart < s->w_size+MAX_DIST(s) || s->block_start >= (long)s->w_size, "slide too late"); fill_window(s); if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; if (s->lookahead == 0) break; /* flush the current block */ } Assert(s->block_start >= 0L, "block gone"); s->strstart += s->lookahead; s->lookahead = 0; /* Emit a stored block if pending_buf will be full: */ max_start = s->block_start + max_block_size; if (s->strstart == 0 || (ulg)s->strstart >= max_start) { /* strstart == 0 is possible when wraparound on 16-bit machine */ s->lookahead = (uInt)(s->strstart - max_start); s->strstart = (uInt)max_start; FLUSH_BLOCK(s, 0); } /* Flush if we may have to slide, otherwise block_start may become * negative and the data will be gone: */ if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { FLUSH_BLOCK(s, 0); } } FLUSH_BLOCK(s, flush == Z_FINISH); return flush == Z_FINISH ? finish_done : block_done; } /* =========================================================================== * Compress as much as possible from the input stream, return the current * block state. * This function does not perform lazy evaluation of matches and inserts * new strings in the dictionary only for unmatched strings or for short * matches. It is used only for the fast compression options. */ local block_state deflate_fast(s, flush) deflate_state *s; int flush; { IPos hash_head = NIL; /* head of the hash chain */ int bflush; /* set if current block must be flushed */ for (;;) { /* Make sure that we always have enough lookahead, except * at the end of the input file. We need MAX_MATCH bytes * for the next match, plus MIN_MATCH bytes to insert the * string following the next match. */ if (s->lookahead < MIN_LOOKAHEAD) { fill_window(s); if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { return need_more; } if (s->lookahead == 0) break; /* flush the current block */ } /* Insert the string window[strstart .. strstart+2] in the * dictionary, and set hash_head to the head of the hash chain: */ if (s->lookahead >= MIN_MATCH) { INSERT_STRING(s, s->strstart, hash_head); } /* Find the longest match, discarding those <= prev_length. * At this point we have always match_length < MIN_MATCH */ if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { /* To simplify the code, we prevent matches with the string * of window index 0 (in particular we have to avoid a match * of the string with itself at the start of the input file). */ if (s->strategy != Z_HUFFMAN_ONLY) { s->match_length = longest_match (s, hash_head); } /* longest_match() sets match_start */ } if (s->match_length >= MIN_MATCH) { check_match(s, s->strstart, s->match_start, s->match_length); _tr_tally_dist(s, s->strstart - s->match_start, s->match_length - MIN_MATCH, bflush); s->lookahead -= s->match_length; /* Insert new strings in the hash table only if the match length * is not too large. This saves time but degrades compression. */ #ifndef FASTEST if (s->match_length <= s->max_insert_length && s->lookahead >= MIN_MATCH) { s->match_length--; /* string at strstart already in hash table */ do { s->strstart++; INSERT_STRING(s, s->strstart, hash_head); /* strstart never exceeds WSIZE-MAX_MATCH, so there are * always MIN_MATCH bytes ahead. */ } while (--s->match_length != 0); s->strstart++; } else #endif { s->strstart += s->match_length; s->match_length = 0; s->ins_h = s->window[s->strstart]; UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); #if MIN_MATCH != 3 Call UPDATE_HASH() MIN_MATCH-3 more times #endif /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not * matter since it will be recomputed at next deflate call. */ } } else { /* No match, output a literal byte */ Tracevv((stderr,"%c", s->window[s->strstart])); _tr_tally_lit (s, s->window[s->strstart], bflush); s->lookahead--; s->strstart++; } if (bflush) FLUSH_BLOCK(s, 0); } FLUSH_BLOCK(s, flush == Z_FINISH); return flush == Z_FINISH ? finish_done : block_done; } /* =========================================================================== * Same as above, but achieves better compression. We use a lazy * evaluation for matches: a match is finally adopted only if there is * no better match at the next window position. */ local block_state deflate_slow(s, flush) deflate_state *s; int flush; { IPos hash_head = NIL; /* head of hash chain */ int bflush; /* set if current block must be flushed */ /* Process the input block. */ for (;;) { /* Make sure that we always have enough lookahead, except * at the end of the input file. We need MAX_MATCH bytes * for the next match, plus MIN_MATCH bytes to insert the * string following the next match. */ if (s->lookahead < MIN_LOOKAHEAD) { fill_window(s); if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { return need_more; } if (s->lookahead == 0) break; /* flush the current block */ } /* Insert the string window[strstart .. strstart+2] in the * dictionary, and set hash_head to the head of the hash chain: */ if (s->lookahead >= MIN_MATCH) { INSERT_STRING(s, s->strstart, hash_head); } /* Find the longest match, discarding those <= prev_length. */ s->prev_length = s->match_length, s->prev_match = s->match_start; s->match_length = MIN_MATCH-1; if (hash_head != NIL && s->prev_length < s->max_lazy_match && s->strstart - hash_head <= MAX_DIST(s)) { /* To simplify the code, we prevent matches with the string * of window index 0 (in particular we have to avoid a match * of the string with itself at the start of the input file). */ if (s->strategy != Z_HUFFMAN_ONLY) { s->match_length = longest_match (s, hash_head); } /* longest_match() sets match_start */ if (s->match_length <= 5 && (s->strategy == Z_FILTERED || (s->match_length == MIN_MATCH && s->strstart - s->match_start > TOO_FAR))) { /* If prev_match is also MIN_MATCH, match_start is garbage * but we will ignore the current match anyway. */ s->match_length = MIN_MATCH-1; } } /* If there was a match at the previous step and the current * match is not better, output the previous match: */ if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; /* Do not insert strings in hash table beyond this. */ check_match(s, s->strstart-1, s->prev_match, s->prev_length); _tr_tally_dist(s, s->strstart -1 - s->prev_match, s->prev_length - MIN_MATCH, bflush); /* Insert in hash table all strings up to the end of the match. * strstart-1 and strstart are already inserted. If there is not * enough lookahead, the last two strings are not inserted in * the hash table. */ s->lookahead -= s->prev_length-1; s->prev_length -= 2; do { if (++s->strstart <= max_insert) { INSERT_STRING(s, s->strstart, hash_head); } } while (--s->prev_length != 0); s->match_available = 0; s->match_length = MIN_MATCH-1; s->strstart++; if (bflush) FLUSH_BLOCK(s, 0); } else if (s->match_available) { /* If there was no match at the previous position, output a * single literal. If there was a match but the current match * is longer, truncate the previous match to a single literal. */ Tracevv((stderr,"%c", s->window[s->strstart-1])); _tr_tally_lit(s, s->window[s->strstart-1], bflush); if (bflush) { FLUSH_BLOCK_ONLY(s, 0); } s->strstart++; s->lookahead--; if (s->strm->avail_out == 0) return need_more; } else { /* There is no previous match to compare with, wait for * the next step to decide. */ s->match_available = 1; s->strstart++; s->lookahead--; } } Assert (flush != Z_NO_FLUSH, "no flush?"); if (s->match_available) { Tracevv((stderr,"%c", s->window[s->strstart-1])); _tr_tally_lit(s, s->window[s->strstart-1], bflush); s->match_available = 0; } FLUSH_BLOCK(s, flush == Z_FINISH); return flush == Z_FINISH ? finish_done : block_done; } libreswan-3.32/linux/net/ipsec/deflate.h000066400000000000000000000266061365625662500202660ustar00rootroot00000000000000/* deflate.h -- internal compression state * Copyright (C) 1995-2002 Jean-loup Gailly * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ /* @(#) $Id: deflate.h,v 1.5 2004/07/10 07:48:38 mcr Exp $ */ #ifndef _DEFLATE_H #define _DEFLATE_H #include "zlib/zutil.h" /* =========================================================================== * Internal compression state. */ #define LENGTH_CODES 29 /* number of length codes, not counting the special END_BLOCK code */ #define LITERALS 256 /* number of literal bytes 0..255 */ #define L_CODES (LITERALS+1+LENGTH_CODES) /* number of Literal or Length codes, including the END_BLOCK code */ #define D_CODES 30 /* number of distance codes */ #define BL_CODES 19 /* number of codes used to transfer the bit lengths */ #define HEAP_SIZE (2*L_CODES+1) /* maximum heap size */ #define MAX_BITS 15 /* All codes must not exceed MAX_BITS bits */ #define INIT_STATE 42 #define BUSY_STATE 113 #define FINISH_STATE 666 /* Stream status */ /* Data structure describing a single value and its code string. */ typedef struct ct_data_s { union { ush freq; /* frequency count */ ush code; /* bit string */ } fc; union { ush dad; /* father node in Huffman tree */ ush len; /* length of bit string */ } dl; } FAR ct_data; #define Freq fc.freq #define Code fc.code #define Dad dl.dad #define Len dl.len typedef struct static_tree_desc_s static_tree_desc; typedef struct tree_desc_s { ct_data *dyn_tree; /* the dynamic tree */ int max_code; /* largest code with non zero frequency */ static_tree_desc *stat_desc; /* the corresponding static tree */ } FAR tree_desc; typedef ush Pos; typedef Pos FAR Posf; typedef unsigned IPos; /* A Pos is an index in the character window. We use short instead of int to * save space in the various tables. IPos is used only for parameter passing. */ typedef struct internal_state { z_streamp strm; /* pointer back to this zlib stream */ int status; /* as the name implies */ Bytef *pending_buf; /* output still pending */ ulg pending_buf_size; /* size of pending_buf */ Bytef *pending_out; /* next pending byte to output to the stream */ int pending; /* nb of bytes in the pending buffer */ int noheader; /* suppress zlib header and adler32 */ Byte data_type; /* UNKNOWN, BINARY or ASCII */ Byte method; /* STORED (for zip only) or DEFLATED */ int last_flush; /* value of flush param for previous deflate call */ /* used by deflate.c: */ uInt w_size; /* LZ77 window size (32K by default) */ uInt w_bits; /* log2(w_size) (8..16) */ uInt w_mask; /* w_size - 1 */ Bytef *window; /* Sliding window. Input bytes are read into the second half of the window, * and move to the first half later to keep a dictionary of at least wSize * bytes. With this organization, matches are limited to a distance of * wSize-MAX_MATCH bytes, but this ensures that IO is always * performed with a length multiple of the block size. Also, it limits * the window size to 64K, which is quite useful on MSDOS. * To do: use the user input buffer as sliding window. */ ulg window_size; /* Actual size of window: 2*wSize, except when the user input buffer * is directly used as sliding window. */ Posf *prev; /* Link to older string with same hash index. To limit the size of this * array to 64K, this link is maintained only for the last 32K strings. * An index in this array is thus a window index modulo 32K. */ Posf *head; /* Heads of the hash chains or NIL. */ uInt ins_h; /* hash index of string to be inserted */ uInt hash_size; /* number of elements in hash table */ uInt hash_bits; /* log2(hash_size) */ uInt hash_mask; /* hash_size-1 */ uInt hash_shift; /* Number of bits by which ins_h must be shifted at each input * step. It must be such that after MIN_MATCH steps, the oldest * byte no longer takes part in the hash key, that is: * hash_shift * MIN_MATCH >= hash_bits */ long block_start; /* Window position at the beginning of the current output block. Gets * negative when the window is moved backwards. */ uInt match_length; /* length of best match */ IPos prev_match; /* previous match */ int match_available; /* set if previous match exists */ uInt strstart; /* start of string to insert */ uInt match_start; /* start of matching string */ uInt lookahead; /* number of valid bytes ahead in window */ uInt prev_length; /* Length of the best match at previous step. Matches not greater than this * are discarded. This is used in the lazy match evaluation. */ uInt max_chain_length; /* To speed up deflation, hash chains are never searched beyond this * length. A higher limit improves compression ratio but degrades the * speed. */ uInt max_lazy_match; /* Attempt to find a better match only when the current match is strictly * smaller than this value. This mechanism is used only for compression * levels >= 4. */ # define max_insert_length max_lazy_match /* Insert new strings in the hash table only if the match length is not * greater than this length. This saves time but degrades compression. * max_insert_length is used only for compression levels <= 3. */ int level; /* compression level (1..9) */ int strategy; /* favor or force Huffman coding*/ uInt good_match; /* Use a faster search when the previous match is longer than this */ int nice_match; /* Stop searching when current match exceeds this */ /* used by trees.c: */ /* Didn't use ct_data typedef below to suppress compiler warning */ struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ struct tree_desc_s l_desc; /* desc. for literal tree */ struct tree_desc_s d_desc; /* desc. for distance tree */ struct tree_desc_s bl_desc; /* desc. for bit length tree */ ush bl_count[MAX_BITS+1]; /* number of codes at each bit length for an optimal tree */ int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ int heap_len; /* number of elements in the heap */ int heap_max; /* element of largest frequency */ /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. * The same heap array is used to build all trees. */ uch depth[2*L_CODES+1]; /* Depth of each subtree used as tie breaker for trees of equal frequency */ uchf *l_buf; /* buffer for literals or lengths */ uInt lit_bufsize; /* Size of match buffer for literals/lengths. There are 4 reasons for * limiting lit_bufsize to 64K: * - frequencies can be kept in 16 bit counters * - if compression is not successful for the first block, all input * data is still in the window so we can still emit a stored block even * when input comes from standard input. (This can also be done for * all blocks if lit_bufsize is not greater than 32K.) * - if compression is not successful for a file smaller than 64K, we can * even emit a stored file instead of a stored block (saving 5 bytes). * This is applicable only for zip (not gzip or zlib). * - creating new Huffman trees less frequently may not provide fast * adaptation to changes in the input data statistics. (Take for * example a binary file with poorly compressible code followed by * a highly compressible string table.) Smaller buffer sizes give * fast adaptation but have of course the overhead of transmitting * trees more frequently. * - I can't count above 4 */ uInt last_lit; /* running index in l_buf */ ushf *d_buf; /* Buffer for distances. To simplify the code, d_buf and l_buf have * the same number of elements. To use different lengths, an extra flag * array would be necessary. */ ulg opt_len; /* bit length of current block with optimal trees */ ulg static_len; /* bit length of current block with static trees */ uInt matches; /* number of string matches in current block */ int last_eob_len; /* bit length of EOB code for last block */ ulg compressed_len; /* total bit length of compressed file mod 2^32 */ ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ ush bi_buf; /* Output buffer. bits are inserted starting at the bottom (least * significant bits). */ int bi_valid; /* Number of valid bits in bi_buf. All bits above the last valid bit * are always zero. */ } FAR deflate_state; /* Output a byte on the stream. * IN assertion: there is enough room in pending_buf. */ #define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} #define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) /* Minimum amount of lookahead, except at the end of the input file. * See deflate.c for comments about the MIN_MATCH+1. */ #define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) /* In order to simplify the code, particularly on 16 bit machines, match * distances are limited to MAX_DIST instead of WSIZE. */ /* in trees.c */ void _tr_init OF((deflate_state *s)); int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, int eof)); void _tr_align OF((deflate_state *s)); void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, int eof)); #define d_code(dist) \ ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) /* Mapping from a distance to a distance code. dist is the distance - 1 and * must not have side effects. _dist_code[256] and _dist_code[257] are never * used. */ #ifndef DEBUG /* Inline versions of _tr_tally for speed: */ #if defined(GEN_TREES_H) || !defined(STDC) extern uch _length_code[]; extern uch _dist_code[]; #else extern const uch _length_code[]; extern const uch _dist_code[]; #endif # define _tr_tally_lit(s, c, flush) \ { uch cc = (c); \ s->d_buf[s->last_lit] = 0; \ s->l_buf[s->last_lit++] = cc; \ s->dyn_ltree[cc].Freq++; \ flush = (s->last_lit == s->lit_bufsize-1); \ } # define _tr_tally_dist(s, distance, length, flush) \ { uch len = (length); \ ush dist = (distance); \ s->d_buf[s->last_lit] = dist; \ s->l_buf[s->last_lit++] = len; \ dist--; \ s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ s->dyn_dtree[d_code(dist)].Freq++; \ flush = (s->last_lit == s->lit_bufsize-1); \ } #else # define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) # define _tr_tally_dist(s, distance, length, flush) \ flush = _tr_tally(s, distance, length) #endif #endif /* _DEFLATE_H */ libreswan-3.32/linux/net/ipsec/des/000077500000000000000000000000001365625662500172525ustar00rootroot00000000000000libreswan-3.32/linux/net/ipsec/des/COPYRIGHT000066400000000000000000000051331365625662500205470ustar00rootroot00000000000000Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) All rights reserved. This package is an DES implementation written by Eric Young (eay@cryptsoft.com). The implementation was written so as to conform with MIT's libdes. This library is free for commercial and non-commercial use as long as the following conditions are adhered to. The following conditions apply to all code found in this distribution. Copyright remains Eric Young's, and as such any Copyright notices in the code are not to be removed. If this package is used in a product, Eric Young should be given attribution as the author of that the SSL library. This can be in the form of a textual message at program startup or in documentation (online or textual) provided with the package. 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 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. All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by Eric Young (eay@cryptsoft.com) THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The license and distribution terms for any publically available version or derivative of this code cannot be changed. i.e. this code cannot simply be copied and put under another distrubution license [including the GNU Public License.] The reason behind this being stated in this direct manner is past experience in code simply being copied and the attribution removed from it and then being distributed as part of other packages. This implementation was a non-trivial and unpaid effort. libreswan-3.32/linux/net/ipsec/des/INSTALL000066400000000000000000000053641365625662500203130ustar00rootroot00000000000000Check the CC and CFLAGS lines in the makefile If your C library does not support the times(3) function, change the #define TIMES to #undef TIMES in speed.c If it does, check the HZ value for the times(3) function. If your system does not define CLK_TCK it will be assumed to be 100.0. If possible use gcc v 2.7.? Turn on the maximum optimising (normally '-O3 -fomit-frame-pointer' for gcc) In recent times, some system compilers give better performance. type 'make' run './destest' to check things are ok. run './rpw' to check the tty code for reading passwords works. run './speed' to see how fast those optimisations make the library run :-) run './des_opts' to determine the best compile time options. The output from des_opts should be put in the makefile options and des_enc.c should be rebuilt. For 64 bit computers, do not use the DES_PTR option. For the DEC Alpha, edit des.h and change DES_LONG to 'unsigned int' and then you can use the 'DES_PTR' option. The file options.txt has the options listed for best speed on quite a few systems. Look and the options (UNROLL, PTR, RISC2 etc) and then turn on the relevant option in the Makefile There are some special Makefile targets that make life easier. make cc - standard cc build make gcc - standard gcc build make x86-elf - x86 assembler (elf), linux-elf. make x86-out - x86 assembler (a.out), FreeBSD make x86-solaris- x86 assembler make x86-bsdi - x86 assembler (a.out with primitive assembler). If at all possible use the assembler (for Windows NT/95, use asm/win32.obj to link with). The x86 assembler is very very fast. A make install will by default install libdes.a in /usr/local/lib/libdes.a des in /usr/local/bin/des des_crypt.man in /usr/local/man/man3/des_crypt.3 des.man in /usr/local/man/man1/des.1 des.h in /usr/include/des.h des(1) should be compatible with sunOS's but I have been unable to test it. These routines should compile on MSDOS, most 32bit and 64bit version of Unix (BSD and SYSV) and VMS, without modification. The only problems should be #include files that are in the wrong places. These routines can be compiled under MSDOS. I have successfully encrypted files using des(1) under MSDOS and then decrypted the files on a SparcStation. I have been able to compile and test the routines with Microsoft C v 5.1 and Turbo C v 2.0. The code in this library is in no way optimised for the 16bit operation of MSDOS. When building for glibc, ignore all of the above and just unpack into glibc-1.??/des and then gmake as per normal. As a final note on performance. Certain CPUs like sparcs and Alpha often give a %10 speed difference depending on the link order. It is rather annoying when one program reports 'x' DES encrypts a second and another reports 'x*0.9' the speed. libreswan-3.32/linux/net/ipsec/des/Makefile.fs2_6000066400000000000000000000035201365625662500216300ustar00rootroot00000000000000# Makefile for KLIPS kernel code as a module for 2.6 kernels # # Makefile for KLIPS kernel code as a module # Copyright (C) 1998, 1999, 2000,2001 Richard Guy Briggs. # Copyright (C) 2002-2004 Michael Richardson # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # # Note! Dependencies are done automagically by 'make dep', which also # removes any old dependencies. DON'T put your own dependencies here # unless it's something special (ie not a .c file). # obj-$(CONFIG_KLIPS_ENC_3DES) += ipsec_alg_3des.o obj-$(CONFIG_KLIPS_ENC_3DES) += cbc_enc.o obj-$(CONFIG_KLIPS_ENC_3DES) += ecb_enc.o obj-$(CONFIG_KLIPS_ENC_3DES) += set_key.o ifeq ($(strip ${SUBARCH}),) SUBARCH:=${ARCH} endif # The assembly version is incompatible with CONFIG_REGPARM=y The # CONFIG_REGPARM defines whether it uses registers or stack to pass # arguments and recent kernels (after 2.6.17 or 2.6.18) uses registers # unconditionally. Therefore, we disable the assembly version for ix86's # completely. # # # the assembly version expects frame pointers, which are # optional in many kernel builds. If you want speed, you should # probably use cryptoapi code instead. #USEASSEMBLY=${SUBARCH}${CONFIG_FRAME_POINTER} #ifeq (${USEASSEMBLY},i386y) #obj-$(CONFIG_KLIPS_ENC_3DES) += dx86unix.o #else #obj-$(CONFIG_KLIPS_ENC_3DES) += des_enc.o #endif obj-$(CONFIG_KLIPS_ENC_3DES) += des_enc.o libreswan-3.32/linux/net/ipsec/des/README000066400000000000000000000043071365625662500201360ustar00rootroot00000000000000 libdes, Version 4.01 10-Jan-97 Copyright (c) 1997, Eric Young All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms specified in COPYRIGHT. -- The primary ftp site for this library is ftp://ftp.psy.uq.oz.au/pub/Crypto/DES/libdes-x.xx.tar.gz libdes is now also shipped with SSLeay. Primary ftp site of ftp://ftp.psy.uq.oz.au/pub/Crypto/SSL/SSLeay-x.x.x.tar.gz The best way to build this library is to build it as part of SSLeay. This kit builds a DES encryption library and a DES encryption program. It supports ecb, cbc, ofb, cfb, triple ecb, triple cbc, triple ofb, triple cfb, desx, and MIT's pcbc encryption modes and also has a fast implementation of crypt(3). It contains support routines to read keys from a terminal, generate a random key, generate a key from an arbitrary length string, read/write encrypted data from/to a file descriptor. The implementation was written so as to conform with the manual entry for the des_crypt(3) library routines from MIT's project Athena. destest should be run after compilation to test the des routines. rpw should be run after compilation to test the read password routines. The des program is a replacement for the sun des command. I believe it conforms to the sun version. The Imakefile is setup for use in the kerberos distribution. These routines are best compiled with gcc or any other good optimising compiler. Just turn you optimiser up to the highest settings and run destest after the build to make sure everything works. I believe these routines are close to the fastest and most portable DES routines that use small lookup tables (4.5k) that are publicly available. The fcrypt routine is faster than ufc's fcrypt (when compiling with gcc2 -O2) on the sparc 2 (1410 vs 1270) but is not so good on other machines (on a sun3/260 168 vs 336). It is a function of CPU on chip cache size. [ 10-Jan-97 and a function of an incorrect speed testing program in ufc which gave much better test figures that reality ]. It is worth noting that on sparc and Alpha CPUs, performance of the DES library can vary by up to %10 due to the positioning of files after application linkage. Eric Young (eay@cryptsoft.com) libreswan-3.32/linux/net/ipsec/des/README.freeswan000066400000000000000000000025451365625662500217510ustar00rootroot00000000000000The only changes the FreeS/WAN project has made to libdes-lite 4.04b are: We #ifdef-ed the declaration of DES_LONG in des.h, so it's more efficient on the Alpha, instead of just noting the issue in a comment. We #ifdef-ed out the des_options() function in ecb_enc.c, because we don't use it, and its call to sprintf() can cause subtle difficulties when KLIPS is built as a module (depending on details of Linux configuration options). We changed some instances of CC=$(CC) in the Makefile to CC='$(CC)' to make it cope better with Linux kernel Makefile stupidities, and took out an explicit CC=gcc (unwise on systems with strange compilers). We deleted some references to and , and a declaration of one function found only in the full libdes (not in libdes-lite), to avoid dragging in bits of stdio/stdlib unnecessarily. (Our thanks to Hans Schultz for spotting this and pointing out the fixes.) We deleted a couple of .obj files in the asm subdirectory, which appear to have been included in the original library by accident. We have added an include of our Makefile.inc file, to permit overriding things like choice of compiler (although the libdes Makefile would probably need some work to make this effective). Note that Eric Young is no longer at the email address listed in these files, and is (alas) no longer working on free crypto software. libreswan-3.32/linux/net/ipsec/des/VERSION000066400000000000000000000370741365625662500203350ustar00rootroot00000000000000Version 4.04 Fixed a few tests in destest. Also added x86 assembler for des_ncbc_encrypt() which is the standard cbc mode function. This makes a very very large performance difference. Ariel Glenn ariel@columbia.edu reports that the terminal 'turn echo off' can return (errno == EINVAL) under solaris when redirection is used. So I now catch that as well as ENOTTY. Version 4.03 Left a static out of enc_write.c, which caused to buffer to be continuously malloc()ed. Does anyone use these functions? I keep on feeling like removing them since I only had these in there for a version of kerberised login. Anyway, this was pointed out by Theo de Raadt The 'n' bit ofb code was wrong, it was not shifting the shift register. It worked correctly for n == 64. Thanks to Gigi Ankeny for pointing this one out. Version 4.02 I was doing 'if (memcmp(weak_keys[i],key,sizeof(key)) == 0)' when checking for weak keys which is wrong :-(, pointed out by Markus F.X.J. Oberhumer . Version 4.01 Even faster inner loop in the DES assembler for x86 and a modification for IP/FP which is faster on x86. Both of these changes are from Svend Olaf Mikkelsen . His changes make the assembler run %40 faster on a pentium. This is just a case of getting the instruction sequence 'just right'. All credit to 'Svend' :-) Quite a few special x86 'make' targets. A libdes-l (lite) distribution. Version 4.00 After a bit of a pause, I'll up the major version number since this is mostly a performance release. I've added x86 assembler and added more options for performance. A %28 speedup for gcc on a pentium and the assembler is a %50 speedup. MIPS CPU's, sparc and Alpha are the main CPU's with speedups. Run des_opts to work out which options should be used. DES_RISC1/DES_RISC2 use alternative inner loops which use more registers but should give speedups on any CPU that does dual issue (pentium). DES_UNROLL unrolls the inner loop, which costs in code size. Version 3.26 I've finally removed one of the shifts in D_ENCRYPT. This meant I've changed the des_SPtrans table (spr.h), the set_key() function and some things in des_enc.c. This has definitely made things faster :-). I've known about this one for some time but I've been too lazy to follow it up :-). Noticed that in the D_ENCRYPT() macro, we can just do L^=(..)^(..)^.. instead of L^=((..)|(..)|(..).. This should save a register at least. Assembler for x86. The file to replace is des_enc.c, which is replaced by one of the assembler files found in asm. Look at des/asm/readme for more info. /* Modification to fcrypt so it can be compiled to support HPUX 10.x's long password format, define -DLONGCRYPT to use this. Thanks to Jens Kupferschmidt . */ SIGWINCH case put in des_read_passwd() so the function does not 'exit' if this function is received. Version 3.25 17/07/96 Modified read_pwd.c so that stdin can be read if not a tty. Thanks to Jeff Barber for the patches. des_init_random_number_generator() shortened due to VMS linker limits. Added RSA's DESX cbc mode. It is a form of cbc encryption, with 2 8 byte quantites xored before and after encryption. des_xcbc_encryption() - the name is funny to preserve the des_ prefix on all functions. Version 3.24 20/04/96 The DES_PTR macro option checked and used by SSLeay configuration Version 3.23 11/04/96 Added DES_LONG. If defined to 'unsigned int' on the DEC Alpha, it gives a %20 speedup :-) Fixed the problem with des.pl under perl5. The patches were sent by Ed Kubaitis (ejk@uiuc.edu). if fcrypt.c, changed values to handle illegal salt values the way normal crypt() implementations do. Some programs apparently use them :-(. The patch was sent by Bjorn Gronvall Version 3.22 29/11/95 Bug in des(1), an error with the uuencoding stuff when the 'data' is small, thanks to Geoff Keating for the patch. Version 3.21 22/11/95 After some emailing back and forth with Colin Plumb , I've tweaked a few things and in a future version I will probably put in some of the optimisation he suggested for use with the DES_USE_PTR option. Extra routines from Mark Murray for use in freeBSD. They mostly involve random number generation for use with kerberos. They involve evil machine specific system calls etc so I would normally suggest pushing this stuff into the application and/or using RAND_seed()/RAND_bytes() if you are using this DES library as part of SSLeay. Redone the read_pw() function so that it is cleaner and supports termios, thanks to Sameer Parekh for the initial patches for this. Renamed 3ecb_encrypt() to ecb3_encrypt(). This has been done just to make things more consistent. I have also now added triple DES versions of cfb and ofb. Version 3.20 Damn, Damn, Damn, as pointed out by Mike_Spreitzer.PARC@xerox.com, my des_random_seed() function was only copying 4 bytes of the passed seed into the init structure. It is now fixed to copy 8. My own suggestion is to used something like MD5 :-) Version 3.19 While looking at my code one day, I though, why do I keep on calling des_encrypt(in,out,ks,enc) when every function that calls it has in and out the same. So I dropped the 'out' parameter, people should not be using this function. Version 3.18 30/08/95 Fixed a few bit with the distribution and the filenames. 3.17 had been munged via a move to DOS and back again. NO CODE CHANGES Version 3.17 14/07/95 Fixed ede3 cbc which I had broken in 3.16. I have also removed some unneeded variables in 7-8 of the routines. Version 3.16 26/06/95 Added des_encrypt2() which does not use IP/FP, used by triple des routines. Tweaked things a bit elsewhere. %13 speedup on sparc and %6 on a R4400 for ede3 cbc mode. Version 3.15 06/06/95 Added des_ncbc_encrypt(), it is des_cbc mode except that it is 'normal' and copies the new iv value back over the top of the passed parameter. CHANGED des_ede3_cbc_encrypt() so that it too now overwrites the iv. THIS WILL BREAK EXISTING CODE, but since this function only new, I feel I can change it, not so with des_cbc_encrypt :-(. I need to update the documentation. Version 3.14 31/05/95 New release upon the world, as part of my SSL implementation. New copyright and usage stuff. Basically free for all to use as long as you say it came from me :-) Version 3.13 31/05/95 A fix in speed.c, if HZ is not defined, I set it to 100.0 which is reasonable for most unixes except SunOS 4.x. I now have a #ifdef sun but timing for SunOS 4.x looked very good :-(. At my last job where I used SunOS 4.x, it was defined to be 60.0 (look at the old INSTALL documentation), at the last release had it changed to 100.0 since I now work with Solaris2 and SVR4 boxes. Thanks to Rory Chisholm for pointing this one out. Version 3.12 08/05/95 As pointed out by The Crypt Keeper , my D_ENCRYPT macro in crypt() had an un-necessary variable. It has been removed. Version 3.11 03/05/95 Added des_ede3_cbc_encrypt() which is cbc mode des with 3 keys and one iv. It is a standard and I needed it for my SSL code. It makes more sense to use this for triple DES than 3cbc_encrypt(). I have also added (or should I say tested :-) cfb64_encrypt() which is cfb64 but it will encrypt a partial number of bytes - 3 bytes in 3 bytes out. Again this is for my SSL library, as a form of encryption to use with SSL telnet. Version 3.10 22/03/95 Fixed a bug in 3cbc_encrypt() :-(. When making repeated calls to cbc3_encrypt, the 2 iv values that were being returned to be used in the next call were reversed :-(. Many thanks to Bill Wade for pointing out this error. Version 3.09 01/02/95 Fixed des_random_key to far more random, it was rather feeble with regards to picking the initial seed. The problem was pointed out by Olaf Kirch . Version 3.08 14/12/94 Added Makefile.PL so libdes can be built into perl5. Changed des_locl.h so RAND is always defined. Version 3.07 05/12/94 Added GNUmake and stuff so the library can be build with glibc. Version 3.06 30/08/94 Added rpc_enc.c which contains _des_crypt. This is for use in secure_rpc v 4.0 Finally fixed the cfb_enc problems. Fixed a few parameter parsing bugs in des (-3 and -b), thanks to Rob McMillan Version 3.05 21/04/94 for unsigned long l; gcc does not produce ((l>>34) == 0) This causes bugs in cfb_enc. Thanks to Hadmut Danisch Version 3.04 20/04/94 Added a version number to des.c and libdes.a Version 3.03 12/01/94 Fixed a bug in non zero iv in 3cbc_enc. Version 3.02 29/10/93 I now work in a place where there are 6+ architectures and 14+ OS versions :-). Fixed TERMIO definition so the most sys V boxes will work :-) Release upon comp.sources.misc Version 3.01 08/10/93 Added des_3cbc_encrypt() Version 3.00 07/10/93 Fixed up documentation. quad_cksum definitely compatible with MIT's now. Version 2.30 24/08/93 Triple DES now defaults to triple cbc but can do triple ecb with the -b flag. Fixed some MSDOS uuen/uudecoding problems, thanks to Added prototypes. Version 2.22 29/06/93 Fixed a bug in des_is_weak_key() which stopped it working :-( thanks to engineering@MorningStar.Com. Version 2.21 03/06/93 des(1) with no arguments gives quite a bit of help. Added -c (generate ckecksum) flag to des(1). Added -3 (triple DES) flag to des(1). Added cfb and ofb routines to the library. Version 2.20 11/03/93 Added -u (uuencode) flag to des(1). I have been playing with byte order in quad_cksum to make it compatible with MIT's version. All I can say is avid this function if possible since MIT's output is endian dependent. Version 2.12 14/10/92 Added MSDOS specific macro in ecb_encrypt which gives a %70 speed up when the code is compiled with turbo C. Version 2.11 12/10/92 Speedup in set_key (recoding of PC-1) I now do it in 47 simple operations, down from 60. Thanks to John Fletcher (john_fletcher@lccmail.ocf.llnl.gov) for motivating me to look for a faster system :-) The speedup is probably less that 1% but it is still 13 instructions less :-). Version 2.10 06/10/92 The code now works on the 64bit ETA10 and CRAY without modifications or #defines. I believe the code should work on any machine that defines long, int or short to be 8 bytes long. Thanks to Shabbir J. Safdar (shabby@mentor.cc.purdue.edu) for helping me fix the code to run on 64bit machines (he had access to an ETA10). Thanks also to John Fletcher for testing the routines on a CRAY. read_password.c has been renamed to read_passwd.c string_to_key.c has been renamed to string2key.c Version 2.00 14/09/92 Made mods so that the library should work on 64bit CPU's. Removed all my uchar and ulong defs. To many different versions of unix define them in their header files in too many different combinations :-) IRIX - Sillicon Graphics mods (mostly in read_password.c). Thanks to Andrew Daviel (advax@erich.triumf.ca) Version 1.99 26/08/92 Fixed a bug or 2 in enc_read.c Fixed a bug in enc_write.c Fixed a pseudo bug in fcrypt.c (very obscure). Version 1.98 31/07/92 Support for the ETA10. This is a strange machine that defines longs and ints as 8 bytes and shorts as 4 bytes. Since I do evil things with long * that assume that they are 4 bytes. Look in the Makefile for the option to compile for this machine. quad_cksum appears to have problems but I will don't have the time to fix it right now, and this is not a function that uses DES and so will not effect the main uses of the library. Version 1.97 20/05/92 eay Fixed the Imakefile and made some changes to des.h to fix some problems when building this package with Kerberos v 4. Version 1.96 18/05/92 eay Fixed a small bug in string_to_key() where problems could occur if des_check_key was set to true and the string generated a weak key. Patch2 posted to comp.sources.misc Version 1.95 13/05/92 eay Added an alternative version of the D_ENCRYPT macro in ecb_encrypt and fcrypt. Depending on the compiler, one version or the other will be faster. This was inspired by Dana How , and her pointers about doing the *(ulong *)((uchar *)ptr+(value&0xfc)) vs ptr[value&0x3f] to stop the C compiler doing a <<2 to convert the long array index. Version 1.94 05/05/92 eay Fixed an incompatibility between my string_to_key and the MIT version. When the key is longer than 8 chars, I was wrapping with a different method. To use the old version, define OLD_STR_TO_KEY in the makefile. Thanks to viktor@newsu.shearson.com (Viktor Dukhovni). Version 1.93 28/04/92 eay Fixed the VMS mods so that echo is now turned off in read_password. Thanks again to brennan@coco.cchs.su.oz.AU. MSDOS support added. The routines can be compiled with Turbo C (v2.0) and MSC (v5.1). Make sure MSDOS is defined. Patch1 posted to comp.sources.misc Version 1.92 13/04/92 eay Changed D_ENCRYPT so that the rotation of R occurs outside of the loop. This required rotating all the longs in sp.h (now called spr.h). Thanks to Richard Outerbridge <71755.204@CompuServe.COM> speed.c has been changed so it will work without SIGALRM. If times(3) is not present it will try to use ftime() instead. Version 1.91 08/04/92 eay Added -E/-D options to des(1) so it can use string_to_key. Added SVR4 mods suggested by witr@rwwa.COM Added VMS mods suggested by brennan@coco.cchs.su.oz.AU. If anyone knows how to turn of tty echo in VMS please tell me or implement it yourself :-). Changed FILE *IN/*OUT to *DES_IN/*DES_OUT since it appears VMS does not like IN/OUT being used. Libdes posted to comp.sources.misc Version 1.9 24/03/92 eay Now contains a fast small crypt replacement. Added des(1) command. Added des_rw_mode so people can use cbc encryption with enc_read and enc_write. Version 1.8 15/10/91 eay Bug in cbc_cksum. Many thanks to Keith Reynolds (keithr@sco.COM) for pointing this one out. Version 1.7 24/09/91 eay Fixed set_key :-) set_key is 4 times faster and takes less space. There are a few minor changes that could be made. Version 1.6 19/09/1991 eay Finally go IP and FP finished. Now I need to fix set_key. This version is quite a bit faster that 1.51 Version 1.52 15/06/1991 eay 20% speedup in ecb_encrypt by changing the E bit selection to use 2 32bit words. This also required modification of the sp table. There is still a way to speedup the IP and IP-1 (hints from outer@sq.com) still working on this one :-(. Version 1.51 07/06/1991 eay Faster des_encrypt by loop unrolling Fixed bug in quad_cksum.c (thanks to hughes@logos.ucs.indiana.edu) Version 1.50 28/05/1991 eay Optimised the code a bit more for the sparc. I have improved the speed of the inner des_encrypt by speeding up the initial and final permutations. Version 1.40 23/10/1990 eay Fixed des_random_key, it did not produce a random key :-( Version 1.30 2/10/1990 eay Have made des_quad_cksum the same as MIT's, the full package should be compatible with MIT's Have tested on a DECstation 3100 Still need to fix des_set_key (make it faster). Does des_cbc_encrypts at 70.5k/sec on a 3100. Version 1.20 18/09/1990 eay Fixed byte order dependencies. Fixed (I hope) all the word alignment problems. Speedup in des_ecb_encrypt. Version 1.10 11/09/1990 eay Added des_enc_read and des_enc_write. Still need to fix des_quad_cksum. Still need to document des_enc_read and des_enc_write. Version 1.00 27/08/1990 eay libreswan-3.32/linux/net/ipsec/des/asm/000077500000000000000000000000001365625662500200325ustar00rootroot00000000000000libreswan-3.32/linux/net/ipsec/des/asm/des-586.pl000077500000000000000000000116111365625662500214650ustar00rootroot00000000000000#!/usr/bin/perl # # The inner loop instruction sequence and the IP/FP modifications are from # Svend Olaf Mikkelsen # push(@INC,"perlasm","../../perlasm"); require "x86asm.pl"; require "cbc.pl"; require "desboth.pl"; # base code is in microsft # op dest, source # format. # &asm_init($ARGV[0],"des-586.pl"); $L="edi"; $R="esi"; &external_label("des_SPtrans"); &des_encrypt("des_encrypt",1); &des_encrypt("des_encrypt2",0); &des_encrypt3("des_encrypt3",1); &des_encrypt3("des_decrypt3",0); &cbc("des_ncbc_encrypt","des_encrypt","des_encrypt",0,4,5,3,5,-1); &cbc("des_ede3_cbc_encrypt","des_encrypt3","des_decrypt3",0,6,7,3,4,5); &asm_finish(); sub des_encrypt { local($name,$do_ip)=@_; &function_begin_B($name,"EXTRN _des_SPtrans:DWORD"); &push("esi"); &push("edi"); &comment(""); &comment("Load the 2 words"); $ks="ebp"; if ($do_ip) { &mov($R,&wparam(0)); &xor( "ecx", "ecx" ); &push("ebx"); &push("ebp"); &mov("eax",&DWP(0,$R,"",0)); &mov("ebx",&wparam(2)); # get encrypt flag &mov($L,&DWP(4,$R,"",0)); &comment(""); &comment("IP"); &IP_new("eax",$L,$R,3); } else { &mov("eax",&wparam(0)); &xor( "ecx", "ecx" ); &push("ebx"); &push("ebp"); &mov($R,&DWP(0,"eax","",0)); &mov("ebx",&wparam(2)); # get encrypt flag &rotl($R,3); &mov($L,&DWP(4,"eax","",0)); &rotl($L,3); } &mov( $ks, &wparam(1) ); &cmp("ebx","0"); &je(&label("start_decrypt")); for ($i=0; $i<16; $i+=2) { &comment(""); &comment("Round $i"); &D_ENCRYPT($i,$L,$R,$i*2,$ks,"des_SPtrans","eax","ebx","ecx","edx"); &comment(""); &comment("Round ".sprintf("%d",$i+1)); &D_ENCRYPT($i+1,$R,$L,($i+1)*2,$ks,"des_SPtrans","eax","ebx","ecx","edx"); } &jmp(&label("end")); &set_label("start_decrypt"); for ($i=15; $i>0; $i-=2) { &comment(""); &comment("Round $i"); &D_ENCRYPT(15-$i,$L,$R,$i*2,$ks,"des_SPtrans","eax","ebx","ecx","edx"); &comment(""); &comment("Round ".sprintf("%d",$i-1)); &D_ENCRYPT(15-$i+1,$R,$L,($i-1)*2,$ks,"des_SPtrans","eax","ebx","ecx","edx"); } &set_label("end"); if ($do_ip) { &comment(""); &comment("FP"); &mov("edx",&wparam(0)); &FP_new($L,$R,"eax",3); &mov(&DWP(0,"edx","",0),"eax"); &mov(&DWP(4,"edx","",0),$R); } else { &comment(""); &comment("Fixup"); &rotr($L,3); # r &mov("eax",&wparam(0)); &rotr($R,3); # l &mov(&DWP(0,"eax","",0),$L); &mov(&DWP(4,"eax","",0),$R); } &pop("ebp"); &pop("ebx"); &pop("edi"); &pop("esi"); &ret(); &function_end_B($name); } sub D_ENCRYPT { local($r,$L,$R,$S,$ks,$desSP,$u,$tmp1,$tmp2,$t)=@_; &mov( $u, &DWP(&n2a($S*4),$ks,"",0)); &xor( $tmp1, $tmp1); &mov( $t, &DWP(&n2a(($S+1)*4),$ks,"",0)); &xor( $u, $R); &xor( $t, $R); &and( $u, "0xfcfcfcfc" ); &and( $t, "0xcfcfcfcf" ); &movb( &LB($tmp1), &LB($u) ); &movb( &LB($tmp2), &HB($u) ); &rotr( $t, 4 ); &mov( $ks, &DWP(" $desSP",$tmp1,"",0)); &movb( &LB($tmp1), &LB($t) ); &xor( $L, $ks); &mov( $ks, &DWP("0x200+$desSP",$tmp2,"",0)); &xor( $L, $ks); ###### &movb( &LB($tmp2), &HB($t) ); &shr( $u, 16); &mov( $ks, &DWP("0x100+$desSP",$tmp1,"",0)); &xor( $L, $ks); ###### &movb( &LB($tmp1), &HB($u) ); &shr( $t, 16); &mov( $ks, &DWP("0x300+$desSP",$tmp2,"",0)); &xor( $L, $ks); &mov( $ks, &wparam(1) ); &movb( &LB($tmp2), &HB($t) ); &and( $u, "0xff" ); &and( $t, "0xff" ); &mov( $tmp1, &DWP("0x600+$desSP",$tmp1,"",0)); &xor( $L, $tmp1); &mov( $tmp1, &DWP("0x700+$desSP",$tmp2,"",0)); &xor( $L, $tmp1); &mov( $tmp1, &DWP("0x400+$desSP",$u,"",0)); &xor( $L, $tmp1); &mov( $tmp1, &DWP("0x500+$desSP",$t,"",0)); &xor( $L, $tmp1); } sub n2a { sprintf("%d",$_[0]); } # now has a side affect of rotating $a by $shift sub R_PERM_OP { local($a,$b,$tt,$shift,$mask,$last)=@_; &rotl( $a, $shift ) if ($shift != 0); &mov( $tt, $a ); &xor( $a, $b ); &and( $a, $mask ); if (!$last eq $b) { &xor( $b, $a ); &xor( $tt, $a ); } else { &xor( $tt, $a ); &xor( $b, $a ); } &comment(""); } sub IP_new { local($l,$r,$tt,$lr)=@_; &R_PERM_OP($l,$r,$tt, 4,"0xf0f0f0f0",$l); &R_PERM_OP($r,$tt,$l,20,"0xfff0000f",$l); &R_PERM_OP($l,$tt,$r,14,"0x33333333",$r); &R_PERM_OP($tt,$r,$l,22,"0x03fc03fc",$r); &R_PERM_OP($l,$r,$tt, 9,"0xaaaaaaaa",$r); if ($lr != 3) { if (($lr-3) < 0) { &rotr($tt, 3-$lr); } else { &rotl($tt, $lr-3); } } if ($lr != 2) { if (($lr-2) < 0) { &rotr($r, 2-$lr); } else { &rotl($r, $lr-2); } } } sub FP_new { local($l,$r,$tt,$lr)=@_; if ($lr != 2) { if (($lr-2) < 0) { &rotl($r, 2-$lr); } else { &rotr($r, $lr-2); } } if ($lr != 3) { if (($lr-3) < 0) { &rotl($l, 3-$lr); } else { &rotr($l, $lr-3); } } &R_PERM_OP($l,$r,$tt, 0,"0xaaaaaaaa",$r); &R_PERM_OP($tt,$r,$l,23,"0x03fc03fc",$r); &R_PERM_OP($l,$r,$tt,10,"0x33333333",$l); &R_PERM_OP($r,$tt,$l,18,"0xfff0000f",$l); &R_PERM_OP($l,$tt,$r,12,"0xf0f0f0f0",$r); &rotr($tt , 4); } libreswan-3.32/linux/net/ipsec/des/asm/des686.pl000077500000000000000000000120771365625662500214200ustar00rootroot00000000000000#!/usr/bin/perl $prog="des686.pl"; # base code is in microsft # op dest, source # format. # # WILL NOT WORK ANYMORE WITH desboth.pl require "desboth.pl"; if ( ($ARGV[0] eq "elf")) { require "x86unix.pl"; } elsif ( ($ARGV[0] eq "a.out")) { $aout=1; require "x86unix.pl"; } elsif ( ($ARGV[0] eq "sol")) { $sol=1; require "x86unix.pl"; } elsif ( ($ARGV[0] eq "cpp")) { $cpp=1; require "x86unix.pl"; } elsif ( ($ARGV[0] eq "win32")) { require "x86ms.pl"; } else { print STDERR <<"EOF"; Pick one target type from elf - linux, FreeBSD etc a.out - old linux sol - x86 solaris cpp - format so x86unix.cpp can be used win32 - Windows 95/Windows NT EOF exit(1); } &comment("Don't even think of reading this code"); &comment("It was automatically generated by $prog"); &comment("Which is a perl program used to generate the x86 assember for"); &comment("any of elf, a.out, Win32, or Solaris"); &comment("It can be found in SSLeay 0.6.5+ or in libdes 3.26+"); &comment("eric "); &comment(""); &file("dx86xxxx"); $L="edi"; $R="esi"; &des_encrypt("des_encrypt",1); &des_encrypt("des_encrypt2",0); &des_encrypt3("des_encrypt3",1); &des_encrypt3("des_decrypt3",0); &file_end(); sub des_encrypt { local($name,$do_ip)=@_; &function_begin($name,"EXTRN _des_SPtrans:DWORD"); &comment(""); &comment("Load the 2 words"); &mov("eax",&wparam(0)); &mov($L,&DWP(0,"eax","",0)); &mov($R,&DWP(4,"eax","",0)); $ksp=&wparam(1); if ($do_ip) { &comment(""); &comment("IP"); &IP_new($L,$R,"eax"); } &comment(""); &comment("fixup rotate"); &rotl($R,3); &rotl($L,3); &exch($L,$R); &comment(""); &comment("load counter, key_schedule and enc flag"); &mov("eax",&wparam(2)); # get encrypt flag &mov("ebp",&wparam(1)); # get ks &cmp("eax","0"); &je(&label("start_decrypt")); # encrypting part for ($i=0; $i<16; $i+=2) { &comment(""); &comment("Round $i"); &D_ENCRYPT($L,$R,$i*2,"ebp","des_SPtrans","ecx","edx","eax","ebx"); &comment(""); &comment("Round ".sprintf("%d",$i+1)); &D_ENCRYPT($R,$L,($i+1)*2,"ebp","des_SPtrans","ecx","edx","eax","ebx"); } &jmp(&label("end")); &set_label("start_decrypt"); for ($i=15; $i>0; $i-=2) { &comment(""); &comment("Round $i"); &D_ENCRYPT($L,$R,$i*2,"ebp","des_SPtrans","ecx","edx","eax","ebx"); &comment(""); &comment("Round ".sprintf("%d",$i-1)); &D_ENCRYPT($R,$L,($i-1)*2,"ebp","des_SPtrans","ecx","edx","eax","ebx"); } &set_label("end"); &comment(""); &comment("Fixup"); &rotr($L,3); # r &rotr($R,3); # l if ($do_ip) { &comment(""); &comment("FP"); &FP_new($R,$L,"eax"); } &mov("eax",&wparam(0)); &mov(&DWP(0,"eax","",0),$L); &mov(&DWP(4,"eax","",0),$R); &function_end($name); } # The logic is to load R into 2 registers and operate on both at the same time. # We also load the 2 R's into 2 more registers so we can do the 'move word down a byte' # while also masking the other copy and doing a lookup. We then also accumulate the # L value in 2 registers then combine them at the end. sub D_ENCRYPT { local($L,$R,$S,$ks,$desSP,$u,$t,$tmp1,$tmp2,$tmp3)=@_; &mov( $u, &DWP(&n2a($S*4),$ks,"",0)); &mov( $t, &DWP(&n2a(($S+1)*4),$ks,"",0)); &xor( $u, $R ); &xor( $t, $R ); &rotr( $t, 4 ); # the numbers at the end of the line are original instruction order &mov( $tmp2, $u ); # 1 2 &mov( $tmp1, $t ); # 1 1 &and( $tmp2, "0xfc" ); # 1 4 &and( $tmp1, "0xfc" ); # 1 3 &shr( $t, 8 ); # 1 5 &xor( $L, &DWP("0x100+$desSP",$tmp1,"",0)); # 1 7 &shr( $u, 8 ); # 1 6 &mov( $tmp1, &DWP(" $desSP",$tmp2,"",0)); # 1 8 &mov( $tmp2, $u ); # 2 2 &xor( $L, $tmp1 ); # 1 9 &and( $tmp2, "0xfc" ); # 2 4 &mov( $tmp1, $t ); # 2 1 &and( $tmp1, "0xfc" ); # 2 3 &shr( $t, 8 ); # 2 5 &xor( $L, &DWP("0x300+$desSP",$tmp1,"",0)); # 2 7 &shr( $u, 8 ); # 2 6 &mov( $tmp1, &DWP("0x200+$desSP",$tmp2,"",0)); # 2 8 &mov( $tmp2, $u ); # 3 2 &xor( $L, $tmp1 ); # 2 9 &and( $tmp2, "0xfc" ); # 3 4 &mov( $tmp1, $t ); # 3 1 &shr( $u, 8 ); # 3 6 &and( $tmp1, "0xfc" ); # 3 3 &shr( $t, 8 ); # 3 5 &xor( $L, &DWP("0x500+$desSP",$tmp1,"",0)); # 3 7 &mov( $tmp1, &DWP("0x400+$desSP",$tmp2,"",0)); # 3 8 &and( $t, "0xfc" ); # 4 1 &xor( $L, $tmp1 ); # 3 9 &and( $u, "0xfc" ); # 4 2 &xor( $L, &DWP("0x700+$desSP",$t,"",0)); # 4 3 &xor( $L, &DWP("0x600+$desSP",$u,"",0)); # 4 4 } sub PERM_OP { local($a,$b,$tt,$shift,$mask)=@_; &mov( $tt, $a ); &shr( $tt, $shift ); &xor( $tt, $b ); &and( $tt, $mask ); &xor( $b, $tt ); &shl( $tt, $shift ); &xor( $a, $tt ); } sub IP_new { local($l,$r,$tt)=@_; &PERM_OP($r,$l,$tt, 4,"0x0f0f0f0f"); &PERM_OP($l,$r,$tt,16,"0x0000ffff"); &PERM_OP($r,$l,$tt, 2,"0x33333333"); &PERM_OP($l,$r,$tt, 8,"0x00ff00ff"); &PERM_OP($r,$l,$tt, 1,"0x55555555"); } sub FP_new { local($l,$r,$tt)=@_; &PERM_OP($l,$r,$tt, 1,"0x55555555"); &PERM_OP($r,$l,$tt, 8,"0x00ff00ff"); &PERM_OP($l,$r,$tt, 2,"0x33333333"); &PERM_OP($r,$l,$tt,16,"0x0000ffff"); &PERM_OP($l,$r,$tt, 4,"0x0f0f0f0f"); } sub n2a { sprintf("%d",$_[0]); } libreswan-3.32/linux/net/ipsec/des/asm/desboth.pl000077500000000000000000000025111365625662500220210ustar00rootroot00000000000000#!/usr/bin/perl $L="edi"; $R="esi"; sub des_encrypt3 { local($name,$enc)=@_; &function_begin_B($name,""); &push("ebx"); &mov("ebx",&wparam(0)); &push("ebp"); &push("esi"); &push("edi"); &comment(""); &comment("Load the data words"); &mov($L,&DWP(0,"ebx","",0)); &mov($R,&DWP(4,"ebx","",0)); &stack_push(3); &comment(""); &comment("IP"); &IP_new($L,$R,"edx",0); # put them back if ($enc) { &mov(&DWP(4,"ebx","",0),$R); &mov("eax",&wparam(1)); &mov(&DWP(0,"ebx","",0),"edx"); &mov("edi",&wparam(2)); &mov("esi",&wparam(3)); } else { &mov(&DWP(4,"ebx","",0),$R); &mov("esi",&wparam(1)); &mov(&DWP(0,"ebx","",0),"edx"); &mov("edi",&wparam(2)); &mov("eax",&wparam(3)); } &mov(&swtmp(2), (($enc)?"1":"0")); &mov(&swtmp(1), "eax"); &mov(&swtmp(0), "ebx"); &call("des_encrypt2"); &mov(&swtmp(2), (($enc)?"0":"1")); &mov(&swtmp(1), "edi"); &mov(&swtmp(0), "ebx"); &call("des_encrypt2"); &mov(&swtmp(2), (($enc)?"1":"0")); &mov(&swtmp(1), "esi"); &mov(&swtmp(0), "ebx"); &call("des_encrypt2"); &stack_pop(3); &mov($L,&DWP(0,"ebx","",0)); &mov($R,&DWP(4,"ebx","",0)); &comment(""); &comment("FP"); &FP_new($L,$R,"eax",0); &mov(&DWP(0,"ebx","",0),"eax"); &mov(&DWP(4,"ebx","",0),$R); &pop("edi"); &pop("esi"); &pop("ebp"); &pop("ebx"); &ret(); &function_end_B($name); } libreswan-3.32/linux/net/ipsec/des/asm/readme000066400000000000000000000133621365625662500212170ustar00rootroot00000000000000First up, let me say I don't like writing in assembler. It is not portable, dependent on the particular CPU architecture release and is generally a pig to debug and get right. Having said that, the x86 architecture is probably the most important for speed due to number of boxes and since it appears to be the worst architecture to get good C compilers for. So due to this, I have lowered myself to do assembler for the inner DES routines in libdes :-). The file to implement in assembler is des_enc.c. Replace the following 4 functions des_encrypt(DES_LONG data[2],des_key_schedule ks, int encrypt); des_encrypt2(DES_LONG data[2],des_key_schedule ks, int encrypt); des_encrypt3(DES_LONG data[2],des_key_schedule ks1,ks2,ks3); des_decrypt3(DES_LONG data[2],des_key_schedule ks1,ks2,ks3); They encrypt/decrypt the 64 bits held in 'data' using the 'ks' key schedules. The only difference between the 4 functions is that des_encrypt2() does not perform IP() or FP() on the data (this is an optimization for when doing triple DES and des_encrypt3() and des_decrypt3() perform triple des. The triple DES routines are in here because it does make a big difference to have them located near the des_encrypt2 function at link time.. Now as we all know, there are lots of different operating systems running on x86 boxes, and unfortunately they normally try to make sure their assembler formating is not the same as the other peoples. The 4 main formats I know of are Microsoft Windows 95/Windows NT Elf Includes Linux and FreeBSD(?). a.out The older Linux. Solaris Same as Elf but different comments :-(. Now I was not overly keen to write 4 different copies of the same code, so I wrote a few perl routines to output the correct assembler, given a target assembler type. This code is ugly and is just a hack. The libraries are x86unix.pl and x86ms.pl. des586.pl, des686.pl and des-som[23].pl are the programs to actually generate the assembler. So to generate elf assembler perl des-som3.pl elf >dx86-elf.s For Windows 95/NT perl des-som2.pl win32 >win32.asm [ update 4 Jan 1996 ] I have added another way to do things. perl des-som3.pl cpp >dx86-cpp.s generates a file that will be included by dx86unix.cpp when it is compiled. To build for elf, a.out, solaris, bsdi etc, cc -E -DELF asm/dx86unix.cpp | as -o asm/dx86-elf.o cc -E -DSOL asm/dx86unix.cpp | as -o asm/dx86-sol.o cc -E -DOUT asm/dx86unix.cpp | as -o asm/dx86-out.o cc -E -DBSDI asm/dx86unix.cpp | as -o asm/dx86bsdi.o This was done to cut down the number of files in the distribution. Now the ugly part. I acquired my copy of Intels "Optimization's For Intel's 32-Bit Processors" and found a few interesting things. First, the aim of the exercise is to 'extract' one byte at a time from a word and do an array lookup. This involves getting the byte from the 4 locations in the word and moving it to a new word and doing the lookup. The most obvious way to do this is xor eax, eax # clear word movb al, cl # get low byte xor edi DWORD PTR 0x100+des_SP[eax] # xor in word movb al, ch # get next byte xor edi DWORD PTR 0x300+des_SP[eax] # xor in word shr ecx 16 which seems ok. For the pentium, this system appears to be the best. One has to do instruction interleaving to keep both functional units operating, but it is basically very efficient. Now the crunch. When a full register is used after a partial write, eg. mov al, cl xor edi, DWORD PTR 0x100+des_SP[eax] 386 - 1 cycle stall 486 - 1 cycle stall 586 - 0 cycle stall 686 - at least 7 cycle stall (page 22 of the above mentioned document). So the technique that produces the best results on a pentium, according to the documentation, will produce hideous results on a pentium pro. To get around this, des686.pl will generate code that is not as fast on a pentium, should be very good on a pentium pro. mov eax, ecx # copy word shr ecx, 8 # line up next byte and eax, 0fch # mask byte xor edi DWORD PTR 0x100+des_SP[eax] # xor in array lookup mov eax, ecx # get word shr ecx 8 # line up next byte and eax, 0fch # mask byte xor edi DWORD PTR 0x300+des_SP[eax] # xor in array lookup Due to the execution units in the pentium, this actually works quite well. For a pentium pro it should be very good. This is the type of output Visual C++ generates. There is a third option. instead of using mov al, ch which is bad on the pentium pro, one may be able to use movzx eax, ch which may not incur the partial write penalty. On the pentium, this instruction takes 4 cycles so is not worth using but on the pentium pro it appears it may be worth while. I need access to one to experiment :-). eric (20 Oct 1996) 22 Nov 1996 - I have asked people to run the 2 different version on pentium pros and it appears that the intel documentation is wrong. The mov al,bh is still faster on a pentium pro, so just use the des586.pl install des686.pl 3 Dec 1996 - I added des_encrypt3/des_decrypt3 because I have moved these functions into des_enc.c because it does make a massive performance difference on some boxes to have the functions code located close to the des_encrypt2() function. 9 Jan 1997 - des-som2.pl is now the correct perl script to use for pentiums. It contains an inner loop from Svend Olaf Mikkelsen which does raw ecb DES calls at 273,000 per second. He had a previous version at 250,000 and the best I was able to get was 203,000. The content has not changed, this is all due to instruction sequencing (and actual instructions choice) which is able to keep both functional units of the pentium going. We may have lost the ugly register usage restrictions when x86 went 32 bit but for the pentium it has been replaced by evil instruction ordering tricks. 13 Jan 1997 - des-som3.pl, more optimizations from Svend Olaf. raw DES at 281,000 per second on a pentium 100. libreswan-3.32/linux/net/ipsec/des/cbc_enc.c000066400000000000000000000115021365625662500207710ustar00rootroot00000000000000/* crypto/des/cbc_enc.c */ /* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@cryptsoft.com). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are adhered to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@cryptsoft.com). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * 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 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@cryptsoft.com)" * The word 'cryptographic' can be left out if the routines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ #include "des/des_locl.h" void des_cbc_encrypt(input, output, length, schedule, ivec, enc) des_cblock(*input); des_cblock(*output); long length; des_key_schedule schedule; des_cblock(*ivec); int enc; { register DES_LONG tin0, tin1; register DES_LONG tout0, tout1, xor0, xor1; register unsigned char *in, *out; register long l = length; DES_LONG tin[2]; unsigned char *iv; in = (unsigned char *)input; out = (unsigned char *)output; iv = (unsigned char *)ivec; if (enc) { c2l(iv, tout0); c2l(iv, tout1); for (l -= 8; l >= 0; l -= 8) { c2l(in, tin0); c2l(in, tin1); tin0 ^= tout0; tin[0] = tin0; tin1 ^= tout1; tin[1] = tin1; des_encrypt((DES_LONG *)tin, schedule, DES_ENCRYPT); tout0 = tin[0]; l2c(tout0, out); tout1 = tin[1]; l2c(tout1, out); } if (l != -8) { c2ln(in, tin0, tin1, l + 8); tin0 ^= tout0; tin[0] = tin0; tin1 ^= tout1; tin[1] = tin1; des_encrypt((DES_LONG *)tin, schedule, DES_ENCRYPT); tout0 = tin[0]; l2c(tout0, out); tout1 = tin[1]; l2c(tout1, out); } } else { c2l(iv, xor0); c2l(iv, xor1); for (l -= 8; l >= 0; l -= 8) { c2l(in, tin0); tin[0] = tin0; c2l(in, tin1); tin[1] = tin1; des_encrypt((DES_LONG *)tin, schedule, DES_DECRYPT); tout0 = tin[0] ^ xor0; tout1 = tin[1] ^ xor1; l2c(tout0, out); l2c(tout1, out); xor0 = tin0; xor1 = tin1; } if (l != -8) { c2l(in, tin0); tin[0] = tin0; c2l(in, tin1); tin[1] = tin1; des_encrypt((DES_LONG *)tin, schedule, DES_DECRYPT); tout0 = tin[0] ^ xor0; tout1 = tin[1] ^ xor1; l2cn(tout0, tout1, out, l + 8); /* xor0=tin0; xor1=tin1; */ } } tin0 = tin1 = tout0 = tout1 = xor0 = xor1 = 0; tin[0] = tin[1] = 0; } libreswan-3.32/linux/net/ipsec/des/des.doc000066400000000000000000000456741365625662500205340ustar00rootroot00000000000000The DES library. Please note that this library was originally written to operate with eBones, a version of Kerberos that had had encryption removed when it left the USA and then put back in. As such there are some routines that I will advise not using but they are still in the library for historical reasons. For all calls that have an 'input' and 'output' variables, they can be the same. This library requires the inclusion of 'des.h'. All of the encryption functions take what is called a des_key_schedule as an argument. A des_key_schedule is an expanded form of the des key. A des_key is 8 bytes of odd parity, the type used to hold the key is a des_cblock. A des_cblock is an array of 8 bytes, often in this library description I will refer to input bytes when the function specifies des_cblock's as input or output, this just means that the variable should be a multiple of 8 bytes. The define DES_ENCRYPT is passed to specify encryption, DES_DECRYPT to specify decryption. The functions and global variable are as follows: int des_check_key; DES keys are supposed to be odd parity. If this variable is set to a non-zero value, des_set_key() will check that the key has odd parity and is not one of the known weak DES keys. By default this variable is turned off; void des_set_odd_parity( des_cblock *key ); This function takes a DES key (8 bytes) and sets the parity to odd. int des_is_weak_key( des_cblock *key ); This function returns a non-zero value if the DES key passed is a weak, DES key. If it is a weak key, don't use it, try a different one. If you are using 'random' keys, the chances of hitting a weak key are 1/2^52 so it is probably not worth checking for them. int des_set_key( des_cblock *key, des_key_schedule schedule); Des_set_key converts an 8 byte DES key into a des_key_schedule. A des_key_schedule is an expanded form of the key which is used to perform actual encryption. It can be regenerated from the DES key so it only needs to be kept when encryption or decryption is about to occur. Don't save or pass around des_key_schedule's since they are CPU architecture dependent, DES keys are not. If des_check_key is non zero, zero is returned if the key has the wrong parity or the key is a weak key, else 1 is returned. int des_key_sched( des_cblock *key, des_key_schedule schedule); An alternative name for des_set_key(). int des_rw_mode; /* defaults to DES_PCBC_MODE */ This flag holds either DES_CBC_MODE or DES_PCBC_MODE (default). This specifies the function to use in the enc_read() and enc_write() functions. void des_encrypt( unsigned long *data, des_key_schedule ks, int enc); This is the DES encryption function that gets called by just about every other DES routine in the library. You should not use this function except to implement 'modes' of DES. I say this because the functions that call this routine do the conversion from 'char *' to long, and this needs to be done to make sure 'non-aligned' memory access do not occur. The characters are loaded 'little endian', have a look at my source code for more details on how I use this function. Data is a pointer to 2 unsigned long's and ks is the des_key_schedule to use. enc, is non zero specifies encryption, zero if decryption. void des_encrypt2( unsigned long *data, des_key_schedule ks, int enc); This functions is the same as des_encrypt() except that the DES initial permutation (IP) and final permutation (FP) have been left out. As for des_encrypt(), you should not use this function. It is used by the routines in my library that implement triple DES. IP() des_encrypt2() des_encrypt2() des_encrypt2() FP() is the same as des_encrypt() des_encrypt() des_encrypt() except faster :-). void des_ecb_encrypt( des_cblock *input, des_cblock *output, des_key_schedule ks, int enc); This is the basic Electronic Code Book form of DES, the most basic form. Input is encrypted into output using the key represented by ks. If enc is non zero (DES_ENCRYPT), encryption occurs, otherwise decryption occurs. Input is 8 bytes long and output is 8 bytes. (the des_cblock structure is 8 chars). void des_ecb3_encrypt( des_cblock *input, des_cblock *output, des_key_schedule ks1, des_key_schedule ks2, des_key_schedule ks3, int enc); This is the 3 key EDE mode of ECB DES. What this means is that the 8 bytes of input is encrypted with ks1, decrypted with ks2 and then encrypted again with ks3, before being put into output; C=E(ks3,D(ks2,E(ks1,M))). There is a macro, des_ecb2_encrypt() that only takes 2 des_key_schedules that implements, C=E(ks1,D(ks2,E(ks1,M))) in that the final encrypt is done with ks1. void des_cbc_encrypt( des_cblock *input, des_cblock *output, long length, des_key_schedule ks, des_cblock *ivec, int enc); This routine implements DES in Cipher Block Chaining mode. Input, which should be a multiple of 8 bytes is encrypted (or decrypted) to output which will also be a multiple of 8 bytes. The number of bytes is in length (and from what I've said above, should be a multiple of 8). If length is not a multiple of 8, I'm not being held responsible :-). ivec is the initialisation vector. This function does not modify this variable. To correctly implement cbc mode, you need to do one of 2 things; copy the last 8 bytes of cipher text for use as the next ivec in your application, or use des_ncbc_encrypt(). Only this routine has this problem with updating the ivec, all other routines that are implementing cbc mode update ivec. void des_ncbc_encrypt( des_cblock *input, des_cblock *output, long length, des_key_schedule sk, des_cblock *ivec, int enc); For historical reasons, des_cbc_encrypt() did not update the ivec with the value requires so that subsequent calls to des_cbc_encrypt() would 'chain'. This was needed so that the same 'length' values would not need to be used when decrypting. des_ncbc_encrypt() does the right thing. It is the same as des_cbc_encrypt accept that ivec is updates with the correct value to pass in subsequent calls to des_ncbc_encrypt(). I advise using des_ncbc_encrypt() instead of des_cbc_encrypt(); void des_xcbc_encrypt( des_cblock *input, des_cblock *output, long length, des_key_schedule sk, des_cblock *ivec, des_cblock *inw, des_cblock *outw, int enc); This is RSA's DESX mode of DES. It uses inw and outw to 'whiten' the encryption. inw and outw are secret (unlike the iv) and are as such, part of the key. So the key is sort of 24 bytes. This is much better than cbc des. void des_3cbc_encrypt( des_cblock *input, des_cblock *output, long length, des_key_schedule sk1, des_key_schedule sk2, des_cblock *ivec1, des_cblock *ivec2, int enc); This function is flawed, do not use it. I have left it in the library because it is used in my des(1) program and will function correctly when used by des(1). If I removed the function, people could end up unable to decrypt files. This routine implements outer triple cbc encryption using 2 ks and 2 ivec's. Use des_ede2_cbc_encrypt() instead. void des_ede3_cbc_encrypt( des_cblock *input, des_cblock *output, long length, des_key_schedule ks1, des_key_schedule ks2, des_key_schedule ks3, des_cblock *ivec, int enc); This function implements inner triple CBC DES encryption with 3 keys. What this means is that each 'DES' operation inside the cbc mode is really an C=E(ks3,D(ks2,E(ks1,M))). Again, this is cbc mode so an ivec is requires. This mode is used by SSL. There is also a des_ede2_cbc_encrypt() that only uses 2 des_key_schedule's, the first being reused for the final encryption. C=E(ks1,D(ks2,E(ks1,M))). This form of triple DES is used by the RSAref library. void des_pcbc_encrypt( des_cblock *input, des_cblock *output, long length, des_key_schedule ks, des_cblock *ivec, int enc); This is Propagating Cipher Block Chaining mode of DES. It is used by Kerberos v4. It's parameters are the same as des_ncbc_encrypt(). void des_cfb_encrypt( unsigned char *in, unsigned char *out, int numbits, long length, des_key_schedule ks, des_cblock *ivec, int enc); Cipher Feedback Back mode of DES. This implementation 'feeds back' in numbit blocks. The input (and output) is in multiples of numbits bits. numbits should to be a multiple of 8 bits. Length is the number of bytes input. If numbits is not a multiple of 8 bits, the extra bits in the bytes will be considered padding. So if numbits is 12, for each 2 input bytes, the 4 high bits of the second byte will be ignored. So to encode 72 bits when using a numbits of 12 take 12 bytes. To encode 72 bits when using numbits of 9 will take 16 bytes. To encode 80 bits when using numbits of 16 will take 10 bytes. etc, etc. This padding will apply to both input and output. void des_cfb64_encrypt( unsigned char *in, unsigned char *out, long length, des_key_schedule ks, des_cblock *ivec, int *num, int enc); This is one of the more useful functions in this DES library, it implements CFB mode of DES with 64bit feedback. Why is this useful you ask? Because this routine will allow you to encrypt an arbitrary number of bytes, no 8 byte padding. Each call to this routine will encrypt the input bytes to output and then update ivec and num. num contains 'how far' we are though ivec. If this does not make much sense, read more about cfb mode of DES :-). void des_ede3_cfb64_encrypt( unsigned char *in, unsigned char *out, long length, des_key_schedule ks1, des_key_schedule ks2, des_key_schedule ks3, des_cblock *ivec, int *num, int enc); Same as des_cfb64_encrypt() accept that the DES operation is triple DES. As usual, there is a macro for des_ede2_cfb64_encrypt() which reuses ks1. void des_ofb_encrypt( unsigned char *in, unsigned char *out, int numbits, long length, des_key_schedule ks, des_cblock *ivec); This is a implementation of Output Feed Back mode of DES. It is the same as des_cfb_encrypt() in that numbits is the size of the units dealt with during input and output (in bits). void des_ofb64_encrypt( unsigned char *in, unsigned char *out, long length, des_key_schedule ks, des_cblock *ivec, int *num); The same as des_cfb64_encrypt() except that it is Output Feed Back mode. void des_ede3_ofb64_encrypt( unsigned char *in, unsigned char *out, long length, des_key_schedule ks1, des_key_schedule ks2, des_key_schedule ks3, des_cblock *ivec, int *num); Same as des_ofb64_encrypt() accept that the DES operation is triple DES. As usual, there is a macro for des_ede2_ofb64_encrypt() which reuses ks1. int des_read_pw_string( char *buf, int length, char *prompt, int verify); This routine is used to get a password from the terminal with echo turned off. Buf is where the string will end up and length is the size of buf. Prompt is a string presented to the 'user' and if verify is set, the key is asked for twice and unless the 2 copies match, an error is returned. A return code of -1 indicates a system error, 1 failure due to use interaction, and 0 is success. unsigned long des_cbc_cksum( des_cblock *input, des_cblock *output, long length, des_key_schedule ks, des_cblock *ivec); This function produces an 8 byte checksum from input that it puts in output and returns the last 4 bytes as a long. The checksum is generated via cbc mode of DES in which only the last 8 byes are kept. I would recommend not using this function but instead using the EVP_Digest routines, or at least using MD5 or SHA. This function is used by Kerberos v4 so that is why it stays in the library. char *des_fcrypt( const char *buf, const char *salt char *ret); This is my fast version of the unix crypt(3) function. This version takes only a small amount of space relative to other fast crypt() implementations. This is different to the normal crypt in that the third parameter is the buffer that the return value is written into. It needs to be at least 14 bytes long. This function is thread safe, unlike the normal crypt. char *crypt( const char *buf, const char *salt); This function calls des_fcrypt() with a static array passed as the third parameter. This emulates the normal non-thread safe semantics of crypt(3). void des_string_to_key( char *str, des_cblock *key); This function takes str and converts it into a DES key. I would recommend using MD5 instead and use the first 8 bytes of output. When I wrote the first version of these routines back in 1990, MD5 did not exist but I feel these routines are still sound. This routines is compatible with the one in MIT's libdes. void des_string_to_2keys( char *str, des_cblock *key1, des_cblock *key2); This function takes str and converts it into 2 DES keys. I would recommend using MD5 and using the 16 bytes as the 2 keys. I have nothing against these 2 'string_to_key' routines, it's just that if you say that your encryption key is generated by using the 16 bytes of an MD5 hash, every-one knows how you generated your keys. int des_read_password( des_cblock *key, char *prompt, int verify); This routine combines des_read_pw_string() with des_string_to_key(). int des_read_2passwords( des_cblock *key1, des_cblock *key2, char *prompt, int verify); This routine combines des_read_pw_string() with des_string_to_2key(). void des_random_seed( des_cblock key); This routine sets a starting point for des_random_key(). void des_random_key( des_cblock ret); This function return a random key. Make sure to 'seed' the random number generator (with des_random_seed()) before using this function. I personally now use a MD5 based random number system. int des_enc_read( int fd, char *buf, int len, des_key_schedule ks, des_cblock *iv); This function will write to a file descriptor the encrypted data from buf. This data will be preceded by a 4 byte 'byte count' and will be padded out to 8 bytes. The encryption is either CBC of PCBC depending on the value of des_rw_mode. If it is DES_PCBC_MODE, pcbc is used, if DES_CBC_MODE, cbc is used. The default is to use DES_PCBC_MODE. int des_enc_write( int fd, char *buf, int len, des_key_schedule ks, des_cblock *iv); This routines read stuff written by des_enc_read() and decrypts it. I have used these routines quite a lot but I don't believe they are suitable for non-blocking io. If you are after a full authentication/encryption over networks, have a look at SSL instead. unsigned long des_quad_cksum( des_cblock *input, des_cblock *output, long length, int out_count, des_cblock *seed); This is a function from Kerberos v4 that is not anything to do with DES but was needed. It is a cksum that is quicker to generate than des_cbc_cksum(); I personally would use MD5 routines now. ===== Modes of DES Quite a bit of the following information has been taken from AS 2805.5.2 Australian Standard Electronic funds transfer - Requirements for interfaces, Part 5.2: Modes of operation for an n-bit block cipher algorithm Appendix A There are several different modes in which DES can be used, they are as follows. Electronic Codebook Mode (ECB) (des_ecb_encrypt()) - 64 bits are enciphered at a time. - The order of the blocks can be rearranged without detection. - The same plaintext block always produces the same ciphertext block (for the same key) making it vulnerable to a 'dictionary attack'. - An error will only affect one ciphertext block. Cipher Block Chaining Mode (CBC) (des_cbc_encrypt()) - a multiple of 64 bits are enciphered at a time. - The CBC mode produces the same ciphertext whenever the same plaintext is encrypted using the same key and starting variable. - The chaining operation makes the ciphertext blocks dependent on the current and all preceding plaintext blocks and therefore blocks can not be rearranged. - The use of different starting variables prevents the same plaintext enciphering to the same ciphertext. - An error will affect the current and the following ciphertext blocks. Cipher Feedback Mode (CFB) (des_cfb_encrypt()) - a number of bits (j) <= 64 are enciphered at a time. - The CFB mode produces the same ciphertext whenever the same plaintext is encrypted using the same key and starting variable. - The chaining operation makes the ciphertext variables dependent on the current and all preceding variables and therefore j-bit variables are chained together and can not be rearranged. - The use of different starting variables prevents the same plaintext enciphering to the same ciphertext. - The strength of the CFB mode depends on the size of k (maximal if j == k). In my implementation this is always the case. - Selection of a small value for j will require more cycles through the encipherment algorithm per unit of plaintext and thus cause greater processing overheads. - Only multiples of j bits can be enciphered. - An error will affect the current and the following ciphertext variables. Output Feedback Mode (OFB) (des_ofb_encrypt()) - a number of bits (j) <= 64 are enciphered at a time. - The OFB mode produces the same ciphertext whenever the same plaintext enciphered using the same key and starting variable. More over, in the OFB mode the same key stream is produced when the same key and start variable are used. Consequently, for security reasons a specific start variable should be used only once for a given key. - The absence of chaining makes the OFB more vulnerable to specific attacks. - The use of different start variables values prevents the same plaintext enciphering to the same ciphertext, by producing different key streams. - Selection of a small value for j will require more cycles through the encipherment algorithm per unit of plaintext and thus cause greater processing overheads. - Only multiples of j bits can be enciphered. - OFB mode of operation does not extend ciphertext errors in the resultant plaintext output. Every bit error in the ciphertext causes only one bit to be in error in the deciphered plaintext. - OFB mode is not self-synchronising. If the two operation of encipherment and decipherment get out of synchronism, the system needs to be re-initialised. - Each re-initialisation should use a value of the start variable different from the start variable values used before with the same key. The reason for this is that an identical bit stream would be produced each time from the same parameters. This would be susceptible to a ' known plaintext' attack. Triple ECB Mode (des_ecb3_encrypt()) - Encrypt with key1, decrypt with key2 and encrypt with key3 again. - As for ECB encryption but increases the key length to 168 bits. There are theoretic attacks that can be used that make the effective key length 112 bits, but this attack also requires 2^56 blocks of memory, not very likely, even for the NSA. - If both keys are the same it is equivalent to encrypting once with just one key. - If the first and last key are the same, the key length is 112 bits. There are attacks that could reduce the key space to 55 bit's but it requires 2^56 blocks of memory. - If all 3 keys are the same, this is effectively the same as normal ecb mode. Triple CBC Mode (des_ede3_cbc_encrypt()) - Encrypt with key1, decrypt with key2 and then encrypt with key3. - As for CBC encryption but increases the key length to 168 bits with the same restrictions as for triple ecb mode. libreswan-3.32/linux/net/ipsec/des/des_enc.c000066400000000000000000000316741365625662500210310ustar00rootroot00000000000000/* crypto/des/des_enc.c */ /* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@cryptsoft.com). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are adhered to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@cryptsoft.com). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * 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 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@cryptsoft.com)" * The word 'cryptographic' can be left out if the routines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ #include "des/des_locl.h" void des_encrypt(data, ks, enc) DES_LONG * data; des_key_schedule ks; int enc; { register DES_LONG l, r, t, u; #ifdef DES_PTR register unsigned char *des_SP = (unsigned char *)des_SPtrans; #endif #ifndef DES_UNROLL register int i; #endif register DES_LONG *s; r = data[0]; l = data[1]; IP(r, l); /* Things have been modified so that the initial rotate is * done outside the loop. This required the * des_SPtrans values in sp.h to be rotated 1 bit to the right. * One perl script later and things have a 5% speed up on a sparc2. * Thanks to Richard Outerbridge <71755.204@CompuServe.COM> * for pointing this out. */ /* clear the top bits on machines with 8byte longs */ /* shift left by 2 */ r = ROTATE(r, 29) & 0xffffffffL; l = ROTATE(l, 29) & 0xffffffffL; s = (DES_LONG *)ks; /* I don't know if it is worth the effort of loop unrolling the * inner loop */ if (enc) { #ifdef DES_UNROLL D_ENCRYPT(l, r, 0); /* 1 */ D_ENCRYPT(r, l, 2); /* 2 */ D_ENCRYPT(l, r, 4); /* 3 */ D_ENCRYPT(r, l, 6); /* 4 */ D_ENCRYPT(l, r, 8); /* 5 */ D_ENCRYPT(r, l, 10); /* 6 */ D_ENCRYPT(l, r, 12); /* 7 */ D_ENCRYPT(r, l, 14); /* 8 */ D_ENCRYPT(l, r, 16); /* 9 */ D_ENCRYPT(r, l, 18); /* 10 */ D_ENCRYPT(l, r, 20); /* 11 */ D_ENCRYPT(r, l, 22); /* 12 */ D_ENCRYPT(l, r, 24); /* 13 */ D_ENCRYPT(r, l, 26); /* 14 */ D_ENCRYPT(l, r, 28); /* 15 */ D_ENCRYPT(r, l, 30); /* 16 */ #else for (i = 0; i < 32; i += 8) { D_ENCRYPT(l, r, i + 0); /* 1 */ D_ENCRYPT(r, l, i + 2); /* 2 */ D_ENCRYPT(l, r, i + 4); /* 3 */ D_ENCRYPT(r, l, i + 6); /* 4 */ } #endif } else { #ifdef DES_UNROLL D_ENCRYPT(l, r, 30); /* 16 */ D_ENCRYPT(r, l, 28); /* 15 */ D_ENCRYPT(l, r, 26); /* 14 */ D_ENCRYPT(r, l, 24); /* 13 */ D_ENCRYPT(l, r, 22); /* 12 */ D_ENCRYPT(r, l, 20); /* 11 */ D_ENCRYPT(l, r, 18); /* 10 */ D_ENCRYPT(r, l, 16); /* 9 */ D_ENCRYPT(l, r, 14); /* 8 */ D_ENCRYPT(r, l, 12); /* 7 */ D_ENCRYPT(l, r, 10); /* 6 */ D_ENCRYPT(r, l, 8); /* 5 */ D_ENCRYPT(l, r, 6); /* 4 */ D_ENCRYPT(r, l, 4); /* 3 */ D_ENCRYPT(l, r, 2); /* 2 */ D_ENCRYPT(r, l, 0); /* 1 */ #else for (i = 30; i > 0; i -= 8) { D_ENCRYPT(l, r, i - 0); /* 16 */ D_ENCRYPT(r, l, i - 2); /* 15 */ D_ENCRYPT(l, r, i - 4); /* 14 */ D_ENCRYPT(r, l, i - 6); /* 13 */ } #endif } /* rotate and clear the top bits on machines with 8byte longs */ l = ROTATE(l, 3) & 0xffffffffL; r = ROTATE(r, 3) & 0xffffffffL; FP(r, l); data[0] = l; data[1] = r; l = r = t = u = 0; } void des_encrypt2(data, ks, enc) DES_LONG * data; des_key_schedule ks; int enc; { register DES_LONG l, r, t, u; #ifdef DES_PTR register unsigned char *des_SP = (unsigned char *)des_SPtrans; #endif #ifndef DES_UNROLL register int i; #endif register DES_LONG *s; r = data[0]; l = data[1]; /* Things have been modified so that the initial rotate is * done outside the loop. This required the * des_SPtrans values in sp.h to be rotated 1 bit to the right. * One perl script later and things have a 5% speed up on a sparc2. * Thanks to Richard Outerbridge <71755.204@CompuServe.COM> * for pointing this out. */ /* clear the top bits on machines with 8byte longs */ r = ROTATE(r, 29) & 0xffffffffL; l = ROTATE(l, 29) & 0xffffffffL; s = (DES_LONG *)ks; /* I don't know if it is worth the effort of loop unrolling the * inner loop */ if (enc) { #ifdef DES_UNROLL D_ENCRYPT(l, r, 0); /* 1 */ D_ENCRYPT(r, l, 2); /* 2 */ D_ENCRYPT(l, r, 4); /* 3 */ D_ENCRYPT(r, l, 6); /* 4 */ D_ENCRYPT(l, r, 8); /* 5 */ D_ENCRYPT(r, l, 10); /* 6 */ D_ENCRYPT(l, r, 12); /* 7 */ D_ENCRYPT(r, l, 14); /* 8 */ D_ENCRYPT(l, r, 16); /* 9 */ D_ENCRYPT(r, l, 18); /* 10 */ D_ENCRYPT(l, r, 20); /* 11 */ D_ENCRYPT(r, l, 22); /* 12 */ D_ENCRYPT(l, r, 24); /* 13 */ D_ENCRYPT(r, l, 26); /* 14 */ D_ENCRYPT(l, r, 28); /* 15 */ D_ENCRYPT(r, l, 30); /* 16 */ #else for (i = 0; i < 32; i += 8) { D_ENCRYPT(l, r, i + 0); /* 1 */ D_ENCRYPT(r, l, i + 2); /* 2 */ D_ENCRYPT(l, r, i + 4); /* 3 */ D_ENCRYPT(r, l, i + 6); /* 4 */ } #endif } else { #ifdef DES_UNROLL D_ENCRYPT(l, r, 30); /* 16 */ D_ENCRYPT(r, l, 28); /* 15 */ D_ENCRYPT(l, r, 26); /* 14 */ D_ENCRYPT(r, l, 24); /* 13 */ D_ENCRYPT(l, r, 22); /* 12 */ D_ENCRYPT(r, l, 20); /* 11 */ D_ENCRYPT(l, r, 18); /* 10 */ D_ENCRYPT(r, l, 16); /* 9 */ D_ENCRYPT(l, r, 14); /* 8 */ D_ENCRYPT(r, l, 12); /* 7 */ D_ENCRYPT(l, r, 10); /* 6 */ D_ENCRYPT(r, l, 8); /* 5 */ D_ENCRYPT(l, r, 6); /* 4 */ D_ENCRYPT(r, l, 4); /* 3 */ D_ENCRYPT(l, r, 2); /* 2 */ D_ENCRYPT(r, l, 0); /* 1 */ #else for (i = 30; i > 0; i -= 8) { D_ENCRYPT(l, r, i - 0); /* 16 */ D_ENCRYPT(r, l, i - 2); /* 15 */ D_ENCRYPT(l, r, i - 4); /* 14 */ D_ENCRYPT(r, l, i - 6); /* 13 */ } #endif } /* rotate and clear the top bits on machines with 8byte longs */ data[0] = ROTATE(l, 3) & 0xffffffffL; data[1] = ROTATE(r, 3) & 0xffffffffL; l = r = t = u = 0; } void des_encrypt3(data, ks1, ks2, ks3) DES_LONG * data; des_key_schedule ks1; des_key_schedule ks2; des_key_schedule ks3; { register DES_LONG l, r; l = data[0]; r = data[1]; IP(l, r); data[0] = l; data[1] = r; des_encrypt2((DES_LONG *)data, ks1, DES_ENCRYPT); des_encrypt2((DES_LONG *)data, ks2, DES_DECRYPT); des_encrypt2((DES_LONG *)data, ks3, DES_ENCRYPT); l = data[0]; r = data[1]; FP(r, l); data[0] = l; data[1] = r; } void des_decrypt3(data, ks1, ks2, ks3) DES_LONG * data; des_key_schedule ks1; des_key_schedule ks2; des_key_schedule ks3; { register DES_LONG l, r; l = data[0]; r = data[1]; IP(l, r); data[0] = l; data[1] = r; des_encrypt2((DES_LONG *)data, ks3, DES_DECRYPT); des_encrypt2((DES_LONG *)data, ks2, DES_ENCRYPT); des_encrypt2((DES_LONG *)data, ks1, DES_DECRYPT); l = data[0]; r = data[1]; FP(r, l); data[0] = l; data[1] = r; } #ifndef DES_DEFAULT_OPTIONS void des_ncbc_encrypt(input, output, length, schedule, ivec, enc) des_cblock(*input); des_cblock(*output); long length; des_key_schedule schedule; des_cblock(*ivec); int enc; { register DES_LONG tin0, tin1; register DES_LONG tout0, tout1, xor0, xor1; register unsigned char *in, *out; register long l = length; DES_LONG tin[2]; unsigned char *iv; in = (unsigned char *)input; out = (unsigned char *)output; iv = (unsigned char *)ivec; if (enc) { c2l(iv, tout0); c2l(iv, tout1); for (l -= 8; l >= 0; l -= 8) { c2l(in, tin0); c2l(in, tin1); tin0 ^= tout0; tin[0] = tin0; tin1 ^= tout1; tin[1] = tin1; des_encrypt((DES_LONG *)tin, schedule, DES_ENCRYPT); tout0 = tin[0]; l2c(tout0, out); tout1 = tin[1]; l2c(tout1, out); } if (l != -8) { c2ln(in, tin0, tin1, l + 8); tin0 ^= tout0; tin[0] = tin0; tin1 ^= tout1; tin[1] = tin1; des_encrypt((DES_LONG *)tin, schedule, DES_ENCRYPT); tout0 = tin[0]; l2c(tout0, out); tout1 = tin[1]; l2c(tout1, out); } iv = (unsigned char *)ivec; l2c(tout0, iv); l2c(tout1, iv); } else { c2l(iv, xor0); c2l(iv, xor1); for (l -= 8; l >= 0; l -= 8) { c2l(in, tin0); tin[0] = tin0; c2l(in, tin1); tin[1] = tin1; des_encrypt((DES_LONG *)tin, schedule, DES_DECRYPT); tout0 = tin[0] ^ xor0; tout1 = tin[1] ^ xor1; l2c(tout0, out); l2c(tout1, out); xor0 = tin0; xor1 = tin1; } if (l != -8) { c2l(in, tin0); tin[0] = tin0; c2l(in, tin1); tin[1] = tin1; des_encrypt((DES_LONG *)tin, schedule, DES_DECRYPT); tout0 = tin[0] ^ xor0; tout1 = tin[1] ^ xor1; l2cn(tout0, tout1, out, l + 8); xor0 = tin0; xor1 = tin1; } iv = (unsigned char *)ivec; l2c(xor0, iv); l2c(xor1, iv); } tin0 = tin1 = tout0 = tout1 = xor0 = xor1 = 0; tin[0] = tin[1] = 0; } void des_ede3_cbc_encrypt(input, output, length, ks1, ks2, ks3, ivec, enc) des_cblock(*input); des_cblock(*output); long length; des_key_schedule ks1; des_key_schedule ks2; des_key_schedule ks3; des_cblock(*ivec); int enc; { register DES_LONG tin0, tin1; register DES_LONG tout0, tout1, xor0, xor1; register unsigned char *in, *out; register long l = length; DES_LONG tin[2]; unsigned char *iv; in = (unsigned char *)input; out = (unsigned char *)output; iv = (unsigned char *)ivec; if (enc) { c2l(iv, tout0); c2l(iv, tout1); for (l -= 8; l >= 0; l -= 8) { c2l(in, tin0); c2l(in, tin1); tin0 ^= tout0; tin1 ^= tout1; tin[0] = tin0; tin[1] = tin1; des_encrypt3((DES_LONG *)tin, ks1, ks2, ks3); tout0 = tin[0]; tout1 = tin[1]; l2c(tout0, out); l2c(tout1, out); } if (l != -8) { c2ln(in, tin0, tin1, l + 8); tin0 ^= tout0; tin1 ^= tout1; tin[0] = tin0; tin[1] = tin1; des_encrypt3((DES_LONG *)tin, ks1, ks2, ks3); tout0 = tin[0]; tout1 = tin[1]; l2c(tout0, out); l2c(tout1, out); } iv = (unsigned char *)ivec; l2c(tout0, iv); l2c(tout1, iv); } else { register DES_LONG t0, t1; c2l(iv, xor0); c2l(iv, xor1); for (l -= 8; l >= 0; l -= 8) { c2l(in, tin0); c2l(in, tin1); t0 = tin0; t1 = tin1; tin[0] = tin0; tin[1] = tin1; des_decrypt3((DES_LONG *)tin, ks1, ks2, ks3); tout0 = tin[0]; tout1 = tin[1]; tout0 ^= xor0; tout1 ^= xor1; l2c(tout0, out); l2c(tout1, out); xor0 = t0; xor1 = t1; } if (l != -8) { c2l(in, tin0); c2l(in, tin1); t0 = tin0; t1 = tin1; tin[0] = tin0; tin[1] = tin1; des_decrypt3((DES_LONG *)tin, ks1, ks2, ks3); tout0 = tin[0]; tout1 = tin[1]; tout0 ^= xor0; tout1 ^= xor1; l2cn(tout0, tout1, out, l + 8); xor0 = t0; xor1 = t1; } iv = (unsigned char *)ivec; l2c(xor0, iv); l2c(xor1, iv); } tin0 = tin1 = tout0 = tout1 = xor0 = xor1 = 0; tin[0] = tin[1] = 0; } #endif /* DES_DEFAULT_OPTIONS */ libreswan-3.32/linux/net/ipsec/des/des_opts.c000066400000000000000000000371631365625662500212500ustar00rootroot00000000000000/* crypto/des/des_opts.c */ /* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@cryptsoft.com). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are adhered to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@cryptsoft.com). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * 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 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@cryptsoft.com)" * The word 'cryptographic' can be left out if the routines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ /* define PART1, PART2, PART3 or PART4 to build only with a few of the options. * This is for machines with 64k code segment size restrictions. */ #ifndef MSDOS #define TIMES #endif #include #ifndef MSDOS #include #else #include extern void exit(); #endif #include #ifndef VMS #ifndef _IRIX #include #endif #ifdef TIMES #include #include #endif #else /* VMS */ #include struct tms { time_t tms_utime; time_t tms_stime; time_t tms_uchild; /* I dunno... */ time_t tms_uchildsys; /* so these names are a guess :-) */ } #endif #ifndef TIMES #include #endif #ifdef sun #include #include #endif #include "des/des_locl.h" #include "des/spr.h" #define DES_DEFAULT_OPTIONS #if !defined(PART1) && !defined(PART2) && !defined(PART3) && !defined(PART4) #define PART1 #define PART2 #define PART3 #define PART4 #endif #ifdef PART1 #undef DES_UNROLL #undef DES_RISC1 #undef DES_RISC2 #undef DES_PTR #undef D_ENCRYPT #define des_encrypt des_encrypt_u4_cisc_idx #define des_encrypt2 des_encrypt2_u4_cisc_idx #define des_encrypt3 des_encrypt3_u4_cisc_idx #define des_decrypt3 des_decrypt3_u4_cisc_idx #undef HEADER_DES_LOCL_H #include "des_enc.c" #define DES_UNROLL #undef DES_RISC1 #undef DES_RISC2 #undef DES_PTR #undef D_ENCRYPT #undef des_encrypt #undef des_encrypt2 #undef des_encrypt3 #undef des_decrypt3 #define des_encrypt des_encrypt_u16_cisc_idx #define des_encrypt2 des_encrypt2_u16_cisc_idx #define des_encrypt3 des_encrypt3_u16_cisc_idx #define des_decrypt3 des_decrypt3_u16_cisc_idx #undef HEADER_DES_LOCL_H #include "des_enc.c" #undef DES_UNROLL #define DES_RISC1 #undef DES_RISC2 #undef DES_PTR #undef D_ENCRYPT #undef des_encrypt #undef des_encrypt2 #undef des_encrypt3 #undef des_decrypt3 #define des_encrypt des_encrypt_u4_risc1_idx #define des_encrypt2 des_encrypt2_u4_risc1_idx #define des_encrypt3 des_encrypt3_u4_risc1_idx #define des_decrypt3 des_decrypt3_u4_risc1_idx #undef HEADER_DES_LOCL_H #include "des_enc.c" #endif #ifdef PART2 #undef DES_UNROLL #undef DES_RISC1 #define DES_RISC2 #undef DES_PTR #undef D_ENCRYPT #undef des_encrypt #undef des_encrypt2 #undef des_encrypt3 #undef des_decrypt3 #define des_encrypt des_encrypt_u4_risc2_idx #define des_encrypt2 des_encrypt2_u4_risc2_idx #define des_encrypt3 des_encrypt3_u4_risc2_idx #define des_decrypt3 des_decrypt3_u4_risc2_idx #undef HEADER_DES_LOCL_H #include "des_enc.c" #define DES_UNROLL #define DES_RISC1 #undef DES_RISC2 #undef DES_PTR #undef D_ENCRYPT #undef des_encrypt #undef des_encrypt2 #undef des_encrypt3 #undef des_decrypt3 #define des_encrypt des_encrypt_u16_risc1_idx #define des_encrypt2 des_encrypt2_u16_risc1_idx #define des_encrypt3 des_encrypt3_u16_risc1_idx #define des_decrypt3 des_decrypt3_u16_risc1_idx #undef HEADER_DES_LOCL_H #include "des_enc.c" #define DES_UNROLL #undef DES_RISC1 #define DES_RISC2 #undef DES_PTR #undef D_ENCRYPT #undef des_encrypt #undef des_encrypt2 #undef des_encrypt3 #undef des_decrypt3 #define des_encrypt des_encrypt_u16_risc2_idx #define des_encrypt2 des_encrypt2_u16_risc2_idx #define des_encrypt3 des_encrypt3_u16_risc2_idx #define des_decrypt3 des_decrypt3_u16_risc2_idx #undef HEADER_DES_LOCL_H #include "des_enc.c" #endif #ifdef PART3 #undef DES_UNROLL #undef DES_RISC1 #undef DES_RISC2 #define DES_PTR #undef D_ENCRYPT #undef des_encrypt #undef des_encrypt2 #undef des_encrypt3 #undef des_decrypt3 #define des_encrypt des_encrypt_u4_cisc_ptr #define des_encrypt2 des_encrypt2_u4_cisc_ptr #define des_encrypt3 des_encrypt3_u4_cisc_ptr #define des_decrypt3 des_decrypt3_u4_cisc_ptr #undef HEADER_DES_LOCL_H #include "des_enc.c" #define DES_UNROLL #undef DES_RISC1 #undef DES_RISC2 #define DES_PTR #undef D_ENCRYPT #undef des_encrypt #undef des_encrypt2 #undef des_encrypt3 #undef des_decrypt3 #define des_encrypt des_encrypt_u16_cisc_ptr #define des_encrypt2 des_encrypt2_u16_cisc_ptr #define des_encrypt3 des_encrypt3_u16_cisc_ptr #define des_decrypt3 des_decrypt3_u16_cisc_ptr #undef HEADER_DES_LOCL_H #include "des_enc.c" #undef DES_UNROLL #define DES_RISC1 #undef DES_RISC2 #define DES_PTR #undef D_ENCRYPT #undef des_encrypt #undef des_encrypt2 #undef des_encrypt3 #undef des_decrypt3 #define des_encrypt des_encrypt_u4_risc1_ptr #define des_encrypt2 des_encrypt2_u4_risc1_ptr #define des_encrypt3 des_encrypt3_u4_risc1_ptr #define des_decrypt3 des_decrypt3_u4_risc1_ptr #undef HEADER_DES_LOCL_H #include "des_enc.c" #endif #ifdef PART4 #undef DES_UNROLL #undef DES_RISC1 #define DES_RISC2 #define DES_PTR #undef D_ENCRYPT #undef des_encrypt #undef des_encrypt2 #undef des_encrypt3 #undef des_decrypt3 #define des_encrypt des_encrypt_u4_risc2_ptr #define des_encrypt2 des_encrypt2_u4_risc2_ptr #define des_encrypt3 des_encrypt3_u4_risc2_ptr #define des_decrypt3 des_decrypt3_u4_risc2_ptr #undef HEADER_DES_LOCL_H #include "des_enc.c" #define DES_UNROLL #define DES_RISC1 #undef DES_RISC2 #define DES_PTR #undef D_ENCRYPT #undef des_encrypt #undef des_encrypt2 #undef des_encrypt3 #undef des_decrypt3 #define des_encrypt des_encrypt_u16_risc1_ptr #define des_encrypt2 des_encrypt2_u16_risc1_ptr #define des_encrypt3 des_encrypt3_u16_risc1_ptr #define des_decrypt3 des_decrypt3_u16_risc1_ptr #undef HEADER_DES_LOCL_H #include "des_enc.c" #define DES_UNROLL #undef DES_RISC1 #define DES_RISC2 #define DES_PTR #undef D_ENCRYPT #undef des_encrypt #undef des_encrypt2 #undef des_encrypt3 #undef des_decrypt3 #define des_encrypt des_encrypt_u16_risc2_ptr #define des_encrypt2 des_encrypt2_u16_risc2_ptr #define des_encrypt3 des_encrypt3_u16_risc2_ptr #define des_decrypt3 des_decrypt3_u16_risc2_ptr #undef HEADER_DES_LOCL_H #include "des_enc.c" #endif /* The following if from times(3) man page. It may need to be changed */ #ifndef HZ # ifndef CLK_TCK # ifndef _BSD_CLK_TCK_ /* FreeBSD fix */ # ifndef VMS # define HZ 100.0 # else /* VMS */ # define HZ 100.0 # endif # else /* _BSD_CLK_TCK_ */ # define HZ ((double)_BSD_CLK_TCK_) # endif # else /* CLK_TCK */ # define HZ ((double)CLK_TCK) # endif #endif #define BUFSIZE ((long)1024) long run = 0; #ifndef NOPROTO double Time_F(int s); #else double Time_F(); #endif #ifdef SIGALRM #if defined(__STDC__) || defined(sgi) #define SIGRETTYPE void #else #define SIGRETTYPE int #endif #ifndef NOPROTO SIGRETTYPE sig_done(int sig); #else SIGRETTYPE sig_done(); #endif SIGRETTYPE sig_done(sig) int sig; { signal(SIGALRM, sig_done); run = 0; #ifdef LINT sig = sig; #endif } #endif #define START 0 #define STOP 1 double Time_F(s) int s; { double ret; #ifdef TIMES static struct tms tstart, tend; if (s == START) { times(&tstart); return 0; } else { times(&tend); ret = ((double)(tend.tms_utime - tstart.tms_utime)) / HZ; return (ret == 0.0) ? 1e-6 : ret; } #else /* !times() */ static struct timeb tstart, tend; long i; if (s == START) { ftime(&tstart); return 0; } else { ftime(&tend); i = (long)tend.millitm - (long)tstart.millitm; ret = (double)(tend.time - tstart.time) + (double)i / 1000.0; return (ret == 0.0) ? 1e-6 : ret; } #endif } #ifdef SIGALRM #define print_name(name) fprintf(stderr, "Doing %s's for 10 seconds\n", name); \ alarm(10); #else #define print_name(name) fprintf(stderr, "Doing %s %ld times\n", name, cb); #endif #define time_it(func, name, index) \ print_name(name); \ Time_F(START); \ for (count = 0, run = 1; COND(cb); count++) \ { \ unsigned long d[2]; \ func(d, &(sch[0]), DES_ENCRYPT); \ } \ tm[index] = Time_F(STOP); \ fprintf(stderr, "%ld %s's in %.2f second\n", count, name, tm[index]); \ tm[index] = ((double)COUNT(cb)) / tm[index]; #define print_it(name, index) \ fprintf(stderr, "%s bytes per sec = %12.2f (%5.1fuS)\n", name, \ tm[index] * 8, 1.0e6 / tm[index]); int main(argc, argv) int argc; char **argv; { long count; static unsigned char buf[BUFSIZE]; static des_cblock key = { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 }; static des_cblock key2 = { 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12 }; static des_cblock key3 = { 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34 }; des_key_schedule sch, sch2, sch3; double d, tm[16], max = 0; int rank[16]; char *str[16]; int max_idx = 0, i, num = 0, j; #ifndef SIGALARM long ca, cb, cc, cd, ce; #endif for (i = 0; i < 12; i++) { tm[i] = 0.0; rank[i] = 0; } #ifndef TIMES fprintf(stderr, "To get the most acurate results, try to run this\n"); fprintf(stderr, "program when this computer is idle.\n"); #endif des_set_key((C_Block *)key, sch); des_set_key((C_Block *)key2, sch2); des_set_key((C_Block *)key3, sch3); #ifndef SIGALRM fprintf(stderr, "First we calculate the approximate speed ...\n"); des_set_key((C_Block *)key, sch); count = 10; do { long i; unsigned long data[2]; count *= 2; Time_F(START); for (i = count; i; i--) des_encrypt(data, &(sch[0]), DES_ENCRYPT); d = Time_F(STOP); } while (d < 3.0); ca = count; cb = count * 3; cc = count * 3 * 8 / BUFSIZE + 1; cd = count * 8 / BUFSIZE + 1; ce = count / 20 + 1; #define COND(d) (count != (d)) #define COUNT(d) (d) #else #define COND(c) (run) #define COUNT(d) (count) signal(SIGALRM, sig_done); alarm(10); #endif #ifdef PART1 time_it(des_encrypt_u4_cisc_idx, "des_encrypt_u4_cisc_idx ", 0); time_it(des_encrypt_u16_cisc_idx, "des_encrypt_u16_cisc_idx ", 1); time_it(des_encrypt_u4_risc1_idx, "des_encrypt_u4_risc1_idx ", 2); num += 3; #endif #ifdef PART2 time_it(des_encrypt_u16_risc1_idx, "des_encrypt_u16_risc1_idx", 3); time_it(des_encrypt_u4_risc2_idx, "des_encrypt_u4_risc2_idx ", 4); time_it(des_encrypt_u16_risc2_idx, "des_encrypt_u16_risc2_idx", 5); num += 3; #endif #ifdef PART3 time_it(des_encrypt_u4_cisc_ptr, "des_encrypt_u4_cisc_ptr ", 6); time_it(des_encrypt_u16_cisc_ptr, "des_encrypt_u16_cisc_ptr ", 7); time_it(des_encrypt_u4_risc1_ptr, "des_encrypt_u4_risc1_ptr ", 8); num += 3; #endif #ifdef PART4 time_it(des_encrypt_u16_risc1_ptr, "des_encrypt_u16_risc1_ptr", 9); time_it(des_encrypt_u4_risc2_ptr, "des_encrypt_u4_risc2_ptr ", 10); time_it(des_encrypt_u16_risc2_ptr, "des_encrypt_u16_risc2_ptr", 11); num += 3; #endif #ifdef PART1 str[0] = " 4 c i"; print_it("des_encrypt_u4_cisc_idx ", 0); max = tm[0]; max_idx = 0; str[1] = "16 c i"; print_it("des_encrypt_u16_cisc_idx ", 1); if (max < tm[1]) { max = tm[1]; max_idx = 1; } str[2] = " 4 r1 i"; print_it("des_encrypt_u4_risc1_idx ", 2); if (max < tm[2]) { max = tm[2]; max_idx = 2; } #endif #ifdef PART2 str[3] = "16 r1 i"; print_it("des_encrypt_u16_risc1_idx", 3); if (max < tm[3]) { max = tm[3]; max_idx = 3; } str[4] = " 4 r2 i"; print_it("des_encrypt_u4_risc2_idx ", 4); if (max < tm[4]) { max = tm[4]; max_idx = 4; } str[5] = "16 r2 i"; print_it("des_encrypt_u16_risc2_idx", 5); if (max < tm[5]) { max = tm[5]; max_idx = 5; } #endif #ifdef PART3 str[6] = " 4 c p"; print_it("des_encrypt_u4_cisc_ptr ", 6); if (max < tm[6]) { max = tm[6]; max_idx = 6; } str[7] = "16 c p"; print_it("des_encrypt_u16_cisc_ptr ", 7); if (max < tm[7]) { max = tm[7]; max_idx = 7; } str[8] = " 4 r1 p"; print_it("des_encrypt_u4_risc1_ptr ", 8); if (max < tm[8]) { max = tm[8]; max_idx = 8; } #endif #ifdef PART4 str[9] = "16 r1 p"; print_it("des_encrypt_u16_risc1_ptr", 9); if (max < tm[9]) { max = tm[9]; max_idx = 9; } str[10] = " 4 r2 p"; print_it("des_encrypt_u4_risc2_ptr ", 10); if (max < tm[10]) { max = tm[10]; max_idx = 10; } str[11] = "16 r2 p"; print_it("des_encrypt_u16_risc2_ptr", 11); if (max < tm[11]) { max = tm[11]; max_idx = 11; } #endif printf("options des ecb/s\n"); printf("%s %12.2f 100.0%%\n", str[max_idx], tm[max_idx]); d = tm[max_idx]; tm[max_idx] = -2.0; max = -1.0; for (;; ) { for (i = 0; i < 12; i++) if (max < tm[i]) { max = tm[i]; j = i; } if (max < 0.0) break; printf("%s %12.2f %4.1f%%\n", str[j], tm[j], tm[j] / d * 100.0); tm[j] = -2.0; max = -1.0; } switch (max_idx) { case 0: printf("-DDES_DEFAULT_OPTIONS\n"); break; case 1: printf("-DDES_UNROLL\n"); break; case 2: printf("-DDES_RISC1\n"); break; case 3: printf("-DDES_UNROLL -DDES_RISC1\n"); break; case 4: printf("-DDES_RISC2\n"); break; case 5: printf("-DDES_UNROLL -DDES_RISC2\n"); break; case 6: printf("-DDES_PTR\n"); break; case 7: printf("-DDES_UNROLL -DDES_PTR\n"); break; case 8: printf("-DDES_RISC1 -DDES_PTR\n"); break; case 9: printf("-DDES_UNROLL -DDES_RISC1 -DDES_PTR\n"); break; case 10: printf("-DDES_RISC2 -DDES_PTR\n"); break; case 11: printf("-DDES_UNROLL -DDES_RISC2 -DDES_PTR\n"); break; } exit(0); #if defined(LINT) || defined(MSDOS) return 0; #endif } libreswan-3.32/linux/net/ipsec/des/dx86unix.S000066400000000000000000001732561365625662500211110ustar00rootroot00000000000000/* * This file was originally generated by Michael Richardson * via the perl scripts found in the ASM subdir. It remains copyright of * Eric Young, see the file COPYRIGHT. * * This was last done on October 9, 2002. * * While this file does not need to go through cpp, we pass it through * CPP by naming it dx86unix.S instead of dx86unix.s because there is * a bug in Rules.make for .s builds - specifically it references EXTRA_CFLAGS * which may contain stuff that AS doesn't understand instead of * referencing EXTRA_AFLAGS. */ .file "dx86unix.S" .version "01.01" .text .align 16 .globl des_encrypt .type des_encrypt , @function des_encrypt: pushl %esi pushl %edi movl 12(%esp), %esi xorl %ecx, %ecx pushl %ebx pushl %ebp movl (%esi), %eax movl 28(%esp), %ebx movl 4(%esi), %edi roll $4, %eax movl %eax, %esi xorl %edi, %eax andl $0xf0f0f0f0, %eax xorl %eax, %esi xorl %eax, %edi roll $20, %edi movl %edi, %eax xorl %esi, %edi andl $0xfff0000f, %edi xorl %edi, %eax xorl %edi, %esi roll $14, %eax movl %eax, %edi xorl %esi, %eax andl $0x33333333, %eax xorl %eax, %edi xorl %eax, %esi roll $22, %esi movl %esi, %eax xorl %edi, %esi andl $0x03fc03fc, %esi xorl %esi, %eax xorl %esi, %edi roll $9, %eax movl %eax, %esi xorl %edi, %eax andl $0xaaaaaaaa, %eax xorl %eax, %esi xorl %eax, %edi .byte 209 .byte 199 movl 24(%esp), %ebp cmpl $0, %ebx je .L000start_decrypt movl (%ebp), %eax xorl %ebx, %ebx movl 4(%ebp), %edx xorl %esi, %eax xorl %esi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %edi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %edi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %edi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %edi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %edi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %edi movl 8(%ebp), %eax xorl %ebx, %ebx movl 12(%ebp), %edx xorl %edi, %eax xorl %edi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %esi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %esi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %esi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %esi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %esi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %esi movl 16(%ebp), %eax xorl %ebx, %ebx movl 20(%ebp), %edx xorl %esi, %eax xorl %esi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %edi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %edi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %edi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %edi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %edi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %edi movl 24(%ebp), %eax xorl %ebx, %ebx movl 28(%ebp), %edx xorl %edi, %eax xorl %edi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %esi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %esi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %esi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %esi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %esi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %esi movl 32(%ebp), %eax xorl %ebx, %ebx movl 36(%ebp), %edx xorl %esi, %eax xorl %esi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %edi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %edi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %edi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %edi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %edi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %edi movl 40(%ebp), %eax xorl %ebx, %ebx movl 44(%ebp), %edx xorl %edi, %eax xorl %edi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %esi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %esi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %esi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %esi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %esi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %esi movl 48(%ebp), %eax xorl %ebx, %ebx movl 52(%ebp), %edx xorl %esi, %eax xorl %esi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %edi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %edi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %edi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %edi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %edi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %edi movl 56(%ebp), %eax xorl %ebx, %ebx movl 60(%ebp), %edx xorl %edi, %eax xorl %edi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %esi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %esi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %esi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %esi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %esi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %esi movl 64(%ebp), %eax xorl %ebx, %ebx movl 68(%ebp), %edx xorl %esi, %eax xorl %esi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %edi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %edi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %edi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %edi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %edi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %edi movl 72(%ebp), %eax xorl %ebx, %ebx movl 76(%ebp), %edx xorl %edi, %eax xorl %edi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %esi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %esi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %esi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %esi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %esi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %esi movl 80(%ebp), %eax xorl %ebx, %ebx movl 84(%ebp), %edx xorl %esi, %eax xorl %esi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %edi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %edi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %edi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %edi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %edi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %edi movl 88(%ebp), %eax xorl %ebx, %ebx movl 92(%ebp), %edx xorl %edi, %eax xorl %edi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %esi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %esi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %esi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %esi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %esi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %esi movl 96(%ebp), %eax xorl %ebx, %ebx movl 100(%ebp), %edx xorl %esi, %eax xorl %esi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %edi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %edi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %edi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %edi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %edi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %edi movl 104(%ebp), %eax xorl %ebx, %ebx movl 108(%ebp), %edx xorl %edi, %eax xorl %edi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %esi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %esi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %esi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %esi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %esi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %esi movl 112(%ebp), %eax xorl %ebx, %ebx movl 116(%ebp), %edx xorl %esi, %eax xorl %esi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %edi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %edi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %edi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %edi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %edi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %edi movl 120(%ebp), %eax xorl %ebx, %ebx movl 124(%ebp), %edx xorl %edi, %eax xorl %edi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %esi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %esi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %esi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %esi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %esi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %esi jmp .L001end .L000start_decrypt: movl 120(%ebp), %eax xorl %ebx, %ebx movl 124(%ebp), %edx xorl %esi, %eax xorl %esi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %edi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %edi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %edi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %edi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %edi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %edi movl 112(%ebp), %eax xorl %ebx, %ebx movl 116(%ebp), %edx xorl %edi, %eax xorl %edi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %esi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %esi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %esi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %esi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %esi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %esi movl 104(%ebp), %eax xorl %ebx, %ebx movl 108(%ebp), %edx xorl %esi, %eax xorl %esi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %edi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %edi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %edi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %edi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %edi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %edi movl 96(%ebp), %eax xorl %ebx, %ebx movl 100(%ebp), %edx xorl %edi, %eax xorl %edi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %esi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %esi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %esi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %esi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %esi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %esi movl 88(%ebp), %eax xorl %ebx, %ebx movl 92(%ebp), %edx xorl %esi, %eax xorl %esi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %edi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %edi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %edi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %edi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %edi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %edi movl 80(%ebp), %eax xorl %ebx, %ebx movl 84(%ebp), %edx xorl %edi, %eax xorl %edi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %esi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %esi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %esi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %esi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %esi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %esi movl 72(%ebp), %eax xorl %ebx, %ebx movl 76(%ebp), %edx xorl %esi, %eax xorl %esi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %edi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %edi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %edi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %edi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %edi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %edi movl 64(%ebp), %eax xorl %ebx, %ebx movl 68(%ebp), %edx xorl %edi, %eax xorl %edi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %esi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %esi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %esi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %esi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %esi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %esi movl 56(%ebp), %eax xorl %ebx, %ebx movl 60(%ebp), %edx xorl %esi, %eax xorl %esi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %edi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %edi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %edi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %edi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %edi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %edi movl 48(%ebp), %eax xorl %ebx, %ebx movl 52(%ebp), %edx xorl %edi, %eax xorl %edi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %esi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %esi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %esi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %esi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %esi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %esi movl 40(%ebp), %eax xorl %ebx, %ebx movl 44(%ebp), %edx xorl %esi, %eax xorl %esi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %edi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %edi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %edi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %edi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %edi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %edi movl 32(%ebp), %eax xorl %ebx, %ebx movl 36(%ebp), %edx xorl %edi, %eax xorl %edi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %esi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %esi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %esi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %esi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %esi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %esi movl 24(%ebp), %eax xorl %ebx, %ebx movl 28(%ebp), %edx xorl %esi, %eax xorl %esi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %edi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %edi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %edi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %edi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %edi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %edi movl 16(%ebp), %eax xorl %ebx, %ebx movl 20(%ebp), %edx xorl %edi, %eax xorl %edi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %esi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %esi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %esi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %esi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %esi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %esi movl 8(%ebp), %eax xorl %ebx, %ebx movl 12(%ebp), %edx xorl %esi, %eax xorl %esi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %edi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %edi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %edi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %edi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %edi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %edi movl (%ebp), %eax xorl %ebx, %ebx movl 4(%ebp), %edx xorl %edi, %eax xorl %edi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %esi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %esi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %esi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %esi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %esi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %esi .L001end: movl 20(%esp), %edx .byte 209 .byte 206 movl %edi, %eax xorl %esi, %edi andl $0xaaaaaaaa, %edi xorl %edi, %eax xorl %edi, %esi roll $23, %eax movl %eax, %edi xorl %esi, %eax andl $0x03fc03fc, %eax xorl %eax, %edi xorl %eax, %esi roll $10, %edi movl %edi, %eax xorl %esi, %edi andl $0x33333333, %edi xorl %edi, %eax xorl %edi, %esi roll $18, %esi movl %esi, %edi xorl %eax, %esi andl $0xfff0000f, %esi xorl %esi, %edi xorl %esi, %eax roll $12, %edi movl %edi, %esi xorl %eax, %edi andl $0xf0f0f0f0, %edi xorl %edi, %esi xorl %edi, %eax rorl $4, %eax movl %eax, (%edx) movl %esi, 4(%edx) popl %ebp popl %ebx popl %edi popl %esi ret .des_encrypt_end: .size des_encrypt , .des_encrypt_end-des_encrypt .ident "desasm.pl" .text .align 16 .globl des_encrypt2 .type des_encrypt2 , @function des_encrypt2: pushl %esi pushl %edi movl 12(%esp), %eax xorl %ecx, %ecx pushl %ebx pushl %ebp movl (%eax), %esi movl 28(%esp), %ebx roll $3, %esi movl 4(%eax), %edi roll $3, %edi movl 24(%esp), %ebp cmpl $0, %ebx je .L002start_decrypt movl (%ebp), %eax xorl %ebx, %ebx movl 4(%ebp), %edx xorl %esi, %eax xorl %esi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %edi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %edi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %edi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %edi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %edi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %edi movl 8(%ebp), %eax xorl %ebx, %ebx movl 12(%ebp), %edx xorl %edi, %eax xorl %edi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %esi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %esi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %esi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %esi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %esi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %esi movl 16(%ebp), %eax xorl %ebx, %ebx movl 20(%ebp), %edx xorl %esi, %eax xorl %esi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %edi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %edi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %edi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %edi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %edi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %edi movl 24(%ebp), %eax xorl %ebx, %ebx movl 28(%ebp), %edx xorl %edi, %eax xorl %edi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %esi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %esi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %esi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %esi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %esi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %esi movl 32(%ebp), %eax xorl %ebx, %ebx movl 36(%ebp), %edx xorl %esi, %eax xorl %esi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %edi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %edi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %edi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %edi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %edi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %edi movl 40(%ebp), %eax xorl %ebx, %ebx movl 44(%ebp), %edx xorl %edi, %eax xorl %edi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %esi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %esi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %esi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %esi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %esi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %esi movl 48(%ebp), %eax xorl %ebx, %ebx movl 52(%ebp), %edx xorl %esi, %eax xorl %esi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %edi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %edi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %edi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %edi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %edi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %edi movl 56(%ebp), %eax xorl %ebx, %ebx movl 60(%ebp), %edx xorl %edi, %eax xorl %edi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %esi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %esi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %esi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %esi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %esi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %esi movl 64(%ebp), %eax xorl %ebx, %ebx movl 68(%ebp), %edx xorl %esi, %eax xorl %esi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %edi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %edi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %edi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %edi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %edi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %edi movl 72(%ebp), %eax xorl %ebx, %ebx movl 76(%ebp), %edx xorl %edi, %eax xorl %edi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %esi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %esi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %esi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %esi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %esi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %esi movl 80(%ebp), %eax xorl %ebx, %ebx movl 84(%ebp), %edx xorl %esi, %eax xorl %esi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %edi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %edi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %edi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %edi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %edi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %edi movl 88(%ebp), %eax xorl %ebx, %ebx movl 92(%ebp), %edx xorl %edi, %eax xorl %edi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %esi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %esi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %esi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %esi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %esi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %esi movl 96(%ebp), %eax xorl %ebx, %ebx movl 100(%ebp), %edx xorl %esi, %eax xorl %esi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %edi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %edi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %edi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %edi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %edi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %edi movl 104(%ebp), %eax xorl %ebx, %ebx movl 108(%ebp), %edx xorl %edi, %eax xorl %edi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %esi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %esi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %esi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %esi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %esi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %esi movl 112(%ebp), %eax xorl %ebx, %ebx movl 116(%ebp), %edx xorl %esi, %eax xorl %esi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %edi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %edi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %edi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %edi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %edi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %edi movl 120(%ebp), %eax xorl %ebx, %ebx movl 124(%ebp), %edx xorl %edi, %eax xorl %edi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %esi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %esi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %esi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %esi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %esi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %esi jmp .L003end .L002start_decrypt: movl 120(%ebp), %eax xorl %ebx, %ebx movl 124(%ebp), %edx xorl %esi, %eax xorl %esi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %edi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %edi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %edi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %edi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %edi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %edi movl 112(%ebp), %eax xorl %ebx, %ebx movl 116(%ebp), %edx xorl %edi, %eax xorl %edi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %esi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %esi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %esi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %esi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %esi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %esi movl 104(%ebp), %eax xorl %ebx, %ebx movl 108(%ebp), %edx xorl %esi, %eax xorl %esi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %edi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %edi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %edi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %edi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %edi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %edi movl 96(%ebp), %eax xorl %ebx, %ebx movl 100(%ebp), %edx xorl %edi, %eax xorl %edi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %esi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %esi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %esi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %esi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %esi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %esi movl 88(%ebp), %eax xorl %ebx, %ebx movl 92(%ebp), %edx xorl %esi, %eax xorl %esi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %edi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %edi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %edi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %edi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %edi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %edi movl 80(%ebp), %eax xorl %ebx, %ebx movl 84(%ebp), %edx xorl %edi, %eax xorl %edi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %esi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %esi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %esi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %esi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %esi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %esi movl 72(%ebp), %eax xorl %ebx, %ebx movl 76(%ebp), %edx xorl %esi, %eax xorl %esi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %edi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %edi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %edi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %edi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %edi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %edi movl 64(%ebp), %eax xorl %ebx, %ebx movl 68(%ebp), %edx xorl %edi, %eax xorl %edi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %esi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %esi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %esi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %esi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %esi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %esi movl 56(%ebp), %eax xorl %ebx, %ebx movl 60(%ebp), %edx xorl %esi, %eax xorl %esi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %edi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %edi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %edi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %edi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %edi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %edi movl 48(%ebp), %eax xorl %ebx, %ebx movl 52(%ebp), %edx xorl %edi, %eax xorl %edi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %esi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %esi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %esi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %esi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %esi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %esi movl 40(%ebp), %eax xorl %ebx, %ebx movl 44(%ebp), %edx xorl %esi, %eax xorl %esi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %edi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %edi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %edi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %edi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %edi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %edi movl 32(%ebp), %eax xorl %ebx, %ebx movl 36(%ebp), %edx xorl %edi, %eax xorl %edi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %esi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %esi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %esi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %esi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %esi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %esi movl 24(%ebp), %eax xorl %ebx, %ebx movl 28(%ebp), %edx xorl %esi, %eax xorl %esi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %edi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %edi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %edi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %edi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %edi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %edi movl 16(%ebp), %eax xorl %ebx, %ebx movl 20(%ebp), %edx xorl %edi, %eax xorl %edi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %esi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %esi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %esi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %esi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %esi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %esi movl 8(%ebp), %eax xorl %ebx, %ebx movl 12(%ebp), %edx xorl %esi, %eax xorl %esi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %edi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %edi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %edi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %edi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %edi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %edi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %edi movl (%ebp), %eax xorl %ebx, %ebx movl 4(%ebp), %edx xorl %edi, %eax xorl %edi, %edx andl $0xfcfcfcfc, %eax andl $0xcfcfcfcf, %edx movb %al, %bl movb %ah, %cl rorl $4, %edx movl des_SPtrans(%ebx),%ebp movb %dl, %bl xorl %ebp, %esi movl 0x200+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movb %dh, %cl shrl $16, %eax movl 0x100+des_SPtrans(%ebx),%ebp xorl %ebp, %esi movb %ah, %bl shrl $16, %edx movl 0x300+des_SPtrans(%ecx),%ebp xorl %ebp, %esi movl 24(%esp), %ebp movb %dh, %cl andl $0xff, %eax andl $0xff, %edx movl 0x600+des_SPtrans(%ebx),%ebx xorl %ebx, %esi movl 0x700+des_SPtrans(%ecx),%ebx xorl %ebx, %esi movl 0x400+des_SPtrans(%eax),%ebx xorl %ebx, %esi movl 0x500+des_SPtrans(%edx),%ebx xorl %ebx, %esi .L003end: rorl $3, %edi movl 20(%esp), %eax rorl $3, %esi movl %edi, (%eax) movl %esi, 4(%eax) popl %ebp popl %ebx popl %edi popl %esi ret .des_encrypt2_end: .size des_encrypt2 , .des_encrypt2_end-des_encrypt2 .ident "desasm.pl" .text .align 16 .globl des_encrypt3 .type des_encrypt3 , @function des_encrypt3: pushl %ebx movl 8(%esp), %ebx pushl %ebp pushl %esi pushl %edi movl (%ebx), %edi movl 4(%ebx), %esi subl $12, %esp roll $4, %edi movl %edi, %edx xorl %esi, %edi andl $0xf0f0f0f0, %edi xorl %edi, %edx xorl %edi, %esi roll $20, %esi movl %esi, %edi xorl %edx, %esi andl $0xfff0000f, %esi xorl %esi, %edi xorl %esi, %edx roll $14, %edi movl %edi, %esi xorl %edx, %edi andl $0x33333333, %edi xorl %edi, %esi xorl %edi, %edx roll $22, %edx movl %edx, %edi xorl %esi, %edx andl $0x03fc03fc, %edx xorl %edx, %edi xorl %edx, %esi roll $9, %edi movl %edi, %edx xorl %esi, %edi andl $0xaaaaaaaa, %edi xorl %edi, %edx xorl %edi, %esi rorl $3, %edx rorl $2, %esi movl %esi, 4(%ebx) movl 36(%esp), %eax movl %edx, (%ebx) movl 40(%esp), %edi movl 44(%esp), %esi movl $1, 8(%esp) movl %eax, 4(%esp) movl %ebx, (%esp) call des_encrypt2 movl $0, 8(%esp) movl %edi, 4(%esp) movl %ebx, (%esp) call des_encrypt2 movl $1, 8(%esp) movl %esi, 4(%esp) movl %ebx, (%esp) call des_encrypt2 addl $12, %esp movl (%ebx), %edi movl 4(%ebx), %esi roll $2, %esi roll $3, %edi movl %edi, %eax xorl %esi, %edi andl $0xaaaaaaaa, %edi xorl %edi, %eax xorl %edi, %esi roll $23, %eax movl %eax, %edi xorl %esi, %eax andl $0x03fc03fc, %eax xorl %eax, %edi xorl %eax, %esi roll $10, %edi movl %edi, %eax xorl %esi, %edi andl $0x33333333, %edi xorl %edi, %eax xorl %edi, %esi roll $18, %esi movl %esi, %edi xorl %eax, %esi andl $0xfff0000f, %esi xorl %esi, %edi xorl %esi, %eax roll $12, %edi movl %edi, %esi xorl %eax, %edi andl $0xf0f0f0f0, %edi xorl %edi, %esi xorl %edi, %eax rorl $4, %eax movl %eax, (%ebx) movl %esi, 4(%ebx) popl %edi popl %esi popl %ebp popl %ebx ret .des_encrypt3_end: .size des_encrypt3 , .des_encrypt3_end-des_encrypt3 .ident "desasm.pl" .text .align 16 .globl des_decrypt3 .type des_decrypt3 , @function des_decrypt3: pushl %ebx movl 8(%esp), %ebx pushl %ebp pushl %esi pushl %edi movl (%ebx), %edi movl 4(%ebx), %esi subl $12, %esp roll $4, %edi movl %edi, %edx xorl %esi, %edi andl $0xf0f0f0f0, %edi xorl %edi, %edx xorl %edi, %esi roll $20, %esi movl %esi, %edi xorl %edx, %esi andl $0xfff0000f, %esi xorl %esi, %edi xorl %esi, %edx roll $14, %edi movl %edi, %esi xorl %edx, %edi andl $0x33333333, %edi xorl %edi, %esi xorl %edi, %edx roll $22, %edx movl %edx, %edi xorl %esi, %edx andl $0x03fc03fc, %edx xorl %edx, %edi xorl %edx, %esi roll $9, %edi movl %edi, %edx xorl %esi, %edi andl $0xaaaaaaaa, %edi xorl %edi, %edx xorl %edi, %esi rorl $3, %edx rorl $2, %esi movl %esi, 4(%ebx) movl 36(%esp), %esi movl %edx, (%ebx) movl 40(%esp), %edi movl 44(%esp), %eax movl $0, 8(%esp) movl %eax, 4(%esp) movl %ebx, (%esp) call des_encrypt2 movl $1, 8(%esp) movl %edi, 4(%esp) movl %ebx, (%esp) call des_encrypt2 movl $0, 8(%esp) movl %esi, 4(%esp) movl %ebx, (%esp) call des_encrypt2 addl $12, %esp movl (%ebx), %edi movl 4(%ebx), %esi roll $2, %esi roll $3, %edi movl %edi, %eax xorl %esi, %edi andl $0xaaaaaaaa, %edi xorl %edi, %eax xorl %edi, %esi roll $23, %eax movl %eax, %edi xorl %esi, %eax andl $0x03fc03fc, %eax xorl %eax, %edi xorl %eax, %esi roll $10, %edi movl %edi, %eax xorl %esi, %edi andl $0x33333333, %edi xorl %edi, %eax xorl %edi, %esi roll $18, %esi movl %esi, %edi xorl %eax, %esi andl $0xfff0000f, %esi xorl %esi, %edi xorl %esi, %eax roll $12, %edi movl %edi, %esi xorl %eax, %edi andl $0xf0f0f0f0, %edi xorl %edi, %esi xorl %edi, %eax rorl $4, %eax movl %eax, (%ebx) movl %esi, 4(%ebx) popl %edi popl %esi popl %ebp popl %ebx ret .des_decrypt3_end: .size des_decrypt3 , .des_decrypt3_end-des_decrypt3 .ident "desasm.pl" .text .align 16 .globl des_ncbc_encrypt .type des_ncbc_encrypt , @function des_ncbc_encrypt: pushl %ebp pushl %ebx pushl %esi pushl %edi movl 28(%esp), %ebp movl 36(%esp), %ebx movl (%ebx), %esi movl 4(%ebx), %edi pushl %edi pushl %esi pushl %edi pushl %esi movl %esp, %ebx movl 36(%esp), %esi movl 40(%esp), %edi movl 56(%esp), %ecx pushl %ecx movl 52(%esp), %eax pushl %eax pushl %ebx cmpl $0, %ecx jz .L004decrypt andl $4294967288, %ebp movl 12(%esp), %eax movl 16(%esp), %ebx jz .L005encrypt_finish .L006encrypt_loop: movl (%esi), %ecx movl 4(%esi), %edx xorl %ecx, %eax xorl %edx, %ebx movl %eax, 12(%esp) movl %ebx, 16(%esp) call des_encrypt movl 12(%esp), %eax movl 16(%esp), %ebx movl %eax, (%edi) movl %ebx, 4(%edi) addl $8, %esi addl $8, %edi subl $8, %ebp jnz .L006encrypt_loop .L005encrypt_finish: movl 56(%esp), %ebp andl $7, %ebp jz .L007finish xorl %ecx, %ecx xorl %edx, %edx movl .L008cbc_enc_jmp_table(,%ebp,4),%ebp jmp *%ebp .L009ej7: movb 6(%esi), %dh sall $8, %edx .L010ej6: movb 5(%esi), %dh .L011ej5: movb 4(%esi), %dl .L012ej4: movl (%esi), %ecx jmp .L013ejend .L014ej3: movb 2(%esi), %ch sall $8, %ecx .L015ej2: movb 1(%esi), %ch .L016ej1: movb (%esi), %cl .L013ejend: xorl %ecx, %eax xorl %edx, %ebx movl %eax, 12(%esp) movl %ebx, 16(%esp) call des_encrypt movl 12(%esp), %eax movl 16(%esp), %ebx movl %eax, (%edi) movl %ebx, 4(%edi) jmp .L007finish .align 16 .L004decrypt: andl $4294967288, %ebp movl 20(%esp), %eax movl 24(%esp), %ebx jz .L017decrypt_finish .L018decrypt_loop: movl (%esi), %eax movl 4(%esi), %ebx movl %eax, 12(%esp) movl %ebx, 16(%esp) call des_encrypt movl 12(%esp), %eax movl 16(%esp), %ebx movl 20(%esp), %ecx movl 24(%esp), %edx xorl %eax, %ecx xorl %ebx, %edx movl (%esi), %eax movl 4(%esi), %ebx movl %ecx, (%edi) movl %edx, 4(%edi) movl %eax, 20(%esp) movl %ebx, 24(%esp) addl $8, %esi addl $8, %edi subl $8, %ebp jnz .L018decrypt_loop .L017decrypt_finish: movl 56(%esp), %ebp andl $7, %ebp jz .L007finish movl (%esi), %eax movl 4(%esi), %ebx movl %eax, 12(%esp) movl %ebx, 16(%esp) call des_encrypt movl 12(%esp), %eax movl 16(%esp), %ebx movl 20(%esp), %ecx movl 24(%esp), %edx xorl %eax, %ecx xorl %ebx, %edx movl (%esi), %eax movl 4(%esi), %ebx .L019dj7: rorl $16, %edx movb %dl, 6(%edi) shrl $16, %edx .L020dj6: movb %dh, 5(%edi) .L021dj5: movb %dl, 4(%edi) .L022dj4: movl %ecx, (%edi) jmp .L023djend .L024dj3: rorl $16, %ecx movb %cl, 2(%edi) sall $16, %ecx .L025dj2: movb %ch, 1(%esi) .L026dj1: movb %cl, (%esi) .L023djend: jmp .L007finish .align 16 .L007finish: movl 64(%esp), %ecx addl $28, %esp movl %eax, (%ecx) movl %ebx, 4(%ecx) popl %edi popl %esi popl %ebx popl %ebp ret .align 16 .L008cbc_enc_jmp_table: .long 0 .long .L016ej1 .long .L015ej2 .long .L014ej3 .long .L012ej4 .long .L011ej5 .long .L010ej6 .long .L009ej7 .align 16 .L027cbc_dec_jmp_table: .long 0 .long .L026dj1 .long .L025dj2 .long .L024dj3 .long .L022dj4 .long .L021dj5 .long .L020dj6 .long .L019dj7 .des_ncbc_encrypt_end: .size des_ncbc_encrypt , .des_ncbc_encrypt_end-des_ncbc_encrypt .ident "desasm.pl" .text .align 16 .globl des_ede3_cbc_encrypt .type des_ede3_cbc_encrypt , @function des_ede3_cbc_encrypt: pushl %ebp pushl %ebx pushl %esi pushl %edi movl 28(%esp), %ebp movl 44(%esp), %ebx movl (%ebx), %esi movl 4(%ebx), %edi pushl %edi pushl %esi pushl %edi pushl %esi movl %esp, %ebx movl 36(%esp), %esi movl 40(%esp), %edi movl 64(%esp), %ecx movl 56(%esp), %eax pushl %eax movl 56(%esp), %eax pushl %eax movl 56(%esp), %eax pushl %eax pushl %ebx cmpl $0, %ecx jz .L028decrypt andl $4294967288, %ebp movl 16(%esp), %eax movl 20(%esp), %ebx jz .L029encrypt_finish .L030encrypt_loop: movl (%esi), %ecx movl 4(%esi), %edx xorl %ecx, %eax xorl %edx, %ebx movl %eax, 16(%esp) movl %ebx, 20(%esp) call des_encrypt3 movl 16(%esp), %eax movl 20(%esp), %ebx movl %eax, (%edi) movl %ebx, 4(%edi) addl $8, %esi addl $8, %edi subl $8, %ebp jnz .L030encrypt_loop .L029encrypt_finish: movl 60(%esp), %ebp andl $7, %ebp jz .L031finish xorl %ecx, %ecx xorl %edx, %edx movl .L032cbc_enc_jmp_table(,%ebp,4),%ebp jmp *%ebp .L033ej7: movb 6(%esi), %dh sall $8, %edx .L034ej6: movb 5(%esi), %dh .L035ej5: movb 4(%esi), %dl .L036ej4: movl (%esi), %ecx jmp .L037ejend .L038ej3: movb 2(%esi), %ch sall $8, %ecx .L039ej2: movb 1(%esi), %ch .L040ej1: movb (%esi), %cl .L037ejend: xorl %ecx, %eax xorl %edx, %ebx movl %eax, 16(%esp) movl %ebx, 20(%esp) call des_encrypt3 movl 16(%esp), %eax movl 20(%esp), %ebx movl %eax, (%edi) movl %ebx, 4(%edi) jmp .L031finish .align 16 .L028decrypt: andl $4294967288, %ebp movl 24(%esp), %eax movl 28(%esp), %ebx jz .L041decrypt_finish .L042decrypt_loop: movl (%esi), %eax movl 4(%esi), %ebx movl %eax, 16(%esp) movl %ebx, 20(%esp) call des_decrypt3 movl 16(%esp), %eax movl 20(%esp), %ebx movl 24(%esp), %ecx movl 28(%esp), %edx xorl %eax, %ecx xorl %ebx, %edx movl (%esi), %eax movl 4(%esi), %ebx movl %ecx, (%edi) movl %edx, 4(%edi) movl %eax, 24(%esp) movl %ebx, 28(%esp) addl $8, %esi addl $8, %edi subl $8, %ebp jnz .L042decrypt_loop .L041decrypt_finish: movl 60(%esp), %ebp andl $7, %ebp jz .L031finish movl (%esi), %eax movl 4(%esi), %ebx movl %eax, 16(%esp) movl %ebx, 20(%esp) call des_decrypt3 movl 16(%esp), %eax movl 20(%esp), %ebx movl 24(%esp), %ecx movl 28(%esp), %edx xorl %eax, %ecx xorl %ebx, %edx movl (%esi), %eax movl 4(%esi), %ebx .L043dj7: rorl $16, %edx movb %dl, 6(%edi) shrl $16, %edx .L044dj6: movb %dh, 5(%edi) .L045dj5: movb %dl, 4(%edi) .L046dj4: movl %ecx, (%edi) jmp .L047djend .L048dj3: rorl $16, %ecx movb %cl, 2(%edi) sall $16, %ecx .L049dj2: movb %ch, 1(%esi) .L050dj1: movb %cl, (%esi) .L047djend: jmp .L031finish .align 16 .L031finish: movl 76(%esp), %ecx addl $32, %esp movl %eax, (%ecx) movl %ebx, 4(%ecx) popl %edi popl %esi popl %ebx popl %ebp ret .align 16 .L032cbc_enc_jmp_table: .long 0 .long .L040ej1 .long .L039ej2 .long .L038ej3 .long .L036ej4 .long .L035ej5 .long .L034ej6 .long .L033ej7 .align 16 .L051cbc_dec_jmp_table: .long 0 .long .L050dj1 .long .L049dj2 .long .L048dj3 .long .L046dj4 .long .L045dj5 .long .L044dj6 .long .L043dj7 .des_ede3_cbc_encrypt_end: .size des_ede3_cbc_encrypt , .des_ede3_cbc_encrypt_end-des_ede3_cbc_encrypt .ident "desasm.pl" libreswan-3.32/linux/net/ipsec/des/ecb_enc.c000066400000000000000000000072751365625662500210070ustar00rootroot00000000000000/* crypto/des/ecb_enc.c */ /* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@cryptsoft.com). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are adhered to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@cryptsoft.com). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * 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 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@cryptsoft.com)" * The word 'cryptographic' can be left out if the routines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ #include "des/des_locl.h" #include "des/spr.h" char *libdes_version = "libdes v 3.24 - 20-Apr-1996 - eay"; char *DES_version = "DES part of SSLeay 0.8.2b 08-Jan-1998"; void des_ecb_encrypt(input, output, ks, enc) des_cblock(*input); des_cblock(*output); des_key_schedule ks; int enc; { register DES_LONG l; register unsigned char *in, *out; DES_LONG ll[2]; in = (unsigned char *)input; out = (unsigned char *)output; c2l(in, l); ll[0] = l; c2l(in, l); ll[1] = l; des_encrypt(ll, ks, enc); l = ll[0]; l2c(l, out); l = ll[1]; l2c(l, out); l = ll[0] = ll[1] = 0; } libreswan-3.32/linux/net/ipsec/des/ipsec_alg_3des.c000066400000000000000000000121471365625662500222670ustar00rootroot00000000000000/* * ipsec_alg 3DES cipher stubs * * Copyright (C) 2005 Michael Richardson * * Adapted from ipsec_alg_aes.c by JuanJo Ciarlante * * ipsec_alg_aes.c,v 1.1.2.1 2003/11/21 18:12:23 jjo Exp * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38) && \ !defined(AUTOCONF_INCLUDED) #include #endif #include /* * special case: ipsec core modular with this static algo inside: * must avoid MODULE magic for this file */ #if defined(CONFIG_KLIPS_MODULE) && defined(CONFIG_KLIPS_ENC_3DES) #undef MODULE #endif #include #include #include /* printk() */ #include /* error codes */ #include /* size_t */ #include /* Low Libreswan header coupling */ #include "libreswan/ipsec_xform.h" #include "libreswan/ipsec_alg.h" #include "klips-crypto/des.h" #include "libreswan/ipsec_alg_3des.h" #define AES_CONTEXT_T aes_context static int debug_3des = 0; static int test_3des = 0; static int excl_3des = 0; #if defined(CONFIG_KLIPS_ENC_3DES_MODULE) MODULE_AUTHOR("Michael Richardson "); #ifdef module_param module_param(debug_3des, int, 0664); module_param(test_des, int, 0664); module_param(excl_des, int, 0664); #else MODULE_PARM(debug_3des, "i"); MODULE_PARM(test_des, "i"); MODULE_PARM(excl_des, "i"); #endif #endif #define ESP_AES_MAC_KEY_SZ 16 /* 128 bit MAC key */ #define ESP_AES_MAC_BLK_LEN 16 /* 128 bit block */ static int _3des_set_key(struct ipsec_alg_enc *alg, __u8 * key_e, const __u8 * key, size_t keysize) { int ret = 0; TripleDES_context *ctx = (TripleDES_context*)key_e; if (keysize != 192 / 8) return EINVAL; des_set_key((des_cblock *)(key + DES_KEY_SZ * 0), ctx->s1); des_set_key((des_cblock *)(key + DES_KEY_SZ * 1), ctx->s2); des_set_key((des_cblock *)(key + DES_KEY_SZ * 2), ctx->s3); if (debug_3des > 0) { printk(KERN_DEBUG "klips_debug:_3des_set_key:" "ret=%d key_e=%p key=%p keysize=%ld\n", ret, key_e, key, (unsigned long int) keysize); } return ret; } static int _3des_cbc_encrypt(struct ipsec_alg_enc *alg, __u8 * key_e, __u8 * in, int ilen, __u8 * iv, int encrypt) { TripleDES_context *ctx = (TripleDES_context*)key_e; des_cblock miv; memcpy(&miv, iv, sizeof(miv)); if (debug_3des > 0) { printk(KERN_DEBUG "klips_debug:_3des_cbc_encrypt:" "key_e=%p in=%p ilen=%d iv=%p encrypt=%d\n", key_e, in, ilen, iv, encrypt); } des_ede3_cbc_encrypt((des_cblock *)in, (des_cblock *)in, ilen, ctx->s1, ctx->s2, ctx->s3, &miv, encrypt); return 1; } static struct ipsec_alg_enc ipsec_alg_3DES = { ixt_common: { ixt_version: IPSEC_ALG_VERSION, ixt_refcnt: ATOMIC_INIT(0), ixt_name: "3des", ixt_blocksize: ESP_3DES_CBC_BLK_LEN, ixt_support: { ias_exttype: IPSEC_ALG_TYPE_ENCRYPT, ias_id: ESP_3DES, //ias_ivlen: 64, ias_keyminbits: ESP_3DES_KEY_SZ * 8, ias_keymaxbits: ESP_3DES_KEY_SZ * 8, }, }, #if defined(MODULE_KLIPS_ENC_3DES_MODULE) ixt_module: THIS_MODULE, #endif ixt_e_keylen: ESP_3DES_KEY_SZ * 8, ixt_e_ctx_size: sizeof(TripleDES_context), ixt_e_set_key: _3des_set_key, ixt_e_cbc_encrypt:_3des_cbc_encrypt, }; #if defined(CONFIG_KLIPS_ENC_3DES_MODULE) IPSEC_ALG_MODULE_INIT_MOD( ipsec_3des_init ) #else IPSEC_ALG_MODULE_INIT_STATIC( ipsec_3des_init ) #endif { int ret, test_ret; if (excl_3des) ipsec_alg_3DES.ixt_common.ixt_state |= IPSEC_ALG_ST_EXCL; ret = register_ipsec_alg_enc(&ipsec_alg_3DES); printk("ipsec_3des_init(alg_type=%d alg_id=%d name=%s): ret=%d\n", ipsec_alg_3DES.ixt_common.ixt_support.ias_exttype, ipsec_alg_3DES.ixt_common.ixt_support.ias_id, ipsec_alg_3DES.ixt_common.ixt_name, ret); if (ret == 0 && test_3des) { test_ret = ipsec_alg_test( ipsec_alg_3DES.ixt_common.ixt_support.ias_exttype, ipsec_alg_3DES.ixt_common.ixt_support.ias_id, test_3des); printk("ipsec_3des_init(alg_type=%d alg_id=%d): test_ret=%d\n", ipsec_alg_3DES.ixt_common.ixt_support.ias_exttype, ipsec_alg_3DES.ixt_common.ixt_support.ias_id, test_ret); } return ret; } #if defined(CONFIG_KLIPS_ENC_3DES_MODULE) IPSEC_ALG_MODULE_EXIT_MOD( ipsec_3des_fini ) #else IPSEC_ALG_MODULE_EXIT_STATIC( ipsec_3des_fini ) #endif { unregister_ipsec_alg_enc(&ipsec_alg_3DES); } /* Dual, because 3des code is 4-clause BSD licensed */ #ifdef MODULE_LICENSE MODULE_LICENSE("Dual BSD/GPL"); #endif libreswan-3.32/linux/net/ipsec/des/set_key.c000066400000000000000000000205141365625662500210630ustar00rootroot00000000000000/* crypto/des/set_key.c */ /* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@cryptsoft.com). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are adhered to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@cryptsoft.com). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * 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 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@cryptsoft.com)" * The word 'cryptographic' can be left out if the routines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ /* set_key.c v 1.4 eay 24/9/91 * 1.4 Speed up by 400% :-) * 1.3 added register declarations. * 1.2 unrolled make_key_sched a bit more * 1.1 added norm_expand_bits * 1.0 First working version */ #include "des/des_locl.h" #include "des/podd.h" #include "des/sk.h" #ifndef NOPROTO static int check_parity(des_cblock (*key)); #else static int check_parity(); #endif int des_check_key = 0; void des_set_odd_parity(key) des_cblock(*key); { int i; for (i = 0; i < (int)DES_KEY_SZ; i++) (*key)[i] = odd_parity[(*key)[i]]; } static int check_parity(key) des_cblock(*key); { int i; for (i = 0; i < (int)DES_KEY_SZ; i++) { if ((*key)[i] != odd_parity[(*key)[i]]) return 0; } return 1; } /* Weak and semi week keys as take from * %A D.W. Davies * %A W.L. Price * %T Security for Computer Networks * %I John Wiley & Sons * %D 1984 * Many thanks to smb@ulysses.att.com (Steven Bellovin) for the reference * (and actual cblock values). */ #define NUM_WEAK_KEY 16 static des_cblock weak_keys[NUM_WEAK_KEY] = { /* weak keys */ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, { 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE }, { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }, { 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0 }, /* semi-weak keys */ { 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE }, { 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01 }, { 0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1 }, { 0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E }, { 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1 }, { 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01 }, { 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE }, { 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E }, { 0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E }, { 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01 }, { 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE }, { 0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1 } }; int des_is_weak_key(key) des_cblock(*key); { int i; for (i = 0; i < NUM_WEAK_KEY; i++) /* Added == 0 to comparison, I obviously don't run * this section very often :-(, thanks to * engineering@MorningStar.Com for the fix * eay 93/06/29 * Another problem, I was comparing only the first 4 * bytes, 97/03/18 */ if (memcmp(weak_keys[i], key, sizeof(des_cblock)) == 0) return 1; return 0; } /* NOW DEFINED IN des_local.h * See ecb_encrypt.c for a pseudo description of these macros. * #define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\ * (b)^=(t),\ * (a)=((a)^((t)<<(n)))) */ #define HPERM_OP(a, t, n, m) ((t) = ((((a) << (16 - (n))) ^ (a)) & (m)), \ (a) = (a) ^ (t) ^ (t >> (16 - (n)))) /* return 0 if key parity is odd (correct), * return -1 if key parity error, * return -2 if illegal weak key. */ int des_set_key(key, schedule) des_cblock(*key); des_key_schedule schedule; { static int shifts2[16] = { 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0 }; register DES_LONG c, d, t, s, t2; register unsigned char *in; register DES_LONG *k; register int i; if (des_check_key) { if (!check_parity(key)) return -1; if (des_is_weak_key(key)) return -2; } k = (DES_LONG *)schedule; in = (unsigned char *)key; c2l(in, c); c2l(in, d); /* do PC1 in 60 simple operations */ /* PERM_OP(d,c,t,4,0x0f0f0f0fL); HPERM_OP(c,t,-2, 0xcccc0000L); HPERM_OP(c,t,-1, 0xaaaa0000L); HPERM_OP(c,t, 8, 0x00ff0000L); HPERM_OP(c,t,-1, 0xaaaa0000L); HPERM_OP(d,t,-8, 0xff000000L); HPERM_OP(d,t, 8, 0x00ff0000L); HPERM_OP(d,t, 2, 0x33330000L); d=((d&0x00aa00aaL)<<7L)|((d&0x55005500L)>>7L)|(d&0xaa55aa55L); d=(d>>8)|((c&0xf0000000L)>>4); c&=0x0fffffffL; */ /* I now do it in 47 simple operations :-) * Thanks to John Fletcher (john_fletcher@lccmail.ocf.llnl.gov) * for the inspiration. :-) */ PERM_OP(d, c, t, 4, 0x0f0f0f0fL); HPERM_OP(c, t, -2, 0xcccc0000L); HPERM_OP(d, t, -2, 0xcccc0000L); PERM_OP(d, c, t, 1, 0x55555555L); PERM_OP(c, d, t, 8, 0x00ff00ffL); PERM_OP(d, c, t, 1, 0x55555555L); d = (((d & 0x000000ffL) << 16L) | (d & 0x0000ff00L) | ((d & 0x00ff0000L) >> 16L) | ((c & 0xf0000000L) >> 4L)); c &= 0x0fffffffL; for (i = 0; i < ITERATIONS; i++) { if (shifts2[i]) { c = ((c >> 2L) | (c << 26L)); d = ((d >> 2L) | (d << 26L)); } else { c = ((c >> 1L) | (c << 27L)); d = ((d >> 1L) | (d << 27L)); } c &= 0x0fffffffL; d &= 0x0fffffffL; /* could be a few less shifts but I am to lazy at this * point in time to investigate */ s = des_skb[0][ (c ) & 0x3f ] | des_skb[1][((c >> 6) & 0x03) | ((c >> 7L) & 0x3c)] | des_skb[2][((c >> 13) & 0x0f) | ((c >> 14L) & 0x30)] | des_skb[3][((c >> 20) & 0x01) | ((c >> 21L) & 0x06) | ((c >> 22L) & 0x38)]; t = des_skb[4][ (d ) & 0x3f ] | des_skb[5][((d >> 7L) & 0x03) | ((d >> 8L) & 0x3c)] | des_skb[6][ (d >> 15L) & 0x3f ] | des_skb[7][((d >> 21L) & 0x0f) | ((d >> 22L) & 0x30)]; /* table contained 0213 4657 */ t2 = ((t << 16L) | (s & 0x0000ffffL)) & 0xffffffffL; *(k++) = ROTATE(t2, 30) & 0xffffffffL; t2 = ((s >> 16L) | (t & 0xffff0000L)); *(k++) = ROTATE(t2, 26) & 0xffffffffL; } return 0; } int des_key_sched(key, schedule) des_cblock(*key); des_key_schedule schedule; { return des_set_key(key, schedule); } libreswan-3.32/linux/net/ipsec/goodmask.c000066400000000000000000000100471365625662500204510ustar00rootroot00000000000000/* * minor utilities for subnet-mask manipulation * Copyright (C) 1998, 1999 Henry Spencer. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. */ #include "libreswan.h" #ifndef ABITS #define ABITS 32 /* bits in an IPv4 address */ #endif /* This file does not use sysdep.h, otherwise this should go into * ports/darwin/include/sysdep.h */ #ifndef s6_addr32 #define s6_addr32 __u6_addr.__u6_addr32 #endif /* - goodmask - is this a good (^1*0*$) subnet mask? * You are not expected to understand this. See Henry S. Warren Jr, * "Functions realizable with word-parallel logical and two's-complement * addition instructions", CACM 20.6 (June 1977), p.439. */ int /* predicate */ goodmask(mask) struct in_addr mask; { unsigned long x = ntohl(mask.s_addr); /* clear rightmost contiguous string of 1-bits */ # define CRCS1B(x) ((((x) | ((x) - 1)) + 1) & (x)) # define TOPBIT (1UL << 31) /* either zero, or has one string of 1-bits which is left-justified */ if (x == 0 || (CRCS1B(x) == 0 && (x & TOPBIT))) return 1; return 0; } /* - masktobits - how many bits in this mask? * The algorithm is essentially a binary search, but highly optimized * for this particular task. */ int /* -1 means !goodmask() */ masktobits(mask) struct in_addr mask; { unsigned long m = ntohl(mask.s_addr); int masklen; if (!goodmask(mask)) return -1; if (m & 0x00000001UL) return 32; masklen = 0; if (m & (0x0000ffffUL << 1)) { /* <<1 for 1-origin numbering */ masklen |= 0x10; m <<= 16; } if (m & (0x00ff0000UL << 1)) { masklen |= 0x08; m <<= 8; } if (m & (0x0f000000UL << 1)) { masklen |= 0x04; m <<= 4; } if (m & (0x30000000UL << 1)) { masklen |= 0x02; m <<= 2; } if (m & (0x40000000UL << 1)) masklen |= 0x01; return masklen; } /* - bitstomask - return a mask with this many high bits on */ struct in_addr bitstomask(n) int n; { struct in_addr result; if (n > 0 && n <= ABITS) result.s_addr = htonl(~((1UL << (ABITS - n)) - 1)); else if (n == 0) result.s_addr = 0; else result.s_addr = 0; /* best error report we can do */ return result; } int /* -1 means !goodmask() */ mask6tobits(mask) struct in6_addr *mask; { int i; int bits = 0; for (i = 0; i < 4; i++) { if (mask->s6_addr32[i] == 0xffffffffUL) { bits += 32; continue; } if (!goodmask(*((struct in_addr *) &mask->s6_addr32[i]))) return -1; bits += masktobits(*((struct in_addr *) &mask->s6_addr32[i])); break; } return bits; } /* - bitstomask6 - return a mask with this many high bits on */ struct in6_addr bitstomask6(n) int n; { struct in6_addr result; if (n > 0 && n <= 32) { result.s6_addr32[0] = htonl(~((1UL << (32 - n)) - 1)); result.s6_addr32[1] = 0; result.s6_addr32[2] = 0; result.s6_addr32[3] = 0; } else if (n > 32 && n <= 64) { result.s6_addr32[0] = 0xffffffffUL; result.s6_addr32[1] = htonl(~((1UL << (64 - n)) - 1)); result.s6_addr32[2] = 0; result.s6_addr32[3] = 0; } else if (n > 64 && n <= 96) { result.s6_addr32[0] = 0xffffffffUL; result.s6_addr32[1] = 0xffffffffUL; result.s6_addr32[2] = htonl(~((1UL << (96 - n)) - 1)); result.s6_addr32[3] = 0; } else if (n > 96 && n <= 128) { result.s6_addr32[0] = 0xffffffff; result.s6_addr32[1] = 0xffffffff; result.s6_addr32[2] = 0xffffffff; result.s6_addr32[3] = htonl(~((1UL << (128 - n)) - 1)); } else { result.s6_addr32[0] = 0; result.s6_addr32[0] = 0; result.s6_addr32[0] = 0; result.s6_addr32[0] = 0; } return result; } libreswan-3.32/linux/net/ipsec/infblock.c000066400000000000000000000302301365625662500204300ustar00rootroot00000000000000/* infblock.c -- interpret and process block types to last block * Copyright (C) 1995-2002 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include #include "infblock.h" #include "inftrees.h" #include "infcodes.h" #include "infutil.h" struct inflate_codes_state {int dummy;}; /* for buggy compilers */ /* simplify the use of the inflate_huft type with some defines */ #define exop word.what.Exop #define bits word.what.Bits /* Table for deflate from PKZIP's appnote.txt. */ local const uInt border[] = { /* Order of the bit length code lengths */ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; /* Notes beyond the 1.93a appnote.txt: 1. Distance pointers never point before the beginning of the output stream. 2. Distance pointers can point back across blocks, up to 32k away. 3. There is an implied maximum of 7 bits for the bit length table and 15 bits for the actual data. 4. If only one code exists, then it is encoded using one bit. (Zero would be more efficient, but perhaps a little confusing.) If two codes exist, they are coded using one bit each (0 and 1). 5. There is no way of sending zero distance codes--a dummy must be sent if there are none. (History: a pre 2.0 version of PKZIP would store blocks with no distance codes, but this was discovered to be too harsh a criterion.) Valid only for 1.93a. 2.04c does allow zero distance codes, which is sent as one code of zero bits in length. 6. There are up to 286 literal/length codes. Code 256 represents the end-of-block. Note however that the static length tree defines 288 codes just to fill out the Huffman codes. Codes 286 and 287 cannot be used though, since there is no length base or extra bits defined for them. Similarly, there are up to 30 distance codes. However, static trees define 32 codes (all 5 bits) to fill out the Huffman codes, but the last two had better not show up in the data. 7. Unzip can check dynamic Huffman blocks for complete code sets. The exception is that a single code would not be complete (see #4). 8. The five bits following the block type is really the number of literal codes sent minus 257. 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits (1+6+6). Therefore, to output three times the length, you output three codes (1+1+1), whereas to output four times the same length, you only need two codes (1+3). Hmm. 10. In the tree reconstruction algorithm, Code = Code + Increment only if BitLength(i) is not zero. (Pretty obvious.) 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19) 12. Note: length code 284 can represent 227-258, but length code 285 really is 258. The last length deserves its own, short code since it gets used a lot in very redundant files. The length 258 is special since 258 - 3 (the min match length) is 255. 13. The literal/length and distance code bit lengths are read as a single stream of lengths. It is possible (and advantageous) for a repeat code (16, 17, or 18) to go across the boundary between the two sets of lengths. */ void inflate_blocks_reset(s, z, c) inflate_blocks_statef *s; z_streamp z; uLongf *c; { if (c != Z_NULL) *c = s->check; if (s->mode == BTREE || s->mode == DTREE) ZFREE(z, s->sub.trees.blens); if (s->mode == CODES) inflate_codes_free(s->sub.decode.codes, z); s->mode = TYPE; s->bitk = 0; s->bitb = 0; s->read = s->write = s->window; if (s->checkfn != Z_NULL) z->adler = s->check = (*s->checkfn)(0L, (const Bytef *)Z_NULL, 0); Tracev((stderr, "inflate: blocks reset\n")); } inflate_blocks_statef *inflate_blocks_new(z, c, w) z_streamp z; check_func c; uInt w; { inflate_blocks_statef *s; if ((s = (inflate_blocks_statef *)ZALLOC (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL) return s; if ((s->hufts = (inflate_huft *)ZALLOC(z, sizeof(inflate_huft), MANY)) == Z_NULL) { ZFREE(z, s); return Z_NULL; } if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL) { ZFREE(z, s->hufts); ZFREE(z, s); return Z_NULL; } s->end = s->window + w; s->checkfn = c; s->mode = TYPE; Tracev((stderr, "inflate: blocks allocated\n")); inflate_blocks_reset(s, z, Z_NULL); return s; } int inflate_blocks(s, z, r) inflate_blocks_statef *s; z_streamp z; int r; { uInt t; /* temporary storage */ uLong b; /* bit buffer */ uInt k; /* bits in bit buffer */ Bytef *p; /* input data pointer */ uInt n; /* bytes available there */ Bytef *q; /* output window write pointer */ uInt m; /* bytes to end of window or read pointer */ /* copy input/output information to locals (UPDATE macro restores) */ LOAD /* process input based on current state */ while (1) switch (s->mode) { case TYPE: NEEDBITS(3) t = (uInt)b & 7; s->last = t & 1; switch (t >> 1) { case 0: /* stored */ Tracev((stderr, "inflate: stored block%s\n", s->last ? " (last)" : "")); DUMPBITS(3) t = k & 7; /* go to byte boundary */ DUMPBITS(t) s->mode = LENS; /* get length of stored block */ break; case 1: /* fixed */ Tracev((stderr, "inflate: fixed codes block%s\n", s->last ? " (last)" : "")); { uInt bl, bd; inflate_huft *tl, *td; inflate_trees_fixed(&bl, &bd, &tl, &td, z); s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z); if (s->sub.decode.codes == Z_NULL) { r = Z_MEM_ERROR; LEAVE } } DUMPBITS(3) s->mode = CODES; break; case 2: /* dynamic */ Tracev((stderr, "inflate: dynamic codes block%s\n", s->last ? " (last)" : "")); DUMPBITS(3) s->mode = TABLE; break; case 3: /* illegal */ DUMPBITS(3) s->mode = BAD; z->msg = (char*)"invalid block type"; r = Z_DATA_ERROR; LEAVE } break; case LENS: NEEDBITS(32) if ((((~b) >> 16) & 0xffff) != (b & 0xffff)) { s->mode = BAD; z->msg = (char*)"invalid stored block lengths"; r = Z_DATA_ERROR; LEAVE } s->sub.left = (uInt)b & 0xffff; b = k = 0; /* dump bits */ Tracev((stderr, "inflate: stored length %u\n", s->sub.left)); s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE); break; case STORED: if (n == 0) LEAVE NEEDOUT t = s->sub.left; if (t > n) t = n; if (t > m) t = m; zmemcpy(q, p, t); p += t; n -= t; q += t; m -= t; if ((s->sub.left -= t) != 0) break; Tracev((stderr, "inflate: stored end, %lu total out\n", z->total_out + (q >= s->read ? q - s->read : (s->end - s->read) + (q - s->window)))); s->mode = s->last ? DRY : TYPE; break; case TABLE: NEEDBITS(14) s->sub.trees.table = t = (uInt)b & 0x3fff; #ifndef PKZIP_BUG_WORKAROUND if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) { s->mode = BAD; z->msg = (char*)"too many length or distance symbols"; r = Z_DATA_ERROR; LEAVE } #endif t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL) { r = Z_MEM_ERROR; LEAVE } DUMPBITS(14) s->sub.trees.index = 0; Tracev((stderr, "inflate: table sizes ok\n")); s->mode = BTREE; case BTREE: while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10)) { NEEDBITS(3) s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7; DUMPBITS(3) } while (s->sub.trees.index < 19) s->sub.trees.blens[border[s->sub.trees.index++]] = 0; s->sub.trees.bb = 7; t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb, &s->sub.trees.tb, s->hufts, z); if (t != Z_OK) { r = t; if (r == Z_DATA_ERROR) { ZFREE(z, s->sub.trees.blens); s->mode = BAD; } LEAVE } s->sub.trees.index = 0; Tracev((stderr, "inflate: bits tree ok\n")); s->mode = DTREE; case DTREE: while (t = s->sub.trees.table, s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)) { inflate_huft *h; uInt i, j, c; t = s->sub.trees.bb; NEEDBITS(t) h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]); t = h->bits; c = h->base; if (c < 16) { DUMPBITS(t) s->sub.trees.blens[s->sub.trees.index++] = c; } else /* c == 16..18 */ { i = c == 18 ? 7 : c - 14; j = c == 18 ? 11 : 3; NEEDBITS(t + i) DUMPBITS(t) j += (uInt)b & inflate_mask[i]; DUMPBITS(i) i = s->sub.trees.index; t = s->sub.trees.table; if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || (c == 16 && i < 1)) { ZFREE(z, s->sub.trees.blens); s->mode = BAD; z->msg = (char*)"invalid bit length repeat"; r = Z_DATA_ERROR; LEAVE } c = c == 16 ? s->sub.trees.blens[i - 1] : 0; do { s->sub.trees.blens[i++] = c; } while (--j); s->sub.trees.index = i; } } s->sub.trees.tb = Z_NULL; { uInt bl, bd; inflate_huft *tl, *td; inflate_codes_statef *c; bl = 9; /* must be <= 9 for lookahead assumptions */ bd = 6; /* must be <= 9 for lookahead assumptions */ t = s->sub.trees.table; t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), s->sub.trees.blens, &bl, &bd, &tl, &td, s->hufts, z); if (t != Z_OK) { if (t == (uInt)Z_DATA_ERROR) { ZFREE(z, s->sub.trees.blens); s->mode = BAD; } r = t; LEAVE } Tracev((stderr, "inflate: trees ok\n")); if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL) { r = Z_MEM_ERROR; LEAVE } s->sub.decode.codes = c; } ZFREE(z, s->sub.trees.blens); s->mode = CODES; case CODES: UPDATE if ((r = inflate_codes(s, z, r)) != Z_STREAM_END) return inflate_flush(s, z, r); r = Z_OK; inflate_codes_free(s->sub.decode.codes, z); LOAD Tracev((stderr, "inflate: codes end, %lu total out\n", z->total_out + (q >= s->read ? q - s->read : (s->end - s->read) + (q - s->window)))); if (!s->last) { s->mode = TYPE; break; } s->mode = DRY; case DRY: FLUSH if (s->read != s->write) LEAVE s->mode = DONE; case DONE: r = Z_STREAM_END; LEAVE case BAD: r = Z_DATA_ERROR; LEAVE default: r = Z_STREAM_ERROR; LEAVE } } int inflate_blocks_free(s, z) inflate_blocks_statef *s; z_streamp z; { inflate_blocks_reset(s, z, Z_NULL); ZFREE(z, s->window); ZFREE(z, s->hufts); ZFREE(z, s); Tracev((stderr, "inflate: blocks freed\n")); return Z_OK; } void inflate_set_dictionary(s, d, n) inflate_blocks_statef *s; const Bytef *d; uInt n; { zmemcpy(s->window, d, n); s->read = s->write = s->window + n; } /* Returns true if inflate is currently at the end of a block generated * by Z_SYNC_FLUSH or Z_FULL_FLUSH. * IN assertion: s != Z_NULL */ int inflate_blocks_sync_point(s) inflate_blocks_statef *s; { return s->mode == LENS; } libreswan-3.32/linux/net/ipsec/infblock.h000066400000000000000000000022751365625662500204450ustar00rootroot00000000000000/* infblock.h -- header to use infblock.c * Copyright (C) 1995-2002 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ struct inflate_blocks_state; typedef struct inflate_blocks_state FAR inflate_blocks_statef; extern inflate_blocks_statef * inflate_blocks_new OF(( z_streamp z, check_func c, /* check function */ uInt w)); /* window size */ extern int inflate_blocks OF(( inflate_blocks_statef *, z_streamp , int)); /* initial return code */ extern void inflate_blocks_reset OF(( inflate_blocks_statef *, z_streamp , uLongf *)); /* check value on output */ extern int inflate_blocks_free OF(( inflate_blocks_statef *, z_streamp)); extern void inflate_set_dictionary OF(( inflate_blocks_statef *s, const Bytef *d, /* dictionary */ uInt n)); /* dictionary length */ extern int inflate_blocks_sync_point OF(( inflate_blocks_statef *s)); libreswan-3.32/linux/net/ipsec/infcodes.c000066400000000000000000000167111365625662500204430ustar00rootroot00000000000000/* infcodes.c -- process literals and length/distance pairs * Copyright (C) 1995-2002 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include #include "inftrees.h" #include "infblock.h" #include "infcodes.h" #include "infutil.h" #include "inffast.h" /* simplify the use of the inflate_huft type with some defines */ #define exop word.what.Exop #define bits word.what.Bits typedef enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ START, /* x: set up for LEN */ LEN, /* i: get length/literal/eob next */ LENEXT, /* i: getting length extra (have base) */ DIST, /* i: get distance next */ DISTEXT, /* i: getting distance extra */ COPY, /* o: copying bytes in window, waiting for space */ LIT, /* o: got literal, waiting for output space */ WASH, /* o: got eob, possibly still output waiting */ END, /* x: got eob and all data flushed */ BADCODE} /* x: got error */ inflate_codes_mode; /* inflate codes private state */ struct inflate_codes_state { /* mode */ inflate_codes_mode mode; /* current inflate_codes mode */ /* mode dependent information */ uInt len; union { struct { inflate_huft *tree; /* pointer into tree */ uInt need; /* bits needed */ } code; /* if LEN or DIST, where in tree */ uInt lit; /* if LIT, literal */ struct { uInt get; /* bits to get for extra */ uInt dist; /* distance back to copy from */ } copy; /* if EXT or COPY, where and how much */ } sub; /* submode */ /* mode independent information */ Byte lbits; /* ltree bits decoded per branch */ Byte dbits; /* dtree bits decoder per branch */ inflate_huft *ltree; /* literal/length/eob tree */ inflate_huft *dtree; /* distance tree */ }; inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z) uInt bl, bd; inflate_huft *tl; inflate_huft *td; /* need separate declaration for Borland C++ */ z_streamp z; { inflate_codes_statef *c; if ((c = (inflate_codes_statef *) ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL) { c->mode = START; c->lbits = (Byte)bl; c->dbits = (Byte)bd; c->ltree = tl; c->dtree = td; Tracev((stderr, "inflate: codes new\n")); } return c; } int inflate_codes(s, z, r) inflate_blocks_statef *s; z_streamp z; int r; { uInt j; /* temporary storage */ inflate_huft *t; /* temporary pointer */ uInt e; /* extra bits or operation */ uLong b; /* bit buffer */ uInt k; /* bits in bit buffer */ Bytef *p; /* input data pointer */ uInt n; /* bytes available there */ Bytef *q; /* output window write pointer */ uInt m; /* bytes to end of window or read pointer */ Bytef *f; /* pointer to copy strings from */ inflate_codes_statef *c = s->sub.decode.codes; /* codes state */ /* copy input/output information to locals (UPDATE macro restores) */ LOAD /* process input and output based on current state */ while (1) switch (c->mode) { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ case START: /* x: set up for LEN */ #ifndef SLOW if (m >= 258 && n >= 10) { UPDATE r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z); LOAD if (r != Z_OK) { c->mode = r == Z_STREAM_END ? WASH : BADCODE; break; } } #endif /* !SLOW */ c->sub.code.need = c->lbits; c->sub.code.tree = c->ltree; c->mode = LEN; case LEN: /* i: get length/literal/eob next */ j = c->sub.code.need; NEEDBITS(j) t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); DUMPBITS(t->bits) e = (uInt)(t->exop); if (e == 0) /* literal */ { c->sub.lit = t->base; Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? "inflate: literal '%c'\n" : "inflate: literal 0x%02x\n", t->base)); c->mode = LIT; break; } if (e & 16) /* length */ { c->sub.copy.get = e & 15; c->len = t->base; c->mode = LENEXT; break; } if ((e & 64) == 0) /* next table */ { c->sub.code.need = e; c->sub.code.tree = t + t->base; break; } if (e & 32) /* end of block */ { Tracevv((stderr, "inflate: end of block\n")); c->mode = WASH; break; } c->mode = BADCODE; /* invalid code */ z->msg = (char*)"invalid literal/length code"; r = Z_DATA_ERROR; LEAVE case LENEXT: /* i: getting length extra (have base) */ j = c->sub.copy.get; NEEDBITS(j) c->len += (uInt)b & inflate_mask[j]; DUMPBITS(j) c->sub.code.need = c->dbits; c->sub.code.tree = c->dtree; Tracevv((stderr, "inflate: length %u\n", c->len)); c->mode = DIST; case DIST: /* i: get distance next */ j = c->sub.code.need; NEEDBITS(j) t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); DUMPBITS(t->bits) e = (uInt)(t->exop); if (e & 16) /* distance */ { c->sub.copy.get = e & 15; c->sub.copy.dist = t->base; c->mode = DISTEXT; break; } if ((e & 64) == 0) /* next table */ { c->sub.code.need = e; c->sub.code.tree = t + t->base; break; } c->mode = BADCODE; /* invalid code */ z->msg = (char*)"invalid distance code"; r = Z_DATA_ERROR; LEAVE case DISTEXT: /* i: getting distance extra */ j = c->sub.copy.get; NEEDBITS(j) c->sub.copy.dist += (uInt)b & inflate_mask[j]; DUMPBITS(j) Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist)); c->mode = COPY; case COPY: /* o: copying bytes in window, waiting for space */ f = q - c->sub.copy.dist; while (f < s->window) /* modulo window size-"while" instead */ f += s->end - s->window; /* of "if" handles invalid distances */ while (c->len) { NEEDOUT OUTBYTE(*f++) if (f == s->end) f = s->window; c->len--; } c->mode = START; break; case LIT: /* o: got literal, waiting for output space */ NEEDOUT OUTBYTE(c->sub.lit) c->mode = START; break; case WASH: /* o: got eob, possibly more output */ if (k > 7) /* return unused byte, if any */ { Assert(k < 16, "inflate_codes grabbed too many bytes") k -= 8; n++; p--; /* can always return one */ } FLUSH if (s->read != s->write) LEAVE c->mode = END; case END: r = Z_STREAM_END; LEAVE case BADCODE: /* x: got error */ r = Z_DATA_ERROR; LEAVE default: r = Z_STREAM_ERROR; LEAVE } #ifdef NEED_DUMMY_RETURN return Z_STREAM_ERROR; /* Some dumb compilers complain without this */ #endif } void inflate_codes_free(c, z) inflate_codes_statef *c; z_streamp z; { ZFREE(z, c); Tracev((stderr, "inflate: codes free\n")); } libreswan-3.32/linux/net/ipsec/infcodes.h000066400000000000000000000014421365625662500204430ustar00rootroot00000000000000/* infcodes.h -- header to use infcodes.c * Copyright (C) 1995-2002 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ #ifndef _INFCODES_H #define _INFCODES_H struct inflate_codes_state; typedef struct inflate_codes_state FAR inflate_codes_statef; extern inflate_codes_statef *inflate_codes_new OF(( uInt, uInt, inflate_huft *, inflate_huft *, z_streamp )); extern int inflate_codes OF(( inflate_blocks_statef *, z_streamp , int)); extern void inflate_codes_free OF(( inflate_codes_statef *, z_streamp )); #endif /* _INFCODES_H */ libreswan-3.32/linux/net/ipsec/inffast.c000066400000000000000000000132231365625662500202760ustar00rootroot00000000000000/* inffast.c -- process literals and length/distance pairs fast * Copyright (C) 1995-2002 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include #include "inftrees.h" #include "infblock.h" #include "infcodes.h" #include "infutil.h" #include "inffast.h" struct inflate_codes_state {int dummy;}; /* for buggy compilers */ /* simplify the use of the inflate_huft type with some defines */ #define exop word.what.Exop #define bits word.what.Bits /* macros for bit input with no checking and for returning unused bytes */ #define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<avail_in-n;c=(k>>3)>3:c;n+=c;p-=c;k-=c<<3;} /* Called with number of bytes left to write in window at least 258 (the maximum string length) and number of input bytes available at least ten. The ten bytes are six bytes for the longest length/ distance pair plus four bytes for overloading the bit buffer. */ int inflate_fast(bl, bd, tl, td, s, z) uInt bl, bd; inflate_huft *tl; inflate_huft *td; /* need separate declaration for Borland C++ */ inflate_blocks_statef *s; z_streamp z; { inflate_huft *t; /* temporary pointer */ uInt e; /* extra bits or operation */ uLong b; /* bit buffer */ uInt k; /* bits in bit buffer */ Bytef *p; /* input data pointer */ uInt n; /* bytes available there */ Bytef *q; /* output window write pointer */ uInt m; /* bytes to end of window or read pointer */ uInt ml; /* mask for literal/length tree */ uInt md; /* mask for distance tree */ uInt c; /* bytes to copy */ uInt d; /* distance back to copy from */ Bytef *r; /* copy source pointer */ /* load input, output, bit values */ LOAD /* initialize masks */ ml = inflate_mask[bl]; md = inflate_mask[bd]; /* do until not enough input or output space for fast loop */ do { /* assume called with m >= 258 && n >= 10 */ /* get literal/length code */ GRABBITS(20) /* max bits for literal/length code */ if ((e = (t = tl + ((uInt)b & ml))->exop) == 0) { DUMPBITS(t->bits) Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? "inflate: * literal '%c'\n" : "inflate: * literal 0x%02x\n", t->base)); *q++ = (Byte)t->base; m--; continue; } do { DUMPBITS(t->bits) if (e & 16) { /* get extra bits for length */ e &= 15; c = t->base + ((uInt)b & inflate_mask[e]); DUMPBITS(e) Tracevv((stderr, "inflate: * length %u\n", c)); /* decode distance base of block to copy */ GRABBITS(15); /* max bits for distance code */ e = (t = td + ((uInt)b & md))->exop; do { DUMPBITS(t->bits) if (e & 16) { /* get extra bits to add to distance base */ e &= 15; GRABBITS(e) /* get extra bits (up to 13) */ d = t->base + ((uInt)b & inflate_mask[e]); DUMPBITS(e) Tracevv((stderr, "inflate: * distance %u\n", d)); /* do the copy */ m -= c; r = q - d; if (r < s->window) /* wrap if needed */ { do { r += s->end - s->window; /* force pointer in window */ } while (r < s->window); /* covers invalid distances */ e = s->end - r; if (c > e) { c -= e; /* wrapped copy */ do { *q++ = *r++; } while (--e); r = s->window; do { *q++ = *r++; } while (--c); } else /* normal copy */ { *q++ = *r++; c--; *q++ = *r++; c--; do { *q++ = *r++; } while (--c); } } else /* normal copy */ { *q++ = *r++; c--; *q++ = *r++; c--; do { *q++ = *r++; } while (--c); } break; } else if ((e & 64) == 0) { t += t->base; e = (t += ((uInt)b & inflate_mask[e]))->exop; } else { z->msg = (char*)"invalid distance code"; UNGRAB UPDATE return Z_DATA_ERROR; } } while (1); break; } if ((e & 64) == 0) { t += t->base; if ((e = (t += ((uInt)b & inflate_mask[e]))->exop) == 0) { DUMPBITS(t->bits) Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? "inflate: * literal '%c'\n" : "inflate: * literal 0x%02x\n", t->base)); *q++ = (Byte)t->base; m--; break; } } else if (e & 32) { Tracevv((stderr, "inflate: * end of block\n")); UNGRAB UPDATE return Z_STREAM_END; } else { z->msg = (char*)"invalid literal/length code"; UNGRAB UPDATE return Z_DATA_ERROR; } } while (1); } while (m >= 258 && n >= 10); /* not enough input or output--restore pointers and return */ UNGRAB UPDATE return Z_OK; } libreswan-3.32/linux/net/ipsec/inffast.h000066400000000000000000000010471365625662500203040ustar00rootroot00000000000000/* inffast.h -- header to use inffast.c * Copyright (C) 1995-2002 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ #ifndef _INFFAST_H #define _INFFAST_H extern int inflate_fast OF(( uInt, uInt, inflate_huft *, inflate_huft *, inflate_blocks_statef *, z_streamp )); #endif /* _INFFAST_H */ libreswan-3.32/linux/net/ipsec/inffixed.h000066400000000000000000000213401365625662500204440ustar00rootroot00000000000000/* inffixed.h -- table for decoding fixed codes * Generated automatically by the maketree.c program */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ local uInt fixed_bl = 9; local uInt fixed_bd = 5; local inflate_huft fixed_tl[] = { {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115}, {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},192}, {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},160}, {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},224}, {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},144}, {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},208}, {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},176}, {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},240}, {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227}, {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},200}, {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},168}, {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},232}, {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},152}, {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},216}, {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},184}, {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},248}, {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163}, {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},196}, {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},164}, {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},228}, {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},148}, {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},212}, {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},180}, {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},244}, {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0}, {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},204}, {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},172}, {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},236}, {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},156}, {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},220}, {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},188}, {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},252}, {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131}, {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},194}, {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},162}, {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},226}, {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},146}, {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},210}, {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},178}, {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},242}, {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258}, {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},202}, {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},170}, {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},234}, {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},154}, {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},218}, {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},186}, {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},250}, {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195}, {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},198}, {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},166}, {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},230}, {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},150}, {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},214}, {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},182}, {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},246}, {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0}, {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},206}, {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},174}, {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},238}, {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},158}, {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},222}, {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},190}, {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},254}, {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115}, {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},193}, {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},161}, {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},225}, {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},145}, {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},209}, {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},177}, {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},241}, {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227}, {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},201}, {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},169}, {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},233}, {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},153}, {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},217}, {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},185}, {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},249}, {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163}, {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},197}, {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},165}, {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},229}, {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},149}, {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},213}, {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},181}, {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},245}, {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0}, {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},205}, {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},173}, {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},237}, {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},157}, {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},221}, {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},189}, {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},253}, {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131}, {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},195}, {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},163}, {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},227}, {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},147}, {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},211}, {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},179}, {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},243}, {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258}, {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},203}, {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},171}, {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},235}, {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},155}, {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},219}, {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},187}, {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},251}, {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195}, {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},199}, {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},167}, {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},231}, {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},151}, {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},215}, {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},183}, {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},247}, {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0}, {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},207}, {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},175}, {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},239}, {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},159}, {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},223}, {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},191}, {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},255} }; local inflate_huft fixed_td[] = { {{{80,5}},1}, {{{87,5}},257}, {{{83,5}},17}, {{{91,5}},4097}, {{{81,5}},5}, {{{89,5}},1025}, {{{85,5}},65}, {{{93,5}},16385}, {{{80,5}},3}, {{{88,5}},513}, {{{84,5}},33}, {{{92,5}},8193}, {{{82,5}},9}, {{{90,5}},2049}, {{{86,5}},129}, {{{192,5}},24577}, {{{80,5}},2}, {{{87,5}},385}, {{{83,5}},25}, {{{91,5}},6145}, {{{81,5}},7}, {{{89,5}},1537}, {{{85,5}},97}, {{{93,5}},24577}, {{{80,5}},4}, {{{88,5}},769}, {{{84,5}},49}, {{{92,5}},12289}, {{{82,5}},13}, {{{90,5}},3073}, {{{86,5}},193}, {{{192,5}},24577} }; libreswan-3.32/linux/net/ipsec/inflate.c000066400000000000000000000227701365625662500202750ustar00rootroot00000000000000/* inflate.c -- zlib interface to inflate modules * Copyright (C) 1995-2002 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include #include "infblock.h" struct inflate_blocks_state {int dummy;}; /* for buggy compilers */ typedef enum { METHOD, /* waiting for method byte */ FLAG, /* waiting for flag byte */ DICT4, /* four dictionary check bytes to go */ DICT3, /* three dictionary check bytes to go */ DICT2, /* two dictionary check bytes to go */ DICT1, /* one dictionary check byte to go */ DICT0, /* waiting for inflateSetDictionary */ BLOCKS, /* decompressing blocks */ CHECK4, /* four check bytes to go */ CHECK3, /* three check bytes to go */ CHECK2, /* two check bytes to go */ CHECK1, /* one check byte to go */ DONE, /* finished check, done */ BAD} /* got an error--stay here */ inflate_mode; /* inflate private state */ struct internal_state { /* mode */ inflate_mode mode; /* current inflate mode */ /* mode dependent information */ union { uInt method; /* if FLAGS, method byte */ struct { uLong was; /* computed check value */ uLong need; /* stream check value */ } check; /* if CHECK, check values to compare */ uInt marker; /* if BAD, inflateSync's marker bytes count */ } sub; /* submode */ /* mode independent information */ int nowrap; /* flag for no wrapper */ uInt wbits; /* log2(window size) (8..15, defaults to 15) */ inflate_blocks_statef *blocks; /* current inflate_blocks state */ }; int ZEXPORT inflateReset(z) z_streamp z; { if (z == Z_NULL || z->state == Z_NULL) return Z_STREAM_ERROR; z->total_in = z->total_out = 0; z->msg = Z_NULL; z->state->mode = z->state->nowrap ? BLOCKS : METHOD; inflate_blocks_reset(z->state->blocks, z, Z_NULL); Tracev((stderr, "inflate: reset\n")); return Z_OK; } int ZEXPORT inflateEnd(z) z_streamp z; { if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL) return Z_STREAM_ERROR; if (z->state->blocks != Z_NULL) inflate_blocks_free(z->state->blocks, z); ZFREE(z, z->state); z->state = Z_NULL; Tracev((stderr, "inflate: end\n")); return Z_OK; } int ZEXPORT inflateInit2_(z, w, version, stream_size) z_streamp z; int w; const char *version; int stream_size; { if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || stream_size != sizeof(z_stream)) return Z_VERSION_ERROR; /* initialize state */ if (z == Z_NULL) return Z_STREAM_ERROR; z->msg = Z_NULL; if (z->zalloc == Z_NULL) { return Z_STREAM_ERROR; /* z->zalloc = zcalloc; z->opaque = (voidpf)0; */ } if (z->zfree == Z_NULL) return Z_STREAM_ERROR; /* z->zfree = zcfree; */ if ((z->state = (struct internal_state FAR *) ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL) return Z_MEM_ERROR; z->state->blocks = Z_NULL; /* handle undocumented nowrap option (no zlib header or check) */ z->state->nowrap = 0; if (w < 0) { w = - w; z->state->nowrap = 1; } /* set window size */ if (w < 8 || w > 15) { inflateEnd(z); return Z_STREAM_ERROR; } z->state->wbits = (uInt)w; /* create inflate_blocks state */ if ((z->state->blocks = inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w)) == Z_NULL) { inflateEnd(z); return Z_MEM_ERROR; } Tracev((stderr, "inflate: allocated\n")); /* reset state */ inflateReset(z); return Z_OK; } int ZEXPORT inflateInit_(z, version, stream_size) z_streamp z; const char *version; int stream_size; { return inflateInit2_(z, DEF_WBITS, version, stream_size); } #define NEEDBYTE {if(z->avail_in==0)return r;r=f;} #define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++) int ZEXPORT inflate(z, f) z_streamp z; int f; { int r; uInt b; if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL) return Z_STREAM_ERROR; f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK; r = Z_BUF_ERROR; while (1) switch (z->state->mode) { case METHOD: NEEDBYTE if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED) { z->state->mode = BAD; z->msg = (char*)"unknown compression method"; z->state->sub.marker = 5; /* can't try inflateSync */ break; } if ((z->state->sub.method >> 4) + 8 > z->state->wbits) { z->state->mode = BAD; z->msg = (char*)"invalid window size"; z->state->sub.marker = 5; /* can't try inflateSync */ break; } z->state->mode = FLAG; case FLAG: NEEDBYTE b = NEXTBYTE; if (((z->state->sub.method << 8) + b) % 31) { z->state->mode = BAD; z->msg = (char*)"incorrect header check"; z->state->sub.marker = 5; /* can't try inflateSync */ break; } Tracev((stderr, "inflate: zlib header ok\n")); if (!(b & PRESET_DICT)) { z->state->mode = BLOCKS; break; } z->state->mode = DICT4; case DICT4: NEEDBYTE z->state->sub.check.need = (uLong)NEXTBYTE << 24; z->state->mode = DICT3; case DICT3: NEEDBYTE z->state->sub.check.need += (uLong)NEXTBYTE << 16; z->state->mode = DICT2; case DICT2: NEEDBYTE z->state->sub.check.need += (uLong)NEXTBYTE << 8; z->state->mode = DICT1; case DICT1: NEEDBYTE z->state->sub.check.need += (uLong)NEXTBYTE; z->adler = z->state->sub.check.need; z->state->mode = DICT0; return Z_NEED_DICT; case DICT0: z->state->mode = BAD; z->msg = (char*)"need dictionary"; z->state->sub.marker = 0; /* can try inflateSync */ return Z_STREAM_ERROR; case BLOCKS: r = inflate_blocks(z->state->blocks, z, r); if (r == Z_DATA_ERROR) { z->state->mode = BAD; z->state->sub.marker = 0; /* can try inflateSync */ break; } if (r == Z_OK) r = f; if (r != Z_STREAM_END) return r; r = f; inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was); if (z->state->nowrap) { z->state->mode = DONE; break; } z->state->mode = CHECK4; case CHECK4: NEEDBYTE z->state->sub.check.need = (uLong)NEXTBYTE << 24; z->state->mode = CHECK3; case CHECK3: NEEDBYTE z->state->sub.check.need += (uLong)NEXTBYTE << 16; z->state->mode = CHECK2; case CHECK2: NEEDBYTE z->state->sub.check.need += (uLong)NEXTBYTE << 8; z->state->mode = CHECK1; case CHECK1: NEEDBYTE z->state->sub.check.need += (uLong)NEXTBYTE; if (z->state->sub.check.was != z->state->sub.check.need) { z->state->mode = BAD; z->msg = (char*)"incorrect data check"; z->state->sub.marker = 5; /* can't try inflateSync */ break; } Tracev((stderr, "inflate: zlib check ok\n")); z->state->mode = DONE; case DONE: return Z_STREAM_END; case BAD: return Z_DATA_ERROR; default: return Z_STREAM_ERROR; } #ifdef NEED_DUMMY_RETURN return Z_STREAM_ERROR; /* Some dumb compilers complain without this */ #endif } int ZEXPORT inflateSetDictionary(z, dictionary, dictLength) z_streamp z; const Bytef *dictionary; uInt dictLength; { uInt length = dictLength; if (z == Z_NULL || z->state == Z_NULL || z->state->mode != DICT0) return Z_STREAM_ERROR; if (adler32(1L, dictionary, dictLength) != z->adler) return Z_DATA_ERROR; z->adler = 1L; if (length >= ((uInt)1<state->wbits)) { length = (1<state->wbits)-1; dictionary += dictLength - length; } inflate_set_dictionary(z->state->blocks, dictionary, length); z->state->mode = BLOCKS; return Z_OK; } int ZEXPORT inflateSync(z) z_streamp z; { uInt n; /* number of bytes to look at */ Bytef *p; /* pointer to bytes */ uInt m; /* number of marker bytes found in a row */ uLong r, w; /* temporaries to save total_in and total_out */ /* set up */ if (z == Z_NULL || z->state == Z_NULL) return Z_STREAM_ERROR; if (z->state->mode != BAD) { z->state->mode = BAD; z->state->sub.marker = 0; } if ((n = z->avail_in) == 0) return Z_BUF_ERROR; p = z->next_in; m = z->state->sub.marker; /* search */ while (n && m < 4) { static const Byte mark[4] = {0, 0, 0xff, 0xff}; if (*p == mark[m]) m++; else if (*p) m = 0; else m = 4 - m; p++, n--; } /* restore */ z->total_in += p - z->next_in; z->next_in = p; z->avail_in = n; z->state->sub.marker = m; /* return no joy or set up to restart on a new block */ if (m != 4) return Z_DATA_ERROR; r = z->total_in; w = z->total_out; inflateReset(z); z->total_in = r; z->total_out = w; z->state->mode = BLOCKS; return Z_OK; } /* Returns true if inflate is currently at the end of a block generated * by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP * implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH * but removes the length bytes of the resulting empty stored block. When * decompressing, PPP checks that at the end of input packet, inflate is * waiting for these length bytes. */ int ZEXPORT inflateSyncPoint(z) z_streamp z; { if (z == Z_NULL || z->state == Z_NULL || z->state->blocks == Z_NULL) return Z_STREAM_ERROR; return inflate_blocks_sync_point(z->state->blocks); } libreswan-3.32/linux/net/ipsec/inftrees.c000066400000000000000000000372121365625662500204670ustar00rootroot00000000000000/* inftrees.c -- generate Huffman trees for efficient decoding * Copyright (C) 1995-2002 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include #include "inftrees.h" #if !defined(BUILDFIXED) && !defined(STDC) # define BUILDFIXED /* non ANSI compilers may not accept inffixed.h */ #endif local const char inflate_copyright[] = " inflate 1.1.4 Copyright 1995-2002 Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot include such an acknowledgment, I would appreciate that you keep this copyright string in the executable of your product. */ struct internal_state {int dummy;}; /* for buggy compilers */ /* simplify the use of the inflate_huft type with some defines */ #define exop word.what.Exop #define bits word.what.Bits local int huft_build OF(( uIntf *, /* code lengths in bits */ uInt, /* number of codes */ uInt, /* number of "simple" codes */ const uIntf *, /* list of base values for non-simple codes */ const uIntf *, /* list of extra bits for non-simple codes */ inflate_huft * FAR*,/* result: starting table */ uIntf *, /* maximum lookup bits (returns actual) */ inflate_huft *, /* space for trees */ uInt *, /* hufts used in space */ uIntf * )); /* space for values */ /* Tables for deflate from PKZIP's appnote.txt. */ local const uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; /* see note #13 above about 258 */ local const uInt cplext[31] = { /* Extra bits for literal codes 257..285 */ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; /* 112==invalid */ local const uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577}; local const uInt cpdext[30] = { /* Extra bits for distance codes */ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13}; /* Huffman code decoding is performed using a multi-level table lookup. The fastest way to decode is to simply build a lookup table whose size is determined by the longest code. However, the time it takes to build this table can also be a factor if the data being decoded is not very long. The most common codes are necessarily the shortest codes, so those codes dominate the decoding time, and hence the speed. The idea is you can have a shorter table that decodes the shorter, more probable codes, and then point to subsidiary tables for the longer codes. The time it costs to decode the longer codes is then traded against the time it takes to make longer tables. This results of this trade are in the variables lbits and dbits below. lbits is the number of bits the first level table for literal/ length codes can decode in one step, and dbits is the same thing for the distance codes. Subsequent tables are also less than or equal to those sizes. These values may be adjusted either when all of the codes are shorter than that, in which case the longest code length in bits is used, or when the shortest code is *longer* than the requested table size, in which case the length of the shortest code in bits is used. There are two different values for the two tables, since they code a different number of possibilities each. The literal/length table codes 286 possible values, or in a flat code, a little over eight bits. The distance table codes 30 possible values, or a little less than five bits, flat. The optimum values for speed end up being about one bit more than those, so lbits is 8+1 and dbits is 5+1. The optimum values may differ though from machine to machine, and possibly even between compilers. Your mileage may vary. */ /* If BMAX needs to be larger than 16, then h and x[] should be uLong. */ #define BMAX 15 /* maximum bit length of any code */ local int huft_build(b, n, s, d, e, t, m, hp, hn, v) uIntf *b; /* code lengths in bits (all assumed <= BMAX) */ uInt n; /* number of codes (assumed <= 288) */ uInt s; /* number of simple-valued codes (0..s-1) */ const uIntf *d; /* list of base values for non-simple codes */ const uIntf *e; /* list of extra bits for non-simple codes */ inflate_huft * FAR *t; /* result: starting table */ uIntf *m; /* maximum lookup bits, returns actual */ inflate_huft *hp; /* space for trees */ uInt *hn; /* hufts used in space */ uIntf *v; /* working area: values in order of bit length */ /* Given a list of code lengths and a maximum table size, make a set of tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR if the given code set is incomplete (the tables are still built in this case), or Z_DATA_ERROR if the input is invalid. */ { uInt a; /* counter for codes of length k */ uInt c[BMAX+1]; /* bit length count table */ uInt f; /* i repeats in table every f entries */ int g; /* maximum code length */ int h; /* table level */ register uInt i; /* counter, current code */ register uInt j; /* counter */ register int k; /* number of bits in current code */ int l; /* bits per table (returned in m) */ uInt mask; /* (1 << w) - 1, to avoid cc -O bug on HP */ register uIntf *p; /* pointer into c[], b[], or v[] */ inflate_huft *q; /* points to current table */ struct inflate_huft_s r; /* table entry for structure assignment */ inflate_huft *u[BMAX]; /* table stack */ register int w; /* bits before this table == (l * h) */ uInt x[BMAX+1]; /* bit offsets, then code stack */ uIntf *xp; /* pointer into x */ int y; /* number of dummy codes added */ uInt z; /* number of entries in current table */ /* Generate counts for each bit length */ p = c; #define C0 *p++ = 0; #define C2 C0 C0 C0 C0 #define C4 C2 C2 C2 C2 C4 /* clear c[]--assume BMAX+1 is 16 */ p = b; i = n; do { c[*p++]++; /* assume all entries <= BMAX */ } while (--i); if (c[0] == n) /* null input--all zero length codes */ { *t = (inflate_huft *)Z_NULL; *m = 0; return Z_OK; } /* Find minimum and maximum length, bound *m by those */ l = *m; for (j = 1; j <= BMAX; j++) if (c[j]) break; k = j; /* minimum code length */ if ((uInt)l < j) l = j; for (i = BMAX; i; i--) if (c[i]) break; g = i; /* maximum code length */ if ((uInt)l > i) l = i; *m = l; /* Adjust last length count to fill out codes, if needed */ for (y = 1 << j; j < i; j++, y <<= 1) if ((y -= c[j]) < 0) return Z_DATA_ERROR; if ((y -= c[i]) < 0) return Z_DATA_ERROR; c[i] += y; /* Generate starting offsets into the value table for each length */ x[1] = j = 0; p = c + 1; xp = x + 2; while (--i) { /* note that i == g from above */ *xp++ = (j += *p++); } /* Make a table of values in order of bit lengths */ p = b; i = 0; do { if ((j = *p++) != 0) v[x[j]++] = i; } while (++i < n); n = x[g]; /* set n to length of v */ /* Generate the Huffman codes and for each, make the table entries */ x[0] = i = 0; /* first Huffman code is zero */ p = v; /* grab values in bit order */ h = -1; /* no tables yet--level -1 */ w = -l; /* bits decoded == (l * h) */ u[0] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */ q = (inflate_huft *)Z_NULL; /* ditto */ z = 0; /* ditto */ /* go through the bit lengths (k already is bits in shortest code) */ for (; k <= g; k++) { a = c[k]; while (a--) { /* here i is the Huffman code of length k bits for value *p */ /* make tables up to required level */ while (k > w + l) { h++; w += l; /* previous table always l bits */ /* compute minimum size table less than or equal to l bits */ z = g - w; z = z > (uInt)l ? l : z; /* table size upper limit */ if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ { /* too few codes for k-w bit table */ f -= a + 1; /* deduct codes from patterns left */ xp = c + k; if (j < z) while (++j < z) /* try smaller tables up to z bits */ { if ((f <<= 1) <= *++xp) break; /* enough codes to use up j bits */ f -= *xp; /* else deduct codes from patterns */ } } z = 1 << j; /* table entries for j-bit table */ /* allocate new table */ if (*hn + z > MANY) /* (note: doesn't matter for fixed) */ return Z_DATA_ERROR; /* overflow of MANY */ u[h] = q = hp + *hn; *hn += z; /* connect to last table, if there is one */ if (h) { x[h] = i; /* save pattern for backing up */ r.bits = (Byte)l; /* bits to dump before this table */ r.exop = (Byte)j; /* bits in this table */ j = i >> (w - l); r.base = (uInt)(q - u[h-1] - j); /* offset to this table */ u[h-1][j] = r; /* connect to last table */ } else *t = q; /* first table is returned result */ } /* set up table entry in r */ r.bits = (Byte)(k - w); if (p >= v + n) r.exop = 128 + 64; /* out of values--invalid code */ else if (*p < s) { r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */ r.base = *p++; /* simple code is just the value */ } else { r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */ r.base = d[*p++ - s]; } /* fill code-like entries with r */ f = 1 << (k - w); for (j = i >> w; j < z; j += f) q[j] = r; /* backwards increment the k-bit code i */ for (j = 1 << (k - 1); i & j; j >>= 1) i ^= j; i ^= j; /* backup over finished tables */ mask = (1 << w) - 1; /* needed on HP, cc -O bug */ while ((i & mask) != x[h]) { h--; /* don't need to update q */ w -= l; mask = (1 << w) - 1; } } } /* Return Z_BUF_ERROR if we were given an incomplete table */ return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK; } int inflate_trees_bits(c, bb, tb, hp, z) uIntf *c; /* 19 code lengths */ uIntf *bb; /* bits tree desired/actual depth */ inflate_huft * FAR *tb; /* bits tree result */ inflate_huft *hp; /* space for trees */ z_streamp z; /* for messages */ { int r; uInt hn = 0; /* hufts used in space */ uIntf *v; /* work area for huft_build */ if ((v = (uIntf*)ZALLOC(z, 19, sizeof(uInt))) == Z_NULL) return Z_MEM_ERROR; r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL, tb, bb, hp, &hn, v); if (r == Z_DATA_ERROR) z->msg = (char*)"oversubscribed dynamic bit lengths tree"; else if (r == Z_BUF_ERROR || *bb == 0) { z->msg = (char*)"incomplete dynamic bit lengths tree"; r = Z_DATA_ERROR; } ZFREE(z, v); return r; } int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, hp, z) uInt nl; /* number of literal/length codes */ uInt nd; /* number of distance codes */ uIntf *c; /* that many (total) code lengths */ uIntf *bl; /* literal desired/actual bit depth */ uIntf *bd; /* distance desired/actual bit depth */ inflate_huft * FAR *tl; /* literal/length tree result */ inflate_huft * FAR *td; /* distance tree result */ inflate_huft *hp; /* space for trees */ z_streamp z; /* for messages */ { int r; uInt hn = 0; /* hufts used in space */ uIntf *v; /* work area for huft_build */ /* allocate work area */ if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) return Z_MEM_ERROR; /* build literal/length tree */ r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v); if (r != Z_OK || *bl == 0) { if (r == Z_DATA_ERROR) z->msg = (char*)"oversubscribed literal/length tree"; else if (r != Z_MEM_ERROR) { z->msg = (char*)"incomplete literal/length tree"; r = Z_DATA_ERROR; } ZFREE(z, v); return r; } /* build distance tree */ r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v); if (r != Z_OK || (*bd == 0 && nl > 257)) { if (r == Z_DATA_ERROR) z->msg = (char*)"oversubscribed distance tree"; else if (r == Z_BUF_ERROR) { #ifdef PKZIP_BUG_WORKAROUND r = Z_OK; } #else z->msg = (char*)"incomplete distance tree"; r = Z_DATA_ERROR; } else if (r != Z_MEM_ERROR) { z->msg = (char*)"empty distance tree with lengths"; r = Z_DATA_ERROR; } ZFREE(z, v); return r; #endif } /* done */ ZFREE(z, v); return Z_OK; } /* build fixed tables only once--keep them here */ #ifdef BUILDFIXED local int fixed_built = 0; #define FIXEDH 544 /* number of hufts used by fixed tables */ local inflate_huft fixed_mem[FIXEDH]; local uInt fixed_bl; local uInt fixed_bd; local inflate_huft *fixed_tl; local inflate_huft *fixed_td; #else #include "inffixed.h" #endif int inflate_trees_fixed(bl, bd, tl, td, z) uIntf *bl; /* literal desired/actual bit depth */ uIntf *bd; /* distance desired/actual bit depth */ inflate_huft * FAR *tl; /* literal/length tree result */ inflate_huft * FAR *td; /* distance tree result */ z_streamp z; /* for memory allocation */ { #ifdef BUILDFIXED /* build fixed tables if not already */ if (!fixed_built) { int k; /* temporary variable */ uInt f = 0; /* number of hufts used in fixed_mem */ uIntf *c; /* length list for huft_build */ uIntf *v; /* work area for huft_build */ /* allocate memory */ if ((c = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) return Z_MEM_ERROR; if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) { ZFREE(z, c); return Z_MEM_ERROR; } /* literal table */ for (k = 0; k < 144; k++) c[k] = 8; for (; k < 256; k++) c[k] = 9; for (; k < 280; k++) c[k] = 7; for (; k < 288; k++) c[k] = 8; fixed_bl = 9; huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl, fixed_mem, &f, v); /* distance table */ for (k = 0; k < 30; k++) c[k] = 5; fixed_bd = 5; huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd, fixed_mem, &f, v); /* done */ ZFREE(z, v); ZFREE(z, c); fixed_built = 1; } #endif *bl = fixed_bl; *bd = fixed_bd; *tl = fixed_tl; *td = fixed_td; return Z_OK; } libreswan-3.32/linux/net/ipsec/inftrees.h000066400000000000000000000051721365625662500204740ustar00rootroot00000000000000/* inftrees.h -- header to use inftrees.c * Copyright (C) 1995-2002 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ /* Huffman code lookup table entry--this entry is four bytes for machines that have 16-bit pointers (e.g. PC's in the small or medium model). */ #ifndef _INFTREES_H #define _INFTREES_H typedef struct inflate_huft_s FAR inflate_huft; struct inflate_huft_s { union { struct { Byte Exop; /* number of extra bits or operation */ Byte Bits; /* number of bits in this code or subcode */ } what; uInt pad; /* pad structure to a power of 2 (4 bytes for */ } word; /* 16-bit, 8 bytes for 32-bit int's) */ uInt base; /* literal, length base, distance base, or table offset */ }; /* Maximum size of dynamic tree. The maximum found in a long but non- exhaustive search was 1004 huft structures (850 for length/literals and 154 for distances, the latter actually the result of an exhaustive search). The actual maximum is not known, but the value below is more than safe. */ #define MANY 1440 extern int inflate_trees_bits OF(( uIntf *, /* 19 code lengths */ uIntf *, /* bits tree desired/actual depth */ inflate_huft * FAR *, /* bits tree result */ inflate_huft *, /* space for trees */ z_streamp)); /* for messages */ extern int inflate_trees_dynamic OF(( uInt, /* number of literal/length codes */ uInt, /* number of distance codes */ uIntf *, /* that many (total) code lengths */ uIntf *, /* literal desired/actual bit depth */ uIntf *, /* distance desired/actual bit depth */ inflate_huft * FAR *, /* literal/length tree result */ inflate_huft * FAR *, /* distance tree result */ inflate_huft *, /* space for trees */ z_streamp)); /* for messages */ extern int inflate_trees_fixed OF(( uIntf *, /* literal desired/actual bit depth */ uIntf *, /* distance desired/actual bit depth */ inflate_huft * FAR *, /* literal/length tree result */ inflate_huft * FAR *, /* distance tree result */ z_streamp)); /* for memory allocation */ #endif /* _INFTREES_H */ libreswan-3.32/linux/net/ipsec/infutil.c000066400000000000000000000037231365625662500203220ustar00rootroot00000000000000/* inflate_util.c -- data and routines common to blocks and codes * Copyright (C) 1995-2002 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include #include "infblock.h" #include "inftrees.h" #include "infcodes.h" #include "infutil.h" struct inflate_codes_state {int dummy;}; /* for buggy compilers */ /* And'ing with mask[n] masks the lower n bits */ uInt inflate_mask[17] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff }; /* copy as much as possible from the sliding window to the output area */ int inflate_flush(s, z, r) inflate_blocks_statef *s; z_streamp z; int r; { uInt n; Bytef *p; Bytef *q; /* local copies of source and destination pointers */ p = z->next_out; q = s->read; /* compute number of bytes to copy as far as end of window */ n = (uInt)((q <= s->write ? s->write : s->end) - q); if (n > z->avail_out) n = z->avail_out; if (n && r == Z_BUF_ERROR) r = Z_OK; /* update counters */ z->avail_out -= n; z->total_out += n; /* update check information */ if (s->checkfn != Z_NULL) z->adler = s->check = (*s->checkfn)(s->check, q, n); /* copy as far as end of window */ zmemcpy(p, q, n); p += n; q += n; /* see if more to copy at beginning of window */ if (q == s->end) { /* wrap pointers */ q = s->window; if (s->write == s->end) s->write = s->window; /* compute bytes to copy */ n = (uInt)(s->write - q); if (n > z->avail_out) n = z->avail_out; if (n && r == Z_BUF_ERROR) r = Z_OK; /* update counters */ z->avail_out -= n; z->total_out += n; /* update check information */ if (s->checkfn != Z_NULL) z->adler = s->check = (*s->checkfn)(s->check, q, n); /* copy */ zmemcpy(p, q, n); p += n; q += n; } /* update pointers */ z->next_out = p; s->read = q; /* done */ return r; } libreswan-3.32/linux/net/ipsec/infutil.h000066400000000000000000000071601365625662500203260ustar00rootroot00000000000000/* infutil.h -- types and macros common to blocks and codes * Copyright (C) 1995-2002 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ #ifndef _INFUTIL_H #define _INFUTIL_H typedef enum { TYPE, /* get type bits (3, including end bit) */ LENS, /* get lengths for stored */ STORED, /* processing stored block */ TABLE, /* get table lengths */ BTREE, /* get bit lengths tree for a dynamic block */ DTREE, /* get length, distance trees for a dynamic block */ CODES, /* processing fixed or dynamic block */ DRY, /* output remaining window bytes */ DONE, /* finished last block, done */ BAD} /* got a data error--stuck here */ inflate_block_mode; /* inflate blocks semi-private state */ struct inflate_blocks_state { /* mode */ inflate_block_mode mode; /* current inflate_block mode */ /* mode dependent information */ union { uInt left; /* if STORED, bytes left to copy */ struct { uInt table; /* table lengths (14 bits) */ uInt index; /* index into blens (or border) */ uIntf *blens; /* bit lengths of codes */ uInt bb; /* bit length tree depth */ inflate_huft *tb; /* bit length decoding tree */ } trees; /* if DTREE, decoding info for trees */ struct { inflate_codes_statef *codes; } decode; /* if CODES, current state */ } sub; /* submode */ uInt last; /* true if this block is the last block */ /* mode independent information */ uInt bitk; /* bits in bit buffer */ uLong bitb; /* bit buffer */ inflate_huft *hufts; /* single malloc for tree space */ Bytef *window; /* sliding window */ Bytef *end; /* one byte after sliding window */ Bytef *read; /* window read pointer */ Bytef *write; /* window write pointer */ check_func checkfn; /* check function */ uLong check; /* check on output */ }; /* defines for inflate input/output */ /* update pointers and return */ #define UPDBITS {s->bitb=b;s->bitk=k;} #define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;} #define UPDOUT {s->write=q;} #define UPDATE {UPDBITS UPDIN UPDOUT} #define LEAVE {UPDATE return inflate_flush(s,z,r);} /* get bytes and bits */ #define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;} #define NEEDBYTE {if(n)r=Z_OK;else LEAVE;} #define NEXTBYTE (n--,*p++) #define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<>=(j);k-=(j);} /* output bytes */ #define WAVAIL (uInt)(qread?s->read-q-1:s->end-q) #define LOADOUT {q=s->write;m=(uInt)WAVAIL;} #define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}} #define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT} #define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE;}}r=Z_OK;} #define OUTBYTE(a) {*q++=(Byte)(a);m--;} /* load local pointers */ #define LOAD {LOADIN LOADOUT} /* masks for lower bits (size given to avoid silly warnings with Visual C++) */ extern uInt inflate_mask[17]; /* copy as much as possible from the sliding window to the output area */ extern int inflate_flush OF(( inflate_blocks_statef *, z_streamp , int)); struct internal_state {int dummy;}; /* for buggy compilers */ #endif /* _INFUTIL_H */ libreswan-3.32/linux/net/ipsec/initaddr.c000066400000000000000000000044571365625662500204530ustar00rootroot00000000000000/* * initialize address structure * Copyright (C) 2000 Henry Spencer. * Copyroght (C) 2009 Paul Wouters * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. * */ #include "libreswan.h" err_t add_port(int af, ip_address *addr, unsigned short port) { switch (af) { case AF_INET: addr->u.v4.sin_port = port; break; case AF_INET6: addr->u.v6.sin6_port = port; break; default: return "unknown address family in add_port"; } return NULL; } /* - initaddr - initialize ip_address from bytes */ err_t /* NULL for success, else string literal */ initaddr(src, srclen, af, dst) const unsigned char *src; size_t srclen; int af; /* address family */ ip_address *dst; { switch (af) { case AF_INET: if (srclen != 4) return "IPv4 address must be exactly 4 bytes"; #if !defined(__KERNEL__) /* On BSD, the kernel compares the entire struct sockaddr when * using bind(). However, this is as large as the largest * address family, so the 'remainder' has to be 0. Linux * compares interface addresses with the length of sa_len, * instead of sizeof(struct sockaddr), so in that case padding * is not needed. * * Patch by Stefan Arentz */ memset(&dst->u.v4, '\0', sizeof(dst->u.v4)); #endif SET_V4(*dst); dst->u.v4.sin_port = 0; memcpy((char *)&dst->u.v4.sin_addr.s_addr, src, srclen); break; case AF_INET6: if (srclen != 16) return "IPv6 address must be exactly 16 bytes"; #if !defined(__KERNEL__) memset(&dst->u.v6, '\0', sizeof(dst->u.v6)); #endif SET_V6(*dst); dst->u.v6.sin6_flowinfo = 0; /* unused */ dst->u.v6.sin6_port = 0; memcpy((char *)&dst->u.v6.sin6_addr, src, srclen); break; default: return "unknown address family in initaddr"; } return NULL; } libreswan-3.32/linux/net/ipsec/ipcomp.c000066400000000000000000000427551365625662500201470ustar00rootroot00000000000000/* * IPCOMP zlib interface code. * implementation of RFC 3173. * * Copyright (C) 2000 Svenning Soerensen * Copyright (C) 2000, 2001 Richard Guy Briggs * Copyright (C) 2012, Paul Wouters * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ /* SSS */ #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38) && \ !defined(AUTOCONF_INCLUDED) #include #endif #define __NO_VERSION__ #include #include /* printk() */ #include "libreswan/ipsec_param.h" #include /* kmalloc() */ #include /* error codes */ #include #include #include #include #include /* struct device, and other headers */ #include /* eth_type_trans */ #include /* struct iphdr */ #include #include #include #include #include #include "libreswan/ipsec_kversion.h" #include "libreswan/radij.h" #include "libreswan/ipsec_encap.h" #include "libreswan/ipsec_sa.h" #include "libreswan/ipsec_xform.h" #include "libreswan/ipsec_tunnel.h" #include "libreswan/ipsec_rcv.h" /* sysctl_ipsec_inbound_policy_check */ extern int sysctl_ipsec_inbound_policy_check; #include "libreswan/ipsec_proto.h" #include "libreswan/ipcomp.h" #include "zlib/zlib.h" #include "zlib/zutil.h" #include /* SADB_X_CALG_DEFLATE */ static voidpf my_zcalloc(voidpf opaque, uInt items, uInt size) { return (voidpf) kmalloc(items * size, GFP_ATOMIC); } static void my_zfree(voidpf opaque, voidpf address) { kfree(address); } /* * We use this function because sometimes we want to pass a negative offset * into skb_put(), this does not work on 64bit platforms because long to * unsigned int casting. */ static inline unsigned char *safe_skb_put(struct sk_buff *skb, int extend) { unsigned char *ptr; if (extend > 0) { /* increase the size of the packet */ ptr = skb_put(skb, extend); } else { /* shrink the size of the packet */ ptr = skb_tail_pointer(skb); skb_trim(skb, skb->len + extend); } return ptr; } struct sk_buff *skb_compress(struct sk_buff *skb, struct ipsec_sa *ips, unsigned int *flags) { struct iphdr *iph; #ifdef CONFIG_KLIPS_IPV6 struct ipv6hdr *iph6; #endif unsigned char nexthdr; unsigned int iphlen, pyldsz, cpyldsz; unsigned char *buffer; z_stream zs; int zresult; KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, "klips_debug:skb_compress: .\n"); if (skb == NULL) { KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, "klips_debug:skb_compress: " "passed in NULL skb, returning ERROR.\n"); if (flags != NULL) *flags |= IPCOMP_PARMERROR; return skb; } if (ips == NULL) { KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, "klips_debug:skb_compress: " "passed in NULL ipsec_sa needed for cpi, returning ERROR.\n"); if (flags) *flags |= IPCOMP_PARMERROR; return skb; } if (flags == NULL) { KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, "klips_debug:skb_compress: " "passed in NULL flags, returning ERROR.\n"); ipsec_kfree_skb(skb); return NULL; } iph = ip_hdr(skb); #ifdef CONFIG_KLIPS_IPV6 iph6 = ipv6_hdr(skb); #endif #ifdef CONFIG_KLIPS_IPV6 if (iph->version == 6) { IPSEC_FRAG_OFF_DECL(frag_off) int nexthdroff; nexthdr = iph6->nexthdr; nexthdroff = ipsec_ipv6_skip_exthdr(skb, ((void *)(iph6 + 1)) - (void*)skb->data, &nexthdr, &frag_off); iphlen = nexthdroff - ((void *)iph6 - (void*)skb->data); pyldsz = ntohs(iph6->payload_len) + sizeof(struct ipv6hdr) - iphlen; } else #endif { nexthdr = iph->protocol; iphlen = iph->ihl << 2; pyldsz = ntohs(iph->tot_len) - iphlen; } switch (nexthdr) { case IPPROTO_COMP: case IPPROTO_AH: case IPPROTO_ESP: KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, "klips_debug:skb_compress: " "skipping compression of packet with ip protocol %d.\n", iph->protocol); *flags |= IPCOMP_UNCOMPRESSABLE; return skb; } /* Don't compress packets already fragmented */ if (iph->version == 4 && (iph->frag_off & __constant_htons(IP_MF | IP_OFFSET))) { KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, "klips_debug:skb_compress: " "skipping compression of fragmented packet.\n"); *flags |= IPCOMP_UNCOMPRESSABLE; return skb; } /* Don't compress less than 90 bytes (rfc 2394) */ if (pyldsz < 90) { KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, "klips_debug:skb_compress: " "skipping compression of tiny packet, len=%d.\n", pyldsz); *flags |= IPCOMP_UNCOMPRESSABLE; return skb; } /* Adaptive decision */ if (ips->ips_comp_adapt_skip) { KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, "klips_debug:skb_compress: " "skipping compression: ips_comp_adapt_skip=%d.\n", ips->ips_comp_adapt_skip); ips->ips_comp_adapt_skip--; *flags |= IPCOMP_UNCOMPRESSABLE; return skb; } zs.zalloc = my_zcalloc; zs.zfree = my_zfree; zs.opaque = 0; /* We want to use deflateInit2 because we don't want the adler header. */ zresult = deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -11, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); if (zresult != Z_OK) { KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, "klips_error:skb_compress: " "deflateInit2() returned error %d (%s), " "skipping compression.\n", zresult, zs.msg ? zs.msg : zError(zresult)); *flags |= IPCOMP_COMPRESSIONERROR; return skb; } /* Max output size. Result should be max this size. * Implementation specific tweak: * If it's not at least 32 bytes and 6.25% smaller than * the original packet, it's probably not worth wasting * the receiver's CPU cycles decompressing it. * Your mileage may vary. */ cpyldsz = pyldsz - sizeof(struct ipcomphdr) - (pyldsz <= 512 ? 32 : pyldsz >> 4); buffer = kmalloc(cpyldsz, GFP_ATOMIC); if (!buffer) { KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, "klips_error:skb_compress: " "unable to kmalloc(%d, GFP_ATOMIC), " "skipping compression.\n", cpyldsz); *flags |= IPCOMP_COMPRESSIONERROR; deflateEnd(&zs); return skb; } if (sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) { __u8 *c; c = (__u8*)iph + iphlen; ipsec_dmp_block("compress before", c, pyldsz); } zs.next_in = (char *) iph + iphlen; /* start of payload */ zs.avail_in = pyldsz; zs.next_out = buffer; /* start of compressed payload */ zs.avail_out = cpyldsz; /* Finish compression in one step */ zresult = deflate(&zs, Z_FINISH); /* Free all dynamically allocated buffers */ deflateEnd(&zs); if (zresult != Z_STREAM_END) { *flags |= IPCOMP_UNCOMPRESSABLE; kfree(buffer); /* Adjust adaptive counters */ if (++(ips->ips_comp_adapt_tries) == IPCOMP_ADAPT_INITIAL_TRIES) { KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, "klips_debug:skb_compress: " "first %d packets didn't compress, " "skipping next %d\n", IPCOMP_ADAPT_INITIAL_TRIES, IPCOMP_ADAPT_INITIAL_SKIP); ips->ips_comp_adapt_skip = IPCOMP_ADAPT_INITIAL_SKIP; } else if (ips->ips_comp_adapt_tries == IPCOMP_ADAPT_INITIAL_TRIES + IPCOMP_ADAPT_SUBSEQ_TRIES) { KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, "klips_debug:skb_compress: " "next %d packets didn't compress, " "skipping next %d\n", IPCOMP_ADAPT_SUBSEQ_TRIES, IPCOMP_ADAPT_SUBSEQ_SKIP); ips->ips_comp_adapt_skip = IPCOMP_ADAPT_SUBSEQ_SKIP; ips->ips_comp_adapt_tries = IPCOMP_ADAPT_INITIAL_TRIES; } return skb; } /* resulting compressed size */ cpyldsz -= zs.avail_out; /* Insert IPCOMP header */ ((struct ipcomphdr*) ((char*) iph + iphlen))->ipcomp_nh = nexthdr; ((struct ipcomphdr*) ((char*) iph + iphlen))->ipcomp_flags = 0; /* use the bottom 16 bits of the spi for the cpi. The top 16 bits are for internal reference only. */ ((struct ipcomphdr*) (((char*)iph) + iphlen))->ipcomp_cpi = htons((__u16)(ntohl(ips->ips_said.spi) & 0x0000ffff)); KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, "klips_debug:skb_compress: " "spi=%08x, spi&0xffff=%04x, cpi=%04x, payload size: raw=%d, comp=%d.\n", ntohl(ips->ips_said.spi), ntohl(ips->ips_said.spi) & 0x0000ffff, ntohs(((struct ipcomphdr*)(((char*)iph) + iphlen))->ipcomp_cpi), pyldsz, cpyldsz); /* Update IP header */ #ifdef CONFIG_KLIPS_IPV6 if (iph->version == 6) { iph6->nexthdr = IPPROTO_COMP; iph6->payload_len = htons(iphlen + sizeof(struct ipcomphdr) + cpyldsz - sizeof(struct ipv6hdr)); } else #endif { iph->protocol = IPPROTO_COMP; iph->tot_len = htons( iphlen + sizeof(struct ipcomphdr) + cpyldsz); #if 1 /* XXX checksum is done by ipsec_tunnel ? */ iph->check = 0; iph->check = ip_fast_csum((char *) iph, iph->ihl); #endif } /* Copy compressed payload */ memcpy((char *) iph + iphlen + sizeof(struct ipcomphdr), buffer, cpyldsz); kfree(buffer); /* Update skb length/tail by "unputting" the shrinkage */ safe_skb_put(skb, cpyldsz + sizeof(struct ipcomphdr) - pyldsz); if (sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) { __u8 *c; c = (__u8*)iph + iphlen + sizeof(struct ipcomphdr); ipsec_dmp_block("compress result", c, cpyldsz); } ips->ips_comp_adapt_skip = 0; ips->ips_comp_adapt_tries = 0; return skb; } struct sk_buff *skb_decompress(struct sk_buff *skb, struct ipsec_sa *ips, unsigned int *flags) { struct sk_buff *nskb = NULL; /* original ip header */ struct iphdr *oiph, *iph; #ifdef CONFIG_KLIPS_IPV6 struct ipv6hdr *oiph6, *iph6; #endif unsigned char nexthdr; unsigned int tot_len, iphlen, pyldsz, cpyldsz; z_stream zs; int zresult; KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, "klips_debug:skb_decompress: .\n"); if (!skb) { KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, "klips_error:skb_decompress: " "passed in NULL skb, returning ERROR.\n"); if (flags) *flags |= IPCOMP_PARMERROR; return skb; } if (!ips && sysctl_ipsec_inbound_policy_check) { KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, "klips_error:skb_decompress: " "passed in NULL ipsec_sa needed for comp alg, returning ERROR.\n"); if (flags) *flags |= IPCOMP_PARMERROR; return skb; } if (!flags) { KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, "klips_error:skb_decompress: " "passed in NULL flags, returning ERROR.\n"); ipsec_kfree_skb(skb); return NULL; } oiph = ip_hdr(skb); #ifdef CONFIG_KLIPS_IPV6 oiph6 = ipv6_hdr(skb); #endif #ifdef CONFIG_KLIPS_IPV6 if (oiph->version == 6) { IPSEC_FRAG_OFF_DECL(frag_off) int nexthdroff; nexthdr = oiph6->nexthdr; nexthdroff = ipsec_ipv6_skip_exthdr(skb, ((void *)(oiph6 + 1)) - (void*)skb->data, &nexthdr, &frag_off); iphlen = nexthdroff - ((void *)oiph6 - (void*)skb->data); tot_len = ntohs(oiph6->payload_len) + sizeof(struct ipv6hdr); } else #endif { iphlen = oiph->ihl << 2; tot_len = ntohs(oiph->tot_len); nexthdr = oiph->protocol; } if (nexthdr != IPPROTO_COMP) { KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, "klips_error:skb_decompress: " "called with non-IPCOMP packet (protocol=%d)," "skipping decompression.\n", oiph->protocol); *flags |= IPCOMP_PARMERROR; return skb; } if (((struct ipcomphdr*)((char*) oiph + iphlen))->ipcomp_flags != 0 || (((struct ipcomphdr*) ((char*) oiph + iphlen))->ipcomp_cpi != htons(SADB_X_CALG_DEFLATE) && sysctl_ipsec_inbound_policy_check && (ips == NULL || ips->ips_encalg != SADB_X_CALG_DEFLATE))) { KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, "klips_error:skb_decompress: " "called with incompatible IPCOMP packet (flags=%d, " "cpi=%d), ips-compalg=%d, skipping decompression.\n", ntohs(((struct ipcomphdr*) ((char*) oiph + iphlen))->ipcomp_flags), ntohs(((struct ipcomphdr*) ((char*) oiph + iphlen))->ipcomp_cpi), ips == NULL ? 0 : ips->ips_encalg); *flags |= IPCOMP_PARMERROR; return skb; } /* if anything other than the DF bit is set */ if (oiph->version == 4 && ntohs(oiph->frag_off) & ~IP_DF) { KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, "klips_error:skb_decompress: " "called with fragmented IPCOMP packet, " "skipping decompression.\n"); *flags |= IPCOMP_PARMERROR; return skb; } /* original compressed payload size */ cpyldsz = tot_len - iphlen - sizeof(struct ipcomphdr); zs.zalloc = my_zcalloc; zs.zfree = my_zfree; zs.opaque = 0; zs.next_in = (char *) oiph + iphlen + sizeof(struct ipcomphdr); zs.avail_in = cpyldsz; /* Maybe we should be a bit conservative about memory requirements and use inflateInit2 */ /* Beware, that this might make us unable to decompress packets from other implementations - HINT: check PGPnet source code */ /* We want to use inflateInit2 because we don't want the adler header. */ zresult = inflateInit2(&zs, -15); if (zresult != Z_OK) { KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, "klips_error:skb_decompress: " "inflateInit2() returned error %d (%s), " "skipping decompression.\n", zresult, zs.msg ? zs.msg : zError(zresult)); *flags |= IPCOMP_DECOMPRESSIONERROR; return skb; } /* We have no way of knowing the exact length of the resulting decompressed output before we have actually done the decompression. For now, we guess that the packet will not be bigger than the attached ipsec device's mtu or 16260, whichever is biggest. This may be wrong, since the sender's mtu may be bigger yet. XXX This must be dealt with later XXX */ /* max payload size */ pyldsz = skb->dev ? (skb->dev->mtu < 16260 ? 16260 : skb->dev->mtu) : (65520 - iphlen); KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, "klips_debug:skb_decompress: " "max payload size: %d\n", pyldsz); while (pyldsz > (cpyldsz + sizeof(struct ipcomphdr)) && (nskb = skb_copy_expand(skb, skb_headroom(skb), pyldsz - cpyldsz - sizeof(struct ipcomphdr), GFP_ATOMIC)) == NULL) { KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, "klips_error:skb_decompress: " "unable to skb_copy_expand(skb, 0, %d, GFP_ATOMIC), " "trying with less payload size.\n", (int)(pyldsz - cpyldsz - sizeof(struct ipcomphdr))); pyldsz >>= 1; } if (!nskb) { KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, "klips_error:skb_decompress: " "unable to allocate memory, dropping packet.\n"); *flags |= IPCOMP_DECOMPRESSIONERROR; inflateEnd(&zs); return skb; } if (sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) { __u8 *c; c = (__u8*)oiph + iphlen + sizeof(struct ipcomphdr); ipsec_dmp_block("decompress before", c, cpyldsz); } safe_skb_put(nskb, pyldsz - cpyldsz - sizeof(struct ipcomphdr)); iph = ip_hdr(nskb); #ifdef CONFIG_KLIPS_IPV6 iph6 = ipv6_hdr(nskb); #endif zs.next_out = (char *)iph + iphlen; zs.avail_out = pyldsz; zresult = inflate(&zs, Z_SYNC_FLUSH); /* work around a bug in zlib, which sometimes wants to taste an extra * byte when being used in the (undocumented) raw deflate mode. */ if (zresult == Z_OK && !zs.avail_in && zs.avail_out) { __u8 zerostuff = 0; zs.next_in = &zerostuff; zs.avail_in = 1; zresult = inflate(&zs, Z_FINISH); } inflateEnd(&zs); if (zresult != Z_STREAM_END) { KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, "klips_error:skb_decompress: " "inflate() returned error %d (%s), " "skipping decompression.\n", zresult, zs.msg ? zs.msg : zError(zresult)); *flags |= IPCOMP_DECOMPRESSIONERROR; ipsec_kfree_skb(nskb); return skb; } /* Update IP header */ /* resulting decompressed size */ pyldsz -= zs.avail_out; nexthdr = ((struct ipcomphdr *) ((char *)oiph + iphlen))->ipcomp_nh; #ifdef CONFIG_KLIPS_IPV6 if (iph->version == 6) { iph6->payload_len = htons(pyldsz + iphlen - sizeof(struct ipv6hdr)); iph6->nexthdr = nexthdr; } else #endif { iph->tot_len = htons(iphlen + pyldsz); iph->protocol = nexthdr; #if 1 /* XXX checksum is done by ipsec_rcv ? */ iph->check = 0; iph->check = ip_fast_csum((char*) iph, iph->ihl); #endif } KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, "klips_debug:skb_decompress: " "spi=%08x, spi&0xffff=%04x, cpi=%04x, payload size: comp=%d, raw=%d, nh=%d.\n", ips ? ntohl(ips->ips_said.spi) : 0, ips ? ntohl(ips->ips_said.spi) & 0x0000ffff : 0, ntohs(((struct ipcomphdr*)(((char*)oiph) + iphlen))->ipcomp_cpi), cpyldsz, pyldsz, nexthdr); /* Update skb length/tail by "unputting" the unused data area */ safe_skb_put(nskb, -zs.avail_out); ipsec_kfree_skb(skb); if (nexthdr == IPPROTO_COMP) { if (sysctl_ipsec_debug_ipcomp) { KLIPS_PRINT(sysctl_ipsec_debug_ipcomp, "klips_debug:skb_decompress: " "Eh? inner packet is also compressed, dropping.\n"); } ipsec_kfree_skb(nskb); return NULL; } if (sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) { __u8 *c; c = (__u8*)iph + iphlen; ipsec_dmp_block("decompress result", c, pyldsz); } return nskb; } libreswan-3.32/linux/net/ipsec/ipsec_ah.c000066400000000000000000000273321365625662500204250ustar00rootroot00000000000000/* * processing code for AH * Copyright (C) 2003-2004 Michael Richardson * Copyright (C) 2012 Paul Wouters * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38) && \ !defined(AUTOCONF_INCLUDED) #include #endif #define __NO_VERSION__ #include #include /* printk() */ #include "libreswan/ipsec_param.h" #include /* kmalloc() */ #include /* error codes */ #include /* size_t */ #include /* mark_bh */ #include /* struct device, and other headers */ #include /* eth_type_trans */ #include /* struct iphdr */ #include #include #include /* *lock* */ #include #include #include "libreswan/radij.h" #include "libreswan/ipsec_encap.h" #include "libreswan/ipsec_sa.h" #ifdef CONFIG_KLIPS_ALG #include "libreswan/ipsec_alg.h" #endif #include "libreswan/ipsec_radij.h" #include "libreswan/ipsec_xform.h" #include "libreswan/ipsec_tunnel.h" #include "libreswan/ipsec_rcv.h" #include "libreswan/ipsec_xmit.h" #include "libreswan/ipsec_auth.h" #include "libreswan/ipsec_ah.h" #include "libreswan/ipsec_proto.h" #ifdef CONFIG_KLIPS_OCF # include "ipsec_ocf.h" #endif __u32 zeroes[AH_AMAX]; enum ipsec_rcv_value ipsec_rcv_ah_checks(struct ipsec_rcv_state *irs, struct sk_buff *skb) { int ahminlen; ahminlen = irs->hard_header_len + sizeof(struct iphdr); /* take care not to deref this pointer until we check the minlen though */ irs->protostuff.ahstuff.ahp = (struct ahhdr *)skb_transport_header(skb); if ((skb->len < ahminlen + sizeof(struct ahhdr)) || (skb->len < ahminlen + (irs->protostuff.ahstuff.ahp->ah_hl << 2))) { KLIPS_PRINT(debug_rcv & DB_RX_INAU, "klips_debug:ipsec_rcv: " "runt ah packet of skb->len=%d received from %s, dropped.\n", skb->len, irs->ipsaddr_txt); if (irs->stats) irs->stats->rx_errors++; return IPSEC_RCV_BADLEN; } irs->said.spi = irs->protostuff.ahstuff.ahp->ah_spi; /* XXX we only support the one 12-byte authenticator for now */ if (irs->protostuff.ahstuff.ahp->ah_hl != ((AHHMAC_HASHLEN + AHHMAC_RPLLEN) >> 2)) { KLIPS_PRINT(debug_rcv & DB_RX_INAU, "klips_debug:ipsec_rcv: " "bad authenticator length %ld, expected %zu from %s.\n", (long)irs->protostuff.ahstuff.ahp->ah_hl << 2, sizeof(struct ahhdr), irs->ipsaddr_txt); if (irs->stats) irs->stats->rx_errors++; return IPSEC_RCV_BADLEN; } return IPSEC_RCV_OK; } enum ipsec_rcv_value ipsec_rcv_ah_setup_auth(struct ipsec_rcv_state *irs, struct sk_buff *skb, __u32 *replay, unsigned char **authenticator) { struct ahhdr *ahp = irs->protostuff.ahstuff.ahp; *replay = ntohl(ahp->ah_rpl); *authenticator = ahp->ah_data; return IPSEC_RCV_OK; } enum ipsec_rcv_value ipsec_rcv_ah_authcalc(struct ipsec_rcv_state *irs, struct sk_buff *skb) { struct ahhdr *ahp = irs->protostuff.ahstuff.ahp; #if defined(CONFIG_KLIPS_AUTH_HMAC_MD5) || defined(CONFIG_KLIPS_AUTH_HMAC_SHA1) struct auth_alg *aa; union { MD5_CTX md5; SHA1_CTX sha1; } tctx; #endif struct iphdr ipo; int ahhlen; #ifdef CONFIG_KLIPS_ALG unsigned char *buf; int len = 0; #endif KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv: " "ipsec_alg hashing proto=%d... ", irs->said.proto); if (irs->said.proto != IPPROTO_AH) return IPSEC_RCV_BADPROTO; #ifdef CONFIG_KLIPS_OCF if (irs->ipsp->ocf_in_use) return ipsec_ocf_rcv(irs); #endif ipo = *lsw_ip4_hdr(irs); ipo.tos = 0; /* mutable RFC 2402 3.3.3.1.1.1 */ ipo.frag_off = 0; ipo.ttl = 0; ipo.check = 0; ahhlen = AH_BASIC_LEN + (ahp->ah_hl << 2); #ifdef CONFIG_KLIPS_ALG if (irs->ipsp->ips_alg_auth) { if ((buf = kmalloc(sizeof(struct iphdr)+skb->len, GFP_KERNEL)) == NULL) return IPSEC_RCV_ERRMEMALLOC; /* do the sanitized header */ memcpy(buf,(caddr_t)&ipo, sizeof(struct iphdr)); len = sizeof(struct iphdr); /* now do the AH header itself */ memcpy(buf+len, (caddr_t)ahp, ahhlen - AHHMAC_HASHLEN); len += (ahhlen - AHHMAC_HASHLEN); /* now, do some zeroes */ memcpy(buf+len, (caddr_t)zeroes, AHHMAC_HASHLEN); len += AHHMAC_HASHLEN; /* finally, do the packet contents themselves */ memcpy(buf+len, (caddr_t)skb_transport_header(skb) + ahhlen, skb->len - ahhlen); len += (skb->len - ahhlen); ipsec_alg_sa_ah_hash(irs->ipsp, (caddr_t)buf, len, irs->hash, AHHMAC_HASHLEN); if (buf) kfree(buf); } else { #endif #if defined(CONFIG_KLIPS_AUTH_HMAC_MD5) || defined(CONFIG_KLIPS_AUTH_HMAC_SHA1) aa = irs->authfuncs; /* copy the initialized keying material */ memcpy(&tctx, irs->ictx, irs->ictx_len); /* do the sanitized header */ (*aa->update)((void*)&tctx, (caddr_t)&ipo, sizeof(struct iphdr)); /* XXX we didn't do the options here! */ /* now do the AH header itself */ (*aa->update)((void*)&tctx, (caddr_t)ahp, ahhlen - AHHMAC_HASHLEN); /* now, do some zeroes */ (*aa->update)((void*)&tctx, (caddr_t)zeroes, AHHMAC_HASHLEN); /* finally, do the packet contents themselves */ (*aa->update)((void*)&tctx, (caddr_t)skb_transport_header(skb) + ahhlen, skb->len - ahhlen); (*aa->final)(irs->hash, (void *)&tctx); memcpy(&tctx, irs->octx, irs->octx_len); (*aa->update)((void *)&tctx, irs->hash, aa->hashlen); (*aa->final)(irs->hash, (void *)&tctx); #endif #ifdef CONFIG_KLIPS_ALG } #endif return IPSEC_RCV_OK; } enum ipsec_rcv_value ipsec_rcv_ah_decap(struct ipsec_rcv_state *irs) { struct ahhdr *ahp = irs->protostuff.ahstuff.ahp; struct sk_buff *skb; int ahhlen; skb = irs->skb; ahhlen = AH_BASIC_LEN + (ahp->ah_hl << 2); lsw_ip4_hdr(irs)->tot_len = htons(ntohs(lsw_ip4_hdr( irs)->tot_len) - ahhlen); irs->next_header = ahp->ah_nh; /* * move the IP header forward by the size of the AH header, * thus removing the the AH header from the packet. */ memmove((void *)(skb_network_header(skb) + ahhlen), (void *)(skb_network_header(skb)), irs->iphlen); ipsec_rcv_dmp("ah postmove", skb->data, skb->len); /* skb_pull below, will move up by ahhlen */ /* XXX not clear how this can happen, as the message indicates */ if (skb->len < ahhlen) { printk(KERN_WARNING "klips_error:ipsec_rcv: " "tried to skb_pull ahhlen=%d, %d available. This should never happen, please report.\n", ahhlen, (int)(skb->len)); return IPSEC_RCV_DECAPFAIL; } skb_pull(skb, ahhlen); skb_set_network_header(skb, -irs->iphlen); irs->iph = (void *) ip_hdr(skb); ipsec_rcv_dmp("ah postpull", (void *)ip_hdr(skb), skb->len); return IPSEC_RCV_OK; } enum ipsec_xmit_value ipsec_xmit_ah_setup(struct ipsec_xmit_state *ixs) { struct iphdr ipo; struct ahhdr *ahp; #if defined(CONFIG_KLIPS_AUTH_HMAC_MD5) || defined(CONFIG_KLIPS_AUTH_HMAC_SHA1) __u8 hash[AH_AMAX]; union { #ifdef CONFIG_KLIPS_AUTH_HMAC_MD5 MD5_CTX md5; #endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ #ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1 SHA1_CTX sha1; #endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */ } tctx; #endif unsigned char *dat = (unsigned char *)ixs->iph; ahp = (struct ahhdr *)(dat + ixs->iphlen); ahp->ah_spi = ixs->ipsp->ips_said.spi; ahp->ah_rpl = htonl(++(ixs->ipsp->ips_replaywin_lastseq)); ahp->ah_rv = 0; ahp->ah_nh = lsw_ip4_hdr(ixs)->protocol; ahp->ah_hl = (sizeof(struct ahhdr) >> 2) - sizeof(__u64) / sizeof(__u32); lsw_ip4_hdr(ixs)->protocol = IPPROTO_AH; ipsec_xmit_dmp("ahp", (char*)ahp, sizeof(*ahp)); ipo = *lsw_ip4_hdr(ixs); ipo.tos = 0; ipo.frag_off = 0; ipo.ttl = 0; ipo.check = 0; ipsec_xmit_dmp("ipo", (char*)&ipo, sizeof(ipo)); switch (ixs->ipsp->ips_authalg) { #ifdef CONFIG_KLIPS_AUTH_HMAC_MD5 case AH_MD5: tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->ictx; ipsec_xmit_dmp("ictx", (char*)&tctx.md5, sizeof(tctx.md5)); osMD5Update(&tctx.md5, (unsigned char *)&ipo, sizeof(struct iphdr)); ipsec_xmit_dmp("ictx+ipo", (char*)&tctx.md5, sizeof(tctx.md5)); osMD5Update(&tctx.md5, (unsigned char *)ahp, sizeof(struct ahhdr) - sizeof(ahp->ah_data)); ipsec_xmit_dmp("ictx+ahp", (char*)&tctx.md5, sizeof(tctx.md5)); osMD5Update(&tctx.md5, (unsigned char *)zeroes, AHHMAC_HASHLEN); ipsec_xmit_dmp("ictx+zeroes", (char*)&tctx.md5, sizeof(tctx.md5)); osMD5Update(&tctx.md5, dat + ixs->iphlen + sizeof(struct ahhdr), ixs->skb->len - ixs->iphlen - sizeof(struct ahhdr)); ipsec_xmit_dmp("ictx+dat", (char*)&tctx.md5, sizeof(tctx.md5)); osMD5Final(hash, &tctx.md5); ipsec_xmit_dmp("ictx hash", (char*)&hash, sizeof(hash)); tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->octx; ipsec_xmit_dmp("octx", (char*)&tctx.md5, sizeof(tctx.md5)); osMD5Update(&tctx.md5, hash, AHMD596_ALEN); ipsec_xmit_dmp("octx+hash", (char*)&tctx.md5, sizeof(tctx.md5)); osMD5Final(hash, &tctx.md5); ipsec_xmit_dmp("octx hash", (char*)&hash, sizeof(hash)); memcpy(ahp->ah_data, hash, AHHMAC_HASHLEN); /* paranoid */ memset((caddr_t)&tctx.md5, 0, sizeof(tctx.md5)); memset((caddr_t)hash, 0, sizeof(*hash)); break; #endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ #ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1 case AH_SHA: tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->ictx; SHA1Update(&tctx.sha1, (unsigned char *)&ipo, sizeof(struct iphdr)); SHA1Update(&tctx.sha1, (unsigned char *)ahp, sizeof(struct ahhdr) - sizeof(ahp->ah_data)); SHA1Update(&tctx.sha1, (unsigned char *)zeroes, AHHMAC_HASHLEN); SHA1Update(&tctx.sha1, dat + ixs->iphlen + sizeof(struct ahhdr), ixs->skb->len - ixs->iphlen - sizeof(struct ahhdr)); SHA1Final(hash, &tctx.sha1); tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->octx; SHA1Update(&tctx.sha1, hash, AHSHA196_ALEN); SHA1Final(hash, &tctx.sha1); memcpy(ahp->ah_data, hash, AHHMAC_HASHLEN); /* paranoid */ memset((caddr_t)&tctx.sha1, 0, sizeof(tctx.sha1)); memset((caddr_t)hash, 0, sizeof(*hash)); break; #endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */ default: ixs->stats->tx_errors++; return IPSEC_XMIT_AH_BADALG; } skb_set_transport_header(ixs->skb, ipsec_skb_offset(ixs->skb, ahp)); return IPSEC_XMIT_OK; } struct xform_functions ah_xform_funcs[] = { { protocol: IPPROTO_AH, rcv_checks: ipsec_rcv_ah_checks, rcv_setup_auth: ipsec_rcv_ah_setup_auth, rcv_calc_auth: ipsec_rcv_ah_authcalc, rcv_decrypt: ipsec_rcv_ah_decap, xmit_setup: ipsec_xmit_ah_setup, xmit_headroom: sizeof(struct ahhdr), xmit_needtailroom: 0, }, }; #ifndef CONFIG_XFRM_ALTERNATE_STACK #ifdef NET_26 struct inet_protocol ah_protocol = { .handler = ipsec_rcv, .no_policy = 1, #ifdef HAVE_NAMESPACES .netns_ok = 1, #endif }; #else struct inet_protocol ah_protocol = { ipsec_rcv, /* AH handler */ NULL, /* TUNNEL error control */ 0, /* next */ IPPROTO_AH, /* protocol ID */ 0, /* copy */ NULL, /* data */ "AH" /* name */ }; #endif /* NET_26 */ #endif /* CONFIG_XFRM_ALTERNATE_STACK */ libreswan-3.32/linux/net/ipsec/ipsec_alg.c000066400000000000000000000773041365625662500206040ustar00rootroot00000000000000/* * Modular extensions service and registration functions * * Author: JuanJo Ciarlante * * Michael Richardson * Paul Wouters * Nick Jones * Copyright (C) 2012 Paul Wouters * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38) && \ !defined(AUTOCONF_INCLUDED) #include #endif #define __NO_VERSION__ #include #include /* printk() */ #include /* struct device, and other headers */ #include /* eth_type_trans */ #include /* struct iphdr */ #include #include #include #include #include /* memcmp() */ #include /* get_random_bytes() */ #include /* error codes */ #include /* *lock* */ #include "libreswan/ipsec_param.h" #include #include "libreswan/ipsec_sa.h" #include "libreswan/radij.h" #include "libreswan/ipsec_encap.h" #include "libreswan/ipsec_radij.h" #include "libreswan/ipsec_xform.h" #include "libreswan/ipsec_tunnel.h" #include "libreswan/ipsec_rcv.h" #if defined(CONFIG_KLIPS_ESP) || defined(CONFIG_KLIPS_AH) # include "libreswan/ipsec_ah.h" #endif /* defined(CONFIG_KLIPS_ESP) || defined(CONFIG_KLIPS_AH) */ #ifdef CONFIG_KLIPS_ESP # include "libreswan/ipsec_esp.h" #endif /* !CONFIG_KLIPS_ESP */ #ifdef CONFIG_KLIPS_IPCOMP # include "libreswan/ipcomp.h" #endif /* CONFIG_KLIPS_COMP */ #include #include #include "libreswan/ipsec_alg.h" #include "libreswan/ipsec_proto.h" #if K_SADB_EALG_MAX < 255 #warning Compiling with limited ESP support ( K_SADB_EALG_MAX < 256 ) #endif static DEFINE_RWLOCK(ipsec_alg_lock); #define IPSEC_ALG_HASHSZ 16 /* must be power of 2, even 2^0=1 */ static struct list_head ipsec_alg_hash_table[IPSEC_ALG_HASHSZ]; /* Old gcc's will fail here */ #define barf_out(fmt, args ...) do { struct ipsec_alg *ixtc = \ (struct ipsec_alg *)ixt; printk( \ KERN_ERR "%s: (%s) " fmt, \ __FUNCTION__, ixtc->ixt_name, \ ## args) \ ; goto out; } while (0) #ifdef NET_26 /* * Must be already protected by lock */ static void __ipsec_alg_usage_inc(struct ipsec_alg *ixt) { #ifdef MODULE if (ixt->ixt_module) try_module_get(ixt->ixt_module); #endif atomic_inc(&ixt->ixt_refcnt); } static void __ipsec_alg_usage_dec(struct ipsec_alg *ixt) { atomic_dec(&ixt->ixt_refcnt); #ifdef MODULE if (ixt->ixt_module) module_put(ixt->ixt_module); #endif } #else /* * Must be already protected by lock */ static void __ipsec_alg_usage_inc(struct ipsec_alg *ixt) { #ifdef MODULE if (ixt->ixt_module) __MOD_INC_USE_COUNT(ixt->ixt_module); #endif atomic_inc(&ixt->ixt_refcnt); } static void __ipsec_alg_usage_dec(struct ipsec_alg *ixt) { atomic_dec(&ixt->ixt_refcnt); #ifdef MODULE if (ixt->ixt_module) __MOD_DEC_USE_COUNT(ixt->ixt_module); #endif } #endif /* * simple hash function, optimized for 0-hash (1 list) special * case */ #if IPSEC_ALG_HASHSZ > 1 static inline unsigned ipsec_alg_hashfn(int alg_type, int alg_id) { return (alg_type ^ alg_id) & (IPSEC_ALG_HASHSZ - 1); } #else #define ipsec_alg_hashfn(x, y) (0) #endif /***************************************************************** * * INTERNAL table handling: insert, delete, find * *****************************************************************/ /* * hash table initialization, called from ipsec_alg_init() */ static void ipsec_alg_hash_init(void) { struct list_head *head = ipsec_alg_hash_table; int i = IPSEC_ALG_HASHSZ; do { INIT_LIST_HEAD(head); head++; i--; } while (i); } /* * hash list lookup by {alg_type, alg_id} and table head, * must be already protected by lock */ static struct ipsec_alg *__ipsec_alg_find(unsigned alg_type, unsigned alg_id, struct list_head * head) { struct list_head *p; struct ipsec_alg *ixt = NULL; for (p = head->next; p != head; p = p->next) { ixt = list_entry(p, struct ipsec_alg, ixt_list); if (ixt->ixt_alg_type == alg_type && ixt->ixt_alg_id == alg_id) goto out; } ixt = NULL; out: return ixt; } /* * inserts (in front) a new entry in hash table, * called from ipsec_alg_register() when new algorithm is registered. */ static int ipsec_alg_insert(struct ipsec_alg *ixt) { int ret = -EINVAL; unsigned hashval = ipsec_alg_hashfn(ixt->ixt_alg_type, ixt->ixt_alg_id); struct list_head *head = ipsec_alg_hash_table + hashval; struct ipsec_alg *ixt_cur; /* new element must be virgin ... */ if (ixt->ixt_list.next != &ixt->ixt_list || ixt->ixt_list.prev != &ixt->ixt_list) { printk(KERN_ERR "ipsec_alg_insert: ixt object \"%s\" " "list head not initialized\n", ixt->ixt_name); return ret; } write_lock_bh(&ipsec_alg_lock); ixt_cur = __ipsec_alg_find(ixt->ixt_alg_type, ixt->ixt_alg_id, head); /* if previous (current) ipsec_alg found check excl flag of _anyone_ */ if (ixt_cur && ((ixt->ixt_state | ixt_cur->ixt_state) & IPSEC_ALG_ST_EXCL)) { barf_out("ipsec_alg for alg_type=%d, alg_id=%d already exist. " "Not loaded (ret=%d).\n", ixt->ixt_alg_type, ixt->ixt_alg_id, ret = -EEXIST); } list_add(&ixt->ixt_list, head); ixt->ixt_state |= IPSEC_ALG_ST_REGISTERED; ret = 0; out: write_unlock_bh(&ipsec_alg_lock); return ret; } /* * deletes an existing entry in hash table, * called from ipsec_alg_unregister() when algorithm is unregistered. */ static int ipsec_alg_delete(struct ipsec_alg *ixt) { write_lock_bh(&ipsec_alg_lock); list_del(&ixt->ixt_list); write_unlock_bh(&ipsec_alg_lock); return 0; } /* * here @user context (read-only when @kernel bh context) * -> no bh disabling * * called from ipsec_alg_enc_key_create(), ipsec_alg_auth_key_create() * ipsec_alg_test_encrypt() and ipsec_alg_test_auth() */ static struct ipsec_alg *ipsec_alg_get(int alg_type, int alg_id) { unsigned hashval = ipsec_alg_hashfn(alg_type, alg_id); struct list_head *head = ipsec_alg_hash_table + hashval; struct ipsec_alg *ixt; read_lock(&ipsec_alg_lock); ixt = __ipsec_alg_find(alg_type, alg_id, head); if (ixt) __ipsec_alg_usage_inc(ixt); read_unlock(&ipsec_alg_lock); return ixt; } static void ipsec_alg_put(struct ipsec_alg *ixt) { __ipsec_alg_usage_dec((struct ipsec_alg *)ixt); } /***************************************************************** * * INTERFACE for ENC services: key creation, encrypt function * *****************************************************************/ /* * main encrypt service entry point * called from ipsec_rcv() with encrypt=IPSEC_ALG_DECRYPT and * ipsec_tunnel_start_xmit with encrypt=IPSEC_ALG_ENCRYPT */ int ipsec_alg_esp_encrypt(struct ipsec_sa *sa_p, __u8 * idat, int ilen, __u8 * iv, int encrypt) { int ret; struct ipsec_alg_enc *ixt_e = sa_p->ips_alg_enc; int debug_flag = (encrypt == IPSEC_ALG_ENCRYPT ? debug_tunnel : debug_rcv); KLIPS_PRINT(debug_flag, "klips_debug:ipsec_alg_esp_encrypt: " "entering with encalg=%d, ixt_e=%p\n", sa_p->ips_encalg, ixt_e); if (ixt_e == NULL) { KLIPS_ERROR(debug_flag, "klips_debug:ipsec_alg_esp_encrypt: " "NULL ipsec_alg_enc object\n"); return -1; } KLIPS_PRINT(debug_flag, "klips_debug:ipsec_alg_esp_encrypt: " "calling cbc_encrypt encalg=%d " "ips_key_e=%p idat=%p ilen=%d iv=%p, encrypt=%d\n", sa_p->ips_encalg, sa_p->ips_key_e, idat, ilen, iv, encrypt); ret = ixt_e->ixt_e_cbc_encrypt(ixt_e, sa_p->ips_key_e, idat, ilen, iv, encrypt); KLIPS_PRINT(debug_flag, "klips_debug:ipsec_alg_esp_encrypt: " "returned ret=%d\n", ret); return ret; } /* * encryption key context creation function * called from pfkey_v2_parser.c:pfkey_ips_init() */ int ipsec_alg_enc_key_create(struct ipsec_sa *sa_p) { int ret = 0; int keyminbits, keymaxbits; caddr_t ekp = NULL; struct ipsec_alg_enc *ixt_e = (struct ipsec_alg_enc *)ipsec_alg_get(IPSEC_ALG_TYPE_ENCRYPT, sa_p->ips_encalg); KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_alg_enc_key_create: " "entering with encalg=%d ixt_e=%p\n", sa_p->ips_encalg, ixt_e); if (!ixt_e) { KLIPS_ERROR(debug_pfkey, "klips_debug:ipsec_alg_enc_key_create: " "NULL ipsec_alg_enc object\n"); return -EPROTO; } /* * grRRR... DES 7bits jurassic stuff ... f*ckk --jjo */ switch (ixt_e->ixt_common.ixt_support.ias_id) { case ESP_3DES: keyminbits = keymaxbits = 192; break; case ESP_DES: keyminbits = keymaxbits = 64; break; default: keyminbits = ixt_e->ixt_common.ixt_support.ias_keyminbits; keymaxbits = ixt_e->ixt_common.ixt_support.ias_keymaxbits; } if (sa_p->ips_key_bits_e < keyminbits || sa_p->ips_key_bits_e > keymaxbits) { KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_alg_enc_key_create: " "incorrect encryption key size for id=%d: %d bits -- " "must be between %d,%d bits\n" /*octets (bytes)\n"*/, ixt_e->ixt_common.ixt_support.ias_id, sa_p->ips_key_bits_e, keyminbits, keymaxbits); ret = -EINVAL; goto ixt_out; } if (ixt_e->ixt_e_new_key) { KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_alg_enc_key_create: " "using ixt_e_new_key to generate key\n"); if ((ekp = ixt_e->ixt_e_new_key(ixt_e, sa_p->ips_key_e, sa_p->ips_key_bits_e / 8)) == NULL) { ret = -EINVAL; goto ixt_out; } } else if (ixt_e->ixt_e_set_key) { KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_alg_enc_key_create: " "using ixt_e_set_key to generate key context\n"); if ((ekp = (caddr_t)kmalloc(ixt_e->ixt_e_ctx_size, GFP_ATOMIC)) == NULL) { ret = -ENOMEM; goto ixt_out; } /* zero-out key_e */ memset(ekp, 0, ixt_e->ixt_e_ctx_size); /* I cast here to allow more decoupling in alg module */ KLIPS_PRINT(debug_pfkey, "set_key(key_ctx=%p, key=%p, key_size=%d)\n", ekp, (caddr_t)sa_p->ips_key_e, sa_p->ips_key_bits_e / 8); ret = ixt_e->ixt_e_set_key(ixt_e, ekp, (caddr_t)sa_p->ips_key_e, sa_p->ips_key_bits_e / 8); if (ret < 0) { kfree(ekp); goto ixt_out; } } else { KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_alg_enc_key_create: " "no function available to generate a key!\n"); ret = -EPROTO; goto ixt_out; } if (sa_p->ips_key_e) { memset(sa_p->ips_key_e, 0, sa_p->ips_key_bits_e / 8); kfree(sa_p->ips_key_e); } sa_p->ips_key_e = ekp; sa_p->ips_key_e_size = ixt_e->ixt_e_ctx_size; sa_p->ips_alg_enc = ixt_e; ixt_e = NULL; ixt_out: if (ixt_e) ipsec_alg_put((struct ipsec_alg *)ixt_e); return ret; } /*************************************************************** * * INTERFACE for AUTH services: key creation, hash functions * ***************************************************************/ /* * auth key context creation function * called from pfkey_v2_parser.c:pfkey_ips_init() */ int ipsec_alg_auth_key_create(struct ipsec_sa *sa_p) { int ret = 0; int keyminbits, keymaxbits; caddr_t akp = NULL; struct ipsec_alg_auth *ixt_a = (struct ipsec_alg_auth *) ipsec_alg_get(IPSEC_ALG_TYPE_AUTH, sa_p->ips_authalg); KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_alg_auth_key_create: " "entering with authalg=%d ixt_a=%p\n", sa_p->ips_authalg, ixt_a); if (!ixt_a) { KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_alg_auth_key_create: " "NULL ipsec_alg_auth object\n"); return -EPROTO; } keyminbits = ixt_a->ixt_common.ixt_support.ias_keyminbits; keymaxbits = ixt_a->ixt_common.ixt_support.ias_keymaxbits; if (sa_p->ips_key_bits_a < keyminbits || sa_p->ips_key_bits_a > keymaxbits) { KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_alg_auth_key_create: incorrect auth" "key size: %d bits -- must be between %d,%d bits\n" /*octets (bytes)\n"*/, sa_p->ips_key_bits_a, keyminbits, keymaxbits); ret = -EINVAL; goto ixt_out; } if (ixt_a->ixt_a_hmac_new_key){ KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_alg_auth_key_create: " "using ixt_a_new_key to generate key\n"); if ((akp = ixt_a->ixt_a_hmac_new_key(ixt_a, sa_p->ips_key_a, sa_p->ips_key_bits_a/8)) == NULL) { ret = -ENOMEM; goto ixt_out; } } else if (ixt_a->ixt_a_hmac_set_key) { /* will hold: 2 ctx and a blocksize buffer: kb */ if ((akp = (caddr_t)kmalloc(ixt_a->ixt_a_ctx_size, GFP_ATOMIC)) == NULL) { ret = -ENOMEM; goto ixt_out; } /* zero-out key_a */ memset(akp, 0, ixt_a->ixt_a_ctx_size); KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_alg_auth_key_create: about to call:" "hmac_set_key(key_ctx=%p, key=%p, key_size=%d)\n", akp, (caddr_t)sa_p->ips_key_a, sa_p->ips_key_bits_a/8); ret = ixt_a->ixt_a_hmac_set_key(ixt_a, akp, sa_p->ips_key_a, sa_p->ips_key_bits_a / 8); /* XXX XXX */ if (ret < 0) { kfree(akp); goto ixt_out; } } else { KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_alg_auth_key_create: " "no hmac_set_key function available!\n"); ret = -EPROTO; goto ixt_out; } if (sa_p->ips_key_a) { memset(sa_p->ips_key_a, 0, sa_p->ips_key_bits_a / 8); kfree(sa_p->ips_key_a); } sa_p->ips_key_a = akp; sa_p->ips_key_a_size = ixt_a->ixt_a_ctx_size; sa_p->ips_auth_bits = ixt_a->ixt_a_keylen * 8; /* XXX XXX */ sa_p->ips_alg_auth = ixt_a; ixt_a = NULL; ixt_out: if (ixt_a) ipsec_alg_put((struct ipsec_alg *)ixt_a); return ret; } int ipsec_alg_sa_esp_hash(const struct ipsec_sa *sa_p, const __u8 *espp, int len, __u8 *hash, int hashlen) { struct ipsec_alg_auth *ixt_a = sa_p->ips_alg_auth; if (!ixt_a) { KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_sa_esp_hash: " "NULL ipsec_alg_auth object\n"); return -EPROTO; } KLIPS_PRINT(debug_tunnel | debug_rcv, "klips_debug:ipsec_sa_esp_hash: " "hashing %p (%d bytes) to %p (%d bytes)\n", espp, len, hash, hashlen); ixt_a->ixt_a_hmac_hash(ixt_a, sa_p->ips_key_a, espp, len, hash, hashlen); return 0; } int ipsec_alg_sa_ah_hash(const struct ipsec_sa *sa_p, const __u8 *ahp, int len, __u8 *hash, int hashlen) { struct ipsec_alg_auth *ixt_a = sa_p->ips_alg_auth; if (!ixt_a) { KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_sa_ah_hash: " "NULL ipsec_alg_auth object\n"); return -EPROTO; } KLIPS_PRINT(debug_tunnel | debug_rcv, "klips_debug:ipsec_sa_ah_hash: " "hashing %p (%d bytes) to %p (%d bytes)\n", ahp, len, hash, hashlen); ixt_a->ixt_a_hmac_hash(ixt_a, sa_p->ips_key_a, ahp, len, hash, hashlen); return 0; } /*************************************************************** * * INTERFACE for module loading,testing, and unloading * ***************************************************************/ /* validation for registering (enc) module */ static int check_enc(struct ipsec_alg_enc *ixt) { int ret = -EINVAL; if (ixt->ixt_common.ixt_blocksize == 0) /* || ixt->ixt_common.ixt_blocksize%2) need for ESP_NULL */ barf_out(KERN_ERR "invalid blocksize=%d\n", ixt->ixt_common.ixt_blocksize); if (ixt->ixt_common.ixt_support.ias_keyminbits == 0 && ixt->ixt_common.ixt_support.ias_keymaxbits == 0 && ixt->ixt_e_keylen == 0) goto zero_key_ok; if (ixt->ixt_common.ixt_support.ias_keyminbits == 0) barf_out(KERN_ERR "invalid keyminbits=%d\n", ixt->ixt_common.ixt_support.ias_keyminbits); if (ixt->ixt_common.ixt_support.ias_keymaxbits == 0) barf_out(KERN_ERR "invalid keymaxbits=%d\n", ixt->ixt_common.ixt_support.ias_keymaxbits); if (ixt->ixt_e_keylen == 0) barf_out(KERN_ERR "invalid keysize=%d\n", ixt->ixt_e_keylen); zero_key_ok: if (ixt->ixt_e_ctx_size == 0 && ixt->ixt_e_new_key == NULL) { barf_out(KERN_ERR "invalid key_e_size=%d and ixt_e_new_key=NULL\n", ixt->ixt_e_ctx_size); } if (ixt->ixt_e_cbc_encrypt == NULL) barf_out(KERN_ERR "e_cbc_encrypt() must be not NULL\n"); ret = 0; out: return ret; } /* validation for registering (auth) module */ static int check_auth(struct ipsec_alg_auth *ixt) { int ret = -EINVAL; if (ixt->ixt_common.ixt_support.ias_id == 0 || ixt->ixt_common.ixt_support.ias_id > K_SADB_AALG_MAX) barf_out("invalid alg_id=%d > %d (K_SADB_AALG_MAX)\n", ixt->ixt_common.ixt_support.ias_id, K_SADB_AALG_MAX); if (ixt->ixt_common.ixt_blocksize == 0 || ixt->ixt_common.ixt_blocksize % 2) barf_out(KERN_ERR "invalid blocksize=%d\n", ixt->ixt_common.ixt_blocksize); if (ixt->ixt_common.ixt_blocksize > AH_BLKLEN_MAX) { barf_out(KERN_ERR "sorry blocksize=%d > %d. " "Please increase AH_BLKLEN_MAX and recompile\n", ixt->ixt_common.ixt_blocksize, AH_BLKLEN_MAX); } if (ixt->ixt_common.ixt_support.ias_keyminbits == 0 && ixt->ixt_common.ixt_support.ias_keymaxbits == 0 && ixt->ixt_a_keylen == 0) goto zero_key_ok; if (ixt->ixt_common.ixt_support.ias_keyminbits == 0) barf_out(KERN_ERR "invalid keyminbits=%d\n", ixt->ixt_common.ixt_support.ias_keyminbits); if (ixt->ixt_common.ixt_support.ias_keymaxbits == 0) barf_out(KERN_ERR "invalid keymaxbits=%d\n", ixt->ixt_common.ixt_support.ias_keymaxbits); if (ixt->ixt_common.ixt_support.ias_keymaxbits != ixt->ixt_common.ixt_support.ias_keyminbits) barf_out(KERN_ERR "keymaxbits must equal keyminbits (not sure).\n"); if (ixt->ixt_a_keylen == 0) barf_out(KERN_ERR "invalid keysize=%d\n", ixt->ixt_a_keylen); zero_key_ok: if (ixt->ixt_a_ctx_size == 0) barf_out(KERN_ERR "invalid a_ctx_size=%d\n", ixt->ixt_a_ctx_size); if (ixt->ixt_a_hmac_set_key==NULL && ixt->ixt_a_hmac_new_key == NULL) barf_out(KERN_ERR "a_hmac_set_key() or a_hmac_new_key() must be not NULL\n"); if (ixt->ixt_a_hmac_hash == NULL) barf_out(KERN_ERR "a_hmac_hash() must be not NULL\n"); ret = 0; out: return ret; } /* * Generic (enc, auth) registration entry point */ int register_ipsec_alg(struct ipsec_alg *ixt) { int ret = -EINVAL; /* Validation */ if (ixt == NULL) barf_out("NULL ipsec_alg object passed\n"); if ((ixt->ixt_version & 0xffffff00) != (IPSEC_ALG_VERSION & 0xffffff00)) { barf_out("incorrect version: %d.%d.%d-%d, " "must be %d.%d.%d[-%d]\n", IPSEC_ALG_VERSION_QUAD(ixt->ixt_version), IPSEC_ALG_VERSION_QUAD(IPSEC_ALG_VERSION)); } switch (ixt->ixt_alg_type) { case IPSEC_ALG_TYPE_AUTH: if ((ret = check_auth((struct ipsec_alg_auth *)ixt) < 0)) goto out; break; case IPSEC_ALG_TYPE_ENCRYPT: if ((ret = check_enc((struct ipsec_alg_enc *)ixt) < 0)) goto out; /* * Adapted two lines below: * ivlen == 0 is possible (NULL enc has blocksize==1) * * fixed NULL support by David De Reu */ if (ixt->ixt_support.ias_ivlen == 0 && ixt->ixt_blocksize > 1) ixt->ixt_support.ias_ivlen = ixt->ixt_blocksize * 8; break; default: barf_out("alg_type=%d not supported\n", ixt->ixt_alg_type); } INIT_LIST_HEAD(&ixt->ixt_list); ret = ipsec_alg_insert(ixt); if (ret < 0) { barf_out(KERN_WARNING "ipsec_alg for alg_id=%d failed." "Not loaded (ret=%d).\n", ixt->ixt_support.ias_id, ret); } ret = pfkey_list_insert_supported( (struct ipsec_alg_supported *)&ixt->ixt_support, &(pfkey_supported_list[ K_SADB_SATYPE_ESP])); if (ret == 0) { ixt->ixt_state |= IPSEC_ALG_ST_SUPP; /* send register event to userspace */ pfkey_register_reply(K_SADB_SATYPE_ESP, NULL); } else { printk(KERN_ERR "pfkey_list_insert_supported returned %d. " "Loading anyway.\n", ret); } ret = 0; out: return ret; } /* * unregister ipsec_alg object from own tables, if * success => calls pfkey_list_remove_supported() */ int unregister_ipsec_alg(struct ipsec_alg *ixt) { int ret = -EINVAL; switch (ixt->ixt_alg_type) { case IPSEC_ALG_TYPE_AUTH: case IPSEC_ALG_TYPE_ENCRYPT: break; default: /* this is not a typo :) */ barf_out("frog found in list (\"%s\"): ixt_p=NULL\n", ixt->ixt_name); } ret = ipsec_alg_delete(ixt); if (ixt->ixt_state & IPSEC_ALG_ST_SUPP) { ixt->ixt_state &= ~IPSEC_ALG_ST_SUPP; pfkey_list_remove_supported( (struct ipsec_alg_supported *)&ixt->ixt_support, &(pfkey_supported_list[ K_SADB_SATYPE_ESP])); /* send register event to userspace */ pfkey_register_reply(K_SADB_SATYPE_ESP, NULL); } out: return ret; } /* * Must be called from user context * used at module load type for testing algo implementation */ static int ipsec_alg_test_encrypt(int enc_alg, int test) { int ret; caddr_t buf = NULL; int iv_size, keysize, key_e_size; struct ipsec_alg_enc *ixt_e; void *tmp_key_e = NULL; # define BUFSZ 1024 # define MARGIN 0 # define test_enc (buf + MARGIN) # define test_dec (test_enc + BUFSZ + MARGIN) # define test_tmp (test_dec + BUFSZ + MARGIN) # define test_key_e (test_tmp + BUFSZ + MARGIN) # define test_iv (test_key_e + key_e_size + MARGIN) # define test_key (test_iv + iv_size + MARGIN) # define test_size (BUFSZ * 3 + key_e_size + iv_size + keysize + \ MARGIN * 7) ixt_e = (struct ipsec_alg_enc *)ipsec_alg_get(IPSEC_ALG_TYPE_ENCRYPT, enc_alg); if (ixt_e == NULL) { KLIPS_PRINT(1, "klips_debug: ipsec_alg_test_encrypt: " "encalg=%d object not found\n", enc_alg); ret = -EINVAL; goto out; } iv_size = ixt_e->ixt_common.ixt_support.ias_ivlen / 8; key_e_size = ixt_e->ixt_e_ctx_size; keysize = ixt_e->ixt_e_keylen; KLIPS_PRINT(1, "klips_debug: ipsec_alg_test_encrypt: " "enc_alg=%d blocksize=%d key_e_size=%d keysize=%d\n", enc_alg, iv_size, key_e_size, keysize); if ((buf = kmalloc(test_size, GFP_KERNEL)) == NULL) { ret = -ENOMEM; goto out; } get_random_bytes(test_key, keysize); get_random_bytes(test_iv, iv_size); if (ixt_e->ixt_e_new_key) { tmp_key_e = ixt_e->ixt_e_new_key(ixt_e, test_key, keysize); ret = tmp_key_e ? 0 : -EINVAL; } else { tmp_key_e = test_key_e; ret = ixt_e->ixt_e_set_key(ixt_e, test_key_e, test_key, keysize); } if (ret < 0) goto out; get_random_bytes(test_enc, BUFSZ); memcpy(test_tmp, test_enc, BUFSZ); ret = ixt_e->ixt_e_cbc_encrypt(ixt_e, tmp_key_e, test_enc, BUFSZ, test_iv, 1); printk(KERN_INFO "klips_info: ipsec_alg_test_encrypt: " "cbc_encrypt=1 ret=%d\n", ret); ret = memcmp(test_enc, test_tmp, BUFSZ); printk(KERN_INFO "klips_info: ipsec_alg_test_encrypt: " "memcmp(enc, tmp) ret=%d: %s\n", ret, ret != 0 ? "OK. (encr->DIFFers)" : "FAIL! (encr->SAME)" ); memcpy(test_dec, test_enc, BUFSZ); ret = ixt_e->ixt_e_cbc_encrypt(ixt_e, tmp_key_e, test_dec, BUFSZ, test_iv, 0); printk(KERN_INFO "klips_info: ipsec_alg_test_encrypt: " "cbc_encrypt=0 ret=%d\n", ret); ret = memcmp(test_dec, test_tmp, BUFSZ); printk(KERN_INFO "klips_info: ipsec_alg_test_encrypt: " "memcmp(dec,tmp) ret=%d: %s\n", ret, ret == 0 ? "OK. (encr->decr->SAME)" : "FAIL! (encr->decr->DIFFers)" ); { /* Shamelessly taken from drivers/md sources O:) */ unsigned long now; int i, count, max = 0; int encrypt, speed; for (encrypt = 0; encrypt < 2; encrypt++) { for (i = 0; i < 5; i++) { now = jiffies; count = 0; while (jiffies == now) { mb(); ixt_e->ixt_e_cbc_encrypt(ixt_e, tmp_key_e, test_tmp, BUFSZ, test_iv, encrypt); mb(); count++; mb(); } if (count > max) max = count; } speed = max * (HZ * BUFSZ / 1024); printk(KERN_INFO "klips_info: ipsec_alg_test_encrypt: " "%s %s speed=%d KB/s\n", ixt_e->ixt_common.ixt_name, encrypt ? "encrypt" : "decrypt", speed); } } out: if (tmp_key_e && ixt_e->ixt_e_destroy_key) ixt_e->ixt_e_destroy_key(ixt_e, tmp_key_e); if (buf) kfree(buf); if (ixt_e) ipsec_alg_put((struct ipsec_alg *)ixt_e); return ret; # undef test_enc # undef test_dec # undef test_tmp # undef test_key_e # undef test_iv # undef test_key # undef test_size } /* * Must be called from user context * used at module load type for testing algo implementation */ static int ipsec_alg_test_auth(int auth_alg, int test) { int ret; caddr_t buf = NULL; int blocksize, keysize, key_a_size; struct ipsec_alg_auth *ixt_a; #define BUFSZ 1024 #define MARGIN 0 #define test_auth (buf + MARGIN) #define test_key_a (test_auth + BUFSZ + MARGIN) #define test_key (test_key_a + key_a_size + MARGIN) #define test_hash (test_key + keysize + MARGIN) #define test_size (BUFSZ + key_a_size + keysize + AHHMAC_HASHLEN + \ MARGIN * 4) ixt_a = (struct ipsec_alg_auth *)ipsec_alg_get(IPSEC_ALG_TYPE_AUTH, auth_alg); if (ixt_a == NULL) { KLIPS_PRINT(1, "klips_debug: ipsec_alg_test_auth: " "encalg=%d object not found\n", auth_alg); ret = -EINVAL; goto out; } blocksize = ixt_a->ixt_common.ixt_blocksize; key_a_size = ixt_a->ixt_a_ctx_size; keysize = ixt_a->ixt_a_keylen; KLIPS_PRINT(1, "klips_debug: ipsec_alg_test_auth: " "auth_alg=%d blocksize=%d key_a_size=%d keysize=%d\n", auth_alg, blocksize, key_a_size, keysize); if (ixt_a->ixt_a_hmac_new_key){ get_random_bytes(test_key, keysize); if ((buf = ixt_a->ixt_a_hmac_new_key(ixt_a, test_key, keysize)) == NULL) { ret= -ENOMEM; goto out; } } else { if ((buf=kmalloc (test_size, GFP_KERNEL)) == NULL) { ret= -ENOMEM; goto out; } get_random_bytes(test_key, keysize); ret = ixt_a->ixt_a_hmac_set_key(ixt_a, test_key_a, test_key, keysize); if (ret < 0 ) goto out; } get_random_bytes(test_auth, BUFSZ); ret = ixt_a->ixt_a_hmac_hash(ixt_a, test_key_a, test_auth, BUFSZ, test_hash, AHHMAC_HASHLEN); printk(KERN_INFO "klips_info: ipsec_alg_test_auth: " "ret=%d\n", ret); { /* Shamelessly taken from drivers/md sources O:) */ unsigned long now; int i, count, max = 0; int speed; for (i = 0; i < 5; i++) { now = jiffies; count = 0; while (jiffies == now) { mb(); ixt_a->ixt_a_hmac_hash(ixt_a, test_key_a, test_auth, BUFSZ, test_hash, AHHMAC_HASHLEN); mb(); count++; mb(); } if (count > max) max = count; } speed = max * (HZ * BUFSZ / 1024); printk(KERN_INFO "klips_info: ipsec_alg_test_auth: " "%s hash speed=%d KB/s\n", ixt_a->ixt_common.ixt_name, speed); } out: if (buf) kfree(buf); if (ixt_a) ipsec_alg_put((struct ipsec_alg *)ixt_a); return ret; # undef test_auth # undef test_key_a # undef test_key # undef test_hash # undef test_size } int ipsec_alg_test(unsigned alg_type, unsigned alg_id, int test) { switch (alg_type) { case IPSEC_ALG_TYPE_ENCRYPT: return ipsec_alg_test_encrypt(alg_id, test); break; case IPSEC_ALG_TYPE_AUTH: return ipsec_alg_test_auth(alg_id, test); break; } printk(KERN_ERR "klips_info: ipsec_alg_test() called incorrectly: " "alg_type=%d alg_id=%d\n", alg_type, alg_id); return -EINVAL; } int ipsec_alg_init(void) { KLIPS_PRINT(1, "klips_info:ipsec_alg_init: " "KLIPS alg v=%d.%d.%d-%d (EALG_MAX=%d, AALG_MAX=%d)\n", IPSEC_ALG_VERSION_QUAD(IPSEC_ALG_VERSION), K_SADB_EALG_MAX, K_SADB_AALG_MAX); /* Initialize tables */ write_lock_bh(&ipsec_alg_lock); ipsec_alg_hash_init(); write_unlock_bh(&ipsec_alg_lock); /* Initialize static algos */ KLIPS_PRINT(1, "klips_info:ipsec_alg_init: " "calling ipsec_alg_static_init()\n"); #if defined(CONFIG_KLIPS_ENC_AES) && CONFIG_KLIPS_ENC_AES && \ !defined(CONFIG_KLIPS_ENC_AES_MODULE) /* register our own AES code */ { extern int ipsec_aes_init(void); ipsec_aes_init(); } #endif #if defined(CONFIG_KLIPS_ENC_3DES) && !defined(CONFIG_KLIPS_ENC_3DES_MODULE) /* register our own 3DES code */ { extern int ipsec_3des_init(void); ipsec_3des_init(); } #endif /* If we are doing CryptoAPI, then init */ #if defined(CONFIG_KLIPS_ENC_CRYPTOAPI) && CONFIG_KLIPS_ENC_CRYPTOAPI && \ !defined(CONFIG_KLIPS_ENC_CRYPTOAPI_MODULE) { extern int ipsec_cryptoapi_init(void); ipsec_cryptoapi_init(); } #endif return 0; } /********************************************** * * INTERFACE for ipsec_sa init and wipe * **********************************************/ /* * Called from pluto -> ipsec_sa.c:ipsec_sa_delchain() */ int ipsec_alg_sa_wipe(struct ipsec_sa *sa_p) { struct ipsec_alg *ixt; if ((ixt = (struct ipsec_alg *)sa_p->ips_alg_enc)) { KLIPS_PRINT(debug_pfkey, "klips_debug: ipsec_alg_sa_wipe() :" "unlinking for encalg=%d\n", ixt->ixt_support.ias_id); ipsec_alg_put(ixt); } if ((ixt = (struct ipsec_alg *)sa_p->ips_alg_auth)) { KLIPS_PRINT(debug_pfkey, "klips_debug: ipsec_alg_sa_wipe() :" "unlinking for authalg=%d\n", ixt->ixt_support.ias_id); ipsec_alg_put(ixt); } return 0; } IPSEC_PROCFS_DEBUG_NO_STATIC int ipsec_xform_show(struct seq_file *seq, void *offset) { int i; struct list_head *head; struct ipsec_alg *ixt; KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, "klips_debug:ipsec_tncfg_show: seq=%p offset=%p\n", seq, offset); for (i=0, head = ipsec_alg_hash_table; i < IPSEC_ALG_HASHSZ; i++, head++) { struct list_head *p; for (p = head->next; p != head; p = p->next) { ixt = list_entry(p, struct ipsec_alg, ixt_list); seq_printf(seq, "VERSION=%d TYPE=%d ID=%d NAME=%s REFCNT=%d ", ixt->ixt_version, ixt->ixt_alg_type, ixt->ixt_support.ias_id, ixt->ixt_name, atomic_read(&ixt->ixt_refcnt)); seq_printf(seq, "STATE=%08x BLOCKSIZE=%d IVLEN=%d " "KEYMINBITS=%d KEYMAXBITS=%d ", ixt->ixt_state, ixt->ixt_blocksize, ixt->ixt_support.ias_ivlen, ixt->ixt_support.ias_keyminbits, ixt->ixt_support.ias_keymaxbits); seq_printf(seq, "IVLEN=%d KEYMINBITS=%d KEYMAXBITS=%d ", ixt->ixt_support.ias_ivlen, ixt->ixt_support.ias_keyminbits, ixt->ixt_support.ias_keymaxbits); switch (ixt->ixt_alg_type) { case IPSEC_ALG_TYPE_AUTH: { struct ipsec_alg_auth *auth = (struct ipsec_alg_auth *)ixt; seq_printf(seq, "KEYLEN=%d CTXSIZE=%d AUTHLEN=%d ", auth->ixt_a_keylen, auth->ixt_a_ctx_size, auth->ixt_a_authlen); break; } case IPSEC_ALG_TYPE_ENCRYPT: { struct ipsec_alg_enc *enc = (struct ipsec_alg_enc *)ixt; seq_printf(seq, "KEYLEN=%d CTXSIZE=%d ", enc->ixt_e_keylen, enc->ixt_e_ctx_size); break; } } seq_printf(seq, "\n"); } } return 0; } /* * As the author of this module, I ONLY ALLOW using it from * GPL (or same LICENSE TERMS as kernel source) modules. * * In respect to hardware crypto engines this means: * * Closed-source device drivers ARE NOT ALLOWED to use * this interface. * * Closed-source VHDL/Verilog firmware running on * the crypto hardware device IS ALLOWED to use this interface * via a GPL (or same LICENSE TERMS as kernel source) device driver. * --Juan Jose Ciarlante 20/03/2002 (thanks RGB for the correct wording) */ /* * These symbols can only be used from GPL modules * for now, I'm disabling this because it creates false * symbol problems for old modutils. */ #ifdef CONFIG_MODULES #ifndef NET_26 #if 0 #ifndef EXPORT_SYMBOL_GPL #undef EXPORT_SYMBOL_GPL #define EXPORT_SYMBOL_GPL EXPORT_SYMBOL #endif #endif EXPORT_SYMBOL(register_ipsec_alg); EXPORT_SYMBOL(unregister_ipsec_alg); EXPORT_SYMBOL(ipsec_alg_test); #endif #endif libreswan-3.32/linux/net/ipsec/ipsec_alg_cryptoapi.c000066400000000000000000000714561365625662500227000ustar00rootroot00000000000000/* * ipsec_alg to linux cryptoapi GLUE * * Authors: CODE.ar TEAM * Harpo MAxx * JuanJo Ciarlante * Luciano Ruete * (C) 2017 Richard Guy Briggs * (C) 2017 Paul Wouters * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * Example usage: * modinfo -p ipsec_cryptoapi (quite useful info, including supported algos) * modprobe ipsec_cryptoapi * modprobe ipsec_cryptoapi test=1 * modprobe ipsec_cryptoapi excl=1 (exclusive cipher/algo) * modprobe ipsec_cryptoapi noauto=1 aes=1 twofish=1 (only these ciphers) * modprobe ipsec_cryptoapi aes=128,128 (force these keylens) * modprobe ipsec_cryptoapi des_ede3=0 (everything but 3DES) */ #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38) && \ !defined(AUTOCONF_INCLUDED) #include #endif /* * special case: ipsec core modular with this static algo inside: * must avoid MODULE magic for this file */ #if defined(CONFIG_KLIPS_MODULE) && defined(CONFIG_KLIPS_ENC_CRYPTOAPI) #undef MODULE #endif #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) # include #endif #include #include /* printk() */ #include /* error codes */ #include /* size_t */ #include #include "libreswan/ipsec_kversion.h" #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) # include #endif /* Check if __exit is defined, if not null it */ #ifndef __exit #define __exit #endif /* warn the innocent */ #if !defined (CONFIG_CRYPTO) && !defined (CONFIG_CRYPTO_MODULE) #warning \ "No linux CryptoAPI configured, install 2.4.22+ or 2.6.x or enable CryptoAPI" #define NO_CRYPTOAPI_SUPPORT #endif #include "libreswan.h" #include "libreswan/ipsec_alg.h" #include "libreswan/ipsec_xform.h" #include #ifdef HAS_SKCIPHER #include #define crypto_has_blkcipher crypto_has_skcipher #define crypto_alloc_blkcipher crypto_alloc_skcipher #define crypto_blkcipher_tfm crypto_skcipher_tfm #define crypto_blkcipher_setkey crypto_skcipher_setkey #define crypto_blkcipher_ivsize crypto_skcipher_ivsize #define crypto_blkcipher_cast __crypto_skcipher_cast #endif /* HAS_SKCIPHER */ #ifdef CRYPTO_API_VERSION_CODE #warning \ "Old CryptoAPI is not supported. Only linux-2.4.22+ or linux-2.6.x are supported" #define NO_CRYPTOAPI_SUPPORT #endif #ifdef NO_CRYPTOAPI_SUPPORT #warning "Building an unusable module :P" /* Catch old CryptoAPI by not allowing module to load */ IPSEC_ALG_MODULE_INIT_STATIC( ipsec_cryptoapi_init ){ printk(KERN_WARNING "ipsec_cryptoapi.o was not built on stock Linux CryptoAPI (2.4.22+ or 2.6.x), not loading.\n"); return -EINVAL; } #else #if LINUX_VERSION_CODE > KERNEL_VERSION(3, 0, 0) #include #else #include #endif #include #include /* * CryptoAPI compat code - we use the current API and macro back to * the older ones. */ #ifndef CRYPTO_TFM_MODE_CBC /* * As of linux-2.6.21 this is no longer defined, and presumably no longer * needed to be passed into the crypto core code. */ #define CRYPTO_TFM_MODE_CBC 0 #define CRYPTO_TFM_MODE_ECB 0 #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24) static inline void sg_set_page(struct scatterlist *sg, struct page *page, unsigned int len, unsigned int offset) { sg->page = page; sg->offset = offset; sg->length = len; } static inline void *sg_virt(struct scatterlist *sg) { return page_address(sg->page) + sg->offset; } #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) #define offset_in_page(p) ((unsigned long)(p) & ~PAGE_MASK) #endif #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) && \ !HAVE_BACKPORTED_NEW_CRYPTOAPI /* * Linux 2.6.19 introduced a new Crypto API, setup macro's to convert new * API into old API. Some SuSe distributions have backported it. */ /* Symmetric/Block Cipher */ struct blkcipher_desc { struct crypto_tfm *tfm; void *info; }; #define ecb(X) \ #X #define cbc(X) \ #X #define crypto_has_blkcipher(X, Y, Z) crypto_alg_available(X, \ 0) #define crypto_blkcipher_cast(X) X #define crypto_blkcipher_tfm(X) X #define crypto_alloc_blkcipher(X, Y, Z) crypto_alloc_tfm(X, \ CRYPTO_TFM_MODE_CBC) #define crypto_blkcipher_ivsize(X) \ crypto_tfm_alg_ivsize(X) #define crypto_blkcipher_blocksize(X) \ crypto_tfm_alg_blocksize(X) #define crypto_blkcipher_setkey(X, Y, Z) crypto_cipher_setkey(X, \ Y, \ Z) #define crypto_blkcipher_encrypt_iv(W, X, Y, Z) \ crypto_cipher_encrypt_iv((W)->tfm, X, Y, Z, (u8 *)((W)->info)) #define crypto_blkcipher_decrypt_iv(W, X, Y, Z) \ crypto_cipher_decrypt_iv((W)->tfm, X, Y, Z, (u8 *)((W)->info)) /* Hash/HMAC/Digest */ struct hash_desc { struct crypto_tfm *tfm; }; #define hmac(X) #X #ifdef HAS_AHASH #define crypto_has_ahash(X, Y, Z) crypto_alg_available(X,0) #define crypto_alloc_ahash(X, Y, Z) crypto_alloc_tfm(X, 0) #define crypto_ahash_digest(W, X, Y, Z) crypto_digest_digest((W)->tfm, X, sg_num, Z) #else #define crypto_alloc_hash(X, Y, Z) crypto_alloc_tfm(X, 0) #define crypto_hash_digestsize(X) crypto_tfm_alg_digestsize(X) #define crypto_hash_digest(W, X, Y, Z) crypto_digest_digest((W)->tfm, X, sg_num, Z) #endif #define crypto_hash_cast(X) X #define crypto_hash_tfm(X) X /* Asymmetric Cipher */ #define crypto_has_cipher(X, Y, Z) crypto_alg_available(X, \ 0) /* Compression */ #define crypto_has_comp(X, Y, Z) crypto_alg_available(X, \ 0) #define crypto_comp_tfm(X) X #define crypto_comp_cast(X) X #define crypto_alloc_comp(X, Y, Z) crypto_alloc_tfm(X, 0) #else #define ecb(X) "ecb(" #X ")" #define cbc(X) "cbc(" #X ")" #define hmac(X) "hmac(" #X ")" #endif /* if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) */ #define CIPHERNAME_NULL "cipher_null" #define CIPHERNAME_AES cbc(aes) #define CIPHERNAME_3DES cbc(des3_ede) #define CIPHERNAME_CAST cbc(cast5) #define CIPHERNAME_SERPENT cbc(serpent) #define CIPHERNAME_TWOFISH cbc(twofish) /* 1DES no longer supported */ #undef CIPHERNAME_1DES #define DIGESTNAME_MD5 "hmac(md5)" #define DIGESTNAME_SHA "hmac(sha1)" #define DIGESTNAME_SHA2_256 "hmac(sha256)" #define DIGESTNAME_SHA2_256_TRUNC "hmac(sha256)" #define DIGESTNAME_SHA2_384 "hmac(sha384)" #define DIGESTNAME_SHA2_512 "hmac(sha512)" #define ESP_NULL 11 #define ESP_SERPENT 252 /* from ipsec drafts */ #define ESP_TWOFISH 253 /* from ipsec drafts */ MODULE_AUTHOR("Juanjo Ciarlante, Harpo MAxx, Luciano Ruete"); static int debug_crypto = 0; static int test_crypto = 0; static int excl_crypto = 0; static int noauto = 0; module_param(debug_crypto, int, 0644); module_param(test_crypto, int, 0644); module_param(excl_crypto, int, 0644); module_param(noauto, int, 0644); MODULE_PARM_DESC(noauto, "Don't try all known algos, just setup enabled ones"); static int cipher_null[] = { -1, -1 }; static int des_ede3[] = { -1, -1 }; static int aes[] = { -1, -1 }; static int cast[] = { -1, -1 }; static int serpent[] = { -1, -1 }; static int twofish[] = { -1, -1 }; static int md5[] = {-1, -1}; static int sha1[] = {-1, -1}; static int sha256[] = {-1, -1}; static int sha512[] = {-1, -1}; static int sha384[] = {-1, -1}; module_param_array(cipher_null, int, NULL, 0444); module_param_array(des_ede3, int, NULL, 0444); module_param_array(aes, int, NULL, 0444); module_param_array(cast, int, NULL, 0444); module_param_array(serpent, int, NULL, 0444); module_param_array(twofish, int, NULL, 0444); MODULE_PARM_DESC(cipher_null, "0: disable | 1: force_enable | min,max: dontuse"); MODULE_PARM_DESC(des_ede3, "0: disable | 1: force_enable | min,max: dontuse"); MODULE_PARM_DESC(aes, "0: disable | 1: force_enable | min,max: keybitlens"); MODULE_PARM_DESC(cast, "0: disable | 1: force_enable | min,max: keybitlens"); MODULE_PARM_DESC(serpent, "0: disable | 1: force_enable | min,max: keybitlens"); MODULE_PARM_DESC(twofish, "0: disable | 1: force_enable | min,max: keybitlens"); struct ipsec_alg_capi_cipher { const char *ciphername; /* cryptoapi's ciphername */ unsigned blocksize; unsigned short minbits; unsigned short maxbits; int *parm; /* lkm param for this cipher */ struct ipsec_alg_enc alg; /* note it's not a pointer */ }; static struct ipsec_alg_capi_cipher alg_capi_carray[] = { { CIPHERNAME_AES, 16, 128, 256, aes, { ixt_common:{ ixt_support:{ ias_id: ESP_AES } } } }, { CIPHERNAME_TWOFISH, 16, 128, 256, twofish, { ixt_common:{ ixt_support:{ ias_id: ESP_TWOFISH, } } } }, { CIPHERNAME_SERPENT, 16, 128, 256, serpent, { ixt_common:{ ixt_support:{ ias_id: ESP_SERPENT, } } } }, { CIPHERNAME_CAST, 8, 128, 128, cast, { ixt_common:{ ixt_support:{ ias_id: ESP_CAST, } } } }, { CIPHERNAME_3DES, 8, 192, 192, des_ede3, { ixt_common:{ ixt_support:{ ias_id: ESP_3DES, } } } }, { CIPHERNAME_NULL, 1, 0, 0, cipher_null, { ixt_common:{ ixt_support:{ ias_id: ESP_NULL, } } } }, { NULL, 0, 0, 0, NULL, {} } }; struct ipsec_alg_capi_digest { const char *digestname; /* cryptoapi's digestname */ unsigned blocksize; unsigned short minbits; unsigned short maxbits; unsigned short authlen; int *parm; /* lkm param for this digest */ struct ipsec_alg_auth alg; /* note it's not a pointer */ }; static struct ipsec_alg_capi_digest alg_capi_darray[] = { { DIGESTNAME_MD5, 64, 128, 128, 12, md5, { ixt_common:{ ixt_support:{ ias_id: AH_MD5, }}}}, { DIGESTNAME_SHA, 64, 160, 160, 12, sha1, { ixt_common:{ ixt_support:{ ias_id: AH_SHA, }}}}, { DIGESTNAME_SHA2_256, 64, 256, 256, 16, sha256, { ixt_common:{ ixt_support:{ ias_id: AH_SHA2_256,}}}}, { DIGESTNAME_SHA2_384, 128, 384, 384, 24, sha384, { ixt_common:{ ixt_support:{ ias_id: AH_SHA2_384,}}}}, { DIGESTNAME_SHA2_512, 128, 512, 512, 32, sha512, { ixt_common:{ ixt_support:{ ias_id: AH_SHA2_512,}}}}, { DIGESTNAME_SHA2_256_TRUNC, 64, 256, 256, 12, sha256, { ixt_common:{ ixt_support:{ ias_id: AH_SHA2_256_TRUNC,}}}}, { NULL, 0, 0, 0, 0, NULL, {} } }; /* * "generic" linux cryptoapi setup_cipher() function */ int setup_cipher(const char *ciphername) { return crypto_has_blkcipher(ciphername, 0, 0); } /* * setups ipsec_alg_capi_cipher "hyper" struct components, calling * register_ipsec_alg for cointaned ipsec_alg object */ static void _capi_destroy_key(struct ipsec_alg_enc *alg, __u8 *key_e); static __u8 * _capi_new_key(struct ipsec_alg_enc *alg, const __u8 *key, size_t keylen); static int _capi_cbc_encrypt(struct ipsec_alg_enc *alg, __u8 * key_e, __u8 * in, int ilen, __u8 * iv, int encrypt); static int setup_ipsec_alg_capi_cipher(struct ipsec_alg_capi_cipher *cptr) { int ret; cptr->alg.ixt_common.ixt_version = IPSEC_ALG_VERSION; cptr->alg.ixt_common.ixt_module = THIS_MODULE; atomic_set(&cptr->alg.ixt_common.ixt_refcnt, 0); /* fill_and_terminate(cptr->alg.ixt_common.ixt_name, cptr->ciphername, * sizeof(cptr->alg.ixt_common.ixt_name)); */ strncpy(cptr->alg.ixt_common.ixt_name, cptr->ciphername, sizeof(cptr->alg.ixt_common.ixt_name)-1); cptr->alg.ixt_common.ixt_name[sizeof(cptr->alg.ixt_common.ixt_name)-1] = '\0'; cptr->alg.ixt_common.ixt_blocksize = cptr->blocksize; cptr->alg.ixt_common.ixt_support.ias_keyminbits = cptr->minbits; cptr->alg.ixt_common.ixt_support.ias_keymaxbits = cptr->maxbits; cptr->alg.ixt_common.ixt_state = 0; if (excl_crypto) cptr->alg.ixt_common.ixt_state |= IPSEC_ALG_ST_EXCL; cptr->alg.ixt_e_keylen = cptr->alg.ixt_common.ixt_support.ias_keymaxbits / 8; cptr->alg.ixt_e_ctx_size = 0; cptr->alg.ixt_common.ixt_support.ias_exttype = IPSEC_ALG_TYPE_ENCRYPT; cptr->alg.ixt_e_new_key = _capi_new_key; cptr->alg.ixt_e_destroy_key = _capi_destroy_key; cptr->alg.ixt_e_cbc_encrypt = _capi_cbc_encrypt; cptr->alg.ixt_common.ixt_data = cptr; ret = register_ipsec_alg_enc(&cptr->alg); printk(KERN_INFO "KLIPS cryptoapi interface: " "alg_type=%d alg_id=%d name=%s " "keyminbits=%d keymaxbits=%d, %s(%d)\n", cptr->alg.ixt_common.ixt_support.ias_exttype, cptr->alg.ixt_common.ixt_support.ias_id, cptr->alg.ixt_common.ixt_name, cptr->alg.ixt_common.ixt_support.ias_keyminbits, cptr->alg.ixt_common.ixt_support.ias_keymaxbits, ret ? "not found" : "found", ret); return ret; } /* * called in ipsec_sa_wipe() time, will destroy key contexts * and do 1 unbind() */ static void _capi_destroy_key(struct ipsec_alg_enc *alg, __u8 *key_e) { struct crypto_tfm *tfm = (struct crypto_tfm*)key_e; if (debug_crypto > 0) printk(KERN_DEBUG "klips_debug: _capi_destroy_key:" "name=%s key_e=%p\n", alg->ixt_common.ixt_name, key_e); if (!key_e) { printk(KERN_ERR "klips_debug: _capi_destroy_key:" "name=%s NULL key_e!\n", alg->ixt_common.ixt_name); return; } crypto_free_tfm(tfm); } /* * create new key context, need alg->ixt_data to know which * (of many) cipher inside this module is the target */ static __u8 *_capi_new_key(struct ipsec_alg_enc *alg, const __u8 *key, size_t keylen) { struct ipsec_alg_capi_cipher *cptr; struct crypto_tfm *tfm = NULL; cptr = alg->ixt_common.ixt_data; if (!cptr) { printk(KERN_ERR "_capi_new_key(): " "NULL ixt_data (?!) for \"%s\" algo\n", alg->ixt_common.ixt_name); goto err; } if (debug_crypto > 0) printk(KERN_DEBUG "klips_debug:_capi_new_key:" "name=%s cptr=%p key=%p keysize=%zd\n", alg->ixt_common.ixt_name, cptr, key, keylen); /* * alloc tfm */ tfm = crypto_blkcipher_tfm(crypto_alloc_blkcipher(cptr->ciphername, 0, 0)); if (!tfm) { printk(KERN_ERR "_capi_new_key(): " "NULL tfm for \"%s\" cryptoapi (\"%s\") algo\n", alg->ixt_common.ixt_name, cptr->ciphername); goto err; } if (crypto_blkcipher_setkey(crypto_blkcipher_cast(tfm), key, keylen) < 0) { printk(KERN_ERR "_capi_new_key(): " "failed new_key() for \"%s\" cryptoapi algo (keylen=%zd)\n", alg->ixt_common.ixt_name, keylen); crypto_free_tfm(tfm); tfm = NULL; } err: if (debug_crypto > 0) printk(KERN_DEBUG "klips_debug:_capi_new_key:" "name=%s key=%p keylen=%zd tfm=%p\n", alg->ixt_common.ixt_name, key, keylen, tfm); return (__u8 *) tfm; } /* * core encryption function: will use cx->ci to call actual cipher's * cbc function */ static int _capi_cbc_encrypt(struct ipsec_alg_enc *alg, __u8 * key_e, __u8 * in, int ilen, __u8 * iv, int encrypt) { int error = 0; struct crypto_tfm *tfm = (struct crypto_tfm *)key_e; struct scatterlist sg; #ifdef HAS_SKCIPHER SYNC_SKCIPHER_REQUEST_ON_STACK(req, __crypto_skcipher_cast(tfm)); #else struct blkcipher_desc desc; #endif int ivsize = crypto_blkcipher_ivsize(crypto_blkcipher_cast(tfm)); char ivp[ivsize]; /* we do not want them copying back the IV in place so copy it */ memcpy(ivp, iv, ivsize); if (debug_crypto > 1) printk(KERN_DEBUG "klips_debug:_capi_cbc_encrypt:" "key_e=%p " "in=%p out=%p ilen=%d iv=%p encrypt=%d\n", key_e, in, in, ilen, iv, encrypt); memset(&sg, 0, sizeof(sg)); sg_init_table(&sg, 1); sg_set_page(&sg, virt_to_page(in), ilen, offset_in_page(in)); #ifdef HAS_SKCIPHER skcipher_request_set_tfm(req, crypto_blkcipher_cast(tfm)); skcipher_request_set_callback(req, 0, NULL, NULL); skcipher_request_set_crypt(req, &sg, &sg, ilen, (void*)&ivp[0]); if (encrypt) error = crypto_skcipher_encrypt(req); else error = crypto_skcipher_decrypt(req); skcipher_request_zero(req); #else memset(&desc, 0, sizeof(desc)); desc.tfm = crypto_blkcipher_cast(tfm); desc.info = (void *) &ivp[0]; if (encrypt) error = crypto_blkcipher_encrypt_iv(&desc, &sg, &sg, ilen); else error = crypto_blkcipher_decrypt_iv(&desc, &sg, &sg, ilen); #endif if (debug_crypto > 1) printk(KERN_DEBUG "klips_debug:_capi_cbc_encrypt:" "error=%d\n", error); return (error < 0) ? error : ilen; } /* * main initialization loop: for each cipher in list, do * 1) setup cryptoapi cipher else continue * 2) register ipsec_alg object */ static int setup_cipher_list(struct ipsec_alg_capi_cipher *clist) { struct ipsec_alg_capi_cipher *cptr; /* foreach cipher in list ... */ for (cptr = clist; cptr->ciphername; cptr++) { /* * see if cipher has been disabled (0) or * if noauto set and not enabled (1) */ if (cptr->parm[0] == 0 || (noauto && cptr->parm[0] < 0)) { if (debug_crypto > 0) printk(KERN_INFO "setup_cipher_list(): " "ciphername=%s skipped at user request: " "noauto=%d parm[0]=%d parm[1]=%d\n", cptr->ciphername, noauto, cptr->parm[0], cptr->parm[1]); continue; } if (debug_crypto > 0) printk(KERN_INFO "setup_cipher_list(): going to init ciphername=%s: noauto=%d parm[0]=%d parm[1]=%d\n", cptr->ciphername, noauto, cptr->parm[0], cptr->parm[1]); /* * use a local ci to avoid touching cptr->ci, * if register ipsec_alg success then bind cipher */ if (cptr->alg.ixt_common.ixt_support.ias_name == NULL) cptr->alg.ixt_common.ixt_support.ias_name = cptr->ciphername; if ( setup_cipher(cptr->ciphername) ) { if (debug_crypto > 0) printk(KERN_DEBUG "klips_debug:" "setup_cipher_list():" "ciphername=%s found\n", cptr->ciphername); if (setup_ipsec_alg_capi_cipher(cptr) != 0) { printk(KERN_ERR "klips_debug:" "setup_cipher_list():" "ciphername=%s failed ipsec_alg_register\n", cptr->ciphername); } } else { printk(KERN_INFO "KLIPS: lookup for ciphername=%s: not found\n", cptr->ciphername); } } return 0; } /* * deregister ipsec_alg objects and unbind ciphers */ static int unsetup_cipher_list(struct ipsec_alg_capi_cipher *clist) { struct ipsec_alg_capi_cipher *cptr; /* foreach cipher in list ... */ for (cptr = clist; cptr->ciphername; cptr++) { if (cptr->alg.ixt_common.ixt_state & IPSEC_ALG_ST_REGISTERED) unregister_ipsec_alg_enc(&cptr->alg); } return 0; } /* * test loop for registered algos */ static int test_cipher_list(struct ipsec_alg_capi_cipher *clist) { int test_ret; struct ipsec_alg_capi_cipher *cptr; /* foreach cipher in list ... */ for (cptr = clist; cptr->ciphername; cptr++) { if (cptr->alg.ixt_common.ixt_state & IPSEC_ALG_ST_REGISTERED) { test_ret = ipsec_alg_test( cptr->alg.ixt_common.ixt_support.ias_exttype, cptr->alg.ixt_common.ixt_support.ias_id, test_crypto); printk("test_cipher_list(alg_type=%d alg_id=%d): test_ret=%d\n", cptr->alg.ixt_common.ixt_support.ias_exttype, cptr->alg.ixt_common.ixt_support.ias_id, test_ret); } } return 0; } /* * "generic" linux cryptoapi setup_digest() function */ int setup_digest(const char *digestname) { #ifdef HAS_AHASH return crypto_has_ahash(digestname, 0, 0); #else return crypto_has_hash(digestname, 0, 0); #endif } /* * setups ipsec_alg_capi_dgest "hyper" struct components, calling * register_ipsec_alg for cointaned ipsec_alg object */ static void _capi_destroy_hmac_key (struct ipsec_alg_auth *alg, __u8 *key_a); static __u8 * _capi_hmac_new_key(struct ipsec_alg_auth *alg, const __u8 *key, int keylen); static int _capi_hmac_hash(struct ipsec_alg_auth *alg, __u8 *key_a, const __u8 *dat, int len, __u8 *hash, int hashlen); static int setup_ipsec_alg_capi_digest(struct ipsec_alg_capi_digest *dptr) { int ret; dptr->alg.ixt_common.ixt_version = IPSEC_ALG_VERSION; dptr->alg.ixt_common.ixt_module = THIS_MODULE; atomic_set(& dptr->alg.ixt_common.ixt_refcnt, 0); /* fill_and_terminate(dptr->alg.ixt_common.ixt_name, dptr->digestname, sizeof(dptr->alg.ixt_common.ixt_name)); */ strncpy(dptr->alg.ixt_common.ixt_name, dptr->digestname, sizeof(dptr->alg.ixt_common.ixt_name)-1); dptr->alg.ixt_common.ixt_name[sizeof(dptr->alg.ixt_common.ixt_name)-1] = '\0'; dptr->alg.ixt_common.ixt_blocksize=dptr->blocksize; dptr->alg.ixt_common.ixt_support.ias_keyminbits=dptr->minbits; dptr->alg.ixt_common.ixt_support.ias_keymaxbits=dptr->maxbits; dptr->alg.ixt_common.ixt_support.ias_ivlen=0; dptr->alg.ixt_common.ixt_state = 0; if (excl_crypto) dptr->alg.ixt_common.ixt_state |= IPSEC_ALG_ST_EXCL; dptr->alg.ixt_a_keylen=dptr->alg.ixt_common.ixt_support.ias_keymaxbits/8; dptr->alg.ixt_a_ctx_size = sizeof(struct crypto_tfm); dptr->alg.ixt_a_authlen = dptr->authlen; dptr->alg.ixt_common.ixt_support.ias_exttype = IPSEC_ALG_TYPE_AUTH; dptr->alg.ixt_a_hmac_new_key = _capi_hmac_new_key; dptr->alg.ixt_a_hmac_hash = _capi_hmac_hash; dptr->alg.ixt_a_destroy_key = _capi_destroy_hmac_key; dptr->alg.ixt_common.ixt_data = dptr; ret=register_ipsec_alg_auth(&dptr->alg); printk(KERN_INFO "KLIPS cryptoapi interface: " "alg_type=%d alg_id=%d name=%s " "ctx_size=%d keyminbits=%d keymaxbits=%d, %s(%d)\n", dptr->alg.ixt_common.ixt_support.ias_exttype, dptr->alg.ixt_common.ixt_support.ias_id, dptr->alg.ixt_common.ixt_name, dptr->alg.ixt_a_ctx_size, dptr->alg.ixt_common.ixt_support.ias_keyminbits, dptr->alg.ixt_common.ixt_support.ias_keymaxbits, ret ? "not found" : "found", ret); return ret; } /* * called in ipsec_sa_wipe() time, will destroy key contexts * and do 1 unbind() */ static void _capi_destroy_hmac_key (struct ipsec_alg_auth *alg, __u8 *key_a) { #ifdef HAS_AHASH struct crypto_ahash *tfm = (struct crypto_ahash*)key_a; #else struct crypto_hash *tfm = (struct crypto_hash*)key_a; #endif if (debug_crypto > 0) printk(KERN_DEBUG "klips_debug: _capi_destroy_hmac_key:" "name=%s key_e=%p\n", alg->ixt_common.ixt_name, key_a); if (!key_a) { printk(KERN_ERR "klips_debug: _capi_destroy_hmac_key:" "name=%s NULL key_e!\n", alg->ixt_common.ixt_name); return; } #ifdef HAS_AHASH crypto_free_ahash(tfm); #else crypto_free_hash(tfm); #endif } /* * create hash * */ static __u8 * _capi_hmac_new_key(struct ipsec_alg_auth *alg, const __u8 *key, int keylen) { struct ipsec_alg_capi_digest *dptr; #ifdef HAS_AHASH struct crypto_ahash *tfm = NULL; #else struct crypto_hash *tfm = NULL; #endif int ret = 0; dptr = alg->ixt_common.ixt_data; if (!dptr) { printk(KERN_ERR "_capi_hmac_new_key_auth(): " "NULL ixt_data (?!) for \"%s\" algo\n" , alg->ixt_common.ixt_name); goto err; } if (debug_crypto > 0) printk(KERN_DEBUG "klips_debug:_capi_hmac_new_key_auth:" "name=%s dptr=%p key=%p keysize=%d\n", alg->ixt_common.ixt_name, dptr, key, keylen); #ifdef HAS_AHASH tfm = crypto_alloc_ahash(dptr->digestname, 0, CRYPTO_ALG_ASYNC); #else tfm = crypto_alloc_hash(dptr->digestname, 0, CRYPTO_ALG_ASYNC); #endif if (IS_ERR(tfm)) { printk(KERN_ERR "_capi_hmac_new_key_auth(): " "NULL hmac for \"%s\" cryptoapi (\"%s\") algo\n" , alg->ixt_common.ixt_name, dptr->digestname); goto err; } #ifdef HAS_AHASH if (crypto_ahash_setkey(tfm, key, keylen)<0) #else if (crypto_hash_setkey(tfm, key, keylen)<0) #endif { printk(KERN_ERR "_capi_hmac_new_key_auth(): " "failed set_key() for \"%s\" cryptoapi algo (key=%p, keylen=%d, err=%d)\n" , alg->ixt_common.ixt_name, key, keylen, ret); #ifdef HAS_AHASH crypto_free_ahash(tfm); #else crypto_free_hash(tfm); #endif tfm=NULL; goto err; } err: if (debug_crypto > 0) printk(KERN_DEBUG "klips_debug:_capi_hmac_new_key:" "name=%s key=%p keylen=%d tfm=%p\n", alg->ixt_common.ixt_name, key, keylen, tfm); return (__u8 *) tfm; } /* * core encryption function * */ static int _capi_hmac_hash(struct ipsec_alg_auth *alg, __u8 *key_a, const __u8 *dat, int len, __u8 *hash, int hashlen) { #ifdef HAS_AHASH struct crypto_ahash *tfm = (struct crypto_ahash*)key_a; struct ahash_request *req; #else struct crypto_hash *tfm = (struct crypto_hash*)key_a; struct hash_desc desc; #endif struct scatterlist sg; int ret = 0; char hash_buf[512]; if (debug_crypto > 0) printk(KERN_DEBUG "klips_debug: _capi_hmac_hash:" "name=%s key_a=%p hash=%p dat=%p len=%d keylen=%d\n", alg->ixt_common.ixt_name, key_a, hash, dat, len, hashlen); if (!key_a) { printk(KERN_ERR "klips_debug: _capi_hmac_hash:" "name=%s NULL key_a!\n", alg->ixt_common.ixt_name); return -1; } memset(&sg, 0, sizeof(sg)); sg_init_table(&sg, 1); sg_set_buf(&sg, dat, len); #ifdef HAS_AHASH req = ahash_request_alloc(tfm, GFP_ATOMIC); if (!req) return -1; ahash_request_set_callback(req, 0, NULL, NULL); ahash_request_set_crypt(req, &sg, hash_buf, len); ret = crypto_ahash_digest(req); #else memset(&desc, 0, sizeof(desc)); desc.tfm = tfm; desc.flags = 0; ret = crypto_hash_digest(&desc, &sg, len, hash_buf); #endif memcpy(hash, hash_buf, hashlen); #ifdef HAS_AHASH ahash_request_free(req); #endif return ret; } /* * main initialization loop: for each digest in list, do * 1) setup cryptoapi digest else continue * 2) register ipsec_alg object */ static int setup_digest_list (struct ipsec_alg_capi_digest* dlist) { struct ipsec_alg_capi_digest *dptr; /* foreach digest in list ... */ for (dptr=dlist;dptr->digestname;dptr++) { /* * see if digest has been disabled (0) or * if noauto set and not enabled (1) */ if (dptr->parm[0] == 0 || (noauto && dptr->parm[0] < 0)) { if (debug_crypto>0) printk(KERN_INFO "setup_digest_list(): " "digest=%s skipped at user request: " "noauto=%d parm[0]=%d parm[1]=%d\n" , dptr->digestname , noauto , dptr->parm[0] , dptr->parm[1]); continue; } if (debug_crypto>0) printk(KERN_INFO "setup_digest_list(): going to init digest=%s: noauto=%d parm[0]=%d parm[1]=%d\n" , dptr->digestname , noauto , dptr->parm[0] , dptr->parm[1]); /* * use a local ci to avoid touching dptr->ci, * if register ipsec_alg success then bind digest */ if (dptr->alg.ixt_common.ixt_support.ias_name == NULL) { dptr->alg.ixt_common.ixt_support.ias_name = dptr->digestname; } if (setup_digest(dptr->digestname) ) { if (debug_crypto > 0) printk(KERN_DEBUG "klips_debug:" "setup_digest_list():" "digestname=%s found\n" , dptr->digestname); if (setup_ipsec_alg_capi_digest(dptr) != 0) { printk(KERN_ERR "klips_debug:" "setup_digest_list():" "digestname=%s failed ipsec_alg_register\n" , dptr->digestname); } } else { printk(KERN_INFO "KLIPS: lookup for digestname=%s: not found\n", dptr->digestname); } } return 0; } /* * deregister ipsec_alg objects and unbind digests */ static int unsetup_digest_list (struct ipsec_alg_capi_digest* dlist) { struct ipsec_alg_capi_digest *dptr; /* foreach digest in list ... */ for (dptr=dlist;dptr->digestname;dptr++) { if (dptr->alg.ixt_common.ixt_state & IPSEC_ALG_ST_REGISTERED) { unregister_ipsec_alg_auth(&dptr->alg); } } return 0; } /* * test loop for registered algos */ static int test_digest_list (struct ipsec_alg_capi_digest* dlist) { int test_ret; struct ipsec_alg_capi_digest *dptr; /* foreach digest in list ... */ for (dptr=dlist;dptr->digestname;dptr++) { if (dptr->alg.ixt_common.ixt_state & IPSEC_ALG_ST_REGISTERED) { test_ret=ipsec_alg_test( dptr->alg.ixt_common.ixt_support.ias_exttype, dptr->alg.ixt_common.ixt_support.ias_id, test_crypto); printk("test_digest_list(alg_type=%d alg_id=%d): test_ret=%d\n", dptr->alg.ixt_common.ixt_support.ias_exttype, dptr->alg.ixt_common.ixt_support.ias_id, test_ret); } } return 0; } IPSEC_ALG_MODULE_INIT_STATIC( ipsec_cryptoapi_init ){ int ret, test_ret; if ((ret = setup_cipher_list(alg_capi_carray)) < 0) return -EPROTONOSUPPORT; if (ret == 0 && test_crypto) test_ret = test_cipher_list(alg_capi_carray); if ((ret=setup_digest_list(alg_capi_darray)) < 0) return -EPROTONOSUPPORT; if (ret==0 && test_crypto) { test_ret=test_digest_list(alg_capi_darray); } return ret; } IPSEC_ALG_MODULE_EXIT_STATIC( ipsec_cryptoapi_fini ){ unsetup_cipher_list(alg_capi_carray); unsetup_digest_list(alg_capi_darray); } #ifdef MODULE_LICENSE MODULE_LICENSE("GPL"); #endif #endif /* NO_CRYPTOAPI_SUPPORT */ libreswan-3.32/linux/net/ipsec/ipsec_esp.c000066400000000000000000000421241365625662500206200ustar00rootroot00000000000000/* * processing code for ESP * Copyright (C) 2003 Michael Richardson * Copyright (C) 2012 Paul Wouters * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38) && \ !defined(AUTOCONF_INCLUDED) #include #endif #define __NO_VERSION__ #include #include /* printk() */ #include "libreswan/ipsec_param.h" #include /* kmalloc() */ #include /* error codes */ #include /* size_t */ #include /* mark_bh */ #include /* struct device, and other headers */ #include /* eth_type_trans */ #include /* struct iphdr */ #include #include #include /* *lock* */ #include #include #include "libreswan/radij.h" #include "libreswan/ipsec_encap.h" #include "libreswan/ipsec_sa.h" #include "libreswan/ipsec_radij.h" #include "libreswan/ipsec_xform.h" #include "libreswan/ipsec_tunnel.h" #include "libreswan/ipsec_rcv.h" #include "libreswan/ipsec_xmit.h" #include "libreswan/ipsec_auth.h" #ifdef CONFIG_KLIPS_ESP #include "libreswan/ipsec_esp.h" #endif /* CONFIG_KLIPS_ESP */ #include "libreswan/ipsec_proto.h" #include "libreswan/ipsec_alg.h" #ifdef CONFIG_KLIPS_OCF # include "ipsec_ocf.h" #endif #define ESP_DMP(_x, _y, _z) { \ if (debug_rcv && sysctl_ipsec_debug_verbose) \ ipsec_dmp_block((_x), (_y), (_z)); \ } #ifdef CONFIG_KLIPS_ESP enum ipsec_rcv_value ipsec_rcv_esp_checks(struct ipsec_rcv_state *irs, struct sk_buff *skb) { /* XXX this will need to be 8 for IPv6 */ if ((irs->proto == IPPROTO_ESP) && ((skb->len - irs->iphlen) % 4)) { printk("klips_error:ipsec_rcv: " "got packet with content length %d - %d = %d from %s -- should be on 4 octet boundary, packet dropped\n", skb->len, irs->iphlen, skb->len - irs->iphlen, irs->ipsaddr_txt); if (irs->stats) irs->stats->rx_errors++; return IPSEC_RCV_BADLEN; } #if 0 /* The problem with this check manifests itself when using l2tp over esp in * udp over pptp/ppp. This check seems to break for ESPinUDP packets, * probably because of how hard_header_len is used with decapsulation. * * When pinging using -s 0 with Windows, one sees: * skb->len = Payload(0) + ICMP (8) + IP (20) + ESP (16) + UDP (16) = 60. * hard_header_len is calculated as 14 (ethernet) instead of 22 (ppp) * * Manifests itself only with Windows, not with xl2tpd as client. * * Disabling this check should not be harmfull, as broken too-short * packets should fail their integrity check anyway. * * Thanks to Hiren Joshi for his excellent debugging on this * */ if (skb->len < (irs->hard_header_len + sizeof(struct iphdr) + sizeof(struct esphdr))) { KLIPS_PRINT(debug_rcv & DB_RX_INAU, "klips_debug:ipsec_rcv: " "runt esp packet of skb->len=%d received from %s, dropped.\n", skb->len, irs->ipsaddr_txt); if (irs->stats) irs->stats->rx_errors++; return IPSEC_RCV_BADLEN; } #endif irs->protostuff.espstuff.espp = (struct esphdr *)skb_transport_header( skb); irs->said.spi = irs->protostuff.espstuff.espp->esp_spi; return IPSEC_RCV_OK; } enum ipsec_rcv_value ipsec_rcv_esp_decrypt_setup(struct ipsec_rcv_state *irs, struct sk_buff *skb, __u32 *replay, unsigned char **authenticator) { struct esphdr *espp = irs->protostuff.espstuff.espp; /* unsigned char *idat = (unsigned char *)espp; */ KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv: " "packet from %s received with seq=%d (iv)=0x%08x%08x iplen=%d esplen=%d sa=%s\n", irs->ipsaddr_txt, (__u32)ntohl(espp->esp_rpl), (__u32)ntohl(*((__u32 *)(espp->esp_iv) )), (__u32)ntohl(*((__u32 *)(espp->esp_iv) + 1)), irs->len, irs->ilen, irs->sa_len ? irs->sa : " (error)"); *replay = ntohl(espp->esp_rpl); *authenticator = &(skb_transport_header(skb)[irs->ilen]); return IPSEC_RCV_OK; } enum ipsec_rcv_value ipsec_rcv_esp_authcalc(struct ipsec_rcv_state *irs, struct sk_buff *skb) { struct auth_alg *aa; struct esphdr *espp = irs->protostuff.espstuff.espp; union { MD5_CTX md5; SHA1_CTX sha1; } tctx; #ifdef CONFIG_KLIPS_OCF if (irs->ipsp->ocf_in_use) return ipsec_ocf_rcv(irs); #endif #ifdef CONFIG_KLIPS_ALG if (irs->ipsp->ips_alg_auth) { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv: " "ipsec_alg hashing proto=%d... ", irs->said.proto); if (irs->said.proto == IPPROTO_ESP) { ipsec_alg_sa_esp_hash(irs->ipsp, (caddr_t)espp, irs->ilen, irs->hash, irs->ixt_a->ixt_a_authlen); return IPSEC_RCV_OK; } return IPSEC_RCV_BADPROTO; } #endif aa = irs->authfuncs; /* copy the initialized keying material */ memcpy(&tctx, irs->ictx, irs->ictx_len); #ifdef HASH_DEBUG ESP_DMP("ictx", irs->ictx, irs->ictx_len); ESP_DMP("mac_esp", (caddr_t)espp, irs->ilen); #endif (*aa->update)((void *)&tctx, (caddr_t)espp, irs->ilen); (*aa->final)(irs->hash, (void *)&tctx); #ifdef HASH_DEBUG ESP_DMP("hash1", irs->hash, aa->hashlen); #endif memcpy(&tctx, irs->octx, irs->octx_len); #ifdef HASH_DEBUG ESP_DMP("octx", irs->octx, irs->octx_len); #endif (*aa->update)((void *)&tctx, irs->hash, aa->hashlen); (*aa->final)(irs->hash, (void *)&tctx); return IPSEC_RCV_OK; } enum ipsec_rcv_value ipsec_rcv_esp_decrypt(struct ipsec_rcv_state *irs) { #if defined(CONFIG_KLIPS_ALG) || defined(CONFIG_KLIPS_OCF) struct ipsec_sa *ipsp = irs->ipsp; #endif #ifdef CONFIG_KLIPS_ALG struct esphdr *espp = irs->protostuff.espstuff.espp; __u8 *idat; /* pointer to content to be decrypted/authenticated */ int encaplen = 0; struct sk_buff *skb; struct ipsec_alg_enc *ixt_e = NULL; #endif #ifdef CONFIG_KLIPS_OCF if (ipsp->ocf_in_use) return ipsec_ocf_rcv(irs); #endif #ifdef CONFIG_KLIPS_ALG skb = irs->skb; idat = skb_transport_header(skb); /* encaplen is the distance between the end of the IP * header and the beginning of the ESP header. * on ESP headers it is zero, but on UDP-encap ESP * it includes the space for the UDP header. * * Note: UDP-encap code has already moved the * skb->data forward to accommodate this. */ encaplen = skb_transport_header(skb) - (skb_network_header(skb) + irs->iphlen); ixt_e = ipsp->ips_alg_enc; irs->esphlen = ESP_HEADER_LEN + ixt_e->ixt_common.ixt_support.ias_ivlen / 8; KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv: " "encalg=%d esphlen=%d\n", ipsp->ips_encalg, irs->esphlen); idat += irs->esphlen; irs->ilen -= irs->esphlen; if (ipsec_alg_esp_encrypt(ipsp, idat, irs->ilen, espp->esp_iv, IPSEC_ALG_DECRYPT) <= 0) { KLIPS_ERROR(debug_rcv, "klips_error:ipsec_rcv: " "got packet with esplen = %d " "from %s -- should be on " "ENC(%d) octet boundary, " "packet dropped\n", irs->ilen, irs->ipsaddr_txt, ipsp->ips_encalg); if (irs->stats) irs->stats->rx_errors++; return IPSEC_RCV_BAD_DECRYPT; } return ipsec_rcv_esp_post_decrypt(irs); #else return IPSEC_RCV_BAD_DECRYPT; #endif /* CONFIG_KLIPS_ALG */ } enum ipsec_rcv_value ipsec_rcv_esp_post_decrypt(struct ipsec_rcv_state *irs) { struct sk_buff *skb; __u8 *idat; /* pointer to content to be decrypted/authenticated */ struct ipsec_sa *ipsp = irs->ipsp; int pad = 0, padlen; int badpad = 0; int i; skb = irs->skb; idat = skb_transport_header(skb) + irs->esphlen; ESP_DMP("postdecrypt", idat, irs->ilen); irs->next_header = idat[irs->ilen - 1]; padlen = idat[irs->ilen - 2]; pad = padlen + 2 + irs->authlen; KLIPS_PRINT(debug_rcv & DB_RX_IPAD, "klips_debug:ipsec_rcv_esp_post_decrypt: " "padlen=%d, contents: 0x: 0x 0x ...\n", padlen); for (i = 1; i <= padlen; i++) { if ((i % 16) == 1) { KLIPS_PRINT(debug_rcv & DB_RX_IPAD, "klips_debug: %02x:", i - 1); } KLIPS_PRINTMORE(debug_rcv & DB_RX_IPAD, " %02x", idat[irs->ilen - 2 - padlen + i - 1]); if (i != idat[irs->ilen - 2 - padlen + i - 1]) badpad = 1; if ((i % 16) == 0) { KLIPS_PRINTMORE(debug_rcv & DB_RX_IPAD, "\n"); } } if ((i % 16) != 1) { KLIPS_PRINTMORE(debug_rcv & DB_RX_IPAD, "\n"); } if (badpad) { KLIPS_PRINT(debug_rcv & DB_RX_IPAD, "klips_debug:ipsec_rcv_esp_post_decrypt: " "warning, decrypted packet from %s has bad padding\n", irs->ipsaddr_txt); KLIPS_PRINT(debug_rcv & DB_RX_IPAD, "klips_debug:ipsec_rcv_esp_post_decrypt: " "...may be bad decryption -- not dropped\n"); ipsp->ips_errs.ips_encpad_errs += 1; } KLIPS_PRINT(debug_rcv & DB_RX_IPAD, "klips_debug:ipsec_rcv_esp_post_decrypt: " "packet decrypted from %s: next_header = %d, padding = %d\n", irs->ipsaddr_txt, irs->next_header, pad - 2 - irs->authlen); if (lsw_ip_hdr_version(irs) == 6) lsw_ip6_hdr(irs)->payload_len = htons(ntohs(lsw_ip6_hdr(irs)->payload_len) - (irs->esphlen + pad)); else lsw_ip4_hdr(irs)->tot_len = htons(ntohs(lsw_ip4_hdr(irs)->tot_len) - (irs->esphlen + pad)); /* * move the IP header forward by the size of the ESP header, * thus removing the the ESP header from the packet. * * XXX this is really unnecessary, since odds we are in tunnel * mode, and we will be *removing* this IP header. * */ memmove((void *)(idat - irs->iphlen), (void *)(skb_network_header(skb)), irs->iphlen); ESP_DMP("esp postmove", (idat - irs->iphlen), irs->iphlen + irs->ilen); /* skb_pull below, will move up by esphlen */ /* XXX not clear how this can happen, as the message indicates */ if (skb->len < irs->esphlen) { printk(KERN_WARNING "klips_error:ipsec_rcv_esp_post_decrypt: " "tried to skb_pull esphlen=%d, %d available. This should never happen, please report.\n", irs->esphlen, (int)(skb->len)); return IPSEC_RCV_ESP_DECAPFAIL; } skb_pull(skb, irs->esphlen); skb_set_network_header(skb, ipsec_skb_offset(skb, idat - irs->iphlen)); irs->iph = (void *) ip_hdr(skb); ESP_DMP("esp postpull", skb->data, skb->len); /* now, trip off the padding from the end */ KLIPS_PRINT(debug_rcv & DB_RX_PKTRX, "klips_debug:ipsec_rcv: " "trimming to %d.\n", irs->len - irs->esphlen - pad); if (pad + irs->esphlen <= irs->len) { skb_trim(skb, irs->len - irs->esphlen - pad); } else { KLIPS_PRINT(debug_rcv & DB_RX_PKTRX, "klips_debug:ipsec_rcv: " "bogus packet, size is zero or negative, dropping.\n"); return IPSEC_RCV_DECAPFAIL; } ESP_DMP("esp posttrim", skb->data, skb->len); return IPSEC_RCV_OK; } #if 0 /* * */ enum ipsec_xmit_value ipsec_xmit_esp_setup(struct ipsec_xmit_state *ixs) { #ifdef CONFIG_KLIPS_ENC_3DES __u32 iv[2]; #endif struct esphdr *espp; int ilen = 0; int padlen = 0, i; unsigned char *dat; unsigned char *idat, *pad; #if defined(CONFIG_KLIPS_AUTH_HMAC_MD5) || defined(CONFIG_KLIPS_AUTH_HMAC_SHA1) __u8 hash[AH_AMAX]; union { #ifdef CONFIG_KLIPS_AUTH_HMAC_MD5 MD5_CTX md5; #endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ #ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1 SHA1_CTX sha1; #endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */ } tctx; #endif dat = (unsigned char *)ixs->iph; espp = (struct esphdr *)(dat + ixs->iphlen); espp->esp_spi = ixs->ipsp->ips_said.spi; espp->esp_rpl = htonl(++(ixs->ipsp->ips_replaywin_lastseq)); switch (ixs->ipsp->ips_encalg) { #if defined(CONFIG_KLIPS_ENC_3DES) #ifdef CONFIG_KLIPS_ENC_3DES case ESP_3DES: #endif /* CONFIG_KLIPS_ENC_3DES */ iv[0] = *((__u32*)&(espp->esp_iv) ) = ((__u32*)(ixs->ipsp->ips_iv))[0]; iv[1] = *((__u32*)&(espp->esp_iv) + 1) = ((__u32*)(ixs->ipsp->ips_iv))[1]; break; #endif /* defined(CONFIG_KLIPS_ENC_3DES) */ default: ixs->stats->tx_errors++; return IPSEC_XMIT_ESP_BADALG; } idat = dat + ixs->iphlen + sizeof(struct esphdr); ilen = ixs->skb->len - (ixs->iphlen + sizeof(struct esphdr) + ixs->authlen); /* Self-describing padding */ pad = &dat[ixs->skb->len - ixs->tailroom]; padlen = ixs->tailroom - 2 - ixs->authlen; for (i = 0; i < padlen; i++) pad[i] = i + 1; dat[ixs->skb->len - ixs->authlen - 2] = padlen; dat[ixs->skb->len - ixs->authlen - 1] = lsw_ip4_hdr(ixs)->protocol; lsw_ip4_hdr(ixs)->protocol = IPPROTO_ESP; switch (ixs->ipsp->ips_encalg) { #ifdef CONFIG_KLIPS_ENC_3DES case ESP_3DES: des_ede3_cbc_encrypt((des_cblock *)idat, (des_cblock *)idat, ilen, ((struct des_eks *)(ixs->ipsp->ips_key_e))[ 0].ks, ((struct des_eks *)(ixs->ipsp->ips_key_e))[ 1].ks, ((struct des_eks *)(ixs->ipsp->ips_key_e))[ 2].ks, (des_cblock *)iv, 1); break; #endif /* CONFIG_KLIPS_ENC_3DES */ default: ixs->stats->tx_errors++; return IPSEC_XMIT_ESP_BADALG; } switch (ixs->ipsp->ips_encalg) { #if defined(CONFIG_KLIPS_ENC_3DES) #ifdef CONFIG_KLIPS_ENC_3DES case ESP_3DES: #endif /* CONFIG_KLIPS_ENC_3DES */ /* XXX update IV with the last 8 octets of the encryption */ #if KLIPS_IMPAIRMENT_ESPIV_CBC_ATTACK ((__u32*)(ixs->ipsp->ips_iv))[0] = ((__u32 *)(idat))[(ilen >> 2) - 2]; ((__u32*)(ixs->ipsp->ips_iv))[1] = ((__u32 *)(idat))[(ilen >> 2) - 1]; #else /* KLIPS_IMPAIRMENT_ESPIV_CBC_ATTACK */ prng_bytes(&ipsec_prng, (char *)ixs->ipsp->ips_iv, EMT_ESPDES_IV_SZ); #endif /* KLIPS_IMPAIRMENT_ESPIV_CBC_ATTACK */ break; #endif /* defined(CONFIG_KLIPS_ENC_3DES) */ default: ixs->stats->tx_errors++; return IPSEC_XMIT_ESP_BADALG; } switch (ixs->ipsp->ips_authalg) { #ifdef CONFIG_KLIPS_AUTH_HMAC_MD5 case AH_MD5: ipsec_xmit_dmp("espp", (char*)espp, ixs->skb->len - ixs->iphlen - ixs->authlen); tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->ictx; ipsec_xmit_dmp("ictx", (char*)&tctx.md5, sizeof(tctx.md5)); osMD5Update(&tctx.md5, (caddr_t)espp, ixs->skb->len - ixs->iphlen - ixs->authlen); ipsec_xmit_dmp("ictx+dat", (char*)&tctx.md5, sizeof(tctx.md5)); osMD5Final(hash, &tctx.md5); ipsec_xmit_dmp("ictx hash", (char*)&hash, sizeof(hash)); tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->octx; ipsec_xmit_dmp("octx", (char*)&tctx.md5, sizeof(tctx.md5)); osMD5Update(&tctx.md5, hash, AHMD596_ALEN); ipsec_xmit_dmp("octx+hash", (char*)&tctx.md5, sizeof(tctx.md5)); osMD5Final(hash, &tctx.md5); ipsec_xmit_dmp("octx hash", (char*)&hash, sizeof(hash)); memcpy(&(dat[ixs->skb->len - ixs->authlen]), hash, ixs->authlen); /* paranoid */ memset((caddr_t)&tctx.md5, 0, sizeof(tctx.md5)); memset((caddr_t)hash, 0, sizeof(*hash)); break; #endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ #ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1 case AH_SHA: tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->ictx; SHA1Update(&tctx.sha1, (caddr_t)espp, ixs->skb->len - ixs->iphlen - ixs->authlen); SHA1Final(hash, &tctx.sha1); tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->octx; SHA1Update(&tctx.sha1, hash, AHSHA196_ALEN); SHA1Final(hash, &tctx.sha1); memcpy(&(dat[ixs->skb->len - ixs->authlen]), hash, ixs->authlen); /* paranoid */ memset((caddr_t)&tctx.sha1, 0, sizeof(tctx.sha1)); memset((caddr_t)hash, 0, sizeof(*hash)); break; #endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */ case AH_NONE: break; default: ixs->stats->tx_errors++; return IPSEC_XMIT_AH_BADALG; } skb_set_transport_header(ixs->skb, ipsec_skb_offset(ixs->skb, espp)); return IPSEC_XMIT_OK; } #endif struct xform_functions esp_xform_funcs[] = { { protocol: IPPROTO_ESP, rcv_checks: ipsec_rcv_esp_checks, rcv_setup_auth: ipsec_rcv_esp_decrypt_setup, rcv_calc_auth: ipsec_rcv_esp_authcalc, rcv_decrypt: ipsec_rcv_esp_decrypt, #if 0 xmit_setup: ipsec_xmit_esp_setup, xmit_headroom: sizeof(struct esphdr), xmit_needtailroom: 1, #endif }, }; #ifndef CONFIG_XFRM_ALTERNATE_STACK #ifdef NET_26 struct inet_protocol esp_protocol = { .handler = ipsec_rcv, .no_policy = 1, #ifdef HAVE_NAMESPACES .netns_ok = 1, #endif }; #ifdef CONFIG_KLIPS_IPV6 struct inet6_protocol esp6_protocol = { .handler = ipsec_rcv, .flags = INET6_PROTO_NOPOLICY, }; #endif #else struct inet_protocol esp_protocol = { ipsec_rcv, /* ESP handler */ NULL, /* TUNNEL error control */ 0, /* next */ IPPROTO_ESP, /* protocol ID */ 0, /* copy */ NULL, /* data */ "ESP" /* name */ }; #endif /* NET_26 */ #endif /* CONFIG_XFRM_ALTERNATE_STACK */ #endif /* !CONFIG_KLIPS_ESP */ libreswan-3.32/linux/net/ipsec/ipsec_init.c000066400000000000000000000327041365625662500207770ustar00rootroot00000000000000/* * @(#) Initialization code. * Copyright (C) 1996, 1997 John Ioannidis. * Copyright (C) 1998 - 2002 Richard Guy Briggs * 2001 - 2004 Michael Richardson * Copyright (C) 2012 Paul Wouters * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * /proc system code was split out into ipsec_proc.c after rev. 1.70. * */ #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38) && \ !defined(AUTOCONF_INCLUDED) #include #endif #include #include /* printk() */ #include "libreswan/ipsec_param.h" #include /* kmalloc() */ #include /* error codes */ #include /* size_t */ #include /* mark_bh */ #include /* struct device, and other headers */ #include /* eth_type_trans */ #include /* struct iphdr */ #include /* struct sockaddr_in */ #include #include /* get_random_bytes() */ #include #include "libreswan/ipsec_param2.h" #include #include /* *lock* */ #include #ifdef CONFIG_PROC_FS # include #endif /* CONFIG_PROC_FS */ # include #include "libreswan/radij.h" #include "libreswan/ipsec_life.h" #include "libreswan/ipsec_stats.h" #include "libreswan/ipsec_sa.h" #include "libreswan/ipsec_encap.h" #include "libreswan/ipsec_radij.h" #include "libreswan/ipsec_xform.h" #include "libreswan/ipsec_tunnel.h" #include "libreswan/ipsec_mast.h" #include "libreswan/ipsec_rcv.h" #include "libreswan/ipsec_xmit.h" #include "libreswan/ipsec_ah.h" #include "libreswan/ipsec_esp.h" #ifdef CONFIG_KLIPS_IPCOMP # include "libreswan/ipcomp.h" #endif /* CONFIG_KLIPS_IPCOMP */ #include "libreswan/ipsec_proto.h" #include "libreswan/ipsec_alg.h" #ifdef CONFIG_KLIPS_OCF #include "ipsec_ocf.h" #endif #include #include #if defined(HAVE_UDP_ENCAP_CONVERT) && defined(CONFIG_IPSEC_NAT_TRAVERSAL) # warning \ "You have CONFIG_IPSEC_NAT_TRAVERSAL set on a kernel > 2.6.22 that no longer need the NAT-T patch - you should recompile without it" #include #endif #ifndef HAVE_UDP_ENCAP_CONVERT # if defined(NET_26) && defined(CONFIG_IPSEC_NAT_TRAVERSAL) && \ !defined(HAVE_XFRM4_UDP_REGISTER) # warning \ "You are trying to build KLIPS2.6 with NAT-T support, but you did not" # error "properly apply the NAT-T patch to your < 2.6.23 kernel source tree." # endif #endif #if !defined(CONFIG_KLIPS_ESP) && !defined(CONFIG_KLIPS_AH) #error "kernel configuration must include ESP or AH" #endif /* * seems to be present in 2.4.10 (Linus), but also in some RH and other * distro kernels of a lower number. */ #ifdef MODULE_LICENSE MODULE_LICENSE("GPL"); #endif struct prng ipsec_prng; #if defined(NET_26) && defined(CONFIG_IPSEC_NAT_TRAVERSAL) xfrm4_rcv_encap_t klips_old_encap = NULL; #endif extern int ipsec_device_event(struct notifier_block *dnot, unsigned long event, void *ptr); /* * the following structure is required so that we receive * event notifications when network devices are enabled and * disabled (ifconfig up and down). */ static struct notifier_block ipsec_dev_notifier = { .notifier_call = ipsec_device_event }; #ifdef CONFIG_SYSCTL extern int ipsec_sysctl_register(void); extern void ipsec_sysctl_unregister(void); #endif /* * inet_*_protocol returns void on 2.4.x, int on 2.6.x * So we need our own wrapper */ #ifdef NET_26 static inline int libreswan_inet_add_protocol(struct inet_protocol *prot, unsigned protocol, char *protstr) { int err = inet_add_protocol(prot, protocol); if (err) printk(KERN_ERR "KLIPS: cannot register %s protocol - recompile with CONFIG_INET_%s disabled or as module\n", protstr, protstr); return err; } #ifdef CONFIG_KLIPS_IPV6 static inline int libreswan_inet6_add_protocol(struct inet6_protocol *prot, unsigned protocol, char *protstr) { int err = inet6_add_protocol(prot, protocol); if (err) printk(KERN_ERR "KLIPS: cannot register %s protocol - recompile with CONFIG_INET_%s disabled or as module\n", protstr, protstr); return err; } #endif static inline int libreswan_inet_del_protocol(struct inet_protocol *prot, unsigned protocol) { return inet_del_protocol(prot, protocol); } #ifdef CONFIG_KLIPS_IPV6 static inline int libreswan_inet6_del_protocol(struct inet6_protocol *prot, unsigned protocol) { return inet6_del_protocol(prot, protocol); } #endif #else static inline int libreswan_inet_add_protocol(struct inet_protocol *prot, unsigned protocol, char *protstr) { #ifdef IPSKB_XFRM_TUNNEL_SIZE inet_add_protocol(prot, protocol); #else inet_add_protocol(prot); #endif return 0; } static inline int libreswan_inet_del_protocol(struct inet_protocol *prot, unsigned protocol) { #ifdef IPSKB_XFRM_TUNNEL_SIZE inet_del_protocol(prot, protocol); #else inet_del_protocol(prot); #endif return 0; } #endif /* void */ int ipsec_klips_init(void) { int error = 0; unsigned char seed[256]; #ifdef CONFIG_KLIPS_ENC_3DES extern int des_check_key; /* turn off checking of keys */ des_check_key = 0; #endif /* CONFIG_KLIPS_ENC_3DES */ KLIPS_PRINT(1, "klips_info:ipsec_init: " "KLIPS startup, Libreswan KLIPS IPsec stack version: %s\n", ipsec_version_code()); error = ipsec_xmit_state_cache_init(); if (error) goto error_xmit_state_cache; error = ipsec_rcv_state_cache_init(); if (error) goto error_rcv_state_cache; error |= ipsec_proc_init(); if (error) goto error_proc_init; spin_lock_init(&ipsec_sadb.sadb_lock); error |= ipsec_sadb_init(); if (error) goto error_sadb_init; error |= ipsec_radijinit(); if (error) goto error_radijinit; error |= pfkey_init(); if (error) goto error_pfkey_init; error |= register_netdevice_notifier(&ipsec_dev_notifier); if (error) goto error_netdev_notifier; #ifdef CONFIG_XFRM_ALTERNATE_STACK error = xfrm_register_alternate_rcv(ipsec_rcv); if (error) goto error_xfrm_register; #else /* CONFIG_XFRM_ALTERNATE_STACK */ #ifdef CONFIG_KLIPS_ESP error |= libreswan_inet_add_protocol(&esp_protocol, IPPROTO_ESP, "ESP"); if (error) goto error_libreswan_inet_add_protocol_esp; #ifdef CONFIG_KLIPS_IPV6 error |= libreswan_inet6_add_protocol(&esp6_protocol, IPPROTO_ESP, "ESP"); if (error) goto error_libreswan_inet6_add_protocol_esp; #endif #endif /* CONFIG_KLIPS_ESP */ #ifdef CONFIG_KLIPS_AH error |= libreswan_inet_add_protocol(&ah_protocol, IPPROTO_AH, "AH"); if (error) goto error_libreswan_inet_add_protocol_ah; #endif /* CONFIG_KLIPS_AH */ /* we never actually link IPCOMP to the stack */ #ifdef IPCOMP_USED_ALONE #ifdef CONFIG_KLIPS_IPCOMP error |= libreswan_inet_add_protocol(&comp_protocol, IPPROTO_COMP, "IPCOMP"); if (error) goto error_libreswan_inet_add_protocol_comp; #endif /* CONFIG_KLIPS_IPCOMP */ #endif #endif /* CONFIG_XFRM_ALTERNATE_STACK */ error |= ipsec_tunnel_init_devices(); if (error) goto error_tunnel_init_devices; error |= ipsec_mast_init_devices(); if (error) goto error_mast_init_devices; #ifdef CONFIG_INET_IPSEC_SAREF error = ipsec_mast_init_saref(); if (error) goto error_mast_init_saref; #endif /* This is no longer needed for >= 2.6.23. We use HAVE_UDP_ENCAP_CONVERT */ #if defined(NET_26) && defined(CONFIG_IPSEC_NAT_TRAVERSAL) /* register our ESP-UDP handler */ if (udp4_register_esp_rcvencap(klips26_rcv_encap, &klips_old_encap) != 0) printk(KERN_ERR "KLIPS: cannot register klips26_rcv_encap function\n"); else KLIPS_PRINT(1, "KLIPS: registered klips26_rcv_encap function\n"); #endif #ifdef CONFIG_SYSCTL error |= ipsec_sysctl_register(); if (error) goto error_sysctl_register; #endif #ifdef CONFIG_KLIPS_ALG ipsec_alg_init(); #endif #ifdef CONFIG_KLIPS_OCF ipsec_ocf_init(); #endif get_random_bytes((void *)seed, sizeof(seed)); prng_init(&ipsec_prng, seed, sizeof(seed)); return error; /* undo ipsec_sysctl_register */ error_sysctl_register: #ifdef CONFIG_INET_IPSEC_SAREF ipsec_mast_cleanup_saref(); error_mast_init_saref: #endif ipsec_mast_cleanup_devices(); error_mast_init_devices: ipsec_tunnel_cleanup_devices(); error_tunnel_init_devices: #ifdef CONFIG_XFRM_ALTERNATE_STACK xfrm_deregister_alternate_rcv(ipsec_rcv); error_xfrm_register: #else /* CONFIG_XFRM_ALTERNATE_STACK */ #ifdef IPCOMP_USED_ALONE #ifdef CONFIG_KLIPS_IPCOMP error_libreswan_inet_add_protocol_comp: libreswan_inet_del_protocol(&comp_protocol, IPPROTO_COMP); #endif /* CONFIG_KLIPS_IPCOMP */ #endif #ifdef CONFIG_KLIPS_AH error_libreswan_inet_add_protocol_ah: libreswan_inet_del_protocol(&ah_protocol, IPPROTO_AH); #endif #ifdef CONFIG_KLIPS_IPV6 error_libreswan_inet6_add_protocol_esp: libreswan_inet6_del_protocol(&esp6_protocol, IPPROTO_ESP); #endif error_libreswan_inet_add_protocol_esp: libreswan_inet_del_protocol(&esp_protocol, IPPROTO_ESP); #endif unregister_netdevice_notifier(&ipsec_dev_notifier); error_netdev_notifier: pfkey_cleanup(); error_pfkey_init: ipsec_radijcleanup(); error_radijinit: ipsec_sadb_cleanup(0); ipsec_sadb_free(); error_sadb_init: error_proc_init: /* ipsec_proc_init() does not cleanup after itself, so we have to do * it here * TODO: ipsec_proc_init() should roll back what it changed on failure */ ipsec_proc_cleanup(); ipsec_rcv_state_cache_cleanup(); error_rcv_state_cache: ipsec_xmit_state_cache_cleanup(); error_xmit_state_cache: return error; } #ifdef NET_26 void #else int #endif ipsec_cleanup(void) { int error = 0; #ifdef CONFIG_SYSCTL ipsec_sysctl_unregister(); #endif #if defined(NET_26) && defined(CONFIG_IPSEC_NAT_TRAVERSAL) # ifndef HAVE_UDP_ENCAP_CONVERT /* unfortunately we have two versions of this function, one with one * argument and one with two. But we cannot know which one. Let's hope * not many people use an old nat-t patch on a new kernel with * libreswan klips >= 2.6.22 */ if (udp4_unregister_esp_rcvencap(klips26_rcv_encap, klips_old_encap) < 0) printk(KERN_ERR "KLIPS: cannot unregister klips_rcv_encap function\n"); # endif #endif #ifdef CONFIG_INET_IPSEC_SAREF ipsec_mast_cleanup_saref(); #endif error |= ipsec_mast_cleanup_devices(); KLIPS_PRINT(debug_netlink, /* debug_tunnel & DB_TN_INIT, */ "klips_debug:ipsec_cleanup: " "calling ipsec_tunnel_cleanup_devices.\n"); error |= ipsec_tunnel_cleanup_devices(); KLIPS_PRINT(debug_netlink, "called ipsec_tunnel_cleanup_devices"); #ifdef CONFIG_XFRM_ALTERNATE_STACK xfrm_deregister_alternate_rcv(ipsec_rcv); #else /* CONFIG_XFRM_ALTERNATE_STACK */ /* we never actually link IPCOMP to the stack */ #ifdef IPCOMP_USED_ALONE #ifdef CONFIG_KLIPS_IPCOMP if (libreswan_inet_del_protocol(&comp_protocol, IPPROTO_COMP) < 0) printk(KERN_INFO "klips_debug:ipsec_cleanup: " "comp close: can't remove protocol\n"); #endif /* CONFIG_KLIPS_IPCOMP */ #endif /* IPCOMP_USED_ALONE */ #ifdef CONFIG_KLIPS_AH if (libreswan_inet_del_protocol(&ah_protocol, IPPROTO_AH) < 0) printk(KERN_INFO "klips_debug:ipsec_cleanup: " "ah close: can't remove protocol\n"); #endif /* CONFIG_KLIPS_AH */ #ifdef CONFIG_KLIPS_ESP if (libreswan_inet_del_protocol(&esp_protocol, IPPROTO_ESP) < 0) printk(KERN_INFO "klips_debug:ipsec_cleanup: " "esp close: can't remove protocol\n"); #ifdef CONFIG_KLIPS_IPV6 if (libreswan_inet6_del_protocol(&esp6_protocol, IPPROTO_ESP) < 0) printk(KERN_INFO "klips_debug:ipsec_cleanup: " "esp6 close: can't remove protocol\n"); #endif #endif /* CONFIG_KLIPS_ESP */ #endif /* CONFIG_XFRM_ALTERNATE_STACK */ error |= unregister_netdevice_notifier(&ipsec_dev_notifier); KLIPS_PRINT(debug_netlink, /* debug_tunnel & DB_TN_INIT, */ "klips_debug:ipsec_cleanup: " "calling ipsec_sadb_cleanup.\n"); error |= ipsec_sadb_cleanup(0); error |= ipsec_sadb_free(); KLIPS_PRINT(debug_netlink, /* debug_tunnel & DB_TN_INIT, */ "klips_debug:ipsec_cleanup: " "calling ipsec_radijcleanup.\n"); error |= ipsec_radijcleanup(); KLIPS_PRINT(debug_pfkey, /* debug_tunnel & DB_TN_INIT, */ "klips_debug:ipsec_cleanup: " "calling pfkey_cleanup.\n"); error |= pfkey_cleanup(); ipsec_rcv_state_cache_cleanup(); ipsec_xmit_state_cache_cleanup(); ipsec_proc_cleanup(); prng_final(&ipsec_prng); #ifdef NET_26 if (error) printk("ipsec_cleanup: error %d\n", error); #else return error; #endif } #if defined(MODULE) || LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) #if defined(NET_26) || LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) late_initcall(ipsec_klips_init); module_exit(ipsec_cleanup); #else int init_module(void) { int error = 0; error |= ipsec_klips_init(); return error; } void cleanup_module(void) { KLIPS_PRINT(debug_netlink, /* debug_tunnel & DB_TN_INIT, */ "klips_debug:cleanup_module: " "calling ipsec_cleanup.\n"); ipsec_cleanup(); KLIPS_PRINT(1, "klips_info:cleanup_module: " "ipsec module unloaded.\n"); } #endif #endif /* MODULE */ libreswan-3.32/linux/net/ipsec/ipsec_ipcomp.c000066400000000000000000000204531365625662500213210ustar00rootroot00000000000000/* * processing code for IPCOMP * Copyright (C) 2003 Michael Richardson * Copyright (C) 2012 Paul Wouters * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38) && \ !defined(AUTOCONF_INCLUDED) #include #endif #define __NO_VERSION__ #include #include /* printk() */ #include "libreswan/ipsec_param.h" #include /* kmalloc() */ #include /* error codes */ #include /* size_t */ #include /* mark_bh */ #include /* struct device, and other headers */ #include /* eth_type_trans */ #include /* struct iphdr */ #include #include #include /* *lock* */ #include #include "libreswan/radij.h" #include "libreswan/ipsec_encap.h" #include "libreswan/ipsec_sa.h" #include "libreswan/ipsec_radij.h" #include "libreswan/ipsec_xform.h" #include "libreswan/ipsec_tunnel.h" #include "libreswan/ipsec_rcv.h" extern int sysctl_ipsec_inbound_policy_check; #include "libreswan/ipsec_xmit.h" #include "libreswan/ipsec_auth.h" #ifdef CONFIG_KLIPS_IPCOMP #include "libreswan/ipsec_ipcomp.h" #endif /* CONFIG_KLIPS_IPCOMP */ #include "libreswan/ipsec_proto.h" #ifdef CONFIG_KLIPS_OCF #include "ipsec_ocf.h" #endif #ifdef CONFIG_KLIPS_IPCOMP enum ipsec_rcv_value ipsec_rcv_ipcomp_checks(struct ipsec_rcv_state *irs, struct sk_buff *skb) { int ipcompminlen; ipcompminlen = sizeof(struct iphdr); if (skb->len < (ipcompminlen + sizeof(struct ipcomphdr))) { KLIPS_PRINT(debug_rcv & DB_RX_INAU, "klips_debug:ipsec_rcv_ipcomp_checks: " "runt comp packet of skb->len=%d received from %s, dropped.\n", skb->len, irs->ipsaddr_txt); if (irs->stats) irs->stats->rx_errors++; return IPSEC_RCV_BADLEN; } irs->protostuff.ipcompstuff.compp = (struct ipcomphdr *)skb_transport_header(skb); irs->said.spi = htonl((__u32)ntohs(irs->protostuff.ipcompstuff.compp-> ipcomp_cpi)); return IPSEC_RCV_OK; } enum ipsec_rcv_value ipsec_rcv_ipcomp_decomp(struct ipsec_rcv_state *irs) { unsigned int flags = 0; struct ipsec_sa *ipsp = irs->ipsp; struct sk_buff *skb; skb = irs->skb; ipsec_xmit_dmp("ipcomp", skb_transport_header(skb), skb->len); if (ipsp == NULL) return IPSEC_RCV_SAIDNOTFOUND; if (sysctl_ipsec_inbound_policy_check && ((((ntohl(ipsp->ips_said.spi) & 0x0000ffff) != (ntohl(irs->said.spi) & 0x0000ffff)) && (ipsp->ips_encalg != ntohl(irs->said.spi)) /* this is a workaround for peer non-compliance with rfc2393 */ ))) { char sa2[SATOT_BUF]; size_t sa_len2 = 0; sa_len2 = KLIPS_SATOT(debug_rcv, &ipsp->ips_said, 0, sa2, sizeof(sa2)); KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_ipcomp_decomp: " "Incoming packet with SA(IPCA):%s does not match policy SA(IPCA):%s cpi=%04x cpi->spi=%08x spi=%08x, spi->cpi=%04x for SA grouping, dropped.\n", irs->sa_len ? irs->sa : " (error)", sa_len2 ? sa2 : " (error)", ntohs(irs->protostuff.ipcompstuff.compp->ipcomp_cpi), (__u32)ntohl(irs->said.spi), (__u32)ntohl((ipsp->ips_said.spi)), (__u16)(ntohl(ipsp->ips_said.spi) & 0x0000ffff)); if (irs->stats) irs->stats->rx_dropped++; return IPSEC_RCV_SAIDNOTFOUND; } if (lsw_ip_hdr_version(irs) == 6) ipsp->ips_comp_ratio_cbytes += ntohs(lsw_ip6_hdr(irs)->payload_len) + sizeof(struct ipv6hdr); else ipsp->ips_comp_ratio_cbytes += ntohs(lsw_ip4_hdr(irs)->tot_len); irs->next_header = irs->protostuff.ipcompstuff.compp->ipcomp_nh; #ifdef CONFIG_KLIPS_OCF if (irs->ipsp->ocf_in_use) return ipsec_ocf_rcv(irs); #endif skb = skb_decompress(skb, ipsp, &flags); if (!skb || flags) { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_ipcomp_decomp: " "skb_decompress() returned error flags=%x, dropped.\n", flags); if (irs->stats) { if (flags) irs->stats->rx_errors++; else irs->stats->rx_dropped++; } return IPSEC_RCV_IPCOMPFAILED; } /* make sure we update the pointer */ irs->skb = skb; irs->iph = (void *) ip_hdr(skb); if (lsw_ip_hdr_version(irs) == 6) ipsp->ips_comp_ratio_dbytes += ntohs(lsw_ip6_hdr(irs)->payload_len) + sizeof(struct ipv6hdr); else ipsp->ips_comp_ratio_dbytes += ntohs(lsw_ip4_hdr(irs)->tot_len); KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_ipcomp_decomp: " "packet decompressed SA(IPCA):%s cpi->spi=%08x spi=%08x, spi->cpi=%04x, nh=%d.\n", irs->sa_len ? irs->sa : " (error)", (__u32)ntohl(irs->said.spi), ipsp != NULL ? (__u32)ntohl((ipsp->ips_said.spi)) : 0, ipsp != NULL ? (__u16)(ntohl(ipsp->ips_said.spi) & 0x0000ffff) : 0, irs->next_header); KLIPS_IP_PRINT(debug_rcv & DB_RX_PKTRX, irs->iph); return IPSEC_RCV_OK; } #if 0 enum ipsec_xmit_value ipsec_xmit_ipcomp_setup(struct ipsec_xmit_state *ixs) { unsigned int flags = 0; unsigned int tot_len, old_tot_len; #ifdef CONFIG_KLIPS_IPV6 if (lsw_ip_hdr_version(ixs) == 6) old_tot_len = ntohs(lsw_ip6_hdr(ixs)->payload_len) + sizeof(struct ipv6hdr); else #endif old_tot_len = ntohs(lsw_ip4_hdr(ixs)->tot_len); ixs->ipsp->ips_comp_ratio_dbytes += old_tot_len; ixs->skb = skb_compress(ixs->skb, ixs->ipsp, &flags); ixs->iph = (void *)ip_hdr(ixs->skb); #ifdef CONFIG_KLIPS_IPV6 if (lsw_ip_hdr_version(ixs) == 6) { IPSEC_FRAG_OFF_DECL(frag_off) int nexthdroff; unsigned char nexthdr = lsw_ip6_hdr(ixs)->nexthdr; nexthdroff = ipsec_ipv6_skip_exthdr(ixs->skb, ((void *)(lsw_ip6_hdr(ixs) + 1)) - (void*)ixs->skb->data, &nexthdr, &frag_off); ixs->iphlen = nexthdroff - (ixs->iph - (void*)ixs->skb->data); tot_len = ntohs(lsw_ip6_hdr(ixs)->payload_len) + sizeof(struct ipv6hdr); } else #endif { ixs->iphlen = lsw_ip4_hdr(ixs)->ihl << 2; tot_len = ntohs(lsw_ip4_hdr(ixs)->tot_len); } ixs->ipsp->ips_comp_ratio_cbytes += tot_len; if (debug_tunnel & DB_TN_CROUT) { if (old_tot_len > tot_len) KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, "klips_debug:ipsec_xmit_ipcomp_setup: " "packet shrunk from %d to %d bytes after compression, cpi=%04x (should be from spi=%08x, spi&0xffff=%04x.\n", old_tot_len, tot_len, ntohs(((struct ipcomphdr *) (((char*)ixs->iph) + (lsw_ip4_hdr(ixs)->ihl << 2)))-> ipcomp_cpi), ntohl(ixs->ipsp->ips_said.spi), (__u16)(ntohl(ixs->ipsp->ips_said.spi) & 0x0000ffff)); else KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, "klips_debug:ipsec_xmit_ipcomp_setup: " "packet did not compress (flags = %d).\n", flags); } return IPSEC_XMIT_OK; } #endif struct xform_functions ipcomp_xform_funcs[] = { { protocol: IPPROTO_COMP, rcv_checks: ipsec_rcv_ipcomp_checks, rcv_decrypt: ipsec_rcv_ipcomp_decomp, #if 0 xmit_setup: ipsec_xmit_ipcomp_setup, xmit_headroom: 0, xmit_needtailroom: 0, #endif }, }; #if 0 /* We probably don't want to install a pure IPCOMP protocol handler, but only want to handle IPCOMP if it is encapsulated inside an ESP payload (which is already handled) */ #ifndef CONFIG_XFRM_ALTERNATE_STACK #ifdef CONFIG_KLIPS_IPCOMP struct inet_protocol comp_protocol = { ipsec_rcv, /* COMP handler */ NULL, /* COMP error control */ #ifdef NET_26 1, /* no policy */ #else 0, /* next */ IPPROTO_COMP, /* protocol ID */ 0, /* copy */ NULL, /* data */ "COMP" /* name */ #endif }; #endif /* CONFIG_KLIPS_IPCOMP */ #endif /* CONFIG_XFRM_ALTERNATE_STACK */ #endif #endif /* CONFIG_KLIPS_IPCOMP */ libreswan-3.32/linux/net/ipsec/ipsec_ipip.c000066400000000000000000000060061365625662500207710ustar00rootroot00000000000000/* * processing code for IPIP * Copyright (C) 2003 Michael Richardson * Copyright (C) 2012 Paul Wouters * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38) && \ !defined(AUTOCONF_INCLUDED) #include #endif #define __NO_VERSION__ #include #include /* printk() */ #include "libreswan/ipsec_param.h" #include /* kmalloc() */ #include /* error codes */ #include /* size_t */ #include /* mark_bh */ #include /* struct device, and other headers */ #include /* eth_type_trans */ #include /* struct iphdr */ #include #include #include /* *lock* */ #include #include "libreswan/radij.h" #include "libreswan/ipsec_encap.h" #include "libreswan/ipsec_sa.h" #include "libreswan/ipsec_radij.h" #include "libreswan/ipsec_xform.h" #include "libreswan/ipsec_tunnel.h" #include "libreswan/ipsec_rcv.h" #include "libreswan/ipsec_xmit.h" #include "libreswan/ipsec_auth.h" #include "libreswan/ipsec_ipip.h" #include "libreswan/ipsec_param.h" #include "libreswan/ipsec_proto.h" #include "libreswan/ipsec_param2.h" enum ipsec_xmit_value ipsec_xmit_ipip_setup(struct ipsec_xmit_state *ixs) { lsw_ip4_hdr(ixs)->version = 4; switch (sysctl_ipsec_tos) { case 0: lsw_ip4_hdr(ixs)->tos = ip_hdr(ixs->skb)->tos; break; case 1: lsw_ip4_hdr(ixs)->tos = 0; break; default: break; } lsw_ip4_hdr(ixs)->ttl = SYSCTL_IPSEC_DEFAULT_TTL; lsw_ip4_hdr(ixs)->frag_off = 0; lsw_ip4_hdr(ixs)->saddr = ((struct sockaddr_in*)(ixs->ipsp->ips_addr_s))->sin_addr.s_addr; lsw_ip4_hdr(ixs)->daddr = ((struct sockaddr_in*)(ixs->ipsp->ips_addr_d))->sin_addr.s_addr; lsw_ip4_hdr(ixs)->protocol = IPPROTO_IPIP; lsw_ip4_hdr(ixs)->ihl = sizeof(struct iphdr) >> 2; #ifdef NET_21 printk("THIS CODE IS NEVER CALLED\n"); skb_set_transport_header(ixs->skb, ipsec_skb_offset(ixs->skb, ip_hdr(ixs->skb))); #endif /* NET_21 */ return IPSEC_XMIT_OK; } struct xform_functions ipip_xform_funcs[] = { { protocol: IPPROTO_IPIP, rcv_checks: NULL, rcv_setup_auth: NULL, rcv_calc_auth: NULL, rcv_decrypt: NULL, xmit_setup: ipsec_xmit_ipip_setup, xmit_headroom: sizeof(struct iphdr), xmit_needtailroom: 0, }, }; libreswan-3.32/linux/net/ipsec/ipsec_kern24.c000066400000000000000000000044231365625662500211360ustar00rootroot00000000000000/* * Copyright 2005 (C) Michael Richardson * Copyright 2011-2012 (C) David McCullough * * This is a file of functions that are present in 2.6 kernels, * but are not available by default in the 2.4 series. * * As such this code is usually from the Linux kernel, and is covered by * GPL. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include #include #include #include "libreswan/ipsec_kversion.h" /* * printk rate limiting, lifted from the networking subsystem. * * This enforces a rate limit: not more than one kernel message * every printk_ratelimit_jiffies to make a denial-of-service * attack impossible. */ static DEFINE_SPINLOCK(ratelimit_lock); int __printk_ratelimit(int ratelimit_jiffies, int ratelimit_burst) { static unsigned long toks = 10 * 5 * HZ; static unsigned long last_msg = 0; static int missed = 0; unsigned long flags; unsigned long now = jiffies; spin_lock_irqsave(&ratelimit_lock, flags); toks += ipsec_jiffies_elapsed(now, last_msg); last_msg = now; if (toks > (ratelimit_burst * ratelimit_jiffies)) toks = ratelimit_burst * ratelimit_jiffies; if (toks >= ratelimit_jiffies) { int lost = missed; missed = 0; toks -= ratelimit_jiffies; spin_unlock_irqrestore(&ratelimit_lock, flags); if (lost) { printk(KERN_WARNING "printk: %d messages suppressed.\n", lost); } return 1; } missed++; spin_unlock_irqrestore(&ratelimit_lock, flags); return 0; } /* minimum time in jiffies between messages */ int printk_ratelimit_jiffies = 5 * HZ; /* number of messages we send before ratelimiting */ int printk_ratelimit_burst = 10; int printk_ratelimit(void) { return __printk_ratelimit(printk_ratelimit_jiffies, printk_ratelimit_burst); } libreswan-3.32/linux/net/ipsec/ipsec_life.c000066400000000000000000000125771365625662500207610ustar00rootroot00000000000000/* * @(#) lifetime structure utilities * * Copyright (C) 2001 Richard Guy Briggs * and Michael Richardson * Copyright (C) 2005-2006 Michael Richardson * Copyright (C) 2006 Paul Wouters * Copyright (C) 2006 Bart Trojanowski * Copyright (C) 2012 David McCullough * Copyright (C) 2013 David McCullough * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ /* * This provides series of utility functions for dealing with lifetime * structures. * * ipsec_check_lifetime - returns -1 hard lifetime exceeded * 0 soft lifetime exceeded * 1 everything is okay * based upon whether or not the count exceeds hard/soft * */ #define __NO_VERSION__ #include #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38) && \ !defined(AUTOCONF_INCLUDED) #include #endif /* for CONFIG_IP_FORWARD */ #include /* printk() */ #include "libreswan/ipsec_param.h" #include /* struct device, struct net_device_stats and other headers */ #include /* eth_type_trans */ #include #include #include #include "libreswan/radij.h" #include "libreswan/ipsec_life.h" #include "libreswan/ipsec_xform.h" #include "libreswan/ipsec_eroute.h" #include "libreswan/ipsec_encap.h" #include "libreswan/ipsec_radij.h" #include "libreswan/ipsec_sa.h" #include "libreswan/ipsec_tunnel.h" #include "libreswan/ipsec_ipe4.h" #include "libreswan/ipsec_ah.h" #include "libreswan/ipsec_esp.h" #ifdef CONFIG_KLIPS_IPCOMP #include "libreswan/ipcomp.h" #endif /* CONFIG_KLIPS_IPCOMP */ #include #include #include "libreswan/ipsec_proto.h" enum ipsec_life_alive ipsec_lifetime_check(struct ipsec_lifetime64 *il64, const char *lifename, const char *saname, enum ipsec_life_type ilt, enum ipsec_direction idir, struct ipsec_sa *ips) { __u64 count; const char *dir; if (saname == NULL) saname = "unknown-SA"; if (idir == ipsec_incoming) dir = "incoming"; else dir = "outgoing"; if (ilt == ipsec_life_timebased) count = ipsec_jiffieshz_elapsed(jiffies / HZ, il64->ipl_count); else count = il64->ipl_count; if (il64->ipl_hard && (count > il64->ipl_hard)) { KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_lifetime_check: " "hard %s lifetime of SA:<%s%s%s> %s has been reached, SA expired, " "%s packet dropped.\n", lifename, IPS_XFORM_NAME(ips), saname, dir); pfkey_expire(ips, 1); return ipsec_life_harddied; } if (il64->ipl_soft && (count > il64->ipl_soft)) { KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_lifetime_check: " "soft %s lifetime of SA:<%s%s%s> %s has been reached, SA expiring, " "soft expire message sent up, %s packet still processed.\n", lifename, IPS_XFORM_NAME(ips), saname, dir); if (ips->ips_state != K_SADB_SASTATE_DYING) pfkey_expire(ips, 0); ips->ips_state = K_SADB_SASTATE_DYING; return ipsec_life_softdied; } return ipsec_life_okay; } /* * This function takes a buffer (with length), a lifetime name and type, * and formats a string to represent the current values of the lifetime. * * It returns the number of bytes that the format took (or would take, * if the buffer were large enough: snprintf semantics). * This is used in /proc routines and in debug output. */ int ipsec_lifetime_format(struct seq_file *seq, char *lifename, enum ipsec_life_type timebaselife, struct ipsec_lifetime64 *lifetime) { int len = 0; __u64 count; if (timebaselife == ipsec_life_timebased) count = ipsec_jiffieshz_elapsed(jiffies / HZ, lifetime->ipl_count); else count = lifetime->ipl_count; if (lifetime->ipl_count > 1 || lifetime->ipl_soft || lifetime->ipl_hard) { seq_printf(seq, "%s(%Lu,%Lu,%Lu)", lifename, count, lifetime->ipl_soft, lifetime->ipl_hard); } return len; } void ipsec_lifetime_update_hard(struct ipsec_lifetime64 *lifetime, __u64 newvalue) { if (newvalue && (!lifetime->ipl_hard || (newvalue < lifetime->ipl_hard))) { lifetime->ipl_hard = newvalue; if (!lifetime->ipl_soft && (lifetime->ipl_hard < lifetime->ipl_soft)) lifetime->ipl_soft = lifetime->ipl_hard; } } void ipsec_lifetime_update_soft(struct ipsec_lifetime64 *lifetime, __u64 newvalue) { if (newvalue && (!lifetime->ipl_soft || (newvalue < lifetime->ipl_soft))) { lifetime->ipl_soft = newvalue; if (lifetime->ipl_hard && (lifetime->ipl_hard < lifetime->ipl_soft)) lifetime->ipl_soft = lifetime->ipl_hard; } } libreswan-3.32/linux/net/ipsec/ipsec_mast.c000066400000000000000000000703741365625662500210050ustar00rootroot00000000000000/* * IPSEC MAST code. * Copyright (C) 2005 Michael Richardson * Copyright (C) 2012 Paul Wouters * Copyright (C) 2017 Paul Wouters * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ char ipsec_mast_c_version[] = "Please use ipsec --version instead"; #define __NO_VERSION__ #include #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38) && \ !defined(AUTOCONF_INCLUDED) #include #endif /* for CONFIG_IP_FORWARD */ #include /* printk() */ #include "libreswan/ipsec_param.h" #include /* kmalloc() */ #include /* error codes */ #include /* size_t */ #include /* mark_bh */ #include #include #include #include #include /* struct device, struct net_device_stats, dev_queue_xmit() and other headers */ #include /* eth_type_trans */ #include /* struct iphdr */ #include #ifdef NET_26 /* 2.6 kernels */ # include #endif #include #include /* icmp_send() */ #include #include #include #include "libreswan/ipsec_kversion.h" #include "libreswan/radij.h" #include "libreswan/ipsec_life.h" #include "libreswan/ipsec_xform.h" #include "libreswan/ipsec_eroute.h" #include "libreswan/ipsec_encap.h" #include "libreswan/ipsec_radij.h" #include "libreswan/ipsec_sa.h" #include "libreswan/ipsec_xmit.h" #include "libreswan/ipsec_mast.h" #include "libreswan/ipsec_tunnel.h" #include "libreswan/ipsec_ipe4.h" #include "libreswan/ipsec_ah.h" #include "libreswan/ipsec_esp.h" #include #include #include "libreswan/ipsec_proto.h" #ifdef CONFIG_IPSEC_NAT_TRAVERSAL # include #endif int ipsec_mastdevice_count = -1; int debug_mast; static __u32 zeroes[64]; DEBUG_NO_STATIC int ipsec_mast_open(struct net_device *dev) { struct mastpriv *prv = netdev_to_mastpriv(dev); prv = prv; /* * Can't open until attached. */ KLIPS_PRINT(debug_mast & DB_MAST_INIT, "klips_debug:ipsec_mast_open: " "dev = %s\n", dev->name); return 0; } DEBUG_NO_STATIC int ipsec_mast_close(struct net_device *dev) { return 0; } static inline int ipsec_mast_xmit2(struct sk_buff *skb) { #ifdef NET_26 /* 2.6 kernels */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) return dst_output(dev_net(skb->dev), skb->sk, skb); #else return dst_output(skb); #endif #else return ip_send(skb); #endif } #ifdef CONFIG_INET_IPSEC_SAREF static int klips_set_ipc_saref(struct ipcm_cookie *ipc, xfrm_sec_unique_t ref) { struct ipsec_sa *sa1; struct sec_path *sp; sp = secpath_dup(NULL); if (!sp) return -EINVAL; sp->ref = ref; KLIPS_PRINT(debug_mast, "klips_debug:klips_set_ipc_saref: " "sending with saref=%u\n", sp->ref); sa1 = ipsec_sa_getbyref(sp->ref, IPSEC_REFOTHER); if (sa1 && sa1->ips_out) { ipc->oif = sa1->ips_out->ifindex; KLIPS_PRINT(debug_mast, "klips_debug:klips_set_ipc_saref: " "setting oif: %d\n", ipc->oif); } ipsec_sa_put(sa1, IPSEC_REFOTHER); ipc->sp = sp; return 0; } static void klips_get_secpath_refs(struct sec_path *sp, xfrm_sec_unique_t *refme, xfrm_sec_unique_t *refhim) { struct ipsec_sa *sa1; if (sp == NULL) return; KLIPS_PRINT(debug_rcv, "klips_debug:klips_get_secpath_refs: " "retrieving saref=%u from sp=%p\n", sp->ref, sp); *refme = sp->ref; sa1 = ipsec_sa_getbyref(sp->ref, IPSEC_REFOTHER); *refhim = sa1 ? sa1->ips_refhim : 0; if (sa1) ipsec_sa_put(sa1, IPSEC_REFOTHER); } static struct ipsec_secpath_saref_ops klips_saref_ops = { .set_ipc_saref = klips_set_ipc_saref, .get_secpath_sarefs = klips_get_secpath_refs, }; int ipsec_mast_init_saref(void) { return register_ipsec_secpath_saref_ops(&klips_saref_ops); } void ipsec_mast_cleanup_saref(void) { unregister_ipsec_secpath_saref_ops(&klips_saref_ops); } #endif #if 0 /* Paul: This seems to be unused dead code */ enum ipsec_xmit_value ipsec_mast_send(struct ipsec_xmit_state *ixs) { /* new route/dst cache code from James Morris */ ixs->skb->dev = ixs->physdev; /*skb_orphan(ixs->skb);*/ if ((ixs->error = ip_route_output(&ixs->route, ixs->skb->nh.iph->daddr, ixs->pass ? 0 : ixs->skb->nh.iph-> saddr, RT_TOS(ixs->skb->nh.iph->tos), ixs->physdev->ifindex /* rgb: should this be 0? */))) { ixs->stats->tx_errors++; KLIPS_PRINT(debug_mast & DB_MAST_XMIT, "klips_debug:ipsec_mast_send: " "ip_route_output failed with error code %d, dropped\n", ixs->error); return IPSEC_XMIT_ROUTEERR; } if (ixs->dev == ixs->route->u.dst.dev) { ip_rt_put(ixs->route); /* This is recursion, drop it. */ ixs->stats->tx_errors++; KLIPS_PRINT(debug_mast & DB_MAST_XMIT, "klips_debug:ipsec_mast_send: " "suspect recursion, dev=rt->u.dst.dev=%s, dropped\n", ixs->dev->name); return IPSEC_XMIT_RECURSDETECT; } dst_release(skb_dst(ixs->skb)); skb_dst_set(ixs->skb, &ixs->route->u.dst); ixs->stats->tx_bytes += ixs->skb->len; if (ixs->skb->len < ixs->skb->nh.raw - ixs->skb->data) { ixs->stats->tx_errors++; printk(KERN_WARNING "klips_error:ipsec_mast_send: " "tried to __skb_pull nh-data=%td, %d available. This should never happen, please report.\n", ixs->skb->nh.raw - ixs->skb->data, ixs->skb->len); return IPSEC_XMIT_PUSHPULLERR; } __skb_pull(ixs->skb, ixs->skb->nh.raw - ixs->skb->data); ipsec_nf_reset(ixs->skb); KLIPS_PRINT(debug_mast & DB_MAST_XMIT, "klips_debug:ipsec_mast_send: " "...done, calling ip_send() on device:%s\n", ixs->skb->dev ? ixs->skb->dev->name : "NULL"); KLIPS_IP_PRINT(debug_mast & DB_MAST_XMIT, ixs->skb->nh.iph); { int err; err = NF_HOOK(PF_INET, LSW_NF_INET_LOCAL_OUT, ixs->skb, NULL, ixs->route->u.dst.dev, ipsec_mast_xmit2); if (err != NET_XMIT_SUCCESS && err != NET_XMIT_CN) { if (net_ratelimit()) printk(KERN_ERR "klips_error:ipsec_mast_send: " "ip_send() failed, err=%d\n", -err); ixs->stats->tx_errors++; ixs->stats->tx_aborted_errors++; ixs->skb = NULL; return IPSEC_XMIT_IPSENDFAILURE; } } ixs->stats->tx_packets++; ixs->skb = NULL; return IPSEC_XMIT_OK; } #endif static void ipsec_mast_xsm_complete(struct ipsec_xmit_state *ixs, enum ipsec_xmit_value stat) { if (stat != IPSEC_XMIT_OK) { KLIPS_PRINT(debug_mast, "klips_debug:ipsec_mast_xsm_complete: " "ipsec_xsm failed: %d\n", stat); goto cleanup; } /* do any final NAT-encapsulation */ stat = ipsec_nat_encap(ixs); if (stat != IPSEC_XMIT_OK) goto cleanup; ipsec_xmit_send(ixs); cleanup: ipsec_xmit_cleanup(ixs); if (ixs->ipsp) { ipsec_sa_put(ixs->ipsp, IPSEC_REFOTHER); ixs->ipsp = NULL; } if (ixs->skb) { ipsec_kfree_skb(ixs->skb); ixs->skb = NULL; } ipsec_xmit_state_delete(ixs); } /* * Verify that the skb can go out on this ipsp. * Return 0 if OK, error code otherwise. */ static int ipsec_mast_check_outbound_policy(struct ipsec_xmit_state *ixs) { int failed_outbound_check = 0; struct ipsec_sa *ipsp = ixs->ipsp; if (!ixs || !ixs->ipsp || !ixs->iph) return -EFAULT; /* Note: "xor" (^) logically replaces "not equal" * (!=) and "bitwise or" (|) logically replaces * "boolean or" (||). This is done to speed up * execution by doing only bitwise operations and * no branch operations */ if (lsw_ip_hdr_version(ixs) == 4) { struct iphdr *ipp = lsw_ip4_hdr(ixs); if (ip_address_family(&ipsp->ips_said.dst) != AF_INET) failed_outbound_check = 1; else if (((ipp->saddr & ipsp->ips_mask_s.u.v4.sin_addr.s_addr) ^ ipsp->ips_flow_s.u.v4.sin_addr.s_addr) | ((ipp->daddr & ipsp->ips_mask_d.u.v4.sin_addr.s_addr) ^ ipsp->ips_flow_d.u.v4.sin_addr.s_addr)) failed_outbound_check = 1; } else if (lsw_ip_hdr_version(ixs) == 6) { struct ipv6hdr *ipp6 = lsw_ip6_hdr(ixs); if (ip_address_family(&ipsp->ips_said.dst) != AF_INET6) failed_outbound_check = 1; else if (((ipp6->saddr.s6_addr32[0] & ipsp->ips_mask_s.u.v6.sin6_addr.s6_addr32[0]) ^ ipsp->ips_flow_s.u.v6.sin6_addr.s6_addr32[0]) | ((ipp6->daddr.s6_addr32[0] & ipsp->ips_mask_d.u.v6.sin6_addr.s6_addr32[0]) ^ ipsp->ips_flow_d.u.v6.sin6_addr.s6_addr32[0])) failed_outbound_check = 1; else if (((ipp6->saddr.s6_addr32[1] & ipsp->ips_mask_s.u.v6.sin6_addr.s6_addr32[1]) ^ ipsp->ips_flow_s.u.v6.sin6_addr.s6_addr32[1]) | ((ipp6->daddr.s6_addr32[1] & ipsp->ips_mask_d.u.v6.sin6_addr.s6_addr32[1]) ^ ipsp->ips_flow_d.u.v6.sin6_addr.s6_addr32[1])) failed_outbound_check = 1; else if (((ipp6->saddr.s6_addr32[2] & ipsp->ips_mask_s.u.v6.sin6_addr.s6_addr32[2]) ^ ipsp->ips_flow_s.u.v6.sin6_addr.s6_addr32[2]) | ((ipp6->daddr.s6_addr32[2] & ipsp->ips_mask_d.u.v6.sin6_addr.s6_addr32[2]) ^ ipsp->ips_flow_d.u.v6.sin6_addr.s6_addr32[2])) failed_outbound_check = 1; else if (((ipp6->saddr.s6_addr32[3] & ipsp->ips_mask_s.u.v6.sin6_addr.s6_addr32[3]) ^ ipsp->ips_flow_s.u.v6.sin6_addr.s6_addr32[3]) | ((ipp6->daddr.s6_addr32[3] & ipsp->ips_mask_d.u.v6.sin6_addr.s6_addr32[3]) ^ ipsp->ips_flow_d.u.v6.sin6_addr.s6_addr32[3])) failed_outbound_check = 1; } if (failed_outbound_check) { char saddr_txt[ADDRTOA_BUF], daddr_txt[ADDRTOA_BUF]; char sflow_txt[SUBNETTOA_BUF], dflow_txt[SUBNETTOA_BUF]; if (ipsp->ips_flow_s.u.v4.sin_family == AF_INET6) { subnet6toa(&ipsp->ips_flow_s.u.v6.sin6_addr, &ipsp->ips_mask_s.u.v6.sin6_addr, 0, sflow_txt, sizeof(sflow_txt)); subnet6toa(&ipsp->ips_flow_d.u.v6.sin6_addr, &ipsp->ips_mask_d.u.v6.sin6_addr, 0, dflow_txt, sizeof(dflow_txt)); inet_addrtot(AF_INET6, &lsw_ip6_hdr(ixs)->saddr, 0, saddr_txt, sizeof(saddr_txt)); inet_addrtot(AF_INET6, &lsw_ip6_hdr(ixs)->daddr, 0, daddr_txt, sizeof(daddr_txt)); } else { subnettoa(ipsp->ips_flow_s.u.v4.sin_addr, ipsp->ips_mask_s.u.v4.sin_addr, 0, sflow_txt, sizeof(sflow_txt)); subnettoa(ipsp->ips_flow_d.u.v4.sin_addr, ipsp->ips_mask_d.u.v4.sin_addr, 0, dflow_txt, sizeof(dflow_txt)); inet_addrtot(AF_INET, &lsw_ip4_hdr(ixs)->saddr, 0, saddr_txt, sizeof(saddr_txt)); inet_addrtot(AF_INET, &lsw_ip4_hdr(ixs)->daddr, 0, daddr_txt, sizeof(daddr_txt)); } if (!ixs->sa_len) { ixs->sa_len = KLIPS_SATOT(debug_mast, &ixs->outgoing_said, 0, ixs->sa_txt, sizeof(ixs->sa_txt)); } KLIPS_PRINT(debug_mast, "klips_debug:ipsec_mast_check_outbound_policy: " "SA:%s, inner tunnel policy [%s -> %s] does not agree with pkt contents [%s -> %s].\n", ixs->sa_len ? ixs->sa_txt : " (error)", sflow_txt, dflow_txt, saddr_txt, daddr_txt); if (ixs->stats) ixs->stats->rx_dropped++; return -EACCES; } #if 0 { char sflow_txt[SUBNETTOA_BUF], dflow_txt[SUBNETTOA_BUF]; char saddr_txt[ADDRTOA_BUF], daddr_txt[ADDRTOA_BUF]; struct in_addr ipaddr; subnettoa(ixs->ipsp->ips_flow_s.u.v4.sin_addr, ixs->ipsp->ips_mask_s.u.v4.sin_addr, 0, sflow_txt, sizeof(sflow_txt)); subnettoa(ixs->ipsp->ips_flow_d.u.v4.sin_addr, ixs->ipsp->ips_mask_d.u.v4.sin_addr, 0, dflow_txt, sizeof(dflow_txt)); ipaddr.s_addr = ixs->iph->saddr; addrtoa(ipaddr, 0, saddr_txt, sizeof(saddr_txt)); ipaddr.s_addr = ixs->iph->daddr; addrtoa(ipaddr, 0, daddr_txt, sizeof(daddr_txt)); if (!ixs->sa_len) ixs->sa_len = KLIPS_SATOT(debug_mast, &ixs->outgoing_said, 0, ixs->sa_txt, sizeof(ixs->sa_txt)); KLIPS_PRINT(debug_mast, "klips_debug:ipsec_mast_check_outbound_policy: " "SA:%s, inner tunnel policy [%s -> %s] agrees with pkt contents [%s -> %s].\n", ixs->sa_len ? ixs->sa_txt : " (error)", sflow_txt, dflow_txt, saddr_txt, daddr_txt); } #endif return 0; } /* * This function assumes it is being called from dev_queue_xmit() * and that skb is filled properly by that function. */ int ipsec_mast_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct ipsec_xmit_state *ixs; IPsecSAref_t SAref; KLIPS_PRINT(debug_mast, "klips_debug:ipsec_mast_start_xmit: skb=%p\n", skb); if (skb == NULL) { printk("ipsec_mast_start_xmit: " "passed NULL\n"); return 0; } ixs = ipsec_xmit_state_new(dev); if (ixs == NULL) return NETDEV_TX_BUSY; ixs->dev = dev; ixs->skb = skb; SAref = 0; #ifdef NET_26 # if defined(CONFIG_NETFILTER) if (skb->nfmark & IPSEC_NFMARK_IS_SAREF_BIT) { SAref = NFmark2IPsecSAref(skb->nfmark); KLIPS_PRINT(debug_mast, "klips_debug:ipsec_mast_start_xmit: " "getting SAref=%d from nfmark\n", SAref); } # endif #endif #ifdef CONFIG_INET_IPSEC_SAREF if (skb->sp && skb->sp->ref != IPSEC_SAREF_NULL) { SAref = skb->sp->ref; KLIPS_PRINT(debug_mast, "klips_debug:ipsec_mast_start_xmit: " "getting SAref=%d from sec_path\n", SAref); } #endif if (ipsec_xmit_sanity_check_mast_dev(ixs) != IPSEC_XMIT_OK) { ipsec_xmit_cleanup(ixs); ipsec_xmit_state_delete(ixs); return 0; } if (ipsec_xmit_sanity_check_skb(ixs) != IPSEC_XMIT_OK) { ipsec_xmit_cleanup(ixs); ipsec_xmit_state_delete(ixs); return 0; } ixs->ipsp = ipsec_sa_getbyref(SAref, IPSEC_REFOTHER); if (ixs->ipsp == NULL) { KLIPS_ERROR(debug_mast, "klips_debug:ipsec_mast_start_xmit: " "%s: no SA for saref=%d\n", dev->name, SAref); ipsec_xmit_cleanup(ixs); ipsec_xmit_state_delete(ixs); return 0; } /* make sure this packet can go out on this SA */ if (ipsec_mast_check_outbound_policy(ixs)) { ipsec_xmit_cleanup(ixs); ipsec_xmit_state_delete(ixs); return 0; } /* fill in outgoing_said using the ipsp we have */ ixs->outgoing_said = ixs->ipsp->ips_said; #ifdef NET_26 # if defined(CONFIG_NETFILTER) /* prevent recursion through the saref route */ if (skb->nfmark & 0x80000000) skb->nfmark = 0; # endif #endif #if 0 /* TODO: do we have to also have to do this? */ if (skb->sp && skb->sp->ref != IPSEC_SAREF_NULL) { secpath_put(skb->sp); skb->sp = NULL; } #endif ixs->mast_mode = 1; ixs->xsm_complete = ipsec_mast_xsm_complete; ixs->state = IPSEC_XSM_INIT2; /* we start later in the process */ ipsec_xsm(ixs); return 0; } DEBUG_NO_STATIC struct net_device_stats *ipsec_mast_get_stats( struct net_device *dev) { return &(netdev_to_mastpriv(dev)->mystats); } #if 0 /* * Revectored calls. * For each of these calls, a field exists in our private structure. */ DEBUG_NO_STATIC int ipsec_mast_hard_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, void *daddr, void *saddr, unsigned len) { struct mastpriv *mprv = netdev_to_mastpriv(dev); struct net_device_stats *stats; /* This device's statistics */ int ret = 0; if (skb == NULL) { KLIPS_PRINT(debug_mast & DB_MAST_REVEC, "klips_debug:ipsec_mast_hard_header: " "no skb...\n"); return -ENODATA; } if (dev == NULL) { KLIPS_PRINT(debug_mast & DB_MAST_REVEC, "klips_debug:ipsec_mast_hard_header: " "no device...\n"); return -ENODEV; } KLIPS_PRINT(debug_mast & DB_MAST_REVEC, "klips_debug:ipsec_mast_hard_header: " "skb->dev=%s\n", dev->name); if (prv == NULL) { KLIPS_PRINT(debug_mast & DB_MAST_REVEC, "klips_debug:ipsec_mast_hard_header: " "no private space associated with dev=%s\n", dev->name ? dev->name : "NULL"); return -ENODEV; } stats = (struct net_device_stats *) &(prv->mystats); /* check if we have to send a IPv6 packet. It might be a Router Solicitation, where the building of the packet happens in reverse order: 1. ll hdr, 2. IPv6 hdr, 3. ICMPv6 hdr -> skb->nh.raw is still uninitialized when this function is called!! If this is no IPv6 packet, we can print debugging messages, otherwise we skip all debugging messages and just build the ll header */ if (type != ETH_P_IPV6) { /* execute this only, if we don't have to build the header for a IPv6 packet */ if (!prv->hard_header) { KLIPS_PRINT(debug_mast & DB_MAST_REVEC, "klips_debug:ipsec_mast_hard_header: " "physical device has been detached, packet dropped 0p%p->0p%p len=%d type=%d dev=%s->NULL ", saddr, daddr, len, type, dev->name); KLIPS_PRINTMORE(debug_mast & DB_MAST_REVEC, "ip=%08x->%08x\n", (__u32)ntohl(skb->nh.iph->saddr), (__u32)ntohl(skb->nh.iph->daddr) ); stats->tx_dropped++; return -ENODEV; } } else { KLIPS_PRINT(debug_mast, "klips_debug:ipsec_mast_hard_header: " "is IPv6 packet, skip debugging messages, only revector and build linklocal header.\n"); } return ret; } DEBUG_NO_STATIC int ipsec_mast_rebuild_header(struct sk_buff *skb) { struct mastpriv *prv = netdev_to_mastpriv(skb->dev); prv = prv; return 0; } DEBUG_NO_STATIC int ipsec_mast_set_mac_address(struct net_device *dev, void *addr) { struct mastpriv *prv = netdev_to_mastpriv(dev); prv = prv; return 0; } DEBUG_NO_STATIC void ipsec_mast_cache_update(struct hh_cache *hh, struct net_device *dev, unsigned char * haddr) { struct mastpriv *prv = netdev_to_mastpriv(dev); if (dev == NULL) { KLIPS_PRINT(debug_mast & DB_MAST_REVEC, "klips_debug:ipsec_mast_cache_update: " "no device..."); return; } if (prv == NULL) { KLIPS_PRINT(debug_mast & DB_MAST_REVEC, "klips_debug:ipsec_mast_cache_update: " "no private space associated with dev=%s", dev->name ? dev->name : "NULL"); return; } KLIPS_PRINT(debug_mast & DB_MAST_REVEC, "klips_debug:ipsec_mast: " "Revectored cache_update\n"); } #endif DEBUG_NO_STATIC int ipsec_mast_neigh_setup(struct neighbour *n) { KLIPS_PRINT(debug_mast & DB_MAST_REVEC, "klips_debug:ipsec_mast_neigh_setup:\n"); if (n->nud_state == NUD_NONE) { #ifndef PRIVATE_ARP_BROKEN_OPS n->ops = &arp_broken_ops; #endif n->output = n->ops->output; } return 0; } DEBUG_NO_STATIC int ipsec_mast_neigh_setup_dev(struct net_device *dev, struct neigh_parms *p) { KLIPS_PRINT(debug_mast & DB_MAST_REVEC, "klips_debug:ipsec_mast_neigh_setup_dev: " "setting up %s\n", dev ? dev->name : "NULL"); if (p->tbl->family == AF_INET) { p->neigh_setup = ipsec_mast_neigh_setup; #ifdef NEIGH_VAR_SET /* * see kernel's include/net/neighbour.h * ??? Not sure which to use: * NEIGH_VAR_INIT or NEIGH_VAR_INIT */ NEIGH_VAR_SET(p, UCAST_PROBES, 0); NEIGH_VAR_SET(p, MCAST_PROBES, 0); #else p->ucast_probes = 0; p->mcast_probes = 0; #endif } return 0; } DEBUG_NO_STATIC int ipsec_mast_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { /* struct ipsecmastconf *cf = (struct ipsecmastconf *)&ifr->ifr_data;*/ /* overlay our struct ipsecmast onto ifr.ifr_ifru union (hope it fits!) */ struct ipsecmastconf *cf = (struct ipsecmastconf *)ifr->ifr_ifru.ifru_newname; struct mastpriv *mprv = netdev_to_mastpriv(dev); cf = cf; mprv = mprv; if (dev == NULL) { KLIPS_PRINT(debug_mast & DB_MAST_INIT, "klips_debug:ipsec_mast_ioctl: " "device not supplied.\n"); return -ENODEV; } KLIPS_PRINT(debug_mast & DB_MAST_INIT, "klips_debug:ipsec_mast_ioctl: " "tncfg service call #%d for dev=%s\n", cmd, dev->name ? dev->name : "NULL"); switch (cmd) { default: KLIPS_PRINT(debug_mast & DB_MAST_INIT, "klips_debug:ipsec_mast_ioctl: " "unknown command %d.\n", cmd); return -EOPNOTSUPP; } } int ipsec_mast_device_event(struct notifier_block *unused, unsigned long event, void *ptr) { struct net_device *dev = ptr; struct mastpriv *priv = netdev_to_mastpriv(dev); priv = priv; if (dev == NULL) { KLIPS_PRINT(debug_mast & DB_MAST_INIT, "klips_debug:ipsec_mast_device_event: " "dev=NULL for event type %ld.\n", event); return NOTIFY_DONE; } /* check for loopback devices */ if (dev && (dev->flags & IFF_LOOPBACK)) return NOTIFY_DONE; switch (event) { case NETDEV_DOWN: /* look very carefully at the scope of these compiler directives before changing anything... -- RGB */ case NETDEV_UNREGISTER: switch (event) { case NETDEV_DOWN: KLIPS_PRINT(debug_mast & DB_MAST_INIT, "klips_debug:ipsec_mast_device_event: " "NETDEV_DOWN dev=%s flags=%x\n", dev->name, dev->flags); if (strncmp(dev->name, "ipsec", strlen("ipsec")) == 0) { printk(KERN_CRIT "IPSEC EVENT: KLIPS device %s shut down.\n", dev->name); } break; case NETDEV_UNREGISTER: KLIPS_PRINT(debug_mast & DB_MAST_INIT, "klips_debug:ipsec_mast_device_event: " "NETDEV_UNREGISTER dev=%s flags=%x\n", dev->name, dev->flags); break; } break; case NETDEV_UP: KLIPS_PRINT(debug_mast & DB_MAST_INIT, "klips_debug:ipsec_mast_device_event: " "NETDEV_UP dev=%s\n", dev->name); break; case NETDEV_REBOOT: KLIPS_PRINT(debug_mast & DB_MAST_INIT, "klips_debug:ipsec_mast_device_event: " "NETDEV_REBOOT dev=%s\n", dev->name); break; case NETDEV_CHANGE: KLIPS_PRINT(debug_mast & DB_MAST_INIT, "klips_debug:ipsec_mast_device_event: " "NETDEV_CHANGE dev=%s flags=%x\n", dev->name, dev->flags); break; case NETDEV_REGISTER: KLIPS_PRINT(debug_mast & DB_MAST_INIT, "klips_debug:ipsec_mast_device_event: " "NETDEV_REGISTER dev=%s\n", dev->name); break; case NETDEV_CHANGEMTU: KLIPS_PRINT(debug_mast & DB_MAST_INIT, "klips_debug:ipsec_mast_device_event: " "NETDEV_CHANGEMTU dev=%s to mtu=%d\n", dev->name, dev->mtu); break; case NETDEV_CHANGEADDR: KLIPS_PRINT(debug_mast & DB_MAST_INIT, "klips_debug:ipsec_mast_device_event: " "NETDEV_CHANGEADDR dev=%s\n", dev->name); break; case NETDEV_GOING_DOWN: KLIPS_PRINT(debug_mast & DB_MAST_INIT, "klips_debug:ipsec_mast_device_event: " "NETDEV_GOING_DOWN dev=%s\n", dev->name); break; case NETDEV_CHANGENAME: KLIPS_PRINT(debug_mast & DB_MAST_INIT, "klips_debug:ipsec_mast_device_event: " "NETDEV_CHANGENAME dev=%s\n", dev->name); break; default: KLIPS_PRINT(debug_mast & DB_MAST_INIT, "klips_debug:ipsec_mast_device_event: " "event type %ld unrecognised for dev=%s\n", event, dev->name); break; } return NOTIFY_DONE; } /* * Called when an ipsec mast device is initialized. * The ipsec mast device structure is passed to us. */ int ipsec_mast_probe(struct net_device *dev) { int i; struct mastpriv *mprv; KLIPS_PRINT(debug_mast, "klips_debug:ipsec_mast_probe: " "allocating %zu bytes initialising device: %s\n", sizeof(struct mastpriv), dev->name ? dev->name : "NULL"); #ifndef USE_NETDEV_OPS /* Add our mast functions to the device */ dev->open = ipsec_mast_open; dev->stop = ipsec_mast_close; dev->hard_start_xmit = ipsec_mast_start_xmit; dev->get_stats = ipsec_mast_get_stats; dev->set_multicast_list = NULL; dev->do_ioctl = ipsec_mast_ioctl; dev->set_mac_address = NULL; dev->neigh_setup = ipsec_mast_neigh_setup_dev; #endif #ifdef ipsec_alloc_netdev # ifdef HAS_PRIV_DESTRUCTOR dev->priv_destructor = free_netdev; # else dev->destructor = free_netdev; # endif #endif #ifndef ipsec_alloc_netdev dev->priv = kmalloc(sizeof(struct mastpriv), GFP_KERNEL); if (dev->priv == NULL) return -ENOMEM; #endif mprv = netdev_priv(dev); memset(mprv, 0, sizeof(struct mastpriv)); mprv->magic = MASTPRIV_MAGIC; for (i = 0; i < sizeof(zeroes); i++) ((__u8*)(zeroes))[i] = 0; #ifdef HAVE_NETDEV_HEADER_OPS dev->header_ops = NULL; #else dev->hard_header = NULL; dev->rebuild_header = NULL; dev->header_cache_update = NULL; #endif dev->hard_header_len = 8 + 20 + 20 + 8; dev->mtu = 0; dev->addr_len = 0; dev->type = ARPHRD_NONE; dev->tx_queue_len = 10; #ifdef IFF_XMIT_DST_RELEASE dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; #endif memset((caddr_t)(dev->broadcast), 0xFF, ETH_ALEN); /* what if this is not attached to ethernet? */ /* New-style flags. */ dev->flags = IFF_NOARP; /* pick a random ethernet address for now. */ random_ether_addr(dev->dev_addr); /* We're done. Have I forgotten anything? */ return 0; } #ifdef ipsec_alloc_netdev static void ipsec_mast_netdev_setup(struct net_device *dev) { } #endif struct net_device *mastdevices[IPSEC_NUM_IFMAX]; int mastdevices_max = -1; #ifdef USE_NETDEV_OPS static const struct net_device_ops ipsec_mast_ops = { .ndo_init = ipsec_mast_probe, .ndo_open = ipsec_mast_open, .ndo_stop = ipsec_mast_close, .ndo_start_xmit = ipsec_mast_start_xmit, .ndo_get_stats = ipsec_mast_get_stats, .ndo_do_ioctl = ipsec_mast_ioctl, .ndo_neigh_setup = ipsec_mast_neigh_setup_dev, }; #endif int ipsec_mast_createnum(int vifnum) { struct net_device *im; int vifentry; char name[IFNAMSIZ]; if (vifnum >= IPSEC_NUM_IFMAX) return -ENOENT; if (mastdevices[vifnum] != NULL) return -EEXIST; /* no identical device */ if (vifnum > mastdevices_max) mastdevices_max = vifnum; vifentry = vifnum; snprintf(name, IFNAMSIZ, MAST_DEV_FORMAT, vifnum); #ifdef ipsec_alloc_netdev im = ipsec_alloc_netdev(sizeof(struct mastpriv), name, NET_NAME_UNKNOWN, ipsec_mast_netdev_setup); #else im = (struct net_device *)kmalloc(sizeof(struct net_device), GFP_KERNEL); #endif if (im == NULL) { printk(KERN_ERR "failed to allocate space for mast%d device\n", vifnum); return -ENOMEM; } #ifndef ipsec_alloc_netdev memset((caddr_t)im, 0, sizeof(struct net_device)); memcpy(im->name, name, IFNAMSIZ); #endif #ifdef USE_NETDEV_OPS im->netdev_ops = &ipsec_mast_ops; #else im->init = ipsec_mast_probe; #endif if (register_netdev(im) != 0) { printk(KERN_ERR "ipsec_mast: failed to register %s\n", im->name); return -EIO; } ipsec_dev_hold(im); mastdevices[vifentry] = im; return 0; } int ipsec_mast_deletenum(int vifnum) { struct net_device *dev_ipsec; if (vifnum >= IPSEC_NUM_IFMAX) return -ENOENT; dev_ipsec = mastdevices[vifnum]; if (dev_ipsec == NULL) return -ENOENT; /* release reference */ mastdevices[vifnum] = NULL; ipsec_dev_put(dev_ipsec); KLIPS_PRINT(debug_tunnel, "Unregistering %s\n", dev_ipsec->name); unregister_netdev(dev_ipsec); KLIPS_PRINT(debug_tunnel, "Unregistered %s\n", dev_ipsec->name); #ifndef ipsec_alloc_netdev kfree(dev_ipsec->priv); dev_ipsec->priv = NULL; #endif return 0; } struct net_device *ipsec_mast_get_device(int vifnum) { int ovifnum = vifnum; if (vifnum > IPSECDEV_OFFSET) { return ipsec_tunnel_get_device(vifnum - IPSECDEV_OFFSET); } else { struct net_device *nd; if (vifnum >= MASTTRANSPORT_OFFSET) vifnum -= MASTTRANSPORT_OFFSET; if (vifnum <= mastdevices_max) { nd = mastdevices[vifnum]; if (nd) ipsec_dev_hold(nd); return nd; } else { KLIPS_ERROR(debug_tunnel, "no such vif %d (ovif=%d)\n", vifnum, ovifnum); return NULL; } } } unsigned int ipsec_mast_is_transport(int vifnum) { if (vifnum > MASTTRANSPORT_OFFSET && vifnum < IPSECDEV_OFFSET) return 1; return 0; } int ipsec_mast_init_devices(void) { /* * mast0 is used for transport mode stuff, and generally is * the default unless the user decides to create more. */ ipsec_mast_createnum(0); return 0; } /* void */ int ipsec_mast_cleanup_devices(void) { int error = 0; int i; struct net_device *dev_mast; for (i = 0; i <= mastdevices_max; i++) { if (mastdevices[i] != NULL) { dev_mast = mastdevices[i]; mastdevices[i] = NULL; ipsec_dev_put(dev_mast); unregister_netdev(dev_mast); #ifndef ipsec_alloc_netdev kfree(dev_mast->priv); dev_mast->priv = NULL; #endif } } return error; } libreswan-3.32/linux/net/ipsec/ipsec_md5c.c000066400000000000000000000243671365625662500206720ustar00rootroot00000000000000/* * The rest of the code is derived from MD5C.C by RSADSI. Minor cosmetic * changes to accommodate it in the kernel by ji. */ #include #include #include "libreswan/ipsec_md5h.h" /* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm */ /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. * * http://www.ietf.org/ietf-ftp/IPR/RSA-MD-all */ /* * Additions by JI * * HAVEMEMCOPY is defined if mem* routines are available * * HAVEHTON is defined if htons() and htonl() can be used * for big/little endian conversions * */ #define HAVEMEMCOPY #ifdef __LITTLE_ENDIAN #define LITTLENDIAN #endif #ifdef __BIG_ENDIAN #define BIGENDIAN #endif /* Constants for MD5Transform routine. */ #define S11 7 #define S12 12 #define S13 17 #define S14 22 #define S21 5 #define S22 9 #define S23 14 #define S24 20 #define S31 4 #define S32 11 #define S33 16 #define S34 23 #define S41 6 #define S42 10 #define S43 15 #define S44 21 static void MD5Transform(UINT4 [4], unsigned char [64]); #ifdef LITTLEENDIAN #define Encode MD5_memcpy #define Decode MD5_memcpy #else static void Encode(unsigned char *, UINT4 *, unsigned int); static void Decode(UINT4 *, unsigned char *, unsigned int); #endif #ifdef HAVEMEMCOPY /* no need to include here; defines these */ #define MD5_memcpy memcpy #define MD5_memset memset #else #ifdef HAVEBCOPY #define MD5_memcpy(_a, _b, _c) bcopy((_b), (_a), (_c)) #define MD5_memset(_a, _b, _c) bzero((_a), (_c)) #else static void MD5_memcpy(POINTER, POINTER, unsigned int); static void MD5_memset(POINTER, int, unsigned int); #endif #endif static unsigned char PADDING[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* F, G, H and I are basic MD5 functions. */ #define F(x, y, z) (((x) & (y)) | ((~x) & (z))) #define G(x, y, z) (((x) & (z)) | ((y) & (~z))) #define H(x, y, z) ((x) ^ (y) ^ (z)) #define I(x, y, z) ((y) ^ ((x) | (~z))) /* ROTATE_LEFT rotates x left n bits. */ #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. Rotation is separate from addition to prevent recomputation. */ #define FF(a, b, c, d, x, s, ac) { \ (a) += F((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT((a), (s)); \ (a) += (b); \ } #define GG(a, b, c, d, x, s, ac) { \ (a) += G((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT((a), (s)); \ (a) += (b); \ } #define HH(a, b, c, d, x, s, ac) { \ (a) += H((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT((a), (s)); \ (a) += (b); \ } #define II(a, b, c, d, x, s, ac) { \ (a) += I((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT((a), (s)); \ (a) += (b); \ } /* * MD5 initialization. Begins an MD5 operation, writing a new context. */ void osMD5Init(void *vcontext) { MD5_CTX *context = vcontext; context->count[0] = context->count[1] = 0; /* Load magic initialization constants.*/ context->state[0] = 0x67452301; context->state[1] = 0xefcdab89; context->state[2] = 0x98badcfe; context->state[3] = 0x10325476; } /* MD5 block update operation. Continues an MD5 message-digest operation, processing another message block, and updating the context. */ void osMD5Update(vcontext, input, inputLen) void *vcontext; unsigned char *input; /* input block */ __u32 inputLen; /* length of input block */ { MD5_CTX *context = vcontext; __u32 i; unsigned int index, partLen; /* Compute number of bytes mod 64 */ index = (unsigned int)((context->count[0] >> 3) & 0x3F); /* Update number of bits */ if ((context->count[0] += ((UINT4)inputLen << 3)) < ((UINT4)inputLen << 3)) context->count[1]++; context->count[1] += ((UINT4)inputLen >> 29); partLen = 64 - index; /* Transform as many times as possible. */ if (inputLen >= partLen) { MD5_memcpy ((POINTER)&context->buffer[index], (POINTER)input, partLen); MD5Transform(context->state, context->buffer); for (i = partLen; i + 63 < inputLen; i += 64) MD5Transform(context->state, &input[i]); index = 0; } else { i = 0; } /* Buffer remaining input */ MD5_memcpy ((POINTER)&context->buffer[index], (POINTER)&input[i], inputLen - i); } /* MD5 finalization. Ends an MD5 message-digest operation, writing the the message digest and zeroizing the context. */ void osMD5Final(digest, vcontext) unsigned char digest[16]; /* message digest */ void *vcontext; /* context */ { MD5_CTX *context = vcontext; unsigned char bits[8]; unsigned int index, padLen; /* Save number of bits */ Encode(bits, context->count, 8); /* Pad out to 56 mod 64. */ index = (unsigned int)((context->count[0] >> 3) & 0x3f); padLen = (index < 56) ? (56 - index) : (120 - index); osMD5Update(context, PADDING, padLen); /* Append length (before padding) */ osMD5Update(context, bits, 8); if (digest != NULL) { /* Bill Simpson's padding */ /* store state in digest */ Encode(digest, context->state, 16); /* Zeroize sensitive information. */ MD5_memset((POINTER)context, 0, sizeof(*context)); } } /* MD5 basic transformation. Transforms state based on block. */ static void MD5Transform(state, block) UINT4 state[4]; unsigned char block[64]; { UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; Decode(x, block, 64); /* Round 1 */ FF(a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ FF(d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ FF(c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ FF(b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ FF(a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ FF(d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ FF(c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ FF(b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ FF(a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ FF(d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ /* Round 2 */ GG(a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ GG(d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ GG(b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ GG(a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */ GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ GG(b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ GG(a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ GG(c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ GG(b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ GG(d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ GG(c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ /* Round 3 */ HH(a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ HH(d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ HH(a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ HH(d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ HH(c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ HH(d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ HH(c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ HH(b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ HH(a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ HH(b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ /* Round 4 */ II(a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ II(d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ II(b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ II(d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ II(b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ II(a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ II(c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ II(a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ II(c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ II(b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ state[0] += a; state[1] += b; state[2] += c; state[3] += d; /* Zeroize sensitive information. */ MD5_memset((POINTER)x, 0, sizeof(x)); } #ifndef LITTLEENDIAN /* Encodes input (UINT4) into output (unsigned char). Assumes len is a multiple of 4. */ static void Encode(output, input, len) unsigned char *output; UINT4 *input; unsigned int len; { unsigned int i, j; for (i = 0, j = 0; j < len; i++, j += 4) { output[j] = (unsigned char)(input[i] & 0xff); output[j + 1] = (unsigned char)((input[i] >> 8) & 0xff); output[j + 2] = (unsigned char)((input[i] >> 16) & 0xff); output[j + 3] = (unsigned char)((input[i] >> 24) & 0xff); } } /* Decodes input (unsigned char) into output (UINT4). Assumes len is a multiple of 4. */ static void Decode(output, input, len) UINT4 * output; unsigned char *input; unsigned int len; { unsigned int i, j; for (i = 0, j = 0; j < len; i++, j += 4) output[i] = ((UINT4)input[j]) | (((UINT4)input[j + 1]) << 8) | (((UINT4)input[j + 2]) << 16) | (((UINT4)input[j + 3]) << 24); } #endif #ifndef HAVEMEMCOPY #ifndef HAVEBCOPY /* Note: Replace "for loop" with standard memcpy if possible. */ static void MD5_memcpy(output, input, len) POINTER output; POINTER input; unsigned int len; { unsigned int i; for (i = 0; i < len; i++) output[i] = input[i]; } /* Note: Replace "for loop" with standard memset if possible. */ static void MD5_memset(output, value, len) POINTER output; int value; unsigned int len; { unsigned int i; for (i = 0; i < len; i++) ((char *)output)[i] = (char)value; } #endif #endif libreswan-3.32/linux/net/ipsec/ipsec_ocf.c000066400000000000000000001152431365625662500206030ustar00rootroot00000000000000/* * IPSEC OCF support * * This code written by David McCullough * Copyright (C) 2005 Intel Corporation. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38) && \ !defined(AUTOCONF_INCLUDED) #include #endif #define __NO_VERSION__ #include #include /* printk() */ #include /* error codes */ #include /* size_t */ #include #include #include #include #include #include "libreswan/ipsec_sa.h" #include "libreswan/ipsec_rcv.h" #include "libreswan/ipsec_xmit.h" #include "libreswan/ipsec_tunnel.h" #include "libreswan/ipsec_xform.h" #include "libreswan/ipsec_auth.h" #include "libreswan/ipsec_esp.h" #include "libreswan/ipsec_ah.h" #include "libreswan/ipcomp.h" #include "libreswan/ipsec_proto.h" #include #include #include "ipsec_ocf.h" extern int debug_pfkey; extern int debug_rcv; int ipsec_ocf_crid = (CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE); /* tuning params for OCF */ int ipsec_ocf_batch = 1; module_param(ipsec_ocf_batch, int, 0644); MODULE_PARM_DESC(ipsec_ocf_batch, "Make OCF queue packets rather than process them immediately"); int ipsec_ocf_cbimm = 1; module_param(ipsec_ocf_cbimm, int, 0644); MODULE_PARM_DESC(ipsec_ocf_cbimm, "Does OCF immediately (ie., at irq time) run callbacks or queue and call later"); /* * processing on different kernels */ #ifdef DECLARE_TASKLET static struct tasklet_struct ipsec_ocf_task; static struct sk_buff_head ipsec_ocf_skbq; static void ipsec_ocf_skbq_process(unsigned long arg) { void (*func)(void *arg); void *this; struct sk_buff *skb; if ((skb = skb_dequeue(&ipsec_ocf_skbq)) != NULL) { func = ((void **) (&skb->cb[0]))[0]; this = ((void **) (&skb->cb[0]))[1]; (*func)(this); /* make sure we run again */ tasklet_schedule(&ipsec_ocf_task); } } static void ipsec_ocf_queue_init(void) { skb_queue_head_init(&ipsec_ocf_skbq); tasklet_init(&ipsec_ocf_task, ipsec_ocf_skbq_process, 0ul); } #define ipsec_ocf_queue_task(func, this) \ ((void **) (&(this)->skb->cb[0]))[0] = func; \ ((void **) (&(this)->skb->cb[0]))[1] = this; \ skb_queue_tail(&ipsec_ocf_skbq, (this)->skb); \ tasklet_schedule(&ipsec_ocf_task); #endif /* * convert libreswan values to OCF values */ static int ipsec_ocf_compalg(int compalg) { switch (compalg) { case IPCOMP_DEFLATE: return CRYPTO_DEFLATE_COMP; case IPCOMP_LZS: return CRYPTO_LZS_COMP; /* ocf does not have these yet... */ #if 0 case IPCOMP_OUI: case IPCOMP_V42BIS: #endif } return 0; } static int ipsec_ocf_authalg(int authalg) { switch (authalg) { case AH_SHA: return CRYPTO_SHA1_HMAC; case AH_SHA2_256: return CRYPTO_SHA2_256_HMAC; case AH_SHA2_384: return CRYPTO_SHA2_384_HMAC; case AH_SHA2_512: return CRYPTO_SHA2_512_HMAC; case AH_MD5: return CRYPTO_MD5_HMAC; } return 0; } static int ipsec_ocf_encalg(int encalg) { switch (encalg) { case ESP_NULL: return CRYPTO_NULL_CBC; case ESP_3DES: return CRYPTO_3DES_CBC; case ESP_AES: return CRYPTO_AES_CBC; case ESP_CAST: return CRYPTO_CAST_CBC; } return 0; } /* * We use this function because sometimes we want to pass a negative offset * into skb_put(), this does not work on 64bit platforms because long to * unsigned int casting. */ static inline unsigned char *safe_skb_put(struct sk_buff *skb, int extend) { unsigned char *ptr; if (extend > 0) { /* increase the size of the packet */ ptr = skb_put(skb, extend); } else { /* shrink the size of the packet */ ptr = skb_tail_pointer(skb); skb_trim(skb, skb->len + extend); } return ptr; } /* * We need to grow the skb to accommodate the expansion of the ipcomp packet. * * The following comment comes from the skb_decompress() which does the * same... * * We have no way of knowing the exact length of the resulting * decompressed output before we have actually done the decompression. * For now, we guess that the packet will not be bigger than the * attached ipsec device's mtu or 16260, whichever is biggest. * This may be wrong, since the sender's mtu may be bigger yet. * XXX This must be dealt with later XXX */ static int ipsec_ocf_ipcomp_copy_expand(struct ipsec_rcv_state *irs) { struct sk_buff *nskb; unsigned grow_to, grow_by; ptrdiff_t ptr_delta; if (!irs->skb) return IPSEC_RCV_IPCOMPFAILED; if (irs->skb->dev) { grow_to = irs->skb->dev->mtu < 16260 ? 16260 : irs->skb->dev->mtu; } else { int tot_len; if (lsw_ip_hdr_version(irs) == 6) tot_len = ntohs(lsw_ip6_hdr(irs)->payload_len) + sizeof(struct ipv6hdr); else tot_len = ntohs(lsw_ip4_hdr(irs)->tot_len); grow_to = 65520 - tot_len; } grow_by = grow_to - irs->skb->len; grow_by -= skb_headroom(irs->skb); grow_by -= skb_tailroom(irs->skb); /* it's big enough */ if (!grow_by) return IPSEC_RCV_OK; nskb = skb_copy_expand(irs->skb, skb_headroom(irs->skb), skb_tailroom(irs->skb) + grow_by, GFP_ATOMIC); if (!nskb) return IPSEC_RCV_ERRMEMALLOC; memcpy(nskb->head, irs->skb->head, skb_headroom(irs->skb)); skb_set_network_header(nskb, ipsec_skb_offset(irs->skb, skb_network_header(irs->skb))); skb_set_transport_header(nskb, ipsec_skb_offset(irs->skb, skb_transport_header( irs->skb))); /* update all irs pointers */ ptr_delta = nskb->data - irs->skb->data; irs->authenticator = (void*)((char*)irs->authenticator + ptr_delta); irs->iph = (void*)((char*)irs->iph + ptr_delta); /* flip in the large one */ irs->pre_ipcomp_skb = irs->skb; irs->skb = nskb; /* move the tail up to the end to let OCF know how big the buffer is */ if (grow_by > (irs->skb->end - irs->skb->tail)) grow_by = irs->skb->end - irs->skb->tail; skb_put(irs->skb, grow_by); return IPSEC_RCV_OK; } /* * if we can do the request ops, setup the sessions and return true * otherwise return false with ipsp unchanged */ int ipsec_ocf_sa_init(struct ipsec_sa *ipsp, int authalg, int encalg) { struct cryptoini crie, cria; int error; KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_ocf_sa_init(a=0x%x,e=0x%x)\n", authalg, encalg); if (authalg && ipsp->ips_key_bits_a == 0) { KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_ocf_sa_init(a=0x%x,e=0x%x) a-key-bits=0\n", authalg, encalg); /* pretend we are happy with this */ return 1; } /* ESP_NULL is a special case, no key */ if (encalg && encalg != ESP_NULL && ipsp->ips_key_bits_e == 0) { KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_ocf_sa_init(a=0x%x,e=0x%x) e-key-bits=0\n", authalg, encalg); /* pretend we are happy with this */ return 1; } if (ipsp->ocf_in_use) printk("KLIPS: ipsec_ocf_sa_init received SA is already initted?\n"); memset(&crie, 0, sizeof(crie)); memset(&cria, 0, sizeof(cria)); cria.cri_alg = ipsec_ocf_authalg(authalg); cria.cri_klen = ipsp->ips_key_bits_a; cria.cri_key = ipsp->ips_key_a; cria.cri_mlen = 12; crie.cri_alg = ipsec_ocf_encalg(encalg); crie.cri_klen = ipsp->ips_key_bits_e; crie.cri_key = ipsp->ips_key_e; switch (crie.cri_alg) { case CRYPTO_AES_CBC: ipsp->ips_iv_size = 16; break; case CRYPTO_3DES_CBC: ipsp->ips_iv_size = 8; break; default: ipsp->ips_iv_size = 0; break; } ipsp->ips_iv_bits = ipsp->ips_iv_size * 8; ipsp->ips_auth_bits = ipsp->ips_key_bits_a; if (authalg && encalg) { crie.cri_next = &cria; error = crypto_newsession(&ipsp->ocf_cryptoid, &crie, ipsec_ocf_crid); } else if (encalg) { error = crypto_newsession(&ipsp->ocf_cryptoid, &crie, ipsec_ocf_crid); } else if (authalg) { error = crypto_newsession(&ipsp->ocf_cryptoid, &cria, ipsec_ocf_crid); } else { KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_ocf_sa_init: " "no authalg or encalg\n"); return 0; } if (error) { KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_ocf_sa_init: " "crypto_newsession failed 0x%x\n", error); return 0; } /* make sure no ALG stuff bites us */ if (ipsp->ips_alg_enc) printk("We received an ALG initted SA\n"); ipsp->ips_alg_enc = NULL; ipsp->ocf_in_use = 1; return 1; } /* this function returns true if OCF can do the compression */ int ipsec_ocf_comp_sa_init(struct ipsec_sa *ipsp, int compalg) { struct cryptoini cric; int error; KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_ocf_comp_sa_init(c=0x%x)\n", compalg); memset(&cric, 0, sizeof(cric)); cric.cri_alg = ipsec_ocf_compalg(compalg); if (!cric.cri_alg) { KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_ocf_comp_sa_init: " "invalid compalg=%d given\n", compalg); return 0; } error = crypto_newsession(&ipsp->ocf_cryptoid, &cric, ipsec_ocf_crid); if (error) { KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_ocf_comp_sa_init: " "crypto_newsession failed 0x%x\n", error); return 0; } ipsp->ocf_in_use = 1; return 1; } int ipsec_ocf_sa_free(struct ipsec_sa *ipsp) { KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_ocf_sa_free()\n"); if (!ipsp->ocf_in_use) printk("KLIPS: ipsec_ocf_sa_free received SA that is not initted?\n"); crypto_freesession(ipsp->ocf_cryptoid); ipsp->ocf_cryptoid = -1; ipsp->ocf_in_use = 0; return 1; } static int ipsec_ocf_rcv_cb(struct cryptop *crp) { struct ipsec_rcv_state *irs = (struct ipsec_rcv_state *)crp->crp_opaque; struct iphdr *newiph; unsigned orig_len, decomp_len; struct cryptodesc *crdc = NULL; KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_ocf_rcv_cb\n"); if (irs == NULL) { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_ocf_rcv_cb: " "NULL irs in callback\n"); return 0; } /* * we must update the state before returning to the state machine. * if we have an error, terminate the processing by moving to the DONE * state */ irs->state = IPSEC_RSM_DONE; /* assume it went badly */ if (crp->crp_etype) { ptrdiff_t ptr_delta; if (crp->crp_etype == EAGAIN) { /* Session has been migrated. Store the new session id and retry */ KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_ocf_rcv_cb: crypto session migrated\n"); irs->ipsp->ocf_cryptoid = crp->crp_sid; /* resubmit request */ if (crypto_dispatch(crp) == 0) return 0; /* resubmit failed */ } KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_ocf_rcv_cb: " "error in processing 0x%x\n", crp->crp_etype); switch (irs->ipsp->ips_said.proto) { case IPPROTO_COMP: /* * we restore the previous skb on error and pretend nothing * happened, just no compression */ ptr_delta = irs->pre_ipcomp_skb->data - irs->skb->data; irs->authenticator = (void*)((char*)irs->authenticator + ptr_delta); irs->iph = (void*)((char*)irs->iph + ptr_delta); kfree_skb(irs->skb); irs->skb = irs->pre_ipcomp_skb; irs->pre_ipcomp_skb = NULL; break; } goto bail; } switch (irs->ipsp->ips_said.proto) { case IPPROTO_ESP: /* ESP, process it */ if (ipsec_rcv_esp_post_decrypt(irs) == IPSEC_RCV_OK) { /* this one came up good, set next state */ irs->state = IPSEC_RSM_DECAP_CONT; } break; case IPPROTO_AH: /* AH post processing, put back fields we had to zero */ if (lsw_ip_hdr_version(irs) == 4) { lsw_ip4_hdr(irs)->ttl = irs->ttl; lsw_ip4_hdr(irs)->check = irs->check; lsw_ip4_hdr(irs)->frag_off = irs->frag_off; lsw_ip4_hdr(irs)->tos = irs->tos; } irs->state = IPSEC_RSM_AUTH_CHK; /* pull up the IP header again after processing */ skb_pull(irs->skb, ((unsigned char *)irs->protostuff.ahstuff.ahp) - ((unsigned char *)irs->iph)); break; case IPPROTO_COMP: crdc = crp->crp_desc; KLIPS_PRINT(debug_rcv, "comp before adjustments:\n"); KLIPS_IP_PRINT(debug_rcv & DB_TN_XMIT, irs->iph); orig_len = irs->skb->len - sizeof(struct ipcomphdr); decomp_len = crp->crp_olen; newiph = (struct iphdr*) ((char*)irs->iph + sizeof(struct ipcomphdr)); KLIPS_PRINT(debug_rcv, "comp results: olen: %u, inject: %u (len=%d) iph->totlen=%u\n", crp->crp_olen, crdc->crd_inject, decomp_len, ntohs(newiph->tot_len)); /* * move the ip header to consume room previously taken by * the ipcomp header */ skb_pull(irs->skb, sizeof(struct ipcomphdr)); memmove(newiph, irs->iph, irs->iphlen); /* adjust the ipp pointer to point to the header we decoded */ irs->iph = newiph; skb_set_network_header(irs->skb, ipsec_skb_offset(irs->skb, ((unsigned char *) skb_network_header(irs->skb)) + sizeof(struct ipcomphdr))); skb_set_transport_header(irs->skb, ipsec_skb_offset(irs->skb, ((unsigned char *) skb_transport_header(irs->skb)) + sizeof(struct ipcomphdr))); if (lsw_ip_hdr_version(irs) == 6) { lsw_ip6_hdr(irs)->nexthdr = irs->next_header; } else { lsw_ip4_hdr(irs)->protocol = irs->next_header; lsw_ip4_hdr(irs)->tot_len = htons( irs->iphlen + decomp_len); lsw_ip4_hdr(irs)->check = 0; lsw_ip4_hdr(irs)->check = ip_fast_csum(irs->iph, lsw_ip4_hdr( irs)->ihl); } KLIPS_PRINT(debug_rcv, "comp after len adjustments:\n"); KLIPS_IP_PRINT(debug_rcv & DB_TN_XMIT, irs->iph); /* Update skb length/tail by "putting" the growth */ safe_skb_put(irs->skb, decomp_len - crp->crp_olen); /* set the new header in the skb */ skb_set_network_header(irs->skb, ipsec_skb_offset(irs->skb, irs->iph)); KLIPS_IP_PRINT(debug_rcv & DB_RX_PKTRX, ip_hdr(irs->skb)); /* release the backup copy */ if (irs->pre_ipcomp_skb) { kfree_skb(irs->pre_ipcomp_skb); irs->pre_ipcomp_skb = NULL; } /* IPcomp finished, continue processing */ irs->state = IPSEC_RSM_DECAP_CONT; break; } bail: crypto_freereq(crp); crp = NULL; ipsec_ocf_queue_task(ipsec_rsm, irs); return 0; } enum ipsec_rcv_value ipsec_ocf_rcv(struct ipsec_rcv_state *irs) { struct cryptop *crp; struct cryptodesc *crde = NULL, *crda = NULL, *crdc = NULL; struct ipsec_sa *ipsp; int req_count = 0; int rc, err; KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_ocf_rcv\n"); ipsp = irs->ipsp; if (!ipsp) { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_ocf_rcv: " "no SA for rcv processing\n"); return IPSEC_RCV_SAIDNOTFOUND; } if (!irs->skb) { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_ocf_rcv: no skb\n"); return IPSEC_RCV_SAIDNOTFOUND; } switch (ipsp->ips_said.proto) { case IPPROTO_COMP: rc = ipsec_ocf_ipcomp_copy_expand(irs); if (rc != IPSEC_RCV_OK) { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_ocf_rcv: " "growing skb for ipcomp failed, rc=%d\n", rc); return rc; } break; case IPPROTO_ESP: case IPPROTO_AH: break; default: KLIPS_PRINT(debug_rcv & DB_RX_XF, "klips_debug:ipsec_ocf_rcv: " "bad protocol %d\n", ipsp->ips_said.proto); return IPSEC_RCV_BADPROTO; } req_count = (ipsp->ips_authalg ? 1 : 0) + (ipsp->ips_encalg ? 1 : 0); crp = crypto_getreq(req_count); if (!crp) { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_ocf_rcv: " "crypto_getreq returned NULL\n"); return IPSEC_RCV_REALLYBAD; } /* we currently don't support any chaining across protocols */ switch (ipsp->ips_said.proto) { case IPPROTO_ESP: /* * we are decrypting, from the setup in ipsec_ocf_sa_init above, we * need to flip the order of hash/cipher for receive so that it is * hash first then decrypt. Transmit is ok. */ if (crp->crp_desc && crp->crp_desc->crd_next) { crda = crp->crp_desc; crde = crda->crd_next; } else { crde = crp->crp_desc; crda = crde->crd_next; } break; case IPPROTO_COMP: crdc = crp->crp_desc; break; case IPPROTO_AH: crda = crp->crp_desc; break; } if (crda) { /* Authentication descriptor */ crda->crd_alg = ipsec_ocf_authalg(ipsp->ips_authalg); if (!crda->crd_alg) { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_ocf_rcv: " "bad auth alg 0x%x\n", ipsp->ips_authalg); crypto_freereq(crp); return IPSEC_RCV_BADPROTO; } if (!crde) { /* assuming AH processing */ /* push the IP header so we can authenticate it */ skb_push(irs->skb, ((unsigned char *)irs->protostuff.ahstuff.ahp) - ((unsigned char *)irs->iph)); } crda->crd_key = ipsp->ips_key_a; crda->crd_klen = ipsp->ips_key_bits_a; crda->crd_inject = irs->authenticator - irs->skb->data; /* OCF needs cri_mlen initialized in order to properly migrate the * session to another driver */ crda->crd_mlen = 12; /* Copy the authenticator to check aganinst later */ memcpy(irs->hash, irs->authenticator, 12); if (!crde) { /* assume AH processing */ /* AH processing, save fields we have to zero */ if (lsw_ip_hdr_version(irs) == 4) { irs->ttl = lsw_ip4_hdr(irs)->ttl; irs->check = lsw_ip4_hdr(irs)->check; irs->frag_off = lsw_ip4_hdr(irs)->frag_off; irs->tos = lsw_ip4_hdr(irs)->tos; lsw_ip4_hdr(irs)->ttl = 0; lsw_ip4_hdr(irs)->check = 0; lsw_ip4_hdr(irs)->frag_off = 0; lsw_ip4_hdr(irs)->tos = 0; } crda->crd_len = irs->skb->len; crda->crd_skip = ((unsigned char *)irs->iph) - irs->skb->data; memset(irs->authenticator, 0, 12); } else { crda->crd_len = irs->ilen; crda->crd_skip = ((unsigned char *) irs->protostuff.espstuff. espp) - irs->skb->data; /* * It would be nice to clear the authenticator here * to be sure we do not see it again later when checking. * We cannot. Some HW actually expects to check the in-data * hash and and flag an error if it is incorrect. * * What we do to allow this is to pass in the current in-data * value. Your OCF driver must ensure that it fails a request * for hash+decrypt with an invalid hash value, or returns the * computed in-data hash as requested. * * If your driver does not check the in-data hash but just * computes it value, you must ensure that it does not return * the original in-data hash by accident. It must invalidate the * in-data hash itself to force an auth check error. * * All existing drivers that do not care about the current * in-data hash do this by clearing the in-data hash before * processing, either directly or via their implementation. */ #if 0 memset(irs->authenticator, 0, 12); #endif } } if (crde) { crde->crd_alg = ipsec_ocf_encalg(ipsp->ips_encalg); if (!crde->crd_alg) { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_ocf_rcv: " "bad enc alg 0x%x\n", ipsp->ips_encalg); crypto_freereq(crp); return IPSEC_RCV_BADPROTO; } irs->esphlen = ESP_HEADER_LEN + ipsp->ips_iv_size; irs->ilen -= irs->esphlen; crde->crd_skip = (skb_transport_header(irs->skb) - irs->skb->data) + irs->esphlen; crde->crd_len = irs->ilen; crde->crd_inject = crde->crd_skip - ipsp->ips_iv_size; crde->crd_klen = ipsp->ips_key_bits_e; crde->crd_key = ipsp->ips_key_e; } if (crdc) { struct ipcomphdr *cmph; int compalg = ipsp->ips_encalg; /* Decompression descriptor */ crdc->crd_alg = ipsec_ocf_compalg(compalg); if (!crdc->crd_alg) { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_ocf_rcv: " "bad decomp alg 0x%x\n", ipsp->ips_encalg); crypto_freereq(crp); return IPSEC_RCV_BADPROTO; } crdc->crd_flags = 0; /* this is where the current ipcomp header is */ cmph = (struct ipcomphdr*)((char*)irs->iph + irs->iphlen); /* store the nested protocol */ irs->next_header = cmph->ipcomp_nh; /* start decompressing after ip header and the ipcomp header */ crdc->crd_skip = ((unsigned char*)irs->iph) + irs->iphlen + sizeof(struct ipcomphdr) - irs->skb->data; /* decompress all ip data past the ipcomp header */ if (lsw_ip_hdr_version(irs) == 6) { crdc->crd_len = (ntohs(lsw_ip6_hdr(irs)->payload_len) + sizeof(struct ipv6hdr)) - irs->iphlen - sizeof(struct ipcomphdr); } else { crdc->crd_len = ntohs(lsw_ip4_hdr(irs)->tot_len) - irs->iphlen - sizeof(struct ipcomphdr); } /* decompress inplace (some hardware can only do inplace) */ crdc->crd_inject = crdc->crd_skip; } crp->crp_ilen = irs->skb->len; /* Total input length */ crp->crp_olen = irs->skb->len; /* Total output length */ crp->crp_flags = CRYPTO_F_SKBUF | (ipsec_ocf_cbimm ? CRYPTO_F_CBIMM : 0) | (ipsec_ocf_batch ? CRYPTO_F_BATCH : 0); crp->crp_buf = (caddr_t) irs->skb; crp->crp_callback = ipsec_ocf_rcv_cb; crp->crp_sid = ipsp->ocf_cryptoid; crp->crp_opaque = (caddr_t) irs; rcv_migrate: if ((err = crypto_dispatch(crp))) { KLIPS_PRINT(debug_rcv, "crypto_dispatch rcv failure %u\n", err); crypto_freereq(crp); return IPSEC_RCV_REALLYBAD; } if (crp->crp_etype == EAGAIN) { /* Session has been migrated. Store the new session id and retry */ ipsp->ocf_cryptoid = crp->crp_sid; goto rcv_migrate; } return IPSEC_RCV_PENDING; } static int ipsec_ocf_xmit_cb(struct cryptop *crp) { struct ipsec_xmit_state *ixs = (struct ipsec_xmit_state *)crp->crp_opaque; struct iphdr *newiph; struct ipcomphdr *cmph; unsigned orig_len, comp_len; struct cryptodesc *crdc = NULL; KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_ocf_xmit_cb\n"); if (ixs == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_ocf_xmit_cb: " "NULL ixs in callback\n"); return 0; } /* * we must update the state before returning to the state machine. * if we have an error, terminate the processing by moving to the DONE * state */ ixs->state = IPSEC_XSM_DONE; /* assume bad xmit */ if (crp->crp_etype) { ptrdiff_t ptr_delta; if (crp->crp_etype == EAGAIN) { /* Session has been migrated. Store the new session id and retry */ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_ocf_xmit_cb: crypto session migrated\n"); ixs->ipsp->ocf_cryptoid = crp->crp_sid; /* resubmit request */ if (crypto_dispatch(crp) == 0) return 0; /* resubmit failed */ } KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_ocf_xmit_cb: " "error in processing 0x%x\n", crp->crp_etype); switch (ixs->ipsp->ips_said.proto) { case IPPROTO_COMP: /* * It's ok for compression to fail... we made a clone * of the packet, so we just revert it now... */ if (!ixs->pre_ipcomp_skb) { KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_ocf_xmit_cb: " "IPcomp on %u bytes failed, " "but we have no clone!\n", (unsigned int) (lsw_ip_hdr_version(ixs) == 6 ? (ntohs(lsw_ip6_hdr(ixs)-> payload_len) + sizeof(struct ipv6hdr)) : ntohs(lsw_ip4_hdr( ixs)->tot_len)) - ixs->iphlen); /* this is a fail. */ break; } KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_ocf_xmit_cb: " "IPcomp on %u bytes failed, " "using backup clone.\n", (unsigned int) (lsw_ip_hdr_version(ixs) == 6 ? (ntohs(lsw_ip6_hdr(ixs)->payload_len) + sizeof(struct ipv6hdr)) : ntohs(lsw_ip4_hdr(ixs)->tot_len)) - ixs->iphlen); ptr_delta = ixs->pre_ipcomp_skb->data - ixs->skb->data; ixs->iph = (void*)((char*)ixs->iph + ptr_delta); /* * cannot free it here, because we are under * IRQ, potentially, so queue it for later */ kfree_skb(ixs->skb); ixs->skb = ixs->pre_ipcomp_skb; ixs->pre_ipcomp_skb = NULL; skb_set_network_header(ixs->skb, ipsec_skb_offset(ixs->skb, ((void *) skb_network_header( ixs->skb)) + ptr_delta)); skb_set_transport_header(ixs->skb, ipsec_skb_offset(ixs->skb, ((void *) skb_transport_header( ixs->skb)) + ptr_delta)); KLIPS_IP_PRINT(debug_tunnel & DB_TN_XMIT, ixs->iph); /* this means we don't compress */ ixs->state = IPSEC_XSM_CONT; break; } goto bail; } switch (ixs->ipsp->ips_said.proto) { case IPPROTO_ESP: /* ESP, nothing to do */ break; case IPPROTO_AH: /* AH post processing, put back fields we had to zero */ if (lsw_ip_hdr_version(ixs) == 4) { lsw_ip4_hdr(ixs)->ttl = ixs->ttl; lsw_ip4_hdr(ixs)->check = ixs->check; lsw_ip4_hdr(ixs)->frag_off = ixs->frag_off; lsw_ip4_hdr(ixs)->tos = ixs->tos; } break; case IPPROTO_COMP: /* IPcomp fill in the header */ crdc = crp->crp_desc; KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_ocf_xmit_cb: " "after <%s%s%s>, SA:%s:\n", IPS_XFORM_NAME(ixs->ipsp), ixs->sa_len ? ixs->sa_txt : " (error)"); KLIPS_IP_PRINT(debug_tunnel & DB_TN_XMIT, ixs->iph); orig_len = (lsw_ip_hdr_version(ixs) == 6 ? (ntohs(lsw_ip6_hdr(ixs)->payload_len) + sizeof(struct ipv6hdr)) : ntohs(lsw_ip4_hdr(ixs)->tot_len)) - ixs->iphlen; comp_len = crp->crp_olen; if (sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) { ipsec_dmp_block("compress after", ((unsigned char*)ixs->iph) + ixs->iphlen, comp_len); } newiph = (struct iphdr *) ((char*)ixs->iph - sizeof(struct ipcomphdr)); cmph = (struct ipcomphdr *)((char*)newiph + ixs->iphlen); /* move the ip header to make room for the new ipcomp header */ memmove(((unsigned char *) ixs->skb->data) - sizeof(struct ipcomphdr), ixs->skb->data, (((unsigned char *) ixs->iph) + ixs->iphlen) - ((unsigned char *) ixs->skb->data)); /* DAVIDM check for head room */ skb_push(ixs->skb, sizeof(struct ipcomphdr)); ixs->iph = newiph; skb_set_network_header(ixs->skb, ipsec_skb_offset(ixs->skb, newiph)); skb_set_transport_header(ixs->skb, ipsec_skb_offset(ixs->skb, newiph) + ixs->iphlen); /* now we can fill in the ipcomp header */ cmph->ipcomp_nh = ixs->next_header; cmph->ipcomp_flags = 0; cmph->ipcomp_cpi = htons((__u16)(ntohl(ixs->ipsp->ips_said.spi) & 0x0000ffff)); /* update the ip header to reflect the compression */ if (lsw_ip_hdr_version(ixs) == 6) { lsw_ip6_hdr(ixs)->nexthdr = IPPROTO_COMP; lsw_ip6_hdr(ixs)->payload_len = htons(ixs->iphlen + sizeof(struct ipcomphdr) + comp_len - sizeof(struct ipv6hdr)); } else { lsw_ip4_hdr(ixs)->protocol = IPPROTO_COMP; lsw_ip4_hdr(ixs)->tot_len = htons(ixs->iphlen + sizeof(struct ipcomphdr) + comp_len); lsw_ip4_hdr(ixs)->check = 0; lsw_ip4_hdr(ixs)->check = ip_fast_csum((char *) ixs->iph, lsw_ip4_hdr(ixs)->ihl); } /* Update skb length/tail by "unputting" the shrinkage */ safe_skb_put(ixs->skb, comp_len - orig_len); ixs->ipsp->ips_comp_adapt_skip = 0; ixs->ipsp->ips_comp_adapt_tries = 0; /* release the backup copy */ if (ixs->pre_ipcomp_skb) { kfree_skb(ixs->pre_ipcomp_skb); ixs->pre_ipcomp_skb = NULL; } KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_ocf_xmit_cb: " "after <%s%s%s>, SA:%s:\n", IPS_XFORM_NAME(ixs->ipsp), ixs->sa_len ? ixs->sa_txt : " (error)"); KLIPS_IP_PRINT(debug_tunnel & DB_TN_XMIT, ixs->iph); break; } /* all good */ ixs->state = IPSEC_XSM_CONT; bail: crypto_freereq(crp); crp = NULL; ipsec_ocf_queue_task(ipsec_xsm, ixs); return 0; } enum ipsec_xmit_value ipsec_ocf_xmit(struct ipsec_xmit_state *ixs) { struct cryptop *crp; struct cryptodesc *crde = NULL, *crda = NULL, *crdc = NULL; struct ipsec_sa *ipsp; int req_count, payload_size; int err; KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_ocf_xmit\n"); ipsp = ixs->ipsp; if (!ipsp) { KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_ocf_xmit: " "no SA for rcv processing\n"); return IPSEC_XMIT_SAIDNOTFOUND; } if (!ixs->skb) { KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_ocf_xmit: no skb\n"); return IPSEC_XMIT_SAIDNOTFOUND; } switch (ipsp->ips_said.proto) { case IPPROTO_COMP: /* * skip packets that have less then 90 bytes of payload to * compress */ #ifdef CONFIG_KLIPS_IPV6 if (lsw_ip_hdr_version(ixs) == 6) { IPSEC_FRAG_OFF_DECL(frag_off) int nexthdroff; unsigned char nexthdr = lsw_ip6_hdr(ixs)->nexthdr; nexthdroff = ipsec_ipv6_skip_exthdr(ixs->skb, ((void *)( lsw_ip6_hdr( ixs) + 1)) - (void*)ixs->skb->data, &nexthdr, &frag_off); ixs->iphlen = nexthdroff - (ixs->iph - (void*)ixs->skb->data); payload_size = ntohs(lsw_ip6_hdr(ixs)->payload_len); } else #endif /* CONFIG_KLIPS_IPV6 */ { ixs->iphlen = lsw_ip4_hdr(ixs)->ihl << 2; payload_size = ntohs(lsw_ip4_hdr(ixs)->tot_len) - ixs->iphlen; } if (payload_size < 90) { KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_ocf_xmit: " "skipping IPcomp on packet with " "%d payload bytes\n", payload_size); return IPSEC_XMIT_OK; } /* * there is a chance that we may not compress, and * since the compression overwrites the data, we will clone * the packet and restore it if we fail to compress */ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_ocf_xmit: " "IPcomp on %d bytes can fail, " "duplicating the skb\n", payload_size); ixs->pre_ipcomp_skb = skb_copy_expand(ixs->skb, skb_headroom(ixs->skb), skb_tailroom(ixs->skb), GFP_ATOMIC); if (!ixs->pre_ipcomp_skb) { /* * We can either drop the packet, but instead we try * to do the compression as it might succeed. Should it * fail, the packet will be dropped in the callback. */ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_ocf_xmit: " "skb_clone failed -- ignoring\n"); } break; case IPPROTO_ESP: case IPPROTO_AH: break; default: KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_ocf_xmit: " "bad protocol %d\n", ipsp->ips_said.proto); return IPSEC_XMIT_BADPROTO; } req_count = (ipsp->ips_authalg ? 1 : 0) + (ipsp->ips_encalg ? 1 : 0); crp = crypto_getreq(req_count); if (!crp) { KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_ocf_xmit: " "crypto_getreq returned NULL\n"); return IPSEC_XMIT_ERRMEMALLOC; } /* we currently don't support any chaining across protocols */ switch (ipsp->ips_said.proto) { case IPPROTO_ESP: crde = crp->crp_desc; crda = crde->crd_next; break; case IPPROTO_COMP: crdc = crp->crp_desc; break; case IPPROTO_AH: crda = crp->crp_desc; break; } if (crda) { /* Authentication descriptor */ crda->crd_alg = ipsec_ocf_authalg(ipsp->ips_authalg); if (!crda->crd_alg) { KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_ocf_xmit: " "bad auth alg 0x%x\n", ipsp->ips_authalg); crypto_freereq(crp); return IPSEC_RCV_BADPROTO; } if (!crde) { /* assume AH processing */ /* AH processing, save fields we have to zero */ crda->crd_skip = ((unsigned char *) ixs->iph) - ixs->skb->data; if (lsw_ip_hdr_version(ixs) == 4) { ixs->ttl = lsw_ip4_hdr(ixs)->ttl; ixs->check = lsw_ip4_hdr(ixs)->check; ixs->frag_off = lsw_ip4_hdr(ixs)->frag_off; ixs->tos = lsw_ip4_hdr(ixs)->tos; lsw_ip4_hdr(ixs)->ttl = 0; lsw_ip4_hdr(ixs)->check = 0; lsw_ip4_hdr(ixs)->frag_off = 0; lsw_ip4_hdr(ixs)->tos = 0; } crda->crd_inject = ((struct ahhdr *)(ixs->dat + ixs->iphlen))-> ah_data - ixs->skb->data; crda->crd_len = ixs->len - ixs->authlen; memset(ixs->skb->data + crda->crd_inject, 0, 12); } else { crda->crd_skip = ((unsigned char *) ixs->espp) - ixs->skb->data; crda->crd_inject = ixs->len - ixs->authlen; crda->crd_len = ixs->len - ixs->iphlen - ixs->authlen; } /* OCF needs cri_mlen initialized in order to properly migrate * the session to another driver */ crda->crd_mlen = 12; crda->crd_key = ipsp->ips_key_a; crda->crd_klen = ipsp->ips_key_bits_a; } if (crde) { /* Encryption descriptor */ crde->crd_alg = ipsec_ocf_encalg(ipsp->ips_encalg); if (!crde->crd_alg) { KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_ocf_xmit: " "bad enc alg 0x%x\n", ipsp->ips_encalg); crypto_freereq(crp); return IPSEC_RCV_BADPROTO; } crde->crd_flags = CRD_F_ENCRYPT; crde->crd_skip = ixs->idat - ixs->dat; crde->crd_len = ixs->ilen; crde->crd_inject = ((unsigned char *) ixs->espp->esp_iv) - ixs->dat; crde->crd_klen = ipsp->ips_key_bits_e; crde->crd_key = ipsp->ips_key_e; } if (crdc) { int compalg = ipsp->ips_encalg; /* Compression descriptor */ crdc->crd_alg = ipsec_ocf_compalg(compalg); if (!crdc->crd_alg) { KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_ocf_xmit: " "bad comp alg 0x%x\n", ipsp->ips_encalg); crypto_freereq(crp); return IPSEC_RCV_BADPROTO; } crdc->crd_flags = CRD_F_ENCRYPT; /* store the nested protocol */ if (lsw_ip_hdr_version(ixs) == 6) ixs->next_header = lsw_ip6_hdr(ixs)->nexthdr; else ixs->next_header = lsw_ip4_hdr(ixs)->protocol; /* start compressing after ip header */ crdc->crd_skip = ipsec_skb_offset(ixs->skb, ((unsigned char*)ixs->iph) + ixs->iphlen); /* compress all ip data */ if (lsw_ip_hdr_version(ixs) == 6) crdc->crd_len = ntohs(lsw_ip6_hdr(ixs)->payload_len); else crdc->crd_len = ntohs(lsw_ip4_hdr(ixs)->tot_len) - ixs->iphlen; /* compress inplace (some hardware can only do inplace) */ crdc->crd_inject = crdc->crd_skip; if (sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) { ipsec_dmp_block("compress before", ((unsigned char*)ixs->iph) + ixs->iphlen, crdc->crd_len); } } crp->crp_ilen = ixs->skb->len; /* Total input length */ crp->crp_olen = ixs->skb->len; /* Total output length */ crp->crp_flags = CRYPTO_F_SKBUF | (ipsec_ocf_cbimm ? CRYPTO_F_CBIMM : 0) | (ipsec_ocf_batch ? CRYPTO_F_BATCH : 0); crp->crp_buf = (caddr_t) ixs->skb; crp->crp_callback = ipsec_ocf_xmit_cb; crp->crp_sid = ipsp->ocf_cryptoid; crp->crp_opaque = (caddr_t) ixs; xmit_migrate: if ((err = crypto_dispatch(crp))) { KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "crypto_dispatch xmit failure %u\n", err); crypto_freereq(crp); return IPSEC_XMIT_ERRMEMALLOC; } if (crp->crp_etype == EAGAIN) { /* Session has been migrated. Store the new session id */ ipsp->ocf_cryptoid = crp->crp_sid; goto xmit_migrate; } return IPSEC_XMIT_PENDING; } #ifdef CONFIG_KLIPS_AH static struct ipsec_alg_supported ocf_ah_algs[] = { { .ias_name = "ocf-md5hmac", .ias_id = AH_MD5, .ias_exttype = SADB_EXT_SUPPORTED_AUTH, .ias_ivlen = 0, .ias_keyminbits = 128, .ias_keymaxbits = 128, }, { .ias_name = "ocf-sha1hmac", .ias_id = AH_SHA, .ias_exttype = SADB_EXT_SUPPORTED_AUTH, .ias_ivlen = 0, .ias_keyminbits = 160, .ias_keymaxbits = 160, }, { .ias_name = "ocf-sha256hmac", .ias_id = AH_SHA2_256, .ias_exttype = SADB_EXT_SUPPORTED_AUTH, .ias_ivlen = 0, .ias_keyminbits = 256, .ias_keymaxbits = 256, }, { .ias_name = "ocf-sha384hmac", .ias_id = AH_SHA2_384, .ias_exttype = SADB_EXT_SUPPORTED_AUTH, .ias_ivlen = 0, .ias_keyminbits = 384, .ias_keymaxbits = 384, }, { .ias_name = "ocf-sha512hmac", .ias_id = AH_SHA2_512, .ias_exttype = SADB_EXT_SUPPORTED_AUTH, .ias_ivlen = 0, .ias_keyminbits = 512, .ias_keymaxbits = 512, }, { .ias_name = NULL, .ias_id = 0, .ias_exttype = 0, .ias_ivlen = 0, .ias_keyminbits = 0, .ias_keymaxbits = 0, } }; #endif /* CONFIG_KLIPS_AH */ static struct ipsec_alg_supported ocf_esp_algs[] = { { .ias_name = "ocf-md5hmac", .ias_id = AH_MD5, .ias_exttype = SADB_EXT_SUPPORTED_AUTH, .ias_ivlen = 0, .ias_keyminbits = 128, .ias_keymaxbits = 128, }, { .ias_name = "ocf-sha1hmac", .ias_id = AH_SHA, .ias_exttype = SADB_EXT_SUPPORTED_AUTH, .ias_ivlen = 0, .ias_keyminbits = 160, .ias_keymaxbits = 160, }, { .ias_name = "ocf-sha256hmac", .ias_id = AH_SHA2_256, .ias_exttype = SADB_EXT_SUPPORTED_AUTH, .ias_ivlen = 0, .ias_keyminbits = 256, .ias_keymaxbits = 256, }, { .ias_name = "ocf-sha384hmac", .ias_id = AH_SHA2_384, .ias_exttype = SADB_EXT_SUPPORTED_AUTH, .ias_ivlen = 0, .ias_keyminbits = 384, .ias_keymaxbits = 384, }, { .ias_name = "ocf-sha512hmac", .ias_id = AH_SHA2_512, .ias_exttype = SADB_EXT_SUPPORTED_AUTH, .ias_ivlen = 0, .ias_keyminbits = 512, .ias_keymaxbits = 512, }, { .ias_name = "ocf-aes", .ias_id = ESP_AES, .ias_exttype = SADB_EXT_SUPPORTED_ENCRYPT, .ias_ivlen = 16, .ias_keyminbits = 128, .ias_keymaxbits = 256, }, { .ias_name = "ocf-3des", .ias_id = ESP_3DES, .ias_exttype = SADB_EXT_SUPPORTED_ENCRYPT, .ias_ivlen = 8, .ias_keyminbits = 192, .ias_keymaxbits = 192, }, { .ias_name = NULL, .ias_id = 0, .ias_exttype = 0, .ias_ivlen = 0, .ias_keyminbits = 0, .ias_keymaxbits = 0, } }; static int ipsec_ocf_check_alg(struct ipsec_alg_supported *s) { struct cryptoini cri; int64_t cryptoid; memset(&cri, 0, sizeof(cri)); if (s->ias_exttype == SADB_EXT_SUPPORTED_ENCRYPT) cri.cri_alg = ipsec_ocf_encalg(s->ias_id); else cri.cri_alg = ipsec_ocf_authalg(s->ias_id); cri.cri_klen = s->ias_keyminbits; cri.cri_key = "0123456789abcdefghijklmnopqrstuvwxyz"; if (crypto_newsession(&cryptoid, &cri, ipsec_ocf_crid)) { KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_ocf:%s not supported\n", s->ias_name); return 0; } crypto_freesession(cryptoid); KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_ocf:%s supported\n", s->ias_name); return 1; } void ipsec_ocf_init(void) { struct ipsec_alg_supported *s; ipsec_ocf_queue_init(); for (s = ocf_esp_algs; s->ias_name; s++) { if (ipsec_ocf_check_alg(s)) { (void)pfkey_list_insert_supported(s, &(pfkey_supported_list [ SADB_SATYPE_ESP ])); } } #ifdef CONFIG_KLIPS_AH for (s = ocf_ah_algs; s->ias_name; s++) { if (ipsec_ocf_check_alg(s)) (void)pfkey_list_insert_supported(s, &(pfkey_supported_list [ SADB_SATYPE_AH ])); } #endif /* send register event to userspace */ pfkey_register_reply(SADB_SATYPE_ESP, NULL); pfkey_register_reply(SADB_SATYPE_AH, NULL); } libreswan-3.32/linux/net/ipsec/ipsec_ocf.h000066400000000000000000000032221365625662500206010ustar00rootroot00000000000000#ifndef _IPSEC_OCF_H_ #define _IPSEC_OCF_H_ /****************************************************************************/ /* * IPSEC OCF support * * This code written by David McCullough * Copyright (C) 2005 Intel Corporation. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38) && \ !defined(AUTOCONF_INCLUDED) #include #endif #include #ifdef CONFIG_KLIPS_OCF #include extern int ipsec_ocf_sa_init(struct ipsec_sa *ipsp, int authalg, int encalg); extern int ipsec_ocf_comp_sa_init(struct ipsec_sa *ipsp, int compalg); extern int ipsec_ocf_sa_free(struct ipsec_sa *ipsp); extern enum ipsec_rcv_value ipsec_ocf_rcv(struct ipsec_rcv_state *irs); extern enum ipsec_xmit_value ipsec_ocf_xmit(struct ipsec_xmit_state *ixs); extern void ipsec_ocf_init(void); #else # error \ This file should not be used without CONFIG_KLIPS_OCF, check MODULE_DEF_INCLUDE and MODULE_DEFCONFIG #endif /****************************************************************************/ #endif /* _IPSEC_OCF_H_ */ libreswan-3.32/linux/net/ipsec/ipsec_proc.c000066400000000000000000000471011365625662500207740ustar00rootroot00000000000000/* * @(#) /proc file system interface code. * * Copyright (C) 1996, 1997 John Ioannidis. * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs * 2001 Michael Richardson * Copyright (C) 2005 Michael Richardson * Copyright (C) 2005-2008 Michael Richardson * Copyright (C) 2006-2012 David McCullough * Copyright (C) 2006-2010 Paul Wouters * Copyright (C) 2011 Bart Trojanowski * Copyright (C) 2012 Paul Wouters * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38) && \ !defined(AUTOCONF_INCLUDED) # include #endif #define __NO_VERSION__ #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) && LINUX_VERSION_CODE >= \ KERNEL_VERSION(2, 4, 26) # include #endif #include /* printk() */ #include /* struct iphdr */ #include "libreswan/ipsec_kversion.h" #include "libreswan/ipsec_param.h" #include /* kmalloc() */ #include /* error codes */ #include /* size_t */ #include /* mark_bh */ #include /* struct device, and other headers */ #include /* eth_type_trans */ #include /* struct sockaddr_in */ #include #include /* copy_from_user */ #include #include /* *lock* */ #include #ifdef CONFIG_PROC_FS #include #endif /* CONFIG_PROC_FS */ #include #include "libreswan/radij.h" #include "libreswan/ipsec_life.h" #include "libreswan/ipsec_stats.h" #include "libreswan/ipsec_sa.h" #include "libreswan/ipsec_encap.h" #include "libreswan/ipsec_radij.h" #include "libreswan/ipsec_xform.h" #include "libreswan/ipsec_tunnel.h" #include "libreswan/ipsec_xmit.h" #include "libreswan/ipsec_rcv.h" #include "libreswan/ipsec_ah.h" #include "libreswan/ipsec_esp.h" #ifdef CONFIG_KLIPS_IPCOMP #include "libreswan/ipcomp.h" #endif /* CONFIG_KLIPS_IPCOMP */ #include "libreswan/ipsec_proto.h" #include #include #include #if defined(IP_IPSEC_REFINFO) || defined(IP_IPSEC_BINDREF) #define IPSEC_PROC_SHOW_SAREF_INFO #endif #ifndef CONFIG_PROC_FS /* * just complain because pluto won't run without /proc! */ #error You must have PROC_FS built in to use KLIPS #endif static struct proc_dir_entry *proc_net_ipsec_dir = NULL; static struct proc_dir_entry *proc_eroute_dir = NULL; static struct proc_dir_entry *proc_spi_dir = NULL; static struct proc_dir_entry *proc_spigrp_dir = NULL; static struct proc_dir_entry *proc_stats_dir = NULL; #ifdef IPSEC_SA_RECOUNT_DEBUG static struct proc_dir_entry *proc_saraw_dir = NULL; #endif int debug_esp = 0; int debug_ah = 0; int sysctl_ipsec_inbound_policy_check = 1; int debug_xmit = 0; int debug_xform = 0; int debug_eroute = 0; int debug_spi = 0; int debug_radij = 0; int debug_pfkey = 0; int debug_rcv = 0; int debug_netlink = 0; int sysctl_ipsec_debug_verbose = 0; int sysctl_ipsec_debug_ipcomp = 0; int sysctl_ipsec_icmp = 0; int sysctl_ipsec_tos = 1; /* hide per default, unless hidetos=no */ #define DECREMENT_UNSIGNED(X, amount) (((X) >= (amount)) ? (X) - (amount) : 0) #ifdef CONFIG_KLIPS_ALG extern int ipsec_xform_show(struct seq_file *seq, void *offset); #endif IPSEC_PROCFS_DEBUG_NO_STATIC int ipsec_eroute_show(struct seq_file *seq, void *offset) { if (debug_radij & DB_RJ_DUMPTREES) rj_dumptrees(); /* XXXXXXXXX */ KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, "klips_debug:ipsec_eroute_show: seq=%p offset=%p\n", seq, offset); spin_lock_bh(&eroute_lock); rj_walktree(rnh, ipsec_rj_walker_show, seq); spin_unlock_bh(&eroute_lock); return 0; } IPSEC_PROCFS_DEBUG_NO_STATIC int ipsec_spi_format(struct ipsec_sa *sa_p, struct seq_file *seq) { char sa[SATOT_BUF]; char buf_s[SUBNETTOA_BUF]; char buf_d[SUBNETTOA_BUF]; size_t sa_len; ipsec_sa_get(sa_p, IPSEC_REFPROC); sa_len = satot(&sa_p->ips_said, 'x', sa, sizeof(sa)); seq_printf(seq, "%s ", sa_len ? sa : " (error)"); seq_printf(seq, "%s%s%s", IPS_XFORM_NAME(sa_p)); seq_printf(seq, ": dir=%s", (sa_p->ips_flags & EMT_INBOUND) ? "in " : "out"); if (sa_p->ips_addr_s) { sin_addrtot(sa_p->ips_addr_s, 0, buf_s, sizeof(buf_s)); seq_printf(seq, " src=%s", buf_s); } if (sa_p->ips_said.proto == IPPROTO_IPIP && (sa_p->ips_flags & (SADB_X_SAFLAGS_INFLOW|SADB_X_SAFLAGS_POLICYONLY))) { if (sa_p->ips_flow_s.u.v4.sin_family == AF_INET) { subnettoa(sa_p->ips_flow_s.u.v4.sin_addr, sa_p->ips_mask_s.u.v4.sin_addr, 0, buf_s, sizeof(buf_s)); subnettoa(sa_p->ips_flow_d.u.v4.sin_addr, sa_p->ips_mask_d.u.v4.sin_addr, 0, buf_d, sizeof(buf_d)); } else { subnet6toa(&sa_p->ips_flow_s.u.v6.sin6_addr, &sa_p->ips_mask_s.u.v6.sin6_addr, 0, buf_s, sizeof(buf_s)); subnet6toa(&sa_p->ips_flow_d.u.v6.sin6_addr, &sa_p->ips_mask_d.u.v6.sin6_addr, 0, buf_d, sizeof(buf_d)); } seq_printf(seq, " policy=%s->%s", buf_s, buf_d); } if (sa_p->ips_iv_bits) { int j; seq_printf(seq, " iv_bits=%dbits iv=0x", sa_p->ips_iv_bits); for (j = 0; j < sa_p->ips_iv_bits / 8; j++) { #ifdef CONFIG_KLIPS_OCF if (sa_p->ips_iv == NULL) { /* * ocf doesn't set the IV * so fake it for the test cases */ seq_printf(seq, "%02x", 0xA5 + j); } else #endif seq_printf(seq, "%02x", ((__u8*)sa_p->ips_iv)[j]); } } if (sa_p->ips_encalg || sa_p->ips_authalg) { if (sa_p->ips_replaywin) seq_printf(seq, " ooowin=%d", sa_p->ips_replaywin); if (sa_p->ips_errs.ips_replaywin_errs) seq_printf(seq, " ooo_errs=%d", sa_p->ips_errs.ips_replaywin_errs); if (sa_p->ips_replaywin_lastseq) seq_printf(seq, " seq=%d", sa_p->ips_replaywin_lastseq); if (sa_p->ips_replaywin_bitmap) seq_printf(seq, " bit=0x%Lx", sa_p->ips_replaywin_bitmap); if (sa_p->ips_replaywin_maxdiff) seq_printf(seq, " max_seq_diff=%d", sa_p->ips_replaywin_maxdiff); } if (sa_p->ips_flags & ~EMT_INBOUND) { seq_printf(seq, " flags=0x%x", sa_p->ips_flags & ~EMT_INBOUND); seq_printf(seq, "<"); /* flag printing goes here */ seq_printf(seq, ">"); } if (sa_p->ips_auth_bits) seq_printf(seq, " alen=%d", sa_p->ips_auth_bits); if (sa_p->ips_key_bits_a) seq_printf(seq, " aklen=%d", sa_p->ips_key_bits_a); if (sa_p->ips_errs.ips_auth_errs) seq_printf(seq, " auth_errs=%d", sa_p->ips_errs.ips_auth_errs); if (sa_p->ips_key_bits_e) seq_printf(seq, " eklen=%d", sa_p->ips_key_bits_e); if (sa_p->ips_errs.ips_encsize_errs) seq_printf(seq, " encr_size_errs=%d", sa_p->ips_errs.ips_encsize_errs); if (sa_p->ips_errs.ips_encpad_errs) seq_printf(seq, " encr_pad_errs=%d", sa_p->ips_errs.ips_encpad_errs); seq_printf(seq, " jiffies=%lu", jiffies); seq_printf(seq, " life(c,s,h)="); ipsec_lifetime_format(seq, "alloc", ipsec_life_countbased, &sa_p->ips_life.ipl_allocations); ipsec_lifetime_format(seq, "bytes", ipsec_life_countbased, &sa_p->ips_life.ipl_bytes); ipsec_lifetime_format(seq, "addtime", ipsec_life_timebased, &sa_p->ips_life.ipl_addtime); ipsec_lifetime_format(seq, "usetime", ipsec_life_timebased, &sa_p->ips_life.ipl_usetime); ipsec_lifetime_format(seq, "packets", ipsec_life_countbased, &sa_p->ips_life.ipl_packets); if (sa_p->ips_life.ipl_usetime.ipl_last) { /* XXX-MCR should be last? */ seq_printf(seq, " idle=%Ld", ipsec_jiffieshz_elapsed(jiffies/HZ, sa_p->ips_life.ipl_usetime.ipl_last)); } #ifdef CONFIG_KLIPS_IPCOMP if (sa_p->ips_said.proto == IPPROTO_COMP && (sa_p->ips_comp_ratio_dbytes || sa_p->ips_comp_ratio_cbytes)) { seq_printf(seq, " ratio=%Ld:%Ld", sa_p->ips_comp_ratio_dbytes, sa_p->ips_comp_ratio_cbytes); } #endif /* CONFIG_KLIPS_IPCOMP */ seq_printf(seq, " natencap="); switch (sa_p->ips_natt_type) { case 0: seq_printf(seq, "none"); break; case ESPINUDP_WITH_NON_IKE: seq_printf(seq, "nonike"); break; case ESPINUDP_WITH_NON_ESP: seq_printf(seq, "nonesp"); break; default: seq_printf(seq, "unknown"); break; } seq_printf(seq, " natsport=%d", sa_p->ips_natt_sport); seq_printf(seq, " natdport=%d", sa_p->ips_natt_dport); /* we decrement by one, because this SA has been referenced in order to dump this info */ seq_printf(seq, " refcount=%d", atomic_read(&sa_p->ips_refcount)-1); #ifdef IPSEC_SA_RECOUNT_DEBUG { int f; seq_printf(seq, "["); for (f = 0; f < sizeof(sa_p->ips_track); f++) seq_printf(seq, "%s%d", f == 0 ? "" : ",", sa_p->ips_track[f]); seq_printf(seq, "]"); } #endif seq_printf(seq, " ref=%d", sa_p->ips_ref); seq_printf(seq, " refhim=%d", sa_p->ips_refhim); if (sa_p->ips_out) { seq_printf(seq, " outif=%s:%d", sa_p->ips_out->name, sa_p->ips_transport_direct); } if (debug_xform) { seq_printf(seq, " reftable=%lu refentry=%lu", (unsigned long)IPsecSAref2table(sa_p->ips_ref), (unsigned long)IPsecSAref2entry(sa_p->ips_ref)); } seq_printf(seq, "\n"); ipsec_sa_put(sa_p, IPSEC_REFPROC); return 0; } IPSEC_PROCFS_DEBUG_NO_STATIC int ipsec_spi_show(struct seq_file *seq, void *offset) { int i; struct ipsec_sa *sa_p; KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, "klips_debug:ipsec_spi_show: seq=%p offset=%p\n", seq, offset); spin_lock_bh(&tdb_lock); for (i = 0; i < SADB_HASHMOD; i++) for (sa_p = ipsec_sadb_hash[i]; sa_p; sa_p = sa_p->ips_hnext) ipsec_spi_format(sa_p, seq); spin_unlock_bh(&tdb_lock); return 0; } IPSEC_PROCFS_DEBUG_NO_STATIC int ipsec_spigrp_show(struct seq_file *seq, void *offset) { int i; struct ipsec_sa *sa_p, *sa_p2; char sa[SATOT_BUF]; size_t sa_len; KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, "klips_debug:ipsec_spigrp_show: seq=%p offset=%p\n", seq, offset); spin_lock_bh(&tdb_lock); for (i = 0; i < SADB_HASHMOD; i++) { for (sa_p = ipsec_sadb_hash[i]; sa_p != NULL; sa_p = sa_p->ips_hnext) { sa_p2 = sa_p; while (sa_p2 != NULL) { struct ipsec_sa *sa2n; sa_len = satot(&sa_p2->ips_said, 'x', sa, sizeof(sa)); seq_printf(seq, "%s ", sa_len ? sa : " (error)"); sa2n = sa_p2->ips_next; sa_p2 = sa2n; } seq_printf(seq, "\n"); } } spin_unlock_bh(&tdb_lock); return 0; } #ifdef IPSEC_SA_RECOUNT_DEBUG IPSEC_PROCFS_DEBUG_NO_STATIC int ipsec_saraw_show(struct seq_file *seq, void *offset) { struct ipsec_sa *sa_p; extern struct ipsec_sa *ipsec_sa_raw; KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, "klips_debug:ipsec_saraw_show: seq=%p offset=%p\n", seq, offset); spin_lock_bh(&tdb_lock); for (sa_p = ipsec_sa_raw; sa_p; sa_p = sa_p->ips_raw) ipsec_spi_format(sa_p, seq); spin_unlock_bh(&tdb_lock); return 0; } #endif /* IPSEC_SA_RECOUNT_DEBUG */ IPSEC_PROCFS_DEBUG_NO_STATIC int ipsec_tncfg_show(struct seq_file *seq, void *offset) { int i; char name[9]; struct net_device *dev, *privdev; struct ipsecpriv *priv; KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, "klips_debug:ipsec_tncfg_show: seq=%p offset=%p\n", seq, offset); for (i = 0; i < IPSEC_NUM_IFMAX; i++) { ipsec_snprintf(name, (ssize_t) sizeof(name), IPSEC_DEV_FORMAT, i); dev = __ipsec_dev_get(name); if (dev) { priv = netdev_to_ipsecpriv(dev); seq_printf(seq, "%s", dev->name); if (priv) { privdev = (struct net_device *)(priv->dev); seq_printf(seq, " -> %s", privdev ? privdev->name : "NULL"); seq_printf(seq, " mtu=%d(%d) -> %d", dev->mtu, priv->mtu, privdev ? privdev->mtu : 0); } else { KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, "klips_debug:ipsec_tncfg_show: " "device '%s' has no private data space!\n", dev->name); } seq_printf(seq, "\n"); } } return 0; } IPSEC_PROCFS_DEBUG_NO_STATIC int ipsec_version_show(struct seq_file *seq, void *offset) { KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, "klips_debug:ipsec_version_show: seq=%p offset=%p\n", seq, offset); seq_printf(seq, "Libreswan version: %s\n", ipsec_version_code()); return 0; } #ifdef IPSEC_PROC_SHOW_SAREF_INFO IPSEC_PROCFS_DEBUG_NO_STATIC int ipsec_saref_show(struct seq_file *seq, void *offset) { KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, "klips_debug:ipsec_saref_show: seq=%p offset=%p\n", seq, offset); #ifdef IP_IPSEC_REFINFO seq_printf(seq, "refinfo patch applied\n"); #endif #ifdef IP_IPSEC_BINDREF seq_printf(seq, "bindref patch applied\n"); #endif #ifdef CONFIG_INET_IPSEC_SAREF seq_printf(seq, "saref enabled (%s)\n", ipsec_version_code()); #else seq_printf(seq, "saref disabled (%s)\n", ipsec_version_code()); #endif return 0; } #endif #ifdef CONFIG_KLIPS_OCF unsigned int ocf_available = 1; #else unsigned int ocf_available = 0; #endif module_param(ocf_available, int, 0644); IPSEC_PROCFS_DEBUG_NO_STATIC int ipsec_ocf_show(struct seq_file *seq, void *offset) { KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, "klips_debug:ipsec_ocf_show: seq=%p offset=%p\n", seq, offset); seq_printf(seq, "%d\n", ocf_available); return 0; } #ifdef CONFIG_IPSEC_NAT_TRAVERSAL unsigned int natt_available = 1; #elif defined (HAVE_UDP_ENCAP_CONVERT) unsigned int natt_available = 2; #else unsigned int natt_available = 0; #endif module_param(natt_available, int, 0644); IPSEC_PROCFS_DEBUG_NO_STATIC int ipsec_natt_show(struct seq_file *seq, void *offset) { KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, "klips_debug:ipsec_natt_show: seq=%p offset=%p\n", seq, offset); seq_printf(seq, "%d\n", natt_available); return 0; } IPSEC_PROCFS_DEBUG_NO_STATIC int ipsec_klipsdebug_show(struct seq_file *seq, void *offset) { KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, "klips_debug:ipsec_klipsdebug_show: seq=%p, offset=%p\n", seq, offset); seq_printf(seq, "debug_tunnel=%08x.\n", debug_tunnel); seq_printf(seq, "debug_xform=%08x.\n", debug_xform); seq_printf(seq, "debug_eroute=%08x.\n", debug_eroute); seq_printf(seq, "debug_spi=%08x.\n", debug_spi); seq_printf(seq, "debug_radij=%08x.\n", debug_radij); seq_printf(seq, "debug_esp=%08x.\n", debug_esp); seq_printf(seq, "debug_ah=%08x.\n", debug_ah); seq_printf(seq, "debug_rcv=%08x.\n", debug_rcv); seq_printf(seq, "debug_pfkey=%08x.\n", debug_pfkey); return 0; } IPSEC_PROCFS_DEBUG_NO_STATIC int ipsec_trap_count_show(struct seq_file *seq, void *offset) { KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, "klips_debug:ipsec_trap_count_show: seq=%p offset=%p\n", seq, offset); seq_printf(seq, "%08x\n", ipsec_xmit_trap_count); return 0; } IPSEC_PROCFS_DEBUG_NO_STATIC int ipsec_trap_sendcount_show(struct seq_file *seq, void *offset) { KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, "klips_debug:ipsec_trap_sendcount_show: seq=%p offset=%p\n", seq, offset); seq_printf(seq, "%08x\n", ipsec_xmit_trap_sendcount); return 0; } struct ipsec_proc_list { char *name; umode_t mode; struct proc_dir_entry **parent; struct proc_dir_entry **dir; int (*proc_open)(struct seq_file *seq, void *offset); void *data; /* not currently used but implemented */ }; #define DIRE(n,p,d) \ { .name = (n), .parent = (p), .dir = (d) } #define NODE(n,p,o,m) \ { .name = (n), .mode = (m), .parent = (p), .proc_open = (o), .data = NULL } static int ipsec_proc_open(struct inode *inode, struct file *file) { struct ipsec_proc_list *it = PDE_DATA(inode); return single_open(file, it->proc_open, it->data); } static const struct file_operations ipsec_proc_fops = { .open = ipsec_proc_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; static struct ipsec_proc_list proc_items[]={ NODE("klipsdebug", &proc_net_ipsec_dir, ipsec_klipsdebug_show, 0), DIRE("eroute", &proc_net_ipsec_dir, &proc_eroute_dir), NODE("all", &proc_eroute_dir, ipsec_eroute_show, 0), DIRE("spi", &proc_net_ipsec_dir, &proc_spi_dir), NODE("all", &proc_spi_dir, ipsec_spi_show, 0), DIRE("spigrp", &proc_net_ipsec_dir, &proc_spigrp_dir), NODE("all", &proc_spigrp_dir, ipsec_spigrp_show, 0), #ifdef IPSEC_SA_RECOUNT_DEBUG DIRE("saraw", &proc_net_ipsec_dir, &proc_saraw_dir), NODE("all", &proc_saraw_dir, ipsec_saraw_show, 0), #endif NODE("tncfg", &proc_net_ipsec_dir, ipsec_tncfg_show, 0), #ifdef CONFIG_KLIPS_ALG NODE("xforms", &proc_net_ipsec_dir, ipsec_xform_show, 0), #endif DIRE("stats", &proc_net_ipsec_dir, &proc_stats_dir), NODE("trap_count", &proc_stats_dir, ipsec_trap_count_show, 0), NODE("trap_sendcount", &proc_stats_dir, ipsec_trap_sendcount_show, 0), NODE("natt", &proc_net_ipsec_dir, ipsec_natt_show, 0), NODE("ocf", &proc_net_ipsec_dir, ipsec_ocf_show, 0), NODE("version", &proc_net_ipsec_dir, ipsec_version_show, 0444), #ifdef IPSEC_PROC_SHOW_SAREF_INFO NODE("saref", &proc_net_ipsec_dir, ipsec_saref_show, 0), #endif NODE("pf_key", &PROC_NET, pfkey_show, 0), NODE("pf_key_supported", &PROC_NET, pfkey_supported_show, 0), NODE("pf_key_registered",&PROC_NET, pfkey_registered_show, 0), {} }; int ipsec_proc_init(void) { int error = 0; struct proc_dir_entry *item; struct ipsec_proc_list *it; /* create /proc/net/ipsec */ proc_net_ipsec_dir = proc_mkdir("ipsec", PROC_NET); if (proc_net_ipsec_dir == NULL) { /* no point in continuing */ return 1; } for (it = proc_items; it->name; it++) { if (it->dir) { item = proc_mkdir(it->name, *it->parent); *it->dir = item; } else item = proc_create_data(it->name, it->mode, *it->parent, &ipsec_proc_fops, it); if (!item) error |= 1; } /* now create some symlinks to provide compatibility */ proc_symlink("ipsec_eroute", PROC_NET, "ipsec/eroute/all"); proc_symlink("ipsec_spi", PROC_NET, "ipsec/spi/all"); proc_symlink("ipsec_spigrp", PROC_NET, "ipsec/spigrp/all"); #ifdef IPSEC_SA_RECOUNT_DEBUG proc_symlink("ipsec_saraw", PROC_NET, "ipsec/saraw/all"); #endif proc_symlink("ipsec_tncfg", PROC_NET, "ipsec/tncfg"); proc_symlink("ipsec_version", PROC_NET, "ipsec/version"); proc_symlink("ipsec_klipsdebug", PROC_NET, "ipsec/klipsdebug"); return error; } void ipsec_proc_cleanup(void) { struct ipsec_proc_list *it; /* remove entries in reverse */ for (it = proc_items; it->name; it++) ; for (it--; it >= proc_items && it->name; it--) remove_proc_subtree(it->name, *it->parent); remove_proc_subtree("ipsec_klipsdebug", PROC_NET); remove_proc_subtree("ipsec_eroute", PROC_NET); remove_proc_subtree("ipsec_spi", PROC_NET); remove_proc_subtree("ipsec_spigrp", PROC_NET); #ifdef IPSEC_SA_RECOUNT_DEBUG remove_proc_subtree("ipsec_saraw", PROC_NET); #endif remove_proc_subtree("ipsec_tncfg", PROC_NET); remove_proc_subtree("ipsec_version", PROC_NET); remove_proc_subtree("ipsec", PROC_NET); } libreswan-3.32/linux/net/ipsec/ipsec_radij.c000066400000000000000000000367721365625662500211360ustar00rootroot00000000000000/* * Interface between the IPSEC code and the radix (radij) tree code * Copyright (C) 1996, 1997 John Ioannidis. * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. * Copyright (C) 2005 Michael Richardson * Copyright (C) 2006-2007 Michael Richardson * Copyright (C) 2006-2008 Paul Wouters * Copyright (C) 2006-2011 Bart Trojanowski * Copyright (C) 2009-2012 David McCullough * Copyright (C) 2012 Paul Wouters * Copyright (C) 2013 David McCullough * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38) && \ !defined(AUTOCONF_INCLUDED) #include #endif #include /* printk() */ #include "libreswan/ipsec_param.h" #include /* kmalloc() */ #include /* error codes */ #include /* size_t */ #include /* mark_bh */ #include /* struct device, struct net_device_stats and other headers */ #include /* eth_type_trans */ #include /* struct iphdr */ #include #include #include /* *lock* */ #include #include "libreswan/ipsec_eroute.h" #include "libreswan/ipsec_sa.h" #include "libreswan/radij.h" #include "libreswan/ipsec_encap.h" #include "libreswan/radij.h" #include "libreswan/ipsec_encap.h" #include "libreswan/ipsec_radij.h" #include "libreswan/ipsec_tunnel.h" /* struct ipsecpriv */ #include "libreswan/ipsec_xform.h" #include #include #include "libreswan/ipsec_proto.h" struct radij_node_head *rnh = NULL; DEFINE_SPINLOCK(eroute_lock); int ipsec_radijinit(void) { maj_keylen = sizeof(struct sockaddr_encap); rj_init(); if (rj_inithead((void **)&rnh, /*16*/ offsetof(struct sockaddr_encap, sen_type) * sizeof(__u8)) == 0) /* 16 is bit offset of sen_type */ return -1; return 0; } int ipsec_radijcleanup(void) { int error = 0; spin_lock_bh(&eroute_lock); error = radijcleanup(); spin_unlock_bh(&eroute_lock); return error; } int ipsec_cleareroutes(void) { int error; spin_lock_bh(&eroute_lock); error = radijcleartree(); spin_unlock_bh(&eroute_lock); return error; } int ipsec_breakroute(struct sockaddr_encap *eaddr, struct sockaddr_encap *emask, struct sk_buff **first, struct sk_buff **last) { struct eroute *ro; struct radij_node *rn; int error; if (debug_eroute) { char buf1[SUBNETTOA_BUF], buf2[SUBNETTOA_BUF]; subnettoa(eaddr->sen_ip_src, emask->sen_ip_src, 0, buf1, sizeof(buf1)); subnettoa(eaddr->sen_ip_dst, emask->sen_ip_dst, 0, buf2, sizeof(buf2)); KLIPS_PRINT(debug_eroute, "klips_debug:ipsec_breakroute: " "attempting to delete eroute for %s:%d->%s:%d %d\n", buf1, ntohs(eaddr->sen_sport), buf2, ntohs(eaddr->sen_dport), eaddr->sen_proto); } spin_lock_bh(&eroute_lock); if ((error = rj_delete(eaddr, emask, rnh, &rn)) != 0) { spin_unlock_bh(&eroute_lock); KLIPS_PRINT(debug_eroute, "klips_debug:ipsec_breakroute: " "node not found, eroute delete failed.\n"); return error; } spin_unlock_bh(&eroute_lock); ro = (struct eroute *)rn; KLIPS_PRINT(debug_eroute, "klips_debug:ipsec_breakroute: " "deleted eroute=0p%p, ident=0p%p->0p%p, first=0p%p, last=0p%p\n", ro, ro->er_ident_s.data, ro->er_ident_d.data, ro->er_first, ro->er_last); if (ro->er_ident_s.data != NULL) kfree(ro->er_ident_s.data); if (ro->er_ident_d.data != NULL) kfree(ro->er_ident_d.data); if (ro->er_first != NULL) { #if 0 struct net_device_stats *stats = &(netdev_to_ipsecpriv(dev)->mystats); stats->tx_dropped--; #endif *first = ro->er_first; } if (ro->er_last != NULL) { #if 0 struct net_device_stats *stats = &(netdev_to_ipsecpriv(dev)->mystats); stats->tx_dropped--; #endif *last = ro->er_last; } if (rn->rj_flags & (RJF_ACTIVE | RJF_ROOT)) panic("ipsec_breakroute RMT_DELEROUTE root or active node\n"); memset((caddr_t)rn, 0, sizeof(struct eroute)); kfree(rn); return 0; } int ipsec_makeroute(struct sockaddr_encap *eaddr, struct sockaddr_encap *emask, ip_said said, uint32_t pid, struct sk_buff *skb, struct ident *ident_s, struct ident *ident_d) { struct eroute *retrt; int error; char sa[SATOT_BUF]; size_t sa_len; if (debug_eroute) { { char buf1[SUBNETTOA_BUF], buf2[SUBNETTOA_BUF]; if (eaddr->sen_type == SENT_IP6) { subnet6toa(&eaddr->sen_ip6_src, &emask->sen_ip6_src, 0, buf1, sizeof(buf1)); subnet6toa(&eaddr->sen_ip6_dst, &emask->sen_ip6_dst, 0, buf2, sizeof(buf2)); } else { subnettoa(eaddr->sen_ip_src, emask->sen_ip_src, 0, buf1, sizeof(buf1)); subnettoa(eaddr->sen_ip_dst, emask->sen_ip_dst, 0, buf2, sizeof(buf2)); } sa_len = KLIPS_SATOT(debug_eroute, &said, 0, sa, sizeof(sa)); KLIPS_PRINT(debug_eroute, "klips_debug:ipsec_makeroute: " "attempting to allocate %zu bytes to insert eroute for %s->%s, SA: %s, PID:%d, skb=0p%p, ident:%s->%s\n", sizeof(struct eroute), buf1, buf2, sa_len ? sa : " (error)", pid, skb, (ident_s ? (ident_s->data ? ident_s->data : "NULL") : "NULL"), (ident_d ? (ident_d->data ? ident_d->data : "NULL") : "NULL")); } { char buf1[sizeof(struct sockaddr_encap) * 2 + 1], buf2[sizeof(struct sockaddr_encap) * 2 + 1]; int i; unsigned char *b1 = buf1, *b2 = buf2, *ea = (unsigned char *)eaddr, *em = (unsigned char *)emask; for (i = 0; i < sizeof(struct sockaddr_encap); i++) { sprintf(b1, "%02x", ea[i]); sprintf(b2, "%02x", em[i]); b1 += 2; b2 += 2; } KLIPS_PRINT(debug_eroute, "klips_debug:ipsec_makeroute: %s / %s\n", buf1, buf2); } } retrt = (struct eroute *)kmalloc(sizeof(struct eroute), GFP_ATOMIC); if (retrt == NULL) { printk("klips_error:ipsec_makeroute: " "not able to allocate kernel memory"); return -ENOMEM; } memset((caddr_t)retrt, 0, sizeof(struct eroute)); retrt->er_eaddr = *eaddr; retrt->er_emask = *emask; retrt->er_said = said; retrt->er_pid = pid; retrt->er_count = 0; retrt->er_lasttime = jiffies / HZ; { /* this is because gcc 3. doesn't like cast's as lvalues */ struct rjtentry *rje = (struct rjtentry *)&(retrt->er_rjt); caddr_t er = (caddr_t)&(retrt->er_eaddr); rje->rd_nodes->rj_key = er; } if (ident_s && ident_s->type != SADB_IDENTTYPE_RESERVED) { int data_len = ident_s->len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident); retrt->er_ident_s.type = ident_s->type; retrt->er_ident_s.id = ident_s->id; retrt->er_ident_s.len = ident_s->len; if (data_len) { KLIPS_PRINT(debug_eroute, "klips_debug:ipsec_makeroute: " "attempting to allocate %u bytes for ident_s.\n", data_len); if (!(retrt->er_ident_s.data = kmalloc(data_len, GFP_KERNEL))) { kfree(retrt); printk("klips_error:ipsec_makeroute: not able to allocate kernel memory (%d)\n", data_len); return ENOMEM; } memcpy(retrt->er_ident_s.data, ident_s->data, data_len); } else { retrt->er_ident_s.data = NULL; } } if (ident_d && ident_d->type != SADB_IDENTTYPE_RESERVED) { int data_len = ident_d->len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident); retrt->er_ident_d.type = ident_d->type; retrt->er_ident_d.id = ident_d->id; retrt->er_ident_d.len = ident_d->len; if (data_len) { KLIPS_PRINT(debug_eroute, "klips_debug:ipsec_makeroute: " "attempting to allocate %u bytes for ident_d.\n", data_len); if (!(retrt->er_ident_d.data = kmalloc(data_len, GFP_KERNEL))) { if (retrt->er_ident_s.data) kfree(retrt->er_ident_s.data); kfree(retrt); printk("klips_error:ipsec_makeroute: not able to allocate kernel memory (%d)\n", data_len); return ENOMEM; } memcpy(retrt->er_ident_d.data, ident_d->data, data_len); } else { retrt->er_ident_d.data = NULL; } } retrt->er_first = skb; retrt->er_last = NULL; KLIPS_PRINT(debug_eroute, "klips_debug:ipsec_makeroute: " "calling rj_addroute now\n"); spin_lock_bh(&eroute_lock); error = rj_addroute(&(retrt->er_eaddr), &(retrt->er_emask), rnh, retrt->er_rjt.rd_nodes); spin_unlock_bh(&eroute_lock); if (error) { sa_len = KLIPS_SATOT(debug_eroute, &said, 0, sa, sizeof(sa)); KLIPS_PRINT(debug_eroute, "klips_debug:ipsec_makeroute: " "rj_addroute not able to insert eroute for SA:%s (error:%d)\n", sa_len ? sa : " (error)", error); if (retrt->er_ident_s.data) kfree(retrt->er_ident_s.data); if (retrt->er_ident_d.data) kfree(retrt->er_ident_d.data); kfree(retrt); return error; } if (debug_eroute) { char buf1[SUBNETTOA_BUF], buf2[SUBNETTOA_BUF]; if (rd_key(&retrt->er_rjt)->sen_type == SENT_IP6) { subnet6toa(&rd_key(&retrt->er_rjt)->sen_ip6_src, &rd_mask(&retrt->er_rjt)->sen_ip6_src, 0, buf1, sizeof(buf1)); subnet6toa(&rd_key(&retrt->er_rjt)->sen_ip6_dst, &rd_mask(&retrt->er_rjt)->sen_ip6_dst, 0, buf2, sizeof(buf2)); } else { subnettoa(rd_key(&retrt->er_rjt)->sen_ip_src, rd_mask(&retrt->er_rjt)->sen_ip_src, 0, buf1, sizeof(buf1)); subnettoa(rd_key(&retrt->er_rjt)->sen_ip_dst, rd_mask(&retrt->er_rjt)->sen_ip_dst, 0, buf2, sizeof(buf2)); } sa_len = KLIPS_SATOT(debug_eroute, &retrt->er_said, 0, sa, sizeof(sa)); KLIPS_PRINT(debug_eroute, "klips_debug:ipsec_makeroute: " "pid=%05d " "count=%10d " "lasttime=%6d " "%-18s -> %-18s => %s\n", retrt->er_pid, retrt->er_count, (int)(ipsec_jiffieshz_elapsed(jiffies / HZ, retrt->er_lasttime)), buf1, buf2, sa_len ? sa : " (error)"); } KLIPS_PRINT(debug_eroute, "klips_debug:ipsec_makeroute: " "succeeded.\n"); return 0; } struct eroute *ipsec_findroute(struct sockaddr_encap *eaddr) { struct radij_node *rn; char buf1[ADDRTOA_BUF], buf2[ADDRTOA_BUF]; if (debug_radij & DB_RJ_FINDROUTE) { unsigned short *sp, *dp; unsigned char *pp, *sb, *eb; if (eaddr->sen_type == SENT_IP6) { inet_addrtot(AF_INET6, &eaddr->sen_ip6_src, 0, buf1, sizeof(buf1)); inet_addrtot(AF_INET6, &eaddr->sen_ip6_dst, 0, buf2, sizeof(buf2)); sp = &eaddr->sen_sport6; dp = &eaddr->sen_dport6; pp = &eaddr->sen_proto6; sb = "["; eb = "]"; } else { addrtoa(eaddr->sen_ip_src, 0, buf1, sizeof(buf1)); addrtoa(eaddr->sen_ip_dst, 0, buf2, sizeof(buf2)); sp = &eaddr->sen_sport; dp = &eaddr->sen_dport; pp = &eaddr->sen_proto; sb = eb = ""; } KLIPS_PRINT(debug_eroute, "klips_debug:ipsec_findroute: " "%s%s%s:%d->%s%s%s:%d %d\n", sb, buf1, eb, ntohs(*sp), sb, buf2, eb, ntohs(*dp), *pp); } rn = rj_match((caddr_t)eaddr, rnh); if (rn) { if (debug_eroute && sysctl_ipsec_debug_verbose) sin_addrtot(&((struct eroute*)rn)->er_said.dst.u, 0, buf1, sizeof(buf1)); KLIPS_PRINT(debug_eroute && sysctl_ipsec_debug_verbose, "klips_debug:ipsec_findroute: " "found, points to proto=%d, spi=%x, dst=%s.\n", ((struct eroute*)rn)->er_said.proto, ntohl(((struct eroute*)rn)->er_said.spi), buf1); } return (struct eroute *)rn; } #ifdef CONFIG_PROC_FS /* * ipsec_rj_walker_show: print one line of eroute table output. */ int ipsec_rj_walker_show(struct radij_node *rn, void *arg) { struct eroute *ro = (struct eroute *)rn; struct rjtentry *rd = (struct rjtentry *)rn; struct seq_file *seq = arg; char buf1[SUBNETTOA_BUF], buf2[SUBNETTOA_BUF]; char buf3[16]; char sa[SATOT_BUF]; size_t sa_len, buf_len; struct sockaddr_encap *key, *mask; KLIPS_PRINT(debug_radij, "klips_debug:ipsec_rj_walker_show: rn=%p, arg=%p\n", rn, arg); if (rn->rj_b >= 0) return 0; key = rd_key(rd); mask = rd_mask(rd); if (key == NULL || mask == NULL) return 0; if (key->sen_type == SENT_IP6) { if (key->sen_sport6 != 0) { *buf1 = '['; buf_len = subnet6toa(&key->sen_ip6_src, &mask->sen_ip6_src, 0, buf1 + 1, sizeof(buf1)); buf1[buf_len - 1] = ']'; sprintf(buf1 + buf_len, ":%d", ntohs(key->sen_sport6)); } else { buf_len = subnet6toa(&key->sen_ip6_src, &mask->sen_ip6_src, 0, buf1, sizeof(buf1)); } if (key->sen_dport6 != 0) { *buf1 = '['; buf_len = subnet6toa(&key->sen_ip6_dst, &mask->sen_ip6_dst, 0, buf2 + 1, sizeof(buf2)); buf1[buf_len - 1] = ']'; sprintf(buf2 + buf_len, ":%d", ntohs(key->sen_dport6)); } else { buf_len = subnet6toa(&key->sen_ip6_dst, &mask->sen_ip6_dst, 0, buf2, sizeof(buf2)); } } else if (key->sen_type == SENT_IP4) { buf_len = subnettoa(key->sen_ip_src, mask->sen_ip_src, 0, buf1, sizeof(buf1)); if (key->sen_sport != 0) sprintf(buf1 + buf_len - 1, ":%d", ntohs(key->sen_sport)); buf_len = subnettoa(key->sen_ip_dst, mask->sen_ip_dst, 0, buf2, sizeof(buf2)); if (key->sen_dport != 0) sprintf(buf2 + buf_len - 1, ":%d", ntohs(key->sen_dport)); } else { return 0; } buf3[0] = '\0'; if (key->sen_proto != 0) sprintf(buf3, ":%d", key->sen_proto); sa_len = KLIPS_SATOT(1, &ro->er_said, 'x', sa, sizeof(sa)); seq_printf(seq, "%-10d " "%-18s -> %-18s => %s%s\n", ro->er_count, buf1, buf2, sa_len ? sa : " (error)", buf3); return 0; } #endif /* CONFIG_PROC_FS */ int ipsec_rj_walker_delete(struct radij_node *rn, void *w0) { struct eroute *ro; struct rjtentry *rd = (struct rjtentry *)rn; struct radij_node *rn2; int error; struct sockaddr_encap *key, *mask; key = rd_key(rd); mask = rd_mask(rd); if (!key || !mask) return -ENODATA; if (debug_radij) { char buf1[SUBNETTOA_BUF], buf2[SUBNETTOA_BUF]; if (key->sen_type == SENT_IP6) { subnet6toa(&key->sen_ip6_src, &mask->sen_ip6_src, 0, buf1, sizeof(buf1)); subnet6toa(&key->sen_ip6_dst, &mask->sen_ip6_dst, 0, buf2, sizeof(buf2)); } else { subnettoa(key->sen_ip_src, mask->sen_ip_src, 0, buf1, sizeof(buf1)); subnettoa(key->sen_ip_dst, mask->sen_ip_dst, 0, buf2, sizeof(buf2)); } KLIPS_PRINT(debug_radij, "klips_debug:ipsec_rj_walker_delete: " "deleting: %s -> %s\n", buf1, buf2); } if ((error = rj_delete(key, mask, rnh, &rn2))) { KLIPS_PRINT(debug_radij, "klips_debug:ipsec_rj_walker_delete: " "rj_delete failed with error=%d.\n", error); return error; } if (rn2 != rn) { printk("klips_debug:ipsec_rj_walker_delete: " "tried to delete a different node?!? This should never happen!\n"); } ro = (struct eroute *)rn; if (ro->er_ident_s.data) kfree(ro->er_ident_s.data); if (ro->er_ident_d.data) kfree(ro->er_ident_d.data); memset((caddr_t)rn, 0, sizeof(struct eroute)); kfree(rn); return 0; } libreswan-3.32/linux/net/ipsec/ipsec_rcv.c000066400000000000000000002116471365625662500206330ustar00rootroot00000000000000/* * receive code * Copyright (C) 1996, 1997 John Ioannidis. * Copyright (C) 1998-2003 Richard Guy Briggs. * Copyright (C) 2004-2007 Michael Richardson * Copyright (C) 2007-2008 Paul Wouters * Copyright (C) 2010 David McCullough * Copyright (C) 2011 Bart Trojanowski * Copyright (C) 2012,2015 Paul Wouters * Copyright (C) 2011-2012 David McCullough * * OCF/receive state machine written by * David McCullough * Copyright (C) 2004-2005 Intel Corporation. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38) && \ !defined(AUTOCONF_INCLUDED) #include #endif #define __NO_VERSION__ #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) && LINUX_VERSION_CODE >= \ KERNEL_VERSION(2, 4, 26) # include #endif #include /* printk() */ #include "libreswan/ipsec_param.h" #include /* kmalloc() */ #include /* error codes */ #include /* size_t */ #include /* mark_bh */ #include /* struct device, and other headers */ #include /* eth_type_trans */ #include /* struct iphdr */ #include #include #ifdef NET_26 # include #endif #include #include #include /* *lock* */ #ifdef NEED_SPINLOCK_TYPES # include #endif #include #include "libreswan/ipsec_kversion.h" #include "libreswan/radij.h" #include "libreswan/ipsec_encap.h" #include "libreswan/ipsec_sa.h" #include "libreswan/ipsec_radij.h" #include "libreswan/ipsec_xform.h" #include "libreswan/ipsec_tunnel.h" #include "libreswan/ipsec_mast.h" #include "libreswan/ipsec_rcv.h" #include "libreswan/ipsec_auth.h" #include "libreswan/ipsec_esp.h" #ifdef CONFIG_KLIPS_AH #include "libreswan/ipsec_ah.h" #endif /* CONFIG_KLIPS_AH */ #ifdef CONFIG_KLIPS_IPCOMP #include "libreswan/ipsec_ipcomp.h" #endif /* CONFIG_KLIPS_COMP */ #include #include #include "libreswan/ipsec_proto.h" #include "libreswan/ipsec_alg.h" #ifdef CONFIG_KLIPS_OCF #include "ipsec_ocf.h" #endif #ifdef CONFIG_IPSEC_NAT_TRAVERSAL #include #endif /* This is a private use protocol, and AT&T should be ashamed. They should have * used protocol # 59, which is "no next header" instead of 0xFE. */ #ifndef IPPROTO_ATT_HEARTBEAT #define IPPROTO_ATT_HEARTBEAT 0xFE #endif /* management of buffers */ static struct ipsec_rcv_state *ipsec_rcv_state_new(void); static void ipsec_rcv_state_delete(struct ipsec_rcv_state *irs); /* * Check-replay-window routine, adapted from the original * by J. Hughes, from draft-ietf-ipsec-esp-des-md5-03.txt * * This is a routine that implements a 64 packet window. This is intend- * ed on being an implementation sample. */ int ipsec_replaywin_override = -1; module_param(ipsec_replaywin_override, int, 0644); MODULE_PARM_DESC(ipsec_replaywin_override, "override replay window (-1=no change, 0=disable, N=override value"); DEBUG_NO_STATIC int ipsec_checkreplaywindow(struct ipsec_sa *ipsp, __u32 seq) { __u32 diff; if (ipsec_replaywin_override >= 0) ipsp->ips_replaywin = ipsec_replaywin_override; if (ipsp->ips_replaywin == 0) /* replay shut off */ return 1; if (seq == 0) return 0; /* first == 0 or wrapped */ /* new larger sequence number */ if (seq > ipsp->ips_replaywin_lastseq) return 1; /* larger is good */ diff = ipsp->ips_replaywin_lastseq - seq; /* too old or wrapped */ /* if wrapped, kill off SA? */ if (diff >= ipsp->ips_replaywin) return 0; /* this packet already seen */ if (ipsp->ips_replaywin_bitmap & (1 << diff)) return 0; return 1; /* out of order but good */ } DEBUG_NO_STATIC int ipsec_updatereplaywindow(struct ipsec_sa *ipsp, __u32 seq) { __u32 diff; if (ipsec_replaywin_override >= 0) ipsp->ips_replaywin = ipsec_replaywin_override; if (ipsp->ips_replaywin == 0) /* replay shut off */ return 1; if (seq == 0) return 0; /* first == 0 or wrapped */ /* new larger sequence number */ if (seq > ipsp->ips_replaywin_lastseq) { diff = seq - ipsp->ips_replaywin_lastseq; /* In win, set bit for this pkt */ if (diff < ipsp->ips_replaywin) ipsp->ips_replaywin_bitmap = (ipsp->ips_replaywin_bitmap << diff) | 1; else /* This packet has way larger seq num */ ipsp->ips_replaywin_bitmap = 1; if (seq - ipsp->ips_replaywin_lastseq - 1 > ipsp->ips_replaywin_maxdiff) { ipsp->ips_replaywin_maxdiff = seq - ipsp-> ips_replaywin_lastseq - 1; } ipsp->ips_replaywin_lastseq = seq; return 1; /* larger is good */ } diff = ipsp->ips_replaywin_lastseq - seq; /* too old or wrapped */ /* if wrapped, kill off SA? */ if (diff >= ipsp->ips_replaywin) { /* if (seq < 0.25*max && ipsp->ips_replaywin_lastseq > 0.75*max) { ipsec_sa_delchain(ipsp); } */ return 0; } /* this packet already seen */ if (ipsp->ips_replaywin_bitmap & (1 << diff)) return 0; ipsp->ips_replaywin_bitmap |= (1 << diff); /* mark as seen */ return 1; /* out of order but good */ } #ifdef CONFIG_KLIPS_AUTH_HMAC_MD5 struct auth_alg ipsec_rcv_md5[] = { { osMD5Init, osMD5Update, osMD5Final, AHMD596_ALEN } }; #endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ #ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1 struct auth_alg ipsec_rcv_sha1[] = { { SHA1Init, SHA1Update, SHA1Final, AHSHA196_ALEN } }; #endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ static inline void ipsec_rcv_redodebug(struct ipsec_rcv_state *irs) { if (lsw_ip_hdr_version(irs) == 4) { inet_addrtot(AF_INET, &lsw_ip4_hdr(irs)->saddr, 0, irs->ipsaddr_txt, sizeof(irs->ipsaddr_txt)); inet_addrtot(AF_INET, &lsw_ip4_hdr(irs)->daddr, 0, irs->ipdaddr_txt, sizeof(irs->ipdaddr_txt)); } else if (lsw_ip_hdr_version(irs) == 6) { inet_addrtot(AF_INET6, &lsw_ip6_hdr(irs)->saddr, 0, irs->ipsaddr_txt, sizeof(irs->ipsaddr_txt)); inet_addrtot(AF_INET6, &lsw_ip6_hdr(irs)->daddr, 0, irs->ipdaddr_txt, sizeof(irs->ipdaddr_txt)); } else { snprintf(irs->ipsaddr_txt, sizeof(irs->ipsaddr_txt), ""); snprintf(irs->ipdaddr_txt, sizeof(irs->ipdaddr_txt), ""); } } /* NOTE: may return a pointer to a static buffer */ DEBUG_NO_STATIC char *ipsec_rcv_err(int err) { static char tmp[32]; switch ((int) err) { case IPSEC_RCV_PENDING: return "IPSEC_RCV_PENDING"; case IPSEC_RCV_LASTPROTO: return "IPSEC_RCV_LASTPROTO"; case IPSEC_RCV_OK: return "IPSEC_RCV_OK"; case IPSEC_RCV_BADPROTO: return "IPSEC_RCV_BADPROTO"; case IPSEC_RCV_BADLEN: return "IPSEC_RCV_BADLEN"; case IPSEC_RCV_ESP_BADALG: return "IPSEC_RCV_ESP_BADALG"; case IPSEC_RCV_3DES_BADBLOCKING: return "IPSEC_RCV_3DES_BADBLOCKING"; case IPSEC_RCV_ESP_DECAPFAIL: return "IPSEC_RCV_ESP_DECAPFAIL"; case IPSEC_RCV_DECAPFAIL: return "IPSEC_RCV_DECAPFAIL"; case IPSEC_RCV_SAIDNOTFOUND: return "IPSEC_RCV_SAIDNOTFOUND"; case IPSEC_RCV_IPCOMPALONE: return "IPSEC_RCV_IPCOMPALONE"; case IPSEC_RCV_IPCOMPFAILED: return "IPSEC_RCV_IPCOMPFAILED"; case IPSEC_RCV_SAIDNOTLIVE: return "IPSEC_RCV_SAIDNOTLIVE"; case IPSEC_RCV_FAILEDINBOUND: return "IPSEC_RCV_FAILEDINBOUND"; case IPSEC_RCV_LIFETIMEFAILED: return "IPSEC_RCV_LIFETIMEFAILED"; case IPSEC_RCV_BADAUTH: return "IPSEC_RCV_BADAUTH"; case IPSEC_RCV_REPLAYFAILED: return "IPSEC_RCV_REPLAYFAILED"; case IPSEC_RCV_AUTHFAILED: return "IPSEC_RCV_AUTHFAILED"; case IPSEC_RCV_REPLAYROLLED: return "IPSEC_RCV_REPLAYROLLED"; case IPSEC_RCV_BAD_DECRYPT: return "IPSEC_RCV_BAD_DECRYPT"; case IPSEC_RCV_REALLYBAD: return "IPSEC_RCV_REALLYBAD"; case IPSEC_RCV_ERRMEMALLOC: return "IPSEC_RCV_ERRMEMALLOC"; } snprintf(tmp, sizeof(tmp), "%d", err); return tmp; } /* * here is a state machine to handle receiving ipsec packets. * basically we keep getting re-entered until processing is * complete. For the simple case we step down the states and finish. * each state is ideally some logical part of the process. If a state * can pend (ie., require async processing to complete), then this * should be the part of last action before it returns IPSEC_RCV_PENDING * * Any particular action may alter the next_state in irs to move us to * a state other than the preferred "next_state", but this is the * exception and is highlighted when it is done. * * prototypes for state action */ static enum ipsec_rcv_value ipsec_rcv_init(struct ipsec_rcv_state *irs); static enum ipsec_rcv_value ipsec_rcv_decap_init(struct ipsec_rcv_state *irs); static enum ipsec_rcv_value ipsec_rcv_decap_lookup(struct ipsec_rcv_state *irs); static enum ipsec_rcv_value ipsec_rcv_auth_init(struct ipsec_rcv_state *irs); static enum ipsec_rcv_value ipsec_rcv_auth_decap(struct ipsec_rcv_state *irs); static enum ipsec_rcv_value ipsec_rcv_auth_calc(struct ipsec_rcv_state *irs); static enum ipsec_rcv_value ipsec_rcv_auth_chk(struct ipsec_rcv_state *irs); static enum ipsec_rcv_value ipsec_rcv_decrypt(struct ipsec_rcv_state *irs); static enum ipsec_rcv_value ipsec_rcv_decap_cont(struct ipsec_rcv_state *irs); static enum ipsec_rcv_value ipsec_rcv_cleanup(struct ipsec_rcv_state *irs); static enum ipsec_rcv_value ipsec_rcv_complete(struct ipsec_rcv_state *irs); /* * the state table and each action */ static struct { enum ipsec_rcv_value (*action)(struct ipsec_rcv_state *irs); int next_state; } rcv_state_table[] = { [IPSEC_RSM_INIT] = { ipsec_rcv_init, IPSEC_RSM_DECAP_INIT }, [IPSEC_RSM_DECAP_INIT] = { ipsec_rcv_decap_init, IPSEC_RSM_DECAP_LOOKUP }, [IPSEC_RSM_DECAP_LOOKUP] = { ipsec_rcv_decap_lookup, IPSEC_RSM_AUTH_INIT }, [IPSEC_RSM_AUTH_INIT] = { ipsec_rcv_auth_init, IPSEC_RSM_AUTH_DECAP }, [IPSEC_RSM_AUTH_DECAP] = { ipsec_rcv_auth_decap, IPSEC_RSM_AUTH_CALC }, [IPSEC_RSM_AUTH_CALC] = { ipsec_rcv_auth_calc, IPSEC_RSM_AUTH_CHK }, [IPSEC_RSM_AUTH_CHK] = { ipsec_rcv_auth_chk, IPSEC_RSM_DECRYPT }, [IPSEC_RSM_DECRYPT] = { ipsec_rcv_decrypt, IPSEC_RSM_DECAP_CONT }, [IPSEC_RSM_DECAP_CONT] = { ipsec_rcv_decap_cont, IPSEC_RSM_CLEANUP }, [IPSEC_RSM_CLEANUP] = { ipsec_rcv_cleanup, IPSEC_RSM_COMPLETE }, [IPSEC_RSM_COMPLETE] = { ipsec_rcv_complete, IPSEC_RSM_DONE }, [IPSEC_RSM_DONE] = { NULL, IPSEC_RSM_DONE }, }; struct sk_buff *ipsec_rcv_unclone(struct sk_buff *skb, struct ipsec_rcv_state *irs) { /* if skb was cloned (most likely due to a packet sniffer such as tcpdump being momentarily attached to the interface), make a copy of our own to modify */ if (skb_cloned(skb)) { /* include any mac header while copying.. */ if (skb_headroom(skb) < irs->hard_header_len) { printk(KERN_WARNING "klips_error:ipsec_rcv_unclone: " "tried to skb_push hhlen=%d, %d available. This should never happen, please report(1).\n", irs->hard_header_len, skb_headroom(skb)); return NULL; } skb_push(skb, irs->hard_header_len); if (skb_cow(skb, skb_headroom(skb)) != 0) return NULL; if (skb->len < irs->hard_header_len) { printk(KERN_WARNING "klips_error:ipsec_rcv_unclone: " "tried to skb_pull hhlen=%d, %d available. This should never happen, please report(2).\n", irs->hard_header_len, skb->len); return NULL; } skb_pull(skb, irs->hard_header_len); } return skb; } #if !defined(NET_26) && defined(CONFIG_IPSEC_NAT_TRAVERSAL) /* * decapsulate a UDP encapsulated ESP packet */ struct sk_buff *ipsec_rcv_natt_decap(struct sk_buff *skb, struct ipsec_rcv_state *irs, int *udp_decap_ret_p) { *udp_decap_ret_p = 0; if (skb->sk && ip_hdr(skb) && ip_hdr(skb)->protocol == IPPROTO_UDP) { /** * Packet comes from udp_queue_rcv_skb so it is already defrag, * checksum verified, ... (ie safe to use) * * If the packet is not for us, return -1 and udp_queue_rcv_skb * will continue to handle it (do not kfree skb !!). */ #ifndef UDP_OPT_IN_SOCK struct udp_opt { __u32 esp_in_udp; }; struct udp_opt *tp = (struct udp_opt *)&(skb->sk->tp_pinfo.af_tcp); #else struct udp_opt *tp = &(skb->sk->tp_pinfo.af_udp); #endif struct iphdr *ip = ip_hdr(skb); struct udphdr *udp = (struct udphdr *)((__u32 *)ip + ip->ihl); __u8 *udpdata = (__u8 *)udp + sizeof(struct udphdr); __u32 *udpdata32 = (__u32 *)udpdata; irs->natt_sport = ntohs(udp->source); irs->natt_dport = ntohs(udp->dest); KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_natt_decap: " "suspected ESPinUDP packet (NAT-Traversal) [%d].\n", tp->esp_in_udp); KLIPS_IP_PRINT(debug_rcv, ip); if (udpdata < skb->tail) { unsigned int len = skb->tail - udpdata; if ((len == 1) && (udpdata[0] == 0xff)) { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_natt_decap: " /* not IPv6 compliant message */ "NAT-keepalive from %pI4.\n", &ip->saddr); *udp_decap_ret_p = 0; return NULL; } else if (tp->esp_in_udp == ESPINUDP_WITH_NON_IKE && len > 2 * sizeof(__u32) + sizeof(struct esphdr) && udpdata32[0] == 0 && udpdata32[1] == 0) { /* ESP Packet with Non-IKE header */ KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_natt_decap: " "ESPinUDP pkt with Non-IKE - spi=0x%x\n", ntohl(udpdata32[2])); irs->natt_type = ESPINUDP_WITH_NON_IKE; irs->natt_len = sizeof(struct udphdr) + (2 * sizeof(__u32)); } else if (tp->esp_in_udp == ESPINUDP_WITH_NON_ESP && len > sizeof(struct esphdr) && udpdata32[0] != 0) { /* ESP Packet without Non-ESP header */ irs->natt_type = ESPINUDP_WITH_NON_ESP; irs->natt_len = sizeof(struct udphdr); KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_natt_decap: " "ESPinUDP pkt without Non-ESP - spi=0x%x\n", ntohl(udpdata32[0])); } else { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_natt_decap: " "IKE packet - not handled here\n"); *udp_decap_ret_p = -1; return NULL; } } else { return NULL; } } return skb; } #endif void ipsec_rcv_setoutif(struct ipsec_rcv_state *irs) { struct sk_buff *skb = irs->skb; if (skb != NULL && irs->ipsp->ips_out) { if (skb->dev != irs->ipsp->ips_out) { KLIPS_PRINT(debug_rcv, "changing originating interface from %s to %s\n", skb->dev->name, irs->ipsp->ips_out->name); } skb->dev = irs->ipsp->ips_out; #ifdef USE_NETDEV_OPS if (skb->dev && skb->dev->netdev_ops->ndo_get_stats) { struct net_device_stats *stats = skb->dev->netdev_ops->ndo_get_stats(skb->dev); irs->stats = stats; } #else if (skb->dev && skb->dev->get_stats) { struct net_device_stats *stats = skb->dev->get_stats( skb->dev); irs->stats = stats; } #endif } } static enum ipsec_rcv_value ipsec_rcv_decap_ipip(struct ipsec_rcv_state *irs) { struct ipsec_sa *ipsp; struct ipsec_sa *ipsnext = NULL; struct sk_buff *skb; struct iphdr *ipp = lsw_ip4_hdr(irs); #ifdef CONFIG_KLIPS_IPV6 struct ipv6hdr *ipp6 = lsw_ip6_hdr(irs); #endif /* CONFIG_KLIPS_IPV6 */ int failed_inbound_check = 0; enum ipsec_rcv_value result = IPSEC_RCV_DECAPFAIL; ipsp = irs->ipsp; skb = irs->skb; irs->sa_len = KLIPS_SATOT(debug_rcv, &irs->said, 0, irs->sa, sizeof(irs->sa)); if (ipp->version == 4 && ipp->protocol != IPPROTO_IPIP && ipp->protocol != IPPROTO_IPV6 && ipp->protocol != IPPROTO_ATT_HEARTBEAT) { /* AT&T heartbeats to SIG/GIG */ KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_decap_ipip: " "SA:%s, Hey! How did this get through? Dropped.\n", irs->sa_len ? irs->sa : " (error)"); if (irs->stats) irs->stats->rx_dropped++; goto rcvleave; } if (sysctl_ipsec_inbound_policy_check) { struct sockaddr_in *psin = NULL; struct sockaddr_in6 *psin6 = NULL; if ((ipsnext = ipsp->ips_next)) { char sa2[SATOT_BUF]; size_t sa_len2; sa_len2 = KLIPS_SATOT(debug_rcv, &ipsnext->ips_said, 0, sa2, sizeof(sa2)); KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_decap_ipip: " "unexpected SA:%s after IPIP SA:%s\n", sa_len2 ? sa2 : " (error)", irs->sa_len ? irs->sa : " (error)"); if (irs->stats) irs->stats->rx_dropped++; goto rcvleave; } if (((struct sockaddr_in6*)(ipsp->ips_addr_s))->sin6_family == AF_INET6) psin6 = (struct sockaddr_in6*)(ipsp->ips_addr_s); else if (((struct sockaddr_in*)(ipsp->ips_addr_s))->sin_family == AF_INET) psin = (struct sockaddr_in*)(ipsp->ips_addr_s); if ((psin && ipp->saddr != psin->sin_addr.s_addr) #ifdef CONFIG_KLIPS_IPV6 || (psin6 && memcmp(&ipp6->saddr, &psin6->sin6_addr, sizeof(ipp6->saddr)) != 0) #endif ) { char saddr1[SUBNETTOA_BUF], saddr2[SUBNETTOA_BUF]; *saddr1 = 0; #ifdef CONFIG_KLIPS_IPV6 if (ipp->version == 6) inet_addrtot(AF_INET6, &ipp6->saddr, 0, saddr1, sizeof(saddr1)); else #endif inet_addrtot(AF_INET, &ipp->saddr, 0, saddr1, sizeof(saddr1)); *saddr2 = 0; sin_addrtot(&psin->sin_addr, 0, saddr2, sizeof(saddr2)); KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_decap_ipip: " "SA:%s, src=%s(%s) does match expected %s.\n", irs->sa_len ? irs->sa : " (error)", irs->ipsaddr_txt, saddr1, saddr2); if (irs->stats) irs->stats->rx_dropped++; goto rcvleave; } } ipsec_rcv_setoutif(irs); /* added to support AT&T heartbeats to SIG/GIG */ if ((ipp->version == 4 || ipp->version == 6) && (irs->proto == IPPROTO_IPIP || irs->proto == IPPROTO_IPV6)) { /* * XXX this needs to be locked from when it was first looked * up in the decapsulation loop. Perhaps it is better to put * the IPIP decap inside the loop. */ ipsp->ips_life.ipl_bytes.ipl_count += skb->len; ipsp->ips_life.ipl_bytes.ipl_last = skb->len; if (!ipsp->ips_life.ipl_usetime.ipl_count) ipsp->ips_life.ipl_usetime.ipl_count = jiffies / HZ; ipsp->ips_life.ipl_usetime.ipl_last = jiffies / HZ; ipsp->ips_life.ipl_packets.ipl_count += 1; /* new L3 header is where L4 payload was */ skb_set_network_header(skb, ipsec_skb_offset(skb, skb_transport_header( skb))); /* now setup new L4 payload location */ ipp = (struct iphdr *)skb_network_header(skb); #ifdef CONFIG_KLIPS_IPV6 ipp6 = (struct ipv6hdr *) ipp; if (ipp->version == 6) { IPSEC_FRAG_OFF_DECL(frag_off) unsigned char nexthdr = ipp6->nexthdr; int nexthdroff; nexthdroff = ipsec_ipv6_skip_exthdr(skb, ipsec_skb_offset( skb, ipp6 + 1), &nexthdr, &frag_off); skb_set_transport_header(skb, ipsec_skb_offset(skb, (void*)skb-> data + nexthdroff)); irs->iphlen = nexthdroff - ipsec_skb_offset(skb, ipp6); } else #endif /* CONFIG_KLIPS_IPV6 */ { skb_set_transport_header(skb, ipsec_skb_offset(skb, skb_network_header( skb) + (ipp->ihl << 2))); irs->iphlen = ipp->ihl << 2; } if (skb->len < irs->iphlen) { printk(KERN_WARNING "klips_debug:ipsec_rcv_decap_ipip: " "tried to skb_pull iphlen=%d, %d available. This should never happen, please report(3).\n", irs->iphlen, (int)(skb->len)); goto rcvleave; } /* * we need to pull up by size of the new IP header, * + options, but also by any UDP/ESP encap there might * have been, and this deals with all cases. */ skb_pull(skb, (skb_transport_header(skb) - skb_network_header(skb))); /* remove any saved options that we might have, * since we have a new IP header. */ memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); #if 0 KLIPS_PRINT(debug_rcv, "csum: %d\n", ip_fast_csum((u8 *)ipp, ipp->ihl)); #endif /* re-do any strings for debugging */ irs->iph = (void*)ipp; if (debug_rcv) ipsec_rcv_redodebug(irs); if (lsw_ip_hdr_version(irs) == 6) skb->protocol = htons(ETH_P_IPV6); else skb->protocol = htons(ETH_P_IP); skb->ip_summed = 0; KLIPS_PRINT(debug_rcv & DB_RX_PKTRX, "klips_debug:ipsec_rcv_decap_ipip: " "IPIP tunnel stripped.\n"); KLIPS_IP_PRINT(debug_rcv & DB_RX_PKTRX, ipp); } if (sysctl_ipsec_inbound_policy_check) { /* Note: "xor" (^) logically replaces "not equal" (!=) and "bitwise or" (|) logically replaces "boolean or" (||). This is done to speed up execution by doing only bitwise operations and no branch operations */ if (ipp->version == 4) { if (ip_address_family(&ipsp->ips_flow_s) != AF_INET) failed_inbound_check = 1; else if (ip_address_family(&ipsp->ips_flow_d) != AF_INET) failed_inbound_check = 1; else if (((ipp->saddr & ipsp->ips_mask_s.u.v4.sin_addr.s_addr) ^ ipsp->ips_flow_s.u.v4.sin_addr.s_addr) | ((ipp->daddr & ipsp->ips_mask_d.u.v4.sin_addr.s_addr) ^ ipsp->ips_flow_d.u.v4.sin_addr.s_addr)) failed_inbound_check = 1; } #ifdef CONFIG_KLIPS_IPV6 else if (ipp->version == 6) { /* boilerplate macro for Bad Bits in address */ #define BB(end, i) ((ipp6->end##addr.s6_addr32[i] & \ ipsp->ips_mask_##end.u.v6.sin6_addr.s6_addr32[i]) ^ \ ipsp->ips_flow_##end.u.v6.sin6_addr.s6_addr32[i]) if (ip_address_family(&ipsp->ips_flow_s) != AF_INET6) failed_inbound_check = 1; else if (ip_address_family(&ipsp->ips_flow_d) != AF_INET6) failed_inbound_check = 1; else if (BB(s, 0) | BB(d, 0) | BB(s, 1) | BB(d, 1) | BB(s, 2) | BB(d, 2) | BB(s, 3) | BB(d, 3)) failed_inbound_check = 1; #undef BB } #endif /* CONFIG_KLIPS_IPV6 */ } if (failed_inbound_check) { char sflow_txt[SUBNETTOA_BUF], dflow_txt[SUBNETTOA_BUF]; #ifdef CONFIG_KLIPS_IPV6 if (ipsp->ips_flow_s.u.v6.sin6_family == AF_INET6) { subnet6toa(&ipsp->ips_flow_s.u.v6.sin6_addr, &ipsp->ips_mask_s.u.v6.sin6_addr, 0, sflow_txt, sizeof(sflow_txt)); subnet6toa(&ipsp->ips_flow_d.u.v6.sin6_addr, &ipsp->ips_mask_d.u.v6.sin6_addr, 0, dflow_txt, sizeof(dflow_txt)); } else #endif { subnettoa(ipsp->ips_flow_s.u.v4.sin_addr, ipsp->ips_mask_s.u.v4.sin_addr, 0, sflow_txt, sizeof(sflow_txt)); subnettoa(ipsp->ips_flow_d.u.v4.sin_addr, ipsp->ips_mask_d.u.v4.sin_addr, 0, dflow_txt, sizeof(dflow_txt)); } KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_decap_ipip: " "SA:%s, inner tunnel policy [%s -> %s] does not agree with pkt contents [%s -> %s].\n", irs->sa_len ? irs->sa : " (error)", sflow_txt, dflow_txt, irs->ipsaddr_txt, irs->ipdaddr_txt); if (irs->stats) irs->stats->rx_dropped++; goto rcvleave; } #if 0 if (sysctl_ipsec_inbound_policy_check) { char sflow_txt[SUBNETTOA_BUF], dflow_txt[SUBNETTOA_BUF]; subnettoa(ipsp->ips_flow_s.u.v4.sin_addr, ipsp->ips_mask_s.u.v4.sin_addr, 0, sflow_txt, sizeof(sflow_txt)); subnettoa(ipsp->ips_flow_d.u.v4.sin_addr, ipsp->ips_mask_d.u.v4.sin_addr, 0, dflow_txt, sizeof(dflow_txt)); KLIPS_PRINT(debug_mast, "klips_debug:ipsec_rcv_decap_ipip: " "SA:%s, inner tunnel policy [%s -> %s] agrees with pkt contents [%s -> %s].\n", irs->sa_len ? irs->sa : " (error)", sflow_txt, dflow_txt, irs->ipsaddr_txt, irs->ipdaddr_txt); } #endif #if defined(CONFIG_KLIPS_COMPAT_NAT_NFMARK) #if defined(CONFIG_NETFILTER) skb->nfmark = IPSEC_NFMARK_IS_SAREF_BIT | (skb->nfmark & (~(IPsecSAref2NFmark(IPSEC_SA_REF_MASK)))) | IPsecSAref2NFmark(IPsecSA2SAref(ipsp)); KLIPS_PRINT(debug_rcv & DB_RX_PKTRX, "klips_debug:ipsec_rcv_decap_ipip: " "IPIP SA sets skb->nfmark=0x%x.\n", (unsigned)skb->nfmark); #endif /* CONFIG_NETFILTER */ #endif result = IPSEC_RCV_OK; rcvleave: return result; } /* * get all the initial checking and setup done. None of this can be off * loaded by any currently support hardware * * the following things should be setup when we exit this function. * * irs->stats == stats structure (or NULL) * irs->ipp = IP header. * irs->len = total length of packet * skb->nh.iph = ipp; * skb->h.raw = start of payload * irs->ipsp = NULL. * irs->iphlen = N/A = is recalculated. * irs->ilen = 0; * irs->authlen = 0; * irs->authfuncs = NULL; * irs->skb = the skb; * * proto_funcs should be from ipsec_esp.c, ipsec_ah.c or ipsec_ipcomp.c. * */ static enum ipsec_rcv_value ipsec_rcv_init(struct ipsec_rcv_state *irs) { struct net_device_stats *stats = NULL; /* This device's statistics */ int i; struct sk_buff *skb; KLIPS_PRINT(debug_rcv, "klips_debug: %s(st=%d,nxt=%d)\n", __FUNCTION__, irs->state, irs->next_state); if (irs == NULL) { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_init: NULL irs."); return IPSEC_RCV_REALLYBAD; } skb = irs->skb; if (!skb) { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_init: NULL skb."); return IPSEC_RCV_REALLYBAD; } if (skb->data == NULL) { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_init: " "NULL skb->data passed in, packet is bogus, dropping.\n"); return IPSEC_RCV_REALLYBAD; } /* dev->hard_header_len is unreliable and should not be used */ /* klips26_rcv_encap will have already set hard_header_len for us */ if (irs->hard_header_len == 0) { irs->hard_header_len = skb_mac_header(skb) ? (skb_network_header(skb) - skb_mac_header(skb)) : 0; if ((irs->hard_header_len < 0) || (irs->hard_header_len > skb_headroom(skb))) irs->hard_header_len = 0; } skb = ipsec_rcv_unclone(skb, irs); if (skb == NULL) return IPSEC_RCV_REALLYBAD; /* In Linux >2.4.4, we may have to reassemble fragments. They are not assembled automatically to save TCP from having to copy twice. */ if (skb_is_nonlinear(skb)) { #ifdef HAVE_NEW_SKB_LINEARIZE if (skb_linearize_cow(skb) != 0) #else if (skb_linearize(skb, GFP_ATOMIC) != 0) #endif return IPSEC_RCV_REALLYBAD; } irs->iph = (void *)ip_hdr(skb); #if defined(CONFIG_IPSEC_NAT_TRAVERSAL) && !defined(NET_26) if (irs->natt_len) { /** * Now, we are sure packet is ESPinUDP, and we have a private * copy that has been linearized, remove natt_len bytes * from packet and modify protocol to ESP. */ if (((unsigned char *)skb->data > (unsigned char *)ip_hdr(skb)) && ((unsigned char *)ip_hdr(skb) > (unsigned char *)skb->head)) { unsigned int _len = (unsigned char *)skb->data - (unsigned char *)ip_hdr(skb); KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_init: adjusting skb: skb_push(%u)\n", _len); skb_push(skb, _len); } KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_init: " "removing %d bytes from ESPinUDP packet\n", irs->natt_len); irs->iph = (struct iphdr *)skb->data; irs->iphlen = lsw_ip4_hdr(irs)->ihl << 2; lsw_ip4_hdr(irs)->tot_len = htons(ntohs(lsw_ip4_hdr(irs)->tot_len) - irs->natt_len); if (skb->len < irs->iphlen + irs->natt_len) { printk(KERN_WARNING "klips_error:ipsec_rcv_init: " "ESPinUDP packet is too small (%d < %d+%d). " "This should never happen, please report.\n", (int)(skb->len), irs->iphlen, irs->natt_len); return IPSEC_RCV_REALLYBAD; } /* advance payload pointer to point past the UDP header */ skb->h.raw = skb->h.raw + irs->natt_len; /* modify protocol */ lsw_ip4_hdr(irs)->protocol = IPPROTO_ESP; skb->sk = NULL; KLIPS_IP_PRINT(debug_rcv, ip_hdr(skb)); } #endif if (debug_rcv) ipsec_rcv_redodebug(irs); #ifdef CONFIG_KLIPS_IPV6 if (lsw_ip_hdr_version(irs) == 6) { IPSEC_FRAG_OFF_DECL(frag_off) int nexthdroff; irs->proto = lsw_ip6_hdr(irs)->nexthdr; nexthdroff = ipsec_ipv6_skip_exthdr(irs->skb, ((void *)(lsw_ip6_hdr( irs) + 1)) - (void*)irs->skb->data, &irs->proto, &frag_off); irs->iphlen = nexthdroff - (irs->iph - (void*)irs->skb->data); } else #endif /* CONFIG_KLIPS_IPV6 */ { irs->iphlen = lsw_ip4_hdr(irs)->ihl << 2; irs->proto = lsw_ip4_hdr(irs)->protocol; } KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_init: " "<<< Info -- "); KLIPS_PRINTMORE(debug_rcv && skb->dev, "skb->dev=%s ", skb->dev->name ? skb->dev->name : "NULL"); KLIPS_PRINTMORE(debug_rcv, "\n"); if (irs->proto != IPPROTO_AH && #ifdef CONFIG_KLIPS_IPCOMP_disabled_until_we_register_IPCOMP_HANDLER irs->proto != IPPROTO_COMP && #endif /* CONFIG_KLIPS_IPCOMP */ irs->proto != IPPROTO_ESP) { KLIPS_PRINT(debug_rcv & DB_RX_IPSA, "klips_debug:ipsec_rcv_init: Why the hell is someone " "passing me a non-ipsec irs->proto = %d packet? -- dropped.\n", irs->proto); return IPSEC_RCV_REALLYBAD; } /* * if there is an attached ipsec device, then use that device for * stats until we know better. */ if (skb->dev) { struct ipsecpriv *prvdev = NULL; struct net_device *ipsecdev = NULL; for (i = 0; i <= ipsecdevices_max; i++) { if (ipsecdevices[i] == NULL) continue; if (!netdev_priv(ipsecdevices[i])) continue; prvdev = netdev_to_ipsecpriv(ipsecdevices[i]); if (prvdev->dev == skb->dev) { ipsecdev = ipsecdevices[i]; break; } } if (ipsecdev) { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_init: " "assigning packet ownership to " "virtual device %s from " "physical device %s.\n", ipsecdev->name, skb->dev->name); skb->dev = ipsecdev; } else { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_init: " "assigning packet ownership to " "virtual device mast0 from " "physical device %s.\n", skb->dev->name); skb->dev = ipsec_mast_get_device(0); /* ipsec_mast_get takes the device */ if (skb->dev) dev_put(skb->dev); } if (prvdev) stats = (struct net_device_stats *) &(prvdev->mystats); } else { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_init: " "device supplied with skb is NULL\n"); } if (stats) stats->rx_packets++; KLIPS_IP_PRINT(debug_rcv, irs->iph); /* set up for decap */ irs->stats = stats; irs->ipsp = NULL; irs->lastipsp = NULL; irs->ilen = 0; irs->authlen = 0; irs->authfuncs = NULL; irs->skb = skb; return IPSEC_RCV_OK; } static enum ipsec_rcv_value ipsec_rcv_decap_init(struct ipsec_rcv_state *irs) { KLIPS_PRINT(debug_rcv, "klips_debug: %s(st=%d,nxt=%d)\n", __FUNCTION__, irs->state, irs->next_state); switch (irs->proto) { case IPPROTO_ESP: irs->proto_funcs = esp_xform_funcs; break; #ifdef CONFIG_KLIPS_AH case IPPROTO_AH: irs->proto_funcs = ah_xform_funcs; break; #endif /* !CONFIG_KLIPS_AH */ #ifdef CONFIG_KLIPS_IPCOMP case IPPROTO_COMP: irs->proto_funcs = ipcomp_xform_funcs; break; #endif /* !CONFIG_KLIPS_IPCOMP */ default: if (irs->stats) irs->stats->rx_errors++; return IPSEC_RCV_BADPROTO; } return IPSEC_RCV_OK; } static enum ipsec_rcv_value ipsec_rcv_decap_lookup(struct ipsec_rcv_state *irs) { struct sk_buff *skb; KLIPS_PRINT(debug_rcv, "klips_debug: %s(st=%d,nxt=%d)\n", __FUNCTION__, irs->state, irs->next_state); irs->replay = 0; #ifdef CONFIG_KLIPS_ALG irs->ixt_a = NULL; #endif /* CONFIG_KLIPS_ALG */ skb = irs->skb; irs->len = skb->len; if (debug_rcv) ipsec_rcv_redodebug(irs); if (lsw_ip_hdr_version(irs) == 6) { irs->said.dst.u.v6.sin6_addr = lsw_ip6_hdr(irs)->daddr; SET_V6(irs->said.dst); } else { irs->said.dst.u.v4.sin_addr.s_addr = lsw_ip4_hdr(irs)->daddr; SET_V4(irs->said.dst); } /* note: rcv_checks set up the said.spi value, if appropriate */ if (irs->proto_funcs->rcv_checks) return (*irs->proto_funcs->rcv_checks)(irs, irs->skb); return IPSEC_RCV_OK; } static enum ipsec_rcv_value ipsec_rcv_auth_init(struct ipsec_rcv_state *irs) { struct ipsec_sa *newipsp; KLIPS_PRINT(debug_rcv, "klips_debug: %s(st=%d,nxt=%d)\n", __FUNCTION__, irs->state, irs->next_state); irs->said.proto = irs->proto; irs->sa_len = KLIPS_SATOT(debug_rcv, &irs->said, 0, irs->sa, sizeof(irs->sa)); newipsp = ipsec_sa_getbyid(&irs->said, IPSEC_REFRX); if (newipsp == NULL) { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_auth_init: " "no ipsec_sa for SA:%s: incoming packet with no SA dropped\n", irs->sa_len ? irs->sa : " (error)"); if (irs->stats) irs->stats->rx_dropped++; return IPSEC_RCV_SAIDNOTFOUND; } /* If it is in larval state, drop the packet, we cannot process yet. */ if (newipsp->ips_state == K_SADB_SASTATE_LARVAL) { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_auth_init: " "ipsec_sa in larval state, cannot be used yet, dropping packet.\n"); if (irs->stats) irs->stats->rx_dropped++; ipsec_sa_put(newipsp, IPSEC_REFRX); return IPSEC_RCV_SAIDNOTLIVE; } if (newipsp->ips_state == K_SADB_SASTATE_DEAD) { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_auth_init: " "ipsec_sa in dead state, cannot be used any more, dropping packet.\n"); if (irs->stats) irs->stats->rx_dropped++; ipsec_sa_put(newipsp, IPSEC_REFRX); return IPSEC_RCV_SAIDNOTLIVE; } if (sysctl_ipsec_inbound_policy_check) { struct sockaddr_in *psin = NULL; struct sockaddr_in6 *psin6 = NULL; char sa_saddr_txt[ADDRTOA_BUF] = { 0, }; if (((struct sockaddr_in6*)(newipsp->ips_addr_s))->sin6_family == AF_INET6) psin6 = (struct sockaddr_in6*)(newipsp->ips_addr_s); else if (((struct sockaddr_in*)(newipsp->ips_addr_s))-> sin_family == AF_INET) psin = (struct sockaddr_in*)(newipsp->ips_addr_s); if ((psin && lsw_ip4_hdr(irs)->saddr != psin->sin_addr.s_addr) || (psin6 && memcmp(&lsw_ip6_hdr(irs)->saddr, &psin6->sin6_addr, sizeof(lsw_ip6_hdr(irs)->saddr)) != 0)) { if (debug_rcv) { /* generate SA->saddr */ if (psin) { inet_addrtot(AF_INET, &psin->sin_addr.s_addr, 0, sa_saddr_txt, sizeof(sa_saddr_txt)); } else if (psin6) { inet_addrtot(AF_INET6, &psin6->sin6_addr.s6_addr, 0, sa_saddr_txt, sizeof(sa_saddr_txt)); } /* generate ipsaddr_txt */ if (!(*irs->ipsaddr_txt)) ipsec_rcv_redodebug(irs); /* regenerate sa_len */ if (!irs->sa_len) { irs->sa_len = KLIPS_SATOT(debug_rcv, &irs->said, 0, irs->sa, sizeof(irs-> sa)); } } KLIPS_ERROR(debug_rcv, "klips_debug:ipsec_rcv_auth_init: " "SA:%s, src=%s of pkt does not agree with expected SA source address policy (%s).\n", irs->sa_len ? irs->sa : " (error)", irs->ipsaddr_txt, sa_saddr_txt); if (irs->stats) irs->stats->rx_dropped++; ipsec_sa_put(newipsp, IPSEC_REFRX); return IPSEC_RCV_FAILEDINBOUND; } KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_auth_init: " "SA:%s, src=%s of pkt agrees with expected SA source address policy.\n", irs->sa_len ? irs->sa : " (error)", irs->ipsaddr_txt); /* * at this point, we have looked up a new SA, and we want to * make sure that if this isn't the first SA in the list, * that the previous SA actually points at this one. */ if (irs->ipsp) { if (irs->ipsp->ips_next != newipsp) { KLIPS_ERROR(debug_rcv, "klips_debug:ipsec_rcv_auth_init: " "unexpected SA:%s: does not agree with ips->inext policy, dropped\n", irs->sa_len ? irs->sa : " (error)"); if (irs->stats) irs->stats->rx_dropped++; ipsec_sa_put(newipsp, IPSEC_REFRX); return IPSEC_RCV_FAILEDINBOUND; } KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_auth_init: " "SA:%s grouping from previous SA is OK.\n", irs->sa_len ? irs->sa : " (error)"); } else { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_auth_init: " "SA:%s First SA in group.\n", irs->sa_len ? irs->sa : " (error)"); } if (irs->proto == IPPROTO_ESP) { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_auth_init: " "natt_type=%u tdbp->ips_natt_type=%u : %s\n", irs->natt_type, newipsp->ips_natt_type, (irs->natt_type == newipsp->ips_natt_type) ? "ok" : "bad"); if (irs->natt_type != newipsp->ips_natt_type) { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_auth_init: " "SA:%s does not agree with expected NAT-T policy.\n", irs->sa_len ? irs->sa : " (error)"); if (irs->stats) irs->stats->rx_dropped++; ipsec_sa_put(newipsp, IPSEC_REFRX); return IPSEC_RCV_FAILEDINBOUND; } } } if (newipsp != irs->ipsp) { if (irs->lastipsp) ipsec_sa_put(irs->lastipsp, IPSEC_REFRX); irs->lastipsp = irs->ipsp; irs->ipsp = newipsp; } else { /* we already have a refcount for it */ ipsec_sa_put(newipsp, IPSEC_REFRX); } return IPSEC_RCV_OK; } static enum ipsec_rcv_value ipsec_rcv_auth_decap(struct ipsec_rcv_state *irs) { ipsec_rcv_setoutif(irs); irs->proto_funcs = irs->ipsp->ips_xformfuncs; if (irs->proto_funcs == NULL) return IPSEC_RCV_BADPROTO; if (irs->proto_funcs->protocol != irs->proto) { if (irs->proto_funcs->protocol == IPPROTO_COMP) { /* looks like an IPCOMP that we can skip */ struct ipsec_sa *newipsp; newipsp = irs->ipsp->ips_next; if (newipsp) ipsec_sa_get(newipsp, IPSEC_REFRX); if (irs->lastipsp) ipsec_sa_put(irs->lastipsp, IPSEC_REFRX); irs->lastipsp = irs->ipsp; irs->ipsp = newipsp; /* come back into here with the next transform */ irs->next_state = IPSEC_RSM_DECAP_INIT; return IPSEC_RCV_OK; } KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_auth_decap: " "packet with protocol %d!=%d dropped, last successful SA:%s.\n", irs->proto_funcs->protocol, irs->proto, irs->sa_len ? irs->sa : " (error)"); if (irs->stats) irs->stats->rx_errors++; return IPSEC_RCV_FAILEDINBOUND; } if (debug_rcv) ipsec_rcv_redodebug(irs); /* now check the lifetimes */ if (ipsec_lifetime_check(&irs->ipsp->ips_life.ipl_bytes, "bytes", irs->sa, ipsec_life_countbased, ipsec_incoming, irs->ipsp) == ipsec_life_harddied || ipsec_lifetime_check(&irs->ipsp->ips_life.ipl_addtime, "addtime", irs->sa, ipsec_life_timebased, ipsec_incoming, irs->ipsp) == ipsec_life_harddied || ipsec_lifetime_check(&irs->ipsp->ips_life.ipl_addtime, "usetime", irs->sa, ipsec_life_timebased, ipsec_incoming, irs->ipsp) == ipsec_life_harddied || ipsec_lifetime_check(&irs->ipsp->ips_life.ipl_packets, "packets", irs->sa, ipsec_life_countbased, ipsec_incoming, irs->ipsp) == ipsec_life_harddied) { /* * disconnect SA from the hash table, so it cannot be * found again. */ ipsec_sa_rm(irs->ipsp); if (irs->stats) irs->stats->rx_dropped++; KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_auth_decap: " "decap (%d) failed lifetime check\n", irs->proto); return IPSEC_RCV_LIFETIMEFAILED; } #if 0 /* * This is removed for some reasons: * 1) it needs to happen *after* authentication. * 2) do we really care, if it authenticates, if it came * from the wrong location? * 3) the NAT_KA messages in IKE will also get to pluto * and it will figure out that stuff has moved. * 4) the 2.6 udp-esp encap function does not pass us * the originating port number, and I can't tell * if skb->sk is guaranteed to be valid here. * 2005-04-16: mcr@xelerance.com */ /* * * XXX we should ONLY update pluto if the SA passes all checks, * which we clearly {do not know | don't do now}. */ if (irs->natt_type != 0 && (irs->ipp->saddr != ((struct sockaddr_in*)(newipsp->ips_addr_s))->sin_addr.s_addr || irs->natt_sport != newipsp->ips_natt_sport)) { struct sockaddr sipaddr; struct sockaddr_in *psin = (struct sockaddr_in*)(newipsp->ips_addr_s); /** Advertise NAT-T addr change to pluto **/ sipaddr.sa_family = AF_INET; ((struct sockaddr_in*)&sipaddr)->sin_addr.s_addr = irs->ipp->saddr; ((struct sockaddr_in*)&sipaddr)->sin_port = htons( irs->natt_sport); pfkey_nat_t_new_mapping(newipsp, &sipaddr, irs->natt_sport); /** * Then allow or block packet depending on * sysctl_ipsec_inbound_policy_check. * * In all cases, pluto will update SA if new mapping is * accepted. */ if (sysctl_ipsec_inbound_policy_check) { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_auth_decap: " "SA:%s, src=%s:%u of pkt does not agree with expected " "SA source address [%08x:%u] (notifying pluto of change).\n", irs->sa_len ? irs->sa : " (error)", irs->ipsaddr_txt, irs->natt_sport, psin->sin_addr.s_addr, newipsp->ips_natt_sport); if (irs->stats) irs->stats->rx_dropped++; ipsec_sa_put(newipsp); return IPSEC_RCV_FAILEDINBOUND; } } #endif irs->authfuncs = NULL; /* authenticate, if required */ #ifdef CONFIG_KLIPS_OCF if (irs->ipsp->ocf_in_use) { irs->authlen = AHHMAC_HASHLEN; irs->authfuncs = NULL; irs->ictx = NULL; irs->octx = NULL; irs->ictx_len = 0; irs->octx_len = 0; } else #endif /* CONFIG_KLIPS_OCF */ #ifdef CONFIG_KLIPS_ALG /* authenticate, if required */ if ((irs->ixt_a = irs->ipsp->ips_alg_auth)) { irs->authlen = irs->ixt_a->ixt_a_authlen; irs->authfuncs = NULL; irs->ictx = NULL; irs->octx = NULL; irs->ictx_len = 0; irs->octx_len = 0; KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_auth_decap: " "authalg=%d authlen=%d\n", irs->ipsp->ips_authalg, irs->authlen); } else #endif /* CONFIG_KLIPS_ALG */ switch (irs->ipsp->ips_authalg) { #ifdef CONFIG_KLIPS_AUTH_HMAC_MD5 case AH_MD5: irs->authlen = AHHMAC_HASHLEN; irs->authfuncs = ipsec_rcv_md5; irs->ictx = (void *) &((struct md5_ctx*)(irs->ipsp->ips_key_a))->ictx; irs->octx = (void *) &((struct md5_ctx*)(irs->ipsp->ips_key_a))->octx; irs->ictx_len = sizeof(((struct md5_ctx*)(irs->ipsp->ips_key_a))->ictx); irs->octx_len = sizeof(((struct md5_ctx*)(irs->ipsp->ips_key_a))->octx); break; #endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ #ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1 case AH_SHA: irs->authlen = AHHMAC_HASHLEN; irs->authfuncs = ipsec_rcv_sha1; irs->ictx = (void *) &((struct sha1_ctx*)(irs->ipsp->ips_key_a))->ictx; irs->octx = (void *) &((struct sha1_ctx*)(irs->ipsp->ips_key_a))->octx; irs->ictx_len = sizeof(((struct sha1_ctx*)(irs->ipsp->ips_key_a))->ictx); irs->octx_len = sizeof(((struct sha1_ctx*)(irs->ipsp->ips_key_a))->octx); break; #endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */ case AH_NONE: irs->authlen = 0; irs->authfuncs = NULL; irs->ictx = NULL; irs->octx = NULL; irs->ictx_len = 0; irs->octx_len = 0; break; default: irs->ipsp->ips_errs.ips_alg_errs += 1; if (irs->stats) irs->stats->rx_errors++; return IPSEC_RCV_BADAUTH; } /* ilen counts number of bytes in ESP portion */ irs->ilen = ((irs->skb->data + irs->skb->len) - skb_transport_header(irs->skb)) - irs->authlen; if (irs->ilen <= 0) { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_auth_decap: " "runt %s packet with no data, dropping.\n", (irs->proto == IPPROTO_ESP ? "esp" : "ah")); if (irs->stats) irs->stats->rx_dropped++; return IPSEC_RCV_BADLEN; } if (irs->authfuncs #ifdef CONFIG_KLIPS_OCF || irs->ipsp->ocf_in_use #endif #ifdef CONFIG_KLIPS_ALG || irs->ixt_a #endif ) { if (irs->proto_funcs->rcv_setup_auth) { return (*irs->proto_funcs->rcv_setup_auth)( irs, irs->skb, &irs->replay, &irs->authenticator); } } return IPSEC_RCV_OK; } static enum ipsec_rcv_value ipsec_rcv_auth_calc(struct ipsec_rcv_state *irs) { KLIPS_PRINT(debug_rcv, "klips_debug: %s(st=%d,nxt=%d)\n", __FUNCTION__, irs->state, irs->next_state); if (irs->authfuncs || #ifdef CONFIG_KLIPS_OCF (irs->ipsp->ocf_in_use && irs->ipsp->ips_authalg) || #endif #ifdef CONFIG_KLIPS_ALG irs->ixt_a || #endif 0) { if (!irs->authenticator) { irs->ipsp->ips_errs.ips_auth_errs += 1; if (irs->stats) irs->stats->rx_dropped++; return IPSEC_RCV_BADAUTH; } if (!ipsec_checkreplaywindow(irs->ipsp, irs->replay)) { irs->ipsp->ips_errs.ips_replaywin_errs += 1; KLIPS_PRINT(debug_rcv & DB_RX_REPLAY, "klips_debug:ipsec_rcv_auth_calc: " "duplicate frame from %s, packet dropped\n", irs->ipsaddr_txt); if (irs->stats) irs->stats->rx_dropped++; return IPSEC_RCV_REPLAYFAILED; } /* * verify authenticator */ KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_auth_calc: " "encalg = %d, authalg = %d.\n", irs->ipsp->ips_encalg, irs->ipsp->ips_authalg); /* calculate authenticator */ if (irs->proto_funcs->rcv_calc_auth == NULL) return IPSEC_RCV_BADAUTH; return (*irs->proto_funcs->rcv_calc_auth)(irs, irs->skb); } return IPSEC_RCV_OK; } static enum ipsec_rcv_value ipsec_rcv_auth_chk(struct ipsec_rcv_state *irs) { KLIPS_PRINT(debug_rcv, "klips_debug: %s(st=%d,nxt=%d) - %s\n", __FUNCTION__, irs->state, irs->next_state, irs->auth_checked ? "already checked" : "will check"); if (irs->auth_checked) return IPSEC_RCV_OK; if (irs->authfuncs || #ifdef CONFIG_KLIPS_OCF (irs->ipsp->ocf_in_use && irs->ipsp->ips_authalg) || #endif #ifdef CONFIG_KLIPS_ALG irs->ixt_a || #endif 0) { if (memcmp(irs->hash, irs->authenticator, irs->authlen)) { irs->ipsp->ips_errs.ips_auth_errs += 1; KLIPS_ERROR(debug_rcv & DB_RX_INAU, "klips_debug:ipsec_rcv_auth_chk: " "auth failed on incoming packet from %s (replay=%d): calculated hash=%08x%08x%08x received hash=%08x%08x%08x, dropped\n", irs->ipsaddr_txt, irs->replay, ntohl(*(__u32*)&irs->hash[0]), ntohl(*(__u32*)&irs->hash[4]), ntohl(*(__u32*)&irs->hash[8]), ntohl(*(__u32*)irs->authenticator), ntohl(*((__u32*)irs->authenticator + 1)), ntohl(*((__u32*)irs->authenticator + 2))); if (irs->stats) irs->stats->rx_dropped++; return IPSEC_RCV_AUTHFAILED; } else { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_auth_chk: " "authentication successful.\n"); } /* Crypto hygiene: clear memory used to calculate autheticator. * The length varies with the algorithm. */ memset(irs->hash, 0, irs->authlen); /* If the sequence number == 0, expire SA, it had rolled */ if (irs->ipsp->ips_replaywin && !irs->replay /* !irs->ipsp->ips_replaywin_lastseq */) { /* we need to remove it from the sadb hash, so that it can't be found again */ ipsec_sa_rm(irs->ipsp); KLIPS_ERROR(debug_rcv, "klips_debug:ipsec_rcv_auth_chk: " "replay window counter rolled, expiring SA.\n"); if (irs->stats) irs->stats->rx_dropped++; return IPSEC_RCV_REPLAYROLLED; } /* now update the replay counter */ if (!ipsec_updatereplaywindow(irs->ipsp, irs->replay)) { irs->ipsp->ips_errs.ips_replaywin_errs += 1; KLIPS_ERROR(debug_rcv & DB_RX_REPLAY, "klips_debug:ipsec_rcv_auth_chk: " "duplicate frame from %s, packet dropped\n", irs->ipsaddr_txt); if (irs->stats) irs->stats->rx_dropped++; return IPSEC_RCV_REPLAYROLLED; } irs->auth_checked = 1; } return IPSEC_RCV_OK; } static enum ipsec_rcv_value ipsec_rcv_decrypt(struct ipsec_rcv_state *irs) { KLIPS_PRINT(debug_rcv, "klips_debug: %s(st=%d,nxt=%d)\n", __FUNCTION__, irs->state, irs->next_state); if (irs->proto_funcs->rcv_decrypt) return (*irs->proto_funcs->rcv_decrypt)(irs); return IPSEC_RCV_OK; } /* * here we decide if there is more decapsulating required and * change the next state appropriately */ static enum ipsec_rcv_value ipsec_rcv_decap_cont(struct ipsec_rcv_state *irs) { struct sk_buff *skb; struct ipsec_sa *ipsnext = NULL; /* next SA towards inside of packet */ enum ipsec_rcv_value rv; KLIPS_PRINT(debug_rcv, "klips_debug: %s(st=%d,nxt=%d)\n", __FUNCTION__, irs->state, irs->next_state); /* * if we haven't checked the auth values yet, do it now. * This is needed for the case where drivers do crypt+hash * in one operation. */ rv = ipsec_rcv_auth_chk(irs); if (rv != IPSEC_RCV_OK) return rv; /* * Adjust pointers after decrypt */ skb = irs->skb; irs->len = skb->len; irs->iph = (void *) ip_hdr(skb); #ifdef CONFIG_KLIPS_IPV6 if (lsw_ip_hdr_version(irs) == 6) { IPSEC_FRAG_OFF_DECL(frag_off) unsigned char nexthdr = lsw_ip6_hdr(irs)->nexthdr; int nexthdroff; nexthdroff = ipsec_ipv6_skip_exthdr(irs->skb, (void *)(lsw_ip6_hdr(irs) + 1) - (void *)irs->skb->data, &nexthdr, &frag_off); irs->iphlen = nexthdroff - (irs->iph - (void*)irs->skb->data); skb_set_transport_header(skb, ipsec_skb_offset(skb, skb_network_header( skb) + irs->iphlen)); } else #endif /* CONFIG_KLIPS_IPV6 */ { irs->iphlen = lsw_ip4_hdr(irs)->ihl << 2; skb_set_transport_header(skb, ipsec_skb_offset(skb, skb_network_header( skb) + irs->iphlen)); } /* zero any options that there might be */ memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); if (debug_rcv) ipsec_rcv_redodebug(irs); /* * Discard the original ESP/AH header */ if (lsw_ip_hdr_version(irs) == 6) { lsw_ip6_hdr(irs)->nexthdr = irs->next_header; skb->protocol = htons(ETH_P_IPV6); } else { lsw_ip4_hdr(irs)->protocol = irs->next_header; lsw_ip4_hdr(irs)->check = 0; /* NOTE: this will be included in checksum */ lsw_ip4_hdr(irs)->check = ip_fast_csum((unsigned char *)ip_hdr(skb), irs->iphlen >> 2); skb->protocol = htons(ETH_P_IP); } irs->proto = irs->next_header; /* needed for decap_init recursion */ KLIPS_PRINT(debug_rcv & DB_RX_PKTRX, "klips_debug:ipsec_rcv_decap_cont: " "after <%s%s%s>, SA:%s:\n", IPS_XFORM_NAME(irs->ipsp), irs->sa_len ? irs->sa : " (error)"); KLIPS_IP_PRINT(debug_rcv & DB_RX_PKTRX, irs->iph); skb->ip_summed = 0; ipsnext = irs->ipsp->ips_next; if (sysctl_ipsec_inbound_policy_check) { if (ipsnext) { if (irs->next_header != IPPROTO_AH && irs->next_header != IPPROTO_ESP && #ifdef CONFIG_KLIPS_IPCOMP irs->next_header != IPPROTO_COMP && (ipsnext->ips_said.proto != IPPROTO_COMP || ipsnext->ips_next) && #endif /* CONFIG_KLIPS_IPCOMP */ irs->next_header != IPPROTO_IPIP && irs->next_header != IPPROTO_IPV6 && irs->next_header != IPPROTO_ATT_HEARTBEAT /* heartbeats to AT&T SIG/GIG */ ) { KLIPS_PRINT(debug_rcv, "packet with incomplete policy dropped, last successful SA:%s.\n", irs->sa_len ? irs->sa : " (error)"); if (irs->stats) irs->stats->rx_dropped++; return IPSEC_RCV_FAILEDINBOUND; } KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_decap_cont: " "SA:%s, Another IPSEC header to process.\n", irs->sa_len ? irs->sa : " (error)"); } else { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_decap_cont: " "No ips_inext from this SA:%s.\n", irs->sa_len ? irs->sa : " (error)"); } } #ifdef CONFIG_KLIPS_IPCOMP /* update ipcomp ratio counters, even if no ipcomp packet is present */ if (ipsnext && ipsnext->ips_said.proto == IPPROTO_COMP && irs->next_header != IPPROTO_COMP) { int tot_len; if (lsw_ip_hdr_version(irs) == 6) tot_len = ntohs(lsw_ip6_hdr(irs)->payload_len) + sizeof(struct ipv6hdr); else tot_len = ntohs(lsw_ip4_hdr(irs)->tot_len); ipsnext->ips_comp_ratio_cbytes += tot_len; ipsnext->ips_comp_ratio_dbytes += tot_len; } #endif /* CONFIG_KLIPS_IPCOMP */ irs->ipsp->ips_life.ipl_bytes.ipl_count += irs->len; irs->ipsp->ips_life.ipl_bytes.ipl_last = irs->len; if (!irs->ipsp->ips_life.ipl_usetime.ipl_count) irs->ipsp->ips_life.ipl_usetime.ipl_count = jiffies / HZ; irs->ipsp->ips_life.ipl_usetime.ipl_last = jiffies / HZ; irs->ipsp->ips_life.ipl_packets.ipl_count += 1; #if defined(CONFIG_KLIPS_COMPAT_NAT_NFMARK) && defined(CONFIG_NETFILTER) if (irs->proto == IPPROTO_ESP || irs->proto == IPPROTO_AH) { skb->nfmark = IPSEC_NFMARK_IS_SAREF_BIT | (skb->nfmark & (~(IPsecSAref2NFmark(IPSEC_SA_REF_MASK)))) | IPsecSAref2NFmark(IPsecSA2SAref(irs->ipsp)); KLIPS_PRINT(debug_rcv & DB_RX_PKTRX, "klips_debug:ipsec_rcv_decap_cont: " "%s SA sets skb->nfmark=0x%x.\n", irs->proto == IPPROTO_ESP ? "ESP" : "AH", (unsigned)skb->nfmark); } #endif /* do we need to do more decapsulation */ if ((irs->proto == IPPROTO_ESP || irs->proto == IPPROTO_AH || #ifdef CONFIG_KLIPS_IPCOMP irs->proto == IPPROTO_COMP || #endif /* CONFIG_KLIPS_IPCOMP */ 0) && irs->ipsp != NULL) irs->next_state = IPSEC_RSM_DECAP_INIT; return IPSEC_RCV_OK; } static enum ipsec_rcv_value ipsec_rcv_cleanup(struct ipsec_rcv_state *irs) { struct sk_buff *skb; KLIPS_PRINT(debug_rcv, "klips_debug: %s(st=%d,nxt=%d)\n", __FUNCTION__, irs->state, irs->next_state); /* set up for cleanup */ skb = irs->skb; if ((irs->natt_type) && (irs->proto != IPPROTO_IPIP)) { /* * NAT-Traversal and Transport Mode: * we need to correct TCP/UDP checksum * If we've got NAT-OA, we can fix checksum without recalculation. */ __u32 natt_oa = (irs->ipsp && irs->ipsp->ips_natt_oa) ? ((struct sockaddr_in*)(irs->ipsp->ips_natt_oa)) ->sin_addr.s_addr : 0; if (natt_oa != 0) { /* reset source address to what it was before NAT */ lsw_ip4_hdr(irs)->saddr = natt_oa; lsw_ip4_hdr(irs)->check = 0; lsw_ip4_hdr(irs)->check = ip_fast_csum( (unsigned char *)irs->iph, lsw_ip4_hdr( irs)->ihl); KLIPS_PRINT(debug_rcv, "csum: %04x\n", lsw_ip4_hdr(irs)->check); } /* * This fails when both systems are behind NAT * mcr: So, either the ports passed in by the NAT-OA mechanism for the fixup * are wrong, and so the checksum fixup is wrong * Not very harmful since the checksum is useless and the crypto hash will * be used anyway. */ #ifdef DISABLE_UDP_CHECKSUM /* see https://bugs.libreswan.org/issues/601 */ if (lsw_ip4_hdr(irs)->protocol == IPPROTO_UDP) { udp_hdr(skb)->check = 0; KLIPS_PRINT(debug_rcv, "UDP checksum for NAT packet disabled at compile time\n"); } #endif } /* okay, acted on all SA's, so free the last SA, and move to the next */ if (irs->ipsp) { struct ipsec_sa *newipsp; newipsp = irs->ipsp->ips_next; if (newipsp) ipsec_sa_get(newipsp, IPSEC_REFRX); if (irs->lastipsp) ipsec_sa_put(irs->lastipsp, IPSEC_REFRX); irs->lastipsp = irs->ipsp; irs->ipsp = newipsp; } #ifdef CONFIG_KLIPS_IPCOMP /* if there is an IPCOMP, but we don't have an IPPROTO_COMP, * then we can just skip it */ if (irs->ipsp && irs->ipsp->ips_said.proto == IPPROTO_COMP) { struct ipsec_sa *newipsp = NULL; newipsp = irs->ipsp->ips_next; if (newipsp) ipsec_sa_get(newipsp, IPSEC_REFRX); if (irs->lastipsp) ipsec_sa_put(irs->lastipsp, IPSEC_REFRX); irs->lastipsp = irs->ipsp; irs->ipsp = newipsp; irs->sa_len = 0; } #endif /* CONFIG_KLIPS_IPCOMP */ /* * the SA is still locked from the loop */ if (irs->ipsp && irs->ipsp->ips_xformfuncs->protocol == IPPROTO_IPIP) { enum ipsec_rcv_value decap_stat; decap_stat = ipsec_rcv_decap_ipip(irs); if (decap_stat != IPSEC_RCV_OK) return decap_stat; } if (irs->stats) irs->stats->rx_bytes += skb->len; /* * if we are supposed to return the packet directly to the transport * layer, then dump it out correctly. */ if (unlikely(!irs->lastipsp)) printk("%s,%d: %s lastipsp should never be NULL\n", __FILE__, __LINE__, __FUNCTION__); if (irs->lastipsp->ips_transport_direct) { KLIPS_PRINT(debug_rcv, "receiving packet as transport direct\n"); skb->ip_summed = CHECKSUM_UNNECESSARY; /* STUFF */ } #ifdef CONFIG_INET_IPSEC_SAREF if (skb->sp) secpath_put(skb->sp); skb->sp = secpath_dup(NULL); if (skb->sp) skb->sp->ref = irs->lastipsp->ips_ref; else return IPSEC_RCV_REALLYBAD; #endif return IPSEC_RCV_OK; } static enum ipsec_rcv_value ipsec_rcv_complete(struct ipsec_rcv_state *irs) { KLIPS_PRINT(debug_rcv, "klips_debug: %s(st=%d,nxt=%d)\n", __FUNCTION__, irs->state, irs->next_state); /* * make sure that data now starts at IP header, since we are going * to pass this back to ip_input (aka netif_rx). Rules for what the * pointers wind up a different for 2.6 vs 2.4, so we just fudge it here. */ #ifdef NET_26 irs->skb->data = skb_push(irs->skb, skb_transport_header(irs->skb) - skb_network_header(irs->skb)); #else irs->skb->data = skb_network_header(irs->skb); { int len; struct iphdr *iph = ip_hdr(irs->skb); #ifdef CONFIG_KLIPS_IPV6 struct ipv6hdr *ip6h = (struct ipv6hdr *) iph; if (iph->version == 6) len = ntohs(iph->payload_len) + sizeof(*ip6h); else #endif /* CONFIG_KLIPS_IPV6 */ len = ntohs(iph->tot_len); irs->skb->len = len; } #endif /* * release the dst that was attached, since we have likely * changed the actual destination of the packet. */ skb_dst_drop(irs->skb); irs->skb->pkt_type = PACKET_HOST; if (irs->hard_header_len && (skb_mac_header(irs->skb) != (skb_network_header(irs->skb) - irs->hard_header_len)) && (irs->hard_header_len <= skb_headroom(irs->skb))) { /* copy back original MAC header */ memmove(skb_network_header(irs->skb) - irs->hard_header_len, skb_mac_header(irs->skb), irs->hard_header_len); skb_set_mac_header(irs->skb, ipsec_skb_offset(irs->skb, skb_network_header(irs->skb) - irs->hard_header_len)); /* we have to fix the protocol, it's not right with IP4/IP6 or * IP6/IP4 tunnels */ if (irs->hard_header_len == ETH_HLEN) eth_hdr(irs->skb)->h_proto = irs->skb->protocol; } ipsec_nf_reset(irs->skb); if (irs->skb->dev == NULL) { /* the physical dev went down and is no longer attached */ KLIPS_PRINT(debug_rcv & DB_RX_PKTRX, "klips_debug:ipsec_rcv_complete: interface for skb is detached.\n"); return IPSEC_RCV_REALLYBAD; } KLIPS_PRINT(debug_rcv & DB_RX_PKTRX, "klips_debug:ipsec_rcv_complete: " "netif_rx(%s) called.\n", irs->skb->dev->name); netif_rx(irs->skb); irs->skb = NULL; return IPSEC_RCV_OK; } /* * ipsec_rsm is responsible for walking us through the state machine * it is the only entry point into the receive processing and does * appropriate checks and state changes for us. */ void ipsec_rsm(struct ipsec_rcv_state *irs) { if (irs == NULL) { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rsm: " "irs == NULL.\n"); return; } /* * make sure nothing is removed from underneath us */ spin_lock_bh(&tdb_lock); /* * if we have a valid said, then we must check it here to ensure it * hasn't gone away while we were waiting for a task to complete */ if (irs->said.proto) { struct ipsec_sa *ipsp; ipsp = ipsec_sa_getbyid(&irs->said, IPSEC_REFRX); if (ipsp == NULL) { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rsm: " "no ipsec_sa for SA:%s: " "incoming packet with no SA dropped\n", irs->sa_len ? irs->sa : " (error)"); if (irs->stats) irs->stats->rx_dropped++; /* drop through and cleanup */ irs->state = IPSEC_RSM_DONE; } else { /* set the refcount back */ ipsec_sa_put(ipsp, IPSEC_REFRX); } } while (irs->state != IPSEC_RSM_DONE) { int rc; irs->next_state = rcv_state_table[irs->state].next_state; rc = rcv_state_table[irs->state].action(irs); if (rc == IPSEC_RCV_OK) { /* some functions change the next state, see the state table */ irs->state = irs->next_state; } else if (rc == IPSEC_RCV_PENDING) { /* * things are on hold until we return here in the next/new state * we check our SA is valid when we return */ spin_unlock_bh(&tdb_lock); return; } else { /* bad result, force state change to done */ KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rsm: " "processing completed due to %s.\n", ipsec_rcv_err(rc)); irs->state = IPSEC_RSM_DONE; } } if (irs->lastipsp) { ipsec_sa_put(irs->lastipsp, IPSEC_REFRX); irs->lastipsp = NULL; } if (irs->ipsp) { ipsec_sa_put(irs->ipsp, IPSEC_REFRX); irs->ipsp = NULL; } /* * all done with anything needing locks */ spin_unlock_bh(&tdb_lock); if (irs->skb) { ipsec_kfree_skb(irs->skb); irs->skb = NULL; } if (irs->pre_ipcomp_skb) { ipsec_kfree_skb(irs->pre_ipcomp_skb); irs->pre_ipcomp_skb = NULL; } ipsec_rcv_state_delete(irs); KLIPS_DEC_USE; /* once less packet using the driver */ } int ipsec_rcv(struct sk_buff *skb ) { struct ipsec_rcv_state *irs = NULL; /* Don't unlink in the middle of a turnaround */ KLIPS_INC_USE; if (skb == NULL) { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv: " "NULL skb passed in.\n"); goto rcvleave; } if (skb->data == NULL) { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv: " "NULL skb->data passed in, packet is bogus, dropping.\n"); goto rcvleave; } irs = ipsec_rcv_state_new(); if (unlikely(!irs)) { KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv: " "failed to allocate a rcv state object\n"); goto rcvleave; } #if defined(CONFIG_IPSEC_NAT_TRAVERSAL) && !defined(NET_26) { /* NET_26 NAT-T is handled by separate function */ struct sk_buff *nskb; int udp_decap_ret = 0; nskb = ipsec_rcv_natt_decap(skb, irs, &udp_decap_ret); if (nskb == NULL) { /* return with non-zero, because UDP.c code * need to send it upstream. */ if (skb && udp_decap_ret == 0) ipsec_kfree_skb(skb); if (irs) ipsec_rcv_state_delete(irs); KLIPS_DEC_USE; return udp_decap_ret; } skb = nskb; } #endif /* NAT_T */ irs->skb = skb; /* * we hand off real early to the state machine because we just cannot * know how much processing it is off-loading */ ipsec_rsm(irs); return 0; rcvleave: if (irs) ipsec_rcv_state_delete(irs); if (skb) ipsec_kfree_skb(skb); KLIPS_DEC_USE; return 0; } #ifdef NET_26 /* * this entry point is not a protocol entry point, so the entry * is a bit different. * * skb->iph->tot_len has been byte-swapped, and reduced by the size of * the IP header (and options). * * skb->h.raw has been pulled up the ESP header. * * skb->iph->protocol = 50 IPPROTO_ESP; * */ int klips26_udp_encap_rcv(struct sock *sk, struct sk_buff *skb) { struct udp_sock *up = udp_sk(sk); struct udphdr *uh; struct iphdr *iph; int iphlen, len; int ret; __u8 *udpdata; __be32 *udpdata32; __u16 encap_type = up->encap_type; /* if this is not encapsulated socket, then just return now */ if (!encap_type) return 1; /* If this is a paged skb, make sure we pull up * whatever data we need to look at. */ len = skb->len - sizeof(struct udphdr); if (!pskb_may_pull(skb, sizeof(struct udphdr) + min(len, 8))) return 1; /* Now we can get the pointers */ uh = udp_hdr(skb); udpdata = (__u8 *)(uh + 1); udpdata32 = (__be32 *)udpdata; switch (encap_type) { default: case UDP_ENCAP_ESPINUDP: KLIPS_PRINT(debug_rcv, "UDP_ENCAP_ESPINUDP_NON_IKE: len=%d 0x%x\n", len, udpdata32[0]); /* Check if this is a keepalive packet. If so, eat it. */ if (len == 1 && udpdata[0] == 0xff) { KLIPS_PRINT(debug_rcv, "UDP_ENCAP_ESPINUDP: keepalive packet detected\n"); goto drop; } else if (len > sizeof(struct ip_esp_hdr) && udpdata32[0] != 0) { KLIPS_PRINT(debug_rcv, "UDP_ENCAP_ESPINUDP: ESP IN UDP packet detected\n"); /* ESP Packet without Non-ESP header */ len = sizeof(struct udphdr); } else { /* Must be an IKE packet.. pass it through */ KLIPS_PRINT(debug_rcv, "UDP_ENCAP_ESPINUDP: IKE packet detected\n"); return 1; } break; case UDP_ENCAP_ESPINUDP_NON_IKE: KLIPS_PRINT(debug_rcv, "UDP_ENCAP_ESPINUDP_NON_IKE: len=%d 0x%x\n", len, udpdata32[0]); /* Check if this is a keepalive packet. If so, eat it. */ if (len == 1 && udpdata[0] == 0xff) { KLIPS_PRINT(debug_rcv, "UDP_ENCAP_ESPINUDP_NON_IKE: keepalive packet detected\n"); goto drop; } else if (len > 2 * sizeof(u32) + sizeof(struct ip_esp_hdr) && udpdata32[0] == 0 && udpdata32[1] == 0) { KLIPS_PRINT(debug_rcv, "UDP_ENCAP_ESPINUDP_NON_IKE: ESP IN UDP NON IKE packet detected\n"); /* ESP Packet with Non-IKE marker */ len = sizeof(struct udphdr) + 2 * sizeof(u32); } else { /* Must be an IKE packet.. pass it through */ KLIPS_PRINT(debug_rcv, "UDP_ENCAP_ESPINUDP_NON_IKE: IKE packet detected\n"); return 1; } break; } /* At this point we are sure that this is an ESPinUDP packet, * so we need to remove 'len' bytes from the packet (the UDP * header and optional ESP marker bytes) and then modify the * protocol to ESP, and then call into the transform receiver. */ if (skb_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) { KLIPS_PRINT(debug_rcv, "clone or expand problem\n"); goto drop; } /* Now we can update and verify the packet length... */ iph = ip_hdr(skb); iphlen = iph->ihl << 2; iph->tot_len = htons(ntohs(iph->tot_len) - len); if (skb->len < iphlen + len) { /* packet is too small!?! */ KLIPS_PRINT(debug_rcv, "packet too small\n"); goto drop; } /* pull the data buffer up to the ESP header and set the * transport header to point to ESP. Keep UDP on the stack * for later. */ __skb_pull(skb, len); skb_reset_transport_header(skb); /* modify the protocol (it's ESP!) */ iph->protocol = IPPROTO_ESP; /* process ESP */ KLIPS_PRINT(debug_rcv, "starting processing ESP packet\n"); ret = klips26_rcv_encap(skb, encap_type); return ret; drop: kfree_skb(skb); return 0; } int klips26_rcv_encap(struct sk_buff *skb, __u16 encap_type) { struct ipsec_rcv_state *irs = NULL; /* Don't unlink in the middle of a turnaround */ KLIPS_INC_USE; if (skb == NULL) { KLIPS_PRINT(debug_rcv, "klips_debug:klips26_rcv_encap: " "NULL skb passed in.\n"); goto rcvleave; } if (skb->data == NULL) { KLIPS_PRINT(debug_rcv, "klips_debug:klips26_rcv_encap: " "NULL skb->data passed in, packet is bogus, dropping.\n"); goto rcvleave; } irs = ipsec_rcv_state_new(); if (unlikely(!irs)) { KLIPS_PRINT(debug_rcv, "klips_debug:klips26_rcv_encap: " "failed to allocate a rcv state object\n"); goto rcvleave; } irs->hard_header_len = skb->dev->hard_header_len; switch (encap_type) { case UDP_ENCAP_ESPINUDP: irs->natt_type = ESPINUDP_WITH_NON_ESP; break; case UDP_ENCAP_ESPINUDP_NON_IKE: irs->natt_type = ESPINUDP_WITH_NON_IKE; break; default: if (printk_ratelimit()) { printk(KERN_INFO "KLIPS received unknown UDP-ESP encap type %u\n", encap_type); } goto rcvleave; } irs->skb = skb; /* * we hand off real early to the state machine because we just cannot * know how much processing it is off-loading */ ipsec_rsm(irs); return 0; rcvleave: if (irs) ipsec_rcv_state_delete(irs); if (skb) ipsec_kfree_skb(skb); KLIPS_DEC_USE; return 0; } #endif /* ------------------------------------------------------------------------ * this handles creating and managing state for recv path */ static DEFINE_SPINLOCK(irs_cache_lock); #ifdef HAVE_KMEM_CACHE_MACRO static struct kmem_cache *irs_cache_allocator = NULL; #else static kmem_cache_t *irs_cache_allocator = NULL; #endif static unsigned irs_cache_allocated_count = 0; int ipsec_irs_cache_allocated_max = 1000; module_param(ipsec_irs_cache_allocated_max, int, 0644); MODULE_PARM_DESC(ipsec_irs_cache_allocated_max, "Maximum outstanding receive packets (before they are dropped)"); int ipsec_rcv_state_cache_init(void) { if (irs_cache_allocator) return -EBUSY; spin_lock_init(&irs_cache_lock); #ifdef HAVE_KMEM_CACHE_MACRO irs_cache_allocator = KMEM_CACHE(ipsec_rcv_state, 0); #else irs_cache_allocator = kmem_cache_create("ipsec_irs", sizeof(struct ipsec_rcv_state), 0, 0, NULL, NULL); #endif if (!irs_cache_allocator) return -ENOMEM; return 0; } void ipsec_rcv_state_cache_cleanup(void) { if (unlikely(irs_cache_allocated_count)) printk("ipsec: deleting ipsec_irs kmem_cache while in use\n"); if (irs_cache_allocator) { kmem_cache_destroy(irs_cache_allocator); irs_cache_allocator = NULL; } irs_cache_allocated_count = 0; } static struct ipsec_rcv_state *ipsec_rcv_state_new(void) { struct ipsec_rcv_state *irs; spin_lock_bh(&irs_cache_lock); if (irs_cache_allocated_count >= ipsec_irs_cache_allocated_max) { spin_unlock_bh(&irs_cache_lock); KLIPS_PRINT(debug_rcv, "klips_debug:ipsec_rcv_state_new: " "exceeded maximum outstanding RX packet cnt %d\n", irs_cache_allocated_count); return NULL; } irs = kmem_cache_alloc(irs_cache_allocator, GFP_ATOMIC); if (likely(irs != NULL)) irs_cache_allocated_count++; spin_unlock_bh(&irs_cache_lock); if (unlikely(NULL == irs)) goto bail; /* initialize the object */ #if 1 memset((caddr_t)irs, 0, sizeof(*irs)); #else /* optimised to only clear the essentials */ irs->state = 0; irs->next_state = 0; irs->auth_checked = 0; irs->stats = NULL; irs->authenticator = NULL; irs->said.proto = 0; irs->hard_header_len = 0; irs->natt_type = 0; irs->natt_len = 0; irs->lastipsp = NULL; irs->ipsp = NULL; #endif bail: return irs; } static void ipsec_rcv_state_delete(struct ipsec_rcv_state *irs) { if (unlikely(!irs)) return; spin_lock_bh(&irs_cache_lock); irs_cache_allocated_count--; kmem_cache_free(irs_cache_allocator, irs); spin_unlock_bh(&irs_cache_lock); } libreswan-3.32/linux/net/ipsec/ipsec_sa.c000066400000000000000000001250551365625662500204410ustar00rootroot00000000000000/* * Common routines for IPsec SA maintenance routines. * * Copyright (C) 1996, 1997 John Ioannidis. * Copyright (C) 1998, 1999, 2000, 2001, 2002 Richard Guy Briggs. * Copyright (C) 2012 Paul Wouters * Copyright (C) 2012 David McCullough * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * This is the file formerly known as "ipsec_xform.h" * */ #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38) && \ !defined(AUTOCONF_INCLUDED) #include #endif #include /* printk() */ #include "libreswan/ipsec_param.h" #include /* kmalloc() */ #include /* vmalloc() */ #include /* error codes */ #include /* size_t */ #include /* mark_bh */ #include /* struct device, and other headers */ #include /* eth_type_trans */ #include /* struct iphdr */ #include #include #include /* *lock* */ #include #include "libreswan/radij.h" #include "libreswan/ipsec_stats.h" #include "libreswan/ipsec_life.h" #include "libreswan/ipsec_sa.h" #include "libreswan/ipsec_xform.h" #include "libreswan/ipsec_encap.h" #include "libreswan/ipsec_radij.h" #include "libreswan/ipsec_xform.h" #include "libreswan/ipsec_ipe4.h" #include "libreswan/ipsec_ah.h" #include "libreswan/ipsec_esp.h" #include "libreswan/ipsec_ipip.h" #ifdef CONFIG_KLIPS_IPCOMP #include "libreswan/ipsec_ipcomp.h" #endif /* CONFIG_KLIPS_COMP */ #include #include #include "libreswan/ipsec_proto.h" #include "libreswan/ipsec_alg.h" #ifdef CONFIG_KLIPS_OCF # include "ipsec_ocf.h" #endif #define SENDERR(_x) do { error = -(_x); goto errlab; } while (0) struct ipsec_sa *ipsec_sadb_hash[SADB_HASHMOD]; DEFINE_SPINLOCK(tdb_lock); #ifdef IPSEC_SA_RECOUNT_DEBUG struct ipsec_sa *ipsec_sa_raw = NULL; #endif struct ipsec_sadb ipsec_sadb; /* the sub table must be narrower (or equal) in bits than the variable type in the main table to count the number of unused entries in it. */ typedef struct { /* kind of compile-time, but not preprocessor time, assertion */ int testSizeOf_refSubTable : ((sizeof(IPsecRefTableUnusedCount) * 8) < IPSEC_SA_REF_SUBTABLE_IDX_WIDTH ? -1 : 1); } dummy; /* The field where the saref will be hosted in the skb must be wide enough to accommodate the information it needs to store. */ typedef struct { /* kind of compile-time, but not preprocessor time, assertion */ int testSizeOf_refField : (IPSEC_SA_REF_HOST_FIELD_WIDTH < IPSEC_SA_REF_TABLE_IDX_WIDTH ? -1 : 1 ); } dummy2; #define IPS_HASH(said) (((said)->spi + (said)->dst.u.v4.sin_addr.s_addr + \ (said)->proto) % SADB_HASHMOD) static int ipsec_saref_verify_slot(IPsecSAref_t ref); static int ipsec_SArefSubTable_alloc(unsigned table); static int ipsec_saref_freelist_init(void); static IPsecSAref_t ipsec_SAref_alloc(int *error); /* pass in error var by pointer */ static int ipsec_SAref_recycle(void) { int table, i; int error = 0; int entry; int addone; ipsec_sadb.refFreeListHead = IPSEC_SAREF_NULL; ipsec_sadb.refFreeListTail = IPSEC_SAREF_NULL; KLIPS_PRINT(debug_xform, "klips_debug:ipsec_SAref_recycle: " "recycling, continuing from SAref=%d (0p%p), table=%d, entry=%d.\n", ipsec_sadb.refFreeListCont, (ipsec_sadb.refTable[IPsecSAref2table(ipsec_sadb. refFreeListCont)] != NULL) ? IPsecSAref2SA(ipsec_sadb.refFreeListCont) : NULL, IPsecSAref2table(ipsec_sadb.refFreeListCont), IPsecSAref2entry(ipsec_sadb.refFreeListCont)); /* add one additional table entry */ addone = 0; for (i = 0; i < IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES; i++) { if (ipsec_sadb.refFreeListCont == IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES * IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES) { KLIPS_PRINT(debug_xform, "klips_debug:ipsec_SAref_recycle: " "end of table reached, continuing at start..\n"); ipsec_sadb.refFreeListCont = IPSEC_SAREF_FIRST; } table = IPsecSAref2table(ipsec_sadb.refFreeListCont); if (ipsec_sadb.refTable[table] == NULL) { if (addone == 0) { addone = 1; error = ipsec_SArefSubTable_alloc(table); if (error) return error; else break; } } for (entry = IPsecSAref2entry(ipsec_sadb.refFreeListCont); entry < IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES; entry++) { if (ipsec_sadb.refTable[table]->entry[entry] == NULL) { ipsec_sadb.refFreeList[++ipsec_sadb. refFreeListTail] = IPsecSArefBuild(table, entry); if (ipsec_sadb.refFreeListTail == (IPSEC_SA_REF_FREELIST_NUM_ENTRIES - 1)) { ipsec_sadb.refFreeListHead = IPSEC_SAREF_FIRST; ipsec_sadb.refFreeListCont = ipsec_sadb.refFreeList[ ipsec_sadb. refFreeListTail ] + 1; KLIPS_PRINT(debug_xform, "klips_debug:ipsec_SAref_recycle: " "SArefFreeList refilled.\n"); return 0; } } ipsec_sadb.refFreeListCont++; } } if (ipsec_sadb.refFreeListTail == IPSEC_SAREF_NULL) { KLIPS_PRINT(debug_xform, "klips_debug:ipsec_SAref_recycle: " "out of room in the SArefTable.\n"); return -ENOSPC; } ipsec_sadb.refFreeListHead = IPSEC_SAREF_FIRST; ipsec_sadb.refFreeListCont = ipsec_sadb.refFreeList[ipsec_sadb.refFreeListTail] + 1; KLIPS_PRINT(debug_xform, "klips_debug:ipsec_SAref_recycle: " "SArefFreeList partly refilled to %d of %d.\n", ipsec_sadb.refFreeListTail, IPSEC_SA_REF_FREELIST_NUM_ENTRIES); return 0; } static int ipsec_SArefSubTable_alloc(unsigned table) { unsigned entry; struct IPsecSArefSubTable *SArefsub; KLIPS_PRINT(debug_xform, "klips_debug:ipsec_SArefSubTable_alloc: " "allocating %zu bytes for table %u of %u.\n", IPSEC_SA_REF_SUBTABLE_SIZE, table, IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES); /* allocate another sub-table */ SArefsub = kmalloc(IPSEC_SA_REF_SUBTABLE_SIZE, GFP_ATOMIC); if (SArefsub == NULL) { KLIPS_PRINT(debug_xform, "klips_debug:ipsec_SArefSubTable_alloc: " "error allocating memory for table %u of %u!\n", table, IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES); return -ENOMEM; } /* add this sub-table to the main table */ ipsec_sadb.refTable[table] = SArefsub; /* initialise each element to NULL */ KLIPS_PRINT(debug_xform, "klips_debug:ipsec_SArefSubTable_alloc: " "initialising %u elements (2 ^ %u) of table %u.\n", IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES, IPSEC_SA_REF_SUBTABLE_IDX_WIDTH, table); for (entry = 0; entry < IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES; entry++) SArefsub->entry[entry] = NULL; return 0; } static int ipsec_saref_verify_slot(IPsecSAref_t ref) { int ref_table = IPsecSAref2table(ref); if (ipsec_sadb.refTable[ref_table] == NULL) return ipsec_SArefSubTable_alloc(ref_table); return 0; } int ipsec_saref_freelist_init(void) { int i; KLIPS_PRINT(debug_xform, "klips_debug:ipsec_saref_freelist_init: " "initialising %u elements of FreeList.\n", IPSEC_SA_REF_FREELIST_NUM_ENTRIES); for (i = 0; i < IPSEC_SA_REF_FREELIST_NUM_ENTRIES; i++) ipsec_sadb.refFreeList[i] = IPSEC_SAREF_NULL; ipsec_sadb.refFreeListHead = IPSEC_SAREF_NULL; ipsec_sadb.refFreeListCont = IPSEC_SAREF_FIRST; ipsec_sadb.refFreeListTail = IPSEC_SAREF_NULL; return 0; } int ipsec_sadb_init(void) { int error = 0; unsigned i; for (i = 0; i < SADB_HASHMOD; i++) ipsec_sadb_hash[i] = NULL; /* parts above are for the old style SADB hash table */ /* initialise SA reference table */ /* initialise the main table */ KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sadb_init: " "initialising main table of size %u (2 ^ %u).\n", IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES, IPSEC_SA_REF_MAINTABLE_IDX_WIDTH); { unsigned table; for (table = 0; table < IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES; table++) ipsec_sadb.refTable[table] = NULL; } /* allocate the first sub-table */ error = ipsec_SArefSubTable_alloc(0); if (error) return error; error = ipsec_saref_freelist_init(); return error; } static IPsecSAref_t ipsec_SAref_alloc(int *error) /* pass in error var by pointer */ { IPsecSAref_t SAref; KLIPS_PRINT(debug_xform, "ipsec_SAref_alloc: " "SAref requested... head=%d, cont=%d, tail=%d, listsize=%d.\n", ipsec_sadb.refFreeListHead, ipsec_sadb.refFreeListCont, ipsec_sadb.refFreeListTail, IPSEC_SA_REF_FREELIST_NUM_ENTRIES); if (ipsec_sadb.refFreeListHead == IPSEC_SAREF_NULL) { KLIPS_PRINT(debug_xform, "ipsec_SAref_alloc: " "FreeList empty, recycling...\n"); *error = ipsec_SAref_recycle(); if (*error) return IPSEC_SAREF_NULL; } SAref = ipsec_sadb.refFreeList[ipsec_sadb.refFreeListHead]; if (SAref == IPSEC_SAREF_NULL) { KLIPS_ERROR(debug_xform, "ipsec_SAref_alloc: " "unexpected error, refFreeListHead = %d points to invalid entry.\n", ipsec_sadb.refFreeListHead); *error = -ESPIPE; return IPSEC_SAREF_NULL; } KLIPS_PRINT(debug_xform, "ipsec_SAref_alloc: " "allocating SAref=%d, table=%u, entry=%u of %u.\n", SAref, IPsecSAref2table(SAref), IPsecSAref2entry(SAref), IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES * IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES); ipsec_sadb.refFreeList[ipsec_sadb.refFreeListHead] = IPSEC_SAREF_NULL; ipsec_sadb.refFreeListHead++; if (ipsec_sadb.refFreeListHead > ipsec_sadb.refFreeListTail) { KLIPS_PRINT(debug_xform, "ipsec_SAref_alloc: " "last FreeList entry allocated, resetting list head to empty.\n"); ipsec_sadb.refFreeListHead = IPSEC_SAREF_NULL; } return SAref; } #if 0 int ipsec_sa_print(struct ipsec_sa *ips) { char sa[SATOT_BUF]; size_t sa_len; printk(KERN_INFO "klips_debug: SA:"); if (ips == NULL) { printk("NULL\n"); return -ENOENT; } printk(" ref=%d", ips->ips_ref); printk(" refcount=%d", atomic_read(&ips->ips_refcount)); if (ips->ips_hnext != NULL) printk(" hnext=0p%p", ips->ips_hnext); if (ips->ips_next != NULL) printk(" next=0p%p", ips->ips_next); if (ips->ips_prev != NULL) printk(" prev=0p%p", ips->ips_prev); sa_len = KLIPS_SATOT(1, &ips->ips_said, 0, sa, sizeof(sa)); printk(" said=%s", sa_len ? sa : " (error)"); if (ips->ips_seq) printk(" seq=%u", ips->ips_seq); if (ips->ips_pid) printk(" pid=%u", ips->ips_pid); if (ips->ips_authalg) printk(" authalg=%u", ips->ips_authalg); if (ips->ips_encalg) printk(" encalg=%u", ips->ips_encalg); printk(" XFORM=%s%s%s", IPS_XFORM_NAME(ips)); if (ips->ips_replaywin) printk(" ooowin=%u", ips->ips_replaywin); if (ips->ips_flags) printk(" flags=%u", ips->ips_flags); if (ips->ips_addr_s) { char buf[SUBNETTOA_BUF]; sin_addrtot(ips->ips_addr_s, 0, buf, sizeof(buf)); printk(" src=%s", buf); } if (ips->ips_addr_d) { char buf[SUBNETTOA_BUF]; sin_addrtot(ips->ips_addr_s, 0, buf, sizeof(buf)); printk(" dst=%s", buf); } if (ips->ips_addr_p) { char buf[SUBNETTOA_BUF]; sin_addrtot(ips->ips_addr_p, 0, buf, sizeof(buf)); printk(" proxy=%s", buf); } if (ips->ips_key_bits_a) printk(" key_bits_a=%u", ips->ips_key_bits_a); if (ips->ips_key_bits_e) printk(" key_bits_e=%u", ips->ips_key_bits_e); printk("\n"); return 0; } #endif struct ipsec_sa*ipsec_sa_alloc(int *error) /* pass in error var by pointer */ { struct ipsec_sa *ips; if ((ips = kmalloc(sizeof(*ips), GFP_ATOMIC) ) == NULL) { KLIPS_PRINT(debug_xform, "ipsec_sa_alloc: " "memory allocation error\n"); *error = -ENOMEM; return NULL; } memset((caddr_t)ips, 0, sizeof(*ips)); #ifdef IPSEC_SA_RECOUNT_DEBUG ips->ips_raw = ipsec_sa_raw; ipsec_sa_raw = ips; #endif /* return with at least counter = 1 */ ipsec_sa_get(ips, IPSEC_REFALLOC); *error = 0; return ips; } void ipsec_sa_untern(struct ipsec_sa *ips) { IPsecSAref_t ref = ips->ips_ref; int error; /* verify that we are removing correct item! */ error = ipsec_saref_verify_slot(ref); if (error) return; if (IPsecSAref2SA(ref) == ips) { IPsecSAref2SA(ref) = NULL; ipsec_sa_put(ips, IPSEC_REFINTERN); } else { KLIPS_PRINT(debug_xform, "ipsec_sa_untern: " "ref=%u -> %p but untern'ing %p\n", ref, IPsecSAref2SA(ref), ips); } } int ipsec_sa_intern(struct ipsec_sa *ips) { int error = 0; IPsecSAref_t ref = ips->ips_ref; if (ref == IPSEC_SAREF_NULL) { ref = ipsec_SAref_alloc(&error); /* pass in error return by pointer */ KLIPS_PRINT(debug_xform, "ipsec_sa_intern: " "allocated ref=%u for sa %p\n", ref, ips); if (ref == IPSEC_SAREF_NULL) { KLIPS_PRINT(debug_xform, "ipsec_sa_intern: " "SAref allocation error\n"); return error; } ips->ips_ref = ref; } error = ipsec_saref_verify_slot(ref); if (error) return error; ipsec_sa_get(ips, IPSEC_REFINTERN); /* * if there is an existing SA at this reference, then free it * note, that nsa might == ips!. That's okay, we just incremented * the reference count above. */ { struct ipsec_sa *nsa = IPsecSAref2SA(ref); if (nsa) ipsec_sa_put(nsa, IPSEC_REFINTERN); } KLIPS_PRINT(debug_xform, "ipsec_sa_intern: " "SAref[%d]=%p\n", ips->ips_ref, ips); IPsecSAref2SA(ips->ips_ref) = ips; /* return OK */ return 0; } struct ipsec_sa *ipsec_sa_getbyid(ip_said *said, int type) { int hashval; struct ipsec_sa *ips; char sa[SATOT_BUF]; size_t sa_len; if (said == NULL) { KLIPS_PRINT(debug_xform, "ipsec_sa_getbyid: " "null pointer passed in!\n"); return NULL; } hashval = IPS_HASH(said); sa_len = KLIPS_SATOT(debug_xform, said, 0, sa, sizeof(sa)); KLIPS_PRINT(debug_xform, "ipsec_sa_getbyid: " "linked entry in ipsec_sa table for hash=%d of SA:%s requested.\n", hashval, sa_len ? sa : " (error)"); if ((ips = ipsec_sadb_hash[hashval]) == NULL) { KLIPS_PRINT(debug_xform, "ipsec_sa_getbyid: " "no entries in ipsec_sa table for hash=%d of SA:%s.\n", hashval, sa_len ? sa : " (error)"); return NULL; } for (; ips; ips = ips->ips_hnext) { if (ips->ips_said.spi == said->spi && ip_address_eq(&ips->ips_said.dst, &said->dst) && ips->ips_said.proto == said->proto) { ipsec_sa_get(ips, type); return ips; } } KLIPS_PRINT(debug_xform, "ipsec_sa_getbyid: " "no entry in linked list for hash=%d of SA:%s.\n", hashval, sa_len ? sa : " (error)"); return NULL; } struct ipsec_sa *ipsec_sa_getbyref(IPsecSAref_t ref, int type) { struct ipsec_sa *ips; struct IPsecSArefSubTable *st = ipsec_sadb.refTable[IPsecSAref2table(ref)]; if (st == NULL) return NULL; ips = st->entry[IPsecSAref2entry(ref)]; if (ips) ipsec_sa_get(ips, type); return ips; } void __ipsec_sa_put(struct ipsec_sa *ips, const char *func, int line, int type) { if (ips == NULL) { KLIPS_PRINT(debug_xform, "ipsec_sa_put: " "null pointer passed in!\n"); return; } if (debug_xform) { char sa[SATOT_BUF]; size_t sa_len; sa_len = KLIPS_SATOT(debug_xform, &ips->ips_said, 0, sa, sizeof(sa)); KLIPS_PRINT(debug_xform, "ipsec_sa_put: " "ipsec_sa %p SA:%s, ref:%d reference count (%d--) decremented by %s:%d.\n", ips, sa_len ? sa : " (error)", ips->ips_ref, atomic_read(&ips->ips_refcount), func, line); } #ifdef IPSEC_SA_RECOUNT_DEBUG if (type >= 0 && type < sizeof(ips->ips_track)) { unsigned long flags; local_irq_save(flags); if (ips->ips_track[type] == 0) printk("ipsec_sa_put: UNDERFLOW for %d @ %s %d\n", type, func, line); else ips->ips_track[type]--; local_irq_restore(flags); } else { printk("BAD BAD BAD @ %s %d\n", func, line); } #endif if (atomic_dec_and_test(&ips->ips_refcount)) { KLIPS_PRINT(debug_xform, "ipsec_sa_put: freeing %p\n", ips); /* it was zero */ ipsec_sa_wipe(ips); } } struct ipsec_sa *__ipsec_sa_get(struct ipsec_sa *ips, const char *func, int line, int type) { if (ips == NULL) return NULL; if (debug_xform) { char sa[SATOT_BUF]; size_t sa_len; sa_len = KLIPS_SATOT(debug_xform, &ips->ips_said, 0, sa, sizeof(sa)); KLIPS_PRINT(debug_xform, "ipsec_sa_get: " "ipsec_sa %p SA:%s, ref:%d reference count (%d++) incremented by %s:%d.\n", ips, sa_len ? sa : " (error)", ips->ips_ref, atomic_read(&ips->ips_refcount), func, line); } atomic_inc(&ips->ips_refcount); #ifdef IPSEC_SA_RECOUNT_DEBUG if (type >= 0 && type < sizeof(ips->ips_track)) { unsigned long flags; local_irq_save(flags); if (ips->ips_track[type] == 255) printk("ipsec_sa_get: OVERFLOW for %d @ %s %d\n", type, func, line); else ips->ips_track[type]++; local_irq_restore(flags); } else { printk("BAD BAD BAD @ %s %d\n", func, line); } #endif #if 0 /* * DAVIDM: if we include this code it means the SA is freed immediately * on creation and then reused ! Not sure why it is here. */ if (atomic_dec_and_test(&ips->ips_refcount)) { KLIPS_PRINT(debug_xform, "ipsec_sa_get: freeing %p\n", ips); /* it was zero */ ipsec_sa_wipe(ips); } #endif return ips; } /* The ipsec_sa table better *NOT* be locked before it is handed in, or SMP locks will happen */ int ipsec_sa_add(struct ipsec_sa *ips) { int error = 0; unsigned int hashval; if (ips == NULL) { KLIPS_PRINT(debug_xform, "klips_error:ipsec_sa_add: " "null pointer passed in!\n"); return -ENODATA; } hashval = IPS_HASH(&ips->ips_said); ipsec_sa_get(ips, IPSEC_REFSAADD); spin_lock_bh(&tdb_lock); ips->ips_hnext = ipsec_sadb_hash[hashval]; ipsec_sadb_hash[hashval] = ips; spin_unlock_bh(&tdb_lock); return error; } /* * remove it from the hash chain, decrementing hash count */ void ipsec_sa_rm(struct ipsec_sa *ips) { unsigned int hashval; char sa[SATOT_BUF]; size_t sa_len; if (ips == NULL) return; hashval = IPS_HASH(&ips->ips_said); sa_len = KLIPS_SATOT(debug_xform, &ips->ips_said, 0, sa, sizeof(sa)); KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sa_del: " "unhashing SA:%s (ref=%u), hashval=%d.\n", sa_len ? sa : " (error)", ips->ips_ref, hashval); if (ipsec_sadb_hash[hashval] == NULL) return; if (ips == ipsec_sadb_hash[hashval]) { ipsec_sadb_hash[hashval] = ipsec_sadb_hash[hashval]->ips_hnext; ips->ips_hnext = NULL; ipsec_sa_put(ips, IPSEC_REFSAADD); KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sa_del: " "successfully unhashed first ipsec_sa in chain.\n"); return; } else { struct ipsec_sa *ipstp; for (ipstp = ipsec_sadb_hash[hashval]; ipstp; ipstp = ipstp->ips_hnext) { if (ipstp->ips_hnext == ips) { ipstp->ips_hnext = ips->ips_hnext; ips->ips_hnext = NULL; ipsec_sa_put(ips, IPSEC_REFSAADD); KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sa_del: " "successfully unhashed link in ipsec_sa chain.\n"); return; } } } } #if 0 /* * The ipsec_sa table better be locked before it is handed in, * or races might happen. * * this routine assumes the SA has a refcount==0, and we free it. * we also assume that the pointers are already cleaned up. */ static int ipsec_sa_del(struct ipsec_sa *ips) { unsigned int hashval; struct ipsec_sa *ipstp; char sa[SATOT_BUF]; size_t sa_len; if (ips == NULL) { KLIPS_ERROR(debug_xform, "klips_error:ipsec_sa_del: " "null pointer passed in!\n"); return -ENODATA; } if (ips->ips_next) { struct ipsec_sa *in = ips->ips_next; ips->ips_next = NULL; ipsec_sa_put(in); } sa_len = KLIPS_SATOT(debug_xform, &ips->ips_said, 0, sa, sizeof(sa)); hashval = IPS_HASH(&ips->ips_said); KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sa_del: " "deleting SA:%s (ref=%u), hashval=%d.\n", sa_len ? sa : " (error)", ips->ips_ref, hashval); if (ipsec_sadb_hash[hashval] == NULL) { /* if this is NULL, then we can be sure that the SA was never * added to the SADB, so we just free it. */ KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sa_del: " "no entries in ipsec_sa table for hash=%d (ref=%u) of SA:%s.\n", hashval, ips->ips_ref, sa_len ? sa : " (error)"); return -ENOENT; } if (ips == ipsec_sadb_hash[hashval]) { ipsec_sadb_hash[hashval] = ipsec_sadb_hash[hashval]->ips_hnext; ips->ips_hnext = NULL; ipsec_sa_put(ips); KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sa_del: " "successfully deleted first ipsec_sa in chain.\n"); return 0; } else { for (ipstp = ipsec_sadb_hash[hashval]; ipstp; ipstp = ipstp->ips_hnext) { if (ipstp->ips_hnext == ips) { ipstp->ips_hnext = ips->ips_hnext; ips->ips_hnext = NULL; ipsec_sa_put(ips); KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sa_del: " "successfully deleted link in ipsec_sa chain.\n"); return 0; } } } KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sa_del: " "no entries in linked list for hash=%d of SA:%s.\n", hashval, sa_len ? sa : " (error)"); return -ENOENT; } #endif int ipsec_sadb_cleanup(__u8 proto) { unsigned i; int error = 0; struct ipsec_sa *ips; /* struct ipsec_sa *ipsnext, **ipsprev; */ /* char sa[SATOT_BUF]; */ /* size_t sa_len; */ KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sadb_cleanup: " "cleaning up proto=%d.\n", proto); spin_lock_bh(&tdb_lock); for (i = 0; i < SADB_HASHMOD; i++) { ips = ipsec_sadb_hash[i]; while (ips) { ipsec_sadb_hash[i] = ips->ips_hnext; ips->ips_hnext = NULL; ipsec_sa_put(ips, IPSEC_REFSAADD); ips = ipsec_sadb_hash[i]; } } /* errlab: */ spin_unlock_bh(&tdb_lock); #if IPSEC_SA_REF_CODE /* clean up SA reference table */ /* go through the ref table and clean out all the SAs */ KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sadb_cleanup: " "removing SAref entries and tables."); { unsigned table, entry; for (table = 0; table < IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES; table++) { KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sadb_cleanup: " "cleaning SAref table=%u.\n", table); if (ipsec_sadb.refTable[table] == NULL) { printk("\n"); KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sadb_cleanup: " "cleaned %u used refTables.\n", table); break; } for (entry = 0; entry < IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES; entry++) { if (ipsec_sadb.refTable[table]->entry[entry] != NULL) { struct ipsec_sa *sa1 = ipsec_sadb.refTable[table]-> entry[entry]; ipsec_sa_put(sa1, IPSEC_REFOTHER); ipsec_sadb.refTable[table]->entry[entry ] = NULL; } } } } #endif /* IPSEC_SA_REF_CODE */ return error; } int ipsec_sadb_free(void) { int error = 0; KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sadb_free: " "freeing SArefTable memory.\n"); /* clean up SA reference table */ /* go through the ref table and clean out all the SAs if any are left and free table memory */ KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sadb_free: " "removing SAref entries and tables.\n"); { unsigned table, entry; for (table = 0; table < IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES; table++) { KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sadb_free: " "removing SAref table=%u.\n", table); if (ipsec_sadb.refTable[table] == NULL) { KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sadb_free: " "removed %u used refTables.\n", table); break; } for (entry = 0; entry < IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES; entry++) { if (ipsec_sadb.refTable[table]->entry[entry] != NULL) { struct ipsec_sa *sa1 = ipsec_sadb.refTable[table]-> entry[entry]; BUG_ON(atomic_read(&sa1->ips_refcount) == 1); ipsec_sa_put(sa1, IPSEC_REFSAADD); ipsec_sadb.refTable[table]->entry[entry] = NULL; } } kfree(ipsec_sadb.refTable[table]); ipsec_sadb.refTable[table] = NULL; } } return error; } int ipsec_sa_wipe(struct ipsec_sa *ips) { int hashval; struct ipsec_sa **tpp; if (ips == NULL) return -ENODATA; #if IPSEC_SA_REF_CODE /* remove me from the SArefTable */ if (debug_xform) { char sa[SATOT_BUF]; size_t sa_len; struct IPsecSArefSubTable *subtable = NULL; if (IPsecSAref2table(IPsecSA2SAref(ips)) < IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES && ipsec_sadb.refTable != NULL) subtable = ipsec_sadb.refTable[ IPsecSAref2table(IPsecSA2SAref(ips))]; sa_len = KLIPS_SATOT(debug_xform, &ips->ips_said, 0, sa, sizeof(sa)); KLIPS_PRINT(debug_xform, "klips_debug:ipsec_sa_wipe: " "removing SA=%s(0p%p), SAref=%d, table=%d(0p%p), entry=%d from the refTable.\n", sa_len ? sa : " (error)", ips, ips->ips_ref, IPsecSAref2table(IPsecSA2SAref(ips)), subtable, subtable ? IPsecSAref2entry(IPsecSA2SAref(ips)) : 0); } if (ips->ips_ref != IPSEC_SAREF_NULL) { struct IPsecSArefSubTable *subtable = NULL; int ref_table = IPsecSAref2table(IPsecSA2SAref(ips)); int ref_entry = IPsecSAref2entry(IPsecSA2SAref(ips)); if (ref_table < IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES) { subtable = ipsec_sadb.refTable[ref_table]; if (subtable != NULL && subtable->entry[ref_entry] == ips) { subtable->entry[ref_entry] = NULL; } } ips->ips_ref = IPSEC_SAREF_NULL; } #endif /* IPSEC_SA_REF_CODE */ /* paranoid clean up */ if (ips->ips_addr_s != NULL) { memset((caddr_t)(ips->ips_addr_s), 0, ips->ips_addr_s_size); kfree(ips->ips_addr_s); } ips->ips_addr_s = NULL; if (ips->ips_addr_d != NULL) { memset((caddr_t)(ips->ips_addr_d), 0, ips->ips_addr_d_size); kfree(ips->ips_addr_d); } ips->ips_addr_d = NULL; if (ips->ips_addr_p != NULL) { memset((caddr_t)(ips->ips_addr_p), 0, ips->ips_addr_p_size); kfree(ips->ips_addr_p); } ips->ips_addr_p = NULL; if (ips->ips_natt_oa) { memset((caddr_t)(ips->ips_natt_oa), 0, ips->ips_natt_oa_size); kfree(ips->ips_natt_oa); } ips->ips_natt_oa = NULL; if (ips->ips_key_a != NULL) { #ifdef CONFIG_KLIPS_ALG if (ips->ips_alg_auth && ips->ips_alg_auth->ixt_a_destroy_key) { ips->ips_alg_auth->ixt_a_destroy_key(ips->ips_alg_auth, ips->ips_key_a); } else #endif { memset((caddr_t)(ips->ips_key_a), 0, ips->ips_key_a_size); kfree(ips->ips_key_a); } } ips->ips_key_a = NULL; if (ips->ips_key_e != NULL) { #ifdef CONFIG_KLIPS_ALG if (ips->ips_alg_enc && ips->ips_alg_enc->ixt_e_destroy_key) { ips->ips_alg_enc->ixt_e_destroy_key(ips->ips_alg_enc, ips->ips_key_e); } else #endif { memset((caddr_t)(ips->ips_key_e), 0, ips->ips_key_e_size); kfree(ips->ips_key_e); } } ips->ips_key_e = NULL; if (ips->ips_iv != NULL) { memset((caddr_t)(ips->ips_iv), 0, ips->ips_iv_size); kfree(ips->ips_iv); } ips->ips_iv = NULL; #ifdef CONFIG_KLIPS_OCF if (ips->ocf_in_use) ipsec_ocf_sa_free(ips); #endif if (ips->ips_ident_s.data != NULL) { memset((caddr_t)(ips->ips_ident_s.data), 0, ips->ips_ident_s.len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident)); kfree(ips->ips_ident_s.data); } ips->ips_ident_s.data = NULL; if (ips->ips_ident_d.data != NULL) { memset((caddr_t)(ips->ips_ident_d.data), 0, ips->ips_ident_d.len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident)); kfree(ips->ips_ident_d.data); } ips->ips_ident_d.data = NULL; #ifdef CONFIG_KLIPS_ALG if (ips->ips_alg_enc || ips->ips_alg_auth) ipsec_alg_sa_wipe(ips); ips->ips_alg_enc = NULL; ips->ips_alg_auth = NULL; #endif if (ips->ips_prev) ips->ips_prev->ips_next = ips->ips_next; if (ips->ips_next) { ips->ips_next->ips_prev = ips->ips_prev; ipsec_sa_put(ips->ips_next, IPSEC_REFALLOC); } ips->ips_next = NULL; ips->ips_prev = NULL; hashval = IPS_HASH(&ips->ips_said); tpp = &ipsec_sadb_hash[hashval]; while (*tpp) { if (*tpp == ips) *tpp = ips->ips_hnext; else tpp = &((*tpp)->ips_hnext); } if (ips->ips_hnext) ipsec_sa_put(ips->ips_hnext, IPSEC_REFALLOC); ips->ips_hnext = NULL; BUG_ON(atomic_read(&ips->ips_refcount) != 0); #ifdef IPSEC_SA_RECOUNT_DEBUG if (ips == ipsec_sa_raw) { ipsec_sa_raw = ips->ips_raw; } else { struct ipsec_sa *raw = ipsec_sa_raw; while (raw) { if (raw->ips_raw == ips) { raw->ips_raw = ips->ips_raw; break; } raw = raw->ips_raw; } } #endif if (ips->ips_out != NULL) { ipsec_dev_put(ips->ips_out); ips->ips_out = NULL; } memset((caddr_t)ips, 0, sizeof(*ips)); kfree(ips); ips = NULL; return 0; } extern int sysctl_ipsec_debug_verbose; int ipsec_sa_init(struct ipsec_sa *ipsp) { int error = 0; char sa[SATOT_BUF]; size_t sa_len; #ifdef CONFIG_KLIPS_DEBUG char ipaddr_txt[ADDRTOA_BUF]; char ipaddr2_txt[ADDRTOA_BUF]; #endif #if defined (CONFIG_KLIPS_AUTH_HMAC_MD5) || \ defined (CONFIG_KLIPS_AUTH_HMAC_SHA1) unsigned char kb[AHMD596_BLKLEN]; int i; #endif if (ipsp == NULL) { KLIPS_PRINT(debug_pfkey, "ipsec_sa_init: " "ipsp is NULL, fatal\n"); SENDERR(EINVAL); } sa_len = KLIPS_SATOT(debug_pfkey, &ipsp->ips_said, 0, sa, sizeof(sa)); KLIPS_PRINT(debug_pfkey, "ipsec_sa_init: " "(pfkey defined) called for SA:%s\n", sa_len ? sa : " (error)"); KLIPS_PRINT(debug_pfkey, "ipsec_sa_init: " "calling init routine of %s%s%s\n", IPS_XFORM_NAME(ipsp)); switch (ipsp->ips_said.proto) { #ifdef CONFIG_KLIPS_IPIP case IPPROTO_IPIP: { ipsp->ips_xformfuncs = ipip_xform_funcs; #ifdef CONFIG_KLIPS_DEBUG sin_addrtot(ipsp->ips_addr_s, 0, ipaddr_txt, sizeof(ipaddr_txt)); sin_addrtot(ipsp->ips_addr_d, 0, ipaddr2_txt, sizeof(ipaddr2_txt)); KLIPS_PRINT(debug_pfkey, "ipsec_sa_init: " "(pfkey defined) IPIP ipsec_sa set for %s->%s.\n", ipaddr_txt, ipaddr2_txt); #endif } break; #endif /* !CONFIG_KLIPS_IPIP */ #ifdef CONFIG_KLIPS_AH case IPPROTO_AH: ipsp->ips_xformfuncs = ah_xform_funcs; #ifdef CONFIG_KLIPS_OCF if (ipsec_ocf_sa_init(ipsp, ipsp->ips_authalg, 0)) break; #endif #ifdef CONFIG_KLIPS_ALG error = ipsec_alg_auth_key_create(ipsp); if ((error < 0) && (error != -EPROTO)) SENDERR(-error); if (error == -EPROTO) { /* perform manual key generation, ignore this particular error */ error = 0; #endif /* CONFIG_KLIPS_ALG */ switch (ipsp->ips_authalg) { # ifdef CONFIG_KLIPS_AUTH_HMAC_MD5 case AH_MD5: { unsigned char *akp; unsigned int aks; MD5_CTX *ictx; MD5_CTX *octx; if (ipsp->ips_key_bits_a != (AHMD596_KLEN * 8)) { KLIPS_PRINT(debug_pfkey, "ipsec_sa_init: " "incorrect key size: %d bits -- must be %d bits\n" /*octets (bytes)\n"*/, ipsp->ips_key_bits_a, AHMD596_KLEN * 8); SENDERR(EINVAL); } # if KLIPS_DIVULGE_HMAC_KEY KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "hmac md5-96 key is 0x%08x %08x %08x %08x\n", ntohl(*(((__u32 *)ipsp->ips_key_a) + 0)), ntohl(*(((__u32 *)ipsp->ips_key_a) + 1)), ntohl(*(((__u32 *)ipsp->ips_key_a) + 2)), ntohl(*(((__u32 *)ipsp->ips_key_a) + 3))); # endif /* KLIPS_DIVULGE_HMAC_KEY */ ipsp->ips_auth_bits = AHMD596_ALEN * 8; /* save the pointer to the key material */ akp = ipsp->ips_key_a; aks = ipsp->ips_key_a_size; KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "allocating %zu bytes for md5_ctx.\n", sizeof(struct md5_ctx)); if ((ipsp->ips_key_a = (caddr_t) kmalloc(sizeof(struct md5_ctx), GFP_ATOMIC)) == NULL) { ipsp->ips_key_a = akp; SENDERR(ENOMEM); } ipsp->ips_key_a_size = sizeof(struct md5_ctx); for (i = 0; i < DIVUP(ipsp->ips_key_bits_a, 8); i++) kb[i] = akp[i] ^ HMAC_IPAD; for (; i < AHMD596_BLKLEN; i++) kb[i] = HMAC_IPAD; ictx = &(((struct md5_ctx*)(ipsp->ips_key_a))->ictx); osMD5Init(ictx); osMD5Update(ictx, kb, AHMD596_BLKLEN); for (i = 0; i < AHMD596_BLKLEN; i++) kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD); octx = &(((struct md5_ctx*)(ipsp->ips_key_a))->octx); osMD5Init(octx); osMD5Update(octx, kb, AHMD596_BLKLEN); # if KLIPS_DIVULGE_HMAC_KEY KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "MD5 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n", ((__u32*)ictx)[0], ((__u32*)ictx)[1], ((__u32*)ictx)[2], ((__u32*)ictx)[3], ((__u32*)octx)[0], ((__u32*)octx)[1], ((__u32*)octx)[2], ((__u32*)octx)[3] ); # endif /* KLIPS_DIVULGE_HMAC_KEY */ /* zero key buffer -- paranoid */ memset(akp, 0, aks); kfree(akp); } break; # endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ # ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1 case AH_SHA: { unsigned char *akp; unsigned int aks; SHA1_CTX *ictx; SHA1_CTX *octx; if (ipsp->ips_key_bits_a != (AHSHA196_KLEN * 8)) { KLIPS_PRINT(debug_pfkey, "ipsec_sa_init: " "incorrect key size: %d bits -- must be %d bits\n" /*octets (bytes)\n"*/, ipsp->ips_key_bits_a, AHSHA196_KLEN * 8); SENDERR(EINVAL); } # if KLIPS_DIVULGE_HMAC_KEY KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "hmac sha1-96 key is 0x%08x %08x %08x %08x\n", ntohl(*(((__u32 *)ipsp->ips_key_a) + 0)), ntohl(*(((__u32 *)ipsp->ips_key_a) + 1)), ntohl(*(((__u32 *)ipsp->ips_key_a) + 2)), ntohl(*(((__u32 *)ipsp->ips_key_a) + 3))); # endif /* KLIPS_DIVULGE_HMAC_KEY */ ipsp->ips_auth_bits = AHSHA196_ALEN * 8; /* save the pointer to the key material */ akp = ipsp->ips_key_a; aks = ipsp->ips_key_a_size; KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "allocating %zu bytes for sha1_ctx.\n", sizeof(struct sha1_ctx)); if ((ipsp->ips_key_a = (caddr_t) kmalloc(sizeof(struct sha1_ctx), GFP_ATOMIC)) == NULL) { ipsp->ips_key_a = akp; SENDERR(ENOMEM); } ipsp->ips_key_a_size = sizeof(struct sha1_ctx); for (i = 0; i < DIVUP(ipsp->ips_key_bits_a, 8); i++) kb[i] = akp[i] ^ HMAC_IPAD; for (; i < AHMD596_BLKLEN; i++) kb[i] = HMAC_IPAD; ictx = &(((struct sha1_ctx*)(ipsp->ips_key_a))->ictx); SHA1Init(ictx); SHA1Update(ictx, kb, AHSHA196_BLKLEN); for (i = 0; i < AHSHA196_BLKLEN; i++) kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD); octx = &(((struct sha1_ctx*)(ipsp->ips_key_a))->octx); SHA1Init(octx); SHA1Update(octx, kb, AHSHA196_BLKLEN); # if KLIPS_DIVULGE_HMAC_KEY KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "SHA1 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n", ((__u32*)ictx)[0], ((__u32*)ictx)[1], ((__u32*)ictx)[2], ((__u32*)ictx)[3], ((__u32*)octx)[0], ((__u32*)octx)[1], ((__u32*)octx)[2], ((__u32*)octx)[3] ); # endif /* KLIPS_DIVULGE_HMAC_KEY */ /* zero key buffer -- paranoid */ memset(akp, 0, aks); kfree(akp); } break; # endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */ default: KLIPS_PRINT(debug_pfkey, "ipsec_sa_init: " "authalg=%d support not available in the kernel", ipsp->ips_authalg); SENDERR(EINVAL); } #ifdef CONFIG_KLIPS_ALG /* closure of the -EPROTO condition above */ } #endif break; #endif /* CONFIG_KLIPS_AH */ #ifdef CONFIG_KLIPS_ESP case IPPROTO_ESP: ipsp->ips_xformfuncs = esp_xform_funcs; { #ifdef CONFIG_KLIPS_OCF if (ipsec_ocf_sa_init(ipsp, ipsp->ips_authalg, ipsp->ips_encalg)) break; #endif #ifdef CONFIG_KLIPS_ALG error = ipsec_alg_enc_key_create(ipsp); if (error < 0) SENDERR(-error); error = ipsec_alg_auth_key_create(ipsp); if ((error < 0) && (error != -EPROTO)) SENDERR(-error); if (error == -EPROTO) { /* perform manual key generation, ignore this particular error */ error = 0; #endif /* CONFIG_KLIPS_ALG */ switch (ipsp->ips_authalg) { #if defined (CONFIG_KLIPS_AUTH_HMAC_MD5) || \ defined (CONFIG_KLIPS_AUTH_HMAC_SHA1) unsigned char *akp; unsigned int aks; #endif # ifdef CONFIG_KLIPS_AUTH_HMAC_MD5 case AH_MD5: { MD5_CTX *ictx; MD5_CTX *octx; if (ipsp->ips_key_bits_a != (AHMD596_KLEN * 8)) { KLIPS_PRINT(debug_pfkey, "ipsec_sa_init: " "incorrect authorisation key size: %d bits -- must be %d bits\n" /*octets (bytes)\n"*/, ipsp->ips_key_bits_a, AHMD596_KLEN * 8); SENDERR(EINVAL); } # if KLIPS_DIVULGE_HMAC_KEY KLIPS_PRINT( debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "hmac md5-96 key is 0x%08x %08x %08x %08x\n", ntohl(*(((__u32 *)(ipsp->ips_key_a)) + 0)), ntohl(*(((__u32 *)(ipsp->ips_key_a)) + 1)), ntohl(*(((__u32 *)(ipsp->ips_key_a)) + 2)), ntohl(*(((__u32 *)(ipsp->ips_key_a)) + 3))); # endif /* KLIPS_DIVULGE_HMAC_KEY */ ipsp->ips_auth_bits = AHMD596_ALEN * 8; /* save the pointer to the key material */ akp = ipsp->ips_key_a; aks = ipsp->ips_key_a_size; KLIPS_PRINT( debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "allocating %zu bytes for md5_ctx.\n", sizeof(struct md5_ctx)); if ((ipsp->ips_key_a = (caddr_t) kmalloc(sizeof(struct md5_ctx), GFP_ATOMIC)) == NULL) { ipsp->ips_key_a = akp; SENDERR(ENOMEM); } ipsp->ips_key_a_size = sizeof(struct md5_ctx); for (i = 0; i < DIVUP(ipsp->ips_key_bits_a, 8); i++) kb[i] = akp[i] ^ HMAC_IPAD; for (; i < AHMD596_BLKLEN; i++) kb[i] = HMAC_IPAD; ictx = &(((struct md5_ctx*)(ipsp->ips_key_a)) ->ictx); osMD5Init(ictx); osMD5Update(ictx, kb, AHMD596_BLKLEN); for (i = 0; i < AHMD596_BLKLEN; i++) kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD); octx = &(((struct md5_ctx*)(ipsp->ips_key_a)) ->octx); osMD5Init(octx); osMD5Update(octx, kb, AHMD596_BLKLEN); # if KLIPS_DIVULGE_HMAC_KEY KLIPS_PRINT( debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "MD5 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n", ((__u32*)ictx)[0], ((__u32*)ictx)[1], ((__u32*)ictx)[2], ((__u32*)ictx)[3], ((__u32*)octx)[0], ((__u32*)octx)[1], ((__u32*)octx)[2], ((__u32*)octx)[3] ); # endif /* KLIPS_DIVULGE_HMAC_KEY */ /* paranoid */ memset(akp, 0, aks); kfree(akp); break; } # endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ # ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1 case AH_SHA: { SHA1_CTX *ictx; SHA1_CTX *octx; if (ipsp->ips_key_bits_a != (AHSHA196_KLEN * 8)) { KLIPS_PRINT(debug_pfkey, "ipsec_sa_init: " "incorrect authorisation key size: %d bits -- must be %d bits\n" /*octets (bytes)\n"*/, ipsp->ips_key_bits_a, AHSHA196_KLEN * 8); SENDERR(EINVAL); } # if KLIPS_DIVULGE_HMAC_KEY KLIPS_PRINT( debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "hmac sha1-96 key is 0x%08x %08x %08x %08x\n", ntohl(*(((__u32 *)ipsp->ips_key_a) + 0)), ntohl(*(((__u32 *)ipsp->ips_key_a) + 1)), ntohl(*(((__u32 *)ipsp->ips_key_a) + 2)), ntohl(*(((__u32 *)ipsp->ips_key_a) + 3))); # endif /* KLIPS_DIVULGE_HMAC_KEY */ ipsp->ips_auth_bits = AHSHA196_ALEN * 8; /* save the pointer to the key material */ akp = ipsp->ips_key_a; aks = ipsp->ips_key_a_size; KLIPS_PRINT( debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "allocating %zu bytes for sha1_ctx.\n", sizeof(struct sha1_ctx)); if ((ipsp->ips_key_a = (caddr_t) kmalloc(sizeof(struct sha1_ctx), GFP_ATOMIC)) == NULL) { ipsp->ips_key_a = akp; SENDERR(ENOMEM); } ipsp->ips_key_a_size = sizeof(struct sha1_ctx); for (i = 0; i < DIVUP(ipsp->ips_key_bits_a, 8); i++) kb[i] = akp[i] ^ HMAC_IPAD; for (; i < AHMD596_BLKLEN; i++) kb[i] = HMAC_IPAD; ictx = &(((struct sha1_ctx*)(ipsp->ips_key_a)) ->ictx); SHA1Init(ictx); SHA1Update(ictx, kb, AHSHA196_BLKLEN); for (i = 0; i < AHSHA196_BLKLEN; i++) kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD); octx = &((struct sha1_ctx*)(ipsp->ips_key_a)) ->octx; SHA1Init(octx); SHA1Update(octx, kb, AHSHA196_BLKLEN); # if KLIPS_DIVULGE_HMAC_KEY KLIPS_PRINT( debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "SHA1 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n", ((__u32*)ictx)[0], ((__u32*)ictx)[1], ((__u32*)ictx)[2], ((__u32*)ictx)[3], ((__u32*)octx)[0], ((__u32*)octx)[1], ((__u32*)octx)[2], ((__u32*)octx)[3] ); # endif /* KLIPS_DIVULGE_HMAC_KEY */ memset(akp, 0, aks); kfree(akp); break; } # endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */ case AH_NONE: break; default: KLIPS_PRINT(debug_pfkey, "ipsec_sa_init: " "authalg=%d support not available in the kernel.\n", ipsp->ips_authalg); SENDERR(EINVAL); } #ifdef CONFIG_KLIPS_ALG /* closure of the -EPROTO condition above */ } #endif ipsp->ips_iv_size = ipsp->ips_alg_enc->ixt_common.ixt_support. ias_ivlen / 8; /* Create IV */ if (ipsp->ips_iv_size) { if ((ipsp->ips_iv = (caddr_t) kmalloc(ipsp->ips_iv_size, GFP_ATOMIC)) == NULL) SENDERR(ENOMEM); prng_bytes(&ipsec_prng, (char *)ipsp->ips_iv, ipsp->ips_iv_size); ipsp->ips_iv_bits = ipsp->ips_iv_size * 8; } } break; #endif /* !CONFIG_KLIPS_ESP */ #ifdef CONFIG_KLIPS_IPCOMP case IPPROTO_COMP: ipsp->ips_xformfuncs = ipcomp_xform_funcs; ipsp->ips_comp_adapt_tries = 0; ipsp->ips_comp_adapt_skip = 0; ipsp->ips_comp_ratio_cbytes = 0; ipsp->ips_comp_ratio_dbytes = 0; #ifdef CONFIG_KLIPS_OCF if (ipsec_ocf_comp_sa_init(ipsp, ipsp->ips_encalg)) break; #endif ipsp->ips_comp_adapt_tries = 0; ipsp->ips_comp_adapt_skip = 0; ipsp->ips_comp_ratio_cbytes = 0; ipsp->ips_comp_ratio_dbytes = 0; break; #endif /* CONFIG_KLIPS_IPCOMP */ default: printk(KERN_ERR "KLIPS sa initialization: " "proto=%d unknown.\n", ipsp->ips_said.proto); SENDERR(EINVAL); } errlab: return error; } libreswan-3.32/linux/net/ipsec/ipsec_sha1.c000066400000000000000000000137411365625662500206700ustar00rootroot00000000000000/* * The rest of the code is derived from sha1.c by Steve Reid, which is * public domain. * Minor cosmetic changes to accommodate it in the Linux kernel by ji. */ #include #include #include "libreswan/ipsec_sha1.h" #if defined(rol) #undef rol #endif #define SHA1HANDSOFF #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) /* blk0() and blk() perform the initial expand. */ /* I got the idea of expanding during the round function from SSLeay */ #ifdef __LITTLE_ENDIAN #define blk0(i) (block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) \ | (rol(block->l[i], 8) & 0x00FF00FF)) #else #define blk0(i) block->l[i] #endif #define blk(i) (block->l[i & \ 15] = \ rol(block->l[(i + 13) & 15] ^ block->l[(i + 8) & 15] \ ^ block->l[(i + \ 2) & 15] ^ block->l[i & 15], 1)) /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ #define R0(v, w, x, y, z, \ i) z += \ ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); w = rol(w, 30); #define R1(v, w, x, y, z, \ i) z += \ ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); w = rol( \ w, 30); #define R2(v, w, x, y, z, \ i) z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + \ rol(v, 5); w = rol(w, 30); #define R3(v, w, x, y, z, \ i) z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \ w = rol(w, 30); #define R4(v, w, x, y, z, \ i) z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + \ rol(v, 5); w = rol(w, 30); /* Hash a single 512-bit block. This is the core of the algorithm. */ void SHA1Transform(__u32 state[5], __u8 buffer[64]) { __u32 a, b, c, d, e; typedef union { unsigned char c[64]; __u32 l[16]; } CHAR64LONG16; CHAR64LONG16* block; #ifdef SHA1HANDSOFF unsigned char workspace[64]; block = (CHAR64LONG16*)workspace; memcpy(block, buffer, 64); #else block = (CHAR64LONG16*)buffer; #endif /* Copy context->state[] to working vars */ a = state[0]; b = state[1]; c = state[2]; d = state[3]; e = state[4]; /* 4 rounds of 20 operations each. Loop unrolled. */ R0(a, b, c, d, e, 0); R0(e, a, b, c, d, 1); R0(d, e, a, b, c, 2); R0(c, d, e, a, b, 3); R0(b, c, d, e, a, 4); R0(a, b, c, d, e, 5); R0(e, a, b, c, d, 6); R0(d, e, a, b, c, 7); R0(c, d, e, a, b, 8); R0(b, c, d, e, a, 9); R0(a, b, c, d, e, 10); R0(e, a, b, c, d, 11); R0(d, e, a, b, c, 12); R0(c, d, e, a, b, 13); R0(b, c, d, e, a, 14); R0(a, b, c, d, e, 15); R1(e, a, b, c, d, 16); R1(d, e, a, b, c, 17); R1(c, d, e, a, b, 18); R1(b, c, d, e, a, 19); R2(a, b, c, d, e, 20); R2(e, a, b, c, d, 21); R2(d, e, a, b, c, 22); R2(c, d, e, a, b, 23); R2(b, c, d, e, a, 24); R2(a, b, c, d, e, 25); R2(e, a, b, c, d, 26); R2(d, e, a, b, c, 27); R2(c, d, e, a, b, 28); R2(b, c, d, e, a, 29); R2(a, b, c, d, e, 30); R2(e, a, b, c, d, 31); R2(d, e, a, b, c, 32); R2(c, d, e, a, b, 33); R2(b, c, d, e, a, 34); R2(a, b, c, d, e, 35); R2(e, a, b, c, d, 36); R2(d, e, a, b, c, 37); R2(c, d, e, a, b, 38); R2(b, c, d, e, a, 39); R3(a, b, c, d, e, 40); R3(e, a, b, c, d, 41); R3(d, e, a, b, c, 42); R3(c, d, e, a, b, 43); R3(b, c, d, e, a, 44); R3(a, b, c, d, e, 45); R3(e, a, b, c, d, 46); R3(d, e, a, b, c, 47); R3(c, d, e, a, b, 48); R3(b, c, d, e, a, 49); R3(a, b, c, d, e, 50); R3(e, a, b, c, d, 51); R3(d, e, a, b, c, 52); R3(c, d, e, a, b, 53); R3(b, c, d, e, a, 54); R3(a, b, c, d, e, 55); R3(e, a, b, c, d, 56); R3(d, e, a, b, c, 57); R3(c, d, e, a, b, 58); R3(b, c, d, e, a, 59); R4(a, b, c, d, e, 60); R4(e, a, b, c, d, 61); R4(d, e, a, b, c, 62); R4(c, d, e, a, b, 63); R4(b, c, d, e, a, 64); R4(a, b, c, d, e, 65); R4(e, a, b, c, d, 66); R4(d, e, a, b, c, 67); R4(c, d, e, a, b, 68); R4(b, c, d, e, a, 69); R4(a, b, c, d, e, 70); R4(e, a, b, c, d, 71); R4(d, e, a, b, c, 72); R4(c, d, e, a, b, 73); R4(b, c, d, e, a, 74); R4(a, b, c, d, e, 75); R4(e, a, b, c, d, 76); R4(d, e, a, b, c, 77); R4(c, d, e, a, b, 78); R4(b, c, d, e, a, 79); /* Add the working vars back into context.state[] */ state[0] += a; state[1] += b; state[2] += c; state[3] += d; state[4] += e; /* Wipe variables */ a = b = c = d = e = 0; } /* SHA1Init - Initialize new context */ void SHA1Init(void *vcontext) { SHA1_CTX* context = vcontext; /* SHA1 initialization constants */ context->state[0] = 0x67452301; context->state[1] = 0xEFCDAB89; context->state[2] = 0x98BADCFE; context->state[3] = 0x10325476; context->state[4] = 0xC3D2E1F0; context->count[0] = context->count[1] = 0; } /* Run your data through this. */ void SHA1Update(void *vcontext, unsigned char* data, __u32 len) { SHA1_CTX* context = vcontext; __u32 i, j; j = context->count[0]; if ((context->count[0] += len << 3) < j) context->count[1]++; context->count[1] += (len >> 29); j = (j >> 3) & 63; if ((j + len) > 63) { memcpy(&context->buffer[j], data, (i = 64 - j)); SHA1Transform(context->state, context->buffer); for (; i + 63 < len; i += 64) SHA1Transform(context->state, &data[i]); j = 0; } else { i = 0; } memcpy(&context->buffer[j], &data[i], len - i); } /* Add padding and return the message digest. */ void SHA1Final(unsigned char digest[SHA1_DIGEST_SIZE], void *vcontext) { __u32 i, j; unsigned char finalcount[8]; SHA1_CTX* context = vcontext; for (i = 0; i < 8; i++) { finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] >> ((3 - (i & 3)) * 8) ) & 255); /* Endian independent */ } SHA1Update(context, (unsigned char *)"\200", 1); while ((context->count[0] & 504) != 448) SHA1Update(context, (unsigned char *)"\0", 1); SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ for (i = 0; i < 20; i++) { digest[i] = (unsigned char) ((context->state[i >> 2] >> ((3 - (i & 3)) * 8) ) & 255); } /* Wipe variables */ i = j = 0; memset(context->buffer, 0, 64); memset(context->state, 0, 20); memset(context->count, 0, 8); memset(&finalcount, 0, 8); #ifdef SHA1HANDSOFF /* make SHA1Transform overwrite its own static vars */ SHA1Transform(context->state, context->buffer); #endif } libreswan-3.32/linux/net/ipsec/ipsec_snprintf.c000066400000000000000000000055761365625662500217060ustar00rootroot00000000000000/* * @(#) ipsec_snprintf() function * * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs * 2001 Michael Richardson * Copyright (C) 2005 Michael Richardson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * Split out from ipsec_proc.c. */ #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38) && \ !defined(AUTOCONF_INCLUDED) #include #endif #define __NO_VERSION__ #include #include /* printk() */ #include "libreswan/ipsec_kversion.h" #include "libreswan/ipsec_param.h" #include #include "libreswan/radij.h" #include "libreswan/ipsec_life.h" #include "libreswan/ipsec_stats.h" #include "libreswan/ipsec_sa.h" #include "libreswan/ipsec_encap.h" #include "libreswan/ipsec_radij.h" #include "libreswan/ipsec_xform.h" #include "libreswan/ipsec_tunnel.h" #include "libreswan/ipsec_xmit.h" #include "libreswan/ipsec_rcv.h" #include "libreswan/ipsec_ah.h" #include "libreswan/ipsec_esp.h" #ifdef CONFIG_KLIPS_IPCOMP #include "libreswan/ipcomp.h" #endif /* CONFIG_KLIPS_IPCOMP */ #include "libreswan/ipsec_proto.h" #include #include /* ipsec_snprintf: like snprintf except * - size is signed and a negative value is treated as if it were 0 * - the returned result is never negative -- * an error generates a "?" or null output (depending on space). * (Our callers are too lazy to check for an error return.) * * @param buf String buffer * @param size Size of the string * @param fmt printf string * @param ... Variables to be displayed in fmt * @return int Return code */ int ipsec_snprintf(char *buf, ssize_t size, const char *fmt, ...) { va_list args; int i; size_t possize = size < 0 ? 0 : size; va_start(args, fmt); i = vsnprintf(buf, possize, fmt, args); va_end(args); if (i < 0) { /* create empty output in place of error */ i = 0; if (size > 0) *buf = '\0'; } return i; } void ipsec_dmp_block(char *s, caddr_t bb, int len) { int i; unsigned char *b = bb; printk(KERN_INFO "klips_dmp: " "at %s, len=%d:\n", s, len); for (i = 0; i < len; i++ /*, c++*/) { if (!(i % 16)) { printk(KERN_INFO "klips_debug: @%03x:", i); } printk(" %02x", b[i]); if (!((i + 1) % 16)) printk("\n"); } if (i % 16) printk("\n"); } libreswan-3.32/linux/net/ipsec/ipsec_tunnel.c000066400000000000000000002141651365625662500213440ustar00rootroot00000000000000/* * IPSEC Tunneling code. Heavily based on drivers/net/new_tunnel.c * Copyright (C) 1996, 1997 John Ioannidis. * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2016 Richard Guy Briggs. * Copyright (C) 2012, 2016 Paul Wouters * Copyright (C) 2012 David McCullough * * OCF/receive state machine written by * David McCullough * Copyright (C) 2004-2005 Intel Corporation. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #define __NO_VERSION__ #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) && LINUX_VERSION_CODE >= \ KERNEL_VERSION(2, 4, 26) # include #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38) && \ !defined(AUTOCONF_INCLUDED) #include #endif #include /* printk() */ #include "libreswan/ipsec_param.h" #include /* kmalloc() */ #include /* error codes */ #include /* size_t */ #include #include /* mark_bh */ #include #include #include #include /* struct device, struct net_device_stats, dev_queue_xmit() and other headers */ #include /* eth_type_trans */ #include /* struct iphdr */ #include #include #include # include # define IS_MYADDR RTN_LOCAL # include # define PHYSDEV_TYPE #ifndef NETDEV_TX_BUSY # ifdef NETDEV_XMIT_CN # define NETDEV_TX_BUSY NETDEV_XMIT_CN # else # define NETDEV_TX_BUSY 1 # endif #endif #include /* icmp_send() */ #include #include #include # include #include #include #include #include "libreswan/ipsec_kversion.h" #include "libreswan/radij.h" #include "libreswan/ipsec_life.h" #include "libreswan/ipsec_xform.h" #include "libreswan/ipsec_eroute.h" #include "libreswan/ipsec_encap.h" #include "libreswan/ipsec_radij.h" #include "libreswan/ipsec_sa.h" #include "libreswan/ipsec_tunnel.h" #include "libreswan/ipsec_xmit.h" #include "libreswan/ipsec_rcv.h" #include "libreswan/ipsec_ipe4.h" #include "libreswan/ipsec_ah.h" #include "libreswan/ipsec_esp.h" #include #include #include "libreswan/ipsec_proto.h" #ifdef CONFIG_IPSEC_NAT_TRAVERSAL #include #endif static __u32 zeroes[64]; /* forward references */ DEBUG_NO_STATIC int ipsec_tunnel_attach(struct net_device *dev, struct net_device *physdev); DEBUG_NO_STATIC int ipsec_tunnel_detach(struct net_device *dev); extern const struct net_device_ops klips_device_ops; #ifdef HAVE_UDP_ENCAP_CONVERT DEBUG_NO_STATIC int ipsec_tunnel_udp_encap_prepare(int fd, int encap_type); DEBUG_NO_STATIC void ipsec_tunnel_udp_encap_destruct(struct sock *sk); DEBUG_NO_STATIC void ipsec_tunnel_upd_encap_cleanup(void); #endif #ifdef CONFIG_KLIPS_DEBUG int debug_tunnel = 0; #endif /* CONFIG_KLIPS_DEBUG */ DEBUG_NO_STATIC int ipsec_tunnel_open(struct net_device *dev) { struct ipsecpriv *prv = netdev_to_ipsecpriv(dev); /* * Can't open until attached. */ KLIPS_PRINT(debug_tunnel & DB_TN_INIT, "klips_debug:ipsec_tunnel_open: " "dev = %s, prv->dev = %s\n", dev->name, prv->dev ? prv->dev->name : "NONE"); if (prv->dev == NULL) return -ENODEV; KLIPS_INC_USE; return 0; } DEBUG_NO_STATIC int ipsec_tunnel_close(struct net_device *dev) { KLIPS_DEC_USE; return 0; } static inline int ipsec_tunnel_xmit2(struct sk_buff *skb) { #ifdef NET_26 /* 2.6 kernels */ # if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) return dst_output(dev_net(skb->dev), skb->sk, skb); # else return dst_output(skb); # endif #else return ip_send(skb); #endif } #ifdef HAVE_NETDEV_HEADER_OPS int klips_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, const void *daddr, const void *saddr, unsigned len) { struct ipsecpriv *prv = netdev_to_ipsecpriv(dev); struct net_device *tmp; int ret; struct net_device_stats *stats; /* This device's statistics */ if (skb == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_hard_header: " "no skb...\n"); return -ENODATA; } if (dev == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_hard_header: " "no device...\n"); return -ENODEV; } KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_hard_header: " "skb->dev=%s dev=%s.\n", skb->dev ? skb->dev->name : "NULL", dev->name); if (prv == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_hard_header: " "no private space associated with dev=%s\n", dev->name ? dev->name : "NULL"); return -ENODEV; } stats = (struct net_device_stats *) &(prv->mystats); if (prv->dev == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_hard_header: " "no physical device associated with dev=%s\n", dev->name ? dev->name : "NULL"); stats->tx_dropped++; return -ENODEV; } if (prv->dev->header_ops == NULL || prv->dev->header_ops->create == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_hard_header: " "cannot revector dev=%s op=%p func=%p", dev->name ? dev->name : "NULL", prv->dev->header_ops, prv->dev->header_ops ? prv->dev->header_ops->create : 0); /* don't fail here or devices without header ops (like ppp) fail */ return 0; } /* check if we have to send a IPv6 packet. It might be a Router Solicitation, where the building of the packet happens in reverse order: 1. ll hdr, 2. IPv6 hdr, 3. ICMPv6 hdr -> skb->nh.raw is still uninitialized when this function is called!! If this is no IPv6 packet, we can print debugging messages, otherwise we skip all debugging messages and just build the ll header */ if (type != ETH_P_IPV6) { /* execute this only, if we don't have to build the header for a IPv6 packet */ if (!prv->dev) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_hard_header: " "physical device has been detached, packet dropped 0p%p->0p%p len=%d type=%d dev=%s->NULL ", saddr, daddr, len, type, dev->name); KLIPS_PRINTMORE(debug_tunnel & DB_TN_REVEC, "ip=%08x->%08x\n", (__u32)ntohl(ip_hdr(skb)->saddr), (__u32)ntohl(ip_hdr(skb)->daddr) ); stats->tx_dropped++; return -ENODEV; } #define da ((struct net_device *)(prv->dev))->dev_addr KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_hard_header: " "Revectored 0p%p->0p%p len=%d type=%d dev=%s->%s dev_addr=%02x:%02x:%02x:%02x:%02x:%02x ", saddr, daddr, len, type, dev->name, prv->dev->name, da[0], da[1], da[2], da[3], da[4], da[5]); KLIPS_PRINTMORE(debug_tunnel & DB_TN_REVEC, "ip=%08x->%08x\n", (__u32)ntohl(ip_hdr(skb)->saddr), (__u32)ntohl(ip_hdr(skb)->daddr) ); } else { KLIPS_PRINT(debug_tunnel, "klips_debug:ipsec_tunnel_hard_header: " "is IPv6 packet, skip debugging messages, only revector and build linklocal header.\n"); } tmp = skb->dev; skb->dev = prv->dev; ret = prv->dev->header_ops->create(skb, prv->dev, type, (void *)daddr, (void *)saddr, len); skb->dev = tmp; return ret; } int klips_header_parse(const struct sk_buff *skb, unsigned char *haddr) { struct ipsecpriv *prv = netdev_to_ipsecpriv(skb->dev); struct net_device_stats *stats; /* This device's statistics */ int ret; stats = (struct net_device_stats *) &(prv->mystats); if (prv->dev == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:klips_header_parse: " "no physical device associated with dev=%s", skb->dev->name ? skb->dev->name : "NULL"); stats->tx_dropped++; return 0; } if (prv->dev->header_ops == NULL || prv->dev->header_ops->parse == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:klips_header_parse: " "cannot revector dev=%s op=%p func=%p", skb->dev->name ? skb->dev->name : "NULL", prv->dev->header_ops, prv->dev->header_ops ? prv->dev->header_ops->parse : 0); stats->tx_dropped++; return 0; } { #if 0 struct net_device *tmp; tmp = skb->dev; skb->dev = prv->dev; #endif ret = prv->dev->header_ops->parse(skb, haddr); #if 0 skb->dev = tmp; #endif } return ret; } #ifdef HAVE_REBUILD_HEADER DEBUG_NO_STATIC int klips_rebuild_header(struct sk_buff *skb) { struct ipsecpriv *prv = netdev_to_ipsecpriv(skb->dev); struct net_device *tmp; int ret; struct net_device_stats *stats; /* This device's statistics */ if (skb->dev == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_rebuild_header: " "no device..."); return -ENODEV; } if (prv == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_rebuild_header: " "no private space associated with dev=%s", skb->dev->name ? skb->dev->name : "NULL"); return -ENODEV; } stats = (struct net_device_stats *) &(prv->mystats); if (prv->dev == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_rebuild_header: " "no physical device associated with dev=%s", skb->dev->name ? skb->dev->name : "NULL"); stats->tx_dropped++; return -ENODEV; } if (prv->dev->header_ops == NULL || prv->dev->header_ops->rebuild == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_rebuild_header: " "cannot revector dev=%s op=%p func=%p", skb->dev->name ? skb->dev->name : "NULL", prv->dev->header_ops, prv->dev->header_ops ? prv->dev->header_ops->rebuild : 0); stats->tx_dropped++; return -ENODEV; } KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel: " "Revectored rebuild_header dev=%s->%s ", skb->dev->name, prv->dev->name); KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "ip=%08x->%08x\n", (__u32)ntohl(ip_hdr(skb)->saddr), (__u32)ntohl(ip_hdr(skb)->daddr) ); tmp = skb->dev; skb->dev = prv->dev; ret = prv->dev->header_ops->rebuild(skb); skb->dev = tmp; return ret; } #endif int klips_header_cache(const struct neighbour *neigh, struct hh_cache *hh #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0) , __be16 type #endif ) { const struct net_device *dev = neigh->dev; struct ipsecpriv *prv = netdev_to_ipsecpriv(dev); struct net_device_stats *stats; stats = (struct net_device_stats *) &(prv->mystats); if (prv->dev == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:klips_header_cache: " "no physical device associated with dev=%s", dev->name ? dev->name : "NULL"); stats->tx_dropped++; return -1; } if (prv->dev->header_ops == NULL || prv->dev->header_ops->cache == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:klips_header_cache: " "cannot revector dev=%s op=%p func=%p", dev->name ? dev->name : "NULL", prv->dev->header_ops, prv->dev->header_ops ? prv->dev->header_ops->cache : 0); /* don't fail here or devices without header ops (like ppp) fail */ return 0; } KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel: " "Revectored cache_update\n"); return prv->dev->header_ops->cache(neigh, hh #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0) , type #endif ); } DEBUG_NO_STATIC void klips_header_cache_update(struct hh_cache *hh, const struct net_device *dev, const unsigned char * haddr) { struct ipsecpriv *prv = netdev_to_ipsecpriv(dev); struct net_device_stats *stats; /* This device's statistics */ if (dev == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_cache_update: " "no device..."); return; } if (prv == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_cache_update: " "no private space associated with dev=%s", dev->name ? dev->name : "NULL"); return; } stats = (struct net_device_stats *) &(prv->mystats); if (prv->dev == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_cache_update: " "no physical device associated with dev=%s", dev->name ? dev->name : "NULL"); stats->tx_dropped++; return; } if (prv->dev->header_ops == NULL || prv->dev->header_ops->cache_update == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_cache_update: " "cannot revector dev=%s op=%p func=%p", dev->name ? dev->name : "NULL", prv->dev->header_ops, prv->dev->header_ops ? prv->dev->header_ops->cache_update : 0); stats->tx_dropped++; return; } KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel: " "Revectored cache_update\n"); prv->dev->header_ops->cache_update(hh, prv->dev, haddr); } const struct header_ops klips_header_ops ____cacheline_aligned = { .create = klips_header, .parse = klips_header_parse, #ifdef HAVE_REBUILD_HEADER .rebuild = klips_rebuild_header, #endif .cache = klips_header_cache, .cache_update = klips_header_cache_update, }; #endif /* HAVE_NETDEV_HEADER_OPS */ enum ipsec_xmit_value ipsec_tunnel_strip_hard_header( struct ipsec_xmit_state *ixs) { /* ixs->physdev->hard_header_len is unreliable and should not be used */ ixs->hard_header_len = (unsigned char *)ixs->iph - ixs->skb->data; if (ixs->hard_header_len < 0) { KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_error:ipsec_xmit_strip_hard_header: " "Negative hard_header_len (%d)?!\n", ixs->hard_header_len); ixs->stats->tx_dropped++; return IPSEC_XMIT_BADHHLEN; } /* while ixs->physdev->hard_header_len is unreliable and * should not be trusted, it accurate and required for ATM, GRE and * some other interfaces to work. Thanks to Willy Tarreau * . */ if (ixs->hard_header_len == 0) { /* no hard header present */ ixs->hard_header_stripped = 1; ixs->hard_header_len = ixs->physdev->hard_header_len; } if (debug_tunnel & DB_TN_XMIT) { int i; char c; printk(KERN_INFO "klips_debug:ipsec_xmit_strip_hard_header: " ">>> skb->len=%ld hard_header_len:%d", (unsigned long int)ixs->skb->len, ixs->hard_header_len); c = ' '; for (i = 0; i < ixs->hard_header_len; i++) { printk("%c%02x", c, ixs->skb->data[i]); c = ':'; } printk("\n"); } KLIPS_IP_PRINT(debug_tunnel & DB_TN_XMIT, ixs->iph); KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, "klips_debug:ipsec_xmit_strip_hard_header: " "Original head,tailroom: %d,%d\n", skb_headroom(ixs->skb), skb_tailroom(ixs->skb)); return IPSEC_XMIT_OK; } enum ipsec_xmit_value ipsec_tunnel_SAlookup(struct ipsec_xmit_state *ixs) { unsigned int bypass; unsigned char nexthdr; int nexthdroff; char tsrc[ADDRTOT_BUF + 1], tdst[ADDRTOT_BUF + 1]; bypass = FALSE; /* * First things first -- look us up in the erouting tables. */ ixs->matcher.sen_len = sizeof(struct sockaddr_encap); ixs->matcher.sen_family = AF_ENCAP; #ifdef CONFIG_KLIPS_IPV6 if (lsw_ip_hdr_version(ixs) == 6) { IPSEC_FRAG_OFF_DECL(frag_off) nexthdr = lsw_ip6_hdr(ixs)->nexthdr; nexthdroff = ipsec_ipv6_skip_exthdr(ixs->skb, ((void *)(lsw_ip6_hdr( ixs) + 1)) - (void*)ixs->skb->data, &nexthdr, &frag_off); ixs->matcher.sen_type = SENT_IP6; ixs->matcher.sen_ip6_src = lsw_ip6_hdr(ixs)->saddr; ixs->matcher.sen_ip6_dst = lsw_ip6_hdr(ixs)->daddr; ixs->matcher.sen_proto6 = nexthdr; if (debug_tunnel & DB_TN_XMIT) { inet_addrtot(AF_INET6, &lsw_ip6_hdr( ixs)->saddr, 0, tsrc, sizeof(tsrc)); inet_addrtot(AF_INET6, &lsw_ip6_hdr( ixs)->daddr, 0, tdst, sizeof(tdst)); } } else #endif /* CONFIG_KLIPS_IPV6 */ { nexthdr = lsw_ip4_hdr(ixs)->protocol; nexthdroff = 0; if ((ntohs(lsw_ip4_hdr(ixs)->frag_off) & IP_OFFSET) == 0) { nexthdroff = (ixs->iph + (lsw_ip4_hdr(ixs)->ihl << 2)) - (void *)ixs->skb->data; } ixs->matcher.sen_type = SENT_IP4; ixs->matcher.sen_ip_src.s_addr = lsw_ip4_hdr(ixs)->saddr; ixs->matcher.sen_ip_dst.s_addr = lsw_ip4_hdr(ixs)->daddr; ixs->matcher.sen_proto = nexthdr; if (debug_tunnel & DB_TN_XMIT) { inet_addrtot(AF_INET, &lsw_ip4_hdr( ixs)->saddr, 0, tsrc, sizeof(tsrc)); inet_addrtot(AF_INET, &lsw_ip4_hdr( ixs)->daddr, 0, tdst, sizeof(tdst)); } } ipsec_extract_ports(ixs->skb, nexthdr, nexthdroff, &ixs->matcher); /* * The spinlock is to prevent any other process from accessing or deleting * the eroute while we are using and updating it. */ spin_lock_bh(&eroute_lock); ixs->eroute = ipsec_findroute(&ixs->matcher); if (nexthdr == IPPROTO_UDP) { struct udphdr _udphdr, *udphdr = NULL; if (nexthdroff) udphdr = skb_header_pointer(ixs->skb, nexthdroff, sizeof(*udphdr), &_udphdr); KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:udp port check: " "version: %d " "nexthdroff: %d " "udphdr: %p\n", lsw_ip_hdr_version(ixs), nexthdroff, udphdr); ixs->sport = 0; ixs->dport = 0; if (ixs->skb->sk) { #ifdef NET_26 #ifdef HAVE_INET_SK_SPORT ixs->sport = ntohs(inet_sk(ixs->skb->sk)->inet_sport); ixs->dport = ntohs(inet_sk(ixs->skb->sk)->inet_dport); #else struct udp_sock *us; us = (struct udp_sock *)ixs->skb->sk; ixs->sport = ntohs(us->inet.sport); ixs->dport = ntohs(us->inet.dport); #endif #else ixs->sport = ntohs(ixs->skb->sk->sport); ixs->dport = ntohs(ixs->skb->sk->dport); #endif } if (udphdr != NULL) { if (ixs->sport == 0) ixs->sport = ntohs(udphdr->source); if (ixs->dport == 0) ixs->dport = ntohs(udphdr->dest); } } /* * practically identical to above, but let's be careful about * tcp vs udp headers */ if (nexthdr == IPPROTO_TCP) { struct tcphdr _tcphdr, *tcphdr = NULL; if (nexthdroff) tcphdr = skb_header_pointer(ixs->skb, nexthdroff, sizeof(*tcphdr), &_tcphdr); ixs->sport = 0; ixs->dport = 0; if (ixs->skb->sk) { #ifdef NET_26 #ifdef HAVE_INET_SK_SPORT ixs->sport = ntohs(inet_sk(ixs->skb->sk)->inet_sport); ixs->dport = ntohs(inet_sk(ixs->skb->sk)->inet_dport); #else struct tcp_tw_bucket *tw; tw = (struct tcp_tw_bucket *)ixs->skb->sk; ixs->sport = ntohs(tw->tw_sport); ixs->dport = ntohs(tw->tw_dport); #endif #else ixs->sport = ntohs(ixs->skb->sk->sport); ixs->dport = ntohs(ixs->skb->sk->dport); #endif } if (tcphdr != NULL) { if (ixs->sport == 0) ixs->sport = ntohs(tcphdr->source); if (ixs->dport == 0) ixs->dport = ntohs(tcphdr->dest); } } #ifdef CONFIG_KLIPS_IPV6 if (lsw_ip_hdr_version(ixs) == 6) { char edst[ADDRTOT_BUF + 1]; struct in6_addr addr6_any = IN6ADDR_ANY_INIT; /* default to a %drop eroute */ ixs->outgoing_said.proto = IPPROTO_INT; ixs->outgoing_said.spi = htonl(SPI_DROP); ixs->outgoing_said.dst.u.v6.sin6_addr = addr6_any; if (debug_tunnel & DB_TN_XMIT) { if (ixs->eroute) sin_addrtot(&ixs->eroute->er_said.dst.u, 0, edst, sizeof(edst)); else memcpy(edst, "0", 2); } KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_xmit_SAlookup: " "checking for local udp/500 IKE, udp/4500 NAT-T, ESP or AH packets " "saddr=%s, er=0p%p, daddr=%s, er_dst=%s, proto=%d sport=%d dport=%d\n", tsrc, ixs->eroute, tdst, edst, nexthdr, ixs->sport, ixs->dport); /* * cheat for now...are we udp/500? If so, let it through * without interference since it is most likely an IKE packet. */ if (ip6_chk_addr(&lsw_ip6_hdr(ixs)->saddr) == IS_MYADDR && (ixs->eroute == NULL || ipv6_addr_cmp(&lsw_ip6_hdr(ixs)->daddr, &ixs->eroute->er_said.dst.u.v6.sin6_addr) == 0 || ipv6_addr_any(&ixs->eroute->er_said.dst.u.v6.sin6_addr)) && (nexthdr == IPPROTO_ESP || nexthdr == IPPROTO_AH || (nexthdr == IPPROTO_UDP && (ixs->sport == 500 || ixs->sport == 4500)))) { /* Whatever the eroute, this is an IKE message * from us (i.e. not being forwarded). * Furthermore, if there is a tunnel eroute, * the destination is the peer for this eroute. * So %pass the packet: modify the default %drop. */ unsigned int ptr; ixs->outgoing_said.spi = htonl(SPI_PASS); if (!ixs->skb->sk && lsw_ipv6_find_hdr(ixs->skb, &ptr, NEXTHDR_FRAGMENT, NULL) != ENOENT) { KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_xmit_SAlookup: " "local UDP/500 (probably IKE) passthrough: base fragment, rest of fragments will probably get filtered.\n"); } bypass = TRUE; } } else #endif /* CONFIG_KLIPS_IPV6 */ { /* default to a %drop eroute */ ixs->outgoing_said.proto = IPPROTO_INT; ixs->outgoing_said.spi = htonl(SPI_DROP); ixs->outgoing_said.dst.u.v4.sin_addr.s_addr = INADDR_ANY; KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_xmit_SAlookup: " "checking for local udp/500 IKE, udp/4500 NAT-T, ESP or AH packets " "saddr=%s, er=0p%p, daddr=%s, er_dst=%x, proto=%d sport=%d dport=%d\n", tsrc, ixs->eroute, tdst, ixs->eroute ? ntohl((unsigned int)ixs->eroute-> er_said.dst.u.v4.sin_addr. s_addr) : 0, nexthdr, ixs->sport, ixs->dport); /* * cheat for now...are we udp/500? If so, let it through * without interference since it is most likely an IKE packet. */ if (ip_chk_addr(lsw_ip4_hdr(ixs)->saddr) == IS_MYADDR && (ixs->eroute == NULL || lsw_ip4_hdr(ixs)->daddr == ixs->eroute->er_said.dst.u.v4.sin_addr.s_addr || INADDR_ANY == ixs->eroute->er_said.dst.u.v4.sin_addr.s_addr) && (nexthdr == IPPROTO_ESP || nexthdr == IPPROTO_AH || (nexthdr == IPPROTO_UDP && (ixs->sport == 500 || ixs->sport == 4500)))) { /* Whatever the eroute, this is an IKE message * from us (i.e. not being forwarded). * Furthermore, if there is a tunnel eroute, * the destination is the peer for this eroute. * So %pass the packet: modify the default %drop. */ ixs->outgoing_said.spi = htonl(SPI_PASS); if (!(ixs->skb->sk) && ((ntohs(lsw_ip4_hdr(ixs)->frag_off) & IP_MF) != 0)) { KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_xmit_SAlookup: " "local UDP/500 (probably IKE) passthrough: base fragment, rest of fragments will probably get filtered.\n"); } bypass = TRUE; } } if (!bypass && ixs->eroute != NULL) { ixs->eroute->er_count++; ixs->eroute->er_lasttime = jiffies / HZ; if (ixs->eroute->er_said.proto == IPPROTO_INT && ixs->eroute->er_said.spi == htonl(SPI_HOLD)) { KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_xmit_SAlookup: " "shunt SA of HOLD: skb stored in HOLD.\n"); if (ixs->eroute->er_last != NULL) { ipsec_kfree_skb(ixs->eroute->er_last); ixs->stats->tx_dropped++; } ixs->eroute->er_last = ixs->skb; ixs->skb = NULL; spin_unlock_bh(&eroute_lock); return IPSEC_XMIT_STOLEN; } ixs->outgoing_said = ixs->eroute->er_said; ixs->eroute_pid = ixs->eroute->er_pid; /* Copy of the ident for the TRAP/TRAPSUBNET eroutes */ if (ixs->outgoing_said.proto == IPPROTO_INT && (ixs->outgoing_said.spi == htonl(SPI_TRAP) || (ixs->outgoing_said.spi == htonl(SPI_TRAPSUBNET)))) { int len; ixs->ips.ips_ident_s.type = ixs->eroute->er_ident_s.type; ixs->ips.ips_ident_s.id = ixs->eroute->er_ident_s.id; ixs->ips.ips_ident_s.len = ixs->eroute->er_ident_s.len; if (ixs->ips.ips_ident_s.len) { len = ixs->ips.ips_ident_s.len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident); KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_xmit_SAlookup: " "allocating %d bytes for ident_s shunt SA of HOLD: skb stored in HOLD.\n", len); if ((ixs->ips.ips_ident_s.data = kmalloc(len, GFP_ATOMIC)) == NULL) { printk(KERN_WARNING "klips_debug:ipsec_xmit_SAlookup: " "Failed, tried to allocate %d bytes for source ident.\n", len); ixs->stats->tx_dropped++; spin_unlock_bh(&eroute_lock); return IPSEC_XMIT_ERRMEMALLOC; } memcpy(ixs->ips.ips_ident_s.data, ixs->eroute->er_ident_s.data, len); } ixs->ips.ips_ident_d.type = ixs->eroute->er_ident_d.type; ixs->ips.ips_ident_d.id = ixs->eroute->er_ident_d.id; ixs->ips.ips_ident_d.len = ixs->eroute->er_ident_d.len; if (ixs->ips.ips_ident_d.len) { len = ixs->ips.ips_ident_d.len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident); KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_xmit_SAlookup: " "allocating %d bytes for ident_d shunt SA of HOLD: skb stored in HOLD.\n", len); if ((ixs->ips.ips_ident_d.data = kmalloc(len, GFP_ATOMIC)) == NULL) { printk(KERN_WARNING "klips_debug:ipsec_xmit_SAlookup: " "Failed, tried to allocate %d bytes for dest ident.\n", len); ixs->stats->tx_dropped++; spin_unlock_bh(&eroute_lock); return IPSEC_XMIT_ERRMEMALLOC; } memcpy(ixs->ips.ips_ident_d.data, ixs->eroute->er_ident_d.data, len); } } } spin_unlock_bh(&eroute_lock); return IPSEC_XMIT_OK; } enum ipsec_xmit_value ipsec_tunnel_restore_hard_header( struct ipsec_xmit_state*ixs) { KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, "klips_debug:ipsec_xmit_restore_hard_header: " "After recursive xforms -- head,tailroom: %d,%d\n", skb_headroom(ixs->skb), skb_tailroom(ixs->skb)); if (ixs->saved_header) { if (skb_headroom(ixs->skb) < ixs->hard_header_len) { printk(KERN_WARNING "klips_error:ipsec_xmit_restore_hard_header: " "tried to skb_push hhlen=%d, %d available. This should never happen, please report.\n", ixs->hard_header_len, skb_headroom(ixs->skb)); ixs->stats->tx_errors++; return IPSEC_XMIT_PUSHPULLERR; } skb_push(ixs->skb, ixs->hard_header_len); { int i; for (i = 0; i < ixs->hard_header_len; i++) ixs->skb->data[i] = ixs->saved_header[i]; } } KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, "klips_debug:ipsec_xmit_restore_hard_header: " "With hard_header, final head,tailroom: %d,%d\n", skb_headroom(ixs->skb), skb_tailroom(ixs->skb)); return IPSEC_XMIT_OK; } /* * when encap processing is complete it call this for us to continue */ void ipsec_tunnel_xsm_complete(struct ipsec_xmit_state *ixs, enum ipsec_xmit_value stat) { unsigned char nexthdr; int nexthdroff; if (stat != IPSEC_XMIT_OK) { if (stat == IPSEC_XMIT_PASS) goto bypass; KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_tunnel_start_xmit: encap_bundle failed: %d\n", stat); goto cleanup; } #ifdef CONFIG_KLIPS_IPV6 if (lsw_ip_hdr_version(ixs) == 6) { IPSEC_FRAG_OFF_DECL(frag_off) nexthdr = lsw_ip6_hdr(ixs)->nexthdr; nexthdroff = ipsec_ipv6_skip_exthdr(ixs->skb, ((void *)(lsw_ip6_hdr( ixs) + 1)) - (void*)ixs->skb->data, &nexthdr, &frag_off); ixs->matcher.sen_type = SENT_IP6; ixs->matcher.sen_ip6_src = lsw_ip6_hdr(ixs)->saddr; ixs->matcher.sen_ip6_dst = lsw_ip6_hdr(ixs)->daddr; ixs->matcher.sen_proto6 = nexthdr; } else #endif /* CONFIG_KLIPS_IPV6 */ { nexthdr = lsw_ip4_hdr(ixs)->protocol; nexthdroff = 0; if ((ntohs(lsw_ip4_hdr(ixs)->frag_off) & IP_OFFSET) == 0) { nexthdroff = (ixs->iph + (lsw_ip4_hdr(ixs)->ihl << 2)) - (void *)ixs->skb->data; } ixs->matcher.sen_type = SENT_IP4; ixs->matcher.sen_ip_src.s_addr = lsw_ip4_hdr(ixs)->saddr; ixs->matcher.sen_ip_dst.s_addr = lsw_ip4_hdr(ixs)->daddr; ixs->matcher.sen_proto = nexthdr; } ipsec_extract_ports(ixs->skb, nexthdr, nexthdroff, &ixs->matcher); spin_lock_bh(&eroute_lock); ixs->eroute = ipsec_findroute(&ixs->matcher); if (ixs->eroute) { ixs->outgoing_said = ixs->eroute->er_said; ixs->eroute_pid = ixs->eroute->er_pid; ixs->eroute->er_count++; ixs->eroute->er_lasttime = jiffies / HZ; } spin_unlock_bh(&eroute_lock); if ( /*((ixs->orgdst != ixs->newdst) || (ixs->orgsrc != ixs->newsrc))*/ !ip_address_eq(&ixs->orgedst, &ixs->outgoing_said.dst) && !ip_address_isany(&ixs->outgoing_said.dst) && ixs->eroute) { KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_tunnel_start_xmit: " "We are recursing here.\n"); ipsec_xsm(ixs); return; } stat = ipsec_nat_encap(ixs); if (stat != IPSEC_XMIT_OK) goto cleanup; stat = ipsec_tunnel_restore_hard_header(ixs); if (stat != IPSEC_XMIT_OK) goto cleanup; bypass: stat = ipsec_tunnel_send(ixs); cleanup: ipsec_xmit_cleanup(ixs); ipsec_xmit_state_delete(ixs); } /* * This function assumes it is being called from dev_queue_xmit() * and that skb is filled properly by that function. */ int ipsec_tunnel_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct ipsec_xmit_state *ixs = NULL; enum ipsec_xmit_value stat; KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "\n\nipsec_tunnel_start_xmit: STARTING"); stat = IPSEC_XMIT_ERRMEMALLOC; ixs = ipsec_xmit_state_new(dev); if (ixs == NULL) return NETDEV_TX_BUSY; ixs->dev = dev; ixs->skb = skb; stat = ipsec_xmit_sanity_check_ipsec_dev(ixs); if (stat != IPSEC_XMIT_OK) goto cleanup; stat = ipsec_xmit_sanity_check_skb(ixs); if (stat != IPSEC_XMIT_OK) goto cleanup; stat = ipsec_tunnel_strip_hard_header(ixs); if (stat != IPSEC_XMIT_OK) goto cleanup; stat = ipsec_tunnel_SAlookup(ixs); if (stat != IPSEC_XMIT_OK) { KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_tunnel_start_xmit: SAlookup failed: %d\n", stat); goto cleanup; } ixs->xsm_complete = ipsec_tunnel_xsm_complete; ipsec_xsm(ixs); return 0; cleanup: ipsec_xmit_cleanup(ixs); ipsec_xmit_state_delete(ixs); return 0; } DEBUG_NO_STATIC struct net_device_stats *ipsec_tunnel_get_stats( struct net_device *dev) { return &(netdev_to_ipsecpriv(dev)->mystats); } /* * Revectored calls. * For each of these calls, a field exists in our private structure. */ DEBUG_NO_STATIC int ipsec_tunnel_hard_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, const void *daddr, const void *saddr, unsigned len) { struct ipsecpriv *prv = netdev_to_ipsecpriv(dev); struct net_device *tmp; int ret; struct net_device_stats *stats; /* This device's statistics */ if (skb == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_hard_header: " "no skb...\n"); return -ENODATA; } if (dev == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_hard_header: " "no device...\n"); return -ENODEV; } KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_hard_header: " "skb->dev=%s dev=%s.\n", skb->dev ? skb->dev->name : "NULL", dev->name); if (prv == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_hard_header: " "no private space associated with dev=%s\n", dev->name ? dev->name : "NULL"); return -ENODEV; } stats = (struct net_device_stats *) &(prv->mystats); if (prv->dev == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_hard_header: " "no physical device associated with dev=%s\n", dev->name ? dev->name : "NULL"); stats->tx_dropped++; return -ENODEV; } /* check if we have to send a IPv6 packet. It might be a Router Solicitation, where the building of the packet happens in reverse order: 1. ll hdr, 2. IPv6 hdr, 3. ICMPv6 hdr -> skb->nh.raw is still uninitialized when this function is called!! If this is no IPv6 packet, we can print debugging messages, otherwise we skip all debugging messages and just build the ll header */ if (type != ETH_P_IPV6) { /* execute this only, if we don't have to build the header for a IPv6 packet */ #ifdef HAVE_NETDEV_HEADER_OPS if (!prv->header_ops->create) #else if (!prv->hard_header) #endif { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_hard_header: " "physical device has been detached, packet dropped 0p%p->0p%p len=%d type=%d dev=%s->NULL ", saddr, daddr, len, type, dev->name); KLIPS_PRINTMORE(debug_tunnel & DB_TN_REVEC, "ip=%08x->%08x\n", (__u32)ntohl(ip_hdr(skb)->saddr), (__u32)ntohl(ip_hdr(skb)->daddr) ); stats->tx_dropped++; return -ENODEV; } #define da ((struct net_device *)(prv->dev))->dev_addr KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_hard_header: " "Revectored 0p%p->0p%p len=%d type=%d dev=%s->%s dev_addr=%02x:%02x:%02x:%02x:%02x:%02x ", saddr, daddr, len, type, dev->name, prv->dev->name, da[0], da[1], da[2], da[3], da[4], da[5]); KLIPS_PRINTMORE(debug_tunnel & DB_TN_REVEC, "ip=%08x->%08x\n", (__u32)ntohl(ip_hdr(skb)->saddr), (__u32)ntohl(ip_hdr(skb)->daddr) ); } else { KLIPS_PRINT(debug_tunnel, "klips_debug:ipsec_tunnel_hard_header: " "is IPv6 packet, skip debugging messages, only revector and build linklocal header.\n"); } tmp = skb->dev; skb->dev = prv->dev; #ifdef HAVE_NETDEV_HEADER_OPS ret = prv->header_ops->create(skb, prv->dev, type, (void *)daddr, (void *)saddr, len); #else ret = prv->hard_header(skb, prv->dev, type, (void *)daddr, (void *)saddr, len); #endif skb->dev = tmp; return ret; } #ifdef HAVE_REBUILD_HEADER DEBUG_NO_STATIC int ipsec_tunnel_rebuild_header(struct sk_buff *skb) { struct ipsecpriv *prv = netdev_to_ipsecpriv(skb->dev); struct net_device *tmp; int ret; struct net_device_stats *stats; /* This device's statistics */ if (skb->dev == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_rebuild_header: " "no device..."); return -ENODEV; } if (prv == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_rebuild_header: " "no private space associated with dev=%s", skb->dev->name ? skb->dev->name : "NULL"); return -ENODEV; } stats = (struct net_device_stats *) &(prv->mystats); if (prv->dev == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_rebuild_header: " "no physical device associated with dev=%s", skb->dev->name ? skb->dev->name : "NULL"); stats->tx_dropped++; return -ENODEV; } #ifdef HAVE_NETDEV_HEADER_OPS if (!prv->header_ops->rebuild) #else if (!prv->rebuild_header) #endif { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_rebuild_header: " "physical device has been detached, packet dropped skb->dev=%s->NULL ", skb->dev->name); KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "ip=%08x->%08x\n", (__u32)ntohl(ip_hdr(skb)->saddr), (__u32)ntohl(ip_hdr(skb)->daddr) ); stats->tx_dropped++; return -ENODEV; } KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel: " "Revectored rebuild_header dev=%s->%s ", skb->dev->name, prv->dev->name); KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "ip=%08x->%08x\n", (__u32)ntohl(ip_hdr(skb)->saddr), (__u32)ntohl(ip_hdr(skb)->daddr) ); tmp = skb->dev; skb->dev = prv->dev; #ifdef HAVE_NETDEV_HEADER_OPS ret = prv->header_ops->rebuild(skb); #else ret = prv->rebuild_header(skb); #endif skb->dev = tmp; return ret; } #endif #ifdef HAVE_SET_MAC_ADDR DEBUG_NO_STATIC int ipsec_tunnel_set_mac_address(struct net_device *dev, void *addr) { struct ipsecpriv *prv = netdev_to_ipsecpriv(dev); struct net_device_stats *stats; /* This device's statistics */ if (dev == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_set_mac_address: " "no device..."); return -ENODEV; } if (prv == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_set_mac_address: " "no private space associated with dev=%s", dev->name ? dev->name : "NULL"); return -ENODEV; } stats = (struct net_device_stats *) &(prv->mystats); if (prv->dev == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_set_mac_address: " "no physical device associated with dev=%s", dev->name ? dev->name : "NULL"); stats->tx_dropped++; return -ENODEV; } if (!prv->dev) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_set_mac_address: " "physical device has been detached, cannot set - skb->dev=%s->NULL\n", dev->name); return -ENODEV; } KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_set_mac_address: " "Revectored dev=%s->%s addr=0p%p\n", dev->name, prv->dev->name, addr); return prv->set_mac_address(prv->dev, addr); } #endif /* HAVE_SET_MAC_ADDR */ DEBUG_NO_STATIC void ipsec_tunnel_cache_update(struct hh_cache *hh, const struct net_device *dev, const unsigned char * haddr) { struct ipsecpriv *prv = netdev_to_ipsecpriv(dev); struct net_device_stats *stats; /* This device's statistics */ if (dev == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_cache_update: " "no device..."); return; } if (prv == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_cache_update: " "no private space associated with dev=%s", dev->name ? dev->name : "NULL"); return; } stats = (struct net_device_stats *) &(prv->mystats); if (prv->dev == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_cache_update: " "no physical device associated with dev=%s", dev->name ? dev->name : "NULL"); stats->tx_dropped++; return; } #ifdef HAVE_NETDEV_HEADER_OPS if (!prv->header_ops->cache_update) #else if (!prv->header_cache_update) #endif { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_cache_update: " "physical device has been detached, cannot set - skb->dev=%s->NULL\n", dev->name); return; } KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel: " "Revectored cache_update\n"); #ifdef HAVE_NETDEV_HEADER_OPS prv->header_ops->cache_update(hh, prv->dev, haddr); #else prv->header_cache_update(hh, prv->dev, haddr); #endif } #ifdef HAVE_NETDEV_HEADER_OPS const struct header_ops ipsec_tunnel_header_ops = { .create = ipsec_tunnel_hard_header, #ifdef HAVE_REBUILD_HEADER .rebuild = ipsec_tunnel_rebuild_header, #endif .cache_update = ipsec_tunnel_cache_update, }; #endif DEBUG_NO_STATIC int ipsec_tunnel_neigh_setup(struct neighbour *n) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_neigh_setup:\n"); if (n->nud_state == NUD_NONE) { #ifndef PRIVATE_ARP_BROKEN_OPS n->ops = &arp_broken_ops; #endif n->output = n->ops->output; } return 0; } DEBUG_NO_STATIC int ipsec_tunnel_neigh_setup_dev(struct net_device *dev, struct neigh_parms *p) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_neigh_setup_dev: " "setting up %s\n", dev ? dev->name : "NULL"); if (p->tbl->family == AF_INET) { p->neigh_setup = ipsec_tunnel_neigh_setup; #ifdef NEIGH_VAR_SET /* * see kernel's include/net/neighbour.h * ??? Not sure which to use: * NEIGH_VAR_INIT or NEIGH_VAR_INIT */ NEIGH_VAR_SET(p, UCAST_PROBES, 0); NEIGH_VAR_SET(p, MCAST_PROBES, 0); #else p->ucast_probes = 0; p->mcast_probes = 0; #endif } return 0; } /* * We call the detach routine to detach the ipsec tunnel from another device. */ DEBUG_NO_STATIC int ipsec_tunnel_detach(struct net_device *dev) { int i; struct ipsecpriv *prv = netdev_to_ipsecpriv(dev); if (dev == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_detach: " "no device..."); return -ENODEV; } if (prv == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_detach: " "no private space associated with dev=%s", dev->name ? dev->name : "NULL"); return -ENODATA; } KLIPS_PRINT(debug_tunnel & DB_TN_INIT, "klips_debug:ipsec_tunnel_detach: " "physical device %s being detached from virtual device %s\n", prv->dev ? prv->dev->name : "NULL", dev->name); ipsec_dev_put(prv->dev); prv->dev = NULL; prv->hard_start_xmit = NULL; prv->get_stats = NULL; #ifdef HAVE_NETDEV_HEADER_OPS prv->header_ops = NULL; #else prv->hard_header = NULL; #ifdef HAVE_REBUILD_HEADER prv->rebuild_header = NULL; #endif prv->header_cache_update = NULL; #endif prv->set_mac_address = NULL; dev->hard_header_len = 0; #ifdef DETACH_AND_DOWN #ifdef HAVE_NETDEV_HEADER_OPS dev->header_ops = NULL; #else dev->hard_header = NULL; #ifdef HAVE_REBUILD_HEADER dev->rebuild_header = NULL; #endif dev->header_cache_update = NULL; dev->neigh_setup = NULL; #endif #ifdef HAVE_SET_MAC_ADDR dev->set_mac_address = NULL; #endif dev->mtu = 0; #endif /* DETACH_AND_DOWN */ prv->mtu = 0; for (i = 0; i < MAX_ADDR_LEN; i++) dev->dev_addr[i] = 0; dev->addr_len = 0; #ifdef PHYSDEV_TYPE dev->type = ARPHRD_VOID; /* ARPHRD_TUNNEL; */ #endif /* PHYSDEV_TYPE */ return 0; } /* * We call the clear routine to detach all ipsec tunnels from other devices. */ DEBUG_NO_STATIC int ipsec_tunnel_clear(void) { int i; struct net_device *ipsecdev = NULL, *prvdev; struct ipsecpriv *prv; int ret; KLIPS_PRINT(debug_tunnel & DB_TN_INIT, "klips_debug:ipsec_tunnel_clear: .\n"); for (i = 0; i < IPSEC_NUM_IFMAX; i++) { ipsecdev = ipsecdevices[i]; if (!ipsecdev || !netdev_priv(ipsecdev)) continue; prv = netdev_to_ipsecpriv(ipsecdev); if (!prv) continue; prvdev = (struct net_device *)(prv->dev); if (!prvdev) continue; KLIPS_PRINT(debug_tunnel & DB_TN_INIT, "klips_debug:ipsec_tunnel_clear: " "physical device for device %s is %s\n", ipsecdev->name, prvdev->name); if ((ret = ipsec_tunnel_detach(ipsecdev))) { KLIPS_PRINT(debug_tunnel & DB_TN_INIT, "klips_debug:ipsec_tunnel_clear: " "error %d detaching device %s from device %s.\n", ret, ipsecdev->name, prvdev->name); return ret; } } return 0; } /* * Used mostly for KLIPS to setup interface, for also with NETKEY when using * 2.6.23+ UDP XFRM code to mark sockets UDP_ENCAP_ESPINUDP_NON_IKE */ DEBUG_NO_STATIC int ipsec_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { /* struct ipsectunnelconf *cf = (struct ipsectunnelconf *)&ifr->ifr_data;*/ /* overlay our struct ipsectunnel onto ifr.ifr_ifru union (hope it fits!) */ struct ipsectunnelconf *cf = (struct ipsectunnelconf *)ifr->ifr_ifru.ifru_newname; struct ipsecpriv *prv = netdev_to_ipsecpriv(dev); struct net_device *them; /* physical device */ char *colon; char realphysname[IFNAMSIZ]; if (dev == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_INIT, "klips_debug:ipsec_tunnel_ioctl: " "device not supplied.\n"); return -ENODEV; } KLIPS_PRINT(debug_tunnel & DB_TN_INIT, "klips_debug:ipsec_tunnel_ioctl: " "tncfg service call #%d for dev=%s\n", cmd, dev->name ? dev->name : "NULL"); switch (cmd) { #if defined(KLIPS) /* attach a virtual ipsec? device to a physical device */ case IPSEC_SET_DEV: KLIPS_PRINT(debug_tunnel & DB_TN_INIT, "klips_debug:ipsec_tunnel_ioctl: " "calling ipsec_tunnel_attatch...\n"); /* If this is an IP alias interface, get its real physical name */ /* fill_and_terminate(realphysname, cf->cf_name, IFNAMSIZ); */ strncpy(realphysname, cf->cf_name, IFNAMSIZ-1); realphysname[IFNAMSIZ - 1] = 0; colon = strchr(realphysname, ':'); if (colon) *colon = 0; them = ipsec_dev_get(realphysname); if (them == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_INIT, "klips_debug:ipsec_tunnel_ioctl: " "physical device %s requested is null\n", cf->cf_name); return -ENXIO; } #if 0 if (them->flags & IFF_UP) { KLIPS_PRINT(debug_tunnel & DB_TN_INIT, "klips_debug:ipsec_tunnel_ioctl: " "physical device %s requested is not up.\n", cf->cf_name); ipsec_dev_put(them); return -ENXIO; } #endif if (prv && prv->dev) { KLIPS_PRINT(debug_tunnel & DB_TN_INIT, "klips_debug:ipsec_tunnel_ioctl: " "virtual device is already connected to %s.\n", prv->dev->name ? prv->dev->name : "NULL"); ipsec_dev_put(them); return -EBUSY; } return ipsec_tunnel_attach(dev, them); case IPSEC_DEL_DEV: KLIPS_PRINT(debug_tunnel & DB_TN_INIT, "klips_debug:ipsec_tunnel_ioctl: " "calling ipsec_tunnel_detatch.\n"); if (!prv->dev) { KLIPS_PRINT(debug_tunnel & DB_TN_INIT, "klips_debug:ipsec_tunnel_ioctl: " "physical device not connected.\n"); return -ENODEV; } return ipsec_tunnel_detach(dev); case IPSEC_CLR_DEV: KLIPS_PRINT(debug_tunnel & DB_TN_INIT, "klips_debug:ipsec_tunnel_ioctl: " "calling ipsec_tunnel_clear.\n"); return ipsec_tunnel_clear(); #endif /* KLIPS */ #ifdef HAVE_UDP_ENCAP_CONVERT /* * we get two int args in ifr_data, the socket fd (0) * and the type of encapsulation needed (1). */ case IPSEC_UDP_ENCAP_CONVERT: { /*unsigned int *ifp =(unsigned int *)&ifr->ifr_data;*/ /* overlay our struct ipsectunnel onto ifr.ifr_ifru union (hope it fits!) */ unsigned int *ifp = (unsigned int *)ifr->ifr_ifru.ifru_newname; return ipsec_tunnel_udp_encap_prepare(ifp[0], ifp[1]); } #endif /* HAVE_UDP_ENCAP_CONVERT */ default: KLIPS_PRINT(debug_tunnel & DB_TN_INIT, "klips_debug:ipsec_tunnel_ioctl: " "unknown command %d.\n", cmd); return -EOPNOTSUPP; } } #ifdef HAVE_UDP_ENCAP_CONVERT #define IPSEC_TUNNEL_UDP_ENCAP_MAGIC 0x58c0b472 struct ipsec_tunnel_udp_encap_ctx { u32 magic; struct list_head link; struct sock *sk; void (*old_sk_destruct)(struct sock *sk); }; #define list_head_to_udp_encap_ctx(lh) \ list_entry(lh, struct ipsec_tunnel_udp_encap_ctx, link) static DEFINE_SPINLOCK(ipsec_tunnel_udp_encap_lock); static LIST_HEAD(ipsec_tunnel_udp_encap_list); DEBUG_NO_STATIC int ipsec_tunnel_udp_encap_prepare(int fd, int encap_type) { struct socket *sock = NULL; struct sock *sk; struct ipsec_tunnel_udp_encap_ctx *ctx = NULL; unsigned long flags; int err = 0; switch (encap_type) { case UDP_ENCAP_ESPINUDP: case UDP_ENCAP_ESPINUDP_NON_IKE: break; default: printk("ipsec: pid %d sent fd %d with invalid encap_type %d\n", fd, current->pid, encap_type); return -EINVAL; } /* translate descriptor to socket structure */ err = -EBADF; sock = sockfd_lookup(fd, &err); if (!sock) { printk("ipsec: failed to lookup socket for fd %d for pid %d\n", fd, current->pid); goto error; } sk = sock->sk; /* Quick sanity checks */ err = -EAFNOSUPPORT; if (sock->ops->family != AF_INET) { printk("ipsec: pid %d sent fd %d with wrong family, " "got %d, expected %d\n", current->pid, fd, sock->ops->family, AF_INET); goto error; } err = -EPROTONOSUPPORT; if (sk->sk_protocol != IPPROTO_UDP) { printk("ipsec: pid %d sent fd %d with wrong protocol, " "got %d, expected %d\n", current->pid, fd, sk->sk_protocol, IPPROTO_UDP); goto error; } err = -EBUSY; if (udp_sk(sk)->encap_type) { printk("ipsec: pid %d sent fd %d with encap_type " "assigned to %d", current->pid, fd, udp_sk(sk)->encap_type); goto error; } err = -EBUSY; ctx = (struct ipsec_tunnel_udp_encap_ctx*)sk->sk_user_data; if (ctx) { printk("ipsec: pid %d sent fd %d with user_data assigned\n", current->pid, fd); goto error; } err = -ENOMEM; sk->sk_user_data = ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) goto error; /* setup the context */ ctx->magic = IPSEC_TUNNEL_UDP_ENCAP_MAGIC; ctx->sk = sk; ctx->old_sk_destruct = sk->sk_destruct; /* convert socket to use our (de)encapsulation routine */ sk->sk_destruct = ipsec_tunnel_udp_encap_destruct; udp_sk(sk)->encap_type = encap_type; udp_sk(sk)->encap_rcv = klips26_udp_encap_rcv; #ifdef NEED_UDP_ENCAP_ENABLE udp_encap_enable(); #endif spin_lock_irqsave(&ipsec_tunnel_udp_encap_lock, flags); /* add the tunnel to our list so we can check on it later */ list_add(&ctx->link, &ipsec_tunnel_udp_encap_list); spin_unlock_irqrestore(&ipsec_tunnel_udp_encap_lock, flags); KLIPS_PRINT(debug_tunnel, "UDP socket: %u set to %s (0x%x) encap mode\n", fd, encap_type == UDP_ENCAP_ESPINUDP_NON_IKE ? "UDP_ENCAP_ESPINUDP_NON_IKE" : "UDP_ENCAP_ESPINUDP_NON_ESP", encap_type ); /* success */ err = 0; error: if (sock) sockfd_put(sock); return err; } DEBUG_NO_STATIC void ipsec_tunnel_udp_encap_destruct(struct sock *sk) { struct ipsec_tunnel_udp_encap_ctx *ctx; unsigned long flags; if (!sk || !sk->sk_user_data) return; if (!sock_flag(sk, SOCK_DEAD)) { pr_err("Attempt to destruct a live pfkey socket: %p\n", sk); return; } ctx = (struct ipsec_tunnel_udp_encap_ctx*)sk->sk_user_data; if (ctx->magic != IPSEC_TUNNEL_UDP_ENCAP_MAGIC) { printk("ipsec: called to destroy ctx with wrong magic, " "got %08x, expected %08x\n", ctx->magic, IPSEC_TUNNEL_UDP_ENCAP_MAGIC); return; } if (ctx->sk != sk) { printk("ipsec: called to destroy ctx with sk(%p) != ctx->sk(%p)\n", sk, ctx->sk); return; } spin_lock_irqsave(&ipsec_tunnel_udp_encap_lock, flags); /* revert the socket back */ udp_sk(sk)->encap_type = 0; udp_sk(sk)->encap_rcv = NULL; sk->sk_user_data = NULL; sk->sk_destruct = ctx->old_sk_destruct; /* remove it from the list */ list_del(&ctx->link); ctx->sk = NULL; spin_unlock_irqrestore(&ipsec_tunnel_udp_encap_lock, flags); if (sk->sk_destruct) sk->sk_destruct(sk); kfree(ctx); } DEBUG_NO_STATIC void ipsec_tunnel_upd_encap_cleanup(void) { struct ipsec_tunnel_udp_encap_ctx *ctx, *tmp; unsigned long flags; int i = 0; /* wait a bit, see if we can cleanup nicely */ while (i++ < 60 && !list_empty(&ipsec_tunnel_udp_encap_list)) mdelay(50); /* * ok, if there is anything left now force it back to the old * destructor */ spin_lock_irqsave(&ipsec_tunnel_udp_encap_lock, flags); list_for_each_entry_safe(ctx, tmp, &ipsec_tunnel_udp_encap_list, link) { struct sock *sk = ctx->sk; /* revert the socket back */ udp_sk(sk)->encap_type = 0; udp_sk(sk)->encap_rcv = NULL; sk->sk_user_data = NULL; sk->sk_destruct = ctx->old_sk_destruct; /* remove it from the list */ list_del(&ctx->link); kfree(ctx); } spin_unlock_irqrestore(&ipsec_tunnel_udp_encap_lock, flags); } #endif struct net_device *ipsec_get_device(int inst) { struct net_device *ipsec_dev; ipsec_dev = NULL; if (inst < IPSEC_NUM_IFMAX) ipsec_dev = ipsecdevices[inst]; return ipsec_dev; } int ipsec_device_event(struct notifier_block *unused, unsigned long event, void *ptr) { #ifdef HAVE_NETDEV_INFO struct net_device *dev = netdev_notifier_info_to_dev(ptr); #else struct net_device *dev = ptr; #endif struct net_device *ipsec_dev; struct ipsecpriv *priv; int i; if (dev == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_INIT, "klips_debug:ipsec_device_event: " "dev=NULL for event type %ld.\n", event); return NOTIFY_DONE; } /* check for loopback devices */ if (dev && (dev->flags & IFF_LOOPBACK)) return NOTIFY_DONE; if (dev->name[0] == '\0') { KLIPS_PRINT(debug_tunnel & DB_TN_INIT, "klips_debug:ipsec_device_event: " "dev=\"\" ??? for event type.\n"); } switch (event) { case NETDEV_DOWN: /* look very carefully at the scope of these compiler directives before changing anything... -- RGB */ case NETDEV_UNREGISTER: #ifdef NETDEV_UNREGISTER_FINAL case NETDEV_UNREGISTER_FINAL: #endif switch (event) { case NETDEV_DOWN: KLIPS_PRINT(debug_tunnel & DB_TN_INIT, "klips_debug:ipsec_device_event: " "NETDEV_DOWN dev=%s flags=%x\n", dev->name, dev->flags); if (strncmp(dev->name, "ipsec", strlen("ipsec")) == 0) { printk(KERN_CRIT "IPSEC EVENT: KLIPS device %s shut down.\n", dev->name); } break; case NETDEV_UNREGISTER: KLIPS_PRINT(debug_tunnel & DB_TN_INIT, "klips_debug:ipsec_device_event: " "NETDEV_UNREGISTER dev=%s flags=%x\n", dev->name, dev->flags); break; #ifdef NETDEV_UNREGISTER_FINAL case NETDEV_UNREGISTER_FINAL: KLIPS_PRINT(debug_tunnel & DB_TN_INIT, "klips_debug:ipsec_device_event: " "NETDEV_UNREGISTER_FINAL dev=%s flags=%x\n", dev->name, dev->flags); break; #endif } /* find the attached physical device and detach it. */ for (i = 0; i < IPSEC_NUM_IFMAX; i++) { ipsec_dev = ipsecdevices[i]; if (!ipsec_dev || !netdev_priv(ipsec_dev)) continue; priv = netdev_to_ipsecpriv(ipsec_dev); if (priv) { if (((struct net_device *)(priv->dev)) == dev) { ipsec_tunnel_detach(ipsec_dev); KLIPS_PRINT(debug_tunnel & DB_TN_INIT, "klips_debug:ipsec_device_event: " "device '%s' has been detached.\n", ipsec_dev->name); break; } } else { KLIPS_PRINT(debug_tunnel & DB_TN_INIT, "klips_debug:ipsec_device_event: " "device '%s' has no private data space!\n", ipsec_dev->name); } } break; case NETDEV_UP: KLIPS_PRINT(debug_tunnel & DB_TN_INIT, "klips_debug:ipsec_device_event: " "NETDEV_UP dev=%s\n", dev->name); break; case NETDEV_REBOOT: KLIPS_PRINT(debug_tunnel & DB_TN_INIT, "klips_debug:ipsec_device_event: " "NETDEV_REBOOT dev=%s\n", dev->name); break; case NETDEV_CHANGE: KLIPS_PRINT(debug_tunnel & DB_TN_INIT, "klips_debug:ipsec_device_event: " "NETDEV_CHANGE dev=%s flags=%x\n", dev->name, dev->flags); break; case NETDEV_REGISTER: KLIPS_PRINT(debug_tunnel & DB_TN_INIT, "klips_debug:ipsec_device_event: " "NETDEV_REGISTER dev=%s\n", dev->name); break; case NETDEV_CHANGEMTU: KLIPS_PRINT(debug_tunnel & DB_TN_INIT, "klips_debug:ipsec_device_event: " "NETDEV_CHANGEMTU dev=%s to mtu=%d\n", dev->name, dev->mtu); break; case NETDEV_CHANGEADDR: KLIPS_PRINT(debug_tunnel & DB_TN_INIT, "klips_debug:ipsec_device_event: " "NETDEV_CHANGEADDR dev=%s\n", dev->name); break; case NETDEV_GOING_DOWN: KLIPS_PRINT(debug_tunnel & DB_TN_INIT, "klips_debug:ipsec_device_event: " "NETDEV_GOING_DOWN dev=%s\n", dev->name); break; case NETDEV_CHANGENAME: KLIPS_PRINT(debug_tunnel & DB_TN_INIT, "klips_debug:ipsec_device_event: " "NETDEV_CHANGENAME dev=%s\n", dev->name); break; default: KLIPS_PRINT(debug_tunnel & DB_TN_INIT, "klips_debug:ipsec_device_event: " "event type %ld unrecognised for dev=%s\n", event, dev->name); break; } return NOTIFY_DONE; } /* * Called when an ipsec tunnel device is initialized. * The ipsec tunnel device structure is passed to us. */ int ipsec_tunnel_init(struct net_device *dev) { int i; struct ipsecpriv *iprv; KLIPS_PRINT(debug_tunnel, "klips_debug:ipsec_tunnel_init: " "allocating %zu bytes initialising device: %s\n", sizeof(struct ipsecpriv), dev->name ? dev->name : "NULL"); #ifdef ipsec_alloc_netdev # ifdef HAS_PRIV_DESTRUCTOR dev->priv_destructor = free_netdev; # else dev->destructor = free_netdev; # endif #endif #ifndef HAVE_NETDEV_PRIV { struct ipsecpriv *priv_dev; priv_dev = kmalloc(sizeof(struct ipsecpriv), GFP_KERNEL); if (priv_dev == NULL) return; dev->priv = priv_dev; } #endif iprv = netdev_priv(dev); memset(iprv, 0, sizeof(struct ipsecpriv)); iprv->magic = IPSECPRIV_MAGIC; for (i = 0; i < sizeof(zeroes); i++) ((__u8*)(zeroes))[i] = 0; #ifdef HAVE_NETDEV_HEADER_OPS dev->header_ops = NULL; #else dev->hard_header = NULL; #ifdef HAVE_REBUILD_HEADER dev->rebuild_header = NULL; #endif dev->header_cache_update = NULL; #endif #ifdef HAVE_NET_DEVICE_OPS dev->netdev_ops = &klips_device_ops; #else dev->open = ipsec_tunnel_open; dev->stop = ipsec_tunnel_close; dev->hard_start_xmit = ipsec_tunnel_start_xmit; dev->get_stats = ipsec_tunnel_get_stats; #ifdef HAVE_SET_MAC_ADDR dev->set_mac_address = NULL; #endif dev->do_ioctl = ipsec_tunnel_ioctl; dev->neigh_setup = ipsec_tunnel_neigh_setup_dev; #endif dev->hard_header_len = 0; dev->mtu = 0; dev->addr_len = 0; dev->type = ARPHRD_VOID; /* ARPHRD_TUNNEL; */ /* ARPHRD_ETHER; */ dev->tx_queue_len = 10; /* Small queue */ #ifdef IFF_XMIT_DST_RELEASE dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; #endif memset((caddr_t)(dev->broadcast), 0xFF, ETH_ALEN); /* what if this is not attached to ethernet? */ /* New-style flags. */ dev->flags = IFF_NOARP /* 0 */ /* Petr Novak */; /* We're done. Have I forgotten anything? */ return 0; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* Module specific interface (but it links with the rest of IPSEC) */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ int ipsec_tunnel_probe(struct net_device *dev) { ipsec_tunnel_init(dev); return 0; } #ifdef ipsec_alloc_netdev static void ipsec_tunnel_netdev_setup(struct net_device *dev) { } #endif struct net_device *ipsecdevices[IPSEC_NUM_IFMAX]; int ipsecdevices_max = -1; int ipsec_tunnel_createnum(int ifnum) { char name[IFNAMSIZ]; struct net_device *dev_ipsec; int vifentry; if (ifnum >= IPSEC_NUM_IFMAX) return -ENOENT; if (ipsecdevices[ifnum] != NULL) return -EEXIST; /* no identical device */ if (ifnum > ipsecdevices_max) ipsecdevices_max = ifnum; vifentry = ifnum; KLIPS_PRINT(debug_tunnel & DB_TN_INIT, "klips_debug:ipsec_tunnel_init_devices: " "creating and registering IPSEC_NUM_IF=%u device\n", ifnum); sprintf(name, IPSEC_DEV_FORMAT, ifnum); #ifdef alloc_netdev dev_ipsec = ipsec_alloc_netdev(sizeof(struct ipsecpriv), name, NET_NAME_UNKNOWN, ipsec_tunnel_netdev_setup); #else dev_ipsec = (struct net_device*)kmalloc(sizeof(struct net_device), GFP_KERNEL); #endif if (dev_ipsec == NULL) { printk(KERN_ERR "klips_debug:ipsec_tunnel_init_devices: " "failed to allocate memory for device %s, quitting device init.\n", name); return -ENOMEM; } #ifndef ipsec_alloc_netdev memset((caddr_t)dev_ipsec, 0, sizeof(struct net_device)); /* fill_and_terminate(dev_ipsec->name, name, sizeof(dev_ipsec->name)); */ strncpy(dev_ipsec->name, name, sizeof(dev_ipsec->name)-1); dev_ipsec->name[sizeof(dev_ipsec->name)-1] ='\0'; #ifdef PAUL_FIXME dev_ipsec->next = NULL; #endif #endif /* ipsec_alloc_netdev */ #ifndef USE_NETDEV_OPS dev_ipsec->init = &ipsec_tunnel_probe; #else dev_ipsec->netdev_ops = &klips_device_ops; #endif KLIPS_PRINT(debug_tunnel & DB_TN_INIT, "klips_debug:ipsec_tunnel_init_devices: " "registering device %s\n", dev_ipsec->name); /* reference and hold the device reference */ ipsec_dev_hold(dev_ipsec); ipsecdevices[vifentry] = dev_ipsec; if (register_netdev(dev_ipsec) != 0) { KLIPS_PRINT(1 || debug_tunnel & DB_TN_INIT, "klips_debug:ipsec_tunnel_init_devices: " "registering device %s failed, quitting device init.\n", dev_ipsec->name); return -EIO; } else { KLIPS_PRINT(debug_tunnel & DB_TN_INIT, "klips_debug:ipsec_tunnel_init_devices: " "registering device %s succeeded, continuing...\n", dev_ipsec->name); } return 0; } int ipsec_tunnel_init_devices(void) { int i; int error; KLIPS_PRINT(debug_tunnel & DB_TN_INIT, "klips_debug:ipsec_tunnel_init_devices: " "creating and registering IPSEC_NUM_IF=%u devices, allocating %zu per device, IFNAMSIZ=%u.\n", IPSEC_NUM_IF, sizeof(struct net_device) + IFNAMSIZ, IFNAMSIZ); for (i = 0; i < IPSEC_NUM_IF; i++) { error = ipsec_tunnel_createnum(i); if (error) break; } return 0; } int ipsec_tunnel_deletenum(int vifnum) { struct net_device *dev_ipsec; if (vifnum >= IPSEC_NUM_IFMAX) return -ENOENT; dev_ipsec = ipsecdevices[vifnum]; if (dev_ipsec == NULL) return -ENOENT; /* release reference */ ipsecdevices[vifnum] = NULL; ipsec_dev_put(dev_ipsec); KLIPS_PRINT(debug_tunnel, "Unregistering %s\n", dev_ipsec->name); unregister_netdev(dev_ipsec); KLIPS_PRINT(debug_tunnel, "Unregistered %s\n", dev_ipsec->name); #ifndef ipsec_alloc_netdev kfree(dev_ipsec->priv); dev_ipsec->priv = NULL; #endif /* ipsec_alloc_netdev */ return 0; } struct net_device *ipsec_tunnel_get_device(int vifnum) { struct net_device *nd; if (vifnum < ipsecdevices_max) { nd = ipsecdevices[vifnum]; if (nd) ipsec_dev_hold(nd); return nd; } else { return NULL; } } /* void */ int ipsec_tunnel_cleanup_devices(void) { int error = 0; int i; struct net_device *dev_ipsec; for (i = 0; i <= ipsecdevices_max; i++) { dev_ipsec = ipsecdevices[i]; if (dev_ipsec == NULL) continue; /* release reference */ ipsecdevices[i] = NULL; ipsec_dev_put(dev_ipsec); KLIPS_PRINT(debug_tunnel, "Unregistering %s\n", dev_ipsec->name); unregister_netdev(dev_ipsec); KLIPS_PRINT(debug_tunnel, "Unregistered %s\n", dev_ipsec->name); #ifndef ipsec_alloc_netdev kfree(dev_ipsec->priv); dev_ipsec->priv = NULL; #endif /* ipsec_alloc_netdev */ } #ifdef HAVE_UDP_ENCAP_CONVERT /* once all devices are down, it's time to restore UDP connections to * not use as for (de)encapsulation anymore */ ipsec_tunnel_upd_encap_cleanup(); #endif return error; } /* ------------------------------------------------------------------------ * this handles creating and managing state for xmit path */ static DEFINE_SPINLOCK(ixs_cache_lock); #ifdef HAVE_KMEM_CACHE_MACRO static struct kmem_cache *ixs_cache_allocator = NULL; #else static kmem_cache_t *ixs_cache_allocator = NULL; #endif static unsigned ixs_cache_allocated_count = 0; int ipsec_ixs_cache_allocated_max = 1000; module_param(ipsec_ixs_cache_allocated_max, int, 0644); MODULE_PARM_DESC(ipsec_ixs_cache_allocated_max, "Maximum outstanding transmit packets"); int ipsec_xmit_state_cache_init(void) { if (ixs_cache_allocator) return -EBUSY; spin_lock_init(&ixs_cache_lock); #ifdef HAVE_KMEM_CACHE_MACRO /* ixs_cache_allocator = KMEM_CACHE(ipsec_ixs,0); */ ixs_cache_allocator = kmem_cache_create("ipsec_ixs", sizeof(struct ipsec_xmit_state), 0, 0, NULL); #else ixs_cache_allocator = kmem_cache_create("ipsec_ixs", sizeof(struct ipsec_xmit_state), 0, 0, NULL, NULL); #endif if (!ixs_cache_allocator) return -ENOMEM; return 0; } void ipsec_xmit_state_cache_cleanup(void) { if (unlikely(ixs_cache_allocated_count)) printk("ipsec: deleting ipsec_ixs kmem_cache while in use\n"); if (ixs_cache_allocator) { kmem_cache_destroy(ixs_cache_allocator); ixs_cache_allocator = NULL; } ixs_cache_allocated_count = 0; } struct ipsec_xmit_state *ipsec_xmit_state_new(struct net_device *dev) { struct ipsec_xmit_state *ixs; spin_lock_bh(&ixs_cache_lock); if (ixs_cache_allocated_count >= ipsec_ixs_cache_allocated_max) { /* check for something that should never happen */ if (!netif_queue_stopped(dev)) { netif_stop_queue(dev); printk("ipsec_tunnel_start_xmit: cannot TX while awake\n"); } spin_unlock_bh(&ixs_cache_lock); KLIPS_PRINT(debug_tunnel, "klips_debug:ipsec_xmit_state_new: " "exceeded maximum outstanding TX packet cnt %d\n", ixs_cache_allocated_count); return NULL; } ixs = kmem_cache_alloc(ixs_cache_allocator, GFP_ATOMIC); if (likely(ixs != NULL)) { ixs_cache_allocated_count++; /* stop the Q if we took the last one */ if (ixs_cache_allocated_count >= ipsec_ixs_cache_allocated_max) netif_stop_queue(dev); } spin_unlock_bh(&ixs_cache_lock); if (unlikely(NULL == ixs)) return NULL; /* initialize the object */ #if 1 /* optimised to only clear the required bits */ memset((caddr_t)ixs, 0, sizeof(*ixs)); #else ixs->pass = 0; ixs->state = 0; ixs->next_state = 0; ixs->ipsp = NULL; ixs->sa_len = 0; ixs->stats = NULL; ixs->ips.ips_ident_s.data = NULL; ixs->ips.ips_ident_d.data = NULL; ixs->outgoing_said.proto = 0; ixs->natt_type = 0, ixs->natt_head = 0; ixs->natt_sport = 0, ixs->natt_dport = 0; ixs->tot_headroom = 0; ixs->tot_tailroom = 0; ixs->eroute = NULL; ixs->hard_header_stripped = 0; ixs->hard_header_len = 0; ixs->cur_mtu = 0; /* FIXME: can we do something better ? */ ixs->oskb = NULL; ixs->saved_header = NULL; /* saved copy of the hard header */ ixs->route = NULL; #endif /* memset */ return ixs; } void ipsec_xmit_state_delete(struct ipsec_xmit_state *ixs) { struct net_device *dev; if (unlikely(!ixs)) return; dev = ixs->dev; spin_lock_bh(&ixs_cache_lock); ixs_cache_allocated_count--; kmem_cache_free(ixs_cache_allocator, ixs); #if defined(HAS_NETIF_QUEUE) || defined (HAVE_NETIF_QUEUE) if (dev && netif_queue_stopped(dev)) netif_wake_queue(dev); #else /* defined(HAS_NETIF_QUEUE) || defined (HAVE_NETIF_QUEUE) */ if (dev) dev->tbusy = 0; #endif /* defined(HAS_NETIF_QUEUE) || defined (HAVE_NETIF_QUEUE) */ spin_unlock_bh(&ixs_cache_lock); } #ifdef HAVE_NET_DEVICE_OPS const struct net_device_ops klips_device_ops = { /* Add our tunnel functions to the device */ .ndo_init = ipsec_tunnel_probe, .ndo_open = ipsec_tunnel_open, .ndo_stop = ipsec_tunnel_close, .ndo_start_xmit = ipsec_tunnel_start_xmit, .ndo_get_stats = ipsec_tunnel_get_stats, .ndo_neigh_setup = ipsec_tunnel_neigh_setup_dev, .ndo_do_ioctl = ipsec_tunnel_ioctl, #ifdef HAVE_SET_MAC_ADDR .ndo_set_mac_address = ipsec_tunnel_set_mac_address, #endif }; #endif /* * We call the attach routine to attach another device. */ DEBUG_NO_STATIC int ipsec_tunnel_attach(struct net_device *dev, struct net_device *physdev) { int i; struct ipsecpriv *prv = netdev_to_ipsecpriv(dev); if (dev == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_attach: " "no device..."); return -ENODEV; } if (prv == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, "klips_debug:ipsec_tunnel_attach: " "no private space associated with dev=%s", dev->name ? dev->name : "NULL"); return -ENODATA; } #ifdef HAVE_NETDEV_HEADER_OPS dev->header_ops = &klips_header_ops; #endif #ifdef HAVE_NET_DEVICE_OPS dev->netdev_ops = &klips_device_ops; #else # ifdef HAVE_SET_MAC_ADDR dev->set_mac_address = ipsec_tunnel_set_mac_address; # endif #endif /* HAVE_NET_DEVICE_OPS */ prv->dev = physdev; #ifdef HAVE_NET_DEVICE_OPS prv->hard_start_xmit = physdev->netdev_ops->ndo_start_xmit; prv->get_stats = physdev->netdev_ops->ndo_get_stats; #else prv->hard_start_xmit = physdev->hard_start_xmit; prv->get_stats = physdev->get_stats; #endif /* * David: I haven't worked through this fully yet, but we were * always copying SKB's because they didn't have enough head room * (even though they were large SKB's). This change got me a 20% * improvement (on TX IIRC) */ dev->hard_header_len = physdev->hard_header_len + 64; /* prv->neigh_setup = physdev->neigh_setup; */ dev->mtu = 16260; /* 0xfff0; */ /* dev->mtu; */ prv->mtu = physdev->mtu; #ifdef PHYSDEV_TYPE dev->type = physdev->type; /* ARPHRD_TUNNEL; */ #endif /* PHYSDEV_TYPE */ dev->addr_len = physdev->addr_len; for (i = 0; i < dev->addr_len; i++) dev->dev_addr[i] = physdev->dev_addr[i]; #ifdef CONFIG_KLIPS_DEBUG if (debug_tunnel & DB_TN_INIT) { printk(KERN_INFO "klips_debug:ipsec_tunnel_attach: " "physical device %s being attached has HW address: %2x", physdev->name, physdev->dev_addr[0]); for (i = 1; i < physdev->addr_len; i++) printk(":%02x", physdev->dev_addr[i]); printk("\n"); } #endif /* CONFIG_KLIPS_DEBUG */ return 0; } #ifdef CONFIG_KLIPS_IPV6 /* * stolen from ip6tables, we need a copy in case iptables is compiled out of * the kernel. * * find the offset to specified header or the protocol number of last header * if target < 0. "last header" is transport protocol header, ESP, or * "No next header". * * If target header is found, its offset is set in *offset and return protocol * number. Otherwise, return -1. * * If the first fragment doesn't contain the final protocol header or * NEXTHDR_NONE it is considered invalid. * * Note that non-1st fragment is special case that "the protocol number * of last header" is "next header" field in Fragment header. In this case, * *offset is meaningless and fragment offset is stored in *fragoff if fragoff * isn't NULL. * */ int lsw_ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, int target, unsigned short *fragoff) { unsigned int start = skb_network_offset(skb) + sizeof(struct ipv6hdr); u8 nexthdr = ipv6_hdr(skb)->nexthdr; unsigned int len = skb->len - start; if (fragoff) *fragoff = 0; while (nexthdr != target) { struct ipv6_opt_hdr _hdr, *hp; unsigned int hdrlen; if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE) { if (target < 0) break; return -ENOENT; } hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr); if (hp == NULL) return -EBADMSG; if (nexthdr == NEXTHDR_FRAGMENT) { unsigned short _frag_off; __be16 *fp; fp = skb_header_pointer(skb, start + offsetof(struct frag_hdr, frag_off), sizeof(_frag_off), &_frag_off); if (fp == NULL) return -EBADMSG; _frag_off = ntohs(*fp) & ~0x7; if (_frag_off) { if (target < 0 && ((!ipv6_ext_hdr(hp->nexthdr)) || hp->nexthdr == NEXTHDR_NONE)) { if (fragoff) *fragoff = _frag_off; return hp->nexthdr; } return -ENOENT; } hdrlen = 8; } else if (nexthdr == NEXTHDR_AUTH) { hdrlen = (hp->hdrlen + 2) << 2; } else { hdrlen = ipv6_optlen(hp); } nexthdr = hp->nexthdr; len -= hdrlen; start += hdrlen; } *offset = start; return nexthdr; } #endif /* CONFIG_KLIPS_IPV6 */ libreswan-3.32/linux/net/ipsec/ipsec_xmit.c000066400000000000000000002577031365625662500210250ustar00rootroot00000000000000/* * IPSEC Transmit code. * Copyright (C) 1996, 1997 John Ioannidis. * Copyright (C) 1998-2003 Richard Guy Briggs. * Copyright (C) 2004-2005 Michael Richardson * Copyright (C) 2010-2012 David McCullough * Copyright (C) 2012 Paul Wouters * * OCF/receive state machine written by * David McCullough * Copyright (C) 2004-2005 Intel Corporation. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #define __NO_VERSION__ #include #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38) && \ !defined(AUTOCONF_INCLUDED) #include #endif /* for CONFIG_IP_FORWARD */ #include /* printk() */ #include "libreswan/ipsec_param.h" #include /* kmalloc() */ #include /* error codes */ #include /* size_t */ #include /* mark_bh */ #include /* struct device, struct net_device_stats, dev_queue_xmit() and other headers */ #include /* eth_type_trans */ #include /* struct iphdr */ #ifdef CONFIG_KLIPS_IPV6 #include /* struct iphdr */ #endif /* CONFIG_KLIPS_IPV6 */ #include #include #ifdef CONFIG_KLIPS_IPV6 #include #endif /* CONFIG_KLIPS_IPV6 */ #include #include #include #include "libreswan/ipsec_param2.h" #include # define MSS_HACK_ /* experimental */ # include # include # define proto_priv cb #include /* icmp_send() */ #include #include #include #ifdef MSS_HACK_DELETE_ME_PLEASE # include /* TCP options */ #endif /* MSS_HACK_DELETE_ME_PLEASE */ #include "libreswan/ipsec_kversion.h" #include "libreswan/radij.h" #include "libreswan/ipsec_life.h" #include "libreswan/ipsec_xform.h" #include "libreswan/ipsec_eroute.h" #include "libreswan/ipsec_encap.h" #include "libreswan/ipsec_radij.h" #include "libreswan/ipsec_xmit.h" #include "libreswan/ipsec_sa.h" #include "libreswan/ipsec_tunnel.h" #include "libreswan/ipsec_ipe4.h" #include "libreswan/ipsec_ah.h" #include "libreswan/ipsec_esp.h" #include "libreswan/ipsec_mast.h" #ifdef CONFIG_KLIPS_IPCOMP #include "libreswan/ipcomp.h" #endif /* CONFIG_KLIPS_IPCOMP */ #include #include #include "libreswan/ipsec_proto.h" #include "libreswan/ipsec_alg.h" #ifdef CONFIG_KLIPS_OCF # include "ipsec_ocf.h" #endif #if defined(CONFIG_KLIPS_AH) #if defined(CONFIG_KLIPS_AUTH_HMAC_MD5) || defined(CONFIG_KLIPS_AUTH_HMAC_SHA1) || defined(CONFIG_KLIPS_ALG) static __u32 zeroes[64]; #endif #endif static int ipsec_set_dst(struct ipsec_xmit_state *ixs); int ipsec_xmit_trap_count = 0; int ipsec_xmit_trap_sendcount = 0; #define dmp(_x, _y, _z) if (debug_xmit && sysctl_ipsec_debug_verbose) \ ipsec_dmp_block(_x, _y, _z) #if defined(KLIPS_UNIT_TESTS) # ifdef CONFIG_KLIPS_IPV6 # error "this code is broken for IPv6" # endif /* * This is mostly skbuff.c:skb_copy(). */ struct sk_buff *skb_copy_expand(const struct sk_buff *skb, int headroom, int tailroom, int priority) { struct sk_buff *n; unsigned long offset; /* * Do sanity checking */ if ((headroom < 0) || (tailroom < 0) || ((headroom + tailroom) < 0)) { printk(KERN_WARNING "klips_error:skb_copy_expand: " "Illegal negative head,tailroom %d,%d\n", headroom, tailroom); return NULL; } /* * Allocate the copy buffer */ n = alloc_skb(skb->end - skb->head + headroom + tailroom, priority); KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, "klips_debug:skb_copy_expand: " "allocating %d bytes, head=0p%p data=0p%p tail=0p%p end=0p%p end-head=%d tail-data=%d\n", skb->end - skb->head + headroom + tailroom, skb->head, skb->data, skb->tail, skb->end, skb->end - skb->head, skb->tail - skb->data); if (n == NULL) return NULL; /* * Shift between the two data areas in bytes */ /* Set the data pointer */ skb_reserve(n, skb->data - skb->head + headroom); /* Set the tail pointer and length */ if (skb_tailroom(n) < skb->len) { printk(KERN_WARNING "klips_error:skb_copy_expand: " "tried to skb_put %ld, %d available. This should never happen, please report.\n", (unsigned long int)skb->len, skb_tailroom(n)); ipsec_kfree_skb(n); return NULL; } skb_put(n, skb->len); offset = n->head + headroom - skb->head; /* Copy the bytes */ memcpy(n->head + headroom, skb->head, skb->end - skb->head); n->csum = skb->csum; n->priority = skb->priority; skb_dst_set(n, dst_clone(skb_dst(skb))); if (skb->nh.raw) n->nh.raw = skb->nh.raw + offset; atomic_set(&n->users, 1); n->destructor = NULL; #ifdef HAVE_SOCK_SECURITY n->security = skb->security; #endif n->protocol = skb->protocol; n->list = NULL; n->sk = NULL; n->dev = skb->dev; if (skb->h.raw) n->h.raw = skb->h.raw + offset; if (skb->mac.raw) n->mac.raw = skb->mac.raw + offset; memcpy(n->proto_priv, skb->proto_priv, sizeof(skb->proto_priv)); n->pkt_type = skb->pkt_type; n->stamp = skb->stamp; return n; } #endif /* KLIPS_UNIT_TESTS */ static void ipsec_print_ip4(struct iphdr *ip) { char buf[ADDRTOA_BUF]; struct tcphdr *tcphdr = NULL; if (!ip) return; /* we are taking some liberties here assuming that the IP and TCP * headers are contiguous in memory */ switch (ip->protocol) { case IPPROTO_TCP: case IPPROTO_UDP: /* NOTE: we only use this for getting port numbers, and they * are at the same offsets for both tcp and udp headers */ tcphdr = (struct tcphdr*)((caddr_t)ip + (ip->ihl << 2)); break; } printk(KERN_INFO "klips_debug: IP:"); printk(" ihl:%d", ip->ihl << 2); printk(" ver:%d", ip->version); printk(" tos:%d", ip->tos); printk(" tlen:%d", ntohs(ip->tot_len)); printk(" id:%d", ntohs(ip->id)); printk(" %s%s%sfrag_off:%d", ip->frag_off & __constant_htons(IP_CE) ? "CE " : "", ip->frag_off & __constant_htons(IP_DF) ? "DF " : "", ip->frag_off & __constant_htons(IP_MF) ? "MF " : "", (ntohs(ip->frag_off) & IP_OFFSET) << 3); printk(" ttl:%d", ip->ttl); printk(" proto:%d", ip->protocol); if (ip->protocol == IPPROTO_UDP) printk(" (UDP)"); if (ip->protocol == IPPROTO_TCP) printk(" (TCP)"); if (ip->protocol == IPPROTO_ICMP) printk(" (ICMP)"); if (ip->protocol == IPPROTO_ESP) printk(" (ESP)"); if (ip->protocol == IPPROTO_AH) printk(" (AH)"); if (ip->protocol == IPPROTO_COMP) printk(" (COMP)"); printk(" chk:%d", ntohs(ip->check)); addrtoa(*((struct in_addr*)(&ip->saddr)), 0, buf, sizeof(buf)); printk(" saddr:%s", buf); if (tcphdr) printk(":%d", ntohs(tcphdr->source)); addrtoa(*((struct in_addr*)(&ip->daddr)), 0, buf, sizeof(buf)); printk(" daddr:%s", buf); if (tcphdr) printk(":%d", ntohs(tcphdr->dest)); if (ip->protocol == IPPROTO_ICMP) { printk(" type:code=%d:%d", ((struct icmphdr*)((caddr_t)ip + (ip->ihl << 2)))->type, ((struct icmphdr*)((caddr_t)ip + (ip->ihl << 2)))->code); } if (ip->protocol == IPPROTO_TCP) { printk(" seq=%u ack=%u", tcphdr->seq, tcphdr->ack_seq); if (tcphdr->fin) printk(" FIN"); if (tcphdr->syn) printk(" SYN"); if (tcphdr->rst) printk(" RST"); if (tcphdr->psh) printk(" PSH"); if (tcphdr->ack) printk(" ACK"); if (tcphdr->urg) printk(" URG"); if (tcphdr->ece) printk(" ECE"); if (tcphdr->cwr) printk(" CWR"); } printk("\n"); if (sysctl_ipsec_debug_verbose) { __u8 *c; int len = ntohs(ip->tot_len) - ip->ihl * 4; c = ((__u8*)ip) + ip->ihl * 4; ipsec_dmp_block("ip_print", c, len); } } #ifdef CONFIG_KLIPS_IPV6 static void ipsec_print_ip6(struct ipv6hdr *ip) { char buf[ADDRTOA_BUF]; printk(KERN_INFO "klips_debug: IPV6:"); printk(" prio:%d", ip->priority); printk(" ver:%d", ip->version); printk(" flow:%02x%02x%02x", ip->flow_lbl[0], ip->flow_lbl[1], ip->flow_lbl[2]); printk(" pllen:%d", ntohs(ip->payload_len)); printk(" hopl:%d", ip->hop_limit); printk(" nexthdr:%d", ip->nexthdr); if (ip->nexthdr == IPPROTO_UDP) printk(" (UDP)"); if (ip->nexthdr == IPPROTO_TCP) printk(" (TCP)"); if (ip->nexthdr == IPPROTO_ICMP) printk(" (ICMP)"); if (ip->nexthdr == IPPROTO_ICMPV6) printk(" (ICMP)"); if (ip->nexthdr == IPPROTO_ESP) printk(" (ESP)"); if (ip->nexthdr == IPPROTO_AH) printk(" (AH)"); if (ip->nexthdr == IPPROTO_COMP) printk(" (COMP)"); inet_addrtot(AF_INET6, &ip->saddr, 0, buf, sizeof(buf)); printk(" saddr:%s", buf); #if 0 if (ip->protocol == IPPROTO_UDP) printk(":%d", ntohs(((struct udphdr*)((caddr_t)ip + (ip->ihl << 2)))->source)); if (ip->protocol == IPPROTO_TCP) printk(":%d", ntohs(((struct tcphdr*)((caddr_t)ip + (ip->ihl << 2)))->source)); #endif inet_addrtot(AF_INET6, &ip->daddr, 0, buf, sizeof(buf)); printk(" daddr:%s", buf); #if 0 if (ip->protocol == IPPROTO_UDP) printk(":%d", ntohs(((struct udphdr*)((caddr_t)ip + (ip->ihl << 2)))->dest)); if (ip->protocol == IPPROTO_TCP) printk(":%d", ntohs(((struct tcphdr*)((caddr_t)ip + (ip->ihl << 2)))->dest)); if (ip->protocol == IPPROTO_ICMP) printk(" type:code=%d:%d", ((struct icmphdr*)((caddr_t)ip + (ip->ihl << 2)))->type, ((struct icmphdr*)((caddr_t)ip + (ip->ihl << 2)))->code); #endif printk("\n"); if (sysctl_ipsec_debug_verbose) { __u8 *c; int len = ntohs(ip->payload_len); c = (__u8 *)&ip[1]; ipsec_dmp_block("ip_print", c, len); } } #endif /* CONFIG_KLIPS_IPV6 */ void ipsec_print_ip(void *ip) { #ifdef CONFIG_KLIPS_IPV6 if (((struct iphdr *) ip)->version == 6) ipsec_print_ip6((struct ipv6hdr *) ip); else #endif ipsec_print_ip4((struct iphdr *) ip); } #ifdef MSS_HACK_DELETE_ME_PLEASE /* * Issues: * 1) Fragments arriving in the tunnel should probably be rejected. * 2) How does this affect syncookies, mss_cache, dst cache ? * 3) Path MTU discovery handling needs to be reviewed. For example, * if we receive an ICMP 'packet too big' message from an intermediate * router specifying its next hop MTU, our stack may process this and * adjust the MSS without taking our AH/ESP overheads into account. */ /* * Recaclulate checksum using differences between changed datum, * borrowed from netfilter. */ DEBUG_NO_STATIC u_int16_t ipsec_fast_csum(u_int32_t oldvalinv, u_int32_t newval, u_int16_t oldcheck) { u_int32_t diffs[] = { oldvalinv, newval }; return csum_fold(csum_partial((char *)diffs, sizeof(diffs), oldcheck ^ 0xFFFF)); } /* * Determine effective MSS. * * Note that we assume that there is always an MSS option for our own * SYN segments, which is mentioned in tcp_syn_build_options(), kernel 2.2.x. * This could change, and we should probably parse TCP options instead. * */ DEBUG_NO_STATIC u_int8_t ipsec_adjust_mss(struct sk_buff *skb, struct tcphdr *tcph, u_int16_t mtu) { u_int16_t oldmss, newmss; u_int32_t *mssp; struct sock *sk = skb->sk; newmss = tcp_sync_mss(sk, mtu); printk(KERN_INFO "klips: setting mss to %u\n", newmss); mssp = (u_int32_t *)tcph + sizeof(struct tcphdr) / sizeof(u_int32_t); oldmss = ntohl(*mssp) & 0x0000FFFF; *mssp = htonl((TCPOPT_MSS << 24) | (TCPOLEN_MSS << 16) | newmss); tcph->check = ipsec_fast_csum(htons(~oldmss), htons(newmss), tcph->check); return 1; } #endif /* MSS_HACK_DELETE_ME_PLEASE */ /* NOTE: may return a pointer to a static buffer */ DEBUG_NO_STATIC const char *ipsec_xmit_err(int err) { static char tmp[32]; switch ((int) err) { case IPSEC_XMIT_STOLEN: return "IPSEC_XMIT_STOLEN"; case IPSEC_XMIT_PASS: return "IPSEC_XMIT_PASS"; case IPSEC_XMIT_OK: return "IPSEC_XMIT_OK"; case IPSEC_XMIT_ERRMEMALLOC: return "IPSEC_XMIT_ERRMEMALLOC"; case IPSEC_XMIT_ESP_BADALG: return "IPSEC_XMIT_ESP_BADALG"; case IPSEC_XMIT_BADPROTO: return "IPSEC_XMIT_BADPROTO"; case IPSEC_XMIT_ESP_PUSHPULLERR: return "IPSEC_XMIT_ESP_PUSHPULLERR"; case IPSEC_XMIT_BADLEN: return "IPSEC_XMIT_BADLEN"; case IPSEC_XMIT_AH_BADALG: return "IPSEC_XMIT_AH_BADALG"; case IPSEC_XMIT_SAIDNOTFOUND: return "IPSEC_XMIT_SAIDNOTFOUND"; case IPSEC_XMIT_SAIDNOTLIVE: return "IPSEC_XMIT_SAIDNOTLIVE"; case IPSEC_XMIT_REPLAYROLLED: return "IPSEC_XMIT_REPLAYROLLED"; case IPSEC_XMIT_LIFETIMEFAILED: return "IPSEC_XMIT_LIFETIMEFAILED"; case IPSEC_XMIT_CANNOTFRAG: return "IPSEC_XMIT_CANNOTFRAG"; case IPSEC_XMIT_MSSERR: return "IPSEC_XMIT_MSSERR"; case IPSEC_XMIT_ERRSKBALLOC: return "IPSEC_XMIT_ERRSKBALLOC"; case IPSEC_XMIT_ENCAPFAIL: return "IPSEC_XMIT_ENCAPFAIL"; case IPSEC_XMIT_NODEV: return "IPSEC_XMIT_NODEV"; case IPSEC_XMIT_NOPRIVDEV: return "IPSEC_XMIT_NOPRIVDEV"; case IPSEC_XMIT_NOPHYSDEV: return "IPSEC_XMIT_NOPHYSDEV"; case IPSEC_XMIT_NOSKB: return "IPSEC_XMIT_NOSKB"; case IPSEC_XMIT_NOIPV6: return "IPSEC_XMIT_NOIPV6"; case IPSEC_XMIT_NOIPOPTIONS: return "IPSEC_XMIT_NOIPOPTIONS"; case IPSEC_XMIT_TTLEXPIRED: return "IPSEC_XMIT_TTLEXPIRED"; case IPSEC_XMIT_BADHHLEN: return "IPSEC_XMIT_BADHHLEN"; case IPSEC_XMIT_PUSHPULLERR: return "IPSEC_XMIT_PUSHPULLERR"; case IPSEC_XMIT_ROUTEERR: return "IPSEC_XMIT_ROUTEERR"; case IPSEC_XMIT_RECURSDETECT: return "IPSEC_XMIT_RECURSDETECT"; case IPSEC_XMIT_IPSENDFAILURE: return "IPSEC_XMIT_IPSENDFAILURE"; case IPSEC_XMIT_ESPUDP: return "IPSEC_XMIT_ESPUDP"; case IPSEC_XMIT_ESPUDP_BADTYPE: return "IPSEC_XMIT_ESPUDP_BADTYPE"; case IPSEC_XMIT_PENDING: return "IPSEC_XMIT_PENDING"; } snprintf(tmp, sizeof(tmp), "%d", err); return tmp; } /* * Sanity checks */ enum ipsec_xmit_value ipsec_xmit_sanity_check_ipsec_dev( struct ipsec_xmit_state *ixs) { if (ixs->dev == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_error:ipsec_xmit_sanity_check_dev: " "No device associated with skb!\n" ); return IPSEC_XMIT_NODEV; } ixs->iprv = netdev_priv(ixs->dev); if (ixs->iprv == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_error:ipsec_xmit_sanity_check_dev: " "Device has no private structure!\n" ); return IPSEC_XMIT_NOPRIVDEV; } ixs->physdev = ixs->iprv->dev; if (ixs->physdev == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_error:ipsec_xmit_sanity_check_dev: " "No physical device set\n" ); return IPSEC_XMIT_NOPHYSDEV; } if (ixs->mast_mode) { KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_error:ipsec_xmit_sanity_check_dev: " "Unexpectedly using mast device\n" ); return IPSEC_XMIT_NOPHYSDEV; } ixs->physmtu = ixs->physdev->mtu; ixs->cur_mtu = ixs->physdev->mtu; ixs->stats = (struct net_device_stats *) &(ixs->iprv->mystats); return IPSEC_XMIT_OK; } /* * Sanity checks */ enum ipsec_xmit_value ipsec_xmit_sanity_check_mast_dev( struct ipsec_xmit_state *ixs) { if (ixs->dev == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_error:ipsec_xmit_sanity_check_dev: " "No device associated with skb!\n" ); return IPSEC_XMIT_NODEV; } ixs->mprv = netdev_priv(ixs->dev); if (ixs->mprv == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_error:ipsec_xmit_sanity_check_dev: " "Device has no private structure!\n" ); return IPSEC_XMIT_NOPRIVDEV; } ixs->physdev = NULL; // not used here /* * we should be calculating the MTU by looking up a route * based upon the destination in the SA, and then cache * it into the SA, but we don't do that right now. */ ixs->cur_mtu = 1460; ixs->physmtu = 1460; ixs->stats = (struct net_device_stats *) &(ixs->mprv->mystats); return IPSEC_XMIT_OK; } enum ipsec_xmit_value ipsec_xmit_sanity_check_skb(struct ipsec_xmit_state *ixs) { /* * Return if there is nothing to do. (Does this ever happen?) XXX */ if (ixs->skb == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_error:ipsec_xmit_sanity_check_skb: " "Nothing to do!\n" ); return IPSEC_XMIT_NOSKB; } /* if skb was cloned (most likely due to a packet sniffer such as tcpdump being momentarily attached to the interface), make a copy of our own to modify */ if (skb_cloned(ixs->skb)) { if (skb_cow(ixs->skb, skb_headroom(ixs->skb)) != 0) { KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_error:ipsec_xmit_sanity_check_skb: " "skb_cow failed to allocate buffer, dropping.\n" ); if (ixs->stats) ixs->stats->tx_dropped++; return IPSEC_XMIT_ERRSKBALLOC; } } ixs->iph = ip_hdr(ixs->skb); #ifdef CONFIG_KLIPS_IPV6 if (lsw_ip_hdr_version(ixs) == 6) { if (lsw_ip6_hdr(ixs)->hop_limit <= 0) { /* Tell the sender its packet died... */ ixs->skb->dev = ixs->physdev; ICMP6_SEND(ixs->skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, 0, ixs->physdev); KLIPS_PRINT(debug_tunnel, "klips_debug:ipsec_xmit_sanity_check_skb: " "hop_limit=0, too many hops!\n"); if (ixs->stats) ixs->stats->tx_dropped++; return IPSEC_XMIT_TTLEXPIRED; } } else #endif /* CONFIG_KLIPS_IPV6 */ { #if IPSEC_DISALLOW_IPOPTIONS if ((lsw_ip4_hdr(ixs)->ihl << 2) != sizeof(struct iphdr)) { KLIPS_PRINT(debug_tunnel, "klips_debug:ipsec_xmit_sanity_check_skb: " "cannot process IP header options yet. May be mal-formed packet.\n"); /* XXX */ if (ixs->stats) ixs->stats->tx_dropped++; return IPSEC_XMIT_NOIPOPTIONS; } #endif /* IPSEC_DISALLOW_IPOPTIONS */ } return IPSEC_XMIT_OK; } enum ipsec_xmit_value ipsec_xmit_encap_init(struct ipsec_xmit_state *ixs) { int new_version = lsw_ip_hdr_version(ixs); ixs->blocksize = 8; ixs->headroom = 0; ixs->tailroom = 0; ixs->authlen = 0; #ifdef CONFIG_KLIPS_ALG ixs->ixt_e = NULL; ixs->ixt_a = NULL; #endif /* CONFIG_KLIPS_ALG */ #ifdef CONFIG_KLIPS_IPV6 if (lsw_ip_hdr_version(ixs) == 6) { IPSEC_FRAG_OFF_DECL(frag_off) int nexthdroff; unsigned char nexthdr = lsw_ip6_hdr(ixs)->nexthdr; nexthdroff = ipsec_ipv6_skip_exthdr(ixs->skb, ((void *)(lsw_ip6_hdr(ixs) +1)) - (void*)ixs->skb->data, &nexthdr, &frag_off); ixs->iphlen = nexthdroff - (ixs->iph - (void*)ixs->skb->data); ixs->pyldsz = ntohs(lsw_ip6_hdr(ixs)->payload_len) + sizeof(struct ipv6hdr) - ixs->iphlen; } else #endif /* CONFIG_KLIPS_IPV6 */ { ixs->iphlen = lsw_ip4_hdr(ixs)->ihl << 2; ixs->pyldsz = ntohs(lsw_ip4_hdr(ixs)->tot_len) - ixs->iphlen; } ixs->sa_len = KLIPS_SATOT(debug_tunnel, &ixs->ipsp->ips_said, 0, ixs->sa_txt, SATOT_BUF); KLIPS_PRINT(debug_tunnel & DB_TN_OXFS, "klips_debug:ipsec_xmit_encap_init: " "calling output for <%s%s%s>, SA:%s\n", IPS_XFORM_NAME(ixs->ipsp), ixs->sa_len ? ixs->sa_txt : " (error)"); switch (ixs->ipsp->ips_said.proto) { #ifdef CONFIG_KLIPS_AH case IPPROTO_AH: #ifdef CONFIG_KLIPS_ALG if ((ixs->ixt_a = ixs->ipsp->ips_alg_auth)) { ixs->authlen = AHHMAC_HASHLEN; } #endif /* CONFIG_KLIPS_ALG */ ixs->headroom += sizeof(struct ahhdr); break; #endif /* CONFIG_KLIPS_AH */ #ifdef CONFIG_KLIPS_ESP case IPPROTO_ESP: #ifdef CONFIG_KLIPS_OCF /* * this needs cleaning up for sure - DM */ if (ixs->ipsp->ocf_in_use) { switch (ixs->ipsp->ips_encalg) { case ESP_DES: case ESP_3DES: ixs->blocksize = 8; ixs->headroom += ESP_HEADER_LEN + 8 /* ivsize */; break; case ESP_AES: ixs->blocksize = 16; ixs->headroom += ESP_HEADER_LEN + 16 /* ivsize */; break; case ESP_NULL: ixs->blocksize = 1; ixs->headroom += ESP_HEADER_LEN + 0 /* ivsize */; break; default: if (ixs->stats) ixs->stats->tx_errors++; return IPSEC_XMIT_ESP_BADALG; } } else #endif #ifdef CONFIG_KLIPS_ALG if ((ixs->ixt_e = ixs->ipsp->ips_alg_enc)) { ixs->blocksize = ixs->ixt_e->ixt_common.ixt_blocksize; ixs->headroom += ESP_HEADER_LEN + ixs->ixt_e->ixt_common.ixt_support. ias_ivlen / 8; } else #endif /* CONFIG_KLIPS_ALG */ { if (ixs->stats) ixs->stats->tx_errors++; return IPSEC_XMIT_ESP_BADALG; } #ifdef CONFIG_KLIPS_OCF if (ixs->ipsp->ocf_in_use) { switch (ixs->ipsp->ips_authalg) { case AH_MD5: case AH_SHA: ixs->authlen = AHHMAC_HASHLEN; break; case AH_NONE: break; } } else #endif /* CONFIG_KLIPS_OCF */ #ifdef CONFIG_KLIPS_ALG if ((ixs->ixt_a = ixs->ipsp->ips_alg_auth)) { ixs->authlen = ixs->ixt_a->ixt_a_authlen; } else #endif /* CONFIG_KLIPS_ALG */ switch (ixs->ipsp->ips_authalg) { #ifdef CONFIG_KLIPS_AUTH_HMAC_MD5 case AH_MD5: ixs->authlen = AHHMAC_HASHLEN; break; #endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ #ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1 case AH_SHA: ixs->authlen = AHHMAC_HASHLEN; break; #endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */ case AH_NONE: break; default: if (ixs->stats) ixs->stats->tx_errors++; return IPSEC_XMIT_ESP_BADALG; } ixs->tailroom += ixs->blocksize != 1 ? ((ixs->blocksize - ((ixs->pyldsz + 2) % ixs->blocksize)) % ixs->blocksize) + 2 : ((4 - ((ixs->pyldsz + 2) % 4)) % 4) + 2; ixs->tailroom += ixs->authlen; break; #endif /* !CONFIG_KLIPS_ESP */ #ifdef CONFIG_KLIPS_IPIP case IPPROTO_IPIP: if (ip_address_family(&ixs->ipsp->ips_said.dst) == AF_INET6) { ixs->headroom += sizeof(struct ipv6hdr); ixs->iphlen = sizeof(struct ipv6hdr); new_version = 6; } else { ixs->headroom += sizeof(struct iphdr); ixs->iphlen = sizeof(struct iphdr); new_version = 4; } break; #endif /* !CONFIG_KLIPS_IPIP */ #ifdef CONFIG_KLIPS_IPCOMP case IPPROTO_COMP: break; #endif /* CONFIG_KLIPS_IPCOMP */ default: if (ixs->stats) ixs->stats->tx_errors++; return IPSEC_XMIT_BADPROTO; } KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, "klips_debug:ipsec_xmit_encap_init: " "pushing %d bytes, putting %d, proto %d.\n", ixs->headroom, ixs->tailroom, ixs->ipsp->ips_said.proto); if (skb_headroom(ixs->skb) < ixs->headroom) { printk(KERN_WARNING "klips_error:ipsec_xmit_encap_init: " "tried to skb_push headroom=%d, %d available. This should never happen, please report.\n", ixs->headroom, skb_headroom(ixs->skb)); if (ixs->stats) ixs->stats->tx_errors++; return IPSEC_XMIT_ESP_PUSHPULLERR; } ixs->dat = skb_push(ixs->skb, ixs->headroom); ixs->ilen = ixs->skb->len - ixs->tailroom; if (skb_tailroom(ixs->skb) < ixs->tailroom) { printk(KERN_WARNING "klips_error:ipsec_xmit_encap_init: " "tried to skb_put %d, %d available. Retuning IPSEC_XMIT_ESP_PUSHPULLERR This should never happen, please report.\n", ixs->tailroom, skb_tailroom(ixs->skb)); if (ixs->stats) ixs->stats->tx_errors++; return IPSEC_XMIT_ESP_PUSHPULLERR; } skb_put(ixs->skb, ixs->tailroom); KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, "klips_debug:ipsec_xmit_encap_init: " "head,tailroom: %d,%d before xform.\n", skb_headroom(ixs->skb), skb_tailroom(ixs->skb)); ixs->len = ixs->skb->len; if (ixs->len > 0xfff0) { printk(KERN_WARNING "klips_error:ipsec_xmit_encap_init: " "tot_len (%d) > 65520. This should never happen, please report.\n", ixs->len); if (ixs->stats) ixs->stats->tx_errors++; return IPSEC_XMIT_BADLEN; } /* * only copy the old ip header if it's the same version, not even sure * we should do it then - DAVIDM */ if (new_version == lsw_ip_hdr_version(ixs)) memmove((void *)ixs->dat, (void *)(ixs->dat + ixs->headroom), ixs->iphlen); else memset((void *)ixs->dat, 0, ixs->iphlen); ixs->iph = (void *)ixs->dat; if (new_version == 6) lsw_ip6_hdr(ixs)->payload_len = htons(ixs->skb->len - sizeof(struct ipv6hdr)); else lsw_ip4_hdr(ixs)->tot_len = htons(ixs->skb->len); return IPSEC_XMIT_OK; } /* * work out which state to proceed to next */ enum ipsec_xmit_value ipsec_xmit_encap_select(struct ipsec_xmit_state *ixs) { switch (ixs->ipsp->ips_said.proto) { #ifdef CONFIG_KLIPS_ESP case IPPROTO_ESP: ixs->next_state = IPSEC_XSM_ESP; break; #endif #ifdef CONFIG_KLIPS_AH case IPPROTO_AH: ixs->next_state = IPSEC_XSM_AH; break; #endif #ifdef CONFIG_KLIPS_IPIP case IPPROTO_IPIP: ixs->next_state = IPSEC_XSM_IPIP; break; #endif #ifdef CONFIG_KLIPS_IPCOMP case IPPROTO_COMP: ixs->next_state = IPSEC_XSM_IPCOMP; break; #endif default: if (ixs->stats) ixs->stats->tx_errors++; return IPSEC_XMIT_BADPROTO; } return IPSEC_XMIT_OK; } #ifdef CONFIG_KLIPS_ESP enum ipsec_xmit_value ipsec_xmit_esp(struct ipsec_xmit_state *ixs) { int i; unsigned char *pad; int padlen = 0; unsigned char nexthdr; ixs->espp = (struct esphdr *)(ixs->dat + ixs->iphlen); skb_set_transport_header(ixs->skb, ipsec_skb_offset(ixs->skb, ixs->espp)); ixs->espp->esp_spi = ixs->ipsp->ips_said.spi; ixs->espp->esp_rpl = htonl(++(ixs->ipsp->ips_replaywin_lastseq)); ixs->idat = ixs->dat + ixs->iphlen + ixs->headroom; ixs->ilen = ixs->len - (ixs->iphlen + ixs->headroom + ixs->authlen); /* Self-describing padding */ pad = &ixs->dat[ixs->len - ixs->tailroom]; padlen = ixs->tailroom - 2 - ixs->authlen; for (i = 0; i < padlen; i++) pad[i] = i + 1; ixs->dat[ixs->len - ixs->authlen - 2] = padlen; #ifdef CONFIG_KLIPS_IPV6 if (lsw_ip_hdr_version(ixs) == 6) { IPSEC_FRAG_OFF_DECL(frag_off) nexthdr = lsw_ip6_hdr(ixs)->nexthdr; i = ipsec_ipv6_skip_exthdr(ixs->skb, ((void *)(lsw_ip6_hdr(ixs) +1)) - (void*)ixs->skb->data, &nexthdr, &frag_off); } else #endif /* CONFIG_KLIPS_IPV6 */ { nexthdr = lsw_ip4_hdr(ixs)->protocol; } ixs->dat[ixs->len - ixs->authlen - 1] = nexthdr; if (ip_address_family(&ixs->ipsp->ips_said.dst) == AF_INET6) lsw_ip6_hdr(ixs)->nexthdr = IPPROTO_ESP; else lsw_ip4_hdr(ixs)->protocol = IPPROTO_ESP; #ifdef CONFIG_KLIPS_OCF if (ixs->ipsp->ocf_in_use) { /* handle the IV code here for now, near the similar code below */ prng_bytes(&ipsec_prng, (char *)ixs->espp->esp_iv, ixs->ipsp->ips_iv_size); return ipsec_ocf_xmit(ixs); } #endif #ifdef CONFIG_KLIPS_ALG if (!ixs->ixt_e) { if (ixs->stats) ixs->stats->tx_errors++; return IPSEC_XMIT_ESP_BADALG; } if (debug_tunnel & DB_TN_ENCAP) dmp("pre-encrypt", ixs->dat, ixs->len); /* * Do all operations here: * copy IV->ESP, encrypt, update ips IV * */ { int ret; memcpy(ixs->espp->esp_iv, ixs->ipsp->ips_iv, ixs->ipsp->ips_iv_size); ret = ipsec_alg_esp_encrypt(ixs->ipsp, ixs->idat, ixs->ilen, ixs->espp->esp_iv, IPSEC_ALG_ENCRYPT); prng_bytes(&ipsec_prng, (char *)ixs->ipsp->ips_iv, ixs->ipsp->ips_iv_size); } return IPSEC_XMIT_OK; #else return IPSEC_XMIT_ESP_BADALG; #endif /* CONFIG_KLIPS_ALG */ } enum ipsec_xmit_value ipsec_xmit_esp_ah(struct ipsec_xmit_state *ixs) { #if defined(CONFIG_KLIPS_AUTH_HMAC_MD5) || defined(CONFIG_KLIPS_AUTH_HMAC_SHA1) __u8 hash[AH_AMAX]; #endif #if defined(CONFIG_KLIPS_AUTH_HMAC_MD5) || defined(CONFIG_KLIPS_AUTH_HMAC_SHA1) union { #ifdef CONFIG_KLIPS_AUTH_HMAC_MD5 MD5_CTX md5; #endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ #ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1 SHA1_CTX sha1; #endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */ } tctx; #endif /* defined(CONFIG_KLIPS_AUTH_HMAC_MD5) || defined(CONFIG_KLIPS_AUTH_HMAC_SHA1) */ #ifdef CONFIG_KLIPS_OCF if (ixs->ipsp->ocf_in_use) { /* we should never be here using OCF */ if (ixs->stats) ixs->stats->tx_errors++; return IPSEC_XMIT_AH_BADALG; } else #endif #ifdef CONFIG_KLIPS_ALG if (ixs->ixt_a) { ipsec_alg_sa_esp_hash(ixs->ipsp, (caddr_t)ixs->espp, ixs->len - ixs->iphlen - ixs->authlen, &(ixs->dat[ixs->len - ixs->authlen]), ixs->authlen); } else #endif /* CONFIG_KLIPS_ALG */ switch (ixs->ipsp->ips_authalg) { #ifdef CONFIG_KLIPS_AUTH_HMAC_MD5 case AH_MD5: dmp("espp", (char*)ixs->espp, ixs->len - ixs->iphlen - ixs->authlen); tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->ictx; dmp("ictx", (char*)&tctx.md5, sizeof(tctx.md5)); osMD5Update(&tctx.md5, (caddr_t)ixs->espp, ixs->len - ixs->iphlen - ixs->authlen); dmp("ictx+dat", (char*)&tctx.md5, sizeof(tctx.md5)); osMD5Final(hash, &tctx.md5); dmp("ictx hash", (char*)&hash, sizeof(hash)); tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->octx; dmp("octx", (char*)&tctx.md5, sizeof(tctx.md5)); osMD5Update(&tctx.md5, hash, AHMD596_ALEN); dmp("octx+hash", (char*)&tctx.md5, sizeof(tctx.md5)); osMD5Final(hash, &tctx.md5); dmp("octx hash", (char*)&hash, sizeof(hash)); memcpy(&(ixs->dat[ixs->len - ixs->authlen]), hash, ixs->authlen); /* paranoid */ memset((caddr_t)&tctx.md5, 0, sizeof(tctx.md5)); memset((caddr_t)hash, 0, sizeof(*hash)); break; #endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ #ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1 case AH_SHA: tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->ictx; SHA1Update(&tctx.sha1, (caddr_t)ixs->espp, ixs->len - ixs->iphlen - ixs->authlen); SHA1Final(hash, &tctx.sha1); tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->octx; SHA1Update(&tctx.sha1, hash, AHSHA196_ALEN); SHA1Final(hash, &tctx.sha1); memcpy(&(ixs->dat[ixs->len - ixs->authlen]), hash, ixs->authlen); /* paranoid */ memset((caddr_t)&tctx.sha1, 0, sizeof(tctx.sha1)); memset((caddr_t)hash, 0, sizeof(*hash)); break; #endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */ case AH_NONE: break; default: if (ixs->stats) ixs->stats->tx_errors++; return IPSEC_XMIT_AH_BADALG; } return IPSEC_XMIT_OK; } #endif /* CONFIG_KLIPS_ESP */ #ifdef CONFIG_KLIPS_AH enum ipsec_xmit_value ipsec_xmit_ah(struct ipsec_xmit_state *ixs) { struct iphdr ipo; struct ahhdr *ahp; #ifdef CONFIG_KLIPS_ALG unsigned char *buf; int len = 0; #endif #if defined(CONFIG_KLIPS_AUTH_HMAC_MD5) || defined(CONFIG_KLIPS_AUTH_HMAC_SHA1) __u8 hash[AH_AMAX]; #endif #if defined(CONFIG_KLIPS_AUTH_HMAC_MD5) || defined(CONFIG_KLIPS_AUTH_HMAC_SHA1) union { #ifdef CONFIG_KLIPS_AUTH_HMAC_MD5 MD5_CTX md5; #endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ #ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1 SHA1_CTX sha1; #endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */ } tctx; #endif /* defined(CONFIG_KLIPS_AUTH_HMAC_MD5) || defined(CONFIG_KLIPS_AUTH_HMAC_SHA1) */ if (lsw_ip_hdr_version(ixs) == 6) { printk("KLIPS AH doesn't support IPv6 yet\n"); return IPSEC_XMIT_AH_BADALG; } ahp = (struct ahhdr *)(ixs->dat + ixs->iphlen); skb_set_transport_header(ixs->skb, ipsec_skb_offset(ixs->skb, ahp)); ahp->ah_spi = ixs->ipsp->ips_said.spi; ahp->ah_rpl = htonl(++(ixs->ipsp->ips_replaywin_lastseq)); ahp->ah_rv = 0; ahp->ah_nh = lsw_ip4_hdr(ixs)->protocol; ahp->ah_hl = (ixs->headroom >> 2) - sizeof(__u64) / sizeof(__u32); lsw_ip4_hdr(ixs)->protocol = IPPROTO_AH; dmp("ahp", (char*)ahp, sizeof(*ahp)); #ifdef CONFIG_KLIPS_OCF if (ixs->ipsp->ocf_in_use) return ipsec_ocf_xmit(ixs); #endif ipo = *lsw_ip4_hdr(ixs); ipo.tos = 0; ipo.frag_off = 0; ipo.ttl = 0; ipo.check = 0; dmp("ipo", (char*)&ipo, sizeof(ipo)); #ifdef CONFIG_KLIPS_ALG if (ixs->ixt_a) { if (ixs->ipsp->ips_authalg != AH_SHA && ixs->ipsp->ips_authalg != AH_MD5) { printk("KLIPS AH doesn't support authalg=%d yet\n",ixs->ipsp->ips_authalg); return IPSEC_XMIT_AH_BADALG; } if ((buf = kmalloc(sizeof(struct iphdr)+ixs->skb->len, GFP_KERNEL)) == NULL) return IPSEC_XMIT_ERRMEMALLOC; memcpy(buf, (unsigned char *)&ipo,sizeof(struct iphdr)); len = sizeof(struct iphdr); memcpy(buf+len, (unsigned char*)ahp,ixs->headroom - sizeof(ahp->ah_data)); len+=(ixs->headroom - sizeof(ahp->ah_data)); memcpy(buf+len, (unsigned char *)zeroes, AHHMAC_HASHLEN); len+=AHHMAC_HASHLEN; memcpy(buf+len, ixs->dat + ixs->iphlen + ixs->headroom, ixs->len - ixs->iphlen - ixs->headroom); len+=(ixs->len - ixs->iphlen - ixs->headroom); ipsec_alg_sa_ah_hash(ixs->ipsp, (caddr_t)buf, len, ahp->ah_data, AHHMAC_HASHLEN); if (buf) kfree(buf); } else #endif /* CONFIG_KLIPS_ALG */ switch (ixs->ipsp->ips_authalg) { #ifdef CONFIG_KLIPS_AUTH_HMAC_MD5 case AH_MD5: tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->ictx; dmp("ictx", (char*)&tctx.md5, sizeof(tctx.md5)); osMD5Update(&tctx.md5, (unsigned char *)&ipo, sizeof(struct iphdr)); dmp("ictx+ipo", (char*)&tctx.md5, sizeof(tctx.md5)); osMD5Update(&tctx.md5, (unsigned char *)ahp, ixs->headroom - sizeof(ahp->ah_data)); dmp("ictx+ahp", (char*)&tctx.md5, sizeof(tctx.md5)); osMD5Update(&tctx.md5, (unsigned char *)zeroes, AHHMAC_HASHLEN); dmp("ictx+zeroes", (char*)&tctx.md5, sizeof(tctx.md5)); osMD5Update(&tctx.md5, ixs->dat + ixs->iphlen + ixs->headroom, ixs->len - ixs->iphlen - ixs->headroom); dmp("ictx+dat", (char*)&tctx.md5, sizeof(tctx.md5)); osMD5Final(hash, &tctx.md5); dmp("ictx hash", (char*)&hash, sizeof(hash)); tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->octx; dmp("octx", (char*)&tctx.md5, sizeof(tctx.md5)); osMD5Update(&tctx.md5, hash, AHMD596_ALEN); dmp("octx+hash", (char*)&tctx.md5, sizeof(tctx.md5)); osMD5Final(hash, &tctx.md5); dmp("octx hash", (char*)&hash, sizeof(hash)); memcpy(ahp->ah_data, hash, AHHMAC_HASHLEN); /* paranoid */ memset((caddr_t)&tctx.md5, 0, sizeof(tctx.md5)); memset((caddr_t)hash, 0, sizeof(*hash)); break; #endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ #ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1 case AH_SHA: tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->ictx; SHA1Update(&tctx.sha1, (unsigned char *)&ipo, sizeof(struct iphdr)); SHA1Update(&tctx.sha1, (unsigned char *)ahp, ixs->headroom - sizeof(ahp->ah_data)); SHA1Update(&tctx.sha1, (unsigned char *)zeroes, AHHMAC_HASHLEN); SHA1Update(&tctx.sha1, ixs->dat + ixs->iphlen + ixs->headroom, ixs->len - ixs->iphlen - ixs->headroom); SHA1Final(hash, &tctx.sha1); tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->octx; SHA1Update(&tctx.sha1, hash, AHSHA196_ALEN); SHA1Final(hash, &tctx.sha1); memcpy(ahp->ah_data, hash, AHHMAC_HASHLEN); /* paranoid */ memset((caddr_t)&tctx.sha1, 0, sizeof(tctx.sha1)); memset((caddr_t)hash, 0, sizeof(*hash)); break; #endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */ default: if (ixs->stats) ixs->stats->tx_errors++; return IPSEC_XMIT_AH_BADALG; } return IPSEC_XMIT_OK; } #endif /* CONFIG_KLIPS_AH */ #ifdef CONFIG_KLIPS_IPIP enum ipsec_xmit_value ipsec_xmit_ipip(struct ipsec_xmit_state *ixs) { int error; #ifdef CONFIG_KLIPS_IPV6 if (ip_address_family(&ixs->ipsp->ips_said.dst) == AF_INET6) { ixs->skb->ip_summed = CHECKSUM_NONE; lsw_ip6_hdr(ixs)->version = 6; /* DAVIDM TOS / DSFIELD stuff in following line */ lsw_ip6_hdr(ixs)->priority = 0; /* what to do with flow_lbl? */ lsw_ip6_hdr(ixs)->flow_lbl[0] = 0; lsw_ip6_hdr(ixs)->flow_lbl[1] = 0; lsw_ip6_hdr(ixs)->flow_lbl[2] = 0; lsw_ip6_hdr(ixs)->hop_limit = SYSCTL_IPSEC_DEFAULT_TTL; lsw_ip6_hdr(ixs)->saddr = ((struct sockaddr_in6*)(ixs->ipsp->ips_addr_s))-> sin6_addr; lsw_ip6_hdr(ixs)->daddr = ((struct sockaddr_in6*)(ixs->ipsp->ips_addr_d))-> sin6_addr; lsw_ip6_hdr(ixs)->nexthdr = ixs->ipip_proto; error = ipsec_set_dst(ixs); if (error != IPSEC_XMIT_OK) return error; /* DAVIDM No identification/fragment code here yet */ skb_set_transport_header(ixs->skb, ipsec_skb_offset(ixs->skb, ixs->iph)); } else #endif /* CONFIG_KLIPS_IPV6 */ { lsw_ip4_hdr(ixs)->version = 4; switch (sysctl_ipsec_tos) { case 0: lsw_ip4_hdr(ixs)->tos = ip_hdr(ixs->skb)->tos; break; case 1: lsw_ip4_hdr(ixs)->tos = 0; break; default: break; } lsw_ip4_hdr(ixs)->ttl = SYSCTL_IPSEC_DEFAULT_TTL; lsw_ip4_hdr(ixs)->frag_off = 0; lsw_ip4_hdr(ixs)->saddr = ((struct sockaddr_in*)(ixs->ipsp->ips_addr_s))-> sin_addr.s_addr; lsw_ip4_hdr(ixs)->daddr = ((struct sockaddr_in*)(ixs->ipsp->ips_addr_d))-> sin_addr.s_addr; lsw_ip4_hdr(ixs)->protocol = ixs->ipip_proto; lsw_ip4_hdr(ixs)->ihl = sizeof(struct iphdr) >> 2; /* newer kernels require skb->dst to be set in KLIPS_IP_SELECT_IDENT */ /* we need to do this before any HASH generation is done */ error = ipsec_set_dst(ixs); if (error != IPSEC_XMIT_OK) return error; KLIPS_IP_SELECT_IDENT(lsw_ip4_hdr(ixs), ixs->skb); skb_set_transport_header(ixs->skb, ipsec_skb_offset(ixs->skb, ixs->iph)); } return IPSEC_XMIT_OK; } #endif /* CONFIG_KLIPS_IPIP */ #ifdef CONFIG_KLIPS_IPCOMP enum ipsec_xmit_value ipsec_xmit_ipcomp(struct ipsec_xmit_state *ixs) { unsigned int old_tot_len, tot_len; int flags = 0; #ifdef CONFIG_KLIPS_OCF if (ixs->ipsp->ocf_in_use) return ipsec_ocf_xmit(ixs); #endif #ifdef CONFIG_KLIPS_IPV6 if (lsw_ip_hdr_version(ixs) == 6) old_tot_len = ntohs(lsw_ip6_hdr(ixs)->payload_len) + sizeof(struct ipv6hdr); else #endif old_tot_len = ntohs(lsw_ip4_hdr(ixs)->tot_len); ixs->ipsp->ips_comp_ratio_dbytes += old_tot_len; ixs->skb = skb_compress(ixs->skb, ixs->ipsp, &flags); ixs->iph = ip_hdr(ixs->skb); #ifdef CONFIG_KLIPS_IPV6 if (lsw_ip_hdr_version(ixs) == 6) { IPSEC_FRAG_OFF_DECL(frag_off) int nexthdroff; unsigned char nexthdr = lsw_ip6_hdr(ixs)->nexthdr; nexthdroff = ipsec_ipv6_skip_exthdr(ixs->skb, ((void *)(lsw_ip6_hdr(ixs) +1)) - (void*)ixs->skb->data, &nexthdr, &frag_off); tot_len = ntohs(lsw_ip6_hdr(ixs)->payload_len) + sizeof(struct ipv6hdr); } else #endif tot_len = ntohs(lsw_ip4_hdr(ixs)->tot_len); ixs->ipsp->ips_comp_ratio_cbytes += tot_len; if (debug_tunnel & DB_TN_CROUT) { if (old_tot_len > tot_len) KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, "klips_debug:ipsec_xmit_ipcomp: " "packet shrunk from %d to %d bytes after compression, cpi=%04x (should be from spi=%08x, spi&0xffff=%04x.\n", old_tot_len, tot_len, ntohs(((struct ipcomphdr*)(((char*) lsw_ip4_hdr(ixs)) + ((lsw_ip4_hdr( ixs)-> ihl) << 2)))-> ipcomp_cpi), ntohl(ixs->ipsp->ips_said.spi), (__u16)(ntohl(ixs->ipsp->ips_said.spi) & 0x0000ffff)); else KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, "klips_debug:ipsec_xmit_ipcomp: " "packet did not compress (flags = %d).\n", flags); } return IPSEC_XMIT_OK; } #endif /* CONFIG_KLIPS_IPCOMP */ /* * upon entry to this function, ixs->skb should be setup * as follows: * * data = beginning of IP packet <- differs from ipsec_rcv(). * nh.raw = beginning of IP packet. * h.raw = data after the IP packet. * */ enum ipsec_xmit_value ipsec_xmit_cont(struct ipsec_xmit_state *ixs) { __u8 padlen; skb_set_network_header(ixs->skb, ipsec_skb_offset(ixs->skb, ixs->skb->data)); /* * if we have more work to do, it's likely this checksum is getting * encapsulated, and we must do it. Otherwise, we do a final one * just before the ip_send/nf hook in ipsec_xmit_send. */ if (ixs->ipsp->ips_next && lsw_ip_hdr_version(ixs) == 4) { lsw_ip4_hdr(ixs)->check = 0; lsw_ip4_hdr(ixs)->check = ip_fast_csum( (unsigned char *)ixs->iph, lsw_ip4_hdr(ixs)->ihl); } KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_xmit_cont: " "after <%s%s%s>, SA:%s:\n", IPS_XFORM_NAME(ixs->ipsp), ixs->sa_len ? ixs->sa_txt : " (error)"); KLIPS_IP_PRINT(debug_tunnel & DB_TN_XMIT, ixs->iph); padlen = ixs->tailroom - ixs->authlen; ixs->ipsp->ips_life.ipl_bytes.ipl_count += ixs->ilen - padlen; ixs->ipsp->ips_life.ipl_bytes.ipl_last = ixs->ilen - padlen; if (!ixs->ipsp->ips_life.ipl_usetime.ipl_count) ixs->ipsp->ips_life.ipl_usetime.ipl_count = jiffies / HZ; ixs->ipsp->ips_life.ipl_usetime.ipl_last = jiffies / HZ; ixs->ipsp->ips_life.ipl_packets.ipl_count++; /* we are done with this SA */ ipsec_sa_put(ixs->ipsp, IPSEC_REFTX); /* move to the next SA */ ixs->ipsp = ixs->ipsp->ips_next; if (ixs->ipsp) ipsec_sa_get(ixs->ipsp, IPSEC_REFTX); /* * start again if we have more work to do */ if (ixs->ipsp) ixs->next_state = IPSEC_XSM_ENCAP_INIT; return IPSEC_XMIT_OK; } /* * If the IP packet (iph) is a carrying TCP/UDP, then set the encaps * source and destination ports to those from the TCP/UDP header. */ void ipsec_extract_ports(struct sk_buff *skb, unsigned char nexthdr, int nexthdroff, struct sockaddr_encap * er) { struct udphdr _udp, *udp; switch (nexthdr) { case IPPROTO_UDP: case IPPROTO_TCP: /* * The ports are at the same offsets in a TCP and UDP * header so hack it ... */ udp = skb_header_pointer(skb, nexthdroff, sizeof(*udp), &_udp); if (udp) { if (SENT_IP4 == er->sen_type) { er->sen_sport = udp->source; er->sen_dport = udp->dest; } else if (SENT_IP6 == er->sen_type) { er->sen_sport6 = udp->source; er->sen_dport6 = udp->dest; } break; } /* FALL THROUGH */ default: if (SENT_IP4 == er->sen_type) { er->sen_sport = 0; er->sen_dport = 0; } else if (SENT_IP6 == er->sen_type) { er->sen_sport6 = 0; er->sen_dport6 = 0; } break; } } /* * A TRAP eroute is installed and we want to replace it with a HOLD * eroute. * * NOTE iph == skb->iph */ static int create_hold_eroute(struct ipsec_xmit_state *ixs) { struct eroute hold_eroute; ip_said hold_said; struct sk_buff *first, *last; int error; first = last = NULL; memset((caddr_t)&hold_eroute, 0, sizeof(hold_eroute)); memset((caddr_t)&hold_said, 0, sizeof(hold_said)); hold_said.proto = IPPROTO_INT; hold_said.spi = htonl(SPI_HOLD); #ifdef CONFIG_KLIPS_IPV6 if (lsw_ip_hdr_version(ixs) == 6) { struct in6_addr addr6_any = IN6ADDR_ANY_INIT; hold_said.dst.u.v6.sin6_addr = addr6_any; SET_V6(hold_said.dst); } else #endif { hold_said.dst.u.v4.sin_addr.s_addr = INADDR_ANY; SET_V4(hold_said.dst); } hold_eroute.er_eaddr.sen_len = sizeof(struct sockaddr_encap); hold_eroute.er_emask.sen_len = sizeof(struct sockaddr_encap); hold_eroute.er_eaddr.sen_family = AF_ENCAP; hold_eroute.er_emask.sen_family = AF_ENCAP; hold_eroute.er_eaddr.sen_type = (lsw_ip_hdr_version(ixs) == 6) ? SENT_IP6 : SENT_IP4; hold_eroute.er_emask.sen_type = 255; #ifdef CONFIG_KLIPS_IPV6 if (lsw_ip_hdr_version(ixs) == 6) { const struct in6_addr in6addr_linklocal_allnodes = IN6ADDR_LINKLOCAL_ALLNODES_INIT; hold_eroute.er_eaddr.sen_ip6_src = lsw_ip6_hdr(ixs)->saddr; hold_eroute.er_eaddr.sen_ip6_dst = lsw_ip6_hdr(ixs)->daddr; hold_eroute.er_emask.sen_ip6_src = in6addr_linklocal_allnodes; hold_eroute.er_emask.sen_ip6_dst = in6addr_linklocal_allnodes; } else #endif /* CONFIG_KLIPS_IPV6 */ { hold_eroute.er_eaddr.sen_ip_src.s_addr = lsw_ip4_hdr(ixs)->saddr; hold_eroute.er_eaddr.sen_ip_dst.s_addr = lsw_ip4_hdr(ixs)->daddr; hold_eroute.er_emask.sen_ip_src.s_addr = INADDR_BROADCAST; hold_eroute.er_emask.sen_ip_dst.s_addr = INADDR_BROADCAST; } hold_eroute.er_emask.sen_sport = 0; hold_eroute.er_emask.sen_dport = 0; hold_eroute.er_pid = ixs->eroute_pid; hold_eroute.er_count = 0; hold_eroute.er_lasttime = jiffies / HZ; /* * if it wasn't captured by a wildcard, then don't record it as * a wildcard. */ if (ixs->eroute->er_eaddr.sen_proto != 0) { unsigned char nexthdr; int nexthdroff; #ifdef CONFIG_KLIPS_IPV6 if (lsw_ip_hdr_version(ixs) == 6) { IPSEC_FRAG_OFF_DECL(frag_off) nexthdr = lsw_ip6_hdr(ixs)->nexthdr; nexthdroff = ipsec_ipv6_skip_exthdr(ixs->skb, ((void *)( lsw_ip6_hdr( ixs) + 1)) - (void*)ixs->skb->data, &nexthdr, &frag_off); hold_eroute.er_eaddr.sen_proto6 = nexthdr; } else #endif /* CONFIG_KLIPS_IPV6 */ { nexthdr = lsw_ip4_hdr(ixs)->protocol; nexthdroff = 0; if ((ntohs(lsw_ip4_hdr(ixs)->frag_off) & IP_OFFSET) == 0) { nexthdroff = (ixs->iph + (lsw_ip4_hdr(ixs)->ihl << 2)) - (void *)ixs->skb->data; } hold_eroute.er_eaddr.sen_proto = nexthdr; } if (nexthdr == IPPROTO_TCP || nexthdr == IPPROTO_UDP) { if (ixs->eroute->er_eaddr.sen_type == SENT_IP4 && (ixs->eroute->er_eaddr.sen_sport != 0 || ixs->eroute->er_eaddr.sen_dport != 0)) { if (ixs->eroute->er_eaddr.sen_sport != 0) hold_eroute.er_emask.sen_sport = ~0; if (ixs->eroute->er_eaddr.sen_dport != 0) hold_eroute.er_emask.sen_dport = ~0; ipsec_extract_ports(ixs->skb, nexthdr, nexthdroff, &hold_eroute.er_eaddr); } else if (ixs->eroute->er_eaddr.sen_type == SENT_IP6 && (ixs->eroute->er_eaddr.sen_sport6 != 0 || ixs->eroute->er_eaddr.sen_dport6 != 0)) { if (ixs->eroute->er_eaddr.sen_sport6 != 0) hold_eroute.er_emask.sen_sport6 = ~0; if (ixs->eroute->er_eaddr.sen_dport6 != 0) hold_eroute.er_emask.sen_dport6 = ~0; ipsec_extract_ports(ixs->skb, nexthdr, nexthdroff, &hold_eroute.er_eaddr); } } } if (debug_pfkey) { char buf1[64], buf2[64]; if (lsw_ip_hdr_version(ixs) == 6) { subnet6toa(&hold_eroute.er_eaddr.sen_ip6_src, &hold_eroute.er_emask.sen_ip6_src, 0, buf1, sizeof(buf1)); subnet6toa(&hold_eroute.er_eaddr.sen_ip6_dst, &hold_eroute.er_emask.sen_ip6_dst, 0, buf2, sizeof(buf2)); } else { subnettoa(hold_eroute.er_eaddr.sen_ip_src, hold_eroute.er_emask.sen_ip_src, 0, buf1, sizeof(buf1)); subnettoa(hold_eroute.er_eaddr.sen_ip_dst, hold_eroute.er_emask.sen_ip_dst, 0, buf2, sizeof(buf2)); } KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_tunnel_start_xmit: " "calling breakeroute and makeroute for %s:%d->%s:%d %d HOLD eroute.\n", buf1, ntohs(hold_eroute.er_eaddr.sen_sport), buf2, ntohs(hold_eroute.er_eaddr.sen_dport), hold_eroute.er_eaddr.sen_proto); } if (ipsec_breakroute(&(hold_eroute.er_eaddr), &(hold_eroute.er_emask), &first, &last)) { KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_tunnel_start_xmit: " "HOLD breakeroute found nothing.\n"); } else if (hold_eroute.er_eaddr.sen_type == SENT_IP6 && debug_pfkey) { char buf1[64], buf2[64]; subnet6toa(&hold_eroute.er_eaddr.sen_ip6_src, &hold_eroute.er_emask.sen_ip6_src, 0, buf1, sizeof(buf1)); subnet6toa(&hold_eroute.er_eaddr.sen_ip6_dst, &hold_eroute.er_emask.sen_ip6_dst, 0, buf2, sizeof(buf2)); KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_tunnel_start_xmit: " "HOLD breakroute deleted [%s]:%u -> [%s]:%u %u\n", buf1, ntohs(hold_eroute.er_eaddr.sen_sport6), buf1, ntohs(hold_eroute.er_eaddr.sen_dport6), hold_eroute.er_eaddr.sen_proto6); } else { KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_tunnel_start_xmit: " "HOLD breakroute deleted %pI4:%u -> %pI4:%u %u\n", &hold_eroute.er_eaddr.sen_ip_src, ntohs(hold_eroute.er_eaddr.sen_sport), &hold_eroute.er_eaddr.sen_ip_dst, ntohs(hold_eroute.er_eaddr.sen_dport), hold_eroute.er_eaddr.sen_proto); } if (first != NULL) ipsec_kfree_skb(first); if (last != NULL) ipsec_kfree_skb(last); error = ipsec_makeroute(&(hold_eroute.er_eaddr), &(hold_eroute.er_emask), hold_said, ixs->eroute_pid, ixs->skb, NULL, NULL); if (error) { KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_tunnel_start_xmit: " "HOLD makeroute returned %d, failed.\n", error); } else { KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_tunnel_start_xmit: " "HOLD makeroute call successful.\n"); } return error == 0; } /* * upon entry to this function, ixs->skb should be setup * as follows: * * data = beginning of IP packet <- differs from ipsec_rcv(). * nh.raw = beginning of IP packet. * h.raw = data after the IP packet. * */ enum ipsec_xmit_value ipsec_xmit_init1(struct ipsec_xmit_state *ixs) { ixs->orgedst = ixs->outgoing_said.dst; ixs->max_headroom = ixs->max_tailroom = 0; #ifdef CONFIG_KLIPS_IPV6 if (lsw_ip_hdr_version(ixs) == 6) { IPSEC_FRAG_OFF_DECL(frag_off) int nexthdroff; unsigned char nexthdr = lsw_ip6_hdr(ixs)->nexthdr; nexthdroff = ipsec_ipv6_skip_exthdr(ixs->skb, ((void *)(lsw_ip6_hdr( ixs) + 1)) - (void*)ixs->skb->data, &nexthdr, &frag_off); ixs->iphlen = nexthdroff - (ixs->iph - (void*)ixs->skb->data); ixs->pyldsz = ntohs(lsw_ip6_hdr(ixs)->payload_len); } else #endif /* CONFIG_KLIPS_IPV6 */ { ixs->iphlen = lsw_ip4_hdr(ixs)->ihl << 2; ixs->pyldsz = ntohs(lsw_ip4_hdr(ixs)->tot_len) - ixs->iphlen; } if (ixs->outgoing_said.proto == IPPROTO_INT) { switch (ntohl(ixs->outgoing_said.spi)) { case SPI_DROP: KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_xmit_encap_bundle: " "shunt SA of DROP or no eroute: dropping.\n"); if (ixs->stats) ixs->stats->tx_dropped++; break; case SPI_REJECT: KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_xmit_encap_bundle: " "shunt SA of REJECT: notifying and dropping.\n"); #ifdef CONFIG_KLIPS_IPV6 if (lsw_ip_hdr_version(ixs) == 6) ICMP6_SEND(ixs->skb, ICMP_DEST_UNREACH, ICMP_PKT_FILTERED, 0, ixs->physdev); else #endif ICMP_SEND(ixs->skb, ICMP_DEST_UNREACH, ICMP_PKT_FILTERED, 0, ixs->physdev); if (ixs->stats) ixs->stats->tx_dropped++; break; case SPI_PASS: ixs->pass = 1; KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_xmit_encap_bundle: " "PASS: calling dev_queue_xmit\n"); return IPSEC_XMIT_PASS; case SPI_HOLD: KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_xmit_encap_bundle: " "shunt SA of HOLD: this does not make sense here, dropping.\n"); if (ixs->stats) ixs->stats->tx_dropped++; break; case SPI_TRAP: case SPI_TRAPSUBNET: #ifdef CONFIG_KLIPS_IPV6 if (lsw_ip_hdr_version(ixs) == 6) { struct sockaddr_in6 src, dst; char bufsrc[ADDRTOA_BUF], bufdst[ADDRTOA_BUF]; unsigned char nexthdr; int nexthdroff; IPSEC_FRAG_OFF_DECL(frag_off) /* Signal all listening KMds with a PF_KEY ACQUIRE */ memset(&src, 0, sizeof(src)); memset(&dst, 0, sizeof(dst)); src.sin6_family = AF_INET6; dst.sin6_family = AF_INET6; #ifdef NEED_SIN_LEN src.sin6_len = sizeof(struct sockaddr_in6); dst.sin6_len = sizeof(struct sockaddr_in6); #endif src.sin6_addr = lsw_ip6_hdr(ixs)->saddr; dst.sin6_addr = lsw_ip6_hdr(ixs)->daddr; ixs->ips.ips_transport_protocol = 0; src.sin6_port = 0; dst.sin6_port = 0; nexthdr = lsw_ip6_hdr(ixs)->nexthdr; nexthdroff = ipsec_ipv6_skip_exthdr(ixs->skb, ((void *)( lsw_ip6_hdr( ixs) + 1)) - (void*)ixs->skb->data, &nexthdr, &frag_off); if (nexthdroff == 0) { printk("KLIPS: broken ipv6 header\n"); nexthdr = -1; } if (ixs->eroute->er_eaddr.sen_type != SENT_IP6) printk("KLIPS: IPv6 on non IPv6 eroute\n"); if (ixs->eroute->er_eaddr.sen_proto != 0) { struct udphdr _udphdr, *udphdr = NULL; struct tcphdr _tcphdr, *tcphdr = NULL; ixs->ips.ips_transport_protocol = nexthdr; if (nexthdroff) { if (nexthdr == IPPROTO_UDP) { udphdr = skb_header_pointer( ixs->skb, nexthdroff, sizeof(*udphdr), &_udphdr); } else if (nexthdr == IPPROTO_TCP) { tcphdr = skb_header_pointer( ixs->skb, nexthdroff, sizeof(*tcphdr), &_tcphdr); } } if (ixs->eroute->er_eaddr.sen_sport6 != 0) { src.sin6_port = (udphdr ? udphdr-> source : (tcphdr ? tcphdr-> source : 0)); } if (ixs->eroute->er_eaddr.sen_dport6 != 0) { dst.sin6_port = (udphdr ? udphdr->dest : (tcphdr ? tcphdr-> dest : 0)); } } ixs->ips.ips_addr_s = (struct sockaddr*)(&src); ixs->ips.ips_addr_d = (struct sockaddr*)(&dst); KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_xmit_encap_bundle: " "SADB_ACQUIRE sent with src=%s:%d, dst=%s:%d, proto=%d.\n", sin_addrtot(ixs->ips.ips_addr_s, 0, bufsrc, sizeof(bufsrc)) <= ADDRTOA_BUF ? bufsrc : "BAD_ADDR", ntohs(((struct sockaddr_in6*)(ixs-> ips. ips_addr_s)) ->sin6_port), sin_addrtot(ixs->ips.ips_addr_d, 0, bufdst, sizeof(bufdst)) <= ADDRTOA_BUF ? bufdst : "BAD_ADDR", ntohs(((struct sockaddr_in6*)(ixs-> ips. ips_addr_d)) ->sin6_port), ixs->ips.ips_said.proto); /* increment count of total traps needed */ ipsec_xmit_trap_count++; if (pfkey_acquire(&ixs->ips) == 0) { /* note that we succeeded */ ipsec_xmit_trap_sendcount++; if (ixs->outgoing_said.spi == htonl(SPI_TRAPSUBNET)) { /* * The spinlock is to prevent any other * process from accessing or deleting * the eroute while we are using and * updating it. */ spin_lock_bh(&eroute_lock); ixs->eroute = ipsec_findroute( &ixs->matcher); if (ixs->eroute) { ixs->eroute->er_said. spi = htonl(SPI_HOLD); ixs->eroute->er_first = ixs->skb; ixs->skb = NULL; } spin_unlock_bh(&eroute_lock); } else if (create_hold_eroute(ixs)) { ixs->skb = NULL; } /* whether or not the above succeeded, we continue */ } if (ixs->stats) ixs->stats->tx_dropped++; } else #endif /* CONFIG_KLIPS_IPV6 */ { struct sockaddr_in src, dst; char bufsrc[ADDRTOA_BUF], bufdst[ADDRTOA_BUF]; /* Signal all listening KMds with a PF_KEY ACQUIRE */ memset(&src, 0, sizeof(src)); memset(&dst, 0, sizeof(dst)); src.sin_family = AF_INET; dst.sin_family = AF_INET; #ifdef NEED_SIN_LEN src.sin_len = sizeof(struct sockaddr_in); dst.sin_len = sizeof(struct sockaddr_in); #endif src.sin_addr.s_addr = lsw_ip4_hdr(ixs)->saddr; dst.sin_addr.s_addr = lsw_ip4_hdr(ixs)->daddr; ixs->ips.ips_transport_protocol = 0; src.sin_port = 0; dst.sin_port = 0; if (ixs->eroute->er_eaddr.sen_proto != 0) { ixs->ips.ips_transport_protocol = lsw_ip4_hdr(ixs)->protocol; if (ixs->eroute->er_eaddr.sen_sport != 0) { src.sin_port = lsw_ip4_hdr(ixs)->protocol == IPPROTO_UDP ? ((struct udphdr*) (((caddr_t)ixs->iph) + (lsw_ip4_hdr(ixs)->ihl << 2))) ->source : lsw_ip4_hdr(ixs)->protocol ==IPPROTO_TCP ? ((struct tcphdr*)((caddr_t)ixs->iph + (lsw_ip4_hdr(ixs)->ihl <<2))) ->source : 0; } if (ixs->eroute->er_eaddr.sen_dport != 0) { dst.sin_port = lsw_ip4_hdr(ixs)->protocol == IPPROTO_UDP ? ((struct udphdr*) (((caddr_t)ixs->iph) + (lsw_ip4_hdr(ixs)->ihl << 2))) ->dest : lsw_ip4_hdr(ixs)->protocol ==IPPROTO_TCP ? ((struct tcphdr*)((caddr_t)ixs->iph + (lsw_ip4_hdr(ixs)->ihl << 2))) ->dest : 0; } } ixs->ips.ips_addr_s = (struct sockaddr*)(&src); ixs->ips.ips_addr_d = (struct sockaddr*)(&dst); KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_xmit_encap_bundle: " "SADB_ACQUIRE sent with src=%s:%d, dst=%s:%d, proto=%d.\n", sin_addrtot(ixs->ips.ips_addr_s, 0, bufsrc, sizeof(bufsrc)) <= ADDRTOA_BUF ? bufsrc : "BAD_ADDR", ntohs(((struct sockaddr_in*)(ixs-> ips. ips_addr_s)) ->sin_port), sin_addrtot(ixs->ips.ips_addr_d, 0, bufdst, sizeof(bufdst)) <= ADDRTOA_BUF ? bufdst : "BAD_ADDR", ntohs(((struct sockaddr_in*)(ixs-> ips. ips_addr_d)) ->sin_port), ixs->ips.ips_said.proto); /* increment count of total traps needed */ ipsec_xmit_trap_count++; if (pfkey_acquire(&ixs->ips) == 0) { /* note that we succeeded */ ipsec_xmit_trap_sendcount++; if (ixs->outgoing_said.spi == htonl(SPI_TRAPSUBNET)) { /* * The spinlock is to prevent any other * process from accessing or deleting * the eroute while we are using and * updating it. */ spin_lock_bh(&eroute_lock); ixs->eroute = ipsec_findroute( &ixs->matcher); if (ixs->eroute) { ixs->eroute->er_said. spi = htonl(SPI_HOLD); ixs->eroute->er_first = ixs->skb; ixs->skb = NULL; } spin_unlock_bh(&eroute_lock); } else if (create_hold_eroute(ixs)) { ixs->skb = NULL; } /* whether or not the above succeeded, we continue */ } if (ixs->stats) ixs->stats->tx_dropped++; } default: /* XXX what do we do with an unknown shunt spi? */ break; } /* switch (ntohl(ixs->outgoing_said.spi)) */ return IPSEC_XMIT_STOLEN; } /* if (ixs->outgoing_said.proto == IPPROTO_INT) */ ixs->ipsp = ipsec_sa_getbyid(&ixs->outgoing_said, IPSEC_REFTX); ixs->sa_len = KLIPS_SATOT(debug_tunnel, &ixs->outgoing_said, 0, ixs->sa_txt, sizeof(ixs->sa_txt)); if (ixs->ipsp == NULL) { KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_xmit_encap_bundle: " "no ipsec_sa for SA%s: outgoing packet with no SA, dropped.\n", ixs->sa_len ? ixs->sa_txt : " (error)"); if (ixs->stats) ixs->stats->tx_dropped++; return IPSEC_XMIT_SAIDNOTFOUND; } return IPSEC_XMIT_OK; } enum ipsec_xmit_value ipsec_xmit_init2(struct ipsec_xmit_state *ixs) { enum ipsec_xmit_value bundle_stat = IPSEC_XMIT_OK; struct ipsec_sa *saved_ipsp; #ifdef CONFIG_KLIPS_ALG ixs->blocksize = 8; ixs->ixt_e = NULL; ixs->ixt_a = NULL; #endif /* CONFIG_KLIPS_ALG */ KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_xmit_init2: " "found ipsec_sa -- SA:<%s%s%s> %s\n", IPS_XFORM_NAME(ixs->ipsp), ixs->sa_len ? ixs->sa_txt : " (error)"); /* * How much headroom do we need to be able to apply * all the grouped transforms? */ saved_ipsp = ixs->ipsp; /* save the head of the ipsec_sa chain */ while (ixs->ipsp) { if (debug_tunnel & DB_TN_XMIT) { ixs->sa_len = KLIPS_SATOT(debug_tunnel, &ixs->ipsp->ips_said, 0, ixs->sa_txt, sizeof(ixs->sa_txt)); if (ixs->sa_len == 0) strcpy(ixs->sa_txt, "(error)"); } else { *ixs->sa_txt = 0; ixs->sa_len = 0; } /* If it is in larval state, drop the packet, we cannot process yet. */ if (ixs->ipsp->ips_state == K_SADB_SASTATE_LARVAL) { KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_xmit_init2: " "ipsec_sa in larval state for SA:<%s%s%s> %s, cannot be used yet, dropping packet.\n", IPS_XFORM_NAME(ixs->ipsp), ixs->sa_len ? ixs->sa_txt : " (error)"); if (ixs->stats) ixs->stats->tx_errors++; bundle_stat = IPSEC_XMIT_SAIDNOTLIVE; goto cleanup; } if (ixs->ipsp->ips_state == K_SADB_SASTATE_DEAD) { KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_xmit_init2: " "ipsec_sa in dead state for SA:<%s%s%s> %s, can no longer be used, dropping packet.\n", IPS_XFORM_NAME(ixs->ipsp), ixs->sa_len ? ixs->sa_txt : " (error)"); if (ixs->stats) ixs->stats->tx_errors++; bundle_stat = IPSEC_XMIT_SAIDNOTLIVE; goto cleanup; } /* If the replay window counter == -1, expire SA, it will roll */ if (ixs->ipsp->ips_replaywin && ixs->ipsp->ips_replaywin_lastseq == -1) { pfkey_expire(ixs->ipsp, 1); KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_xmit_init2: " "replay window counter rolled for SA:<%s%s%s> %s, packet dropped, expiring SA.\n", IPS_XFORM_NAME(ixs->ipsp), ixs->sa_len ? ixs->sa_txt : " (error)"); ipsec_sa_rm(ixs->ipsp); if (ixs->stats) ixs->stats->tx_errors++; bundle_stat = IPSEC_XMIT_REPLAYROLLED; goto cleanup; } /* * if this is the first time we are using this SA, mark start time, * and offset hard/soft counters by "now" for later checking. */ #if 0 if (ixs->ipsp->ips_life.ipl_usetime.count == 0) { ixs->ipsp->ips_life.ipl_usetime.count = jiffies; ixs->ipsp->ips_life.ipl_usetime.hard += jiffies; ixs->ipsp->ips_life.ipl_usetime.soft += jiffies; } #endif if (ipsec_lifetime_check(&ixs->ipsp->ips_life.ipl_bytes, "bytes", ixs->sa_txt, ipsec_life_countbased, ipsec_outgoing, ixs->ipsp) == ipsec_life_harddied || ipsec_lifetime_check(&ixs->ipsp->ips_life.ipl_addtime, "addtime", ixs->sa_txt, ipsec_life_timebased, ipsec_outgoing, ixs->ipsp) == ipsec_life_harddied || ipsec_lifetime_check(&ixs->ipsp->ips_life.ipl_usetime, "usetime", ixs->sa_txt, ipsec_life_timebased, ipsec_outgoing, ixs->ipsp) == ipsec_life_harddied || ipsec_lifetime_check(&ixs->ipsp->ips_life.ipl_packets, "packets", ixs->sa_txt, ipsec_life_countbased, ipsec_outgoing, ixs->ipsp) == ipsec_life_harddied) { ipsec_sa_rm(ixs->ipsp); if (ixs->stats) ixs->stats->tx_errors++; bundle_stat = IPSEC_XMIT_LIFETIMEFAILED; goto cleanup; } ixs->headroom = ixs->tailroom = 0; KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, "klips_debug:ipsec_xmit_init2: " "calling room for <%s%s%s>, SA:%s\n", IPS_XFORM_NAME(ixs->ipsp), ixs->sa_len ? ixs->sa_txt : " (error)"); switch (ixs->ipsp->ips_said.proto) { #ifdef CONFIG_KLIPS_AH case IPPROTO_AH: ixs->headroom += sizeof(struct ahhdr); break; #endif /* CONFIG_KLIPS_AH */ #ifdef CONFIG_KLIPS_ESP case IPPROTO_ESP: #ifdef CONFIG_KLIPS_OCF /* * this needs cleaning up for sure - DM */ if (ixs->ipsp->ocf_in_use) { switch (ixs->ipsp->ips_encalg) { case ESP_DES: case ESP_3DES: ixs->blocksize = 8; ixs->headroom += ESP_HEADER_LEN + 8 /* ivsize */; break; case ESP_AES: ixs->blocksize = 16; ixs->headroom += ESP_HEADER_LEN + 16 /* ivsize */; break; case ESP_NULL: ixs->blocksize = 16; ixs->headroom += ESP_HEADER_LEN + 0 /* ivsize */; break; default: if (ixs->stats) ixs->stats->tx_errors++; bundle_stat = IPSEC_XMIT_ESP_BADALG; goto cleanup; } } else #endif /* CONFIG_KLIPS_OCF */ #ifdef CONFIG_KLIPS_ALG if ((ixs->ixt_e = ixs->ipsp->ips_alg_enc)) { ixs->blocksize = ixs->ixt_e->ixt_common.ixt_blocksize; ixs->headroom += ESP_HEADER_LEN + ixs->ixt_e->ixt_common. ixt_support.ias_ivlen / 8; } else #endif /* CONFIG_KLIPS_ALG */ { if (ixs->stats) ixs->stats->tx_errors++; bundle_stat = IPSEC_XMIT_ESP_BADALG; goto cleanup; } #ifdef CONFIG_KLIPS_OCF if (ixs->ipsp->ocf_in_use) { switch (ixs->ipsp->ips_authalg) { case AH_MD5: case AH_SHA: ixs->tailroom += AHHMAC_HASHLEN; break; case AH_NONE: break; } } else #endif /* CONFIG_KLIPS_OCF */ #ifdef CONFIG_KLIPS_ALG if ((ixs->ixt_a = ixs->ipsp->ips_alg_auth)) ixs->tailroom += ixs->ixt_a->ixt_a_authlen; else #endif /* CONFIG_KLIPS_ALG */ switch (ixs->ipsp->ips_authalg) { #ifdef CONFIG_KLIPS_AUTH_HMAC_MD5 case AH_MD5: ixs->tailroom += AHHMAC_HASHLEN; break; #endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ #ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1 case AH_SHA: ixs->tailroom += AHHMAC_HASHLEN; break; #endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */ case AH_NONE: break; default: if (ixs->stats) ixs->stats->tx_errors++; bundle_stat = IPSEC_XMIT_AH_BADALG; goto cleanup; } ixs->tailroom += ixs->blocksize != 1 ? ((ixs->blocksize - ((ixs->pyldsz + 2) % ixs->blocksize)) % ixs->blocksize) + 2 : ((4 - ((ixs->pyldsz + 2) % 4)) % 4) + 2; if ((ixs->ipsp->ips_natt_type) && (!ixs->natt_type)) { ixs->natt_type = ixs->ipsp->ips_natt_type; ixs->natt_sport = ixs->ipsp->ips_natt_sport; ixs->natt_dport = ixs->ipsp->ips_natt_dport; switch (ixs->natt_type) { case ESPINUDP_WITH_NON_IKE: ixs->natt_head = sizeof(struct udphdr) + (2 * sizeof(__u32)); break; case ESPINUDP_WITH_NON_ESP: ixs->natt_head = sizeof(struct udphdr); break; default: KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, "klips_xmit: invalid nat-t type %d", ixs->natt_type); bundle_stat = IPSEC_XMIT_ESPUDP_BADTYPE; goto cleanup; break; } ixs->tailroom += ixs->natt_head; } break; #endif /* CONFIG_KLIPS_ESP */ #ifdef CONFIG_KLIPS_IPIP case IPPROTO_IPIP: if (ip_address_family(&ixs->ipsp->ips_said.dst) == AF_INET6) ixs->headroom += sizeof(struct ipv6hdr); else ixs->headroom += sizeof(struct iphdr); ixs->ipip_proto = lsw_ip_hdr_version(ixs) == 6 ? IPPROTO_IPV6 : IPPROTO_IPIP; break; #endif /* !CONFIG_KLIPS_IPIP */ case IPPROTO_COMP: #ifdef CONFIG_KLIPS_IPCOMP /* We can't predict how much the packet will shrink without doing the actual compression. We could do it here, if we were the first encapsulation in the chain. That might save us a skb_copy_expand, since we might fit into the existing skb then. However, this would be a bit unclean (and this hack has bit us once), so we better not do it. After all, the skb_copy_expand is cheap in comparison to the actual compression. At least we know the packet will not grow. */ break; #endif /* CONFIG_KLIPS_IPCOMP */ default: if (ixs->stats) ixs->stats->tx_errors++; bundle_stat = IPSEC_XMIT_BADPROTO; goto cleanup; } ixs->ipsp = ixs->ipsp->ips_next; KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, "klips_debug:ipsec_xmit_init2: " "Required head,tailroom: %d,%d\n", ixs->headroom, ixs->tailroom); ixs->max_headroom += ixs->headroom; ixs->max_tailroom += ixs->tailroom; ixs->pyldsz += (ixs->headroom + ixs->tailroom); } ixs->ipsp = saved_ipsp; /* restore the head of the ipsec_sa chain */ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, "klips_debug:ipsec_xmit_init2: " "existing head,tailroom: %d,%d before applying xforms with head,tailroom: %d,%d .\n", skb_headroom(ixs->skb), skb_tailroom(ixs->skb), ixs->max_headroom, ixs->max_tailroom); ixs->tot_headroom += ixs->max_headroom; ixs->tot_tailroom += ixs->max_tailroom; ixs->mtudiff = ixs->cur_mtu + ixs->tot_headroom + ixs->tot_tailroom - ixs->physmtu; KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, "klips_debug:ipsec_xmit_init2: " "mtu:%d physmtu:%d tothr:%d tottr:%d mtudiff:%d ippkttotlen:%u\n", ixs->cur_mtu, ixs->physmtu, ixs->tot_headroom, ixs->tot_tailroom, ixs->mtudiff, (unsigned int) (lsw_ip_hdr_version(ixs) == 6 ? (ntohs(lsw_ip6_hdr(ixs)->payload_len) + sizeof(struct ipv6hdr)) : ntohs(lsw_ip4_hdr(ixs)->tot_len))); if (ixs->cur_mtu == 0 || ixs->mtudiff > 0) { int newmtu = ixs->physmtu - (ixs->tot_headroom + ((ixs->tot_tailroom + 2) & ~7) + 5); KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, "klips_info:ipsec_xmit_init2: " "dev %s mtu of %d decreased by %d to %d\n", ixs->dev ? ixs->dev->name : "ifX", ixs->cur_mtu, ixs->cur_mtu - newmtu, newmtu); ixs->cur_mtu = newmtu; /* this would seem to adjust the MTU of the route as well */ #if 0 skb_dst(ixs->skb)->pmtu = ixs->iprv->mtu; /* RGB */ #endif /* 0 */ } /* If the sender is doing PMTU discovery, and the packet doesn't fit within ixs->prv->mtu, notify him (unless it was an ICMP packet, or it was not the zero-offset packet) and send it anyways. Note: buggy firewall configuration may prevent the ICMP packet from getting back. */ if (sysctl_ipsec_icmp) { int tot_len = lsw_ip_hdr_version(ixs) == 6 ? (ntohs(lsw_ip6_hdr(ixs)->payload_len) + sizeof(struct ipv6hdr)) : ntohs(lsw_ip4_hdr(ixs)->tot_len); if (ixs->cur_mtu < tot_len && lsw_ip_hdr_version(ixs) == 4 && (lsw_ip4_hdr(ixs)->frag_off & __constant_htons(IP_DF))) { int notify = lsw_ip4_hdr(ixs)->protocol != IPPROTO_ICMP && (lsw_ip4_hdr(ixs)->frag_off & __constant_htons(IP_OFFSET)) == 0; #ifdef IPSEC_obey_DF KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, "klips_debug:ipsec_xmit_init2: " "fragmentation needed and DF set; %sdropping packet\n", notify ? "sending ICMP and " : ""); if (notify) ICMP_SEND(ixs->skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, ixs->cur_mtu, ixs->physdev); if (ixs->stats) ixs->stats->tx_errors++; bundle_stat = IPSEC_XMIT_CANNOTFRAG; goto cleanup; #else /* IPSEC_obey_DF */ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, "klips_debug:ipsec_xmit_init2: " "fragmentation needed and DF set; %spassing packet\n", notify ? "sending ICMP and " : ""); if (notify) ICMP_SEND(ixs->skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, ixs->cur_mtu, ixs->physdev); #endif /* IPSEC_obey_DF */ } #ifdef CONFIG_KLIPS_IPV6 else if (ixs->cur_mtu < tot_len && lsw_ip_hdr_version(ixs) == 6) { IPSEC_FRAG_OFF_DECL(frag_off) int nexthdroff; unsigned char nexthdr = lsw_ip6_hdr(ixs)->nexthdr; nexthdroff = ipsec_ipv6_skip_exthdr(ixs->skb, ((void *)(lsw_ip6_hdr(ixs) + 1)) - (void*)ixs->skb->data, &nexthdr, &frag_off); ixs->iphlen = nexthdroff - (ixs->iph - (void*)ixs->skb->data); ixs->pyldsz = ntohs(lsw_ip6_hdr(ixs)->payload_len) + sizeof(struct ipv6hdr) - ixs->iphlen; KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, "klips_debug:ipsec_xmit_init2: " "fragmentation needed for nexthdr(%d) (got %d but mtu is %d); sending ICMPV6_PKT_TOOBIG and dropping the packet\n", nexthdr, tot_len, ixs->cur_mtu); ICMP6_SEND(ixs->skb, ICMPV6_PKT_TOOBIG, /* type */ 0, /* code */ ntohl(ixs->cur_mtu), ixs->physdev); if (ixs->stats) ixs->stats->tx_errors++; bundle_stat = IPSEC_XMIT_CANNOTFRAG; goto cleanup; } #endif } #ifdef MSS_HACK_DELETE_ME_PLEASE #ifdef CONFIG_KLIPS_IPV6 #error "this code is broken for IPv6" #endif /* * If this is a transport mode TCP packet with * SYN set, determine an effective MSS based on * AH/ESP overheads determined above. */ if (ixs->iph->protocol == IPPROTO_TCP && ixs->outgoing_said.proto != IPPROTO_IPIP) { struct tcphdr *tcph = ixs->skb->h.th; if (tcph->syn && !tcph->ack) { if (!ipsec_adjust_mss(ixs->skb, tcph, ixs->cur_mtu)) { printk(KERN_WARNING "klips_warning:ipsec_xmit_init2: " "ipsec_adjust_mss() failed\n"); if (ixs->stats) ixs->stats->tx_errors++; bundle_stat = IPSEC_XMIT_MSSERR; goto cleanup; } } } #endif /* MSS_HACK_DELETE_ME_PLEASE */ if ((ixs->natt_type) && (ixs->outgoing_said.proto != IPPROTO_IPIP)) { /** * NAT-Traversal and Transport Mode: * we need to force destination address to sane value */ struct sockaddr_in *sv4 = (struct sockaddr_in *)ixs->ipsp->ips_addr_d; __u32 natt_d = sv4->sin_addr.s_addr; struct iphdr *ipp = ixs->iph; /* set the destination address to what it needs to be for the * NAT encapsulation. */ KLIPS_PRINT(debug_tunnel, "xmit: setting ND=%08x\n", natt_d); ipp->daddr = natt_d; ipp->check = 0; /* zeroed so we get the right checksum */ ipp->check = ip_fast_csum((unsigned char *)ipp, ipp->ihl); } if (!ixs->hard_header_stripped && ixs->hard_header_len > 0) { KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_xmit_init2: " "allocating %d bytes for hardheader.\n", ixs->hard_header_len); if ((ixs->saved_header = kmalloc(ixs->hard_header_len, GFP_ATOMIC)) == NULL) { printk(KERN_WARNING "klips_debug:ipsec_xmit_init2: " "Failed, tried to allocate %d bytes for temp hard_header.\n", ixs->hard_header_len); if (ixs->stats) ixs->stats->tx_errors++; bundle_stat = IPSEC_XMIT_ERRMEMALLOC; goto cleanup; } memcpy(&ixs->saved_header[0], &ixs->skb->data[0], ixs->hard_header_len); if (ixs->skb->len < ixs->hard_header_len) { printk(KERN_WARNING "klips_error:ipsec_xmit_init2: " "tried to skb_pull hhlen=%d, %d available. This should never happen, please report.\n", ixs->hard_header_len, (int)(ixs->skb->len)); if (ixs->stats) ixs->stats->tx_errors++; bundle_stat = IPSEC_XMIT_ESP_PUSHPULLERR; goto cleanup; } skb_pull(ixs->skb, ixs->hard_header_len); ixs->hard_header_stripped = 1; /* ixs->iph = (struct iphdr *) (ixs->skb->data); */ KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, "klips_debug:ipsec_xmit_init2: " "head,tailroom: %d,%d after hard_header stripped.\n", skb_headroom(ixs->skb), skb_tailroom(ixs->skb)); KLIPS_IP_PRINT(debug_tunnel & DB_TN_CROUT, ixs->iph); } else { KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, "klips_debug:ipsec_xmit_init2: " "hard header already stripped.\n"); } ixs->ll_headroom = (ixs->hard_header_len + 15) & ~15; if ((skb_headroom(ixs->skb) >= ixs->max_headroom + 2 * ixs->ll_headroom) && (skb_tailroom(ixs->skb) >= ixs->max_tailroom) ) { KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, "klips_debug:ipsec_xmit_init2: " "data fits in existing skb\n"); } else { struct sk_buff *tskb; tskb = skb_copy_expand(ixs->skb, /* The need for 2 * link layer length here remains unexplained...RGB */ ixs->max_headroom + 2 * ixs->ll_headroom, ixs->max_tailroom, GFP_ATOMIC); if (tskb && ixs->skb->sk) skb_set_owner_w(tskb, ixs->skb->sk); if (ixs->oskb) ipsec_kfree_skb(ixs->skb); else ixs->oskb = ixs->skb; ixs->skb = tskb; if (!ixs->skb) { printk(KERN_WARNING "klips_debug:ipsec_xmit_init2: " "Failed, tried to allocate %d head and %d tailroom\n", ixs->max_headroom, ixs->max_tailroom); if (ixs->stats) ixs->stats->tx_errors++; bundle_stat = IPSEC_XMIT_ERRSKBALLOC; goto cleanup; } KLIPS_PRINT(debug_tunnel & DB_TN_CROUT, "klips_debug:ipsec_xmit_init2: " "head,tailroom: %d,%d after allocation\n", skb_headroom(ixs->skb), skb_tailroom(ixs->skb)); } KLIPS_IP_PRINT(debug_tunnel & DB_TN_ENCAP, ixs->iph); cleanup: return bundle_stat; } void ipsec_xmit_cleanup(struct ipsec_xmit_state *ixs) { void *p; if (ixs->saved_header) { p = ixs->saved_header; ixs->saved_header = NULL; kfree(p); } if (ixs->skb) { p = ixs->skb; ixs->skb = NULL; ipsec_kfree_skb(p); } if (ixs->oskb) { p = ixs->oskb; ixs->oskb = NULL; ipsec_kfree_skb(p); } if (ixs->pre_ipcomp_skb) { p = ixs->pre_ipcomp_skb; ixs->pre_ipcomp_skb = NULL; ipsec_kfree_skb(p); } if (ixs->ips.ips_ident_s.data) { p = ixs->ips.ips_ident_s.data; ixs->ips.ips_ident_s.data = NULL; kfree(p); } if (ixs->ips.ips_ident_d.data) { p = ixs->ips.ips_ident_d.data; ixs->ips.ips_ident_d.data = NULL; kfree(p); } if (ixs->ipsp) { p = ixs->ipsp; ixs->ipsp = NULL; ipsec_sa_put(p, IPSEC_REFTX); } } #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0) static inline int ipsec_xmit_send2(struct sk_buff *skb) #elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0) static inline int ipsec_xmit_send2(struct sock *sk, struct sk_buff *skb) #else static inline int ipsec_xmit_send2(struct net *net, struct sock *sk, struct sk_buff *skb) #endif { #ifdef NET_26 /* 2.6 kernels */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) return dst_output(dev_net(skb->dev), sk, skb); #else return dst_output(skb); #endif #else return ip_send(skb); #endif } static inline int ipsec_xmit_send2_mast(struct sk_buff *skb) { #ifdef NET_26 /* 2.6 kernels */ # if defined(CONFIG_NETFILTER) /* prevent recursion through the saref route */ if (skb->nfmark & 0x80000000) skb->nfmark = 0; # endif #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0) return ipsec_xmit_send2(skb); #elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0) return ipsec_xmit_send2(skb->sk, skb); #else return ipsec_xmit_send2(dev_net(skb->dev), skb->sk, skb); #endif } enum ipsec_xmit_value ipsec_nat_encap(struct ipsec_xmit_state *ixs) { if (ixs->natt_type && ixs->natt_head) { struct iphdr *ipp = ip_hdr(ixs->skb); struct udphdr *udp; KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_nat_encap: " "encapsuling packet into UDP (NAT-Traversal) (%d %d)\n", ixs->natt_type, ixs->natt_head); ixs->iphlen = ipp->ihl << 2; ipp->tot_len = htons(ntohs(ipp->tot_len) + ixs->natt_head); if (skb_tailroom(ixs->skb) < ixs->natt_head) { printk(KERN_WARNING "klips_error:ipsec_nat_encap: " "tried to skb_put %d, %d available. Returning IPSEC_XMIT_ESPUDP. " "This should never happen, please report.\n", ixs->natt_head, skb_tailroom(ixs->skb)); if (ixs->stats) ixs->stats->tx_errors++; return IPSEC_XMIT_ESPUDP; } skb_put(ixs->skb, ixs->natt_head); udp = (struct udphdr *)((char *)ipp + ixs->iphlen); /* move ESP hdr after UDP hdr */ memmove((void *)((char *)udp + ixs->natt_head), (void *)(udp), ntohs(ipp->tot_len) - ixs->iphlen - ixs->natt_head); #if 0 /* set IP destination address (matters in transport mode) */ { struct sockaddr_in *d = (struct sockaddr_in *)ixs->ipsp->ips_addr_d; ipp->daddr = d->sin_addr.s_addr; } #endif /* clear UDP & Non-IKE Markers (if any) */ memset(udp, 0, ixs->natt_head); /* fill UDP with useful informations ;-) */ udp->source = htons(ixs->natt_sport); udp->dest = htons(ixs->natt_dport); udp->len = htons(ntohs(ipp->tot_len) - ixs->iphlen); /* set protocol */ ipp->protocol = IPPROTO_UDP; /* fix IP checksum */ ipp->check = 0; ipp->check = ip_fast_csum((unsigned char *)ipp, ipp->ihl); } return IPSEC_XMIT_OK; } static int ipsec_set_dst(struct ipsec_xmit_state *ixs) { struct dst_entry *dst = NULL; int error = 0; #ifdef NET_26 struct flowi fl; #endif if (ixs->set_dst) return IPSEC_XMIT_OK; #ifdef NET_26 memset(&fl, 0, sizeof(fl)); /* new route/dst cache code from James Morris */ ixs->skb->dev = ixs->physdev; fl.flowi_oif = ixs->physdev ? ixs->physdev->ifindex : 0; # ifdef CONFIG_KLIPS_IPV6 if (lsw_ip_hdr_version(ixs) == 6) { /* saddr must not be set with ipv6, otherwise you can't * force the output device with linux kernels >= 4.3. * (kernel commit d46a9d678e4c9fac1e968d0593e4dba683389324) */ memset(&fl.nl_u.ip6_u.saddr, 0, sizeof(fl.nl_u.ip6_u.saddr)); fl.nl_u.ip6_u.daddr = lsw_ip6_hdr(ixs)->daddr; /* fl->nl_u.ip6_u.tos = RT_TOS(lsw_ip6_hdr(ixs)->tos); */ fl.flowi_proto = IPPROTO_IPV6; # ifndef FLOW_HAS_NO_MARK fl.flowi_mark = ixs->skb->mark; # endif # if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 24) dst = ip6_route_output(NULL, &fl); # elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39) dst = ip6_route_output(&init_net, NULL, &fl); # else dst = ip6_route_output(&init_net, NULL, &fl.nl_u.ip6_u); # endif error = dst->error; } else # endif /* CONFIG_KLIPS_IPV6 */ { fl.nl_u.ip4_u.daddr = lsw_ip4_hdr(ixs)->daddr; fl.nl_u.ip4_u.saddr = ixs->pass ? 0 : lsw_ip4_hdr(ixs)->saddr; fl.flowi_tos = RT_TOS(lsw_ip4_hdr(ixs)->tos); fl.flowi_proto = lsw_ip4_hdr(ixs)->protocol; # ifndef FLOW_HAS_NO_MARK fl.flowi_mark = ixs->skb->mark; # endif # if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39) # if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 24) error = ip_route_output_key(&ixs->route, &fl); # else error = ip_route_output_key(&init_net, &ixs->route, &fl); # endif if (ixs->route) dst = &ipsec_route_dst(ixs->route); # else ixs->route = ip_route_output_key(&init_net, &fl.u.ip4); if (IS_ERR(ixs->route)) { error = PTR_ERR(ixs->route); ixs->route = NULL; } else { error = 0; dst = &ipsec_route_dst(ixs->route); } # endif } #else # ifdef CONFIG_KLIPS_IPV6 # error "this code is broken for IPv6" # endif /*skb_orphan(ixs->skb);*/ error = ip_route_output(&ixs->route, lsw_ip4_hdr(ixs)->daddr, ixs->pass ? 0 : lsw_ip4_hdr(ixs)->saddr, RT_TOS(lsw_ip4_hdr(ixs)->tos), /* mcr->rgb: should this be 0 instead? */ ixs->physdev->ifindex); if (ixs->route) dst = &ipsec_route_dst(ixs->route); #endif if (error) { if (ixs->stats) ixs->stats->tx_errors++; KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_set_dst: " "ip_route_output failed with error code %d, dropped\n", error); return IPSEC_XMIT_ROUTEERR; } if (dst == NULL) { if (ixs->stats) ixs->stats->tx_errors++; KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_set_dst: " "ip_route_output failed with no dst, dropped\n"); return IPSEC_XMIT_ROUTEERR; } /* ixs->physdev can be NULL in mast mode and we searched for a non-device * specific route. Now we can use the device for the route we found. */ if (!ixs->skb->dev) ixs->skb->dev = dst->dev; if (ixs->dev == dst->dev) { if (lsw_ip_hdr_version(ixs) == 6) dst_release(dst); else ip_rt_put(ixs->route); /* This is recursion, drop it. */ if (ixs->stats) ixs->stats->tx_errors++; KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_set_dst: " "suspect recursion, dev=rt->u.dst.dev=%s, dropped\n", ixs->dev->name); return IPSEC_XMIT_RECURSDETECT; } skb_dst_drop(ixs->skb); skb_dst_set(ixs->skb, dst); ixs->set_dst = 1; return IPSEC_XMIT_OK; } enum ipsec_xmit_value ipsec_xmit_send(struct ipsec_xmit_state *ixs) { int error; if (ixs->skb == NULL || ixs->skb->dev == NULL) return IPSEC_XMIT_NODEV; /* * ipsec_set_dst may have been done in the IPIP code, or we do it now. * DAVIDM - I actually think it must have always been done before * now, but ESP without IPIP and no AH may be the * exception. You cannot hash and then do ipsec_set_dst :-) */ error = ipsec_set_dst(ixs); if (error != IPSEC_XMIT_OK) return error; if (ixs->stats) ixs->stats->tx_bytes += ixs->skb->len; if (ixs->skb->len < skb_network_header(ixs->skb) - ixs->skb->data) { if (ixs->stats) ixs->stats->tx_errors++; printk(KERN_WARNING "klips_error:ipsec_xmit_send: " "tried to __skb_pull nh-data=%td, %d available. This should never happen, please report.\n", skb_network_header(ixs->skb) - ixs->skb->data, ixs->skb->len); return IPSEC_XMIT_PUSHPULLERR; } __skb_pull(ixs->skb, skb_network_header(ixs->skb) - ixs->skb->data); if (!ixs->pass) ipsec_nf_reset(ixs->skb); /* fix up the checksum after changes to the header */ if (ip_hdr(ixs->skb)->version == 4) { ip_hdr(ixs->skb)->check = 0; ip_hdr(ixs->skb)->check = ip_fast_csum((unsigned char *)ip_hdr(ixs->skb), ip_hdr(ixs->skb)->ihl); } KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_xmit_send: " "...done, calling ip_send() on device:%s%s\n", ixs->skb->dev ? ixs->skb->dev->name : "NULL", ixs->mast_mode ? "(mast)" : ""); KLIPS_IP_PRINT(debug_tunnel & DB_TN_XMIT, ip_hdr(ixs->skb)); { int err; if (ixs->mast_mode) { /* skip filtering on mast devices, since it resets our * route, nfmark, and causes nasty reentrancy. */ err = ipsec_xmit_send2_mast(ixs->skb); } else if (ip_hdr(ixs->skb)->version == 6) { err = NF_HOOK(PF_INET6, LSW_NF_INET_LOCAL_OUT, #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) dev_net(ixs->skb->dev), #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) ixs->skb->sk, #endif ixs->skb, NULL, ixs->route ? ipsec_route_dst(ixs->route).dev : skb_dst(ixs->skb)->dev, ipsec_xmit_send2); } else { err = NF_HOOK(PF_INET, LSW_NF_INET_LOCAL_OUT, #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) dev_net(ixs->skb->dev), #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) ixs->skb->sk, #endif ixs->skb, NULL, ixs->route ? ipsec_route_dst(ixs->route).dev : skb_dst(ixs->skb)->dev, ipsec_xmit_send2); } if (err != NET_XMIT_SUCCESS && err != NET_XMIT_CN) { if (net_ratelimit()) { printk(KERN_ERR "klips_error:ipsec_xmit_send: " "ip_send() failed, err=%d\n", -err); } if (ixs->stats) { ixs->stats->tx_errors++; ixs->stats->tx_aborted_errors++; } ixs->skb = NULL; return IPSEC_XMIT_IPSENDFAILURE; } } if (ixs->stats) ixs->stats->tx_packets++; ixs->skb = NULL; return IPSEC_XMIT_OK; } enum ipsec_xmit_value ipsec_tunnel_send(struct ipsec_xmit_state *ixs) { return ipsec_xmit_send(ixs); } /* * here is a state machine to handle encapsulation * basically we keep getting re-entered until processing is * complete. For the simple case we step down the states and finish. * each state is ideally some logical part of the process. If a state * can pend (ie., require async processing to complete), then this * should be the part of last action before it returns IPSEC_RCV_PENDING * * Any particular action may alter the next_state in ixs to move us to * a state other than the preferred "next_state", but this is the * exception and is highlighted when it is done. * * prototypes for state action */ static struct { enum ipsec_xmit_value (*action)(struct ipsec_xmit_state *ixs); int next_state; } xmit_state_table[] = { [IPSEC_XSM_INIT1] = { ipsec_xmit_init1, IPSEC_XSM_INIT2 }, [IPSEC_XSM_INIT2] = { ipsec_xmit_init2, IPSEC_XSM_ENCAP_INIT }, [IPSEC_XSM_ENCAP_INIT] = { ipsec_xmit_encap_init, IPSEC_XSM_ENCAP_SELECT }, [IPSEC_XSM_ENCAP_SELECT] = { ipsec_xmit_encap_select, IPSEC_XSM_DONE }, #ifdef CONFIG_KLIPS_ESP [IPSEC_XSM_ESP] = { ipsec_xmit_esp, IPSEC_XSM_ESP_AH }, [IPSEC_XSM_ESP_AH] = { ipsec_xmit_esp_ah, IPSEC_XSM_CONT }, #endif #ifdef CONFIG_KLIPS_AH [IPSEC_XSM_AH] = { ipsec_xmit_ah, IPSEC_XSM_CONT }, #endif #ifdef CONFIG_KLIPS_IPIP [IPSEC_XSM_IPIP] = { ipsec_xmit_ipip, IPSEC_XSM_CONT }, #endif #ifdef CONFIG_KLIPS_IPCOMP [IPSEC_XSM_IPCOMP] = { ipsec_xmit_ipcomp, IPSEC_XSM_CONT }, #endif [IPSEC_XSM_CONT] = { ipsec_xmit_cont, IPSEC_XSM_DONE }, [IPSEC_XSM_DONE] = { NULL, IPSEC_XSM_DONE }, }; void ipsec_xsm(struct ipsec_xmit_state *ixs) { enum ipsec_xmit_value stat = IPSEC_XMIT_ENCAPFAIL; unsigned more_allowed; if (ixs == NULL) { KLIPS_PRINT(debug_tunnel, "klips_debug:ipsec_xsm: ixs == NULL.\n"); return; } /* * make sure nothing is removed from underneath us */ spin_lock_bh(&tdb_lock); /* * if we have a valid said, then we must check it here to ensure it * hasn't gone away while we were waiting for a task to complete. * * If the said was found via saref in mast code, skip this check. */ if (ixs->ipsp && !ixs->mast_mode) { struct ipsec_sa *ipsp; ipsp = ipsec_sa_getbyid(&ixs->outgoing_said, IPSEC_REFTX); if (unlikely(ipsp == NULL)) { KLIPS_PRINT(debug_tunnel, "klips_debug:ipsec_xsm: " "no ipsec_sa for SA:%s: " "outgoing packet with no SA dropped\n", ixs->sa_len ? ixs->sa_txt : " (error)"); if (ixs->stats) ixs->stats->tx_dropped++; /* drop through and cleanup */ stat = IPSEC_XMIT_SAIDNOTFOUND; ixs->state = IPSEC_XSM_DONE; } else { /* put the ref count back */ ipsec_sa_put(ipsp, IPSEC_REFTX); } } more_allowed = 1000; while (ixs->state != IPSEC_XSM_DONE && --more_allowed) { ixs->next_state = xmit_state_table[ixs->state].next_state; stat = xmit_state_table[ixs->state].action(ixs); if (stat == IPSEC_XMIT_OK) { /* some functions change the next state, see the state table */ ixs->state = ixs->next_state; } else if (stat == IPSEC_XMIT_PENDING) { /* * things are on hold until we return here in the next/new state * we check our SA is valid when we return */ spin_unlock_bh(&tdb_lock); return; } else { /* bad result, force state change to done */ KLIPS_PRINT(debug_tunnel, "klips_debug:ipsec_xsm: " "processing completed due to %s.\n", ipsec_xmit_err(stat)); ixs->state = IPSEC_XSM_DONE; } } /* * all done with anything needing locks */ spin_unlock_bh(&tdb_lock); /* * let the caller continue with their processing */ ixs->xsm_complete(ixs, stat); } libreswan-3.32/linux/net/ipsec/match586.S000066400000000000000000000241301365625662500201620ustar00rootroot00000000000000/* match.s -- Pentium-optimized version of longest_match() * Written for zlib 1.1.2 * Copyright (C) 1998 Brian Raiter * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License. */ #ifndef NO_UNDERLINE #define match_init _ipcomp_match_init #define longest_match _ipcomp_longest_match #else #define match_init ipcomp_match_init #define longest_match ipcomp_longest_match #endif #define MAX_MATCH (258) #define MIN_MATCH (3) #define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1) #define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7) /* stack frame offsets */ #define wmask 0 /* local copy of s->wmask */ #define window 4 /* local copy of s->window */ #define windowbestlen 8 /* s->window + bestlen */ #define chainlenscanend 12 /* high word: current chain len */ /* low word: last bytes sought */ #define scanstart 16 /* first two bytes of string */ #define scanalign 20 /* dword-misalignment of string */ #define nicematch 24 /* a good enough match size */ #define bestlen 28 /* size of best match so far */ #define scan 32 /* ptr to string wanting match */ #define LocalVarsSize (36) /* saved ebx 36 */ /* saved edi 40 */ /* saved esi 44 */ /* saved ebp 48 */ /* return address 52 */ #define deflatestate 56 /* the function arguments */ #define curmatch 60 /* Offsets for fields in the deflate_state structure. These numbers * are calculated from the definition of deflate_state, with the * assumption that the compiler will dword-align the fields. (Thus, * changing the definition of deflate_state could easily cause this * program to crash horribly, without so much as a warning at * compile time. Sigh.) */ #define dsWSize 36 #define dsWMask 44 #define dsWindow 48 #define dsPrev 56 #define dsMatchLen 88 #define dsPrevMatch 92 #define dsStrStart 100 #define dsMatchStart 104 #define dsLookahead 108 #define dsPrevLen 112 #define dsMaxChainLen 116 #define dsGoodMatch 132 #define dsNiceMatch 136 .file "match.S" .globl match_init, longest_match .text /* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */ longest_match: /* Save registers that the compiler may be using, and adjust %esp to */ /* make room for our stack frame. */ pushl %ebp pushl %edi pushl %esi pushl %ebx subl $LocalVarsSize, %esp /* Retrieve the function arguments. %ecx will hold cur_match */ /* throughout the entire function. %edx will hold the pointer to the */ /* deflate_state structure during the function's setup (before */ /* entering the main loop). */ movl deflatestate(%esp), %edx movl curmatch(%esp), %ecx /* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */ movl dsNiceMatch(%edx), %eax movl dsLookahead(%edx), %ebx cmpl %eax, %ebx jl LookaheadLess movl %eax, %ebx LookaheadLess: movl %ebx, nicematch(%esp) /* register Bytef *scan = s->window + s->strstart; */ movl dsWindow(%edx), %esi movl %esi, window(%esp) movl dsStrStart(%edx), %ebp lea (%esi,%ebp), %edi movl %edi, scan(%esp) /* Determine how many bytes the scan ptr is off from being */ /* dword-aligned. */ movl %edi, %eax negl %eax andl $3, %eax movl %eax, scanalign(%esp) /* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */ /* s->strstart - (IPos)MAX_DIST(s) : NIL; */ movl dsWSize(%edx), %eax subl $MIN_LOOKAHEAD, %eax subl %eax, %ebp jg LimitPositive xorl %ebp, %ebp LimitPositive: /* unsigned chain_length = s->max_chain_length; */ /* if (s->prev_length >= s->good_match) { */ /* chain_length >>= 2; */ /* } */ movl dsPrevLen(%edx), %eax movl dsGoodMatch(%edx), %ebx cmpl %ebx, %eax movl dsMaxChainLen(%edx), %ebx jl LastMatchGood shrl $2, %ebx LastMatchGood: /* chainlen is decremented once beforehand so that the function can */ /* use the sign flag instead of the zero flag for the exit test. */ /* It is then shifted into the high word, to make room for the scanend */ /* scanend value, which it will always accompany. */ decl %ebx shll $16, %ebx /* int best_len = s->prev_length; */ movl dsPrevLen(%edx), %eax movl %eax, bestlen(%esp) /* Store the sum of s->window + best_len in %esi locally, and in %esi. */ addl %eax, %esi movl %esi, windowbestlen(%esp) /* register ush scan_start = *(ushf*)scan; */ /* register ush scan_end = *(ushf*)(scan+best_len-1); */ movw (%edi), %bx movw %bx, scanstart(%esp) movw -1(%edi,%eax), %bx movl %ebx, chainlenscanend(%esp) /* Posf *prev = s->prev; */ /* uInt wmask = s->w_mask; */ movl dsPrev(%edx), %edi movl dsWMask(%edx), %edx mov %edx, wmask(%esp) /* Jump into the main loop. */ jmp LoopEntry .balign 16 /* do { * match = s->window + cur_match; * if (*(ushf*)(match+best_len-1) != scan_end || * *(ushf*)match != scan_start) continue; * [...] * } while ((cur_match = prev[cur_match & wmask]) > limit * && --chain_length != 0); * * Here is the inner loop of the function. The function will spend the * majority of its time in this loop, and majority of that time will * be spent in the first ten instructions. * * Within this loop: * %ebx = chainlenscanend - i.e., ((chainlen << 16) | scanend) * %ecx = curmatch * %edx = curmatch & wmask * %esi = windowbestlen - i.e., (window + bestlen) * %edi = prev * %ebp = limit * * Two optimization notes on the choice of instructions: * * The first instruction uses a 16-bit address, which costs an extra, * unpairable cycle. This is cheaper than doing a 32-bit access and * zeroing the high word, due to the 3-cycle misalignment penalty which * would occur half the time. This also turns out to be cheaper than * doing two separate 8-bit accesses, as the memory is so rarely in the * L1 cache. * * The window buffer, however, apparently spends a lot of time in the * cache, and so it is faster to retrieve the word at the end of the * match string with two 8-bit loads. The instructions that test the * word at the beginning of the match string, however, are executed * much less frequently, and there it was cheaper to use 16-bit * instructions, which avoided the necessity of saving off and * subsequently reloading one of the other registers. */ LookupLoop: /* 1 U & V */ movw (%edi,%edx,2), %cx /* 2 U pipe */ movl wmask(%esp), %edx /* 2 V pipe */ cmpl %ebp, %ecx /* 3 U pipe */ jbe LeaveNow /* 3 V pipe */ subl $0x00010000, %ebx /* 4 U pipe */ js LeaveNow /* 4 V pipe */ LoopEntry: movb -1(%esi,%ecx), %al /* 5 U pipe */ andl %ecx, %edx /* 5 V pipe */ cmpb %bl, %al /* 6 U pipe */ jnz LookupLoop /* 6 V pipe */ movb (%esi,%ecx), %ah cmpb %bh, %ah jnz LookupLoop movl window(%esp), %eax movw (%eax,%ecx), %ax cmpw scanstart(%esp), %ax jnz LookupLoop /* Store the current value of chainlen. */ movl %ebx, chainlenscanend(%esp) /* Point %edi to the string under scrutiny, and %esi to the string we */ /* are hoping to match it up with. In actuality, %esi and %edi are */ /* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */ /* initialized to -(MAX_MATCH_8 - scanalign). */ movl window(%esp), %esi movl scan(%esp), %edi addl %ecx, %esi movl scanalign(%esp), %eax movl $(-MAX_MATCH_8), %edx lea MAX_MATCH_8(%edi,%eax), %edi lea MAX_MATCH_8(%esi,%eax), %esi /* Test the strings for equality, 8 bytes at a time. At the end, * adjust %edx so that it is offset to the exact byte that mismatched. * * We already know at this point that the first three bytes of the * strings match each other, and they can be safely passed over before * starting the compare loop. So what this code does is skip over 0-3 * bytes, as much as necessary in order to dword-align the %edi * pointer. (%esi will still be misaligned three times out of four.) * * It should be confessed that this loop usually does not represent * much of the total running time. Replacing it with a more * straightforward "rep cmpsb" would not drastically degrade * performance. */ LoopCmps: movl (%esi,%edx), %eax movl (%edi,%edx), %ebx xorl %ebx, %eax jnz LeaveLoopCmps movl 4(%esi,%edx), %eax movl 4(%edi,%edx), %ebx xorl %ebx, %eax jnz LeaveLoopCmps4 addl $8, %edx jnz LoopCmps jmp LenMaximum LeaveLoopCmps4: addl $4, %edx LeaveLoopCmps: testl $0x0000FFFF, %eax jnz LenLower addl $2, %edx shrl $16, %eax LenLower: subb $1, %al adcl $0, %edx /* Calculate the length of the match. If it is longer than MAX_MATCH, */ /* then automatically accept it as the best possible match and leave. */ lea (%edi,%edx), %eax movl scan(%esp), %edi subl %edi, %eax cmpl $MAX_MATCH, %eax jge LenMaximum /* If the length of the match is not longer than the best match we */ /* have so far, then forget it and return to the lookup loop. */ movl deflatestate(%esp), %edx movl bestlen(%esp), %ebx cmpl %ebx, %eax jg LongerMatch movl chainlenscanend(%esp), %ebx movl windowbestlen(%esp), %esi movl dsPrev(%edx), %edi movl wmask(%esp), %edx andl %ecx, %edx jmp LookupLoop /* s->match_start = cur_match; */ /* best_len = len; */ /* if (len >= nice_match) break; */ /* scan_end = *(ushf*)(scan+best_len-1); */ LongerMatch: movl nicematch(%esp), %ebx movl %eax, bestlen(%esp) movl %ecx, dsMatchStart(%edx) cmpl %ebx, %eax jge LeaveNow movl window(%esp), %esi addl %eax, %esi movl %esi, windowbestlen(%esp) movl chainlenscanend(%esp), %ebx movw -1(%edi,%eax), %bx movl dsPrev(%edx), %edi movl %ebx, chainlenscanend(%esp) movl wmask(%esp), %edx andl %ecx, %edx jmp LookupLoop /* Accept the current string, with the maximum possible length. */ LenMaximum: movl deflatestate(%esp), %edx movl $MAX_MATCH, bestlen(%esp) movl %ecx, dsMatchStart(%edx) /* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */ /* return s->lookahead; */ LeaveNow: movl deflatestate(%esp), %edx movl bestlen(%esp), %ebx movl dsLookahead(%edx), %eax cmpl %eax, %ebx jg LookaheadRet movl %ebx, %eax LookaheadRet: /* Restore the stack and return from whence we came. */ addl $LocalVarsSize, %esp popl %ebx popl %esi popl %edi popl %ebp match_init: ret libreswan-3.32/linux/net/ipsec/match686.S000066400000000000000000000216251365625662500201710ustar00rootroot00000000000000/* match.s -- Pentium-Pro-optimized version of longest_match() * Written for zlib 1.1.2 * Copyright (C) 1998 Brian Raiter * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License. */ #ifndef NO_UNDERLINE #define match_init _ipcomp_match_init #define longest_match _ipcomp_longest_match #else #define match_init ipcomp_match_init #define longest_match ipcomp_longest_match #endif #define MAX_MATCH (258) #define MIN_MATCH (3) #define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1) #define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7) /* stack frame offsets */ #define chainlenwmask 0 /* high word: current chain len */ /* low word: s->wmask */ #define window 4 /* local copy of s->window */ #define windowbestlen 8 /* s->window + bestlen */ #define scanstart 16 /* first two bytes of string */ #define scanend 12 /* last two bytes of string */ #define scanalign 20 /* dword-misalignment of string */ #define nicematch 24 /* a good enough match size */ #define bestlen 28 /* size of best match so far */ #define scan 32 /* ptr to string wanting match */ #define LocalVarsSize (36) /* saved ebx 36 */ /* saved edi 40 */ /* saved esi 44 */ /* saved ebp 48 */ /* return address 52 */ #define deflatestate 56 /* the function arguments */ #define curmatch 60 /* Offsets for fields in the deflate_state structure. These numbers * are calculated from the definition of deflate_state, with the * assumption that the compiler will dword-align the fields. (Thus, * changing the definition of deflate_state could easily cause this * program to crash horribly, without so much as a warning at * compile time. Sigh.) */ #define dsWSize 36 #define dsWMask 44 #define dsWindow 48 #define dsPrev 56 #define dsMatchLen 88 #define dsPrevMatch 92 #define dsStrStart 100 #define dsMatchStart 104 #define dsLookahead 108 #define dsPrevLen 112 #define dsMaxChainLen 116 #define dsGoodMatch 132 #define dsNiceMatch 136 .file "match.S" .globl match_init, longest_match .text /* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */ longest_match: /* Save registers that the compiler may be using, and adjust %esp to */ /* make room for our stack frame. */ pushl %ebp pushl %edi pushl %esi pushl %ebx subl $LocalVarsSize, %esp /* Retrieve the function arguments. %ecx will hold cur_match */ /* throughout the entire function. %edx will hold the pointer to the */ /* deflate_state structure during the function's setup (before */ /* entering the main loop). */ movl deflatestate(%esp), %edx movl curmatch(%esp), %ecx /* uInt wmask = s->w_mask; */ /* unsigned chain_length = s->max_chain_length; */ /* if (s->prev_length >= s->good_match) { */ /* chain_length >>= 2; */ /* } */ movl dsPrevLen(%edx), %eax movl dsGoodMatch(%edx), %ebx cmpl %ebx, %eax movl dsWMask(%edx), %eax movl dsMaxChainLen(%edx), %ebx jl LastMatchGood shrl $2, %ebx LastMatchGood: /* chainlen is decremented once beforehand so that the function can */ /* use the sign flag instead of the zero flag for the exit test. */ /* It is then shifted into the high word, to make room for the wmask */ /* value, which it will always accompany. */ decl %ebx shll $16, %ebx orl %eax, %ebx movl %ebx, chainlenwmask(%esp) /* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */ movl dsNiceMatch(%edx), %eax movl dsLookahead(%edx), %ebx cmpl %eax, %ebx jl LookaheadLess movl %eax, %ebx LookaheadLess: movl %ebx, nicematch(%esp) /* register Bytef *scan = s->window + s->strstart; */ movl dsWindow(%edx), %esi movl %esi, window(%esp) movl dsStrStart(%edx), %ebp lea (%esi,%ebp), %edi movl %edi, scan(%esp) /* Determine how many bytes the scan ptr is off from being */ /* dword-aligned. */ movl %edi, %eax negl %eax andl $3, %eax movl %eax, scanalign(%esp) /* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */ /* s->strstart - (IPos)MAX_DIST(s) : NIL; */ movl dsWSize(%edx), %eax subl $MIN_LOOKAHEAD, %eax subl %eax, %ebp jg LimitPositive xorl %ebp, %ebp LimitPositive: /* int best_len = s->prev_length; */ movl dsPrevLen(%edx), %eax movl %eax, bestlen(%esp) /* Store the sum of s->window + best_len in %esi locally, and in %esi. */ addl %eax, %esi movl %esi, windowbestlen(%esp) /* register ush scan_start = *(ushf*)scan; */ /* register ush scan_end = *(ushf*)(scan+best_len-1); */ /* Posf *prev = s->prev; */ movzwl (%edi), %ebx movl %ebx, scanstart(%esp) movzwl -1(%edi,%eax), %ebx movl %ebx, scanend(%esp) movl dsPrev(%edx), %edi /* Jump into the main loop. */ movl chainlenwmask(%esp), %edx jmp LoopEntry .balign 16 /* do { * match = s->window + cur_match; * if (*(ushf*)(match+best_len-1) != scan_end || * *(ushf*)match != scan_start) continue; * [...] * } while ((cur_match = prev[cur_match & wmask]) > limit * && --chain_length != 0); * * Here is the inner loop of the function. The function will spend the * majority of its time in this loop, and majority of that time will * be spent in the first ten instructions. * * Within this loop: * %ebx = scanend * %ecx = curmatch * %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask) * %esi = windowbestlen - i.e., (window + bestlen) * %edi = prev * %ebp = limit */ LookupLoop: andl %edx, %ecx movzwl (%edi,%ecx,2), %ecx cmpl %ebp, %ecx jbe LeaveNow subl $0x00010000, %edx js LeaveNow LoopEntry: movzwl -1(%esi,%ecx), %eax cmpl %ebx, %eax jnz LookupLoop movl window(%esp), %eax movzwl (%eax,%ecx), %eax cmpl scanstart(%esp), %eax jnz LookupLoop /* Store the current value of chainlen. */ movl %edx, chainlenwmask(%esp) /* Point %edi to the string under scrutiny, and %esi to the string we */ /* are hoping to match it up with. In actuality, %esi and %edi are */ /* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */ /* initialized to -(MAX_MATCH_8 - scanalign). */ movl window(%esp), %esi movl scan(%esp), %edi addl %ecx, %esi movl scanalign(%esp), %eax movl $(-MAX_MATCH_8), %edx lea MAX_MATCH_8(%edi,%eax), %edi lea MAX_MATCH_8(%esi,%eax), %esi /* Test the strings for equality, 8 bytes at a time. At the end, * adjust %edx so that it is offset to the exact byte that mismatched. * * We already know at this point that the first three bytes of the * strings match each other, and they can be safely passed over before * starting the compare loop. So what this code does is skip over 0-3 * bytes, as much as necessary in order to dword-align the %edi * pointer. (%esi will still be misaligned three times out of four.) * * It should be confessed that this loop usually does not represent * much of the total running time. Replacing it with a more * straightforward "rep cmpsb" would not drastically degrade * performance. */ LoopCmps: movl (%esi,%edx), %eax xorl (%edi,%edx), %eax jnz LeaveLoopCmps movl 4(%esi,%edx), %eax xorl 4(%edi,%edx), %eax jnz LeaveLoopCmps4 addl $8, %edx jnz LoopCmps jmp LenMaximum LeaveLoopCmps4: addl $4, %edx LeaveLoopCmps: testl $0x0000FFFF, %eax jnz LenLower addl $2, %edx shrl $16, %eax LenLower: subb $1, %al adcl $0, %edx /* Calculate the length of the match. If it is longer than MAX_MATCH, */ /* then automatically accept it as the best possible match and leave. */ lea (%edi,%edx), %eax movl scan(%esp), %edi subl %edi, %eax cmpl $MAX_MATCH, %eax jge LenMaximum /* If the length of the match is not longer than the best match we */ /* have so far, then forget it and return to the lookup loop. */ movl deflatestate(%esp), %edx movl bestlen(%esp), %ebx cmpl %ebx, %eax jg LongerMatch movl windowbestlen(%esp), %esi movl dsPrev(%edx), %edi movl scanend(%esp), %ebx movl chainlenwmask(%esp), %edx jmp LookupLoop /* s->match_start = cur_match; */ /* best_len = len; */ /* if (len >= nice_match) break; */ /* scan_end = *(ushf*)(scan+best_len-1); */ LongerMatch: movl nicematch(%esp), %ebx movl %eax, bestlen(%esp) movl %ecx, dsMatchStart(%edx) cmpl %ebx, %eax jge LeaveNow movl window(%esp), %esi addl %eax, %esi movl %esi, windowbestlen(%esp) movzwl -1(%edi,%eax), %ebx movl dsPrev(%edx), %edi movl %ebx, scanend(%esp) movl chainlenwmask(%esp), %edx jmp LookupLoop /* Accept the current string, with the maximum possible length. */ LenMaximum: movl deflatestate(%esp), %edx movl $MAX_MATCH, bestlen(%esp) movl %ecx, dsMatchStart(%edx) /* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */ /* return s->lookahead; */ LeaveNow: movl deflatestate(%esp), %edx movl bestlen(%esp), %ebx movl dsLookahead(%edx), %eax cmpl %eax, %ebx jg LookaheadRet movl %ebx, %eax LookaheadRet: /* Restore the stack and return from whence we came. */ addl $LocalVarsSize, %esp popl %ebx popl %esi popl %edi popl %ebp match_init: ret libreswan-3.32/linux/net/ipsec/pfkey_v2.c000066400000000000000000001077561365625662500204100ustar00rootroot00000000000000/* * @(#) RFC2367 PF_KEYv2 Key management API domain socket I/F * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs. * Copyright (C) 2010-12 David McCullough * Copyright (C) 2013 David McCullough * Copyright (C) 2012-2013 Paul Wouters * Copyright (C) 2015 Greg Ungerer * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ /* * Template from /usr/src/linux-2.0.36/net/unix/af_unix.c. * Hints from /usr/src/linux-2.0.36/net/ipv4/udp.c. */ #define __NO_VERSION__ #include #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38) && \ !defined(AUTOCONF_INCLUDED) # include #endif #include #include "libreswan/ipsec_param.h" #include #include #include /* old location of send_sig() ? */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) # include /* new location of send_sig() */ #endif #include #include #include #include #include #include #include #include #include #include /* struct socket */ #include #include #include /* kmalloc() */ #ifdef CONFIG_X86 # include #endif #include #include #include /* struct sock */ #include /* #include */ #include #ifdef CONFIG_PROC_FS # include #endif /* CONFIG_PROC_FS */ #ifdef HAVE_SEQ_FILE # include #endif #include #include "libreswan/ipsec_param2.h" #include #include "libreswan/radij.h" #include "libreswan/ipsec_encap.h" #include "libreswan/ipsec_sa.h" #include #include #include "libreswan/ipsec_proto.h" #include "libreswan/ipsec_kversion.h" #include "libreswan/ipsec_sysctl.h" #define SENDERR(_x) do { error = -(_x); goto errlab; } while (0) #ifndef SOCKOPS_WRAPPED #define SOCKOPS_WRAPPED(name) name #endif /* SOCKOPS_WRAPPED */ #ifndef SOCKOPS_WRAP #define SOCKOPS_WRAP(name, fam) #endif /* SOCKOPS_WRAP */ extern struct proto_ops SOCKOPS_WRAPPED(pfkey_ops); #ifdef NET_26 static DEFINE_RWLOCK(pfkey_sock_lock); static HLIST_HEAD(pfkey_sock_list); static DECLARE_WAIT_QUEUE_HEAD(pfkey_sock_wait); static atomic_t pfkey_sock_users = ATOMIC_INIT(0); #else static struct sock *pfkey_sock_list = NULL; #endif struct supported_list *pfkey_supported_list[K_SADB_SATYPE_MAX + 1]; struct socket_list *pfkey_open_sockets = NULL; struct socket_list *pfkey_registered_sockets[K_SADB_SATYPE_MAX + 1]; int pfkey_msg_interp(struct sock *, struct sadb_msg *); #if defined(NET_26_24_SKALLOC) || defined(NET_44_SKALLOC) #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38) DEBUG_NO_STATIC int pfkey_create(struct net *net, struct socket *sock, int protocol, int kern); #else DEBUG_NO_STATIC int pfkey_create(struct net *net, struct socket *sock, int protocol); #endif #else DEBUG_NO_STATIC int pfkey_create(struct socket *sock, int protocol); #endif DEBUG_NO_STATIC int pfkey_shutdown(struct socket *sock, int mode); DEBUG_NO_STATIC int pfkey_release(struct socket *sock); #ifdef NET_26 # if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) DEBUG_NO_STATIC int pfkey_sendmsg(struct socket *sock, struct msghdr *msg, size_t len); DEBUG_NO_STATIC int pfkey_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, int flags); # else DEBUG_NO_STATIC int pfkey_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len); DEBUG_NO_STATIC int pfkey_recvmsg(struct kiocb *kiocb, struct socket *sock, struct msghdr *msg, size_t size, int flags); # endif #else DEBUG_NO_STATIC int pfkey_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm); DEBUG_NO_STATIC int pfkey_recvmsg(struct socket *sock, struct msghdr *msg, int size, int flags, struct scm_cookie *scm); #endif static struct net_proto_family pfkey_family_ops = { #ifdef NET_26 .owner = THIS_MODULE, #endif .family = PF_KEY, .create = pfkey_create }; struct proto_ops SOCKOPS_WRAPPED(pfkey_ops) = { #ifdef NET_26 owner: THIS_MODULE, #endif family: PF_KEY, release: pfkey_release, bind: sock_no_bind, connect: sock_no_connect, socketpair: sock_no_socketpair, accept: sock_no_accept, getname: sock_no_getname, poll: datagram_poll, ioctl: sock_no_ioctl, listen: sock_no_listen, shutdown: pfkey_shutdown, setsockopt: sock_no_setsockopt, getsockopt: sock_no_getsockopt, sendmsg: pfkey_sendmsg, recvmsg: pfkey_recvmsg, mmap: sock_no_mmap, }; #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39) #include #endif SOCKOPS_WRAP(pfkey, PF_KEY); #ifdef NET_26 static void pfkey_sock_list_grab(void) { write_lock_bh(&pfkey_sock_lock); if (atomic_read(&pfkey_sock_users)) { DECLARE_WAITQUEUE(wait, current); add_wait_queue_exclusive(&pfkey_sock_wait, &wait); for (;; ) { set_current_state(TASK_UNINTERRUPTIBLE); if (atomic_read(&pfkey_sock_users) == 0) break; write_unlock_bh(&pfkey_sock_lock); schedule(); write_lock_bh(&pfkey_sock_lock); } __set_current_state(TASK_RUNNING); remove_wait_queue(&pfkey_sock_wait, &wait); } } static __inline__ void pfkey_sock_list_ungrab(void) { write_unlock_bh(&pfkey_sock_lock); wake_up(&pfkey_sock_wait); } static __inline__ void pfkey_lock_sock_list(void) { /* read_lock() synchronizes us to pfkey_table_grab */ read_lock(&pfkey_sock_lock); atomic_inc(&pfkey_sock_users); read_unlock(&pfkey_sock_lock); } static __inline__ void pfkey_unlock_sock_list(void) { if (atomic_dec_and_test(&pfkey_sock_users)) wake_up(&pfkey_sock_wait); } #endif static int pfkey_list_remove_socket(struct socket *socketp, struct socket_list **sockets) { struct socket_list *socket_listp, *prev; if (!socketp) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_list_remove_socket: " "NULL socketp handed in, failed.\n"); return -EINVAL; } if (!sockets) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_list_remove_socket: " "NULL sockets list handed in, failed.\n"); return -EINVAL; } socket_listp = *sockets; prev = NULL; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_list_remove_socket: " "removing sock=0p%p\n", socketp); while (socket_listp != NULL) { if (socket_listp->socketp == socketp) { if (prev != NULL) prev->next = socket_listp->next; else *sockets = socket_listp->next; kfree((void*)socket_listp); break; } prev = socket_listp; socket_listp = socket_listp->next; } return 0; } int pfkey_list_insert_socket(struct socket *socketp, struct socket_list **sockets) { struct socket_list *socket_listp; if (!socketp) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_list_insert_socket: " "NULL socketp handed in, failed.\n"); return -EINVAL; } if (!sockets) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_list_insert_socket: " "NULL sockets list handed in, failed.\n"); return -EINVAL; } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_list_insert_socket: " "allocating %zu bytes for socketp=0p%p\n", sizeof(struct socket_list), socketp); if ((socket_listp = (struct socket_list *) kmalloc(sizeof(struct socket_list), GFP_KERNEL)) == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_list_insert_socket: " "memory allocation error.\n"); return -ENOMEM; } socket_listp->socketp = socketp; socket_listp->next = *sockets; *sockets = socket_listp; return 0; } int pfkey_list_remove_supported(struct ipsec_alg_supported *supported, struct supported_list **supported_list) { struct supported_list *supported_listp = *supported_list, *prev = NULL; if (!supported) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_list_remove_supported: " "NULL supported handed in, failed.\n"); return -EINVAL; } if (!supported_list) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_list_remove_supported: " "NULL supported_list handed in, failed.\n"); return -EINVAL; } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_list_remove_supported: " "removing supported=0p%p\n", supported); while (supported_listp != NULL) { if (supported_listp->supportedp == supported) { if (prev != NULL) prev->next = supported_listp->next; else *supported_list = supported_listp->next; kfree((void*)supported_listp); break; } prev = supported_listp; supported_listp = supported_listp->next; } return 0; } int pfkey_list_insert_supported(struct ipsec_alg_supported *supported, struct supported_list **supported_list) { struct supported_list *supported_listp; if (!supported) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_list_insert_supported: " "NULL supported handed in, failed.\n"); return -EINVAL; } if (!supported_list) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_list_insert_supported: " "NULL supported_list handed in, failed.\n"); return -EINVAL; } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_list_insert_supported: " "allocating %zu bytes for incoming, supported=0p%p, supported_list=0p%p\n", sizeof(struct supported_list), supported, supported_list); supported_listp = (struct supported_list *) kmalloc(sizeof(struct supported_list), GFP_KERNEL); if (supported_listp == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_list_insert_supported: " "memory allocation error.\n"); return -ENOMEM; } supported_listp->supportedp = supported; supported_listp->next = *supported_list; *supported_list = supported_listp; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_list_insert_supported: " "outgoing, supported=0p%p, supported_list=0p%p\n", supported, supported_list); return 0; } #ifdef NET_26 DEBUG_NO_STATIC void pfkey_insert_socket(struct sock *sk) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_insert_socket: " "sk=0p%p\n", sk); pfkey_sock_list_grab(); sk_add_node(sk, &pfkey_sock_list); pfkey_sock_list_ungrab(); } DEBUG_NO_STATIC void pfkey_remove_socket(struct sock *sk) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_remove_socket: 0p%p\n", sk); pfkey_sock_list_grab(); sk_del_node_init(sk); pfkey_sock_list_ungrab(); } #else DEBUG_NO_STATIC void pfkey_insert_socket(struct sock *sk) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_insert_socket: " "sk=0p%p\n", sk); cli(); sk->next = pfkey_sock_list; pfkey_sock_list = sk; sti(); } DEBUG_NO_STATIC void pfkey_remove_socket(struct sock *sk) { struct sock **s; s = NULL; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_remove_socket: .\n"); cli(); s = &pfkey_sock_list; while (*s != NULL) { if (*s == sk) { *s = sk->next; sk->next = NULL; sti(); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_remove_socket: " "succeeded.\n"); return; } s = &((*s)->next); } sti(); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_remove_socket: " "not found.\n"); } #endif DEBUG_NO_STATIC void pfkey_destroy_socket(struct sock *sk) { struct sk_buff *skb; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_destroy_socket: 0p%p\n", sk); pfkey_remove_socket(sk); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_destroy_socket: " "pfkey_remove_socket called, sk=0p%p\n", sk); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_destroy_socket: " "sk(0p%p)->(&0p%p)receive_queue.{next=0p%p,prev=0p%p}.\n", sk, &(sk->sk_receive_queue), sk->sk_receive_queue.next, sk->sk_receive_queue.prev); while (sk && ((skb = skb_dequeue(&(sk->sk_receive_queue))) != NULL)) { if (debug_pfkey && sysctl_ipsec_debug_verbose) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_destroy_socket: " "skb=0p%p dequeued.\n", skb); printk(KERN_INFO "klips_debug:pfkey_destroy_socket: " "pfkey_skb contents:"); printk(" next:0p%p", skb->next); printk(" prev:0p%p", skb->prev); printk(" sk:0p%p", skb->sk); printk(" dev:0p%p", skb->dev); if (skb->dev) { if (skb->dev->name) printk(" dev->name:%s", skb->dev->name); else printk(" dev->name:NULL?"); } else { printk(" dev:NULL"); } printk(" h:0p%p", skb_transport_header(skb)); printk(" nh:0p%p", skb_network_header(skb)); printk(" mac:0p%p", skb_mac_header(skb)); printk(" dst:0p%p", skb_dst(skb)); if (sysctl_ipsec_debug_verbose) { int i; printk(" cb"); for (i = 0; i < 48; i++) printk(":%2x", skb->cb[i]); } printk(" len:%d", skb->len); printk(" csum:%d", skb->csum); printk(" cloned:%d", skb->cloned); printk(" pkt_type:%d", skb->pkt_type); printk(" ip_summed:%d", skb->ip_summed); printk(" priority:%d", skb->priority); printk(" protocol:%d", skb->protocol); #ifdef HAVE_SOCK_SECURITY printk(" security:%d", skb->security); #endif printk(" truesize:%d", skb->truesize); printk(" head:0p%p", skb->head); printk(" data:0p%p", skb->data); printk(" tail:0p%p", skb_tail_pointer(skb)); printk(" end:0p%p", skb_end_pointer(skb)); if (sysctl_ipsec_debug_verbose) { unsigned char* i; printk(" data"); for (i = skb->head; i < skb_end_pointer(skb); i++) printk(":%2x", (unsigned char)(*(i))); } printk(" destructor:0p%p", skb->destructor); printk("\n"); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_destroy_socket: " "skb=0p%p freed.\n", skb); ipsec_kfree_skb(skb); } #ifdef NET_26 sock_set_flag(sk, SOCK_DEAD); #else sk->dead = 1; #endif sk_free(sk); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_destroy_socket: destroyed.\n"); } #ifdef HAVE_USER_NS uint32_t pfkey_kuid_to_uid(kuid_t kuid) { return from_kuid(&init_user_ns, kuid); } #endif int pfkey_upmsg(struct socket *sock, struct sadb_msg *pfkey_msg) { struct sock *sk; if (sock == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_upmsg: " "NULL socket passed in.\n"); return -EINVAL; } if (pfkey_msg == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_upmsg: " "NULL pfkey_msg passed in.\n"); return -EINVAL; } sk = sock->sk; return pfkey_upmsgsk(sk, pfkey_msg); } int pfkey_upmsgsk(struct sock *sk, struct sadb_msg *pfkey_msg) { int error = 0; struct sk_buff * skb = NULL; if (sk == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_upmsg: " "NULL sock passed in.\n"); return -EINVAL; } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_upmsg: " "allocating %d bytes...\n", (int)(pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN)); if (!(skb = alloc_skb(pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN, GFP_ATOMIC) )) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_upmsg: " "no buffers left to send up a message.\n"); return -ENOBUFS; } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_upmsg: " "...allocated at 0p%p.\n", skb); skb->dev = NULL; if (skb_tailroom(skb) < pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN) { printk(KERN_WARNING "klips_error:pfkey_upmsg: " "tried to skb_put %ld, %d available. This should never happen, please report.\n", (unsigned long int)pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN, skb_tailroom(skb)); ipsec_kfree_skb(skb); return -ENOBUFS; } skb_set_transport_header(skb, ipsec_skb_offset(skb, skb_put(skb, pfkey_msg-> sadb_msg_len * IPSEC_PFKEYv2_ALIGN))); memcpy(skb_transport_header(skb), pfkey_msg, pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN); if ((error = sock_queue_rcv_skb(sk, skb)) < 0) { skb->sk = NULL; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_upmsg: " "error=%d calling sock_queue_rcv_skb with skb=0p%p.\n", error, skb); ipsec_kfree_skb(skb); return error; } return error; } #if defined(NET_26_12_SKALLOC) || defined(NET_26_24_SKALLOC) || defined(NET_44_SKALLOC) static struct proto key_proto = { .name = "KEY", .owner = THIS_MODULE, .obj_size = sizeof(struct sock), }; #endif #if defined(NET_26_24_SKALLOC) || defined(NET_44_SKALLOC) DEBUG_NO_STATIC int pfkey_create(struct net *net, struct socket *sock, int protocol #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, \ 38) , int kern #endif ) #else DEBUG_NO_STATIC int pfkey_create(struct socket *sock, int protocol) #endif { struct sock *sk; if (sock == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_create: " "socket NULL.\n"); return -EINVAL; } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_create: " "sock=0p%p type:%d state:%d flags:%ld protocol:%d\n", sock, sock->type, (unsigned int)(sock->state), sock->flags, protocol); if (sock->type != SOCK_RAW) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_create: " "only SOCK_RAW supported.\n"); return -ESOCKTNOSUPPORT; } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38) if (!kern && !capable(CAP_NET_RAW)) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_create: " "no permissions.\n"); return -EPERM; } #endif if (protocol != PF_KEY_V2) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_create: " "protocol not PF_KEY_V2.\n"); return -EPROTONOSUPPORT; } if (!capable(CAP_NET_ADMIN)) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_create: " "must be root (or have net_admin capability) to open pfkey sockets.\n"); return -EACCES; } sock->state = SS_UNCONNECTED; KLIPS_INC_USE; #ifdef NET_26 #ifdef NET_44_SKALLOC sk = (struct sock *)sk_alloc(net, PF_KEY, GFP_KERNEL, &key_proto, 0); #else #ifdef NET_26_24_SKALLOC sk = (struct sock *)sk_alloc(net, PF_KEY, GFP_KERNEL, &key_proto); #else #ifdef NET_26_12_SKALLOC sk = (struct sock *)sk_alloc(PF_KEY, GFP_KERNEL, &key_proto, 1); #else sk = (struct sock *)sk_alloc(PF_KEY, GFP_KERNEL, 1, NULL); #endif #endif #endif #else /* 2.4 interface */ sk = (struct sock *)sk_alloc(PF_KEY, GFP_KERNEL, 1); #endif if (sk == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_create: " "Out of memory trying to allocate.\n"); KLIPS_DEC_USE; return -ENOMEM; } sock_init_data(sock, sk); sk->sk_destruct = NULL; sk->sk_reuse = 1; sock->ops = &SOCKOPS_WRAPPED(pfkey_ops); sk->sk_family = PF_KEY; /* sk->num = protocol; */ sk->sk_protocol = protocol; #ifdef HAVE_USER_NS key_pid(sk) = pfkey_kuid_to_uid(current_uid()); #else key_pid(sk) = current_uid(); #endif #ifdef HAVE_SOCKET_WQ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_create: " "sock->wq->fasync_list=0p%p sk_sleep(sk)=0p%p.\n", sock->wq->fasync_list, sk_sleep(sk)); #else KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_create: " "sock->fasync_list=0p%p sk->sleep=0p%p.\n", sock->fasync_list, sk->sk_sleep); #endif pfkey_insert_socket(sk); pfkey_list_insert_socket(sock, &pfkey_open_sockets); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_create: " "Socket sock=0p%p sk=0p%p initialised.\n", sock, sk); return 0; } DEBUG_NO_STATIC int pfkey_release(struct socket *sock) { struct sock *sk; int i; if (sock == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_release: " "No socket attached.\n"); return 0; /* -EINVAL; */ } sk = sock->sk; /* May not have data attached */ if (sk == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_release: " "No sk attached to sock=0p%p.\n", sock); return 0; /* -EINVAL; */ } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_release: " "sock=0p%p sk=0p%p\n", sock, sk); if (sock_flag(sk, SOCK_DEAD)) { if (sk->sk_state_change) sk->sk_state_change(sk); } sock->sk = NULL; /* Try to flush out this socket. Throw out buffers at least */ pfkey_destroy_socket(sk); pfkey_list_remove_socket(sock, &pfkey_open_sockets); for (i = K_SADB_SATYPE_UNSPEC; i <= K_SADB_SATYPE_MAX; i++) pfkey_list_remove_socket(sock, &(pfkey_registered_sockets[i])); KLIPS_DEC_USE; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_release: " "succeeded.\n"); return 0; } DEBUG_NO_STATIC int pfkey_shutdown(struct socket *sock, int mode) { struct sock *sk; if (sock == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_shutdown: " "NULL socket passed in.\n"); return -EINVAL; } sk = sock->sk; if (sk == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_shutdown: " "No sock attached to socket.\n"); return -EINVAL; } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_shutdown: " "mode=%x.\n", mode); mode++; if (mode & SEND_SHUTDOWN) { sk->sk_shutdown |= SEND_SHUTDOWN; sk->sk_state_change(sk); } if (mode & RCV_SHUTDOWN) { sk->sk_shutdown |= RCV_SHUTDOWN; sk->sk_state_change(sk); } return 0; } /* * Send PF_KEY data down. */ DEBUG_NO_STATIC int #ifdef NET_26 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) pfkey_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) #else pfkey_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len) #endif #else pfkey_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm) #endif { struct sock *sk; int error = 0; struct sadb_msg *pfkey_msg = NULL, *pfkey_reply = NULL; if (sock == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: " "Null socket passed in.\n"); SENDERR(EINVAL); } sk = sock->sk; if (sk == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: " "Null sock passed in.\n"); SENDERR(EINVAL); } if (msg == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: " "Null msghdr passed in.\n"); SENDERR(EINVAL); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: .\n"); if (sk->sk_err) { error = sock_error(sk); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: " "sk->err is non-zero, returns %d.\n", error); SENDERR(-error); } if (!capable(CAP_NET_ADMIN)) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: " "must be root (or have net_admin capability) to send messages to pfkey sockets.\n"); SENDERR(EACCES); } if (msg->msg_control) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: " "can't set flags or set msg_control.\n"); SENDERR(EINVAL); } if (sk->sk_shutdown & SEND_SHUTDOWN) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: " "shutdown.\n"); send_sig(SIGPIPE, current, 0); SENDERR(EPIPE); } if (len < sizeof(struct sadb_msg)) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: " "bogus msg len of %d, too small.\n", (int)len); SENDERR(EMSGSIZE); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: " "allocating %d bytes for downward message.\n", (int)len); if ((pfkey_msg = (struct sadb_msg*)kmalloc(len, GFP_KERNEL)) == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: " "memory allocation error.\n"); SENDERR(ENOBUFS); } memcpy_from_msg((void *)pfkey_msg, msg, len); if (pfkey_msg->sadb_msg_version != PF_KEY_V2) { KLIPS_PRINT(1 || debug_pfkey, "klips_debug:pfkey_sendmsg: " "not PF_KEY_V2 msg, found %d, should be %d.\n", pfkey_msg->sadb_msg_version, PF_KEY_V2); kfree((void*)pfkey_msg); return -EINVAL; } if (len != pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: " "bogus msg len of %d, not %d byte aligned.\n", (int)len, (int)IPSEC_PFKEYv2_ALIGN); SENDERR(EMSGSIZE); } if (pfkey_msg->sadb_msg_reserved) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: " "reserved field must be zero, set to %d.\n", pfkey_msg->sadb_msg_reserved); SENDERR(EINVAL); } if ((pfkey_msg->sadb_msg_type > K_SADB_MAX) || (!pfkey_msg->sadb_msg_type)) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: " "msg type too large or small:%d.\n", pfkey_msg->sadb_msg_type); SENDERR(EINVAL); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: " "msg sent for parsing.\n"); if ((error = pfkey_msg_interp(sk, pfkey_msg))) { struct socket_list *pfkey_socketsp; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: " "pfkey_msg_parse returns %d.\n", error); if ((pfkey_reply = (struct sadb_msg*) kmalloc(sizeof(struct sadb_msg), GFP_KERNEL)) == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: " "memory allocation error.\n"); SENDERR(ENOBUFS); } memcpy((void*)pfkey_reply, (void*)pfkey_msg, sizeof(struct sadb_msg)); pfkey_reply->sadb_msg_errno = -error; pfkey_reply->sadb_msg_len = sizeof(struct sadb_msg) / IPSEC_PFKEYv2_ALIGN; for (pfkey_socketsp = pfkey_open_sockets; pfkey_socketsp; pfkey_socketsp = pfkey_socketsp->next) { int error_upmsg = 0; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: " "sending up error=%d message=0p%p to socket=0p%p.\n", error, pfkey_reply, pfkey_socketsp->socketp); if ((error_upmsg = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: " "sending up error message to socket=0p%p failed with error=%d.\n", pfkey_socketsp->socketp, error_upmsg); /* pfkey_msg_free(&pfkey_reply); */ /* SENDERR(-error); */ } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: " "sending up error message to socket=0p%p succeeded.\n", pfkey_socketsp->socketp); } pfkey_msg_free(&pfkey_reply); SENDERR(-error); } errlab: if (pfkey_msg) kfree((void*)pfkey_msg); if (error) return error; else return len; } /* * Receive PF_KEY data up. */ DEBUG_NO_STATIC int #ifdef NET_26 # if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) pfkey_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, int flags) # else pfkey_recvmsg(struct kiocb *kiocb, struct socket *sock, struct msghdr *msg, size_t size, int flags) # endif #else pfkey_recvmsg(struct socket *sock, struct msghdr *msg, int size, int flags, struct scm_cookie *scm) #endif { struct sock *sk; int noblock = flags & MSG_DONTWAIT; struct sk_buff *skb; int error; if (sock == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_recvmsg: " "Null socket passed in.\n"); return -EINVAL; } sk = sock->sk; if (sk == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_recvmsg: " "Null sock passed in for sock=0p%p.\n", sock); return -EINVAL; } if (msg == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_recvmsg: " "Null msghdr passed in for sock=0p%p, sk=0p%p.\n", sock, sk); return -EINVAL; } KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "klips_debug:pfkey_recvmsg: sock=0p%p sk=0p%p msg=0p%p size=%d.\n", sock, sk, msg, (int)size); if (flags & ~MSG_PEEK) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: " "flags (%d) other than MSG_PEEK not supported.\n", flags); return -EOPNOTSUPP; } msg->msg_namelen = 0; /* sizeof(*ska); */ if (sk->sk_err) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: " "sk->sk_err=%d.\n", sk->sk_err); return sock_error(sk); } if ((skb = skb_recv_datagram(sk, flags, noblock, &error) ) == NULL) return error; if (size > skb->len) size = skb->len; else if (size < skb->len) msg->msg_flags |= MSG_TRUNC; skb_copy_datagram_msg(skb, 0, msg, size); #ifdef HAVE_KERNEL_TSTAMP sk->sk_stamp = skb->tstamp; #elif defined(HAVE_TSTAMP) sk->sk_stamp.tv_sec = skb->tstamp.off_sec; sk->sk_stamp.tv_usec = skb->tstamp.off_usec; #else sk->sk_stamp = skb->stamp; #endif skb_free_datagram(sk, skb); return size; } #ifdef CONFIG_PROC_FS int pfkey_show(struct seq_file *seq, void *offset) { struct sock *sk; #ifdef SK_FOR_EACH_NEED_NODE struct hlist_node *node; #endif if (!sysctl_ipsec_debug_verbose) { seq_printf(seq, " sock pid socket next prev e n p sndbf Flags Type St\n"); } else { seq_printf(seq, " sock pid d sleep socket next prev e r z n p sndbf stamp Flags Type St\n"); } SK_FOR_EACH(sk, &pfkey_sock_list) { if (!sysctl_ipsec_debug_verbose) { seq_printf(seq, "%8p %5d %8p %d %d %5d %08lX %8X %2X\n", sk, key_pid(sk), sk->sk_socket, sk->sk_err, sk->sk_protocol, sk->sk_sndbuf, sk->sk_socket->flags, sk->sk_socket->type, sk->sk_socket->state); } else { struct timeval t; grab_socket_timeval(t, *sk); seq_printf(seq, "%8p %5d %d %8p %8p %d %d %d %d %5d %d.%06d %08lX %8X %2X\n", sk, key_pid(sk), sock_flag(sk, SOCK_DEAD), #ifdef HAVE_SOCKET_WQ sk->sk_wq, #else sk->sk_sleep, #endif sk->sk_socket, sk->sk_err, sk->sk_reuse, #ifdef HAVE_SOCK_ZAPPED sock_flag(sk, SOCK_ZAPPED), #else sk->sk_zapped, #endif sk->sk_protocol, sk->sk_sndbuf, (unsigned int)t.tv_sec, (unsigned int)t.tv_usec, sk->sk_socket->flags, sk->sk_socket->type, sk->sk_socket->state); } } return 0; } int pfkey_supported_show(struct seq_file *seq, void *offset) { int satype; struct supported_list *ps; seq_printf(seq, "satype exttype alg_id ivlen minbits maxbits name\n"); for (satype = K_SADB_SATYPE_UNSPEC; satype <= K_SADB_SATYPE_MAX; satype++) { ps = pfkey_supported_list[satype]; while (ps != NULL) { struct ipsec_alg_supported *alg = ps->supportedp; const char *n = alg->ias_name; if (n == NULL) n = "unknown"; seq_printf(seq, " %2d %2d %2d %3d %3d %3d %20s\n", satype, alg->ias_exttype, alg->ias_id, alg->ias_ivlen, alg->ias_keyminbits, alg->ias_keymaxbits, n); ps = ps->next; } } return 0; } int pfkey_registered_show(struct seq_file *seq, void *offset) { int satype; struct socket_list *pfkey_sockets; seq_printf(seq, "satype socket pid sk\n"); for (satype = K_SADB_SATYPE_UNSPEC; satype <= K_SADB_SATYPE_MAX; satype++) { pfkey_sockets = pfkey_registered_sockets[satype]; while (pfkey_sockets != NULL) { seq_printf(seq, " %2d %8p %5d %8p\n", satype, pfkey_sockets->socketp, key_pid(pfkey_sockets->socketp->sk), pfkey_sockets->socketp->sk); pfkey_sockets = pfkey_sockets->next; } } return 0; } #endif /* CONFIG_PROC_FS */ DEBUG_NO_STATIC int supported_add_all(int satype, struct ipsec_alg_supported supported[], int size) { int i; int error = 0; KLIPS_PRINT(debug_pfkey, "klips_debug:init_pfkey: " "sizeof(supported_init_)[%d]/sizeof(struct ipsec_alg_supported)[%d]=%d.\n", satype, size, (int)sizeof(struct ipsec_alg_supported), (int)(size / sizeof(struct ipsec_alg_supported))); for (i = 0; i < size / sizeof(struct ipsec_alg_supported); i++) { const char *n = supported[i].ias_name; if (n == NULL) n = "unknown"; KLIPS_PRINT(debug_pfkey, "klips_debug:init_pfkey: " "i=%d inserting satype=%d exttype=%d id=%d ivlen=%d minbits=%d maxbits=%d name=%s.\n", i, satype, supported[i].ias_exttype, supported[i].ias_id, supported[i].ias_ivlen, supported[i].ias_keyminbits, supported[i].ias_keymaxbits, n); error |= pfkey_list_insert_supported(&(supported[i]), &(pfkey_supported_list[ satype])); } return error; } DEBUG_NO_STATIC int supported_remove_all(int satype) { int error = 0; struct ipsec_alg_supported *supportedp; while (pfkey_supported_list[satype]) { const char *n; supportedp = pfkey_supported_list[satype]->supportedp; n = supportedp->ias_name; if (n == NULL) n = "unknown"; KLIPS_PRINT(debug_pfkey, "klips_debug:init_pfkey: " "removing satype=%d exttype=%d id=%d ivlen=%d minbits=%d maxbits=%d name=%s.\n", satype, supportedp->ias_exttype, supportedp->ias_id, supportedp->ias_ivlen, supportedp->ias_keyminbits, supportedp->ias_keymaxbits, n); error |= pfkey_list_remove_supported(supportedp, &(pfkey_supported_list[ satype])); } return error; } int pfkey_init(void) { int error = 0; int i; static struct ipsec_alg_supported supported_init_ah[] = { #ifdef CONFIG_KLIPS_AUTH_HMAC_MD5 { K_SADB_EXT_SUPPORTED_AUTH, K_SADB_AALG_MD5HMAC, 0, 128, 128 }, #endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ #ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1 { K_SADB_EXT_SUPPORTED_AUTH, K_SADB_AALG_SHA1HMAC, 0, 160, 160 } #endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */ }; static struct ipsec_alg_supported supported_init_esp[] = { #ifdef CONFIG_KLIPS_AUTH_HMAC_MD5 { K_SADB_EXT_SUPPORTED_AUTH, K_SADB_AALG_MD5HMAC, 0, 128, 128 }, #endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ #ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1 { K_SADB_EXT_SUPPORTED_AUTH, K_SADB_AALG_SHA1HMAC, 0, 160, 160 }, #endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */ #ifdef CONFIG_KLIPS_ENC_3DES { K_SADB_EXT_SUPPORTED_ENCRYPT, K_SADB_EALG_3DESCBC, 64, 168, 168 }, #endif /* CONFIG_KLIPS_ENC_3DES */ }; static struct ipsec_alg_supported supported_init_ipip[] = { { K_SADB_EXT_SUPPORTED_ENCRYPT, K_SADB_X_TALG_IPv4_in_IPv4, 0, 32, 32 } #if defined(CONFIG_KLIPS_IPV6) , { K_SADB_EXT_SUPPORTED_ENCRYPT, K_SADB_X_TALG_IPv6_in_IPv4, 0, 128, 32 }, { K_SADB_EXT_SUPPORTED_ENCRYPT, K_SADB_X_TALG_IPv4_in_IPv6, 0, 32, 128 }, { K_SADB_EXT_SUPPORTED_ENCRYPT, K_SADB_X_TALG_IPv6_in_IPv6, 0, 128, 128 } #endif /* defined(CONFIG_KLIPS_IPV6) */ }; #ifdef CONFIG_KLIPS_IPCOMP static struct ipsec_alg_supported supported_init_ipcomp[] = { { K_SADB_EXT_SUPPORTED_ENCRYPT, SADB_X_CALG_DEFLATE, 0, 1, 1 } }; #endif /* CONFIG_KLIPS_IPCOMP */ #if 0 printk(KERN_INFO "klips_info:pfkey_init: " "libreswan: initialising PF_KEYv2 domain sockets.\n"); #endif for (i = K_SADB_SATYPE_UNSPEC; i <= K_SADB_SATYPE_MAX; i++) { pfkey_registered_sockets[i] = NULL; pfkey_supported_list[i] = NULL; } error |= supported_add_all(K_SADB_SATYPE_AH, supported_init_ah, sizeof(supported_init_ah)); error |= supported_add_all(K_SADB_SATYPE_ESP, supported_init_esp, sizeof(supported_init_esp)); #ifdef CONFIG_KLIPS_IPCOMP error |= supported_add_all(K_SADB_X_SATYPE_COMP, supported_init_ipcomp, sizeof(supported_init_ipcomp)); #endif /* CONFIG_KLIPS_IPCOMP */ error |= supported_add_all(K_SADB_X_SATYPE_IPIP, supported_init_ipip, sizeof(supported_init_ipip)); error |= sock_register(&pfkey_family_ops); return error; } int pfkey_cleanup(void) { int error = 0; printk(KERN_INFO "klips_info:pfkey_cleanup: " "shutting down PF_KEY domain sockets.\n"); #ifdef VOID_SOCK_UNREGISTER sock_unregister(PF_KEY); #else error |= sock_unregister(PF_KEY); #endif error |= supported_remove_all(K_SADB_SATYPE_AH); error |= supported_remove_all(K_SADB_SATYPE_ESP); #ifdef CONFIG_KLIPS_IPCOMP error |= supported_remove_all(K_SADB_X_SATYPE_COMP); #endif /* CONFIG_KLIPS_IPCOMP */ error |= supported_remove_all(K_SADB_X_SATYPE_IPIP); /* other module unloading cleanup happens here */ return error; } #ifdef MODULE #if 0 int init_module(void) { pfkey_init(); return 0; } void cleanup_module(void) { pfkey_cleanup(); } #endif /* 0 */ #else /* MODULE */ struct net_protocol; void pfkey_proto_init(struct net_protocol *pro) { pfkey_init(); } #endif /* MODULE */ libreswan-3.32/linux/net/ipsec/pfkey_v2_build.c000066400000000000000000001136121365625662500215530ustar00rootroot00000000000000/* * RFC2367 PF_KEYv2 Key management API message parser * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs. * Copyright (C) 2012 Paul Wouters * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ /* * Template from klips/net/ipsec/ipsec/ipsec_parser.c. */ /* * Some ugly stuff to allow consistent debugging code for use in the * kernel and in user space */ #if defined(__KERNEL__) && (defined(linux) || defined(__linux__)) # include /* for printk */ # include "libreswan/ipsec_kversion.h" /* for malloc switch */ # include /* kmalloc() */ # include /* error codes */ # include /* size_t */ # include /* mark_bh */ # include /* struct device, and other headers */ # include /* eth_type_trans */ # include /* struct iphdr */ # if defined(CONFIG_KLIPS_IPV6) # include /* struct ipv6hdr */ # endif /* if defined(CONFIG_KLIPS_IPV6) */ # define MALLOC(size) kmalloc(size, GFP_ATOMIC) # define FREE(obj) kfree(obj) # include #else /* __KERNEL__ */ # include # include # include # include # include # include /* memset */ # include #endif /* __KERNEL__ */ #include #include #ifdef __KERNEL__ #include "libreswan/radij.h" /* rd_nodes */ #include "libreswan/ipsec_encap.h" /* sockaddr_encap */ #endif /* __KERNEL__ */ #include "libreswan/ipsec_sa.h" /* IPSEC_SAREF_NULL, IPSEC_SA_REF_TABLE_IDX_WIDTH */ #include "libreswan/pfkey_debug.h" #include "ip_address.h" /* for ADDRTOT_BUF */ #define SENDERR(_x) { error = -(_x); goto errlab; } void pfkey_extensions_init(struct sadb_ext *extensions[K_SADB_EXT_MAX + 1]) { int i; for (i = 0; i != K_SADB_EXT_MAX + 1; i++) extensions[i] = NULL; } void pfkey_extensions_free(struct sadb_ext *extensions[K_SADB_EXT_MAX + 1]) { int i; if (!extensions) return; if (extensions[0]) { DEBUGGING(PF_KEY_DEBUG_BUILD, "%s:Free extension %d (%zu)\n", "pfkey_extensions_free", 0, sizeof(struct sadb_msg)); memset(extensions[0], 0, sizeof(struct sadb_msg)); FREE(extensions[0]); extensions[0] = NULL; } for (i = 1; i != K_SADB_EXT_MAX + 1; i++) { if (extensions[i]) { DEBUGGING(PF_KEY_DEBUG_BUILD, "%s:Free extension %d (%zu)\n", "pfkey_extensions_free", i, extensions[i]->sadb_ext_len * IPSEC_PFKEYv2_ALIGN); memset(extensions[i], 0, extensions[i]->sadb_ext_len * IPSEC_PFKEYv2_ALIGN); FREE(extensions[i]); extensions[i] = NULL; } } } void pfkey_msg_free(struct sadb_msg **pfkey_msg) { if (*pfkey_msg) { memset(*pfkey_msg, 0, (*pfkey_msg)->sadb_msg_len * IPSEC_PFKEYv2_ALIGN); FREE(*pfkey_msg); *pfkey_msg = NULL; } } /* Default extension builders taken from the KLIPS code */ int pfkey_msg_hdr_build(struct sadb_ext **pfkey_ext, uint8_t msg_type, uint8_t satype, uint8_t msg_errno, uint32_t seq, uint32_t pid) { int error = 0; struct sadb_msg *pfkey_msg = (struct sadb_msg *)*pfkey_ext; DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_msg_hdr_build:\n"); DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_msg_hdr_build: " "on_entry &pfkey_ext=0p%p pfkey_ext=0p%p *pfkey_ext=0p%p.\n", &pfkey_ext, pfkey_ext, *pfkey_ext); /* sanity checks... */ if (pfkey_msg) { ERROR("pfkey_msg_hdr_build: " "why is pfkey_msg already pointing to something?\n"); SENDERR(EINVAL); } if (!msg_type) { ERROR("pfkey_msg_hdr_build: " "msg type not set, must be non-zero..\n"); SENDERR(EINVAL); } if (msg_type > K_SADB_MAX) { ERROR("pfkey_msg_hdr_build: " "msg type too large:%d.\n", msg_type); SENDERR(EINVAL); } if (satype > K_SADB_SATYPE_MAX) { ERROR("pfkey_msg_hdr_build: " "satype %d > max %d\n", satype, SADB_SATYPE_MAX); SENDERR(EINVAL); } pfkey_msg = (struct sadb_msg*)MALLOC(sizeof(struct sadb_msg)); *pfkey_ext = (struct sadb_ext*)pfkey_msg; if (pfkey_msg == NULL) { ERROR("pfkey_msg_hdr_build: " "memory allocation failed\n"); SENDERR(ENOMEM); } memset(pfkey_msg, 0, sizeof(struct sadb_msg)); pfkey_msg->sadb_msg_len = sizeof(struct sadb_msg) / IPSEC_PFKEYv2_ALIGN; pfkey_msg->sadb_msg_type = msg_type; pfkey_msg->sadb_msg_satype = satype; pfkey_msg->sadb_msg_version = PF_KEY_V2; pfkey_msg->sadb_msg_errno = msg_errno; pfkey_msg->sadb_msg_reserved = 0; pfkey_msg->sadb_msg_seq = seq; pfkey_msg->sadb_msg_pid = pid; DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_msg_hdr_build: " "on_exit &pfkey_ext=0p%p pfkey_ext=0p%p *pfkey_ext=0p%p.\n", &pfkey_ext, pfkey_ext, *pfkey_ext); errlab: return error; } int pfkey_sa_builds(struct sadb_ext **pfkey_ext, struct sadb_builds sab) { int error = 0; struct k_sadb_sa *pfkey_sa = (struct k_sadb_sa *)*pfkey_ext; DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_sa_build: " "spi=%08x replay=%d sa_state=%d auth=%d encrypt=%d flags=%d\n", ntohl(sab.sa_base.sadb_sa_spi), /* in network order */ sab.sa_base.sadb_sa_replay, sab.sa_base.sadb_sa_state, sab.sa_base.sadb_sa_auth, sab.sa_base.sadb_sa_encrypt, sab.sa_base.sadb_sa_flags); /* sanity checks... */ if (pfkey_sa) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_sa_build: " "why is pfkey_sa already pointing to something?\n"); SENDERR(EINVAL); } if (sab.sa_base.sadb_sa_exttype != SADB_EXT_SA && sab.sa_base.sadb_sa_exttype != K_SADB_X_EXT_SA2) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_sa_build: " "invalid exttype=%d.\n", sab.sa_base.sadb_sa_exttype); SENDERR(EINVAL); } if (sab.sa_base.sadb_sa_replay > 64) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_sa_build: " "replay window size: %d -- must be 0 <= size <= 64\n", sab.sa_base.sadb_sa_replay); SENDERR(EINVAL); } #if K_SADB_AALG_MAX < 255 if (sab.sa_base.sadb_sa_auth > K_SADB_AALG_MAX) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_sa_build: " "auth=%d > K_SADB_AALG_MAX=%d.\n", sab.sa_base.sadb_sa_auth, K_SADB_AALG_MAX); SENDERR(EINVAL); } #endif #if K_SADB_EALG_MAX < 255 if (sab.sa_base.sadb_sa_encrypt > K_SADB_EALG_MAX) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_sa_build: " "encrypt=%d > K_SADB_EALG_MAX=%d.\n", sab.sa_base.sadb_sa_encrypt, K_SADB_EALG_MAX); SENDERR(EINVAL); } #endif if (sab.sa_base.sadb_sa_state > K_SADB_SASTATE_MAX) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_sa_build: " "sa_state=%d exceeds MAX=%d.\n", sab.sa_base.sadb_sa_state, K_SADB_SASTATE_MAX); SENDERR(EINVAL); } if (sab.sa_base.sadb_sa_state == K_SADB_SASTATE_DEAD) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_sa_build: " "sa_state=%d is DEAD=%d is not allowed.\n", sab.sa_base.sadb_sa_state, K_SADB_SASTATE_DEAD); SENDERR(EINVAL); } if (IPSEC_SAREF_NULL != sab.sa_base.sadb_x_sa_ref && sab.sa_base.sadb_x_sa_ref >= (1 << IPSEC_SA_REF_TABLE_IDX_WIDTH)) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_sa_build: " "SAref=%d must be (SAref == IPSEC_SAREF_NULL(%d) || SAref < IPSEC_SA_REF_TABLE_NUM_ENTRIES(%d)).\n", sab.sa_base.sadb_x_sa_ref, IPSEC_SAREF_NULL, IPSEC_SA_REF_TABLE_NUM_ENTRIES); SENDERR(EINVAL); } pfkey_sa = (struct k_sadb_sa*)MALLOC(sizeof(struct k_sadb_sa)); *pfkey_ext = (struct sadb_ext*)pfkey_sa; if (pfkey_sa == NULL) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_sa_build: " "memory allocation failed\n"); SENDERR(ENOMEM); } memset(pfkey_sa, 0, sizeof(struct k_sadb_sa)); *pfkey_sa = sab.sa_base; pfkey_sa->sadb_sa_len = sizeof(*pfkey_sa) / IPSEC_PFKEYv2_ALIGN; errlab: return error; } int pfkey_sa_build(struct sadb_ext **pfkey_ext, uint16_t exttype, uint32_t spi, uint8_t replay_window, uint8_t sa_state, uint8_t auth, uint8_t encrypt, uint32_t flags) { struct sadb_builds sab; memset(&sab, 0, sizeof(sab)); sab.sa_base.sadb_sa_exttype = exttype; sab.sa_base.sadb_sa_spi = spi; sab.sa_base.sadb_sa_replay = replay_window; sab.sa_base.sadb_sa_state = sa_state; sab.sa_base.sadb_sa_auth = auth; sab.sa_base.sadb_sa_encrypt = encrypt; sab.sa_base.sadb_sa_flags = flags; sab.sa_base.sadb_x_sa_ref = IPSEC_SAREF_NULL; return pfkey_sa_builds(pfkey_ext, sab); } int pfkey_lifetime_build(struct sadb_ext ** pfkey_ext, uint16_t exttype, uint32_t allocations, uint64_t bytes, uint64_t addtime, uint64_t usetime, uint32_t packets UNUSED) { int error = 0; struct sadb_lifetime *pfkey_lifetime = (struct sadb_lifetime *)*pfkey_ext; DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_lifetime_build:\n"); /* sanity checks... */ if (pfkey_lifetime) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_lifetime_build: " "why is pfkey_lifetime already pointing to something?\n"); SENDERR(EINVAL); } if (exttype != SADB_EXT_LIFETIME_CURRENT && exttype != SADB_EXT_LIFETIME_HARD && exttype != SADB_EXT_LIFETIME_SOFT) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_lifetime_build: " "invalid exttype=%d.\n", exttype); SENDERR(EINVAL); } pfkey_lifetime = (struct sadb_lifetime*)MALLOC(sizeof(struct sadb_lifetime)); *pfkey_ext = (struct sadb_ext*) pfkey_lifetime; if (pfkey_lifetime == NULL) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_lifetime_build: " "memory allocation failed\n"); SENDERR(ENOMEM); } memset(pfkey_lifetime, 0, sizeof(struct sadb_lifetime)); pfkey_lifetime->sadb_lifetime_len = sizeof(struct sadb_lifetime) / IPSEC_PFKEYv2_ALIGN; pfkey_lifetime->sadb_lifetime_exttype = exttype; pfkey_lifetime->sadb_lifetime_allocations = allocations; pfkey_lifetime->sadb_lifetime_bytes = bytes; pfkey_lifetime->sadb_lifetime_addtime = addtime; pfkey_lifetime->sadb_lifetime_usetime = usetime; #ifdef NOT_YET /* XXX it is defined in struct sadb_lifetime, but not found?? */ pfkey_lifetime->sadb_x_lifetime_packets = packets; #endif errlab: return error; } int pfkey_address_build(struct sadb_ext **pfkey_ext, uint16_t exttype, uint8_t proto, uint8_t prefixlen, struct sockaddr *address) { int error = 0; int saddr_len = 0; int len; char ipaddr_txt[ADDRTOT_BUF + 6 /*extra for port number*/]; struct sadb_address *pfkey_address = (struct sadb_address *)*pfkey_ext; DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_address_build: " "exttype=%d proto=%d prefixlen=%d\n", exttype, proto, prefixlen); /* sanity checks... */ if (pfkey_address) { ERROR("pfkey_address_build: " "why is pfkey_address already pointing to something?\n"); SENDERR(EINVAL); } if (!address) { ERROR("pfkey_address_build: " "address is NULL\n"); SENDERR(EINVAL); } switch (exttype) { case SADB_EXT_ADDRESS_SRC: case SADB_EXT_ADDRESS_DST: case SADB_EXT_ADDRESS_PROXY: case K_SADB_X_EXT_ADDRESS_DST2: case K_SADB_X_EXT_ADDRESS_SRC_FLOW: case K_SADB_X_EXT_ADDRESS_DST_FLOW: case K_SADB_X_EXT_ADDRESS_SRC_MASK: case K_SADB_X_EXT_ADDRESS_DST_MASK: case K_SADB_X_EXT_NAT_T_OA: break; default: ERROR("pfkey_address_build: " "unrecognised ext_type=%d.\n", exttype); SENDERR(EINVAL); } switch (address->sa_family) { case AF_INET: DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_address_build: " "found address family AF_INET.\n"); saddr_len = sizeof(struct sockaddr_in); len = sin_addrtot(address, 0, ipaddr_txt, sizeof(ipaddr_txt)); if (len > 0 && len < (int)sizeof(ipaddr_txt)) { snprintf(&ipaddr_txt[len - 1], sizeof(ipaddr_txt) - len, ":%d", ntohs(((struct sockaddr_in*)address)-> sin_port)); } break; case AF_INET6: DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_address_build: " "found address family AF_INET6.\n"); saddr_len = sizeof(struct sockaddr_in6); /* IPv6 convention with a port is [addr]:port */ len = sin_addrtot(address, 0, &ipaddr_txt[1], sizeof(ipaddr_txt) - 2); if (len > 0) { ipaddr_txt[0] = '['; snprintf(&ipaddr_txt[len], sizeof(ipaddr_txt) - len, "]:%d", ntohs(((struct sockaddr_in6*)address)-> sin6_port)); } break; default: ERROR("pfkey_address_build: " "address->sa_family=%d not supported.\n", address->sa_family); SENDERR(EPFNOSUPPORT); } DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_address_build: " "found address=%s.\n", ipaddr_txt); if (prefixlen != 0) { ERROR("pfkey_address_build: " "address prefixes not supported yet.\n"); SENDERR(EAFNOSUPPORT); /* not supported yet */ } /* allocate some memory for the extension */ pfkey_address = (struct sadb_address*) MALLOC(ALIGN_N(sizeof(struct sadb_address) + saddr_len, IPSEC_PFKEYv2_ALIGN)); *pfkey_ext = (struct sadb_ext*)pfkey_address; if (pfkey_address == NULL ) { ERROR("pfkey_lifetime_build: " "memory allocation failed\n"); SENDERR(ENOMEM); } memset(pfkey_address, 0, ALIGN_N(sizeof(struct sadb_address) + saddr_len, IPSEC_PFKEYv2_ALIGN)); pfkey_address->sadb_address_len = DIVUP( sizeof(struct sadb_address) + saddr_len, IPSEC_PFKEYv2_ALIGN); pfkey_address->sadb_address_exttype = exttype; pfkey_address->sadb_address_proto = proto; pfkey_address->sadb_address_prefixlen = prefixlen; pfkey_address->sadb_address_reserved = 0; memcpy((char*)pfkey_address + sizeof(struct sadb_address), address, saddr_len); #if 0 for (i = 0; i < sizeof(struct sockaddr_in) - offsetof(struct sockaddr_in, sin_zero); i++) pfkey_address_s_ska.sin_zero[i] = 0; #endif DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_address_build: " "successful created len: %d.\n", pfkey_address->sadb_address_len); errlab: return error; } int pfkey_key_build(struct sadb_ext **pfkey_ext, uint16_t exttype, uint16_t key_bits, unsigned char * key) { int error = 0; struct sadb_key *pfkey_key = (struct sadb_key *)*pfkey_ext; DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_key_build:\n"); /* sanity checks... */ if (pfkey_key) { ERROR("pfkey_key_build: " "why is pfkey_key already pointing to something?\n"); SENDERR(EINVAL); } if (!key_bits) { ERROR("pfkey_key_build: " "key_bits is zero, it must be non-zero.\n"); SENDERR(EINVAL); } if ( !((exttype == SADB_EXT_KEY_AUTH) || (exttype == SADB_EXT_KEY_ENCRYPT))) { ERROR("pfkey_key_build: " "unsupported extension type=%d.\n", exttype); SENDERR(EINVAL); } pfkey_key = (struct sadb_key*) MALLOC(sizeof(struct sadb_key) + DIVUP(key_bits, 64) * IPSEC_PFKEYv2_ALIGN); *pfkey_ext = (struct sadb_ext*)pfkey_key; if (pfkey_key == NULL) { ERROR("pfkey_key_build: " "memory allocation failed\n"); SENDERR(ENOMEM); } memset(pfkey_key, 0, sizeof(struct sadb_key) + DIVUP(key_bits, 64) * IPSEC_PFKEYv2_ALIGN); pfkey_key->sadb_key_len = DIVUP( sizeof(struct sadb_key) * IPSEC_PFKEYv2_ALIGN + key_bits, 64); pfkey_key->sadb_key_exttype = exttype; pfkey_key->sadb_key_bits = key_bits; pfkey_key->sadb_key_reserved = 0; memcpy((char*)pfkey_key + sizeof(struct sadb_key), key, DIVUP(key_bits, 8)); errlab: return error; } int pfkey_ident_build(struct sadb_ext **pfkey_ext, uint16_t exttype, uint16_t ident_type, uint64_t ident_id, uint8_t ident_len, char *ident_string) { int error = 0; struct sadb_ident *pfkey_ident = (struct sadb_ident *)*pfkey_ext; int data_len = ident_len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident); DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_ident_build:\n"); /* sanity checks... */ if (pfkey_ident) { ERROR("pfkey_ident_build: " "why is pfkey_ident already pointing to something?\n"); SENDERR(EINVAL); } if ( !((exttype == SADB_EXT_IDENTITY_SRC) || (exttype == SADB_EXT_IDENTITY_DST))) { ERROR("pfkey_ident_build: " "unsupported extension type=%d.\n", exttype); SENDERR(EINVAL); } if (ident_type == SADB_IDENTTYPE_RESERVED) { ERROR("pfkey_ident_build: " "ident_type must be non-zero.\n"); SENDERR(EINVAL); } if (ident_type > SADB_IDENTTYPE_MAX) { ERROR("pfkey_ident_build: " "identtype=%d out of range.\n", ident_type); SENDERR(EINVAL); } if (((ident_type == SADB_IDENTTYPE_PREFIX) || (ident_type == SADB_IDENTTYPE_FQDN)) && !ident_string) { ERROR("pfkey_ident_build: " "string required to allocate size of extension.\n"); SENDERR(EINVAL); } #if 0 if ((ident_type == SADB_IDENTTYPE_USERFQDN) ) { } #endif pfkey_ident = (struct sadb_ident*) MALLOC(ident_len * IPSEC_PFKEYv2_ALIGN); *pfkey_ext = (struct sadb_ext*)pfkey_ident; if (pfkey_ident == NULL) { ERROR("pfkey_ident_build: " "memory allocation failed\n"); SENDERR(ENOMEM); } memset(pfkey_ident, 0, ident_len * IPSEC_PFKEYv2_ALIGN); pfkey_ident->sadb_ident_len = ident_len; pfkey_ident->sadb_ident_exttype = exttype; pfkey_ident->sadb_ident_type = ident_type; pfkey_ident->sadb_ident_reserved = 0; pfkey_ident->sadb_ident_id = ident_id; memcpy((char*)pfkey_ident + sizeof(struct sadb_ident), ident_string, data_len); errlab: return error; } #if 0 /* ??? not yet used or working */ int pfkey_sens_build(struct sadb_ext **pfkey_ext, uint32_t dpd, uint8_t sens_level, uint8_t sens_len, uint64_t *sens_bitmap, uint8_t integ_level, uint8_t integ_len, uint64_t *integ_bitmap) { int error = 0; struct sadb_sens *pfkey_sens = (struct sadb_sens *)*pfkey_ext; int i; uint64_t *bitmap; DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_sens_build:\n"); /* sanity checks... */ if (pfkey_sens != NULL) { ERROR("pfkey_sens_build: " "why is pfkey_sens already pointing to something?\n"); SENDERR(EINVAL); } /* * ??? we've just determined that *pfkey_ext == NULL, why are we dereferencing it? * I guess that this is an insanity check. */ DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_sens_build: " "Sorry, I can't build exttype=%d yet.\n", (*pfkey_ext)->sadb_ext_type); SENDERR(EINVAL); /* don't process these yet */ pfkey_sens = (struct sadb_sens*) MALLOC(sizeof(struct sadb_sens) + (sens_len + integ_len) * sizeof(uint64_t)); *pfkey_ext = (struct sadb_ext*)pfkey_sens; if (pfkey_sens == NULL) { ERROR("pfkey_sens_build: " "memory allocation failed\n"); SENDERR(ENOMEM); } memset(pfkey_sens, 0, sizeof(struct sadb_sens) + (sens_len + integ_len) * sizeof(uint64_t)); pfkey_sens->sadb_sens_len = (sizeof(struct sadb_sens) + (sens_len + integ_len) * sizeof(uint64_t)) / IPSEC_PFKEYv2_ALIGN; pfkey_sens->sadb_sens_exttype = SADB_EXT_SENSITIVITY; pfkey_sens->sadb_sens_dpd = dpd; pfkey_sens->sadb_sens_sens_level = sens_level; pfkey_sens->sadb_sens_sens_len = sens_len; pfkey_sens->sadb_sens_integ_level = integ_level; pfkey_sens->sadb_sens_integ_len = integ_len; pfkey_sens->sadb_sens_reserved = 0; bitmap = (uint64_t*)((char*)pfkey_ext + sizeof(struct sadb_sens)); for (i = 0; i < sens_len; i++) { *bitmap = sens_bitmap[i]; bitmap++; } for (i = 0; i < integ_len; i++) { *bitmap = integ_bitmap[i]; bitmap++; } errlab: return error; } #endif int pfkey_prop_build(struct sadb_ext **pfkey_ext, uint8_t replay, unsigned int comb_num, struct sadb_comb *comb) { int error = 0; int i; struct sadb_prop *pfkey_prop = (struct sadb_prop *)*pfkey_ext; struct sadb_comb *combp; DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_prop_build:\n"); /* sanity checks... */ if (pfkey_prop) { ERROR("pfkey_prop_build: " "why is pfkey_prop already pointing to something?\n"); SENDERR(EINVAL); } pfkey_prop = (struct sadb_prop*) MALLOC(sizeof(struct sadb_prop) + comb_num * sizeof(struct sadb_comb)); *pfkey_ext = (struct sadb_ext*)pfkey_prop; if (pfkey_prop == NULL) { ERROR("pfkey_prop_build: " "memory allocation failed\n"); SENDERR(ENOMEM); } memset(pfkey_prop, 0, sizeof(struct sadb_prop) + comb_num * sizeof(struct sadb_comb)); pfkey_prop->sadb_prop_len = (sizeof(struct sadb_prop) + comb_num * sizeof(struct sadb_comb)) / IPSEC_PFKEYv2_ALIGN; pfkey_prop->sadb_prop_exttype = SADB_EXT_PROPOSAL; pfkey_prop->sadb_prop_replay = replay; for (i = 0; i < 3; i++) pfkey_prop->sadb_prop_reserved[i] = 0; combp = (struct sadb_comb*) ((char*)*pfkey_ext + sizeof(struct sadb_prop)); for (i = 0; i < (int)comb_num; i++) { memcpy(combp, &(comb[i]), sizeof(struct sadb_comb)); combp++; } #if 0 uint8_t sadb_comb_auth; uint8_t sadb_comb_encrypt; uint16_t sadb_comb_flags; uint16_t sadb_comb_auth_minbits; uint16_t sadb_comb_auth_maxbits; uint16_t sadb_comb_encrypt_minbits; uint16_t sadb_comb_encrypt_maxbits; uint32_t sadb_comb_reserved; uint32_t sadb_comb_soft_allocations; uint32_t sadb_comb_hard_allocations; uint64_t sadb_comb_soft_bytes; uint64_t sadb_comb_hard_bytes; uint64_t sadb_comb_soft_addtime; uint64_t sadb_comb_hard_addtime; uint64_t sadb_comb_soft_usetime; uint64_t sadb_comb_hard_usetime; uint32_t sadb_comb_soft_packets; uint32_t sadb_comb_hard_packets; #endif errlab: return error; } int pfkey_supported_build(struct sadb_ext **pfkey_ext, uint16_t exttype, unsigned int alg_num, struct sadb_alg *alg) { int error = 0; unsigned int i; struct sadb_supported *pfkey_supported = (struct sadb_supported *)*pfkey_ext; struct sadb_alg *pfkey_alg; /* sanity checks... */ if (pfkey_supported) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_supported_build: " "why is pfkey_supported already pointing to something?\n"); SENDERR(EINVAL); } if ( !((exttype == SADB_EXT_SUPPORTED_AUTH) || (exttype == SADB_EXT_SUPPORTED_ENCRYPT))) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_supported_build: " "unsupported extension type=%d.\n", exttype); SENDERR(EINVAL); } pfkey_supported = (struct sadb_supported*) MALLOC(sizeof(struct sadb_supported) + alg_num * sizeof(struct sadb_alg)); *pfkey_ext = (struct sadb_ext*)pfkey_supported; if (pfkey_supported == NULL) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_supported_build: " "memory allocation failed\n"); SENDERR(ENOMEM); } memset(pfkey_supported, 0, sizeof(struct sadb_supported) + alg_num * sizeof(struct sadb_alg)); pfkey_supported->sadb_supported_len = (sizeof(struct sadb_supported) + alg_num * sizeof(struct sadb_alg)) / IPSEC_PFKEYv2_ALIGN; pfkey_supported->sadb_supported_exttype = exttype; pfkey_supported->sadb_supported_reserved = 0; pfkey_alg = (struct sadb_alg*) ((char*)pfkey_supported + sizeof(struct sadb_supported)); for (i = 0; i < alg_num; i++) { memcpy(pfkey_alg, &(alg[i]), sizeof(struct sadb_alg)); pfkey_alg->sadb_alg_reserved = 0; pfkey_alg++; } #if 0 DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_supported_build: " "Sorry, I can't build exttype=%d yet.\n", (*pfkey_ext)->sadb_ext_type); SENDERR(EINVAL); /* don't process these yet */ uint8_t sadb_alg_id; uint8_t sadb_alg_ivlen; uint16_t sadb_alg_minbits; uint16_t sadb_alg_maxbits; uint16_t sadb_alg_reserved; #endif errlab: return error; } #if 0 static int pfkey_spirange_build(struct sadb_ext **pfkey_ext, uint16_t exttype UNUSED, uint32_t min, /* in network order */ uint32_t max) /* in network order */ { int error = 0; struct sadb_spirange *pfkey_spirange = (struct sadb_spirange *)*pfkey_ext; /* sanity checks... */ if (pfkey_spirange) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_spirange_build: " "why is pfkey_spirange already pointing to something?\n"); SENDERR(EINVAL); } if (ntohl(max) < ntohl(min)) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_spirange_build: " "minspi=%08x must be < maxspi=%08x.\n", ntohl(min), ntohl(max)); SENDERR(EINVAL); } if (ntohl(min) <= 255) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_spirange_build: " "minspi=%08x must be > 255.\n", ntohl(min)); SENDERR(EEXIST); } pfkey_spirange = (struct sadb_spirange*) MALLOC(sizeof(struct sadb_spirange)); *pfkey_ext = (struct sadb_ext*)pfkey_spirange; if (pfkey_spirange == NULL) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_spirange_build: " "memory allocation failed\n"); SENDERR(ENOMEM); } memset(pfkey_spirange, 0, sizeof(struct sadb_spirange)); pfkey_spirange->sadb_spirange_len = sizeof(struct sadb_spirange) / IPSEC_PFKEYv2_ALIGN; pfkey_spirange->sadb_spirange_exttype = SADB_EXT_SPIRANGE; pfkey_spirange->sadb_spirange_min = min; pfkey_spirange->sadb_spirange_max = max; pfkey_spirange->sadb_spirange_reserved = 0; errlab: return error; } static int pfkey_x_kmprivate_build(struct sadb_ext **pfkey_ext) { int error = 0; struct sadb_x_kmprivate *pfkey_x_kmprivate = (struct sadb_x_kmprivate *)*pfkey_ext; /* sanity checks... */ if (pfkey_x_kmprivate) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_x_kmprivate_build: " "why is pfkey_x_kmprivate already pointing to something?\n"); SENDERR(EINVAL); } pfkey_x_kmprivate->sadb_x_kmprivate_reserved = 0; DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_x_kmprivate_build: " "Sorry, I can't build exttype=%d yet.\n", (*pfkey_ext)->sadb_ext_type); SENDERR(EINVAL); /* don't process these yet */ pfkey_x_kmprivate = (struct sadb_x_kmprivate*) MALLOC(sizeof(struct sadb_x_kmprivate)); *pfkey_ext = (struct sadb_ext*)pfkey_x_kmprivate; if (pfkey_x_kmprivate == NULL) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_x_kmprivate_build: " "memory allocation failed\n"); SENDERR(ENOMEM); } memset(pfkey_x_kmprivate, 0, sizeof(struct sadb_x_kmprivate)); pfkey_x_kmprivate->sadb_x_kmprivate_len = sizeof(struct sadb_x_kmprivate) / IPSEC_PFKEYv2_ALIGN; pfkey_x_kmprivate->sadb_x_kmprivate_exttype = K_SADB_X_EXT_KMPRIVATE; pfkey_x_kmprivate->sadb_x_kmprivate_reserved = 0; errlab: return error; } #endif int pfkey_x_satype_build(struct sadb_ext **pfkey_ext, uint8_t satype) { int error = 0; int i; struct sadb_x_satype *pfkey_x_satype = (struct sadb_x_satype *)*pfkey_ext; DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_x_satype_build:\n"); /* sanity checks... */ if (pfkey_x_satype) { ERROR("pfkey_x_satype_build: " "why is pfkey_x_satype already pointing to something?\n"); SENDERR(EINVAL); } if (!satype) { ERROR("pfkey_x_satype_build: " "SA type not set, must be non-zero.\n"); SENDERR(EINVAL); } if (satype > K_SADB_SATYPE_MAX) { ERROR("pfkey_x_satype_build: " "satype %d > max %d\n", satype, K_SADB_SATYPE_MAX); SENDERR(EINVAL); } pfkey_x_satype = (struct sadb_x_satype*) MALLOC(sizeof(struct sadb_x_satype)); *pfkey_ext = (struct sadb_ext*)pfkey_x_satype; if (pfkey_x_satype == NULL) { ERROR("pfkey_x_satype_build: " "memory allocation failed\n"); SENDERR(ENOMEM); } memset(pfkey_x_satype, 0, sizeof(struct sadb_x_satype)); pfkey_x_satype->sadb_x_satype_len = sizeof(struct sadb_x_satype) / IPSEC_PFKEYv2_ALIGN; pfkey_x_satype->sadb_x_satype_exttype = K_SADB_X_EXT_SATYPE2; pfkey_x_satype->sadb_x_satype_satype = satype; for (i = 0; i < 3; i++) pfkey_x_satype->sadb_x_satype_reserved[i] = 0; errlab: return error; } int pfkey_x_debug_build(struct sadb_ext **pfkey_ext, uint32_t tunnel, uint32_t netlink, uint32_t xform, uint32_t eroute, uint32_t spi, uint32_t radij, uint32_t esp, uint32_t ah, uint32_t rcv, uint32_t pfkey, uint32_t ipcomp, uint32_t verbose) { int error = 0; int i; struct sadb_x_debug *pfkey_x_debug = (struct sadb_x_debug *)*pfkey_ext; DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_x_debug_build:\n"); /* sanity checks... */ if (pfkey_x_debug) { ERROR("pfkey_x_debug_build: " "why is pfkey_x_debug already pointing to something?\n"); SENDERR(EINVAL); } DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_x_debug_build: " "tunnel=%x netlink=%x xform=%x eroute=%x spi=%x radij=%x esp=%x ah=%x rcv=%x pfkey=%x ipcomp=%x verbose=%x?\n", tunnel, netlink, xform, eroute, spi, radij, esp, ah, rcv, pfkey, ipcomp, verbose); pfkey_x_debug = (struct sadb_x_debug*) MALLOC(sizeof(struct sadb_x_debug)); *pfkey_ext = (struct sadb_ext*)pfkey_x_debug; if (pfkey_x_debug == NULL) { ERROR("pfkey_x_debug_build: " "memory allocation failed\n"); SENDERR(ENOMEM); } #if 0 memset(pfkey_x_debug, 0, sizeof(struct sadb_x_debug)); #endif pfkey_x_debug->sadb_x_debug_len = sizeof(struct sadb_x_debug) / IPSEC_PFKEYv2_ALIGN; pfkey_x_debug->sadb_x_debug_exttype = K_SADB_X_EXT_DEBUG; pfkey_x_debug->sadb_x_debug_tunnel = tunnel; pfkey_x_debug->sadb_x_debug_netlink = netlink; pfkey_x_debug->sadb_x_debug_xform = xform; pfkey_x_debug->sadb_x_debug_eroute = eroute; pfkey_x_debug->sadb_x_debug_spi = spi; pfkey_x_debug->sadb_x_debug_radij = radij; pfkey_x_debug->sadb_x_debug_esp = esp; pfkey_x_debug->sadb_x_debug_ah = ah; pfkey_x_debug->sadb_x_debug_rcv = rcv; pfkey_x_debug->sadb_x_debug_pfkey = pfkey; pfkey_x_debug->sadb_x_debug_ipcomp = ipcomp; pfkey_x_debug->sadb_x_debug_verbose = verbose; for (i = 0; i < 4; i++) pfkey_x_debug->sadb_x_debug_reserved[i] = 0; errlab: return error; } int pfkey_x_nat_t_type_build(struct sadb_ext **pfkey_ext, uint8_t type) { int error = 0; int i; struct sadb_x_nat_t_type *pfkey_x_nat_t_type = (struct sadb_x_nat_t_type *)*pfkey_ext; DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_x_nat_t_type_build:\n"); /* sanity checks... */ if (pfkey_x_nat_t_type) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_x_nat_t_type_build: " "why is pfkey_x_nat_t_type already pointing to something?\n"); SENDERR(EINVAL); } DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_x_nat_t_type_build: " "type=%d\n", type); pfkey_x_nat_t_type = (struct sadb_x_nat_t_type*) MALLOC(sizeof(struct sadb_x_nat_t_type)); *pfkey_ext = (struct sadb_ext*)pfkey_x_nat_t_type; if (pfkey_x_nat_t_type == NULL) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_x_nat_t_type_build: " "memory allocation failed\n"); SENDERR(ENOMEM); } pfkey_x_nat_t_type->sadb_x_nat_t_type_len = sizeof(struct sadb_x_nat_t_type) / IPSEC_PFKEYv2_ALIGN; pfkey_x_nat_t_type->sadb_x_nat_t_type_exttype = K_SADB_X_EXT_NAT_T_TYPE; pfkey_x_nat_t_type->sadb_x_nat_t_type_type = type; for (i = 0; i < 3; i++) pfkey_x_nat_t_type->sadb_x_nat_t_type_reserved[i] = 0; errlab: return error; } int pfkey_x_nat_t_port_build(struct sadb_ext **pfkey_ext, uint16_t exttype, uint16_t port) { int error = 0; struct sadb_x_nat_t_port *pfkey_x_nat_t_port = (struct sadb_x_nat_t_port *)*pfkey_ext; DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_x_nat_t_port_build:\n"); /* sanity checks... */ if (pfkey_x_nat_t_port) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_x_nat_t_port_build: " "why is pfkey_x_nat_t_port already pointing to something?\n"); SENDERR(EINVAL); } switch (exttype) { case K_SADB_X_EXT_NAT_T_SPORT: case K_SADB_X_EXT_NAT_T_DPORT: break; default: DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_nat_t_port_build: " "unrecognised ext_type=%d.\n", exttype); SENDERR(EINVAL); } DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_x_nat_t_port_build: " "ext=%d, port=%d\n", exttype, port); pfkey_x_nat_t_port = (struct sadb_x_nat_t_port*) MALLOC(sizeof(struct sadb_x_nat_t_port)); *pfkey_ext = (struct sadb_ext*)pfkey_x_nat_t_port; if (pfkey_x_nat_t_port == NULL) { DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_x_nat_t_port_build: " "memory allocation failed\n"); SENDERR(ENOMEM); } pfkey_x_nat_t_port->sadb_x_nat_t_port_len = sizeof(struct sadb_x_nat_t_port) / IPSEC_PFKEYv2_ALIGN; pfkey_x_nat_t_port->sadb_x_nat_t_port_exttype = exttype; pfkey_x_nat_t_port->sadb_x_nat_t_port_port = port; pfkey_x_nat_t_port->sadb_x_nat_t_port_reserved = 0; errlab: return error; } int pfkey_x_protocol_build(struct sadb_ext **pfkey_ext, uint8_t protocol) { int error = 0; struct sadb_protocol * p = (struct sadb_protocol *)*pfkey_ext; DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_x_protocol_build: protocol=%u\n", protocol); /* sanity checks... */ if (p != 0) { ERROR("pfkey_x_protocol_build: bogus protocol pointer\n"); SENDERR(EINVAL); } if ((p = (struct sadb_protocol*)MALLOC(sizeof(*p))) == 0) { ERROR("pfkey_build: memory allocation failed\n"); SENDERR(ENOMEM); } *pfkey_ext = (struct sadb_ext *)p; p->sadb_protocol_len = sizeof(*p) / IPSEC_PFKEYv2_ALIGN; p->sadb_protocol_exttype = K_SADB_X_EXT_PROTOCOL; p->sadb_protocol_proto = protocol; p->sadb_protocol_flags = 0; p->sadb_protocol_reserved2 = 0; errlab: return error; } int pfkey_outif_build(struct sadb_ext **pfkey_ext, uint16_t outif) { int error = 0; struct sadb_x_plumbif *p; if ((p = (struct sadb_x_plumbif*)MALLOC(sizeof(*p))) == 0) { ERROR("pfkey_build: memory allocation failed\n"); SENDERR(ENOMEM); } *pfkey_ext = (struct sadb_ext *)p; p->sadb_x_outif_len = IPSEC_PFKEYv2_WORDS(sizeof(*p)); p->sadb_x_outif_exttype = K_SADB_X_EXT_PLUMBIF; p->sadb_x_outif_ifnum = outif; errlab: return error; } int pfkey_saref_build(struct sadb_ext **pfkey_ext, IPsecSAref_t in, IPsecSAref_t out) { int error = 0; struct sadb_x_saref *s; /* +4 because sadb_x_saref is not a multiple of 8 bytes */ if ((s = (struct sadb_x_saref*)MALLOC(sizeof(*s) + 4)) == 0) { ERROR("pfkey_build: memory allocation failed\n"); SENDERR(ENOMEM); } *pfkey_ext = (struct sadb_ext *)s; s->sadb_x_saref_len = IPSEC_PFKEYv2_WORDS(sizeof(*s)); s->sadb_x_saref_exttype = K_SADB_X_EXT_SAREF; s->sadb_x_saref_me = in; s->sadb_x_saref_him = out; errlab: return error; } #if defined(I_DONT_THINK_THIS_WILL_BE_USEFUL) && \ I_DONT_THINK_THIS_WILL_BE_USEFUL int(*ext_default_builders[K_SADB_EXT_MAX + 1])(struct sadb_msg*, struct sadb_ext*) = { NULL, /* pfkey_msg_build, */ pfkey_sa_build, pfkey_lifetime_build, pfkey_lifetime_build, pfkey_lifetime_build, pfkey_address_build, pfkey_address_build, pfkey_address_build, pfkey_key_build, pfkey_key_build, pfkey_ident_build, pfkey_ident_build, pfkey_sens_build, pfkey_prop_build, pfkey_supported_build, pfkey_supported_build, pfkey_spirange_build, pfkey_x_kmprivate_build, pfkey_x_satype_build, pfkey_sa_build, pfkey_address_build, pfkey_address_build, pfkey_address_build, pfkey_address_build, pfkey_address_build, pfkey_x_ext_debug_build }; #endif int pfkey_msg_build(struct sadb_msg **pfkey_msg, struct sadb_ext *extensions[], int dir) { int error = 0; unsigned ext; unsigned total_size; struct sadb_ext *pfkey_ext; pfkey_ext_track extensions_seen = 0; #ifndef __KERNEL__ struct sadb_ext *extensions_check[K_SADB_EXT_MAX + 1]; #endif if (!extensions[0]) { ERROR("pfkey_msg_build: " "extensions[0] must be specified (struct sadb_msg).\n"); SENDERR(EINVAL); } /* figure out the total size for all the requested extensions */ total_size = IPSEC_PFKEYv2_WORDS(sizeof(struct sadb_msg)); DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_msg_build: extensions[%d] needs %zu bytes\n", 0, total_size * IPSEC_PFKEYv2_ALIGN); for (ext = 1; ext <= K_SADB_EXT_MAX; ext++) { if (extensions[ext]) { total_size += (extensions[ext])->sadb_ext_len; DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_msg_build: extensions[%d] needs %zu bytes\n", ext, (extensions[ext])->sadb_ext_len * IPSEC_PFKEYv2_ALIGN); } } /* allocate that much space */ *pfkey_msg = (struct sadb_msg*)MALLOC(total_size * IPSEC_PFKEYv2_ALIGN); if (*pfkey_msg == NULL) { ERROR("pfkey_msg_build: " "memory allocation failed\n"); SENDERR(ENOMEM); } DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_msg_build: " "pfkey_msg=0p%p allocated %zu bytes, &(extensions[0])=0p%p\n", *pfkey_msg, total_size * IPSEC_PFKEYv2_ALIGN, &(extensions[0])); memcpy(*pfkey_msg, extensions[0], sizeof(struct sadb_msg)); (*pfkey_msg)->sadb_msg_len = total_size; (*pfkey_msg)->sadb_msg_reserved = 0; extensions_seen = 1; /* * point pfkey_ext to immediately after the space for the header, * i.e. at the first extension location. */ pfkey_ext = (struct sadb_ext*) (((char*)(*pfkey_msg)) + sizeof(struct sadb_msg)); for (ext = 1; ext <= K_SADB_EXT_MAX; ext++) { /* copy from extension[ext] to buffer */ if (extensions[ext]) { size_t el; /* Is this type of extension permitted for this type of message? */ if (!pfkey_permitted_extension(dir, (*pfkey_msg)-> sadb_msg_type, ext)) { ERROR("ext type %d not permitted for %d/%d (build)\n", ext, dir, (*pfkey_msg)->sadb_msg_type); SENDERR(EINVAL); } el = extensions[ext]->sadb_ext_len * IPSEC_PFKEYv2_ALIGN; DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_msg_build: " "copying %zu bytes from extensions[%u] (type=%d)\n", el, ext, extensions[ext]->sadb_ext_type); memcpy(pfkey_ext, extensions[ext], el); pfkey_ext = (struct sadb_ext *) ((unsigned char *)pfkey_ext + el); /* Mark that we have seen this extension */ pfkey_mark_extension(ext, &extensions_seen); } } #if 0 /* check required extensions */ DEBUGGING(PF_KEY_DEBUG_BUILD, "pfkey_msg_build: " "extensions permitted=%08x, seen=%08x, required=%08x.\n", extensions_bitmaps[dir][EXT_BITS_PERM][(*pfkey_msg)-> sadb_msg_type], extensions_seen, extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)-> sadb_msg_type]); #endif #ifndef __KERNEL__ /* * this is silly, there is no need to reparse the message that we just built. * */ if ((error = pfkey_msg_parse(*pfkey_msg, NULL, extensions_check, dir))) { ERROR("pfkey_msg_build: " "Trouble parsing newly built pfkey message, error=%d.\n", error); SENDERR(-error); } #endif errlab: return error; } libreswan-3.32/linux/net/ipsec/pfkey_v2_debug.c000066400000000000000000000141211365625662500215350ustar00rootroot00000000000000/* * @(#) pfkey version 2 debugging messages * * Copyright (C) 2001 Richard Guy Briggs * and Michael Richardson * Copyright (C) 2012 Paul Wouters * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #ifdef __KERNEL__ # include /* for printk */ # include "libreswan/ipsec_kversion.h" /* for malloc switch */ # include /* kmalloc() */ # include /* error codes */ # include /* size_t */ # include /* mark_bh */ # include /* struct device, and other headers */ # include /* eth_type_trans */ extern int debug_pfkey; #else /* __KERNEL__ */ # include #if defined(linux) # include # include #endif #endif /* __KERNEL__ */ #include "libreswan.h" #include "libreswan/pfkeyv2.h" #include "libreswan/pfkey.h" /* * This file provides ASCII translations of PF_KEY magic numbers. * */ static char *pfkey_sadb_ext_strings[] = { "reserved", /* K_SADB_EXT_RESERVED 0 */ "security-association", /* K_SADB_EXT_SA 1 */ "lifetime-current", /* K_SADB_EXT_LIFETIME_CURRENT 2 */ "lifetime-hard", /* K_SADB_EXT_LIFETIME_HARD 3 */ "lifetime-soft", /* K_SADB_EXT_LIFETIME_SOFT 4 */ "source-address", /* K_SADB_EXT_ADDRESS_SRC 5 */ "destination-address", /* K_SADB_EXT_ADDRESS_DST 6 */ "proxy-address", /* K_SADB_EXT_ADDRESS_PROXY 7 */ "authentication-key", /* K_SADB_EXT_KEY_AUTH 8 */ "cipher-key", /* K_SADB_EXT_KEY_ENCRYPT 9 */ "source-identity", /* K_SADB_EXT_IDENTITY_SRC 10 */ "destination-identity", /* K_SADB_EXT_IDENTITY_DST 11 */ "sensitivity-label", /* K_SADB_EXT_SENSITIVITY 12 */ "proposal", /* K_SADB_EXT_PROPOSAL 13 */ "supported-auth", /* K_SADB_EXT_SUPPORTED_AUTH 14 */ "supported-cipher", /* K_SADB_EXT_SUPPORTED_ENCRYPT 15 */ "spi-range", /* K_SADB_EXT_SPIRANGE 16 */ "X-kmpprivate", /* K_SADB_X_EXT_KMPRIVATE 17 */ "X-satype2", /* K_SADB_X_EXT_SATYPE2 18 */ "X-security-association", /* K_SADB_X_EXT_SA2 19 */ "X-destination-address2", /* K_SADB_X_EXT_ADDRESS_DST2 20 */ "X-source-flow-address", /* K_SADB_X_EXT_ADDRESS_SRC_FLOW 21 */ "X-dest-flow-address", /* K_SADB_X_EXT_ADDRESS_DST_FLOW 22 */ "X-source-mask", /* K_SADB_X_EXT_ADDRESS_SRC_MASK 23 */ "X-dest-mask", /* K_SADB_X_EXT_ADDRESS_DST_MASK 24 */ "X-set-debug", /* K_SADB_X_EXT_DEBUG 25 */ "X-ext-protocol", /* K_SADB_X_EXT_PROTOCOL 26 */ "X-NAT-T-type", /* K_SADB_X_EXT_NAT_T_TYPE 27 */ "X-NAT-T-sport", /* K_SADB_X_EXT_NAT_T_SPORT 28 */ "X-NAT-T-dport", /* K_SADB_X_EXT_NAT_T_DPORT 29 */ "X-NAT-T-OA", /* K_SADB_X_EXT_NAT_T_OA 30 */ "X-plumbif", /* K_SADB_X_EXT_PLUMBIF 31 */ "X-saref", /* K_SADB_X_EXT_SAREF 32 */ }; const char *pfkey_v2_sadb_ext_string(int ext) { if (ext <= K_SADB_EXT_MAX) return pfkey_sadb_ext_strings[ext]; else return "unknown-ext"; } static char *pfkey_sadb_type_strings[K_SADB_MAX + 1] = { [K_SADB_RESERVED] = "reserved", /* K_SADB_RESERVED */ [K_SADB_GETSPI] = "getspi", /* K_SADB_GETSPI */ [K_SADB_UPDATE] = "update", /* K_SADB_UPDATE */ [K_SADB_ADD] = "add", /* K_SADB_ADD */ [K_SADB_DELETE] = "delete", /* K_SADB_DELETE */ [K_SADB_GET] = "get", /* K_SADB_GET */ [K_SADB_ACQUIRE] = "acquire", /* K_SADB_ACQUIRE */ [K_SADB_REGISTER] = "register", /* K_SADB_REGISTER */ [K_SADB_EXPIRE] = "expire", /* K_SADB_EXPIRE */ [K_SADB_FLUSH] = "flush", /* K_SADB_FLUSH */ [K_SADB_DUMP] = "dump", /* K_SADB_DUMP */ [K_SADB_X_PROMISC] = "x-promisc", /* K_SADB_X_PROMISC */ [K_SADB_X_PCHANGE] = "x-pchange", /* K_SADB_X_PCHANGE */ [K_SADB_X_GRPSA] = "x-groupsa", /* K_SADB_X_GRPSA */ [K_SADB_X_ADDFLOW] = "x-addflow(eroute)", /* K_SADB_X_ADDFLOW */ [K_SADB_X_DELFLOW] = "x-delflow(eroute)", /* K_SADB_X_DELFLOW */ [K_SADB_X_DEBUG] = "x-debug", /* K_SADB_X_DEBUG */ [K_SADB_X_NAT_T_NEW_MAPPING] = "x-natt-new-mapping", /* K_SADB_X_NAT_T_NEW_MAPPING */ [K_SADB_X_PLUMBIF] = "x-plumbif", /* K_SADB_X_PLUMBIF */ [K_SADB_X_UNPLUMBIF] = "x-unplumbif", /* K_SADB_X_UNPLUMBIF */ }; const char *pfkey_v2_sadb_type_string(unsigned sadb_type) { if (sadb_type <= K_SADB_MAX && pfkey_sadb_type_strings[sadb_type] != NULL) return pfkey_sadb_type_strings[sadb_type]; else return "unknown-sadb-type"; } libreswan-3.32/linux/net/ipsec/pfkey_v2_ext_bits.c000066400000000000000000000546401365625662500223020ustar00rootroot00000000000000/* * RFC2367 PF_KEYv2 Key management API message parser * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs. * Copyright (C) 2012 Paul Wouters * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ /* * Template from klips/net/ipsec/ipsec/ipsec_parse.c. */ /* * Some ugly stuff to allow consistent debugging code for use in the * kernel and in user space */ #if defined(__KERNEL__) && (defined(linux) || defined(__linux__)) # include /* for printk */ # include "libreswan/ipsec_kversion.h" /* for malloc switch */ # include /* kmalloc() */ # include /* error codes */ # include /* size_t */ # include /* mark_bh */ # include /* struct device, and other headers */ # include /* eth_type_trans */ # include /* struct iphdr */ # if defined(CONFIG_KLIPS_IPV6) # include # endif /* defined(CONFIG_KLIPS_IPV6) */ #else /* __KERNEL__ */ # include # include # include #endif #include #include #include #include "libreswan/pfkey_debug.h" /* array of bitmaps to specify payloads for extensions */ /* ??? why does each bitmap include 1ULL << SADB_EXT_RESERVED? */ pfkey_ext_track extensions_bitmaps [2 /* inbound, outbound */] [2 /* permitted, required */] [K_SADB_MAX + 1] = { /* INBOUND EXTENSIONS */ { /* PERMITTED IN */ { /* K_SADB_RESERVED */ 0 , /* SADB_GETSPI */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << SADB_EXT_ADDRESS_PROXY | 1ULL << SADB_EXT_SPIRANGE , /* SADB_UPDATE */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_LIFETIME_CURRENT | 1ULL << SADB_EXT_LIFETIME_HARD | 1ULL << SADB_EXT_LIFETIME_SOFT | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << SADB_EXT_ADDRESS_PROXY | 1ULL << SADB_EXT_KEY_AUTH | 1ULL << SADB_EXT_KEY_ENCRYPT | 1ULL << SADB_EXT_IDENTITY_SRC | 1ULL << SADB_EXT_IDENTITY_DST | 1ULL << SADB_EXT_SENSITIVITY | 1ULL << K_SADB_X_EXT_NAT_T_SPORT | 1ULL << K_SADB_X_EXT_NAT_T_DPORT , /* SADB_ADD */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_LIFETIME_HARD | 1ULL << SADB_EXT_LIFETIME_SOFT | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << SADB_EXT_ADDRESS_PROXY | 1ULL << SADB_EXT_KEY_AUTH | 1ULL << SADB_EXT_KEY_ENCRYPT | 1ULL << SADB_EXT_IDENTITY_SRC | 1ULL << SADB_EXT_IDENTITY_DST | 1ULL << SADB_EXT_SENSITIVITY | 1ULL << K_SADB_X_EXT_NAT_T_TYPE | 1ULL << K_SADB_X_EXT_NAT_T_SPORT | 1ULL << K_SADB_X_EXT_NAT_T_DPORT | 1ULL << K_SADB_X_EXT_NAT_T_OA | 1ULL << K_SADB_X_EXT_PLUMBIF | 1ULL << K_SADB_X_EXT_SAREF , /* SADB_DELETE */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST , /* SADB_GET */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << SADB_EXT_LIFETIME_CURRENT , /* SADB_ACQUIRE */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << SADB_EXT_ADDRESS_PROXY | 1ULL << SADB_EXT_IDENTITY_SRC | 1ULL << SADB_EXT_IDENTITY_DST | 1ULL << SADB_EXT_SENSITIVITY | 1ULL << SADB_EXT_PROPOSAL , /* K_SADB_REGISTER */ 1ULL << K_SADB_EXT_RESERVED , /* K_SADB_EXPIRE */ 0 , /* K_SADB_FLUSH */ 1ULL << K_SADB_EXT_RESERVED , /* K_SADB_DUMP */ 1ULL << K_SADB_EXT_RESERVED , /* SADB_X_PROMISC */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_LIFETIME_CURRENT | 1ULL << SADB_EXT_LIFETIME_HARD | 1ULL << SADB_EXT_LIFETIME_SOFT | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << SADB_EXT_ADDRESS_PROXY | 1ULL << SADB_EXT_KEY_AUTH | 1ULL << SADB_EXT_KEY_ENCRYPT | 1ULL << SADB_EXT_IDENTITY_SRC | 1ULL << SADB_EXT_IDENTITY_DST | 1ULL << SADB_EXT_SENSITIVITY | 1ULL << SADB_EXT_PROPOSAL | 1ULL << SADB_EXT_SUPPORTED_AUTH | 1ULL << SADB_EXT_SUPPORTED_ENCRYPT | 1ULL << SADB_EXT_SPIRANGE | 1ULL << K_SADB_X_EXT_KMPRIVATE | 1ULL << K_SADB_X_EXT_SATYPE2 | 1ULL << K_SADB_X_EXT_SA2 | 1ULL << K_SADB_X_EXT_ADDRESS_DST2 , /* SADB_X_PCHANGE */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_LIFETIME_CURRENT | 1ULL << SADB_EXT_LIFETIME_HARD | 1ULL << SADB_EXT_LIFETIME_SOFT | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << SADB_EXT_ADDRESS_PROXY | 1ULL << SADB_EXT_KEY_AUTH | 1ULL << SADB_EXT_KEY_ENCRYPT | 1ULL << SADB_EXT_IDENTITY_SRC | 1ULL << SADB_EXT_IDENTITY_DST | 1ULL << SADB_EXT_SENSITIVITY | 1ULL << SADB_EXT_PROPOSAL | 1ULL << SADB_EXT_SUPPORTED_AUTH | 1ULL << SADB_EXT_SUPPORTED_ENCRYPT | 1ULL << SADB_EXT_SPIRANGE | 1ULL << K_SADB_X_EXT_KMPRIVATE | 1ULL << K_SADB_X_EXT_SATYPE2 | 1ULL << K_SADB_X_EXT_SA2 | 1ULL << K_SADB_X_EXT_ADDRESS_DST2 , /* SADB_X_GRPSA */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << K_SADB_X_EXT_SATYPE2 | 1ULL << K_SADB_X_EXT_SA2 | 1ULL << K_SADB_X_EXT_ADDRESS_DST2 , /* SADB_X_ADDFLOW */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << K_SADB_X_EXT_ADDRESS_SRC_FLOW | 1ULL << K_SADB_X_EXT_ADDRESS_DST_FLOW | 1ULL << K_SADB_X_EXT_ADDRESS_SRC_MASK | 1ULL << K_SADB_X_EXT_ADDRESS_DST_MASK | 1ULL << SADB_EXT_IDENTITY_SRC | 1ULL << SADB_EXT_IDENTITY_DST | 1ULL << K_SADB_X_EXT_PROTOCOL , /* SADB_X_DELFLOW */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << K_SADB_X_EXT_ADDRESS_SRC_FLOW | 1ULL << K_SADB_X_EXT_ADDRESS_DST_FLOW | 1ULL << K_SADB_X_EXT_ADDRESS_SRC_MASK | 1ULL << K_SADB_X_EXT_ADDRESS_DST_MASK | 1ULL << SADB_EXT_IDENTITY_SRC | 1ULL << SADB_EXT_IDENTITY_DST | 1ULL << K_SADB_X_EXT_PROTOCOL , /* SADB_X_DEBUG */ 1ULL << SADB_EXT_RESERVED | 1ULL << K_SADB_X_EXT_DEBUG , /* SADB_X_NAT_T_NEW_MAPPING */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << K_SADB_X_EXT_NAT_T_SPORT | 1ULL << K_SADB_X_EXT_NAT_T_DPORT , /* SADB_X_PLUMBIF */ 1ULL << SADB_EXT_RESERVED | 1ULL << K_SADB_X_EXT_PLUMBIF , /* SADB_X_UNPLUMBIF */ 1ULL << SADB_EXT_RESERVED | 1ULL << K_SADB_X_EXT_PLUMBIF }, /* REQUIRED IN */ { /* K_SADB_RESERVED */ 0 , /* K_SADB_GETSPI */ 1ULL << K_SADB_EXT_RESERVED | 1ULL << K_SADB_EXT_ADDRESS_SRC | 1ULL << K_SADB_EXT_ADDRESS_DST | 1ULL << K_SADB_EXT_SPIRANGE , /* K_SADB_UPDATE */ 1ULL << K_SADB_EXT_RESERVED | 1ULL << K_SADB_EXT_SA | 1ULL << K_SADB_EXT_ADDRESS_SRC | 1ULL << K_SADB_EXT_ADDRESS_DST , /* K_SADB_ADD */ 1ULL << K_SADB_EXT_RESERVED | 1ULL << K_SADB_EXT_SA | 1ULL << K_SADB_EXT_ADDRESS_SRC | 1ULL << K_SADB_EXT_ADDRESS_DST , /* K_SADB_DELETE */ 1ULL << K_SADB_EXT_RESERVED | 1ULL << K_SADB_EXT_SA | 1ULL << K_SADB_EXT_ADDRESS_SRC | 1ULL << K_SADB_EXT_ADDRESS_DST , /* K_SADB_GET */ 1ULL << K_SADB_EXT_RESERVED | 1ULL << K_SADB_EXT_SA | 1ULL << K_SADB_EXT_ADDRESS_SRC | 1ULL << K_SADB_EXT_ADDRESS_DST , /* K_SADB_ACQUIRE */ 1ULL << K_SADB_EXT_RESERVED | 1ULL << K_SADB_EXT_ADDRESS_SRC | 1ULL << K_SADB_EXT_ADDRESS_DST | 1ULL << K_SADB_EXT_PROPOSAL , /* K_SADB_REGISTER */ 1ULL << K_SADB_EXT_RESERVED , /* K_SADB_EXPIRE */ 0 , /* K_SADB_FLUSH */ 1ULL << K_SADB_EXT_RESERVED , /* K_SADB_DUMP */ 1ULL << K_SADB_EXT_RESERVED , /* SADB_X_PROMISC */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_LIFETIME_CURRENT | 1ULL << SADB_EXT_LIFETIME_HARD | 1ULL << SADB_EXT_LIFETIME_SOFT | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << SADB_EXT_ADDRESS_PROXY | 1ULL << SADB_EXT_KEY_AUTH | 1ULL << SADB_EXT_KEY_ENCRYPT | 1ULL << SADB_EXT_IDENTITY_SRC | 1ULL << SADB_EXT_IDENTITY_DST | 1ULL << SADB_EXT_SENSITIVITY | 1ULL << SADB_EXT_PROPOSAL | 1ULL << SADB_EXT_SUPPORTED_AUTH | 1ULL << SADB_EXT_SUPPORTED_ENCRYPT | 1ULL << SADB_EXT_SPIRANGE | 1ULL << K_SADB_X_EXT_KMPRIVATE | 1ULL << K_SADB_X_EXT_SATYPE2 | 1ULL << K_SADB_X_EXT_SA2 | 1ULL << K_SADB_X_EXT_ADDRESS_DST2 , /* SADB_X_PCHANGE */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_LIFETIME_CURRENT | 1ULL << SADB_EXT_LIFETIME_HARD | 1ULL << SADB_EXT_LIFETIME_SOFT | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << SADB_EXT_ADDRESS_PROXY | 1ULL << SADB_EXT_KEY_AUTH | 1ULL << SADB_EXT_KEY_ENCRYPT | 1ULL << SADB_EXT_IDENTITY_SRC | 1ULL << SADB_EXT_IDENTITY_DST | 1ULL << SADB_EXT_SENSITIVITY | 1ULL << SADB_EXT_PROPOSAL | 1ULL << SADB_EXT_SUPPORTED_AUTH | 1ULL << SADB_EXT_SUPPORTED_ENCRYPT | 1ULL << SADB_EXT_SPIRANGE | 1ULL << K_SADB_X_EXT_KMPRIVATE | 1ULL << K_SADB_X_EXT_SATYPE2 | 1ULL << K_SADB_X_EXT_SA2 | 1ULL << K_SADB_X_EXT_ADDRESS_DST2 , /* SADB_X_GRPSA */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_ADDRESS_DST , /* SADB_X_ADDFLOW */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << K_SADB_X_EXT_ADDRESS_SRC_FLOW | 1ULL << K_SADB_X_EXT_ADDRESS_DST_FLOW | 1ULL << K_SADB_X_EXT_ADDRESS_SRC_MASK | 1ULL << K_SADB_X_EXT_ADDRESS_DST_MASK , /* SADB_X_DELFLOW */ 1ULL << SADB_EXT_RESERVED #if 0 /* SADB_X_CLREROUTE doesn't need all these... */ | 1ULL << K_SADB_X_EXT_ADDRESS_SRC_FLOW | 1ULL << K_SADB_X_EXT_ADDRESS_DST_FLOW | 1ULL << K_SADB_X_EXT_ADDRESS_SRC_MASK | 1ULL << K_SADB_X_EXT_ADDRESS_DST_MASK #endif , /* SADB_X_DEBUG */ 1ULL << SADB_EXT_RESERVED | 1ULL << K_SADB_X_EXT_DEBUG , /* SADB_X_NAT_T_NEW_MAPPING */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << K_SADB_X_EXT_NAT_T_SPORT | 1ULL << K_SADB_X_EXT_NAT_T_DPORT , /* SADB_X_PLUMBIF */ 1ULL << SADB_EXT_RESERVED | 1ULL << K_SADB_X_EXT_PLUMBIF , /* SADB_X_UNPLUMBIF */ 1ULL << SADB_EXT_RESERVED | 1ULL << K_SADB_X_EXT_PLUMBIF } }, /* OUTBOUND EXTENSIONS */ { /* PERMITTED OUT */ { /* K_SADB_RESERVED */ 0 , /* SADB_GETSPI */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST , /* SADB_UPDATE */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_LIFETIME_CURRENT | 1ULL << SADB_EXT_LIFETIME_HARD | 1ULL << SADB_EXT_LIFETIME_SOFT | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << SADB_EXT_ADDRESS_PROXY | 1ULL << SADB_EXT_IDENTITY_SRC | 1ULL << SADB_EXT_IDENTITY_DST | 1ULL << SADB_EXT_SENSITIVITY | 1ULL << K_SADB_X_EXT_NAT_T_SPORT | 1ULL << K_SADB_X_EXT_NAT_T_DPORT , /* SADB_ADD */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_LIFETIME_HARD | 1ULL << SADB_EXT_LIFETIME_SOFT | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << SADB_EXT_IDENTITY_SRC | 1ULL << SADB_EXT_IDENTITY_DST | 1ULL << SADB_EXT_SENSITIVITY | 1ULL << K_SADB_X_EXT_NAT_T_TYPE | 1ULL << K_SADB_X_EXT_NAT_T_SPORT | 1ULL << K_SADB_X_EXT_NAT_T_DPORT | 1ULL << K_SADB_X_EXT_NAT_T_OA | 1ULL << K_SADB_X_EXT_PLUMBIF | 1ULL << K_SADB_X_EXT_SAREF , /* SADB_DELETE */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST , /* SADB_GET */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_LIFETIME_CURRENT | 1ULL << SADB_EXT_LIFETIME_HARD | 1ULL << SADB_EXT_LIFETIME_SOFT | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << SADB_EXT_ADDRESS_PROXY | 1ULL << SADB_EXT_KEY_AUTH | 1ULL << SADB_EXT_KEY_ENCRYPT | 1ULL << SADB_EXT_IDENTITY_SRC | 1ULL << SADB_EXT_IDENTITY_DST | 1ULL << SADB_EXT_SENSITIVITY | 1ULL << K_SADB_X_EXT_NAT_T_TYPE | 1ULL << K_SADB_X_EXT_NAT_T_SPORT | 1ULL << K_SADB_X_EXT_NAT_T_DPORT | 1ULL << K_SADB_X_EXT_NAT_T_OA , /* SADB_ACQUIRE */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << SADB_EXT_ADDRESS_PROXY | 1ULL << SADB_EXT_IDENTITY_SRC | 1ULL << SADB_EXT_IDENTITY_DST | 1ULL << SADB_EXT_SENSITIVITY | 1ULL << SADB_EXT_PROPOSAL , /* SADB_REGISTER */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SUPPORTED_AUTH | 1ULL << SADB_EXT_SUPPORTED_ENCRYPT , /* SADB_EXPIRE */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_LIFETIME_CURRENT | 1ULL << SADB_EXT_LIFETIME_HARD | 1ULL << SADB_EXT_LIFETIME_SOFT | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST , /* SADB_FLUSH */ 1ULL << SADB_EXT_RESERVED , /* SADB_DUMP */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_LIFETIME_CURRENT | 1ULL << SADB_EXT_LIFETIME_HARD | 1ULL << SADB_EXT_LIFETIME_SOFT | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << SADB_EXT_ADDRESS_PROXY | 1ULL << SADB_EXT_KEY_AUTH | 1ULL << SADB_EXT_KEY_ENCRYPT | 1ULL << SADB_EXT_IDENTITY_SRC | 1ULL << SADB_EXT_IDENTITY_DST | 1ULL << SADB_EXT_SENSITIVITY | 1ULL << K_SADB_X_EXT_NAT_T_TYPE | 1ULL << K_SADB_X_EXT_NAT_T_SPORT | 1ULL << K_SADB_X_EXT_NAT_T_DPORT | 1ULL << K_SADB_X_EXT_NAT_T_OA , /* SADB_X_PROMISC */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_LIFETIME_CURRENT | 1ULL << SADB_EXT_LIFETIME_HARD | 1ULL << SADB_EXT_LIFETIME_SOFT | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << SADB_EXT_ADDRESS_PROXY | 1ULL << SADB_EXT_KEY_AUTH | 1ULL << SADB_EXT_KEY_ENCRYPT | 1ULL << SADB_EXT_IDENTITY_SRC | 1ULL << SADB_EXT_IDENTITY_DST | 1ULL << SADB_EXT_SENSITIVITY | 1ULL << SADB_EXT_PROPOSAL | 1ULL << SADB_EXT_SUPPORTED_AUTH | 1ULL << SADB_EXT_SUPPORTED_ENCRYPT | 1ULL << SADB_EXT_SPIRANGE | 1ULL << K_SADB_X_EXT_KMPRIVATE | 1ULL << K_SADB_X_EXT_SATYPE2 | 1ULL << K_SADB_X_EXT_SA2 | 1ULL << K_SADB_X_EXT_ADDRESS_DST2 , /* SADB_X_PCHANGE */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_LIFETIME_CURRENT | 1ULL << SADB_EXT_LIFETIME_HARD | 1ULL << SADB_EXT_LIFETIME_SOFT | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << SADB_EXT_ADDRESS_PROXY | 1ULL << SADB_EXT_KEY_AUTH | 1ULL << SADB_EXT_KEY_ENCRYPT | 1ULL << SADB_EXT_IDENTITY_SRC | 1ULL << SADB_EXT_IDENTITY_DST | 1ULL << SADB_EXT_SENSITIVITY | 1ULL << SADB_EXT_PROPOSAL | 1ULL << SADB_EXT_SUPPORTED_AUTH | 1ULL << SADB_EXT_SUPPORTED_ENCRYPT | 1ULL << SADB_EXT_SPIRANGE | 1ULL << K_SADB_X_EXT_KMPRIVATE | 1ULL << K_SADB_X_EXT_SATYPE2 | 1ULL << K_SADB_X_EXT_SA2 | 1ULL << K_SADB_X_EXT_ADDRESS_DST2 , /* SADB_X_GRPSA */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << K_SADB_X_EXT_SATYPE2 | 1ULL << K_SADB_X_EXT_SA2 | 1ULL << K_SADB_X_EXT_ADDRESS_DST2 , /* SADB_X_ADDFLOW */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << K_SADB_X_EXT_ADDRESS_SRC_FLOW | 1ULL << K_SADB_X_EXT_ADDRESS_DST_FLOW | 1ULL << K_SADB_X_EXT_ADDRESS_SRC_MASK | 1ULL << K_SADB_X_EXT_ADDRESS_DST_MASK | 1ULL << K_SADB_X_EXT_PROTOCOL , /* SADB_X_DELFLOW */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << K_SADB_X_EXT_ADDRESS_SRC_FLOW | 1ULL << K_SADB_X_EXT_ADDRESS_DST_FLOW | 1ULL << K_SADB_X_EXT_ADDRESS_SRC_MASK | 1ULL << K_SADB_X_EXT_ADDRESS_DST_MASK | 1ULL << K_SADB_X_EXT_PROTOCOL , /* SADB_X_DEBUG */ 1ULL << SADB_EXT_RESERVED | 1ULL << K_SADB_X_EXT_DEBUG , /* SADB_X_NAT_T_NEW_MAPPING */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST | 1ULL << K_SADB_X_EXT_NAT_T_SPORT | 1ULL << K_SADB_X_EXT_NAT_T_DPORT , /* SADB_X_PLUMBIF */ 1ULL << SADB_EXT_RESERVED | 1ULL << K_SADB_X_EXT_PLUMBIF , /* SADB_X_UNPLUMBIF */ 1ULL << SADB_EXT_RESERVED | 1ULL << K_SADB_X_EXT_PLUMBIF }, /* REQUIRED OUT */ { /* K_SADB_RESERVED */ 0 , /* SADB_GETSPI */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST , /* SADB_UPDATE */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST , /* SADB_ADD */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST , /* SADB_DELETE */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST , /* SADB_GET */ 1ULL << SADB_EXT_RESERVED | 1ULL << SADB_EXT_SA | 1ULL << SADB_EXT_ADDRESS_SRC | 1ULL << SADB_EXT_ADDRESS_DST /* | 1ULL< * Copyright (C) 2012 Paul Wouters * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ /* * Template from klips/net/ipsec/ipsec/ipsec_netlink.c. */ #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38) && \ !defined(AUTOCONF_INCLUDED) #include #endif #include /* printk() */ #include "libreswan/ipsec_param.h" #include /* kmalloc() */ #include /* error codes */ #include /* size_t */ #include /* mark_bh */ #include /* struct device, and other headers */ #include /* eth_type_trans */ #include /* struct iphdr */ #include #include #include #include /* *lock* */ # include # define IS_MYADDR RTN_LOCAL #include #include #include /* get_random_bytes() */ #include "libreswan/radij.h" #include "libreswan/ipsec_encap.h" #include "libreswan/ipsec_sa.h" #include "libreswan/ipsec_radij.h" #include "libreswan/ipsec_xform.h" #include "libreswan/ipsec_ah.h" #include "libreswan/ipsec_esp.h" #include "libreswan/ipsec_tunnel.h" #include "libreswan/ipsec_rcv.h" #include "libreswan/ipcomp.h" #include #include #include "libreswan/ipsec_proto.h" #include "libreswan/ipsec_alg.h" #ifdef CONFIG_KLIPS_OCF #include "ipsec_ocf.h" #endif #define SENDERR(_x) do { error = -(_x); goto errlab; } while (0) /* returns 0 on success */ int pfkey_sa_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr) { struct k_sadb_sa *k_pfkey_sa = (struct k_sadb_sa *)pfkey_ext; struct sadb_sa *pfkey_sa = (struct sadb_sa *)pfkey_ext; int error = 0; struct ipsec_sa *ipsp; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sa_process: .\n"); if (!extr || !extr->ips) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sa_process: " "extr or extr->ips is NULL, fatal\n"); SENDERR(EINVAL); } switch (pfkey_ext->sadb_ext_type) { case K_SADB_EXT_SA: ipsp = extr->ips; break; case K_SADB_X_EXT_SA2: if (extr->ips2 == NULL) extr->ips2 = ipsec_sa_alloc(&error); /* pass error var by pointer */ if (extr->ips2 == NULL) SENDERR(-error); ipsp = extr->ips2; break; default: KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sa_process: " "invalid exttype=%d.\n", pfkey_ext->sadb_ext_type); SENDERR(EINVAL); } ipsp->ips_said.spi = pfkey_sa->sadb_sa_spi; ipsp->ips_replaywin = pfkey_sa->sadb_sa_replay; ipsp->ips_state = pfkey_sa->sadb_sa_state; ipsp->ips_flags = pfkey_sa->sadb_sa_flags; ipsp->ips_replaywin_lastseq = ipsp->ips_replaywin_bitmap = 0; if (k_pfkey_sa->sadb_sa_len > sizeof(struct sadb_sa) / IPSEC_PFKEYv2_ALIGN) ipsp->ips_ref = k_pfkey_sa->sadb_x_sa_ref; switch (ipsp->ips_said.proto) { case IPPROTO_AH: ipsp->ips_authalg = pfkey_sa->sadb_sa_auth; ipsp->ips_encalg = K_SADB_EALG_NONE; #ifdef CONFIG_KLIPS_OCF if (ipsec_ocf_sa_init(ipsp, ipsp->ips_authalg, 0)) break; #endif break; case IPPROTO_ESP: ipsp->ips_authalg = pfkey_sa->sadb_sa_auth; ipsp->ips_encalg = pfkey_sa->sadb_sa_encrypt; #ifdef CONFIG_KLIPS_OCF if (ipsec_ocf_sa_init(ipsp, ipsp->ips_authalg, ipsp->ips_encalg)) break; #endif break; case IPPROTO_IPIP: ipsp->ips_authalg = AH_NONE; ipsp->ips_encalg = ESP_NONE; break; #ifdef CONFIG_KLIPS_IPCOMP case IPPROTO_COMP: ipsp->ips_authalg = AH_NONE; ipsp->ips_encalg = pfkey_sa->sadb_sa_encrypt; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sa_process: " "IPPROTO_COMP ips_encalg=%d.\n", ipsp->ips_encalg); break; #endif /* CONFIG_KLIPS_IPCOMP */ case IPPROTO_INT: ipsp->ips_authalg = AH_NONE; ipsp->ips_encalg = ESP_NONE; break; case 0: break; default: KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sa_process: " "unknown proto=%d.\n", ipsp->ips_said.proto); SENDERR(EINVAL); } errlab: return error; } int pfkey_lifetime_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr) { int error = 0; struct sadb_lifetime *pfkey_lifetime = (struct sadb_lifetime *)pfkey_ext; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_lifetime_process: .\n"); if (!extr || !extr->ips) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_lifetime_process: " "extr or extr->ips is NULL, fatal\n"); SENDERR(EINVAL); } switch (pfkey_lifetime->sadb_lifetime_exttype) { case K_SADB_EXT_LIFETIME_CURRENT: KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_lifetime_process: " "lifetime_current not supported yet.\n"); SENDERR(EINVAL); break; case K_SADB_EXT_LIFETIME_HARD: ipsec_lifetime_update_hard( &extr->ips->ips_life.ipl_allocations, pfkey_lifetime->sadb_lifetime_allocations); ipsec_lifetime_update_hard(&extr->ips->ips_life.ipl_bytes, pfkey_lifetime->sadb_lifetime_bytes); ipsec_lifetime_update_hard(&extr->ips->ips_life.ipl_addtime, pfkey_lifetime->sadb_lifetime_addtime); ipsec_lifetime_update_hard(&extr->ips->ips_life.ipl_usetime, pfkey_lifetime->sadb_lifetime_usetime); break; case K_SADB_EXT_LIFETIME_SOFT: ipsec_lifetime_update_soft( &extr->ips->ips_life.ipl_allocations, pfkey_lifetime->sadb_lifetime_allocations); ipsec_lifetime_update_soft(&extr->ips->ips_life.ipl_bytes, pfkey_lifetime->sadb_lifetime_bytes); ipsec_lifetime_update_soft(&extr->ips->ips_life.ipl_addtime, pfkey_lifetime->sadb_lifetime_addtime); ipsec_lifetime_update_soft(&extr->ips->ips_life.ipl_usetime, pfkey_lifetime->sadb_lifetime_usetime); break; default: KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_lifetime_process: " "invalid exttype=%d.\n", pfkey_ext->sadb_ext_type); SENDERR(EINVAL); } errlab: return error; } int pfkey_address_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr) { int error = 0; int saddr_len = 0; char ipaddr_txt[ADDRTOA_BUF]; unsigned char **sap; unsigned short * portp = 0; struct sadb_address *pfkey_address = (struct sadb_address *)pfkey_ext; struct sockaddr *s = (struct sockaddr*) ((char*)pfkey_address + sizeof(*pfkey_address)); struct ipsec_sa *ipsp; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_process:\n"); if (!extr || !extr->ips) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_process: " "extr or extr->ips is NULL, fatal\n"); SENDERR(EINVAL); } switch (s->sa_family) { case AF_INET: saddr_len = sizeof(struct sockaddr_in); if (debug_pfkey) sin_addrtot(s, 0, ipaddr_txt, sizeof(ipaddr_txt)); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_process: " "found address family=%d, AF_INET, %s.\n", s->sa_family, ipaddr_txt); break; #if defined(CONFIG_KLIPS_IPV6) case AF_INET6: saddr_len = sizeof(struct sockaddr_in6); if (debug_pfkey) sin_addrtot(s, 0, ipaddr_txt, sizeof(ipaddr_txt)); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_process: " "found address family=%d, AF_INET6, %s.\n", s->sa_family, ipaddr_txt); break; #endif /* defined(CONFIG_KLIPS_IPV6) */ default: KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_process: " "s->sa_family=%d not supported.\n", s->sa_family); SENDERR(EPFNOSUPPORT); } switch (pfkey_address->sadb_address_exttype) { case K_SADB_EXT_ADDRESS_SRC: KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_process: " "found src address.\n"); sap = (unsigned char **)&(extr->ips->ips_addr_s); extr->ips->ips_addr_s_size = saddr_len; break; case K_SADB_EXT_ADDRESS_DST: KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_process: " "found dst address.\n"); sap = (unsigned char **)&(extr->ips->ips_addr_d); extr->ips->ips_addr_d_size = saddr_len; break; case K_SADB_EXT_ADDRESS_PROXY: KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_process: " "found proxy address.\n"); sap = (unsigned char **)&(extr->ips->ips_addr_p); extr->ips->ips_addr_p_size = saddr_len; break; case K_SADB_X_EXT_ADDRESS_DST2: KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_process: " "found 2nd dst address.\n"); if (extr->ips2 == NULL) extr->ips2 = ipsec_sa_alloc(&error); /* pass error var by pointer */ if (extr->ips2 == NULL) SENDERR(-error); sap = (unsigned char **)&(extr->ips2->ips_addr_d); extr->ips2->ips_addr_d_size = saddr_len; break; case K_SADB_X_EXT_ADDRESS_SRC_FLOW: KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_process: " "found src flow address.\n"); if (pfkey_alloc_eroute(&(extr->eroute)) == ENOMEM) SENDERR(ENOMEM); if (s->sa_family == AF_INET6) { sap = (unsigned char **) &(extr->eroute->er_eaddr.sen_ip6_src); portp = &(extr->eroute->er_eaddr.sen_sport6); extr->eroute->er_eaddr.sen_type = SENT_IP6; } else { sap = (unsigned char **) &(extr->eroute->er_eaddr.sen_ip_src); portp = &(extr->eroute->er_eaddr.sen_sport); extr->eroute->er_eaddr.sen_type = SENT_IP4; } break; case K_SADB_X_EXT_ADDRESS_DST_FLOW: KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_process: " "found dst flow address.\n"); if (pfkey_alloc_eroute(&(extr->eroute)) == ENOMEM) SENDERR(ENOMEM); if (s->sa_family == AF_INET6) { sap = (unsigned char **) &(extr->eroute->er_eaddr.sen_ip6_dst); portp = &(extr->eroute->er_eaddr.sen_dport6); extr->eroute->er_eaddr.sen_type = SENT_IP6; } else { sap = (unsigned char **) &(extr->eroute->er_eaddr.sen_ip_dst); portp = &(extr->eroute->er_eaddr.sen_dport); extr->eroute->er_eaddr.sen_type = SENT_IP4; } break; case K_SADB_X_EXT_ADDRESS_SRC_MASK: KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_process: " "found src mask address.\n"); if (pfkey_alloc_eroute(&(extr->eroute)) == ENOMEM) SENDERR(ENOMEM); if (s->sa_family == AF_INET6) { sap = (unsigned char **) &(extr->eroute->er_emask.sen_ip6_src); portp = &(extr->eroute->er_emask.sen_sport6); extr->eroute->er_eaddr.sen_type = SENT_IP6; } else { sap = (unsigned char **) &(extr->eroute->er_emask.sen_ip_src); portp = &(extr->eroute->er_emask.sen_sport); extr->eroute->er_eaddr.sen_type = SENT_IP4; } break; case K_SADB_X_EXT_ADDRESS_DST_MASK: KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_process: " "found dst mask address.\n"); if (pfkey_alloc_eroute(&(extr->eroute)) == ENOMEM) SENDERR(ENOMEM); if (s->sa_family == AF_INET6) { sap = (unsigned char **) &(extr->eroute->er_emask.sen_ip6_dst); portp = &(extr->eroute->er_emask.sen_dport6); extr->eroute->er_eaddr.sen_type = SENT_IP6; } else { sap = (unsigned char **) &(extr->eroute->er_emask.sen_ip_dst); portp = &(extr->eroute->er_emask.sen_dport); extr->eroute->er_eaddr.sen_type = SENT_IP4; } break; case K_SADB_X_EXT_NAT_T_OA: KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_process: " "found NAT-OA address.\n"); sap = (unsigned char **)&(extr->ips->ips_natt_oa); extr->ips->ips_natt_oa_size = saddr_len; break; default: KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_process: " "unrecognised ext_type=%d.\n", pfkey_address->sadb_address_exttype); SENDERR(EINVAL); } switch (pfkey_address->sadb_address_exttype) { case K_SADB_EXT_ADDRESS_SRC: case K_SADB_EXT_ADDRESS_DST: case K_SADB_EXT_ADDRESS_PROXY: case K_SADB_X_EXT_ADDRESS_DST2: #if 0 case K_SADB_X_EXT_ADDRESS_SRC_FLOW: case K_SADB_X_EXT_ADDRESS_DST_FLOW: case K_SADB_X_EXT_ADDRESS_SRC_MASK: case K_SADB_X_EXT_ADDRESS_DST_MASK: #endif case K_SADB_X_EXT_NAT_T_OA: KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_process: " "allocating %d bytes for saddr.\n", saddr_len); if (!(*sap = kmalloc(saddr_len, GFP_KERNEL))) SENDERR(ENOMEM); memcpy(*sap, s, saddr_len); break; default: if (s->sa_family != AF_INET && s->sa_family != AF_INET6) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_process: " "s->sa_family=%d " "sadb_address_exttype=%d " "not supported.\n", s->sa_family, pfkey_address->sadb_address_exttype); SENDERR(EPFNOSUPPORT); } if (s->sa_family == AF_INET6) { *(struct in6_addr *)sap = ((struct sockaddr_in6 *)s)->sin6_addr; if (portp != 0) *portp = ((struct sockaddr_in6*)s)->sin6_port; } else { *(struct in_addr *)sap = ((struct sockaddr_in *)s)->sin_addr; if (portp != 0) *portp = ((struct sockaddr_in*)s)->sin_port; } if (extr->eroute) { if (debug_pfkey) { char buf1[64], buf2[64]; unsigned short sp, dp; if (extr->eroute->er_eaddr.sen_type == SENT_IP6) { subnet6toa( &extr->eroute->er_eaddr.sen_ip6_src, &extr->eroute->er_emask.sen_ip6_src, 0, buf1, sizeof(buf1)); subnet6toa( &extr->eroute->er_eaddr.sen_ip6_dst, &extr->eroute->er_emask.sen_ip6_dst, 0, buf2, sizeof(buf2)); sp = extr->eroute->er_eaddr.sen_sport6; dp = extr->eroute->er_eaddr.sen_dport6; } else { subnettoa( extr->eroute->er_eaddr.sen_ip_src, extr->eroute->er_emask.sen_ip_src, 0, buf1, sizeof(buf1)); subnettoa( extr->eroute->er_eaddr.sen_ip_dst, extr->eroute->er_emask.sen_ip_dst, 0, buf2, sizeof(buf2)); sp = extr->eroute->er_eaddr.sen_sport; dp = extr->eroute->er_eaddr.sen_dport; } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_parse: " "extr->eroute set to %s:%d->%s:%d\n", buf1, ntohs(sp), buf2, ntohs(dp)); } } } ipsp = extr->ips; switch (pfkey_address->sadb_address_exttype) { case K_SADB_X_EXT_ADDRESS_DST2: ipsp = extr->ips2; case K_SADB_EXT_ADDRESS_DST: if (s->sa_family == AF_INET) { ipsp->ips_said.dst.u.v4.sin_addr.s_addr = ((struct sockaddr_in*)(ipsp->ips_addr_d))-> sin_addr.s_addr; SET_V4(ipsp->ips_said.dst); if (debug_pfkey) sin_addrtot(ipsp->ips_addr_d, 0, ipaddr_txt, sizeof(ipaddr_txt)); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_process: " "ips_said.dst set to %s.\n", ipaddr_txt); } else if (s->sa_family == AF_INET6) { ipsp->ips_said.dst.u.v6.sin6_addr = ((struct sockaddr_in6 *)(ipsp->ips_addr_d))-> sin6_addr; SET_V6(ipsp->ips_said.dst); if (debug_pfkey) sin_addrtot(ipsp->ips_addr_d, 0, ipaddr_txt, sizeof(ipaddr_txt)); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_process: " "ips_said.dst set to %s.\n", ipaddr_txt); } else { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_process: " "uh, ips_said.dst doesn't do address family=%d yet, said will be invalid.\n", s->sa_family); } default: break; } /* XXX check if port!=0 */ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_address_process: successful.\n"); errlab: return error; } int pfkey_key_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr) { int error = 0; struct sadb_key *pfkey_key = (struct sadb_key *)pfkey_ext; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_key_process: .\n"); if (!extr || !extr->ips) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_key_process: " "extr or extr->ips is NULL, fatal\n"); SENDERR(EINVAL); } switch (pfkey_key->sadb_key_exttype) { case K_SADB_EXT_KEY_AUTH: KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_key_process: " "allocating %d bytes for authkey.\n", DIVUP(pfkey_key->sadb_key_bits, 8)); if (!(extr->ips->ips_key_a = kmalloc(DIVUP(pfkey_key->sadb_key_bits, 8), GFP_KERNEL))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_key_process: " "memory allocation error.\n"); SENDERR(ENOMEM); } extr->ips->ips_key_bits_a = pfkey_key->sadb_key_bits; extr->ips->ips_key_a_size = DIVUP(pfkey_key->sadb_key_bits, 8); memcpy(extr->ips->ips_key_a, (char*)pfkey_key + sizeof(struct sadb_key), extr->ips->ips_key_a_size); break; case K_SADB_EXT_KEY_ENCRYPT: /* Key(s) */ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_key_process: " "allocating %d bytes for enckey.\n", DIVUP(pfkey_key->sadb_key_bits, 8)); if (!(extr->ips->ips_key_e = kmalloc(DIVUP(pfkey_key->sadb_key_bits, 8), GFP_KERNEL))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_key_process: " "memory allocation error.\n"); SENDERR(ENOMEM); } extr->ips->ips_key_bits_e = pfkey_key->sadb_key_bits; extr->ips->ips_key_e_size = DIVUP(pfkey_key->sadb_key_bits, 8); memcpy(extr->ips->ips_key_e, (char*)pfkey_key + sizeof(struct sadb_key), extr->ips->ips_key_e_size); break; default: SENDERR(EINVAL); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_key_process: " "success.\n"); errlab: return error; } int pfkey_ident_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr) { int error = 0; struct sadb_ident *pfkey_ident = (struct sadb_ident *)pfkey_ext; int data_len; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_ident_process: .\n"); if (!extr || !extr->ips) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_ident_process: " "extr or extr->ips is NULL, fatal\n"); SENDERR(EINVAL); } switch (pfkey_ident->sadb_ident_exttype) { case K_SADB_EXT_IDENTITY_SRC: data_len = pfkey_ident->sadb_ident_len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident); extr->ips->ips_ident_s.type = pfkey_ident->sadb_ident_type; extr->ips->ips_ident_s.id = pfkey_ident->sadb_ident_id; extr->ips->ips_ident_s.len = pfkey_ident->sadb_ident_len; if (data_len) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_ident_process: " "allocating %d bytes for ident_s.\n", data_len); if (!(extr->ips->ips_ident_s.data = kmalloc(data_len, GFP_KERNEL))) SENDERR(ENOMEM); memcpy(extr->ips->ips_ident_s.data, (char*)pfkey_ident + sizeof(struct sadb_ident), data_len); } else { extr->ips->ips_ident_s.data = NULL; } break; case K_SADB_EXT_IDENTITY_DST: /* Identity(ies) */ data_len = pfkey_ident->sadb_ident_len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident); extr->ips->ips_ident_d.type = pfkey_ident->sadb_ident_type; extr->ips->ips_ident_d.id = pfkey_ident->sadb_ident_id; extr->ips->ips_ident_d.len = pfkey_ident->sadb_ident_len; if (data_len) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_ident_process: " "allocating %d bytes for ident_d.\n", data_len); if (!(extr->ips->ips_ident_d.data = kmalloc(data_len, GFP_KERNEL))) SENDERR(ENOMEM); memcpy(extr->ips->ips_ident_d.data, (char*)pfkey_ident + sizeof(struct sadb_ident), data_len); } else { extr->ips->ips_ident_d.data = NULL; } break; default: SENDERR(EINVAL); } errlab: return error; } int pfkey_sens_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr) { int error = 0; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sens_process: " "Sorry, I can't process exttype=%d yet.\n", pfkey_ext->sadb_ext_type); SENDERR(EINVAL); /* don't process these yet */ errlab: return error; } int pfkey_prop_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr) { int error = 0; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_prop_process: " "Sorry, I can't process exttype=%d yet.\n", pfkey_ext->sadb_ext_type); SENDERR(EINVAL); /* don't process these yet */ errlab: return error; } int pfkey_supported_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr) { int error = 0; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_supported_process: " "Sorry, I can't process exttype=%d yet.\n", pfkey_ext->sadb_ext_type); SENDERR(EINVAL); /* don't process these yet */ errlab: return error; } int pfkey_spirange_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr) { int error = 0; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_spirange_process: .\n"); /* errlab: */ return error; } int pfkey_x_kmprivate_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr) { int error = 0; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_kmprivate_process: " "Sorry, I can't process exttype=%d yet.\n", pfkey_ext->sadb_ext_type); SENDERR(EINVAL); /* don't process these yet */ errlab: return error; } int pfkey_x_satype_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr) { int error = 0; struct sadb_x_satype *pfkey_x_satype = (struct sadb_x_satype *)pfkey_ext; KLIPS_PRINT(debug_pfkey, "pfkey_x_satype_process: .\n"); if (!extr || !extr->ips) { KLIPS_PRINT(debug_pfkey, "pfkey_x_satype_process: " "extr or extr->ips is NULL, fatal\n"); SENDERR(EINVAL); } if (extr->ips2 == NULL) extr->ips2 = ipsec_sa_alloc(&error); /* pass error var by pointer */ if (extr->ips2 == NULL) SENDERR(-error); if (!(extr->ips2->ips_said.proto = satype2proto(pfkey_x_satype->sadb_x_satype_satype))) { KLIPS_ERROR(debug_pfkey, "pfkey_x_satype_process: " "proto lookup from satype=%d failed.\n", pfkey_x_satype->sadb_x_satype_satype); SENDERR(EINVAL); } KLIPS_PRINT(debug_pfkey, "pfkey_x_satype_process: " "protocol==%d decoded from satype==%d(%s).\n", extr->ips2->ips_said.proto, pfkey_x_satype->sadb_x_satype_satype, satype2name(pfkey_x_satype->sadb_x_satype_satype)); errlab: return error; } int pfkey_x_nat_t_type_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr) { int error = 0; struct sadb_x_nat_t_type *pfkey_x_nat_t_type = (struct sadb_x_nat_t_type *)pfkey_ext; if (!pfkey_x_nat_t_type) { printk("klips_debug:pfkey_x_nat_t_type_process: " "null pointer passed in\n"); SENDERR(EINVAL); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_nat_t_type_process: %d.\n", pfkey_x_nat_t_type->sadb_x_nat_t_type_type); if (!extr || !extr->ips) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_type_process: " "extr or extr->ips is NULL, fatal\n"); SENDERR(EINVAL); } switch (pfkey_x_nat_t_type->sadb_x_nat_t_type_type) { case ESPINUDP_WITH_NON_IKE: /* with Non-IKE (older version) */ case ESPINUDP_WITH_NON_ESP: /* with Non-ESP */ extr->ips->ips_natt_type = pfkey_x_nat_t_type->sadb_x_nat_t_type_type; break; default: KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_nat_t_type_process: " "unknown type %d.\n", pfkey_x_nat_t_type->sadb_x_nat_t_type_type); SENDERR(EINVAL); break; } errlab: return error; } int pfkey_x_nat_t_port_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr) { int error = 0; struct sadb_x_nat_t_port *pfkey_x_nat_t_port = (struct sadb_x_nat_t_port *)pfkey_ext; if (!pfkey_x_nat_t_port) { printk("klips_debug:pfkey_x_nat_t_port_process: " "null pointer passed in\n"); SENDERR(EINVAL); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_nat_t_port_process: %d/%d.\n", pfkey_x_nat_t_port->sadb_x_nat_t_port_exttype, pfkey_x_nat_t_port->sadb_x_nat_t_port_port); if (!extr || !extr->ips) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_type_process: " "extr or extr->ips is NULL, fatal\n"); SENDERR(EINVAL); } switch (pfkey_x_nat_t_port->sadb_x_nat_t_port_exttype) { case K_SADB_X_EXT_NAT_T_SPORT: extr->ips->ips_natt_sport = pfkey_x_nat_t_port->sadb_x_nat_t_port_port; break; case K_SADB_X_EXT_NAT_T_DPORT: extr->ips->ips_natt_dport = pfkey_x_nat_t_port->sadb_x_nat_t_port_port; break; default: KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_nat_t_port_process: " "unknown exttype %d.\n", pfkey_x_nat_t_port->sadb_x_nat_t_port_exttype); SENDERR(EINVAL); break; } errlab: return error; } int pfkey_x_debug_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr) { int error = 0; struct sadb_x_debug *pfkey_x_debug = (struct sadb_x_debug *)pfkey_ext; if (!pfkey_x_debug) { printk("klips_debug:pfkey_x_debug_process: " "null pointer passed in\n"); SENDERR(EINVAL); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_debug_process: .\n"); if (pfkey_x_debug->sadb_x_debug_netlink >> (sizeof(pfkey_x_debug->sadb_x_debug_netlink) * 8 - 1)) { pfkey_x_debug->sadb_x_debug_netlink &= ~(1 << (sizeof(pfkey_x_debug->sadb_x_debug_netlink) * 8 - 1)); debug_tunnel |= pfkey_x_debug->sadb_x_debug_tunnel; debug_netlink |= pfkey_x_debug->sadb_x_debug_netlink; debug_xform |= pfkey_x_debug->sadb_x_debug_xform; debug_eroute |= pfkey_x_debug->sadb_x_debug_eroute; debug_spi |= pfkey_x_debug->sadb_x_debug_spi; debug_radij |= pfkey_x_debug->sadb_x_debug_radij; debug_esp |= pfkey_x_debug->sadb_x_debug_esp; debug_ah |= pfkey_x_debug->sadb_x_debug_ah; debug_rcv |= pfkey_x_debug->sadb_x_debug_rcv; debug_pfkey |= pfkey_x_debug->sadb_x_debug_pfkey; #ifdef CONFIG_KLIPS_IPCOMP sysctl_ipsec_debug_ipcomp |= pfkey_x_debug->sadb_x_debug_ipcomp; #endif /* CONFIG_KLIPS_IPCOMP */ sysctl_ipsec_debug_verbose |= pfkey_x_debug->sadb_x_debug_verbose; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_debug_process: " "set\n"); } else { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_debug_process: " "unset\n"); debug_tunnel &= pfkey_x_debug->sadb_x_debug_tunnel; debug_netlink &= pfkey_x_debug->sadb_x_debug_netlink; debug_xform &= pfkey_x_debug->sadb_x_debug_xform; debug_eroute &= pfkey_x_debug->sadb_x_debug_eroute; debug_spi &= pfkey_x_debug->sadb_x_debug_spi; debug_radij &= pfkey_x_debug->sadb_x_debug_radij; debug_esp &= pfkey_x_debug->sadb_x_debug_esp; debug_ah &= pfkey_x_debug->sadb_x_debug_ah; debug_rcv &= pfkey_x_debug->sadb_x_debug_rcv; debug_pfkey &= pfkey_x_debug->sadb_x_debug_pfkey; #ifdef CONFIG_KLIPS_IPCOMP sysctl_ipsec_debug_ipcomp &= pfkey_x_debug->sadb_x_debug_ipcomp; #endif /* CONFIG_KLIPS_IPCOMP */ sysctl_ipsec_debug_verbose &= pfkey_x_debug->sadb_x_debug_verbose; } errlab: return error; } libreswan-3.32/linux/net/ipsec/pfkey_v2_parse.c000066400000000000000000001326641365625662500215760ustar00rootroot00000000000000/* * RFC2367 PF_KEYv2 Key management API message parser * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs. * Copyright (C) 2012 Paul Wouters * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ /* * Template from klips/net/ipsec/ipsec/ipsec_parser.c. */ /* * Some ugly stuff to allow consistent debugging code for use in the * kernel and in user space */ #ifdef __KERNEL__ # include /* for printk */ # include "libreswan/ipsec_kversion.h" /* for malloc switch */ # include /* kmalloc() */ # include /* error codes */ # include /* size_t */ # include /* mark_bh */ # include /* struct device, and other headers */ # include /* eth_type_trans */ # include /* struct iphdr */ # if defined(CONFIG_KLIPS_IPV6) # include /* struct ipv6hdr */ # endif /* if defined(CONFIG_KLIPS_IPV6) */ extern int debug_pfkey; # include #include "libreswan/ipsec_encap.h" #else /* __KERNEL__ */ # include # include # include # include # include "constants.h" #endif /* __KERNEL__ */ #include #include #include "libreswan/ipsec_sa.h" /* IPSEC_SAREF_NULL, IPSEC_SA_REF_TABLE_IDX_WIDTH */ /* * how to handle debugging for pfkey. */ #include unsigned int pfkey_lib_debug = PF_KEY_DEBUG_PARSE_NONE; libreswan_keying_debug_func_t pfkey_debug_func = NULL; libreswan_keying_debug_func_t pfkey_error_func = NULL; #define SENDERR(_x) do { error = -(_x); goto errlab; } while (0) static struct satype_tbl { uint8_t proto; uint8_t satype; char *name; } satype_tbl[] = { #ifdef __KERNEL__ { IPPROTO_ESP, K_SADB_SATYPE_ESP, "ESP" }, { IPPROTO_AH, K_SADB_SATYPE_AH, "AH" }, { IPPROTO_IPIP, K_SADB_X_SATYPE_IPIP, "IPIP" }, #ifdef CONFIG_KLIPS_IPCOMP { IPPROTO_COMP, K_SADB_X_SATYPE_COMP, "COMP" }, #endif /* CONFIG_KLIPS_IPCOMP */ { IPPROTO_INT, K_SADB_X_SATYPE_INT, "INT" }, #else /* __KERNEL__ */ { SA_ESP, K_SADB_SATYPE_ESP, "ESP" }, { SA_AH, K_SADB_SATYPE_AH, "AH" }, { SA_IPIP, K_SADB_X_SATYPE_IPIP, "IPIP" }, { SA_COMP, K_SADB_X_SATYPE_COMP, "COMP" }, { SA_INT, K_SADB_X_SATYPE_INT, "INT" }, #endif /* __KERNEL__ */ { 0, 0, "UNKNOWN" } }; uint8_t satype2proto(uint8_t satype) { int i = 0; while (satype_tbl[i].satype != satype && satype_tbl[i].satype != 0) i++; return satype_tbl[i].proto; } uint8_t proto2satype(uint8_t proto) { int i = 0; while (satype_tbl[i].proto != proto && satype_tbl[i].proto != 0) i++; return satype_tbl[i].satype; } char *satype2name(uint8_t satype) { int i = 0; while (satype_tbl[i].satype != satype && satype_tbl[i].satype != 0) i++; return satype_tbl[i].name; } /* Default extension parsers taken from the KLIPS code */ DEBUG_NO_STATIC int pfkey_sa_parse(struct sadb_ext *pfkey_ext) { int error = 0; struct k_sadb_sa *pfkey_sa = (struct k_sadb_sa *)pfkey_ext; /* sanity checks... */ if (!pfkey_sa) { ERROR("pfkey_sa_parse: " "NULL pointer passed in.\n"); SENDERR(EINVAL); } if (pfkey_sa->sadb_sa_len != sizeof(struct k_sadb_sa) / IPSEC_PFKEYv2_ALIGN && pfkey_sa->sadb_sa_len != sizeof(struct sadb_sa) / IPSEC_PFKEYv2_ALIGN) { ERROR("pfkey_sa_parse: " "size wrong pfkey_sa->sadb_sa_len=%d sizeof(struct sadb_sa)=%d.\n", pfkey_sa->sadb_sa_len, (int)sizeof(struct k_sadb_sa)); SENDERR(EINVAL); } #if K_SADB_EALG_MAX < 255 /* probably to silence a gcc warning */ if (pfkey_sa->sadb_sa_encrypt > K_SADB_EALG_MAX) { ERROR("pfkey_sa_parse: " "pfkey_sa->sadb_sa_encrypt=%d > K_SADB_EALG_MAX=%d.\n", pfkey_sa->sadb_sa_encrypt, K_SADB_EALG_MAX); SENDERR(EINVAL); } #endif #if K_SADB_AALG_MAX < 255 if (pfkey_sa->sadb_sa_auth > K_SADB_AALG_MAX) { ERROR("pfkey_sa_parse: " "pfkey_sa->sadb_sa_auth=%d > K_SADB_AALG_MAX=%d.\n", pfkey_sa->sadb_sa_auth, K_SADB_AALG_MAX); SENDERR(EINVAL); } #endif #if K_SADB_SASTATE_MAX < 255 if (pfkey_sa->sadb_sa_state > K_SADB_SASTATE_MAX) { ERROR("pfkey_sa_parse: " "state=%d exceeds MAX=%d.\n", pfkey_sa->sadb_sa_state, K_SADB_SASTATE_MAX); SENDERR(EINVAL); } #endif if (pfkey_sa->sadb_sa_state == K_SADB_SASTATE_DEAD) { ERROR("pfkey_sa_parse: " "state=%d is DEAD=%d.\n", pfkey_sa->sadb_sa_state, K_SADB_SASTATE_DEAD); SENDERR(EINVAL); } if (pfkey_sa->sadb_sa_replay > 64) { ERROR("pfkey_sa_parse: " "replay window size: %d -- must be 0 <= size <= 64\n", pfkey_sa->sadb_sa_replay); SENDERR(EINVAL); } if (pfkey_sa->sadb_sa_exttype != K_SADB_EXT_SA && pfkey_sa->sadb_sa_exttype != K_SADB_X_EXT_SA2) { ERROR("pfkey_sa_parse: " "unknown exttype=%d, expecting K_SADB_EXT_SA=%d or K_SADB_X_EXT_SA2=%d.\n", pfkey_sa->sadb_sa_exttype, K_SADB_EXT_SA, K_SADB_X_EXT_SA2); SENDERR(EINVAL); } if (pfkey_sa->sadb_sa_len > sizeof(struct sadb_sa) / IPSEC_PFKEYv2_ALIGN) { if (pfkey_sa->sadb_x_sa_ref == IPSEC_SAREF_NULL || pfkey_sa->sadb_x_sa_ref == ~IPSEC_SAREF_NULL) pfkey_sa->sadb_x_sa_ref = IPSEC_SAREF_NULL; } if (IPSEC_SAREF_NULL != pfkey_sa->sadb_x_sa_ref && pfkey_sa->sadb_x_sa_ref >= (1 << IPSEC_SA_REF_TABLE_IDX_WIDTH)) { ERROR("pfkey_sa_parse: " "SAref=%d must be (SAref == IPSEC_SAREF_NULL(%d) || SAref < IPSEC_SA_REF_TABLE_NUM_ENTRIES(%d)).\n", pfkey_sa->sadb_x_sa_ref, IPSEC_SAREF_NULL, IPSEC_SA_REF_TABLE_NUM_ENTRIES); SENDERR(EINVAL); } DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, "pfkey_sa_parse: " "successfully found len=%d exttype=%d(%s) spi=%08lx replay=%d state=%d auth=%d encrypt=%d flags=%d ref=%d.\n", pfkey_sa->sadb_sa_len, pfkey_sa->sadb_sa_exttype, pfkey_v2_sadb_ext_string(pfkey_sa->sadb_sa_exttype), (long unsigned int)ntohl(pfkey_sa->sadb_sa_spi), pfkey_sa->sadb_sa_replay, pfkey_sa->sadb_sa_state, pfkey_sa->sadb_sa_auth, pfkey_sa->sadb_sa_encrypt, pfkey_sa->sadb_sa_flags, pfkey_sa->sadb_x_sa_ref); errlab: return error; } DEBUG_NO_STATIC int pfkey_lifetime_parse(struct sadb_ext *pfkey_ext) { int error = 0; struct sadb_lifetime *pfkey_lifetime = (struct sadb_lifetime *)pfkey_ext; DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW, "pfkey_lifetime_parse:enter\n"); /* sanity checks... */ if (!pfkey_lifetime) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_lifetime_parse: " "NULL pointer passed in.\n"); SENDERR(EINVAL); } if (pfkey_lifetime->sadb_lifetime_len != sizeof(struct sadb_lifetime) / IPSEC_PFKEYv2_ALIGN) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_lifetime_parse: " "size wrong pfkey_lifetime->sadb_lifetime_len=%d (*sizeof(u64)=%zu) sizeof(struct sadb_lifetime)=%d.\n", pfkey_lifetime->sadb_lifetime_len, pfkey_lifetime->sadb_lifetime_len * IPSEC_PFKEYv2_ALIGN, (int)sizeof(struct sadb_lifetime)); SENDERR(EINVAL); } switch (pfkey_lifetime->sadb_lifetime_exttype) { case K_SADB_EXT_LIFETIME_HARD: case K_SADB_EXT_LIFETIME_SOFT: case K_SADB_EXT_LIFETIME_CURRENT: break; /* OK */ default: DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_lifetime_parse: " "unexpected ext_type=%d.\n", pfkey_lifetime->sadb_lifetime_exttype); SENDERR(EINVAL); } DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, "pfkey_lifetime_parse: " "life_type=%d(%s) alloc=%u bytes=%u add=%u use=%u.\n", pfkey_lifetime->sadb_lifetime_exttype, pfkey_v2_sadb_ext_string(pfkey_lifetime-> sadb_lifetime_exttype), pfkey_lifetime->sadb_lifetime_allocations, (unsigned)pfkey_lifetime->sadb_lifetime_bytes, (unsigned)pfkey_lifetime->sadb_lifetime_addtime, (unsigned)pfkey_lifetime->sadb_lifetime_usetime); errlab: return error; } DEBUG_NO_STATIC int pfkey_address_parse(struct sadb_ext *pfkey_ext) { int error = 0; int saddr_len = 0; struct sadb_address *pfkey_address = (struct sadb_address *)pfkey_ext; struct sockaddr *s = (struct sockaddr*)((char*)pfkey_address + sizeof(*pfkey_address)); char ipaddr_txt[ADDRTOT_BUF]; /* sanity checks... */ if (!pfkey_address) { ERROR("pfkey_address_parse: " "NULL pointer passed in.\n"); SENDERR(EINVAL); } if (pfkey_address->sadb_address_len < (sizeof(struct sadb_address) + sizeof(struct sockaddr)) / IPSEC_PFKEYv2_ALIGN) { ERROR("pfkey_address_parse: " "size wrong 1 ext_len=%d, adr_ext_len=%d, saddr_len=%d.\n", pfkey_address->sadb_address_len, (int)sizeof(struct sadb_address), (int)sizeof(struct sockaddr)); SENDERR(EINVAL); } if (pfkey_address->sadb_address_reserved) { ERROR("pfkey_address_parse: " "res=%d, must be zero.\n", pfkey_address->sadb_address_reserved); SENDERR(EINVAL); } switch (pfkey_address->sadb_address_exttype) { case K_SADB_EXT_ADDRESS_SRC: case K_SADB_EXT_ADDRESS_DST: case K_SADB_EXT_ADDRESS_PROXY: case K_SADB_X_EXT_ADDRESS_DST2: case K_SADB_X_EXT_ADDRESS_SRC_FLOW: case K_SADB_X_EXT_ADDRESS_DST_FLOW: case K_SADB_X_EXT_ADDRESS_SRC_MASK: case K_SADB_X_EXT_ADDRESS_DST_MASK: case K_SADB_X_EXT_NAT_T_OA: break; default: ERROR("pfkey_address_parse: " "unexpected ext_type=%d.\n", pfkey_address->sadb_address_exttype); SENDERR(ENODEV); } switch (s->sa_family) { case AF_INET: saddr_len = sizeof(struct sockaddr_in); sin_addrtot(s, 0, ipaddr_txt, sizeof(ipaddr_txt)); DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, "pfkey_address_parse: " "found exttype=%u(%s) family=%d(AF_INET) address=%s proto=%u port=%u.\n", pfkey_address->sadb_address_exttype, pfkey_v2_sadb_ext_string(pfkey_address-> sadb_address_exttype), s->sa_family, ipaddr_txt, pfkey_address->sadb_address_proto, ntohs(((struct sockaddr_in*)s)->sin_port)); break; case AF_INET6: saddr_len = sizeof(struct sockaddr_in6); sin_addrtot(s, 0, ipaddr_txt, sizeof(ipaddr_txt)); DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, "pfkey_address_parse: " "found exttype=%u(%s) family=%d(AF_INET6) address=%s proto=%u port=%u.\n", pfkey_address->sadb_address_exttype, pfkey_v2_sadb_ext_string(pfkey_address-> sadb_address_exttype), s->sa_family, ipaddr_txt, pfkey_address->sadb_address_proto, ((struct sockaddr_in6*)s)->sin6_port); break; default: ERROR("pfkey_address_parse: " "s->sa_family=%d not supported.\n", s->sa_family); SENDERR(EPFNOSUPPORT); } if (pfkey_address->sadb_address_len != DIVUP(sizeof(struct sadb_address) + saddr_len, IPSEC_PFKEYv2_ALIGN)) { ERROR("pfkey_address_parse: " "size wrong 2 ext_len=%d, adr_ext_len=%d, saddr_len=%d.\n", pfkey_address->sadb_address_len, (int)sizeof(struct sadb_address), saddr_len); SENDERR(EINVAL); } if (pfkey_address->sadb_address_prefixlen != 0) { ERROR("pfkey_address_parse: " "address prefixes not supported yet.\n"); SENDERR(EAFNOSUPPORT); /* not supported yet */ } /* XXX check if port!=0 */ DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW, "pfkey_address_parse: successful.\n"); errlab: return error; } DEBUG_NO_STATIC int pfkey_key_parse(struct sadb_ext *pfkey_ext) { int error = 0; struct sadb_key *pfkey_key = (struct sadb_key *)pfkey_ext; /* sanity checks... */ if (!pfkey_key) { ERROR("pfkey_key_parse: " "NULL pointer passed in.\n"); SENDERR(EINVAL); } if (pfkey_key->sadb_key_len < sizeof(struct sadb_key) / IPSEC_PFKEYv2_ALIGN) { ERROR("pfkey_key_parse: " "size wrong ext_len=%d, key_ext_len=%d.\n", pfkey_key->sadb_key_len, (int)sizeof(struct sadb_key)); SENDERR(EINVAL); } if (!pfkey_key->sadb_key_bits) { ERROR("pfkey_key_parse: " "key length set to zero, must be non-zero.\n"); SENDERR(EINVAL); } if (pfkey_key->sadb_key_len != DIVUP(sizeof(struct sadb_key) * OCTETBITS + pfkey_key->sadb_key_bits, PFKEYBITS)) { ERROR("pfkey_key_parse: " "key length=%d does not agree with extension length=%d.\n", pfkey_key->sadb_key_bits, pfkey_key->sadb_key_len); SENDERR(EINVAL); } if (pfkey_key->sadb_key_reserved) { ERROR("pfkey_key_parse: " "res=%d, must be zero.\n", pfkey_key->sadb_key_reserved); SENDERR(EINVAL); } if (!( (pfkey_key->sadb_key_exttype == K_SADB_EXT_KEY_AUTH) || (pfkey_key->sadb_key_exttype == K_SADB_EXT_KEY_ENCRYPT))) { ERROR("pfkey_key_parse: " "expecting extension type AUTH or ENCRYPT, got %d.\n", pfkey_key->sadb_key_exttype); SENDERR(EINVAL); } DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, "pfkey_key_parse: " "success, found len=%d exttype=%d(%s) bits=%d reserved=%d.\n", pfkey_key->sadb_key_len, pfkey_key->sadb_key_exttype, pfkey_v2_sadb_ext_string(pfkey_key->sadb_key_exttype), pfkey_key->sadb_key_bits, pfkey_key->sadb_key_reserved); errlab: return error; } DEBUG_NO_STATIC int pfkey_ident_parse(struct sadb_ext *pfkey_ext) { int error = 0; struct sadb_ident *pfkey_ident = (struct sadb_ident *)pfkey_ext; /* sanity checks... */ if (pfkey_ident->sadb_ident_len < sizeof(struct sadb_ident) / IPSEC_PFKEYv2_ALIGN) { ERROR("pfkey_ident_parse: " "size wrong ext_len=%d, key_ext_len=%d.\n", pfkey_ident->sadb_ident_len, (int)sizeof(struct sadb_ident)); SENDERR(EINVAL); } if (pfkey_ident->sadb_ident_type > K_SADB_IDENTTYPE_MAX) { ERROR("pfkey_ident_parse: " "ident_type=%d out of range, must be less than %d.\n", pfkey_ident->sadb_ident_type, K_SADB_IDENTTYPE_MAX); SENDERR(EINVAL); } if (pfkey_ident->sadb_ident_reserved) { ERROR("pfkey_ident_parse: " "res=%d, must be zero.\n", pfkey_ident->sadb_ident_reserved); SENDERR(EINVAL); } /* string terminator/padding must be zero */ if (pfkey_ident->sadb_ident_len > sizeof(struct sadb_ident) / IPSEC_PFKEYv2_ALIGN) { if (*((char*)pfkey_ident + pfkey_ident->sadb_ident_len * IPSEC_PFKEYv2_ALIGN - 1)) { ERROR("pfkey_ident_parse: " "string padding must be zero, last is 0x%02x.\n", *((char*)pfkey_ident + pfkey_ident->sadb_ident_len * IPSEC_PFKEYv2_ALIGN - 1)); SENDERR(EINVAL); } } if ( !((pfkey_ident->sadb_ident_exttype == K_SADB_EXT_IDENTITY_SRC) || (pfkey_ident->sadb_ident_exttype == K_SADB_EXT_IDENTITY_DST))) { ERROR("pfkey_key_parse: " "expecting extension type IDENTITY_SRC or IDENTITY_DST, got %d.\n", pfkey_ident->sadb_ident_exttype); SENDERR(EINVAL); } errlab: return error; } DEBUG_NO_STATIC int pfkey_sens_parse(struct sadb_ext *pfkey_ext) { int error = 0; struct sadb_sens *pfkey_sens = (struct sadb_sens *)pfkey_ext; /* sanity checks... */ if (pfkey_sens->sadb_sens_len < sizeof(struct sadb_sens) / IPSEC_PFKEYv2_ALIGN) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_sens_parse: " "size wrong ext_len=%d, key_ext_len=%d.\n", pfkey_sens->sadb_sens_len, (int)sizeof(struct sadb_sens)); SENDERR(EINVAL); } DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_sens_parse: " "Sorry, I can't parse exttype=%d yet.\n", pfkey_ext->sadb_ext_type); #if 0 SENDERR(EINVAL); /* don't process these yet */ #endif errlab: return error; } DEBUG_NO_STATIC int pfkey_prop_parse(struct sadb_ext *pfkey_ext) { int error = 0; int i, num_comb; struct sadb_prop *pfkey_prop = (struct sadb_prop *)pfkey_ext; struct k_sadb_comb *k_pfkey_comb = (struct k_sadb_comb *) ((char*)pfkey_ext + sizeof(struct sadb_prop)); /* sanity checks... */ if ((pfkey_prop->sadb_prop_len < sizeof(struct sadb_prop) / IPSEC_PFKEYv2_ALIGN) || (((pfkey_prop->sadb_prop_len * IPSEC_PFKEYv2_ALIGN) - sizeof(struct sadb_prop)) % sizeof(struct sadb_comb))) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_prop_parse: " "size wrong ext_len=%d, prop_ext_len=%d comb_ext_len=%d.\n", pfkey_prop->sadb_prop_len, (int)sizeof(struct sadb_prop), (int)sizeof(struct sadb_comb)); SENDERR(EINVAL); } if (pfkey_prop->sadb_prop_replay > 64) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_prop_parse: " "replay window size: %d -- must be 0 <= size <= 64\n", pfkey_prop->sadb_prop_replay); SENDERR(EINVAL); } for (i = 0; i < 3; i++) { if (pfkey_prop->sadb_prop_reserved[i]) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_prop_parse: " "res[%d]=%d, must be zero.\n", i, pfkey_prop->sadb_prop_reserved[i]); SENDERR(EINVAL); } } num_comb = ((pfkey_prop->sadb_prop_len * IPSEC_PFKEYv2_ALIGN) - sizeof(struct sadb_prop)) / sizeof(struct sadb_comb); for (i = 0; i < num_comb; i++) { struct sadb_comb *pfkey_comb = (struct sadb_comb *)k_pfkey_comb; #if K_SADB_AALG_MAX < 255 if (pfkey_comb->sadb_comb_auth > K_SADB_AALG_MAX) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_prop_parse: " "pfkey_comb[%d]->sadb_comb_auth=%d > K_SADB_AALG_MAX=%d.\n", i, pfkey_comb->sadb_comb_auth, K_SADB_AALG_MAX); SENDERR(EINVAL); } #endif if (pfkey_comb->sadb_comb_auth) { if (!pfkey_comb->sadb_comb_auth_minbits) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_prop_parse: " "pfkey_comb[%d]->sadb_comb_auth_minbits=0, fatal.\n", i); SENDERR(EINVAL); } if (!pfkey_comb->sadb_comb_auth_maxbits) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_prop_parse: " "pfkey_comb[%d]->sadb_comb_auth_maxbits=0, fatal.\n", i); SENDERR(EINVAL); } if (pfkey_comb->sadb_comb_auth_minbits > pfkey_comb->sadb_comb_auth_maxbits) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_prop_parse: " "pfkey_comb[%d]->sadb_comb_auth_minbits=%d > maxbits=%d, fatal.\n", i, pfkey_comb->sadb_comb_auth_minbits, pfkey_comb->sadb_comb_auth_maxbits); SENDERR(EINVAL); } } else { if (pfkey_comb->sadb_comb_auth_minbits) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_prop_parse: " "pfkey_comb[%d]->sadb_comb_auth_minbits=%d != 0, fatal.\n", i, pfkey_comb->sadb_comb_auth_minbits); SENDERR(EINVAL); } if (pfkey_comb->sadb_comb_auth_maxbits) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_prop_parse: " "pfkey_comb[%d]->sadb_comb_auth_maxbits=%d != 0, fatal.\n", i, pfkey_comb->sadb_comb_auth_maxbits); SENDERR(EINVAL); } } #if K_SADB_EALG_MAX < 255 if (pfkey_comb->sadb_comb_encrypt > K_SADB_EALG_MAX) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_comb_parse: " "pfkey_comb[%d]->sadb_comb_encrypt=%d > K_SADB_EALG_MAX=%d.\n", i, pfkey_comb->sadb_comb_encrypt, K_SADB_EALG_MAX); SENDERR(EINVAL); } #endif if (pfkey_comb->sadb_comb_encrypt) { if (!pfkey_comb->sadb_comb_encrypt_minbits) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_prop_parse: " "pfkey_comb[%d]->sadb_comb_encrypt_minbits=0, fatal.\n", i); SENDERR(EINVAL); } if (!pfkey_comb->sadb_comb_encrypt_maxbits) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_prop_parse: " "pfkey_comb[%d]->sadb_comb_encrypt_maxbits=0, fatal.\n", i); SENDERR(EINVAL); } if (pfkey_comb->sadb_comb_encrypt_minbits > pfkey_comb->sadb_comb_encrypt_maxbits) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_prop_parse: " "pfkey_comb[%d]->sadb_comb_encrypt_minbits=%d > maxbits=%d, fatal.\n", i, pfkey_comb->sadb_comb_encrypt_minbits, pfkey_comb->sadb_comb_encrypt_maxbits); SENDERR(EINVAL); } } else { if (pfkey_comb->sadb_comb_encrypt_minbits) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_prop_parse: " "pfkey_comb[%d]->sadb_comb_encrypt_minbits=%d != 0, fatal.\n", i, pfkey_comb->sadb_comb_encrypt_minbits); SENDERR(EINVAL); } if (pfkey_comb->sadb_comb_encrypt_maxbits) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_prop_parse: " "pfkey_comb[%d]->sadb_comb_encrypt_maxbits=%d != 0, fatal.\n", i, pfkey_comb->sadb_comb_encrypt_maxbits); SENDERR(EINVAL); } } /* XXX do sanity check on flags */ if (pfkey_comb->sadb_comb_hard_allocations && pfkey_comb->sadb_comb_soft_allocations > pfkey_comb->sadb_comb_hard_allocations) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_prop_parse: " "pfkey_comb[%d]->sadb_comb_soft_allocations=%d > hard_allocations=%d, fatal.\n", i, pfkey_comb->sadb_comb_soft_allocations, pfkey_comb->sadb_comb_hard_allocations); SENDERR(EINVAL); } if (pfkey_comb->sadb_comb_hard_bytes && pfkey_comb->sadb_comb_soft_bytes > pfkey_comb->sadb_comb_hard_bytes) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_prop_parse: " "pfkey_comb[%d]->sadb_comb_soft_bytes=%Ld > hard_bytes=%Ld, fatal.\n", i, (unsigned long long int)pfkey_comb->sadb_comb_soft_bytes, (unsigned long long int)pfkey_comb->sadb_comb_hard_bytes); SENDERR(EINVAL); } if (pfkey_comb->sadb_comb_hard_addtime && pfkey_comb->sadb_comb_soft_addtime > pfkey_comb->sadb_comb_hard_addtime) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_prop_parse: " "pfkey_comb[%d]->sadb_comb_soft_addtime=%Ld > hard_addtime=%Ld, fatal.\n", i, (unsigned long long int)pfkey_comb->sadb_comb_soft_addtime, (unsigned long long int)pfkey_comb->sadb_comb_hard_addtime); SENDERR(EINVAL); } if (pfkey_comb->sadb_comb_hard_usetime && pfkey_comb->sadb_comb_soft_usetime > pfkey_comb->sadb_comb_hard_usetime) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_prop_parse: " "pfkey_comb[%d]->sadb_comb_soft_usetime=%Ld > hard_usetime=%Ld, fatal.\n", i, (unsigned long long int)pfkey_comb->sadb_comb_soft_usetime, (unsigned long long int)pfkey_comb->sadb_comb_hard_usetime); SENDERR(EINVAL); } #ifdef COMB_PACKETS if (pfkey_comb->sadb_x_comb_hard_packets && pfkey_comb->sadb_x_comb_soft_packets > pfkey_comb->sadb_x_comb_hard_packets) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_prop_parse: " "pfkey_comb[%d]->sadb_x_comb_soft_packets=%d > hard_packets=%d, fatal.\n", i, k_pfkey_comb->sadb_x_comb_soft_packets, k_pfkey_comb->sadb_x_comb_hard_packets); SENDERR(EINVAL); } #endif pfkey_comb++; } errlab: return error; } DEBUG_NO_STATIC int pfkey_supported_parse(struct sadb_ext *pfkey_ext) { int error = 0; unsigned int i, num_alg; struct sadb_supported *pfkey_supported = (struct sadb_supported *)pfkey_ext; struct sadb_alg *pfkey_alg = (struct sadb_alg*) ((char*)pfkey_ext + sizeof(struct sadb_supported)); /* sanity checks... */ if ((pfkey_supported->sadb_supported_len < sizeof(struct sadb_supported) / IPSEC_PFKEYv2_ALIGN) || (((pfkey_supported->sadb_supported_len * IPSEC_PFKEYv2_ALIGN) - sizeof(struct sadb_supported)) % sizeof(struct sadb_alg))) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_supported_parse: " "size wrong ext_len=%d, supported_ext_len=%d alg_ext_len=%d.\n", pfkey_supported->sadb_supported_len, (int)sizeof(struct sadb_supported), (int)sizeof(struct sadb_alg)); SENDERR(EINVAL); } if (pfkey_supported->sadb_supported_reserved) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_supported_parse: " "res=%d, must be zero.\n", pfkey_supported->sadb_supported_reserved); SENDERR(EINVAL); } num_alg = ((pfkey_supported->sadb_supported_len * IPSEC_PFKEYv2_ALIGN) - sizeof(struct sadb_supported)) / sizeof(struct sadb_alg); for (i = 0; i < num_alg; i++) { /* process algo description */ if (pfkey_alg->sadb_alg_reserved) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_supported_parse: " "alg[%d], id=%d, ivlen=%d, minbits=%d, maxbits=%d, res=%d, must be zero.\n", i, pfkey_alg->sadb_alg_id, pfkey_alg->sadb_alg_ivlen, pfkey_alg->sadb_alg_minbits, pfkey_alg->sadb_alg_maxbits, pfkey_alg->sadb_alg_reserved); SENDERR(EINVAL); } /* XXX can alg_id auth/enc be determined from info given? Yes, but OpenBSD's method does not iteroperate with rfc2367. rgb, 2000-04-06 */ switch (pfkey_supported->sadb_supported_exttype) { case K_SADB_EXT_SUPPORTED_AUTH: #if K_SADB_AALG_MAX < 255 if (pfkey_alg->sadb_alg_id > K_SADB_AALG_MAX) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_supported_parse: " "alg[%d], alg_id=%d > K_SADB_AALG_MAX=%d, fatal.\n", i, pfkey_alg->sadb_alg_id, K_SADB_AALG_MAX); SENDERR(EINVAL); } #endif break; case SADB_EXT_SUPPORTED_ENCRYPT: #if K_SADB_EALG_MAX < 255 if (pfkey_alg->sadb_alg_id > K_SADB_EALG_MAX) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_supported_parse: " "alg[%d], alg_id=%d > K_SADB_EALG_MAX=%d, fatal.\n", i, pfkey_alg->sadb_alg_id, K_SADB_EALG_MAX); SENDERR(EINVAL); } #endif break; default: DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_supported_parse: " "alg[%d], alg_id=%d > K_SADB_EALG_MAX=%d, fatal.\n", i, pfkey_alg->sadb_alg_id, K_SADB_EALG_MAX); SENDERR(EINVAL); } pfkey_alg++; } errlab: return error; } DEBUG_NO_STATIC int pfkey_spirange_parse(struct sadb_ext *pfkey_ext) { int error = 0; struct sadb_spirange *pfkey_spirange = (struct sadb_spirange *)pfkey_ext; /* sanity checks... */ if (pfkey_spirange->sadb_spirange_len != sizeof(struct sadb_spirange) / IPSEC_PFKEYv2_ALIGN) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_spirange_parse: " "size wrong ext_len=%d, key_ext_len=%d.\n", pfkey_spirange->sadb_spirange_len, (int)sizeof(struct sadb_spirange)); SENDERR(EINVAL); } if (pfkey_spirange->sadb_spirange_reserved) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_spirange_parse: " "reserved=%d must be set to zero.\n", pfkey_spirange->sadb_spirange_reserved); SENDERR(EINVAL); } if (ntohl(pfkey_spirange->sadb_spirange_max) < ntohl(pfkey_spirange->sadb_spirange_min)) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_spirange_parse: " "minspi=%08x must be < maxspi=%08x.\n", ntohl(pfkey_spirange->sadb_spirange_min), ntohl(pfkey_spirange->sadb_spirange_max)); SENDERR(EINVAL); } if (ntohl(pfkey_spirange->sadb_spirange_min) <= 255) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_spirange_parse: " "minspi=%08x must be > 255.\n", ntohl(pfkey_spirange->sadb_spirange_min)); SENDERR(EEXIST); } DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, "pfkey_spirange_parse: " "ext_len=%u ext_type=%u(%s) min=%u max=%u res=%u.\n", pfkey_spirange->sadb_spirange_len, pfkey_spirange->sadb_spirange_exttype, pfkey_v2_sadb_ext_string(pfkey_spirange-> sadb_spirange_exttype), pfkey_spirange->sadb_spirange_min, pfkey_spirange->sadb_spirange_max, pfkey_spirange->sadb_spirange_reserved); errlab: return error; } DEBUG_NO_STATIC int pfkey_x_kmprivate_parse(struct sadb_ext *pfkey_ext) { int error = 0; struct sadb_x_kmprivate *pfkey_x_kmprivate = (struct sadb_x_kmprivate *)pfkey_ext; /* sanity checks... */ if (pfkey_x_kmprivate->sadb_x_kmprivate_len < sizeof(struct sadb_x_kmprivate) / IPSEC_PFKEYv2_ALIGN) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_kmprivate_parse: " "size wrong ext_len=%d, key_ext_len=%d.\n", pfkey_x_kmprivate->sadb_x_kmprivate_len, (int)sizeof(struct sadb_x_kmprivate)); SENDERR(EINVAL); } if (pfkey_x_kmprivate->sadb_x_kmprivate_reserved) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_kmprivate_parse: " "reserved=%d must be set to zero.\n", pfkey_x_kmprivate->sadb_x_kmprivate_reserved); SENDERR(EINVAL); } DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_kmprivate_parse: " "Sorry, I can't parse exttype=%d yet.\n", pfkey_ext->sadb_ext_type); SENDERR(EINVAL); /* don't process these yet */ errlab: return error; } DEBUG_NO_STATIC int pfkey_x_satype_parse(struct sadb_ext *pfkey_ext) { int error = 0; int i; struct sadb_x_satype *pfkey_x_satype = (struct sadb_x_satype *)pfkey_ext; DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW, "pfkey_x_satype_parse: enter\n"); /* sanity checks... */ if (pfkey_x_satype->sadb_x_satype_len != sizeof(struct sadb_x_satype) / IPSEC_PFKEYv2_ALIGN) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_satype_parse: " "size wrong ext_len=%d, key_ext_len=%d.\n", pfkey_x_satype->sadb_x_satype_len, (int)sizeof(struct sadb_x_satype)); SENDERR(EINVAL); } if (!pfkey_x_satype->sadb_x_satype_satype) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_satype_parse: " "satype is zero, must be non-zero.\n"); SENDERR(EINVAL); } if (pfkey_x_satype->sadb_x_satype_satype > K_SADB_SATYPE_MAX) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_satype_parse: " "satype %d > max %d, invalid.\n", pfkey_x_satype->sadb_x_satype_satype, K_SADB_SATYPE_MAX); SENDERR(EINVAL); } if (!(satype2proto(pfkey_x_satype->sadb_x_satype_satype))) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_satype_parse: " "proto lookup from satype=%d failed.\n", pfkey_x_satype->sadb_x_satype_satype); SENDERR(EINVAL); } for (i = 0; i < 3; i++) { if (pfkey_x_satype->sadb_x_satype_reserved[i]) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_satype_parse: " "reserved[%d]=%d must be set to zero.\n", i, pfkey_x_satype->sadb_x_satype_reserved[i]); SENDERR(EINVAL); } } DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, "pfkey_x_satype_parse: " "len=%u ext=%u(%s) satype=%u(%s) res=%u,%u,%u.\n", pfkey_x_satype->sadb_x_satype_len, pfkey_x_satype->sadb_x_satype_exttype, pfkey_v2_sadb_ext_string(pfkey_x_satype-> sadb_x_satype_exttype), pfkey_x_satype->sadb_x_satype_satype, satype2name(pfkey_x_satype->sadb_x_satype_satype), pfkey_x_satype->sadb_x_satype_reserved[0], pfkey_x_satype->sadb_x_satype_reserved[1], pfkey_x_satype->sadb_x_satype_reserved[2]); errlab: return error; } DEBUG_NO_STATIC int pfkey_x_ext_debug_parse(struct sadb_ext *pfkey_ext) { int error = 0; int i; struct sadb_x_debug *pfkey_x_debug = (struct sadb_x_debug *)pfkey_ext; DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW, "pfkey_x_debug_parse: enter\n"); /* sanity checks... */ if (pfkey_x_debug->sadb_x_debug_len != sizeof(struct sadb_x_debug) / IPSEC_PFKEYv2_ALIGN) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_debug_parse: " "size wrong ext_len=%d, key_ext_len=%d.\n", pfkey_x_debug->sadb_x_debug_len, (int)sizeof(struct sadb_x_debug)); SENDERR(EINVAL); } for (i = 0; i < 4; i++) { if (pfkey_x_debug->sadb_x_debug_reserved[i]) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_debug_parse: " "reserved[%d]=%d must be set to zero.\n", i, pfkey_x_debug->sadb_x_debug_reserved[i]); SENDERR(EINVAL); } } errlab: return error; } DEBUG_NO_STATIC int pfkey_x_ext_protocol_parse(struct sadb_ext *pfkey_ext) { int error = 0; struct sadb_protocol *p = (struct sadb_protocol *)pfkey_ext; DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_protocol_parse:\n"); /* sanity checks... */ if (p->sadb_protocol_len != sizeof(*p) / IPSEC_PFKEYv2_ALIGN) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_protocol_parse: size wrong ext_len=%d, key_ext_len=%d.\n", p->sadb_protocol_len, (int)sizeof(*p)); SENDERR(EINVAL); } if (p->sadb_protocol_reserved2 != 0) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_protocol_parse: res=%d, must be zero.\n", p->sadb_protocol_reserved2); SENDERR(EINVAL); } errlab: return error; } DEBUG_NO_STATIC int pfkey_x_ext_nat_t_type_parse( struct sadb_ext *pfkey_ext UNUSED) { return 0; } DEBUG_NO_STATIC int pfkey_x_ext_nat_t_port_parse( struct sadb_ext *pfkey_ext UNUSED) { return 0; } DEBUG_NO_STATIC int pfkey_x_ext_outif_parse(struct sadb_ext *pfkey_ext) { int error = 0; struct sadb_x_plumbif *p = (struct sadb_x_plumbif *)pfkey_ext; DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_outif_parse:\n"); /* sanity checks... */ if (p->sadb_x_outif_len != IPSEC_PFKEYv2_WORDS(sizeof(*p))) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_outif_parse: size wrong ext_len=%d, key_ext_len=%d.\n", p->sadb_x_outif_len, (int)sizeof(*p)); SENDERR(EINVAL); } errlab: return error; } DEBUG_NO_STATIC int pfkey_x_ext_saref_parse(struct sadb_ext *pfkey_ext) { int error = 0; struct sadb_x_saref *p = (struct sadb_x_saref *)pfkey_ext; DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_saref_parse:\n"); /* sanity checks... */ if (p->sadb_x_saref_len != IPSEC_PFKEYv2_WORDS(sizeof(*p))) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_saref_parse: size wrong ext_len=%d, key_ext_len=%d.\n", p->sadb_x_saref_len, (int)sizeof(*p)); SENDERR(EINVAL); } errlab: return error; } #define DEFINEPARSER(NAME) static struct pf_key_ext_parsers_def NAME ## _def = \ { NAME, #NAME }; DEFINEPARSER(pfkey_sa_parse); DEFINEPARSER(pfkey_lifetime_parse); DEFINEPARSER(pfkey_address_parse); DEFINEPARSER(pfkey_key_parse); DEFINEPARSER(pfkey_ident_parse); DEFINEPARSER(pfkey_sens_parse); DEFINEPARSER(pfkey_prop_parse); DEFINEPARSER(pfkey_supported_parse); DEFINEPARSER(pfkey_spirange_parse); DEFINEPARSER(pfkey_x_kmprivate_parse); DEFINEPARSER(pfkey_x_satype_parse); DEFINEPARSER(pfkey_x_ext_debug_parse); DEFINEPARSER(pfkey_x_ext_protocol_parse); DEFINEPARSER(pfkey_x_ext_nat_t_type_parse); DEFINEPARSER(pfkey_x_ext_nat_t_port_parse); DEFINEPARSER(pfkey_x_ext_outif_parse); DEFINEPARSER(pfkey_x_ext_saref_parse); static struct pf_key_ext_parsers_def *ext_default_parsers[] = { NULL, /* pfkey_msg_parse, */ &pfkey_sa_parse_def, &pfkey_lifetime_parse_def, &pfkey_lifetime_parse_def, &pfkey_lifetime_parse_def, &pfkey_address_parse_def, &pfkey_address_parse_def, &pfkey_address_parse_def, &pfkey_key_parse_def, &pfkey_key_parse_def, &pfkey_ident_parse_def, &pfkey_ident_parse_def, &pfkey_sens_parse_def, &pfkey_prop_parse_def, &pfkey_supported_parse_def, &pfkey_supported_parse_def, &pfkey_spirange_parse_def, &pfkey_x_kmprivate_parse_def, &pfkey_x_satype_parse_def, &pfkey_sa_parse_def, &pfkey_address_parse_def, &pfkey_address_parse_def, &pfkey_address_parse_def, &pfkey_address_parse_def, &pfkey_address_parse_def, &pfkey_x_ext_debug_parse_def, &pfkey_x_ext_protocol_parse_def, &pfkey_x_ext_nat_t_type_parse_def, &pfkey_x_ext_nat_t_port_parse_def, &pfkey_x_ext_nat_t_port_parse_def, &pfkey_address_parse_def, &pfkey_x_ext_outif_parse_def, &pfkey_x_ext_saref_parse_def, }; int pfkey_msg_parse(struct sadb_msg *pfkey_msg, struct pf_key_ext_parsers_def *ext_parsers[], struct sadb_ext *extensions[], int dir) { int error = 0; int remain; struct sadb_ext *pfkey_ext; pfkey_ext_track extensions_seen; DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, "pfkey_msg_parse: " "parsing message ver=%d, type=%d(%s), errno=%d, satype=%d(%s), len=%d, res=%d, seq=%d, pid=%d.\n", pfkey_msg->sadb_msg_version, pfkey_msg->sadb_msg_type, pfkey_v2_sadb_type_string(pfkey_msg->sadb_msg_type), pfkey_msg->sadb_msg_errno, pfkey_msg->sadb_msg_satype, satype2name(pfkey_msg->sadb_msg_satype), pfkey_msg->sadb_msg_len, pfkey_msg->sadb_msg_reserved, pfkey_msg->sadb_msg_seq, pfkey_msg->sadb_msg_pid); if (ext_parsers == NULL) ext_parsers = ext_default_parsers; pfkey_extensions_init(extensions); remain = pfkey_msg->sadb_msg_len; remain -= IPSEC_PFKEYv2_WORDS(sizeof(struct sadb_msg)); pfkey_ext = (struct sadb_ext*)((char*)pfkey_msg + sizeof(struct sadb_msg)); extensions[0] = (struct sadb_ext *) pfkey_msg; if (pfkey_msg->sadb_msg_version != PF_KEY_V2) { ERROR("pfkey_msg_parse: " "not PF_KEY_V2 msg, found %d, should be %d.\n", pfkey_msg->sadb_msg_version, PF_KEY_V2); SENDERR(EINVAL); } if (!pfkey_msg->sadb_msg_type) { ERROR("pfkey_msg_parse: " "msg type not set, must be non-zero..\n"); SENDERR(EINVAL); } if (pfkey_msg->sadb_msg_type > K_SADB_MAX) { ERROR("pfkey_msg_parse: " "msg type=%d > max=%d.\n", pfkey_msg->sadb_msg_type, K_SADB_MAX); SENDERR(EINVAL); } switch (pfkey_msg->sadb_msg_type) { case K_SADB_GETSPI: case K_SADB_UPDATE: case K_SADB_ADD: case K_SADB_DELETE: case K_SADB_GET: case K_SADB_X_GRPSA: case K_SADB_X_ADDFLOW: if (!satype2proto(pfkey_msg->sadb_msg_satype)) { ERROR("pfkey_msg_parse: " "satype %d conversion to proto failed for msg_type %d (%s).\n", pfkey_msg->sadb_msg_satype, pfkey_msg->sadb_msg_type, pfkey_v2_sadb_type_string(pfkey_msg-> sadb_msg_type)); SENDERR(EINVAL); } else { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_msg_parse: " "satype %d(%s) conversion to proto gives %d for msg_type %d(%s).\n", pfkey_msg->sadb_msg_satype, satype2name(pfkey_msg->sadb_msg_satype), satype2proto(pfkey_msg->sadb_msg_satype), pfkey_msg->sadb_msg_type, pfkey_v2_sadb_type_string(pfkey_msg-> sadb_msg_type)); } /* FALLTHROUGH */ case K_SADB_ACQUIRE: case K_SADB_REGISTER: case K_SADB_EXPIRE: if (!pfkey_msg->sadb_msg_satype) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_msg_parse: " "satype is zero, must be non-zero for msg_type %d(%s).\n", pfkey_msg->sadb_msg_type, pfkey_v2_sadb_type_string(pfkey_msg-> sadb_msg_type)); SENDERR(EINVAL); } break; default: break; } /* errno must not be set in downward messages */ /* this is not entirely true... a response to an ACQUIRE could return an error */ if ((dir == EXT_BITS_IN) && (pfkey_msg->sadb_msg_type != K_SADB_ACQUIRE) && pfkey_msg->sadb_msg_errno) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_msg_parse: " "errno set to %d.\n", pfkey_msg->sadb_msg_errno); SENDERR(EINVAL); } DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW, "pfkey_msg_parse: " "remain=%d\n", remain ); extensions_seen = 1ULL << SADB_EXT_RESERVED; while ( (remain * IPSEC_PFKEYv2_ALIGN) >= sizeof(struct sadb_ext) ) { /* Is there enough message left to support another extension header? */ if (remain < pfkey_ext->sadb_ext_len) { ERROR("pfkey_msg_parse: " "remain %d less than ext len %d.\n", remain, pfkey_ext->sadb_ext_len); SENDERR(EINVAL); } DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW, "pfkey_msg_parse: " "parsing ext type=%d(%s) remain=%d.\n", pfkey_ext->sadb_ext_type, pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type), remain); /* Is the extension header type valid? */ if ((pfkey_ext->sadb_ext_type > K_SADB_EXT_MAX) || (!pfkey_ext->sadb_ext_type)) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_msg_parse: " "ext type %d(%s) invalid, K_SADB_EXT_MAX=%d.\n", pfkey_ext->sadb_ext_type, pfkey_v2_sadb_ext_string(pfkey_ext-> sadb_ext_type), K_SADB_EXT_MAX); SENDERR(EINVAL); } /* Have we already seen this type of extension? */ if (extensions[pfkey_ext->sadb_ext_type] != NULL) { ERROR("pfkey_msg_parse: " "ext type %d(%s) already seen.\n", pfkey_ext->sadb_ext_type, pfkey_v2_sadb_ext_string( pfkey_ext->sadb_ext_type)); SENDERR(EINVAL); } /* Do I even know about this type of extension? */ if (ext_parsers[pfkey_ext->sadb_ext_type] == NULL) { ERROR("pfkey_msg_parse: " "ext type %d(%s) unknown, ignoring.\n", pfkey_ext->sadb_ext_type, pfkey_v2_sadb_ext_string( pfkey_ext->sadb_ext_type)); goto next_ext; } /* Is this type of extension permitted for this type of message? */ if (!pfkey_permitted_extension(dir, pfkey_msg->sadb_msg_type, pfkey_ext->sadb_ext_type)) { ERROR("ext type %d(%s) not permitted (parse)\n", pfkey_ext->sadb_ext_type, pfkey_v2_sadb_ext_string( pfkey_ext->sadb_ext_type)); SENDERR(EINVAL); } DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, "pfkey_msg_parse: " "remain=%d ext_type=%d(%s) ext_len=%d parsing ext 0p%p with parser %s.\n", remain, pfkey_ext->sadb_ext_type, pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type), pfkey_ext->sadb_ext_len, pfkey_ext, ext_parsers[pfkey_ext->sadb_ext_type]->parser_name); /* Parse the extension */ if ((error = (*ext_parsers[pfkey_ext->sadb_ext_type]->parser)( pfkey_ext))) { ERROR("pfkey_msg_parse: " "extension parsing for type %d(%s) failed with error %d.\n", pfkey_ext->sadb_ext_type, pfkey_v2_sadb_ext_string( pfkey_ext->sadb_ext_type), error); SENDERR(-error); } DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW, "pfkey_msg_parse: " "Extension %d(%s) parsed.\n", pfkey_ext->sadb_ext_type, pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type)); /* Mark that we have seen this extension and remember the header location */ extensions[pfkey_ext->sadb_ext_type] = pfkey_ext; pfkey_mark_extension(pfkey_ext->sadb_ext_type, &extensions_seen); next_ext: /* Calculate how much message remains */ remain -= pfkey_ext->sadb_ext_len; if (!remain) break; /* Find the next extension header */ pfkey_ext = (struct sadb_ext*)((char*)pfkey_ext + pfkey_ext->sadb_ext_len * IPSEC_PFKEYv2_ALIGN); } if (remain) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_msg_parse: " "unexpected remainder of %d.\n", remain); /* why is there still something remaining? */ SENDERR(EINVAL); } /* don't check further if it is an error return message since it may not have a body */ if (pfkey_msg->sadb_msg_errno) SENDERR(-error); if (pfkey_extensions_missing(dir, pfkey_msg->sadb_msg_type, extensions_seen)) { ERROR("required extensions missing; seen=%08llx.\n", (unsigned long long)extensions_seen); SENDERR(EINVAL); } if (dir == EXT_BITS_IN && pfkey_msg->sadb_msg_type == K_SADB_X_DELFLOW && (extensions_seen & K_SADB_X_EXT_ADDRESS_DELFLOW) != K_SADB_X_EXT_ADDRESS_DELFLOW && ((extensions_seen & (1ULL << SADB_EXT_SA)) == 0 || (((struct k_sadb_sa *)extensions[SADB_EXT_SA])->sadb_sa_flags & SADB_X_SAFLAGS_CLEARFLOW) == 0)) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_msg_parse: " "required SADB_X_DELFLOW extensions missing: either %16llx must be present or %16llx must be present with SADB_X_SAFLAGS_CLEARFLOW set.\n", K_SADB_X_EXT_ADDRESS_DELFLOW & ~extensions_seen, (1ULL << SADB_EXT_SA) & ~extensions_seen); SENDERR(EINVAL); } switch (pfkey_msg->sadb_msg_type) { case K_SADB_ADD: case K_SADB_UPDATE: /* check maturity */ if (((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state != K_SADB_SASTATE_MATURE) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_msg_parse: " "state=%d for add or update should be MATURE=%d.\n", ((struct k_sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state, K_SADB_SASTATE_MATURE); SENDERR(EINVAL); } /* check AH and ESP */ switch (((struct sadb_msg*)extensions[SADB_EXT_RESERVED])-> sadb_msg_satype) { case SADB_SATYPE_AH: if ((struct k_sadb_sa*)extensions[SADB_EXT_SA] == NULL || ((struct k_sadb_sa*)extensions[SADB_EXT_SA])-> sadb_sa_auth == SADB_AALG_NONE) { ERROR("pfkey_msg_parse: " "auth alg is zero; must be non-zero for AH SAs.\n"); SENDERR(EINVAL); } if (((struct k_sadb_sa*)(extensions[SADB_EXT_SA]))-> sadb_sa_encrypt != SADB_EALG_NONE) { ERROR("pfkey_msg_parse: " "AH handed encalg=%d; must be zero.\n", ((struct k_sadb_sa*)(extensions[ SADB_EXT_SA]))->sadb_sa_encrypt); SENDERR(EINVAL); } break; case SADB_SATYPE_ESP: if ((struct k_sadb_sa*)extensions[SADB_EXT_SA] == NULL || ((struct k_sadb_sa*)extensions[SADB_EXT_SA])-> sadb_sa_encrypt == SADB_EALG_NONE) { ERROR("pfkey_msg_parse: " "encrypt alg=%d is zero; must be non-zero for ESP=%d SAs.\n", ((struct k_sadb_sa*)extensions[ SADB_EXT_SA])->sadb_sa_encrypt, ((struct sadb_msg*)extensions[ SADB_EXT_RESERVED])->sadb_msg_satype); SENDERR(EINVAL); } if ((((struct k_sadb_sa*)(extensions[SADB_EXT_SA]))-> sadb_sa_encrypt == SADB_EALG_NULL) && (((struct k_sadb_sa*)(extensions[SADB_EXT_SA]))-> sadb_sa_auth == SADB_AALG_NONE) ) { ERROR("pfkey_msg_parse: " "ESP handed encNULL+authNONE, illegal combination.\n"); SENDERR(EINVAL); } break; case K_SADB_X_SATYPE_COMP: if (!(((struct k_sadb_sa*)extensions[SADB_EXT_SA]) && ((struct k_sadb_sa*)extensions[SADB_EXT_SA])-> sadb_sa_encrypt != SADB_EALG_NONE)) { ERROR("pfkey_msg_parse: " "encrypt alg=%d is zero, must be non-zero for COMP=%d SAs.\n", ((struct k_sadb_sa*)extensions[ SADB_EXT_SA])->sadb_sa_encrypt, ((struct sadb_msg*)extensions[ SADB_EXT_RESERVED])->sadb_msg_satype); SENDERR(EINVAL); } if (((struct k_sadb_sa*)(extensions[SADB_EXT_SA]))-> sadb_sa_auth != SADB_AALG_NONE) { ERROR("pfkey_msg_parse: " "COMP handed auth=%d, must be zero.\n", ((struct k_sadb_sa*)(extensions[ SADB_EXT_SA]))->sadb_sa_auth); SENDERR(EINVAL); } break; default: break; } if (ntohl(((struct k_sadb_sa*)(extensions[SADB_EXT_SA]))-> sadb_sa_spi) <= 255) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_msg_parse: " "spi=%08x must be > 255.\n", ntohl(((struct k_sadb_sa*)(extensions[ SADB_EXT_SA ]))->sadb_sa_spi)); SENDERR(EINVAL); } default: break; } errlab: return error; } libreswan-3.32/linux/net/ipsec/pfkey_v2_parser.c000066400000000000000000003076551365625662500217640ustar00rootroot00000000000000/* * @(#) RFC2367 PF_KEYv2 Key management API message parser * Copyright (C) 1999, 2000, 2001, 2017 Richard Guy Briggs * Copyright (C) 2012 Paul Wouters * Copyright (C) 2012 David McCullough * * OCF support written by David McCullough * Copyright (C) 2004-2005 Intel Corporation. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ /* * Template from klips/net/ipsec/ipsec/ipsec_netlink.c. */ #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38) && \ !defined(AUTOCONF_INCLUDED) #include #endif #include /* printk() */ #include "libreswan/ipsec_param.h" #include /* kmalloc() */ #include /* error codes */ #include /* size_t */ #include /* mark_bh */ #include /* struct device, and other headers */ #include /* eth_type_trans */ #include /* struct iphdr */ #include #include "libreswan/ipsec_param2.h" #include #include #include /* *lock* */ # include /* inet_addr_type */ # include # include # define IS_MYADDR RTN_LOCAL #include #include #include /* get_random_bytes() */ #include "libreswan/radij.h" #include "libreswan/ipsec_encap.h" #include "libreswan/ipsec_sa.h" #include "libreswan/ipsec_radij.h" #include "libreswan/ipsec_xform.h" #include "libreswan/ipsec_ah.h" #include "libreswan/ipsec_esp.h" #include "libreswan/ipsec_tunnel.h" #include "libreswan/ipsec_mast.h" #include "libreswan/ipsec_rcv.h" #include "libreswan/ipcomp.h" #include #include #include "libreswan/ipsec_proto.h" #include "libreswan/ipsec_alg.h" #include "libreswan/ipsec_kversion.h" #define SENDERR(_x) { error = -(_x); goto errlab; } struct sklist_t { struct socket *sk; struct sklist_t *next; } pfkey_sklist_head, *pfkey_sklist, *pfkey_sklist_prev; static __u32 pfkey_msg_seq = 0; #if 0 #define DUMP_SAID dump_said(&extr->ips->ips_said, __LINE__) #define DUMP_SAID2 dump_said(&extr.ips->ips_said, __LINE__) static void dump_said(ip_said *s, int line) { char msa[SATOT_BUF]; size_t msa_len; msa_len = KLIPS_SATOT(1, s, 0, msa, sizeof(msa)); printk("line: %d msa: %s\n", line, msa); } #endif int pfkey_alloc_eroute(struct eroute **eroute) { int error = 0; if (*eroute) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_alloc_eroute: " "eroute struct already allocated\n"); SENDERR(EEXIST); } if ((*eroute = kmalloc(sizeof(**eroute), GFP_ATOMIC) ) == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_alloc_eroute: " "memory allocation error\n"); SENDERR(ENOMEM); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_alloc_eroute: " "allocating %zu bytes for an eroute at 0p%p\n", sizeof(**eroute), *eroute); memset((caddr_t)*eroute, 0, sizeof(**eroute)); (*eroute)->er_eaddr.sen_len = (*eroute)->er_emask.sen_len = sizeof(struct sockaddr_encap); (*eroute)->er_eaddr.sen_family = (*eroute)->er_emask.sen_family = AF_ENCAP; (*eroute)->er_eaddr.sen_type = SENT_IP4; (*eroute)->er_emask.sen_type = 255; (*eroute)->er_pid = 0; (*eroute)->er_count = 0; (*eroute)->er_lasttime = jiffies / HZ; errlab: return error; } DEBUG_NO_STATIC int pfkey_x_protocol_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr) { int error = 0; struct sadb_protocol * p = (struct sadb_protocol *)pfkey_ext; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_protocol_process: " "%p\n", extr); if (extr == 0) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_protocol_process:" "extr is NULL, fatal\n"); SENDERR(EINVAL); } if (extr->eroute == 0) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_protocol_process:" "extr->eroute is NULL, fatal\n"); SENDERR(EINVAL); } extr->eroute->er_eaddr.sen_proto = p->sadb_protocol_proto; extr->eroute->er_emask.sen_proto = p->sadb_protocol_proto ? ~0 : 0; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_protocol_process: " "protocol = %d.\n", p->sadb_protocol_proto); errlab: return error; } DEBUG_NO_STATIC int pfkey_ipsec_sa_init(struct ipsec_sa *ipsp) { int rc; KLIPS_PRINT(debug_pfkey, "Calling SA_INIT\n"); rc = ipsec_sa_init(ipsp); return rc; } static int pfkey_safe_build(int error, struct sadb_ext *extensions[K_SADB_MAX + 1]) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_safe_build: " "error=%d\n", error); if (!error) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_safe_build:" "success.\n"); return 1; } else { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_safe_build:" "caught error %d\n", error); pfkey_extensions_free(extensions); return 0; } } DEBUG_NO_STATIC int pfkey_getspi_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data *extr) { int error = 0; ipsec_spi_t minspi = htonl(256), maxspi = htonl(-1L); int found_avail = 0; struct ipsec_sa *ipsq; char sa[SATOT_BUF]; size_t sa_len; struct sadb_ext *extensions_reply[K_SADB_EXT_MAX + 1]; struct sadb_msg *pfkey_reply = NULL; struct socket_list *pfkey_socketsp; uint8_t satype = ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_satype; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: .\n"); pfkey_extensions_init(extensions_reply); if (extr == NULL || extr->ips == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " "error, extr or extr->ipsec_sa pointer NULL\n"); SENDERR(EINVAL); } if (extensions[K_SADB_EXT_SPIRANGE]) { minspi = ((struct sadb_spirange *) extensions[K_SADB_EXT_SPIRANGE])->sadb_spirange_min; maxspi = ((struct sadb_spirange *) extensions[K_SADB_EXT_SPIRANGE])->sadb_spirange_max; } if (maxspi == minspi) { extr->ips->ips_said.spi = maxspi; spin_lock_bh(&tdb_lock); ipsq = ipsec_sa_getbyid(&(extr->ips->ips_said), IPSEC_REFSA); if (ipsq != NULL) { sa_len = KLIPS_SATOT(debug_pfkey, &extr->ips->ips_said, 0, sa, sizeof(sa)); ipsec_sa_put(ipsq, IPSEC_REFSA); spin_unlock_bh(&tdb_lock); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " "EMT_GETSPI found an old ipsec_sa for SA: %s, delete it first.\n", sa_len ? sa : " (error)"); SENDERR(EEXIST); } else { found_avail = 1; } spin_unlock_bh(&tdb_lock); } else { int i = 0; __u32 rand_val; __u32 spi_diff; while ( ( i < (spi_diff = (ntohl(maxspi) - ntohl(minspi)))) && !found_avail ) { prng_bytes(&ipsec_prng, (char *) &(rand_val), ( (spi_diff < (2 ^ 8)) ? 1 : ( (spi_diff < (2 ^ 16)) ? 2 : ( (spi_diff < (2 ^ 24)) ? 3 : 4 ) ) ) ); extr->ips->ips_said.spi = htonl(ntohl(minspi) + (rand_val % (spi_diff + 1))); i++; spin_lock_bh(&tdb_lock); ipsq = ipsec_sa_getbyid(&(extr->ips->ips_said), IPSEC_REFSA); if (ipsq == NULL) found_avail = 1; else ipsec_sa_put(ipsq, IPSEC_REFSA); spin_unlock_bh(&tdb_lock); } } sa_len = KLIPS_SATOT(debug_pfkey, &extr->ips->ips_said, 0, sa, sizeof(sa)); if (!found_avail) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " "found an old ipsec_sa for SA: %s, delete it first.\n", sa_len ? sa : " (error)"); SENDERR(EEXIST); } #ifdef CONFIG_KLIPS_IPV6 if (ip_address_family(&extr->ips->ips_said.dst) == AF_INET6 && ip6_chk_addr(&extr->ips->ips_said.dst.u.v6.sin6_addr) == IS_MYADDR) extr->ips->ips_flags |= EMT_INBOUND; else #endif if (ip_chk_addr(extr->ips->ips_said.dst.u.v4.sin_addr.s_addr) == IS_MYADDR) extr->ips->ips_flags |= EMT_INBOUND; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " "existing ipsec_sa not found (this is good) for SA: %s, %s-bound, allocating.\n", sa_len ? sa : " (error)", extr->ips->ips_flags & EMT_INBOUND ? "in" : "out"); /* XXX extr->ips->ips_rcvif = &(enc_softc[em->em_if].enc_if);*/ extr->ips->ips_rcvif = NULL; extr->ips->ips_life.ipl_addtime.ipl_count = jiffies / HZ; extr->ips->ips_state = K_SADB_SASTATE_LARVAL; if (!extr->ips->ips_life.ipl_allocations.ipl_count) extr->ips->ips_life.ipl_allocations.ipl_count += 1; if (!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], K_SADB_GETSPI, satype, 0, ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_seq, ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_pid), extensions_reply) && pfkey_safe_build(error = pfkey_sa_build(&extensions_reply[K_SADB_EXT_SA], K_SADB_EXT_SA, extr->ips->ips_said.spi, 0, K_SADB_SASTATE_LARVAL, 0, 0, 0), extensions_reply) && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[K_SADB_EXT_ADDRESS_SRC], K_SADB_EXT_ADDRESS_SRC, 0, /*extr->ips->ips_said.proto,*/ 0, extr->ips->ips_addr_s), extensions_reply) && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[K_SADB_EXT_ADDRESS_DST], K_SADB_EXT_ADDRESS_DST, 0, /*extr->ips->ips_said.proto,*/ 0, extr->ips->ips_addr_d), extensions_reply) )) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " "failed to build the getspi reply message extensions\n"); goto errlab; } if ((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " "failed to build the getspi reply message\n"); SENDERR(-error); } for (pfkey_socketsp = pfkey_open_sockets; pfkey_socketsp; pfkey_socketsp = pfkey_socketsp->next) { if ((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " "sending up getspi reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", satype, satype2name(satype), pfkey_socketsp->socketp, error); SENDERR(-error); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " "sending up getspi reply message for satype=%d(%s) to socket=0p%p succeeded.\n", satype, satype2name(satype), pfkey_socketsp->socketp); } /* ipsec_sa_add does tdb_lock */ if ((error = ipsec_sa_add(extr->ips))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " "failed to add the larval SA=%s with error=%d.\n", sa_len ? sa : " (error)", error); SENDERR(-error); } extr->ips = NULL; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " "successful for SA: %s\n", sa_len ? sa : " (error)"); errlab: if (pfkey_reply) pfkey_msg_free(&pfkey_reply); pfkey_extensions_free(extensions_reply); return error; } DEBUG_NO_STATIC int pfkey_update_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data *extr) { int error = 0; struct ipsec_sa *ipsq; char sa[SATOT_BUF]; size_t sa_len; struct sadb_ext *extensions_reply[K_SADB_EXT_MAX + 1]; struct sadb_msg *pfkey_reply = NULL; struct socket_list *pfkey_socketsp; uint8_t satype = ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_satype; struct ipsec_sa *nat_t_ips_saved = NULL; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: .\n"); pfkey_extensions_init(extensions_reply); if (((struct sadb_sa*)extensions[K_SADB_EXT_SA])->sadb_sa_state != K_SADB_SASTATE_MATURE) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: " "error, sa_state=%d must be MATURE=%d\n", ((struct sadb_sa*)extensions[K_SADB_EXT_SA])->sadb_sa_state, K_SADB_SASTATE_MATURE); SENDERR(EINVAL); } if (extr == NULL || extr->ips == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: " "error, extr or extr->ips pointer NULL\n"); SENDERR(EINVAL); } sa_len = KLIPS_SATOT(debug_pfkey, &extr->ips->ips_said, 0, sa, sizeof(sa)); spin_lock_bh(&tdb_lock); ipsq = ipsec_sa_getbyid(&(extr->ips->ips_said), IPSEC_REFSA); if (ipsq == NULL) { spin_unlock_bh(&tdb_lock); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: " "reserved ipsec_sa for SA: %s not found. Call K_SADB_GETSPI first or call K_SADB_ADD instead.\n", sa_len ? sa : " (error)"); SENDERR(ENOENT); } #ifdef CONFIG_KLIPS_IPV6 if (ip_address_family(&extr->ips->ips_said.dst) == AF_INET6 && ip6_chk_addr(&extr->ips->ips_said.dst.u.v6.sin6_addr) == IS_MYADDR) extr->ips->ips_flags |= EMT_INBOUND; else #endif if (ip_chk_addr(extr->ips->ips_said.dst.u.v4.sin_addr.s_addr) == IS_MYADDR) extr->ips->ips_flags |= EMT_INBOUND; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: " "existing ipsec_sa found (this is good) for SA: %s, %s-bound, updating.\n", sa_len ? sa : " (error)", extr->ips->ips_flags & EMT_INBOUND ? "in" : "out"); if (extr->ips->ips_natt_sport || extr->ips->ips_natt_dport) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: " "only updating NAT-T ports (%u:%u -> %u:%u)\n", ipsq->ips_natt_sport, ipsq->ips_natt_dport, extr->ips->ips_natt_sport, extr->ips->ips_natt_dport); if (extr->ips->ips_natt_sport) { ipsq->ips_natt_sport = extr->ips->ips_natt_sport; if (ipsq->ips_addr_s->sa_family == AF_INET) ((struct sockaddr_in *)(ipsq->ips_addr_s))->sin_port = htons(extr->ips->ips_natt_sport); } if (extr->ips->ips_natt_dport) { ipsq->ips_natt_dport = extr->ips->ips_natt_dport; if (ipsq->ips_addr_d->sa_family == AF_INET) ((struct sockaddr_in *)(ipsq->ips_addr_d))->sin_port = htons(extr->ips->ips_natt_dport); } nat_t_ips_saved = extr->ips; extr->ips = ipsq; } else { /* XXX extr->ips->ips_rcvif = &(enc_softc[em->em_if].enc_if);*/ extr->ips->ips_rcvif = NULL; if ((error = pfkey_ipsec_sa_init(extr->ips))) { ipsec_sa_put(ipsq, IPSEC_REFSA); spin_unlock_bh(&tdb_lock); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: " "not successful for SA: %s, deleting.\n", sa_len ? sa : " (error)"); SENDERR(-error); } extr->ips->ips_life.ipl_addtime.ipl_count = ipsq->ips_life.ipl_addtime.ipl_count; /* this will call delchain-equivalent if refcount=>0 */ ipsec_sa_put(ipsq, IPSEC_REFSA); } spin_unlock_bh(&tdb_lock); if (!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], K_SADB_UPDATE, satype, 0, ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_seq, ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_pid), extensions_reply) && pfkey_safe_build(error = pfkey_sa_build(&extensions_reply[K_SADB_EXT_SA], K_SADB_EXT_SA, extr->ips->ips_said.spi, extr->ips->ips_replaywin, extr->ips->ips_state, extr->ips->ips_authalg, extr->ips->ips_encalg, extr->ips->ips_flags), extensions_reply) && /* The 3 lifetime extensions should only be sent if non-zero. */ (extensions[K_SADB_EXT_LIFETIME_HARD] == 0 || pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[K_SADB_EXT_LIFETIME_HARD], K_SADB_EXT_LIFETIME_HARD, extr->ips->ips_life.ipl_allocations.ipl_hard, extr->ips->ips_life.ipl_bytes.ipl_hard, extr->ips->ips_life.ipl_addtime.ipl_hard, extr->ips->ips_life.ipl_usetime.ipl_hard, extr->ips->ips_life.ipl_packets.ipl_hard), extensions_reply)) && (extensions[K_SADB_EXT_LIFETIME_SOFT] == 0 || pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[K_SADB_EXT_LIFETIME_SOFT], K_SADB_EXT_LIFETIME_SOFT, extr->ips->ips_life.ipl_allocations.ipl_count, extr->ips->ips_life.ipl_bytes.ipl_count, extr->ips->ips_life.ipl_addtime.ipl_count, extr->ips->ips_life.ipl_usetime.ipl_count, extr->ips->ips_life.ipl_packets.ipl_count), extensions_reply)) && (!(extr->ips->ips_life.ipl_allocations.ipl_count || extr->ips->ips_life.ipl_bytes.ipl_count || extr->ips->ips_life.ipl_addtime.ipl_count || extr->ips->ips_life.ipl_usetime.ipl_count || extr->ips->ips_life.ipl_packets.ipl_count) || pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[K_SADB_EXT_LIFETIME_CURRENT], K_SADB_EXT_LIFETIME_CURRENT, extr->ips->ips_life.ipl_allocations.ipl_count, extr->ips->ips_life.ipl_bytes.ipl_count, extr->ips->ips_life.ipl_addtime.ipl_count, extr->ips->ips_life.ipl_usetime.ipl_count, extr->ips->ips_life.ipl_packets.ipl_count), extensions_reply)) && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[K_SADB_EXT_ADDRESS_SRC], K_SADB_EXT_ADDRESS_SRC, 0, /*extr->ips->ips_said.proto,*/ 0, extr->ips->ips_addr_s), extensions_reply) && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[K_SADB_EXT_ADDRESS_DST], K_SADB_EXT_ADDRESS_DST, 0, /*extr->ips->ips_said.proto,*/ 0, extr->ips->ips_addr_d), extensions_reply) && (!extr->ips->ips_ident_s.data || pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[K_SADB_EXT_IDENTITY_SRC], K_SADB_EXT_IDENTITY_SRC, extr->ips->ips_ident_s.type, extr->ips->ips_ident_s.id, extr->ips->ips_ident_s.len, extr->ips->ips_ident_s.data), extensions_reply)) && (!extr->ips->ips_ident_d.data || pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[K_SADB_EXT_IDENTITY_DST], K_SADB_EXT_IDENTITY_DST, extr->ips->ips_ident_d.type, extr->ips->ips_ident_d.id, extr->ips->ips_ident_d.len, extr->ips->ips_ident_d.data), extensions_reply)) #if 0 /* FIXME: This won't work yet because I have not finished it */ && (!extr->ips->ips_sens || pfkey_safe_build(error = pfkey_sens_build(&extensions_reply[K_SADB_EXT_SENSITIVITY], extr->ips->ips_sens_dpd, extr->ips->ips_sens_sens_level, extr->ips->ips_sens_sens_len, extr->ips->ips_sens_sens_bitmap, extr->ips->ips_sens_integ_level, extr->ips->ips_sens_integ_len, extr->ips->ips_sens_integ_bitmap), extensions_reply)) #endif )) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: " "failed to build the update reply message extensions\n"); SENDERR(-error); } if ((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: " "failed to build the update reply message\n"); SENDERR(-error); } for (pfkey_socketsp = pfkey_open_sockets; pfkey_socketsp; pfkey_socketsp = pfkey_socketsp->next) { if ((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: " "sending up update reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", satype, satype2name(satype), pfkey_socketsp->socketp, error); SENDERR(-error); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: " "sending up update reply message for satype=%d(%s) to socket=0p%p succeeded.\n", satype, satype2name(satype), pfkey_socketsp->socketp); } if (nat_t_ips_saved) { /** * As we _really_ update existing SA, we keep tdbq and need to delete * parsed ips (nat_t_ips_saved, was extr->ips). * * goto errlab with extr->ips = nat_t_ips_saved will free it. */ extr->ips = nat_t_ips_saved; error = 0; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse " "(NAT-T ports): successful for SA: %s\n", sa_len ? sa : " (error)"); goto errlab; } /* ipsec_sa_add does tdb_lock */ if ((error = ipsec_sa_add(extr->ips))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: " "failed to update the mature SA=%s with error=%d.\n", sa_len ? sa : " (error)", error); SENDERR(-error); } extr->ips = NULL; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: " "successful for SA: %s\n", sa_len ? sa : " (error)"); errlab: if (pfkey_reply) pfkey_msg_free(&pfkey_reply); pfkey_extensions_free(extensions_reply); return error; } DEBUG_NO_STATIC int pfkey_add_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data *extr) { int error = 0; struct ipsec_sa *ipsq; char sa[SATOT_BUF]; size_t sa_len; struct sadb_ext *extensions_reply[K_SADB_EXT_MAX + 1]; struct sadb_msg *pfkey_reply = NULL; struct socket_list *pfkey_socketsp; uint8_t satype = ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_satype; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: .\n"); pfkey_extensions_init(extensions_reply); if (((struct sadb_sa*)extensions[K_SADB_EXT_SA])->sadb_sa_state != K_SADB_SASTATE_MATURE) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: " "error, sa_state=%d must be MATURE=%d\n", ((struct sadb_sa*)extensions[K_SADB_EXT_SA])->sadb_sa_state, K_SADB_SASTATE_MATURE); SENDERR(EINVAL); } if (!extr || !extr->ips) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: " "extr or extr->ips pointer NULL\n"); SENDERR(EINVAL); } sa_len = KLIPS_SATOT(debug_pfkey, &extr->ips->ips_said, 0, sa, sizeof(sa)); spin_lock_bh(&tdb_lock); ipsq = ipsec_sa_getbyid(&(extr->ips->ips_said), IPSEC_REFSA); if (ipsq != NULL) { ipsec_sa_put(ipsq, IPSEC_REFSA); spin_unlock_bh(&tdb_lock); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: " "found an old ipsec_sa for SA%s, delete it first.\n", sa_len ? sa : " (error)"); SENDERR(EEXIST); } spin_unlock_bh(&tdb_lock); #ifdef CONFIG_KLIPS_IPV6 if (ip_address_family(&extr->ips->ips_said.dst) == AF_INET6 && ip6_chk_addr(&extr->ips->ips_said.dst.u.v6.sin6_addr) == IS_MYADDR) extr->ips->ips_flags |= EMT_INBOUND; else #endif if (ip_chk_addr(extr->ips->ips_said.dst.u.v4.sin_addr.s_addr) == IS_MYADDR) extr->ips->ips_flags |= EMT_INBOUND; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: " "existing ipsec_sa not found (this is good) for SA%s, %s-bound, allocating.\n", sa_len ? sa : " (error)", extr->ips->ips_flags & EMT_INBOUND ? "in" : "out"); /* XXX extr->ips->ips_rcvif = &(enc_softc[em->em_if].enc_if);*/ extr->ips->ips_rcvif = NULL; if ((error = ipsec_sa_init(extr->ips))) { KLIPS_ERROR(debug_pfkey, "pfkey_add_parse: " "not successful for SA: %s, deleting.\n", sa_len ? sa : " (error)"); SENDERR(-error); } if (extr->sarefme != IPSEC_SAREF_NULL && extr->ips->ips_ref == IPSEC_SAREF_NULL) extr->ips->ips_ref = extr->sarefme; if (extr->sarefhim != IPSEC_SAREF_NULL && extr->ips->ips_refhim == IPSEC_SAREF_NULL) extr->ips->ips_refhim = extr->sarefhim; /* attach it to the SAref table */ spin_lock_bh(&tdb_lock); if ((error = ipsec_sa_intern(extr->ips)) != 0) { spin_unlock_bh(&tdb_lock); KLIPS_ERROR(debug_pfkey, "pfkey_add_parse: " "failed to intern SA as SAref#%lu\n", (unsigned long)extr->ips->ips_ref); SENDERR(-error); } spin_unlock_bh(&tdb_lock); extr->ips->ips_life.ipl_addtime.ipl_count = jiffies / HZ; if (!extr->ips->ips_life.ipl_allocations.ipl_count) extr->ips->ips_life.ipl_allocations.ipl_count += 1; if (!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], K_SADB_ADD, satype, 0, ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_seq, ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_pid), extensions_reply) && pfkey_safe_build(error = pfkey_sa_build(&extensions_reply[K_SADB_EXT_SA], K_SADB_EXT_SA, extr->ips->ips_said.spi, extr->ips->ips_replaywin, extr->ips->ips_state, extr->ips->ips_authalg, extr->ips->ips_encalg, extr->ips->ips_flags), extensions_reply) && pfkey_safe_build(error = pfkey_saref_build(&extensions_reply[K_SADB_X_EXT_SAREF], extr->ips->ips_ref, extr->ips->ips_refhim), extensions_reply) && /* The 3 lifetime extensions should only be sent if non-zero. */ (extensions[K_SADB_EXT_LIFETIME_HARD] == 0 || pfkey_safe_build(error = pfkey_lifetime_build(& extensions_reply [K_SADB_EXT_LIFETIME_HARD], K_SADB_EXT_LIFETIME_HARD, extr->ips->ips_life.ipl_allocations.ipl_hard, extr->ips->ips_life.ipl_bytes.ipl_hard, extr->ips->ips_life.ipl_addtime.ipl_hard, extr->ips->ips_life.ipl_usetime.ipl_hard, extr->ips->ips_life.ipl_packets.ipl_hard), extensions_reply)) && (extensions[K_SADB_EXT_LIFETIME_SOFT] == 0 || pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[K_SADB_EXT_LIFETIME_SOFT], K_SADB_EXT_LIFETIME_SOFT, extr->ips->ips_life.ipl_allocations.ipl_soft, extr->ips->ips_life.ipl_bytes.ipl_soft, extr->ips->ips_life.ipl_addtime.ipl_soft, extr->ips->ips_life.ipl_usetime.ipl_soft, extr->ips->ips_life.ipl_packets.ipl_soft), extensions_reply)) && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[K_SADB_EXT_ADDRESS_SRC], K_SADB_EXT_ADDRESS_SRC, 0, /*extr->ips->ips_said.proto,*/ 0, extr->ips->ips_addr_s), extensions_reply) && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[K_SADB_EXT_ADDRESS_DST], K_SADB_EXT_ADDRESS_DST, 0, /*extr->ips->ips_said.proto,*/ 0, extr->ips->ips_addr_d), extensions_reply) && (extr->ips->ips_ident_s.data == 0 || pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[K_SADB_EXT_IDENTITY_SRC ], K_SADB_EXT_IDENTITY_SRC, extr->ips->ips_ident_s.type, extr->ips->ips_ident_s.id, extr->ips->ips_ident_s.len, extr->ips->ips_ident_s.data), extensions_reply)) && (extr->ips->ips_ident_d.data == 0 || pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[K_SADB_EXT_IDENTITY_DST], K_SADB_EXT_IDENTITY_DST, extr->ips->ips_ident_d.type, extr->ips->ips_ident_d.id, extr->ips->ips_ident_d.len, extr->ips->ips_ident_d.data), extensions_reply)) #if 0 /* FIXME: This won't work yet because I have not finished it */ && (extr->ips->ips_sens_== 0 || pfkey_safe_build(error = pfkey_sens_build(&extensions_reply[K_SADB_EXT_SENSITIVITY], extr->ips->ips_sens_dpd, extr->ips->ips_sens_sens_level, extr->ips->ips_sens_sens_len, extr->ips->ips_sens_sens_bitmap, extr->ips->ips_sens_integ_level, extr->ips->ips_sens_integ_len, extr->ips->ips_sens_integ_bitmap), extensions_reply)) #endif )) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: " "failed to build the add reply message extensions\n"); SENDERR(-error); } if ((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: " "failed to build the add reply message\n"); SENDERR(-error); } for (pfkey_socketsp = pfkey_open_sockets; pfkey_socketsp; pfkey_socketsp = pfkey_socketsp->next) { if ((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: " "sending up add reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", satype, satype2name(satype), pfkey_socketsp->socketp, error); SENDERR(-error); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: " "sending up add reply message for satype=%d(%s) to socket=0p%p succeeded.\n", satype, satype2name(satype), pfkey_socketsp->socketp); } if (extr->outif != 0 && extr->outif != -1) { extr->ips->ips_out = ipsec_mast_get_device(extr->outif); extr->ips->ips_transport_direct = ipsec_mast_is_transport( extr->outif); } /* ipsec_sa_add does tdb_lock */ if ((error = ipsec_sa_add(extr->ips))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: " "failed to add the mature SA=%s with error=%d.\n", sa_len ? sa : " (error)", error); SENDERR(-error); } extr->ips = NULL; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: " "successful for SA: %s\n", sa_len ? sa : " (error)"); errlab: if (pfkey_reply) pfkey_msg_free(&pfkey_reply); pfkey_extensions_free(extensions_reply); return error; } DEBUG_NO_STATIC int pfkey_delete_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data *extr) { struct ipsec_sa *ipsp, *ipsq, *ipsr; char sa[SATOT_BUF]; size_t sa_len; int error = 0; struct sadb_ext *extensions_reply[K_SADB_EXT_MAX + 1]; struct sadb_msg *pfkey_reply = NULL; struct socket_list *pfkey_socketsp; uint8_t satype = ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_satype; IPsecSAref_t ref; struct sadb_builds sab; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_delete_parse: .\n"); pfkey_extensions_init(extensions_reply); if (!extr || !extr->ips) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_delete_parse: " "extr or extr->ips pointer NULL, fatal\n"); SENDERR(EINVAL); } sa_len = KLIPS_SATOT(debug_pfkey, &extr->ips->ips_said, 0, sa, sizeof(sa)); spin_lock_bh(&tdb_lock); ipsp = ipsec_sa_getbyid(&(extr->ips->ips_said), IPSEC_REFSA); if (ipsp == NULL) { spin_unlock_bh(&tdb_lock); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_delete_parse: " "ipsec_sa not found for SA:%s, could not delete.\n", sa_len ? sa : " (error)"); SENDERR(ESRCH); } ref = ipsp->ips_ref; /* save a copy of ref */ /* * remove it from SAref tables * * if we are part of a group we must untern/rm the whole group * as this is what user space expects, so find the start of the chain. */ ipsq = ipsp; while (ipsq->ips_prev) ipsq = ipsq->ips_prev; while (ipsq) { ipsr = ipsq->ips_next; ipsec_sa_untern(ipsq); ipsec_sa_rm(ipsq); ipsq = ipsr; } /* this will call delchain-equivalent if refcount -> 0 * noting that get() above, added to ref count */ ipsec_sa_put(ipsp, IPSEC_REFSA); /* put the original ALLOC to free the SA */ ipsq = ipsp; while (ipsq->ips_prev) ipsq = ipsq->ips_prev; /* this should cause ipsec_sa_wipe to get called on the SA/group */ ipsec_sa_put(ipsq, IPSEC_REFALLOC); spin_unlock_bh(&tdb_lock); memset(&sab, 0, sizeof(sab)); sab.sa_base.sadb_sa_exttype = K_SADB_EXT_SA; sab.sa_base.sadb_sa_spi = extr->ips->ips_said.spi; sab.sa_base.sadb_sa_replay = 0; sab.sa_base.sadb_sa_state = 0; sab.sa_base.sadb_sa_auth = 0; sab.sa_base.sadb_sa_encrypt = 0; sab.sa_base.sadb_sa_flags = 0; sab.sa_base.sadb_x_sa_ref = ref; if (!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], K_SADB_DELETE, satype, 0, ((struct sadb_msg*) extensions[K_SADB_EXT_RESERVED])->sadb_msg_seq, ((struct sadb_msg*) extensions[K_SADB_EXT_RESERVED])->sadb_msg_pid), extensions_reply) && pfkey_safe_build(error = pfkey_sa_builds(&extensions_reply[K_SADB_EXT_SA], sab), extensions_reply) && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[K_SADB_EXT_ADDRESS_SRC], K_SADB_EXT_ADDRESS_SRC, 0, /*extr->ips->ips_said.proto,*/ 0, extr->ips->ips_addr_s), extensions_reply) && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[K_SADB_EXT_ADDRESS_DST], K_SADB_EXT_ADDRESS_DST, 0, /*extr->ips->ips_said.proto,*/ 0, extr->ips->ips_addr_d), extensions_reply) )) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_delete_parse: " "failed to build the delete reply message extensions\n"); SENDERR(-error); } if ((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_delete_parse: " "failed to build the delete reply message\n"); SENDERR(-error); } for (pfkey_socketsp = pfkey_open_sockets; pfkey_socketsp; pfkey_socketsp = pfkey_socketsp->next) { if ((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_delete_parse: " "sending up delete reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", satype, satype2name(satype), pfkey_socketsp->socketp, error); SENDERR(-error); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_delete_parse: " "sending up delete reply message for satype=%d(%s) to socket=0p%p succeeded.\n", satype, satype2name(satype), pfkey_socketsp->socketp); } errlab: if (pfkey_reply) pfkey_msg_free(&pfkey_reply); pfkey_extensions_free(extensions_reply); return error; } DEBUG_NO_STATIC int pfkey_get_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data *extr) { int error = 0; struct ipsec_sa *ipsp; char sa[SATOT_BUF]; size_t sa_len; struct sadb_ext *extensions_reply[K_SADB_EXT_MAX + 1]; struct sadb_msg *pfkey_reply = NULL; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: .\n"); pfkey_extensions_init(extensions_reply); if (!extr || !extr->ips) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: " "extr or extr->ips pointer NULL, fatal\n"); SENDERR(EINVAL); } sa_len = KLIPS_SATOT(debug_pfkey, &extr->ips->ips_said, 0, sa, sizeof(sa)); spin_lock_bh(&tdb_lock); ipsp = ipsec_sa_getbyid(&(extr->ips->ips_said), IPSEC_REFSA); if (ipsp == NULL) { spin_unlock_bh(&tdb_lock); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: " "ipsec_sa not found for SA=%s, could not get.\n", sa_len ? sa : " (error)"); SENDERR(ESRCH); } if (!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], K_SADB_GET, ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_satype, 0, ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_seq, ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_pid), extensions_reply) && pfkey_safe_build(error = pfkey_sa_build(&extensions_reply[K_SADB_EXT_SA], K_SADB_EXT_SA, extr->ips->ips_said.spi, extr->ips->ips_replaywin, extr->ips->ips_state, extr->ips->ips_authalg, extr->ips->ips_encalg, extr->ips->ips_flags), extensions_reply) && /* The 3 lifetime extensions should only be sent if non-zero. */ (!(ipsp->ips_life.ipl_allocations.ipl_count || ipsp->ips_life.ipl_bytes.ipl_count || ipsp->ips_life.ipl_addtime.ipl_count || ipsp->ips_life.ipl_usetime.ipl_count || ipsp->ips_life.ipl_packets.ipl_count) || pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[K_SADB_EXT_LIFETIME_CURRENT], K_SADB_EXT_LIFETIME_CURRENT, ipsp->ips_life.ipl_allocations.ipl_count, ipsp->ips_life.ipl_bytes.ipl_count, ipsp->ips_life.ipl_addtime.ipl_count, ipsp->ips_life.ipl_usetime.ipl_count, ipsp->ips_life.ipl_packets.ipl_count), extensions_reply)) && (!(ipsp->ips_life.ipl_allocations.ipl_hard || ipsp->ips_life.ipl_bytes.ipl_hard || ipsp->ips_life.ipl_addtime.ipl_hard || ipsp->ips_life.ipl_usetime.ipl_hard || ipsp->ips_life.ipl_packets.ipl_hard) || pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[K_SADB_EXT_LIFETIME_HARD], K_SADB_EXT_LIFETIME_HARD, ipsp->ips_life.ipl_allocations.ipl_hard, ipsp->ips_life.ipl_bytes.ipl_hard, ipsp->ips_life.ipl_addtime.ipl_hard, ipsp->ips_life.ipl_usetime.ipl_hard, ipsp->ips_life.ipl_packets.ipl_hard), extensions_reply)) && (!(ipsp->ips_life.ipl_allocations.ipl_soft || ipsp->ips_life.ipl_bytes.ipl_soft || ipsp->ips_life.ipl_addtime.ipl_soft || ipsp->ips_life.ipl_usetime.ipl_soft || ipsp->ips_life.ipl_packets.ipl_soft) || pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[K_SADB_EXT_LIFETIME_SOFT], K_SADB_EXT_LIFETIME_SOFT, ipsp->ips_life.ipl_allocations.ipl_soft, ipsp->ips_life.ipl_bytes.ipl_soft, ipsp->ips_life.ipl_addtime.ipl_soft, ipsp->ips_life.ipl_usetime.ipl_soft, ipsp->ips_life.ipl_packets.ipl_soft), extensions_reply)) && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[K_SADB_EXT_ADDRESS_SRC], K_SADB_EXT_ADDRESS_SRC, 0, /*extr->ips->ips_said.proto,*/ 0, extr->ips->ips_addr_s), extensions_reply) && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[K_SADB_EXT_ADDRESS_DST], K_SADB_EXT_ADDRESS_DST, 0, /*extr->ips->ips_said.proto,*/ 0, extr->ips->ips_addr_d), extensions_reply) && (extr->ips->ips_addr_p == NULL || pfkey_safe_build(error = pfkey_address_build(&extensions_reply[K_SADB_EXT_ADDRESS_PROXY], K_SADB_EXT_ADDRESS_PROXY, 0, /*extr->ips->ips_said.proto,*/ 0, extr->ips->ips_addr_p), extensions_reply)) #if 0 /* * FIXME: This won't work yet because the keys are not * stored directly in the ipsec_sa. They are stored as * contexts. */ && (extr->ips->ips_key_a_size == 0 || pfkey_safe_build(error = pfkey_key_build(&extensions_reply[K_SADB_EXT_KEY_AUTH], K_SADB_EXT_KEY_AUTH, extr->ips->ips_key_a_size * 8, extr->ips->ips_key_a), extensions_reply) : 1) /* * FIXME: This won't work yet because the keys are not * stored directly in the ipsec_sa. They are stored as * key schedules. */ && (extr->ips->ips_key_e_size ? pfkey_safe_build(error = pfkey_key_build(&extensions_reply[K_SADB_EXT_KEY_ENCRYPT], K_SADB_EXT_KEY_ENCRYPT, extr->ips->ips_key_e_size * 8, extr->ips->ips_key_e), extensions_reply)) #endif && (extr->ips->ips_ident_s.data == 0 || pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[K_SADB_EXT_IDENTITY_SRC], K_SADB_EXT_IDENTITY_SRC, extr->ips->ips_ident_s.type, extr->ips->ips_ident_s.id, extr->ips->ips_ident_s.len, extr->ips->ips_ident_s.data), extensions_reply)) && (extr->ips->ips_ident_d.data == 0 || pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[K_SADB_EXT_IDENTITY_DST], K_SADB_EXT_IDENTITY_DST, extr->ips->ips_ident_d.type, extr->ips->ips_ident_d.id, extr->ips->ips_ident_d.len, extr->ips->ips_ident_d.data), extensions_reply)) #if 0 /* FIXME: This won't work yet because I have not finished it */ && (extr->ips->ips_sens_== 0 || pfkey_safe_build(error = pfkey_sens_build(&extensions_reply[K_SADB_EXT_SENSITIVITY], extr->ips->ips_sens_dpd, extr->ips->ips_sens_sens_level, extr->ips->ips_sens_sens_len, extr->ips->ips_sens_sens_bitmap, extr->ips->ips_sens_integ_level, extr->ips->ips_sens_integ_len, extr->ips->ips_sens_integ_bitmap), extensions_reply)) #endif )) { ipsec_sa_put(ipsp, IPSEC_REFSA); spin_unlock_bh(&tdb_lock); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: " "failed to build the get reply message extensions\n"); SENDERR(-error); } ipsec_sa_put(ipsp, IPSEC_REFSA); spin_unlock_bh(&tdb_lock); if ((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: " "failed to build the get reply message\n"); SENDERR(-error); } if ((error = pfkey_upmsg(sk->sk_socket, pfkey_reply))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: " "failed to send the get reply message\n"); SENDERR(-error); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: " "succeeded in sending get reply message.\n"); errlab: if (pfkey_reply) pfkey_msg_free(&pfkey_reply); pfkey_extensions_free(extensions_reply); return error; } DEBUG_NO_STATIC int pfkey_acquire_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data *extr) { int error = 0; struct socket_list *pfkey_socketsp; uint8_t satype = ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_satype; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire_parse: .\n"); /* XXX I don't know if we want an upper bound, since userspace may want to register itself for an satype > K_SADB_SATYPE_MAX. */ if ((satype == 0) || (satype > K_SADB_SATYPE_MAX)) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire_parse: " "SATYPE=%d invalid.\n", satype); SENDERR(EINVAL); } if (!(pfkey_registered_sockets[satype])) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire_parse: " "no sockets registered for SAtype=%d(%s).\n", satype, satype2name(satype)); SENDERR(EPROTONOSUPPORT); } for (pfkey_socketsp = pfkey_registered_sockets[satype]; pfkey_socketsp; pfkey_socketsp = pfkey_socketsp->next) { if ((error = pfkey_upmsg(pfkey_socketsp->socketp, ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire_parse: " "sending up acquire reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", satype, satype2name(satype), pfkey_socketsp->socketp, error); SENDERR(-error); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire_parse: " "sending up acquire reply message for satype=%d(%s) to socket=0p%p succeeded.\n", satype, satype2name(satype), pfkey_socketsp->socketp); } errlab: return error; } DEBUG_NO_STATIC int pfkey_register_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data *extr) { int error = 0; uint8_t satype = ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_satype; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_parse: .\n"); /* XXX I don't know if we want an upper bound, since userspace may want to register itself for an satype > K_SADB_SATYPE_MAX. */ if ((satype == 0) || (satype > K_SADB_SATYPE_MAX)) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_parse: " "SATYPE=%d invalid.\n", satype); SENDERR(EINVAL); } if (!pfkey_list_insert_socket(sk->sk_socket, &(pfkey_registered_sockets[satype]))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_parse: " "SATYPE=%02d(%s) successfully registered by KMd (pid=%d).\n", satype, satype2name(satype), key_pid(sk)); } /* send up register msg with supported SATYPE algos */ error = pfkey_register_reply(satype, (struct sadb_msg*)extensions[K_SADB_EXT_RESERVED]); errlab: return error; } int pfkey_register_reply(int satype, struct sadb_msg *sadb_msg) { struct sadb_ext *extensions_reply[K_SADB_EXT_MAX + 1]; struct sadb_msg *pfkey_reply = NULL; struct socket_list *pfkey_socketsp; struct supported_list *pfkey_supported_listp; unsigned int alg_num_a = 0, alg_num_e = 0; struct sadb_alg *alg_a = NULL, *alg_e = NULL, *alg_ap = NULL, *alg_ep = NULL; int error = 0; pfkey_extensions_init(extensions_reply); if ((satype == 0) || (satype > K_SADB_SATYPE_MAX)) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " "SAtype=%d unspecified or unknown.\n", satype); SENDERR(EINVAL); } if (!(pfkey_registered_sockets[satype])) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " "no sockets registered for SAtype=%d(%s).\n", satype, satype2name(satype)); SENDERR(EPROTONOSUPPORT); } /* send up register msg with supported SATYPE algos */ pfkey_supported_listp = pfkey_supported_list[satype]; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " "pfkey_supported_list[%d]=0p%p\n", satype, pfkey_supported_list[satype]); while (pfkey_supported_listp) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " "checking supported=0p%p\n", pfkey_supported_listp); if (pfkey_supported_listp->supportedp->ias_exttype == K_SADB_EXT_SUPPORTED_AUTH) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " "adding auth alg.\n"); alg_num_a++; } if (pfkey_supported_listp->supportedp->ias_exttype == K_SADB_EXT_SUPPORTED_ENCRYPT) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " "adding encrypt alg.\n"); alg_num_e++; } pfkey_supported_listp = pfkey_supported_listp->next; } if (alg_num_a) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " "allocating %zu bytes for auth algs.\n", alg_num_a * sizeof(struct sadb_alg)); if ((alg_a = kmalloc(alg_num_a * sizeof(struct sadb_alg), GFP_ATOMIC) ) == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " "auth alg memory allocation error\n"); SENDERR(ENOMEM); } alg_ap = alg_a; } if (alg_num_e) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " "allocating %zu bytes for enc algs.\n", alg_num_e * sizeof(struct sadb_alg)); if ((alg_e = kmalloc(alg_num_e * sizeof(struct sadb_alg), GFP_ATOMIC) ) == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " "enc alg memory allocation error\n"); SENDERR(ENOMEM); } alg_ep = alg_e; } pfkey_supported_listp = pfkey_supported_list[satype]; while (pfkey_supported_listp) { if (alg_num_a) { if (pfkey_supported_listp->supportedp->ias_exttype == K_SADB_EXT_SUPPORTED_AUTH) { alg_ap->sadb_alg_id = pfkey_supported_listp->supportedp->ias_id; alg_ap->sadb_alg_ivlen = pfkey_supported_listp->supportedp->ias_ivlen; alg_ap->sadb_alg_minbits = pfkey_supported_listp->supportedp->ias_keyminbits; alg_ap->sadb_alg_maxbits = pfkey_supported_listp->supportedp->ias_keymaxbits; alg_ap->sadb_alg_reserved = 0; KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "klips_debug:pfkey_register_reply: " "adding auth=0p%p\n", alg_ap); alg_ap++; } } if (alg_num_e) { if (pfkey_supported_listp->supportedp->ias_exttype == K_SADB_EXT_SUPPORTED_ENCRYPT) { alg_ep->sadb_alg_id = pfkey_supported_listp->supportedp->ias_id; alg_ep->sadb_alg_ivlen = pfkey_supported_listp->supportedp->ias_ivlen; alg_ep->sadb_alg_minbits = pfkey_supported_listp->supportedp->ias_keyminbits; alg_ep->sadb_alg_maxbits = pfkey_supported_listp->supportedp->ias_keymaxbits; alg_ep->sadb_alg_reserved = 0; KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "klips_debug:pfkey_register_reply: " "adding encrypt=0p%p\n", alg_ep); alg_ep++; } } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " "found satype=%d(%s) exttype=%d id=%d ivlen=%d minbits=%d maxbits=%d.\n", satype, satype2name(satype), pfkey_supported_listp->supportedp->ias_exttype, pfkey_supported_listp->supportedp->ias_id, pfkey_supported_listp->supportedp->ias_ivlen, pfkey_supported_listp->supportedp->ias_keyminbits, pfkey_supported_listp->supportedp->ias_keymaxbits); pfkey_supported_listp = pfkey_supported_listp->next; } if (!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], K_SADB_REGISTER, satype, 0, sadb_msg ? sadb_msg->sadb_msg_seq : ++ pfkey_msg_seq, sadb_msg ? sadb_msg->sadb_msg_pid : #ifdef HAVE_USER_NS pfkey_kuid_to_uid(current_uid())), #else current_uid()), #endif extensions_reply) && (alg_num_a == 0 || pfkey_safe_build(error = pfkey_supported_build(&extensions_reply[K_SADB_EXT_SUPPORTED_AUTH], K_SADB_EXT_SUPPORTED_AUTH, alg_num_a, alg_a), extensions_reply)) && (alg_num_e == 0 || pfkey_safe_build(error = pfkey_supported_build(&extensions_reply[K_SADB_EXT_SUPPORTED_ENCRYPT], K_SADB_EXT_SUPPORTED_ENCRYPT, alg_num_e, alg_e), extensions_reply)))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " "failed to build the register message extensions_reply\n"); SENDERR(-error); } if ((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " "failed to build the register message\n"); SENDERR(-error); } /* this should go to all registered sockets for that satype only */ for (pfkey_socketsp = pfkey_registered_sockets[satype]; pfkey_socketsp; pfkey_socketsp = pfkey_socketsp->next) { if ((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " "sending up acquire message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", satype, satype2name(satype), pfkey_socketsp->socketp, error); SENDERR(-error); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: " "sending up register message for satype=%d(%s) to socket=0p%p succeeded.\n", satype, satype2name(satype), pfkey_socketsp->socketp); } errlab: if (alg_a) kfree(alg_a); if (alg_e) kfree(alg_e); if (pfkey_reply) pfkey_msg_free(&pfkey_reply); pfkey_extensions_free(extensions_reply); return error; } DEBUG_NO_STATIC int pfkey_expire_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data *extr) { int error = 0; struct socket_list *pfkey_socketsp; uint8_t satype = ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_satype; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire_parse: .\n"); if (pfkey_open_sockets) { for (pfkey_socketsp = pfkey_open_sockets; pfkey_socketsp; pfkey_socketsp = pfkey_socketsp->next) { if ((error = pfkey_upmsg(pfkey_socketsp->socketp, ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire_parse: " "sending up expire reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", satype, satype2name(satype), pfkey_socketsp->socketp, error); SENDERR(-error); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire_parse: " "sending up expire reply message for satype=%d(%s) to socket=0p%p succeeded.\n", satype, satype2name(satype), pfkey_socketsp->socketp); } } errlab: return error; } /* * * flush all SAs from the table */ DEBUG_NO_STATIC int pfkey_flush_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data *extr) { int error = 0; struct socket_list *pfkey_socketsp; uint8_t satype = ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_satype; uint8_t proto = 0; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_flush_parse: " "flushing type %d SAs\n", satype); if (satype && !(proto = satype2proto(satype))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_flush_parse: " "satype %d lookup failed.\n", ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_satype); SENDERR(EINVAL); } if ((error = ipsec_sadb_cleanup(proto))) SENDERR(-error); if (pfkey_open_sockets) { for (pfkey_socketsp = pfkey_open_sockets; pfkey_socketsp; pfkey_socketsp = pfkey_socketsp->next) { if ((error = pfkey_upmsg(pfkey_socketsp->socketp, ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_flush_parse: " "sending up flush reply message for satype=%d(%s) (proto=%d) to socket=0p%p failed with error=%d.\n", satype, satype2name(satype), proto, pfkey_socketsp->socketp, error); SENDERR(-error); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_flush_parse: " "sending up flush reply message for satype=%d(%s) to socket=0p%p succeeded.\n", satype, satype2name(satype), pfkey_socketsp->socketp); } } errlab: return error; } DEBUG_NO_STATIC int pfkey_dump_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data *extr) { int error = 0; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_dump_parse: .\n"); SENDERR(ENOSYS); errlab: return error; } DEBUG_NO_STATIC int pfkey_x_promisc_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data *extr) { int error = 0; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_promisc_parse: .\n"); SENDERR(ENOSYS); errlab: return error; } DEBUG_NO_STATIC int pfkey_x_pchange_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data *extr) { int error = 0; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_pchange_parse: .\n"); SENDERR(ENOSYS); errlab: return error; } DEBUG_NO_STATIC int pfkey_x_grpsa_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data *extr) { struct ipsec_sa *ips1p, *ips2p, *ipsp; struct sadb_ext *extensions_reply[K_SADB_EXT_MAX + 1]; struct sadb_msg *pfkey_reply = NULL; struct socket_list *pfkey_socketsp; uint8_t satype = ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_satype; char sa1[SATOT_BUF], sa2[SATOT_BUF]; size_t sa_len1, sa_len2 = 0; int error = 0; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: .\n"); pfkey_extensions_init(extensions_reply); if (extr == NULL || extr->ips == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: " "extr or extr->ips is NULL, fatal.\n"); SENDERR(EINVAL); } sa_len1 = KLIPS_SATOT(debug_pfkey, &extr->ips->ips_said, 0, sa1, sizeof(sa1)); if (extr->ips2 != NULL) sa_len2 = KLIPS_SATOT(debug_pfkey, &extr->ips2->ips_said, 0, sa2, sizeof(sa2)); spin_lock_bh(&tdb_lock); ips1p = ipsec_sa_getbyid(&(extr->ips->ips_said), IPSEC_REFSA); if (ips1p == NULL) { spin_unlock_bh(&tdb_lock); KLIPS_ERROR(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: " "reserved ipsec_sa for SA1: %s not found. Call K_SADB_ADD/UPDATE first.\n", sa_len1 ? sa1 : " (error)"); SENDERR(ENOENT); } if (extr->ips2) { /* GRPSA */ /* group ips2p to be after ips1p */ ips2p = ipsec_sa_getbyid(&(extr->ips2->ips_said), IPSEC_REFSA); if (ips2p == NULL) { ipsec_sa_put(ips1p, IPSEC_REFSA); spin_unlock_bh(&tdb_lock); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: " "reserved ipsec_sa for SA2: %s not found. Call K_SADB_ADD/UPDATE first.\n", sa_len2 ? sa2 : " (error)"); SENDERR(ENOENT); } /* userspace puts things in inner to outer order */ if (ips2p->ips_flags & EMT_INBOUND) { struct ipsec_sa *t; /* exchange ips and ips2 */ t = ips1p; ips1p = ips2p; ips2p = t; } /* Is ips1p already linked? */ if (ips1p->ips_next) { ipsec_sa_put(ips1p, IPSEC_REFSA); ipsec_sa_put(ips2p, IPSEC_REFSA); spin_unlock_bh(&tdb_lock); KLIPS_ERROR(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: " "ipsec_sa for SA: %s is already linked.\n", sa_len1 ? sa1 : " (error)"); SENDERR(EEXIST); } /* Is extr->ips already linked to extr->ips2? */ ipsp = ips2p; while (ipsp) { if (ipsp == ips1p) { ipsec_sa_put(ips1p, IPSEC_REFSA); ipsec_sa_put(ips2p, IPSEC_REFSA); spin_unlock_bh(&tdb_lock); KLIPS_ERROR(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: " "ipsec_sa for SA: %s is already linked to %s.\n", sa_len1 ? sa1 : " (error)", sa_len2 ? sa2 : " (error)"); SENDERR(EEXIST); } ipsp = ipsp->ips_next; } /* link 'em */ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: " "linking ipsec_sa SA: %s with %s.\n", sa_len1 ? sa1 : " (error)", sa_len2 ? sa2 : " (error)"); ips1p->ips_next = ips2p; ips2p->ips_prev = ips1p; ipsec_sa_put(ips1p, IPSEC_REFSA); ipsec_sa_put(ips2p, IPSEC_REFSA); } else { /* UNGRPSA */ while (ips1p) { struct ipsec_sa *ipsn; /* take the reference to next */ ipsn = ips1p->ips_next; if (ipsn) ipsn->ips_prev = NULL; ips1p->ips_next = NULL; ips1p->ips_prev = NULL; /* drop reference to current */ ipsec_sa_put(ips1p, IPSEC_REFSA); ips1p = ipsn; } /* note: we have dropped reference to ips1p, and * it is now NULL */ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: " "unlinking ipsec_sa SA: %s.\n", sa_len1 ? sa1 : " (error)"); } spin_unlock_bh(&tdb_lock); /* MCR: not only is this ugly to read, and impossible * to debug through, but it's also really inefficient. * XXX simplify me. */ if (!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], K_SADB_X_GRPSA, satype, 0, ((struct sadb_msg*) extensions[K_SADB_EXT_RESERVED])->sadb_msg_seq, ((struct sadb_msg*) extensions[K_SADB_EXT_RESERVED])->sadb_msg_pid), extensions_reply) && pfkey_safe_build(error = pfkey_sa_build(&extensions_reply[K_SADB_EXT_SA], K_SADB_EXT_SA, extr->ips->ips_said.spi, extr->ips->ips_replaywin, extr->ips->ips_state, extr->ips->ips_authalg, extr->ips->ips_encalg, extr->ips->ips_flags), extensions_reply) && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[K_SADB_EXT_ADDRESS_DST], K_SADB_EXT_ADDRESS_DST, 0, /*extr->ips->ips_said.proto,*/ 0, extr->ips->ips_addr_d), extensions_reply) && (extr->ips2 == 0 || (pfkey_safe_build(error = pfkey_x_satype_build(&extensions_reply [K_SADB_X_EXT_SATYPE2], ((struct sadb_x_satype*) extensions[K_SADB_X_EXT_SATYPE2])->sadb_x_satype_satype /* proto2satype(extr->ips2->ips_said.proto) */), extensions_reply) && pfkey_safe_build(error = pfkey_sa_build(&extensions_reply[K_SADB_X_EXT_SA2], K_SADB_X_EXT_SA2, extr->ips2->ips_said.spi, extr->ips2->ips_replaywin, extr->ips2->ips_state, extr->ips2->ips_authalg, extr->ips2->ips_encalg, extr->ips2->ips_flags), extensions_reply) && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[K_SADB_X_EXT_ADDRESS_DST2], K_SADB_X_EXT_ADDRESS_DST2, 0, /*extr->ips->ips_said.proto,*/ 0, extr->ips2->ips_addr_d), extensions_reply) )) )) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: " "failed to build the x_grpsa reply message extensions\n"); SENDERR(-error); } if ((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: " "failed to build the x_grpsa reply message\n"); SENDERR(-error); } for (pfkey_socketsp = pfkey_open_sockets; pfkey_socketsp; pfkey_socketsp = pfkey_socketsp->next) { if ((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: " "sending up x_grpsa reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", satype, satype2name(satype), pfkey_socketsp->socketp, error); SENDERR(-error); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: " "sending up x_grpsa reply message for satype=%d(%s) to socket=0p%p succeeded.\n", satype, satype2name(satype), pfkey_socketsp->socketp); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: " "succeeded in sending x_grpsa reply message.\n"); errlab: if (pfkey_reply) pfkey_msg_free(&pfkey_reply); pfkey_extensions_free(extensions_reply); return error; } DEBUG_NO_STATIC int pfkey_x_addflow_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data *extr) { int error = 0; struct sadb_ext *extensions_reply[K_SADB_EXT_MAX + 1]; struct sadb_msg *pfkey_reply = NULL; struct socket_list *pfkey_socketsp; uint8_t satype = ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_satype; ip_address srcflow, dstflow, srcmask, dstmask; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: .\n"); pfkey_extensions_init(extensions_reply); memset((caddr_t)&srcflow, 0, sizeof(srcflow)); memset((caddr_t)&dstflow, 0, sizeof(dstflow)); memset((caddr_t)&srcmask, 0, sizeof(srcmask)); memset((caddr_t)&dstmask, 0, sizeof(dstmask)); if (!extr || !(extr->ips) || !(extr->eroute)) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " "missing extr, ipsec_sa or eroute data.\n"); SENDERR(EINVAL); } if (extr->eroute->er_eaddr.sen_type == SENT_IP6) { SET_V6(srcflow); SET_V6(dstflow); SET_V6(srcmask); SET_V6(dstmask); srcflow.u.v6.sin6_addr = extr->eroute->er_eaddr.sen_ip6_src; dstflow.u.v6.sin6_addr = extr->eroute->er_eaddr.sen_ip6_dst; srcmask.u.v6.sin6_addr = extr->eroute->er_emask.sen_ip6_src; dstmask.u.v6.sin6_addr = extr->eroute->er_emask.sen_ip6_dst; } else { SET_V4(srcflow); SET_V4(dstflow); SET_V4(srcmask); SET_V4(dstmask); srcflow.u.v4.sin_addr = extr->eroute->er_eaddr.sen_ip_src; dstflow.u.v4.sin_addr = extr->eroute->er_eaddr.sen_ip_dst; srcmask.u.v4.sin_addr = extr->eroute->er_emask.sen_ip_src; dstmask.u.v4.sin_addr = extr->eroute->er_emask.sen_ip_dst; } if (debug_pfkey) { char buf1[64], buf2[64]; if (extr->eroute->er_eaddr.sen_type == SENT_IP6) { subnet6toa(&extr->eroute->er_eaddr.sen_ip6_src, &extr->eroute->er_emask.sen_ip6_src, 0, buf1, sizeof(buf1)); subnet6toa(&extr->eroute->er_eaddr.sen_ip6_dst, &extr->eroute->er_emask.sen_ip6_dst, 0, buf2, sizeof(buf2)); } else { subnettoa(extr->eroute->er_eaddr.sen_ip_src, extr->eroute->er_emask.sen_ip_src, 0, buf1, sizeof(buf1)); subnettoa(extr->eroute->er_eaddr.sen_ip_dst, extr->eroute->er_emask.sen_ip_dst, 0, buf2, sizeof(buf2)); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " "calling breakeroute and/or makeroute for %s->%s\n", buf1, buf2); } if (extr->ips->ips_flags & SADB_X_SAFLAGS_INFLOW || extr->ips->ips_flags & SADB_X_SAFLAGS_POLICYONLY) { struct ipsec_sa *ipsp, *ipsq; char sa[SATOT_BUF]; size_t sa_len; spin_lock_bh(&tdb_lock); ipsq = ipsec_sa_getbyid(&(extr->ips->ips_said), IPSEC_REFSA); if (ipsq == NULL) { spin_unlock_bh(&tdb_lock); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " "ipsec_sa not found, cannot set incoming policy.\n"); SENDERR(ENOENT); } ipsp = ipsq; while (ipsp && ipsp->ips_said.proto != IPPROTO_IPIP) ipsp = ipsp->ips_next; if (ipsp == NULL) { ipsec_sa_put(ipsq, IPSEC_REFSA); spin_unlock_bh(&tdb_lock); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " "SA chain does not have an IPIP SA, cannot set incoming policy.\n"); SENDERR(ENOENT); } sa_len = KLIPS_SATOT(debug_pfkey, &extr->ips->ips_said, 0, sa, sizeof(sa)); ipsp->ips_flags |= extr->ips->ips_flags & (SADB_X_SAFLAGS_INFLOW | SADB_X_SAFLAGS_POLICYONLY); ipsp->ips_flow_s = srcflow; ipsp->ips_flow_d = dstflow; ipsp->ips_mask_s = srcmask; ipsp->ips_mask_d = dstmask; ipsec_sa_put(ipsq, IPSEC_REFSA); spin_unlock_bh(&tdb_lock); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " "inbound eroute, setting incoming policy information in IPIP ipsec_sa for SA: %s.\n", sa_len ? sa : " (error)"); } else { struct sk_buff *first = NULL, *last = NULL; if (extr->ips->ips_flags & SADB_X_SAFLAGS_REPLACEFLOW) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " "REPLACEFLOW flag set, calling breakeroute.\n"); if ((error = ipsec_breakroute(&(extr->eroute->er_eaddr), &(extr->eroute->er_emask), &first, &last))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " "breakeroute returned %d. first=0p%p, last=0p%p\n", error, first, last); if (first != NULL) ipsec_kfree_skb(first); if (last != NULL) ipsec_kfree_skb(last); SENDERR(-error); } } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " "calling makeroute.\n"); if ((error = ipsec_makeroute(&(extr->eroute->er_eaddr), &(extr->eroute->er_emask), extr->ips->ips_said, ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_pid, NULL, &(extr->ips->ips_ident_s), &(extr->ips->ips_ident_d)))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " "makeroute returned %d.\n", error); SENDERR(-error); } if (first != NULL) { KLIPS_PRINT(debug_eroute, "klips_debug:pfkey_x_addflow_parse: " "first=0p%p HOLD packet re-injected.\n", first); dev_queue_xmit(first); } if (last != NULL) { KLIPS_PRINT(debug_eroute, "klips_debug:pfkey_x_addflow_parse: " "last=0p%p HOLD packet re-injected.\n", last); dev_queue_xmit(last); } } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " "makeroute call successful.\n"); if (!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], K_SADB_X_ADDFLOW, satype, 0, ((struct sadb_msg*) extensions[K_SADB_EXT_RESERVED])->sadb_msg_seq, ((struct sadb_msg*) extensions[K_SADB_EXT_RESERVED])->sadb_msg_pid), extensions_reply) && pfkey_safe_build(error = pfkey_sa_build(&extensions_reply[K_SADB_EXT_SA], K_SADB_EXT_SA, extr->ips->ips_said.spi, extr->ips->ips_replaywin, extr->ips->ips_state, extr->ips->ips_authalg, extr->ips->ips_encalg, extr->ips->ips_flags), extensions_reply) && (extensions[K_SADB_EXT_ADDRESS_SRC] == NULL || pfkey_safe_build(error = pfkey_address_build(&extensions_reply[K_SADB_EXT_ADDRESS_SRC], K_SADB_EXT_ADDRESS_SRC, 0, /*extr->ips->ips_said.proto,*/ 0, extr->ips->ips_addr_s), extensions_reply)) && (extensions[K_SADB_EXT_ADDRESS_DST] == NULL || pfkey_safe_build(error = pfkey_address_build(&extensions_reply[K_SADB_EXT_ADDRESS_DST], K_SADB_EXT_ADDRESS_DST, 0, /*extr->ips->ips_said.proto,*/ 0, extr->ips->ips_addr_d), extensions_reply)) && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[K_SADB_X_EXT_ADDRESS_SRC_FLOW], K_SADB_X_EXT_ADDRESS_SRC_FLOW, 0, /*extr->ips->ips_said.proto,*/ 0, (struct sockaddr*)&srcflow), extensions_reply) && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[K_SADB_X_EXT_ADDRESS_DST_FLOW], K_SADB_X_EXT_ADDRESS_DST_FLOW, 0, /*extr->ips->ips_said.proto,*/ 0, (struct sockaddr*)&dstflow), extensions_reply) && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[K_SADB_X_EXT_ADDRESS_SRC_MASK], K_SADB_X_EXT_ADDRESS_SRC_MASK, 0, /*extr->ips->ips_said.proto,*/ 0, (struct sockaddr*)&srcmask), extensions_reply) && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[K_SADB_X_EXT_ADDRESS_DST_MASK], K_SADB_X_EXT_ADDRESS_DST_MASK, 0, /*extr->ips->ips_said.proto,*/ 0, (struct sockaddr*)&dstmask), extensions_reply) )) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " "failed to build the x_addflow reply message extensions\n"); SENDERR(-error); } if ((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " "failed to build the x_addflow reply message\n"); SENDERR(-error); } for (pfkey_socketsp = pfkey_open_sockets; pfkey_socketsp; pfkey_socketsp = pfkey_socketsp->next) { if ((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " "sending up x_addflow reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", satype, satype2name(satype), pfkey_socketsp->socketp, error); SENDERR(-error); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " "sending up x_addflow reply message for satype=%d(%s) (proto=%d) to socket=0p%p succeeded.\n", satype, satype2name(satype), extr->ips->ips_said.proto, pfkey_socketsp->socketp); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: " "extr->ips cleaned up and freed.\n"); errlab: if (pfkey_reply) pfkey_msg_free(&pfkey_reply); pfkey_extensions_free(extensions_reply); return error; } DEBUG_NO_STATIC int pfkey_x_delflow_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data *extr) { int error = 0; struct sadb_ext *extensions_reply[K_SADB_EXT_MAX + 1]; struct sadb_msg *pfkey_reply = NULL; struct socket_list *pfkey_socketsp; uint8_t satype = ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_satype; ip_address srcflow, dstflow, srcmask, dstmask; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: .\n"); pfkey_extensions_init(extensions_reply); memset((caddr_t)&srcflow, 0, sizeof(srcflow)); memset((caddr_t)&dstflow, 0, sizeof(dstflow)); memset((caddr_t)&srcmask, 0, sizeof(srcmask)); memset((caddr_t)&dstmask, 0, sizeof(dstmask)); if (!extr || !(extr->ips)) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: " "extr, or extr->ips is NULL, fatal\n"); SENDERR(EINVAL); } if (extr->ips->ips_flags & SADB_X_SAFLAGS_POLICYONLY) { /* nothing else to do */ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: " "POLICYONLY flag set, done.\n"); } else if (extr->ips->ips_flags & SADB_X_SAFLAGS_CLEARFLOW) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: " "CLEARFLOW flag set, calling cleareroutes.\n"); if ((error = ipsec_cleareroutes())) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: " "cleareroutes returned %d.\n", error); SENDERR(-error); } } else { struct sk_buff *first = NULL, *last = NULL; if (!(extr->eroute)) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: " "extr->eroute is NULL, fatal.\n"); SENDERR(EINVAL); } if (extr->eroute->er_eaddr.sen_type == SENT_IP6) { SET_V6(srcflow); SET_V6(dstflow); SET_V6(srcmask); SET_V6(dstmask); srcflow.u.v6.sin6_addr = extr->eroute->er_eaddr.sen_ip6_src; dstflow.u.v6.sin6_addr = extr->eroute->er_eaddr.sen_ip6_dst; srcmask.u.v6.sin6_addr = extr->eroute->er_emask.sen_ip6_src; dstmask.u.v6.sin6_addr = extr->eroute->er_emask.sen_ip6_dst; } else { SET_V4(srcflow); SET_V4(dstflow); SET_V4(srcmask); SET_V4(dstmask); srcflow.u.v4.sin_addr = extr->eroute->er_eaddr.sen_ip_src; dstflow.u.v4.sin_addr = extr->eroute->er_eaddr.sen_ip_dst; srcmask.u.v4.sin_addr = extr->eroute->er_emask.sen_ip_src; dstmask.u.v4.sin_addr = extr->eroute->er_emask.sen_ip_dst; } if (debug_pfkey) { char buf1[64], buf2[64]; if (extr->eroute->er_eaddr.sen_type == SENT_IP6) { subnet6toa(&extr->eroute->er_eaddr.sen_ip6_src, &extr->eroute->er_emask.sen_ip6_src, 0, buf1, sizeof(buf1)); subnet6toa(&extr->eroute->er_eaddr.sen_ip6_dst, &extr->eroute->er_emask.sen_ip6_dst, 0, buf2, sizeof(buf2)); } else { subnettoa(extr->eroute->er_eaddr.sen_ip_src, extr->eroute->er_emask.sen_ip_src, 0, buf1, sizeof(buf1)); subnettoa(extr->eroute->er_eaddr.sen_ip_dst, extr->eroute->er_emask.sen_ip_dst, 0, buf2, sizeof(buf2)); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: " "calling breakeroute for %s->%s\n", buf1, buf2); } error = ipsec_breakroute(&(extr->eroute->er_eaddr), &(extr->eroute->er_emask), &first, &last); if (error) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: " "breakeroute returned %d. first=0p%p, last=0p%p\n", error, first, last); } if (first != NULL) ipsec_kfree_skb(first); if (last != NULL) ipsec_kfree_skb(last); if (error) SENDERR(-error); } error = pfkey_msg_hdr_build(&extensions_reply[0], K_SADB_X_DELFLOW, satype, 0, ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_seq, ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED])->sadb_msg_pid); if (pfkey_safe_build(error, extensions_reply)) { error = pfkey_sa_build(&extensions_reply[K_SADB_EXT_SA], K_SADB_EXT_SA, extr->ips->ips_said.spi, extr->ips->ips_replaywin, extr->ips->ips_state, extr->ips->ips_authalg, extr->ips->ips_encalg, extr->ips->ips_flags); } if (!(extr->ips->ips_flags & (SADB_X_SAFLAGS_CLEARFLOW | SADB_X_SAFLAGS_POLICYONLY))) { if (pfkey_safe_build(error, extensions_reply)) { error = pfkey_address_build( &extensions_reply[K_SADB_X_EXT_ADDRESS_SRC_FLOW], K_SADB_X_EXT_ADDRESS_SRC_FLOW, 0, /*extr->ips->ips_said.proto,*/ 0, (struct sockaddr*)&srcflow); } if (pfkey_safe_build(error, extensions_reply)) { error = pfkey_address_build( &extensions_reply[K_SADB_X_EXT_ADDRESS_DST_FLOW], K_SADB_X_EXT_ADDRESS_DST_FLOW, 0, /*extr->ips->ips_said.proto,*/ 0, (struct sockaddr*)&dstflow); } if (pfkey_safe_build(error, extensions_reply)) { error = pfkey_address_build( &extensions_reply[K_SADB_X_EXT_ADDRESS_SRC_MASK], K_SADB_X_EXT_ADDRESS_SRC_MASK, 0, /*extr->ips->ips_said.proto,*/ 0, (struct sockaddr*)&srcmask); } if (pfkey_safe_build(error, extensions_reply)) { error = pfkey_address_build( &extensions_reply[K_SADB_X_EXT_ADDRESS_DST_MASK], K_SADB_X_EXT_ADDRESS_DST_MASK, 0, /*extr->ips->ips_said.proto,*/ 0, (struct sockaddr*)&dstmask); } } if (!pfkey_safe_build(error, extensions_reply)) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: " "failed to build the x_delflow reply message extensions\n"); SENDERR(-error); } if ((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: " "failed to build the x_delflow reply message\n"); SENDERR(-error); } for (pfkey_socketsp = pfkey_open_sockets; pfkey_socketsp; pfkey_socketsp = pfkey_socketsp->next) { if ((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: " "sending up x_delflow reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", satype, satype2name(satype), pfkey_socketsp->socketp, error); SENDERR(-error); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: " "sending up x_delflow reply message for satype=%d(%s) to socket=0p%p succeeded.\n", satype, satype2name(satype), pfkey_socketsp->socketp); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: " "extr->ips cleaned up and freed.\n"); errlab: if (pfkey_reply) pfkey_msg_free(&pfkey_reply); pfkey_extensions_free(extensions_reply); return error; } DEBUG_NO_STATIC int pfkey_x_msg_debug_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data *extr) { int error = 0; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_msg_debug_parse: .\n"); /* errlab:*/ return error; } /* pfkey_expire expects the ipsec_sa table to be locked before being called. */ int pfkey_expire(struct ipsec_sa *ipsp, int hard) { struct sadb_ext *extensions[K_SADB_EXT_MAX + 1]; struct sadb_msg *pfkey_msg = NULL; struct socket_list *pfkey_socketsp; int error = 0; uint8_t satype; pfkey_extensions_init(extensions); if (!(satype = proto2satype(ipsp->ips_said.proto))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: " "satype lookup for protocol %d lookup failed.\n", ipsp->ips_said.proto); SENDERR(EINVAL); } if (!pfkey_open_sockets) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: " "no sockets listening.\n"); SENDERR(EPROTONOSUPPORT); } if (!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions[0], K_SADB_EXPIRE, satype, 0, ++pfkey_msg_seq, 0), extensions) && pfkey_safe_build(error = pfkey_sa_build(&extensions[K_SADB_EXT_SA ], K_SADB_EXT_SA, ipsp->ips_said.spi, ipsp->ips_replaywin, ipsp->ips_state, ipsp->ips_authalg, ipsp->ips_encalg, ipsp->ips_flags), extensions) && pfkey_safe_build(error = pfkey_lifetime_build(&extensions[K_SADB_EXT_LIFETIME_CURRENT], K_SADB_EXT_LIFETIME_CURRENT, ipsp->ips_life.ipl_allocations.ipl_count, ipsp->ips_life.ipl_bytes.ipl_count, ipsp->ips_life.ipl_addtime.ipl_count, ipsp->ips_life.ipl_usetime.ipl_count, ipsp->ips_life.ipl_packets.ipl_count), extensions) && (hard ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions[K_SADB_EXT_LIFETIME_HARD], K_SADB_EXT_LIFETIME_HARD, ipsp->ips_life.ipl_allocations.ipl_hard, ipsp->ips_life.ipl_bytes.ipl_hard, ipsp->ips_life.ipl_addtime.ipl_hard, ipsp->ips_life.ipl_usetime.ipl_hard, ipsp->ips_life.ipl_packets.ipl_hard), extensions) : pfkey_safe_build(error = pfkey_lifetime_build(&extensions[K_SADB_EXT_LIFETIME_SOFT], K_SADB_EXT_LIFETIME_SOFT, ipsp->ips_life.ipl_allocations.ipl_soft, ipsp->ips_life.ipl_bytes.ipl_soft, ipsp->ips_life.ipl_addtime.ipl_soft, ipsp->ips_life.ipl_usetime.ipl_soft, ipsp->ips_life.ipl_packets.ipl_soft), extensions)) && pfkey_safe_build(error = pfkey_address_build(&extensions[K_SADB_EXT_ADDRESS_SRC], K_SADB_EXT_ADDRESS_SRC, 0, /* ipsp->ips_said.proto, */ 0, ipsp->ips_addr_s), extensions) && pfkey_safe_build(error = pfkey_address_build(&extensions[K_SADB_EXT_ADDRESS_DST], K_SADB_EXT_ADDRESS_DST, 0, /* ipsp->ips_said.proto, */ 0, ipsp->ips_addr_d), extensions))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: " "failed to build the expire message extensions\n"); spin_unlock_bh(&tdb_lock); goto errlab; } if ((error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_OUT))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: " "failed to build the expire message\n"); SENDERR(-error); } for (pfkey_socketsp = pfkey_open_sockets; pfkey_socketsp; pfkey_socketsp = pfkey_socketsp->next) { if ((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_msg))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: " "sending up expire message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", satype, satype2name(satype), pfkey_socketsp->socketp, error); SENDERR(-error); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: " "sending up expire message for satype=%d(%s) (proto=%d) to socket=0p%p succeeded.\n", satype, satype2name(satype), ipsp->ips_said.proto, pfkey_socketsp->socketp); } errlab: if (pfkey_msg) pfkey_msg_free(&pfkey_msg); pfkey_extensions_free(extensions); return error; } int pfkey_acquire(struct ipsec_sa *ipsp) { struct sadb_ext *extensions[K_SADB_EXT_MAX + 1]; struct sadb_msg *pfkey_msg = NULL; struct socket_list *pfkey_socketsp; int error = 0; struct sadb_comb comb[] = { /* auth; encrypt; flags; */ /* auth_minbits; auth_maxbits; encrypt_minbits; encrypt_maxbits; */ /* reserved; soft_allocations; hard_allocations; soft_bytes; hard_bytes; */ /* soft_addtime; hard_addtime; soft_usetime; hard_usetime; */ /* soft_packets; hard_packets; */ { K_SADB_AALG_MD5HMAC, K_SADB_EALG_3DESCBC, SADB_SAFLAGS_PFS, 128, 128, 168, 168, 0, 0, 0, 0, 0, 16*secs_per_hour, secs_per_day, 16*secs_per_hour, secs_per_day }, { K_SADB_AALG_SHA1HMAC, K_SADB_EALG_3DESCBC, SADB_SAFLAGS_PFS, 160, 160, 168, 168, 0, 0, 0, 0, 0, 16*secs_per_hour, secs_per_day, 16*secs_per_hour, secs_per_day }, }; /* XXX This should not be hard-coded. It should be taken from the spdb */ uint8_t satype = K_SADB_SATYPE_ESP; pfkey_extensions_init(extensions); if ((satype == 0) || (satype > K_SADB_SATYPE_MAX)) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire: " "SAtype=%d unspecified or unknown.\n", satype); SENDERR(EINVAL); } if (!(pfkey_registered_sockets[satype])) { KLIPS_PRINT(1 | debug_pfkey, "klips_debug:pfkey_acquire: " "no sockets registered for SAtype=%d(%s).\n", satype, satype2name(satype)); SENDERR(EPROTONOSUPPORT); } if (!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions[0], K_SADB_ACQUIRE, satype, 0, ++pfkey_msg_seq, 0), extensions) && pfkey_safe_build(error = pfkey_address_build(&extensions[K_SADB_EXT_ADDRESS_SRC], K_SADB_EXT_ADDRESS_SRC, ipsp->ips_transport_protocol, 0, ipsp->ips_addr_s), extensions) && pfkey_safe_build(error = pfkey_address_build(&extensions[K_SADB_EXT_ADDRESS_DST], K_SADB_EXT_ADDRESS_DST, ipsp->ips_transport_protocol, 0, ipsp->ips_addr_d), extensions) #if 0 && (ipsp->ips_addr_p == NULL || pfkey_safe_build(error = pfkey_address_build(&extensions[K_SADB_EXT_ADDRESS_PROXY], K_SADB_EXT_ADDRESS_PROXY, ipsp->ips_transport_protocol, 0, ipsp->ips_addr_p), extensions)) #endif && (ipsp->ips_ident_s.type == SADB_IDENTTYPE_RESERVED || pfkey_safe_build(error = pfkey_ident_build(&extensions[SADB_EXT_IDENTITY_SRC], K_SADB_EXT_IDENTITY_SRC, ipsp->ips_ident_s.type, ipsp->ips_ident_s.id, ipsp->ips_ident_s.len, ipsp->ips_ident_s.data), extensions)) && (ipsp->ips_ident_d.type == SADB_IDENTTYPE_RESERVED || pfkey_safe_build(error = pfkey_ident_build(&extensions[K_SADB_EXT_IDENTITY_DST], K_SADB_EXT_IDENTITY_DST, ipsp->ips_ident_d.type, ipsp->ips_ident_d.id, ipsp->ips_ident_d.len, ipsp->ips_ident_d.data), extensions)) #if 0 /* FIXME: This won't work yet because I have not finished it */ && (ipsp->ips_sens_== 0 || pfkey_safe_build(error = pfkey_sens_build(&extensions[K_SADB_EXT_SENSITIVITY], ipsp->ips_sens_dpd, ipsp->ips_sens_sens_level, ipsp->ips_sens_sens_len, ipsp->ips_sens_sens_bitmap, ipsp->ips_sens_integ_level, ipsp->ips_sens_integ_len, ipsp->ips_sens_integ_bitmap), extensions)) #endif && pfkey_safe_build(error = pfkey_prop_build(&extensions[K_SADB_EXT_PROPOSAL], 64, /* replay */ sizeof(comb) / sizeof(struct sadb_comb), &(comb[0])), extensions) )) { KLIPS_PRINT(1 | debug_pfkey, "klips_debug:pfkey_acquire: " "failed to build the acquire message extensions\n"); SENDERR(-error); } if ((error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_OUT))) { KLIPS_PRINT(1 | debug_pfkey, "klips_debug:pfkey_acquire: " "failed to build the acquire message\n"); SENDERR(-error); } #ifdef KLIPS_PFKEY_ACQUIRE_LOSSAGE # if KLIPS_PFKEY_ACQUIRE_LOSSAGE > 0 if (sysctl_ipsec_regress_pfkey_lossage) return 0; # endif #endif /* this should go to all registered sockets for that satype only */ for (pfkey_socketsp = pfkey_registered_sockets[satype]; pfkey_socketsp; pfkey_socketsp = pfkey_socketsp->next) { if ((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_msg))) { KLIPS_PRINT(1 | debug_pfkey, "klips_debug:pfkey_acquire: " "sending up acquire message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", satype, satype2name(satype), pfkey_socketsp->socketp, error); SENDERR(-error); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire: " "sending up acquire message for satype=%d(%s) to socket=0p%p succeeded.\n", satype, satype2name(satype), pfkey_socketsp->socketp); } errlab: if (pfkey_msg) pfkey_msg_free(&pfkey_msg); pfkey_extensions_free(extensions); return error; } int pfkey_nat_t_new_mapping(struct ipsec_sa *ipsp, struct sockaddr *ipaddr, __u16 sport) { struct sadb_ext *extensions[K_SADB_EXT_MAX + 1]; struct sadb_msg *pfkey_msg = NULL; struct socket_list *pfkey_socketsp; int error = 0; uint8_t satype = (ipsp->ips_said.proto == IPPROTO_ESP) ? K_SADB_SATYPE_ESP : 0; /* Construct K_SADB_X_NAT_T_NEW_MAPPING message */ pfkey_extensions_init(extensions); if ((satype == 0) || (satype > K_SADB_SATYPE_MAX)) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: " "SAtype=%d unspecified or unknown.\n", satype); SENDERR(EINVAL); } if (!(pfkey_registered_sockets[satype])) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: " "no sockets registered for SAtype=%d(%s).\n", satype, satype2name(satype)); SENDERR(EPROTONOSUPPORT); } if (!(pfkey_safe_build (error = pfkey_msg_hdr_build(&extensions[0], K_SADB_X_NAT_T_NEW_MAPPING, satype, 0, ++pfkey_msg_seq, 0), extensions) && /* SA */ pfkey_safe_build (error = pfkey_sa_build(&extensions[K_SADB_EXT_SA], K_SADB_EXT_SA, ipsp->ips_said.spi, 0, 0, 0, 0, 0), extensions) && /* ADDRESS_SRC = old addr */ pfkey_safe_build (error = pfkey_address_build(&extensions[K_SADB_EXT_ADDRESS_SRC], K_SADB_EXT_ADDRESS_SRC, ipsp->ips_said.proto, 0, ipsp->ips_addr_s), extensions) && /* NAT_T_SPORT = old port */ pfkey_safe_build (error = pfkey_x_nat_t_port_build(&extensions[K_SADB_X_EXT_NAT_T_SPORT], K_SADB_X_EXT_NAT_T_SPORT, ipsp->ips_natt_sport), extensions) && /* ADDRESS_DST = new addr */ pfkey_safe_build (error = pfkey_address_build(&extensions[K_SADB_EXT_ADDRESS_DST], K_SADB_EXT_ADDRESS_DST, ipsp->ips_said.proto, 0, ipaddr), extensions) && /* NAT_T_DPORT = new port */ pfkey_safe_build (error = pfkey_x_nat_t_port_build(&extensions[K_SADB_X_EXT_NAT_T_DPORT], K_SADB_X_EXT_NAT_T_DPORT, sport), extensions) )) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: " "failed to build the nat_t_new_mapping message extensions\n"); SENDERR(-error); } if ((error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_OUT))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: " "failed to build the nat_t_new_mapping message\n"); SENDERR(-error); } /* this should go to all registered sockets for that satype only */ for (pfkey_socketsp = pfkey_registered_sockets[satype]; pfkey_socketsp; pfkey_socketsp = pfkey_socketsp->next) { if ((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_msg))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: " "sending up nat_t_new_mapping message for satype=%d(%s) to socket=%p failed with error=%d.\n", satype, satype2name(satype), pfkey_socketsp->socketp, error); SENDERR(-error); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: " "sending up nat_t_new_mapping message for satype=%d(%s) to socket=%p succeeded.\n", satype, satype2name(satype), pfkey_socketsp->socketp); } errlab: if (pfkey_msg) pfkey_msg_free(&pfkey_msg); pfkey_extensions_free(extensions); return error; } DEBUG_NO_STATIC int pfkey_x_nat_t_new_mapping_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data *extr) { /* K_SADB_X_NAT_T_NEW_MAPPING not used in kernel */ return -EINVAL; } /******************************* * EXTENSION PARSERS FOR KLIPS ********************************/ DEBUG_NO_STATIC int pfkey_x_outif_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr) { struct sadb_x_plumbif *oif; oif = (struct sadb_x_plumbif *)pfkey_ext; extr->outif = oif->sadb_x_outif_ifnum; return 0; } DEBUG_NO_STATIC int pfkey_x_saref_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr) { struct sadb_x_saref *saf; saf = (struct sadb_x_saref *)pfkey_ext; extr->sarefme = saf->sadb_x_saref_me; extr->sarefhim = saf->sadb_x_saref_him; return 0; } /* ext_processors: array of pointer to functions * * eg.: int ext_processor_function(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr) * returns 0 on success. */ DEBUG_NO_STATIC int(*ext_processors[K_SADB_EXT_MAX + 1]) ( struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr) = { NULL, /* pfkey_msg_process, */ pfkey_sa_process, pfkey_lifetime_process, pfkey_lifetime_process, pfkey_lifetime_process, pfkey_address_process, pfkey_address_process, pfkey_address_process, pfkey_key_process, pfkey_key_process, pfkey_ident_process, pfkey_ident_process, pfkey_sens_process, pfkey_prop_process, pfkey_supported_process, pfkey_supported_process, pfkey_spirange_process, pfkey_x_kmprivate_process, pfkey_x_satype_process, pfkey_sa_process, pfkey_address_process, pfkey_address_process, pfkey_address_process, pfkey_address_process, pfkey_address_process, pfkey_x_debug_process, pfkey_x_protocol_process, pfkey_x_nat_t_type_process, pfkey_x_nat_t_port_process, pfkey_x_nat_t_port_process, pfkey_address_process, pfkey_x_outif_process, pfkey_x_saref_process, }; /******************************* * MESSAGE PARSERS FOR KLIPS ********************************/ DEBUG_NO_STATIC int pfkey_x_simple_reply(struct sock *sk, struct sadb_ext *extensions[], int err) { struct sadb_msg *pfkey_reply = NULL; int error = 0; struct sadb_msg *m = ((struct sadb_msg*)extensions[K_SADB_EXT_RESERVED]); /* err is either 0 (success) or a negative 'errno' value */ if (err <= 0 && err >= -255) m->sadb_msg_errno = -err; else /* out of range for a uint8_t */ m->sadb_msg_errno = 255; if ((error = pfkey_msg_build(&pfkey_reply, extensions, EXT_BITS_OUT))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: " "failed to build the expire message\n"); SENDERR(-error); } error = pfkey_upmsgsk(sk, pfkey_reply); if (error) { KLIPS_ERROR(debug_pfkey, "pfkey_simple reply:" "sending up simple reply to pid=%d error=%d.\n", m->sadb_msg_pid, err); } errlab: if (pfkey_reply) pfkey_msg_free(&pfkey_reply); return error; } /* * this is a request to create a new device. Figure out which kind, and call appropriate * routine in mast or tunnel code. */ DEBUG_NO_STATIC int pfkey_x_plumb_parse(struct sock *sk, struct sadb_ext *extensions[], struct pfkey_extracted_data *extr) { unsigned int vifnum; int err; vifnum = extr->outif; if (vifnum > IPSECDEV_OFFSET) err = ipsec_tunnel_createnum(vifnum - IPSECDEV_OFFSET); else err = ipsec_mast_createnum(vifnum); return pfkey_x_simple_reply(sk, extensions, err); } DEBUG_NO_STATIC int pfkey_x_unplumb_parse(struct sock *sk, struct sadb_ext *extensions[], struct pfkey_extracted_data *extr) { unsigned int vifnum; int err; vifnum = extr->outif; if (vifnum > IPSECDEV_OFFSET) err = ipsec_tunnel_deletenum(vifnum - IPSECDEV_OFFSET); else err = ipsec_mast_deletenum(vifnum); return pfkey_x_simple_reply(sk, extensions, err); } /* msg_parsers: array of pointers to functions */ DEBUG_NO_STATIC int(*msg_parsers[K_SADB_MAX + 1]) ( struct sock *sk, struct sadb_ext *extensions[], struct pfkey_extracted_data *extr) = { NULL, /* RESERVED */ pfkey_getspi_parse, pfkey_update_parse, pfkey_add_parse, pfkey_delete_parse, pfkey_get_parse, pfkey_acquire_parse, pfkey_register_parse, pfkey_expire_parse, pfkey_flush_parse, pfkey_dump_parse, pfkey_x_promisc_parse, pfkey_x_pchange_parse, pfkey_x_grpsa_parse, pfkey_x_addflow_parse, pfkey_x_delflow_parse, pfkey_x_msg_debug_parse, pfkey_x_nat_t_new_mapping_parse, pfkey_x_plumb_parse, pfkey_x_unplumb_parse, }; int pfkey_build_reply(struct sadb_msg *pfkey_msg, struct pfkey_extracted_data *extr, struct sadb_msg **pfkey_reply) { struct sadb_ext *extensions[K_SADB_EXT_MAX + 1]; int error = 0; int msg_type = pfkey_msg->sadb_msg_type; int seq = pfkey_msg->sadb_msg_seq; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_build_reply: " "building reply with type: %d\n", msg_type); pfkey_extensions_init(extensions); if (!extr || !extr->ips) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_build_reply: " "bad ipsec_sa passed\n"); return EINVAL; /* TODO: should this not be negative? */ } error = pfkey_safe_build(pfkey_msg_hdr_build(&extensions[0], msg_type, proto2satype(extr->ips->ips_said.proto), 0, seq, pfkey_msg->sadb_msg_pid), extensions); if (!error && pfkey_required_extension(EXT_BITS_OUT, msg_type, K_SADB_EXT_SA)) { error = pfkey_sa_build(&extensions[K_SADB_EXT_SA], K_SADB_EXT_SA, extr->ips->ips_said.spi, extr->ips->ips_replaywin, extr->ips->ips_state, extr->ips->ips_authalg, extr->ips->ips_encalg, extr->ips->ips_flags); pfkey_safe_build(error, extensions); } if (!error && pfkey_required_extension(EXT_BITS_OUT, msg_type, K_SADB_X_EXT_SAREF)) { error = pfkey_saref_build(&extensions[K_SADB_X_EXT_SAREF], extr->ips->ips_ref, extr->ips->ips_refhim); pfkey_safe_build(error, extensions); } if (!error && pfkey_required_extension(EXT_BITS_OUT, msg_type, K_SADB_EXT_LIFETIME_CURRENT)) { error = pfkey_lifetime_build(&extensions [K_SADB_EXT_LIFETIME_CURRENT], K_SADB_EXT_LIFETIME_CURRENT, extr->ips->ips_life.ipl_allocations.ipl_count, extr->ips->ips_life.ipl_bytes.ipl_count, extr->ips->ips_life.ipl_addtime.ipl_count, extr->ips->ips_life.ipl_usetime.ipl_count, extr->ips->ips_life.ipl_packets.ipl_count); pfkey_safe_build(error, extensions); } if (!error && pfkey_required_extension(EXT_BITS_OUT, msg_type, K_SADB_EXT_ADDRESS_SRC)) { error = pfkey_address_build( &extensions[K_SADB_EXT_ADDRESS_SRC], K_SADB_EXT_ADDRESS_SRC, extr->ips->ips_said.proto, 0, extr->ips->ips_addr_s); pfkey_safe_build(error, extensions); } if (!error && pfkey_required_extension(EXT_BITS_OUT, msg_type, K_SADB_EXT_ADDRESS_DST)) { error = pfkey_address_build( &extensions[K_SADB_EXT_ADDRESS_DST], K_SADB_EXT_ADDRESS_DST, extr->ips->ips_said.proto, 0, extr->ips->ips_addr_d); pfkey_safe_build(error, extensions); } if (error == 0) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_build_reply: " "building extensions failed\n"); return EINVAL; } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_build_reply: " "built extensions, proceed to build the message\n"); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_build_reply: " "extensions[1]=0p%p\n", extensions[1]); error = pfkey_msg_build(pfkey_reply, extensions, EXT_BITS_OUT); pfkey_extensions_free(extensions); return error; } /* * interpret a pfkey message for klips usage. * it used to be that we provided a reply in a separate buffer, * but now we overwrite the request buffer and return it. */ int pfkey_msg_interp(struct sock *sk, struct sadb_msg *pfkey_msg) { int error = 0; int i; struct sadb_ext *extensions[K_SADB_EXT_MAX + 1]; /* should be kalloc */ struct pfkey_extracted_data extr; memset(&extr, 0, sizeof(extr)); pfkey_extensions_init(extensions); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_msg_interp: " "parsing message ver=%d, type=%d, errno=%d, satype=%d(%s), len=%d, res=%d, seq=%d, pid=%d.\n", pfkey_msg->sadb_msg_version, pfkey_msg->sadb_msg_type, pfkey_msg->sadb_msg_errno, pfkey_msg->sadb_msg_satype, satype2name(pfkey_msg->sadb_msg_satype), pfkey_msg->sadb_msg_len, pfkey_msg->sadb_msg_reserved, pfkey_msg->sadb_msg_seq, pfkey_msg->sadb_msg_pid); extr.ips = ipsec_sa_alloc(&error); /* pass in error var by pointer */ if (extr.ips == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_msg_interp: " "memory allocation error.\n"); SENDERR(-error); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_msg_interp: " "allocated extr->ips=0p%p.\n", extr.ips); if (pfkey_msg->sadb_msg_satype > K_SADB_SATYPE_MAX) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_msg_interp: " "satype %d > max %d\n", pfkey_msg->sadb_msg_satype, K_SADB_SATYPE_MAX); SENDERR(EINVAL); } switch (pfkey_msg->sadb_msg_type) { case K_SADB_GETSPI: case K_SADB_UPDATE: case K_SADB_ADD: case K_SADB_DELETE: case K_SADB_GET: case K_SADB_X_GRPSA: case K_SADB_X_ADDFLOW: if (!(extr.ips->ips_said.proto = satype2proto(pfkey_msg->sadb_msg_satype))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_msg_interp: " "satype %d lookup failed.\n", pfkey_msg->sadb_msg_satype); SENDERR(EINVAL); } else { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_msg_interp: " "satype %d lookups to proto=%d.\n", pfkey_msg->sadb_msg_satype, extr.ips->ips_said.proto); } break; default: break; } /* The NULL below causes the default extension parsers to be used */ /* Parse the extensions */ if ((error = pfkey_msg_parse(pfkey_msg, NULL, extensions, EXT_BITS_IN))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_msg_interp: " "message parsing failed with error %d.\n", error); SENDERR(-error); } /* Process the extensions */ for (i = 1; i <= K_SADB_EXT_MAX; i++) { if (extensions[i] != NULL && ext_processors[i] != NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_msg_interp: " "processing ext %d 0p%p with processor 0p%p.\n", i, extensions[i], ext_processors[i]); if ((error = ext_processors[i](extensions[i], &extr))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_msg_interp: " "extension processing for type %d failed with error %d.\n", i, error); SENDERR(-error); } } } /* Parse the message types */ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_msg_interp: " "parsing message type %d(%s) with msg_parser 0p%p.\n", pfkey_msg->sadb_msg_type, pfkey_v2_sadb_type_string(pfkey_msg->sadb_msg_type), msg_parsers[pfkey_msg->sadb_msg_type]); if ((error = msg_parsers[pfkey_msg->sadb_msg_type](sk, extensions, &extr))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_msg_interp: " "message parsing failed with error %d.\n", error); SENDERR(-error); } errlab: if (extr.ips != NULL) ipsec_sa_put(extr.ips, IPSEC_REFALLOC); if (extr.ips2 != NULL) ipsec_sa_put(extr.ips2, IPSEC_REFALLOC); if (extr.eroute != NULL) kfree(extr.eroute); return error; } libreswan-3.32/linux/net/ipsec/prng.c000066400000000000000000000065201365625662500176140ustar00rootroot00000000000000/* * crypto-class pseudorandom number generator * currently uses same algorithm as RC4(TM), from Schneier 2nd ed p397 * Copyright (C) 2002 Henry Spencer. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. */ #include "libreswan.h" #ifndef __KERNEL__ #ifndef SWAN_TESTING #error This file should only be used for building KLIPS #endif #endif #include "libreswan/ipsec_proto.h" /* for local_bh_disable() on older kernels without linux/asm/softirq.h */ #include /* * A horrible locking hack, we ride on tdb_lock for now since it * is basically what we want. Since all calls into prng_bytes pass in * a pointer to ipsec_prng, there is contention on the data in ipsec_prng * as it is not always locked. To make sure we never mess up the PRNG, just * locked it if we don't already have the tdb_lock */ /* ??? what's with the dangling else? */ #define LOCK_PRNG() \ int ul = 0; \ if (spin_trylock_bh(&tdb_lock)) { \ ul = 1; \ } else /* ??? what's with the dangling else? */ #define UNLOCK_PRNG() \ if (ul) { \ ul = 0; \ spin_unlock_bh(&tdb_lock); \ } else /* - prng_init - initialize PRNG from a key */ void prng_init(prng, key, keylen) struct prng *prng; const unsigned char *key; size_t keylen; { unsigned char k[256]; int i, j; const unsigned char *p; const unsigned char *keyend = key + keylen; unsigned char t; for (i = 0; i <= 255; i++) prng->sbox[i] = i; p = key; for (i = 0; i <= 255; i++) { k[i] = *p++; if (p >= keyend) p = key; } j = 0; for (i = 0; i <= 255; i++) { j = (j + prng->sbox[i] + k[i]) & 0xff; t = prng->sbox[i]; prng->sbox[i] = prng->sbox[j]; prng->sbox[j] = t; k[i] = 0; /* clear out key memory */ } prng->i = 0; prng->j = 0; prng->count = 0; } /* - prng_bytes - get some pseudorandom bytes from PRNG */ void prng_bytes(prng, dst, dstlen) struct prng *prng; unsigned char *dst; size_t dstlen; { int i, j, t; unsigned char *p = dst; size_t remain = dstlen; # define MAXCOUNT 4000000000ul LOCK_PRNG(); while (remain > 0) { i = (prng->i + 1) & 0xff; prng->i = i; j = (prng->j + prng->sbox[i]) & 0xff; prng->j = j; t = prng->sbox[i]; prng->sbox[i] = prng->sbox[j]; prng->sbox[j] = t; t = (t + prng->sbox[i]) & 0xff; *p++ = prng->sbox[t]; remain--; } if (prng->count < MAXCOUNT - dstlen) prng->count += dstlen; else prng->count = MAXCOUNT; UNLOCK_PRNG(); } /* - prnt_count - how many bytes have been extracted from PRNG so far? */ unsigned long prng_count(prng) struct prng *prng; { unsigned long c; LOCK_PRNG(); c = prng->count; UNLOCK_PRNG(); return c; } /* - prng_final - clear out PRNG to ensure nothing left in memory */ void prng_final(prng) struct prng *prng; { int i; for (i = 0; i <= 255; i++) prng->sbox[i] = 0; prng->i = 0; prng->j = 0; prng->count = 0; /* just for good measure */ } libreswan-3.32/linux/net/ipsec/radij.c000066400000000000000000000631021365625662500177360ustar00rootroot00000000000000/* * This file is defived from ${SRC}/sys/net/radix.c of BSD 4.4lite * * Variable and procedure names have been modified so that they don't * conflict with the original BSD code, as a small number of modifications * have been introduced and we may want to reuse this code in BSD. * * The `j' in `radij' is pronounced as a voiceless guttural (like a Greek * chi or a German ch sound (as `doch', not as in `milch'), or even a * spanish j as in Juan. It is not as far back in the throat like * the corresponding Hebrew sound, nor is it a soft breath like the English h. * It has nothing to do with the Dutch ij sound. * * Here is the appropriate copyright notice: */ /* * Copyright (c) 1988, 1989, 1993 * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)radix.c 8.2 (Berkeley) 1/4/94 */ /* * Routines to build and maintain radix trees for routing lookups. */ #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38) && \ !defined(AUTOCONF_INCLUDED) #include #endif #include /* printk() */ #include "libreswan/ipsec_param.h" #include /* kmalloc() */ #include /* error codes */ #include /* size_t */ #include /* mark_bh */ #include /* struct device, and other headers */ #include /* eth_type_trans */ #include /* struct iphdr */ #include # include #include #include #include "libreswan/radij.h" #include "libreswan/ipsec_encap.h" #include "libreswan/ipsec_radij.h" int maj_keylen; struct radij_mask *rj_mkfreelist; struct radij_node_head *mask_rjhead; static int gotOddMasks; static char *maskedKey; static char *rj_zeroes, *rj_ones; #define rj_masktop (mask_rjhead->rnh_treetop) #ifdef Bcmp # undef Bcmp #endif /* Bcmp */ #define Bcmp(a, b, l) \ ((l) == 0 ? 0 : memcmp((caddr_t)(b), (caddr_t)(a), (size_t)(l))) /* * The data structure for the keys is a radix tree with one way * branching removed. The index rj_b at an internal node n represents a bit * position to be tested. The tree is arranged so that all descendants * of a node n have keys whose bits all agree up to position rj_b - 1. * (We say the index of n is rj_b.) * * There is at least one descendant which has a one bit at position rj_b, * and at least one with a zero there. * * A route is determined by a pair of key and mask. We require that the * bit-wise logical and of the key and mask to be the key. * We define the index of a route to associated with the mask to be * the first bit number in the mask where 0 occurs (with bit number 0 * representing the highest order bit). * * We say a mask is normal if every bit is 0, past the index of the mask. * If a node n has a descendant (k, m) with index(m) == index(n) == rj_b, * and m is a normal mask, then the route applies to every descendant of n. * If the index(m) < rj_b, this implies the trailing last few bits of k * before bit b are all 0, (and hence consequently true of every descendant * of n), so the route applies to all descendants of the node as well. * * The present version of the code makes no use of normal routes, * but similar logic shows that a non-normal mask m such that * index(m) <= index(n) could potentially apply to many children of n. * Thus, for each non-host route, we attach its mask to a list at an internal * node as high in the tree as we can go. */ struct radij_node *rj_search(v_arg, head) void *v_arg; struct radij_node *head; { register struct radij_node *x; register caddr_t v; for (x = head, v = v_arg; x->rj_b >= 0; ) { if (x->rj_bmask & v[x->rj_off]) x = x->rj_r; else x = x->rj_l; } return x; }; struct radij_node *rj_search_m(v_arg, head, m_arg) struct radij_node *head; void *v_arg, *m_arg; { register struct radij_node *x; register caddr_t v = v_arg, m = m_arg; for (x = head; x->rj_b >= 0; ) { if ((x->rj_bmask & m[x->rj_off]) && (x->rj_bmask & v[x->rj_off])) x = x->rj_r; else x = x->rj_l; } return x; }; int rj_refines(m_arg, n_arg) void *m_arg, *n_arg; { register caddr_t m = m_arg, n = n_arg; register caddr_t lim, lim2 = lim = n + *(u_char *)n; int longer = (*(u_char *)n++) - (int)(*(u_char *)m++); int masks_are_equal = 1; if (longer > 0) lim -= longer; while (n < lim) { if (*n & ~(*m)) return 0; if (*n++ != *m++) masks_are_equal = 0; } while (n < lim2) if (*n++) return 0; if (masks_are_equal && (longer < 0)) { for (lim2 = m - longer; m < lim2; ) if (*m++) return 1; } return !masks_are_equal; } struct radij_node *rj_match(v_arg, head) void *v_arg; struct radij_node_head *head; { caddr_t v = v_arg; register struct radij_node *t = head->rnh_treetop, *x; register caddr_t cp = v, cp2, cp3; caddr_t cplim, mstart; struct radij_node *saved_t, *top = t; int off = t->rj_off, vlen = *(u_char *)cp, matched_off; /* * Open code rj_search(v, top) to avoid overhead of extra * subroutine call. */ for (; t->rj_b >= 0; ) { if (t->rj_bmask & cp[t->rj_off]) t = t->rj_r; else t = t->rj_l; } /* * See if we match exactly as a host destination */ KLIPS_PRINT(debug_radij, "klips_debug:rj_match: " "* See if we match exactly as a host destination\n"); cp += off; cp2 = t->rj_key + off; cplim = v + vlen; for (; cp < cplim; cp++, cp2++) if (*cp != *cp2) goto on1; /* * This extra grot is in case we are explicitly asked * to look up the default. Ugh! */ if ((t->rj_flags & RJF_ROOT) && t->rj_dupedkey) t = t->rj_dupedkey; return t; on1: matched_off = cp - v; saved_t = t; KLIPS_PRINT(debug_radij, "klips_debug:rj_match: " "** try to match a leaf, t=0p%p\n", t); do { if (t->rj_mask) { /* * Even if we don't match exactly as a hosts; * we may match if the leaf we wound up at is * a route to a net. */ cp3 = matched_off + t->rj_mask; cp2 = matched_off + t->rj_key; for (; cp < cplim; cp++) if ((*cp2++ ^ *cp) & *cp3++) break; if (cp == cplim) return t; cp = matched_off + v; } } while ((t = t->rj_dupedkey)); t = saved_t; /* start searching up the tree */ KLIPS_PRINT(debug_radij, "klips_debug:rj_match: " "*** start searching up the tree, t=0p%p\n", t); do { register struct radij_mask *m; t = t->rj_p; KLIPS_PRINT(debug_radij, "klips_debug:rj_match: " "**** t=0p%p\n", t); if ((m = t->rj_mklist)) { /* * After doing measurements here, it may * turn out to be faster to open code * rj_search_m here instead of always * copying and masking. */ /* off = min(t->rj_off, matched_off); */ off = t->rj_off; if (matched_off < off) off = matched_off; mstart = maskedKey + off; do { cp2 = mstart; cp3 = m->rm_mask + off; KLIPS_PRINT(debug_radij, "klips_debug:rj_match: " "***** cp2=0p%p cp3=0p%p\n", cp2, cp3); for (cp = v + off; cp < cplim; ) *cp2++ = *cp++ & *cp3++; x = rj_search(maskedKey, t); while (x && x->rj_mask != m->rm_mask) x = x->rj_dupedkey; if (x && (Bcmp(mstart, x->rj_key + off, vlen - off) == 0)) return x; } while ((m = m->rm_mklist)); } } while (t != top); KLIPS_PRINT(debug_radij, "klips_debug:rj_match: " "***** not found.\n"); return 0; }; #ifdef RJ_DEBUG int rj_nodenum; struct radij_node *rj_clist; int rj_saveinfo; DEBUG_NO_STATIC void traverse(struct radij_node *); #ifdef RJ_DEBUG2 int rj_debug = 1; #else int rj_debug = 0; #endif /* RJ_DEBUG2 */ #endif /* RJ_DEBUG */ struct radij_node *rj_newpair(v, b, nodes) void *v; int b; struct radij_node nodes[2]; { register struct radij_node *tt = nodes, *t = tt + 1; t->rj_b = b; t->rj_bmask = 0x80 >> (b & 7); t->rj_l = tt; t->rj_off = b >> 3; tt->rj_b = -1; tt->rj_key = (caddr_t)v; tt->rj_p = t; tt->rj_flags = t->rj_flags = RJF_ACTIVE; #ifdef RJ_DEBUG tt->rj_info = rj_nodenum++; t->rj_info = rj_nodenum++; tt->rj_twin = t; tt->rj_ybro = rj_clist; rj_clist = tt; #endif /* RJ_DEBUG */ return t; } struct radij_node *rj_insert(v_arg, head, dupentry, nodes) void *v_arg; struct radij_node_head *head; int *dupentry; struct radij_node nodes[2]; { caddr_t v = v_arg; struct radij_node *top = head->rnh_treetop; int head_off = top->rj_off, vlen = (int)*((u_char *)v); register struct radij_node *t = rj_search(v_arg, top); register caddr_t cp = v + head_off; register int b; struct radij_node *tt; /* * find first bit at which v and t->rj_key differ */ { register caddr_t cp2 = t->rj_key + head_off; register int cmp_res; caddr_t cplim = v + vlen; while (cp < cplim) if (*cp2++ != *cp++) goto on1; *dupentry = 1; return t; on1: *dupentry = 0; cmp_res = (cp[-1] ^ cp2[-1]) & 0xff; for (b = (cp - v) << 3; cmp_res; b--) cmp_res >>= 1; } { register struct radij_node *p, *x = top; cp = v; do { p = x; if (cp[x->rj_off] & x->rj_bmask) x = x->rj_r; else x = x->rj_l; } while (b > (unsigned) x->rj_b); /* x->rj_b < b && x->rj_b >= 0 */ #ifdef RJ_DEBUG if (rj_debug) printk("klips_debug:rj_insert: Going In:\n"), traverse(p); #endif /* RJ_DEBUG */ t = rj_newpair(v_arg, b, nodes); tt = t->rj_l; if ((cp[p->rj_off] & p->rj_bmask) == 0) p->rj_l = t; else p->rj_r = t; x->rj_p = t; t->rj_p = p; /* frees x, p as temp vars below */ if ((cp[t->rj_off] & t->rj_bmask) == 0) { t->rj_r = x; } else { t->rj_r = tt; t->rj_l = x; } #ifdef RJ_DEBUG if (rj_debug) printk("klips_debug:rj_insert: Coming out:\n"), traverse(p); #endif /* RJ_DEBUG */ } return tt; } struct radij_node *rj_addmask(n_arg, search, skip) int search, skip; void *n_arg; { caddr_t netmask = (caddr_t)n_arg; register struct radij_node *x; register caddr_t cp, cplim; register int b, mlen, j; int maskduplicated; mlen = *(u_char *)netmask; if (search) { x = rj_search(netmask, rj_masktop); mlen = *(u_char *)netmask; if (Bcmp(netmask, x->rj_key, mlen) == 0) return x; } R_Malloc(x, struct radij_node *, maj_keylen + 2 * sizeof(*x)); if (x == 0) return 0; Bzero(x, maj_keylen + 2 * sizeof(*x)); cp = (caddr_t)(x + 2); Bcopy(netmask, cp, mlen); netmask = cp; x = rj_insert(netmask, mask_rjhead, &maskduplicated, x); /* * Calculate index of mask. */ cplim = netmask + mlen; for (cp = netmask + skip; cp < cplim; cp++) if (*(u_char *)cp != 0xff) break; b = (cp - netmask) << 3; if (cp != cplim) { if (*cp != 0) { gotOddMasks = 1; for (j = 0x80; j; b++, j >>= 1) if ((j & *cp) == 0) break; } } x->rj_b = -1 - b; return x; } #if 0 struct radij_node * #endif unsigned char *dumper; int dumper_len; int rj_addroute(v_arg, n_arg, head, treenodes) void *v_arg, *n_arg; struct radij_node_head *head; struct radij_node treenodes[2]; { caddr_t v = (caddr_t)v_arg, netmask = (caddr_t)n_arg; register struct radij_node *t, *x = NULL, *tt; struct radij_node *saved_tt, *top = head->rnh_treetop; short b = 0, b_leaf; int mlen, keyduplicated; caddr_t cplim; struct radij_mask *m, **mp; /* * In dealing with non-contiguous masks, there may be * many different routes which have the same mask. * We will find it useful to have a unique pointer to * the mask to speed avoiding duplicate references at * nodes and possibly save time in calculating indices. */ if (netmask) { x = rj_search(netmask, rj_masktop); mlen = *(u_char *)netmask; if (Bcmp(netmask, x->rj_key, mlen) != 0) { x = rj_addmask(netmask, 0, top->rj_off); if (x == 0) return -ENOMEM; /* (0) rgb */ } netmask = x->rj_key; b = -1 - x->rj_b; } /* * Deal with duplicated keys: attach node to previous instance */ saved_tt = tt = rj_insert(v, head, &keyduplicated, treenodes); #ifdef RJ_DEBUG printk("addkey: duplicated: %d\n", keyduplicated); #endif if (keyduplicated) { do { if (tt->rj_mask == netmask) return -EEXIST; /* -ENXIO; (0) rgb */ t = tt; if (netmask == 0 || (tt->rj_mask && rj_refines(netmask, tt->rj_mask))) break; } while ((tt = tt->rj_dupedkey)); /* * If the mask is not duplicated, we wouldn't * find it among possible duplicate key entries * anyway, so the above test doesn't hurt. * * We sort the masks for a duplicated key the same way as * in a masklist -- most specific to least specific. * This may require the unfortunate nuisance of relocating * the head of the list. */ if (tt && t == saved_tt) { struct radij_node *xx = x; /* link in at head of list */ (tt = treenodes)->rj_dupedkey = t; tt->rj_flags = t->rj_flags; tt->rj_p = x = t->rj_p; if (x->rj_l == t) x->rj_l = tt; else x->rj_r = tt; saved_tt = tt; x = xx; } else { (tt = treenodes)->rj_dupedkey = t->rj_dupedkey; t->rj_dupedkey = tt; } #ifdef RJ_DEBUG t = tt + 1; tt->rj_info = rj_nodenum++; t->rj_info = rj_nodenum++; tt->rj_twin = t; tt->rj_ybro = rj_clist; rj_clist = tt; #endif /* RJ_DEBUG */ t = saved_tt; tt->rj_key = (caddr_t) v; tt->rj_b = -1; tt->rj_flags = t->rj_flags & ~RJF_ROOT; } /* * Put mask in tree. */ if (netmask) { tt->rj_mask = netmask; tt->rj_b = x->rj_b; } t = saved_tt->rj_p; b_leaf = -1 - t->rj_b; if (t->rj_r == saved_tt) x = t->rj_l; else x = t->rj_r; /* Promote general routes from below */ if (x->rj_b < 0) { if (x->rj_mask && (x->rj_b >= b_leaf) && x->rj_mklist == 0) { MKGet(m); if (m) { Bzero(m, sizeof *m); m->rm_b = x->rj_b; m->rm_mask = x->rj_mask; x->rj_mklist = t->rj_mklist = m; } } } else if (x->rj_mklist) { /* * Skip over masks whose index is > that of new node */ for (mp = &x->rj_mklist; (m = *mp); mp = &m->rm_mklist) if (m->rm_b >= b_leaf) break; t->rj_mklist = m; *mp = 0; } /* Add new route to highest possible ancestor's list */ if ((netmask == 0) || (b > t->rj_b )) { #ifdef RJ_DEBUG printk("klips:radij.c: netmask = %p or b(%d)>t->rjb(%d)\n", netmask, b, t->rj_b); #endif return 0; /* tt rgb */ /* can't lift at all */ } b_leaf = tt->rj_b; do { x = t; t = t->rj_p; } while (b <= t->rj_b && x != top); /* * Search through routes associated with node to * insert new route according to index. * For nodes of equal index, place more specific * masks first. */ cplim = netmask + mlen; for (mp = &x->rj_mklist; (m = *mp); mp = &m->rm_mklist) { if (m->rm_b < b_leaf) continue; if (m->rm_b > b_leaf) break; if (m->rm_mask == netmask) { m->rm_refs++; tt->rj_mklist = m; #ifdef RJ_DEBUG printk("klips:radij.c: m->rm_mask %p == netmask\n", netmask); #endif return 0; /* tt rgb */ } if (rj_refines(netmask, m->rm_mask)) break; } MKGet(m); if (m == 0) { printk("klips_debug:rj_addroute: " "Mask for route not entered\n"); return 0; /* (tt) rgb */ } Bzero(m, sizeof *m); m->rm_b = b_leaf; m->rm_mask = netmask; m->rm_mklist = *mp; *mp = m; tt->rj_mklist = m; #ifdef RJ_DEBUG printk("klips:radij.c: addroute done\n"); #endif return 0; /* tt rgb */ } int rj_delete(v_arg, netmask_arg, head, node) void *v_arg, *netmask_arg; struct radij_node_head *head; struct radij_node **node; { register struct radij_node *t, *p, *x, *tt; struct radij_mask *m, *saved_m, **mp; struct radij_node *dupedkey, *saved_tt, *top; caddr_t v, netmask; int b, head_off, vlen; v = v_arg; netmask = netmask_arg; x = head->rnh_treetop; tt = rj_search(v, x); head_off = x->rj_off; vlen = *(u_char *)v; saved_tt = tt; top = x; if (tt == 0 || Bcmp(v + head_off, tt->rj_key + head_off, vlen - head_off)) return -EFAULT; /* (0) rgb */ /* * Delete our route from mask lists. */ if ((dupedkey = tt->rj_dupedkey)) { if (netmask) netmask = rj_search(netmask, rj_masktop)->rj_key; while (tt->rj_mask != netmask) if ((tt = tt->rj_dupedkey) == 0) return -ENOENT; /* -ENXIO; (0) rgb */ } if (tt->rj_mask == 0 || (saved_m = m = tt->rj_mklist) == 0) goto on1; if (m->rm_mask != tt->rj_mask) { printk("klips_debug:rj_delete: " "inconsistent annotation\n"); goto on1; } if (--m->rm_refs >= 0) goto on1; b = -1 - tt->rj_b; t = saved_tt->rj_p; if (b > t->rj_b) goto on1; /* Wasn't lifted at all */ do { x = t; t = t->rj_p; } while (b <= t->rj_b && x != top); for (mp = &x->rj_mklist; (m = *mp); mp = &m->rm_mklist) if (m == saved_m) { *mp = m->rm_mklist; MKFree(m); break; } if (m == 0) printk("klips_debug:rj_delete: " "couldn't find our annotation\n"); on1: /* * Eliminate us from tree */ if (tt->rj_flags & RJF_ROOT) return -EFAULT; /* (0) rgb */ #ifdef RJ_DEBUG /* Get us out of the creation list */ for (t = rj_clist; t && t->rj_ybro != tt; t = t->rj_ybro) { } if (t) t->rj_ybro = tt->rj_ybro; #endif /* RJ_DEBUG */ t = tt->rj_p; if (dupedkey) { if (tt == saved_tt) { x = dupedkey; x->rj_p = t; if (t->rj_l == tt) t->rj_l = x; else t->rj_r = x; } else { for (x = p = saved_tt; p && p->rj_dupedkey != tt; ) p = p->rj_dupedkey; if (p) p->rj_dupedkey = tt->rj_dupedkey; else printk("klips_debug:rj_delete: " "couldn't find node that we started with\n"); } t = tt + 1; if (t->rj_flags & RJF_ACTIVE) { #ifndef RJ_DEBUG *++x = *t; p = t->rj_p; #else b = t->rj_info; *++x = *t; t->rj_info = b; p = t->rj_p; #endif /* RJ_DEBUG */ if (p->rj_l == t) p->rj_l = x; else p->rj_r = x; x->rj_l->rj_p = x; x->rj_r->rj_p = x; } goto out; } if (t->rj_l == tt) x = t->rj_r; else x = t->rj_l; p = t->rj_p; if (p->rj_r == t) p->rj_r = x; else p->rj_l = x; x->rj_p = p; /* * Demote routes attached to us. */ if (t->rj_mklist) { if (x->rj_b >= 0) { for (mp = &x->rj_mklist; (m = *mp); ) mp = &m->rm_mklist; *mp = t->rj_mklist; } else { for (m = t->rj_mklist; m; ) { struct radij_mask *mm = m->rm_mklist; if (m == x->rj_mklist && (--(m->rm_refs) < 0)) { x->rj_mklist = 0; MKFree(m); } else { printk("klips_debug:rj_delete: " "Orphaned Mask 0p%p at 0p%p\n", m, x); } m = mm; } } } /* * We may be holding an active internal node in the tree. */ x = tt + 1; if (t != x) { #ifndef RJ_DEBUG *t = *x; #else b = t->rj_info; *t = *x; t->rj_info = b; #endif /* RJ_DEBUG */ t->rj_l->rj_p = t; t->rj_r->rj_p = t; p = x->rj_p; if (p->rj_l == x) p->rj_l = t; else p->rj_r = t; } out: tt->rj_flags &= ~RJF_ACTIVE; tt[1].rj_flags &= ~RJF_ACTIVE; *node = tt; return 0; /* (tt) rgb */ } int rj_walktree(h, f, w) struct radij_node_head *h; register int (*f)(struct radij_node *, void *); void *w; { int error; struct radij_node *base, *next; register struct radij_node *rn; if (!h || !f /* || !w */) return -ENODATA; rn = h->rnh_treetop; /* * This gets complicated because we may delete the node * while applying the function f to it, so we need to calculate * the successor node in advance. */ /* First time through node, go left */ while (rn->rj_b >= 0) rn = rn->rj_l; for (;; ) { if (debug_radij) { printk("klips_debug:rj_walktree: " "for: rn=0p%p rj_b=%d rj_flags=%x", rn, rn->rj_b, rn->rj_flags); rn->rj_b >= 0 ? printk(" node off=%x\n", rn->rj_off) : printk(" leaf key = %08x->%08x\n", (u_int)ntohl(((struct sockaddr_encap *)rn-> rj_key)->sen_ip_src.s_addr), (u_int)ntohl(((struct sockaddr_encap *)rn-> rj_key)->sen_ip_dst.s_addr)); } base = rn; /* If at right child go back up, otherwise, go right */ while (rn->rj_p->rj_r == rn && (rn->rj_flags & RJF_ROOT) == 0) rn = rn->rj_p; /* Find the next *leaf* since next node might vanish, too */ for (rn = rn->rj_p->rj_r; rn->rj_b >= 0; ) rn = rn->rj_l; next = rn; if (debug_radij) { printk("klips_debug:rj_walktree: " "processing leaves, rn=0p%p rj_b=%d rj_flags=%x", rn, rn->rj_b, rn->rj_flags); rn->rj_b >= 0 ? printk(" node off=%x\n", rn->rj_off) : printk(" leaf key = %08x->%08x\n", (u_int)ntohl(((struct sockaddr_encap *)rn-> rj_key)->sen_ip_src.s_addr), (u_int)ntohl(((struct sockaddr_encap *)rn-> rj_key)->sen_ip_dst.s_addr)); } /* Process leaves */ while ((rn = base)) { base = rn->rj_dupedkey; if (debug_radij) { printk("klips_debug:rj_walktree: " "while: base=0p%p rn=0p%p rj_b=%d rj_flags=%x", base, rn, rn->rj_b, rn->rj_flags); rn->rj_b >= 0 ? printk(" node off=%x\n", rn->rj_off) : printk(" leaf key = %08x->%08x\n", (u_int)ntohl(((struct sockaddr_encap *) rn->rj_key)->sen_ip_src. s_addr), (u_int)ntohl(((struct sockaddr_encap *) rn->rj_key)->sen_ip_dst. s_addr)); } if (!(rn->rj_flags & RJF_ROOT) && (error = (*f)(rn, w))) return -error; } rn = next; if (rn->rj_flags & RJF_ROOT) return 0; } /* NOTREACHED */ } int rj_inithead(head, off) void **head; int off; { register struct radij_node_head *rnh; register struct radij_node *t, *tt, *ttt; if (*head) return 1; R_Malloc(rnh, struct radij_node_head *, sizeof(*rnh)); if (rnh == NULL) return 0; Bzero(rnh, sizeof(*rnh)); *head = rnh; t = rj_newpair(rj_zeroes, off, rnh->rnh_nodes); ttt = rnh->rnh_nodes + 2; t->rj_r = ttt; t->rj_p = t; tt = t->rj_l; tt->rj_flags = t->rj_flags = RJF_ROOT | RJF_ACTIVE; tt->rj_b = -1 - off; *ttt = *tt; ttt->rj_key = rj_ones; rnh->rnh_addaddr = rj_addroute; rnh->rnh_deladdr = rj_delete; rnh->rnh_matchaddr = rj_match; rnh->rnh_walktree = rj_walktree; rnh->rnh_treetop = t; return 1; } void rj_init(void) { char *cp, *cplim; if (maj_keylen == 0) { printk("klips_debug:rj_init: " "radij functions require maj_keylen be set\n"); return; } R_Malloc(rj_zeroes, char *, 3 * maj_keylen); if (rj_zeroes == NULL) panic("rj_init"); Bzero(rj_zeroes, 3 * maj_keylen); rj_ones = cp = rj_zeroes + maj_keylen; maskedKey = cplim = rj_ones + maj_keylen; while (cp < cplim) *cp++ = -1; if (rj_inithead((void **)&mask_rjhead, 0) == 0) panic("rj_init 2"); } void rj_preorder(struct radij_node *rn, int l) { int i; if (rn == NULL) { printk("klips_debug:rj_preorder: " "NULL pointer\n"); return; } if (rn->rj_b >= 0) { rj_preorder(rn->rj_l, l + 1); rj_preorder(rn->rj_r, l + 1); printk("klips_debug:"); for (i = 0; i < l; i++) printk("*"); printk(" off = %d\n", rn->rj_off); } else { printk("klips_debug:"); for (i = 0; i < l; i++) printk("@"); printk(" flags = %x", (u_int)rn->rj_flags); if (rn->rj_flags & RJF_ACTIVE) { printk(" @key=0p%p", rn->rj_key); printk(" key = %08x->%08x", (u_int)ntohl(((struct sockaddr_encap *)rn-> rj_key)->sen_ip_src.s_addr), (u_int)ntohl(((struct sockaddr_encap *)rn-> rj_key)->sen_ip_dst.s_addr)); printk(" @mask=0p%p", rn->rj_mask); if (rn->rj_mask) { printk(" mask = %08x->%08x", (u_int)ntohl(((struct sockaddr_encap *) rn->rj_mask)->sen_ip_src. s_addr), (u_int)ntohl(((struct sockaddr_encap *) rn->rj_mask)->sen_ip_dst. s_addr)); } if (rn->rj_dupedkey) printk(" dupedkey = 0p%p", rn->rj_dupedkey); } printk("\n"); } } #ifdef RJ_DEBUG DEBUG_NO_STATIC void traverse(struct radij_node *p) { rj_preorder(p, 0); } #endif /* RJ_DEBUG */ void rj_dumptrees(void) { rj_preorder(rnh->rnh_treetop, 0); } void rj_free_mkfreelist(void) { struct radij_mask *mknp, *mknp2; mknp = rj_mkfreelist; while (mknp) { mknp2 = mknp; mknp = mknp->rm_mklist; kfree(mknp2); } } int radijcleartree(void) { return rj_walktree(rnh, ipsec_rj_walker_delete, NULL); } int radijcleanup(void) { int error = 0; error = radijcleartree(); rj_free_mkfreelist(); /* rj_walktree(mask_rjhead, ipsec_rj_walker_delete, NULL); */ if (mask_rjhead) kfree(mask_rjhead); if (rj_zeroes) kfree(rj_zeroes); if (rnh) kfree(rnh); return error; } libreswan-3.32/linux/net/ipsec/satot.c000066400000000000000000000067451365625662500200110ustar00rootroot00000000000000/* * convert from binary form of SA ID to text * Copyright (C) 2000, 2001 Henry Spencer. * Copyright (C) 2012 David McCullough * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. */ #include "libreswan.h" static struct typename { char type; char *name; } typenames[] = { { SA_AH, "ah" }, { SA_ESP, "esp" }, { SA_IPIP, "tun" }, { SA_COMP, "comp" }, { SA_INT, "int" }, { 0, NULL } }; /* - satot - convert SA to text "ah507@1.2.3.4" */ size_t /* space needed for full conversion */ satot(sa, format, dst, dstlen) const ip_said * sa; int format; /* character */ char *dst; /* need not be valid if dstlen is 0 */ size_t dstlen; { size_t len = 0; /* 0 means "not recognized yet" */ int base; int showversion; /* use delimiter to show IP version? */ struct typename *tn; char *p; char *pre; char buf[10 + 1 + ULTOT_BUF + ADDRTOT_BUF]; char unk[10]; switch (format) { case 0: base = 16; showversion = 1; break; case 'f': base = 17; showversion = 1; break; case 'x': base = 'x'; showversion = 0; break; case 'd': base = 10; showversion = 0; break; default: if (dstlen > 0) { strncpy(dst, "(error)", dstlen-1); dst[dstlen-1] = '\0'; } return 0; break; } memset(buf, 0, sizeof(buf)); pre = NULL; for (tn = typenames; tn->name != NULL; tn++) if (sa->proto == tn->type) { pre = tn->name; break; /* NOTE BREAK OUT */ } if (pre == NULL) { /* unknown protocol */ strcpy(unk, "unk"); (void) ultot((unsigned char)sa->proto, 10, unk + strlen(unk), sizeof(unk) - strlen(unk)); pre = unk; } if (strcmp(pre, PASSTHROUGHTYPE) == 0 && sa->spi == PASSTHROUGHSPI && isunspecaddr(&sa->dst)) { strcpy(buf, (addrtypeof(&sa->dst) == AF_INET) ? PASSTHROUGH4NAME : PASSTHROUGH6NAME); len = strlen(buf); } if (sa->proto == SA_INT) { char intunk[10]; switch (ntohl(sa->spi)) { case SPI_PASS: p = "%pass"; break; case SPI_DROP: p = "%drop"; break; case SPI_REJECT: p = "%reject"; break; case SPI_HOLD: p = "%hold"; break; case SPI_TRAP: p = "%trap"; break; case SPI_TRAPSUBNET: p = "%trapsubnet"; break; default: snprintf(intunk, sizeof(intunk), "%%unk-%d", ntohl(sa->spi)); p = intunk; break; } if (p != NULL) { strcpy(buf, p); len = strlen(buf); } } if (len == 0) { /* general case needed */ strcpy(buf, pre); len = strlen(buf); if (showversion) { *(buf + len) = (addrtypeof(&sa->dst) == AF_INET) ? '.' : ':'; len++; *(buf + len) = '\0'; } len += ultot(ntohl(sa->spi), base, buf + len, sizeof(buf) - len); *(buf + len - 1) = '@'; len += addrtot(&sa->dst, 0, buf + len, sizeof(buf) - len); *(buf + len) = '\0'; } if (dst != NULL) { if (len > dstlen) *(buf + dstlen - 1) = '\0'; strcpy(dst, buf); } return len; } libreswan-3.32/linux/net/ipsec/subnetof.c000066400000000000000000000026041365625662500204720ustar00rootroot00000000000000/* * minor network-address manipulation utilities * Copyright (C) 1998, 1999 Henry Spencer. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. */ #include "libreswan.h" /* - subnetof - given address and mask, return subnet part */ struct in_addr subnetof(addr, mask) struct in_addr addr; struct in_addr mask; { struct in_addr result; result.s_addr = addr.s_addr & mask.s_addr; return result; } /* - hostof - given address and mask, return host part */ struct in_addr hostof(addr, mask) struct in_addr addr; struct in_addr mask; { struct in_addr result; result.s_addr = addr.s_addr & ~mask.s_addr; return result; } /* - broadcastof - given (network) address and mask, return broadcast address */ struct in_addr broadcastof(addr, mask) struct in_addr addr; struct in_addr mask; { struct in_addr result; result.s_addr = addr.s_addr | ~mask.s_addr; return result; } libreswan-3.32/linux/net/ipsec/subnettoa.c000066400000000000000000000046261365625662500206570ustar00rootroot00000000000000/* * convert binary form of subnet description to ASCII * Copyright (C) 1998, 1999 Henry Spencer. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. */ #include "libreswan.h" /* - subnettoa - convert address and mask to ASCII "addr/mask" * Output expresses the mask as a bit count if possible, else dotted decimal. */ size_t /* space needed for full conversion */ subnettoa(addr, mask, format, dst, dstlen) struct in_addr addr; struct in_addr mask; int format; /* character */ char *dst; /* need not be valid if dstlen is 0 */ size_t dstlen; { size_t len; size_t rest; int n; char *p; switch (format) { case 0: break; default: return 0; break; } len = addrtoa(addr, 0, dst, dstlen); if (len < dstlen) { dst[len - 1] = '/'; p = dst + len; rest = dstlen - len; } else { p = NULL; rest = 0; } n = masktobits(mask); if (n >= 0) len += ultot((unsigned long)n, 10, p, rest); else len += addrtoa(mask, 0, p, rest); return len; } /* - subnettoa - convert address and mask to ASCII "addr/mask" * Output expresses the mask as a bit count if possible, else dotted decimal. */ size_t /* space needed for full conversion */ subnet6toa(addr, mask, format, dst, dstlen) struct in6_addr *addr; struct in6_addr *mask; int format; /* character */ char *dst; /* need not be valid if dstlen is 0 */ size_t dstlen; { size_t len; size_t rest; int n; char *p; switch (format) { case 0: break; default: return 0; break; } len = inet_addrtot(AF_INET6, addr, 0, dst, dstlen); if (len < dstlen) { dst[len - 1] = '/'; p = dst + len; rest = dstlen - len; } else { p = NULL; rest = 0; } n = mask6tobits(mask); if (n >= 0) len += ultot((unsigned long)n, 10, p, rest); else len += inet_addrtot(AF_INET6, mask, 0, p, rest); return len; } libreswan-3.32/linux/net/ipsec/sysctl_net_ipsec.c000066400000000000000000000250711365625662500222220ustar00rootroot00000000000000/* * sysctl interface to net IPSEC subsystem. * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include "libreswan/ipsec_kversion.h" #include "libreswan/ipsec_param.h" #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) #include #endif #include #include #include #ifdef CONFIG_SYSCTL extern int debug_ah; extern int debug_esp; extern int debug_mast; extern int debug_tunnel; extern int debug_xmit; extern int debug_eroute; extern int debug_spi; extern int debug_radij; extern int debug_netlink; extern int debug_xform; extern int debug_rcv; extern int debug_pfkey; extern int sysctl_ipsec_debug_verbose; #ifdef CONFIG_KLIPS_IPCOMP extern int sysctl_ipsec_debug_ipcomp; #endif /* CONFIG_KLIPS_IPCOMP */ extern int sysctl_ipsec_icmp; extern int sysctl_ipsec_inbound_policy_check; extern int sysctl_ipsec_tos; int sysctl_ipsec_regress_pfkey_lossage; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) #define NET_IPSEC CTL_UNNUMBERED #define NET_IPSEC_DEBUG_AH CTL_UNNUMBERED #define NET_IPSEC_DEBUG_ESP CTL_UNNUMBERED #define NET_IPSEC_DEBUG_TUNNEL CTL_UNNUMBERED #define NET_IPSEC_DEBUG_EROUTE CTL_UNNUMBERED #define NET_IPSEC_DEBUG_SPI CTL_UNNUMBERED #define NET_IPSEC_DEBUG_RADIJ CTL_UNNUMBERED #define NET_IPSEC_DEBUG_NETLINK CTL_UNNUMBERED #define NET_IPSEC_DEBUG_XFORM CTL_UNNUMBERED #define NET_IPSEC_DEBUG_RCV CTL_UNNUMBERED #define NET_IPSEC_DEBUG_PFKEY CTL_UNNUMBERED #define NET_IPSEC_DEBUG_VERBOSE CTL_UNNUMBERED #define NET_IPSEC_DEBUG_IPCOMP CTL_UNNUMBERED #define NET_IPSEC_ICMP CTL_UNNUMBERED #define NET_IPSEC_INBOUND_POLICY_CHECK CTL_UNNUMBERED #define NET_IPSEC_TOS CTL_UNNUMBERED #define NET_IPSEC_REGRESS_PFKEY_LOSSAGE CTL_UNNUMBERED #define NET_IPSEC_DEBUG_MAST CTL_UNNUMBERED #define NET_IPSEC_DEBUG_XMIT CTL_UNNUMBERED #else enum { #define NET_IPSEC 2112 /* Random number - if not blame linux sysctl people */ NET_IPSEC_DEBUG_AH=1, NET_IPSEC_DEBUG_ESP=2, NET_IPSEC_DEBUG_TUNNEL=3, NET_IPSEC_DEBUG_EROUTE=4, NET_IPSEC_DEBUG_SPI=5, NET_IPSEC_DEBUG_RADIJ=6, NET_IPSEC_DEBUG_NETLINK=7, NET_IPSEC_DEBUG_XFORM=8, NET_IPSEC_DEBUG_RCV=9, NET_IPSEC_DEBUG_PFKEY=10, NET_IPSEC_DEBUG_VERBOSE=11, NET_IPSEC_DEBUG_IPCOMP=12, NET_IPSEC_ICMP=13, NET_IPSEC_INBOUND_POLICY_CHECK=14, NET_IPSEC_TOS=15, NET_IPSEC_REGRESS_PFKEY_LOSSAGE=16, NET_IPSEC_DEBUG_MAST=17, NET_IPSEC_DEBUG_XMIT=18, }; #endif static ctl_table ipsec_table[] = { #ifdef CTL_TABLE_PARENT { CTL_NAME(NET_IPSEC_DEBUG_AH) .procname = "debug_ah", .data = &debug_ah, .maxlen = sizeof(int), .mode = 0644, .child = NULL, .proc_handler = &proc_dointvec, }, { CTL_NAME(NET_IPSEC_DEBUG_ESP) .procname = "debug_esp", .data = &debug_esp, .maxlen = sizeof(int), .mode = 0644, .child = NULL, .proc_handler = &proc_dointvec, }, { CTL_NAME(NET_IPSEC_DEBUG_MAST) .procname = "debug_mast", .data = &debug_mast, .maxlen = sizeof(int), .mode = 0644, .child = NULL, .proc_handler = &proc_dointvec, }, { CTL_NAME(NET_IPSEC_DEBUG_TUNNEL) .procname = "debug_tunnel", .data = &debug_tunnel, .maxlen = sizeof(int), .mode = 0644, .child = NULL, .proc_handler = &proc_dointvec, }, { CTL_NAME(NET_IPSEC_DEBUG_XMIT) .procname = "debug_xmit", .data = &debug_xmit, .maxlen = sizeof(int), .mode = 0644, .child = NULL, .proc_handler = &proc_dointvec, }, { CTL_NAME(NET_IPSEC_DEBUG_EROUTE) .procname = "debug_eroute", .data = &debug_eroute, .maxlen = sizeof(int), .mode = 0644, .child = NULL, .proc_handler = &proc_dointvec, }, { CTL_NAME(NET_IPSEC_DEBUG_SPI) .procname = "debug_spi", .data = &debug_spi, .maxlen = sizeof(int), .mode = 0644, .child = NULL, .proc_handler = &proc_dointvec, }, { CTL_NAME(NET_IPSEC_DEBUG_RADIJ) .procname = "debug_radij", .data = &debug_radij, .maxlen = sizeof(int), .mode = 0644, .child = NULL, .proc_handler = &proc_dointvec, }, { CTL_NAME(NET_IPSEC_DEBUG_NETLINK) .procname = "debug_netlink", .data = &debug_netlink, .maxlen = sizeof(int), .mode = 0644, .child = NULL, .proc_handler = &proc_dointvec, }, { CTL_NAME(NET_IPSEC_DEBUG_XFORM) .procname = "debug_xform", .data = &debug_xform, .maxlen = sizeof(int), .mode = 0644, .child = NULL, .proc_handler = &proc_dointvec, }, { CTL_NAME(NET_IPSEC_DEBUG_RCV) .procname = "debug_rcv", .data = &debug_rcv, .maxlen = sizeof(int), .mode = 0644, .child = NULL, .proc_handler = &proc_dointvec, }, { CTL_NAME(NET_IPSEC_DEBUG_PFKEY) .procname = "debug_pfkey", .data = &debug_pfkey, .maxlen = sizeof(int), .mode = 0644, .child = NULL, .proc_handler = &proc_dointvec, }, { CTL_NAME(NET_IPSEC_DEBUG_VERBOSE) .procname = "debug_verbose", .data = &sysctl_ipsec_debug_verbose, .maxlen = sizeof(int), .mode = 0644, .child = NULL, .proc_handler = &proc_dointvec, }, #else { NET_IPSEC_DEBUG_AH, "debug_ah", &debug_ah, sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec }, { NET_IPSEC_DEBUG_ESP, "debug_esp", &debug_esp, sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec }, { NET_IPSEC_DEBUG_MAST, "debug_mast", &debug_mast, sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec }, { NET_IPSEC_DEBUG_TUNNEL, "debug_tunnel", &debug_tunnel, sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec }, { NET_IPSEC_DEBUG_TUNNEL, "debug_xmit", &debug_xmit, sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec }, { NET_IPSEC_DEBUG_EROUTE, "debug_eroute", &debug_eroute, sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec }, { NET_IPSEC_DEBUG_SPI, "debug_spi", &debug_spi, sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec }, { NET_IPSEC_DEBUG_RADIJ, "debug_radij", &debug_radij, sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec }, { NET_IPSEC_DEBUG_NETLINK, "debug_netlink", &debug_netlink, sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec }, { NET_IPSEC_DEBUG_XFORM, "debug_xform", &debug_xform, sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec }, { NET_IPSEC_DEBUG_RCV, "debug_rcv", &debug_rcv, sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec }, { NET_IPSEC_DEBUG_PFKEY, "debug_pfkey", &debug_pfkey, sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec }, { NET_IPSEC_DEBUG_VERBOSE, "debug_verbose", &sysctl_ipsec_debug_verbose, sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec }, #endif /* CTL_TABLE_PARENT */ #ifdef CONFIG_KLIPS_IPCOMP #ifdef CTL_TABLE_PARENT { CTL_NAME(NET_IPSEC_DEBUG_IPCOMP) .procname = "debug_ipcomp", .data = &sysctl_ipsec_debug_ipcomp, .maxlen = sizeof(int), .mode = 0644, .child = NULL, .proc_handler = &proc_dointvec, }, #else { NET_IPSEC_DEBUG_IPCOMP, "debug_ipcomp", &sysctl_ipsec_debug_ipcomp, sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec }, #endif #endif /* CONFIG_KLIPS_IPCOMP */ #ifdef CONFIG_KLIPS_REGRESS #ifdef CTL_TABLE_PARENT { CTL_NAME(NET_IPSEC_REGRESS_PFKEY_LOSSAGE) .procname = "pfkey_lossage", .data = &sysctl_ipsec_regress_pfkey_lossage, .maxlen = sizeof(int), .mode = 0644, .child = NULL, .proc_handler = &proc_dointvec, }, #else { NET_IPSEC_REGRESS_PFKEY_LOSSAGE, "pfkey_lossage", &sysctl_ipsec_regress_pfkey_lossage, sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec }, #endif /* CTL_TABLE_PARENT */ #endif /* CONFIG_KLIPS_REGRESS */ #ifdef CTL_TABLE_PARENT { CTL_NAME(NET_IPSEC_ICMP) .procname = "icmp", .data = &sysctl_ipsec_icmp, .maxlen = sizeof(int), .mode = 0644, .child = NULL, .proc_handler = &proc_dointvec, }, { CTL_NAME(NET_IPSEC_INBOUND_POLICY_CHECK) .procname = "inbound_policy_check", .data = &sysctl_ipsec_inbound_policy_check, .maxlen = sizeof(int), .mode = 0644, .child = NULL, .proc_handler = &proc_dointvec, }, { CTL_NAME(NET_IPSEC_TOS) .procname = "tos", .data = &sysctl_ipsec_tos, .maxlen = sizeof(int), .mode = 0644, .child = NULL, .proc_handler = &proc_dointvec, }, # ifdef HAS_PRIV_DESTRUCTOR { } # else { 0 } # endif #else { NET_IPSEC_ICMP, "icmp", &sysctl_ipsec_icmp, sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec }, { NET_IPSEC_INBOUND_POLICY_CHECK, "inbound_policy_check", &sysctl_ipsec_inbound_policy_check, sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec }, { NET_IPSEC_TOS, "tos", &sysctl_ipsec_tos, sizeof(int), 0644, NULL, .proc_handler = &proc_dointvec }, # ifdef HAS_PRIV_DESTRUCTOR { } # else { 0 } # endif #endif }; static ctl_table ipsec_net_table[] = { #ifdef CTL_TABLE_PARENT { CTL_NAME(NET_IPSEC) .procname = "ipsec", .data = NULL, .maxlen = 0, .mode = 0555, .child = ipsec_table, .proc_handler = NULL, }, # ifdef HAS_PRIV_DESTRUCTOR { } # else { 0 } # endif #else { NET_IPSEC, "ipsec", NULL, 0, 0555, ipsec_table }, #endif }; static ctl_table ipsec_root_table[] = { #ifdef CTL_TABLE_PARENT { CTL_NAME(CTL_NET) .procname = "net", .data = NULL, .maxlen = 0, .mode = 0555, .child = ipsec_net_table, .proc_handler = NULL, }, # ifdef HAS_PRIV_DESTRUCTOR { } # else { 0 } # endif #else { CTL_NET, "net", NULL, 0, 0555, ipsec_net_table }, # ifdef HAS_PRIV_DESTRUCTOR { } # else { 0 } # endif #endif }; static struct ctl_table_header *ipsec_table_header; int ipsec_sysctl_register(void) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 21) ipsec_table_header = register_sysctl_table(ipsec_root_table); #else ipsec_table_header = register_sysctl_table(ipsec_root_table, 0); #endif printk("registered KLIPS /proc/sys/net"); if (!ipsec_table_header) return -ENOMEM; return 0; } void ipsec_sysctl_unregister(void) { unregister_sysctl_table(ipsec_table_header); } #endif /* CONFIG_SYSCTL */ libreswan-3.32/linux/net/ipsec/tagsfile.mak000066400000000000000000000001711365625662500207660ustar00rootroot00000000000000TAGS: etags *.c ../../include/*.h ../../include/freeswan/*.h ctags *.c ../../include/*.h ../../include/freeswan/*.h libreswan-3.32/linux/net/ipsec/trees.c000066400000000000000000001253031365625662500177710ustar00rootroot00000000000000/* trees.c -- output deflated data using Huffman coding * Copyright (C) 1995-2002 Jean-loup Gailly * For conditions of distribution and use, see copyright notice in zlib.h */ /* * ALGORITHM * * The "deflation" process uses several Huffman trees. The more * common source values are represented by shorter bit sequences. * * Each code tree is stored in a compressed form which is itself * a Huffman encoding of the lengths of all the code strings (in * ascending order by source values). The actual code strings are * reconstructed from the lengths in the inflate process, as described * in the deflate specification. * * REFERENCES * * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc * * Storer, James A. * Data Compression: Methods and Theory, pp. 49-50. * Computer Science Press, 1988. ISBN 0-7167-8156-5. * * Sedgewick, R. * Algorithms, p290. * Addison-Wesley, 1983. ISBN 0-201-06672-6. */ /* @(#) $Id: trees.c,v 1.4 2004/07/10 07:48:39 mcr Exp $ */ /* #define GEN_TREES_H */ #include "deflate.h" /* =========================================================================== * Constants */ #define MAX_BL_BITS 7 /* Bit length codes must not exceed MAX_BL_BITS bits */ #define END_BLOCK 256 /* end of block literal code */ #define REP_3_6 16 /* repeat previous bit length 3-6 times (2 bits of repeat count) */ #define REPZ_3_10 17 /* repeat a zero length 3-10 times (3 bits of repeat count) */ #define REPZ_11_138 18 /* repeat a zero length 11-138 times (7 bits of repeat count) */ local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; local const int extra_dbits[D_CODES] /* extra bits for each distance code */ = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; local const uch bl_order[BL_CODES] = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; /* The lengths of the bit length codes are sent in order of decreasing * probability, to avoid transmitting the lengths for unused bit length codes. */ #define Buf_size (8 * 2*sizeof(char)) /* Number of bits used within bi_buf. (bi_buf might be implemented on * more than 16 bits on some systems.) */ /* =========================================================================== * Local data. These are initialized only once. */ #define DIST_CODE_LEN 512 /* see definition of array dist_code below */ #if defined(GEN_TREES_H) || !defined(STDC) /* non ANSI compilers may not accept trees.h */ local ct_data static_ltree[L_CODES+2]; /* The static literal tree. Since the bit lengths are imposed, there is no * need for the L_CODES extra codes used during heap construction. However * The codes 286 and 287 are needed to build a canonical tree (see _tr_init * below). */ local ct_data static_dtree[D_CODES]; /* The static distance tree. (Actually a trivial tree since all codes use * 5 bits.) */ uch _dist_code[DIST_CODE_LEN]; /* Distance codes. The first 256 values correspond to the distances * 3 .. 258, the last 256 values correspond to the top 8 bits of * the 15 bit distances. */ uch _length_code[MAX_MATCH-MIN_MATCH+1]; /* length code for each normalized match length (0 == MIN_MATCH) */ local int base_length[LENGTH_CODES]; /* First normalized length for each code (0 = MIN_MATCH) */ local int base_dist[D_CODES]; /* First normalized distance for each code (0 = distance of 1) */ #else # include "trees.h" #endif /* GEN_TREES_H */ struct static_tree_desc_s { const ct_data *static_tree; /* static tree or NULL */ const intf *extra_bits; /* extra bits for each code or NULL */ int extra_base; /* base index for extra_bits */ int elems; /* max number of elements in the tree */ int max_length; /* max bit length for the codes */ }; local static_tree_desc static_l_desc = {static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; local static_tree_desc static_d_desc = {static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; local static_tree_desc static_bl_desc = {(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; /* =========================================================================== * Local (static) routines in this file. */ local void tr_static_init OF((void)); local void init_block OF((deflate_state *s)); local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); local void build_tree OF((deflate_state *s, tree_desc *desc)); local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); local int build_bl_tree OF((deflate_state *s)); local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, int blcodes)); local void compress_block OF((deflate_state *s, const ct_data *ltree, const ct_data *dtree)); local void set_data_type OF((deflate_state *s)); local unsigned bi_reverse OF((unsigned value, int length)); local void bi_windup OF((deflate_state *s)); local void bi_flush OF((deflate_state *s)); local void copy_block OF((deflate_state *s, charf *buf, unsigned len, int header)); #ifdef GEN_TREES_H local void gen_trees_header OF((void)); #endif #ifndef DEBUG # define send_code(s, c, tree) send_bits(s, (tree)[c].Code, (tree)[c].Len) /* Send a code of the given tree. c and tree must not have side effects */ #else /* DEBUG */ # define send_code(s, c, tree) \ { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ send_bits(s, (tree)[c].Code, (tree)[c].Len); } #endif /* =========================================================================== * Output a short LSB first on the stream. * IN assertion: there is enough room in pendingBuf. */ #define put_short(s, w) { \ put_byte(s, (uch)((w) & 0xff)); \ put_byte(s, (uch)((ush)(w) >> 8)); \ } /* =========================================================================== * Send a value on a given number of bits. * IN assertion: length <= 16 and value fits in length bits. */ #ifdef DEBUG local void send_bits OF((deflate_state *s, int value, int length)); local void send_bits(s, value, length) deflate_state *s; int value; /* value to send */ int length; /* number of bits */ { Tracevv((stderr," l %2d v %4x ", length, value)); Assert(length > 0 && length <= 15, "invalid length"); s->bits_sent += (ulg)length; /* If not enough room in bi_buf, use (valid) bits from bi_buf and * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) * unused bits in value. */ if (s->bi_valid > (int)Buf_size - length) { s->bi_buf |= (value << s->bi_valid); put_short(s, s->bi_buf); s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); s->bi_valid += length - Buf_size; } else { s->bi_buf |= value << s->bi_valid; s->bi_valid += length; } } #else /* !DEBUG */ #define send_bits(s, value, length) \ { int len = (length);\ if ((s)->bi_valid > (int)Buf_size - len) {\ int val = (value);\ (s)->bi_buf |= (val << (s)->bi_valid);\ put_short(s, (s)->bi_buf);\ (s)->bi_buf = (ush)val >> (Buf_size - (s)->bi_valid);\ (s)->bi_valid += len - Buf_size;\ } else {\ (s)->bi_buf |= (value) << (s)->bi_valid;\ (s)->bi_valid += len;\ }\ } #endif /* DEBUG */ #define MAX(a,b) ((a) >= (b) ? (a) : (b)) /* the arguments must not have side effects */ /* =========================================================================== * Initialize the various 'constant' tables. */ local void tr_static_init(void) { #if defined(GEN_TREES_H) || !defined(STDC) static int static_init_done = 0; int n; /* iterates over tree elements */ int bits; /* bit counter */ int length; /* length value */ int code; /* code value */ int dist; /* distance index */ ush bl_count[MAX_BITS+1]; /* number of codes at each bit length for an optimal tree */ if (static_init_done) return; /* For some embedded targets, global variables are not initialized: */ static_l_desc.static_tree = static_ltree; static_l_desc.extra_bits = extra_lbits; static_d_desc.static_tree = static_dtree; static_d_desc.extra_bits = extra_dbits; static_bl_desc.extra_bits = extra_blbits; /* Initialize the mapping length (0..255) -> length code (0..28) */ length = 0; for (code = 0; code < LENGTH_CODES-1; code++) { base_length[code] = length; for (n = 0; n < (1< dist code (0..29) */ dist = 0; for (code = 0 ; code < 16; code++) { base_dist[code] = dist; for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ for ( ; code < D_CODES; code++) { base_dist[code] = dist << 7; for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { _dist_code[256 + dist++] = (uch)code; } } Assert (dist == 256, "tr_static_init: 256+dist != 512"); /* Construct the codes of the static literal tree */ for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; n = 0; while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; /* Codes 286 and 287 do not exist, but we must include them in the * tree construction to get a canonical Huffman tree (longest code * all ones) */ gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); /* The static distance tree is trivial: */ for (n = 0; n < D_CODES; n++) { static_dtree[n].Len = 5; static_dtree[n].Code = bi_reverse((unsigned)n, 5); } static_init_done = 1; # ifdef GEN_TREES_H gen_trees_header(); # endif #endif /* defined(GEN_TREES_H) || !defined(STDC) */ } /* =========================================================================== * Generate the file trees.h describing the static trees. */ #ifdef GEN_TREES_H # ifndef DEBUG # include # endif # define SEPARATOR(i, last, width) \ ((i) == (last)? "\n};\n\n" : \ ((i) % (width) == (width)-1 ? ",\n" : ", ")) void gen_trees_header(void) { FILE *header = fopen("trees.h", "w"); int i; Assert (header != NULL, "Can't open trees.h"); fprintf(header, "/* header created automatically with -DGEN_TREES_H */\n\n"); fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); for (i = 0; i < L_CODES+2; i++) { fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); } fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); for (i = 0; i < D_CODES; i++) { fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); } fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n"); for (i = 0; i < DIST_CODE_LEN; i++) { fprintf(header, "%2u%s", _dist_code[i], SEPARATOR(i, DIST_CODE_LEN-1, 20)); } fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { fprintf(header, "%2u%s", _length_code[i], SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); } fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); for (i = 0; i < LENGTH_CODES; i++) { fprintf(header, "%1u%s", base_length[i], SEPARATOR(i, LENGTH_CODES-1, 20)); } fprintf(header, "local const int base_dist[D_CODES] = {\n"); for (i = 0; i < D_CODES; i++) { fprintf(header, "%5u%s", base_dist[i], SEPARATOR(i, D_CODES-1, 10)); } fclose(header); } #endif /* GEN_TREES_H */ /* =========================================================================== * Initialize the tree data structures for a new zlib stream. */ void _tr_init(s) deflate_state *s; { tr_static_init(); s->l_desc.dyn_tree = s->dyn_ltree; s->l_desc.stat_desc = &static_l_desc; s->d_desc.dyn_tree = s->dyn_dtree; s->d_desc.stat_desc = &static_d_desc; s->bl_desc.dyn_tree = s->bl_tree; s->bl_desc.stat_desc = &static_bl_desc; s->bi_buf = 0; s->bi_valid = 0; s->last_eob_len = 8; /* enough lookahead for inflate */ #ifdef DEBUG s->compressed_len = 0L; s->bits_sent = 0L; #endif /* Initialize the first block of the first file: */ init_block(s); } /* =========================================================================== * Initialize a new block. */ local void init_block(s) deflate_state *s; { int n; /* iterates over tree elements */ /* Initialize the trees. */ for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; s->dyn_ltree[END_BLOCK].Freq = 1; s->opt_len = s->static_len = 0L; s->last_lit = s->matches = 0; } #define SMALLEST 1 /* Index within the heap array of least frequent node in the Huffman tree */ /* =========================================================================== * Remove the smallest element from the heap and recreate the heap with * one less element. Updates heap and heap_len. */ #define pqremove(s, tree, top) \ {\ (top) = (s)->heap[SMALLEST]; \ (s)->heap[SMALLEST] = (s)->heap[(s)->heap_len--]; \ pqdownheap(s, tree, SMALLEST); \ } /* =========================================================================== * Compares to subtrees, using the tree depth as tie breaker when * the subtrees have equal frequency. This minimizes the worst case length. */ #define smaller(tree, n, m, depth) \ ((tree)[n].Freq < (tree)[m].Freq || \ ((tree)[n].Freq == (tree)[m].Freq && (depth)[n] <= (depth)[m])) /* =========================================================================== * Restore the heap property by moving down the tree starting at node k, * exchanging a node with the smallest of its two sons if necessary, stopping * when the heap property is re-established (each father smaller than its * two sons). */ local void pqdownheap(s, tree, k) deflate_state *s; ct_data *tree; /* the tree to restore */ int k; /* node to move down */ { int v = s->heap[k]; int j = k << 1; /* left son of k */ while (j <= s->heap_len) { /* Set j to the smallest of the two sons: */ if (j < s->heap_len && smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { j++; } /* Exit if v is smaller than both sons */ if (smaller(tree, v, s->heap[j], s->depth)) break; /* Exchange v with the smallest son */ s->heap[k] = s->heap[j]; k = j; /* And continue down the tree, setting j to the left son of k */ j <<= 1; } s->heap[k] = v; } /* =========================================================================== * Compute the optimal bit lengths for a tree and update the total bit length * for the current block. * IN assertion: the fields freq and dad are set, heap[heap_max] and * above are the tree nodes sorted by increasing frequency. * OUT assertions: the field len is set to the optimal bit length, the * array bl_count contains the frequencies for each bit length. * The length opt_len is updated; static_len is also updated if stree is * not null. */ local void gen_bitlen(s, desc) deflate_state *s; tree_desc *desc; /* the tree descriptor */ { ct_data *tree = desc->dyn_tree; int max_code = desc->max_code; const ct_data *stree = desc->stat_desc->static_tree; const intf *extra = desc->stat_desc->extra_bits; int base = desc->stat_desc->extra_base; int max_length = desc->stat_desc->max_length; int h; /* heap index */ int n, m; /* iterate over the tree elements */ int bits; /* bit length */ int xbits; /* extra bits */ ush f; /* frequency */ int overflow = 0; /* number of elements with bit length too large */ for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; /* In a first pass, compute the optimal bit lengths (which may * overflow in the case of the bit length tree). */ tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ for (h = s->heap_max+1; h < HEAP_SIZE; h++) { n = s->heap[h]; bits = tree[tree[n].Dad].Len + 1; if (bits > max_length) bits = max_length, overflow++; tree[n].Len = (ush)bits; /* We overwrite tree[n].Dad which is no longer needed */ if (n > max_code) continue; /* not a leaf node */ s->bl_count[bits]++; xbits = 0; if (n >= base) xbits = extra[n-base]; f = tree[n].Freq; s->opt_len += (ulg)f * (bits + xbits); if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); } if (overflow == 0) return; Trace((stderr,"\nbit length overflow\n")); /* This happens for example on obj2 and pic of the Calgary corpus */ /* Find the first bit length which could increase: */ do { bits = max_length-1; while (s->bl_count[bits] == 0) bits--; s->bl_count[bits]--; /* move one leaf down the tree */ s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ s->bl_count[max_length]--; /* The brother of the overflow item also moves one step up, * but this does not affect bl_count[max_length] */ overflow -= 2; } while (overflow > 0); /* Now recompute all bit lengths, scanning in increasing frequency. * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all * lengths instead of fixing only the wrong ones. This idea is taken * from 'ar' written by Haruhiko Okumura.) */ for (bits = max_length; bits != 0; bits--) { n = s->bl_count[bits]; while (n != 0) { m = s->heap[--h]; if (m > max_code) continue; if (tree[m].Len != (unsigned) bits) { Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); s->opt_len += ((long)bits - (long)tree[m].Len) *(long)tree[m].Freq; tree[m].Len = (ush)bits; } n--; } } } /* =========================================================================== * Generate the codes for a given tree and bit counts (which need not be * optimal). * IN assertion: the array bl_count contains the bit length statistics for * the given tree and the field len is set for all tree elements. * OUT assertion: the field code is set for all tree elements of non * zero code length. */ local void gen_codes (tree, max_code, bl_count) ct_data *tree; /* the tree to decorate */ int max_code; /* largest code with non zero frequency */ ushf *bl_count; /* number of codes at each bit length */ { ush next_code[MAX_BITS+1]; /* next code value for each bit length */ ush code = 0; /* running code value */ int bits; /* bit index */ int n; /* code index */ /* The distribution counts are first used to generate the code values * without bit reversal. */ for (bits = 1; bits <= MAX_BITS; bits++) { next_code[bits] = code = (code + bl_count[bits-1]) << 1; } /* Check that the bit counts in bl_count are consistent. The last code * must be all ones. */ Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; const ct_data *stree = desc->stat_desc->static_tree; int elems = desc->stat_desc->elems; int n, m; /* iterate over heap elements */ int max_code = -1; /* largest code with non zero frequency */ int node; /* new node being created */ /* Construct the initial heap, with least frequent element in * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. * heap[0] is not used. */ s->heap_len = 0, s->heap_max = HEAP_SIZE; for (n = 0; n < elems; n++) { if (tree[n].Freq != 0) { s->heap[++(s->heap_len)] = max_code = n; s->depth[n] = 0; } else { tree[n].Len = 0; } } /* The pkzip format requires that at least one distance code exists, * and that at least one bit should be sent even if there is only one * possible code. So to avoid special checks later on we force at least * two codes of non zero frequency. */ while (s->heap_len < 2) { node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); tree[node].Freq = 1; s->depth[node] = 0; s->opt_len--; if (stree) s->static_len -= stree[node].Len; /* node is 0 or 1 so it does not have extra bits */ } desc->max_code = max_code; /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, * establish sub-heaps of increasing lengths: */ for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); /* Construct the Huffman tree by repeatedly combining the least two * frequent nodes. */ node = elems; /* next internal node of the tree */ do { pqremove(s, tree, n); /* n = node of least frequency */ m = s->heap[SMALLEST]; /* m = node of next least frequency */ s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ s->heap[--(s->heap_max)] = m; /* Create a new node father of n and m */ tree[node].Freq = tree[n].Freq + tree[m].Freq; s->depth[node] = (uch) (MAX(s->depth[n], s->depth[m]) + 1); tree[n].Dad = tree[m].Dad = (ush)node; #ifdef DUMP_BL_TREE if (tree == s->bl_tree) { fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); } #endif /* and insert the new node in the heap */ s->heap[SMALLEST] = node++; pqdownheap(s, tree, SMALLEST); } while (s->heap_len >= 2); s->heap[--(s->heap_max)] = s->heap[SMALLEST]; /* At this point, the fields freq and dad are set. We can now * generate the bit lengths. */ gen_bitlen(s, (tree_desc *)desc); /* The field len is now set, we can generate the bit codes */ gen_codes ((ct_data *)tree, max_code, s->bl_count); } /* =========================================================================== * Scan a literal or distance tree to determine the frequencies of the codes * in the bit length tree. */ local void scan_tree (s, tree, max_code) deflate_state *s; ct_data *tree; /* the tree to be scanned */ int max_code; /* and its largest code of non zero frequency */ { int n; /* iterates over all tree elements */ int prevlen = -1; /* last emitted length */ int curlen; /* length of current code */ int nextlen = tree[0].Len; /* length of next code */ int count = 0; /* repeat count of the current code */ int max_count = 7; /* max repeat count */ int min_count = 4; /* min repeat count */ if (nextlen == 0) max_count = 138, min_count = 3; tree[max_code+1].Len = (ush)0xffff; /* guard */ for (n = 0; n <= max_code; n++) { curlen = nextlen; nextlen = tree[n+1].Len; if (++count < max_count && curlen == nextlen) { continue; } else if (count < min_count) { s->bl_tree[curlen].Freq += count; } else if (curlen != 0) { if (curlen != prevlen) s->bl_tree[curlen].Freq++; s->bl_tree[REP_3_6].Freq++; } else if (count <= 10) { s->bl_tree[REPZ_3_10].Freq++; } else { s->bl_tree[REPZ_11_138].Freq++; } count = 0; prevlen = curlen; if (nextlen == 0) { max_count = 138, min_count = 3; } else if (curlen == nextlen) { max_count = 6, min_count = 3; } else { max_count = 7, min_count = 4; } } } /* =========================================================================== * Send a literal or distance tree in compressed form, using the codes in * bl_tree. */ local void send_tree (s, tree, max_code) deflate_state *s; ct_data *tree; /* the tree to be scanned */ int max_code; /* and its largest code of non zero frequency */ { int n; /* iterates over all tree elements */ int prevlen = -1; /* last emitted length */ int curlen; /* length of current code */ int nextlen = tree[0].Len; /* length of next code */ int count = 0; /* repeat count of the current code */ int max_count = 7; /* max repeat count */ int min_count = 4; /* min repeat count */ /* tree[max_code+1].Len = -1; */ /* guard already set */ if (nextlen == 0) max_count = 138, min_count = 3; for (n = 0; n <= max_code; n++) { curlen = nextlen; nextlen = tree[n+1].Len; if (++count < max_count && curlen == nextlen) { continue; } else if (count < min_count) { do { send_code(s, curlen, s->bl_tree); } while (--count != 0); } else if (curlen != 0) { if (curlen != prevlen) { send_code(s, curlen, s->bl_tree); count--; } Assert(count >= 3 && count <= 6, " 3_6?"); send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); } else if (count <= 10) { send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); } else { send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); } count = 0; prevlen = curlen; if (nextlen == 0) { max_count = 138, min_count = 3; } else if (curlen == nextlen) { max_count = 6, min_count = 3; } else { max_count = 7, min_count = 4; } } } /* =========================================================================== * Construct the Huffman tree for the bit lengths and return the index in * bl_order of the last bit length code to send. */ local int build_bl_tree(s) deflate_state *s; { int max_blindex; /* index of last bit length code of non zero freq */ /* Determine the bit length frequencies for literal and distance trees */ scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); /* Build the bit length tree: */ build_tree(s, (tree_desc *)(&(s->bl_desc))); /* opt_len now includes the length of the tree representations, except * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. */ /* Determine the number of bit length codes to send. The pkzip format * requires that at least 4 bit length codes be sent. (appnote.txt says * 3 but the actual value used is 4.) */ for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; } /* Update opt_len to include the bit length tree and counts */ s->opt_len += 3*(max_blindex+1) + 5+5+4; Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", s->opt_len, s->static_len)); return max_blindex; } /* =========================================================================== * Send the header for a block using dynamic Huffman trees: the counts, the * lengths of the bit length codes, the literal tree and the distance tree. * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. */ local void send_all_trees(s, lcodes, dcodes, blcodes) deflate_state *s; int lcodes, dcodes, blcodes; /* number of codes for each tree */ { int rank; /* index in bl_order */ Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, "too many codes"); Tracev((stderr, "\nbl counts: ")); send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ send_bits(s, dcodes-1, 5); send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ for (rank = 0; rank < blcodes; rank++) { Tracev((stderr, "\nbl code %2d ", bl_order[rank])); send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); } Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); } /* =========================================================================== * Send a stored block */ void _tr_stored_block(s, buf, stored_len, eof) deflate_state *s; charf *buf; /* input block */ ulg stored_len; /* length of input block */ int eof; /* true if this is the last block for a file */ { send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ #ifdef DEBUG s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; s->compressed_len += (stored_len + 4) << 3; #endif copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ } /* =========================================================================== * Send one empty static block to give enough lookahead for inflate. * This takes 10 bits, of which 7 may remain in the bit buffer. * The current inflate code requires 9 bits of lookahead. If the * last two codes for the previous block (real code plus EOB) were coded * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode * the last real code. In this case we send two empty static blocks instead * of one. (There are no problems if the previous block is stored or fixed.) * To simplify the code, we assume the worst case of last real code encoded * on one bit only. */ void _tr_align(s) deflate_state *s; { send_bits(s, STATIC_TREES<<1, 3); send_code(s, END_BLOCK, static_ltree); #ifdef DEBUG s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ #endif bi_flush(s); /* Of the 10 bits for the empty block, we have already sent * (10 - bi_valid) bits. The lookahead for the last real code (before * the EOB of the previous block) was thus at least one plus the length * of the EOB plus what we have just sent of the empty static block. */ if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { send_bits(s, STATIC_TREES<<1, 3); send_code(s, END_BLOCK, static_ltree); #ifdef DEBUG s->compressed_len += 10L; #endif bi_flush(s); } s->last_eob_len = 7; } /* =========================================================================== * Determine the best encoding for the current block: dynamic trees, static * trees or store, and output the encoded block to the zip file. */ void _tr_flush_block(s, buf, stored_len, eof) deflate_state *s; charf *buf; /* input block, or NULL if too old */ ulg stored_len; /* length of input block */ int eof; /* true if this is the last block for a file */ { ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ int max_blindex = 0; /* index of last bit length code of non zero freq */ /* Build the Huffman trees unless a stored block is forced */ if (s->level > 0) { /* Check if the file is ascii or binary */ if (s->data_type == Z_UNKNOWN) set_data_type(s); /* Construct the literal and distance trees */ build_tree(s, (tree_desc *)(&(s->l_desc))); Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, s->static_len)); build_tree(s, (tree_desc *)(&(s->d_desc))); Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, s->static_len)); /* At this point, opt_len and static_len are the total bit lengths of * the compressed block data, excluding the tree representations. */ /* Build the bit length tree for the above two trees, and get the index * in bl_order of the last bit length code to send. */ max_blindex = build_bl_tree(s); /* Determine the best encoding. Compute first the block length in bytes*/ opt_lenb = (s->opt_len+3+7)>>3; static_lenb = (s->static_len+3+7)>>3; Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, s->last_lit)); if (static_lenb <= opt_lenb) opt_lenb = static_lenb; } else { Assert(buf != (char*)0, "lost buf"); opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ } #ifdef FORCE_STORED if (buf != (char*)0) { /* force stored block */ #else if (stored_len+4 <= opt_lenb && buf != (char*)0) { /* 4: two words for the lengths */ #endif /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. * Otherwise we can't have processed more than WSIZE input bytes since * the last block flush, because compression would have been * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to * transform a block into a stored block. */ _tr_stored_block(s, buf, stored_len, eof); #ifdef FORCE_STATIC } else if (static_lenb >= 0) { /* force static trees */ #else } else if (static_lenb == opt_lenb) { #endif send_bits(s, (STATIC_TREES<<1)+eof, 3); compress_block(s, static_ltree, static_dtree); #ifdef DEBUG s->compressed_len += 3 + s->static_len; #endif } else { send_bits(s, (DYN_TREES<<1)+eof, 3); send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, max_blindex+1); compress_block(s, s->dyn_ltree, s->dyn_dtree); #ifdef DEBUG s->compressed_len += 3 + s->opt_len; #endif } Assert (s->compressed_len == s->bits_sent, "bad compressed size"); /* The above check is made mod 2^32, for files larger than 512 MB * and uLong implemented on 32 bits. */ init_block(s); if (eof) { bi_windup(s); #ifdef DEBUG s->compressed_len += 7; /* align on byte boundary */ #endif } Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, s->compressed_len-7*eof)); } /* =========================================================================== * Save the match info and tally the frequency counts. Return true if * the current block must be flushed. */ int _tr_tally (s, dist, lc) deflate_state *s; unsigned dist; /* distance of matched string */ unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ { s->d_buf[s->last_lit] = (ush)dist; s->l_buf[s->last_lit++] = (uch)lc; if (dist == 0) { /* lc is the unmatched char */ s->dyn_ltree[lc].Freq++; } else { s->matches++; /* Here, lc is the match length - MIN_MATCH */ dist--; /* dist = match distance - 1 */ Assert((ush)dist < (ush)MAX_DIST(s) && (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; s->dyn_dtree[d_code(dist)].Freq++; } #ifdef TRUNCATE_BLOCK /* Try to guess if it is profitable to stop the current block here */ if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { /* Compute an upper bound for the compressed length */ ulg out_length = (ulg)s->last_lit*8L; ulg in_length = (ulg)((long)s->strstart - s->block_start); int dcode; for (dcode = 0; dcode < D_CODES; dcode++) { out_length += (ulg)s->dyn_dtree[dcode].Freq * (5L+extra_dbits[dcode]); } out_length >>= 3; Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", s->last_lit, in_length, out_length, 100L - out_length*100L/in_length)); if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; } #endif return (s->last_lit == s->lit_bufsize-1); /* We avoid equality with lit_bufsize because of wraparound at 64K * on 16 bit machines and because stored blocks are restricted to * 64K-1 bytes. */ } /* =========================================================================== * Send the block data compressed using the given Huffman trees */ local void compress_block(s, ltree, dtree) deflate_state *s; const ct_data *ltree; /* literal tree */ const ct_data *dtree; /* distance tree */ { unsigned dist; /* distance of matched string */ int lc; /* match length or unmatched char (if dist == 0) */ unsigned lx = 0; /* running index in l_buf */ unsigned code; /* the code to send */ int extra; /* number of extra bits to send */ if (s->last_lit != 0) do { dist = s->d_buf[lx]; lc = s->l_buf[lx++]; if (dist == 0) { send_code(s, lc, ltree); /* send a literal byte */ Tracecv(isgraph(lc), (stderr," '%c' ", lc)); } else { /* Here, lc is the match length - MIN_MATCH */ code = _length_code[lc]; send_code(s, code+LITERALS+1, ltree); /* send the length code */ extra = extra_lbits[code]; if (extra != 0) { lc -= base_length[code]; send_bits(s, lc, extra); /* send the extra length bits */ } dist--; /* dist is now the match distance - 1 */ code = d_code(dist); Assert (code < D_CODES, "bad d_code"); send_code(s, code, dtree); /* send the distance code */ extra = extra_dbits[code]; if (extra != 0) { dist -= base_dist[code]; send_bits(s, dist, extra); /* send the extra distance bits */ } } /* literal or match pair ? */ /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ Assert(s->pending < s->lit_bufsize + 2*lx, "pendingBuf overflow"); } while (lx < s->last_lit); send_code(s, END_BLOCK, ltree); s->last_eob_len = ltree[END_BLOCK].Len; } /* =========================================================================== * Set the data type to ASCII or BINARY, using a crude approximation: * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise. * IN assertion: the fields freq of dyn_ltree are set and the total of all * frequencies does not exceed 64K (to fit in an int on 16 bit machines). */ local void set_data_type(s) deflate_state *s; { int n = 0; unsigned ascii_freq = 0; unsigned bin_freq = 0; while (n < 7) bin_freq += s->dyn_ltree[n++].Freq; while (n < 128) ascii_freq += s->dyn_ltree[n++].Freq; while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq; s->data_type = (Byte)(bin_freq > (ascii_freq >> 2) ? Z_BINARY : Z_ASCII); } /* =========================================================================== * Reverse the first len bits of a code, using straightforward code (a faster * method would use a table) * IN assertion: 1 <= len <= 15 */ local unsigned bi_reverse(code, len) unsigned code; /* the value to invert */ int len; /* its bit length */ { register unsigned res = 0; do { res |= code & 1; code >>= 1, res <<= 1; } while (--len > 0); return res >> 1; } /* =========================================================================== * Flush the bit buffer, keeping at most 7 bits in it. */ local void bi_flush(s) deflate_state *s; { if (s->bi_valid == 16) { put_short(s, s->bi_buf); s->bi_buf = 0; s->bi_valid = 0; } else if (s->bi_valid >= 8) { put_byte(s, (Byte)s->bi_buf); s->bi_buf >>= 8; s->bi_valid -= 8; } } /* =========================================================================== * Flush the bit buffer and align the output on a byte boundary */ local void bi_windup(s) deflate_state *s; { if (s->bi_valid > 8) { put_short(s, s->bi_buf); } else if (s->bi_valid > 0) { put_byte(s, (Byte)s->bi_buf); } s->bi_buf = 0; s->bi_valid = 0; #ifdef DEBUG s->bits_sent = (s->bits_sent+7) & ~7; #endif } /* =========================================================================== * Copy a stored block, storing first the length and its * one's complement if requested. */ local void copy_block(s, buf, len, header) deflate_state *s; charf *buf; /* the input data */ unsigned len; /* its length */ int header; /* true if block header must be written */ { bi_windup(s); /* align on byte boundary */ s->last_eob_len = 8; /* enough lookahead for inflate */ if (header) { put_short(s, (ush)len); put_short(s, (ush)~len); #ifdef DEBUG s->bits_sent += 2*16; #endif } #ifdef DEBUG s->bits_sent += (ulg)len<<3; #endif while (len--) { put_byte(s, *buf++); } } libreswan-3.32/linux/net/ipsec/trees.h000066400000000000000000000203741365625662500200000ustar00rootroot00000000000000/* header created automatically with -DGEN_TREES_H */ local const ct_data static_ltree[L_CODES+2] = { {{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, {{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, {{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, {{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, {{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, {{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, {{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, {{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, {{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, {{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, {{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, {{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, {{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, {{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, {{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, {{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, {{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, {{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, {{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, {{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, {{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, {{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, {{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, {{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, {{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, {{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, {{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, {{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, {{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, {{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, {{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, {{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, {{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, {{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, {{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, {{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, {{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, {{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, {{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, {{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, {{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, {{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, {{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, {{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, {{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, {{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, {{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, {{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, {{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, {{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, {{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, {{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, {{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, {{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, {{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, {{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, {{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, {{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} }; local const ct_data static_dtree[D_CODES] = { {{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, {{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, {{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, {{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, {{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, {{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} }; const uch _dist_code[DIST_CODE_LEN] = { 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, 18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 }; const uch _length_code[MAX_MATCH-MIN_MATCH+1]= { 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 }; local const int base_length[LENGTH_CODES] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 0 }; local const int base_dist[D_CODES] = { 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 }; libreswan-3.32/linux/net/ipsec/ultot.c000066400000000000000000000033521365625662500200150ustar00rootroot00000000000000/* * convert unsigned long to text * Copyright (C) 2000 Henry Spencer. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. */ #include "libreswan.h" /* - ultot - convert unsigned long to text */ size_t /* length required for full conversion */ ultot(n, base, dst, dstlen) unsigned long n; int base; char *dst; /* need not be valid if dstlen is 0 */ size_t dstlen; { char buf[3 * sizeof(unsigned long) + 1]; char *bufend = buf + sizeof(buf); size_t len; char *p; static const char hex[] = "0123456789abcdef"; # define HEX32 (32 / 4) p = bufend; *--p = '\0'; switch (base) { case 10: case 'd': do { *--p = n % 10 + '0'; n /= 10; } while (n != 0); break; case 16: case 17: case 'x': do { *--p = hex[n & 0xf]; n >>= 4; } while (n != 0); if (base == 17) while (bufend - p < HEX32 + 1) *--p = '0'; if (base == 'x') { *--p = 'x'; *--p = '0'; } break; case 8: case 'o': do { *--p = (n & 07) + '0'; n >>= 3; } while (n != 0); if (base == 'o') *--p = '0'; break; default: return 0; break; } len = bufend - p; if (dstlen > 0) { if (len > dstlen) *(p + dstlen - 1) = '\0'; strcpy(dst, p); } return len; } libreswan-3.32/linux/net/ipsec/version.in.c000066400000000000000000000034101365625662500207330ustar00rootroot00000000000000/* * return IPsec version information * Copyright (C) 2001 Henry Spencer. * Copyright (C) 2013 Paul Wouters * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. * */ #ifdef __KERNEL__ # include #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38) && \ !defined(AUTOCONF_INCLUDED) # include # endif # define __NO_VERSION__ # include # if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) && LINUX_VERSION_CODE >= \ KERNEL_VERSION(2, 4, 26) # include # endif #endif #include "libreswan.h" #define V "@IPSECVERSION@" /* substituted in by Makefile */ #define VID "@IPSECVIDVERSION@" /* substituted in by Makefile */ #define OUR_VENDOR_VID "OE-Libreswan-@IPSECVIDVERSION@" /* substituted in by Makefile */ static const char libreswan_number[] = V; static const char libreswan_string[] = "Libreswan " V; #ifdef __KERNEL__ static #endif const char libreswan_vendorid[] = OUR_VENDOR_VID; /* * pass version to modinfo */ #ifdef MODULE_VERSION MODULE_VERSION(V); #endif const char *ipsec_version_code(void) { return libreswan_number; } const char *ipsec_version_string(void) { return libreswan_string; } const char *ipsec_version_vendorid(void) { return libreswan_vendorid; } libreswan-3.32/linux/net/ipsec/zutil.c000066400000000000000000000122551365625662500200170ustar00rootroot00000000000000/* zutil.c -- target dependent utility functions for the compression library * Copyright (C) 1995-2002 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id: zutil.c,v 1.5 2004/07/10 07:48:40 mcr Exp $ */ #include #define MY_ZCALLOC struct internal_state {int dummy;}; /* for buggy compilers */ #ifndef STDC extern void exit OF((int)); #endif const char *z_errmsg[10] = { "need dictionary", /* Z_NEED_DICT 2 */ "stream end", /* Z_STREAM_END 1 */ "", /* Z_OK 0 */ "file error", /* Z_ERRNO (-1) */ "stream error", /* Z_STREAM_ERROR (-2) */ "data error", /* Z_DATA_ERROR (-3) */ "insufficient memory", /* Z_MEM_ERROR (-4) */ "buffer error", /* Z_BUF_ERROR (-5) */ "incompatible version",/* Z_VERSION_ERROR (-6) */ ""}; const char * ZEXPORT zlibVersion() { return ZLIB_VERSION; } #if 0 # ifndef verbose # define verbose 0 # endif int z_verbose = verbose; void z_error (m) char *m; { fprintf(stderr, "%s\n", m); exit(1); } #endif /* exported to allow conversion of error code to string for compress() and * uncompress() */ const char * ZEXPORT zError(err) int err; { return ERR_MSG(err); } #ifndef HAVE_MEMCPY void zmemcpy(dest, source, len) Bytef* dest; const Bytef* source; uInt len; { if (len == 0) return; do { *dest++ = *source++; /* ??? to be unrolled */ } while (--len != 0); } int zmemcmp(s1, s2, len) const Bytef* s1; const Bytef* s2; uInt len; { uInt j; for (j = 0; j < len; j++) { if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; } return 0; } void zmemzero(dest, len) Bytef* dest; uInt len; { if (len == 0) return; do { *dest++ = 0; /* ??? to be unrolled */ } while (--len != 0); } #endif #ifdef __TURBOC__ #if (defined( __BORLANDC__) || !defined(SMALL_MEDIUM)) && !defined(__32BIT__) /* Small and medium model in Turbo C are for now limited to near allocation * with reduced MAX_WBITS and MAX_MEM_LEVEL */ # define MY_ZCALLOC /* Turbo C malloc() does not allow dynamic allocation of 64K bytes * and farmalloc(64K) returns a pointer with an offset of 8, so we * must fix the pointer. Warning: the pointer must be put back to its * original form in order to free it, use zcfree(). */ #define MAX_PTR 10 /* 10*64K = 640K */ local int next_ptr = 0; typedef struct ptr_table_s { voidpf org_ptr; voidpf new_ptr; } ptr_table; local ptr_table table[MAX_PTR]; /* This table is used to remember the original form of pointers * to large buffers (64K). Such pointers are normalized with a zero offset. * Since MSDOS is not a preemptive multitasking OS, this table is not * protected from concurrent access. This hack doesn't work anyway on * a protected system like OS/2. Use Microsoft C instead. */ voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) { voidpf buf = opaque; /* just to make some compilers happy */ ulg bsize = (ulg)items*size; /* If we allocate less than 65520 bytes, we assume that farmalloc * will return a usable pointer which doesn't have to be normalized. */ if (bsize < 65520L) { buf = farmalloc(bsize); if (*(ush*)&buf != 0) return buf; } else { buf = farmalloc(bsize + 16L); } if (buf == NULL || next_ptr >= MAX_PTR) return NULL; table[next_ptr].org_ptr = buf; /* Normalize the pointer to seg:0 */ *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; *(ush*)&buf = 0; table[next_ptr++].new_ptr = buf; return buf; } void zcfree (voidpf opaque, voidpf ptr) { int n; if (*(ush*)&ptr != 0) { /* object < 64K */ farfree(ptr); return; } /* Find the original pointer */ for (n = 0; n < next_ptr; n++) { if (ptr != table[n].new_ptr) continue; farfree(table[n].org_ptr); while (++n < next_ptr) { table[n-1] = table[n]; } next_ptr--; return; } ptr = opaque; /* just to make some compilers happy */ Assert(0, "zcfree: ptr not found"); } #endif #endif /* __TURBOC__ */ #if defined(M_I86) && !defined(__32BIT__) /* Microsoft C in 16-bit mode */ # define MY_ZCALLOC #if (!defined(_MSC_VER) || (_MSC_VER <= 600)) # define _halloc halloc # define _hfree hfree #endif voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) { if (opaque) opaque = 0; /* to make compiler happy */ return _halloc((long)items, size); } void zcfree (voidpf opaque, voidpf ptr) { if (opaque) opaque = 0; /* to make compiler happy */ _hfree(ptr); } #endif /* MSC */ #ifndef MY_ZCALLOC /* Any system without a special alloc function */ #ifndef STDC extern voidp calloc OF((uInt items, uInt size)); extern void free OF((voidpf ptr)); #endif voidpf zcalloc (opaque, items, size) voidpf opaque; unsigned items; unsigned size; { if (opaque) items += size - size; /* make compiler happy */ return (voidpf)calloc(items, size); } void zcfree (opaque, ptr) voidpf opaque; voidpf ptr; { free(ptr); if (opaque) return; /* make compiler happy */ } #endif /* MY_ZCALLOC */ libreswan-3.32/linux/net/ipv4/000077500000000000000000000000001365625662500162565ustar00rootroot00000000000000libreswan-3.32/linux/net/ipv4/af_inet.c.fs2_4.patch000066400000000000000000000007261365625662500220460ustar00rootroot00000000000000--- linux/net/ipv4/af_inet.c.preipsec Wed Apr 26 15:13:17 2000 +++ linux/net/ipv4/af_inet.c Fri Jun 30 15:01:27 2000 @@ -1019,6 +1019,17 @@ ip_mr_init(); #endif +#if defined(CONFIG_KLIPS) + { + extern /* void */ int ipsec_klips_init(void); + /* + * Initialise AF_INET ESP and AH protocol support including + * e-routing and SA tables + */ + ipsec_klips_init(); + } +#endif /* CONFIG_KLIPS */ + /* * Create all the /proc entries. */ libreswan-3.32/linux/net/ipv4/af_inet.c.fs2_6.patch000066400000000000000000000006711365625662500220470ustar00rootroot00000000000000--- swan26/net/ipv4/af_inet.c.orig Wed Jun 16 01:18:58 2004 +++ swan26/net/ipv4/af_inet.c Fri Aug 13 23:09:27 2004 @@ -1169,4 +1169,16 @@ #endif + +#if defined(CONFIG_KLIPS) + { + extern int ipsec_klips_init(void); + /* + * Initialise AF_INET ESP and AH protocol support including + * e-routing and SA tables + */ + ipsec_klips_init(); + } +#endif /* CONFIG_IPSEC */ + /* * Initialise per-cpu ipv4 mibs */ libreswan-3.32/macports/000077500000000000000000000000001365625662500152775ustar00rootroot00000000000000libreswan-3.32/macports/nspr/000077500000000000000000000000001365625662500162615ustar00rootroot00000000000000libreswan-3.32/macports/nspr/Portfile000066400000000000000000000035721365625662500177770ustar00rootroot00000000000000# $Id: Portfile 49105 2009-04-04 00:41:21Z jeremyhu@macports.org $ PortSystem 1.0 name nspr version 4.7.4 revision 1 categories devel maintainers jeremyhu openmaintainer platforms darwin description A platform-neutral API for system level and libc like functions. long_description ${description} homepage http://www.mozilla.org/projects/nspr master_sites http://ftp.mozilla.org/pub/mozilla.org/nspr/releases/v${version}/src/ \ ftp://ftp.mozilla.org/pub/mozilla.org/nspr/releases/v${version}/src/ checksums md5 ec1a991fc211450085149905c5e340da worksrcdir ${worksrcdir}/mozilla/nsprpub post-patch { reinplace "s|@executable_path|${prefix}/lib/nspr|g" \ ${worksrcpath}/configure.in \ ${worksrcpath}/configure } universal_variant no configure.args \ --disable-debug \ --enable-optimize='-O2' \ --enable-strip \ --libdir=${prefix}/lib/nspr variant debug description "build with debugging symbols" { configure.args-delete --disable-debug \ --enable-optimize='-O2' \ --enable-strip configure.args-append --enable-debug='-ggdb3' \ --disable-optimize \ --disable-strip configure.cflags "" } post-destroot { file mkdir ${destroot}${prefix}/lib/pkgconfig copy ${filespath}/nspr.pc ${destroot}${prefix}/lib/pkgconfig reinplace "s|@@prefix@@|${prefix}|" ${destroot}${prefix}/lib/pkgconfig/nspr.pc set mylibs [exec ${destroot}${prefix}/bin/nspr-config --libs] set mycflags [exec ${destroot}${prefix}/bin/nspr-config --cflags] set myversion [exec ${destroot}${prefix}/bin/nspr-config --version] reinplace "s|@@FULL_NSPR_LIBS@@|${mylibs}|" ${destroot}${prefix}/lib/pkgconfig/nspr.pc reinplace "s|@@FULL_NSPR_CFLAGS@@|${mycflags}|" ${destroot}${prefix}/lib/pkgconfig/nspr.pc reinplace "s|@@NSPR_VERSION@@|${myversion}|" ${destroot}${prefix}/lib/pkgconfig/nspr.pc } libreswan-3.32/macports/nspr/files/000077500000000000000000000000001365625662500173635ustar00rootroot00000000000000libreswan-3.32/macports/nspr/files/nspr.pc000066400000000000000000000003461365625662500206740ustar00rootroot00000000000000prefix=@@prefix@@ exec_prefix=@@prefix@@ libdir=@@prefix@@/lib includedir=@@prefix@@/include Name: NSPR Description: The Netscape Portable Runtime Version: @@NSPR_VERSION@@ Libs: @@FULL_NSPR_LIBS@@ Cflags: @@FULL_NSPR_CFLAGS@@ libreswan-3.32/macports/nss/000077500000000000000000000000001365625662500161025ustar00rootroot00000000000000libreswan-3.32/macports/nss/Portfile000066400000000000000000000077051365625662500176220ustar00rootroot00000000000000# $Id$ PortSystem 1.0 name nss version 3.12.3 set NSS_VMAJOR 3 set NSS_VMINOR 12 set NSS_VPATCH 3 categories net maintainers jeremyhu openmaintainer description Network Security Service libraries. depends_lib port:nspr long_description ${description} use_configure no homepage http://www.mozilla.org/projects/security/pki/nss/ platforms darwin set my_release NSS_[strsed ${version} {g/\./_/}]_RTM use_bzip2 yes master_sites ftp://ftp.mozilla.org/pub/mozilla.org/security/nss/releases/${my_release}/src/ \ http://ftp.mozilla.org/pub/mozilla.org/security/nss/releases/${my_release}/src/ checksums md5 ecb7079ba4ebcf29b7716775384f1f18 \ sha1 eeca14a37629287baa10eb7562a5fb927e9dd171 \ rmd160 b5339eda9dfc87385b2c11e2ca53be249b75ed69 depends_lib \ port:nspr \ port:sqlite3 patchfiles patch-UNIX.mk.diff \ patch-Darwin.mk.diff post-patch { reinplace "s|@executable_path|${prefix}/lib/nss|g" \ ${worksrcpath}/mozilla/security/coreconf/Darwin.mk \ ${worksrcpath}/mozilla/security/nss/cmd/platlibs.mk \ ${worksrcpath}/mozilla/security/nss/lib/smime/config.mk \ ${worksrcpath}/mozilla/security/nss/lib/ssl/config.mk reinplace "s|@@PREFIX@@|${prefix}|g" \ ${worksrcpath}/mozilla/security/coreconf/Darwin.mk \ ${worksrcpath}/mozilla/security/coreconf/UNIX.mk reinplace "s|= cc\$|= ${configure.cc}|" \ ${worksrcpath}/mozilla/security/coreconf/Darwin.mk reinplace "s|= c++\$|= ${configure.cxx}|" \ ${worksrcpath}/mozilla/security/coreconf/Darwin.mk reinplace "s|= ranlib\$|= /usr/bin/ranlib|" \ ${worksrcpath}/mozilla/security/coreconf/Darwin.mk } build {system "cd ${worksrcpath} && make -C mozilla/security/coreconf/nsinstall && make -C mozilla/security/dbm && make -C mozilla/security/nss NSPR_LIB_DIR=${prefix}/lib/nspr NSS_USE_SYSTEM_SQLITE=1"} destroot { xinstall -m 755 -d ${destroot}${prefix}/include/nss eval xinstall -m 755 [glob ${worksrcpath}/mozilla/dist/public/nss/*] ${destroot}${prefix}/include/nss eval xinstall -m 755 [glob ${worksrcpath}/mozilla/dist/public/dbm/*] ${destroot}${prefix}/include/nss xinstall -m 755 -d ${destroot}${prefix}/bin foreach f [glob ${worksrcpath}/mozilla/dist/Darwin*/bin/*] { xinstall -m 755 $f ${destroot}${prefix}/bin/nss-[file tail $f] } xinstall -m 755 -d ${destroot}${prefix}/lib/nss eval xinstall -m 755 [glob ${worksrcpath}/mozilla/dist/Darwin*/lib/*.dylib] ${destroot}${prefix}/lib/nss eval xinstall -m 644 [glob ${worksrcpath}/mozilla/dist/Darwin*/lib/libcrmf.a] ${destroot}${prefix}/lib/nss xinstall -m 755 -d ${destroot}${prefix}/lib/pkgconfig xinstall ${filespath}/nss.pc.in ${destroot}${prefix}/lib/pkgconfig/nss.pc xinstall -m 755 ${filespath}/nss-config.in ${destroot}${prefix}/bin/nss-config reinplace "s,@libdir@,${prefix}/lib/nss,g" ${destroot}${prefix}/bin/nss-config reinplace "s,@prefix@,${prefix},g" ${destroot}${prefix}/bin/nss-config reinplace "s,@exec_prefix@,${prefix},g" ${destroot}${prefix}/bin/nss-config reinplace "s,@includedir@,${prefix}/include/nss,g" ${destroot}${prefix}/bin/nss-config reinplace "s,@MOD_MAJOR_VERSION@,${NSS_VMAJOR},g" ${destroot}${prefix}/bin/nss-config reinplace "s,@MOD_MINOR_VERSION@,${NSS_VMINOR},g" ${destroot}${prefix}/bin/nss-config reinplace "s,@MOD_PATCH_VERSION@,${NSS_VPATCH},g" ${destroot}${prefix}/bin/nss-config set nspr_version [exec ${prefix}/bin/nspr-config --version] set nss_version [exec ${destroot}${prefix}/bin/nss-config --version] reinplace "s,@libdir@,${prefix}/lib/nss,g" ${destroot}${prefix}/lib/pkgconfig/nss.pc reinplace "s,@prefix@,${prefix},g" ${destroot}${prefix}/lib/pkgconfig/nss.pc reinplace "s,@exec_prefix@,${prefix},g" ${destroot}${prefix}/lib/pkgconfig/nss.pc reinplace "s,@includedir@,${prefix}/include/nss," ${destroot}${prefix}/lib/pkgconfig/nss.pc reinplace "s,@NSPR_VERSION@,${nspr_version},g" ${destroot}${prefix}/lib/pkgconfig/nss.pc reinplace "s,@NSS_VERSION@,${nss_version},g" ${destroot}${prefix}/lib/pkgconfig/nss.pc } libreswan-3.32/macports/nss/files/000077500000000000000000000000001365625662500172045ustar00rootroot00000000000000libreswan-3.32/macports/nss/files/nss-config.in000066400000000000000000000045141365625662500216060ustar00rootroot00000000000000#!/bin/sh prefix=@prefix@ major_version=@MOD_MAJOR_VERSION@ minor_version=@MOD_MINOR_VERSION@ patch_version=@MOD_PATCH_VERSION@ usage() { cat <&2 fi lib_ssl=yes lib_smime=yes lib_nss=yes lib_nssutil=yes while test $# -gt 0; do case "$1" in -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;; *) optarg= ;; esac case $1 in --prefix=*) prefix=$optarg ;; --prefix) echo_prefix=yes ;; --exec-prefix=*) exec_prefix=$optarg ;; --exec-prefix) echo_exec_prefix=yes ;; --includedir=*) includedir=$optarg ;; --includedir) echo_includedir=yes ;; --libdir=*) libdir=$optarg ;; --libdir) echo_libdir=yes ;; --version) echo ${major_version}.${minor_version}.${patch_version} ;; --cflags) echo_cflags=yes ;; --libs) echo_libs=yes ;; ssl) lib_ssl=yes ;; smime) lib_smime=yes ;; nss) lib_nss=yes ;; nssutil) lib_nssutil=yes ;; *) usage 1 1>&2 ;; esac shift done # Set variables that may be dependent upon other variables if test -z "$exec_prefix"; then exec_prefix=@exec_prefix@ fi if test -z "$includedir"; then includedir=@includedir@ fi if test -z "$libdir"; then libdir=@libdir@ fi if test "$echo_prefix" = "yes"; then echo $prefix fi if test "$echo_exec_prefix" = "yes"; then echo $exec_prefix fi if test "$echo_includedir" = "yes"; then echo $includedir fi if test "$echo_libdir" = "yes"; then echo $libdir fi if test "$echo_cflags" = "yes"; then echo -I$includedir fi if test "$echo_libs" = "yes"; then libdirs="-L$libdir" if test -n "$lib_ssl"; then libdirs="$libdirs -lssl${major_version}" fi if test -n "$lib_smime"; then libdirs="$libdirs -lsmime${major_version}" fi if test -n "$lib_nss"; then libdirs="$libdirs -lnss${major_version}" fi if test -n "$lib_nssutil"; then libdirs="$libdirs -lnssutil${major_version}" fi echo $libdirs fi libreswan-3.32/macports/nss/files/nss.pc.in000066400000000000000000000004011365625662500207330ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: NSS Description: Network Security Services Version: @NSS_VERSION@ Requires: nspr >= @NSPR_VERSION@ Libs: -L${libdir} -lssl3 -lsmime3 ${NSSLIBS} Cflags: -I${includedir} libreswan-3.32/macports/nss/files/patch-Darwin.mk.diff000066400000000000000000000026351365625662500227730ustar00rootroot00000000000000--- mozilla/security/coreconf/Darwin.mk.orig 2008-01-05 04:17:18.000000000 +0100 +++ mozilla/security/coreconf/Darwin.mk 2008-01-05 04:16:10.000000000 +0100 @@ -74,7 +74,7 @@ export NEXT_ROOT else # GCC >= 4 - DARWIN_SDK_CFLAGS = -isysroot $(MACOS_SDK_DIR) + DARWIN_SDK_CFLAGS = -isysroot $(MACOS_SDK_DIR) -arch i386 -arch ppc ifneq (4.0.0,$(GCC_VERSION_FULL)) # gcc > 4.0.0 passes -syslibroot to ld based on -isysroot. # Don't add -isysroot to DARWIN_SDK_LDFLAGS, because the programs @@ -83,7 +83,7 @@ else # gcc 4.0.0 doesn't pass -syslibroot to ld, it needs to be # explicit. - DARWIN_SDK_LDFLAGS = -Wl,-syslibroot,$(MACOS_SDK_DIR) + DARWIN_SDK_LDFLAGS = -Wl,-syslibroot,$(MACOS_SDK_DIR) -arch i386 -arch ppc DARWIN_SDK_SHLIBFLAGS = $(DARWIN_SDK_LDFLAGS) endif endif @@ -111,7 +111,7 @@ DSO_CFLAGS = -fPIC # May override this with -bundle to create a loadable module. -DSO_LDOPTS = -dynamiclib -compatibility_version 1 -current_version 1 -install_name @executable_path/$(notdir $@) -headerpad_max_install_names +DSO_LDOPTS = -dynamiclib -compatibility_version 1 -current_version 1 -install_name @executable_path/$(notdir $@) -headerpad_max_install_names -L@@PREFIX@@/lib/nspr -L@@PREFIX@@/lib/ MKSHLIB = $(CC) $(DSO_LDOPTS) $(DARWIN_SDK_SHLIBFLAGS) DLL_SUFFIX = dylib libreswan-3.32/macports/nss/files/patch-UNIX.mk.diff000066400000000000000000000007471365625662500223340ustar00rootroot00000000000000--- mozilla/security/coreconf/UNIX.mk.orig 2008-10-03 12:12:41.000000000 -0700 +++ mozilla/security/coreconf/UNIX.mk 2009-05-10 21:11:17.000000000 -0700 @@ -48,7 +48,7 @@ else OPTIMIZER += -g USERNAME := $(shell whoami) USERNAME := $(subst -,_,$(USERNAME)) - DEFINES += -DDEBUG -UNDEBUG -DDEBUG_$(USERNAME) + DEFINES += -DDEBUG -UNDEBUG -DDEBUG_$(USERNAME) -I@@PREFIX@@/include/nspr -L@@PREFIX@@/lib/nspr -I@@PREFIX@@/include -L@@PREFIX@@/lib endif ifdef BUILD_TREE libreswan-3.32/mk/000077500000000000000000000000001365625662500140565ustar00rootroot00000000000000libreswan-3.32/mk/README.md000066400000000000000000000126121365625662500153370ustar00rootroot00000000000000 Overview ======== The kvm-* make targets provide an alternative build and test framework. Just keep in mind that some is experimental. Installing KVM test domains --------------------------- Preparation (FC23) ------------------ sudo dnf install virt-manager virt-install python3-pexpect sudo usermod -a -G qemu cagney sudo chmod g+w /var/lib/libvirt/qemu/ Makefile.inc.local configuration ................................ (from "make kvm-config-variables") Before creating the test domains, the following make variables need to be defined (these make variables are only used when creating the domains): KVM_POOL: directory containing the test domain disks KVM_SOURCEDIR: directory to mount on /source within the domains KVM_TESTINGDIR: directory to mount on /testing within the domains For a traditional test domain configuration, with a single libreswan source directory mounted under /source, add the following to Makefile.inc.local: KVM_POOL = /home/build/pool KVM_SOURCEDIR = $(abs_top_srcdir) KVM_TESTINGDIR = $(abs_top_srcdir)/testing Alternatively, if you have multiple libreswan source directories and would like their common parent directory to be mounted under /source then add the following to Makefile.inc.local: KVM_POOL = $(abspath $(abs_top_srcdir)/../pool) KVM_SOURCEDIR = $(abspath $(abs_top_srcdir)/..) KVM_TESTINGDIR = $(abs_top_srcdir)/testing Installing and uninstalling test networks and test domains .......................................................... Once the make variables are set, the test networks and test domains can be installed with: make install-kvm-networks make install-kvm-domains If not already present, a base domain, from which the test domains are be cloned, is also be created. Conversely the test domains and networks can be completely uninstalled using: make uninstall-kvm-networks make uninstall-kvm-domains The base domain, from which the test domains are cloned, is not uninstalled. To also remove the base domain use: make uninstall-kvm-domains uninstall-kvm-base-domain This is both to prevent accidental domain updates; and avoid the unreliable and slow process of creating the base .qcow2 file. Logging into a test domain -------------------------- To get a shell prompt on a domain, such as east, use either: ./testing/utils/kvmsh.py east or: make kvmsh-east to exit enter the escape character '^]'. Installing libreswan -------------------- To install libreswan on all test domains (except nic), use: make kvm-install and to install libreswan on just one domain, for instance "east", use: make kvm-install-east To clean the kvm build directory use: make kvm-clean (This replaces something like "make check UPDATEONLY=1") Creating test keys ------------------ The tests requires custom keys. They are generated using a test domain, with: make kvm-keys Please note that they are not currently automatically re-generated (this is because of concern that critical keys may be accidentally deleted). To manually re-build the keys use: make clean-kvm-keys kvm-keys (This replaces directly running scripts in testing/x509 directory) Running the tests ----------------- There are two targets available for running the testsuite. The difference is in how previously run tests are handled. - run tests unconditionally: make kvm-test This target is best suited for the iterative build test cycle where a limited set of tests need to be run. For instance, to update the domain east with the latest changes and then run a subset of tests, use: make kvm-install-east kvm-test KVM_TESTS=testing/pluto/ikev2-algo-* - to run tests that haven't passed (i.e, un-tested and failed tests): make kvm-check This target is best suited for running or updating the entire testsuite. For instance, because some tests fail intermittently, a second kvm-check will likely improve the test results. (This replaces and better focuses the functionality found in "make check" and the script testing/utils/swantest.) (If you forget to run kvm-keys it doesn't matter, both kvm-test and kvm-check depend on the kvm-keys target.) Examining test results ---------------------- The script kvmresults can be used to examine the results from the current test run: ./testing/utils/kvmresults.py testing/pluto (even while the testsuite is still running) and compare the results with an earlier baseline vis: ./testing/utils/kvmresults.py testing/pluto ../saved-testing-pluto-directory mk/manpages.mk -------------- The make variable MANPAGES contains the list of man pages to be built and installed. For instance, assuming there is foo.3.xml source, then: MANPAGES += foo.3 will build/install foo.3 into $(MANDIR.3) (man3). If the .xml source is being generated (into $(builddir)/foo.3.xml) then $(builddir) should be specified vis: MANPAGES += $(builddir)/foo.3 If the .xml file specifies multiple entries then they will all be installed (see packaging/utils/refname.sh). TODO: Invert this rule, instead of specifying the output, specify the source files: MANPAGES += foo.3.xml mk/find.sh ---------- This script outputs a list of everything that might be make file related. For instance: ./mk/find.sh | xargs grep PROGRAMS mk/tests.sh ----------- This script goes through a whole heap of make commands, such as sub-directory clean/build, that should work. libreswan-3.32/mk/TODO.md000066400000000000000000000060311365625662500151450ustar00rootroot00000000000000 Where is this code going? ------------------------- The basic idea is to reduce things to the point that a Makefile looks something like: PROGRAMS=foo include ../../mk/program.mk ifdef EXTRA_STUFF LIBS+=-lextra endif Either subdirs.mk, program.mk, or library.mk gets included. This means: - the srcdir/objdir shuffle has to go - all the flags get set up - all the auto-dependency stuff is delt with - makefiles use a small well-defined set of flags And a small set of well defined targets work: - make (default to programs or all?) - make install - make clean - make distclean? TODO: a.k.a. what needs fixing ------------------------------ The following are quirks in the build system: - merge config.mk and userlandcflags.mk; two types of flags are needed: USERLAND_CFLAGS += -D ... - defined for all builds _LDFLAGS = ... - added as needed to an application's LDFLAGS - build/install test applications at build/install time stops tests needing to get to /source (the build tree) during testing - when fips, generate fipshmac checksums during install - stop program.mk switching to $(builddir) - recursive make targets should stick to $(srcdir); currently some switch back to $(builddir) at the last moment (see above) - remove the redundant prefix in -I${SRCDIR}${LIBRESWANSRCDIR} - rename modobj to something more specific - like builddir - unit tests under testing/ could do with their own unit-test.mk file; grep for UNITTEST in testing's Makefile-s - be more consistent with "=", ":=" and "?="; there's a meta issue here - configuration files are included early leading to "?=" rather than late - run "make --warn-undefined-variables" - do not generate the makefiles under $(OBJDIR); need to stop things switching to that directory first - eliminate Makefile.ver: this is really messy as scripts do all sorts of weird and wonderful stuff with it. - make building individual programs configurable - add a minimal config for small systems The following are quirks inside of pluto: - log, as a separate line, the file's basename, line and function The following are quirks with /testing: - don't have /etc/ipsec.conf refer to /testing - don't have tests run scripts in /testing - run ../../../testing/guestbin/swan-init (a relative path within the current test tree), and not /testing/guestbin/swan-init - kvmrunner should write a marker at the start/end of each script and when things are done - clean up "abort" magic - kvmrunner should always format its output as /OUTPUT The following are quirks in the test infrastructure: - move guest scripts from testing/pluto/bin to testing/guestbin; and KVM scripts to testing/libvirt - have *init.sh et.al. scripts always succeed. This means that commands like ping that are expected to fail (demonstrating no conectivity) will need a "!" prefix so the failure is success. - simplify fips check - swan-transmogrify runs chcon -R testing/pluto, it should only run that over the current test directory - simplify and speed up ping deadness check libreswan-3.32/mk/builddir.mk000066400000000000000000000002111365625662500161770ustar00rootroot00000000000000# Targets needing the builddir should add: # # | $(builddir) # # as a soft/order-only dependency. $(builddir): mkdir -p $(builddir) libreswan-3.32/mk/config.mk000066400000000000000000000422651365625662500156650ustar00rootroot00000000000000# Libreswan pathnames and other master configuration # # Copyright (C) 2001, 2002 Henry Spencer. # Copyright (C) 2003-2006 Xelerance Corporation # Copyright (C) 2012 Paul Wouters # Copyright (C) 2015,2017-2018 Andrew Cagney # Copyright (C) 2015-2019 Tuomo Soini # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. ifndef config.mk config.mk = true # A Makefile wanting to test variables defined below has two choides: # # - include config.mk early and use GNU-make's 'ifeq' statement # # - include config.mk late, and use $(call if-enabled,VARIABLE,result) # if-enabled = $(if $(filter true, $($(strip $(1)))),$(2),$(3)) # # # TODO: Some creative ifeq ($(BUILDENV,xxx) to automatically determine # where we are building on and disable things (eg KLIPS on OSX) # Doc: man make # Doc: http://www.gnu.org/software/make/manual/make.html # Include any local Makefile.inc.local; local.mk is a wrapper # that deals with multiple include issues. include ${LIBRESWANSRCDIR}/mk/local.mk # Pull in the target/build/host description and get a definition of # OBJDIR, BUILDENV, et.al. include ${LIBRESWANSRCDIR}/mk/objdir.mk # Pull in OSDEP specific makefile stub. # # Don't try to deal with OS family variants (debian vs fedora vs ...) # needing different build options (e.g., auditing, fips). Instead, # put all that code in the OS family ${BUILDENV}.mk file - the logic # ends up being a horrible mess so that hopefully keeps it a little # contained. # # Using the "build" machine to select "target" configuration options # is, to say the least, a little weird. It's "historic". include ${LIBRESWANSRCDIR}/mk/defaults/${BUILDENV}.mk # Variables in this file with names starting with INC_ are not for use # by Makefiles that include this file; they are subject to change without warning. # # "Final" and "finally" refer to where the files will end up on the # running IPsec system, as opposed to where they get installed by our # Makefiles. (The two are different for cross-compiles and the like, # where our Makefiles are not the end of the installation process.) # Paths with FINAL in their names are the only ones that the installed # software itself depends on. (Very few things should know about the # FINAL paths; think twice and consult Tuomo before making something new # depend on them.) All other paths are install targets. # See also DESTDIR, below. # # Note: Variables here are for Makefiles and build system only. # IPSEC_ prefixed variables are to be used in source code ### install pathnames # DESTDIR can be used to supply a prefix to all install targets. # (Note that "final" pathnames, signifying where files will eventually # reside rather than where install puts them, are exempt from this.) # The prefixing is done in this file, so as to have central control over # it; DESTDIR itself should never appear in any other Makefile. DESTDIR?= # "local" part of tree, used in building other pathnames INC_USRLOCAL?=/usr/local # PUBDIR is where the "ipsec" command goes; beware, many things define PATH # settings which are assumed to include PUBDIR (or at least, to include *some* # copy of the "ipsec" command). PUBDIR?=$(DESTDIR)$(INC_USRLOCAL)/sbin # BINDIR is where sub-commands get put, FINALBINDIR is where the "ipsec" # command will look for them when it is run. Also called LIBEXECDIR. FINALLIBEXECDIR?=$(INC_USRLOCAL)/libexec/ipsec LIBEXECDIR?=$(DESTDIR)$(FINALLIBEXECDIR) FINALBINDIR?=$(FINALLIBEXECDIR) BINDIR?=$(LIBEXECDIR) # SBINDIR is where the user interface command goes. FINALSBINDIR?=$(INC_USRLOCAL)/sbin SBINDIR?=$(DESTDIR)$(FINALSBINDIR) # where the appropriate manpage tree is located # location within INC_USRLOCAL INC_MANDIR?=man FINALMANDIR=$(INC_USRLOCAL)/$(INC_MANDIR) # the full pathname MANTREE?=$(DESTDIR)$(FINALMANDIR) # where configuration files go FINALSYSCONFDIR?=/etc # run dir - defaults to /run/pluto # Some older systems might need to set this to /var/run/pluto # DEFAULT_RUNDIR=/run/pluto FINALRUNDIR?=/run/pluto RUNDIR?=$(DESTDIR)$(FINALRUNDIR) # final configuration file FINALCONFFILE?=$(FINALSYSCONFDIR)/ipsec.conf CONFFILE?=$(DESTDIR)$(FINALCONFFILE) FINALCONFDIR?=$(FINALSYSCONFDIR) CONFDIR?=$(DESTDIR)$(FINALCONFDIR) SYSCONFDIR?=$(DESTDIR)$(FINALSYSCONFDIR) FINALCONFDDIR?=$(FINALCONFDIR)/ipsec.d CONFDDIR?=$(DESTDIR)$(FINALCONFDDIR) FINALNSSDIR?=/etc/ipsec.d # Debian uses /var/lib/ipsec #FINALNSSDIR?=/var/lib/ipsec NSSDIR?=$(DESTDIR)$(FINALNSSDIR) # where dynamic PPKs go, for now FINALPPKDIR?=$(FINALCONFDDIR) PPKDIR?=$(DESTDIR)$(FINALPPKDIR) # sample configuration files go into INC_DOCDIR?=share/doc FINALEXAMPLECONFDIR?=$(INC_USRLOCAL)/$(INC_DOCDIR)/libreswan EXAMPLECONFDIR?=$(DESTDIR)$(FINALEXAMPLECONFDIR) FINALDOCDIR?=$(INC_USRLOCAL)/$(INC_DOCDIR)/libreswan DOCDIR?=$(DESTDIR)$(FINALDOCDIR) # where per-conn pluto logs go FINALVARDIR?=/var VARDIR?=$(DESTDIR)$(FINALVARDIR) FINALLOGDIR?=$(FINALVARDIR)/log LOGDIR?=$(DESTDIR)$(FINALLOGDIR) # Note: this variable gets passed in, as in "make INITSYSTEM=systemd" INITSYSTEM ?= $(shell $(top_srcdir)/packaging/utils/lswan_detect.sh init) DOCKER_PLUTONOFORK?=--nofork # An attempt is made to automatically figure out where boot/shutdown scripts # will finally go: the first directory in INC_RCDIRS that exists gets them. # If none of those exists (or INC_RCDIRS is empty), INC_RCDEFAULT gets them. # With a non-null DESTDIR, INC_RCDEFAULT will be used unless one of the # INC_RCDIRS directories has been pre-created under DESTDIR. INC_RCDIRS?=/etc/rc.d/init.d /etc/rc.d /etc/init.d /sbin/init.d INC_RCDEFAULT?=/etc/rc.d/init.d # RCDIR is where boot/shutdown scripts go; FINALRCDIR is where they think # will finally be (so utils/Makefile can create a symlink in BINDIR to the # place where the boot/shutdown script will finally be, rather than the # place where it is installed). FINALRCDIR?=$(shell for d in $(INC_RCDIRS) ; \ do if test -d $(DESTDIR)/$$d ; \ then echo $$d ; exit 0 ; \ fi ; done ; echo $(INC_RCDEFAULT) ) RCDIR?=$(DESTDIR)$(FINALRCDIR) # PYTHON_BINARY is used for python scripts shebang PYTHON_BINARY ?= /usr/bin/python3 # SHELL_BINARY is used for sh scripts shebang SHELL_BINARY ?= /bin/sh ### kernel pathnames # Kernel location: where patches are inserted, where kernel builds are done. # this is a hack using the wildcard to look for existence of a file/dir ifneq ($(wildcard /usr/src/linux-2.6),) KERNELSRC?=/usr/src/linux-2.6 else ifneq ($(wildcard /usr/src/linux-2.4),) KERNELSRC?=/usr/src/linux-2.4 else KERNELSRC?=/lib/modules/$(shell uname -r)/build endif endif # where kernel configuration outputs are located KCFILE=$(KERNELSRC)/.config ACFILE=$(KERNELSRC)/include/linux/autoconf.h VERFILE=$(KERNELSRC)/include/linux/version.h # where KLIPS kernel module is install OSMOD_DESTDIR?=net/ipsec # What command to use to load the modules. openwrt does not have modprobe # Using -b enables blacklisting - this is needed for some known bad # versions of crypto acceleration modules. MODPROBEBIN?=modprobe MODPROBEARGS?=--quiet --use-blacklist ### misc installation stuff # what program to use when installing things INSTALL?=install # flags to the install program, for programs, manpages, and config # files -b has install make backups (n.b., unlinks original), --suffix # controls how backup names are composed. Since install procedures # will never overwrite an existing config file they omit -b. # While --suffix is linux centric, there isn't a portable alternative. INSTBINFLAGS ?= -b --suffix=.old # The -m flag is more portable than --mode=. INSTMANFLAGS ?= -m 0644 INSTCONFFLAGS ?= -m 0644 # flags for bison, overrode in packages/default/foo BISONOSFLAGS?= # XXX: Don't add NSSFLAGS to USERLAND_CFLAGS for now. It needs to go # after -I$(top_srcdir)/include and fixing that is an entirely # separate cleanup. NSSFLAGS ?= $(NSS_CFLAGS) # We don't want to link against every library pkg-config --libs nss # returns NSS_LDFLAGS ?= -lnss3 NSS_SMIME_LDFLAGS ?= -lsmime3 NSS_UTIL_LDFLAGS ?= -lnssutil3 NSPR_LDFLAGS ?= -lnspr4 # Use local copy of nss function CERT_CompareAVA # See https://bugzilla.mozilla.org/show_bug.cgi?id=1336487 # This work-around is needed with nss versions before 3.30. USE_NSS_AVA_COPY?=false ifeq ($(USE_NSS_AVA_COPY),true) NSSFLAGS += -DNSS_REQ_AVA_COPY endif # Use nss IPsec profile for X509 validation. This is less restrictive # on EKU's. Enable when using NSS >= 3.41 (or RHEL-7.6 / RHEL-8.0) # See https://bugzilla.mozilla.org/show_bug.cgi?id=1252891 USE_NSS_IPSEC_PROFILE?=true ifeq ($(USE_NSS_IPSEC_PROFILE),true) NSSFLAGS += -DNSS_IPSEC_PROFILE endif # Use a local copy of xfrm.h. This can be needed on older systems # that do not ship linux/xfrm.h, or when the shipped version is too # old. Since we ship some not-yet merged ipsec-next offload code, this # is currently true for basically all distro's USE_XFRM_HEADER_COPY?=true XFRM_LIFETIME_DEFAULT?=30 USE_XFRM_INTERFACE_IFLA_HEADER?=false # Some systems have a bogus combination of glibc and kernel-headers which # causes a conflict in the IPv6 defines. Try enabling this option as a workaround # when you see errors related to 'struct in6_addr' USE_GLIBC_KERN_FLIP_HEADERS?=false # When compiling on a system where unbound is missing the required unbound-event.h # include file, enable this workaround option that will enable an included copy of # this file as shipped with libreswan. The copy is taken from unbound 1.6.0. USE_UNBOUND_EVENT_H_COPY?=false # Install the portexclude service for policies/portexcludes.conf policies # Disabled per default for now because it requires python[23] USE_PORTEXCLUDES?=false # The default DNSSEC root key location is set to /var/lib/unbound/root.key # DEFAULT_DNSSEC_ROOTKEY_FILE=/var/lib/unbound/root.key # To build with clang, use: scan-build make programs #GCC=clang GCC?=gcc MAKE?=make # Enable AddressSanitizer - see https://libreswan.org/wiki/Compiling_with_AddressSanitizer # requires clang or gcc >= 4.8 and libasan. Do not combine with Electric Fence and do not # run pluto with --leak-detective # ASAN=-fsanitize=address ASAN?= ### misc configuration, included here in hopes that other files will not ### have to be changed for common customizations. KLIPSCOMPILE?=-O2 -DCONFIG_KLIPS_ALG -DDISABLE_UDP_CHECKSUM # You can also run this before starting libreswan on glibc systems: #export MALLOC_PERTURB_=$(($RANDOM % 255 + 1)) PORTINCLUDE?= # command used to link/copy KLIPS into kernel source tree # There are good reasons why this is "ln -s"; only people like distribution # builders should ever change it. KLIPSLINK?=ln -s -f # extra options for use in kernel build KERNMAKEOPTS?= # kernel Makefile targets to be done before build # Can be overridden if you are *sure* your kernel doesn't need them. (2.2.xx # and later reportedly do not.) KERNDEP?=dep KERNCLEAN?=clean # kernel make name: zImage for 2.0.xx, bzImage for 2.2.xx and later, and # boot on non-x86s (what ever happened to standards?) INC_B?=$(shell test -d $(DIRIN22) && echo b) KERNEL?=$(shell if expr " `uname -m`" : ' i.86' >/dev/null ; \ then echo $(INC_B)zImage ; \ else echo boot ; \ fi) # look for POD2MAN command POD2MAN?=$(shell which pod2man | grep / | head -n1) ## build environment variations # # USE_ variables determine if features are compiled into Libreswan. # these let you turn on/off specific features # HAVE_ variables let you tell Libreswan what system related libraries # you may or maynot have # Enable support for DNSSEC. This requires the unbound and ldns libraries. USE_DNSSEC?=true # For systemd start/stop notifications and watchdog feature # We only enable this by default if used INITSYSTEM is systemd ifeq ($(INITSYSTEM),systemd) USE_SYSTEMD_WATCHDOG?=true SD_RESTART_TYPE?="on-failure" SD_PLUTO_OPTIONS?="--leak-detective" else USE_SYSTEMD_WATCHDOG?=false endif # Figure out ipsec.service file Type= option ifeq ($(USE_SYSTEMD_WATCHDOG),true) SD_TYPE=notify SD_WATCHDOGSEC?=200 else SD_WATCHDOGSEC?=0 SD_TYPE=simple endif # Do we want all the configuration files like ipsec.conf and ipsec.secrets # and any certificates to be in a single directory defined by # FINALCONFDDIR? USE_SINGLE_CONF_DIR?=false # Build support for KEY RR # this will become false in the future, as all OE sites transition to # using IPSECKEY instead of KEY records. See references to 'Flag Day' # Except this to change in Q1 2011 USE_KEYRR?=true # Build support for integrity check for libreswan on startup USE_FIPSCHECK?=false FIPSPRODUCTCHECK?=/etc/system-fips # Enable Labeled IPsec Functionality (requires SElinux) USE_LABELED_IPSEC?=false # Enable seccomp support (whitelist allows syscalls) USE_SECCOMP?=false # Support for Network Manager USE_NM?=true # Include LDAP support (currently used for fetching CRLs) USE_LDAP?=false # Include libcurl support (currently used for fetching CRLs) USE_LIBCURL?=true # Do we want to limit the number of ipsec connections artificially USE_IPSEC_CONNECTION_LIMIT?=false IPSEC_CONNECTION_LIMIT?=250 # For Angstrom linux with broken popen() set to true. See bug #1067 HAVE_BROKEN_POPEN?=false NONINTCONFIG=oldconfig -include ${LIBRESWANSRCDIR}/Makefile.ver # make sure we only run this once per build, its too expensive to run # every time Makefile.inc is included ifndef IPSECVERSION ifeq ($(VERSION_ADD_GIT_DIRTY),true) ADD_GIT_DIRTY = --add-git-diry endif IPSECVERSION:=$(shell ${LIBRESWANSRCDIR}/packaging/utils/setlibreswanversion ${ADD_GIT_DIRTY} ${IPSECBASEVERSION} ${LIBRESWANSRCDIR}) export IPSECVERSION endif ifndef IPSECVIDVERSION # VID is a somewhat shortened version, eg "3.5" or "3.5-xxx" IPSECVIDVERSION:=$(shell echo ${IPSECVERSION} | sed 's/^\([^-]*\)-\([^-]*\)-.*/\1-\2/') export IPSECVIDVERSION endif OBJDIRTOP?=${LIBRESWANSRCDIR}/${OBJDIR} # # Paranoia says to export these just to sure: export OBJDIR export OBJDIRTOP ### paths within the source tree KLIPSSRCDIR=${LIBRESWANSRCDIR}/linux/net/ipsec LIBSWANDIR=${LIBRESWANSRCDIR}/lib/libswan # Need to specify absolute paths as 'make' (checks dependencies) and # 'ld' (does the link) are run from different directories. LIBRESWANLIB=$(abs_top_builddir)/lib/libswan/libswan.a LSWTOOLLIB=$(abs_top_builddir)/lib/liblswtool/liblswtool.a BSDPFKEYLIB=$(abs_top_builddir)/lib/libbsdpfkey/libbsdpfkey.a # XXX: $(LSWTOOLLIB) has circular references to $(LIBRESWANLIB). LSWTOOLLIBS=$(LSWTOOLLIB) $(LIBRESWANLIB) LIBDESSRCDIR=${LIBRESWANSRCDIR}/linux/crypto/ciphers/des WHACKLIB=${OBJDIRTOP}/lib/libwhack/libwhack.a IPSECCONFLIB=${OBJDIRTOP}/lib/libipsecconf/libipsecconf.a # export everything so that scripts can use them. export LIBSWANDIR LIBRESWANSRCDIR ARCH PORTINCLUDE export LIBRESWANLIB LSWTOOLLIB export LIBDESSRCDIR export LIBTWOFISH LIBSERPENT export WHACKLIB IPSECCONFLIB #KERNELBUILDMFLAGS=--debug=biv V=1 IPSEC_SECRETS_FILE ?= $(FINALCONFDIR)/ipsec.secrets # how to do variable substitution in sed-transformed files TRANSFORM_VARIABLES = sed -e "s:@IPSECVERSION@:$(IPSECVERSION):g" \ -e "/@${OSDEP}_START@/,/@${OSDEP}_END@/d" \ -e "s:@EXAMPLECONFDIR@:$(EXAMPLECONFDIR):g" \ -e "s:@FINALBINDIR@:$(FINALBINDIR):g" \ -e "s:@FINALCONFDDIR@:$(FINALCONFDDIR):g" \ -e "s:@FINALCONFDIR@:$(FINALCONFDIR):g" \ -e "s:@FINALCONFFILE@:$(FINALCONFFILE):g" \ -e "s:@FINALDOCDIR@:$(FINALDOCDIR):g" \ -e "s:@FINALEXAMPLECONFDIR@:$(FINALEXAMPLECONFDIR):g" \ -e "s:@FINALLIBEXECDIR@:$(FINALLIBEXECDIR):g" \ -e "s:@FINALRCDIR@:$(FINALRCDIR):g" \ -e "s:@FINALSBINDIR@:$(FINALSBINDIR):g" \ -e "s:@FINALSYSCONFDIR@:$(FINALSYSCONFDIR):g" \ -e "s:@FINALVARDIR@:$(FINALVARDIR):g" \ -e "s:@IPSEC_CONF@:$(FINALCONFFILE):g" \ -e "s:@IPSEC_CONFDDIR@:$(FINALCONFDDIR):g" \ -e "s:@IPSEC_RUNDIR@:$(FINALRUNDIR):g" \ -e "s:@IPSEC_NSSDIR@:$(FINALNSSDIR):g" \ -e "s:@IPSEC_PPKDIR@:$(FINALPPKDIR):g" \ -e "s:@IPSEC_DIR@:$(FINALBINDIR):g" \ -e "s:@IPSEC_EXECDIR@:$(FINALLIBEXECDIR):g" \ -e "s:@IPSEC_VARDIR@:$(FINALVARDIR):g" \ -e "s:@IPSEC_SBINDIR@:$(FINALSBINDIR):g" \ -e "s:@IPSEC_SECRETS_FILE@:$(IPSEC_SECRETS_FILE):g" \ -e "s:@MODPROBEBIN@:$(MODPROBEBIN):g" \ -e "s:@MODPROBEARGS@:$(MODPROBEARGS):g" \ -e "s:@PYTHON_BINARY@:$(PYTHON_BINARY):g" \ -e "s:@SHELL_BINARY@:$(SHELL_BINARY):g" \ -e "s:@USE_DEFAULT_CONNS@:$(USE_DEFAULT_CONNS):g" \ -e "s:@SD_TYPE@:$(SD_TYPE):g" \ -e "s:@SD_RESTART_TYPE@:$(SD_RESTART_TYPE):g" \ -e "s:@SD_PLUTO_OPTIONS@:$(SD_PLUTO_OPTIONS):g" \ -e "s:@SD_WATCHDOGSEC@:$(SD_WATCHDOGSEC):g" \ -e "s:@INITSYSTEM@:$(INITSYSTEM):g" \ -e "s:@DOCKER_PLUTONOFORK@:$(DOCKER_PLUTONOFORK):g" \ # For KVM testing setup #POOL?=${LIBRESWANSRCDIR}/pool POOL?=/vol/pool # support types are fedora and ubuntu OSTYPE?=fedora OSMEDIA?=http://download.fedoraproject.org/pub/fedora/linux/releases/28/Server/x86_64/os/ # Ubuntu media # OSTYPE?=ubuntu # OSMEDIA?=http://ftp.ubuntu.com/ubuntu/dists/precise/main/installer-amd64/ # Now that all the configuration variables are defined, use them to # define USERLAND_CFLAGS and USERLAND_LDFLAGS include ${LIBRESWANSRCDIR}/mk/userland.mk endif libreswan-3.32/mk/configs.sh000077500000000000000000000012211365625662500160410ustar00rootroot00000000000000#!/bin/sh # Try building a clearly arbitrary set of configurations set -e makes() { gmake clean && nice nice gmake base "$@" } # defaults for this system makes # flip flop algorithms makes USE_SERPENT=true USE_TWOFISH=true USE_3DES=true USE_DH2=true USE_DH22=true USE_DH23=true USE_DH24=true USE_DH31=true USE_CAMELLIA=true USE_CAST=true USE_RIPEMD=true makes USE_SERPENT=false USE_TWOFISH=false USE_3DES=false USE_DH2=false USE_DH22=false USE_DH23=false USE_DH24=false USE_DH31=false USE_CAMELLIA=false USE_CAST=false USE_RIPEMD=false # flip flop other common flags makes USE_DNSSEC=true USE_SECCOMP=true makes USE_DNSSEC=false USE_SECCOMP=false libreswan-3.32/mk/defaults/000077500000000000000000000000001365625662500156655ustar00rootroot00000000000000libreswan-3.32/mk/defaults/linux.mk000066400000000000000000000034711365625662500173620ustar00rootroot00000000000000USE_NETKEY = true USERLAND_CFLAGS += -DTimeZoneOffset=timezone # This normally comes in via bind9/config.h # Fixes a warning in lib/libisc/random.c:44 USERLAND_CFLAGS += -DHAVE_SYS_TYPES_H=1 USERLAND_CFLAGS += -DHAVE_UNISTD_H=1 # Not all environments set this? happened on a arm_tools cross compile USERLAND_CFLAGS += -Dlinux # udpfromto socket option for Linux USERLAND_CFLAGS += -DHAVE_UDPFROMTO=1 USERLAND_CFLAGS += -DHAVE_IP_PKTINFO=1 KLIPSSRC=${LIBRESWANSRCDIR}/linux/net/ipsec MODULE_DEF_INCLUDE=${LIBRESWANSRCDIR}/packaging/linus/config-all.h MODULE_DEFCONFIG?=${KLIPSSRC}/defconfig MOD24BUILDDIR?=${LIBRESWANSRCDIR}/modobj24 MODBUILDDIR?=${LIBRESWANSRCDIR}/modobj MODULE_FLAGS:=KLIPSMODULE=true -f ${MODULE_DEFCONFIG} PORTDEFINE=-DSCANDIR_HAS_CONST BISONOSFLAGS=-g --verbose # Detect linux variants and releases. # So that the sub-shell is invoked only once, ":=" is used. This in # turn means 'ifndef' is needed as := is unconditional. ifndef LINUX_VARIANT ifneq ($(wildcard /etc/os-release),) LINUX_VARIANT:=$(shell sed -n -e 's/^ID=//p' /etc/os-release) export LINUX_VARIANT endif endif #(info LINUX_VARIANT=$(LINUX_VARIANT)) ifndef LINUX_VARIANT_VERSION ifneq ($(wildcard /etc/os-release),) LINUX_VARIANT_VERSION:=$(shell sed -n -e 's/^VERSION_ID=//p' /etc/os-release) export LINUX_VARIANT_VERSION endif endif #(info LINUX_VARIANT_VERSION=$(LINUX_VARIANT_VERSION)) ifeq ($(LINUX_VARIANT),fedora) USE_FIPSCHECK?=true USE_LINUX_AUDIT?=true USE_SECCOMP?=true USE_LABELED_IPSEC?=true # Assume that fedora 22 (used by test VMs) needs the hack ifeq ($(LINUX_VARIANT_VERSION),22) USE_GLIBC_KERN_FLIP_HEADERS=true endif endif #(info USE_GLIBC_KERN_FLIP_HEADERS=$(USE_GLIBC_KERN_FLIP_HEADERS)) ifndef NSS_CFLAGS NSS_CFLAGS := $(shell pkg-config --cflags nss) export NSS_CFLAGS endif libreswan-3.32/mk/defaults/netbsd.mk000066400000000000000000000014571365625662500175040ustar00rootroot00000000000000USERLAND_CFLAGS += -I/usr/pkg/include USERLAND_CFLAGS += -DHAS_SUN_LEN USERLAND_CFLAGS += -DNEED_SIN_LEN USERLAND_CFLAGS += -DHAVE_NETINET6_IN_H USERLAND_CFLAGS += -DHAVE_UDPFROMTO USERLAND_CFLAGS += -DHAVE_IP_RECVDSTADDR USERLAND_CFLAGS += -Ds6_addr16=__u6_addr.__u6_addr16 USERLAND_CFLAGS += -Ds6_addr32=__u6_addr.__u6_addr32 USE_BSDKAME=true USE_LIBCAP_NG=false LDFLAGS += -lipsec -L/usr/pkg/lib -Wl,-rpath,/usr/pkg/lib NSS_CFLAGS = -I/usr/pkg/include/nspr -I/usr/pkg/include/nss/nss NSS_LDFLAGS = -L/usr/pkg/lib/nss -Wl,-rpath,/usr/pkg/lib/nss -lnss3 -lfreebl3 -lssl3 NSPR_LDFLAGS = -L/usr/pkg/lib/nspr -Wl,-rpath,/usr/pkg/lib/nspr -lnspr4 CRYPT_LDFLAGS = INITSYSTEM= FINAL_PAM_D_DIR=/usr/local/etc/pam.d FINALSYSCONFDIR=/usr/local/etc FINALRUNDIR=/usr/local/run/pluto FINALNSSDIR=/usr/local/etc/ipsec.d libreswan-3.32/mk/depend.mk000066400000000000000000000041651365625662500156540ustar00rootroot00000000000000# Libreswan Makefile dependencies and rules # # Copyright (C) 2015 Andrew Cagney # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # list of files requiring dependency generation ifndef OBJS $(error define OBJS) endif # cflags for this variant of the compile command ifndef CFLAGS $(error define CFLAGS) endif # In addition to compiling the .c file to .o, generate a dependency # file. Force all output to the build directory. $(basename # $(notdir)) is an approximation of UNIX basename. # # -MP: add a fake header target for when a header is deleted # -MMD: only list user header files # -MT: the target (otherwise $(builddir)/$(notdir $@) is used # -MF: where to write the dependency .c.o: $(CC) $(CFLAGS) \ -MF $(builddir)/$(basename $(notdir $@)).d \ -MP -MMD -MT $@ \ -o $(builddir)/$(notdir $@) \ -c $(abspath $<) # Assume each source file has its own generated dependency file that # is updated whenever the corresponding output is updated. Given # these files, create an include file that includes them. mk.depend.file := $(lastword $(MAKEFILE_LIST)) mk.depend.dependencies.file := $(builddir)/Makefile.depend.mk $(mk.depend.dependencies.file): $(srcdir)/Makefile $(mk.depend.file) | $(builddir) set -e ; \ for f in $(OBJS) ; do \ case $$f in \ *.c ) echo "-include \$$(builddir)/$$(basename $$f .c).d # $$f" ;; \ *.o ) echo "-include \$$(builddir)/$$(basename $$f .o).d # $$f" ;; \ * ) echo "# $$f ignored by Makefile.dep" ;; \ esac ; \ done > $@.tmp mv $@.tmp $@ clean: mk.depend.clean .PHONY: mk.depend.clean mk.depend.clean: rm -f $(mk.depend.dependencies.file) rm -f $(builddir)/*.d -include $(mk.depend.dependencies.file) libreswan-3.32/mk/dirs.mk000066400000000000000000000137731365625662500153630ustar00rootroot00000000000000# Define autoconf style directory variables, for Libreswan. # # Copyright (C) 2015 Andrew Cagney # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # From a source directory Makefile use: # # ifndef top_srcdir # include ../../mk/dirs.mk # endif # # (Since the Makefile is included from the build (OBJDIR) directory # where the relative paths are different and dirs.mk has already been # included, a guard is needed.) # # From a generated build (OBJDIR) directory Makefile use: # # include ../../../mk/dirs.mk # # To help testing there is the target ".dirs.mk". This will print out # all defined variables. For instance: # # ( cd . && make -f mk/dirs.mk .dirs.mk ) # ( cd programs && make -f ../mk/dirs.mk .dirs.mk ) # ( cd programs/pluto && make -f ../../mk/dirs.mk .dirs.mk ) # # ( cd OBJ.* && make -f ../mk/dirs.mk .dirs.mk ) # ( cd OBJ.*/programs && make -f ../../mk/dirs.mk .dirs.mk ) # ( cd OBJ.*/programs/pluto && make -f ../../../mk/dirs.mk .dirs.mk ) # # Check for double include of mk/dirs.mk. This, as they say, will # never happen. # # Unfortunately, given the presence of this test, you can guess that # it has. Some broken Makefile code was effectively executing: # # cd $(abs_top_builddir) && OBJDIR=$(abs_top_builddir) make ... # # (i.e., a totally bogus OBJDIR was being pushed into the child make's # environment). Either by luck, or poor design, the generated OBJDIR # Makefiles would then "fix" OBJDIR forcing it to a correct value. # Remove the "fix" and chaos ensues. ifeq ($(.dirs.mk),) .dirs.mk := $(MAKEFILE_LIST) else $(warning mk/dirs.mk included twice) $(warning first include MAKEFILE_LIST: $(.dirs.mk)) $(warning second include MAKEFILE_LIST: $(MAKEFILE_LIST)) $(warning dirs.mk.in.srcdir: $(dirs.mk.in.srcdir)) $(warning srcdir: $(srcdir)) $(warning builddir: $(builddir)) $(warning OBJDIR: $(OBJDIR)) $(warning cwd: $(abspath .)) $(error this will never happen ...) endif # Given a path to a higher directory (e.g., ../..) convert it to the # path from that directory down. For instance: given "../.." ($(1) # variable) and the current directory "/libreswan/OBJ.linux/foo/bar", # "/foo/bar" is returned; given "." ($(1) variable) and the current # directory "/libreswan", "" is returned. dirs.mk.down.path.from = $(subst $(abspath $(1)),,$(abspath .)) # Determine top_srcdir # # The last item in the GNU make variable MAKEFILE_LIST is the relative # path to the most recent included file (i.e., dirs.mk). Since the # location of dirs.mk is known relative to top_srcdir, top_srcdir can # be determined. These variables are "simply expanded" so that they # capture the current value. For more information see MAKEFILE_LIST # and "simply expanded variables" in "info make". # # Extract the relative path to this file dirs.mk.file := $(lastword $(MAKEFILE_LIST)) # Convert the relative path to this file into a relative path to this # file's directory. Since $(dir) appends a trailing / (such as "mk/" # or "../mk/") that needs to be stripped. dirs.mk.dir := $(patsubst %/,%,$(dir $(dirs.mk.file))) # Finally, drop the mk/ sub-directory. Again, since $(dir) appends a # trailing / (such as "./" or "../") that needs to be stripped. top_srcdir := $(patsubst %/,%,$(dir $(dirs.mk.dir))) # Pull in sufficient stuff to get a definition of OBJDIR. It might be # set by local includes so pull that in first. include $(top_srcdir)/mk/local.mk include $(top_srcdir)/mk/objdir.mk # Is this being included from the source directory (i.e., $(OBJDIR) # isn't found in the path)? ifeq ($(findstring /$(OBJDIR)/,$(abspath .)/),) dirs.mk.included.from.srcdir := true else dirs.mk.included.from.srcdir := false endif ifeq ($(dirs.mk.included.from.srcdir),true) # In the source tree ... srcdir := . ifeq ($(patsubst /%,/,$(OBJDIR)),/) # absolute top_builddir := $(OBJDIR) else ifeq ($(top_srcdir),.) # avoid ./OBJDIR top_builddir := $(OBJDIR) else top_builddir := $(top_srcdir)/$(OBJDIR) endif builddir := $(top_builddir)$(call dirs.mk.down.path.from,$(top_srcdir)) else # In the build (OBJDIR) tree ... builddir := . ifeq ($(top_srcdir),..) # avoid "" top_builddir := . else top_builddir := $(patsubst ../%,%,$(top_srcdir)) endif srcdir := $(top_srcdir)$(call dirs.mk.down.path.from,$(top_builddir)) endif # Absolute versions abs_srcdir := $(abspath $(srcdir)) abs_top_srcdir := $(abspath $(top_srcdir)) abs_builddir := $(abspath $(builddir)) abs_top_builddir := $(abspath $(top_builddir)) # Always include the other directory in the search path. # # XXX: The VPATH+=$(srcdir) will hopefully go away and this will # become unconditional. ifeq ($(srcdir),.) VPATH += $(builddir) endif ifeq ($(builddir),.) VPATH += $(srcdir) endif # For compatibility with existing include files: LIBRESWANSRCDIR?=$(abs_top_srcdir) SRCDIR?=$(abs_srcdir)/ OBJDIRTOP?=$(abs_top_builddir) # Dot targets are never the default. .PHONY: .dirs.mk .dirs.mk: @echo "" @echo For debugging: @echo "" @echo dirs.mk.file=$(dirs.mk.file) @echo dirs.mk.dir=$(dirs.mk.dir) @echo top_srcdir=$(top_srcdir) @echo dirs.mk.included.from.srcdir="$(dirs.mk.included.from.srcdir)" @echo "" @echo Relative paths: @echo "" @echo srcdir=$(srcdir) @echo top_srcdir=$(top_srcdir) @echo builddir=$(builddir) @echo top_builddir=$(top_builddir) @echo "" @echo Absolute paths: @echo "" @echo abs_srcdir=$(abs_srcdir) @echo abs_top_srcdir=$(abs_top_srcdir) @echo abs_builddir=$(abs_builddir) @echo abs_top_builddir=$(abs_top_builddir) @echo "" @echo Backward compatibility: @echo "" @echo SRCDIR=$(SRCDIR) @echo OBJDIRTOP=$(OBJDIRTOP) @echo LIBRESWANSRCDIR=$(LIBRESWANSRCDIR) libreswan-3.32/mk/docker-targets.mk000066400000000000000000000227711365625662500173360ustar00rootroot00000000000000# docker make/start/stop targets, for Libreswan testing # # Copyright (C) 2016-2019 Antony Antony # # make DISTRO=fedora DISTRO_REL=28 docker-image # # make DISTRO=fedora DISTRO_REL=28 DI_T=swanbase docker-image # # The variables above could be set from command line. # DOCKER_CMD ?= sudo podman D ?= testing/docker DI_T ?= swanbase #docker image tag W1 = $(firstword $(subst -, ,$1)) W2 = $(or $(word 2, $(subst -, ,$1)), $(value 2)) W3 = $(or $(word 3, $(subst -, ,$1)), $(value 2)) W4 = $(or $(word 4, $(subst -, ,$1)), $(value 2)) FIRST_TARGET ?=$@ # keep track of original target DISTRO ?= fedora # default distro DISTRO_REL ?= 30 # default release D_USE_UNBOUND_EVENT_H_COPY ?= true D_USE_DNSSEC ?= false D_USE_NSS_IPSEC_PROFILE ?= flase D_USE_GLIBC_KERN_FLIP_HEADERS ?= true D_USE_NSS_AVA_COPY ?= true DOCKERFILE ?= $(D)/dockerfile SUDO_CMD ?= sudo PKG_CMD = $(shell test -f /usr/bin/dnf && echo /usr/bin/dnf || (test -f /usr/bin/yum && echo /usr/bin/yum || echo "no yum or dnf found" && exit 1)) PKG_BUILDDEP = $(shell test -f /usr/bin/dnf && echo "/usr/bin/dnf builddep" || echo /usr/bin/yum-builddep ) REPO_POWERTOOLS = $(shell grep -qE '^ID="centos"' /etc/os-release && echo "--enablerepo=PowerTools" || echo "" ) PKG_INSTALL = $(SUDO_CMD) $(PKG_CMD) $(REPO_POWERTOOLS) install -y PKG_UPGRADE = $(SUDO_CMD) $(PKG_CMD) $(REPO_POWERTOOLS) upgrade -y PKG_DEBUGINFO_INSTALL = $(SUDO_CMD) $(PKG_CMD) $(REPO_POWERTOOLS) debuginfo-install -y PKG_DEBUGINFO_UPGRADE = $(SUDO_CMD) $(PKG_CMD) $(REPO_POWERTOOLS) upgrade --enablerepo=*-debuginfo "*-debuginfo" -y # end of configurable variables DI = $(DISTRO)-$(DISTRO_REL) DOCKERFILE_PKG = $(D)/Dockerfile-$(DISTRO)-min-packages TWEAKS= LOCAL_MAKE_FLAGS= MAKE_BASE = base MAKE_INSTLL_BASE = install-base ifdef TRAVIS_ENABLED BRANCH = $(shell test -d .git -o -f .git && (git rev-parse --abbrev-ref HEAD || echo '')) TRAVIS_BANCH ?= $(call W1, $(BRANCH),'') endif ifeq ($(TRAVIS_BANCH), travis) DISTRO = $(call W2, $(BRANCH),fedora) DISTRO_REL = $(call W3, $(BRANCH),27) endif # # Distribution specific tweaks # ifeq ($(DISTRO), ubuntu) MAKE_BASE = deb MAKE_INSTLL_BASE = deb-install DOCKERFILE_PKG=$(D)/Dockerfile-debian-min-packages endif ifeq ($(DISTRO), debian) DOCKERFILE_PKG=$(D)/Dockerfile-debian-min-packages TWEAKS = dockerfile-debian-cmd MAKE_BASE = deb MAKE_INSTLL_BASE = deb-install endif ifeq ($(DISTRO), centos) MAKE_BASE = base MAKE_INSTLL_BASE = install-base ifeq ($(DISTRO_REL), 6) DOCKERFILE_PKG = $(D)/Dockerfile-$(DISTRO)6-min-packages LOCAL_MAKE_FLAGS += USE_DNSSEC=$(D_USE_DNSSEC) LOCAL_MAKE_FLAGS += USE_NSS_IPSEC_PROFILE=$(D_USE_NSS_IPSEC_PROFILE) LOCAL_MAKE_FLAGS += USE_XFRM_INTERFACE_IFLA_HEADER=true endif ifeq ($(DISTRO_REL), 7) LOCAL_MAKE_FLAGS += USE_XFRM_INTERFACE_IFLA_HEADER=true endif ifeq ($(DISTRO_REL), 8) # CentOS 8 Fedora 28 based so it should be able to handle basic build DOCKERFILE_PKG = $(D)/Dockerfile-fedora-min-packages endif endif ifeq ($(DISTRO), fedora) ifeq ($(DISTRO_REL), rawhide) TWEAKS += rawhide-remove-dnf-update endif MAKE_BASE = base MAKE_INSTLL_BASE = install-base LOCAL_MAKE_FLAGS = endif .PHONY: rawhide-remove-dnf-update rawhide-remove-dnf-update: # on rawhide RUN dnf -y update could be a bad idea $(shell sed -i '/RUN dnf -y update/d' testing/docker/dockerfile) .PHONY: dockerfile-remove-libreswan-spec dockerfile-remove-libreswan-spec: $(shell sed -i '/libreswan\.spec/d' testing/docker/dockerfile) .PHONY: dockerfile-debian-cmd dockerfile-debian-cmd: $(shell sed -i 's#CMD.*#CMD ["/lib/systemd/systemd"]#' testing/docker/dockerfile) .PHONY: dockerfile-ubuntu-cmd dockerfile-ubuntu-cmd: $(shell sed -i 's#CMD.*#CMD ["/sbin/init"]#' testing/docker/dockerfile) .PHONY: use_unbound_event_h_copy use_unbound_event_h_copy: # # end of Distribution tweaks # .PHONY: install-testing-rpm-dep install-testing-rpm-dep: install-rpm-build-dep install-rpm-run-dep $(if $(KVM_INSTALL_PACKAGES), $(PKG_INSTALL) $(KVM_INSTALL_PACKAGES)) $(if $(KVM_UPGRADE_PACKAGES), $(PKG_UPGRADE) $(KVM_UPGRADE_PACKAGES)) $(if $(KVM_DEBUGINFO_INSTALL), $(if $(KVM_DEBUGINFO), \ $(PKG_DEBUGINFO_INSTALL) $(KVM_DEBUGINFO))) $(if $(KVM_DEBUGINFO_INSTALL), $(if $(KVM_DEBUGINFO), \ $(PKG_DEBUGINFO_UPGRADE))) .PHONY: install-rpm-run-dep RUN_RPMS = $$($(PKG_CMD) deplist --arch $$(uname -m) --forcearch $$(uname -m) libreswan | awk '/provider:/ {print $$2}' | sort -u) install-rpm-run-dep: $(PKG_INSTALL) --skip-broken $(RUN_RPMS) .PHONY: install-rpm-build-dep install-rpm-build-dep: $(SUDO_CMD) $(PKG_CMD) groupinstall $(POWER_TOOLS) -y 'Development Tools' $(SUDO_CMD) $(PKG_BUILDDEP) $(REPO_POWERTOOLS) -y libreswan .PHONY: install-deb-dep # RUN_DEBS_OLD ?= $$(grep -qE 'jessie|xenial' /etc/os-release && echo "host iptables") # hard codde these two packages it fail on xenial and old ones. # on buster host is virtual package RUN_DEBS_OLD ?= bind9-host iptables RUN_DEBS ?= $$(test -f /usr/bin/apt-cache && apt-cache depends libreswan | awk '/Depends:/{print $$2}' | grep -v "<" | sort -u) install-deb-dep: apt-get update # development dependencies apt-get install -y equivs devscripts dh-systemd # libreswan specific development dependencies # apt-get -y --no-install-recommends build-dep libreswan cp -r packaging/debian/control libreswan-control mk-build-deps --install --tool "apt-get -o Dpkg::Options::="--force-confold" -o Debug::pkgProblemResolver=yes -y --no-install-recommends" libreswan-control # install libreswan runtime dependencies apt-get install -y $(RUN_DEBS) $(RUN_DEBS_OLD) # give another kick apt-get --fix-broken install -y .PHONY: travis-docker-image travis-docker-image: $(MAKE) DISTRO=$(DISTRO) DISTRO_REL=$(DISTRO_REL) docker-image .PHONY: travis-docker-base travis-docker-base: $(MAKE) $(MAKE_BASE) define debian_exp_repo if [ $(1) == "experimental" ] ; then \ echo 'RUN echo "deb http://deb.debian.org/debian experimental main" >> /etc/apt/sources.list.d/experimental.list' >> $(2);\ fi endef .PHONY: dockerfile dockerfile: $(DOCKERFILE_PKG) echo "FROM $(DISTRO):$(DISTRO_REL)" > $(DOCKERFILE) echo "ENV container docker" >> $(DOCKERFILE) echo 'MAINTAINER "Antony Antony" ' >> $(DOCKERFILE) @$(call debian_exp_repo,$(DISTRO_REL),$(DOCKERFILE)) cat $(DOCKERFILE_PKG) >> $(DOCKERFILE) .PHONY: travis-ubuntu-xenial travis-ubuntu-xenial: ubuntu-xenial-packages $(DOCKER_CMD) run -h $(DI_T) --privileged --name $(DI_T) \ -v $(PWD):/home/build/libreswan \ -v /sys/fs/cgroup:/sys/fs/cgroup:ro -d ubuntu-xenial-packages $(DOCKER_CMD) ps -a .PHONY: docker-build docker-build: dockerfile # --volume is only in podman # $(DOCKER_CMD) build -t $(DI_T) --volume /home/build/libreswan:/home/build/libreswan -f $(DOCKERFILE) . $(DOCKER_CMD) build -t $(DI_T) -f $(DOCKERFILE) . .PHONY: docker-ssh-image docker-ssh-image: DOCKERFILE_SSH = $(D)/Dockerfile-swan-ssh docker-ssh-image: $(DOCKERFILE_SSH) cat $(DOCKERFILE_SSH) >> $(DOCKERFILE) .PHONY: docker-min-image docker-min-image: dockerfile $(TWEAKS) docker-build echo "done docker image tag $(DI_T) from $(DISTRO)-$(DISTRO_REL)" .PHONY: docker-image docker-image: dockerfile $(TWEAKS) docker-ssh-image docker-build echo "done docker image tag $(DI_T) from $(DISTRO)-$(DISTRO_REL) with ssh" # NEW tragets to get docker handling 201906 .PHONY: docker-instance-name docker-instance-name: echo $(DI_T) .PHONY: travis-docker-make travis-docker-make: $(DOCKER_CMD) exec -ti $(DI_T) /bin/bash -c "cd /home/build/libreswan && $(MAKE) DISTRO=$(DISTRO) DISTRO_REL=$(DISTRO_REL) make-base" .PHONY: travis-docker-make-install travis-docker-make-install: $(DOCKER_CMD) exec -ti $(DI_T) /bin/bash -c "cd /home/build/libreswan && $(MAKE) DISTRO=$(DISTRO) DISTRO_REL=$(DISTRO_REL) make-install" .PHONY: docker-exec docker-exec: $(DOCKER_CMD) exec -ti $(DI_T) /bin/bash -c "cd /home/build/libreswan && $(MAKE) $(1)" .PHONY: docker-stop docker-stop: $(DOCKER_CMD) stop $(DI_T) && $(DOCKER_CMD) rm $(DI_T) || echo "nothing to stop $(DI_T)" .PHONY: docker-shell docker-shell: $(DOCKER_CMD) exec -ti $(DI_T) /bin/bash .PHONY: make-base make-base: $(LOCAL_MAKE_FLAGS) $(MAKE) $(MAKE_BASE) .PHONY: make-install make-install: $(LOCAL_MAKE_FLAGS) $(MAKE) $(MAKE_INSTLL_BASE) .PHONY: deb-install deb-install: install-deb-dep dpkg -i ../*.deb || apt-get --fix-broken install -y .PHONY: docker-make-install docker-make-install: docker-stop $(DOCKER_CMD) run --privileged --net=none --name $(DI_T) \ -v $(PWD):/home/build/libreswan \ -v /sys/fs/cgroup:/sys/fs/cgroup:ro \ -ti $(DI_T) /bin/bash -c "cd /home/build/libreswan && $(MAKE) $(MAKE_INSTLL_BASE)" .PHONY: docker-make-base docker-make-base: docker-stop $(DOCKER_CMD) run --privileged --net=none --name $(DI_T) \ -v $(PWD):/home/build/libreswan \ -v /sys/fs/cgroup:/sys/fs/cgroup:ro \ -ti $(DI_T) /bin/bash -c "cd /home/build/libreswan && \ $(LOCAL_MAKE_FLAGS) $(MAKE) $(MAKE_BASE)" .PHONY: travis-docker-start travis-docker-start: $(DOCKER_CMD) run -h $(DI_T) --privileged --name $(DI_T) \ -v $(PWD):/home/build/libreswan/ \ -v /sys/fs/cgroup:/sys/fs/cgroup:ro -d $(DI_T) .PHONY: nsrunclean nsrunclean: sudo rm -fr $(abs_top_srcdir)/testing/pluto/*/OUTPUT $(abs_top_srcdir)/testing/pluto/*/NS NSURNDIRS = $(shell mount | grep "^nsfs" | cut -d " " -f 3) .PHONY: nsrun nsrun: nsrunclean $(if $(NSURNDIRS), $(shell sudo umount $(NSURNDIRS)), $(echo "no nsfs")) $(abs_top_srcdir)/testing/utils/nsrun --ns --shutdown --log-level debug --verbos 2 --testrun .PHONY: nsinstall nsinstall: $(MAKE) clean $(MAKE) INITSYSTEM=docker DOCKER_PLUTONOFORK= base sudo $(MAKE) INITSYSTEM=docker DOCKER_PLUTONOFORK= install-base libreswan-3.32/mk/find.sh000077500000000000000000000020121365625662500153300ustar00rootroot00000000000000#!/bin/sh -e # Find anything remotely related to makefiles; used to find makefile # variable references. Assume this is being run as .../mk/find.sh. look() { d=$(dirname $(dirname $0)) find $d/* \ -false \ -o -type d -name '__pycache__' -prune \ \ -o -type f -name '*~' -prune \ -o -type f -name '*.orig' -prune \ -o -type f -name '*.rej' -prune \ -o -type f -name '.*' -prune \ \ -o -type d -path '$d/BACKUP' -prune \ -o -type d -path "$d/OBJ.*" -prune \ -o -type d -path "$d/linux" -prune \ -o -type d -path "$d/testing/pluto/*/*" -prune \ \ -o -type f -path "$d/testing/utils/*" -print \ -o -type f -path "$d/testing/guestbin/*" -print \ \ -o -type f -path "$d/packaging/*" -print \ \ -o -type f -name 'Makefile*' -print \ -o -type f -name '*.mk' -print \ -o -type f -name '*.py' -print \ -o -type f -name '*.sh' -print \ -o -type f -name '*.awk' -print \ -o -type f -name '*.[chly]' -print } if test $# -gt 0 ; then look | xargs grep -n "$@" else look fi libreswan-3.32/mk/kernel.mk000066400000000000000000000417751365625662500157050ustar00rootroot00000000000000# Libreswan master makefile # # Copyright (C) 1998-2002 Henry Spencer. # Copyright (C) 2003-2004 Xelerance Corporation # Copyright (C) 2017, Richard Guy Briggs # Copyright (C) 2015-2018 Andrew Cagney # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # PATCHES=linux # where KLIPS goes in the kernel # note, some of the patches know the last part of this path KERNELKLIPS=$(KERNELSRC)/net/ipsec KERNELCRYPTODES=$(KERNELSRC)/crypto/ciphers/des KERNELLIBFREESWAN=$(KERNELSRC)/lib/libfreeswan KERNELLIBZLIB=$(KERNELSRC)/lib/zlib KERNELINCLUDE=$(KERNELSRC)/include MAKEUTILS=packaging/utils ERRCHECK=${MAKEUTILS}/errcheck KVUTIL=${MAKEUTILS}/kernelversion KVSHORTUTIL=${MAKEUTILS}/kernelversion-short # kernel details # what variant of our patches should we use, and where is it KERNELREL=$(shell ${KVSHORTUTIL} ${KERNELSRC}/Makefile) # directories visited by all recursion # declaration for make's benefit .PHONY: def insert kpatch patches _patches _patches2.4 \ klipsdefaults programs man install \ precheck verset confcheck kernel \ module module24 module26 kinstall minstall minstall24 minstall26 \ moduleclean mod24clean module24clean mod26clean module26clean \ backup unpatch uninstall \ check \ kpatch: unapplypatch applypatch klipsdefaults npatch: unapplynpatch applynpatch sarefpatch: unapplysarefpatch applysarefpatch unapplypatch: @echo "info: making unapplypatch in `pwd` and KERNELSRC=\"${KERNELSRC}\";" -@if [ -f ${KERNELSRC}/libreswan.patch ]; then \ echo Undoing previous patches; \ cat ${KERNELSRC}/libreswan.patch | (cd ${KERNELSRC} && patch -p1 -R --force -E -z .preipsec --reverse --ignore-whitespace ); \ fi applypatch: @echo "info: Now performing forward patches in `pwd`"; ${MAKE} kernelpatch${KERNELREL} | tee ${KERNELSRC}/libreswan.patch | (cd ${KERNELSRC} && patch -p1 -b -z .preipsec --forward --ignore-whitespace ) unapplynpatch: @echo "info: making unapplynpatch (note the second N) in `pwd`"; -@if [ -f ${KERNELSRC}/natt.patch ]; then \ echo Undoing previous NAT patches; \ cat ${KERNELSRC}/natt.patch | (cd ${KERNELSRC} && patch -p1 -R --force -E -z .preipsec --reverse --ignore-whitespace ); \ fi applynpatch: @echo "info: Now performing forward NAT patches in `pwd`"; ${MAKE} nattpatch${KERNELREL} | tee ${KERNELSRC}/natt.patch | (cd ${KERNELSRC} && patch -p1 -b -z .preipsec --forward --ignore-whitespace ) unapplysarefpatch: @echo "info: making unapplysarefpatch in `pwd`"; -@if [ -f ${KERNELSRC}/saref.patch ]; then \ echo Undoing previous saref patches; \ cat ${KERNELSRC}/saref.patch | (cd ${KERNELSRC} && patch -p1 -R --force -E -z .preng --reverse --ignore-whitespace ); \ fi applysarefpatch: @echo "info: Now performing SAref patches in `pwd`"; ${MAKE} sarefpatch${KERNELREL} | tee ${KERNELSRC}/klipsng.patch | (cd ${KERNELSRC} && patch -p1 -b -z .preng --forward --ignore-whitespace ) # patch kernel PATCHER=packaging/utils/patcher _patches: echo "===============" >>out.kpatch echo "`date` `cd $(KERNELSRC) ; pwd`" >>out.kpatch $(MAKE) __patches$(KERNELREL) >>out.kpatch # Linux-2.4.0 version __patches2.4: @$(PATCHER) -v -c $(KERNELSRC) Documentation/Configure.help \ 'CONFIG_KLIPS' $(PATCHES)/Documentation/Configure.help.fs2_2.patch @$(PATCHER) -v $(KERNELSRC) net/Config.in \ 'CONFIG_KLIPS' $(PATCHES)/net/Config.in.fs2_4.patch @$(PATCHER) -v $(KERNELSRC) net/Makefile \ 'CONFIG_KLIPS' $(PATCHES)/net/Makefile.fs2_4.patch @$(PATCHER) -v $(KERNELSRC) net/ipv4/af_inet.c \ 'CONFIG_KLIPS' $(PATCHES)/net/ipv4/af_inet.c.fs2_4.patch @$(PATCHER) -v $(KERNELSRC) net/ipv4/udp.c \ 'CONFIG_KLIPS' $(PATCHES)/net/ipv4/udp.c.fs2_4.patch @$(PATCHER) -v $(KERNELSRC) include/net/sock.h \ 'CONFIG_KLIPS' $(PATCHES)/include/net/sock.h.fs2_4.patch # Removed patches, will unpatch automatically. @$(PATCHER) -v $(KERNELSRC) include/linux/proc_fs.h @$(PATCHER) -v $(KERNELSRC) net/core/dev.c @$(PATCHER) -v $(KERNELSRC) net/ipv4/protocol.c @$(PATCHER) -v $(KERNELSRC) drivers/net/Space.c @$(PATCHER) -v $(KERNELSRC) include/linux/netlink.h @$(PATCHER) -v $(KERNELSRC) net/netlink/af_netlink.c @$(PATCHER) -v $(KERNELSRC) net/netlink/netlink_dev.c @$(PATCHER) -v $(KERNELSRC) drivers/isdn/isdn_net.c klipsdefaults: @KERNELDEFCONFIG=$(KERNELSRC)/arch/$(ARCH)/defconfig ; \ KERNELCONFIG=$(KCFILE) ; \ if ! grep -E -q 'CONFIG_KLIPS' $$KERNELDEFCONFIG ; \ then \ set -x ; \ cp -a $$KERNELDEFCONFIG $$KERNELDEFCONFIG.orig ; \ chmod u+w $$KERNELDEFCONFIG ; \ cat $$KERNELDEFCONFIG $(KERNELKLIPS)/defconfig \ >$$KERNELDEFCONFIG.tmp ; \ rm -f $$KERNELDEFCONFIG ; \ cp -a $$KERNELDEFCONFIG.tmp $$KERNELDEFCONFIG ; \ rm -f $$KERNELDEFCONFIG.tmp ; \ fi ; \ if ! grep -E -q 'CONFIG_KLIPS' $$KERNELCONFIG ; \ then \ set -x ; \ cp -a $$KERNELCONFIG $$KERNELCONFIG.orig ; \ chmod u+w $$KERNELCONFIG ; \ cat $$KERNELCONFIG $(KERNELKLIPS)/defconfig \ >$$KERNELCONFIG.tmp ; \ rm -f $$KERNELCONFIG ; \ cp -a $$KERNELCONFIG.tmp $$KERNELCONFIG ; \ rm -f $$KERNELCONFIG.tmp ; \ fi local-clean-base: moduleclean distclean: moduleclean module24clean module26clean clean-kvm-keys # proxies for major kernel make operations # do-everything entries KINSERT_PRE=precheck verset insert PRE=precheck verset kpatch POST=confcheck programs kernel install MPOST=confcheck programs module install # preliminaries precheck: @if test ! -d $(KERNELSRC) -a ! -L $(KERNELSRC) ; \ then \ echo '*** cannot find directory "$(KERNELSRC)"!!' ; \ echo '*** may be necessary to add symlink to kernel source' ; \ exit 1 ; \ fi @if ! cd $(KERNELSRC) ; \ then \ echo '*** cannot "cd $(KERNELSRC)"!!' ; \ echo '*** may be necessary to add symlink to kernel source' ; \ exit 1 ; \ fi @if test ! -f $(KCFILE) ; \ then \ echo '*** cannot find "$(KCFILE)"!!' ; \ echo '*** perhaps kernel has never been configured?' ; \ echo '*** please do that first; the results are necessary.' ; \ exit 1 ; \ fi @if test ! -f $(VERFILE) ; \ then \ echo '*** cannot find "$(VERFILE)"!!' ; \ echo '*** perhaps kernel has never been compiled?' ; \ echo '*** please do that first; the results are necessary.' ; \ exit 1 ; \ fi # configuring (exit statuses disregarded, something fishy here sometimes) xcf: -cd $(KERNELSRC) ; $(MAKE) $(KERNMAKEOPTS) xconfig mcf: -cd $(KERNELSRC) ; $(MAKE) $(KERNMAKEOPTS) menuconfig pcf: -cd $(KERNELSRC) ; $(MAKE) $(KERNMAKEOPTS) config ocf: -cd $(KERNELSRC) ; $(MAKE) $(KERNMAKEOPTS) oldconfig rcf: cd $(KERNELSRC) ; $(MAKE) $(KERNMAKEOPTS) ${NONINTCONFIG} /dev/null kclean: -cd $(KERNELSRC) ; $(MAKE) $(KERNMAKEOPTS) clean confcheck: @if test ! -f $(KCFILE) ; \ then echo '*** no kernel configuration file written!!' ; exit 1 ; \ fi @if ! grep -E -q '^CONFIG_KLIPS=[my]' $(KCFILE) ; \ then echo '*** IPsec not in kernel config ($(KCFILE))!!' ; exit 1 ; \ fi @if ! grep -E -q 'CONFIG_KLIPS[ ]+1' $(ACFILE) && \ ! grep -E -q 'CONFIG_KLIPS_MODULE[ ]+1' $(ACFILE) ; \ then echo '*** IPsec in kernel config ($(KCFILE)),' ; \ echo '*** but not in config header file ($(ACFILE))!!' ; \ exit 1 ; \ fi @if grep -E -q '^CONFIG_KLIPS=m' $(KCFILE) && \ ! grep -E -q '^CONFIG_MODULES=y' $(KCFILE) ; \ then echo '*** IPsec configured as module in kernel with no module support!!' ; exit 1 ; \ fi @if ! grep -E -q 'CONFIG_KLIPS_AH[ ]+1' $(ACFILE) && \ ! grep -E -q 'CONFIG_KLIPS_ESP[ ]+1' $(ACFILE) ; \ then echo '*** IPsec configuration must include AH or ESP!!' ; exit 1 ; \ fi # kernel building, with error checks kernel: rm -f out.kbuild out.kinstall # undocumented kernel folklore: clean BEFORE dep. # we run make dep separately, because there is no point in running ERRCHECK # on the make dep output. # see LKML thread "clean before or after dep?" ( cd $(KERNELSRC) ; $(MAKE) $(KERNMAKEOPTS) $(KERNCLEAN) $(KERNDEP) ) ( cd $(KERNELSRC) ; $(MAKE) $(KERNMAKEOPTS) $(KERNEL) ) 2>&1 | tee out.kbuild @if grep -E -q '^CONFIG_MODULES=y' $(KCFILE) ; \ then set -x ; \ ( cd $(KERNELSRC) ; \ $(MAKE) $(KERNMAKEOPTS) modules 2>&1 ) | tee -a out.kbuild ; \ fi ${ERRCHECK} out.kbuild # module-only building, with error checks ifneq ($(strip $(MOD24BUILDDIR)),) ${MOD24BUILDDIR}/Makefile : ${LIBRESWANSRCDIR}/packaging/makefiles/module24.make mkdir -p ${MOD24BUILDDIR} cp ${LIBRESWANSRCDIR}/packaging/makefiles/module24.make ${MOD24BUILDDIR}/Makefile module: @if [ -f ${KERNELSRC}/README.libreswan-2 ] ; then \ echo "WARNING: Kernel source ${KERNELSRC} has already been patched with libreswan-2, out of tree build might fail!"; \ fi; @if [ -f ${KERNELSRC}/README.openswan ] ; then \ echo "WARNING: Kernel source ${KERNELSRC} has already been patched with openswan, out of tree build might fail!"; \ fi; @if [ -f ${KERNELSRC}/README.openswan-2 ] ; then \ echo "WARNING: Kernel source ${KERNELSRC} has already been patched with openswan-2, out of tree build might fail!"; \ fi; @if [ -f ${KERNELSRC}/README.freeswan ] ; then \ echo "ERROR: Kernel source ${KERNELSRC} has already been patched with freeswan, out of tree build will fail!"; \ fi; @if [ -f ${KERNELSRC}/Rules.make ] ; then \ echo "Building module for a 2.4 kernel"; ${MAKE} module24 ; \ else echo "Building module for a 2.6 kernel"; ${MAKE} module26; \ fi; modclean moduleclean: @if [ -f ${KERNELSRC}/Rules.make ] ; then \ echo "Cleaning module for a 2.4 kernel"; ${MAKE} module24clean ; \ else echo "Cleaning module for a 2.6 kernel"; ${MAKE} module26clean; \ fi; module24: @if [ ! -f ${KERNELSRC}/Rules.make ] ; then \ echo "Warning: Building for a 2.4 kernel in what looks like a 2.6 tree"; \ fi ; \ ${MAKE} ${MOD24BUILDDIR}/Makefile ${MAKE} -C ${MOD24BUILDDIR} LIBRESWANSRCDIR=${LIBRESWANSRCDIR} ARCH=${ARCH} V=${V} ${MODULE_FLAGS} MODULE_DEF_INCLUDE=${MODULE_DEF_INCLUDE} TOPDIR=${KERNELSRC} -f Makefile ipsec.o @echo @echo '=========================================================' @echo @echo 'KLIPS24 module built successfully. ' @echo ipsec.o is in ${MOD24BUILDDIR} @echo @(cd ${MOD24BUILDDIR}; ls -l ipsec.o) @(cd ${MOD24BUILDDIR}; size ipsec.o) @echo @echo 'use make minstall as root to install it' @echo @echo '=========================================================' @echo mod24clean module24clean: rm -rf ${MOD24BUILDDIR} #autoodetect 2.4 and 2.6 module_install minstall install-module: @if [ -f $(KERNELSRC)/Rules.make ] ; then \ $(MAKE) minstall24 ; \ else \ $(MAKE) minstall26 ; \ fi; # Extract the value of MODLIB from the output of $(MAKE). Also hide # the sup-process $(MAKE) so that GNU Make doesn't always invoke the # target ("make -n" ignored). # # If $(MAKE) directly appears in a target (for instance in minstall26) # then GNU Make will assume that it is a recursive make invocation and # invoke the target regardless of -n. # # XXX: minstall24 should also use this. osmodlib-from-make = \ OSMODLIB=$$($(MAKE) $(1) 2>/dev/null | sed -n -e 's/^MODLIB[ :=]*\([^;]*\).*/\1/p' | head -1) ; \ test -z "$$OSMODLIB" || echo "OSMODLIB=$$OSMODLIB ($(MAKE) $(1))" # module-only install, with error checks minstall24: ( OSMODLIB=`${MAKE} -C $(KERNELSRC) -p dummy | ( sed -n -e '/^MODLIB/p' -e '/^MODLIB/q' ; cat > /dev/null ) | sed -e 's/^MODLIB[ :=]*\([^;]*\).*/\1/'` ; \ if [ -z "$$OSMODLIB" ] ; then \ OSMODLIB=`${MAKE} -C $(KERNELSRC) -n -p modules_install | ( sed -n -e '/^MODLIB/p' -e '/^MODLIB/q' ; cat > /dev/null ) | sed -e 's/^MODLIB[ :=]*\([^;]*\).*/\1/'` ; \ fi ; \ if [ -z "$$OSMODLIB" ] ; then \ echo "No known place to install module. Aborting." ; \ exit 93 ; \ fi ; \ set -x ; \ mkdir -p $$OSMODLIB/kernel/$(OSMOD_DESTDIR) ; \ cp $(MOD24BUILDDIR)/ipsec.o $$OSMODLIB/kernel/$(OSMOD_DESTDIR) ; \ if [ -f /sbin/depmod ] ; then /sbin/depmod -a ; fi; \ if [ -n "$(OSMOD_DESTDIR)" ] ; then \ mkdir -p $$OSMODLIB/kernel/$(OSMOD_DESTDIR) ; \ if [ -f $$OSMODLIB/kernel/ipsec.o -a -f $$OSMODLIB/kernel/$(OSMOD_DESTDIR)/ipsec.o ] ; then \ echo "WARNING: two ipsec.o modules found in $$OSMODLIB/kernel:" ; \ ls -l $$OSMODLIB/kernel/ipsec.o $$OSMODLIB/kernel/$(OSMOD_DESTDIR)/ipsec.o ; \ exit 1; \ fi ; \ fi ; \ set -x ) ; else module: echo 'Building in place is no longer supported. Please set MOD24BUILDDIR=' exit 1 endif # module-only building, with error checks ifneq ($(strip $(MODBUILDDIR)),) ${MODBUILDDIR}/Makefile : ${LIBRESWANSRCDIR}/packaging/makefiles/module.make mkdir -p ${MODBUILDDIR} echo ln -s -f ${LIBRESWANSRCDIR}/linux/net/ipsec/des/*.S ${MODBUILDDIR} (rm -f ${MODBUILDDIR}/des; mkdir -p ${MODBUILDDIR}/des && cd ${MODBUILDDIR}/des && ln -s -f ${LIBRESWANSRCDIR}/linux/net/ipsec/des/* . && ln -s -f Makefile.fs2_6 Makefile) (rm -f ${MODBUILDDIR}/aes; mkdir -p ${MODBUILDDIR}/aes && cd ${MODBUILDDIR}/aes && ln -s -f ${LIBRESWANSRCDIR}/linux/net/ipsec/aes/* . && ln -s -f Makefile.fs2_6 Makefile) mkdir -p ${MODBUILDDIR}/aes cp ${LIBRESWANSRCDIR}/packaging/makefiles/module.make ${MODBUILDDIR}/Makefile ln -s -f ${LIBRESWANSRCDIR}/linux/net/ipsec/match*.S ${MODBUILDDIR} module26: @if [ -f ${KERNELSRC}/Rules.make ] ; then \ echo "Warning: Building for a 2.6+ kernel in what looks like a 2.4 tree"; \ fi ; \ ${MAKE} ${MODBUILDDIR}/Makefile ${MAKE} -C ${KERNELSRC} ${KERNELBUILDMFLAGS} BUILDDIR=${MODBUILDDIR} SUBDIRS=${MODBUILDDIR} INITSYSTEM=$(INITSYSTEM) MODULE_DEF_INCLUDE=${MODULE_DEF_INCLUDE} MODULE_DEFCONFIG=${MODULE_DEFCONFIG} MODULE_EXTRA_INCLUDE=${MODULE_EXTRA_INCLUDE} ARCH=${ARCH} V=${V} modules @echo @echo '=========================================================' @echo @echo 'KLIPS module built successfully. ' @echo ipsec.ko is in ${MODBUILDDIR} @echo @(cd ${MODBUILDDIR}; ls -l ipsec.ko) @(cd ${MODBUILDDIR}; size ipsec.ko) @echo @echo 'use make minstall as root to install it' @echo @echo '=========================================================' @echo mod26clean module26clean: rm -rf ${MODBUILDDIR} # module-only install, with error checks minstall26: $(call osmodlib-from-make,-C $(KERNELSRC) -p help) ; \ if [ -z "$$OSMODLIB" ] ; then \ $(call osmodlib-from-make,-C $(KERNELSRC) -n -p modules_install) ; \ fi ; \ if [ -z "$$OSMODLIB" ] ; then \ echo "No known place to install module. Aborting." ; \ exit 93 ; \ fi ; \ set -x ; \ mkdir -p $$OSMODLIB/kernel/$(OSMOD_DESTDIR) ; \ cp $(MODBUILDDIR)/ipsec.ko $$OSMODLIB/kernel/$(OSMOD_DESTDIR) ; \ if [ -f /sbin/depmod ] ; then \ /sbin/depmod -a ; \ fi ; \ if [ -n "$(OSMOD_DESTDIR)" ] ; then \ mkdir -p $$OSMODLIB/kernel/$(OSMOD_DESTDIR) ; \ if [ -f $$OSMODLIB/kernel/ipsec.ko -a -f $$OSMODLIB/kernel/$(OSMOD_DESTDIR)/ipsec.ko ] ; then \ echo "WARNING: two ipsec.ko modules found in $$OSMODLIB/kernel:" ; \ ls -l $$OSMODLIB/kernel/ipsec.ko $$OSMODLIB/kernel/$(OSMOD_DESTDIR)/ipsec.ko ; \ exit 1; \ fi ; \ fi else module26: echo 'Building in place is no longer supported. Please set MODBUILDDIR=' exit 1 endif # kernel install, with error checks kinstall: rm -f out.kinstall >out.kinstall # undocumented kernel folklore: modules_install must precede install (observed on RHL8.0) @if grep -E -q '^CONFIG_MODULES=y' $(KCFILE) ; \ then set -x ; \ ( cd $(KERNELSRC) ; \ $(MAKE) $(KERNMAKEOPTS) modules_install 2>&1 ) | tee -a out.kinstall ; \ fi ( cd $(KERNELSRC) ; $(MAKE) $(KERNMAKEOPTS) install ) 2>&1 | tee -a out.kinstall ${ERRCHECK} out.kinstall kernelpatch3 kernelpatch3.5 kernelpatch2.6 kernelpatch: packaging/utils/kernelpatch 2.6 kernelpatch2.4: packaging/utils/kernelpatch 2.4 nattpatch: if [ -f ${KERNELSRC}/Makefile ]; then \ ${MAKE} nattpatch${KERNELREL}; \ else echo "Cannot determine Linux kernel version. Perhaps you need to set KERNELSRC? (eg: export KERNELSRC=/usr/src/linux-`uname -r`/)"; exit 1; \ fi; sarefpatch2.6: #cat patches/kernel/2.6.38/0001-SAREF-add-support-for-SA-selection-through-sendmsg.patch #packaging/utils/sarefpatch 2.6 echo "" nattpatch2.6: packaging/utils/nattpatch 2.6 nattpatch2.4: packaging/utils/nattpatch 2.4 nattupdate: (cd UMLPOOL && diff -u plain26/net/ipv4/udp.c.orig plain26/net/ipv4/udp.c; exit 0) >nat-t/net/ipv4/udp.c.os2_6.patch # take all the patches out of the kernel # (Note, a couple of files are modified by non-patch means; they are # included in "make backup".) unpatch: @echo \"make unpatch\" is obsolete. See make unapplypatch. exit 1 _unpatch: for f in `find $(KERNELSRC)/. -name '*.preipsec' -print` ; \ do \ echo "restoring $$f:" ; \ dir=`dirname $$f` ; \ core=`basename $$f .preipsec` ; \ cd $$dir ; \ mv -f $$core.preipsec $$core ; \ rm -f $$core.wipsec $$core.ipsecmd5 ; \ done libreswan-3.32/mk/kvm-targets.mk000066400000000000000000001234141365625662500166600ustar00rootroot00000000000000# KVM make targets, for Libreswan # # Copyright (C) 2015-2020 Andrew Cagney # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # Note: GNU Make doesn't let you combine pattern targets (e.x., # kvm-install-%: kvm-reboot-%) with .PHONY. Consequently, so that # patterns can be used, any targets with dependencies are not marked # as .PHONY. Sigh! # Note: for pattern targets, the value of % can be found in the make # variable '$*'. It is used to extract the DOMAIN from targets like # kvm-install-DOMAIN. # # The guest operating system. # # Pull in all its defaults so that they override everything below. KVM_GUEST_OS ?= f30 include testing/libvirt/$(KVM_GUEST_OS).mk # # where things live and what gets created # KVM_SOURCEDIR ?= $(abs_top_srcdir) KVM_TESTINGDIR ?= $(abs_top_srcdir)/testing # An educated guess ... KVM_POOLDIR ?= $(abspath $(abs_top_srcdir)/../pool) KVM_LOCALDIR ?= $(KVM_POOLDIR) # While KVM_PREFIX might be empty, KVM_PREFIXES is never empty. KVM_PREFIX ?= KVM_PREFIXES ?= $(if $(KVM_PREFIX), $(KVM_PREFIX), '') KVM_WORKERS ?= 1 #KVM_WORKERS ?= $(shell awk 'BEGIN { c=1 } /cpu cores/ { c=$$4 } END { if (c>1) print c/2; }' /proc/cpuinfo) KVM_GROUP ?= qemu #KVM_PYTHON ?= PYTHONPATH=/home/python/pexpect:/home/python/ptyprocess /home/python/v3.8/bin/python3 KVM_PIDFILE ?= kvmrunner.pid # Should these live in the OS.mk file? KVM_USE_EFENCE ?= true KVM_USE_NSS_IPSEC_PROFILE ?= true KVM_ALL_ALGS ?= false KVM_USE_SECCOMP ?= true KVM_USE_LABELED_IPSEC ?= true KVM_SD_RESTART_TYPE=no KVM_USE_KLIPS ?= true KVM_USE_FIPSCHECK ?= true KVM_KLIPS_MODULE ?= false KVM_MAKEFLAGS ?= \ USE_EFENCE=$(KVM_USE_EFENCE) \ ALL_ALGS=$(KVM_ALL_ALGS) \ USE_SECCOMP=$(KVM_USE_SECCOMP) \ USE_LABELED_IPSEC=$(KVM_USE_LABELED_IPSEC) \ USE_NSS_IPSEC_PROFILE=$(KVM_USE_NSS_IPSEC_PROFILE) \ SD_RESTART_TYPE=$(KVM_SD_RESTART_TYPE) \ USE_KLIPS=$(KVM_USE_KLIPS) \ USE_NSS_PRF=$(KVM_USE_NSS_PRF) \ USE_FIPSCHECK=$(KVM_USE_FIPSCHECK) KVM_UID ?= $(shell id -u) KVM_GID ?= $(shell id -g $(KVM_GROUP)) # targets for dumping the above .PHONY: print-kvm-prefixes print-kvm-prefixes: ; @echo "$(KVM_PREFIXES)" # # Generate local names using prefixes # strip-prefix = $(subst '',,$(subst "",,$(1))) # for-each-kvm-prefix = how? add-kvm-prefixes = \ $(foreach prefix, $(KVM_PREFIXES), \ $(addprefix $(call strip-prefix,$(prefix)),$(1))) KVM_FIRST_PREFIX = $(call strip-prefix,$(firstword $(KVM_PREFIXES))) # To avoid the problem where the host has no "default" KVM network # (there's a rumour that libreswan's main testing machine has this # problem) define a dedicated swandefault gateway. KVM_GATEWAY ?= swandefault # The alternative is qemu:///session and it doesn't require root. # However, it has never been used, and the python tools all assume # qemu://system. Finally, it comes with a warning: QEMU usermode # session is not the virt-manager default. It is likely that any # pre-existing QEMU/KVM guests will not be available. Networking # options are very limited. KVM_CONNECTION ?= qemu:///system VIRSH = sudo virsh --connect $(KVM_CONNECTION) VIRT_INSTALL ?= sudo virt-install --connect $(KVM_CONNECTION) --check path_in_use=off VIRT_CPU ?= --cpu host-passthrough VIRT_DISK_SIZE_GB ?=8 VIRT_RND ?= --rng type=random,device=/dev/random VIRT_SECURITY ?= --security type=static,model=dac,label='$(KVM_UID):$(KVM_GID)',relabel=yes VIRT_GATEWAY ?= --network=network:$(KVM_GATEWAY),model=virtio VIRT_SOURCEDIR ?= --filesystem type=mount,accessmode=squash,source=$(KVM_SOURCEDIR),target=swansource VIRT_TESTINGDIR ?= --filesystem type=mount,accessmode=squash,source=$(KVM_TESTINGDIR),target=testing VIRT_POOLDIR ?= --filesystem type=mount,accessmode=squash,source=$(KVM_POOLDIR),target=pool KVM_OS_VARIANT ?= $(KVM_GUEST_OS) VIRT_OS_VARIANT ?= --os-variant $(KVM_OS_VARIANT) VIRT_INSTALL_COMMAND = \ $(VIRT_INSTALL) \ $(VIRT_OS_VARIANT) \ --vcpus=1 \ --nographics \ $(VIRT_CPU) \ $(VIRT_GATEWAY) \ $(VIRT_RND) \ $(VIRT_SECURITY) \ $(VIRT_SOURCEDIR) \ $(VIRT_TESTINGDIR) \ $(VIRT_POOLDIR) \ --noreboot # # Hosts # KVM_BASE_HOST = swan$(KVM_GUEST_OS)base KVM_BUILD_HOST = build KVM_BUILD_HOST_CLONES = $(filter-out $(KVM_BASIC_HOSTS), $(KVM_TEST_HOSTS)) KVM_TEST_HOSTS = $(notdir $(wildcard testing/libvirt/vm/*[a-z])) KVM_BASIC_HOSTS = nic KVM_LOCAL_HOSTS = $(sort $(KVM_BUILD_HOST) $(KVM_TEST_HOSTS)) KVM_HOSTS = $(KVM_BASE_HOST) $(KVM_LOCAL_HOSTS) # # Domains # KVM_BASE_DOMAIN = $(addprefix $(KVM_FIRST_PREFIX), $(KVM_BASE_HOST)) KVM_BASE_DOMAIN_CLONES = $(KVM_BUILD_DOMAIN) $(KVM_BASIC_DOMAINS) KVM_BASIC_DOMAINS = $(call add-kvm-prefixes, $(KVM_BASIC_HOSTS)) KVM_BUILD_DOMAIN = $(addprefix $(KVM_FIRST_PREFIX), $(KVM_BUILD_HOST)) KVM_BUILD_DOMAIN_CLONES = $(call add-kvm-prefixes, $(KVM_BUILD_HOST_CLONES)) KVM_TEST_DOMAINS = $(call add-kvm-prefixes, $(KVM_TEST_HOSTS)) KVM_LOCAL_DOMAINS = $(sort $(KVM_BUILD_DOMAIN) $(KVM_TEST_DOMAINS)) KVM_DOMAINS = $(KVM_BASE_DOMAIN) $(KVM_LOCAL_DOMAINS) # # Other utilities and directories # KVMSH ?= $(KVM_PYTHON) $(abs_top_srcdir)/testing/utils/kvmsh.py KVMRUNNER ?= $(KVM_PYTHON) $(abs_top_srcdir)/testing/utils/kvmrunner.py KVMRESULTS ?= $(KVM_PYTHON) $(abs_top_srcdir)/testing/utils/kvmresults.py KVMTEST ?= $(KVM_PYTHON) $(abs_top_srcdir)/testing/utils/kvmtest.py KVM_OBJDIR = OBJ.kvm RPM_VERSION = $(shell make showrpmversion) RPM_PREFIX = libreswan-$(RPM_VERSION) RPM_BUILD_CLEAN ?= --rmsource --rmspec --clean # file to mark keys are up-to-date KVM_KEYS = testing/x509/keys/up-to-date # # For when HOST!=DOMAIN, generate maps from the host rule to the # domain rule. # define kvm-HOST-DOMAIN #(info kvm-HOST-DOMAIN prefix=$(1) host=$(2) suffix=$(3)) .PHONY: $(1)$(2)$(3) $(1)$(2)$(3): $(1)$$(addprefix $$(KVM_FIRST_PREFIX),$(2))$(3) endef # # Check that things are correctly configured for creating the KVM # domains # # Use := so that the make variable is evaluated only once. Result is # either empty, or a make target that will print the error. # KVM_ENTROPY_FILE ?= /proc/sys/kernel/random/entropy_avail KVM_ENTROPY_OK := $(shell test ! -r $(KVM_ENTROPY_FILE) || test $(shell cat $(KVM_ENTROPY_FILE)) -gt 100 || echo broken-kvm-entropy) .PHONY: broken-kvm-entropy broken-kvm-entropy: : : According to $(KVM_ENTROPY_FILE) your computer does not seem to have much entropy. : : Check the wiki for hints on how to fix this. : false KVM_QEMUDIR ?= /var/lib/libvirt/qemu KVM_QEMUDIR_OK := $(shell test -w $(KVM_QEMUDIR) || echo broken-kvm-qemu-directory) .PHONY: broken-kvm-qemu-directory broken-kvm-qemu-directory: : : The directory: : : $(KVM_QEMUDIR) : : is not writeable. This will break virsh which is : used to manipulate the domains. : false # # Don't create $(KVM_POOLDIR) - let the user do that as it lives # outside of the current directory tree. # # However, do create $(KVM_LOCALDIR) (but not using -p) if it is # unique and doesn't exist - convention seems to be to point it at # /tmp/pool which needs to be re-created every time the host is # rebooted. # # Defining a macro and the printing it using $(info) is easier than # a bunch of echo's or :s. # define kvm-pooldir-info The directory: "$(KVM_POOLDIR)" specified by KVM_POOLDIR and used to store the base domain disk and other files, does not exist. Either create the directory or adjust its location by setting KVM_POOLDIR in the file: Makefile.inc.local endef $(KVM_POOLDIR): $(info $(kvm-pooldir-info)) false ifneq ($(KVM_POOLDIR),$(KVM_LOCALDIR)) $(KVM_LOCALDIR): : not -p mkdir $(KVM_LOCALDIR) endif # # [re]run the testsuite. # # If the testsuite is being run a second time (for instance, # re-started or re-run) what should happen: run all tests regardless; # just run tests that have never been started; run tests that haven't # yet passed? Since each alternative has merit, let the user decide # by providing both kvm-test and kvm-retest. KVM_TESTS ?= testing/pluto # Given a make command like: # # make kvm-test "KVM_TESTS=$(./testing/utils/kvmresults.py --quick testing/pluto | awk '/output-different/ { print $1 }' )" # # then KVM_TESTS ends up containing new lines, strip them out. STRIPPED_KVM_TESTS = $(strip $(KVM_TESTS)) .PHONY: web-pages-disabled: @echo @echo Web-pages disabled. @echo @echo To enable web pages create the directory: $(LSW_WEBDIR) @echo To convert this result into a web page run: make web-page @echo # Run the testsuite. # # - depends on kvm-keys and not $(KVM_KEYS) so that the check that the # keys are up-to-date is run. # # - need local domains shutdown as, otherwise, test domains can refuse # to boot because the domain they were cloned from is still running. define kvm-test .PHONY: $(1) $(1): $$(KVM_QMUDIR_OK) \ $$(KVM_ENTROPY_OK) \ kvm-keys-ok \ kvm-shutdown-local-domains @$(MAKE) $$(if $$(WEB_ENABLED), web-test-prep, -s web-pages-disabled) : kvm-test target=$(1) param=$(2) : KVM_TESTS=$(STRIPPED_KVM_TESTS) $$(KVMRUNNER) \ $(if $(KVM_PIDFILE), --pid-file "$(KVM_PIDFILE)") \ $$(foreach prefix,$$(KVM_PREFIXES), --prefix $$(prefix)) \ $$(if $$(KVM_WORKERS), --workers $$(KVM_WORKERS)) \ $$(if $$(WEB_ENABLED), \ --publish-hash $$(WEB_HASH) \ --publish-results $$(WEB_RESULTSDIR) \ --publish-status $$(WEB_SUMMARYDIR)/status.json) \ $(2) $$(KVM_TEST_FLAGS) $$(STRIPPED_KVM_TESTS) @$(MAKE) $$(if $$(WEB_ENABLED), web-test-post, -s web-pages-disabled) endef # XXX: $(file < "x") tries to open '"x"' !!! .PHONY: kvm-kill kvm-kill: test -s "$(KVM_PIDFILE)" && kill $(file < $(KVM_PIDFILE)) .PHONY: kvm-status kvm-status: test -s "$(KVM_PIDFILE)" && ps $(file < $(KVM_PIDFILE)) # "test" and "check" just runs the entire testsuite. $(eval $(call kvm-test,kvm-check kvm-test, --test-status "good")) # "retest" and "recheck" re-run the testsuite updating things that # didn't pass. $(eval $(call kvm-test,kvm-retest kvm-recheck, --test-status "good" --skip passed)) # clean up; accept pretty much everything KVM_TEST_CLEAN_TARGETS = \ clean-kvm-check kvm-clean-check kvm-check-clean \ clean-kvm-test kvm-clean-test kvm-test-clean \ clean-kvm-tests kvm-clean-tests kvm-tests-clean .PHONY: $(KVM_TEST_CLEAN_TARGETS) $(KVM_TEST_CLEAN_TARGETS): find $(STRIPPED_KVM_TESTS) -name OUTPUT -type d -prune -print0 | xargs -0 -r rm -r .PHONY: kvm-results kvm-results: $(KVMRESULTS) $(KVM_TEST_FLAGS) $(STRIPPED_KVM_TESTS) $(if $(KVM_BASELINE),--baseline $(KVM_BASELINE)) .PHONY: kvm-diffs kvm-diffs: $(KVMRESULTS) $(KVM_TEST_FLAGS) $(STRIPPED_KVM_TESTS) $(if $(KVM_BASELINE),--baseline $(KVM_BASELINE)) --print diffs KVM_MODIFIED_TESTS = git status testing/pluto | awk '/(modified|deleted):/ { print $$2 }' | cut -d/ -f1-3 | sort -u .PHONY: kvm-modified kvm-modified: @$(KVM_MODIFIED_TESTS) .PHONY: kvm-modified-test kvm-modified-check kvm-modified-test kvm-modified-check: $(MAKE) kvm-test KVM_TESTS="$$($(KVM_MODIFIED_TESTS))" .PHONY: kvm-modified-retest kvm-modified-recheck kvm-modified-retest kvm-modified-recheck: $(MAKE) kvm-retest KVM_TESTS="$$($(KVM_MODIFIED_TESTS))" .PHONY: kvm-modified-results kvm-modified-results: $(KVMRESULTS) $$($(KVM_MODIFIED_TESTS)) .PHONY: kvm-modified-diffs kvm-modified-diffs: $(KVMRESULTS) --print diffs $$($(KVM_MODIFIED_TESTS)) # # Build the KVM keys using the KVM. # # XXX: # # Can't yet force the domain's creation. This target may have been # invoked by testing/pluto/Makefile which relies on old domain # configurations. # # Make certain everything is shutdown. Can't depend on the phony # target kvm-shutdown-local-domains as that triggers an unconditional # rebuild. Instead invoke that rule inline. # # "dist_certs.py" can't create a directory called "certs/" on a 9p # mounted file system (OSError: [Errno 13] Permission denied: # 'certs/'). In fact, "mkdir xxx/ certs/" half fails (only xxx/ is # created) so it might even be a problem with the mkdir call! Get # around this by first creating the certs in /tmp on the guest, and # then copying back using a tar file. # # "dist_certs.py" always writes its certificates to $(dirname $0). # Get around this by running a copy of dist_certs.py placed in /tmp. KVM_KEYS_EXPIRATION_DAY = 7 KVM_KEYS_EXPIRED = find testing/x509/*/ -type f -mtime +$(KVM_KEYS_EXPIRATION_DAY) -ls .PHONY: kvm-keys kvm-keys: $(KVM_KEYS) $(KVM_KEYS): $(top_srcdir)/testing/x509/dist_certs.py \ $(top_srcdir)/testing/x509/openssl.cnf \ $(top_srcdir)/testing/x509/strongswan-ec-gen.sh \ $(top_srcdir)/testing/baseconfigs/all/etc/bind/generate-dnssec.sh \ $(KVM_QEMUDIR_OK) \ $(KVM_ENTROPY_OK) : invoke phony target to shut things down and delete old keys $(MAKE) kvm-shutdown-local-domains $(MAKE) $(KVM_LOCALDIR)/$(KVM_BUILD_DOMAIN).xml $(MAKE) kvm-keys-clean : : disable FIPS : $(KVMSH) $(KVM_BUILD_DOMAIN) rm -f /etc/system-fips $(KVMSH) --chdir . $(KVM_BUILD_DOMAIN) ./testing/guestbin/fipsoff : : create the empty /tmp/x509 directory ready for the keys : $(KVMSH) $(KVM_BUILD_DOMAIN) rm -rf /tmp/x509 $(KVMSH) $(KVM_BUILD_DOMAIN) mkdir /tmp/x509 : : per comments, generate everything in /tmp/x509 : $(KVMSH) --chdir . $(KVM_BUILD_DOMAIN) cp -f ./testing/x509/dist_certs.py /tmp/x509 $(KVMSH) --chdir . $(KVM_BUILD_DOMAIN) cp -f ./testing/x509/openssl.cnf /tmp/x509 $(KVMSH) --chdir /tmp/x509 $(KVM_BUILD_DOMAIN) ./dist_certs.py $(KVMSH) --chdir . $(KVM_BUILD_DOMAIN) cp -f ./testing/x509/strongswan-ec-gen.sh /tmp/x509 $(KVMSH) --chdir /tmp/x509 $(KVM_BUILD_DOMAIN) ./strongswan-ec-gen.sh : : copy the certs from guest to host in a tar ball to avoid 9fs bug : rm -f testing/x509/kvm-keys.tar $(KVMSH) --chdir /tmp/x509 $(KVM_BUILD_DOMAIN) tar cf kvm-keys.tar '*/' nss-pw $(KVMSH) --chdir . $(KVM_BUILD_DOMAIN) cp /tmp/x509/kvm-keys.tar testing/x509 cd testing/x509 && tar xf kvm-keys.tar rm -f testing/x509/kvm-keys.tar : : Also regenerate the DNSSEC keys -- uses host : $(top_srcdir)/testing/baseconfigs/all/etc/bind/generate-dnssec.sh $(KVMSH) --shutdown $(KVM_BUILD_DOMAIN) touch $@ KVM_KEYS_CLEAN_TARGETS = clean-kvm-keys kvm-clean-keys kvm-keys-clean .PHONY: $(KVM_KEYS_CLEAN_TARGETS) $(KVM_KEYS_CLEAN_TARGETS): rm -rf testing/x509/*/ rm -f testing/x509/nss-pw rm -f testing/baseconfigs/all/etc/bind/signed/*.signed rm -f testing/baseconfigs/all/etc/bind/keys/*.key rm -f testing/baseconfigs/all/etc/bind/keys/*.private rm -f testing/baseconfigs/all/etc/bind/dsset/dsset-* rm -f testing/x509/kvm-keys.tar # For moment don't force keys to be re-built. .PHONY: kvm-keys-ok kvm-keys-ok: @if test ! -r $(KVM_KEYS); then \ echo "" ; \ echo "The KVM keys are missing; was 'make kvm-install' run?" ; \ echo "" ; \ exit 1 ; \ elif test $$($(KVM_KEYS_EXPIRED) | wc -l) -gt 0 ; then \ echo "" ; \ echo "The following KVM keys are too old:" ; \ $(KVM_KEYS_EXPIRED) ; \ echo "run 'make kvm-keys-clean kvm-keys' to force an update" ; \ echo "" ; \ exit 1 ; \ fi # # Create an RPM for the test domains # .PHONY: kvm-rpm kvm-rpm: @echo building rpm for libreswan testing mkdir -p ~/rpmbuild/SPECS/ sed -e "s/@IPSECBASEVERSION@/$(RPM_VERSION)/g" \ -e "s/^Version:.*/Version: $(RPM_VERSION)/g" \ -e "s/@INITSYSTEM@/$(INITSYSTEM)/g" \ packaging/fedora/libreswan-testing.spec \ > ~/rpmbuild/SPECS/libreswan-testing.spec mkdir -p ~/rpmbuild/SOURCES git archive --format=tar --prefix=$(RPM_PREFIX)/ \ -o ~/rpmbuild/SOURCES/$(RPM_PREFIX).tar HEAD if [ -a Makefile.inc.local ] ; then \ tar --transform "s|^|$(RPM_PREFIX)/|" -rf ~/rpmbuild/SOURCES/$(RPM_PREFIX).tar Makefile.inc.local ; \ fi; gzip -f ~/rpmbuild/SOURCES/$(RPM_PREFIX).tar rpmbuild -ba $(RPM_BUILD_CLEAN) ~/rpmbuild/SPECS/libreswan-testing.spec # # Build a pool of networks from scratch # # This defines the primitives, the public rules are defined near the # end. define create-kvm-network : : create-kvm-network network=$(1) file=$(2) : $(VIRSH) net-define '$(2)' $(VIRSH) net-autostart '$(1)' $(VIRSH) net-start '$(1)' endef define destroy-kvm-network : destroy-kvm-network network=$(1) if $(VIRSH) net-info '$(1)' 2>/dev/null | grep 'Active:.*yes' > /dev/null ; then \ $(VIRSH) net-destroy '$(1)' ; \ fi if $(VIRSH) net-info '$(1)' >/dev/null 2>&1 ; then \ $(VIRSH) net-undefine '$(1)' ; \ fi endef # # The Gateway # # Because the gateway is created directly from libvirt/swandefault and # that file contains hardwired IP addresses, only one is possible. # # XXX: Why? Perhaps it is so that SSHing into the VMs is possible, # but with lots of VMs what address gets assigned stops being # predictable. # KVM_GATEWAY_FILE = $(KVM_POOLDIR)/$(KVM_GATEWAY).gw .PHONY: install-kvm-network-$(KVM_GATEWAY) install-kvm-network-$(KVM_GATEWAY): $(KVM_GATEWAY_FILE) .PHONY: uninstall-kvm-network-$(KVM_GATEWAY) kvm-uninstall-base-network uninstall-kvm-network-$(KVM_GATEWAY) kvm-uninstall-base-network: rm -f $(KVM_GATEWAY_FILE) $(call destroy-kvm-network,$(KVM_GATEWAY)) $(KVM_GATEWAY_FILE): | testing/libvirt/net/$(KVM_GATEWAY) $(KVM_POOLDIR) $(call destroy-kvm-network,$(KVM_GATEWAY)) $(call create-kvm-network,$(KVM_GATEWAY),testing/libvirt/net/$(KVM_GATEWAY)) touch $@ # zap dependent domains uninstall-kvm-network-$(KVM_GATEWAY): uninstall-kvm-domain-$(KVM_BASE_DOMAIN) uninstall-kvm-network-$(KVM_GATEWAY): uninstall-kvm-domain-$(KVM_BUILD_DOMAIN) # # Test networks. # # Since networks survive across reboots and don't use any disk, they # are stored in $(KVM_POOLDIR) and not $(KVM_LOCALDIR). # KVM_TEST_SUBNETS = \ $(notdir $(wildcard testing/libvirt/net/192_*)) KVM_TEST_NETWORKS = \ $(call add-kvm-prefixes, $(KVM_TEST_SUBNETS)) KVM_TEST_NETWORK_FILES = \ $(addsuffix .net, $(addprefix $(KVM_POOLDIR)/, $(KVM_TEST_NETWORKS))) .PRECIOUS: $(KVM_TEST_NETWORK_FILES) # .net; if is blank call it swan* KVM_BRIDGE_NAME = $(strip $(if $(patsubst 192_%,,$*), \ $*, \ swan$(subst _,,$(patsubst %192_,,$*)))) $(KVM_POOLDIR)/%.net: | $(KVM_POOLDIR) $(call destroy-kvm-network,$*) rm -f '$@.tmp' echo "" >> '$@.tmp' echo " $*" >> '$@.tmp' echo " > '$@.tmp' echo " stp='on' delay='0'/>" >> '$@.tmp' $(if $(patsubst 192_%,, $*), \ echo " " >> '$@.tmp') echo "" >> '$@.tmp' $(call create-kvm-network,$*,$@.tmp) mv $@.tmp $@ .PHONY: kvm-install-test-networks kvm-install-test-networks: $(KVM_TEST_NETWORK_FILES) .PHONY: kvm-uninstall-test-networks kvm-uninstall-test-networks: kvm-uninstall-test-domains $(foreach network_file, $(KVM_TEST_NETWORK_FILES), \ $(call destroy-kvm-network,$(notdir $(basename $(network_file))))$(crlf) \ rm -f $(network_file)$(crlf)) # # Build KVM domains from scratch # KVM_ISO = $(KVM_POOLDIR)/$(notdir $(KVM_ISO_URL)) .PHONY: kvm-iso kvm-iso: $(KVM_ISO) $(KVM_ISO): | $(KVM_POOLDIR) cd $(KVM_POOLDIR) && wget $(KVM_ISO_URL) define destroy-kvm-domain : destroy-kvm-domain domain=$(1) if $(VIRSH) domstate $(1) 2>/dev/null | grep running > /dev/null ; then \ $(VIRSH) destroy $(1) ; \ fi if $(VIRSH) dominfo $(1) >/dev/null 2>&1 ; then \ $(VIRSH) undefine $(1) ; \ fi endef # # Create + package install + package upgrade the base domain # # Create and upgrade the base domain and (as a side effect) the disk # image. # # The package install is to ensure that all currently required # packages are present (perhaps $(KVM_PACKAGES) changed), and the # upgrade is to ensure that the latest version is installed (rather # than an older version from the DVD image, say). # # Does the order matter? Trying to upgrade an uninstalled package # barfs. And re-installing a package with a pending upgrade does # nothing. # # To avoid unintended re-builds triggered by things like a git branch # switch, this target is order-only dependent on its sources. # # The create the domain rule's target is .ks - moved into place # right at the very end. That way the problem of a virt-install crash # leaving the disk-image in an incomplete state is avoided. # # The .upgraded target then depends on the .ks target. This way an # upgrade can be triggered without needing to rebuild the entire base # domain. .PRECIOUS: $(KVM_POOLDIR)/$(KVM_BASE_DOMAIN).ks $(KVM_POOLDIR)/$(KVM_BASE_DOMAIN).ks: \ $(KVM_QEMUDIR_OK) \ | \ $(KVM_ISO) \ $(KVM_KICKSTART_FILE) \ $(KVM_GATEWAY_FILE) \ $(KVM_POOLDIR) : Confirm that there is a tty - else virt-install fails mysteriously tty $(call destroy-kvm-domain,$(KVM_BASE_DOMAIN)) : delete any old disk and let virt-install create the image rm -f '$(basename $@).qcow2' $(VIRT_INSTALL_COMMAND) \ --name=$(KVM_BASE_DOMAIN) \ --memory 1024 \ --disk size=$(VIRT_DISK_SIZE_GB),cache=writeback,path=$(basename $@).qcow2 \ --location=$(KVM_ISO) \ --initrd-inject=$(KVM_KICKSTART_FILE) \ --extra-args="swanname=$(KVM_BASE_DOMAIN) ks=file:/$(notdir $(KVM_KICKSTART_FILE)) console=tty0 console=ttyS0,115200 net.ifnames=0 biosdevname=0" : the reboot message from virt-install can be ignored touch $@ $(KVM_POOLDIR)/$(KVM_BASE_DOMAIN).upgraded: \ $(KVM_POOLDIR)/$(KVM_BASE_DOMAIN).ks \ $(KVM_QEMUDIR_OK) $(if $(KVM_PACKAGE_INSTALL), $(if $(KVM_INSTALL_PACKAGES), \ $(KVMSH) $(KVM_BASE_DOMAIN) $(KVM_PACKAGE_INSTALL) $(KVM_INSTALL_PACKAGES))) $(if $(KVM_PACKAGE_UPGRADE), $(if $(KVM_UPGRADE_PACKAGES), \ $(KVMSH) $(KVM_BASE_DOMAIN) $(KVM_PACKAGE_UPGRADE) $(KVM_UPGRADE_PACKAGES))) $(if $(KVM_INSTALL_RPM_LIST), \ $(KVMSH) $(KVM_BASE_DOMAIN) $(KVM_INSTALL_RPM_LIST)) $(if $(KVM_DEBUGINFO_INSTALL), $(if $(KVM_DEBUGINFO), \ $(KVMSH) $(KVM_BASE_DOMAIN) $(KVM_DEBUGINFO_INSTALL) $(KVM_DEBUGINFO))) $(MAKE) kvm-shutdown-base-domain touch $@ .PHONY: install-kvm-domain-$(KVM_BASE_DOMAIN) install-kvm-domain-$(KVM_BASE_DOMAIN): $(KVM_POOLDIR)/$(KVM_BASE_DOMAIN).upgraded # # Create the local disk images # .PRECIOUS: $(foreach domain, $(KVM_LOCAL_DOMAINS), $(KVM_LOCALDIR)/$(domain).qcow2) # Create the local disk images from clone define shadow-kvm-disk : : shadow-kvm-disk from=$(1) to=$(2) : : Fix any disk modes - qemu changes them under the hood : If this fails, the steps: : https://libreswan.org/wiki/Test_Suite_-_KVM#Setting_Users_and_Groups : were probably missed groups | grep $(KVM_GROUP) test -r $(1) || sudo chgrp $(KVM_GROUP) $(1) test -r $(1) || sudo chmod g+r $(1) test -r $(1) test -w $(dir $(2)) : shutdown from $(KVMSH) --shutdown $(basename $(notdir $(1))) : create a shadow - from is used as a backing store rm -f $(2) qemu-img create -f qcow2 -b $(1) $(2) endef KVM_BASE_DISK_CLONES = $(addsuffix .qcow2, $(addprefix $(KVM_LOCALDIR)/, $(KVM_BASE_DOMAIN_CLONES))) $(KVM_BASE_DISK_CLONES): \ $(KVM_QEMUDIR_OK) \ | \ $(KVM_POOLDIR)/$(KVM_BASE_DOMAIN).upgraded \ $(KVM_LOCALDIR) : copy-base-disk from=$< to=$@ $(MAKE) kvm-shutdown-base-domain test -r $(KVM_POOLDIR)/$(KVM_BASE_DOMAIN).qcow2 || sudo chgrp $(KVM_GROUP) $(KVM_POOLDIR)/$(KVM_BASE_DOMAIN).qcow2 test -r $(KVM_POOLDIR)/$(KVM_BASE_DOMAIN).qcow2 || sudo chmod g+r $(KVM_POOLDIR)/$(KVM_BASE_DOMAIN).qcow2 : if this test fails, the steps: : https://libreswan.org/wiki/Test_Suite_-_KVM#Setting_Users_and_Groups : were probably missed test -r $(KVM_POOLDIR)/$(KVM_BASE_DOMAIN).qcow2 $(call shadow-kvm-disk,$(KVM_POOLDIR)/$(KVM_BASE_DOMAIN).qcow2,$@.tmp) mv $@.tmp $@ KVM_BUILD_DISK_CLONES = $(addsuffix .qcow2, $(addprefix $(KVM_LOCALDIR)/, $(KVM_BUILD_DOMAIN_CLONES))) $(KVM_BUILD_DISK_CLONES): \ $(KVM_QEMUDIR_OK) \ | \ $(KVM_LOCALDIR)/$(KVM_BUILD_DOMAIN).qcow2 \ $(KVM_LOCALDIR) : copy-build-disk $@ $(call shadow-kvm-disk,$(KVM_LOCALDIR)/$(KVM_BUILD_DOMAIN).qcow2,$@.tmp) mv $@.tmp $@ # # Create the local domains # # Since running a domain will likely modify its .qcow2 disk image # (changing MTIME), the domain's disk isn't a good indicator that a # domain needs updating. Instead use the .xml file to indicate that a # domain has been created. .PRECIOUS: $(foreach domain, $(KVM_LOCAL_DOMAINS), $(KVM_LOCALDIR)/$(domain).xml) # # Create the "build" domain (if unique) # # Depend on a fully constructed $(KVM_BASE_DOMAIN) (and not just that # domain's disk image). If make creates the $(KVM_BUILD_DOMAIN) # before $(KVM_BASE_DOMAIN) then virt-install complains that # $(KVM_BASE_DOMAIN)'s disk is already in use. # $(KVM_LOCALDIR)/$(KVM_BUILD_DOMAIN).xml: \ $(KVM_QEMUDIR_OK) \ | \ $(KVM_BASE_GATEWAY_FILE) \ $(KVM_POOLDIR)/$(KVM_BASE_DOMAIN).upgraded \ $(KVM_LOCALDIR)/$(KVM_BUILD_DOMAIN).qcow2 : build-domain $@ $(call destroy-kvm-domain,$(KVM_BUILD_DOMAIN)) $(VIRT_INSTALL_COMMAND) \ --name $(KVM_BUILD_DOMAIN) \ --memory 1024 \ --import \ --disk cache=writeback,path=$(KVM_LOCALDIR)/$(KVM_BUILD_DOMAIN).qcow2 \ --noautoconsole $(VIRSH) dumpxml $(KVM_BUILD_DOMAIN) > $@.tmp mv $@.tmp $@ .PHONY: install-kvm-domain-$(KVM_BUILD_DOMAIN) install-kvm-domain-$(KVM_BUILD_DOMAIN): $(KVM_LOCALDIR)/$(KVM_BUILD_DOMAIN).xml # # Create the test domains # define install-kvm-test-domain #(info install-kvm-test-domain prefix=$(1) host=$(2) domain=$(1)$(2)) .PHONY: install-kvm-domain-$(1)$(2) install-kvm-domain-$(1)$(2): $$(KVM_LOCALDIR)/$(1)$(2).xml $$(KVM_LOCALDIR)/$(1)$(2).xml: \ $$(KVM_QEMUDIR_OK) \ | \ $$(foreach subnet,$$(KVM_TEST_SUBNETS), \ $$(KVM_POOLDIR)/$(1)$$(subnet).net) \ testing/libvirt/vm/$(2) \ $(KVM_LOCALDIR)/$(1)$(2).qcow2 : install-kvm-test-domain prefix=$(1) host=$(2) $$(call destroy-kvm-domain,$(1)$(2)) sed \ -e "s:@@NAME@@:$(1)$(2):" \ -e "s:@@TESTINGDIR@@:$$(KVM_TESTINGDIR):" \ -e "s:@@SOURCEDIR@@:$$(KVM_SOURCEDIR):" \ -e "s:@@POOLSPACE@@:$$(KVM_LOCALDIR):" \ -e "s:@@USER@@:$$(KVM_UID):" \ -e "s:@@GROUP@@:$$(KVM_GID):" \ -e "s:network='192_:network='$(1)192_:" \ < 'testing/libvirt/vm/$(2)' \ > '$$@.tmp' $$(VIRSH) define $$@.tmp mv $$@.tmp $$@ endef $(foreach prefix, $(KVM_PREFIXES), \ $(foreach host,$(KVM_TEST_HOSTS), \ $(eval $(call install-kvm-test-domain,$(call strip-prefix,$(prefix)),$(host))))) # # Rules to uninstall individual domains # define uninstall-kvm-domain-DOMAIN #(info uninstall-kvm-domain-DOMAIN domain=$(1) dir=$(2)) .PHONY: uninstall-kvm-domain-$(1) uninstall-kvm-domain-$(1): : uninstall-kvm-domain domain=$(1) dir=$(2) $$(call destroy-kvm-domain,$(1)) rm -f $(2)/$(1).xml rm -f $(2)/$(1).upgraded rm -f $(2)/$(1).ks rm -f $(2)/$(1).qcow2 rm -f $(2)/$(1).img endef $(foreach domain, $(KVM_BASE_DOMAIN), \ $(eval $(call uninstall-kvm-domain-DOMAIN,$(domain),$(KVM_POOLDIR)))) $(foreach domain, $(KVM_BUILD_DOMAIN) $(KVM_TEST_DOMAINS), \ $(eval $(call uninstall-kvm-domain-DOMAIN,$(domain),$(KVM_LOCALDIR)))) # Direct dependencies. This is so that a primitive like # uninstall-kvm-domain-clone isn't run until all its dependencies, # such as uninstall-kvm-domain-build, have been run. Using # kvm-uninstall-* rules leads to indirect dependencies and # out-of-order destruction. $(addprefix uninstall-kvm-domain-, $(KVM_BUILD_DOMAIN)): \ $(addprefix uninstall-kvm-domain-, $(KVM_BUILD_DOMAIN_CLONES)) $(addprefix uninstall-kvm-domain-, $(KVM_BASE_DOMAIN)): \ $(addprefix uninstall-kvm-domain-, $(KVM_BASE_DOMAIN_CLONES)) # # Generic kvm-* rules, point at the *-kvm-* primitives defined # elsewhere. # define kvm-hosts-domains #(info kvm-host-domains rule=$(1) .PHONY: kvm-$(1)-base-domain kvm-$(1)-base-domain: $$(addprefix $(1)-kvm-domain-, $$(KVM_BASE_DOMAIN)) .PHONY: kvm-$(1)-build-domain kvm-$(1)-build-domain: $$(addprefix $(1)-kvm-domain-, $$(KVM_BUILD_DOMAIN)) .PHONY: kvm-$(1)-basic-domains kvm-$(1)-basic-domains: $$(addprefix $(1)-kvm-domain-, $$(KVM_BASIC_DOMAINS)) .PHONY: kvm-$(1)-install-domains kvm-$(1)-install-domains: $$(addprefix $(1)-kvm-domain-, $$(KVM_BUILD_DOMAIN_CLONES)) .PHONY: kvm-$(1)-test-domains kvm-$(1)-test-domains: $$(addprefix $(1)-kvm-domain-, $$(KVM_TEST_DOMAINS)) .PHONY: kvm-$(1)-local-domains kvm-$(1)-local-domains: $$(addprefix $(1)-kvm-domain-, $$(KVM_LOCAL_DOMAINS)) endef $(eval $(call kvm-hosts-domains,install)) $(eval $(call kvm-hosts-domains,uninstall)) $(eval $(call kvm-hosts-domains,shutdown)) # # Get rid of (almost) everything # # After a purge, there should be an upgrade. Force this by deleting # the .upgraded file. # # XXX: don't depend on targets that trigger a KVM build. # # For kvm-uninstall, instead of trying to uninstall libreswan from the # $(KVM_BUILD_DOMAIN_CLONES), delete both $(KVM_BUILD_DOMAIN_CLONES) and # $(KVM_BUILD_DOMAIN) the install domains were cloned from. This way, # in addition to giving kvm-install a 100% fresh start (no depdenence # on 'make uninstall') the next test run also gets entirely new # domains. .PHONY: kvm-clean kvm-clean: kvm-shutdown kvm-clean: kvm-keys-clean kvm-clean: kvm-test-clean rm -rf $(KVM_OBJDIR) .PHONY: kvm-uninstall kvm-uninstall: kvm-uninstall-test-domains kvm-uninstall: kvm-uninstall-build-domain .PHONY: kvm-upgrade kvm-upgrade: kvm-uninstall rm -f $(KVM_POOLDIR)/$(KVM_BASE_DOMAIN).upgraded $(MAKE) kvm-install-base-domain .PHONY: kvm-purge kvm-purge: kvm-clean kvm-purge: kvm-uninstall kvm-purge: kvm-uninstall-test-networks rm -f $(KVM_POOLDIR)/$(KVM_BASE_DOMAIN).upgraded .PHONY: kvm-demolish kvm-demolish: kvm-purge kvm-demolish: kvm-uninstall-base-domain kvm-demolish: kvm-uninstall-base-network # # kvm-build target # # First delete all of the build domain's clones. The build domain # won't boot when its clones are running. .PHONY: kvm-$(KVM_BUILD_DOMAIN)-build kvm-$(KVM_BUILD_DOMAIN)-build: \ $(KVM_QEMUDIR_OK) \ | \ $(KVM_LOCALDIR)/$(KVM_BUILD_DOMAIN).xml ifeq ($(KVM_INSTLL_RPM), true) $(KVMSH) $(KVMSH_FLAGS) --chdir . $(KVM_BUILD_DOMAIN) 'rm -fr ~/rpmbuild/*RPMS' $(KVMSH) $(KVMSH_FLAGS) --chdir . $(KVM_BUILD_DOMAIN) 'make kvm-rpm' else $(KVMSH) $(KVMSH_FLAGS) --chdir . $(KVM_BUILD_DOMAIN) 'export OBJDIR=$(KVM_OBJDIR)' $(KVMSH) $(KVMSH_FLAGS) --chdir . $(KVM_BUILD_DOMAIN) 'make OBJDIR=$(KVM_OBJDIR) $(KVM_MAKEFLAGS) base' endif ifeq ($(KVM_KLIPS_MODULE),true) $(KVMSH) $(KVMSH_FLAGS) --chdir . $(KVM_BUILD_DOMAIN) 'make OBJDIR=$(KVM_OBJDIR) $(KVM_MAKEFLAGS) module' endif : install will run $(KVMSH) --shutdown $(1) .PHONY: kvm-build kvm-build: $(foreach domain, $(KVM_BUILD_DOMAIN_CLONES), uninstall-kvm-domain-$(domain)) $(MAKE) kvm-$(KVM_BUILD_DOMAIN)-build # # kvm-install target # # So that all the INSTALL domains are deleted before the build domain # is booted, this is done using a series of sub-makes (without this, # things barf because the build domain things its disk is in use). .PHONY: kvm-$(KVM_BUILD_DOMAIN)-install kvm-$(KVM_BUILD_DOMAIN)-install: $(KVM_QEMUDIR_OK) kvm-$(KVM_BUILD_DOMAIN)-build | $(KVM_LOCALDIR)/$(KVM_BUILD_DOMAIN).xml ifeq ($(KVM_INSTLL_RPM), true) $(KVMSH) $(KVMSH_FLAGS) --chdir . $(KVM_BUILD_DOMAIN) 'rpm -aq | grep libreswan && rpm -e $$(rpm -aq | grep libreswan) || true' $(KVMSH) $(KVMSH_FLAGS) --chdir . $(KVM_BUILD_DOMAIN) 'rpm -i ~/rpmbuild/RPMS/x86_64/libreswan*rpm' $(KVMSH) $(KVMSH_FLAGS) --chdir . $(KVM_BUILD_DOMAIN) 'cp -f ~/rpmbuild/RPMS/x86_64/libreswan*rpm /source/' $(KVMSH) $(KVMSH_FLAGS) --chdir . $(KVM_BUILD_DOMAIN) 'cp -f ~/rpmbuild/SRPMS/libreswan*rpm /source/' else $(KVMSH) $(KVMSH_FLAGS) --chdir . $(KVM_BUILD_DOMAIN) 'make OBJDIR=$(KVM_OBJDIR) $(KVM_MAKEFLAGS) install-base' ifeq ($(KVM_USE_FIPSCHECK),true) $(KVMSH) $(KVMSH_FLAGS) --chdir . $(KVM_BUILD_DOMAIN) 'make OBJDIR=$(KVM_OBJDIR) $(KVM_MAKEFLAGS) install-fipshmac' endif endif ifeq ($(KVM_KLIPS_MODULE),true) $(KVMSH) $(KVMSH_FLAGS) --chdir . $(KVM_BUILD_DOMAIN) 'make OBJDIR=$(KVM_OBJDIR) $(KVM_MAKEFLAGS) module_install' endif $(KVMSH) $(KVMSH_FLAGS) --chdir . $(KVM_BUILD_DOMAIN) 'restorecon /usr/local/sbin /usr/local/libexec/ipsec -Rv' $(KVMSH) --shutdown $(KVM_BUILD_DOMAIN) .PHONY: kvm-install kvm-install: $(foreach domain, $(KVM_BUILD_DOMAIN_CLONES), uninstall-kvm-domain-$(domain)) $(MAKE) kvm-$(KVM_BUILD_DOMAIN)-install $(MAKE) $(foreach domain, $(KVM_BUILD_DOMAIN_CLONES) $(KVM_BASIC_DOMAINS), install-kvm-domain-$(domain)) $(MAKE) kvm-keys .PHONY: kvm-bisect kvm-bisect: : 125 is git bisect magic for 'skip' $(MAKE) kvm-install || exit 125 $(MAKE) kvm-test kvm-diffs $(if $(KVM_TESTS),KVM_TESTS="$(KVM_TESTS)") # # kvmsh-HOST # # Map this onto the first domain group. Logging into the other # domains can be done by invoking kvmsh.py directly. # define kvmsh-DOMAIN #(info kvmsh-DOMAIN domain=$(1) file=$(2)) .PHONY: kvmsh-$(1) kvmsh-$(1): $$(KVM_QEMUDIR_OK) \ | \ $(2) : kvmsh-DOMAIN domain=$(1) file=$(2) $$(KVMSH) $$(KVMSH_FLAGS) $(1) $(KVMSH_COMMAND) endef $(foreach domain, $(KVM_BASE_DOMAIN), \ $(eval $(call kvmsh-DOMAIN,$(domain),$$(KVM_POOLDIR)/$$(KVM_BASE_DOMAIN).ks))) $(foreach domain, $(KVM_LOCAL_DOMAINS), \ $(eval $(call kvmsh-DOMAIN,$(domain),$$(KVM_LOCALDIR)/$(domain).xml))) $(foreach host, $(filter-out $(KVM_DOMAINS), $(KVM_HOSTS)), \ $(eval $(call kvm-HOST-DOMAIN,kvmsh-,$(host)))) .PHONY: kvmsh-base kvmsh-base: kvmsh-$(KVM_BASE_DOMAIN) .PHONY: kvmsh-build kvmsh-build: kvmsh-$(KVM_BUILD_DOMAIN) # # Shutdown domains and hosts. # # Generate rules to shut down all the domains (kvm-shutdown) and # individual domains (kvm-shutdown-domain). # # Don't require the domains to exist. define shutdown-kvm-domain #(info shutdown-kvm-domain domain=$(1)) .PHONY: shutdown-kvm-domain-$(1) shutdown-kvm-domain-$(1): : shutdown-kvm-domain domain=$(1) echo ; \ if $(VIRSH) dominfo $(1) > /dev/null 2>&1 ; then \ $(KVMSH) --shutdown $(1) || exit 1 ; \ else \ echo Domain $(1) does not exist ; \ fi ; \ echo endef $(foreach domain, $(KVM_DOMAINS), \ $(eval $(call shutdown-kvm-domain,$(domain)))) .PHONY: kvm-shutdown kvm-shutdown: $(addprefix shutdown-kvm-domain-,$(KVM_DOMAINS)) .PHONY: kvm-shutdown-install-domains kvm-shutdown-install-domains: $(addprefix shutdown-kvm-domain-,$(KVM_BUILD_DOMAIN_CLONES)) .PHONY: kvm-shutdown-test-domains kvm-shutdown-test-domains: $(addprefix shutdown-kvm-domain-,$(KVM_TEST_DOMAINS)) .PHONY: kvm-shutdown-local-domains kvm-shutdown-local-domains: $(addprefix shutdown-kvm-domain-,$(KVM_LOCAL_DOMAINS)) # # Some hints # # Only what is listed in here is "supported" # empty = comma = , sp = $(empty) $(empty) # the first blank line is ignored define crlf endef define kvm-var-value $(1)=$($(1)) [$(value $(1))] endef define kvm-value $($(1)) [$(value $(1))] endef define kvm-var $($(1)) [$$($(1))] endef define kvm-config Configuration: Makefile variables: $(call kvm-var-value,KVM_SOURCEDIR) $(call kvm-var-value,KVM_TESTINGDIR) $(call kvm-var-value,KVM_PREFIXES) $(call kvm-var-value,KVM_WORKERS) $(call kvm-var-value,KVM_GROUP) $(call kvm-var-value,KVM_UID) $(call kvm-var-value,KVM_GID) $(call kvm-var-value,KVM_CONNECTION) $(call kvm-var-value,KVM_MAKEFLAGS) $(call kvm-var-value,KVM_POOLDIR)$(if $(wildcard $(KVM_POOLDIR)),, [MISSING]) default directory for storing VM files $(call kvm-var-value,KVM_POOLDIR)$(if $(wildcard $(KVM_POOLDIR)),, [MISSING]) directory for storing the shared base (master) VM; should be relatively permanent storage $(call kvm-var-value,KVM_LOCALDIR)$(if $(wildcard $(KVM_LOCALDIR)),, [MISSING]) directory for storing the VMs local to this build tree; can be temporary storage (for instance /tmp) $(call kvm-var-value,KVM_GATEWAY) the shared NATting gateway; used by the base (master) domain along with any local domains when internet access is required $(call kvm-var-value,KVM_GUEST_OS) $(call kvm-var-value,KVM_KICKSTART_FILE) $(call kvm-var-value,KVM_GATEWAY) $(call kvm-var-value,KVM_BASE_HOST) $(call kvm-var-value,KVM_BASE_DOMAIN) $(call kvm-var-value,KVM_BUILD_HOST) $(call kvm-var-value,KVM_BUILD_DOMAIN) $(call kvm-var-value,KVM_TEST_SUBNETS) $(call kvm-var-value,KVM_TEST_NETWORKS) $(call kvm-var-value,KVM_TEST_NETWORK_FILES) $(call kvm-var-value,KVM_TEST_HOSTS) $(call kvm-var-value,KVM_TEST_DOMAINS) KVM Domains: $(KVM_BASE_DOMAIN) | gateway: $(KVM_GATEWAY) | directory: $(KVM_POOLDIR) | +- $(KVM_BUILD_DOMAIN) | | gateway: $(KVM_GATEWAY) | | directory: $(KVM_LOCALDIR) | | \ $(foreach prefix,$(KVM_PREFIXES), \ \ $(crlf)$(sp)$(sp)$(sp)$(sp)|$(sp)$(sp)| test group $(prefix) \ $(crlf)$(sp)$(sp)$(sp) +----- \ $(foreach basic,$(KVM_BASIC_HOSTS),$(call strip-prefix,$(prefix))$(basic)) \ \ $(crlf)$(sp)$(sp)$(sp)$(sp)|$(sp) +-- \ $(foreach install,$(KVM_BUILD_HOST_CLONES),$(call strip-prefix,$(prefix))$(install)) \ \ $(crlf)$(sp)$(sp)$(sp)$(sp)|$(sp)$(sp)|$(sp$)$(sp)$(sp) networks: \ $(foreach network, $(KVM_TEST_SUBNETS),$(call strip-prefix,$(prefix))$(network)) \ \ $(crlf)$(sp)$(sp)$(sp)$(sp)|$(sp)$(sp)| \ ) endef define kvm-help Domains and networks: These directly manipulate the underling domains and networks and are not not generally recommended. For the most part kvm-install and kvm-unsintall are sufficient. Domains: kvm-install-base-domain (kvm-uninstall-base-domain) - (un)install the base domain - install dependencies: base gateway kvm-install-build-domain (kvm-uninstall-build-domain) - (un)install this directory's build domain - install dependencies: local gateway; test networks kvm-install-test-domains (kvm-uninstall-test-domains) - (un)install this directory's test domains - install dependencies: build domain; test networks kvm-install-local-domains (kvm-uninstall-local-domains) - (un)install this directory's build and test domains - install dependencies: see above Networks: kvm-install-gateway (kvm-uninstall-gateway) - (un)install the NATting base gateway used by the base and build domains - uninstall dependencies: base domain kvm-install-test-networks (kvm-uninstall-test-networks) - (un)install the test networks used by this directory's test domains - uninstall dependencies: test domains Standard targets and operations: Delete the installed KVMs and networks so that the next kvm-install will create new versions: kvm-uninstall: force clean test and build domains - delete test domains - delete build kvm-upgrade: force OS upgrade - also flag base domain as needing upgrade kvm-purge: clean up a directory - also delete test networks - also delete test results - also delete test build kvm-demolish: wipe out a directory - also delete the base domain Note that kvm-upgrade immediately upgrades the base domain while kvm-purge and kvm-demolish leave the upgrade to the next kvm-install. Manipulating and accessing (logging into) domains: kvmsh-base kvmsh-build kvmsh-HOST ($(filter-out build, $(KVM_TEST_HOSTS))) - use 'virsh console' to login to the given domain - for HOST login to the first domain vis $(addprefix $(KVM_FIRST_PREFIX), HOST) - if necessary, create and boot the host $(addprefix kvmsh-, $(KVM_LOCAL_DOMAINS)) - login to the specific domain - if necessary, create and boot the domain kvm-shutdown - shutdown all domains To build or delete the keys used when testing: kvm-keys (kvm-clean-keys) - use the local build domain to create the test keys To set things up for a test run: kvm-install: install (or update) libreswan on the test domains - cheats by building/installing using the local build domain ($(KVM_BUILD_DOMAIN)) and then cloning it to create the test domains - if necessary, creates the local build domain ($(KVM_BUILD_DOMAIN)) from the local base domain ($(KVM_BASE_DOMAIN)) - if necessary, creates and upgrade the local base domain ($(KVM_BASE_DOMAIN)) kvm-uninstall: uninstall libreswan from the the test domains - cheats by deleting the build and test domains kvm-clean: cleans the directory forcing 'kvm-install' to perform a 'clean' build - deletes the test domains - deletes the build domain ($(KVM_BUILD_DOMAIN)) - deletes the test keys so the next kvm-check builds fresh keys - deletes the test results from the previous test run To run the testsuite against libreswan installed on the test domains (see "make kvm-install" above): kvm-check - run all GOOD tests against the previously installed libreswan kvm-check KVM_TESTS+=testing/pluto/basic-pluto-0[0-1] - run test matching the pattern kvm-check KVM_TEST_FLAGS='--test-status "good|wip"' - run both good and wip tests kvm-recheck - like kvm-check but skip tests that passed during the previous kvm-check kvm-check-clean - delete the test OUTPUT/ directories distclean - scrubs the source tree (but don't touch the KVMS) kvm-status - prints PS for the currently running tests kvm-kill - kill the currently running tests To analyze test results: kvm-results - list the tests and their results compare against KVM_BASELINE when defined kvm-diffs - list the tests and their differences compare against KVM_BASELINE when defined kvm-modified kvm-modified-check kvm-modified-recheck kvm-modified-results kvm-modified-diffs - list/check/examine any tests with modified files To run 'git bisect': git bisect start; git bisect good ...; gid bisect bad ...; then git bisect run make kvm-bisect KVM_TESTS=test/that/changed - kvm-bisect is roughly equivalent to: make kvm-install || exit 125 make kvm-test kvm-diffs KVM_TESTS=... To print make variables: print-kvm-prefixes print prefixes being used endef .PHONY: kvm-help kvm-help: $(info $(kvm-help)) $(info For more details see "make kvm-config" and "make web-config") .PHONY: kvm-config kvm-config: $(info $(kvm-config)) libreswan-3.32/mk/library.mk000066400000000000000000000020261365625662500160530ustar00rootroot00000000000000# Make life easy, just include everything that is needed. ifndef top_srcdir include $(dir $(lastword $(MAKEFILE_LIST)))dirs.mk endif include $(top_srcdir)/mk/config.mk include $(top_srcdir)/mk/version.mk include $(top_srcdir)/mk/targets.mk INCLUDES+=-I${LIBRESWANSRCDIR}/include # nss INCLUDES+=${NSSFLAGS} CFLAGS+=${PORTINCLUDE} ${INCLUDES} ${CROSSFLAGS} CFLAGS+=-pthread # XXX: hack until everything uses a consistent .c.o rule CFLAGS+=$(USERLAND_CFLAGS) ARFLAGS=crvs local-base: $(LIB) local-clean-base: rm -f $(builddir)/*.o rm -f $(builddir)/*.a rm -f $(builddir)/*.c list-local-base: @: never nothing to do # So that removing something from $(OBJS) triggers an archive build: # depend on Makefile; and always build a new archive. Could also # depend the mk/* directory? $(LIB): $(OBJS) $(srcdir)/Makefile | $(builddir) rm -f $(builddir)/$(LIB).tmp cd $(builddir) && $(AR) $(ARFLAGS) $(LIB).tmp $(OBJS) mv $(builddir)/$(LIB).tmp $(builddir)/$(LIB) include $(top_srcdir)/mk/depend.mk include $(top_srcdir)/mk/builddir.mk libreswan-3.32/mk/local.mk000066400000000000000000000027021365625662500155020ustar00rootroot00000000000000# Wrapper around local make file, for Libreswan. # # Copyright (C) 2015 Andrew Cagney # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # Currently both mk/dirs.mk and Makefile.inc need to see the local # definitions in Makefile.inc.local but Makefile.inc can't (yet) # assume dirs.mk has been included. This wrapper prevents multiple # includes. # Why can't mk/dirs.mk include Makefile.inc or Makefile.inc include # mk/dirs? # # The problem is circular. Makefile.inc uses variables like # LIBRESWANSRCDIR but at the point where Makefile.inc.local should be # included by mk/dirs.mk (very early as it might set OBJDIR), # mk/dirs.mk hasn't yet had a chance to define them. # Only include a local make file once. ifndef local.mk local.mk = true # try to include ifdef top_srcdir # mk/dirs.mk case -include $(top_srcdir)/Makefile.inc.local else # Makefile.inc case, when mk/dirs.mk hasn't been included -include $(LIBRESWANSRCDIR)/Makefile.inc.local endif endif libreswan-3.32/mk/manpages.mk000066400000000000000000000060101365625662500161770ustar00rootroot00000000000000# Manpage rules, for Libreswan. # # Copyright (C) 2015-2016, Andrew Cagney # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # NOTE: libreswan includes custom makefile configuration first, hence # need a weak assign XMLTO ?= xmlto # $(MANDIR$(suffix $(MANPAGE))) will expand one of the below, roughly: # 3 is libraries; 8 is for system programs; and 5 is for file formats. MANDIR.3 ?= $(MANTREE)/man3 MANDIR.5 ?= $(MANTREE)/man5 MANDIR.8 ?= $(MANTREE)/man8 # List of the intermediate (transformed) man pages. Don't let GNU # make delete these. TRANSFORMED_MANPAGES = $(addprefix $(builddir)/,$(addsuffix .tmp,$(MANPAGES))) .PRECIOUS: $(TRANSFORMED_MANPAGES) # Given the file MANPAGE.[0-9].{xml,tmp}, generate a list of # entries, including the section number. refnames = $(shell $(top_srcdir)/packaging/utils/refnames.sh $(1)) # Man pages to build, since the list of generated man pages isn't # predictable (see refnames.sh) use a fake target to mark that each # page has been generated. local-manpages: $(addprefix $(builddir)/,$(addsuffix .man,$(MANPAGES))) local-install-manpages: local-manpages @set -eu $(foreach manpage,$(MANPAGES), \ $(foreach refname,$(call refnames,$(builddir)/$(manpage).tmp), \ $(foreach destdir,$(MANDIR$(suffix $(refname))), \ ; src=$(builddir)/$(refname) \ ; echo $$src '->' $(destdir) \ ; mkdir -p $(destdir) \ ; $(INSTALL) $(INSTMANFLAGS) $$src $(destdir)))) list-local-manpages: $(TRANSFORMED_MANPAGES) @set -eu $(foreach manpage,$(MANPAGES), \ $(foreach refname,$(call refnames,$(builddir)/$(manpage).tmp), \ ; echo $(MANDIR$(suffix $(refname)))/$(refname))) local-clean-manpages: rm -f $(builddir)/*.[1-8] rm -f $(builddir)/*.[1-8].tmp rm -f $(builddir)/*.[1-8].man # Default rule for creating the TRANSFORMED_MANPAGES. # # Directories, such as programs/configs/, that generate the man page # source, should provide a custom equivalent of this rule. $(builddir)/%.tmp: $(srcdir)/%.xml | $(builddir) ${TRANSFORM_VARIABLES} < $< > $@.tmp mv $@.tmp $@ # Default rule for creating the man pages from the intermediate # (transformed) input. # # Note: XMLTO seems to fail even when it succeeds so ignore the exit # status and instead explicitlay check for the expected output files. # # Use a dummy target since the generated man pages probably don't # match the target name. $(builddir)/%.man: $(builddir)/%.tmp : ignoring seemingly bogus $(XMLTO) exit status $(XMLTO) man $< -o $(builddir) || true test -z "" $(foreach refname,$(call refnames,$<), -a -r $(builddir)/$(refname)) touch $@ libreswan-3.32/mk/objdir.mk000066400000000000000000000037551365625662500156720ustar00rootroot00000000000000# Define OBJDIR, for Libreswan pathnames and other master configuration # # Copyright (C) 2001, 2002 Henry Spencer. # Copyright (C) 2003-2006 Xelerance Corporation # Copyright (C) 2012 Paul Wouters # Copyright (C) 2015 Andrew Cagney # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # XXX: # # "uname" describes the the build system's kernel, and not the target # system's operating environment (architecture, kernel, operating # system version, glibc version, ...) - think cross compile. # # An improvement might be: # # $(CC) -dumpmachine # # but this assumes CC has already been set (currently CC can be set # later, via Makefile.inc, by packaging/defaults/$(BUILDENV) and/or # packaging/defaults/$(BUILDENV).$(ARCH) # # Trying to query the build environment with tricks like: # # ( echo '#include ' ; echo 'major=__GLIBC__ ; # minor=__GLIBC_MINOR__') | gcc -E - # # have a similar result. # supply kernel-configuration ARCH defaults ifeq ($(ARCH),) ARCH:=$(shell uname -m) endif # always sanitize $(ARCH) ARCH:=$(shell echo $(ARCH) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/ -e 's/ //g') # OSDEP=linux,bsd,cygwin,darwin ifeq ($(OSDEP),) OSDEP:=$(shell uname -s | tr 'A-Z' 'a-z') endif export OSDEP # BUILDENV could already be set by Makefile.inc.local to # mingw32-linux, darwin, or mingw32, etc.. ifeq ($(BUILDENV),) BUILDENV:=$(shell uname -s | tr 'A-Z' 'a-z' | sed -e 's/\(.*\)-.*/\1/') endif export BUILDENV OBJDIR?=OBJ.${BUILDENV}.${ARCH} libreswan-3.32/mk/perf.sh000077500000000000000000000042121365625662500153500ustar00rootroot00000000000000#!/bin/sh # script to try combinations of workers and prefixes grep ^kvmplutotest testing/pluto/TESTLIST \ | head -100 > testing/pluto/SHORTLIST for workers in 1 2 3 4 5 ; do p="" for prefix in a. b. c. d. e. ; do p="$p $prefix" log="w=${workers}-p=$(echo $p | wc -w).log" if test ! -r $log ; then make 2>&1 kvm-install kvm-test \ KVM_WORKERS=${workers} \ "KVM_PREFIX=${p}" \ KVM_TESTS=testing/pluto/SHORTLIST \ | tee $log fi done done fields() { failed=$(awk '/ failed: / { f=$4 } END { print f }' < $log) start=$(awk '/run started at/ { print $NF }' < $log) time=$(awk '/run finished at/ { print $NF }' < $log) minutes=$(awk '/run finished at/ { n = split($NF,t,":") s = 0 for (i = 1; i < n; i++) { s = s * 60 + t[i] } print s }' < $log) } workers() { ls *.log | sed -e 's/.*w=\([0-9]\).*/\1/' | sort -n -u } prefixes() { ls *.log | sed -e 's/.*p=\([0-9]\).*/\1/' | sort -n -u } echo "Parallel Reboots vs Parallel Tests: Failures" printf "Parallel Reboots" for prefix in $(prefixes) ; do printf ",$prefix Tests" done printf "\n" for worker in $(workers) ; do printf $worker for log in *w=$worker*.log ; do fields printf ,$failed done printf '\n' done echo "Parallel Tests vs Parallel Reboots: Failures" printf "Parallel Tests" for worker in $(workers) ; do printf ",$worker Reboots" done printf "\n" for prefix in $(prefixes) ; do printf $prefix for log in *p=$prefix*.log ; do fields printf ,$failed done printf '\n' done echo "Parallel Reboots vs Parallel Tests: Time" printf "Parallel Reboots" for prefix in $(prefixes) ; do printf ",$prefix Tests" done printf "\n" for worker in $(workers) ; do printf $worker for log in *w=$worker*.log ; do fields printf ,$minutes done printf '\n' done echo "Parallel Tests vs Parallel Reboots: Time" printf "Parallel Tests" for worker in $(workers) ; do printf ",$worker Reboots" done printf "\n" for prefix in $(prefixes) ; do printf $prefix for log in *p=$prefix*.log ; do fields printf ,$minutes done printf '\n' done libreswan-3.32/mk/program.mk000066400000000000000000000100641365625662500160570ustar00rootroot00000000000000# Make life easy, just include everything that is needed. ifndef top_srcdir include $(dir $(lastword $(MAKEFILE_LIST)))dirs.mk endif # Unless PROGRAM_MANPAGE has been pre-defined (only done by whack and # only to suppress its man page), force MANPAGES to include a MANPAGE # for this program. PROGRAM_MANPAGE ?= $(addsuffix .8, $(PROGRAM)) MANPAGES += $(PROGRAM_MANPAGE) include $(top_srcdir)/mk/config.mk include $(top_srcdir)/mk/version.mk include $(top_srcdir)/mk/targets.mk include $(top_srcdir)/mk/manpages.mk LEX=flex BISON=bison RM=rm # XXX: hack until everything uses a consistent .c.o rule. CFLAGS += -pthread CFLAGS += $(USERLAND_CFLAGS) CFLAGS += $(PORTINCLUDE) CFLAGS += -I$(top_srcdir)/include CFLAGS += $(NSSFLAGS) CFLAGS += $(CROSSFLAGS) ifneq ($(LD_LIBRARY_PATH),) LDFLAGS+=-L$(LD_LIBRARY_PATH) endif ifndef PROGRAMDIR PROGRAMDIR=${LIBEXECDIR} endif ifndef CONFDSUBDIR CONFDSUBDIR=. endif # the list of stuff to be built for "make programs" CONFIGLIST=$(CONFFILES) $(CONFDSUBDIRFILES) PROGRAMSLIST=${PROGRAM} $(CONFIGLIST) local-base: $(PROGRAMSLIST) local-clean-base: rm -f $(builddir)/*.o $(foreach p,$(PROGRAMSLIST), $(builddir)/$(p)) src-file = $(firstword $(wildcard $(srcdir)/$(1) $(builddir)/$(1))) foreach-file = set -eu ; $(foreach f, $(1), \ file=$(f) ; \ destdir=$(strip $(2)) ; \ src=$(call src-file,$(f)) ; \ $(3) \ ) local-install-base: @$(call foreach-file, $(PROGRAM), $(PROGRAMDIR), \ echo $$src '->' $$destdir/$$file ; \ mkdir -p $$destdir ; \ $(INSTALL) $(INSTBINFLAGS) $$src $$destdir/$$file ; \ ) @set -eu ; $(foreach file, $(CONFFILES), \ if [ ! -f $(CONFDIR)/$(file) ]; then \ echo $(call src-file,$(file)) '->' $(CONFDIR)/$(file) ; \ mkdir -p $(CONFDIR) ; \ $(INSTALL) $(INSTCONFFLAGS) $($(file).INSTFLAGS) $(call src-file,$(file)) $(CONFDIR)/$(file) ; \ fi ; \ ) @$(call foreach-file, $(CONFFILES), $(CONFDIR), \ echo $$src '->' $(EXAMPLECONFDIR)/$$file-sample ; \ mkdir -p $(EXAMPLECONFDIR) ; \ $(INSTALL) $(INSTCONFFLAGS) $$src $(EXAMPLECONFDIR)/$$file-sample ; \ ) @$(call foreach-file, $(EXCONFFILES), $(EXAMPLECONFDIR), \ echo $$src '->' $$destdir/$$file-sample ; \ $(INSTALL) $(INSTCONFFLAGS) $$src $$destdir/$$file-sample ; \ ) @$(call foreach-file, $(CONFDSUBDIRFILES), $(CONFDDIR)/$(CONFDSUBDIR), \ if [ ! -f $$destdir/$$file ]; then \ echo $$src '->' $$destdir/$$file ; \ mkdir -p $$destdir ; \ $(INSTALL) $(INSTCONFFLAGS) $$src $$destdir/$$file ; \ fi ; \ ) list-local-base: @$(call foreach-file, $(PROGRAM), $(PROGRAMDIR), \ echo $$destdir/$$file ; \ ) @$(call foreach-file, $(CONFFILES), $(CONFDIR), \ echo $$destdir/$$file ; \ ) @$(call foreach-file, $(CONFFILES), $(CONFDIR), \ echo $(EXAMPLECONFDIR)/$$file-sample ; \ ) @$(call foreach-file, $(EXCONFFILES), $(EXAMPLECONFDIR), \ echo $$destdir/$$file-sample ; \ ) @$(call foreach-file, $(CONFDSUBDIRFILES), $(CONFDDIR)/$(CONFDSUBDIR), \ echo $$destdir/$$file ; \ ) ifdef OBJS # To avoid problems with implicit make rules creating and then # deleting $(PROGRAM).o, $(OBJS) must include the main object # (typically $(PROGRAM).o). Since there is no difference between how # objects and archives are handled, $(OBJS) includes both. Duplicate # archives do no harm. # # Need to depend on Makefile so that when $(OBJS) changes (for # instance something is removed), a re-link is triggered. $(PROGRAM): $(OBJS) $(srcdir)/Makefile cd $(builddir) && $(CC) $(CFLAGS) -o $@ $(OBJS) $(LDFLAGS) $(USERLAND_LDFLAGS) include $(top_srcdir)/mk/depend.mk else %: %.in $(top_srcdir)/Makefile.inc $(top_srcdir)/Makefile.ver | $(builddir) @echo 'IN' $< '->' $(builddir)/$@ ${TRANSFORM_VARIABLES} < $< > $(builddir)/$@ @if [ -x $< ]; then chmod +x $(builddir)/$@; fi @if [ "${PROGRAM}.in" = $< ]; then chmod +x $(builddir)/$@; fi %: %.pl $(top_srcdir)/Makefile.inc $(top_srcdir)/Makefile.ver | $(builddir) @echo 'PL' $< '->' $(builddir)/$@ @${TRANSFORM_VARIABLES} < $< > $(builddir)/$@ @if [ -x $< ]; then chmod +x $(builddir)/$@; fi @if [ "${PROGRAM}.pl" = $< ]; then chmod +x $(builddir)/$@; fi endif include $(top_srcdir)/mk/builddir.mk libreswan-3.32/mk/subdirs.mk000066400000000000000000000013531365625662500160640ustar00rootroot00000000000000# Makefile stub to build SUBDIRS # # Copyright (C) 2015 Andrew Cagney # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. default: @echo "Please read INSTALL before running make" @false .PHONY: default include $(top_srcdir)/mk/targets.mk libreswan-3.32/mk/targets.mk000066400000000000000000000075531365625662500160720ustar00rootroot00000000000000# Default Makefile targets, for Libreswan # # Copyright (C) 2015-2016, Andrew Cagney # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # Define a standard set of global (recursive) and local targets. # Note: To prevent recursive explosion, recursive targets should # depend directly on local targets, and not on other recursive # targets. # Note: To prevent a parallel recursion explosion, recursive targets # should only depend on local targets. For instance implementing # "all" as "all: base manpages" would result in make attempting to, in # parallel, recursively build both "base" and "manpages". Rules # building Makefile dependencies are not ready for this. # # Note: For reasons similar to the above target aliases should, at # most, depend on on global (recursive) target. # This is the default; unless your Makefile puts something earlier. all: # Map common, and historic targets, onto current names. For historic # reasons, "programs" also builds everything. .PHONY: programs programs: all man: manpages # # Generate a recursive target. # define recursive-target .PHONY: $(1) local-$(1) recursive-$(1) $(1) local-$(1) recursive-$(1): # Force recursion before running the local target. While this is # what make systems like autoconf do, pluto was for a very long time # doing the opposite - doing the recursion last. $(1): recursive-$(1) @$$(MAKE) --no-print-directory local-$(1) recursive-$(1): @set -eu $$(foreach subdir,$$(SUBDIRS),; $$(MAKE) -C $$(subdir) $$(patsubst recursive-%,%,$$@)) endef # The build is split into several sub-targets - namely so that # manpages are not built by default. # # For each define: TARGET clean-TARGET install-TARGET TARGETS = base manpages $(foreach target,$(TARGETS),$(eval $(call recursive-target,$(target)))) $(foreach target,$(TARGETS),$(eval $(call recursive-target,clean-$(target)))) $(foreach target,$(TARGETS),$(eval $(call recursive-target,install-$(target)))) # install requires up-to-date build; recursive make, being evil, makes # this less than 100% reliable. local-install-base: local-base local-install-manpages: local-manpages # More generic targets. These, in each directory, invoke local # versions of the above. $(eval $(call recursive-target,all)) local-all: $(patsubst %,local-%,$(TARGETS)) $(eval $(call recursive-target,clean)) local-clean: $(patsubst %,local-clean-%,$(TARGETS)) $(eval $(call recursive-target,install)) local-install: $(patsubst %,local-install-%,$(TARGETS)) $(eval $(call recursive-target,check)) $(eval $(call recursive-target,selfcheck)) # The install_file_list target is special; the command: # # $ make install_file_list > file-list # # must only contain the list of files that would be installed # (generated by list-local-base et.al.). Consequently: # # - to stop "Nothing to be done" messages, the target is never empty # # - to stop make's directory messages, --no-print-directory is # specified LOCAL_TARGETS = $(addprefix local-, $(TARGETS)) LIST_TARGETS = $(addprefix list-, $(TARGETS)) LIST_LOCAL_TARGETS = $(addprefix list-, $(LOCAL_TARGETS)) .PHONY: install_file_list $(LIST_TARGETS) $(LIST_LOCAL_TARGETS) install_file_list $(LIST_TARGETS): @set -eu ; $(foreach dir,$(SUBDIRS), \ echo $(PWD)/$(dir): 1>&2 ; \ $(MAKE) -C $(dir) --no-print-directory $@ ; \ ) install_file_list: list-local-base list-local-manpages list-base: list-local-base list-manpages: list-local-manpages libreswan-3.32/mk/tests.sh000077500000000000000000000013541365625662500155620ustar00rootroot00000000000000#!/bin/sh -eux # A script to put various build sequences through their paces. j=-j$(grep ^processor /proc/cpuinfo | wc -l) echo make $j sleep 1 while read target do case "$target" in "#"* ) ;; * ) log=$(echo mk/make $target | tr '[ ]' '[_]') if test ! -r $log.log then rm -rf OBJ.* make $j $target | tee $log.tmp mv $log.tmp $log.log fi ;; esac done < # Copyright (C) 2015-2018 Andrew Cagney # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # -D... goes in here USERLAND_CFLAGS+=-std=gnu99 # # Options that really belong in CFLAGS (making for an intuitive way to # override them). # # Unfortunately this file is shared with the kernel which seems to # have its own ideas on CFLAGS. # DEBUG_CFLAGS?=-g USERLAND_CFLAGS+=$(DEBUG_CFLAGS) # eventually: -Wshadow -pedantic? WERROR_CFLAGS?=-Werror -Wno-missing-field-initializers USERLAND_CFLAGS+= $(WERROR_CFLAGS) WARNING_CFLAGS?=-Wall -Wextra -Wformat -Wformat-nonliteral -Wformat-security -Wundef -Wmissing-declarations -Wredundant-decls -Wnested-externs USERLAND_CFLAGS+= $(WARNING_CFLAGS) # _FORTIFY_SOURCE requires at least -O. Gentoo, pre-defines # _FORTIFY_SOURCE (to what? who knows!); force it to our preferred # value. OPTIMIZE_CFLAGS?=-O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 USERLAND_CFLAGS+=$(OPTIMIZE_CFLAGS) # Dumping ground for an arbitrary set of flags. Should probably be # separated out. USERCOMPILE?=-fstack-protector-all -fno-strict-aliasing -fPIE -DPIE USERLAND_CFLAGS+=$(USERCOMPILE) # Basic linking flags USERLINK?=-Wl,-z,relro,-z,now -pie USERLAND_LDFLAGS+=-Wl,--as-needed USERLAND_LDFLAGS+=$(USERLINK) $(ASAN) # Build/link against the more pedantic ElectricFence memory allocator; # used when testing. USE_EFENCE ?= false ifeq ($(USE_EFENCE),true) USERLAND_CFLAGS+=-DUSE_EFENCE USERLAND_LDFLAGS+=-lefence endif ifneq ($(EFENCE),) $(warning EFENCE=$(EFENCE) replaced by USE_EFENCE=true) endif # # Configuration options. # # Sometimes the make variable is called USE_ and the C macro # is called HAVE_, but not always. # # # Kernel support # # set in mk/defaults/*.mk # support Linux kernel's NETLINK_XFRM (aka XFRM/NETKEY) (aka "native") USE_NETKEY?=false # support Linux KLIPS kernel module (KLIPS requires PFKEYv2) USE_KLIPS?=false # support BSD/KAME kernels (on *BSD and OSX)? USE_BSDKAME?=false USE_XFRM_INTERFACE?=true ifeq ($(USE_NETKEY),true) USERLAND_CFLAGS+=-DNETKEY_SUPPORT ifeq ($(USE_XFRM_INTERFACE), true) USERLAND_CFLAGS+=-DUSE_XFRM_INTERFACE endif endif ifeq ($(USE_KLIPS),true) USERLAND_CFLAGS+=-DKLIPS USERLAND_CFLAGS+=-DPFKEY endif ifeq ($(USE_BSDKAME),true) USE_NETKEY?=false USE_KLIPS?=false endif ifeq ($(USE_BSDKAME),true) USERLAND_CFLAGS += -DBSD_KAME endif ifeq ($(USE_DNSSEC),true) USERLAND_CFLAGS+=-DUSE_DNSSEC UNBOUND_LDFLAGS ?= -lunbound -lldns DEFAULT_DNSSEC_ROOTKEY_FILE ?= "/var/lib/unbound/root.key" USERLAND_CFLAGS+=-DDEFAULT_DNSSEC_ROOTKEY_FILE=\"${DEFAULT_DNSSEC_ROOTKEY_FILE}\" endif ifeq ($(USE_FIPSCHECK),true) USERLAND_CFLAGS+=-DFIPS_CHECK USERLAND_CFLAGS+=-DFIPSPRODUCTCHECK=\"${FIPSPRODUCTCHECK}\" FIPSCHECK_LDFLAGS ?= -lfipscheck endif ifeq ($(USE_LABELED_IPSEC),true) USERLAND_CFLAGS+=-DHAVE_LABELED_IPSEC endif ifeq ($(USE_SECCOMP),true) USERLAND_CFLAGS+=-DHAVE_SECCOMP SECCOMP_LDFLAGS=-lseccomp endif ifeq ($(USE_LIBCURL),true) USERLAND_CFLAGS+=-DLIBCURL CURL_LDFLAGS ?= -lcurl endif # Build support for the Linux Audit system USE_LINUX_AUDIT ?= false ifeq ($(USE_LINUX_AUDIT),true) USERLAND_CFLAGS += -DUSE_LINUX_AUDIT LINUX_AUDIT_LDFLAGS ?= -laudit endif ifeq ($(USE_SYSTEMD_WATCHDOG),true) USERLAND_CFLAGS+=-DUSE_SYSTEMD_WATCHDOG SYSTEMD_WATCHDOG_LDFLAGS ?= -lsystemd endif ifeq ($(USE_LDAP),true) USERLAND_CFLAGS += -DLIBLDAP LDAP_LDFLAGS ?= -lldap -llber endif ifeq ($(USE_NM),true) USERLAND_CFLAGS+=-DHAVE_NM endif # Link with -lrt (only for glibc versions before 2.17) RT_LDFLAGS ?= -lrt # include PAM support for XAUTH when available on the platform USE_XAUTHPAM?=true ifeq ($(USE_XAUTHPAM),true) USERLAND_CFLAGS += -DXAUTH_HAVE_PAM XAUTHPAM_LDFLAGS ?= -lpam endif # # Algorithms (encryption, PRF, DH, ....) # # See https://tools.ietf.org/html/rfc8247 for what should be enabled # by default. # ALL_ALGS ?= false USE_3DES?=true ifeq ($(USE_3DES),true) USERLAND_CFLAGS+=-DUSE_3DES endif USE_AES ?= true ifeq ($(USE_AES),true) USERLAND_CFLAGS+=-DUSE_AES endif USE_CAST ?= $(ALL_ALGS) ifeq ($(USE_CAST),true) USERLAND_CFLAGS += -DUSE_CAST endif USE_CAMELLIA ?= true ifeq ($(USE_CAMELLIA),true) USERLAND_CFLAGS += -DUSE_CAMELLIA endif USE_CHACHA?=true ifeq ($(USE_CHACHA),true) USERLAND_CFLAGS+=-DUSE_CHACHA endif USE_DH2 ?= false ifeq ($(USE_DH2),true) USERLAND_CFLAGS+=-DUSE_DH2 endif USE_DH22 ?= $(ALL_ALGS) ifeq ($(USE_DH22),true) USERLAND_CFLAGS += -DUSE_DH22 endif USE_DH23 ?= $(ALL_ALGS) ifeq ($(USE_DH23),true) USERLAND_CFLAGS += -DUSE_DH23 endif USE_DH24 ?= $(ALL_ALGS) ifeq ($(USE_DH24),true) USERLAND_CFLAGS += -DUSE_DH24 endif USE_DH31 ?= true ifeq ($(USE_DH31),true) USERLAND_CFLAGS += -DUSE_DH31 endif USE_MD5 ?= true ifeq ($(USE_MD5),true) USERLAND_CFLAGS += -DUSE_MD5 endif USE_RIPEMD ?= $(ALL_ALGS) ifeq ($(USE_RIPEMD),true) USERLAND_CFLAGS += -DUSE_RIPEMD endif USE_SERPENT?=true ifeq ($(USE_SERPENT),true) USERLAND_CFLAGS += -DUSE_SERPENT LIBSERPENT = ${OBJDIRTOP}/lib/libcrypto/libserpent/libserpent.a endif USE_SHA1 ?= true ifeq ($(USE_SHA1),true) USERLAND_CFLAGS += -DUSE_SHA1 endif USE_SHA2 ?= true ifeq ($(USE_SHA2),true) USERLAND_CFLAGS += -DUSE_SHA2 endif USE_TWOFISH?=true ifeq ($(USE_TWOFISH),true) USERLAND_CFLAGS += -DUSE_TWOFISH LIBTWOFISH= ${OBJDIRTOP}/lib/libcrypto/libtwofish/libtwofish.a endif # Used mostly for IoT USE_PRF_AES_XCBC ?= true ifeq ($(USE_PRF_AES_XCBC),true) USERLAND_CFLAGS += -DUSE_PRF_AES_XCBC endif # Use the NSS Key Derivation Function (KDF) instead of using the NSS # secure hash functions to build our own PRF. With this enabled, # libreswan itself no longer needs to be FIPS validated. # # Requires NSS > 3.52 (3.44 up to 3.51 are missing one required KDF function) USE_NSS_PRF ?= false ifeq ($(USE_NSS_PRF),true) USERLAND_CFLAGS += -DUSE_NSS_PRF endif ifeq ($(USE_SINGLE_CONF_DIR),true) USERLAND_CFLAGS+=-DSINGLE_CONF_DIR=1 endif USERLAND_CFLAGS+=-DDEFAULT_RUNDIR=\"$(FINALRUNDIR)\" USERLAND_CFLAGS+=-DFIPSPRODUCTCHECK=\"${FIPSPRODUCTCHECK}\" USERLAND_CFLAGS+=-DIPSEC_CONF=\"$(FINALCONFFILE)\" USERLAND_CFLAGS+=-DIPSEC_CONFDDIR=\"$(FINALCONFDDIR)\" USERLAND_CFLAGS+=-DIPSEC_NSSDIR=\"$(FINALNSSDIR)\" USERLAND_CFLAGS+=-DIPSEC_CONFDIR=\"$(FINALCONFDIR)\" USERLAND_CFLAGS+=-DIPSEC_EXECDIR=\"$(FINALLIBEXECDIR)\" USERLAND_CFLAGS+=-DIPSEC_SBINDIR=\"${FINALSBINDIR}\" USERLAND_CFLAGS+=-DIPSEC_VARDIR=\"$(FINALVARDIR)\" USERLAND_CFLAGS+=-DPOLICYGROUPSDIR=\"${FINALCONFDDIR}/policies\" USERLAND_CFLAGS+=-DIPSEC_SECRETS_FILE=\"$(IPSEC_SECRETS_FILE)\" # Ensure that calls to NSPR's PR_ASSERT() really do abort. While all # calls should have been eliminated (replaced by passert()), keep this # definition just in case. USERLAND_CFLAGS+=-DFORCE_PR_ASSERT # stick with RETRANSMIT_INTERVAL_DEFAULT as makefile variable name ifdef RETRANSMIT_INTERVAL_DEFAULT USERLAND_CFLAGS+=-DRETRANSMIT_INTERVAL_DEFAULT_MS="$(RETRANSMIT_INTERVAL_DEFAULT)" endif ifeq ($(HAVE_BROKEN_POPEN),true) USERLAND_CFLAGS+=-DHAVE_BROKEN_POPEN endif # Do things like create a daemon using the sequence fork()+exit(). If # you don't have or don't want to use fork() disable this. USE_FORK ?= true ifeq ($(USE_FORK),true) USERLAND_CFLAGS += -DUSE_FORK=1 else USERLAND_CFLAGS += -DUSE_FORK=0 endif # Where possible use vfork() instead of fork(). For instance, when # creating a child process, use the call sequence vfork()+exec(). # # Systems with nommu, which do not have fork(), should set this. USE_VFORK ?= false ifeq ($(USE_VFORK),true) USERLAND_CFLAGS += -DUSE_VFORK=1 else USERLAND_CFLAGS += -DUSE_VFORK=0 endif # Where possible use daemon() instead of fork()+exit() to create a # daemon (detached) processes. # # Some system's don't support daemon() and some systems don't support # fork(). Since the daemon call can lead to a race it isn't the # preferred option. USE_DAEMON ?= false ifeq ($(USE_DAEMON),true) USERLAND_CFLAGS += -DUSE_DAEMON=1 else USERLAND_CFLAGS += -DUSE_DAEMON=0 endif # OSX, for instance, doesn't have this call. USE_PTHREAD_SETSCHEDPRIO ?= true ifeq ($(USE_PTHREAD_SETSCHEDPRIO),true) USERLAND_CFLAGS += -DUSE_PTHREAD_SETSCHEDPRIO=1 else USERLAND_CFLAGS += -DUSE_PTHREAD_SETSCHEDPRIO=0 endif ifeq ($(origin GCC_LINT),undefined) GCC_LINT=-DGCC_LINT endif USERLAND_CFLAGS+=$(GCC_LINT) # Enable ALLOW_MICROSOFT_BAD_PROPOSAL USERLAND_CFLAGS+=-DALLOW_MICROSOFT_BAD_PROPOSAL # some systems require -lcrypt when calling crypt() some do not. CRYPT_LDFLAGS ?= -lcrypt # Support for LIBCAP-NG to drop unneeded capabilities for the pluto daemon USE_LIBCAP_NG?=true ifeq ($(USE_LIBCAP_NG),true) USERLAND_CFLAGS += -DHAVE_LIBCAP_NG LIBCAP_NG_LDFLAGS ?= -lcap-ng endif libreswan-3.32/mk/version.mk000066400000000000000000000000261365625662500160720ustar00rootroot00000000000000IPSECBASEVERSION=3.32 libreswan-3.32/mk/web-targets.mk000066400000000000000000000250001365625662500166300ustar00rootroot00000000000000# WEB make targets, for Libreswan # # Copyright (C) 2017-2018 Andrew Cagney # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # If the $(LSW_WEBDIR) directory exists, publish the results in # HTML/json form. # # Because web-page dependencies are very heavy (invoking git et.al.) # much of this code needs to be made conditional. LSW_WEBDIR ?= $(top_srcdir)/RESULTS WEB_SUMMARYDIR ?= $(LSW_WEBDIR) ifneq ($(wildcard $(WEB_SUMMARYDIR)),) WEB_ENABLED ?= true endif WEB_UTILSDIR ?= testing/utils WEB_SOURCEDIR ?= testing/web WEB_REPODIR ?= . # these are verbose so multiple invocations can be spotted WEB_SUBDIR ?= $(shell $(WEB_SOURCEDIR)/gime-git-description.sh $(WEB_REPODIR)) # shortcuts to use when web is enabled, set up to evaluate once as # they can be a little expensive. These make variable can only be # used inside of WEB_ENABLED blocks. ifdef WEB_ENABLED ifndef WEB_HASH WEB_HASH := $(shell cd $(WEB_REPODIR) ; git show --no-patch --format=%H HEAD) endif ifndef WEB_RESULTSDIR WEB_RESULTSDIR := $(WEB_SUMMARYDIR)/$(WEB_SUBDIR) endif ifndef WEB_SOURCES WEB_SOURCES := $(wildcard $(addprefix $(WEB_SOURCEDIR)/, *.css *.js *.html)) endif ifndef WEB_TIME WEB_TIME := $(shell $(WEB_SOURCEDIR)/now.sh) endif ifndef WEB_TESTSDIR WEB_TESTSDIR := $(WEB_SUMMARYDIR)/tests endif endif # # Force the creation and/or update of the web pages # # Since $(WEB_SUMMARYDIR) (aka $(LSW_WEBDIR)) is created (via a # dependency) before invoking the sub-$(MAKE), the sub-$(MAKE) will # always see a configuration where web pages are enabled. # # Order matters: the results directory is created first so that so # that the web-summarydir will pick up its contents. web web-page: | $(WEB_SUMMARYDIR) $(MAKE) web-resultsdir web-summarydir $(WEB_SUMMARYDIR): mkdir $(WEB_SUMMARYDIR) # # Build or update the web pages ready for a new test run # # For the results directory, just install the HTML / javascript files # (kvmrunner.py will fill in all the json files). For the summary # directory, do a full update so that all the previous runs are # included. .PHONY: web-test-prep web-test-post web-page web web-test-prep: web-test-post: ifdef WEB_ENABLED web-test-prep: web-results-html web-summarydir web-testsdir web-test-post: web-tests-json endif # # Update the web site # # Well almost everything, result .json files are not updated by # default - very slow. # .PHONY: web-site web-site: # # Create or update just the summary web page. # # This is a cheap short-cut that, unlike "web", doesn't update the # sub-directory's html. # .PHONY: web-summarydir web-summarydir: # # Create or update a test run's results page. # .PHONY: web-resultsdir web-resultsdir: # # Create the tests directory # ifdef WEB_ENABLED web-testsdir: | $(WEB_TESTSDIR) $(WEB_TESTSDIR): mkdir $@ .PHONY: web-tests-json: $(WEB_SOURCEDIR)/json-tests.sh $(WEB_REPODIR) $(WEB_TESTSDIR) $(WEB_RESULTSDIR) endif # # Create or update just the summary web page. # # This is a cheap short-cut that, unlike "web", doesn't update the # sub-directory's html. # ifdef WEB_ENABLED .PHONY: web-summary-html web-site web-summarydir: web-summary-html web-summary-html: $(WEB_SUMMARYDIR)/index.html $(WEB_SUMMARYDIR)/index.html: $(WEB_SOURCES) $(WEB_SUMMARYDIR)/tsconfig.json | $(WEB_SUMMARYDIR) tsc --project $(WEB_SUMMARYDIR)/tsconfig.json cp $(filter-out %.js, $(WEB_SOURCES)) $(WEB_SUMMARYDIR) cp $(WEB_SOURCEDIR)/summary.html $(WEB_SUMMARYDIR)/index.html endif # # Update the pooled summary (summaries.json) of all the test runs # # Note that $(WEB_SUMMARYDIR) may be a soft-link. # # Because the number of summaries can get large a FIND and not a GLOB # is used to generate the list. ifdef WEB_ENABLED .PHONY: web-summaries-json web-site web-summarydir web-summaries-json: $(WEB_SUMMARYDIR)/summaries.json $(WEB_SUMMARYDIR)/summaries.json: $(wildcard $(WEB_SUMMARYDIR)/*/summary.json) $(WEB_SOURCEDIR)/json-summaries.sh : -H - follow any $(WEB_SUMMARYDIR) link : -maxdepth 2 - stop before $(WEB_SUMMARYDIR)/*/*/ find -H $(WEB_SUMMARYDIR) \ -maxdepth 2 \ \( -type f -name summary.json -print \) \ | $(WEB_SOURCEDIR)/json-summaries.sh $(WEB_REPODIR) - > $@.tmp mv $@.tmp $@ endif # # update the status.json # # no dependencies, just ensure it exists. ifdef WEB_ENABLED .PHONY: web-status-json web-site web-summarydir web-status-json: $(WEB_SUMMARYDIR)/status.json $(WEB_SUMMARYDIR)/status.json: $(WEB_SOURCEDIR)/json-status.sh "initialized" > $@.tmp mv $@.tmp $@ endif # # Update the commits.json database # # Since identifying all commits.json's dependencies is expensive - it # depends on parsing WEB_SUMMARYDIR and WEB_REPODIR - it is # implemented as a recursive make target - that way the computation is # only done when needed. # # Should the generation script be modified then this will trigger a # rebuild of all relevant commits. # # In theory, all the .json files needing an update can be processed # using a single make invocation. Unfortunately the list can get so # long that it exceeds command line length limits, so a slow pipe is # used instead. ifdef WEB_ENABLED WEB_COMMITSDIR = $(WEB_SUMMARYDIR)/commits FIRST_COMMIT = $(shell $(WEB_SOURCEDIR)/earliest-commit.sh $(WEB_SUMMARYDIR) $(WEB_REPODIR)) .PHONY: web-commits-json $(WEB_SUMMARYDIR)/commits.json web-site web-summarydir web-commits-json: $(WEB_SUMMARYDIR)/commits.json $(WEB_SUMMARYDIR)/commits.json: web-commitsdir : pick up all commits unconditionally and unsorted. find $(WEB_COMMITSDIR) -name '*.json' \ | xargs --no-run-if-empty cat \ | jq -s 'unique_by(.hash)' > $@.tmp mv $@.tmp $@ .PHONY: web-commitsdir web-commitsdir: | $(WEB_COMMITSDIR) : -s suppresses the sub-make message ... is up to date : watch out for the sub-make re-valuating make variables ( cd $(WEB_REPODIR) && git rev-list $(FIRST_COMMIT)^.. ) \ | awk '{print "$(WEB_COMMITSDIR)/" $$1 ".json"}' \ | xargs --no-run-if-empty \ $(MAKE) --no-print-directory -s $(WEB_COMMITSDIR)/%.json: $(WEB_SOURCEDIR)/json-commit.sh | $(WEB_COMMITSDIR) echo $@ $(WEB_SOURCEDIR)/json-commit.sh $* $(WEB_REPODIR) > $@.tmp mv $@.tmp $@ $(WEB_COMMITSDIR): mkdir $(WEB_COMMITSDIR) endif # # Update the html in all the result directories # # Not part of web-summarydir, web-resultsdir or web-results-html ifdef WEB_ENABLED WEB_RESULTS_HTML = $(wildcard $(WEB_SUMMARYDIR)/*-g*/results.html) web-site: $(WEB_RESULTS_HTML) $(WEB_SUMMARYDIR)/%/results.html: $(WEB_SOURCES) $(MAKE) web-resultsdir \ WEB_SUMMARYDIR=$(WEB_SUMMARYDIR) WEB_RESULTSDIR=$(dir $@) endif # # Conditional rules for building an individual test run's results # page. Requires WEB_SUMMARYDIR or WEB_RESULTSDIR. # ifdef WEB_ENABLED .PHONY: web-resultsdir web-results-html web-results-json web-resultsdir: web-results-html web-results-json web-results-html: $(WEB_RESULTSDIR)/index.html web-results-json: $(WEB_RESULTSDIR)/summary.json $(WEB_RESULTSDIR)/index.html: $(WEB_SOURCES) $(WEB_RESULTSDIR)/tsconfig.json | $(WEB_RESULTSDIR) tsc --project $(WEB_RESULTSDIR)/tsconfig.json cp $(filter-out %.js, $(WEB_SOURCES)) $(WEB_RESULTSDIR) cp $(WEB_SOURCEDIR)/results.html $(WEB_RESULTSDIR)/index.html $(WEB_RESULTSDIR)/summary.json: | $(WEB_RESULTSDIR) $(WEB_UTILSDIR)/kvmresults.py \ --exit-ok \ --quick \ --test-kind '' \ --test-status '' \ --publish-summary $@.tmp \ --publish-status $(WEB_SUMMARYDIR)/status.json \ --publish-results $(WEB_RESULTSDIR) \ --publish-hash $(WEB_HASH) \ testing/pluto mv $@.tmp $@ %/tsconfig.json: $(WEB_SOURCEDIR)/tsconfig.json.in mk/web-targets.mk | % sed -e 's;@@DEST_DIR@@;$(realpath $(dir $@));' \ -e 's;@@SOURCE_DIR@@;$(realpath $(WEB_SOURCEDIR));' \ $(WEB_SOURCEDIR)/tsconfig.json.in \ > $@.tmp mv $@.tmp $@ $(WEB_RESULTSDIR): | $(WEB_SUMMARYDIR) mkdir $(WEB_RESULTSDIR) endif # # update the json in all the results directories; very slow so only # enabled when WEB_SCRATCH_REPODIR is set and things are not pointing # at this directory. # ifdef WEB_ENABLED ifdef WEB_SCRATCH_REPODIR ifneq ($(abspath $(WEB_SCRATCH_REPODIR)),$(abspath .)) .PHONY: web-results-json web-site web-results-json: $(sort $(wildcard $(WEB_SUMMARYDIR)/*-g*/results.json)) $(WEB_SUMMARYDIR)/%/results.json: $(WEB_UTILSDIR)/kvmresults.py $(WEB_UTILSDIR)/fab/*.py $(WEB_SOURCEDIR)/json-results.sh $(WEB_SCRATCH_REPODIR) $(dir $@) endif endif endif # # Equivalent of help # define web-config Web Configuration: The test results can be published as a web page using either of the make variables: $(call kvm-var-value,LSW_WEBDIR) $(call kvm-var-value,WEB_SUMMARYDIR) The top-level html directory containing a summary of all test runs. The results from individual test runs are stored under this directory. $(call kvm-var-value,WEB_SUBDIR) $(call kvm-var-value,WEB_RESULTSDIR) Sub-directory to store the current test run's results. By default, the test run's results are stored as the sub-directory $$(WEB_SUBDIR) under $$(WEB_SUMMARYDIR), and $$(WEB_SUBDIR) is formatted as TAG-OFFSET-gREV-BRANCH using information from $$(WEB_REPODIR)'s current commit (see also `git describe --long`). $(call kvm-var-value,WEB_REPODIR) The git repository to use when constructing the web pages (for instance the list of commits). By default, the current directory is used. Internal targets: web-site: update the web site web-results-html: update the HTML files in all the test run sub-directories under $$(WEB_SUMMARYDIR) web-commits-json: update the commits.json file in $$(WEB_SUMMARYDIR) web-results-json: update the results.json in all the test run sub-directories under $$(WEB_SUMMARYDIR) very slow requires $$(WEB_SCRATCH_REPODIR) set and pointing at a dedicated git repository Web targets: web-summarydir: build or update the top-level summary web page under $$(WEB_SUMMARYDIR) (the test run sub-directories are not updated, see above). web-resultsdir: build or update $$(WEB_RESULTSDIR) web-page: build or update the web page in $(LSW_WEBDIR) including the results from the most recent test run endef .PHONY: web-config web-help web-config web-help: $(info $(web-config)) libreswan-3.32/nat-t/000077500000000000000000000000001365625662500144725ustar00rootroot00000000000000libreswan-3.32/nat-t/include/000077500000000000000000000000001365625662500161155ustar00rootroot00000000000000libreswan-3.32/nat-t/include/net/000077500000000000000000000000001365625662500167035ustar00rootroot00000000000000libreswan-3.32/nat-t/include/net/sock.h.fs2_2.patch000066400000000000000000000007351365625662500220300ustar00rootroot00000000000000--- linux/include/net/sock.h Fri Nov 2 17:39:16 2001 +++ linux/include/net/sock.h Mon Jun 10 19:44:55 2002 @@ -201,6 +201,12 @@ __u32 end_seq; }; +#if 1 +struct udp_opt { + __u32 esp_in_udp; +}; +#endif + struct tcp_opt { int tcp_header_len; /* Bytes of tcp header to send */ @@ -443,6 +449,9 @@ #if defined(CONFIG_SPX) || defined (CONFIG_SPX_MODULE) struct spx_opt af_spx; #endif /* CONFIG_SPX */ +#if 1 + struct udp_opt af_udp; +#endif } tp_pinfo; libreswan-3.32/nat-t/include/net/sock.h.fs2_4.patch000066400000000000000000000010231365625662500220210ustar00rootroot00000000000000--- linux/include/net/sock.h 2002/02/06 15:25:10 1.1 +++ linux/include/net/sock.h 2002/05/22 12:14:56 @@ -488,7 +488,13 @@ } bictcp; }; - +#if 1 +#define UDP_OPT_IN_SOCK 1 +struct udp_opt { + __u32 esp_in_udp; +}; +#endif + /* * This structure really needs to be cleaned up. * Most of it is for TCP, and not used by any of @@ -655,6 +661,9 @@ #if defined(CONFIG_SPX) || defined (CONFIG_SPX_MODULE) struct spx_opt af_spx; #endif /* CONFIG_SPX */ +#if 1 + struct udp_opt af_udp; +#endif } tp_pinfo; libreswan-3.32/nat-t/include/net/xfrmudp.h.os2_6000066400000000000000000000006411365625662500214710ustar00rootroot00000000000000/* * pointer to function for type that xfrm4_input wants, to permit * decoupling of XFRM from udp.c */ #define HAVE_XFRM4_UDP_REGISTER typedef int (*xfrm4_rcv_encap_t)(struct sk_buff *skb, __u16 encap_type); extern int udp4_register_esp_rcvencap(xfrm4_rcv_encap_t func , xfrm4_rcv_encap_t *oldfunc); extern int udp4_unregister_esp_rcvencap(xfrm4_rcv_encap_t func , xfrm4_rcv_encap_t oldfunc); libreswan-3.32/nat-t/net/000077500000000000000000000000001365625662500152605ustar00rootroot00000000000000libreswan-3.32/nat-t/net/Config.in.fs2_4.patch000066400000000000000000000003061365625662500210260ustar00rootroot00000000000000--- linux/net/Config.in.orig Fri Feb 9 14:34:13 2001 +++ linux/net/Config.in Thu Feb 22 19:40:08 2001 @@ -88,3 +88,5 @@ endmenu +bool 'IPSEC NAT-Traversal' CONFIG_IPSEC_NAT_TRAVERSAL + endmenu libreswan-3.32/nat-t/net/ipv4/000077500000000000000000000000001365625662500161425ustar00rootroot00000000000000libreswan-3.32/nat-t/net/ipv4/Kconfig.os2_6.patch000066400000000000000000000005751365625662500215010ustar00rootroot00000000000000--- /distros/kernel/linux-2.6.11.2/net/ipv4/Kconfig 2005-03-09 03:12:33.000000000 -0500 +++ swan26/net/ipv4/Kconfig 2005-04-04 18:46:13.000000000 -0400 @@ -351,2 +351,8 @@ +config IPSEC_NAT_TRAVERSAL + bool "IPSEC NAT-Traversal (KLIPS compatible)" + depends on INET + ---help--- + Includes support for RFC3947/RFC3948 NAT-Traversal of ESP over UDP. + config IP_TCPDIAG libreswan-3.32/nat-t/net/ipv4/udp.c.fs2_2.patch000066400000000000000000000050121365625662500211040ustar00rootroot00000000000000--- linux/net/ipv4/udp.c Sun Mar 25 18:37:41 2001 +++ linux/net/ipv4/udp.c Mon Jun 10 19:53:18 2002 @@ -965,6 +965,9 @@ static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) { +#ifdef CONFIG_IPSEC_NAT_TRAVERSAL + struct udp_opt *tp = &(sk->tp_pinfo.af_udp); +#endif /* * Charge it to the socket, dropping if the queue is full. */ @@ -982,3 +985,14 @@ } #endif +#ifdef CONFIG_IPSEC_NAT_TRAVERSAL + if (tp->esp_in_udp) { + /* + * Set skb->sk and xmit packet to ipsec_rcv. + * + * If ret != 0, ipsec_rcv refused the packet (not ESPinUDP), + * restore skb->sk and fall back to sock_queue_rcv_skb + */ + struct inet_protocol *esp = NULL; + +#if defined(CONFIG_KLIPS) && !defined(CONFIG_KLIPS_MODULE) * /* optomize only when we know it is statically linked */ + extern struct inet_protocol esp_protocol; + esp = &esp_protocol; +#else + for (esp = (struct inet_protocol *)inet_protos[IPPROTO_ESP & (MAX_INET_PROTOS - 1)]; + (esp) && (esp->protocol != IPPROTO_ESP); + esp = esp->next); +#endif + + if (esp && esp->handler) { + struct sock *sav_sk = skb->sk; + skb->sk = sk; + if (esp->handler(skb, 0) == 0) { + skb->sk = sav_sk; + /* not sure we might count ESPinUDP as UDP... */ + udp_statistics.UdpInDatagrams++; + return 0; + } + skb->sk = sav_sk; + } + } +#endif if (sock_queue_rcv_skb(sk,skb)<0) { udp_statistics.UdpInErrors++; ip_statistics.IpInDiscards++; @@ -1165,6 +1200,44 @@ return(0); } +#if 1 +static int udp_setsockopt(struct sock *sk, int level, int optname, + char *optval, int optlen) +{ + struct udp_opt *tp = &(sk->tp_pinfo.af_udp); + int val; + int err = 0; + + if (level != SOL_UDP) + return ip_setsockopt(sk, level, optname, optval, optlen); + + if(optlenesp_in_udp = val; + break; +#endif + default: + err = -ENOPROTOOPT; + break; + } + + release_sock(sk); + return err; +} +#endif + struct proto udp_prot = { (struct sock *)&udp_prot, /* sklist_next */ (struct sock *)&udp_prot, /* sklist_prev */ @@ -1179,7 +1252,11 @@ NULL, /* init */ NULL, /* destroy */ NULL, /* shutdown */ +#if 1 + udp_setsockopt, /* setsockopt */ +#else ip_setsockopt, /* setsockopt */ +#endif ip_getsockopt, /* getsockopt */ udp_sendmsg, /* sendmsg */ udp_recvmsg, /* recvmsg */ libreswan-3.32/nat-t/net/ipv4/udp.c.fs2_4.patch000066400000000000000000000045731365625662500211210ustar00rootroot00000000000000--- linux/net/ipv4/udp.c.1 Wed Jan 28 15:57:05 2004 +++ linux/net/ipv4/udp.c Wed Jan 28 15:58:56 2004 @@ -787,6 +787,9 @@ static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) { +#ifdef CONFIG_IPSEC_NAT_TRAVERSAL + struct udp_opt *tp = &(sk->tp_pinfo.af_udp); +#endif /* * Charge it to the socket, dropping if the queue is full. */ @@ -804,6 +807,40 @@ } #endif +#ifdef CONFIG_IPSEC_NAT_TRAVERSAL + if (tp->esp_in_udp) { + /* + * Set skb->sk and xmit packet to ipsec_rcv. + * + * If ret != 0, ipsec_rcv refused the packet (not ESPinUDP), + * restore skb->sk and fall back to sock_queue_rcv_skb + */ + struct inet_protocol *esp = NULL; + +#if defined(CONFIG_KLIPS) && !defined(CONFIG_KLIPS_MODULE) + /* optomize only when we know it is statically linked */ + extern struct inet_protocol esp_protocol; + esp = &esp_protocol; +#else + for (esp = (struct inet_protocol *)inet_protos[IPPROTO_ESP & (MAX_INET_PROTOS - 1)]; + (esp) && (esp->protocol != IPPROTO_ESP); + esp = esp->next); +#endif + + if (esp && esp->handler) { + struct sock *sav_sk = skb->sk; + skb->sk = sk; + if (esp->handler(skb) == 0) { + skb->sk = sav_sk; + /*not sure we might count ESPinUDP as UDP...*/ + UDP_INC_STATS_BH(UdpInDatagrams); + return 0; + } + skb->sk = sav_sk; + } + } +#endif + if (sock_queue_rcv_skb(sk,skb)<0) { UDP_INC_STATS_BH(UdpInErrors); IP_INC_STATS_BH(IpInDiscards); @@ -1027,13 +1064,49 @@ return len; } +static int udp_setsockopt(struct sock *sk, int level, int optname, + char *optval, int optlen) +{ + struct udp_opt *tp = &(sk->tp_pinfo.af_udp); + int val; + int err = 0; + + if (level != SOL_UDP) + return ip_setsockopt(sk, level, optname, optval, optlen); + + if(optlenesp_in_udp = val; + break; +#endif + default: + err = -ENOPROTOOPT; + break; + } + + release_sock(sk); + return err; +} + struct proto udp_prot = { name: "UDP", close: udp_close, connect: udp_connect, disconnect: udp_disconnect, ioctl: udp_ioctl, - setsockopt: ip_setsockopt, + setsockopt: udp_setsockopt, getsockopt: ip_getsockopt, sendmsg: udp_sendmsg, recvmsg: udp_recvmsg, libreswan-3.32/nat-t/net/ipv4/udp.c.os2_6.patch000066400000000000000000000050101365625662500211170ustar00rootroot00000000000000--- plain26/net/ipv4/udp.c.orig 2006-12-28 20:53:17.000000000 -0500 +++ plain26/net/ipv4/udp.c 2007-05-11 10:22:50.000000000 -0400 @@ -108,6 +108,7 @@ #include #include #include +#include /* * Snmp MIB for the UDP layer @@ -881,6 +882,31 @@ sk_common_release(sk); } +#if defined(CONFIG_XFRM) || defined(CONFIG_IPSEC_NAT_TRAVERSAL) + +static xfrm4_rcv_encap_t xfrm4_rcv_encap_func = NULL; +int udp4_register_esp_rcvencap(xfrm4_rcv_encap_t func + , xfrm4_rcv_encap_t *oldfunc) +{ + if(oldfunc != NULL) { + *oldfunc = xfrm4_rcv_encap_func; + } + + xfrm4_rcv_encap_func = func; + return 0; +} + +int udp4_unregister_esp_rcvencap(xfrm4_rcv_encap_t func, xfrm4_rcv_encap_t old) +{ + if(xfrm4_rcv_encap_func != func) + return -1; + + xfrm4_rcv_encap_func = old; + return 0; +} +#endif /* CONFIG_XFRM_MODULE || CONFIG_IPSEC_NAT_TRAVERSAL */ + + /* return: * 1 if the the UDP system should process it * 0 if we should drop this packet @@ -888,9 +914,9 @@ */ static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb) { -#ifndef CONFIG_XFRM +#if !defined(CONFIG_XFRM) && !defined(CONFIG_IPSEC_NAT_TRAVERSAL) return 1; -#else +#else /* either CONFIG_XFRM or CONFIG_IPSEC_NAT_TRAVERSAL */ struct udp_sock *up = udp_sk(sk); struct udphdr *uh; struct iphdr *iph; @@ -1018,10 +1044,27 @@ return 0; } if (ret < 0) { - /* process the ESP packet */ - ret = xfrm4_rcv_encap(skb, up->encap_type); - UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS); - return -ret; + if(xfrm4_rcv_encap_func != NULL) + ret = (*xfrm4_rcv_encap_func)(skb, up->encap_type); + + switch(ret) { + case 1: + /* FALLTHROUGH to send-up */; + break; + + case 0: + /* PROCESSED, free it */ + UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS); + return 0; + + case -1: + /* PACKET wasn't for _func, or no func, pass it + * to stock function + */ + ret = xfrm4_rcv_encap(skb, up->encap_type); + UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS); + return -ret; + } } /* FALLTHROUGH -- it's a UDP Packet */ } @@ -1110,7 +1153,6 @@ /* * All we need to do is get the socket, and then do a checksum. */ - int udp_rcv(struct sk_buff *skb) { struct sock *sk; @@ -1599,3 +1641,9 @@ EXPORT_SYMBOL(udp_proc_register); EXPORT_SYMBOL(udp_proc_unregister); #endif + +#if defined(CONFIG_IPSEC_NAT_TRAVERSAL) +EXPORT_SYMBOL(udp4_register_esp_rcvencap); +EXPORT_SYMBOL(udp4_unregister_esp_rcvencap); +#endif + libreswan-3.32/packaging/000077500000000000000000000000001365625662500153735ustar00rootroot00000000000000libreswan-3.32/packaging/centos000077700000000000000000000000001365625662500174612rhelustar00rootroot00000000000000libreswan-3.32/packaging/debian/000077500000000000000000000000001365625662500166155ustar00rootroot00000000000000libreswan-3.32/packaging/debian/90-libreswan.preset000066400000000000000000000002211365625662500222500ustar00rootroot00000000000000# Libreswan IPsec daemon needs to be configured before enabling. # See /usr/share/doc/libreswan/README.Debian for details. disable ipsec.service libreswan-3.32/packaging/debian/README.Debian000066400000000000000000000046421365625662500206640ustar00rootroot00000000000000libreswan for Debian -------------------- 1) General Remarks This package has been created by dkg with some reference/guidance from previous packaging work by several other packagers of both libreswan and other historical *swan projects (freeswan, openswan, etc). 2) System "ipsec" service is disabled by default This package ships with the system service disabled by default. After any configuration (see ipsec.conf(5) and ipsec.secrets(5)), you can start the service for the current boot with: systemctl start ipsec If you want to make the service start at every boot, do: systemctl enable ipsec Future versions may enable the service by default if a sufficiently-robust, configuration-free opportunistic mode is available. 3) Opportunistic Encryption To set up opportunistic encryption, you may want to make use of /usr/share/doc/libreswan/examples/oe-upgrade-authnull.conf You can see what associations have been created with: ipsec whack --trafficstatus See also: https://libreswan.org/wiki/HOWTO:_Opportunistic_IPsec 4) Raw RSA key creation Raw RSA keys can be generated with ipsec newhostkey To display the key identifier of the key for use in leftrsasigkey/rightrsasigkey in the "conn" section of ipsec.conf, use: ipsec showhostkey --left (or --right) For further information please take a closer look at the manpages ipsec_rsasigkey, ipsec.secrets, ipsec_showhostkey and ipsec.conf. 5) X.509 and secret key support uses /var/lib/ipsec/nss All certificate material, including CA certificates, CRLs and private keys are now stored in the NSS database in /var/lib/ipsec/nss When migrating from pre-NSS openswan, the files from /etc/ipsec.d/private, /etc/ipsec.d/cacerts, /etc/ipsec.d/crls and /etc/ipsec.d/certs need to be imported into NSS using certutil, crlutil or pk12util. For more information see https://libreswan.org/wiki/Using_NSS_with_libreswan Please keep in mind that upstream documentation assumes that the NSS database is stored in /etc/ipsec.d instead of /var/lib/ipsec/nss, and translate accordingly! Debian uses /var/lib/ipsec/nss to avoid clutter in /etc/ipsec.d, for easier cleanup, and to follow the FHS. 6) IPsec Kernel Support Note: This package uses the in-kernel IPsec stack, which is available in all recent stock Debian kernel images. This packaging does not currently support KLIPS or KLIPS/MAST. -- Daniel Kahn Gillmor , Wed, 22 Jun 2016 17:58:47 -0400 libreswan-3.32/packaging/debian/TODO000066400000000000000000000021071365625662500173050ustar00rootroot00000000000000Notes about possible future directions in libreswan debian packaging ==================================================================== Service status at package installation -------------------------------------- libreswan currently ships with an ipsec.service, which is deliberately not enabled by default, since it is usually meaningless to enable such a service without manual configuration. The configuration necessary is probably too complex to put sanely into debconf. If an opportunistic/no-configuration-needed mode is functional and well-tested enough to run without configuration, we may enable the service by default in future versions. Integration with non-systemd initsystems ---------------------------------------- The Debian packaging currently only supports integration with systemd. It looks like upstream's sysvinit support is relatively untested, and other initsystems are not supported upstream at all. If anyone wants to test and help maintain support for alternate initsystems (possibly in a separate binary package, e.g. libreswan-runit) that would be welcome! libreswan-3.32/packaging/debian/changelog000066400000000000000000000002001365625662500204570ustar00rootroot00000000000000libreswan (3.32-1); urgency=low * Release 3.32-1 -- Unknown User Mon, 30 Mar 2020 01:00:00 +0200 libreswan-3.32/packaging/debian/compat000066400000000000000000000000031365625662500200140ustar00rootroot0000000000000010 libreswan-3.32/packaging/debian/control000066400000000000000000000040361365625662500202230ustar00rootroot00000000000000Source: libreswan Section: net Priority: optional Maintainer: Libreswan Dev List Uploaders: Paul Wouters , Vcs-Browser: https://github.com/libreswan/libreswan Vcs-Git: https://github.com/libreswan/libreswan Standards-Version: 4.1.0 # Rules-Requires-Root: no # breaks jessie # libunbound-dev (>= 1.6.5~) # this is not yet Build-Depends: bison, bzip2, debhelper (>= 9), dh-systemd, flex, htmldoc, libaudit-dev [linux-any], libcap-ng-dev [linux-any], libcurl4-nss-dev, libevent-dev, libkrb5-dev, libldap2-dev, libldns-dev, libnspr4-dev, libnss3-dev (>= 3.16.1), libnss3-tools, libpam0g-dev, libselinux1-dev [linux-any], libsystemd-dev, libunbound-dev, man2html, pkg-config, po-debconf, systemd, xmlto, Homepage: https://libreswan.org/ Package: libreswan Architecture: any Pre-Depends: debconf | debconf-2.0, Depends: bsdmainutils, dns-root-data, bind9-host, iproute2, iptables, libnspr4, libnss3 (>= 3.16), libnss3-tools, systemd, ${misc:Depends}, ${shlibs:Depends}, Recommends: python3, Provides: ike-server, Conflicts: ike-server, strongswan-libcharon, strongswan-starter, Replaces: ike-server, Description: Internet Key Exchange daemon Libreswan is an IPsec implementation for Linux. It has support for most of the extensions (RFC + IETF drafts) related to IPsec, including IKEv2, X.509 Digital Certificates, NAT Traversal, and many others. . Libreswan has been forked from Openswan 2.6.38, which was forked from FreeS/WAN 2.04. . The Libreswan IKE daemon is named pluto. It was inherited from the FreeS/WAN project, but provides improved X.509 certificate support and other features. Package: libreswan-dbg Architecture: any Section: debug Priority: optional Depends: libreswan (= ${binary:Version}), ${misc:Depends} Description: Internet Key Exchange daemon - debugging symbols Libreswan is an IPsec based VPN solution for the Linux kernel. Both IKEv1 and IKEv2 protocols are supported. . This package provides the symbols needed for debugging of libreswan binaries. libreswan-3.32/packaging/debian/copyright000066400000000000000000000275601365625662500205620ustar00rootroot00000000000000Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: libreswan Upstream-Contact: The Libreswan Project Source: https://download.libreswan.org/ Comment: Security contact: security@libreswan.org Libreswan derives its copyright from Openswan. See CREDITS.openswan Openswan derives its copyright from FreeS/WAN. See CREDITS.freeswan Files: * Copyright: 1998-2016 The Libreswan Project or their individual authors License: GPL-2+ Files: programs/pluto/udpfromto.c Copyright: 2001 Miquel van Smoorenburg 2003 Jan Berkel License: LGPL-2.1+ Files: lib/libcrypto/libserpent/* lib/libswan/initsaid.c lib/libswan/initsubnet.c lib/libswan/internal.h lib/libswan/iprange.c lib/libswan/keyblobtoid.c lib/libswan/pfkey_error.c lib/libswan/pfkey_sock.c lib/libswan/rangetosubnet.c lib/libswan/sameaddr.c lib/libswan/sanitizestring.c lib/libswan/satoa.c lib/libswan/subnettot.c lib/libswan/subnettypeof.c lib/libswan/ttoaddr.c lib/libswan/ttodata.c lib/libswan/ttorange.c lib/libswan/ttosa.c lib/libswan/ttosubnet.c lib/libswan/ttoul.c Copyright: 1998-2002 Henry Spencer 1998-2002 D. Hugh Redelmeier 2000 Gisle Sælensminde 2003,2006 Michael Richardson 2013 Antony Antony 2016 Andrew Cagney License: LGPL-2+ Files: linux/include/zlib/* linux/net/ipsec/zutil.c linux/net/ipsec/infutil.c linux/net/ipsec/infutil.h linux/net/ipsec/inflate.c linux/net/ipsec/infcodes.c linux/net/ipsec/infcodes.h linux/net/ipsec/deflate.c linux/net/ipsec/deflate.h linux/net/ipsec/trees.c linux/net/ipsec/infblock.c linux/net/ipsec/inffast.c linux/net/ipsec/infblock.h linux/net/ipsec/inffast.h linux/net/ipsec/inftrees.c linux/net/ipsec/inftrees.h linux/net/ipsec/adler32.c Copyright: 1995-2002 Jean-loup Gailly and Mark Adler License: J-lG-MA-3-clause This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. . Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: . 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. . Jean-loup Gailly Mark Adler jloup@gzip.org madler@alumni.caltech.edu Files: linux/include/libreswan/radij.h linux/net/ipsec/radij.c Copyright: 1983, 1987, 1988, 1989, 1990, 1991, 1993, 1994, 1996 The Regents of the University of California. All rights reserved. License: BSD-4-clause 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. All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by the University of California, Berkeley and its contributors. 4. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. . THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Files: include/libbsdkame/libpfkey.h lib/libbsdpfkey/* Copyright: 1995, 1996, 1997, 1998, and 1999 WIDE Project. License: BSD-3-clause 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. Neither the name of the project nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. . THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Files: linux/include/des/* linux/include/klips-crypto/des.h linux/net/ipsec/des/cbc_enc.c linux/net/ipsec/des/des_enc.c linux/net/ipsec/des/des_opts.c linux/net/ipsec/des/ecb_enc.c linux/net/ipsec/des/set_key.c Copyright: 1995-1998 Eric Young License: OpenSSL Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) All rights reserved. . This package is an SSL implementation written by Eric Young (eay@cryptsoft.com). The implementation was written so as to conform with Netscapes SSL. . This library is free for commercial and non-commercial use as long as the following conditions are adhered to. The following conditions apply to all code found in this distribution, be it the RC4, RSA, lhash, DES, etc., code; not just the SSL code. The SSL documentation included with this distribution is covered by the same copyright terms except that the holder is Tim Hudson (tjh@cryptsoft.com). . Copyright remains Eric Young's, and as such any Copyright notices in the code are not to be removed. If this package is used in a product, Eric Young should be given attribution as the author of the parts of the library used. This can be in the form of a textual message at program startup or in documentation (online or textual) provided with the package. . 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 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. All advertising materials mentioning features or use of this software must display the following acknowledgement: "This product includes cryptographic software written by Eric Young (eay@cryptsoft.com)" The word 'cryptographic' can be left out if the routines from the library being used are not cryptographic related :-). 4. If you include any Windows specific code (or a derivative thereof) from the apps directory (application code) you must include an acknowledgement: "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" . THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. . The licence and distribution terms for any publically available version or derivative of this code cannot be changed. i.e. this code cannot simply be copied and put under another distribution licence [including the GNU Public Licence.] Files: linux/include/libreswan/pfkeyv2.h Copyright: U.S. Naval Research Laboratory License: public-domain This file defines structures and symbols for the PF_KEY Version 2 key management interface. It was written at the U.S. Naval Research Laboratory. This file is in the public domain. The authors ask that you leave this credit intact on any copies of this file. License: LGPL-2+ This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. See . . This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. . On Debian systems, a copy of the GNU Library General Public License, version 2, can be found in the file /usr/share/common-licenses/LGPL-2. License: LGPL-2.1+ This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. . This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. . On Debian systems, a copy of the GNU Lesser General Public License, version 2.1, can be found in the file /usr/share/common-licenses/LGPL-2.1. License: GPL-2+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. See . . This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. . On Debian systems, a copy of the GNU General Public License, version 2, can be found in the file /usr/share/common-licenses/GPL-2. libreswan-3.32/packaging/debian/gbp.conf000066400000000000000000000000721365625662500202330ustar00rootroot00000000000000[DEFAULT] pristine-tar = True upstream-tag = v%(version)s libreswan-3.32/packaging/debian/libreswan.dirs000066400000000000000000000000231365625662500214610ustar00rootroot00000000000000/var/lib/ipsec/nss libreswan-3.32/packaging/debian/libreswan.docs000066400000000000000000000001141365625662500214510ustar00rootroot00000000000000CREDITS README.md README.nss README.x509 docs/README.XAUTH docs/README.rfcs libreswan-3.32/packaging/debian/libreswan.examples000066400000000000000000000000201365625662500223330ustar00rootroot00000000000000docs/examples/* libreswan-3.32/packaging/debian/libreswan.install000066400000000000000000000000651365625662500221740ustar00rootroot00000000000000debian/90-libreswan.preset lib/systemd/system-preset libreswan-3.32/packaging/debian/libreswan.lintian-overrides000066400000000000000000000005761365625662500241730ustar00rootroot00000000000000# This is the name of one of the upstream maintainers: libreswan: spelling-error-in-copyright Antony Antony (duplicate word) Antony libreswan: spelling-error-in-changelog Antony Antony (duplicate word) Antony # the errors below are from licensing imported by upstream which are unlikely to change libreswan: spelling-error-in-copyright GNU Public Licence GNU General Public License libreswan-3.32/packaging/debian/libreswan.logcheck.ignore.paranoid000066400000000000000000000005221365625662500253610ustar00rootroot00000000000000pluto.*: deleting state pluto.*: forgetting secrets pluto.*: shutting down pluto.*: \| pluto.*: .* bytes loaded pluto.*: including X\.509 patch pluto.*: Loading my X\.509 certificate pluto.*: Starting pluto pluto.*: adding interface pluto.*: listening for IKE messages pluto.*: loading secrets pluto.*: regenerating DH private secret libreswan-3.32/packaging/debian/libreswan.logcheck.ignore.server000066400000000000000000000007501365625662500250750ustar00rootroot00000000000000pluto.*: deleting state pluto.*: forgetting secrets pluto.*: shutting down pluto.*: \| pluto.*: .* bytes loaded pluto.*: including X\.509 patch pluto.*: Loading my X\.509 certificate pluto.*: Starting pluto pluto.*: added connection description pluto.*: adding interface pluto.*: listening for IKE messages pluto.*: loading secrets pluto.*: .* SA established pluto.*: .* SA expired pluto.*: replacing stale .* SA pluto.*: initiating Quick Mode pluto.*: regenerating DH private secret libreswan-3.32/packaging/debian/libreswan.logcheck.ignore.workstation000066400000000000000000000007501365625662500261530ustar00rootroot00000000000000pluto.*: deleting state pluto.*: forgetting secrets pluto.*: shutting down pluto.*: \| pluto.*: .* bytes loaded pluto.*: including X\.509 patch pluto.*: Loading my X\.509 certificate pluto.*: Starting pluto pluto.*: added connection description pluto.*: adding interface pluto.*: listening for IKE messages pluto.*: loading secrets pluto.*: .* SA established pluto.*: .* SA expired pluto.*: replacing stale .* SA pluto.*: initiating Quick Mode pluto.*: regenerating DH private secret libreswan-3.32/packaging/debian/libreswan.postrm000066400000000000000000000002651365625662500220540ustar00rootroot00000000000000#!/bin/sh set -e if [ "$1" = "purge" ] ; then # clean up NSS database (see debian/README.Debian for more # details) rm -f \ /var/lib/ipsec/nss/* fi #DEBHELPER# libreswan-3.32/packaging/debian/patches/000077500000000000000000000000001365625662500202445ustar00rootroot00000000000000libreswan-3.32/packaging/debian/patches/0002-debian-pam.d-pluto.patch000066400000000000000000000023241365625662500252250ustar00rootroot00000000000000From: Marc-Christian Petersen Date: Wed, 9 Mar 2016 19:22:41 +0200 Subject: debian-pam.d-pluto debian: fix /etc/pam.d/pluto to work with debian Signed-off-by: Tuomo Soini --- pam.d/pluto | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/pam.d/pluto b/pam.d/pluto index 3855385..bb9b22c 100644 --- a/pam.d/pluto +++ b/pam.d/pluto @@ -1,16 +1,11 @@ -#%PAM-1.0 -# Regular System auth -auth include system-auth -# -# Google Authenticator with Regular System auth in combined prompt mode -# (OTP is added to the password at the password prompt without separator) -# auth required pam_google_authenticator.so forward_pass -# auth include system-auth use_first_pass -# -# Common -account required pam_nologin.so -account include system-auth -password include system-auth -session optional pam_keyinit.so force revoke -session include system-auth -session required pam_loginuid.so +@include common-auth + +account required pam_nologin.so +account required pam_access.so +@include common-account + +session optional pam_keyinit.so force revoke +session required pam_loginuid.so +@include common-session + +@include common-password 0003-update-README.nss-to-match-debian-defaults-for-IPSEC.patch000066400000000000000000000045161365625662500327770ustar00rootroot00000000000000libreswan-3.32/packaging/debian/patchesdiff --git a/README.nss b/README.nss index d3fc62078..f68540db0 100644 --- a/README.nss +++ b/README.nss @@ -64,7 +64,7 @@ using: By default the NSS db is created in /etc/ipsec.d/ on RHEL/Fedora/CentOS but in /var/lib/ipsec/nss/ on Debian/Ubuntu. The remainder of this file -uses /etc/ipsec.d/ in the examples. +uses /var/lib/ipsec/nss/ in the examples. When creating a database, you are prompted for a password. The default libreswan package install for RHEL/Fedora/CentOS uses an empty password. @@ -74,7 +74,7 @@ running in FIPS mode. To change the empty password, run: - certutil -W -d sql:/etc/ipsec.d + certutil -W -d sql:/var/lib/ipsec/nss Enter return for the "old password", then enter your new password. @@ -136,7 +136,7 @@ Below, we will be using the nss tools to generate certificates * To create a certificate authority (CA certificate): certutil -S -k rsa -n "ExampleCA" -s "CN=Example CA Inc" -v 12 \ - -t "CT,," -x -d sql:/etc/ipsec.d + -t "CT,," -x -d sql:/var/lib/ipsec/nss It creates a certificate with RSA keys (-k rsa) with the nickname "ExampleCA", and with common name "Example CA Inc". The option @@ -151,7 +151,7 @@ certificate can be obtained from anywhere in the world. * To create a user certificate signed by the above CA certutil -S -k rsa -c "ExampleCA" -n "user1" -s "CN=User Common Name" \ - -v 12 -t "u,u,u" -d sql:/etc/ipsec.d + -v 12 -t "u,u,u" -d sql:/var/lib/ipsec/nss It creates a user cert with nickname "user1" with attributes "u,u,u" signed by the CA cert "ExampleCA". @@ -208,7 +208,7 @@ Now you can import the file into the NSS db: ipsec import certkey.p12 If you did not pick a name using the -name option, you can use -certutil -L -d sql:/etc/ipsec.d to figure out the name NSS picked during +certutil -L -d sql:/var/lib/ipsec/nss to figure out the name NSS picked during the import. Add following to /etc/ipsec.secrets file: @@ -229,12 +229,12 @@ Paul: add "ipsec export" ? To export the CA certificate: - pk12util -o cacert1.p12 -n cacert1 -d sql:/etc/ipsec.d + pk12util -o cacert1.p12 -n cacert1 -d sql:/var/lib/ipsec/nss Copy the file "cacert1.p12" to the new machine and import it using: ipsec import cacert1.p12 - certutil -M -n cacert1 -t "CT,," -d sql:/etc/ipsec.d + certutil -M -n cacert1 -t "CT,," -d sql:/var/lib/ipsec/nss Example connection for ipsec.conf: libreswan-3.32/packaging/debian/patches/series000066400000000000000000000002311365625662500214550ustar00rootroot00000000000000#0001-do-not-use-git-version.patch 0002-debian-pam.d-pluto.patch 0003-update-README.nss-to-match-debian-defaults-for-IPSEC.patch #0005-fix-speling.patch libreswan-3.32/packaging/debian/rules000077500000000000000000000046031365625662500177000ustar00rootroot00000000000000#!/usr/bin/make -f include /usr/share/dpkg/default.mk %: dh $@ --with systemd # this should track the definition of USERCOMPILE in mk/userland-cflags.mk:43 # but without -fstack-protector-all for arches that lack stack-protector ifneq (,$(filter $(DEB_HOST_ARCH), hppa alpha)) export USERCOMPILE = -fexceptions -fno-strict-aliasing -fPIE -DPIE endif ifeq ($(DEB_HOST_ARCH_OS),linux) ENABLE_SELINUX = USE_LABELED_IPSEC=true USE_LINUX_AUDIT=true ENABLE_LIBCAP_NG = USE_LIBCAP_NG=true else ENABLE_SELINUX = USE_LABELED_IPSEC=false USE_LINUX_AUDIT=false ENABLE_LIBCAP_NG = USE_LIBCAP_NG=false endif # Distribution & Release sepcfic config option. DISTRO_CONF = DISTRO_CONF += $(shell grep -qE 'jessie|xenial|stretch' /etc/os-release && echo USE_DNSSEC=false) DISTRO_CONF += $(shell grep -qE 'jessie|xenial' /etc/os-release && echo USE_GLIBC_KERN_FLIP_HEADERS=true) DISTRO_CONF += $(shell grep -qE 'bionic|cosmic|jessie|stretch|xenial' /etc/os-release && echo USE_NSS_IPSEC_PROFILE=false) DISTRO_CONF += $(shell grep -qE 'jessie|stretch|xenial' /etc/os-release && echo USE_NSS_AVA_COPY=true) DISTRO_CONF += $(shell grep -qE 'jessie|stretch' /etc/os-release && echo USE_DH31=false) DISTRO_CONF += $(shell grep -qE 'jessie|xenial|cosmic' /etc/os-release && echo USE_XFRM_INTERFACE=false) DISTRO_CONF += $(shell grep -qE 'stretch|bionic' /etc/os-release && echo USE_XFRM_INTERFACE_IFLA_HEADER=true) override_dh_auto_build: $(MAKE) programs \ ARCH=$(DEB_HOST_ARCH) \ IPSECVERSION=$(DEB_VERSION_UPSTREAM_REVISION) \ INC_USRLOCAL=/usr \ FINALLIBEXECDIR=/usr/lib/ipsec \ PUBDIR=/usr/sbin \ INC_MANDIR=share/man \ FINALNSSDIR=/var/lib/ipsec/nss \ USE_LDAP=true \ USE_FIPSCHECK=false \ $(ENABLE_LIBCAP_NG) \ $(ENABLE_SELINUX) \ DEFAULT_DNSSEC_ROOTKEY_FILE=/usr/share/dns/root.key \ $(DISTRO_CONF) override_dh_auto_install-arch: # Add here commands to install the package into debian/libreswan $(MAKE) install \ ARCH=$(DEB_HOST_ARCH) \ IPSECVERSION=$(DEB_VERSION_UPSTREAM_REVISION) \ INC_USRLOCAL=/usr \ FINALLIBEXECDIR=/usr/lib/ipsec \ INC_MANDIR=share/man \ FINALNSSDIR=/var/lib/ipsec/nss \ USE_LDAP=true \ USE_FIPSCHECK=false \ $(ENABLE_LIBCAP_NG) \ $(ENABLE_SELINUX) \ PUBDIR=$(CURDIR)/debian/libreswan/usr/sbin \ DESTDIR=$(CURDIR)/debian/libreswan \ $(DISTRO_CONF) override_dh_auto_test: echo "Skip dh_auto_test" override_dh_strip: dh_strip --dbg-package=libreswan-dbg libreswan-3.32/packaging/debian/source/000077500000000000000000000000001365625662500201155ustar00rootroot00000000000000libreswan-3.32/packaging/debian/source/format000066400000000000000000000000141365625662500213230ustar00rootroot000000000000003.0 (quilt) libreswan-3.32/packaging/debian/tests/000077500000000000000000000000001365625662500177575ustar00rootroot00000000000000libreswan-3.32/packaging/debian/tests/control000066400000000000000000000001631365625662500213620ustar00rootroot00000000000000Tests: opportunistic Restrictions: needs-root, isolation-machine Depends: @, iputils-ping, wget, systemd, dnsutils libreswan-3.32/packaging/debian/tests/opportunistic000077500000000000000000000022061365625662500226270ustar00rootroot00000000000000#!/bin/bash set -e # fetch some stuff from oe.libreswan.org, make sure it's bad: badstring='OH noooooos!!' ping -c 5 oe.libreswan.org 2>&1 dig +short -x `dig +short oe.libreswan.org` ipseckey +trusted-key=/usr/share/dns/root.key +sigchase wget -q --tries=2 --timeout=5 -O "${AUTOPKGTEST_ARTIFACTS}/before.html" http://oe.libreswan.org/ echo "0.0.0.0/0" > /etc/ipsec.d/policies/private-or-clear grep -F "$badstring" "${AUTOPKGTEST_ARTIFACTS}/before.html" systemctl status ipsec cp /usr/share/doc/libreswan/examples/oe-dnssec-client.conf /etc/ipsec.d/ systemctl restart ipsec systemctl status ipsec # TODO: better details? ipsec whack --trafficstatus ping -c 5 oe.libreswan.org 2>&1 systemctl status ipsec # now fetch some stuff from oe.libreswan.org, make sure it's good! wget -q --tries=2 --timeout=5 -O "${AUTOPKGTEST_ARTIFACTS}/after.html" http://oe.libreswan.org/ if grep -F "$badstring" "${AUTOPKGTEST_ARTIFACTS}/after.html"; then printf "we got 'oh nooooooos' from http://oe.libreswan.org after bringing up opportunistic ipsec\n" exit 1 fi # TODO: better details? ipsec whack --trafficstatus libreswan-3.32/packaging/debian/upstream/000077500000000000000000000000001365625662500204555ustar00rootroot00000000000000libreswan-3.32/packaging/debian/upstream/signing-key.asc000066400000000000000000000066671365625662500234100ustar00rootroot00000000000000-----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v1.4.13 (GNU/Linux) mQINBFDjilcBEAChkfasfBKTzGys9DwgBsmDVsPConW60uyKnu16+wO1kIKMFWi6 wGllwKUJmCBY2FSQHbOBy5eHPPT1ijJhYt4j7WU+YJVh5Ca5RE3trFt31FX0vzp+ KMqdQ8HOofA7jO6bgyHUwOJ539YkqYj1jHKfrdRqOnzB9fFyEb7485sq1F8j/rHk cSar1Hd9QfGAZHxXqgncgHFobB/xXEGRJIi+4kNL5SYasbw9tfYUGPrUXVol1+pn tsG92736O5Qe5K+wH2nAS4hwPJ1Xr4XIKeNNwxQW25wWqn4mLa4Vly+PA2uSE7ZP RcxE3yBCaLFMlw4rLhFAzd6TeslQONZ+9K51yfBYm7m0vWM3Ixq8yuD8E49OkKr8 QRMaA2g89NW3AuNLExiTE0zQzAs/g6eX8WZdeWCvKxhRTAUYkw0QTimFgv6LXIeS //5DOAAO9WwzlseTGmUgek3BbnnJJiGHVLBgnLaqWLOZ1Y8ON1uC8lQnbIeYbTQq EE5R0cbVLVXBJoKakBF8gwHF51HC2pSBYmHNZsSbjMuHpJWJM4fVldNWPNaqriKC OkL8QgvNoapgk20k1ajLl/ibv32k7QBKy3cTMtbQYPdreXcoZuMw38ysQcgFxPCs Zh92aaWW0ceWowkJ7CFnes2jdPcMSOYE37wodmV3/VV7cusmTD8wikyUdQARAQAB tCxMaWJyZXN3YW4gKFNpZ25pbmcgS2V5KSA8dGVhbUBsaWJyZXN3YW4ub3JnPokC OAQTAQIAIgUCUOOKVwIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQhf9L Q7MPxvkHyRAAgSq/QhdBurBaIjzqM4jZpaHEOURPlL38wHTBBeH4U5IZcwiPul9X Et1HqwHLDv89YjljHj76oOLt5xR14exgV0xWolZaLVpji3S6/NbCh37UMoWIBCSP j6/S6oAXxtX+oCI1lXmS4w60ZDDuYgVUrtAv77ODlQoPVf5TM0tU7Gb2Y3WB47DS XioIzwjFwJmtK3RzDRtF4oC2YFN3DBovVHmv6hbIt7NDNp7+NYRlx+wdi+XYFcNv +ZIARFkoc1Sr4HDk+lA2qx5jfvgZvabTn7OCTlCKwkSwO5sK0ICNcLmG9nb4ZNrU C2GXryTNQOMLcdvZAyBvxtgNzI7qqMAxeipsyCz5ypp5S3SwzHjqeCUJJ4pv7Ebn BnYIOgdLkq/WPsS6om7qwr3EdkR8iTZnuTi2Fejw7WnQP8dYLVXwG/90vNCU/HTE IYhal4ob7p0SsyLYF47U/iKl/b6ZErOcbq3YF0fMe8iusAtNLeIN4BLk9tpclGde weTPuB+MhRuDsLCF764ZB/R5v0CjWFVcBxnRXQbjlrm6dMlEXPFKjjV1fHL1HZhB GXopPmsw+NIf9sTSjcgNnLZGJFGGBsIxQD18AN6nzi2vtGRksB/FqLY7gIeGWaPu HlUI1qHdRLS7aus9nrS/RQTTUdCOsn1fRVozX2eVklAWgLuoz58oPhiJARwEEAEI AAYFAlDlHbkACgkQ5xgGprXMJ+Hc8Qf/Sd4NJMJifpU8hYET7IzMSgAdGZkkFV7/ 3/YCoEIVQS18xx+66L/TrUrAtJnlHLpmNUMA1wVFTtGJ/CRwFt3LsZYVM1jCwdRe AF492OHxEWXAboVnGRnGfJ3yhfCTd3XgRbthqBwR/8BSWCzs9Gy9YA5N6oceNf6q QkkLKk3YwdSNnW3b7o/AVdNcFbwkE+amNQ2mhWUtzzuvlsmgOrnCpUlq3djhnEKs pbl+T/apqvn7JRsOvuy/26kjoTbVrb7OpFmAjlIqbbxokaONFuDpqn/mtgG7Bk0r 3Pv501mRItACslhaKPJ02oPufAmzBrphjzzhCYlR1TeEek++9qoHyLkCDQRQ44pX ARAA1wzfaN4nMg8vorcuOQrEH6NX/OMS+qCSIAixhsJt0RT4Ds3YMWhO04i81tjQ bovsh8sOPFkU8WfVwuh7Riox+lz7z+ZxePMLLO7Y80Tc5jYE6exuOx5Ft5Q9FWF+ DanwpsUCvYE16G9fiRZlpBF5F5mWINnW59URLR29N8d+9GeeO6473aaKUFuo2ksN AueegzsW/cHiai6gHdrmTuJ8Ibg7P1TPkMsvvzJR0257Jp2CDKMwyzJh2dTzHiZU xTzH2qWrsfVA04EOXcC49hYkP7hDM731b1tt4cZaVlR7HHMGUe+zzA7eDW4/+0JT iCqYIndq/EsgZoYxE9rv1EksxWMyvCdlo6C3MYrjE8K5zOm926orkg1DABKDTfNe Am6c+siwdsMirOTe2QP5VSzRPDFe7aPDg8MNZ0tmww3+fyTDbeWlrv4jtmwa2BN9 C6h0d20lekD+eyZ87pzPWOFdQZxCmFteAPfq0R9ZNXuQrkubasaUrm54hfNAHVMj 4xfK1zmNFEQ+s2NLOPONzX/Uza/JHv9ZmqixJFABdNwMAUfKM9uO8pbu+aveMraW FBSQJDXqqZPF8qaiiTFXJeDXxD/d9CUfNrBozcpVbv2+BLKin5pKFPFRTNZX7mql 9btmQ6FKRtiKP86XldO0UNCkx3SgXo84sdiDdE+1uBtCV3MAEQEAAYkCHwQYAQIA CQUCUOOKVwIbDAAKCRCF/0tDsw/G+SkfD/43VjVVcO+P6Aj7be/Vda9FzeCNGQU0 GYCqdyZmXXGZUtlM8eLtVYcXHrw0O34f2eWNcQwYfiCsBfN4SSl8uevjyQZWCBo3 NhkxJlNcqOBPYrnT6uehRW+nnpV9agX8SNGR3VoM1pq7Zwheucxk5nmDKXJOGbin SQF9gDOpFnAYpLeI0/0qq3EvLf3blkUklYopMFw/Gj3sQM/V7nsyPstxMbqbf5al MlbQld7dP4FkQDLsKzB/0QARD02kHZsSs4tDpDA5R4cHl2VoNP7d9ly4YZsuH/99 DYSmJ57Tev6XTQ2/L4p+Tj9jEciQxyMpANh2XGL43WUuN/j24rqgwkyCzL8VA2I8 R7M4BIXi2q4kb5kcBNR0Y2VjU8xk41IMr/N11IayKAJYDFctrUAGrSmzVWAJ+XZg NDQgyp0rM2rON4AKUko4dlF5qv6MMKVY+s2B3KFdIHQriydQTy7LTdGRjvoPnkaU yPe/v9OLIM/4SJg7Juxtw4p3q7PxQ2nm7aTEc1bIYeZSIFQZwk9+oXR1vG7sogIE ULY6u21/CSzeBK5sZauGt9zmHO0xjQt4xUZuF0mOkVAzHeroUQ+YSmQdjfGs9O/e tNyu53Pd8d9grmpRwiQ/jO2dv4/a90903MuvaDPqYD+PMMkqPlxBhwjOThu2DTYi fMUPyfgigsi0FQ== =X982 -----END PGP PUBLIC KEY BLOCK----- libreswan-3.32/packaging/debian/watch000066400000000000000000000004771365625662500176560ustar00rootroot00000000000000version=4 # look for normal releases: opts=pgpsigurlmangle=s/$/.asc/ \ https://download.libreswan.org/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ # look for development releases: opts=pgpsigurlmangle=s/$/.asc/,uversionmangle=s/(dr|rc)/~\\1/ \ https://download.libreswan.org/development/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ libreswan-3.32/packaging/fedora/000077500000000000000000000000001365625662500166335ustar00rootroot00000000000000libreswan-3.32/packaging/fedora/libreswan-prelink.conf000066400000000000000000000000271365625662500231310ustar00rootroot00000000000000-b /usr/libexec/ipsec/ libreswan-3.32/packaging/fedora/libreswan-sysctl.conf000066400000000000000000000010151365625662500230040ustar00rootroot00000000000000# when using 1 interface for two networks when using NETKEY, the kernel # thinks it can be clever by sending a redirect (cause it cannot tell # an encrypted packet came in, but a decrypted packet came out), # so it sends a bogus ICMP redirect # # We disable redirects for XFRM/IPsec net.ipv6.conf.default.accept_redirects = 0 net.ipv6.conf.all.accept_redirects = 0 net.ipv4.conf.default.send_redirects = 0 net.ipv4.conf.default.accept_redirects = 0 net.ipv4.conf.all.send_redirects = 0 net.ipv4.conf.all.accept_redirects = 0 libreswan-3.32/packaging/fedora/libreswan-testing.spec000066400000000000000000000152161365625662500231550ustar00rootroot00000000000000%global _hardened_build 1 # These are rpm macros and are 0 or 1 %global with_efence 1 %global with_development 1 %global nss_version 3.41 %global unbound_version 1.6.6 %global with_cavstests 0 %global _exec_prefix %{_prefix}/local %global initsystem @INITSYSTEM@ # Libreswan config options %global libreswan_config \\\ FINALDOCDIR=%{_pkgdocdir} \\\ FINALEXAMPLECONFDIR=%{_pkgdocdir} \\\ FINALLIBEXECDIR=%{_libexecdir}/ipsec \\\ FINALMANDIR=%{_mandir} \\\ FINALRUNDIR=%{_rundir}/pluto \\\ FIPSPRODUCTCHECK=%{_sysconfdir}/system-fips \\\ INC_RCDEFAULT=%{_initrddir} \\\ INC_USRLOCAL=%{_exec_prefix} \\\ IPSECVERSION=%{IPSECVERSION} \\\ INITSYSTEM=%{initsystem} \\\ USE_NSS_IPSEC_PROFILE=true \\\ PYTHON_BINARY=%{__python3} \\\ SHELL_BINARY=%{_prefix}/bin/sh \\\ %{nil} %{nil} #global prever rc1 %global rel %{?prever:0.}1%{?prever:.%{prever}} # for pluto --version %global IPSECVERSION %{version}-%{rel} Name: libreswan Summary: IPsec implementation with IKEv1 and IKEv2 keying protocols # version is replaced in make target Version: 3.30 Release: %{rel}%{?dist} License: GPLv2 Url: https://libreswan.org/ Source0: https://download.libreswan.org/%{?prever:development/}%{name}-%{version}%{?prever}.tar.gz %if 0%{with_cavstests} Source1: https://download.libreswan.org/cavs/ikev1_dsa.fax.bz2 Source2: https://download.libreswan.org/cavs/ikev1_psk.fax.bz2 Source3: https://download.libreswan.org/cavs/ikev2.fax.bz2 %endif BuildRequires: gcc BuildRequires: bison BuildRequires: flex BuildRequires: pkgconfig BuildRequires: systemd-devel Conflicts: openswan < %{version}-%{release} Obsoletes: openswan < %{version}-%{release} Provides: openswan = %{version}-%{release} Provides: openswan-doc = %{version}-%{release} BuildRequires: pkgconfig hostname BuildRequires: nss-devel >= 3.16.1 BuildRequires: nspr-devel BuildRequires: pam-devel BuildRequires: libevent-devel BuildRequires: unbound-devel >= 1.5.0-1 BuildRequires: ldns-devel BuildRequires: libseccomp-devel BuildRequires: libselinux-devel BuildRequires: fipscheck-devel Requires: fipscheck%{_isa} Buildrequires: audit-libs-devel BuildRequires: libcap-ng-devel BuildRequires: openldap-devel BuildRequires: curl-devel %if 0%{with_efence} BuildRequires: ElectricFence %endif BuildRequires: xmlto Requires: nss-tools Requires: nss-softokn Requires: iproute >= 2.6.8 %description Libreswan is a free implementation of IPsec & IKE for Linux. IPsec is the Internet Protocol Security and uses strong cryptography to provide both authentication and encryption services. These services allow you to build secure tunnels through untrusted networks. Everything passing through the untrusted net is encrypted by the ipsec gateway machine and decrypted by the gateway at the other end of the tunnel. The resulting tunnel is a virtual private network or VPN. This package contains the daemons and userland tools for setting up Libreswan. To build KLIPS, see the kmod-libreswan.spec file. Libreswan also supports IKEv2 (RFC4309) and Secure Labeling Libreswan is based on Openswan-2.6.38 which in turn is based on FreeS/WAN-2.04 %prep %setup -q -n libreswan-%{version}%{?prever} sed -i "s:#[ ]*include \(.*\)\(/crypto-policies/back-ends/libreswan.config\)$:include \1\2:" programs/configs/ipsec.conf.in %build make %{?_smp_mflags} \ %if 0%{with_development} OPTIMIZE_CFLAGS="%{?_hardened_cflags}" \ %else OPTIMIZE_CFLAGS="%{optflags}" \ %endif %if 0%{with_efence} USE_EFENCE=true \ %endif %{libreswan_config} \ programs FS=$(pwd) # Add generation of HMAC checksums of the final stripped binaries %define __spec_install_post \ %{?__debug_package:%{__debug_install_post}} \ %{__arch_install_post} \ %{__os_install_post} \ fipshmac -d %{buildroot}%{_libdir}/fipscheck %{buildroot}%{_libexecdir}/ipsec/pluto \ %{nil} %install make \ DESTDIR=%{buildroot} \ %{libreswan_config} \ install FS=$(pwd) # Work around for FINALEXAMPLECONFDIR not working properly rm -rf %{buildroot}%{_prefix}/share/doc install -d -m 0700 %{buildroot}%{_rundir}/pluto # used when setting --perpeerlog without --perpeerlogbase install -d -m 0700 %{buildroot}%{_localstatedir}/log/pluto/peer install -d %{buildroot}%{_sbindir} install -d %{buildroot}%{_sysconfdir}/sysctl.d install -m 0644 packaging/fedora/libreswan-sysctl.conf \ %{buildroot}%{_sysconfdir}/sysctl.d/50-libreswan.conf mkdir -p %{buildroot}%{_libdir}/fipscheck echo "include %{_sysconfdir}/ipsec.d/*.secrets" \ > %{buildroot}%{_sysconfdir}/ipsec.secrets rm -fr %{buildroot}%{_sysconfdir}/rc.d/rc* %if 0%{with_cavstests} %check # There is an elaborate upstream testing infrastructure which we do not # run here - it takes hours and uses kvm # We only run the CAVS tests. # cp %{SOURCE1} %{SOURCE2} %{SOURCE3} . # bunzip2 *.fax.bz2 # work around for older xen based machines export NSS_DISABLE_HW_GCM=1 : starting CAVS test for IKEv2 %{buildroot}%{_libexecdir}/ipsec/cavp -v2 ikev2.fax | \ diff -u ikev2.fax - > /dev/null : starting CAVS test for IKEv1 RSASIG %{buildroot}%{_libexecdir}/ipsec/cavp -v1sig ikev1_dsa.fax | \ diff -u ikev1_dsa.fax - > /dev/null : starting CAVS test for IKEv1 PSK %{buildroot}%{_libexecdir}/ipsec/cavp -v1psk ikev1_psk.fax | \ diff -u ikev1_psk.fax - > /dev/null : CAVS tests passed %endif %if "%{initsystem}" == "systemd" %post %systemd_post ipsec.service %preun %systemd_preun ipsec.service %postun %systemd_postun_with_restart ipsec.service %endif %files %doc CHANGES COPYING CREDITS README* LICENSE %doc docs/*.* docs/examples %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ipsec.conf %attr(0600,root,root) %config(noreplace) %{_sysconfdir}/ipsec.secrets %attr(0700,root,root) %dir %{_sysconfdir}/ipsec.d %attr(0700,root,root) %dir %{_sysconfdir}/ipsec.d/policies %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ipsec.d/policies/* %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/sysctl.d/50-libreswan.conf %attr(0700,root,root) %dir %{_localstatedir}/log/pluto %attr(0700,root,root) %dir %{_localstatedir}/log/pluto/peer %attr(0700,root,root) %dir %{_rundir}/pluto %if "%{initsystem}" == "systemd" %attr(0644,root,root) %{_tmpfilesdir}/libreswan.conf %attr(0644,root,root) %{_unitdir}/ipsec.service %endif %if "%{initsystem}" == "docker" || "%{initsystem}" == "sysvinit" %attr(0755,root,root) %{_initddir}/ipsec %config(noreplace) %{_sysconfdir}/sysconfig/pluto %endif %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/pam.d/pluto %{_sbindir}/ipsec %{_libexecdir}/ipsec %{_mandir}/*/* %{_libdir}/fipscheck/pluto.hmac %changelog * Wed Aug 9 2017 Team Libreswan - @IPSECBASEVERSION@ - Automated build for testing from git tree. - All compile time options are set in Makefile.inc.local not here. libreswan-3.32/packaging/fedora/libreswan.spec000066400000000000000000000153611365625662500215030ustar00rootroot00000000000000%global _hardened_build 1 # These are rpm macros and are 0 or 1 %global with_efence 0 %global with_development 0 %global with_cavstests 1 %global nss_version 3.41 %global unbound_version 1.6.6 # Libreswan config options %global libreswan_config \\\ FINALLIBEXECDIR=%{_libexecdir}/ipsec \\\ FINALMANDIR=%{_mandir} \\\ INC_RCDEFAULT=%{_initrddir} \\\ INC_USRLOCAL=%{_prefix} \\\ INITSYSTEM=systemd \\\ PYTHON_BINARY=%{__python3} \\\ SHELL_BINARY=%{_bindir}/sh \\\ USE_DNSSEC=true \\\ USE_FIPSCHECK=false \\\ USE_KLIPS=false \\\ USE_LABELED_IPSEC=true \\\ USE_LDAP=true \\\ USE_LIBCAP_NG=true \\\ USE_LIBCURL=true \\\ USE_LINUX_AUDIT=true \\\ USE_NM=true \\\ USE_NSS_IPSEC_PROFILE=true \\\ USE_SECCOMP=true \\\ USE_XAUTHPAM=true \\\ %{nil} #global prever rc1 Name: libreswan Summary: Internet Key Exchange (IKEv1 and IKEv2) implementation for IPsec # version is generated in the release script Version: 3.32 Release: %{?prever:0.}1%{?prever:.%{prever}}%{?dist} License: GPLv2 Url: https://libreswan.org/ Source0: https://download.libreswan.org/%{?prever:development/}%{name}-%{version}%{?prever}.tar.gz %if 0%{with_cavstests} Source1: https://download.libreswan.org/cavs/ikev1_dsa.fax.bz2 Source2: https://download.libreswan.org/cavs/ikev1_psk.fax.bz2 Source3: https://download.libreswan.org/cavs/ikev2.fax.bz2 %endif BuildRequires: audit-libs-devel BuildRequires: bison BuildRequires: curl-devel BuildRequires: flex BuildRequires: gcc BuildRequires: hostname BuildRequires: ldns-devel BuildRequires: libcap-ng-devel BuildRequires: libevent-devel BuildRequires: libseccomp-devel BuildRequires: libselinux-devel BuildRequires: nspr-devel BuildRequires: nss-devel >= %{nss_version} BuildRequires: openldap-devel BuildRequires: pam-devel BuildRequires: pkgconfig BuildRequires: systemd-devel BuildRequires: unbound-devel >= %{unbound_version} BuildRequires: xmlto %if 0%{with_efence} BuildRequires: ElectricFence %endif Requires: iproute >= 2.6.8 Requires: nss >= %{nss_version} Requires: nss-softokn Requires: nss-tools Requires: unbound-libs >= %{unbound_version} Requires(post): bash Requires(post): coreutils Requires(post): systemd Requires(preun): systemd Requires(postun): systemd Conflicts: openswan < %{version}-%{release} Obsoletes: openswan < %{version}-%{release} Provides: openswan = %{version}-%{release} Provides: openswan-doc = %{version}-%{release} %description Libreswan is a free implementation of IPsec & IKE for Linux. IPsec is the Internet Protocol Security and uses strong cryptography to provide both authentication and encryption services. These services allow you to build secure tunnels through untrusted networks. Everything passing through the untrusted net is encrypted by the ipsec gateway machine and decrypted by the gateway at the other end of the tunnel. The resulting tunnel is a virtual private network or VPN. This package contains the daemons and userland tools for setting up Libreswan. Libreswan also supports IKEv2 (RFC7296) and Secure Labeling Libreswan is based on Openswan-2.6.38 which in turn is based on FreeS/WAN-2.04 %prep %setup -q -n libreswan-%{version}%{?prever} # enable crypto-policies support sed -i "s:#[ ]*include \(.*\)\(/crypto-policies/back-ends/libreswan.config\)$:include \1\2:" programs/configs/ipsec.conf.in # linking to freebl is no longer needed sed -i "s/-lfreebl //" mk/config.mk %build make %{?_smp_mflags} \ %if 0%{with_development} OPTIMIZE_CFLAGS="%{?_hardened_cflags}" \ %else OPTIMIZE_CFLAGS="%{optflags}" \ %endif %if 0%{with_efence} USE_EFENCE=true \ %endif USERLINK="%{?__global_ldflags}" \ %{libreswan_config} \ programs FS=$(pwd) %install make \ DESTDIR=%{buildroot} \ %{libreswan_config} \ install FS=$(pwd) rm -rf %{buildroot}/usr/share/doc/libreswan rm -rf %{buildroot}%{_libexecdir}/ipsec/*check install -d -m 0755 %{buildroot}%{_rundir}/pluto # used when setting --perpeerlog without --perpeerlogbase install -d -m 0700 %{buildroot}%{_localstatedir}/log/pluto/peer install -d %{buildroot}%{_sbindir} install -d %{buildroot}%{_sysconfdir}/sysctl.d install -m 0644 packaging/fedora/libreswan-sysctl.conf \ %{buildroot}%{_sysconfdir}/sysctl.d/50-libreswan.conf echo "include %{_sysconfdir}/ipsec.d/*.secrets" \ > %{buildroot}%{_sysconfdir}/ipsec.secrets rm -fr %{buildroot}%{_sysconfdir}/rc.d/rc* %if 0%{with_cavstests} %check # There is an elaborate upstream testing infrastructure which we do not # run here - it takes hours and uses kvm # We only run the CAVS tests. cp %{SOURCE1} %{SOURCE2} %{SOURCE3} . bunzip2 *.fax.bz2 # work around for older xen based machines export NSS_DISABLE_HW_GCM=1 : starting CAVS test for IKEv2 %{buildroot}%{_libexecdir}/ipsec/cavp -v2 ikev2.fax | \ diff -u ikev2.fax - > /dev/null : starting CAVS test for IKEv1 RSASIG %{buildroot}%{_libexecdir}/ipsec/cavp -v1dsa ikev1_dsa.fax | \ diff -u ikev1_dsa.fax - > /dev/null : starting CAVS test for IKEv1 PSK %{buildroot}%{_libexecdir}/ipsec/cavp -v1psk ikev1_psk.fax | \ diff -u ikev1_psk.fax - > /dev/null : CAVS tests passed %endif # Some of these tests will show ERROR for negative testing - it will exit on real errors %{buildroot}%{_libexecdir}/ipsec/algparse -tp || { echo prooposal test failed; exit 1; } %{buildroot}%{_libexecdir}/ipsec/algparse -ta || { echo algorithm test failed; exit 1; } : Algorithm parser tests passed # self test for pluto daemon - this also shows which algorithms it allows in FIPS mode tmpdir=$(mktemp -d /tmp/libreswan-XXXXX) certutil -N -d sql:$tmpdir --empty-password %{buildroot}%{_libexecdir}/ipsec/pluto --selftest --nssdir $tmpdir --rundir $tmpdir : pluto self-test passed - verify FIPS algorithms allowed is still compliant with NIST %post %systemd_post ipsec.service %preun %systemd_preun ipsec.service %postun %systemd_postun_with_restart ipsec.service %files %doc CHANGES COPYING CREDITS README* LICENSE %doc docs/*.* docs/examples %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ipsec.conf %attr(0600,root,root) %config(noreplace) %{_sysconfdir}/ipsec.secrets %attr(0700,root,root) %dir %{_sysconfdir}/ipsec.d %attr(0700,root,root) %dir %{_sysconfdir}/ipsec.d/policies %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ipsec.d/policies/* %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/sysctl.d/50-libreswan.conf %attr(0700,root,root) %dir %{_localstatedir}/log/pluto %attr(0700,root,root) %dir %{_localstatedir}/log/pluto/peer %attr(0755,root,root) %dir %{_rundir}/pluto %attr(0644,root,root) %{_tmpfilesdir}/libreswan.conf %attr(0644,root,root) %{_unitdir}/ipsec.service %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/pam.d/pluto %{_sbindir}/ipsec %{_libexecdir}/ipsec %doc %{_mandir}/*/* %changelog * Mon Mar 30 2020 Team Libreswan - 3.32-1 - Automated build from release tar ball libreswan-3.32/packaging/foobar000077700000000000000000000000001365625662500174362rhelustar00rootroot00000000000000libreswan-3.32/packaging/linus/000077500000000000000000000000001365625662500165255ustar00rootroot00000000000000libreswan-3.32/packaging/linus/config-all.h000066400000000000000000000043171365625662500207160ustar00rootroot00000000000000#ifndef _CONFIG_ALL_H_ /* * Copyright (C) 2002 Michael Richardson * Copyright (C) 2011 Paul Wouters * * This kernel module is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This kernel module is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public * License for more details. * */ #define _CONFIG_ALL_H_ /* seen it, no need to see it again */ #define CONFIG_KLIPS_MODULE 1 #ifndef CONFIG_KLIPS_AH #define CONFIG_KLIPS_AH 1 #endif #ifndef CONFIG_KLIPS_DEBUG #define CONFIG_KLIPS_DEBUG 1 #endif #ifndef CONFIG_KLIPS_ESP #define CONFIG_KLIPS_ESP 1 #endif #ifndef CONFIG_KLIPS_IPCOMP #define CONFIG_KLIPS_IPCOMP 1 #endif #ifndef CONFIG_KLIPS_IPIP #define CONFIG_KLIPS_IPIP 1 #endif #ifndef CONFIG_KLIPS_AUTH_HMAC_MD5 #define CONFIG_KLIPS_AUTH_HMAC_MD5 1 #endif #ifndef CONFIG_KLIPS_AUTH_HMAC_SHA1 #define CONFIG_KLIPS_AUTH_HMAC_SHA1 1 #endif #ifndef CONFIG_KLIPS_DYNDEV #define CONFIG_KLIPS_DYNDEV 1 #endif #ifndef CONFIG_KLIPS_ENC_3DES #define CONFIG_KLIPS_ENC_3DES 1 #endif /* no longer needed as of 2.6.22 and up */ #if 0 # ifndef CONFIG_IPSEC_NAT_TRAVERSAL # define CONFIG_IPSEC_NAT_TRAVERSAL 1 # endif #endif #undef CONFIG_IPSEC_NAT_TRAVERSAL #ifndef CONFIG_KLIPS_ENC_AES #define CONFIG_KLIPS_ENC_AES 1 #endif #ifndef CONFIG_KLIPS_ENC_CRYPTOAPI #define CONFIG_KLIPS_ENC_CRYPTOAPI 1 #endif /* off by default requires kernel patch */ #if 0 # ifndef CONFIG_KLIPS_OCF # define CONFIG_KLIPS_OCF 1 # endif #endif #undef CONFIG_KLIPS_OCF #ifndef CONFIG_KLIPS_ALG_AES_MAC #define CONFIG_KLIPS_ALG_AES_MAC 1 #endif /* ALGO: */ #if 0 /* goal: cleanup KLIPS code from hardcoded algos :} */ # undef CONFIG_KLIPS_AUTH_HMAC_MD5 # undef CONFIG_KLIPS_AUTH_HMAC_SHA1 # undef CONFIG_KLIPS_ENC_3DES #endif #ifndef CONFIG_KLIPS_ALG #define CONFIG_KLIPS_ALG 1 #endif #endif /* _CONFIG_ALL_H */ libreswan-3.32/packaging/linus/config-all.hmodules000066400000000000000000000045571365625662500223150ustar00rootroot00000000000000#ifndef _CONFIG_ALL_H_ /* * Copyright (C) 2002 Michael Richardson * Copyright (C) 2011 Paul Wouters * * This kernel module is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This kernel module is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public * License for more details. * */ #define _CONFIG_ALL_H_ /* seen it, no need to see it again */ #define CONFIG_KLIPS_MODULES 1 #ifndef CONFIG_KLIPS_AH #define CONFIG_KLIPS_AH 1 #endif #ifndef CONFIG_KLIPS_DEBUG #define CONFIG_KLIPS_DEBUG 1 #endif #ifndef CONFIG_KLIPS_ESP #define CONFIG_KLIPS_ESP 1 #endif #ifndef CONFIG_KLIPS_IPCOMP #define CONFIG_KLIPS_IPCOMP 1 #endif #ifndef CONFIG_KLIPS_IPIP #define CONFIG_KLIPS_IPIP 1 #endif #ifndef CONFIG_KLIPS_AUTH_HMAC_MD5 #define CONFIG_KLIPS_AUTH_HMAC_MD5 1 #endif #ifndef CONFIG_KLIPS_AUTH_HMAC_SHA1 #define CONFIG_KLIPS_AUTH_HMAC_SHA1 1 #endif #ifndef CONFIG_KLIPS_DYNDEV #define CONFIG_KLIPS_DYNDEV 1 #endif #ifndef CONFIG_KLIPS_ENC_3DES #define CONFIG_KLIPS_ENC_3DES 1 #endif /* no longer needed as of 2.6.22 and up */ #if 0 # ifndef CONFIG_KLIPS_NAT_TRAVERSAL # define CONFIG_KLIPS_NAT_TRAVERSAL 1 # define CONFIG_KLIPS_COMPAT_NAT_NFMARK 1 # endif #endif #undef CONFIG_KLIPS_NAT_TRAVERSAL #undef CONFIG_KLIPS_COMPAT_NAT_NFMARK #ifndef CONFIG_KLIPS_ENC_AES #define CONFIG_KLIPS_ENC_AES 1 #endif #ifndef CONFIG_KLIPS_ENC_CRYPTOAPI #define CONFIG_KLIPS_ENC_CRYPTOAPI 1 #endif #if 0 /* off by default requiers kernel patch */ # ifndef CONFIG_KLIPS_OCF # define CONFIG_KLIPS_OCF 1 # endif #endif #undef CONFIG_KLIPS_OCF #define CONFIG_KLIPS_ALG_CRYPTOAPI #error #define CONFIG_KLIPS_ALG_AES #error #ifndef CONFIG_KLIPS_ALG_AES_MAC #define CONFIG_KLIPS_ALG_AES_MAC 1 #endif /* ALGO: */ #if 0 /* goal: cleanup KLIPS code from hardcoded algos :} */ # undef CONFIG_KLIPS_AUTH_HMAC_MD5 # undef CONFIG_KLIPS_AUTH_HMAC_SHA1 # undef CONFIG_KLIPS_ENC_3DES #endif #ifndef CONFIG_KLIPS_ALG #define CONFIG_KLIPS_ALG 1 #endif #endif /* _CONFIG_ALL_H */ libreswan-3.32/packaging/makefiles/000077500000000000000000000000001365625662500173335ustar00rootroot00000000000000libreswan-3.32/packaging/makefiles/module.defs000066400000000000000000000017021365625662500214630ustar00rootroot00000000000000# To config as static (preferred), 'y'. To config as module, 'm'. CONFIG_KLIPS=m # To enable authentication without encryption, say 'y'. (Not so recommended) CONFIG_KLIPS_AH=y CONFIG_KLIPS_IPIP=y # Authentication algorithm(s): CONFIG_KLIPS_AUTH_HMAC_MD5=m CONFIG_KLIPS_AUTH_HMAC_SHA1=m # To enable encryption with authentication, say 'y'. (Highly recommended) CONFIG_KLIPS_ESP=y # modular algo extensions (and new ALGOs) CONFIG_KLIPS_ALG=y # Encryption algorithm(s): CONFIG_KLIPS_ENC_3DES=y CONFIG_KLIPS_ENC_AES=y CONFIG_KLIPS_ALG_TWOFISH=m CONFIG_KLIPS_ALG_BLOWFISH=m CONFIG_KLIPS_ALG_SERPENT=m CONFIG_KLIPS_ALG_MD5=m CONFIG_KLIPS_ALG_SHA1=m CONFIG_KLIPS_ALG_SHA2=m #CONFIG_KLIPS_ALG_CAST=n #CONFIG_KLIPS_ALG_NULL=n # Use CryptoAPI for ALG? - by default, no. CONFIG_KLIPS_ENC_CRYPTOAPI=y # IP Compression: new, probably still has minor bugs. CONFIG_KLIPS_IPCOMP=y # To enable userspace-switchable KLIPS debugging, say 'y'. CONFIG_KLIPS_DEBUG=y libreswan-3.32/packaging/makefiles/module.make000066400000000000000000000037221365625662500214630ustar00rootroot00000000000000# I really am not happy about using symlinks to make this work. # # I think that there should be a better way to do this. # see module26.sh in packaging/makefiles # ifndef LIBRESWANSRCDIR $(error You Must set LIBRESWANSRCDIR) endif include ${LIBRESWANSRCDIR}/Makefile.inc KLIPS_TOP := ${LIBRESWANSRCDIR}/linux # include file with .h-style macros that would otherwise be created by # config. Must occur before other includes. ifneq ($(strip $(MODULE_EXTRA_INCLUDE)),) EXTRA_CFLAGS += -include ${MODULE_EXTRA_INCLUDE} endif ifneq ($(strip $(MODULE_DEF_INCLUDE)),) EXTRA_CFLAGS += -include ${MODULE_DEF_INCLUDE} endif # Enable DISABLE_UDP_CHECKSUM for KLIPS, see bug #601 EXTRA_CFLAGS += -DDISABLE_UDP_CHECKSUM EXTRA_CFLAGS += -I${KLIPS_TOP}/include #EXTRA_CFLAGS += -I${LIBRESWANSRCDIR}/include EXTRA_CFLAGS += -I${KLIPSSRC}/. # build version.c using version number from Makefile.ver ${BUILDDIR}/version.c: ${KLIPSSRC}/version.in.c ${LIBRESWANSRCDIR}/Makefile.ver sed '/"/s/@IPSECVERSION@/$(IPSECVERSION)/' ${KLIPSSRC}/version.in.c >$@ ${BUILDDIR}/%.c : ${KLIPSSRC}/%.c ln -s -f $< $@ ${BUILDDIR}/%.h : ${KLIPSSRC}/%.h ln -s -f $< $@ ${BUILDDIR}/%.c : ${KLIPSSRC}/des/%.c ln -s -f $< $@ ${BUILDDIR}/%.S : ${KLIPSSRC}/des/%.S ln -s -f $< $@ ${BUILDDIR}/%.c : ${KLIPSSRC}/aes/%.c ln -s -f $< $@ ${BUILDDIR}/%.c : ${KLIPSSRC}/alg/%.c ln -s -f $< $@ .PRECIOUS: ${BUILDDIR}/%.c ${BUILDDIR}/%.h # I'm not fixing this in a better way, because we should use the # in-kernel zlib! ${BUILDDIR}/deflate.c: ${BUILDDIR}/deflate.h ${BUILDDIR}/infblock.c: ${BUILDDIR}/infblock.h ${BUILDDIR}/inftrees.h ${BUILDDIR}/infblock.c: ${BUILDDIR}/infcodes.h ${BUILDDIR}/infutil.h ${BUILDDIR}/infcodes.c: ${BUILDDIR}/inffast.h ${BUILDDIR}/inftrees.c: ${BUILDDIR}/inffixed.h ${BUILDDIR}/trees.c: ${BUILDDIR}/trees.h MODULE26=true include ${LIBRESWANSRCDIR}/packaging/makefiles/module.defs ifneq ($(strip $(MODULE_DEFCONFIG)),) include ${MODULE_DEFCONFIG} endif include ${KLIPSSRC}/Makefile.fs2_6 libreswan-3.32/packaging/makefiles/module.sh000077500000000000000000000006111365625662500211550ustar00rootroot00000000000000#!/bin/sh LIBRESWANSRCDIR=/mara4/libreswan-2/klips26 KERNELSRC=/mara4/libreswan-2/klips26/UMLPOOL/plain26 MODULE_DEF_INCLUDE=${LIBRESWANSRCDIR}/packaging/linus/config-all.h export LIBRESWANSRCDIR KERNELSRC MODULE_DEF_INCLUDE #SUBDIRS=${LIBRESWANSRCDIR}/linux/net/ipsec make --debug=biv -C ${KERNELSRC} V=1 BUILDDIR=`pwd` SUBDIRS=`pwd` MODULE_DEF_INCLUDE=${MODULE_DEF_INCLUDE} ARCH=um $* libreswan-3.32/packaging/makefiles/module24.make000066400000000000000000000026221365625662500216270ustar00rootroot00000000000000ifndef LIBRESWANSRCDIR $(error You Must set LIBRESWANSRCDIR) endif include ${LIBRESWANSRCDIR}/Makefile.inc export TOPDIR CONFIG_SHELL=/bin/sh export CONFIG_SHELL CONFIG_MODULES=true KLIPS_TOP=${LIBRESWANSRCDIR}/linux VPATH+=${KLIPSSRC} # include file with .h-style macros that would otherwise be created by # config. Must occur before other includes. ifneq ($(strip $(MODULE_DEF_INCLUDE)),) EXTRA_CFLAGS += -include ${MODULE_DEF_INCLUDE} endif # Enable DISABLE_UDP_CHECKSUM for KLIPS, see bug #601 EXTRA_CFLAGS += -DDISABLE_UDP_CHECKSUM EXTRA_CFLAGS += $(KLIPSCOMPILE) EXTRA_CFLAGS += -Wall -DIPCOMP_PREFIX #EXTRA_CFLAGS += -Werror #EXTRA_CFLAGS += -Wconversion #EXTRA_CFLAGS += -Wmissing-prototypes # 'override CFLAGS' should really be 'EXTRA_CFLAGS' KERNEL_CFLAGS= $(shell $(MAKE) -C $(TOPDIR) --no-print-directory -s -f Makefile ARCH=$(ARCH) MAKEFLAGS= script SCRIPT='@echo $$(CFLAGS)' ) MODULE_CFLAGS= $(shell $(MAKE) -C $(TOPDIR) --no-print-directory -s -f Makefile ARCH=$(ARCH) MAKEFLAGS= script SCRIPT='@echo $$(MODFLAGS)' ) EXTRA_CFLAGS += ${KERNEL_CFLAGS} EXTRA_CFLAGS += -I${KLIPS_TOP}/include #EXTRA_CFLAGS += -I${LIBRESWANSRCDIR}/include EXTRA_CFLAGS += -I${KLIPSSRC}/. EXTRA_CFLAGS += -I${TOPDIR}/include EXTRA_CFLAGS += -I${LIBZLIBSRCDIR} version.c: ${KLIPSSRC}/version.in.c ${LIBRESWANSRCDIR}/Makefile.ver sed '/"/s/@IPSECVERSION@/$(IPSECVERSION)/' $< >$@ include ${KLIPSSRC}/Makefile.fs2_4 libreswan-3.32/packaging/ocf/000077500000000000000000000000001365625662500161425ustar00rootroot00000000000000libreswan-3.32/packaging/ocf/config-all.h000066400000000000000000000047641365625662500203410ustar00rootroot00000000000000#ifndef _CONFIG_ALL_H_ /* * Copyright (C) 2002 Michael Richardson * Copyright (C) 2011 Paul Wouters * * This kernel module is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This kernel module is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public * License for more details. * * This is the OCF version. It builds support for 3 crypto subsystems, and KLIPS * will use the first one found in the following order: OCF, CryptoAPI, inline * Cryptoapi might support more ciphers then the other subsystems. * Requires ocf kernel module - see http://ocf-linux.sf.net/ */ #define _CONFIG_ALL_H_ /* seen it, no need to see it again */ #define CONFIG_KLIPS 1 #ifndef CONFIG_KLIPS_AH #define CONFIG_KLIPS_AH 1 #endif #ifndef CONFIG_KLIPS_DEBUG #define CONFIG_KLIPS_DEBUG 1 #endif #ifndef CONFIG_KLIPS_ESP #define CONFIG_KLIPS_ESP 1 #endif #ifndef CONFIG_KLIPS_IPCOMP #define CONFIG_KLIPS_IPCOMP 1 #endif #ifndef CONFIG_KLIPS_IPIP #define CONFIG_KLIPS_IPIP 1 #endif #ifndef CONFIG_KLIPS_AUTH_HMAC_MD5 #define CONFIG_KLIPS_AUTH_HMAC_MD5 1 #endif #ifndef CONFIG_KLIPS_AUTH_HMAC_SHA1 #define CONFIG_KLIPS_AUTH_HMAC_SHA1 1 #endif #ifndef CONFIG_KLIPS_DYNDEV #define CONFIG_KLIPS_DYNDEV 1 #endif #ifndef CONFIG_KLIPS_ENC_3DES #define CONFIG_KLIPS_ENC_3DES 1 #endif /* no longer needed on 2.6.22 and newer */ #if 0 # ifndef CONFIG_IPSEC_NAT_TRAVERSAL # define CONFIG_IPSEC_NAT_TRAVERSAL 1 # endif #endif #undef CONFIG_IPSEC_NAT_TRAVERSAL #ifndef CONFIG_KLIPS_ENC_AES #define CONFIG_KLIPS_ENC_AES 1 #endif /* enable cryptoapi as well */ #ifndef CONFIG_KLIPS_ENC_CRYPTOAPI #define CONFIG_KLIPS_ENC_CRYPTOAPI 1 #endif /* requires ocf kernel module - see http://ocf-linux.sf.net */ #ifndef CONFIG_KLIPS_OCF # define CONFIG_KLIPS_OCF 1 #endif #ifndef CONFIG_KLIPS_ALG_AES_MAC #define CONFIG_KLIPS_ALG_AES_MAC 1 #endif /* ALGO: */ #if 0 /* goal: cleanup KLIPS code from hardcoded algos :} */ # undef CONFIG_KLIPS_AUTH_HMAC_MD5 # undef CONFIG_KLIPS_AUTH_HMAC_SHA1 # undef CONFIG_KLIPS_ENC_3DES #endif #ifndef CONFIG_KLIPS_ALG #define CONFIG_KLIPS_ALG 1 #endif #endif /* _CONFIG_ALL_H */ libreswan-3.32/packaging/ocf/config-all.hmodules000066400000000000000000000046341365625662500217260ustar00rootroot00000000000000#ifndef _CONFIG_ALL_H_ /* * Copyright (C) 2002 Michael Richardson * Copyright (C) 2011 Paul Wouters * * This kernel module is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This kernel module is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public * License for more details. * * This is the OCF version. It builds support for 3 crypto subsystems, and KLIPS * will use the first one found in the following order: OCF, CryptoAPI, inline * Cryptoapi might support more ciphers then the other subsystems. * Requires ocf kernel module - see http://ocf-linux.sf.net/ */ #define _CONFIG_ALL_H_ /* seen it, no need to see it again */ #define CONFIG_KLIPS 1 #define CONFIG_KLIPS_MODULE 1 #ifndef CONFIG_KLIPS_AH #define CONFIG_KLIPS_AH 1 #endif #ifndef CONFIG_KLIPS_DEBUG #define CONFIG_KLIPS_DEBUG 1 #endif #ifndef CONFIG_KLIPS_ESP #define CONFIG_KLIPS_ESP 1 #endif #ifndef CONFIG_KLIPS_IPCOMP #define CONFIG_KLIPS_IPCOMP 1 #endif #ifndef CONFIG_KLIPS_IPIP #define CONFIG_KLIPS_IPIP 1 #endif #ifndef CONFIG_KLIPS_AUTH_HMAC_MD5 #define CONFIG_KLIPS_AUTH_HMAC_MD5 1 #endif #ifndef CONFIG_KLIPS_AUTH_HMAC_SHA1 #define CONFIG_KLIPS_AUTH_HMAC_SHA1 1 #endif #ifndef CONFIG_KLIPS_DYNDEV #define CONFIG_KLIPS_DYNDEV 1 #endif #ifndef CONFIG_KLIPS_ENC_3DES #define CONFIG_KLIPS_ENC_3DES 1 #endif /* no longer required for 2.6.22 and up */ #if 0 # ifndef CONFIG_KLIPS_NAT_TRAVERSAL # define CONFIG_KLIPS_NAT_TRAVERSAL 1 # define CONFIG_KLIPS_COMPAT_NAT_NFMARK 1 # endif #endif #undef CONFIG_KLIPS_NAT_TRAVERSAL #undef CONFIG_KLIPS_COMPAT_NAT_NFMARK #ifndef CONFIG_KLIPS_ENC_AES #define CONFIG_KLIPS_ENC_AES 1 #endif #ifndef CONFIG_KLIPS_ENC_CRYPTOAPI #define CONFIG_KLIPS_ENC_CRYPTOAPI 1 #endif #ifndef CONFIG_KLIPS_OCF # define CONFIG_KLIPS_OCF 1 #endif #define CONFIG_KLIPS_ALG_CRYPTOAPI #error #define CONFIG_KLIPS_ALG_AES #error #ifndef CONFIG_KLIPS_ALG_AES_MAC #define CONFIG_KLIPS_ALG_AES_MAC 1 #endif #ifndef CONFIG_KLIPS_ALG #define CONFIG_KLIPS_ALG 1 #endif #endif /* _CONFIG_ALL_H */ libreswan-3.32/packaging/ocf/defconfig000066400000000000000000000025751365625662500200220ustar00rootroot00000000000000# # Libreswan IPsec implementation, KLIPS+OCF kernel config defaults # # # First, let's override stuff already set or not in the kernel config. # # We can't even think about leaving this off... CONFIG_INET=y # # This must be on for subnet protection. CONFIG_IP_FORWARD=y # Shut off IPSEC masquerading if it has been enabled, since it will # break the compile. IPPROTO_ESP and IPPROTO_AH were included in # net/ipv4/ip_masq.c when they should have gone into include/linux/in.h. CONFIG_IP_MASQUERADE_IPSEC=n # # Next, let's set the recommended FreeS/WAN configuration. # # To config as static (preferred), 'y'. To config as module, 'm'. CONFIG_KLIPS=m # To do tunnel mode IPsec, this must be enabled. CONFIG_KLIPS_IPIP=y # To enable authentication, say 'y'. (Highly recommended) CONFIG_KLIPS_AH=y # Authentication algorithm(s): CONFIG_KLIPS_AUTH_HMAC_MD5=y CONFIG_KLIPS_AUTH_HMAC_SHA1=y # To enable encryption, say 'y'. (Highly recommended) CONFIG_KLIPS_ESP=y # modular algo extensions (and new ALGOs) CONFIG_KLIPS_ALG=y # Encryption algorithm(s): CONFIG_KLIPS_ENC_3DES=y CONFIG_KLIPS_ENC_AES=y # Use CryptoAPI for ALG? - by default, no. CONFIG_KLIPS_ENC_CRYPTOAPI=y # IP Compression: new, probably still has minor bugs. CONFIG_KLIPS_IPCOMP=y # To enable userspace-switchable KLIPS debugging, say 'y'. CONFIG_KLIPS_DEBUG=y # OCF HW offloading, requires kernel patch CONFIG_KLIPS_OCF=y libreswan-3.32/packaging/rhel/000077500000000000000000000000001365625662500163255ustar00rootroot00000000000000libreswan-3.32/packaging/rhel/6/000077500000000000000000000000001365625662500164725ustar00rootroot00000000000000libreswan-3.32/packaging/rhel/6/libreswan.spec000066400000000000000000000156271365625662500213470ustar00rootroot00000000000000# These are rpm macros and are 0 or 1 %global with_cavstests 1 %global with_development 0 %global with_efence 0 # There is no new enough unbound on rhel6 %global with_dnssec 0 %global nss_version 3.34.0-4 # _rundir is not defined on rhel6 %{!?_rundir:%global _rundir %{_localstatedir}/run} # Libreswan config options %global libreswan_config \\\ FINALLIBEXECDIR=%{_libexecdir}/ipsec \\\ FINALMANDIR=%{_mandir} \\\ FINALRUNDIR=%{_rundir}/pluto \\\ FIPSPRODUCTCHECK=%{_sysconfdir}/system-fips \\\ INC_RCDEFAULT=%{_initrddir} \\\ INC_USRLOCAL=%{_prefix} \\\ INITSYSTEM=sysvinit \\\ PYTHON_BINARY=%{__python} \\\ USE_DNSSEC=%{USE_DNSSEC} \\\ USE_FIPSCHECK=true \\\ USE_KLIPS=false \\\ USE_LABELED_IPSEC=true \\\ USE_LDAP=true \\\ USE_LIBCAP_NG=true \\\ USE_LIBCURL=true \\\ USE_LINUX_AUDIT=true \\\ USE_NM=true \\\ USE_NSS_IPSEC_PROFILE=false \\\ USE_SECCOMP=false \\\ USE_XAUTHPAM=true \\\ %{nil} #global prever rc1 Name: libreswan Summary: Internet Key Exchange (IKEv1 and IKEv2) implementation for IPsec Version: 3.32 Release: %{?prever:0.}1%{?prever:.%{prever}}%{?dist} License: GPLv2 Url: https://libreswan.org/ Source0: https://download.libreswan.org/%{?prever:development/}%{name}-%{version}%{?prever}.tar.gz %if 0%{with_cavstests} Source10: https://download.libreswan.org/cavs/ikev1_dsa.fax.bz2 Source11: https://download.libreswan.org/cavs/ikev1_psk.fax.bz2 Source12: https://download.libreswan.org/cavs/ikev2.fax.bz2 %endif BuildRequires: audit-libs-devel BuildRequires: bison BuildRequires: curl-devel BuildRequires: fipscheck-devel BuildRequires: flex BuildRequires: libcap-ng-devel BuildRequires: libevent2-devel BuildRequires: libselinux-devel BuildRequires: nspr-devel BuildRequires: nss-devel >= %{nss_version} BuildRequires: nss-tools BuildRequires: openldap-devel BuildRequires: pam-devel BuildRequires: pkgconfig BuildRequires: pkgconfig net-tools BuildRequires: redhat-rpm-config BuildRequires: xmlto %if 0%{with_efence} BuildRequires: ElectricFence %endif %if 0%{with_dnssec} BuildRequires: ldns-devel BuildRequires: unbound-devel >= 1.6.0 Requires: unbound-libs >= 1.6.0 %global USE_DNSSEC true %else %global USE_DNSSEC false %endif Requires: fipscheck%{_isa} Requires: iproute >= 2.6.8 Requires: nss >= %{nss_version} Requires: nss-softokn Requires: nss-tools Requires(post): /sbin/chkconfig Requires(preun): /sbin/chkconfig Requires(preun): /sbin/service Conflicts: openswan < %{version}-%{release} Obsoletes: openswan < %{version}-%{release} Provides: openswan = %{version}-%{release} Provides: openswan-doc = %{version}-%{release} %description Libreswan is a free implementation of IPsec & IKE for Linux. IPsec is the Internet Protocol Security and uses strong cryptography to provide both authentication and encryption services. These services allow you to build secure tunnels through untrusted networks. Everything passing through the untrusted net is encrypted by the ipsec gateway machine and decrypted by the gateway at the other end of the tunnel. The resulting tunnel is a virtual private network or VPN. This package contains the daemons and userland tools for setting up Libreswan. To build KLIPS, see the kmod-libreswan.spec file. Libreswan also supports IKEv2 (RFC7296) and Secure Labeling Libreswan is based on Openswan-2.6.38 which in turn is based on FreeS/WAN-2.04 %prep %setup -q -n libreswan-%{version}%{?prever} %build make %{?_smp_mflags} \ %if 0%{with_development} OPTIMIZE_CFLAGS="%{?_hardened_cflags}" \ %else OPTIMIZE_CFLAGS="%{optflags}" \ %endif %if 0%{with_efence} USE_EFENCE=true \ %endif WERROR_CFLAGS="-Werror -Wno-missing-field-initializers" \ USERLINK="%{?__global_ldflags}" \ %{libreswan_config} \ programs FS=$(pwd) # Add generation of HMAC checksums of the final stripped binaries %define __spec_install_post \ %{?__debug_package:%{__debug_install_post}} \ %{__arch_install_post} \ %{__os_install_post} \ fipshmac %{buildroot}%{_libexecdir}/ipsec/pluto \ %{nil} %install make \ DESTDIR=%{buildroot} \ %{libreswan_config} \ install FS=$(pwd) rm -rf %{buildroot}/usr/share/doc/libreswan rm -rf %{buildroot}%{_libexecdir}/ipsec/*check install -d -m 0755 %{buildroot}%{_rundir}/pluto # used when setting --perpeerlog without --perpeerlogbase install -d -m 0700 %{buildroot}%{_localstatedir}/log/pluto/peer install -d %{buildroot}%{_sbindir} # replace with rhel[56] specific version install -m 0755 initsystems/sysvinit/init.rhel \ %{buildroot}%{_initrddir}/ipsec echo "include %{_sysconfdir}/ipsec.d/*.secrets" \ > %{buildroot}%{_sysconfdir}/ipsec.secrets rm -fr %{buildroot}%{_sysconfdir}/rc.d/rc* install -d %{buildroot}%{_sysconfdir}/prelink.conf.d/ install -m644 packaging/rhel/libreswan-prelink.conf \ %{buildroot}%{_sysconfdir}/prelink.conf.d/libreswan-fips.conf %if 0%{with_cavstests} %check # There is an elaborate upstream testing infrastructure which we do not # run here. # We only run the CAVS tests here. cp %{SOURCE10} %{SOURCE11} %{SOURCE12} . bunzip2 *.fax.bz2 # work around for older xen based machines export NSS_DISABLE_HW_GCM=1 : starting CAVS test for IKEv2 %{buildroot}%{_libexecdir}/ipsec/cavp -v2 ikev2.fax | \ diff -u ikev2.fax - > /dev/null : starting CAVS test for IKEv1 RSASIG %{buildroot}%{_libexecdir}/ipsec/cavp -v1dsa ikev1_dsa.fax | \ diff -u ikev1_dsa.fax - > /dev/null : starting CAVS test for IKEv1 PSK %{buildroot}%{_libexecdir}/ipsec/cavp -v1psk ikev1_psk.fax | \ diff -u ikev1_psk.fax - > /dev/null : CAVS tests passed %endif %post /sbin/chkconfig --add ipsec || : prelink -u %{_libexecdir}/ipsec/* 2>/dev/null || : %preun if [ $1 -eq 0 ]; then /sbin/service ipsec stop > /dev/null 2>&1 || : /sbin/chkconfig --del ipsec fi %postun if [ $1 -ge 1 ] ; then /sbin/service ipsec condrestart 2>&1 >/dev/null || : fi %files %doc CHANGES COPYING CREDITS README* LICENSE %doc docs/*.* docs/examples %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ipsec.conf %attr(0600,root,root) %config(noreplace) %{_sysconfdir}/ipsec.secrets %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/sysconfig/pluto %attr(0700,root,root) %dir %{_sysconfdir}/ipsec.d %attr(0700,root,root) %dir %{_sysconfdir}/ipsec.d/policies %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ipsec.d/policies/* %attr(0700,root,root) %dir %{_localstatedir}/log/pluto %attr(0700,root,root) %dir %{_localstatedir}/log/pluto/peer %attr(0755,root,root) %dir %{_rundir}/pluto %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/pam.d/pluto %{_sbindir}/ipsec %attr(0755,root,root) %dir %{_libexecdir}/ipsec %{_libexecdir}/ipsec/* %attr(0644,root,root) %{_mandir}/*/*.gz %{_initrddir}/ipsec %{_libexecdir}/ipsec/.pluto.hmac # We own the directory so we don't have to require prelink %attr(0755,root,root) %dir %{_sysconfdir}/prelink.conf.d/ %{_sysconfdir}/prelink.conf.d/libreswan-fips.conf %changelog * Mon Mar 30 2020 Team Libreswan - 3.32-1 - Automated build from release tar ball libreswan-3.32/packaging/rhel/7/000077500000000000000000000000001365625662500164735ustar00rootroot00000000000000libreswan-3.32/packaging/rhel/7/libreswan.spec000066400000000000000000000166311365625662500213440ustar00rootroot00000000000000# These are rpm macros and are 0 or 1 %global _hardened_build 1 %global with_efence 0 %global with_development 0 %global with_cavstests 1 # There is no new enough unbound on rhel7 %global with_dnssec 0 %global nss_version 3.36.0-7.1 # Libreswan config options %global libreswan_config \\\ USE_KLIPS=false \\\ FINALLIBEXECDIR=%{_libexecdir}/ipsec \\\ FINALMANDIR=%{_mandir} \\\ INC_RCDEFAULT=%{_initrddir} \\\ INC_USRLOCAL=%{_prefix} \\\ INITSYSTEM=systemd \\\ PYTHON_BINARY=%{__python} \\\ USE_DNSSEC=%{USE_DNSSEC} \\\ USE_FIPSCHECK=true \\\ USE_LABELED_IPSEC=true \\\ USE_LDAP=true \\\ USE_LIBCAP_NG=true \\\ USE_LIBCURL=true \\\ USE_NM=true \\\ USE_NSS_IPSEC_PROFILE=true \\\ USE_SECCOMP=true \\\ USE_XAUTHPAM=true \\\ USE_XFRM_INTERFACE_IFLA_HEADER=true \\\ USE_NSS_PRF=true \\\ %{nil} #global prever rc1 Name: libreswan Summary: Internet Key Exchange (IKEv1 and IKEv2) implementation for IPsec Version: 3.32 Release: %{?prever:0.}1%{?prever:.%{prever}}%{?dist} License: GPLv2 Url: https://libreswan.org/ Source0: https://download.libreswan.org/%{?prever:development/}%{name}-%{version}%{?prever}.tar.gz %if 0%{with_cavstests} Source10: https://download.libreswan.org/cavs/ikev1_dsa.fax.bz2 Source11: https://download.libreswan.org/cavs/ikev1_psk.fax.bz2 Source12: https://download.libreswan.org/cavs/ikev2.fax.bz2 %endif BuildRequires: audit-libs-devel BuildRequires: bison BuildRequires: curl-devel BuildRequires: fipscheck-devel BuildRequires: flex BuildRequires: hostname BuildRequires: libcap-ng-devel BuildRequires: libevent-devel BuildRequires: libseccomp-devel BuildRequires: libselinux-devel BuildRequires: nspr-devel BuildRequires: nss-devel >= %{nss_version} BuildRequires: nss-tools BuildRequires: openldap-devel BuildRequires: pam-devel BuildRequires: pkgconfig BuildRequires: pkgconfig BuildRequires: redhat-rpm-config BuildRequires: systemd-devel BuildRequires: xmlto %if 0%{with_efence} BuildRequires: ElectricFence %endif %if 0%{with_dnssec} BuildRequires: ldns-devel BuildRequires: unbound-devel >= 1.6.0 Requires: unbound-libs >= 1.6.0 %global USE_DNSSEC true %else %global USE_DNSSEC false %endif Requires: fipscheck%{_isa} Requires: iproute Requires: nss >= %{nss_version} Requires: nss-softokn Requires: nss-tools Requires(post): bash Requires(post): coreutils Requires(post): systemd Requires(postun): systemd Requires(preun): systemd Conflicts: openswan < %{version}-%{release} Obsoletes: openswan < %{version}-%{release} Provides: openswan = %{version}-%{release} Provides: openswan-doc = %{version}-%{release} %description Libreswan is a free implementation of IPsec & IKE for Linux. IPsec is the Internet Protocol Security and uses strong cryptography to provide both authentication and encryption services. These services allow you to build secure tunnels through untrusted networks. Everything passing through the untrusted net is encrypted by the ipsec gateway machine and decrypted by the gateway at the other end of the tunnel. The resulting tunnel is a virtual private network or VPN. This package contains the daemons and userland tools for setting up Libreswan. Libreswan also supports IKEv2 (RFC7296) and Secure Labeling Libreswan is based on Openswan-2.6.38 which in turn is based on FreeS/WAN-2.04 %prep %setup -q -n libreswan-%{version}%{?prever} %build make %{?_smp_mflags} \ %if 0%{with_development} OPTIMIZE_CFLAGS="%{?_hardened_cflags}" \ %else OPTIMIZE_CFLAGS="%{optflags}" \ %endif %if 0%{with_efence} USE_EFENCE=true \ %endif WERROR_CFLAGS="-Werror -Wno-missing-field-initializers" \ USERLINK="%{?__global_ldflags}" \ %{libreswan_config} \ programs FS=$(pwd) # Add generation of HMAC checksums of the final stripped binaries %define __spec_install_post \ %{?__debug_package:%{__debug_install_post}} \ %{__arch_install_post} \ %{__os_install_post} \ fipshmac -d %{buildroot}%{_libdir}/fipscheck %{buildroot}%{_libexecdir}/ipsec/pluto %{nil} %install make \ DESTDIR=%{buildroot} \ %{libreswan_config} \ install FS=$(pwd) rm -rf %{buildroot}/usr/share/doc/libreswan rm -rf %{buildroot}%{_libexecdir}/ipsec/*check install -d -m 0755 %{buildroot}%{_rundir}/pluto # used when setting --perpeerlog without --perpeerlogbase install -d -m 0700 %{buildroot}%{_localstatedir}/log/pluto/peer install -d %{buildroot}%{_sbindir} install -d %{buildroot}%{_sysconfdir}/sysctl.d install -m 0644 packaging/rhel/libreswan-sysctl.conf \ %{buildroot}%{_sysconfdir}/sysctl.d/50-libreswan.conf mkdir -p %{buildroot}%{_libdir}/fipscheck install -d %{buildroot}%{_sysconfdir}/prelink.conf.d/ install -m644 packaging/rhel/libreswan-prelink.conf \ %{buildroot}%{_sysconfdir}/prelink.conf.d/libreswan-fips.conf echo "include /etc/ipsec.d/*.secrets" \ > %{buildroot}%{_sysconfdir}/ipsec.secrets %if 0%{with_cavstests} %check # There is an elaborate upstream testing infrastructure which we do not # run here. # We only run the CAVS tests here. cp %{SOURCE10} %{SOURCE11} %{SOURCE12} . bunzip2 *.fax.bz2 # work around for older xen based machines export NSS_DISABLE_HW_GCM=1 : starting CAVS test for IKEv2 %{buildroot}%{_libexecdir}/ipsec/cavp -v2 ikev2.fax | \ diff -u ikev2.fax - > /dev/null : starting CAVS test for IKEv1 RSASIG %{buildroot}%{_libexecdir}/ipsec/cavp -v1dsa ikev1_dsa.fax | \ diff -u ikev1_dsa.fax - > /dev/null : starting CAVS test for IKEv1 PSK %{buildroot}%{_libexecdir}/ipsec/cavp -v1psk ikev1_psk.fax | \ diff -u ikev1_psk.fax - > /dev/null : CAVS tests passed # Some of these tests will show ERROR for negative testing - it will exit on real errors %{buildroot}%{_libexecdir}/ipsec/algparse -tp || { echo prooposal test failed; exit 1; } %{buildroot}%{_libexecdir}/ipsec/algparse -ta || { echo algorithm test failed; exit 1; } : Algorithm parser tests passed # self test for pluto daemon - this also shows which algorithms it allows in FIPS mode tmpdir=$(mktemp -d /tmp/libreswan-XXXXX) certutil -N -d sql:$tmpdir --empty-password %{buildroot}%{_libexecdir}/ipsec/pluto --selftest --nssdir $tmpdir --rundir $tmpdir : pluto self-test passed - verify FIPS algorithms allowed is still compliant with NIST %endif %post %systemd_post ipsec.service prelink -u %{_libexecdir}/ipsec/* 2>/dev/null || : %preun %systemd_preun ipsec.service %postun %systemd_postun_with_restart ipsec.service %files %doc CHANGES COPYING CREDITS README* LICENSE %doc docs/*.* docs/examples %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ipsec.conf %attr(0600,root,root) %config(noreplace) %{_sysconfdir}/ipsec.secrets %attr(0700,root,root) %dir %{_sysconfdir}/ipsec.d %attr(0700,root,root) %dir %{_sysconfdir}/ipsec.d/policies %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ipsec.d/policies/* %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/sysctl.d/50-libreswan.conf %attr(0700,root,root) %dir %{_localstatedir}/log/pluto %attr(0700,root,root) %dir %{_localstatedir}/log/pluto/peer %attr(0755,root,root) %dir %{_rundir}/pluto %attr(0644,root,root) %{_tmpfilesdir}/libreswan.conf %attr(0644,root,root) %{_unitdir}/ipsec.service %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/pam.d/pluto %{_sbindir}/ipsec %{_libexecdir}/ipsec %doc %{_mandir}/*/* %{_libdir}/fipscheck/pluto.hmac # We own the directory so we don't have to require prelink %dir %{_sysconfdir}/prelink.conf.d/ %{_sysconfdir}/prelink.conf.d/libreswan-fips.conf %changelog * Mon Mar 30 2020 Team Libreswan - 3.32-1 - Automated build from release tar ball libreswan-3.32/packaging/rhel/8/000077500000000000000000000000001365625662500164745ustar00rootroot00000000000000libreswan-3.32/packaging/rhel/8/libreswan.spec000066400000000000000000000162211365625662500213400ustar00rootroot00000000000000%global _hardened_build 1 # These are rpm macros and are 0 or 1 %global with_efence 0 %global with_development 0 %global with_cavstests 1 # minimum version for support for rhbz#1651314 %global nss_version 3.39.0-1.4 %global unbound_version 1.6.6 # Libreswan config options %global libreswan_config \\\ FINALLIBEXECDIR=%{_libexecdir}/ipsec \\\ FINALMANDIR=%{_mandir} \\\ FIPSPRODUCTCHECK=%{_sysconfdir}/system-fips \\\ INC_RCDEFAULT=%{_initrddir} \\\ INC_USRLOCAL=%{_prefix} \\\ INITSYSTEM=systemd \\\ NSS_REQ_AVA_COPY=false \\\ NSS_HAS_IPSEC_PROFILE=true \\\ PYTHON_BINARY=%{__python3} \\\ USE_DNSSEC=true \\\ USE_FIPSCHECK=true \\\ USE_LABELED_IPSEC=true \\\ USE_LDAP=true \\\ USE_LIBCAP_NG=true \\\ USE_LIBCURL=true \\\ USE_LINUX_AUDIT=true \\\ USE_NM=true \\\ USE_SECCOMP=true \\\ USE_XAUTHPAM=true \\\ USE_KLIPS=false \\\ USE_NSS_PRF=true \\\ %{nil} #global prever rc1 Name: libreswan Summary: IPsec implementation with IKEv1 and IKEv2 keying protocols # version is generated in the release script Version: 3.32 Release: %{?prever:0.}1%{?prever:.%{prever}}%{?dist} License: GPLv2 Url: https://libreswan.org/ Source0: https://download.libreswan.org/%{?prever:with_development/}%{name}-%{version}%{?prever}.tar.gz %if 0%{with_cavstests} Source1: https://download.libreswan.org/cavs/ikev1_dsa.fax.bz2 Source2: https://download.libreswan.org/cavs/ikev1_psk.fax.bz2 Source3: https://download.libreswan.org/cavs/ikev2.fax.bz2 %endif BuildRequires: audit-libs-devel BuildRequires: bison BuildRequires: curl-devel BuildRequires: fipscheck-devel BuildRequires: flex BuildRequires: gcc BuildRequires: ldns-devel BuildRequires: libcap-ng-devel BuildRequires: libevent-devel BuildRequires: libseccomp-devel BuildRequires: libselinux-devel BuildRequires: nspr-devel BuildRequires: nss-devel >= %{nss_version} BuildRequires: nss-tools BuildRequires: openldap-devel BuildRequires: pam-devel BuildRequires: pkgconfig BuildRequires: pkgconfig hostname BuildRequires: redhat-rpm-config BuildRequires: systemd-devel BuildRequires: unbound-devel >= %{unbound_version} BuildRequires: xmlto %if 0%{with_efence} BuildRequires: ElectricFence %endif Requires: fipscheck%{_isa} Requires: iproute >= 2.6.8 Requires: nss >= %{nss_version} Requires: nss-softokn Requires: nss-tools Requires: unbound-libs >= %{unbound_version} Requires(post): bash Requires(post): coreutils Requires(post): systemd Requires(preun): systemd Requires(postun): systemd %description Libreswan is a free implementation of IKE/IPsec for Linux. IPsec is the Internet Protocol Security and uses strong cryptography to provide both authentication and encryption services. These services allow you to build secure tunnels through untrusted networks. Everything passing through the untrusted net is encrypted by the ipsec gateway machine and decrypted by the gateway at the other end of the tunnel. The resulting tunnel is a virtual private network or VPN. This package contains the daemons and userland tools for setting up Libreswan. Libreswan also supports IKEv2 (RFC7296) and Secure Labeling Libreswan is based on Openswan-2.6.38 which in turn is based on FreeS/WAN-2.04 %prep %setup -q -n libreswan-%{version}%{?prever} # replace unsupported KLIPS README echo "KLIPS is not supported with RHEL8" > README.KLIPS # linking to freebl is not needed sed -i "s/-lfreebl //" mk/config.mk # enable crypto-policies support sed -i "s:#[ ]*include \(.*\)\(/crypto-policies/back-ends/libreswan.config\)$:include \1\2:" programs/configs/ipsec.conf.in %build make %{?_smp_mflags} \ %if 0%{with_development} OPTIMIZE_CFLAGS="%{?_hardened_cflags}" \ %else OPTIMIZE_CFLAGS="%{optflags}" \ %endif %if 0%{with_efence} USE_EFENCE=true \ %endif WERROR_CFLAGS="-Werror -Wno-missing-field-initializers" \ USERLINK="%{?__global_ldflags}" \ %{libreswan_config} \ programs FS=$(pwd) # Add generation of HMAC checksums of the final stripped binaries %define __spec_install_post \ %{?__debug_package:%{__debug_install_post}} \ %{__arch_install_post} \ %{__os_install_post} \ fipshmac -d %{buildroot}%{_libdir}/fipscheck %{buildroot}%{_libexecdir}/ipsec/pluto \ %{nil} %install make \ DESTDIR=%{buildroot} \ %{libreswan_config} \ install FS=$(pwd) rm -rf %{buildroot}/usr/share/doc/libreswan rm -rf %{buildroot}%{_libexecdir}/ipsec/*check install -d -m 0755 %{buildroot}%{_rundir}/pluto # used when setting --perpeerlog without --perpeerlogbase install -d -m 0700 %{buildroot}%{_localstatedir}/log/pluto/peer install -d %{buildroot}%{_sbindir} install -d %{buildroot}%{_sysconfdir}/sysctl.d install -m 0644 packaging/fedora/libreswan-sysctl.conf \ %{buildroot}%{_sysconfdir}/sysctl.d/50-libreswan.conf mkdir -p %{buildroot}%{_libdir}/fipscheck echo "include %{_sysconfdir}/ipsec.d/*.secrets" \ > %{buildroot}%{_sysconfdir}/ipsec.secrets rm -fr %{buildroot}%{_sysconfdir}/rc.d/rc* %if 0%{with_cavstests} %check # There is an elaborate upstream testing infrastructure which we do not # run here - it takes hours and uses kvm # We only run the CAVS tests. cp %{SOURCE1} %{SOURCE2} %{SOURCE3} . bunzip2 *.fax.bz2 : starting CAVS test for IKEv2 %{buildroot}%{_libexecdir}/ipsec/cavp -v2 ikev2.fax | \ diff -u ikev2.fax - > /dev/null : starting CAVS test for IKEv1 RSASIG %{buildroot}%{_libexecdir}/ipsec/cavp -v1dsa ikev1_dsa.fax | \ diff -u ikev1_dsa.fax - > /dev/null : starting CAVS test for IKEv1 PSK %{buildroot}%{_libexecdir}/ipsec/cavp -v1psk ikev1_psk.fax | \ diff -u ikev1_psk.fax - > /dev/null : CAVS tests passed %{buildroot}%{_libexecdir}/ipsec/algparse -tp || { echo prooposal test failed; exit 1; } %{buildroot}%{_libexecdir}/ipsec/algparse -ta || { echo algorithm test failed; exit 1; } # self test for pluto daemon - this also shows which algorithms it allows in FIPS mode tmpdir=$(mktemp -d /tmp/libreswan-XXXXX) certutil -N -d sql:$tmpdir --empty-password %{buildroot}%{_libexecdir}/ipsec/pluto --selftest --nssdir $tmpdir --rundir $tmpdir : pluto self-test passed - verify FIPS algorithms allowed is still compliant with NIST %endif %post %systemd_post ipsec.service %preun %systemd_preun ipsec.service %postun %systemd_postun_with_restart ipsec.service %files %doc CHANGES COPYING CREDITS README* LICENSE %doc docs/*.* docs/examples %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ipsec.conf %attr(0600,root,root) %config(noreplace) %{_sysconfdir}/ipsec.secrets %attr(0700,root,root) %dir %{_sysconfdir}/ipsec.d %attr(0700,root,root) %dir %{_sysconfdir}/ipsec.d/policies %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ipsec.d/policies/* %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/sysctl.d/50-libreswan.conf %attr(0700,root,root) %dir %{_localstatedir}/log/pluto %attr(0700,root,root) %dir %{_localstatedir}/log/pluto/peer %attr(0755,root,root) %dir %{_rundir}/pluto %attr(0644,root,root) %{_tmpfilesdir}/libreswan.conf %attr(0644,root,root) %{_unitdir}/ipsec.service %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/pam.d/pluto %{_sbindir}/ipsec %{_libexecdir}/ipsec %attr(0644,root,root) %doc %{_mandir}/*/* %{_libdir}/fipscheck/pluto.hmac %changelog * Mon Mar 30 2020 Team Libreswan - 3.32-1 - Automated build from release tar ball libreswan-3.32/packaging/rhel/libreswan-prelink.conf000066400000000000000000000000271365625662500226230ustar00rootroot00000000000000-b /usr/libexec/ipsec/ libreswan-3.32/packaging/rhel/libreswan-sysctl.conf000066400000000000000000000010151365625662500224760ustar00rootroot00000000000000# when using 1 interface for two networks when using NETKEY, the kernel # thinks it can be clever by sending a redirect (cause it cannot tell # an encrypted packet came in, but a decrypted packet came out), # so it sends a bogus ICMP redirect # # We disable redirects for XFRM/IPsec net.ipv6.conf.default.accept_redirects = 0 net.ipv6.conf.all.accept_redirects = 0 net.ipv4.conf.default.send_redirects = 0 net.ipv4.conf.default.accept_redirects = 0 net.ipv4.conf.all.send_redirects = 0 net.ipv4.conf.all.accept_redirects = 0 libreswan-3.32/packaging/suse/000077500000000000000000000000001365625662500163525ustar00rootroot00000000000000libreswan-3.32/packaging/suse/README.build000066400000000000000000000015511365625662500203320ustar00rootroot00000000000000libreswan.spec is a spec file for sles11 and opensuse 11.4. I also use 'build' package and invoke "build --dist sl11.4 --define 'buildklips 1' --debug libreswan.spec" on opensuse 11.4 and kernel modules for all flavors are built. If rpmbuild is used directly, install kernel-syms package and do "rpmbuild --define 'buildklips 1' libreswan.spec". sles10.spec is a spec file for sles10. It needs an additional patch kernelsrc.patch. There are same problems on other projects. ex. http://osdir.com/ml/linux.iscsi.iscsi-target.devel/2006-02/msg00049.html libreswan uses a KERNELSRC variable in Makefile, and it conflicts the same variable in /lib/modules/.../build/Makefile. Without this patch, make process gets into infinite loop. It is the case for older kernels, and it's not the case for RHEL5 though it has older 2.6.18 kernel, it has a very customized Makefile. libreswan-3.32/packaging/suse/README.sles10000066400000000000000000000003051365625662500203360ustar00rootroot00000000000000The sles10.spec file should be used for building on old SLES10 machines. It also uses a required kernel patch "kernelsrc.patch" to work around a clash in libreswan and the kernel using $KERNELSRC libreswan-3.32/packaging/suse/kernelsrc.patch000066400000000000000000000454151365625662500213740ustar00rootroot00000000000000From 694755867a4adf61191bc065541888ad6828cfc6 Mon Sep 17 00:00:00 2001 From: FURUSO Shinichi Date: Mon, 8 Aug 2011 14:01:03 +0900 Subject: [PATCH 1/2] rename KERNELSRC with KERNELDIR for sles10 --- Makefile | 136 +++++++++++++++++++++++++++++----------------------------- Makefile.inc | 12 +++--- Makefile.top | 10 ++-- 3 files changed, 79 insertions(+), 79 deletions(-) diff --git a/Makefile b/Makefile index 462bd77..1973524 100644 --- a/Makefile +++ b/Makefile @@ -31,10 +31,10 @@ def: @echo "Commonly used build commands:" @echo @echo "When using KLIPS:" - @echo " make KERNELSRC=/usr/src/linux-2.6.36 module minstall programs install" + @echo " make KERNELDIR=/usr/src/linux-2.6.36 module minstall programs install" @echo @echo "When using KLIPS with OCF:" - @echo " make KERNELSRC=/usr/src/linux-2.6.36-ocf/ MODULE_DEF_INCLUDE=$${LIBRESWANSRCDIR}/packaging/ocf/config-all.hmodules module minstall programs install" + @echo " make KERNELDIR=/usr/src/linux-2.6.36-ocf/ MODULE_DEF_INCLUDE=$${LIBRESWANSRCDIR}/packaging/ocf/config-all.hmodules module minstall programs install" @echo @echo "When using NETKEY:" @echo " make programs install" @@ -47,7 +47,7 @@ include ${LIBRESWANSRCDIR}/Makefile.top # kernel details # what variant of our patches should we use, and where is it -KERNELREL=$(shell ${KVSHORTUTIL} ${KERNELSRC}/Makefile) +KERNELREL=$(shell ${KVSHORTUTIL} ${KERNELDIR}/Makefile) # directories visited by all recursion @@ -70,37 +70,37 @@ npatch: unapplynpatch applynpatch sarefpatch: unapplysarefpatch applysarefpatch unapplypatch: - @echo "info: making unapplypatch in `pwd` and KERNELSRC=\"${KERNELSRC}\";" - -@if [ -f ${KERNELSRC}/libreswan.patch ]; then \ + @echo "info: making unapplypatch in `pwd` and KERNELDIR=\"${KERNELDIR}\";" + -@if [ -f ${KERNELDIR}/libreswan.patch ]; then \ echo Undoing previous patches; \ - cat ${KERNELSRC}/libreswan.patch | (cd ${KERNELSRC} && patch -p1 -R --force -E -z .preipsec --reverse --ignore-whitespace ); \ + cat ${KERNELDIR}/libreswan.patch | (cd ${KERNELDIR} && patch -p1 -R --force -E -z .preipsec --reverse --ignore-whitespace ); \ fi applypatch: @echo "info: Now performing forward patches in `pwd`"; - ${MAKE} kernelpatch${KERNELREL} | tee ${KERNELSRC}/libreswan.patch | (cd ${KERNELSRC} && patch -p1 -b -z .preipsec --forward --ignore-whitespace ) + ${MAKE} kernelpatch${KERNELREL} | tee ${KERNELDIR}/libreswan.patch | (cd ${KERNELDIR} && patch -p1 -b -z .preipsec --forward --ignore-whitespace ) unapplynpatch: @echo "info: making unapplynpatch (note the second N) in `pwd`"; - -@if [ -f ${KERNELSRC}/natt.patch ]; then \ + -@if [ -f ${KERNELDIR}/natt.patch ]; then \ echo Undoing previous NAT patches; \ - cat ${KERNELSRC}/natt.patch | (cd ${KERNELSRC} && patch -p1 -R --force -E -z .preipsec --reverse --ignore-whitespace ); \ + cat ${KERNELDIR}/natt.patch | (cd ${KERNELDIR} && patch -p1 -R --force -E -z .preipsec --reverse --ignore-whitespace ); \ fi applynpatch: @echo "info: Now performing forward NAT patches in `pwd`"; - ${MAKE} nattpatch${KERNELREL} | tee ${KERNELSRC}/natt.patch | (cd ${KERNELSRC} && patch -p1 -b -z .preipsec --forward --ignore-whitespace ) + ${MAKE} nattpatch${KERNELREL} | tee ${KERNELDIR}/natt.patch | (cd ${KERNELDIR} && patch -p1 -b -z .preipsec --forward --ignore-whitespace ) unapplysarefpatch: @echo "info: making unapplysarefpatch in `pwd`"; - -@if [ -f ${KERNELSRC}/saref.patch ]; then \ + -@if [ -f ${KERNELDIR}/saref.patch ]; then \ echo Undoing previous saref patches; \ - cat ${KERNELSRC}/saref.patch | (cd ${KERNELSRC} && patch -p1 -R --force -E -z .preng --reverse --ignore-whitespace ); \ + cat ${KERNELDIR}/saref.patch | (cd ${KERNELDIR} && patch -p1 -R --force -E -z .preng --reverse --ignore-whitespace ); \ fi applysarefpatch: @echo "info: Now performing SAref patches in `pwd`"; - ${MAKE} sarefpatch${KERNELREL} | tee ${KERNELSRC}/klipsng.patch | (cd ${KERNELSRC} && patch -p1 -b -z .preng --forward --ignore-whitespace ) + ${MAKE} sarefpatch${KERNELREL} | tee ${KERNELDIR}/klipsng.patch | (cd ${KERNELDIR} && patch -p1 -b -z .preng --forward --ignore-whitespace ) # patch kernel PATCHER=packaging/utils/patcher @@ -111,36 +111,36 @@ patches: _patches: echo "===============" >>out.kpatch - echo "`date` `cd $(KERNELSRC) ; pwd`" >>out.kpatch + echo "`date` `cd $(KERNELDIR) ; pwd`" >>out.kpatch $(MAKE) __patches$(KERNELREL) >>out.kpatch # Linux-2.4.0 version PATCHES22=klips/patches2.2 __patches2.3 __patches2.4: - @$(PATCHER) -v -c $(KERNELSRC) Documentation/Configure.help \ + @$(PATCHER) -v -c $(KERNELDIR) Documentation/Configure.help \ 'CONFIG_KLIPS' $(PATCHES)/Documentation/Configure.help.fs2_2.patch - @$(PATCHER) -v $(KERNELSRC) net/Config.in \ + @$(PATCHER) -v $(KERNELDIR) net/Config.in \ 'CONFIG_KLIPS' $(PATCHES)/net/Config.in.fs2_4.patch - @$(PATCHER) -v $(KERNELSRC) net/Makefile \ + @$(PATCHER) -v $(KERNELDIR) net/Makefile \ 'CONFIG_KLIPS' $(PATCHES)/net/Makefile.fs2_4.patch - @$(PATCHER) -v $(KERNELSRC) net/ipv4/af_inet.c \ + @$(PATCHER) -v $(KERNELDIR) net/ipv4/af_inet.c \ 'CONFIG_KLIPS' $(PATCHES)/net/ipv4/af_inet.c.fs2_4.patch - @$(PATCHER) -v $(KERNELSRC) net/ipv4/udp.c \ + @$(PATCHER) -v $(KERNELDIR) net/ipv4/udp.c \ 'CONFIG_KLIPS' $(PATCHES)/net/ipv4/udp.c.fs2_4.patch - @$(PATCHER) -v $(KERNELSRC) include/net/sock.h \ + @$(PATCHER) -v $(KERNELDIR) include/net/sock.h \ 'CONFIG_KLIPS' $(PATCHES)/include/net/sock.h.fs2_4.patch # Removed patches, will unpatch automatically. - @$(PATCHER) -v $(KERNELSRC) include/linux/proc_fs.h - @$(PATCHER) -v $(KERNELSRC) net/core/dev.c - @$(PATCHER) -v $(KERNELSRC) net/ipv4/protocol.c - @$(PATCHER) -v $(KERNELSRC) drivers/net/Space.c - @$(PATCHER) -v $(KERNELSRC) include/linux/netlink.h - @$(PATCHER) -v $(KERNELSRC) net/netlink/af_netlink.c - @$(PATCHER) -v $(KERNELSRC) net/netlink/netlink_dev.c - @$(PATCHER) -v $(KERNELSRC) drivers/isdn/isdn_net.c + @$(PATCHER) -v $(KERNELDIR) include/linux/proc_fs.h + @$(PATCHER) -v $(KERNELDIR) net/core/dev.c + @$(PATCHER) -v $(KERNELDIR) net/ipv4/protocol.c + @$(PATCHER) -v $(KERNELDIR) drivers/net/Space.c + @$(PATCHER) -v $(KERNELDIR) include/linux/netlink.h + @$(PATCHER) -v $(KERNELDIR) net/netlink/af_netlink.c + @$(PATCHER) -v $(KERNELDIR) net/netlink/netlink_dev.c + @$(PATCHER) -v $(KERNELDIR) drivers/isdn/isdn_net.c klipsdefaults: - @KERNELDEFCONFIG=$(KERNELSRC)/arch/$(ARCH)/defconfig ; \ + @KERNELDEFCONFIG=$(KERNELDIR)/arch/$(ARCH)/defconfig ; \ KERNELCONFIG=$(KCFILE) ; \ if ! egrep -q 'CONFIG_KLIPS' $$KERNELDEFCONFIG ; \ then \ @@ -233,15 +233,15 @@ obsolete_target: # preliminaries precheck: - @if test ! -d $(KERNELSRC) -a ! -L $(KERNELSRC) ; \ + @if test ! -d $(KERNELDIR) -a ! -L $(KERNELDIR) ; \ then \ - echo '*** cannot find directory "$(KERNELSRC)"!!' ; \ + echo '*** cannot find directory "$(KERNELDIR)"!!' ; \ echo '*** may be necessary to add symlink to kernel source' ; \ exit 1 ; \ fi - @if ! cd $(KERNELSRC) ; \ + @if ! cd $(KERNELDIR) ; \ then \ - echo '*** cannot "cd $(KERNELSRC)"!!' ; \ + echo '*** cannot "cd $(KERNELDIR)"!!' ; \ echo '*** may be necessary to add symlink to kernel source' ; \ exit 1 ; \ fi @@ -264,21 +264,21 @@ Makefile: Makefile.ver # configuring (exit statuses disregarded, something fishy here sometimes) xcf: - -cd $(KERNELSRC) ; $(MAKE) $(KERNMAKEOPTS) xconfig + -cd $(KERNELDIR) ; $(MAKE) $(KERNMAKEOPTS) xconfig mcf: - -cd $(KERNELSRC) ; $(MAKE) $(KERNMAKEOPTS) menuconfig + -cd $(KERNELDIR) ; $(MAKE) $(KERNMAKEOPTS) menuconfig pcf: - -cd $(KERNELSRC) ; $(MAKE) $(KERNMAKEOPTS) config + -cd $(KERNELDIR) ; $(MAKE) $(KERNMAKEOPTS) config ocf: - -cd $(KERNELSRC) ; $(MAKE) $(KERNMAKEOPTS) oldconfig + -cd $(KERNELDIR) ; $(MAKE) $(KERNMAKEOPTS) oldconfig rcf: - cd $(KERNELSRC) ; $(MAKE) $(KERNMAKEOPTS) ${NONINTCONFIG} /dev/null + cd $(KERNELDIR) ; $(MAKE) $(KERNMAKEOPTS) ${NONINTCONFIG} /dev/null kclean: - -cd $(KERNELSRC) ; $(MAKE) $(KERNMAKEOPTS) clean + -cd $(KERNELDIR) ; $(MAKE) $(KERNMAKEOPTS) clean confcheck: @if test ! -f $(KCFILE) ; \ @@ -309,11 +309,11 @@ kernel: # we run make dep separately, because there is no point in running ERRCHECK # on the make dep output. # see LKML thread "clean before or after dep?" - ( cd $(KERNELSRC) ; $(MAKE) $(KERNMAKEOPTS) $(KERNCLEAN) $(KERNDEP) ) - ( cd $(KERNELSRC) ; $(MAKE) $(KERNMAKEOPTS) $(KERNEL) ) 2>&1 | tee out.kbuild + ( cd $(KERNELDIR) ; $(MAKE) $(KERNMAKEOPTS) $(KERNCLEAN) $(KERNDEP) ) + ( cd $(KERNELDIR) ; $(MAKE) $(KERNMAKEOPTS) $(KERNEL) ) 2>&1 | tee out.kbuild @if egrep -q '^CONFIG_MODULES=y' $(KCFILE) ; \ then set -x ; \ - ( cd $(KERNELSRC) ; \ + ( cd $(KERNELDIR) ; \ $(MAKE) $(KERNMAKEOPTS) modules 2>&1 ) | tee -a out.kbuild ; \ fi ${ERRCHECK} out.kbuild @@ -347,33 +347,33 @@ ${MOD24BUILDDIR}/Makefile : ${LIBRESWANSRCDIR}/packaging/makefiles/module.make cp ${LIBRESWANSRCDIR}/packaging/makefiles/module.make ${MOD24BUILDDIR}/Makefile echo "# " >> ${MOD24BUILDDIR}/Makefile echo "# Local Variables: " >> ${MOD24BUILDDIR}/Makefile - echo "# compile-command: \"${MAKE} LIBRESWANSRCDIR=${LIBRESWANSRCDIR} ARCH=${ARCH} TOPDIR=${KERNELSRC} ${MODULE_FLAGS} MODULE_DEF_INCLUDE=${MODULE_DEF_INCLUDE} MODULE_DEFCONFIG=${MODULE_DEFCONFIG} -f Makefile ipsec.o\"" >> ${MOD24BUILDDIR}/Makefile + echo "# compile-command: \"${MAKE} LIBRESWANSRCDIR=${LIBRESWANSRCDIR} ARCH=${ARCH} TOPDIR=${KERNELDIR} ${MODULE_FLAGS} MODULE_DEF_INCLUDE=${MODULE_DEF_INCLUDE} MODULE_DEFCONFIG=${MODULE_DEFCONFIG} -f Makefile ipsec.o\"" >> ${MOD24BUILDDIR}/Makefile echo "# End: " >> ${MOD24BUILDDIR}/Makefile module: - @if [ -f ${KERNELSRC}/README.libreswan-2 ] ; then \ - echo "WARNING: Kernel source ${KERNELSRC} has already been patched with libreswan-2, out of tree build might fail!"; \ + @if [ -f ${KERNELDIR}/README.libreswan-2 ] ; then \ + echo "WARNING: Kernel source ${KERNELDIR} has already been patched with libreswan-2, out of tree build might fail!"; \ fi; - @if [ -f ${KERNELSRC}/README.freeswan ] ; then \ - echo "ERROR: Kernel source ${KERNELSRC} has already been patched with freeswan, out of tree build will fail!"; \ + @if [ -f ${KERNELDIR}/README.freeswan ] ; then \ + echo "ERROR: Kernel source ${KERNELDIR} has already been patched with freeswan, out of tree build will fail!"; \ fi; - @if [ -f ${KERNELSRC}/Rules.make ] ; then \ + @if [ -f ${KERNELDIR}/Rules.make ] ; then \ echo "Building module for a 2.4 kernel"; ${MAKE} module24 ; \ else echo "Building module for a 2.6 kernel"; ${MAKE} module26; \ fi; modclean moduleclean: - @if [ -f ${KERNELSRC}/Rules.make ] ; then \ + @if [ -f ${KERNELDIR}/Rules.make ] ; then \ echo "Cleaning module for a 2.4 kernel"; ${MAKE} module24clean ; \ else echo "Cleaning module for a 2.6 kernel"; ${MAKE} module26clean; \ fi; module24: - @if [ ! -f ${KERNELSRC}/Rules.make ] ; then \ + @if [ ! -f ${KERNELDIR}/Rules.make ] ; then \ echo "Warning: Building for a 2.4 kernel in what looks like a 2.6 tree"; \ fi ; \ ${MAKE} ${MOD24BUILDDIR}/Makefile - ${MAKE} -C ${MOD24BUILDDIR} LIBRESWANSRCDIR=${LIBRESWANSRCDIR} ARCH=${ARCH} V=${V} ${MODULE_FLAGS} MODULE_DEF_INCLUDE=${MODULE_DEF_INCLUDE} TOPDIR=${KERNELSRC} -f Makefile ipsec.o + ${MAKE} -C ${MOD24BUILDDIR} LIBRESWANSRCDIR=${LIBRESWANSRCDIR} ARCH=${ARCH} V=${V} ${MODULE_FLAGS} MODULE_DEF_INCLUDE=${MODULE_DEF_INCLUDE} TOPDIR=${KERNELDIR} -f Makefile ipsec.o @echo @echo '=========================================================' @echo @@ -394,15 +394,15 @@ mod24clean module24clean: #autoodetect 2.4 and 2.6 module_install: minstall minstall: - @if [ -f ${KERNELSRC}/Rules.make ] ; then \ + @if [ -f ${KERNELDIR}/Rules.make ] ; then \ ${MAKE} minstall24 ; else ${MAKE} minstall26; \ fi; # module-only install, with error checks minstall24: - ( OSMODLIB=`${MAKE} -C $(KERNELSRC) -p dummy | ( sed -n -e '/^MODLIB/p' -e '/^MODLIB/q' ; cat > /dev/null ) | sed -e 's/^MODLIB[ :=]*\([^;]*\).*/\1/'` ; \ + ( OSMODLIB=`${MAKE} -C $(KERNELDIR) -p dummy | ( sed -n -e '/^MODLIB/p' -e '/^MODLIB/q' ; cat > /dev/null ) | sed -e 's/^MODLIB[ :=]*\([^;]*\).*/\1/'` ; \ if [ -z "$$OSMODLIB" ] ; then \ - OSMODLIB=`${MAKE} -C $(KERNELSRC) -n -p modules_install | ( sed -n -e '/^MODLIB/p' -e '/^MODLIB/q' ; cat > /dev/null ) | sed -e 's/^MODLIB[ :=]*\([^;]*\).*/\1/'` ; \ + OSMODLIB=`${MAKE} -C $(KERNELDIR) -n -p modules_install | ( sed -n -e '/^MODLIB/p' -e '/^MODLIB/q' ; cat > /dev/null ) | sed -e 's/^MODLIB[ :=]*\([^;]*\).*/\1/'` ; \ fi ; \ if [ -z "$$OSMODLIB" ] ; then \ echo "No known place to install module. Aborting." ; \ @@ -441,15 +441,15 @@ ${MODBUILDDIR}/Makefile : ${LIBRESWANSRCDIR}/packaging/makefiles/module26.make cp ${LIBRESWANSRCDIR}/packaging/makefiles/module26.make ${MODBUILDDIR}/Makefile echo "# " >> ${MODBUILDDIR}/Makefile echo "# Local Variables: " >> ${MODBUILDDIR}/Makefile - echo "# compile-command: \"${MAKE} -C ${LIBRESWANSRCDIR} ARCH=${ARCH} KERNELSRC=${KERNELSRC} MODBUILDDIR=${MODBUILDDIR} module26\"" >> ${MODBUILDDIR}/Makefile + echo "# compile-command: \"${MAKE} -C ${LIBRESWANSRCDIR} ARCH=${ARCH} KERNELDIR=${KERNELDIR} MODBUILDDIR=${MODBUILDDIR} module26\"" >> ${MODBUILDDIR}/Makefile echo "# End: " >> ${MODBUILDDIR}/Makefile ln -s -f ${LIBRESWANSRCDIR}/linux/net/ipsec/match*.S ${MODBUILDDIR} module26: - @if [ -f ${KERNELSRC}/Rules.make ] ; then \ echo "Warning: Building for a 2.6 kernel in what looks like a 2.4 tree"; \ + @if [ -f ${KERNELDIR}/Rules.make ] ; then \ echo "Warning: Building for a 2.6 kernel in what looks like a 2.4 tree"; \ fi ; \ ${MAKE} ${MODBUILDDIR}/Makefile - ${MAKE} -C ${KERNELSRC} ${KERNELBUILDMFLAGS} BUILDDIR=${MODBUILDDIR} SUBDIRS=${MODBUILDDIR} MODULE_DEF_INCLUDE=${MODULE_DEF_INCLUDE} MODULE_DEFCONFIG=${MODULE_DEFCONFIG} MODULE_EXTRA_INCLUDE=${MODULE_EXTRA_INCLUDE} ARCH=${ARCH} V=${V} modules + ${MAKE} -C ${KERNELDIR} ${KERNELBUILDMFLAGS} BUILDDIR=${MODBUILDDIR} SUBDIRS=${MODBUILDDIR} MODULE_DEF_INCLUDE=${MODULE_DEF_INCLUDE} MODULE_DEFCONFIG=${MODULE_DEFCONFIG} MODULE_EXTRA_INCLUDE=${MODULE_EXTRA_INCLUDE} ARCH=${ARCH} V=${V} modules @echo @echo '=========================================================' @echo @@ -469,9 +469,9 @@ mod26clean module26clean: # module-only install, with error checks minstall26: - ( OSMODLIB=`${MAKE} -C $(KERNELSRC) -p help | ( sed -n -e '/^MODLIB/p' -e '/^MODLIB/q' ; cat > /dev/null ) | sed -e 's/^MODLIB[ :=]*\([^;]*\).*/\1/'` ; \ + ( OSMODLIB=`${MAKE} -C $(KERNELDIR) -p help | ( sed -n -e '/^MODLIB/p' -e '/^MODLIB/q' ; cat > /dev/null ) | sed -e 's/^MODLIB[ :=]*\([^;]*\).*/\1/'` ; \ if [ -z "$$OSMODLIB" ] ; then \ - OSMODLIB=`${MAKE} -C $(KERNELSRC) -n -p modules_install | ( sed -n -e '/^MODLIB/p' -e '/^MODLIB/q' ; cat > /dev/null ) | sed -e 's/^MODLIB[ :=]*\([^;]*\).*/\1/'` ; \ + OSMODLIB=`${MAKE} -C $(KERNELDIR) -n -p modules_install | ( sed -n -e '/^MODLIB/p' -e '/^MODLIB/q' ; cat > /dev/null ) | sed -e 's/^MODLIB[ :=]*\([^;]*\).*/\1/'` ; \ fi ; \ if [ -z "$$OSMODLIB" ] ; then \ echo "No known place to install module. Aborting." ; \ @@ -506,10 +506,10 @@ kinstall: # undocumented kernel folklore: modules_install must precede install (observed on RHL8.0) @if egrep -q '^CONFIG_MODULES=y' $(KCFILE) ; \ then set -x ; \ - ( cd $(KERNELSRC) ; \ + ( cd $(KERNELDIR) ; \ $(MAKE) $(KERNMAKEOPTS) modules_install 2>&1 ) | tee -a out.kinstall ; \ fi - ( cd $(KERNELSRC) ; $(MAKE) $(KERNMAKEOPTS) install ) 2>&1 | tee -a out.kinstall + ( cd $(KERNELDIR) ; $(MAKE) $(KERNMAKEOPTS) install ) 2>&1 | tee -a out.kinstall ${ERRCHECK} out.kinstall kernelpatch2.6 kernelpatch: @@ -525,9 +525,9 @@ kernelpatch2.0: packaging/utils/kernelpatch 2.0 nattpatch: - if [ -f ${KERNELSRC}/Makefile ]; then \ + if [ -f ${KERNELDIR}/Makefile ]; then \ ${MAKE} nattpatch${KERNELREL}; \ - else echo "Cannot determine Linux kernel version. Perhaps you need to set KERNELSRC? (eg: export KERNELSRC=/usr/src/linux-`uname -r`/)"; exit 1; \ + else echo "Cannot determine Linux kernel version. Perhaps you need to set KERNELDIR? (eg: export KERNELDIR=/usr/src/linux-`uname -r`/)"; exit 1; \ fi; sarefpatch26: @@ -553,7 +553,7 @@ unpatch: exit 1 _unpatch: - for f in `find $(KERNELSRC)/. -name '*.preipsec' -print` ; \ + for f in `find $(KERNELDIR)/. -name '*.preipsec' -print` ; \ do \ echo "restoring $$f:" ; \ dir=`dirname $$f` ; \ @@ -592,11 +592,11 @@ ipkg_strip: ipkg_module: @echo "Moving ipsec.o into temporary location..." - KV=$(shell ${KVUTIL} ${KERNELSRC}/Makefile) && \ + KV=$(shell ${KVUTIL} ${KERNELDIR}/Makefile) && \ mkdir -p $(LIBRESWANSRCDIR)/packaging/ipkg/kernel-module/lib/modules/$$KV/net/ipsec - KV=$(shell ${KVUTIL} ${KERNELSRC}/Makefile) && \ + KV=$(shell ${KVUTIL} ${KERNELDIR}/Makefile) && \ cp ${LIBRESWANSRCDIR}/modobj*/ipsec.[k]o $(LIBRESWANSRCDIR)/packaging/ipkg/kernel-module/lib/modules/$$KV/net/ipsec/ - KV=$(shell ${KVUTIL} ${KERNELSRC}/Makefile) + KV=$(shell ${KVUTIL} ${KERNELDIR}/Makefile) ipkg_clean: rm -rf $(LIBRESWANSRCDIR)/packaging/ipkg/kernel-module/ diff --git a/Makefile.inc b/Makefile.inc index 5ceb09d..19c797e 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -139,19 +139,19 @@ RCDIR?=$(DESTDIR)$(FINALRCDIR) # this is a hack using the wildcard to look for existence of a file/dir ifneq ($(wildcard /usr/src/linux-2.6),) -KERNELSRC?=/usr/src/linux-2.6 +KERNELDIR?=/usr/src/linux-2.6 else ifneq ($(wildcard /usr/src/linux-2.4),) -KERNELSRC?=/usr/src/linux-2.4 +KERNELDIR?=/usr/src/linux-2.4 else -KERNELSRC?=/lib/modules/$(shell uname -r)/build +KERNELDIR?=/lib/modules/$(shell uname -r)/build endif endif # where kernel configuration outputs are located -KCFILE=$(KERNELSRC)/.config -ACFILE=$(KERNELSRC)/include/linux/autoconf.h -VERFILE=$(KERNELSRC)/include/linux/version.h +KCFILE=$(KERNELDIR)/.config +ACFILE=$(KERNELDIR)/include/linux/autoconf.h +VERFILE=$(KERNELDIR)/include/linux/version.h # where KLIPS kernel module is install OSMOD_DESTDIR?=net/ipsec diff --git a/Makefile.top b/Makefile.top index cabbdb2..1094c60 100644 --- a/Makefile.top +++ b/Makefile.top @@ -18,11 +18,11 @@ PATCHES=linux # where KLIPS goes in the kernel # note, some of the patches know the last part of this path -KERNELKLIPS=$(KERNELSRC)/net/ipsec -KERNELCRYPTODES=$(KERNELSRC)/crypto/ciphers/des -KERNELLIBFREESWAN=$(KERNELSRC)/lib/libfreeswan -KERNELLIBZLIB=$(KERNELSRC)/lib/zlib -KERNELINCLUDE=$(KERNELSRC)/include +KERNELKLIPS=$(KERNELDIR)/net/ipsec +KERNELCRYPTODES=$(KERNELDIR)/crypto/ciphers/des +KERNELLIBFREESWAN=$(KERNELDIR)/lib/libfreeswan +KERNELLIBZLIB=$(KERNELDIR)/lib/zlib +KERNELINCLUDE=$(KERNELDIR)/include MAKEUTILS=packaging/utils ERRCHECK=${MAKEUTILS}/errcheck -- 1.7.6 libreswan-3.32/packaging/suse/libreswan.README.SUSE000066400000000000000000000032361365625662500220010ustar00rootroot00000000000000Packaging info for libreswan --------------------------- libreswan has replaced the freeswan package that was present on previous versions of SUSE Linux Professional and Enterprise Server. SUSE had been applying many patches to enhance the functionality of FreeS/WAN; many of them came from SuperFreeS/WAN which was an enhanced version of FreeS/WAN and the predecessor of OpenS/WAN. So, with libreswan, SUSE had only to add a few patches on top of libreswan: - MSL2TP workaround - startup scripts ... integrated into SUSE Linux - Avoid trouble with bonded interfaces (ignore slaves) - build fixes (64bit, no klips, ...) Firewalling with 2.6 kernel IPsec --------------------------------- In former times (2.4 kernel with KLIPS module), the use could use firewall rules that were matching only network packets received to sent via ipsec by specifying the interface ipsecX. This interface does not exist any more with the in-kernel implementation of IPsec support in kernel 2.6. To allow filtering specifically for IPsec packets, a new netfilter policy module has been created. To find out about it, enter ipsec -m policy --help You can match IPsec/non-IPsec traffic (--pol ipsec/none) by direction (in/out), protocol (esp/ah/ipcomp), mode (tunnel/transport), ... and do whatever you want with the matching packets (ACCEPT, DROP, ...) Here's an example that rejects all incoming packets from the interface $WLAN_IF that is are not IPsec ESP packets. iptables -A FORWARD -i $WLAN_IF -m policy --dir in --pol ipsec -j ACCEPT iptables -A FORWARD -i $WLAN_IF -j LOG --log-prefix "NonESP: " iptables -A FORWARD -i $WLAN_IF -j DROP Your Novell/SUSE team. http://www.suse.com/feedback/ libreswan-3.32/packaging/suse/libreswan.ip-up000077500000000000000000000011671365625662500213240ustar00rootroot00000000000000#!/bin/bash # # /etc/ppp/ip-{up,down}.d/freeswan # # wrapper script to call freeswan if-up/if-down script to work around dial on # demand problems with ifdown (#39048) BASENAME=${0##*/} INTERFACE="$1" DEVICE="$2" SPEED="$3" LOCALIP="$4" REMOTEIP="$5" IPPARAM="$6" if [ -z "$ifcfg" -o -z "$INTERFACE" ]; then echo "this script needs to be run from ip-up or ip-down" exit 0 fi case "$0" in *ip-up*) /etc/sysconfig/network/if-up.d/freeswan "$ifcfg" "$INTERFACE" ;; *ip-down*) /etc/sysconfig/network/if-down.d/freeswan "$ifcfg" "$INTERFACE" ;; *) echo "this script needs to be run from ip-up or ip-down" ;; esac exit 0 libreswan-3.32/packaging/suse/libreswan.spec000066400000000000000000000167051365625662500212250ustar00rootroot00000000000000# needsrootforbuild # for sles11+ and opensuse 11.4 # for sles10, use sles10.spec Summary: Libreswan IPSEC implementation Name: libreswan Version: IPSECBASEVERSION # Build KLIPS kernel module? %{!?buildklips: %{expand: %%define buildklips 0}} # Libreswan -pre/-rc nomenclature has to co-exist with hyphen paranoia %define srcpkgver %(echo %{version} | tr -s '_' '-') %define ourrelease 1 Release: %{ourrelease} License: GPLv2 Url: https://libreswan.org/ Source: libreswan-%{srcpkgver}.tar.gz Patch1: rc.patch Group: Productivity/Networking/Security BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) Summary: Libreswan - An IPsec and IKE implementation PreReq: %insserv_prereq %fillup_prereq perl BuildRequires: bison flex bind-devel xmlto Requires: iproute2 >= 2.6.8 AutoReqProv: on %if %{buildklips} %kernel_module_package -p preamble BuildRequires: %kernel_module_package_buildreqs %endif Prefix: /usr %description Libreswan is a free implementation of IPSEC & IKE for Linux. IPSEC is the Internet Protocol Security and uses strong cryptography to provide both authentication and encryption services. These services allow you to build secure tunnels through untrusted networks. Everything passing through the untrusted net is encrypted by the ipsec gateway machine and decrypted by the gateway at the other end of the tunnel. The resulting tunnel is a virtual private network or VPN. This package contains the daemons and userland tools for setting up Libreswan on a freeswan enabled kernel. It optionally also builds the Libreswan KLIPS IPsec stack that is an alternative for the NETKEY/XFRM IPsec stack that exists in the default Linux kernel. %if %{buildklips} %package KMP Summary: Libreswan kernel module Group: System/Kernel %endif %if %{buildklips} %description KMP This package contains only the ipsec module for the SuSE series of kernels. %endif %prep %setup -q -n libreswan-%{srcpkgver} %patch1 -p1 sed -i 's/-Werror/#-Werror/' lib/libdns/Makefile sed -i 's/-Werror/#-Werror/' lib/libisc/Makefile sed -i 's/-Werror/#-Werror/' lib/liblwres/Makefile %build # Suse has no %{_libexecdir} directory, put it all in libdir instead (yuck) %{__make} \ USERCOMPILE='-g $(RPM_OPT_FLAGS) -DGCC_LINT' \ FINALBINDIR=%{_libdir}/ipsec \ FINALLIBEXECDIR=%{_libdir}/ipsec \ FINALMANDIR=%{_mandir} \ INC_DOCDIR=share/doc/packages \ INC_RCDEFAULT=%{_initrddir} \ INC_RCDIRS='/etc/init.d /etc/rc.d/init.d /etc/rc.d /sbin/init.d' \ INC_USRLOCAL=%{_prefix} \ programs %if %{buildklips} FS=$(pwd) for flavor in %flavors_to_build; do %{__make} -C $FS MODBUILDDIR=$FS/BUILD.%{_target_cpu}.$flavor \ LIBRESWANSRCDIR=$FS \ KERNELSRC=%{kernel_source $flavor} \ ARCH=%{_arch} \ include module done %endif %install %{__make} \ DESTDIR=%{buildroot} \ FINALBINDIR=%{_libdir}/ipsec \ FINALLIBEXECDIR=%{_libdir}/ipsec \ FINALMANDIR=%{_mandir} \ INC_RCDEFAULT=%{_initrddir} \ INC_USRLOCAL=%{_prefix} \ install FS=$(pwd) rm -rf %{buildroot}/usr/share/doc/libreswan rm -rf %{buildroot}/%{_initrddir}/setup rm -rf %{buildroot}/etc/ipsec.d/examples find %{buildroot}%{_mandir} -type f | xargs chmod a-x install -d -m 0755 %{buildroot}%{_localstatedir}/run/pluto install -d %{buildroot}%{_sbindir} #suse specific ln -sf /etc/init.d/ipsec ${RPM_BUILD_ROOT}%{_prefix}/sbin/rcipsec #echo "# see man ipsec.secrets" > $RPM_BUILD_ROOT/etc/ipsec.secrets install -d -m 755 %{buildroot}/etc/sysconfig/network/{scripts,if-up.d,if-down.d} install -m 755 packaging/suse/sysconfig.network.scripts.libreswan %{buildroot}/etc/sysconfig/network/scripts/freeswan install -m 644 packaging/suse/sysconfig.network.scripts.libreswan-functions %{buildroot}/etc/sysconfig/network/scripts/freeswan-functions ln -s ../scripts/freeswan %{buildroot}/etc/sysconfig/network/if-up.d/freeswan ln -s ../scripts/freeswan %{buildroot}/etc/sysconfig/network/if-down.d/freeswan # ip-up script (#39048) install -d -m 750 -g dialout %{buildroot}/etc/ppp/ip-{up,down}.d install -d -m 750 %{buildroot}/etc/ppp/ip-{up,down}.d install -m 755 packaging/suse/libreswan.ip-up %{buildroot}/etc/ppp/ip-up.d/freeswan ln -s ../ip-up.d/freeswan %{buildroot}/etc/ppp/ip-down.d/freeswan rm -f %{buildroot}/etc/rc?.d/[KS]*ipsec %if %{buildklips} export INSTALL_MOD_PATH=$RPM_BUILD_ROOT export INSTALL_MOD_DIR=updates for flavor in %flavors_to_build; do make -C %{kernel_source $flavor} modules_install M=$FS/BUILD.%{_target_cpu}.$flavor done %endif %clean rm -rf ${RPM_BUILD_ROOT} %files %defattr(-,root,root) %doc CHANGES COPYING CREDITS README LICENSE %doc OBJ.linux.*/programs/examples/*.conf #%doc doc/manpage.d/* # /usr/share/doc/libreswan/* %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ipsec.conf %attr(0700,root,root) %dir %{_sysconfdir}/ipsec.d %attr(0700,root,root) %dir %{_sysconfdir}/ipsec.d/cacerts %attr(0700,root,root) %dir %{_sysconfdir}/ipsec.d/crls %attr(0700,root,root) %dir %{_sysconfdir}/ipsec.d/policies %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ipsec.d/policies/* %ghost %attr(0755,root,root) %dir %{_localstatedir}/run/pluto %{_initrddir}/ipsec %{_libdir}/ipsec %{_sbindir}/rcipsec %{_sbindir}/ipsec %doc %{_mandir}/*/* /etc/sysconfig/network/scripts/* /etc/sysconfig/network/if-up.d/freeswan /etc/sysconfig/network/if-down.d/freeswan /etc/ppp/ip-up.d/freeswan /etc/ppp/ip-down.d/freeswan %dir %attr(700,root,root) /etc/ipsec.d/private %preun %{stop_on_removal ipsec} # Some people expect to not loose their secrets even after multiple rpm -e. if test -s etc/ipsec.secrets.rpmsave; then cp -p --backup=numbered etc/ipsec.secrets.rpmsave etc/ipsec.secrets.rpmsave.old fi exit 0 %postun %{restart_on_update ipsec} %{insserv_cleanup} %post %{fillup_and_insserv ipsec} # don't create host keys on install - might be no entropy! # libreswan automatically does it on 'start' if no ipsec.secrets is found %changelog * Wed May 07 2008 Paul Wouters - 2.5.50-1 - Various spec file fixes to compile on SLES 10 SP1 - Suse has no libexec directory - use libdir * Fri Apr 18 2008 Paul Wouters - 2.5.49-1 - Incororated Suse initscripts and some SPEC semantics from mt@suse.de * Thu Dec 20 2007 Paul Wouters - 2.6.01-1 - Work around for warnings in BIND related code - Remove bogus file /etc/init.d/setup at install - Cleaned up spec file * Mon Oct 10 2005 Paul Wouters - Updated for klips on xen - added ldconfig for post klips to obtain ipsec module dependencies - Run 'make include' since on FC4 kernel source does not have the links yet. * Wed Jan 5 2005 Paul Wouters - Updated for x86_64 and klips on 2.6 * Sun Sep 5 2004 Paul Wouters - Updated for libreswan * Fri Aug 22 2003 Sam Sgro - Juggling release/source package names to allow for -pre/-rc releases to build. * Thu Aug 14 2003 Sam Sgro - Reverting back to pre-x.509 version, cosmetic changes. * Tue May 20 2003 Charlie Brady 2.0.0-x509_1.3.2_2es - Add "Obsoletes: freeswan" to userland RPM. * Fri May 16 2003 Charlie Brady 2.0.0-x509_1.3.2_1es - Add version 1.3.2 of the x509 patch. - Add missing /usr/libexec/ipsec dir and files. - Minor tidy up of spec file. * Thu May 15 2003 Charlie Brady 2.0.0-1es - Based on work by Paul Lahaie of Steamballoon, Michael Richardson of freeS/WAN team and Tuomo Soini . - Build freeswan RPMs from a single source RPM, for RedHat, but should work on any RPM based system. libreswan-3.32/packaging/suse/preamble000066400000000000000000000000571365625662500200660ustar00rootroot00000000000000Requires: kernel-%1 Obsoletes: libreswan-klips libreswan-3.32/packaging/suse/rc.patch000066400000000000000000000010151365625662500177740ustar00rootroot00000000000000diff -r aa447af2817b programs/setup/setup.in --- a/programs/setup/setup.in Fri Apr 08 19:41:58 2011 +0900 +++ b/programs/setup/setup.in Fri Apr 08 19:55:04 2011 +0900 @@ -5,7 +5,7 @@ # Provides: ipsec # Required-Start: $network $remote_fs $syslog $named # Required-Stop: $syslog $remote_fs -# Default-Start: +# Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Start Libreswan IPsec at boot time # Description: Enable automatic key management for IPsec (KLIPS and NETKEY) libreswan-3.32/packaging/suse/sles10.spec000066400000000000000000000166451365625662500203510ustar00rootroot00000000000000# needsrootforbuild Summary: Libreswan IPSEC implementation Name: libreswan Version: IPSECBASEVERSION # Build KLIPS kernel module? %{!?buildklips: %{expand: %%define buildklips 0}} # Libreswan -pre/-rc nomenclature has to co-exist with hyphen paranoia %define srcpkgver %(echo %{version} | tr -s '_' '-') %define ourrelease 1 Release: %{ourrelease} License: GPLv2 Url: https://libreswan.org/ Source: libreswan-%{srcpkgver}.tar.gz Patch1: rc.patch Patch2: kernelsrc.patch Group: Productivity/Networking/Security BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) Summary: Libreswan - An IPsec and IKE implementation PreReq: %insserv_prereq %fillup_prereq perl BuildRequires: bison flex bind-devel xmlto sgml-skel Requires: iproute2 >= 2.6.8 AutoReqProv: on %if %{buildklips} %suse_kernel_module_package -p preamble kdump um BuildRequires: %kernel_module_package_buildreqs %endif Prefix: /usr %description Libreswan is a free implementation of IPSEC & IKE for Linux. IPSEC is the Internet Protocol Security and uses strong cryptography to provide both authentication and encryption services. These services allow you to build secure tunnels through untrusted networks. Everything passing through the untrusted net is encrypted by the ipsec gateway machine and decrypted by the gateway at the other end of the tunnel. The resulting tunnel is a virtual private network or VPN. This package contains the daemons and userland tools for setting up Libreswan on a freeswan enabled kernel. It optionally also builds the Libreswan KLIPS IPsec stack that is an alternative for the NETKEY/XFRM IPsec stack that exists in the default Linux kernel. %if %{buildklips} %package KMP Summary: Libreswan kernel module Group: System/Kernel %endif %if %{buildklips} %description KMP This package contains only the ipsec module for the SuSE series of kernels. %endif %prep %setup -q -n libreswan-%{srcpkgver} %patch1 -p1 %patch2 -p1 sed -i 's/-Werror/#-Werror/' lib/libdns/Makefile sed -i 's/-Werror/#-Werror/' lib/libisc/Makefile sed -i 's/-Werror/#-Werror/' lib/liblwres/Makefile %build # Suse has no %{_libexecdir} directory, put it all in libdir instead (yuck) %{__make} \ USERCOMPILE='-g $(RPM_OPT_FLAGS) -DGCC_LINT' \ INC_USRLOCAL=%{_prefix} \ FINALBINDIR=%{_libdir}/ipsec \ FINALLIBEXECDIR=%{_libdir}/ipsec \ MANTREE=%{_mandir} \ INC_RCDEFAULT=%{_initrddir} \ INC_RCDIRS='/etc/init.d /etc/rc.d/init.d /etc/rc.d /sbin/init.d' \ INC_DOCDIR=share/doc/packages \ programs %if %{buildklips} FS=$(pwd) for flavor in %flavors_to_build; do %{__make} -C $FS MODBUILDDIR=$FS/BUILD.%{_target_cpu}.$flavor \ LIBRESWANSRCDIR=$FS \ KERNELDIR=%{kernel_source $flavor} \ ARCH=%{_arch} \ include module done %endif %install %{__make} \ DESTDIR=%{buildroot} \ INC_USRLOCAL=%{_prefix} \ FINALBINDIR=%{_libdir}/ipsec \ FINALLIBEXECDIR=%{_libdir}/ipsec \ MANTREE=%{buildroot}%{_mandir} \ INC_RCDEFAULT=%{_initrddir} \ install FS=$(pwd) rm -rf %{buildroot}/usr/share/doc/libreswan rm -rf %{buildroot}/%{_initrddir}/setup rm -rf %{buildroot}/etc/ipsec.d/examples find %{buildroot}%{_mandir} -type f | xargs chmod a-x install -d -m 0700 %{buildroot}%{_localstatedir}/run/pluto install -d %{buildroot}%{_sbindir} #suse specific ln -sf /etc/init.d/ipsec ${RPM_BUILD_ROOT}%{_prefix}/sbin/rcipsec #echo "# see man ipsec.secrets" > $RPM_BUILD_ROOT/etc/ipsec.secrets install -d -m 755 %{buildroot}/etc/sysconfig/network/{scripts,if-up.d,if-down.d} install -m 755 packaging/suse/sysconfig.network.scripts.libreswan %{buildroot}/etc/sysconfig/network/scripts/freeswan install -m 644 packaging/suse/sysconfig.network.scripts.libreswan-functions %{buildroot}/etc/sysconfig/network/scripts/freeswan-functions ln -s ../scripts/freeswan %{buildroot}/etc/sysconfig/network/if-up.d/freeswan ln -s ../scripts/freeswan %{buildroot}/etc/sysconfig/network/if-down.d/freeswan # ip-up script (#39048) install -d -m 750 -g dialout %{buildroot}/etc/ppp/ip-{up,down}.d install -d -m 750 %{buildroot}/etc/ppp/ip-{up,down}.d install -m 755 packaging/suse/libreswan.ip-up %{buildroot}/etc/ppp/ip-up.d/freeswan ln -s ../ip-up.d/freeswan %{buildroot}/etc/ppp/ip-down.d/freeswan rm -f %{buildroot}/etc/rc?.d/[KS]*ipsec %if %{buildklips} export INSTALL_MOD_PATH=$RPM_BUILD_ROOT export INSTALL_MOD_DIR=updates for flavor in %flavors_to_build; do make -C %{kernel_source $flavor} modules_install M=$FS/BUILD.%{_target_cpu}.$flavor done %endif %clean rm -rf ${RPM_BUILD_ROOT} %files %defattr(-,root,root) %doc CHANGES COPYING CREDITS README LICENSE %doc OBJ.linux.*/programs/examples/*.conf #%doc doc/manpage.d/* # /usr/share/doc/libreswan/* %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ipsec.conf %attr(0700,root,root) %dir %{_sysconfdir}/ipsec.d %attr(0700,root,root) %dir %{_sysconfdir}/ipsec.d/cacerts %attr(0700,root,root) %dir %{_sysconfdir}/ipsec.d/crls %attr(0700,root,root) %dir %{_sysconfdir}/ipsec.d/policies %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ipsec.d/policies/* %{_localstatedir}/run/pluto %{_initrddir}/ipsec %{_libdir}/ipsec %{_sbindir}/rcipsec %{_sbindir}/ipsec %doc %{_mandir}/*/* /etc/sysconfig/network/scripts/* /etc/sysconfig/network/if-up.d/freeswan /etc/sysconfig/network/if-down.d/freeswan /etc/ppp/ip-up.d/freeswan /etc/ppp/ip-down.d/freeswan %dir %attr(700,root,root) /etc/ipsec.d/private %preun %{stop_on_removal ipsec} # Some people expect to not loose their secrets even after multiple rpm -e. if test -s etc/ipsec.secrets.rpmsave; then cp -p --backup=numbered etc/ipsec.secrets.rpmsave etc/ipsec.secrets.rpmsave.old fi exit 0 %postun %{restart_on_update ipsec} %{insserv_cleanup} %post %{fillup_and_insserv ipsec} # don't create host keys on install - might be no entropy! # libreswan automatically does it on 'start' if no ipsec.secrets is found %changelog * Wed May 07 2008 Paul Wouters - 2.5.50-1 - Various spec file fixes to compile on SLES 10 SP1 - Suse has no libexec directory - use libdir * Fri Apr 18 2008 Paul Wouters - 2.5.49-1 - Incororated Suse initscripts and some SPEC semantics from mt@suse.de * Thu Dec 20 2007 Paul Wouters - 2.6.01-1 - Work around for warnings in BIND related code - Remove bogus file /etc/init.d/setup at install - Cleaned up spec file * Mon Oct 10 2005 Paul Wouters - Updated for klips on xen - added ldconfig for post klips to obtain ipsec module dependencies - Run 'make include' since on FC4 kernel source does not have the links yet. * Wed Jan 5 2005 Paul Wouters - Updated for x86_64 and klips on 2.6 * Sun Sep 5 2004 Paul Wouters - Updated for libreswan * Fri Aug 22 2003 Sam Sgro - Juggling release/source package names to allow for -pre/-rc releases to build. * Thu Aug 14 2003 Sam Sgro - Reverting back to pre-x.509 version, cosmetic changes. * Tue May 20 2003 Charlie Brady 2.0.0-x509_1.3.2_2es - Add "Obsoletes: freeswan" to userland RPM. * Fri May 16 2003 Charlie Brady 2.0.0-x509_1.3.2_1es - Add version 1.3.2 of the x509 patch. - Add missing /usr/libexec/ipsec dir and files. - Minor tidy up of spec file. * Thu May 15 2003 Charlie Brady 2.0.0-1es - Based on work by Paul Lahaie of Steamballoon, Michael Richardson of freeS/WAN team and Tuomo Soini . - Build freeswan RPMs from a single source RPM, for RedHat, but should work on any RPM based system. libreswan-3.32/packaging/suse/sysconfig.network.scripts.libreswan000077500000000000000000000024531365625662500254530ustar00rootroot00000000000000#!/bin/bash set -e unset ${!LC_*} LANUGUAGE export LANG=POSIX export PATH=/sbin:/usr/sbin:/usr/local/sbin:/usr/local/bin:/usr/bin:/bin config="$1" iface="$2" FREESWAN_ADD= FREESWAN_UP= . /etc/sysconfig/network/scripts/freeswan-functions || exit 1 . /etc/sysconfig/network/ifcfg-"$config" 2>/dev/null || die "no config for $config found" [ -z "$FREESWAN_ADD$FREESWAN_UP" ] && die 0 [ -e /var/run/pluto.pid ] || die "pluto not running, can't handle $iface" start() { getfirstipv4addr $iface || die "unable to determine ip address for $iface" [ -z "$ip" ] && die "unable to determine ip address for $iface" ipsec auto --ready local up up= for conn in $FREESWAN_ADD --up $FREESWAN_UP; do # marker [ "$conn" = "--up" ] && { up=1; continue; } checkconnactive $conn && die 0 "$conn already active" ipsec auto --left "$ip" --add "$conn" [ -z "$up" ] || ipsec auto --asynchronous --up "$conn" || true done } stop() { local up up= for conn in $FREESWAN_ADD --up $FREESWAN_UP; do # marker [ "$conn" = "--up" ] && { up=1; continue; } checkconnactive $conn || die 0 "$conn not active" [ -z "$up" ] || ipsec auto --down "$conn" || true ipsec auto --delete "$conn" done ipsec auto --ready } case "$0" in *if-up.d*) start ;; *if-down.d*) stop ;; *) die "don't know what to do" ;; esac libreswan-3.32/packaging/suse/sysconfig.network.scripts.libreswan-functions000066400000000000000000000021341365625662500274520ustar00rootroot00000000000000 # hook cleanup () { true; } die() { local ret=1 trap EXIT cleanup case "$1" in [0-9]) ret="$1"; shift ;; esac [ -z "$@" ] || echo "$@" >&2 exit $ret } checkconnactive() { [ -z "$1" ] && return 0 ipsec auto --status | awk -v var="$1" ' BEGIN { expr="^000 \"" var "\": " status=1 } $0 ~ expr { gsub("^000 \"","") gsub("\": .*","") status=0 exit } END { exit status } ' return $? } # set $interface, $gateway defaultrouteinterface() { gateway= interface= while read -a a; do [ "${a[0]}" != "default" ] && continue set -- "${a[@]}" break done < <(ip route show) while [ $# -gt 0 ]; do token="$1" shift case "$token" in via) gateway="$1" shift ;; dev) interface="$1" shift ;; esac done } # set $ip, $mask, $brd for $1 getfirstipv4addr() { iface="$1" ip= mask= brd= [ -z "$iface" ] && return 1 read -a a < <(ip -o -4 a show dev $iface) set -- "${a[@]}" while [ $# -gt 0 ]; do token="$1" shift case "$token" in inet) ip=${1%%/*} mask=${1##*/} shift ;; brd) brd=${1} shift ;; esac done return 0 } libreswan-3.32/packaging/utils/000077500000000000000000000000001365625662500165335ustar00rootroot00000000000000libreswan-3.32/packaging/utils/ciabot.pl000077500000000000000000000151211365625662500203340ustar00rootroot00000000000000#!/usr/bin/perl -w # # ciabot -- Mail a git log message to a given address, for the purposes of CIA # # Loosely based on cvslog by Russ Allbery # Copyright 1998 Board of Trustees, Leland Stanford Jr. University # # Copyright 2001, 2003, 2004, 2005 Petr Baudis # # This program is free software; you can redistribute it and/or modify it under # the terms of the GNU General Public License version 2, as published by the # Free Software Foundation. # # The master location of this file is in the Cogito repository # (see http://www.kernel.org/git/). # # This program is designed to run as the .git/commit-post-hook script. It takes # the commit information, massaging it and mailing it to the address given below. # # The calling convention of the commit-post-hook script is: # # commit-post-hook $commit_sha1 $branch_name # # If it does not work, try to disable $xml_rpc in the configuration section # below. # # # Note that you can (and it might be actually more desirable) also use this # script as the GIT update hook: # # refname=${1#refs/heads/} # [ "$refname" = "master" ] && refname= # oldhead=$2 # newhead=$3 # for merged in $(git-rev-list $newhead ^$oldhead | tac); do # /path/to/ciabot.pl $merged $refname # done # # This is useful when you use a remote repository without working copy, where # you only push to - the update hook will be triggered each time you push into # that repository, and the pushed commits will be reported through CIA. use strict; use vars qw ($project $from_email $dest_email $noisy $rpc_uri $sendmail $xml_rpc $ignore_regexp $alt_local_message_target); ### Configuration # Project name (as known to CIA). $project = 'Libreswan'; # The from address in generated mails. $from_email = 'commits@libreswan.org'; # Mail all reports to this address. $dest_email = 'nightly@lists.libreswan.org'; # If using XML-RPC, connect to this URI. $rpc_uri = 'http://cia.vc/xmlrpc.php' # Path to your USCD sendmail compatible binary (your mailer daemon created this # program somewhere). $sendmail = '/usr/sbin/sendmail'; # If set, the script will send CIA the full commit message. If unset, only the # first line of the commit message will be sent. $noisy = 1; # This script can communicate with CIA either by mail or by an XML-RPC # interface. The XML-RPC interface is faster and more efficient, however you # need to have RPC::XML perl module installed, and some large CVS hosting sites # (like Savannah or Sourceforge) might not allow outgoing HTTP connections # while they allow outgoing mail. Also, this script will hang and eventually # not deliver the event at all if CIA server happens to be down, which is # unfortunately not an uncommon condition. $xml_rpc = 0; # You can make this bot to totally ignore events concerning the objects # specified below. Each object is composed of /, # # This variable should contain regexp, against which will each object be # checked, and if the regexp is matched, the file is ignored. Therefore ie. to # ignore all changes in the two files above and everything concerning module # 'admin', use: # # $ignore_regexp = "^(gentoo/Manifest|elinks/src/bfu/inphist.c|admin/)"; $ignore_regexp = ""; # It can be useful to also grab the generated XML message by some other # programs and ie. autogenerate some content based on it. Here you can specify # a file to which it will be appended. $alt_local_message_target = ""; ### The code itself use vars qw ($commit $tree @parent $author $committer); use vars qw ($user $branch $rev @files $logmsg $message); my $line; ### Input data loading # The commit stuff $commit = $ARGV[0]; $branch = $ARGV[1]; open COMMIT, "git-cat-file commit $commit|" or die "git-cat-file commit $commit: $!"; my $state = 0; $logmsg = ''; while (defined ($line = )) { if ($state == 1) { $logmsg .= $line; $noisy or $state++; next; } elsif ($state > 1) { next; } chomp $line; unless ($line) { $state = 1; next; } my ($key, $value) = split(/ /, $line, 2); if ($key eq 'tree') { $tree = $value; } elsif ($key eq 'parent') { push(@parent, $value); } elsif ($key eq 'author') { $author = $value; } elsif ($key eq 'committer') { $committer = $value; } } close COMMIT; open DIFF, "git-diff-tree -r $parent[0] $tree|" or die "git-diff-tree $parent[0] $tree: $!"; while (defined ($line = )) { chomp $line; my @f; (undef, @f) = split(/\t/, $line, 2); push (@files, @f); } close DIFF; # Figure out who is doing the update. # XXX: Too trivial this way? ($user) = $author =~ /<(.*?)@/; $rev = substr($commit, 0, 12); ### Remove to-be-ignored files @files = grep { $_ !~ m/$ignore_regexp/; } @files if ($ignore_regexp); exit unless @files; ### Compose the mail message my ($VERSION) = '1.0'; my $ts = time; $message = < CIA Perl client for Git $VERSION $project EM ; $message .= " $branch" if ($branch); $message .= < $ts $user $rev EM ; foreach (@files) { s/&/&/g; s//>/g; $message .= " $_\n"; } $logmsg =~ s/&/&/g; $logmsg =~ s//>/g; $message .= < $logmsg EM ; ### Write the message to an alt-target if ($alt_local_message_target and open (ALT, ">>$alt_local_message_target")) { print ALT $message; close ALT; } ### Send out the XML-RPC message if ($xml_rpc) { # We gotta be careful from now on. We silence all the warnings because # RPC::XML code is crappy and works with undefs etc. $^W = 0; $RPC::XML::ERROR if (0); # silence perl's compile-time warning require RPC::XML; require RPC::XML::Client; my $rpc_client = new RPC::XML::Client $rpc_uri; my $rpc_request = RPC::XML::request->new('hub.deliver', $message); my $rpc_response = $rpc_client->send_request($rpc_request); unless (ref $rpc_response) { die "XML-RPC Error: $RPC::XML::ERROR\n"; } exit; } ### Send out the mail # Open our mail program open (MAIL, "| $sendmail -t -oi -oem") or die "Cannot execute $sendmail : " . ($?>>8); # The mail header print MAIL <> 8) . "\n" unless ($? == 0); # vi: set sw=2: libreswan-3.32/packaging/utils/git-private-update-hook000077500000000000000000000012621365625662500231330ustar00rootroot00000000000000#!/bin/sh # # An example hook script to mail out commit update information. # Called by git-receive-pack with arguments: refname sha1-old sha1-new # # To enable this hook: # (1) change the recipient e-mail address # (2) make this file executable by "chmod +x update". # exec 1>&2 recipient="commits@lists.libreswan.org" if expr "$2" : '0*$' >/dev/null then echo "Created a new ref, with the following commits:" git-rev-list --pretty "$3" else base=$(git-merge-base "$2" "$3") case "$base" in "$2") echo "New commits:" ;; *) echo "Rebased ref, commits from common ancestor:" ;; esac fi git-rev-list --pretty "$3" "^$base" | mail -s "Changes to ref $1" "$recipient" exit 0 libreswan-3.32/packaging/utils/git-update-hook000077500000000000000000000004231365625662500214610ustar00rootroot00000000000000#!/bin/sh refname=${1#refs/heads/} [ "$refname" = "master" ] && refname= oldhead=$2 newhead=$3 for merged in $(git-rev-list $newhead ^$oldhead | tac); do /public/scm/libreswan.public/.git/ciabot.pl $merged $refname done touch /public/scm/libreswan.public/.git/last-update libreswan-3.32/packaging/utils/kernelpatch000077500000000000000000000032641365625662500207660ustar00rootroot00000000000000#!/bin/sh # wander through an Libreswan linux directory, creating a patch file (to stdout) # that will apply the code to a kernel source directory. # # $Id: kernelpatch,v 1.14 2005/09/26 02:37:53 mcr Exp $ # KERN=$1 shift patch20=false patch22=false patch24=false patch26=false . packaging/utils/kernelpatching.sh case $KERN in 2.4) patchname=os2_4; altname=fs2_4; patch24=true ;; 2.6) patchname=os2_6; altname=fs2_6; patch26=true ;; 3.*) patchname=os2_6; altname=fs2_6; patch26=true ;; *) echo "Invalid kernel patch target: $KERN"; exit 1;; esac # make sure that sort gets the right locale. LANG=C export LANG LC_ALL=C export LC_ALL find linux -type f -print | grep -v CVS | grep -v 'linux/Makefile' | sort | while read file do base=`basename $file` pname=`echo $file | sed -e 's,\.fs._.$,,' -e 's,\.os._.$,,'` case $base in TAGS) ;; tags) ;; .cvsignore) ;; .*.o.flags) ;; .\#*);; *.o) ;; *~) ;; version.in.c) doversion $file ;; tagsfile.mak) ;; *.${patchname}.patch) cat $file;; *.${altname}.patch) cat $file;; *.patch) ;; *.fs2_4) fakeallpatch $patch24 $file $pname ;; *.fs2_6) fakeallpatch $patch26 $file $pname ;; *.os2_4) fakeallpatch $patch24 $file $pname ;; *.os2_6) fakeallpatch $patch26 $file $pname ;; *) fakeallpatch true $file $file ;; esac done # # finally, we have to produce a diff for linux/net/linux/Makefile.ver, # a file which is generated at runtime, so there is nothing in CVS. # echo '--- /dev/null Fri May 10 13:59:54 2002' echo '+++ linux/net/ipsec/Makefile.ver Wed Dec 31 19:00:00 1969' echo '@@ -0,0 +1 @@' echo -n '+' (cd ${LIBRESWANSRCDIR} && make env ) | grep IPSECVERSION exit 0 libreswan-3.32/packaging/utils/kernelpatching.sh000077500000000000000000000017341365625662500220750ustar00rootroot00000000000000#!/bin/sh # routines to help build patch files. fakeallpatch() { # $1 true/false as to whether to continue # $2 file contents # $3 target name doit=$1 content=$2 target=$3 if $doit then : else return fi set -- `wc -l $content ` lines=$1 echo "diff -ruN a/${target#*/} b/${target#*/}" echo '--- /dev/null Tue Mar 11 13:02:56 2003' echo "+++ $target Mon Feb 9 13:51:03 2004" echo "@@ -0,0 +1,$lines @@" sed -e 's/^/+/' $content } doversion() { content=$1 target=`echo $content | sed -e 's/.in.c/.c/'` set -- `wc -l $content ` lines=$1 # get IPSECVERSION eval $(cd ${LIBRESWANSRCDIR} && make env | grep IPSECVERSION) echo "diff -ruN a/${target#*/} b/${target#*/}" echo '--- /dev/null Tue Mar 11 13:02:56 2003' echo "+++ $target Mon Feb 9 13:51:03 2004" echo "@@ -0,0 +1,$lines @@" sed -e 's/^/+/' -e '/"/s/@IPSECVERSION@/'${IPSECVERSION}'/' $content } libreswan-3.32/packaging/utils/kernelversion000077500000000000000000000004501365625662500213460ustar00rootroot00000000000000#! /bin/sh # determine kernel version code, mostly for use in RPM building awk 'BEGIN { FS = " *= *" } NF != 2 { next } $1 == "VERSION" { maj = $2 } $1 == "PATCHLEVEL" { mid = $2 } $1 == "SUBLEVEL" { min = $2 } $1 == "EXTRAVERSION" { ext = $2 } END { print maj "." mid "." min ext }' "$@" libreswan-3.32/packaging/utils/kernelversion-short000077500000000000000000000003321365625662500225020ustar00rootroot00000000000000#! /bin/sh # determine kernel version code, mostly for use in RPM building awk 'BEGIN { FS = " *= *" } NF != 2 { next } $1 == "VERSION" { maj = $2 } $1 == "PATCHLEVEL" { mid = $2 } END { print maj "." mid }' "$@" libreswan-3.32/packaging/utils/lswan_detect.sh000077500000000000000000000106271365625662500215540ustar00rootroot00000000000000#!/bin/sh # # We use sh here so this might run correctly on ANY unix host. # hopefully this will be very cross platform. Standards people!! # # Some distro's don't add the sbin directories to the normal users PATH PATH=${PATH}:/sbin:/usr/sbin return_initsystem() { # try to detect the running init system, perhaps more then one can # be installed? if [ -z "$(uname -o 2> /dev/null | grep inux)" ]; then echo "Error: This init system is not yet supported." >&2 return 89 fi # works for systemd, not upstart? if [ -e /proc/1/comm ]; then if [ "$(cat /proc/1/comm)" = "systemd" ]; then echo "systemd" return fi fi if [ -f /lib/systemd/systemd -a -d /var/run/systemd ]; then echo "systemd" return fi if [ -f /sbin/start ]; then # override for rhel/centos to use sysvinit if [ -e /etc/redhat-release ]; then echo "sysvinit" else echo "upstart" fi return fi if [ -f /sbin/rc-service -o -f /usr/sbin/rc-service ]; then echo "openrc" return fi # really, most have this, it is probably a backwards compatibility or # really sysvinit - we have no other known targets at this point anyway if [ -d /etc/init.d -o -d /etc/rc.d ]; then echo "sysvinit" return fi echo "unknown init system, please email swan-dev@lists.libreswan.org with: $(uname -a)" >&2 echo "unknown" exit 1 } return_distro() { # try to detect the distro if [ -z "$(uname -o 2> /dev/null | grep inux)" ]; then # non-Linux, so this will be BSD, OSX or cygwin/Windows echo "Error: This system is not supported yet." >&2 return 88 fi if [ -f /etc/redhat-release ]; then VER="$(grep 'Fedora release' /etc/redhat-release | awk '{print $3;}')" if [ -n "${VER}" ]; then echo "fedora/${VER}" return fi VER="$(grep 'Red Hat Enterprise' /etc/redhat-release | awk '{print $7;}')" if [ -n "${VER}" ]; then echo "rhel/${VER}" return fi VER="$(grep CentOS /etc/redhat-release | awk '{ print $3;}')" if [ -n "${VER}" ]; then echo "centos/${VER}" return fi VER="$(grep 'Foobar Linux' /etc/redhat-release | awk '{print $4;}')" if [ -n "${VER}" ]; then echo "foobar/${VER}" return fi if [ -n "$(grep enterprise-release /etc/redhat-release)" ]; then echo "The unbreakable broke - Oracle is welcome to submit patches" >&2 return 90 fi fi # Test for OpenSuSE: if [ -f /etc/SuSE-brand ]; then if [ "$(head -1 /etc/SuSE-brand | tr '[:upper:]' '[:lower:]')" = "opensuse" ]; then echo "opensuse/$(grep VERSION /etc/SuSE-brand | awk '{print $3;}')" return fi fi # Test for SuSE/SLES: if [ -f /etc/SuSE-release ]; then if grep -i suse /etc/SuSE-release > /dev/null 2>&1; then VER="$(grep VERSION /etc/SuSE-release | awk '{print $3;}')" PAT="$(grep PATCHLEVEL /etc/SuSE-release | awk '{print $3;}')" echo "suse/${VER}.${PAT}" fi return fi # Check ubuntu before debian, as it also has /etc/debian_version if [ -f /etc/lsb-release ]; then . /etc/lsb-release if [ "${DISTRIB_ID}" = "Ubuntu" ]; then echo "ubuntu/${DISTRIB_RELEASE}" return fi fi if [ -f /etc/debian_version ]; then VER="$(cat /etc/debian_version | sed 's/^\([0-9]\.[0-9]\).*$/\1/')" echo "debian/${VER}" return fi if [ -f /etc/arch-release ]; then # Arch Linux has no version, rolling release only echo "archlinux" return fi if [ -f /etc/alpine-release ]; then VER="$(cat /etc/alpine-release | sed 's/^\([0-9]\.[0-9]\).*$/\1/')" echo "alpine/${VER}" return fi if [ -f /etc/gentoo-release ]; then VER="$(cat /etc/gentoo-release | awk '{print $NF;}')" echo "gentoo/${VER}" return fi if [ -f /etc/slackware-version ]; then VER="`cat /etc/slackware-version | awk '{print $2}'`" echo "slackware/$VER" return fi echo "unknown distribution, please email swan-dev@lists.libreswan.org with: $(uname -a)" >&2 echo "unknown" exit 1 } case "$1" in distro|--distro) return_distro ;; init|--init|initsystem|--initsystem) return_initsystem ;; *) echo "Usage: $0 " echo " distro will detect the distribution (eg fedora/18, ubuntu/12.10, etc.)" echo " init will detect the init system used (systemd, upstart, sysvinit)" echo " " echo " output is currently a single line used by make/scripts for configuration and" echo " installation of distribution and init-system specific files" echo exit 1 ;; esac libreswan-3.32/packaging/utils/makerelease000077500000000000000000000025071365625662500207430ustar00rootroot00000000000000#!/bin/sh if [ ! -f Makefile.ver ] then echo >&2 "error: make release should be run from the top directory" exit 1 fi if [ -z "$VERSION" ] then VERSION=`git describe --tags --dirty | tail -1| sed -e "s/v//"` fi if [ -z "$FORCE" ] then if [ -n "`git diff | head -10`" ] then echo >&2 "error: tree is not clean - changes would be lost. aborted" exit 1 fi # will become branch 'release' instead of master TOPUSH=`git log master ^origin/master` if [ -n "$TOPUSH" ] then echo >&2 "ERROR: unpushed changes - git push first" git log master ^origin/master exit 1 fi fi if [ -f release/libreswan-$VERSION.tar.gz ] then echo >&2 "ERROR: release already exists. Aborted" exit 1 else mkdir -p release fi git archive --format=tar --prefix=libreswan-$VERSION/ HEAD | gzip > release/libreswan-$VERSION.tar.gz # subshell for easier path ( cd release tar zxf libreswan-$VERSION.tar.gz cd libreswan-$VERSION echo "IPSECBASEVERSION?=$VERSION" > mk/version.mk sed -i "s/(unreleased)/(`C= LOCALE= LANG= date +"%B %d, %Y"`)/" CHANGES for file in `find packaging -type f | xargs grep IPSECBASEVERSION |sed "s/:.*$//"` do sed -i "s/@IPSECBASEVERSION@/$VERSION/" $file done cd .. tar zcf libreswan-$VERSION.tar.gz libreswan-$VERSION ) ls -l release/libreswan-$VERSION.tar.gz echo please sign the release now with GPG and upload it libreswan-3.32/packaging/utils/makeshadowdir000077500000000000000000000022471365625662500213100ustar00rootroot00000000000000#!/bin/sh -e SRCDIR=$1 ; shift OBJDIR=$1 ; shift dirs=$1 if test $(cd ${SRCDIR} ; pwd) = $(cd ${SRCDIR} ; cd ${OBJDIR} ; pwd) then echo "failed. ${OBJDIR} == ${SRCDIR}" exit 1 fi cd ${SRCDIR} mkdir -p ${OBJDIR} # Generate sub-directories first find ${dirs} -type d -print | while read dirname do if test -r $dirname/Makefile then ( echo Generating ${OBJDIR}/$dirname/Makefile cd ${OBJDIR} mkdir -p $dirname cd $dirname top_builddir=$(echo $dirname | sed -e 's;[^/]*;..;g') cat <Makefile.tmp # Generated by $0 # define autoconf style names such as srcdir, builddir, abs_srcdir, # top_srcdir, abs_top_srcdir, ... include ${top_builddir}/../mk/dirs.mk include \${srcdir}/Makefile EOF mv Makefile.tmp Makefile ) fi done # OBJDIR makefile is just different enough cat < $OBJDIR/Makefile.tmp # Generated by $0 # define autoconf style names such as srcdir, builddir, abs_srcdir, # top_srcdir, abs_top_srcdir, ... include ../mk/dirs.mk programs config man install clean install-programs: set -e ; \\ for d in \$(SUBDIRS) ; \\ do \\ ( cd \$\$d && \$(MAKE) \$@ ) ; \\ done EOF mv $OBJDIR/Makefile.tmp $OBJDIR/Makefile libreswan-3.32/packaging/utils/manlink000077500000000000000000000033271365625662500201170ustar00rootroot00000000000000#! /bin/sh # # $Id: manlink,v 1.8 2002/09/17 20:17:16 sam Exp $ # # make list of alternate names for manpages PATH=/bin:/usr/bin ; export PATH usage="$0 manpage ..." for m do bm=`basename $m` if test ! -f $m then echo "$0: cannot find \`$m'" >&2 exit 1 fi suf=$(expr $bm : '.*\([.][^.][^.]*\)$') # a .\"+ line rules them=$(awk '/^\.\\"\+[ ]/ { for (i = 2; i <= NF; i++) print $i }' $m) # otherwise, try to intuit the list of names from the NAME section if test " $them" = " " then them=$( awk '/^\.SH[ \t]+NAME/,/^\.SH[ \t]+[^N]/' $m | grep -v '^\.' | tr ' ,' ' ' | sed -n '/ *\\*- *.*/s///p' | tr -s ' ' '\012' | grep -v '^ipsec$' ) fi # do it for f in $them do case $f in ipsec*) ff="$f" ;; # ipsec.8, ipsec.conf.5, etc. *) ff="ipsec_$f" ;; esac case $ff in *.[1-8]) ;; *) ff="$ff$suf" ;; esac #echo "Q: $bm FF: $ff" >&2 if [ " $ff" != " $bm" ] && [ " $ff" != " ipsec_$bm" ] then echo $bm $ff fi done done # # $Log: manlink,v $ # Revision 1.8 2002/09/17 20:17:16 sam # # The "make doc" fix broke "make install" silently; some man page symlinks # were being linked incorrectly. This resulted in files which passed the make # install test but linked to nothing. # # Revision 1.7 2002/08/07 06:23:35 sam # # freeswan/packaging/utils/manlink # # Revision 1.6 2002/05/06 21:20:24 mcr # manlink -n idea is a fail. It depended upon being able to # read the man page at the installed location, which isn't going # to work consistently. manlink now just generates a list of links # that should be made, leaving the Makefile script to decide what # to do with them. Further, it now processes the files found in the # repository, rather than the ones installed. # # libreswan-3.32/packaging/utils/patcher000077500000000000000000000101441365625662500201070ustar00rootroot00000000000000#! /bin/sh # smart patch applier # Copyright (C) 1999, 2001 Henry Spencer. # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # # patcher [-v] [-c] targetdir target [ key patchfile ] ... # In targetdir, patch target from patchfile unless it already contains # key and it appears to have been patched with the same patch. (If the # patch has changed, undo the old one and then put the new one in.) Save # original as target.preipsec, and patched copy as target.wipsec, with # patch md5sum stored as target.ipsecmd5. If the patch doesn't work, # put the original back and save the patch attempt as target.mangled. # If there are no key+patchfile pairs, undo any old patch and leave it # at that. # -v means verbose # -c means do "patching" by appending rather than by using patch(1) PATH=/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin:/usr/local/sbin export PATH umask 022 verbose= modifier=patch while [ $# != 0 ] do case "$1" in -v) verbose=yes ;; -c) modifier=cat ;; --) shift ; break ;; -*) echo "$0: unknown option \`$1'" >&2 ; exit 2 ;; *) break ;; esac shift done if test $# -lt 2 then echo "Usage: $0 [-v] [-c] targetdir target [ key patchfile ] ..." >&2 exit 2 fi need() { if test ! -f $1 then echo "$0: cannot find file \`$1'" >&2 exit 1 fi } note() { if test "$verbose" then echo "* $1" fi } dir="$1" target="$2" shift ; shift it=$dir/$target need $it patches= if test ! -s $it.ipsecmd5 then # no records of patching... while test $# -ge 2 do key="$1" patchfile="$2" shift ; shift need $patchfile if grep -E -q "$key" $it then # patched but no record of how note "$it no longer needs patch $patchfile" else patches="$patches $patchfile" fi done elif test ! -f $it.preipsec -o ! -f $it.wipsec then echo "$0: $it.preipsec or .wipsec is missing!" >&2 exit 1 else # determine whether patches have changed tmp=/tmp/patcher.$$ >$tmp while test $# -ge 2 do key="$1" patchfile="$2" shift ; shift need $patchfile md5sum $patchfile | awk '{print $1}' >>$tmp if grep -E -q "$key" $it.preipsec then note "$it no longer needs patch $patchfile" else patches="$patches $patchfile" fi done if cmp -s $tmp $it.ipsecmd5 then note "$it already fully patched" rm -f $tmp exit 0 fi rm -f $tmp # must undo old patch(es) note "$it old patches must be undone, undoing them..." if ! cmp -s $it $it.wipsec then note "$it has changed, cannot undo old patches!" echo "$0: cannot unpatch $it, it has changed since patching" >&2 exit 1 fi rm $it mv $it.preipsec $it rm $it.wipsec $it.ipsecmd5 fi # if no necessary patches, we're done if test " $patches" = " " then note "$it no longer needs patching" exit 0 fi # try to figure out patch options if test " $modifier" = " patch" then if patch --help >/dev/null 2>/dev/null then # looks like a modern version popts='-p1 -b' else # looks like an old one popts='-p1' fi fi # do it >$it.ipsecmd5 for patchfile in $patches do note "applying $patchfile to $it..." # make local copy - this defeats hard and soft links mv $it $it.preipsec || exit 0 rm -f $it cp -p $it.preipsec $it case "$modifier" in patch) ( cd $dir ; patch $popts ) <$patchfile ;; cat) cat $patchfile >>$it ;; esac status=$? if test $status -ne 0 then note "$it patch failed, restoring original" echo "$0: patch on $it failed!" >&2 echo "$0: restoring original $it," >&2 echo "$0: leaving patch attempt in $it.mangled" >&2 mv $it $it.mangled mv $it.preipsec $it rm -f $it.ipsecmd5 exit 1 fi rm -f $it.orig # some patch versions leave debris md5sum $patchfile | awk '{print $1}' >>$it.ipsecmd5 done cp -p $it $it.wipsec libreswan-3.32/packaging/utils/refnames.sh000077500000000000000000000011601365625662500206700ustar00rootroot00000000000000#!/bin/sh -e awk ' BEGIN { debug = 0 } // && !manvolnum { manvolnum = gensub(/[^0-9]*/, "", "g") if (debug) print "manvolnum:", manvolnum >> "/dev/stderr" } // { refname = $0 if (debug) print "refname:", refname >> "/dev/stderr" refname = gensub(/[^>]*>/, "", "1", refname) if (debug) print "refname:", refname >> "/dev/stderr" refname = gensub(/<.*/, "", "1", refname) if (debug) print "refname:", refname >> "/dev/stderr" refname = gensub(/ /, "_", "g", refname) if (debug) print "refname:", refname >> "/dev/stderr" print refname "." manvolnum } ' $@ libreswan-3.32/packaging/utils/sarefpatch000077500000000000000000000023011365625662500205750ustar00rootroot00000000000000#!/bin/sh # wander through an Libreswan ng-patch directory, # creating a patch file (to stdout) # that will apply the code to a kernel source directory. # # KERN=$1 shift . packaging/utils/kernelpatching.sh patch20=false patch22=false patch24=false patch26=false case $KERN in 2.4) echo "SAref only supported for 2.6+ kernels, not $KERN"; exit 1;; 2.6) patchname=os2_6; patch26=true;; *) echo "Invalid kernel patch target: $KERN"; exit 1;; esac # make sure that sort gets the right locale. LANG=C export LANG LC_ALL=C export LC_ALL find ng-patch -type f -print | grep -v CVS | grep -v 'linux/Makefile' | sort | while read file do base=`basename $file` pname=`echo $file | sed -e 's,\.fs._.$,,' -e 's,\.os._.$,,'` case $base in TAGS) ;; tags) ;; .cvsignore) ;; .*.o.flags) ;; .\#*);; *.o) ;; *~) ;; tagsfile.mak) ;; *.$patchname.patch) cat $file;; *.$altname.patch) cat $file;; *.os2_0) fakeallpatch $patch20 $file $pname ;; *.os2_2) fakeallpatch $patch22 $file $pname ;; *.os2_4) fakeallpatch $patch24 $file $pname ;; *.os2_6) fakeallpatch $patch26 $file $pname ;; *.patch) ;; *) diff -u /dev/null $file;; esac done exit 0 libreswan-3.32/packaging/utils/setlibreswanversion000077500000000000000000000015231365625662500225720ustar00rootroot00000000000000#!/bin/sh # # Copyright (C) 2012 Paul Wouters # # Based on Openswan version # # Called via mk/config.mk # # Options: IPSECVERSION is passed as ${1}, basedir as ${2} usage() { echo "Usage: $0 [srctree]" >&2 echo " $0 --add-git-diry [srctree]" >&2 exit 1 } ADD_GIT_DIRTY= if [ "${1}" = "--add-git-diry" ]; then ADD_GIT_DIRTY=' --dirty'; shift; fi baseversion="${1}" [ -n "${baseversion}" ] || usage cd "${2:-.}" || usage # -f .git check is needed for "git worktree" if [ -d .git -o -f .git ]; then if git version >/dev/null 2>&1; then CUR=$(git describe --tags ${ADD_GIT_DIRTY}) BRANCH=$(git rev-parse --abbrev-ref HEAD) echo "${CUR}-${BRANCH}" exit 0 else echo "Error: git should be installed to determine exact Libreswan version" >&2 fi fi echo "${baseversion}" libreswan-3.32/pam.d/000077500000000000000000000000001365625662500144465ustar00rootroot00000000000000libreswan-3.32/pam.d/pluto000066400000000000000000000007761365625662500155460ustar00rootroot00000000000000#%PAM-1.0 # Regular System auth auth include system-auth # # Google Authenticator with Regular System auth in combined prompt mode # (OTP is added to the password at the password prompt without separator) # auth required pam_google_authenticator.so forward_pass # auth include system-auth use_first_pass # # Common account required pam_nologin.so account include system-auth password include system-auth session optional pam_keyinit.so force revoke session include system-auth session required pam_loginuid.so libreswan-3.32/pam.d/pluto.example-url000066400000000000000000000016741365625662500177760ustar00rootroot00000000000000#%PAM-1.0 # # Requires pam_url. Ensure resource is on https, not http auth sufficient pam_url.so [config=/etc/pam_url.conf] [use_first_pass=1] account sufficient pam_url.so [config=/etc/pam_url.conf] # example /etc/pam_url.conf to run against Fedora FAS server (supports yubikey!) # pam_url: { settings: { # URI to fetch url = "https://id.dev.fedoraproject.org/pam"; # The remote script/cgi should return a 200 http code and # this string as its only results returncode = "OK"; # userfield name to send userfield = "username"; # passwdfield name to send passwdfield = "password"; # extradata to send extradata = "&do=login"; prompt = "Password+Token: "; }; # debug version #auth sufficient pam_url.so [debug] [config=/etc/pam_url.conf] [use_first_pass=1] #account sufficient pam_url.so [debug] [config=/etc/pam_url.conf] libreswan-3.32/pam.d/pluto.example.google-authenticator000066400000000000000000000006761365625662500233220ustar00rootroot00000000000000#%PAM-1.0 # Google Authenticator with Regular System auth in combined prompt mode # (OTP is added to the password at the password prompt without separator) auth required pam_google_authenticator.so forward_pass auth include system-auth use_first_pass account required pam_nologin.so account include system-auth password include system-auth session optional pam_keyinit.so force revoke session include system-auth session required pam_loginuid.so libreswan-3.32/pam.d/pluto.example.sssdldap-secureid000066400000000000000000000014641365625662500226100ustar00rootroot00000000000000#%PAM-1.0 #auth [success=done ignore=ignore default=bad] pam_selinux_permit.so auth required pam_securid.so #auth substack password-auth auth required pam_succeed_if.so user != root quiet auth optional pam_gnome_keyring.so auth include postlogin #account required pam_nologin.so #account include password-auth account include system-auth password include password-auth #session required pam_selinux.so close session include system-auth session required pam_loginuid.so session required pam_securid.so session required pam_sss.so session optional pam_console.so #session required pam_selinux.so open session optional pam_keyinit.so force revoke session required pam_namespace.so session optional pam_gnome_keyring.so auto_start session include password-auth session include postlogin session required as_pam_logon.so libreswan-3.32/programs/000077500000000000000000000000001365625662500153015ustar00rootroot00000000000000libreswan-3.32/programs/Makefile000066400000000000000000000027621365625662500167500ustar00rootroot00000000000000# Makefile for the KLIPS interface utilities # # Copyright (C) 1998, 1999 Henry Spencer. # Copyright (C) 1999, 2000, 2001 Richard Guy Briggs # Copyright (C) 2012 Paul Wouters # Copyright (C) 2015,2017 Andrew Cagney # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. ifndef top_srcdir include ../mk/dirs.mk endif include $(top_srcdir)/Makefile.inc SUBDIRS= SUBDIRS+=pluto SUBDIRS+=whack SUBDIRS+=proc addconn SUBDIRS+=configs _plutorun _stackmanager SUBDIRS+=_secretcensor _updown _unbound-hook SUBDIRS+=auto barf verify show ipsec look newhostkey SUBDIRS+=rsasigkey setup showhostkey SUBDIRS+=readwriteconf SUBDIRS+=_import_crl SUBDIRS+=algparse SUBDIRS+=cavp SUBDIRS+=letsencrypt ifeq ($(USE_PORTEXCLUDES),true) SUBDIRS+=portexcludes endif ifeq ($(USE_KLIPS),true) SUBDIRS+= _updown.klips eroute klipsdebug pf_key spi spigrp tncfg endif ifeq ($(USE_NETKEY),true) SUBDIRS+= _updown.netkey endif ifeq ($(USE_BSDKAME),true) SUBDIRS+=_realsetup.bsd _updown.bsdkame endif include $(top_srcdir)/mk/subdirs.mk libreswan-3.32/programs/_import_crl/000077500000000000000000000000001365625662500176125ustar00rootroot00000000000000libreswan-3.32/programs/_import_crl/Makefile000066400000000000000000000015631365625662500212570ustar00rootroot00000000000000# _import_crl Makefile # Copyright (C) 2015 Matt Rogers # Copyright (C) 2017 Andrew Cagney # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. PROGRAM=_import_crl OBJS += $(PROGRAM).o OBJS += $(LIBRESWANLIB) OBJS += $(LSWTOOLLIBS) LDFLAGS += $(NSS_LDFLAGS) LDFLAGS += $(NSPR_LDFLAGS) ifdef top_srcdir include $(top_srcdir)/mk/program.mk else include ../../mk/program.mk endif libreswan-3.32/programs/_import_crl/_import_crl.8.xml000066400000000000000000000027121365625662500230150ustar00rootroot00000000000000 MattRogersplaceholder to suppress warning _IMPORT_CRL 8 Feb 2015 libreswan Executable programs ipsec _import_crl helper program for importing a crl to the NSS database DESCRIPTION _import_crl is spawned by pluto in order to add or update a CRL in the NSS database (default: @IPSEC_NSSDIR@) SEE ALSO pluto8. HISTORY Man page written for the Libreswan project <https://libreswan.org/> by Matt Rogers libreswan-3.32/programs/_import_crl/_import_crl.c000066400000000000000000000051131365625662500222670ustar00rootroot00000000000000/* CRL import helper, for libreswan. * * Copyright (C) 2015 Matt Rogers * Copyright (C) 2016, Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * */ #include #include #include "lswconf.h" #include "lswnss.h" #include #include #include #include #include #include #include #ifdef __clang__ /* * clang complains about these from nss.h, gcc does not? */ extern SECStatus NSS_Shutdown(void); extern SECStatus NSS_InitReadWrite(const char *configdir); #endif static int import_crl(const char *url, unsigned char *buf, size_t len) { CERTSignedCrl *crl = NULL; SECItem si = {siBuffer, NULL, 0}; CERTCertDBHandle *handle = CERT_GetDefaultCertDB(); if (handle == NULL) return -1; si.data = buf; si.len = len; if ((crl = CERT_ImportCRL(handle, &si, (char *)url, SEC_CRL_TYPE, NULL)) == NULL) { return PORT_GetError(); } SEC_DestroyCrl(crl); return 0; } /* * _import_crl * the der blob is passed through STDIN from pluto's fork */ int main(int argc, char *argv[]) { char *url, *lenstr; unsigned char *buf, *tbuf; size_t len, tlen; ssize_t rd; int fin; if (argc != 3) exit(-1); char *progname = argv[0]; url = argv[1]; lenstr = argv[2]; /* can't be 0 */ if (*lenstr == '0' && strlen(lenstr) == 1) exit(-1); while (*lenstr != '\0') { if (!isalnum(*lenstr++)) { exit(-1); } } tlen = len = (size_t) atoi(argv[2]); tbuf = buf = (unsigned char *) malloc(len); if (tbuf == NULL) exit(-1); while (tlen != 0 && (rd = read(STDIN_FILENO, buf, len)) != 0) { if (rd == -1) { if (errno == EINTR) continue; exit(-1); } tlen -= rd; buf += rd; } if ((size_t)(buf - tbuf) != len) exit(-1); const struct lsw_conf_options *oco = lsw_init_options(); lsw_nss_buf_t err; if (!lsw_nss_setup(oco->nssdir, 0, lsw_nss_get_password, err)) { fprintf(stderr, "%s: %s\n", progname, err); exit(1); } fin = import_crl(url, tbuf, len); if (tbuf != NULL) free(tbuf); NSS_Shutdown(); return fin; } libreswan-3.32/programs/_plutorun/000077500000000000000000000000001365625662500173305ustar00rootroot00000000000000libreswan-3.32/programs/_plutorun/Makefile000066400000000000000000000013561365625662500207750ustar00rootroot00000000000000# Makefile for miscellaneous programs # Copyright (C) 2002 Michael Richardson # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. PROGRAM=_plutorun ifdef top_srcdir include $(top_srcdir)/mk/program.mk else include ../../mk/program.mk endif libreswan-3.32/programs/_plutorun/_plutorun.8.xml000066400000000000000000000042351365625662500222530ustar00rootroot00000000000000 PaulWoutersplaceholder to suppress warning _PLUTORUN 8 12 Nov 2012 libreswan Executable programs ipsec _plutorun internal script to (re)start pluto on old SYSV initscript systems DESCRIPTION _plutorun is called by _realsetup to configure and bring up pluto(8). It invokes pluto, and watches to makes sure that pluto is restarted if it fails, as the SYSV initscripts do not provide a restart facility. When other init systems are used, such as systemd or upstart, _plutorun is not used. SEE ALSO ipsec8, ipsec_setup8, ipsec__realsetup8, pluto8. HISTORY Man page written for the Linux FreeS/WAN project <https://www.freeswan.org/> by Michael Richardson. Original program written by Henry Spencer. Updated for the Libreswan project <https://libreswan.org/> by Paul Wouters libreswan-3.32/programs/_plutorun/_plutorun.in000077500000000000000000000057631365625662500217250ustar00rootroot00000000000000#!@SHELL_BINARY@ # Pluto control daemon # Copyright (C) 1998, 1999, 2001 Henry Spencer. # Copyright (C) 2010-2013 Tuomo Soini # Copyright (C) 2012 Paul Wouters # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. PLUTO_OPTIONS=$* pidfile=@IPSEC_RUNDIR@/pluto.pid execdir=${IPSEC_EXECDIR:-@IPSEC_EXECDIR@} # create nss if the admin deleted it or the packaging did not create it ipsec --checknss # precautions if [ -f ${pidfile} ]; then echo "pluto appears to be running already (\"${pidfile}\" exists), will not start another" | \ logger -s -p authpriv.error -t ipsec__plutorun >/dev/null 2>&1 exit 1 fi # spin off into the background, with our own logging echo "Starting Pluto" | logger -p authpriv.error -t ipsec__plutorun >/dev/null 2>&1 # Work around problem with broken shells (e.g. Busybox sh). # We are called with stdout & stderr going to a logger process started # by "ipsec setup". For some reason, when the below loop runs with # stdout & stderr redirected to a new logger, the pipe to the old logger # is leaked through to _plutorun as file descriptor 11, and the old # logger (and "ipsec setup") can never exit. By closing fds 1 & 2 # before they can be dup'd to 11, we somehow avoid the problem. # This problem may also apply to Ubuntu's dash shell # but the workaround has not been tested there. exec 1>/dev/null exec 2>/dev/null ${execdir}/pluto ${PLUTO_OPTIONS} status=$? case "$status" in 10) echo "pluto apparently already running (?!?), giving up" | \ logger -s -p authpriv.error -t ipsec__plutorun >/dev/null 2>&1 exit 0 ;; 137) echo "pluto killed by SIGKILL, terminating without restart or unlock" | \ logger -s -p authpriv.error -t ipsec__plutorun >/dev/null 2>&1 rm -f ${pidfile} exit 0 ;; 0) echo "pluto killed by SIGTERM, terminating without restart" | \ logger -s -p authpriv.error -t ipsec__plutorun >/dev/null 2>&1 # pluto now does its own unlock for this exit 0 ;; *) st=${status} if [ ${st} -gt 128 ]; then st="${st} (signal $((${st} - 128)))" fi echo "!pluto failure!: exited with error status ${st}" | \ logger -s -p authpriv.error -t ipsec__plutorun >/dev/null 2>&1 echo "restarting IPsec after pause..." | \ logger -s -p authpriv.error -t ipsec__plutorun >/dev/null 2>&1 ( sleep 10 # use start, not restart for now, due to module unloading/loading # clean up old pidfile so new start will be successful rm -f ${pidfile} ipsec setup start ) /dev/null 2>&1 & exit 1 ;; esac exit 0 libreswan-3.32/programs/_realsetup.bsd/000077500000000000000000000000001365625662500202135ustar00rootroot00000000000000libreswan-3.32/programs/_realsetup.bsd/Makefile000066400000000000000000000014141365625662500216530ustar00rootroot00000000000000# Makefile for miscellaneous programs # Copyright (C) 2002 Michael Richardson # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. PROGRAM=_realsetup PROGRAMOBJDIR=_realsetup.bsd ifdef top_srcdir include $(top_srcdir)/mk/program.mk else include ../../mk/program.mk endif libreswan-3.32/programs/_realsetup.bsd/_realsetup.8.xml000066400000000000000000000034201365625662500232450ustar00rootroot00000000000000 PaulWoutersplaceholder to suppress warning _REALSETUP 8 25 Apr 2002 libreswan Executable programs ipsec _realsetup internal routine to start FreeS/WAN. DESCRIPTION _realsetup is called by the system init scripts to start the FreeS/WAN system. It starts KLIPS (the kernel component) and pluto (the userspace keying component). SEE ALSO ipsec8, ipsec__klipsstart8, ipsec__plutorun8. HISTORY Man page written for the Linux FreeS/WAN project <https://www.freeswan.org/> by Michael Richardson. Original program by Henry Spencer. libreswan-3.32/programs/_realsetup.bsd/_realsetup.in000077500000000000000000000172041365625662500227150ustar00rootroot00000000000000#!@SHELL_BINARY@ # # IPsec startup and shutdown command # Copyright (C) 2006 Michael Richardson # Copyright (C) 2019 Paul Wouters # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # # WARNING: This script needs updating to use the new libreswan startup method test $IPSEC_INIT_SCRIPT_DEBUG && set -v -x LC_ALL=C export LC_ALL me='ipsec setup' # for messages # Misc. paths (some of this should perhaps be overrideable from ipsec.conf). plutopid=/var/run/pluto/pluto.pid plutoctl=/var/run/pluto/pluto.ctl subsyslock=/var/lock/subsys/ipsec lock=/var/run/pluto/ipsec_setup.pid xfrm_stat=/proc/sys/net/core/xfrm_acq_expires # defaults for "config setup" items IPSECuniqueids=${IPSECuniqueids:-yes} IPSECcrlcheckinterval=${IPSECcrlcheckinterval:-0} IPSECprotostack=${IPSECprotostack:-bsdkame} IPSECplutostderrlogtime=${IPSECplutostderrlogtime:-no} # IPSECoverridemtu "" # which kernel are we using? case $IPSECprotostack in bsdkame) ;; *) echo "On FreeBSD the stack must be bsdkame (not $IPSECprotostack)"; exit 1;; esac # Shall we trace? execute="true" display="false" for i in $IPSEC_setupflags do case "$i" in "--showonly") execute="false" ; display=true ;; "--show") display=true ;; esac done if $display then echo " " PATH="$PATH" fi perform() { if $display then echo " " "$*" fi if $execute then eval "$*" fi } # for no-stdout logging: LOGONLY="logger -p daemon.error -t ipsec_setup" KILLKLIPS='echo "Clearing out any lingering policy "; setkey -F; setkey -FP' # do it case "$1" in start|--start|_autostart) # First, does it seem to be going already? perform test ! -f $lock "||" "{" \ echo "\"Libreswan IPsec apparently already running, start aborted\"" ";" \ exit 1 ";" \ "}" # announcement # (Warning, changes to this log message may affect barf.) version="$(ipsec --version | awk 'NR == 1 { print $(3) }' | sed -e 's/^U\(.*\)\/K(.*/\1/')" case "$1" in start|--start) perform echo "\"Starting Libreswan IPsec $version...\"" ;; _autostart) perform echo "\"Restarting Libreswan IPsec $version...\"" ;; esac # preliminaries perform rm -f $lock for f in /dev/random /dev/urandom do perform test -r $f "||" "{" \ echo "\"...unable to start Libreswan IPsec, no $f!\"" ";" \ exit 1 ";" \ "}" done # the meaning of $$ at a different runtime is questionable! perform echo '$$' ">" $lock perform test -s $lock "||" "{" \ echo "\"...unable to create $lock, aborting start!\"" ";" \ rm -f $lock ";" \ exit 1 ";" \ "}" # misc pre-Pluto setup perform test -d $(dirname $subsyslock) "&&" touch $subsyslock # Pluto case "$1" in start|--start) re= ;; _autostart) re=--re ;; esac perform ipsec _plutorun $re \ --debug "\"$IPSECplutodebug\"" \ --uniqueids "\"$IPSECuniqueids\"" \ --nocrsend "\"$IPSECnocrsend\"" \ --strictcrlpolicy "\"$IPSECstrictcrlpolicy\"" \ --keep_alive "\"$IPSECkeep_alive\"" \ --protostack "\"$IPSECprotostack\"" \ --virtual_private "\"$IPSECvirtual_private\"" \ --crlcheckinterval "\"$IPSECcrlcheckinterval\"" \ --nhelpers "\"$IPSECnhelpers\"" \ --dump "\"$IPSECdumpdir\"" \ --stderrlog "\"$IPSECplutostderrlog\"" \ --plutostderrlogtime "\"$IPSECplutostderrlogtime\"" \ --log daemon.error \ --pid "\"$plutopid\"" "||" "{" \ $KILLKLIPS ";" \ rm -f $lock ";" \ exit 1 ";" \ "}" # done! perform echo "\"...Libreswan IPsec started\"" "|" $LOGONLY ;; stop|--stop|_autostop) # _autostop is same as stop # Shut things down. perform echo "\"Stopping Libreswan IPsec...\"" perform \ if test -r $lock ";" \ then \ status=0 ";" \ else \ echo "\"stop ordered, but IPsec does not appear to be running!\"" ";" \ echo "\"doing cleanup anyway...\"" ";" \ status=1 ";" \ fi perform test -f $plutopid "&&" "{" \ if ps -p '`' cat $plutopid '`' ">" /dev/null ";" \ then \ ipsec whack --shutdown "|" grep -v "^002" ";" \ sleep 1 ";" \ if test -s $plutopid ";" \ then \ echo "\"Attempt to shut Pluto down failed! Trying kill:\"" ";" \ kill '`' cat $plutopid '`' ";" \ sleep 5 ";" \ fi ";" \ else \ echo "\"Removing orphaned $plutopid:\"" ";" \ fi ";" \ rm -f $plutopid ";" \ "}" perform $KILLKLIPS rm -f /var/run/pluto.pid # When we exit we clean up (remove) the modules we are using, even the kame'ish ones if test -e ${xfrm_stat}; then lsmod 2>&1 | grep "^xfrm4_tunnel" > /dev/null && rmmod xfrm4_tunnel lsmod 2>&1 | grep "^af_key" > /dev/null && rmmod af_key # old name for xfrm4_tunnel lsmod 2>&1 | grep "^xfrm_user" > /dev/null && rmmod xfrm_user fi perform test -d $(dirname $subsyslock) "&&" rm -f $subsyslock perform rm -f $lock $plutopid perform echo "...Libreswan IPsec stopped" "|" $LOGONLY perform exit \$status ;; status|--status) if test " $IPSEC_setupflags" != " " then echo "$me $1 does not support $IPSEC_setupflags" exit 1 fi if test -f $lock then haslock=yes fi if test -f $subsyslock then hassublock=yes fi if test -s $plutopid then if ps -p $(cat $plutopid) >/dev/null then plutokind=normal elif ps -C pluto >/dev/null then plutokind=illicit fi elif ps -C pluto >/dev/null then plutokind=orphaned else plutokind=no fi if test -r /proc/net/ipsec_eroute then if test " $(wc -l /proc/net/ipsec_eroute 2> /dev/null )" -gt 0 then eroutes=$(wc -l /proc/net/ipsec_eroute 2> /dev/null | sed -e 's/ //g') fi else eroutes=$(ipsec eroute 2> /dev/null | wc -l | sed -e 's/\ //g') fi if test "$haslock" then echo "IPsec running" " - pluto pid: $(cat $plutopid)" # might not be a subsystem lock dir, ignore that issue if test "$plutokind" = "normal" -a \( "$klips" = "yes" -o "$lk26sec" = "yes" \) then echo "pluto pid $(cat $plutopid)" case "$eroutes" in 0) echo "No tunnels up" ;; *) echo "$eroutes tunnels up" ;; esac exit 0 fi echo "but..." if test "$plutokind" != "normal" then echo "$plutokind Pluto running" " - pluto pid: $(cat $plutopid)" fi case $klips in maybe) echo "KLIPS module is not loaded!" ;; none) echo "no KLIPS in kernel!" ;; esac if test "$eroutes" then if test "$eroutes" -gt 0 then echo "some eroutes exist" fi fi else echo "IPsec stopped" if test ! "$hassublock" -a "$plutokind" = "no" -a "$eroutes" -eq 0 then exit 0 fi echo "but..." if test "$hassublock" then echo "has subsystem lock ($subsyslock)!" fi if test "$plutokind" != "no" then echo "An ${plutokind} Pluto is running?" fi if test "$eroutes" -gt 0 then echo "some (${eroutes}) eroutes exist!" fi exit 1 fi # todo: ipsec verify --quiet that only shows problems /usr/sbin/ipsec verify; exit $?; ;; --version) if test " $IPSEC_setupflags" != " " then echo "$me $1 does not support $IPSEC_setupflags" exit 1 fi echo "$me $IPSEC_VERSION" exit 0 ;; --help) if test " $IPSEC_setupflags" != " " then echo "$me $1 does not support $IPSEC_setupflags" exit 1 fi echo "Usage: $me {--start|--stop|--restart|--status}" exit 0 ;; *) echo "Usage: $me {--start|--stop|--restart|--status}" >&2 exit 2 esac exit 0 libreswan-3.32/programs/_realsetup.bsd/ipsec_realsetup.8000066400000000000000000000034461365625662500235020ustar00rootroot00000000000000'\" t .\" Title: _REALSETUP .\" Author: Paul Wouters .\" Generator: DocBook XSL Stylesheets v1.77.1 .\" Date: 12/16/2012 .\" Manual: Executable programs .\" Source: libreswan .\" Language: English .\" .TH "_REALSETUP" "8" "12/16/2012" "libreswan" "Executable programs" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" https://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" ipsec__realsetup \- internal routine to start FreeS/WAN\&. .SH "DESCRIPTION" .PP \fI_realsetup\fR is called by the system init scripts to start the FreeS/WAN system\&. It starts \fBKLIPS\fR (the kernel component) and \fBpluto\fR (the userspace keying component)\&. .SH "SEE ALSO" .PP \fBipsec\fR(8), \fBipsec__klipsstart\fR(8), \fBipsec__plutorun\fR(8)\&. .SH "HISTORY" .PP Man page written for the Linux FreeS/WAN project <\m[blue]\fBhttp://www\&.freeswan\&.org/\fR\m[]> by Michael Richardson\&. Original program by Henry Spencer\&. .SH "AUTHOR" .PP \fBPaul Wouters\fR .RS 4 placeholder to suppress warning .RE libreswan-3.32/programs/_secretcensor/000077500000000000000000000000001365625662500201375ustar00rootroot00000000000000libreswan-3.32/programs/_secretcensor/Makefile000066400000000000000000000013621365625662500216010ustar00rootroot00000000000000# Makefile for miscellaneous programs # Copyright (C) 2002 Michael Richardson # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. PROGRAM=_secretcensor ifdef top_srcdir include $(top_srcdir)/mk/program.mk else include ../../mk/program.mk endif libreswan-3.32/programs/_secretcensor/_secretcensor.8.xml000066400000000000000000000032361365625662500236710ustar00rootroot00000000000000 PaulWoutersplaceholder to suppress warning _SECRETCENSOR 8 25 Apr 2002 libreswan Executable programs ipsec _secretcensor internal routing to sanitize files DESCRIPTION _secretcensor is called by ipsec barf to process the @IPSEC_SECRETS_FILE@ file to remove the private key components from the file prior to revealing the contents. SEE ALSO ipsec8, ipsec_barf8. HISTORY Man page written for the Linux FreeS/WAN project <https://www.freeswan.org/> by Michael Richardson. Original program by Henry Spencer. libreswan-3.32/programs/_secretcensor/_secretcensor.in000077500000000000000000000035761365625662500233430ustar00rootroot00000000000000#! /bin/sh # implements secret censoring for barf # Copyright (C) 1999 Henry Spencer. # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. usage="Usage: $0 [file ...]" me="ipsec _secretcensor" while [ "$#" != 0 ] do case "$1" in --help) echo "$usage" ; exit 0 ;; --version) echo "$me $IPSEC_VERSION" ; exit 0 ;; --) shift ; break ;; -*) echo "$0: unknown option \`$1'" >&2 ; exit 2 ;; *) break ;; esac shift done awk ' function cool(hot, q, cooled, run) { # warning: may destroy input line! q = "'"'"'" # single quote if (hot ~ q) return "[cannot be summed]" if (hot ~ /^0s/) return "[keyid " substr(hot, 3, 9) "]" run = "echo " q hot q " | md5sum" run | getline close(run) return "[sums to " substr($1, 1, 4) "...]" } /"/ { i = match($0, /"[^"]+"/) cold1 = substr($0, 1, i) cold2 = substr($0, i+RLENGTH-1) hot = substr($0, i+1, RLENGTH-2) print cold1 cool(hot) cold2 next } /#pubkey=/ { i = match($0, /^.*#pubkey=/) i += RLENGTH-1 cold = substr($0, 1, i) hot = substr($0, i+1) print cold cool(hot) next } /#IN KEY / { i = match($0, /^.*[ \t][^ \t]/) i += RLENGTH-2 cold = substr($0, 1, i) hot = substr($0, i+1) print cold cool("0s" hot) next } /^[ \t]+(Modulus|P[a-z]+Exponent|Prime[12]|Exponent[12]|Coefficient):/ { i = match($0, /^[^:]*:[ \t]*/) i += RLENGTH-1 cold = substr($0, 1, i) print cold "[...]" next } { print }' "$@" libreswan-3.32/programs/_stackmanager/000077500000000000000000000000001365625662500201005ustar00rootroot00000000000000libreswan-3.32/programs/_stackmanager/Makefile000066400000000000000000000013551365625662500215440ustar00rootroot00000000000000# Makefile for miscellaneous programs # Copyright (C) 2012 Paul Wouters # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. PROGRAM=_stackmanager ifdef top_srcdir include $(top_srcdir)/mk/program.mk else include ../../mk/program.mk endif libreswan-3.32/programs/_stackmanager/_stackmanager.8.xml000066400000000000000000000066321365625662500235760ustar00rootroot00000000000000 PaulWoutersplaceholder to suppress warning _STACKMANAGER 8 06 May 2019 libreswan Executable programs ipsec _stackmanager internal script to bring up kernel components for Libreswan ipsec _stackmanager start --xfrm ipsec _stackmanager stop DESCRIPTION ipsec _stackmanager is called from within the init sub-system (systemd, upstart, sysv initscripts) to bring up the Libreswan kernel component as configured via the protostack= option in the ipsec.conf configuration file. This involves loading and optionally unloading of the required kernel modules. Because the Linux kernel cannot autodetect most crypto related drivers on-demand, _stackmanager handles loading OpenBSD/FreeBSD Cryptographic Framework (OCF) drivers, CryptoAPI drivers, and the modules for the specific IPsec stack (Linux XFRM or KLIPS). Probing for OCF supported hardware is not supported - those modules must be loaded by the system before the start of the Libreswan sub system. When the --xfrm option is given to the start command, the XFRM stack is loaded regardless of the existence or contents of the ipsec.conf file. This is used for docker tests where the host system, which might not have libreswan installed, needs to run _stackmanager from the source tree to load the modules on the host so the modules are available inside the containers. SEE ALSO ip8, ipsec_tncfg8, ipsec.conf5, ipsec_addconn8, pluto8 HISTORY This script was introduced in Libreswan. On the older Openswan systems, this functionality was split over various script files such as ipsec _startnetkey, ipsec _startklips, ipsec _realsetup and ipsec setup. Man page written for the Libreswan project <https://libreswan.org/> by Paul Wouters. libreswan-3.32/programs/_stackmanager/_stackmanager.in000066400000000000000000000303011365625662500232240ustar00rootroot00000000000000#!@SHELL_BINARY@ # STACK startup script # Copyright (C) 2007 Ken Bantoft # Copyright (C) 2007-2008 Paul Wouters # Copyright (C) 2008-2019 Tuomo Soini # Copyright (C) 2012-2014 Paul Wouters # Copyright (C) 2019 Paul Wouters # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # # nothing to do if the kernel has no module loading/unloading support [ ! -f /proc/modules ] && exit 0 # These prevent coverity warnings; variables come in via ipsec addconn call xfrmlifetime="" overridemtu="" fragicmp="" hidetos="" IPSEC_CONF="${IPSEC_CONF:-@FINALCONFFILE@}" PATH=@FINALSBINDIR@:${PATH} export PATH # export config setup items needs rename of - to _ eval $(ASAN_OPTIONS=detect_leaks=0 ipsec addconn --configsetup | grep -v "#" | sed "s/-/_/g") test ${IPSEC_INIT_SCRIPT_DEBUG} && set -v -x MODPROBE="@MODPROBEBIN@ @MODPROBEARGS@" xfrm_stat=/proc/sys/net/core/xfrm_acq_expires klipsstack=/proc/net/ipsec/version action="${1}" if [ -z "${action}" ]; then echo "no action specified - aborted" >&2 exit 1 fi stopnetkey() { local wait larval_drop wait="" larval_drop="" # Validate wait option [ "${1}" = "--wait" -o "${1}" = "-w" ] && wait="${1}" if [ -f ${xfrm_stat} ]; then ip xfrm state flush ip xfrm policy flush if [ -n "$(ip xfrm state)" -o -n "$(ip xfrm policy)" ]; then echo "XFRM IPsec stack could not be cleared" >&2 fi if [ -f /proc/modules ]; then # check if we can write our own settings if [ -n "${wait}" -a -w /proc/sys/net/core/xfrm_larval_drop ]; then # read previous state so we can restore it larval_drop=$(cat /proc/sys/net/core/xfrm_larval_drop) if [ -n "${larval_drop}" ]; then # set to 0 so we can unload modules echo 0 >/proc/sys/net/core/xfrm_larval_drop fi fi # netkey stack found, let's unload. for mod in xfrm_ipcomp ipcomp ipcomp6 ip_vti xfrm6_tunnel \ xfrm6_mode_tunnel xfrm6_mode_beet xfrm6_mode_ro \ xfrm6_mode_transport xfrm4_mode_transport xfrm4_mode_tunnel \ xfrm4_tunnel xfrm4_mode_beet esp4 esp6 ah4 ah6 \ xfrm_user xfrm_interface do # first try and unload the modules without the 10s wait pause if [ -n "$(grep ^${mod} /proc/modules)" ]; then # echo "unloading module ${mod}" >&2 rmmod ${mod} 2>/dev/null fi # We only run rmmod again with --wait if requested if [ -n "${wait}" -a \ -n "$(grep ^${mod} /proc/modules)" ]; then # echo "unloading module ${mod} using --wait" >&2 # we start rmmod to background so unloading one module # won't block rmmod ${wait} ${mod} 2>/dev/null & fi done # Finally we wait for background executed rmmods to complete if [ -n "${wait}" ]; then wait if [ -n "${larval_drop}" -a \ -w /proc/sys/net/core/xfrm_larval_drop ]; then # restore original value of xfrm_larval_drop echo "${larval_drop}" >/proc/sys/net/core/xfrm_larval_drop larval_drop="" fi fi fi fi # if we were executed with --wait or -w option we inform about unload # failure if [ -n "${wait}" -a -n "$(lsmod | grep ^esp)" ]; then echo "FAIL" >&2 exit 1 fi } # We can get called even if we abort with "pluto already running" startnetkey() { # in case pluto crashed if pidof pluto > /dev/null; then : pluto is running, skip cleanup else ip xfrm policy flush ip xfrm state flush fi cryptomodules if [ -f ${klipsstack} ]; then echo "Warning: found KLIPS stack loaded - attempting to unload..." >&2 stopklips if [ -f ${klipsstack} ]; then echo "FAILURE to unload KLIPS module" >&2 exit 1 fi fi if [ -f /proc/modules ]; then # load all XFRM modules for mod in ipcomp6 xfrm_ipcomp ipcomp xfrm6_tunnel xfrm6_mode_tunnel \ xfrm6_mode_beet xfrm6_mode_ro xfrm6_mode_transport \ xfrm4_mode_transport xfrm4_mode_tunnel xfrm4_tunnel \ xfrm4_mode_beet esp4 esp6 ah4 ah6 ip_vti xfrm_interface do # echo -n "${mod} " >&2 ${MODPROBE} ${mod} 2>/dev/null done # xfrm_user is the old name for xfrm4_tunnel - backwards compatibility ${MODPROBE} xfrm_user 2>/dev/null fi # Time before kernel ACQUIRE for ondemand/ Opportunistic expires # Also Time before reserved kernel SPI times out xcur=$(cat /proc/sys/net/core/xfrm_acq_expires 2>/dev/null) if [ -w /proc/sys/net/core/xfrm_acq_expires ]; then if [ ${xfrmlifetime} -ne 0${xcur} ]; then echo "changing /proc/sys/net/core/xfrm_acq_expires from ${xcur} to ${xfrmlifetime}" echo ${xfrmlifetime} >/proc/sys/net/core/xfrm_acq_expires fi else echo "WARNING: can not change /proc/sys/net/core/xfrm_acq_expires from ${xcur} to ${xfrmlifetime}" >&2 fi # Fail on error in loading XFRM IPsec stack if [ ! -f ${xfrm_stat} ]; then echo "FAILURE in loading XFRM IPsec stack" >&2 exit 1 fi } stopklips() { if [ -f ${klipsstack} ]; then # Bring down ipsecX interfaces ifl=$(grep -v NULL /proc/net/ipsec_tncfg 2>/dev/null | sed -n -e "/^ipsec/s/ .*//p") if [ -n "${ifl}" ]; then for iface in ${ifl}; do ip link set ${iface} down ip addr flush dev ${iface} ipsec tncfg --detach --virtual ${iface} # ipsec0 won't let itself be deleted ipsec tncfg --delete ${iface} done [ -r /proc/net/ipsec_klipsdebug ] && ipsec klipsdebug --none [ -d /proc/net/ipsec/eroute ] && ipsec eroute --clear [ -d /proc/net/ipsec/spi ] && ipsec spi --clear fi if [ -f /proc/modules ]; then rmmod ipsec 2>/dev/null fi fi if [ -f ${klipsstack} -o -n "$(lsmod | grep ^ipsec)" ]; then echo "FAILURE to unload KLIPS module" >&2 exit 1 fi } stop() { stopnetkey stopklips } cryptomodules() { # load any OCF and CryptoAPI modules we might need for acceleration # (OCF works for XFRM IPsec and KLIPS) # OCF cryptosoft is for kernel acceleration (ESP/AH) ${MODPROBE} cryptosoft 2>/dev/null # We skip cryptodev.ko because we no longer support /dev/crypto offloading # (the overhead of cryptodev is not worth it even on embedded platforms) if [ -d /sys/module/ocf ]; then # OCF tuning - If we have enough bogomips and RAM, # use bigger OCF queues bogomips=$(grep -i bogomips /proc/cpuinfo | head -1 | awk '{print $3;}' | sed "s/\..*$//") ram=$(head -1 /proc/meminfo | awk '{print $2;}') limit=1000 if [ ${bogomips} -gt 1000 ]; then if [ ${ram} -gt 262143 ]; then limit=10000 #echo "OCF limit set to ${limit}" >&2 fi fi echo ${limit} >/sys/module/ocf/parameters/crypto_q_max fi # load the most common ciphers/algo's # padlock must load before aes module - though does not exist on newer # kernels # padlock-aes must load before padlock-sha for some reason ${MODPROBE} padlock 2>/dev/null ${MODPROBE} padlock-aes 2>/dev/null ${MODPROBE} padlock-sha 2>/dev/null # load the most common ciphers/algo's # aes-x86_64 has higher priority in via crypto api # kernel directory does not match uname -m on x86_64 :( modules=$(ls /lib/modules/$(uname -r)/kernel/arch/*/crypto/* 2>/dev/null) modules="aesni-intel aes-x86_64 geode-aes aes aes_generic des sha512 \ sha256 md5 cbc xcbc ecb twofish blowfish serpent ccm gcm ctr cts \ deflate cast5 cast6 lzo sha256_generic sha512_generic camellia \ cmac chacha20poly1305 ${modules}" for module in ${modules} do module=$(basename ${module} | sed "s/\.ko$//") # echo -n "${module} " >&2 ${MODPROBE} ${module} 2>/dev/null done } startklips() { cryptomodules if [ -f ${xfrm_stat} ]; then echo "Warning: found possible XFRM IPsec stack loaded - attempting to unload..." >&2 stopnetkey --wait fi if [ ! -f ${klipsstack} ]; then # KLIPS-related paths bareversion=$(uname -r | sed -e 's/\.nptl//' | sed -e 's/^\(2\.[0-9]\.[1-9][0-9]*-[1-9][0-9]*\(\.[0-9][0-9]*\)*\(\.x\)*\).*$/\1/') case ${bareversion} in 2.4*) modulename=ipsec.o ;; *) modulename=ipsec.ko ;; esac # modprobe does not like specifying .o or .ko, but insmod needs it if [ "$(basename "@MODPROBEBIN@")" = "modprobe" ]; then ${MODPROBE} ipsec else ${MODPROBE} ${modulename} fi if [ ! -f ${klipsstack} ]; then echo "FAILURE to load KLIPS module" >&2 exit 1 fi if [ -d /sys/module/ocf ]; then echo ${limit} >/sys/module/ipsec/parameters/ipsec_irs_cache_allocated_max echo ${limit} >/sys/module/ipsec/parameters/ipsec_ixs_cache_allocated_max fi fi if [ ${stack} = "klips" ]; then # in klips mode we attach it to the physical device # clear tables out in case dregs have been left over ipsec eroute --clear ipsec spi --clear # detach all ipsecX devices ipsec tncfg --clear phys=$(ip ro li | grep default | sed "s/^.* dev \([^ ]*\) .*$/\1/") if [ -z "${interfaces}" ]; then interfaces="%defaultroute" if [ -z "$phys" ]; then echo "ERROR: no default route found and no interfaces= option set" exit 1 fi fi for iface in ${interfaces}; do if [ "${iface}" = "%none" ]; then echo "ignoring obsolete interface %none" >&2 continue elif [ "${iface}" = "%defaultroute" ]; then virt="ipsec0" else virt="$(expr ${iface} : '\([^=]*\)=.*')" phys="$(expr ${iface} : '[^=]*=\(.*\)')" fi # ipsecX might not exist yet if [ ! -d /sys/devices/virtual/net/${virt} ]; then ipsec tncfg --create ${virt} fi ipsec tncfg --attach --virtual ${virt} --physical ${phys} # configure all the IPv4/IPv6 addresses (including point-to-point) ip addr show dev ${phys} label ${phys} | \ awk '$1 == "inet" || ($1 == "inet6" && !/ dynamic/) { cmd = "ip addr add" if ($1 == "inet") sub(" [^ ]+:[^ ]+"," ") sub("secondary","") sub("/.*","",$2) sub("dynamic","") for (i = 2; i < NF; i++) { if ($i == "brd" || $i == "peer" || $i == "secondary") i++ else cmd = cmd " " $i } if ($NF != phys) cmd = cmd " " $NF cmd = cmd " dev " virt ">/dev/null 2>/dev/null" system(cmd) }' phys=${phys} virt=${virt} ip link set up dev ${virt} if [ "${overridemtu}" != "" ]; then ip link set mtu ${overridemtu} dev ${virt} else # Double check the mtu is not 0 # if it is set it to a saner default ip link show dev ${virt} | grep -q 'mtu 0 ' RETVAL=$? if [ "${RETVAL}" -eq 0 ]; then echo "Fixup of mtu on ${virt} to 16260" >&2 ip link set mtu 16260 dev ${virt} fi fi done elif [ ${stack} = "none" ]; then echo "protostack=none selected - No IPsec SA's will be injected into the kernel" >&2 fi # global module options for KLIPS if [ "${fragicmp}" = "yes" ]; then echo 1 >/proc/sys/net/ipsec/icmp fi if [ "${hidetos}" = "no" ]; then echo 0 >/proc/sys/net/ipsec/tos fi } # Start the actual work if [ $(id -u) -ne 0 ]; then echo "permission denied (must be superuser)" >&2 exit 4 fi if [ "$2" = "--netkey" -o "$2" = "--xfrm" ]; then # manual override for use in docker stack=netkey else stack="$(ASAN_OPTIONS=detect_leaks=0 ipsec addconn --config ${IPSEC_CONF} --liststack | grep -v "#")" fi case ${stack} in netkey|klips|none) ;; auto) echo "protostack=auto is not longer supported, defaulting to netkey" >&2 stack=netkey ;; *) echo "unknown stack ${stack}" >&2 exit 1 ;; esac case ${action} in stop) # We don't unload XFRM IPsec on stop - only when we detect a stack # change. if [ -f ${klipsstack} ]; then ipsec eroute --clear # this clears all IP addresses on ipsecX interfaces by # unloading the module stopklips elif [ -f ${xfrm_stat} ]; then ip xfrm state flush ip xfrm policy flush # module unloading skipped on purpose - can hang for a long # time or fail fi ;; start) case ${stack} in netkey) startnetkey ;; klips) startklips ;; esac ;; restart) stop start ;; *) echo "unknown action ${action}" >&2 exit 1 ;; esac exit 0 libreswan-3.32/programs/_unbound-hook/000077500000000000000000000000001365625662500200505ustar00rootroot00000000000000libreswan-3.32/programs/_unbound-hook/Makefile000066400000000000000000000014041365625662500215070ustar00rootroot00000000000000# Makefile for miscellaneous programs # Copyright (C) 2017 Paul Wouters # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. PROGRAM=_unbound-hook ifdef top_srcdir include $(top_srcdir)/mk/program.mk else include ../../mk/program.mk endif programs: ${PROGRAM} libreswan-3.32/programs/_unbound-hook/_unbound-hook.8.xml000066400000000000000000000032121365625662500235050ustar00rootroot00000000000000 PaulWoutersplaceholder to suppress warning _UNBOUND-HOOK 8 22 Oct 2017 libreswan Executable programs ipsec _unbound-hook Opportunistic IPsec DNS unbound hook script _unbound-hook is invoked by the unbound DNS server to inform pluto of a new hostname, IP address and public key, so that pluto can opportunistically initiate an IPsec connection. Please see the libreswan wiki for more information about Opportunistic IPsec. SEE ALSO ipsec8, ipsec_pluto8. HISTORY Man page written for the libreswan project <https:/libreswan.org/> by Paul Wouters. libreswan-3.32/programs/_unbound-hook/_unbound-hook.in000077500000000000000000000041161365625662500231540ustar00rootroot00000000000000#!@PYTHON_BINARY@ # # Copyright (C) 2018 Paul Wouters # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. import sys import subprocess # Get my %defaultroute IP address myip = subprocess.check_output("ip -o route get 8.8.8.8", shell=True) myip = myip.split("src")[1].strip().split()[0] argv = sys.argv ourself = argv.pop(0) try: qname = argv.pop(0) ttl = argv.pop(0) ip = argv.pop(0) except: sys.exit("Bad arguments to ipsec _unbound") # unbound now quotes the entire RRDATAs, so it counts as 1 argument in the list data = argv.pop(0).split(" ") while (data != []): try: gwprec = data.pop(0) gwtype = data.pop(0) gwalg = data.pop(0) gwid = data.pop(0) pubkey = data.pop(0) addkeyip = "ipsec whack --keyid %s --addkey --pubkeyrsa 0s%s"%(ip, pubkey) addkeyhostname = "ipsec whack --keyid @%s --addkey --pubkeyrsa 0s%s"%(qname, pubkey) print("processing an IPSECKEY record for Opportunistic IPsec to %s(%s)"%(qname,ip)) print(subprocess.call(addkeyip, shell=True)) print(subprocess.call(addkeyhostname, shell=True)) except: sys.exit("failed to process an IPSECKEY record for Opportunistic IPsec to %s(%s)"%(qname,ip)) # done injecting all IPSECKEY records into pluto - try actual OE now cmdoeip = "ipsec whack --oppohere %s --oppothere %s"%(myip, ip) print(subprocess.check_output(cmdoeip, shell=True)) #cmdoeqname = "ipsec whack --oppohere %s --oppothere %s"%(myip, qname) #ret, output = commands.getstatusoutput(cmdoeqname) print(subprocess.check_output("ipsec whack --trafficstatus", shell=True)) libreswan-3.32/programs/_updown.bsdkame/000077500000000000000000000000001365625662500203615ustar00rootroot00000000000000libreswan-3.32/programs/_updown.bsdkame/Makefile000066400000000000000000000014201365625662500220160ustar00rootroot00000000000000# Makefile for miscellaneous programs # Copyright (C) 2002-2006 Michael Richardson # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. PROGRAM=_updown.bsdkame ifdef top_srcdir include $(top_srcdir)/mk/program.mk else include ../../mk/program.mk endif programs: ${PROGRAM} libreswan-3.32/programs/_updown.bsdkame/_updown.bsdkame.8.xml000066400000000000000000000034621365625662500243360ustar00rootroot00000000000000 PaulWoutersplaceholder to suppress warning _UPDOWN 8 25 Apr 2002 libreswan Executable programs ipsec _updown.bsdkame bsd manipulation script _updown is invoked by pluto when it has brought up a new connection. This script is used to insert the appropriate routing entries for IPsec operation. The BSD version of this script does very little at present, and does not support the sourceip= parameters. SEE ALSO ipsec 8 , ipsec_pluto 8 . HISTORY Man page written for the Linux FreeS/WAN project <https://www.freeswan.org/> by Michael Richardson. Original program written by Henry Spencer. libreswan-3.32/programs/_updown.bsdkame/_updown.bsdkame.in000066400000000000000000000160331365625662500237740ustar00rootroot00000000000000#! /bin/sh # iproute2 version, default updown script # # Copyright (C) 2003-2004 Nigel Metheringham # Copyright (C) 2002-2004 Michael Richardson # Copyright (C) 2003-2005 Tuomo Soini # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # # CAUTION: Installing a new version of FreeS/WAN will install a new # copy of this script, wiping out any custom changes you make. If # you need changes, make a copy of this under another name, and customize # that, and use the (left/right)updown parameters in ipsec.conf to make # FreeS/WAN use yours instead of this default one. test $IPSEC_INIT_SCRIPT_DEBUG && set -v -x LC_ALL=C export LC_ALL # things that this script gets (from ipsec_pluto(8) man page) # # # PLUTO_VERSION # indicates what version of this interface is being # used. This document describes version 1.1. This # is upwardly compatible with version 1.0. # # PLUTO_VERB # specifies the name of the operation to be performed # (prepare-host, prepare-client, up-host, up-client, # down-host, or down-client). If the address family # for security gateway to security gateway communica- # tions is IPv6, then a suffix of -v6 is added to the # verb. # # PLUTO_CONNECTION # is the name of the connection for which we are # routing. # # PLUTO_CONN_POLICY # the policy of the connection, as in: # RSASIG+ENCRYPT+TUNNEL+PFS+DONTREKEY+OPPORTUNISTIC+failureDROP+lKOD+rKOD # # PLUTO_NEXT_HOP # is the next hop to which packets bound for the peer # must be sent. # # PLUTO_INTERFACE # is the name of the ipsec interface to be used. # # PLUTO_ME # is the IP address of our host. # # PLUTO_MY_CLIENT # is the IP address / count of our client subnet. If # the client is just the host, this will be the # host's own IP address / mask (where max is 32 for # IPv4 and 128 for IPv6). # # PLUTO_MY_CLIENT_NET # is the IP address of our client net. If the client # is just the host, this will be the host's own IP # address. # # PLUTO_MY_CLIENT_MASK # is the mask for our client net. If the client is # just the host, this will be 255.255.255.255. # # PLUTO_MY_SOURCEIP # if non-empty, then the source address for the route will be # set to this IP address. # # PLUTO_MY_PROTOCOL # is the protocol for this connection. Useful for # firewalling. # # PLUTO_MY_PORT # is the port. Useful for firewalling. # # PLUTO_PEER # is the IP address of our peer. # # PLUTO_PEER_CLIENT # is the IP address / count of the peer's client sub- # net. If the client is just the peer, this will be # the peer's own IP address / mask (where max is 32 # for IPv4 and 128 for IPv6). # # PLUTO_PEER_CLIENT_NET # is the IP address of the peer's client net. If the # client is just the peer, this will be the peer's # own IP address. # # PLUTO_PEER_CLIENT_MASK # is the mask for the peer's client net. If the # client is just the peer, this will be # 255.255.255.255. # # PLUTO_PEER_PROTOCOL # is the protocol set for remote end with port # selector. # # PLUTO_PEER_PORT # is the peer's port. Useful for firewalling. # # PLUTO_CONNECTION_TYPE # # PLUTO_SA_REQID # When using KAME or XFRM/NETKEY, the IPsec SA reqid value # check parameter(s) case "$1:$*" in ':') # no parameters ;; ipfwadm:ipfwadm) # due to (left/right)firewall; for default script only ;; custom:*) # custom parameters (see above CAUTION comment) ;; *) echo "$0: unknown parameters \`$*'" >&2 exit 2 ;; esac # utility functions for route manipulation # Meddling with this stuff should not be necessary and requires great care. uproute() { doroute add } downroute() { doroute delete } uprule() { # virtual sourceip support if [ -n "$PLUTO_MY_SOURCEIP" ] then addsource changesource fi } downrule() { if [ -n "$PLUTO_MY_SOURCEIP" ] then dorule delete fi } addsource() { st=0 ## add an alias to the loopback interface if not already there snet=${PLUTO_MY_SOURCEIP}/32 st=1 return $st } changesource() { st=0 st=1 return $st } dorule() { st=0 return $st } doroute() { st=0 return $st } # the big choice case "$PLUTO_VERB:$1" in prepare-host:*|prepare-client:*) # delete possibly-existing route (preliminary to adding a route) exit 0 ;; route-host:*|route-client:*) # connection to me or my client subnet being routed uproute ;; unroute-host:*|unroute-client:*) # connection to me or my client subnet being unrouted downroute ;; up-host:*) # connection to me coming up uprule # If you are doing a custom version, firewall commands go here. ;; down-host:*) # connection to me going down downrule # If you are doing a custom version, firewall commands go here. ;; up-client:) # connection to my client subnet coming up uprule # If you are doing a custom version, firewall commands go here. ;; down-client:) # connection to my client subnet going down downrule # If you are doing a custom version, firewall commands go here. ;; up-client:ipfwadm) # connection to client subnet, with (left/right)firewall=yes, coming up uprule ;; down-client:ipfwadm) # connection to client subnet, with (left/right)firewall=yes, going down downrule ;; # # IPv6 # prepare-host-v6:*|prepare-client-v6:*) ;; route-host-v6:*|route-client-v6:*) # connection to me or my client subnet being routed #uproute_v6 ;; unroute-host-v6:*|unroute-client-v6:*) # connection to me or my client subnet being unrouted #downroute_v6 ;; up-host-v6:*) # connection to me coming up # If you are doing a custom version, firewall commands go here. ;; down-host-v6:*) # connection to me going down # If you are doing a custom version, firewall commands go here. ;; up-client-v6:) # connection to my client subnet coming up # If you are doing a custom version, firewall commands go here. ;; down-client-v6:) # connection to my client subnet going down # If you are doing a custom version, firewall commands go here. ;; *) echo "$0: unknown verb \`$PLUTO_VERB' or parameter \`$1'" >&2 exit 1 ;; esac libreswan-3.32/programs/_updown.klips/000077500000000000000000000000001365625662500200755ustar00rootroot00000000000000libreswan-3.32/programs/_updown.klips/Makefile000066400000000000000000000014161365625662500215370ustar00rootroot00000000000000# Makefile for miscellaneous programs # Copyright (C) 2002-2006 Michael Richardson # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. PROGRAM=_updown.klips ifdef top_srcdir include $(top_srcdir)/mk/program.mk else include ../../mk/program.mk endif programs: ${PROGRAM} libreswan-3.32/programs/_updown.klips/_updown.klips.8.xml000066400000000000000000000032111365625662500235560ustar00rootroot00000000000000 PaulWoutersplaceholder to suppress warning _UPDOWN 8 25 Apr 2002 libreswan Executable programs ipsec _updown.klips klips manipulation script _updown is invoked by pluto when it has brought up a new connection. This script is used to insert the appropriate routing entries for IPsec operation. The interface to the script is documented in the pluto man page. SEE ALSO ipsec8, ipsec_pluto8. HISTORY Man page written for the Linux FreeS/WAN project <https://www.freeswan.org/> by Michael Richardson. Original program written by Henry Spencer. libreswan-3.32/programs/_updown.klips/_updown.klips.in000066400000000000000000000445441365625662500232340ustar00rootroot00000000000000#! /bin/sh # iproute2 version, default updown script # # Copyright (C) 2003-2004 Nigel Metheringham # Copyright (C) 2002-2007 Michael Richardson # Copyright (C) 2003-2013 Tuomo Soini # Copyright (C) 2003-2007 Paul Wouters # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # CAUTION: Installing a new version of Libreswan will install a new # copy of this script, wiping out any custom changes you make. If # you need changes, make a copy of this under another name, and customize # that, and use the (left/right)updown= parameters in ipsec.conf to make # Libreswan use yours instead of this default one. test ${IPSEC_INIT_SCRIPT_DEBUG} && set -v -x LC_ALL=C export LC_ALL # things that this script gets (from ipsec_pluto(8) man page) # # # PLUTO_VERSION # indicates what version of this interface is being # used. This document describes version 1.1. This # is upwardly compatible with version 1.0. # # PLUTO_VERB # specifies the name of the operation to be performed # (prepare-host, prepare-client, up-host, up-client, # down-host, or down-client). If the address family # for security gateway to security gateway communications # is IPv6, then a suffix of -v6 is added to the # verb. # # PLUTO_CONNECTION # is the name of the connection for which we are # routing. # # PLUTO_CONN_POLICY # the policy of the connection, as in: # RSASIG+ENCRYPT+TUNNEL+PFS+DONTREKEY+OPPORTUNISTIC # +failureDROP+lKOD+rKOD # # PLUTO_NEXT_HOP # is the next hop to which packets bound for the peer # must be sent. # # PLUTO_VIRT_INTERFACE # is the name of the ipsec interface to be used. # # PLUTO_ME # is the IP address of our host. # # PLUTO_METRIC # is the metric to set for the route # # PLUTO_MTU # is the mtu to set for the route # # PLUTO_MY_CLIENT # is the IP address / count of our client subnet. If # the client is just the host, this will be the # host's own IP address / mask (where max is 32 for # IPv4 and 128 for IPv6). # # PLUTO_MY_CLIENT_NET # is the IP address of our client net. If the client # is just the host, this will be the host's own IP # address. # # PLUTO_MY_CLIENT_MASK # is the mask for our client net. If the client is # just the host, this will be 255.255.255.255. # # PLUTO_MY_SOURCEIP # if non-empty, then the source address for the route will be # set to this IP address. # # PLUTO_MY_PROTOCOL # is the protocol for this connection. Useful for # firewalling. # # PLUTO_MY_PORT # is the port. Useful for firewalling. # # PLUTO_PEER # is the IP address of our peer. # # PLUTO_PEER_CLIENT # is the IP address / count of the peer's client subnet. # If the client is just the peer, this will be # the peer's own IP address / mask (where max is 32 # for IPv4 and 128 for IPv6). # # PLUTO_PEER_CLIENT_NET # is the IP address of the peer's client net. If the # client is just the peer, this will be the peer's # own IP address. # # PLUTO_PEER_CLIENT_MASK # is the mask for the peer's client net. If the # client is just the peer, this will be # 255.255.255.255. # # PLUTO_PEER_PROTOCOL # is the protocol set for remote end with port # selector. # # PLUTO_PEER_PORT # is the peer's port. Useful for firewalling. # # PLUTO_CONNECTION_TYPE # # PLUTO_CONN_ADDRFAMILY # is the family type, "ipv4" or "ipv6" # # PLUTO_STACK # the kernel stack being used (eg protostack= value) # # PLUTO_NM_CONFIGURED=0|1 # is NetworkManager used for resolv.conf update # # PLUTO_SA_REQID # When using KAME or XFRM/NETKEY, the IPsec SA reqid value # Import default _updown configs from the # @FINALSYSCONFDIR@/[sysconfig|default]/pluto_updown file # # Two variables can be set in this file: # # IPROUTETABLE # is the default value for IPROUTETABLE # # IPROUTEARGS # is the extra argument list for ip route command # # IPRULEARGS # is the extra argument list for ip rule command # rpm based systems if [ -f @FINALSYSCONFDIR@/sysconfig/pluto_updown ]; then . @FINALSYSCONFDIR@/sysconfig/pluto_updown # deb based systems elif [ -f @FINALSYSCONFDIR@/default/pluto_updown ]; then . @FINALSYSCONFDIR@/default/pluto_updown fi LIBRESWAN_RESOLV_CONF=@IPSEC_RUNDIR@/libreswan-resolv-conf-backup ORIG_RESOLV_CONF=@FINALSYSCONFDIR@/resolv.conf MAX_CIDR=32 # for ipv4 [ "${PLUTO_CONN_ADDRFAMILY}" = ipv6 ] && MAX_CIDR=128 # check parameter(s) case "${1}:$*" in ':') # no parameters ;; custom:*) # custom parameters (see above CAUTION comment) ;; *) echo "${0}: unknown parameters \"$*\"" >&2 exit 2 ;; esac # utility functions for route manipulation # Meddling with this stuff should not be necessary and requires great care. uproute() { doproxyarp add doroute add ip route flush cache } downroute() { doroute delete ip route flush cache doproxyarp delete } uprule() { # policy based advanced routing if [ -n "${IPROUTETABLE}" ]; then dorule delete dorule add fi # virtual sourceip support if [ -n "${PLUTO_MY_SOURCEIP}" ]; then addsource changesource fi ip route flush cache } downrule() { if [ -n "${PLUTO_MY_SOURCEIP}" -a ${PLUTO_IS_PEER_CISCO} -eq 1 ]; then dorule delete ip route flush cache fi } updateresolvconf() { if [ -z "${PLUTO_PEER_DNS_INFO}" -o -z "${PLUTO_PEER_DOMAIN_INFO}" ]; then return 0 fi if [ -n "$(pidof unbound)" ]; then echo "updating local nameserver for ${PLUTO_PEER_DOMAIN_INFO} with ${PLUTO_PEER_DNS_INFO}" /usr/sbin/unbound-control forward_add ${PLUTO_PEER_DOMAIN_INFO} \ ${PLUTO_PEER_DNS_INFO} /usr/sbin/unbound-control flush_zone ${PLUTO_PEER_DOMAIN_INFO} /usr/sbin/unbound-control flush_requestlist return 0 fi if [ 0${PLUTO_NM_CONFIGURED} -eq 0 ]; then echo "updating resolvconf" if [ ! -e "${ORIG_RESOLV_CONF}" ]; then echo "resolv.conf does not exist, so doing nothing" return 0 fi if [ -e "${LIBRESWAN_RESOLV_CONF}" ]; then if grep -q Libreswan "${ORIG_RESOLV_CONF}"; then echo "Current resolv.conf is generated by Libreswan, and backup resolv.conf already exists, so doing nothing" return 0 else echo "backup resolv.conf exists, but current resolv.conf is not generated by Libreswan" fi fi rm -f -- "${LIBRESWAN_RESOLV_CONF}" cp -- "${ORIG_RESOLV_CONF}" "${LIBRESWAN_RESOLV_CONF}" RESOLVE_CONF="# Generated by Libreswan (IPsec)" if [ -n "${PLUTO_PEER_DOMAIN_INFO}" ]; then if grep -q ^domain "${ORIG_RESOLV_CONF}"; then RESOLVE_CONF="${RESOLVE_CONF} domain ${PLUTO_PEER_DOMAIN_INFO} search ${PLUTO_PEER_DOMAIN_INFO}" else RESOLVE_CONF="${RESOLVE_CONF} search ${PLUTO_PEER_DOMAIN_INFO}" fi fi if [ -n "${PLUTO_PEER_DNS_INFO}" ]; then for resolver in ${PLUTO_PEER_DNS_INFO}; do RESOLVE_CONF="${RESOLVE_CONF} nameserver ${resolver}" done fi ORIG_NAMESERVER=$(grep --max-count 1 ^nameserver "${ORIG_RESOLV_CONF}") RESOLVE_CONF="${RESOLVE_CONF} ${ORIG_NAMESERVER}" rm -f -- "${ORIG_RESOLV_CONF}" echo "${RESOLVE_CONF}" > "${ORIG_RESOLV_CONF}" return $? fi } restoreresolvconf() { if [ -z "${PLUTO_PEER_DNS_INFO}" -o -z "${PLUTO_PEER_DOMAIN_INFO}" ]; then return 0 fi if [ -n "$(pidof unbound)" ]; then echo "flushing local nameserver of ${PLUTO_PEER_DOMAIN_INFO}" /usr/sbin/unbound-control forward_remove ${PLUTO_PEER_DOMAIN_INFO} /usr/sbin/unbound-control flush_zone ${PLUTO_PEER_DOMAIN_INFO} /usr/sbin/unbound-control flush_requestlist return 0 fi if [ 0${PLUTO_NM_CONFIGURED} -eq 0 ]; then echo "restoring resolvconf" if [ ! -e "${LIBRESWAN_RESOLV_CONF}" ]; then echo "Problem in restoring the resolv.conf, as there is no backup file" return 2 fi if grep -q Libreswan "${ORIG_RESOLV_CONF}"; then cp -- "${LIBRESWAN_RESOLV_CONF}" "${ORIG_RESOLV_CONF}" else echo "Current resolv.conf is not generated by Libreswan, so doing nothing" fi rm -f -- "${LIBRESWAN_RESOLV_CONF}" return 0 fi } notifyNM() { # This will be called whenever a connection is established or # fails to establish (either phase 1, xauth phase, or phase 2) # or whenever an already established connection is being terminated. # This will send a singal to NetworkManager over dbus so that NM # can keep track of the coonnections. if [ 0${PLUTO_NM_CONFIGURED} -eq 1 ]; then echo "sending $1 signal to NetworkManager" libreswan_reason=$1 export libreswan_reason export PLUTO_PEER_DOMAIN_INFO export PLUTO_PEER_DNS_INFO export PLUTO_PEER_BANNER export PLUTO_MY_SOURCEIP export PLUTO_PEER [ -x /usr/libexec/nm-libreswan-service-helper ] && \ /usr/libexec/nm-libreswan-service-helper fi return 0 } addsource() { st=0 # check if given sourceip is local and add as alias if not if ! ip -o route get ${PLUTO_MY_SOURCEIP} | grep -q ^local; then it="ip addr add ${PLUTO_MY_SOURCEIP}/${MAX_CIDR} dev ${PLUTO_VIRT_INTERFACE%:*}" oops="$(eval ${it} 2>&1)" st=$? if [ -z "${oops}" -a ${st} -ne 0 ]; then oops="silent error, exit status ${st}" fi case "${oops}" in 'RTNETLINK answers: File exists'*) # should not happen, but ... ignore if the # address was already assigned on interface oops="" st=0 ;; esac if [ -n "${oops}" -o ${st} -ne 0 ]; then echo "${0}: addsource \"${it}\" failed (${oops})" >&2 fi fi return ${st} } changesource() { st=0 parms="${PLUTO_PEER_CLIENT}" parms2="dev ${PLUTO_VIRT_INTERFACE}" parms3="src ${PLUTO_MY_SOURCEIP}" if [ -n "${IPROUTETABLE}" ]; then parms3="${parms3} table ${IPROUTETABLE}" fi it="ip route replace ${parms} ${parms2} ${parms3}${PLUTO_MTU:+ mtu ${PLUTO_MTU}} ${PLUTO_METRIC:+ metric ${PLUTO_METRIC}}" case "${PLUTO_PEER_CLIENT}" in "0.0.0.0/0"|"::/0") # opportunistic encryption work around it= ;; esac oops="$(eval ${it} 2>&1)" st=$? if [ -z "${oops}" -a ${st} -ne 0 ]; then oops="silent error, exit status ${st}" fi if [ -n "${oops}" -o ${st} -ne 0 ]; then echo "${0}: changesource \"${it}\" failed (${oops})" >&2 fi return ${st} } dorule() { st=0 it2= iprule="from ${PLUTO_MY_CLIENT}" iprule2="to ${PLUTO_PEER_CLIENT}" if [ -n "${IPROUTETABLE}" ]; then iprule2="${iprule2} table ${IPROUTETABLE}" fi iprule2="${iprule2} ${IPRULEARGS}" case "${PLUTO_PEER_CLIENT}" in "0.0.0.0/0"|"::/0") # opportunistic encryption work around st=0 ;; *) if [ -z "${PLUTO_MY_SOURCEIP}" ]; then if [ "${PLUTO_ME}" = "${PLUTO_MY_CLIENT%/*}" ]; then it="ip rule ${1} iif lo ${iprule2}" else it="ip rule ${1} ${iprule} ${iprule2}" fi else if [ "${PLUTO_MY_SOURCEIP}" = "${PLUTO_MY_CLIENT%/*}" ]; then it="ip rule ${1} iif lo ${iprule2}" else it="ip rule ${1} ${iprule} ${iprule2}" it2="ip rule ${1} iif lo ${iprule2}" fi fi oops="$(eval ${it} 2>&1)" st=$? if [ -z "${oops}" -a ${st} -ne 0 ]; then oops="silent error, exit status ${st}" fi case "${oops}" in 'RTNETLINK answers: No such process'*) # This is what ip rule gives # for "could not find such a rule" oops= st=0 ;; esac if [ -n "${oops}" -o ${st} -ne 0 ]; then echo "${0}: dorule \"${it}\" failed (${oops})" >&2 fi if [ ${st} -eq 0 -a -n "${it2}" ]; then oops="$(eval ${it2} 2>&1)" st=$? if [ -z "${oops}" -a ${st} -ne 0 ]; then oops="silent error, exit status ${st}" fi case "${oops}" in 'RTNETLINK answers: No such process'*) # This is what ip rule gives # for "could not find such a rule" oops= st=0 ;; esac if [ -n "${oops}" -o ${st} -ne 0 ]; then echo "${0}: dorule \"${it2}\" failed (${oops})" >&2 fi fi ;; esac return ${st} } doproxyarp() { # Check if client has a single ip only client net if [ ${PLUTO_PEER_CLIENT#*/} = ${MAX_CIDR} ]; then # Skip OE special connections if [ ${PLUTO_PEER_CLIENT_NET} = 0.0.0.0 -o \ ${PLUTO_PEER_CLIENT_NET} = "::" ]; then return 0 fi # check if client is routeable if ip -o route get ${PLUTO_PEER_CLIENT_NET} | \ grep -E -q -s -v " via |^local"; then iface=$(ip -o route get ${PLUTO_PEER_CLIENT_NET} | \ awk '{print $3}') if [ -r /sys/class/net/${iface}/address ]; then macaddr=$(cat /sys/class/net/${iface}/address) fi # add/remove arp entry for the client on ethernet devices only if [ -n "${macaddr}" ]; then if [ "$1" = add ]; then ip neigh add proxy ${PLUTO_PEER_CLIENT_NET} dev ${iface} \ lladdr ${macaddr} nud permanent else ip neigh del proxy ${PLUTO_PEER_CLIENT_NET} dev ${iface} fi fi fi fi } doroute() { st=0 parms="${PLUTO_PEER_CLIENT}" parms2= if [ -n "${PLUTO_NEXT_HOP}" -a "${PLUTO_NEXT_HOP}" != "${PLUTO_PEER}" ]; then # nexthop is not needed on ppp interfaces. unset it to make cases # work, where left is set but no leftnexthop (e.g. left=%defaultroute) ip link show "${PLUTO_VIRT_INTERFACE%:*}" | grep -qs POINTOPOINT && unset PLUTO_NEXT_HOP # skip routing via nexthop if it is not reachable through any # directly connected network (but via default route only): ip route list match "${PLUTO_NEXT_HOP}" dev "${PLUTO_VIRT_INTERFACE}" | \ grep -qs -v default || unset PLUTO_NEXT_HOP if [ -n "${PLUTO_NEXT_HOP}" ]; then parms2="via ${PLUTO_NEXT_HOP}" fi fi parms2="${parms2} dev ${PLUTO_VIRT_INTERFACE}${PLUTO_MTU:+ mtu ${PLUTO_MTU}}${PLUTO_METRIC:+ metric ${PLUTO_METRIC}}" parms3="${IPROUTEARGS}" if [ -n "${IPROUTETABLE}" ]; then parms3="${parms3} table ${IPROUTETABLE}" fi if [ "${1}" = "add" -a -n "${PLUTO_MY_SOURCEIP}" ]; then addsource parms3="${parms3} src ${PLUTO_MY_SOURCEIP}" fi case "${PLUTO_PEER_CLIENT}" in "0.0.0.0/0") # opportunistic encryption work around # need to provide route that eclipses default, without # replacing it. it="ip route ${1} 0.0.0.0/1 ${parms2} ${parms3} && ip route ${1} 128.0.0.0/1 ${parms2} ${parms3}" ;; "::/0") # opportunistic encryption work around # need to provide route that eclipses default, without # replacing it. it="ip -6 route ${1} 0::/1 ${parms2} ${parms3} && ip -6 route ${1} 8000::/1 ${parms2} ${parms3}" ;; *) # Despite not having -6, the ip route commands works for ipv6 it="ip route ${1} ${parms} ${parms2} ${parms3}" ;; esac oops="$(eval ${it} 2>&1)" st=$? if [ -z "${oops}" -a ${st} -ne 0 ]; then oops="silent error, exit status ${st}" fi case "${oops}" in 'RTNETLINK answers: No such process'*) # should not happen, but ... ignore if the # route was already removed oops="" st=0 ;; esac if [ -n "${oops}" -o ${st} -ne 0 ]; then echo "${0}: doroute \"${it}\" failed (${oops})" >&2 fi return ${st} } # the big choice case "${PLUTO_VERB}:${1}" in prepare-host:*|prepare-client:*) # delete possibly-existing route (preliminary to adding a route) case "${PLUTO_PEER_CLIENT}" in "0.0.0.0/0") # need to provide route that eclipses default, without # replacing it. parms1="0.0.0.0/1" parms2="128.0.0.0/1" it="ip route delete ${parms1} ${IPROUTEARGS} 2>&1 ; ip route delete ${parms2} ${IPROUTEARGS} 2>&1" oops="$(ip route delete ${parms1} ${IPROUTEARGS} 2>&1 ; ip route delete ${parms2} ${IPROUTEARGS} 2>&1)" ;; "::/0") # need to provide route that eclipses default, without # replacing it. parms1="0::/1" parms2="8000::/1" it="ip route delete ${parms1} ${IPROUTEARGS} 2>&1 ; ip route delete ${parms2} ${IPROUTEARGS} 2>&1" oops="$(ip route delete ${parms1} ${IPROUTEARGS} 2>&1 ; ip route delete ${parms2} ${IPROUTEARGS} 2>&1)" ;; *) parms="${PLUTO_PEER_CLIENT} ${IPROUTEARGS}" if [ -n "${IPROUTETABLE}" ]; then parms="${parms} table ${IPROUTETABLE}" fi it="ip route delete ${parms} 2>&1" oops="$(ip route delete ${parms} 2>&1)" ;; esac st="$?" if [ -z "${oops}" -a ${st} -ne 0 ]; then oops="silent error, exit status ${st}" fi case "${oops}" in *'RTNETLINK answers: No such process'*) # This is what route (currently -- not documented!) gives # for "could not find such a route". oops= st=0 ;; esac if [ -n "${oops}" -o ${st} -ne 0 ]; then echo "${0}: \"${it}\" failed (${oops})" >&2 fi exit ${st} ;; route-host:*|route-client:*) # connection to me or my client subnet being routed uproute ;; unroute-host:*|unroute-client:*) # connection to me or my client subnet being unrouted downroute ;; up-host:*) # connection to me coming up uprule # If you are doing a custom version, firewall commands go here. ;; down-host:*) # connection to me going down downrule # If you are doing a custom version, firewall commands go here. ;; up-client:) # connection to my client subnet coming up uprule # If you are doing a custom version, firewall commands go here. updateresolvconf notifyNM connect ;; down-client:) # connection to my client subnet going down downrule # If you are doing a custom version, firewall commands go here. restoreresolvconf notifyNM disconnect ;; # # IPv6 # prepare-host-v6:*|prepare-client-v6:*) case "${PLUTO_PEER_CLIENT_NET}" in "0.0.0.0"|"::"|"%any") ;; *) ip -6 route del ${PLUTO_PEER_CLIENT} || echo ;; esac ;; route-host-v6:*|route-client-v6:*) # connection to me or my client subnet being routed uproute #uproute_v6 ;; unroute-host-v6:*|unroute-client-v6:*) # connection to me or my client subnet being unrouted downroute #downroute_v6 ;; up-host-v6:*) # connection to me coming up uprule # If you are doing a custom version, firewall commands go here. ;; down-host-v6:*) # connection to me going down downrule # If you are doing a custom version, firewall commands go here. ;; up-client-v6:) # connection to my client subnet coming up uprule # If you are doing a custom version, firewall commands go here. ;; down-client-v6:) # connection to my client subnet going down downrule # If you are doing a custom version, firewall commands go here. ;; *) echo "${0}: unknown verb \"${PLUTO_VERB}\" or parameter \"${1}\"" >&2 exit 1 ;; esac libreswan-3.32/programs/_updown.netkey/000077500000000000000000000000001365625662500202525ustar00rootroot00000000000000libreswan-3.32/programs/_updown.netkey/Makefile000066400000000000000000000014171365625662500217150ustar00rootroot00000000000000# Makefile for miscellaneous programs # Copyright (C) 2002-2006 Michael Richardson # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. PROGRAM=_updown.netkey ifdef top_srcdir include $(top_srcdir)/mk/program.mk else include ../../mk/program.mk endif programs: ${PROGRAM} libreswan-3.32/programs/_updown.netkey/_updown.netkey.8.xml000066400000000000000000000032171365625662500241160ustar00rootroot00000000000000 PaulWoutersplaceholder to suppress warning _UPDOWN 8 25 February 2008 libreswan Executable programs ipsec _updown.netkey klips manipulation script _updown is invoked by pluto when it has brought up a new connection. This script is used to insert the appropriate routing entries for IPsec operation. The interface to the script is documented in the pluto man page. SEE ALSO ipsec8, ipsec_pluto8. HISTORY Man page written for the Linux FreeS/WAN project <https://www.freeswan.org/> by Michael Richardson. Original program written by Henry Spencer. libreswan-3.32/programs/_updown.netkey/_updown.netkey.in000066400000000000000000000646601365625662500235670ustar00rootroot00000000000000#! /bin/sh # # default updown script for use with NETKEY(XFRM) # # Copyright (C) 2003-2004 Nigel Metheringham # Copyright (C) 2002-2007 Michael Richardson # Copyright (C) 2007-2008 Paul Wouters # Copyright (C) 2003-2020 Tuomo Soini # Copyright (C) 2011-2016 Paul Wouters # Copyright (C) 2016 Antony Antony # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # CAUTION: Installing a new version of Libreswan will install a new # copy of this script, wiping out any custom changes you make. If # you need changes, make a copy of this under another name, and customize # that, and use the (left/right)updown= parameters in ipsec.conf to make # Libreswan use your modified updown script instead of this default one. test ${IPSEC_INIT_SCRIPT_DEBUG} && set -v -x LC_ALL=C export LC_ALL # Things that this script gets (from ipsec_pluto(8) man page) # # # PLUTO_VERSION # indicates what version of this interface is being # used. This document describes version 1.1. This # is upwardly compatible with version 1.0. # # PLUTO_VERB # specifies the name of the operation to be performed # (prepare-host, prepare-client, up-host, up-client, # down-host, or down-client). If the address family # for security gateway to security gateway # communications is IPv6, then a suffix of -v6 is added # to the verb. # # PLUTO_CONNECTION # is the name of the connection for which we are # routing. # # PLUTO_CONN_POLICY # the policy of the connection, as in: # RSASIG+ENCRYPT+TUNNEL+PFS+DONTREKEY+OPPORTUNISTIC # +failureDROP+lKOD+rKOD # # PLUTO_NEXT_HOP # is the next hop to which packets bound for the peer # must be sent. # # PLUTO_INTERFACE # is the name of the real interace used for encrypted, IKE traffic # # PLUTO_ME # is the IP address of our host. # # PLUTO_METRIC # is the metric to set for the route # # PLUTO_MTU # is the mtu to set for the route # # PLUTO_MY_CLIENT # is the IP address / count of our client subnet. If # the client is just the host, this will be the # host's own IP address / mask (where max is 32 for # IPv4 and 128 for IPv6). # # PLUTO_MY_CLIENT_NET # is the IP address of our client net. If the client # is just the host, this will be the host's own IP # address. # # PLUTO_MY_CLIENT_MASK # is the mask for our client net. If the client is # just the host, this will be 255.255.255.255. # # PLUTO_MY_SOURCEIP # if non-empty, then the source address for the route will be # set to this IP address. # # PLUTO_MY_PROTOCOL # is the protocol for this connection. Useful for # firewalling. # # PLUTO_MY_PORT # is the port. Useful for firewalling. # # PLUTO_PEER # is the IP address of our peer. # # PLUTO_PEER_CLIENT # is the IP address / count of the peer's client subnet. # If the client is just the peer, this will be # the peer's own IP address / mask (where max is 32 # for IPv4 and 128 for IPv6). # # PLUTO_PEER_CLIENT_NET # is the IP address of the peer's client net. If the # client is just the peer, this will be the peer's # own IP address. # # PLUTO_PEER_CLIENT_MASK # is the mask for the peer's client net. If the # client is just the peer, this will be # 255.255.255.255. # # PLUTO_PEER_PROTOCOL # is the protocol set for remote end with port # selector. # # PLUTO_PEER_PORT # is the peer's port. Useful for firewalling. # # PLUTO_CFG_CLIENT=0|1 # is MODECFG or IKEv2 Config client. # # PLUTO_CFG_SERVER=0|1 # is MODECFG or IKEv2 Config server. # # PLUTO_CONNECTION_TYPE # # PLUTO_CONN_ADDRFAMILY # is the family type, "ipv4" or "ipv6" # # PLUTO_PROTO_STACK # is the local IPsec kernel stack used, eg KLIPS, NETKEY, # MAST, NOSTACK # # PLUTO_IS_PEER_CISCO=0|1 # remote server type is cisco. Add support for cisco extensions # when used with xauth. # # PLUTO_NM_CONFIGURED=0|1 # is NetworkManager used for resolv.conf update # # PLUTO_SA_REQID # When using KAME or XFRM/NETKEY, the IPsec SA reqid base value. # ESP/AH out is base, ESP/AH in = base + 1 # IPCOMP is base + 2 plus for inbound + 1 # # PLUTO_SA_TYPE # The type of IPsec SA (ESP or AH) # # PLUTO_USERNAME # The username (XAUTH or GSSAPI) that was authenticated (if any) # for this SA # # PLUTO_VIRT_INTERFACE # is the name of the real interace used for encrypted, IKE traffic # # # XAUTH_FAILED # If xauthfail=soft this will be set to 1 if XAUTH authentication # failed. If xauthfail=hard, the updown scripts never run. # # CONNMARK # If mark= is set on the connection, this variable will be # set with the value. It can be used for iptables or VTI. # # VTI_IFAC=iface # Name of VTI interface to create # # VTI_ROUTING=yes|no # Whether or not to perform ip rule and ip route commands # covering the IPsec SA address ranges to route those packets # into the VTI_IFACE interface. This should be enabled unless # the IPsec SA covers 0.0.0.0/0 <-> 0.0.0.0/0 # # VTI_SHARED=yes|no # Whether or not more conns (or instances) share a VTI device. # If not shared, the VTI device is deleted when tunnel goes down. # # SPI_IN / SPI_OUT # The inbound and outbound SPI's of the connection. # rpm based systems if [ -f @FINALSYSCONFDIR@/sysconfig/pluto_updown ]; then . @FINALSYSCONFDIR@/sysconfig/pluto_updown # deb based systems elif [ -f @FINALSYSCONFDIR@/default/pluto_updown ]; then . @FINALSYSCONFDIR@/default/pluto_updown fi BACKUP_RESOLV_CONF=@IPSEC_RUNDIR@/libreswan-resolv-conf-backup ETC_RESOLV_CONF=@FINALSYSCONFDIR@/resolv.conf case "${PLUTO_CONN_ADDRFAMILY}" in ipv4) FAMILY=4 MAX_CIDR=32 SCOPE=50 # Use scope 50 to verify ip was added by addsource() ;; ipv6) FAMILY=6 MAX_CIDR=128 SCOPE=global ;; *) echo "unkown address family \"${PLUTO_CONN_ADDRFAMILY}\"" >&2 exit 1 ;; esac export FAMILY MAX_CIDR SCOPE # Ignore parameter custom if [ "${1}" = "custom" ]; then shift fi while [ $# -gt 0 ]; do case ${1} in --route) case ${2} in [Yy]*) ROUTE=yes PROXY_ARP_ROUTE=no ;; *) ROUTE= PROXY_ARP_ROUTE= ;; esac shift; shift ;; --iproute) IPRARGS="${2}" shift; shift ;; *) echo "$0: Unknown argument \"${1}\"" >&2 exit 1 ;; esac done # utility functions for route manipulation # Meddling with this stuff should not be necessary and requires great care. uproute() { doproxyarp add doroute replace } downroute() { doroute del doproxyarp delete } downrule() { if [ -n "${PLUTO_MY_SOURCEIP}" -a 0${PLUTO_IS_PEER_CISCO} -eq 1 ]; then doroute del fi } updateresolvconf() { local domain local nameserver local new_nameserver local new_resolv_conf local new_search local orig_domain local orig_nameserver local rc rc=0 if [ 0${PLUTO_CFG_CLIENT} -eq 0 ]; then return ${rc} fi if [ -n "$(pidof unbound)" -a \ -n "${PLUTO_PEER_DNS_INFO}" -a \ -n "${PLUTO_PEER_DOMAIN_INFO}" ] then for domain in ${PLUTO_PEER_DOMAIN_INFO}; do echo "updating local nameserver for ${domain} with ${PLUTO_PEER_DNS_INFO}" unbound-control forward_add ${domain} \ ${PLUTO_PEER_DNS_INFO} unbound-control flush_zone ${domain} unbound-control flush_requestlist done rc=$? elif [ 0${PLUTO_NM_CONFIGURED} -eq 0 -a \ -n "${PLUTO_PEER_DNS_INFO}" ] then echo "updating resolvconf" if [ ! -e "${ETC_RESOLV_CONF}" ]; then echo "resolv.conf does not exist, so doing nothing" return 0 fi if [ -e "${BACKUP_RESOLV_CONF}" ]; then if grep -q Libreswan "${ETC_RESOLV_CONF}"; then echo "Current resolv.conf is generated by Libreswan, and backup resolv.conf already exists, so doing nothing" return 0 else echo "backup resolv.conf exists, but current resolv.conf is not generated by Libreswan" fi fi rm -f -- "${BACKUP_RESOLV_CONF}" cp -- "${ETC_RESOLV_CONF}" "${BACKUP_RESOLV_CONF}" new_resolv_conf="# Generated by Libreswan (IPsec)" orig_domain="$(grep ^domain "${ETC_RESOLV_CONF}" 2>/dev/null | \ awk '{ print $2 }')" orig_search=$(grep ^search "${ETC_RESOLV_CONF}" 2>/dev/null | \ sed 's/^search[[:space:]]\+//;s/[[:space:]]*\#.*//') if [ -n "${orig_domain}" ]; then new_resolv_conf="${new_resolv_conf} domain ${orig_domain}" fi if [ -n "${orig_search}" ]; then new_search="${orig_search}" elif [ -n "${orig_domain}" ]; then new_search="${orig_domain}" fi if [ -n "${PLUTO_PEER_DOMAIN_INFO}" ]; then if [ -n "${new_search}" ]; then new_search=$(echo $(echo "${new_search} ${PLUTO_PEER_DOMAIN_INFO}" | tr [:space:] '\n' | awk '!a[$0]++')) else new_search="${PLUTO_PEER_DOMAIN_INFO}" fi fi if [ -n "${new_search}" ]; then new_resolv_conf="${new_resolv_conf} search ${new_search}" fi orig_nameserver=$(grep -m 1 ^nameserver "${ETC_RESOLV_CONF}" | \ sed 's/^nameserver[[:space:]]\+//;s/[[:space:]]*\#.*//') if [ -n "${orig_nameserver}" ]; then new_nameserver=$(echo $(echo "${PLUTO_PEER_DNS_INFO} ${orig_nameserver}" | tr [:space:] '\n' | awk '!a[$0]++')) else new_nameserver="${PLUTO_PEER_DNS_INFO}" fi for nameserver in ${new_nameserver}; do new_resolv_conf="${new_resolv_conf} nameserver ${nameserver}" done echo "${new_resolv_conf}" > "${ETC_RESOLV_CONF}" rc=$? fi return ${rc} } restoreresolvconf() { local domain local rc rc=0 if [ 0${PLUTO_CFG_CLIENT} -eq 0 ]; then return ${rc} fi if [ -n "$(pidof unbound)" -a \ -n "${PLUTO_PEER_DNS_INFO}" -a \ -n "${PLUTO_PEER_DOMAIN_INFO}" ] then for domain in ${PLUTO_PEER_DOMAIN_INFO}; do echo "flushing local nameserver of ${domain}" unbound-control forward_remove ${domain} unbound-control flush_zone ${domain} unbound-control flush_requestlist done rc=$? elif [ 0${PLUTO_NM_CONFIGURED} -eq 0 ]; then # We only restore if current resolv.conf is made by us. if grep -q Libreswan "${ETC_RESOLV_CONF}" 2>/dev/null; then # And if there is a backup... if [ -e "${BACKUP_RESOLV_CONF}" ]; then echo "restoring resolvconf" else return 0 fi cp -- "${BACKUP_RESOLV_CONF}" "${ETC_RESOLV_CONF}" fi rm -f -- "${BACKUP_RESOLV_CONF}" rc=0 fi return ${rc} } notifyNM() { # This will be called whenever a connection is established or # fails to establish (either phase 1, xauth phase, or phase 2) # or whenever an already established connection is being terminated. # This will send a singal to NetworkManager over dbus so that NM # can keep track of the coonnections. if [ 0${PLUTO_NM_CONFIGURED} -eq 1 ]; then echo "sending $1 signal to NetworkManager" libreswan_reason=$1 export libreswan_reason export PLUTO_PEER_DOMAIN_INFO export PLUTO_PEER_DNS_INFO export PLUTO_PEER_BANNER export PLUTO_MY_SOURCEIP export PLUTO_PEER [ -x /usr/libexec/nm-libreswan-service-helper ] && \ /usr/libexec/nm-libreswan-service-helper fi return 0 } addsource() { local interface local st interface=lo st=0 if [ -z "${PLUTO_MY_SOURCEIP}" ]; then return ${st} fi # check if given sourceip is local and add as alias if not if ! ip -${FAMILY} -o route get ${PLUTO_MY_SOURCEIP} | grep -q ^local; then if [ -n "${VTI_IFACE}" -a "${VTI_ROUTING}" = yes ]; then interface="${VTI_IFACE}" elif [ -n "${PLUTO_XFRMI_ROUTE}" ]; then interface=${PLUTO_VIRT_INTERFACE} fi it="ip addr add ${PLUTO_MY_SOURCEIP}/${MAX_CIDR} dev ${interface} scope ${SCOPE}" oops="$(eval ${it} 2>&1)" st=$? if [ -z "${oops}" -a ${st} -ne 0 ]; then oops="silent error, exit status ${st}" fi case "${oops}" in 'RTNETLINK answers: File exists'*) # should not happen, but ... ignore if the # address was already assigned on interface oops="" st=0 ;; esac if [ -n "${oops}" -o ${st} -ne 0 ]; then echo "$0: addsource \"${it}\" failed (${oops})" >&2 fi fi return ${st} } delsource() { local interface local oops local st interface=lo st=0 if [ -z "${PLUTO_MY_SOURCEIP}" ]; then return ${st} fi # Remove source ip if it's not used any more. if [ -z "$(ip -${FAMILY} -o route list src ${PLUTO_MY_SOURCEIP})" ]; then if [ -n "${VTI_IFACE}" -a "${VTI_ROUTING}" = yes ]; then interface="${VTI_IFACE}" elif [ -n "${PLUTO_XFRMI_ROUTE}" ]; then interface=${PLUTO_VIRT_INTERFACE} fi # If there is no ip we just return if ! ip -${FAMILY} -o addr list dev ${interface} scope ${SCOPE} | \ grep -q ${PLUTO_MY_SOURCEIP}/${MAX_CIDR} then return ${st} fi if [ -n "${PLUTO_MOBIKE_EVENT}" ] ; then return ${st} fi it="ip -${FAMILY} addr del ${PLUTO_MY_SOURCEIP}/${MAX_CIDR} dev ${interface}" oops="$(eval ${it} 2>&1)" st=$? if [ -z "${oops}" -a ${st} -ne 0 ]; then oops="silent error, exit status ${st}" fi case "${oops}" in 'RTNETLINK answers: File exists'*) # should not happen, but ... ignore if the # address was already assigned on interface oops="" st=0 ;; 'RTNETLINK answers: Cannot assign'*) # Address is not there to remove or is there with different # netmask and in that case we must not remove it so we ignore # the error. oops="" st=0 ;; esac if [ -n "${oops}" -o ${st} -ne 0 ]; then echo "$0: delsource \"${it}\" failed (${oops})" >&2 fi fi return ${st} } doproxyarp() { local cmd local iface cmd=${1} # Check if client has a single ip only client net if [ ${PLUTO_PEER_CLIENT#*/} = ${MAX_CIDR} ]; then # Skip OE special connections and direct host-host connections if [ "${PLUTO_PEER_CLIENT_NET}" = "0.0.0.0" -o \ "${PLUTO_PEER_CLIENT_NET}" = "::" -o \ "${PLUTO_PEER_CLIENT_NET}" = "${PLUTO_PEER}" -o \ "${PLUTO_MY_CLIENT_NET}" = "${PLUTO_ME}" ] then return 0 fi # check if client is routeable if ip -${FAMILY} -o route get ${PLUTO_PEER_CLIENT_NET} 2>/dev/null | \ grep -E -q -s -v " via |^local" then iface=$(ip -${FAMILY} -o route get ${PLUTO_PEER_CLIENT_NET} 2>/dev/null | \ awk '{print $3}') if [ -r /sys/class/net/${iface}/address ]; then macaddr=$(cat /sys/class/net/${iface}/address) fi # add/remove arp entry for the client on ethernet devices only if [ -n "${macaddr}" ]; then if [ "${cmd}" = "add" ]; then ip -${FAMILY} neigh add proxy ${PLUTO_PEER_CLIENT_NET} dev ${iface} \ lladdr ${macaddr} nud permanent # Force routing, required for proxyarp to work PROXY_ARP_ROUTE=yes export PROXY_ARP_ROUTE else ip -${FAMILY} neigh del proxy ${PLUTO_PEER_CLIENT_NET} dev ${iface} fi fi fi fi } do_ip() { local cmd="$1" oops="$(eval ${cmd} 2>&1)" st=$? if [ -z "${oops}" -a ${st} -ne 0 ]; then oops="silent error, exit status ${st}" fi case "${oops}" in 'RTNETLINK answers: No such process'*) # should not happen, but ... ignore if the # route was already removed oops="" st=0 ;; esac if [ -n "${oops}" -a ${st} -ne 0 ]; then echo "$0: doroute \"${cmd}\" failed (${oops})" >&2 fi return ${st} } doroute() { local cmd local esp_nexthop local esp_peer_interface local espipro local ipru local route_table local oops local parms local parms2 local st local xfrmi_route local xfrmi_rule cmd=${1} route_table=50 st=0 xfrmi_route="${PLUTO_XFRMI_ROUTE}" if [ ${cmd} != del ]; then oops="$(ip -${FAMILY} route get ${PLUTO_PEER_CLIENT_NET} 2>&1)" case "${oops}" in 'RTNETLINK answers: No route to host'*) if [ -z "${PLUTO_XFRMI_ROUTE}" ]; then ROUTE=yes # Routing is mandatory for IPsec fi ;; esac fi if [ -n "${PLUTO_XFRMI_FWMARK}" ]; then xfrmi_rule=yes # we have to add "ip rules" and "ip route table" ROUTE=no # xfrmi_route will add the route fi # skip routing if it's not enabled or necessary if [ -z "${PLUTO_MY_SOURCEIP}" -a \ -z "${PLUTO_MTU}" -a \ "${PROXY_ARP_ROUTE}" != yes -a \ "${cmd}" != "del" ] then PROXY_ARP_ROUTE=no fi if [ -n "${PLUTO_MY_SOURCEIP}" -o -n "${PLUTO_MTU}" ]; then ROUTE=yes fi if [ "${PLUTO_PEER_CLIENT}" = "${PLUTO_MY_CLIENT}" -a \ "${PLUTO_XFRMI_ROUTE}" = yes ] then xfrmi_route="samesubnets"; echo "leftsubet == rightsubnet = ${PLUTO_PEER_CLIENT} can not add route" fi parms="${PLUTO_PEER_CLIENT}" parms2=${IPRARGS} # nexthop is not needed on ppp interfaces. unset it to make cases # work, where left is set but no leftnexthop (e.g. left=%defaultroute) if ip link show "${PLUTO_INTERFACE%:*}" | grep -q POINTOPOINT; then POINTPOINT=yes fi # use nexthop if nexthop is not %direct and POINTPOINT is not set if [ "${PLUTO_NEXT_HOP}" != "${PLUTO_PEER}" -a -z "${POINTPOINT}" ]; then # XFRM interface needs no nexthop if [ -z "${PLUTO_XFRMI_ROUTE}" ]; then parms2="via ${PLUTO_NEXT_HOP}" fi esp_nexthop="via ${PLUTO_NEXT_HOP} " fi # route via proper interface according to routing table if [ "${cmd}" = "del" ]; then case "${PLUTO_PEER_CLIENT}" in "0.0.0.0/0") # in case of default route we use half routes peer_interface=$(ip -${FAMILY} -o route list exact 0.0.0.0/1 | \ sed "s/^.*dev \([^ ]*\) .*/\1/") ;; "::/0") # in case of default route we use half routes peer_interface=$(ip -${FAMILY} -o route list exact 2000::/3 | \ sed "s/^.*dev \([^ ]*\) .*/\1/") ;; *) peer_interface=$(ip -${FAMILY} -o route get ${PLUTO_PEER_CLIENT_NET} | \ sed "s/^.*dev \([^ ]*\) .*/\1/") ;; esac else peer_interface=$(ip -o route get ${PLUTO_NEXT_HOP} | \ sed "s/^.*dev \([^ ]*\) .*/\1/") fi esp_peer_interface=$(ip -${FAMILY} -o route get ${PLUTO_NEXT_HOP} \ from ${PLUTO_ME} | sed "s/^.*\(dev [^ ]*\) .*/\1/") if [ -z "${esp_peer_interface}" ]; then esp_peer_interface="dev ${PLUTO_INTERFACE}" fi if [ -z "${peer_interface}" ]; then peer_interface=${PLUTO_INTERFACE} fi if [ "${PLUTO_XFRMI_ROUTE}" = "yes" ]; then peer_interface=${PLUTO_VIRT_INTERFACE} fi if [ -n "${VTI_IFACE}" ]; then addsource peer_interface="${VTI_IFACE}" fi parms2="${parms2}${PLUTO_MTU:+ mtu ${PLUTO_MTU}}" parms2="${parms2}${PLUTO_METRIC:+ metric ${PLUTO_METRIC}} ${IPROUTEARGS}" parms2="${parms2} dev ${peer_interface%:*}" # make sure whe have sourceip locally in this machine if [ "${cmd}" = "replace" -a -n "${PLUTO_MY_SOURCEIP}" ]; then addsource # use sourceip as route default source parms2="${parms2} src ${PLUTO_MY_SOURCEIP}" fi case "${PLUTO_PEER_CLIENT}" in "0.0.0.0/0") # need to provide route that eclipses default, without # replacing it. it="ip -${FAMILY} route ${cmd} 0.0.0.0/1 ${parms2} && \ ip -${FAMILY} route ${cmd} 128.0.0.0/1 ${parms2}" ;; "::/0") # need to provide route that eclipses default, without # replacing it. it="ip -${FAMILY} route ${cmd} 2000::/3 ${parms2}" ;; *) it="ip -${FAMILY} route ${cmd} ${parms} ${parms2}" ;; esac if [ "${ROUTE}" = yes -o \ "${xfrmi_route}" = yes -o \ "${PROXY_ARP_ROUTE}" = yes ] then do_ip "${it}" st=$? if [ ${st} -ne 0 ]; then return ${st} fi fi if [ "${xfrmi_rule}" = "yes" ]; then espipro="ip -${FAMILY} route ${cmd} ${PLUTO_PEER}/${MAX_CIDR} ${esp_nexthop} ${esp_peer_interface%:*} table ${route_table}" do_ip "${espipro}" st=$? if [ ${st} -ne 0 ]; then return ${st} fi iprulecmd="${cmd}" if [ "${cmd}" = "replace" ]; then iprulecmd="add" fi ipru="ip -${FAMILY} rule ${iprulecmd} prio 100 to ${parms}" ipru="${ipru} fwmark ${PLUTO_XFRMI_FWMARK} lookup ${route_table}" do_ip "${ipru}" st=$? if [ ${st} -ne 0 ]; then return ${st} fi fi return 0 } # TODO: We need to specify CIDR mask but our _MASK variables are in old school format # TODO: Exclude udp 4500 traffic addnflog() { if [ -n "${NFLOG}" ]; then iptables -I OUTPUT -m policy --dir out --pol ipsec \ -s ${PLUTO_MY_CLIENT} -d ${PLUTO_PEER_CLIENT} \ -j NFLOG --nflog-group ${NFLOG} --nflog-prefix ${PLUTO_CONNECTION} iptables -I INPUT -m policy --dir in --pol ipsec \ -s ${PLUTO_PEER_CLIENT} -d ${PLUTO_MY_CLIENT} \ -j NFLOG --nflog-group ${NFLOG} --nflog-prefix ${PLUTO_CONNECTION} fi } delnflog() { if [ -n "${NFLOG}" ]; then iptables -D OUTPUT -m policy --dir out --pol ipsec \ -s ${PLUTO_MY_CLIENT} -d ${PLUTO_PEER_CLIENT} \ -j NFLOG --nflog-group ${NFLOG} --nflog-prefix ${PLUTO_CONNECTION} iptables -D INPUT -m policy --dir in --pol ipsec \ -s ${PLUTO_PEER_CLIENT} -d ${PLUTO_MY_CLIENT} \ -j NFLOG --nflog-group ${NFLOG} --nflog-prefix ${PLUTO_CONNECTION} fi } addvtiiface() { if [ -n "${VTI_IFACE}" ]; then if [ -z "${CONNMARK_IN}" -o -z "${CONNMARK_OUT}" ]; then echo "vti-interface option ignored because no mark was configured" else if [ ! -d "/proc/sys/net/ipv4/conf/${VTI_IFACE}" ]; then # echo "creating vti interface" vtipeer="${PLUTO_PEER}" if [ "${PLUTO_CONN_KIND}" = CK_INSTANCE -o "${VTI_SHARED}" = "yes" ]; then vtipeer="0.0.0.0" fi ip tunnel add ${VTI_IFACE} mode vti local ${PLUTO_ME} \ remote ${vtipeer} okey ${CONNMARK_OUT%/*} \ ikey ${CONNMARK_IN%/*} sysctl -w net.ipv4.conf.${VTI_IFACE}.disable_policy=1 sysctl -w net.ipv4.conf.${VTI_IFACE}.rp_filter=0 sysctl -w net.ipv4.conf.${VTI_IFACE}.forwarding=1 if [ -n "${VTI_IP}" ]; then ip addr add ${VTI_IP} dev ${VTI_IFACE} fi ip link set ${VTI_IFACE} up else # check there was no conflict if we are sharing - might be sensitive to /sbin/ip differences if [ "${VTI_SHARED}" = yes ]; then #test: ip/ip remote 3.4.5.6 local 1.2.3.4 ttl inherit key 5 cur="$(ip tun show ${VTI_IFACE})" new="${VTI_IFACE}: ip/ip remote any local ${PLUTO_ME} ttl inherit key ${CONNMARK_OUT%/*}" if [ "${cur}" != "${new}" ]; then echo "vti interface \"${VTI_IFACE}\" already exists with conflicting setting" echo "existing: ${cur}" echo "wanted : ${new}" else # temp debug echo "vti interface already exists with identical parameters, OK" fi else echo "vti interface \"${VTI_IFACE}\" already exists with conflicting setting (perhaps need vti-sharing=yes ?" fi fi fi fi } addvti() { if [ -n "${VTI_IFACE}" ]; then if [ -z "${CONNMARK_IN}" -o -z "${CONNMARK_OUT}" ]; then echo "vti-interface option ignored because no mark was configured" else if [ "${VTI_ROUTING}" = yes ]; then # Tuomo should improve this with using ${PLUTO_MY_CLIENT_NET} # echo "setting up vti routing" r=add ip route list | grep -q "${PLUTO_PEER_CLIENT%/*}" && r=change if [ "${r}" = change ]; then # resolve LAN conflict by forcing host route for default gw gw="$(ip ro li | grep ^default | awk '{ print $3;}')" gwdev="$(ip ro li | grep ^default | awk '{ print $5;}')" # echo "ip route add ${gw} dev ${gwdev}" ip route add ${gw} dev ${gwdev} >/dev/null ||: fi srcip="" if [ -n "${PLUTO_MY_SOURCEIP}" ]; then srcip=" src ${PLUTO_MY_SOURCEIP}" fi # echo "ip route ${r} ${PLUTO_PEER_CLIENT} dev ${VTI_IFACE} ${srcip}" ip route ${r} ${PLUTO_PEER_CLIENT} dev ${VTI_IFACE} ${srcip} echo "done ip route" fi fi fi } delvti() { if [ -n "${VTI_IFACE}" -a -d /proc/sys/net/ipv4/conf/${VTI_IFACE} ]; then if [ "${VTI_ROUTING}" = yes ]; then ip route del ${PLUTO_PEER_CLIENT} dev ${VTI_IFACE} \ src ${PLUTO_MY_SOURCEIP} ||: fi # TODO: we can't delete vti interface because we don't have proper reference # counting. #if [ "${VTI_SHARED}" = no -a "${PLUTO_CONN_KIND}" != CK_INSTANCE ]; then # ip tun del ${VTI_IFACE} ||: #fi fi } # Client Address Translation CAT addcat() { if [ -n "${CAT}" ] && [ "${PLUTO_MY_CLIENT_NET}" != "0.0.0.0" ] ; then iptables -t nat -I POSTROUTING -m policy --dir out --pol ipsec \ -d ${PLUTO_PEER_CLIENT} -j SNAT --to-source ${PLUTO_MY_CLIENT_NET} iptables -t nat -I PREROUTING -m policy --dir in --pol ipsec \ -d ${PLUTO_MY_CLIENT_NET} -s ${PLUTO_PEER_CLIENT} \ -j DNAT --to-destination ${PLUTO_ME} fi } delcat() { if [ -n "${CAT}" ]; then iptables -t nat -D PREROUTING -m policy --dir in --pol ipsec \ -d ${PLUTO_MY_CLIENT_NET} -s ${PLUTO_PEER_CLIENT} \ -j DNAT --to-destination ${PLUTO_ME} iptables -t nat -D POSTROUTING -m policy --dir out --pol ipsec \ -d ${PLUTO_PEER_CLIENT} -j SNAT --to-source ${PLUTO_MY_CLIENT_NET} fi } # the big choice case "${PLUTO_VERB}" in prepare-host|prepare-client) addvtiiface ;; route-host|route-client) # connection to me or my client subnet being routed addvti uproute addnflog ;; unroute-host|unroute-client) # connection to me or my client subnet being unrouted downroute delsource ;; up-host) # connection to me coming up # If you are doing a custom version, firewall commands go here. ;; down-host) # connection to me going down downrule delnflog delcat delvti # If you are doing a custom version, firewall commands go here. ;; up-client) # connection to my client subnet coming up addvtiiface updateresolvconf addcat addsource notifyNM connect addvti # If you are doing a custom version, firewall commands go here. ;; down-client) # connection to my client subnet going down downrule delnflog delcat delvti restoreresolvconf notifyNM disconnect # If you are doing a custom version, firewall commands go here. ;; # # IPv6 # prepare-host-v6|prepare-client-v6) # prepare client for connection ;; route-host-v6|route-client-v6) # connection to me or my client subnet being routed uproute ;; unroute-host-v6|unroute-client-v6) # connection to me or my client subnet being unrouted downroute delsource ;; up-host-v6) # connection to me coming up # If you are doing a custom version, firewall commands go here. ;; down-host-v6) # connection to me going down # If you are doing a custom version, firewall commands go here. ;; up-client-v6) # connection to my client subnet coming up addsource updateresolvconf notifyNM connect # If you are doing a custom version, firewall commands go here. ;; down-client-v6) # connection to my client subnet going down restoreresolvconf notifyNM disconnect # If you are doing a custom version, firewall commands go here. ;; *) echo "$0: unknown verb \"${PLUTO_VERB}\" or parameter \"${1}\"" >&2 exit 1 ;; esac libreswan-3.32/programs/_updown/000077500000000000000000000000001365625662500167545ustar00rootroot00000000000000libreswan-3.32/programs/_updown/Makefile000066400000000000000000000014021365625662500204110ustar00rootroot00000000000000# Makefile for miscellaneous programs # Copyright (C) 2002 Michael Richardson # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. PROGRAM=_updown ifdef top_srcdir include $(top_srcdir)/mk/program.mk else include ../../mk/program.mk endif programs: ${PROGRAM} libreswan-3.32/programs/_updown/_updown.8.xml000066400000000000000000000151151365625662500213220ustar00rootroot00000000000000 PaulWoutersplaceholder to suppress warning _UPDOWN 8 28 Oct 2006 libreswan Executable programs ipsec _updown kernel and routing manipulation script _updown is invoked by pluto when it has brought up a new connection. This script is used to insert the appropriate routing entries for IPsec operation on some kernel IPsec stacks, such as KLIPS and MAST, and may do other necessary work that is kernel or user specific, such as defining custom firewall rules. The interface to the script is documented in the pluto man page. VARIABLES The _updown is passed along a number of variables which can be used to act differently based on the information: PLUTO_VERSION indicates what version of this interface is being used. This document describes version 1.1. This is upwardly compatible with version 1.0. PLUTO_VERB specifies the name of the operation to be performed, which can be one of , , , , or . If the address family for security gateway to security gateway communications is IPv6, then a suffix of -v6 is added to this verb. PLUTO_CONNECTION is the name of the connection for which we are routing. PLUTO_NEXT_HOP is the next hop to which packets bound for the peer must be sent. PLUTO_INTERFACE is the name of the ipsec interface to be used. PLUTO_ME is the IP address of our host. PLUTO_MY_CLIENT is the IP address / count of our client subnet. If the client is just the host, this will be the host's own IP address / max (where max is 32 for IPv4 and 128 for IPv6). PLUTO_MY_CLIENT_NET is the IP address of our client net. If the client is just the host, this will be the host's own IP address. PLUTO_MY_CLIENT_MASK is the mask for our client net. If the client is just the host, this will be 255.255.255.255. PLUTO_PEER is the IP address of our peer. PLUTO_PEER_CLIENT is the IP address / count of the peer's client subnet. If the client is just the peer, this will be the peer's own IP address / max (where max is 32 for IPv4 and 128 for IPv6). PLUTO_PEER_CLIENT_NET is the IP address of the peer's client net. If the client is just the peer, this will be the peer's own IP address. PLUTO_PEER_CLIENT_MASK is the mask for the peer's client net. If the client is just the peer, this will be 255.255.255.255. PLUTO_MY_PROTOCOL lists the protocols allowed over this IPsec SA. PLUTO_PEER_PROTOCOL lists the protocols the peer allows over this IPsec SA. PLUTO_MY_PORT lists the ports allowed over this IPsec SA. PLUTO_PEER_PORT lists the ports the peer allows over this IPsec SA. PLUTO_MY_ID lists our id. PLUTO_PEER_ID lists our peer's id. PLUTO_PEER_CA lists the peer's CA. SEE ALSO ipsec8, ipsec_pluto8. HISTORY Man page written for the Linux FreeS/WAN project <https://www.freeswan.org/> by Michael Richardson. Original program written by Henry Spencer. libreswan-3.32/programs/_updown/_updown.in000066400000000000000000000103461365625662500207630ustar00rootroot00000000000000#! /bin/sh # iproute2 version, default updown script # # Copyright (C) 2003-2004 Nigel Metheringham # Copyright (C) 2002-2007 Michael Richardson # Copyright (C) 2003-2013 Tuomo Soini # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # # CAUTION: Installing a new version of Libreswan will install a new # copy of this script, wiping out any custom changes you make. If # you need changes, make a copy of this under another name, and customize # that, and use the (left/right)updown parameters in ipsec.conf to make # Libreswan use yours instead of this default one. test $IPSEC_INIT_SCRIPT_DEBUG && set -v -x LC_ALL=C export LC_ALL # things that this script gets (from ipsec_pluto(8) man page) # # # PLUTO_VERSION # indicates what version of this interface is being # used. This document describes version 1.1. This # is upwardly compatible with version 1.0. # # PLUTO_VERB # specifies the name of the operation to be performed # (prepare-host, prepare-client, up-host, up-client, # down-host, or down-client). If the address family # for security gateway to security gateway communications # is IPv6, then a suffix of -v6 is added to the # verb. # # PLUTO_CONNECTION # is the name of the connection for which we are # routing. # # PLUTO_CONN_POLICY # the policy of the connection, as in: # RSASIG+ENCRYPT+TUNNEL+PFS+DONTREKEY+OPPORTUNISTIC+failureDROP+lKOD+rKOD # # PLUTO_NEXT_HOP # is the next hop to which packets bound for the peer # must be sent. # # PLUTO_INTERFACE # is the name of the ipsec interface to be used. # # PLUTO_ME # is the IP address of our host. # # PLUTO_MY_CLIENT # is the IP address / count of our client subnet. If # the client is just the host, this will be the # host's own IP address / mask (where max is 32 for # IPv4 and 128 for IPv6). # # PLUTO_MY_CLIENT_NET # is the IP address of our client net. If the client # is just the host, this will be the host's own IP # address. # # PLUTO_MY_CLIENT_MASK # is the mask for our client net. If the client is # just the host, this will be 255.255.255.255. # # PLUTO_MY_SOURCEIP # if non-empty, then the source address for the route will be # set to this IP address. # # PLUTO_MY_PROTOCOL # is the protocol for this connection. Useful for # firewalling. # # PLUTO_MY_PORT # is the port. Useful for firewalling. # # PLUTO_PEER # is the IP address of our peer. # # PLUTO_PEER_CLIENT # is the IP address / count of the peer's client subnet. # If the client is just the peer, this will be # the peer's own IP address / mask (where max is 32 # for IPv4 and 128 for IPv6). # # PLUTO_PEER_CLIENT_NET # is the IP address of the peer's client net. If the # client is just the peer, this will be the peer's # own IP address. # # PLUTO_PEER_CLIENT_MASK # is the mask for the peer's client net. If the # client is just the peer, this will be # 255.255.255.255. # # PLUTO_PEER_PROTOCOL # is the protocol set for remote end with port # selector. # # PLUTO_PEER_PORT # is the peer's port. Useful for firewalling. # # PLUTO_CONNECTION_TYPE # # PLUTO_MY_REF/PLUTO_PEER_REF # KLIPSng(mast) references to the SA to be used in each # direction. # # PLUTO_STACK # The kernel level IPstack used (see protostack=) # # PLUTO_SA_REQID # When using KAME or XFRM/NETKEY, the IPsec SA reqid value case $PLUTO_VERSION in 1.*) # Older Pluto?!? Play it safe, script may be using new features. echo "$0: obsolete interface version \"$PLUTO_VERSION\"," >&2 echo "$0: called by obsolete Pluto?" >&2 exit 2 ;; 2.*) ;; esac if [ -x @IPSEC_EXECDIR@/_updown.${PLUTO_STACK} ]; then exec @IPSEC_EXECDIR@/_updown.${PLUTO_STACK} "$@" else echo "FATAL: Could not execute @IPSEC_EXECDIR@/_updown.${PLUTO_STACK} $*" fi exit 3 libreswan-3.32/programs/addconn/000077500000000000000000000000001365625662500167075ustar00rootroot00000000000000libreswan-3.32/programs/addconn/Makefile000066400000000000000000000016701365625662500203530ustar00rootroot00000000000000# ipsec starter Makefile # # Copyright (C) 2001 Mathieu Lafon - Arkoon Network Security # Copyright (C) 2017 Andrew Cagney # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. PROGRAM=addconn OBJS += $(PROGRAM).o OBJS += $(IPSECCONFLIB) OBJS += $(WHACKLIB) OBJS += $(LIBRESWANLIB) OBJS += $(LSWTOOLLIBS) LDFLAGS += $(UNBOUND_LDFLAGS) $(SECCOMP_LDFLAGS) ifdef top_srcdir include $(top_srcdir)/mk/program.mk else include ../../mk/program.mk endif libreswan-3.32/programs/addconn/addconn.8.xml000066400000000000000000000147201365625662500212110ustar00rootroot00000000000000 PaulWoutersplaceholder to suppress warning IPSEC_ADDCONN 8 15 Jun 2010 libreswan Executable programs ipsec addconn load a given policy into the pluto IKE daemon ipsec addconn --configsetup --rootdir dir --config filename --ctlbase socketfile --verbose --noexport --warningsfatal ipsec addconn --liststack --rootdir dir --config filename --ctlbase socketfile --verbose --noexport --warningsfatal ipsec addconn --checkconfig --rootdir dir --config filename --ctlbase socketfile --verbose --warningsfatal ipsec addconn --autoall --rootdir dir --config filename --ctlbase socketfile --verbose --warningsfatal ipsec addconn --rootdir dir --config filename --ctlbase socketfile --verbose --warningsfatal name1 name2 .. ipsec addconn --listall --liststart --listroute --listadd --listignore --rootdir dir --config filename --ctlbase socketfile --verbose --warningsfatal ipsec addconn --help DESCRIPTION ipsec addconn takes a config file (or stdin) containing the format of ipsec.conf, or the format of individual "conn" sections, and uses that information to load named or all connections defined in that configuration file into the running libreswan pluto IKE daemon. If no configuration file is specified, the default configuration file is used. If no pluto socket is specified, the default socket location will be used. When --addall is used, all connections defined in the config file will be operated on. Otherwise, only the specified connection names will be affected. When addcon is run, connections that have the auto= option set to add, start or route will be loaded, routed or initiated. If a connection was loaded or initiated already, it will be replaced. When --configsetup is specified, the configuration file is parsed for the config setup section and printed to the terminal usable as a shell script. These are prefaced with export unless --noexport is specified. When --checkconfig is specified, the configuration file is parsed and all sections are checked for correct syntax. If an error is found, information about it is printed to the terminal. When --listroute or --liststart is specified, no connections are added or replaced, only shown. This command can be used to verify which connections the addcon command would act upon, without actually performing any action. HISTORY Man page written for the Libreswan project <https://libreswan.org/> by Paul Wouters libreswan-3.32/programs/addconn/addconn.c000066400000000000000000000417461365625662500204750ustar00rootroot00000000000000/* * A program to read the configuration file and load a single conn * Copyright (C) 2005 Michael Richardson * Copyright (C) 2012-2014 Paul Wouters * Copyright (C) 2014 D. Hugh Redelmeier * Copyright (C) 2012-2013 Kim B. Heino * Copyright (C) 2019 Andrew Cagney * Copyright (C) 2019 Paul Wouters * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include #include #include #include #include "lswlog.h" #include "lswcdefs.h" /* for UNUSED */ #include "lswalloc.h" #include "lswtool.h" #include "whack.h" #include "ipsecconf/parser-controls.h" #include "ipsecconf/starterlog.h" #include "ipsecconf/confread.h" #include "ipsecconf/confwrite.h" #include "ipsecconf/starterwhack.h" #ifdef NETKEY_SUPPORT #include "addr_lookup.h" #endif #ifdef USE_DNSSEC # include "dnssec.h" #endif #ifdef HAVE_SECCOMP #define LSW_SECCOMP_EXIT_FAIL 8 #include "lswseccomp.h" #endif static int verbose = 0; /* * make options valid environment variables */ static char *environlize(const char *str) { char *cpy = strndup(str, strlen(str)); char *cur = cpy; while((cur = strchr(cur, '-')) != NULL) { *cur++ = '_'; } return cpy; } /* * See if conn's left or right is %defaultroute and resolve it. * * XXX: why not let pluto resolve all this like it is already doing? * because of MOBIKE. */ static void resolve_defaultroute(struct starter_conn *conn UNUSED) { #ifdef NETKEY_SUPPORT if (resolve_defaultroute_one(&conn->left, &conn->right, verbose != 0) == 1) resolve_defaultroute_one(&conn->left, &conn->right, verbose != 0); if (resolve_defaultroute_one(&conn->right, &conn->left, verbose != 0) == 1) resolve_defaultroute_one(&conn->right, &conn->left, verbose != 0); #else /* !defined(NETKEY_SUPPORT) */ fprintf(stderr, "addcon: without XFRM/NETKEY, cannot resolve_defaultroute()\n"); exit(7); /* random code */ #endif } #ifdef HAVE_SECCOMP static void init_seccomp_addconn(uint32_t def_action) { scmp_filter_ctx ctx = seccomp_init(def_action); if (ctx == NULL) { fprintf(stderr, "seccomp_init_addconn() failed!"); exit(LSW_SECCOMP_EXIT_FAIL); } /* * Because on bootup, addconn is started by pluto, any syscall * here MUST also appear in the syscall list for "main" inside * pluto */ LSW_SECCOMP_ADD(ctx, access); LSW_SECCOMP_ADD(ctx, arch_prctl); LSW_SECCOMP_ADD(ctx, brk); LSW_SECCOMP_ADD(ctx, bind); LSW_SECCOMP_ADD(ctx, clone); LSW_SECCOMP_ADD(ctx, clock_gettime); LSW_SECCOMP_ADD(ctx, close); LSW_SECCOMP_ADD(ctx, connect); LSW_SECCOMP_ADD(ctx, epoll_create); LSW_SECCOMP_ADD(ctx, epoll_ctl); LSW_SECCOMP_ADD(ctx, epoll_wait); LSW_SECCOMP_ADD(ctx, epoll_pwait); LSW_SECCOMP_ADD(ctx, exit_group); LSW_SECCOMP_ADD(ctx, fcntl); LSW_SECCOMP_ADD(ctx, fstat); LSW_SECCOMP_ADD(ctx, futex); LSW_SECCOMP_ADD(ctx, getdents); LSW_SECCOMP_ADD(ctx, getegid); LSW_SECCOMP_ADD(ctx, getpid); LSW_SECCOMP_ADD(ctx, getrlimit); LSW_SECCOMP_ADD(ctx, geteuid); LSW_SECCOMP_ADD(ctx, getgid); LSW_SECCOMP_ADD(ctx, getrandom); LSW_SECCOMP_ADD(ctx, getuid); LSW_SECCOMP_ADD(ctx, ioctl); LSW_SECCOMP_ADD(ctx, mmap); LSW_SECCOMP_ADD(ctx, lseek); LSW_SECCOMP_ADD(ctx, munmap); LSW_SECCOMP_ADD(ctx, mprotect); LSW_SECCOMP_ADD(ctx, open); LSW_SECCOMP_ADD(ctx, openat); LSW_SECCOMP_ADD(ctx, poll); LSW_SECCOMP_ADD(ctx, prctl); LSW_SECCOMP_ADD(ctx, read); LSW_SECCOMP_ADD(ctx, readlink); LSW_SECCOMP_ADD(ctx, recvfrom); LSW_SECCOMP_ADD(ctx, rt_sigaction); LSW_SECCOMP_ADD(ctx, rt_sigprocmask); LSW_SECCOMP_ADD(ctx, sendto); LSW_SECCOMP_ADD(ctx, setsockopt); LSW_SECCOMP_ADD(ctx, set_robust_list); LSW_SECCOMP_ADD(ctx, set_tid_address); LSW_SECCOMP_ADD(ctx, sigreturn); LSW_SECCOMP_ADD(ctx, socket); LSW_SECCOMP_ADD(ctx, socketcall); LSW_SECCOMP_ADD(ctx, socketpair); LSW_SECCOMP_ADD(ctx, stat); LSW_SECCOMP_ADD(ctx, statfs); LSW_SECCOMP_ADD(ctx, uname); LSW_SECCOMP_ADD(ctx, waitpid); LSW_SECCOMP_ADD(ctx, write); #ifdef USE_EFENCE LSW_SECCOMP_ADD(ctx, madvise); #endif int rc = seccomp_load(ctx); if (rc < 0) { fprintf(stderr, "seccomp_load() failed!"); seccomp_release(ctx); exit(LSW_SECCOMP_EXIT_FAIL); } } #endif static const char *usage_string = "" "Usage: addconn [--config file] [--ctlsocket socketfile]\n" " [--varprefix prefix] [--noexport]\n" " [--verbose]\n" " [--configsetup]\n" " [--liststack]\n" " [--checkconfig]\n" " [--autoall]\n" " [--listall] [--listadd] [--listroute] [--liststart]\n" " [--listignore]\n" " names\n"; static void usage(void) { /* print usage */ fputs(usage_string, stderr); exit(10); } static const struct option longopts[] = { { "config", required_argument, NULL, 'C' }, { "debug", no_argument, NULL, 'D' }, { "verbose", no_argument, NULL, 'D' }, { "addall", no_argument, NULL, 'a' }, /* alias, backwards compat */ { "autoall", no_argument, NULL, 'a' }, { "listall", no_argument, NULL, 'A' }, { "listadd", no_argument, NULL, 'L' }, { "listroute", no_argument, NULL, 'r' }, { "liststart", no_argument, NULL, 's' }, { "listignore", no_argument, NULL, 'i' }, { "varprefix", required_argument, NULL, 'P' }, { "ctlsocket", required_argument, NULL, 'c' }, { "ctlbase", required_argument, NULL, 'c' }, /* backwards compatibility */ { "configsetup", no_argument, NULL, 'T' }, { "liststack", no_argument, NULL, 'S' }, { "checkconfig", no_argument, NULL, 'K' }, { "noexport", no_argument, NULL, 'N' }, { "help", no_argument, NULL, 'h' }, /* obsoleted, eat and ignore for compatibility */ {"defaultroute", required_argument, NULL, 'd'}, {"defaultroutenexthop", required_argument, NULL, 'n'}, { 0, 0, 0, 0 } }; int main(int argc, char *argv[]) { tool_init_log(argv[0]); int opt; bool autoall = FALSE; bool configsetup = FALSE; bool checkconfig = FALSE; const char *export = "export"; /* display export before the foo=bar or not */ bool dolist = FALSE, listadd = FALSE, listroute = FALSE, liststart = FALSE, listignore = FALSE, listall = FALSE, liststack = FALSE; char *configfile = NULL; const char *varprefix = ""; int exit_status = 0; struct starter_conn *conn = NULL; const char *ctlsocket = NULL; #if 0 /* efence settings */ extern int EF_PROTECT_BELOW; extern int EF_PROTECT_FREE; EF_PROTECT_BELOW = 1; EF_PROTECT_FREE = 1; #endif while ((opt = getopt_long(argc, argv, "", longopts, 0)) != EOF) { switch (opt) { case 'h': /* usage: */ usage(); break; case 'a': autoall = TRUE; break; case 'D': verbose++; lex_verbosity++; break; case 'T': configsetup = TRUE; break; case 'K': checkconfig = TRUE; break; case 'N': export = ""; break; case 'C': configfile = clone_str(optarg, "config file name"); break; case 'c': ctlsocket = clone_str(optarg, "control socket"); break; case 'L': listadd = TRUE; dolist = TRUE; break; case 'r': listroute = TRUE; dolist = TRUE; break; case 's': liststart = TRUE; dolist = TRUE; break; case 'S': liststack = TRUE; dolist = TRUE; break; case 'i': listignore = TRUE; dolist = TRUE; break; case 'A': listall = TRUE; dolist = TRUE; break; case 'P': varprefix = optarg; break; case 'd': case 'n': fprintf(stderr, "Warning: options --defaultroute and --defaultroutenexthop are obsolete and were ignored\n"); break; default: usage(); } } if (autoall) { /* pluto forks us, we might have to wait on it to create the socket */ struct stat sb; int ws = 5; /* somewhat arbitrary */ while (ws > 0) { int ret = stat(ctlsocket == NULL ? DEFAULT_CTL_SOCKET : ctlsocket, &sb); if (ret == -1) { sleep(1); } else { break; } ws--; } if (ws == 0) { fprintf(stderr, "ipsec addconn: timeout waiting on pluto socket %s - aborted\n", ctlsocket); exit(3); } } /* if nothing to add, then complain */ if (optind == argc && !autoall && !dolist && !configsetup && !checkconfig) usage(); if (verbose > 3) { yydebug = 1; } char *confdir = IPSEC_CONFDIR; if (configfile == NULL) { /* ??? see code clone in programs/readwriteconf/readwriteconf.c */ configfile = alloc_bytes(strlen(confdir) + sizeof("/ipsec.conf"), "conf file"); /* calculate default value for configfile */ strcpy(configfile, confdir); /* safe: see allocation above */ if (configfile[0] != '\0' && configfile[strlen(configfile) - 1] != '/') strcat(configfile, "/"); /* safe: see allocation above */ strcat(configfile, "ipsec.conf"); /* safe: see allocation above */ } if (verbose > 0) printf("opening file: %s\n", configfile); starter_use_log(verbose != 0, TRUE, verbose == 0); struct starter_config *cfg = NULL; { starter_errors_t errl = { NULL }; cfg = confread_load(configfile, &errl, ctlsocket, configsetup); if (cfg == NULL) { fprintf(stderr, "cannot load config '%s': %s\n", configfile, errl.errors); pfreeany(errl.errors); exit(3); } if (errl.errors != NULL) { fprintf(stderr, "addconn, in config '%s', ignoring: %s\n", configfile, errl.errors); pfree(errl.errors); } if (checkconfig) { confread_free(cfg); exit(0); } } #ifdef HAVE_SECCOMP switch (cfg->setup.options[KBF_SECCOMP]) { case SECCOMP_ENABLED: init_seccomp_addconn(SCMP_ACT_KILL); break; case SECCOMP_TOLERANT: init_seccomp_addconn(SCMP_ACT_ERRNO(EACCES)); break; case SECCOMP_DISABLED: break; default: bad_case(cfg->setup.options[KBF_SECCOMP]); } #endif #ifdef USE_DNSSEC unbound_sync_init(cfg->setup.options[KBF_DO_DNSSEC], cfg->setup.strings[KSF_PLUTO_DNSSEC_ROOTKEY_FILE], cfg->setup.strings[KSF_PLUTO_DNSSEC_ANCHORS]); #endif if (autoall) { if (verbose > 0) printf("loading all conns according to their auto= settings\n"); /* * Load all conns marked as auto=add or better. * First, do the auto=route and auto=add conns to quickly * get routes in place, then do auto=start as these can be * slower. * This mimics behaviour of the old _plutoload */ if (verbose > 0) printf(" Pass #1: Loading auto=add, auto=route and auto=start connections\n"); for (conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) { if (conn->desired_state == STARTUP_ADD || conn->desired_state == STARTUP_ONDEMAND || conn->desired_state == STARTUP_START) { if (verbose > 0) printf(" %s", conn->name); resolve_defaultroute(conn); starter_whack_add_conn(cfg, conn); } } /* * We loaded all connections. Now tell pluto to listen, * then route the conns and resolve default route. */ starter_whack_listen(cfg); if (verbose > 0) printf(" Pass #2: Routing auto=route connections\n"); for (conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) { if (conn->desired_state == STARTUP_ONDEMAND) { if (verbose > 0) printf(" %s", conn->name); if (conn->desired_state == STARTUP_ONDEMAND) starter_whack_route_conn(cfg, conn); } } if (verbose > 0) printf(" Pass #3: Initiating auto=start connections\n"); for (conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) { if (conn->desired_state == STARTUP_START) { if (verbose > 0) printf(" %s", conn->name); starter_whack_initiate_conn(cfg, conn); } } if (verbose > 0) printf("\n"); } else { /* load named conns, regardless of their state */ int connum; if (verbose > 0) printf("loading named conns:"); for (connum = optind; connum < argc; connum++) { const char *connname = argv[connum]; const char *p1 = ""; /* message prefix components */ const char *p2 = ""; const char *p3 = ""; if (verbose > 0) printf(" %s", connname); /* find first name match, if any */ for (conn = cfg->conns.tqh_first; conn != NULL && !streq(conn->name, connname); conn = conn->link.tqe_next) { } if (conn == NULL) { /* We didn't find name; look for first alias */ p1 = "alias: "; p2 = connname; p3 = " "; for (conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) { if (lsw_alias_cmp(connname, conn->strings[KSCF_CONNALIAS])) { break; } } } if (conn == NULL) { /* we found neither name nor alias */ exit_status += RC_UNKNOWN_NAME; /* cause non-zero exit code */ if (verbose > 0) { printf(" (notfound)\n"); } fprintf(stderr, "conn '%s': not found (tried aliases)\n", connname); } else { /* found name or alias */ if (conn->state == STATE_ADDED) { fprintf(stderr, "\n%s%s%sconn %s already added\n", p1, p2, p3, conn->name); } else if (conn->state == STATE_FAILED) { fprintf(stderr, "\n%s%s%sconn %s did not load properly\n", p1, p2, p3, conn->name); } else { resolve_defaultroute(conn); exit_status = starter_whack_add_conn( cfg, conn); conn->state = STATE_ADDED; } } } } if (listall) { if (verbose > 0) printf("listing all conns\n"); for (conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) printf("%s ", conn->name); printf("\n"); } else { if (listadd) { if (verbose > 0) printf("listing all conns marked as auto=add\n"); /* list all conns marked as auto=add */ for (conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) { if (conn->desired_state == STARTUP_ADD) printf("%s ", conn->name); } } if (listroute) { if (verbose > 0) printf("listing all conns marked as auto=route and auto=start\n"); /* * list all conns marked as auto=route or start or * better */ for (conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) { if (conn->desired_state == STARTUP_START || conn->desired_state == STARTUP_ONDEMAND) printf("%s ", conn->name); } } if (liststart && !listroute) { if (verbose > 0) printf("listing all conns marked as auto=start\n"); /* list all conns marked as auto=start */ for (conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) { if (conn->desired_state == STARTUP_START) printf("%s ", conn->name); } } if (listignore) { if (verbose > 0) printf("listing all conns marked as auto=ignore\n"); /* list all conns marked as auto=start */ for (conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) { if (conn->desired_state == STARTUP_IGNORE) printf("%s ", conn->name); } printf("\n"); } } if (liststack) { const struct keyword_def *kd; for (kd = ipsec_conf_keywords; kd->keyname != NULL; kd++) { if (strstr(kd->keyname, "protostack")) { if (cfg->setup.strings[kd->field]) { printf("%s\n", cfg->setup.strings[kd->field]); } else { /* implicit default */ printf("netkey\n"); } } } confread_free(cfg); exit(0); } if (configsetup) { const struct keyword_def *kd; printf("%s %sconfreadstatus=''\n", export, varprefix); for (kd = ipsec_conf_keywords; kd->keyname != NULL; kd++) { if ((kd->validity & kv_config) == 0) continue; /* don't print backwards compatible aliases */ if ((kd->validity & kv_alias) != 0) continue; char *safe_kwname = environlize(kd->keyname); switch (kd->type) { case kt_string: case kt_filename: case kt_dirname: case kt_loose_enum: if (cfg->setup.strings[kd->field]) { printf("%s %s%s='%s'\n", export, varprefix, safe_kwname, cfg->setup.strings[kd->field]); } break; case kt_bool: printf("%s %s%s='%s'\n", export, varprefix, safe_kwname, bool_str(cfg->setup.options[kd->field])); break; case kt_list: printf("%s %s%s='", export, varprefix, safe_kwname); confwrite_list(stdout, "", cfg->setup.options[kd->field], kd); printf("'\n"); break; case kt_obsolete: break; default: if (cfg->setup.options[kd->field] || cfg->setup.options_set[kd->field]) { printf("%s %s%s='%d'\n", export, varprefix, safe_kwname, cfg->setup.options[kd->field]); } break; } free(safe_kwname); } confread_free(cfg); exit(0); } confread_free(cfg); #ifdef USE_DNSSEC unbound_ctx_free(); #endif /* * Only RC_ codes between RC_EXIT_FLOOR (RC_DUPNAME) and * RC_EXIT_ROOF (RC_NEW_V1_STATE) are errors Some starter code * above can also return -1 which is not a valid RC_ code */ if (exit_status > 0 && (exit_status < RC_EXIT_FLOOR || exit_status >= RC_EXIT_ROOF)) exit_status = 0; exit(exit_status); } libreswan-3.32/programs/algparse/000077500000000000000000000000001365625662500170775ustar00rootroot00000000000000libreswan-3.32/programs/algparse/Makefile000066400000000000000000000033341365625662500205420ustar00rootroot00000000000000# algparse Makefile, for libreswan # # Copyright (C) 2017 Andrew Cagney # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # XXX: Hack to suppress the man page. Should one be added? PROGRAM_MANPAGE = PROGRAM = algparse OBJS += $(PROGRAM).o # # XXX: For the moment build things by pulling in chunks of pluto. # What, if anything, should be moved to libswan or another library? # PLUTOOBJS += crypt_symkey.o PLUTOOBJS += crypt_hash.o PLUTOOBJS += crypt_prf.o PLUTOOBJS += test_buffer.o PLUTOOBJS += cbc_test_vectors.o PLUTOOBJS += ctr_test_vectors.o PLUTOOBJS += gcm_test_vectors.o PLUTOOBJS += prf_test_vectors.o # Need absolute path as 'make' (check dependencies) and 'ld' (do link) # are run from different directories. OBJS += $(addprefix $(abs_top_builddir)/programs/pluto/, $(PLUTOOBJS)) # $(PROGRAM): pluto-base # .PHONY: pluto-base # pluto-base: # $(MAKE) -C $(top_srcdir)/programs/pluto base OBJS += $(LIBRESWANLIB) OBJS += $(LSWTOOLLIBS) OBJS += $(LIBSERPENT) OBJS += $(LIBTWOFISH) LDFLAGS += $(NSS_LDFLAGS) LDFLAGS += $(NSPR_LDFLAGS) ifdef top_srcdir include $(top_srcdir)/mk/program.mk else include ../../mk/program.mk endif local-selfcheck: $(PROGRAM) $(top_srcdir)/testing/pluto/basic-pluto-00/algparse.sh $(builddir)/$(PROGRAM) libreswan-3.32/programs/algparse/algparse.c000066400000000000000000000427501365625662500210510ustar00rootroot00000000000000#include #include #include "lswlog.h" #include "lswtool.h" #include "lswalloc.h" #include "lswnss.h" #include "lswfips.h" #include "lswconf.h" #include "ike_alg.h" #include "proposals.h" static bool test_proposals = false; static bool test_algs = false; static bool verbose = false; static bool debug = false; static bool impair = false; static enum ike_version ike_version = IKEv2; static unsigned parser_version = 0; static bool ignore_parser_errors = false; static bool fips = false; static bool pfs = false; static int failures = 0; enum status { PASSED = 0, FAILED = 1, ERROR = 126, }; enum expect { FAIL = false, PASS = true, COUNT, }; #define CHECK(CHECK,PARSE,OK) { \ struct proposal_policy policy = { \ .version = ike_version, \ .parser_version = parser_version, \ .alg_is_ok = OK, \ .pfs = pfs, \ .warning = warning, \ .check_pfs_vs_dh = CHECK, \ .ignore_parser_errors = ignore_parser_errors, \ }; \ printf("algparse "); \ if (impair) { \ printf("-impair "); \ } \ if (parser_version > 0) { \ printf("-p%d ", parser_version); \ } \ if (fips) { \ printf("-fips "); \ } \ switch (ike_version) { \ case IKEv1: printf("-v1 "); break; \ case IKEv2: printf("-v2 "); break; \ default: break; \ } \ if (pfs) { \ printf("-pfs "); \ } \ if (algstr == NULL) { \ printf("'%s'\n", #PARSE); \ } else { \ printf("'%s=%s'\n", #PARSE, algstr); \ } \ fflush(NULL); \ struct proposal_parser *parser = \ PARSE##_proposal_parser(&policy); \ struct proposals *proposals = \ proposals_from_str(parser, algstr); \ if (proposals != NULL) { \ pexpect(parser->error[0] == '\0'); \ FOR_EACH_PROPOSAL(proposals, proposal) { \ LSWLOG_FILE(stdout, log) { \ lswlogf(log, "\t"); \ fmt_proposal(log, proposal); \ } \ } \ proposals_delref(&proposals); \ if (expected == FAIL) { \ failures++; \ fprintf(stderr, \ "UNEXPECTED PASS: %s%s%s\n", \ #PARSE, \ algstr == NULL ? "" : "=", \ algstr == NULL ? "" : algstr); \ } \ } else { \ pexpect(parser->error[0]); \ printf("\tERROR: %s\n", parser->error); \ if (expected == PASS) { \ failures++; \ fprintf(stderr, \ "UNEXPECTED FAIL: %s%s%s\n", \ #PARSE, \ algstr == NULL ? "" : "=", \ algstr == NULL ? "" : algstr); \ } else if (expected == COUNT) { \ failures++; \ } \ } \ free_proposal_parser(&parser); \ fflush(NULL); \ } /* * Dump warnings to stdout. */ static int warning(const char *fmt, ...) { printf("\tWARNING: "); va_list ap; va_start(ap, fmt); vprintf(fmt, ap); va_end(ap); printf("\n"); return 0; } /* * Kernel not available so fake it. */ static bool kernel_alg_is_ok(const struct ike_alg *alg) { if (alg->algo_type == &ike_alg_dh) { /* require an in-process/ike implementation of DH */ return ike_alg_is_ike(alg); } else { /* no kernel to ask! */ return TRUE; } } static void esp(enum expect expected, const char *algstr) { CHECK(true, esp, kernel_alg_is_ok); } static void ah(enum expect expected, const char *algstr) { CHECK(true, ah, kernel_alg_is_ok); } static void ike(enum expect expected, const char *algstr) { CHECK(false, ike, ike_alg_is_ike); } typedef void (protocol_t)(enum expect expected, const char *); struct protocol { const char *name; protocol_t *parser; }; const struct protocol protocols[] = { { "ike", ike, }, { "ah", ah, }, { "esp", esp, }, }; static void all(const char *algstr) { for (const struct protocol *protocol = protocols; protocol < protocols + elemsof(protocols); protocol++) { protocol->parser(COUNT, algstr); } } static void test_proposal(const char *arg) { const char *eq = strchr(arg, '='); for (const struct protocol *protocol = protocols; protocol < protocols + elemsof(protocols); protocol++) { if (streq(arg, protocol->name)) { protocol->parser(COUNT, NULL); return; } if (startswith(arg, protocol->name) && arg + strlen(protocol->name) == eq) { protocol->parser(COUNT, eq + 1); return; } } if (eq != NULL) { fprintf(stderr, "unrecognized PROTOCOL in '%s'", arg); exit(1); } all(arg); } static void test(void) { /* * esp= */ esp(true, NULL); esp(false, ""); #ifdef USE_AES esp(true, "aes"); esp(true, "aes;modp2048"); # ifdef USE_SHA1 esp(true, "aes-sha1"); esp(true, "aes-sha1"); esp(true, "aes-sha1-modp2048"); esp(true, "aes-128-sha1"); esp(true, "aes-128-sha1"); esp(true, "aes-128-sha1-modp2048"); # endif esp(true, "aes-128"); esp(true, "aes_gcm_a-128-null"); #endif #ifdef USE_3DES # ifdef USE_DH2 esp(true, "3des-sha1;modp1024"); # else esp(false, "3des-sha1;modp1024"); # endif # ifdef USE_SHA1 esp(!fips, "3des-sha1;modp1536"); esp(true, "3des-sha1;modp2048"); esp(ike_version == IKEv2, "3des-sha1;dh21"); esp(ike_version == IKEv2, "3des-sha1;ecp_521"); esp(false, "3des-sha1;dh23"); esp(false, "3des-sha1;dh24"); esp(true, "3des-sha1"); # endif #endif #ifdef USE_SHA1 esp(!fips, "null-sha1"); #endif #ifdef USE_AES esp(true, "aes_cbc"); # ifdef USE_SHA1 esp(true, "aes-sha"); esp(true, "aes-sha1"); esp(true, "aes128-sha1"); # endif # ifdef USE_SHA2 esp(true, "aes-sha2"); esp(true, "aes-sha256"); esp(true, "aes-sha384"); esp(true, "aes-sha512"); # endif esp(!fips, "aes128-aes_xcbc"); # ifdef USE_SHA1 esp(true, "aes192-sha1"); esp(true, "aes256-sha1"); esp(true, "aes256-sha"); # endif # ifdef USE_SHA2 esp(true, "aes256-sha2"); esp(true, "aes256-sha2_256"); esp(true, "aes256-sha2_384"); esp(true, "aes256-sha2_512"); # endif #endif #ifdef USE_CAMELLIA esp(!fips, "camellia"); esp(!fips, "camellia128"); esp(!fips, "camellia192"); esp(!fips, "camellia256"); #endif #ifdef USE_AES /* this checks the bit sizes as well */ esp(true, "aes_ccm"); esp(true, "aes_ccm_a-128-null"); esp(true, "aes_ccm_a-192-null"); esp(true, "aes_ccm_a-256-null"); esp(true, "aes_ccm_b-128-null"); esp(true, "aes_ccm_b-192-null"); esp(true, "aes_ccm_b-256-null"); esp(true, "aes_ccm_c-128-null"); esp(true, "aes_ccm_c-192-null"); esp(true, "aes_ccm_c-256-null"); esp(true, "aes_gcm"); esp(true, "aes_gcm_a-128-null"); esp(true, "aes_gcm_a-192-null"); esp(true, "aes_gcm_a-256-null"); esp(true, "aes_gcm_b-128-null"); esp(true, "aes_gcm_b-192-null"); esp(true, "aes_gcm_b-256-null"); esp(true, "aes_gcm_c-128-null"); esp(true, "aes_gcm_c-192-null"); esp(true, "aes_gcm_c-256-null"); esp(true, "aes_ccm_a-null"); esp(true, "aes_ccm_b-null"); esp(true, "aes_ccm_c-null"); esp(true, "aes_gcm_a-null"); esp(true, "aes_gcm_b-null"); esp(true, "aes_gcm_c-null"); esp(true, "aes_ccm-null"); esp(true, "aes_gcm-null"); esp(true, "aes_ccm-256-null"); esp(true, "aes_gcm-192-null"); esp(true, "aes_ccm_256-null"); esp(true, "aes_gcm_192-null"); esp(true, "aes_ccm_8-null"); esp(true, "aes_ccm_12-null"); esp(true, "aes_ccm_16-null"); esp(true, "aes_gcm_8-null"); esp(true, "aes_gcm_12-null"); esp(true, "aes_gcm_16-null"); esp(true, "aes_ccm_8-128-null"); esp(true, "aes_ccm_12-192-null"); esp(true, "aes_ccm_16-256-null"); esp(true, "aes_gcm_8-128-null"); esp(true, "aes_gcm_12-192-null"); esp(true, "aes_gcm_16-256-null"); esp(true, "aes_ccm_8_128-null"); esp(true, "aes_ccm_12_192-null"); esp(true, "aes_ccm_16_256-null"); esp(true, "aes_gcm_8_128-null"); esp(true, "aes_gcm_12_192-null"); esp(true, "aes_gcm_16_256-null"); /* other */ esp(true, "aes_ctr"); esp(true, "aesctr"); esp(true, "aes_ctr128"); esp(true, "aes_ctr192"); esp(true, "aes_ctr256"); #endif #ifdef USE_SERPENT esp(!fips, "serpent"); #endif #ifdef USE_TWOFISH esp(!fips, "twofish"); #endif #ifdef USE_CAMELLIA esp(!fips, "camellia_cbc_256-hmac_sha2_512_256;modp8192"); /* long */ #endif esp(true, "null_auth_aes_gmac_256-null;modp8192"); /* long */ #ifdef USE_3DES # ifdef USE_SHA1 esp(true, "3des-sha1;modp8192"); /* allow ';' when unambigious */ esp(true, "3des-sha1-modp8192"); /* allow '-' when unambigious */ # endif #endif #ifdef USE_AES # ifdef USE_3DES # ifdef USE_SHA1 esp(!pfs, "aes-sha1,3des-sha1;modp8192"); esp(true, "aes-sha1-modp8192,3des-sha1-modp8192"); /* silly */ # endif # endif # ifdef USE_SHA1 esp(true, "aes-sha1-modp8192,aes-sha1-modp8192,aes-sha1-modp8192"); /* suppress duplicates */ # endif esp(ike_version == IKEv2, "aes;none"); esp(ike_version == IKEv2 && !pfs, "aes;none,aes"); esp(ike_version == IKEv2, "aes;none,aes;modp2048"); # ifdef USE_SHA1 esp(ike_version == IKEv2, "aes-sha1-none"); esp(ike_version == IKEv2, "aes-sha1;none"); # endif #endif /* * should this be supported - for now man page says not * esp("modp1536"); */ /* ESP tests that should fail */ /* So these do not require ifdef's to prevent bad exit code */ esp(impair, "3des168-sha1"); /* wrong keylen */ esp(impair, "3des-null"); /* non-null integ */ esp(impair, "aes128-null"); /* non-null-integ */ esp(impair, "aes224-sha1"); /* wrong keylen */ esp(impair, "aes-224-sha1"); /* wrong keylen */ esp(false, "aes0-sha1"); /* wrong keylen */ esp(false, "aes-0-sha1"); /* wrong keylen */ esp(impair, "aes512-sha1"); /* wrong keylen */ esp(false, "aes-sha1555"); /* unknown integ */ esp(impair, "camellia666-sha1"); /* wrong keylen */ esp(false, "blowfish"); /* obsoleted */ esp(false, "des-sha1"); /* obsoleted */ esp(impair, "aes_ctr666"); /* bad key size */ esp(false, "aes128-sha2_128"); /* _128 does not exist */ esp(false, "aes256-sha2_256-4096"); /* double keysize */ esp(false, "aes256-sha2_256-128"); /* now what?? */ esp(false, "vanitycipher"); esp(false, "ase-sah"); /* should get rejected */ esp(false, "aes-sah1"); /* should get rejected */ esp(false, "id3"); /* should be rejected; idXXX removed */ esp(false, "aes-id3"); /* should be rejected; idXXX removed */ esp(impair, "aes_gcm-md5"); /* AEAD must have auth null */ esp(false, "mars"); /* support removed */ esp(impair, "aes_gcm-16"); /* don't parse as aes_gcm_16 */ esp(false, "aes_gcm-0"); /* invalid keylen */ esp(false, "aes_gcm-123456789012345"); /* huge keylen */ esp(false, "3des-sha1;dh22"); /* support for dh22 removed */ esp(!pfs, "3des-sha1;modp8192,3des-sha2"); /* ;DH must be last */ esp(!pfs, "3des-sha1-modp8192,3des-sha2"); /* -DH must be last */ esp(true, "3des-sha1-modp8192,3des-sha2-modp8192"); esp(true, "3des-sha1-modp8192,3des-sha2;modp8192"); esp(true, "3des-sha1;modp8192,3des-sha2-modp8192"); esp(true, "3des-sha1;modp8192,3des-sha2;modp8192"); esp(!pfs, "3des-sha1-modp8192,3des-sha2-modp2048"); /* * ah= */ ah(true, NULL); ah(false, ""); #ifdef USE_MD5 ah(!fips, "md5"); #endif #ifdef USE_SHA1 ah(true, "sha"); ah(true, "sha;modp2048"); ah(true, "sha1"); #endif #ifdef USE_SHA2 ah(true, "sha2"); ah(true, "sha256"); ah(true, "sha384"); ah(true, "sha512"); ah(true, "sha2_256"); ah(true, "sha2_384"); ah(true, "sha2_512"); #endif #ifdef USE_AES ah(!fips, "aes_xcbc"); #endif #ifdef USE_SHA2 ah(ike_version == IKEv2, "sha2-none"); ah(ike_version == IKEv2, "sha2;none"); #endif #ifdef USE_SHA1 ah(true, "sha1-modp8192,sha1-modp8192,sha1-modp8192"); /* suppress duplicates */ ah(impair, "aes-sha1"); #endif ah(false, "vanityhash1"); #ifdef USE_AES ah(impair, "aes_gcm_c-256"); #endif ah(false, "id3"); /* should be rejected; idXXX removed */ #ifdef USE_3DES ah(impair, "3des"); #endif ah(impair, "null"); #ifdef USE_AES ah(impair, "aes_gcm"); ah(impair, "aes_ccm"); #endif ah(false, "ripemd"); /* support removed */ /* * ike= */ ike(true, NULL); ike(false, ""); ike(true, "3des-sha1"); ike(true, "3des-sha1"); ike(!fips, "3des-sha1;modp1536"); ike(true, "3des;dh21"); ike(true, "3des-sha1;dh21"); ike(true, "3des-sha1-ecp_521"); ike(ike_version == IKEv2, "aes_gcm"); ike(true, "aes-sha1-modp8192,aes-sha1-modp8192,aes-sha1-modp8192"); /* suppress duplicates */ ike(false, "aes;none"); ike(false, "id2"); /* should be rejected; idXXX removed */ ike(false, "3des-id2"); /* should be rejected; idXXX removed */ ike(false, "aes_ccm"); /* ESP/AH only */ ike(impair, "aes_gcm-sha1-none-modp2048"); ike(impair, "aes_gcm+aes_gcm-sha1-none-modp2048"); ike(false, "aes+aes_gcm"); /* mixing AEAD and NORM encryption */ } static void usage(void) { fprintf(stderr, "Usage:\n" "\n" " algparse [