pax_global_header00006660000000000000000000000064145737206420014524gustar00rootroot0000000000000052 comment=50d011081b9361da0f48eb30b400af3bcf77ed2c libreswan-4.14/000077500000000000000000000000001457372064200134425ustar00rootroot00000000000000libreswan-4.14/.github/000077500000000000000000000000001457372064200150025ustar00rootroot00000000000000libreswan-4.14/.github/codeql-analysis.yml000066400000000000000000000046411457372064200206220ustar00rootroot00000000000000# For most projects, this workflow file will not need changing; you simply need # to commit it to your repository. # # You may wish to alter this file to override the set of languages analyzed, # or to provide custom queries or build logic. # # ******** NOTE ******** # We have attempted to detect the languages in your repository. Please check # the `language` matrix defined below to confirm you have the correct set of # supported CodeQL languages. # name: "CodeQL" on: push: branches: [ main ] pull_request: # The branches below must be a subset of the branches above branches: [ main ] schedule: - cron: '21 16 * * 2' jobs: analyze: name: Analyze runs-on: ubuntu-latest permissions: actions: read contents: read security-events: write strategy: fail-fast: false matrix: language: [ 'cpp', 'javascript', 'python' ] # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] # Learn more: # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed steps: - name: Checkout repository uses: actions/checkout@v2 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL uses: github/codeql-action/init@v1 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. # By default, queries listed here will override any specified in a config file. # Prefix the list here with "+" to use these queries and those in the config file. # queries: ./path/to/local/query, your-org/your-repo/queries@main # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild uses: github/codeql-action/autobuild@v1 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines # and modify them (or add more) to build your code if your project # uses a compiled language #- run: | # make bootstrap # make release - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v1 libreswan-4.14/.gitignore000066400000000000000000000010141457372064200154260ustar00rootroot00000000000000*~ .*.sw? \#*\# .\#* BACKUP RESULTS DEADJOE OBJ.* *.rej *.orig *.bak *.pyc *.o *.core 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-4.14/.travis.yml000066400000000000000000000022151457372064200155530ustar00rootroot00000000000000sudo: 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 Fedora 32 # - 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 script: - make TRAVIS_ENABLED=true travis-docker-make || travis_terminate 1; - make TRAVIS_ENABLED=true travis-docker-make-install || travis_terminate 1; libreswan-4.14/CHANGES000066400000000000000000003463451457372064200144540ustar00rootroot00000000000000 See also https://libreswan.org/ v4.14 (March 11, 2024) * Fix compile error in 4.13 in gntoid() [Andrew] * testing: fixup ikev2-tfc-03 for padded packets [Andrew/Paul] v4.13 (March 11, 2024) * Security: Fixes http://libreswan.org/security/CVE-2024-2357 * Linux: make libcap-ng failures non-fatal [Andrew] * BSD: fix esp=aes_gcm [Andrew] * NetBSD: fix compiler warning in lib/libswan/x509.c [Andrew] * x509: unpack IPv6 general names based on length [Andrew] * pluto: TFC padding was not set for AEAD algorithms [SaiKumarCholleti@github] v4.12 (Aug 8, 2023) * SECURITY IKEv2: Fixes https://libreswan.org/security/CVE-2023-38710 * SECURITY IKEv1: Fixes https://libreswan.org/security/CVE-2023-38711 * SECURITY IKEv1: Fixes https://libreswan.org/security/CVE-2023-38712 * pluto: Do not crash on ipcomp expiry msg [Andrew] v4.11 (May 3, 2023) * SECURITY IKEv1: Fixes https://libreswan.org/security/CVE-2023-30570 v4.10 (February 28, 2023) * SECURITY IKEv2: Fixes https://libreswan.org/security/CVE-2023-23009 * IKEv1: only clean up a connection when it isn't deleted [Andrew] v4.9 (October 13, 2022) * IKEv1: fix crasher (introduced in 4.8) when USE_NSS_KDF=false or MD5 [Andrew] * IKEv2: fix RFC 8229 IKE/ESP over IPv6 TCP [Andrew] v4.8 (October 2, 2022) * release: remove SHA1 bindings from LIBRESWAN OpenPGP key [dkg/Paul] * pluto: ignore obsoleted unused interfaces= / --iface [Paul/Andrew] * pluto: various internal crypto struct changes [Andrew] * pluto: fix traffic counters for AH and IPCOMP [Andrew] * pluto: improve logging of duplicate serial cert error [Andrew] * pluto: support for maxbytes/maxpacket counters [Antony/Paul] * pluto: handle HW tokens using strange CKAIDs; github/815 [Andrew] * pluto: added --ipsec-max-bytes / --ipsec-max-packets support [Antony] * libipsecconf: added ipsec-max-bytes= and ipsec-max-packets= options [Paul] * IKEv2: emit one CERTREQ payload with all the hashes [Andrew] * addconn/whack: add support for {left,right}pubkey= [Andrew] * showhostkey: add support for ECDSA pubkeys [Andrew] * Crypto: add KDF self tests [Daiki Ueno] * IPv6: open IPv6 IKE port 4500; github/800 [Andrew] * showhostkey: add --pem option to print PEM encoded public key [Andrew] * unbound: _unbound-hook converted from python to shell [Andrew] * BSD: delete old BSDKAME code replaced by PFKEYV2 code [Andrew] * BSD: fix replay window byte vs bit math [Andrew] * BSD: fix code finding interfaces; github/728 [Andrew] * FreeBSD: support large replay window; github/756 [Andrew] * FreeBSD: support ESN; github/721 [Andrew] * linux: update copy of xfrm.h header [Paul] * packaging: update fedora spec file [Paul/Tuomo] * building: on BSD, always use GCC; freebsd/264288 llvm/55963 [Andrew] * building: enable LTO when USE_LTO=true; github/836 github/834 [Andrew] * building: dropped default build and packaging support for: Fedora 22, 28, 29, 30 Debian stretch Ubuntu cosmic, xenial RHEL6 was removed in v4.5 Add SUSE, Arch, Mint v4.7 (May 24, 2022) * IKEv2: EAPTLS support [Timo Teräs / Andrew] * IKEv2: EAPONLY support [Andrew] * IKEv2: fix interop when IPCOMP+transport-mode [Andrew] * IKEv2: fix race between new IKE SA and liveness [Andrew] * IKEv2: fix interop with Android 12 + certificates [Andrew] * IKEv1: reject IKEv2 only authby=secret+rsasig [Andrew] * kernel: fix double delete of kernel policy when tearing down SA [Andrew] * kernel: fix deleting policy when an XFRMi FD ID; github/618 [Andrew] * kernel: general cleanups [Andrew] * _stackmanager / pluto: support Ubuntu 18.04 LTS kernels [Paul] * FreeBSD: libreswan builds out-of-the-box [Andrew] * BSD: Add IPv6 support (tested on NetBSD) * building: fix build on fedora rawhide [Paul] * internals: initiate IKEv2 CREATE_CHILD_SA exchange using IKE SA [Andrew] * internals: _updown.bsdkame renamed to _updown.bsd v4.6 (January 11, 2022) * SECURITY: Fixes CVE-2022-23094 https://libreswan.org/security/CVE-2022-23094 * IKEv2: aggressively check incoming fragments [Andrew] * IKEv2: when rekeying and PFS, only propose/allow original crypt-suite [Andrew] * IKEv2: when PFS, don't repeatedly log all proposals [Andrew] * IKEv2: Labeled IPsec improvements [Andrew] * IKEv1: support for ISAKMP_N_CISCO_LOAD_BALANCE removed [Andrew] * pluto: Revamp the host connection lookup mechanism [Andrew] * pluto: Change default replay-window from 32 to 128 [Paul] * pluto: Change default esn= to "either" and prefer "yes" [Paul] * pluto: Disable esn when replay-window=0 [Paul] * pluto: Drop obsolete debug options such as crypto-low [Andrew] * seccomp: Updated syscall allow-list [Paul] * packaging: replace old SUSE packaging with pointer to downstream [Andrew] * NetBSD: Don't use ESN - not supported by kernel [Andrew] * letsencrypt: Fix bashisms in letsencrypt script [dkg] * libipsecconf: allow leftauth=ecdsa|rsa (match authby= values) [Paul] * testing: significantly improved testing [Andrew, Paul] v4.5 (August 20, 2021) * IKEv1: multiple subnets could lead to crossed wires, failures [Paul/Andrew] * IKEv2: don't tear down IKE SA on TS_UNACCEPTABLE [Paul] * IKEv2: unpend/delete Child SA when rejected by IKE_AUTH response [Andrew] * IKEv2: mobike: resolve_defaultroute_one() updates [Andrew] * IKEv2: mobike: prevent sending duplicate mobike response [Andrew] * IKEv2: Support for Childless IKE SA [Andrew] * IKEv2: redirect: make peer redirecting in IKE_AUTH childless [Vukasin] * IKEv2: Labeled IPsec --up causes Childless IKE SA [Andrew/Paul] * IKEv2: Labeled IPsec conns share SPD policies (as IKEv1) [Andrew/Paul/Kavinda] * IKEv2: Performance; eliminate more O(#CONNECTIONS) code [Andrew] * IKEv2: Immediately delete replaced Child from new (IC) IKE SA [Andrew/Paul] * pluto: mismatched subnets= could take down all conns [Paul] * pluto: Don't delete existing IKE SA of connection instance [Paul] * pluto: fail better on parse errors in subnet= clause [Paul] * libswan: use getaddrinfo(3) instead of gethostbyname2(3) [Hugh] * libipsecconf: fail to load conn if no right= or left= set [Paul] * libipsecconf: change default of initial-contact= to yes [Paul] * X509: directly append new CRL requests to the fetch queue [Andrew] * whack: implement --impair trigger: [Andrew] * ipsec.service: remove reload which did not work as expected [Tuomo] * portexcludes: update to use python3 [Kim] * building: fix NetBSD build [Andrew] * building: fix arm / aarch64 build [kekePower@github] * building: Remove support for RHEL6 USE_OLD_SELINUX [Paul] * packaging: handle properly rpm sysctl config [Tuomo] * packaging: rhel7: fix python2 shebang [Tuomo] v4.4 (April 22, 2021) * IKEv2: Fixes for TCP encap in Transport Mode and host-to-host [Paul/Sabrina] * IKEv2: Fixes to Labeled IPsec policies [Kavinda Wewegama/Paul] * IKEv2: Add redirect statistics to whack --globalstatus [Clive Zagno] * IKEv2: Connections would not always switch when needed [Andrew/Paul] * pluto: Fix for host-to-host connections use non-standard IKE ports [Paul] * pluto: Use peer ID (IKEv2 IDr, IKEv1 Aggr) to select best initial conn [Paul] * pluto: Disable interface-ip= as the feature is not yet implemented [Paul] * pluto: Fix PLUTO_PEER_CLIENT* in updown for NAT + Transport Mode [Paul] * pluto: Remove never updated PLUTO_VERSION for updown scripts [Paul] * pluto: Actually set PLUTO_CONNECTION_TYPE= to transport or tunnel [Paul] * pluto: Allow non-templated wildcard ID connections to match [Paul] * pluto: Reduce and merge various logging messages [Andrew] * libipsecconf: Do not allow vhost/vnet in IKEv2 connections [Paul] * XFRM: Restarting pluto when using ipsec-interface= could fail [Paul] * contrib/munin: Update plugin to use python3 and update doc header [Tuomo] * testing: Enable OpenBSD interop tests [Paul/Ravi] * testing: Make tests more reliable on KVM [Andrew] v4.3 (February 21, 2021) * pluto: Restore range checking on Labeled IPsec [Paul/Andrew] * pluto: Higher state serialno does not imply newest state [Paul] * pluto: Cleanup ip_address vs ip_endpoint (protoport dropping) [Andrew] * pluto: Revival of code could accidentally fallback to IKEv1 [Andrew] * newhostkey: Add support for generating ECDSA keys [Daiki Ueno] * libipsecconf: Ignore empty option at end of config (rhbz#1685653) [Andrew] * whack: Add --global-redirect and --global-redirect-to options [Pietro Monteiro] v4.2 (February 2, 2021) * IKEv2: Support for IKEv2 Labeled IPsec [Hugh, Sahana, Paul, Kavinda Wewegama] * IKEv2: MOBIKE could cause assertion failure due to eroute ownership [Paul] * IKEv2: MOBIKE and NAT port update code interfered with each other [Andrew] * IKEv1: Re-enable questionable Microsoft proposals to fix L2TP/IPsec [Paul] * IKEv1: Do not load IKEv1 conns when IKEv1 support not compiled in [Paul] * IKEv1: Fix XAUTH: re-transmit when sending CFG request [Andrew] * pluto: New config setup option ikev1-policy= [Paul] * pluto: Change default ikelifetime from 1h to 8h [Paul] * pluto: Add ignore-peer-dns=yes|no and whack --ignore-peer-dns [Paul] * pluto: Startup could take long time closing fd's (github#373) [Andrew] * pluto: IKEv2 connection could accidentally retry as IKEv1 [Andrew] * pluto: change default IKE SA lifetime from 1h to 8h [Paul] Resolves: github#362, github#405, hwdsl2/setup-ipsec-vpn#912 * pluto: Revived conns can try to quickly re-use existing NAT mapping. Can be used with new auto=keep [Paul, Andrew] * pluto: Don't complain about DNS names starting with number [Paul] * pluto: Re-implement Labeled IPsec for IKEv1 [Paul, Sahana] * pluto: Support for --shutdown --leave-state [Paul] * whack: add very raw --processstatus [Andrew] * whack: no longer require --ipv6 when specifying raw IPv6 host addresses * libswan: Re-introduce xauthusername/remote_peer_type for NM-libreswan [Paul] * initsystem: fix docker/podman startup with sysvinit [Paul] * initsystem: ensure non-testing namespaces work with systemd [Paul] * initsystem: systemd support for ipsec whack --shutdown --leave-state [Paul] * pluto: prefer IPv4 over IPv6 when performing DNS lookups [Andrew] * building: Support for compiling without IKEv1 via USE_IKEv1=false [Paul] * building: Various clang compiler related fixes [Timm Baeder] * building: fix NetBSD arm64 build [Andrew] * testing: many updates [Andrew, Paul] v4.1 (October 18, 2020) * IKEv2: Fix Notify protocol ID interop with Cisco introduced in 4.0 [Antony] * addconn: Fix resolving with %defaultroute plus peer with A + AAAA [Antony] * building: minor cleanups [Andrew/Tuomo] v4.0 (October 14, 2020) * KLIPS: Support for KLIPS completely removed [Paul] * pluto: Removed support for deprecated algos: serpent, twofish, cast [Paul] * IKEv2: EXPERIMENTAL: Support for RFC 8229 IKE/ESP over TCP [Andrew/Mayank Totale] New per-conn keywords: listen-tcp=yes|no, tcponly=yes|no, tcp-remoteport= Requires: Linux kernel >= 5.8 * IKEv2: Support for leftikeport= / rightikeport= [Andrew/Paul] * IKEv2: EXPERIMENTAL: Support for INTERMEDIATE Exchange [Yulia Kuzovkova/GSoC] New keyword: intermediate=yes * FIPS: Remove DH 23/24 from FIPS allowed list as per SP 800 56A Rev 3 [Paul] * pluto: Support for rereading configured certificates from NSS [Myungjin Lee] * pluto: plutodebug= keywords are now: base,cpu-usage,crypt,tmi,private [Andrew] * pluto: find_pluto_xfrmi_interface() would only check first interface [Paul] * pluto: ddos cookies-threshold and max-halfopen output was swapped [John Mah] * pluto: Fix leased IP address leak [Andrew/Paul] * pluto: Fix displaying PLUTO_BYTES_ counters [Paul] * pluto: Replace/remove deprecated libselinux functions [Eduardo Barretto] * pluto: Update selinux calls for Labeled IPsec support [Richard Haines] * pluto: Memory leak fixes [Hugh] * pluto: Remove unused per peer logging [Andrew] * pluto: Cleanup logging code for minimal logging support [Andrew] * pluto: Cleanup netlink / XFRM code [Hugh] * pluto: xfrmi used mark-out for XFRMA_SET_MARK [Antony/Wolfgang] * pluto: Support for ipsec0 interface to help migrate from KLIPS to XFRM [Paul] * pluto: Fix logging some IKE messages to proper IKE SA state [Andrew] * pluto: Remove global ikeport/nat-ikeport, add listen-udp/listen-tcp [Paul] * pluto: Connections now have serial numbers which are logged [Paul/Andrew] * pluto: No longer require :RSA sections in ipsec.secrets [Andrew] * pluto: pluto chooses wrong raw RSA key (github#352) [Andrew] * seccomp: Update syscall allowlist for pluto and addconn [Paul] * whack: Support for ipsec whack --rereadcerts [Paul] * whack: Rename --ikev1-allow and --ikev2-allow to --ikev1 and --ikev2 [Paul] * whack: Clear inherited defaults for IKEv2 from IKEv1 connections [Paul] * show: Fixup for python3 version of ipaddress module [Paul] * IKEv2: Fix Windows 10 rekey being rejected [Antony/Paul] * IKEv2: Remove duplicaes from proposals using "+" [Andrew] * IKEv2: CERTREQ payload was not sent for authby=ecdsa [Paul] * IKEv2: Decode notify payloads into the message digest [Andrew] * IKEv2: Don't use NAT-T port when no NAT DETECTION payloads received [Andrew] * IKEv2: Add load-balance support (multiple targets) to redirect [Vukasin] * IKEv2: Only sent REDIRECTs to established IKE SA's (not IPsec SAs) [Paul] * IKEv2: Fix AUTH failure if ID payload reserved fields != 0 [Paul/Andrew/Hugh] * IKEv2: A delete(IKE SA) request should not trigger a delete request [Andrew] * IKEv2: Ignore, not abort when receiving unknown type transforms [Andrew] * IKEv2: Don't switch NAT port on receiving non-NAT notify payloads [Andrew] * IKEv1: Prevent crashing in Quick Mode on unused NAT payload [Daniel Wendler] * libipsecconf: Fix config handling of policy-label [bauen1] * libipsecconf: Promote ah= / esp= as desired keywords over phase2alg= [Paul] * libipsecconf: Remove most obsoleted option names with undersscore(_) [Paul] * rsasigkey/newhostkey: Remove obsoleted --output option [Paul] * building: Add NetBSD support [Andrew] * building: Remove support for SINGLE_CONF_DIR, EMIT_ISAKMP_SPI, [Paul] USE_KEYRR and TEST_INDECENT_PROPOSAL * building: Merge userland.mk into config.mk to simplify makefiles [Tuomo] * building: Deprecate INC_ variables [Tuomo] * building: Remove all support for SERPENT, TWOFISH, CAST and RIPEMD [Paul] * building: Remove -DALLOW_MICROSOFT_BAD_PROPOSAL [Tuomo] * building: The define USE_NSS_PRF was renamed to USE_NSS_KDF [Tuomo] * building: Rename master branch to main branch [Paul] * building: Fix finding ipsec command in non-standard bin dirs [Tuomo] * building: Introduce USE_OLD_SELINUX to support libselinux < 2.1.9 [Paul] * building: NETKEY options changed to XFRM options [Paul] * building: NSS database (*.db) are now expected in /var/lib/ipsec/nss [Tuomo] ipsec checknss called in initsystem will migrate files Use FINALNSSDIR=/etc/ipsec.d to use the pre-4.0 location * packaging: Debian: remove runtime dependency on systemd [Stephen Kitt] * packaging: Fedora: add missing build dependency for certutil [Stephen Kitt] * packaging: Debian switched to using /usr/libexec/ [dkg] * testing: Support Fedora32, Ubuntu, improved namespaces support [Paul/Others] * testing: Work around kernel ICMP Acquire bug [Paul] * testing: Added interop testing with OpenBSD iked [Ravi Teja] * documentation: friendler ipsec cmd output [Paul] 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 [Tuomo] * 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 occurrences [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 add 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-4.14/CODE_OF_CONDUCT.md000066400000000000000000000044541457372064200162500ustar00rootroot00000000000000# 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-4.14/COPYING000066400000000000000000000432541457372064200145050ustar00rootroot00000000000000 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-4.14/CREDITS000066400000000000000000000022141457372064200144610ustar00rootroot00000000000000The 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 Vukasin Karadzic Yulia Kuzovkova David McCullough Amir Naftali Wolfgang Nothdurft Sahana Prasad D. Hugh Redelmeier Lubomir Rintel Matt Rogers Tuomo Soini Ravi Teja Timo Teräs Paul Wouters Herbert Xu Libreswan is a continuation 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 docs/CREDITS.freeswan file from FreeS/WAN for details on original work. libreswan-4.14/CROSSCOMPILE.sh000077500000000000000000000026031457372064200157040ustar00rootroot00000000000000#!/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-4.14/INSTALL000066400000000000000000000015161457372064200144760ustar00rootroot00000000000000 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 nspr libevent for systemd: pkgconfig hostname systemd for pam/xauth: pam for dnssec support: unbound ldns for legacy FIPS support: fipscheck for libcap-ng support: libcap-ng for CRL fetching support: libcurl for CRL ldap fetching support: openldap for audit support: audit-libs for seccomp support: libseccomp for labeled ipsec support: libselinux for man page regeneration: xmlto 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. libreswan-4.14/LIBRESWAN-OPENPGP-KEY.txt000066400000000000000000000061131457372064200172660ustar00rootroot00000000000000-----BEGIN PGP PUBLIC KEY BLOCK----- mQINBFDjilcBEAChkfasfBKTzGys9DwgBsmDVsPConW60uyKnu16+wO1kIKMFWi6 wGllwKUJmCBY2FSQHbOBy5eHPPT1ijJhYt4j7WU+YJVh5Ca5RE3trFt31FX0vzp+ KMqdQ8HOofA7jO6bgyHUwOJ539YkqYj1jHKfrdRqOnzB9fFyEb7485sq1F8j/rHk cSar1Hd9QfGAZHxXqgncgHFobB/xXEGRJIi+4kNL5SYasbw9tfYUGPrUXVol1+pn tsG92736O5Qe5K+wH2nAS4hwPJ1Xr4XIKeNNwxQW25wWqn4mLa4Vly+PA2uSE7ZP RcxE3yBCaLFMlw4rLhFAzd6TeslQONZ+9K51yfBYm7m0vWM3Ixq8yuD8E49OkKr8 QRMaA2g89NW3AuNLExiTE0zQzAs/g6eX8WZdeWCvKxhRTAUYkw0QTimFgv6LXIeS //5DOAAO9WwzlseTGmUgek3BbnnJJiGHVLBgnLaqWLOZ1Y8ON1uC8lQnbIeYbTQq EE5R0cbVLVXBJoKakBF8gwHF51HC2pSBYmHNZsSbjMuHpJWJM4fVldNWPNaqriKC OkL8QgvNoapgk20k1ajLl/ibv32k7QBKy3cTMtbQYPdreXcoZuMw38ysQcgFxPCs Zh92aaWW0ceWowkJ7CFnes2jdPcMSOYE37wodmV3/VV7cusmTD8wikyUdQARAQAB tCxMaWJyZXN3YW4gKFNpZ25pbmcgS2V5KSA8dGVhbUBsaWJyZXN3YW4ub3JnPokC TgQTAQoAOBYhBJB+eQ8lwejlYc1ztYX/S0OzD8b5BQJi4cg4AhsDBQsJCAcDBRUK CQgLBRYCAwEAAh4FAheAAAoJEIX/S0OzD8b5zNcP/RuDb05Xr+IpuGWtJ38yGMWG mZglLHrzCAOXNAr/QXt6Kz3sThJoZFIh2E4Ab5yW59iFLFpW3VuZIGVCyh7vsuVw MuKoJtrZtdbHSdLbE+FHpY7osQDrcuodTv5b7STfG2Wje18iG/dCATVIDDgbPmuJ FpNLcR3scuoIlgxmP3Y1AFgufLR5MiN60PKnS2Husyj0f5Gqc3USLofWKgEQ4wFa gT1iIjkf4zkFcVlJ5K0SE1ULn8K7umkOUvLcKg6ji+1sEwEM1kCNmxI8HkiNt296 9Z/TLK1h8McFGwG7x1p8fZ7Kjmzwnv1TSxAt1wHMoa0m9LntQOXnn3hVJaC74AzX heFtqDHmATpcGtQLR0zutrZ+ohUb6AEt+hAPfyDDYIR5y3oNdSLozJkJ1wlrhsYh SR1Hv4b3fdD6XgyUPggituOYm+yv1PuHrSEaoznnlX2z0MaVJyJIN0zUHlPBmWKC LmzQX2A7l9bHhkXYgHoSdeBHdwvcQQGWwkVmN2WUwsM/m9Abk8OdLdE13nI8824R 0+b6XzJ2g4L+RIsVseerX2WIMHSMvkbFuLpEE4ILOrL+9Lq5bdx9MvZPtsZ/ZutY QVVvJ+nJtmPp0HpybnJdXzB7Za02A0r2gXIUrund32K97qe8XblCwxkZbZCeLcSL 5+mb8O1XPGD39S6CCZbRuQINBFDjilcBEADXDN9o3icyDy+ity45CsQfo1f84xL6 oJIgCLGGwm3RFPgOzdgxaE7TiLzW2NBui+yHyw48WRTxZ9XC6HtGKjH6XPvP5nF4 8wss7tjzRNzmNgTp7G47HkW3lD0VYX4NqfCmxQK9gTXob1+JFmWkEXkXmZYg2dbn 1REtHb03x370Z547rjvdpopQW6jaSw0C556DOxb9weJqLqAd2uZO4nwhuDs/VM+Q yy+/MlHTbnsmnYIMozDLMmHZ1PMeJlTFPMfapaux9UDTgQ5dwLj2FiQ/uEMzvfVv W23hxlpWVHsccwZR77PMDt4Nbj/7QlOIKpgid2r8SyBmhjET2u/USSzFYzK8J2Wj oLcxiuMTwrnM6b3bqiuSDUMAEoNN814Cbpz6yLB2wyKs5N7ZA/lVLNE8MV7to8OD ww1nS2bDDf5/JMNt5aWu/iO2bBrYE30LqHR3bSV6QP57JnzunM9Y4V1BnEKYW14A 9+rRH1k1e5CuS5tqxpSubniF80AdUyPjF8rXOY0URD6zY0s4843Nf9TNr8ke/1ma qLEkUAF03AwBR8oz247ylu75q94ytpYUFJAkNeqpk8XypqKJMVcl4NfEP930JR82 sGjNylVu/b4EsqKfmkoU8VFM1lfuaqX1u2ZDoUpG2Io/zpeV07RQ0KTHdKBejzix 2IN0T7W4G0JXcwARAQABiQI1BBgBCAAgAhsMFiEEkH55DyXB6OVhzXO1hf9LQ7MP xvkFAmLkGmgACgkQhf9LQ7MPxvnelg/4lttwjkVAbJ39aWdsZvbZNfg4Hj42q48L DdTCaMcWBthK4HrPu4AITz8HNEgsvFQrJBqq+R/wZqXIsSn1ynwVWU+TLGIvwcaY CzCw8k8OigV3RkHwnGHh4Gf5frWlw7Kbp6IflVj9nGXh9ayTWGj7HzrwDvOPCPWt bt0QT+0nJvMQ5wG/SmcQRHWu2R++KN5iTwLW9g3yF1TOsxRE41TduqOmKNy7WDs2 fj+zke5VJn3u0uKLbf3qDqT5jH0rcB+lX/4djHxHFzB7jxnZaTbQVl8VLKLxXAEH EoW2aklDtlAcuymcZ8PSGEpsYmgsIxVBSj4zp/whd7RdBoOZS8qKr4YhvbSp1y08 HLjDSOmdtbIjSuZf3cHWg4dTbZIikjGdqdjRuY6XIahkTT9zXDfmL4L6FDAuXQ+j i0IP/mwkquPMDLK691QE/S9ddzBXjLhwpfbhmPnCio/jhg0B4bmOjEfc/9jA7XeG xOjdNFQFRj5qzxRJExqqAdKkuKf/FkeDaSc/CidGwid3lYarE50VKjJtneu8bYre 1aZ3yOFO3S0HNdgxPxwnw3G8roI0uR809mWuaLDjTTaj6Mte1TddmO+5F0pua5Jt fr6sX/gsYU7VjEOCCDAQ+aWcK9gHITWe6HeOiH5kwCR4EE+wtRJnf9AUS7xgDDXI 6nITdpymKA== =JUBw -----END PGP PUBLIC KEY BLOCK----- libreswan-4.14/LICENSE000066400000000000000000000005331457372064200144500ustar00rootroot00000000000000Except 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. 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-4.14/Makefile000066400000000000000000000155061457372064200151110ustar00rootroot00000000000000# Libreswan top level 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 $(top_srcdir)/mk/config.mk MAIN_RPM_VERSION = $(shell make showversion | sed "s/-.*//") MAIN_RPM_PREVER = $(shell make showversion | sed -e "s/^.[^-]*-\([^-]*\)-\(.*\)/rc\1_\2/" -e "s/-/_/g") 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) RHEL_LIKE= $(shell cat /etc/os-release | grep ID_LIKE | sed -e "s/ID_LIKE=//" -e 's/"//g' -e "s/ .*//") RHEL_MAJOR= $(shell cat /etc/os-release |grep VERSION_ID | sed -e 's/.*"\([0-9]*\)"/\1/' -e 's/VERSION_ID=//') SRCDIR?=$(shell pwd)/ # dummy default rule def: all help: @echo @echo "To build and install on a recent Linux kernel:" @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 @echo "To build debian packages: make deb" @echo "To build fedora/rhel/centos rpms: make rpm" @echo @false .PHONY: def help ERRCHECK=${MAKEUTILS}/errcheck KVUTIL=${MAKEUTILS}/kernelversion KVSHORTUTIL=${MAKEUTILS}/kernelversion-short SUBDIRS?=lib programs initsystems testing configs TAGSFILES = $(wildcard include/*.h include/*/*.h lib/lib*/*.[ch] programs/*/*.[ch] testing/check/*/*.[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/targets.mk # 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) ; ) # 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: kvm-clean-keys rm -f $(RPMTMPDIR) $(RPMDEST) out.* rm -rf testing/pluto/*/OUTPUT* rm -rf OBJ.* $(OBJDIR) rm -rf BACKUP rm -f tags TAGS cscope rm -f cscope.files rpm: @if [ -d .git ]; then \ echo "For git trees, please run: make git-rpm" ; \ fi @if [ ! -d .git -a -n "$(RHEL_LIKE)" ]; then \ rpmbuild -ba packaging/rhel/$(RHEL_MAJOR)/libreswan.spec ; \ fi @if [ ! -d .git -a -f /etc/fedora-release ]; then \ rpmbuild -ba packaging/fedora/libreswan.spec ; \ fi git-rpm: @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: @$(MAKE) --silent --directory packaging/debian showdebversion 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 get fixed not to use root .PHONY: deb deb: if [ -f /etc/devuan_version ]; then \ $(MAKE) --directory packaging/devuan ; \ else \ $(MAKE) --directory packaging/debian ; \ fi release: packaging/utils/makerelease local-install: # 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 libreswan-4.14/README.md000066400000000000000000000165321457372064200147300ustar00rootroot00000000000000# 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 XFRM IPsec stack. 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 to 5.x, as well as NetBSD and FreeBSD are supported platforms. Libreswan has been ported to Windows and OSX in the past as well. With effort, it can be compiled to run on Linux no-mmu systems as well. Most distributions have native packaged support for Libreswan. Libreswan is available for RHEL, Fedora, CentOS, 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 (unbound is build without event api, set USE_DNSSEC=false) For Fedora/RHEL8/CentOS8 yum install audit-libs-devel bison curl-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 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 (fipscheck is needed because the nss library is too old for USE_NSS_KDF=true) 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 The packaging/ directory is used to find the proper spce file for your distribution. Simply issue the command: make rpm You can also pick a specific spec file. 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: For Linux, 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, Openswan 2.x or older Libreswan versions to Libreswan 4.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. Note that for rpm based systems, the NSS directory changed from /etc/ipsec.d to /var/lib/ipsec/nss/ ## 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 #libreswan irc.libera.chat ## Bugs Bugs can be reported on the mailing list or using our bug tracking system, at https://github.com/libreswan/libreswan/issues ## 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.libera.chat 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 has been removed. Please use the XFRM stack. If you wish to have network interfaces like KLIPS had, please use the XFRMi interfaces via the ipsec-interface= keyword, or use the less capable VTI interface support. libreswan-4.14/README.nss000066400000000000000000000243271457372064200151340ustar00rootroot00000000000000 ######################################################################### # 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 /var/lib/ipsec/nss/. Older RHEL/Fedora/CentOS used /etc/ipsec.d/ but Debian/Ubuntu used /var/lib/ipsec/nss/ (the new default). The remainder of this file 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. 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:/var/lib/ipsec/nss/ 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/nssdir [--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:/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 "-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:/var/lib/ipsec/nss 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:/var/lib/ipsec/nss 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:/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:/var/lib/ipsec/nss 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-4.14/README.x509000066400000000000000000000000751457372064200150300ustar00rootroot00000000000000 See README.nss or check the wiki at https://libreswan.org/ libreswan-4.14/TRADEMARK000066400000000000000000000005531457372064200147020ustar00rootroot00000000000000 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-4.14/configs/000077500000000000000000000000001457372064200150725ustar00rootroot00000000000000libreswan-4.14/configs/Makefile000066400000000000000000000116711457372064200165400ustar00rootroot00000000000000# 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. # the man page source is generated MANPAGES += ipsec.conf.5 MANPAGES += ipsec.secrets.5 # different mode ipsec.secrets.INSTFLAGS = -m 0600 CONFFILES += ipsec.conf CONFFILES += ipsec.secrets LOGROTATECONFFILE += libreswan CONFDSUBDIR = policies CONFDSUBDIRFILES = clear clear-or-private private-or-clear private block portexcludes.conf ifndef top_srcdir include ../mk/dirs.mk endif include $(top_srcdir)/mk/config.mk include $(top_srcdir)/mk/targets.mk include $(top_srcdir)/mk/rules.mk include $(top_srcdir)/mk/manpages.mk local-base: $(CONFFILES) $(CONFDSUBDIRFILES) $(LOGROTATECONFFILE) local-clean-base: rm -f $(foreach file, $(CONFFILES) $(CONFDSUBDIRFILES) $(LOGROTATECONFFILE), $(builddir)/$(file)) local-install-base: $(CONFFILES) $(CONFDSUBDIRFILES) $(LOGROTATECONFFILE) @if test ! -d $(CONFDDIR) ; then \ mkdir -p $(CONFDDIR) ; \ chmod 0700 $(CONFDDIR) ; \ fi @if test ! -d $(CONFDDIR)/$(CONFDSUBDIR) ; then \ mkdir -p $(CONFDDIR)/$(CONFDSUBDIR) ; \ chmod 0700 $(CONFDDIR)/$(CONFDSUBDIR) ; \ fi @if test ! -d $(LOGROTATEDDIR) ; then \ mkdir -p $(LOGROTATEDDIR) ; \ fi @set -eu ; $(foreach file, $(CONFFILES), \ src=$(builddir)/$(file) ; \ dst=$(CONFDIR)/$(file) ; \ if [ ! -f $${dst} ]; then \ echo $${src} '->' $${dst} ; \ mkdir -p $(CONFDIR) ; \ $(INSTALL) $(INSTCONFFLAGS) $($(file).INSTFLAGS) $${src} $${dst} ; \ fi ; \ ) @set -eu ; $(foreach file, $(CONFFILES), \ src=$(builddir)/$(file) ; \ dst=$(EXAMPLECONFDIR)/$(file)-sample ; \ echo $${src} '->' $${dst} ; \ mkdir -p $(EXAMPLECONFDIR) ; \ $(INSTALL) $(INSTCONFFLAGS) $${src} $${dst} ; \ ) @set -eu ; $(foreach file, $(CONFDSUBDIRFILES), \ src=$(builddir)/$(file) ; \ dst=$(CONFDDIR)/$(CONFDSUBDIR)/$(file) ; \ if [ ! -f $${dst} ]; then \ echo $${src} '->' $${dst} ; \ $(INSTALL) $(INSTCONFFLAGS) $${src} $${dst} ; \ fi ; \ ) @set -eu ; $(foreach file, $(LOGROTATECONFFILE), \ src=$(builddir)/$(file) ; \ dst=$(LOGROTATEDDIR)/$(file) ; \ if [ ! -f $${dst} ]; then \ echo $${src} '->' $${dst} ; \ $(INSTALL) $(INSTCONFFLAGS) $${src} $${dst} ; \ fi ; \ ) @if test ! -d $(NSSDIR) ; then \ mkdir -p $(NSSDIR) ; \ chmod 0700 $(NSSDIR) ; \ fi @if test -z "$(DESTDIR)" -a -x /usr/sbin/selinuxenabled -a $(SBINDIR) != "$(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 ifeq ($(USE_AUTHPAM),true) @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 endif list-local-base: @set -eu ; $(foreach file, $(CONFFILES), \ echo $(CONFDIR)/$(file) ; \ ) @set -eu ; $(foreach file, $(CONFFILES), \ echo $(EXAMPLECONFDIR)/$(file)-sample ; \ ) @set -eu ; $(foreach file, $(CONFDSUBDIRFILES), \ echo $(CONFDDIR)/$(CONFDSUBDIR)/$${file} ; \ ) # Since man page is generated, override the default rule for # generating $(buildir)/$(MANPAGE).tmp from $(MANPAGE).xml xmlsources = d.ipsec.conf/order.txt $(builddir)/ipsec.conf.5.tmp: d.ipsec.conf/*.xml $(xmlsources) | $(builddir) missing=$$(find d.ipsec.conf -name '*.xml' | sort - $(xmlsources) | uniq -u) ; \ if test "$${missing}" != ""; then \ echo "$${missing}" ; \ exit 1 ; \ fi cat $(xmlsources) | xargs cat | $(TRANSFORM_VARIABLES) > $@.tmp mv $@.tmp $@ libreswan-4.14/configs/block.in000066400000000000000000000006131457372064200165140ustar00rootroot00000000000000# This file defines the set of network destinations for which # communication should never be allowed. # # One IPv4 or IPv6 CIDR per line, optionally specifying a further # narrowing of protocol, source port and destination port # # examples: # 10.0.1.0/24 # 2a03:6000:1004:1::/64 # # block some outgoing ssh to range # 10.0.1.0/24 tcp 0 22 # block all incoming ssh # 0.0.0.0/0 tcp 22 0 libreswan-4.14/configs/clear-or-private.in000066400000000000000000000016621457372064200206030ustar00rootroot00000000000000# This file defines the set of CIDRs (network/mask-length) to which # we will communicate in the clear, or, if the other side initiates IPSEC, # using encryption. This behaviour is also called "Opportunistic Responder". # One IPv4 or IPv6 CIDR per line. # This file defines the set of network destinations for which # communications will be in the clear, or if the other side initiates IPsec # to use, will be encrypted on their request. This behaviour is also called # "Opportunistic Responder". # # One IPv4 or IPv6 CIDR per line, optionally specifying a further # narrowing of protocol, source port and destination port # # examples: # encrypt all traffic to an IPv4 or IPv6 host or subnet if they request it # 10.0.1.0/24 # 10.1.1.1/32 # 2a03:6000:1004:1::/64 # # encrypt all smtp traffic to some host if they want to # 10.0.1.0/24 tcp 0 25 # encrypt all incoming smtp traffic from some host if they request it # 0.0.0.0/0 tcp 25 0 libreswan-4.14/configs/clear.in000066400000000000000000000006411457372064200165110ustar00rootroot00000000000000# This file defines the set of network destinations for which # communication should always be in the clear. # # One IPv4 or IPv6 CIDR per line, optionally specifying a further # narrowing of protocol, source port and destination port # # examples: # 10.0.1.0/24 # 2a03:6000:1004:1::/64 # # don't IPsec encrypt ssh to a range # 10.0.1.0/24 tcp 0 22 # don't IPsec encrypt any incoming ssh # 0.0.0.0/0 tcp 22 0 libreswan-4.14/configs/d.ipsec.conf/000077500000000000000000000000001457372064200173435ustar00rootroot00000000000000libreswan-4.14/configs/d.ipsec.conf/aggressive.xml000066400000000000000000000033371457372064200222320ustar00rootroot00000000000000 aggressive Use IKEv1 Aggressive Mode instead of IKEv1 Main Mode. This option has no effect when IKEv2 is used. Acceptable values are no (the default) or yes. When this option is enabled, IKEv1 Main Mode will no longer be allowed for this connection. The old name of this option was aggrmode. Aggressive Mode is less secure, and more vulnerable to Denial Of Service attacks. It is also vulnerable to brute force attacks with software such as ikecrack. It should not be used, and it should especially not be used with XAUTH and group secrets (PSK). If the remote system administrator insists on staying irresponsible, enable this option. Aggressive Mode is further limited to only proposals with one DH group as there is no room to negotiate the DH group. Therefore it is mandatory for Aggressive Mode connections that both ike= and phase2alg= options are specified with only one fully specified proposal using one DH group. The KE payload is created in the first exchange packet when using aggressive mode. The KE payload depends on the DH group used. This is why there cannot be multiple DH groups in IKEv1 aggressive mode. In IKEv2, which uses a similar method to IKEv1 Aggressive Mode, there is an INVALID_KE response payload that can inform the initiator of the responder's desired DH group and so an IKEv2 connection can actually recover from picking the wrong DH group by restarting its negotiation. libreswan-4.14/configs/d.ipsec.conf/ah.xml000066400000000000000000000026421457372064200204610ustar00rootroot00000000000000 ah A comma separated list of AH algorithms that will be offered/accepted when negotiating the Child SA. The general syntax is: AH = PROPOSAL[,PROPOSAL...] PROPOSAL = INTEG_ALGS[-DH_ALGS] INTEG_ALGS = INTEG_ALG[+INTEG_ALG...] DH_ALGS = DH_ALG[+DH_ALG...] During startup, ipsec_pluto 8 will log all supported AH algorithms. Specifying the DH algorithms explicitly is not recommended. When PFS is enabled, and the DH algorithms are omitted, each PROPOSAL will automatically include the DH algorithm negotiated during the IKE exchange. The default is not to use AH. If for some (invalid) reason you still think you need AH, please use esp with the null encryption cipher instead. For instance: ah=sha2_256+sha2_512 ah=sha2_256+sha2_512-dh14+dh19 If not specified, a secure set of defaults will be used. The program: ipsec algparse ah=... can be used to query these defaults. libreswan-4.14/configs/d.ipsec.conf/audit-log.xml000066400000000000000000000016471457372064200217620ustar00rootroot00000000000000 audit-log Whether pluto should produce Linux Auditing System log messages. If enabled, pluto will log start, stop and fail for the negotiation of IKE and IPsec SA's. The kernel will also log success and failures for actually adding and removing IPsec SA's from the kernel's SADB. Valid options are yes(the default) and no. On non-Linux systems, this option is ignored. If enabled but the kernel is lacking audit support, audit messages are not sent. If the kernel has audit support and using it fails, pluto will abort. Note that for compliance reasons, audit log messages contain the relevant IP addresses, even if logip=no. libreswan-4.14/configs/d.ipsec.conf/authby.xml000066400000000000000000000053711457372064200213670ustar00rootroot00000000000000 authby how the two security gateways should authenticate each other; the default value is rsasig,ecdsa which allows ECDSA with SHA-2 and RSA with SHA2 or SHA1. To limit this further, there are the options of ecdsa for ECDSA digital signatures using SHA-2, rsa-sha2 for RSASSA-PSS digital signatures based authentication with SHA2-256, rsa-sha2_384 for RSASSA-PSS digital signatures based authentication with SHA2-384, rsa-sha2_512 for RSASSA-PSS digital signatures based authentication with SHA2-512, rsa-sha1 for RSA-PKCSv1.5 digital signatures based authentication with SHA1, secret for shared secrets (PSK) authentication, secret|rsasig for either, never if negotiation is never to be attempted or accepted (useful for shunt-only conns), and null for null-authentication. If asymmetric authentication is requested, IKEv2 must be enabled, and the options leftauth= and rightauth= should be used instead of authby. For IKEv1, SHA2 based signatures are not defined and ECDSA is not implemented, so the default authby= value is rsa-sha1. Using authby=rsasig results in only rsa-sha1 as well. For IKEv2, using authby=rsasig means using rsa-sha2_512, rsa-sha2_384, rsa-sha2_256 and rsa-sha1, where rsa-sha1 will used only if RFC 7427 is not supported by the peer. As per RFC 8221, authby=rsa-sha1 is only supported in the old style, meaning RSA-PKCSv1.5. The SHA2 variants are only supported for the new style of RFC 7427, so authby=rsa-sha2 will use the new style. The default authby= will remove rsa-sha1 in the near future. It is strongly recommended that if certificates are used, the certificates and the authby= signature methods used are the same, as it increases interoperability and keeps the authentication of everything within one digital signature system. Digital signatures are superior in every way to shared secrets. Especially IKEv1 in Aggressive Mode is vulnerable to offline dictionary attacks and is performed routinely by at least the NSA on monitored internet traffic globally. The never option is only used for connections that do not actually start an IKE negotiation, such as type=passthrough connections. The auth method null is used for "anonymous opportunistic IPsec" and should not be used for regular pre-configured IPsec VPNs. libreswan-4.14/configs/d.ipsec.conf/auto.xml000066400000000000000000000023761457372064200210450ustar00rootroot00000000000000 auto what operation, if any, should be done automatically at IPsec startup; currently-accepted values are add (signifying an ipsec auto ), ondemand (signifying that plus an ipsec auto ), start (signifying that plus an ipsec auto ), and ignore (also the default) (signifying no automatic startup operation), and keep (signifying an add plus an attempt to keep the connection up once the remote peer brought it up). See the config setup discussion below. Relevant only locally, other end need not agree on it (but in general, for an intended-to-be-permanent connection, both ends should use auto=start to ensure that any reboot causes immediate renegotiation). The option ondemand used to be called route libreswan-4.14/configs/d.ipsec.conf/cisco-unity.xml000066400000000000000000000011751457372064200223370ustar00rootroot00000000000000 cisco-unity whether to send a CISCO_UNITY payload to the peer. Acceptable values are: no (the default) and yes. It is recommended to leave this option unset, unless the remote peer (Cisco client or server) requires it. This option does not modify local behaviour. It can be needed to connect as a client to a Cisco server. It can also be needed to act as a server for a Cisco client, which otherwise might send back an error DEL_REASON_NON_UNITY_PEER. libreswan-4.14/configs/d.ipsec.conf/clientaddrfamily.xml000066400000000000000000000007621457372064200234050ustar00rootroot00000000000000 clientaddrfamily the address family of the clients (subnets); currently the accepted values are ipv4 and ipv6. The default is to detect this based on the network IP addresses specified or the network IP addresses resolved, so this option is not needed, unless you specify names that resolve to both IPv4 and IPv6. libreswan-4.14/configs/d.ipsec.conf/compress.xml000066400000000000000000000013571457372064200217260ustar00rootroot00000000000000 compress whether IPComp compression of content is proposed on the connection (link-level compression does not work on encrypted data, so to be effective, compression must be done before encryption); acceptable values are yes and no (the default). For IKEv1, compress settings on both peers must match. For IKEv2, compression can only be suggested and a mismatched compress setting results in connection without compression. When set to yes, compression is negotiated for the DEFLATE compression algorithm. libreswan-4.14/configs/d.ipsec.conf/configsections.xml000066400000000000000000000015161457372064200231050ustar00rootroot00000000000000CONFIG SECTIONS At present, the only config section known to the IPsec software is the one named setup, which contains information used when the software is being started (see ipsec_setup8). Here's an example: config setup logfile=/var/log/pluto.log plutodebug=all Parameters are optional unless marked “(required)”. The currently-accepted parameter names in a config setup section are: libreswan-4.14/configs/d.ipsec.conf/configsectionsend.xml000066400000000000000000000000351457372064200235670ustar00rootroot00000000000000 libreswan-4.14/configs/d.ipsec.conf/connauto.xml000066400000000000000000000005401457372064200217120ustar00rootroot00000000000000CONN PARAMETERS: AUTOMATIC KEYING The following parameters are relevant to automatic keying via IKE. Unless otherwise noted, for a connection to work, in general it is necessary for the two ends to agree exactly on the values of these parameters. libreswan-4.14/configs/d.ipsec.conf/connautoend.xml000066400000000000000000000000521457372064200223770ustar00rootroot00000000000000 libreswan-4.14/configs/d.ipsec.conf/conngeneral.xml000066400000000000000000000005111457372064200223550ustar00rootroot00000000000000CONN PARAMETERS: GENERAL The following parameters are relevant to IKE automatic keying. Unless otherwise noted, for a connection to work, in general it is necessary for the two ends to agree exactly on the values of these parameters. libreswan-4.14/configs/d.ipsec.conf/conngeneralend.xml000066400000000000000000000017061457372064200230530ustar00rootroot00000000000000 If one or both security gateways are doing forwarding firewalling (possibly including masquerading), and this is specified using the firewall parameters, tunnels established with IPsec are exempted from it so that packets can flow unchanged through the tunnels. (This means that all subnets connected in this manner must have distinct, non-overlapping subnet address blocks.) This is done by the default updown script (see ipsec_pluto8). The implementation of this makes certain assumptions about firewall setup, and the availability of the Linux Advanced Routing tools. In situations calling for more control, it may be preferable for the user to supply his own updown script, which makes the appropriate adjustments for his system. libreswan-4.14/configs/d.ipsec.conf/connsections.xml000066400000000000000000000157511457372064200226030ustar00rootroot00000000000000DESCRIPTION The ipsec.conf file specifies most configuration and control information for the Libreswan IPsec subsystem. (The major exception is secrets for authentication; see ipsec.secrets5.) Its contents are not security-sensitive. Configurations can be added using this configuration file or by using ipsec whack directly. This means that technically, the ipsec.conf file is optional, but a few warnings might show up when this file is missing. ipsec.conf is a text file, consisting of one or more sections. White space followed by # followed by anything to the end of the line is a comment and is ignored, as are empty lines that are not within a section. A line that contains include and a file name, separated by white space, is replaced by the contents of that file, preceded and followed by empty lines. If the file name is not a full pathname, it is considered to be relative to the directory that contains the including file. Such inclusions can be nested. Only a single filename may be supplied, and it may not contain white space, but it may include shell wildcards (see sh1); for example: include /etc/ipsec.d/*.conf The intention of the include facility is mostly to permit keeping information on connections, or sets of connections, separate from the main configuration file. This permits such connection descriptions to be changed, copied to the other security gateways involved, etc., without having to constantly extract them from the configuration file and then insert them back into it. Note also the also and alsoflip parameters (described below) which permit splitting a single logical section (e.g. a connection description) into several distinct sections. The first significant line of the file may specify a version of this specification for backwards compatibility with freeswan and openswan. It is ignored and unused. For compatibility with openswan, specify: version 2 A section begins with a line of the form: type name where type indicates what type of section follows, and name is an arbitrary name that distinguishes the section from others of the same type. (Names must start with a letter and may contain only letters, digits, periods, underscores, and hyphens.) All subsequent non-empty lines that begin with white space are part of the section; comments within a section must begin with white space too. There may be only one section of a given type with a given name. Lines within the section are generally of the form      parameter=value (note the mandatory preceding white space). There can be white space on either side of the =. Parameter names follow the same syntax as section names, and are specific to a section type. Unless otherwise explicitly specified, no parameter name may appear more than once in a section. An empty value stands for the system default value (if any) of the parameter, i.e. it is roughly equivalent to omitting the parameter line entirely. A value may contain white space only if the entire value is enclosed in double quotes ("); a value cannot itself contain a double quote, nor may it be continued across more than one line. Numeric values are specified to be either an “integer” (a sequence of digits) or a “decimal number” (sequence of digits optionally followed by `.' and another sequence of digits). There is currently one parameter that is available in any type of section: also the value is a section name; the parameters of that section are appended to this section, as if they had been written as part of it. The specified section must exist, must follow the current one, and must have the same section type. (Nesting is permitted, and there may be more than one also in a single section, although it is forbidden to append the same section more than once.) This allows, for example, keeping the encryption keys for a connection in a separate file from the rest of the description, by using both an also parameter and an include line. (Caution, see BUGS below for some restrictions.) alsoflip can be used in a conn section. It acts like an also that flips the referenced section's entries left-for-right. Parameter names beginning with x- (or X-, or x_, or X_) are reserved for user extensions and will never be assigned meanings by IPsec. Parameters with such names must still observe the syntax rules (limits on characters used in the name; no white space in a non-quoted value; no newlines or double quotes within the value). All other as-yet-unused parameter names are reserved for future IPsec improvements. A section with name %default specifies defaults for sections of the same type. For each parameter in it, any section of that type that does not have a parameter of the same name gets a copy of the one from the %default section. There may be multiple %default sections of a given type, but only one default may be supplied for any specific parameter name. %default sections may not contain also or alsoflip parameters. Currently there are two types of section: a config section specifies general configuration information for IPsec, while a conn section specifies an IPsec connection. libreswan-4.14/configs/d.ipsec.conf/crl-strict.xml000066400000000000000000000012621457372064200221540ustar00rootroot00000000000000 crl-strict if not set, pluto is tolerant about missing or expired X.509 Certificate Revocation Lists (CRL's), and will allow peer certificates as long as they do not appear on an expired CRL. When this option is enabled, all connections with an expired or missing CRL will be denied. Active connections will be terminated at rekey time. This setup is more secure, but vulnerable to downtime if the CRL expires. Acceptable values are yes or no (the default). This option used to be called strictcrlpolicy. libreswan-4.14/configs/d.ipsec.conf/crlcheckinterval.xml000066400000000000000000000011711457372064200234100ustar00rootroot00000000000000 crlcheckinterval interval expressed in second units, for example crlcheckinterval=8h for 8 hours, after which pluto will fetch new Certificate Revocation List (CRL) from crl distribution points. List of used CRL distribution points are collected from CA certificates and end certificates. Loaded X.509 CRL's are verified to be valid and updates are imported to NSS database. If set to 0, which is also the default value if this option is not specified, CRL updating is disabled. libreswan-4.14/configs/d.ipsec.conf/curl-iface.xml000066400000000000000000000005251457372064200221010ustar00rootroot00000000000000 curl-iface The name of the interface that is used for CURL lookups. This is needed on rare situations where the interface needs to be forced to be different from the default interface used based on the routing table. libreswan-4.14/configs/d.ipsec.conf/curl-timeout.xml000066400000000000000000000003501457372064200225140ustar00rootroot00000000000000 curl-timeout The timeout for the curl library calls used to fetch CRL and OCSP requests. The default is 5s. libreswan-4.14/configs/d.ipsec.conf/ddos-ike-threshold.xml000066400000000000000000000006471457372064200235650ustar00rootroot00000000000000 ddos-ike-threshold The number of half-open IKE SAs before the pluto IKE daemon will be placed in busy mode. When in busy mode, pluto activates anti-DDoS counter measures. The default is 25000. See also ddos-mode and ipsec whack --ddos-XXX. libreswan-4.14/configs/d.ipsec.conf/ddos-mode.xml000066400000000000000000000013221457372064200217360ustar00rootroot00000000000000 ddos-mode The startup mode of the DDoS defense mechanism. Acceptable values are busy, unlimited or auto (the default). This option can also be given to the IKE daemon while running, for example by issuing ipsec whack --ddos--busy. When in busy mode, pluto activates anti-DDoS counter measures. Currently, counter measures consist of requiring IKEv2 anti-DDoS cookies on new incoming IKE requests, and a more aggressive cleanup of partially established or AUTH_NULL connections. libreswan-4.14/configs/d.ipsec.conf/decap-dscp.xml000066400000000000000000000010261457372064200220670ustar00rootroot00000000000000 decap-dscp Enable decapsulating the Differentiated Services Code Point (DSCP, formerly known as Terms Of Service (TOS)) bits. If these bits are set on the inner (encrypted) IP packets, these bits are set on the decrypted IP packets. Acceptable values are no (the default) or yes. Currently this feature is only implemented for the Linux XFRM stack. libreswan-4.14/configs/d.ipsec.conf/dns-match-id.xml000066400000000000000000000023001457372064200223300ustar00rootroot00000000000000 dns-match-id Whether to perform an additional DNS lookup and confirm the remote ID payload with the DNS name in the reverse DNS PTR record. Accepted values are no (the default) or yes. This check should be enabled when Opportunistic IPsec is enabled in a mode that is based on packet triggers (on-demand) using IPSECKEY records in DNS. Since in that case the IKE daemon pluto does not know the remote ID, it only knows the remote IP address, this option forces it to confirm the peer's proposed ID (and thus its public/private key) with its actual IP address as listed in the DNS. This prevents attacks where mail.example.com's IP address is taken over by a neighbour machine with a valid web.example.com setup. This check is not needed for certificate based Opportunistic IPsec, as "mail.example.com"s certificate does not have an entry for "web.example.com". It is also not needed for DNS server triggered Opportunistic IPsec, as in that case the IKE daemon pluto is informed of both the IP address, and the hostname/public key. libreswan-4.14/configs/d.ipsec.conf/dnssec.xml000066400000000000000000000021431457372064200213440ustar00rootroot00000000000000 dnssec-enable Whether pluto should perform dnssec validation using libunbound, provided libreswan was compiled with USE_DNSSEC. A value of yes (the default) means pluto should perform DNSSEC validation. Note that pluto reads the file /etc/resolv.conf to determine which nameservers to use. dnssec-rootkey-file The location of the DNSSEC root zone public key file. The default is /var/lib/unbound/root.key but this can be changed at compile time. dnssec-anchors The location of a file containing additional DNSSEC Trust Anchors. This can be used when a network is using split-DNS and the internal hierarchy is using DNSSEC trust anchors. There is no default value. libreswan-4.14/configs/d.ipsec.conf/dpdaction.xml000066400000000000000000000014171457372064200220350ustar00rootroot00000000000000 dpdaction When a DPD enabled peer is declared dead, what action should be taken. hold (default) means the eroute will be put into %hold status, while clear means the eroute and SA with both be cleared. restart means that ALL SAs to the dead peer will renegotiated. dpdaction=clear is really only useful on the server of a Road Warrior config. The value restart_by_peer has been obsoleted and its functionality moved into the regular restart action. libreswan-4.14/configs/d.ipsec.conf/dpddelay.xml000066400000000000000000000006271457372064200216600ustar00rootroot00000000000000 dpddelay Set the delay (in time units, defaults to seconds) between Dead Peer Detection (IKEv1 RFC 3706) or IKEv2 Liveness keepalives that are sent for this connection (default 0 seconds). Set to enable checking. If dpddelay is set, dpdtimeout also needs to be set. libreswan-4.14/configs/d.ipsec.conf/dpdtimeout.xml000066400000000000000000000007561457372064200222530ustar00rootroot00000000000000 dpdtimeout Set the length of time (in time units, defaults to seconds) that we will idle without hearing back from our peer. After this period has elapsed with no response and no traffic, we will declare the peer dead, and remove the SA (default 0 seconds). Set value bigger than dpddelay to enable. If dpdtimeout is set, dpddelay also needs to be set. libreswan-4.14/configs/d.ipsec.conf/dumpdir.xml000066400000000000000000000007031457372064200215310ustar00rootroot00000000000000 dumpdir in what directory should things started by setup (notably the Pluto daemon) be allowed to dump core? The default value is /var/run/pluto. When SELinux runs in enforced mode, changing this requires a similar change in the SELinux policy for the pluto daemon. libreswan-4.14/configs/d.ipsec.conf/enable-tcp.xml000066400000000000000000000017231457372064200221020ustar00rootroot00000000000000 enable-tcp Normally, IKE negotiation and ESP encapsulation happens over UDP. This option enables support for IKE and ESP over TCP as per RFC 8229. Acceptable values are no(the default), yes meaning only TCP will be used, or fallback meaning that TCP will be attempted only after negotiation over UDP failed. Since performance over TCP is much less, and TCP sessions are vulnerable to simply RST resets and MITM attacks causing the TCP connection to close, this option should really only be used in fallback mode. If used in fallback mode, it is recommend to reduce the retransmit-timeout from the default 60s to a much shorter value such as 10s, so that one does not have to wait a minute for the TCP fallback to be attempted. libreswan-4.14/configs/d.ipsec.conf/encapsulation.xml000066400000000000000000000017151457372064200227360ustar00rootroot00000000000000 encapsulation In some cases, for example when ESP packets are filtered or when a broken IPsec peer does not properly recognise NAT, it can be useful to force RFC-3948 encapsulation. In other cases, where IKE is NAT'ed but ESP packets can or should flow without encapsulation, it can be useful to ignore the NAT-Traversal auto-detection. encapsulation=yes forces the NAT detection code to lie and tell the remote peer that RFC-3948 encapsulation (ESP in port 4500 packets) is required. encapsulation=no ignores the NAT detection causing ESP packets to send send without encapsulation. The default value of encapsulation=auto follows the regular outcome of the NAT auto-detection code performed in IKE. This option replaced the obsoleted forceencaps option. libreswan-4.14/configs/d.ipsec.conf/esn.xml000066400000000000000000000016401457372064200206530ustar00rootroot00000000000000 esn Whether or not to enable Extended Sequence Number (ESN) for the IPsec SA. This option is only implemented for IKEv2. ESN is typically used for very high-speed links (10Gbps or faster) where the standard 32 bit sequence number is exhausted too quickly, causing IPsec SA's rekeys to happen too often. Accepted values are either (the default), yes and no. If either is specified as an initiator, the responder will make the choice. As a responder, if either is received, yes is picked. If replay-window is set to 0, ESN is disabled as some (most?) IPsec stacks won't support ESN in such a configuration. libreswan-4.14/configs/d.ipsec.conf/esp.xml000066400000000000000000000030501457372064200206520ustar00rootroot00000000000000 esp Specifies the algorithms that will be offered/accepted when negotiating a a Child SA. The general syntax is: ESP = PROPOSAL[,PROPOSAL...] PROPOSAL = ENCRYPT_ALGS[-INTEG_ALGS[-DH_ALGS]] ENCRYPT_ALGS = ENCRYPT_ALG[+ENCRYPT_ALG...] INTEG_ALGS = INTEG_ALG[+INTEG_ALG...] DH_ALGS = DH_ALG[+DH_ALG...] During startup, ipsec_pluto 8 will log all supported ESP algorithms. Specifying the DH algorithms explicitly is not recommended. When PFS is enabled, and the DH algorithms are omitted, each PROPOSAL will automatically include the DH algorithm negotiated during the IKE exchange. AEAD algorithms such as AES_GCM and AES_CCM no not require a separate integrity algorithm. For example esp=aes_gcm256 or esp=aes_ccm. For instance: esp=aes_gcm,aes128+aes256-sha2_512+sha2_256-dh14+dh19 esp=aes128-sha2_512-dh14+dh19 If not specified, a secure set of defaults will be used. The program: ipsec algparse esp=... can be used to query these defaults. libreswan-4.14/configs/d.ipsec.conf/exampleleftright.xml000066400000000000000000000047341457372064200234410ustar00rootroot00000000000000CONN SECTIONS A conn section contains a connection specification, defining a network connection to be made using IPsec. The name given is arbitrary, and is used to identify the connection to ipsec_auto8 Here's a simple example: conn snt left=10.11.11.1 leftsubnet=10.0.1.0/24 leftnexthop=172.16.55.66 leftsourceip=10.0.1.1 right=192.168.22.1 rightsubnet=10.0.2.0/24 rightnexthop=172.16.88.99 rightsourceip=10.0.2.1 keyingtries=%forever A note on terminology... In automatic keying, there are two kinds of communications going on: transmission of user IP packets, and gateway-to-gateway negotiations for keying, rekeying, and general control. The data path (a set of “IPsec SAs”) used for user packets is herein referred to as the “connection”; the path used for negotiations (built with “ISAKMP SAs”) is referred to as the “keying channel”. To avoid trivial editing of the configuration file to suit it to each system involved in a connection, connection specifications are written in terms of left and right participants, rather than in terms of local and remote. Which participant is considered left or right is arbitrary; IPsec figures out which one it is being run on based on internal information. This permits using identical connection specifications on both ends. There are cases where there is no symmetry; a good convention is to use left for the local side and right for the remote side (the first letters are a good mnemonic). Many of the parameters relate to one participant or the other; only the ones for left are listed here, but every parameter whose name begins with left has a right counterpart, whose description is the same but with left and right reversed. Parameters are optional unless marked “(required)” libreswan-4.14/configs/d.ipsec.conf/failureshunt.xml000066400000000000000000000006121457372064200225750ustar00rootroot00000000000000 failureshunt what to do with packets when negotiation fails. The default is none: no shunt; passthrough, drop, and reject have the obvious meanings. libreswan-4.14/configs/d.ipsec.conf/fake-strongswan.xml000066400000000000000000000012441457372064200231770ustar00rootroot00000000000000 fake-strongswan whether to send a STRONGSWAN Vendor ID payload to the peer. Acceptable values are: no (the default) and yes. This used to be required because strongswan rejects certain proposals with private use numbers such as esp=twofish or esp=serpent unless it receives a strongswan vendorid by the peer. This option sends such an (unversioned) vendor id. Note that libreswan and strongswan no longer support twofish or serpent, so enabling this option likely will no longer do anything. libreswan-4.14/configs/d.ipsec.conf/fragmentation.xml000066400000000000000000000020121457372064200227160ustar00rootroot00000000000000 fragmentation Whether or not to allow IKE fragmentation. Valid values are yes, (the default), no or force. IKEv1 fragmentation capabilities are negotiated via a well-known private vendor id. IKEv2 fragmentation support is implemented using RFC 7383. If pluto does not receive the fragmentation payload, no IKE fragments will be sent, regardless of the fragmentation= setting. When set to yes, IKE fragmentation will be attempted on the first re-transmit of an IKE packet of a size larger then 576 bytes for IPv4 and 1280 bytes for IPv6. If fragmentation is set to force, IKE fragmentation is used on initial transmits of such sized packets as well. When we have received IKE fragments for a connection, pluto behaves as if in force mode. libreswan-4.14/configs/d.ipsec.conf/global-redirect.xml000066400000000000000000000030711457372064200231250ustar00rootroot00000000000000 global-redirect Whether to send requests for the remote peer to redirect IKE/IPsec SA's during IKE_SA_INIT. Valid options are no (the default), yes and auto, where auto means that the requests will be sent if DDoS mode is active (see ddos-mode). If set, the option global-redirect-to= must also be set to indicate where to redirect peers to. For specific connection redirection after IKE SA authentication, see the send-redirect= and redirect-to= options. This configuration can be changed at runtime via the ipsec whack --global-redirect command. global-redirect-to Where to send remote peers to via the global-redirect option. This can be a list, or a single entry, of IP addresses or hostnames (FQDNs). If there is a list of entries, they must be separated with comma's. One specified entry means all peers will be redirected to it, while multiple specified entries means peers will be evenly distributed across the specified servers. This configuration can be changed at runtime via the ipsec whack --global-redirect-to command. libreswan-4.14/configs/d.ipsec.conf/head.xml000066400000000000000000000014421457372064200207670ustar00rootroot00000000000000 PaulWoutersdocumenter IPSEC.CONF 5 12 Dec 2012 libreswan Executable programs ipsec.conf IPsec configuration and connections libreswan-4.14/configs/d.ipsec.conf/hostaddrfamily.xml000066400000000000000000000011571457372064200231030ustar00rootroot00000000000000 hostaddrfamily the address family of the hosts; currently the accepted values are ipv4 and ipv6. The default is to detect this based on the IP addresses specified or the IP addresses resolved, so this option is not needed, unless you specify hostnames that resolve to both IPv4 and IPv6. This option used to be named connaddrfamily but its use was broken so it was obsoleted in favour or using the new hostaddrfamily and clientaddrfamily. libreswan-4.14/configs/d.ipsec.conf/ignore-peer-dns.xml000066400000000000000000000015631457372064200230700ustar00rootroot00000000000000 ignore-peer-dns whether to ignore received DNS configuration. Acceptable values are: no (the default) and yes. Normally, when a roadwarrior connects to a remote VPN, the remote VPN server sends a list of DNS domains and DNS nameserver IP addresses that the roadwarrior can use to reach internal only resources through the VPN. This option allows the roadwarrior to ignore the server's suggestion. The roadwarrior will normally use this information to update the DNS resolving process. What is changed depends on the detected DNS configuration. It can modify /etc/resolv.conf directly, or reconfigure a locally running DNS server (unbound, knot, stubby or systemd-resolved) or inform NetworkManager. libreswan-4.14/configs/d.ipsec.conf/ike-socket.xml000066400000000000000000000024111457372064200221210ustar00rootroot00000000000000 ike-socket-bufsize Set the IKE socket buffer size. Default size is determined by the OS (as of writing, this seems to be set to 212992. On Linux this is visible via /proc/sys/net/core/rmem_default and /proc/sys/net/core/wmem_default. On Linux, this option uses SO_RCVBUFFORCE and SO_SNDBUFFORCE so that it can override rmem_max/wmem_max values of the OS. This requires CAP_NET_ADMIN (which is also required for other tasks). This option can also be toggled on a running system using ipsec whack --ike-socket-bufsize bufsize. ike-socket-errqueue Whether to enable or disable receiving socket errors via IP_RECVERR. The default is enabled. This will cause the socket to receive, process and log socket errors, such as ICMP unreachable messages or Connection Refused messages. Disabling this only makes sense on very busy servers, and even then it might not make much of a difference. This option can also be toggled on a running system using ipsec whack --ike-socket-errqueue-toggle. libreswan-4.14/configs/d.ipsec.conf/ike.xml000066400000000000000000000117261457372064200206440ustar00rootroot00000000000000 ike IKE encryption/authentication algorithm to be used for the connection (phase 1 aka ISAKMP SA or IKE SA). If this option is not set, the builtin defaults will be used. This is the preferred method, and allows for gradual automatic updates using the same configuration. Some distributions, such as Fedora and RHEL/CentOS, use a System Wide Crypto Policy that sets the default ike= (and esp=) lines. Specifying your own ike= line means overriding all these system or software recommended defaults, but can be necessary at times. Note that libreswan does not support using a PRF algorithm that is different from the INTEGRITY (hash) algorithm by design. The format is "cipher-hash;modpgroup, cipher-hash;modpgroup, ..." Any omitited option will be filled in with all allowed default values. Multiple proposals are separated by a comma. If an ike= line is specified, no other received proposals will be accepted than those specified on the IKE line. Some examples are ike=3des-sha1,aes-sha1, ike=aes, ike=aes_ctr, ike=aes_gcm256-sha2, ike=aes128-md5;modp2048, ike=aes256-sha2;dh19, ike=aes128-sha1;dh22, ike=3des-md5;modp1024,aes-sha1;modp1536. IKEv2 allows combining elements into a single proposal. These can be specified by using the + symbol. An example is: ike=aes_gcm+chacha20_poly1305;dh14+dh19,aes+3des-sha2+sha1;dh14. Note that AEAD algorithms (aes_gcm, aes_ccm, chacha20_poly1305) and non-AEAD algorithms (aes, 3des) cannot be combined into a single proposal. To support aes and aes_gcm, two proposals separated by a comma must be used. The default IKE proposal depends on the version of libreswan used. It follow the recommendations of RFC4306, RFC7321 and as of this writing their successor draft documents RFC4306bis and RFC7321bis. As for libreswan 3.32, SHA1 and MODP1536(dh5) are still allowed per default for backwards compatibility, but 3DES and MODP1024(dh2) are not allowed per default. As of libreswan 4.x, modp1024(dh2) support is no longer compiled in at all. For IKEv2, the defaults include AES, AES-GCM, DH14 and stronger, and SHA2. The default key size is 256 bits. The default AES_GCM ICV is 16 bytes. Note that AES-GCM is an AEAD algorithm, meaning that it performs encryption+authentication in one step. This means that AES-GCM must not specify an authentication algorithm. However, for IKE it does require a PRF function, so the second argument to an AEAD algorithm denotes the PRF. So ike=aes_gcm-sha2 means propose AES_GCM with SHA2 as the prf. Note that for phase2alg, there is no prf, so AES-GCM is specified for ESP as esp=aes_gcm-null. The AES-GCM and AES-CCM algorithms support 8,12 and 16 byte ICV's. These can be specified using a postfix, for example aes_gcm_a (for 8), aes_gcm_b (for 12) and aes_gcm_c (for 16). The default (aes_gcm without postfix) refers to the 16 byte ICV version. It is strongly recommended to NOT use the 8 or 12 byte versions of GCM or CCM. These versions are NOT included in the default and will be removed in a future version, following the recommendation of RFC 8247 or it successor. Weak algorithms are regularly removed from libreswan. Currently, 1DES and modp768(DH1) have been removed and modp1024(DH2) has been disabled at compile time. Additionally, MD5 and SHA1 will be removed within the next few years. Null encryption is available, and should only be used for testing or benchmarking purposes. Please do not request for insecure algorithms to be re-added to libreswan. IKEv1 has been disabled per default, and will soon no longer be compiled in by default. For all Diffie-Hellman groups, the "dh" keyword can be used instead of the "modp" keyword. For example ike=3des-sha1;dh19. Diffie-Hellman groups 19,20 and 21 from RFC-5903 are supported. Curve25519 from RFC-8031 is supported as "dh31". Curve448 and GOST DH groups are not yet supported in libreswan because these are not supported yet in the NSS crypto library. Diffie-Hellman groups 22, 23 and 24 from RFC-5114 are implemented but not compiled in by default. These DH groups are extremely controversial and MUST NOT be used unless forced (administratively) by the other party. This is further documented in RFC 8247, but the summary is that it cannot be proven that these DH groups do not contain a cryptographic trapdoor (a backdoor by the USG who provided these primes without revealing the seeds and generation process used). The modp syntax will be removed in favour of the dh syntax in the future libreswan-4.14/configs/d.ipsec.conf/ikelifetime.xml000066400000000000000000000011061457372064200223520ustar00rootroot00000000000000 ikelifetime how long the keying channel of a connection (buzzphrase: “IKE SA” or “Parent SA”) should last before being renegotiated; acceptable values as for salifetime. The default as of version 4.2 is 8h, before that it was 1h. The maximum is 24h. The two-ends-disagree case is similar to that of salifetime. libreswan-4.14/configs/d.ipsec.conf/ikepad.xml000066400000000000000000000017641457372064200213320ustar00rootroot00000000000000 ikepad Whether or not to pad IKEv1 messages to a multiple of 4 bytes. Valid values are yes, (the default) and no. IKE padding is allowed in IKEv1 but has been known to cause interoperability issues. The ikepad= option can be used to disable IKEv1 padding. This used to be required for some devices (such as Checkpoint in Aggressive Mode) that reject padded IKEv1 packets. A bug was fixed in libreswan 3.25 that applied wrong IKE padding in XAUTH, so it is suspected that Checkpoint padding issue bas been resolved. And this option should not be needed by anyone. In IKEv2, no padding is allowed, and this option has no effect. If you find a device that seems to require IKE padding, please contact the libreswan developers. This option should almost never be enabled and might be removed in a future version. libreswan-4.14/configs/d.ipsec.conf/ikev1-policy.xml000066400000000000000000000010761457372064200224050ustar00rootroot00000000000000 ikev1-policy What to do with received IKEv1 packets. Valid options are accept (default), reject which will reply with an error, and drop which will silently drop any received IKEv1 packet. If this option is set to drop or reject, an attempt to load an IKEv1 connection will fail, as these connections would never be able to receive a packet for processing. libreswan-4.14/configs/d.ipsec.conf/ikev1-secctx-attr-type.xml000066400000000000000000000012701457372064200243220ustar00rootroot00000000000000 ikev1-secctx-attr-type The value for the IKEv1 IPsec SA security context attribute identifier that is used for Labeled IPsec. Defaults to the private use IANA value 32001 from the IPsec SA attributes registry. Old openswan versions might still be using the (stolen) value 10, which has since been assigned by IANA for something else. Other values are not recommended unless IANA assigns an actual value for this option. Labeled IPsec using IKEv2 does not use this option, it only uses an IANA allocated Notify number. See also policy-label. libreswan-4.14/configs/d.ipsec.conf/ikev2.xml000066400000000000000000000013671457372064200211140ustar00rootroot00000000000000 ikev2 Whether to use IKEv2 (RFC 7296) or IKEv1 (RFC 4301). Currently the accepted values are yes (the default), signifying only IKEv2 is accepted, or no, signifying only IKEv1 is accepted. Previous versions allowed the keywords propose or permit that would allow either IKEv1 or IKEv2, but this is no longer supported. The permit option is interpreted as no and the propose option is interpreted as yes. Older versions also supported keyword insist which is now interpreted as yes. libreswan-4.14/configs/d.ipsec.conf/initial-contact.xml000066400000000000000000000012511457372064200231460ustar00rootroot00000000000000 initial-contact whether to send an INITIAL_CONTACT payload to the peer we are initiating to, if we currently have no IPsec SAs up with that peer. Acceptable values are: yes (the default) and no. It is recommended to leave this option set, unless multiple clients with the same identity are expected to connect using the same subnets and should operate at the same time. Or if a reconnecting client should not delete its old instance (eg perhaps it is still running). This is unlikely to be true. libreswan-4.14/configs/d.ipsec.conf/ipsec-interface.xml000066400000000000000000000063571457372064200231410ustar00rootroot00000000000000 ipsec-interface Create or use an existing virtual interface ipsecXXX for "Routing based VPNs" (as opposed to "Policy based VPNs"). Valid options are yes, no or a number. When using a number, the IPsec interface created and/or used will use that number as part of the interface name. For example setting ipsec-interface=5 will create and/or use the ipsec5 interface. The value 0 cannot be used and is interpreted as no. The value yes is interpreted as the number 1, and thus will use the interface named ipsec1. An IP address can be configured for this interface via the interface-ip= option. The ipsec-interface is used to route outbound traffic that needs to be encrypted, and will decrypt inbound traffic that arrives on this interface. All traffic that is routed to this interface will be automatically encrypted providing the IPsec SA policy covers this traffic. Traffic not matching the IPsec SA will be dropped. Tools such as tcpdump, iptables, ifconfig and tools that need traffic counters can be used on all cleartext pre-encrypt and post-decrypt traffic on the device. When leftsubnet= is equal to rightsubnet=, the routing needs to be manged by an external routing daemon or manually by the administrator. This option is currently only supported on Linux kernels 4.19 or later when compiled with XFRMi support (CONFIG_XFRM_INTERFACE). The number of the ipsecX device corresponds with the XFRM IF_ID policy option of the IPsec SA in the Linux kernel. On Linux, XFRMi interfaces can be managed by libreswan automatically or can be preconfigured on the system using the existing init system or via networking tools such as systemd-networkd and NetworkManager. The _updown script handles certain Linux specific interfaces settings required for proper functioning, such as forwarding and routing rules for IPsec traffic. The ipsec-interface=0 will create an interface with the same name as the old KLIPS interface, ipsec0. This interface name should only be used when required for migration from KLIPS to XFRM interfaces. Since XFRM IF_ID and marking cannot use 0, this is mapped to 16384. This means that the devices ipsec0 and ipsec16384 cannot both be in use. interface-ip= NOTE: This option is currently not implemented pending pluto IP address reference counting. The IP address and netmask to configure on a virtual device (eg ipsecXXX). This is often used when building Routing based IPsec tunnels using transport mode and GRE, but can also be useful in other scenarios. Currently requires ipsec-interface=. See also leftvti= for cnofiguring IP addresses when using VTI. libreswan-4.14/configs/d.ipsec.conf/ipsec-max-bytes.xml000066400000000000000000000037111457372064200231010ustar00rootroot00000000000000 ipsec-max-bytes how many bytes can be sent, or how many bytes can be received on an IPsec SA instance for a connection; acceptable values are an integer optionally followed by KiB, MiB, GiB, TiB, PiB or EiB to signify kilobytes, megabytes, gigabytes, terabytes, petabytes or exabytes. An IPsec SA contains two keys, one for inbound and one for outbound traffic. The ipsec-max-bytes sets two limits on each of these keys: the hard limit which is the total number of bytes that a given key can encrypt, and the soft limit which is the number of bytes that can be encrypted before a renegotiation of the IPsec SA is initiated. Normally the renegotation (via the IKE SA) is completed before the ipsec-max-bytes value is reached. Pluto sets the the original initiator's soft limit to 25% of ipsec-max-bytes (with 12% fuzz) and on the original responder's soft limit to 50% of ipsec-max-bytes (with 12% fuzz). This way the original initiator hopefully is the one initiating the renegotiation of the IPsec SA. This option is not negotiated between IKE peers. Each end of the IPsec SA sets their own limits independently. The default (hard limit) is 2^63 bytes. The original initiator's soft limit is 2^61 bytes (approx.) and the original responder's soft limit is 2^62 bytes (approx.). libreswan-4.14/configs/d.ipsec.conf/ipsec-max-packets.xml000066400000000000000000000010301457372064200233750ustar00rootroot00000000000000 ipsec-max-packets how many packets can be sent/received on a particular instance of a connection (a set of encryption/authentication keys for user packets) , from successful negotiation to expiry. Default values and caveats are the same as for ipsec-max-bytes. This option uses a prefix without "B" for bytes. libreswan-4.14/configs/d.ipsec.conf/ipsecdir.xml000066400000000000000000000042031457372064200216660ustar00rootroot00000000000000 ipsecdir Specifies a directory for administrator-controlled configuration files and directories. The default value is /etc/ipsec.d. It may contain the following files and directories: passwd (optional) for XAUTH support if not using PAM (this file should not be world-readable). See README.XAUTH for more information. nsspassword (optional) passwords needed to unlock the NSS database in @IPSEC_NSSDIR@ (this file should not be world-readable). See README.nss for more information. policies/ a directory containing policy group configuration information. See POLICY GROUP FILES in this document for more information. cacerts/ DEPRECATED: a directory to store trust anchors (root certificate authority certificates). The preferred (and default) approach is to store CA certs in the NSS database instead. See README.nss for more information. crls/ DEPRECATED: a directory to store certificate revocation lists. The preferred (and default) approach is to store CRLs in the NSS database instead. See README.nss for more information. When SELinux runs in enforced mode, changing this requires a similar change in the SELinux policy for the pluto daemon. libreswan-4.14/configs/d.ipsec.conf/keep-alive.xml000066400000000000000000000004671457372064200221160ustar00rootroot00000000000000 keep-alive The delay (in seconds) for NAT-T keep-alive packets, if these are enabled using nat-keepalive This parameter may eventually become per-connection. libreswan-4.14/configs/d.ipsec.conf/keyexchange.xml000066400000000000000000000003661457372064200223650ustar00rootroot00000000000000 keyexchange method of key exchange; the default and currently the only accepted value is ike libreswan-4.14/configs/d.ipsec.conf/keyingtries.xml000066400000000000000000000021341457372064200224220ustar00rootroot00000000000000 keyingtries how many attempts (a whole number or %forever) should be made to negotiate a connection, or a replacement for one, before giving up (default %forever). The value %forever or 0 means to keep trying forever. For Opportunistic Encryption connections, a keyingtries value of %forever or 0 is set to 1 and a warning message will be logged. This is because an expired failureshunt triggers new keyingtries on-demand later, when there is traffic. This prevents accumulating an infinite amount of attempts to peers that do not support Opportunistic Encryption. For Opportunistic, a keyingtries value of > 1 is allowed but currently not recommended. The meaning of failureshunt= is unclear when there is continued (failed) keying happening with a negotiationshunt installed. Relevant only locally, other end need not agree on it. libreswan-4.14/configs/d.ipsec.conf/labeled-ipsec.xml000066400000000000000000000004551457372064200225620ustar00rootroot00000000000000 labeled-ipsec This option is obsolete. To enable labeled IPsec, setting the policy-label= is enough. See also policy-label= and secctx-attr-type= libreswan-4.14/configs/d.ipsec.conf/left.xml000066400000000000000000000043411457372064200210210ustar00rootroot00000000000000 left (required) the IP address or DNS hostname of the left participant's public-network interface, Currently, IPv4 and IPv6 IP addresses are supported. If a DNS hostname is used, it will be resolved to an IP address on load time, and whenever a connection is rekeying or restarting (such as when restarted via a DPD failure detection). This allows one to use a DNS hostname when the endpoint is on a dynamic IP address. There are several magic values. If it is %defaultroute, left will be filled in automatically with the local address of the default-route interface (as determined at IPsec startup time); this also overrides any value supplied for leftnexthop. (Either left or right may be %defaultroute, but not both.) The value %any signifies an address to be filled in (by automatic keying) during negotiation. The value %opportunistic signifies that both left and leftnexthop are to be filled in (by automatic keying) from DNS data for left's client. The value can also contain the interface name, which will then later be used to obtain the IP address from to fill in. For example %ppp0. The values %group and %opportunisticgroup makes this a policy group conn: one that will be instantiated into a regular or opportunistic conn for each CIDR block listed in the policy group file with the same name as the conn. If using IP addresses in combination with NAT, always use the actual local machine's (NATed) IP address, and if the remote (eg right=) is NATed as well, the remote's public (not NATed) IP address. Note that this makes the configuration no longer symmetrical on both sides, so you cannot use an identical configuration file on both hosts. libreswan-4.14/configs/d.ipsec.conf/leftaddresspool.xml000066400000000000000000000030011457372064200232510ustar00rootroot00000000000000 leftaddresspool address pool from where the IKEv1 ModeCFG or IKEv2 server can assign IP addresses to clients. When configured as a server, using leftxauthserver=yes this option specifies the address pool from which IP addresses are taken to assign the clients. The syntax of the address pool specifies a range (not a CIDR) for IPv4 and CIDR for IPv6, in the following syntax: rightaddresspool=192.168.1.100-192.168.1.200 or rightaddresspool=2001:db8:0:3:1::/97 Generally, the rightaddresspool= option will be accompanied by rightxauthclient=yes, leftxauthserver=yes and leftsubnet=0.0.0.0/0 option. When leftaddresspool= is specified, the connection may not specify either leftsubnet= or leftsubnets=. Address pools are fully allocated when the connection is loaded, so the ranges should be sane. For example, specifying a range rightaddresspool=10.0.0.0-11.0.0.0 will lead to massive memory allocation. Address pools specifying the exact same range are shared between different connections. Different addresspools should not be defined to partially overlap. libreswan-4.14/configs/d.ipsec.conf/leftauth.xml000066400000000000000000000035401457372064200217030ustar00rootroot00000000000000 leftauth How the security gateways will authenticate to the other side in the case of asymmetric authentication; acceptable values are rsasig or rsa for RSA Authentication with SHA-1, rsa-sha2 for RSA-PSS digital signatures based authentication with SHA2-256, rsa-sha2_384 for RSA-PSS digital signatures based authentication with SHA2-384, rsa-sha2_512 for RSA-PSS digital signatures based authentication with SHA2-512, ecdsa for ECDSA digital signatures based authentication, secret for shared secrets (PSK) authentication and null for null-authentication. There is no default value - if unset, the symmetrical authby= keyword is used to determine the authentication policy of the connection. Asymmetric authentication is only supported with IKEv2. If symmetric authentication is required, use authby= instead of leftauth and rightauth. If leftauth is set, rightauth must also be set and authby= must not be set. Asymmetric authentication cannot use secret (psk) on one side and null on the other side - use psk on both ends instead. When using EAPONLY authentication, which omits the regular IKEv2 AUTH payload, leftauth= (or rightauth=) should be set to eaponly. Be aware that the symmetric keyword is authby= but the asymmetric keyword is leftauth and rightauth (without the "by"). libreswan-4.14/configs/d.ipsec.conf/leftautheap.xml000066400000000000000000000011021457372064200223610ustar00rootroot00000000000000 leftautheap Whether the security gateways will authenticate uing an EAP method. Acceptable values are none (the default) and tls for EAPTLS. If EAP is the only authentication method, set leftauth=none in addition to leftautheap=tls=. The EAP authentication mechanisms are only available for IKEv2 based connections. libreswan-4.14/configs/d.ipsec.conf/leftca.xml000066400000000000000000000013071457372064200213240ustar00rootroot00000000000000 leftca specifies the authorized Certificate Authority (CA) that signed the certificate of the peer. If undefined, it defaults to the CA that signed the certificate specified in leftcert. The special rightca=%same is implied when not specifying a rightca and means that only peers with certificates signed by the same CA as the leftca will be allowed. This option is only useful in complex multi CA certificate situations. When using a single CA, it can be safely omitted for both left and right. libreswan-4.14/configs/d.ipsec.conf/leftcat.xml000066400000000000000000000013511457372064200215070ustar00rootroot00000000000000 leftcat Whether to perform Client Address Translation ("CAT") when using Opportunistic IPsec behind NAT. Accepted values are no (the default) and yes. This option should only be enabled on the special Opportunistic IPsec connections, usually called "private" and "private-or-clear". When set, this option causes the given addresspool IP from the remote peer to be NATed with iptables. It will also install an additional IPsec SA policy to cover the pre-NAT IP. See the Opportunistic IPsec information on the libreswan website for more information and examples. libreswan-4.14/configs/d.ipsec.conf/leftcert.xml000066400000000000000000000005131457372064200216740ustar00rootroot00000000000000 leftcert If you are using leftrsasigkey=%cert this defines the certificate nickname of your certificate in the NSS database. This can be on software or hardware security device. libreswan-4.14/configs/d.ipsec.conf/leftckaid.xml000066400000000000000000000003411457372064200220110ustar00rootroot00000000000000 leftckaid The hex CKAID of the X.509 certificate. Certificates are stored in the NSS database. libreswan-4.14/configs/d.ipsec.conf/leftfirewall.xml000066400000000000000000000002751457372064200225510ustar00rootroot00000000000000 leftfirewall This option is obsolete and should not used anymore. libreswan-4.14/configs/d.ipsec.conf/leftid.xml000066400000000000000000000034611457372064200213400ustar00rootroot00000000000000 leftid how the left participant should be identified for authentication; defaults to left. Can be an IP address or a fully-qualified domain name which will be resolved. If preceded by @, the value is used as a literal string and will not be resolved. To support opaque identifiers (usually of type ID_KEY_ID, such as used by Cisco to specify Group Name, use square brackets, eg rightid=@[GroupName]. The magic value %fromcert causes the ID to be set to a DN taken from a certificate that is loaded. Prior to 2.5.16, this was the default if a certificate was specified. The magic value %none sets the ID to no ID. This is included for completeness, as the ID may have been set in the default conn, and one wishes for it to default instead of being explicitly set. The magic value %myid stands for the current setting of myid. This is set in config setup or by ipsec_whack8), or, if not set, it is the IP address in %defaultroute (if that is supported by a TXT record in its reverse domain), or otherwise it is the system's hostname (if that is supported by a TXT record in its forward domain), or otherwise it is undefined. When using certificate based ID's, one need to specify the full RDN, optionally using wildcard matching (eg CN='*'). If the RDN contains a comma, this can be masked using a comma (eg OU='Foo,, Bar and associates') libreswan-4.14/configs/d.ipsec.conf/leftikeport.xml000066400000000000000000000004501457372064200224140ustar00rootroot00000000000000 leftikeport The UDP IKE port to listen on or send data to. This port cannot be 0 or 500. For TCP, see tcp-remoteport= libreswan-4.14/configs/d.ipsec.conf/leftmodecfgclient.xml000066400000000000000000000005161457372064200235450ustar00rootroot00000000000000 leftmodecfgclient Left is a Mode Config client. It can receive network configuration from the server. Acceptable values are yes or no (the default). libreswan-4.14/configs/d.ipsec.conf/leftmodecfgserver.xml000066400000000000000000000005111457372064200235700ustar00rootroot00000000000000 leftmodecfgserver Left is a Mode Config server. It can push network configuration to the client. Acceptable values are yes or no (the default). libreswan-4.14/configs/d.ipsec.conf/leftnexthop.xml000066400000000000000000000015761457372064200224360ustar00rootroot00000000000000 leftnexthop next-hop gateway IP address for the left participant's connection to the public network; defaults to %direct (meaning right). If the value is to be overridden by the left=%defaultroute method (see above), an explicit value must not be given. If that method is not being used, but leftnexthop is %defaultroute, the next-hop gateway address of the default-route interface will be used. The magic value %direct signifies a value to be filled in (by automatic keying) with the peer's address. Relevant only locally, other end need not agree on it. libreswan-4.14/configs/d.ipsec.conf/leftprotoport.xml000066400000000000000000000052121457372064200230100ustar00rootroot00000000000000 leftprotoport allowed protocols and ports over connection, also called Port Selectors. The argument is in the form protocol, which can be a number or a name that will be looked up in /etc/protocols, such as leftprotoport=icmp, or in the form of protocol/port, such as tcp/smtp. Ports can be defined as a number (eg. 25) or as a name (eg smtp) which will be looked up in /etc/services. A special keyword %any can be used to allow all ports of a certain protocol. The most common use of this option is for L2TP connections to only allow l2tp packets (UDP port 1701), eg: leftprotoport=17/1701. To filter on specific icmp type and code, use the higher 8 bits for type and the lower 8 bits for port. For example, to allow icmp echo packets (type 8, code 0) the 'port' would be 0x0800, or 2048 in decimal, so you configure leftprotoport=icmp/2048. Similarly, to allow ipv6-icmp Neighbour Discovery which has type 136 (0x88) and code 0(0x00) this becomes 0x8800 or in decimal 34816 resulting in leftprotoport=ipv6-icmp/34816 . Some clients, notably older Windows XP and some Mac OSX clients, use a random high port as source port. In those cases rightprotoport=17/%any can be used to allow all UDP traffic on the connection. Note that this option is part of the proposal, so it cannot be arbitrarily left out if one end does not care about the traffic selection over this connection - both peers have to agree. The Port Selectors show up in the output of ipsec eroute and ipsec auto --status eg:"l2tp": 193.110.157.131[@aivd.libreswan.org]:7/1701...%any:17/1701 This option only filters outbound traffic. Inbound traffic selection must still be based on firewall rules activated by an updown script. The variables $PLUTO_MY_PROTOCOL, $PLUTO_PEER_PROTOCOL, $PLUTO_MY_PORT, and $PLUTO_PEER_PORT are available for use in updown scripts. Older workarounds for bugs involved a setting of 17/0 to denote any single UDP port (not UDP port 0). Some clients, most notably OSX, uses a random high port, instead of port 1701 for L2TP. libreswan-4.14/configs/d.ipsec.conf/leftrsasigkey.xml000066400000000000000000000031721457372064200227440ustar00rootroot00000000000000 leftrsasigkey the left participant's public key for RSA signature authentication, in RFC 2537 format using ipsec_ttodata3 encoding. The magic value %none means the same as not specifying a value (useful to override a default). The value %dnsondemand (the default) means the key is to be fetched from DNS at the time it is needed. The value %dnsonload means the key is to be fetched from DNS at the time the connection description is read from ipsec.conf; currently this will be treated as %none if right=%any or right=%opportunistic. The value %dns is currently treated as %dnsonload but will change to %dnsondemand in the future. The identity used for the left participant must be a specific host, not %any or another magic value. The value %cert will load the information required from a certificate defined in %leftcert and automatically define leftid for you. Caution: if two connection descriptions specify different public keys for the same leftid, confusion and madness will ensue. libreswan-4.14/configs/d.ipsec.conf/leftsendcert.xml000066400000000000000000000017111457372064200225470ustar00rootroot00000000000000 leftsendcert This option configures when Libreswan will send X.509 certificates to the remote host. Acceptable values are yes|always (signifying that we should always send a certificate), sendifasked (signifying that we should send a certificate if the remote end asks for it), and no|never (signifying that we will never send a X.509 certificate). The default for this option is sendifasked which may break compatibility with other vendor's IPsec implementations, such as Cisco and SafeNet. If you find that you are getting errors about no ID/Key found, you likely need to set this to always. This per-conn option replaces the obsolete global nocrsend option. libreswan-4.14/configs/d.ipsec.conf/leftsourceip.xml000066400000000000000000000014561457372064200225770ustar00rootroot00000000000000 leftsourceip the IP address for this host to use when transmitting a packet to the other side of this link. Relevant only locally, the other end need not agree. This option is used to make the gateway itself use its internal IP, which is part of the leftsubnet, to communicate to the rightsubnet or right. Otherwise, it will use its nearest IP address, which is its public IP address. This option is mostly used when defining subnet-subnet connections, so that the gateways can talk to each other and the subnet at the other end, without the need to build additional host-subnet, subnet-host and host-host tunnels. Both IPv4 and IPv6 addresses are supported. libreswan-4.14/configs/d.ipsec.conf/leftsubnet.xml000066400000000000000000000026711457372064200222460ustar00rootroot00000000000000 leftsubnet private subnet behind the left participant, expressed as network/netmask (actually, any form acceptable to ipsec_ttosubnet3); Currently, IPv4 and IPv6 ranges are supported. if omitted, essentially assumed to be left/32, signifying that the left end of the connection goes to the left participant only It supports two magic shorthands vhost: and vnet:, which can list subnets in the same syntax as virtual-private. The value %priv expands to the networks specified in virtual-private. The value %no means no subnet. A common use for allowing roadwarriors to come in on public IPs or via accepted NATed networks from RFC1918 is to use leftsubnet=vhost:%no,%priv. The vnet: option can be used to allow RFC1918 subnets without hardcoding them. When using vnet the connection will instantiate, allowing for multiple tunnels with different subnets. libreswan-4.14/configs/d.ipsec.conf/leftsubnets.xml000066400000000000000000000015011457372064200224200ustar00rootroot00000000000000 leftsubnets specify multiple private subnets behind the left participant, expressed as { networkA/netmaskA, networkB/netmaskB [...] } If both a leftsubnets= and rightsubnets= are defined, all combinations of subnet tunnels will be established as IPsec tunnels. You cannot use leftsubnet= and leftsubnets= together. For examples see testing/pluto/multinet-*. Be aware that when using spaces as separator, that the entire option value needs to be in double quotes. libreswan-4.14/configs/d.ipsec.conf/leftupdown.xml000066400000000000000000000015631457372064200222610ustar00rootroot00000000000000 leftupdown what "updown" script to run to adjust routing and/or firewalling when the status of the connection changes (default ipsec _updown). May include positional parameters separated by white space (although this requires enclosing the whole string in quotes); including shell metacharacters is unwise. An example to enable routing when using the XFRM stack, one can use: leftupdown="ipsec _updown --route yes" To disable calling an updown script, set it to the empty string, eg leftupdown="" or leftupdown="%disabled". See ipsec_pluto8 for details. Relevant only locally, other end need not agree on it. libreswan-4.14/configs/d.ipsec.conf/leftusername.xml000066400000000000000000000006661457372064200225670ustar00rootroot00000000000000 leftusername The username associated with this connection. The username can be the IKEv2 XAUTH username, a GSSAPI username or IKEv2 CP username. For the XAUTH username, the XAUTH password can be configured in the ipsec.secrets file. This option was previously called leftxauthusername. libreswan-4.14/configs/d.ipsec.conf/leftvti.xml000066400000000000000000000011511457372064200215400ustar00rootroot00000000000000 leftvti the address/mask to configure on the VTI interface when vti-interface is set. It takes the form of network/netmask (actually, any form acceptable to ipsec_ttosubnet3); Currently, IPv4 and IPv6 ranges are supported. This option is often used in combination with routed based VPNs. libreswan-4.14/configs/d.ipsec.conf/leftxauthclient.xml000066400000000000000000000017271457372064200232770ustar00rootroot00000000000000 leftxauthclient Left is an XAUTH client. The xauth connection will have to be started interactively and cannot be configured using auto=start. Instead, it has to be started from the commandline using ipsec auto --up connname. You will then be prompted for the username and password. To setup an XAUTH connection non-interactively, which defeats the whole purpose of XAUTH, but is regularly requested by users, it is possible to use a whack command - ipsec whack --name baduser --ipsecgroup-xauth --xauthname badusername --xauthpass password --initiate The other side of the connection should be configured as rightxauthserver. Acceptable values are yes or no (the default). libreswan-4.14/configs/d.ipsec.conf/leftxauthserver.xml000066400000000000000000000016071457372064200233240ustar00rootroot00000000000000 leftxauthserver Left is an XAUTH server. This can use PAM for authentication or md5 passwords in /etc/ipsec.d/passwd. These are additional credentials to verify the user identity, and should not be confused with the XAUTH group secret, which is just a regular PSK defined in ipsec.secrets. The other side of the connection should be configured as rightxauthclient. XAUTH connections cannot rekey, so rekey=no should be specified in this conn. For further details on how to compile and use XAUTH, see README.XAUTH. Acceptable values are yes or no (the default). libreswan-4.14/configs/d.ipsec.conf/listen-tcp.xml000066400000000000000000000007351457372064200221540ustar00rootroot00000000000000 listen-tcp Whether the pluto IKE daemon should listen on the (pseudo) standard TCP port 4500. The value "no" is the current default, but this will be changed in the future to "yes". The TCP usage complies to RFC 8229 for IKE and ESP over TCP support. Connections can specify their own non-standard port using leftikeport=. libreswan-4.14/configs/d.ipsec.conf/listen-udp.xml000066400000000000000000000011311457372064200221450ustar00rootroot00000000000000 listen-udp Whether the pluto IKE daemon should listen on the standard UDP ports of 500 and 4500. The value "yes" means to listen on these ports, and is the default. This should almost never be disabled. In the rare case where it is known that only ever TCP or non-standard UDP ports will be used, this option can disable the standard UDP ports. Connections can specify their own non-standard port using leftikeport=. libreswan-4.14/configs/d.ipsec.conf/listen.xml000066400000000000000000000003221457372064200213600ustar00rootroot00000000000000 listen IP address to listen on, defaults to ANY. Currently only accepts one IP address. libreswan-4.14/configs/d.ipsec.conf/logappend.xml000066400000000000000000000013241457372064200220360ustar00rootroot00000000000000 logappend If pluto is instructed to log to a file using logfile=, this option determines whether the log file should be appended to or overwritten. Valid options are yes (the default) to append and no to overwrite. Since on modern systems, pluto is restarted by other daemons, such as systemd, this option should be left at its default yes value to preserve the log entries of previous runs of pluto. The option is mainly of use for running the test suite, which needs to create new log files from scratch. libreswan-4.14/configs/d.ipsec.conf/logfile.xml000066400000000000000000000004071457372064200215070ustar00rootroot00000000000000 logfile do not use syslog, but rather log to stderr, and direct stderr to the argument file. This option used to be called plutostderrlog= libreswan-4.14/configs/d.ipsec.conf/logip.xml000066400000000000000000000016511457372064200212020ustar00rootroot00000000000000 logip If pluto is instructed to log the IP address of incoming connections. Valid options are yes (the default) and no. Note that this only affects regular logging. Any enabled debugging via plutodebug= will still contain IP addresses of peers. This option is mostly meant for servers that want to avoid logging IP addresses of incoming clients. Other identifiable information might still be logged, such as ID payloads and X.509 certificate details. When using ID of type IP address, this option will not hide the actual IP address as part of the ID. Most deployments will not want to change this from the default. If logging of IP addresses is unwanted, audit-log=no should also be set. libreswan-4.14/configs/d.ipsec.conf/logtime.xml000066400000000000000000000010641457372064200215260ustar00rootroot00000000000000 logtime When pluto is directed to log to a file using logfile=, this option determines whether or not to log the current timestamp as prefix. Values are yes (the default) or no. The no value can be used to create logs without ephemeral timestamps, such as those created when running the test suite. This option used to be called plutostderrlogtime= libreswan-4.14/configs/d.ipsec.conf/mark.xml000066400000000000000000000023411457372064200210170ustar00rootroot00000000000000 mark If set, the MARK to set for the IPsec SA of this connection. The format of a CONNMARK is mark/mask. If the mask is left out, a default mask of 0xffffffff is used. A mark value of -1 means to assign a new global unique mark number for each instance of the connection. Global marks start at 1001. This option is only available on linux XFRM kernels. It can be used with iptables to create custom iptables rules using CONNMARK. It can also be used with Virtual Tunnel Interfaces ("VTI") to direct marked traffic to specific vtiXX devices. mark-in The same as mark, but mark-in only applies to the inbound half of the IPsec SA. It overrides any mark= setting. mark-out The same as mark, but mark-out only applies to the outbound half of the IPsec SA. It overrides any mark= setting. libreswan-4.14/configs/d.ipsec.conf/max-halfopen-ike.xml000066400000000000000000000004511457372064200232120ustar00rootroot00000000000000 max-halfopen-ike The number of half-open IKE SAs before the IKE daemon starts refusing all new IKE attempts. Established IKE peers are not affected. The default value is 50000. libreswan-4.14/configs/d.ipsec.conf/metric.xml000066400000000000000000000005031457372064200213460ustar00rootroot00000000000000 metric Set the metric for added routes. This value is passed to the _updown scripts as PLUTO_METRIC. Acceptable values are positive numbers, with the default being 1. libreswan-4.14/configs/d.ipsec.conf/mobike.xml000066400000000000000000000012741457372064200213370ustar00rootroot00000000000000 mobike Whether to allow MOBIKE (RFC 4555) to enable a connection to migrate its endpoint without needing to restart the connection from scratch. This is used on mobile devices that switch between wired, wireless or mobile data connections. Current values are no (the default) or yes, Only connection acting as modecfgclient will allow the initiator to migrate using mobike. Only connections acting as modecfgserver will allow clients to migrate. VTI and MOBIKE might not work well when used together. libreswan-4.14/configs/d.ipsec.conf/modecfgoptions.xml000066400000000000000000000020741457372064200231100ustar00rootroot00000000000000 modecfgdns modecfgdomains modecfgbanner When configured as IKEv1 ModeCFG or IKEv2 server, specifying any of these options will cause those options and values to be sent to the connecting client. Libreswan as a client will use these received options to either update /etc/resolv.conf or the running unbound DNS server. When the connection is brought down, the previous DNS resolving state is restored. The modecfgdns option takes a comma or space separated list of IP addresses that can be used for DNS resolution. The modecfgdomains option takes a comma or space separated list of internal domain names that are reachable via the supplied modecfgdns DNS servers. The IKEv1 split tunnel directive will be sent automatically if the xauth server side has configured a network other than 0.0.0.0/0. For IKEv2, this is automated via narrowing. libreswan-4.14/configs/d.ipsec.conf/modecfgpull.xml000066400000000000000000000004561457372064200223730ustar00rootroot00000000000000 modecfgpull Pull the Mode Config network information from the server. Acceptable values are yes or no (the default). libreswan-4.14/configs/d.ipsec.conf/ms-dh-downgrade.xml000066400000000000000000000014571457372064200230540ustar00rootroot00000000000000 ms-dh-downgrade Whether to allow a downgrade of DiffieHellman group during rekey (using CREATE_CHILD_SA). Microsoft Windows (at the time of writing, Feb 2018) defaults to using the very weak modp1024 (DH2). This can be changed using a Windows registry setting to use modp2048 (DH14). However, at rekey times, it will shamelessly use modp1024 again and the connection might fail. Setting this option to yes (and adding modp1024 proposals to the ike line) this will allow this downgrade attack to happen. This should only be used to support Windows that feature this bug. Currently the accepted values are no, (the default) or yes. libreswan-4.14/configs/d.ipsec.conf/mtu.xml000066400000000000000000000011261457372064200206720ustar00rootroot00000000000000 mtu Set the MTU for the route(s) to the remote endpoint and/or subnets. This is sometimes required when the overhead of the IPsec encapsulation would cause the packet the become too big for a router on the path. Since IPsec cannot trust any unauthenticated ICMP messages, PATH MTU discovery does not work. This can also be needed when using "6to4" IPV6 deployments, which adds another header on the packet size. Acceptable values are positive numbers. There is no default. libreswan-4.14/configs/d.ipsec.conf/myvendorid.xml000066400000000000000000000003531457372064200222460ustar00rootroot00000000000000 myvendorid The string to use as our vendor id (VID) when send-vendorid=yes. The default is OE-Libreswan-VERSION. libreswan-4.14/configs/d.ipsec.conf/narrowing.xml000066400000000000000000000022341457372064200220740ustar00rootroot00000000000000 narrowing IKEv2 (RFC5996) Section 2.9 Traffic Selector narrowing options. Currently the accepted values are no, (the default) signifying no narrowing will be proposed or accepted, or yes, signifying IKEv2 negotiation may allow establishing an IPsec connection with narrowed down traffic selectors. This option is ignored for IKEv1. There are security implications in allowing narrowing down the proposal. For one, what should be done with packets that we hoped to tunnel, but cannot. Should these be dropped or send in the clear? Second, this could cause thousands of narrowed down Child SAs to be created if the conn has a broad policy (eg 0/0 to 0/0). One possible good use case scenario is that a remote end (that you fully trust) allows you to define a 0/0 to them, while adjusting what traffic you route via them, and what traffic remains outside the tunnel. However, it is always preferred to setup the exact tunnel policy you want, as this will be much clearer to the user. libreswan-4.14/configs/d.ipsec.conf/nat-ikev1-method.xml000066400000000000000000000023711457372064200231450ustar00rootroot00000000000000 nat-ikev1-method NAT Traversal in IKEv1 is negotiated via Vendor ID options as specified in RFC 3947. However, many implementations only support the draft version of the RFC. Libreswan sends both the RFC and the most common draft versions (02, 02_n and 03) to maximize interoperability. Unfortunately, there are known broken implementations of RFC 3947, notably Cisco routers that have not been updated to the latest firmware. As the NAT-T payload is sent in the very first packet of the initiator, there is no method to auto-detect this problem and initiate a workaround. This option allows fine tuning which of the NAT-T payloads to consider for sending and processing. Currently the accepted values are drafts, rfc, both (the default) and none. To interoperate with known broken devices, use nat-ikev1-method=drafts. To prevent the other end from triggering IKEv1 NAT-T encapsulation, set this to none. This will omit the NAT-T payloads used to determine NAT, forcing the other end not to use encapsulation. libreswan-4.14/configs/d.ipsec.conf/nat-keepalive.xml000066400000000000000000000006501457372064200226130ustar00rootroot00000000000000 nat-keepalive whether to send any NAT-T keep-alives. These one byte packets are send to prevent the NAT router from closing its port when there is not enough traffic on the IPsec connection. Acceptable values are: yes (the default) and no. libreswan-4.14/configs/d.ipsec.conf/negotiationshunt.xml000066400000000000000000000012101457372064200234610ustar00rootroot00000000000000 negotiationshunt What to do with packets during the IKE negotiation. Valid options are hold (the default) or passthrough. This should almost always be left to the default hold value to avoid cleartext packet leaking. The only reason to set this to passthrough is if plaintext service availability is more important than service security or privacy, a scenario that also implies failureshunt=passthrough and most likely authby=%null using Opportunistic Encryption. libreswan-4.14/configs/d.ipsec.conf/nflog-all.xml000066400000000000000000000014631457372064200217440ustar00rootroot00000000000000 nflog-all If set, the NFLOG group number to log all pre-crypt and post-decrypt traffic to. The default value of 0 means no logging at all. This option is only available on linux kernel 2.6.14 and later. It allows common network utilities such as tcpdump, wireshark and dumpcap, to use nflog:XXX pseudo interfaces where XXX is the nflog group number. During startup and shutdown of the IPsec service, iptables commands will be used to add or remove the global NFLOG table rules. The rules are setup with the nflog-prefix all-ipsec. See also the per-connection nflog option. libreswan-4.14/configs/d.ipsec.conf/nflog.xml000066400000000000000000000014701457372064200211740ustar00rootroot00000000000000 nflog If set, the NFLOG group number to log this connection's pre-crypt and post-decrypt traffic to. The default value of 0 means no logging at all. This option is only available on linux kernel 2.6.14 and later. It allows common network utilities such as tcpdump, wireshark and dumpcap, to use nflog:XXX pseudo interfaces where XXX is the nflog group number. During the updown phase of a connection, iptables will be used to add and remove the source/destination pair to the nflog group specified. The rules are setup with the nflog-prefix matching the connection name. See also the global nflog-all option. libreswan-4.14/configs/d.ipsec.conf/nhelpers.xml000066400000000000000000000011401457372064200217010ustar00rootroot00000000000000 nhelpers how many pluto helpers are started to help with cryptographic operations. Pluto will start as many helpers as the number of CPU's, minus 1 to dedicate to the main thread. For machines with less than 4 CPU's, an equal number of helpers to CPU's are started. A value of 0 forces pluto to do all operations inline using the main process. A value of -1 tells pluto to perform the above calculation. Any other value forces the number to that amount. libreswan-4.14/configs/d.ipsec.conf/nic-offload.xml000066400000000000000000000015041457372064200222460ustar00rootroot00000000000000 nic-offload Set the method of Network Interface Controller (NIC) hardware offload for ESP/AH packet processing. Acceptable values are auto (the default), yes or no. This option is separate from any CPU hardware offload available and is currently only available on Linux 4.13+ using the XFRM IPsec stack, when compiled with the options CONFIG_XFRM_OFFLOAD, CONFIG_INET_ESP_OFFLOAD and CONFIG_INET6_ESP_OFFLOAD. The auto option will attempt to auto-detect the presence of kernel and hardware support, and then automatically mark the IPsec SA for hardware offloading. One vendor supporting this offload method is Mellanox. libreswan-4.14/configs/d.ipsec.conf/nm-configured.xml000066400000000000000000000006471457372064200226310ustar00rootroot00000000000000 nm-configured Mark this connection as controlled by Network Manager. Acceptable values are yes or no (the default). Currently, setting this to yes will cause libreswan to skip reconfiguring resolv.conf when used with XAUTH and ModeConfig. libreswan-4.14/configs/d.ipsec.conf/nopmtudisc.xml000066400000000000000000000005451457372064200222560ustar00rootroot00000000000000 nopmtudisc Disable Path MTU discovery for the IPsec SA. Acceptable values are no (the default) or yes. Currently this feature is only implemented for the Linux XFRM stack. libreswan-4.14/configs/d.ipsec.conf/nssdir.xml000066400000000000000000000017511457372064200213730ustar00rootroot00000000000000 nssdir Specifies a directory for NSS database files. The default value is @IPSEC_NSSDIR@. It may contain the following files: pkcs11.txt Detailed info about NSS database creation parameteres. cert9.db NSS Certificate database. key4.db NSS Key database. When SELinux runs in enforced mode, changing this requires a similar change in the SELinux policy for the pluto daemon. libreswan-4.14/configs/d.ipsec.conf/ocsp-global.xml000066400000000000000000000067561457372064200223050ustar00rootroot00000000000000 ocsp-enable Whether to perform Online Certificate Store Protocol ("OCSP") checks on those certificates that have an OCSP URI defined. Acceptable values are yes or no (the default). ocsp-strict if set to no, pluto is tolerant about failing to obtain an OCSP responses and a certificate is not rejected when the OCSP request fails, only when the OCSP request succeeds and lists the certificate as revoked. If set to yes, any failure on obtaining an OCSP status for a certificate will be fatal and the certificate will be rejected. Acceptable values are yes or no (the default). The strict mode refers to the NSS ocspMode_FailureIsVerificationFailure mode, while non-strict mode refers to the NSS ocspMode_FailureIsNotAVerificationFailure mode. ocsp-method The HTTP methods used for fetching OCSP data. Valid options are get (the default) and post. Note that this behaviour depends on the NSS crypto library that is actually performing the fetching. When set to the get method, post is attempted only as fallback in case of failure. When set to post, only the post method is ever used. ocsp-timeout The time until an OCSP request is aborted and considered failed. The default value is 2 seconds. ocsp-uri The URI to use for OCSP requests instead of the default OCSP URI listed in the CA certificate. This requires the ocsp-trustname option to be set to the nick (friendly name) of the OCSP server certificate, which needs to be present in the NSS database. These option combined with the next option sets the OCSP default responder. ocsp-trustname The nickname of the certificate that has been imported into the NSS database of the server handling the OCSP requests. This requires the ocsp-uri option to be set as well. This option and the previous options sets the OCSP default responder. ocsp-cache-size The maximum size (in number of certificates) of OCSP responses that will be kept in the cache. The default is 1000. Setting this value to 0 means the cache is disabled. ocsp-cache-min-age The minimum age (in seconds) before a new fetch will be attempted. The default is 1 hour. ocsp-cache-max-age The maximum age (in seconds) before a new fetch will be attempted. The default is 1 day. libreswan-4.14/configs/d.ipsec.conf/oe_conns.xml000066400000000000000000000070011457372064200216660ustar00rootroot00000000000000 OPPORTUNISTIC CONNS For Opportunistic connections, the system requires creating special named conns that are used to implement the default policy groups. Currently, these names cannot be changed. conn clear type=passthrough authby=never left=%defaultroute right=%group auto=route conn clear-or-private type=passthrough left=%defaultroute leftid=%myid right=%opportunisticgroup failureshunt=passthrough keyingtries=3 ikelifetime=1h salifetime=1h rekey=no auto=route conn private-or-clear type=tunnel left=%defaultroute leftid=%myid right=%opportunisticgroup failureshunt=passthrough keyingtries=3 ikelifetime=1h salifetime=1h rekey=no auto=route conn private type=tunnel left=%defaultroute leftid=%myid right=%opportunisticgroup failureshunt=drop keyingtries=3 ikelifetime=1h salifetime=1h rekey=no auto=route conn block type=reject authby=never left=%defaultroute right=%group auto=route These conns will only work if %defaultroute works. The leftid will be the interfaces IP address by default, but it can also be set to %fromcert or use a DNS name. POLICY GROUP FILES The optional files under /etc/ipsec.d/policies, including /etc/ipsec.d/policies/clear /etc/ipsec.d/policies/clear-or-private /etc/ipsec.d/policies/private-or-clear /etc/ipsec.d/policies/private /etc/ipsec.d/policies/block may contain policy group configuration information to supplement ipsec.conf. Their contents are not security-sensitive. These files are text files. Each consists of a list of CIDR blocks, one per line. White space followed by # followed by anything to the end of the line is a comment and is ignored, as are empty lines. A connection in ipsec.conf that has right=%group or right=%opportunisticgroup is a policy group connection. When a policy group file of the same name is loaded at system start, the connection is instantiated such that each CIDR block serves as an instance's right value. The system treats the resulting instances as normal connections. For example, given a suitable connection definition private, and the file /etc/ipsec.d/policies/private with an entry 192.0.2.3, the system creates a connection instance private#192.0.2.3. This connection inherits all details from private, except that its right client is 192.0.2.3. DEFAULT POLICY GROUPS The standard Libreswan install includes several policy groups which provide a way of classifying possible peers into IPsec security classes: private (talk encrypted only), private-or-clear (prefer encryption), clear-or-private (respond to requests for encryption), clear and block. libreswan-4.14/configs/d.ipsec.conf/order.txt000066400000000000000000000103061457372064200212170ustar00rootroot00000000000000d.ipsec.conf/head.xml d.ipsec.conf/connsections.xml d.ipsec.conf/exampleleftright.xml d.ipsec.conf/conngeneral.xml d.ipsec.conf/keyexchange.xml d.ipsec.conf/hostaddrfamily.xml d.ipsec.conf/clientaddrfamily.xml d.ipsec.conf/type.xml d.ipsec.conf/left.xml d.ipsec.conf/leftsubnet.xml d.ipsec.conf/leftsubnets.xml d.ipsec.conf/leftvti.xml d.ipsec.conf/leftaddresspool.xml d.ipsec.conf/leftprotoport.xml d.ipsec.conf/leftnexthop.xml d.ipsec.conf/leftsourceip.xml d.ipsec.conf/leftupdown.xml d.ipsec.conf/leftcat.xml d.ipsec.conf/leftfirewall.xml d.ipsec.conf/conngeneralend.xml d.ipsec.conf/connauto.xml d.ipsec.conf/auto.xml d.ipsec.conf/authby.xml d.ipsec.conf/ike.xml d.ipsec.conf/phase2.xml d.ipsec.conf/phase2alg.xml d.ipsec.conf/sha2-truncbug.xml d.ipsec.conf/ms-dh-downgrade.xml d.ipsec.conf/dns-match-id.xml d.ipsec.conf/require-id-on-certificate.xml d.ipsec.conf/ppk.xml d.ipsec.conf/nat-ikev1-method.xml d.ipsec.conf/esp.xml d.ipsec.conf/ah.xml d.ipsec.conf/fragmentation.xml d.ipsec.conf/ikepad.xml d.ipsec.conf/ikev2.xml d.ipsec.conf/mobike.xml d.ipsec.conf/esn.xml d.ipsec.conf/decap-dscp.xml d.ipsec.conf/nopmtudisc.xml d.ipsec.conf/narrowing.xml d.ipsec.conf/sareftrack.xml d.ipsec.conf/nic-offload.xml d.ipsec.conf/leftid.xml d.ipsec.conf/leftrsasigkey.xml d.ipsec.conf/leftcert.xml d.ipsec.conf/leftckaid.xml d.ipsec.conf/leftauth.xml d.ipsec.conf/leftautheap.xml d.ipsec.conf/leftca.xml d.ipsec.conf/leftikeport.xml d.ipsec.conf/leftsendcert.xml d.ipsec.conf/leftxauthserver.xml d.ipsec.conf/leftxauthclient.xml d.ipsec.conf/leftusername.xml d.ipsec.conf/leftmodecfgserver.xml d.ipsec.conf/leftmodecfgclient.xml d.ipsec.conf/xauthby.xml d.ipsec.conf/xauthfail.xml d.ipsec.conf/pam-authorize.xml d.ipsec.conf/modecfgpull.xml d.ipsec.conf/modecfgoptions.xml d.ipsec.conf/remote-peer-type.xml d.ipsec.conf/nm-configured.xml d.ipsec.conf/encapsulation.xml d.ipsec.conf/enable-tcp.xml d.ipsec.conf/tcp-remoteport.xml d.ipsec.conf/nat-keepalive.xml d.ipsec.conf/initial-contact.xml d.ipsec.conf/cisco-unity.xml d.ipsec.conf/ignore-peer-dns.xml d.ipsec.conf/redirect.xml d.ipsec.conf/fake-strongswan.xml d.ipsec.conf/send-vendorid.xml d.ipsec.conf/overlapip.xml d.ipsec.conf/reqid.xml d.ipsec.conf/dpddelay.xml d.ipsec.conf/dpdtimeout.xml d.ipsec.conf/dpdaction.xml d.ipsec.conf/pfs.xml d.ipsec.conf/pfsgroup.xml d.ipsec.conf/aggressive.xml d.ipsec.conf/salifetime.xml d.ipsec.conf/ipsec-max-bytes.xml d.ipsec.conf/ipsec-max-packets.xml d.ipsec.conf/replay-window.xml d.ipsec.conf/rekey.xml d.ipsec.conf/rekeymargin.xml d.ipsec.conf/rekeyfuzz.xml d.ipsec.conf/keyingtries.xml d.ipsec.conf/ikelifetime.xml d.ipsec.conf/retransmit-timeout.xml d.ipsec.conf/retransmit-interval.xml d.ipsec.conf/compress.xml d.ipsec.conf/metric.xml d.ipsec.conf/mtu.xml d.ipsec.conf/tfc.xml d.ipsec.conf/nflog.xml d.ipsec.conf/mark.xml d.ipsec.conf/vti.xml d.ipsec.conf/ipsec-interface.xml d.ipsec.conf/priority.xml d.ipsec.conf/sendca.xml d.ipsec.conf/labeled-ipsec.xml d.ipsec.conf/policy-label.xml d.ipsec.conf/failureshunt.xml d.ipsec.conf/negotiationshunt.xml d.ipsec.conf/connautoend.xml d.ipsec.conf/configsections.xml d.ipsec.conf/protostack.xml d.ipsec.conf/listen.xml d.ipsec.conf/ike-socket.xml d.ipsec.conf/listen-udp.xml d.ipsec.conf/listen-tcp.xml d.ipsec.conf/nflog-all.xml d.ipsec.conf/keep-alive.xml d.ipsec.conf/virtual-private.xml d.ipsec.conf/myvendorid.xml d.ipsec.conf/nhelpers.xml d.ipsec.conf/seedbits.xml d.ipsec.conf/ikev1-secctx-attr-type.xml d.ipsec.conf/ikev1-policy.xml d.ipsec.conf/crlcheckinterval.xml d.ipsec.conf/crl-strict.xml d.ipsec.conf/curl-iface.xml d.ipsec.conf/curl-timeout.xml d.ipsec.conf/ocsp-global.xml d.ipsec.conf/syslog.xml d.ipsec.conf/plutodebug.xml d.ipsec.conf/uniqueids.xml d.ipsec.conf/logfile.xml d.ipsec.conf/logappend.xml d.ipsec.conf/logip.xml d.ipsec.conf/audit-log.xml d.ipsec.conf/logtime.xml d.ipsec.conf/ddos-mode.xml d.ipsec.conf/ddos-ike-threshold.xml d.ipsec.conf/global-redirect.xml d.ipsec.conf/max-halfopen-ike.xml d.ipsec.conf/shuntlifetime.xml d.ipsec.conf/xfrmlifetime.xml d.ipsec.conf/dumpdir.xml d.ipsec.conf/statsbin.xml d.ipsec.conf/ipsecdir.xml d.ipsec.conf/nssdir.xml d.ipsec.conf/secretsfile.xml d.ipsec.conf/seccomp.xml d.ipsec.conf/dnssec.xml d.ipsec.conf/configsectionsend.xml d.ipsec.conf/oe_conns.xml d.ipsec.conf/tail.xml libreswan-4.14/configs/d.ipsec.conf/overlapip.xml000066400000000000000000000013151457372064200220660ustar00rootroot00000000000000 overlapip a boolean (yes/no) that determines, when (left|right)subnet=vhost: is used, if the virtual IP claimed by this states created from this connection can with states created from other connections. Note that connection instances created by the Opportunistic Encryption or PKIX (x.509) instantiation system are distinct internally. They will inherit this policy bit. The default is no. This feature is only available with kernel drivers that support SAs to overlapping conns. At present only the (klips) mast protocol stack supports this feature. libreswan-4.14/configs/d.ipsec.conf/pam-authorize.xml000066400000000000000000000012321457372064200226500ustar00rootroot00000000000000 pam-authorize IKEv1 supports PAM authorization via XAUTH using xauthby=pam. IKEv2 does not support receiving a plaintext username and password. Libreswan does not yet support EAP authentication methods for IKE. The pam-authorize=yes option performs an authorization call via PAM, but only includes the remote ID (not username or password). This allows for backends to disallow an ID based on non-password situations, such as "user disabled" or "user over quota". See also xauthby=pam libreswan-4.14/configs/d.ipsec.conf/pfs.xml000066400000000000000000000006441457372064200206610ustar00rootroot00000000000000 pfs whether Perfect Forward Secrecy of keys is desired on the connection's keying channel (with PFS, penetration of the key-exchange protocol does not compromise keys negotiated earlier); Acceptable values are yes (the default) and no. libreswan-4.14/configs/d.ipsec.conf/pfsgroup.xml000066400000000000000000000004301457372064200217270ustar00rootroot00000000000000 pfsgroup This option is obsoleted, please use phase2alg if you need the PFS to be different from phase1 (the default) using: phase2alg=aes128-md5;modp1024 libreswan-4.14/configs/d.ipsec.conf/phase2.xml000066400000000000000000000015261457372064200212530ustar00rootroot00000000000000 phase2 Sets the type of SA that will be produced. Valid options are: esp for encryption (the default), ah for authentication only. The very first IPsec designs called for use of AH plus ESP to offer authentication, integrity and confidentiality. That dual protocol use was a significant burden, so ESP was extended to offer all three services, and AH remained as an auth/integ. The old mode of ah+esp is no longer supported in compliance with RFC 8221 Section 4. Additionally, AH does not play well with NATs, so it is strongly recommended to use ESP with the null cipher if you require unencrypted authenticated transport. libreswan-4.14/configs/d.ipsec.conf/phase2alg.xml000066400000000000000000000003031457372064200217270ustar00rootroot00000000000000 phase2alg This option is alias to esp. libreswan-4.14/configs/d.ipsec.conf/plutodebug.xml000066400000000000000000000023151457372064200222400ustar00rootroot00000000000000 plutodebug how much Pluto debugging output should be logged. An empty value, or the magic value none, means no debug output (the default). Otherwise only the specified types of output (a quoted list, names without the prefix, separated by white space) are enabled; The current option values are base that represents moderate amounts of information, cpu-usage for getting timing/load based information (best used without any other debugging options), crypt for all crypto related operations and tmi (Too Much Information) for excessive logging. To log any sensitive private key or password material, use the special private value. The old plutodebug options (control, controlmore, x509, kernel, etc) are mapped to either base or tmi. Note that all maps to base and not tmi. libreswan-4.14/configs/d.ipsec.conf/policy-label.xml000066400000000000000000000006471457372064200224500ustar00rootroot00000000000000 policy-label The string representation of an access control security label that is interpreted by the LSM (e.g. SELinux) for use with Labeled IPsec. See also labeled-ipsec= and secctx-attr-type=. For example, policy-label=system_u:object_r:ipsec_spd_t:s0-s15:c0.c1023 libreswan-4.14/configs/d.ipsec.conf/ppk.xml000066400000000000000000000015231457372064200206600ustar00rootroot00000000000000 ppk EXPERIMENTAL: Post-quantum preshared keys (PPKs) to be used. Currently the accepted values are propose or yes (the default), signifying we propose to use PPK for this connection; insist, signifying we allow communication only if PPK is used for key derivation; never or no, signifying that PPK should not be used for key derivation. PPKs can be used in connections that allow only IKEv2. In libreswan that would mean that ikev2 option must have value insist. (currently based on draft-fluhrer-qr-ikev2, not raft-ietf-ipsecme-qr-ikev2-00) libreswan-4.14/configs/d.ipsec.conf/priority.xml000066400000000000000000000020161457372064200217450ustar00rootroot00000000000000 priority The priority in the kernel SPD/SAD database, when matching up packets. Each kernel (XFRM, OSX, etc) has its own mechanism for setting the priority. Setting this option to non-zero passes the priority to the kernel stack unmodified. The maximum value depends on the stack. It is recommended not to exceed 65536 XFRM use a priority system based on "most specific match first". It uses an internal algorithm to calculate these based on network prefix length, protocol and port selectors. A lower value means a higher priority. Typical values are about the 2000 range. These can be seen on the XFRM stack using ip xfrm policy when the connection is up. For "anonymous IPsec" or Opportunistic Encryption based connections, a much lower priority (65535) is used to ensure administrator configured IPsec always takes precedence over opportunistic IPsec. libreswan-4.14/configs/d.ipsec.conf/protostack.xml000066400000000000000000000007741457372064200222660ustar00rootroot00000000000000 protostack decide which protocol stack is going to be used. Valid values are "xfrm" and "bsd". This option should no longer be set, as the stack is currently auto-detected. The values "klips, "mast", "netkey", "native", "kame" and "auto" are obsolete. The option is kept only because it is suspected that Linux and BSD will get userspace stacks with IPsec support soon (such as dpdk). libreswan-4.14/configs/d.ipsec.conf/redirect.xml000066400000000000000000000036201457372064200216670ustar00rootroot00000000000000 accept-redirect Whether requests of the remote peer to redirect IKE/IPsec SA's are accepted. Valid options are no (the default) and yes. See also accept-redirect-to. accept-redirect-to Specify the comma separated list of addresses we accept being redirected to. Both IPv4 and IPv6 addresses are supported as well the FQDNs. The value %any, as well as not specifying any address, signifes that we will redirect to any address gateway sends us in REDIRECT notify payload. The value of this option is not considered at all if accept-redirect is set to no. send-redirect Whether to send requests for the remote peer to redirect IKE/IPsec SA's during IKE_AUTH. Valid options are no (the default) and yes. If set, the option redirect-to= must also be set to indicate where to redirect peers to. For redirection during IKE_SA_INIT exchange, see the global-redirect= and global-redirect-to= options. Runtime redirects can be triggered via the ipsec whack --redirect command. redirect-to Where to send remote peers to via the send-redirect option. This can be an IP address or hostname (FQDN). libreswan-4.14/configs/d.ipsec.conf/rekey.xml000066400000000000000000000011441457372064200212040ustar00rootroot00000000000000 rekey whether a connection should be renegotiated when it is about to expire; acceptable values are yes (the default) and no. The two ends need not agree, but while a value of no prevents Pluto from requesting renegotiation, it does not prevent responding to renegotiation requested from the other end, so no will be largely ineffective unless both ends agree on it. libreswan-4.14/configs/d.ipsec.conf/rekeyfuzz.xml000066400000000000000000000014641457372064200221300ustar00rootroot00000000000000 rekeyfuzz maximum percentage by which rekeymargin should be randomly increased to randomize rekeying intervals (important for hosts with many connections); acceptable values are an integer, which may exceed 100, followed by a `%' (default set by ipsec_pluto8, currently 100%). The value of rekeymargin, after this random increase, must not exceed salifetime. The value 0% will suppress time randomization. Relevant only locally, other end need not agree on it. libreswan-4.14/configs/d.ipsec.conf/rekeymargin.xml000066400000000000000000000006311457372064200224020ustar00rootroot00000000000000 rekeymargin how long before connection expiry or keying-channel expiry should attempts to negotiate a replacement begin; acceptable values as for salifetime (default 9m). Relevant only locally, other end need not agree on it. libreswan-4.14/configs/d.ipsec.conf/remote-peer-type.xml000066400000000000000000000011341457372064200232670ustar00rootroot00000000000000 remote-peer-type Set the remote peer type. This can enable additional processing during the IKE negotiation. Acceptable values are cisco or ietf (the default). When set to cisco, support for Cisco IPsec gateway redirection and Cisco obtained DNS and domainname are enabled. This includes automatically updating (and restoring) /etc/resolv.conf. These options require that XAUTH is also enabled on this connection. libreswan-4.14/configs/d.ipsec.conf/replay-window.xml000066400000000000000000000025101457372064200226640ustar00rootroot00000000000000 replay-window The size of the IPsec SA replay window protection in packets. Kernels (Linux, and most BSDs) support a window size of at least 2040 packets. The default replay window size is 128 packets. A value of 0 disables replay protection. Disabling of replay protection is sometimes used on a pair of IPsec servers in a High Availability setup, or on servers with very unpredictable latency, such as mobile networks, which can cause an excessive amount of out of order packets. Disabling replay protection will also disable Extended Sequence Numbers (esn=no), as advise from RFC 4303 caused some stacks to not support ESN without a replay-window. Note: on Linux, sequence errors can be seen in /proc/net/xfrm_stat. Note: the BSD setkey utility displays the replay window size in bytes (8 packets per byte) and not packets. Technically, at least the Linux kernel can install IPsec SA's with an IPsec SA Sequence Number, but this is currently not supported by libreswan. libreswan-4.14/configs/d.ipsec.conf/reqid.xml000066400000000000000000000020561457372064200211740ustar00rootroot00000000000000 reqid a unique identifier used to match IPsec SAs using iptables with XFRM. This identifier is normally automatically allocated in groups of 4. 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 16380 and higher. Manually specified reqid values therefore must be between 1 and 16379. Automatically generated reqids use a range of 0-3 (eg 16380-16383 for the first reqid). These are used depending on the exact policy (AH, AH+ESP, IPCOMP, etc). WARNING: Manually assigned reqids are all identical. Instantiations of connections (those using %any wildcards) will all use the same reqid. If you use manual assigning you should make sure your connections only match single road warrior only or you break multiple road warriors behind same NAT router because this feature requires unique reqids to work. libreswan-4.14/configs/d.ipsec.conf/require-id-on-certificate.xml000066400000000000000000000013241457372064200250250ustar00rootroot00000000000000 require-id-on-certificate When using certificates, check whether the IKE peer ID is present as a subjectAltName (SAN) on the peer certificate. Accepted values are yes (the default) or no. This check should only be disabled when intentionally using certificates that do not have their peer ID specified as a SAN on the certificate. These certificates violate RFC 4945 Section 3.1 and are normally rejected to prevent a compromised host from assuming the IKE identity of another host. The SAN limits the IDs that the peer is able to assume. libreswan-4.14/configs/d.ipsec.conf/retransmit-interval.xml000066400000000000000000000011631457372064200241000ustar00rootroot00000000000000 retransmit-interval the initial interval time period, specified in msecs, that pluto waits before retransmitting an IKE packet. This interval is doubled for each attempt (exponential back-off). The default set by ipsec_pluto8, currently is 500. See also: retransmit-timeout, rekey and keyingtries. libreswan-4.14/configs/d.ipsec.conf/retransmit-timeout.xml000066400000000000000000000011501457372064200237360ustar00rootroot00000000000000 retransmit-timeout how long a single packet, including retransmits of that packet, may take before the IKE attempt is aborted. If rekeying is enabled, a new IKE attempt is started. The default set by ipsec_pluto8, currently is 60s. See also: retransmit-interval, rekey and keyingtries. libreswan-4.14/configs/d.ipsec.conf/salifetime.xml000066400000000000000000000021251457372064200222070ustar00rootroot00000000000000 salifetime how long a particular instance of a connection (a set of encryption/authentication keys for user packets) should last, from successful negotiation to expiry; acceptable values are an integer optionally followed by s (a time in seconds) or a decimal number followed by m, h, or d (a time in minutes, hours, or days respectively) (default 8h, maximum 24h). Normally, the connection is renegotiated (via the keying channel) before it expires. The two ends need not exactly agree on salifetime, although if they do not, there will be some clutter of superseded connections on the end which thinks the lifetime is longer. The keywords "keylife" and "lifetime" are obsoleted aliases for "salifetime." Change your configs to use "salifetime" instead. libreswan-4.14/configs/d.ipsec.conf/sareftrack.xml000066400000000000000000000023451457372064200222160ustar00rootroot00000000000000 sareftrack Set the method of tracking reply packets with SArefs when using an SAref compatible stack. Currently only the mast stack supports this. Acceptable values are yes (the default), no or conntrack. This option is ignored when SArefs are not supported. This option is passed as PLUTO_SAREF_TRACKING to the updown script which makes the actual decisions whether to perform any iptables/ip_conntrack manipulation. A value of yes means that an IPSEC mangle table will be created. This table will be used to match reply packets. A value of conntrack means that additionally, subsequent packets using this connection will be marked as well, reducing the lookups needed to find the proper SAref by using the ip_conntrack state. A value of no means no IPSEC mangle table is created, and SAref tracking is left to a third-party (kernel) module. In case of a third party module, the SArefs can be relayed using the statsbin= notification helper. libreswan-4.14/configs/d.ipsec.conf/seccomp.xml000066400000000000000000000035621457372064200215240ustar00rootroot00000000000000 seccomp Set the seccomp kernel syscall whitelisting feature. When set to enabled, if pluto calls a syscall that is not on the compiled-in whitelist, the kernel will assume an exploit is attempting to use pluto for malicious access to the system and terminate the pluto daemon. When set to tolerant, the kernel will only block the rogue syscall and pluto will attempt to continue. If set to disabled, pluto is allowed to call any syscall offered by the kernel, although it might be restricted via other security mechanisms, such as capabilities, SElinux, AppArmor or other OS security features. The current default is disabled, but it is expected that in the future this feature will be enabled on all supported operating systems. Similarly, it is expected that further privilege separation will reduce the allowed syscalls - for example for the crypto helpers or DNS helpers. Warning: The restrictions of pluto are inherited by the updown scripts, so these scripts are also not allowed to use syscalls that are forbidden for pluto. This feature can be tested using ipsec whack --seccomp-crashtest. Warning: With seccomp=enabled, pluto will be terminated by the kernel. With seccomp=tolerant or seccomp=disabled, pluto will report the results of the seccomp test. SECCOMP will log the forbidden syscall numbers to the audit log, but only with seccomp=enabled. The tool scmp_sys_resolver from the libseccomp development package can be used to translate the syscall number into a name. See programs/pluto/pluto_seccomp.c for the list of allowed syscalls. libreswan-4.14/configs/d.ipsec.conf/secretsfile.xml000066400000000000000000000005421457372064200223760ustar00rootroot00000000000000 secretsfile pathname of the file that stores the secret credentials such as preshared keys (PSKs). See man ipsec.secrets for the syntax. The default value is @IPSEC_SECRETS_FILE@. libreswan-4.14/configs/d.ipsec.conf/seedbits.xml000066400000000000000000000012761457372064200216750ustar00rootroot00000000000000 seedbits Pluto uses the NSS crypto library as its random source. Some government Three Letter Agencies require that pluto reads additional bits from /dev/random and feed these into the NSS RNG before drawing random from the NSS library, despite the NSS library itself already seeding its internal state. This process can block pluto for an extended time during startup, depending on the entropy of the system. Therefore, the default is to not perform this redundant seeding. If specifying a value, it is recommended to specify at least 460 bits (for FIPS) or 440 bits (for BSI). libreswan-4.14/configs/d.ipsec.conf/send-vendorid.xml000066400000000000000000000016771457372064200226410ustar00rootroot00000000000000 send-vendorid whether to send our Vendor ID during IKE. Acceptable values are: no (the default) and yes. The vendor id sent can be configured using the "config setup" option myvendorid=. It defaults to OE-Libreswan-VERSION. Vendor ID's can be useful in tracking interoperability problems. However, specific vendor identification and software versions can be useful to an attacker when there are known vulnerabilities to a specific vendor/version. The prefix OE stands for "Opportunistic Encryption". This prefix was historically used by The FreeS/WAN Project and The Openswan Project (openswan up to version 2.6.38) and in one Xeleranized openswan versions (2.6.39). Further Xeleranized openswan's use the prefix OSW. libreswan-4.14/configs/d.ipsec.conf/sendca.xml000066400000000000000000000007521457372064200213260ustar00rootroot00000000000000 sendca How much of our available X.509 trust chain to send with the End certificate, excluding any root CA's. Specifying issuer sends just the issuing intermediate CA, while all will send the entire chain of intermediate CA's.none (the default) will not send any CA certs. libreswan-4.14/configs/d.ipsec.conf/sha2-truncbug.xml000066400000000000000000000015171457372064200225550ustar00rootroot00000000000000 sha2-truncbug The default ESP hash truncation for sha2_256 is 128 bits. Some IPsec implementations (Linux before 2.6.33, some Cisco (2811?) routers) implement the draft version which stated 96 bits. If a draft implementation communicates with an RFC implementation, both ends will reject encrypted packets from each other. This option enables using the draft 96 bits version to interop with those implementations. Currently the accepted values are no, (the default) signifying default RFC truncation of 128 bits, or yes, signifying the draft 96 bits truncation. Another workaround is to switch from sha2_256 to sha2_128 or sha2_512. libreswan-4.14/configs/d.ipsec.conf/shuntlifetime.xml000066400000000000000000000013001457372064200227370ustar00rootroot00000000000000 shuntlifetime The time until bare shunts (kernel policies not associated with connections) are deleted from the kernel. The default value is 15m. When using Opportunistic Encryption to a specific host fails, the system will either install a %pass or %hold shunt to let the traffic out clear text or block it. During the the shuntlifetime, no new Opportunistic Encryption attempt will be started, although the system will still respond to incoming OE requests from the remote IP. See also failureshunt and negotiationshunt libreswan-4.14/configs/d.ipsec.conf/statsbin.xml000066400000000000000000000006241457372064200217160ustar00rootroot00000000000000 statsbin This option specifies an optional external program to report tunnel state changes too. The default is not to report tunnel state changes. This program can be used to notify the user's desktop (dbus, NetworkManager) or to report tunnel changes to a central logging server. libreswan-4.14/configs/d.ipsec.conf/syslog.xml000066400000000000000000000005501457372064200214050ustar00rootroot00000000000000 syslog the syslog2 “facility” name and priority to use for startup/shutdown log messages, default daemon.error. libreswan-4.14/configs/d.ipsec.conf/tail.xml000066400000000000000000000107331457372064200210220ustar00rootroot00000000000000CHOOSING A CONNECTION [THIS SECTION IS EXTREMELY OUT OF DATE When choosing a connection to apply to an outbound packet caught with a %trap, the system prefers the one with the most specific eroute that includes the packet's source and destination IP addresses. Source subnets are examined before destination subnets. For initiating, only routed connections are considered. For responding, unrouted but added connections are considered. When choosing a connection to use to respond to a negotiation that doesn't match an ordinary conn, an opportunistic connection may be instantiated. Eventually, its instance will be /32 -> /32, but for earlier stages of the negotiation, there will not be enough information about the client subnets to complete the instantiation. FILES /etc/ipsec.conf /etc/ipsec.d/policies/clear /etc/ipsec.d/policies/clear-or-private /etc/ipsec.d/policies/private-or-clear /etc/ipsec.d/policies/private /etc/ipsec.d/policies/block SEE ALSO ipsec8, ipsec_auto8, ipsec_rsasigkey8 HISTORY Designed for the FreeS/WAN project <https://www.freeswan.org> by Henry Spencer. BUGS Before reporting new bugs, please ensure you are using the latest version of Libreswan. When type or failureshunt is set to drop or reject, Libreswan blocks outbound packets using eroutes, but assumes inbound blocking is handled by the firewall. Libreswan offers firewall hooks via an “updown” script. However, the default ipsec _updown provides no help in controlling a modern firewall. Including attributes of the keying channel (authentication methods, ikelifetime, etc.) as an attribute of a connection, rather than of a participant pair, is dubious and incurs limitations. The use of %any with the protoport= option is ambiguous. Should the SA permits any port through or should the SA negotiate any single port through? The first is a basic conn with a wildcard. The second is a template. The second is the current behaviour, and it's wrong for quite a number of uses involving TCP. The keyword %one may be introduced in the future to separate these two cases. It would be good to have a line-continuation syntax, especially for the very long lines involved in RSA signature keys. The ability to specify different identities, authby, and public keys for different automatic-keyed connections between the same participants is misleading; this doesn't work dependably because the identity of the participants is not known early enough. This is especially awkward for the “Road Warrior” case, where the remote IP address is specified as 0.0.0.0, and that is considered to be the “participant” for such connections. If conns are to be added before DNS is available, left=FQDN, leftnextop=FQDN, and leftrsasigkey=%dnsonload will fail. ipsec_pluto8 does not actually use the public key for our side of a conn but it isn't generally known at a add-time which side is ours (Road Warrior and Opportunistic conns are currently exceptions). The myid option does not affect explicit ipsec auto --add or ipsec auto --replace commands for implicit conns. libreswan-4.14/configs/d.ipsec.conf/tcp-remoteport.xml000066400000000000000000000010201457372064200230420ustar00rootroot00000000000000 tcp-remoteport Which remote TCP port to use when IKE over TCP is attempted. The default value is to use the NAT-T IKE port (4500). This value is not negotiated and should be configured properly on all endpoints. When opening a TCP socket to the remote host in this port, a regular ephemeral source port is obtained from the OS. For changing the UDP ports, see leftikeport= libreswan-4.14/configs/d.ipsec.conf/tfc.xml000066400000000000000000000026431457372064200206460ustar00rootroot00000000000000 tfc Enable Traffic Flow Confidentiality ("TFC") (RFC-4303) for outgoing ESP packets in Tunnel Mode. When enabled, ESP packets are padded to the specified size (up to the PMTU size) to prevent leaking information based on ESP packet size. This option is ignored for AH and for ESP in Transport Mode as those always leak traffic characteristics and applying TFC will not do anything. Acceptable values are positive numbers. The value 0 means TFC padding is not performed. Currently this feature is only implemented for the Linux XFRM stack. In IKEv2, when the notify payload ESP_TFC_PADDING_NOT_SUPPORTED is received, TFC padding is disabled. The default is not to do any TFC padding, but this might change in the near future. send-no-esp-tfc Whether or not to tell the remote peer that we do not support Traffic Flow Confidentiality ("TFC") (RFC-4303). Possible values are no (the default) which allows the peer to use TFC or yes which prevents to peer from using TFC. This does not affect whether this endpoint uses TFC, which only depends on the local tfc setting. This option is only valid for IKEv2. libreswan-4.14/configs/d.ipsec.conf/type.xml000066400000000000000000000012711457372064200210470ustar00rootroot00000000000000 type the type of the connection; currently the accepted values are tunnel (the default) signifying a host-to-host, host-to-subnet, or subnet-to-subnet tunnel; transport, signifying host-to-host transport mode; passthrough, signifying that no IPsec processing should be done at all; drop, signifying that packets should be discarded; and reject, signifying that packets should be discarded and a diagnostic ICMP returned. libreswan-4.14/configs/d.ipsec.conf/uniqueids.xml000066400000000000000000000016551457372064200221020ustar00rootroot00000000000000 uniqueids Whether IDs should be considered identifying remote parties uniquely. Acceptable values are yes (the default) and no. Participant IDs normally are unique, so a new connection instance using the same remote ID is almost invariably intended to replace an old existing connection. When the connection is defined to be a server (using xauthserver=) and the connection policy is authby=secret, this option is ignored (as of 3.20) and old connections will never be replaced. This situation is commonly known as clients using a "Group ID". This option may disappear in the near future. People using identical X.509 certificates on multiple devices are urged to upgrade to use separate certificates per client and device. libreswan-4.14/configs/d.ipsec.conf/virtual-private.xml000066400000000000000000000036161457372064200232310ustar00rootroot00000000000000 virtual-private contains the networks that are allowed as (left|right)subnet= for the remote clients when using the vhost: or vnet: keywords in the (left|right)subnet= parameters. In other words, the address ranges that may live behind a NAT router through which a client connects. This value is usually set to all the RFC-1918 address space, excluding the space used in the local subnet behind the NAT (An IP address cannot live at two places at once). IPv4 address ranges are denoted as %v4:a.b.c.d/mm and IPv6 is denoted as %v6:aaaa::bbbb:cccc:dddd:eeee/mm. One can exclude subnets by using the !. For example, if the VPN server is giving access to 192.168.1.0/24, this option should be set to: 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. This parameter is only needed on the server side and not on the client side that resides behind the NAT router, as the client will just use its IP address for the inner IP setting. This parameter may eventually become per-connection. See also leftsubnet= Note: It seems that T-Mobile in the US and Rogers/Fido in Canada have started using 25.0.0.0/8 as their pre-NAT range. This range technically belongs to the Defence Interoperable Network Services Authority (DINSA), an agency of the Ministry of Defence of the United Kingdom. The network range seems to not have been announced for decades, which is probably why these organisations "borrowed" this range. To support roadwarriors on these 3G networks, you might have to add it to the virtual-private= line. libreswan-4.14/configs/d.ipsec.conf/vti.xml000066400000000000000000000054131457372064200206720ustar00rootroot00000000000000 vti-interface This option is used to create "Routing based VPNs" (as opposed to "Policy based VPNs"). It will create a new interface that can be used to route traffic in for encryption/decryption. The Virtual Tunnel Interface ("VTI") interface name is used to for all IPsec SA's created by this connection. This requires that the connection also enables either the mark= or mark-in= / mark-out- option(s). All traffic marked with the proper MARKs will be automatically encrypted if there is an IPsec SA policy covering the source/destination traffic. Tools such as tcpdump and iptables can be used on all cleartext pre-encrypt and post-decrypt traffic on the device. See the libreswan wiki for example configurations that use VTI. VTI interfaces are currently only supported on Linux with XFRM. The _updown script handles certain Linux specific interfaces settings required for proper functioning (disable_policy, rp_filter, forwarding, etc). Interface names are limited to 16 characters and may not allow all characters to be used. If marking and vti-routing=yes is used, no manual iptables should be required. However, administrators can use the iptables mangle table to mark traffic manually if desired. vti-routing Whether or not to add network rules or routes for IPsec SA's to the respective VTI devices. Valid values are yes (the default) or no. When using "routing based VPNs" with a subnets policy of 0.0.0.0/0, this setting needs to set to no to prevent imploding the tunnel, and the administrator is expected to manually add ip rules and ip routes to configure what traffic must be encrypted. When set to yes, the _updown script will automatically route the leftsubnet/rightsubnet traffic into the VTI device specified with vti-interface vti-shared Whether or not the VTI device is shared amongst connections. Valid values are no (the default) or yes. When set to no, the VTI device is automatically deleted if the connection is a single non-instantiated connection. If a connection instantiates (eg right=%any) then this option has no effect, as the VTI device is not removed as it is shared with multiple roadwarriors. libreswan-4.14/configs/d.ipsec.conf/xauthby.xml000066400000000000000000000025671457372064200215630ustar00rootroot00000000000000 xauthby When IKEv1 XAUTH support is available, set the method used by XAUTH to authenticate the user with IKEv1. The currently supported values are file (the default), pam or alwaysok. The password file is located at /etc/ipsec.d/passwd, and follows a syntax similar to the Apache htpasswd file, except an additional connection name argument (and optional static IP address) are also present:       username:password:conname:ipaddress For supported password hashing methods, see crypt 3. If pluto is running in FIPS mode, some hash methods, such as MD5, might not be available. Threads are used to launch an xauth authentication helper for file as well as PAM methods. The alwaysok should only be used if the XAUTH user authentication is not really used, but is required for interoperability, as it defeats the whole point of XAUTH which is to rely on a secret only known by a human. See also pam-authorize=yes libreswan-4.14/configs/d.ipsec.conf/xauthfail.xml000066400000000000000000000012001457372064200220430ustar00rootroot00000000000000 xauthfail When XAUTH support is available, set the failure method desired when authentication has failed. The currently supported values are hard (the default) and soft. A soft failure means the IPsec SA is allowed to be established, as if authentication had passed successfully, but the XAUTH_FAILED environment variable will be set to 1 for the updown script, which can then be used to redirect the user into a walled garden, for example a payment portal. libreswan-4.14/configs/d.ipsec.conf/xfrmlifetime.xml000066400000000000000000000016551457372064200225670ustar00rootroot00000000000000 xfrmlifetime The time in seconds until the XFRM acquire state times out. The default value is 30 seconds. For auto=ondemand connections and Opportunistic connections an IPsec policy is installed in the kernel. If an incoming or outgoing packet matches this policy, a state is created in the kernel and the kernel sends an ACQUIRE message to the IKE daemon pluto. While this state is in place, no new acquires will come in for this connection. The default should be fine for most people. One use case of shortening these is if opportunistc encryption is used towards cloud instances that can quickly re-use IP addresses. This value is only used during the libreswan startup process by the ipsec _stackmanager helper. See also failureshunt and negotiationshunt libreswan-4.14/configs/ipsec.conf.in000066400000000000000000000032371457372064200174560ustar00rootroot00000000000000# @FINALCONFDIR@/ipsec.conf - Libreswan 4.0 configuration file # # see 'man ipsec.conf' and 'man pluto' for more information # # For example configurations and documentation, see https://libreswan.org/wiki/ config setup # If logfile= is unset, syslog is used to send log messages too. # Note that on busy VPN servers, the amount of logging can trigger # syslogd (or journald) to rate limit messages. #logfile=@FINALLOGDIR@/pluto.log # # Debugging should only be used to find bugs, not configuration issues! # "base" regular debug, "tmi" is excessive (!) and "private" will log # sensitive key material (not available in FIPS mode). The "cpu-usage" # value logs timing information and should not be used with other # debug options as it will defeat getting accurate timing information. # Default is "none" # plutodebug="base" # plutodebug="tmi" #plutodebug="none" # # Some machines use a DNS resolver on localhost with broken DNSSEC # support. This can be tested using the command: # dig +dnssec DNSnameOfRemoteServer # If that fails but omitting '+dnssec' works, the system's resolver is # broken and you might need to disable DNSSEC. # dnssec-enable=no # # To enable IKE and IPsec over TCP for VPN server. Requires at least # Linux 5.7 kernel or a kernel with TCP backport (like RHEL8 4.18.0-291) # listen-tcp=yes # To enable IKE and IPsec over TCP for VPN client, also specify # tcp-remote-port=4500 in the client's conn section. # if it exists, include system wide crypto-policy defaults # include /etc/crypto-policies/back-ends/libreswan.config # It is best to add your IPsec connections as separate files # in @IPSEC_CONFDDIR@/ include @IPSEC_CONFDDIR@/*.conf libreswan-4.14/configs/ipsec.secrets.5.xml000066400000000000000000000301431457372064200205320ustar00rootroot00000000000000 PaulWouterslibreswan secrets files IPSEC.SECRETS 5 25 September 2020 libreswan Executable programs ipsec.secrets secrets for IKE/IPsec authentication DESCRIPTION The file ipsec.secrets contains a list of secrets. Currently supported secrets are preshared secrets (PSKs), postquantum preshared keys (PPKs) and XAUTH passwords. As of libreswan version 4.0, the secrets entries for raw RSA keys are no longer needed and ignored. All private keys from public keypairs (RSA or ECDSA) are stored completely in the NSS database and :RSA entries are no longer required to locate these. These secrets are used by pluto8 , the Libreswan Internet Key Exchange daemon, to authenticate other hosts. There is another one type of secret, post-quantum preshared keys (PPKs), that are used for protecting traffic from quantum computer attack. XAUTH passwords are stored in plaintext in this file. The secrets file should be owned by root, and permissions should be set to block all access by others. (eg: chmod 600) The file is a sequence of entries and include directives. Here is an example - each entry or directive must start at the left margin, but if it continues beyond a single line, each continuation line must be indented. # sample @IPSEC_SECRETS_FILE@ file for 10.1.0.1 10.1.0.1 10.2.0.1 : PSK "secret shared by two hosts" # sample roadwarrior %any gateway.corp.com : PSK "shared secret with many roadwarriors" # sample server for roadwarriors myip %any : PSK "shared secret with many roadwarriors" # an entry may be split across lines, # but indentation matters www.xs4all.nl @www.kremvax.ru     10.6.0.1 10.7.0.1 1.8.0.1 : PSK "secret shared by 5 systems" # sample entry for static PPK 10.1.0.1 10.2.0.1 : PPKS "PPK_ID_1" "post-quantum preshared key for extra security" # XAUTH password, used with leftusername=username @username : XAUTH "password" include ipsec.*.secrets # get secrets from other files Each entry in the file is a list of indices, followed by a secret. The two parts are separated by a colon (:) that is followed by whitespace or a newline. An index is an IP address, or a Fully Qualified Domain Name, user@FQDN, %any or %any6 (other kinds may come). An IP address may be written in the familiar dotted quad form or as a domain name to be looked up when the file is loaded. Be aware that using domain names requires DNS to be functional before the IPsec tunnel comes up. To denote a Fully Qualified Domain Name (as opposed to an IP address denoted by its domain name), precede the name with an at sign (@). Matching IDs with indices is fairly straightforward: they have to be equal. In the case of a "Road Warrior" connection, if an equal match is not found for the Peer's ID, and it is in the form of an IP address, an index of %any will match the peer's IP address if IPV4 and %any6 will match a the peer's IP address if IPV6. This file is only read at startup time. If any changes are made to this file, the pluto daemon should be told to re-read this file using the command ipsec secrets or ipsec auto --rereadsecrets. Note that currently there is no way to add a specific new entry - it's all or nothing. Smartcard support has been moved from Libreswan to NSS. The location of these are specified using leftcert/rightcert entries with a PKIX URI in ipsec.conf. No entry in the secrets file is required for these. An additional complexity arises in the case of authentication by preshared secret in IKEv1 Main Mode: the responder will need to look up the secret before the Peer's ID payload has been decoded, so the ID used will be the IP address. IKEv1 Aggressive Mode (aggrmode=yes) can be used to work around this, at the price of leaking the ID in the clear and allowing a brute force attack against the PSK to be performed offline. PSKs are the least secure authentication method and should be avoided. To authenticate a connection between two hosts, the entry that most specifically matches the host and peer IDs is used. An entry with no index will match any host and peer. More specifically, an entry with one index will match a host and peer if the index matches the host's ID (the peer isn't considered). Still more specifically, an entry with multiple indices will match a host and peer if the host ID and peer ID each match one of the indices. It is acceptable for two entries to be the best match as long as they agree about the secret. Authentication by preshared secret requires that both systems find the identical secret (the secret is not actually transmitted by the IKE protocol). If both the host and peer appear in the index list, the same entry will be suitable for both systems so verbatim copying between systems can be used. This naturally extends to larger groups sharing the same secret. Thus multiple-index entries are best for PSK authentication. When running in FIPS mode, PSK's need to comply to a minimum strength requirement depending on the integrity and PRF algorithm used. It is recommended not to use PSK's shorter then 64 random characters. The token "XAUTH" indicates an IKEv1 eXtended Authentication password. There should be one index, and it should be in the @FQDN format. The file will be searched with the XAUTH username, which is usually provided in the configuration file. XAUTH is otherwise identical to PSK in syntax. A preshared secret is most conveniently represented as a sequence of characters, delimited by the double-quote character ("). The sequence cannot contain a newline or double-quote. Strictly speaking, the secret is actually the sequence of bytes that is used in the file to represent the sequence of characters (excluding the delimiters). A preshared secret may also be represented, without quotes, in any of supported 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. Post-quantum preshared keys (PPK) can be static. The token “PPKS” indicates that the following key will be a PPK. The next token is a PPK_ID that uniquely represents the given PPK. PPK_ID must be represented as a sequence of characters delimited by the double-quote character ("). The next token is a PPK itself. The static PPK may be represented in any format that can be used for representing a preshared secret. It is recommended that the static PPK be at least 256 bits in order to provide real security against quantum computer attacks. The first token of an entry must start in the first column of its line. Subsequent tokens must be separated by whitespace, except for a colon token, which only needs to be followed by whitespace. A newline is taken as whitespace, but every line of an entry after the first must be indented. Whitespace at the end of a line is ignored (except in the 0t notation for a key). At the start of line or after whitespace, # and the following text up to the end of the line is treated as a comment. Within entries, all lines must be indented (except for lines with no tokens). Outside entries, no line may be indented (this is to make sure that the file layout reflects its structure). An include directive causes the contents of the named file to be processed before continuing with the current file. The filename is subject to "globbing" as in sh1, so every file with a matching name is processed. Includes may be nested to a modest depth (10, currently). If the filename doesn't start with a /, the directory containing the current file is prepended to the name. The include directive is a line that starts with the word include, followed by whitespace, followed by the filename (which must not contain whitespace). FILES @IPSEC_SECRETS_FILE@ SEE ALSO The rest of the Libreswan distribution, in particular ipsec.conf5, ipsec8, ipsec_newhostkey8, ipsec_rsasigkey8, ipsec_showhostkey8, ipsec_auto8 , and pluto8 . HISTORY Originally designed for the FreeS/WAN project <https://www.freeswan.org> by D. Hugh Redelmeier. Updated for Openswan by Ken Bantoft. Updated for Libreswan by Paul Wouters This file originally stored the private part of RSA keys. This was later on moved to the NSS database, and all private fields were filled with the CKAID to enable lookup in the NSS database. This was further obsoleted in libreswan 4.0 and now the secrets file no longer contains any public key pair information. BUGS If an ID is 0.0.0.0, it will match %any; if it is 0::0, it will match %any6. libreswan-4.14/configs/ipsec.secrets.in000066400000000000000000000011431457372064200201730ustar00rootroot00000000000000# This file holds shared secrets (PSK) and XAUTH user passwords used for # authentication. See pluto(8) manpage or the libreswan website. # Unlike older openswan, this file does NOT contain any X.509 related # information such as private key :RSA statements as these now reside # in the NSS database. See: # # https://libreswan.org/wiki/Using_NSS_with_libreswan # https://libreswan.org/wiki/Migrating_from_Openswan # # The preferred method for adding secrets is to create a new file in # the @IPSEC_CONFDDIR@/ directory, so it will be included via the include # line below include @IPSEC_CONFDDIR@/*.secrets libreswan-4.14/configs/libreswan.in000066400000000000000000000001121457372064200174020ustar00rootroot00000000000000@FINALLOGDIR@/pluto.log { missingok notifempty copytruncate } libreswan-4.14/configs/pam.d/000077500000000000000000000000001457372064200160715ustar00rootroot00000000000000libreswan-4.14/configs/pam.d/pluto000066400000000000000000000007761457372064200171710ustar00rootroot00000000000000#%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-4.14/configs/pam.d/pluto.example-url000066400000000000000000000016741457372064200214210ustar00rootroot00000000000000#%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-4.14/configs/pam.d/pluto.example.google-authenticator000066400000000000000000000006761457372064200247450ustar00rootroot00000000000000#%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-4.14/configs/pam.d/pluto.example.sssdldap-secureid000066400000000000000000000014241457372064200242270ustar00rootroot00000000000000#%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 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-4.14/configs/portexcludes.conf.in000066400000000000000000000007301457372064200210670ustar00rootroot00000000000000# Direction Proto Source Dest Prio # # Exclude ssh incoming and outgoing from IPsec encryption for ipv4 and ipv6 #both tcp any 22 1023 # # Exclude outgoing HTTPS from IPsec encryption for ipv4 and ipv6 #out tcp any 443 1023 # # Exclude incoming SMTP for ipv4 for ipv4 #in tcp any4 25 1023 # Exclude incoming SMTP for ipv4 from 10.0.0.0/8 only #in tcp 10.0.0.0/8 25 1023 # # All udp port 666 should go in the clear within 10/8 #both udp 10.0.0.0/8 10.0.0.0/8@666 1023 libreswan-4.14/configs/private-or-clear.in000066400000000000000000000013301457372064200205730ustar00rootroot00000000000000# This file defines the set of CIDRs (network/mask-length) to which # communication should be encrypted when possible, but will fallback # to in the clear otherwise. # # This is enforced (and can be tweaked) by setting the failureshunt= # to passthrough. # # One IPv4 or IPv6 CIDR per line, optionally specifying a further # narrowing of protocol, source port and destination port # # examples: # prefer to encrypt all traffic to an IPv4 or IPv6 host or subnet # 10.0.1.0/24 # 10.1.1.1/32 # 2a03:6000:1004:1::/64 # # prefer to encrypt all smtp traffic to some host # 10.0.1.0/24 tcp 0 25 # prefer encrypt all incoming smtp traffic # 0.0.0.0/0 tcp 25 0 # # Ideally, enable this for every host on the internet # 0.0.0.0/0 libreswan-4.14/configs/private.in000066400000000000000000000011461457372064200170760ustar00rootroot00000000000000# This file defines the set of CIDRs (network/mask-length) to which # we MUST communicate in the clear. Otherwise traffic is blocked. This # is enforced (and can be tweaked) by setting the negotiationshunt= and # failureshunt= to drop. # # One IPv4 or IPv6 CIDR per line, optionally specifying a further # narrowing of protocol, source port and destination port # # examples: # encrypt all traffic to an IPv4 or IPv6 host or subnet # 10.0.1.0/24 # 10.1.1.1/32 # 2a03:6000:1004:1::/64 # # encrypt all smtp traffic to some host # 10.0.1.0/24 tcp 0 25 # encrypt all incoming smtp traffic # 0.0.0.0/0 tcp 25 0 libreswan-4.14/configs/st000066400000000000000000000007301457372064200154430ustar00rootroot00000000000000# Direction Proto Source Dest Prio # # Exclude ssh incoming and outgoing from IPsec encryption for ipv4 and ipv6 #both tcp any 22 1023 # # Exclude outgoing HTTPS from IPsec encryption for ipv4 and ipv6 #out tcp any 443 1023 # # Exclude incoming SMTP for ipv4 for ipv4 #in tcp any4 25 1023 # Exclude incoming SMTP for ipv4 from 10.0.0.0/8 only #in tcp 10.0.0.0/8 25 1023 # # All udp port 666 should go in the clear within 10/8 #both udp 10.0.0.0/8 10.0.0.0/8@666 1023 libreswan-4.14/contrib/000077500000000000000000000000001457372064200151025ustar00rootroot00000000000000libreswan-4.14/contrib/README000066400000000000000000000010411457372064200157560ustar00rootroot00000000000000 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-4.14/contrib/c-swan/000077500000000000000000000000001457372064200162725ustar00rootroot00000000000000libreswan-4.14/contrib/c-swan/Makefile000066400000000000000000000011101457372064200177230ustar00rootroot00000000000000.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-4.14/contrib/c-swan/is_encrypted.c000066400000000000000000000035711457372064200211340ustar00rootroot00000000000000/* * 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-4.14/contrib/c-swan/swan.c000066400000000000000000000156751457372064200174240ustar00rootroot00000000000000/* * 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 "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-4.14/contrib/c-swan/swan.h000066400000000000000000000017121457372064200174140ustar00rootroot00000000000000/* * 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-4.14/contrib/cisco-decrypt/000077500000000000000000000000001457372064200176525ustar00rootroot00000000000000libreswan-4.14/contrib/cisco-decrypt/Makefile000066400000000000000000000004231457372064200213110ustar00rootroot00000000000000all: 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-4.14/contrib/cisco-decrypt/README000066400000000000000000000002601457372064200205300ustar00rootroot00000000000000See 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-4.14/contrib/cisco-decrypt/cisco-decrypt.1000066400000000000000000000020261457372064200225040ustar00rootroot00000000000000.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-4.14/contrib/cisco-decrypt/cisco-decrypt.c000066400000000000000000000104631457372064200225720ustar00rootroot00000000000000 /* 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-4.14/contrib/cisco-pcf/000077500000000000000000000000001457372064200167505ustar00rootroot00000000000000libreswan-4.14/contrib/cisco-pcf/README000066400000000000000000000006761457372064200176410ustar00rootroot00000000000000This 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-4.14/contrib/cisco-pcf/pcf2os.pl000077500000000000000000000020501457372064200205010ustar00rootroot00000000000000#!/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-4.14/contrib/cisco-pcf/sample.pcf000066400000000000000000000010461457372064200207240ustar00rootroot00000000000000[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-4.14/contrib/ipsec-dyndns/000077500000000000000000000000001457372064200175025ustar00rootroot00000000000000libreswan-4.14/contrib/ipsec-dyndns/README000066400000000000000000000004011457372064200203550ustar00rootroot00000000000000 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-4.14/contrib/ipsec-dyndns/dyn.nohats.ca.key000066400000000000000000000001321457372064200226570ustar00rootroot00000000000000key "dyn.nohats.ca" { algorithm hmac-sha256; secret "NotTheRealSecretKeyObviously"; }; libreswan-4.14/contrib/ipsec-dyndns/ipseckey-update000077500000000000000000000041301457372064200225220ustar00rootroot00000000000000#!/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 < 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-4.14/contrib/lucent/UDP501encap.c000066400000000000000000000176531457372064200204410ustar00rootroot00000000000000 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-4.14/contrib/munin/000077500000000000000000000000001457372064200162305ustar00rootroot00000000000000libreswan-4.14/contrib/munin/README000066400000000000000000000001571457372064200171130ustar00rootroot00000000000000 this is a libreswan plugin for munin. See: http://munin-monitoring.org/ It requires libreswan 3.20 or later libreswan-4.14/contrib/munin/libreswan000077500000000000000000000175671457372064200201640ustar00rootroot00000000000000#!/usr/bin/python3 """Munin plugin to monitor Libreswan IPsec connections. =head1 NAME libreswan - monitor Libreswan IPsec connections =head1 APPLICABLE SYSTEMS Systems with Libreswan. =head1 CONFIGURATION This plugin requires Munin config /etc/munin/plugin-conf.d/libreswan: [libreswan] user root =head1 AUTHOR Kim B. Heino Paul Wouters =head1 LICENSE GPLv2 =head1 MAGIC MARKERS #%# capabilities=autoconf #%# family=auto =cut """ import subprocess import sys from collections import defaultdict def tree(): """Tree of dicts.""" return defaultdict(tree) def get_stats(): """Get statistics.""" # Get status output try: output = subprocess.run(['ipsec', 'whack', '--globalstatus'], stdout=subprocess.PIPE, check=False, encoding='utf-8', errors='ignore') except FileNotFoundError: return {} # Parse output values = tree() for line in output.stdout.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('{entry}.label {entry}'.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 security') 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 security') 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('{entry}.label {entry}'.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(): """Do it all main program.""" values = get_stats() if len(sys.argv) > 1 and sys.argv[1] == 'autoconf': print('yes' if values else 'no (Libreswan is not running)') elif len(sys.argv) > 1 and sys.argv[1] == 'config': print_values(values, True) else: print_values(values, False) if __name__ == '__main__': main() libreswan-4.14/contrib/python-swan/000077500000000000000000000000001457372064200173715ustar00rootroot00000000000000libreswan-4.14/contrib/python-swan/is_encrypted.py000066400000000000000000000034251457372064200224370ustar00rootroot00000000000000#!/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-4.14/contrib/python-swan/swan/000077500000000000000000000000001457372064200203415ustar00rootroot00000000000000libreswan-4.14/contrib/python-swan/swan/__init__.py000066400000000000000000000072051457372064200224560ustar00rootroot00000000000000# -*- 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 its 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-4.14/contrib/updown-example/000077500000000000000000000000001457372064200200475ustar00rootroot00000000000000libreswan-4.14/contrib/updown-example/example-terminate.py000077500000000000000000000035671457372064200240600ustar00rootroot00000000000000#!/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.xfrm (for protostack=xfrm) # This is an example that logs XAUTH users to /tmp/terminate.log when the # tunnel goes down: # # Inside _updown.xfrm 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-4.14/docs/000077500000000000000000000000001457372064200143725ustar00rootroot00000000000000libreswan-4.14/docs/CHANGES.freeswan.pluto000066400000000000000000001171261457372064200203500ustar00rootroot00000000000000Changes 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-4.14/docs/CHANGES.openswan000066400000000000000000002177011457372064200172260ustar00rootroot00000000000000 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-4.14/docs/CREDITS.freeswan000066400000000000000000000056111457372064200172260ustar00rootroot00000000000000We 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-4.14/docs/CREDITS.openswan000066400000000000000000000046021457372064200172450ustar00rootroot00000000000000The 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-4.14/docs/PlutoFlow.png000066400000000000000000001064051457372064200170410ustar00rootroot00000000000000PNG  IHDR?Z pHYs M MέNtEXtSoftwareGPL Ghostscript 8.01L~ IDATxrPs+9jIȀaIcԮ]!lL<; @$wwLT]>4MuxxեW}΍vz7Ǿ<7>^f,:fGӇd޺LKHZ5})&.huN?9d~L V4m^dڏj5pKNVw~ujkΣ+{yYBc[˪=WW* ys=?zmybV˃j6ʞvWVUsRdcO7)ɭ}e=.~/E|߾Qd;Yݤ-7Z{-,>e x˭frW3Wt ۻؤFioOg!:w&|mOL'FjކYkG+7pٳї쏰׆ Y3Pv/0K'-qwyo2ƑYo]Dquw+>k[c[wFV;ްڙٱl[ދ׻װ묫s^ҭg{k^6ʽW7 [<^@F5&{h.@F4wyB<D"  d"p( "  "  "  "  "~V;;۟mSKwFv3B<tC~l ?'ZKn/i7m,|/OUW[\=2ּ;s}%k.WYֲm.O\lAvnl`{-4ZkW;v@Pb "E>/~Os"@[H$xDH$xDH$xDH$xDH$x.PUHL4GIп4ww6,OWW]'4Wfc Y!y3yJoBl']rgҖDtaګ}  6Sl d2dr!Qw*d qeԈ+ YqL7omHScQƶCʂޣ_gߡx{ZovWQup,k)W;:1kx{d>l+?mMsꝔ$s_e߶9xzmu󱔇\'Q?G0U4gdYvFV;ou/]X_%Ͳ{y[-W;>~{Ƚj~܇9brzRM3{:._6 wWݺBqg^U%_,B^j{HVfS*ţ:<@eg8b]y{ E:,.olܾjܭڕMoo?ƟݍF͞ޖ-,w3u8-T|њoʉ_2Tm1B na 7?nG,x,HHHHVMH$xDH$xDH|~Hl[F#ѨH$xDH$xDH$xDH$xDH$xDH$xDH$xDH$xDH$xDH$xDH$x4M$C1}Y8ϻ|D!d!;%CQ5CXra4% . 5cQNI?c "a*g< Ji %p @h< ;tCH$x#RTqI00}  "a8i 4 "a F<D"X @t<D"@$ww8`9Y?&C0T@$<D"@$<D"@$<D"@$<D"@$<Dwwl~^Ӕ|=q<}j w``gݦɻ\O{wpN*DH$x#@$<D"@$v۞Z[v? SQ}eV.=5,+UZS0["}\Rn[dkal\O^Irڰ0})i\o{X *$2]Nusٽ7ʢc05¾ho7.x; qvo7r@N;ݲ0 vI.]e$Gs'hdρ*·'$y;ľ]Wߺxkw [~Wc n-l̵<>,5v8Nhb[V_𲟍V7~'{ڻ ط{t<Л[2etgZ5@$x 3j^i;@$x aTfsrEHAZ!fPH<3'@$<a  XJ $xDH$xC zg1eߤk޹&ip6eS4;6Mޅf)_Fd   "RI9 "  .e'R@H$xDH$xl3IK<&| $xDH$xDKR@L~@d<Dwwe;=N1x `=<8]I0;2eidckTiKtzuramu)Ӗ˦Ȏ+5iDp+c00yVC[m۶4/[Fkޖh|Ynt2;s/3Ɇ[7]ySn￑ HWH6}m6[M՗\mh\3aٗ[f:!la,kj_VBٽ{p{25.llujz9lz?_CYxU40:S5Vȏ6=KVXʭv( `ޖ٬{3*Gu5ϯ$ V,|ۥ(dfXqn,<9(g&')eI?,` ߟN ]ٽ;|*ZoUD.| T@anKhd4[plw" 2Y*^IPE\| $x"xHu[2@$xwH0(C$a,=WC<&| X.N_.T#계&HEr%IH0>3~Y;wݙ&qWqavMkW{:cr6MޅrYrH$xD<g "1Lf6@@$xFWGD"  "  "  "  "ӟQ7 Ky<DwwO$<_.lv:^ݶy6n[Uy8Z=i]IL[afmmU?;FMwz%ClKx-#l&ѿin-z"Cu'L/{~m7}exwBAyb僭 1<1x-~ժM!,o/ZiVڛF,蒛疻'{ڻ$-}r<m=Ç|0, )i<C$Ç|0 "D%oICjy49H78DH$P '`@(g824= %F"x$;I78DH$xDH$]^ ?MӀ3ʍy$ywG Hα i?3Y#ʲ;r:t],ZfTi7Z[\^.U3tF&i͂\nmA}ҕ.M)6Zv㓣&?<.I(J5Vpz=NL8h=0 !M@0[~NjIsa7[svīK Fw~L2pW#ؔ&uU<1x`i7s:{N&ْ5 agMdwn"1z5+jQ$xKp U4HHhdl 'fF*DH$xDH$xDH$xDH$xDH$xDMtwc$x\#O4/;|NUCwJ!dy]|$xZ'vBa ;t@Q7. I0: X'<¸;AA$xD($x1aD . "a, i : Fr @$< `<&@$<D"@@$xD$xDկ B!)K\*DH$xDH$xDH$xDH$xDM.aCHгyKc_NqpR<˗x4M:+Ww(]RӭAHЛ%Vcndz^MiN_^YmU_彡է>`{14"W?|G1xPKl0*U>j)~e=?=1xDH$xDH$xDH$xz U'V7:\B^ozk~K^ytue=Ku۬W2 _6[m V+j^e;}< !oKx{T{Ouu/:+ $kc6wtA1U40%6i+!AnE){&P_oZcjgYqZ^_]W uW{KcaLi9x`"_fNS1xDH$xDH$x\4 `pySEHHHHHHHTY$x_5/ yywH0,z$x:ʾvBaK< a];%@w9"a,i : gz"@$)<D"@$<DwwFrqyT0*cHk@nax)h4͵_[aD}1My [ קͫKuٳi[=߿Ɓ4 xc0r;y3+­6ƫMoجekْl`YR00#,]|dyVeOȾVd;eÈa.<ʫeĥ,i٬#~2@aq&:@hh腫S` <D"@$<D" 35c  "  "Jn8 ҉;DBQe-_9o멷Olb5~i{$?"1x[xx6 M:7m|)$x_5CqIйu5<"~yT0 "@$xߕ@\<Ϡ;DQw>H0(H04CP3ݐa F<Ȑ<%@$)> Z׾.Q -N'~ <\!܍b 5HlGC뇝|Y!^{5G"TшOޓH>Dj':X'˨urS vVذqC81xHdw (oխa)\E,K:ttr&@m\nx*[mWٴ?[!o 0d|O:ZA{7I{ZE3O x0cغtiZAUҮɖYqjyiVuljOފko':<J!ħ]yGM61xz)h  "aZ9s}, ~+yˍ\q<Db6IC6nY c1Hp)<|@H$xaxsLfaq|['ɍz;n3{9In'1U4HHM  $xoY4$xj0-?Ig멷Ol򴽗+L$ S2}d廿&gŲo΢^zM3$O]kisAdoC/‰M_^M0sќ'W9~{k8m9g5/weIYްfKeGUUx=ޫmfk9wY.]#?ΫJU;w ~UZd5ѵꚯwҞֶz`o;R'#i;~k[\Hmd+Whw)ߩoharq'vY~mm@i12'?[Gj}m Fovj먳-ոnmgdmᄡlw; Rx{\鍗mW۷>?Ъ+8g*WmgBvWZwff=7Zt?yՂxlr=W*L_~11&:L$z7:y`gC%~8OH$cL1p: >z$x)|F}'$x-4vi>"|DciRMyO,k$cw`(oK?6&æyWnhHNt^D]Z,H<@GnL]ݏ:B-/r4eO֦ԩóI\"sεssǾ˷Nlb} <ƝQETs1+ Z³:o)!Tm{`e'f5R4s+d SղjlFlv+zoM0m851bG3ϳ7Bz{mBuۧ?R˒d]I;3*韷S:޵~c<#Fua V4nԻ^nN_ r_&@G; 5nTmyyNW vM ?vj5XmǞ5I%c.s3=W=xmQ6эN*u)ٳo2N#GFC"T MF=U4tNHp I}H9`'AG%@$1{(mԜe)d\`paLO"8/0I98* "1 q%+9߃:ru/Sz1 F 6q>/<$}Siaw@6M|,hm630?lǧ嶛PLi9+,?/ o+;cݜzzӨ=\Ɠ~%k<]`첵lۯŕp exm +V_@ιhj fe.Z:ߔUzDe Rk4ZH̿ 7K˧) IDATGXߖߢ}.~()iEc1m:U~*M?AE oY394eY/l0Vjj_ל7_:}ͺ m >BJ\j~B ŝf56@&<yԛllai#SNk/_~S]9umx~aٓl,:O_T %ÿbV.`}{|sꏬは:!vҍZ5k.W]wة1ν^\`pN.myVCk?ŏyy`}ORⳟEJl5ݸ;uQ߫;6wry!iZ?.l4I.'m•eSFd6LBOR^ZldYY\gJlƫ'k_=٘5K1zו:rgI79vs9OVbRɱ-qu(šnβq(U6=IpLDm6nنӴ}Ttgas|&"NJ40 (\n27H{61FJ;:,i' 1!pc;Q+q驹'%;ma)6Fyt^slcZk__Edž+Yb4tԾ!8gg }3h|YL_o}Ck| nA}xmIfI/~6)Nb3l^q m=n'k6^+JY.:peS-;oJ g .WmnOOb'ݸʪH ӑkD.~!;.u\͉Onh(-Ok4z??I]ngڼXpjO?̖7n]Q{f(@wߐS+k3ڈ?ܮU ;U6p~}Bnl~-lm/k_Nq/U4d>[4gUĽ~g*ZNq/ ;=t6SIsD4ǐ1$xdpn\EH$xD`N&W1 1   "ثNq?ww a6.H@SV*m%W't*<D"@$6&^<D"oc.:Ft*<D"@$<{u2G'ݸhHۘ{I^'tҍHh+Ydpn\EH$xDH$xD\4K\4u:U$xDH$xNq ~Wp/ "1   :)OW  ~sp/ :W1   "  ~s%t*<D"oc.%@$<{ur`'ݸ àW1ҩ=` ~$ΎG D"W'vҍHH۸ NQ'ݸI9H;:?I/j|QhyjZљwp oFzNW㴅-O1:[&=62=Ho5_ү tO,;~6,z0[fF?}?#cNgc(w(]rm̵ISKŕӦ{]'34sߢ[[Zוdi? f˗.٭x ~!5oZ+؎kQIғkzu y-O8z#ë}-YFӭ>+BBYkc5OɁI7" /;_RY>UMV^!onqQߕ.޷[Əi s#| {{o#BQAM3yTq{.*X:U$xx;ǰv6p0iBsNHI1['ݸMIx ~WMp/ :)OW  "  ~sp/ ~sI4W  ~f}K4;:Nޖm70}hl핗/'[y>Ѫ5U<;W;l +C5w깁:x^8eA|Ft /\v5ѩW1F ~7 UzK]iN^Yn\<%'ͧ9tD_e3H6OOz3o {.$xR'kxK{ e_$wҍM"IO'<TM_hXI7"BX$x\3tԁt;U$xD`eYHO'<kf"ثI7"@$< />D"<8I7"@$<D"bNx?ww ЇaxKT'K;UT[]]muNq-c,6(TY'ӯh?wW9t}I'qv=:/;U@$<%/ЂWavw$<>ۀgf]ud<D"@$x%(=ԮЇk}Qx:YB.Fמ|&~qpg 0U Ə.׿}2ou~NnD'3h(y,a*t[b9gy "u.8fvk%զ ] 1x5ߢ,X\&tƳnm8EtyA;k9TH<!׀~N9*ϣ!,ϻzc(G;0EF)˱j9ث:0QE>$Ѫz'?ڲYS3t׎ g}W.Mw\̺T nm/vVN̆z"'q8MoSm_.-?vC'5 q40x9?=Ӷ+H/$x77_vMk, \`+ Ä :  "g,rG'x_gYkvrM3{?u|>N7Xtz<{k 1&IlX4/#Ht;<@~,lѵw`8￳1EPE˙|jq3<{kT kOe-++[غ <1xkTwN]i# s.6VX-j٥b%j}8б+@t\YR|"QIݯbaHoNۿKY3BIh2⳵TUl'ҸkHql18]KKQދ˗]m|rUɓvƳ_[kԯl^6TE@p?5 ct.ӓ vR[g ":*.6#rUéH$xDaU7qLqHS"8X8GLy~z}vT6R57m촱UZ 8^Q>]a(5k.7l촱GvW CղZb#^N'ƙCél^{쟵tr^>qbS+w Ն\M>}};wMe^j-v<ҢvRZqrɎK\F<#zQl\H^s9Tg}_V{վt^%Nbp>lqs2~i~K[k@]u)a۝Wa+xcͬ0ѱ/_찼V2ڻ¾V2mlGqe ޮ83!޲m-$x8Fj%"/IcͻGu&ogbդv|HHHHHHHH@a _<2]"  "  "  "  "  "  "  "  "  "  "  "  "  "  "  "  "  "  "  "  "  "  "  "  "  " ?ww0 wwq #_H'qv>h  "  "  "  "qG':=qҨTR핇aȶuýA.&eh-aA<^9缣y@ ? @\LM|SVΆ :cEv=ԞӬp$x:p#Muu>=O!8@Y =c0U.c-O W&řпUדm+/͌/v[1vő=Iv2n3q+Ips8ev :%q_ ozJEW wtH$xDH$xDH$xDH$xDH$xDH$xDH$xDH$xDH$xz7 ]qZkYaIENDB`PNG  IHDR?Z pHYs M MέNtEXtSoftwareGPL Ghostscript 8.01L~ IDATxA 0C/U, 8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qP@%J<8x(qPn81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81uJDhIDATx81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x81x8 c 'IENDB`libreswan-4.14/docs/PlutoFlow.svg000066400000000000000000000636551457372064200170650ustar00rootroot00000000000000 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-4.14/docs/ProgrammingConventions.txt000066400000000000000000000124631457372064200216510ustar00rootroot00000000000000Notes on Pluto Conventions ========================== Pluto previously had its 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-4.14/docs/README.IANA-PEN000066400000000000000000000003271457372064200164030ustar00rootroot00000000000000 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-4.14/docs/README.XAUTH000066400000000000000000000053321457372064200161450ustar00rootroot00000000000000 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 use 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-4.14/docs/README.labeledipsec000066400000000000000000000002221457372064200176610ustar00rootroot00000000000000Be 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-4.14/docs/README.rfcs000066400000000000000000000157341457372064200162200ustar00rootroot00000000000000 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-4.14/docs/copyright-sh000066400000000000000000000011641457372064200167370ustar00rootroot00000000000000#!/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-4.14/docs/diagrams/000077500000000000000000000000001457372064200161615ustar00rootroot00000000000000libreswan-4.14/docs/diagrams/NETKEY.png000066400000000000000000000307771457372064200177040ustar00rootroot00000000000000PNG  IHDR+ pHYs M MέNtEXtSoftwareESP Ghostscript 7.07 IDATxYPFe'ئXs~dxc* I@>]׽5.EȞ1.b 4i3+sz.bK9o-N%qJ.>+H'ЀsI]g%j<'TZ$rIT]E;!sI}yb\J T\J \J T\J \RK(&PorI]d @ch>%5VU,JT@?wO$^+ 9>hTYxPW%^#&PӉ]Z*E5R|ח|wuPB%(H w[}6`'c>,m(r1=k`8,b|XkY\ ־@] ;;Gm+]&EmZ{n.h8~\CD_Lx024i'Þ6>@o{k &/n 8Į.&qvL*@%z=~;?O%Xʒ'q8͜Λ!s}ЎF2I~*K ǹ*}S_Rc4J ߗ85F #,*|Kj2J?՗G$D~Q 8FJ`N; u+{EGT!y wq*,bpc+ m_U8,~ qY Wpnىaqr"s܇t&8ޟ@6&ֹdPrE.)J58m,fBEti.)c U_VFJ ۼ( ޺:'5ԗ@\3" k*=![ BH`~WܥDe&vjqKsFVv%@{ _+/U~cćnΎcGXԗPBL,>C|f>%\rR_@;J]#J ;^!\@.C-!nv|Ȳg*KҼf wY<8> 7<짾z,RY`qr B.R%@ H!) \Kr B.RxVyoL d{hR%@ H!) \Kr B.>]wϛ3{%@ H .ûM0eHkp/Z߆8OQ(̩Nq$I v]W>Gp6%Ti4-FM%TL%Gc8XI`mˌ$\F;); ~}; S_Ǜ#r e1HӉ#\s\GH~!\Dl8s shs78BۦqF8,.r6=2F1@qr B.R%@ H!) \K g%:y"긐L<$kS-(K} Luh:hBTg~d>xdbkr/AKՖIxHeI3|}@nƇyJw\}G.':"& uzhç=%aRYu0dT4\ٞȍxc{&x{_O0vf,X(_-e.QBr/>0y|Y4e-+?vNRt?m'_:e>GmW%BHnք {*Q.$^k-wc\Hm5*Z#G{d#★HمN@[-v3U[ugK} L ,w)Vz<+u-MK`]擖ŝ'樌RiIr o)ڠO'4yǒK){:$KwlH%@ H!)2~+\l)J.eI޺Cr=ŏǒKm'sJkͨ8&y&.1UljTw.q`Ps В;{Y>bsT60=h}v \KRt]wexYZ !o}nXB.R|?C-0T)8$eŁI6,6^I8딖q>q#owm&nQH8\ЬqĠ=S?v5+C֮gv=ar'X-ԗpw#Ͼ{4[U|xlr-qZW!fOM$ոx9 *K@Pͥy[Ҟvh)qk"ak|'<_g5v6 M~kk9dceJm[ 7MR.1ך{3T$Vwb=:Ǿ䦛tV _cmqb H_SḌs =4%k Eg3ETuD뱞v`?j* jd^uYq&=~:7+ J.]$ <:8 ۲l\2%)Tr W8ss3`Tpq(yr@'o J 5K4r B.R%@ H!) \Kr B.R%@ H!) \Kr B.R%@ H!) \Kr B.R%@ H!) \Kr B.R%@ H!) \Kr B.R%@ H!) \Kr B.R%@ H!) \Kr B.R%@ H!) \Kr B.R%@ HhYuwz}*.r n!Ўh䗫WMIi䒗#; 8@ H!) \Kr B.R%@ RuV{;4^0>/zń#9"\뺾)<0K~U՗h V%Ǥ"SIly$_r^>J)ic-v D(arIY j4mKUv|Z>\}ǚr).e7v~/~Ѐqkft^'B.iZPI3u+%;'%yٴv5hs. gOhXɰg@ɞ mK4iHr,V>'iK;Y)F\ qy%Ou ^ <\Nr(_K B92L.,,FY%K"Kr B;꽵 'H'!v \Kr B.R%@ H!) \KǛ8|k8J#.Qe?1iǩ=%@ &Lh\R'Kr @6TW]m6A5-Kj#0vWsu嫍;#8p=# И;<9”vE#U?‡|9#jI}x#ly_|-敲  $.=LRPN9s>Ip\66*3N2_UhIr @qKr 7߮3n<'3b[ wck+oS.6<@oǣ{|7O8\==^?j<} ,70WgKN1|wh&_g [h8{'G} B.RhXIp `J7v \Kr 0ɪ>~>v \Kr B.R%@ H!)3yVu?zkGxA.:Cv]7'UK8yqa͙˨/x% _m9jvtXdqΙk%bi9,)fwl9sFH;P#Ǯ/eBI]u:YjJH!) \Kr B.R%@ H!) \Kr B.R%@ H!) \?}]w"NraΛu9-*@io'ЀSKR+*Ƌ{5_m"(+`jwـPV v|} l@Kڎ6 T S_Kr B.R%@ H!) \Kr \ק:╁'qC6vL=Pw.Y4Ii]փۍw!mlhF}dj`zOs 4q{`a>xZ/~+NN8Q\w?o_.ـPqn n)W K5%/,ր9ь/<-%cqn* IDATg\imW]|6IG3k.hBE/@Eח") \Kr B.R%@ H!) \Kr/tp.ٯn{zg:N/irGlmHGpJ^cecBE+rbk]aB18@ H!) \Kr B.R%@ H!) \Kr B.R%@ H!) \K[0g3%{}_Zܽ[p!IxqY8ImDIwO繖 \ -d -oif libreswan-4.14/docs/examples/ipv6.conf000066400000000000000000000016261457372064200177500ustar00rootroot00000000000000# 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) 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-4.14/docs/examples/l2tp-cert.conf000066400000000000000000000030551457372064200206760ustar00rootroot00000000000000conn 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 # 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-4.14/docs/examples/l2tp-psk.conf000066400000000000000000000032051457372064200205330ustar00rootroot00000000000000conn 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 # 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-4.14/docs/examples/linux-linux.conf000066400000000000000000000022051457372064200213520ustar00rootroot00000000000000conn 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-4.14/docs/examples/oe-authnull.conf000066400000000000000000000024571457372064200213240ustar00rootroot00000000000000# /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-4.14/docs/examples/oe-dnssec-client.conf000066400000000000000000000010411457372064200222070ustar00rootroot00000000000000 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-4.14/docs/examples/oe-dnssec-server.conf000066400000000000000000000010121457372064200222350ustar00rootroot00000000000000 # 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-4.14/docs/examples/oe-exclude-dns.conf000066400000000000000000000003531457372064200216740ustar00rootroot00000000000000conn 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-4.14/docs/examples/oe-letsencrypt-README.txt000066400000000000000000000024301457372064200226600ustar00rootroot00000000000000 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-4.14/docs/examples/oe-letsencrypt-client.conf000066400000000000000000000007051457372064200233120ustar00rootroot00000000000000conn 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-4.14/docs/examples/oe-letsencrypt-server.conf000066400000000000000000000007321457372064200233420ustar00rootroot00000000000000conn 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-4.14/docs/examples/oe-upgrade-authnull.conf000066400000000000000000000027221457372064200227440ustar00rootroot00000000000000# /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-4.14/docs/examples/sysctl.conf000066400000000000000000000034461457372064200204070ustar00rootroot00000000000000 # 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 packets being received, 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 XFRM, the kernel # kernel thinks it can be clever by sending a redirect (because 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 # 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 # 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-4.14/docs/examples/xauth.conf000066400000000000000000000011351457372064200202100ustar00rootroot00000000000000conn 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 cannot 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-4.14/docs/l2tp-overhead.txt000066400000000000000000000001351457372064200176060ustar00rootroot00000000000000IP 20 UDP 14 ESP spi 4 iv 8 auth 12 pad 8 total 36 UDP 14 L2TP 8 PPP 2 libreswan-4.14/docs/nss-howto.txt000066400000000000000000000077231457372064200171050ustar00rootroot00000000000000######################################################################### # 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. Note2: We are assuming the new default location of the libreswan NSS db to be in /var/lib/ipsec/nss . For older versions this directory is /etc/ipsec.d Note3: It is no longer needed to specify the certificate in the ipsec.secrets file. 1. Create a new (if not already) nss db on both machines as follows: ipsec initnss 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:/var/lib/ipsec/nss Copy the file "cacert1.p12" to the machine2 in "/root/" directory. On machine 2: Import the "cacert1" as follows: cd /root/ pk12util -i cacert1.p12 -d sql:/var/lib/ipsec/nss certutil -M -n cacert1 -t "C, C, C" -d sql:/var/lib/ipsec/nss 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:/var/lib/ipsec/nss (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:/var/lib/ipsec/nss (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 ######################################################################### # 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 /var/lib/ipsec/nss example: certutil -A -i CaCert.pem -n "CaCert" -t "C,C,C" -d /var/lib/ipsec/nss Import a cert: certutil -A -i -n "" -t "C,C,C" -d /var/lib/ipsec/nss example: certutil -A -i serverCert.pemm -n "serverCert" -t "C,C,C" -d /var/lib/ipsec/nss Import a client cert: certutil -A -i -n "" -t "u,u,u" -d /var/lib/ipsec/nss example: certutil -A -i userCert.pem -n "userCert" -t "u,u,u" -d /var/lib/ipsec/nss Convert key: openssl pkcs12 -export -in userCert.pem -inkey userKey.pem -name "userCert" -out userKey.p12 Import Key: ipsec import userKey.p12 Show a list of the current certificates and trust attributes in a certificate database: certutil -L -d /var/lib/ipsec/nss libreswan-4.14/docs/opportunistic-v1.historic/000077500000000000000000000000001457372064200214635ustar00rootroot00000000000000libreswan-4.14/docs/opportunistic-v1.historic/opportunism-spec.txt000066400000000000000000001407531457372064200255650ustar00rootroot00000000000000 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-4.14/docs/opportunistic-v1.historic/opportunism.nr000066400000000000000000001304361457372064200244320ustar00rootroot00000000000000.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-4.14/docs/pluto-internals.txt000066400000000000000000000347461457372064200203110ustar00rootroot00000000000000Routing 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-4.14/docs/testing/000077500000000000000000000000001457372064200160475ustar00rootroot00000000000000libreswan-4.14/docs/testing/testnet.fig000066400000000000000000000120121457372064200202200ustar00rootroot00000000000000#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-4.14/docs/testing/testnet.png000066400000000000000000000275261457372064200202570ustar00rootroot00000000000000PNG  IHDR'ZG pHYs M MέNtEXtSoftwareGNU Ghostscript 6.53nGu IDATxQc<ٷ!"Hd9n5h+=]a@ua߈+Rc,)W;|]2qrϐ? ( Œc.PώRb"u uл.*w蜫EP%(w!uЯ….sR@ RzeDrWϤ.EGOrW&tNac#{'TtFE%g}*g#rSZveu[صu3] ?1qj՞vNmf P66]٩)mHhZW$д#xvTk42oert6-_H wcjۯժU16XwԖȶL`7)wW0'N`o)Lyj8u:e]xz*6DRWZoͤd,E:ĺ6=\XH Z-wRl)E&X=~s<廔.ܕ^;nۑ&vZ5Iŭ6MD]a”^g\L{xMI\씹l?`;\U[ďzzo$7N8ݶ{7[(@vgF"-0x~%H|fyl ]wÉO(ŻWKCad9qz'׶1/^uN8omUDЗ\T_줮$<5Eӂ+^y{5粜f5}|,rس֓Үgit&Υ]8G?"RXNyjm ͉jo-RZKM\`V>"ˮvb;xg.˗Gv ~Ժ#R:ރqgL<qڼ V@Պo_N$cڇgOQCϠwe=к@P낰将\L.)<xKia(t1U<.fj]E.....V.Ob"C$qa(A(A(A(A(A(A(A([wI]|rǡ>9PPPPPs^{g;N]F΅|tSIƅ6Ժ=e=k.iWP+=gP0 8Ggu1˨4`y(01]VRWujCEZԺkr=?28~/{u@4ti(=lO[p' ]wNYۦrǂZ$ombAZM,a8|gq .a_`jv߇aBdDt`מux<4ߠxl萷ζhZK)V.8u}72Ap#{L%uBRSu"+5)3        צw&O P#%H]%H]%H]%H]%H]%H]%H]%H]%H]%H]%H]%y{ 08g[7V9-Z] |_ M8 ^JpHþ5z"c_yR tB|4y5Ub\3z"[W+ &u%Ĩ@ ސ˃"}*OPs)@sm:x|KZksgnI^Ga*ij.kuaugݰ[$ճ)ps-_:=~򷏯 ŲµxV$e4^7ݖ̸I]~ #6m$N.|u@64ňUPb2[x)Yė5wQQ)K[>NhxR@FH=[Kj]AL)/tܵ|pTO]jBj]Ћ,3?xyuzmy&;,brAWԺzET 3ͲȬOL uɘc2f4A Tb)SJ_`BJ[9.=rڛ8RZ2(Y4uad3]_Ωuk잘j.1shq.9)IhoB#В`į߿G/#]$xfl!xj .%hrTǽG'KWd.@? …oS(A(A=8c' F..............ӆax{ߠI]%H]%H]%H]%H]%y{/ϫqyY4)gog|-j]@N`wsj]@ b0 WueVPHZd3c[vmQ{q.bG/ٲUA8ΆFb VƖC^^wS!u#c| ie<+a-RMordR[ɳu}\2$e@6F,r& PbݲEЕԕr}apmՅ-&ۅ\=rM. nyKܳ+GߕkߤHۧF;=6*-;4a~{;O q›Im[eJawG #P 7پ*8e{M7Q;~S.#~P\ @v(Iv}{Q+ҷ1k KOGUolO'|}Ǜo#M01..u ^ϭZ^D%)KK]@L?M~͏!uI>s0 eVFkҤPPP}Dr# ށan.s8&^a_=߇NmO_T)R =.l"-:"ھԺBxݵ}ξul'^[[j]Ԯ?3UvTm[GдM,*:RFq=};ZWBEU?xA8:B1vTKl->kKuЉfθh+q;o0[i/-[/Zd4uS_϶]:Q*pϸ52R62k9r o~.IC?d>WzDU !Z%6V,wԖ[+_w:~7,{`?Fg|_  s'=}ãn'[5,8Uga2Ry)W $/:=,2W $wk\JR/E1{[/a/>f\_<;^xO^&[+x-[w[\M m=E䑽 ~<z}}u,=u G5 o^_{] z}N|W_.y[a *?ovBj$ib ˎ}];?{IUEė6񹮲0 w<8fiݶK|kEad1OZf{q#R> 7xFV>D)dT>ڔy}pC;'&$]}]ZtG R찣+{`WRv58ËFZ[M<,̭ՖJmq|^;PbkgAn][,5Թɂ3]v[kmP낋"1+ȳ[;EOɯ3ko.+jOt{7E h\(u`1?wڎyu-)6~.~)ŗ hZВb}uN3B>o9~iᦩu u1Q~j^!5wg3!ySTMFTWIH]Уj?)P3 Z;f2P r  z󱶞xPPPPŸ;@Z|6Tb p5 #P@ۧ[Lvx'ueL ð,/%ޔ7N&ɝL]UqjS>74T$ T,LSzօ%M|U`ʘ留j]Jdy\AճB?K99,R$~%Z]>x+KZ؞|WV^َFr"kexHZK̑uHmRWJ$~(9uVzJldݿ ^ kQ߲ݎv&peK{Hu\?uim[rGjh5&z+x]|yS-,7oCn쑵J#nyS=kwwCߡT en6'>-dʢ6:u?~kyU1 pm 3r#Hqq\(t-wQO mmܗ4+e`Xmﷶm!e-ɕ" Q\k5`0ʩSWҳ/56չ_nԺ/|[wV;U"kQV,fʆ^ܪyä~/i.ۏ\PTk{-$چe0O WIE+y;GO1Q%c0ѥmr0|K ˗ޮ~wij]%H]%H]%H]|QO(xSliP={۵ox 0݀E";o\m%0Z "a/xGmӓrE'e6LxΠ_o}!hE!:whO;D܇ڍ\] M|*dAlg}0Qj]@.i)r$N|bEfzᵤPQj]CE)]ѿW"b%Z Ɋ 3MlĦI]5w8>ڿ ^躰={8AޢE9f)o OPQgokle<8I]\Th[?%.m7 fim}!#QIӹbǸueyH$uq]=2_.<T%9>gaä*0Reww4 >!rQ3lz+wiBo&L"';"BTN+t4TB"w *dä~R}~wëƗH]49aR9}+_d65S>~rw۾J0O,d-'WOR);uioS{-'yv2ߜG\4Dst%ER8go-MlH]L f[gaz0XvZMsq,-R2?D+R06x9usb\A%,uyNE_PcYP2XX' mRp|*bGJe7 0w-ůri-Ժ g,fQM+?:9_Z j]%H]%H]%H]%H]%H]%H]%H]%H]%H]%H]%H]%H]%H]%H]%y{ "4ie~a#_#G+|ʇ GMdY[ŔħmN8RK_>C GG^r86[ZԺzET 3Ͳ"3U&j]@{2昔c7g7D@CԺJ%/9gjtN hϵvm.ZXdmTu-qol5뚳(8E.4f_Dmkf4q3a3B9;A)3r! 6.%_q8}/ҭ^a~σ󒺀r"~g gЭ[0 { sR]rZB::ԩ%0ؚ+.W)'$՟64WAgod۱{+^A7joyVSn.ZQI؂`eRxY2.<, l-8۹D{v'8jiW˩*U\K7׮"Gn.թ_.}٫$-U;.'p#YI?0@/-.Ca'ֵJ3{W]Ȳ\;K\AFD5u@0Q5d [9D؄ԫѰ5[.q]%H]%H]@'uI. U\.4wAWR+rje\|8+.زN#xW]. I􇟷[7ߜ&.a+rݳ}$CyQc;,8`zu)ux}|!s<;Y|['uЋL$:*CvdSnߞ²Zm op p9s=ٛl+{YYۏc/ .W9bx~;??*T0@ q "8o!]½5ʌ,Ld"oWɂn6,Xpx\t;`>z .l(̂?O-Sƅ27}\SoK ['uЅ1C)jJ E=jkۺjebH pi \w`u0%~.0nTJ)W/"q/w<|m#[y!lW![ag8 pE ~ѯw0c Z IENDB`libreswan-4.14/docs/win2k-notes.txt000066400000000000000000000061331457372064200173160ustar00rootroot00000000000000The 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 its 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-4.14/docs/windows-cross-compile.txt000066400000000000000000000076501457372064200214120ustar00rootroot00000000000000WHAT 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-4.14/include/000077500000000000000000000000001457372064200150655ustar00rootroot00000000000000libreswan-4.14/include/addr_lookup.h000066400000000000000000000022771457372064200175510ustar00rootroot00000000000000/* default route lookup, for libreswan * * Copyright (C) 2018,2022 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 ADDR_LOOKUP_H #define ADDR_LOOKUP_H #include #include "lset.h" #include "ip_address.h" struct starter_end; struct logger; void resolve_default_route(struct starter_end *host, struct starter_end *peer, lset_t verbose_rc_flags, struct logger *logger); enum route_status { ROUTE_SUCCESS, ROUTE_GATEWAY_FAILED, ROUTE_SOURCE_FAILED, ROUTE_FATAL, /* already logged */ }; struct ip_route { ip_address source; ip_address gateway; }; enum route_status get_route(ip_address dest, struct ip_route *route, struct logger *logger); #endif libreswan-4.14/include/alg_byname.h000066400000000000000000000027251457372064200173420ustar00rootroot00000000000000/* * 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-4.14/include/asn1.h000066400000000000000000000061401457372064200161010ustar00rootroot00000000000000/* Simple ASN.1 parser, for libreswan * * 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 * Copyright (C) 2022 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 ASN1_H #define ASN1_H #include "realtime.h" #include "chunk.h" /* Defines some primitive ASN1 types */ enum asn1_type { 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 }; extern void code_asn1_length(size_t length, chunk_t *code); bool is_asn1_printablestring(shunk_t str); typedef shunk_t asn1_t; #define ASN1(CHUNK) \ ({ \ chunk_t h_ = CHUNK; /* type assertion */ \ asn1_t asn1_ = { .ptr = h_.ptr, .len = h_.len, }; \ asn1_; \ }) int known_oid(asn1_t object); err_t asn1_ok(asn1_t blob); err_t unwrap_asn1_type(asn1_t *cursor, enum asn1_type *ty); err_t unwrap_asn1_length(asn1_t *cursor, size_t *length); err_t unwrap_asn1_value(asn1_t *cursor, size_t length, asn1_t *value); /* type-length-value https://en.wikipedia.org/wiki/Type%E2%80%93length%E2%80%93value */ err_t unwrap_asn1_tlv(asn1_t *cursor, enum asn1_type ty, asn1_t *contents); #endif libreswan-4.14/include/authby.h000066400000000000000000000042311457372064200165320ustar00rootroot00000000000000/* Authentication, for libreswan * * Copyright (C) 2022 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 AUTHBY_H #define AUTHBY_H #include #include "lset.h" enum keyword_auth; struct jambuf; struct authby { bool psk; bool null; bool never; bool rsasig; bool ecdsa; bool rsasig_v1_5; }; #define AUTHBY_RSASIG (struct authby) { .rsasig = true, .rsasig_v1_5 = true, } #define AUTHBY_ECDSA (struct authby) { .ecdsa = true, } #define AUTHBY_NEVER (struct authby) { .never = true, } #define AUTHBY_NULL (struct authby) { .null = true, } #define AUTHBY_PSK (struct authby) { .psk = true, } #define AUTHBY_NONE (struct authby) {0} #define AUTHBY_ALL (struct authby) { true, true, true, true, true, true } #define AUTHBY_DEFAULTS (struct authby) { .rsasig = true, .rsasig_v1_5 = true, .ecdsa = true } struct authby authby_xor(struct authby lhs, struct authby rhs); struct authby authby_and(struct authby lhs, struct authby rhs); struct authby authby_or(struct authby lhs, struct authby rhs); struct authby authby_not(struct authby lhs); bool authby_le(struct authby lhs, struct authby rhs); bool authby_is_set(struct authby authby); bool authby_eq(struct authby, struct authby); bool authby_has_rsasig(struct authby); bool authby_has_ecdsa(struct authby); bool authby_has_digsig(struct authby); enum keyword_auth auth_from_authby(struct authby authby); struct authby authby_from_auth(enum keyword_auth auth); typedef struct { char buf[sizeof("RSA+NULL+NEVER+RSASIG+ECDSA+RSASIG_v1_5") + 1/*canary*/]; } authby_buf; const char *str_authby(struct authby authby, authby_buf *buf); size_t jam_authby(struct jambuf *buf, struct authby authby); #endif libreswan-4.14/include/binary-iec-60027-2.h000066400000000000000000000015141457372064200200740ustar00rootroot00000000000000/* binary IEC 60027-2 prefix and scale, for libreswan * * Copyright (C) 2022 Antony Antony * * 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 TTOBINARY_H #define TTOBINARY_H /* seen it, no need to see it again */ #include "diag.h" diag_t ttobinary(const char *t, uint64_t *b, bool prefix_B); #endif libreswan-4.14/include/binaryscale-iec-60027-2.h000066400000000000000000000022301457372064200211000ustar00rootroot00000000000000/* scale binary IEC 60027-2, for libreswan * * Copyright (C) 2022 Antony Antony * * 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 BINARYSCALE_H #define BINARYSCALE_H /* seen it, no need to see it again */ #include /* for uintmax_t */ #include "shunk.h" struct binaryscale { const char *suffix; uint64_t b; }; extern const struct binaryscale bin_default; extern const struct binaryscale bin_bytedefult; #define PRI_BINARYSCALE "1%s(%ju%s)" #define pri_binaryscale(B) (B).suffix, (B).b, (B).prefix const struct binaryscale *ttobinaryscale(shunk_t s); const struct binaryscale *ttobinarybytesscale(shunk_t s); #endif libreswan-4.14/include/certs.h000066400000000000000000000047041457372064200163630ustar00rootroot00000000000000/* 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" struct show; /* 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 cert { CERTCertificate *nss_cert; /* CERT_X509_SIGNATURE */ } cert_t; const char *cert_nickname(const struct cert *cert); enum ike_cert_type cert_ike_type(const struct cert *cert); shunk_t cert_der(const struct cert *cert); extern void list_certs(struct show *s); /* * 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-4.14/include/chunk.h000066400000000000000000000073411457372064200163530ustar00rootroot00000000000000/* * 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 "hunk.h" #include "lswalloc.h" /* for freeanychunk() referring 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 chunk2(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 implicitly 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) chunk2(&(THING), sizeof(THING)) chunk_t alloc_chunk(size_t count, const char *name); /* result is always a WRITEABLE, hence chunk; NULL->NULL_CHUNK */ chunk_t clone_bytes_as_chunk(const void *first_ptr, size_t first_len, const char *name); #define clone_hunk(HUNK, NAME) \ ({ \ typeof(HUNK) hunk_ = HUNK; /* evaluate once */ \ clone_bytes_as_chunk(hunk_.ptr, hunk_.len, NAME); \ }) chunk_t clone_bytes_bytes_as_chunk(const void *first_ptr, size_t first_len, const void *second_ptr, size_t second_len, const char *name); #define clone_hunk_hunk(LHS, RHS, NAME) \ ({ \ typeof(LHS) lhs_ = LHS; /* evaluate once */ \ typeof(RHS) rhs_ = RHS; /* evaluate once */ \ clone_bytes_bytes_as_chunk(lhs_.ptr, lhs_.len, \ rhs_.ptr, rhs_.len, \ NAME); \ }) /* * replace RHS with the contatenation of LHS+RHS * * These functions have their name first which, while inconsistent * with the other functions does read better. */ void append_chunk_bytes(const char *name, chunk_t *lhs, const void *rhs, size_t sizeof_rhs); #define append_chunk_hunk(NAME, LHS, RHS) \ ({ \ typeof(RHS) rhs_ = RHS; /* evaluate once */ \ append_chunk_bytes(NAME, LHS, (rhs_).ptr, (rhs_).len); \ }) #define append_chunk_thing(NAME, LHS, THING) \ ({ \ append_chunk_bytes(NAME, LHS, &(THING), sizeof(THING)); \ }) /* * Free contents of chunk (if any) and blat chunk. */ void free_chunk_content(chunk_t *chunk); /* blats *CHUNK */ void replace_chunk(chunk_t *dest, chunk_t src); /* * misc ops. */ 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); #endif libreswan-4.14/include/ckaid.h000066400000000000000000000040251457372064200163120ustar00rootroot00000000000000/* * NSS boilerplate stuff, for libreswan. * * Copyright (C) 2016,2020 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 uint8_t */ #include /* for SECItem */ #include /* for size_t */ #include "err.h" #include "chunk.h" struct jambuf; /* * For rationale behind *_t? Blame chunk_t. * * Field names are so that it is chunk_t like. * * Sane backend uses SHA1 (or eventually SHA2) to generate the CKAID. * However, if a certificate has SubjectKeyIdentifier then that value * is used and it can be anything (even an ASCII string). Ulgh. * * NSS's certutil command has an internal and hard-wired upper limit * of 40 bytes, hence that value here. * * XXX: should CKAID go back to being dynamic? */ #define CKAID_SIZE 40 typedef struct { size_t len; uint8_t ptr[CKAID_SIZE]; } ckaid_t; bool ckaid_starts_with(const ckaid_t *ckaid, const char *start); err_t string_to_ckaid(const char *string, ckaid_t *ckaid); /* raw bytes in lower-case hex */ typedef struct { char buf[CKAID_SIZE * 2 + 1/*nul*/ + 1/*canary*/]; } ckaid_buf; const char *str_ckaid(const ckaid_t *ckaid, ckaid_buf *buf); size_t jam_ckaid(struct jambuf *buf, const ckaid_t *ckaid); bool ckaid_eq_nss(const ckaid_t *l, const SECItem *r); ckaid_t ckaid_from_secitem(const SECItem *const nss_ckaid); SECItem same_ckaid_as_secitem(const ckaid_t *ciaid); #endif libreswan-4.14/include/constants.h000066400000000000000000000263741457372064200172660ustar00rootroot00000000000000/* * * 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 jambuf; /* 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 }; enum binary { binary_per_kilo = UINT64_C(1024), binary_per_mega = UINT64_C(1024) * binary_per_kilo, binary_per_giga = UINT64_C(1024) * binary_per_mega, binary_per_tera = UINT64_C(1024) * binary_per_giga, binary_per_peta = UINT64_C(1024) * binary_per_tera, binary_per_exa = UINT64_C(1024) * binary_per_peta, /* 2^64 s 16 Exa */ }; /* * This file was split into internal constants (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)) #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) #define thingeq(L, R) \ ({ \ /* check type compat by flipping types */ \ const typeof(R) *l_ = &(L);/* type flip */ \ const typeof(L) *r_ = &(R);/* type flip */ \ memeq(l_, r_, sizeof(L)); \ }) /* Remember, THING 1 and THING 2 are inseparable */ #define FOR_EACH_THING(THING, THING1, THING2, ...) \ for (typeof(THING1) things_[] = { THING1, THING2, ##__VA_ARGS__ }, \ *thingp_ = things_, THING; \ thingp_ < things_ + elemsof(things_) ? (THING = *thingp_, true) : false; \ thingp_++) #define FOR_EACH_ELEMENT(THING, ARRAY) \ for (typeof(&(ARRAY)[0]) THING = (ARRAY); \ THING < (ARRAY) + elemsof(ARRAY); \ THING++) #define FOR_EACH_ELEMENT_FROM_1(THING, ARRAY) \ for (typeof(&(ARRAY)[1]) THING = &(ARRAY)[1]; \ THING < (ARRAY) + elemsof(ARRAY); \ THING++) /* * 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). * * Recommended for determining an enum's validity: * * enum_name*() returns the name of an enum value, or NULL if * unnamed. * * Recommended for logging: * * str_enum*() is similar to enum_name, except it formats a numeric * representation for any unnamed value in a caller-supplied buffer. * * jam_enum() appends the name of an enum value; if unnamed, append * a mashup of the standard prefix and the numeric value. * * {*}_short() same as for root, but with any standard prefix removed. */ typedef const struct enum_names enum_names; extern const char *enum_name(enum_names *ed, unsigned long val); extern const char *enum_name_short(enum_names *ed, unsigned long val); size_t jam_enum(struct jambuf *, enum_names *en, unsigned long val); size_t jam_enum_short(struct jambuf *, enum_names *en, unsigned long val); /* * caller-allocated buffer for str_enum*(). * * 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. */ typedef struct { char buf[(sizeof(unsigned long) * 241 + 99) / 100 + sizeof("??")]; } enum_buf; typedef enum_buf esb_buf; /* XXX: TBD */ extern const char *str_enum(enum_names *ed, unsigned long val, enum_buf *); extern const char *str_enum_short(enum_names *ed, unsigned long val, enum_buf *); #define enum_show str_enum /* XXX: TBD */ /* * 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); 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); /* * primitives: * * Return the enum_names range containing VAL; and using its result, * the corresponding and adjusted name. */ const struct enum_names *enum_range(enum_names *en, unsigned long val, const char **prefix); const char *enum_range_name(enum_names *range, unsigned long val, const char *prefix, bool shorten); /* * 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. * * jam_enum_enum() appends TABLE VAL's enum name; if unnamed, append a * mashup of the standard prefix and the numeric value. * * jam_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 *str_enum_enum(enum_enum_names *e, unsigned long table, unsigned long val, enum_buf *buf); const char *str_enum_enum_short(enum_enum_names *e, unsigned long table, unsigned long val, enum_buf *buf); size_t jam_enum_enum(struct jambuf *log, enum_enum_names *een, unsigned long table, unsigned long val); size_t jam_enum_enum_short(struct jambuf *log, enum_enum_names *een, unsigned long table, unsigned long val); /* XXX: assumes enums are 8-bits!?! */ #define LOOSE_ENUM_OTHER 255 extern void init_constants(void); #include "ietf_constants.h" #include "pluto_constants.h" #include "names_constant.h" #endif /* _CONSTANTS_H_ */ libreswan-4.14/include/crypt_hash.h000066400000000000000000000040601457372064200174020ustar00rootroot00000000000000/* 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, struct logger *logger); /* * 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, struct logger *logger); #endif libreswan-4.14/include/crypt_mac.h000066400000000000000000000025241457372064200172220ustar00rootroot00000000000000/* 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 (notably 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-4.14/include/crypt_prf.h000066400000000000000000000064551457372064200172600ustar00rootroot00000000000000/* 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 logger *logger); 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, struct logger *logger); #define crypt_prf_init_hunk(PRF_NAME, PRF, KEY_NAME, KEY, LOGGER) \ crypt_prf_init_bytes(PRF_NAME, PRF, KEY_NAME, (KEY).ptr, (KEY).len, LOGGER) /* * 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-4.14/include/crypt_symkey.h000066400000000000000000000132621457372064200200040ustar00rootroot00000000000000/* * 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" struct jambuf; struct ike_alg; struct hash_desc; struct encrypt_desc; struct prf_desc; void init_crypt_symkey(struct logger *logger); /* * Log some information on a SYMKEY. * * The format is : -key@... */ void DBG_symkey(struct logger *logger, const char *prefix, const char *name, PK11SymKey *key); void jam_symkey(struct jambuf *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); void symkey_newref(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, struct logger *logger); void append_symkey_bytes(const char *result, PK11SymKey **lhs, const void *rhs, size_t sizeof_rhs, struct logger *logger); #define append_symkey_hunk(NAME, LHS, RHS, LOGGER) \ append_symkey_bytes(NAME, LHS, (RHS).ptr, (RHS).len, LOGGER) void prepend_bytes_to_symkey(const char *result, const void *lhs, size_t sizeof_lhs, PK11SymKey **rhs, struct logger *logger); #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, struct logger *logger); /* * 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 *result_name, const struct prf_desc *prf, size_t symkey_start_byte, size_t sizeof_symkey, PK11SymKey *source_key, where_t where, struct logger *logger); /* * 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 *result_name, const struct encrypt_desc *encrypt, size_t symkey_start_byte, size_t sizeof_symkey, PK11SymKey *source_key, where_t where, struct logger *logger); /* * 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, struct logger *logger); 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, struct logger *logger); #define symkey_from_hunk(NAME, HUNK, LOGGER) \ symkey_from_bytes(NAME, (HUNK).ptr, (HUNK).len, LOGGER) PK11SymKey *encrypt_key_from_bytes(const char *name, const struct encrypt_desc *encrypt, const uint8_t *bytes, size_t sizeof_bytes, where_t where, struct logger *logger); /* XXX: can't pass HERE aka '{,}' to macros */ #define encrypt_key_from_hunk(NAME, ENCRYPT, HUNK, LOGGER) \ encrypt_key_from_bytes(NAME, ENCRYPT, (HUNK).ptr, (HUNK).len, HERE, LOGGER) PK11SymKey *prf_key_from_bytes(const char *name, const struct prf_desc *prf, const uint8_t *bytes, size_t sizeof_bytes, where_t where, struct logger *logger); /* XXX: can't pass HERE aka '{,}' to macros */ #define prf_key_from_hunk(NAME, PRF, HUNK, LOGGER) \ prf_key_from_bytes(NAME, PRF, (HUNK).ptr, (HUNK).len, HERE, LOGGER) /* * 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(const char *result_name, PK11SymKey *source_key, size_t next_byte, size_t sizeof_key, where_t where, struct logger *logger); /* * XOR a symkey with a chunk. */ PK11SymKey *xor_symkey_chunk(PK11SymKey *lhs, chunk_t rhs, struct logger *logger); /* * 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, struct logger *logger); #endif libreswan-4.14/include/deltatime.h000066400000000000000000000063371457372064200172170ustar00rootroot00000000000000/* 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 "diag.h" #include "shunk.h" struct jambuf; struct timescale; /* * 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; extern const deltatime_t deltatime_zero; #define DELTATIME_INIT(S) { .dt = { .tv_sec = (S), } } deltatime_t deltatime(time_t secs); deltatime_t deltatime_ms(intmax_t milliseconds); /* for monotime(a-b) and realtime(a-b) */ deltatime_t deltatime_timevals_diff(struct timeval l, struct timeval r); /* sign(a - b); see timercmp() for hacks origin */ int deltatime_sub_sign(deltatime_t l, deltatime_t r); #define deltatime_cmp(L, OP, R) (deltatime_sub_sign(L, R) OP 0) /* 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-b */ deltatime_t deltatime_sub(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 deltatime_scale(deltatime_t d, int num, int denom); /* Convert to/from struct timeval - time used by libevent. */ struct timeval timeval_from_deltatime(deltatime_t); deltatime_t deltatime_from_timeval(const struct timeval a); /* 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(struct jambuf *buf, deltatime_t d); diag_t ttodeltatime(const char *t, deltatime_t *d, const struct timescale *default_scale); /* primitives used to implement times. */ struct timeval timeval_ms(intmax_t milliseconds); /* for *time_cmp(): sign(l-r) */ int timeval_sub_sign(struct timeval l, struct timeval r); #endif libreswan-4.14/include/diag.h000066400000000000000000000031001457372064200161340ustar00rootroot00000000000000/* diagnostic return type, for libreswan * * Copyright (C) 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. */ #ifndef DIAG_H #define DIAG_H #include #include "lswcdefs.h" #include "lset.h" struct jambuf; struct logger; enum pluto_exit_code; typedef struct diag *diag_t; diag_t diag(const char *message, ...) PRINTF_LIKE(1) MUST_USE_RESULT; diag_t diag_errno(int error, const char *message, ...) PRINTF_LIKE(2) MUST_USE_RESULT; diag_t diag_va_list(const char *fmt, va_list ap) VPRINTF_LIKE(1) MUST_USE_RESULT; diag_t diag_jambuf(struct jambuf *buf); diag_t diag_diag(diag_t *d, const char *message, ...) PRINTF_LIKE(2) MUST_USE_RESULT; void llog_diag(lset_t rc_flags, struct logger *logger, diag_t *diag, const char *fmt, ...) PRINTF_LIKE(4); void fatal_diag(enum pluto_exit_code rc, struct logger *logger, diag_t *diag, const char *message, ...) PRINTF_LIKE(4) NEVER_RETURNS; const char *str_diag(diag_t diag); size_t jam_diag(struct jambuf *buf, diag_t diag); diag_t clone_diag(struct diag *diag); void pfree_diag(struct diag **diag); #endif libreswan-4.14/include/dnssec.h000066400000000000000000000021411457372064200165130ustar00rootroot00000000000000#ifndef _DNSSEC_H # define _DNSSEC_H #include #include "ip_address.h" #include "diag.h" struct logger; struct event_base; extern void unbound_ctx_free(void); extern void unbound_sync_init(bool do_dnssec, const char *rootfile, const char *trusted, struct logger *logger); extern diag_t unbound_event_init(struct event_base *eb, bool do_dnssec, const char *rootfile, const char *trusted, struct logger *logger); extern bool unbound_resolve(char *src, const struct ip_info *afi, ip_address *ipaddr, struct logger *logger); 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_EVENT_SECURE = 2, }; #endif libreswan-4.14/include/enum_names.h000066400000000000000000000023361457372064200173710ustar00rootroot00000000000000/* 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() */ #ifndef ENUM_NAMES_H #define ENUM_NAMES_H #include /* for size_t */ 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 struct 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 struct 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(const struct enum_names *checklist[], size_t tl); #endif libreswan-4.14/include/err.h000066400000000000000000000025001457372064200160230ustar00rootroot00000000000000/* 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-4.14/include/fd.h000066400000000000000000000045131457372064200156320ustar00rootroot00000000000000/* 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 /* for size_t */ #include /* for ssize_t */ struct msghdr; struct logger; struct where; /* 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, const struct where *where, struct logger *logger); struct fd *fd_addref_where(struct fd *fd, const struct where *where); void fd_delref_where(struct fd **fd, const struct where *where); #define fd_addref(FD) fd_addref_where(FD, HERE) #define fd_delref(FD) fd_delref_where(FD, HERE) void fd_leak(struct fd *fd, const struct where *where); /* return nr-bytes, or -ERRNO */ ssize_t fd_sendmsg(const struct fd *fd, const struct msghdr *msg, int flags); ssize_t fd_read(const struct fd *fd, void *buf, size_t nbytes); /* * 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(const struct fd *fd); bool same_fd(const struct fd *l, const 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@%p" #define pri_fd(FD) (FD) #endif libreswan-4.14/include/hunk.h000066400000000000000000000221001457372064200161760ustar00rootroot00000000000000/* buffer (pointer+length) like structs, 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 HUNK_H #define HUNK_H #include #include /* size_t */ #include /* uint8_t */ /* * Macros and functions for manipulating hunk like structures. Any * struct containing .ptr and .len fields is considered a hunk. * * The two most common hunks are: * * chunk_t: for a writeable buffer; also the original structure and * why the DATA field is called .ptr (.data, as used by NSS would have * been better). * * shunk_t: for a readonly buffer; the S is for STRING and originally * for static constant string manipulation. * * However, it is also possible to use these macros to manipulate * pre-sized buffers such as ckaid_t and struct crypt_hash where .ptr * is an array (hence comment above about .data being a better * choice). * * To avoid repeated evaluation of functions, the macros below first * make a copy of the hunk being manipulated. For structures such as * ckaid_t where that will copy the buffer contents, it is assumed * that the compiler will see that things are constant and eliminate * them. */ #define THING_AS_HUNK(THING) { .ptr = &(THING), .len = sizeof(THING), } #define NULL_HUNK { .ptr = NULL, .len = 0, } /* #define EMPTY_HUNK { .ptr = &buffer, .len = 0, } */ /* * hunk 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. */ #define hunk_cmp(L, R) \ ({ \ typeof(L) l_ = L; /* evaluate once */ \ typeof(R) r_ = R; /* evaluate once */ \ raw_cmp(l_.ptr, l_.len, r_.ptr, r_.len); \ }) int raw_cmp(const void *l_ptr, size_t l_len, const void *r_ptr, size_t r_len); bool bytes_eq(const void *l_ptr, size_t l_len, const void *r_ptr, size_t r_len); bool case_eq(const void *l_ptr, size_t l_len, const void *r_ptr, size_t r_len); #define hunk_isempty(HUNK) \ ({ \ (HUNK).len == 0; \ }) #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_caseeq(L, R) /* case independent */ \ ({ \ const typeof(L) l_ = L; /* evaluate once */ \ const typeof(R) r_ = R; /* evaluate once */ \ case_eq(l_.ptr, l_.len, r_.ptr, r_.len); \ }) #define hunk_streq(HUNK, STRING) \ ({ \ const typeof(HUNK) hunk_ = HUNK; /* evaluate once */ \ const char *string_ = STRING; /* evaluate once */ \ bytes_eq(hunk_.ptr, hunk_.len, string_, \ string_ != NULL ? strlen(string_) : 0); \ }) #define hunk_strcaseeq(HUNK, STRING) /* case independent */ \ ({ \ const typeof(HUNK) hunk_ = HUNK; /* evaluate once */ \ const char *string_ = STRING; /* evaluate once */ \ case_eq(hunk_.ptr, hunk_.len, string_, \ string_ != NULL ? strlen(string_) : 0); \ }) /* test the start */ #define hunk_starteq(HUNK, START) \ ({ \ const typeof(HUNK) hunk_ = HUNK; /* evaluate once */ \ const typeof(START) start_ = START; /* evaluate once */ \ hunk_.len < start_.len ? false : \ bytes_eq(hunk_.ptr, start_.len, \ start_.ptr, start_.len); \ }) #define hunk_casestarteq(HUNK, START) /* case independent */ \ ({ \ const typeof(HUNK) hunk_ = HUNK; /* evaluate once */ \ const typeof(START) start_ = START; /* evaluate once */ \ hunk_.len < start_.len ? false : \ case_eq(hunk_.ptr, start_.len, \ start_.ptr, start_.len); \ }) #define hunk_strstarteq(HUNK, STRING) \ ({ \ const typeof(HUNK) hunk_ = HUNK; /* evaluate once */ \ const char *string_ = STRING; /* evaluate once */ \ size_t slen_ = string_ != NULL ? strlen(string_) : 0; \ hunk_.len < slen_ ? false : \ bytes_eq(hunk_.ptr, slen_, string_, slen_); \ }) #define hunk_strcasestarteq(HUNK, STRING) \ ({ \ const typeof(HUNK) hunk_ = HUNK; /* evaluate once */ \ const char *string_ = STRING; /* evaluate once */ \ size_t slen_ = string_ != NULL ? strlen(string_) : 0; \ hunk_.len < slen_ ? false : \ case_eq(hunk_.ptr, slen_, string_, slen_); \ }) #define hunk_strnlen(HUNK) \ ({ \ typeof(HUNK) hunk_ = HUNK; /* evaluate once */ \ strnlen((const char *)hunk_.ptr, hunk_.len); \ }) /* misc */ #define hunk_memeq(HUNK, MEM, SIZE) \ ({ \ const typeof(HUNK) hunk_ = HUNK; /* evaluate once */ \ const void *mem_ = MEM; /* evaluate once */ \ size_t size_ = SIZE; /* evaluate once */ \ bytes_eq(hunk_.ptr, hunk_.len, mem_, size_); \ }) #define hunk_thingeq(SHUNK, THING) hunk_memeq(SHUNK, &(THING), sizeof(THING)) /* * Manipulate the hunk as an array of characters. */ /* returns '\0' when out of range */ #define hunk_char(HUNK, INDEX) \ ({ \ const typeof(HUNK) hc_hunk_ = HUNK; /* evaluate once */ \ size_t hc_index_ = INDEX;/* evaluate once */ \ const char *hc_char_ = hc_hunk_.ptr; \ hc_index_ < hc_hunk_.len ? hc_char_[INDEX] : '\0'; \ }) /* returns the unsigned byte cast to int; or -1 when end-of-hunk */ #define hunk_byte(HUNK, INDEX) \ ({ \ const typeof(HUNK) hb_hunk_ = HUNK; /* evaluate once */ \ size_t hb_index_ = INDEX;/* evaluate once */ \ const uint8_t *hb_byte_ = hb_hunk_.ptr; \ hb_index_ < hb_hunk_.len ? hb_byte_[INDEX] : -1; \ }) /* * Macros to treat the HUNK like a data stream. * * - get/put advance the pointer and reduce the length * * - returns the get/put object as a pointer into the buffer * * Caller is responsible for ensuring that pointer is aligned. * For instance, PF_KEY V2 structures are kept 8-byte aligned. * * - returns NULL when end-of-buffer is reached */ #define hunk_get(HUNK, LEN) \ ({ \ size_t hg_len_ = LEN; /* evaluate once */ \ typeof(HUNK) hg_hunk_ = HUNK; /* evaluate once */ \ bool hg_ok_ = (hg_hunk_->len >= hg_len_); \ const void *hg_ptr_ = NULL; \ if (hg_ok_) { \ hg_ptr_ = hg_hunk_->ptr; \ hg_hunk_->ptr += hg_len_; \ hg_hunk_->len -= hg_len_; \ } \ hg_ptr_; \ }) #define hunk_get_thing(HUNK, TYPE) \ (TYPE *) hunk_get(HUNK, sizeof(TYPE)) /* returns POINTER to start of write; or NULL; see pfkey v2 code */ #define hunk_put(HUNK, PTR, LEN) \ ({ \ typeof(HUNK) hp_hunk_ = HUNK; /* evaluate once */ \ size_t hp_len_ = LEN; /* evaluate once */ \ const void *hp_src_ = PTR; /* evaluate once */ \ void *hp_dst_ = NULL; \ if (hp_hunk_->len >= hp_len_) { \ /* can't assume memory alignment */ \ hp_dst_ = hp_hunk_->ptr; \ memcpy(hp_dst_, hp_src_, hp_len_); \ hp_hunk_->len -= hp_len_; \ hp_hunk_->ptr += hp_len_; \ } \ /* XXX: can't assume alignment; but */ \ (typeof(PTR)) hp_dst_; \ }) #define hunk_put_hunk(HUNK, DATA) \ ({ \ typeof(DATA) hph_hunk_ = DATA; /* evaluate once */ \ hunk_put(HUNK, hph_hunk_.ptr, hph_hunk_.len); \ }) #define hunk_put_thing(HUNK, THING) \ (typeof(THING)*) hunk_put(HUNK, &(THING), sizeof(THING)) /* see hunkcheck.c */ bool char_isbdigit(char c); bool char_isblank(char c); bool char_isdigit(char c); bool char_islower(char c); bool char_isodigit(char c); bool char_isprint(char c); bool char_isspace(char c); bool char_isupper(char c); bool char_isxdigit(char c); char char_tolower(char c); char char_toupper(char c); #define hunk_char_ischar(HUNK, OFFSET, CHARS) \ ({ \ unsigned char c_ = hunk_char(HUNK, OFFSET); \ strchr(CHARS, c_); \ }) #define memcpy_hunk(DST, HUNK, SIZE) \ ({ \ const typeof(HUNK) hunk_ = HUNK; /* evaluate once */ \ passert(hunk_.len == SIZE); \ memcpy(DST, hunk_.ptr, SIZE); \ }) /* * Convert between uintmax_t and network-byte-ordered data. */ void hton_bytes(uintmax_t h, void *bytes, size_t size); uintmax_t ntoh_bytes(const void *bytes, size_t size); #define ntoh_hunk(HUNK) \ ({ \ const typeof(HUNK) hunk_ = HUNK; /* evaluate once */ \ ntoh_bytes(hunk_.ptr, hunk_.len); \ }) #define hton_chunk(H, HUNK) /* writeable */ \ ({ \ const chunk_t hunk_ = HUNK; /* evaluate once */ \ hton_bytes(H, hunk_.ptr, hunk_.len); \ }) /* * convert a hunk into a NUL terminated string; NULL is NULL. */ char *clone_bytes_as_string(const void *ptr, size_t len, const char *name); #define clone_hunk_as_string(HUNK, NAME) \ ({ \ typeof(HUNK) hunk_ = HUNK; /* evaluate once */ \ clone_bytes_as_string(hunk_.ptr, hunk_.len, NAME); \ }) #endif libreswan-4.14/include/id.h000066400000000000000000000056101457372064200156340ustar00rootroot00000000000000/* identity representation, as in IKE ID Payloads (RFC 2407 DOI 4.6.2.1) * * Copyright (C) 1999-2001 D. Hugh Redelmeier * Copyright (C) 2019-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. */ #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" /* for typedef jam_bytes_fn */ 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 */ shunk_t name; /* when non-NULL, delete */ void *scratch; }; struct id_list { struct id id; struct id_list *next; }; extern const struct id empty_id; /* ID_NONE */ /* * parsing. */ err_t atoid(const char *src, struct id *id); /* * Formatting. * * The primitive jam_id_bytes() only outputs printable ASCII. This * means that the two calls: * * jam_id_bytes(jam_raw_bytes) * jam_id_bytes(jam_sanitized_bytes) * * are equivalent (the latter would never encounter a character * needing sanitizing). * * Hence str_id() is implemented using jam_id_bytes(jam_raw_bytes). * However, callers will often specify jam_sanitized_bytes() just to * be sure. * * However, it isn't good for shell commands et.al.. Use * jam_shell_quoted_bytes(), for instance, to apply additional * escaping. */ void jam_id_bytes(struct jambuf *buf, const struct id *id, jam_bytes_fn *jam_bytes); typedef struct { char buf[512]; } id_buf; const char *str_id_bytes(const struct id *id, jam_bytes_fn *jam_bytes, id_buf *buf); #define str_id(ID, BUF) str_id_bytes(ID, jam_raw_bytes, BUF) /* see above */ /* * 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 id_is_any(const struct id *a); extern bool id_eq(const struct id *a, const struct id *b); extern bool same_id(const struct id *a, const struct id *b); /* fuzzy */ #define MAX_WILDCARDS 15 extern bool match_id(const char *prefix, const struct id *a, const struct id *b, int *wildcards); extern bool id_has_wildcards(const struct id *id); #define id_is_ipaddr(id) ((id)->kind == ID_IPV4_ADDR || (id)->kind == ID_IPV6_ADDR) /* 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); #endif libreswan-4.14/include/ietf_constants.h000066400000000000000000002161401457372064200202650ustar00rootroot00000000000000/* * 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 * Copyright (C) 2017 Mayank Totale * Copyright (C) 2020 Yulia Kuzovkova * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT 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 /* RFC8229: prefix at start of tcp stream (no NUL) */ #define IKE_IN_TCP_PREFIX { 'I', 'K', 'E', 'T', 'C', 'P', } /* ICMP type number for neighbor discovery */ #define ICMP_NEIGHBOR_DISCOVERY 34816 #define ICMP_NEIGHBOR_SOLICITATION 34560 /* RFC3748, section 4: EAP Code */ enum eap_code { EAP_CODE_REQUEST = 1, EAP_CODE_RESPONSE, EAP_CODE_SUCCESS, EAP_CODE_FAILURE, }; /* EAP Type */ enum eap_type { EAP_TYPE_TLS = 13, /* RFC5216 EAP-TLS */ }; /* RFC5216, section 3.1: EAP-TLS flags */ enum { EAPTLS_FLAGS_START_IX = 5, EAPTLS_FLAGS_MORE_IX = 6, EAPTLS_FLAGS_LENGTH_IX = 7, }; #define EAPTLS_FLAGS_START (1<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 }; /* * 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, /* RSA_DIGITAL_SIGNATURE */ IKEv2_AUTH_PSK = 2, /* SHARED_KEY_MAC */ IKEv2_AUTH_DSS_DIGITAL_SIGNATURE = 3, /* 4 - 8 unassigned */ IKEv2_AUTH_ECDSA_SHA2_256_P256 = 9, /* RFC 4754 */ IKEv2_AUTH_ECDSA_SHA2_384_P384 = 10, /* RFC 4754 */ IKEv2_AUTH_ECDSA_SHA2_512_P521 = 11, /* RFC 4754 */ IKEv2_AUTH_GENERIC_SECURE_PASSWORD_AUTHENTICATION_METHOD = 12, /* RFC 6467 */ IKEv2_AUTH_NULL = 13, /* NULL_AUTHENTICATION draft-ietf-ipsecme-ikev2-null-auth */ IKEv2_AUTH_DIGSIG = 14, /* DIGITAL_SIGNATURE 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 { v1N_NOTHING_WRONG = 0, /* Unofficial! Must be zero to match default C initial value. */ v1N_INVALID_PAYLOAD_TYPE = 1, v1N_DOI_NOT_SUPPORTED = 2, v1N_SITUATION_NOT_SUPPORTED = 3, v1N_INVALID_COOKIE = 4, v1N_INVALID_MAJOR_VERSION = 5, v1N_INVALID_MINOR_VERSION = 6, v1N_INVALID_EXCHANGE_TYPE = 7, v1N_INVALID_FLAGS = 8, v1N_INVALID_MESSAGE_ID = 9, v1N_INVALID_PROTOCOL_ID = 10, v1N_INVALID_SPI = 11, v1N_INVALID_TRANSFORM_ID = 12, v1N_ATTRIBUTES_NOT_SUPPORTED = 13, v1N_NO_PROPOSAL_CHOSEN = 14, v1N_BAD_PROPOSAL_SYNTAX = 15, v1N_PAYLOAD_MALFORMED = 16, v1N_INVALID_KEY_INFORMATION = 17, v1N_INVALID_ID_INFORMATION = 18, v1N_INVALID_CERT_ENCODING = 19, v1N_INVALID_CERTIFICATE = 20, v1N_CERT_TYPE_UNSUPPORTED = 21, v1N_INVALID_CERT_AUTHORITY = 22, v1N_INVALID_HASH_INFORMATION = 23, v1N_AUTHENTICATION_FAILED = 24, v1N_INVALID_SIGNATURE = 25, v1N_ADDRESS_NOTIFICATION = 26, v1N_NOTIFY_SA_LIFETIME = 27, v1N_CERTIFICATE_UNAVAILABLE = 28, v1N_UNSUPPORTED_EXCHANGE_TYPE = 29, v1N_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) */ v1N_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. */ v1N_IPSEC_RESPONDER_LIFETIME = 24576, v1N_IPSEC_REPLAY_STATUS = 24577, v1N_IPSEC_INITIAL_CONTACT = 24578, /* Cisco specific messages */ v1N_ISAKMP_N_CISCO_HELLO = 30000, v1N_ISAKMP_N_CISCO_WWTEBR = 30001, v1N_ISAKMP_N_CISCO_SHUT_UP = 30002, v1N_ISAKMP_N_IOS_KEEP_ALIVE_REQ = 32768, v1N_ISAKMP_N_IOS_KEEP_ALIVE_ACK = 32769, v1N_ISAKMP_N_CISCO_LOAD_BALANCE = 40501, v1N_ISAKMP_N_CISCO_UNKNOWN_40502 = 40502, v1N_ISAKMP_N_CISCO_PRESHARED_KEY_HASH = 40503, /* RFC 3706 DPD */ v1N_R_U_THERE = 36136, v1N_R_U_THERE_ACK = 36137, /* * Netscreen / Juniper private use - notification contains * internal ip */ v1N_NETSCREEN_NHTB_INFORM = 40001, } v1_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_INTERMEDIATE_EXCHANGE_SUPPORTED = 16438, /* draft-ietf-ipsecme-ikev2-intermediate-04 */ v2N_STATUS_PSTATS_ROOF, /* used to cap status statistics array */ /* 16438 - 40959 Unassigned */ /* 40960 - 65535 Private Use */ v2N_NULL_AUTH = 40960, } 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 ipseckey_algorithm_type { IPSECKEY_ALGORITHM_DSA = 1, IPSECKEY_ALGORITHM_RSA = 2, IPSECKEY_ALGORITHM_ECDSA = 3, /* E*D*DSA? */ IPSECKEY_ALGORITHM_X_PUBKEY = 4, /* Subject Public Key Info - guess */ }; extern const struct enum_names ipseckey_algorithm_type_names; extern const struct enum_names ipseckey_algorithm_config_names; /* in ipsec.conf */ /* * 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 */ }; extern const struct enum_names ike_id_type_names; /* all */ extern const struct enum_names ikev1_ike_id_type_names; extern const struct enum_names ikev2_ike_id_type_names; /* * 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_ipcomp_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 */ }; /* * Internet Key Exchange Version 2 (IKEv2) Parameters: IKEv2 Hash Algorithms * https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xhtml#hash-algorithms * * Currently it is only used by RFC 7427 Signature Authentication in * the Internet Key Exchange Version 2. * * XXX: Danger! * * As well as IKEv2_HASH_ALGORITHM_* and the the lset_t constants * NEGOTIATE_AUTH_HASH_*, pluto defines the enum POL_SIGHASH_*_IX and * lset_t constants POL_SIGHHASH_* using different values. Ulgh. * * sighash_policy_bit_names is for the _latter. */ enum ikev2_hash_algorithm { IKEv2_HASH_ALGORITHM_RESERVED = 0, IKEv2_HASH_ALGORITHM_SHA1 = 1, IKEv2_HASH_ALGORITHM_SHA2_256 = 2, IKEv2_HASH_ALGORITHM_SHA2_384 = 3, IKEv2_HASH_ALGORITHM_SHA2_512 = 4, IKEv2_HASH_ALGORITHM_IDENTITY = 5, /* RFC 4307-bis */ /* 6-1023 Unassigned */ /* 1024-65535 Reserved for private use */ #define IKEv2_HASH_ALGORITHM_ROOF (IKEv2_HASH_ALGORITHM_IDENTITY + 1) }; /* * RFC 7427: Signature Authentication in the Internet Key Exchange * Version 2 (IKEv2) * * 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: Signature Authentication in the Internet Key Exchange * Version 2 (IKEv2) * * 3. Authentication Payload * * Following the 64-byte Authentication payload header is the * Authentication Data which, for Digital Signature, consists of: * * 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | ASN.1 Length | AlgorithmIdentifier ASN.1 object | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | | * ~ AlgorithmIdentifier ASN.1 object continuing ~ * | | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | | * ~ Signature Value ~ * | | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /* * Appendix A. Commonly Used ASN.1 Objects (blobs) */ enum digital_signature_blob { DIGITAL_SIGNATURE_PKCS1_1_5_RSA_BLOB, /* A.1. */ /* DIGITAL_SIGNATURE_DSA_BLOB, .. A.2. */ DIGITAL_SIGNATURE_RSASSA_PSS_BLOB, /* A.3. */ DIGITAL_SIGNATURE_ECDSA_BLOB, /* A.4. */ #define DIGITAL_SIGNATURE_BLOB_ROOF (DIGITAL_SIGNATURE_ECDSA_BLOB+1) }; /* * RFC 7427: A.1. PKCS#1 1.5 RSA Encryption. */ #define ASN1_PKCS1_1_5_RSA_SIZE 15 /* A.1.1. sha1WithRSAEncryption */ #define ASN1_PKCS1_1_5_RSA_SHA1_BLOB \ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \ 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00 /* A.1.2. sha256WithRSAEncryption */ #define ASN1_PKCS1_1_5_RSA_SHA2_256_BLOB \ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \ 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00 /* A.1.3. sha384WithRSAEncryption */ #define ASN1_PKCS1_1_5_RSA_SHA2_384_BLOB \ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \ 0xf7, 0x0d, 0x01, 0x01, 0x0c, 0x05, 0x00 /* A.1.4. sha512WithRSAEncryption */ #define ASN1_PKCS1_1_5_RSA_SHA2_512_BLOB \ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \ 0xf7, 0x0d, 0x01, 0x01, 0x0d, 0x05, 0x00 /* * A.2. DSA */ #define ASN1_DSA_SHA1_SIZE 11 #define ASN1_DSA_SHA2_SIZE 13 /* A.2.1. dsa-with-sha1 */ #define ASN1_DSA_SHA1_BLOB \ 0x30, 0x09, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, \ 0x38, 0x04, 0x03 /* A.2.2. dsa-with-sha256 */ #define ASN1_DSA1_SHA2 \ 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, \ 0x65, 0x03, 0x04, 0x03 0x02 /* * A.3. ECDSA */ #define ASN1_ECDSA_SHA1_SIZE 11 #define ASN1_ECDSA_SHA2_SIZE 12 /* A.3.1. ecdsa-with-sha1 */ #define ASN1_ECDSA_SHA1_BLOB \ 0x30, 0x09, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, \ 0x3d, 0x04, 0x01 /* A.3.2. ecdsa-with-sha256 */ #define ASN1_ECDSA_SHA2_256_BLOB \ 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, \ 0x3d, 0x04, 0x03, 0x02 /* A.3.3. ecdsa-with-sha384 */ #define ASN1_ECDSA_SHA2_384_BLOB \ 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, \ 0x3d, 0x04, 0x03, 0x03 /* A.3.4. ecdsa-with-sha512 */ #define ASN1_ECDSA_SHA2_512_BLOB \ 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, \ 0x3d, 0x04, 0x03, 0x04 /* * A.4. RSASSA-PSS * * Size of algorithm RSASSA-PSS with SHA2 is 67 bytes for all its * variants. */ #define ASN1_RSASSA_PSS_SHA2_SIZE 67 /* length of ASN.1 Algorithm Identifier(variable length) is 1 byte */ #define ASN1_LEN_ALGO_IDENTIFIER 1 /* A.4.1. RSASSA-PSS with Empty Parameters */ /* A.4.2. RSASSA-PSS with Default Parameters */ /* A.4.3. RSASSA-PSS with SHA2-256 */ #define ASN1_RSASSA_PSS_SHA2_256_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 /* A.4.3. RSASSA-PSS with SHA2-384 */ #define ASN1_RSASSA_PSS_SHA2_384_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 /* A.4.3. RSASSA-PSS with SHA2-512 */ #define ASN1_RSASSA_PSS_SHA2_512_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 /* 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 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-4.14/include/ike_alg.h000066400000000000000000000647101457372064200166410ustar00rootroot00000000000000/* * 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 "shunk.h" #include "ietf_constants.h" struct ike_alg; struct jambuf; enum ike_alg_key; struct logger; /* * 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 \ : "NULL") #define pexpect_ike_alg(LOGGER, ALG, ASSERTION) \ { \ /* wrapping ASSERTION in parens suppresses -Wparen */ \ bool assertion__ = ASSERTION; /* no paren */ \ if (!assertion__) { \ llog_pexpect(LOGGER, HERE, \ PRI_IKE_ALG" fails: " #ASSERTION, \ pri_ike_alg(ALG)); \ } \ } #define pexpect_ike_alg_key(LOGGER, ALG, KEY, ASSERTION) \ { \ /* wrapping ASSERTION in parens suppresses -Wparen */ \ bool assertion__ = ASSERTION; /* no paren */ \ if (!assertion__) { \ llog_pexpect(LOGGER, HERE, \ PRI_IKE_ALG" %s fails: "#ASSERTION, \ pri_ike_alg(ALG), \ ike_alg_key_name(KEY)); \ } \ } #define pexpect_ike_alg_streq(LOGGER, 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)) { \ llog_pexpect(LOGGER, HERE, \ PRI_IKE_ALG" fails: %s != %s (%s != %s)", \ pri_ike_alg(ALG), \ lhs, rhs, #LHS, #RHS); \ } \ } #define pexpect_ike_alg_strcaseeq(LOGGER, 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)) { \ llog_pexpect(LOGGER, 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; extern const struct ike_alg_type ike_alg_ipcomp; /* 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 #define IKE_ALG_IPCOMP &ike_alg_ipcomp /* * 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, SADB_ALG_ID, }; #define IKE_ALG_KEY_ROOF (SADB_ALG_ID+1) #define 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); const struct ike_alg *ike_alg_by_key_id(const struct ike_alg_type *type, enum ike_alg_key key, unsigned id); 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 * COMP: ipsec_ipcomp_algo ipsec_ipcomp_algo_names ? * * 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 * IPCOMP: N/A * * 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 * IPCOMP: ipsec_ipcomp_algo ipsec_ipcomp_algo_names ? * * * (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 accommodate 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 *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). */ #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]; const struct ike_alg_type *algo_type; /* * Is this algorithm FIPS approved (i.e., can be enabled in * FIPS mode)? */ struct { const bool approved; uintmax_t operation_limit; } fips; }; /* * Encryption algorithm re-aranges the bits. */ 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 _preferred_ 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 * accommodate missing algorithms. Hence it is not used here. */ #define encrypt_sadb_ealg_id common.id[SADB_ALG_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. */ struct { /* * The NSS_OID_TAG identifies the the PK11 digest * (hash) context that should created when using * PL11_Digest*(). * * This is all somewhat redundant. Unfortunately * there isn't a way to map between them. */ SECOidTag oid_tag; /* * The DERIVE_MECHANISM specifies the derivation * (algorithm) to use when using PK11_Derive(). * * This is all somewhat redundant. Unfortunately * there isn't a way to map between them. */ CK_MECHANISM_TYPE derivation_mechanism; /* * For digital sign schema */ const CK_RSA_PKCS_PSS_PARAMS *rsa_pkcs_pss_params; /* * For PKCS#1 1.5 RSA crypto using SGN*() */ SECOidTag pkcs1_1_5_rsa_oid_tag; } nss; /* * ASN.1 blobs specific to a particular hash algorithm are * sent in the Auth payload as part of Digital signature * authentication as per RFC7427 */ shunk_t digital_signature_blob[DIGITAL_SIGNATURE_BLOB_ROOF]; const struct hash_ops *hash_ops; }; /* * 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 accommodate missing algorithms. * Hence it is not used here. */ #define integ_sadb_aalg_id common.id[SADB_ALG_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; }; /* * 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; /* raw bytes to be put on wire */ /* * 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; /* * For most EC algorithms, NSS's public key value consists of * the one byte EC_POINT_FORM_UNCOMPRESSED prefix followed by * two equal-sized points. * * There's one exception (curve25519) which contains no prefix * and just a single point. */ bool nss_adds_ec_point_form_uncompressed; const struct dh_ops *dh_ops; }; extern const struct dh_desc unset_group; /* magic signifier */ /* * IPCOMP, like encryption, re-aranges the bits. */ struct ipcomp_desc { struct ike_alg common; /* must be first */ struct { /* * This encryption algorithm's NETLINK / XFRM name, if known. * NULL implies not supported. */ const char *xfrm_name; } kernel; /* * The algorithms's SADB (pfkeyv2) value (>0 when defined for * this OS). */ #define ipcomp_sadb_calg_id common.id[SADB_ALG_ID] /* * Will IKE ever support IPCOMP? */ const struct ipcomp_ops *ipcomp_ops; }; /* * 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(struct logger *logger); void test_ike_alg(struct logger *logger); /* * 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); const struct ipcomp_desc **next_ipcomp_desc(const struct ipcomp_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); /* * 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); const struct ipcomp_desc *ipcomp_desc(const struct ike_alg *alg); /* * Find the ENCRYPT / HASH / 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 hash_desc *ikev2_get_hash_desc(enum ikev2_hash_algorithm); 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); const struct ipcomp_desc *ikev2_get_ipcomp_desc(enum ipsec_ipcomp_algo); /* * 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); const struct ipcomp_desc *ikev1_get_ike_ipcomp_desc(enum ipsec_ipcomp_algo); /* * 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); const struct ipcomp_desc *ikev1_get_kernel_ipcomp_desc(enum ipsec_ipcomp_algo); /* * 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); const struct ipcomp_desc *ipcomp_desc_by_sadb_calg_id(unsigned id); #endif /* _IKE_ALG_H */ libreswan-4.14/include/ike_alg_dh.h000066400000000000000000000031651457372064200173110ustar00rootroot00000000000000/* * 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_secp256r1; extern const struct dh_desc ike_alg_dh_secp384r1; extern const struct dh_desc ike_alg_dh_secp521r1; #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_curve25519; #endif /* * IKEv2 RFC 7296 uses the term "NONE" when referring to no DH * algorithm. */ extern const struct dh_desc ike_alg_dh_none; libreswan-4.14/include/ike_alg_dh_ops.h000066400000000000000000000035331457372064200201710ustar00rootroot00000000000000/* * 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 #include "diag.h" #include "chunk.h" struct logger; struct dh_ops { const char *backend; /* * Delegate responsibility for checking OPS specific fields. */ void (*const check)(const struct dh_desc *alg, struct logger *logger); /* * 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_local_secret)(const struct dh_desc *group, SECKEYPrivateKey **local_privk, SECKEYPublicKey **locak_pubk, struct logger *logger); shunk_t (*local_secret_ke)(const struct dh_desc *group, const SECKEYPublicKey *local_pubk); diag_t (*calc_shared_secret)(const struct dh_desc *group, SECKEYPrivateKey *local_privk, const SECKEYPublicKey *local_pubk, chunk_t remote_ke, PK11SymKey **shared_secret, struct logger *logger) MUST_USE_RESULT; }; extern const struct dh_ops ike_alg_dh_nss_ecp_ops; extern const struct dh_ops ike_alg_dh_nss_modp_ops; #endif libreswan-4.14/include/ike_alg_encrypt.h000066400000000000000000000031231457372064200203740ustar00rootroot00000000000000/* 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_3DES extern const struct encrypt_desc ike_alg_encrypt_3des_cbc; #endif extern const struct encrypt_desc ike_alg_encrypt_null; #ifdef USE_CHACHA extern const struct encrypt_desc ike_alg_encrypt_chacha20_poly1305; #endif libreswan-4.14/include/ike_alg_encrypt_ops.h000066400000000000000000000042211457372064200212550ustar00rootroot00000000000000/* 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 logger; struct encrypt_ops { const char *backend; /* * Delegate responsibility for checking OPS specific fields. */ void (*const check)(const struct encrypt_desc *alg, struct logger *logger); /* * 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, struct logger *logger); /* * 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, struct logger *logger); }; 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-4.14/include/ike_alg_hash.h000066400000000000000000000023431457372064200176360ustar00rootroot00000000000000/* 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. */ #ifndef IKE_ALG_HASH_H #define IKE_ALG_HASH_H extern const struct hash_desc ike_alg_hash_sha1; /* also used for NAT */ 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 extern const struct hash_desc ike_alg_hash_md5; /* also used for Vendor IDs */ extern const struct hash_desc ike_alg_hash_identity; #endif libreswan-4.14/include/ike_alg_hash_ops.h000066400000000000000000000025601457372064200205200ustar00rootroot00000000000000/* * 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 logger *logger); 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-4.14/include/ike_alg_integ.h000066400000000000000000000026361457372064200200260ustar00rootroot00000000000000/* 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 /* * 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-4.14/include/ike_alg_ipcomp.h000066400000000000000000000016011457372064200201760ustar00rootroot00000000000000/* * IKE modular algorithm handling interface, for libreswan * * Copyright (C) 2022 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_IPCOMP_H #define IKE_ALG_IPCOMP_H struct ipcomp_desc; extern const struct ipcomp_desc ike_alg_ipcomp_deflate; extern const struct ipcomp_desc ike_alg_ipcomp_lzs; extern const struct ipcomp_desc ike_alg_ipcomp_lzjh; #endif libreswan-4.14/include/ike_alg_ipcomp_ops.h000066400000000000000000000013611457372064200210620ustar00rootroot00000000000000/* Fictitious IPCOMP operations for libreswan. * * Copyright (C) 2022 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_IPCOMP_OPS_H #define IKE_ALG_IPCOMP_OPS_H struct ipcomp_ops { const char *backend; }; #endif libreswan-4.14/include/ike_alg_prf.h000066400000000000000000000020411457372064200174750ustar00rootroot00000000000000/* 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-4.14/include/ike_alg_prf_ikev1_ops.h000066400000000000000000000130251457372064200214610ustar00rootroot00000000000000/* 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 logger; 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, struct logger *logger); PK11SymKey *(*pre_shared_key_skeyid)(const struct prf_desc *prf_desc, chunk_t pre_shared_key, chunk_t Ni_b, chunk_t Nr_b, struct logger *logger); /* * 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, struct logger *logger); /* * 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, struct logger *logger); /* * 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, struct logger *logger); /* * 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, struct logger *logger); /* * Section 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, struct logger *logger); }; extern const struct prf_ikev1_ops ike_alg_prf_ikev1_mac_ops; #ifdef USE_NSS_KDF extern const struct prf_ikev1_ops ike_alg_prf_ikev1_nss_ops; #endif #endif libreswan-4.14/include/ike_alg_prf_ikev2_ops.h000066400000000000000000000052651457372064200214710ustar00rootroot00000000000000/* IKEv1 PRF specific operations, for libreswan * * Copyright (C) 2019 Andrew Cagney * Copyright (C) 2020 Yulia Kuzovkova * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT 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 logger; 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, struct logger *logger); /* 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, struct logger *logger); /* 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, struct logger *logger); /* 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, struct logger *logger); /* 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, struct logger *logger); /* AUTH = prf( prf(Shared Secret, "Key Pad for IKEv2"), <{Initiator,Responder}SignedOctets>) */ struct crypt_mac (*psk_auth)(const struct prf_desc *prf_desc, shunk_t pss, chunk_t first_packet, chunk_t nonce, const struct crypt_mac *id_hash, chunk_t intermediate_packet, struct logger *logger); }; extern const struct prf_ikev2_ops ike_alg_prf_ikev2_mac_ops; #ifdef USE_NSS_KDF extern const struct prf_ikev2_ops ike_alg_prf_ikev2_nss_ops; #endif #endif libreswan-4.14/include/ike_alg_prf_mac_ops.h000066400000000000000000000034051457372064200212030ustar00rootroot00000000000000/* * 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 logger; struct prf_mac_ops { const char *backend; /* * Delegate responsibility for checking OPS specific fields. */ void (*const check)(const struct prf_desc *alg, struct logger *logger); struct prf_context *(*init_symkey)(const struct prf_desc *prf_desc, const char *name, const char *key_name, PK11SymKey *key, struct logger *logger); 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, struct logger *logger); 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-4.14/include/ike_alg_test_cbc.h000066400000000000000000000020571457372064200205030ustar00rootroot00000000000000/* * 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, struct logger *logger); libreswan-4.14/include/ike_alg_test_ctr.h000066400000000000000000000020471457372064200205430ustar00rootroot00000000000000/* * 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, struct logger *logger); libreswan-4.14/include/ike_alg_test_gcm.h000066400000000000000000000022121457372064200205130ustar00rootroot00000000000000/* * 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, struct logger *logger); libreswan-4.14/include/ike_alg_test_prf.h000066400000000000000000000027551457372064200205500ustar00rootroot00000000000000/* * 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, struct logger *logger); struct kdf_test_vector { const char *description; const char *ni; unsigned ni_size; const char *nr; unsigned nr_size; const char *gir; const char *gir_new; unsigned gir_size; const char *spii; const char *spir; const char *skeyseed; const char *skeyseed_rekey; const char *dkm; unsigned dkm_size; }; extern const struct kdf_test_vector hmac_sha1_kdf_tests[]; bool test_kdf_vectors(const struct prf_desc *desc, const struct kdf_test_vector *tests, struct logger *logger); libreswan-4.14/include/ike_spi.h000066400000000000000000000030631457372064200166630ustar00rootroot00000000000000/* IKE SPI generation routines, for libreswan * * Copyright (C) 1998-2002 D. Hugh Redelmeier. * 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 IKE_SPI_H #define IKE_SPI_H #include #include #include "ietf_constants.h" /* for IKE_SA_SPI_SIZE */ #include "ip_endpoint.h" struct state; typedef struct { uint8_t bytes[IKE_SA_SPI_SIZE]; } ike_spi_t; extern const ike_spi_t zero_ike_spi; bool ike_spi_is_zero(const ike_spi_t *ike_spi); bool ike_spi_eq(const ike_spi_t *lhs, const ike_spi_t *rhs); typedef struct { ike_spi_t initiator; ike_spi_t responder; } ike_spis_t; bool ike_spis_eq(const ike_spis_t *lhs, const ike_spis_t *rhs); /* * Need to handle two cases: * * - new IKE SA - and ST is the IKE SA * * - rekeying old IKE SA - and ST has not yet been emancipated so it * still looks like a child */ ike_spi_t ike_initiator_spi(void); ike_spi_t ike_responder_spi(const ip_endpoint *initiator_endpoint, struct logger *logger); void refresh_ike_spi_secret(void); #endif libreswan-4.14/include/ikev1_prf.h000066400000000000000000000051521457372064200171270ustar00rootroot00000000000000/* * 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. */ #ifndef ikev1_prf_h #define ikev1_prf_h #include "lswnss.h" #include "chunk.h" struct prf_desc; struct encrypt_desc; /* * IKE SA SKEYID for authentication * * Be warned, this is not DSS (even though NIST call it Digital * Signature Algorithm). It is used by RSA-SIG. */ PK11SymKey *ikev1_signature_skeyid(const struct prf_desc *prf_desc, const chunk_t Ni_b, const chunk_t Nr_b, PK11SymKey *dh_secret, struct logger *logger); PK11SymKey *ikev1_pre_shared_key_skeyid(const struct prf_desc *prf_desc, chunk_t pre_shared_key, chunk_t Ni_b, chunk_t Nr_b, struct logger *logger); /* * Authenticated keying material. * * Perhaps this should just return a struct? */ PK11SymKey *ikev1_skeyid_d(const struct prf_desc *prf_desc, PK11SymKey *skeyid, PK11SymKey *dh_secret, chunk_t cky_i, chunk_t cky_r, struct logger *logger); PK11SymKey *ikev1_skeyid_a(const struct prf_desc *prf_desc, PK11SymKey *skeyid, PK11SymKey *skeyid_d, PK11SymKey *dh_secret, chunk_t cky_i, chunk_t cky_r, struct logger *logger); PK11SymKey *ikev1_skeyid_e(const struct prf_desc *prf_desc, PK11SymKey *skeyid, PK11SymKey *skeyid_a, PK11SymKey *dh_secret, chunk_t cky_i, chunk_t cky_r, struct logger *logger); PK11SymKey *ikev1_appendix_b_keymat_e(const struct prf_desc *prf_desc, const struct encrypt_desc *encrypter, PK11SymKey *skeyid_e, unsigned required_keymat, struct logger *logger); chunk_t ikev1_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, struct logger *logger); #endif libreswan-4.14/include/ikev2_prf.h000066400000000000000000000044211457372064200171260ustar00rootroot00000000000000/* * Calculate IKEv2 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) 2020 Yulia Kuzovkova * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT 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 _IKEV2_PRF_H #define _IKEV2_PRF_H #include "lswnss.h" #include "ike_spi.h" #include "chunk.h" #include "shunk.h" struct prf_desc; /* * IKE SA */ PK11SymKey *ikev2_prfplus(const struct prf_desc *prf_desc, PK11SymKey *key, PK11SymKey *seed, size_t required_keymat, struct logger *logger); PK11SymKey *ikev2_ike_sa_skeyseed(const struct prf_desc *prf_desc, const chunk_t Ni, const chunk_t Nr, PK11SymKey *dh_secret, struct logger *logger); PK11SymKey *ikev2_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, struct logger *logger); PK11SymKey *ikev2_ike_sa_keymat(const struct prf_desc *prf_desc, PK11SymKey *skeyseed, const chunk_t Ni, const chunk_t Nr, const ike_spis_t *ike_spis, size_t required_bytes, struct logger *logger); /* * Child SA */ PK11SymKey *ikev2_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, struct logger *logger); /* * Authentication. */ struct crypt_mac ikev2_psk_auth(const struct prf_desc *prf_desc, shunk_t pss, chunk_t first_packet, chunk_t nonce, const struct crypt_mac *id_hash, chunk_t intermediate_packet, struct logger *logger); #endif libreswan-4.14/include/impair.h000066400000000000000000000116531457372064200165250ustar00rootroot00000000000000/* impair operation, for libreswan * * Copyright (C) 2018-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. * */ #ifndef IMPAIR_H #define IMPAIR_H #include #include "lswcdefs.h" struct fd; struct logger; struct jambuf; /* * Meddle with the contents of a payload. */ enum impair_emit { IMPAIR_EMIT_NO = 0, IMPAIR_EMIT_OMIT, IMPAIR_EMIT_EMPTY, IMPAIR_EMIT_DUPLICATE, IMPAIR_EMIT_ROOF, /* >= ROOF -> */ }; /* * Meddle with a specific exchange. */ enum impair_v1_exchange { IMPAIR_v1_EXCHANGE_NO = 0, IMPAIR_v1_NOTIFICATION_EXCHANGE, IMPAIR_v1_QUICK_EXCHANGE, IMPAIR_v1_XAUTH_EXCHANGE, IMPAIR_v1_DELETE_EXCHANGE, }; /* * Meddle with an (IKEv2) transform. */ enum impair_v2_transform { IMPAIR_v2_TRANSFORM_NO = 0, IMPAIR_v2_TRANSFORM_ALLOW_NONE, IMPAIR_v2_TRANSFORM_DROP_NONE, IMPAIR_v2_TRANSFORM_OMIT, }; /* * What can be impaired. * * See impair.c for documentation. * * XXX: make this a structure so it can be copied? */ struct impair { bool revival; bool emitting; /* * 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. */ enum impair_emit ke_payload; enum impair_emit ike_key_length_attribute; enum impair_emit child_key_length_attribute; unsigned log_rate_limit; enum impair_emit v1_hash_payload; enum impair_v1_exchange v1_hash_exchange; bool v1_hash_check; unsigned ike_initiator_spi; unsigned ike_responder_spi; bool bust_mi2; bool bust_mr2; bool drop_i2; bool sa_creation; bool jacob_two_two; bool allow_null_none; bool major_version_bump; bool minor_version_bump; bool timeout_on_retransmit; bool delete_on_retransmit; bool suppress_retransmits; bool send_bogus_payload_flag; bool send_bogus_isakmp_flag; bool send_no_delete; bool send_no_ikev2_auth; bool send_no_xauth_r0; bool send_no_idr; bool drop_xauth_r0; bool send_no_main_r2; bool force_fips; bool send_key_size_check; bool send_bogus_dcookie; bool childless_ikev2_supported; enum impair_v2_transform v2_proposal_integ; enum impair_v2_transform v2_proposal_dh; unsigned ikev2_add_ike_transform; unsigned ikev2_add_child_transform; bool replay_duplicates; bool replay_forward; bool replay_backward; bool replay_encrypted; bool corrupt_encrypted; bool proposal_parser; bool allow_dns_insecure; bool send_pkcs7_thingie; bool send_nonzero_reserved; bool send_nonzero_reserved_id; bool ikev1_del_with_notify; bool bad_ike_auth_xchg; bool rekey_initiate_supernet; bool rekey_initiate_subnet; bool rekey_respond_supernet; bool rekey_respond_subnet; bool tcp_use_blocking_write; bool tcp_skip_setsockopt_espintcp; unsigned add_unknown_v2_payload_to; unsigned add_unknown_v2_payload_to_sk; bool unknown_v2_payload_critical; unsigned force_v2_auth_method; bool ignore_v2N_SIGNATURE_HASH_ALGORITHMS; bool omit_v2N_SIGNATURE_HASH_ALGORITHMS; bool omit_v2_ike_auth_child; bool ignore_v2_ike_auth_child; bool event_check_crls; bool ignore_soft_expire; bool ignore_hard_expire; enum impair_emit v1_isakmp_delete_payload; enum impair_emit v1_ipsec_delete_payload; unsigned v2_delete_protoid; unsigned v2n_rekey_sa_protoid; unsigned v2_proposal_protoid; /* * add more here */ unsigned v1_remote_quick_id; }; extern struct impair impair; /* * What whack sends across the wire for a impair. */ struct whack_impair { unsigned what; unsigned biased_value; }; enum impair_status { IMPAIR_OK = 1, IMPAIR_HELP, IMPAIR_ERROR, }; enum impair_status parse_impair(const char *optarg, struct whack_impair *whack_impair, bool enable, struct logger *logger); enum impair_action { CALL_IMPAIR_UPDATE, CALL_INITIATE_v2_LIVENESS, CALL_SEND_KEEPALIVE, CALL_GLOBAL_EVENT_HANDLER, CALL_STATE_EVENT_HANDLER, CALL_IMPAIR_DROP_INCOMING, CALL_IMPAIR_DROP_OUTGOING, #if 0 CALL_IMPAIR_DUP_INCOMING, CALL_IMPAIR_DUP_OUTGOING, CALL_IMPAIR_CORRUPT_INCOMING, CALL_IMPAIR_CORRUPT_OUTGOING, #endif }; bool process_impair(const struct whack_impair *whack_impair, void (*action)(enum impair_action, unsigned what, unsigned how, bool background, struct logger *logger), bool background, struct logger *logger); bool have_impairments(void); void jam_impairments(struct jambuf *buf, const char *sep); #endif libreswan-4.14/include/ip_address.h000066400000000000000000000135711457372064200173620ustar00rootroot00000000000000/* 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" #include "where.h" #include "ip_bytes.h" struct in_addr; struct in6_addr; struct jambuf; 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 { bool is_set; /* * Index into the struct ip_info array; must be stream * friendly. */ enum ip_version version; /* 0, 4, 6 */ /* * We need something that makes static IPv4 initializers possible * (struct in_addr requires htonl() which is run-time only). */ struct ip_bytes bytes; } ip_address; #define PRI_ADDRESS "" #define pri_address(A) \ ((A)->is_set ? "set" : "unset"), \ (A)->version, \ pri_ip_bytes((A)->bytes) void pexpect_address(const ip_address *a, where_t where); #define paddress(A) pexpect_address(A, HERE) /* * Constructors. */ ip_address address_from_raw(where_t where, enum ip_version version, const struct ip_bytes bytes); 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; /* 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 ttoaddress_num(shunk_t src, const struct ip_info *type, ip_address *dst); /* if numeric lookup fails, try a DNS lookup */ err_t ttoaddress_dns(shunk_t src, const struct ip_info *type, ip_address *dst); /* assumes list addresses in dotted / colon notation */ err_t ttoaddress_list_num(shunk_t input, const char *delim, const struct ip_info *type, ip_address **output); /* * 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 { /* sizeof(string) includes NUL, add 1 for canary */ char buf[sizeof("[1111:2222:3333:4444:5555:6666:7777:8888]") + 1/*CANARY*/]; } address_buf; size_t jam_address(struct jambuf *buf, const ip_address *src); const char *str_address(const ip_address *src, address_buf *dst); /* either N.N.N.N or [::] */ size_t jam_address_wrapped(struct jambuf *buf, const ip_address *src); const char *str_address_wrapped(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 { /* sizeof(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/*CANARY*/]; } address_reversed_buf; size_t jam_address_sensitive(struct jambuf *buf, const ip_address *src); size_t jam_address_reversed(struct jambuf *buf, const ip_address *src); 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); typedef address_buf ipstr_buf; const char *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 an AF_UNSPEC address (i.e., uninitialized or unset), * is identified by *_unset(). */ extern const ip_address unset_address; bool address_is_unset(const ip_address *address); /* handles NULL */ const struct ip_info *address_type(const ip_address *address); /* handles NULL */ const struct ip_info *address_info(const ip_address address); bool address_is_specified(const ip_address address); bool address_is_loopback(const ip_address address); /* are two is_set() addresses identical? */ bool address_eq_address(const ip_address address, const ip_address another); /* * 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. */ /* misc. conversions and related */ 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); #endif libreswan-4.14/include/ip_bytes.h000066400000000000000000000055001457372064200170540ustar00rootroot00000000000000/* ip address type, for libreswan * * Copyright (C) 2021 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_BYTES_H #define IP_BYTES_H #include /* for uint8_t */ struct ip_info; enum ip_version { IPv4 = 4, IPv6 = 6, }; /* * We need something that makes static IPv4 initializers possible * (struct in_addr requires htonl() which is run-time only). */ struct ip_bytes { uint8_t byte[16]; }; extern const struct ip_bytes unset_ip_bytes; #define PRI_IP_BYTES "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" #define pri_ip_bytes(B) \ (B).byte[0], \ (B).byte[1], \ (B).byte[2], \ (B).byte[3], \ (B).byte[4], \ (B).byte[5], \ (B).byte[6], \ (B).byte[7], \ (B).byte[8], \ (B).byte[9], \ (B).byte[10], \ (B).byte[11], \ (B).byte[12], \ (B).byte[13], \ (B).byte[14], \ (B).byte[15] /* * Modify address bytes broken down according to AFI as * ROUTING-PREFIX:HOST-ID. */ extern const struct ip_blit set_bits; extern const struct ip_blit clear_bits; extern const struct ip_blit keep_bits; struct ip_bytes ip_bytes_from_blit(const struct ip_info *afi, const struct ip_bytes bytes, const struct ip_blit *routing_prefix, const struct ip_blit *host_id, unsigned nr_prefix_bits); /* Calculate l-r using unsigned arithmetic */ struct ip_bytes ip_bytes_sub(const struct ip_info *afi, const struct ip_bytes l, const struct ip_bytes r); /* find first non-zero bit from left */ int ip_bytes_first_set_bit(const struct ip_info *afi, const struct ip_bytes bytes); /* match prefixes, or -1 */ int ip_bytes_prefix_bits(const struct ip_info *afi, const struct ip_bytes lo, const struct ip_bytes hi); int ip_bytes_cmp(enum ip_version l_version, const struct ip_bytes l_bytes, enum ip_version r_version, const struct ip_bytes r_bytes); bool ip_bytes_is_zero(const struct ip_bytes *bytes); #define IP_INFO_UNSET(IP) \ (IP == NULL ? "null" : \ !IP->is_set ? "unset" : \ IP->info == NULL ? "family-unset" : \ NULL) #define IP_INFO_PROTOCOL_UNSET(IP) \ (IP == NULL ? "null" : \ !IP->is_set ? "unset" : \ IP->info == NULL ? "family-unset" : \ IP->protocol == NULL ? "protocol-unset" : \ NULL) #endif libreswan-4.14/include/ip_cidr.h000066400000000000000000000043631457372064200166550ustar00rootroot00000000000000/* ip cidr (prefix/host-id), for libreswan * * Copyright (C) 2020 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_CIDR_H #define IP_CIDR_H /* * NETWORK_PREFIX/HOST_IDENTIFIER * * Unlike ip_subnet, this allows a non-zero host_identifier. */ #include "ip_address.h" /* for ip_bytes */ struct jambuf; typedef struct { bool is_set; enum ip_version version; struct ip_bytes bytes; unsigned prefix_bits; } ip_cidr; #define PRI_CIDR "" #define pri_cidr(A) \ ((A).is_set ? "set" : "unset"), \ (A).version, \ pri_ip_bytes((A).bytes), \ (A).prefix_bits void pexpect_cidr(const ip_cidr a, where_t where); #define pcidr(A) pexpect_cidr(A, HERE) extern const ip_cidr unset_cidr; const struct ip_info *cidr_type(const ip_cidr *cidr); /* handles NULL */ const struct ip_info *cidr_info(const ip_cidr cidr); ip_address cidr_address(const ip_cidr cidr); /* convert CIDR address/mask; does not judge the result */ ip_cidr cidr_from_raw(where_t where, enum ip_version version, const struct ip_bytes bytes, unsigned prefix_bits); err_t numeric_to_cidr(shunk_t src, const struct ip_info *afi, ip_cidr *cidr); /* * return why, if CDIR isn't useful. * * "specified"? wikipedia refers to ::/0 as "Default route (no * specific route)" and ::/128 as "Unspecified address". While these * addresses are valid, they don't specifically specify anything... */ err_t cidr_specified(const ip_cidr cidr); bool cidr_is_specified(const ip_cidr cidr); typedef struct { char buf[sizeof(address_buf) + 4/*/128*/]; } cidr_buf; size_t jam_cidr(struct jambuf *buf, const ip_cidr *cidr); const char *str_cidr(const ip_cidr *cidr, cidr_buf*buf); #endif libreswan-4.14/include/ip_encap.h000066400000000000000000000027111457372064200170150ustar00rootroot00000000000000/* IP encapsulation, for libreswan * * Copyright (C) 2020 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. * */ /* * Should the the ESP/AH packet be encapsulated using some other * transport? For UDP this is called NAT. For TCP this is called * IKETCP. * * XXX: Confusingly mode (TUNNEL, TRANSPORT) is also (understandably) * referred to as encapsulation :-( */ #ifndef IP_ENCAP_H #define IP_ENCAP_H struct ip_encap { const char *name; const struct ip_protocol *outer; const struct ip_protocol *inner; /* * Passed into the kernel to flag that this transform is * encapsulated. * * TCP Encap of IKE and IPsec Packets * https://tools.ietf.org/html/rfc8229 */ unsigned encap_type; }; extern const struct ip_encap ip_encap_esp_in_tcp; extern const struct ip_encap ip_encap_esp_in_udp; #define PRI_IP_ENCAP "%u(%s)" #define pri_ip_encap(E) (E) == NULL ? 0 : (E)->encap_type, (E) == NULL ? "none" : (E)->name #endif libreswan-4.14/include/ip_endpoint.h000066400000000000000000000105141457372064200175470ustar00rootroot00000000000000/* ip endpoint (address + port), for libreswan * * Copyright (C) 2019-2020 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_port.h" #include "ip_protoport.h" #include "ip_bytes.h" struct jambuf; struct ip_protocol; typedef struct { bool is_set; /* * Index into the struct ip_info array; must be stream * friendly. */ enum ip_version version; /* 0, 4, 6 */ /* * We need something that makes static IPv4 initializers possible * (struct in_addr requires htonl() which is run-time only). */ struct ip_bytes bytes; /* * Protocol 0 is interpreted as a wild card so isn't allowed. */ unsigned ipproto; /* * For protocols such as UDP and TCP, the 0 port is * interpreted as a wild card so isn't allowed. */ int hport; } ip_endpoint; #define PRI_ENDPOINT "" #define pri_endpoint(A) \ ((A)->is_set ? "set" : "unset"), \ (A)->version, \ ((A)->ipproto > 255 ? "PROTO>255" : \ protocol_by_ipproto((A)->ipproto)->name), \ pri_ip_bytes((A)->bytes), \ (A)->hport void pexpect_endpoint(const ip_endpoint *e, where_t where); #define pendpoint(E) pexpect_endpoint(E, HERE) /* * Constructors. */ ip_endpoint endpoint_from_raw(where_t where, enum ip_version version, const struct ip_bytes bytes, const struct ip_protocol *protocol, ip_port port); ip_endpoint endpoint_from_address_protocol_port(const ip_address address, const struct ip_protocol *protocol, ip_port 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" * * XXX: sizeof("") includes '\0'. What's an extra few bytes between * friends? */ typedef struct { char buf[sizeof("[") + sizeof(address_buf) + sizeof("]:65535")]; } endpoint_buf; size_t jam_endpoint(struct jambuf *, const ip_endpoint*); size_t jam_endpoint_sensitive(struct jambuf *, const ip_endpoint*); const char *str_endpoint(const ip_endpoint *, endpoint_buf *); const char *str_endpoint_sensitive(const ip_endpoint *, endpoint_buf *); typedef struct { char buf[sizeof(endpoint_buf) + sizeof("--UNKNOWN--UNKNOWN-->") + sizeof(endpoint_buf)]; } endpoints_buf; size_t jam_endpoints(struct jambuf *jambuf, const ip_endpoint *src, const ip_endpoint *dst); const char *str_endpoints(const ip_endpoint *src, const ip_endpoint *dst, endpoints_buf *buf); /* * 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 an AF_UNSPEC address (i.e., uninitialized or unset), * is identified by *_unset(). */ extern const ip_endpoint unset_endpoint; bool endpoint_is_unset(const ip_endpoint *endpoint); /* handles NULL */ const struct ip_info *endpoint_type(const ip_endpoint *endpoint); /* handles NULL */ const struct ip_info *endpoint_info(const ip_endpoint endpoint); bool endpoint_is_specified(const ip_endpoint endpoint); const struct ip_protocol *endpoint_protocol(const ip_endpoint endpoint); ip_address endpoint_address(const ip_endpoint endpoint); ip_port endpoint_port(const ip_endpoint endpoint); /* * Logic */ bool endpoint_eq_endpoint(const ip_endpoint l, const ip_endpoint r); bool endpoint_address_eq_address(const ip_endpoint endpoint, const ip_address address); /* * hacks */ int endpoint_hport(const ip_endpoint endpoint); ip_endpoint set_endpoint_port(const ip_endpoint endpoint, ip_port port) MUST_USE_RESULT; void update_endpoint_port(ip_endpoint *endpoint, ip_port port); #endif libreswan-4.14/include/ip_index.h000066400000000000000000000014231457372064200170350ustar00rootroot00000000000000/* ip address type index, for libreswan * * Copyright (C) 2022 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_INDEX_H #define IP_INDEX_H enum ip_index { IPv4_INDEX, IPv6_INDEX, }; #define IP_INDEX_ROOF (IPv6_INDEX+1) #endif libreswan-4.14/include/ip_info.h000066400000000000000000000052311457372064200166620ustar00rootroot00000000000000/* 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" #include "ip_selector.h" #include "ip_sockaddr.h" #include "ip_index.h" struct ip_info { /* * address family */ enum ip_version ip_version; /* 4 or 6 */ const char *ip_name; /* "IPv4" or "IPv6" */ size_t ip_size; /* 4 or 16 */ unsigned mask_cnt; /* 32 or 128 */ /* * ip_address */ struct { const ip_address unspec; /* 0.0.0.0 or :: */ const ip_address loopback; /* 127.0.0.1 or ::1 */ size_t (*jam)(struct jambuf *buf, const struct ip_info *info, const struct ip_bytes *bytes); /* N.N.N.N or [MM:MM:MM...] */ size_t (*jam_wrapped)(struct jambuf *buf, const struct ip_info *info, const struct ip_bytes *bytes); } address; /* * ip_endpoint */ struct { size_t (*jam)(struct jambuf *buf, const struct ip_info *info, const struct ip_bytes *bytes, unsigned hport); } endpoint; /* * ip_subnet. */ struct { const ip_subnet zero; /* ::/128 or 0.0.0.0/32 */ const ip_subnet all; /* ::/0 or 0.0.0.0/0 */ } subnet; /* * ip_range. */ struct { const ip_range zero; const ip_range all; } range; /* * ip_selector * * none: match no endpoints/addresses * all: matches all endpoints/addresses * * (if nothing else, used for edge case testing) */ struct { /* matches no addresses */ const ip_selector zero; /* ::/128 or 0.0.0.0/32 */ /* matches all addresses */ const ip_selector all; /* ::/0 or 0.0.0.0/0 */ } selector; /* * ike */ /* IPv4 and IPv6 have different fragment sizes */ unsigned ikev1_max_fragment_size; unsigned ikev2_max_fragment_size; /* * socket(domain, type, protocol) * * AKA protocol family (hence PF in PF_INET and PF_INET6). * The values are the same as AF_INET and AF_INET6, and Linux * documents those instead. */ struct { int domain; const char *domain_name; } socket; /* * Sockaddr. * * AF_INET or AF_INET6 */ int af; const char *af_name; /* misc */ size_t sockaddr_size; /* sizeof(sockaddr_in) | sizeof(sockaddr_in6)? */ ip_address (*address_from_sockaddr)(const ip_sockaddr sa); ip_port (*port_from_sockaddr)(const ip_sockaddr sa); /* * IKEv2 Traffic Selector Stuff. */ enum ikev2_ts_type ikev2_ts_addr_range_type; /* * ID stuff. */ enum ike_id_type id_ip_addr; enum ike_id_type id_ip_addr_subnet; enum ike_id_type id_ip_addr_range; }; extern const struct ip_info ip_families[IP_INDEX_ROOF]; #define ipv4_info ip_families[IPv4_INDEX] #define ipv6_info ip_families[IPv6_INDEX] extern const struct ip_info *aftoinfo(int af); const struct ip_info *ip_version_info(unsigned version); #endif libreswan-4.14/include/ip_packet.h000066400000000000000000000062041457372064200171770ustar00rootroot00000000000000/* ip packet extracted from acquire, for libreswan * * Copyright (C) 2020-2021 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_PACKET_H #define IP_PACKET_H #include "ip_bytes.h" #include "ip_port.h" #include "ip_endpoint.h" #include "ip_selector.h" struct ip_protocol; struct jambuf; /* * Packet between two endpoints. */ typedef struct { bool is_set; const struct ip_info *info; /* 0, 4, 6 */ const struct ip_protocol *protocol; struct { struct ip_bytes bytes; /* * Note: An acquire triggered by a packet that did not * specify the source port (i.e., it's ephemeral) will * have .src.hport set to zero. */ int hport; } src, dst; /*XXX sec_label?*/ } ip_packet; #define PRI_PACKET "["PRI_IP_BYTES"]:%u>" #define pri_packet(S) \ ((S)->is_set ? "set" : "unset"), \ (S)->info != NULL ? (S)->info->ip_name : "IPv?", \ pri_ip_bytes((S)->src.bytes), \ (S)->src.hport, \ (S)->protocol != NULL ? (S)->protocol->name : "", \ pri_ip_bytes((S)->dst.bytes), \ (S)->dst.hport void pexpect_packet(const ip_packet *s, where_t where); #define ppacket(S) pexpect_packet(S, HERE) ip_packet packet_from_raw(where_t where, /* AFI determines meaning of ... */ const struct ip_info *afi, /* ... BYTES */ const struct ip_bytes *src_bytes, const struct ip_bytes *dst_bytes, /* PROTOCOL determines meaning of ... */ const struct ip_protocol *protocol, /* ... PORTs */ const ip_port src_port, const ip_port dst_port); /* * 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 an AF_UNSPEC address (i.e., uninitialized or unset), * is identified by *_unset(). */ extern const ip_packet unset_packet; /* attributes */ ip_address packet_src_address(const ip_packet packet); ip_address packet_dst_address(const ip_packet packet); /* packet_src_endpoint() N/A as as src port can be zero */ ip_endpoint packet_dst_endpoint(const ip_packet packet); ip_selector packet_src_selector(const ip_packet packet); ip_selector packet_dst_selector(const ip_packet packet); /* * Output. */ typedef struct { /* way over size? */ char buf[sizeof(endpoint_buf) + sizeof("-->") + sizeof(protocol_buf) + sizeof(endpoint_buf) + 1/*canary*/]; } packet_buf; size_t jam_packet(struct jambuf *buf, const ip_packet *packet); const char *str_packet(const ip_packet *packet, packet_buf *buf); #endif libreswan-4.14/include/ip_port.h000066400000000000000000000035351457372064200167200ustar00rootroot00000000000000/* ip port (port), for libreswan * * Copyright (C) 2020 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_PORT_H #define IP_PORT_H /* * XXX: Something to force the order of the port. * * Probably overkill, but then port byte order and parameters keep * being messed up. */ #include #include #include #include "err.h" struct jambuf; typedef struct { /* XXX: 0 is 0 (is this a good idea?); network ordered */ unsigned hport; } ip_port; extern const ip_port unset_port; /* aka all ports? */ ip_port ip_hport(unsigned hport); ip_port ip_nport(unsigned nport); unsigned hport(ip_port port); unsigned nport(ip_port port); bool port_is_unset(ip_port port); #define port_is_set !port_is_unset err_t ttoport(const char *text, unsigned *port); /* * XXX: to choices, which is better? * * str/jam can potentially deal with NULL and but should they? */ #define PRI_HPORT "%u" #define pri_hport(PORT) hport(PORT) #define PRI_NPORT "%04x" #define pri_nport(PORT) hport(PORT) /* yes, hport() */ typedef struct { char buf[sizeof("65535")+1/*canary*/]; } port_buf; size_t jam_hport(struct jambuf *buf, ip_port port); size_t jam_nport(struct jambuf *buf, ip_port port); const char *str_hport(ip_port port, port_buf *buf); const char *str_nport(ip_port port, port_buf *buf); #endif libreswan-4.14/include/ip_port_range.h000066400000000000000000000025001457372064200200630ustar00rootroot00000000000000/* ip port range, for libreswan * * Copyright (C) 2020 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_PORT_RANGE_H #define IP_PORT_RANGE_H #include #include #include "ip_port.h" /* * XXX: open question: all ports should be represented as 0..65535, * but how to represent no ports (magic 0 0?). * * This feeds into the selector code. */ typedef struct { bool is_set; unsigned lo; unsigned hi; } ip_port_range; ip_port_range port_range_from_ports(ip_port lo, ip_port hi); extern const ip_port_range unset_port_range; typedef struct { char buf[sizeof("65535-65535") + 1/*canary*/]; } port_range_buf; size_t jam_port_range(struct jambuf *buf, ip_port_range port_range); const char *str_port_range(ip_port_range port_range, port_range_buf *buf); #endif libreswan-4.14/include/ip_protocol.h000066400000000000000000000065661457372064200176040ustar00rootroot00000000000000/* 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 #include #include /* for IPPROTO_* */ #include "shunk.h" #include "err.h" struct jambuf; /* * What's being encapsulated using DST IP packets. * * See: * https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml * * Also see ip(7) and socket(IF_INET, SOCK_RAW, protocol). */ typedef struct ip_protocol { /* * https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml * * IPPROTO_* */ unsigned ipproto; const char *description; const char *prefix; const char *name; bool ipv6_extension_header; const char *reference; /* * IKEv1's Protocol ID * RFC2407 The Internet IP security Domain of Interpretation for ISAKMP 4.4.1 */ unsigned ikev1_protocol_id; /* * Using this to encapsulate. */ const struct ip_encap *encap_esp; /* is a port required? */ bool endpoint_requires_non_zero_port; } ip_protocol; #ifdef IPPROTO_COMP #define IPCOMP_IPPROTO IPPROTO_COMP /*linux*/ #endif #ifdef IPPROTO_IPCOMP #define IPCOMP_IPPROTO IPPROTO_IPCOMP /*everything else*/ #endif #define INTERNAL_IPPROTO 61 extern const struct ip_protocol ip_protocols[256]; #define ip_protocol_all ip_protocols[0] /* "the SA can carry all protocols" */ #define ip_protocol_icmp ip_protocols[IPPROTO_ICMP] /* Internet Control Message */ #define ip_protocol_icmpv6 ip_protocols[IPPROTO_ICMPV6] /* Internet Control Message */ #define ip_protocol_ipip ip_protocols[IPPROTO_IPIP] /* IPv4 encapsulation */ #define ip_protocol_tcp ip_protocols[IPPROTO_TCP] /* any host internal protocol */ #define ip_protocol_udp ip_protocols[IPPROTO_UDP] /* any host internal protocol */ #define ip_protocol_esp ip_protocols[IPPROTO_ESP] /* Encapsulated Security Payload */ #define ip_protocol_ah ip_protocols[IPPROTO_AH] /* Authentication Header */ #define ip_protocol_ipcomp ip_protocols[IPCOMP_IPPROTO] /* IP Payload Compression Protocol */ #define ip_protocol_internal ip_protocols[INTERNAL_IPPROTO] /* any host internal protocol */ /* match then eat the start of prefix */ const struct ip_protocol *protocol_by_caseeat_prefix(shunk_t *prefix); const struct ip_protocol *protocol_by_ipproto(unsigned protoid); const struct ip_protocol *protocol_by_shunk(shunk_t protocol); err_t ttoprotocol(shunk_t text, const ip_protocol **ipproto); /* these are kind of pointless */ typedef struct { char buf[19]; } protocol_buf; size_t jam_protocol(struct jambuf *, const struct ip_protocol *); const char *str_protocol(const struct ip_protocol *); /* ex: sep='=' gives '=TCP=>' */ size_t jam_protocols(struct jambuf *buf, const ip_protocol *src, char sep, const ip_protocol *dst); /* used to size other buffers */ #endif libreswan-4.14/include/ip_protoport.h000066400000000000000000000026021457372064200177760ustar00rootroot00000000000000/* header file for protoport, * * Copyright (C) 2020 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_PROTOPORT_H #define IP_PROTOPORT_H /* seen it, no need to see it again */ #include #include #include /* for size_t */ #include "err.h" #include "ip_port.h" #include "ip_protocol.h" struct jambuf; typedef struct { bool is_set; bool has_port_wildcard; /* i.e., must narrow port */ unsigned hport; /* 1..65535; 0->0-65535 */ unsigned ipproto; /* 1..255; 0->unset */ } ip_protoport; extern const ip_protoport unset_protoport; err_t ttoprotoport(const char *src, ip_protoport *protoport); typedef struct { char buf[32+1+32+1+1]; } protoport_buf; size_t jam_protoport(struct jambuf *buf, const ip_protoport *protoport); const char *str_protoport(const ip_protoport *protoport, protoport_buf *buf); #endif libreswan-4.14/include/ip_range.h000066400000000000000000000103741457372064200170270ustar00rootroot00000000000000/* address range, for libreswan * * 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 { bool is_set; bool is_subnet; /* hint for jam_range */ enum ip_version version; struct ip_bytes start; struct ip_bytes end; } ip_range; #define PRI_RANGE "["PRI_IP_BYTES"]>" #define pri_range(R) \ ((R)->is_set ? "set" : "unset"), \ (R)->version, \ pri_ip_bytes((R)->start), \ pri_ip_bytes((R)->end) void pexpect_range(const ip_range *r, where_t where); #define prange(R) pexpect_range(R, HERE) /* caller knows best */ ip_range range_from_raw(where_t where, enum ip_version version, const struct ip_bytes start, const struct ip_bytes end); ip_range range_from_address(const ip_address subnet); ip_range range_from_subnet(const ip_subnet subnet); err_t addresses_to_nonzero_range(const ip_address start, const ip_address end, ip_range *dst) MUST_USE_RESULT; err_t range_to_subnet(const ip_range range, ip_subnet *subnet) MUST_USE_RESULT; err_t ttorange(const char *src, const struct ip_info *afi, ip_range *dst) MUST_USE_RESULT; /* * Formatting */ typedef struct { char buf[sizeof(address_buf) + 1/*"-"*/ + sizeof(address_buf)]; } range_buf; size_t jam_range(struct jambuf *buf, const ip_range *range); const char *str_range(const ip_range *range, range_buf *buf); /* * 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 an AF_UNSPEC address (i.e., uninitialized or unset), * is identified by *_unset(). */ extern const ip_range unset_range; bool range_is_unset(const ip_range *r); /* handles NULL */ const struct ip_info *range_type(const ip_range *r); /* handles NULL */ const struct ip_info *range_info(const ip_range r); /* handles NULL */ bool range_is_zero(ip_range range); /* ::-ffff... or 0.0.0.0-0.0.0.0 */ bool range_is_all(const ip_range r); /* ::-:: or 0.0.0.0-0.0.0.0 */ bool range_eq_address(const ip_range range, const ip_address address); bool range_eq_subnet(const ip_range range, const ip_subnet subnet); bool range_eq_range(const ip_range l, const ip_range r); bool address_in_range(const ip_address address, const ip_range range); bool subnet_in_range(const ip_subnet subnet, const ip_range range); bool range_in_range(const ip_range inner, const ip_range outer); bool range_overlaps_range(const ip_range l, const ip_range r); /* * range_host_len: Calculate the number of significant bits in the * size of the range. floor(log2(|high-low| + 1)). * * If RANGE is CIDR then this returns the number of HOST IDENTIFIER * bits, otherwise it returns something slightly higher. */ int range_host_len(const ip_range range); int range_prefix_len(const ip_range range); /* * range_size: the number of IP addresses within an ip_range. * * Special return values: * 0 indicates that the range isn't of IPv4 or IPv6 addresses. * UINTMAX_MAX indicates that the range size is UINTMAX_MAX or more */ uintmax_t range_size(const ip_range r); /* * operations */ ip_address range_start(const ip_range range); /* floor */ ip_address range_end(const ip_range range); /* ceiling */ err_t range_offset_to_address(const ip_range range, uintmax_t offset, ip_address *address) MUST_USE_RESULT; err_t address_to_range_offset(const ip_range range, const ip_address address, uintmax_t *offset) MUST_USE_RESULT; #endif libreswan-4.14/include/ip_said.h000066400000000000000000000075161457372064200166570ustar00rootroot00000000000000/* 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 "diag.h" #include "ip_endpoint.h" #include "ipsec_spi.h" /* for ipsec_spi_t */ #include "ttodata.h" #include "ip_protocol.h" struct jambuf; /* * Magic SAID names for for passthrough SA. */ #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 /* * Magic values for use in combination with ip_protocol_internal to * flag shunt types. * * Danger! these are in host order; but SPIs are often in network * order. * * XXX: why do these start at 256? i.e., require more than one byte? */ enum policy_spi { SPI_NONE = 0, SPI_PASS = 256, SPI_DROP = 257, SPI_REJECT = 258, SPI_HOLD = 259, SPI_TRAP = 260, SPI_IGNORE = 261, SPI_TRAPSUBNET = 262, }; extern const struct enum_names policy_spi_names; /* * to identify an SA, we need */ typedef struct { bool is_set; /* * Index into the struct ip_info array; must be stream * friendly. */ enum ip_version version; /* 0, 4, 6 */ /* * We need something that makes static IPv4 initializers possible * (struct in_addr requires htonl() which is run-time only). */ struct ip_bytes dst; /* * Protocol 0 is interpreted as a wild card so isn't allowed. */ unsigned ipproto; /* * 32-bit SPI, assigned by the destination host; or one of the * below magic values above (in network order). * * 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 incoming packets? */ ipsec_spi_t spi; #if 0 /* * The "port" which might actually be some sort of ICMP * encoding. Determined by ipproto. */ int hport; #endif } ip_said; extern const ip_said unset_said; /* * Constructors * * Technically it should be constructed from an endpoint; * unfortunately code still passes around address+protocol+[port]. */ ip_said said_from_raw(where_t where, enum ip_version version, const struct ip_bytes bytes, const struct ip_protocol *protocol, /*ip_port port,*/ ipsec_spi_t spi); ip_said said_from_endpoint_spi(const ip_endpoint endpoint, const ipsec_spi_t spi/*network-byte-ordered*/); ip_said said_from_address_protocol_spi(const ip_address address, const struct ip_protocol *proto, ipsec_spi_t spi/*network-byte-order*/); /* * Formatting */ typedef struct { char buf[5 + ULTOT_BUF + 1 + sizeof(address_buf)]; } said_buf; size_t jam_said(struct jambuf *buf, const ip_said *said); const char *str_said(const ip_said *said, said_buf *buf); /* * Details. */ bool said_is_unset(const ip_said *said); /* handles NULL */ const struct ip_info *said_type(const ip_said *said); /* handles NULL */ const struct ip_info *said_info(const ip_said said); ip_address said_address(const ip_said said); const struct ip_protocol *said_protocol(const ip_said said); /* * Parsing */ extern diag_t ttosaid(shunk_t src, ip_said *dst); #endif libreswan-4.14/include/ip_selector.h000066400000000000000000000166641457372064200175630ustar00rootroot00000000000000/* ip traffic selector, for libreswan * * Copyright (C) 2020-2021 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_SELECTOR_H #define IP_SELECTOR_H #include "ip_address.h" #include "ip_endpoint.h" #include "ip_subnet.h" #include "ip_protoport.h" #include "ip_protocol.h" #include "ip_range.h" #include "ip_bytes.h" struct jambuf; /* * IKEv2 style traffic selectors can describe. * * LO_ADDRESS..HI_ADDRESS : LO_PORT..HI_PORT * * However, this is currently implemented using a subnet which, * bizarrely, can describe: * * 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. */ typedef struct { bool is_set; /* * Index into the struct ip_info array; must be stream * friendly. */ enum ip_version version; /* 0, 4, 6 */ /* * We need something that makes static IPv4 initializers * possible (struct in_addr requires htonl() which is run-time * only). */ struct ip_bytes bytes; /* * (routing prefix) bits. */ unsigned maskbits; unsigned ipproto; /* * For moment, one port */ int hport; } ip_selector; #define PRI_SELECTOR "" #define pri_selector(S) \ ((S)->is_set ? "set" : "unset"), \ (S)->version, \ ((S)->ipproto > 255 ? "IPPROTO>255" : \ protocol_by_ipproto((S)->ipproto)->name), \ pri_ip_bytes((S)->bytes), \ (S)->hport, \ (S)->maskbits void pexpect_selector(const ip_selector *s, where_t where); #define pselector(S) pexpect_selector(S, HERE) ip_selector selector_from_raw(where_t where, enum ip_version version, const struct ip_bytes bytes, unsigned prefix_bits, const struct ip_protocol *protocol, const ip_port port); ip_selector selector_from_address(const ip_address address); ip_selector selector_from_address_protocol(const ip_address address, const struct ip_protocol *protocol); ip_selector selector_from_address_protocol_port(const ip_address address, const struct ip_protocol *protocol, const ip_port port); ip_selector selector_from_endpoint(const ip_endpoint address); ip_selector selector_from_subnet(const ip_subnet subnet); ip_selector selector_from_subnet_protocol_port(const ip_subnet subnet, const struct ip_protocol *protocol, const ip_port port); ip_selector selector_from_range(const ip_range range); ip_selector selector_from_range_protocol_port(const ip_range range, const struct ip_protocol *protocol, const ip_port port); ip_selector selector_from_address_protoport(const ip_address address, const ip_protoport protoport); ip_selector selector_from_subnet_protoport(const ip_subnet subnet, const ip_protoport protoport); err_t numeric_to_selector(shunk_t src, const struct ip_info *afi, ip_selector *dst); /* * 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 an AF_UNSPEC address (i.e., uninitialized or unset), * is identified by *_unset(). */ extern const ip_selector unset_selector; bool selector_is_unset(const ip_selector *selector); /* handles NULL */ const struct ip_info *selector_type(const ip_selector *selector); /* handles NULL */ const struct ip_info *selector_info(const ip_selector selector); bool selector_is_zero(const ip_selector selector); /* ::/128 or 0.0.0.0/32 */ bool selector_is_all(const ip_selector selector); /* ::/0 or 0.0.0.0/0 */ /* attributes */ const struct ip_protocol *selector_protocol(const ip_selector selector); ip_range selector_range(const ip_selector selector); ip_port selector_port(const ip_selector selector); /* ip_ports selector_port_range(const ip_selector *selector); */ /* hacks */ int selector_hport(const ip_selector selector); #define update_selector_hport(SELECTOR, HPORT) { (SELECTOR)->hport = (HPORT); } #define update_selector_ipproto(SELECTOR, IPPROTO) { (SELECTOR)->ipproto = (IPPROTO); } /* assuming a subnet like XFRM does */ ip_address selector_prefix(const ip_selector selector); ip_address selector_prefix_mask(const ip_selector selector); unsigned selector_prefix_bits(const ip_selector selector); bool selector_contains_one_address(const ip_selector selector); bool address_in_selector(const ip_address l, const ip_selector r); bool endpoint_in_selector(const ip_endpoint l, const ip_selector r); bool subnet_in_selector(const ip_subnet l, const ip_selector r); bool range_in_selector(const ip_range l, const ip_selector r); bool selector_in_selector(const ip_selector l, const ip_selector r); bool selector_eq_address(const ip_selector selector, const ip_address address); bool selector_eq_endpoint(const ip_selector selector, const ip_endpoint endpoint); bool selector_eq_subnet(const ip_selector selector, const ip_subnet subnet); bool selector_eq_range(const ip_selector selector, const ip_range range); bool selector_eq_selector(const ip_selector l, const ip_selector r); bool selector_overlaps_selector(const ip_selector l, const ip_selector r); /* printing */ typedef struct { char buf[sizeof(address_buf) + 4/*"/NNN"*/ + 6/*:65535*/]; } selector_buf; const char *str_selector(const ip_selector *selector, selector_buf *out); const char *str_selector_subnet(const ip_selector *selector, subnet_buf *buf); const char *str_selector_subnet_port(const ip_selector *selector, selector_buf *out); size_t jam_selector(struct jambuf *buf, const ip_selector *selector); size_t jam_selector_subnet(struct jambuf *buf, const ip_selector *selector); size_t jam_selector_subnet_port(struct jambuf *buf, const ip_selector *selector); typedef struct { char buf[sizeof(selector_buf) + sizeof("=UNKNOWN=UNKNOWN=>") + sizeof(selector_buf)]; } selectors_buf; const char *str_selectors(const ip_selector *src, const ip_selector *dst, selectors_buf *out); size_t jam_selectors(struct jambuf *buf, const ip_selector *src, const ip_selector *dst); const char *str_selectors_sensitive(const ip_selector *src, const ip_selector *dst, selectors_buf *out); size_t jam_selectors_sensitive(struct jambuf *buf, const ip_selector *src, const ip_selector *dst); /* * XXX: hacks to get around .client not containing a proper selector * and instead needing to compare just the client's subnet. * * These are needed by code manipulating end.client because it is * serving double time. It holding either: * * - the configured client subnet * - a connection's shunt */ ip_subnet selector_subnet(const ip_selector selector); bool selector_range_eq_selector_range(const ip_selector lhs, const ip_selector rhs); bool selector_range_in_selector_range(const ip_selector lhs, const ip_selector rhs); bool selector_range_eq_address(const ip_selector selector, const ip_address address); bool address_in_selector_range(const ip_address l, const ip_selector r); #endif libreswan-4.14/include/ip_sockaddr.h000066400000000000000000000034731457372064200175270ustar00rootroot00000000000000/* unix sockaddr 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 */ #include /* for struct sockaddr_in */ #ifdef HAVE_INET6_IN6_H #include /* for struct sockaddr_in6 */ #endif #include /* * Size the sockaddr 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 struct { socklen_t len; union { /* sa.sa_* */ struct sockaddr sa; /* sin.sin_* */ struct sockaddr_in sin; /* sin6.sin6_* */ struct sockaddr_in6 sin6; } sa; } ip_sockaddr; extern const ip_sockaddr unset_sockaddr; /* * conversions * * if a port is needed then, presumably, it's an endpoint? */ ip_sockaddr sockaddr_from_address(const ip_address address); ip_sockaddr sockaddr_from_address_port(const ip_address address, const ip_port port); ip_sockaddr sockaddr_from_endpoint(const ip_endpoint endpoint); err_t sockaddr_to_address_port(const struct sockaddr *sa, size_t len, ip_address *address, ip_port *port); #endif libreswan-4.14/include/ip_subnet.h000066400000000000000000000076411457372064200172360ustar00rootroot00000000000000/* ip subnet, for libreswan * * Copyright (C) 1998, 1999, 2000 Henry Spencer. * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs * Copyright (C) 2019-2020 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 defines a traditional subnet: * * ADDRESS_PREFIX / MASK * */ #include "ip_address.h" #include "ip_endpoint.h" #include "ip_bytes.h" #include "err.h" struct jambuf; typedef struct { bool is_set; /* * Index into the struct ip_info array; must be stream * friendly. */ enum ip_version version; /* 0, 4, 6 */ /* * We need something that makes static IPv4 initializers * possible (struct in_addr requires htonl() which is run-time * only). */ struct ip_bytes bytes; /* * (routing prefix) bits. */ unsigned maskbits; } ip_subnet; #define PRI_SUBNET "" #define pri_subnet(S) \ ((S)->is_set ? "set" : "unset"), \ (S)->version, \ pri_ip_bytes((S)->bytes), \ (S)->maskbits void pexpect_subnet(const ip_subnet *s, where_t where); #define psubnet(S) pexpect_subnet(S, HERE) /* * Constructors */ ip_subnet subnet_from_raw(where_t where, enum ip_version version, const struct ip_bytes bytes, unsigned prefix_bits); /* ADDRESS..ADDRESS */ ip_subnet subnet_from_address(const ip_address address); /* ADDRESS/PREFIX_BITS */ ip_subnet subnet_from_address_prefix_bits(const ip_address address, unsigned prefixbits); /* barf if not valid */ err_t address_mask_to_subnet(const ip_address address, const ip_address mask, ip_subnet *subnet); extern err_t addresses_to_nonzero_subnet(const ip_address from, const ip_address to, ip_subnet *dst) MUST_USE_RESULT; /* * Format as a string. */ typedef struct { char buf[sizeof(address_buf) + 4/*"/NNN"*/]; } subnet_buf; extern const char *str_subnet(const ip_subnet *subnet, subnet_buf *out); extern size_t jam_subnet(struct jambuf *buf, const ip_subnet *subnet); /* * 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 an AF_UNSPEC address (i.e., uninitialized or unset), * is identified by *_unset(). */ extern const ip_subnet unset_subnet; bool subnet_is_unset(const ip_subnet *subnet); /* handles NULL */ const struct ip_info *subnet_type(const ip_subnet *subnet); /* handles NULL */ const struct ip_info *subnet_info(const ip_subnet subnet); bool subnet_is_zero(const ip_subnet subnet); /* ::/128 or 0.0.0.0/32 */ bool subnet_is_all(const ip_subnet subnet); /* ::/0 or 0.0.0.0/0 */ bool address_in_subnet(const ip_address address, const ip_subnet subnet); bool subnet_in_subnet(const ip_subnet lhs, const ip_subnet rhs); bool subnet_eq_address(const ip_subnet selector, const ip_address address); /* subnet_eq_range() === range_eq_subnet() */ bool subnet_eq_subnet(const ip_subnet a, const ip_subnet b); /* Given ROUTING_PREFIX|HOST_ID return ROUTING_PREFIX|0 */ ip_address subnet_prefix(const ip_subnet subnet); ip_address subnet_prefix_mask(const ip_subnet subnet); unsigned subnet_prefix_bits(const ip_subnet subnet); uintmax_t subnet_size(const ip_subnet subnet); extern err_t ttosubnet(shunk_t src, const struct ip_info *afi, int clash, ip_subnet *dst, struct logger *logger); #endif libreswan-4.14/include/ipsec_spi.h000066400000000000000000000023101457372064200172100ustar00rootroot00000000000000/* * 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 IPSEC_SPI_H #define IPSEC_SPI_H /* seen it, no need to see it again */ #include /* * And the SA ID stuff. * * The value is in network order. * * XXX: Like IKE SPIs it should be hunk like byte array so that the * network ordering is enforced. * * struct ipsec_spi_t { uint8_t[4]val; }; */ typedef uint32_t ipsec_spi_t; #define PRI_IPSEC_SPI "%08x" #define pri_ipsec_spi(SPI) ((unsigned) ntohl(SPI)) #endif libreswan-4.14/include/ipsecconf/000077500000000000000000000000001457372064200170365ustar00rootroot00000000000000libreswan-4.14/include/ipsecconf/confread.h000066400000000000000000000112311457372064200207660ustar00rootroot00000000000000/* 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 * Copyright (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 /* for TAILQ_ENTRY() */ #include "ipsecconf/keywords.h" # define DEFAULT_UPDOWN "ipsec _updown" #include "lset.h" #include "err.h" #include "ip_range.h" #include "ip_subnet.h" #include "ip_protoport.h" #include "ip_cidr.h" #include "lswcdefs.h" #include "authby.h" struct logger; /* 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 intmax_t 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 { const char *leftright; const struct ip_info *host_family; enum keyword_host addrtype; enum keyword_host nexttype; ip_address addr; ip_address nexthop; ip_address sourceip; bool has_client; ip_subnet subnet; ip_cidr vti_ip; ip_cidr ifaceip; char *iface; char *id; ip_protoport protoport; enum keyword_pubkey pubkey_type; enum ipseckey_algorithm_type pubkey_alg; char *pubkey; bool key_from_DNS_on_demand; 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; enum ike_version ike_version; lset_t policy; struct authby authby; lset_t sighash_policy; enum shunt_policy prospective_shunt; enum shunt_policy negotiation_shunt; enum shunt_policy failure_shunt; 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 *sec_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, struct logger *logger); extern void confread_free(struct starter_config *cfg); #endif /* _IPSEC_CONFREAD_H_ */ libreswan-4.14/include/ipsecconf/confwrite.h000066400000000000000000000021531457372064200212100ustar00rootroot00000000000000/* 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-4.14/include/ipsecconf/exec.h000066400000000000000000000014241457372064200201340ustar00rootroot00000000000000/* 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-4.14/include/ipsecconf/interfaces.h000066400000000000000000000020111457372064200213240ustar00rootroot00000000000000/* 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, const struct ip_info *family, ip_address *dst, ip_address *nh); #endif /* _STARTER_INTERFACES_H_ */ libreswan-4.14/include/ipsecconf/keywords.h000066400000000000000000000323111457372064200210560ustar00rootroot00000000000000/* 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 * Copyright (C) 2017 Mayank Totale * Copyright (C) 2020, Yulia Kuzovkova * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT 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 TAILQ_ENTRY() et.al. */ #include /* for uintmax_t */ #include "lset.h" #include "constants.h" /* * 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_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_UNIQUEIDS, KBF_DO_DNSSEC, KBF_LOGTIME, KBF_LOGAPPEND, KBF_LOGIP, KBF_AUDIT_LOG, KBF_IKEBUF, KBF_IKE_ERRQUEUE, KBF_PERPEERLOG, #ifdef XFRM_LIFETIME_DEFAULT KBF_XFRMLIFETIME, #endif KBF_CRL_STRICT, KBF_CRL_CHECKINTERVAL_MS, KBF_OCSP_STRICT, KBF_OCSP_ENABLE, KBF_OCSP_TIMEOUT, KBF_OCSP_CACHE_SIZE, KBF_OCSP_CACHE_MIN_AGE_MS, KBF_OCSP_CACHE_MAX_AGE_MS, KBF_OCSP_METHOD, KBF_CURLTIMEOUT_MS, KBF_SEEDBITS, KBF_DROP_OPPO_NULL, KBF_KEEPALIVE, KBF_PLUTODEBUG, KBF_NHELPERS, KBF_SHUNTLIFETIME_MS, 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_LISTEN_TCP, /* listen on TCP port 4500 - default no */ KBF_LISTEN_UDP, /* listen on UDP port 500/4500 - default yes */ KBF_GLOBAL_IKEv1, /* global ikev1 policy - default accept */ 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_RSASIGKEY, /* loose_enum */ /* left/right */ KSCF_ECDSAKEY, /* loose_enum */ /* left/right */ KSCF_PUBKEY, /* loose_enum */ /* left/right */ KSCF_XFRM_IF_ID, KSCF_last_loose = KSCF_XFRM_IF_ID, KSCF_UPDOWN, /* left/right */ KSCF_ID, /* left/right */ KSCF_SEC_LABEL, /* 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_SA_SEC_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_RSASIGKEY = KSCF_RSASIGKEY, /* loose_enum */ /* left/right */ KNCF_ECDSAKEY = KSCF_ECDSAKEY, /* loose_enum */ /* left/right */ KNCF_PUBKEY = KSCF_PUBKEY, /* 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_IKEPORT, /* left/right: IKE Port that must be used */ KNCF_AUTH, /* left/right */ KNCF_EAP, /* left/right */ KNCF_last_leftright = KNCF_EAP, 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_MS, KNCF_DPDTIMEOUT_MS, 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_IPSEC_LIFETIME_MS, KNCF_IPSEC_MAXBYTES, KNCF_IPSEC_MAXPACKETS, KNCF_REKEY, KNCF_REAUTH, KNCF_REKEYMARGIN_MS, KNCF_REKEYFUZZ, KNCF_COMPRESS, KNCF_KEYINGTRIES, KNCF_REPLAY_WINDOW, KNCF_IKE_LIFETIME_MS, KNCF_RETRANSMIT_TIMEOUT_MS, KNCF_RETRANSMIT_INTERVAL_MS, KNCF_AGGRMODE, KNCF_MODECONFIGPULL, KNCF_ENCAPS, KNCF_IKEv2, KNCF_PPK, KNCF_INTERMEDIATE, /* enable support for Intermediate Exchange */ 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_TCP, /* TCP (yes/no/fallback) */ KNCF_REMOTE_TCPPORT, /* TCP remote port - default 4500 */ KNCF_IGNORE_PEER_DNS, /* Accept DNS nameservers from peer */ 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 variants */ 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 */ kv_milliseconds = LELEM(9), /* value already in milliseconds */ }; #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, STARTUP_KEEP = 5, }; /* * 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_NEGO_PASS, KNS_NEGO_HOLD }; 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_pubkey, /* a public key, or set of values */ kt_number, /* an integer */ kt_time, /* a number representing time */ kt_percent, /* a number representing percentage */ kt_byte, /* a number representing Binary bytes with prefixs. KiB.. IEC 60027-2/ISO 8000 */ kt_binary, /* a number representing Binary prefixes Ki. IEC 60027-2/ISO 8000 */ 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 sparse_name *validenum; const struct lmod_info *info; }; struct keyword { const struct keyword_def *keydef; bool keyleft; bool keyright; char *string; }; /* note: these lists are dynamic */ struct kw_list { struct kw_list *next; struct keyword keyword; char *string; uintmax_t 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); #if defined(HAVE_IPTABLES) && defined(HAVE_NFTABLES) #error "set HAVE_IPTABLES or HAVE_NFTABLES" #endif #endif /* _KEYWORDS_H_ */ libreswan-4.14/include/ipsecconf/parser-controls.h000066400000000000000000000030231457372064200223420ustar00rootroot00000000000000/* 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-4.14/include/ipsecconf/parser-flex.h000066400000000000000000000015001457372064200214330ustar00rootroot00000000000000/* 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-4.14/include/ipsecconf/parser.h000066400000000000000000000022551457372064200205070ustar00rootroot00000000000000/* 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 "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-4.14/include/ipsecconf/parserlast.h000066400000000000000000000017161457372064200213740ustar00rootroot00000000000000/* 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-4.14/include/ipsecconf/pluto.h000066400000000000000000000016611457372064200203560ustar00rootroot00000000000000/* 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-4.14/include/ipsecconf/starterlog.h000066400000000000000000000022461457372064200214010ustar00rootroot00000000000000/* 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-4.14/include/ipsecconf/starterwhack.h000066400000000000000000000023251457372064200217130ustar00rootroot00000000000000/* 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; struct logger; int starter_whack_add_conn(struct starter_config *cfg, const struct starter_conn *conn, struct logger *logger); int starter_whack_route_conn(struct starter_config *cfg, struct starter_conn *conn, struct logger *logger); 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-4.14/include/jambuf.h000066400000000000000000000202161457372064200165030ustar00rootroot00000000000000/* 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" /* * struct jambuf provides a mechanism for accumulating formatted * strings into a string buffer, vis: * * struct jambuf 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 occurred and no further 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. */ struct jambuf { char *array; size_t total; size_t roof; const char *dots; }; bool jambuf_ok(struct jambuf *buf); /* * Wrap a character array up in a struct jambuf 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) { * struct jambuf buf = ARRAY_AS_JAMBUF(out->buf); * jam_...(&buf, ...); * return out->buf; * } */ struct jambuf array_as_jambuf(char *array, size_t sizeof_array); #define ARRAY_AS_JAMBUF(ARRAY) array_as_jambuf((ARRAY), sizeof(ARRAY)) /* primitive to construct a JAMBUF on the stack. */ #define JAMBUF(BUF) \ /* create the buffer */ \ for (char lswbuf[LOG_WIDTH], *lswbuf_ = lswbuf; \ lswbuf_ != NULL; lswbuf_ = NULL) \ /* create the jambuf */ \ for (struct jambuf jambuf = ARRAY_AS_JAMBUF(lswbuf), \ *BUF = &jambuf; \ BUF != NULL; BUF = NULL) /* * 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(struct jambuf *buf); const char *jambuf_cursor(struct jambuf *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(struct jambuf *buf); void jambuf_set_pos(struct jambuf *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(struct jambuf *buf, const char *format, va_list ap) VPRINTF_LIKE(2); size_t jam_raw_bytes(struct jambuf *buf, const void *bytes, size_t nr_bytes); /* wrap above */ size_t jam(struct jambuf *buf, const char *format, ...) PRINTF_LIKE(2); size_t jam_char(struct jambuf *buf, char c); size_t jam_string(struct jambuf *buf, const char *string); size_t jam_jambuf(struct jambuf *buf, struct jambuf *in); /* * Jam a string of bytes formatted in some way. */ typedef size_t (jam_bytes_fn)(struct jambuf *buf, const void *bytes, size_t size); /* * bytes as hex ... */ /* upper case hex - B1B2... */ jam_bytes_fn jam_HEX_bytes; #define jam_HEX_hunk(BUF, HUNK) \ ({ \ typeof(HUNK) hunk_ = (HUNK); /* evaluate once */ \ jam_HEX_bytes(BUF, hunk_.ptr, hunk_.len); \ }) /* lower case hex - b1b2... */ jam_bytes_fn jam_hex_bytes; #define jam_hex_hunk(BUF, HUNK) \ ({ \ typeof(HUNK) hunk_ = (HUNK); /* evaluate once */ \ jam_hex_bytes(BUF, hunk_.ptr, hunk_.len); \ }) /* hex bytes - b1 b2 b3 b4 b6 b6 b7 b8 - like DBG_dump */ jam_bytes_fn jam_dump_bytes; #define jam_dump_hunk(BUF, HUNK) \ ({ \ typeof(HUNK) hunk_ = (HUNK); /* evaluate once */ \ jam_dump_bytes(BUF, hunk_.ptr, hunk_.len); \ }) /* * bytes as base64 ... */ jam_bytes_fn jam_base64_bytes; #define jam_base64_hunk(BUF, HUNK) \ ({ \ typeof(HUNK) hunk_ = (HUNK); /* evaluate once */ \ jam_base64_bytes(BUF, hunk_.ptr, hunk_.len); \ }) /* * bytes as a string. */ /* (isprint(b1) ? \NNN : b1)... */ jam_bytes_fn jam_sanitized_bytes; #define jam_sanitized_hunk(BUF, HUNK) \ ({ \ typeof(HUNK) hunk_ = (HUNK); /* evaluate once */ \ jam_sanitized_bytes(BUF, hunk_.ptr, hunk_.len); \ }) /* (ismeta(b1)) ? \NNN : b1)... (i.e., escaped for shell within quotes) */ jam_bytes_fn jam_shell_quoted_bytes; #define jam_shell_quoted_hunk(BUF, HUNK) \ ({ \ typeof(HUNK) hunk_ = (HUNK); /* evaluate once */ \ jam_shell_quoted_bytes(BUF, hunk_.ptr, hunk_.len); \ }) /* * jam_humber(): * * Make large numbers clearer by expressing them as Ki, Mi, Gi, Ti, * Pi, Ei and 2^64 will be 16Ei based on * https://en.wikipedia.org/wiki/Binary_prefix IEC 60027-2 standard. * The prefix and suffix2 are literally copied into the output. * e.g. use sufix2 "B" for Bytes. */ typedef struct { /* lets say 3 decimal digits per byte which is way over */ char buf[sizeof(uintmax_t)*3 + 2/*Gi*/ + 1/*NUL*/ + 1/*CANARY*/]; } humber_buf; size_t jam_humber(struct jambuf *buf, uintmax_t num); const char *str_humber(uintmax_t num, humber_buf *b); /* * 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); /* (errno ERROR) */ size_t jam_errno(struct jambuf *buf, int error); #endif libreswan-4.14/include/kernel_netlink_query.h000066400000000000000000000014461457372064200214740ustar00rootroot00000000000000/* * Copyright (C) 2020 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. * */ #ifndef KERNEL_NETLINK_QUERY_H #define KERNEL_NETLINK_QUERY_H struct logger; struct nlmsghdr; int nl_send_query(const struct nlmsghdr *req, int protocol, struct logger *logger); #endif libreswan-4.14/include/kernel_netlink_reply.h000066400000000000000000000021171457372064200214560ustar00rootroot00000000000000/* * 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. * */ #ifndef KERNEL_NETLINK_REPLY_H #define KERNEL_NETLINK_REPLY_H #include /* for size_t */ 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 #endif libreswan-4.14/include/keyid.h000066400000000000000000000021471457372064200163470ustar00rootroot00000000000000/* keyid_t for libreswan * * Copyright (C) 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. */ #ifndef KEYID_H #define KEYID_H #include /* for size_t */ #include #include "err.h" #include "lswcdefs.h" typedef struct { char keyid[10/* up to 9 text digits + NUL */]; } keyid_t; extern const keyid_t empty_keyid; #define str_keyid(KEYID) (KEYID).keyid err_t splitkey_to_keyid(const uint8_t *e, size_t elen, const uint8_t *m, size_t mlen, keyid_t *dst) MUST_USE_RESULT; err_t keyblob_to_keyid(const uint8_t *src, size_t srclen, keyid_t *dst) MUST_USE_RESULT; #endif libreswan-4.14/include/keywords.h000066400000000000000000000073451457372064200171160ustar00rootroot00000000000000/* 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 jambuf; /* * NAME<>VALUE map (but with bonus .details) * * We've already got enum_names 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 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 jam_keyword_name(struct jambuf *buf, const struct keywords *keywords, unsigned value); size_t jam_keyword_sname(struct jambuf *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-4.14/include/lex.h000066400000000000000000000031171457372064200160300ustar00rootroot00000000000000/* 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 */ 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; char quote; /* was TOK wrapped in QUOTE? */ struct logger *logger; /* where to send errors */ }; extern bool lexopen(struct file_lex_position **flp, const char *name, bool optional, const struct file_lex_position *oflp); extern void lexclose(struct file_lex_position **flp); #define tokeq(FLP, S) streq((FLP)->tok, (S)) #define tokeqword(FLP, S) strcaseeq((FLP)->tok, (S)) extern bool shift(struct file_lex_position *flp); extern bool flushline(struct file_lex_position *flp, const char *message); libreswan-4.14/include/lmod.h000066400000000000000000000027511457372064200161760ustar00rootroot00000000000000/* 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" struct jambuf; /* * 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_alias { const char *name; lset_t bits; }; struct lmod_info { const enum_names *names; lset_t mask; struct lmod_alias *aliases; }; bool lmod_arg(lmod_t *mod, const struct lmod_info *info, const char *optarg, bool enable); size_t jam_lmod(struct jambuf *buf, const enum_names *names, const char *separator, lmod_t mod); #endif libreswan-4.14/include/lset.h000066400000000000000000000045071457372064200162130ustar00rootroot00000000000000/* 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 jambuf; struct sparse_name; /* * 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: */ typedef struct { char buf[512]; /* arbitrary */ } lset_buf; extern bool test_lset(const struct enum_names *table, lset_t val); size_t jam_lset(struct jambuf *, const struct enum_names *sd, lset_t val); const char *str_lset(const struct enum_names *sd, lset_t val, lset_buf *buf); size_t jam_sparse_lset(struct jambuf *, const struct sparse_name *sd, lset_t val); size_t jam_lset_short(struct jambuf *, const struct enum_names *sd, const char *separator, lset_t val); const char *str_lset_short(const struct enum_names *sd, const char *separator, lset_t val, lset_buf *buf); #endif /* CONSTANTS_H */ libreswan-4.14/include/lsw-pfkeyv2.h000066400000000000000000000106141457372064200174310ustar00rootroot00000000000000/* 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_PFKEYV2_H #define LSW_PFKEYV2_H #if defined(KERNEL_PFKEYV2) /* * See: https://tools.ietf.org/html/rfc2367 * See: https://datatracker.ietf.org/doc/html/draft-schilcher-mobike-pfkey-extension-01 * * This header pulls in all the SADB_* macro and sadb_* struct * declarations described by RFC 2368 along with any extensions. * * But what about divergence? * * RFC 2367, 1.1 Terminology * * In either case, the mandatory-to-implement, or MUST, items MUST * be fully implemented as specified here. If any mandatory item is * not implemented as specified here, that implementation is not * conforming and not compliant with this specification. * * RFC 2367, 1.7 Name Spaces: * * Inclusion of the file MUST NOT define symbols or * structures in the PF_KEYv2 name space that are not described in * this document without the explicit prior permission of the * authors. Any symbols or structures in the PF_KEYv2 name space * that are not described in this document MUST start with "SADB_X_" * or "sadb_x_". * * Things haven't exactly followed this so some tricks are used to * signal this to code using these headers: * * + implementations have replaced/renamed fields (typically reserved) * with new structure members. When this happens a macro definition * of the new name is added. * * + implementations have (arrrg, and for no obvious reason) completly * rewritten some structures. When this happens things are hacked so * that it looks like there's an sadb_x structure available. * * + implementations define SADB_X_EXT_* macro without defining / * using the corresponding sadb_x_ext_* structure. When this happens * the SADB_X_EXT_* macro is undefined. */ #ifdef __linux__ # include # include #else # include # include #endif /* * Work-around OpenBSD which defines SADB_X_EXT_SA2 but not struct * sadb_x_sa2 (it doesn't even use that structure). */ #ifdef __OpenBSD__ # ifdef SADB_X_EXT_SA2 # if SADB_X_EXT_SA2 != 23 # error confused # endif # undef SADB_X_EXT_SA2 # endif #endif /* * Work-around OpenBSD which completely re-defined struct * sadb_x_policy: the fields are not the same; the way it is used is * not the same. */ #ifdef __OpenBSD__ # ifdef SADB_X_EXT_POLICY # if SADB_X_EXT_POLICY != 25 # error confused # endif # undef SADB_X_EXT_POLICY # endif #endif /* * Work-around OpenBSD gutting struct sadb_address: * * -> dropped sadb_address_proto * -> dropped sadb_address_prefixlen * * XXX: HOW? * * XXX: But why? Since OpenBSD uses address+mask and not * address/prefixlen when specifying child selectors, I'm guessing * that the extra seemingly unused fields were simply dropped. * * The thing is that, even at the time, code was starting to use * /prefixlen, and IKEv2 introduced start-end. The IKEv1 mask was on * the way out! */ /* * Work-around various OSs reusing / renaming fields of existing * strctures. * * Use the macro expands to itself hack. */ #ifdef __OpenBSD__ /* in sadb_prop */ # define sadb_prop_num sadb_prop_num /* was sadb_prop_reserved */ #endif #ifdef __linux__ /* in sadb_x_policy */ # define sadb_x_policy_priority sadb_x_policy_priority /* was sadb_x_policy_reserved2 */ /* in sadb_x_ipsecrequest */ /* sadb_x_ipsecrequest_reqid is 32-bits not 16-bits */ # define sadb_x_ipsecrequest_reserved1 sadb_x_ipsecrequest_reserved1 # define sadb_x_ipsecrequest_reserved2 sadb_x_ipsecrequest_reserved2 #endif #ifdef __FreeBSD__ /* in sadb_x_policy */ # define sadb_x_policy_scope sadb_x_policy_scope /* was sadb_x_policy_reserved */ /* define sadb_x_policy_ifindex == sadb_x_policy_priority */ # define sadb_x_policy_priority sadb_x_policy_priority /* was sadb_x_policy_reserved2 */ #endif #endif /* KERNEL_PFKEYV2 */ #endif libreswan-4.14/include/lsw_socket.h000066400000000000000000000015241457372064200174150ustar00rootroot00000000000000/* wrap apple's lack of SOCK_CLOEXEC, for libreswan * * Copyright (C) 2022 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_SOCKET_H #define LSW_SOCKET_H #include /* * Hack to get around Darwin's (Apple's) lack of SOCK_CLOEXEC. */ int cloexec_socket(int domain, int type, int protocol); #endif libreswan-4.14/include/lswalloc.h000066400000000000000000000105301457372064200170550ustar00rootroot00000000000000/* * 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 #include #include "constants.h" #include "lswcdefs.h" struct logger; /* memory allocation */ extern void pfree(void *ptr); /* Never returns NULL; allocates 0 bytes as 1-byte */ extern void *alloc_bytes(size_t size, const char *name); /* clone's NULL bytes as NULL bytes, not 1-byte */ void *clone_bytes(const void *orig, size_t size, const char *name); void *clone_bytes_bytes(const void *lhs_ptr, size_t lhs_len, const void *rhs_ptr, size_t rhs_len, const char *name); void realloc_bytes(void **ptr, size_t old_size, size_t new_size, const char *name); extern bool leak_detective; extern bool report_leaks(struct logger *logger); /* true is bad */ /* * 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))) /* XXX: No NAME parameter; get ready for implicit HERE */ #define over_alloc_thing(THING, EXTRA) \ ((THING*) alloc_bytes(sizeof(THING) + (EXTRA), #THING)) #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 zero_thing(THING) memset(&(THING), '\0', sizeof(THING)) #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_const_things(ORIG, COUNT, NAME) \ clone_bytes((ORIG), (COUNT) * sizeof((ORIG)[0]), (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); /* can't use vaprintf() as it calls malloc() directly */ char *alloc_printf(const char *fmt, ...) PRINTF_LIKE(1) MUST_USE_RESULT; char *alloc_vprintf(const char *fmt, va_list ap) VPRINTF_LIKE(1) MUST_USE_RESULT; #endif /* _LSW_ALLOC_H_ */ libreswan-4.14/include/lswcdefs.h000066400000000000000000000042541457372064200170550ustar00rootroot00000000000000/* 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 NEVER_RETURNS __attribute__ ((noreturn)) # define UNUSED __attribute__ ((unused)) # define MUST_USE_RESULT __attribute__ ((warn_unused_result)) #else # define NEVER_RETURNS /* ignore */ # define UNUSED /* ignore */ # define MUST_USE_RESULT /* ignore */ #endif #ifdef COMPILER_HAS_NO_PRINTF_LIKE # define PRINTF_LIKE(n) /* ignore */ # define VPRINTF_LIKE(n) /* ignore */ # define STRFTIME_LIKE(n) /* ignore */ #else # define PRINTF_LIKE(n) __attribute__ ((format(printf, n, n + 1))) # define VPRINTF_LIKE(n) __attribute__((format(printf, n, 0))) # define STRFTIME_LIKE(n) __attribute__ ((format(strftime, n, 0))) #endif /* * A macro to discard the const portion of a variable to avoid * otherwise unavoidable -Wcast-qual warnings. USE WITH CAUTION and * only when you know it's safe to discard the const. */ #define DISCARD_CONST(VARTYPE, VARNAME) \ ({ \ const VARTYPE tmp = (VARNAME); \ (VARTYPE)tmp; \ }) #endif libreswan-4.14/include/lswconf.h000066400000000000000000000040421457372064200167110ustar00rootroot00000000000000/* 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 struct logger; 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, struct logger *logger); void lsw_conf_nssdir(const char *nssdir, struct logger *logger); void lsw_conf_nsspassword(const char *nsspassword); extern int libreswan_selinux(struct logger *logger); #endif libreswan-4.14/include/lswendian.h000066400000000000000000000037411457372064200172270ustar00rootroot00000000000000/* 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-4.14/include/lswfips.h000066400000000000000000000024021457372064200167230ustar00rootroot00000000000000/* 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 */ struct logger; enum lsw_fips_mode { 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(struct logger *logger); extern bool libreswan_fipsmode(void); #endif libreswan-4.14/include/lswglob.h000066400000000000000000000020761457372064200167140ustar00rootroot00000000000000/* Thread / logger friendly glob(), for libreswan. * * Copyright (C) 2005 Michael Richardson * Copyright (C) 2017 D. Hugh Redelmeier * Copyright (C) 2017 Paul Wouters * Copyright (C) 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. */ #ifndef LSWGLOB_H #define LSWGLOB_H #include #ifndef GLOB_ABORTED #define GLOB_ABORTED GLOB_ABEND /* fix for old versions */ #endif struct logger; int lswglob(const char *pattern, glob_t *pglob, const char *what, struct logger *logger); #endif libreswan-4.14/include/lswlog.h000066400000000000000000000402661457372064200165550ustar00rootroot00000000000000/* logging declarations * * 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 "passert.h" #include "constants.h" /* for DBG_... */ #include "where.h" /* used by macros */ #include "fd.h" /* for null_fd */ #include "impair.h" #define LOG_WIDTH ((size_t)1024) /* roof of number of chars in log line */ 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 with 000 prefix(does not affect exit status) */ RC_RAW, /* ditto, but also suppresses the 000 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 jambuf; /* * 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. * * This means that a simple RC_* code will go to both whack and and * the log files. */ enum stream { /* Mask the whack RC; max value is 64435+200 */ RC_MASK = 0x0fffff, STREAM_MASK = 0xf00000, NO_PREFIX = 0x1000000, /* syslog() */ /* Severity Whack Tools Prefix */ ALL_STREAMS = 0x000000, /* WARNING yes err? */ LOG_STREAM = 0x100000, /* WARNING no err? */ DEBUG_STREAM = 0x200000, /* DEBUG no err | */ WHACK_STREAM = 0x300000, /* N/A yes err */ ERROR_STREAM = 0x400000, /* ERR no err */ NO_STREAM = 0xf00000, /* N/A N/A */ /* * : add prefix when object is available * * |: add both "| " and prefex when object is available and * feature is enabled * * err?: write to stderr when enabled (tests log_to_stderr, * typically via -v). */ #define ERROR_FLAGS (ERROR_STREAM|RC_LOG_SERIOUS) #define PRINTF_FLAGS (NO_PREFIX|WHACK_STREAM) }; /* * Broadcast a log message. * * By default send it to the log file and any attached whacks (both * globally and the object). * * If any *_STREAM flag is specified then only send the message to * that stream. * * llog() is a catch-all for code that may or may not have ST. * For instance a responder decoding a message may not yet have * created the state. It will will use ST, MD, or nothing as the * prefix, and logs to ST's whackfd when possible. */ struct logger_object_vec { const char *name; bool free_object; size_t (*jam_object_prefix)(struct jambuf *buf, const void *object); #define jam_logger_prefix(BUF, LOGGER) (LOGGER)->object_vec->jam_object_prefix(BUF, (LOGGER)->object) #define jam_logger_prefix_rc(BUF, LOGGER, RC_FLAGS) \ ({ \ if (((RC_FLAGS) & NO_PREFIX) == LEMPTY && \ (((RC_FLAGS) & STREAM_MASK) != DEBUG_STREAM || \ DBGP(DBG_ADD_PREFIX))) { \ jam_logger_prefix(BUF, LOGGER); \ } \ }) /* * When opportunistic encryption or the initial responder, for * instance, some logging is suppressed. */ bool (*suppress_object_log)(const void *object); #define suppress_log(LOGGER) (LOGGER)->object_vec->suppress_object_log((LOGGER)->object) }; bool suppress_object_log_false(const void *object); bool suppress_object_log_true(const void *object); size_t jam_object_prefix_none(struct jambuf *buf, const void *object); #ifndef GLOBAL_LOGGER extern const struct logger global_logger; #define GLOBAL_LOGGER #endif struct logger { struct fd *global_whackfd; struct fd *object_whackfd; const void *object; const struct logger_object_vec *object_vec; where_t where; /* used by timing to nest its logging output */ int timing_level; }; #define PRI_LOGGER "logger@%p/"PRI_FD"/"PRI_FD #define pri_logger(LOGGER) (LOGGER), (LOGGER) == NULL ? NULL : (LOGGER)->global_whackfd, (LOGGER) == NULL ? NULL : (LOGGER)->object_whackfd void llog(lset_t rc_flags, const struct logger *log, const char *format, ...) PRINTF_LIKE(3); void llog_va_list(lset_t rc_flags, const struct logger *logger, const char *message, va_list ap) VPRINTF_LIKE(3); void jambuf_to_logger(struct jambuf *buf, const struct logger *logger, lset_t rc_flags); #define LLOG_JAMBUF(RC_FLAGS, LOGGER, BUF) \ JAMBUF(BUF) \ for (jam_logger_prefix_rc(BUF, LOGGER, RC_FLAGS); \ BUF != NULL; \ jambuf_to_logger(BUF, (LOGGER), RC_FLAGS), BUF = NULL) void llog_dump(lset_t rc_flags, const struct logger *log, const void *p, size_t len); #define llog_dump_hunk(RC_FLAGS, LOGGER, HUNK) \ { \ const typeof(HUNK) *hunk_ = &(HUNK); /* evaluate once */ \ llog_dump(RC_FLAGS, LOGGER, hunk_->ptr, hunk_->len); \ } void llog_base64_bytes(lset_t rc_flags, const struct logger *log, const void *p, size_t len); #define llog_base64_hunk(RC_FLAGS, LOGGER, HUNK) \ { \ const typeof(HUNK) *hunk_ = &(HUNK); /* evaluate once */ \ llog_base64_bytes(RC_FLAGS, LOGGER, hunk_->ptr, hunk_->len); \ } void llog_pem_bytes(lset_t rc_flags, const struct logger *log, const char *name, const void *p, size_t len); #define llog_pem_hunk(RC_FLAGS, LOGGER, NAME, HUNK) \ { \ const typeof(HUNK) *hunk_ = &(HUNK); /* evaluate once */ \ llog_pem_bytes(RC_FLAGS, LOGGER, NAME, hunk_->ptr, hunk_->len); \ } /* * 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 are implemented as wrapper functions * so that backtrace will include the below function call and that * _includes_ the MESSAGE parameter - makes debugging much easier. */ void libreswan_exit(enum pluto_exit_code rc) NEVER_RETURNS; /* * XXX: The message format is: * ERROR: [: (errno)] * and not: * ERROR: ... */ void log_error(struct logger *logger, int error, const char *message, ...) PRINTF_LIKE(3); #define llog_error(LOGGER, ERRNO, FMT, ...) \ { \ int e_ = ERRNO; /* save value across va args */ \ log_error(LOGGER, e_, FMT, ##__VA_ARGS__); \ } /* like log_error() but no ERROR: prefix */ void llog_errno(lset_t rc_flags, const struct logger *logger, int error, const char *message, ...) PRINTF_LIKE(4); /* * XXX: The message format is: * FATAL ERROR: * and not: * FATAL ERROR: */ void fatal(enum pluto_exit_code rc, const struct logger *logger, const char *message, ...) PRINTF_LIKE(3) NEVER_RETURNS; void fatal_errno(enum pluto_exit_code rc, const struct logger *logger, int error, const char *message, ...) PRINTF_LIKE(4) NEVER_RETURNS; /* * 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 DEBUG_PREFIX "| " #define DBGP(cond) (cur_debugging & (cond)) #define DBGF(COND, MESSAGE, ...) \ { \ if (DBGP(COND)) { \ DBG_log(MESSAGE, ##__VA_ARGS__); \ } \ } #define dbg(MESSAGE, ...) \ { \ if (DBGP(DBG_BASE)) { \ DBG_log(MESSAGE, ##__VA_ARGS__); \ } \ } #define ldbg(LOGGER, MESSAGE, ...) \ { \ if (DBGP(DBG_BASE)) { \ llog(DEBUG_STREAM, (LOGGER), \ MESSAGE, ##__VA_ARGS__); \ } \ } #define LDBGP(LOGGER, COND, BUF) \ /* allocate the buffer */ \ for (char buf_[LOG_WIDTH], \ *dbgp_ = (DBGP(COND) ? buf_ : NULL); \ dbgp_ != NULL; \ dbgp_ = NULL) \ /* create the jambuf_; no prefix; use jambuf_ */ \ for (struct jambuf jambuf_ = ARRAY_AS_JAMBUF(buf_), \ *BUF = &jambuf_; \ BUF != NULL; \ BUF = NULL, \ jambuf_to_logger(&jambuf_, LOGGER, DEBUG_STREAM)) #define LDBG(LOGGER, BUF) LDBGP(LOGGER, DBG_BASE, BUF) /* DBG_*() are unconditional */ void DBG_log(const char *message, ...) PRINTF_LIKE(1); void DBG_va_list(const char *message, va_list ap) VPRINTF_LIKE(1); void DBG_dump(const char *label, const void *p, size_t len); #define DBG_dump_hunk(LABEL, HUNK) \ { \ const 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)) /* * 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 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? */ /* * 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 jambuf *log) { LSWBUF(buf) { jam(buf, "written to buf"); lswlogl(log, buf); /* add to calling array */ } } #endif /* * 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 analyzer tools are easily confused, explicitly * return the assertion result. */ #ifdef EXAMPLE void lswlog_pexpect_example(void *p) { if (!pexpect(p != NULL)) { return; } } #endif extern void llog_pexpect(const struct logger *logger, where_t where, const char *message, ...) PRINTF_LIKE(3); #define PEXPECT(LOGGER, ASSERTION) \ ({ \ /* wrapping ASSERTION in parens suppresses -Wparen */ \ bool assertion__ = ASSERTION; /* no parens */ \ if (!assertion__) { \ where_t here_ = HERE; \ const struct logger *logger_ = LOGGER; \ llog_pexpect(logger_, here_, "%s", #ASSERTION); \ } \ assertion__; /* result */ \ }) #define pexpect(ASSERTION) PEXPECT(&global_logger, ASSERTION) /* 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, LOGGER, ASSERTION) \ { \ if (impair.BEHAVIOUR) { \ bool assertion_ = ASSERTION; \ if (!assertion_) { \ llog(RC_LOG, LOGGER, \ "IMPAIR: assertion '%s' failed", \ #ASSERTION); \ } \ } else { \ passert(ASSERTION); \ } \ } #endif /* _LSWLOG_H_ */ libreswan-4.14/include/lswnss.h000066400000000000000000000066271457372064200166020ustar00rootroot00000000000000/* * 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 /* for PRErrorCode, for PR_GetError() */ #include #include "lswcdefs.h" /* for PRINTF_LIKE() */ #include "lset.h" #include "lswalloc.h" #include "secrets.h" #include "diag.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. */ diag_t lsw_nss_setup(const char *config_dir, unsigned flags, struct logger *logger); void lsw_nss_shutdown(void); /* * Any code that could call back into lsw_nss_get_password() needs to * pass in a context parameter - the logger is it. Otherwise the * password code can't log! * * Just a wrapper but type checked. */ #define lsw_nss_get_password_context(LOGGER) ({ struct logger *l_ = LOGGER; l_; }) PK11SlotInfo *lsw_nss_get_authenticated_slot(struct logger *logger); /* * These get the error using the thread-local PR_GetError() which * should always be set (or is passed in). * * jam: (...) * log: NSS: : (...) * * XXX: not all are implemented. */ size_t jam_nss_error_code(struct jambuf *log, PRErrorCode code); void llog_nss_error_code(lset_t rc_log, struct logger *logger, PRErrorCode code, const char *message, ...) PRINTF_LIKE(4); #define llog_nss_error(RC_LOG, LOGGER, MESSAGE, ...) \ llog_nss_error_code(RC_LOG, LOGGER, PR_GetError(), \ MESSAGE, ##__VA_ARGS__) diag_t diag_nss_error(const char *message, ...) PRINTF_LIKE(1); void passert_nss_error(const struct logger *logger, where_t where, const char *message, ...) PRINTF_LIKE(3) NEVER_RETURNS; void pexpect_nss_error(struct logger *logger, where_t where, const char *message, ...) PRINTF_LIKE(3); #define ldbg_nss_error(LOGGER, MESSAGE, ...) \ { \ if (DBGP(DBG_BASE)) { \ llog_nss_error(DEBUG_STREAM, logger, \ MESSAGE, ##__VA_ARGS__); \ } \ } size_t jam_nss_cka(struct jambuf *buf, CK_ATTRIBUTE_TYPE attribute); size_t jam_nss_ckf(struct jambuf *buf, CK_FLAGS flags); size_t jam_nss_ckm(struct jambuf *buf, CK_MECHANISM_TYPE mechanism); size_t jam_nss_oid(struct jambuf *buf, SECOidTag oidtag); size_t jam_nss_secitem(struct jambuf *buf, const SECItem *secitem); const char *str_nss_oid(SECOidTag oid, enum_buf *buf); const char *str_nss_ckm(CK_MECHANISM_TYPE mechanism, enum_buf *buf); /* these do not clone */ chunk_t same_secitem_as_chunk(SECItem si); shunk_t same_secitem_as_shunk(SECItem si); SECItem same_chunk_as_secitem(chunk_t chunk, SECItemType type); SECItem same_shunk_as_secitem(shunk_t chunk, SECItemType type); /* NSS doesn't do const */ /* this clones */ chunk_t clone_secitem_as_chunk(SECItem si, const char *name); #endif libreswan-4.14/include/lswseccomp.h000066400000000000000000000031071457372064200174160ustar00rootroot00000000000000/* * 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 #include #include "lswlog.h" /* for libreswan_exit() et.al. referred to by macro */ /* * Add system call NAME to seccomp. * * Needs to be a macro so that SCMP_SYS(NAME) expands correctly. * * XXX: seccomp_release() isn't technically needed - the context * hasn't been loaded so can be dropped on the floor. */ #define LSW_SECCOMP_ADD(NAME) { \ /* returns 0 or -ve errno */ \ int rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, \ SCMP_SYS(NAME), 0); \ if (rc != 0) { \ seccomp_release(ctx); /* XXX: needed? */ \ if (rc < 0) { \ fatal_errno(PLUTO_EXIT_SECCOMP_FAIL, logger, -rc, \ "seccomp_rule_add() failed for system call '%s'", \ #NAME); \ } else { \ fatal(PLUTO_EXIT_SECCOMP_FAIL, logger, \ "seccomp_rule_add() failed for system call '%s' with unexpected error %d", \ #NAME, rc); \ } \ } \ } #endif libreswan-4.14/include/lswtool.h000066400000000000000000000002711457372064200167410ustar00rootroot00000000000000 /* * For stand-alone tools. * * XXX: can "progname" be made private to lswlog.c? */ struct logger; extern const char *progname; struct logger *tool_init_log(const char *progname); libreswan-4.14/include/lswversion.h000066400000000000000000000020421457372064200174470ustar00rootroot00000000000000/* * 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 LSWVERSION_H #define LSWVERSION_H /* seen it, no need to see it again */ 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[]; #endif libreswan-4.14/include/monotime.h000066400000000000000000000051111457372064200170630ustar00rootroot00000000000000/* 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); monotime_t monotime_ms(intmax_t milliseconds); #define MONOTIME_EPOCH { { 0, 0 } } extern const monotime_t monotime_epoch; bool is_monotime_epoch(monotime_t t); monotime_t mononow(void); monotime_t monotime_add(monotime_t t, deltatime_t d); monotime_t monotime_sub(monotime_t t, deltatime_t d); /* sign(a - b); see timercmp() for hacks origin */ int monotime_sub_sign(monotime_t l, monotime_t r); #define monotime_cmp(L, OP, R) (monotime_sub_sign(L, R) OP 0) 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(struct jambuf *buf, monotime_t d); #endif libreswan-4.14/include/names_constant.h000066400000000000000000000075531457372064200202640ustar00rootroot00000000000000/* * names_constant.h */ #include extern enum_names ip_protocol_id_names; /* aka ipproto_*; in ip_protocol.c */ extern enum_names sa_policy_bit_names; extern enum_names dpd_action_names; #ifdef KERNEL_XFRM extern enum_names xfrm_policy_names; #endif extern enum_names sd_action_names; extern enum_names stf_status_names; extern enum_names keyword_auth_names; extern enum_names keyword_host_names; extern const enum_names debug_names; extern const enum_names debug_help; extern const struct lmod_info debug_lmod_info; extern enum_names shunt_policy_names; extern enum_names connection_kind_names; extern enum_names routing_story; extern enum_names certpolicy_type_names; extern enum_names oakley_attr_names; extern enum_names 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 enum_names sa_lifetime_names; extern enum_names encapsulation_mode_names; extern enum_names auth_alg_names; extern enum_names oakley_lifetime_names; extern enum_names ike_version_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 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 isakmp_xchg_type_names; extern enum_enum_names exchange_type_names; extern enum_names ikev1_protocol_names; extern enum_names isakmp_transformid_names; extern enum_names ah_transformid_names; extern enum_names esp_transformid_names; extern enum_names ipsec_ipcomp_algo_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 v1_notification_names; /* IKEv2 */ extern enum_names ikev2_auth_method_names; extern enum_names ikev2_hash_algorithm_names; extern enum_names ikev2_proposal_protocol_id_names; /* 1=IKE SA, 2=AH, 3=ESP */ extern enum_names ikev2_delete_protocol_id_names; /* 1=IKE SA, 2=AH, 3=ESP */ extern enum_names ikev2_notify_protocol_id_names; /* NONE=0, 1=IKE, 2=AH, 3=ESP */ 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_cert_type_names; extern enum_names v2_notification_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; extern enum_names eap_code_names; extern enum_names eap_type_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 enum_names natt_method_names; extern enum_names secret_kind_names; extern enum_names ikev2_ppk_id_type_names; /* natt traversal types */ extern const char *const natt_type_bitnames[]; libreswan-4.14/include/netlink_attrib.h000066400000000000000000000033101457372064200202440ustar00rootroot00000000000000#ifndef NETLINK_ATTRIB_H #define NETLINK_ATTRIB_H #include /* for uint32_t */ /* * GRRR: * * GLIBC/Linux and MUSL/Linux define sockaddr_in et.al. in * , and the generic network code uses this. * Unfortunately (cough) the Linux kernel headers also provide * definitions of those structures in et.al. which, * depending on header include order can result in conflicting * definitions. For instance, if sockaddr_in is not defined, * will include the definition in but that * will then clash with a later include of . * * GLIBC/Linux has hacks on hacks to work-around this, not MUSL. * Fortunately, including first will force the Linux * kernel headers to use that definition. */ #include #include "linux/xfrm.h" /* local (if configured) or system copy; for xfrm_user... */ #include /* for nlmmsghdr et.al. */ #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; }; void 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); void nl_addattr_nest_end(struct nlmsghdr *n, struct rtattr *nest); void nl_addattrstrz(struct nlmsghdr *n, int maxlen, int type, const char *str); void nl_addattr32(struct nlmsghdr *n, int maxlen, int type, const uint32_t data); #endif libreswan-4.14/include/nss_cert_load.h000066400000000000000000000021351457372064200200560ustar00rootroot00000000000000/* * 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 "ckaid.h" #include "secrets.h" extern CERTCertificate *get_cert_by_nickname_from_nss(const char *nickname, struct logger *logger); extern CERTCertificate *get_cert_by_ckaid_from_nss(const ckaid_t *ckaid, struct logger *logger); #endif /* _NSS_CERT_LOAD_H */ libreswan-4.14/include/oid.h000066400000000000000000000032111457372064200160060ustar00rootroot00000000000000/* * 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-4.14/include/passert.h000066400000000000000000000041051457372064200167170ustar00rootroot00000000000000/* * 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" struct logger; /* our versions of assert: log result */ /* * Preferred: can log with prefix to whack from a thread. */ #ifndef GLOBAL_LOGGER extern const struct logger global_logger; #define GLOBAL_LOGGER #endif extern void llog_passert(const struct logger *logger, where_t where, const char *message, ...) NEVER_RETURNS PRINTF_LIKE(3); #define PASSERT(LOGGER, ASSERTION) \ ({ \ /* wrapping ASSERTION in parens suppresses -Wparen */ \ bool assertion__ = ASSERTION; /* no parens */ \ if (!assertion__) { \ where_t here = HERE; \ const struct logger *logger_ = LOGGER; \ llog_passert(logger_, here, "%s", #ASSERTION); \ } \ (void) true; \ }) #define passert(ASSERTION) PASSERT(&global_logger, ASSERTION) /* evaluate x exactly once; assert that err_t result is NULL; */ #define happy(x) /* TBD: use ??? */ \ { \ err_t ugh = x; \ if (ugh != NULL) { \ llog_passert(&global_logger, HERE, \ "%s", ugh); \ } \ } #endif /* _LIBRESWAN_PASSERT_H */ libreswan-4.14/include/pfkeyv2/000077500000000000000000000000001457372064200164535ustar00rootroot00000000000000libreswan-4.14/include/pfkeyv2/README.md000066400000000000000000000016251457372064200177360ustar00rootroot00000000000000This directory contains versions of taken from the various BSD derived distributions that provide PFKEY V2. They are included for reference: - BSD builds include the system header - Linux builds shouldn't include pfkeyv2.h at all The files are: - a copy of embedded in RFC 2367 (named rfc2367.h) this file, from NRL, is in the public domain - copy of taken from mainline FreeBSD and NetBSD, (named freebsd.h, netbsd.h) the files are BSD-3-Clause (C) WIDE Project - copy of taken from mainline OpenBSD (named openbsd.h) the file is BSD-4-Clause (C) NRL This (C) is strange: NRL releaed the same text as public domain; Berkley revoked the 4th clause; and constant's can't be (C). (with some Make foo, it is possible to build the BSD kernel code on a linux host using one of these files; just don't try to run it) libreswan-4.14/include/pfkeyv2/darwin-xnu.h000066400000000000000000000420571457372064200207300ustar00rootroot00000000000000/* * Copyright (c) 2000-2011 Apple Computer, Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. The rights granted to you under the License * may not be used to create, or enable the creation or redistribution of, * unlawful or unlicensed copies of an Apple operating system, or to * circumvent, violate, or enable the circumvention or violation of, any * terms of an Apple operating system software license agreement. * * Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* $KAME: pfkeyv2.h,v 1.10 2000/03/22 07:04:20 sakane 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. */ /* * This file has been derived rfc 2367, * And added some flags of SADB_KEY_FLAGS_ as SADB_X_EXT_. * sakane@ydc.co.jp */ #ifndef _NET_PFKEYV2_H_ #define _NET_PFKEYV2_H_ #include #include /* * 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 #define PF_KEY_V2 2 #define PFKEYV2_REVISION 199806L #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 /* by policy index */ #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 /* by policy id */ #define SADB_GETSASTAT 23 #define SADB_X_SPDENABLE 24 /* by policy id */ #define SADB_X_SPDDISABLE 25 /* by policy id */ #define SADB_MIGRATE 26 #define SADB_MAX 26 struct sadb_msg { u_int8_t sadb_msg_version; u_int8_t sadb_msg_type; u_int8_t sadb_msg_errno; u_int8_t sadb_msg_satype; u_int16_t sadb_msg_len; u_int16_t sadb_msg_reserved; u_int32_t sadb_msg_seq; u_int32_t sadb_msg_pid; }; struct sadb_ext { u_int16_t sadb_ext_len; u_int16_t sadb_ext_type; }; struct sadb_sa { u_int16_t sadb_sa_len; u_int16_t sadb_sa_exttype; u_int32_t sadb_sa_spi; u_int8_t sadb_sa_replay; u_int8_t sadb_sa_state; u_int8_t sadb_sa_auth; u_int8_t sadb_sa_encrypt; u_int32_t sadb_sa_flags; }; #ifdef PRIVATE struct sadb_sa_2 { struct sadb_sa sa; u_int16_t sadb_sa_natt_port; union { u_int16_t sadb_reserved0; u_int16_t sadb_sa_natt_interval; }; u_int16_t sadb_sa_natt_offload_interval; #define SADB_SA_NATT_SRC_PORT 1 u_int16_t sadb_sa_natt_src_port; }; #endif /* PRIVATE */ struct sadb_lifetime { u_int16_t sadb_lifetime_len; u_int16_t sadb_lifetime_exttype; u_int32_t sadb_lifetime_allocations; u_int64_t sadb_lifetime_bytes; u_int64_t sadb_lifetime_addtime; u_int64_t sadb_lifetime_usetime; }; struct sadb_address { u_int16_t sadb_address_len; u_int16_t sadb_address_exttype; u_int8_t sadb_address_proto; u_int8_t sadb_address_prefixlen; u_int16_t sadb_address_reserved; }; struct sadb_key { u_int16_t sadb_key_len; u_int16_t sadb_key_exttype; u_int16_t sadb_key_bits; u_int16_t sadb_key_reserved; }; struct sadb_ident { u_int16_t sadb_ident_len; u_int16_t sadb_ident_exttype; u_int16_t sadb_ident_type; u_int16_t sadb_ident_reserved; u_int64_t sadb_ident_id; }; struct sadb_sens { u_int16_t sadb_sens_len; u_int16_t sadb_sens_exttype; u_int32_t sadb_sens_dpd; u_int8_t sadb_sens_sens_level; u_int8_t sadb_sens_sens_len; u_int8_t sadb_sens_integ_level; u_int8_t sadb_sens_integ_len; u_int32_t sadb_sens_reserved; }; struct sadb_prop { u_int16_t sadb_prop_len; u_int16_t sadb_prop_exttype; u_int8_t sadb_prop_replay; u_int8_t sadb_prop_reserved[3]; }; struct sadb_comb { u_int8_t sadb_comb_auth; u_int8_t sadb_comb_encrypt; u_int16_t sadb_comb_flags; u_int16_t sadb_comb_auth_minbits; u_int16_t sadb_comb_auth_maxbits; u_int16_t sadb_comb_encrypt_minbits; u_int16_t sadb_comb_encrypt_maxbits; u_int32_t sadb_comb_reserved; u_int32_t sadb_comb_soft_allocations; u_int32_t sadb_comb_hard_allocations; u_int64_t sadb_comb_soft_bytes; u_int64_t sadb_comb_hard_bytes; u_int64_t sadb_comb_soft_addtime; u_int64_t sadb_comb_hard_addtime; u_int64_t sadb_comb_soft_usetime; u_int64_t sadb_comb_hard_usetime; }; struct sadb_supported { u_int16_t sadb_supported_len; u_int16_t sadb_supported_exttype; u_int32_t sadb_supported_reserved; }; struct sadb_alg { u_int8_t sadb_alg_id; u_int8_t sadb_alg_ivlen; u_int16_t sadb_alg_minbits; u_int16_t sadb_alg_maxbits; u_int16_t sadb_alg_reserved; }; struct sadb_spirange { u_int16_t sadb_spirange_len; u_int16_t sadb_spirange_exttype; u_int32_t sadb_spirange_min; u_int32_t sadb_spirange_max; u_int32_t sadb_spirange_reserved; }; struct sadb_x_kmprivate { u_int16_t sadb_x_kmprivate_len; u_int16_t sadb_x_kmprivate_exttype; u_int32_t sadb_x_kmprivate_reserved; }; /* * XXX Additional SA Extension. * mode: tunnel or transport * reqid: to make SA unique nevertheless the address pair of SA are same. * Mainly it's for VPN. */ struct sadb_x_sa2 { u_int16_t sadb_x_sa2_len; u_int16_t sadb_x_sa2_exttype; u_int8_t sadb_x_sa2_mode; union { u_int8_t sadb_x_sa2_reserved1; #ifdef PRIVATE u_int8_t sadb_x_sa2_alwaysexpire; #endif }; union { u_int16_t sadb_x_sa2_reserved2; #ifdef PRIVATE u_int16_t sadb_x_sa2_flags; #endif }; u_int32_t sadb_x_sa2_sequence; u_int32_t sadb_x_sa2_reqid; }; /* XXX Policy Extension */ /* sizeof(struct sadb_x_policy) == 16 */ struct sadb_x_policy { u_int16_t sadb_x_policy_len; u_int16_t sadb_x_policy_exttype; u_int16_t sadb_x_policy_type; /* See policy type of ipsec.h */ u_int8_t sadb_x_policy_dir; /* direction, see ipsec.h */ u_int8_t sadb_x_policy_reserved; u_int32_t sadb_x_policy_id; u_int32_t sadb_x_policy_reserved2; }; /* * When policy_type == IPSEC, it is followed by some of * the ipsec policy request. * [total length of ipsec policy requests] * = (sadb_x_policy_len * sizeof(uint64_t) - sizeof(struct sadb_x_policy)) */ #ifdef PRIVATE /* IPsec Interface Extension: * IPsec interface can be specified alone, or all three * of internal, outgoing, and IPsec interfaces must be * specified. */ struct sadb_x_ipsecif { u_int16_t sadb_x_ipsecif_len; u_int16_t sadb_x_ipsecif_exttype; char sadb_x_ipsecif_internal_if[IFXNAMSIZ]; /* Steal packets from this interface */ char sadb_x_ipsecif_outgoing_if[IFXNAMSIZ]; /* Send packets out on this interface */ char sadb_x_ipsecif_ipsec_if[IFXNAMSIZ]; /* Direct packets through ipsec interface */ u_int16_t sadb_x_ipsecif_init_disabled; /* 0 or 1, flag to ignore policy */ u_int16_t reserved; }; #endif /* XXX IPsec Policy Request Extension */ /* * This structure is aligned 8 bytes. */ struct sadb_x_ipsecrequest { u_int16_t sadb_x_ipsecrequest_len; /* structure length aligned to 8 bytes. * This value is true length of bytes. * Not in units of 64 bits. */ u_int16_t sadb_x_ipsecrequest_proto; /* See ipsec.h */ u_int8_t sadb_x_ipsecrequest_mode; /* See IPSEC_MODE_XX in ipsec.h. */ u_int8_t sadb_x_ipsecrequest_level; /* See IPSEC_LEVEL_XX in ipsec.h */ u_int16_t sadb_x_ipsecrequest_reqid; /* See ipsec.h */ /* * followed by source IP address of SA, and immediately followed by * destination IP address of SA. These encoded into two of sockaddr * structure without any padding. Must set each sa_len exactly. * Each of length of the sockaddr structure are not aligned to 64bits, * but sum of x_request and addresses is aligned to 64bits. */ }; struct sadb_session_id { u_int16_t sadb_session_id_len; u_int16_t sadb_session_id_exttype; /* [0] is an arbitrary handle that means something only for requester * [1] is a global session id for lookups in the kernel and racoon. */ u_int64_t sadb_session_id_v[2]; } __attribute__ ((aligned(8))); struct sastat { u_int32_t spi; /* SPI Value, network byte order */ u_int32_t created; /* for lifetime */ struct sadb_lifetime lft_c; /* CURRENT lifetime. */ }; // no need to align struct sadb_sastat { u_int16_t sadb_sastat_len; u_int16_t sadb_sastat_exttype; u_int32_t sadb_sastat_dir; u_int32_t sadb_sastat_reserved; u_int32_t sadb_sastat_list_len; /* list of struct sastat comes after */ } __attribute__ ((aligned(8))); #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 #define SADB_EXT_SESSION_ID 20 #define SADB_EXT_SASTAT 21 #define SADB_X_EXT_IPSECIF 22 #define SADB_X_EXT_ADDR_RANGE_SRC_START 23 #define SADB_X_EXT_ADDR_RANGE_SRC_END 24 #define SADB_X_EXT_ADDR_RANGE_DST_START 25 #define SADB_X_EXT_ADDR_RANGE_DST_END 26 #define SADB_EXT_MIGRATE_ADDRESS_SRC 27 #define SADB_EXT_MIGRATE_ADDRESS_DST 28 #define SADB_X_EXT_MIGRATE_IPSECIF 29 #define SADB_EXT_MAX 29 #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_X_SATYPE_POLICY 10 #define SADB_SATYPE_MAX 11 #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 #define SADB_SAFLAGS_PFS 1 /* RFC2367 numbers - meets RFC2407 */ #define SADB_AALG_NONE 0 #define SADB_AALG_MD5HMAC 1 /*2*/ #define SADB_AALG_SHA1HMAC 2 /*3*/ #define SADB_AALG_MAX 8 /* private allocations - based on RFC2407/IANA assignment */ #define SADB_X_AALG_SHA2_256 6 /*5*/ #define SADB_X_AALG_SHA2_384 7 /*6*/ #define SADB_X_AALG_SHA2_512 8 /*7*/ /* private allocations should use 249-255 (RFC2407) */ #define SADB_X_AALG_MD5 3 /*249*/ /* Keyed MD5 */ #define SADB_X_AALG_SHA 4 /*250*/ /* Keyed SHA */ #define SADB_X_AALG_NULL 5 /*251*/ /* null authentication */ /* RFC2367 numbers - meets RFC2407 */ #define SADB_EALG_NONE 0 #define SADB_EALG_DESCBC 1 /*2*/ #define SADB_EALG_3DESCBC 2 /*3*/ #define SADB_EALG_NULL 3 /*11*/ #define SADB_EALG_MAX 12 /* private allocations - based on RFC2407/IANA assignment */ #define SADB_X_EALG_CAST128CBC 5 /*6*/ #define SADB_X_EALG_BLOWFISHCBC 4 /*7*/ #define SADB_X_EALG_RIJNDAELCBC 12 #define SADB_X_EALG_AESCBC 12 #define SADB_X_EALG_AES 12 #define SADB_X_EALG_AES_GCM 13 #define SADB_X_EALG_CHACHA20POLY1305 14 /* private allocations should use 249-255 (RFC2407) */ #if 1 /*nonstandard */ #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_MAX 4 #endif #define SADB_IDENTTYPE_RESERVED 0 #define SADB_IDENTTYPE_PREFIX 1 #define SADB_IDENTTYPE_FQDN 2 #define SADB_IDENTTYPE_USERFQDN 3 #define SADB_X_IDENTTYPE_ADDR 4 #define SADB_IDENTTYPE_MAX 4 /* `flags' in sadb_sa structure holds followings */ #define SADB_X_EXT_NONE 0x0000 /* i.e. new format. */ #define SADB_X_EXT_OLD 0x0001 /* old format. */ #ifdef PRIVATE #define SADB_X_EXT_NATT 0x0002 /* Use UDP encapsulation to traverse NAT */ #define SADB_X_EXT_NATT_KEEPALIVE 0x0004 /* Local node is behind NAT, send keepalives */ /* Should only be set for outbound SAs */ #define SADB_X_EXT_NATT_MULTIPLEUSERS 0x0008 /* For use on VPN server - support multiple users */ #endif /* PRIVATE */ #define SADB_X_EXT_IV4B 0x0010 /* IV length of 4 bytes in use */ #define SADB_X_EXT_DERIV 0x0020 /* DES derived */ #define SADB_X_EXT_CYCSEQ 0x0040 /* allowing to cyclic sequence. */ /* three of followings are exclusive flags each them */ #define SADB_X_EXT_PSEQ 0x0000 /* sequencial padding for ESP */ #define SADB_X_EXT_PRAND 0x0100 /* random padding for ESP */ #define SADB_X_EXT_PZERO 0x0200 /* zero padding for ESP */ #define SADB_X_EXT_PMASK 0x0300 /* mask for padding flag */ #define SADB_X_EXT_IIV 0x0400 /* Implicit IV */ #ifdef PRIVATE #define SADB_X_EXT_NATT_DETECTED_PEER 0x1000 #define SADB_X_EXT_ESP_KEEPALIVE 0x2000 #define SADB_X_EXT_PUNT_RX_KEEPALIVE 0x4000 #define SADB_X_EXT_NATT_KEEPALIVE_OFFLOAD 0x8000 #endif /* PRIVATE */ #ifdef PRIVATE #define NATT_KEEPALIVE_OFFLOAD_INTERVAL 0x1 #endif #if 1 #define SADB_X_EXT_RAWCPI 0x0080 /* use well known CPI (IPComp) */ #endif #define SADB_KEY_FLAGS_MAX 0x7fff #ifdef PRIVATE #define SADB_X_EXT_SA2_DELETE_ON_DETACH 0x0001 #define SADB_X_EXT_SA2_SEQ_PER_TRAFFIC_CLASS 0x0002 #endif /* SPI size for PF_KEYv2 */ #define PFKEY_SPI_SIZE sizeof(u_int32_t) /* Identifier for menber of lifetime structure */ #define SADB_X_LIFETIME_ALLOCATIONS 0 #define SADB_X_LIFETIME_BYTES 1 #define SADB_X_LIFETIME_ADDTIME 2 #define SADB_X_LIFETIME_USETIME 3 /* The rate for SOFT lifetime against HARD one. */ #define PFKEY_SOFT_LIFETIME_RATE 80 /* Utilities */ #define PFKEY_ALIGN8(a) (1 + (((a) - 1) | (8 - 1))) #define PFKEY_EXTLEN(msg) \ PFKEY_UNUNIT64(((struct sadb_ext *)(msg))->sadb_ext_len) #define PFKEY_ADDR_PREFIX(ext) \ (((struct sadb_address *)(ext))->sadb_address_prefixlen) #define PFKEY_ADDR_PROTO(ext) \ (((struct sadb_address *)(ext))->sadb_address_proto) #define PFKEY_ADDR_SADDR(ext) \ ((struct sockaddr *)((caddr_t)(ext) + sizeof(struct sadb_address))) /* in 64bits */ #define PFKEY_UNUNIT64(a) ((a) << 3) #define PFKEY_UNIT64(a) ((a) >> 3) #endif /* __PFKEY_V2_H */ #endif /* _NET_PFKEYV2_H_ */ libreswan-4.14/include/pfkeyv2/freebsd.h000066400000000000000000000350561457372064200202470ustar00rootroot00000000000000/* $FreeBSD$ */ /* $KAME: pfkeyv2.h,v 1.37 2003/09/06 05:15:43 itojun Exp $ */ /*- * SPDX-License-Identifier: BSD-3-Clause * * 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. */ /* * This file has been derived rfc 2367, * And added some flags of SADB_KEY_FLAGS_ as SADB_X_EXT_. * sakane@ydc.co.jp */ #ifndef _NET_PFKEYV2_H_ #define _NET_PFKEYV2_H_ /* 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 #define PF_KEY_V2 2 #define PFKEYV2_REVISION 199806L #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 /* by policy index */ #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 /* by policy id */ #define SADB_MAX 22 struct sadb_msg { u_int8_t sadb_msg_version; u_int8_t sadb_msg_type; u_int8_t sadb_msg_errno; u_int8_t sadb_msg_satype; u_int16_t sadb_msg_len; u_int16_t sadb_msg_reserved; u_int32_t sadb_msg_seq; u_int32_t sadb_msg_pid; }; struct sadb_ext { u_int16_t sadb_ext_len; u_int16_t sadb_ext_type; }; struct sadb_sa { u_int16_t sadb_sa_len; u_int16_t sadb_sa_exttype; u_int32_t sadb_sa_spi; u_int8_t sadb_sa_replay; u_int8_t sadb_sa_state; u_int8_t sadb_sa_auth; u_int8_t sadb_sa_encrypt; u_int32_t sadb_sa_flags; }; struct sadb_lifetime { u_int16_t sadb_lifetime_len; u_int16_t sadb_lifetime_exttype; u_int32_t sadb_lifetime_allocations; u_int64_t sadb_lifetime_bytes; u_int64_t sadb_lifetime_addtime; u_int64_t sadb_lifetime_usetime; }; struct sadb_address { u_int16_t sadb_address_len; u_int16_t sadb_address_exttype; u_int8_t sadb_address_proto; u_int8_t sadb_address_prefixlen; u_int16_t sadb_address_reserved; }; struct sadb_key { u_int16_t sadb_key_len; u_int16_t sadb_key_exttype; u_int16_t sadb_key_bits; u_int16_t sadb_key_reserved; }; struct sadb_ident { u_int16_t sadb_ident_len; u_int16_t sadb_ident_exttype; u_int16_t sadb_ident_type; u_int16_t sadb_ident_reserved; u_int64_t sadb_ident_id; }; struct sadb_sens { u_int16_t sadb_sens_len; u_int16_t sadb_sens_exttype; u_int32_t sadb_sens_dpd; u_int8_t sadb_sens_sens_level; u_int8_t sadb_sens_sens_len; u_int8_t sadb_sens_integ_level; u_int8_t sadb_sens_integ_len; u_int32_t sadb_sens_reserved; }; struct sadb_prop { u_int16_t sadb_prop_len; u_int16_t sadb_prop_exttype; u_int8_t sadb_prop_replay; u_int8_t sadb_prop_reserved[3]; }; struct sadb_comb { u_int8_t sadb_comb_auth; u_int8_t sadb_comb_encrypt; u_int16_t sadb_comb_flags; u_int16_t sadb_comb_auth_minbits; u_int16_t sadb_comb_auth_maxbits; u_int16_t sadb_comb_encrypt_minbits; u_int16_t sadb_comb_encrypt_maxbits; u_int32_t sadb_comb_reserved; u_int32_t sadb_comb_soft_allocations; u_int32_t sadb_comb_hard_allocations; u_int64_t sadb_comb_soft_bytes; u_int64_t sadb_comb_hard_bytes; u_int64_t sadb_comb_soft_addtime; u_int64_t sadb_comb_hard_addtime; u_int64_t sadb_comb_soft_usetime; u_int64_t sadb_comb_hard_usetime; }; struct sadb_supported { u_int16_t sadb_supported_len; u_int16_t sadb_supported_exttype; u_int32_t sadb_supported_reserved; }; struct sadb_alg { u_int8_t sadb_alg_id; u_int8_t sadb_alg_ivlen; u_int16_t sadb_alg_minbits; u_int16_t sadb_alg_maxbits; u_int16_t sadb_alg_reserved; }; struct sadb_spirange { u_int16_t sadb_spirange_len; u_int16_t sadb_spirange_exttype; u_int32_t sadb_spirange_min; u_int32_t sadb_spirange_max; u_int32_t sadb_spirange_reserved; }; struct sadb_x_kmprivate { u_int16_t sadb_x_kmprivate_len; u_int16_t sadb_x_kmprivate_exttype; u_int32_t sadb_x_kmprivate_reserved; }; /* * XXX Additional SA Extension. * mode: tunnel or transport * reqid: to make SA unique nevertheless the address pair of SA are same. * Mainly it's for VPN. */ struct sadb_x_sa2 { u_int16_t sadb_x_sa2_len; u_int16_t sadb_x_sa2_exttype; u_int8_t sadb_x_sa2_mode; u_int8_t sadb_x_sa2_reserved1; u_int16_t sadb_x_sa2_reserved2; u_int32_t sadb_x_sa2_sequence; /* lowermost 32bit of sequence number */ u_int32_t sadb_x_sa2_reqid; }; /* XXX Policy Extension */ struct sadb_x_policy { u_int16_t sadb_x_policy_len; u_int16_t sadb_x_policy_exttype; u_int16_t sadb_x_policy_type; /* See policy type of ipsec.h */ u_int8_t sadb_x_policy_dir; /* direction, see ipsec.h */ u_int8_t sadb_x_policy_scope; /* scope, see ipsec.h */ u_int32_t sadb_x_policy_id; u_int32_t sadb_x_policy_priority; #define sadb_x_policy_reserved sadb_x_policy_scope /* Policy with ifnet scope uses priority field to store ifindex */ #define sadb_x_policy_ifindex sadb_x_policy_priority }; _Static_assert(sizeof(struct sadb_x_policy) == 16, "struct size mismatch"); /* * When policy_type == IPSEC, it is followed by some of * the ipsec policy request. * [total length of ipsec policy requests] * = (sadb_x_policy_len * sizeof(uint64_t) - sizeof(struct sadb_x_policy)) */ /* XXX IPsec Policy Request Extension */ /* * This structure is aligned 8 bytes. */ struct sadb_x_ipsecrequest { u_int16_t sadb_x_ipsecrequest_len; /* structure length in 64 bits. */ u_int16_t sadb_x_ipsecrequest_proto; /* See ipsec.h */ u_int8_t sadb_x_ipsecrequest_mode; /* See IPSEC_MODE_XX in ipsec.h. */ u_int8_t sadb_x_ipsecrequest_level; /* See IPSEC_LEVEL_XX in ipsec.h */ u_int16_t sadb_x_ipsecrequest_reqid; /* See ipsec.h */ /* * followed by source IP address of SA, and immediately followed by * destination IP address of SA. These encoded into two of sockaddr * structure without any padding. Must set each sa_len exactly. * Each of length of the sockaddr structure are not aligned to 64bits, * but sum of x_request and addresses is aligned to 64bits. */ }; /* NAT-Traversal type, see RFC 3948 (and drafts). */ struct sadb_x_nat_t_type { u_int16_t sadb_x_nat_t_type_len; u_int16_t sadb_x_nat_t_type_exttype; u_int8_t sadb_x_nat_t_type_type; u_int8_t sadb_x_nat_t_type_reserved[3]; }; _Static_assert(sizeof(struct sadb_x_nat_t_type) == 8, "struct size mismatch"); /* NAT-Traversal source or destination port. */ struct sadb_x_nat_t_port { u_int16_t sadb_x_nat_t_port_len; u_int16_t sadb_x_nat_t_port_exttype; u_int16_t sadb_x_nat_t_port_port; u_int16_t sadb_x_nat_t_port_reserved; }; _Static_assert(sizeof(struct sadb_x_nat_t_port) == 8, "struct size mismatch"); /* ESP fragmentation size. */ struct sadb_x_nat_t_frag { u_int16_t sadb_x_nat_t_frag_len; u_int16_t sadb_x_nat_t_frag_exttype; u_int16_t sadb_x_nat_t_frag_fraglen; u_int16_t sadb_x_nat_t_frag_reserved; }; _Static_assert(sizeof(struct sadb_x_nat_t_frag) == 8, "struct size mismatch"); /* Additional large replay window support */ struct sadb_x_sa_replay { u_int16_t sadb_x_sa_replay_len; u_int16_t sadb_x_sa_replay_exttype; u_int32_t sadb_x_sa_replay_replay; /* in packets */ }; _Static_assert(sizeof(struct sadb_x_sa_replay) == 8, "struct size mismatch"); #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 #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 /* Deprecated. */ #define SADB_X_EXT_NAT_T_OAI 23 /* Peer's NAT_OA for src of SA. */ #define SADB_X_EXT_NAT_T_OAR 24 /* Peer's NAT_OA for dst of SA. */ #define SADB_X_EXT_NAT_T_FRAG 25 /* Manual MTU override. */ #define SADB_X_EXT_SA_REPLAY 26 /* Replay window override. */ #define SADB_X_EXT_NEW_ADDRESS_SRC 27 #define SADB_X_EXT_NEW_ADDRESS_DST 28 #define SADB_EXT_MAX 28 #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_X_SATYPE_POLICY 10 obsolete, do not reuse */ #define SADB_X_SATYPE_TCPSIGNATURE 11 #define SADB_SATYPE_MAX 12 #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 #define SADB_SAFLAGS_PFS 1 /* SADB_X_SAFLAGS_ESN was defined in sys/net/pfkeyv2.h in OpenBSD sources */ #define SADB_X_SAFLAGS_ESN 0x400 /* * Though some of these numbers (both _AALG and _EALG) appear to be * IKEv2 numbers and others original IKE numbers, they have no meaning. * These are constants that the various IKE daemons use to tell the kernel * what cipher to use. * * Do not use these constants directly to decide which Transformation ID * to send. You are responsible for mapping them yourself. */ #define SADB_AALG_NONE 0 #define SADB_AALG_MD5HMAC 2 #define SADB_AALG_SHA1HMAC 3 #define SADB_AALG_MAX 252 #define SADB_X_AALG_SHA2_256 5 #define SADB_X_AALG_SHA2_384 6 #define SADB_X_AALG_SHA2_512 7 #define SADB_X_AALG_RIPEMD160HMAC 8 #define SADB_X_AALG_AES_XCBC_MAC 9 /* RFC3566 */ #define SADB_X_AALG_AES128GMAC 11 /* RFC4543 + Errata1821 */ #define SADB_X_AALG_AES192GMAC 12 #define SADB_X_AALG_AES256GMAC 13 #define SADB_X_AALG_MD5 249 /* Keyed MD5 */ #define SADB_X_AALG_SHA 250 /* Keyed SHA */ #define SADB_X_AALG_NULL 251 /* null authentication */ #define SADB_X_AALG_TCP_MD5 252 /* Keyed TCP-MD5 (RFC2385) */ #define SADB_EALG_NONE 0 #define SADB_EALG_DESCBC 2 #define SADB_EALG_3DESCBC 3 #define SADB_X_EALG_CAST128CBC 6 #define SADB_X_EALG_BLOWFISHCBC 7 #define SADB_EALG_NULL 11 #define SADB_X_EALG_RIJNDAELCBC 12 #define SADB_X_EALG_AES 12 #define SADB_X_EALG_AESCBC 12 #define SADB_X_EALG_AESCTR 13 #define SADB_X_EALG_AESGCM8 18 /* RFC4106 */ #define SADB_X_EALG_AESGCM12 19 #define SADB_X_EALG_AESGCM16 20 #define SADB_X_EALG_CAMELLIACBC 22 #define SADB_X_EALG_AESGMAC 23 /* RFC4543 + Errata1821 */ #define SADB_EALG_MAX 23 /* !!! keep updated !!! */ /* private allocations - based on RFC2407/IANA assignment */ #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_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_ADDR 4 #define SADB_IDENTTYPE_MAX 4 /* `flags' in sadb_sa structure holds followings */ #define SADB_X_EXT_NONE 0x0000 /* i.e. new format. */ #define SADB_X_EXT_OLD 0x0001 /* old format. */ #define SADB_X_EXT_IV4B 0x0010 /* IV length of 4 bytes in use */ #define SADB_X_EXT_DERIV 0x0020 /* DES derived */ #define SADB_X_EXT_CYCSEQ 0x0040 /* allowing to cyclic sequence. */ /* three of followings are exclusive flags each them */ #define SADB_X_EXT_PSEQ 0x0000 /* sequencial padding for ESP */ #define SADB_X_EXT_PRAND 0x0100 /* random padding for ESP */ #define SADB_X_EXT_PZERO 0x0200 /* zero padding for ESP */ #define SADB_X_EXT_PMASK 0x0300 /* mask for padding flag */ #if 1 #define SADB_X_EXT_RAWCPI 0x0080 /* use well known CPI (IPComp) */ #endif #define SADB_KEY_FLAGS_MAX 0x0fff /* SPI size for PF_KEYv2 */ #define PFKEY_SPI_SIZE sizeof(u_int32_t) /* Identifier for menber of lifetime structure */ #define SADB_X_LIFETIME_ALLOCATIONS 0 #define SADB_X_LIFETIME_BYTES 1 #define SADB_X_LIFETIME_ADDTIME 2 #define SADB_X_LIFETIME_USETIME 3 /* The rate for SOFT lifetime against HARD one. */ #define PFKEY_SOFT_LIFETIME_RATE 80 /* Utilities */ #define PFKEY_ALIGN8(a) (1 + (((a) - 1) | (8 - 1))) #define PFKEY_EXTLEN(msg) \ PFKEY_UNUNIT64(((struct sadb_ext *)(msg))->sadb_ext_len) #define PFKEY_ADDR_PREFIX(ext) \ (((struct sadb_address *)(ext))->sadb_address_prefixlen) #define PFKEY_ADDR_PROTO(ext) \ (((struct sadb_address *)(ext))->sadb_address_proto) #define PFKEY_ADDR_SADDR(ext) \ ((struct sockaddr *)((caddr_t)(ext) + sizeof(struct sadb_address))) /* in 64bits */ #define PFKEY_UNUNIT64(a) ((a) << 3) #define PFKEY_UNIT64(a) ((a) >> 3) #endif /* __PFKEY_V2_H */ #endif /* _NET_PFKEYV2_H_ */ libreswan-4.14/include/pfkeyv2/linux.h000066400000000000000000000245111457372064200177660ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* 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 { __u8 sadb_msg_version; __u8 sadb_msg_type; __u8 sadb_msg_errno; __u8 sadb_msg_satype; __u16 sadb_msg_len; __u16 sadb_msg_reserved; __u32 sadb_msg_seq; __u32 sadb_msg_pid; } __attribute__((packed)); /* sizeof(struct sadb_msg) == 16 */ struct sadb_ext { __u16 sadb_ext_len; __u16 sadb_ext_type; } __attribute__((packed)); /* sizeof(struct sadb_ext) == 4 */ struct sadb_sa { __u16 sadb_sa_len; __u16 sadb_sa_exttype; __be32 sadb_sa_spi; __u8 sadb_sa_replay; __u8 sadb_sa_state; __u8 sadb_sa_auth; __u8 sadb_sa_encrypt; __u32 sadb_sa_flags; } __attribute__((packed)); /* sizeof(struct sadb_sa) == 16 */ struct sadb_lifetime { __u16 sadb_lifetime_len; __u16 sadb_lifetime_exttype; __u32 sadb_lifetime_allocations; __u64 sadb_lifetime_bytes; __u64 sadb_lifetime_addtime; __u64 sadb_lifetime_usetime; } __attribute__((packed)); /* sizeof(struct sadb_lifetime) == 32 */ struct sadb_address { __u16 sadb_address_len; __u16 sadb_address_exttype; __u8 sadb_address_proto; __u8 sadb_address_prefixlen; __u16 sadb_address_reserved; } __attribute__((packed)); /* sizeof(struct sadb_address) == 8 */ struct sadb_key { __u16 sadb_key_len; __u16 sadb_key_exttype; __u16 sadb_key_bits; __u16 sadb_key_reserved; } __attribute__((packed)); /* sizeof(struct sadb_key) == 8 */ struct sadb_ident { __u16 sadb_ident_len; __u16 sadb_ident_exttype; __u16 sadb_ident_type; __u16 sadb_ident_reserved; __u64 sadb_ident_id; } __attribute__((packed)); /* sizeof(struct sadb_ident) == 16 */ struct sadb_sens { __u16 sadb_sens_len; __u16 sadb_sens_exttype; __u32 sadb_sens_dpd; __u8 sadb_sens_sens_level; __u8 sadb_sens_sens_len; __u8 sadb_sens_integ_level; __u8 sadb_sens_integ_len; __u32 sadb_sens_reserved; } __attribute__((packed)); /* sizeof(struct sadb_sens) == 16 */ /* followed by: __u64 sadb_sens_bitmap[sens_len]; __u64 sadb_integ_bitmap[integ_len]; */ struct sadb_prop { __u16 sadb_prop_len; __u16 sadb_prop_exttype; __u8 sadb_prop_replay; __u8 sadb_prop_reserved[3]; } __attribute__((packed)); /* sizeof(struct sadb_prop) == 8 */ /* followed by: struct sadb_comb sadb_combs[(sadb_prop_len + sizeof(__u64) - sizeof(struct sadb_prop)) / sizeof(struct sadb_comb)]; */ struct sadb_comb { __u8 sadb_comb_auth; __u8 sadb_comb_encrypt; __u16 sadb_comb_flags; __u16 sadb_comb_auth_minbits; __u16 sadb_comb_auth_maxbits; __u16 sadb_comb_encrypt_minbits; __u16 sadb_comb_encrypt_maxbits; __u32 sadb_comb_reserved; __u32 sadb_comb_soft_allocations; __u32 sadb_comb_hard_allocations; __u64 sadb_comb_soft_bytes; __u64 sadb_comb_hard_bytes; __u64 sadb_comb_soft_addtime; __u64 sadb_comb_hard_addtime; __u64 sadb_comb_soft_usetime; __u64 sadb_comb_hard_usetime; } __attribute__((packed)); /* sizeof(struct sadb_comb) == 72 */ struct sadb_supported { __u16 sadb_supported_len; __u16 sadb_supported_exttype; __u32 sadb_supported_reserved; } __attribute__((packed)); /* sizeof(struct sadb_supported) == 8 */ /* followed by: struct sadb_alg sadb_algs[(sadb_supported_len + sizeof(__u64) - sizeof(struct sadb_supported)) / sizeof(struct sadb_alg)]; */ struct sadb_alg { __u8 sadb_alg_id; __u8 sadb_alg_ivlen; __u16 sadb_alg_minbits; __u16 sadb_alg_maxbits; __u16 sadb_alg_reserved; } __attribute__((packed)); /* sizeof(struct sadb_alg) == 8 */ struct sadb_spirange { __u16 sadb_spirange_len; __u16 sadb_spirange_exttype; __u32 sadb_spirange_min; __u32 sadb_spirange_max; __u32 sadb_spirange_reserved; } __attribute__((packed)); /* sizeof(struct sadb_spirange) == 16 */ struct sadb_x_kmprivate { __u16 sadb_x_kmprivate_len; __u16 sadb_x_kmprivate_exttype; __u32 sadb_x_kmprivate_reserved; } __attribute__((packed)); /* sizeof(struct sadb_x_kmprivate) == 8 */ struct sadb_x_sa2 { __u16 sadb_x_sa2_len; __u16 sadb_x_sa2_exttype; __u8 sadb_x_sa2_mode; __u8 sadb_x_sa2_reserved1; __u16 sadb_x_sa2_reserved2; __u32 sadb_x_sa2_sequence; __u32 sadb_x_sa2_reqid; } __attribute__((packed)); /* sizeof(struct sadb_x_sa2) == 16 */ struct sadb_x_policy { __u16 sadb_x_policy_len; __u16 sadb_x_policy_exttype; __u16 sadb_x_policy_type; __u8 sadb_x_policy_dir; __u8 sadb_x_policy_reserved; __u32 sadb_x_policy_id; __u32 sadb_x_policy_priority; } __attribute__((packed)); /* sizeof(struct sadb_x_policy) == 16 */ struct sadb_x_ipsecrequest { __u16 sadb_x_ipsecrequest_len; __u16 sadb_x_ipsecrequest_proto; __u8 sadb_x_ipsecrequest_mode; __u8 sadb_x_ipsecrequest_level; __u16 sadb_x_ipsecrequest_reserved1; __u32 sadb_x_ipsecrequest_reqid; __u32 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 { __u16 sadb_x_nat_t_type_len; __u16 sadb_x_nat_t_type_exttype; __u8 sadb_x_nat_t_type_type; __u8 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 { __u16 sadb_x_nat_t_port_len; __u16 sadb_x_nat_t_port_exttype; __be16 sadb_x_nat_t_port_port; __u16 sadb_x_nat_t_port_reserved; } __attribute__((packed)); /* sizeof(struct sadb_x_nat_t_port) == 8 */ /* Generic LSM security context */ struct sadb_x_sec_ctx { __u16 sadb_x_sec_len; __u16 sadb_x_sec_exttype; __u8 sadb_x_ctx_alg; /* LSMs: e.g., selinux == 1 */ __u8 sadb_x_ctx_doi; __u16 sadb_x_ctx_len; } __attribute__((packed)); /* sizeof(struct sadb_sec_ctx) = 8 */ /* Used by MIGRATE to pass addresses IKE will use to perform * negotiation with the peer */ struct sadb_x_kmaddress { __u16 sadb_x_kmaddress_len; __u16 sadb_x_kmaddress_exttype; __u32 sadb_x_kmaddress_reserved; } __attribute__((packed)); /* sizeof(struct sadb_x_kmaddress) == 8 */ /* To specify the SA dump filter */ struct sadb_x_filter { __u16 sadb_x_filter_len; __u16 sadb_x_filter_exttype; __u32 sadb_x_filter_saddr[4]; __u32 sadb_x_filter_daddr[4]; __u16 sadb_x_filter_family; __u8 sadb_x_filter_splen; __u8 sadb_x_filter_dplen; } __attribute__((packed)); /* sizeof(struct sadb_x_filter) == 40 */ /* 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_X_MIGRATE 24 #define SADB_MAX 24 /* Security Association flags */ #define SADB_SAFLAGS_PFS 1 #define SADB_SAFLAGS_NOPMTUDISC 0x20000000 #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_NULL 251 /* kame */ #define SADB_AALG_MAX 251 /* Encryption algorithms */ #define SADB_EALG_NONE 0 #define SADB_EALG_DESCBC 2 #define SADB_EALG_3DESCBC 3 #define SADB_X_EALG_CASTCBC 6 #define SADB_X_EALG_BLOWFISHCBC 7 #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_CAMELLIACBC 22 #define SADB_X_EALG_NULL_AES_GMAC 23 #define SADB_EALG_MAX 253 /* last EALG */ /* private allocations should use 249-255 (RFC2407) */ #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_X_EXT_SEC_CTX 24 /* Used with MIGRATE to pass @ to IKE for negotiation */ #define SADB_X_EXT_KMADDRESS 25 #define SADB_X_EXT_FILTER 26 #define SADB_EXT_MAX 26 /* 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-4.14/include/pfkeyv2/netbsd.h000066400000000000000000000404171457372064200201110ustar00rootroot00000000000000/* $NetBSD: pfkeyv2.h,v 1.32 2017/07/04 08:11:32 ozaki-r Exp $ */ /* $KAME: pfkeyv2.h,v 1.36 2003/07/25 09:33:37 itojun 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. */ /* * This file has been derived rfc 2367, * And added some flags of SADB_KEY_FLAGS_ as SADB_X_EXT_. * sakane@ydc.co.jp */ #ifndef _NET_PFKEYV2_H_ #define _NET_PFKEYV2_H_ /* 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 #define PF_KEY_V2 2 #define PFKEYV2_REVISION 199806L #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 /* by policy index */ #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 /* not yet */ #define SADB_X_SPDDELETE2 22 /* by policy id */ #define SADB_X_NAT_T_NEW_MAPPING 23 #if 0 #define SADB_X_MIGRATE 24 /* KAME */ #endif #define SADB_MAX 23 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; }; struct sadb_ext { uint16_t sadb_ext_len; uint16_t sadb_ext_type; }; 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; }; 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; }; 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; }; struct sadb_key { uint16_t sadb_key_len; uint16_t sadb_key_exttype; uint16_t sadb_key_bits; uint16_t sadb_key_reserved; }; 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; }; 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; }; struct sadb_prop { uint16_t sadb_prop_len; uint16_t sadb_prop_exttype; uint8_t sadb_prop_replay; uint8_t sadb_prop_reserved[3]; }; 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; }; struct sadb_supported { uint16_t sadb_supported_len; uint16_t sadb_supported_exttype; uint32_t sadb_supported_reserved; }; 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; }; 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; }; struct sadb_x_kmprivate { uint16_t sadb_x_kmprivate_len; uint16_t sadb_x_kmprivate_exttype; uint32_t sadb_x_kmprivate_reserved; }; /* * XXX Additional SA Extension. * mode: tunnel or transport * reqid: to make SA unique nevertheless the address pair of SA are same. * Mainly it's for VPN. */ 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; /* topmost 16bits are always 0 */ }; /* XXX Policy Extension */ /* sizeof(struct sadb_x_policy) == 16 */ struct sadb_x_policy { uint16_t sadb_x_policy_len; uint16_t sadb_x_policy_exttype; uint16_t sadb_x_policy_type; /* See policy type of ipsec.h */ uint8_t sadb_x_policy_dir; /* direction, see ipsec.h */ uint8_t sadb_x_policy_reserved; uint32_t sadb_x_policy_id; uint32_t sadb_x_policy_reserved2; }; /* * When policy_type == IPSEC, it is followed by some of * the ipsec policy request. * [total length of ipsec policy requests] * = (sadb_x_policy_len * sizeof(uint64_t) - sizeof(struct sadb_x_policy)) */ /* XXX IPsec Policy Request Extension */ /* * This structure is aligned 8 bytes. */ struct sadb_x_ipsecrequest { uint16_t sadb_x_ipsecrequest_len; /* structure length in 64 bits. */ uint16_t sadb_x_ipsecrequest_proto; /* See ipsec.h */ uint8_t sadb_x_ipsecrequest_mode; /* See IPSEC_MODE_XX in ipsec.h. */ uint8_t sadb_x_ipsecrequest_level; /* See IPSEC_LEVEL_XX in ipsec.h */ uint16_t sadb_x_ipsecrequest_reqid; /* See ipsec.h */ /* * followed by source IP address of SA, and immediately followed by * destination IP address of SA. These encoded into two of sockaddr * structure without any padding. Must set each sa_len exactly. * Each of length of the sockaddr structure are not aligned to 64bits, * but sum of x_request and addresses is aligned to 64bits. */ }; /* NAT traversal type, see draft-ietf-ipsec-udp-encaps-06 */ /* sizeof(struct sadb_x_nat_t_type) == 8 */ 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]; }; /* NAT traversal source or destination port */ /* sizeof(struct sadb_x_nat_t_port) == 8 */ 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; }; /* ESP fragmentation size */ /* sizeof(struct sadb_x_nat_t_frag) == 8 */ struct sadb_x_nat_t_frag { uint16_t sadb_x_nat_t_frag_len; uint16_t sadb_x_nat_t_frag_exttype; uint16_t sadb_x_nat_t_frag_fraglen; uint16_t sadb_x_nat_t_frag_reserved; }; #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 #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 /* compat */ #define SADB_X_EXT_NAT_T_OAI 23 #define SADB_X_EXT_NAT_T_OAR 24 #define SADB_X_EXT_NAT_T_FRAG 25 #if 0 #define SADB_X_EXT_TAG 25 /* KAME */ #define SADB_X_EXT_SA3 26 /* KAME */ #define SADB_X_EXT_PACKET 27 /* KAME */ #endif #define SADB_EXT_MAX 25 #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_X_SATYPE_POLICY 10 obsolete, do not reuse */ #define SADB_X_SATYPE_TCPSIGNATURE 11 #define SADB_SATYPE_MAX 12 #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 #define SADB_SASTATE_USABLE_P(sav) \ ((sav)->state == SADB_SASTATE_MATURE || (sav)->state == SADB_SASTATE_DYING) #define SADB_SAFLAGS_PFS 1 /* * Statistics variable definitions. For ESP/AH/IPCOMP we define * indirection arrays of 256 elements indexed by algorithm (which * is uint8_t. All unknown/unhandled entries are summed in the 0th * element. We provide three variables per protocol: * 1. *_STATS_INIT: a list of initializers * 2. *_STATS_NUM: number of algorithms/statistics including (0/unknown) * 3. *_STATS_STR: a list of strings to symbolically print the statistics */ /* RFC2367 numbers - meets RFC2407 */ #define SADB_AALG_NONE 0 #define SADB_AALG_MD5HMAC 2 #define SADB_AALG_SHA1HMAC 3 #define SADB_AALG_MAX 251 /* private allocations - based on RFC2407/IANA assignment */ #define SADB_X_AALG_SHA2_256 5 #define SADB_X_AALG_SHA2_384 6 #define SADB_X_AALG_SHA2_512 7 #define SADB_X_AALG_RIPEMD160HMAC 8 #define SADB_X_AALG_AES_XCBC_MAC 9 /* RFC3566 */ #define SADB_X_AALG_AES128GMAC 11 /* RFC4543 + Errata1821 */ #define SADB_X_AALG_AES192GMAC 12 #define SADB_X_AALG_AES256GMAC 13 /* private allocations should use 249-255 (RFC2407) */ #define SADB_X_AALG_MD5 249 /* Keyed MD5 */ #define SADB_X_AALG_SHA 250 /* Keyed SHA */ #define SADB_X_AALG_NULL 251 /* null authentication */ #define SADB_X_AALG_TCP_MD5 252 /* Keyed TCP-MD5 (RFC2385) */ #define SADB_AALG_STATS_INIT \ [SADB_AALG_NONE] = 1, \ [SADB_AALG_MD5HMAC] = 2, \ [SADB_AALG_SHA1HMAC] = 3, \ [SADB_X_AALG_SHA2_256] = 4, \ [SADB_X_AALG_SHA2_384] = 5, \ [SADB_X_AALG_SHA2_512] = 6, \ [SADB_X_AALG_RIPEMD160HMAC] = 7, \ [SADB_X_AALG_AES_XCBC_MAC] = 8, \ [SADB_X_AALG_AES128GMAC] = 9, \ [SADB_X_AALG_AES192GMAC] = 10, \ [SADB_X_AALG_AES256GMAC] = 11, \ [SADB_X_AALG_MD5] = 12, \ [SADB_X_AALG_SHA] = 13, \ [SADB_X_AALG_NULL] = 14, \ [SADB_X_AALG_TCP_MD5] = 15, #define SADB_AALG_STATS_NUM 16 #define SADB_AALG_STATS_STR \ "*unknown*", \ "none", \ "hmac-md5", \ "hmac-sha1", \ "hmac-sha2-256", \ "hmac-sha2-384", \ "hmac-sha2-512", \ "hmac-ripe-md160", \ "aes-xbc-mac", \ "aes-128-mac", \ "aes-192-mac", \ "aes-256-mac", \ "md5", \ "sha", \ "null", \ "tcp-md5", /* RFC2367 numbers - meets RFC2407 */ #define SADB_EALG_NONE 0 #define SADB_EALG_DESCBC 2 #define SADB_EALG_3DESCBC 3 #define SADB_EALG_NULL 11 #define SADB_EALG_MAX 250 /* private allocations - based on RFC2407/IANA assignment */ #define SADB_X_EALG_CAST128CBC 6 #define SADB_X_EALG_BLOWFISHCBC 7 #define SADB_X_EALG_RIJNDAELCBC 12 #define SADB_X_EALG_AES 12 #define SADB_X_EALG_AESCTR 13 /* RFC3686 */ #define SADB_X_EALG_AESGCM8 18 /* RFC4106 */ #define SADB_X_EALG_AESGCM12 19 #define SADB_X_EALG_AESGCM16 20 #define SADB_X_EALG_CAMELLIACBC 22 /* RFC4312 */ #define SADB_X_EALG_AESGMAC 23 /* RFC4543 + Errata1821 */ /* private allocations should use 249-255 (RFC2407) */ #define SADB_X_EALG_SKIPJACK 250 #define SADB_EALG_STATS_INIT \ [SADB_EALG_NONE] = 1, \ [SADB_EALG_DESCBC] = 2, \ [SADB_EALG_3DESCBC] = 3, \ [SADB_EALG_NULL] = 4, \ [SADB_X_EALG_CAST128CBC] = 5, \ [SADB_X_EALG_BLOWFISHCBC] = 6, \ [SADB_X_EALG_RIJNDAELCBC] = 7, \ [SADB_X_EALG_AESCTR] = 8, \ [SADB_X_EALG_AESGCM8] = 9, \ [SADB_X_EALG_AESGCM12] = 10, \ [SADB_X_EALG_AESGCM16] = 11, \ [SADB_X_EALG_CAMELLIACBC] = 12, \ [SADB_X_EALG_AESGMAC] = 13, \ [SADB_X_EALG_SKIPJACK] = 14, #define SADB_EALG_STATS_NUM 15 #define SADB_EALG_STATS_STR \ "*unknown*", \ "none", \ "des-cbc", \ "3des-cbc", \ "null", \ "cast128-cbc", \ "blowfish-cbc", \ "aes-cbc", \ "aes-ctr", \ "aes-gcm-8", \ "aes-gcm-12", \ "aes-gcm-16", \ "camelia-cbc", \ "aes-gmac", \ "skipjack", /* private allocations - based on RFC2407/IANA assignment */ #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_MAX 4 #define SADB_CALG_STATS_INIT \ [SADB_X_CALG_NONE] = 1, \ [SADB_X_CALG_OUI] = 2, \ [SADB_X_CALG_DEFLATE] = 3, \ [SADB_X_CALG_LZS] = 4, #define SADB_CALG_STATS_NUM 5 #define SADB_CALG_STATS_STR \ "*unknown*", \ "none", \ "oui", \ "deflate", \ "lzs", #define SADB_IDENTTYPE_RESERVED 0 #define SADB_IDENTTYPE_PREFIX 1 #define SADB_IDENTTYPE_FQDN 2 #define SADB_IDENTTYPE_USERFQDN 3 #define SADB_X_IDENTTYPE_ADDR 4 #define SADB_IDENTTYPE_MAX 4 /* `flags' in sadb_sa structure holds followings */ #define SADB_X_EXT_NONE 0x0000 /* i.e. new format. */ #define SADB_X_EXT_OLD 0x0001 /* old format. */ #define SADB_X_EXT_IV4B 0x0010 /* IV length of 4 bytes in use */ #define SADB_X_EXT_DERIV 0x0020 /* DES derived */ #define SADB_X_EXT_CYCSEQ 0x0040 /* allowing to cyclic sequence. */ /* three of followings are exclusive flags each them */ #define SADB_X_EXT_PSEQ 0x0000 /* sequencial padding for ESP */ #define SADB_X_EXT_PRAND 0x0100 /* random padding for ESP */ #define SADB_X_EXT_PZERO 0x0200 /* zero padding for ESP */ #define SADB_X_EXT_PMASK 0x0300 /* mask for padding flag */ #if 1 #define SADB_X_EXT_RAWCPI 0x0080 /* use well known CPI (IPComp) */ #endif #define SADB_KEY_FLAGS_MAX 0x0fff /* SPI size for PF_KEYv2 */ #define PFKEY_SPI_SIZE sizeof(uint32_t) /* Identifier for menber of lifetime structure */ #define SADB_X_LIFETIME_ALLOCATIONS 0 #define SADB_X_LIFETIME_BYTES 1 #define SADB_X_LIFETIME_ADDTIME 2 #define SADB_X_LIFETIME_USETIME 3 /* The rate for SOFT lifetime against HARD one. */ #define PFKEY_SOFT_LIFETIME_RATE 80 /* Utilities */ #define PFKEY_ALIGN8(a) (1 + (((a) - 1) | (8 - 1))) #define PFKEY_EXTLEN(msg) \ PFKEY_UNUNIT64(((const struct sadb_ext *)(const void *)(msg))->sadb_ext_len) #define PFKEY_ADDR_PREFIX(ext) \ (((const struct sadb_address *)(const void *)(ext))->sadb_address_prefixlen) #define PFKEY_ADDR_PROTO(ext) \ (((const struct sadb_address *)(const void *)(ext))->sadb_address_proto) #define PFKEY_ADDR_SADDR(ext) \ ((struct sockaddr *)(void *)((char *)(void *)(ext) + \ sizeof(struct sadb_address))) /* in 64bits */ #define PFKEY_UNUNIT64(a) ((a) << 3) #define PFKEY_UNIT64(a) ((a) >> 3) #endif /* __PFKEY_V2_H */ #endif /* !_NET_PFKEYV2_H_ */ libreswan-4.14/include/pfkeyv2/openbsd.h000066400000000000000000000353471457372064200202720ustar00rootroot00000000000000/* $OpenBSD: pfkeyv2.h,v 1.92 2022/03/02 09:27:34 claudio Exp $ */ /* * @(#)COPYRIGHT 1.1 (NRL) January 1998 * * NRL grants permission for redistribution and use in source and binary * forms, with or without modification, of the software and documentation * created at NRL 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 acknowledgements: * This product includes software developed by the University of * California, Berkeley and its contributors. * This product includes software developed at the Information * Technology Division, US Naval Research Laboratory. * 4. Neither the name of the NRL nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL 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 NRL 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 views and conclusions contained in the software and documentation * are those of the authors and should not be interpreted as representing * official policies, either expressed or implied, of the US Naval * Research Laboratory (NRL). */ #ifndef _NET_PFKEY_V2_H_ #define _NET_PFKEY_V2_H_ #define PF_KEY_V2 2 #define PFKEYV2_REVISION 199806L /* This should be updated whenever the API is altered. */ #define _OPENBSD_IPSEC_API_VERSION 2 #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_ADDFLOW 12 #define SADB_X_DELFLOW 13 #define SADB_X_GRPSPIS 14 #define SADB_X_ASKPOLICY 15 #define SADB_X_SPDDUMP 16 #define SADB_MAX 16 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; }; struct sadb_ext { uint16_t sadb_ext_len; uint16_t sadb_ext_type; }; 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; }; 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; }; struct sadb_address { uint16_t sadb_address_len; uint16_t sadb_address_exttype; uint32_t sadb_address_reserved; }; struct sadb_key { uint16_t sadb_key_len; uint16_t sadb_key_exttype; uint16_t sadb_key_bits; uint16_t sadb_key_reserved; }; 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; }; 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; }; struct sadb_prop { uint16_t sadb_prop_len; uint16_t sadb_prop_exttype; uint8_t sadb_prop_num; uint8_t sadb_prop_replay; uint16_t sadb_prop_reserved; }; 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; }; struct sadb_supported { uint16_t sadb_supported_len; uint16_t sadb_supported_exttype; uint32_t sadb_supported_reserved; }; 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; }; 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; }; 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; }; struct sadb_x_policy { uint16_t sadb_x_policy_len; uint16_t sadb_x_policy_exttype; uint32_t sadb_x_policy_seq; }; struct sadb_x_udpencap { uint16_t sadb_x_udpencap_len; uint16_t sadb_x_udpencap_exttype; uint16_t sadb_x_udpencap_port; uint16_t sadb_x_udpencap_reserved; }; struct sadb_x_tag { uint16_t sadb_x_tag_len; uint16_t sadb_x_tag_exttype; uint32_t sadb_x_tag_taglen; }; struct sadb_x_replay { uint16_t sadb_x_replay_len; uint16_t sadb_x_replay_exttype; uint32_t sadb_x_replay_reserved; uint64_t sadb_x_replay_count; }; struct sadb_x_rdomain { uint16_t sadb_x_rdomain_len; uint16_t sadb_x_rdomain_exttype; uint16_t sadb_x_rdomain_dom1; uint16_t sadb_x_rdomain_dom2; }; struct sadb_x_tap { uint16_t sadb_x_tap_len; uint16_t sadb_x_tap_exttype; uint32_t sadb_x_tap_unit; }; struct sadb_x_counter { uint16_t sadb_x_counter_len; uint16_t sadb_x_counter_exttype; uint32_t sadb_x_counter_pad; uint64_t sadb_x_counter_ipackets; /* Input IPsec packets */ uint64_t sadb_x_counter_opackets; /* Output IPsec packets */ uint64_t sadb_x_counter_ibytes; /* Input bytes */ uint64_t sadb_x_counter_obytes; /* Output bytes */ uint64_t sadb_x_counter_idrops; /* Dropped on input */ uint64_t sadb_x_counter_odrops; /* Dropped on output */ uint64_t sadb_x_counter_idecompbytes; /* Input bytes, decompressed */ uint64_t sadb_x_counter_ouncompbytes; /* Output bytes, uncompressed */ }; struct sadb_x_mtu { uint16_t sadb_x_mtu_len; uint16_t sadb_x_mtu_exttype; uint32_t sadb_x_mtu_mtu; }; #ifdef _KERNEL #define SADB_X_GETSPROTO(x) \ ( (x) == SADB_SATYPE_AH ? IPPROTO_AH :\ (x) == SADB_SATYPE_ESP ? IPPROTO_ESP :\ (x) == SADB_X_SATYPE_TCPSIGNATURE ? IPPROTO_TCP :\ (x) == SADB_X_SATYPE_IPCOMP ? IPPROTO_IPCOMP: IPPROTO_IPIP ) #endif #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_SRC_MASK 17 #define SADB_X_EXT_DST_MASK 18 #define SADB_X_EXT_PROTOCOL 19 #define SADB_X_EXT_FLOW_TYPE 20 #define SADB_X_EXT_SRC_FLOW 21 #define SADB_X_EXT_DST_FLOW 22 #define SADB_X_EXT_SA2 23 #define SADB_X_EXT_DST2 24 #define SADB_X_EXT_POLICY 25 #define SADB_X_EXT_LOCAL_CREDENTIALS 26 #define SADB_X_EXT_REMOTE_CREDENTIALS 27 #define SADB_X_EXT_LOCAL_AUTH 28 #define SADB_X_EXT_REMOTE_AUTH 29 #define SADB_X_EXT_SUPPORTED_COMP 30 #define SADB_X_EXT_UDPENCAP 31 #define SADB_X_EXT_LIFETIME_LASTUSE 32 #define SADB_X_EXT_TAG 33 #define SADB_X_EXT_TAP 34 #define SADB_X_EXT_SATYPE2 35 #define SADB_X_EXT_COUNTER 36 #define SADB_X_EXT_RDOMAIN 37 #define SADB_X_EXT_MTU 38 #define SADB_X_EXT_REPLAY 39 #define SADB_EXT_MAX 39 /* Fix pfkeyv2.c struct pfkeyv2_socket if SATYPE_MAX > 31 */ #define SADB_SATYPE_UNSPEC 0 #define SADB_SATYPE_AH 1 #define SADB_SATYPE_ESP 2 #define SADB_SATYPE_RSVP 3 #define SADB_SATYPE_OSPFV2 4 #define SADB_SATYPE_RIPV2 5 #define SADB_SATYPE_MIP 6 #define SADB_X_SATYPE_IPIP 7 #define SADB_X_SATYPE_TCPSIGNATURE 8 #define SADB_X_SATYPE_IPCOMP 9 #define SADB_SATYPE_MAX 9 #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 #define SADB_AALG_NONE 0 #define SADB_AALG_MD5HMAC 2 #define SADB_AALG_SHA1HMAC 3 #define SADB_X_AALG_SHA2_256 5 #define SADB_X_AALG_SHA2_384 6 #define SADB_X_AALG_SHA2_512 7 #define SADB_X_AALG_RIPEMD160HMAC 8 #define SADB_X_AALG_AES128GMAC 9 #define SADB_X_AALG_AES192GMAC 10 #define SADB_X_AALG_AES256GMAC 11 #define SADB_X_AALG_CHACHA20POLY1305 12 #define SADB_AALG_MAX 12 #define SADB_EALG_NONE 0 #define SADB_EALG_3DESCBC 3 #define SADB_X_EALG_CAST 6 #define SADB_X_EALG_BLF 7 #define SADB_EALG_NULL 11 #define SADB_X_EALG_AES 12 #define SADB_X_EALG_AESCTR 13 #define SADB_X_EALG_AESGCM8 18 #define SADB_X_EALG_AESGCM12 19 #define SADB_X_EALG_AESGCM16 20 #define SADB_X_EALG_AESGMAC 21 #define SADB_X_EALG_CHACHA20POLY1305 22 #define SADB_EALG_MAX 22 #define SADB_X_CALG_NONE 0 #define SADB_X_CALG_OUI 1 #define SADB_X_CALG_DEFLATE 2 #define SADB_X_CALG_MAX 2 #define SADB_SAFLAGS_PFS 0x001 /* perfect forward secrecy */ #define SADB_X_SAFLAGS_TUNNEL 0x004 /* Force tunneling */ #define SADB_X_SAFLAGS_CHAINDEL 0x008 /* Delete whole SA chain */ #define SADB_X_SAFLAGS_UDPENCAP 0x200 /* ESP in UDP */ #define SADB_X_SAFLAGS_ESN 0x400 /* Extended Sequence Number */ #define SADB_X_POLICYFLAGS_POLICY 0x0001 /* This is a static policy */ #define SADB_IDENTTYPE_RESERVED 0 #define SADB_IDENTTYPE_PREFIX 1 #define SADB_IDENTTYPE_FQDN 2 #define SADB_IDENTTYPE_USERFQDN 3 #define SADB_IDENTTYPE_ASN1_DN 4 #define SADB_IDENTTYPE_MAX 4 #define SADB_KEY_FLAGS_MAX 0 #ifdef _KERNEL #define PFKEYV2_LIFETIME_HARD 0 #define PFKEYV2_LIFETIME_SOFT 1 #define PFKEYV2_LIFETIME_CURRENT 2 #define PFKEYV2_LIFETIME_LASTUSE 3 #define PFKEYV2_IDENTITY_SRC 0 #define PFKEYV2_IDENTITY_DST 1 #define PFKEYV2_ENCRYPTION_KEY 0 #define PFKEYV2_AUTHENTICATION_KEY 1 #define PFKEYV2_SOCKETFLAGS_REGISTERED 1 #define PFKEYV2_SOCKETFLAGS_PROMISC 2 #define PFKEYV2_SENDMESSAGE_UNICAST 1 #define PFKEYV2_SENDMESSAGE_REGISTERED 2 #define PFKEYV2_SENDMESSAGE_BROADCAST 3 #endif /* _KERNEL */ #define SADB_X_FLOW_TYPE_USE 1 #define SADB_X_FLOW_TYPE_ACQUIRE 2 #define SADB_X_FLOW_TYPE_REQUIRE 3 #define SADB_X_FLOW_TYPE_BYPASS 4 #define SADB_X_FLOW_TYPE_DENY 5 #define SADB_X_FLOW_TYPE_DONTACQ 6 #ifdef _KERNEL struct tdb; struct socket; struct mbuf; #define EXTLEN(x) (((struct sadb_ext *)(x))->sadb_ext_len * sizeof(uint64_t)) #define PADUP(x) (((x) + sizeof(uint64_t) - 1) & ~(sizeof(uint64_t) - 1)) int pfkeyv2_parsemessage(void *, int, void **); int pfkeyv2_expire(struct tdb *, u_int16_t); int pfkeyv2_acquire(struct ipsec_policy *, union sockaddr_union *, union sockaddr_union *, u_int32_t *, struct sockaddr_encap *); int pfkeyv2_get(struct tdb *, void **, void **, int *, int *); int pfkeyv2_policy(struct ipsec_acquire *, void **, void **, int *); int pfkeyv2_send(struct socket *, void *, int); int pfkeyv2_sendmessage(void **, int, struct socket *, u_int8_t, int, u_int); int pfkeyv2_dump_policy(struct ipsec_policy *, void **, void **, int *); int pfkeyv2_dump_walker(struct tdb *, void *, int); int pfkeyv2_get_proto_alg(u_int8_t, u_int8_t *, int *); int pfkeyv2_sysctl(int *, u_int, void *, size_t *, void *, size_t); int pfkeyv2_sysctl_walker(struct tdb *, void *, int); int pfkeyv2_sysctl_dump(void *); int pfdatatopacket(void *, int, struct mbuf **); void export_address(void **, struct sockaddr *); void export_identities(void **, struct ipsec_ids *, int, void **); void export_lifetime(void **, struct tdb *, int); void export_sa(void **, struct tdb *); void export_flow(void **, u_int8_t, struct sockaddr_encap *, struct sockaddr_encap *, void **); void export_key(void **, struct tdb *, int); void export_udpencap(void **, struct tdb *); void export_tag(void **, struct tdb *); void export_replay(void **, struct tdb *); void export_rdomain(void **, struct tdb *); void export_mtu(void **, struct tdb *); void export_tap(void **, struct tdb *); void export_satype(void **, struct tdb *); void export_counter(void **, struct tdb *); void import_address(struct sockaddr *, struct sadb_address *); void import_identities(struct ipsec_ids **, int, struct sadb_ident *, struct sadb_ident *); void import_key(struct ipsecinit *, struct sadb_key *, int); void import_lifetime(struct tdb *, struct sadb_lifetime *, int); void import_sa(struct tdb *, struct sadb_sa *, struct ipsecinit *); int import_flow(struct sockaddr_encap *, struct sockaddr_encap *, struct sadb_address *, struct sadb_address *, struct sadb_address *, struct sadb_address *, struct sadb_protocol *, struct sadb_protocol *); void import_udpencap(struct tdb *, struct sadb_x_udpencap *); void import_tag(struct tdb *, struct sadb_x_tag *); void import_rdomain(struct tdb *, struct sadb_x_rdomain *); void import_tap(struct tdb *, struct sadb_x_tap *); extern const uint64_t sadb_exts_allowed_out[SADB_MAX+1]; extern const uint64_t sadb_exts_required_out[SADB_MAX+1]; extern struct pool ipsec_policy_pool; extern struct pool ipsec_acquire_pool; #endif /* _KERNEL */ #endif /* _NET_PFKEY_V2_H_ */ libreswan-4.14/include/pfkeyv2/rfc2367.h000066400000000000000000000122151457372064200177210ustar00rootroot00000000000000/* 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 #define PF_KEY_V2 2 #define PFKEYV2_REVISION 199806L #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_MAX 12 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; }; struct sadb_ext { uint16_t sadb_ext_len; uint16_t sadb_ext_type; }; 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; }; 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; }; 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; }; struct sadb_key { uint16_t sadb_key_len; uint16_t sadb_key_exttype; uint16_t sadb_key_bits; uint16_t sadb_key_reserved; }; 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; }; 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; }; struct sadb_prop { uint16_t sadb_prop_len; uint16_t sadb_prop_exttype; uint8_t sadb_prop_replay; uint8_t sadb_prop_reserved[3]; }; 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; }; struct sadb_supported { uint16_t sadb_supported_len; uint16_t sadb_supported_exttype; uint32_t sadb_supported_reserved; }; 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; }; 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; }; struct sadb_x_kmprivate { uint16_t sadb_x_kmprivate_len; uint16_t sadb_x_kmprivate_exttype; uint32_t sadb_x_kmprivate_reserved; }; #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_EXT_MAX 17 #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_SATYPE_MAX 8 #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 #define SADB_SAFLAGS_PFS 1 #define SADB_AALG_NONE 0 #define SADB_AALG_MD5HMAC 2 #define SADB_AALG_SHA1HMAC 3 #define SADB_AALG_MAX 3 #define SADB_EALG_NONE 0 #define SADB_EALG_DESCBC 2 #define SADB_EALG_3DESCBC 3 #define SADB_EALG_NULL 11 #define SADB_EALG_MAX 11 #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 #define SADB_KEY_FLAGS_MAX 0 #endif /* __PFKEY_V2_H */ libreswan-4.14/include/pluto_constants.h000066400000000000000000001101251457372064200204750ustar00rootroot00000000000000/* 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 * Copyright (C) 2020 Yulia Kuzovkova * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT 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 * 8 #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 */ /* * XFRM_INF is a uint64_t, hence use that to define upper bound of * constant. */ #define IPSEC_SA_MAX_OPERATIONS (UINT64_C(1) << 63) #define IPSEC_SA_MAX_OPERATIONS_STRING "2^63" /* how to print IPSEC_SA_MAX_OPERATIONS */ #define IPSEC_SA_MAX_SOFT_LIMIT_PERCENTAGE 50 #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 IKE_BUF_AUTO 0 /* use system values for IKE socket buffer size */ #define DEFAULT_XFRM_IF_NAME "ipsec1" /* 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, }; enum keyword_auth { AUTH_UNSET = 0, AUTH_NEVER, AUTH_PSK, AUTH_RSASIG, AUTH_ECDSA, AUTH_NULL, AUTH_EAPONLY, }; enum keyword_xauthby { XAUTHBY_FILE = 0, XAUTHBY_PAM = 1, XAUTHBY_ALWAYSOK = 2, }; enum allow_global_redirect { GLOBAL_REDIRECT_NO = 1, GLOBAL_REDIRECT_YES = 2, GLOBAL_REDIRECT_AUTO = 3, }; 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 */ }; enum global_ikev1_policy { GLOBAL_IKEv1_ACCEPT = 0, GLOBAL_IKEv1_REJECT = 1, GLOBAL_IKEv1_DROP = 2, }; /* 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 */ /* * Timer events not associated with states (aka global * timers). */ extern const struct enum_names global_timer_names; enum global_timer { 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_LIMITER, /* set rate limited log message count back to 0 */ #define RESET_LOG_LIMITER_FREQUENCY deltatime(secs_per_hour) EVENT_NAT_T_KEEPALIVE, /* NAT Traversal Keepalive */ EVENT_PROCESS_KERNEL_QUEUE, /* non-netkey */ }; /* * State based events and timers. */ extern const struct enum_names event_type_names; enum event_type { EVENT_NULL, /* non-event */ /* events associated with connections */ /* events associated with states */ EVENT_RETRANSMIT, /* v1/v2 retransmit IKE packet */ EVENT_CRYPTO_TIMEOUT, /* v1/v2 after some time, give up on crypto helper */ /* * For IKEv2 'replace' is really either a re-key a full * replace, or expire. IKEv1 should be the same but isn't. */ EVENT_SA_DISCARD, /* v1/v2 discard unfinished state object */ 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_DPD, /* v1 dead peer detection */ EVENT_v1_DPD_TIMEOUT, /* v1 dead peer detection timeout */ EVENT_v1_PAM_TIMEOUT, /* v1 give up on PAM helper */ EVENT_v1_REPLACE_IF_USED, /* v1 replacement event */ EVENT_v2_REKEY, /* SA rekey event */ EVENT_v2_REAUTH, /* SA re-authenticate event */ EVENT_v2_LIVENESS, /* for dead peer detection */ EVENT_v2_ADDR_CHANGE, /* process IP address deletion */ 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 deltatime(3) /* seconds */ #define PARENT_MIN_LIFE_DELAY deltatime(1) /* second */ #define EXPIRE_OLD_SA_DELAY deltatime(1) /* second */ #define REPLACE_ORPHAN_DELAY deltatime(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 EVENT_CRYPTO_TIMEOUT_DELAY deltatime(RETRANSMIT_TIMEOUT_DEFAULT) /* wait till the other side give up on us */ #define EVENT_v1_PAM_TIMEOUT_DELAY deltatime(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_v1N + ( 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_v1N+. 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_v1N+, 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 and PAM * 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_V2_RESPONDER_DELETE_IKE_FAMILY, /* does not send delete */ STF_V2_INITIATOR_DELETE_IKE_FAMILY, /* sends delete */ /* forced maybe maybe 'success' */ STF_FATAL, /* no always never fail */ STF_FAIL_v1N, /* no maybe? maybe? fail */ #define STF_ROOF (STF_FAIL_v1N + 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 EXCHANGE_TIMEOUT_DELAY deltatime(200) /* seconds before giving up on an exchange */ #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 128 /* for Linux, requires 2.6.39+ */ #define IKE_V2_OVERLAPPING_WINDOW_SIZE 1 /* our default for rfc 7296 # 2.3 */ #define PPK_ID_MAXLEN 64 /* fairly arbitrary */ /* * debugging settings: a set of selections for reporting These would * be more naturally situated in log.h, but they are shared with * whack. * * 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, DBG_REFCNT_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, }; /* 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_REFCNT LELEM(DBG_REFCNT_IX) #define DBG_ALL (DBG_BASE | DBG_CPU_USAGE | DBG_REFCNT) /* singleton sets: must be kept in sync with the items! */ /* 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) /* 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 */ #ifdef USE_IKEv1 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! */ #endif /* * IKEv2 states. * * Note: that message reliably sending is done by initiator * only, unlike with IKEv1. * * Note: order matters. Larval states come before * ESTABLISHED_*_SA. */ STATE_IKEv2_FLOOR, /* IKE SA */ STATE_V2_PARENT_I0 = STATE_IKEv2_FLOOR, /* waiting for KE to finish */ STATE_V2_PARENT_I1, /* IKE_SA_INIT: sent initial message, waiting for reply */ STATE_V2_PARENT_I2, /* IKE_AUTH: sent auth message, waiting for reply */ STATE_V2_PARENT_R0, /* just starting */ STATE_V2_PARENT_R1, /* IKE_SA_INIT: sent response */ STATE_V2_PARENT_R_EAP, /* IKE_AUTH EAP negotiation */ /* IKE exchange can also create a child */ STATE_V2_IKE_AUTH_CHILD_I0, /* ephemeral: child from IKE exchange */ STATE_V2_IKE_AUTH_CHILD_R0, /* ephemeral: child from IKE exchange */ /* IKEv2 CREATE_CHILD_SA Initiator states */ STATE_V2_NEW_CHILD_I0, /* larval: sent nothing yet */ STATE_V2_NEW_CHILD_I1, /* sent first message of CREATE_CHILD new IPsec */ STATE_V2_REKEY_IKE_I0, /* larval: sent nothing yet */ STATE_V2_REKEY_IKE_I1, /* sent first message (via parrenti) to rekey parent */ STATE_V2_REKEY_CHILD_I0, /* larval: sent nothing yet */ STATE_V2_REKEY_CHILD_I1, /* sent first message (via parent to rekey child sa. */ /* IKEv2 CREATE_CHILD_SA Responder states */ STATE_V2_NEW_CHILD_R0, /* larval: sent nothing yet. */ STATE_V2_REKEY_IKE_R0, /* larval: sent nothing yet terminal state STATE_V2_PARENT_R2 */ STATE_V2_REKEY_CHILD_R0, /* larval: sent nothing yet. */ /* IKEv2's established states */ STATE_V2_ESTABLISHED_IKE_SA, STATE_V2_ESTABLISHED_CHILD_SA, /* IKEv2 Delete States */ STATE_V2_IKE_SA_DELETE, STATE_V2_CHILD_SA_DELETE, 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! */ /* * Perspective from which the operation is being performed. * * For instance, is the hash being computed from the LOCAL or REMOTE * perspective? */ enum perspective { NO_PERSPECTIVE, /* invalid */ LOCAL_PERSPECTIVE, REMOTE_PERSPECTIVE, }; extern const struct enum_names perspective_names; /* * 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(Response) 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. */ enum message_role { NO_MESSAGE = 0, #define MESSAGE_ROLE_FLOOR 1 MESSAGE_REQUEST = 1, /* MSG_R missing */ MESSAGE_RESPONSE = 2, /* MSR_R present */ #define MESSAGE_ROLE_ROOF 3 }; 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. */ enum sa_role { SA_INITIATOR = 1, SA_RESPONDER = 2, }; extern struct keywords sa_role_names; #ifdef USE_IKEv1 #define V1_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_V1_PHASE1(ST) (STATE_MAIN_R0 <= (ST) && (ST) <= STATE_AGGR_R2) #define IS_V1_PHASE15(ST) (STATE_XAUTH_R0 <= (ST) && (ST) <= STATE_XAUTH_I1) #define IS_V1_QUICK(ST) (STATE_QUICK_R0 <= (ST) && (ST) <= STATE_QUICK_R2) #define V1_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_V1_ISAKMP_ENCRYPTED(ST) ((LELEM(ST) & V1_ISAKMP_ENCRYPTED_STATES) != LEMPTY) /* ??? Is this really authenticate? Even in xauth case? In STATE_INFO case? */ #define IS_V1_ISAKMP_AUTHENTICATED(ST) (STATE_MAIN_R3 <= ((ST)->kind) && \ STATE_AGGR_R0 != ((ST)->kind) && \ STATE_AGGR_I1 != ((ST)->kind)) #define V1_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)) #define IS_V1_ISAKMP_SA_ESTABLISHED(ST) \ ((LELEM((ST)->st_state->kind) & V1_ISAKMP_SA_ESTABLISHED_STATES) != LEMPTY) #define IS_V1_ISAKMP_SA(ST) ((ST)->st_ike_version == IKEv1 && (ST)->st_clonedfrom == SOS_NOBODY) #define IS_V1_MODE_CFG_ESTABLISHED(ST) (((ST)->kind) == STATE_MODE_CFG_R2) #else /* no IKEV1 */ /* saves a bunch of ugly ifdefs elsewhere */ #define IS_V1_ISAKMP_SA_ESTABLISHED(ST) false #endif #define IKEV2_ISAKMP_INITIATOR_STATES (LELEM(STATE_V2_PARENT_I0) | \ LELEM(STATE_V2_PARENT_I1) | \ LELEM(STATE_V2_PARENT_I2)) /* IKEv1 or IKEv2 */ #ifdef USE_IKEv1 #define IS_IPSEC_SA_ESTABLISHED(ST) (IS_CHILD_SA(ST) && \ (((ST)->st_state->kind) == STATE_QUICK_I2 || \ ((ST)->st_state->kind) == STATE_QUICK_R1 || \ ((ST)->st_state->kind) == STATE_QUICK_R2 || \ ((ST)->st_state->kind) == STATE_V2_ESTABLISHED_CHILD_SA)) #else #define IS_IPSEC_SA_ESTABLISHED(ST) (IS_CHILD_SA(ST) && \ ((ST)->st_state->kind) == STATE_V2_ESTABLISHED_CHILD_SA) #endif /* * ??? Issue here is that our child SA appears as a * STATE_V2_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_ESTABLISHED_CHILD_SA) #define IS_IKE_SA_ESTABLISHED(ST) \ ((ST)->st_state->kind == STATE_V2_ESTABLISHED_IKE_SA) #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 tcp_options { IKE_TCP_NO = 1, /* default */ IKE_TCP_ONLY = 2, IKE_TCP_FALLBACK = 3, }; enum eap_options { IKE_EAP_NONE = 0, /* default */ IKE_EAP_TLS = 1, }; /* * 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! */ typedef struct { char buf[512];/*arbitrary*/ } policy_buf; const char *str_policy(lset_t policy, policy_buf *buf); size_t jam_policy(struct jambuf *buf, 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 shunt_policy { SHUNT_UNSET, SHUNT_NONE, SHUNT_HOLD, /* during negotiation, don't change */ SHUNT_TRAP, SHUNT_PASS, SHUNT_DROP, SHUNT_REJECT, #define SHUNT_POLICY_ROOF (SHUNT_REJECT+1) }; enum sa_policy_bits { 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_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_MASK LRANGE(POLICY_ENCRYPT_IX, POLICY_NOPMTUDISC_IX) /* connection policy * Other policies could vary per state object. These live in connection. */ 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? */ 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_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_INTERMEDIATE_IX, /* allow Intermediate Exchange */ POLICY_IGNORE_PEER_DNS_IX, /* install obtained DNS servers locally */ #define POLICY_IX_LAST POLICY_IGNORE_PEER_DNS_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_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_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_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_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_INTERMEDIATE LELEM(POLICY_INTERMEDIATE_IX) /* allow Intermediate Exchange */ #define POLICY_IGNORE_PEER_DNS LELEM(POLICY_IGNORE_PEER_DNS_IX) /* * RFC 7427 Signature Hash Algorithm exchang */ #define POL_SIGHASH_SHA1 LELEM(IKEv2_HASH_ALGORITHM_SHA1) /* rfc7427 does responder support SHA1? */ #define POL_SIGHASH_SHA2_256 LELEM(IKEv2_HASH_ALGORITHM_SHA2_256) /* rfc7427 does responder support SHA2-256? */ #define POL_SIGHASH_SHA2_384 LELEM(IKEv2_HASH_ALGORITHM_SHA2_384) /* rfc7427 does responder support SHA2-384? */ #define POL_SIGHASH_SHA2_512 LELEM(IKEv2_HASH_ALGORITHM_SHA2_512) /* rfc7427 does responder support SHA2-512? */ #define POL_SIGHASH_IDENTITY LELEM(IKEv2_HASH_ALGORITHM_IDENTITY) /* rfc4307-bis does responder support IDENTITY? */ #define POL_SIGHASH_DEFAULTS (POL_SIGHASH_SHA2_256 | POL_SIGHASH_SHA2_384 | POL_SIGHASH_SHA2_512); /* 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= * * LOOSE_ENUM_OTHER is used by the config parser's loose-enum code to * flag that the field didn't match one of the pre-defined "%..." * values. */ 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 }; #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 */ PLUTO_EXIT_SELINUX_FAIL = 11, PLUTO_EXIT_LEAVE_STATE = 12, /* leave kernel state and routes */ /**/ PLUTO_EXIT_GIT_BISECT_CAN_NOT_TEST = 125, PLUTO_EXIT_SHELL_COMMAND_NOT_FOUND = 126, PLUTO_EXIT_SHELL_COMMAND_NOT_EXECUTABLE = 127, }; extern const struct enum_names pluto_exit_code_names; /* * EXPIRE type events from the kernel. * Based on these, different actions can be taken, eg skipping delete SPI */ enum sa_expire_kind { /* 0 reserved */ SA_ACTIVE = 1 << 1, SA_SOFT_EXPIRED = 1 << 2, SA_HARD_EXPIRED = 1 << 3, }; #define SWAN_MAX_DOMAIN_LEN 256 /* includes nul termination */ extern void init_pluto_constants(void); /* * Maximum data (including 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-4.14/include/proposals.h000066400000000000000000000203111457372064200172550ustar00rootroot00000000000000/* 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" #include "diag.h" struct jambuf; struct alg_info; struct proposal_protocol; struct proposal; struct proposals; struct proposal_policy; struct proposal_parser; enum stream; /* * 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; diag_t diag; }; /* * 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); /* * logging context */ struct logger *logger; lset_t logger_rc_flags; }; /* * 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(const struct proposals *proposals); bool default_proposals(const struct proposals *proposals); void free_proposals(struct proposals **proposals); extern struct proposal *alloc_proposal(const 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); void remove_duplicate_algorithms(struct proposal_parser *parser, struct proposal *proposal, enum proposal_algorithm algorithm); 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 jam_proposal(struct jambuf *log, const struct proposal *proposal); void jam_proposals(struct jambuf *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); /* * INTERNAL: tokenize into */ struct proposal_tokenizer { char prev_term; shunk_t this; char this_term; shunk_t next; char next_term; shunk_t input; const char *delims; }; struct proposal_tokenizer proposal_first_token(shunk_t input, const char *delim); void proposal_next_token(struct proposal_tokenizer *token); bool proposal_parse_encrypt(struct proposal_parser *parser, struct proposal_tokenizer *tokens, const struct ike_alg **encrypt, int *enckeylen); #endif /* PROPOSALS_H */ libreswan-4.14/include/realtime.h000066400000000000000000000051221457372064200170400ustar00rootroot00000000000000/* 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 jambuf; /* * 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 seconds); realtime_t realtime_ms(intmax_t milliseconds); /* * 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(struct jambuf *buf, realtime_t r, bool utc); /* * math */ realtime_t realtimesum(realtime_t t, deltatime_t d); bool is_realtime_epoch(realtime_t t); /* sign(a - b); see timercmp() for hacks origin */ int realtime_sub_sign(realtime_t l, realtime_t r); #define realtime_cmp(L, OP, R) (realtime_sub_sign(L, R) OP 0) 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-4.14/include/refcnt.h000066400000000000000000000057001457372064200165210ustar00rootroot00000000000000/* 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" struct refcnt_base { const char *what; void (*free)(void *object, where_t where); }; typedef struct refcnt { volatile unsigned count; const struct refcnt_base *base; } refcnt_t; /* * Initialize the refcnt. * * Note: the over-allocated memory is _NOT_ aligned. * Note: ref_init(OBJ,HERE) breaks as HERE contains braces. */ void refcnt_init(const void *pointer, struct refcnt *refcnt, const struct refcnt_base *base, where_t where); #define refcnt_overalloc(THING, EXTRA, FREE, WHERE) \ ({ \ static const struct refcnt_base b_ = { \ .what = #THING, \ .free = FREE, \ }; \ THING *t_ = alloc_bytes(sizeof(THING) + (EXTRA), b_.what); \ refcnt_init(t_, &t_->refcnt, &b_, WHERE); \ t_; \ }) #define refcnt_alloc(THING, FREE, WHERE) \ refcnt_overalloc(THING, /*extra*/0, FREE, WHERE) /* look at refcnt atomically */ unsigned refcnt_peek(const refcnt_t *refcnt); /* * Add a reference. * * Note that ref_add(OBJ,HERE) breaks as HERE contains braces. */ void refcnt_addref_where(const char *what, const void *pointer, refcnt_t *refcnt, where_t where); #define addref_where(OBJ, WHERE) \ ({ \ typeof(OBJ) o_ = OBJ; /* evaluate once */ \ refcnt_addref_where(#OBJ, o_, o_ == NULL ? NULL : &o_->refcnt, WHERE); \ o_; /* result */ \ }) #define addref(OBJ) \ ({ \ where_t where = HERE; \ addref_where(OBJ, where); \ }) /* * Delete a reference. * * Note that ref_delete(OBJ,HERE) breaks as HERE contains braces. */ void refcnt_delref_where(const char *what, void *pointer, struct refcnt *refcnt, where_t where); #define delref_where(OBJ, WHERE) \ { \ typeof(OBJ) o_ = OBJ; \ refcnt_delref_where(#OBJ, *o_, *o_ == NULL ? NULL : &(*o_)->refcnt, WHERE); \ *o_ = NULL; /*kill pointer */ \ } #define delref(OBJ) \ { \ where_t where = HERE; \ delref_where(OBJ, where); \ } /* for code wanting to use refcnt for normal allocs */ void dbg_alloc(const char *what, const void *pointer, where_t where); void dbg_free(const char *what, const void *pointer, where_t where); #endif libreswan-4.14/include/reqid.h000066400000000000000000000032651457372064200163500ustar00rootroot00000000000000/* 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-4.14/include/rnd.h000066400000000000000000000020201457372064200160130ustar00rootroot00000000000000/* randomness machinery * * Copyright (C) 1998, 1999 D. Hugh Redelmeier. * 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 PLUTO_RND_H #define PLUTO_RND_H #include /* for uintmax_t */ #include /* for size_t */ #include "chunk.h" struct logger; extern void fill_rnd_chunk(chunk_t chunk); extern void get_rnd_bytes(void *buffer, size_t size); extern uintmax_t get_rnd_uintmax(uintmax_t roof); extern chunk_t alloc_rnd_chunk(size_t size, const char *name); #endif libreswan-4.14/include/secrets.h000066400000000000000000000225351457372064200167150ustar00rootroot00000000000000/* 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 "lswcdefs.h" #include "x509.h" #include "id.h" #include "err.h" #include "realtime.h" #include "ckaid.h" #include "diag.h" #include "keyid.h" #include "refcnt.h" #include "crypt_mac.h" #include "ike_alg.h" /* for HASH_ALGORITHM_IDENTIFIER */ struct logger; struct state; /* forward declaration */ struct secret; /* opaque definition, private to secrets.c */ struct pubkey; /* forward */ struct pubkey_content; /* forward */ struct pubkey_type; /* forward */ struct hash_desc; struct cert; /* * The raw public key. * * While this is abstracted as a SECKEYPublicKey, it can be thought of * as the Subject Public Key Info. */ struct pubkey_content { const struct pubkey_type *type; keyid_t keyid; /* see ipsec_keyblobtoid(3) */ ckaid_t ckaid; SECKEYPublicKey *public_key; }; /* * private key types */ enum secret_kind { /* start at one so accidental 0 will not match */ SECRET_PSK = 1, SECRET_RSA, SECRET_XAUTH, SECRET_PPK, SECRET_ECDSA, /* should not be needed */ SECRET_NULL, SECRET_INVALID, }; struct secret_pubkey_stuff { SECKEYPrivateKey *private_key; struct pubkey_content content; }; struct secret_stuff { enum secret_kind kind; /* * 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 secret_pubkey_stuff pubkey; } u; chunk_t ppk; chunk_t ppk_id; }; diag_t secret_pubkey_stuff_to_pubkey_der(struct secret_stuff *pks, chunk_t *der); diag_t pubkey_der_to_pubkey_content(shunk_t pubkey_der, struct pubkey_content *pkc); extern struct secret_stuff *get_secret_stuff(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 secret_stuff *pks, void *uservoid); struct secret *foreach_secret(struct secret *secrets, secret_eval func, void *uservoid); struct hash_signature { size_t len; /* * For ECDSA, see https://tools.ietf.org/html/rfc4754#section-7 * for where 1056 is coming from (it is the largest of the * signature lengths amongst ECDSA 256, 384, and 521). * * For RSA this needs to be big enough to fit the modulus. * Because the modulus in the SECItem is signed (but the raw * value is unsigned), the modulus may have been prepended * with an additional zero byte. Hence the +1 to accomodate * fuzzy checks against modulus.len. * * New code should just ask NSS for the signature length. */ uint8_t ptr[PMAX(BYTES_FOR_BITS(8192)+1/*RSA*/, BYTES_FOR_BITS(1056)/*ECDSA*/)]; }; struct pubkey_type { const char *name; enum secret_kind private_key_kind; void (*free_pubkey_content)(struct pubkey_content *pkc); /* to/from the blob in DNS's IPSECKEY's Public Key field */ diag_t (*ipseckey_rdata_to_pubkey_content)(shunk_t ipseckey_pubkey, struct pubkey_content *pkc); err_t (*pubkey_content_to_ipseckey_rdata)(const struct pubkey_content *pkc, chunk_t *ipseckey_pubkey, enum ipseckey_algorithm_type *ipseckey_algorithm); /* nss */ err_t (*extract_pubkey_content)(struct pubkey_content *pkc, SECKEYPublicKey *pubkey_nss, SECItem *ckaid_nss); bool (*pubkey_same)(const struct pubkey_content *lhs, const struct pubkey_content *rhs); #define pubkey_strength_in_bits(PUBKEY) ((PUBKEY)->content.type->strength_in_bits(PUBKEY)) size_t (*strength_in_bits)(const struct pubkey *pubkey); }; struct pubkey_signer { const char *name; enum digital_signature_blob digital_signature_blob; const struct pubkey_type *type; struct hash_signature (*sign_hash)(const struct secret_stuff *pks, const uint8_t *hash_octets, size_t hash_len, const struct hash_desc *hash_algo, struct logger *logger); /* * Danger! This function returns three results * * true;FATAL_DIAG=NULL: pubkey verified * false;FATAL_DIAG=NULL: pubkey did not verify * false;FATAL_DIAG!=NULL: operation should be aborted */ bool (*authenticate_signature)(const struct crypt_mac *hash, shunk_t signature, struct pubkey *kr, const struct hash_desc *hash_algo, diag_t *fatal_diag, struct logger *logger); size_t (*jam_auth_method)(struct jambuf *, const struct pubkey_signer *, const struct pubkey *, const struct hash_desc *); }; extern const struct pubkey_type pubkey_type_rsa; extern const struct pubkey_type pubkey_type_ecdsa; extern const struct pubkey_signer pubkey_signer_raw_rsa; /* IKEv1 */ extern const struct pubkey_signer pubkey_signer_raw_pkcs1_1_5_rsa; /* rfc7296 */ extern const struct pubkey_signer pubkey_signer_raw_ecdsa; /* rfc4754 */ extern const struct pubkey_signer pubkey_signer_digsig_pkcs1_1_5_rsa; /* rfc7427 */ extern const struct pubkey_signer pubkey_signer_digsig_rsassa_pss; /* rfc7427 */ extern const struct pubkey_signer pubkey_signer_digsig_ecdsa; /* rfc7427 */ const struct pubkey_type *pubkey_alg_type(enum ipseckey_algorithm_type alg); /* * Public Key Machinery. * * This is a mashup of fields taken both from the certificate and the * subject public key info. */ struct pubkey { refcnt_t refcnt; /* reference counted! */ struct id id; 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 */ asn1_t issuer; struct pubkey_content content; /* for overalloc of issuer */ uint8_t end[]; }; /* * 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 ckaid_t *pubkey_ckaid(const struct pubkey *pk); const keyid_t *pubkey_keyid(const struct pubkey *pk); const ckaid_t *secret_ckaid(const struct secret *); const keyid_t *secret_keyid(const struct secret *); 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); diag_t unpack_dns_ipseckey(const struct id *id, /* ASKK */ enum dns_auth_level dns_auth_level, enum ipseckey_algorithm_type algorithm_type, realtime_t install_time, realtime_t until_time, uint32_t ttl, shunk_t dnssec_pubkey, struct pubkey **pubkey, struct pubkey_list **head); void replace_public_key(struct pubkey_list **pubkey_db, struct pubkey **pk); 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, keyid_t *keyid, size_t *keysize); /*XXX: make static? */ struct pubkey *pubkey_addref_where(struct pubkey *pk, where_t where); #define pubkey_addref(PK) pubkey_addref_where(PK, HERE) extern void pubkey_delref_where(struct pubkey **pkp, where_t where); #define pubkey_delref(PKP) pubkey_delref_where(PKP, HERE) bool secret_pubkey_same(struct secret *lhs, struct secret *rhs); extern void lsw_load_preshared_secrets(struct secret **psecrets, const char *secrets_file, struct logger *logger); extern void lsw_free_preshared_secrets(struct secret **psecrets, struct logger *logger); extern struct secret *lsw_find_secret_by_id(struct secret *secrets, enum secret_kind 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); /* err_t!=NULL -> neither found nor loaded; loaded->just pulled in */ err_t find_or_load_private_key_by_cert(struct secret **secrets, const struct cert *cert, const struct secret_stuff **pks, bool *load_needed, struct logger *logger); err_t find_or_load_private_key_by_ckaid(struct secret **secrets, const ckaid_t *ckaid, const struct secret_stuff **pks, bool *load_needed, struct logger *logger); diag_t create_pubkey_from_cert(const struct id *id, CERTCertificate *cert, struct pubkey **pk, struct logger *logger) MUST_USE_RESULT; #endif /* _SECRETS_H */ libreswan-4.14/include/shunk.h000066400000000000000000000117171457372064200163750ustar00rootroot00000000000000/* 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 uintmax_t */ #include "hunk.h" #include "err.h" #include "where.h" /* * Think of shunk_t and chunk_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. */ 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 HUNK_AS_SHUNK(HUNK) ({ typeof(HUNK) h_ = (HUNK); shunk2(h_.ptr, h_.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); /* only the shunk_t** pointer needs freeing */ shunk_t *clone_shunk_tokens(shunk_t input, const char *delim, where_t here); /* * Return the sequence of characters 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 functions that gobble up the start of a string (or * at least libreswan's versions). * * Confusingly and just like POSIX, the *case*() variant ignores case. * * Just like a NULL and EMPTY ("") string, a NULL (uninitialized) and * EMPTY (pointing somewhere but no bytes) are considered different. */ bool shunk_eat(shunk_t *lhs, shunk_t rhs); bool shunk_caseeat(shunk_t *lhs, shunk_t rhs); bool shunk_streat(shunk_t *lhs, const char *string); bool shunk_strcaseeat(shunk_t *lhs, const char *string); /* * Number conversion; loosely based on strtoul(START, END, BASE). * * Parse INPUT according to BASE (see strtoul()). Should the numeric * value be missing or invalid, or the value overflow uintmax_t then * an error is returned. * * If CURSOR is NULL, having text following the numeric value is * considered an error (strtoul() silently ignores trailing junk when * END=NULL). * * If CURSOR is non-NULL, it is set to the text following the numeric * value. */ err_t shunk_to_uintmax(shunk_t input, shunk_t *cursor, unsigned base, uintmax_t *value); /* * 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-4.14/include/sparse_names.h000066400000000000000000000044511457372064200177220ustar00rootroot00000000000000/* sparse_names, for libreswan * * 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 SPARSE_NAMES_H #define SPARSE_NAMES_H struct jambuf; /* * sparse_names is much like enum_names, except values are not known * to be contiguous or ordered. * * The array is NULL terminated, as in .name==NULL; but suggest using * SPARSE_NULL in case that needs to change. */ #define SPARSE_NULL { NULL, 0, } struct sparse_name { /* field order (backwards?) dictated by started() */ const char *const name; unsigned long value; }; typedef const struct sparse_name sparse_names[]; typedef struct { char buf[16];/*how big?*/ } sparse_buf; const char *sparse_name(sparse_names sd, unsigned long val); size_t jam_sparse(struct jambuf *buf, sparse_names sd, unsigned long val); const char *str_sparse(sparse_names sd, unsigned long val, sparse_buf *buf); /* * sparse_sparse_names is much like enum_enum_names, except, again the * values are neither assumed to be contingious or ordered. * * The array is terminated by a NULL entry. */ struct sparse_sparse_name { unsigned long value; const struct sparse_name *names; }; typedef const struct sparse_sparse_name sparse_sparse_names[]; extern const char *sparse_sparse_name(sparse_sparse_names sd, unsigned long v1, unsigned long v2); #endif /* _CONSTANTS_H_ */ libreswan-4.14/include/sysdep.h000066400000000000000000000006441457372064200165510ustar00rootroot00000000000000/* * 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-4.14/include/test_buffer.h000066400000000000000000000030351457372064200175470ustar00rootroot00000000000000/* * Copyright (C) 2014 Andrew Cagney * 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. */ #include #include #include "chunk.h" chunk_t decode_to_chunk(const char *prefix, const char *string); PK11SymKey *decode_hex_to_symkey(const char *prefix, const char *string, struct logger *logger); bool verify_symkey(const char *desc, chunk_t expected, PK11SymKey *actual, struct logger *logger); bool verify_bytes(const char *desc, const void *expected, size_t expected_size, const void *actual, size_t actual_size); #define verify_hunk(DESC, EXPECTED, ACTUAL) \ ({ \ typeof(EXPECTED) expected_ = EXPECTED; /* evaluate once */ \ typeof(ACTUAL) actual_ = ACTUAL; /* evaluate once */ \ verify_bytes(DESC, expected_.ptr, expected_.len, \ actual_.ptr, actual_.len); \ }) struct encrypt_desc; PK11SymKey *decode_to_key(const struct encrypt_desc *encrypt_desc, const char *string, struct logger *logger); libreswan-4.14/include/timescale.h000066400000000000000000000024521457372064200172070ustar00rootroot00000000000000/* scale time, for libreswan * * Copyright (C) 2022 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 TIMESCALE_H #define TIMESCALE_H /* seen it, no need to see it again */ #include /* for uintmax_t */ #include "shunk.h" struct timescale { const char *suffix; uintmax_t ms; }; extern const struct timescale timescale_milliseconds; extern const struct timescale timescale_seconds; extern const struct timescale timescale_minutes; extern const struct timescale timescale_hours; extern const struct timescale timescale_days; extern const struct timescale timescale_weeks; #define PRI_TIMESCALE "1%s(%jums)" #define pri_timescale(TS) (TS).suffix, (TS).ms const struct timescale *ttotimescale(shunk_t s, const struct timescale *default_scale); #endif libreswan-4.14/include/ttodata.h000066400000000000000000000030741457372064200167020ustar00rootroot00000000000000/* * 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 TTODATA_H #define TTODATA_H /* seen it, no need to see it again */ #include /* for size_t */ #include "err.h" #include "lset.h" #include "chunk.h" #include "shunk.h" /* * new IPv6-compatible functions */ /* text conversions */ 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 ((64+2)/3 + 1) /* holds 64 bits in octal + NUL */ extern err_t ttodata(const char *src, size_t srclen, int base, char *buf, size_t buflen, size_t *needed); extern err_t ttochunk(shunk_t src, int base, chunk_t *chunk); extern size_t datatot(const unsigned char *src, size_t srclen, int format, char *buf, size_t buflen); #endif libreswan-4.14/include/unbound/000077500000000000000000000000001457372064200165375ustar00rootroot00000000000000libreswan-4.14/include/unbound/README000066400000000000000000000007541457372064200174250ustar00rootroot00000000000000 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-4.14/include/unbound/unbound-event.h000066400000000000000000000253631457372064200215120ustar00rootroot00000000000000/* * 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 whith 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_type)(void*, int, void*, int, int, char*, int); /** * 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_type callback, int* async_id); #ifdef __cplusplus } #endif #endif /* _UB_UNBOUND_H */ libreswan-4.14/include/vendorid.h000066400000000000000000000131271457372064200170540ustar00rootroot00000000000000/* Libreswan ISAKMP VendorID * * Copyright (C) 2002-2003 Mathieu Lafon - Arkoon Network Security * Copyright (C) 2005-2008 Michael Richardson * Copyright (C) 2007 Ken Bantoft * Copyright (C) 2008-2011 Paul Wouters * Copyright (C) 2012 Paul Wouters * Copyright (C) 2013-2018 Paul Wouters * Copyright (C) 2013 D. Hugh Redelmeier * Copyright (C) 2013 Wolfgang Nothdurft * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT 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 VENDORID_H #define VENDORID_H #include "constants.h" /* for enum_buf */ #include "shunk.h" struct logger; void init_vendorid(struct logger *logger); enum known_vendorid vendorid_by_shunk(shunk_t vid); shunk_t shunk_from_vendorid(enum known_vendorid id); void llog_vendorid(struct logger *logger, enum known_vendorid id, shunk_t vid, bool useful); const char *str_vendorid(enum known_vendorid id, enum_buf *eb); enum known_vendorid { VID_none = 0, /* when none seen, this will appear */ /* Implementation names */ VID_OPENPGP, VID_KAME_RACOON, /* https://msdn.microsoft.com/en-us/library/cc233476.aspx */ VID_MS_WIN2K, VID_MS_WINXP, VID_MS_WIN2003, VID_MS_WINVISTA, VID_MS_WIN2008, VID_MS_WIN7, VID_MS_WIN2008R2, VID_MS_WINKSINK09, VID_MS_WINKEYMODS_IKE, VID_MS_WINKEYMODS_AUTHIP, VID_MS_WINKEYMODS_IKEv2, VID_MS_AUTHIP_KE_DH_NONE, VID_MS_AUTHIP_KE_DH1, VID_MS_AUTHIP_KE_DH2, VID_MS_AUTHIP_KE_DH14, VID_MS_AUTHIP_KE_DH19, VID_MS_AUTHIP_KE_DH20, VID_MS_AUTHIP_KE_DH21, VID_MS_AUTHIP_KE_DHMAX, VID_MS_NLBS_PRESENT, VID_MS_AUTHIP_SUPPORTED, VID_MS_CGA_SUPPORTED, VID_MS_NEGOTIATION_DISCOVERY_SUPPORTED, VID_MS_XBOX_ONE_2013, VID_MS_XBOX_IKEv2, VID_MS_SEC_REALM_ID, VID_SSH_SENTINEL, VID_SSH_SENTINEL_1_1, VID_SSH_SENTINEL_1_2, VID_SSH_SENTINEL_1_3, VID_SSH_IPSEC_1_1_0, VID_SSH_IPSEC_1_1_1, VID_SSH_IPSEC_1_1_2, VID_SSH_IPSEC_1_2_1, VID_SSH_IPSEC_1_2_2, VID_SSH_IPSEC_2_0_0, VID_SSH_IPSEC_2_1_0, VID_SSH_IPSEC_2_1_1, VID_SSH_IPSEC_2_1_2, VID_SSH_IPSEC_3_0_0, VID_SSH_IPSEC_3_0_1, VID_SSH_IPSEC_4_0_0, VID_SSH_IPSEC_4_0_1, VID_SSH_IPSEC_4_1_0, VID_SSH_IPSEC_4_2_0, VID_CISCO_UNITY, VID_CISCO_VPN_REV_02, VID_CISCO3K, VID_CISCO_IOS, VID_CISCO_UNITY_FWTYPE, VID_CISCO_DELETE_REASON, VID_CISCO_FLEXVPN_SUPPORTED, VID_CISCO_DYNAMIC_ROUTE, VID_SSH_SENTINEL_1_4, VID_SSH_SENTINEL_1_4_1, VID_TIMESTEP, VID_FSWAN_2_00_VID, VID_FSWAN_2_00_X509_1_3_1_VID, VID_FSWAN_2_00_X509_1_3_1_LDAP_VID, VID_OPENSWAN2, VID_XOPENSWAN, VID_OPENSWANORG, VID_ELVIS, VID_OPPORTUNISTIC, VID_LIBRESWANSELF, VID_LIBRESWAN, VID_LIBRESWAN_OLD, VID_NCP, VID_SONICWALL_1, VID_SONICWALL_2, VID_SHREWSOFT, VID_NETSCREEN_01, VID_NETSCREEN_02, VID_NETSCREEN_03, VID_NETSCREEN_04, VID_NETSCREEN_05, VID_NETSCREEN_06, VID_NETSCREEN_07, VID_NETSCREEN_08, VID_NETSCREEN_09, VID_NETSCREEN_10, VID_NETSCREEN_11, VID_NETSCREEN_12, VID_NETSCREEN_13, VID_NETSCREEN_14, VID_NETSCREEN_15, VID_NETSCREEN_16, VID_ZYWALL, VID_SIDEWINDER, VID_LUCENT_GW9, VID_LUCENT_CL7, VID_CHECKPOINT, VID_GSSAPI, VID_GSSAPILONG, /* NAT-Traversal */ VID_NATT_STENBERG_01, VID_NATT_STENBERG_02, VID_NATT_HUTTUNEN, VID_NATT_HUTTUNEN_ESPINUDP, VID_NATT_IETF_00, VID_NATT_IETF_01, VID_NATT_IETF_02_N, VID_NATT_IETF_02, VID_NATT_IETF_03, VID_NATT_IETF_04, VID_NATT_IETF_05, VID_NATT_IETF_06, VID_NATT_IETF_07, VID_NATT_IETF_08, VID_NATT_DRAFT_IETF_IPSEC_NAT_T_IKE, VID_NATT_RFC, /* Strongswan */ VID_STRONGSWAN, VID_STRONGSWAN_2_2_0, VID_STRONGSWAN_2_2_1, VID_STRONGSWAN_2_2_2, VID_STRONGSWAN_2_3_0, VID_STRONGSWAN_2_3_1, VID_STRONGSWAN_2_3_2, VID_STRONGSWAN_2_4_0, VID_STRONGSWAN_2_4_1, VID_STRONGSWAN_2_4_2, VID_STRONGSWAN_2_4_3, VID_STRONGSWAN_2_4_4, VID_STRONGSWAN_2_5_0, VID_STRONGSWAN_2_5_1, VID_STRONGSWAN_2_5_2, VID_STRONGSWAN_2_5_3, VID_STRONGSWAN_2_5_4, VID_STRONGSWAN_2_5_5, VID_STRONGSWAN_2_5_6, VID_STRONGSWAN_2_5_7, VID_STRONGSWAN_2_6_0, VID_STRONGSWAN_2_6_1, VID_STRONGSWAN_2_6_2, VID_STRONGSWAN_2_6_3, VID_STRONGSWAN_2_6_4, VID_STRONGSWAN_2_7_0, VID_STRONGSWAN_2_7_1, VID_STRONGSWAN_2_7_2, VID_STRONGSWAN_2_7_3, VID_STRONGSWAN_2_8_0, VID_STRONGSWAN_2_8_1, VID_STRONGSWAN_2_8_2, VID_STRONGSWAN_2_8_3, VID_STRONGSWAN_2_8_4, VID_STRONGSWAN_2_8_5, VID_STRONGSWAN_2_8_6, VID_STRONGSWAN_2_8_7, VID_STRONGSWAN_2_8_8, VID_STRONGSWAN_4_0_0, VID_STRONGSWAN_4_0_1, VID_STRONGSWAN_4_0_2, VID_STRONGSWAN_4_0_3, VID_STRONGSWAN_4_0_4, VID_STRONGSWAN_4_0_5, VID_STRONGSWAN_4_0_6, VID_STRONGSWAN_4_0_7, VID_STRONGSWAN_4_1_0, VID_STRONGSWAN_4_1_1, VID_STRONGSWAN_4_1_2, VID_STRONGSWAN_4_1_3, VID_STRONGSWAN_4_1_4, VID_STRONGSWAN_4_1_5, VID_STRONGSWAN_4_1_6, VID_STRONGSWAN_4_1_7, VID_STRONGSWAN_4_1_8, VID_STRONGSWAN_4_1_9, VID_STRONGSWAN_4_1_10, VID_STRONGSWAN_4_1_11, VID_STRONGSWAN_4_2_0, VID_STRONGSWAN_4_2_1, VID_STRONGSWAN_4_2_2, VID_STRONGSWAN_4_2_3, VID_FORTINET_ENDPOINT_CONTROL, VID_FORTINET_CONNECT_LICENSE, /* Misc */ VID_MISC_XAUTH, VID_MISC_DPD, VID_MISC_HEARTBEAT_NOTIFY, VID_IKE_FRAGMENTATION, VID_INITIAL_CONTACT, VID_MISC_IKEv2, VID_DPD1_NG, #define VID_ROOF (VID_DPD1_NG+1) }; #endif libreswan-4.14/include/whack.h000066400000000000000000000272501457372064200163410ustar00rootroot00000000000000/* 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 * Copyright (C) 2017 Mayank Totale * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT 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" #include "ip_protoport.h" #include "ip_cidr.h" #include "authby.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) + 49) /* 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 { const char *leftright; /* either "left" or "right" (not shipped) */ char *id; /* id 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 */ /* * Where, if anywhere, is the public/private key coming from? * Pass everything over and let pluto decide what if anything * conflict. */ char *cert; char *ckaid; char *pubkey; enum ipseckey_algorithm_type pubkey_alg; enum keyword_auth auth; enum keyword_host host_type; ip_address host_addr; unsigned host_ikeport; ip_address host_nexthop; ip_address host_srcip; ip_cidr host_vtiip; ip_cidr ifaceip; ip_subnet client; ip_protoport protoport; bool key_from_DNS_on_demand; char *updown; /* string */ 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 */ enum certpolicy sendcert; enum eap_options eap; 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_addresspool_status; bool whack_show_states; bool whack_seccomp_crashtest; bool whack_shutdown; /* END OF BASIC COMMANDS * If you change anything earlier in this struct, update WHACK_BASIC_MAGIC. */ bool whack_process_status; /* non-basic */ bool whack_leave_state; /* non-basic: dont send delete or clean kernel state on shutdown */ /* name is used in connection and initiate */ size_t name_len; /* string 1 */ char *name; /* for WHACK_OPTIONS: */ bool whack_options; lmod_t debugging; /* what to impair and how */ struct whack_impair *impairments; unsigned nr_impairments; /* for WHACK_CONNECTION */ bool whack_connection; bool whack_async; enum ike_version ike_version; lset_t policy; struct authby authby; lset_t sighash_policy; enum shunt_policy prospective_shunt; enum shunt_policy negotiation_shunt; enum shunt_policy failure_shunt; deltatime_t sa_ike_life_seconds; deltatime_t sa_ipsec_life_seconds; deltatime_t sa_rekey_margin; uintmax_t sa_ipsec_max_bytes; uintmax_t sa_ipsec_max_packets; unsigned long sa_rekey_fuzz; unsigned long sa_keying_tries; uintmax_t sa_replay_window; deltatime_t retransmit_timeout; deltatime_t retransmit_interval; 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; /* Remote TCP port to use, 0 indicates no TCP */ int remote_tcpport; /* Allow TCP as fallback, only do TCP or only do UDP */ enum tcp_options iketcp; /* 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; char *sec_label; /* sec_label string (if any) -- decoded by pluto */ /* 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 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 ipseckey_algorithm_type 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; struct { struct { ip_address address; ip_port port; } local, remote; unsigned ipproto; } oppo; /* 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_checkpubkeys; /* --checkpubkeys */ bool whack_listpubkeys; /* --listpubkeys */ lset_t whack_list; /* for WHACK_REREAD */ uint8_t 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 */ enum allow_global_redirect global_redirect; char *global_redirect_to; char *redirect_to; char *accept_redirect_to; char *active_redirect_dests; /* 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) */ 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_CERTS 0x08 /* update CERT(S) of connection(s) */ #define REREAD_ALL LRANGES(REREAD_SECRETS, REREAD_CERTS) /* 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 bool unpack_whack_msg(struct whackpacker *wp, struct logger *logger); extern void clear_end(const char *leftright, 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-4.14/include/where.h000066400000000000000000000025601457372064200163530ustar00rootroot00000000000000/* 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_FILENAME #define HERE_FILENAME (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) #endif /* * For appending: (in FUNC() at FILE:LINE) */ typedef const struct where { const char *func; const char *file; long line; } *where_t; #define HERE \ ({ \ static const struct where here = { \ .func = __func__, \ .file = HERE_FILENAME, \ .line = __LINE__, \ }; \ &here; \ }) #define PRI_WHERE "(%s() +%lu %s)" #define pri_where(SC) (SC)->func, (SC)->line, (SC)->file #endif libreswan-4.14/include/x509.h000066400000000000000000000106311457372064200157440ustar00rootroot00000000000000/* 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 /* dep:libnss3-dev */ #include "deltatime.h" #include "chunk.h" #include "err.h" #include "constants.h" #include "jambuf.h" /* for typedef jam_bytes_fn */ #include "asn1.h" struct logger; struct pubkey_list; struct fd; struct show; struct id; /* * 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; }; /* * check periodically for expired crls */ extern deltatime_t crl_check_interval; extern bool same_dn(asn1_t a, asn1_t b); extern bool match_dn(asn1_t a, asn1_t b, int *wildcards); extern bool match_dn_any_order_wild(const char *prefix, asn1_t a, asn1_t b, int *wildcards); extern bool dn_has_wildcards(asn1_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 show *s); extern void list_crls(struct show *s); extern void clear_ocsp_cache(void); /* * New NSS x509 converted functions */ extern SECItem same_shunk_as_dercert_secitem(shunk_t chunk); extern chunk_t get_dercert_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, struct logger *logger); extern bool trusted_ca(asn1_t a, asn1_t b, int *pathlen); extern CERTCertList *get_all_certificates(struct logger *logger); /* * 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; const char *str_dn(asn1_t dn, dn_buf *buf); const char *str_dn_or_null(asn1_t dn, const char *null_dn, dn_buf *buf); void jam_dn_or_null(struct jambuf *buf, asn1_t dn, const char *null_dn, jam_bytes_fn *jam_bytes); void jam_dn(struct jambuf *buf, asn1_t dn, jam_bytes_fn *jam_bytes); void jam_raw_dn(struct jambuf *buf, asn1_t dn, jam_bytes_fn *jam_bytes, bool nss_compatible); err_t parse_dn(asn1_t dn); #endif /* _X509_H */ libreswan-4.14/initsystems/000077500000000000000000000000001457372064200160355ustar00rootroot00000000000000libreswan-4.14/initsystems/Makefile000066400000000000000000000016041457372064200174760ustar00rootroot00000000000000# 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/targets.mk libreswan-4.14/initsystems/docker/000077500000000000000000000000001457372064200173045ustar00rootroot00000000000000libreswan-4.14/initsystems/docker/Makefile000066400000000000000000000027161457372064200207520ustar00rootroot00000000000000ifndef top_srcdir include ../../mk/dirs.mk endif LIBRESWANSRCDIR?=$(shell cd ../..; pwd) SRCDIR?=${LIBRESWANSRCDIR}/initsystems/docker/ INITDFILE=$(builddir)/ipsec.init SYSCONFIGFILE=$(builddir)/sysconfig.pluto SUBDIRS= SYSCONFIGDIR=$(SYSCONFDIR)/sysconfig SYSVINIT_DEFAULT_START?= include $(top_srcdir)/mk/config.mk # 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 include ${top_srcdir}/mk/targets.mk include ${top_srcdir}/mk/rules.mk libreswan-4.14/initsystems/docker/ipsec.init.in000077500000000000000000000143421457372064200217100ustar00rootroot00000000000000#!@SHELL_BINARY@ # -*- mode: sh; sh-shell: 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 (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-4.14/initsystems/docker/sysconfig.pluto.in000066400000000000000000000001061457372064200227770ustar00rootroot00000000000000# Put extra pluto command line options you want here PLUTO_OPTIONS="" libreswan-4.14/initsystems/openrc/000077500000000000000000000000001457372064200173235ustar00rootroot00000000000000libreswan-4.14/initsystems/openrc/Makefile000066400000000000000000000013361457372064200207660ustar00rootroot00000000000000ifndef top_srcdir include ../../mk/dirs.mk endif LIBRESWANSRCDIR?=$(shell cd ../..; pwd) SRCDIR?=${LIBRESWANSRCDIR}/initsystems/openrc/ INITDFILE=$(builddir)/ipsec.init SUBDIRS= include $(top_srcdir)/mk/config.mk # 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 include ${top_srcdir}/mk/targets.mk include ${top_srcdir}/mk/rules.mk libreswan-4.14/initsystems/openrc/ipsec.init.in000077500000000000000000000030471457372064200217270ustar00rootroot00000000000000#!/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-4.14/initsystems/rc.d/000077500000000000000000000000001457372064200166635ustar00rootroot00000000000000libreswan-4.14/initsystems/rc.d/Makefile000066400000000000000000000032771457372064200203340ustar00rootroot00000000000000ifndef top_srcdir include ../../mk/dirs.mk endif include $(top_srcdir)/mk/config.mk INSTINITSYSTEMFLAGS ?= $(INSTBINFLAGS) INITSYSTEMFILES = pluto # XXX: Hack to suppress the man page. Should one be added? PROGRAM_MANPAGE= local-base: $(INITSYSTEMFILES) local-install-base: $(INITSYSTEMFILES) @set -eu $(foreach file, $(INITSYSTEMFILES), ; \ if test ! -f $(INITSYSTEMDIR)/$(file) ; then \ echo $(builddir)$(file) '->' $(INITSYSTEMDIR)/$(file) ; \ mkdir -p $(INITSYSTEMDIR) ; \ $(INSTALL) $(INSTBINFLAGS) $(builddir)/$(file) $(INITSYSTEMDIR)/$(file) ; \ else \ echo "#" $(builddir)/$(file) '->' $(INITSYSTEMDIR)/$(file) ; \ fi \ ) @set -eu $(foreach file, $(INITSYSTEMFILES), ; \ echo $(builddir)$(file) '->' $(INITSYSTEMEXAMPLESDIR)/$(file) ; \ mkdir -p $(INITSYSTEMEXAMPLESDIR) ; \ $(INSTALL) $(INSTBINFLAGS) $(builddir)/$(file) $(INITSYSTEMEXAMPLESDIR)/$(file) ; \ ) ifneq ($(BSD_VARIANT),openbsd) @. /etc/rc.subr ; \ load_rc_config pluto ; \ case " $$rc_directories " in \ *" $(FINALINITSYSTEMDIR) "* ) ;; \ * ) \ echo "" ; \ echo "" ; \ echo " WARNING:" ; \ echo "" ; \ echo " FINALINITSYSTEMDIR=$(FINALINITSYSTEMDIR) is not included in" ; \ echo " the /etc/rc.conf variable:" ; \ echo "" ; \ echo " rc_directories=\"$${rc_directories}\"" ; \ echo "" ; \ ;; \ esac endif list-local-base: @set -eu $(foreach file, $(INITSYSTEMFILES), ; echo $(FINALINITSYSTEMDIR)/$(file)) @set -eu $(foreach file, $(INITSYSTEMFILES), ; echo $(INITSYSTEMEXAMPLESDIR)/$(file)) ) include $(top_srcdir)/mk/targets.mk include $(top_srcdir)/mk/rules.mk # assumes a single word pluto: $(BSD_VARIANT).sh $(TRANSFORM_DEPS) | $(builddir) $(transform_script) libreswan-4.14/initsystems/rc.d/freebsd.sh000077500000000000000000000010431457372064200206320ustar00rootroot00000000000000#!/bin/sh # mimic ipsec # PROVIDE: ike # REQUIRE: FILESYSTEMS isdnd kdc ppp # BEFORE: DAEMON mountcritremote # KEYWORD: nojailvnet . /etc/rc.subr name="pluto" desc="Libreswan IKE Daemon" required_modules=ipsec rcvar=${name}_enable command="@FINALLIBEXECDIR@/pluto" command_args="--logfile @FINALLOGDIR@/pluto.log --config @FINALSYSCONFDIR@/ipsec.conf --leak-detective" required_files="@FINALSYSCONFDIR@/ipsec.conf" pidfile="@IPSEC_RUNDIR@/${name}.pid" start_precmd="@FINALSBINDIR@/ipsec checknss" load_rc_config $name run_rc_command "$1" libreswan-4.14/initsystems/rc.d/netbsd.sh000077500000000000000000000007311457372064200205020ustar00rootroot00000000000000#!/bin/sh # mimic racoon # PROVIDE: ike # REQUIRE: isdnd kdc ppp # BEFORE: SERVERS # KEYWORD: shutdown $_rc_subr_loaded . /etc/rc.subr name="pluto" rcvar=$name pidfile="@IPSEC_RUNDIR@/${name}.pid" command="@FINALLIBEXECDIR@/pluto" command_args="--logfile @FINALLOGDIR@/pluto.log --config @FINALSYSCONFDIR@/ipsec.conf --leak-detective" required_files="@FINALSYSCONFDIR@/ipsec.conf" start_precmd="@FINALSBINDIR@/ipsec checknss" load_rc_config $name run_rc_command "$1" libreswan-4.14/initsystems/rc.d/openbsd.sh000077500000000000000000000005721457372064200206600ustar00rootroot00000000000000#!/bin/ksh daemon="@FINALLIBEXECDIR@/pluto" daemon_flags="--logfile @FINALLOGDIR@/pluto.log --config @FINALSYSCONFDIR@/ipsec.conf --leak-detective" . /etc/rc.d/rc.subr #pidfile="@IPSEC_RUNDIR@/${name}.pid" #required_files="@FINALSYSCONFDIR@/ipsec.conf" case $1 in onestart ) set start ;; onestop ) set stop ;; esac rc_pre() { @FINALSBINDIR@/ipsec checknss } rc_cmd $1 libreswan-4.14/initsystems/systemd/000077500000000000000000000000001457372064200175255ustar00rootroot00000000000000libreswan-4.14/initsystems/systemd/Makefile000066400000000000000000000064041457372064200211710ustar00rootroot00000000000000ifndef top_srcdir include ../../mk/dirs.mk endif UNITFILE=ipsec.service TMPFILESCONFIG=libreswan.conf include $(top_srcdir)/mk/config.mk # 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 include ${top_srcdir}/mk/targets.mk include ${top_srcdir}/mk/rules.mk libreswan-4.14/initsystems/systemd/check-systemd.sh000077500000000000000000000041761457372064200226370ustar00rootroot00000000000000#!/bin/sh # # Test / warn for broken systemd-resolved that mistakenly can # drop DNSSEC # records from the reply resulting in libreswan # resolving failures (even for non-DNSSEC domains!) # No known fixed version as of version 246 FIXED_VERSION=500 # Is systemd-resolved active ? /usr/bin/systemctl is-active systemd-resolved > /dev/null || exit 0 # Is /etc/resolv.conf pointing to systemd-resolved ? grep "nameserver 127.0.0.53" /etc/resolv.conf > /dev/null || exit 0 # Is the installed version of systemd broken ? VERSION=$(resolvectl --version |grep systemd | awk '{ print $2}') test ${VERSION} -ge ${FIXED_VERSION} && exit 0 # A broken systemd-resolved was found which will break libreswan's use # of the libunbound binary. # https://github.com/systemd/systemd/issues/4621" # https://github.com/systemd/systemd/issues/12317 # https://github.com/systemd/systemd/issues/17272 # https://bugzilla.redhat.com/show_bug.cgi?id=1879028 echo "------------------------------------------------------------------------" echo "You are using version ${VERSION} of systemd-resolved which breaks DNS security!" echo "------------------------------------------------------------------------" echo "This setup breaks any application (including libreswan) that uses a" echo "modern DNS library for additional DNS security and privacy features." echo "This bug was reported in 2016 and remains unfixed to date:" echo " https://github.com/systemd/systemd/issues/4621" echo "" echo "To resolve this issue, you can (in order of preference):" echo "- Upgrade systemd to version ${FIXED_VERSION}" echo "- Reconfigure NetworkManager to not list systemd-resolved in /etc/resolv.conf" echo "- Reconfigure /etc/resolv.conf so that NetworkManager won't configure" echo " systemd-resolved again by Removing or changing the line with" echo " # Generated by NetworkManager" echo " and then changing the nameserver entry for 127.0.0.53 to point to a real" echo " DNS server (eg 8.8.8.8 or 1.1.1.1 or 9.9.9.9 or your own)" echo "- Degrade libreswan's DNS security by adding the following line to" echo " /etc/ipsec.conf in the 'global setup' section:" echo " dnssec-enable=no" exit 1 libreswan-4.14/initsystems/systemd/ipsec.service.in000066400000000000000000000030361457372064200226210ustar00rootroot00000000000000[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@ # 12 is the shutdown while leaving kernel state. Restarting would still kill kernel state RestartPreventExitStatus=12 #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 # 12 is the exit code of pluto for shutting down "leaving state" ExecStopPost=/bin/bash -c 'if test "$EXIT_STATUS" != "12"; then /sbin/ip xfrm policy flush; /sbin/ip xfrm state flush; fi' ExecStopPost=@FINALSBINDIR@/ipsec --stopnflog [Install] WantedBy=multi-user.target libreswan-4.14/initsystems/systemd/libreswan.conf.in000066400000000000000000000000411457372064200227620ustar00rootroot00000000000000d @IPSEC_RUNDIR@ 755 root root - libreswan-4.14/initsystems/systemd/test.sh000077500000000000000000000003271457372064200210450ustar00rootroot00000000000000#!/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-4.14/initsystems/sysvinit/000077500000000000000000000000001457372064200177255ustar00rootroot00000000000000libreswan-4.14/initsystems/sysvinit/Makefile000066400000000000000000000027231457372064200213710ustar00rootroot00000000000000ifndef top_srcdir include ../../mk/dirs.mk endif LIBRESWANSRCDIR?=$(shell cd ../..; pwd) SRCDIR?=${LIBRESWANSRCDIR}/initsystems/sysvinit/ INITDFILE=$(builddir)/ipsec.init SYSCONFIGFILE=$(builddir)/sysconfig.pluto SUBDIRS= SYSCONFIGDIR=$(SYSCONFDIR)/sysconfig SYSVINIT_DEFAULT_START?= include $(top_srcdir)/mk/config.mk # 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 include ${top_srcdir}/mk/targets.mk include ${top_srcdir}/mk/rules.mk libreswan-4.14/initsystems/sysvinit/init.debian.in000066400000000000000000000122641457372064200224460ustar00rootroot00000000000000 FIXME #!@SHELL_BINARY@ # -*- mode: sh; sh-shell: 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 ### 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-4.14/initsystems/sysvinit/init.rhel000077500000000000000000000147241457372064200215570ustar00rootroot00000000000000#!/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-4.14/initsystems/sysvinit/ipsec.init.in000077500000000000000000000171131457372064200223300ustar00rootroot00000000000000#!@SHELL_BINARY@ # -*- mode: sh; sh-shell: 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: @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 @FINALINITDDIR@/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 @FINALINITDDIR@/functions ]; then . @FINALINITDDIR@/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-4.14/initsystems/sysvinit/sysconfig.pluto.in000066400000000000000000000001071457372064200234210ustar00rootroot00000000000000# Put extra pluto command line options you want here PLUTO_OPTIONS=" " libreswan-4.14/initsystems/upstart/000077500000000000000000000000001457372064200175375ustar00rootroot00000000000000libreswan-4.14/initsystems/upstart/Makefile000066400000000000000000000016521457372064200212030ustar00rootroot00000000000000ifndef 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 $(top_srcdir)/mk/config.mk # 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 include ${top_srcdir}/mk/targets.mk include ${top_srcdir}/mk/rules.mk libreswan-4.14/initsystems/upstart/default.pluto.in000066400000000000000000000001061457372064200226520ustar00rootroot00000000000000# Put extra pluto command line options you want here PLUTO_OPTIONS="" libreswan-4.14/initsystems/upstart/ipsec.conf.in000066400000000000000000000017501457372064200221210ustar00rootroot00000000000000# 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-4.14/kvm000077500000000000000000000244771457372064200142030ustar00rootroot00000000000000#!/bin/bash # uses bash's define set -e # possible hostnames, always implies first # gmake isn't on debian? gnumake=make platforms="fedora freebsd netbsd openbsd" buildhosts=${platforms} basehosts= upgradehosts= for p in ${platforms} ; do basehosts="${basehosts} ${p}-base ${p}-upgrade" upgradehosts="${upgradehosts} ${p}-upgrade ${p}-upgrade" done # eat newlines testhosts=$(echo $($(dirname $0)/testing/utils/kvmhosts.sh)) hosts="${testhosts} ${buildhosts} ${basehosts} ${upgradehosts}" # Anything matching '^____[-a-z]' is considered a command ('_' denotes # a space). pass1help() { cat < specify baseline directory to compare against --baseline-passed specify baseline directory to compare against --baseline-failed specify baseline directory to compare against To log into a domain: sh [ ] start a shell on which can be a: test domain: ${testhosts} build domain: ${platforms} base domain: ${basehosts} upgrade domain: ${upgradehosts} EOF } pass1=$(pass1help | awk '/^ [-a-z]/ { printf " %s ", $1 }' ; echo ${host}) # Anything matching '^____[-a-z]' is considered a command (_ denotes a # space). pass2help() { cat < ... ] run the testsuite Examine the test results: diffs [ ... ] show differences (for the specified tests) exit non-zero when differences are found results [ ... ] list test results (for the specified tests) exit non-zero when failures are found Re-run, or run a-new the testsuite: recheck [ ... ] re-run the testsuite clean clean the test environment (delete test and build domains and build trees) check-clean delete the test results (leave the build trees and domains alone) keys update the keys used for testing purge delete build and test domains delete any build trees delete any keys Update the expected test results (and GIT repository): patch [ ... ] apply test differences (to the specified test directories) add [ ... ] <> (the specified test directories) Manipulate the kvmrunner process: status report the status of the running test kill kill the running testsuite Step wize create/delete the domains (just use ./kvm install): base[-PLATFORM] (re)create a domain containing the base OS creates: ${basehosts} upgrade[-PLATFORM] (re)create the upgrade domain from the base domain installs missing + upgrades existing packages on base domain creates: ${upgradehosts} transmogrify[-PLATFORM] (re)create the build domain from the upgrade domain transmogrifies the domain ready for building and testing creates: ${platforms} build[-PLATFORM] build/install libreswan on the build domains uses: ${platforms} install[-PLATFORM] build/install libreswan clones build domains to create the test domains Stepwize delete the domains (just use ./kvm purge): shutdown[-PLATFORM] shutdown all domains uninstall[-PLATFORM] delete test-domains, PLATFORM (but leave the build trees and base domains alone) downgrade[-PLATFORM] delete test-domains, PLATFORM, PLATFORM.upgrade remove any updates to the base domains demolish[-PLATFORM] delete test-domains, PLATFORM, PLATFORM.upgrade, PLATFORM.base delete all domains and all builds EOF } pass2=$(pass2help | awk -v "plat=${platforms}" -- ' BEGIN { split(plat, platforms) } /^ [a-z]*.-PLATFORM.$/ { t=$1 sub(/[^a-z]*$/,"",t) printf " %s ", t for (i in platforms) { printf " %s-%s ", t, platforms[i] } next } /^ [-a-z]*/ { printf " %s ", $1 }') # Invoked by completer with: # # $0 ? # # ${pass1}, ${pass2} and ${hosts} contain completion values. if test "$1" = $0 -a $# -eq 3 ; then command=$1 word=$2 previous=$3 # hack to detect first vs later argument if test "${previous}" = "${command}" ; then # first command compgen -W "${pass1} ${pass2}" "${word}" | sort elif test "${previous}" = sh ; then # pass 1 command compgen -W "${hosts}" "${word}" else case $pass2 in *" ${word}"* ) # word looks to be matching a command (or is empty), # expand to either or compgen -o plusdirs -W "${pass2}" "${word}" ;; * ) # doesn't match a command, so throw in the testing # directory as a quick expansion compgen -o plusdirs -W "${pass2}" -G "testing/pluto/${word}*" "${word}" ;; esac fi exit 0 fi # Translate ../../../kvm [...] into ./kvm [...] and with no [...] # implying "clean". Do this before checking $#=0 as this can add the # missing parameter. if test $(realpath $(dirname $0)) != $(realpath ${PWD}) ; then if test $# -eq 0 ; then set -- check ${PWD} else declare -a args i=0 for arg in "$@" ; do if test -d "${arg}" ; then dir=true args[$i]=$(realpath ${arg}) elif test "${arg}" = check ; then check=true args[$i]="${arg}" else args[$i]="${arg}" fi i=$((i + 1)) done set -- "${args[@]}" fi cd $(dirname $0) echo "$@" fi # Finally is there at least one parameter? if test $# -eq 0; then cat < ... ... ... EOF pass1help echo pass2help cat <&2 exec testing/utils/kvmsh.py ${host} "$@" ;; # wrappers modified ) modified=$(git status testing/pluto/ \ | awk '/(modified|deleted|renamed|new file):/ { print $NF }' \ | grep '/.*/.*/' \ | cut -d/ -f1-3 \ | sort -u) if test -z "${modified}" ; then echo "no modified tests" 1>&2 exit 1 fi ;; baseline | baseline-passed | baseline-failed ) if test -z "${__baseline}" ; then echo "no KVM_BASELINE" 1&2 exit 1 fi baseline=$1 ;; * ) # either a directory; or a hostname case " ${hosts} " in *" $1 "* ) host=${prefix}$1 ; shift echo "Connecting to ${host}" 1>&2 exec testing/utils/kvmsh.py ${host} "$@" ;; * ) # check first trailing argument is a directory if test ! -d "$1" ; then if test -z "${ops[*]}" ; then echo "unknown command: $1" 1>&2 else echo "not a directory: $1" 1>&2 fi exit 1 fi break esac esac ;; esac shift done if test -n "${modified}" ; then if test -z "${ops[*]}" ; then echo "${modified}" exit 0 elif test $# -ne 0 ; then echo "both modified and tests specified" 1>&2 exit 1 fi set -- ${modified} elif test $# -eq 0 ; then set -- ${kvm_testingdir} fi if test -z "${ops[*]}" ; then echo "nothing to do!" 1>&2 exit 1 fi results_command() { if test -n "${baseline}" ; then ./testing/utils/kvmresults.py --test-status "${kvm_test_status}" ${kvm_test_flags} ${__baseline} "$@" \ | grep --line-buffered -v -e baseline:untested \ | grep --line-buffered -e ${baseline} else ./testing/utils/kvmresults.py --test-status "${kvm_test_status}" ${kvm_test_flags} "$@" status=$? fi } diffs_command() { if test -n "${baseline}" ; then ./testing/utils/kvmresults.py --test-status "${kvm_test_status}" ${kvm_test_flags} ${__baseline} --stats none "$@" \ | grep --line-buffered -v -e baseline:untested \ | grep --line-buffered -e "${baseline}" \ | while read test eol ; do ./testing/utils/kvmresults.py --stats none --print diffs ${test} done else ./testing/utils/kvmresults.py --test-status "${kvm_test_status}" ${kvm_test_flags} --stats none --print diffs "$@" status=$? fi } # second pass status=0 for op in "${ops[@]}" ; do case ${op} in add ) git add "$@" ;; kill ) ${gnumake} kvm-${op} ;; base* | upgrade* | transmogrify* | build* | install* | \ shutdown* | uninstall* | downgrade* | demolish* | \ status | check-clean | clean ) echo ${gnumake} kvm-${op} ${gnumake} kvm-${op} || exit $? ;; check | recheck ) echo ${op}: "$@" ${gnumake} kvm-${op} KVM_TESTS="$*" || exit $? ;; diffs ) diffs_command "$@" ;; results ) results_command "$@" ;; patch ) diffs_command "$@" | patch -p1 ;; keys ) ${gnumake} kvm-keys-clean kvm-keys esac done exit ${status} libreswan-4.14/lib/000077500000000000000000000000001457372064200142105ustar00rootroot00000000000000libreswan-4.14/lib/COPYING.LIB000066400000000000000000000614471457372064200156640ustar00rootroot00000000000000 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-4.14/lib/Makefile000066400000000000000000000016161457372064200156540ustar00rootroot00000000000000# Makefile for the 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)/mk/config.mk SUBDIRS=libswan libwhack libipsecconf SUBDIRS += liblswtool include $(top_srcdir)/mk/targets.mk libreswan-4.14/lib/libipsecconf/000077500000000000000000000000001457372064200166505ustar00rootroot00000000000000libreswan-4.14/lib/libipsecconf/Makefile000066400000000000000000000075211457372064200203150ustar00rootroot00000000000000# 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 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} 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.lex : 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 BISONOSFLAGS=-g --verbose 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-4.14/lib/libipsecconf/confread.c000066400000000000000000001432521457372064200206040ustar00rootroot00000000000000/* 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 * Copyright (C) 2017 Mayank Totale * Copyright (C) 2020 Yulia Kuzovkova * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT 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 /* for AF_UNSPEC */ #include "lswalloc.h" #include "ip_address.h" #include "ip_info.h" #include "hunk.h" /* for char_is_space() */ #include "ip_cidr.h" #include "ttodata.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 */ #include "lswlog.h" #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_LOGTIME, true); SOPT(KBF_LOGAPPEND, true); SOPT(KBF_LOGIP, true); SOPT(KBF_AUDIT_LOG, true); SOPT(KBF_UNIQUEIDS, true); SOPT(KBF_LISTEN_UDP, true); SOPT(KBF_LISTEN_TCP, false); SOPT(KBF_DO_DNSSEC, true); SOPT(KBF_PERPEERLOG, false); SOPT(KBF_IKEBUF, IKE_BUF_AUTO); SOPT(KBF_IKE_ERRQUEUE, true); SOPT(KBF_NFLOG_ALL, 0); /* disabled per default */ #ifdef XFRM_LIFETIME_DEFAULT SOPT(KBF_XFRMLIFETIME, XFRM_LIFETIME_DEFAULT); /* not used by pluto itself */ #endif SOPT(KBF_NHELPERS, -1); /* see also plutomain.c */ SOPT(KBF_KEEPALIVE, 0); /* config setup */ SOPT(KBF_DDOS_IKE_THRESHOLD, DEFAULT_IKE_SA_DDOS_THRESHOLD); SOPT(KBF_MAX_HALFOPEN_IKE, DEFAULT_MAXIMUM_HALFOPEN_IKE_SA); SOPT(KBF_SHUNTLIFETIME_MS, PLUTO_SHUNT_LIFE_DURATION_DEFAULT * 1000); /* 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_AGE_MS, OCSP_DEFAULT_CACHE_MIN_AGE * 1000); SOPT(KBF_OCSP_CACHE_MAX_AGE_MS, OCSP_DEFAULT_CACHE_MAX_AGE * 1000); 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, "default dnssec rootkey file"); cfg->setup.strings[KSF_NSSDIR] = clone_str(IPSEC_NSSDIR, "default ipsec nssdir"); cfg->setup.strings[KSF_SECRETSFILE] = clone_str(IPSEC_SECRETS_FILE, "default ipsec.secrets file"); cfg->setup.strings[KSF_DUMPDIR] = clone_str(DEFAULT_RUNDIR, "default dumpdir"); cfg->setup.strings[KSF_IPSECDIR] = clone_str(IPSEC_CONFDDIR, "default ipsec.d dir"); /* ==== 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, true); 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); DOPT(KNCF_TCP, IKE_TCP_NO); DOPT(KNCF_REMOTE_TCPPORT, NAT_IKE_UDP_PORT); /* 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_IKE_LIFETIME_MS, IKE_SA_LIFETIME_DEFAULT * 1000); DOPT(KNCF_REPLAY_WINDOW, IPSEC_SA_DEFAULT_REPLAY_WINDOW); DOPT(KNCF_RETRANSMIT_TIMEOUT_MS, RETRANSMIT_TIMEOUT_DEFAULT * 1000); DOPT(KNCF_RETRANSMIT_INTERVAL_MS, RETRANSMIT_INTERVAL_DEFAULT_MS); DOPT(KNCF_IPSEC_LIFETIME_MS, IPSEC_SA_LIFETIME_DEFAULT * 1000); DOPT(KNCF_REKEYMARGIN_MS, SA_REPLACEMENT_MARGIN_DEFAULT * 1000); DOPT(KNCF_IPSEC_MAXBYTES, IPSEC_SA_MAX_OPERATIONS); DOPT(KNCF_IPSEC_MAXPACKETS, IPSEC_SA_MAX_OPERATIONS); 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, UINT32_MAX); # undef DOPT d->ike_version = IKEv2; d->policy = (POLICY_TUNNEL | POLICY_ENCRYPT | POLICY_PFS | /* ike_frag=yes */ POLICY_IKE_FRAG_ALLOW | /* esn=either */ POLICY_ESN_NO | POLICY_ESN_YES); d->authby = AUTHBY_NONE; /* blank goes to defaults */ d->prospective_shunt = SHUNT_UNSET; d->negotiation_shunt = SHUNT_UNSET; d->failure_shunt = SHUNT_UNSET; d->sighash_policy = POL_SIGHASH_DEFAULTS; d->left.leftright = "left"; d->left.host_family = NULL; d->left.addr = unset_address; d->left.nexttype = KH_NOTSET; d->left.nexthop = unset_address; d->right.leftright = "right"; d->right.host_family = NULL; d->right.addr = unset_address; d->right.nexttype = KH_NOTSET; d->right.nexthop = unset_address; d->xfrm_if_id = UINT32_MAX; /* 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.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' && !char_isspace(*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: case kt_binary: case kt_byte: /* 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_pubkey: 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; } /** * 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. It sets the conn's sec_label * into its left/right struct end options * * @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, starter_errors_t *perrl, struct logger *logger) { const char *leftright = end->leftright; err_t er = NULL; bool err = false; pexpect(end->host_family == &ipv4_info || end->host_family == &ipv6_info); /* i.e., not NULL */ # define ERR_FOUND(...) { starter_error_append(perrl, __VA_ARGS__); err = true; } if (!end->options_set[KNCF_IP]) conn_st->state = STATE_INCOMPLETE; /* validate the KSCF_IP/KNCF_IP */ end->addrtype = end->options[KNCF_IP]; switch (end->addrtype) { case KH_ANY: end->addr = unset_address; 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, end->host_family, &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 = ttoaddress_num(shunk1(end->strings[KNCF_IP]), end->host_family, &end->addr); if (er != NULL) { /* not an IP address, so set the type to the string */ end->addrtype = KH_IPHOSTNAME; } else { pexpect(end->host_family == address_type(&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: starter_log(LOG_LEVEL_DEBUG, "starter: %s is KH_DEFAULTROUTE", leftright); break; case KH_NOTSET: /* cannot error out here, it might be a partial also= conn */ break; } if (end->strings_set[KSCF_VTI_IP]) { const char *value = end->strings[KSCF_VTI_IP]; err_t oops = numeric_to_cidr(shunk1(value), NULL, &end->vti_ip); if (oops != NULL) { ERR_FOUND("bad addr %s%s=%s [%s]", leftright, "vti", value, oops); } oops = cidr_specified(end->vti_ip); if (oops != NULL) { ERR_FOUND("bad addr %s%s=%s [%s]", leftright, "vti", value, oops); } /* XXX: check type? */ } /* 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:")) { if (conn_st->ike_version != IKEv1) { ERR_FOUND("The vnet: and vhost: keywords are only valid for IKEv1 connections"); } er = NULL; end->virt = clone_str(value, "validate_end item"); } else { end->has_client = true; er = ttosubnet(shunk1(value), AF_UNSPEC, '0', &end->subnet, logger); } if (er != NULL) ERR_FOUND("bad subnet %ssubnet=%s [%s]", leftright, value, er); } /* * validate the KSCF_NEXTHOP; set nexthop address to * something consistent, by default */ end->nexthop = end->host_family->address.unspec; if (end->strings_set[KSCF_NEXTHOP]) { char *value = end->strings[KSCF_NEXTHOP]; if (strcaseeq(value, "%defaultroute")) { end->nexttype = KH_DEFAULTROUTE; } else { ip_address nexthop = unset_address; #ifdef USE_DNSSEC if (ttoaddress_num(shunk1(value), end->host_family, &nexthop) != NULL) { starter_log(LOG_LEVEL_DEBUG, "Calling unbound_resolve() for %snexthop value", leftright); if (!unbound_resolve(value, end->host_family, &nexthop, logger)) ERR_FOUND("bad value for %snexthop=%s\n", leftright, value); } #else err_t e = ttoaddress_dns(shunk1(value), end->host_family, &nexthop); if (e != NULL) { ERR_FOUND("bad value for %snexthop=%s [%s]", leftright, value, e); } #endif end->nexthop = nexthop; end->nexttype = KH_IPADDR; } } else { end->nexthop = end->host_family->address.unspec; 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] = '\\'; } } } static const struct { enum ipseckey_algorithm_type alg; enum keyword_string_conn_field kscf; const char *name; } keys[] = { { .alg = IPSECKEY_ALGORITHM_RSA, KSCF_RSASIGKEY, "rsasigkey", }, { .alg = IPSECKEY_ALGORITHM_ECDSA, KSCF_ECDSAKEY, "ecdsakey", }, { .alg = IPSECKEY_ALGORITHM_X_PUBKEY, KSCF_PUBKEY, "pubkey", }, }; FOR_EACH_ELEMENT(key, keys) { if (!end->options_set[key->kscf]) { continue; } if (end->pubkey != NULL) { ERR_FOUND("duplicate public key"); } end->pubkey_type = end->options[key->kscf]; end->pubkey_alg = key->alg; switch (end->options[key->kscf]) { case PUBKEY_DNSONDEMAND: end->key_from_DNS_on_demand = true; break; default: end->key_from_DNS_on_demand = false; /* validate the KSCF_RSASIGKEY1/RSASIGKEY2 */ if (end->strings[key->kscf] != NULL) { char *value = end->strings[key->kscf]; pfreeany(end->pubkey); end->pubkey = clone_str(value, "end->pubkey"); } } } /* 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]; /* * XXX: suspect this lookup should be forced to use * the same family as the client. */ ip_address sourceip = unset_address; #ifdef USE_DNSSEC /* try numeric first */ err_t e = ttoaddress_num(shunk1(value), NULL/*UNSPEC*/, &sourceip); if (e != NULL) { starter_log(LOG_LEVEL_DEBUG, "Calling unbound_resolve() for %ssourceip value", leftright); if (!unbound_resolve(value, &ipv4_info, &end->sourceip, logger) && !unbound_resolve(value, &ipv6_info, &end->sourceip, logger)) ERR_FOUND("bad value for %ssourceip=%s\n", leftright, value); } #else /* try numeric then DNS */ err_t e = ttoaddress_dns(shunk1(value), AF_UNSPEC, &sourceip); if (e != NULL) { ERR_FOUND("bad addr %ssourceip=%s [%s]", leftright, value, e); } #endif end->sourceip = sourceip; if (!end->has_client) { end->subnet = subnet_from_address(end->sourceip); end->has_client = true; } if (end->strings_set[KSCF_INTERFACE_IP]) { ERR_FOUND("cannot 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]) { char *value = end->strings[KSCF_PROTOPORT]; err_t ugh = ttoprotoport(value, &end->protoport); 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 (range_type(&end->pool_range) == &ipv6_info && !end->pool_range.is_subnet) { ERR_FOUND("bad IPv6 %saddresspool=%s not subnet", leftright, addresspool); } } if (end->strings_set[KSCF_INTERFACE_IP]) { const char *value = end->strings[KSCF_INTERFACE_IP]; err_t oops = numeric_to_cidr(shunk1(value), NULL, &end->ifaceip); if (oops != NULL) { ERR_FOUND("bad addr %s%s=%s [%s]", leftright, "interface-ip", value, oops); } oops = cidr_specified(end->ifaceip); if (oops != NULL) { ERR_FOUND("bad addr %s%s=%s [%s]", leftright, "interface-ip", value, oops); } if (end->strings_set[KSCF_SOURCEIP]) { ERR_FOUND("cannot 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_field(struct starter_conn *conn, const struct section_list *sl, enum keyword_set assigned_value, starter_errors_t *perrl, const struct kw_list *kw, const char *leftright, ksf *the_strings, str_set *set_strings, unsigned str_floor, unsigned str_roof, knf *the_options, int_set *set_options, unsigned opt_floor, unsigned opt_roof) { bool serious_err = false; 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%s' in conn %s while processing def %s", leftright, 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_pubkey: 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%s' in conn %s while processing def %s", leftright, 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: case kt_binary: case kt_byte: /* 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%s' in conn %s while processing def %s", leftright, 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 bool translate_leftright(struct starter_conn *conn, const struct section_list *sl, enum keyword_set assigned_value, starter_errors_t *perrl, const struct kw_list *kw, struct starter_end *this) { return translate_field(conn, sl, assigned_value, perrl, kw, /*leftright*/this->leftright, /*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); } 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; } if (kw->keyword.keydef->validity & kv_leftright) { if (kw->keyword.keyleft) { serious_err |= translate_leftright(conn, sl, assigned_value, perrl, kw, &conn->left); } if (kw->keyword.keyright) { serious_err |= translate_leftright(conn, sl, assigned_value, perrl, kw, &conn->right); } } else { serious_err |= translate_field(conn, sl, assigned_value, perrl, kw, /*leftright*/"", /*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); } } 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, struct logger *logger) { 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_TUNNEL; conn->prospective_shunt = SHUNT_TRAP; break; case KS_TRANSPORT: conn->policy &= ~POLICY_TUNNEL; conn->prospective_shunt = SHUNT_TRAP; break; case KS_PASSTHROUGH: conn->policy &= ~(POLICY_ENCRYPT | POLICY_AUTHENTICATE | POLICY_TUNNEL); conn->authby = AUTHBY_NONE; conn->prospective_shunt = SHUNT_PASS; break; case KS_DROP: conn->policy &= ~(POLICY_ENCRYPT | POLICY_AUTHENTICATE | POLICY_TUNNEL); conn->authby = AUTHBY_NONE; conn->prospective_shunt = SHUNT_DROP; break; case KS_REJECT: conn->policy &= ~(POLICY_ENCRYPT | POLICY_AUTHENTICATE | POLICY_TUNNEL); conn->authby = AUTHBY_NONE; conn->prospective_shunt = SHUNT_REJECT; break; } } if (conn->options_set[KNCF_NEGOTIATIONSHUNT]) { switch (conn->options[KNCF_NEGOTIATIONSHUNT]) { case KNS_NEGO_PASS: conn->negotiation_shunt = SHUNT_PASS; break; case KNS_NEGO_HOLD: conn->negotiation_shunt = SHUNT_HOLD; break; } } if (conn->options_set[KNCF_FAILURESHUNT]) { switch (conn->options[KNCF_FAILURESHUNT]) { case KFS_FAIL_NONE: conn->failure_shunt = SHUNT_NONE; break; case KFS_FAIL_PASS: conn->failure_shunt = SHUNT_PASS; break; case KFS_FAIL_DROP: conn->failure_shunt = SHUNT_DROP; break; case KFS_FAIL_REJECT: conn->failure_shunt = SHUNT_REJECT; break; } } KW_POLICY_FLAG(KNCF_COMPRESS, POLICY_COMPRESS); KW_POLICY_FLAG(KNCF_PFS, POLICY_PFS); 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); KW_POLICY_FLAG(KNCF_INTERMEDIATE, POLICY_INTERMEDIATE); KW_POLICY_FLAG(KNCF_IGNORE_PEER_DNS, POLICY_IGNORE_PEER_DNS); 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); str_to_conn(sec_label, KSCF_SA_SEC_LABEL); /* copied to left/right later */ 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->ike_version = IKEv1; break; case fo_propose: case fo_insist: conn->ike_version = IKEv2; break; } } if (conn->options_set[KNCF_SEND_REDIRECT]) { if (conn->ike_version >= IKEv2) { 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 (conn->ike_version >= IKEv2) { 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->ike_version >= IKEv2) { 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; } } /* * Read in the authby= string and translate to policy bits. * * This is the symmetric (left+right) version. There is also * leftauth=/rightauth= version stored in 'end' * * authby=secret|rsasig|null|never|rsa-HASH * * using authby=rsasig results in both 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]) { conn->sighash_policy = LEMPTY; conn->authby = (struct authby) {0}; shunk_t curseby = shunk1(conn->strings[KSCF_AUTHBY]); while (true) { shunk_t val = shunk_token(&curseby, NULL/*delim*/, ", "); if (val.ptr == NULL) { break; } #if 0 if (val.len == 0) { /* ignore empty fields? */ continue; } #endif /* Supported for IKEv1 and IKEv2 */ if (hunk_streq(val, "secret")) { conn->authby.psk = true;; } else if (hunk_streq(val, "rsasig") || hunk_streq(val, "rsa")) { conn->authby.rsasig = true; conn->authby.rsasig_v1_5 = true; conn->sighash_policy |= POL_SIGHASH_SHA2_256; conn->sighash_policy |= POL_SIGHASH_SHA2_384; conn->sighash_policy |= POL_SIGHASH_SHA2_512; } else if (hunk_streq(val, "never")) { conn->authby.never = true; /* everything else is only supported for IKEv2 */ } else if (conn->ike_version == IKEv1) { starter_error_append(perrl, "ikev1 connection must use authby= of rsasig, secret or never"); return true; } else if (hunk_streq(val, "null")) { conn->authby.null = true; } else if (hunk_streq(val, "rsa-sha1")) { conn->authby.rsasig_v1_5 = true; } else if (hunk_streq(val, "rsa-sha2")) { conn->authby.rsasig = true; conn->sighash_policy |= POL_SIGHASH_SHA2_256; conn->sighash_policy |= POL_SIGHASH_SHA2_384; conn->sighash_policy |= POL_SIGHASH_SHA2_512; } else if (hunk_streq(val, "rsa-sha2_256")) { conn->authby.rsasig = true; conn->sighash_policy |= POL_SIGHASH_SHA2_256; } else if (hunk_streq(val, "rsa-sha2_384")) { conn->authby.rsasig = true; conn->sighash_policy |= POL_SIGHASH_SHA2_384; } else if (hunk_streq(val, "rsa-sha2_512")) { conn->authby.rsasig = true; conn->sighash_policy |= POL_SIGHASH_SHA2_512; } else if (hunk_streq(val, "ecdsa") || hunk_streq(val, "ecdsa-sha2")) { conn->authby.ecdsa = true; conn->sighash_policy |= POL_SIGHASH_SHA2_256; conn->sighash_policy |= POL_SIGHASH_SHA2_384; conn->sighash_policy |= POL_SIGHASH_SHA2_512; } else if (hunk_streq(val, "ecdsa-sha2_256")) { conn->authby.ecdsa = true; conn->sighash_policy |= POL_SIGHASH_SHA2_256; } else if (hunk_streq(val, "ecdsa-sha2_384")) { conn->authby.ecdsa = true; conn->sighash_policy |= POL_SIGHASH_SHA2_384; } else if (hunk_streq(val, "ecdsa-sha2_512")) { conn->authby.ecdsa = true; conn->sighash_policy |= POL_SIGHASH_SHA2_512; } else if (hunk_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; } } } /* * 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_DECAP_DSCP | POLICY_NOPMTUDISC) & /* remove IKE related options */ ~(POLICY_IKE_FRAG_ALLOW | POLICY_IKE_FRAG_FORCE)); } /* * 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 */ const struct ip_info *afi = aftoinfo(conn->options[KNCF_HOSTADDRFAMILY]); if (afi == NULL) { FOR_EACH_THING(end, &conn->left, &conn->right) { FOR_EACH_THING(ips, end->strings[KNCF_IP], end->strings[KNCF_NEXTHOP]) { if (ips == NULL) { continue; } /* IPv6 like address */ if (strchr(ips, ':') != NULL || streq(ips, "%defaultroute6") || streq(ips, "%any6")) { afi = &ipv6_info; break; } } if (afi != NULL) { break; } } } if (afi == NULL) { afi = &ipv4_info; } conn->left.host_family = conn->right.host_family = afi; err |= validate_end(conn, &conn->left, perrl, logger); err |= validate_end(conn, &conn->right, perrl, logger); /* * 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]; if (conn->desired_state == STARTUP_KEEP) conn->policy |= POLICY_UP; /* auto=keep means once up, keep up */ 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(sec_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(pubkey); 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, struct logger *logger) { 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, logger); 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, struct logger *logger) { 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], logger); #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, true/*default conn*/, perrl, logger); } } /* * 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/*default conn*/, perrl, logger); } } 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(sec_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(pubkey); 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-4.14/lib/libipsecconf/confwrite.c000066400000000000000000000333671457372064200210300ustar00rootroot00000000000000/* * 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 "constants.h" #include "lswlog.h" #include "lmod.h" #include "ip_address.h" #include "sparse_names.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) { char *sep = ""; for (const struct sparse_name *kev = k->validenum; kev->name != NULL; kev++) { unsigned int mask = kev->value; if (mask != 0 && (val & mask) == mask) { fprintf(out, "%s%s%s", sep, prefix, kev->name); sep = " "; } } } static void confwrite_int(FILE *out, const 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_pubkey: 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 { for (const struct sparse_name *kev = k->validenum; kev->name != NULL; kev++) { /* XXX: INT vs UNSIGNED magic? */ if ((int)kev->value == val) { break; } } 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) { JAMBUF(buf) { jam_lset_short(buf, k->info->names, ",", val); fprintf(out, "\t%s%s=\""PRI_SHUNK"\"\n", side, k->keyname, pri_shunk(jambuf_as_shunk(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_binary: case kt_byte: case kt_number: if (options_set[k->field]) fprintf(out, "\t%s%s=%jd\n", side, k->keyname, options[k->field]); } } } static void confwrite_str(FILE *out, const 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_pubkey: 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: case kt_binary: case kt_byte: /* 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) { const char *side = end->leftright; 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); /* * We don't write out end->strings_set[KSCF_SEC_LABEL] as it is printed * from the symmetric conn option "policylabel" */ 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 (!subnet_eq_address(end->subnet, end->addr)) { subnet_buf as; fprintf(out, "\t%ssubnet=%s\n", side, str_subnet(&end->subnet, &as)); } } if (cidr_is_specified(end->vti_ip)) { cidr_buf as; fprintf(out, "\t%svti=%s\n", side, str_cidr(&end->vti_ip, &as)); } if (cidr_is_specified(end->ifaceip)) { cidr_buf as; fprintf(out, "\t%sinterface-ip=%s\n", side, str_cidr(&end->ifaceip, &as)); } if (end->pubkey != NULL && end->pubkey[0] != '\0') { enum_buf pkb; fprintf(out, "\t%s%s=%s\n", side, str_enum(&ipseckey_algorithm_config_names, end->pubkey_alg, &pkb), end->pubkey); } if (end->protoport.is_set) { protoport_buf buf; fprintf(out, "\t%sprotoport=%s\n", side, str_protoport(&end->protoport, &buf)); } 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); confwrite_side(out, &conn->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; case STARTUP_KEEP: dsn = "keep"; break; } cwf("auto", dsn); } if (conn->policy != LEMPTY || conn->prospective_shunt != SHUNT_UNSET) { lset_t phase2_policy = (conn->policy & (POLICY_AUTHENTICATE | POLICY_ENCRYPT)); enum shunt_policy shunt_policy = conn->prospective_shunt; 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 SHUNT_UNSET: case SHUNT_TRAP: cwf("type", conn->policy & POLICY_TUNNEL? "tunnel" : "transport"); cwpb("compress", POLICY_COMPRESS); cwpb("pfs", POLICY_PFS); cwpbf("ikepad", POLICY_NO_IKEPAD); if (conn->left.options[KNCF_AUTH] == k_unset || conn->right.options[KNCF_AUTH] == k_unset) { authby_buf ab; cwf("authby", str_authby(conn->authby, &ab)); } { 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; switch (conn->ike_version) { case IKEv1: v2ps = "no"; break; case IKEv2: v2ps = "yes"; break; default: v2ps = "UNKNOWN"; break; } 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 SHUNT_PASS: cwf("type", "passthrough"); break; case SHUNT_DROP: cwf("type", "drop"); break; case SHUNT_REJECT: cwf("type", "reject"); break; case SHUNT_NONE: cwf("type", "none"); /* can't happen */ break; case SHUNT_HOLD: cwf("type", "hold"); /* can't happen */ 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-4.14/lib/libipsecconf/interfaces.c000066400000000000000000000051661457372064200211470ustar00rootroot00000000000000/* 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 "lsw_socket.h" #include "constants.h" #include "ip_endpoint.h" #include "ip_address.h" #include "passert.h" #include "ipsecconf/interfaces.h" #include "ipsecconf/exec.h" #include "ipsecconf/starterlog.h" #include "lswlog.h" /* for pexpect() */ #include "ip_info.h" #include "ip_protocol.h" #include "ip_sockaddr.h" bool starter_iface_find(const char *iface, const struct ip_info *family, ip_address *dst, ip_address *nh) { /* XXX: danger REQ is recycled by ioctl() calls */ struct ifreq req; if (iface == NULL) return false; /* ??? can this ever happen? */ int sock = cloexec_socket(family->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 (nh != NULL && (req.ifr_flags & IFF_POINTOPOINT) != 0x0 && (ioctl(sock, SIOCGIFDSTADDR, &req) == 0)) { if (req.ifr_addr.sa_family == family->af) { ip_address nh_address; ip_port nh_port; happy(sockaddr_to_address_port(&req.ifr_addr, family->sockaddr_size, &nh_address, &nh_port)); pexpect(hport(nh_port) == 0); *nh = nh_address; } } /* get DST */ if (dst != NULL && ioctl(sock, SIOCGIFADDR, &req) == 0) { if (req.ifr_addr.sa_family == family->af) { ip_address dst_address; ip_port dst_port; happy(sockaddr_to_address_port(&req.ifr_addr, family->sockaddr_size, &dst_address, &dst_port)); pexpect(hport(dst_port) == 0); *dst = dst_address; } } close(sock); return true; } libreswan-4.14/lib/libipsecconf/keywords.c000066400000000000000000000714101457372064200206660ustar00rootroot00000000000000/* * 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-2022 Andrew Cagney * Copyright (C) 2017 Mayank Totale * Copyright (C) 2020 Yulia Kuzovkova * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT 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 /* for AF_INET/AF_INET6 */ #include "constants.h" #include "lmod.h" #include "lswcdefs.h" /* for elemsof() */ #include "sparse_names.h" #include "ipsecconf/keywords.h" #include "ipsecconf/parser.h" /* includes parser.tab.h generated by bison; requires keywords.h */ #include "ipsecconf/parserlast.h" /* * Values for failureshunt={passthrough, drop, reject, none} */ static const struct sparse_name kw_failureshunt_list[] = { { "none", KFS_FAIL_NONE }, { "passthrough", KFS_FAIL_PASS }, { "drop", KFS_FAIL_DROP }, { "hold", KFS_FAIL_DROP }, /* alias */ { "reject", KFS_FAIL_REJECT }, SPARSE_NULL }; /* * Values for negotiationshunt={passthrough, hold} */ static const struct sparse_name kw_negotiationshunt_list[] = { { "passthrough", KNS_NEGO_PASS }, { "drop", KNS_NEGO_HOLD }, /* alias */ { "hold", KNS_NEGO_HOLD }, SPARSE_NULL }; /* * Values for enable-tcp={no, yes, fallback} */ static const struct sparse_name kw_tcp_list[] = { { "no", IKE_TCP_NO }, /* default */ { "yes", IKE_TCP_ONLY }, { "fallback", IKE_TCP_FALLBACK }, SPARSE_NULL }; /* * Values for keyexchange= */ static const struct sparse_name kw_keyexchange_list[] = { { "ike", KE_IKE }, SPARSE_NULL }; /* * Values for Four-State options, used for ppk= */ static const struct sparse_name kw_fourvalued_list[] = { { "never", fo_never }, { "permit", fo_permit }, { "propose", fo_propose }, { "insist", fo_insist }, { "yes", fo_propose }, { "always", fo_insist }, { "no", fo_never }, SPARSE_NULL }; /* * Values for yes/no/force, used by fragmentation= */ static const struct sparse_name kw_ynf_list[] = { { "never", ynf_no }, { "no", ynf_no }, { "yes", ynf_yes }, { "insist", ynf_force }, { "force", ynf_force }, SPARSE_NULL }; #ifdef USE_XFRM_INTERFACE /* Values for no/yes, used by ipsec-interface */ static const struct sparse_name kw_yndev_list[] = { { "yes", 1 /* ipsec1 */ }, { "no", UINT32_MAX /* disabled */}, /* any specified number becomes ipsecXXXX */ SPARSE_NULL }; #endif /* Values for yes/no/auto, used by encapsulation and nic-offload */ static const struct sparse_name kw_yna_list[] = { { "yes", yna_yes }, { "no", yna_no }, { "auto", yna_auto }, SPARSE_NULL }; static const struct sparse_name kw_esn_list[] = { { "yes", ESN_YES }, { "no", ESN_NO }, { "either", ESN_EITHER }, SPARSE_NULL }; static const struct sparse_name kw_ddos_list[] = { { "auto", DDOS_AUTO }, { "busy", DDOS_FORCE_BUSY }, { "unlimited", DDOS_FORCE_UNLIMITED }, SPARSE_NULL }; #ifdef USE_SECCOMP static const struct sparse_name kw_seccomp_list[] = { { "enabled", SECCOMP_ENABLED }, { "disabled", SECCOMP_DISABLED }, { "tolerant", SECCOMP_TOLERANT }, SPARSE_NULL }; #endif static const struct sparse_name kw_auth_list[] = { { "never", AUTH_NEVER }, { "secret", AUTH_PSK }, { "rsasig", AUTH_RSASIG }, { "rsa", AUTH_RSASIG }, /* alias */ { "ecdsa", AUTH_ECDSA }, { "null", AUTH_NULL }, { "eaponly", AUTH_EAPONLY }, SPARSE_NULL }; /* * Values for dpdaction={hold,clear,restart} */ static const struct sparse_name kw_dpdaction_list[] = { { "hold", DPD_ACTION_HOLD }, { "clear", DPD_ACTION_CLEAR }, { "restart", DPD_ACTION_RESTART }, /* obsoleted keyword - functionality moved into "restart" */ { "restart_by_peer", DPD_ACTION_RESTART }, SPARSE_NULL }; /* * Values for sendca={none,issuer,all} */ static const struct sparse_name kw_sendca_list[] = { { "none", CA_SEND_NONE }, { "issuer", CA_SEND_ISSUER }, { "all", CA_SEND_ALL }, SPARSE_NULL }; /* * Values for auto={add,start,ondemand,ignore,keep} */ static const struct sparse_name kw_auto_list[] = { { "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 */ { "keep", STARTUP_KEEP }, /* add plus once up, keep up */ SPARSE_NULL }; /* * Values for addrfamily={ipv4,ipv6} */ static const struct sparse_name kw_addrfamily_list[] = { { "ipv4", AF_INET }, { "ipv6", AF_INET6 }, /* aliases - undocumented on purpose */ { "v4", AF_INET }, { "inet", AF_INET }, { "v6", AF_INET6 }, { "inet6", AF_INET6 }, SPARSE_NULL }; /* * Values for type={tunnel,transport,etc} */ static const struct sparse_name kw_type_list[] = { { "tunnel", KS_TUNNEL }, { "transport", KS_TRANSPORT }, { "pass", KS_PASSTHROUGH }, { "passthrough", KS_PASSTHROUGH }, { "reject", KS_REJECT }, { "drop", KS_DROP }, SPARSE_NULL }; /* * Values for {rsasigkey,ecdsakey,pubkey}={ %cert, %dnsondemand, %dns, literal } */ static const struct sparse_name kw_pubkey_list[] = { { "", PUBKEY_PREEXCHANGED }, { "%cert", PUBKEY_CERTIFICATE }, #ifdef USE_DNSSEC { "%dns", PUBKEY_DNSONDEMAND }, { "%dnsondemand", PUBKEY_DNSONDEMAND }, #endif SPARSE_NULL }; /* * Cisco interop: remote peer type */ static const struct sparse_name kw_remote_peer_type_list[] = { { "cisco", CISCO }, SPARSE_NULL }; static const struct sparse_name kw_xauthby_list[] = { { "file", XAUTHBY_FILE }, #ifdef USE_PAM_AUTH { "pam", XAUTHBY_PAM }, #endif { "alwaysok", XAUTHBY_ALWAYSOK }, SPARSE_NULL }; static const struct sparse_name kw_xauthfail_list[] = { { "hard", XAUTHFAIL_HARD }, { "soft", XAUTHFAIL_SOFT }, SPARSE_NULL }; /* * Values for right= and left= */ static struct sparse_name kw_host_list[] = { { "%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 */ SPARSE_NULL }; static const struct sparse_name kw_phase2types_list[] = { /* 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 */ SPARSE_NULL }; /* * Values for {left/right}sendcert={never,sendifasked,always,forcedtype} */ static const struct sparse_name kw_sendcert_list[] = { { "never", CERT_NEVERSEND}, { "sendifasked", CERT_SENDIFASKED }, { "alwayssend", CERT_ALWAYSSEND }, { "always", CERT_ALWAYSSEND }, SPARSE_NULL }; /* * Values for nat-ikev1-method={drafts,rfc,both,none} */ static const struct sparse_name kw_ikev1natt_list[] = { { "both", NATT_BOTH }, { "rfc", NATT_RFC }, { "drafts", NATT_DRAFTS }, { "none", NATT_NONE }, SPARSE_NULL }; /* * 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 sparse_name kw_ocsp_method_list[] = { { "get", OCSP_METHOD_GET }, { "post", OCSP_METHOD_POST }, SPARSE_NULL }; static const struct sparse_name kw_global_ikev1_list[] = { { "accept", GLOBAL_IKEv1_ACCEPT }, { "reject", GLOBAL_IKEv1_REJECT }, { "drop", GLOBAL_IKEv1_DROP }, SPARSE_NULL }; static const struct sparse_name kw_eap_list[] = { { "none", IKE_EAP_NONE }, /* default */ { "tls", IKE_EAP_TLS }, SPARSE_NULL }; /* MASTER KEYWORD LIST * Note: this table is terminated by an entry with keyname == NULL. */ const struct keyword_def ipsec_conf_keywords[] = { { "ikev1-policy", kv_config, kt_enum, KBF_GLOBAL_IKEv1, kw_global_ikev1_list, NULL, }, { "curl-iface", kv_config, kt_string, KSF_CURLIFACE, NULL, NULL, }, { "curl-timeout", kv_config, kt_time, KBF_CURLTIMEOUT_MS, NULL, NULL, }, { "myvendorid", kv_config, kt_string, KSF_MYVENDORID, NULL, NULL, }, { "syslog", kv_config, kt_string, KSF_SYSLOG, NULL, NULL, }, { "plutodebug", kv_config, kt_lset, KBF_PLUTODEBUG, NULL, &debug_lmod_info, }, { "logfile", kv_config, kt_filename, KSF_LOGFILE, NULL, NULL, }, { "plutostderrlog", kv_config, kt_filename, KSF_LOGFILE, NULL, NULL, }, /* obsolete name, but very common :/ */ { "logtime", kv_config, kt_bool, KBF_LOGTIME, NULL, NULL, }, { "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, }, { "uniqueids", kv_config, kt_bool, KBF_UNIQUEIDS, NULL, NULL, }, { "shuntlifetime", kv_config, kt_time, KBF_SHUNTLIFETIME_MS, 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, }, { "crlcheckinterval", kv_config, kt_time, KBF_CRL_CHECKINTERVAL_MS, NULL, NULL, }, { "ocsp-strict", kv_config, kt_bool, KBF_OCSP_STRICT, NULL, NULL, }, { "ocsp-enable", kv_config, kt_bool, KBF_OCSP_ENABLE, NULL, NULL, }, { "ocsp-uri", kv_config, kt_string, KSF_OCSP_URI, NULL, NULL, }, { "ocsp-timeout", kv_config, kt_number, KBF_OCSP_TIMEOUT, NULL, NULL, }, { "ocsp-trustname", kv_config, kt_string, KSF_OCSP_TRUSTNAME, NULL, NULL, }, { "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_AGE_MS, NULL, NULL, }, { "ocsp-cache-max-age", kv_config, kt_time, KBF_OCSP_CACHE_MAX_AGE_MS, 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 USE_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, }, { "ike-socket-bufsize", kv_config, kt_number, KBF_IKEBUF, NULL, NULL, }, { "ike-socket-errqueue", kv_config, kt_bool, KBF_IKE_ERRQUEUE, NULL, NULL, }, #if defined(HAVE_IPTABLES) || defined(HAVE_NFTABLES) { "nflog-all", kv_config, kt_number, KBF_NFLOG_ALL, NULL, NULL, }, #endif #ifdef XFRM_LIFETIME_DEFAULT { "xfrmlifetime", kv_config, kt_number, KBF_XFRMLIFETIME, NULL, NULL, }, #endif { "virtual-private", kv_config, kt_string, KSF_VIRTUALPRIVATE, NULL, NULL, }, { "virtual_private", kv_config, kt_string, KSF_VIRTUALPRIVATE, NULL, NULL, }, /* obsolete variant, very common */ { "seedbits", kv_config, kt_number, KBF_SEEDBITS, NULL, NULL, }, { "keep-alive", kv_config, kt_number, KBF_KEEPALIVE, NULL, NULL, }, { "listen-tcp", kv_config, kt_bool, KBF_LISTEN_TCP, NULL, NULL }, { "listen-udp", kv_config, kt_bool, KBF_LISTEN_UDP, NULL, NULL }, { "listen", kv_config, kt_string, KSF_LISTEN, NULL, NULL, }, { "protostack", kv_config, kt_string, KSF_PROTOSTACK, NULL, 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 { "ikev1-secctx-attr-type", kv_config, kt_number, KBF_SECCTX, NULL, NULL, }, /* obsolete: not a value, a type */ { "secctx-attr-type", kv_config | kv_alias, kt_number, KBF_SECCTX, NULL, NULL, }, #endif { "interfaces", kv_config, kt_obsolete, KNCF_WARNIGNORE, NULL, NULL, }, /* obsoleted but often present keyword */ /* these options are obsoleted (and not old aliases) */ /* * 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, }, { "ikeport", kv_conn | kv_leftright, kt_number, KNCF_IKEPORT, NULL, NULL, }, #if 0 /* requires pluto refcounting IP/mask addresses on ipsec interface */ { "interface-ip", kv_conn | kv_leftright, kt_subnet, KSCF_INTERFACE_IP, NULL, NULL, }, #endif { "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_pubkey, KSCF_RSASIGKEY, kw_pubkey_list, NULL, }, { "ecdsakey", kv_conn | kv_leftright, kt_pubkey, KSCF_ECDSAKEY, kw_pubkey_list, NULL, }, { "pubkey", kv_conn | kv_leftright, kt_pubkey, KSCF_PUBKEY, kw_pubkey_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 is still used in NetworkManager-libreswan :/ */ { "xauthusername", kv_conn | kv_leftright, kt_string, KSCF_USERNAME, NULL, NULL, }, /* old alias */ { "addresspool", kv_conn | kv_leftright, kt_range, KSCF_ADDRESSPOOL, NULL, NULL, }, { "auth", kv_conn | kv_leftright, kt_enum, KNCF_AUTH, kw_auth_list, NULL, }, #ifdef HAVE_IPTABLES { "cat", kv_conn | kv_leftright, kt_bool, KNCF_CAT, NULL, NULL, }, #endif { "protoport", kv_conn | kv_leftright | kv_processed, kt_string, KSCF_PROTOPORT, NULL, NULL, }, { "autheap", kv_conn | kv_leftright, kt_enum, KNCF_EAP, kw_eap_list, 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, }, { "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, }, { "intermediate", kv_conn | kv_processed, kt_bool, KNCF_INTERMEDIATE, NULL, 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, }, { "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, }, { "pfs", kv_conn, kt_bool, KNCF_PFS, NULL, NULL, }, { "nat-keepalive", kv_conn, kt_bool, KNCF_NAT_KEEPALIVE, NULL, NULL, }, { "initial-contact", kv_conn, kt_bool, KNCF_INITIAL_CONTACT, NULL, NULL, }, { "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, kt_bool, KNCF_SEND_VENDORID, NULL, NULL, }, { "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, }, { "ipsec-max-bytes", kv_conn, kt_byte, KNCF_IPSEC_MAXBYTES, NULL, NULL, }, { "ipsec-lifetime", kv_conn, kt_time, KNCF_IPSEC_LIFETIME_MS, NULL, NULL, }, { "keylife", kv_conn | kv_alias, kt_time, KNCF_IPSEC_LIFETIME_MS, NULL, NULL, }, /* old name */ { "lifetime", kv_conn | kv_alias, kt_time, KNCF_IPSEC_LIFETIME_MS, NULL, NULL, }, /* old name */ { "salifetime", kv_conn, kt_time, KNCF_IPSEC_LIFETIME_MS, NULL, NULL, }, /* old name */ { "ipsec-max-packets", kv_conn, kt_binary, KNCF_IPSEC_MAXPACKETS, NULL, NULL, }, { "retransmit-timeout", kv_conn, kt_time, KNCF_RETRANSMIT_TIMEOUT_MS, NULL, NULL, }, { "retransmit-interval", kv_conn|kv_milliseconds, kt_time, 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, }, { "policy-label", kv_conn, kt_string, KSCF_SA_SEC_LABEL, NULL, NULL, }, /* obsolete variant */ { "sec-label", kv_conn, kt_string, KSCF_SA_SEC_LABEL, NULL, NULL, }, /* really stored into struct end */ /* Cisco interop: remote peer type */ { "remote-peer-type", kv_conn, kt_enum, KNCF_REMOTEPEERTYPE, kw_remote_peer_type_list, NULL, }, /* another alias used by NetworkManager-libreswan :/ */ { "remote_peer_type", kv_conn, kt_enum, KNCF_REMOTEPEERTYPE, kw_remote_peer_type_list, NULL, }, /* Network Manager support */ #ifdef HAVE_NM { "nm-configured", kv_conn, kt_bool, KNCF_NMCONFIGURED, NULL, NULL, }, #endif { "xauthby", kv_conn, kt_enum, KNCF_XAUTHBY, kw_xauthby_list, NULL, }, { "xauthfail", kv_conn, kt_enum, KNCF_XAUTHFAIL, kw_xauthfail_list, NULL, }, { "modecfgpull", kv_conn, kt_invertbool, KNCF_MODECONFIGPULL, NULL, NULL, }, { "modecfgdns", kv_conn, kt_string, KSCF_MODECFGDNS, NULL, NULL, }, { "modecfgdomains", kv_conn, kt_string, KSCF_MODECFGDOMAINS, NULL, NULL, }, { "modecfgbanner", kv_conn, kt_string, KSCF_MODECFGBANNER, NULL, NULL, }, { "ignore-peer-dns", kv_conn, kt_bool, KNCF_IGNORE_PEER_DNS, 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_yndev_list, NULL, }, #endif { "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_MS, 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_IKE_LIFETIME_MS, NULL, NULL, }, { "failureshunt", kv_conn, kt_enum, KNCF_FAILURESHUNT, kw_failureshunt_list, NULL, }, { "negotiationshunt", kv_conn, kt_enum, KNCF_NEGOTIATIONSHUNT, kw_negotiationshunt_list, NULL, }, { "enable-tcp", kv_conn, kt_enum, KNCF_TCP, kw_tcp_list, NULL }, { "tcp-remoteport", kv_conn, kt_number, KNCF_REMOTE_TCPPORT, NULL, NULL }, { "connalias", kv_conn | kv_processed, kt_appendstring, KSCF_CONNALIAS, NULL, NULL, }, /* attributes of the phase2 policy */ { "esp", kv_conn, kt_string, KSCF_ESP, NULL, NULL, }, { "ah", kv_conn, kt_string, KSCF_ESP, NULL, NULL, }, { "phase2alg", kv_conn | kv_alias, kt_string, KSCF_ESP, NULL, NULL, }, /* obsolete */ { "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_MS, NULL, NULL, }, { "dpdtimeout", kv_conn, kt_time, KNCF_DPDTIMEOUT_MS, 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, }, #ifdef HAVE_IPTABLES { "nflog", kv_conn, kt_number, KNCF_NFLOG_CONN, NULL, NULL, }, #endif { "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) { bool left = false; bool right = false; int keywordtype; const struct keyword_def *k; for (k = ipsec_conf_keywords; k->keyname != NULL; k++) { if (strcaseeq(s, k->keyname)) { if (k->validity & kv_leftright) { #if 0 /* see github#663 */ left = true; #endif right = true; } break; } if (k->validity & kv_leftright) { if (strncaseeq(s, "left", 4) && strcaseeq(s + 4, k->keyname)) { left = true; break; } if (strncaseeq(s, "right", 5) && strcaseeq(s + 5, k->keyname)) { right = true; break; } } } 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_binary: keywordtype = BINARYWORD; break; case kt_byte: keywordtype = BYTEWORD; 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 = left; lval->k.keyright = right; return keywordtype; } unsigned int parser_enum_list(const struct keyword_def *kd, const char *s, bool list) { assert(kd->type == kt_list || kd->type == kt_enum); 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; shunk_t cursor = shunk1(s); while (true) { shunk_t piece = shunk_token(&cursor, NULL/*delim*/, ":, \t"); if (piece.ptr == NULL) { break; } if (piece.len == 0) { /* discard empty strings */ continue; } assert(kd->validenum != NULL); for (const struct sparse_name *kev = kd->validenum; kev->name != NULL; kev++) { if (hunk_strcaseeq(piece, kev->name)) { /* found it: count it */ numfound++; valresult |= kev->value; break; } } if (numfound == 0) { /* we didn't find anything, complain */ fprintf(stderr, "ERROR: %s: %d: keyword %s, invalid value: "PRI_SHUNK"\n", parser_cur_filename(), parser_cur_lineno(), kd->keyname, pri_shunk(piece)); exit(1); } } if (numfound > 1 && !list) { fprintf(stderr, "ERROR: %s: %d: keyword %s accepts only one value, not %s\n", parser_cur_filename(), parser_cur_lineno(), kd->keyname, s); exit(1); } ; 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; unsigned int valresult; assert(kd->type == kt_loose_enum || kd->type == kt_pubkey); assert(kd->validenum != NULL && kd->validenum != NULL); const struct sparse_name *kev; for (kev = kd->validenum; kev->name != NULL; kev++) { if (strcaseeq(s, kev->name)) { break; } } /* if we found something */ if (kev->name != NULL) { /* * 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-4.14/lib/libipsecconf/parser.lex000066400000000000000000000316141457372064200206630ustar00rootroot00000000000000/* -*- 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 "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; } /* XXX: assumes YYTEXT is [0-9]+; see rule */ static uintmax_t parser_lex_unsigned(const char *yytext) { uintmax_t val; err_t err = shunk_to_uintmax(shunk1(yytext), NULL, /*base*/10, &val); if (err != NULL) { char ebuf[128]; snprintf(ebuf, sizeof(ebuf), "%s: %s", err, yytext); yyerror(ebuf); } return val; } %} /* lexical states: * * INITIAL: pre-defined and default lex state * * BOOLEAN_KEY, COMMENT_KEY, KEY: just matched the BOOLWORD, * "x-comment", other keyword; expecting '=' * * VALUE: just matched '=' in KEY state; matches a quoted/braced/raw * string; returns to INITIAL state * * BOOLEAN_VALUE: just matched '=' in BOOLEAN_KEY state; matches a * boolean token; returns to INITIAL state * * COMMENT_VALUE: just matched '=' in COMMENT_KEY state; matches * everything up to \n as a string; returns to INITIAL state */ %x KEY VALUE BOOLEAN_KEY BOOLEAN_VALUE COMMENT_KEY COMMENT_VALUE %% <> { #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 */ yylval.num = parser_lex_unsigned(yytext); BEGIN INITIAL; return INTEGER; } %forever { /* a number, really 0 */ yylval.num = 0; BEGIN INITIAL; return INTEGER; } [\t ] /* eat blanks */ \n { /* missing equals? */ stacktop->line++; BEGIN INITIAL; return EOL; } = { BEGIN VALUE; return EQUAL; } = { BEGIN BOOLEAN_VALUE; return EQUAL; } = { BEGIN COMMENT_VALUE; return EQUAL; } [\t ] /* eat blanks (not COMMENT_VALUE) */ \n { /* missing value? (not COMMENT_VALUE) */ stacktop->line++; BEGIN INITIAL; return EOL; } 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; } [^\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-blanks */ yylval.s = strdup(yytext); BEGIN INITIAL; return STRING; } [^\{} \t\n]+ { /* string-without-braces-or-blanks */ yylval.s = strdup(yytext); BEGIN INITIAL; return STRING; } \n { stacktop->line++; return EOL; } = { BEGIN VALUE; return EQUAL; } version return VERSION; config return CONFIG; setup return SETUP; conn { BEGIN VALUE; 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_KEY; break; case COMMENT: BEGIN COMMENT_KEY; break; default: BEGIN KEY; break; } return tok; } #.* { /* eat comment to end of line */ } . yyerror(yytext); %% int yywrap(void) { return 1; } libreswan-4.14/lib/libipsecconf/parser.y000066400000000000000000000270011457372064200203360ustar00rootroot00000000000000%{ /* -*- 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 "deltatime.h" #include "timescale.h" #include "binary-iec-60027-2.h" #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, uintmax_t number); /* forward */ static struct starter_comments_list *parser_comments; /** * Functions */ %} %union { char *s; uintmax_t 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 BINARYWORD %token BYTEWORD %token COMMENT %% /* * 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 */ uintmax_t 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_pubkey: 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: case kt_binary: case kt_byte: 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 */ uintmax_t 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_pubkey: 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: case kt_binary: case kt_byte: 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 INTEGER { struct keyword *kw = &$1; deltatime_t d; if (kw->keydef->validity & kv_milliseconds) { d = deltatime_ms($3); } else { d = deltatime($3); } new_parser_kw(kw, NULL, deltamillisecs(d)); } | TIMEWORD EQUAL STRING { struct keyword *kw = &$1; const char *const str = $3; const struct timescale *scale; if (kw->keydef->validity & kv_milliseconds) { scale = ×cale_milliseconds; } else { scale = ×cale_seconds; } deltatime_t d; diag_t diag = ttodeltatime(str, &d, scale); if (diag != NULL) { yyerror(str_diag(diag)); pfree_diag(&diag); } else { new_parser_kw(kw, NULL, deltamillisecs(d)); } } | 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 (!streq(endptr, "%")) { 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 */ } | BINARYWORD EQUAL INTEGER { struct keyword *kw = &$1; unsigned long b = $3; new_parser_kw(kw, NULL, b); } | BINARYWORD EQUAL STRING { struct keyword *kw = &$1; const char *const str = $3; uint64_t b; diag_t diag = ttobinary(str, &b, 0 /* no B prefix */); if (diag != NULL) { yyerror(str_diag(diag)); pfree_diag(&diag); } else { new_parser_kw(kw, NULL, b); } } | BYTEWORD EQUAL INTEGER { struct keyword *kw = &$1; uint64_t b = $3; new_parser_kw(kw, NULL, b); } | BYTEWORD EQUAL STRING { struct keyword *kw = &$1; const char *const str = $3; uint64_t b; diag_t diag = ttobinary(str, &b, 1 /* with B prefix */); if (diag != NULL) { yyerror(str_diag(diag)); pfree_diag(&diag); } else { new_parser_kw(kw, NULL, b); } } ; %% 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, uintmax_t 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-4.14/lib/libipsecconf/starterlog.c000066400000000000000000000044571457372064200212140ustar00rootroot00000000000000/* 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 "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-4.14/lib/libipsecconf/starterwhack.c000066400000000000000000000614761457372064200215340ustar00rootroot00000000000000/* * 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 * Copyright (C) 2017 Mayank Totale * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT 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 "lsw_socket.h" #include "ttodata.h" #include "ipsecconf/starterwhack.h" #include "ipsecconf/confread.h" #include "ipsecconf/starterlog.h" #include "lswalloc.h" #include "lswlog.h" #include "whack.h" #include "id.h" #include "ip_address.h" #include "ip_info.h" 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 = cloexec_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 const struct whack_message empty_whack_message = { .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 bool set_whack_end(struct whack_end *w, const struct starter_end *l) { const char *lr = l->leftright; w->leftright = lr; 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 = unset_address; break; case KH_OPPO: case KH_GROUP: case KH_OPPOGROUP: /* policy should have been set to OPPO */ w->host_addr = unset_address; break; case KH_ANY: w->host_addr = unset_address; break; default: printf("Failed to load connection %s= is not set\n", lr); return false; } 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 = l->host_family->address.unspec; 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 (cidr_is_specified(l->vti_ip)) w->host_vtiip = l->vti_ip; if (cidr_is_specified(l->ifaceip)) w->ifaceip = l->ifaceip; if (l->has_client) { w->client = l->subnet; } else { w->client = unset_subnet; } w->host_ikeport = l->options[KNCF_IKEPORT]; w->protoport = l->protoport; if (l->certx != NULL) { w->cert = l->certx; } if (l->ckaid != NULL) { w->ckaid = l->ckaid; } if (l->pubkey_type == PUBKEY_PREEXCHANGED) { /* * Only send over raw (prexchanged) rsapubkeys (i.e., * not %cert et.a.) * * XXX: but what is with the two rsasigkeys? Whack seems * to be willing to send pluto two raw pubkeys under * the same ID. Just assume that the first key should * be used for the CKAID. */ passert(l->pubkey != NULL); passert(l->pubkey_alg != 0); w->pubkey_alg = l->pubkey_alg; w->pubkey = l->pubkey; } 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->auth = l->options[KNCF_AUTH]; if (l->options_set[KNCF_EAP]) w->eap = l->options[KNCF_EAP]; else w->eap = IKE_EAP_NONE; w->updown = l->updown; w->virt = NULL; 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; return true; } static int starter_whack_add_pubkey(struct starter_config *cfg, const struct starter_conn *conn, const struct starter_end *end) { int ret = 0; const char *lr = end->leftright; struct whack_message msg = empty_whack_message; msg.whack_key = true; msg.pubkey_alg = end->pubkey_alg; if (end->id && end->pubkey != NULL) { msg.keyid = end->id; switch (end->pubkey_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: { int base; switch (end->pubkey_alg) { case IPSECKEY_ALGORITHM_RSA: case IPSECKEY_ALGORITHM_ECDSA: base = 0; /* figure it out */ break; case IPSECKEY_ALGORITHM_X_PUBKEY: base = 64; /* dam it */ break; default: bad_case(end->pubkey_alg); } chunk_t keyspace = NULL_HUNK; /* must free */ err_t err = ttochunk(shunk1(end->pubkey), base, &keyspace); if (err != NULL) { enum_buf pkb; starter_log(LOG_LEVEL_ERR, "conn %s: %s%s malformed [%s]", connection_name(conn), lr, str_enum(&ipseckey_algorithm_config_names, end->pubkey_alg, &pkb), err); return 1; } enum_buf pkb; starter_log(LOG_LEVEL_DEBUG, "\tsending %s %s%s=%s", connection_name(conn), lr, str_enum(&ipseckey_algorithm_config_names, end->pubkey_alg, &pkb), end->pubkey); msg.keyval = keyspace; ret = send_whack_msg(&msg, cfg->ctlsocket); free_chunk_content(&keyspace); } } } if (ret < 0) return ret; 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 = empty_whack_message; msg.whack_connection = true; msg.whack_delete = true; /* always do replace for now */ msg.name = connection_name(conn); msg.tunnel_addr_family = conn->left.host_family->af; 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_ms(conn->options[KNCF_IKE_LIFETIME_MS]); msg.sa_ipsec_life_seconds = deltatime_ms(conn->options[KNCF_IPSEC_LIFETIME_MS]); msg.sa_rekey_margin = deltatime_ms(conn->options[KNCF_REKEYMARGIN_MS]); msg.sa_ipsec_max_bytes = conn->options[KNCF_IPSEC_MAXBYTES]; msg.sa_ipsec_max_packets = conn->options[KNCF_IPSEC_MAXPACKETS]; 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.retransmit_interval = deltatime_ms(conn->options[KNCF_RETRANSMIT_INTERVAL_MS]); msg.retransmit_timeout = deltatime_ms(conn->options[KNCF_RETRANSMIT_TIMEOUT_MS]); msg.ike_version = conn->ike_version; msg.policy = conn->policy; msg.authby = conn->authby; msg.sighash_policy = conn->sighash_policy; msg.prospective_shunt = conn->prospective_shunt; msg.negotiation_shunt = conn->negotiation_shunt; msg.failure_shunt = conn->failure_shunt; 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]; } } if (conn->options_set[KNCF_REMOTE_TCPPORT]) { msg.remote_tcpport = conn->options[KNCF_REMOTE_TCPPORT]; } else { msg.remote_tcpport = NAT_IKE_UDP_PORT; } if (conn->options_set[KNCF_TCP]) { msg.iketcp = conn->options[KNCF_TCP]; } else { msg.iketcp = IKE_TCP_NO; } /* default to HOLD */ msg.dpd_action = DPD_ACTION_HOLD; switch (conn->ike_version) { case IKEv1: if (conn->options_set[KNCF_DPDDELAY_MS] && conn->options_set[KNCF_DPDTIMEOUT_MS]) { msg.dpd_delay = deltatime_ms(conn->options[KNCF_DPDDELAY_MS]); msg.dpd_timeout = deltatime_ms(conn->options[KNCF_DPDTIMEOUT_MS]); if (conn->options_set[KNCF_DPDACTION]) { msg.dpd_action = conn->options[KNCF_DPDACTION]; } } else if (conn->options_set[KNCF_DPDDELAY_MS] || conn->options_set[KNCF_DPDTIMEOUT_MS] || conn->options_set[KNCF_DPDACTION]) { starter_log(LOG_LEVEL_ERR, "conn: \"%s\" warning IKEv1 dpd settings are ignored unless both dpdtimeout= and dpddelay= are set", conn->name); } break; case IKEv2: if (conn->options_set[KNCF_DPDDELAY_MS]) { msg.dpd_delay = deltatime_ms(conn->options[KNCF_DPDDELAY_MS]); if (conn->options_set[KNCF_DPDACTION]) { msg.dpd_action = conn->options[KNCF_DPDACTION]; } } else if (conn->options_set[KNCF_DPDACTION]) { starter_log(LOG_LEVEL_ERR, "conn: \"%s\" warning IKEv2 liveness setting dpdaction= is ignored unless dpddelay= is set", conn->name); } if (conn->options_set[KNCF_DPDTIMEOUT_MS]) { starter_log(LOG_LEVEL_ERR, "conn: \"%s\" warning IKEv2 liveness uses retransmit-timeout=, dpdtimeout= ignored", conn->name); } break; } /* check for conflicts */ 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; } } 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 if (conn->strings_set[KSCF_SA_SEC_LABEL]) { msg.sec_label = conn->sec_label; starter_log(LOG_LEVEL_DEBUG, "conn: \"%s\" sec_label=%s", conn->name, msg.sec_label); } 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]; if (!set_whack_end(&msg.left, &conn->left)) return -1; if (!set_whack_end(&msg.right, &conn->right)) return -1; msg.esp = conn->esp; conn_log_val(conn, "esp", msg.esp); msg.ike = conn->ike_crypto; conn_log_val(conn, "ike", msg.ike); int r = send_whack_msg(&msg, cfg->ctlsocket); if (r != 0) return r; if (conn->left.pubkey != NULL) { r = starter_whack_add_pubkey(cfg, conn, &conn->left); if (r != 0) return r; } if (conn->right.pubkey != NULL) { r = starter_whack_add_pubkey(cfg, conn, &conn->right); if (r != 0) return r; } return 0; } /* * When false, should also check error. */ struct subnets { const char *leftright; const struct starter_end *end; const struct starter_conn *conn; struct logger *logger; /* keep track */ const char *subnets; int count; /* results */ ip_subnet subnet; err_t error; }; static bool next_subnet(struct subnets *sn); static bool first_subnet(struct subnets *sn) { sn->subnets = (sn->end->strings_set[KSCF_SUBNETS]) ? sn->end->strings[KSCF_SUBNETS] : ""; sn->count = 0; sn->subnet = unset_subnet; if (sn->end->strings_set[KSCF_SUBNET]) { sn->subnet = sn->end->subnet; /* .count == 0 */ return true; } /* advances .count to 1 */ return next_subnet(sn); } static bool next_subnet(struct subnets *sn) { sn->subnet = unset_subnet; /* always */ const char *subnets = sn->subnets; if (subnets == NULL) { /* XXX: never happens */ return false; } /* find first non-space item */ while (*subnets != '\0' && (char_isspace(*subnets) || *subnets == ',')) { subnets++; } /* did we find something? */ if (*subnets == '\0') { return false; /* no more input */ } const char *eln = subnets; /* save start */ /* find end of this item */ while (*subnets != '\0' && !(char_isspace(*subnets) || *subnets == ',')) { subnets++; } sn->error = ttosubnet(shunk2(eln, subnets - eln), sn->end->host_family, '6', &sn->subnet, sn->logger); if (sn->error != NULL) { starter_log(LOG_LEVEL_ERR, "conn: \"%s\" warning '%s' is not a subnet declaration. (%ssubnets): %s", sn->conn->name, eln, sn->leftright, sn->error); return false; } sn->subnets = subnets; sn->count++; 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 logger *logger) { /* * 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= * */ struct subnets left = { .logger = logger, .conn = conn, .end = &conn->left, .leftright = "left", }; if (!first_subnet(&left)) { /* no subnets at all!?! */ return 1; } pexpect(left.count >= 0); struct subnets right = { .logger = logger, .conn = conn, .end = &conn->right, .leftright = "right", }; if (!first_subnet(&right)) { /* no subnets at all!?! */ return 1; } pexpect(right.count >= 0); for (;;) { /* copy conn --- we can borrow all pointers, since this * is a temporary copy */ struct starter_conn sc = *conn; /* fix up leftsubnet/rightsubnet properly, make sure * that has_client is set. */ sc.left.subnet = left.subnet; sc.left.has_client = true; sc.right.subnet = right.subnet; sc.right.has_client = true; char tmpconnname[256]; snprintf(tmpconnname, sizeof(tmpconnname), "%s/%ux%u", conn->name, left.count, right.count); sc.name = tmpconnname; sc.connalias = conn->name; int fail = (*operation)(cfg, &sc); if (fail != 0) { /* Fail at first failure? I think so. */ return fail; } /* * Okay, advance right first, and if it is out, rewind * and do left instead. */ if (!next_subnet(&right)) { if (right.error != NULL) { /* really bad */ return 1; } /* reset right, and advance left! */ if (!first_subnet(&right)) { return 1; } /* left */ if (!next_subnet(&left)) { if (left.error != NULL) { /* really bad */ return 1; } break; } } } return 0; /* success. */ } int starter_whack_add_conn(struct starter_config *cfg, const struct starter_conn *conn, struct logger *logger) { /* 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, logger); } static int starter_whack_basic_route_conn(struct starter_config *cfg, const struct starter_conn *conn) { struct whack_message msg = empty_whack_message; 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, struct logger *logger) { /* 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, logger); } int starter_whack_initiate_conn(struct starter_config *cfg, struct starter_conn *conn) { struct whack_message msg = empty_whack_message; 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 = empty_whack_message; msg.whack_listen = true; return send_whack_msg(&msg, cfg->ctlsocket); } libreswan-4.14/lib/liblswtool/000077500000000000000000000000001457372064200164025ustar00rootroot00000000000000libreswan-4.14/lib/liblswtool/Makefile000066400000000000000000000014311457372064200200410ustar00rootroot00000000000000# 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-4.14/lib/liblswtool/libreswan_exit.c000066400000000000000000000013301457372064200215620ustar00rootroot00000000000000/* * 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-4.14/lib/liblswtool/lswlog.c000066400000000000000000000053141457372064200200600ustar00rootroot00000000000000/* * 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 /* used only if MSG_NOSIGNAL not defined */ #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 size_t jam_progname_prefix(struct jambuf *buf, const void *object UNUSED) { const char *progname = object; if (progname != NULL) { return jam(buf, "%s: ", progname); } return 0; } static bool suppress_progname_log(const void *object UNUSED) { return false; } const struct logger_object_vec progname_object_vec = { .name = "tool", .jam_object_prefix = jam_progname_prefix, .suppress_object_log = suppress_progname_log, }; static struct logger progname_logger = { .object_vec = &progname_object_vec, .object = NULL, /* progname */ }; struct logger *tool_init_log(const char *name) { const char *last_slash = strrchr(name, '/'); progname_logger.object = progname = last_slash == NULL ? name : last_slash + 1; if (log_to_stderr) { setbuf(stderr, NULL); } return &progname_logger; } void jambuf_to_logger(struct jambuf *buf, const struct logger *logger UNUSED, lset_t rc_flags) { enum stream only = rc_flags & STREAM_MASK; switch (only) { case DEBUG_STREAM: fprintf(stderr, DEBUG_PREFIX"%s\n", buf->array); break; case ALL_STREAMS: case LOG_STREAM: if (log_to_stderr) { fprintf(stderr, "%s\n", buf->array); } break; case WHACK_STREAM: /* AKA the console */ fprintf(stdout, "%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); } } libreswan-4.14/lib/libswan/000077500000000000000000000000001457372064200156475ustar00rootroot00000000000000libreswan-4.14/lib/libswan/DBG_dump.c000066400000000000000000000024631457372064200174410ustar00rootroot00000000000000/* 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,2021 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 DBG_dump(const char *label, const void *p, size_t len) { if (label != NULL) { llog(DEBUG_STREAM, &global_logger, "%s", label); } llog_dump(DEBUG_STREAM, &global_logger, p, len); } libreswan-4.14/lib/libswan/DBG_log.c000066400000000000000000000020521457372064200172470ustar00rootroot00000000000000/* 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, ...) { JAMBUF(buf) { va_list args; va_start(args, message); jam_va_list(buf, message, args); va_end(args); jambuf_to_logger(buf, &global_logger, DEBUG_STREAM); } } libreswan-4.14/lib/libswan/DBG_va_list.c000066400000000000000000000015121457372064200201270ustar00rootroot00000000000000/* logging, for libreswan * * Copyright (C) 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. */ #include #include #include "lswlog.h" void DBG_va_list(const char *message, va_list ap) { JAMBUF(buf) { jam_va_list(buf, message, ap); jambuf_to_logger(buf, &global_logger, DEBUG_STREAM); } } libreswan-4.14/lib/libswan/Makefile000066400000000000000000000137051457372064200173150ustar00rootroot00000000000000# 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-2022 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 += authby.o OBJS += rnd.o OBJS += constants.o \ id.o \ initaddr.o \ lex.o \ lswconf.o \ lswfips.o \ sameaddr.o \ subnettypeof.o ttodata.o \ ttosaid.o \ ttosubnet.o \ ttoul.o \ secitem_chunk.o \ lswnss.o \ alg_byname.o OBJS += cloexec_socket.o OBJS += secret_pubkey_stuff_to_pubkey_der.o OBJS += pubkey_der_to_pubkey_content.o OBJS += clone_shunk_tokens.o OBJS += secrets.o OBJS += pubkey_rsa.o OBJS += pubkey_ecdsa.o OBJS += sparse_names.o OBJS += ttoaddress.o OBJS += ttoaddress_list_num.o OBJS += ttoprotocol.o OBJS += ttobinary-iec-60027-2.o OBJS += binaryscale-iec-60027-2.o OBJS += alloc.o OBJS += alloc_printf.o OBJS += diag.o OBJS += passert.o OBJS += pexpect.o OBJS += nss_cert_load.o OBJS += certs.o OBJS += reqid.o OBJS += keyid.o ifneq ($(LINUX_VARIANT),) OBJS += kernel_netlink_reply.o OBJS += kernel_netlink_query.o ifeq ($(USE_XFRM_INTERFACE), true) OBJS += netlink_attrib.o endif endif # implement resolve_default_route() ifneq ($(LINUX_VARIANT),) OBJS += resolve_default_route_linux.o endif ifneq ($(BSD_VARIANT),) OBJS += resolve_default_route_bsd.o endif OBJS += log_ip.o OBJS += fd.o OBJS += role.o OBJS += datatot.o OBJS += ultot.o OBJS += vendorid.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 += hunk.o OBJS += ip_bytes.o OBJS += ip_address.o OBJS += ip_cidr.o OBJS += ip_encap.o OBJS += ip_endpoint.o OBJS += ip_info.o OBJS += ip_port.o OBJS += ip_port_range.o OBJS += ip_protocol.o OBJS += ip_protoport.o OBJS += ip_range.o OBJS += ip_said.o OBJS += ip_selector.o OBJS += ip_sockaddr.o OBJS += ip_subnet.o OBJS += ip_packet.o OBJS += lmod.o OBJS += lset.o OBJS += timescale.o OBJS += deltatime.o OBJS += realtime.o OBJS += monotime.o OBJS += ttodeltatime.o OBJS += refcnt.o OBJS += debug.o OBJS += impair.o OBJS += keywords.o OBJS += DBG_dump.o OBJS += DBG_log.o OBJS += DBG_va_list.o OBJS += llog_base64_bytes.o OBJS += llog_pem_bytes.o OBJS += llog_errno.o OBJS += log_error.o OBJS += fatal.o OBJS += libreswan_bad_case.o OBJS += lswglob.o OBJS += global_logger.o OBJS += jambuf.o OBJS += jam_humber.o OBJS += jam_bytes.o OBJS += jam_base64_bytes.o OBJS += llog.o OBJS += llog_dump.o OBJS += llog_va_list.o OBJS += log_nss_error.o OBJS += jam_nss_cka.o OBJS += jam_nss_ckf.o OBJS += jam_nss_ckm.o OBJS += jam_nss_error.o OBJS += jam_nss_oid.o OBJS += jam_nss_secitem.o # Crypto code: OBJS += test_buffer.o OBJS += ike_alg.o OBJS += ike_alg_dh.o OBJS += ike_alg_hash_identity.o OBJS += ike_alg_ipcomp.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_KDF),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 ifeq ($(USE_AES),true) OBJS += ike_alg_aes.o endif ifeq ($(USE_CAMELLIA),true) OBJS += ike_alg_camellia.o endif # used by Vendor ID OBJS += ike_alg_hash_md5.o ifeq ($(USE_MD5),true) OBJS += ike_alg_md5.o endif OBJS += ike_alg_none.o # used by NAT OBJS += ike_alg_hash_sha1.o ifeq ($(USE_SHA1),true) OBJS += ike_alg_sha1.o endif # used by Cookies OBJS += ike_alg_hash_sha2_256.o ifeq ($(USE_SHA2),true) OBJS += ike_alg_sha2.o endif OBJS += ike_alg_encrypt_cbc_test_vectors.o OBJS += ike_alg_encrypt_ctr_test_vectors.o OBJS += ike_alg_encrypt_gcm_test_vectors.o OBJS += ike_alg_prf_test_vectors.o OBJS += crypt_mac.o OBJS += crypt_hash.o OBJS += crypt_prf.o OBJS += crypt_symkey.o ifeq ($(USE_IKEv1),true) OBJS += ikev1_prf.o endif OBJS += ikev2_prf.o ifeq ($(USE_NSS_AVA_COPY),true) OBJS += nss_copies.o endif ifeq ($(USE_DNSSEC),true) OBJS += unbound.o endif ifeq ($(USE_UNBOUND_EVENT_H_COPY),true) USERLAND_INCLUDES += -I$(top_srcdir)/include/unbound endif OBJS += enum_names.o OBJS += pluto_exit_code_names.o OBJS += ipseckey_algorithm_type_names.o OBJS += ipseckey_algorithm_config_names.o ifneq ($(LINUX_VARIANT),) OBJS += xfrm_policy_names.o endif OBJS += $(abs_builddir)/version.o # build version.c using version number from mk/version.mk $(abs_builddir)/version.c: $(srcdir)/version.in.c $(top_srcdir)/mk/version.mk rm -f $@.tmp sed -e '/"/s/@IPSECVERSION@/$(subst /,\/,$(IPSECVERSION))/' \ -e '/"/s/@IPSECVIDVERSION@/$(IPSECVIDVERSION)/' \ $(srcdir)/version.in.c \ > $@.tmp mv $@.tmp $@ include $(top_srcdir)/mk/library.mk libreswan-4.14/lib/libswan/ah_info.c000066400000000000000000000067241457372064200174270ustar00rootroot00000000000000/* * 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, parser->policy->logger, next_algorithm(proposal, PROPOSAL_encrypt, NULL) == NULL); impaired_passert(proposal_parser, parser->policy->logger, next_algorithm(proposal, PROPOSAL_prf, NULL) == NULL); impaired_passert(proposal_parser, parser->policy->logger, 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-4.14/lib/libswan/alg_byname.c000066400000000000000000000124071457372064200201150ustar00rootroot00000000000000/* * 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" #include "impair.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) { passert(parser->diag == NULL); 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->diag != NULL); DBGF(DBG_PROPOSAL_PARSER, "ike_alg_byname() failed: %s", str_diag(parser->diag)); return NULL; } /* * Does it pass muster? */ if (!alg_byname_ok(parser, alg, print_name)) { passert(parser->diag != NULL); DBGF(DBG_PROPOSAL_PARSER, "alg_byname_ok() failed: %s", str_diag(parser->diag)); 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 encryption algorithm %s does not allow a key lengths", parser->protocol->name, encrypt->common.fqn); if (!impair_proposal_errors(parser)) { return NULL; } } if (!encrypt_has_key_bit_length(encrypt, key_bit_length)) { JAMBUF(buf) { jam(buf, "%s encryption algorithm %s with key length %zu invalid; valid key lengths:", parser->protocol->name, encrypt->common.fqn, key_bit_length); /* reverse: table in descending order with trailing zeros */ const char *sep = " "; for (int i = elemsof(encrypt->key_bit_lengths) - 1; i >= 0; i--) { if (encrypt->key_bit_lengths[i] > 0) { jam(buf, "%s%d", sep, encrypt->key_bit_lengths[i]); sep = ", "; } } proposal_error(parser, PRI_SHUNK, pri_shunk(jambuf_as_shunk(buf))); } if (!impair_proposal_errors(parser)) { return NULL; } } } return alg; } libreswan-4.14/lib/libswan/alloc.c000066400000000000000000000202301457372064200171020ustar00rootroot00000000000000/* * 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) { llog_passert(&global_logger, HERE, "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) { llog_passert(&global_logger, HERE, "pointer %p invalid, possible double free (magic == ~LEAK_MAGIC)", ptr); } else if (p->i.magic != LEAK_MAGIC) { llog_passert(&global_logger, HERE, "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); } } bool report_leaks(struct logger *logger) { 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) llog(RC_LOG, logger, "leak: %lu * %s, item size: %lu", n, pprev->i.name, pprev->i.size); else llog(RC_LOG, logger, "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) { llog(RC_LOG, logger, "leak detective found %lu leaks, total size %lu", numleaks, total); } else { llog(RC_LOG, logger, "leak detective found no leaks"); } return numleaks != 0; } static void *zalloc(size_t size) { return calloc(1, size); } void *alloc_bytes(size_t size, const char *name) { return allocate(zalloc, size, name); } /* * Note: * orig=NULL; size=0 -> NULL * orig=PTR; size=0 -> new PTR (for instance a shunk with PTR = "") * orig=PTR; size>0 -> new PTR */ void *clone_bytes(const void *orig, size_t size, const char *name) { if (orig == NULL) { passert(size == 0); return NULL; } /* * Even when size is 0, allocate something. * * Note: memcpy(DST,NULL,*) is undefined. Since size>0 * implies !NULL use that (string code can end up with * {!NULL,0}. */ void *p = uninitialized_malloc(size, name); if (size > 0) { passert(orig != NULL); /* per above */ memcpy(p, orig, size); } return p; } void *clone_bytes_bytes(const void *lhs_ptr, size_t lhs_len, const void *rhs_ptr, size_t rhs_len, const char *name) { if (lhs_ptr == NULL && rhs_ptr == NULL) { passert(lhs_len == 0); passert(rhs_len == 0); return NULL; } /* * When at least one PTR is non-NULL allocate something (even * though SIZE can be zero). * * Note: memcpy(DST,NULL,*) is undefined. Since LEN>0 implies * !NULL use that (string code can end up with {!NULL,0}. */ size_t size = lhs_len + rhs_len; void *new = uninitialized_malloc(size, name); if (lhs_len > 0) { passert(lhs_ptr != NULL); memcpy(new, lhs_ptr, lhs_len); } if (rhs_len > 0) { passert(rhs_ptr != NULL); memcpy(new + lhs_len, rhs_ptr, rhs_len); } return new; } /* * 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) { llog_passert(&global_logger, HERE, "unable to reallocate %zu bytes for %s", new_size, name); } 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-4.14/lib/libswan/alloc_printf.c000066400000000000000000000023401457372064200204660ustar00rootroot00000000000000/* asprintf(), for libreswan * * Copyright (C) 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. */ #include #include #include "passert.h" #include "lswalloc.h" char *alloc_vprintf(const char *fmt, va_list master_ap /* must va_copy */) { int length; { va_list ap; va_copy(ap, master_ap); length = vsnprintf(NULL, 0, fmt, ap); va_end(ap); } passert(length >= 0); length++; /* space for '\0' */ char *buf = alloc_things(char, length, fmt); { va_list ap; va_copy(ap, master_ap); vsnprintf(buf, length, fmt, ap); va_end(ap); } return buf; } char *alloc_printf(const char *fmt, ...) { va_list ap; va_start(ap, fmt); char *d = alloc_vprintf(fmt, ap); va_end(ap); return d; } libreswan-4.14/lib/libswan/asn1.c000066400000000000000000000142631457372064200166630ustar00rootroot00000000000000/* * 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(asn1_t object) { int oid = 0; while (object.len > 0) { if (oid_names[oid].octet == *(const uint8_t*)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; } /* * 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] = (uint8_t) 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_asn1_printablestring(shunk_t str) { /* * Map ASCII character onto a printable bit. The printable * characters are: * * "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 '()+,-./:=?" * * Each byte contains a bit mask of valid characters. The * most-significant bit contains the first character's bit, * and so on (so &0x80 checks the left-most character). */ static const uint8_t printable_set[256 / 8] = { 0000u, /* 0x00 */ 0000u, /* 0x08 */ 0000u, /* 0x10 */ 0000u, /* 0x18 */ 0201u, /* 0x20 ' (first is the real SPACE) */ 0337u, /* 0x28 () +, -./ */ 0377u, /* 0x30 01 234 567 */ 0345u, /* 0x38 89 : = ? */ 0177u, /* 0x40 A BCD EFG */ 0377u, /* 0x48 HI JKL MNO */ 0377u, /* 0x50 PQ RST UVW */ 0340u, /* 0x58 XY Z */ 0177u, /* 0x60 a bcd efg */ 0377u, /* 0x68 hi jkl mno */ 0377u, /* 0x70 pq rst uvw */ 0340u, /* 0x78 xy z */ }; const uint8_t *s = str.ptr; for (unsigned i = 0; i < str.len; i++) { /* * Check if the bit within printable_set[] is set. * Left shift the mask so that 0x80 checks the bit. */ uint8_t u = s[i]; uint8_t ps = printable_set[u / 8]; uint8_t pb = ps << (u % 8); /* printf("checking '%c' %o %x\n", u, ps, pb); */ if (!(pb & 0x80)) { return false; } } return true; } /* * tests if a blob contains a valid ASN.1 set or sequence */ err_t asn1_ok(asn1_t blob) { err_t e; enum asn1_type type; e = unwrap_asn1_type(&blob, &type); if (e != NULL) { return e; } switch (type) { case ASN1_SEQUENCE: case ASN1_SET: break; /* looks OK */ default: return "content is not binary ASN.1"; } size_t length; e = unwrap_asn1_length(&blob, &length); if (e != NULL) { return e; } return NULL; } err_t unwrap_asn1_type(asn1_t *cursor, enum asn1_type *ty) { *ty = 0; const uint8_t *b = hunk_get(cursor, sizeof(uint8_t)); if (b == NULL) { return "missing ASN.1 type"; } *ty = *b; return NULL; } /* * Decode the length in bytes of an ASN.1 object. * CURSOR is updated to reflect the length that was consumed. */ err_t unwrap_asn1_length(asn1_t *cursor, size_t *length) { *length = 0; /* read first octet of length field */ const uint8_t *np = hunk_get_thing(cursor, uint8_t); if (np == NULL) { return "insufficient number of octets to parse ASN.1 length"; } uint8_t n = *np; if ((n & 0x80) == 0) { /* single length octet */ if (n > cursor->len) { return "number of length octets is larger than ASN.1 object"; } *length = n; return NULL; } /* composite length, determine number of length octets */ n &= 0x7f; if (n > sizeof(*length)) { return "number of length octets overflows size_t"; } const uint8_t *lp = hunk_get(cursor, n); if (lp == NULL) { return "number of length octets is larger than ASN.1 object"; } size_t len = 0; while (n-- > 0) { len = 256 * len + *lp++; } if (len > cursor->len) { return "remaining ASN.1 object is shorter than length"; } *length = len; return NULL; } /* * Unwrap . */ err_t unwrap_asn1_value(asn1_t *cursor, size_t length, asn1_t *contents) { /* XXX: redundant */ if (length > cursor->len) { return "ASN.1 length larger than space"; } contents->ptr = cursor->ptr; contents->len = length; cursor->ptr += length; cursor->len -= length; return NULL; } err_t unwrap_asn1_tlv(asn1_t *cursor, enum asn1_type ty, asn1_t *value) { err_t e; enum asn1_type type; e = unwrap_asn1_type(cursor, &type); if (e != NULL) { return e; } if (ty != type) { return "unexpected ASN.1 type"; } size_t length; e = unwrap_asn1_length(cursor, &length); if (e != NULL) { return e; } e = unwrap_asn1_value(cursor, length, value); if (e != NULL) { return e; } return NULL; } libreswan-4.14/lib/libswan/atoaddr.3.xml000066400000000000000000000277461457372064200201700ustar00rootroot00000000000000 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-4.14/lib/libswan/atoasr.3000066400000000000000000000104221457372064200172230ustar00rootroot00000000000000.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-4.14/lib/libswan/authby.c000066400000000000000000000071641457372064200173170ustar00rootroot00000000000000/* Authentication, for libreswan * * Copyright (C) 2022 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 "authby.h" #include "constants.h" /* for enum keyword_auth */ #include "jambuf.h" #include "lswlog.h" /* for bad_case() */ #define REDUCE(LHS, OP) \ ((LHS).null OP \ (LHS).never OP \ (LHS).psk OP \ (LHS).rsasig OP \ (LHS).rsasig_v1_5 OP \ (LHS).ecdsa) #define OP(LHS, OP, RHS) \ ({ \ struct authby tmp_ = { \ .null = (LHS).null OP (RHS).null, \ .never = (LHS).never OP (RHS).never, \ .psk = (LHS).psk OP (RHS).psk, \ .rsasig = (LHS).rsasig OP (RHS).rsasig, \ .ecdsa = (LHS).ecdsa OP (RHS).ecdsa, \ .rsasig_v1_5 = (LHS).rsasig_v1_5 OP (RHS).rsasig_v1_5, \ }; \ tmp_; \ }) bool authby_is_set(struct authby authby) { return REDUCE(authby, ||); } struct authby authby_xor(struct authby lhs, struct authby rhs) { return OP(lhs, !=, rhs); } struct authby authby_not(struct authby lhs) { return authby_xor(lhs, AUTHBY_ALL); } struct authby authby_and(struct authby lhs, struct authby rhs) { return OP(lhs, &&, rhs); } struct authby authby_or(struct authby lhs, struct authby rhs) { return OP(lhs, ||, rhs); } bool authby_eq(struct authby lhs, struct authby rhs) { struct authby eq = OP(lhs, ==, rhs); return REDUCE(eq, &&); } bool authby_le(struct authby lhs, struct authby rhs) { struct authby le = OP(lhs, <=, rhs); return REDUCE(le, &&); } bool authby_has_rsasig(struct authby lhs) { return lhs.rsasig || lhs.rsasig_v1_5; } bool authby_has_ecdsa(struct authby lhs) { return lhs.ecdsa; } bool authby_has_digsig(struct authby lhs) { return authby_has_ecdsa(lhs) || authby_has_rsasig(lhs); } enum keyword_auth auth_from_authby(struct authby authby) { return (authby.rsasig ? AUTH_RSASIG : authby.ecdsa ? AUTH_ECDSA : authby.rsasig_v1_5 ? AUTH_RSASIG : authby.psk ? AUTH_PSK : authby.null ? AUTH_NULL : authby.never ? AUTH_NEVER : AUTH_UNSET); } struct authby authby_from_auth(enum keyword_auth auth) { switch (auth) { case AUTH_RSASIG: return (struct authby) { .rsasig = true, .rsasig_v1_5 = true }; case AUTH_ECDSA: return (struct authby) { .ecdsa = true, }; case AUTH_PSK: return (struct authby) { .psk = true, }; case AUTH_NULL: return (struct authby) { .null = true, }; case AUTH_NEVER: case AUTH_UNSET: return (struct authby) { .never = true, }; case AUTH_EAPONLY: return (struct authby) {0}; } bad_case(auth); } size_t jam_authby(struct jambuf *buf, struct authby authby) { #define JAM_AUTHBY(F, N) \ { \ if (authby.F) { \ s += jam_string(buf, sep); \ s += jam_string(buf, #N); \ sep = "+"; \ } \ } size_t s = 0; const char *sep = ""; JAM_AUTHBY(psk, PSK); JAM_AUTHBY(rsasig, RSASIG); JAM_AUTHBY(ecdsa, ECDSA); JAM_AUTHBY(never, AUTH_NEVER); JAM_AUTHBY(null, AUTH_NULL); JAM_AUTHBY(rsasig_v1_5, RSASIG_v1_5); #undef JAM_AUTHBY if (s == 0) { s += jam_string(buf, "none"); } return s; } const char *str_authby(struct authby authby, authby_buf *buf) { struct jambuf jambuf = ARRAY_AS_JAMBUF(buf->buf); jam_authby(&jambuf, authby); return buf->buf; } libreswan-4.14/lib/libswan/binaryscale-iec-60027-2.c000066400000000000000000000051251457372064200216630ustar00rootroot00000000000000/* binary IEC 60027-2 scale, for libreswan * * Copyright (C) 2022 Antony Antony * * 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 "binary-iec-60027-2.h" #include "lswcdefs.h" #include "constants.h" /* for binary_per_kilo */ #include "binaryscale-iec-60027-2.h" const struct binaryscale bin_default = {"", .b = 1, }; const struct binaryscale bin_kilo = {"Ki", .b = 1 * binary_per_kilo, }; const struct binaryscale bin_mega = {"Mi", .b = 1 * binary_per_mega, }; const struct binaryscale bin_giga = {"Gi", .b = 1 * binary_per_giga, }; const struct binaryscale bin_tera = {"Ti", .b = 1 * binary_per_tera, }; const struct binaryscale bin_peta = {"Pi", .b = 1 * binary_per_peta, }; const struct binaryscale bin_exa = {"Ei", .b = 1 * binary_per_exa, }; const struct binaryscale bin_bytedefult = {"", .b = 1}; const struct binaryscale bin_kilobytes = {"KiB", .b = 1 * binary_per_kilo, }; const struct binaryscale bin_megabytes = {"MiB", .b = 1 * binary_per_mega, }; const struct binaryscale bin_gigabytes = {"GiB", .b = 1 * binary_per_giga, }; const struct binaryscale bin_terabytes = {"TiB", .b = 1 * binary_per_tera, }; const struct binaryscale bin_petabytes = {"PiB", .b = 1 * binary_per_peta, }; const struct binaryscale bin_exabytes = {"PiB", .b = 1 * binary_per_exa, }; static const struct binaryscale *binaryscales[] = { &bin_kilo, &bin_mega, &bin_giga, &bin_tera, &bin_peta, &bin_exa, }; static const struct binaryscale *binarybytesscales[] = { &bin_kilobytes, &bin_megabytes, &bin_gigabytes, &bin_terabytes, &bin_petabytes, &bin_exabytes, }; const struct binaryscale *ttobinaryscale(shunk_t cursor) { if (cursor.len == 0) return &bin_default; /* default scaling */ FOR_EACH_ELEMENT(scale, binaryscales) { if (hunk_strcaseeq(cursor, (*scale)->suffix)) return *scale; } return NULL; } const struct binaryscale *ttobinarybytesscale(shunk_t cursor) { if (cursor.len == 0) return &bin_bytedefult; /* default scaling */ FOR_EACH_ELEMENT(scale, binarybytesscales) { if (hunk_strcaseeq(cursor, (*scale)->suffix)) return *scale; } return NULL; } libreswan-4.14/lib/libswan/certs.c000066400000000000000000000046611457372064200171420ustar00rootroot00000000000000/* 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 "passert.h" #include "lswnss.h" /* for same_secitem_as_shunk() */ 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; } enum ike_cert_type cert_ike_type(const struct cert *cert UNUSED) { if (cert == NULL || cert->nss_cert == NULL) { return CERT_NONE; } else { return CERT_X509_SIGNATURE; } } shunk_t cert_der(const struct cert *cert) { if (cert == NULL || cert->nss_cert == NULL) { return null_shunk; } else { return same_secitem_as_shunk(cert->nss_cert->derCert); } } libreswan-4.14/lib/libswan/chunk.c000066400000000000000000000061771457372064200171360ustar00rootroot00000000000000/* 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 /* for strtoul() */ const chunk_t empty_chunk = NULL_HUNK; chunk_t chunk2(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 chunk2(ptr, count); } void free_chunk_content(chunk_t *chunk) { if (chunk->ptr != NULL) { pfree(chunk->ptr); } *chunk = empty_chunk; } void replace_chunk(chunk_t *dest, chunk_t src) { free_chunk_content(dest); *dest = src; } chunk_t clone_bytes_as_chunk(const void *bytes, size_t sizeof_bytes, const char *name) { /* * orig=NULL; size=0 -> NULL * orig=PTR; size=0 -> new PTR (for instance a shunk with PTR = "") * orig=PTR; size>0 -> new PTR */ return chunk2(clone_bytes(bytes, sizeof_bytes, name), sizeof_bytes); } chunk_t clone_bytes_bytes_as_chunk(const void *lhs_ptr, size_t lhs_len, const void *rhs_ptr, size_t rhs_len, const char *name) { void *new = clone_bytes_bytes(lhs_ptr, lhs_len, rhs_ptr, rhs_len, name); return chunk2(new, lhs_len + rhs_len); } void append_chunk_bytes(const char *name, chunk_t *lhs, const void *rhs_ptr, size_t rhs_len) { chunk_t new = clone_bytes_bytes_as_chunk(lhs->ptr, lhs->len, rhs_ptr, rhs_len, name); replace_chunk(lhs, new); } /* * 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 (consisting 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 (!char_isxdigit(pos[0]) || !char_isxdigit(pos[1])) { /* friendly barf for debugging */ llog_passert(&global_logger, HERE, "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-4.14/lib/libswan/ckaid.c000066400000000000000000000063231457372064200170720ustar00rootroot00000000000000/* * 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 "lswnss.h" #include "lswlog.h" #include "lswnss.h" #include "ttodata.h" /* * Return true IFF CKAID starts with all of START (which is in HEX). */ bool ckaid_starts_with(const ckaid_t *ckaid, const char *start) { if (strlen(start) > ckaid->len * 2) { return false; } for (int i = 0; start[i] != '\0'; i++) { const char *p = start + i; unsigned byte = ckaid->ptr[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; } bool ckaid_eq_nss(const ckaid_t *l, const SECItem *r) { return (l->len == r->len && memeq(l->ptr, r->data, r->len)); } size_t jam_ckaid(struct jambuf *buf, const ckaid_t *ckaid) { return jam_hex_bytes(buf, ckaid->ptr, ckaid->len); } const char *str_ckaid(const ckaid_t *ckaid, ckaid_buf *buf) { struct jambuf jam = ARRAY_AS_JAMBUF(buf->buf); jam_ckaid(&jam, ckaid); return buf->buf; } ckaid_t ckaid_from_secitem(const SECItem *const nss_ckaid) { size_t nss_ckaid_len = nss_ckaid->len; /* ckaid = { .len = min(...), } barfs with gcc 11.2.1 */ ckaid_t ckaid = {0}; /* should not be truncated but can be */ ckaid.len = min(nss_ckaid_len, sizeof(ckaid.ptr/*array*/)), pexpect(ckaid.len == nss_ckaid_len); memmove(ckaid.ptr, nss_ckaid->data, ckaid.len); return ckaid; } SECItem same_ckaid_as_secitem(const ckaid_t *ckaid) { SECItem nss_ckaid = { .data = (void*)ckaid->ptr, /* NSS doesn't do const */ .len = ckaid->len, .type = siBuffer, }; return nss_ckaid; } /* convert hex string ckaid to binary bin */ err_t string_to_ckaid(const char *string, ckaid_t *ckaid) { if (string == NULL) { return "empty"; } ckaid->len = (strlen(string) + 1) / 2; if (ckaid->len > sizeof(ckaid->ptr/*array*/)) { return "too long"; } /* binlen will be "fixed"; ttodata doesn't take void* */ const char *err = ttodata(string, 0, 16, (void*)ckaid->ptr, ckaid->len, &ckaid->len); if (err != NULL) { return err; } return NULL; } libreswan-4.14/lib/libswan/cloexec_socket.c000066400000000000000000000022751457372064200210130ustar00rootroot00000000000000/* wrap apple's lack of SOCK_CLOEXEC, for libreswan * * Copyright (C) 2022 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 "lsw_socket.h" #ifndef SOCK_CLOEXEC #include #include #include /* for close() */ #endif /* * Hack to get around Darwin's (Apple's) lack of SOCK_CLOEXEC. */ int cloexec_socket(int domain, int type, int protocol) { #ifdef SOCK_CLOEXEC return socket(domain, type|SOCK_CLOEXEC, protocol); #else int sock = socket(domain, type, protocol); int error = errno; if (sock < 0) { return sock; } int e = fcntl(sock, F_SETFD, FD_CLOEXEC); if (e < 0) { close(sock); errno = error; return -1; } return sock; #endif } libreswan-4.14/lib/libswan/clone_shunk_tokens.c000066400000000000000000000037251457372064200217150ustar00rootroot00000000000000/* cloning a token list, for libreswan * * Copyright (C) 2022 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 "passert.h" #include "lswlog.h" /* for dbg() */ shunk_t *clone_shunk_tokens(shunk_t input, const char *delims, where_t where) { if (input.ptr == NULL) { return NULL; } dbg("%s() input: "PRI_SHUNK, __func__, pri_shunk(input)); /* * Pass 1: determine the number of tokens. */ unsigned nr_tokens = 0; shunk_t cursor = input; while (true) { shunk_t token = shunk_token(&cursor, NULL/*delim*/, delims); if (token.ptr == NULL) { break; } if (token.len == 0) { continue; } nr_tokens++; } if (nr_tokens == 0) { return NULL; } /* * Allocate. */ size_t sizeof_tokens = (nr_tokens + 1) * sizeof(shunk_t); void *buf = alloc_bytes(sizeof_tokens + input.len, where->func); shunk_t *tokens = buf; char *strings = buf + sizeof_tokens; dbg("%s() nr tokens %u, sizeof-tokens %zu sizeof-strings %zu", __func__, nr_tokens, sizeof_tokens, input.len); /* * pass 2: copy things over. */ memcpy(strings, input.ptr, input.len); cursor = shunk2(strings, input.len); unsigned nr = 0; while (true) { shunk_t token = shunk_token(&cursor, NULL/*delim*/, delims); if (token.ptr == NULL) { break; } if (token.len == 0) { continue; } tokens[nr] = token; dbg("%s() %d: "PRI_SHUNK, __func__, nr, pri_shunk(token)); nr++; } tokens[nr] = null_shunk; return tokens; } libreswan-4.14/lib/libswan/constants.c000066400000000000000000001702231457372064200200340ustar00rootroot00000000000000/* * 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 * Copyright (C) 2020 Yulia Kuzovkova * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT 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 "passert.h" #include "constants.h" #include "enum_names.h" #include "lswlog.h" #include "ip_said.h" /* for SPI_PASS et.al. */ #include "secrets.h" /* for enum privae_key_kind */ 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 = { 0, IKEv2, ARRAY_REF(ike_version_name), "IKE", /* 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) */ static 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", }; 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), "ISAKMP_NEXT_", /* prefix */ NULL }; enum_names ikev1_payload_names = { ISAKMP_NEXT_NONE, ISAKMP_NEXT_GAP, ARRAY_REF(payload_name_ikev1), "ISAKMP_NEXT_", /* 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 */ 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 */ }; /* * 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), 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), NULL, /* prefix */ &payload_names_ikev1_private_use }; enum_names payload_names_ikev1orv2 = { ISAKMP_NEXT_NONE, ISAKMP_NEXT_GAP, ARRAY_REF(payload_name_ikev1), 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 */ "ISAKMP_v2_GSA_AUTH", /* draft-yeung-g-ikev2 */ "ISAKMP_v2_GSA_REGISTRATION", /* draft-yeung-g-ikev2 */ "ISAKMP_v2_GSA_REKEY", /* draft-yeung-g-ikev2 */ "ISAKMP_v2_UNASSIGNED_42", /* avoid hole in enum */ "ISAKMP_v2_IKE_INTERMEDIATE", }; 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_INTERMEDIATE, 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 isakmp_xchg_type_names = { 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 */ static const char *const isakmp_flag_name[] = { "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", }; const struct enum_names isakmp_flag_names = { ISAKMP_FLAGS_v1_ENCRYPTION_IX, ISAKMP_FLAGS_RESERVED_BIT7_IX, ARRAY_REF(isakmp_flag_name), NULL, /* prefix */ NULL, /* next */ }; /* Situation BITS definition for IPsec DOI */ static const char *const sit_bit_name[] = { #define P(N) [N##_IX] = #N P(SIT_IDENTITY_ONLY), P(SIT_SECRECY), P(SIT_INTEGRITY), #undef P }; const struct enum_names sit_bit_names = { SIT_IDENTITY_ONLY_IX, SIT_INTEGRITY_IX, ARRAY_REF(sit_bit_name), NULL, /* prefix */ NULL, /* next */ }; /* 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 }; /* 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 ipsec_ipcomp_algo_name[] = { #define P(N) [N] = #N P(IPCOMP_NONE), P(IPCOMP_OUI), P(IPCOMP_DEFLATE), P(IPCOMP_LZS), P(IPCOMP_LZJH), /* 5-47 Reserved for approved algorithms */ /* 48-63 Reserved for private use */ /* 64-255 Unassigned */ #undef P }; enum_names ipsec_ipcomp_algo_names = { IPCOMP_NONE, IPCOMP_LZJH, ARRAY_REF(ipsec_ipcomp_algo_name), "IPCOMP_", /* prefix */ NULL }; /* * IANA IKEv2 Hash Algorithms * https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xhtml#hash-algorithms */ static const char *const ikev2_hash_algorithm_name[] = { "IKEv2_HASH_ALGORITHM_RESERVED", "IKEv2_HASH_ALGORITHM_SHA1", "IKEv2_HASH_ALGORITHM_SHA2_256", "IKEv2_HASH_ALGORITHM_SHA2_384", "IKEv2_HASH_ALGORITHM_SHA2_512", "IKEv2_HASH_ALGORITHM_IDENTITY" /* 6-1023 Unassigned */ }; enum_names ikev2_hash_algorithm_names = { IKEv2_HASH_ALGORITHM_RESERVED, IKEv2_HASH_ALGORITHM_IDENTITY, ARRAY_REF(ikev2_hash_algorithm_name), "IKEv2_HASH_ALGORITHM_", /* 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 ikev1_ike_id_type_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. * * XXX: why not treat them as longs? */ static enum_names ike_idtype_names_fromcert = ID_NR(ID_FROMCERT, ID_FROMCERT, NULL); enum_names ike_id_type_names = ID_NR(ID_NONE, ID_NULL, &ike_idtype_names_fromcert); /* 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_ike_id_type_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 */ static const char *const oakley_attr_bit_name[] = { #define S(E) [E - OAKLEY_ENCRYPTION_ALGORITHM] = #E S(OAKLEY_ENCRYPTION_ALGORITHM), S(OAKLEY_HASH_ALGORITHM), S(OAKLEY_AUTHENTICATION_METHOD), S(OAKLEY_GROUP_DESCRIPTION), S(OAKLEY_GROUP_TYPE), S(OAKLEY_GROUP_PRIME), S(OAKLEY_GROUP_GENERATOR_ONE), S(OAKLEY_GROUP_GENERATOR_TWO), S(OAKLEY_GROUP_CURVE_A), S(OAKLEY_GROUP_CURVE_B), S(OAKLEY_LIFE_TYPE), S(OAKLEY_LIFE_DURATION), S(OAKLEY_PRF), S(OAKLEY_KEY_LENGTH), S(OAKLEY_FIELD_SIZE), S(OAKLEY_GROUP_ORDER), #undef S }; const struct enum_names oakley_attr_bit_names = { OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_GROUP_ORDER, ARRAY_REF(oakley_attr_bit_name), NULL, /*prefix*/ NULL, /*next*/ }; 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_name), 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", "ECN_TUNNEL or old SECCTX", "ESN_64BIT_SEQNUM", "IKEv1_IPSEC_ATTR_UNSPEC_12", /* Maybe Tero knows why it was skipped? */ "SIG_ENC_ALGO_VAL", "ADDRESS_PRESERVATION", "SA_DIRECTION", }; /* * 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)", "NULL", /* ECN_TUNNEL_or_old_SECCTX */ NULL, /* ESN_64BIT_SEQNUM */ NULL, /* IKEv1_IPSEC_ATTR_UNSPEC_12 */ NULL, /* SIG_ENC_ALGO_VAL */ NULL, /* ADDRESS_PRESERVATION */ NULL, /* SA_DIRECTION */ }; 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 }; static enum_names ipsec_attr_desc_tv = { SA_LIFE_TYPE + ISAKMP_ATTR_AF_TV, SA_DIRECTION + ISAKMP_ATTR_AF_TV, ARRAY_REF(ipsec_attr_name), NULL, /* prefix */ &ipsec_private_attr_names }; enum_names ipsec_attr_names = { SA_LIFE_TYPE, SA_DIRECTION, 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[IPSEC_ATTR_VAL_DESCS_ROOF] = { NULL, /* (none) */ &sa_lifetime_names, /* SA_LIFE_TYPE */ NULL, /* SA_LIFE_DURATION */ &oakley_group_names, /* GROUP_DESCRIPTION */ &encapsulation_mode_names, &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 NULL, /* ESN_64BIT_SEQNUM */ NULL, /* IKEv1_IPSEC_ATTR_UNSPEC_12 */ NULL, /* SIG_ENC_ALGO_VAL */ NULL, /* ADDRESS_PRESERVATION */ NULL, /* SA_DIRECTION */ }; /* 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 encapsulation_mode_draft_name[] = { #define P(N) [N - ENCAPSULATION_MODE_UDP_TUNNEL_DRAFTS] = #N P(ENCAPSULATION_MODE_UDP_TUNNEL_DRAFTS), P(ENCAPSULATION_MODE_UDP_TRANSPORT_DRAFTS), #undef P }; enum_names encapsulation_mode_draft_names = { ENCAPSULATION_MODE_UDP_TUNNEL_DRAFTS, ENCAPSULATION_MODE_UDP_TRANSPORT_DRAFTS, ARRAY_REF(encapsulation_mode_draft_name), "ENCAPSULATION_MODE_", /* prefix */ NULL, }; static const char *const encapsulation_mode_rfc_name[] = { #define P(N) [N - ENCAPSULATION_MODE_TUNNEL] = #N P(ENCAPSULATION_MODE_TUNNEL), P(ENCAPSULATION_MODE_TRANSPORT), P(ENCAPSULATION_MODE_UDP_TUNNEL_RFC), P(ENCAPSULATION_MODE_UDP_TRANSPORT_RFC), #undef P }; enum_names encapsulation_mode_names = { ENCAPSULATION_MODE_TUNNEL, ENCAPSULATION_MODE_UDP_TRANSPORT_RFC, ARRAY_REF(encapsulation_mode_rfc_name), "ENCAPSULATION_MODE_", /* prefix */ &encapsulation_mode_draft_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 strings */ 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 strings */ 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_method_name[] = { #define E(S) [S] = #S E(IKEv2_AUTH_RESERVED), E(IKEv2_AUTH_RSA), [IKEv2_AUTH_PSK] = "IKEv2_AUTH_SHARED", E(IKEv2_AUTH_DSS_DIGITAL_SIGNATURE), /* 4 - 8 unassigned */ E(IKEv2_AUTH_ECDSA_SHA2_256_P256), E(IKEv2_AUTH_ECDSA_SHA2_384_P384), E(IKEv2_AUTH_ECDSA_SHA2_512_P521), E(IKEv2_AUTH_GENERIC_SECURE_PASSWORD_AUTHENTICATION_METHOD), /* 12 - RFC 6467 */ E(IKEv2_AUTH_NULL), E(IKEv2_AUTH_DIGSIG), /* 14 - RFC 7427 */ #undef E }; enum_names ikev2_auth_method_names = { IKEv2_AUTH_RESERVED, IKEv2_AUTH_DIGSIG, ARRAY_REF(ikev2_auth_method_name), "IKEv2_AUTH_", /* 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 strings */ 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 v1_notification_name[] = { "v1N_INVALID_PAYLOAD_TYPE", /* 1 */ "v1N_DOI_NOT_SUPPORTED", "v1N_SITUATION_NOT_SUPPORTED", "v1N_INVALID_COOKIE", "v1N_INVALID_MAJOR_VERSION", "v1N_INVALID_MINOR_VERSION", "v1N_INVALID_EXCHANGE_TYPE", "v1N_INVALID_FLAGS", "v1N_INVALID_MESSAGE_ID", "v1N_INVALID_PROTOCOL_ID", "v1N_INVALID_SPI", "v1N_INVALID_TRANSFORM_ID", "v1N_ATTRIBUTES_NOT_SUPPORTED", "v1N_NO_PROPOSAL_CHOSEN", "v1N_BAD_PROPOSAL_SYNTAX", "v1N_PAYLOAD_MALFORMED", "v1N_INVALID_KEY_INFORMATION", "v1N_INVALID_ID_INFORMATION", "v1N_INVALID_CERT_ENCODING", "v1N_INVALID_CERTIFICATE", "v1N_CERT_TYPE_UNSUPPORTED", "v1N_INVALID_CERT_AUTHORITY", "v1N_INVALID_HASH_INFORMATION", "v1N_AUTHENTICATION_FAILED", "v1N_INVALID_SIGNATURE", "v1N_ADDRESS_NOTIFICATION", "v1N_NOTIFY_SA_LIFETIME", "v1N_CERTIFICATE_UNAVAILABLE", "v1N_UNSUPPORTED_EXCHANGE_TYPE", "v1N_UNEQUAL_PAYLOAD_LENGTHS", }; static const char *const v1_notification_connected_name[] = { "v1N_CONNECTED", /* 16384 */ }; static const char *const v1_notification_ipsec_name[] = { "v1N_IPSEC_RESPONDER_LIFETIME", /* 24576 */ "v1N_IPSEC_REPLAY_STATUS", "v1N_IPSEC_INITIAL_CONTACT", }; static const char *const v1_notification_cisco_chatter_name[] = { "v1N_ISAKMP_N_CISCO_HELLO", /* 30000 */ "v1N_ISAKMP_N_CISCO_WWTEBR", "v1N_ISAKMP_N_CISCO_SHUT_UP", }; static const char *const v1_notification_ios_alives_name[] = { "v1N_ISAKMP_N_IOS_KEEP_ALIVE_REQ", /* 32768 */ "v1N_ISAKMP_N_IOS_KEEP_ALIVE_ACK", }; static const char *const v1_notification_dpd_name[] = { "v1N_R_U_THERE", /* 36136 */ "v1N_R_U_THERE_ACK", }; static const char *const v1_notification_juniper_name[] = { /* Next Hop Tunnel Binding */ "v1N_NETSCREEN_NHTB_INFORM", /* 40001 */ }; static const char *const v1_notification_cisco_more_name[] = { "v1N_ISAKMP_N_CISCO_LOAD_BALANCE", /* 40501 */ "v1N_ISAKMP_N_CISCO_UNKNOWN_40502", "v1N_ISAKMP_N_CISCO_PRESHARED_KEY_HASH", }; static enum_names v1_notification_cisco_more_names = { v1N_ISAKMP_N_CISCO_LOAD_BALANCE, v1N_ISAKMP_N_CISCO_PRESHARED_KEY_HASH, ARRAY_REF(v1_notification_cisco_more_name), NULL, /* prefix */ NULL, /* next */ }; static enum_names v1_notification_juniper_names = { v1N_NETSCREEN_NHTB_INFORM, v1N_NETSCREEN_NHTB_INFORM, ARRAY_REF(v1_notification_juniper_name), NULL, /* prefix */ &v1_notification_cisco_more_names }; static enum_names v1_notification_dpd_names = { v1N_R_U_THERE, v1N_R_U_THERE_ACK, ARRAY_REF(v1_notification_dpd_name), NULL, /* prefix */ &v1_notification_juniper_names }; static enum_names v1_notification_ios_alives_names = { v1N_ISAKMP_N_IOS_KEEP_ALIVE_REQ, v1N_ISAKMP_N_IOS_KEEP_ALIVE_ACK, ARRAY_REF(v1_notification_ios_alives_name), NULL, /* prefix */ &v1_notification_dpd_names }; static enum_names v1_notification_cisco_chatter_names = { v1N_ISAKMP_N_CISCO_HELLO, v1N_ISAKMP_N_CISCO_SHUT_UP, ARRAY_REF(v1_notification_cisco_chatter_name), NULL, /* prefix */ &v1_notification_ios_alives_names }; static enum_names v1_notification_ipsec_names = { v1N_IPSEC_RESPONDER_LIFETIME, v1N_IPSEC_INITIAL_CONTACT, ARRAY_REF(v1_notification_ipsec_name), NULL, /* prefix */ &v1_notification_cisco_chatter_names }; static enum_names v1_notification_connected_names = { v1N_CONNECTED, v1N_CONNECTED, ARRAY_REF(v1_notification_connected_name), NULL, /* prefix */ &v1_notification_ipsec_names }; enum_names v1_notification_names = { v1N_INVALID_PAYLOAD_TYPE, v1N_UNEQUAL_PAYLOAD_LENGTHS, ARRAY_REF(v1_notification_name), "v1N_", /* prefix */ &v1_notification_connected_names }; static const char *const ikev2_notify_name_private[] = { "v2N_NULL_AUTH", /* 40960, used for mixed OE */ }; static enum_names v2_notification_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", "v2N_INTERMEDIATE_EXCHANGE_SUPPORTED" /* 16438*/, }; static enum_names v2_notification_names_16384 = { v2N_INITIAL_CONTACT, v2N_INTERMEDIATE_EXCHANGE_SUPPORTED, ARRAY_REF(ikev2_notify_name_16384), "v2N_", /* prefix */ &v2_notification_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 v2_notification_names = { v2N_NOTHING_WRONG, v2N_AUTHORIZATION_FAILED, ARRAY_REF(ikev2_notify_name), "v2N_", /* prefix */ &v2_notification_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", /* 7 */ "IKEv2_TS_IPV6_ADDR_RANGE", /* 8 */ "IKEv2_TS_FC_ADDR_RANGE", /* 9; not implemented */ "IKEv2_TS_SECLABEL", /* 10; Early Code Point */ }; enum_names ikev2_ts_type_names = { IKEv2_TS_IPV4_ADDR_RANGE, IKEv2_TS_SECLABEL, 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 */ static const char *const payload_flag_name[] = { "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 */ }; const enum_names payload_flag_names = { ISAKMP_PAYLOAD_FLAG_LIBRESWAN_BOGUS_IX, ISAKMP_PAYLOAD_FLAG_CRITICAL_IX, ARRAY_REF(payload_flag_name), NULL, /* prefix */ NULL, /* next */ }; /* * IKEv2 Security Protocol Identifiers */ /* proposal payload allows IKE=1, AH=2, ESP=3 */ static const char *const ikev2_proposal_protocol_id_name[] = { "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_proposal_protocol_id_names = { IKEv2_SEC_PROTO_IKE, IKEv2_SEC_FC_CT_AUTHENTICATION, ARRAY_REF(ikev2_proposal_protocol_id_name), .en_prefix = "IKEv2_SEC_PROTO_", /* prefix */ }; /* delete payload allows IKE=1, AH=2, ESP=3 */ static const char *const ikev2_delete_protocol_id_name[] = { "IKEv2_SEC_PROTO_IKE", "IKEv2_SEC_PROTO_AH", "IKEv2_SEC_PROTO_ESP", }; enum_names ikev2_delete_protocol_id_names = { IKEv2_SEC_PROTO_IKE, IKEv2_SEC_PROTO_ESP, ARRAY_REF(ikev2_delete_protocol_id_name), .en_prefix = "IKEv2_SEC_PROTO_", /* prefix */ }; /* * Notify payload allows NONE=0, [IKE=1,] AH=2, ESP=3 * https://tools.ietf.org/html/rfc7296#section-3.10 * Technically 1 is not valid but is sent by by Cisco, * and the RFC states we should accept and ignore it: * "If the SPI field is empty, this field MUST be * sent as zero and MUST be ignored on receipt." */ static const char *const ikev2_protocol_id_notify_name[] = { #define E(V) [V] = #V E(IKEv2_SEC_PROTO_NONE), E(IKEv2_SEC_PROTO_IKE), E(IKEv2_SEC_PROTO_AH), E(IKEv2_SEC_PROTO_ESP), #undef E }; enum_names ikev2_notify_protocol_id_names = { IKEv2_SEC_PROTO_NONE, IKEv2_SEC_PROTO_ESP, ARRAY_REF(ikev2_protocol_id_notify_name), .en_prefix = "IKEv2_SEC_PROTO_", /* prefix */ }; /* 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_INTEG_NONE, IKEv2_INTEG_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 secret_kind_name[] = { "SECRET_PSK", "SECRET_RSA", "SECRET_XAUTH", "SECRET_PPK", "SECRET_ECDSA", "SECRET_NULL", "SECRET_INVALID", }; enum_names secret_kind_names = { SECRET_PSK, SECRET_INVALID, ARRAY_REF(secret_kind_name), "SECRET_", /* 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 }; /* EAP - RFC 3748 */ static const char *const eap_code_name[] = { "EAP_CODE_REQUEST", "EAP_CODE_RESPONSE", "EAP_CODE_SUCCESS", "EAP_CODE_FAILURE", }; enum_names eap_code_names = { EAP_CODE_REQUEST, EAP_CODE_FAILURE, ARRAY_REF(eap_code_name), "EAP_CODE_", /* prefix */ NULL }; static const char *const eap_type_name[] = { "EAP_TYPE_TLS", }; enum_names eap_type_names = { EAP_TYPE_TLS, EAP_TYPE_TLS, ARRAY_REF(eap_type_name), "EAP_TYPE_", /* prefix */ NULL }; /* EAP-TLS Flag BITS */ static const char *const eaptls_flag_name[] = { "EAPTLS_FLAG_START", "EAPTLS_FLAG_MORE", "EAPTLS_FLAG_LENGTH", }; const struct enum_names eaptls_flag_names = { EAPTLS_FLAGS_START_IX, EAPTLS_FLAGS_LENGTH_IX, ARRAY_REF(eaptls_flag_name), "EAPTLS_FLAG_", /* prefix */ NULL, /* next */ }; /* magic SPI values (specific to Libreswan */ static const char *const policy_spi_none_name[] = { "0", }; static enum_names policy_spi_none_names = { SPI_NONE, SPI_NONE, ARRAY_REF(policy_spi_none_name), NULL, /* prefix */ NULL }; static const char *const policy_spi_name[] = { "%pass", "%drop", "%reject", "%hold", "%trap", "%ignore", "%trapsubnet", }; enum_names policy_spi_names = { SPI_PASS, SPI_TRAPSUBNET, ARRAY_REF(policy_spi_name), "%", /* prefix */ &policy_spi_none_names }; /* * enum global_timers */ static const char *global_timer_name[] = { #define E(T) [T] = #T E(EVENT_REINIT_SECRET), E(EVENT_SHUNT_SCAN), E(EVENT_PENDING_DDNS), E(EVENT_SD_WATCHDOG), E(EVENT_PENDING_PHASE2), E(EVENT_CHECK_CRLS), E(EVENT_REVIVE_CONNS), E(EVENT_FREE_ROOT_CERTS), E(EVENT_RESET_LOG_LIMITER), E(EVENT_PROCESS_KERNEL_QUEUE), E(EVENT_NAT_T_KEEPALIVE), #undef E }; const struct enum_names global_timer_names = { 0, elemsof(global_timer_name) - 1, ARRAY_REF(global_timer_name), "EVENT_", NULL, }; /* * enum event_type */ static const char *const event_name[] = { #define E(EVENT) [EVENT - EVENT_NULL] = #EVENT E(EVENT_NULL), E(EVENT_RETRANSMIT), E(EVENT_CRYPTO_TIMEOUT), #undef E }; static const enum_names event_names = { EVENT_NULL, EVENT_CRYPTO_TIMEOUT, ARRAY_REF(event_name), "EVENT_", /* prefix */ NULL }; static const char *const event_sa_name[] = { #define E(EVENT) [EVENT - EVENT_SA_DISCARD] = #EVENT E(EVENT_SA_DISCARD), E(EVENT_SA_REPLACE), E(EVENT_SA_EXPIRE), #undef E }; static const enum_names event_sa_names = { EVENT_SA_DISCARD, EVENT_SA_EXPIRE, ARRAY_REF(event_sa_name), "EVENT_SA_", /* prefix */ &event_names, }; static const char *const event_v1_name[] = { #define E(EVENT) [EVENT - EVENT_v1_SEND_XAUTH] = #EVENT E(EVENT_v1_SEND_XAUTH), E(EVENT_v1_DPD), E(EVENT_v1_DPD_TIMEOUT), E(EVENT_v1_PAM_TIMEOUT), E(EVENT_v1_REPLACE_IF_USED), #undef E }; static const enum_names event_v1_names = { EVENT_v1_SEND_XAUTH, EVENT_v1_REPLACE_IF_USED, ARRAY_REF(event_v1_name), "EVENT_v1_", /* prefix */ &event_sa_names }; static const char *const event_v2_name[] = { #define E(EVENT) [EVENT - EVENT_v2_REKEY] = #EVENT E(EVENT_v2_REKEY), E(EVENT_v2_REAUTH), E(EVENT_v2_LIVENESS), E(EVENT_v2_ADDR_CHANGE), #undef E }; static const enum_names event_v2_names = { EVENT_v2_REKEY, EVENT_v2_ADDR_CHANGE, ARRAY_REF(event_v2_name), "EVENT_v2_", /* prefix */ &event_v1_names, }; static const char *const event_retain_name[] = { #define E(EVENT) [EVENT - EVENT_RETAIN] = #EVENT E(EVENT_RETAIN), #undef E }; const enum_names event_type_names = { EVENT_RETAIN, EVENT_RETAIN, ARRAY_REF(event_retain_name), "EVENT_", /* prefix */ &event_v2_names, }; /* 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, &isakmp_xchg_type_names, &ikev1_protocol_names, &isakmp_transformid_names, &ah_transformid_names, &esp_transformid_names, &ipsec_ipcomp_algo_names, &ikev1_ike_id_type_names, &ikev2_ike_id_type_names, &ike_cert_type_names, &ikev2_cert_type_names, &certpolicy_type_names, &oakley_attr_names, &ipsec_attr_names, &sa_lifetime_names, &encapsulation_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_method_names, &oakley_group_names, &oakley_group_type_names, &v1_notification_names, &v2_notification_names, &ikev2_ts_type_names, &attr_msg_type_names, &ikev2_proposal_protocol_id_names, &ikev2_delete_protocol_id_names, &ikev2_notify_protocol_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, &secret_kind_names, &ikev2_ppk_id_type_names, &ikev2_redirect_gw_names, &ip_protocol_id_names, &ike_version_names, &payload_flag_names, &oakley_attr_bit_names, &global_timer_names, &event_type_names, &policy_spi_names, &eaptls_flag_names, &pluto_exit_code_names, &ipseckey_algorithm_type_names, &ipseckey_algorithm_config_names, #ifdef KERNEL_XFRM &xfrm_policy_names, #endif }; 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-4.14/lib/libswan/crypt_hash.c000066400000000000000000000103261457372064200201610ustar00rootroot00000000000000/* * Hash algorithms, for libreswan * * Copyright (C) 2016-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 "lswalloc.h" #include "lswlog.h" #include "ike_alg.h" #include "ike_alg_hash_ops.h" #include "crypt_hash.h" #include "crypt_symkey.h" struct crypt_hash { struct hash_context *context; const char *name; const struct hash_desc *desc; struct logger *logger; }; struct crypt_hash *crypt_hash_init(const char *name, const struct hash_desc *hash_desc, struct logger *logger) { DBGF(DBG_CRYPT, "%s hash %s init", name, hash_desc->common.fqn); struct hash_context *context = hash_desc->hash_ops->init(hash_desc, name); if (context == NULL) { return NULL; } struct crypt_hash hash = { .context = context, .name = name, .desc = hash_desc, .logger = logger, }; return clone_thing(hash, name); } void crypt_hash_digest_symkey(struct crypt_hash *hash, const char *name, PK11SymKey *symkey) { if (DBGP(DBG_CRYPT)) { DBG_log("%s hash %s digest %s-key@%p (size %zu)", hash->name, hash->desc->common.fqn, name, symkey, sizeof_symkey(symkey)); DBG_symkey(hash->logger, hash->name, name, symkey); } hash->desc->hash_ops->digest_symkey(hash->context, name, symkey); } void crypt_hash_digest_byte(struct crypt_hash *hash, const char *name, uint8_t byte) { if (DBGP(DBG_CRYPT)) { DBG_log("%s hash %s digest %s 0x%"PRIx8" (%"PRIu8")", hash->name, hash->desc->common.fqn, name, byte, byte); DBG_dump_thing(NULL, byte); } hash->desc->hash_ops->digest_bytes(hash->context, name, &byte, 1); } void crypt_hash_digest_bytes(struct crypt_hash *hash, const char *name, const void *bytes, size_t sizeof_bytes) { if (DBGP(DBG_CRYPT)) { /* * XXX: don't log BYTES using @POINTER syntax as it * might be bogus - confusing refcnt.awk. */ DBG_log("%s hash %s digest %s (%p length %zu)", hash->name, hash->desc->common.fqn, name, bytes, sizeof_bytes); DBG_dump(NULL, bytes, sizeof_bytes); } hash->desc->hash_ops->digest_bytes(hash->context, name, bytes, sizeof_bytes); } void crypt_hash_final_bytes(struct crypt_hash **hashp, uint8_t *bytes, size_t sizeof_bytes) { struct crypt_hash *hash = *hashp; /* Must be correct, else hash code can crash. */ passert(sizeof_bytes == hash->desc->hash_digest_size); hash->desc->hash_ops->final_bytes(&hash->context, bytes, sizeof_bytes); if (DBGP(DBG_CRYPT)) { DBG_log("%s hash %s final bytes@%p (length %zu)", hash->name, hash->desc->common.fqn, bytes, sizeof_bytes); DBG_dump(NULL, bytes, sizeof_bytes); } pfree(*hashp); *hashp = hash = NULL; } struct crypt_mac crypt_hash_final_mac(struct crypt_hash **hashp) { struct crypt_hash *hash = *hashp; struct crypt_mac output = { .len = hash->desc->hash_digest_size, }; passert(output.len <= sizeof(output.ptr/*array*/)); hash->desc->hash_ops->final_bytes(&hash->context, output.ptr, output.len); if (DBGP(DBG_CRYPT)) { DBG_log("%s hash %s final length %zu", hash->name, hash->desc->common.fqn, output.len); DBG_dump_hunk(NULL, output); } pfree(*hashp); *hashp = hash = NULL; return output; } PK11SymKey *crypt_hash_symkey(const char *name, const struct hash_desc *hash_desc, const char *symkey_name, PK11SymKey *symkey, struct logger *logger) { DBGF(DBG_CRYPT, "%s hash %s %s-key@%p (size %zu)", name, hash_desc->common.fqn, symkey_name, symkey, sizeof_symkey(symkey)); struct crypt_hash *hash = crypt_hash_init(name, hash_desc, logger); crypt_hash_digest_symkey(hash, symkey_name, symkey); struct crypt_mac out = crypt_hash_final_mac(&hash); PK11SymKey *key = symkey_from_hunk(name, out, logger); return key; } libreswan-4.14/lib/libswan/crypt_mac.c000066400000000000000000000013201457372064200177700ustar00rootroot00000000000000/* 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-4.14/lib/libswan/crypt_prf.c000066400000000000000000000155701457372064200200330ustar00rootroot00000000000000/* * PRF helper functions, for libreswan * * Copyright (C) 2007-2008 Michael C. Richardson * Copyright (C) 2008 Antony Antony * Copyright (C) 2009 David McCullough * Copyright (C) 2009-2012 Avesh Agarwal * Copyright (C) 2009-2010 Paul Wouters * Copyright (C) 2010 Tuomo Soini * Copyright (C) 2012-2013 Paul Wouters * Copyright (C) 2012 Wes Hardaker * Copyright (C) 2013 Antony Antony * Copyright (C) 2013-2019 D. Hugh Redelmeier * Copyright (C) 2015 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 "lswalloc.h" #include "lswlog.h" #include "ike_alg.h" #include "crypt_prf.h" #include "crypt_symkey.h" #include "ike_alg_prf_mac_ops.h" size_t crypt_prf_fips_key_size_min(const struct prf_desc *prf) { /* * FIPS 198 Section 3 CRYPTOGRAPHIC KEYS requires keys to be * >= "L/2" (where L is the block-size in bytes of the hash * function). * * FIPS 198-1 Section 3 instead cites SP 800-107 which dictates * requirements in Section 5.4.3 */ return prf->prf_key_size / 2; } size_t crypt_prf_fips_key_size_floor(void) { static size_t key_size_floor = 0; if (key_size_floor == 0) { key_size_floor = SIZE_MAX; for (const struct prf_desc **prfp = next_prf_desc(NULL); prfp != NULL; prfp = next_prf_desc(prfp)) { if ((*prfp)->common.fips.approved) { key_size_floor = min(key_size_floor, crypt_prf_fips_key_size_min(*prfp)); } } } return key_size_floor; } struct crypt_prf { struct prf_context *context; const char *name; const struct prf_desc *desc; struct logger *logger; }; static struct crypt_prf *wrap(const struct prf_desc *prf_desc, const char *name, struct logger *logger, struct prf_context *context) { struct crypt_prf *prf = NULL; if (context != NULL) { prf = alloc_thing(struct crypt_prf, name); *prf = (struct crypt_prf) { .context = context, .name = name, .desc = prf_desc, .logger = logger, }; } /* not @POINTER, confuses refcnt.awk */ DBGF(DBG_CRYPT, "%s PRF %s %p", name, prf_desc->common.fqn, prf); return prf; } struct crypt_prf *crypt_prf_init_bytes(const char *name, const struct prf_desc *prf_desc, const char *key_name, const void *key, size_t key_size, struct logger *logger) { if (DBGP(DBG_CRYPT)) { DBG_log("%s PRF %s init %s-chunk@%p (length %zd)", name, prf_desc->common.fqn, key_name, key, key_size); DBG_dump(NULL, key, key_size); } return wrap(prf_desc, name, logger, prf_desc->prf_mac_ops->init_bytes(prf_desc, name, key_name, key, key_size, logger)); } struct crypt_prf *crypt_prf_init_symkey(const char *name, const struct prf_desc *prf_desc, const char *key_name, PK11SymKey *key, struct logger *logger) { if (DBGP(DBG_CRYPT)) { DBG_log("%s PRF %s init %s-key@%p (size %zd)", name, prf_desc->common.fqn, key_name, key, sizeof_symkey(key)); DBG_symkey(logger, name, key_name, key); } return wrap(prf_desc, name, logger, prf_desc->prf_mac_ops->init_symkey(prf_desc, name, key_name, key, logger)); } /* * Accumulate data. */ void crypt_prf_update_symkey(struct crypt_prf *prf, const char *name, PK11SymKey *update) { if (DBGP(DBG_CRYPT)) { DBG_log("%s PRF %s update %s-key@%p (size %zd)", prf->name, prf->desc->common.fqn, name, update, sizeof_symkey(update)); DBG_symkey(prf->logger, prf->name, name, update); } prf->desc->prf_mac_ops->digest_symkey(prf->context, name, update); } void crypt_prf_update_byte(struct crypt_prf *prf, const char *name, uint8_t update) { if (DBGP(DBG_CRYPT)) { DBG_log("%s PRF %s update %s 0x%"PRIx8" (%"PRIu8")", prf->name, prf->desc->common.fqn, name, update, update); DBG_dump_thing(NULL, update); } prf->desc->prf_mac_ops->digest_bytes(prf->context, name, &update, 1); } void crypt_prf_update_bytes(struct crypt_prf *prf, const char *name, const void *update, size_t sizeof_update) { if (DBGP(DBG_CRYPT)) { /* * XXX: don't log UPDATE using @POINTER syntax as it * might be bogus - confusing refcnt.awk. */ DBG_log("%s PRF %s update %s (%p length %zu)", prf->name, prf->desc->common.fqn, name, update, sizeof_update); DBG_dump(NULL, update, sizeof_update); } prf->desc->prf_mac_ops->digest_bytes(prf->context, name, update, sizeof_update); } PK11SymKey *crypt_prf_final_symkey(struct crypt_prf **prfp) { struct crypt_prf *prf = *prfp; PK11SymKey *tmp = prf->desc->prf_mac_ops->final_symkey(&prf->context); if (DBGP(DBG_CRYPT)) { DBG_log("%s PRF %s final-key@%p (size %zu)", (*prfp)->name, (*prfp)->desc->common.fqn, tmp, sizeof_symkey(tmp)); DBG_symkey((*prfp)->logger, (*prfp)->name, "key", tmp); } pfree(*prfp); *prfp = prf = NULL; return tmp; } void crypt_prf_final_bytes(struct crypt_prf **prfp, void *bytes, size_t sizeof_bytes) { struct crypt_prf *prf = *prfp; prf->desc->prf_mac_ops->final_bytes(&prf->context, bytes, sizeof_bytes); if (DBGP(DBG_CRYPT)) { DBG_log("%s PRF %s final-bytes@%p (length %zu)", (*prfp)->name, (*prfp)->desc->common.fqn, bytes, sizeof_bytes); DBG_dump(NULL, bytes, sizeof_bytes); } pfree(*prfp); *prfp = prf = NULL; } struct crypt_mac crypt_prf_final_mac(struct crypt_prf **prfp, const struct integ_desc *integ) { struct crypt_prf *prf = *prfp; /* get the MAC's length, INTEG trumps PRF */ struct crypt_mac output; if (integ != NULL) { /* integ derived from prf */ passert(integ->prf == prf->desc); /* truncating */ passert(integ->integ_output_size <= prf->desc->prf_output_size); output = (struct crypt_mac) { .len = integ->integ_output_size, }; } else { output = (struct crypt_mac) { .len = prf->desc->prf_output_size, }; } /* extract it, note that PRF's size must be passed in */ passert(prf->desc->prf_output_size <= sizeof(output.ptr/*array*/)); prf->desc->prf_mac_ops->final_bytes(&prf->context, output.ptr, prf->desc->prf_output_size); if (DBGP(DBG_CRYPT)) { DBG_log("%s PRF %s final length %zu", (*prfp)->name, (*prfp)->desc->common.fqn, output.len); DBG_dump_hunk(NULL, output); } /* clean up */ pfree(*prfp); *prfp = prf = NULL; return output; } libreswan-4.14/lib/libswan/crypt_symkey.c000066400000000000000000000413061457372064200205610ustar00rootroot00000000000000/* * SYMKEY manipulation functions, for libreswan * * Copyright (C) 2015-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 "lswalloc.h" #include "lswlog.h" #include "ike_alg.h" #include "crypt_symkey.h" #include "lswfips.h" #include "lswnss.h" #define SPACES " " static PK11SymKey *ephemeral_symkey; void init_crypt_symkey(struct logger *logger) { /* get a secret key */ PK11SlotInfo *slot = PK11_GetBestSlot(CKM_AES_KEY_GEN, lsw_nss_get_password_context(logger)); if (slot == NULL) { char error[LOG_WIDTH]; struct jambuf buf[1] = { ARRAY_AS_JAMBUF(error), }; jam(buf, "NSS: ephemeral slot error: "); jam_nss_error_code(buf, PR_GetError()); fatal(PLUTO_EXIT_FAIL, logger, "%s", error); } ephemeral_symkey = PK11_KeyGen(slot, CKM_AES_KEY_GEN, NULL, 128/8, NULL); PK11_FreeSlot(slot); /* reference counted */ if (DBGP(DBG_CRYPT)) { DBG_symkey(logger, SPACES, "ephemeral", ephemeral_symkey); } } void release_symkey(const char *prefix, const char *name, PK11SymKey **key) { if (*key != NULL) { DBGF(DBG_REFCNT, "%s: delref %s-key@%p", prefix, name, *key); PK11_FreeSymKey(*key); } else { DBGF(DBG_REFCNT, "%s: delref %s-key@NULL", prefix, name); } *key = NULL; } PK11SymKey *reference_symkey(const char *prefix, const char *name, PK11SymKey *key) { if (key != NULL) { DBGF(DBG_REFCNT, "%s: addref %s-key@%p", prefix, name, key); PK11_ReferenceSymKey(key); } else { DBGF(DBG_REFCNT, "%s: addref %s-key@NULL", prefix, name); } return key; } size_t sizeof_symkey(PK11SymKey *key) { if (key == NULL) { return 0; } else { return PK11_GetKeyLength(key); } } void jam_symkey(struct jambuf *buf, const char *name, PK11SymKey *key) { if (key == NULL) { /* * For instance, when a zero-length key gets extracted * from an existing key. */ jam(buf, "%s-key@NULL", name); } else { jam(buf, "%s-key@%p (%zd-bytes, ", name, key, sizeof_symkey(key)); jam_nss_ckm(buf, PK11_GetMechanism(key)); jam(buf, ")"); } } void DBG_symkey(struct logger *logger, const char *prefix, const char *name, PK11SymKey *key) { LLOG_JAMBUF(DEBUG_STREAM, logger, buf) { jam(buf, "%s: ", prefix); jam_symkey(buf, name, key); } #if 0 if (DBGP(DBG_CRYPT)) { if (libreswan_fipsmode()) { DBG_log("%s secured by FIPS", prefix); } else { chunk_t bytes = chunk_from_symkey(prefix, key, logger); /* NULL suppresses the dump header */ DBG_dump_hunk(NULL, bytes); free_chunk_content(&bytes); } } #endif } 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, struct logger *logger) { #define DBG_DERIVE() \ LLOG_JAMBUF(DEBUG_STREAM, logger, buf) { \ jam_nss_ckm(buf, derive); \ jam_string(buf, ":"); \ } \ LLOG_JAMBUF(DEBUG_STREAM, logger, buf) { \ jam_string(buf, SPACES"target: "); \ jam_nss_ckm(buf, target_mechanism); \ } \ if (flags != 0) { \ LLOG_JAMBUF(DEBUG_STREAM, logger, buf) { \ jam_string(buf, SPACES"flags: "); \ jam_nss_ckf(buf, flags); \ } \ } \ if (key_size != 0) { \ LLOG_JAMBUF(DEBUG_STREAM, logger, buf) { \ jam(buf, SPACES "key_size: %d-bytes", \ key_size); \ } \ } \ LLOG_JAMBUF(DEBUG_STREAM, logger, buf) { \ jam_string(buf, SPACES"base: "); \ jam_symkey(buf, "base", base_key); \ } \ if (operation != CKA_DERIVE) { \ LLOG_JAMBUF(DEBUG_STREAM, logger, buf) { \ jam_string(buf, SPACES"operation: "); \ jam_nss_cka(buf, operation); \ } \ } \ if (params != NULL) { \ LLOG_JAMBUF(DEBUG_STREAM, logger, buf) { \ jam(buf, SPACES "params: %d-bytes@%p", \ params->len, params->data); \ } \ } if (DBGP(DBG_CRYPT)) { DBG_DERIVE(); } PK11SymKey *target_key = PK11_DeriveWithFlags(base_key, derive, params, target_mechanism, operation, key_size, flags); if (target_key == NULL) { JAMBUF(buf) { jam_string(buf, "NSS: "); jam_nss_ckm(buf, derive); jam_string(buf, " failed: "); jam_nss_error_code(buf, PR_GetError()); /* XXX: hack - double copy */ llog_pexpect(logger, HERE, PRI_SHUNK, pri_shunk(jambuf_as_shunk(buf))); } DBG_DERIVE(); } else if (DBGP(DBG_REFCNT)) { LLOG_JAMBUF(DEBUG_STREAM, logger, buf) { jam_string(buf, SPACES"result: newref "); jam_symkey(buf, target_name, target_key); jam(buf, PRI_WHERE, pri_where(where)); } } return target_key; #undef DBG_DERIVE } /* * Merge a symkey and an array of bytes into a new SYMKEY using * DERIVE. * * derive: the operation that is to be performed; target: the * mechanism/type of the resulting symkey. */ static PK11SymKey *merge_symkey_bytes(const char *result_name, PK11SymKey *base_key, const void *data, size_t sizeof_data, CK_MECHANISM_TYPE derive, CK_MECHANISM_TYPE target, struct logger *logger) { passert(sizeof_data > 0); CK_KEY_DERIVATION_STRING_DATA string = { .pData = (void *)data, .ulLen = sizeof_data, }; SECItem data_param = { .data = (unsigned char*)&string, .len = sizeof(string), }; CK_ATTRIBUTE_TYPE operation = CKA_DERIVE; int key_size = 0; return crypt_derive(base_key, derive, &data_param, result_name, target, operation, key_size, /*flags*/0, HERE, logger); } /* * Merge two SYMKEYs into a new SYMKEY using DERIVE. * * derive: the operation to be performed; target: the mechanism/type * of the resulting symkey. */ static PK11SymKey *merge_symkey_symkey(const char *result_name, PK11SymKey *base_key, PK11SymKey *key, CK_MECHANISM_TYPE derive, CK_MECHANISM_TYPE target, struct logger *logger) { CK_OBJECT_HANDLE key_handle = PK11_GetSymKeyHandle(key); SECItem key_param = { .data = (unsigned char*)&key_handle, .len = sizeof(key_handle) }; CK_ATTRIBUTE_TYPE operation = CKA_DERIVE; int key_size = 0; return crypt_derive(base_key, derive, &key_param, result_name, target, operation, key_size, /*flags*/0, HERE, logger); } /* * Extract a SYMKEY from an existing SYMKEY. */ static PK11SymKey *symkey_from_symkey(const char *result_name, PK11SymKey *base_key, CK_MECHANISM_TYPE target, CK_FLAGS flags, size_t key_offset, size_t key_size, where_t where, struct logger *logger) { /* spell out all the parameters */ CK_EXTRACT_PARAMS bs = key_offset * BITS_PER_BYTE; SECItem param = { .data = (unsigned char*)&bs, .len = sizeof(bs), }; CK_MECHANISM_TYPE derive = CKM_EXTRACT_KEY_FROM_KEY; CK_ATTRIBUTE_TYPE operation = CKA_FLAGS_ONLY; if (DBGP(DBG_CRYPT)) { DBG_log(SPACES "key-offset: %zd, key-size: %zd", key_offset, key_size); } return crypt_derive(base_key, derive, ¶m, result_name, target, operation, key_size, flags, where, logger); } /* * For on-wire algorithms. */ chunk_t chunk_from_symkey(const char *name, PK11SymKey *symkey, struct logger *logger) { SECStatus status; if (symkey == NULL) { DBGF(DBG_CRYPT, "%s NULL key has no bytes", name); return EMPTY_CHUNK; } size_t sizeof_bytes = sizeof_symkey(symkey); if (DBGP(DBG_CRYPT)) { DBG_log("%s extracting all %zd bytes of key@%p", name, sizeof_bytes, symkey); DBG_symkey(logger, name, "symkey", symkey); } /* get a secret key */ PK11SymKey *ephemeral_key = ephemeral_symkey; /* * Ensure that the source key shares a slot with the * ephemeral_key. The "move" always returns something that * needs to be released (if no move is needed, the reference * count is incremented). */ PK11SymKey *slot_key; { PK11SlotInfo *slot = PK11_GetSlotFromKey(ephemeral_key); slot_key = PK11_MoveSymKey(slot, CKA_UNWRAP, 0, 0, symkey); PK11_FreeSlot(slot); /* reference counted */ passert(slot_key != NULL); } if (DBGP(DBG_REFCNT)) { if (slot_key == symkey) { /* output should mimic reference_symkey() */ DBG_log("%s: slot-key@%p: addref sym-key@%p", name, slot_key, symkey); } else { DBG_symkey(logger, name, "newref slot", slot_key); } } SECItem wrapped_key; /* Round up the wrapped key length to a 16-byte boundary. */ wrapped_key.len = (sizeof_bytes + 15) & ~15; wrapped_key.data = alloc_bytes(wrapped_key.len, name); DBGF(DBG_CRYPT, "sizeof bytes %d", wrapped_key.len); status = PK11_WrapSymKey(CKM_AES_ECB, NULL, ephemeral_key, slot_key, &wrapped_key); passert(status == SECSuccess); if (DBGP(DBG_CRYPT)) { LLOG_JAMBUF(DEBUG_STREAM, logger, buf) { jam_string(buf, "wrapper: "); jam_nss_secitem(buf, &wrapped_key); } } void *bytes = alloc_bytes(wrapped_key.len, name); unsigned int out_len = 0; status = PK11_Decrypt(ephemeral_key, CKM_AES_ECB, NULL, bytes, &out_len, wrapped_key.len, wrapped_key.data, wrapped_key.len); pfreeany(wrapped_key.data); release_symkey(name, "slot-key", &slot_key); passert(status == SECSuccess); passert(out_len >= sizeof_bytes); if (DBGP(DBG_CRYPT)) { DBG_log("%s extracted len %d bytes at %p", name, out_len, bytes); DBG_dump("unwrapped:", bytes, out_len); } return (chunk_t) { .ptr = bytes, .len = sizeof_bytes, }; } /* * Extract SIZEOF_SYMKEY bytes of keying material as a generic * key. * * Since NSS NSS expects a key's mechanism to match the NSS algorithm * the key is intended for, this generic key cannot be used for * encryption and/or PRF calculation. Instead use encrypt_key_*() or * prf_key_*(). * * Offset into the SYMKEY is in BYTES. */ PK11SymKey *symkey_from_bytes(const char *name, const uint8_t *bytes, size_t sizeof_bytes, struct logger *logger) { if (sizeof_bytes == 0) { /* hopefully caller knows what they are doing */ return NULL; } PK11SymKey *scratch = ephemeral_symkey; PK11SymKey *tmp = merge_symkey_bytes(name, scratch, bytes, sizeof_bytes, CKM_CONCATENATE_DATA_AND_BASE, CKM_EXTRACT_KEY_FROM_KEY, logger); passert(tmp != NULL); /* * Something of an old code hack. Keys fed to the hasher, for * instance, get this type. */ CK_FLAGS flags = 0; CK_MECHANISM_TYPE target = CKM_EXTRACT_KEY_FROM_KEY; PK11SymKey *key = symkey_from_symkey(name, tmp, target, flags, 0, sizeof_bytes, HERE, logger); passert(key != NULL); release_symkey(name, "tmp", &tmp); return key; } PK11SymKey *encrypt_key_from_bytes(const char *name, const struct encrypt_desc *encrypt, const uint8_t *bytes, size_t sizeof_bytes, where_t where, struct logger *logger) { PK11SymKey *scratch = ephemeral_symkey; PK11SymKey *tmp = merge_symkey_bytes(name, scratch, bytes, sizeof_bytes, CKM_CONCATENATE_DATA_AND_BASE, CKM_EXTRACT_KEY_FROM_KEY, logger); passert(tmp != NULL); PK11SymKey *key = encrypt_key_from_symkey_bytes(name, encrypt, 0, sizeof_bytes, tmp, where, logger); passert(key != NULL); release_symkey(name, "tmp", &tmp); return key; } PK11SymKey *prf_key_from_bytes(const char *name, const struct prf_desc *prf, const uint8_t *bytes, size_t sizeof_bytes, where_t where, struct logger *logger) { PK11SymKey *scratch = ephemeral_symkey; PK11SymKey *tmp = merge_symkey_bytes(name, scratch, bytes, sizeof_bytes, CKM_CONCATENATE_DATA_AND_BASE, CKM_EXTRACT_KEY_FROM_KEY, logger); passert(tmp != NULL); PK11SymKey *key = prf_key_from_symkey_bytes(name, prf, 0, sizeof_bytes, tmp, where, logger); passert(key != NULL); release_symkey(name, "tmp", &tmp); return key; } /* * Append new keying material to an existing key; replace the existing * key with the result. * * Use this to chain a series of concat operations. */ void append_symkey_symkey(PK11SymKey **lhs, PK11SymKey *rhs, struct logger *logger) { PK11SymKey *newkey = merge_symkey_symkey("result", *lhs, rhs, CKM_CONCATENATE_BASE_AND_KEY, PK11_GetMechanism(*lhs), logger); release_symkey(__func__, "lhs", lhs); *lhs = newkey; } void append_symkey_bytes(const char *name, PK11SymKey **lhs, const void *rhs, size_t sizeof_rhs, struct logger *logger) { if (sizeof_rhs == 0) { /* no change required; stops nss crash */ return; } PK11SymKey *newkey = merge_symkey_bytes(name, *lhs, rhs, sizeof_rhs, CKM_CONCATENATE_BASE_AND_DATA, PK11_GetMechanism(*lhs), logger); release_symkey(__func__, "lhs", lhs); *lhs = newkey; } void prepend_bytes_to_symkey(const char *result, const void *lhs, size_t sizeof_lhs, PK11SymKey **rhs, struct logger *logger) { /* copy the existing KEY's type (mechanism). */ PK11SymKey *newkey = merge_symkey_bytes(result, *rhs, lhs, sizeof_lhs, CKM_CONCATENATE_DATA_AND_BASE, PK11_GetMechanism(*rhs), logger); release_symkey(__func__, "rhs", rhs); *rhs = newkey; } void append_symkey_byte(PK11SymKey **lhs, uint8_t rhs, struct logger *logger) { append_symkey_bytes("result", lhs, &rhs, sizeof(rhs), logger); } /* * Extract SIZEOF_SYMKEY bytes of keying material as a PRF key. * * 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, struct logger *logger) { /* * NSS expects a key's mechanism to match the NSS algorithm * the key is intended for. If this is wrong then the * operation fails. * * Unfortunately, some algorithms are not implemented by NSS, * so the correct key type can't always be specified. For * those specify CKM_VENDOR_DEFINED. * * XXX: this function should be part of prf_ops. */ CK_FLAGS flags; CK_MECHANISM_TYPE mechanism; if (prf->nss.mechanism == 0) { flags = 0; mechanism = CKM_VENDOR_DEFINED; } else { flags = CKF_SIGN; mechanism = prf->nss.mechanism; } return symkey_from_symkey(name, source_key, mechanism, flags, symkey_start_byte, sizeof_symkey, where, logger); } /* * Extract SIZEOF_SYMKEY bytes of keying material as an ENCRYPTER key * (i.e., can be used to encrypt/decrypt data using ENCRYPTER). * * 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, struct logger *logger) { /* * NSS expects a key's mechanism to match the NSS algorithm * the key is intended for. If this is wrong then the * operation fails. * * Unfortunately, some algorithms are not implemented by NSS, * so the correct key type can't always be specified. For * those specify CKM_VENDOR_DEFINED. * * XXX: This function should be part of encrypt_ops. */ CK_FLAGS flags; CK_MECHANISM_TYPE mechanism; if (encrypt->nss.mechanism == 0) { flags = 0; mechanism = CKM_VENDOR_DEFINED; } else { flags = CKF_ENCRYPT | CKF_DECRYPT; mechanism = encrypt->nss.mechanism; } return symkey_from_symkey(name, source_key, mechanism, flags, symkey_start_byte, sizeof_symkey, where, logger); } PK11SymKey *key_from_symkey_bytes(const char *result_name, PK11SymKey *source_key, size_t next_byte, size_t sizeof_key, where_t where, struct logger *logger) { if (sizeof_key == 0) { return NULL; } else { return symkey_from_symkey(result_name, source_key, CKM_EXTRACT_KEY_FROM_KEY, 0, next_byte, sizeof_key, where, logger); } } /* * XOR a symkey with a chunk. * * XXX: hmac.c had very similar code, only, instead of * target=CKM_CONCATENATE_BASE_AND_DATA it used * target=hasher-to-ckm(hasher). * * hasher-to-ckm mapped hasher->common.alg_id to CMK vis: OAKLEY_MD5 -> * CKM_MD5; OAKLEY_SHA1 -> CKM_SHA_1; OAKLEY_SHA2_256 -> CKM_SHA256; * OAKLEY_SHA2_384 -> CKM_SHA384; OAKLEY_SHA2_512 -> CKM_SHA512; only * in the default case it would set target to 0x80000000???? */ PK11SymKey *xor_symkey_chunk(PK11SymKey *lhs, chunk_t rhs, struct logger *logger) { return merge_symkey_bytes("result", lhs, rhs.ptr, rhs.len, CKM_XOR_BASE_AND_DATA, CKM_CONCATENATE_BASE_AND_DATA, logger); } libreswan-4.14/lib/libswan/datatot.c000066400000000000000000000122561457372064200174610ustar00rootroot00000000000000/* * 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 "ttodata.h" #include "passert.h" static void convert(const char *src, size_t nreal, int format, char *out); /* * - datatot - convert data bytes to text * true length (with NUL) for success */ size_t datatot(const unsigned char *src, size_t srclen, int format, /* character indicating what format */ char *dst, size_t dstlen) /* need not be valid if dstlen is 0 */ { 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': breakevery = 8; inblocksize = 1; outblocksize = 2; prefix = "0x"; format = 'x'; break; case 'x': inblocksize = 1; outblocksize = 2; prefix = "0x"; break; case ':': breakevery = 2; breakchar = ':'; inblocksize = 1; outblocksize = 2; prefix = ""; format = 'x'; break; 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; } 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(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-4.14/lib/libswan/debug.c000066400000000000000000000047101457372064200171030ustar00rootroot00000000000000/* 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 /* start of debug-all */ D(DBG_BASE, "debug-base", "enable detailed debug logging"), D(DBG_CPU_USAGE, "debug-cpu-usage", "estimate cpu used"), D(DBG_REFCNT, "debug-refcnt", "debug reference counts"), /* end of debug-all */ 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_alias debug_aliases[] = { { "all", DBG_ALL, }, { "tmi", DBG_ALL|DBG_TMI, }, { NULL, LEMPTY, }, }; const struct lmod_info debug_lmod_info = { .names = &debug_names, .mask = DBG_MASK, .aliases = debug_aliases, }; const struct enum_names debug_help = { DBG_floor_IX, DBG_roof_IX - 1, ARRAY_REF(debug.help), NULL, NULL, }; libreswan-4.14/lib/libswan/deltatime.c000066400000000000000000000100331457372064200177600ustar00rootroot00000000000000/* 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 /* for UINT_MAX */ #include "deltatime.h" #include "timescale.h" #include "lswlog.h" const deltatime_t deltatime_zero; /* * Rather than deal with the 'bias' in a -ve timeval, this code * converts everything into +ve timevals. */ static struct timeval negate_timeval(struct timeval tv) { struct timeval zero = {0}; struct timeval res; timersub(&zero, &tv, &res); return res; } deltatime_t deltatime(time_t secs) { return (deltatime_t) DELTATIME_INIT(secs); } struct timeval timeval_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); struct timeval tv = { .tv_sec = ams / 1000, .tv_usec = ams % 1000 * 1000, }; if (ms < 0) { tv = negate_timeval(tv); } return tv; } deltatime_t deltatime_ms(intmax_t milliseconds) { return (deltatime_t) { .dt = timeval_ms(milliseconds), }; } deltatime_t deltatime_timevals_diff(struct timeval a, struct timeval b) { deltatime_t res; timersub(&a, &b, &res.dt); return res; } int timeval_sub_sign(struct timeval l, struct timeval r) { /* sign(l - r) */ if (timercmp(&l, &r, <)) { return -1; } if (timercmp(&l, &r, >)) { return 1; } return 0; } int deltatime_sub_sign(deltatime_t l, deltatime_t r) { return timeval_sub_sign(l.dt, r.dt); } 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_sub(deltatime_t a, deltatime_t b) { deltatime_t res; timersub(&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 deltatime_scale(deltatime_t d, int num, int denom) { /* ??? should check for overflow */ return deltatime((deltasecs(d) * num) / denom); } struct timeval timeval_from_deltatime(deltatime_t d) { return d.dt; } deltatime_t deltatime_from_timeval(struct timeval t) { deltatime_t d = { t, }; return d; } /* * Try to be smart by only printing the precision necessary. For * instance 1, 0.5, ... */ static size_t frac(struct jambuf *buf, intmax_t usec) { int precision = 6; while (usec % 10 == 0 && precision > 1) { precision--; usec = usec / 10; } return jam(buf, ".%0*jd", precision, usec); } size_t jam_deltatime(struct jambuf *buf, deltatime_t d) { size_t s = 0; if (d.dt.tv_sec < 0) { s += jam(buf, "-"); d.dt = negate_timeval(d.dt); } s += jam(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) { struct jambuf buf = ARRAY_AS_JAMBUF(out->buf); jam_deltatime(&buf, d); return out->buf; } libreswan-4.14/lib/libswan/diag.c000066400000000000000000000065641457372064200167320ustar00rootroot00000000000000/* diagnostic return type, for libreswan * * Copyright (C) 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. */ #include #include #include "passert.h" #include "diag.h" #include "lswalloc.h" #include "jambuf.h" #include "lswlog.h" struct diag { char message[1]; /* buffer overflow hack */ }; diag_t diag_va_list(const char *fmt, va_list ap) { return (diag_t)alloc_vprintf(fmt, ap); } diag_t diag(const char *fmt, ...) { va_list ap; va_start(ap, fmt); diag_t d = diag_va_list(fmt, ap); va_end(ap); return d; } diag_t diag_errno(int error, const char *fmt, ...) { char output[LOG_WIDTH]; struct jambuf buf = ARRAY_AS_JAMBUF(output); va_list ap; va_start(ap, fmt); jam_va_list(&buf, fmt, ap); va_end(ap); jam_string(&buf, ": "); jam_errno(&buf, error); return (diag_t)clone_str(output, "diag-errno"); } diag_t diag_diag(diag_t *d, const char *fmt, ...) { va_list fmt_ap; va_start(fmt_ap, fmt); diag_t dd; { /* compute size */ int fmt_len; { va_list ap; va_copy(ap, fmt_ap); fmt_len = vsnprintf(NULL, 0, fmt, ap); va_end(ap); } /* allocate */ passert(fmt_len >= 0); size_t length = fmt_len + 1/*'\0'*/ + strlen((*d)->message); char *buf = alloc_things(char, length, fmt); /* add FMT... */ { va_list ap; va_copy(ap, fmt_ap); vsnprintf(buf, length, fmt, ap); va_end(ap); } /* add D */ strcpy(buf + fmt_len, (*d)->message); passert(strlen(buf) + 1 == length); dd = (diag_t)buf; } pfree_diag(d); va_end(fmt_ap); return dd; } diag_t diag_jambuf(struct jambuf *buf) { shunk_t msg = jambuf_as_shunk(buf); /* no '\0', but there is one */ return (diag_t) clone_hunk_as_string(msg, "diag jambuf"); } diag_t clone_diag(diag_t diag) { /* clone_str() clones NULL as NULL */ return (diag_t) clone_str((char*)diag, "diag clone"); } const char *str_diag(diag_t diag) { /* let caller deal with mess */ return (char*)diag; } void pfree_diag(diag_t *diag) { if (*diag != NULL) { pfree(*diag); *diag = NULL; } } size_t jam_diag(struct jambuf *buf, diag_t diag) { return jam_string(buf, str_diag(diag)); } void llog_diag(lset_t rc_flags, struct logger *logger, diag_t *diag, const char *fmt, ...) { LLOG_JAMBUF(rc_flags, logger, buf) { va_list ap; va_start(ap, fmt); jam_va_list(buf, fmt, ap); va_end(ap); jam_diag(buf, *diag); } pfree_diag(diag); } void fatal_diag(enum pluto_exit_code rc, struct logger *logger, diag_t *diag, const char *fmt, ...) { JAMBUF(buf) { /* XXX: The message format is: * FATAL ERROR: * and not: * FATAL ERROR: */ jam(buf, "FATAL ERROR: "); jam_logger_prefix(buf, logger); va_list ap; va_start(ap, fmt); jam_va_list(buf, fmt, ap); va_end(ap); jam_diag(buf, *diag); jambuf_to_logger(buf, logger, ERROR_FLAGS); } pfree_diag(diag); /* XXX: bother? */ libreswan_exit(rc); } libreswan-4.14/lib/libswan/enum_names.c000066400000000000000000000222371457372064200201500ustar00rootroot00000000000000/* * 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 * Copyright (C) 2020 Yulia Kuzovkova * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT 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 "passert.h" #include "constants.h" #include "enum_names.h" #include "lswlog.h" #include "ip_said.h" /* for SPI_PASS et.al. */ #include "secrets.h" /* for enum privae_key_kind */ /* * 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; } } } /* * the enum_name range containing VAL, or NULL. */ const struct enum_names *enum_range(const struct enum_names *en, unsigned long val, const char **prefix) { *prefix = NULL; for (enum_names *p = en; p != NULL; p = p->en_next_range) { passert(p->en_last - p->en_first + 1 == p->en_checklen); /* return most recent prefix */ if (p->en_prefix != NULL) { *prefix = p->en_prefix; } if (p->en_first <= val && val <= p->en_last) { return p; } } return NULL; } /* * The actual name for VAL, using RANGE; possibly shortened using * PREFIX. */ const char *enum_range_name(const struct enum_names *range, unsigned long val, const char *prefix, bool shorten) { if (range == NULL) { return NULL; } passert(range->en_first <= val && val <= range->en_last); /* can be NULL */ const char *name = range->en_names[val - range->en_first]; if (name != NULL && prefix != NULL && shorten) { /* grr: can't use eat() */ size_t pl = strlen(prefix); return strneq(name, prefix, pl) ? name + pl : name; } else { return name; } } /* look up enum names in an enum_names */ const char *enum_name(enum_names *ed, unsigned long val) { const char *prefix = NULL; /* can be NULL */ const struct enum_names *range = enum_range(ed, val, &prefix); /* can be NULL */ return enum_range_name(range, val, prefix, /*shorten?*/false); } const char *enum_name_short(enum_names *ed, unsigned long val) { const char *prefix = NULL; /* can be NULL */ const struct enum_names *range = enum_range(ed, val, &prefix); /* can be NULL */ return enum_range_name(range, val, prefix, /*shorten?*/true); } size_t jam_enum(struct jambuf *buf, enum_names *en, unsigned long val) { const char *name = enum_name(en, val); if (name == NULL) { if (en->en_prefix != NULL) { jam_string(buf, en->en_prefix); jam_string(buf, "_"); } return jam(buf, "%lu??", val); } return jam_string(buf, name); } size_t jam_enum_short(struct jambuf *buf, enum_names *en, unsigned long val) { const char *name = enum_name_short(en, val); if (name == NULL) { if (en->en_prefix != NULL) { jam_string(buf, en->en_prefix); jam_string(buf, "_"); } return jam(buf, "%lu??", val); } return jam_string(buf, name); } /* * find or construct a string to describe an enum value * * Note: result may or may not be in b. */ const char *str_enum(enum_names *ed, unsigned long val, enum_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 *str_enum_short(enum_names *ed, unsigned long val, enum_buf *b) { const char *prefix; const struct enum_names *range = enum_range(ed, val, &prefix); /* could be NULL */ const char *name = enum_range_name(range, val, prefix, /*shorten?*/true); if (name == NULL) { snprintf(b->buf, sizeof(b->buf), "%lu??", val); name = b->buf; } return name; } /* * 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) { const char *prefix = NULL; for (enum_names *p = ed; p != NULL; p = p->en_next_range) { passert(p->en_last - p->en_first + 1 == p->en_checklen); prefix = (p->en_prefix == NULL ? prefix : p->en_prefix); 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); size_t prefix_len = (prefix == NULL ? 0 : strlen(prefix)); /* suffix must not and will not overlap prefix */ const char *suffix = strchr(name + prefix_len, '('); size_t suffix_len = (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(suffix_len > 0, 0, suffix_len) || try(prefix_len > 0, prefix_len, 0) || try(prefix_len > 0 && suffix_len > 0, prefix_len, suffix_len)) { 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 *str_enum_enum(enum_enum_names *een, unsigned long table, unsigned long val, enum_buf *b) { enum_names *en = enum_enum_table(een, table); if (en == NULL) { /* assume the log context implies the table name */ snprintf(b->buf, sizeof(b->buf), "%lu??", val); return b->buf; } return str_enum(en, val, b); } const char *str_enum_enum_short(enum_enum_names *een, unsigned long table, unsigned long val, enum_buf *b) { enum_names *en = enum_enum_table(een, table); if (en == NULL) { /* assume the log context implies the table name */ snprintf(b->buf, sizeof(b->buf), "%lu??", val); return b->buf; } return str_enum_short(en, val, b); } size_t jam_enum_enum(struct jambuf *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 jam(buf, "%lu??%lu??", table, val); } return jam_enum(buf, en, val); } size_t jam_enum_enum_short(struct jambuf *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 jam(buf, "%lu??%lu??", table, val); } return jam_enum_short(buf, en, val); } 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); } } libreswan-4.14/lib/libswan/esp_info.c000066400000000000000000000065051457372064200176230ustar00rootroot00000000000000/* 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, parser->policy->logger, next_algorithm(proposal, PROPOSAL_encrypt, NULL) != NULL); impaired_passert(proposal_parser, parser->policy->logger, next_algorithm(proposal, PROPOSAL_prf, NULL) == NULL); impaired_passert(proposal_parser, parser->policy->logger, 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-4.14/lib/libswan/fatal.c000066400000000000000000000033071457372064200171050ustar00rootroot00000000000000/* 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" VPRINTF_LIKE(3) static void jam_fatal(struct jambuf *buf, const struct logger *logger, const char *fmt, va_list ap) { /* XXX: The message format is: * FATAL ERROR: * and not: * FATAL ERROR: */ jam(buf, "FATAL ERROR: "); jam_logger_prefix(buf, logger); jam_va_list(buf, fmt, ap); } void fatal(enum pluto_exit_code rc, const struct logger *logger, const char *fmt, ...) { char output[LOG_WIDTH]; struct jambuf buf = ARRAY_AS_JAMBUF(output); va_list ap; va_start(ap, fmt); jam_fatal(&buf, logger, fmt, ap); va_end(ap); jambuf_to_logger(&buf, logger, ERROR_FLAGS); libreswan_exit(rc); } void fatal_errno(enum pluto_exit_code rc, const struct logger *logger, int error, const char *fmt, ...) { char output[LOG_WIDTH]; struct jambuf buf = ARRAY_AS_JAMBUF(output); va_list ap; va_start(ap, fmt); jam_fatal(&buf, logger, fmt, ap); va_end(ap); jam_string(&buf, ": "); jam_errno(&buf, error); jambuf_to_logger(&buf, logger, ERROR_FLAGS); libreswan_exit(rc); } libreswan-4.14/lib/libswan/fd.c000066400000000000000000000065231457372064200164120ustar00rootroot00000000000000/* 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 *fd_addref_where(struct fd *fd, const struct where *where) { pexpect(fd == NULL || fd->magic == FD_MAGIC); return addref_where(fd, where); } static void free_fd(void *obj, where_t where) { struct fd *fd = obj; pexpect(fd->magic == FD_MAGIC); if (close(fd->fd) != 0) { if (DBGP(DBG_BASE)) { llog_errno(DEBUG_STREAM, &global_logger, errno, "freeref "PRI_FD" close() failed "PRI_WHERE/*: */, pri_fd(fd), pri_where(where)); } } else { dbg("freeref "PRI_FD" "PRI_WHERE"", pri_fd(fd), pri_where(where)); } fd->magic = ~FD_MAGIC; pfree(fd); } void fd_delref_where(struct fd **fd, where_t where) { delref_where(fd, where); } void fd_leak(struct fd *fd, where_t where) { dbg("leaking "PRI_FD"'s FD; will be closed when pluto exits "PRI_WHERE"", pri_fd(fd), pri_where(where)); /* leave the old underlying file descriptor open */ if (fd != NULL) { fd->fd = dup(fd->fd); } } ssize_t fd_sendmsg(const struct fd *fd, const struct msghdr *msg, int flags) { if (fd == NULL || fd->magic != FD_MAGIC) { /* * XXX: passert() / pexpect() would be recursive - * they will call this function when trying to write * to whack. */ return -EFAULT; } ssize_t s = sendmsg(fd->fd, msg, flags); return s < 0 ? -errno : s; } struct fd *fd_accept(int socket, const struct where *where, struct logger *logger) { struct sockaddr_un addr; socklen_t addrlen = sizeof(addr); int fd = accept(socket, (struct sockaddr *)&addr, &addrlen); if (fd < 0) { llog_error(logger, errno, "accept() failed in "PRI_WHERE"", pri_where(where)); return NULL; } if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) { llog_error(logger, errno, "failed to set CLOEXEC in "PRI_WHERE"", pri_where(where)); close(fd); return NULL; } struct fd *fdt = refcnt_alloc(struct fd, free_fd, where); fdt->fd = fd; fdt->magic = FD_MAGIC; dbg("%s: new "PRI_FD" "PRI_WHERE"", __func__, pri_fd(fdt), pri_where(where)); return fdt; } ssize_t fd_read(const struct fd *fd, void *buf, size_t nbytes) { if (fd == NULL || fd->magic != FD_MAGIC) { return -EFAULT; } ssize_t s = read(fd->fd, buf, nbytes); return s < 0 ? -errno : s; } bool fd_p(const struct fd *fd) { if (fd == NULL) { return false; } if (fd->magic != FD_MAGIC) { llog_pexpect(&global_logger, HERE, "wrong magic for "PRI_FD"", pri_fd(fd)); return false; } return true; } bool same_fd(const struct fd *l, const struct fd *r) { return fd_p(l) && fd_p(r) && l == r; } libreswan-4.14/lib/libswan/global_logger.c000066400000000000000000000024351457372064200206160ustar00rootroot00000000000000/* logging declarations * * Copyright (C) 2021 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" bool suppress_object_log_false(const void *object UNUSED) { return false; } bool suppress_object_log_true(const void *object UNUSED) { return true; } size_t jam_object_prefix_none(struct jambuf *buf UNUSED, const void *object UNUSED) { return 0; } static const struct logger_object_vec logger_global_vec = { .name = "global", .suppress_object_log = suppress_object_log_false, .jam_object_prefix = jam_object_prefix_none, .free_object = false, }; const struct where global_where = { .line = 0, .file = "", .func = "", }; const struct logger global_logger = { .where = &global_where, .object = NULL, .object_vec = &logger_global_vec, }; libreswan-4.14/lib/libswan/goodmask.3.xml000066400000000000000000000064471457372064200203510ustar00rootroot00000000000000 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-4.14/lib/libswan/hunk.c000066400000000000000000000065761457372064200167760ustar00rootroot00000000000000/* hunk like buffers, for libreswan * * Copyright (C) 2018-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. * */ #include #include /* for strtoul() */ #include #include "lswalloc.h" /* for clone_bytes() */ #include "hunk.h" char *clone_bytes_as_string(const void *ptr, size_t maxlen, const char *name) { if (ptr == NULL) { return NULL; } /* Look for terminating NULL, if there is one */ size_t len = strnlen(ptr, maxlen); char *out = alloc_things(char, len + 1, name); memcpy(out, ptr, len); out[maxlen] = '\0'; /* also done by alloc_things() */ return out; } int raw_cmp(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) { if (l_ptr != NULL) { return 1; } if (r_ptr != NULL) { return -11; } return 0; } size_t len = min(l_len, r_len); int d = memcmp(l_ptr, r_ptr, len); if (d != 0) { return d; } /* lets ignore 32-bit overflow */ return ((int)l_len - (int)r_len); } 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 case_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 strncasecmp(l_ptr, r_ptr, r_len) == 0; } void hton_bytes(uintmax_t h, void *bytes, size_t size) { uint8_t *byte = bytes; for (unsigned i = 0; i < size; i++) { unsigned j = size - i - 1; byte[j] = h & 0xff; h = h >> 8; } } uintmax_t ntoh_bytes(const void *bytes, size_t size) { uintmax_t h = 0; const uint8_t *byte = bytes; for (unsigned i = 0; i < size; i++) { uintmax_t n = (h<<8) + byte[i]; if (n < h) { h = UINTMAX_MAX; } else { h = n; } } return h; } bool char_isupper(char c) { return (c >= 'A' && c <= 'Z'); } bool char_islower(char c) { return (c >= 'a' && c <= 'z'); } bool char_isspace(char c) { return (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v'); } bool char_isblank(char c) { return (c == ' ' || c == '\t'); } bool char_isdigit(char c) { return (c >= '0' && c <= '9'); } bool char_isbdigit(char c) { return (c >= '0' && c <= '1'); } bool char_isodigit(char c) { return (c >= '0' && c <= '7'); } bool char_isxdigit(char c) { return ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')); } bool char_isprint(char c) { return (c >= 0x20 && c <= 0x7e); } char char_tolower(char c) { return char_isupper(c) ? c - 'A' + 'a' : c; } char char_toupper(char c) { return char_islower(c) ? c - 'a' + 'A' : c; } libreswan-4.14/lib/libswan/id.c000066400000000000000000000253161457372064200164160ustar00rootroot00000000000000/* * 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 "sysdep.h" #include "constants.h" #include "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" #include "ttodata.h" const struct id empty_id = { .kind = ID_NONE, }; /* * Convert textual form of id into a struct id. */ err_t atoid(const char *src, struct id *id) { *id = empty_id; if (streq("%fromcert", src)) { *id = (struct id) { .kind = ID_FROMCERT, }; return NULL; } if (streq("%none", src)) { *id = (struct id) { .kind = ID_NONE, }; return NULL; } if (streq("%null", src)) { *id = (struct id) { .kind = ID_NULL, }; return NULL; } if (strchr(src, '=') != NULL) { /* * We interpret this as an ASCII X.501 ID_DER_ASN1_DN. * * convert from LDAP style or openssl x509 -subject style * to ASN.1 DN * discard optional @ character in front of DN */ chunk_t name = empty_chunk; err_t ugh = atodn((*src == '@') ? src + 1 : src, &name); if (ugh != NULL) { return ugh; } *id = (struct id) { .kind = ID_DER_ASN1_DN, .name = HUNK_AS_SHUNK(name), .scratch = name.ptr, }; return NULL; } if (streq(src, "%any") || streq(src, "0.0.0.0")) { /* any ID will be accepted */ *id = (struct id) { .kind = ID_NONE, }; return NULL; } if (strchr(src, '@') == NULL) { /* * !!! 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; ip_address addr; err_t ugh = ttoaddress_dns(shunk1(src), afi, &addr); if (ugh != NULL) { return ugh; } *id = (struct id) { .kind = afi->id_ip_addr, .ip_addr = addr, }; return NULL; } if (strneq(src, "@#", 2)) { /* * if there is a second specifier (#) on the line we * interpret this as ID_KEY_ID. * * Discard @#, convert from hex to bin. */ src += 2; /* drop "@#" */ chunk_t name = NULL_HUNK; err_t ugh = ttochunk(shunk1(src), 16, &name); if (ugh != NULL) { return ugh; } *id = (struct id) { .kind = ID_KEY_ID, .name = HUNK_AS_SHUNK(name), .scratch = name.ptr, }; return NULL; } if (strneq(src, "@~", 2)) { /* * if there is a second specifier (~) on the line we * interpret this as a binary ID_DER_ASN1_DN. * * discard @~, convert from hex to bin. */ src += 2; /* drop "@~" */ chunk_t name = NULL_HUNK; err_t ugh = ttochunk(shunk1(src), 16, &name); if (ugh != NULL) { return ugh; } *id = (struct id) { .kind = ID_DER_ASN1_DN, .name = HUNK_AS_SHUNK(name), .scratch = name.ptr, }; return NULL; } if (strneq(src, "@[", 2)) { /* * 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. */ src += 2; /* drop "@[" */ int len = strlen(src); if (src[len-1] == ']') { len -= 1; /* drop trailing "]" */ } chunk_t name = clone_bytes_as_chunk(src, len, "key id"); *id = (struct id) { .kind = ID_KEY_ID, .name = ASN1(name), .scratch = name.ptr, }; return NULL; } if (*src == '@') { chunk_t name = clone_bytes_as_chunk(src + 1, strlen(src)-1, "fqdn id"); *id = (struct id) { .kind = ID_FQDN, /* discard @ */ .name = ASN1(name), .scratch = name.ptr, }; return NULL; } /* * We leave in @, as per DOI 4.6.2.4 (but DNS wants * . instead). */ chunk_t name = clone_bytes_as_chunk(src, strlen(src), "DOI 4.6.2.4"); *id = (struct id) { .kind = ID_USER_FQDN, .name = ASN1(name), .scratch = name.ptr, }; return NULL; } void jam_id_bytes(struct jambuf *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 (address_is_specified(id->ip_addr)) { jam_address(buf, &id->ip_addr); } else { jam_string(buf, "%any"); } 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_bytes(const struct id *id, jam_bytes_fn *jam_bytes, id_buf *dst) { struct jambuf buf = ARRAY_AS_JAMBUF(dst->buf); /* JAM_ID() only emits printable ASCII */ jam_id_bytes(&buf, id, jam_bytes); return dst->buf; } struct id clone_id(const struct id *src, const char *story) { chunk_t name = clone_hunk(src->name, story); struct id dst = { .kind = src->kind, .ip_addr = src->ip_addr, .name = ASN1(name), .scratch = name.ptr, }; 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: pfreeany(id->scratch); 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 id_is_any(const struct id *a) { switch (a->kind) { case ID_NONE: return true; /* wildcard */ case ID_IPV4_ADDR: case ID_IPV6_ADDR: return (!address_is_specified(a->ip_addr)); case ID_FQDN: case ID_USER_FQDN: case ID_DER_ASN1_DN: case ID_DER_ASN1_GN: case ID_KEY_ID: case ID_NULL: return false; default: return false; } } /* compare two struct id values */ bool id_eq(const struct id *a, const struct id *b) { if (a->kind != b->kind) { return false; } switch (a->kind) { case ID_NONE: return true; /* repeat of above for completeness */ case ID_NULL: dbg("ID_NULL: id kind matches"); return true; 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?) */ /* strip trailing dots */ size_t al = a->name.len; while (al > 0 && ((const uint8_t*)a->name.ptr)[al - 1] == '.') al--; size_t bl = b->name.len; while (bl > 0 && ((const uint8_t*)b->name.ptr)[bl - 1] == '.') bl--; return (al == bl /* same length */ && strncaseeq((char *)a->name.ptr, (char *)b->name.ptr, al)); } case ID_FROMCERT: dbg("%s() received ID_FROMCERT - unexpected", __func__); return same_dn(a->name, b->name); case ID_DER_ASN1_DN: return same_dn(a->name, b->name); case ID_KEY_ID: return hunk_eq(a->name, b->name); default: bad_case(a->kind); } } bool same_id(const struct id *a, const struct id *b) { if (b->kind == ID_NONE || a->kind == ID_NONE) { dbg("id type with ID_NONE means wildcard match"); return true; /* it's the wildcard */ } return id_eq(a, b); } /* compare two struct id values, DNs can contain wildcards */ bool match_id(const char *prefix, const struct id *a, const struct id *b, int *wildcards_out) { bool match; int wildcards; if (b->kind == ID_NONE) { wildcards = MAX_WILDCARDS; match = true; } else if (a->kind != b->kind) { /* should this allow SAN match of cert with right ID_DER_ASN1_DN? */ wildcards = MAX_WILDCARDS; match = false; } else if (a->kind == ID_DER_ASN1_DN) { match = match_dn_any_order_wild(prefix, a->name, b->name, &wildcards); } else if (same_id(a, b)) { wildcards = 0; match = true; } else { wildcards = MAX_WILDCARDS; match = false; } if (DBGP(DBG_BASE)) { id_buf buf; DBG_log("%smatch_id a=%s", prefix, str_id(a, &buf)); DBG_log("%s b=%s", prefix, str_id(b, &buf)); DBG_log("%sresults %s wildcards=%d", prefix, match ? "matched" : "fail", wildcards); } *wildcards_out = wildcards; return match; } /* count the number of wildcards in an id */ bool id_has_wildcards(const struct id *id) { bool has_wildcards; switch (id->kind) { case ID_NONE: has_wildcards = true; break; #if 0 /* true? */ case ID_IPV4_ADDR: case ID_IPV6_ADDR: has_willdcards = !address_is_specified(id->ip_addr); break; #endif case ID_DER_ASN1_DN: has_wildcards = dn_has_wildcards(id->name); break; default: has_wildcards = false; break; } id_buf b; dbg("id %s has wildcards: %s", str_id(id, &b), bool_str(has_wildcards)); return has_wildcards; } /* * 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_ip_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-4.14/lib/libswan/ike_alg.c000066400000000000000000001122031457372064200174050ustar00rootroot00000000000000/* * 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" #include "ike_alg_ipcomp.h" #include "ike_alg_ipcomp_ops.h" #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*, struct logger *logger); 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, &ike_alg_ipcomp, }; 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", [SADB_ALG_ID] = "SADB 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 ipcomp_desc **next_ipcomp_desc(const struct ipcomp_desc **last) { return (const struct ipcomp_desc**)next_alg(&ike_alg_ipcomp, (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 (hunk_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) { const char *name = enum_name_short(type->enum_names[key], id); DBGF(debug, "%s %s id: %s=%u, found %s\n", type->name, __func__, name ? name : "???", id, alg->fqn); return alg; } } const char *name = enum_name_short(type->enum_names[key], id); DBGF(debug, "%s %s id: %s=%u, not found\n", type->name, __func__, name ? name : "???", id); return NULL; } const struct ike_alg *ike_alg_by_key_id(const struct ike_alg_type *type, enum ike_alg_key key, unsigned id) { return lookup_by_id(type, key, id, DBG_CRYPT); } 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 ipcomp_desc *ikev1_get_ike_ipcomp_desc(enum ipsec_ipcomp_algo id) { return ipcomp_desc(ikev1_oakley_lookup(&ike_alg_ipcomp, 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)); } const struct ipcomp_desc *ikev1_get_kernel_ipcomp_desc(enum ipsec_ipcomp_algo id) { return ipcomp_desc(lookup_by_id(&ike_alg_ipcomp, 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 hash_desc *ikev2_get_hash_desc(enum ikev2_hash_algorithm id) { return hash_desc(ikev2_lookup(&ike_alg_hash, 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)); } const struct ipcomp_desc *ikev2_get_ipcomp_desc(enum ipsec_ipcomp_algo id) { return ipcomp_desc(ikev2_lookup(&ike_alg_ipcomp, id)); } const struct encrypt_desc *encrypt_desc_by_sadb_ealg_id(unsigned id) { return encrypt_desc(lookup_by_id(&ike_alg_encrypt, SADB_ALG_ID, id, DBG_CRYPT)); } const struct integ_desc *integ_desc_by_sadb_aalg_id(unsigned id) { return integ_desc(lookup_by_id(&ike_alg_integ, SADB_ALG_ID, id, DBG_CRYPT)); } const struct ipcomp_desc *ipcomp_desc_by_sadb_calg_id(unsigned id) { return ipcomp_desc(lookup_by_id(&ike_alg_ipcomp, SADB_ALG_ID, id, DBG_CRYPT)); } /* * 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(struct logger *logger, where_t where, const struct ike_alg *alg, const struct ike_alg *base_alg) { if (!ike_alg_in_table(base_alg)) { llog_pexpect(logger, 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 (hunk_caseeq(alg_name, name)) { return true; } } return false; } static bool pexpect_ike_alg_has_name(struct logger *logger, where_t where, const struct ike_alg *alg, const char *name, const char *description) { if (name == NULL) { llog_pexpect(logger, where, PRI_IKE_ALG" %s name is NULL", pri_ike_alg(alg), description); return false; } else if (!ike_alg_has_name(alg, shunk1(name))) { llog_pexpect(logger, 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(struct logger *logger, 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)) { llog_pexpect(logger, 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 &ike_alg_hash_identity, }; static void hash_desc_check(const struct ike_alg *alg, struct logger *logger) { const struct hash_desc *hash = hash_desc(alg); size_t min_size = (hash == &ike_alg_hash_identity ? 0 : 1); pexpect_ike_alg(logger, alg, hash->hash_digest_size >= min_size); pexpect_ike_alg(logger, alg, hash->hash_block_size >= min_size); struct crypt_mac mac; pexpect_ike_alg(logger, alg, hash->hash_digest_size <= sizeof(mac.ptr/*an array*/)); if (hash->hash_ops != NULL) { pexpect_ike_alg(logger, alg, hash->hash_ops->backend != NULL); pexpect_ike_alg(logger, alg, hash->hash_ops->check != NULL); pexpect_ike_alg(logger, alg, hash->hash_ops->digest_symkey != NULL); pexpect_ike_alg(logger, alg, hash->hash_ops->digest_bytes != NULL); pexpect_ike_alg(logger, alg, hash->hash_ops->final_bytes != NULL); hash->hash_ops->check(hash, logger); } } 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, [IKEv2_ALG_ID] = &ikev2_hash_algorithm_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, struct logger *logger) { const struct prf_desc *prf = prf_desc(alg); pexpect_ike_alg(logger, alg, prf->prf_key_size > 0); pexpect_ike_alg(logger, alg, prf->prf_output_size > 0); struct crypt_mac mac; pexpect_ike_alg(logger, alg, prf->prf_output_size <= sizeof(mac.ptr/*an array*/)); pexpect_ike_alg_has_name(logger, HERE, alg, prf->prf_ike_audit_name, ".prf_ike_audit_name"); /* all or none */ pexpect_ike_alg(logger, alg, (prf->prf_mac_ops != NULL) == (prf->prf_ikev1_ops != NULL)); pexpect_ike_alg(logger, alg, (prf->prf_mac_ops != NULL) == (prf->prf_ikev2_ops != NULL)); if (prf->prf_mac_ops != NULL) { pexpect_ike_alg(logger, alg, prf->prf_mac_ops->backend != NULL); pexpect_ike_alg(logger, alg, prf->prf_mac_ops->check != NULL); pexpect_ike_alg(logger, alg, prf->prf_mac_ops->init_symkey != NULL); pexpect_ike_alg(logger, alg, prf->prf_mac_ops->init_bytes != NULL); pexpect_ike_alg(logger, alg, prf->prf_mac_ops->digest_symkey != NULL); pexpect_ike_alg(logger, alg, prf->prf_mac_ops->digest_bytes != NULL); pexpect_ike_alg(logger, alg, prf->prf_mac_ops->final_symkey != NULL); pexpect_ike_alg(logger, alg, prf->prf_mac_ops->final_bytes != NULL); /* * IKEv1 IKE algorithms must have a hasher - used for * things like computing IV. */ pexpect_ike_alg(logger, alg, prf->common.id[IKEv1_OAKLEY_ID] < 0 || prf->hasher != NULL); prf->prf_mac_ops->check(prf, logger); } if (prf->prf_ikev1_ops != NULL) { pexpect_ike_alg(logger, alg, prf->prf_ikev1_ops->backend != NULL); pexpect_ike_alg(logger, alg, prf->prf_ikev1_ops->signature_skeyid != NULL); pexpect_ike_alg(logger, alg, prf->prf_ikev1_ops->pre_shared_key_skeyid != NULL); pexpect_ike_alg(logger, alg, prf->prf_ikev1_ops->skeyid_d != NULL); pexpect_ike_alg(logger, alg, prf->prf_ikev1_ops->skeyid_a != NULL); pexpect_ike_alg(logger, alg, prf->prf_ikev1_ops->skeyid_e != NULL); pexpect_ike_alg(logger, alg, prf->prf_ikev1_ops->appendix_b_keymat_e != NULL); } if (prf->prf_ikev2_ops != NULL) { pexpect_ike_alg(logger, alg, prf->prf_ikev2_ops->backend != NULL); pexpect_ike_alg(logger, alg, prf->prf_ikev2_ops->prfplus != NULL); pexpect_ike_alg(logger, alg, prf->prf_ikev2_ops->ike_sa_skeyseed != NULL); pexpect_ike_alg(logger, alg, prf->prf_ikev2_ops->ike_sa_rekey_skeyseed != NULL); pexpect_ike_alg(logger, alg, prf->prf_ikev2_ops->ike_sa_keymat != NULL); pexpect_ike_alg(logger, alg, prf->prf_ikev2_ops->child_sa_keymat != NULL); pexpect_ike_alg(logger, alg, prf->prf_ikev2_ops->psk_auth != NULL); } if (prf->hasher != NULL) { /* * Check for dangling pointer. */ pexpect_ike_alg_base_in_table(logger, HERE, &prf->common, &prf->hasher->common); pexpect_ike_alg(logger, alg, prf->prf_output_size == prf->hasher->hash_digest_size); pexpect_ike_alg_has_base_names(logger, 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 &ike_alg_integ_none, }; static void integ_desc_check(const struct ike_alg *alg, struct logger *logger) { const struct integ_desc *integ = integ_desc(alg); pexpect_ike_alg(logger, alg, integ->integ_keymat_size > 0); pexpect_ike_alg(logger, alg, integ->integ_output_size > 0); struct crypt_mac mac; pexpect_ike_alg(logger, alg, integ->integ_output_size <= sizeof(mac.ptr/*an array*/)); pexpect_ike_alg_has_name(logger, HERE, alg, integ->integ_tcpdump_name, ".integ_tcpdump_name"); pexpect_ike_alg_has_name(logger, HERE, alg, integ->integ_ike_audit_name, ".integ_ike_audit_name"); pexpect_ike_alg_has_name(logger, HERE, alg, integ->integ_kernel_audit_name, ".integ_kernel_audit_name"); if (integ->common.id[IKEv1_ESP_ID] >= 0) { enum_buf esb; pexpect_ike_alg_streq(logger, alg, integ->integ_kernel_audit_name, str_enum_short(&auth_alg_names, integ->common.id[IKEv1_ESP_ID], &esb)); } if (integ->prf != NULL) { pexpect_ike_alg(logger, alg, integ->integ_keymat_size == integ->prf->prf_key_size); pexpect_ike_alg(logger, alg, integ->integ_output_size <= integ->prf->prf_output_size); pexpect_ike_alg(logger, alg, prf_desc_is_ike(&integ->prf->common)); pexpect_ike_alg_has_base_names(logger, 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 &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, struct logger *logger) { 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(logger, alg, encrypt->encrypt_tcpdump_name, "aes_gcm"); pexpect_ike_alg_streq(logger, alg, encrypt->encrypt_ike_audit_name, "aes_gcm"); } else { pexpect_ike_alg_has_name(logger, HERE, alg, encrypt->encrypt_tcpdump_name, ".encrypt_tcpdump_name"); pexpect_ike_alg_has_name(logger, HERE, alg, encrypt->encrypt_ike_audit_name, ".encrypt_ike_audit_name"); } pexpect_ike_alg_has_name(logger, HERE, alg, encrypt->encrypt_kernel_audit_name, ".encrypt_kernel_audit_name"); if (encrypt->common.id[IKEv1_ESP_ID] >= 0) { enum_buf esb; pexpect_ike_alg_streq(logger, alg, encrypt->encrypt_kernel_audit_name, str_enum_short(&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(logger, alg, encrypt->encrypt_ops->backend != NULL); pexpect_ike_alg(logger, alg, encrypt->encrypt_ops->check != NULL); pexpect_ike_alg(logger, 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(logger, alg, encrypt->encrypt_ops->do_aead == NULL || encrypt->aead_tag_size > 0); pexpect_ike_alg(logger, 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(logger, alg, encrypt->keydeflen == 0); pexpect_ike_alg(logger, alg, encrypt->common.id[IKEv1_ESP_ID] == ESP_NULL); pexpect_ike_alg(logger, alg, encrypt->common.id[IKEv2_ALG_ID] == IKEv2_ENCR_NULL); pexpect_ike_alg(logger, alg, encrypt->enc_blocksize == 1); pexpect_ike_alg(logger, alg, encrypt->wire_iv_size == 0); pexpect_ike_alg(logger, alg, encrypt->key_bit_lengths[0] == 0); } else { pexpect_ike_alg(logger, alg, encrypt->keydeflen > 0); pexpect_ike_alg(logger, 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(logger, alg, encrypt->key_bit_lengths[elemsof(encrypt->key_bit_lengths) - 1] == 0); for (; *keylenp != 0; keylenp++) { pexpect_ike_alg(logger, alg, last_key_len > *keylenp); } } /* * The default (even when 0) is always valid. */ pexpect_ike_alg(logger, 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_secp256r1, &ike_alg_dh_secp384r1, &ike_alg_dh_secp521r1, #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_curve25519, #endif }; static void dh_desc_check(const struct ike_alg *alg, struct logger *logger) { const struct dh_desc *dh = dh_desc(alg); pexpect_ike_alg(logger, alg, dh->group > 0); pexpect_ike_alg(logger, alg, dh->bytes > 0); pexpect_ike_alg(logger, alg, dh->common.id[IKEv2_ALG_ID] == dh->group); pexpect_ike_alg(logger, alg, dh->common.id[IKEv1_OAKLEY_ID] == dh->group); /* always implemented */ pexpect_ike_alg(logger, alg, dh->dh_ops != NULL); if (dh->dh_ops != NULL) { pexpect_ike_alg(logger, alg, dh->dh_ops->backend != NULL); pexpect_ike_alg(logger, alg, dh->dh_ops->check != NULL); pexpect_ike_alg(logger, alg, dh->dh_ops->calc_local_secret != NULL); pexpect_ike_alg(logger, alg, dh->dh_ops->calc_shared_secret != NULL); /* more? */ dh->dh_ops->check(dh, logger); /* IKEv1 supports MODP groups but not ECC. */ pexpect_ike_alg(logger, 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, }; /* * IPCOMP */ static const struct ipcomp_desc *ipcomp_descriptors[] = { &ike_alg_ipcomp_deflate, &ike_alg_ipcomp_lzs, &ike_alg_ipcomp_lzjh, }; static void ipcomp_desc_check(const struct ike_alg *alg, struct logger *logger) { const struct ipcomp_desc *ipcomp = ipcomp_desc(alg); pexpect_ike_alg(logger, alg, ipcomp != NULL); } static bool ipcomp_desc_is_ike(const struct ike_alg *alg) { const struct ipcomp_desc *ipcomp = ipcomp_desc(alg); return ipcomp->ipcomp_ops != NULL; } static struct algorithm_table ipcomp_algorithms = ALGORITHM_TABLE(ipcomp_descriptors); const struct ike_alg_type ike_alg_ipcomp = { .name = "IPCOMP", .Name = "IPCOMP", .algorithms = &ipcomp_algorithms, .enum_names = { [IKEv1_OAKLEY_ID] = &ipsec_ipcomp_algo_names, [IKEv1_ESP_ID] = &ipsec_ipcomp_algo_names, [IKEv2_ALG_ID] = &ipsec_ipcomp_algo_names, }, .desc_check = ipcomp_desc_check, .desc_is_ike = ipcomp_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, struct logger *logger) { if (id >= 0) { if (enum_names == NULL) { llog_passert(logger, HERE, "%s %s %s has no enum names", alg->algo_type->name, alg->fqn, what); } const char *enum_name = enum_name_short(enum_names, id); DBGF(DBG_CRYPT, "%s id: %d enum name: %s", what, id, enum_name); pexpect_ike_alg_has_name(logger, HERE, alg, enum_name, "enum table name"); } else { DBGF(DBG_CRYPT, "%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, struct logger *logger) { /* * 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); DBGF(DBG_CRYPT, "%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: %d, IKEv1 ESP_INFO: %d, IKEv2: %d SADB: %d", type->name, alg->fqn, alg->id[IKEv1_OAKLEY_ID], alg->id[IKEv1_ESP_ID], alg->id[IKEv2_ALG_ID], alg->id[SADB_ALG_ID]); /* * Check the FQN first; and require upper case. If * this one fails abort as everything else relies on a * usable .fqn. */ if (!pexpect_ike_alg_has_name(logger, HERE, alg, alg->fqn, ".fqn")) { continue; } pexpect_ike_alg(logger, 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(logger, HERE, alg, alg->fqn, ".name"); /* * Check the IDs have all been set (i.e, non-zero). * * 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++) { int id = alg->id[key]; switch (key) { case SADB_ALG_ID: pexpect_ike_alg_key(logger, alg, key, id >= 0); break; default: pexpect_ike_alg_key(logger, alg, key, id == -1 || id > 0); break; } } } /* * 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]; switch (key) { case SADB_ALG_ID: /* SADB needs sparse names */ continue; default: if (id < 0) continue; break; } at_least_one_valid_id = true; check_enum_name(ike_alg_key_name(key), alg, id, type->enum_names[key], logger); } pexpect_ike_alg(logger, 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]; switch (key) { case SADB_ALG_ID: if (id <= 0) continue; break; default: if (id < 0) continue; break; } pexpect_ike_alg_key(logger, alg, key, 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(logger, alg, type->desc_check != NULL); type->desc_check(alg, logger); } } } static const char *backend_name(const struct ike_alg *alg) { if (alg->algo_type == &ike_alg_hash) { const struct hash_desc *hash = hash_desc(alg); if (hash->hash_ops != NULL) { return hash->hash_ops->backend; } } else if (alg->algo_type == &ike_alg_prf) { const struct prf_desc *prf = prf_desc(alg); if (prf->prf_mac_ops != NULL) { return prf->prf_mac_ops->backend; } } else if (alg->algo_type == &ike_alg_integ) { const struct integ_desc *integ = integ_desc(alg); if (integ->prf != NULL && integ->prf->prf_mac_ops != NULL) { return integ->prf->prf_mac_ops->backend; } } else if (alg->algo_type == &ike_alg_encrypt) { const struct encrypt_desc *encrypt = encrypt_desc(alg); if (encrypt->encrypt_ops != NULL) { return encrypt->encrypt_ops->backend; } } else if (alg->algo_type == &ike_alg_dh) { const struct dh_desc *dh = dh_desc(alg); if (dh->dh_ops != NULL) { return dh->dh_ops->backend; } } else if (alg->algo_type == &ike_alg_ipcomp) { const struct ipcomp_desc *ipcomp = ipcomp_desc(alg); if (ipcomp->ipcomp_ops != NULL) { return ipcomp->ipcomp_ops->backend; } } else { bad_case(0); } return NULL; } static void jam_ike_alg_details(struct jambuf *buf, size_t name_width, size_t backend_width, const struct ike_alg *alg) { /* * NAME [{256,192,*128}]: */ name_width -= jam_string(buf, alg->fqn); /* * Concatenate [key,...] or {key,...} with default * marked with '*'. */ if (alg->algo_type == IKE_ALG_ENCRYPT) { #define MAX_KEYSIZES (int)strlen("{256,192,*128}") name_width -= MAX_KEYSIZES; jam(buf, "%*s", (int) name_width, ""); const struct encrypt_desc *encr = encrypt_desc(alg); int s = 0; s += jam_string(buf, encr->keylen_omitted ? "[" : "{"); const char *sep = ""; for (const unsigned *keyp = encr->key_bit_lengths; *keyp; keyp++) { s += jam_string(buf, sep); if (*keyp == encr->keydeflen) { s += jam(buf, "*"); } s += jam(buf, "%d", *keyp); sep = ","; } s += jam(buf, encr->keylen_omitted ? "]" : "}"); jam(buf, "%*s", MAX_KEYSIZES - s, ""); } else { jam(buf, "%*s", (int) name_width, ""); } jam_string(buf, " "); /* * 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 if (alg->algo_type == &ike_alg_ipcomp) { v1_esp = v1_ah = alg->id[IKEv1_ESP_ID] >= 0; v2_esp = v2_ah = alg->id[IKEv2_ALG_ID] >= 0; } else { bad_case(0); } jam_string(buf, "IKEv1:"); jam_string(buf, (v1_ike ? " IKE" : " ")); jam_string(buf, (v1_esp ? " ESP" : " ")); jam_string(buf, (v1_ah ? " AH" : " ")); jam_string(buf, " IKEv2:"); jam_string(buf, (v2_ike ? " IKE" : " ")); jam_string(buf, (v2_esp ? " ESP" : " ")); jam_string(buf, (v2_ah ? " AH" : " ")); jam_string(buf, (alg->fips.approved ? " FIPS" : " ")); /* * Concatenate: XXX backend */ if (backend_width > 0) { const char *b = backend_name(alg); jam(buf, " %-*s", (int) backend_width, b != NULL ? b : ""); } /* * Concatenate: alias ... */ { const char *sep = " "; FOR_EACH_IKE_ALG_NAME(alg, alg_name) { /* filter out NAME */ if (!hunk_strcaseeq(alg_name, alg->fqn)) { jam(buf, "%s"PRI_SHUNK, sep, pri_shunk(alg_name)); sep = ", "; } } } } static void log_ike_algs(struct logger *logger) { /* * Find a suitable column width by looking for the longest * name. */ size_t name_width = 0; size_t backend_width = 0; FOR_EACH_IKE_ALG_TYPEP(typep) { const struct ike_alg_type *type = *typep; FOR_EACH_IKE_ALGP(type, algp) { size_t s = strlen((*algp)->fqn); if ((*algp)->algo_type == IKE_ALG_ENCRYPT) { s += MAX_KEYSIZES + 1; } name_width = max(s, name_width); const char *b = backend_name(*algp); if (b != NULL) { size_t s = strlen(b); backend_width = max(s, backend_width); } } } /* * When in FIPS mode sprinkle "FIPS" through out the output. * This way grepping for FIPS shows up more information. */ FOR_EACH_IKE_ALG_TYPEP(typep) { const struct ike_alg_type *type = *typep; llog(RC_LOG, logger, "%s%s algorithms:", libreswan_fipsmode() ? "FIPS " : "", type->Name); FOR_EACH_IKE_ALGP(type, algp) { LLOG_JAMBUF(RC_LOG, logger, buf) { jam_string(buf, " "); jam_ike_alg_details(buf, name_width, backend_width, *algp); } } } } /* * 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, struct logger *logger) { 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.approved) { llog(RC_LOG, logger, "%s algorithm %s disabled; not FIPS compliant", type->Name, alg->fqn); continue; } *end++ = alg; } type->algorithms->end = end; } void init_ike_alg(struct logger *logger) { 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, logger); } } /* * Now verify what is left. */ FOR_EACH_IKE_ALG_TYPEP(typep) { check_algorithm_table(*typep, logger); } /* * Log the final lists as a pretty table. */ log_ike_algs(logger); } libreswan-4.14/lib/libswan/ike_alg_3des.c000066400000000000000000000033041457372064200203240ustar00rootroot00000000000000/* 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 "lsw-pfkeyv2.h" /* for SADB_*ALG_* */ const struct encrypt_desc ike_alg_encrypt_3des_cbc = { .common = { .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, #ifdef SADB_EALG_3DESCBC [SADB_ALG_ID] = SADB_EALG_3DESCBC, #endif }, .fips.approved = 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, .encrypt_netlink_xfrm_name = "des3_ede", .encrypt_tcpdump_name = "3des", .encrypt_ike_audit_name = "3des", .encrypt_kernel_audit_name = "3DES", }; libreswan-4.14/lib/libswan/ike_alg_aes.c000066400000000000000000000301011457372064200202310ustar00rootroot00000000000000/* * 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 "lsw-pfkeyv2.h" /* for SADB_*ALG_* */ const struct encrypt_desc ike_alg_encrypt_aes_cbc = { .common = { .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, #if defined SADB_X_EALG_AES [SADB_ALG_ID] = SADB_X_EALG_AES, /* Orig, NetBSD, FreeBSD */ #elif defined SADB_X_EALG_AESCBC [SADB_ALG_ID] = SADB_X_EALG_AESCBC, /* also FreeBSD; ulgh */ #endif }, .fips.approved = 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, .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 = { .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, #ifdef SADB_X_EALG_AESCTR [SADB_ALG_ID] = SADB_X_EALG_AESCTR, #endif }, .fips.approved = 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, .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 = { .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, #ifdef SADB_X_EALG_AES_GCM_ICV8 [SADB_ALG_ID] = SADB_X_EALG_AES_GCM_ICV8, #endif #ifdef SADB_X_EALG_AES_GCM8 [SADB_ALG_ID] = SADB_X_EALG_AES_GCM8, #endif #ifdef SADB_X_EALG_AESGCM8 [SADB_ALG_ID] = SADB_X_EALG_AESGCM8, /* NetBSD */ #endif }, .fips.approved = true, .fips.operation_limit = UINTMAX_C(1) << 32, }, .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, .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 = { .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, #ifdef SADB_X_EALG_AES_GCM_ICV12 [SADB_ALG_ID] = SADB_X_EALG_AES_GCM_ICV12, #endif #ifdef SADB_X_EALG_AES_GCM12 [SADB_ALG_ID] = SADB_X_EALG_AES_GCM12, #endif #ifdef SADB_X_EALG_AESGCM12 [SADB_ALG_ID] = SADB_X_EALG_AESGCM12, /* NetBSD */ #endif }, .fips.approved = true, .fips.operation_limit = UINTMAX_C(1) << 32, }, .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, .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 = { .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, #ifdef SADB_X_EALG_AES_GCM_ICV16 [SADB_ALG_ID] = SADB_X_EALG_AES_GCM_ICV16, #endif #ifdef SADB_X_EALG_AES_GCM16 [SADB_ALG_ID] = SADB_X_EALG_AES_GCM16, #endif #ifdef SADB_X_EALG_AESGCM16 [SADB_ALG_ID] = SADB_X_EALG_AESGCM16, /* NetBSD */ #endif }, .fips.approved = true, .fips.operation_limit = UINTMAX_C(1) << 32, }, .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, .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 = { .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, #ifdef SADB_X_EALG_AES_CCM_ICV8 [SADB_ALG_ID] = SADB_X_EALG_AES_CCM_ICV8, #endif }, .fips.approved = 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, .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 = { .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, #ifdef SADB_X_EALG_AES_CCM_ICV12 [SADB_ALG_ID] = SADB_X_EALG_AES_CCM_ICV12, #endif }, .fips.approved = 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, .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 = { .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, #ifdef SADB_X_EALG_AES_CCM_ICV16 [SADB_ALG_ID] = SADB_X_EALG_AES_CCM_ICV16, #endif }, .fips.approved = 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, .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 = { .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.approved = 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 = { .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_INTEG_AES_XCBC_96, #ifdef SADB_X_AALG_AES_XCBC_MAC [SADB_ALG_ID] = SADB_X_AALG_AES_XCBC_MAC, #endif }, .fips.approved = 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 .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 = { .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_INTEG_AES_CMAC_96, #ifdef SADB_X_AALG_AES_CMAC_96 [SADB_ALG_ID] = SADB_X_AALG_AES_CMAC_96, #endif }, .fips.approved = true, }, .integ_keymat_size = BYTES_FOR_BITS(128), .integ_output_size = BYTES_FOR_BITS(96), /* truncated */ .integ_ikev1_ah_transform = AH_AES_CMAC_96, .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 = { .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, #ifdef SADB_X_EALG_NULL_AUTH_AES_GMAC [SADB_ALG_ID] = SADB_X_EALG_NULL_AUTH_AES_GMAC, #endif #ifdef SADB_X_EALG_AESGMAC [SADB_ALG_ID] = SADB_X_EALG_AESGMAC, #endif }, .fips.approved = 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, .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-4.14/lib/libswan/ike_alg_camellia.c000066400000000000000000000057451457372064200212500ustar00rootroot00000000000000/* * 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 "lsw-pfkeyv2.h" /* for SADB_*ALG_* */ /* 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 = { .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, #ifdef SADB_X_EALG_CAMELLIACBC [SADB_ALG_ID] = SADB_X_EALG_CAMELLIACBC, #endif }, }, .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, .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 = { .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-4.14/lib/libswan/ike_alg_desc.c000066400000000000000000000033171457372064200204100ustar00rootroot00000000000000/* * 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; } const struct ipcomp_desc *ipcomp_desc(const struct ike_alg *alg) { passert(alg == NULL || alg->algo_type == IKE_ALG_IPCOMP); return (const struct ipcomp_desc *)alg; } libreswan-4.14/lib/libswan/ike_alg_dh.c000066400000000000000000000171621457372064200200700ustar00rootroot00000000000000/* * 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, .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, .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, .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.approved = 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, .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.approved = 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, .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.approved = 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, .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.approved = 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, .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.approved = 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_secp256r1 = { .common = { .algo_type = IKE_ALG_DH, .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.approved = true, }, .group = OAKLEY_GROUP_ECP_256, .bytes = BYTES_FOR_BITS(256) * 2, .nss_oid = SEC_OID_SECG_EC_SECP256R1, .nss_adds_ec_point_form_uncompressed = true, .dh_ops = &ike_alg_dh_nss_ecp_ops, }; const struct dh_desc ike_alg_dh_secp384r1 = { .common = { .algo_type = IKE_ALG_DH, .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.approved = true, }, .group = OAKLEY_GROUP_ECP_384, .bytes = BYTES_FOR_BITS(384) * 2, .nss_oid = SEC_OID_SECG_EC_SECP384R1, .nss_adds_ec_point_form_uncompressed = true, .dh_ops = &ike_alg_dh_nss_ecp_ops, }; const struct dh_desc ike_alg_dh_secp521r1 = { .common = { .algo_type = IKE_ALG_DH, .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.approved = true, }, .group = OAKLEY_GROUP_ECP_521, .bytes = BYTES_FOR_BITS(521) * 2, .nss_oid = SEC_OID_SECG_EC_SECP521R1, .nss_adds_ec_point_form_uncompressed = true, .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, .fqn = "DH22", .names = "dh22", .id = { [IKEv1_OAKLEY_ID] = OAKLEY_GROUP_DH22, [IKEv1_ESP_ID] = OAKLEY_GROUP_DH22, [IKEv2_ALG_ID] = OAKLEY_GROUP_DH22, }, .fips.approved = false, /* SP 800-56A rev 3 */ }, .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, .fqn = "DH23", .names = "dh23", .id = { [IKEv1_OAKLEY_ID] = OAKLEY_GROUP_DH23, [IKEv1_ESP_ID] = OAKLEY_GROUP_DH23, [IKEv2_ALG_ID] = OAKLEY_GROUP_DH23, }, .fips.approved = false, /* SP 800-56A rev 3 */ }, .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, .fqn = "DH24", .names = "dh24", .id = { [IKEv1_OAKLEY_ID] = OAKLEY_GROUP_DH24, [IKEv1_ESP_ID] = OAKLEY_GROUP_DH24, [IKEv2_ALG_ID] = OAKLEY_GROUP_DH24, }, .fips.approved = false, /* SP 800-56A rev 3 */ }, .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_curve25519 = { .common = { .algo_type = IKE_ALG_DH, .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-4.14/lib/libswan/ike_alg_dh_nss_ecp_ops.c000066400000000000000000000156611457372064200224650ustar00rootroot00000000000000/* * 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 "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_local_secret(const struct dh_desc *group, SECKEYPrivateKey **privk, SECKEYPublicKey **pubk, struct logger *logger) { /* * Get the PK11 formatted EC parameters (stored in static * data) from NSS. */ DBGF(DBG_CRYPT, "oid %d %x", group->nss_oid, group->nss_oid); /* * Wrap the raw OID in ASN.1. SECKEYECParams is just a * glorifed SECItem. * * See also ECDSA code. */ const SECOidData *ec_oid = SECOID_FindOIDByTag(group->nss_oid); /*static*/ if (ec_oid == NULL) { llog_passert(logger, HERE, "lookup of OID %d for EC group %s parameters failed", group->nss_oid, group->common.fqn); } SECKEYECParams *ec_params = SEC_ASN1EncodeItem(NULL/*must-double-free*/, NULL, &ec_oid->oid, SEC_ObjectIDTemplate); if (ec_params == NULL) { llog_passert(logger, HERE, "wrapping of OID %d EC group %s parameters failed", group->nss_oid, group->common.fqn); } *privk = SECKEY_CreateECPrivateKey(ec_params, pubk, lsw_nss_get_password_context(logger)); SECITEM_FreeItem(ec_params, PR_TRUE/*also-free-SECItem*/); if (*pubk == NULL || *privk == NULL) { passert_nss_error(logger, HERE, "DH ECP private key creation failed"); } if (DBGP(DBG_CRYPT)) { LLOG_JAMBUF(DEBUG_STREAM, logger, buf) { jam(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); jam_nss_secitem(buf, &(*pubk)->u.ec.publicValue); } } } /* * NSS sometimes includes the EC_POINT_FORM_UNCOMPRESSED prefix but * what is needed is the plain EC coordinate without that prefix (see * documentation in pk11_get_EC_PointLenInBytes()). */ static shunk_t nss_ecp_local_secret_ke(const struct dh_desc *group, const SECKEYPublicKey *local_pubk) { if (group->nss_adds_ec_point_form_uncompressed) { passert(local_pubk->u.ec.publicValue.data[0] == EC_POINT_FORM_UNCOMPRESSED); passert(local_pubk->u.ec.publicValue.len == group->bytes + 1); return shunk2(local_pubk->u.ec.publicValue.data + 1, group->bytes); } /* * 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(local_pubk->u.ec.publicValue.len == group->bytes); dbg("putting NSS raw CURVE25519 public key blob on wire"); return same_secitem_as_shunk(local_pubk->u.ec.publicValue); } static diag_t nss_ecp_calc_shared_secret(const struct dh_desc *group, SECKEYPrivateKey *local_privk, const SECKEYPublicKey *local_pubk, chunk_t remote_ke, PK11SymKey **shared_secret, struct logger *logger) { 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(remote_ke.len == group->bytes); if (SECITEM_AllocItem(NULL, &remote_pubk.u.ec.publicValue, local_pubk->u.ec.publicValue.len) == NULL) { return diag_nss_error("location of ECC public key failed"); } /* must NSS-free remote_pubk.u.ec.publicValue */ if (group->nss_adds_ec_point_form_uncompressed) { /* * NSS returns and expects the encoded EC X-point pair * as the public part; but prefixed by * EC_POINT_FORM_COMPRESSED. */ passert(remote_ke.len + 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.ptr, remote_ke.len); } else { /* * NSS returns and expects the raw EC X-point as the * public part. The raw remote KE matches this format * (see comments in pk11_get_EC_PointLenInBytes()). */ passert(remote_ke.len == 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.ptr, remote_ke.len); } /* * 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_nss_get_password_context(logger)); if (temp == NULL) { *shared_secret = NULL; SECITEM_FreeItem(&remote_pubk.u.ec.publicValue, PR_FALSE); return diag_nss_error("shared key calculation using ECP failed"); } dbg_alloc("temp", temp, HERE); /* * 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. */ *shared_secret = key_from_symkey_bytes("ecp-shared-secret", temp, 0, sizeof_symkey(temp), HERE, logger); release_symkey(__func__, "temp", &temp); SECITEM_FreeItem(&remote_pubk.u.ec.publicValue, PR_FALSE); return NULL; } static void nss_ecp_check(const struct dh_desc *dhmke, struct logger *logger) { const struct ike_alg *alg = &dhmke->common; pexpect_ike_alg(logger, alg, dhmke->nss_oid > 0); } const struct dh_ops ike_alg_dh_nss_ecp_ops = { .backend = "NSS(ECP)", .check = nss_ecp_check, .calc_local_secret = nss_ecp_calc_local_secret, .local_secret_ke = nss_ecp_local_secret_ke, .calc_shared_secret = nss_ecp_calc_shared_secret, }; libreswan-4.14/lib/libswan/ike_alg_dh_nss_modp_ops.c000066400000000000000000000077221457372064200226540ustar00rootroot00000000000000/* * 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 "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_local_secret(const struct dh_desc *group, SECKEYPrivateKey **privk, SECKEYPublicKey **pubk, struct logger *logger) { chunk_t prime = chunk_from_hex(group->modp, group->modp); chunk_t base = chunk_from_hex(group->gen, group->gen); if (DBGP(DBG_CRYPT)) { DBG_dump_hunk("NSS: Value of Prime:", prime); 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) { DBGF(DBG_CRYPT, "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_nss_get_password_context(logger)); if (*pubk == NULL || *privk == NULL) { passert_nss_error(logger, HERE, "DH MODP private key creation failed"); } } while (group->bytes != (*pubk)->u.dh.publicValue.len); free_chunk_content(&prime); free_chunk_content(&base); } static shunk_t nss_modp_local_secret_ke(const struct dh_desc *group, const SECKEYPublicKey *local_pubk) { /* clone secitem as chunk()? */ passert(local_pubk->u.dh.publicValue.len == group->bytes); return shunk2(local_pubk->u.dh.publicValue.data, group->bytes); } static diag_t nss_modp_calc_shared_secret(const struct dh_desc *group, SECKEYPrivateKey *local_privk, const SECKEYPublicKey *local_pubk, chunk_t remote_ke, PK11SymKey **shared_secret, struct logger *logger) { DBGF(DBG_CRYPT, "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.ptr,/*NSS-doesn't do const*/ .len = remote_ke.len, .type = siBuffer }, }, }; *shared_secret = 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_nss_get_password_context(logger)); if (*shared_secret == NULL) { return diag_nss_error("shared key calculation using MODP failed"); } if (DBGP(DBG_BASE)) { DBG_symkey(logger, "newref ", "g_ir", *shared_secret); } return NULL; } static void nss_modp_check(const struct dh_desc *dhmke, struct logger *logger) { const struct ike_alg *alg = &dhmke->common; pexpect_ike_alg(logger, alg, dhmke->gen != NULL); pexpect_ike_alg(logger, alg, dhmke->modp != NULL); } const struct dh_ops ike_alg_dh_nss_modp_ops = { .backend = "NSS(MODP)", .check = nss_modp_check, .calc_local_secret = nss_modp_calc_local_secret, .local_secret_ke = nss_modp_local_secret_ke, .calc_shared_secret = nss_modp_calc_shared_secret, }; libreswan-4.14/lib/libswan/ike_alg_encrypt_cbc_test_vectors.c000066400000000000000000000161111457372064200245650ustar00rootroot00000000000000/* * 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 "constants.h" #include "lswalloc.h" #include "ike_alg.h" #include "test_buffer.h" #include "ike_alg_test_cbc.h" #include "ike_alg_encrypt_ops.h" /* XXX: oops */ #include "lswfips.h" #include "pk11pub.h" #include "crypt_symkey.h" #include "lswlog.h" /* * Ref: https://tools.ietf.org/html/rfc3602: Test Vectors */ static const struct cbc_test_vector aes_cbc_test_vectors[] = { { .description = "Encrypting 16 bytes (1 block) using AES-CBC with 128-bit key", .key = "0x06a9214036b8a15b512e03d534120006", .iv = "0x3dafba429d9eb430b422da802c9fac41", .plaintext = "Single block msg", .ciphertext = "0xe353779c1079aeb82708942dbe77181a" }, { .description = "Encrypting 32 bytes (2 blocks) using AES-CBC with 128-bit key", .key = "0xc286696d887c9aa0611bbb3e2025a45a", .iv = "0x562e17996d093d28ddb3ba695a2e6f58", .plaintext = "0x000102030405060708090a0b0c0d0e0f" "101112131415161718191a1b1c1d1e1f", .ciphertext = "0xd296cd94c2cccf8a3a863028b5e1dc0a" "7586602d253cfff91b8266bea6d61ab1" }, { .description = "Encrypting 48 bytes (3 blocks) using AES-CBC with 128-bit key", .key = "0x6c3ea0477630ce21a2ce334aa746c2cd", .iv = "0xc782dc4c098c66cbd9cd27d825682c81", .plaintext = "This is a 48-byte message (exactly 3 AES blocks)", .ciphertext = "0xd0a02b3836451753d493665d33f0e886" "2dea54cdb293abc7506939276772f8d5" "021c19216bad525c8579695d83ba2684" }, { .description = "Encrypting 64 bytes (4 blocks) using AES-CBC with 128-bit key", .key = "0x56e47a38c5598974bc46903dba290349", .iv = "0x8ce82eefbea0da3c44699ed7db51b7d9", .plaintext = "0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf" "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf", .ciphertext = "0xc30e32ffedc0774e6aff6af0869f71aa" "0f3af07a9a31a9c684db207eb0ef8e4e" "35907aa632c3ffdf868bb7b29d3d46ad" "83ce9f9a102ee99d49a53e87f4c3da55" }, { .description = NULL, } }; const struct cbc_test_vector *const aes_cbc_tests = aes_cbc_test_vectors; /* * https://tools.ietf.org/html/rfc4312 * https://info.isl.ntt.co.jp/crypt/index.html * https://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/t_camellia.txt */ static const struct cbc_test_vector camellia_cbc_test_vectors[] = { { .description = "Camellia: 16 bytes with 128-bit key", .key = "0x" "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", .iv = "0x" "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", .plaintext = "0x" "80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", .ciphertext = "0x" "07 92 3A 39 EB 0A 81 7D 1C 4D 87 BD B8 2D 1F 1C" }, { .description = "Camellia: 16 bytes with 128-bit key", .key = "0x" "00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF", .iv = "0x" "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", .plaintext = "0x" "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 ", .ciphertext = "0x" "14 4D 2B 0F 50 0C 27 B7 EC 2C D1 2D 91 59 6F 37" }, { .description = "Camellia: 16 bytes with 256-bit key", .key = "0x" "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", .iv = "0x" "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", .plaintext = "0x" "80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", .ciphertext = "0x" "B0 C6 B8 8A EA 51 8A B0 9E 84 72 48 E9 1B 1B 9D" }, { .description = "Camellia: 16 bytes with 256-bit key", .key = "0x" "00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF FF EE DD CC BB AA 99 88 77 66 55 44 33 22 11 00", .iv = "0x" "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", .plaintext = "0x" "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01", .ciphertext = "0x" "CC 39 FF EE 18 56 D3 EB 61 02 5E 93 21 9B 65 23 " }, { .description = NULL, } }; const struct cbc_test_vector *const camellia_cbc_tests = camellia_cbc_test_vectors; static bool test_cbc_op(const struct encrypt_desc *encrypt_desc, const char *description, int encrypt, PK11SymKey *sym_key, const char *encoded_iv, const char *input_name, const char *input, const char *output_name, const char *output, struct logger *logger) { const char *op = encrypt ? "encrypt" : "decrypt"; bool ok = true; chunk_t iv = decode_to_chunk("IV: ", encoded_iv); /* * If encrypting, the new iv is in the output, if decrypting, * the new iv is the input. The expected IV is found in the * last few bytes. */ chunk_t expected_iv = decode_to_chunk("new IV: ", encrypt ? output : input); chunk_t tmp = decode_to_chunk(input_name, input); chunk_t expected = decode_to_chunk(output_name, output); /* do_crypt modifies the data and IV in place. */ encrypt_desc->encrypt_ops->do_crypt(encrypt_desc, tmp.ptr, tmp.len, sym_key, iv.ptr, encrypt, logger); if (!verify_hunk(op, expected, tmp)) { DBGF(DBG_CRYPT, "test_cbc_op: %s: %s: output does not match", description, op); ok = false; } if (!verify_bytes("updated CBC IV", iv.ptr, iv.len, expected_iv.ptr + expected_iv.len - iv.len, iv.len)) { DBGF(DBG_CRYPT, "test_cbc_op: %s: %s: IV does not match", description, op); ok = false; } free_chunk_content(&iv); free_chunk_content(&expected_iv); free_chunk_content(&tmp); free_chunk_content(&expected); return ok; } /* * https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/nss_sample_code/NSS_Sample_Code_sample2 * https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/NSS_Tech_Notes/nss_tech_note5 */ static bool test_cbc_vector(const struct encrypt_desc *encrypt_desc, const struct cbc_test_vector *test, struct logger *logger) { bool ok = true; PK11SymKey *sym_key = decode_to_key(encrypt_desc, test->key, logger); if (!test_cbc_op(encrypt_desc, test->description, 1, sym_key, test->iv, "plaintext: ", test->plaintext, "ciphertext: ", test->ciphertext, logger)) { ok = false; } if (!test_cbc_op(encrypt_desc, test->description, 0, sym_key, test->iv, "ciphertext: ", test->ciphertext, "plaintext: ", test->plaintext, logger)) { ok = false; } /* Clean up. */ release_symkey(__func__, "sym_key", &sym_key); DBGF(DBG_CRYPT, "test_ctr_vector: %s %s", test->description, ok ? "passed" : "failed"); return ok; } bool test_cbc_vectors(const struct encrypt_desc *desc, const struct cbc_test_vector *tests, struct logger *logger) { bool ok = true; const struct cbc_test_vector *test; for (test = tests; test->description != NULL; test++) { llog(RC_LOG, logger, " %s", test->description); if (!test_cbc_vector(desc, test, logger)) { ok = false; } } return ok; } libreswan-4.14/lib/libswan/ike_alg_encrypt_chacha20_poly1305.c000066400000000000000000000032231457372064200241570ustar00rootroot00000000000000/* 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 = { .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-4.14/lib/libswan/ike_alg_encrypt_ctr_test_vectors.c000066400000000000000000000202541457372064200246310ustar00rootroot00000000000000/* * Copyright (C) 2014-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. */ #include #include #include "constants.h" #include "lswalloc.h" #include "ike_alg.h" #include "test_buffer.h" #include "ike_alg_test_ctr.h" #include "ike_alg_encrypt_ops.h" /* XXX: oops */ #include "lswfips.h" #include "pk11pub.h" #include "crypt_symkey.h" #include "lswlog.h" /* * Ref: https://tools.ietf.org/html/rfc3686 Test Vectors */ static const struct ctr_test_vector aes_ctr_test_vectors[] = { { .description = "Encrypting 16 octets using AES-CTR with 128-bit key", .key = "0x AE 68 52 F8 12 10 67 CC 4B F7 A5 76 55 77 F3 9E", .plaintext = "0x 53 69 6E 67 6C 65 20 62 6C 6F 63 6B 20 6D 73 67", .cb = "0x 00 00 00 30 00 00 00 00 00 00 00 00 00 00 00 01", .ciphertext = "0x E4 09 5D 4F B7 A7 B3 79 2D 61 75 A3 26 13 11 B8", .output_cb = "0x 00 00 00 30 00 00 00 00 00 00 00 00 00 00 00 02", }, { .description = "Encrypting 32 octets using AES-CTR with 128-bit key", .key = "0x 7E 24 06 78 17 FA E0 D7 43 D6 CE 1F 32 53 91 63", .plaintext = "0x" "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F" "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F", .cb = "0x 00 6C B6 DB C0 54 3B 59 DA 48 D9 0B 00 00 00 01", .ciphertext = "0x" "51 04 A1 06 16 8A 72 D9 79 0D 41 EE 8E DA D3 88" "EB 2E 1E FC 46 DA 57 C8 FC E6 30 DF 91 41 BE 28", .output_cb = "0x 00 6C B6 DB C0 54 3B 59 DA 48 D9 0B 00 00 00 03", }, { .description = "Encrypting 36 octets using AES-CTR with 128-bit key", .key = "0x 76 91 BE 03 5E 50 20 A8 AC 6E 61 85 29 F9 A0 DC", .plaintext = "0x" "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F" "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F" "20 21 22 23", .cb = "0x 00 E0 01 7B 27 77 7F 3F 4A 17 86 F0 00 00 00 01", .ciphertext = "0x" "C1 CF 48 A8 9F 2F FD D9 CF 46 52 E9 EF DB 72 D7" "45 40 A4 2B DE 6D 78 36 D5 9A 5C EA AE F3 10 53" "25 B2 07 2F", .output_cb = "0x 00 E0 01 7B 27 77 7F 3F 4A 17 86 F0 00 00 00 04", }, { .description = "Encrypting 16 octets using AES-CTR with 192-bit key", .key = "0x" "16 AF 5B 14 5F C9 F5 79 C1 75 F9 3E 3B FB 0E ED" "86 3D 06 CC FD B7 85 15", .plaintext = "0x 53 69 6E 67 6C 65 20 62 6C 6F 63 6B 20 6D 73 67", .cb = "0x 00 00 00 48 36 73 3C 14 7D 6D 93 CB 00 00 00 01", .ciphertext = "0x 4B 55 38 4F E2 59 C9 C8 4E 79 35 A0 03 CB E9 28", .output_cb = "0x 00 00 00 48 36 73 3C 14 7D 6D 93 CB 00 00 00 02", }, { .description = "Encrypting 32 octets using AES-CTR with 192-bit key", .key = "0x" "7C 5C B2 40 1B 3D C3 3C 19 E7 34 08 19 E0 F6 9C" "67 8C 3D B8 E6 F6 A9 1A", .plaintext = "0x" "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F" "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F", .cb = "0x 00 96 B0 3B 02 0C 6E AD C2 CB 50 0D 00 00 00 01", .ciphertext = "0x" "45 32 43 FC 60 9B 23 32 7E DF AA FA 71 31 CD 9F" "84 90 70 1C 5A D4 A7 9C FC 1F E0 FF 42 F4 FB 00", .output_cb = "0x 00 96 B0 3B 02 0C 6E AD C2 CB 50 0D 00 00 00 03", }, { .description = "Encrypting 36 octets using AES-CTR with 192-bit key", .key = "0x" "02 BF 39 1E E8 EC B1 59 B9 59 61 7B 09 65 27 9B" "F5 9B 60 A7 86 D3 E0 FE", .plaintext = "0x" "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F" "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F" "20 21 22 23", .cb = "0x 00 07 BD FD 5C BD 60 27 8D CC 09 12 00 00 00 01", .ciphertext = "0x" "96 89 3F C5 5E 5C 72 2F 54 0B 7D D1 DD F7 E7 58" "D2 88 BC 95 C6 91 65 88 45 36 C8 11 66 2F 21 88" "AB EE 09 35", .output_cb = "0x 00 07 BD FD 5C BD 60 27 8D CC 09 12 00 00 00 04", }, { .description = "Encrypting 16 octets using AES-CTR with 256-bit key", .key = "0x" "77 6B EF F2 85 1D B0 6F 4C 8A 05 42 C8 69 6F 6C" "6A 81 AF 1E EC 96 B4 D3 7F C1 D6 89 E6 C1 C1 04", .plaintext = "0x 53 69 6E 67 6C 65 20 62 6C 6F 63 6B 20 6D 73 67", .cb = "0x 00 00 00 60 DB 56 72 C9 7A A8 F0 B2 00 00 00 01", .ciphertext = "0x 14 5A D0 1D BF 82 4E C7 56 08 63 DC 71 E3 E0 C0", .output_cb = "0x 00 00 00 60 DB 56 72 C9 7A A8 F0 B2 00 00 00 02", }, { .description = "Encrypting 32 octets using AES-CTR with 256-bit key", .key = "0x" "F6 D6 6D 6B D5 2D 59 BB 07 96 36 58 79 EF F8 86" "C6 6D D5 1A 5B 6A 99 74 4B 50 59 0C 87 A2 38 84", .plaintext = "0x" "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F" "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F", .cb = "0x 00 FA AC 24 C1 58 5E F1 5A 43 D8 75 00 00 00 01", .ciphertext = "0x" "F0 5E 23 1B 38 94 61 2C 49 EE 00 0B 80 4E B2 A9" "B8 30 6B 50 8F 83 9D 6A 55 30 83 1D 93 44 AF 1C", .output_cb = "0x 00 FA AC 24 C1 58 5E F1 5A 43 D8 75 00 00 00 03", }, { .description = "Encrypting 36 octets using AES-CTR with 256-bit key", .key = "0x" "FF 7A 61 7C E6 91 48 E4 F1 72 6E 2F 43 58 1D E2" "AA 62 D9 F8 05 53 2E DF F1 EE D6 87 FB 54 15 3D", .plaintext = "0x" "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F" "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F" "20 21 22 23", .cb = "0x 00 1C C5 B7 51 A5 1D 70 A1 C1 11 48 00 00 00 01", .ciphertext = "0x" "EB 6C 52 82 1D 0B BB F7 CE 75 94 46 2A CA 4F AA" "B4 07 DF 86 65 69 FD 07 F4 8C C0 B5 83 D6 07 1F" "1E C0 E6 B8", .output_cb = "0x 00 1C C5 B7 51 A5 1D 70 A1 C1 11 48 00 00 00 04", }, { .description = NULL, } }; const struct ctr_test_vector *const aes_ctr_tests = aes_ctr_test_vectors; static bool test_ctr_op(const struct encrypt_desc *encrypt_desc, const char *description, int encrypt, PK11SymKey *sym_key, const char *encoded_cb, const char *output_cb, const char *input_name, const char *input, const char *output_name, const char *output, struct logger *logger) { const char *op = encrypt ? "encrypt" : "decrypt"; bool ok = true; chunk_t cb = decode_to_chunk("input counter-block: ", encoded_cb); chunk_t tmp = decode_to_chunk(input_name, input); chunk_t expected_output = decode_to_chunk(output_name, output); chunk_t expected_cb = decode_to_chunk("expected counter-block: ", output_cb); /* do_crypt modifies the data and IV in place. */ encrypt_desc->encrypt_ops->do_crypt(encrypt_desc, tmp.ptr, tmp.len, sym_key, cb.ptr, encrypt, logger); if (!verify_hunk(op, expected_output, tmp)) { DBGF(DBG_CRYPT, "test_ctr_op: %s: %s: output does not match", description, op); ok = false; } if (!verify_hunk("counter-block", expected_cb, cb)) { DBGF(DBG_CRYPT, "test_ctr_op: %s: %s: counter-block does not match", description, op); ok = false; } free_chunk_content(&cb); free_chunk_content(&expected_cb); free_chunk_content(&tmp); free_chunk_content(&expected_output); return ok; } static bool test_ctr_vector(const struct encrypt_desc *encrypt_desc, const struct ctr_test_vector *test, struct logger *logger) { bool ok = true; PK11SymKey *sym_key = decode_to_key(encrypt_desc, test->key, logger); if (!test_ctr_op(encrypt_desc, test->description, 1, sym_key, test->cb, test->output_cb, "Plaintext", test->plaintext, "Ciphertext", test->ciphertext, logger)) { ok = false; } if (!test_ctr_op(encrypt_desc, test->description, 0, sym_key, test->cb, test->output_cb, "Ciphertext", test->ciphertext, "Plaintext", test->plaintext, logger)) { ok = false; } /* Clean up. */ release_symkey(__func__, "sym_key", &sym_key); DBGF(DBG_CRYPT, "test_ctr_vector: %s %s", test->description, ok ? "passed" : "failed"); return ok; } bool test_ctr_vectors(const struct encrypt_desc *desc, const struct ctr_test_vector *tests, struct logger *logger) { bool ok = true; const struct ctr_test_vector *test; for (test = tests; test->description != NULL; test++) { llog(RC_LOG, logger, " %s", test->description); if (!test_ctr_vector(desc, test, logger)) { ok = false; } } return ok; } libreswan-4.14/lib/libswan/ike_alg_encrypt_gcm_test_vectors.c000066400000000000000000000130761457372064200246130ustar00rootroot00000000000000/* * 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. */ #include #include #include "constants.h" #include "lswalloc.h" #include "lswfips.h" #include "ike_alg.h" #include "test_buffer.h" #include "ike_alg_test_gcm.h" #include "ike_alg_encrypt_ops.h" /* XXX: oops */ #include "pk11pub.h" #include "crypt_symkey.h" #include "lswlog.h" /* * Ref: http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip * * some select entries */ static const struct gcm_test_vector aes_gcm_test_vectors[] = { { .description = "empty string", .key ="0xcf063a34d4a9a76c2c86787d3f96db71", .salted_iv = "0x113b9785971864c83b01c787", .ciphertext = "", .aad = "", .tag = "0x72ac8493e3a5228b5d130a69d2510e42", .plaintext = "" }, { .description = "one block", .key = "0xe98b72a9881a84ca6b76e0f43e68647a", .salted_iv = "0x8b23299fde174053f3d652ba", .ciphertext = "0x5a3c1cf1985dbb8bed818036fdd5ab42", .aad = "", .tag = "0x23c7ab0f952b7091cd324835043b5eb5", .plaintext = "0x28286a321293253c3e0aa2704a278032", }, { .description = "two blocks", .key = "0xbfd414a6212958a607a0f5d3ab48471d", .salted_iv = "0x86d8ea0ab8e40dcc481cd0e2", .ciphertext = "0x62171db33193292d930bf6647347652c1ef33316d7feca99d54f1db4fcf513f8", .aad = "", .tag = "0xc28280aa5c6c7a8bd366f28c1cfd1f6e", .plaintext = "0xa6b76a066e63392c9443e60272ceaeb9d25c991b0f2e55e2804e168c05ea591a", }, { .description = "two blocks with associated data", .key = "0x006c458100fc5f4d62949d2c833b82d1", .salted_iv = "0xa4e9c4bc5725a21ff42c82b2", .ciphertext = "0xf39b4db3542d8542fb73fd2d66be568f26d7f814b3f87d1eceac3dd09a8d697e", .aad = "0x2efb14fb3657cdd6b9a8ff1a5f5a39b9", .tag = "0x39f045cb23b698c925db134d56c5", .plaintext = "0xf381d3bfbee0a879f7a4e17b623278cedd6978053dd313530a18f1a836100950", }, { .key = NULL, } }; const struct gcm_test_vector *const aes_gcm_tests = aes_gcm_test_vectors; static bool test_gcm_vector(const struct encrypt_desc *encrypt_desc, const struct gcm_test_vector *test, struct logger *logger) { const size_t salt_size = encrypt_desc->salt_size; bool ok = true; PK11SymKey *sym_key = decode_to_key(encrypt_desc, test->key, logger); chunk_t salted_iv = decode_to_chunk("salted IV", test->salted_iv); passert(salted_iv.len == encrypt_desc->wire_iv_size + salt_size); chunk_t salt = { .ptr = salted_iv.ptr, .len = salt_size }; chunk_t wire_iv = { .ptr = salted_iv.ptr + salt_size, .len = salted_iv.len - salt_size }; chunk_t aad = decode_to_chunk("AAD", test->aad); chunk_t plaintext = decode_to_chunk("plaintext", test->plaintext); chunk_t ciphertext = decode_to_chunk("ciphertext", test->ciphertext); passert(plaintext.len == ciphertext.len); size_t len = plaintext.len; chunk_t tag = decode_to_chunk("tag", test->tag); chunk_t text_and_tag; text_and_tag.len = len + tag.len; text_and_tag.ptr = alloc_bytes(text_and_tag.len, "GCM data"); /* macro to test encryption or decryption * * This would be better as a function but it uses too many locals * from test_gcm_vector to be pleasant: * text_and_tag, len, tag, aad, salt, wire_iv, sym_key */ # define try(enc, desc, from, to) \ { \ memcpy(text_and_tag.ptr, from.ptr, from.len); \ text_and_tag.len = len + tag.len; \ if (DBGP(DBG_CRYPT)) { \ DBG_log("test_gcm_vector: %s: aad-size=%zd salt-size=%zd wire-IV-size=%zd text-size=%zd tag-size=%zd", \ desc, aad.len, salt.len, wire_iv.len, len, tag.len); \ DBG_dump_hunk("test_gcm_vector: text+tag on call", \ text_and_tag); \ } \ if (!encrypt_desc->encrypt_ops->do_aead(encrypt_desc, \ salt.ptr, salt.len, \ wire_iv.ptr, wire_iv.len, \ aad.ptr, aad.len, \ text_and_tag.ptr, \ len, tag.len, \ sym_key, enc, \ logger) || \ !verify_bytes("output ciphertext", to.ptr, to.len, \ text_and_tag.ptr, to.len) || \ !verify_bytes("TAG", tag.ptr, tag.len, \ text_and_tag.ptr + len, tag.len)) \ ok = false; \ if (DBGP(DBG_CRYPT)) { \ DBG_dump_hunk("test_gcm_vector: text+tag on return", \ text_and_tag); \ } \ } /* test decryption */ memcpy(text_and_tag.ptr + len, tag.ptr, tag.len); try(false, "decrypt", ciphertext, plaintext); /* test encryption */ memset(text_and_tag.ptr + len, '\0', tag.len); try(true, "encrypt", plaintext, ciphertext); # undef try free_chunk_content(&salted_iv); free_chunk_content(&aad); free_chunk_content(&plaintext); free_chunk_content(&ciphertext); free_chunk_content(&tag); free_chunk_content(&text_and_tag); /* Clean up. */ release_symkey(__func__, "sym_key", &sym_key); DBGF(DBG_CRYPT, "test_gcm_vector: %s", ok ? "passed" : "failed"); return ok; } bool test_gcm_vectors(const struct encrypt_desc *desc, const struct gcm_test_vector *tests, struct logger *logger) { bool ok = true; const struct gcm_test_vector *test; for (test = tests; test->key != NULL; test++) { llog(RC_LOG, logger, " %s", test->description); if (!test_gcm_vector(desc, test, logger)) { ok = false; } } return ok; } libreswan-4.14/lib/libswan/ike_alg_encrypt_nss_aead_ops.c000066400000000000000000000073511457372064200236760ustar00rootroot00000000000000/* 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, struct logger *logger) { /* 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_hunk_hunk(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) { llog_nss_error(RC_LOG, logger, "AEAD encryption using %s_%u and PK11_Encrypt() failed", alg->common.fqn, PK11_GetKeyLength(sym_key) * BITS_PER_BYTE); ok = false; } else if (out_len != text_and_tag_size) { /* should this be a pexpect fail? */ llog_nss_error(RC_LOG_SERIOUS, logger, "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); 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) { llog_nss_error(RC_LOG, logger, "NSS: AEAD decryption using %s_%u and PK11_Decrypt() failed", alg->common.fqn, PK11_GetKeyLength(sym_key) * BITS_PER_BYTE); ok = false; } else if (out_len != text_size) { /* should this be a pexpect fail? */ llog_nss_error(RC_LOG_SERIOUS, logger, "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); ok = false; } } memcpy(text_and_tag, out_buf, out_len); PR_Free(out_buf); free_chunk_content(&iv); return ok; } static void nss_aead_check(const struct encrypt_desc *encrypt, struct logger *logger) { const struct ike_alg *alg = &encrypt->common; pexpect_ike_alg(logger, 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-4.14/lib/libswan/ike_alg_encrypt_nss_cbc_ops.c000066400000000000000000000067461457372064200235420ustar00rootroot00000000000000/* * 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 llog_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, struct logger *logger) { DBGF(DBG_CRYPT, "NSS ike_alg_nss_cbc: %s - enter", alg->common.fqn); if (symkey == NULL) { llog_passert(logger, HERE, "%s - NSS derived enc key in NULL", alg->common.fqn); } SECItem ivitem; ivitem.type = siBuffer; ivitem.data = iv; ivitem.len = alg->enc_blocksize; SECItem *secparam = PK11_ParamFromIV(alg->nss.mechanism, &ivitem); if (secparam == NULL) { llog_passert(logger, HERE, "%s - Failure to set up PKCS11 param (err %d)", alg->common.fqn, PR_GetError()); } PK11Context *enccontext; enccontext = PK11_CreateContextBySymKey(alg->nss.mechanism, enc ? CKA_ENCRYPT : CKA_DECRYPT, symkey, secparam); if (enccontext == NULL) { passert_nss_error(logger, HERE, "%s: PKCS11 context creation failure", alg->common.fqn); } /* 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) { passert_nss_error(logger, HERE, "%s: PKCS11 operation failure", alg->common.fqn); } 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); DBGF(DBG_CRYPT, "NSS ike_alg_nss_cbc: %s - exit", alg->common.fqn); } static void nss_cbc_check(const struct encrypt_desc *encrypt, struct logger *logger) { const struct ike_alg *alg = &encrypt->common; pexpect_ike_alg(logger, 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-4.14/lib/libswan/ike_alg_encrypt_nss_ctr_ops.c000066400000000000000000000067771457372064200236070ustar00rootroot00000000000000/* * 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 #include #include #include #include "constants.h" #include "lswlog.h" #include "ike_alg.h" #include "lswnss.h" #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, struct logger *logger) { DBGF(DBG_CRYPT, "do_aes_ctr: enter"); passert(sym_key); if (sym_key == NULL) { llog_passert(logger, HERE, "%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_nss_error(logger, HERE, "PK11_Encrypt failure"); } } else { SECStatus rv = PK11_Decrypt(sym_key, CKM_AES_CTR, ¶m, out_buf, &out_len, buf_len, buf, buf_len); if (rv != SECSuccess) { passert_nss_error(logger, HERE, "PK11_Decrypt failure"); } } 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; DBGF(DBG_CRYPT, "do_aes_ctr: counter-block updated from 0x%" PRIx32 " to 0x%" PRIx32 " for %zd bytes", old_counter, new_counter, buf_len); /* Wrap ... */ passert(new_counter >= old_counter); *counter = htonl(new_counter); DBGF(DBG_CRYPT, "do_aes_ctr: exit"); } static void nss_ctr_check(const struct encrypt_desc *alg UNUSED, struct logger *unused_logger UNUSED) { } const struct encrypt_ops ike_alg_encrypt_nss_ctr_ops = { .backend = "NSS(CTR)", .check = nss_ctr_check, .do_crypt = do_nss_ctr, }; libreswan-4.14/lib/libswan/ike_alg_encrypt_nss_gcm_ops.c000066400000000000000000000074731457372064200235570ustar00rootroot00000000000000/* 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 /* * Special advise from Bob Relyea - needs to go before any nss include * */ #define NSS_PKCS11_2_0_COMPAT 1 #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, struct logger *logger) { /* 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_hunk_hunk(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) { llog_nss_error(RC_LOG, logger, "AEAD encryption using %s_%u and PK11_Encrypt() failed", alg->common.fqn, PK11_GetKeyLength(sym_key) * BITS_PER_BYTE); ok = false; } else if (out_len != text_and_tag_size) { /* should this be a pexpect fail? */ llog_nss_error(RC_LOG_SERIOUS, logger, "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); 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) { llog_nss_error(RC_LOG, logger, "AEAD decryption using %s_%u and PK11_Decrypt() failed", alg->common.fqn, PK11_GetKeyLength(sym_key) * BITS_PER_BYTE); ok = false; } else if (out_len != text_size) { /* should this be a pexpect fail? */ llog_nss_error(RC_LOG_SERIOUS, logger, "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); ok = false; } } memcpy(text_and_tag, out_buf, out_len); PR_Free(out_buf); free_chunk_content(&iv); return ok; } static void nss_gcm_check(const struct encrypt_desc *encrypt, struct logger *logger) { const struct ike_alg *alg = &encrypt->common; pexpect_ike_alg(logger, 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-4.14/lib/libswan/ike_alg_hash_identity.c000066400000000000000000000020661457372064200223260ustar00rootroot00000000000000/* * Copyright (C) 2022 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" /* * RFC 8420 */ const struct hash_desc ike_alg_hash_identity = { .common = { .fqn = "IDENTITY", .names = "identity", .algo_type = IKE_ALG_HASH, .id = { [IKEv1_OAKLEY_ID] = -1, [IKEv1_ESP_ID] = -1, [IKEv2_ALG_ID] = IKEv2_HASH_ALGORITHM_IDENTITY, }, .fips.approved = true, }, }; libreswan-4.14/lib/libswan/ike_alg_hash_md5.c000066400000000000000000000031131457372064200211540ustar00rootroot00000000000000/* 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_hash_ops.h" const struct hash_desc ike_alg_hash_md5 = { .common = { .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, }; libreswan-4.14/lib/libswan/ike_alg_hash_nss_ops.c000066400000000000000000000054461457372064200221660ustar00rootroot00000000000000/* * 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, struct logger *logger) { const struct ike_alg *alg = &hash->common; // pexpect_ike_alg(alg, hash->common.nss_mechanism == 0); pexpect_ike_alg(logger, alg, hash->nss.oid_tag > 0); pexpect_ike_alg(logger, 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-4.14/lib/libswan/ike_alg_hash_sha1.c000066400000000000000000000043231457372064200213270ustar00rootroot00000000000000/* 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_hash_ops.h" static const uint8_t asn1_pkcs1_1_5_rsa_sha1_blob[1+ASN1_PKCS1_1_5_RSA_SIZE] = { ASN1_PKCS1_1_5_RSA_SIZE, ASN1_PKCS1_1_5_RSA_SHA1_BLOB }; static const uint8_t asn1_ecdsa_sha1_blob[1+ASN1_ECDSA_SHA1_SIZE] = { ASN1_ECDSA_SHA1_SIZE, ASN1_ECDSA_SHA1_BLOB }; const struct hash_desc ike_alg_hash_sha1 = { .common = { .fqn = "SHA1", .names = "sha,sha1", .algo_type = IKE_ALG_HASH, .id = { [IKEv1_OAKLEY_ID] = OAKLEY_SHA1, [IKEv1_ESP_ID] = -1, [IKEv2_ALG_ID] = IKEv2_HASH_ALGORITHM_SHA1, }, .fips = { .approved = true, }, }, .nss = { .oid_tag = SEC_OID_SHA1, .derivation_mechanism = CKM_SHA1_KEY_DERIVATION, .pkcs1_1_5_rsa_oid_tag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION, }, .hash_digest_size = SHA1_DIGEST_SIZE, .hash_block_size = 64, /* B from RFC 2104 */ .hash_ops = &ike_alg_hash_nss_ops, .digital_signature_blob = { [DIGITAL_SIGNATURE_PKCS1_1_5_RSA_BLOB] = THING_AS_HUNK(asn1_pkcs1_1_5_rsa_sha1_blob), [DIGITAL_SIGNATURE_ECDSA_BLOB] = THING_AS_HUNK(asn1_ecdsa_sha1_blob), }, }; libreswan-4.14/lib/libswan/ike_alg_hash_sha2_256.c000066400000000000000000000050541457372064200217260ustar00rootroot00000000000000/* * 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_hash_ops.h" /* SHA-2 256 */ static const uint8_t asn1_pkcs1_1_5_rsa_sha2_256_blob[1+ASN1_PKCS1_1_5_RSA_SIZE] = { ASN1_PKCS1_1_5_RSA_SIZE, ASN1_PKCS1_1_5_RSA_SHA2_256_BLOB }; static const uint8_t asn1_ecdsa_sha2_256_blob[1+ASN1_ECDSA_SHA2_SIZE] = { ASN1_ECDSA_SHA2_SIZE, ASN1_ECDSA_SHA2_256_BLOB }; static const uint8_t asn1_rsassa_pss_sha2_256_blob[1+ASN1_RSASSA_PSS_SHA2_SIZE] = { ASN1_RSASSA_PSS_SHA2_SIZE, ASN1_RSASSA_PSS_SHA2_256_BLOB }; static const CK_RSA_PKCS_PSS_PARAMS rsa_pss_sha2_256 = { .hashAlg = CKM_SHA256, .mgf = CKG_MGF1_SHA256, .sLen = SHA2_256_DIGEST_SIZE, }; const struct hash_desc ike_alg_hash_sha2_256 = { .common = { .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] = IKEv2_HASH_ALGORITHM_SHA2_256, }, .fips = { .approved = true, }, }, .nss = { .oid_tag = SEC_OID_SHA256, .derivation_mechanism = CKM_SHA256_KEY_DERIVATION, .rsa_pkcs_pss_params = &rsa_pss_sha2_256, .pkcs1_1_5_rsa_oid_tag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION, }, .hash_digest_size = SHA2_256_DIGEST_SIZE, .hash_block_size = 64, /* from RFC 4868 */ .hash_ops = &ike_alg_hash_nss_ops, .digital_signature_blob = { [DIGITAL_SIGNATURE_PKCS1_1_5_RSA_BLOB] = THING_AS_HUNK(asn1_pkcs1_1_5_rsa_sha2_256_blob), [DIGITAL_SIGNATURE_ECDSA_BLOB] = THING_AS_HUNK(asn1_ecdsa_sha2_256_blob), [DIGITAL_SIGNATURE_RSASSA_PSS_BLOB] = THING_AS_HUNK(asn1_rsassa_pss_sha2_256_blob), }, }; libreswan-4.14/lib/libswan/ike_alg_ipcomp.c000066400000000000000000000041111457372064200207520ustar00rootroot00000000000000/* IKE modular algorithm handling interface, for libreswan * * Copyright (C) 2022 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_ipcomp.h" #include "ike_alg_ipcomp_ops.h" #include "lsw-pfkeyv2.h" const struct ipcomp_desc ike_alg_ipcomp_deflate = { .common = { .algo_type = IKE_ALG_IPCOMP, .fqn = "DEFLATE", .names = "deflate", .id = { [IKEv1_OAKLEY_ID] = -1, [IKEv1_ESP_ID] = IPCOMP_DEFLATE, [IKEv2_ALG_ID] = IPCOMP_DEFLATE, #ifdef SADB_X_CALG_DEFLATE [SADB_ALG_ID] = SADB_X_CALG_DEFLATE, #endif }, .fips.approved = true, /* it's meaningless */ }, .kernel = { .xfrm_name = "deflate", }, }; const struct ipcomp_desc ike_alg_ipcomp_lzs = { .common = { .algo_type = IKE_ALG_IPCOMP, .fqn = "LZS", .names = "lzs", .id = { [IKEv1_OAKLEY_ID] = -1, [IKEv1_ESP_ID] = -1, /*IPCOMP_LZS*/ [IKEv2_ALG_ID] = IPCOMP_LZS, #ifdef SADB_X_CALG_LZS [SADB_ALG_ID] = SADB_X_CALG_LZS, #endif }, .fips.approved = true, /* it's meaningless */ }, .kernel = { .xfrm_name = "lzs", }, }; const struct ipcomp_desc ike_alg_ipcomp_lzjh = { .common = { .algo_type = IKE_ALG_IPCOMP, .fqn = "LZJH", .names = "lzjh", .id = { [IKEv1_OAKLEY_ID] = -1, [IKEv1_ESP_ID] = -1, /*IPCOMP_LZJH*/ [IKEv2_ALG_ID] = IPCOMP_LZJH, #ifdef SADB_X_CALG_LZJH [SADB_ALG_ID] = SADB_X_CALG_LZJH, #endif }, .fips.approved = true, /* it's meaningless */ }, .kernel = { .xfrm_name = "lzjh", }, }; libreswan-4.14/lib/libswan/ike_alg_md5.c000066400000000000000000000047511457372064200201620ustar00rootroot00000000000000/* 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 "lsw-pfkeyv2.h" /* for SADB_*ALG_* */ const struct prf_desc ike_alg_prf_hmac_md5 = { .common = { .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 = { .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_INTEG_HMAC_MD5_96, #ifdef SADB_AALG_MD5HMAC [SADB_ALG_ID] = SADB_AALG_MD5HMAC, #endif }, }, .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, .integ_netlink_xfrm_name = "md5", .integ_tcpdump_name = "md5", .integ_ike_audit_name = "md5", .integ_kernel_audit_name = "HMAC_MD5", }; libreswan-4.14/lib/libswan/ike_alg_none.c000066400000000000000000000063661457372064200204400ustar00rootroot00000000000000/* * 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 "lsw-pfkeyv2.h" /* for SADB_*ALG_* */ /* * References for NULL. * * https://tools.ietf.org/html/rfc2410 */ const struct encrypt_desc ike_alg_encrypt_null = { .common = { .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, #ifdef SADB_EALG_NULL [SADB_ALG_ID] = SADB_EALG_NULL, #endif }, }, .enc_blocksize = 1, .wire_iv_size = 0, .pad_to_blocksize = false, .keylen_omitted = true, .keydeflen = 0, .key_bit_lengths = { 0, }, .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 = { .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_INTEG_NONE, #ifdef SADB_X_AALG_NULL /* This is from BSD's KAME */ [SADB_ALG_ID] = SADB_X_AALG_NULL, #endif }, /* * 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.approved = true, }, .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 = { .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.approved = true, }, .group = OAKLEY_GROUP_NONE, /* * While patently untrue, this does keep things happy. */ .dh_ops = &ike_alg_dh_nss_modp_ops, }; libreswan-4.14/lib/libswan/ike_alg_prf_ikev1_mac_ops.c000066400000000000000000000163111457372064200230570ustar00rootroot00000000000000/* * 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" #include "passert.h" #include "lswlog.h" /* for pexpect() */ /* * 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 */, struct logger *logger) { /* key = Ni|Nr */ chunk_t key = clone_hunk_hunk(Ni, Nr, "key = Ni|Nr"); struct crypt_prf *prf = crypt_prf_init_hunk("SKEYID sig", prf_desc, "Ni|Nr", key, logger); free_chunk_content(&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, struct logger *logger) { /* key = pre-shared-key */ struct crypt_prf *prf = crypt_prf_init_hunk("SKEYID psk", prf_desc, "psk", pre_shared_key, logger); /* 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, struct logger *logger) { /* key = SKEYID */ struct crypt_prf *prf = crypt_prf_init_symkey("SKEYID_d", prf_desc, "SKEYID", skeyid, logger); /* 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, struct logger *logger) { /* key = SKEYID */ struct crypt_prf *prf = crypt_prf_init_symkey("SKEYID_a", prf_desc, "SKEYID", skeyid, logger); /* 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, struct logger *logger) { /* key = SKEYID */ struct crypt_prf *prf = crypt_prf_init_symkey("SKEYID_e", prf_desc, "SKEYID", skeyid, logger); /* 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, struct logger *logger) { if (sizeof_symkey(skeyid_e) >= required_keymat) { return encrypt_key_from_symkey_bytes("keymat", encrypter, 0, required_keymat, skeyid_e, HERE, logger); } /* K1 = prf(skeyid_e, 0) */ PK11SymKey *keymat; { struct crypt_prf *prf = crypt_prf_init_symkey("appendix_b", prf_desc, "SKEYID_e", skeyid_e, logger); 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, logger); crypt_prf_update_symkey(prf, "old_k", old_k); PK11SymKey *new_k = crypt_prf_final_symkey(&prf); append_symkey_symkey(&keymat, new_k, logger); 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, logger); 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, struct logger *logger) { 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, logger); 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); /* * XXX: truncate the returned value back to what was * requested, rather than what was generated. */ PASSERT(logger, keymat.len >= required_keymat); 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-4.14/lib/libswan/ike_alg_prf_ikev1_nss_ops.c000066400000000000000000000224421457372064200231240ustar00rootroot00000000000000/* * 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 */, struct logger *logger) { 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, logger); } /* * 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, struct logger *logger) { PK11SymKey *psk = prf_key_from_hunk("psk", prf_desc, pre_shared_key, logger); 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, logger); 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, struct logger *logger) { 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, logger); } /* * 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, struct logger *logger) { 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, logger); } /* * 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, struct logger *logger) { 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, logger); } static PK11SymKey *appendix_b_keymat_e(const struct prf_desc *prf, const struct encrypt_desc *encrypter, PK11SymKey *skeyid_e, unsigned required_keymat, struct logger *logger) { /* * XXX: This requires a fix to an old bug adding * CKM_NSS_IKE1_APP_B_PRF_DERIVE to the allowed operations * that was embedded in the below changeset. * * changeset: 15575:225bb39eade1 * user: Robert Relyea * date: Mon Apr 20 16:58:16 2020 -0700 * summary: Bug 1629663 NSS missing IKEv1 Quick Mode KDF prf r=kjacobs */ 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, logger); } 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, struct logger *logger) { /* * XXX: this requires: * * changeset: 15575:225bb39eade1 * user: Robert Relyea * date: Mon Apr 20 16:58:16 2020 -0700 * summary: Bug 1629663 NSS missing IKEv1 Quick Mode KDF prf r=kjacobs * * We found another KDF function in libreswan that is not * using the NSS KDF API. * * Unfortunately, it seems the existing IKE KDF's in NSS are * not usable for the Quick Mode use. * * The libreswan code is in compute_proto_keymat() and the * specification is in * https://tools.ietf.org/html/rfc2409#section-5.5 * * [...] * * This patch implements this by extendind the Appendix B * Mechanism to take and optional key and data in a new * Mechanism parameter structure. Which flavor is used (old * CK_MECHANISM_TYPE or the new parameter) is determined by * the mechanism parameter lengths. Application which try to * use this new feature on old versions of NSS will get an * error (rather than invalid data). * * XXX: yes, it looks at params.len; ewwwww! */ 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_KDF=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, logger); chunk_t keymat = chunk_from_symkey("section 5 keymat", key, logger); PASSERT(logger, keymat.len == required_keymat); release_symkey("section 5 keymat", "keymat", &key); pfree(extra); return keymat; } const struct prf_ikev1_ops ike_alg_prf_ikev1_nss_ops = { .backend = "NSS", .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-4.14/lib/libswan/ike_alg_prf_ikev2_mac_ops.c000066400000000000000000000221171457372064200230610ustar00rootroot00000000000000/* * 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, struct logger *logger) { uint8_t count = 1; /* T1(prfplus) = prf(KEY, SEED|1) */ PK11SymKey *concatenated; { struct crypt_prf *prf = crypt_prf_init_symkey("prf+0", prf_desc, "key", key, logger); crypt_prf_update_symkey(prf, "seed", seed); crypt_prf_update_byte(prf, "1++", count++); concatenated = crypt_prf_final_symkey(&prf); } /* make a copy to keep things easy */ PK11SymKey *old_t = reference_symkey(__func__, "old_t[1]", concatenated); while (sizeof_symkey(concatenated) < required_keymat) { /* Tn = prf(KEY, Tn-1|SEED|n) */ struct crypt_prf *prf = crypt_prf_init_symkey("prf+N", prf_desc, "key", key, logger); 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(&concatenated, new_t, logger); release_symkey(__func__, "old_t[N]", &old_t); old_t = new_t; } release_symkey(__func__, "old_t[final]", &old_t); /* truncate the result to match the length with required_keymat */ PK11SymKey *result = key_from_symkey_bytes("result", concatenated, 0, required_keymat, HERE, logger); release_symkey(__func__, "concatenated", &concatenated); 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, struct logger *logger) { /* * 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 = chunk2(Ni.ptr, BYTES_FOR_BITS(64)); chunk_t Nr64 = chunk2(Nr.ptr, BYTES_FOR_BITS(64)); key = clone_hunk_hunk(Ni64, Nr64, "key = Ni|Nr"); key_name = "Ni[0:63] | Nr[0:63]"; break; } default: key = clone_hunk_hunk(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, logger); free_chunk_content(&key); if (prf == NULL) { llog_pexpect(logger, HERE, "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, struct logger *logger) { /* key = SK_d (old) */ struct crypt_prf *prf = crypt_prf_init_symkey("ike sa rekey skeyseed", prf_desc, "SK_d (old)", SK_d_old, logger); if (prf == NULL) { llog_pexpect(logger, HERE, "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, struct logger *logger) { PK11SymKey *data = symkey_from_hunk("data=Ni", Ni, logger); append_symkey_hunk("data+=Nr", &data, Nr, logger); append_symkey_hunk("data+=SPIi", &data, SPIi, logger); append_symkey_hunk("data+=SPIr", &data, SPIr, logger); PK11SymKey *result = prfplus(prf_desc, skeyseed, data, required_bytes, logger); 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, struct logger *logger) { if (required_bytes == 0) { /* * For instance esp=null-none. Caller should * interpret NULL to mean empty (NSS doesn't create * zero length keys). */ ldbg(logger, "no CHILD SA KEMAT is required"); return NULL; } PK11SymKey *data; if (new_dh_secret == NULL) { data = symkey_from_hunk("data=Ni", Ni, logger); append_symkey_hunk("data+=Nr", &data, Nr, logger); } else { /* make a local "readonly copy" and manipulate that */ data = reference_symkey("prf", "data", new_dh_secret); append_symkey_hunk("data+=Ni", &data, Ni, logger); append_symkey_hunk("data+=Nr", &data, Nr, logger); } PK11SymKey *result = prfplus(prf_desc, SK_d, data, required_bytes, logger); release_symkey(__func__, "data", &data); return result; } static struct crypt_mac psk_auth(const struct prf_desc *prf_desc, shunk_t pss, chunk_t first_packet, chunk_t nonce, const struct crypt_mac *id_hash, chunk_t intermediate_packet, struct logger *logger) { /* calculate inner prf */ PK11SymKey *prf_psk; { struct crypt_prf *prf = crypt_prf_init_hunk(" = prf(,\"Key Pad for IKEv2\")", prf_desc, "shared secret", pss, logger); if (prf == NULL) { if (libreswan_fipsmode()) { llog_passert(logger, HERE, "FIPS: failure creating %s PRF context for digesting PSK", prf_desc->common.fqn); } llog_pexpect(logger, HERE, "failure creating %s PRF context for digesting PSK", prf_desc->common.fqn); 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, logger); /* * 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); crypt_prf_update_hunk(prf,"IntAuth", intermediate_packet); 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-4.14/lib/libswan/ike_alg_prf_ikev2_nss_ops.c000066400000000000000000000204071457372064200231240ustar00rootroot00000000000000/* * 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, struct logger *logger) { 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, logger); } static PK11SymKey *prfplus(const struct prf_desc *prf_desc, PK11SymKey *key, PK11SymKey *seed, size_t required_keymat, struct logger *logger) { return prfplus_key_data("prfplus", prf_desc, key, seed, empty_chunk, required_keymat, logger); } /* * 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, struct logger *logger) { 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, logger); } /* * 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, struct logger *logger) { 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, logger); } /* * 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, struct logger *logger) { PK11SymKey *prf_plus; chunk_t seed_data = clone_hunk_hunk(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, logger); free_chunk_content(&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, struct logger *logger) { if (required_bytes == 0) { /* * For instance esp=null-none. Caller should * interpret NULL to mean empty (NSS doesn't create * zero length keys). */ ldbg(logger, "no CHILD SA KEMAT is required"); return NULL; } chunk_t seed_data; PK11SymKey *prf_plus; seed_data = clone_hunk_hunk(Ni, Nr, "seed_data = Ni || Nr"); prf_plus = prfplus_key_data("keymat", prf_desc, SK_d, new_dh_secret, seed_data, required_bytes, logger); free_chunk_content(&seed_data); return prf_plus; } static struct crypt_mac psk_auth(const struct prf_desc *prf_desc, shunk_t pss, chunk_t first_packet, chunk_t nonce, const struct crypt_mac *id_hash, chunk_t intermediate_packet, struct logger *logger) { 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, logger); if (pss_key == NULL) { if (libreswan_fipsmode()) { llog_passert(logger, HERE, "FIPS: failure creating %s PRF context for digesting PSK", prf_desc->common.fqn); } llog_pexpect(logger, HERE, "failure creating %s PRF context for digesting PSK", prf_desc->common.fqn); 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, logger); 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, logger); /* * 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); crypt_prf_update_hunk(prf,"IntAuth", intermediate_packet); 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-4.14/lib/libswan/ike_alg_prf_mac_hmac_ops.c000066400000000000000000000141731457372064200227540ustar00rootroot00000000000000/* * 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; struct logger *logger; }; 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 logger *logger) { struct prf_context prf = { .name = name, .desc = prf_desc, .logger = logger, }; return clone_thing(prf, name); } 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 logger *logger) { struct prf_context *prf = prf_init(prf_desc, name, logger); /* XXX: use an untyped key */ prf->key = symkey_from_bytes(name, key, sizeof_key, logger); 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 logger *logger) { struct prf_context *prf = prf_init(prf_desc, name, logger); 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, prf->logger); 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("trimmed key", &prf->key, z, prf->desc->hasher->hash_block_size - sizeof_symkey(prf->key), prf->logger); } 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, prf->logger); } /* * 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, prf->logger); } 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, prf->logger); } /* * 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, prf->logger); 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, prf->logger); append_symkey_symkey(&outer, hashed_inner, prf->logger); 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, (*prfp)->logger); release_symkey((*prfp)->name, "outer", &outer); if (DBGP(DBG_CRYPT)) { DBG_symkey((*prfp)->logger, " ", " 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, (*prfp)->logger); 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, struct logger *logger) { const struct ike_alg *alg = &prf->common; pexpect_ike_alg(logger, 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-4.14/lib/libswan/ike_alg_prf_mac_nss_ops.c000066400000000000000000000124471457372064200226510ustar00rootroot00000000000000/* * 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; struct logger *logger; }; /* * 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, struct logger *logger) { 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) { pexpect_nss_error(logger, HERE, "%s create %s context from key %s(%p) failed ", name, prf_desc->common.fqn, key_name, key); return NULL; } DBGF(DBG_CRYPT, "%s prf: created %s context %p from %s-key@%p", name, prf_desc->common.fqn, context, key_name, key); SECStatus rc = PK11_DigestBegin(context); if (rc) { pexpect_nss_error(logger, HERE, "%s digest begin failed for %s (%x)\n", name, prf_desc->common.fqn, 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.fqn, context, key_name, key); struct prf_context prf = { .name = name, .desc = prf_desc, .context = context, .logger = logger, }; return clone_thing(prf, name); } static struct prf_context *init_symkey(const struct prf_desc *prf_desc, const char *name, const char *key_name, PK11SymKey *key, struct logger *logger) { /* * 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, logger); struct prf_context *prf = init(prf_desc, name, key_name, clone, logger); 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, struct logger *logger) { /* * 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, logger); struct prf_context *prf = init(prf_desc, name, key_name, clone, logger); 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, prf->logger); SECStatus rc = PK11_DigestOp(prf->context, chunk.ptr, chunk.len); free_chunk_content(&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, (*prf)->logger); pfree(bytes); pfree(*prf); *prf = NULL; return final; } static void nss_prf_check(const struct prf_desc *prf, struct logger *logger) { const struct ike_alg *alg = &prf->common; pexpect_ike_alg(logger, 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-4.14/lib/libswan/ike_alg_prf_mac_xcbc_ops.c000066400000000000000000000225561457372064200227670ustar00rootroot00000000000000/* * 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; struct logger *logger; }; static void encrypt(const char *name, chunk_t out, chunk_t in, const struct prf_desc *prf, PK11SymKey *key, struct logger *logger) { 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) { passert_nss_error(logger, HERE, "encryption %s failed: ", name); } } static chunk_t derive_ki(const struct prf_desc *prf, PK11SymKey *key, int ki, struct logger *logger) { 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, logger); free_chunk_content(&in); return out; } static chunk_t xcbc_mac(const struct prf_desc *prf, PK11SymKey *key, chunk_t bytes, struct logger *logger) { if (DBGP(DBG_CRYPT)) { DBG_dump_hunk("XCBC: data", bytes); chunk_t k = chunk_from_symkey("K", key, logger); DBG_dump_hunk("XCBC: K:", k); free_chunk_content(&k); } chunk_t k1t = derive_ki(prf, key, 1, logger); if (DBGP(DBG_CRYPT)) { DBG_dump_hunk("XCBC: K1", k1t); } PK11SymKey *k1 = prf_key_from_hunk("k1", prf, k1t, logger); free_chunk_content(&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 = chunk2(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, logger); 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, logger); 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); } free_chunk_content(&k2); } else { chunk_t k3 = derive_ki(prf, key, 3, logger); 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); } free_chunk_content(&k3); } encrypt("K1(M[n]^E[n-1]^K2)", e, t, prf, k1, logger); if (DBGP(DBG_CRYPT)) { DBG_dump_hunk("XCBC: MAC", e); } release_symkey("xcbc", "k1", &k1); free_chunk_content(&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, struct logger *logger) { /* * 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, logger); key = prf_key_from_symkey_bytes(name, prf_desc, 0, prf_desc->prf_key_size, local_draft_key, HERE, logger); /* free all in reverse order */ release_symkey(name, "local_draft_key", &local_draft_key); free_chunk_content(&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, logger); chunk_t draft_chunk = chunk_from_symkey("draft_chunk", draft_key, logger); chunk_t key_chunk = xcbc_mac(prf_desc, zero_key, draft_chunk, logger); key = prf_key_from_hunk(key_name, prf_desc, key_chunk, logger); /* free all in reverse order */ free_chunk_content(&key_chunk); free_chunk_content(&draft_chunk); release_symkey(name, "zero_key", &zero_key); free_chunk_content(&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, logger); } struct prf_context prf = { .key = key, .name = name, .desc = prf_desc, .logger = logger, }; return clone_thing(prf, name); } 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, struct logger *logger) { /* * 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, logger); struct prf_context *context = nss_xcbc_init_symkey(prf_desc, name, key_name, clone, logger); 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) { chunk_t symkey_chunk = chunk_from_symkey(symkey_name, symkey, prf->logger); append_chunk_hunk(symkey_name, &prf->bytes, symkey_chunk); free_chunk_content(&symkey_chunk); } 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, (*prf)->logger); memcpy(bytes, mac.ptr, sizeof_bytes); free_chunk_content(&mac); free_chunk_content(&(*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, (*prf)->logger); PK11SymKey *key = symkey_from_hunk("xcbc", mac, (*prf)->logger); free_chunk_content(&mac); free_chunk_content(&(*prf)->bytes); release_symkey((*prf)->name, "key", &(*prf)->key); pfree(*prf); return key; } static void nss_xcbc_check(const struct prf_desc *prf, struct logger *logger) { const struct ike_alg *alg = &prf->common; pexpect_ike_alg(logger, 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-4.14/lib/libswan/ike_alg_prf_test_vectors.c000066400000000000000000000270661457372064200230740ustar00rootroot00000000000000/* * Copyright (C) 2014-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 "lswalloc.h" #include "ike_alg.h" #include "ike_alg_prf.h" #include "test_buffer.h" #include "ike_alg_test_prf.h" #include "lswfips.h" #include "pk11pub.h" #include "crypt_prf.h" #include "crypt_symkey.h" #include "ikev2_prf.h" #include "lswlog.h" /* * Ref: https://tools.ietf.org/html/rfc4435: Test Vectors */ const struct prf_test_vector aes_xcbc_prf_tests[] = { /* from RFC 3566 */ { .description = "RFC 3566 Test Case 1: AES-XCBC-MAC-96 with 0-byte input", .key = "0x000102030405060708090a0b0c0d0e0f", .key_size = 16, .message = "", .prf_output = "0x75f0251d528ac01c4573dfd584d79f29", /* AES-XCBC-MAC-96: 75f0251d528ac01c4573dfd5 */ }, { .description = "RFC 3566 Test Case 2: AES-XCBC-MAC-96 with 3-byte input", .key = "0x000102030405060708090a0b0c0d0e0f", .key_size = 16, .message = "0x000102", .prf_output = "0x5b376580ae2f19afe7219ceef172756f", /* AES-XCBC-MAC-96: 5b376580ae2f19afe7219cee */ }, { .description = "RFC 3566 Test Case 3: AES-XCBC-MAC-96 with 16-byte input", .key = "0x000102030405060708090a0b0c0d0e0f", .key_size = 16, .message = "0x000102030405060708090a0b0c0d0e0f", .prf_output = "0xd2a246fa349b68a79998a4394ff7a263", /* AES-XCBC-MAC-96: d2a246fa349b68a79998a439 */ }, { .description = "RFC 3566 Test Case 4: AES-XCBC-MAC-96 with 20-byte input", .key = "0x000102030405060708090a0b0c0d0e0f", .key_size = 16, .message = "0x000102030405060708090a0b0c0d0e0f10111213", .prf_output = "0x47f51b4564966215b8985c63055ed308", /* AES-XCBC-MAC-96: 47f51b4564966215b8985c63 */ }, { .description = "RFC 3566 Test Case 5: AES-XCBC-MAC-96 with 32-byte input", .key = "0x000102030405060708090a0b0c0d0e0f", .key_size = 16, .message = ("0x000102030405060708090a0b0c0d0e0f10111213141516171819" "1a1b1c1d1e1f"), .prf_output = "0xf54f0ec8d2b9f3d36807734bd5283fd4", /* AES-XCBC-MAC-96: f54f0ec8d2b9f3d36807734b */ }, { .description = "RFC 3566 Test Case 6: AES-XCBC-MAC-96 with 34-byte input", .key = "0x000102030405060708090a0b0c0d0e0f", .key_size = 16, .message = ("0x000102030405060708090a0b0c0d0e0f10111213141516171819" "1a1b1c1d1e1f2021"), .prf_output = "0xbecbb3bccdb518a30677d5481fb6b4d8", /* AES-XCBC-MAC-96: becbb3bccdb518a30677d548 */ }, { .description = "RFC 3566 Test Case 7: AES-XCBC-MAC-96 with 1000-byte input", .key = "0x000102030405060708090a0b0c0d0e0f", .key_size = 16, /* .message = "0x00000000000000000000 ... 00000000000000000000 [1000 bytes]", */ .message_size = 1000, .prf_output = "0xf0dafee895db30253761103b5d84528f", /* AES-XCBC-MAC-96: f0dafee895db30253761103b */ }, /* from RFC 4434 */ { .description = "RFC 4434 Test Case AES-XCBC-PRF-128 with 20-byte input (key length 16)", .key = "0x000102030405060708090a0b0c0d0e0f", .key_size = 16, .message = "0x000102030405060708090a0b0c0d0e0f10111213", .prf_output = "0x47f51b4564966215b8985c63055ed308", }, { .description = "RFC 4434 Test Case AES-XCBC-PRF-128 with 20-byte input (key length 10)", .key = "0x00010203040506070809", .key_size = 10, .message = "0x000102030405060708090a0b0c0d0e0f10111213", .prf_output = "0x0fa087af7d866e7653434e602fdde835", }, { .description = "RFC 4434 Test Case AES-XCBC-PRF-128 with 20-byte input (key length 18)", .key = "0x000102030405060708090a0b0c0d0e0fedcb", .key_size = 18, .message = "0x000102030405060708090a0b0c0d0e0f10111213", .prf_output = "0x8cd3c93ae598a9803006ffb67c40e9e4", }, { .description = NULL, } }; const struct prf_test_vector hmac_md5_prf_tests[] = { { .description = "RFC 2104: MD5_HMAC test 1", .key = "0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", .key_size = 16, /* bytes */ .message = "Hi There", /* data_len = 8 bytes */ .prf_output = "0x9294727a3638bb1c13f48ef8158bfc9d", }, { .description = "RFC 2104: MD5_HMAC test 2", .key = "Jefe", .key_size = 4, .message = "what do ya want for nothing?", /* data_len = 28 bytes */ .prf_output = "0x750c783e6ab0b503eaa86e310a5db738", }, { .description = "RFC 2104: MD5_HMAC test 3", .key = "0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", .key_size = 16, /* bytes */ .message = ("0xDDDDDDDDDDDDDDDDDDDD" "DDDDDDDDDDDDDDDDDDDD" "DDDDDDDDDDDDDDDDDDDD" "DDDDDDDDDDDDDDDDDDDD" "DDDDDDDDDDDDDDDDDDDD"), /* data_len = 50 bytes */ .prf_output = "0x56be34521d144c88dbb8c733f0e8b3f6", }, { .description = NULL, }, }; static bool test_prf_vector(const struct prf_desc *prf, const struct prf_test_vector *test, struct logger *logger) { chunk_t chunk_key = decode_to_chunk(__func__, test->key); passert(chunk_key.len == test->key_size); chunk_t chunk_message = (test->message != NULL) ? decode_to_chunk(__func__, test->message) : alloc_chunk(test->message_size, __func__); chunk_t prf_output = decode_to_chunk(__func__, test->prf_output); bool ok = true; /* chunk interface */ struct crypt_prf *chunk_prf = crypt_prf_init_hunk("PRF chunk interface", prf, "key", chunk_key, logger); crypt_prf_update_hunk(chunk_prf, "message", chunk_message); struct crypt_mac chunk_output = crypt_prf_final_mac(&chunk_prf, NULL); if (DBGP(DBG_CRYPT)) { DBG_dump_hunk("chunk output", chunk_output); } if (!verify_hunk(test->description, prf_output, chunk_output)) { ok = false; } /* symkey interface */ PK11SymKey *symkey_key = symkey_from_hunk("key symkey", chunk_key, logger); struct crypt_prf *symkey_prf = crypt_prf_init_symkey("PRF symkey interface", prf, "key symkey", symkey_key, logger); PK11SymKey *symkey_message = symkey_from_hunk("message symkey", chunk_message, logger); crypt_prf_update_symkey(symkey_prf, "symkey message", symkey_message); PK11SymKey *symkey_output = crypt_prf_final_symkey(&symkey_prf); if (DBGP(DBG_CRYPT)) { DBG_symkey(logger, "output", "symkey", symkey_output); } if (!verify_symkey(test->description, prf_output, symkey_output, logger)) { ok = false; } DBGF(DBG_CRYPT, "%s: %s %s", __func__, test->description, ok ? "passed" : "failed"); free_chunk_content(&chunk_message); free_chunk_content(&chunk_key); release_symkey(__func__, "message", &symkey_message); release_symkey(__func__, "key", &symkey_key); release_symkey(__func__, "output", &symkey_output); free_chunk_content(&prf_output); return ok; } bool test_prf_vectors(const struct prf_desc *desc, const struct prf_test_vector *tests, struct logger *logger) { bool ok = true; for (const struct prf_test_vector *test = tests; test->description != NULL; test++) { llog(RC_LOG, logger, " %s", test->description); if (!test_prf_vector(desc, test, logger)) { ok = false; } } return ok; } const struct kdf_test_vector hmac_sha1_kdf_tests[] = { { .description = "CAVP: IKEv2 key derivation with HMAC-SHA1", .ni = "0x32b50d5f4a3763f3", .ni_size = 8, .nr = "0x9206a04b26564cb1", .nr_size = 8, .gir = ("0x4b2c1f971981a8ad8d0abeafabf38cf7" "5fc8349c148142465ed9c8b516b8be52"), .gir_new = ("0x863f3c9d06efd39d2b907b97f8699e5d" "d5251ef64a2a176f36ee40c87d4f9330"), .gir_size = 32, .spii = "0x34c9e7c188868785", .spir = "0x3ff77d760d2b2199", .skeyseed = "0xa9a7b222b59f8f48645f28a1db5b5f5d7479cba7", .skeyseed_rekey = "0x63e81194946ebd05df7df5ebf5d8750056bf1f1d", .dkm = ("0xa14293677cc80ff8f9cc0eee30d895da" "9d8f405666e30ef0dfcb63c634a46002" "a2a63080e514a062768b76606f9fa5e9" "92204fc5a670bde3f10d6b027113936a" "5c55b648a194ae587b0088d52204b702" "c979fa280870d2ed41efa9c549fd1119" "8af1670b143d384bd275c5f594cf266b" "05ebadca855e4249520a441a81157435" "a7a56cc4"), .dkm_size = 132, }, { .description = NULL, } }; static bool test_kdf_vector(const struct prf_desc *prf, const struct kdf_test_vector *test, struct logger *logger) { chunk_t chunk_ni = decode_to_chunk(__func__, test->ni); passert(chunk_ni.len == test->ni_size); chunk_t chunk_nr = decode_to_chunk(__func__, test->nr); passert(chunk_nr.len == test->nr_size); chunk_t chunk_spii = decode_to_chunk(__func__, test->spii); chunk_t chunk_spir = decode_to_chunk(__func__, test->spir); chunk_t chunk_gir = decode_to_chunk(__func__, test->gir); passert(chunk_gir.len == test->gir_size); chunk_t chunk_gir_new = decode_to_chunk(__func__, test->gir_new); passert(chunk_gir_new.len == test->gir_size); chunk_t chunk_skeyseed = decode_to_chunk(__func__, test->skeyseed); chunk_t chunk_skeyseed_rekey = decode_to_chunk(__func__, test->skeyseed_rekey); chunk_t chunk_dkm = decode_to_chunk(__func__, test->dkm); passert(chunk_dkm.len == test->dkm_size); bool ok = true; /* SKEYSEED = prf(Ni | Nr, g^ir) */ PK11SymKey *gir = symkey_from_hunk("gir symkey", chunk_gir, logger); PK11SymKey *skeyseed = ikev2_ike_sa_skeyseed(prf, chunk_ni, chunk_nr, gir, logger); if (!verify_symkey(test->description, chunk_skeyseed, skeyseed, logger)) { ok = false; } /* prf+ (SKEYSEED, Ni | Nr | SPIi | SPIr) */ ike_spis_t spi_ir; passert(sizeof(spi_ir.initiator.bytes) == chunk_spii.len); memcpy(spi_ir.initiator.bytes, chunk_spii.ptr, chunk_spii.len); passert(sizeof(spi_ir.responder.bytes) == chunk_spir.len); memcpy(spi_ir.responder.bytes, chunk_spir.ptr, chunk_spir.len); PK11SymKey *dkm = ikev2_ike_sa_keymat(prf, skeyseed, chunk_ni, chunk_nr, &spi_ir, test->dkm_size, logger); if (!verify_symkey(test->description, chunk_dkm, dkm, logger)) { ok = false; } /* SKEYSEED = prf(SK_d (old), g^ir (new) | Ni | Nr) */ PK11SymKey *skd = key_from_symkey_bytes("SK_d", dkm, 0, prf->prf_key_size, HERE, logger); PK11SymKey *gir_new = symkey_from_hunk("gir_new symkey", chunk_gir_new, logger); PK11SymKey *skeyseed_rekey = ikev2_ike_sa_rekey_skeyseed(prf, skd, gir_new, chunk_ni, chunk_nr, logger); if (!verify_symkey(test->description, chunk_skeyseed_rekey, skeyseed_rekey, logger)) { ok = false; } DBGF(DBG_CRYPT, "%s: %s %s", __func__, test->description, ok ? "passed" : "failed"); release_symkey(__func__, "gir", &gir); release_symkey(__func__, "gir_new", &gir_new); release_symkey(__func__, "skeyseed", &skeyseed); release_symkey(__func__, "dkm", &dkm); release_symkey(__func__, "skd", &skd); release_symkey(__func__, "skeyseed_rekey", &skeyseed_rekey); free_chunk_content(&chunk_ni); free_chunk_content(&chunk_nr); free_chunk_content(&chunk_gir); free_chunk_content(&chunk_gir_new); free_chunk_content(&chunk_spii); free_chunk_content(&chunk_spir); free_chunk_content(&chunk_skeyseed); free_chunk_content(&chunk_skeyseed_rekey); free_chunk_content(&chunk_dkm); return ok; } bool test_kdf_vectors(const struct prf_desc *desc, const struct kdf_test_vector *tests, struct logger *logger) { bool ok = true; for (const struct kdf_test_vector *test = tests; test->description != NULL; test++) { llog(RC_LOG, logger, " %s", test->description); if (!test_kdf_vector(desc, test, logger)) { ok = false; } } return ok; } libreswan-4.14/lib/libswan/ike_alg_sha1.c000066400000000000000000000054271457372064200203320ustar00rootroot00000000000000/* 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_prf_mac_ops.h" #include "ike_alg_prf_ikev1_ops.h" #include "ike_alg_prf_ikev2_ops.h" #include "lsw-pfkeyv2.h" /* for SADB_*ALG_* */ const struct prf_desc ike_alg_prf_sha1 = { .common = { .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.approved = 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_KDF .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 = { .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_INTEG_HMAC_SHA1_96, #ifdef SADB_AALG_SHA1HMAC [SADB_ALG_ID] = SADB_AALG_SHA1HMAC, #endif }, .fips.approved = 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, .integ_netlink_xfrm_name = "sha1", .integ_tcpdump_name = "sha1", .integ_ike_audit_name = "sha1", .integ_kernel_audit_name = "HMAC_SHA1", }; libreswan-4.14/lib/libswan/ike_alg_sha2.c000066400000000000000000000234511457372064200203300ustar00rootroot00000000000000/* * 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 #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 "lsw-pfkeyv2.h" /* for SADB_*ALG_* */ /* SHA-2 256 */ const struct prf_desc ike_alg_prf_sha2_256 = { .common = { .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.approved = 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_KDF .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 = { .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_INTEG_HMAC_SHA2_256_128, #ifdef SADB_X_AALG_SHA2_256HMAC [SADB_ALG_ID] = SADB_X_AALG_SHA2_256HMAC, #endif #ifdef SADB_X_AALG_SHA2_256 [SADB_ALG_ID] = SADB_X_AALG_SHA2_256, #endif }, .fips.approved = 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, .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 = { .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, #ifdef SADB_X_AALG_SHA2_256HMAC_TRUNCBUG [SADB_ALG_ID] = SADB_X_AALG_SHA2_256HMAC_TRUNCBUG, #endif }, .fips.approved = false, }, .integ_keymat_size = SHA2_256_DIGEST_SIZE, .integ_output_size = BYTES_FOR_BITS(96), .integ_ikev1_ah_transform = AH_SHA2_256_TRUNCBUG, .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", }; /* SHA-2 384 */ static const uint8_t asn1_pkcs1_1_5_rsa_sha2_384_blob[1+ASN1_PKCS1_1_5_RSA_SIZE] = { ASN1_PKCS1_1_5_RSA_SIZE, ASN1_PKCS1_1_5_RSA_SHA2_384_BLOB }; static const uint8_t asn1_ecdsa_sha2_384_blob[1+ASN1_ECDSA_SHA2_SIZE] = { ASN1_ECDSA_SHA2_SIZE, ASN1_ECDSA_SHA2_384_BLOB }; static const uint8_t asn1_rsassa_pss_sha2_384_blob[1+ASN1_RSASSA_PSS_SHA2_SIZE] = { ASN1_RSASSA_PSS_SHA2_SIZE, ASN1_RSASSA_PSS_SHA2_384_BLOB }; const CK_RSA_PKCS_PSS_PARAMS rsa_pss_sha2_384 = { .hashAlg = CKM_SHA384, .mgf = CKG_MGF1_SHA384, .sLen = SHA2_384_DIGEST_SIZE, }; const struct hash_desc ike_alg_hash_sha2_384 = { .common = { .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] = IKEv2_HASH_ALGORITHM_SHA2_384, }, .fips.approved = true, }, .nss = { .oid_tag = SEC_OID_SHA384, .derivation_mechanism = CKM_SHA384_KEY_DERIVATION, .rsa_pkcs_pss_params = &rsa_pss_sha2_384, .pkcs1_1_5_rsa_oid_tag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION, }, .hash_digest_size = SHA2_384_DIGEST_SIZE, .hash_block_size = 128, /* from RFC 4868 */ .hash_ops = &ike_alg_hash_nss_ops, .digital_signature_blob = { [DIGITAL_SIGNATURE_PKCS1_1_5_RSA_BLOB] = THING_AS_HUNK(asn1_pkcs1_1_5_rsa_sha2_384_blob), [DIGITAL_SIGNATURE_ECDSA_BLOB] = THING_AS_HUNK(asn1_ecdsa_sha2_384_blob), [DIGITAL_SIGNATURE_RSASSA_PSS_BLOB] = THING_AS_HUNK(asn1_rsassa_pss_sha2_384_blob), }, }; const struct prf_desc ike_alg_prf_sha2_384 = { .common = { .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.approved = 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_KDF .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 = { .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_INTEG_HMAC_SHA2_384_192, #ifdef SADB_X_AALG_SHA2_384HMAC [SADB_ALG_ID] = SADB_X_AALG_SHA2_384HMAC, #endif #ifdef SADB_X_AALG_SHA2_384 [SADB_ALG_ID] = SADB_X_AALG_SHA2_384, #endif }, .fips.approved = 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, .integ_netlink_xfrm_name = "hmac(sha384)", .integ_tcpdump_name = "sha384", .integ_ike_audit_name = "sha384", .integ_kernel_audit_name = "HMAC_SHA2_384", }; /* SHA-2 512 */ static const uint8_t asn1_pkcs1_1_5_rsa_sha2_512_blob[1+ASN1_PKCS1_1_5_RSA_SIZE] = { ASN1_PKCS1_1_5_RSA_SIZE, ASN1_PKCS1_1_5_RSA_SHA2_512_BLOB }; static const uint8_t asn1_ecdsa_sha2_512_blob[1+ASN1_ECDSA_SHA2_SIZE] = { ASN1_ECDSA_SHA2_SIZE, ASN1_ECDSA_SHA2_512_BLOB }; static const uint8_t asn1_rsassa_pss_sha2_512_blob[1+ASN1_RSASSA_PSS_SHA2_SIZE] = { ASN1_RSASSA_PSS_SHA2_SIZE, ASN1_RSASSA_PSS_SHA2_512_BLOB }; const CK_RSA_PKCS_PSS_PARAMS rsa_pss_sha2_512 = { .hashAlg = CKM_SHA512, .mgf = CKG_MGF1_SHA512, .sLen = SHA2_512_DIGEST_SIZE, }; const struct hash_desc ike_alg_hash_sha2_512 = { .common = { .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] = IKEv2_HASH_ALGORITHM_SHA2_512, }, .fips.approved = true, }, .nss = { .oid_tag = SEC_OID_SHA512, .derivation_mechanism = CKM_SHA512_KEY_DERIVATION, .rsa_pkcs_pss_params = &rsa_pss_sha2_512, .pkcs1_1_5_rsa_oid_tag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION, }, .hash_digest_size = SHA2_512_DIGEST_SIZE, .hash_block_size = 128, /* from RFC 4868 */ .hash_ops = &ike_alg_hash_nss_ops, .digital_signature_blob = { [DIGITAL_SIGNATURE_PKCS1_1_5_RSA_BLOB] = THING_AS_HUNK(asn1_pkcs1_1_5_rsa_sha2_512_blob), [DIGITAL_SIGNATURE_ECDSA_BLOB] = THING_AS_HUNK(asn1_ecdsa_sha2_512_blob), [DIGITAL_SIGNATURE_RSASSA_PSS_BLOB] = THING_AS_HUNK(asn1_rsassa_pss_sha2_512_blob), }, }; const struct prf_desc ike_alg_prf_sha2_512 = { .common = { .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.approved = 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_KDF .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 = { .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_INTEG_HMAC_SHA2_512_256, #ifdef SADB_X_AALG_SHA2_512HMAC [SADB_ALG_ID] = SADB_X_AALG_SHA2_512HMAC, #endif #ifdef SADB_X_AALG_SHA2_512 [SADB_ALG_ID] = SADB_X_AALG_SHA2_512, #endif }, .fips.approved = 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, .integ_netlink_xfrm_name = "hmac(sha512)", .integ_tcpdump_name = "sha512", .integ_ike_audit_name = "sha512", .integ_kernel_audit_name = "HMAC_SHA2_512", }; libreswan-4.14/lib/libswan/ike_alg_test.c000066400000000000000000000035131457372064200204470ustar00rootroot00000000000000/* 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)) { \ llog(RC_LOG, logger, \ "skipping tests for disabled %s algorithm", \ (ALG).common.fqn); \ } else { \ llog(RC_LOG, logger, \ "testing %s:", (ALG).common.fqn); \ passert(TESTER(&ALG, TESTS, logger)); \ } void test_ike_alg(struct logger *logger) { #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 #ifdef USE_SHA1 TEST(test_kdf_vectors, ike_alg_prf_sha1, hmac_sha1_kdf_tests); #endif } libreswan-4.14/lib/libswan/ike_info.c000066400000000000000000000125421457372064200176020ustar00rootroot00000000000000/* * 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, parser->policy->logger, 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, parser->policy->logger, 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, parser->policy->logger, 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, parser->policy->logger, 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_secp256r1.common, &ike_alg_dh_secp384r1.common, &ike_alg_dh_secp521r1.common, #ifdef USE_DH31 &ike_alg_dh_curve25519.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-4.14/lib/libswan/ikev1_prf.c000066400000000000000000000116541457372064200177100ustar00rootroot00000000000000/* * 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 "ikev1_prf.h" #include "ike_alg.h" #include "ike_alg_prf_ikev1_ops.h" #include "crypt_symkey.h" /* for DBG_symkey() */ /* * Compute: SKEYID = prf(Ni_b | Nr_b, g^xy) * * MUST BE THREAD-SAFE */ PK11SymKey *ikev1_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 */, struct logger *logger) { if (DBGP(DBG_CRYPT)) { ldbg(logger, "calling %s.%s():", prf_desc->prf_ikev1_ops->backend, __func__); } PK11SymKey *result = prf_desc->prf_ikev1_ops->signature_skeyid(prf_desc, Ni, Nr, dh_secret, logger); return result; } /* * Compute: SKEYID = prf(pre-shared-key, Ni_b | Nr_b) */ PK11SymKey *ikev1_pre_shared_key_skeyid(const struct prf_desc *prf_desc, chunk_t pre_shared_key, chunk_t Ni, chunk_t Nr, struct logger *logger) { if (DBGP(DBG_CRYPT)) { ldbg(logger, "calling %s.%s():", prf_desc->prf_ikev1_ops->backend, __func__); } PK11SymKey *result = prf_desc->prf_ikev1_ops->pre_shared_key_skeyid(prf_desc, pre_shared_key, Ni, Nr, logger); return result; } /* * SKEYID_d = prf(SKEYID, g^xy | CKY-I | CKY-R | 0) */ PK11SymKey *ikev1_skeyid_d(const struct prf_desc *prf_desc, PK11SymKey *skeyid, PK11SymKey *dh_secret, chunk_t cky_i, chunk_t cky_r, struct logger *logger) { if (DBGP(DBG_CRYPT)) { ldbg(logger, "calling %s.%s():", prf_desc->prf_ikev1_ops->backend, __func__); } PK11SymKey *result = prf_desc->prf_ikev1_ops->skeyid_d(prf_desc, skeyid, dh_secret, cky_i, cky_r, logger); return result; } /* * SKEYID_a = prf(SKEYID, SKEYID_d | g^xy | CKY-I | CKY-R | 1) */ PK11SymKey *ikev1_skeyid_a(const struct prf_desc *prf_desc, PK11SymKey *skeyid, PK11SymKey *skeyid_d, PK11SymKey *dh_secret, chunk_t cky_i, chunk_t cky_r, struct logger *logger) { if (DBGP(DBG_CRYPT)) { ldbg(logger, "calling %s.%s():", prf_desc->prf_ikev1_ops->backend, __func__); } PK11SymKey *result = prf_desc->prf_ikev1_ops->skeyid_a(prf_desc, skeyid, skeyid_d, dh_secret, cky_i, cky_r, logger); return result; } /* * SKEYID_e = prf(SKEYID, SKEYID_a | g^xy | CKY-I | CKY-R | 2) */ PK11SymKey *ikev1_skeyid_e(const struct prf_desc *prf_desc, PK11SymKey *skeyid, PK11SymKey *skeyid_a, PK11SymKey *dh_secret, chunk_t cky_i, chunk_t cky_r, struct logger *logger) { if (DBGP(DBG_CRYPT)) { ldbg(logger, "calling %s.%s():", prf_desc->prf_ikev1_ops->backend, __func__); } PK11SymKey *result = prf_desc->prf_ikev1_ops->skeyid_e(prf_desc, skeyid, skeyid_a, dh_secret, cky_i, cky_r, logger); return result; } PK11SymKey *ikev1_appendix_b_keymat_e(const struct prf_desc *prf_desc, const struct encrypt_desc *encrypter, PK11SymKey *skeyid_e, unsigned required_keymat, struct logger *logger) { if (DBGP(DBG_CRYPT)) { ldbg(logger, "calling %s.%s():", prf_desc->prf_ikev1_ops->backend, __func__); } PK11SymKey *result = prf_desc->prf_ikev1_ops->appendix_b_keymat_e(prf_desc, encrypter, skeyid_e, required_keymat, logger); return result; } chunk_t ikev1_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, struct logger *logger) { if (DBGP(DBG_CRYPT)) { DBG_log("calling %s.%s():", prf_desc->prf_ikev1_ops->backend, __func__); DBG_symkey(logger, __func__, "SKEYID_d:", SKEYID_d); DBG_symkey(logger, __func__, "g_xy:", g_xy); DBG_log("protocol: 0x%02"PRIx8, protocol); DBG_dump_hunk("SPI", SPI); DBG_dump_hunk("Ni_b", Ni_b); DBG_dump_hunk("Ni_b", Nr_b); DBG_log("required keymat: %u", required_keymat); } chunk_t result = prf_desc->prf_ikev1_ops->section_5_keymat(prf_desc, SKEYID_d, g_xy, protocol, SPI, Ni_b, Nr_b, required_keymat, logger); if (DBGP(DBG_CRYPT)) { DBG_log("%s.%s() returns:", prf_desc->prf_ikev1_ops->backend, __func__); DBG_dump_hunk(NULL, result); } return result; } libreswan-4.14/lib/libswan/ikev2_prf.c000066400000000000000000000066211457372064200177070ustar00rootroot00000000000000/* * 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 * Copyright (C) 2020 Yulia Kuzovkova * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT 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 "ikev2_prf.h" #include "crypt_prf.h" #include "crypt_symkey.h" #include "lswfips.h" /* * IKEv2 - RFC4306 2.14 SKEYSEED - calculation. */ PK11SymKey *ikev2_prfplus(const struct prf_desc *prf_desc, PK11SymKey *key, PK11SymKey *seed, size_t required_keymat, struct logger *logger) { return prf_desc->prf_ikev2_ops->prfplus(prf_desc, key, seed, required_keymat, logger); } /* * SKEYSEED = prf(Ni | Nr, g^ir) * * */ PK11SymKey *ikev2_ike_sa_skeyseed(const struct prf_desc *prf_desc, const chunk_t Ni, const chunk_t Nr, PK11SymKey *dh_secret, struct logger *logger) { return prf_desc->prf_ikev2_ops->ike_sa_skeyseed(prf_desc, Ni, Nr, dh_secret, logger); } /* * SKEYSEED = prf(SK_d (old), g^ir (new) | Ni | Nr) */ PK11SymKey *ikev2_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, struct logger *logger) { return prf_desc->prf_ikev2_ops->ike_sa_rekey_skeyseed(prf_desc, SK_d_old, new_dh_secret, Ni, Nr, logger); } /* * Compute: prf+ (SKEYSEED, Ni | Nr | SPIi | SPIr) */ PK11SymKey *ikev2_ike_sa_keymat(const struct prf_desc *prf_desc, PK11SymKey *skeyseed, const chunk_t Ni, const chunk_t Nr, const ike_spis_t *SPIir, size_t required_bytes, struct logger *logger) { return prf_desc->prf_ikev2_ops->ike_sa_keymat(prf_desc, skeyseed, Ni, Nr, THING_AS_SHUNK(SPIir->initiator), THING_AS_SHUNK(SPIir->responder), required_bytes, logger); } /* * Compute: prf+(SK_d, [ g^ir (new) | ] Ni | Nr) */ PK11SymKey *ikev2_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, struct logger *logger) { return prf_desc->prf_ikev2_ops->child_sa_keymat(prf_desc, SK_d, new_dh_secret, Ni, Nr, required_bytes, logger); } struct crypt_mac ikev2_psk_auth(const struct prf_desc *prf_desc, shunk_t pss, chunk_t first_packet, chunk_t nonce, const struct crypt_mac *id_hash, chunk_t intermediate_packet, struct logger *logger) { return prf_desc->prf_ikev2_ops->psk_auth(prf_desc, pss, first_packet, nonce, id_hash, intermediate_packet, logger); } libreswan-4.14/lib/libswan/impair.c000066400000000000000000000546031457372064200173040ustar00rootroot00000000000000/* 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" static const struct keyword impair_emit_value[] = { #define S(E, H) [IMPAIR_EMIT_##E] = { \ .name = "IMPAIR_EMIT_" #E, \ .sname = #E, \ .value = IMPAIR_EMIT_##E, \ .details = H, \ } S(OMIT, "do not emit content"), S(EMPTY, "emit zero length content"), S(DUPLICATE, "emit content twice"), #undef S }; static const struct keywords impair_emit_keywords = DIRECT_KEYWORDS("send impaired content", impair_emit_value); static const struct keyword impair_v1_exchange_value[] = { #define S(E, H) [IMPAIR_v1_##E##_EXCHANGE] = { \ .name = "IMPAIR_v1_" #E "_EXCHANGE", \ .sname = #E, \ .value = IMPAIR_v1_##E##_EXCHANGE, \ .details = H, \ } 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 impair_v1_exchange_keywords = DIRECT_KEYWORDS("impaire exchange content", impair_v1_exchange_value); /* transform */ static const struct keyword impair_v2_transform_value[] = { #define S(S, E, H) [IMPAIR_v2_TRANSFORM_##E] = { .name = "IMPAIR_v2_TRANSFORM_"#E, .sname = S, .value = IMPAIR_v2_TRANSFORM_##E, .details = H, } S("no", NO, "do not modify transform"), S("allow-none", ALLOW_NONE, "allow TRANSFORM=NONE when part of a proposal"), S("drop-none", DROP_NONE, "drop TRANSFORM=NONE even when part of a proposal"), S("omit", OMIT, "omit transform from proposal"), #undef S }; static const struct keywords impair_v2_transform_keywords = DIRECT_KEYWORDS("transform impaired content", impair_v2_transform_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_keywords; const struct enum_names *how_enum_names; const char *unsigned_help; void *value; /* size_t offsetof_value; */ size_t sizeof_value; enum impair_action action; unsigned param; }; struct impairment impairments[] = { { .what = NULL, }, #define A(WHAT, ACTION, PARAM, HELP, UNSIGNED_HELP, ...) { .what = WHAT, .action = CALL_##ACTION, .param = PARAM, .help = HELP, .unsigned_help = UNSIGNED_HELP, ##__VA_ARGS__, } #define V(WHAT, VALUE, HELP, ...) { .what = WHAT, .action = CALL_IMPAIR_UPDATE, .value = &impair.VALUE, .help = HELP, .sizeof_value = sizeof(impair.VALUE), ##__VA_ARGS__, } V("allow-dns-insecure", allow_dns_insecure, "allow IPSECKEY lookups without DNSSEC protection"), V("allow-null-none", allow_null_none, "cause pluto to allow esp=null-none and ah=none for testing"), V("bad-ikev2-auth-xchg", bad_ike_auth_xchg, "causes pluto to send IKE_AUTH replies with wrong exchange type"), V("bust-mi2", bust_mi2, "make MI2 really large"), V("bust-mr2", bust_mr2, "make MR2 really large"), V("child-key-length-attribute", child_key_length_attribute, "corrupt the outgoing CHILD proposal's key length attribute", .how_keywords = &impair_emit_keywords, .unsigned_help = "emit as the key length"), V("corrupt-encrypted", corrupt_encrypted, "corrupts the encrypted packet so that the decryption fails"), V("delete-on-retransmit", delete_on_retransmit, "causes pluto to fail on the first retransmit"), V("drop-i2", drop_i2, "drop second initiator packet"), V("drop-xauth-r0", drop_xauth_r0, "causes pluto to drop an XAUTH user/passwd request on IKE initiator"), V("emitting", emitting, "disable correctness-checks when emitting a payload (let anything out)"), V("force-fips", force_fips, "causes pluto to believe we are in fips mode, NSS needs its own hack"), V("ike-initiator-spi", ike_initiator_spi, "corrupt the IKE initiator SPI", .unsigned_help = "set SPI to "), V("ike-key-length-attribute", ike_key_length_attribute, "corrupt the outgoing IKE proposal's key length attribute", .how_keywords = &impair_emit_keywords, .unsigned_help = "emit as the key length"), V("ike-responder-spi", ike_responder_spi, "corrupt the IKE responder SPI", .unsigned_help = "set SPI to "), V("ikev1-del-with-notify", ikev1_del_with_notify, "causes pluto to send IKE Delete with additional bogus Notify payload"), V("v2-proposal-integ", v2_proposal_integ, "integrity in proposals", .how_keywords = &impair_v2_transform_keywords), V("v2-proposal-dh", v2_proposal_dh, "dh in proposals", .how_keywords = &impair_v2_transform_keywords), V("ikev2-add-ike-transform", ikev2_add_ike_transform, "add an extra (possibly bogus) transform to the first IKE proposal", .unsigned_help = "transform type+id encoded as TYPE<<16|ID"), V("ikev2-add-child-transform", ikev2_add_child_transform, "add an extra (possibly bogus) transform to the first CHILD proposal", .unsigned_help = "transform type+id encoded as TYPE<<16|ID"), V("jacob-two-two", jacob_two_two, "cause pluto to send all messages twice."), V("ke-payload", ke_payload, "corrupt the outgoing KE payload", .how_keywords = &impair_emit_keywords, .unsigned_help = "emit the KE payload filled with bytes"), V("log-rate-limit", log_rate_limit, "set the per-hour(?) cap on rate-limited log messages"), V("major-version-bump", major_version_bump, "cause pluto to send an IKE major version that's higher then we support."), V("minor-version-bump", minor_version_bump, "cause pluto to send an IKE minor version that's higher then we support."), V("childless-ikev2-supported", childless_ikev2_supported, "causes pluto to omit/ignore the CHILDLESS_IKEV2_SUPPORTED notify in the IKE_SA_INIT exchange"), V("ignore-v2n-signature-hash-algorithms", ignore_v2N_SIGNATURE_HASH_ALGORITHMS, "causes pluto to ignore the notification SIGNATURE_HASH_ALGORITHMS in the IKE_SA_INIT exchange"), V("omit-v2n-signature-hash-algorithms", omit_v2N_SIGNATURE_HASH_ALGORITHMS, "causes pluto to omit the notification SIGNATURE_HASH_ALGORITHMS in the IKE_SA_INIT exchange"), V("proposal-parser", proposal_parser, "impair algorithm parser - what you see is what you get"), V("rekey-initiate-supernet", rekey_initiate_supernet, "impair IPsec SA rekey initiator TSi and TSR to 0/0 ::0, emulate Windows client"), V("rekey-initiate-subnet", rekey_initiate_subnet, "impair IPsec SA rekey initiator TSi and TSR to X/32 or X/128"), V("rekey-respond-supernet", rekey_respond_supernet, "impair IPsec SA rekey responder TSi and TSR to 0/0 ::0"), V("rekey-respond-subnet", rekey_respond_subnet, "impair IPsec SA rekey responder TSi and TSR to X/32 X/128"), V("replay-backward", replay_backward, "replay all earlier packets new-to-old"), V("replay-duplicates", replay_duplicates, "replay duplicates of each incoming packet"), V("replay-encrypted", replay_encrypted, "replay encrypted packets"), V("replay-forward", replay_forward, "replay all earlier packets old-to-new"), V("revival", revival, "disable code that revives a connection that is supposed to stay up"), V("sa-creation", sa_creation, "fail all SA creation"), V("send-bogus-dcookie", send_bogus_dcookie, "causes pluto to send a a bogus IKEv2 DCOOKIE"), V("send-bogus-isakmp-flag", send_bogus_isakmp_flag, "causes pluto to set a RESERVED ISAKMP flag to test ignoring/zeroing it"), V("send-bogus-payload-flag", send_bogus_payload_flag, "causes pluto to set a RESERVED PAYLOAD flag to test ignoring/zeroing it"), V("send-key-size-check", send_key_size_check, "causes pluto to omit checking configured ESP key sizes for testing"), V("send-no-delete", send_no_delete, "causes pluto to omit sending Notify/Delete messages"), V("send-no-ikev2-auth", send_no_ikev2_auth, "causes pluto to omit sending an IKEv2 IKE_AUTH packet"), V("send-no-main-r2", send_no_main_r2, "causes pluto to omit sending an last Main Mode response packet"), V("send-no-xauth-r0", send_no_xauth_r0, "causes pluto to omit sending an XAUTH user/passwd request"), V("send-no-idr", send_no_idr, "causes pluto as initiator to omit sending an IDr payload"), V("send-pkcs7-thingie", send_pkcs7_thingie, "send certificates as a PKCS7 thingie"), V("send-nonzero-reserved", send_nonzero_reserved, "send non-zero reserved fields in IKEv2 proposal fields"), V("send-nonzero-reserved-id", send_nonzero_reserved_id, "send non-zero reserved fields in IKEv2 ID payload that is part of the AUTH hash calculation"), V("suppress-retransmits", suppress_retransmits, "causes pluto to never send retransmits (wait the full timeout)"), V("timeout-on-retransmit", timeout_on_retransmit, "causes pluto to 'retry' (switch protocol) on the first retransmit"), V("event-check-crls", event_check_crls, "do not schedule the CRL check event"), V("v1-hash-check", v1_hash_check, "disable check of incoming IKEv1 hash payload"), V("v1-hash-exchange", v1_hash_exchange, "corrupt the HASH payload in the outgoing exchange", .how_keywords = &impair_v1_exchange_keywords), V("v1-hash-payload", v1_hash_payload, "corrupt the emitted HASH payload", .how_keywords = &impair_emit_keywords, .unsigned_help = "emit the hash payload filled with bytes"), V("tcp-use-blocking-write", tcp_use_blocking_write, "use a blocking write when sending TCP encapsulated IKE messages"), V("tcp-skip-setsockopt-espintcp", tcp_skip_setsockopt_espintcp, "skip the required setsockopt(\"espintcp\") call"), A("initiate-v2-liveness", INITIATE_v2_LIVENESS, 0, "initiate an IKEv2 liveness exchange", "IKE SA"), A("send-keepalive", SEND_KEEPALIVE, 0, "send a NAT keepalive packet", "SA"), A("drop-incoming", IMPAIR_DROP_INCOMING, 0, "drop the N'th incoming message", "message number"), A("drop-outgoing", IMPAIR_DROP_OUTGOING, 0, "drop the N'th outgoing message", "message number"), V("add-unknown-v2-payload-to", add_unknown_v2_payload_to, "impair the (unencrypted) part of the exchange", .how_enum_names = &ikev2_exchange_names), V("add-unknown-v2-payload-to-sk", add_unknown_v2_payload_to_sk, "impair the encrypted part of the exchange", .how_enum_names = &ikev2_exchange_names), V("unknown-v2-payload-critical", unknown_v2_payload_critical, "include the unknown payload in the encrypted SK payload"), V("ignore-soft-expire", ignore_soft_expire, "ignore kernel soft expire events"), V("ignore-hard-expire", ignore_hard_expire, "ignore kernel hard expire events"), V("force-v2-auth-method", force_v2_auth_method, "force the use of the specified IKEv2 AUTH method", .how_enum_names = &ikev2_auth_method_names), V("omit-v2-ike-auth-child", omit_v2_ike_auth_child, "omit, and don't expect, CHILD SA payloads in IKE_AUTH message"), V("ignore-v2-ike-auth-child", ignore_v2_ike_auth_child, "ignore, but do expect, CHILD SA payloads in the IKE_AUTH message"), A("trigger", GLOBAL_EVENT_HANDLER, 0, "trigger the global event", "EVENT", .how_enum_names = &global_timer_names), A("event-v2-rekey", STATE_EVENT_HANDLER, EVENT_v2_REKEY, "trigger the rekey event", "SA"), A("event-v2-reauth", STATE_EVENT_HANDLER, EVENT_v2_REAUTH, "trigger the reauthenticate event", "SA"), A("event-v2-liveness", STATE_EVENT_HANDLER, EVENT_v2_LIVENESS, "trigger the liveness event", "SA"), A("event-sa-replace", STATE_EVENT_HANDLER, EVENT_SA_REPLACE, "trigger the replace event", "SA"), V("v1_remote_quick_id", v1_remote_quick_id, "set the remote quick ID", .unsigned_help = "value to set quick id too"), V("v1_isakmp_delete_payload", v1_isakmp_delete_payload, "corrupt outgoing ISAKMP delete payload", .how_keywords = &impair_emit_keywords), V("v1_ipsec_delete_payload", v1_ipsec_delete_payload, "corrupt outgoing IPsec delete payload", .how_keywords = &impair_emit_keywords), #define U(VALUE, HELP, ...) \ { .what = #VALUE, .action = CALL_IMPAIR_UPDATE, .value = &impair.VALUE, .help = HELP, .sizeof_value = sizeof(impair.VALUE), .unsigned_help = "", ##__VA_ARGS__, } U(v2_delete_protoid, "corrupt the IKEv2 Delete protocol ID"), U(v2n_rekey_sa_protoid, "corrupt the IKEv2 REKEY CHILD notify protocol ID"), U(v2_proposal_protoid, "corrupt the IKEv2 proposal substructure protocol ID"), #undef U #undef V #undef A }; static void help(const char *prefix, const struct impairment *cr, FILE *file) { fprintf(file, "%s%s: %s\n", prefix, cr->what, cr->help); if (cr->how_keywords != NULL) { const struct keywords *kw = cr->how_keywords; /* skip 0, always no */ for (unsigned ki = 1; ki < kw->nr_values; ki++) { const struct keyword *kv = &kw->values[ki]; if (kv->details != NULL) { fprintf(file, "%s %s: %s\n", prefix, kv->sname, kv->details); } } } if (cr->how_enum_names != NULL) { bool first = true; for (long e = next_enum(cr->how_enum_names, -1); e >= 0; e = next_enum(cr->how_enum_names, e)) { if (first) { fprintf(file, "%s ", prefix); first = false; } else { fprintf(file, ", "); } const char *sname = enum_name_short(cr->how_enum_names, e); fprintf(file, "%s", sname); } fprintf(file, "\n"); } if (cr->unsigned_help != NULL) { fprintf(file, "%s %s: %s\n", prefix, "", cr->unsigned_help); } } static void help_impair(const char *prefix, FILE *file) { for (unsigned ci = 1; ci < elemsof(impairments); ci++) { const struct impairment *impairment = &impairments[ci]; help(prefix, impairment, file); } } /* * Return the long value in STRING, but with +ve values adjusted by * BIAS. If the operation fails, zero is returned - bias must be * non-zero. */ static unsigned parse_biased_unsigned(shunk_t string, const struct impairment *cr) { unsigned bias = cr->how_keywords != NULL ? cr->how_keywords->nr_values : 1; uintmax_t u; err_t err = shunk_to_uintmax(string, NULL, 0/*base*/, &u); /* * Since, after bias, value must be non-zero, this acts as an * error flag. */ if (err != NULL) { return 0; } if (u > UINTMAX_MAX - bias) { return 0; /* i.e., u+bias overflows */ } return u + bias; } #define IMPAIR_DISABLE (elemsof(impairments) + 0) #define IMPAIR_LIST (elemsof(impairments) + 1) enum impair_status parse_impair(const char *optarg, struct whack_impair *whack_impair, bool enable /* --impair ... vs --no-impair ...*/, struct logger *logger) { if (streq(optarg, "help")) { help_impair("", stdout); return IMPAIR_HELP; } if (enable && streq(optarg, "none")) { *whack_impair = (struct whack_impair) { .what = IMPAIR_DISABLE, .biased_value = 0, }; return IMPAIR_OK; } if (enable && streq(optarg, "list")) { *whack_impair = (struct whack_impair) { .what = IMPAIR_LIST, .biased_value = 0, }; return IMPAIR_OK; } /* Break OPTARG into WHAT[=BIASED_VALUE] */ 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. */ bool what_no = shunk_strcaseeat(&what, "no-"); unsigned ci = 1; const struct impairment *impairment = NULL; for (ci = 1/*skip 0*/; ci < elemsof(impairments); ci++) { if (hunk_strcaseeq(what, impairments[ci].what)) { impairment = &impairments[ci]; break; } } if (impairment == NULL) { llog(ERROR_STREAM, logger, "unrecognized impair option '"PRI_SHUNK"'\n", pri_shunk(what)); return IMPAIR_ERROR; } /* * no matter how negated, "help" always works */ if (hunk_strcaseeq(how, "help") || hunk_strcaseeq(how, "?")) { help("", impairment, stdout); return IMPAIR_HELP; } /* * Reject overly negative or conflicting combinations. For * instance: --no-impair no-foo:bar. */ if ((!enable + what_no + (how.ptr != NULL)) > 1) { llog(ERROR_STREAM, logger, "overly negative --%simpair %s", enable ? "" : "no-", optarg); return IMPAIR_ERROR; } /* * Always recognize "no". */ if (!enable || what_no || hunk_strcaseeq(how, "no")) { *whack_impair = (struct whack_impair) { .what = ci, .biased_value = 0, }; return IMPAIR_OK; } /* * For WHAT:HOW, lookup the keyword HOW. */ if (impairment->how_keywords != NULL) { /* try the keyword. */ const struct keyword *kw = keyword_by_sname(impairment->how_keywords, how); if (kw != NULL) { *whack_impair = (struct whack_impair) { .what = ci, .biased_value = kw->value, }; return IMPAIR_OK; } } else if (impairment->how_enum_names != NULL) { long e = enum_match(impairment->how_enum_names, how); if (e >= 0) { *whack_impair = (struct whack_impair) { .what = ci, .biased_value = e, }; return IMPAIR_OK; } } else { /* * Assume boolean - use "yes" and "no" as that is what * bool_str() prints. * * XXX: this can't use keywords as they won't * interpret "" as yes. */ if (hunk_strcaseeq(how, "no")) { /* --impair WHAT:no */ *whack_impair = (struct whack_impair) { .what = ci, .biased_value = false, }; return IMPAIR_OK; } if (how.len == 0 || hunk_strcaseeq(how, "yes")) { /* --impair WHAT:yes or --impair WHAT */ *whack_impair = (struct whack_impair) { .what = ci, .biased_value = true, }; return IMPAIR_OK; } } if (impairment->unsigned_help != NULL) { unsigned biased_value = parse_biased_unsigned(how, impairment); if (biased_value > 0) { *whack_impair = (struct whack_impair) { .what = ci, .biased_value = biased_value, }; return IMPAIR_OK; } } llog(ERROR_STREAM, logger, "ignoring impair option '"PRI_SHUNK"' with unrecognized parameter '"PRI_SHUNK"' (%s)", pri_shunk(what), pri_shunk(how), optarg); return IMPAIR_ERROR; } /* * Print something that can be fed back into --impair ARG. */ static uintmax_t value_of(const struct impairment *impairment) { switch (impairment->sizeof_value) { #define L(T) case sizeof(uint##T##_t): return *(uint##T##_t*)impairment->value L(8); L(16); L(32); L(64); #undef L default: bad_case(impairment->sizeof_value); } } static void jam_impairment(struct jambuf *buf, const struct impairment *impairment) { jam(buf, "%s:", impairment->what); unsigned value = value_of(impairment); if (impairment->how_keywords != NULL) { const struct keyword *kw = keyword_by_value(impairment->how_keywords, value); if (kw != NULL) { jam_string(buf, kw->sname); } else if (value >= impairment->how_keywords->nr_values) { jam(buf, "%zu", value - impairment->how_keywords->nr_values); } else { jam(buf, "?%u?", value); } } else if (impairment->how_enum_names != NULL) { const char *sname = enum_name_short(impairment->how_enum_names, value); if (sname != NULL) { jam_string(buf, sname); } else { jam(buf, "?%u?", value); } } else if (impairment->unsigned_help != NULL) { /* always one biased */ if (value == 0) { jam(buf, "no"); } else { jam(buf, "%u", value-1); } } else { switch (value) { case 0: jam(buf, "no"); break; case 1: jam(buf, "yes"); break; default: jam(buf, "?%u?", value); } } } bool have_impairments(void) { /* is there anything enabled? */ for (unsigned ci = 1; ci < elemsof(impairments); ci++) { const struct impairment *impairment = &impairments[ci]; if (impairment->action == CALL_IMPAIR_UPDATE && value_of(impairment) != 0) { return true; } } return false; } void jam_impairments(struct jambuf *buf, const char *sep) { const char *s = ""; for (unsigned ci = 1; ci < elemsof(impairments); ci++) { const struct impairment *impairment = &impairments[ci]; if (impairment->action == CALL_IMPAIR_UPDATE && value_of(impairment) != 0) { jam_string(buf, s); s = sep; jam_impairment(buf, impairment); } } } bool process_impair(const struct whack_impair *wc, void (*action)(enum impair_action impairment_action, unsigned impairment_param, unsigned biased_value, bool background, struct logger *logger), bool background, struct logger *logger) { if (wc->what == 0) { /* ignore; silently */ return true; } else if (wc->what == IMPAIR_DISABLE) { for (unsigned ci = 1; ci < elemsof(impairments); ci++) { const struct impairment *impairment = &impairments[ci]; if (impairment->action == CALL_IMPAIR_UPDATE && value_of(impairment) != 0) { dbg("%s: disabled", impairment->what); memset(impairment->value, 0, impairment->sizeof_value); } } return true; } else if (wc->what == IMPAIR_LIST) { for (unsigned ci = 1; ci < elemsof(impairments); ci++) { const struct impairment *impairment = &impairments[ci]; if (impairment->action == CALL_IMPAIR_UPDATE && value_of(impairment) != 0) { LLOG_JAMBUF(RC_COMMENT, logger, buf) { jam_impairment(buf, impairment); } } } return true; } else if (wc->what >= elemsof(impairments)) { llog(RC_LOG|ERROR_STREAM, logger, "impairment %u out-of-range", wc->what); return false; } const struct impairment *impairment = &impairments[wc->what]; switch (impairment->action) { case CALL_IMPAIR_UPDATE: /* do not un-bias */ switch (impairment->sizeof_value) { #define L(T) case sizeof(uint##T##_t): *(uint##T##_t*)impairment->value = wc->biased_value; break; L(8); L(16); L(32); L(64); #undef L default: bad_case(impairment->sizeof_value); } /* log the update */ LLOG_JAMBUF(DEBUG_STREAM, logger, buf) { jam_impairment(buf, impairment); } return true; case CALL_INITIATE_v2_LIVENESS: case CALL_SEND_KEEPALIVE: case CALL_GLOBAL_EVENT_HANDLER: case CALL_STATE_EVENT_HANDLER: case CALL_IMPAIR_DROP_INCOMING: case CALL_IMPAIR_DROP_OUTGOING: /* how is always biased */ if (action == NULL) { llog(RC_LOG|DEBUG_STREAM, logger, "no action for impairment %s", impairment->what); return false; } action(impairment->action, impairment->param, wc->biased_value, background, logger); return true; } /* not inside case */ bad_case(impairment->action); } /* * XXX: define these at the end of the file so that all references are * forced to use the extern declaration in the header (help stop code * referring to the wrong variable?). */ struct impair impair; libreswan-4.14/lib/libswan/initaddr.3.xml000066400000000000000000000142221457372064200203310ustar00rootroot00000000000000 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-4.14/lib/libswan/initaddr.c000066400000000000000000000033361457372064200176160ustar00rootroot00000000000000/* * 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 /* for AF_INET/AF_INET6 */ #include "ip_info.h" #include "ip_address.h" #include "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 = unset_address; 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-4.14/lib/libswan/initsubnet.3.xml000066400000000000000000000144121457372064200207200ustar00rootroot00000000000000 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-4.14/lib/libswan/ip_address.c000066400000000000000000000146571457372064200201450ustar00rootroot00000000000000/* * 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 /* for AF_INET/AF_INET6/AF_UNSPEC */ #include "jambuf.h" #include "ip_address.h" #include "lswlog.h" /* for dbg() */ #include "ip_info.h" const ip_address unset_address; /* all zeros */ ip_address address_from_raw(where_t where, enum ip_version version, const struct ip_bytes bytes) { ip_address a = { .is_set = true, .version = version, .bytes = bytes, }; pexpect_address(&a, where); return a; } ip_address address_from_in_addr(const struct in_addr *in) { struct ip_bytes bytes = { .byte = { 0, }, }; memcpy(bytes.byte, in, sizeof(*in)); return address_from_raw(HERE, IPv4, bytes); } 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) { struct ip_bytes bytes = { .byte = { 0, }, }; memcpy(bytes.byte, in6, sizeof(*in6)); return address_from_raw(HERE, IPv6, bytes); } const struct ip_info *address_type(const ip_address *address) { if (address == NULL) { return NULL; } /* may return NULL */ return address_info(*address); } const struct ip_info *address_info(const ip_address address) { if (!address.is_set) { return NULL; } /* may return NULL */ 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); } shunk_t address_as_shunk(const ip_address *address) { 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) { const struct ip_info *afi = address_type(address); if (afi == NULL) { /* NULL+unset+unknown */ return empty_chunk; } return chunk2(&address->bytes, afi->ip_size); } size_t jam_address(struct jambuf *buf, const ip_address *address) { if (address_is_unset(address)) { return jam_string(buf, ""); } const struct ip_info *afi = address_type(address); if (afi == NULL) { return jam_string(buf, ""); } return afi->address.jam(buf, afi, &address->bytes); } size_t jam_address_wrapped(struct jambuf *buf, const ip_address *address) { if (address_is_unset(address)) { return jam_string(buf, ""); } const struct ip_info *afi = address_type(address); if (afi == NULL) { return jam_string(buf, ""); } return afi->address.jam_wrapped(buf, afi, &address->bytes); } size_t jam_address_sensitive(struct jambuf *buf, const ip_address *address) { if (!log_ip) { return jam_string(buf, "
"); } return jam_address(buf, address); } size_t jam_address_reversed(struct jambuf *buf, const ip_address *address) { const struct ip_info *afi = address_type(address); if (afi == NULL) { return jam(buf, ""); } shunk_t bytes = address_as_shunk(address); size_t s = 0; switch (afi->af) { case AF_INET: for (int i = bytes.len - 1; i >= 0; i--) { const uint8_t *byte = bytes.ptr; s += jam(buf, "%d.", byte[i]); } s += jam(buf, "IN-ADDR.ARPA."); break; case AF_INET6: for (int i = bytes.len - 1; i >= 0; i--) { const uint8_t *byte = bytes.ptr; s += jam(buf, "%x.%x.", byte[i] & 0xf, byte[i] >> 4); } s += jam(buf, "IP6.ARPA."); break; case AF_UNSPEC: s += jam(buf, ""); break; default: bad_case(afi->af); break; } return s; } const char *str_address(const ip_address *src, address_buf *dst) { struct jambuf buf = ARRAY_AS_JAMBUF(dst->buf); jam_address(&buf, src); return dst->buf; } const char *str_address_wrapped(const ip_address *src, address_buf *dst) { struct jambuf buf = ARRAY_AS_JAMBUF(dst->buf); jam_address_wrapped(&buf, src); return dst->buf; } const char *str_address_sensitive(const ip_address *src, address_buf *dst) { struct jambuf 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) { struct jambuf buf = ARRAY_AS_JAMBUF(dst->buf); jam_address_reversed(&buf, src); return dst->buf; } bool address_is_unset(const ip_address *address) { if (address == NULL) { return true; } return !address->is_set; } bool address_is_specified(const ip_address address) { const struct ip_info *afi = address_type(&address); if (afi == NULL) { return false; } /* exclude any address */ if (address_eq_address(address, afi->address.unspec)) { return false; } return true; } bool address_eq_address(const ip_address l, const ip_address r) { if (address_is_unset(&l) && address_is_unset(&r)) { /* unset/NULL addresses are equal */ return true; } if (address_is_unset(&l) || address_is_unset(&r)) { return false; } /* must compare individual fields */ return (l.version == r.version && thingeq(l.bytes, r.bytes)); } bool address_is_loopback(const ip_address address) { const struct ip_info *afi = address_type(&address); if (afi == NULL) { /* NULL+unset+unknown */ return false; } return address_eq_address(address, afi->address.loopback); } void pexpect_address(const ip_address *a, where_t where) { if (a == NULL) { return; } /* more strict than is_unset() */ if (address_eq_address(*a, unset_address)) { return; } if (a->is_set == false || a->version == 0) { llog_pexpect(&global_logger, where, "invalid address: "PRI_ADDRESS, pri_address(a)); } } libreswan-4.14/lib/libswan/ip_bytes.c000066400000000000000000000124301457372064200176310ustar00rootroot00000000000000/* low-level ip_byte ugliness * * Copyright (C) 2000 Henry Spencer. * Copyright (C) 2018, 2021 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 "lswlog.h" /* for pexpect() */ #include "ip_bytes.h" #include "ip_info.h" const struct ip_bytes unset_ip_bytes; /* * mashup() notes: * * - mashup operates on network-order IP address bytes. */ struct ip_blit { uint8_t and; /* first operation */ uint8_t or; /* second operation */ }; 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, }; struct ip_bytes ip_bytes_from_blit(const struct ip_info *afi, const struct ip_bytes in, const struct ip_blit *routing_prefix, const struct ip_blit *host_identifier, unsigned prefix_bit_length) { if (!pexpect(prefix_bit_length <= afi->mask_cnt)) { return unset_ip_bytes; /* "can't happen" */ } struct ip_bytes out = in; uint8_t *p = out.byte; /* * Split the byte array into: * * leading | xbyte:xbit | trailing * * where LEADING only contains ROUTING_PREFIX bits, TRAILING * only contains HOST_ID bits, and XBYTE is the cross over and * contains the first HOST_ID bit at big (aka PPC) endian * position XBIT. */ size_t xbyte = prefix_bit_length / BITS_PER_BYTE; unsigned xbit = prefix_bit_length % BITS_PER_BYTE; /* leading bytes only contain the ROUTING_PREFIX */ for (unsigned b = 0; b < xbyte; b++) { p[b] &= routing_prefix->and; p[b] |= routing_prefix->or; } /* * Handle the cross over byte: * * & {ROUTING_PREFIX,HOST_ID}->and | {ROUTING_PREFIX,HOST_ID}->or * * the hmask's shift is a little counter intuitive - it clears * the first (most significant) XBITs. * * tricky logic: * - if xbyte == raw.len we must not access p[xbyte] */ if (xbyte < afi->ip_size) { uint8_t hmask = 0xFF >> xbit; /* clear MSBs */ uint8_t pmask = ~hmask; /* set MSBs */ p[xbyte] &= (routing_prefix->and & pmask) | (host_identifier->and & hmask); p[xbyte] |= (routing_prefix->or & pmask) | (host_identifier->or & hmask); } /* trailing bytes only contain the HOST_ID */ for (unsigned b = xbyte + 1; b < afi->ip_size; b++) { p[b] &= host_identifier->and; p[b] |= host_identifier->or; } return out; } /* * Calculate l-r using unsigned arithmetic */ struct ip_bytes ip_bytes_sub(const struct ip_info *afi, const struct ip_bytes l, const struct ip_bytes r) { struct ip_bytes diff = unset_ip_bytes; /* subtract: diff = hi - lo */ unsigned borrow = 0; for (int j = afi->ip_size - 1; j >= 0; j--) { unsigned val = l.byte[j] - r.byte[j] - borrow; diff.byte[j] = val; borrow = (val >> 8) & 1u; } /* ??? what should happen if l > r? borrow will be 1. */ pexpect(borrow == 0); return diff; } int ip_bytes_first_set_bit(const struct ip_info *afi, const struct ip_bytes bytes) { for (unsigned i = 0; i < afi->ip_size; i++) { uint8_t byte = bytes.byte[i]; if (byte != 0) { /* find leftmost set bit in non-zero B */ unsigned bo = 0; for (unsigned bit = 0x80u; (bit & byte) == 0; bit >>=1) { bo++; } return i * 8 + bo; } } return afi->ip_size * 8; } int ip_bytes_prefix_bits(const struct ip_info *afi, const struct ip_bytes lo, const struct ip_bytes hi) { /* * Determine the prefix_bits (the CIDR network part) by * matching leading bits of FROM and TO. Trailing bits * (subnet address) must be either all 0 (from) or 1 (to). */ /* look for a mismatching byte */ unsigned prefix_bits = 0; unsigned i; for (i = 0; i < afi->ip_size && lo.byte[i] == hi.byte[i]; i++) { prefix_bits += 8; } /* mid-byte boundary? */ if (i < afi->ip_size && (lo.byte[i] != 0x00 || hi.byte[i] != 0xff)) { /* * clear each LB bit, and set each HB as it is matched * so that, at the end FB==0x00 and TB=0xFF */ uint8_t lb = lo.byte[i]; uint8_t hb = hi.byte[i]; uint8_t bit = 0x80; while ((lb & bit) == (hb & bit)) { lb &= ~bit; hb |= bit; bit >>= 1; prefix_bits++; } if (lb != 0x00 || hb != 0xff) { return -1; } i++; /* skip boundary */ } /* check trailing bytes are correct */ for (; i < afi->ip_size; i++) { if (lo.byte[i] != 0x00 || hi.byte[i] != 0xff) { return -1; } } return prefix_bits; } /* * bytes_cmp - compare two raw addresses */ int ip_bytes_cmp(enum ip_version l_version, const struct ip_bytes l_bytes, enum ip_version r_version, const struct ip_bytes r_bytes) { int cmp = l_version - r_version; if (cmp != 0) { return cmp; } /* just compare everything */ return memcmp(l_bytes.byte, r_bytes.byte, sizeof(l_bytes)); } bool ip_bytes_is_zero(const struct ip_bytes *bytes) { return thingeq(*bytes, unset_ip_bytes); } libreswan-4.14/lib/libswan/ip_cidr.c000066400000000000000000000074051457372064200174320ustar00rootroot00000000000000/* ip cidr, for libreswan * * Copyright (C) 2019-2020 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 "passert.h" #include "jambuf.h" #include "lswlog.h" #include "ip_cidr.h" #include "ip_info.h" const ip_cidr unset_cidr; ip_cidr cidr_from_raw(where_t where, enum ip_version version, const struct ip_bytes bytes, unsigned prefix_bits) { /* combine */ ip_cidr cidr = { .is_set = true, .version = version, .bytes = bytes, .prefix_bits = prefix_bits, }; pexpect_cidr(cidr, where); return cidr; } const struct ip_info *cidr_type(const ip_cidr *cidr) { if (cidr == NULL) { return NULL; } /* may return NULL */ return cidr_info(*cidr); } const struct ip_info *cidr_info(const ip_cidr cidr) { if (!cidr.is_set) { return NULL; } /* may return NULL */ return ip_version_info(cidr.version); } ip_address cidr_address(const ip_cidr cidr) { const struct ip_info *afi = cidr_type(&cidr); if (afi == NULL) { return unset_address; } return address_from_raw(HERE, cidr.version, cidr.bytes); } err_t cidr_specified(const ip_cidr cidr) { if (!cidr.is_set) { return "unset"; } const struct ip_info *afi = cidr_type(&cidr); if (afi == NULL) { return "unknown address family"; } /* https://en.wikipedia.org/wiki/IPv6_address#Special_addresses */ /* ::/0 and/or 0.0.0.0/0 */ if (cidr.prefix_bits == 0 && thingeq(cidr.bytes, unset_ip_bytes)) { return "default route (no specific route)"; } if (thingeq(cidr.bytes, unset_ip_bytes)) { return "unspecified address"; } return NULL; } bool cidr_is_specified(const ip_cidr cidr) { return cidr_specified(cidr) == NULL; } err_t numeric_to_cidr(shunk_t src, const struct ip_info *afi, ip_cidr *cidr) { *cidr = unset_cidr; err_t err; /* split CIDR into ADDRESS/MASK. */ char slash; shunk_t address = shunk_token(&src, &slash, "/"); shunk_t mask = src; if (slash == '\0') { return "missing mask"; } if (mask.len == 0) { return "empty mask"; } /* parse ADDRESS */ ip_address addr; err = ttoaddress_num(address, afi/*possibly NULL */, &addr); if (err != NULL) { return err; } /* Fix AFI, now that it is known */ afi = address_type(&addr); passert(afi != NULL); /* parse MASK */ uintmax_t maskbits = afi->mask_cnt;/*anything*/ /* don't use bound - error is confusing */ err = shunk_to_uintmax(mask, NULL, 0, &maskbits); if (err != NULL) { /* not a number */ return err; } if (maskbits > (uintmax_t)afi->mask_cnt) { return "mask is too big"; } /* combine */ *cidr = cidr_from_raw(HERE, addr.version, addr.bytes, maskbits); return NULL; } size_t jam_cidr(struct jambuf *buf, const ip_cidr *cidr) { if (cidr == NULL) { return jam_string(buf, ""); } if (!cidr->is_set) { return jam_string(buf, ""); } size_t s = 0; ip_address sa = cidr_address(*cidr); s += jam_address(buf, &sa); /* sensitive? */ s += jam(buf, "/%u", cidr->prefix_bits); return s; } const char *str_cidr(const ip_cidr *cidr, cidr_buf *out) { struct jambuf buf = ARRAY_AS_JAMBUF(out->buf); jam_cidr(&buf, cidr); return out->buf; } void pexpect_cidr(const ip_cidr cidr, where_t where) { if (cidr.is_set == false || cidr.version == 0) { llog_pexpect(&global_logger, where, "invalid "PRI_CIDR, pri_cidr(cidr)); } } libreswan-4.14/lib/libswan/ip_encap.c000066400000000000000000000025411457372064200175730ustar00rootroot00000000000000/* 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. */ /* * XXX: linux can't include both headers. */ #ifdef linux # include /* for TCP_ENCAP_ESPINTCP and UDP_ENCAP_ESPINUDP */ #else # include /* for u_short that netinet/udp.h needs on FreeBSD */ # include /* for UDP_ENCAP_ESPINUDP aka NAT */ #endif #include "ip_protocol.h" #include "ip_encap.h" const struct ip_encap ip_encap_esp_in_tcp = { .name = "espintcp", .outer = &ip_protocol_tcp, .inner = &ip_protocol_esp, #ifdef TCP_ENCAP_ESPINTCP .encap_type = TCP_ENCAP_ESPINTCP, #endif }; const struct ip_encap ip_encap_esp_in_udp = { .name = "espinudp", .outer = &ip_protocol_udp, .inner = &ip_protocol_esp, #ifdef UDP_ENCAP_ESPINUDP .encap_type = UDP_ENCAP_ESPINUDP, #endif }; libreswan-4.14/lib/libswan/ip_endpoint.c000066400000000000000000000162351457372064200203320ustar00rootroot00000000000000/* 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 /* for AF_INET/AF_INET6 */ #include "jambuf.h" #include "ip_endpoint.h" #include "constants.h" /* for memeq() */ #include "ip_info.h" #include "ip_protocol.h" #include "lswlog.h" /* for bad_case() */ const ip_endpoint unset_endpoint; /* all zeros */ ip_endpoint endpoint_from_raw(where_t where, enum ip_version version, const struct ip_bytes bytes, const struct ip_protocol *protocol, ip_port port) { ip_endpoint endpoint = { .is_set = true, .version = version, .bytes = bytes, .hport = port.hport, .ipproto = protocol->ipproto, }; pexpect_endpoint(&endpoint, where); return endpoint; } ip_endpoint endpoint_from_address_protocol_port(const ip_address address, const struct ip_protocol *protocol, ip_port port) { return endpoint_from_raw(HERE, address.version, address.bytes, protocol, port); } ip_address endpoint_address(const ip_endpoint endpoint) { const struct ip_info *afi = endpoint_type(&endpoint); if (afi == NULL) { /* NULL+unset+unknown */ return unset_address; /* empty_address? */ } return address_from_raw(HERE, endpoint.version, endpoint.bytes); } int endpoint_hport(const ip_endpoint endpoint) { const struct ip_info *afi = endpoint_type(&endpoint); if (afi == NULL) { /* NULL+unset+unknown */ /* not asserting, who knows what nonsense a user can generate */ dbg("%s has unspecified type", __func__); return -1; } return endpoint.hport; } ip_port endpoint_port(const ip_endpoint endpoint) { const struct ip_info *afi = endpoint_type(&endpoint); if (afi == NULL) { /* NULL+unset+unknown */ /* not asserting, who knows what nonsense a user can generate */ dbg("%s has unspecified type", __func__); return unset_port; } return ip_hport(endpoint.hport); } void update_endpoint_port(ip_endpoint *endpoint, ip_port port) { *endpoint = set_endpoint_port(*endpoint, port); } ip_endpoint set_endpoint_port(const ip_endpoint endpoint, ip_port port) { const struct ip_info *afi = endpoint_type(&endpoint); if (afi == NULL) { /* includes NULL+unset+unknown */ /* not asserting, who knows what nonsense a user can generate */ dbg("endpoint has unspecified type"); return unset_endpoint; } ip_endpoint dst = endpoint; dst.hport = hport(port); pendpoint(&dst); return dst; } const struct ip_info *endpoint_type(const ip_endpoint *endpoint) { if (endpoint == NULL) { return NULL; } /* may return NULL */ return endpoint_info(*endpoint); } const struct ip_info *endpoint_info(const ip_endpoint endpoint) { if (!endpoint.is_set) { return NULL; } /* may return NULL */ return ip_version_info(endpoint.version); } bool endpoint_is_unset(const ip_endpoint *endpoint) { if (endpoint == NULL) { return true; } return !endpoint->is_set; } const struct ip_protocol *endpoint_protocol(const ip_endpoint endpoint) { if (endpoint_is_unset(&endpoint)) { return NULL; } return protocol_by_ipproto(endpoint.ipproto); } bool endpoint_is_specified(const ip_endpoint endpoint) { const struct ip_info *afi = endpoint_type(&endpoint); if (afi == NULL) { /* NULL+unset+unknown */ return false; } /* treat any 0 address as suspect */ if (thingeq(endpoint.bytes, unset_ip_bytes)) { /* any address (but we know it is zero) */ return false; } return true; } /* * 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. */ size_t jam_endpoint(struct jambuf *buf, const ip_endpoint *endpoint) { if (endpoint_is_unset(endpoint)) { return jam_string(buf, ""); } const struct ip_info *afi = endpoint_type(endpoint); if (afi == NULL) { return jam_string(buf, ""); } return afi->endpoint.jam(buf, afi, &endpoint->bytes, endpoint->hport); } const char *str_endpoint(const ip_endpoint *endpoint, endpoint_buf *dst) { struct jambuf buf = ARRAY_AS_JAMBUF(dst->buf); jam_endpoint(&buf, endpoint); return dst->buf; } size_t jam_endpoint_sensitive(struct jambuf *buf, const ip_endpoint *endpoint) { if (!log_ip) { return jam_string(buf, ""); } return jam_endpoint(buf, endpoint); } const char *str_endpoint_sensitive(const ip_endpoint *endpoint, endpoint_buf *dst) { struct jambuf buf = ARRAY_AS_JAMBUF(dst->buf); jam_endpoint_sensitive(&buf, endpoint); return dst->buf; } size_t jam_endpoints(struct jambuf *buf, const ip_endpoint *src, const ip_endpoint *dst) { size_t s = 0; s += jam_endpoint(buf, src); s += jam_char(buf, ' '); const ip_protocol *srcp = src != NULL ? endpoint_protocol(*src) : &ip_protocol_all; const ip_protocol *dstp = src != NULL ? endpoint_protocol(*dst) : &ip_protocol_all; s += jam_protocols(buf, srcp, '-', dstp); s += jam_char(buf, ' '); s += jam_endpoint(buf, dst); return s; } const char *str_endpoints(const ip_endpoint *src, const ip_endpoint *dst, endpoints_buf *out) { struct jambuf buf = ARRAY_AS_JAMBUF(out->buf); jam_endpoints(&buf, src, dst); return out->buf; } bool endpoint_eq_endpoint(const ip_endpoint l, const ip_endpoint r) { if (endpoint_is_unset(&l) && endpoint_is_unset(&r)) { /* unset/NULL endpoints are equal */ return true; } if (endpoint_is_unset(&l) || endpoint_is_unset(&r)) { return false; } /* must compare individual fields */ return (l.version == r.version && thingeq(l.bytes, r.bytes) && l.ipproto == r.ipproto && l.hport == r.hport); } bool endpoint_address_eq_address(const ip_endpoint endpoint, const ip_address address) { ip_address ea = endpoint_address(endpoint); return address_eq_address(ea, address); } void pexpect_endpoint(const ip_endpoint *e, where_t where) { if (e == NULL) { return; } /* more strict than is_unset() */ if (endpoint_eq_endpoint(*e, unset_endpoint)) { return; } /* * XXX: xfrm generates tcp acquires of the form: * * 192.1.2.45:TCP/0 -> 192.1.2.23:TCP/80 (0x5000) * * Presumably source port 0 is because the connect(?) call * specified no source port. * * Until there's an ip_traffic object to wrap this up, this * passert can't require a port. * * XXX: is [::]:TCP/10 valid? */ const ip_protocol *protocol = endpoint_protocol(*e); if (e->is_set == false || e->version == 0 || e->ipproto == 0 || protocol == NULL /* || (protocol->endpoint_requires_non_zero_port && e->hport == 0) */) { llog_pexpect(&global_logger, where, "invalid endpoint: "PRI_ENDPOINT, pri_endpoint(e)); } } libreswan-4.14/lib/libswan/ip_info.c000066400000000000000000000202001457372064200174300ustar00rootroot00000000000000/* 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 /* for AF_INET/AF_INET6/AF_UNSPEC */ #include "ietf_constants.h" #include "ip_info.h" #include "passert.h" #include "lswlog.h" /* for bad_case() */ /* * Implement https://tools.ietf.org/html/rfc5952 */ static size_t jam_ipv4_address(struct jambuf *buf, const struct ip_info *afi, const struct ip_bytes *bytes) { const char *sep = ""; size_t s = 0; for (size_t i = 0; i < afi->ip_size; i++) { s += jam(buf, "%s%"PRIu8, sep, bytes->byte[i]); sep = "."; } return s; } static size_t jam_ipv4_endpoint(struct jambuf *buf, const struct ip_info *afi, const struct ip_bytes *bytes, unsigned hport) { size_t s = 0; /* N.N.N.N:PORT */ s += afi->address.jam(buf, afi, bytes); s += jam(buf, ":%u", hport); return s; } /* * Find longest run of zero pairs that should be suppressed (need at * least two). */ static shunk_t zeros_to_skip(const struct ip_info *afi, const struct ip_bytes *bytes) { shunk_t zero = null_shunk; const uint8_t *ptr = bytes->byte; /* stop at or before last pair; ensure ptr[1] safe */ const uint8_t *last = ptr + afi->ip_size - 2; while (ptr <= last) { /* * Set L to the the number of paired zero bytes * starting at PTR (could be zero). */ unsigned l = 0; for (l = 0; ptr + l <= last; l += 2) { /* need both bytes zero */ if (ptr[l+0] != 0 || ptr[l+1] != 0) { break; } } /* * Save longer run, but only when more than one pair. */ if (l > 2 && l > zero.len) { zero = shunk2(ptr, l); ptr += l; } else { ptr += 2; } } return zero; } static size_t jam_ipv6_address(struct jambuf *buf, const struct ip_info *afi, const struct ip_bytes *bytes) { size_t s = 0; shunk_t zeros = zeros_to_skip(afi, bytes); const char *sep = ""; const uint8_t *ptr = bytes->byte; /* stop at or before last pair; ensure ptr[1] safe */ const uint8_t *last = ptr + afi->ip_size - 2; while (ptr <= last) { if (ptr == zeros.ptr) { /* skip zero run */ s += jam(buf, "::"); sep = ""; ptr += zeros.len; } else { /* print pair of bytes in hex, suppress leading zeros */ unsigned ia = (ptr[0] << 8) + ptr[1]; s += jam(buf, "%s%x", sep, ia); sep = ":"; ptr += 2; } } return s; } static size_t jam_ipv6_address_wrapped(struct jambuf *buf, const struct ip_info *afi, const struct ip_bytes *bytes) { size_t s = 0; s += jam_string(buf, "["); s += jam_ipv6_address(buf, afi, bytes); s += jam_string(buf, "]"); return s; } static size_t jam_ipv6_endpoint(struct jambuf *buf, const struct ip_info *afi, const struct ip_bytes *bytes, unsigned hport) { size_t s = 0; /* [N:..:N]:PORT */ s += jam_ipv6_address_wrapped(buf, afi, bytes); s += jam(buf, ":%u", hport); return s; } static ip_address address_from_ipv4_sockaddr(const ip_sockaddr sa) { passert(sa.sa.sa.sa_family == AF_INET); return address_from_in_addr(&sa.sa.sin.sin_addr); } static ip_address address_from_ipv6_sockaddr(const ip_sockaddr sa) { passert(sa.sa.sa.sa_family == AF_INET6); return address_from_in6_addr(&sa.sa.sin6.sin6_addr); } static ip_port port_from_ipv4_sockaddr(const ip_sockaddr sa) { passert(sa.sa.sa.sa_family == AF_INET); return ip_nport(sa.sa.sin.sin_port); } static ip_port port_from_ipv6_sockaddr(const ip_sockaddr sa) { passert(sa.sa.sa.sa_family == AF_INET6); return ip_nport(sa.sa.sin6.sin6_port); } /* * Construct well known addresses. */ #define IPv4_FF { { 255, 255, 255, 255, }, } const struct ip_info ip_families[IP_INDEX_ROOF] = { [IPv4_INDEX] = { .ip_version = IPv4, .ip_size = sizeof(struct in_addr), .ip_name = "IPv4", .mask_cnt = 32, /* ip_address - .address.any matches grep */ .address.unspec = { .is_set = true, .version = IPv4, }, /* 0.0.0.0 */ .address.loopback = { .is_set = true, .version = IPv4, .bytes = { { 127, 0, 0, 1, }, }, }, .address.jam = jam_ipv4_address, .address.jam_wrapped = jam_ipv4_address, /* ip_endpoint - */ .endpoint.jam = jam_ipv4_endpoint, /* ip_subnet - .subnet.any matches grep */ .subnet.zero = { .is_set = true, .version = IPv4, .maskbits = 32, }, /* 0.0.0.0/32 */ .subnet.all = { .is_set = true, .version = IPv4, .maskbits = 0, }, /* 0.0.0.0/0 */ /* ip_range - .range.any matches grep */ .range.zero = { .is_set = true, .version = IPv4, }, .range.all = { .is_set = true, .version = IPv4, .end = IPv4_FF, }, /* ip_selector - .selector.any matches grep */ .selector.zero = { .is_set = true, .version = IPv4, .maskbits = 32, }, /* 0.0.0.0/0 */ .selector.all = { .is_set = true, .version = IPv4, .maskbits = 0, }, /* 0.0.0.0/0 */ /* ike */ .ikev1_max_fragment_size = ISAKMP_V1_FRAG_MAXLEN_IPv4, .ikev2_max_fragment_size = ISAKMP_V2_FRAG_MAXLEN_IPv4, /* socket() */ .socket = { .domain = PF_INET, .domain_name = "PF_INET", }, /* sockaddr */ .af = AF_INET, .af_name = "AF_INET", .sockaddr_size = sizeof(struct sockaddr_in), .address_from_sockaddr = address_from_ipv4_sockaddr, .port_from_sockaddr = port_from_ipv4_sockaddr, /* IKEv2 Traffic Selector */ .ikev2_ts_addr_range_type = IKEv2_TS_IPV4_ADDR_RANGE, /* id */ .id_ip_addr = ID_IPV4_ADDR, .id_ip_addr_subnet = ID_IPV4_ADDR_SUBNET, .id_ip_addr_range = ID_IPV4_ADDR_RANGE, }, #define IPv6_FF { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }, } [IPv6_INDEX] = { .ip_version = IPv6, .ip_size = sizeof(struct in6_addr), .ip_name = "IPv6", .mask_cnt = 128, /* ip_address - .address.any matches grep */ .address.unspec = { .is_set = true, .version = IPv6, }, /* :: */ .address.loopback = { .is_set = true, .version = IPv6, .bytes = { { [15] = 1, }, }, }, /* ::1 */ .address.jam = jam_ipv6_address, .address.jam_wrapped = jam_ipv6_address_wrapped, /* ip_endpoint - */ .endpoint.jam = jam_ipv6_endpoint, /* ip_subnet - .subnet.any matches grep */ .subnet.zero = { .is_set = true, .version = IPv6, .maskbits = 128, }, /* ::/128 */ .subnet.all = { .is_set = true, .version = IPv6, .maskbits = 0, }, /* ::/0 */ /* ip_range - .range.any matches grep */ .range.zero = { .is_set = true, .version = IPv6, }, .range.all = { .is_set = true, .version = IPv6, .end = IPv6_FF, }, /* ip_selector - .selector.any matches grep */ .selector.zero = { .is_set = true, .version = IPv6, .maskbits = 128, }, /* ::/0 */ .selector.all = { .is_set = true, .version = IPv6, .maskbits = 0, }, /* ::/0 */ /* ike */ .ikev1_max_fragment_size = ISAKMP_V1_FRAG_MAXLEN_IPv6, .ikev2_max_fragment_size = ISAKMP_V2_FRAG_MAXLEN_IPv6, /* socket() */ .socket = { .domain = PF_INET6, .domain_name = "PF_INET6", }, /* sockaddr */ .af = AF_INET6, .af_name = "AF_INET6", .sockaddr_size = sizeof(struct sockaddr_in6), .address_from_sockaddr = address_from_ipv6_sockaddr, .port_from_sockaddr = port_from_ipv6_sockaddr, /* IKEv2 Traffic Selector */ .ikev2_ts_addr_range_type = IKEv2_TS_IPV6_ADDR_RANGE, /* id */ .id_ip_addr = ID_IPV6_ADDR, .id_ip_addr_subnet = ID_IPV6_ADDR_SUBNET, .id_ip_addr_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: #if 0 return &unspec_info; #else return NULL; #endif default: return NULL; } } const struct ip_info *ip_version_info(unsigned version) { static const struct ip_info *ip_types[] = { [0] = NULL, [IPv4] = &ipv4_info, [IPv6] = &ipv6_info, }; passert(version < elemsof(ip_types)); return ip_types[version]; } libreswan-4.14/lib/libswan/ip_packet.c000066400000000000000000000104571457372064200177610ustar00rootroot00000000000000/* up selector, for libreswan * * Copyright (C) 2020 Andrew Cagney * Copyright (C) 2000 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 "lswlog.h" #include "ip_packet.h" #include "ip_info.h" #include "ip_protocol.h" const ip_packet unset_packet; ip_packet packet_from_raw(where_t where, /* INFO determines meaning of BYTES */ const struct ip_info *info, const struct ip_bytes *src_bytes, const struct ip_bytes *dst_bytes, /* PROTOCOL determines meaning of PORTs */ const struct ip_protocol *protocol, ip_port src_port, ip_port dst_port) { ip_packet packet = { .is_set = true, .info = info, .protocol = protocol, .src = { .bytes = *src_bytes, .hport = src_port.hport, /* can be zero */ }, .dst = { .bytes = *dst_bytes, .hport = dst_port.hport, }, }; pexpect_packet(&packet, where); return packet; } static const char *unset(const ip_packet *packet) { return IP_INFO_PROTOCOL_UNSET(packet); } ip_address packet_src_address(const ip_packet packet) { if (packet.is_set) { return address_from_raw(HERE, packet.info->ip_version, packet.src.bytes); } else { return unset_address; } } ip_address packet_dst_address(const ip_packet packet) { if (packet.is_set) { return address_from_raw(HERE, packet.info->ip_version, packet.dst.bytes); } else { return unset_address; } } ip_endpoint packet_dst_endpoint(const ip_packet packet) { if (packet.is_set) { return endpoint_from_raw(HERE, packet.info->ip_version, packet.dst.bytes, packet.protocol, ip_hport(packet.dst.hport)); } else { return unset_endpoint; } } ip_selector packet_src_selector(const ip_packet packet) { if (packet.is_set) { return selector_from_raw(HERE, packet.info->ip_version, packet.src.bytes, packet.info->mask_cnt, packet.protocol, ip_hport(packet.src.hport)); } else { return unset_selector; } } ip_selector packet_dst_selector(const ip_packet packet) { if (packet.is_set) { return selector_from_raw(HERE, packet.info->ip_version, packet.dst.bytes, packet.info->mask_cnt, packet.protocol, ip_hport(packet.dst.hport)); } else { return unset_selector; } } size_t jam_packet(struct jambuf *buf, const ip_packet *packet) { const char *u = unset(packet); if (u != NULL) { return jam(buf, "", u); } const struct ip_info *afi = packet->info; size_t s = 0; /* src port can be zero aka wildcard */ if (packet->src.hport == 0 && packet->protocol->endpoint_requires_non_zero_port) { /* For IPv6 includes [] */ s += afi->address.jam_wrapped(buf, afi, &packet->src.bytes); } else { s += afi->endpoint.jam(buf, afi, &packet->src.bytes, packet->src.hport); } /* dst port is always valid */ s += jam(buf, "-%s->", packet->protocol->name); s += afi->endpoint.jam(buf, afi, &packet->dst.bytes, packet->dst.hport); return s; } const char *str_packet(const ip_packet *packet, packet_buf *dst) { struct jambuf buf = ARRAY_AS_JAMBUF(dst->buf); jam_packet(&buf, packet); return dst->buf; } void pexpect_packet(const ip_packet *packet, where_t where) { if (packet == NULL) { llog_pexpect(&global_logger, where, "null packet"); return; } if (packet->info == NULL || packet->protocol == NULL || ip_bytes_is_zero(&packet->src.bytes) || ip_bytes_is_zero(&packet->dst.bytes) || /* * An acquire triggered by a packet with no specified * source port will have a zero source port. */ (packet->protocol->endpoint_requires_non_zero_port && packet->dst.hport == 0)) { if (packet->is_set) { llog_pexpect(&global_logger, where, "invalid packet: "PRI_PACKET, pri_packet(packet)); } } else if (!packet->is_set) { llog_pexpect(&global_logger, where, "invalid packet: "PRI_PACKET, pri_packet(packet)); } } libreswan-4.14/lib/libswan/ip_port.c000066400000000000000000000044521457372064200174740ustar00rootroot00000000000000/* ip port (port), for libreswan * * Copyright (C) 2020 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 getservbyname() */ #include /* for ntohs() */ #include /* for strtol() */ #include "jambuf.h" #include "constants.h" /* for thingeq() */ #include "ip_port.h" const ip_port unset_port; /* aka all ports? */ ip_port ip_hport(unsigned hport) { ip_port port = { .hport = hport, }; return port; } ip_port ip_nport(unsigned nport) { return ip_hport(ntohs(nport)); } unsigned hport(const ip_port port) { return port.hport; } unsigned nport(const ip_port port) { return htons(port.hport); } bool port_is_unset(ip_port port) { return thingeq(port, unset_port); } size_t jam_hport(struct jambuf *buf, ip_port port) { return jam(buf, PRI_HPORT, hport(port)); } size_t jam_nport(struct jambuf *buf, ip_port port) { return jam(buf, PRI_NPORT, pri_nport(port)); } const char *str_hport(ip_port port, port_buf *buf) { struct jambuf jambuf = ARRAY_AS_JAMBUF(buf->buf); jam_hport(&jambuf, port); return buf->buf; } const char *str_nport(ip_port port, port_buf *buf) { struct jambuf jambuf = ARRAY_AS_JAMBUF(buf->buf); jam_nport(&jambuf, port); return buf->buf; } err_t ttoport(const char *service_name, unsigned *port) { /* extract port by trying to resolve it by name */ const struct servent *service = getservbyname(service_name, NULL); if (service != NULL) { *port = ntohs(service->s_port); return NULL; } /* failed, now try it by number */ char *end; long l = strtol(service_name, &end, 0); if (*service_name && *end) { *port = 0; return " is neither a number nor a valid name"; } if (l < 0 || l > 0xffff) { *port = 0; return " must be between 0 and 65535"; } *port = l; return NULL; } libreswan-4.14/lib/libswan/ip_port_range.c000066400000000000000000000025721457372064200206510ustar00rootroot00000000000000/* ip port range, for libreswan * * Copyright (C) 2020 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 ntohs() */ #include "jambuf.h" #include "ip_port_range.h" #include "lswlog.h" /* for pexpect() */ const ip_port_range unset_port_range; ip_port_range port_range_from_ports(ip_port lo, ip_port hi) { ip_port_range r = { .is_set = true, .lo = lo.hport, .hi = hi.hport, }; pexpect(r.lo <= r.hi); return r; } size_t jam_port_range(struct jambuf *buf, ip_port_range r) { if (!r.is_set) { return jam(buf, ""); } if (r.lo == r.hi) { return jam(buf, "%u", r.lo); } else { return jam(buf, "%u-%u", r.lo, r.hi); } } const char *str_port_range(ip_port_range port, port_range_buf *buf) { struct jambuf jambuf = ARRAY_AS_JAMBUF(buf->buf); jam_port_range(&jambuf, port); return buf->buf; } libreswan-4.14/lib/libswan/ip_protocol.c000066400000000000000000001130421457372064200203450ustar00rootroot00000000000000/* 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 /* for getprotobyname() */ #include /* for IPPROTO_* */ #include "lswcdefs.h" /* for elemsof() */ #include "constants.h" /* for strncaseeq() */ #include "enum_names.h" #include "passert.h" #include "lswalloc.h" #include "ip_protocol.h" #include "ip_encap.h" #include "jambuf.h" const struct ip_protocol ip_protocols[256] = { /* * Hand generated from: * https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml * * Decimal,Keyword,Protocol,IPv6 Extension Header,Reference */ #if 0 /* * IPv6 defines protocol 0 (it loosely translates to look in * next header) but pluto assumes 0 is wild-card. */ [0] = { .description = "IPv6 Hop-by-Hop Option", .name = "HOPOPT", .ipproto = 0, .ipv6_extension_header = true, .reference = "[RFC8200]", }, #else [0] = { .description = "all", .name = "ALL", .prefix = "unk", .ipproto = 0, }, #endif [1] = { .description = "Internet Control Message", .name = "ICMP", .ipproto = IPPROTO_ICMP, .reference = "[RFC792]", /* libreswan */ .prefix = "icmp", }, [2] = { .description = "Internet Group Management", .name = "IGMP", .ipproto = 2, .reference = "[RFC1112]", }, [3] = { .description = "Gateway-to-Gateway", .name = "GGP", .ipproto = 3, .reference = "[RFC823]", }, [4] = { .description = "IPv4 encapsulation", .name = "IPv4", .ipproto = IPPROTO_IPIP, .reference = "[RFC2003]", /* libreswan */ .prefix = "tun", }, [5] = { .description = "Stream", .name = "ST", .ipproto = 5, .reference = "[RFC1190][RFC1819]", }, [6] = { .description = "Transmission Control", .name = "TCP", .ipproto = IPPROTO_TCP, .reference = "[RFC793]", /* libreswan */ .prefix = "tcp", .encap_esp = &ip_encap_esp_in_tcp, .endpoint_requires_non_zero_port = true, }, [7] = { .description = "CBT", .name = "CBT", .ipproto = 7, .reference = "[Tony_Ballardie]", }, [8] = { .description = "Exterior Gateway Protocol", .name = "EGP", .ipproto = 8, .reference = "[RFC888][David_Mills]", }, [9] = { .description = "any private interior gateway (used by Cisco for their IGRP)", .name = "IGP", .ipproto = 9, .reference = "[Internet_Assigned_Numbers_Authority]", }, [10] = { .description = "BBN RCC Monitoring", .name = "BBN-RCC-MON", .ipproto = 10, .reference = "[Steve_Chipman]", }, [11] = { .description = "Network Voice Protocol", .name = "NVP-II", .ipproto = 11, .reference = "[RFC741][Steve_Casner]", }, [12] = { .description = "PUP", .name = "PUP", .ipproto = 12, .reference = "[Boggs, D., J. Shoch, E. Taft, and R. Metcalfe, \"PUP: An Internetwork Architecture\", XEROX Palo Alto Research Center, CSL-79-10, July 1979; also in IEEE Transactions on Communication, Volume COM-28, Number 4, April 1980.][[XEROX]]", }, [13] = { .description = "ARGUS", .name = "ARGUS (deprecated)", .ipproto = 13, .reference = "[Robert_W_Scheifler]", }, [14] = { .description = "EMCON", .name = "EMCON", .ipproto = 14, .reference = "[]", }, [15] = { .description = "Cross Net Debugger", .name = "XNET", .ipproto = 15, .reference = "[Haverty, J., \"XNET Formats for Internet Protocol Version 4\", IEN 158, October 1980.][Jack_Haverty]", }, [16] = { .description = "Chaos", .name = "CHAOS", .ipproto = 16, .reference = "[J_Noel_Chiappa]", }, [17] = { .description = "User Datagram", .name = "UDP", .ipproto = IPPROTO_UDP, .reference = "[RFC768][Jon_Postel]", /* libreswan */ .prefix = "udp", .encap_esp = &ip_encap_esp_in_udp, .endpoint_requires_non_zero_port = true, }, [18] = { .description = "Multiplexing", .name = "MUX", .ipproto = 18, .reference = "[Cohen, D. and J. Postel, \"Multiplexing Protocol\", IEN 90, USC/Information Sciences Institute, May 1979.][Jon_Postel]", }, [19] = { .description = "DCN Measurement Subsystems", .name = "DCN-MEAS", .ipproto = 19, .reference = "[David_Mills]", }, [20] = { .description = "Host Monitoring", .name = "HMP", .ipproto = 20, .reference = "[RFC869][Bob_Hinden]", }, [21] = { .description = "Packet Radio Measurement", .name = "PRM", .ipproto = 21, .reference = "[Zaw_Sing_Su]", }, [22] = { .description = "XEROX NS IDP", .name = "XNS-IDP", .ipproto = 22, .reference = "[\"The Ethernet, A Local Area Network: Data Link Layer and Physical Layer Specification\", AA-K759B-TK, Digital Equipment Corporation, Maynard, MA. Also as: \"The Ethernet - A Local Area Network\", Version 1.0, Digital Equipment Corporation, Intel Corporation, Xerox Corporation, September 1980. And: \"The Ethernet, A Local Area Network: Data Link Layer and Physical Layer Specifications\", Digital, Intel and Xerox, November 1982. And: XEROX, \"The Ethernet, A Local Area Network: Data Link Layer and Physical Layer Specification\", X3T51/80-50, Xerox Corporation, Stamford, CT., October 1980.][[XEROX]]", }, [23] = { .description = "Trunk-1", .name = "TRUNK-1", .ipproto = 23, .reference = "[Barry_Boehm]", }, [24] = { .description = "Trunk-2", .name = "TRUNK-2", .ipproto = 24, .reference = "[Barry_Boehm]", }, [25] = { .description = "Leaf-1", .name = "LEAF-1", .ipproto = 25, .reference = "[Barry_Boehm]", }, [26] = { .description = "Leaf-2", .name = "LEAF-2", .ipproto = 26, .reference = "[Barry_Boehm]", }, [27] = { .description = "Reliable Data Protocol", .name = "RDP", .ipproto = 27, .reference = "[RFC908][Bob_Hinden]", }, [28] = { .description = "Internet Reliable Transaction", .name = "IRTP", .ipproto = 28, .reference = "[RFC938][Trudy_Miller]", }, [29] = { .description = "ISO Transport Protocol Class 4", .name = "ISO-TP4", .ipproto = 29, .reference = "[RFC905][]", }, [30] = { .description = "Bulk Data Transfer Protocol", .name = "NETBLT", .ipproto = 30, .reference = "[RFC969][David_Clark]", }, [31] = { .description = "MFE Network Services Protocol", .name = "MFE-NSP", .ipproto = 31, .reference = "[Shuttleworth, B., ""A Documentary of MFENet, a National Computer Network"", UCRL-52317, Lawrence Livermore Labs, Livermore, California, June 1977.][Barry_Howard]", }, [32] = { .description = "MERIT Internodal Protocol", .name = "MERIT-INP", .ipproto = 32, .reference = "[Hans_Werner_Braun]", }, [33] = { .description = "Datagram Congestion Control Protocol", .name = "DCCP", .ipproto = 33, .reference = "[RFC4340]", }, [34] = { .description = "Third Party Connect Protocol", .name = "3PC", .ipproto = 34, .reference = "[Stuart_A_Friedberg]", }, [35] = { .description = "Inter-Domain Policy Routing Protocol", .name = "IDPR", .ipproto = 35, .reference = "[Martha_Steenstrup]", }, [36] = { .description = "XTP", .name = "XTP", .ipproto = 36, .reference = "[Greg_Chesson]", }, [37] = { .description = "Datagram Delivery Protocol", .name = "DDP", .ipproto = 37, .reference = "[Wesley_Craig]", }, [38] = { .description = "IDPR Control Message Transport Proto", .name = "IDPR-CMTP", .ipproto = 38, .reference = "[Martha_Steenstrup]", }, [39] = { .description = "TP++ Transport Protocol", .name = "TP++", .ipproto = 39, .reference = "[Dirk_Fromhein]", }, [40] = { .description = "IL Transport Protocol", .name = "IL", .ipproto = 40, .reference = "[Dave_Presotto]", }, [41] = { .description = "IPv6 encapsulation", .name = "IPv6", .ipproto = 41, .reference = "[RFC2473]", }, [42] = { .description = "Source Demand Routing Protocol", .name = "SDRP", .ipproto = 42, .reference = "[Deborah_Estrin]", }, [43] = { .description = "Routing Header for IPv6", .name = "IPv6-Route", .ipproto = 43, .ipv6_extension_header = true, .reference = "[Steve_Deering]", }, [44] = { .description = "Fragment Header for IPv6", .name = "IPv6-Frag", .ipproto = 44, .ipv6_extension_header = true, .reference = "[Steve_Deering]", }, [45] = { .description = "Inter-Domain Routing Protocol", .name = "IDRP", .ipproto = 45, .reference = "[Sue_Hares]", }, [46] = { .description = "Reservation Protocol", .name = "RSVP", .ipproto = 46, .reference = "[RFC2205][RFC3209][Bob_Braden]", }, [47] = { .description = "Generic Routing Encapsulation", .name = "GRE", .ipproto = 47, .reference = "[RFC2784][Tony_Li]", }, [48] = { .description = "Dynamic Source Routing Protocol", .name = "DSR", .ipproto = 48, .reference = "[RFC4728]", }, [49] = { .description = "BNA", .name = "BNA", .ipproto = 49, .reference = "[Gary Salamon]", }, [50] = { .description = "Encap Security Payload", .name = "ESP", .ipproto = IPPROTO_ESP, .ipv6_extension_header = true, .reference = "[RFC4303]", /* libreswan */ .prefix = "esp", .ikev1_protocol_id = PROTO_IPSEC_ESP, }, [51] = { .description = "Authentication Header", .name = "AH", .ipproto = IPPROTO_AH, .ipv6_extension_header = true, .reference = "[RFC4302]", /* libreswan */ .prefix = "ah", .ikev1_protocol_id = PROTO_IPSEC_AH, }, [52] = { .description = "Integrated Net Layer Security TUBA", .name = "I-NLSP", .ipproto = 52, .reference = "[K_Robert_Glenn]", }, [53] = { .description = "IP with Encryption", .name = "SWIPE (deprecated)", .ipproto = 53, .reference = "[John_Ioannidis]", }, [54] = { .description = "NBMA Address Resolution Protocol", .name = "NARP", .ipproto = 54, .reference = "[RFC1735]", }, [55] = { .description = "IP Mobility", .name = "MOBILE", .ipproto = 55, .reference = "[Charlie_Perkins]", }, [56] = { .description = "Transport Layer Security Protocol using Kryptonet key management", .name = "TLSP", .ipproto = 56, .reference = "[Christer_Oberg]", }, [57] = { .description = "SKIP", .name = "SKIP", .ipproto = 57, .reference = "[Tom_Markson]", }, [58] = { .description = "ICMP for IPv6", .name = "IPv6-ICMP", .ipproto = 58, .reference = "[RFC8200]", }, [59] = { .description = "No Next Header for IPv6", .name = "IPv6-NoNxt", .ipproto = 59, .reference = "[RFC8200]", }, [60] = { .description = "Destination Options for IPv6", .name = "IPv6-Opts", .ipproto = 60, .ipv6_extension_header = true, .reference = "[RFC8200]", }, [61] = { .description = "any host internal protocol", .name = "61", .ipproto = INTERNAL_IPPROTO, .reference = "[Internet_Assigned_Numbers_Authority]", /* libreswan */ .prefix = "int", }, [62] = { .description = "CFTP", .name = "CFTP", .ipproto = 62, .reference = "[Forsdick, H., ""CFTP"", Network Message, Bolt Beranek and Newman, January 1982.][Harry_Forsdick]", }, [63] = { .description = "any local network", .name = "63", .ipproto = 63, .reference = "[Internet_Assigned_Numbers_Authority]", }, [64] = { .description = "SATNET and Backroom EXPAK", .name = "SAT-EXPAK", .ipproto = 64, .reference = "[Steven_Blumenthal]", }, [65] = { .description = "Kryptolan", .name = "KRYPTOLAN", .ipproto = 65, .reference = "[Paul Liu]", }, [66] = { .description = "MIT Remote Virtual Disk Protocol", .name = "RVD", .ipproto = 66, .reference = "[Michael_Greenwald]", }, [67] = { .description = "Internet Pluribus Packet Core", .name = "IPPC", .ipproto = 67, .reference = "[Steven_Blumenthal]", }, [68] = { .description = "any distributed file system", .name = "68", .ipproto = 68, .reference = "[Internet_Assigned_Numbers_Authority]", }, [69] = { .description = "SATNET Monitoring", .name = "SAT-MON", .ipproto = 69, .reference = "[Steven_Blumenthal]", }, [70] = { .description = "VISA Protocol", .name = "VISA", .ipproto = 70, .reference = "[Gene_Tsudik]", }, [71] = { .description = "Internet Packet Core Utility", .name = "IPCV", .ipproto = 71, .reference = "[Steven_Blumenthal]", }, [72] = { .description = "Computer Protocol Network Executive", .name = "CPNX", .ipproto = 72, .reference = "[David Mittnacht]", }, [73] = { .description = "Computer Protocol Heart Beat", .name = "CPHB", .ipproto = 73, .reference = "[David Mittnacht]", }, [74] = { .description = "Wang Span Network", .name = "WSN", .ipproto = 74, .reference = "[Victor Dafoulas]", }, [75] = { .description = "Packet Video Protocol", .name = "PVP", .ipproto = 75, .reference = "[Steve_Casner]", }, [76] = { .description = "Backroom SATNET Monitoring", .name = "BR-SAT-MON", .ipproto = 76, .reference = "[Steven_Blumenthal]", }, [77] = { .description = "SUN ND PROTOCOL-Temporary", .name = "SUN-ND", .ipproto = 77, .reference = "[William_Melohn]", }, [78] = { .description = "WIDEBAND Monitoring", .name = "WB-MON", .ipproto = 78, .reference = "[Steven_Blumenthal]", }, [79] = { .description = "WIDEBAND EXPAK", .name = "WB-EXPAK", .ipproto = 79, .reference = "[Steven_Blumenthal]", }, [80] = { .description = "ISO Internet Protocol", .name = "ISO-IP", .ipproto = 80, .reference = "[Marshall_T_Rose]", }, [81] = { .description = "VMTP", .name = "VMTP", .ipproto = 81, .reference = "[Dave_Cheriton]", }, [82] = { .description = "SECURE-VMTP", .name = "SECURE-VMTP", .ipproto = 82, .reference = "[Dave_Cheriton]", }, [83] = { .description = "VINES", .name = "VINES", .ipproto = 83, .reference = "[Brian Horn]", }, #if 0 /* duplicate! */ [84] = { .description = "Transaction Transport Protocol", .name = "TTP", .ipproto = 84, .reference = "[Jim_Stevens]", }, [84] = { .description = "Internet Protocol Traffic Manager", .name = "IPTM", .ipproto = 84, .reference = "[Jim_Stevens]", }, #else [84] = { .description = "Transaction Transport Protocol|Internet Protocol Traffic Manager", .name = "TTP|IPTM", .ipproto = 84, .reference = "[Jim_Stevens]", }, #endif [85] = { .description = "NSFNET-IGP", .name = "NSFNET-IGP", .ipproto = 85, .reference = "[Hans_Werner_Braun]", }, [86] = { .description = "Dissimilar Gateway Protocol", .name = "DGP", .ipproto = 86, .reference = "[M/A-COM Government Systems, ""Dissimilar Gateway Protocol Specification, Draft Version"", Contract no. CS901145, November 16, 1987.][Mike_Little]", }, [87] = { .description = "TCF", .name = "TCF", .ipproto = 87, .reference = "[Guillermo_A_Loyola]", }, [88] = { .description = "EIGRP", .name = "EIGRP", .ipproto = 88, .reference = "[RFC7868]", }, [89] = { .description = "OSPFIGP", .name = "OSPFIGP", .ipproto = 89, .reference = "[RFC1583][RFC2328][RFC5340][John_Moy]", }, [90] = { .description = "Sprite RPC Protocol", .name = "Sprite-RPC", .ipproto = 90, .reference = "[Welch, B., ""The Sprite Remote Procedure Call System"", Technical Report, UCB/Computer Science Dept., 86/302, University of California at Berkeley, June 1986.][Bruce Willins]", }, [91] = { .description = "Locus Address Resolution Protocol", .name = "LARP", .ipproto = 91, .reference = "[Brian Horn]", }, [92] = { .description = "Multicast Transport Protocol", .name = "MTP", .ipproto = 92, .reference = "[Susie_Armstrong]", }, [93] = { .description = "AX.25 Frames", .name = "AX.25", .ipproto = 93, .reference = "[Brian_Kantor]", }, [94] = { .description = "IP-within-IP Encapsulation Protocol", .name = "IPIP", .ipproto = 94, .reference = "[John_Ioannidis]", }, [95] = { .description = "Mobile Internetworking Control Pro.", .name = "MICP (deprecated)", .ipproto = 95, .reference = "[John_Ioannidis]", }, [96] = { .description = "Semaphore Communications Sec. Pro.", .name = "SCC-SP", .ipproto = 96, .reference = "[Howard_Hart]", }, [97] = { .description = "Ethernet-within-IP Encapsulation", .name = "ETHERIP", .ipproto = 97, .reference = "[RFC3378]", }, [98] = { .description = "Encapsulation Header", .name = "ENCAP", .ipproto = 98, .reference = "[RFC1241][Robert_Woodburn]", }, [99] = { .description = "any private encryption scheme", .name = "99", .ipproto = 99, .reference = "[Internet_Assigned_Numbers_Authority]", }, [100] = { .description = "GMTP", .name = "GMTP", .ipproto = 100, .reference = "[[RXB5]]", }, [101] = { .description = "Ipsilon Flow Management Protocol", .name = "IFMP", .ipproto = 101, .reference = "[Bob_Hinden][November 1995, 1997.]", }, [102] = { .description = "PNNI over IP", .name = "PNNI", .ipproto = 102, .reference = "[Ross_Callon]", }, [103] = { .description = "Protocol Independent Multicast", .name = "PIM", .ipproto = 103, .reference = "[RFC7761][Dino_Farinacci]", }, [104] = { .description = "ARIS", .name = "ARIS", .ipproto = 104, .reference = "[Nancy_Feldman]", }, [105] = { .description = "SCPS", .name = "SCPS", .ipproto = 105, .reference = "[Robert_Durst]", }, [106] = { .description = "QNX", .name = "QNX", .ipproto = 106, .reference = "[Michael_Hunter]", }, [107] = { .description = "Active Networks", .name = "A/N", .ipproto = 107, .reference = "[Bob_Braden]", }, [IPCOMP_IPPROTO] = { .description = "IP Payload Compression Protocol", .name = "IPComp", .ipproto = 108, .reference = "[RFC2393]", /* libreswan */ .prefix = "comp", }, [109] = { .description = "Sitara Networks Protocol", .name = "SNP", .ipproto = 109, .reference = "[Manickam_R_Sridhar]", }, [110] = { .description = "Compaq Peer Protocol", .name = "Compaq-Peer", .ipproto = 110, .reference = "[Victor_Volpe]", }, [111] = { .description = "IPX in IP", .name = "IPX-in-IP", .ipproto = 111, .reference = "[CJ_Lee]", }, [112] = { .description = "Virtual Router Redundancy Protocol", .name = "VRRP", .ipproto = 112, .reference = "[RFC5798]", }, [113] = { .description = "PGM Reliable Transport Protocol", .name = "PGM", .ipproto = 113, .reference = "[Tony_Speakman]", }, [114] = { .description = "any 0-hop protocol", .name = "114", .ipproto = 114, .reference = "[Internet_Assigned_Numbers_Authority]", }, [115] = { .description = "Layer Two Tunneling Protocol", .name = "L2TP", .ipproto = 115, .reference = "[RFC3931][Bernard_Aboba]", }, [116] = { .description = "D-II Data Exchange (DDX)", .name = "DDX", .ipproto = 116, .reference = "[John_Worley]", }, [117] = { .description = "Interactive Agent Transfer Protocol", .name = "IATP", .ipproto = 117, .reference = "[John_Murphy]", }, [118] = { .description = "Schedule Transfer Protocol", .name = "STP", .ipproto = 118, .reference = "[Jean_Michel_Pittet]", }, [119] = { .description = "SpectraLink Radio Protocol", .name = "SRP", .ipproto = 119, .reference = "[Mark_Hamilton]", }, [120] = { .description = "UTI", .name = "UTI", .ipproto = 120, .reference = "[Peter_Lothberg]", }, [121] = { .description = "Simple Message Protocol", .name = "SMP", .ipproto = 121, .reference = "[Leif_Ekblad]", }, [122] = { .description = "Simple Multicast Protocol", .name = "SM (deprecated)", .ipproto = 122, .reference = "[Jon_Crowcroft][draft-perlman-simple-multicast]", }, [123] = { .description = "Performance Transparency Protocol", .name = "PTP", .ipproto = 123, .reference = "[Michael_Welzl]", }, [124] = { .description = "124", .name = "ISIS over IPv4", .ipproto = 124, .reference = "[Tony_Przygienda]", }, [125] = { .description = "125", .name = "FIRE", .ipproto = 125, .reference = "[Criag_Partridge]", }, [126] = { .description = "Combat Radio Transport Protocol", .name = "CRTP", .ipproto = 126, .reference = "[Robert_Sautter]", }, [127] = { .description = "Combat Radio User Datagram", .name = "CRUDP", .ipproto = 127, .reference = "[Robert_Sautter]", }, [128] = { .description = "128", .name = "SSCOPMCE", .ipproto = 128, .reference = "[Kurt_Waber]", }, [129] = { .description = "129", .name = "IPLT", .ipproto = 129, .reference = "[[Hollbach]]", }, [130] = { .description = "Secure Packet Shield", .name = "SPS", .ipproto = 130, .reference = "[Bill_McIntosh]", }, [131] = { .description = "Private IP Encapsulation within IP", .name = "PIPE", .ipproto = 131, .reference = "[Bernhard_Petri]", }, [132] = { .description = "Stream Control Transmission Protocol", .name = "SCTP", .ipproto = 132, .reference = "[Randall_R_Stewart]", }, [133] = { .description = "Fibre Channel", .name = "FC", .ipproto = 133, .reference = "[Murali_Rajagopal][RFC6172]", }, [134] = { .description = "134", .name = "RSVP-E2E-IGNORE", .ipproto = 134, .reference = "[RFC3175]", }, [135] = { .description = "135", .name = "Mobility Header", .ipproto = 135, .ipv6_extension_header = true, .reference = "[RFC6275]", }, [136] = { .description = "136", .name = "UDPLite", .ipproto = 136, .reference = "[RFC3828]", }, [137] = { .description = "137", .name = "MPLS-in-IP", .ipproto = 137, .reference = "[RFC4023]", }, [138] = { .description = "MANET Protocols", .name = "manet", .ipproto = 138, .reference = "[RFC5498]", }, [139] = { .description = "Host Identity Protocol", .name = "HIP", .ipproto = 139, .ipv6_extension_header = true, .reference = "[RFC7401]", }, [140] = { .description = "Shim6 Protocol", .name = "Shim6", .ipproto = 140, .ipv6_extension_header = true, .reference = "[RFC5533]", }, [141] = { .description = "Wrapped Encapsulating Security Payload", .name = "WESP", .ipproto = 141, .reference = "[RFC5840]", }, [142] = { .description = "Robust Header Compression", .name = "ROHC", .ipproto = 142, .reference = "[RFC5858]", }, [143] = { .description = "Ethernet", .name = "Ethernet", .ipproto = 143, .reference = "[RFC-ietf-spring-srv6-network-programming-28]", }, [144] = { .description = "144", .name = "144", .ipproto = 144, .reference = "[Internet_Assigned_Numbers_Authority]", }, [145] = { .description = "145", .name = "145", .ipproto = 145, .reference = "[Internet_Assigned_Numbers_Authority]", }, [146] = { .description = "146", .name = "146", .ipproto = 146, .reference = "[Internet_Assigned_Numbers_Authority]", }, [147] = { .description = "147", .name = "147", .ipproto = 147, .reference = "[Internet_Assigned_Numbers_Authority]", }, [148] = { .description = "148", .name = "148", .ipproto = 148, .reference = "[Internet_Assigned_Numbers_Authority]", }, [149] = { .description = "149", .name = "149", .ipproto = 149, .reference = "[Internet_Assigned_Numbers_Authority]", }, [150] = { .description = "150", .name = "150", .ipproto = 150, .reference = "[Internet_Assigned_Numbers_Authority]", }, [151] = { .description = "151", .name = "151", .ipproto = 151, .reference = "[Internet_Assigned_Numbers_Authority]", }, [152] = { .description = "152", .name = "152", .ipproto = 152, .reference = "[Internet_Assigned_Numbers_Authority]", }, [153] = { .description = "153", .name = "153", .ipproto = 153, .reference = "[Internet_Assigned_Numbers_Authority]", }, [154] = { .description = "154", .name = "154", .ipproto = 154, .reference = "[Internet_Assigned_Numbers_Authority]", }, [155] = { .description = "155", .name = "155", .ipproto = 155, .reference = "[Internet_Assigned_Numbers_Authority]", }, [156] = { .description = "156", .name = "156", .ipproto = 156, .reference = "[Internet_Assigned_Numbers_Authority]", }, [157] = { .description = "157", .name = "157", .ipproto = 157, .reference = "[Internet_Assigned_Numbers_Authority]", }, [158] = { .description = "158", .name = "158", .ipproto = 158, .reference = "[Internet_Assigned_Numbers_Authority]", }, [159] = { .description = "159", .name = "159", .ipproto = 159, .reference = "[Internet_Assigned_Numbers_Authority]", }, [160] = { .description = "160", .name = "160", .ipproto = 160, .reference = "[Internet_Assigned_Numbers_Authority]", }, [161] = { .description = "161", .name = "161", .ipproto = 161, .reference = "[Internet_Assigned_Numbers_Authority]", }, [162] = { .description = "162", .name = "162", .ipproto = 162, .reference = "[Internet_Assigned_Numbers_Authority]", }, [163] = { .description = "163", .name = "163", .ipproto = 163, .reference = "[Internet_Assigned_Numbers_Authority]", }, [164] = { .description = "164", .name = "164", .ipproto = 164, .reference = "[Internet_Assigned_Numbers_Authority]", }, [165] = { .description = "165", .name = "165", .ipproto = 165, .reference = "[Internet_Assigned_Numbers_Authority]", }, [166] = { .description = "166", .name = "166", .ipproto = 166, .reference = "[Internet_Assigned_Numbers_Authority]", }, [167] = { .description = "167", .name = "167", .ipproto = 167, .reference = "[Internet_Assigned_Numbers_Authority]", }, [168] = { .description = "168", .name = "168", .ipproto = 168, .reference = "[Internet_Assigned_Numbers_Authority]", }, [169] = { .description = "169", .name = "169", .ipproto = 169, .reference = "[Internet_Assigned_Numbers_Authority]", }, [170] = { .description = "170", .name = "170", .ipproto = 170, .reference = "[Internet_Assigned_Numbers_Authority]", }, [171] = { .description = "171", .name = "171", .ipproto = 171, .reference = "[Internet_Assigned_Numbers_Authority]", }, [172] = { .description = "172", .name = "172", .ipproto = 172, .reference = "[Internet_Assigned_Numbers_Authority]", }, [173] = { .description = "173", .name = "173", .ipproto = 173, .reference = "[Internet_Assigned_Numbers_Authority]", }, [174] = { .description = "174", .name = "174", .ipproto = 174, .reference = "[Internet_Assigned_Numbers_Authority]", }, [175] = { .description = "175", .name = "175", .ipproto = 175, .reference = "[Internet_Assigned_Numbers_Authority]", }, [176] = { .description = "176", .name = "176", .ipproto = 176, .reference = "[Internet_Assigned_Numbers_Authority]", }, [177] = { .description = "177", .name = "177", .ipproto = 177, .reference = "[Internet_Assigned_Numbers_Authority]", }, [178] = { .description = "178", .name = "178", .ipproto = 178, .reference = "[Internet_Assigned_Numbers_Authority]", }, [179] = { .description = "179", .name = "179", .ipproto = 179, .reference = "[Internet_Assigned_Numbers_Authority]", }, [180] = { .description = "180", .name = "180", .ipproto = 180, .reference = "[Internet_Assigned_Numbers_Authority]", }, [181] = { .description = "181", .name = "181", .ipproto = 181, .reference = "[Internet_Assigned_Numbers_Authority]", }, [182] = { .description = "182", .name = "182", .ipproto = 182, .reference = "[Internet_Assigned_Numbers_Authority]", }, [183] = { .description = "183", .name = "183", .ipproto = 183, .reference = "[Internet_Assigned_Numbers_Authority]", }, [184] = { .description = "184", .name = "184", .ipproto = 184, .reference = "[Internet_Assigned_Numbers_Authority]", }, [185] = { .description = "185", .name = "185", .ipproto = 185, .reference = "[Internet_Assigned_Numbers_Authority]", }, [186] = { .description = "186", .name = "186", .ipproto = 186, .reference = "[Internet_Assigned_Numbers_Authority]", }, [187] = { .description = "187", .name = "187", .ipproto = 187, .reference = "[Internet_Assigned_Numbers_Authority]", }, [188] = { .description = "188", .name = "188", .ipproto = 188, .reference = "[Internet_Assigned_Numbers_Authority]", }, [189] = { .description = "189", .name = "189", .ipproto = 189, .reference = "[Internet_Assigned_Numbers_Authority]", }, [190] = { .description = "190", .name = "190", .ipproto = 190, .reference = "[Internet_Assigned_Numbers_Authority]", }, [191] = { .description = "191", .name = "191", .ipproto = 191, .reference = "[Internet_Assigned_Numbers_Authority]", }, [192] = { .description = "192", .name = "192", .ipproto = 192, .reference = "[Internet_Assigned_Numbers_Authority]", }, [193] = { .description = "193", .name = "193", .ipproto = 193, .reference = "[Internet_Assigned_Numbers_Authority]", }, [194] = { .description = "194", .name = "194", .ipproto = 194, .reference = "[Internet_Assigned_Numbers_Authority]", }, [195] = { .description = "195", .name = "195", .ipproto = 195, .reference = "[Internet_Assigned_Numbers_Authority]", }, [196] = { .description = "196", .name = "196", .ipproto = 196, .reference = "[Internet_Assigned_Numbers_Authority]", }, [197] = { .description = "197", .name = "197", .ipproto = 197, .reference = "[Internet_Assigned_Numbers_Authority]", }, [198] = { .description = "198", .name = "198", .ipproto = 198, .reference = "[Internet_Assigned_Numbers_Authority]", }, [199] = { .description = "199", .name = "199", .ipproto = 199, .reference = "[Internet_Assigned_Numbers_Authority]", }, [200] = { .description = "200", .name = "200", .ipproto = 200, .reference = "[Internet_Assigned_Numbers_Authority]", }, [201] = { .description = "201", .name = "201", .ipproto = 201, .reference = "[Internet_Assigned_Numbers_Authority]", }, [202] = { .description = "202", .name = "202", .ipproto = 202, .reference = "[Internet_Assigned_Numbers_Authority]", }, [203] = { .description = "203", .name = "203", .ipproto = 203, .reference = "[Internet_Assigned_Numbers_Authority]", }, [204] = { .description = "204", .name = "204", .ipproto = 204, .reference = "[Internet_Assigned_Numbers_Authority]", }, [205] = { .description = "205", .name = "205", .ipproto = 205, .reference = "[Internet_Assigned_Numbers_Authority]", }, [206] = { .description = "206", .name = "206", .ipproto = 206, .reference = "[Internet_Assigned_Numbers_Authority]", }, [207] = { .description = "207", .name = "207", .ipproto = 207, .reference = "[Internet_Assigned_Numbers_Authority]", }, [208] = { .description = "208", .name = "208", .ipproto = 208, .reference = "[Internet_Assigned_Numbers_Authority]", }, [209] = { .description = "209", .name = "209", .ipproto = 209, .reference = "[Internet_Assigned_Numbers_Authority]", }, [210] = { .description = "210", .name = "210", .ipproto = 210, .reference = "[Internet_Assigned_Numbers_Authority]", }, [211] = { .description = "211", .name = "211", .ipproto = 211, .reference = "[Internet_Assigned_Numbers_Authority]", }, [212] = { .description = "212", .name = "212", .ipproto = 212, .reference = "[Internet_Assigned_Numbers_Authority]", }, [213] = { .description = "213", .name = "213", .ipproto = 213, .reference = "[Internet_Assigned_Numbers_Authority]", }, [214] = { .description = "214", .name = "214", .ipproto = 214, .reference = "[Internet_Assigned_Numbers_Authority]", }, [215] = { .description = "215", .name = "215", .ipproto = 215, .reference = "[Internet_Assigned_Numbers_Authority]", }, [216] = { .description = "216", .name = "216", .ipproto = 216, .reference = "[Internet_Assigned_Numbers_Authority]", }, [217] = { .description = "217", .name = "217", .ipproto = 217, .reference = "[Internet_Assigned_Numbers_Authority]", }, [218] = { .description = "218", .name = "218", .ipproto = 218, .reference = "[Internet_Assigned_Numbers_Authority]", }, [219] = { .description = "219", .name = "219", .ipproto = 219, .reference = "[Internet_Assigned_Numbers_Authority]", }, [220] = { .description = "220", .name = "220", .ipproto = 220, .reference = "[Internet_Assigned_Numbers_Authority]", }, [221] = { .description = "221", .name = "221", .ipproto = 221, .reference = "[Internet_Assigned_Numbers_Authority]", }, [222] = { .description = "222", .name = "222", .ipproto = 222, .reference = "[Internet_Assigned_Numbers_Authority]", }, [223] = { .description = "223", .name = "223", .ipproto = 223, .reference = "[Internet_Assigned_Numbers_Authority]", }, [224] = { .description = "224", .name = "224", .ipproto = 224, .reference = "[Internet_Assigned_Numbers_Authority]", }, [225] = { .description = "225", .name = "225", .ipproto = 225, .reference = "[Internet_Assigned_Numbers_Authority]", }, [226] = { .description = "226", .name = "226", .ipproto = 226, .reference = "[Internet_Assigned_Numbers_Authority]", }, [227] = { .description = "227", .name = "227", .ipproto = 227, .reference = "[Internet_Assigned_Numbers_Authority]", }, [228] = { .description = "228", .name = "228", .ipproto = 228, .reference = "[Internet_Assigned_Numbers_Authority]", }, [229] = { .description = "229", .name = "229", .ipproto = 229, .reference = "[Internet_Assigned_Numbers_Authority]", }, [230] = { .description = "230", .name = "230", .ipproto = 230, .reference = "[Internet_Assigned_Numbers_Authority]", }, [231] = { .description = "231", .name = "231", .ipproto = 231, .reference = "[Internet_Assigned_Numbers_Authority]", }, [232] = { .description = "232", .name = "232", .ipproto = 232, .reference = "[Internet_Assigned_Numbers_Authority]", }, [233] = { .description = "233", .name = "233", .ipproto = 233, .reference = "[Internet_Assigned_Numbers_Authority]", }, [234] = { .description = "234", .name = "234", .ipproto = 234, .reference = "[Internet_Assigned_Numbers_Authority]", }, [235] = { .description = "235", .name = "235", .ipproto = 235, .reference = "[Internet_Assigned_Numbers_Authority]", }, [236] = { .description = "236", .name = "236", .ipproto = 236, .reference = "[Internet_Assigned_Numbers_Authority]", }, [237] = { .description = "237", .name = "237", .ipproto = 237, .reference = "[Internet_Assigned_Numbers_Authority]", }, [238] = { .description = "238", .name = "238", .ipproto = 238, .reference = "[Internet_Assigned_Numbers_Authority]", }, [239] = { .description = "239", .name = "239", .ipproto = 239, .reference = "[Internet_Assigned_Numbers_Authority]", }, [240] = { .description = "240", .name = "240", .ipproto = 240, .reference = "[Internet_Assigned_Numbers_Authority]", }, [241] = { .description = "241", .name = "241", .ipproto = 241, .reference = "[Internet_Assigned_Numbers_Authority]", }, [242] = { .description = "242", .name = "242", .ipproto = 242, .reference = "[Internet_Assigned_Numbers_Authority]", }, [243] = { .description = "243", .name = "243", .ipproto = 243, .reference = "[Internet_Assigned_Numbers_Authority]", }, [244] = { .description = "244", .name = "244", .ipproto = 244, .reference = "[Internet_Assigned_Numbers_Authority]", }, [245] = { .description = "245", .name = "245", .ipproto = 245, .reference = "[Internet_Assigned_Numbers_Authority]", }, [246] = { .description = "246", .name = "246", .ipproto = 246, .reference = "[Internet_Assigned_Numbers_Authority]", }, [247] = { .description = "247", .name = "247", .ipproto = 247, .reference = "[Internet_Assigned_Numbers_Authority]", }, [248] = { .description = "248", .name = "248", .ipproto = 248, .reference = "[Internet_Assigned_Numbers_Authority]", }, [249] = { .description = "249", .name = "249", .ipproto = 249, .reference = "[Internet_Assigned_Numbers_Authority]", }, [250] = { .description = "250", .name = "250", .ipproto = 250, .reference = "[Internet_Assigned_Numbers_Authority]", }, [251] = { .description = "251", .name = "251", .ipproto = 251, .reference = "[Internet_Assigned_Numbers_Authority]", }, [252] = { .description = "252", .name = "252", .ipproto = 252, .reference = "[Internet_Assigned_Numbers_Authority]", }, [253] = { .description = "Use for experimentation and testing", .name = "253", .ipproto = 253, .ipv6_extension_header = true, .reference = "[RFC3692]", }, [254] = { .description = "Use for experimentation and testing", .name = "254", .ipproto = 254, .ipv6_extension_header = true, .reference = "[RFC3692]", }, [255] = { .description = "255", .name = "Reserved", .ipproto = 255, .reference = "[Internet_Assigned_Numbers_Authority]", }, }; const struct ip_protocol *protocol_by_caseeat_prefix(shunk_t *prefix) { for (unsigned ipproto = 0; ipproto < elemsof(ip_protocols); ipproto++) { const struct ip_protocol *p = &ip_protocols[ipproto]; passert(p->ipproto == ipproto); if (shunk_strcaseeat(prefix, p->prefix)) { return p; } } return NULL; } const struct ip_protocol *protocol_by_shunk(shunk_t token) { /* try the name */ for (unsigned ipproto = 0; ipproto < elemsof(ip_protocols); ipproto++) { const struct ip_protocol *p = &ip_protocols[ipproto]; passert(p->ipproto == ipproto); if (hunk_strcaseeq(token, p->name) || hunk_strcaseeq(token, p->prefix)) { return p; } } /* try the number */ uintmax_t ipproto; err_t err = shunk_to_uintmax(token, NULL, 10, &ipproto); if (err != NULL) { return NULL; /* not found */ } if (ipproto > 255) { return NULL; } return protocol_by_ipproto(ipproto); } const struct ip_protocol *protocol_by_ipproto(unsigned ipproto) { if (ipproto >= elemsof(ip_protocols)) { return NULL; } const struct ip_protocol *p = &ip_protocols[ipproto]; return p; } /* * Abstract ENUM names to work with above table? */ static const char *const ip_protocol_id_name[] = { [0] = "ALL", #define A(P) [IPPROTO_##P] = #P A(UDP), A(TCP), A(ICMP), #undef A }; enum_names ip_protocol_id_names = { 0, elemsof(ip_protocol_id_name) - 1, ARRAY_REF(ip_protocol_id_name), NULL, /* prefix */ NULL, /* next */ }; size_t jam_protocol(struct jambuf *buf, const struct ip_protocol *protocol) { return jam_string(buf, str_protocol(protocol)); } const char *str_protocol(const struct ip_protocol *protocol) { if (protocol == NULL) { return ""; } return protocol->name; } size_t jam_protocols(struct jambuf *buf, const ip_protocol *src, char sep, const ip_protocol *dst) { size_t s = 0; /* caller adds ' ' */ s += jam_char(buf, sep); s += jam_string(buf, (src == NULL ? "" : src->ipproto == 0 ? "" : src->name)); if (src != dst) { s += jam_char(buf, sep); s += jam_string(buf, (dst == NULL ? "" : dst->ipproto == 0 ? "" : dst->name)); } s += jam_char(buf, sep); s += jam_char(buf, '>'); /* caller adds ' ' */ return s; } libreswan-4.14/lib/libswan/ip_protoport.c000066400000000000000000000065521457372064200205630ustar00rootroot00000000000000/* * 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 "jambuf.h" #include "ip_protoport.h" #include "constants.h" /* for zero() */ #include "chunk.h" /* for clone_bytes_as_string() */ #include "lswlog.h" /* for pexpect() */ const ip_protoport unset_protoport; /* * ttoprotoport - converts from protocol/port string to protocol and * port */ err_t ttoprotoport(const char *src, ip_protoport *protoport) { err_t err; zero(protoport); /* get the length of the string */ size_t src_len = strlen(src); /* locate delimiter '/' between protocol and port */ char *end = strchr(src, '/'); const char *service_name; shunk_t proto_name; if (end != NULL) { /* PROT/PORT */ proto_name = shunk2(src, end - src); service_name = end + 1; } else if (streq(src, "%any")) { /* %any */ proto_name = shunk1("unknown"); service_name = src + src_len; /*NUL*/ } else { /* PROTO */ proto_name = shunk2(src, src_len); service_name = src + src_len; /*NUL*/ } /* extract protocol by trying to resolve it by name */ const struct ip_protocol *protocol; err = ttoprotocol(proto_name, &protocol); if (err != NULL) { return err; } /* is there a port wildcard? */ unsigned port; bool port_wildcard; if (service_name[0] == '\0') { /* allow N/ and N; different to N/%any */ port = 0; port_wildcard = false; } else if (streq(service_name, "%any")) { if (protocol->ipproto == 0) { return "port wildcard (%any) requires a valid protocol"; } port = 0; port_wildcard = true; } else { /* Port 0-65535 is different to %any */ err = ttoport(service_name, &port); if (err != NULL) { return err; } if (protocol->ipproto == 0 && port != 0) { return "protocol 0 must have 0 port"; } port_wildcard = false; } protoport->is_set = true; protoport->ipproto = protocol->ipproto; protoport->has_port_wildcard = port_wildcard; protoport->hport = port; return NULL; } size_t jam_protoport(struct jambuf *buf, const ip_protoport *protoport) { if (protoport == NULL) { return jam(buf, ""); } if (!protoport->is_set) { return jam(buf, ""); } if (protoport->ipproto == 0) { pexpect(protoport->has_port_wildcard == false); pexpect(protoport->hport == 0); return jam_string(buf, "%any"); } size_t s = 0; s += jam(buf, "%s/", protocol_by_ipproto(protoport->ipproto)->name); if (protoport->has_port_wildcard) { pexpect(protoport->hport == 0); s += jam_string(buf, "%any"); } else { /* 0 implies 0-65535 */ s += jam(buf, "%u", protoport->hport); } return s; } const char *str_protoport(const ip_protoport *protoport, protoport_buf *buf) { struct jambuf jambuf = ARRAY_AS_JAMBUF(buf->buf); jam_protoport(&jambuf, protoport); return buf->buf; } libreswan-4.14/lib/libswan/ip_range.c000066400000000000000000000304011457372064200175750ustar00rootroot00000000000000/* 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 "passert.h" #include "lswlog.h" /* for pexpect() */ const ip_range unset_range; /* all zeros */ ip_range range_from_raw(where_t where, enum ip_version version, const struct ip_bytes start, const struct ip_bytes end) { ip_range r = { .is_set = true, .version = version, .start = start, .end = end, }; pexpect_range(&r, where); return r; } /* * Calculate the number of significant bits in the size of the range. * floor(lg(|high-low| + 1)) */ int range_prefix_len(const ip_range range) { const struct ip_info *afi = range_type(&range); if (afi == NULL) { /* NULL+unset+unknown */ return -1; } struct ip_bytes diff = ip_bytes_sub(afi, range.end, range.start); int fsb = ip_bytes_first_set_bit(afi, diff); return fsb; } int range_host_len(const ip_range range) { const struct ip_info *afi = range_type(&range); if (afi == NULL) { /* NULL+unset+unknown */ return -1; } struct ip_bytes diff = ip_bytes_sub(afi, range.end, range.start); int fsb = ip_bytes_first_set_bit(afi, diff); return (afi->ip_size * 8) - fsb; } /* * ttorange() * * Convert "addr1-addr2" or subnet/mask to an address range. */ err_t ttorange(const char *src, const struct ip_info *afi, ip_range *dst) { *dst = unset_range; err_t err; shunk_t cursor = shunk1(src); /* START or START/MASK or START-END */ char sep = '\0'; shunk_t start_token = shunk_token(&cursor, &sep, "/-"); /* convert start address */ ip_address start_address; err = ttoaddress_num(start_token, afi/*possibly NULL*/, &start_address); if (err != NULL) { return err; } /* get real AFI */ afi = address_type(&start_address); passert(afi != NULL); switch (sep) { case '\0': { /* single address */ *dst = range_from_raw(HERE, start_address.version, start_address.bytes, start_address.bytes); return NULL; } case '/': { /* START/MASK */ uintmax_t maskbits = afi->mask_cnt; err = shunk_to_uintmax(cursor, NULL, 0, &maskbits); if (err != NULL) { return err; } if (maskbits > afi->mask_cnt) { return "too large"; } /* XXX: should this reject bad addresses */ *dst = range_from_raw(HERE, afi->ip_version, ip_bytes_from_blit(afi, start_address.bytes, /*routing-prefix*/&keep_bits, /*host-identifier*/&clear_bits, maskbits), ip_bytes_from_blit(afi, start_address.bytes, /*routing-prefix*/&keep_bits, /*host-identifier*/&set_bits, maskbits)); dst->is_subnet = (afi == &ipv6_info); return NULL; } case '-': { /* START-END */ ip_address end_address; err = ttoaddress_num(cursor, afi, &end_address); if (err != NULL) { /* includes IPv4 vs IPv6 */ return err; } passert(afi == address_type(&end_address)); if (ip_bytes_cmp(start_address.version, start_address.bytes, end_address.version, end_address.bytes) > 0) { return "start of range is greater than end"; } *dst = range_from_raw(HERE, afi->ip_version, start_address.bytes, end_address.bytes); return NULL; } default: /* SEP is invalid, but being more specific means diag_t */ return "expecting '-' or '/'"; } } size_t jam_range(struct jambuf *buf, const ip_range *range) { if (range_is_unset(range)) { return jam_string(buf, ""); } const struct ip_info *afi = range_type(range); if (afi == NULL) { return jam_string(buf, ""); } size_t s = 0; s += afi->address.jam(buf, afi, &range->start); /* when a subnet, try to calculate the prefix-bits */ int prefix_bits = (range->is_subnet ? ip_bytes_prefix_bits(afi, range->start, range->end) : -1); if (prefix_bits >= 0) { s += jam(buf, "/%d", prefix_bits); } else { s += jam(buf, "-"); s += afi->address.jam(buf, afi, &range->end); } return s; } const char *str_range(const ip_range *range, range_buf *out) { struct jambuf buf = ARRAY_AS_JAMBUF(out->buf); jam_range(&buf, range); return out->buf; } ip_range range_from_address(const ip_address address) { const struct ip_info *afi = address_type(&address); if (afi == NULL) { /* NULL+unset+unknown */ return unset_range; } return range_from_raw(HERE, address.version, address.bytes, address.bytes); } ip_range range_from_subnet(const ip_subnet subnet) { const struct ip_info *afi = subnet_type(&subnet); if (afi == NULL) { /* NULL+unset+unknown */ return unset_range; } return range_from_raw(HERE, afi->ip_version, ip_bytes_from_blit(afi, subnet.bytes, /*routing-prefix*/&keep_bits, /*host-identifier*/&clear_bits, subnet.maskbits), ip_bytes_from_blit(afi, subnet.bytes, /*routing-prefix*/&keep_bits, /*host-identifier*/&set_bits, subnet.maskbits)); } const struct ip_info *range_type(const ip_range *range) { if (range == NULL) { return NULL; } /* may return NULL */ return range_info(*range); } const struct ip_info *range_info(const ip_range range) { if (!range.is_set) { return NULL; } /* may return NULL */ return ip_version_info(range.version); } bool range_is_unset(const ip_range *range) { if (range == NULL) { return true; } return !range->is_set; } bool range_is_zero(const ip_range range) { const struct ip_info *afi = range_type(&range); if (afi == NULL) { return false; } return range_eq_range(range, afi->range.zero); } bool range_is_all(const ip_range range) { const struct ip_info *afi = range_type(&range); if (afi == NULL) { return false; } return range_eq_range(range, afi->range.all); } uintmax_t range_size(const ip_range range) { const struct ip_info *afi = range_type(&range); if (afi == NULL) { return 0; } struct ip_bytes diff_bytes = ip_bytes_sub(afi, range.end, range.start); /* more than uintmax_t-bits of host-prefix always overflows. */ unsigned prefix_bits = ip_bytes_first_set_bit(afi, diff_bytes); unsigned host_bits = afi->mask_cnt - prefix_bits; if (host_bits > sizeof(uintmax_t) * 8) { return UINTMAX_MAX; } /* * can't overflow; but could be 0xf..f and adding one will * overflow */ uintmax_t diff = ntoh_bytes(diff_bytes.byte, afi->ip_size); if (diff >= UINTMAX_MAX) { /* size+1 would overflow */ return UINTMAX_MAX; } return diff + 1; } bool range_eq_address(const ip_range range, const ip_address address) { ip_range address_range = range_from_address(address); return range_eq_range(range, address_range); } bool range_eq_subnet(const ip_range range, const ip_subnet subnet) { ip_range subnet_range = range_from_subnet(subnet); return range_eq_range(range, subnet_range); } bool range_eq_range(const ip_range l, const ip_range r) { if (range_is_unset(&l) && range_is_unset(&r)) { /* unset/NULL ranges are equal */ return true; } if (range_is_unset(&l) || range_is_unset(&r)) { return false; } return (ip_bytes_cmp(l.version, l.start, r.version, r.start) == 0 && ip_bytes_cmp(l.version, l.end, r.version, r.end) == 0); } bool address_in_range(const ip_address address, const ip_range range) { ip_range address_range = range_from_address(address); return range_in_range(address_range, range); } bool subnet_in_range(const ip_subnet subnet, const ip_range range) { ip_range subnet_range = range_from_subnet(subnet); return range_in_range(subnet_range, range); } bool range_in_range(const ip_range inner, const ip_range outer) { if (range_is_unset(&inner) || range_is_unset(&outer)) { return false; } return (ip_bytes_cmp(inner.version, inner.start, outer.version, outer.start) >= 0 && ip_bytes_cmp(inner.version, inner.end, outer.version, outer.end) <= 0); } ip_address range_start(const ip_range range) { const struct ip_info *afi = range_type(&range); if (afi == NULL) { return unset_address; } return address_from_raw(HERE, range.version, range.start); } ip_address range_end(const ip_range range) { const struct ip_info *afi = range_type(&range); if (afi == NULL) { return unset_address; } return address_from_raw(HERE, range.version, range.end); } bool range_overlaps_range(const ip_range l, const ip_range r) { if (range_is_unset(&l) || range_is_unset(&r)) { /* presumably overlap is bad */ return false; } /* l before r */ if (ip_bytes_cmp(l.version, l.end, r.version, r.start) < 0) { return false; } /* l after r */ if (ip_bytes_cmp(l.version, l.start, r.version, r.end) > 0) { return false; } return true; } err_t addresses_to_nonzero_range(const ip_address start, const ip_address end, ip_range *dst) { *dst = unset_range; if (address_is_unset(&start)) { /* NULL+unset+unknown */ return "start address invalid"; } if (address_is_unset(&end)) { /* NULL+unset+unknown */ return "end address invalid"; } if (start.version != end.version) { return "conflicting address types"; } /* reject both 0 */ if (thingeq(start.bytes, unset_ip_bytes) && thingeq(end.bytes, unset_ip_bytes)) { return "zero address range"; } if (addrcmp(&start, &end) > 0) { return "out-of-order"; } *dst = range_from_raw(HERE, start.version, start.bytes, end.bytes); return NULL; } err_t range_to_subnet(const ip_range range, ip_subnet *dst) { *dst = unset_subnet; const struct ip_info *afi = range_type(&range); if (afi == NULL) { return "invalid range"; } /* * Determine the prefix_bits (the CIDR network part) by * matching leading bits of FROM and TO. Trailing bits * (subnet address) must be either all 0 (from) or 1 (to). */ int prefix_bits = ip_bytes_prefix_bits(afi, range.start, range.end); if (prefix_bits < 0) { return "address range is not a subnet"; } *dst = subnet_from_raw(HERE, afi->ip_version, range.start, prefix_bits); return NULL; } err_t range_offset_to_address(const ip_range range, uintmax_t offset, ip_address *address) { *address = unset_address; const struct ip_info *afi = range_type(&range); if (afi == NULL) { return "invalid range"; } int carry = 0; struct ip_bytes sum = unset_ip_bytes;/*be safe*/ for (int j = afi->ip_size - 1; j >= 0; j--) { /* extract the next byte to add */ unsigned add = offset & 0xff; offset >>= 8; /* update */ unsigned val = range.start.byte[j] + add + carry; carry = val > 0xff; sum.byte[j] = val; /* truncates */ } if (offset > 0) { return "offset overflow"; } if (carry > 0) { return "address overflow"; } ip_address tmp = address_from_raw(HERE, range.version, sum); if (!address_in_range(tmp, range)) { return "range overflow"; } *address = tmp; return NULL; } err_t address_to_range_offset(const ip_range range, const ip_address address, uintmax_t *offset) { *offset = UINTMAX_MAX; const struct ip_info *afi = range_type(&range); if (afi == NULL) { return "range invalid"; } if (address_type(&address) != afi) { return "address is not from range"; } if (!address_in_range(address, range)) { return "address out-of-bounds"; } struct ip_bytes diff = ip_bytes_sub(afi, address.bytes, range.start); *offset = ntoh_bytes(diff.byte, afi->ip_size); if (*offset == UINTMAX_MAX) { return "offset overflow"; } return NULL; } void pexpect_range(const ip_range *r, where_t where) { if (r == NULL) { return; } /* more strict than is_unset() */ if (range_eq_range(*r, unset_range)) { return; } if (r->is_set == false || r->version == 0 || ip_bytes_cmp(r->version, r->start, r->version, r->end) > 0) { llog_pexpect(&global_logger, where, "invalid range: "PRI_RANGE, pri_range(r)); } } libreswan-4.14/lib/libswan/ip_said.c000066400000000000000000000076021457372064200174300ustar00rootroot00000000000000/* 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 "ip_info.h" #include "jambuf.h" const ip_said unset_said; ip_said said_from_raw(where_t where UNUSED, enum ip_version version, const struct ip_bytes dst, const struct ip_protocol *protocol, ipsec_spi_t spi) { ip_said said = { .is_set = true, .version = version, .dst = dst, .ipproto = protocol->ipproto, .spi = spi, }; return said; } ip_said said_from_address_protocol_spi(const ip_address address, const struct ip_protocol *protocol, ipsec_spi_t spi) { return said_from_raw(HERE, address.version, address.bytes, protocol, spi); } bool said_is_unset(const ip_said *said) { if (said == NULL) { return true; } return !said->is_set; } /* * convert SA to text "ah507@1.2.3.4" */ size_t jam_said(struct jambuf *buf, const ip_said *said) { if (!said->is_set) { return jam_string(buf, ""); } if (said->ipproto == ip_protocol_internal.ipproto) { switch (ntohl(said->spi)) { case SPI_PASS: return jam_string(buf, "%pass"); case SPI_DROP: return jam_string(buf, "%drop"); case SPI_REJECT: return jam_string(buf, "%reject"); case SPI_HOLD: return jam_string(buf, "%hold"); case SPI_TRAP: return jam_string(buf, "%trap"); case SPI_IGNORE: return jam_string(buf, "%ignore"); case SPI_TRAPSUBNET: return jam_string(buf, "%trapsubnet"); default: #if 0 return jam(buf, "%s-"PRI_IPSEC_SPI, "%unk", pri_ipsec_spi(said->spi)); #else return jam(buf, "%s-%d", "%unk", ntohl(said->spi)); #endif } } const struct ip_info *afi = said_type(said); if (afi == NULL) { return jam(buf, "ipproto); if (proto == &ip_protocol_ipip/*TUN*/ && said->spi == PASSTHROUGHSPI && /* any zero */ thingeq(said->dst, unset_ip_bytes)) { return jam_string(buf, (afi == &ipv4_info ? PASSTHROUGH4NAME : afi == &ipv6_info ? PASSTHROUGH6NAME : ""));; } /* general case needed */ size_t s = 0; s += jam_string(buf, proto->prefix != NULL ? proto->prefix : proto->name); /* .SPI */ s += jam_char(buf, (afi == &ipv4_info ? '.' : afi == &ipv6_info ? ':' : '?')); s += jam(buf, "%x", ntohl(said->spi));; s += jam_char(buf, '@'); s += afi->address.jam(buf, afi, &said->dst); return s; } const char *str_said(const ip_said *said, said_buf *buf) { struct jambuf b = ARRAY_AS_JAMBUF(buf->buf); jam_said(&b, said); return buf->buf; } const struct ip_info *said_type(const ip_said *said) { if (said == NULL) { return NULL; } /* may return NULL */ return said_info(*said); } const struct ip_info *said_info(const ip_said said) { if (!said.is_set) { return NULL; } /* may return NULL */ return ip_version_info(said.version); } ip_address said_address(const ip_said said) { const struct ip_info *afi = said_type(&said); if (afi == NULL) { /* NULL+unset+unknown */ return unset_address; /* empty_address? */ } return address_from_raw(HERE, said.version, said.dst); } const struct ip_protocol *said_protocol(const ip_said said) { if (said_is_unset(&said)) { return NULL; } return protocol_by_ipproto(said.ipproto); } libreswan-4.14/lib/libswan/ip_selector.c000066400000000000000000000442471457372064200203360ustar00rootroot00000000000000/* ip selector, for libreswan * * Copyright (C) 2020 Andrew Cagney * Copyright (C) 2000 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 "lswlog.h" #include "ip_selector.h" #include "ip_info.h" const ip_selector unset_selector; bool selector_is_unset(const ip_selector *selector) { if (selector == NULL) { return true; } return !selector->is_set; } bool selector_is_zero(const ip_selector selector) { const struct ip_info *afi = selector_type(&selector); if (afi == NULL) { /* NULL+unset+unknown+any */ return false; } /* ::/128 or 0.0.0.0/32 */ return selector_eq_selector(selector, afi->selector.zero); } bool selector_is_all(const ip_selector selector) { const struct ip_info *afi = selector_type(&selector); if (afi == NULL) { /* NULL+unset+unknown+any */ return false; } /* ::/0 or 0.0.0.0/0 */ return selector_eq_selector(selector, afi->selector.all); } bool selector_contains_one_address(const ip_selector selector) { const struct ip_info *afi = selector_type(&selector); if (afi == NULL) { /* NULL+unset+unknown */ return false; } /* Unlike subnetishost() this rejects 0.0.0.0/32. */ return (!thingeq(selector.bytes, unset_ip_bytes) && selector.maskbits == afi->mask_cnt && selector.ipproto == 0 && selector.hport == 0); } size_t jam_selector(struct jambuf *buf, const ip_selector *selector) { if (selector == NULL) { return jam_string(buf, ""); } if (!selector->is_set) { return jam(buf, PRI_SELECTOR, pri_selector(selector)); } const struct ip_info *afi = selector_type(selector); if (afi == NULL) { return jam(buf, PRI_SELECTOR, pri_selector(selector)); } size_t s = 0; ip_address sa = selector_prefix(*selector); s += jam_address(buf, &sa); s += jam(buf, "/%u", selector->maskbits); if (selector->ipproto != 0 || selector->hport != 0) { s += jam(buf, ":"); s += jam(buf, "%s/", selector_protocol(*selector)->name); if (selector->hport == 0) { s += jam_string(buf, "0-65535"); } else { s += jam(buf, "%d", selector->hport); } } return s; } const char *str_selector(const ip_selector *selector, selector_buf *out) { struct jambuf buf = ARRAY_AS_JAMBUF(out->buf); jam_selector(&buf, selector); return out->buf; } size_t jam_selector_subnet(struct jambuf *buf, const ip_selector *selector) { if (selector_is_unset(selector)) { return jam(buf, PRI_SELECTOR, pri_selector(selector)); } ip_address address = selector_prefix(*selector); unsigned prefix_bits = selector_prefix_bits(*selector); ip_subnet subnet = subnet_from_address_prefix_bits(address, prefix_bits); return jam_subnet(buf, &subnet); } const char *str_selector_subnet(const ip_selector *selector, subnet_buf *out) { struct jambuf buf = ARRAY_AS_JAMBUF(out->buf); jam_selector_subnet(&buf, selector); return out->buf; } size_t jam_selector_subnet_port(struct jambuf *buf, const ip_selector *selector) { if (selector_is_unset(selector)) { return jam_string(buf, ""); } const struct ip_info *afi = selector_type(selector); if (afi == NULL) { return jam_string(buf, ""); } size_t s = 0; ip_address sa = selector_prefix(*selector); s += jam_address(buf, &sa); s += jam(buf, "/%u", selector->maskbits); if (selector->ipproto != 0 || selector->hport != 0) { s += jam(buf, ":%d", selector->hport); } return s; } const char *str_selector_subnet_port(const ip_selector *selector, selector_buf *out) { struct jambuf buf = ARRAY_AS_JAMBUF(out->buf); jam_selector_subnet_port(&buf, selector); return out->buf; } size_t jam_selectors(struct jambuf *buf, const ip_selector *src, const ip_selector *dst) { if (selector_is_unset(src) || selector_is_unset(dst)) { return jam_string(buf, ""); } const struct ip_protocol *srcp = selector_protocol(*src); const struct ip_protocol *dstp = selector_protocol(*dst); size_t s = 0; s += jam_selector_subnet_port(buf, src); s += jam_char(buf, ' '); s += jam_protocols(buf, srcp, '-', dstp); s += jam_char(buf, ' '); s += jam_selector_subnet_port(buf, dst); return s; } const char *str_selectors(const ip_selector *src, const ip_selector *dst, selectors_buf *out) { struct jambuf buf = ARRAY_AS_JAMBUF(out->buf); jam_selectors(&buf, src, dst); return out->buf; } size_t jam_selectors_sensitive(struct jambuf *buf, const ip_selector *src, const ip_selector *dst) { if(!log_ip) { return jam_string(buf, " -> "); } return jam_selectors(buf, src, dst); } const char *str_selectors_sensitive(const ip_selector *src, const ip_selector *dst, selectors_buf *out) { struct jambuf buf = ARRAY_AS_JAMBUF(out->buf); jam_selectors_sensitive(&buf, src, dst); return out->buf; } ip_selector selector_from_raw(where_t where, enum ip_version version, const struct ip_bytes bytes, unsigned prefix_bits, const struct ip_protocol *protocol, const ip_port port) { ip_selector selector = { .is_set = true, .maskbits = prefix_bits, .version = version, .bytes = bytes, .ipproto = protocol->ipproto, .hport = port.hport, }; pexpect_selector(&selector, where); return selector; } ip_selector selector_from_address(const ip_address address) { const struct ip_info *afi = address_type(&address); if (afi == NULL) { return unset_selector; } return selector_from_raw(HERE, address.version, address.bytes, afi->mask_cnt, &ip_protocol_all, unset_port); } ip_selector selector_from_address_protocol(const ip_address address, const struct ip_protocol *protocol) { const struct ip_info *afi = address_type(&address); if (afi == NULL) { return unset_selector; } return selector_from_raw(HERE, address.version, address.bytes, afi->mask_cnt, protocol, unset_port); } ip_selector selector_from_address_protocol_port(const ip_address address, const struct ip_protocol *protocol, const ip_port port) { const struct ip_info *afi = address_type(&address); if (afi == NULL) { return unset_selector; } return selector_from_raw(HERE, address.version, address.bytes, afi->mask_cnt, protocol, port); } ip_selector selector_from_endpoint(const ip_endpoint endpoint) { const struct ip_info *afi = endpoint_type(&endpoint); if (afi == NULL) { return unset_selector; } return selector_from_raw(HERE, endpoint.version, endpoint.bytes, afi->mask_cnt, endpoint_protocol(endpoint), endpoint_port(endpoint)); } ip_selector selector_from_subnet(const ip_subnet subnet) { if (subnet_is_unset(&subnet)) { return unset_selector; } return selector_from_raw(HERE, subnet.version, subnet.bytes, subnet.maskbits, &ip_protocol_all, unset_port); } ip_selector selector_from_subnet_protocol_port(const ip_subnet subnet, const struct ip_protocol *protocol, const ip_port port) { if (subnet_is_unset(&subnet)) { return unset_selector; } return selector_from_raw(HERE, subnet.version, subnet.bytes, subnet.maskbits, protocol, port); } ip_selector selector_from_range(const ip_range range) { return selector_from_range_protocol_port(range, &ip_protocol_all, unset_port); } ip_selector selector_from_range_protocol_port(const ip_range range, const struct ip_protocol *protocol, const ip_port port) { if (range_is_unset(&range)) { return unset_selector; } ip_subnet subnet; happy(range_to_subnet(range, &subnet)); return selector_from_raw(HERE, subnet.version, subnet.bytes, subnet.maskbits, protocol, port); } ip_selector selector_from_address_protoport(const ip_address address, const ip_protoport protoport) { if (address_is_unset(&address)) { return unset_selector; } ip_subnet subnet = subnet_from_address(address); return selector_from_subnet_protoport(subnet, protoport); } ip_selector selector_from_subnet_protoport(const ip_subnet subnet, const ip_protoport protoport) { const struct ip_protocol *protocol = protocol_by_ipproto(protoport.ipproto); const ip_port port = ip_hport(protoport.hport); return selector_from_subnet_protocol_port(subnet, protocol, port); } const struct ip_info *selector_type(const ip_selector *selector) { if (selector == NULL) { return NULL; } /* may return NULL */ return selector_info(*selector); } const struct ip_info *selector_info(const ip_selector selector) { if (!selector.is_set) { return NULL; } /* may return NULL */ return ip_version_info(selector.version); } ip_port selector_port(const ip_selector selector) { if (selector_is_unset(&selector)) { return unset_port; } return ip_hport(selector.hport); } const ip_protocol *selector_protocol(const ip_selector selector) { if (selector_is_unset(&selector)) { return NULL; } return protocol_by_ipproto(selector.ipproto); } ip_range selector_range(const ip_selector selector) { const struct ip_info *afi = selector_type(&selector); if (afi == NULL) { /* NULL+unset+unknown */ return unset_range; } struct ip_bytes start = ip_bytes_from_blit(afi, selector.bytes, /*routing-prefix*/&keep_bits, /*host-identifier*/&clear_bits, selector.maskbits); struct ip_bytes end = ip_bytes_from_blit(afi, selector.bytes, /*routing-prefix*/&keep_bits, /*host-identifier*/&set_bits, selector.maskbits); return range_from_raw(HERE, afi->ip_version, start, end); } ip_address selector_prefix(const ip_selector selector) { const struct ip_info *afi = selector_type(&selector); if (afi == NULL) { /* NULL+unset+unknown */ return unset_address; } return address_from_raw(HERE, selector.version, selector.bytes); } unsigned selector_prefix_bits(const ip_selector selector) { return selector.maskbits; } ip_address selector_prefix_mask(const ip_selector selector) { const struct ip_info *afi = selector_type(&selector); if (afi == NULL) { /* NULL+unset+unknown */ return unset_address; } struct ip_bytes prefix = ip_bytes_from_blit(afi, selector.bytes, /*routing-prefix*/ &set_bits, /*host-identifier*/ &clear_bits, selector.maskbits); return address_from_raw(HERE, afi->ip_version, prefix); } bool selector_eq_address(const ip_selector selector, const ip_address address) { ip_selector s = selector_from_address(address); return selector_eq_selector(selector, s); } bool selector_eq_endpoint(const ip_selector selector, const ip_endpoint endpoint) { ip_selector es = selector_from_endpoint(endpoint); return selector_eq_selector(selector, es); } bool selector_eq_subnet(const ip_selector selector, const ip_subnet subnet) { ip_selector ss = selector_from_subnet(subnet); return selector_eq_selector(selector, ss); } bool selector_eq_range(const ip_selector selector, const ip_range range) { ip_selector s = selector_from_range(range); return selector_eq_selector(selector, s); } bool address_in_selector(const ip_address address, const ip_selector selector) { ip_selector as = selector_from_address(address); return selector_in_selector(as, selector); } bool subnet_in_selector(const ip_subnet subnet, const ip_selector selector) { ip_selector ss = selector_from_subnet(subnet); return selector_in_selector(ss, selector); } bool range_in_selector(const ip_range range, const ip_selector selector) { ip_selector rs = selector_from_range(range); return selector_in_selector(rs, selector); } bool selector_in_selector(const ip_selector i, const ip_selector o) { const struct ip_info *afi = selector_type(&i); if (afi == NULL) { /* NULL+unset+unknown */ return false; } /* version wild card? (actually version is 4/6) */ /* work in */ if (selector_type(&o) != afi) { return false; } /* more maskbits => more prefix & smaller subnet */ if (i.maskbits < o.maskbits) { return false; } /* ib=i.prefix[0 .. o.bits] == ob=o.prefix[0 .. o.bits] */ struct ip_bytes ib = ip_bytes_from_blit(afi, /*INNER*/i.bytes, /*routing-prefix*/&keep_bits, /*host-identifier*/&clear_bits, /*OUTER*/o.maskbits); if (!thingeq(ib, o.bytes)) { return false; } /* protocol wildcards */ if (o.ipproto != 0 && i.ipproto != o.ipproto) { return false; } /* port wildcard; XXX: assumes UDP/TCP */ if (o.hport != 0 && i.hport != o.hport) { return false; } return true; } bool address_in_selector_range(const ip_address address, const ip_selector selector) { if (address_is_unset(&address) || selector_is_unset(&selector)) { return false; } ip_subnet subnet = selector_subnet(selector); return address_in_subnet(address, subnet); } bool endpoint_in_selector(const ip_endpoint endpoint, const ip_selector selector) { if (endpoint_is_unset(&endpoint) || selector_is_unset(&selector)) { return false; } ip_selector inner = selector_from_endpoint(endpoint); return selector_in_selector(inner, selector); } bool selector_eq_selector(const ip_selector l, const ip_selector r) { if (selector_is_unset(&l) && selector_is_unset(&r)) { /* NULL/unset selectors are equal */ return true; } if (selector_is_unset(&l) || selector_is_unset(&r)) { return false; } /* must compare individual fields */ return (l.version == r.version && thingeq(l.bytes, r.bytes) && l.maskbits == r.maskbits && l.ipproto == r.ipproto && l.hport == r.hport); } bool selector_overlaps_selector(const ip_selector l, const ip_selector r) { /* since these are just subnets */ return (selector_in_selector(l, r) || selector_in_selector(r, l)); } void pexpect_selector(const ip_selector *s, where_t where) { if (s == NULL) { return; } /* more strict than is_unset() */ if (selector_eq_selector(*s, unset_selector)) { return; } if (s->is_set == false || s->version == 0) { llog_pexpect(&global_logger, where, "invalid selector: "PRI_SELECTOR, pri_selector(s)); } } int selector_hport(const ip_selector s) { return s.hport; } /* * Parse the selector: * *
*
/ *
/:/ <- NOTE *
/:/ * * new syntax required for: * *
-
:/- * */ err_t numeric_to_selector(shunk_t input, const struct ip_info *afi, /* could be NULL */ ip_selector *dst) { err_t oops; /* *
/ ... */ char address_term; shunk_t address_token = shunk_token(&input, &address_term, "/"); /* fprintf(stderr, "address="PRI_SHUNK"\n", pri_shunk(address_token)); */ ip_address address; oops = ttoaddress_num(address_token, afi/*possibly NULL*/, &address); if (oops != NULL) { return oops; } if (afi == NULL) { afi = address_type(&address); } if (!pexpect(afi != NULL)) { return "confused address family"; } /* * ... : ... */ char prefix_bits_term; shunk_t prefix_bits_token = shunk_token(&input, &prefix_bits_term, ":"); /* fprintf(stderr, "prefix-bits="PRI_SHUNK"\n", pri_shunk(prefix_bits_token)); */ uintmax_t prefix_bits = afi->mask_cnt; if (prefix_bits_token.len > 0) { oops = shunk_to_uintmax(prefix_bits_token, NULL, 0, &prefix_bits); if (oops != NULL) { return oops; } if (prefix_bits > afi->mask_cnt) { return "too large"; } } else if (prefix_bits_token.ptr != NULL) { /* found but empty */ pexpect(prefix_bits_token.len == 0); return "missing prefix bit size"; } struct ip_bytes host = ip_bytes_from_blit(afi, address.bytes, /*routing-prefix*/&clear_bits, /*host-identifier*/&keep_bits, prefix_bits); if (!thingeq(host, unset_ip_bytes)) { return "host-identifier must be zero"; } /* * ... / ... */ char protocol_term; shunk_t protocol_token = shunk_token(&input, &protocol_term, "/"); /* fprintf(stderr, "protocol="PRI_SHUNK"\n", pri_shunk(protocol_token)); */ const ip_protocol *protocol = &ip_protocol_all; /*0*/ if (protocol_token.len > 0) { if (protocol_term != '/') { return "protocol must be followed by '/'"; } protocol = protocol_by_shunk(protocol_token); if (protocol == NULL) { return "unknown protocol"; } } else if (protocol_token.ptr != NULL) { /* found but empty */ pexpect(protocol_token.len == 0); return "missing protocol/port following ':'"; } /* * ... */ shunk_t port_token = input; /* fprintf(stderr, "port="PRI_SHUNK"\n", pri_shunk(port_token)); */ ip_port port = unset_port; if (port_token.len > 0) { uintmax_t hport; err_t oops = shunk_to_uintmax(port_token, NULL, 0, &hport); if (oops != NULL) { return oops; } if (hport > 65535) { return "too large"; } if (protocol == &ip_protocol_all && hport != 0) { return "a non-zero port requires a valid protocol"; } port = ip_hport(hport); } else if (port_token.ptr != NULL) { /* found but empty */ pexpect(port_token.len == 0); return "missing port following protocol/"; } ip_subnet subnet = subnet_from_address_prefix_bits(address, prefix_bits); *dst = selector_from_subnet_protocol_port(subnet, protocol, port); return NULL; } ip_subnet selector_subnet(const ip_selector selector) { ip_address address = selector_prefix(selector); unsigned prefix_bits = selector_prefix_bits(selector); return subnet_from_address_prefix_bits(address, prefix_bits); } bool selector_range_eq_selector_range(const ip_selector lhs, const ip_selector rhs) { if (selector_is_unset(&lhs) || selector_is_unset(&rhs)) { return false; } ip_range lhs_range = selector_range(lhs); ip_range rhs_range = selector_range(rhs); return range_eq_range(lhs_range, rhs_range); } bool selector_range_in_selector_range(const ip_selector lhs, const ip_selector rhs) { if (selector_is_unset(&lhs) || selector_is_unset(&rhs)) { return false; } ip_subnet lhs_subnet = selector_subnet(lhs); ip_subnet rhs_subnet = selector_subnet(rhs); return subnet_in_subnet(lhs_subnet, rhs_subnet); } bool selector_range_eq_address(const ip_selector selector, const ip_address address) { if (address_is_unset(&address) || selector_is_unset(&selector)) { return false; } ip_subnet subnet = selector_subnet(selector); return subnet_eq_address(subnet, address); } libreswan-4.14/lib/libswan/ip_sockaddr.c000066400000000000000000000063051457372064200203010ustar00rootroot00000000000000/* 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 "ip_sockaddr.h" #include "ip_info.h" #include "lswlog.h" /* for bad_case() */ const ip_sockaddr unset_sockaddr; err_t sockaddr_to_address_port(const struct sockaddr *unaligned_sa, size_t len, ip_address *address, ip_port *port) { /* always clear; both are optional */ if (address != NULL) { *address = unset_address; } if (port != NULL) { *port = unset_port; } /* * Move to an aligned structure. * * UNALIGNED_SA can point into a raw buffer. LEN indicates * the max number of bytes that can be safely read. * * XXX: use PMIN(), and not min(), to avoid gcc/102288. */ ip_sockaddr sa = { .len = PMIN(len, sizeof(sa.sa)), }; memcpy(&sa.sa, unaligned_sa, sa.len); socklen_t min_len = offsetof(struct sockaddr, sa_family) + sizeof(sa_family_t); if (sa.len < min_len) { return "too small"; } const struct ip_info *afi = aftoinfo(sa.sa.sa.sa_family); if (afi == NULL) { return "unexpected address family"; } if (sa.len < afi->sockaddr_size) { return "address truncated"; } if (address != NULL) { *address = afi->address_from_sockaddr(sa); } if (port != NULL) { *port = afi->port_from_sockaddr(sa); } return NULL; } /* * Construct and return a sockaddr structure. */ ip_sockaddr sockaddr_from_address_port(const ip_address address, ip_port port) { if (address_is_unset(&address)) { return unset_sockaddr; } const struct ip_info *afi = address_type(&address); shunk_t src_addr = address_as_shunk(&address); chunk_t dst_addr; ip_sockaddr sa = unset_sockaddr; switch (afi->af) { case AF_INET: sa.sa.sin.sin_family = afi->af; sa.sa.sin.sin_port = nport(port); dst_addr = THING_AS_CHUNK(sa.sa.sin.sin_addr); #ifdef USE_SOCKADDR_LEN sa.sa.sin.sin_len = sizeof(struct sockaddr_in); #endif break; case AF_INET6: sa.sa.sin6.sin6_family = afi->af; sa.sa.sin6.sin6_port = nport(port); dst_addr = THING_AS_CHUNK(sa.sa.sin6.sin6_addr); #ifdef USE_SOCKADDR_LEN sa.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); sa.len = afi->sockaddr_size; return sa; } ip_sockaddr sockaddr_from_address(const ip_address address) { return sockaddr_from_address_port(address, unset_port); } ip_sockaddr sockaddr_from_endpoint(const ip_endpoint endpoint) { if (endpoint_is_unset(&endpoint)) { return unset_sockaddr; } return sockaddr_from_address_port(endpoint_address(endpoint), endpoint_port(endpoint)); } libreswan-4.14/lib/libswan/ip_subnet.c000066400000000000000000000163611457372064200200120ustar00rootroot00000000000000/* 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-2020 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 "passert.h" #include "lswlog.h" /* for pexpect() */ #include "ip_info.h" const ip_subnet unset_subnet; /* all zeros */ ip_subnet subnet_from_raw(where_t where, enum ip_version version, const struct ip_bytes bytes, unsigned prefix_bits) { ip_subnet s = { .is_set = true, .version = version, .bytes = bytes, .maskbits = prefix_bits, }; pexpect_subnet(&s, where); return s; } ip_subnet subnet_from_address_prefix_bits(const ip_address address, unsigned prefix_bits) { if (address_is_unset(&address)) { return unset_subnet; } return subnet_from_raw(HERE, address.version, address.bytes, prefix_bits); } ip_subnet subnet_from_address(const ip_address address) { const struct ip_info *afi = address_type(&address); if (afi == NULL) { return unset_subnet; } return subnet_from_raw(HERE, afi->ip_version, address.bytes, afi->mask_cnt); } err_t address_mask_to_subnet(const ip_address address, const ip_address mask, ip_subnet *subnet) { *subnet = unset_subnet; const struct ip_info *afi = address_type(&address); if (afi == NULL) { return "invalid address"; } if (address_type(&mask) != afi) { return "invalid mask"; } int prefix_bits = masktocount(&mask); if (prefix_bits < 0) { return "invalid mask"; } struct ip_bytes prefix = ip_bytes_from_blit(afi, address.bytes, /*routing-prefix*/&keep_bits, /*host-identifier*/&clear_bits, prefix_bits); *subnet = subnet_from_raw(HERE, afi->ip_version, prefix, prefix_bits); return NULL; } ip_address subnet_prefix(const ip_subnet subnet) { const struct ip_info *afi = subnet_type(&subnet); if (afi == NULL) { /* NULL+unset+unknown */ return unset_address; } struct ip_bytes prefix = ip_bytes_from_blit(afi, subnet.bytes, /*routing-prefix*/&keep_bits, /*host-identifier*/&clear_bits, subnet.maskbits); return address_from_raw(HERE, afi->ip_version, prefix); } const struct ip_info *subnet_type(const ip_subnet *subnet) { if (subnet == NULL) { return NULL; } /* may return NULL */ return subnet_info(*subnet); } const struct ip_info *subnet_info(const ip_subnet subnet) { if (!subnet.is_set) { return NULL; } /* may return NULL */ return ip_version_info(subnet.version); } bool subnet_is_unset(const ip_subnet *subnet) { if (subnet == NULL) { return true; } return !subnet->is_set; } bool subnet_is_zero(const ip_subnet subnet) { const struct ip_info *afi = subnet_type(&subnet); if (afi == NULL) { /* NULL+unset+unknown */ return false; } return subnet_eq_subnet(subnet, afi->subnet.zero); } bool subnet_is_all(const ip_subnet subnet) { const struct ip_info *afi = subnet_type(&subnet); if (afi == NULL) { /* NULL+unset+unknown */ return false; } return subnet_eq_subnet(subnet, afi->subnet.all); } uintmax_t subnet_size(const ip_subnet subnet) { ip_range range = range_from_subnet(subnet); return range_size(range); } /* * 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_prefix_mask(const ip_subnet subnet) { const struct ip_info *afi = subnet_type(&subnet); if (afi == NULL) { /* NULL+unset+unknown */ return unset_address; } struct ip_bytes mask = ip_bytes_from_blit(afi, subnet.bytes, /*routing-prefix*/ &set_bits, /*host-identifier*/ &clear_bits, subnet.maskbits); return address_from_raw(HERE, afi->ip_version, mask); } unsigned subnet_prefix_bits(const ip_subnet subnet) { return subnet.maskbits; } size_t jam_subnet(struct jambuf *buf, const ip_subnet *subnet) { if (subnet_is_unset(subnet)) { return jam_string(buf, ""); } const struct ip_info *afi = subnet_type(subnet); if (afi == NULL) { return jam_string(buf, ""); } size_t s = 0; ip_address sa = subnet_prefix(*subnet); s += jam_address(buf, &sa); /* sensitive? */ s += jam(buf, "/%u", subnet->maskbits); return s; } const char *str_subnet(const ip_subnet *subnet, subnet_buf *out) { struct jambuf buf = ARRAY_AS_JAMBUF(out->buf); jam_subnet(&buf, subnet); return out->buf; } void pexpect_subnet(const ip_subnet *s, where_t where) { if (s == NULL) { return; } /* more strict than is_unset() */ if (subnet_eq_subnet(*s, unset_subnet)) { return; } if (s->is_set == false || s->version == 0) { llog_pexpect(&global_logger, where, "invalid subnet: "PRI_SUBNET, pri_subnet(s)); } } bool subnet_eq_subnet(const ip_subnet l, const ip_subnet r) { if (subnet_is_unset(&l) && subnet_is_unset(&r)) { /* NULL/unset subnets are equal */ return true; } if (subnet_is_unset(&l) || subnet_is_unset(&r)) { return false; } /* must compare individual fields */ return (l.version == r.version && thingeq(l.bytes, r.bytes) && l.maskbits == r.maskbits); } bool subnet_eq_address(const ip_subnet subnet, const ip_address address) { const struct ip_info *afi = subnet_type(&subnet); if (afi == NULL) { return false; } /* XXX: reject any? */ /* must compare individual fields */ return (subnet.version == address.version && thingeq(subnet.bytes, address.bytes) && subnet.maskbits == afi->mask_cnt); } bool subnet_in_subnet(const ip_subnet l, const ip_subnet r) { const struct ip_info *afi = subnet_type(&l); if (afi == NULL) { return false; } if (subnet_type(&r) != afi) { return false; } /* l's prefix needs to be longer than r's */ if (l.maskbits < r.maskbits) { return false; } /* L.prefix[0 .. R.bits] == R.prefix[0.. R.bits] */ struct ip_bytes lb = ip_bytes_from_blit(afi, /*LEFT*/l.bytes, /*routing-prefix*/&keep_bits, /*host-identifier*/&clear_bits, /*RIGHT*/r.maskbits); return thingeq(lb, r.bytes); } bool address_in_subnet(const ip_address l, const ip_subnet r) { const struct ip_info *afi = address_type(&l); if (afi == NULL) { return false; } if (subnet_type(&r) != afi) { return false; } /* L.prefix[0 .. R.bits] == R.prefix[0.. R.bits] */ struct ip_bytes lb = ip_bytes_from_blit(afi, /*LEFT*/l.bytes, /*routing-prefix*/&keep_bits, /*host-identifier*/&clear_bits, /*RIGHT*/r.maskbits); return thingeq(lb, r.bytes); } err_t addresses_to_nonzero_subnet(const ip_address start, const ip_address end, ip_subnet *dst) { *dst = unset_subnet; ip_range range; err_t err = addresses_to_nonzero_range(start, end, &range); if (err != NULL) { return err; } return range_to_subnet(range, dst); } libreswan-4.14/lib/libswan/ipsec_addrbytesof.3000066400000000000000000000000321457372064200214170ustar00rootroot00000000000000.so man3/ipsec_initaddr.3 libreswan-4.14/lib/libswan/ipsec_addrbytesptr.3000066400000000000000000000000321457372064200216200ustar00rootroot00000000000000.so man3/ipsec_initaddr.3 libreswan-4.14/lib/libswan/ipsec_addrcmp.3000066400000000000000000000000321457372064200205230ustar00rootroot00000000000000.so man3/ipsec_sameaddr.3 libreswan-4.14/lib/libswan/ipsec_addrinsubnet.3000066400000000000000000000000321457372064200215730ustar00rootroot00000000000000.so man3/ipsec_sameaddr.3 libreswan-4.14/lib/libswan/ipsec_addrlenof.3000066400000000000000000000000321457372064200210470ustar00rootroot00000000000000.so man3/ipsec_initaddr.3 libreswan-4.14/lib/libswan/ipsec_addrtoa.3000066400000000000000000000000311457372064200205260ustar00rootroot00000000000000.so man3/ipsec_atoaddr.3 libreswan-4.14/lib/libswan/ipsec_addrtosubnet.3000066400000000000000000000000341457372064200216110ustar00rootroot00000000000000.so man3/ipsec_initsubnet.3 libreswan-4.14/lib/libswan/ipsec_addrtot.3000066400000000000000000000000311457372064200205510ustar00rootroot00000000000000.so man3/ipsec_ttoaddr.3 libreswan-4.14/lib/libswan/ipsec_addrtypeof.3000066400000000000000000000000321457372064200212520ustar00rootroot00000000000000.so man3/ipsec_initaddr.3 libreswan-4.14/lib/libswan/ipsec_atoasr.3000066400000000000000000000135431457372064200204150ustar00rootroot00000000000000'\" 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-4.14/lib/libswan/ipsec_atosubnet.3000066400000000000000000000000311457372064200211140ustar00rootroot00000000000000.so man3/ipsec_atoaddr.3 libreswan-4.14/lib/libswan/ipsec_bitstomask.3000066400000000000000000000000321457372064200212710ustar00rootroot00000000000000.so man3/ipsec_goodmask.3 libreswan-4.14/lib/libswan/ipsec_broadcastof.3000066400000000000000000000000321457372064200214000ustar00rootroot00000000000000.so man3/ipsec_subnetof.3 libreswan-4.14/lib/libswan/ipsec_datatot.3000066400000000000000000000000311457372064200205500ustar00rootroot00000000000000.so man3/ipsec_ttodata.3 libreswan-4.14/lib/libswan/ipsec_hostof.3000066400000000000000000000000321457372064200204130ustar00rootroot00000000000000.so man3/ipsec_subnetof.3 libreswan-4.14/lib/libswan/ipsec_initsaid.3000066400000000000000000000000271457372064200207210ustar00rootroot00000000000000.so man3/ipsec_ttosa.3 libreswan-4.14/lib/libswan/ipsec_isanyaddr.3000066400000000000000000000000311457372064200210660ustar00rootroot00000000000000.so man3/ipsec_anyaddr.3 libreswan-4.14/lib/libswan/ipsec_isloopbackaddr.3000066400000000000000000000000311457372064200220710ustar00rootroot00000000000000.so man3/ipsec_anyaddr.3 libreswan-4.14/lib/libswan/ipsec_isunspecaddr.3000066400000000000000000000000311457372064200215740ustar00rootroot00000000000000.so man3/ipsec_anyaddr.3 libreswan-4.14/lib/libswan/ipsec_loopbackaddr.3000066400000000000000000000000311457372064200215350ustar00rootroot00000000000000.so man3/ipsec_anyaddr.3 libreswan-4.14/lib/libswan/ipsec_maskof.3000066400000000000000000000000341457372064200203730ustar00rootroot00000000000000.so man3/ipsec_initsubnet.3 libreswan-4.14/lib/libswan/ipsec_masktobits.3000066400000000000000000000000321457372064200212710ustar00rootroot00000000000000.so man3/ipsec_goodmask.3 libreswan-4.14/lib/libswan/ipsec_masktocount.3000066400000000000000000000000341457372064200214620ustar00rootroot00000000000000.so man3/ipsec_initsubnet.3 libreswan-4.14/lib/libswan/ipsec_networkof.3000066400000000000000000000000341457372064200211310ustar00rootroot00000000000000.so man3/ipsec_initsubnet.3 libreswan-4.14/lib/libswan/ipsec_prng_bytes.3000066400000000000000000000000331457372064200212660ustar00rootroot00000000000000.so man3/ipsec_prng_init.3 libreswan-4.14/lib/libswan/ipsec_prng_final.3000066400000000000000000000000331457372064200212310ustar00rootroot00000000000000.so man3/ipsec_prng_init.3 libreswan-4.14/lib/libswan/ipsec_prng_init.3000066400000000000000000000120061457372064200211060ustar00rootroot00000000000000'\" 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-4.14/lib/libswan/ipsec_rangetoa.3000066400000000000000000000000301457372064200207070ustar00rootroot00000000000000.so man3/ipsec_atoasr.3 libreswan-4.14/lib/libswan/ipsec_sameaddrtype.3000066400000000000000000000000321457372064200215730ustar00rootroot00000000000000.so man3/ipsec_sameaddr.3 libreswan-4.14/lib/libswan/ipsec_samesaid.3000066400000000000000000000000321457372064200206770ustar00rootroot00000000000000.so man3/ipsec_sameaddr.3 libreswan-4.14/lib/libswan/ipsec_samesubnet.3000066400000000000000000000000321457372064200212570ustar00rootroot00000000000000.so man3/ipsec_sameaddr.3 libreswan-4.14/lib/libswan/ipsec_samesubnettype.3000066400000000000000000000000321457372064200221610ustar00rootroot00000000000000.so man3/ipsec_sameaddr.3 libreswan-4.14/lib/libswan/ipsec_satot.3000066400000000000000000000000271457372064200202470ustar00rootroot00000000000000.so man3/ipsec_ttosa.3 libreswan-4.14/lib/libswan/ipsec_setportof.3000066400000000000000000000000301457372064200211340ustar00rootroot00000000000000.so man3/ipsec_portof.3 libreswan-4.14/lib/libswan/ipsec_sockaddrlenof.3000066400000000000000000000000301457372064200217250ustar00rootroot00000000000000.so man3/ipsec_portof.3 libreswan-4.14/lib/libswan/ipsec_sockaddrof.3000066400000000000000000000000301457372064200212260ustar00rootroot00000000000000.so man3/ipsec_portof.3 libreswan-4.14/lib/libswan/ipsec_splitkeytoid.3000066400000000000000000000000351457372064200216400ustar00rootroot00000000000000.so man3/ipsec_keyblobtoid.3 libreswan-4.14/lib/libswan/ipsec_subnetinsubnet.3000066400000000000000000000000321457372064200221610ustar00rootroot00000000000000.so man3/ipsec_sameaddr.3 libreswan-4.14/lib/libswan/ipsec_subnetishost.3000066400000000000000000000000321457372064200216430ustar00rootroot00000000000000.so man3/ipsec_sameaddr.3 libreswan-4.14/lib/libswan/ipsec_subnettoa.3000066400000000000000000000000311457372064200211140ustar00rootroot00000000000000.so man3/ipsec_atoaddr.3 libreswan-4.14/lib/libswan/ipsec_subnettot.3000066400000000000000000000000311457372064200211370ustar00rootroot00000000000000.so man3/ipsec_ttoaddr.3 libreswan-4.14/lib/libswan/ipsec_subnettypeof.3000066400000000000000000000000341457372064200216420ustar00rootroot00000000000000.so man3/ipsec_initsubnet.3 libreswan-4.14/lib/libswan/ipsec_tnatoaddr.3000066400000000000000000000000311457372064200210700ustar00rootroot00000000000000.so man3/ipsec_ttoaddr.3 libreswan-4.14/lib/libswan/ipsec_ttosubnet.3000066400000000000000000000000311457372064200211370ustar00rootroot00000000000000.so man3/ipsec_ttoaddr.3 libreswan-4.14/lib/libswan/ipsec_ultot.3000066400000000000000000000000271457372064200202640ustar00rootroot00000000000000.so man3/ipsec_ttoul.3 libreswan-4.14/lib/libswan/ipsec_unspecaddr.3000066400000000000000000000000311457372064200212400ustar00rootroot00000000000000.so man3/ipsec_anyaddr.3 libreswan-4.14/lib/libswan/ipsec_version_code.3000066400000000000000000000044011457372064200215740ustar00rootroot00000000000000'\" 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-4.14/lib/libswan/ipsec_version_string.3000066400000000000000000000000361457372064200221700ustar00rootroot00000000000000.so man3/ipsec_version_code.3 libreswan-4.14/lib/libswan/ipseckey_algorithm_config_names.c000066400000000000000000000022701457372064200244060ustar00rootroot00000000000000/* tables of names for values defined in constants.h * * Copyright (C) 2022 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 "lswcdefs.h" /* for ARRAY_REF() */ #include "enum_names.h" #include "ietf_constants.h" /* for enum ipseckey_algorithm_type_names */ static const char *ipseckey_algorithm_config_name[] = { #define S(E,S) [E - IPSECKEY_ALGORITHM_RSA] = S S(IPSECKEY_ALGORITHM_RSA, "rsasigkey"), S(IPSECKEY_ALGORITHM_ECDSA, "ecdsakey"), S(IPSECKEY_ALGORITHM_X_PUBKEY, "pubkey"), #undef S }; const struct enum_names ipseckey_algorithm_config_names = { IPSECKEY_ALGORITHM_RSA, IPSECKEY_ALGORITHM_X_PUBKEY, ARRAY_REF(ipseckey_algorithm_config_name), NULL, NULL, }; libreswan-4.14/lib/libswan/ipseckey_algorithm_type_names.c000066400000000000000000000022651457372064200241260ustar00rootroot00000000000000/* tables of names for values defined in constants.h * * Copyright (C) 2022 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 "lswcdefs.h" /* for ARRAY_REF() */ #include "enum_names.h" #include "ietf_constants.h" /* for enum ipseckey_algorithm_type */ static const char *ipseckey_algorithm_type_name[] = { #define S(E) [E - IPSECKEY_ALGORITHM_DSA] = #E S(IPSECKEY_ALGORITHM_DSA), S(IPSECKEY_ALGORITHM_RSA), S(IPSECKEY_ALGORITHM_ECDSA), S(IPSECKEY_ALGORITHM_X_PUBKEY), #undef S }; const struct enum_names ipseckey_algorithm_type_names = { IPSECKEY_ALGORITHM_DSA, IPSECKEY_ALGORITHM_X_PUBKEY, ARRAY_REF(ipseckey_algorithm_type_name), "IPSECKEY_ALGORITHM_", NULL, }; libreswan-4.14/lib/libswan/jam_base64_bytes.c000066400000000000000000000022641457372064200211400ustar00rootroot00000000000000/* Output base64 bytes, for libreswan * * Copyright (C) 2022 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 "jambuf.h" #include "chunk.h" #include "ttodata.h" /* for datatot() */ #include "passert.h" size_t jam_base64_bytes(struct jambuf *buf, const void *ptr, size_t size) { /* * A byte is 8-bits, base64 uses 6-bits (2^6=64). Plus some * for \0. Plus some extra for the trailing === and rounding. */ chunk_t base64 = alloc_chunk(size * 8 / 6 + 1 + 10, "base64"); size_t length = datatot(ptr, size, 64, (void*)base64.ptr, base64.len); passert(length < base64.len); jam_raw_bytes(buf, base64.ptr, length); free_chunk_content(&base64); return length; } libreswan-4.14/lib/libswan/jam_bytes.c000066400000000000000000000072101457372064200177700ustar00rootroot00000000000000/* 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 "jambuf.h" #include "chunk.h" #include "ttodata.h" /* for datatot() */ #include "passert.h" size_t jam_hex_bytes(struct jambuf *buf, const void *ptr, size_t size) { size_t n = 0; const uint8_t *bytes = ptr; for (unsigned i = 0; i < size; i++) { n += jam(buf, "%02x", bytes[i]); } return n; } size_t jam_HEX_bytes(struct jambuf *buf, const void *ptr, size_t size) { size_t n = 0; const uint8_t *bytes = ptr; for (unsigned i = 0; i < size; i++) { n += jam(buf, "%02X", bytes[i]); } 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(struct jambuf *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. */ size_t jam_sanitized_bytes(struct jambuf *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]; /* * Notes: * * - NUL is always represented as '\0'. * * - octal format can use up-to 3 digts but can't be * ambiguous, so only use when next character isn't * numeric */ switch (c) { case '\0': n += jam_string(buf, "\\0"); break; case '\a': n += jam_string(buf, "\\a"); break; case '\b': n += jam_string(buf, "\\b"); break; case '\t': n += jam_string(buf, "\\t"); break; case '\n': n += jam_string(buf, "\\n"); break; case '\v': n += jam_string(buf, "\\v"); break; case '\f': n += jam_string(buf, "\\f"); break; case '\r': n += jam_string(buf, "\\r"); break; default: if (char_isprint(c)) { n += jam_char(buf, c); } else if (i + 1 == size || !char_isdigit(chars[i + 1])) { n += jam(buf, "\\%o", c & 0xFF); } else { n += jam(buf, "\\%03o", c & 0xFF); } break; } } return n; } /* * For shell variables. Output the string in a format suitable for * use by shell scripts, but wrapped in single quotes. * * XXX: bonus points for anyone encoding \r \n ... correctly? But is * it even safe? */ size_t jam_shell_quoted_bytes(struct jambuf *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]; switch (c) { case '\'': case '\\': case '"': case '`': case '$': n += jam(buf, "\\%03o", c & 0xFF); break; default: if (char_isprint(c)) { n += jam_char(buf, c); } else { n += jam(buf, "\\%03o", c & 0xFF); } break; } } return n; } libreswan-4.14/lib/libswan/jam_humber.c000066400000000000000000000035701457372064200201310ustar00rootroot00000000000000/* routines for state objects, for libreswan * * Copyright (C) 2022 Antony Antony * Copyright (C) 2022 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" #include "jambuf.h" /* * readable_humber: make large numbers clearer by expressing them * as Ki,Mi,Gi,Ti,Pi,Ei and 2^64 will be 16Ei based on * https://en.wikipedia.org/wiki/Binary_prefix IEC 60027-2 standard. * The prefix and suffix2 are literally copied into the output. * e.g. use sufix2 "B" for Bytes. */ size_t jam_humber(struct jambuf *buf, uintmax_t num) { const char *suffix; uint64_t to_print; if (num >= binary_per_exa) { to_print = num / binary_per_exa; suffix = "Ei"; } else if (num >= binary_per_peta) { to_print = num / binary_per_peta; suffix = "Pi"; } else if (num >= binary_per_tera) { to_print = num / binary_per_tera; suffix = "Ti"; } else if (num >= binary_per_giga) { to_print = num / binary_per_giga; suffix = "Gi"; } else if (num >= binary_per_mega) { to_print = num / binary_per_mega; suffix = "Mi"; } else if (num >= binary_per_kilo) { to_print = num / binary_per_kilo; suffix = "Ki"; } else { to_print = num; suffix = ""; } return jam(buf, "%ju%s", to_print, suffix); } const char *str_humber(uintmax_t num, humber_buf *buf) { struct jambuf jb = ARRAY_AS_JAMBUF(buf->buf); jam_humber(&jb, num); return buf->buf; } libreswan-4.14/lib/libswan/jam_nss_cka.c000066400000000000000000000023641457372064200202700ustar00rootroot00000000000000/* 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 jam_nss_cka(struct jambuf *buf, CK_ATTRIBUTE_TYPE attribute) { switch (attribute) { /* Not using #T + strlen("CKA_") because of clang's -Wstring-plus-int */ #define CASE(T) case T: return jam_string(buf, &#T[strlen("CKA_")]) CASE(CKA_DERIVE); CASE(CKA_FLAGS_ONLY); CASE(CKA_WRAP); CASE(CKA_UNWRAP); CASE(CKA_ENCRYPT); CASE(CKA_DECRYPT); CASE(CKA_SIGN); CASE(CKA_SIGN_RECOVER); CASE(CKA_VERIFY); CASE(CKA_VERIFY_RECOVER); #undef CASE default: return jam(buf, "CKA_%08lx", (long)attribute); } } libreswan-4.14/lib/libswan/jam_nss_ckf.c000066400000000000000000000023561457372064200202760ustar00rootroot00000000000000/* 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 jam_nss_ckf(struct jambuf *buf, CK_FLAGS flags) { const char *sep = ""; size_t size = 0; /* nothing smart about this */ #define FLAG(F) \ if (flags & F) { \ size += jam_string(buf, sep); \ /* Not using #T + strlen("CKF_") because of clang's -Wstring-plus-int */ \ size += jam_string(buf, &#F[strlen("CKF_")]); \ sep = "+"; \ flags ^= F; \ } FLAG(CKF_SIGN); FLAG(CKF_ENCRYPT); FLAG(CKF_DECRYPT); if (flags != 0) { size += jam(buf, "%sCKF_%08lx", sep, (long) flags); } return size; } libreswan-4.14/lib/libswan/jam_nss_ckm.c000066400000000000000000000051371457372064200203050ustar00rootroot00000000000000/* 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? * * Kind of SECOID_FindOIDByMechanism() works for some, but not all * values. */ #include "lswlog.h" #include "lswnss.h" const char *str_nss_ckm(CK_MECHANISM_TYPE mechanism, enum_buf *buf) { switch (mechanism) { /* Not using #T + strlen("CKM_") because of clang's -Wstring-plus-int */ #define CASE(T) case T: return &#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 /* print whenever defined */ 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 /* print whenever defined */ CASE(CKM_NSS_IKE_PRF_DERIVE); #endif #ifdef CKM_NSS_IKE1_PRF_DERIVE /* print whenever defined */ CASE(CKM_NSS_IKE1_PRF_DERIVE); #endif #ifdef CKM_NSS_IKE_PRF_PLUS_DERIVE /* print whenever defined */ CASE(CKM_NSS_IKE_PRF_PLUS_DERIVE); #endif #ifdef CKM_NSS_IKE1_APP_B_PRF_DERIVE /* print whenever defined */ CASE(CKM_NSS_IKE1_APP_B_PRF_DERIVE); #endif CASE(CKM_VENDOR_DEFINED); #undef CASE default: { snprintf(buf->buf, sizeof(buf->buf), "CKM_%08lx", (long)mechanism); return buf->buf; } } } size_t jam_nss_ckm(struct jambuf *buf, CK_MECHANISM_TYPE mechanism) { enum_buf b; return jam_string(buf, str_nss_ckm(mechanism, &b)); } libreswan-4.14/lib/libswan/jam_nss_error.c000066400000000000000000000037201457372064200206600ustar00rootroot00000000000000/* 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 jam_nss_error_code(struct jambuf *buf, PRErrorCode code) { if (code == 0) { return jam_string(buf, "error code not saved by NSS"); } size_t size = 0; /* * Print the symbolic name, if known. This makes tracking * down the error in NSS's code base easier. * * If the name isn't known print the magic code (but would * that ever happen?). */ const char *name = PR_ErrorToName(code); if (name != NULL) { size += jam_string(buf, name); } else if (IS_SEC_ERROR(code)) { size += jam(buf, "SEC_ERROR_BASE+%d", code - SEC_ERROR_BASE); #if 0 } else if (IS_SSL_ERROR(code)) { size += jam(buf, "SSL_ERROR_BASE+%d", code - SSL_ERROR_BASE); #endif } else { size += jam(buf, "NSS %d 0x%x", code, code); } jam_string(buf, ": "); /* * NSPR should contain string tables for all known error * classes. When it doesn't it returns "Unknown code ...". * Should this specify the english language? * * Note: PORT_ErrorToString(err) is just a macro wrapper that * expands to the below call. */ const char *string = PR_ErrorToString(code, PR_LANGUAGE_I_DEFAULT); size += jam_string(buf, string); return size; } libreswan-4.14/lib/libswan/jam_nss_oid.c000066400000000000000000000022561457372064200203050ustar00rootroot00000000000000/* Output the decoded NSS SECOidTag, for libreswan * * Copyright (C) 2022 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" const char *str_nss_oid(SECOidTag oidtag, enum_buf *buf) { SECOidData *data = SECOID_FindOIDByTag(oidtag); if (data != NULL) { return data->desc; } else { snprintf(buf->buf, sizeof(buf->buf), "SEC_OID_%d", oidtag); return buf->buf; } } size_t jam_nss_oid(struct jambuf *buf, SECOidTag oidtag) { SECOidData *data = SECOID_FindOIDByTag(oidtag); if (data != NULL) { return jam_string(buf, data->desc); } return jam(buf, "SEC_OID_%d", oidtag); } libreswan-4.14/lib/libswan/jam_nss_secitem.c000066400000000000000000000030111457372064200211510ustar00rootroot00000000000000/* 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 jam_nss_secitemtype(struct jambuf *buf, SECItemType type) { #define C(T) case T: return jam_string(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 jam(buf, "(SECItemType)%d", type); } } size_t jam_nss_secitem(struct jambuf *buf, const SECItem *secitem) { size_t size = 0; if (secitem == NULL) { size = jam_string(buf, "(SECItem*)NULL"); } else { jam_nss_secitemtype(buf, secitem->type); jam(buf, ": "); jam_dump_bytes(buf, secitem->data, secitem->len); } return size; } libreswan-4.14/lib/libswan/jambuf.c000066400000000000000000000200161457372064200172560ustar00rootroot00000000000000/* 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 /* for ERANGE */ #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(struct jambuf *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 */ struct jambuf 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 */ struct jambuf buf = { .array = array, .total = 0, .roof = sizeof_array - 1, .dots = "...", }; buf.array[buf.roof-1] = buf.array[buf.total/*0*/] = '\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 { /* * Position in the buffer to store the next string (always * points at the trailing '\n' character of the string so far). */ char *cursor; /* * Free space, or zero when the stream has been truncated. * * Up to SIZE-1 + the trailing '\0' can be written. */ size_t size; }; static struct dest dest(struct jambuf *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(struct jambuf *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(struct jambuf *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(struct jambuf *buf, const char *format, va_list ap) { assert_jambuf(buf); struct dest d = dest(buf); /* * The return value (N) is the number of characters, not * including the trailing NUL, that should have been written * to the buffer. * * The buffer will contain up to d.size-1 characters plus a * trailing NUL. */ 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(struct jambuf *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(struct jambuf *buf, char c) { return jam_raw_bytes(buf, &c, 1); } size_t jam_string(struct jambuf *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_errno(struct jambuf *buf, int error) { assert_jambuf(buf); struct dest d = dest(buf); if (d.size == 0) { /* should be strlen(strerror()) */ return 1; } /* * strerror_r() will store up to d.size-1 characters plus a * trailing NUL. */ int e = strerror_r(error, d.cursor, d.size); int n = strlen(d.cursor); buf->total += n; if (e == ERANGE) { /* * Need to force overflow as strerror_r() only stores * up to d.size-1 characters (excluding '\0') which * leaves buf->total==buf->roof-1. */ buf->total = buf->roof; truncate_buf(buf); } else if (e != EINVAL) { /* assume unknown E already includes number */ n += jam(buf, " (errno %d)", error); } assert_jambuf(buf); return n; } size_t jam_jambuf(struct jambuf *buf, struct jambuf *jambuf) { shunk_t s = jambuf_as_shunk(jambuf); return jam_raw_bytes(buf, s.ptr, s.len); } bool jambuf_ok(struct jambuf *buf) { assert_jambuf(buf); return buf->total < buf->roof; } const char *jambuf_cursor(struct jambuf *buf) { assert_jambuf(buf); struct dest d = dest(buf); return d.cursor; } shunk_t jambuf_as_shunk(struct jambuf *buf) { assert_jambuf(buf); struct dest d = dest(buf); return shunk2(buf->array, d.cursor - buf->array); } jampos_t jambuf_get_pos(struct jambuf *buf) { assert_jambuf(buf); jampos_t pos = { .total = buf->total, }; return pos; } void jambuf_set_pos(struct jambuf *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-4.14/lib/libswan/kernel_netlink_query.c000066400000000000000000000030761457372064200222520ustar00rootroot00000000000000/* * Copyright (C) 2018-2020 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. */ #include #include #include #include #include #include #include "kernel_netlink_query.h" #include "lsw_socket.h" #include "lswlog.h" /* returns a file descriptor on success; -1 on error */ int nl_send_query(const struct nlmsghdr *req, int protocol, struct logger *logger) { int nl_fd = cloexec_socket(AF_NETLINK, SOCK_DGRAM|SOCK_NONBLOCK, protocol); if (nl_fd < 0) { llog_error(logger, errno, "socket() in nl_send_query() protocol %d", protocol); return nl_fd; /* -1 */ } size_t len = req->nlmsg_len; ssize_t r; do { r = write(nl_fd, req, len); } while (r < 0 && errno == EINTR); if (r < 0) { llog_error(logger, errno, "netlink nl_send_query() write"); close(nl_fd); return -1; } else if ((size_t)r != len) { llog_error(logger, 0/*no-strerr*/, "netlink write() message truncated: %zd instead of %zu", r, len); close(nl_fd); return -1; } return nl_fd; } libreswan-4.14/lib/libswan/kernel_netlink_reply.c000066400000000000000000000042441457372064200222360ustar00rootroot00000000000000/* * 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_netlink_reply.h" /* ??? one caller thinks errno is meaningful after a failure */ 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-4.14/lib/libswan/keyblobtoid.3.xml000066400000000000000000000123461457372064200210470ustar00rootroot00000000000000 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-4.14/lib/libswan/keyid.c000066400000000000000000000044031457372064200171210ustar00rootroot00000000000000/* printable key IDs, for libreswan * * Copyright (C) 2002 Henry Spencer. * Copyright (C) 2020 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 "keyid.h" #include "ttodata.h" /* for datatot() */ const keyid_t empty_keyid; /* * keyblobtokeyid - generate a printable key ID from an RFC 2537/3110 * key blob * * Current algorithm is just to use first nine base64 digits. */ err_t keyblob_to_keyid(const uint8_t *src, size_t srclen, keyid_t *dst) { /* XXX: datatot() returns number of bytes including trailing '\0' */ size_t ret = datatot(src, srclen, 64, dst->keyid, sizeof(dst->keyid)); if (ret < sizeof(dst->keyid)) { /* how would this happen? */ return "key blob is too small"; } else { return NULL; } } /* * splitkeytokeyid - generate a printable key ID from * exponent/modulus pair * * Just constructs the beginnings of a key blob and calls * keyblobtoid(). */ err_t splitkey_to_keyid(const uint8_t *e, size_t elen, const uint8_t *m, size_t mlen, keyid_t *dst) { /* form the leading few bytes of the raw keyblob */ uint8_t keyblob[sizeof(keyid_t)]; /* ample room */ uint8_t *const blob_end = keyblob + sizeof(keyblob); uint8_t *p = keyblob; /* start with length of e; assume that it fits */ if (elen <= 0xff) { /* one byte */ *p++ = elen; } else if (elen <= 0xffff) { /* two bytes */ *p++ = 0; *p++ = (elen >> 8) & 0xff; *p++ = elen & 0xff; } else { *dst = empty_keyid; return "unrepresentable exponent length"; } /* append as much of e as fits */ while (elen > 0 && p < blob_end) { *p++ = *e++; elen--; } /* append as much of m as fits */ while (mlen > 0 && p < blob_end) { *p++ = *m++; mlen--; } return keyblob_to_keyid(keyblob, p - keyblob, dst); } libreswan-4.14/lib/libswan/keywords.c000066400000000000000000000052541457372064200176700ustar00rootroot00000000000000/* 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 && hunk_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 && hunk_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 jam_keyword_name(struct jambuf *buf, const struct keywords *keywords, unsigned value) { const struct keyword *keyword = keyword_by_value(keywords, value); if (keyword == NULL) { return jam(buf, "'%s %u'", keywords->name, value); } else { return jam_string(buf, keyword->name); } } size_t jam_keyword_sname(struct jambuf *buf, const struct keywords *keywords, unsigned value) { const struct keyword *keyword = keyword_by_value(keywords, value); if (keyword == NULL) { return jam(buf, "'%s %u'", keywords->name, value); } else { return jam_string(buf, keyword->sname); } } libreswan-4.14/lib/libswan/lex.c000066400000000000000000000152031457372064200166040ustar00rootroot00000000000000/* * 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 "sysdep.h" #include "constants.h" #include "lswlog.h" #include "lex.h" #include "lswlog.h" #include "lswalloc.h" #include "hunk.h" /* for char_is_space() */ /* * 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 **flp, const char *name, bool optional, const struct file_lex_position *oflp) { FILE *f = fopen(name, "r"); if (f == NULL) { if (!optional || errno != ENOENT) { llog_error(oflp->logger, errno, "could not open \"%s\"", name); } else if (DBGP(DBG_TMI)) { llog_errno(DEBUG_STREAM, oflp->logger, errno, "lex open: %s"/*: */, name); } return false; } DBGF(DBG_TMI, "lex open: %s", name); struct file_lex_position *new_flp = alloc_thing(struct file_lex_position, name); new_flp->depth = oflp->depth + 1; new_flp->filename = clone_str(name, "lexopen filename"); new_flp->fp = f; new_flp->lino = 0; new_flp->bdry = B_none; new_flp->cur = new_flp->buffer; /* nothing loaded yet */ new_flp->under = *new_flp->cur = '\0'; new_flp->logger = oflp->logger; shift(new_flp); /* prime tok */ *flp = new_flp; return true; } /* * Close filehandle */ void lexclose(struct file_lex_position **flp) { DBGF(DBG_TMI, "lex close:"); fclose((*flp)->fp); pfreeany((*flp)->filename); pfree(*flp); *flp = NULL; } /* * 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. */ /* * We have an end-of-line aka start-of-record: return it, deferring * "real" token Caller will clear .bdry so shift() can read the new * line and return the next token. */ static void start_record(struct file_lex_position *flp, char *p) { flp->bdry = B_record; flp->tok = NULL; flp->under = *p; flp->cur = p; } /* * shift - load next token into tok * * @return bool True if successful (i.e., there is a token) */ bool shift(struct file_lex_position *flp) { char *p = flp->cur; char *start_of_record = NULL; /* start of record for any new lines */ passert(flp->bdry == B_none); *p = flp->under; flp->under = '\0'; flp->quote = '\0'; /* truthy */ for (;;) { switch (*p) { case '\0': /* end of line */ case '#': /* comment at end of line */ /* * Treat comment at end of line like line end, * by getting the next line. */ if (fgets(flp->buffer, sizeof(flp->buffer) - 1, flp->fp) == NULL) { flp->bdry = B_file; flp->tok = flp->cur = NULL; DBGF(DBG_TMI, "lex shift: file(eof)"); return false; /* no token */ } /* strip trailing whitespace, including \n */ for (p = flp->buffer + strlen(flp->buffer); p > flp->buffer && char_isspace(p[-1]); p--) ; *p = '\0'; flp->lino++; start_of_record = 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 == start_of_record) { /* * Need to return start of record * before quoted string (on re-entry, * P hasn't advanced, but * START_OF_RECORD is NULL). */ start_record(flp, p); DBGF(DBG_TMI, "lex shift: record(new line, with quotes)"); return false; /* no token */ } /* * we have a quoted token: * note and advance to its end */ flp->tok = p; p = strchr(p + 1, *p); if (p == NULL) { llog(RC_LOG_SERIOUS, flp->logger, "unterminated string"); p = flp->tok + strlen(flp->tok); } else { /* strip quotes from token */ flp->quote = *flp->tok; flp->tok++; *p = '\0'; p++; } /* * Remember token delimiter and replace with * '\0' (kind of pointless but consistent). */ flp->under = *p; *p = '\0'; flp->cur = p; DBGF(DBG_TMI, "lex shift: '%s'", flp->tok); return true; /* token */ default: if (p == start_of_record) { /* * Need to return start of record * before token (On re-entry, P hasn't * advanced, but START_OF_RECORD is * NULL). */ start_record(flp, p); DBGF(DBG_TMI, "lex shift: record(new line, with quotes)"); return false; /* no token */ } /* * 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' && !char_isblank(*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; DBGF(DBG_TMI, "lex shift: '%s'", flp->tok); return true; /* token */ } } } /* * 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(struct file_lex_position *flp, const char *message) { if (flp->bdry != B_none) { DBGF(DBG_TMI, "lex flushline: already on eof or record boundary"); return true; } /* discard tokens until boundary reached */ DBGF(DBG_TMI, "lex flushline: need to flush tokens"); if (message != NULL) { llog(RC_LOG_SERIOUS, flp->logger, "%s", message); } do { DBGF(DBG_TMI, "lex flushline: discarding '%s'", flp->tok); } while (shift(flp)); return false; } libreswan-4.14/lib/libswan/libreswan_bad_case.c000066400000000000000000000016231457372064200216040ustar00rootroot00000000000000/* 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) { llog_passert(&global_logger, where, "switch (%s) case %ld (0x%lx) unexpected", expression, value, value); } libreswan-4.14/lib/libswan/llog.c000066400000000000000000000015171457372064200167540ustar00rootroot00000000000000/* logging, for libreswan * * Copyright (C) 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. */ #include #include "lswlog.h" void llog(lset_t rc_flags, const struct logger *logger, const char *message, ...) { va_list ap; va_start(ap, message); llog_va_list(rc_flags, logger, message, ap); va_end(ap); } libreswan-4.14/lib/libswan/llog_base64_bytes.c000066400000000000000000000027631457372064200213320ustar00rootroot00000000000000/* Output raw bytes, for libreswan * * Copyright (C) 2022 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 "chunk.h" #include "ttodata.h" /* for datatot() */ #include "passert.h" void llog_base64_bytes(lset_t rc_flags, const struct logger *logger, const void *ptr, size_t size) { /* * A byte is 8-bits, base64 uses 6-bits (2^6=64). Plus some * for \0. Plus some extra for the trailing === and rounding. */ chunk_t base64 = alloc_chunk(size * 8 / 6 + 1 + 10, "base64"); size_t base64_size = datatot(ptr, size, 64, (void*)base64.ptr, base64.len); /* BASE64_SIZE includes '\0' */ passert(base64_size <= base64.len); passert(base64_size > 0); shunk_t rest = shunk2(base64.ptr, base64_size - 1); while (true) { shunk_t line = shunk_slice(rest, 0, min((size_t)64, rest.len)); if (line.len == 0) break; rest = shunk_slice(rest, line.len, rest.len); llog(rc_flags, logger, PRI_SHUNK, pri_shunk(line)); } free_chunk_content(&base64); } libreswan-4.14/lib/libswan/llog_dump.c000066400000000000000000000041131457372064200177740ustar00rootroot00000000000000/* 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,2021 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 llog_dump(lset_t rc_flags, const struct logger *logger, const void *p, size_t len) { const uint8_t *cp = p; do { /* each line shows 16 bytes; remember sizeof includes '\0' */ char hex[sizeof(" xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx")]; char str[sizeof("................")]; char *hp = hex; char *sp = str; for (int i = 0; len != 0 && i != 4; i++) { *hp++ = ' '; for (int j = 0; len != 0 && j != 4; len--, j++) { static const char hexdig[] = "0123456789abcdef"; *hp++ = ' '; *hp++ = hexdig[(*cp >> 4) & 0xF]; *hp++ = hexdig[(*cp >> 0) & 0xF]; *sp++ = (char_isprint(*cp) ? *cp : '.'); cp++; } } *hp++ = '\0'; *sp++ = '\0'; passert(hp <= hex + elemsof(hex)); passert(sp <= str + elemsof(str)); llog(rc_flags, logger, "%-*s %s", (int)sizeof(hex)-1, hex, str); } while (len != 0); } libreswan-4.14/lib/libswan/llog_errno.c000066400000000000000000000020641457372064200201570ustar00rootroot00000000000000/* 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 llog_errno(lset_t rc_flags, const struct logger *logger, int error, const char *fmt, ...) { char output[LOG_WIDTH]; struct jambuf buf[] = { ARRAY_AS_JAMBUF(output), }; jam_logger_prefix(buf, logger); va_list ap; va_start(ap, fmt); jam_va_list(buf, fmt, ap); va_end(ap); jam(buf, ": "); /* mimic perror() */ jam_errno(buf, error); jambuf_to_logger(buf, logger, rc_flags); } libreswan-4.14/lib/libswan/llog_pem_bytes.c000066400000000000000000000016531457372064200210240ustar00rootroot00000000000000/* Output raw bytes, for libreswan * * Copyright (C) 2022 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 llog_pem_bytes(lset_t rc_flags, const struct logger *logger, const char *name, const void *ptr, size_t size) { llog(rc_flags, logger, "-----BEGIN %s-----", name); llog_base64_bytes(rc_flags, logger, ptr, size); llog(rc_flags, logger, "-----END %s-----", name); } libreswan-4.14/lib/libswan/llog_va_list.c000066400000000000000000000015341457372064200204740ustar00rootroot00000000000000/* logging, for libreswan * * Copyright (C) 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. */ #include #include #include "lswlog.h" void llog_va_list(lset_t rc_flags, const struct logger *logger, const char *message, va_list ap) { LLOG_JAMBUF(rc_flags, logger, buf) { jam_va_list(buf, message, ap); } } libreswan-4.14/lib/libswan/lmod.c000066400000000000000000000056521457372064200167560ustar00rootroot00000000000000/* 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) { bool ok = true; shunk_t cursor = shunk1(args); while (true) { shunk_t elem = shunk_token(&cursor, NULL/*delim*/, "+, \t"); if (elem.ptr == NULL) { break; } if (elem.len == 0) { /* ignore empty */ continue; } if (enable && hunk_streq(elem, "none")) { /* excludes --no-... none */ mod->clr = info->mask; mod->set = LEMPTY; } else { /* non-empty */ shunk_t arg = elem; /* excludes --no-... no-... */ bool no = enable ? shunk_streat(&arg, "no-") : true; lset_t bits = LEMPTY; /* try aliases first */ if (info->aliases != NULL) { for (struct lmod_alias *c = info->aliases; c->name != NULL; c++) { if (hunk_streq(arg, c->name)) { bits = c->bits; break; } } } /* try bit mask second */ if (bits == LEMPTY) { int ix = enum_match(info->names, arg); if (ix >= 0) { bits = LELEM(ix); } } /* some sort of success */ if (bits == LEMPTY) { ok = false; break; } /* update masks */ if (no) { mod->clr |= bits; mod->set &= ~bits; } else { mod->set |= bits; mod->clr &= ~bits; } } } return ok; } size_t jam_lmod(struct jambuf *buf, enum_names *names, const char *separator, lmod_t mod) { size_t s = 0; s += jam_lset_short(buf, names, separator, mod.set); if (mod.clr != LEMPTY) { s += jam(buf, " - "); s += jam_lset_short(buf, names, separator, mod.clr); } return s; } libreswan-4.14/lib/libswan/log_error.c000066400000000000000000000022371457372064200200110ustar00rootroot00000000000000/* 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_error(struct logger *logger, int error, const char *fmt, ...) { char output[LOG_WIDTH]; struct jambuf buf[] = { ARRAY_AS_JAMBUF(output), }; /* XXX: notice how is in the middle */ /* ERROR: */ jam(buf, "ERROR: "); jam_logger_prefix(buf, logger); va_list ap; va_start(ap, fmt); jam_va_list(buf, fmt, ap); va_end(ap); if (error != 0) { jam(buf, ": "); /* mimic perror() */ jam_errno(buf, error); } jambuf_to_logger(buf, logger, ERROR_FLAGS); } libreswan-4.14/lib/libswan/log_ip.c000066400000000000000000000012651457372064200172700ustar00rootroot00000000000000/* 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-4.14/lib/libswan/log_nss_error.c000066400000000000000000000045301457372064200206720ustar00rootroot00000000000000/* Output an (NS)PR error, for libreswan * * Copyright (C) 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. */ #include #include #include #include #include "lswlog.h" #include "lswalloc.h" #include "lswnss.h" /* * See https://bugzilla.mozilla.org/show_bug.cgi?id=172051 */ VPRINTF_LIKE(3) static void jam_va_nss_error_code(struct jambuf *buf, PRErrorCode code, const char *message, va_list ap) { jam(buf, "NSS: "); jam_va_list(buf, message, ap); va_end(ap); jam(buf, ": "); jam_nss_error_code(buf, code); } void llog_nss_error_code(lset_t rc_flags, struct logger *logger, PRErrorCode code, const char *message, ...) { LLOG_JAMBUF(rc_flags, logger, buf) { va_list ap; va_start(ap, message); jam_va_nss_error_code(buf, code, message, ap); va_end(ap); } } diag_t diag_nss_error(const char *message, ...) { char lswbuf[LOG_WIDTH]; struct jambuf buf = ARRAY_AS_JAMBUF(lswbuf); va_list ap; va_start(ap, message); jam_va_nss_error_code(&buf, PR_GetError(), message, ap); va_end(ap); return diag_jambuf(&buf); } void passert_nss_error(const struct logger *logger, where_t where, const char *message, ...) { char scratch[LOG_WIDTH]; struct jambuf buf[1] = { ARRAY_AS_JAMBUF(scratch), }; va_list ap; va_start(ap, message); jam_va_nss_error_code(buf, PR_GetError(), message, ap); va_end(ap); /* XXX: double copy */ llog_passert(logger, where, PRI_SHUNK, pri_shunk(jambuf_as_shunk(buf))); } void pexpect_nss_error(struct logger *logger, where_t where, const char *message, ...) { char scratch[LOG_WIDTH]; struct jambuf buf[1] = { ARRAY_AS_JAMBUF(scratch), }; va_list ap; va_start(ap, message); jam_va_nss_error_code(buf, PR_GetError(), message, ap); va_end(ap); /* XXX: double copy */ llog_pexpect(logger, where, PRI_SHUNK, pri_shunk(jambuf_as_shunk(buf))); } libreswan-4.14/lib/libswan/lset.c000066400000000000000000000066061457372064200167720ustar00rootroot00000000000000/* 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() */ #include "enum_names.h" #include "sparse_names.h" /* test a set by seeing if all bits have names */ bool test_lset(const struct enum_names *en, lset_t val) { for (unsigned e = 0; val != 0; e++) { lset_t bit = LELEM(e); if (val & bit) { const char *n = enum_name(en, e); if (n == NULL) { return false; } } val &= ~bit; } return true; } static size_t jam_lset_pretty(struct jambuf *buf, enum_names *en, lset_t val, const char *separator, bool shorten) { if (val == LEMPTY) { return jam(buf, "none"); } size_t s = 0; const char *sep = ""; const struct enum_names *range = NULL; const char *prefix = NULL; for (unsigned e = 0; val != 0; e++) { lset_t bit = LELEM(e); if (val & bit) { /* range!=NULL implies e>=range->en_first */ if (range == NULL || e > range->en_last) { /* try to find a new range */ range = enum_range(en, e, &prefix); } s += jam_string(buf, sep); sep = separator; /* can handle range==NULL */ const char *name = enum_range_name(range, e, prefix, shorten); if (name == NULL) { /* No name for this bit, use hex. */ s += jam(buf, "0x" PRI_LSET, bit); } else { s += jam_string(buf, name); } } val &= ~bit; } return s; } #define LSET_SEPARATOR "+" size_t jam_lset(struct jambuf *buf, enum_names *en, lset_t val) { return jam_lset_pretty(buf, en, val, LSET_SEPARATOR, /*shorten?*/false); } const char *str_lset(enum_names *en, lset_t val, lset_buf *out) { struct jambuf buf = ARRAY_AS_JAMBUF(out->buf); jam_lset(&buf, en, val); return out->buf; } size_t jam_lset_short(struct jambuf *buf, enum_names *en, const char *separator, lset_t val) { return jam_lset_pretty(buf, en, val, separator, /*shorten?*/true); } const char *str_lset_short(enum_names *en, const char *separator, lset_t val, lset_buf *out) { struct jambuf buf = ARRAY_AS_JAMBUF(out->buf); jam_lset_short(&buf, en, separator, val); return out->buf; } size_t jam_sparse_lset(struct jambuf *buf, const struct sparse_name *sd, lset_t val) { if (val == LEMPTY) { return jam(buf, "none"); } size_t s = 0; const char *sep = ""; for (unsigned e = 0; val != 0; e++) { lset_t bit = LELEM(e); if (val & bit) { s += jam_string(buf, sep); sep = LSET_SEPARATOR; /* can return NULL */ const char *name = sparse_name(sd, bit); if (name == NULL) { /* No name for this bit, use hex. */ s += jam(buf, "0x" PRI_LSET, bit); } else { s += jam_string(buf, name); } } val &= ~bit; } return s; } libreswan-4.14/lib/libswan/lswconf.3.xml000066400000000000000000000226361457372064200202160ustar00rootroot00000000000000 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-4.14/lib/libswan/lswconf.c000066400000000000000000000124161457372064200174720ustar00rootroot00000000000000/* * 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 static struct lsw_conf_options global_oco; #define SUBDIRNAME(X) X /* * 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, struct logger *logger) { lsw_conf_setdefault(); subst(&global_oco.confddir, confddir, "override ipsec.d"); lsw_conf_calculate(); if (!streq(global_oco.confddir, IPSEC_CONFDDIR)) llog(RC_LOG, logger, " adjusting ipsec.d to %s", global_oco.confddir); } void lsw_conf_nssdir(const char *nssdir, struct logger *logger) { lsw_conf_setdefault(); subst(&global_oco.nssdir, nssdir, "override nssdir"); lsw_conf_calculate(); if (!streq(global_oco.nssdir, IPSEC_NSSDIR)) llog(RC_LOG, logger, " 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(struct logger *logger) { 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) { dbg("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) { llog(RC_LOG, logger, "SElinux: could not read 1 byte from the selinux enforce file"); return 2; } if (selinux_flag[0] == '1') return 1; else return 0; } libreswan-4.14/lib/libswan/lswfips.c000066400000000000000000000073011457372064200175030ustar00rootroot00000000000000/* * 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 /* for NSS_IsInitialized() */ #include "lswlog.h" #include "lswnss.h" #include "lswfips.h" /* * 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_fips_product(struct logger *logger) { if (access(FIPSPRODUCTCHECK, F_OK) != 0) { if (errno == ENOENT || errno == ENOTDIR) { return LSW_FIPS_OFF; } llog_errno(RC_LOG_SERIOUS, logger, errno, "FIPS ABORT: FIPS product check failed to determine status for %s"/*: */, FIPSPRODUCTCHECK); return LSW_FIPS_UNKNOWN; } return LSW_FIPS_ON; } #endif static enum lsw_fips_mode fips_mode = LSW_FIPS_UNKNOWN; /* * Only called by lsw_nss_setup(). */ enum lsw_fips_mode lsw_get_fips_mode(struct logger *logger) { /* * NSS returns bogus results for the FIPS check if you did not * open a database. If the program/tool runs libswan code * without a config file (and so it doesn't know where any nss * db lives), that tool should call NSS_NoDB_Init("."); before * using libswan code. See lsw_nss_setup() for an example. */ passert(NSS_IsInitialized()); /* * Has FIPS mode been forced using set_fips_mode()? */ if (fips_mode > LSW_FIPS_UNKNOWN) { return fips_mode; } #ifdef FIPS_CHECK enum lsw_fips_mode product = lsw_fips_product(logger); #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; llog(RC_LOG, logger, "FIPS Product: %s", product == LSW_FIPS_UNKNOWN ? "UNKNOWN" : product == LSW_FIPS_ON ? "YES" : "NO"); llog(RC_LOG, logger, "FIPS System: %s", system == LSW_FIPS_UNKNOWN ? "UNKNOWN" : system == LSW_FIPS_ON ? "YES" : "NO"); #endif llog(RC_LOG, logger, "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) { pexpect(fips_mode != LSW_FIPS_UNKNOWN); 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-4.14/lib/libswan/lswglob.c000066400000000000000000000030001457372064200174550ustar00rootroot00000000000000/* log wrapper, for libreswan * * Copyright (C) 2005 Michael Richardson * Copyright (C) 2017 D. Hugh Redelmeier * Copyright (C) 2017 Paul Wouters * Copyright (C) 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. * */ #include #include "lswglob.h" #include "lswlog.h" static pthread_mutex_t lswglob_mutex = PTHREAD_MUTEX_INITIALIZER; static struct logger *lswglob_logger; static const char *lswglob_what; static int lswglob_errfunc(const char *epath, int eerrno) { llog_error(lswglob_logger, eerrno, "problem with %s file \"%s\"", lswglob_what, epath); return 1; /* stop glob */ } int lswglob(const char *pattern, glob_t *pglob, const char *what, struct logger *logger) { int r; pthread_mutex_lock(&lswglob_mutex); { lswglob_logger = logger; lswglob_what = what; r = glob(pattern, GLOB_ERR, lswglob_errfunc, pglob); lswglob_logger = NULL; lswglob_what = NULL; } pthread_mutex_unlock(&lswglob_mutex); return r; } libreswan-4.14/lib/libswan/lswnss.c000066400000000000000000000170631457372064200173530ustar00rootroot00000000000000/* * 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 /* for NSS_Initialize() */ #include "lswconf.h" #include "lswnss.h" #include "lswalloc.h" #include "lswlog.h" #include "lswfips.h" static char *lsw_nss_get_password(PK11SlotInfo *slot, PRBool retry, void *arg); static unsigned flags; diag_t lsw_nss_setup(const char *configdir, unsigned setup_flags, struct logger *logger) { /* * Turn (possibly NULL) CONFIGDIR into (possibly NULL) nssdir * so it can be used in error messages. */ #define SQL "sql:" char *nssdir; if (configdir == NULL) { nssdir = NULL; } else if (startswith(configdir, SQL)) { nssdir = clone_str(configdir, "nssdir"); } else { nssdir = alloc_printf(SQL"%s", configdir); } /* * Always log what is about to happen. */ if (nssdir == NULL) { llog(RC_LOG, logger, "Initializing NSS"); } else { llog(RC_LOG, logger, "Initializing NSS using %s database \"%s\"", (flags & LSW_NSS_READONLY) ? "read-only" : "read-write", nssdir); } /* * 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); /* * Initialize NSS, possibly flipping it to the correct mode. */ enum lsw_fips_mode fips_mode; if (nssdir != NULL) { SECStatus rv = NSS_Initialize(nssdir, "", "", SECMOD_DB, (flags & LSW_NSS_READONLY) ? NSS_INIT_READONLY : 0); if (rv != SECSuccess) { /* NSS: : (SECERR: N) */ diag_t d = diag_nss_error("initialization using %s database \"%s\" failed", (flags & LSW_NSS_READONLY) ? "read-only" : "read-write", nssdir); pfree(nssdir); return d; } fips_mode = lsw_get_fips_mode(logger); } else { NSS_NoDB_Init("."); fips_mode = lsw_get_fips_mode(logger); if (fips_mode == LSW_FIPS_ON && !PK11_IsFIPS()) { SECMODModule *internal = SECMOD_GetInternalModule(); if (internal == NULL) { return diag_nss_error("SECMOD_GetInternalModule() failed"); } if (SECMOD_DeleteInternalModule(internal->commonName) != SECSuccess) { return diag_nss_error("SECMOD_DeleteInternalModule(%s) failed", internal->commonName); } if (!PK11_IsFIPS()) { return diag("NSS: toggling to FIPS mode failed"); } } } if (fips_mode == LSW_FIPS_UNKNOWN) { pfreeany(nssdir); return diag("NSS: FIPS mode could not be determined"); } /* * The wrapper lsw_nss_get_password_context(LOGGER) must be * passed as the the final argument to any NSS call that might * call lsw_nss_get_password(). NSS will then pass the * context along. * * It is currently the logger but it might change. */ PK11_SetPasswordFunc(lsw_nss_get_password); if (nssdir != NULL) { PK11SlotInfo *slot = lsw_nss_get_authenticated_slot(logger); if (slot == NULL) { /* already logged */ pfreeany(nssdir); return diag("NSS: could not authenticate slot"); } PK11_FreeSlot(slot); } pfreeany(nssdir); return NULL; } void lsw_nss_shutdown(void) { NSS_Shutdown(); /* this flag is never set anywhere */ if (!(flags & LSW_NSS_SKIP_PR_CLEANUP)) { PR_Cleanup(); } } PK11SlotInfo *lsw_nss_get_authenticated_slot(struct logger *logger) { PK11SlotInfo *slot = PK11_GetInternalKeySlot(); /* refcnt_add() */ if (slot == NULL) { llog(RC_LOG_SERIOUS|ERROR_STREAM, logger, "no internal key slot"); return NULL; } if (PK11_IsFIPS() || PK11_NeedLogin(slot)) { SECStatus status = PK11_Authenticate(slot, PR_FALSE, lsw_nss_get_password_context(logger)); if (status != SECSuccess) { const char *token = PK11_GetTokenName(slot); llog(RC_LOG_SERIOUS|ERROR_STREAM, logger, "authentication of \"%s\" failed", token); PK11_FreeSlot(slot); /* refcnt_del() */ return NULL; } } return slot; } static char *lsw_nss_get_password(PK11SlotInfo *slot, PRBool retry, void *arg) { struct logger *logger = arg; pexpect(logger != NULL); 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) { llog(RC_LOG, logger, "NSS Password slot has no token name"); return NULL; } if (PK11_ProtectedAuthenticationPath(slot)) { llog(RC_LOG, logger, "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); llog(RC_LOG, logger, "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) { llog(RC_LOG, logger, "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) { llog(RC_LOG, logger, "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) { llog(RC_LOG, logger, "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]); llog(RC_LOG, logger, "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 */ llog(RC_LOG, logger, "NSS Password file \"%s\" does not contain token \"%s\"", oco->nsspassword_file, token); PORT_Free(passwords); return NULL; } libreswan-4.14/lib/libswan/monotime.c000066400000000000000000000062151457372064200176460ustar00rootroot00000000000000/* 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 #include "constants.h" /* for memeq() which is clearly not a constant */ #include "jambuf.h" #include "lswlog.h" /* for fatal_errno() */ #include "monotime.h" monotime_t monotime(intmax_t seconds) { return (monotime_t) { .mt = { .tv_sec = seconds, }, }; } monotime_t monotime_ms(intmax_t milliseconds) { return (monotime_t) { .mt = timeval_ms(milliseconds), }; } 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) { /* * This code assumes clock_gettime() always succeeds - * if it were expected to fail then there'd either be * a logger and/or a way to return the failure to the * caller. */ fatal_errno(PLUTO_EXIT_KERNEL_FAIL, &global_logger, errno, "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 monotime_add(monotime_t t, deltatime_t d) { monotime_t s = MONOTIME_EPOCH; timeradd(&t.mt, &d.dt, &s.mt); return s; } monotime_t monotime_sub(monotime_t t, deltatime_t d) { monotime_t s = MONOTIME_EPOCH; timersub(&t.mt, &d.dt, &s.mt); return s; } bool monobefore(monotime_t a, monotime_t b) { return timercmp(&a.mt, &b.mt, <); } int monotime_sub_sign(monotime_t l, monotime_t r) { return timeval_sub_sign(l.mt, r.mt); } deltatime_t monotimediff(monotime_t a, monotime_t b) { return deltatime_timevals_diff(a.mt, b.mt); } size_t jam_monotime(struct jambuf *buf, monotime_t m) { /* convert it to time-since-epoch and log that */ return jam_deltatime(buf, monotimediff(m, monotime_epoch)); } const char *str_monotime(monotime_t m, monotime_buf *buf) { struct jambuf jambuf = ARRAY_AS_JAMBUF(buf->buf); jam_monotime(&jambuf, m); return buf->buf; } libreswan-4.14/lib/libswan/netlink_attrib.c000066400000000000000000000041041457372064200210230ustar00rootroot00000000000000/* * netlink attributes 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))) void 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); passert(NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) <= maxlen); struct rtattr *rta = NLMSG_TAIL(n); rta->rta_type = type; rta->rta_len = len; memcpy(RTA_DATA(rta), data, alen); n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len); } 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; } void nl_addattr_nest_end(struct nlmsghdr *n, struct rtattr *nest) { nest->rta_len = (void *)NLMSG_TAIL(n) - (void *)nest; } void nl_addattrstrz(struct nlmsghdr *n, int maxlen, int type, const char *str /*non-NULL*/) { nl_addattr_l(n, maxlen, type, str, strlen(str)+1); } void nl_addattr32(struct nlmsghdr *n, int maxlen, int type, const uint32_t data) { nl_addattr_l(n, maxlen, type, &data, sizeof(uint32_t)); } libreswan-4.14/lib/libswan/nss_cert_load.c000066400000000000000000000041461457372064200206370ustar00rootroot00000000000000/* * 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, struct logger *logger) { return nickname == NULL ? NULL : PK11_FindCertFromNickname(nickname, lsw_nss_get_password_context(logger)); } struct ckaid_match_arg { SECItem ckaid; CERTCertificate *cert; struct logger *logger; }; 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_nss_get_password_context(ckaid_match_arg->logger)); if (ckaid == NULL) { dbg("GetLowLevelID for cert %s failed", cert->nickname); return SECSuccess; } if (SECITEM_ItemsAreEqual(ckaid, &ckaid_match_arg->ckaid)) { dbg("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_from_nss(const ckaid_t *ckaid, struct logger *logger) { struct ckaid_match_arg ckaid_match_arg = { .cert = NULL, .ckaid = same_ckaid_as_secitem(ckaid), .logger = logger, }; PK11_TraverseSlotCerts(ckaid_match, &ckaid_match_arg, lsw_nss_get_password_context(logger)); return ckaid_match_arg.cert; } libreswan-4.14/lib/libswan/nss_copies.c000066400000000000000000000065621457372064200201710ustar00rootroot00000000000000/* 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-4.14/lib/libswan/oid.c000066400000000000000000000277761457372064200166110ustar00rootroot00000000000000/* * 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-4.14/lib/libswan/oid.pl000066400000000000000000000066121457372064200167640ustar00rootroot00000000000000#!/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-4.14/lib/libswan/oid.txt000066400000000000000000000153431457372064200171710ustar00rootroot00000000000000# 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-4.14/lib/libswan/passert.c000066400000000000000000000020751457372064200175000ustar00rootroot00000000000000/* * abort functions, for libreswan * * Copyright (C) 2017, 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. */ #include /* for abort() */ #include "passert.h" #include "lswlog.h" void llog_passert(const struct logger *logger, where_t where, const char *fmt, ...) { JAMBUF(buf) { jam_string(buf, "ABORT: ASSERTION FAILED: "); jam_logger_prefix(buf, logger); va_list ap; va_start(ap, fmt); jam_va_list(buf, fmt, ap); va_end(ap); jam(buf, " "PRI_WHERE, pri_where(where)); jambuf_to_logger(buf, logger, ERROR_FLAGS); } abort(); } libreswan-4.14/lib/libswan/pexpect.c000066400000000000000000000020271457372064200174640ustar00rootroot00000000000000/* pexpect, for libreswan * * Copyright (C) 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. * */ #include #include #include "lswlog.h" void llog_pexpect(const struct logger *logger, where_t where, const char *message, ...) { JAMBUF(buf) { jam_string(buf, "EXPECTATION FAILED: "); jam_logger_prefix(buf, logger); va_list ap; va_start(ap, message); jam_va_list(buf, message, ap); va_end(ap); jam(buf, " "PRI_WHERE, pri_where(where)); jambuf_to_logger(buf, logger, ERROR_FLAGS); } } libreswan-4.14/lib/libswan/pluto_exit_code_names.c000066400000000000000000000034231457372064200223660ustar00rootroot00000000000000/* tables of names for values defined in constants.h * * Copyright (C) 2022 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 "lswcdefs.h" /* for ARRAY_REF() */ #include "enum_names.h" #include "constants.h" /* for enum pluto_exit_code in pluto_constants.h */ static const char *pluto_exit_code_name_hi[] = { #define S(E) [E - PLUTO_EXIT_GIT_BISECT_CAN_NOT_TEST] = #E S(PLUTO_EXIT_GIT_BISECT_CAN_NOT_TEST), S(PLUTO_EXIT_SHELL_COMMAND_NOT_FOUND), S(PLUTO_EXIT_SHELL_COMMAND_NOT_EXECUTABLE), #undef S }; static enum_names pluto_exit_code_names_hi = { PLUTO_EXIT_GIT_BISECT_CAN_NOT_TEST, PLUTO_EXIT_SHELL_COMMAND_NOT_EXECUTABLE, ARRAY_REF(pluto_exit_code_name_hi), NULL, NULL, }; static const char *pluto_exit_code_name[] = { #define S(E) [E] = #E S(PLUTO_EXIT_OK), S(PLUTO_EXIT_FAIL), S(PLUTO_EXIT_SOCKET_FAIL), S(PLUTO_EXIT_FORK_FAIL), S(PLUTO_EXIT_FIPS_FAIL), S(PLUTO_EXIT_KERNEL_FAIL), S(PLUTO_EXIT_NSS_FAIL), S(PLUTO_EXIT_AUDIT_FAIL), S(PLUTO_EXIT_SECCOMP_FAIL), S(PLUTO_EXIT_UNBOUND_FAIL), S(PLUTO_EXIT_LOCK_FAIL), S(PLUTO_EXIT_SELINUX_FAIL), S(PLUTO_EXIT_LEAVE_STATE), #undef S }; enum_names pluto_exit_code_names = { PLUTO_EXIT_OK, PLUTO_EXIT_LEAVE_STATE, ARRAY_REF(pluto_exit_code_name), "PLUTO_EXIT_", /* prefix */ &pluto_exit_code_names_hi, }; libreswan-4.14/lib/libswan/portof.3.xml000066400000000000000000000075331457372064200200530ustar00rootroot00000000000000 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-4.14/lib/libswan/proposals.c000066400000000000000000000564401457372064200200460ustar00rootroot00000000000000/* * Algorithm info parsing and creation functions * Author: JuanJo Ciarlante * * Copyright (C) 2012 Paul Wouters * 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. */ #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; 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->diag = NULL; return parser; } void free_proposal_parser(struct proposal_parser **parser) { pfree_diag(&(*parser)->diag); 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 cannot 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->fqn); 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->fqn); return false; } return true; } /* * Proposals struct can be shared by a connection template and its * instances. Fortunately, the connection template is only deleted * after all instances. */ void free_proposals(struct proposals **proposals) { if ((*proposals) != NULL) { free_proposal(&(*proposals)->proposals); pfree((*proposals)); *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(const 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(const 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 { llog_passert(&global_logger, HERE, "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) { if (alg == NULL) { DBGF(DBG_PROPOSAL_PARSER, "no algorithm to append"); return; } enum proposal_algorithm algorithm = ike_to_proposal_algorithm(alg); passert(algorithm < elemsof(proposal->algorithms)); /* find end */ struct algorithm **end = &proposal->algorithms[algorithm]; while ((*end) != NULL) { end = &(*end)->next; } /* append */ struct algorithm new_algorithm = { .desc = alg, .enckeylen = enckeylen, }; DBGF(DBG_PROPOSAL_PARSER, "appending %s %s algorithm %s[_%d]", parser->protocol->name, ike_alg_type_name(alg->algo_type), alg->fqn, enckeylen); *end = clone_thing(new_algorithm, "alg"); } void remove_duplicate_algorithms(struct proposal_parser *parser, struct proposal *proposal, enum proposal_algorithm algorithm) { passert(algorithm < elemsof(proposal->algorithms)); /* XXX: not efficient */ for (struct algorithm *alg = proposal->algorithms[algorithm]; alg != NULL; alg = alg->next) { struct algorithm **dup = &alg->next; while ((*dup) != NULL) { /* * Since enckeylen=0 is a wildcard there's no * point following it enckeylen=128 say; OTOH * enckeylen=128 then enckeylen=0 is ok as * latter picks up 192 and 256. */ if (alg->desc == (*dup)->desc && (alg->desc->algo_type != IKE_ALG_ENCRYPT || alg->enckeylen == 0 || alg->enckeylen == (*dup)->enckeylen)) { struct algorithm *dead = (*dup); if (impair.proposal_parser) { llog(parser->policy->logger_rc_flags, parser->policy->logger, "IMPAIR: ignoring duplicate algorithms"); return; } LLOG_JAMBUF(parser->policy->logger_rc_flags, parser->policy->logger, buf) { jam(buf, "discarding duplicate %s %s algorithm %s", parser->protocol->name, ike_alg_type_name(dead->desc->algo_type), dead->desc->fqn); if (dead->enckeylen != 0) { jam(buf, "_%d", dead->enckeylen); } } (*dup) = (*dup)->next; /* remove */ pfree(dead); } else { dup = &(*dup)->next; /* advance */ } } } } void jam_proposal(struct jambuf *log, const struct proposal *proposal) { const char *ps = ""; /* proposal separator */ const char *as; /* attribute separator (within a proposal) */ # define startprop() { as = ps; } # define jamsep() { jam_string(log, as); ps = "-"; as = "+"; } as = ps; FOR_EACH_ALGORITHM(proposal, encrypt, alg) { const struct encrypt_desc *encrypt = encrypt_desc(alg->desc); jamsep(); jam_string(log, encrypt->common.fqn); if (alg->enckeylen != 0) { jam(log, "_%d", alg->enckeylen); } } startprop(); /* ESP, or AEAD */ bool print_integ = (impair.proposal_parser || /* no PRF */ next_algorithm(proposal, PROPOSAL_prf, NULL) == NULL || /* AEAD when not NONE */ (proposal_encrypt_aead(proposal) && !proposal_integ_none(proposal))); /* non-AEAD when PRF and INTEG don't match */ if (!print_integ && proposal_encrypt_norm(proposal)) { 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); } } if (print_integ) { FOR_EACH_ALGORITHM(proposal, integ, alg) { const struct integ_desc *integ = integ_desc(alg->desc); jamsep(); jam_string(log, integ->common.fqn); } } startprop(); FOR_EACH_ALGORITHM(proposal, prf, alg) { const struct prf_desc *prf = prf_desc(alg->desc); jamsep(); jam_string(log, prf->common.fqn); } startprop(); FOR_EACH_ALGORITHM(proposal, dh, alg) { const struct dh_desc *dh = dh_desc(alg->desc); jamsep(); jam_string(log, dh->common.fqn); } # undef startprop # undef jamsep } void jam_proposals(struct jambuf *log, const struct proposals *proposals) { const char *sep = ""; FOR_EACH_PROPOSAL(proposals, proposal) { jam_string(log, sep); jam_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) { llog(parser->policy->logger_rc_flags, parser->policy->logger, "ignoring redundant %s DH algorithm NONE as PFS policy is disabled", parser->protocol->name); } else if (dh != NULL) { llog(parser->policy->logger_rc_flags, parser->policy->logger, "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); passert(parser->diag == NULL); parser->diag = diag_va_list(fmt, ap); va_end(ap); } bool impair_proposal_errors(struct proposal_parser *parser) { passert(parser->diag != NULL); if (impair.proposal_parser) { llog_diag(parser->policy->logger_rc_flags, parser->policy->logger, &parser->diag, "IMPAIR: ignoring proposal error: "); 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) { free_proposals(&proposals); return NULL; } if (proposals->proposals == NULL) { free_proposals(&proposals); return NULL; } if (parser->policy->check_pfs_vs_dh && !proposals_pfs_vs_dh_check(parser, proposals)) { passert(parser->diag != NULL); free_proposals(&proposals); return NULL; } return proposals; } bool default_proposals(const struct proposals *proposals) { return proposals == NULL || proposals->defaulted; } /* * Try to parse any of -, _, * , or using some look-ahead. */ static int parse_proposal_eklen(struct proposal_parser *parser, shunk_t print, shunk_t buf) { passert(parser->diag == NULL); /* convert - if present */ char *end = NULL; long eklen = strtol(buf.ptr, &end, 10); if (buf.ptr + buf.len != end) { proposal_error(parser, "%s encryption algorithm '"PRI_SHUNK"' key length contains a non-numeric character", parser->protocol->name, pri_shunk(print)); return 0; } if (eklen >= INT_MAX) { proposal_error(parser, "%s encryption algorithm '"PRI_SHUNK"' key length WAY too big", parser->protocol->name, pri_shunk(print)); return 0; } if (eklen == 0) { proposal_error(parser, "%s encryption key length is zero", parser->protocol->name); return 0; } return eklen; } bool proposal_parse_encrypt(struct proposal_parser *parser, struct proposal_tokenizer *tokens, const struct ike_alg **encrypt, int *encrypt_keylen) { if (tokens->this.len == 0) { proposal_error(parser, "%s encryption algorithm is empty", parser->protocol->name); return false; } /* * Does it match -? * * Use the tokens NEXT lookahead to check first. If * it starts with a digit then just assume - and * error out if it is not so. */ if (tokens->this_term == '-' && tokens->next.len > 0 && char_isdigit(hunk_char(tokens->next, 0))) { /* assume - */ shunk_t ealg = tokens->this; shunk_t eklen = tokens->next; /* print "-" in errors */ shunk_t print = shunk2(ealg.ptr, eklen.ptr + eklen.len - ealg.ptr); int enckeylen = parse_proposal_eklen(parser, print, eklen); if (enckeylen <= 0) { passert(parser->diag != NULL); return false; } 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), str_diag(parser->diag)); return false; } /* consume - */ proposal_next_token(tokens); proposal_next_token(tokens); // append_algorithm(parser, proposal, alg, enckeylen); *encrypt = alg; *encrypt_keylen = enckeylen; return true; } /* * Does it match (without any _ suffix?) */ const shunk_t print = tokens->this; shunk_t ealg = tokens->this; const struct ike_alg *alg = encrypt_alg_byname(parser, ealg, 0/*enckeylen*/, print); if (alg != NULL) { /* consume */ proposal_next_token(tokens); // append_algorithm(parser, proposal, alg, 0/*enckeylen*/); *encrypt = alg; *encrypt_keylen = 0; return true; } /* buffer still contains error from lookup */ passert(parser->diag != NULL); /* * See if there's a trailing in . If there * isn't then the lookup error above can be returned. */ size_t end = ealg.len; while (end > 0 && char_isdigit(hunk_char(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->diag != NULL); return false; // warning_or_false(parser, "encryption", print); } /* buffer still contains error from lookup */ passert(parser->diag != NULL); pfree_diag(&parser->diag); /* * Try parsing the found in . For something * like aes_gcm_16, above lookup should have found the * algorithm so isn't a problem here. */ shunk_t eklen = shunk_slice(ealg, end, ealg.len); int enckeylen = parse_proposal_eklen(parser, print, eklen); if (enckeylen <= 0) { passert(parser->diag != NULL); return false; } /* * The in or _ parsed; trim * from and then try the lookup. */ ealg = shunk_slice(ealg, 0, end); if (hunk_char_ischar(ealg, ealg.len-1, "_")) { ealg = shunk_slice(ealg, 0, end-1); } pfree_diag(&parser->diag); /* zap old error */ alg = encrypt_alg_byname(parser, ealg, enckeylen, print); if (alg == NULL) { passert(parser->diag != NULL); return false; // warning_or_false(parser, "encryption", print); } /* consume */ proposal_next_token(tokens); // append_algorithm(parser, proposal, alg, enckeylen); *encrypt = alg; *encrypt_keylen = enckeylen; return true; } struct proposal_tokenizer proposal_first_token(shunk_t input, const char *delims) { struct proposal_tokenizer token = { .input = input, .delims = delims, }; /* parse next */ proposal_next_token(&token); /* next<-this; parse next */ proposal_next_token(&token); return token; } void proposal_next_token(struct proposal_tokenizer *tokens) { /* shuffle terminators */ tokens->prev_term = tokens->this_term; tokens->this_term = tokens->next_term; /* shuffle tokens */ tokens->this = tokens->next; tokens->next = shunk_token(&tokens->input, &tokens->next_term, tokens->delims); if (DBGP(DBG_PROPOSAL_PARSER)) { JAMBUF(buf) { jam(buf, "token: "); if (tokens->prev_term != '\0') { jam(buf, "'%c'", tokens->prev_term); } else { jam(buf, "''"); } jam(buf, " "); if (tokens->this.ptr == NULL) { jam(buf, ""); } else { jam(buf, "\""PRI_SHUNK"\"", pri_shunk(tokens->this)); } jam(buf, " "); if (tokens->this_term != '\0') { jam(buf, "'%c'", tokens->this_term); } else { jam(buf, "''"); } jam(buf, " "); if (tokens->next.ptr == NULL) { jam(buf, ""); } else { jam(buf, "\""PRI_SHUNK"\"", pri_shunk(tokens->next)); } jam(buf, " "); if (tokens->next_term != '\0') { jam(buf, "'%c'", tokens->next_term); } else { jam(buf, "''"); } jambuf_to_logger(buf, &global_logger, DEBUG_STREAM); } } } libreswan-4.14/lib/libswan/pubkey_der_to_pubkey_content.c000066400000000000000000000055441457372064200237670ustar00rootroot00000000000000/* Convert a private key to a Subect Public Key Info DER, for libreswan * * Copyright (C) 2022 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 "lswnss.h" #include "secrets.h" static diag_t seckey_to_pubkey_content(SECKEYPublicKey *seckey, struct pubkey_content *pkc) { KeyType key_type = seckey->keyType; switch (key_type) { case rsaKey: { chunk_t exponent = same_secitem_as_chunk(seckey->u.rsa.publicExponent); chunk_t modulus = same_secitem_as_chunk(seckey->u.rsa.modulus); SECItem *nss_ckaid = PK11_MakeIDFromPubKey(&seckey->u.rsa.modulus); if (nss_ckaid == NULL) { return diag("unable to compute 'CKAID' from modulus"); } pkc->ckaid = ckaid_from_secitem(nss_ckaid); SECITEM_FreeItem(nss_ckaid, PR_TRUE); size_t size; form_keyid(exponent, modulus, &pkc->keyid, &size); pkc->type = &pubkey_type_rsa; pkc->public_key = seckey; dbg_alloc("ecdsa->public_key", seckey, HERE); break; } case ecKey: { SECItem *nss_ckaid = PK11_MakeIDFromPubKey(&seckey->u.ec.publicValue); if (nss_ckaid == NULL) { return diag("unable to compute 'CKAID' from public value"); } pkc->ckaid = ckaid_from_secitem(nss_ckaid); SECITEM_FreeItem(nss_ckaid, PR_TRUE); err_t e = keyblob_to_keyid(pkc->ckaid.ptr, pkc->ckaid.len, &pkc->keyid); if (e != NULL) { return diag("%s", e); } pkc->type = &pubkey_type_ecdsa; pkc->public_key = seckey; dbg_alloc("ecdsa->public_key", seckey, HERE); break; } default: return diag("decoded Public Key has unknown type %d", key_type); } return NULL; } static diag_t spki_to_pubkey_content(CERTSubjectPublicKeyInfo *spki, struct pubkey_content *pkc) { SECKEYPublicKey *seckey = SECKEY_ExtractPublicKey(spki); if (seckey == NULL) { return diag_nss_error("extracting Public Key from Subject Public Key Info"); } diag_t d = seckey_to_pubkey_content(seckey, pkc); if (d != NULL) { SECKEY_DestroyPublicKey(seckey); } return d; } diag_t pubkey_der_to_pubkey_content(shunk_t der, struct pubkey_content *pkc) { SECItem der_item = same_shunk_as_secitem(der, siBuffer);/*loose const */ CERTSubjectPublicKeyInfo *spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&der_item); if (spki == NULL) { return diag_nss_error("decoding Subject Public Key Info DER"); } diag_t d = spki_to_pubkey_content(spki, pkc); SECKEY_DestroySubjectPublicKeyInfo(spki); return d; } libreswan-4.14/lib/libswan/pubkey_ecdsa.c000066400000000000000000000404261457372064200204570ustar00rootroot00000000000000/* * 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 #include #include /* * In addition to EC_POINT_FORM_UNCOMPRESSED, defines * things like AES_BLOCK_SIZE which conflicts with "ietf_constants.h". */ #if 0 #include #else #define EC_POINT_FORM_UNCOMPRESSED 0x04 #endif #include "lswnss.h" #include "lswlog.h" #include "secrets.h" #include "ike_alg_dh.h" /* for OID and size of EC algorithms */ #include "refcnt.h" /* for dbg_{alloc,free}() */ static diag_t ECDSA_ipseckey_rdata_to_pubkey_content(const shunk_t ipseckey_pubkey, struct pubkey_content *pkc) { static const struct dh_desc *dh[] = { &ike_alg_dh_secp256r1, &ike_alg_dh_secp384r1, &ike_alg_dh_secp521r1, }; /* * Look for an EC curve with the same length as * ipseckey_pubkey. * * Raw EC pubkeys contain the EC point (or points). */ const struct dh_desc *group = NULL; shunk_t raw = null_shunk; const uint8_t *const ipseckey_pubkey_ptr = ipseckey_pubkey.ptr; FOR_EACH_ELEMENT(e, dh) { /* * A simple match, the buffer cnotains just the key. */ if (ipseckey_pubkey.len == (*e)->bytes) { raw = HUNK_AS_SHUNK(ipseckey_pubkey); group = (*e); break; } /* * The raw IPSECKEY_PUBKEY, which could come from the * internet or a config file, can include the * EC_POINT_FORM_UNCOMPRESSED prefix. * * Allow for and strip that off when necessary. */ if (group->nss_adds_ec_point_form_uncompressed && ipseckey_pubkey.len == (*e)->bytes + 1 && ipseckey_pubkey_ptr[0] == EC_POINT_FORM_UNCOMPRESSED) { /* ignore prefix */ raw = shunk2(ipseckey_pubkey_ptr + 1, ipseckey_pubkey.len - 1); group = (*e); break; } } if (group == NULL) { return diag("unrecognized EC Public Key with length %zu", ipseckey_pubkey.len); } passert(raw.ptr != NULL && raw.len > 0); /* * Allocate the public key, giving it its own NSS arena. * * Since the arena contains everything allocated to the * seckey, error recovery just requires freeing that. */ PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (arena == NULL) { return diag_nss_error("allocating ECDSA arena"); } SECKEYPublicKey *seckey = PORT_ArenaZNew(arena, SECKEYPublicKey); if (seckey == NULL) { diag_t d = diag_nss_error("allocating ECDSA SECKEYPublicKey"); PORT_FreeArena(arena, /*zero?*/PR_TRUE); return d; } seckey->arena = arena; seckey->keyType = ecKey; seckey->pkcs11Slot = NULL; seckey->pkcs11ID = CK_INVALID_HANDLE; SECKEYECPublicKey *ec = &seckey->u.ec; /* * Copy the RAW EC point(s) into the arena, adding them to the * public key. */ if (SECITEM_AllocItem(arena, &ec->publicValue, raw.len + 1) == NULL) { diag_t d = diag_nss_error("copying 'k' to EDSA public key"); PORT_FreeArena(arena, /*zero?*/PR_TRUE); return d; } ec->publicValue.data[0] = EC_POINT_FORM_UNCOMPRESSED; memcpy(ec->publicValue.data + 1, raw.ptr, raw.len); /* * Copy the OID (wrapped in ASN.1 ObjectID template) into the * arena, adding it to the public key. * * See also DH code. */ const SECOidData *ec_oid = SECOID_FindOIDByTag(group->nss_oid); /*static*/ if (ec_oid == NULL) { diag_t d = diag_nss_error("lookup of EC OID failed"); PORT_FreeArena(arena, /*zero?*/PR_TRUE); return d; } if (SEC_ASN1EncodeItem(arena, &ec->DEREncodedParams, &ec_oid->oid, SEC_ObjectIDTemplate) == NULL) { diag_t d = diag_nss_error("ASN.1 encoding of EC OID failed"); PORT_FreeArena(arena, /*zero?*/PR_TRUE); return d; } /* * Maintain magic values. */ /* should this include EC? */ SECItem *nss_ckaid = PK11_MakeIDFromPubKey(&ec->publicValue); if (nss_ckaid == NULL) { diag_t d = diag_nss_error("unable to compute 'CKAID' from public value"); PORT_FreeArena(arena, /*zero?*/PR_TRUE); return d; } pkc->ckaid = ckaid_from_secitem(nss_ckaid); SECITEM_FreeItem(nss_ckaid, PR_TRUE); /* * Use the ckaid since that digested the entire pubkey (this * is made up) */ err_t e = keyblob_to_keyid(pkc->ckaid.ptr, pkc->ckaid.len, &pkc->keyid); if (e != NULL) { diag_t d = diag("%s", e); PORT_FreeArena(arena, /*zero?*/PR_TRUE); return d; } pkc->type = &pubkey_type_ecdsa; pkc->public_key = seckey; dbg_alloc("pkc->public_key(ecdsa)", seckey, HERE); if (DBGP(DBG_BASE)) { /* pubkey information isn't DBG_PRIVATE */ DBG_log("ECDSA Key:"); DBG_log("keyid: *%s", str_keyid(pkc->keyid)); DBG_dump("pub", ec->publicValue.data, ec->publicValue.len); DBG_dump_hunk("CKAID", pkc->ckaid); } return NULL; } static err_t ECDSA_pubkey_content_to_ipseckey_rdata(const struct pubkey_content *ecdsa, chunk_t *ipseckey_pubkey, enum ipseckey_algorithm_type *ipseckey_algorithm) { const SECKEYECPublicKey *ec = &ecdsa->public_key->u.ec; passert((ec->publicValue.len & 1) == 1); passert(ec->publicValue.data[0] == EC_POINT_FORM_UNCOMPRESSED); *ipseckey_pubkey = clone_bytes_as_chunk(ec->publicValue.data + 1, ec->publicValue.len - 1, "EC POINTS (even)"); *ipseckey_algorithm = IPSECKEY_ALGORITHM_ECDSA; return NULL; } static void ECDSA_free_pubkey_content(struct pubkey_content *ecdsa) { dbg_free("ecdsa->public_key", ecdsa->public_key, HERE); SECKEY_DestroyPublicKey(ecdsa->public_key); ecdsa->public_key = NULL; } static err_t ECDSA_extract_pubkey_content(struct pubkey_content *pkc, SECKEYPublicKey *seckey_public, SECItem *ckaid_nss) { pkc->type = &pubkey_type_ecdsa; pkc->public_key = SECKEY_CopyPublicKey(seckey_public); dbg_alloc("pkc->public_key(ecdsa)", pkc->public_key, HERE); pkc->ckaid = ckaid_from_secitem(ckaid_nss); /* keyid; make this up */ err_t e = keyblob_to_keyid(pkc->ckaid.ptr, pkc->ckaid.len, &pkc->keyid); passert(e == NULL); if (DBGP(DBG_BASE)) { ckaid_buf cb; DBG_log("ECDSA keyid *%s", str_keyid(pkc->keyid)); DBG_log("ECDSA keyid *%s", str_ckaid(&pkc->ckaid, &cb)); } /* * The only unsafe (according to FIPS) curve is p192, and NSS * does not implement this, so there is no ECDSA curve that * libreswan needs to disallow for security reasons */ return NULL; } static bool ECDSA_pubkey_same(const struct pubkey_content *lhs, const struct pubkey_content *rhs) { /* * 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. */ bool e = hunk_eq(same_secitem_as_shunk(lhs->public_key->u.ec.publicValue), same_secitem_as_shunk(rhs->public_key->u.ec.publicValue)); if (DBGP(DBG_CRYPT)) { DBG_log("e did %smatch", e ? "" : "NOT "); } return lhs == rhs || e; } static size_t ECDSA_strength_in_bits(const struct pubkey *pubkey) { return SECKEY_PublicKeyStrengthInBits(pubkey->content.public_key); } const struct pubkey_type pubkey_type_ecdsa = { .name = "ECDSA", .private_key_kind = SECRET_ECDSA, /* XXX: delete field */ .ipseckey_rdata_to_pubkey_content = ECDSA_ipseckey_rdata_to_pubkey_content, .pubkey_content_to_ipseckey_rdata = ECDSA_pubkey_content_to_ipseckey_rdata, .free_pubkey_content = ECDSA_free_pubkey_content, .extract_pubkey_content = ECDSA_extract_pubkey_content, .pubkey_same = ECDSA_pubkey_same, .strength_in_bits = ECDSA_strength_in_bits, }; static struct hash_signature ECDSA_raw_sign_hash(const struct secret_stuff *pks, const uint8_t *hash_val, size_t hash_len, const struct hash_desc *hash_algo_unused UNUSED, struct logger *logger) { DBGF(DBG_CRYPT, "%s: started using NSS", __func__); if (!pexpect(pks->u.pubkey.private_key != NULL)) { dbg("no private key!"); return (struct hash_signature) { .len = 0, }; } /* point HASH to sign at HASH_VAL */ SECItem hash_to_sign = { .type = siBuffer, .len = hash_len, .data = DISCARD_CONST(uint8_t *, hash_val), }; /* point signature at the SIG_VAL buffer */ struct hash_signature signature = {0}; SECItem raw_signature = { .type = siBuffer, .len = PK11_SignatureLen(pks->u.pubkey.private_key), .data = signature.ptr/*array*/, }; passert(raw_signature.len <= sizeof(signature.ptr/*array*/)); dbg("ECDSA signature.len %d", raw_signature.len); /* create the raw signature */ SECStatus s = PK11_Sign(pks->u.pubkey.private_key, &raw_signature, &hash_to_sign); if (DBGP(DBG_CRYPT)) { DBG_dump("PK11_Sign()", raw_signature.data, raw_signature.len); } if (s != SECSuccess) { /* PR_GetError() returns the thread-local error */ llog_nss_error(RC_LOG_SERIOUS, logger, "ECDSA sign function failed"); return (struct hash_signature) { .len = 0, }; } passert(sizeof(signature.ptr/*array*/) >= raw_signature.len); signature.len = raw_signature.len; dbg("%s: signed hash", __func__); return signature; } static bool ECDSA_raw_authenticate_signature(const struct crypt_mac *hash, shunk_t signature, struct pubkey *kr, const struct hash_desc *unused_hash_algo UNUSED, diag_t *fatal_diag, struct logger *logger) { const struct pubkey_content *ecdsa = &kr->content; /* * Turn the signature and hash into SECItem/s (NSS doesn't do * const, but it does pretend). */ const SECItem raw_signature = { .type = siBuffer, .data = DISCARD_CONST(uint8_t *, signature.ptr),/*NSS doesn't do const*/ .len = signature.len }; const SECItem hash_item = { .type = siBuffer, .data = DISCARD_CONST(uint8_t *, hash->ptr),/*NSS doesn't do const*/ .len = hash->len, }; if (DBGP(DBG_CRYPT)) { LLOG_JAMBUF(DEBUG_STREAM, logger, buf) { jam(buf, "%d-byte raw ESCSA signature: ", raw_signature.len); jam_nss_secitem(buf, &raw_signature); } LLOG_JAMBUF(DEBUG_STREAM, logger, buf) { jam(buf, "%d-byte hash: ", hash_item.len); jam_nss_secitem(buf, &hash_item); } } if (PK11_Verify(ecdsa->public_key, &raw_signature, &hash_item, lsw_nss_get_password_context(logger)) != SECSuccess) { llog_nss_error(DEBUG_STREAM, logger, "verifying AUTH hash using PK11_Verify() failed:"); *fatal_diag = NULL; return false; } dbg("%s: verified signature", __func__); *fatal_diag = NULL; return true; } static size_t ECDSA_jam_auth_method(struct jambuf *buf, const struct pubkey_signer *signer, const struct pubkey *pubkey, const struct hash_desc *hash) { return jam(buf, "P-%d %s with %s", SECKEY_PublicKeyStrengthInBits(pubkey->content.public_key), signer->name, hash->common.fqn); } const struct pubkey_signer pubkey_signer_raw_ecdsa = { .name = "ECDSA", /* name from RFC 7427 */ .type = &pubkey_type_ecdsa, .digital_signature_blob = DIGITAL_SIGNATURE_BLOB_ROOF, .sign_hash = ECDSA_raw_sign_hash, .authenticate_signature = ECDSA_raw_authenticate_signature, .jam_auth_method = ECDSA_jam_auth_method, }; static struct hash_signature ECDSA_digsig_sign_hash(const struct secret_stuff *pks, const uint8_t *hash_val, size_t hash_len, const struct hash_desc *hash_algo_unused UNUSED, struct logger *logger) { if (!pexpect(pks->u.pubkey.private_key != NULL)) { dbg("no private key!"); return (struct hash_signature) { .len = 0, }; } DBGF(DBG_CRYPT, "ECDSA_sign_hash: Started using NSS"); /* point HASH to sign at HASH_VAL */ SECItem hash_to_sign = { .type = siBuffer, .len = hash_len, .data = DISCARD_CONST(uint8_t *, hash_val), }; /* point signature at the SIG_VAL buffer */ uint8_t raw_signature_data[sizeof(struct hash_signature)]; SECItem raw_signature = { .type = siBuffer, .len = PK11_SignatureLen(pks->u.pubkey.private_key), .data = raw_signature_data, }; passert(raw_signature.len <= sizeof(raw_signature_data)); dbg("ECDSA signature.len %d", raw_signature.len); /* create the raw signature */ SECStatus s = PK11_Sign(pks->u.pubkey.private_key, &raw_signature, &hash_to_sign); if (DBGP(DBG_CRYPT)) { DBG_dump("sig_from_nss", raw_signature.data, raw_signature.len); } if (s != SECSuccess) { /* PR_GetError() returns the thread-local error */ llog_nss_error(RC_LOG_SERIOUS, logger, "ECDSA sign function failed"); return (struct hash_signature) { .len = 0, }; } SECItem encoded_signature = {0,}; /* must be initialized*/ if (DSAU_EncodeDerSigWithLen(&encoded_signature, &raw_signature, raw_signature.len) != SECSuccess) { /* PR_GetError() returns the thread-local error */ llog_nss_error(RC_LOG, logger, "NSS: constructing DER encoded ECDSA signature using DSAU_EncodeDerSigWithLen() failed:"); return (struct hash_signature) { .len = 0, }; } struct hash_signature signature = { .len = encoded_signature.len, }; passert(encoded_signature.len <= sizeof(signature.ptr/*an-array*/)); memcpy(signature.ptr, encoded_signature.data, encoded_signature.len); SECITEM_FreeItem(&encoded_signature, PR_FALSE); DBGF(DBG_CRYPT, "ECDSA_sign_hash: Ended using NSS"); return signature; } static bool ECDSA_digsig_authenticate_signature(const struct crypt_mac *hash, shunk_t signature, struct pubkey *pubkey, const struct hash_desc *unused_hash_algo UNUSED, diag_t *fatal_diag, struct logger *logger) { const struct pubkey_content *ecdsa = &pubkey->content; /* * Convert the signature into raw form (NSS doesn't do const). */ SECItem der_signature = { .type = siBuffer, .data = DISCARD_CONST(unsigned char *, signature.ptr),/*NSS doesn't do const*/ .len = signature.len }; if (DBGP(DBG_BASE)) { LLOG_JAMBUF(DEBUG_STREAM, logger, buf) { jam(buf, "%d-byte DER encoded ECDSA signature: ", der_signature.len); jam_nss_secitem(buf, &der_signature); } } SECItem *raw_signature = DSAU_DecodeDerSigToLen(&der_signature, SECKEY_SignatureLen(ecdsa->public_key)); if (raw_signature == NULL) { /* not fatal as dependent on key being tried */ llog_nss_error(DEBUG_STREAM, logger, "unpacking DER encoded ECDSA signature using DSAU_DecodeDerSigToLen()"); *fatal_diag = NULL; return false; } if (DBGP(DBG_BASE)) { LLOG_JAMBUF(DEBUG_STREAM, logger, buf) { jam(buf, "%d-byte raw ESCSA signature: ", raw_signature->len); jam_nss_secitem(buf, raw_signature); } } /* * put the hash somewhere writable; so it can later be logged? * * XXX: cast away const? */ struct crypt_mac hash_data = *hash; SECItem hash_item = { .type = siBuffer, .data = hash_data.ptr, .len = hash_data.len, }; if (PK11_Verify(ecdsa->public_key, raw_signature, &hash_item, lsw_nss_get_password_context(logger)) != SECSuccess) { llog_nss_error(DEBUG_STREAM, logger, "verifying AUTH hash using PK11_Verify() failed:"); SECITEM_FreeItem(raw_signature, PR_TRUE/*and-pointer*/); *fatal_diag = NULL; return false; } dbg("NSS: verified signature"); SECITEM_FreeItem(raw_signature, PR_TRUE); *fatal_diag = NULL; return true; } const struct pubkey_signer pubkey_signer_digsig_ecdsa = { .name = "ECDSA", /* name from RFC 7427 */ .type = &pubkey_type_ecdsa, .digital_signature_blob = DIGITAL_SIGNATURE_ECDSA_BLOB, .sign_hash = ECDSA_digsig_sign_hash, .authenticate_signature = ECDSA_digsig_authenticate_signature, .jam_auth_method = ECDSA_jam_auth_method, }; libreswan-4.14/lib/libswan/pubkey_rsa.c000066400000000000000000000542141457372064200201650ustar00rootroot00000000000000/* * 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 #include #include "lswnss.h" #include "lswlog.h" #include "secrets.h" #include "ike_alg.h" #include "ike_alg_hash.h" /* * Deal with RFC Resource Records as defined in rfc3110 (nee rfc2537). */ static err_t RSA_pubkey_content_to_ipseckey_rdata(const struct pubkey_content *pkc, chunk_t *ipseckey_pubkey, enum ipseckey_algorithm_type *ipseckey_algorithm) { SECKEYRSAPublicKey *rsa = &pkc->public_key->u.rsa; chunk_t exponent = same_secitem_as_chunk(rsa->publicExponent); chunk_t modulus = same_secitem_as_chunk(rsa->modulus); *ipseckey_pubkey = EMPTY_CHUNK; *ipseckey_algorithm = 0; /* * 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; uint8_t *buf = alloc_bytes(rrlen, "buffer for rfc3110"); uint8_t *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; *ipseckey_algorithm = IPSECKEY_ALGORITHM_RSA; *ipseckey_pubkey = (chunk_t) { .ptr = buf, .len = p - buf, }; return NULL; } /* * Note: e and n will point int rr. * * See https://www.rfc-editor.org/rfc/rfc3110#section-2 */ static diag_t pubkey_ipseckey_rdata_to_rsa_pubkey(shunk_t rr, shunk_t *e, shunk_t *n) { *e = null_shunk; *n = null_shunk; /* * Step 1: find the bounds of the exponent and modulus within * the resource record and verify that they are sane. * * XXX: this isn't an ASN.1 encoded length so what is it? */ shunk_t exponent = null_shunk; const uint8_t *const rr_ptr = rr.ptr; if (rr.len >= 2 && rr_ptr[0] != 0x00) { /* * Exponent length is one-byte, followed by that many * exponent bytes */ exponent = shunk2(rr_ptr + 1, 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 = shunk2(rr_ptr + 3, (rr_ptr[1] << BITS_PER_BYTE) + rr_ptr[2]); } else { /* not even room for length! */ return diag("%zu byte raw RSA public is way too short", rr.len); } /* * Does the exponent fall off the end of the resource record? */ const uint8_t *const exponent_end = exponent.ptr + exponent.len; const uint8_t *const rr_end = rr_ptr + rr.len; if (exponent_end > rr_end) { return diag("%zu byte raw RSA public key is too short for exponent of length %zu", rr.len, exponent.len); } /* * What is left over forms the modulus. * * XXX: This overlaps RSA_secret_sane. */ shunk_t modulus = shunk2(exponent_end, rr_end - exponent_end); if (modulus.len < RSA_MIN_OCTETS_RFC) { return diag("%zu byte raw RSA public key %zu byte modulus is shorter than RFC minimum %d", rr.len, modulus.len, RSA_MIN_OCTETS_RFC); } if (modulus.len < RSA_MIN_OCTETS) { return diag("%zu byte raw RSA public key %zu byte modulus is shorter than minimum %d", rr.len, modulus.len, RSA_MIN_OCTETS); } struct hash_signature scratch_signature; size_t max_hash_size = sizeof(scratch_signature.ptr/*array*/); if (modulus.len > max_hash_size) { return diag("%zu byte raw RSA public key %zu byte modulus is longer than maximum %zu", rr.len, modulus.len, max_hash_size); } /* * Step 2: all looks good, export the slices */ *e = exponent; *n = modulus; return NULL; } static diag_t RSA_ipseckey_rdata_to_pubkey_content(shunk_t ipseckey_pubkey, struct pubkey_content *pkc) { /* unpack */ shunk_t exponent; shunk_t modulus; diag_t d = pubkey_ipseckey_rdata_to_rsa_pubkey(ipseckey_pubkey, &exponent, &modulus); if (d != NULL) { return d; } /* * Allocate the public key, giving it its own arena. * * Since the arena contains everything allocated to the * seckey, error recovery just requires freeing that. */ PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (arena == NULL) { return diag_nss_error("allocating RSA arena"); } SECKEYPublicKey *seckey = PORT_ArenaZNew(arena, SECKEYPublicKey); if (seckey == NULL) { diag_t d = diag_nss_error("allocating RSA SECKEYPublicKey"); PORT_FreeArena(arena, /*zero?*/PR_TRUE); return d; } seckey->arena = arena; seckey->keyType = rsaKey; seckey->pkcs11Slot = NULL; seckey->pkcs11ID = CK_INVALID_HANDLE; SECKEYRSAPublicKey *rsa = &seckey->u.rsa; /* * Copy n and e to form the public key in the SECKEYPublicKey * data structure */ if (SECITEM_MakeItem(arena, &rsa->modulus, modulus.ptr, modulus.len) != SECSuccess) { diag_t d = diag_nss_error("copying 'n' (modulus) to RSA SECKEYPublicKey"); PORT_FreeArena(arena, /*zero?*/PR_TRUE); return d; } if (SECITEM_MakeItem(arena, &rsa->publicExponent, exponent.ptr, exponent.len) != SECSuccess) { diag_t d = diag_nss_error("copying 'e' (exponent) to RSA public key"); PORT_FreeArena(arena, /*zero?*/PR_TRUE); return d; } /* ckaid */ SECItem *nss_ckaid = PK11_MakeIDFromPubKey(&rsa->modulus); if (nss_ckaid == NULL) { diag_t d = diag_nss_error("unable to compute 'CKAID' from modulus"); PORT_FreeArena(arena, /*zero?*/PR_TRUE); return d; } if (DBGP(DBG_BASE)) { DBG_dump("computed rsa CKAID", nss_ckaid->data, nss_ckaid->len); } pkc->ckaid = ckaid_from_secitem(nss_ckaid); SECITEM_FreeItem(nss_ckaid, PR_TRUE); err_t kberr = keyblob_to_keyid(ipseckey_pubkey.ptr, ipseckey_pubkey.len, &pkc->keyid); if (kberr != NULL) { diag_t d = diag("%s", kberr); PORT_FreeArena(arena, /*zero?*/PR_TRUE); return d; } pkc->type = &pubkey_type_rsa; pkc->public_key = seckey; dbg_alloc("rsa->public_key", pkc->public_key, HERE); /* generate the CKAID */ if (DBGP(DBG_BASE)) { /* pubkey information isn't DBG_PRIVATE */ DBG_log("keyid: *%s", str_keyid(pkc->keyid)); DBG_dump_hunk(" n", modulus); DBG_dump_hunk(" e", exponent); DBG_dump_hunk(" CKAID", pkc->ckaid); } return NULL; } static void RSA_free_pubkey_content(struct pubkey_content *rsa) { SECKEY_DestroyPublicKey(rsa->public_key); dbg_free("rsa->public_key", rsa->public_key, HERE); rsa->public_key = NULL; } static err_t RSA_extract_pubkey_content(struct pubkey_content *pkc, SECKEYPublicKey *seckey_public, SECItem *cert_ckaid) { chunk_t exponent = same_secitem_as_chunk(seckey_public->u.rsa.publicExponent); chunk_t modulus = same_secitem_as_chunk(seckey_public->u.rsa.modulus); size_t size; form_keyid(exponent, modulus, &pkc->keyid, &size); /* up to this point nothing has been allocated */ /* * PKCS#1 1.5 section 6 requires modulus to have at least 12 * octets. * * We actually require more (for security). */ if (size < RSA_MIN_OCTETS) return RSA_MIN_OCTETS_UGH; /* * We picked a max modulus size to simplify buffer allocation. */ struct hash_signature scratch_signature; size_t max_hash_size = sizeof(scratch_signature.ptr/*array*/); if (modulus.len > max_hash_size) { return "RSA modulus too large for signature buffer"; } /* now allocate */ pkc->type = &pubkey_type_rsa; pkc->public_key = SECKEY_CopyPublicKey(seckey_public); dbg_alloc("rsa->public_key", pkc->public_key, HERE); pkc->ckaid = ckaid_from_secitem(cert_ckaid); return NULL; } static bool RSA_pubkey_same(const struct pubkey_content *lhs, const struct pubkey_content *rhs) { /* * 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. */ bool e = hunk_eq(same_secitem_as_shunk(lhs->public_key->u.rsa.publicExponent), same_secitem_as_shunk(rhs->public_key->u.rsa.publicExponent)); bool n = hunk_eq(same_secitem_as_shunk(lhs->public_key->u.rsa.modulus), same_secitem_as_shunk(rhs->public_key->u.rsa.modulus)); if (DBGP(DBG_CRYPT)) { DBG_log("n did %smatch", n ? "" : "NOT "); DBG_log("e did %smatch", e ? "" : "NOT "); } return lhs == rhs || (e && n); } static size_t RSA_strength_in_bits(const struct pubkey *pubkey) { return SECKEY_PublicKeyStrengthInBits(pubkey->content.public_key); } const struct pubkey_type pubkey_type_rsa = { .name = "RSA", .private_key_kind = SECRET_RSA, /* XXX: delete field */ .free_pubkey_content = RSA_free_pubkey_content, .ipseckey_rdata_to_pubkey_content = RSA_ipseckey_rdata_to_pubkey_content, .pubkey_content_to_ipseckey_rdata = RSA_pubkey_content_to_ipseckey_rdata, .extract_pubkey_content = RSA_extract_pubkey_content, .pubkey_same = RSA_pubkey_same, .strength_in_bits = RSA_strength_in_bits, }; /* returns the length of the result on success; 0 on failure */ static struct hash_signature RSA_sign_hash_raw_rsa(const struct secret_stuff *pks, const uint8_t *hash_val, size_t hash_len, const struct hash_desc *hash_algo, struct logger *logger) { dbg("%s: started using NSS", __func__); if (!pexpect(hash_algo == &ike_alg_hash_sha1)) { return (struct hash_signature) { .len = 0, }; } if (!pexpect(pks->u.pubkey.private_key != NULL)) { dbg("no private key!"); return (struct hash_signature) { .len = 0, }; } SECItem data = { .type = siBuffer, .len = hash_len, .data = DISCARD_CONST(uint8_t *, hash_val), }; struct hash_signature sig = { .len = PK11_SignatureLen(pks->u.pubkey.private_key), }; passert(sig.len <= sizeof(sig.ptr/*array*/)); SECItem signature = { .type = siBuffer, .len = sig.len, .data = sig.ptr, }; SECStatus s = PK11_Sign(pks->u.pubkey.private_key, &signature, &data); if (s != SECSuccess) { /* PR_GetError() returns the thread-local error */ llog_nss_error(RC_LOG_SERIOUS, logger, "PK11_Sign() function failed"); return (struct hash_signature) { .len = 0, }; } dbg("%s: ended using NSS", __func__); return sig; } static bool RSA_authenticate_signature_raw_rsa(const struct crypt_mac *expected_hash, shunk_t signature, struct pubkey *pubkey, const struct hash_desc *unused_hash_algo UNUSED, diag_t *fatal_diag, struct logger *logger) { SECKEYPublicKey *seckey_public = pubkey->content.public_key; /* decrypt the signature -- reversing RSA_sign_hash */ if (signature.len != (size_t)seckey_public->u.rsa.modulus.len) { /* XXX notification: INVALID_KEY_INFORMATION */ *fatal_diag = NULL; return false; } if (DBGP(DBG_BASE)) { DBG_dump_hunk("NSS RSA: verifying that decrypted signature matches hash: ", *expected_hash); } /* * Use the same space used by the out going hash. */ SECItem decrypted_signature = { .type = siBuffer, }; if (SECITEM_AllocItem(NULL, &decrypted_signature, signature.len) == NULL) { llog_nss_error(RC_LOG, logger, "allocating space for decrypted RSA signature"); return false; } /* NSS doesn't do const */ const SECItem encrypted_signature = { .type = siBuffer, .data = DISCARD_CONST(unsigned char *, signature.ptr), .len = signature.len, }; if (PK11_VerifyRecover(seckey_public, &encrypted_signature, &decrypted_signature, lsw_nss_get_password_context(logger)) != SECSuccess) { SECITEM_FreeItem(&decrypted_signature, PR_FALSE/*not-pointer*/); dbg("NSS RSA verify: decrypting signature is failed"); *fatal_diag = NULL; return false; } if (DBGP(DBG_CRYPT)) { LLOG_JAMBUF(DEBUG_STREAM, logger, buf) { jam_string(buf, "NSS RSA verify: decrypted sig: "); jam_nss_secitem(buf, &decrypted_signature); } } /* * Expect the matching hash to appear at the end. See above * for length check. It may, or may not, be prefixed by a * PKCS#1 1.5 RSA ASN.1 blob. */ passert(decrypted_signature.len >= expected_hash->len); uint8_t *start = (decrypted_signature.data + decrypted_signature.len - expected_hash->len); if (!memeq(start, expected_hash->ptr, expected_hash->len)) { dbg("RSA Signature NOT verified"); SECITEM_FreeItem(&decrypted_signature, PR_FALSE/*not-pointer*/); *fatal_diag = NULL; return false; } SECITEM_FreeItem(&decrypted_signature, PR_FALSE/*not-pointer*/); *fatal_diag = NULL; return true; } static size_t RSA_jam_auth_method(struct jambuf *buf, const struct pubkey_signer *signer, const struct pubkey *pubkey, const struct hash_desc *hash) { return jam(buf, "%d-bit %s with %s", SECKEY_PublicKeyStrengthInBits(pubkey->content.public_key), signer->name, hash->common.fqn); } const struct pubkey_signer pubkey_signer_raw_rsa = { .name = "RSA", .digital_signature_blob = DIGITAL_SIGNATURE_BLOB_ROOF, .type = &pubkey_type_rsa, .sign_hash = RSA_sign_hash_raw_rsa, .authenticate_signature = RSA_authenticate_signature_raw_rsa, .jam_auth_method = RSA_jam_auth_method, }; /* returns the length of the result on success; 0 on failure */ static struct hash_signature RSA_sign_hash_pkcs1_1_5_rsa(const struct secret_stuff *pks, const uint8_t *hash_val, size_t hash_len, const struct hash_desc *hash_algo, struct logger *logger) { dbg("%s: started using NSS", __func__); if (!pexpect(pks->u.pubkey.private_key != NULL)) { dbg("no private key!"); return (struct hash_signature) { .len = 0, }; } SECItem digest = { .type = siBuffer, .len = hash_len, .data = DISCARD_CONST(uint8_t *, hash_val), }; /* * XXX: the call expects the OID TAG for the hash algorithm * used to generate the signature. */ SECItem signature_result = {0}; SECStatus s = SGN_Digest(pks->u.pubkey.private_key, hash_algo->nss.oid_tag, &signature_result, &digest); if (s != SECSuccess) { /* PR_GetError() returns the thread-local error */ enum_buf tb; llog_nss_error(RC_LOG_SERIOUS, logger, "SGN_Digest(%s) function failed", str_nss_oid(hash_algo->nss.oid_tag, &tb)); return (struct hash_signature) { .len = 0, }; } /* save the signature, free the returned pointer */ struct hash_signature signature = { .len = PK11_SignatureLen(pks->u.pubkey.private_key), }; passert(signature.len <= sizeof(signature.ptr/*array*/)); memcpy(signature.ptr, signature_result.data, signature.len); PORT_Free(signature_result.data); dbg("%s: ended using NSS", __func__); return signature; } static bool RSA_authenticate_signature_pkcs1_1_5_rsa(const struct crypt_mac *expected_hash, shunk_t signature, struct pubkey *pubkey, const struct hash_desc *unused_hash_algo UNUSED, diag_t *fatal_diag, struct logger *logger) { SECKEYPublicKey *seckey_public = pubkey->content.public_key; /* decrypt the signature -- reversing RSA_sign_hash */ if (signature.len != (size_t)seckey_public->u.rsa.modulus.len) { /* XXX notification: INVALID_KEY_INFORMATION */ *fatal_diag = NULL; return false; } if (DBGP(DBG_BASE)) { DBG_dump_hunk("NSS RSA: verifying that decrypted signature matches hash: ", *expected_hash); } /* * Use the same space used by the out going hash. */ SECItem decrypted_signature = { .type = siBuffer, }; if (SECITEM_AllocItem(NULL, &decrypted_signature, signature.len) == NULL) { llog_nss_error(RC_LOG, logger, "allocating space for decrypted RSA signature"); return false; } /* NSS doesn't do const */ const SECItem encrypted_signature = { .type = siBuffer, .data = DISCARD_CONST(unsigned char *, signature.ptr), .len = signature.len, }; if (PK11_VerifyRecover(seckey_public, &encrypted_signature, &decrypted_signature, lsw_nss_get_password_context(logger)) != SECSuccess) { SECITEM_FreeItem(&decrypted_signature, PR_FALSE/*not-pointer*/); dbg("NSS RSA verify: decrypting signature is failed"); *fatal_diag = NULL; return false; } if (DBGP(DBG_CRYPT)) { LLOG_JAMBUF(DEBUG_STREAM, logger, buf) { jam_string(buf, "NSS RSA verify: decrypted sig: "); jam_nss_secitem(buf, &decrypted_signature); } } /* * Expect the matching hash to appear at the end. See above * for length check. It may, or may not, be prefixed by a * PKCS#1 1.5 RSA ASN.1 blob. */ passert(decrypted_signature.len >= expected_hash->len); uint8_t *start = (decrypted_signature.data + decrypted_signature.len - expected_hash->len); if (!memeq(start, expected_hash->ptr, expected_hash->len)) { dbg("RSA Signature NOT verified"); SECITEM_FreeItem(&decrypted_signature, PR_FALSE/*not-pointer*/); *fatal_diag = NULL; return false; } SECITEM_FreeItem(&decrypted_signature, PR_FALSE/*not-pointer*/); *fatal_diag = NULL; return true; } const struct pubkey_signer pubkey_signer_raw_pkcs1_1_5_rsa = { .name = "PKCS#1 1.5 RSA", /* name from RFC 7427 */ .digital_signature_blob = DIGITAL_SIGNATURE_BLOB_ROOF, .type = &pubkey_type_rsa, .sign_hash = RSA_sign_hash_pkcs1_1_5_rsa, .authenticate_signature = RSA_authenticate_signature_pkcs1_1_5_rsa, .jam_auth_method = RSA_jam_auth_method, }; const struct pubkey_signer pubkey_signer_digsig_pkcs1_1_5_rsa = { .name = "PKCS#1 1.5 RSA", /* name from RFC 7427 */ .digital_signature_blob = DIGITAL_SIGNATURE_PKCS1_1_5_RSA_BLOB, .type = &pubkey_type_rsa, .sign_hash = RSA_sign_hash_pkcs1_1_5_rsa, .authenticate_signature = RSA_authenticate_signature_pkcs1_1_5_rsa, .jam_auth_method = RSA_jam_auth_method, }; /* returns the length of the result on success; 0 on failure */ static struct hash_signature RSA_sign_hash_rsassa_pss(const struct secret_stuff *pks, const uint8_t *hash_val, size_t hash_len, const struct hash_desc *hash_algo, struct logger *logger) { dbg("%s: started using NSS", __func__); if (!pexpect(pks->u.pubkey.private_key != NULL)) { dbg("no private key!"); return (struct hash_signature) { .len = 0, }; } SECItem data = { .type = siBuffer, .len = hash_len, .data = DISCARD_CONST(uint8_t *, hash_val), }; struct hash_signature sig = { .len = PK11_SignatureLen(pks->u.pubkey.private_key), }; passert(sig.len <= sizeof(sig.ptr/*array*/)); SECItem signature = { .type = siBuffer, .len = sig.len, .data = sig.ptr, }; const CK_RSA_PKCS_PSS_PARAMS *mech = hash_algo->nss.rsa_pkcs_pss_params; if (mech == NULL) { llog(RC_LOG_SERIOUS, logger, "digital signature scheme not supported for hash algorithm %s", hash_algo->common.fqn); return (struct hash_signature) { .len = 0, }; } SECItem mech_item = { .type = siBuffer, .data = (void*)mech, /* strip const */ .len = sizeof(*mech), }; SECStatus s = PK11_SignWithMechanism(pks->u.pubkey.private_key, CKM_RSA_PKCS_PSS, &mech_item, &signature, &data); if (s != SECSuccess) { /* PR_GetError() returns the thread-local error */ llog_nss_error(RC_LOG_SERIOUS, logger, "RSA DSS sign function failed"); return (struct hash_signature) { .len = 0, }; } dbg("%s: ended using NSS", __func__); return sig; } static bool RSA_authenticate_signature_rsassa_pss(const struct crypt_mac *expected_hash, shunk_t signature, struct pubkey *pubkey, const struct hash_desc *hash_algo, diag_t *fatal_diag, struct logger *logger) { SECKEYPublicKey *seckey_public = pubkey->content.public_key; /* decrypt the signature -- reversing RSA_sign_hash */ if (signature.len != (size_t)seckey_public->u.rsa.modulus.len) { /* XXX notification: INVALID_KEY_INFORMATION */ *fatal_diag = NULL; return false; } if (DBGP(DBG_BASE)) { DBG_dump_hunk("NSS RSA: verifying that decrypted signature matches hash: ", *expected_hash); } /* * Convert the signature into raw form (NSS doesn't do const). */ const SECItem encrypted_signature = { .type = siBuffer, .data = DISCARD_CONST(unsigned char *, signature.ptr), .len = signature.len, }; /* * Digital signature scheme with RSA-PSS */ const CK_RSA_PKCS_PSS_PARAMS *mech = hash_algo->nss.rsa_pkcs_pss_params; if (!pexpect(mech != NULL)) { dbg("NSS RSA verify: hash algorithm not supported"); /* internal error? */ *fatal_diag = NULL; return false; } const SECItem hash_mech_item = { .type = siBuffer, .data = (void*)mech, /* strip const */ .len = sizeof(*mech), }; struct crypt_mac hash_data = *expected_hash; /* cast away const */ const SECItem expected_hash_item = { .len = hash_data.len, .data = hash_data.ptr, .type = siBuffer, }; if (PK11_VerifyWithMechanism(seckey_public, CKM_RSA_PKCS_PSS, &hash_mech_item, &encrypted_signature, &expected_hash_item, lsw_nss_get_password_context(logger)) != SECSuccess) { dbg("NSS RSA verify: decrypting signature is failed"); *fatal_diag = NULL; return false; } *fatal_diag = NULL; return true; } const struct pubkey_signer pubkey_signer_digsig_rsassa_pss = { .name = "RSASSA-PSS", /* name from RFC 7427 */ .type = &pubkey_type_rsa, .digital_signature_blob = DIGITAL_SIGNATURE_RSASSA_PSS_BLOB, .sign_hash = RSA_sign_hash_rsassa_pss, .authenticate_signature = RSA_authenticate_signature_rsassa_pss, .jam_auth_method = RSA_jam_auth_method, }; libreswan-4.14/lib/libswan/realtime.c000066400000000000000000000070171457372064200176220ustar00rootroot00000000000000/* 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 #include "constants.h" /* for memeq() which is clearly not a constant */ #include "passert.h" #include "jambuf.h" #include "lswlog.h" /* for fatal_errno() */ #include "realtime.h" const realtime_t realtime_epoch = REALTIME_EPOCH; realtime_t realtime(time_t time) { return (realtime_t) { { time, 0, }, }; } realtime_t realtime_ms(intmax_t milliseconds) { return (realtime_t) { .rt = timeval_ms(milliseconds), }; } realtime_t realtimesum(realtime_t t, deltatime_t d) { realtime_t s; timeradd(&t.rt, &d.dt, &s.rt); return s; } bool is_realtime_epoch(realtime_t t) { return !timerisset(&t.rt); } int realtime_sub_sign(realtime_t l, realtime_t r) { /* sign(l - r) */ return timeval_sub_sign(l.rt, r.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) { /* * This code assumes clock_gettime() always succeeds - * if it were expected to fail then there'd either be * a logger and/or a way to return the failure to the * caller. */ fatal_errno(PLUTO_EXIT_KERNEL_FAIL, &global_logger, errno, "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(struct jambuf *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) { struct jambuf jambuf = ARRAY_AS_JAMBUF(buf->buf); jam_realtime(&jambuf, r, utc); return buf->buf; } libreswan-4.14/lib/libswan/refcnt.c000066400000000000000000000063711457372064200173030ustar00rootroot00000000000000/* 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 #include "refcnt.h" static pthread_mutex_t refcnt_mutex = PTHREAD_MUTEX_INITIALIZER; static void dbg_ref(const char *why, const char *what, const void *pointer, where_t where, int old_count, int new_count) { if (DBGP(DBG_REFCNT)) { DBG_log("%sref %s@%p(%u->%u) "PRI_WHERE"", why, what, pointer, old_count, new_count, pri_where(where)); } } #define DEBUG_LOG(WHY) \ dbg_ref(WHY, refcnt->base->what, pointer, where, old, new) /* * So existing code can use the refcnt tracer. */ void dbg_alloc(const char *what, const void *pointer, where_t where) { dbg_ref("new", what, pointer, where, 0, 1); } void dbg_free(const char *what, const void *pointer, where_t where) { dbg_ref("del", what, pointer, where, 1, 0); } /* -- */ void refcnt_init(const void *pointer, struct refcnt *refcnt, const struct refcnt_base *base, const struct where *where) { unsigned old, new; pthread_mutex_lock(&refcnt_mutex); { old = refcnt->count; refcnt->count++; refcnt->base = base; new = refcnt->count; } pthread_mutex_unlock(&refcnt_mutex); if (old != 0 || new != 1) { llog_pexpect(&global_logger, where, "refcnt for %s@%p should have been 0 initialized", base->what, pointer); } DEBUG_LOG("new"); } void refcnt_addref_where(const char *what, const void *pointer, refcnt_t *refcnt, where_t where) { if (pointer == NULL) { dbg("addref %s@NULL "PRI_WHERE"", what, pri_where(where)); return; } unsigned old, new; pthread_mutex_lock(&refcnt_mutex); { old = refcnt->count; refcnt->count++; new = refcnt->count; } pthread_mutex_unlock(&refcnt_mutex); if (old == 0) { llog_pexpect(&global_logger, where, "refcnt for %s@%p should have been non-0", what, pointer); } DEBUG_LOG("add"); } /* * look at refcnt atomically * This is a bit slow but it is used rarely. */ unsigned refcnt_peek(const refcnt_t *refcnt) { unsigned val; pthread_mutex_lock(&refcnt_mutex); { val = refcnt->count; } pthread_mutex_unlock(&refcnt_mutex); return val; } void refcnt_delref_where(const char *what, void *pointer, struct refcnt *refcnt, const struct where *where) { if (pointer == NULL) { dbg("delref %s@NULL "PRI_WHERE"", what, pri_where(where)); return; } /* on main thread */ unsigned old, new; pthread_mutex_lock(&refcnt_mutex); { old = refcnt->count; if (old > 0) { refcnt->count--; } new = refcnt->count; } pthread_mutex_unlock(&refcnt_mutex); if (old == 0) { llog_pexpect(&global_logger, where, "refcnt for %s@%p should have been non-0", what, pointer); } DEBUG_LOG("del"); if (new == 0) { refcnt->base->free(pointer, where); } } libreswan-4.14/lib/libswan/reqid.c000066400000000000000000000035471457372064200171300ustar00rootroot00000000000000/* 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 "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-4.14/lib/libswan/resolve_default_route_bsd.c000066400000000000000000000132361457372064200232510ustar00rootroot00000000000000/* BSD route resolution, for libreswan * * Copyright (C) 2017 Antony Antony * Copyright (C) 2018 Paul Wouters * Copyright (C) 2022 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 "lsw_socket.h" /* NetBSD defines RT_ADVANCE(); FreeBSD SA_SIZE(); OpenBSD nada */ #ifndef RT_ADVANCE # if defined __FreeBSD__ # define RT_ADVANCE(AP, SA) AP += SA_SIZE(SA) # elif defined __OpenBSD__ # define RT_ADVANCE(AP, SA) AP += (1 + (((SA)->sa_len - 1) | (sizeof(long) - 1))) # elif defined __APPLE__ # define RT_ADVANCE(AP, SA) AP += (1 + (((SA)->sa_len - 1) | (sizeof(long) - 1))) # else # error RT_ADVANCE # endif #endif #include "addr_lookup.h" #include "constants.h" #include "ipsecconf/confread.h" #include "lswlog.h" /* for fatal() */ #include "ip_sockaddr.h" #include "ip_info.h" #include "sparse_names.h" static const struct sparse_name rta_names[] = { #define E(N) { #N, N, } E(RTA_DST), E(RTA_IFP), E(RTA_IFA), E(RTA_GATEWAY), E(RTA_NETMASK), E(RTA_GENMASK), #undef E SPARSE_NULL, }; void resolve_default_route(struct starter_end *host, struct starter_end *peer, lset_t verbose_rc_flags UNUSED, struct logger *logger) { /* What kind of result are we seeking? */ bool seeking_src = (host->addrtype == KH_DEFAULTROUTE || peer->addrtype == KH_DEFAULTROUTE); bool seeking_gateway = (host->nexttype == KH_DEFAULTROUTE || peer->nexttype == KH_DEFAULTROUTE); if (!seeking_src && !seeking_gateway) return; /* this end already figured out */ fatal(PLUTO_EXIT_FAIL, logger, "addcon: without XFRM, cannot resolve_defaultroute()"); } static enum route_status get_route_1(int s, ip_address dst, const struct ip_info *afi, struct ip_route *route, struct logger *logger) { struct { struct rt_msghdr hdr; uint8_t buf[512/*something big*/]; } msg = { .hdr = { .rtm_version = RTM_VERSION, .rtm_type = RTM_GET, .rtm_seq = 1, .rtm_flags = RTF_UP|RTF_GATEWAY|RTF_HOST|RTF_STATIC, }, }; uint8_t *ap = msg.buf; /* append dst */ msg.hdr.rtm_addrs |= RTA_DST; ip_sockaddr sa = sockaddr_from_address(dst); memcpy(ap, &sa.sa, sa.len); RT_ADVANCE(ap, (&sa.sa.sa)); /* append IFP */ msg.hdr.rtm_addrs |= RTA_IFP; struct sockaddr *ifp = (void*)ap; ifp->sa_family = AF_LINK, ifp->sa_len = sizeof(struct sockaddr_dl), RT_ADVANCE(ap, ifp); /* final length */ msg.hdr.rtm_msglen = ap - (uint8_t*)&msg; /* send */ int w = write(s, &msg, msg.hdr.rtm_msglen); if (w < 0) { llog_errno(ERROR_FLAGS, logger, errno, "write failed"); return ROUTE_FATAL; } /* recv */ int r = read(s, &msg, sizeof(msg)); if (r < 0) { llog_errno(ERROR_FLAGS, logger, errno, "write failed"); return ROUTE_FATAL; } /* verify */ if (sizeof(msg.hdr.rtm_msglen) > (unsigned)r) { llog(ERROR_FLAGS, logger, "response of %d bytes way too small", r); return ROUTE_FATAL; } if (msg.hdr.rtm_msglen > r) { llog(ERROR_FLAGS, logger, "response of %d bytes was truncated", r); return ROUTE_FATAL; } if (msg.hdr.rtm_version != RTM_VERSION) { llog(ERROR_FLAGS, logger, "response version %d wrong", msg.hdr.rtm_version); return ROUTE_FATAL; } if (msg.hdr.rtm_errno != 0) { llog(ERROR_FLAGS, logger, "response failed: %s", strerror(errno)); return ROUTE_FATAL; } if (msg.hdr.rtm_type != RTM_GET) { llog(ERROR_FLAGS, logger, "response type %d wrong", msg.hdr.rtm_type); return ROUTE_FATAL; } /* go through bits lsb->msb; match payload */ ap = msg.buf; unsigned a = msg.hdr.rtm_addrs; for (unsigned b = 0; a != 0; b++) { unsigned m = 1 << b; if (a & m) { sparse_buf eb; dbg("found %s", str_sparse(rta_names, m, &eb)); a &= ~m; struct sockaddr *sa = (void*)ap; RT_ADVANCE(ap, sa); if (sa->sa_family != afi->af) { continue; } err_t e = NULL; switch (m) { case RTA_DST: /* destination sockaddr present */ break; case RTA_GATEWAY: /* gateway sockaddr present */ e = sockaddr_to_address_port(sa, sa->sa_len, &route->gateway, NULL); break; case RTA_NETMASK: /* netmask sockaddr present */ case RTA_GENMASK: /* cloning mask sockaddr present */ case RTA_IFP: /* interface name sockaddr present */ break; case RTA_IFA: /* interface addr sockaddr present */ e = sockaddr_to_address_port(sa, sa->sa_len, &route->source, NULL); break; case RTA_AUTHOR: /* sockaddr for author of redirect */ case RTA_BRD: /* for NEWADDR, broadcast or p-p dest addr */ #ifdef RTA_TAG case RTA_TAG: /* route tag */ #endif break; } if (e != NULL) { llog(ERROR_FLAGS, logger, "invalid %s", e); return ROUTE_FATAL; } } } /* unpack */ return ROUTE_SUCCESS; } enum route_status get_route(ip_address dst, struct ip_route *route, struct logger *logger) { zero(route); const struct ip_info *afi = address_type(&dst); int s = cloexec_socket(PF_ROUTE, SOCK_RAW, afi->af); if (s < 0) { llog_errno(ERROR_FLAGS, logger, errno, "cloexec_socket(PF_ROUTE, SOCK_RAW, %s) failed", afi->ip_name); return ROUTE_FATAL; } enum route_status status = get_route_1(s, dst, afi, route, logger); close(s); return status; } libreswan-4.14/lib/libswan/resolve_default_route_linux.c000066400000000000000000000451121457372064200236360ustar00rootroot00000000000000/* * 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 * Copyright (C) 2021 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 /* RTA_UID hack */ #include #include #include #include #include #include #include #include #include "lsw_socket.h" #include "constants.h" #include "lswalloc.h" #include "ipsecconf/confread.h" #include "kernel_netlink_reply.h" #include "addr_lookup.h" #ifdef USE_DNSSEC # include "dnssec.h" #endif #include "ip_info.h" #include "lswlog.h" struct verbose { struct logger *logger; lset_t rc_flags; int level; }; #define vlog(FMT, ...) \ { \ if (verbose.rc_flags) { \ llog(verbose.rc_flags, verbose.logger, \ "%*s"FMT, \ verbose.level * 2, "", ##__VA_ARGS__); \ } \ } static void resolve_point_to_point_peer(const char *interface, const struct ip_info *afi, ip_address *peer, struct verbose 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) { continue; } if (!streq(ifa->ifa_name, interface)) { continue; } struct sockaddr *sa = ifa->ifa_ifu.ifu_dstaddr; if (sa == NULL || sa->sa_family != afi->af) { continue; } err_t err = sockaddr_to_address_port(sa, afi->sockaddr_size, peer, NULL/*ignore port*/); if (err != NULL) { vlog("interface %s had invalid sockaddr: %s", interface, err); continue; } address_buf ab; vlog("found peer %s to interface %s", str_address(peer, &ab), interface); break; } 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 struct nlmsghdr *netlink_query_init(const struct ip_info *afi, char type, int flags, struct verbose verbose) { struct nlmsghdr *nlmsg = alloc_bytes(RTNL_BUFSIZE, "netlink query"); struct rtmsg *rtmsg; nlmsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); nlmsg->nlmsg_flags = flags; nlmsg->nlmsg_type = type; nlmsg->nlmsg_seq = 0; nlmsg->nlmsg_pid = getpid(); rtmsg = (struct rtmsg *)NLMSG_DATA(nlmsg); rtmsg->rtm_family = afi->af; rtmsg->rtm_table = 0; /* RT_TABLE_MAIN doesn't seem to do much */ 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; vlog("query %s%s%s%s", (type == RTM_GETROUTE ? "GETROUTE" : "?"), (flags & NLM_F_REQUEST ? "+REQUEST" : ""), /*NLM_F_DUMP==NLM_F_ROOT|NLM_F_MATCH*/ (flags & NLM_F_ROOT ? "+ROOT" : ""), (flags & NLM_F_MATCH ? "+MATCH" : "")); return nlmsg; } /* * Add RTA_SRC or RTA_DST attribute to netlink query message. */ static void netlink_query_add(struct nlmsghdr *nlmsg, int rta_type, const ip_address *addr, const char *what, struct verbose verbose) { struct rtmsg *rtmsg; struct rtattr *rtattr; int rtlen; 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; address_buf ab; vlog("add RTA_%s %s (%s)", (rta_type == RTA_DST ? "DST" : rta_type == RTA_GATEWAY ? "GATEWAY" : rta_type == RTA_SRC ? "SRC" : rta_type == RTA_PREFSRC ? "PREFSRC" : "???"), str_address(addr, &ab), what); } /* * Send netlink query message and read reply. */ static ssize_t netlink_query(struct nlmsghdr **nlmsgp, size_t bufsize) { int sock = cloexec_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 = *nlmsgp; 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; netlink_read_reply() may re-allocate buffer. */ errno = 0; /* in case failure does not set it */ ssize_t len = netlink_read_reply(sock, (char**)nlmsgp, 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. */ static const char *pa(enum keyword_host type, ip_address address, const char *hostname, address_buf *buf) { switch (type) { case KH_NOTSET: return ""; case KH_DEFAULTROUTE: return ""; case KH_ANY: return ""; case KH_IFACE: return hostname; case KH_OPPO: return ""; case KH_OPPOGROUP: return ""; case KH_GROUP: return ""; case KH_IPHOSTNAME: return hostname; case KH_IPADDR: return str_address(&address, buf); default: return ""; } } enum resolve_status { RESOLVE_FAILURE = -1, RESOLVE_SUCCESS = 0, RESOLVE_PLEASE_CALL_AGAIN = 1, }; static enum resolve_status resolve_defaultroute_one(struct starter_end *host, struct starter_end *peer, struct verbose verbose) { /* * "left=" == host->addrtype and host->addr * "leftnexthop=" == host->nexttype and host->nexthop */ const struct ip_info *afi = host->host_family; address_buf ab, gb, pb; vlog("resolving family=%s src=%s gateway=%s peer %s", (afi == NULL ? "" : afi->ip_name), pa(host->addrtype, host->addr, host->strings[KSCF_IP], &ab), pa(host->nexttype, host->nexthop, host->strings[KSCF_NEXTHOP], &gb), pa(peer->addrtype, peer->addr, peer->strings[KSCF_IP], &pb)); verbose.level = 1; /* * Can only resolve one at a time. * * XXX: OLD comments: * * 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 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. */ enum seeking { NOTHING, PREFSRC, GATEWAY, } seeking = (host->nexttype == KH_DEFAULTROUTE ? GATEWAY : host->addrtype == KH_DEFAULTROUTE ? PREFSRC : NOTHING); vlog("seeking %s", (seeking == NOTHING ? "NOTHING" : seeking == PREFSRC ? "PREFSRC" : seeking == GATEWAY ? "GATEWAY" : "?")); verbose.level = 2; if (seeking == NOTHING) { return RESOLVE_SUCCESS; /* this end already figured out */ } /* * msgbuf is dynamically allocated since the buffer may need * to be grown. */ struct nlmsghdr *msgbuf = netlink_query_init(afi, /*type*/RTM_GETROUTE, (/*flags*/NLM_F_REQUEST | (seeking == GATEWAY ? NLM_F_DUMP : 0)), verbose); /* * If known, add a destination address. Either the peer, or * the gateway. */ const bool has_peer = (peer->addrtype == KH_IPADDR || peer->addrtype == KH_IPHOSTNAME); bool added_dst; if (host->nexttype == KH_IPADDR && afi == &ipv4_info) { pexpect(seeking == PREFSRC); /* * 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 that there is an (old) bug when looking up IPv4 src * IPv6 with gateway link local address will return link local * address and not the global address. */ added_dst = true; netlink_query_add(msgbuf, RTA_DST, &host->nexthop, "host->nexthop", verbose); } else if (has_peer) { /* * Peer IP is specified. * We may need to figure out source IP * and gateway IP to get there. * * XXX: should this also update peer->addrtype? */ pexpect(peer->host_family != NULL); if (peer->addrtype == KH_IPHOSTNAME) { #ifdef USE_DNSSEC /* try numeric first */ err_t er = ttoaddress_num(shunk1(peer->strings[KSCF_IP]), peer->host_family, &peer->addr); if (er != NULL) { /* not numeric, so resolve it */ if (!unbound_resolve(peer->strings[KSCF_IP], peer->host_family, &peer->addr, verbose.logger)) { pfree(msgbuf); return RESOLVE_FAILURE; } } #else err_t er = ttoaddress_dns(shunk1(peer->strings[KSCF_IP]), peer->host_family, &peer->addr); if (er != NULL) { pfree(msgbuf); return RESOLVE_FAILURE; } #endif } else { pexpect(peer->addrtype == KH_IPADDR); } added_dst = true; netlink_query_add(msgbuf, RTA_DST, &peer->addr, "peer->addr", verbose); } else if (host->nexttype == KH_IPADDR && (peer->addrtype == KH_GROUP || peer->addrtype == KH_OPPOGROUP)) { added_dst = true; netlink_query_add(msgbuf, RTA_DST, &host->nexthop, "host->nexthop peer=group", verbose); } else { added_dst = false; } if (added_dst && host->addrtype == KH_IPADDR) { /* SRC works only with DST */ pexpect(seeking == GATEWAY); netlink_query_add(msgbuf, RTA_SRC, &host->addr, "host->addr", verbose); } /* Send netlink get_route request */ ssize_t len = netlink_query(&msgbuf, RTNL_BUFSIZE); vlog("query returned %zd bytes", len); if (len < 0) { pfree(msgbuf); return RESOLVE_FAILURE; } /* Parse reply */ verbose.level = 1; vlog("processing response"); struct nlmsghdr *nlmsg = (struct nlmsghdr *)msgbuf; enum resolve_status status = RESOLVE_FAILURE; /* assume the worst */ for (; NLMSG_OK(nlmsg, (size_t)len) && status == RESOLVE_FAILURE; nlmsg = NLMSG_NEXT(nlmsg, len)) { verbose.level = 2; if (nlmsg->nlmsg_type == NLMSG_DONE) break; if (nlmsg->nlmsg_type == NLMSG_ERROR) { llog(RC_LOG, verbose.logger, "netlink error"); pfree(msgbuf); return RESOLVE_FAILURE; } /* ignore all but IPv4 and IPv6 */ struct rtmsg *rtmsg = (struct rtmsg *) NLMSG_DATA(nlmsg); if (rtmsg->rtm_family != afi->af) { continue; } /* Parse one route entry */ char r_interface[IF_NAMESIZE+1]; zero(&r_interface); ip_address src = unset_address; ip_address prefsrc = unset_address; ip_address gateway = unset_address; ip_address dst = unset_address; int priority = -1; signed char pref = -1; int table; const char *cacheinfo = ""; const char *uid = ""; struct rtattr *rtattr = (struct rtattr *) RTM_RTA(rtmsg); int rtlen = RTM_PAYLOAD(nlmsg); vlog("parsing route entry (RTA payloads)"); verbose.level = 3; while (RTA_OK(rtattr, rtlen)) { const void *data = RTA_DATA(rtattr); unsigned len = RTA_PAYLOAD(rtattr); switch (rtattr->rta_type) { case RTA_OIF: if_indextoname(*(int *)RTA_DATA(rtattr), r_interface); break; case RTA_PREFSRC: #define PARSE_ADDRESS(OUT, WHAT) \ { \ err_t err = data_to_address(data, len, afi, OUT); \ if (err != NULL) { \ vlog("invalid RTA_%s from kernel: %s", WHAT, err); \ } else { \ address_buf ab; \ vlog("RTA_%s=%s", WHAT, str_address(OUT, &ab)); \ } \ } PARSE_ADDRESS(&prefsrc, "PREFSRC"); break; case RTA_GATEWAY: PARSE_ADDRESS(&gateway, "GATEWAY"); break; case RTA_DST: PARSE_ADDRESS(&dst, "DST"); break; case RTA_SRC: PARSE_ADDRESS(&src, "SRC"); break; #undef PARSE_ADDRESS case RTA_PRIORITY: #define PARSE_NUMBER(OUT, WHAT) \ { \ if (len != sizeof(OUT)) { \ vlog("ignoring RTA_%s with wrong size %d", WHAT, len); \ } else { \ memcpy(&OUT, data, len); \ vlog("RTA_%s=%d", WHAT, OUT); \ } \ } PARSE_NUMBER(priority, "PRIORITY"); break; case RTA_PREF: PARSE_NUMBER(pref, "PREF"); break; case RTA_TABLE: PARSE_NUMBER(table, "TABLE"); break; #undef PARSE_NUMBER case RTA_CACHEINFO: cacheinfo = " +cacheinfo"; break; #if LINUX_VERSION_CODE >= KERNEL_VERSION(5,11,16) case RTA_UID: /* * XXX: Above kernel version matches * when this code was added to this * file and not when RTA_UID was added * to the kernel herders. That was: * * commit 4fb74506838b3e34eaaebfcf90ebcd1fd52ab813 * Merge: 0d53072aa42b e2d118a1cb5e * Author: David S. Miller * Date: Fri Nov 4 14:45:24 2016 -0400 * * Merge branch 'uid-routing' * * but who knows what that kernel * version was. * * A sane kernel would include: * * #define RTA_UID RTA_UID * * when adding the enum so that: * * #ifdef RTA_ID * * could do the right thing. Sigh. */ uid = " +uid"; break; #endif default: vlog("ignoring RTA type %d", rtattr->rta_type); } rtattr = RTA_NEXT(rtattr, rtlen); } /* * Ignore if not main table. * Ignore ipsecX or mastX interfaces. * * XXX: instead of rtm_table, should this be checking * TABLE? */ address_buf sb, psb, db, gb; vlog("using src=%s prefsrc=%s gateway=%s dst=%s dev='%s' priority=%d pref=%d table=%d%s%s", str_address(&src, &sb), str_address(&prefsrc, &psb), str_address(&gateway, &gb), str_address(&dst, &db), (r_interface[0] ? r_interface : "?"), priority, pref, rtmsg->rtm_table, cacheinfo, uid); verbose.level = 2; if (rtmsg->rtm_table != RT_TABLE_MAIN) { vlog("IGNORE: table %d is not main(%d)", rtmsg->rtm_table, RT_TABLE_MAIN); continue; } if (startswith(r_interface, "ipsec") || startswith(r_interface, "mast")) { vlog("IGNORE: interface %s", r_interface); continue; } switch (seeking) { case PREFSRC: if (!address_is_unset(&prefsrc)) { status = RESOLVE_SUCCESS; host->addrtype = KH_IPADDR; host->addr = prefsrc; address_buf ab; vlog("found prefsrc(host_addr): %s", str_address(&host->addr, &ab)); } break; case GATEWAY: if (address_is_unset(&dst)) { if (address_is_unset(&gateway) && r_interface[0] != '\0') { /* * Point-to-Point default gw without * "via IP". Attempt to find gateway * as the IP address on the interface. */ resolve_point_to_point_peer(r_interface, host->host_family, &gateway, verbose); } if (!address_is_unset(&gateway)) { /* * Note: Use first even if * multiple. * * XXX: assume a gateway * always requires a second * call to get PREFSRC, code * above will quickly return * when it isn't. */ status = RESOLVE_PLEASE_CALL_AGAIN; host->nexttype = KH_IPADDR; host->nexthop = gateway; address_buf ab; vlog("found gateway(host_nexthop): %s", str_address(&host->nexthop, &ab)); } } break; default: bad_case(seeking); } } pfree(msgbuf); verbose.level = 1; vlog("%s: src=%s gateway=%s", (status == RESOLVE_FAILURE ? "failure" : status == RESOLVE_SUCCESS ? "success" : status == RESOLVE_PLEASE_CALL_AGAIN ? "please-call-again" : "???"), pa(host->addrtype, host->addr, host->strings[KSCF_IP], &ab), pa(host->nexttype, host->nexthop, host->strings[KSCF_NEXTHOP], &gb)); return status; } enum route_status get_route(ip_address dest, struct ip_route *route, struct logger *logger) { /* let's re-discover local address */ struct starter_end this = { .addrtype = KH_DEFAULTROUTE, .nexttype = KH_DEFAULTROUTE, .host_family = address_type(&dest), }; struct starter_end that = { .addrtype = KH_IPADDR, .host_family = this.host_family, .addr = dest, }; struct verbose verbose = { .logger = logger, .rc_flags = DBGP(DBG_BASE) ? DEBUG_STREAM : LEMPTY, .level = 0, }; /* * mobike need two lookups. one for the gateway and the one * for the source address. */ switch (resolve_defaultroute_one(&this, &that, verbose)) { case RESOLVE_FAILURE: return ROUTE_GATEWAY_FAILED; case RESOLVE_SUCCESS: /* cannot happen */ /* ??? original code treated this as failure */ /* bad_case(0); */ llog_pexpect(logger, HERE, "unexpected SUCCESS from first resolve_defaultroute_one())"); return ROUTE_FATAL; case RESOLVE_PLEASE_CALL_AGAIN: /* please call again: more to do */ /* expected; so far only gateway resolved */ break; } switch (resolve_defaultroute_one(&this, &that, verbose)) { case RESOLVE_FAILURE: return ROUTE_SOURCE_FAILED; case RESOLVE_SUCCESS: break; case RESOLVE_PLEASE_CALL_AGAIN: /* please call again: more to do */ /* cannot happen */ /* ??? original code treated this as failure */ /* bad_case(1); */ llog_pexpect(logger, HERE, "unexpected TRY AGAIN from second resolve_defaultroute_one()"); return ROUTE_FATAL; } route->source = this.addr; route->gateway = this.nexthop; return ROUTE_SUCCESS; } void resolve_default_route(struct starter_end *host, struct starter_end *peer, lset_t verbose_rc_flags, struct logger *logger) { struct verbose verbose = { .rc_flags = verbose_rc_flags, .logger = logger, .level = 0, }; switch (resolve_defaultroute_one(host, peer, verbose)) { case RESOLVE_FAILURE: return; case RESOLVE_SUCCESS: return; case RESOLVE_PLEASE_CALL_AGAIN: break; } resolve_defaultroute_one(host, peer, verbose); } libreswan-4.14/lib/libswan/rnd.c000066400000000000000000000061241457372064200166010ustar00rootroot00000000000000/* randomness machinery * Copyright (C) 1997 Angelos D. Keromytis. * Copyright (C) 1998-2001 D. Hugh Redelmeier. * Copyright (C) 2006-2007 Michael C Richardson * Copyright (C) 2007-2008 Antony Antony * Copyright (C) 2007-2008 Paul Wouters * Copyright (C) 2012 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 #include "rnd.h" #include "lswlog.h" /* for global_logger */ #include "lswnss.h" /* for passert_nss_error() */ /* A true random number generator (we hope) * * Under LINUX, use NSS for FIPS compliant RNG. * Under OpenBSD ("__OpenBSD__" predefined), use arc4random(). * Otherwise use our own random number generator based on clock skew. * I (ADK) first heard of the idea from John Ioannidis, who heard it * from Matt Blaze and/or Jack Lacy. * ??? Why is mixing need for linux but not OpenBSD? */ /* Pluto's uses of randomness: * * - Setting up the "secret_of_the_day". This changes every hour! 20 * bytes a shot. It is used in building responder cookies. * * - generating initiator cookies (8 bytes, once per Phase 1 initiation). * * - IKEv1: 32 bytes per DH local secret. Once per Aggr/Main Mode exchange and once * per Quick Mode Exchange with PFS. (Size is our choice, with * tradeoffs.) * - IKEv2: * * - IKEv1: 16 bytes per nonce we generate. Once per Aggr/Main Mode exchange and * once per Quick Mode exchange. (Again, we choose the size.) * - IKEv2: * * - 4 bytes per SPI number that we generate. We choose the SPIs for all * inbound SPIs, one to three per IPSEC SA (one for AH (rare, probably) * one for ESP (almost always), and one for tunnel (very common)). * I don't actually know how the kernel would generate these numbers -- * currently Pluto generates them; this isn't the way things will be * done in the future. * * - 4 bytes per Message ID we need to generate. One per Quick Mode * exchange. Eventually, one per informational exchange. */ void get_rnd_bytes(void *buffer, size_t length) { if (PK11_GenerateRandom(buffer, length) != SECSuccess) { passert_nss_error(&global_logger, HERE, "generating %zu random bytes", length); } } uintmax_t get_rnd_uintmax(uintmax_t roof) { uintmax_t rnd; get_rnd_bytes(&rnd, sizeof(rnd)); return rnd % roof; } void fill_rnd_chunk(chunk_t chunk) { get_rnd_bytes(chunk.ptr, chunk.len); } chunk_t alloc_rnd_chunk(size_t size, const char *name) { chunk_t chunk = alloc_chunk(size, name); fill_rnd_chunk(chunk); return chunk; } libreswan-4.14/lib/libswan/role.c000066400000000000000000000024021457372064200167520ustar00rootroot00000000000000/* 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-4.14/lib/libswan/sameaddr.3.xml000066400000000000000000000143701457372064200203170ustar00rootroot00000000000000 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-4.14/lib/libswan/sameaddr.c000066400000000000000000000026431457372064200176000ustar00rootroot00000000000000/* * 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 "passert.h" /* * addrcmp - compare two addresses * Caution, the order of the tests is subtle: doing type test before * size test can yield cases where ac. * * computes "l-r" */ int /* like memcmp */ addrcmp(const ip_address *l, const ip_address *r) { if (address_is_unset(l) && address_is_unset(r)) { /* unset addresses equal */ return 0; } if (address_is_unset(l)) { return -1; } if (address_is_unset(r)) { return 1; } return ip_bytes_cmp(l->version, l->bytes, r->version, r->bytes); } /* * sameaddr - are two addresses the same? */ bool sameaddr(const ip_address *a, const ip_address *b) { return addrcmp(a, b) == 0; } libreswan-4.14/lib/libswan/secitem_chunk.c000066400000000000000000000025531457372064200206410ustar00rootroot00000000000000/* * 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 "lswalloc.h" #include "jambuf.h" #include "lswnss.h" SECItem same_chunk_as_secitem(chunk_t chunk, SECItemType type) { SECItem si = { .type = type, .data = chunk.ptr, .len = chunk.len, }; return si; } SECItem same_shunk_as_secitem(shunk_t shunk, SECItemType type) { SECItem si = { .type = type, .data = DISCARD_CONST(uint8_t *, shunk.ptr), .len = shunk.len, }; return si; } chunk_t same_secitem_as_chunk(SECItem si) { return chunk2(si.data, si.len); } shunk_t same_secitem_as_shunk(SECItem si) { return shunk2(si.data, si.len); } 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; } libreswan-4.14/lib/libswan/secret_pubkey_stuff_to_pubkey_der.c000066400000000000000000000027521457372064200250070ustar00rootroot00000000000000/* Convert a private key to a Subect Public Key Info DER, for libreswan * * Copyright (C) 2022 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 "lswnss.h" #include "secrets.h" static diag_t seckey_pubkey_to_der(SECKEYPublicKey *seckey_pubkey, chunk_t *der) { SECItem *seckey_der = SECKEY_EncodeDERSubjectPublicKeyInfo(seckey_pubkey); if (seckey_der == NULL) { return diag_nss_error("encoding Subject Public Key Info as DER"); } *der = clone_secitem_as_chunk(*seckey_der, "Subject Public Key Info DER"); SECITEM_FreeItem(seckey_der, PR_TRUE/*and SECItem*/); return NULL; } diag_t secret_pubkey_stuff_to_pubkey_der(struct secret_stuff *pks, chunk_t *der) { SECKEYPublicKey *seckey_pubkey = SECKEY_ConvertToPublicKey(pks->u.pubkey.private_key); if (seckey_pubkey == NULL) { return diag_nss_error("extracting Public Key from Private Key"); } diag_t d = seckey_pubkey_to_der(seckey_pubkey, der); SECKEY_DestroyPublicKey(seckey_pubkey); return d; } libreswan-4.14/lib/libswan/secrets.c000066400000000000000000001133771457372064200174770ustar00rootroot00000000000000/* * 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 /* missing from on old systems */ #include #include #include #include #include #include "ttodata.h" #include "lswglob.h" #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 "lswconf.h" #include "lswnss.h" #include "ip_info.h" #include "nss_cert_load.h" #include "ike_alg.h" #include "ike_alg_hash.h" #include "certs.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 */ static err_t builddiag(const char *fmt, ...) PRINTF_LIKE(1); /* NOT RE-ENTRANT */ static 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; } struct fld { const char *name; ssize_t offset; }; static void process_secrets_file(struct file_lex_position *flp, struct secret **psecrets, const char *file_pat); struct secret { struct secret *next; struct id_list *ids; struct secret_stuff stuff; }; struct secret_stuff *get_secret_stuff(struct secret *secret) { return &secret->stuff; } 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, keyid_t *keyid, size_t *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. */ DBGF(DBG_CRYPT, "XXX: adjusted modulus length %zu->%zu", n.len, n.len - 1); n.ptr++; n.len--; } /* form the Libreswan keyid */ err_t err = splitkey_to_keyid(e.ptr, e.len, n.ptr, n.len, keyid); passert(err == NULL); /* return the RSA modulus size in octets */ *keysize = n.len; } const struct pubkey_type *pubkey_alg_type(enum ipseckey_algorithm_type alg) { static const struct pubkey_type *pubkey_types[] = { [IPSECKEY_ALGORITHM_RSA] = &pubkey_type_rsa, [IPSECKEY_ALGORITHM_ECDSA] = &pubkey_type_ecdsa, [IPSECKEY_ALGORITHM_X_PUBKEY] = NULL, }; if (alg < elemsof(pubkey_types)) { return pubkey_types[alg]; } return NULL; } const keyid_t *pubkey_keyid(const struct pubkey *pk) { return &pk->content.keyid; } const ckaid_t *pubkey_ckaid(const struct pubkey *pk) { return &pk->content.ckaid; } const ckaid_t *secret_ckaid(const struct secret *secret) { switch (secret->stuff.kind) { case SECRET_RSA: case SECRET_ECDSA: /* some sort of PKI */ return &secret->stuff.u.pubkey.content.ckaid; default: return NULL; } } const keyid_t *secret_keyid(const struct secret *secret) { switch (secret->stuff.kind) { case SECRET_RSA: case SECRET_ECDSA: /* some sort of PKI */ return &secret->stuff.u.pubkey.content.keyid; default: return NULL; } } struct secret *foreach_secret(struct secret *secrets, secret_eval func, void *uservoid) { for (struct secret *s = secrets; s != NULL; s = s->next) { struct secret_stuff *pks = &s->stuff; int result = (*func)(s, pks, uservoid); if (result == 0) return s; if (result == -1) break; } return NULL; } static struct secret *find_secret_by_pubkey_ckaid_1(struct secret *secrets, const struct pubkey_type *type, const SECItem *pubkey_ckaid) { for (struct secret *s = secrets; s != NULL; s = s->next) { const struct secret_stuff *pks = &s->stuff; id_buf idb; dbg("trying secret %s:%s", enum_name(&secret_kind_names, pks->kind), (pexpect(s->ids != NULL) ? str_id(&s->ids->id, &idb) : "")); /* should be == SECRET_PKI */ switch (pks->kind) { case SECRET_RSA: case SECRET_ECDSA: /* some sort of PKI */ break; default: dbg(" not PKI"); continue; } if (type != NULL && pks->u.pubkey.content.type != type) { /* need exact or wildcard */ dbg(" not %s", type->name); continue; } if (!ckaid_eq_nss(&pks->u.pubkey.content.ckaid, pubkey_ckaid)) { dbg(" wrong ckaid"); continue; } dbg(" matched"); return s; } return NULL; } bool secret_pubkey_same(struct secret *lhs, struct secret *rhs) { /* should be == SECRET_PKI */ switch (lhs->stuff.kind) { case SECRET_RSA: case SECRET_ECDSA: break; default: return false; } /* should be == SECRET_PKI */ switch (rhs->stuff.kind) { case SECRET_RSA: case SECRET_ECDSA: break; default: return false; } if (lhs->stuff.u.pubkey.content.type != rhs->stuff.u.pubkey.content.type) { return false; } return lhs->stuff.u.pubkey.content.type->pubkey_same(&lhs->stuff.u.pubkey.content, &rhs->stuff.u.pubkey.content); } struct secret *lsw_find_secret_by_id(struct secret *secrets, enum secret_kind kind, const struct id *local_id, const struct id *remote_id, bool asym) { enum { match_none = 0, /* bits */ match_default = 1, match_any = 2, match_remote = 4, match_local = 8 }; lset_t 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->stuff.line, enum_name(&secret_kind_names, kind), str_id(local_id, &idl), enum_name(&secret_kind_names, s->stuff.kind)); } if (s->stuff.kind != kind) { dbg(" wrong kind"); continue; } lset_t 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 (id_is_any(&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 -> "PRI_LSET, 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; } if (match == match_none) { dbg(" id didn't match"); continue; } dbg(" match="PRI_LSET, match); if (match == best_match) { /* * Two good matches are equally good: do they * agree? */ bool same = false; switch (kind) { case SECRET_NULL: same = true; break; case SECRET_PSK: same = hunk_eq(s->stuff.u.preshared_secret, best->stuff.u.preshared_secret); break; case SECRET_RSA: case SECRET_ECDSA: same = secret_pubkey_same(s, best); break; case SECRET_XAUTH: /* * We don't support this yet, * but no need to die. */ break; case SECRET_PPK: same = hunk_eq(s->stuff.ppk, best->stuff.ppk); break; default: bad_case(kind); } if (!same) { dbg(" multiple ipsec.secrets entries with distinct secrets match endpoints: first secret used"); /* * list is backwards: take latest in * list */ best = s; } continue; } if (match == match_local && !asym) { /* * Only when this is an asymmetric (eg. public * key) system, allow this-side-only match to * count, even when there are other ids in the * list. */ dbg(" local match not asymetric"); continue; } switch (match) { case match_local: 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 */ /* * XXX: what combinations are missing? */ if (match > best_match) { dbg(" match "PRI_LSET" beats previous best_match "PRI_LSET" match=%p (line=%d)", match, best_match, s, s->stuff.line); /* this is the best match so far */ best_match = match; best = s; } else { dbg(" match "PRI_LSET" loses to best_match "PRI_LSET, match, best_match); } } } dbg("concluding with best_match="PRI_LSET" best=%p (lineno=%d)", best_match, best, best == NULL ? -1 : best->stuff.line); return best; } /* * 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 process_psk_secret(struct file_lex_position *flp, chunk_t *psk) { err_t ugh = NULL; if (flp->quote == '"' || flp->quote == '\'') { size_t len = strlen(flp->tok); if (len < 8) { llog(RC_LOG_SERIOUS, flp->logger, "WARNING: using a weak secret (PSK)"); } *psk = clone_bytes_as_chunk(flp->tok, len, "PSK"); shift(flp); } else { ugh = ttochunk(shunk2(flp->tok, flp->cur - flp->tok), 0, psk); if (ugh != NULL) { /* ttodata didn't like PSK data */ ugh = builddiag("PSK data malformed (%s): %s", ugh, flp->tok); } else { shift(flp); } } dbg("processing PSK at line %d: %s", flp->lino, ugh == NULL ? "passed" : ugh); return ugh; } /* parse XAUTH secret from file */ static err_t process_xauth_secret(struct file_lex_position *flp, chunk_t *xauth) { err_t ugh = NULL; if (flp->quote == '"' || flp->quote == '\'') { *xauth = clone_bytes_as_chunk(flp->tok, strlen(flp->tok), "XAUTH"); shift(flp); } else { ugh = ttochunk(shunk2(flp->tok, flp->cur - flp->tok), 0, xauth); if (ugh != NULL) { /* ttodata didn't like PSK data */ ugh = builddiag("PSK data malformed (%s): %s", ugh, flp->tok); } else { shift(flp); } } dbg("processing XAUTH at line %d: %s", flp->lino, ugh == NULL ? "passed" : ugh); return ugh; } /* parse static PPK */ static err_t process_ppk_static_secret(struct file_lex_position *flp, chunk_t *ppk, chunk_t *ppk_id) { err_t ugh = NULL; if (flp->quote == '"' || flp->quote == '\'') { *ppk_id = clone_bytes_as_chunk(flp->tok, strlen(flp->tok), "PPK ID"); } else { ugh = "No quotation marks found. PPK ID should be in quotation marks"; return ugh; } if (!shift(flp)) { ugh = "No PPK found. PPK should be specified after PPK ID"; free_chunk_content(ppk_id); return ugh; } if (flp->quote == '"' || flp->quote == '\'') { *ppk = clone_bytes_as_chunk(flp->tok, strlen(flp->tok), "PPK"); shift(flp); } else { ugh = ttochunk(shunk2(flp->tok, flp->cur - flp->tok), 0, ppk); if (ugh != NULL) { /* ttodata didn't like PPK data */ ugh = builddiag("PPK data malformed (%s): %s", ugh, flp->tok); free_chunk_content(ppk_id); } else { shift(flp); } } dbg("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 secret_stuff pks = s->stuff; if (pks.kind == SECRET_PPK && hunk_eq(pks.ppk_id, ppk_id)) return s; s = s->next; } return NULL; } static SECKEYPrivateKey *copy_private_key(SECKEYPrivateKey *private_key) { SECKEYPrivateKey *unpacked_key = NULL; if (private_key->pkcs11Slot != NULL) { PK11SlotInfo *slot = PK11_ReferenceSlot(private_key->pkcs11Slot); if (slot != NULL) { dbg("copying key using reference slot"); unpacked_key = PK11_CopyTokenPrivKeyToSessionPrivKey(slot, private_key); PK11_FreeSlot(slot); } } if (unpacked_key == NULL) { CK_MECHANISM_TYPE mech = PK11_MapSignKeyType(private_key->keyType); PK11SlotInfo *slot = PK11_GetBestSlot(mech, NULL); if (slot != NULL) { dbg("copying key using mech/slot"); unpacked_key = PK11_CopyTokenPrivKeyToSessionPrivKey(slot, private_key); PK11_FreeSlot(slot); } } if (unpacked_key == NULL) { dbg("copying key using SECKEY_CopyPrivateKey()"); unpacked_key = SECKEY_CopyPrivateKey(private_key); } return unpacked_key; } 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. * * XXX: The below seem to be acting as a sentinal so that * lsw_find_secret_by_id() always finds something (they act as * wildcards) in the ID list. * * But why are two needed?!?. */ 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 = unset_address; 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 = unset_address; s->ids = idl2; } lock_certs_and_keys(story); s->next = *slist; *slist = s; unlock_certs_and_keys(story); } static void process_secret(struct file_lex_position *flp, struct secret **psecrets, struct secret *s) { err_t ugh = NULL; if (tokeqword(flp, "psk")) { s->stuff.kind = SECRET_PSK; /* preshared key: quoted string or ttodata format */ ugh = !shift(flp) ? "ERROR: unexpected end of record in PSK" : process_psk_secret(flp, &s->stuff.u.preshared_secret); } else if (tokeqword(flp, "xauth")) { /* xauth key: quoted string or ttodata format */ s->stuff.kind = SECRET_XAUTH; ugh = !shift(flp) ? "ERROR: unexpected end of record in PSK" : process_xauth_secret(flp, &s->stuff.u.preshared_secret); } else if (tokeqword(flp, "ppks")) { s->stuff.kind = SECRET_PPK; ugh = !shift(flp) ? "ERROR: unexpected end of record in static PPK" : process_ppk_static_secret(flp, &s->stuff.ppk, &s->stuff.ppk_id); } else { ugh = builddiag("WARNING: ignored unrecognized keyword: %s", flp->tok); } if (ugh != NULL) { llog(RC_LOG_SERIOUS, flp->logger, "\"%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(flp, "expected record boundary in key")) { /* gauntlet has been run: install new secret */ add_secret(psecrets, s, "process_secret"); } } static void process_secret_records(struct file_lex_position *flp, struct secret **psecrets) { /* const struct secret *secret = *psecrets; */ /* read records from ipsec.secrets and load them into our table */ for (;; ) { flushline(flp, NULL); /* silently ditch leftovers, if any */ if (flp->bdry == B_file) break; flp->bdry = B_none; /* eat the Record Boundary */ shift(flp); /* get real first token */ if (tokeqword(flp, "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(flp)) { llog(RC_LOG_SERIOUS, flp->logger, "\"%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) { llog(RC_LOG_SERIOUS, flp->logger, "\"%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); shift(flp); /* move to Record Boundary, we hope */ if (flushline(flp, "ignoring malformed INCLUDE -- expected Record Boundary after filename")) { process_secrets_file(flp, 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->stuff.kind = SECRET_PSK; /* default */ s->stuff.u.preshared_secret = EMPTY_CHUNK; s->stuff.line = flp->lino; s->next = NULL; for (;;) { struct id id; err_t ugh; if (tokeq(flp, ":")) { /* found key part */ shift(flp); /* eat ":" */ process_secret(flp, psecrets, s); break; } /* * an id * See RFC2407 IPsec Domain of * Interpretation 4.6.2 */ if (tokeq(flp, "%any")) { id = empty_id; id.kind = ID_IPV4_ADDR; id.ip_addr = ipv4_info.address.unspec; ugh = NULL; } else if (tokeq(flp, "%any6")) { id = empty_id; id.kind = ID_IPV6_ADDR; id.ip_addr = ipv6_info.address.unspec; ugh = NULL; } else { ugh = atoid(flp->tok, &id); } if (ugh != NULL) { llog(RC_LOG_SERIOUS, flp->logger, "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 = id; i->next = s->ids; s->ids = i; id_buf b; dbg("id type added to secret(%p) %s: %s", s, enum_name(&secret_kind_names, s->stuff.kind), str_id(&id, &b)); } if (!shift(flp)) { /* unexpected Record Boundary or EOF */ llog(RC_LOG_SERIOUS, flp->logger, "\"%s\" line %d: unexpected end of id list", flp->filename, flp->lino); pfree(s); break; } } } } } static void process_secrets_file(struct file_lex_position *oflp, struct secret **psecrets, const char *file_pat) { if (oflp->depth > 10) { llog(RC_LOG_SERIOUS, oflp->logger, "preshared secrets file \"%s\" nested too deeply", file_pat); return; } /* do globbing */ glob_t globbuf; int r = lswglob(file_pat, &globbuf, "secrets", oflp->logger); switch (r) { case 0: /* success */ /* for each file... */ for (char **fnp = globbuf.gl_pathv; fnp != NULL && *fnp != NULL; fnp++) { struct file_lex_position *flp = NULL; if (lexopen(&flp, *fnp, false, oflp)) { llog(RC_LOG, flp->logger, "loading secrets from \"%s\"", *fnp); flushline(flp, "file starts with indentation (continuation notation)"); process_secret_records(flp, psecrets); lexclose(&flp); } } break; case GLOB_NOSPACE: llog(RC_LOG_SERIOUS, oflp->logger, "out of space processing secrets filename \"%s\"", file_pat); break; case GLOB_ABORTED: /* already logged by globugh_secrets() */ break; case GLOB_NOMATCH: llog(RC_LOG, oflp->logger, "no secrets filename matched \"%s\"", file_pat); break; default: llog(RC_LOG_SERIOUS, oflp->logger, "unknown glob error %d", r); break; } globfree(&globbuf); } void lsw_free_preshared_secrets(struct secret **psecrets, struct logger *logger) { lock_certs_and_keys("free_preshared_secrets"); if (*psecrets != NULL) { struct secret *s, *ns; llog(RC_LOG, logger, "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->stuff.kind) { case SECRET_PSK: pfree(s->stuff.u.preshared_secret.ptr); break; case SECRET_PPK: pfree(s->stuff.ppk.ptr); pfree(s->stuff.ppk_id.ptr); break; case SECRET_XAUTH: pfree(s->stuff.u.preshared_secret.ptr); break; case SECRET_RSA: case SECRET_ECDSA: /* Note: pub is all there is */ SECKEY_DestroyPrivateKey(s->stuff.u.pubkey.private_key); s->stuff.u.pubkey.content.type->free_pubkey_content(&s->stuff.u.pubkey.content); break; default: bad_case(s->stuff.kind); } pfree(s); } *psecrets = NULL; } unlock_certs_and_keys("free_preshared_secrets"); } void lsw_load_preshared_secrets(struct secret **psecrets, const char *secrets_file, struct logger *logger) { lsw_free_preshared_secrets(psecrets, logger); struct file_lex_position flp = { .logger = logger, .depth = 0, }; process_secrets_file(&flp, psecrets, secrets_file); } struct pubkey *pubkey_addref_where(struct pubkey *pk, where_t where) { return addref_where(pk, where); } /* * free a public key struct */ static void free_pubkey(void *obj, where_t where UNUSED) { struct pubkey *pk = obj; free_id_content(&pk->id); /* algorithm-specific freeing */ pk->content.type->free_pubkey_content(&pk->content); pfree(pk); } void pubkey_delref_where(struct pubkey **pkp, where_t where) { delref_where(pkp, where); } /* * 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) pubkey_delref_where(&p->key, HERE); pfree(p); return nxt; } void free_public_keys(struct pubkey_list **keys) { while (*keys != NULL) *keys = free_public_keyentry(*keys); } /* * XXX: this gets called, via replace_public_key() with a PK that is * still pointing into a cert. Hence the "how screwed up is this?" * :-( */ static void install_public_key(struct pubkey **pk, struct pubkey_list **head) { struct pubkey_list *p = alloc_thing(struct pubkey_list, "pubkey entry"); /* install new key at front */ p->key = *pk; p->next = *head; *head = p; *pk = NULL; /* stolen */ } 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->content.type == type) *pp = free_public_keyentry(p); else pp = &p->next; } } void replace_public_key(struct pubkey_list **pubkey_db, struct pubkey **pk) { /* ??? clang 3.5 thinks pk might be NULL */ delete_public_keys(pubkey_db, &(*pk)->id, (*pk)->content.type); install_public_key(pk, pubkey_db); passert(*pk == NULL); /* stolen */ } static struct pubkey *alloc_pubkey(const struct id *id, /* ASKK */ enum dns_auth_level dns_auth_level, realtime_t install_time, realtime_t until_time, uint32_t ttl, const struct pubkey_content *pkc, shunk_t issuer, where_t where) { pexpect(pkc->keyid.keyid[0] != '\0'); pexpect(pkc->ckaid.len > 0); struct pubkey *pk = refcnt_overalloc(struct pubkey, issuer.len, free_pubkey, where); pk->content = *pkc; pk->id = clone_id(id, "public key id"); pk->dns_auth_level = dns_auth_level; pk->installed_time = install_time; pk->until_time = until_time; pk->dns_ttl = ttl; /* Append any issuer to the end */ if (issuer.len > 0) { memcpy(pk->end, issuer.ptr, issuer.len); pk->issuer = shunk2(pk->end, issuer.len); } return pk; } diag_t unpack_dns_ipseckey(const struct id *id, /* ASKK */ enum dns_auth_level dns_auth_level, enum ipseckey_algorithm_type algorithm_type, realtime_t install_time, realtime_t until_time, uint32_t ttl, const shunk_t dnssec_pubkey, struct pubkey **pkp, struct pubkey_list **head) { /* * First: unpack the raw public key. */ struct pubkey_content scratch_pkc; if (algorithm_type == IPSECKEY_ALGORITHM_X_PUBKEY) { diag_t d = pubkey_der_to_pubkey_content(dnssec_pubkey, &scratch_pkc); if (d != NULL) { return d; } } else { const struct pubkey_type *pubkey_type = NULL; /* TBD */ switch (algorithm_type) { case IPSECKEY_ALGORITHM_RSA: pubkey_type = &pubkey_type_rsa; break; case IPSECKEY_ALGORITHM_ECDSA: pubkey_type = &pubkey_type_ecdsa; break; default: return diag("invalid IPSECKEY Algorithm Type %u", algorithm_type); } diag_t d = pubkey_type->ipseckey_rdata_to_pubkey_content(dnssec_pubkey, &scratch_pkc); if (d != NULL) { return d; } } passert(scratch_pkc.type != NULL); /* * Second: use extracted information to create the pubkey. */ struct pubkey *pubkey = alloc_pubkey(id, dns_auth_level, install_time, until_time, ttl, &scratch_pkc, null_shunk, /* raw keys have no issuer */ HERE); if (pkp != NULL) { *pkp = pubkey_addref(pubkey); } install_public_key(&pubkey, head); passert(pubkey == NULL); /* stolen */ return NULL; } static const struct pubkey_type *pubkey_type_nss(SECKEYPublicKey *pubk) { KeyType key_type = SECKEY_GetPublicKeyType(pubk); switch (key_type) { case rsaKey: return &pubkey_type_rsa; case ecKey: return &pubkey_type_ecdsa; default: return NULL; } } static const struct pubkey_type *private_key_type_nss(SECKEYPrivateKey *private_key) { KeyType key_type = SECKEY_GetPrivateKeyType(private_key); switch (key_type) { case rsaKey: return &pubkey_type_rsa; case ecKey: return &pubkey_type_ecdsa; default: return NULL; } } static err_t add_private_key(struct secret **secrets, const struct secret_stuff **pks, SECKEYPublicKey *pubk, SECItem *ckaid_nss, const struct pubkey_type *type, SECKEYPrivateKey *private_key) { struct secret *s = alloc_thing(struct secret, "pubkey secret"); s->stuff.kind = type->private_key_kind; s->stuff.line = 0; /* make an unpacked copy of the private key */ s->stuff.u.pubkey.private_key = copy_private_key(private_key); err_t err = type->extract_pubkey_content(&s->stuff.u.pubkey.content, pubk, ckaid_nss); if (err != NULL) { /* extract should leave pubkey_content clean */ SECKEY_DestroyPrivateKey(s->stuff.u.pubkey.private_key); /* allocated above */ pfree(s); return err; } passert(s->stuff.u.pubkey.content.type == type); pexpect(s->stuff.u.pubkey.content.ckaid.len > 0); pexpect(s->stuff.u.pubkey.content.keyid.keyid[0] != '\0'); add_secret(secrets, s, "lsw_add_rsa_secret"); *pks = &s->stuff; return NULL; } static err_t find_or_load_private_key_by_cert_3(struct secret **secrets, CERTCertificate *cert, const struct secret_stuff **pks, struct logger *logger, SECKEYPublicKey *pubk, SECItem *ckaid_nss, const struct pubkey_type *type) { SECKEYPrivateKey *private_key = PK11_FindKeyByAnyCert(cert, lsw_nss_get_password_context(logger)); if (private_key == NULL) return "NSS: cert private key not found"; err_t err = add_private_key(secrets, pks, /* extracted fields */ pubk, ckaid_nss, type, private_key); SECKEY_DestroyPrivateKey(private_key); return err; } static err_t find_or_load_private_key_by_cert_2(struct secret **secrets, CERTCertificate *cert, const struct secret_stuff **pks, bool *load_needed, struct logger *logger, SECKEYPublicKey *pubk, SECItem *ckaid_nss) { /* XXX: see also nss_cert_key_kind(cert) */ const struct pubkey_type *type = pubkey_type_nss(pubk); if (type == NULL) { return "NSS cert not supported"; } struct secret *s = find_secret_by_pubkey_ckaid_1(*secrets, type, ckaid_nss); if (s != NULL) { dbg("secrets entry for certificate already exists: %s", cert->nickname); *pks = &s->stuff; *load_needed = false; return NULL; } dbg("adding %s secret for certificate: %s", type->name, cert->nickname); *load_needed = true; err_t err = find_or_load_private_key_by_cert_3(secrets, cert, pks, logger, /* extracted fields */ pubk, ckaid_nss, type); return err; } static err_t find_or_load_private_key_by_cert_1(struct secret **secrets, CERTCertificate *cert, const struct secret_stuff **pks, bool *load_needed, struct logger *logger, SECKEYPublicKey *pubk) { /* * Getting a SECItem ptr from PK11_GetLowLevelKeyID doesn't * mean that the private key exists - it is just a hash formed * from the cert's public key. */ SECItem *ckaid_nss = PK11_GetLowLevelKeyIDForCert(NULL, cert, lsw_nss_get_password_context(logger)); /* MUST FREE */ if (ckaid_nss == NULL) { return "NSS: key ID not found"; } err_t err = find_or_load_private_key_by_cert_2(secrets, cert, pks, load_needed, logger, /* extracted fields */ pubk, ckaid_nss); SECITEM_FreeItem(ckaid_nss, PR_TRUE); return err; } err_t find_or_load_private_key_by_cert(struct secret **secrets, const struct cert *cert, const struct secret_stuff **pks, bool *load_needed, struct logger *logger) { *load_needed = false; if (cert == NULL || cert->nss_cert == NULL) { return "NSS cert not found"; } SECKEYPublicKey *pubk = SECKEY_ExtractPublicKey(&cert->nss_cert->subjectPublicKeyInfo); if (pubk == NULL) { /* dbg(... nss error) */ return "NSS: could not determine certificate kind; SECKEY_ExtractPublicKey() failed"; } err_t err = find_or_load_private_key_by_cert_1(secrets, cert->nss_cert, pks, load_needed, logger, /* extracted fields */ pubk); SECKEY_DestroyPublicKey(pubk); return err; } static err_t find_or_load_private_key_by_ckaid_1(struct secret **secrets, const struct secret_stuff **pks, SECItem *ckaid_nss, SECKEYPrivateKey *private_key) { const struct pubkey_type *type = private_key_type_nss(private_key); if (type == NULL) { return "NSS private key not supported (unknown type)"; } SECKEYPublicKey *pubk = SECKEY_ConvertToPublicKey(private_key); /* must free */ if (pubk == NULL) { return "NSS private key has no public key"; } err_t err = add_private_key(secrets, pks, pubk, ckaid_nss, type, private_key); SECKEY_DestroyPublicKey(pubk); return err; } err_t find_or_load_private_key_by_ckaid(struct secret **secrets, const ckaid_t *ckaid, const struct secret_stuff **pks, bool *load_needed, struct logger *logger) { *load_needed = false; passert(ckaid != NULL); SECItem ckaid_nss = same_ckaid_as_secitem(ckaid); struct secret *s = find_secret_by_pubkey_ckaid_1(*secrets, NULL, &ckaid_nss); if (s != NULL) { dbg("secrets entry for ckaid already exists"); *pks = &s->stuff; *load_needed = false; return NULL; } *load_needed = true; PK11SlotInfo *slot = PK11_GetInternalKeySlot(); if (!pexpect(slot != NULL)) { return "NSS: has no internal slot ...."; } /* must free */ SECKEYPrivateKey *private_key = PK11_FindKeyByKeyID(slot, &ckaid_nss, lsw_nss_get_password_context(logger)); if (private_key == NULL) { /* * XXX: The code loading ipsec.secrets also tries to * use the CKAID to find the certificate, and then * uses that to find the private key? Why? */ return "can't find the private key matching the NSS CKAID"; } ckaid_buf ckb; dbg("loaded private key matching CKAID %s", str_ckaid(ckaid, &ckb)); err_t err = find_or_load_private_key_by_ckaid_1(secrets, pks, &ckaid_nss, private_key); SECKEY_DestroyPrivateKey(private_key); return err; } static diag_t create_pubkey_from_cert_1(const struct id *id, CERTCertificate *cert, SECKEYPublicKey *pubkey_nss, struct pubkey **pk, struct logger *logger) { const struct pubkey_type *type = pubkey_type_nss(pubkey_nss); if (type == NULL) { return diag("NSS: certificate key kind is unknown; not creating pubkey"); } SECItem *ckaid_nss = PK11_GetLowLevelKeyIDForCert(NULL, cert, lsw_nss_get_password_context(logger)); /* must free */ if (ckaid_nss == NULL) { /* someone deleted CERT from the NSS DB */ return diag("NSS: could not extract CKAID from RSA certificate '%s'", cert->nickname); } struct pubkey_content pkc = {0}; err_t err = type->extract_pubkey_content(&pkc, pubkey_nss, ckaid_nss); if (err != NULL) { SECITEM_FreeItem(ckaid_nss, PR_TRUE); return diag("NSS: could not extract pubkey content: %s", err); } passert(pkc.type != NULL); realtime_t install_time = realnow(); realtime_t until_time; PRTime not_before, not_after; if (CERT_GetCertTimes(cert, ¬_before, ¬_after) != SECSuccess) { until_time = realtime(-1); } else { until_time = realtime(not_after / PR_USEC_PER_SEC); } *pk = alloc_pubkey(id, /*dns_auth_level*/0/*default*/, install_time, until_time, /*ttl*/0, &pkc, same_secitem_as_shunk(cert->derIssuer), HERE); SECITEM_FreeItem(ckaid_nss, PR_TRUE); return NULL; } diag_t create_pubkey_from_cert(const struct id *id, CERTCertificate *cert, struct pubkey **pk, struct logger *logger) { if (!pexpect(cert != NULL)) { return NULL; } /* * Try to convert CERT to an internal PUBKEY object. If * someone, in parallel, deletes the underlying cert from the * NSS DB, then this will fail. */ SECKEYPublicKey *pubkey_nss = SECKEY_ExtractPublicKey(&cert->subjectPublicKeyInfo); /* must free */ if (pubkey_nss == NULL) { return diag("NSS: could not extract public key from certificate '%s'", cert->nickname); } diag_t d = create_pubkey_from_cert_1(id, cert, pubkey_nss, pk, logger); SECKEY_DestroyPublicKey(pubkey_nss); return d; } libreswan-4.14/lib/libswan/shunk.c000066400000000000000000000154761457372064200171600ustar00rootroot00000000000000/* 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 "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_HUNK; 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_eat(shunk_t *shunk, shunk_t dinner) { if (shunk->ptr == NULL || dinner.ptr == NULL) { return false; } if (shunk->len < dinner.len) { return false; } if (strncmp(shunk->ptr, dinner.ptr, dinner.len) != 0) { return false; } *shunk = shunk_slice(*shunk, dinner.len, shunk->len); return true; } bool shunk_streat(shunk_t *shunk, const char *dinner) { return shunk_eat(shunk, shunk1(dinner)); } 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 INPUT to an unsigned. * * If OUTPUT is NULL, INPUT must only contain the numeric value, else * OUTPUT is set to any trailing characters. * * If CEILING is non-ZERO, *dest can't be greater than CEILING. */ err_t shunk_to_uintmax(shunk_t input, shunk_t *output, unsigned draft_base, uintmax_t *dest) { *dest = 0; if (output != NULL) { *output = (shunk_t) NULL_HUNK; } if (input.len == 0) { return "empty string"; } /* * Detect standard prefixes. * * MIMIC BSD: * * Only auto detect the 0[xb] prefix when it is followed by at * least one valid digit. If the digit is missing, fall back * to decimal, and not octal, so that decimal errors are * returned. */ unsigned base; if (draft_base == 0) { if (hunk_strcasestarteq(input, "0x")) { if (char_isxdigit(hunk_char(input, 2))) { shunk_strcaseeat(&input, "0x"); base = 16; } else { base = 10; } } else if (hunk_strcasestarteq(input, "0b")) { if (char_isbdigit(hunk_char(input, 2))) { shunk_strcaseeat(&input, "0b"); base = 2; } else { base = 10; } } else if (hunk_char(input, 0) == '0') { /* so 0... is interpreted as 0 below */ base = 8; } else { base = 10; } #if 0 /* don't mimic this part of strtoul()? */ } else if (base == 8) { shunk_strcaseeat(&input, "0"); } else if (base == 16) { shunk_strcaseeat(&input, "0x"); #endif } else { base = draft_base; } /* something to convert */ shunk_t cursor = input; /* something */ uintmax_t u = 0; while (char_isprint(hunk_char(cursor, 0))) { unsigned char c = hunk_char(cursor, 0); /* convert to a digit; <0 will overflow */ unsigned d; if (char_isdigit(c)) { d = c - '0'; } else if (c >= 'a') { d = c - 'a' + 10; } else if (c >= 'A') { d = c - 'A' + 10; } else { break; } /* valid? */ if (d >= base) { break; } /* will multiplying U by BASE overflow? */ const uintmax_t rlimit = UINTMAX_MAX / base; if (u > rlimit) { return "unsigned-long overflow"; } u = u * base; /* will adding D to U*BASE overflow? */ const uintmax_t dlimit = UINTMAX_MAX - u; if (d > dlimit) { return "unsigned-long overflow"; } u = u + d; cursor = shunk_slice(cursor, 1, cursor.len); } if (cursor.len == input.len) { /* nothing valid */ switch (draft_base) { case 2: return "first binary digit invalid"; case 8: return "first octal digit invalid"; case 10: return "first decimal digit invalid"; case 16: return "first hex digit invalid"; default: return "first digit invalid"; } } /* everything consumed? */ if (output == NULL) { if (cursor.len > 0) { switch (base) { case 2: return "non-binary digit in number"; case 8: return "non-octal digit in number"; case 10: return "non-decimal digit in number"; case 16: return "non-hex digit in number"; default: return "non-digit in number"; } } } *dest = u; if (output != NULL) { *output = cursor; } return NULL; } libreswan-4.14/lib/libswan/sparse_names.c000066400000000000000000000037511457372064200205010ustar00rootroot00000000000000/* * 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 * Copyright (C) 2020 Yulia Kuzovkova * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT 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 "sparse_names.h" #include "jambuf.h" /* look up enum names in a sparse_names */ const char *sparse_name(sparse_names sd, unsigned long val) { for (const struct sparse_name *p = sd; p->name != NULL; p++) { if (p->value == val) { return p->name; } } return NULL; } /* * find or construct a string to describe an sparse value */ size_t jam_sparse(struct jambuf *buf, sparse_names sd, unsigned long val) { const char *p = sparse_name(sd, val); if (p != NULL) { return jam_string(buf, p); } return jam(buf, "%lu??", val); } const char *str_sparse(sparse_names sd, unsigned long val, sparse_buf *buf) { const char *p = sparse_name(sd, val); if (p != NULL) { return p; } snprintf(buf->buf, sizeof(buf->buf), "%lu??", val); return buf->buf; } const char *sparse_sparse_name(sparse_sparse_names ssd, unsigned long v1, unsigned long v2) { while (ssd->names != NULL) { if (ssd->value == v1) { return sparse_name(ssd->names, v2); } ssd++; } return NULL; } libreswan-4.14/lib/libswan/subnetof.3.xml000066400000000000000000000061141457372064200203610ustar00rootroot00000000000000 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-4.14/lib/libswan/subnettypeof.c000066400000000000000000000025541457372064200205500ustar00rootroot00000000000000/* * 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-4.14/lib/libswan/test_buffer.c000066400000000000000000000070261457372064200203300ustar00rootroot00000000000000/* * Copyright (C) 2014-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. */ #include #include "constants.h" #include "lswalloc.h" #include "pk11pub.h" #include "crypt_symkey.h" #include "test_buffer.h" #include "ike_alg.h" #include "lswlog.h" static chunk_t zalloc_chunk(size_t length, const char *name) { chunk_t chunk; chunk.len = length; chunk.ptr = alloc_bytes(length, name); memset(chunk.ptr, 0, chunk.len); return chunk; } /* * Given an ASCII string, convert it into a chunk of bytes. If the * string is prefixed by 0x assume the contents are hex (with spaces) * and decode it; otherwise it is assumed that the ASCII (minus the * NUL) should be copied. * The caller must free the chunk. */ chunk_t decode_to_chunk(const char *prefix, const char *original) { DBGF(DBG_CRYPT, "decode_to_chunk: %s: input \"%s\"", prefix, original); chunk_t chunk; if (startswith(original, "0x")) { chunk = chunk_from_hex(original + strlen("0x"), original); } else { chunk = zalloc_chunk(strlen(original), original); memcpy(chunk.ptr, original, chunk.len); } if (DBGP(DBG_CRYPT)) { DBG_dump_hunk("decode_to_chunk: output: ", chunk); } return chunk; } PK11SymKey *decode_hex_to_symkey(const char *prefix, const char *string, struct logger *logger) { chunk_t chunk = chunk_from_hex(string, prefix); PK11SymKey *symkey = symkey_from_hunk(prefix, chunk, logger); free_chunk_content(&chunk); return symkey; } /* * Verify that the chunk's data is the same as actual. */ bool verify_bytes(const char *desc, const void *expected, size_t expected_size, const void *actual, size_t actual_size) { if (expected_size != actual_size) { DBGF(DBG_CRYPT, "verify_chunk: %s: expected length %zd but got %zd", desc, expected_size, actual_size); return false; } size_t i; for (i = 0; i < expected_size; i++) { uint8_t e = ((const uint8_t*)expected)[i]; uint8_t a = ((const uint8_t*)actual)[i]; if (e != a) { /* Caller should issue the real log message. */ DBGF(DBG_CRYPT, "verify_chunk_data: %s: bytes at %zd differ, expected %02x found %02x", desc, i, e, a); return false; } } DBGF(DBG_CRYPT, "verify_chunk_data: %s: ok", desc); return true; } /* verify that expected is the same as actual */ bool verify_symkey(const char *desc, chunk_t expected, PK11SymKey *actual, struct logger *logger) { if (expected.len != sizeof_symkey(actual)) { DBGF(DBG_CRYPT, "%s: expected length %zd but got %zd", desc, expected.len, sizeof_symkey(actual)); return false; } chunk_t chunk = chunk_from_symkey(desc, actual, logger); bool ok = verify_hunk(desc, expected, chunk); free_chunk_content(&chunk); return ok; } /* * Turn the raw key into SymKey. */ PK11SymKey *decode_to_key(const struct encrypt_desc *encrypt_desc, const char *encoded_key, struct logger *logger) { chunk_t raw_key = decode_to_chunk("raw_key", encoded_key); PK11SymKey *symkey = encrypt_key_from_hunk("symkey", encrypt_desc, raw_key, logger); free_chunk_content(&raw_key); return symkey; } libreswan-4.14/lib/libswan/timescale.c000066400000000000000000000033201457372064200177570ustar00rootroot00000000000000/* time scale, for libreswan * * Copyright (C) 2022 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 "timescale.h" #include "lswcdefs.h" #include "constants.h" /* for secs_per_* */ const struct timescale timescale_milliseconds = { "ms", .ms = 1, }; const struct timescale timescale_seconds = { "s", .ms = 1 * 1000, }; const struct timescale timescale_minutes = { "m", .ms = 1 * 1000 * secs_per_minute, }; const struct timescale timescale_hours = { "h", .ms = 1 * 1000 * secs_per_hour, }; const struct timescale timescale_days = { "d", .ms = 1 * 1000 * secs_per_day, }; const struct timescale timescale_weeks = { "w", .ms = 1 * 1000 * secs_per_day * 7, }; static const struct timescale *timescales[] = { ×cale_milliseconds, ×cale_seconds, ×cale_minutes, ×cale_hours, ×cale_days, ×cale_weeks, }; const struct timescale *ttotimescale(shunk_t cursor, const struct timescale *default_scale) { if (cursor.len == 0) { /* default scaling */ return default_scale; } FOR_EACH_ELEMENT(scale, timescales) { if (hunk_strcaseeq(cursor, (*scale)->suffix)) { return *scale; } } return NULL; } libreswan-4.14/lib/libswan/ttoaddress.3.xml000066400000000000000000000360021457372064200207070ustar00rootroot00000000000000 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-4.14/lib/libswan/ttoaddress.c000066400000000000000000000230271457372064200201730ustar00rootroot00000000000000/* * conversion from text forms of addresses to internal ones * * Copyright (C) 2000 Henry Spencer. * Copyright (C) 2019-2021 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. * */ /* * Unit testing is available through * OBJ.$WHATEVER/testing/programs/ipcheck/ipcheck * This does not require KVM and is built by "make base". */ #include #include /* for gethostbyname2() */ #include /* for AF_INET/AF_INET6/AF_UNSPEC */ #include "ip_address.h" #include "ip_sockaddr.h" #include "ip_info.h" #include "lswalloc.h" /* for alloc_things(), pfree() */ #include "lswlog.h" /* for pexpect() */ #include "hunk.h" /* for char_is_xdigit() */ static bool tryhex(shunk_t hex, ip_address *dst); static err_t trydotted(shunk_t src, ip_address *); static err_t colon(shunk_t src, ip_address *); /* * ttoaddress_num - convert "numeric" IP address to binary address. * * NULL for success, else static string literal diagnostic. */ err_t ttoaddress_num(shunk_t src, const struct ip_info *afi, ip_address *dst) { *dst = unset_address; if (src.len == 0) { return "empty string"; } /* * Hack to recognize a HEX IPv4 address; presumably DNS names * can't start with a number so this can't be misinterpreted. * * If this fails, stumble on like nothing happened, letting * the more typical code report an error. */ if (afi == &ipv4_info) { if (tryhex(src, dst)) { return NULL; } return trydotted(src, dst); } if (afi == &ipv6_info) { return colon(src, dst); } if (afi == NULL) { if (tryhex(src, dst)) { return NULL; } if (memchr(src.ptr, ':', src.len) != NULL) { return colon(src, dst); } return trydotted(src, dst); } return "address family unknown"; } /* * tryhex - try conversion as an eight-digit hex number (AF_INET only) */ static bool tryhex(shunk_t hex, ip_address *dst) { if (hex.len != strlen("0x12345678")) { return false; } if (!shunk_strcaseeat(&hex, "0x")) { return false; } uintmax_t ul; err_t err = shunk_to_uintmax(hex, NULL, 16, &ul); if (err != NULL) { return false; } if (ul > UINT32_MAX) { return false; /* IPv4 is 32-bit */ } struct in_addr addr = { htonl(ul), }; *dst = address_from_in_addr(&addr); return true; } /* * trydotted - try conversion as dotted numeric (AF_INET only). * * But could a DNS name also be a valid IPv4 address, vis: * - can start with a decimal-digit * - can end with a decimal-digit * - must contain at least one letter * https://tools.ietf.org/html/rfc1912 * * Yes, for instance: 0x01.0x02.0x03.0x04. * * This code tries to avoid this pitfall by only allowing non-decimal * fields when they match a very limited format. */ static err_t trydotted(shunk_t src, ip_address *dst) { struct ip_bytes bytes = unset_ip_bytes; shunk_t cursor = src; for (unsigned b = 0; b < 4 && cursor.ptr != NULL /* more-input */; b++) { /* Danger: nested breaks and returns. */ /* * Carve off the next number. * * This way, given "09.1.2.", the full sub-string "09" * is extracted and converted. Being invalid, it will * report an error about a bogus digit (and not the * less meaningful trailing garbage error). * * After the last token has been extracted cursor is * left pointing at NULL i.e., cursor.ptr==NULL. */ shunk_t token = shunk_token(&cursor, NULL, "."); if (token.len == 0) { /* ex: 0xa. */ return "empty dotted-numeric address field"; } #if 0 fprintf(stderr, "cursor="PRI_SHUNK" token="PRI_SHUNK"\n", pri_shunk(cursor), pri_shunk(token)); #endif /* * Try converting to a number. * * See examples in wikepedia. * * This lets uintmax decide how to convert the number * (play with wget). * * The alternative is to do a very strict check. */ #if 0 unsigned base; if (token.len == strlen("0xXX") && shunk_strcaseeat(&token, "0x")) { base = 16; } else if (token.len == strlen("0ooo") && shunk_strcaseeat(&token, "0")) { base = 8; } else { base = 10; } if (hunk_strcasestarteq(token, "0") && token.len == strlen("0xXX")) { base = 16; } uintmax_t byte; err_t err = shunk_to_uintmax(token, NULL, base, &byte); #else uintmax_t byte; err_t err = shunk_to_uintmax(token, NULL, 0, &byte); #endif if (err != NULL) { return err; } /* * The last byte overflows into earlier unfilled * bytes. For instance: * * 127.1 -> 127.0.0.1 * 127.65534 -> 127.0.255.254 * * A bizarre hangover from address classes: * https://en.wikipedia.org/wiki/IPv4#Address_representations * * Now while it is arguable that: * * 65534 -> 0.0.255.254 * 127 -> 0.0.0.127 !?!?! * * is also valid, that is too weird and rejected (but * 0x01020304 is accepted by an earlier call to * tryhex()). */ if (cursor.len == 0 && b > 0) { for (unsigned e = 3; e >= b && byte != 0; e--) { bytes.byte[e] = byte; /* truncate */ byte = byte >> 8; } if (byte != 0) { return "overflow in dotted-numeric address"; } break; } /* A non-last bytes need to fit into the byte */ if (byte > UINT8_MAX) { return "byte overflow in dotted-numeric address"; } bytes.byte[b] = byte; } if (cursor.ptr != NULL) { return "garbage at end of dotted-address"; } *dst = address_from_raw(HERE, ipv4_info.ip_version, bytes); return NULL; } /* * colon - convert IPv6 "numeric" address */ static err_t colon(shunk_t src, ip_address *dst) { shunk_t cursor = src; struct ip_bytes u = unset_ip_bytes; # define IT "IPv6 numeric address" int gapat = -1; /* where was empty piece seen */ unsigned colon_count = 0; unsigned i = 0; /* while there is more to parse and room for a pair of octets ... */ while (cursor.len > 0 && i <= sizeof(u.byte) - 2) { /* all paths needs to make progress or return */ if (shunk_strcaseeat(&cursor, ":")) { colon_count++; if (colon_count > 2) { return "::: in " IT; } if (colon_count == 2) { if (gapat >= 0) { return "more than one :: in " IT; } gapat = i; } } else if (colon_count == 1 && i == 0) { return "single leading `:' in " IT; } else { /* parsing: NNNN[:...] */ colon_count = 0; uintmax_t value; err_t oops = shunk_to_uintmax(cursor, &cursor, 16, &value); if (oops != NULL) { return oops; } if (value > 65535) { return "too large"; } /* network order */ u.byte[i++] = value >> 8; u.byte[i++] = value & 0xff; } } if (cursor.len != 0 && hunk_char(cursor, 0) == ':') { /* special, common case */ return "trailing `:' in " IT; } if (cursor.len != 0) { return "extra garbage on end of " IT; } if (gapat < 0 && i < sizeof(u.byte)) { return "incomplete " IT; } if (gapat >= 0 && i == sizeof(u.byte)) { return "non-abbreviating empty field in " IT; } /* shift bytes; fill gap with zeros */ if (gapat >= 0) { int gap = sizeof(u.byte) - i; /* short by ... */ /* use memmove(); there definitely an overlap! */ memmove(&u.byte[gapat + gap], &u.byte[gapat], i - gapat); memset(&u.byte[gapat], '\0', gap); } *dst = address_from_raw(HERE, ipv6_info.ip_version, u); return NULL; } /* * ttoaddress_dns * * ??? numeric addresses are handled by getaddrinfo; perhaps the hex form is lost. * ??? change: we no longer filter out bad characters. Surely getaddrinfo(3) does. */ err_t ttoaddress_dns(shunk_t src, const struct ip_info *afi, ip_address *dst) { *dst = unset_address; char *name = clone_hunk_as_string(src, "ttoaddress_dns"); /* must free */ struct addrinfo *res = NULL; /* must-free when EAI==0 */ int family = afi == NULL ? AF_UNSPEC : afi->af; const struct addrinfo hints = (struct addrinfo) { .ai_family = family, }; int eai = getaddrinfo(name, NULL, &hints, &res); if (eai != 0) { /* * Return what the pluto testsuite expects for now. * * Error return is intricate because we cannot compose * a static string. * * XXX: How portable are errors returned by * gai_strerror(eai)? * * XXX: what is with "(no validation performed)"? * Perhaps it is referring to DNSSEC. */ pfree(name); /* RES is not defined */ switch (family) { case AF_INET6: return "not a numeric IPv6 address and name lookup failed (no validation performed)"; case AF_INET: return "not a numeric IPv4 address and name lookup failed (no validation performed)"; default: return "not a numeric IPv4 or IPv6 address and name lookup failed (no validation performed)"; } } /* * When AFI is specified, use the first entry; and prefer IPv4 * when it wasn't. * * Linux orders things IPv4->IPv6, but NetBSD at least is the * reverse; hence the search. */ struct addrinfo *winner = res; if (afi == NULL) { for (struct addrinfo *r = res; r!= NULL; r = r->ai_next) { if (r->ai_family == AF_INET) { winner = r; break; } } } /* boneheaded getaddrinfo(3) leaves port field undefined */ err_t err = sockaddr_to_address_port(winner->ai_addr, winner->ai_addrlen, dst, NULL/*ignore port*/); passert(address_type(dst)->af == winner->ai_family); freeaddrinfo(res); pfree(name); return err; } libreswan-4.14/lib/libswan/ttoaddress_list_num.c000066400000000000000000000040101457372064200220740ustar00rootroot00000000000000/* cloning an address list, for libreswan * * Copyright (C) 2022 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 "passert.h" #include "lswlog.h" /* for dbg() */ #include "ip_address.h" err_t ttoaddress_list_num(shunk_t input, const char *delims, const struct ip_info *type, ip_address **output) { *output = NULL; if (input.ptr == NULL) { return NULL; } dbg("%s() input: "PRI_SHUNK, __func__, pri_shunk(input)); /* * Pass 1: determine the number of tokens. */ unsigned nr_tokens = 0; shunk_t cursor = input; while (true) { shunk_t token = shunk_token(&cursor, NULL/*delim*/, delims); if (token.ptr == NULL) { break; } if (token.len == 0) { continue; } /* validate during first pass */ ip_address tmp; err_t e = ttoaddress_num(token, type, &tmp); if (e != NULL) { return e; } nr_tokens++; } if (nr_tokens == 0) { return NULL; } /* * Allocate. */ dbg("%s() nr tokens %u", __func__, nr_tokens); *output = alloc_things(ip_address, nr_tokens + 1, "addresses"); /* * pass 2: copy things over. */ cursor = input; ip_address *address = *output; while (true) { shunk_t token = shunk_token(&cursor, NULL/*delim*/, delims); if (token.ptr == NULL) { break; } if (token.len == 0) { continue; } err_t e = ttoaddress_num(token, type, address); passert(e == NULL); address_buf ab; dbg("%s() %s", __func__, str_address(address, &ab)); address++; } *address = unset_address; return NULL; } libreswan-4.14/lib/libswan/ttobinary-iec-60027-2.c000066400000000000000000000032541457372064200214030ustar00rootroot00000000000000/* ttobinary(), for libreswan * * Copyright (C) 2022 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. */ #include #include "lswcdefs.h" /* for elemsof() */ #include "constants.h" /* for strncaseeq() */ #include "enum_names.h" #include "binary-iec-60027-2.h" #include "binaryscale-iec-60027-2.h" #include "passert.h" #include "lswalloc.h" #include "ip_protocol.h" #include "ip_encap.h" #include "jambuf.h" diag_t ttobinary(const char *t, uint64_t *r, bool prefix_B) { *r = 0; uint64_t v; shunk_t cursor = shunk1(t); err_t err = shunk_to_uintmax(cursor, &cursor, 10/*any-base*/, &v); if (err != NULL) { return diag("bad binary%s value \"%s\": %s", prefix_B ? " Bytes" : "", t, err); } const struct binaryscale *scale = prefix_B ? ttobinarybytesscale(cursor) : ttobinaryscale(cursor); if (scale == NULL) { return diag("unrecognized binary%s multiplier \""PRI_SHUNK"\"", prefix_B ? "Bytes" : "", pri_shunk(cursor)); } /* XXX: I guess this works? */ *r = v * scale->b; if (v != 0 && *r / v != scale->b) { *r = 0; return diag("binary too large: \"%s\" is more than %llu %s", t, ULLONG_MAX, prefix_B ? " Bytes" : ""); } return NULL; } libreswan-4.14/lib/libswan/ttodata.3.xml000066400000000000000000000257601457372064200202040ustar00rootroot00000000000000 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-4.14/lib/libswan/ttodata.c000066400000000000000000000456521457372064200174670ustar00rootroot00000000000000/* * 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 "ttodata.h" #include "hunk.h" /* for char_to_lower() */ #include "passert.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 err_t badch(void); /* 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 */ #define TTODATAV_IGNORE_BASE64_SPACES (1 << 1) /* ignore spaces in base64 encodings */ static const char *ttodatav(const char *src, size_t srclen, 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) */ lset_t flags /*XXX: always LEMPTY*/) { 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; bool skipSpace = false; 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_IGNORE_BASE64_SPACES) skipSpace = true; 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(); 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) */ { /* zero means apply strlen() */ if (srclen == 0) srclen = strlen(src); return ttodatav(src, srclen, base, dst, dstlen, lenp, LEMPTY); } const char *ttochunk(shunk_t src, int base, /* 0 means figure it out */ chunk_t *dst) { size_t size = 0; err_t err = ttodatav(src.ptr, src.len, base, NULL/*dst*/, 0/*dstlen*/, &size, LEMPTY); if (err != NULL) { return err; } passert(size > 0); /* see pdone variable above */ *dst = alloc_chunk(size, "ttochunk"); err = ttodatav(src.ptr, src.len, base, (char*)dst->ptr, dst->len, &size, LEMPTY); passert(err == NULL); passert(dst->len == size); return NULL; } /* * 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, char_tolower(*src)); if (p == NULL) return BADCH0; byte = (p - hex) << 4; src++; p = strchr(hex, *src); if (p == NULL) p = strchr(hex, char_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 * * Rewrite to return diag_t. */ static err_t badch(void) /* (const char *src, int errcode, char *errp, // might be NULL size_t errlen) */ { #if 1 return "unknown character in input"; #else 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 (char_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; #endif } #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), LEMPTY); 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_IGNORE_BASE64_SPACES), &status); if (xbase != 0) check(r, buf, n, ttodatav(r->ascii + 2, 0, xbase, buf, sizeof(buf), &n, NULL, 0, TTODATAV_IGNORE_BASE64_SPACES), &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_IGNORE_BASE64_SPACES), &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_IGNORE_BASE64_SPACES), &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-4.14/lib/libswan/ttodeltatime.c000066400000000000000000000027771457372064200205270ustar00rootroot00000000000000/* time conversion, for libreswan * * Copyright (C) 2022 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 "diag.h" #include "deltatime.h" #include "timescale.h" diag_t ttodeltatime(const char *t, deltatime_t *d, const struct timescale *default_scale) { *d = deltatime_zero; uintmax_t time; shunk_t cursor = shunk1(t); /* [] => TIME + [] */ err_t err = shunk_to_uintmax(cursor, &cursor, 10/*base*/, &time); if (err != NULL) { return diag("bad duration value \"%s\": %s", t, err); } /* [] */ const struct timescale *scale = ttotimescale(cursor, default_scale); if (scale == NULL) { return diag("unrecognized duration multiplier \""PRI_SHUNK"\"", pri_shunk(cursor)); } /* check convertint TIME to MS doesn't overflow */ if (UINTMAX_MAX / scale->ms < time) { return diag("duration too large: \"%s\" is more than %ju seconds", t, UINTMAX_MAX); } *d = deltatime_ms(time * scale->ms); return NULL; } libreswan-4.14/lib/libswan/ttoprotocol.c000066400000000000000000000032551457372064200204100ustar00rootroot00000000000000/* ttoprotocol(), for libreswan * * Copyright (C) 2021 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 getprotobyname() */ #include /* for IPPROTO_* */ #include "lswcdefs.h" /* for elemsof() */ #include "constants.h" /* for strncaseeq() */ #include "enum_names.h" #include "passert.h" #include "lswalloc.h" #include "ip_protocol.h" #include "ip_encap.h" #include "jambuf.h" err_t ttoprotocol(shunk_t text, const ip_protocol **proto) { /* look it up */ *proto = protocol_by_caseeat_prefix(&text); if (*proto != NULL) { return NULL; } /* failed, now try it by number in [0,255]*/ uintmax_t p; err_t err = shunk_to_uintmax(text, NULL, 0, &p); if (err == NULL) { /* possible success */ if (p > 255) { return "numeric protocol must be <= 255"; } *proto = protocol_by_ipproto(p); passert(*proto != NULL); return NULL; } /* act of desperation */ char *n = clone_hunk_as_string(text, "proto name"); const struct protoent *protocol = getprotobyname(n); pfree(n); if (protocol != NULL) { *proto = protocol_by_ipproto(protocol->p_proto); return NULL; } /* make something up */ return err; } libreswan-4.14/lib/libswan/ttosa.3.xml000066400000000000000000000256541457372064200177000ustar00rootroot00000000000000 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-4.14/lib/libswan/ttosaid.c000066400000000000000000000061621457372064200174670ustar00rootroot00000000000000/* * 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 #include "ip_said.h" #include "ip_info.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" }, { "%ignore", "int261@0.0.0.0" }, { "%trapsubnet", "int262@0.0.0.0" }, { NULL, NULL } }; /* * ttosaid - convert text "ah507@10.0.0.1" to SA identifier * * NULL for success, else string literal */ diag_t ttosaid(shunk_t src, ip_said *said) { *said = unset_said; err_t oops; if (src.len == 0) { return diag("empty string"); } # define MINLEN strlen("ah0@0"/*is as short as it can get */) if (src.len < MINLEN) { return diag("string too short to be SA identifier"); } /* * Try to turn %... into its equivalent. */ shunk_t input; if (hunk_char(src, 0) == '%') { struct magic *mp; for (mp = magic; mp->name != NULL; mp++) { if (hunk_streq(src, mp->name)) { break; } } if (mp->name == NULL) { return diag("keyword "PRI_SHUNK" unknown", pri_shunk(src)); } /* now parse the real string */ input = shunk1(mp->really); } else { input = src; } const struct ip_protocol *protocol = protocol_by_caseeat_prefix(&input); if (protocol == NULL) { return diag("SA specifier "PRI_SHUNK" lacks valid protocol prefix", pri_shunk(src)); } if (input.len == 0) { return diag("no SPI in SA specifier "PRI_SHUNK, pri_shunk(src)); } unsigned base; const struct ip_info *afi; if (shunk_strcaseeat(&input, ".")) { afi = &ipv4_info; base = 16; } else if (shunk_strcaseeat(&input, ":")) { afi = &ipv6_info; base = 16; } else { afi = NULL; /* not known yet */ base = 0; } if (input.len == 0) { return diag("no SPI following protocol in SA specifier "PRI_SHUNK, pri_shunk(src)); } uintmax_t hspi; shunk_t spis = input; oops = shunk_to_uintmax(input, &input, base, &hspi); if (oops != NULL) { return diag("SPI "PRI_SHUNK" invalid: %s", pri_shunk(spis), oops); } if (!shunk_strcaseeat(&input, "@")) { return diag("missing @ in SA specifier"); } ip_address dst; shunk_t dsts = input; oops = ttoaddress_num(input, afi, &dst); if (oops != NULL) { return diag("address "PRI_SHUNK" invalid: %s", pri_shunk(dsts), oops); } *said = said_from_address_protocol_spi(dst, protocol, htonl(hspi)); return NULL; } libreswan-4.14/lib/libswan/ttosubnet.c000066400000000000000000000073321457372064200200470ustar00rootroot00000000000000/* * 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 "ip_info.h" /* ipv6_info */ #include "lswlog.h" /* for dbg() */ #include "ip_protocol.h" #ifndef DEFAULTSUBNET #define DEFAULTSUBNET "%default" #endif /* * ttosubnet - convert text "addr/mask" to address and mask * Mask can be integer bit count. */ err_t ttosubnet(shunk_t src, const struct ip_info *afi, /* could be NULL */ int clash, /* '0' zero host-part bits, 'x' die on them, '6' die on IPv6 and warn on IPv4 */ ip_subnet *dst, struct logger *logger) { err_t oops; /* * Match %default, can't work when AFI=NULL. * * you cannot use af==AF_UNSPEC and src=0/0, * makes no sense as will it be AF_INET */ if (hunk_strcaseeq(src, DEFAULTSUBNET)) { if (afi == NULL) { return "unknown address family with " DEFAULTSUBNET " subnet not allowed."; } *dst = afi->subnet.all; /* 0.0.0.0/0 or ::/0 */ return NULL; } /* split the input into ADDR "/" MASK */ char slash; shunk_t addr = shunk_token(&src, &slash, "/"); shunk_t mask = src; if (slash == '\0') { /* consumed entire input */ return "no / in subnet specification"; } /* parse ADDR */ ip_address addrtmp; oops = ttoaddress_num(addr, afi, &addrtmp); if (oops != NULL) { return oops; } if (afi == NULL) { afi = address_type(&addrtmp); } if (afi == NULL) { /* XXX: pexpect()? */ return "unknown address family in ttosubnet"; } /* parse MASK */ uintmax_t prefix_bits; oops = shunk_to_uintmax(mask, NULL, 10, &prefix_bits); if (oops != NULL || prefix_bits > afi->mask_cnt) { if (afi == &ipv4_info) { ip_address masktmp; oops = ttoaddress_num(mask, afi, &masktmp); if (oops != NULL) { return oops; } int i = masktocount(&masktmp); if (i < 0) { return "non-contiguous or otherwise erroneous mask"; } prefix_bits = i; } else { return "masks are not permitted for IPv6 addresses"; } } bool die = false; bool warn = 0; switch (clash) { case '0': die = 0; break; case 'x': die = 1; break; case '6': if (afi == &ipv6_info) die = 1; warn = 1; break; default: return "unknown clash-control value in initsubnet"; } chunk_t addr_chunk = address_as_chunk(&addrtmp); unsigned n = addr_chunk.len; uint8_t *p = addr_chunk.ptr; /* cast void* */ if (n == 0) return "unknown address family"; unsigned c = prefix_bits / 8; if (c > n) return "impossible mask count"; p += c; n -= c; unsigned m = 0xff; c = prefix_bits % 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 = subnet_from_address_prefix_bits(addrtmp, prefix_bits); if (warning) { LLOG_JAMBUF(RC_LOG, logger, buf) { jam(buf, "WARNING:improper subnet mask, host-part bits on input "); jam_address(buf, &addrtmp); jam(buf, "/%ju ", prefix_bits); jam(buf, " extracted subnet "); jam_subnet(buf, dst); } } return NULL; } libreswan-4.14/lib/libswan/ttoul.3.xml000066400000000000000000000207361457372064200177110ustar00rootroot00000000000000 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-4.14/lib/libswan/ttoul.c000066400000000000000000000053451457372064200171710ustar00rootroot00000000000000/* * 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 "ttodata.h" /* * ttoul - convert text substring to unsigned long number * * NULL for success, else static string literal */ static err_t ttoul(const char *src, size_t srclen, 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) 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; } /* NULL for success, else string literal */ err_t ttoulb(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) { if (srclen == 0) srclen = strlen(src); const char *ugh = ttoul(src, srclen, base, resultp); return ugh != NULL ? ugh : *resultp > upb ? "too large" : NULL; } libreswan-4.14/lib/libswan/ultot.c000066400000000000000000000033761457372064200171730ustar00rootroot00000000000000/* * 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 "ttodata.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-4.14/lib/libswan/unbound.c000066400000000000000000000220071457372064200174660ustar00rootroot00000000000000/* * 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 /* deb:libevent-dev */ #include /* rpm:unbound-devel deb:libunbound-dev */ #include /* see USE_UNBOUND_EVENT_H_COPY */ #include "lswglob.h" #include "dnssec.h" #include "constants.h" #include "lswlog.h" #include "ip_info.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 void unbound_ctx_config(bool do_dnssec, const char *rootfile, const char *trusted, struct logger *logger) { int ugh; if (DBGP(DBG_BASE)) { 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) { llog(RC_LOG_SERIOUS, logger, "error reading hosts: %s: %s", ub_strerror(ugh), strerror(errno)); } else { dbg("/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 */ llog(RC_LOG_SERIOUS, logger, "error reading /etc/resolv.conf: %s: [errno: %s]", ub_strerror(ugh), strerror(e)); } else { dbg("/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) { llog(RC_LOG_SERIOUS, logger, "error setting outgoing-port-avoid: %s: %s", ub_strerror(ugh), strerror(errno)); } else { dbg("outgoing-port-avoid set 0-65535"); } errno = 0; ugh = ub_ctx_set_option(dns_ctx, "outgoing-port-permit:", "32768-60999"); if (ugh != 0) { llog(RC_LOG_SERIOUS, logger, "error setting outgoing-port-permit: %s: %s", ub_strerror(ugh), strerror(errno)); } else { dbg("outgoing-port-permit set 32768-60999"); } if (!do_dnssec) { /* No DNSSEC - nothing more to configure */ dbg("dnssec validation disabled by configuration"); return; } /* Only DNSSEC related configuration from here */ if (rootfile == NULL) { if (trusted == NULL) { llog(RC_LOG_SERIOUS, logger, "dnssec-enable=yes but no dnssec-rootkey-file or trust anchors specified."); llog(RC_LOG_SERIOUS, logger, "WARNING: DNSSEC validation disabled"); return; } else { llog(RC_LOG_SERIOUS, logger, "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 { dbg("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 */ llog(RC_LOG_SERIOUS, logger, "error adding dnssec root key: %s [errno: %s]", ub_strerror(ugh), strerror(e)); llog(RC_LOG_SERIOUS, logger, "WARNING: DNSSEC validation disabled"); } } if (trusted == NULL) { dbg("no additional dnssec trust anchors defined via dnssec-trusted= option"); } else { glob_t globbuf; int r = lswglob(trusted, &globbuf, "trusted anchor", logger); switch (r) { case 0: /* success */ for (char **fnp = globbuf.gl_pathv; fnp != NULL && *fnp != NULL; fnp++) { ugh = ub_ctx_add_ta_file(dns_ctx, *fnp); if (ugh != 0) { llog(RC_LOG_SERIOUS, logger, "Ignored trusted key file %s: %s", *fnp, ub_strerror(ugh)); } else { dbg("added contents of trusted key file %s to unbound resolver context", *fnp); } } break; case GLOB_NOSPACE: llog(RC_LOG_SERIOUS, logger, "out of space processing dnssec-trusted= argument: %s", trusted); break; case GLOB_ABORTED: /* already logged by globugh_ta */ break; case GLOB_NOMATCH: llog(RC_LOG_SERIOUS, logger, "no trust anchor files matched '%s'", trusted); break; default: llog(RC_LOG_SERIOUS, logger, "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 */ diag_t unbound_event_init(struct event_base *eb, bool do_dnssec, const char *rootfile, const char *trusted, struct logger *logger) { passert(dns_ctx == NULL); /* block re-entry to the function */ dns_ctx = ub_ctx_create_event(eb); if (dns_ctx == NULL) { return diag("failed to initialize unbound libevent ABI, please recompile libunbound with libevent support or recompile libreswan without USE_DNSSEC"); } unbound_ctx_config(do_dnssec, rootfile, trusted, logger); return NULL; } /* * 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, struct logger *logger) { 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, logger); } /* * synchronous blocking resolving - simple replacement of ttoaddress_dns() * src_len == 0 means "apply strlen" * af == AF_UNSPEC means default to AF_INET(A/IPv4) */ bool unbound_resolve(char *src, const struct ip_info *afi, ip_address *ipaddr, struct logger *logger) { /* 28 = AAAA record, 1 = A record */ const int qtype = (afi == &ipv6_info) ? 28/*AAAA*/ : 1/*A*/; passert(dns_ctx != NULL); if (strlen(src) == 0) { return diag("empty hostname in host lookup"); } struct ub_result *result; int ugh = ub_resolve(dns_ctx, src, qtype, 1 /* CLASS IN */, &result); if (ugh != 0) { llog(RC_LOG, logger, "unbound error: %s", ub_strerror(ugh)); ub_resolve_free(result); return false; } if (result->bogus) { llog_error(logger, 0/*no-errno*/, "%s failed DNSSEC validation", result->qname); ub_resolve_free(result); return false; } if (!result->havedata) { if (result->secure) { dbg("validated reply proves '%s' does not exist", src); } else { dbg("failed to resolve '%s' (%s)", src, result->bogus ? "BOGUS" : "insecure"); } ub_resolve_free(result); return false; } if (!result->secure) { dbg("warning: %s lookup was not protected by DNSSEC!", result->qname); } if (DBGP(DBG_TMI)) { 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); } /* XXX: for now pick the first one and return that */ passert(result->data != NULL); passert(result->data[0] != NULL); passert(result->len != NULL); if ((size_t)result->len[0] != afi->ip_size) { llog_pexpect(logger, HERE, "dns record is %u bytes, expecting %zu", result->len[0], afi->ip_size); ub_resolve_free(result); return false; } struct ip_bytes bytes = unset_ip_bytes; memcpy(bytes.byte, result->data[0], afi->ip_size); *ipaddr = address_from_raw(HERE, afi->ip_version, bytes); dbg("success for %s lookup", afi->ip_name); return true; } struct ub_ctx * get_unbound_ctx(void) { return dns_ctx; } libreswan-4.14/lib/libswan/v1_proposals.c000066400000000000000000000270741457372064200204550ustar00rootroot00000000000000/* 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->fqn))) { DBGF(DBG_PROPOSAL_PARSER, "skipping default %s", str_diag(parser->diag)); pfree_diag(&parser->diag); continue; } /* add it */ DBGF(DBG_PROPOSAL_PARSER, "adding default %s %s", ike_alg_type_name(type), alg->fqn); struct v1_proposal merged_proposal = merge_alg_default(*proposal, *default_alg); if (!add_proposal_defaults(parser, defaults, proposals, &merged_proposal)) { passert(parser->diag != NULL); 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.fqn); 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 bool parser_proposals_add(struct proposal_parser *parser, struct proposal_tokenizer *tokens, struct v1_proposal proposal, struct proposals *proposals) { 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->this.ptr != NULL && tokens->prev_term != ';') { const struct ike_alg *encrypt; int encrypt_keylen; if (!proposal_parse_encrypt(parser, tokens, &encrypt, &encrypt_keylen)) { if (impair.proposal_parser) { /* ignore the lookup and stumble on */ pfree_diag(&parser->diag); } else { passert(parser->diag != NULL); return false; } } proposal.encrypt = encrypt_desc(encrypt); proposal.enckeylen = encrypt_keylen; } 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->this; shunk_t integ = tokens->next; if (prf.ptr != NULL && integ.ptr != NULL) { lookup_prf = (alg_byname(parser, IKE_ALG_INTEG, integ, integ) != NULL); pfree_diag(&parser->diag); } } if (lookup_prf && tokens->this.ptr != NULL && tokens->prev_term != ';') { shunk_t prf = tokens[0].this; proposal.prf = prf_desc(alg_byname(parser, IKE_ALG_PRF, prf, prf)); if (parser->diag != NULL) { return false; } proposal_next_token(tokens); } /* * 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->this.ptr != NULL && tokens->prev_term != ';') { shunk_t integ = tokens[0].this; proposal.integ = integ_desc(alg_byname(parser, IKE_ALG_INTEG, integ, integ)); if (parser->diag != NULL) { if (tokens->next.ptr != NULL) { /* * This alg should have been * integrity, since the next would be * DH; error applies. */ passert(parser->diag != NULL); return false; } if (tokens->next.ptr == NULL && !parser->protocol->prf) { /* * Only one arg, integrity is preferred * to DH (and no PRF); error applies. */ passert(parser->diag != NULL); return false; } /* let DH try */ pfree_diag(&parser->diag); } else { proposal_next_token(tokens); } } bool lookup_dh = parser->protocol->dh || impair.proposal_parser; if (lookup_dh && tokens->this.ptr != NULL) { shunk_t dh = tokens[0].this; proposal.dh = dh_desc(alg_byname(parser, IKE_ALG_DH, dh, dh)); if (parser->diag != NULL) { return false; } proposal_next_token(tokens); } if (tokens->this.ptr != NULL) { proposal_error(parser, "%s proposals contain unexpected '"PRI_SHUNK"'", parser->protocol->name, pri_shunk(tokens[0].this)); 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) { DBGF(DBG_PROPOSAL_PARSER, "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, "%s proposal is empty", parser->protocol->name); return false; } shunk_t prop_ptr = alg_str; do { /* find the next proposal */ shunk_t prop = shunk_token(&prop_ptr, NULL, ","); /* parse it */ struct proposal_tokenizer tokens = proposal_first_token(prop, "-;"); struct v1_proposal proposal = { .protocol = parser->protocol, }; if (!parser_proposals_add(parser, &tokens, proposal, proposals)) { passert(parser->diag != NULL); return false; } } while (prop_ptr.ptr != NULL); return true; } libreswan-4.14/lib/libswan/v2_proposals.c000066400000000000000000000311451457372064200204500ustar00rootroot00000000000000/* 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) { passert(parser->diag != NULL); 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 ...? */ llog(RC_LOG, parser->policy->logger, "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) { passert(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->fqn); 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) { passert(parser->diag == NULL); if (token.len == 0) { proposal_error(parser, "%s %s algorithm is empty", parser->protocol->name, ike_alg_type_name(alg_type)); 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; } enum proposal_status { PROPOSAL_OK = 1, PROPOSAL_IGNORE, PROPOSAL_ERROR, }; static enum proposal_status parse_proposal(struct proposal_parser *parser, struct proposal *proposal, shunk_t input) { if (DBGP(DBG_PROPOSAL_PARSER)) { DBG_log("proposal: '"PRI_SHUNK"'", pri_shunk(input)); } struct proposal_tokenizer tokens = proposal_first_token(input, "-;+"); /* * 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" might be * invalid on some IPsec stacks. 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 */ const struct ike_alg *encrypt; int encrypt_keylen; if (!proposal_parse_encrypt(parser, &tokens, &encrypt, &encrypt_keylen)) { passert(parser->diag != NULL); return PROPOSAL_ERROR; } passert(parser->diag == NULL); append_algorithm(parser, proposal, encrypt, encrypt_keylen); /* further encryption algorithm tokens are optional */ while (tokens.prev_term == '+') { if (!proposal_parse_encrypt(parser, &tokens, &encrypt, &encrypt_keylen)) { passert(parser->diag != NULL); return PROPOSAL_ERROR; } passert(parser->diag == NULL); append_algorithm(parser, proposal, encrypt, encrypt_keylen); } /* deal with all encryption algorithm tokens being discarded */ if (next_algorithm(proposal, PROPOSAL_encrypt, NULL) == NULL) { if (parser->policy->ignore_parser_errors) { DBGF(DBG_PROPOSAL_PARSER, "all encryption algorithms skipped; stumbling on"); passert(parser->diag == NULL); return PROPOSAL_IGNORE; } if (!impair.proposal_parser) { llog_pexpect(parser->policy->logger, HERE, "all encryption algorithms skipped"); proposal_error(parser, "all encryption algorithms discarded"); passert(parser->diag != NULL); return PROPOSAL_ERROR; } } remove_duplicate_algorithms(parser, proposal, PROPOSAL_encrypt); } /* Error left in parser->diag */ #define PARSE_ALG(TOKENS, ALG) \ passert(parser->diag == NULL); /* so far so good */ \ DBGF(DBG_PROPOSAL_PARSER, "parsing "#ALG":"); \ if (parse_alg(parser, proposal, \ &ike_alg_##ALG, TOKENS.this)) { \ passert(parser->diag == NULL); \ proposal_next_token(&TOKENS); \ while (TOKENS.prev_term == '+' && \ parse_alg(parser, proposal, \ &ike_alg_##ALG, TOKENS.this)) { \ passert(parser->diag == NULL); \ proposal_next_token(&TOKENS); \ } \ remove_duplicate_algorithms(parser, proposal, PROPOSAL_##ALG); \ } /* * Try to parse: * * -... * * If it succeeds, assume the proposal is -- * and not ---. The merge code will * fill in with either NONE (AEAD) or the s * converted to integ. * * If it fails, code below will try --. * * This means, to specify integrity, the full integrity * algorithm name is needed. This means that * aes_gcm-none-sha1-dh21 is easy but anything else is a pain. * Hopefully this is ok as specifying integrity different to * the PRF isn't something to encourage. */ diag_t prf_diag = NULL; /* must free or transfer */ if (parser->protocol->prf && tokens.this.ptr != NULL /*more*/ && tokens.prev_term != ';' /*!DH*/) { /* not impaired */ struct proposal_tokenizer prf_tokens = tokens; PARSE_ALG(prf_tokens, prf); if (parser->diag == NULL) { /* advance */ DBGF(DBG_PROPOSAL_PARSER, "- succeeded, advancing tokens"); tokens = prf_tokens; remove_duplicate_algorithms(parser, proposal, PROPOSAL_prf); } else { /* toss the result, but save the error */ DBGF(DBG_PROPOSAL_PARSER, "- failed, saving error '%s' and tossing result", str_diag(parser->diag)); free_algorithms(proposal, PROPOSAL_prf); prf_diag = parser->diag; parser->diag = NULL; } } /* * Parse: * * -... (if above fails) * ... */ if ((parser->protocol->integ || impair.proposal_parser) && tokens.this.ptr != NULL /*more*/ && tokens.prev_term != ';' /*!DH*/ && /* - either failed or wasn't needed */ next_algorithm(proposal, PROPOSAL_prf, NULL) == NULL) { PARSE_ALG(tokens, integ); if (parser->diag != NULL) { if (prf_diag != NULL) { DBGF(DBG_PROPOSAL_PARSER, "- and - failed, returning earlier PRF error '%s' and discarding INTEG error '%s')", str_diag(prf_diag), str_diag(parser->diag)); pfree_diag(&parser->diag); parser->diag = prf_diag; return PROPOSAL_ERROR; } else { DBGF(DBG_PROPOSAL_PARSER, " or - failed '%s')", str_diag(parser->diag)); pexpect(prf_diag == NULL); pfree_diag(&prf_diag); return PROPOSAL_ERROR; } } remove_duplicate_algorithms(parser, proposal, PROPOSAL_integ); } pfree_diag(&prf_diag); /* when INTEG ok but PRF failed */ /* * Parse: * * --... * * But only when - didn't succeed. */ if ((parser->protocol->prf || impair.proposal_parser) && tokens.this.ptr != NULL /*more*/ && tokens.prev_term != ';' /*!DH*/ && /* above parsed integrity */ next_algorithm(proposal, PROPOSAL_prf, NULL) == NULL) { PARSE_ALG(tokens, prf); if (parser->diag != NULL) { DBGF(DBG_PROPOSAL_PARSER, "-- failed '%s'", str_diag(parser->diag)); return PROPOSAL_ERROR; } remove_duplicate_algorithms(parser, proposal, PROPOSAL_prf); } /* * Parse: * * ...; * -- (IKE) * --- (IKE) * -- (ESP) * - (AH) * * But only when - didn't succeed. */ if ((parser->protocol->dh || impair.proposal_parser) && tokens.this.ptr != NULL /*more*/) { PARSE_ALG(tokens, dh); if (parser->diag != NULL) { DBGF(DBG_PROPOSAL_PARSER, "... failed '%s'", str_diag(parser->diag)); return PROPOSAL_ERROR; } remove_duplicate_algorithms(parser, proposal, PROPOSAL_dh); } /* end of token stream? */ if (tokens.this.ptr != NULL) { proposal_error(parser, "%s proposal contains unexpected '"PRI_SHUNK"'", parser->protocol->name, pri_shunk(tokens.this)); passert(parser->diag != NULL); return PROPOSAL_ERROR; } if (!impair.proposal_parser && !merge_defaults(parser, proposal)) { passert(parser->diag != NULL); return PROPOSAL_ERROR; } /* back end? */ if (!parser->protocol->proposal_ok(parser, proposal)) { passert(parser->diag != NULL); return PROPOSAL_ERROR; } return PROPOSAL_OK; } bool v2_proposals_parse_str(struct proposal_parser *parser, struct proposals *proposals, shunk_t input) { DBGF(DBG_PROPOSAL_PARSER, "parsing '"PRI_SHUNK"' for %s", pri_shunk(input), parser->protocol->name); if (input.len == 0) { /* XXX: hack to keep testsuite happy */ proposal_error(parser, "%s proposal is empty", parser->protocol->name); return false; } do { /* find the next proposal */ shunk_t raw_proposal = shunk_token(&input, NULL, ","); struct proposal *proposal = alloc_proposal(parser); switch (parse_proposal(parser, proposal, raw_proposal)) { case PROPOSAL_ERROR: passert(parser->diag != NULL); free_proposal(&proposal); return false; case PROPOSAL_IGNORE: passert(parser->diag == NULL); free_proposal(&proposal); break; case PROPOSAL_OK: passert(parser->diag == NULL); append_proposal(proposals, &proposal); break; } } while (input.ptr != NULL); return true; } libreswan-4.14/lib/libswan/vendorid.c000066400000000000000000001017531457372064200176340ustar00rootroot00000000000000/* Libreswan ISAKMP VendorID Handling * * Copyright (C) 2002-2003 Mathieu Lafon - Arkoon Network Security * Copyright (C) 2004 Xelerance Corporation * Copyright (C) 2012-2019 Paul Wouters * Copyright (C) 2013 Wolfgang Nothdurft * Copyright (C) 2013-2019 D. Hugh Redelmeier * Copyright (C) 2019 Andrew Cagney * * See also https://github.com/royhills/ike-scan/blob/master/ike-vendor-ids * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT 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 NULL et.al. */ #include "lswversion.h" /* for libreswan_vendorid */ #include "crypt_hash.h" #include "ike_alg_hash.h" #include "vendorid.h" #include "lswlog.h" /** * Listing of interesting but details unknown Vendor IDs: * * SafeNet SoftRemote 8.0.0: * 47bbe7c993f1fc13b4e6d0db565c68e5010201010201010310382e302e3020284275696c6420313029000000 * >> 382e302e3020284275696c6420313029 = '8.0.0 (Build 10)' * da8e937880010000 * * SafeNet SoftRemote 9.0.1 * 47bbe7c993f1fc13b4e6d0db565c68e5010201010201010310392e302e3120284275696c6420313229000000 * >> 392e302e3120284275696c6420313229 = '9.0.1 (Build 12)' * da8e937880010000 * * Netscreen: * d6b45f82f24bacb288af59a978830ab7 * cf49908791073fb46439790fdeb6aeed981101ab0000000500000300 * * Cisco: * 1f07f70eaa6514d3b0fa96542a500100 (Cisco VPN Concentrator) * 1f07f70eaa6514d3b0fa96542a500300 (VPN 3000 version 3.0.0) * 1f07f70eaa6514d3b0fa96542a500301 (VPN 3000 version 3.0.1) * 1f07f70eaa6514d3b0fa96542a500305 (VPN 3000 version 3.0.5) * 1f07f70eaa6514d3b0fa96542a500407 (VPN 3000 version 4.0.7) * (Can you see the pattern?) * afcad71368a1f1c96b8696fc77570100 (Non-RFC Dead Peer Detection ?) * c32364b3b4f447eb17c488ab2a480a57 * 6d761ddc26aceca1b0ed11fabbb860c4 * 5946c258f99a1a57b03eb9d1759e0f24 (From a Cisco VPN 3k) * ebbc5b00141d0c895e11bd395902d690 (From a Cisco VPN 3k) * 3e984048101e66cc659fd002b0ed3655 (From a Cisco 1800 IOS device) * ade1e70e9953c1328373ebf0257b85ed (From a Cisco PIX) * * Microsoft L2TP (???): * (This could be the MSL2TP client, which is a stripped version of SafeNet) * * 47bbe7c993f1fc13b4e6d0db565c68e5010201010201010310382e312e3020284275696c6420313029000000 * >> 382e312e3020284275696c6420313029 = '8.1.0 (Build 10)' * 3025dbd21062b9e53dc441c6aab5293600000000 * da8e937880010000 * * 3COM-superstack * da8e937880010000 * 404bf439522ca3f6 * * Nortel contivity 251 (RAS F/W Version: VA251_2.0.0.0.013 | 12/3/2003 * DSL FW Version: Alcatel, Version 3.9.122) * 4485152d18b6bbcd0be8a8469579ddcc * 625027749d5ab97f5616c1602765cf480a3b7d0b) * 424e455300000009 (Nortel Contivity) * * Zyxel Zywall 2 / Zywall 30w * 625027749d5ab97f5616c1602765cf480a3b7d0b * * Astaro ? * 7f50cc4ebf04c2d9da73abfd69b77aa2 * * Solaris 10 has RF 3974 but also md5('RFC XXXX') whih is 810fa565f8ab14369105d706fbd57279 * (yes, the 'XXXX' are _really_ four times the letter X) * * Juniper, unknown vid: * 699369228741c6d4ca094c93e242c9de19e7b7c60000000500000500 * 166f932d55eb64d8e4df4fd37e2313f0d0fd8451000000000000 * * KAME / Apple / Mac OSX? * While searching (strings) in /usr/sbin/racoon on Mac OS X 10.3.3, I found it : * # echo -n "draft-ietf-ipsec-nat-t-ike" | md5sum * 4df37928e9fc4fd1b3262170d515c662 * But this VID has not been seen in any IETF drafts. (mlafon) */ #define MAX_LOG_VID_LEN 32 #define VID_KEEP 0x0000 #define VID_MD5HASH 0x0001 #define VID_STRING 0x0002 #define VID_FSWAN_HASH 0x0004 #define VID_SUBSTRING_DUMPHEXA 0x0100 #define VID_SUBSTRING_DUMPASCII 0x0200 #define VID_SUBSTRING_MATCH 0x0400 #define VID_SUBSTRING (VID_SUBSTRING_DUMPHEXA | VID_SUBSTRING_DUMPASCII | \ VID_SUBSTRING_MATCH) struct vid_struct { const enum known_vendorid id; const unsigned short flags; const char *const data; /* filled in at runtime: */ const char *descr; shunk_t vid; }; #define DEC_MD5_VID_D(ID, STR, DESCR) \ VID(ID, VID_MD5HASH, STR, DESCR) #define DEC_MD5_VID(ID, STR) \ VID(ID, VID_MD5HASH, STR, NULL) #define DEC_FSWAN_VID(ID, STR, DESCR) \ VID(ID, VID_FSWAN_HASH, STR, DESCR) #define VID(ID, FLAGS, DATA, DESCR) \ [ID] = { .id = ID, .flags = FLAGS, .data = DATA, .descr = DESCR, } #define RAW(ID, FLAGS, DESCR, RAW_VID) \ [ID] = { \ .id = ID, \ .flags = FLAGS, \ .descr = DESCR, \ .vid = { \ .ptr = RAW_VID, \ .len = sizeof(RAW_VID) - 1 /*don't count NUL*/, \ }, \ } static struct vid_struct vid_tab[] = { /* Implementation names */ VID(VID_OPPORTUNISTIC, VID_STRING, "Opportunistic IPsec", NULL), VID(VID_OPENPGP, VID_STRING, "OpenPGP10171", "OpenPGP"), DEC_MD5_VID(VID_KAME_RACOON, "KAME/racoon"), /* * https://msdn.microsoft.com/en-us/library/cc233476.aspx * The first few are "MS NT5 ISAKMPOAKLEY" with a version number appended */ RAW(VID_MS_WIN2K, VID_KEEP, "Windows 2000", "\x1E\x2B\x51\x69\x05\x99\x1C\x7D\x7C\x96\xFC\xBF\xB5\x87\xE4\x61\x00\x00\x00\x02"), RAW(VID_MS_WINXP, VID_KEEP, "Windows XP", "\x1E\x2B\x51\x69\x05\x99\x1C\x7D\x7C\x96\xFC\xBF\xB5\x87\xE4\x61\x00\x00\x00\x03"), RAW(VID_MS_WIN2003, VID_KEEP, "Windows Server 2003", "\x1E\x2B\x51\x69\x05\x99\x1C\x7D\x7C\x96\xFC\xBF\xB5\x87\xE4\x61\x00\x00\x00\x04"), RAW(VID_MS_WINVISTA, VID_KEEP, "Windows Vista", "\x1E\x2B\x51\x69\x05\x99\x1C\x7D\x7C\x96\xFC\xBF\xB5\x87\xE4\x61\x00\x00\x00\x05"), RAW(VID_MS_WIN2008, VID_KEEP, "Windows Server 2008", "\x1E\x2B\x51\x69\x05\x99\x1C\x7D\x7C\x96\xFC\xBF\xB5\x87\xE4\x61\x00\x00\x00\x06"), RAW(VID_MS_WIN7, VID_KEEP, "Windows 7", "\x1E\x2B\x51\x69\x05\x99\x1C\x7D\x7C\x96\xFC\xBF\xB5\x87\xE4\x61\x00\x00\x00\x07"), RAW(VID_MS_WIN2008R2, VID_KEEP, "Windows Server 2008 R2", "\x1E\x2B\x51\x69\x05\x99\x1C\x7D\x7C\x96\xFC\xBF\xB5\x87\xE4\x61\x00\x00\x00\x08"), RAW(VID_MS_WINKSINK09, VID_KEEP, "Windows 8, 8.1, 10, Server 2012 R2, Server 2016", "\x1E\x2B\x51\x69\x05\x99\x1C\x7D\x7C\x96\xFC\xBF\xB5\x87\xE4\x61\x00\x00\x00\x09"), RAW(VID_MS_WINKEYMODS_IKE, VID_KEEP, "Windows KEY_MODS (IKE)", "\x01\x52\x8b\xbb\xc0\x06\x96\x12\x18\x49\xab\x9a\x1c\x5b\x2a\x51\x00\x00\x00\x00"), RAW(VID_MS_WINKEYMODS_AUTHIP, VID_KEEP, "Windows KEY_MODS (AUTHIP)", "\x01\x52\x8b\xbb\xc0\x06\x96\x12\x18\x49\xab\x9a\x1c\x5b\x2a\x51\x00\x00\x00\x01"), RAW(VID_MS_WINKEYMODS_IKEv2, VID_KEEP, "Windows KEY_MODS (IKEv2)", "\x01\x52\x8b\xbb\xc0\x06\x96\x12\x18\x49\xab\x9a\x1c\x5b\x2a\x51\x00\x00\x00\x02"), RAW(VID_MS_AUTHIP_KE_DH_NONE, VID_KEEP, "AUTHIP INIT KE DH NONE", "\x7B\xB9\x38\x67\xD7\x6C\x8D\x80\xDF\x0F\x40\xFA\xE8\xFC\x3B\x19\x00\x00\x00\x00"), RAW(VID_MS_AUTHIP_KE_DH1, VID_KEEP, "AUTHIP INIT KE DH1", "\x7B\xB9\x38\x67\xD7\x6C\x8D\x80\xDF\x0F\x40\xFA\xE8\xFC\x3B\x19\x00\x00\x00\x01"), RAW(VID_MS_AUTHIP_KE_DH2, VID_KEEP, "AUTHIP INIT KE DH2", "\x7B\xB9\x38\x67\xD7\x6C\x8D\x80\xDF\x0F\x40\xFA\xE8\xFC\x3B\x19\x00\x00\x00\x02"), RAW(VID_MS_AUTHIP_KE_DH14, VID_KEEP, "AUTHIP INIT KE DH14", "\x7B\xB9\x38\x67\xD7\x6C\x8D\x80\xDF\x0F\x40\xFA\xE8\xFC\x3B\x19\x00\x00\x00\x03"), RAW(VID_MS_AUTHIP_KE_DH19, VID_KEEP, "AUTHIP INIT KE DH19(ECP 256)", "\x7B\xB9\x38\x67\xD7\x6C\x8D\x80\xDF\x0F\x40\xFA\xE8\xFC\x3B\x19\x00\x00\x00\x04"), RAW(VID_MS_AUTHIP_KE_DH20, VID_KEEP, "AUTHIP INIT KE DH20(ECP 384)", "\x7B\xB9\x38\x67\xD7\x6C\x8D\x80\xDF\x0F\x40\xFA\xE8\xFC\x3B\x19\x00\x00\x00\x05"), RAW(VID_MS_AUTHIP_KE_DH21, VID_KEEP, "AUTHIP INIT KE DH21(ECP 521)", "\x7B\xB9\x38\x67\xD7\x6C\x8D\x80\xDF\x0F\x40\xFA\xE8\xFC\x3B\x19\x00\x00\x00\x06"), RAW(VID_MS_AUTHIP_KE_DHMAX, VID_KEEP, "AUTHIP INIT KE DH MAX", "\x7B\xB9\x38\x67\xD7\x6C\x8D\x80\xDF\x0F\x40\xFA\xE8\xFC\x3B\x19\x00\x00\x00\x07"), RAW(VID_MS_NLBS_PRESENT, VID_KEEP, "NLB/MSCS fast failover supported", "\x72\x87\x2B\x95\xFC\xDA\x2E\xB7\x08\xEF\xE3\x22\x11\x9B\x49\x71"), RAW(VID_MS_AUTHIP_SUPPORTED, VID_KEEP, "AuthIP supported", "\x21\x4C\xA4\xFA\xFF\xA7\xF3\x2D\x67\x48\xE5\x30\x33\x95\xAE\x83"), RAW(VID_MS_CGA_SUPPORTED, VID_KEEP, "CGA supported", "\xE3\xA5\x96\x6A\x76\x37\x9F\xE7\x07\x22\x82\x31\xE5\xCE\x86\x52"), RAW(VID_MS_NEGOTIATION_DISCOVERY_SUPPORTED, VID_KEEP, "Negotiation discovery supported", "\xFB\x1D\xE3\xCD\xF3\x41\xB7\xEA\x16\xB7\xE5\xBE\x08\x55\xF1\x20"), RAW(VID_MS_XBOX_ONE_2013, VID_KEEP, "Microsoft Xbox One 2013", "\x8A\xA3\x94\xCF\x8A\x55\x77\xDC\x31\x10\xC1\x13\xB0\x27\xA4\xF2"), RAW(VID_MS_XBOX_IKEv2, VID_KEEP, "Xbox IKEv2 Negotiation", "\x66\x08\x22\xB3\xA7\x3A\x24\x41\x49\x57\x8D\x62\xE0\xEB\x46\xA0"), RAW(VID_MS_SEC_REALM_ID, VID_KEEP, "MSFT IPsec Security Realm Id", "\x68\x6A\x8C\xBD\xFE\x63\x4B\x40\x51\x46\xFB\x2B\xAF\x33\xE9\xE8"), /* These two VID's plus VID_MS_NT5 trigger GSS-API support on Windows */ DEC_MD5_VID(VID_GSSAPILONG, "A GSS-API Authentication Method for IKE"), DEC_MD5_VID(VID_GSSAPI, "GSSAPI"), DEC_MD5_VID(VID_SSH_SENTINEL, "SSH Sentinel"), DEC_MD5_VID(VID_SSH_SENTINEL_1_1, "SSH Sentinel 1.1"), DEC_MD5_VID(VID_SSH_SENTINEL_1_2, "SSH Sentinel 1.2"), DEC_MD5_VID(VID_SSH_SENTINEL_1_3, "SSH Sentinel 1.3"), DEC_MD5_VID(VID_SSH_SENTINEL_1_4, "SSH Sentinel 1.4"), DEC_MD5_VID(VID_SSH_SENTINEL_1_4_1, "SSH Sentinel 1.4.1"), /* These ones come from SSH vendors.txt */ DEC_MD5_VID(VID_SSH_IPSEC_1_1_0, "Ssh Communications Security IPSEC Express version 1.1.0"), DEC_MD5_VID(VID_SSH_IPSEC_1_1_1, "Ssh Communications Security IPSEC Express version 1.1.1"), DEC_MD5_VID(VID_SSH_IPSEC_1_1_2, "Ssh Communications Security IPSEC Express version 1.1.2"), DEC_MD5_VID(VID_SSH_IPSEC_1_2_1, "Ssh Communications Security IPSEC Express version 1.2.1"), DEC_MD5_VID(VID_SSH_IPSEC_1_2_2, "Ssh Communications Security IPSEC Express version 1.2.2"), DEC_MD5_VID(VID_SSH_IPSEC_2_0_0, "SSH Communications Security IPSEC Express version 2.0.0"), DEC_MD5_VID(VID_SSH_IPSEC_2_1_0, "SSH Communications Security IPSEC Express version 2.1.0"), DEC_MD5_VID(VID_SSH_IPSEC_2_1_1, "SSH Communications Security IPSEC Express version 2.1.1"), DEC_MD5_VID(VID_SSH_IPSEC_2_1_2, "SSH Communications Security IPSEC Express version 2.1.2"), DEC_MD5_VID(VID_SSH_IPSEC_3_0_0, "SSH Communications Security IPSEC Express version 3.0.0"), DEC_MD5_VID(VID_SSH_IPSEC_3_0_1, "SSH Communications Security IPSEC Express version 3.0.1"), DEC_MD5_VID(VID_SSH_IPSEC_4_0_0, "SSH Communications Security IPSEC Express version 4.0.0"), DEC_MD5_VID(VID_SSH_IPSEC_4_0_1, "SSH Communications Security IPSEC Express version 4.0.1"), DEC_MD5_VID(VID_SSH_IPSEC_4_1_0, "SSH Communications Security IPSEC Express version 4.1.0"), DEC_MD5_VID(VID_SSH_IPSEC_4_2_0, "SSH Communications Security IPSEC Express version 4.2.0"), /* The VPN 3000 concentrator VID is a truncated MD5 hash of "ALTIGA GATEWAY" */ /* Last two bytes are version number, eg 0306 = 3.0.6 */ RAW(VID_CISCO3K, VID_SUBSTRING_MATCH, "Cisco VPN 3000 Series", "\x1f\x07\xf7\x0e\xaa\x65\x14\xd3\xb0\xfa\x96\x54\x2a\x50"), RAW(VID_CISCO_IOS, VID_SUBSTRING_MATCH, "Cisco IOS Device", "\x3e\x98\x40\x48"), /* note: md5('CISCO-UNITY') = 12f5f28c457168a9702d9fe274cc02d4 */ /* last two bytes replaced with 01 00 */ RAW(VID_CISCO_UNITY, VID_KEEP, "Cisco-Unity", "\x12\xf5\xf2\x8c\x45\x71\x68\xa9\x70\x2d\x9f\xe2\x74\xcc\x01\x00"), /* 434953434f56504e2d5245562d3032 */ VID(VID_CISCO_VPN_REV_02, VID_STRING, "CISCOVPN-REV-02", NULL), RAW(VID_CISCO_UNITY_FWTYPE, VID_KEEP, "Cisco-Unity FW type", "\x80\x01\x00\x01\x80\x02\x00\x01\x80\x03\x00\x02"), /* 434953434f2d44454c4554452d524541534f4e */ VID(VID_CISCO_DELETE_REASON, VID_STRING, "CISCO-DELETE-REASON", NULL), /* 434953434f2d44594e414d49432d524f555445 */ VID(VID_CISCO_DYNAMIC_ROUTE, VID_STRING, "CISCO-DYNAMIC-ROUTE", NULL), /* 464c455856504e2d535550504f52544544 */ VID(VID_CISCO_FLEXVPN_SUPPORTED, VID_STRING, "FLEXVPN-SUPPORTED", NULL), /* * Timestep VID seen: * - 54494d455354455020312053475720313532302033313520322e303145303133 * = 'TIMESTEP 1 SGW 1520 315 2.01E013' */ VID(VID_TIMESTEP, VID_STRING | VID_SUBSTRING_DUMPASCII, "TIMESTEP", NULL), DEC_FSWAN_VID(VID_FSWAN_2_00_VID, "Linux FreeS/WAN 2.00 PLUTO_SENDS_VENDORID", "FreeS/WAN 2.00"), DEC_FSWAN_VID(VID_FSWAN_2_00_X509_1_3_1_VID, "Linux FreeS/WAN 2.00 X.509-1.3.1 PLUTO_SENDS_VENDORID", "FreeS/WAN 2.00 (X.509-1.3.1)"), DEC_FSWAN_VID(VID_FSWAN_2_00_X509_1_3_1_LDAP_VID, "Linux FreeS/WAN 2.00 X.509-1.3.1 LDAP PLUTO_SENDS_VENDORID", "FreeS/WAN 2.00 (X.509-1.3.1 + LDAP)"), DEC_FSWAN_VID(VID_OPENSWAN2, "Openswan 2.2.0", "Openswan 2.2.0"), /* always make sure to include ourself! */ VID(VID_LIBRESWANSELF, VID_STRING, libreswan_vendorid, "Libreswan (this version)"), /* NAT-Traversal */ DEC_MD5_VID(VID_NATT_STENBERG_01, "draft-stenberg-ipsec-nat-traversal-01"), DEC_MD5_VID(VID_NATT_STENBERG_02, "draft-stenberg-ipsec-nat-traversal-02"), DEC_MD5_VID(VID_NATT_HUTTUNEN, "ESPThruNAT"), DEC_MD5_VID(VID_NATT_HUTTUNEN_ESPINUDP, "draft-huttunen-ipsec-esp-in-udp-00.txt"), DEC_MD5_VID(VID_NATT_IETF_00, "draft-ietf-ipsec-nat-t-ike-00"), DEC_MD5_VID(VID_NATT_IETF_01, "draft-ietf-ipsec-nat-t-ike-01"), DEC_MD5_VID(VID_NATT_IETF_02, "draft-ietf-ipsec-nat-t-ike-02"), /* hash in draft-ietf-ipsec-nat-t-ike-02 contains '\n'... Accept both */ DEC_MD5_VID_D(VID_NATT_IETF_02_N, "draft-ietf-ipsec-nat-t-ike-02\n", "draft-ietf-ipsec-nat-t-ike-02_n"), DEC_MD5_VID(VID_NATT_IETF_03, "draft-ietf-ipsec-nat-t-ike-03"), DEC_MD5_VID(VID_NATT_IETF_04, "draft-ietf-ipsec-nat-t-ike-04"), DEC_MD5_VID(VID_NATT_IETF_05, "draft-ietf-ipsec-nat-t-ike-05"), DEC_MD5_VID(VID_NATT_IETF_06, "draft-ietf-ipsec-nat-t-ike-06"), DEC_MD5_VID(VID_NATT_IETF_07, "draft-ietf-ipsec-nat-t-ike-07"), DEC_MD5_VID(VID_NATT_IETF_08, "draft-ietf-ipsec-nat-t-ike-08"), DEC_MD5_VID(VID_NATT_DRAFT_IETF_IPSEC_NAT_T_IKE, "draft-ietf-ipsec-nat-t-ike"), DEC_MD5_VID(VID_NATT_RFC, "RFC 3947"), /* SonicWall */ RAW(VID_SONICWALL_1, VID_KEEP, "Sonicwall 1 (TZ 170 Standard?)", "\x40\x4b\xf4\x39\x52\x2c\xa3\xf6"), /* apparently also Watchguard FireBoxs */ RAW(VID_SONICWALL_2, VID_KEEP, "Sonicwall 2 (3.1.0.12-86s?)", "\xda\x8e\x93\x78\x80\x01\x00\x00"), /* MD5("draft-ietf-ipsra-isakmp-xauth-06.txt") */ RAW(VID_MISC_XAUTH, VID_KEEP, "XAUTH", "\x09\x00\x26\x89\xdf\xd6\xb7\x12"), RAW(VID_MISC_DPD, VID_KEEP, "Dead Peer Detection", "\xaf\xca\xd7\x13\x68\xa1\xf1\xc9\x6b\x86\x96\xfc\x77\x57\x01\x00"), /* From Shrew Soft source code */ RAW(VID_DPD1_NG, VID_KEEP, "DPDv1_NG", "\x3b\x90\x31\xdc\xe4\xfc\xf8\x8b\x48\x9a\x92\x39\x63\xdd\x0c\x49"), /* Obsolete: Was used by libreswan and openswan to detect bid-down attacks */ VID(VID_MISC_IKEv2, VID_STRING, "IKEv2", "CAN-IKEv2(obsolete)"), /* VID is ASCII "HeartBeat_Notify" plus a few bytes (version?) */ VID(VID_MISC_HEARTBEAT_NOTIFY, VID_STRING | VID_SUBSTRING_DUMPHEXA, "HeartBeat_Notify", "HeartBeat Notify"), /* FRAGMENTATION; Cisco VPN 3000 and strongSwan send extra values */ RAW(VID_IKE_FRAGMENTATION, VID_SUBSTRING_DUMPHEXA, "FRAGMENTATION", "\x40\x48\xb7\xd5\x6e\xbc\xe8\x85\x25\xe7\xde\x7f\x00\xd6\xc2\xd3"), DEC_MD5_VID(VID_INITIAL_CONTACT, "Vid-Initial-Contact"), /* * strongSwan */ DEC_MD5_VID(VID_STRONGSWAN, "strongSwan"), DEC_MD5_VID(VID_STRONGSWAN_4_0_0, "strongSwan 4.0.0"), DEC_MD5_VID(VID_STRONGSWAN_4_0_1, "strongSwan 4.0.1"), DEC_MD5_VID(VID_STRONGSWAN_4_0_2, "strongSwan 4.0.2"), DEC_MD5_VID(VID_STRONGSWAN_4_0_3, "strongSwan 4.0.3"), DEC_MD5_VID(VID_STRONGSWAN_4_0_4, "strongSwan 4.0.4"), DEC_MD5_VID(VID_STRONGSWAN_4_0_5, "strongSwan 4.0.5"), DEC_MD5_VID(VID_STRONGSWAN_4_0_6, "strongSwan 4.0.6"), DEC_MD5_VID(VID_STRONGSWAN_4_0_7, "strongSwan 4.0.7"), DEC_MD5_VID(VID_STRONGSWAN_4_1_0, "strongSwan 4.1.0"), DEC_MD5_VID(VID_STRONGSWAN_4_1_1, "strongSwan 4.1.1"), DEC_MD5_VID(VID_STRONGSWAN_4_1_2, "strongSwan 4.1.2"), DEC_MD5_VID(VID_STRONGSWAN_4_1_3, "strongSwan 4.1.3"), DEC_MD5_VID(VID_STRONGSWAN_4_1_4, "strongSwan 4.1.4"), DEC_MD5_VID(VID_STRONGSWAN_4_1_5, "strongSwan 4.1.5"), DEC_MD5_VID(VID_STRONGSWAN_4_1_6, "strongSwan 4.1.6"), DEC_MD5_VID(VID_STRONGSWAN_4_1_7, "strongSwan 4.1.7"), DEC_MD5_VID(VID_STRONGSWAN_4_1_8, "strongSwan 4.1.8"), DEC_MD5_VID(VID_STRONGSWAN_4_1_9, "strongSwan 4.1.9"), DEC_MD5_VID(VID_STRONGSWAN_4_1_10, "strongSwan 4.1.10"), DEC_MD5_VID(VID_STRONGSWAN_4_1_11, "strongSwan 4.1.11"), DEC_MD5_VID(VID_STRONGSWAN_4_2_0, "strongSwan 4.2.0"), DEC_MD5_VID(VID_STRONGSWAN_4_2_1, "strongSwan 4.2.1"), DEC_MD5_VID(VID_STRONGSWAN_4_2_2, "strongSwan 4.2.2"), DEC_MD5_VID(VID_STRONGSWAN_4_2_3, "strongSwan 4.2.3"), DEC_MD5_VID(VID_STRONGSWAN_2_8_8, "strongSwan 2.8.8"), DEC_MD5_VID(VID_STRONGSWAN_2_8_7, "strongSwan 2.8.7"), DEC_MD5_VID(VID_STRONGSWAN_2_8_6, "strongSwan 2.8.6"), DEC_MD5_VID(VID_STRONGSWAN_2_8_5, "strongSwan 2.8.5"), DEC_MD5_VID(VID_STRONGSWAN_2_8_4, "strongSwan 2.8.4"), DEC_MD5_VID(VID_STRONGSWAN_2_8_3, "strongSwan 2.8.3"), DEC_MD5_VID(VID_STRONGSWAN_2_8_2, "strongSwan 2.8.2"), DEC_MD5_VID(VID_STRONGSWAN_2_8_1, "strongSwan 2.8.1"), DEC_MD5_VID(VID_STRONGSWAN_2_8_0, "strongSwan 2.8.0"), DEC_MD5_VID(VID_STRONGSWAN_2_7_3, "strongSwan 2.7.3"), DEC_MD5_VID(VID_STRONGSWAN_2_7_2, "strongSwan 2.7.2"), DEC_MD5_VID(VID_STRONGSWAN_2_7_1, "strongSwan 2.7.1"), DEC_MD5_VID(VID_STRONGSWAN_2_7_0, "strongSwan 2.7.0"), DEC_MD5_VID(VID_STRONGSWAN_2_6_4, "strongSwan 2.6.4"), DEC_MD5_VID(VID_STRONGSWAN_2_6_3, "strongSwan 2.6.3"), DEC_MD5_VID(VID_STRONGSWAN_2_6_2, "strongSwan 2.6.2"), DEC_MD5_VID(VID_STRONGSWAN_2_6_1, "strongSwan 2.6.1"), DEC_MD5_VID(VID_STRONGSWAN_2_6_0, "strongSwan 2.6.0"), DEC_MD5_VID(VID_STRONGSWAN_2_5_7, "strongSwan 2.5.7"), DEC_MD5_VID(VID_STRONGSWAN_2_5_6, "strongSwan 2.5.6"), DEC_MD5_VID(VID_STRONGSWAN_2_5_5, "strongSwan 2.5.5"), DEC_MD5_VID(VID_STRONGSWAN_2_5_4, "strongSwan 2.5.4"), DEC_MD5_VID(VID_STRONGSWAN_2_5_3, "strongSwan 2.5.3"), DEC_MD5_VID(VID_STRONGSWAN_2_5_2, "strongSwan 2.5.2"), DEC_MD5_VID(VID_STRONGSWAN_2_5_1, "strongSwan 2.5.1"), DEC_MD5_VID(VID_STRONGSWAN_2_5_0, "strongSwan 2.5.0"), DEC_MD5_VID(VID_STRONGSWAN_2_4_4, "strongSwan 2.4.4"), DEC_MD5_VID(VID_STRONGSWAN_2_4_3, "strongSwan 2.4.3"), DEC_MD5_VID(VID_STRONGSWAN_2_4_2, "strongSwan 2.4.2"), DEC_MD5_VID(VID_STRONGSWAN_2_4_1, "strongSwan 2.4.1"), DEC_MD5_VID(VID_STRONGSWAN_2_4_0, "strongSwan 2.4.0"), DEC_MD5_VID(VID_STRONGSWAN_2_3_2, "strongSwan 2.3.2"), DEC_MD5_VID(VID_STRONGSWAN_2_3_1, "strongSwan 2.3.1"), DEC_MD5_VID(VID_STRONGSWAN_2_3_0, "strongSwan 2.3.0"), DEC_MD5_VID(VID_STRONGSWAN_2_2_2, "strongSwan 2.2.2"), DEC_MD5_VID(VID_STRONGSWAN_2_2_1, "strongSwan 2.2.1"), DEC_MD5_VID(VID_STRONGSWAN_2_2_0, "strongSwan 2.2.0"), /* * NCP.de * Also seen from ncp client: * eb4c1b788afd4a9cb7730a68d56d088b * c61baca1f1a60cc10800000000000000 * cbe79444a0870de4224a2c151fbfe099 */ RAW(VID_NCP, VID_KEEP, "NCP client", "\x10\x1f\xb0\xb3\x5c\x5a\x4f\x4c\x08\xb9\x19\xf1\xcb\x97\x77\xb0"), RAW(VID_SHREWSOFT, VID_KEEP, "Shrew Soft client", "\xf1\x4b\x94\xb7\xbf\xf1\xfe\xf0\x27\x73\xb8\xc4\x9f\xed\xed\x26"), RAW(VID_NETSCREEN_01, VID_KEEP, "Netscreen-01", "\x29\x9e\xe8\x28\x9f\x40\xa8\x97\x3b\xc7\x86\x87\xe2\xe7\x22\x6b\x53\x2c\x3b\x76"), RAW(VID_NETSCREEN_02, VID_KEEP, "Netscreen-02", "\x3a\x15\xe1\xf3\xcf\x2a\x63\x58\x2e\x3a\xc8\x2d\x1c\x64\xcb\xe3\xb6\xd7\x79\xe7"), RAW(VID_NETSCREEN_03, VID_KEEP, "Netscreen-03", "\x47\xd2\xb1\x26\xbf\xcd\x83\x48\x97\x60\xe2\xcf\x8c\x5d\x4d\x5a\x03\x49\x7c\x15"), RAW(VID_NETSCREEN_04, VID_KEEP, "Netscreen-04", "\x4a\x43\x40\xb5\x43\xe0\x2b\x84\xc8\x8a\x8b\x96\xa8\xaf\x9e\xbe\x77\xd9\xac\xcc"), RAW(VID_NETSCREEN_05, VID_KEEP, "Netscreen-05", "\x64\x40\x5f\x46\xf0\x3b\x76\x60\xa2\x3b\xe1\x16\xa1\x97\x50\x58\xe6\x9e\x83\x87"), RAW(VID_NETSCREEN_06, VID_KEEP, "Netscreen-06", "\x69\x93\x69\x22\x87\x41\xc6\xd4\xca\x09\x4c\x93\xe2\x42\xc9\xde\x19\xe7\xb7\xc6"), RAW(VID_NETSCREEN_07, VID_KEEP, "Netscreen-07", "\x8c\x0d\xc6\xcf\x62\xa0\xef\x1b\x5c\x6e\xab\xd1\xb6\x7b\xa6\x98\x66\xad\xf1\x6a"), RAW(VID_NETSCREEN_08, VID_KEEP, "Netscreen-08", "\x92\xd2\x7a\x9e\xcb\x31\xd9\x92\x46\x98\x6d\x34\x53\xd0\xc3\xd5\x7a\x22\x2a\x61"), RAW(VID_NETSCREEN_09, VID_KEEP, "Netscreen-09", "\x9b\x09\x6d\x9a\xc3\x27\x5a\x7d\x6f\xe8\xb9\x1c\x58\x31\x11\xb0\x9e\xfe\xd1\xa0"), RAW(VID_NETSCREEN_10, VID_KEEP, "Netscreen-10", "\xbf\x03\x74\x61\x08\xd7\x46\xc9\x04\xf1\xf3\x54\x7d\xe2\x4f\x78\x47\x9f\xed\x12"), RAW(VID_NETSCREEN_11, VID_KEEP, "Netscreen-11", "\xc2\xe8\x05\x00\xf4\xcc\x5f\xbf\x5d\xaa\xee\xd3\xbb\x59\xab\xae\xee\x56\xc6\x52"), RAW(VID_NETSCREEN_12, VID_KEEP, "Netscreen-12", "\xc8\x66\x0a\x62\xb0\x3b\x1b\x61\x30\xbf\x78\x16\x08\xd3\x2a\x6a\x8d\x0f\xb8\x9f"), RAW(VID_NETSCREEN_13, VID_KEEP, "Netscreen-13", "\xf8\x85\xda\x40\xb1\xe7\xa9\xab\xd1\x76\x55\xec\x5b\xbe\xc0\xf2\x1f\x0e\xd5\x2e"), RAW(VID_NETSCREEN_14, VID_KEEP, "Netscreen-14", "\x2a\x2b\xca\xc1\x9b\x8e\x91\xb4\x26\x10\x78\x07\xe0\x2e\x72\x49\x56\x9d\x6f\xd3"), RAW(VID_NETSCREEN_15, VID_KEEP, "Netscreen-15", "\x16\x6f\x93\x2d\x55\xeb\x64\xd8\xe4\xdf\x4f\xd3\x7e\x23\x13\xf0\xd0\xfd\x84\x51"), RAW(VID_NETSCREEN_16, VID_KEEP, "Netscreen-16", "\xa3\x5b\xfd\x05\xca\x1a\xc0\xb3\xd2\xf2\x4e\x9e\x82\xbf\xcb\xff\x9c\x9e\x52\xb5"), RAW(VID_ZYWALL, VID_KEEP, "Zywall", "\x62\x50\x27\x74\x9d\x5a\xb9\x7f\x56\x16\xc1\x60\x27\x65\xcf\x48\x0a\x3b\x7d\x0b"), RAW(VID_SIDEWINDER, VID_KEEP, "Sidewinder", "\x84\x04\xad\xf9\xcd\xa0\x57\x60\xb2\xca\x29\x2e\x4b\xff\x53\x7b"), RAW(VID_LUCENT_GW9, VID_KEEP, "Lucent VPN Gateway 9 (LVG9.1.255:BRICK:9.1.255)", "\x4c\x56\x47\x39\x2e\x32\x2e\x32\x34\x35\x3a\x42\x52\x49\x43\x4b\x3a\x39\x2e\x32\x2e\x32\x34\x35"), RAW(VID_LUCENT_CL7, VID_KEEP, "Lucent VPN Client 7 (LVC7.1.2:XP)", "\x4c\x56\x43\x37\x2e\x31\x2e\x32\x3a\x58\x50"), RAW(VID_CHECKPOINT, VID_KEEP, "Check Point", "\xf4\xed\x19\xe0\xc1\x14\xeb\x51\x6f\xaa\xac\x0e\xe3\x7d\xaf\x28\x07\xb4\x38\x1f"), RAW(VID_LIBRESWAN, VID_SUBSTRING_DUMPHEXA, "Libreswan (3.6+)", "\x4f\x45\x2d\x4c\x69\x62\x72\x65\x73\x77\x61\x6e\x2d"), RAW(VID_LIBRESWAN_OLD, VID_SUBSTRING_MATCH, "Libreswan 3.0 - 3.5", "\x4f\x45\x4e"), RAW(VID_XOPENSWAN, VID_SUBSTRING_MATCH, "Openswan(xeleranized)", "\x4f\x53\x57"), RAW(VID_OPENSWANORG, VID_KEEP | VID_SUBSTRING_MATCH, "Openswan(project)", "\x4f\x45"), /* * "ELVIS-PLUS Zastava" * Last two bytes (not matched here) are major|minor nibbles and a reserved 00 */ RAW(VID_ELVIS, VID_KEEP | VID_SUBSTRING_DUMPHEXA, "ELVIS-PLUS Zastava", "\x08\xdb\x45\xe6\xcb\x01\xf8\x0b\xb5\x76\xe9\xa7\x8c\x0f\x54\xe1\x30\x0b\x88\x81"), /* * Fortinet */ DEC_MD5_VID(VID_FORTINET_ENDPOINT_CONTROL, "Fortinet Endpoint Control"), DEC_MD5_VID(VID_FORTINET_CONNECT_LICENSE, "forticlient connect license"), /* END OF TABLE */ VID(VID_none, 0, NULL, NULL), #undef VID #undef RAW }; /* * SEE: comments in init_vendorid(). */ struct vid_entry { const struct vid_struct *entry; /* in VID_TAB[] */ }; /* vendor IDs sorted by the raw .vid; VID_none aka 0 is omitted */ static struct vid_entry vid_sorted[elemsof(vid_tab) - 1/*leave out entry 0*/]; /* bsearch table pointing at VID_SORTED[] */ static const struct vid_entry *vid_lookup[elemsof(vid_sorted)]; unsigned elemsof_vid_lookup; static int vid_sorted_cmp(const void *lp, const void *rp) { const struct vid_entry *l = lp; const struct vid_entry *r = rp; /* * If this isn't sufficient there are deeper problems. */ return hunk_cmp(l->entry->vid, r->entry->vid); } static int vid_entry_cmp(const shunk_t *key, const struct vid_entry *member) { if (member->entry->vid.len < key->len && (member->entry->flags & VID_SUBSTRING)) { return raw_cmp(key->ptr, member->entry->vid.len, member->entry->vid.ptr, member->entry->vid.len); } else { return hunk_cmp(*key, member->entry->vid); } } static int vid_lookup_cmp(const void *key, const void *member) { return vid_entry_cmp(key, *(const struct vid_entry**)member); } /* * Setup VendorID structs, and populate them * FIXME: This functions leaks a little bit, but these are one time leaks: * leak: 3 * vid->data, item size: 6 * leak: self-vendor ID, item size: 37 * leak: 2 * vid->data, item size: 13 */ static void DBG_vid_struct(const struct vid_struct *vid, const struct logger *logger) { LLOG_JAMBUF(DEBUG_STREAM, logger, buf) { jam(buf, " %3d ", vid->id); /* match " %3s " below */ jam_string(buf, vid->descr); if (vid->flags & VID_MD5HASH) { jam_string(buf, " +md5"); } if (vid->flags & VID_SUBSTRING_DUMPHEXA) { jam_string(buf, " substring+hexa"); } if (vid->flags & VID_SUBSTRING_DUMPASCII) { jam_string(buf, " substring+ascii"); } if (vid->flags & VID_SUBSTRING_MATCH) { jam_string(buf, " substring+match"); } } LLOG_JAMBUF(DEBUG_STREAM, logger, buf) { jam(buf, " %3s ", ""); /* match " %3d " above */ jam_dump_hunk(buf, vid->vid); jam_string(buf, " ["); jam_sanitized_bytes(buf, vid->vid.ptr, vid->vid.len); jam_string(buf, "]"); } } void init_vendorid(struct logger *logger) { dbg("building Vendor ID table"); FOR_EACH_ELEMENT_FROM_1(vid, vid_tab) { bool good = true; /* * Point the lookup table at VID table. * * Entry VID_TAB[0] is not included; hence ID-1. */ passert(vid->id > 0); unsigned id0 = vid->id - 1; passert(id0 < elemsof(vid_sorted)); vid_sorted[id0].entry = vid; if (vid->flags & VID_STRING) { /** VendorID is a string **/ good &= pexpect(vid->vid.ptr == NULL); good &= pexpect(vid->vid.len == 0); good &= pexpect(vid->descr == NULL || !streq(vid->descr, vid->data)); vid->vid = shunk1(vid->data); } else if (vid->flags & VID_MD5HASH) { /** VendorID is a string to hash with MD5 **/ good &= pexpect(vid->vid.ptr == NULL); good &= pexpect(vid->vid.len == 0); /* TODO: This use must allowed even with USE_MD5=false */ struct crypt_hash *ctx = crypt_hash_init("vendor id", &ike_alg_hash_md5, logger); crypt_hash_digest_bytes(ctx, "data", vid->data, strlen(vid->data)); void *vidm = alloc_bytes(MD5_DIGEST_SIZE, "VendorID MD5 (ignore)"); crypt_hash_final_bytes(&ctx, vidm, MD5_DIGEST_SIZE); vid->vid = shunk2(vidm, MD5_DIGEST_SIZE); } else if (vid->flags & VID_FSWAN_HASH) { /** FreeS/WAN 2.00+ specific hash **/ good &= pexpect(vid->vid.ptr == NULL); good &= pexpect(vid->vid.len == 0); #define FSWAN_VID_SIZE 12 unsigned char hash[MD5_DIGEST_SIZE]; char *vidm = alloc_bytes(FSWAN_VID_SIZE, "fswan VID (ignore)"); struct crypt_hash *ctx = crypt_hash_init("vendor id", &ike_alg_hash_md5, logger); crypt_hash_digest_bytes(ctx, "data", vid->data, strlen(vid->data)); crypt_hash_final_bytes(&ctx, hash, MD5_DIGEST_SIZE); vidm[0] = 'O'; vidm[1] = 'E'; #if FSWAN_VID_SIZE <= 2 + MD5_DIGEST_SIZE memcpy(vidm + 2, hash, FSWAN_VID_SIZE - 2); /* truncate hash */ #else memcpy(vidm + 2, hash, MD5_DIGEST_SIZE); memset(vidm + 2 + MD5_DIGEST_SIZE, '\0', FSWAN_VID_SIZE - (2 + MD5_DIGEST_SIZE)); /* pad hash */ #endif for (int i = 2; i < FSWAN_VID_SIZE; i++) { vidm[i] &= 0x7f; vidm[i] |= 0x40; } vid->vid = shunk2(vidm, FSWAN_VID_SIZE); #undef FSWAN_VID_SIZE } else { /* RAW() */ good &= pexpect(vid->vid.len > 0); good &= pexpect(vid->vid.ptr != NULL); good &= pexpect(vid->descr != NULL); good &= pexpect(vid->data == NULL); } if (vid->descr == NULL) { /** Find something to display **/ vid->descr = vid->data; } /* job done? */ good &= pexpect(vid->descr != NULL); good &= pexpect(vid->vid.ptr != NULL); good &= pexpect(vid->vid.len > 0); if (!good || DBGP(DBG_TMI)) { DBG_vid_struct(vid, logger); } } /* * Sort the VID_TAB[] creating VID_SORTED. Because VIDs * overlap, the result is a table containing overlapping * entries which means it isn't suitable for a binary search. * * For instance, given: * * "OA.*" * "OE.*" * "OE Libreswan.*" * "OE Libreswan 123" * "OF.*" * * a search for "OE LIBRESWAN" could find "OE.*" or fail. */ qsort(vid_sorted, elemsof(vid_sorted), sizeof(vid_sorted[0]), vid_sorted_cmp); /* * Prune the VID_SORTED[] table of all but the shortest VIDs * creating VID_LOOKUP[]. Each entry points point into * VID_SORTED[] at the first of the overlapping VIDs that * match the VID_LOOKUP[] entry. * * For instance, creating: * * VID_LOOKUP[] VID_SORTED[] * "OA.*" -> "OA.*" * "OE.*" -> "OE.*" * "OE Libreswan.*" * "OE Libreswan 123" * "OF.*" -> "OF.*" * * A search for "OE LIBRESWAN" is then performed in two steps: * * 1. using bsearch(VID_LOOKUP) to find the element "OE.*" * 2. a linear search of VID_SORTED[] starting at it's "OE.*" entry */ dbg("verifying VID lookup table"); vid_lookup[elemsof_vid_lookup++] = &vid_sorted[0]; FOR_EACH_ELEMENT_FROM_1(vidp, vid_sorted) { /* do this and prev clash? */ const struct vid_entry *prev = vid_lookup[elemsof_vid_lookup-1]; int c = vid_entry_cmp(&vidp->entry->vid, prev); if (c > 0) { /* no: easy peasy; lemon squeezy */ vid_lookup[elemsof_vid_lookup++] = vidp; continue; } if (DBGP(DBG_BASE)) { DBG_log("Vendor ID '%s' and '%s' clash", prev->entry->descr, vidp->entry->descr); DBG_vid_struct(prev->entry, logger); DBG_vid_struct(vidp->entry, logger); } } } void llog_vendorid(struct logger *logger, enum known_vendorid id, shunk_t vid, bool vid_useful) { if (id == VID_none) { /* * Unknown Vendor ID. Log the beginning. */ LLOG_JAMBUF(RC_LOG_SERIOUS, logger, buf) { jam(buf, "ignoring unknown Vendor ID payload ["); jam_dump_bytes(buf, vid.ptr, PMIN(vid.len, MAX_LOG_VID_LEN)); if (vid.len > MAX_LOG_VID_LEN) { jam(buf, "..."); } jam(buf, "]"); } } else { /* * Known Vendor ID, casually mention it in the debug * logs. */ if (DBGP(DBG_BASE)) { const struct vid_struct *pvid = &vid_tab[id]; LLOG_JAMBUF(DEBUG_STREAM, logger, buf) { jam(buf, "%s Vendor ID payload [", vid_useful ? "received" : "ignoring"); if (pvid->flags & VID_SUBSTRING_DUMPHEXA) { /* Dump description + Hexa */ jam(buf, "%s ", pvid->descr); jam_dump_hunk(buf, vid); } else if (pvid->flags & VID_SUBSTRING_DUMPASCII) { /* Dump ASCII content */ /* no descr? */ jam_sanitized_hunk(buf, vid); } else { /* Dump description (descr) */ jam_string(buf, pvid->descr); } jam(buf, "]"); } } } } /* * Handle VendorID's. This function parses what the remote peer * sends us, calls handle_known_vendorid on each VID we received * * Known VendorID's are defined in vendor.h * * @param md Message Digest from remote peer * @param vid String of VendorIDs * @param len Length of vid * @param vid VendorID Struct (see vendor.h) * @param st State Structure (Hopefully initialized) * @return void */ enum known_vendorid vendorid_by_shunk(shunk_t vid) { /* * Find known VendorID in vid_tab */ if (vid.len > 0) { #if 1 /* oh for generics */ const struct vid_entry **bvid = bsearch(&vid, vid_lookup, elemsof_vid_lookup, sizeof(vid_lookup[0]), vid_lookup_cmp); if (bvid == NULL) { /* no luck */ return VID_none; } /* BVID points into VID_LOOKUP[] */ passert(bvid >= &vid_lookup[0]); passert(bvid < &vid_lookup[elemsof_vid_lookup]); /* *BVID points into VID_SORTED[] */ const struct vid_entry *best = *bvid; pexpect(vid_entry_cmp(&vid, best) == 0); passert(best >= &vid_sorted[0]); passert(best < &vid_sorted[elemsof(vid_sorted)]); if (DBGP(DBG_TMI)) { DBG_log("starting with first clash:"); DBG_vid_struct(best->entry, &global_logger); } for (const struct vid_entry *vidp = best + 1; vidp < &vid_sorted[elemsof(vid_sorted)]; vidp++) { if (DBGP(DBG_TMI)) { DBG_vid_struct(vidp->entry, &global_logger); } int c = vid_entry_cmp(&vid, vidp); if (c < 0) { if (DBGP(DBG_TMI)) { DBG_log("end of clashes reached:"); } break; } if (c == 0) { if (DBGP(DBG_TMI)) { DBG_log("updating best"); } best = vidp; continue; } if (DBGP(DBG_TMI)) { DBG_log("not the best"); } } return best->entry->id; #else FOR_EACH_ELEMENT_FROM_1(pvid, vid_tab) { if (pvid->vid.len == vid.len) { if (hunk_eq(pvid->vid, vid)) { return pvid->id; } } else if (pvid->flags & VID_SUBSTRING) { if (hunk_starteq(vid, pvid->vid)) { return pvid->id; } } } #endif } return VID_none; } const char *str_vendorid(enum known_vendorid id, enum_buf *eb) { if (id > 0 && id < elemsof(vid_tab)) { return vid_tab[id].descr; } snprintf(eb->buf, sizeof(eb->buf), "VID_%u", id); return eb->buf; } shunk_t shunk_from_vendorid(enum known_vendorid id) { passert(id > 0); passert(id < elemsof(vid_tab)); const struct vid_struct *pvid = &vid_tab[id]; return pvid->vid; } libreswan-4.14/lib/libswan/version.in.c000066400000000000000000000024441457372064200201110ustar00rootroot00000000000000/* * 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. * */ #include "lswversion.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; const char libreswan_vendorid[] = OUR_VENDOR_VID; 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-4.14/lib/libswan/x509dn.c000066400000000000000000000743371457372064200170600ustar00rootroot00000000000000/* Support of X.509 certificates and CRLs, for libreswan * * 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 /* for size_t */ #include "oid.h" #include "x509.h" #include "asn1.h" #include "lswlog.h" #include "id.h" /* coding of X.501 distinguished name */ typedef const struct { const char *name; const unsigned char *oid_ptr; size_t oid_len; enum asn1_type 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 init_rdn(asn1_t dn, /* input (copy) */ asn1_t *rdn, /* output */ asn1_t *attribute, /* output */ bool *more) /* output */ { *attribute = (asn1_t) NULL_HUNK; /* a DN is a SEQUENCE OF RDNs */ RETURN_IF_ERR(unwrap_asn1_tlv(&dn, ASN1_SEQUENCE, 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(asn1_t *rdn, /* input/output */ asn1_t *attribute, /* input/output */ asn1_t *oid /* output */, asn1_t *value_ber, /* output */ enum asn1_type *value_type, /* output */ asn1_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_tlv(rdn, ASN1_SET, attribute)); } /* An attributeTypeAndValue is a SEQUENCE */ asn1_t body; RETURN_IF_ERR(unwrap_asn1_tlv(attribute, ASN1_SEQUENCE, &body)); /* extract oid from body */ RETURN_IF_ERR(unwrap_asn1_tlv(&body, ASN1_OID, oid)); /* extract string value and its type from body */ if (body.len == 0) return "no room for string's type"; *value_ber = body; RETURN_IF_ERR(unwrap_asn1_type(&body, value_type)); /* ??? 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"; } size_t length; RETURN_IF_ERR(unwrap_asn1_length(&body, &length)); RETURN_IF_ERR(unwrap_asn1_value(&body, length, 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. */ bool dn_has_wildcards(asn1_t dn) { asn1_t rdn; asn1_t attribute; bool more; err_t ugh = init_rdn(dn, &rdn, &attribute, &more); if (ugh != NULL) { return false; } while (more) { asn1_t oid; asn1_t value_ber; enum asn1_type value_type; asn1_t value_content; ugh = get_next_rdn(&rdn, &attribute, &oid, &value_ber, &value_type, &value_content, &more); if (ugh != NULL) { return false; } if (value_content.len == 1 && *(const char*)value_content.ptr == '*') { return true; /* we have found a wildcard RDN */ } } return false; } /* * 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 in 2007. * * 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 in 2017. * * 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. * * See also NSS bug 1709676. */ static err_t format_dn(struct jambuf *buf, asn1_t dn, jam_bytes_fn *jam_bytes, bool nss_compatible) { asn1_t rdn; asn1_t attribute; bool more; RETURN_IF_ERR(init_rdn(dn, &rdn, &attribute, &more)); for (bool first = true; more; first = false) { asn1_t oid; asn1_t value_ber; enum asn1_type value_type; asn1_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 * off 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 singular - 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(struct jambuf *buf, asn1_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 */ if (DBGP(DBG_BASE)) { dbg("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); } } err_t parse_dn(asn1_t dn) { dn_buf dnb; struct jambuf buf = ARRAY_AS_JAMBUF(dnb.buf); return format_dn(&buf, dn, jam_raw_bytes, true/*nss_compatible*/); } void jam_dn_or_null(struct jambuf *buf, asn1_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(asn1_t dn, const char *null_dn, dn_buf *dst) { struct jambuf buf = ARRAY_AS_JAMBUF(dst->buf); jam_dn_or_null(&buf, dn, null_dn, jam_sanitized_bytes); return dst->buf; } void jam_dn(struct jambuf *buf, asn1_t dn, jam_bytes_fn *jam_bytes) { jam_dn_or_null(buf, dn, "(empty)", jam_bytes); } const char *str_dn(asn1_t dn, dn_buf *dst) { struct jambuf buf = ARRAY_AS_JAMBUF(dst->buf); jam_dn(&buf, dn, jam_sanitized_bytes); return dst->buf; } /* * 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 * } * } * } * } * } * * See https://bugzilla.mozilla.org/show_bug.cgi?id=1709676 for why * this doesn't use the NSS code. Sigh. */ err_t atodn(const char *src, chunk_t *dn) { dbg("ASCII to DN <= \"%s\"", src); *dn = empty_chunk; /* stack of unfilled lengths */ uint8_t *(patchpoints[5]); /* only 4 are actually needed */ uint8_t **patchpointer = patchpoints; uint8_t dn_buf[sizeof(id_buf)]; /* space for result */ uint8_t *dn_ptr = dn_buf; /* growth point */ uint8_t *dn_redline = dn_buf + sizeof(dn_buf); # define START_OBJ() { *patchpointer++ = 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 - *--patchpointer; \ unsigned char len_buf[1 + sizeof(len)] = { ty }; \ chunk_t obj_len = { len_buf + 1, 0 }; \ /* only handles up to 4 bytes */ \ code_asn1_length(len, &obj_len); \ passert(obj_len.len <= sizeof(len_buf)); \ if (dn_redline - dn_ptr < (ptrdiff_t)obj_len.len + 1) \ return "DN overflow"; \ memmove(*patchpointer + obj_len.len + 1, *patchpointer, len); \ memcpy(*patchpointer, 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] == '#') { /* assume it is a BER and parse the raw hex dump */ src++; while (char_isxdigit(src[0]) && char_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] == '\\' && char_isxdigit(src[1]) && char_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 = patchpointer[-1]; /* name operand start */ enum asn1_type t = (op->type == ASN1_PRINTABLESTRING && !is_asn1_printablestring(shunk2(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 = clone_bytes_as_chunk(dn_buf, dn_ptr - dn_buf, "atodn"); 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(asn1_t a, asn1_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(asn1_t a, asn1_t b, int *wildcards) { asn1_t rdn_a, rdn_b; asn1_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. */ asn1_t oid_a, oid_b; asn1_t value_ber_a, value_ber_b; enum asn1_type value_type_a, value_type_b; asn1_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 (!hunk_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 && *(const char *)value_content_b.ptr == '*') { (*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) { uint8_t or = 0x00; for (size_t i = 0; i != value_content_a.len; i++) { or |= ((const uint8_t*)value_content_a.ptr)[i]; or |= ((const uint8_t*)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) { dn_buf abuf; dn_buf bbuf; dbg("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; } /* * match an equal number of RDNs, in any order * if wildcards != NULL, wildcard matches are enabled */ 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; } static bool match_dn_unordered(const char *prefix, asn1_t a, asn1_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("%smatching unordered DNs A: '%s' B: '%s'", prefix, 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%s matched: %d, rdn_num: %d, wc %d", prefix, __func__, matched, rdn_num, wildcards ? *wildcards : 0); return matched > 0 && rdn_num > 0 && matched == rdn_num; } bool match_dn_any_order_wild(const char *prefix, asn1_t a, asn1_t b, int *wildcards) { bool ret = match_dn(a, b, wildcards); if (!ret) { dbg("%s%s: not an exact match, now checking any RDN order with %d wildcards", prefix, __func__, *wildcards); /* recount wildcards */ *wildcards = 0; ret = match_dn_unordered(prefix, a, b, wildcards); } return ret; } /* * 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-4.14/lib/libswan/xfrm_policy_names.c000066400000000000000000000036001457372064200215300ustar00rootroot00000000000000 /* tables of names for values defined in constants.h * * Copyright (C) 2022 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. */ /* * GRRR: * * GLIBC/Linux and MUSL/Linux define sockaddr_in et.al. in * , and the generic network code uses this. * Unfortunately (cough) the Linux kernel headers also provide * definitions of those structures in et.al. which, * depending on header include order can result in conflicting * definitions. For instance, if sockaddr_in is not defined, * will include the definition in but that * will then clash with a later include of . * * GLIBC/Linux has hacks on hacks to work-around this, not MUSL. * Fortunately, including first will force the Linux * kernel headers to use that definition. * * XXX: here this is overkill as there is no convoluted include * arangement. */ #include #include "linux/xfrm.h" /* local (if configured) or system copy */ #include "lswcdefs.h" /* for ARRAY_REF() */ #include "enum_names.h" /* XFRM POLICY direction names */ static const char *const xfrm_policy_name[] = { #define S(E) [E] = #E S(XFRM_POLICY_IN), S(XFRM_POLICY_OUT), S(XFRM_POLICY_FWD), #undef S }; const struct enum_names xfrm_policy_names = { XFRM_POLICY_IN, XFRM_POLICY_FWD, ARRAY_REF(xfrm_policy_name), "XFRM_POLICY_", /* prefix */ NULL }; libreswan-4.14/lib/libwhack/000077500000000000000000000000001457372064200157745ustar00rootroot00000000000000libreswan-4.14/lib/libwhack/Makefile000066400000000000000000000016241457372064200174370ustar00rootroot00000000000000# 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-4.14/lib/libwhack/aliascomp.c000066400000000000000000000027161457372064200201160ustar00rootroot00000000000000/* 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-4.14/lib/libwhack/whacklib.c000066400000000000000000000305161457372064200177310ustar00rootroot00000000000000/* 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 "sysdep.h" #include "constants.h" #include "lswalloc.h" #include "lswlog.h" #include "whack.h" #include "lswlog.h" #include "ip_info.h" /* * Pack and unpack bytes */ static bool pack_raw(struct whackpacker *wp, void **bytes, size_t nr_bytes, const char *what) { if (wp->str_next + nr_bytes > wp->str_roof) { DBGF(DBG_TMI, "%s: buffer overflow for '%s'", __func__, what); return false; /* would overflow buffer */ } memcpy(wp->str_next, *bytes, nr_bytes); wp->str_next += nr_bytes; return true; } static bool unpack_raw(struct whackpacker *wp, void **bytes, size_t nr_bytes, const char *what) { uint8_t *end = wp->str_next + nr_bytes; if (end > wp->str_roof) { /* overflow */ DBGF(DBG_TMI, "%s: buffer overflow for '%s'; needing %zu bytes", __func__, what, nr_bytes); return false; } *bytes = wp->str_next; wp->str_next = end; return true; } /* * Pack and unpack a memory hunks. * * Notes: * * - to prevent the hunk pointer going across the wire, it is set to * NULL after packing * * - the unpacked pointer points into the whack message do don't free * it * * - zero length pointers are converted to NULL pointers */ #define PACK_HUNK(WP, HUNK, WHAT) \ { \ if (hunk_isempty(*HUNK)) { \ HUNK->ptr = NULL; /* be safe */ \ return true; \ } \ if (!pack_raw(WP, (void**)&(HUNK)->ptr, \ HUNK->len, WHAT)) { \ return false; \ } \ HUNK->ptr = NULL; /* kill pointer being sent on wire! */ \ return true; \ } #define UNPACK_HUNK(WP, HUNK, WHAT) \ { \ if (HUNK->len == 0) { \ /* expect wire-pointer to be NULL */ \ pexpect(HUNK->ptr == NULL); \ HUNK->ptr = NULL; \ return true; \ } \ if (!unpack_raw(WP, (void**)&(HUNK)->ptr, \ HUNK->len, WHAT)) { \ return false; \ } \ return true; \ } static bool pack_chunk(struct whackpacker *wp, chunk_t *chunk, const char *what) { PACK_HUNK(wp, chunk, what); } static bool unpack_chunk(struct whackpacker *wp, chunk_t *chunk, const char *what) { UNPACK_HUNK(wp, chunk, what); } static bool pack_shunk(struct whackpacker *wp, shunk_t *shunk, const char *what) { PACK_HUNK(wp, shunk, what); } static bool unpack_shunk(struct whackpacker *wp, shunk_t *shunk, const char *what) { UNPACK_HUNK(wp, shunk, what); } /* * Pack and unpack a nul-terminated string to a whack messages * * Notes: * * - to prevent the string pointer going across the wire, it is set to * NULL after packing * * - the unpacked pointer stored in *P points into the whack message * do don't free it * * - NULL pointers are converted to "" */ static bool pack_string(struct whackpacker *wp, char **p, const char *what) { 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) { DBGF(DBG_TMI, "%s: buffer overflow for '%s'", __func__, what); return false; /* would overflow buffer */ } strcpy((char *)wp->str_next, s); wp->str_next += len; *p = NULL; /* kill pointer being sent on wire! */ return true; } static bool unpack_string(struct whackpacker *wp, char **p, const char *what) { /* expect wire-pointer to be NULL */ pexpect(*p == NULL); uint8_t *end = memchr(wp->str_next, '\0', (wp->str_roof - wp->str_next) ); if (end == NULL) { DBGF(DBG_TMI, "%s: buffer overflow for '%s'; missing NUL", __func__, what); return false; /* fishy: no end found */ } unsigned char *s = (wp->str_next == end ? NULL : wp->str_next); DBGF(DBG_TMI, "%s: '%s' is %ld bytes", __func__, what, (long int)(end - wp->str_next)); *p = (char *)s; wp->str_next = end + 1; return true; } /* * IP pointers. */ static bool pack_ip_info(struct whackpacker *wp UNUSED, const struct ip_info **info, const char *what UNUSED) { /* spell out conversions */ *info = (const void*)(uintptr_t)(unsigned)(*info)->ip_version; return true; } static bool unpack_ip_info(struct whackpacker *wp UNUSED, const struct ip_info **info, const char *what UNUSED) { /* spell out conversions */ *info = ip_version_info((unsigned)(uintptr_t)(const void*)*info); return *info != NULL; } static bool pack_ip_protocol(struct whackpacker *wp UNUSED, const struct ip_protocol **protocol, const char *what UNUSED) { /* spell out conversions */ *protocol = (const void*)(uintptr_t)(unsigned)(*protocol)->ipproto; return true; } static bool unpack_ip_protocol(struct whackpacker *wp UNUSED, const struct ip_protocol **protocol, const char *what UNUSED) { /* spell out conversions */ *protocol = protocol_by_ipproto((unsigned)(uintptr_t)(const void*)*protocol); return *protocol != NULL; } static bool pack_constant_string(struct whackpacker *wp UNUSED, const char **string, const char *constant, const char *what) { if (*string != NULL) { DBGF(DBG_TMI, "%s: '%s' was: %s (%s)", __func__, what, *string, constant); passert(streq(*string, constant)); *string = NULL; } else { /* * For instance, when whack sends constrol messages * such as "status" the whack_end .leftright field is * still NULL. * * The unpack will set the field, oops. */ DBGF(DBG_TMI, "%s: '%s' was null (%s)", __func__, what, constant); } return true; } static bool unpack_constant_string(struct whackpacker *wp UNUSED, const char **string, const char *constant, const char *what) { pexpect(*string == NULL); *string = constant; DBGF(DBG_TMI, "%s: '%s' is %s", __func__, what, *string); return true; } /* * in and out/ */ struct pickler { bool (*string)(struct whackpacker *wp, char **p, const char *what); bool (*shunk)(struct whackpacker *wp, shunk_t *s, const char *what); bool (*chunk)(struct whackpacker *wp, chunk_t *s, const char *what); bool (*raw)(struct whackpacker *wp, void **bytes, size_t nr_bytes, const char *what); bool (*ip_info)(struct whackpacker *wp, const struct ip_info **info, const char *what); bool (*ip_protocol)(struct whackpacker *wp, const struct ip_protocol **protocol, const char *what); bool (*constant_string)(struct whackpacker *wp, const char **p, const char *leftright, const char *what); }; const struct pickler pickle_packer = { .string = pack_string, .shunk = pack_shunk, .chunk = pack_chunk, .raw = pack_raw, .ip_info = pack_ip_info, .ip_protocol = pack_ip_protocol, .constant_string = pack_constant_string, }; const struct pickler pickle_unpacker = { .string = unpack_string, .shunk = unpack_shunk, .chunk = unpack_chunk, .raw = unpack_raw, .ip_info = unpack_ip_info, .ip_protocol = unpack_ip_protocol, .constant_string = unpack_constant_string, }; #define PICKLE_STRING(FIELD) pickle->string(wp, FIELD, #FIELD) #define PICKLE_CHUNK(FIELD) pickle->chunk(wp, FIELD, #FIELD) #define PICKLE_SHUNK(FIELD) pickle->shunk(wp, FIELD, #FIELD) #define PICKLE_THINGS(THINGS, NR) pickle->raw(wp, (void**)(THINGS), NR*sizeof((THINGS)[0][0]), #THINGS) #define PICKLE_CONSTANT_STRING(FIELD, VALUE) pickle->constant_string(wp, FIELD, VALUE, #FIELD) #if 0 #define PICKLE_CIDR(CIDR) \ ((CIDR)->is_set ? pickle->ip_info(wp, &((CIDR)->info), #CIDR) : true) #else #define PICKLE_CIDR(CIDR) true #endif static bool pickle_whack_end(struct whackpacker *wp, const char *leftright, struct whack_end *end, const struct pickler *pickle) { return (PICKLE_CONSTANT_STRING(&end->leftright, leftright), PICKLE_STRING(&end->id) && PICKLE_STRING(&end->cert) && PICKLE_STRING(&end->pubkey) && PICKLE_STRING(&end->ckaid) && PICKLE_STRING(&end->ca) && PICKLE_STRING(&end->groups) && PICKLE_STRING(&end->updown) && PICKLE_STRING(&end->virt) && PICKLE_STRING(&end->xauth_username) && PICKLE_STRING(&end->host_addr_name) && PICKLE_CIDR(&end->host_vtiip) && PICKLE_CIDR(&end->ifaceip) && true); } static bool pickle_whack_message(struct whackpacker *wp, const struct pickler *pickle) { return (PICKLE_STRING(&wp->msg->name) && /* first */ pickle_whack_end(wp, "left", &wp->msg->left, pickle) && pickle_whack_end(wp, "right",&wp->msg->right, pickle) && PICKLE_STRING(&wp->msg->keyid) && PICKLE_STRING(&wp->msg->ike) && PICKLE_STRING(&wp->msg->esp) && PICKLE_STRING(&wp->msg->connalias) && PICKLE_STRING(&wp->msg->string1) && PICKLE_STRING(&wp->msg->string2) && PICKLE_STRING(&wp->msg->string3) && PICKLE_STRING(&wp->msg->dnshostname) && PICKLE_STRING(&wp->msg->modecfg_dns) && PICKLE_STRING(&wp->msg->modecfg_domains) && PICKLE_STRING(&wp->msg->modecfg_banner) && PICKLE_STRING(&wp->msg->conn_mark_both) && PICKLE_STRING(&wp->msg->conn_mark_in) && PICKLE_STRING(&wp->msg->conn_mark_out) && PICKLE_STRING(&wp->msg->vti_iface) && PICKLE_STRING(&wp->msg->remote_host) && PICKLE_STRING(&wp->msg->global_redirect_to) && PICKLE_STRING(&wp->msg->redirect_to) && PICKLE_STRING(&wp->msg->accept_redirect_to) && PICKLE_STRING(&wp->msg->active_redirect_dests) && PICKLE_CHUNK(&wp->msg->keyval) && PICKLE_THINGS(&wp->msg->impairments, wp->msg->nr_impairments) && PICKLE_STRING(&wp->msg->sec_label) && 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 (!pickle_whack_message(wp, &pickle_packer)) { return "too many bytes of strings or key to fit in message to pluto"; } return NULL; } /** * Unpack a message whack received * * @param wp The whack message * @return err_t */ bool unpack_whack_msg(struct whackpacker *wp, struct logger *logger) { if (wp->str_next > wp->str_roof) { llog(RC_BADWHACKMESSAGE, logger, "ignoring truncated message from whack: got %d bytes; expected %zu", wp->n, sizeof(wp->msg)); return false; } if (!pickle_whack_message(wp, &pickle_unpacker)) { llog(RC_BADWHACKMESSAGE, logger, "message from whack contains bad string or key"); return false; } return true; } void clear_end(const char *leftright, struct whack_end *e) { static const struct whack_end zero_end; /* zeros and NULL pointers */ *e = zero_end; e->leftright = leftright; } 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-4.14/macports/000077500000000000000000000000001457372064200152725ustar00rootroot00000000000000libreswan-4.14/macports/nspr/000077500000000000000000000000001457372064200162545ustar00rootroot00000000000000libreswan-4.14/macports/nspr/Portfile000066400000000000000000000035721457372064200177720ustar00rootroot00000000000000# $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-4.14/macports/nspr/files/000077500000000000000000000000001457372064200173565ustar00rootroot00000000000000libreswan-4.14/macports/nspr/files/nspr.pc000066400000000000000000000003461457372064200206670ustar00rootroot00000000000000prefix=@@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-4.14/macports/nss/000077500000000000000000000000001457372064200160755ustar00rootroot00000000000000libreswan-4.14/macports/nss/Portfile000066400000000000000000000077051457372064200176150ustar00rootroot00000000000000# $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-4.14/macports/nss/files/000077500000000000000000000000001457372064200171775ustar00rootroot00000000000000libreswan-4.14/macports/nss/files/nss-config.in000066400000000000000000000045141457372064200216010ustar00rootroot00000000000000#!/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-4.14/macports/nss/files/nss.pc.in000066400000000000000000000004011457372064200207260ustar00rootroot00000000000000prefix=@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-4.14/macports/nss/files/patch-Darwin.mk.diff000066400000000000000000000026351457372064200227660ustar00rootroot00000000000000--- 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-4.14/macports/nss/files/patch-UNIX.mk.diff000066400000000000000000000007471457372064200223270ustar00rootroot00000000000000--- 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-4.14/mk/000077500000000000000000000000001457372064200140515ustar00rootroot00000000000000libreswan-4.14/mk/README.md000066400000000000000000000126121457372064200153320ustar00rootroot00000000000000 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-4.14/mk/TODO.md000066400000000000000000000060321457372064200151410ustar00rootroot00000000000000 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 connectivity) 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-4.14/mk/config.mk000066400000000000000000000634061457372064200156600ustar00rootroot00000000000000# Libreswan configuration # # Copyright (C) 2001, 2002 Henry Spencer. # Copyright (C) 2003-2006 Xelerance Corporation # Copyright (C) 2012-2020 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 # # Configuration options. # # Sometimes the make variable is called USE_ and the C macro # is called HAVE_, but not always. # # USE_ assume a package and enable corresponding feature # # For instance USE_SECCOMP assumes the seccomp library and # enables the seccomp code. # # HAVE_ variables let you tell Libreswan what system related libraries # you may or maynot have # A Makefile wanting to test variables defined below has two choices: # # - 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 ($(OSDEP,xxx) to automatically determine # where we are building on and disable things # 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, OSDEP, 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 $(OSDEP).mk file - the logic ends # up being a horrible mess so hopefully that helps to keep the mess # within the family. # # Using the "build" machine to select "target" configuration options # is, to say the least, a little weird. It's "historic". include ${LIBRESWANSRCDIR}/mk/defaults/${OSDEP}.mk # "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 # -D... goes in here USERLAND_CFLAGS += -pthread # should this go in CFLAGS? USERLAND_CFLAGS += -std=gnu99 # # Error out on deprecated since 4.0 config variables. # ifdef BINDIR $(error ERROR: Deprecated BINDIR variable set, use LIBEXECDIR instead) endif ifdef PUBDIR $(error ERROR: Deprecated PUBDIR variable is set, use SBINDIR instead) endif ifdef EFENCE $(error ERROR: Deprecated EFENCE variable is set, use USE_EFENCE instead) endif ifdef INC_USRLOCAL $(error ERROR: Deprecated INC_USRLOCAL variable is set, use PREFIX instead) endif ifdef MANTREE $(error ERROR: Deprecated MANTREE variable is set, use FINALMANDIR instead) endif ifdef USE_XAUTHPAM $(error ERROR: Deprecated USE_XAUTHPAM variable is set, use USE_AUTHPAM instead) endif ifdef USE_NETKEY $(error ERROR: Deprecated USE_NETKEY variable is set, use USE_XFRM instead) endif ifdef USE_KLIPS $(error ERROR: Deprecated USE_KLIPS variable is set, migrate to use USE_XFRM instead) endif ifdef INC_MANDIR $(error ERROR: Deprecated INC_MANDIR variable is set, use FINALMANDIR instead) endif ifdef INC_DOCDIR $(error ERROR: Deprecated INC_DOCDIR variable is set, use FINALDOCDIR instead) endif ifdef INC_RCDIRS $(error ERROR: Deprecated variable INC_RCDIRS is set, use INITDDIRS instead endif ifdef INC_RCDEFAULT $(error ERROR: Deprecated variable INC_RCDEFAULT is set, use INITDDIR_DEFAULT instead) endif # # Options that really belong in CFLAGS (making for an intuitive way to # override them). # # AUTOCONF dogma is to put debug and optimization options such as the # DEBUG_CFLAGS, WARNING_CFLAGS and OPTIMIZE_CFLAGS below, in CFLAGS # making them easy to tweak. Stuff that shouldn change such as # include paths are then put elsewhere (such as USERLAND_CFLAGS). # DEBUG_CFLAGS ?= -g USERLAND_CFLAGS += $(DEBUG_CFLAGS) # eventually: -Wshadow -pedantic? WERROR_CFLAGS ?= -Werror 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) # pick up any generated headers USERLAND_INCLUDES += -I$(builddir) # pick up libreswan's includes USERLAND_INCLUDES += -I$(top_srcdir)/include # Basic linking flags USERLAND_LDFLAGS += -Wl,--as-needed USERLINK ?= -Wl,-z,relro,-z,now -pie USERLAND_LDFLAGS += $(USERLINK) # # Enable LTO by default # # Should only need USERLAND_CFLAGS+=-flto. Unfortunately this doesn't # work on BSD. Hence the extra knobs to allow developers to play. USE_LTO ?= false LTO_CFLAGS ?= -flto LTO_LDFLAGS ?= ifeq ($(USE_LTO),true) USERLAND_CFLAGS += $(LTO_CFLAGS) USERLAND_LDFLAGS += $(LTO_LDFLAGS) endif ### 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 ?= # "PREFIX" part of tree, used in building other pathnames. PREFIX ?= /usr/local # LIBEXECDIR is where sub-commands get put, FINALLIBEXECDIR is where # the "ipsec" command will look for them when it is run. FINALLIBEXECDIR ?= $(PREFIX)/libexec/ipsec LIBEXECDIR ?= $(DESTDIR)$(FINALLIBEXECDIR) # SBINDIR is where the user interface command goes. FINALSBINDIR ?= $(PREFIX)/sbin SBINDIR ?= $(DESTDIR)$(FINALSBINDIR) # where the appropriate manpage tree is located FINALMANDIR ?= $(PREFIX)/share/man # the full pathname MANDIR ?= $(DESTDIR)$(FINALMANDIR) # where configuration files go FINALSYSCONFDIR ?= /etc # where INITSYSTEM files go FINALINITSYSTEMDIR ?= $(FINALSYSCONFDIR)/$(INITSYSTEM) INITSYSTEMDIR ?= $(DESTDIR)$(FINALINITSYSTEMDIR) FINALINITSYSTEMEXAMPLESDIR ?= $(PREFIX)/share/examples/$(INITSYSTEM) INITSYSTEMEXAMPLESDIR ?= $(DESTDIR)$(FINALINITSYSTEMEXAMPLESDIR) # run dir - defaults to /run/pluto # Some older systems might need to set this to /var/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) # where dynamic PPKs go, for now FINALPPKDIR ?= $(FINALCONFDDIR) PPKDIR ?= $(DESTDIR)$(FINALPPKDIR) # Documentation directory FINALDOCDIR ?= $(PREFIX)/share/doc/libreswan DOCDIR ?= $(DESTDIR)$(FINALDOCDIR) # sample configuration files go into FINALEXAMPLECONFDIR ?= $(FINALDOCDIR) EXAMPLECONFDIR ?= $(DESTDIR)$(FINALEXAMPLECONFDIR) # where per-conn pluto logs go FINALVARDIR ?= /var VARDIR ?= $(DESTDIR)$(FINALVARDIR) FINALLOGDIR ?= $(FINALVARDIR)/log LOGDIR ?= $(DESTDIR)$(FINALLOGDIR) # Directory for logrotate config FINALLOGROTATEDDIR ?= $(FINALSYSCONFDIR)/logrotate.d LOGROTATEDDIR ?= $(DESTDIR)$(FINALLOGROTATEDDIR) # Where nss databases go FINALNSSDIR ?= $(FINALVARDIR)/lib/ipsec/nss # RHEL/CentOS <= 8 and Fedora <= 32 uses /etc/ipsec.d #FINALNSSDIR ?= /etc/ipsec.d NSSDIR ?= $(DESTDIR)$(FINALNSSDIR) DOCKER_PLUTONOFORK ?= --nofork # An attempt is made to automatically figure out where boot/shutdown scripts # will finally go: the first directory in INITDDIRS that exists gets them. # If none of those exists (or INITDDIRS is empty), INITDDIR_DEFAULT gets them. # With a non-null DESTDIR, INITDDIR_DEFAULT will be used unless one of the # INITDDIRS directories has been pre-created under DESTDIR. INITDDIRS ?= /etc/rc.d/init.d /etc/init.d INITDDIR_DEFAULT ?= /etc/init.d # INITDDIR is where boot/shutdown scripts go; FINALINITDDIR is where they think # will finally be (so utils/Makefile can create a symlink in LIBEXECDIR to # the place where the boot/shutdown script will finally be, rather than # the place where it is installed). FINALINITDDIR ?= $(shell for d in $(INITDDIRS) ; \ do if test -d $(DESTDIR)/$$d ; \ then echo $$d ; exit 0 ; \ fi ; done ; echo $(INITDDIR_DEFAULT) ) # XXX: overlaps FINALINITSYSTEMDIR INITDDIR ?= $(DESTDIR)$(FINALINITDDIR) # 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 # used by _stackmanager # # 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) (let # install choose the suffix). Since install procedures will never # overwrite an existing config file they omit -b. INSTBINFLAGS ?= -b # The -m flag is more portable than --mode=. INSTMANFLAGS ?= -m 0644 INSTCONFFLAGS ?= -m 0644 # must be before all uses; invoking is expensive called once PKG_CONFIG ?= pkg-config # XXX: Append NSS_CFLAGS to USERLAND_INCLUDES which puts it after # -I$(top_srcdir)/include; expanded on every compile so invoke once. ifndef NSS_CFLAGS NSS_CFLAGS := $(shell $(PKG_CONFIG) --cflags nss) endif USERLAND_INCLUDES += $(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 SSL_LDFLAGS ?= -lssl3 # 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) USERLAND_CFLAGS += -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) USERLAND_CFLAGS += -DNSS_IPSEC_PROFILE endif # 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 # -levent can mean two things? LIBEVENT_LDFLAGS ?= -levent_core -levent_pthreads # Install the portexclude service for policies/portexcludes.conf policies # Disabled per default for now because it requires python[23] USE_PORTEXCLUDES ?= false # 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 ?= USERLAND_LDFLAGS += $(ASAN) ### misc configuration, included here in hopes that other files will not ### have to be changed for common customizations. # You can also run this before starting libreswan on glibc systems: #export MALLOC_PERTURB_=$(($RANDOM % 255 + 1)) # look for POD2MAN command POD2MAN ?= $(shell which pod2man | grep / | head -n1) # Enable or disable support for IKEv1. When disabled, the ike-policy= value # will be ignored and all IKEv1 packets will be dropped. USE_IKEv1 ?= true ifeq ($(USE_IKEv1),true) USERLAND_CFLAGS += -DUSE_IKEv1 endif # 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 SYSTEMUNITDIR ?= $(shell $(PKG_CONFIG) systemd --variable=systemdsystemunitdir) SYSTEMTMPFILESDIR ?= $(shell $(PKG_CONFIG) systemd --variable=tmpfilesdir) UNITDIR ?= $(DESTDIR)$(SYSTEMUNITDIR) TMPFILESDIR ?= $(DESTDIR)$(SYSTEMTMPFILESDIR) 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 # 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 $(top_srcdir)/mk/version.mk # Make sure we only run this once per build, its too expensive to run # every time mk/config.mk 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 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 export LIBRESWANLIB LSWTOOLLIB export WHACKLIB IPSECCONFLIB IPSEC_SECRETS_FILE ?= $(FINALCONFDIR)/ipsec.secrets # how to do variable substitution in sed-transformed files TRANSFORM_VARIABLES = sed \ -e "/@${OSDEP}_START@/,/@${OSDEP}_END@/d" \ -e "s:@DOCKER_PLUTONOFORK@:$(DOCKER_PLUTONOFORK):g" \ -e "s:@EXAMPLECONFDIR@:$(EXAMPLECONFDIR):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:@FINALINITDDIR@:$(FINALINITDDIR):g" \ -e "s:@FINALINITSYSTEMDIR@:$(FINALINITSYSTEMDIR):g" \ -e "s:@FINALINITSYSTEMEXAMPLESDIR@:$(FINALINITSYSTEMEXAMPLESDIR):g" \ -e "s:@FINALLIBEXECDIR@:$(FINALLIBEXECDIR):g" \ -e "s:@FINALLOGDIR@:$(FINALLOGDIR):g" \ -e "s:@FINALLOGROTATEDDIR@:$(FINALLOGROTATEDDIR):g" \ -e "s:@FINALSBINDIR@:$(FINALSBINDIR):g" \ -e "s:@FINALSYSCONFDIR@:$(FINALSYSCONFDIR):g" \ -e "s:@FINALVARDIR@:$(FINALVARDIR):g" \ -e "s:@INITSYSTEM@:$(INITSYSTEM):g" \ -e "s:@IPSECVERSION@:$(IPSECVERSION):g" \ -e "s:@IPSEC_CONF@:$(FINALCONFFILE):g" \ -e "s:@IPSEC_CONFDDIR@:$(FINALCONFDDIR):g" \ -e "s:@IPSEC_EXECDIR@:$(FINALLIBEXECDIR):g" \ -e "s:@IPSEC_NSSDIR@:$(FINALNSSDIR):g" \ -e "s:@IPSEC_PPKDIR@:$(FINALPPKDIR):g" \ -e "s:@IPSEC_RUNDIR@:$(FINALRUNDIR):g" \ -e "s:@IPSEC_SBINDIR@:$(FINALSBINDIR):g" \ -e "s:@IPSEC_SECRETS_FILE@:$(IPSEC_SECRETS_FILE):g" \ -e "s:@IPSEC_VARDIR@:$(FINALVARDIR):g" \ -e "s:@MODPROBEARGS@:$(MODPROBEARGS):g" \ -e "s:@MODPROBEBIN@:$(MODPROBEBIN):g" \ -e "s:@OSDEP@:${OSDEP}:g" \ -e "s:@PYTHON_BINARY@:$(PYTHON_BINARY):g" \ -e "s:@SD_PLUTO_OPTIONS@:$(SD_PLUTO_OPTIONS):g" \ -e "s:@SD_RESTART_TYPE@:$(SD_RESTART_TYPE):g" \ -e "s:@SD_TYPE@:$(SD_TYPE):g" \ -e "s:@SD_WATCHDOGSEC@:$(SD_WATCHDOGSEC):g" \ -e "s:@SHELL_BINARY@:$(SHELL_BINARY):g" \ -e "s:@USE_DEFAULT_CONNS@:$(USE_DEFAULT_CONNS):g" \ -e "s:@HAVE_IPTABLES@:$(HAVE_IPTABLES):g" \ -e "s:@HAVE_NFTABLES@:$(HAVE_NFTABLES):g" \ $(NULL) # 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/ # 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 # # Kernel support # # KLIPS is no longer supported # These are really set in mk/defaults/*.mk # # support Linux kernel's XFRM (aka NETKEY) USE_XFRM ?= false # support pfkey v2 interface (typically KAME derived) USE_PFKEYV2 ?= false ifeq ($(USE_XFRM),true) USERLAND_CFLAGS += -DKERNEL_XFRM endif ifeq ($(USE_PFKEYV2),true) USERLAND_CFLAGS += -DKERNEL_PFKEYV2 endif # extra XFRM options ifeq ($(USE_XFRM),true) USE_XFRM_INTERFACE ?= true ifeq ($(USE_XFRM_INTERFACE), true) USERLAND_CFLAGS += -DUSE_XFRM_INTERFACE endif 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 ?= false USE_XFRM_INTERFACE_IFLA_HEADER ?= false ifeq ($(USE_XFRM),true) XFRM_LIFETIME_DEFAULT ?= 30 USERLAND_CFLAGS += -DXFRM_LIFETIME_DEFAULT=$(XFRM_LIFETIME_DEFAULT) endif # Enable support for DNSSEC. This requires the unbound and ldns # libraries. The default DNSSEC root key location must be set in # default/*.mk; look for auto-trust-anchor-file in unbound.conf. USE_DNSSEC ?= true # DEFAULT_DNSSEC_ROOTKEY_FILE= ifeq ($(USE_DNSSEC),true) USERLAND_CFLAGS += -DUSE_DNSSEC UNBOUND_LDFLAGS ?= -lunbound -lldns ifndef DEFAULT_DNSSEC_ROOTKEY_FILE $(error DEFAULT_DNSSEC_ROOTKEY_FILE unknown) endif 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 += -DUSE_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 IKEv1 XAUTH and IKE2 pam-authorize when available on the platform USE_AUTHPAM ?= true ifeq ($(USE_AUTHPAM),true) USERLAND_CFLAGS += -DUSE_PAM_AUTH AUTHPAM_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_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 ?= $(ALL_ALGS) 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_SHA1 ?= true ifeq ($(USE_SHA1),true) USERLAND_CFLAGS += -DUSE_SHA1 endif USE_SHA2 ?= true ifeq ($(USE_SHA2),true) USERLAND_CFLAGS += -DUSE_SHA2 endif # Used mostly for IoT USE_PRF_AES_XCBC ?= true ifeq ($(USE_PRF_AES_XCBC),true) USERLAND_CFLAGS += -DUSE_PRF_AES_XCBC endif # Use NSS's FIPS compliant Key Derivation Function (KDF). # # With this enabled, libreswan itself no longer needs to be FIPS # validated. With this disabled, libreswan will use it's own KDF # code. # # Requires NSS >= 3.52 # NSS 3.44 - 3.51 can be used if the following NSS upstream commit # is applied: # # HG changeset patch # User Robert Relyea # Date 1587427096 25200 # Mon Apr 20 16:58:16 2020 -0700 # Node ID 225bb39eade102eef5f3999eae04a7a16da9b330 # Parent aae226c20dfd2189fb395f43269fe06cf1fb9cb1 # Bug 1629663 NSS missing IKEv1 Quick Mode KDF prf r=kjacobs ifdef USE_NSS_PRF $(error ERROR: Deprecated USE_NSS_PRF variable set, use USE_NSS_KDF instead) endif USE_NSS_KDF ?= true ifeq ($(USE_NSS_KDF),true) USERLAND_CFLAGS += -DUSE_NSS_KDF endif USERLAND_CFLAGS += -DDEFAULT_RUNDIR=\"$(FINALRUNDIR)\" 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 # iptables for CAT, or NFLOG, look, barf, verify HAVE_IPTABLES ?= false ifeq ($(HAVE_IPTABLES),true) USERLAND_CFLAGS += -DHAVE_IPTABLES endif # nft nflog-all(nflog not yet), look, barf, verfiy HAVE_NFTABLES ?= false ifeq ($(HAVE_NFTABLES),true) USERLAND_CFLAGS += -DHAVE_NFTABLES 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) # 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 endif libreswan-4.14/mk/configs.sh000077500000000000000000000010151457372064200160350ustar00rootroot00000000000000#!/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_3DES=true USE_DH2=true USE_DH22=true USE_DH23=true USE_DH24=true USE_DH31=true USE_CAMELLIA=true makes USE_3DES=false USE_DH2=false USE_DH22=false USE_DH23=false USE_DH24=false USE_DH31=false USE_CAMELLIA=false # flip flop other common flags makes USE_DNSSEC=true USE_SECCOMP=true makes USE_DNSSEC=false USE_SECCOMP=false libreswan-4.14/mk/defaults/000077500000000000000000000000001457372064200156605ustar00rootroot00000000000000libreswan-4.14/mk/defaults/darwin.mk000066400000000000000000000020241457372064200174730ustar00rootroot00000000000000BSD_VARIANT=darwin # sketch out pkgsrc PKG_BASE ?= /usr/local # See: https://github.com/llvm/llvm-project/issues/55963 # See: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=264288 # See: https://github.com/libreswan/libreswan/issues/735 CC=gcc USERLAND_CFLAGS += -DUSE_SOCKADDR_LEN USERLAND_INCLUDES += -I$(PKG_BASE)/include USERLAND_LDFLAGS += -L$(PKG_BASE)/lib -Wl,-rpath,$(PKG_BASE)/lib # NSS includes more than needed in ldflags NSS_LDFLAGS = -L$(PKG_BASE)/lib/nss -Wl,-rpath,$(PKG_BASE)/lib/nss -lnss3 -lfreebl3 -lssl3 NSPR_LDFLAGS = -L$(PKG_BASE)/lib/nspr -Wl,-rpath,$(PKG_BASE)/lib/nspr -lnspr4 USE_PFKEYV2 = true USE_LIBCAP_NG = false USE_PTHREAD_SETSCHEDPRIO = false USE_UNBOUND = false #USE_UNBOUND_EVENT_H_COPY = true USE_DNSSEC = false #DEFAULT_DNSSEC_ROOTKEY_FILE = /usr/local/etc/unbound/root.key INITSYSTEM=rc.d # not /run/pluto FINALRUNDIR=/var/run/pluto # PREFIX = /usr/local from mk/config.mk FINALSYSCONFDIR=$(PREFIX)/etc FINALNSSDIR=$(PREFIX)/etc/ipsec.d FINALEXAMPECONFDIR=$(PREFIX)/share/examples/libreswan libreswan-4.14/mk/defaults/freebsd.mk000066400000000000000000000020651457372064200176260ustar00rootroot00000000000000BSD_VARIANT=freebsd # sketch out pkgsrc PKG_BASE ?= /usr/local # See: https://github.com/llvm/llvm-project/issues/55963 # See: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=264288 # See: https://github.com/libreswan/libreswan/issues/735 CC=gcc USERLAND_CFLAGS += -DUSE_SOCKADDR_LEN USERLAND_INCLUDES += -I$(PKG_BASE)/include USERLAND_LDFLAGS += -L$(PKG_BASE)/lib -Wl,-rpath,$(PKG_BASE)/lib # NSS includes more than needed in ldflags NSS_LDFLAGS = -L$(PKG_BASE)/lib/nss -Wl,-rpath,$(PKG_BASE)/lib/nss -lnss3 -lfreebl3 -lssl3 NSPR_LDFLAGS = -L$(PKG_BASE)/lib/nspr -Wl,-rpath,$(PKG_BASE)/lib/nspr -lnspr4 USE_PFKEYV2 = true USE_LIBCAP_NG = false USE_UNBOUND_EVENT_H_COPY = true USE_PTHREAD_SETSCHEDPRIO = false USE_DNSSEC = true DEFAULT_DNSSEC_ROOTKEY_FILE = /usr/local/etc/unbound/root.key INITSYSTEM=rc.d # not /run/pluto FINALRUNDIR=/var/run/pluto # PREFIX = /usr/local from mk/config.mk FINALSYSCONFDIR=$(PREFIX)/etc FINALNSSDIR=$(PREFIX)/etc/ipsec.d FINALEXAMPECONFDIR=$(PREFIX)/share/examples/libreswan # LTO seems either broken or confused USE_LTO ?= false libreswan-4.14/mk/defaults/linux.mk000066400000000000000000000062511457372064200173540ustar00rootroot00000000000000# Detect linux variants and releases. # So that the sub-shell is invoked only once, ":=" is used. Because # there is no conditional version of := (':=' is unconditional), the # assignment needs to be wrapped in 'ifndef'. ifndef LINUX_VARIANT # ID+ID_LIKE, for instance: # Debian: ID=debian # Fedora: ID=fedora # Red Hat: ID=redhat ID_LIKE=fedora? => redhat fedora? # Mint: ID=linuxmint ID_LIKE=ubuntu => linuxmint ubuntu # $(sort) gets rid of duplicates (needed?) export LINUX_VARIANT := $(sort $(shell sed -n -e 's/"//g' -e 's/^ID_LIKE=//p' -e 's/^ID=//p' /etc/os-release)) endif ifndef LINUX_VERSION_CODENAME # VERSION_CODENAME+UBUNTU_CODENAME, for instance: # Debian: VERSION_CODENAME=buster # Fedora: VERSION_CODENAME="" # Mint: UBUNTU_CODENAME=focal VERSION_CODENAME=una => focal una # $(sort) gets rid of duplicates (needed?) export LINUX_VERSION_CODENAME := $(sort $(shell sed -n -e 's/^VERSION_CODENAME=//p' -e 's/^UBUNTU_CODENAME=//p' /etc/os-release)) endif ifndef LINUX_VERSION_ID export LINUX_VERSION_ID := $(shell sed -n -e 's/^VERSION_ID=//p' /etc/os-release) endif #(info LINUX_VARIANT=$(LINUX_VARIANT)) #(info LINUX_VERSION_ID=$(LINUX_VERSION_ID)) #(info LINUX_VERSION_CODENAME=$(LINUX_VERSION_CODENAME)) # # Debian derived; ubuntu derived # ifneq ($(filter debian ubuntu,$(LINUX_VARIANT)),) DEFAULT_DNSSEC_ROOTKEY_FILE ?= /usr/share/dns/root.key ifeq ($(LINUX_VERSION_CODENAME),buster) # Debian 10 (Buster); until June 2024 USE_NSS_KDF ?= false endif ifeq ($(LINUX_VERSION_CODENAME),focal) # Ubuntu 20.04 LTS (Focal Fossa); until April 2025 USE_NSS_KDF ?= false endif ifeq ($(LINUX_VERSION_CODENAME),bionic) # Ubuntu 18.04 LTS (Bionic Beaver); until April 2023 USE_NSS_KDF ?= false USE_XFRM_INTERFACE_IFLA_HEADER ?= true USE_NSS_IPSEC_PROFILE ?= false endif endif # # Fedora derived # ifneq ($(filter fedora,$(LINUX_VARIANT)),) DEFAULT_DNSSEC_ROOTKEY_FILE ?= /var/lib/unbound/root.key USE_LINUX_AUDIT ?= true USE_SECCOMP ?= true USE_LABELED_IPSEC ?= true endif # # OpenSuSe derived # https://en.opensuse.org/SDB:SUSE_and_openSUSE_Products_Version_Outputs # ifneq ($(filter suse,$(LINUX_VARIANT)),) # https://lists.opensuse.org/archives/list/users@lists.opensuse.org/message/HYB6CKB7DPMPAN7BGUC6MRHE6TWZDABI/ DEFAULT_DNSSEC_ROOTKEY_FILE ?= /var/lib/unbound/root.key endif # # Arch Linux derived # ifneq ($(filter arch,$(LINUX_VARIANT)),) # https://wiki.archlinux.org/title/unbound#Root_hints DEFAULT_DNSSEC_ROOTKEY_FILE ?= /etc/trusted-key.key endif # # INITSYSTEM # ifndef INITSYSTEM ifneq ($(and $(wildcard /lib/systemd/systemd),$(wildcard /run/systemd)),) INITSYSTEM=systemd else ifneq ($(and $(wildcard /sbin/start),$(wildcard /etc/redhat-release)),) # override for rhel/centos to use sysvinit INITSYSTEM=sysvinit else ifneq ($(wildcard /sbin/start),) INITSYSTEM=upstart else ifneq ($(wildcard /sbin/rc-service /usr/sbin/rc-service),) # either INITSYSTEM=openrc else INITSYSTEM=sysvinit endif endif # # basic stuff (unless overwridden by above) # USE_XFRM ?= true USE_XFRM_HEADER_COPY ?= true USE_DNSSEC ?= true ifneq ($(HAVE_NFTABLES), true) HAVE_IPTABLES ?= true endif libreswan-4.14/mk/defaults/netbsd.mk000066400000000000000000000017121457372064200174710ustar00rootroot00000000000000BSD_VARIANT=netbsd # sketch out pkgsrc PKG_BASE ?= /usr/pkg PKG_DBDIR ?= /var/db/pkg PKG_PATH ?= /usr/pkgsrc/packages/All USERLAND_CFLAGS += -DUSE_SOCKADDR_LEN USERLAND_INCLUDES += -I$(PKG_BASE)/include USERLAND_LDFLAGS += -L$(PKG_BASE)/lib -Wl,-rpath,$(PKG_BASE)/lib # NSS includes more than needed in ldflags NSS_LDFLAGS = -L$(PKG_BASE)/lib/nss -Wl,-rpath,$(PKG_BASE)/lib/nss -lnss3 -lfreebl3 -lssl3 NSPR_LDFLAGS = -L$(PKG_BASE)/lib/nspr -Wl,-rpath,$(PKG_BASE)/lib/nspr -lnspr4 CRYPT_LDFLAGS = LIBEVENT_LDFLAGS = -levent -levent_pthreads USE_PFKEYV2 = true USE_LIBCAP_NG = false INITSYSTEM=rc.d USE_DNSSEC = true DEFAULT_DNSSEC_ROOTKEY_FILE = /usr/pkg/etc/unbound/root.key # not /run/pluto FINALRUNDIR=/var/run/pluto # PREFIX = /usr/local from mk/config.mk FINALSYSCONFDIR=$(PREFIX)/etc FINALNSSDIR=$(PREFIX)/etc/ipsec.d FINALEXAMPECONFDIR=$(PREFIX)/share/examples/libreswan FINALMANDIR=$(PREFIX)/man # LTO seems either broken or confused USE_LTO ?= false libreswan-4.14/mk/defaults/openbsd.mk000066400000000000000000000022001457372064200176350ustar00rootroot00000000000000BSD_VARIANT = openbsd # sketch out pkgsrc PKG_BASE ?= /usr/local # See: https://github.com/llvm/llvm-project/issues/55963 # See: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=264288 # See: https://github.com/libreswan/libreswan/issues/735 #CC=gcc WARNING_CFLAGS += -Wno-unused USERLAND_CFLAGS += -DUSE_SOCKADDR_LEN USERLAND_INCLUDES += -I$(PKG_BASE)/include USERLAND_LDFLAGS += -L$(PKG_BASE)/lib -Wl,-rpath,$(PKG_BASE)/lib # NSS includes more than needed in ldflags NSS_LDFLAGS = -L$(PKG_BASE)/lib/nss -Wl,-rpath,$(PKG_BASE)/lib/nss -lnss3 -lfreebl3 -lssl3 NSPR_LDFLAGS = -L$(PKG_BASE)/lib/nspr -Wl,-rpath,$(PKG_BASE)/lib/nspr -lnspr4 USE_PFKEYV2 = true CRYPT_LDFLAGS = RT_LDFLAGS = USE_LIBCAP_NG = false USE_UNBOUND_EVENT_H_COPY = true USE_PTHREAD_SETSCHEDPRIO = false USE_AUTHPAM = false USE_DNSSEC = true DEFAULT_DNSSEC_ROOTKEY_FILE = /var/unbound/db/root.key INITSYSTEM=rc.d # not /run/pluto FINALRUNDIR=/var/run/pluto # PREFIX = /usr/local from mk/config.mk FINALSYSCONFDIR=$(PREFIX)/etc FINALNSSDIR=$(PREFIX)/etc/ipsec.d FINALEXAMPECONFDIR=$(PREFIX)/share/examples/libreswan # LTO seems either broken or confused USE_LTO ?= false libreswan-4.14/mk/dirs.mk000066400000000000000000000123511457372064200153450ustar00rootroot00000000000000# Define autoconf style directory variables, for Libreswan. # # Copyright (C) 2015, 2021 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 # # 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., this file - 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))) abs_top_srcdir := $(abspath $(top_srcdir)) # 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 srcdir := . abs_srcdir := $(abspath $(srcdir)) ifeq ($(patsubst /%,/,$(OBJDIR)),/) # absolute top_builddir := $(OBJDIR) else ifeq ($(top_srcdir),.) # avoid ./OBJDIR top_builddir := $(OBJDIR) else top_builddir := $(top_srcdir)/$(OBJDIR) endif abs_top_builddir := $(abspath $(top_builddir)) # path down from $(top_srcdir); note that PATH_SRCDIR contains a # leading / (else top-level breaks). path_srcdir := $(subst $(abs_top_srcdir),,$(abs_srcdir)) builddir := $(top_builddir)$(path_srcdir) abs_builddir := $(abspath $(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 path_srcdir=$(path_srcdir) @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-4.14/mk/docker-targets.mk000066400000000000000000000232351457372064200173250ustar00rootroot00000000000000# 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 TESTING_DEB_PACKAGES ?= \ bind9utils \ python3-pexpect \ python3-openssl \ python3-distutils 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 ?= 32 # default release D_USE_UNBOUND_EVENT_H_COPY ?= true D_USE_DNSSEC ?= false D_USE_NSS_IPSEC_PROFILE ?= flase D_USE_NSS_AVA_COPY ?= true DOCKERFILE ?= $(D)/dockerfile NOGPGPCHECK ?= false 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), 7) LOCAL_MAKE_FLAGS += USE_XFRM_INTERFACE_IFLA_HEADER=true LOCAL_MAKE_FLAGS += USE_NSS_KDF=false 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 TWEAKS += dnf-nogpgcheck LOCAL_MAKE_FLAGS += USE_FIPSCHECK=false endif MAKE_BASE = base MAKE_INSTLL_BASE = install-base endif ifeq ($(NOGPGPCHECK), true) TWEAKS += dnf-nogpgcheck 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: dnf-nogpgcheck dnf-nogpgcheck: $(shell sed -i 's/dnf install -y /dnf install --nogpgcheck -y /' testing/docker/dockerfile) $(shell sed -i 's/dnf update -y/dnf update -y --nogpgcheck /' 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-testing-deb-dep install-testing-deb-dep: install-deb-dep apt-get update $(if $(TESTING_DEB_PACKAGES), apt-get install -y --no-install-recommends \ $(TESTING_DEB_PACKAGES)) .PHONY: install-deb-dep # only for buster and older DEV_BUSTER_DEB ?= $$(grep -qE 'buster' /etc/os-release && echo "dh-systemd ") 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 $(DEV_BUSTER_DEB) # 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: docker-build docker-build: dockerfile # --volume is only in podman $(DOCKER_CMD) build -t $(DI_T) --volume $(PWD):/home/build/libreswan -f $(DOCKERFILE) . # for docker # $(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 targets 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 .PHONY: nsreinstall nsreinstall: $(MAKE) INITSYSTEM=docker DOCKER_PLUTONOFORK= base sudo $(MAKE) INITSYSTEM=docker DOCKER_PLUTONOFORK= install-base libreswan-4.14/mk/find.sh000077500000000000000000000021261457372064200153310ustar00rootroot00000000000000#!/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/contrib" -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 '*.in' -print \ -o -type f -name '*.[chly]' -print } if test $# -gt 0 ; then look | xargs grep -n "$@" else look fi libreswan-4.14/mk/kvm-targets.mk000066400000000000000000001423331457372064200166540ustar00rootroot00000000000000# KVM make targets, for Libreswan # # Copyright (C) 2015-2022 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 '$*' (why not $%!?!?!, because that was used for archives). # It is used to extract the DOMAIN from targets like # kvm-install-DOMAIN. empty = comma = , sp = $(empty) $(empty) # the first blank line is ignored define crlf endef # # The guest operating system. # include testing/libvirt/fedora/fedora.mk include testing/libvirt/freebsd/freebsd.mk include testing/libvirt/netbsd/netbsd.mk include testing/libvirt/openbsd/openbsd.mk # # where things live and what gets created # # can be a separate directories 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_PYTHON ?= PYTHONPATH=/home/python/pexpect:/home/python/ptyprocess /home/python/v3.8/bin/python3 KVM_PIDFILE ?= kvmrunner.pid # Current user's UID; and GID used by QEMU KVM_UID ?= $(shell id -u) KVM_GID ?= $(shell stat --format=%g $(KVM_HOST_QEMUDIR)) KVM_TRANSMOGRIFY = \ sed \ -e 's;@@GATEWAY@@;$(KVM_GATEWAY_ADDRESS);' \ -e 's;@@POOLDIR@@;$(KVM_POOLDIR);' \ -e 's;@@SOURCEDIR@@;$(KVM_SOURCEDIR);' \ -e 's;@@LOCALDIR@@;$(KVM_LOCALDIR);' \ -e 's;@@TESTINGDIR@@;$(KVM_TESTINGDIR);' \ -e 's;@@USER@@;$(KVM_UID);' \ -e 's;@@GROUP@@;$(KVM_GID);' \ -e 's;@@PREFIX@@;$(KVM_FIRST_PREFIX);' # 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) # # Makeflags passed to the KVM build # # Note that $($*) in KVM_MAKEFLAGS expands to DEBIAN, FEDORA, FREEBSD, # NETBSD, OPENBSD, ... so that each platform has their own flags. # For instance: # # KVM_$($*)_NSS_CFLAGS # # becomes: # # KVM_FEDORA_NSS_CFLAGS KVM_FREEBSD_NSS_CFLAGS et.al. KVM_ALL_ALGS ?= false # On Fedora, overide linux defaults KVM_FEDORA_FINALNSSDIR ?= $(FINALCONFDIR)/ipsec.d KVM_FEDORA_SD_RESTART_TYPE ?= no KVM_FEDORA_USE_EFENCE ?= true KVM_FEDORA_USE_LABELED_IPSEC ?= true KVM_FEDORA_USE_SECCOMP ?= true KVM_MAKEFLAGS ?= \ -j$(shell expr $(KVM_WORKERS) + 1) \ $(if $(KVM_ALL_ALGS),ALL_ALGS=$(KVM_ALL_ALGS)) \ $(if $(KVM_$($*)_FINALNSSDIR),FINALNSSDIR="$(KVM_$($*)_FINALNSSDIR)") \ $(if $(KVM_$($*)_NSS_CFLAGS),NSS_CFLAGS="$(KVM_$($*)_NSS_CFLAGS)") \ $(if $(KVM_$($*)_NSS_LDFLAGS),NSS_LDFLAGS="$(KVM_$($*)_NSS_LDFLAGS)") \ $(if $(KVM_$($*)_SD_RESTART_TYPE),SD_RESTART_TYPE="$(KVM_$($*)_SD_RESTART_TYPE)") \ $(if $(KVM_$($*)_USE_EFENCE),USE_EFENCE="$(KVM_$($*)_USE_EFENCE)") \ $(if $(KVM_$($*)_USE_LABELED_IPSEC),USE_LABELED_IPSEC="$(KVM_$($*)_USE_LABELED_IPSEC)") \ $(if $(KVM_$($*)_USE_LTO),USE_LTO="$(KVM_$($*)_USE_LTO)") \ $(if $(KVM_$($*)_USE_NSS_KDF),USE_NSS_KDF="$(KVM_$($*)_USE_NSS_KDF)") \ $(if $(KVM_$($*)_USE_SECCOMP),USE_SECCOMP="$(KVM_$($*)_USE_SECCOMP)") \ $(NULL) # Fine-tune the BASE and BUILD machines. # # BASE is kept small. # # BUILD is more complex: # # CPUs: so as to not over allocate host cores, stick with # $(KVM_WORKERS) (default 1). The heuristic is to set $(KVM_WORKERS) # to #cores/2 - as it seems that a [booting] machine ties up two # cores. # # Memory: a test typically requires two 512mb VMs. With $(KVM_WORKERS) # that makes at least $(KVM_WORKERS)*2*512mb of ram being used by # tests VMs. Boost build's memory by that amount. # # XXX: Ignore KVM_PREFIXES, it is probably going away. VIRT_INSTALL ?= sudo virt-install VIRT_CPU ?= --cpu=host-passthrough VIRT_DISK_SIZE_GB ?= 10 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_POOLDIR ?= --filesystem=target=pool,type=mount,accessmode=squash,source=$(KVM_POOLDIR) VIRT_SOURCEDIR ?= --filesystem=target=source,type=mount,accessmode=squash,source=$(KVM_SOURCEDIR) VIRT_TESTINGDIR ?= --filesystem=target=testing,type=mount,accessmode=squash,source=$(KVM_TESTINGDIR) VIRT_INSTALL_FLAGS = \ --connect=$(KVM_CONNECTION) \ --check=path_in_use=off \ --graphics=none \ --virt-type=kvm \ --noreboot \ --console=pty,target_type=serial \ --vcpus=$(KVM_WORKERS) \ --memory=$(shell expr 1024 + $(KVM_WORKERS) \* 2 \* 512) \ $(VIRT_CPUS) \ $(VIRT_CPU) \ $(VIRT_GATEWAY) \ $(VIRT_RND) \ $(VIRT_SECURITY) \ $(VIRT_POOLDIR) # # Platforms / OSs # # To disable an OS use something like: # KVM_OPENBSD= # NOT ...=false KVM_DEBIAN ?= KVM_FEDORA ?= true KVM_FREEBSD ?= KVM_NETBSD ?= KVM_OPENBSD ?= # so that $($*) converts % to upper case debian = DEBIAN fedora = FEDORA freebsd = FREEBSD netbsd = NETBSD openbsd = OPENBSD # this is what could work #KVM_PLATFORM += debian KVM_PLATFORM += fedora KVM_PLATFORM += freebsd KVM_PLATFORM += netbsd KVM_PLATFORM += openbsd # this is what is enabled KVM_OS += $(if $(KVM_DEBIAN), debian) KVM_OS += $(if $(KVM_FEDORA), fedora) KVM_OS += $(if $(KVM_FREEBSD), freebsd) KVM_OS += $(if $(KVM_NETBSD), netbsd) KVM_OS += $(if $(KVM_OPENBSD), openbsd) # fed into virt-install --os-variant KVM_DEBIAN_OS_VARIANT ?= $(shell osinfo-query os | awk '/debian[1-9]/ {print $$1}' | sort -V | tail -1) KVM_FEDORA_OS_VARIANT ?= $(shell osinfo-query os | awk '/fedora[1-9]/ {print $$1}' | sort -V | tail -1) KVM_FREEBSD_OS_VARIANT ?= $(shell osinfo-query os | awk '/freebsd[1-9]/ {print $$1}' | sort -V | tail -1) KVM_NETBSD_OS_VARIANT ?= $(shell osinfo-query os | awk '/netbsd[1-9]/ {print $$1}' | sort -V | tail -1) KVM_OPENBSD_OS_VARIANT ?= $(shell osinfo-query os | awk '/openbsd[1-9]/ {print $$1}' | sort -V | tail -1) # # Hosts # KVM_DEBIAN_HOST_NAMES = debiane debianw KVM_FEDORA_HOST_NAMES = east west north road nic fipse fipsw KVM_FREEBSD_HOST_NAMES = freebsde freebsdw KVM_NETBSD_HOST_NAMES = netbsde netbsdw KVM_OPENBSD_HOST_NAMES = openbsde openbsdw KVM_TEST_HOST_NAMES = $(foreach os, $(KVM_OS), $(KVM_$($(os))_HOST_NAMES)) KVM_BUILD_HOST_NAMES += $(foreach os, $(KVM_OS), $(os)) KVM_BUILD_HOST_NAMES += $(foreach os, $(KVM_OS), $(os)-base) KVM_BUILD_HOST_NAMES += $(foreach os, $(KVM_OS), $(os)-upgrade) KVM_HOST_NAMES = $(KVM_TEST_HOST_NAMES) $(KVM_BUILD_HOST_NAMES) # # Domains # # 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))) # targets for dumping the above .PHONY: print-kvm-prefixes print-kvm-prefixes: ; @echo '$(KVM_PREFIXES)' .PHONY: print-kvm-test-status print-kvm-test-status: ; @echo '$(STRIPPED_KVM_TEST_STATUS)' .PHONY: print-kvm-test-flags print-kvm-test-flags: ; @echo '$(KVM_TEST_FLAGS)' .PHONY: print-kvm-testingdir print-kvm-testingdir: ; @echo '$(KVM_TESTINGDIR)' .PHONY: print-kvm-baseline print-kvm-baseline: ; @echo '$(KVM_BASELINE)' KVM_BUILD_DOMAIN_NAMES = $(addprefix $(KVM_FIRST_PREFIX), $(KVM_BUILD_HOST_NAMES)) KVM_TEST_DOMAIN_NAMES = $(call add-kvm-prefixes, $(KVM_TEST_HOST_NAMES)) KVM_DOMAIN_NAMES = $(sort $(KVM_TEST_DOMAIN_NAMES) $(KVM_BUILD_DOMAIN_NAMES)) KVM_POOLDIR_PREFIX = $(KVM_POOLDIR)/$(KVM_FIRST_PREFIX) KVM_LOCALDIR_PREFIXES = \ $(call strip-prefix, \ $(foreach prefix, $(KVM_PREFIXES), \ $(addprefix $(KVM_LOCALDIR)/, $(prefix)))) add-kvm-localdir-prefixes = \ $(foreach prefix, $(KVM_LOCALDIR_PREFIXES), \ $(patsubst %, $(prefix)%, $(1))) KVM_BUILD_DOMAINS = $(addprefix $(KVM_POOLDIR)/, $(KVM_BUILD_DOMAIN_NAMES)) KVM_TEST_DOMAINS = $(addprefix $(KVM_LOCALDIR)/, $(KVM_TEST_DOMAIN_NAMES)) KVM_PLATFORM_BUILD_HOST_NAMES += $(foreach platform, $(KVM_PLATFORM), $(platform)) KVM_PLATFORM_BUILD_HOST_NAMES += $(foreach platform, $(KVM_PLATFORM), $(platform)-base) KVM_PLATFORM_BUILD_HOST_NAMES += $(foreach platform, $(KVM_PLATFORM), $(platform)-upgrade) KVM_PLATFORM_TEST_HOST_NAMES += $(foreach platform, $(KVM_PLATFORM), $(KVM_$($(platform))_HOST_NAMES)) KVM_PLATFORM_BUILD_DOMAIN_NAMES = $(addprefix $(KVM_FIRST_PREFIX), $(KVM_PLATFORM_BUILD_HOST_NAMES)) KVM_PLATFORM_TEST_DOMAIN_NAMES = $(call add-kvm-prefixes, $(KVM_PLATFORM_TEST_HOST_NAMES)) KVM_PLATFORM_DOMAIN_NAMES = $(KVM_PLATFORM_BUILD_DOMAIN_NAMES) $(KVM_PLATFORM_TEST_DOMAIN_NAMES) # # Other utilities and directories # QEMU_IMG ?= sudo qemu-img KVMSH ?= $(KVM_PYTHON) testing/utils/kvmsh.py KVMRUNNER ?= $(KVM_PYTHON) testing/utils/kvmrunner.py KVMRESULTS ?= $(KVM_PYTHON) testing/utils/kvmresults.py KVMTEST ?= $(KVM_PYTHON) testing/utils/kvmtest.py RPM_VERSION = $(shell $(MAKE) --no-print-directory showrpmversion) RPM_PREFIX = libreswan-$(RPM_VERSION) RPM_BUILD_CLEAN ?= --rmsource --rmspec --clean # # Detect a fresh boot of the host machine. Use this as a dependency # for actions that should only be run once after each boot. # # The first time $(MAKE) is run after a boot, this file is touched, # any further rules leave the file alone. # KVM_FRESH_BOOT_FILE = $(KVM_POOLDIR_PREFIX)boot.ok $(KVM_FRESH_BOOT_FILE): $(firstword $(wildcard /var/run/rc.log /var/log/boot.log)) | $(KVM_LOCALDIR) touch $@ # # Check that there is enough entoropy for running the domains. # # Only do this once per boot. # KVM_HOST_ENTROPY_FILE ?= /proc/sys/kernel/random/entropy_avail KVM_HOST_ENTROPY_OK = $(KVM_POOLDIR_PREFIX)entropy.ok $(KVM_HOST_ENTROPY_OK): $(KVM_FRESH_BOOT_FILE) $(KVM_HOST_ENTROPY_OK): | $(KVM_POOLDIR) @if test ! -r $(KVM_HOST_ENTROPY_FILE); then \ echo no entropy to check ; \ elif test $$(cat $(KVM_HOST_ENTROPY_FILE)) -gt 100 ; then \ echo lots of entropy ; \ else \ echo ; \ echo According to: \ echo ; \ echo $(KVM_HOST_ENTROPY_FILE) ; \ echo ; \ echo your computer does not have much entropy ; \ echo ; \ echo Check the wiki for hints on how to fix this. ; \ echo ; \ false ; \ fi touch $@ KVM_HOST_OK += $(KVM_HOST_ENTROPY_OK) # # Check that the QEMUDIR is writeable by us. # # (assumes that the machine is rebooted after a qemu update) # KVM_HOST_QEMUDIR ?= /var/lib/libvirt/qemu KVM_HOST_QEMUDIR_OK = $(KVM_POOLDIR_PREFIX)qemudir.ok $(KVM_HOST_QEMUDIR_OK): $(KVM_FRESH_BOOT_FILE) $(KVM_HOST_QEMUDIR_OK): | $(KVM_POOLDIR) $(KVM_HOST_QEMUDIR_OK): | $(KVM_POOLDIR) @if ! test -w $(KVM_HOST_QEMUDIR) ; then \ echo ; \ echo " The directory:" ; \ echo ; \ echo " $(KVM_HOST_QEMUDIR) (KVM_HOST_QEMUDIR)" ; \ echo ; \ echo " is not writeable vis:" ; \ echo ; \ echo -n " " ; ls -ld $(KVM_HOST_QEMUDIR) ; \ echo ; \ echo " This will break virsh which is" ; \ echo " used to manipulate the domains." ; \ echo ; \ false ; \ fi touch $@ KVM_HOST_OK += $(KVM_HOST_QEMUDIR_OK) # # ensure that NFS is running and everything is exported # KVM_HOST_NFS_OK = $(KVM_POOLDIR_PREFIX)nfs.ok $(KVM_HOST_NFS_OK): testing/libvirt/nfs.sh $(KVM_HOST_NFS_OK): $(KVM_FRESH_BOOT_FILE) $(KVM_HOST_NFS_OK): | $(KVM_POOLDIR) sh testing/libvirt/nfs.sh $(KVM_POOLDIR) $(KVM_SOURCEDIR) $(KVM_TESTINGDIR) touch $@ KVM_HOST_OK += $(KVM_HOST_NFS_OK) # # 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 ?= $(KVM_TESTINGDIR)/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-ok and not kvm-keys or $(KVM_KEYS) so that the # check that the keys are up-to-date is run. # # - need build domains shutdown as, otherwise, test domains can refuse # to boot because the domain they were cloned from is still running. # 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)) # Allow any of 'KVM_TEST_STATUS=good|wip', 'KVM_TEST_STATUS=good wip', # or KVM_TEST_STATUS+=wip. KVM_TEST_STATUS += good KVM_TEST_STATUS += $(if $(KVM_FREEBSD),freebsd) KVM_TEST_STATUS += $(if $(KVM_NETBSD),netbsd) KVM_TEST_STATUS += $(if $(KVM_OPENBSD),openbsd) STRIPPED_KVM_TEST_STATUS = $(subst $(sp),|,$(sort $(KVM_TEST_STATUS))) kvm-test kvm-check kvm-retest kvm-recheck: \ kvm-%: $(KVM_HOST_OK) kvm-keys-ok : shutdown all the build domains, kvmrunner shuts down the test domains $(foreach domain, $(KVM_BUILD_DOMAINS), $(call shutdown-os-domain, $(domain))) @$(MAKE) $(if $(WEB_ENABLED), web-test-prep, -s web-pages-disabled) : 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)) \ $(if $(WEB_ENABLED), --publish-results $(WEB_RESULTSDIR)) \ $(if $(WEB_ENABLED), --publish-status $(WEB_SUMMARYDIR)/status.json) \ --test-status '$(STRIPPED_KVM_TEST_STATUS)' \ $(if $(filter kvm-re%, $@), --skip passed) \ $(KVMRUNNER_FLAGS) \ $(KVM_TEST_FLAGS) \ $(STRIPPED_KVM_TESTS) @$(MAKE) $(if $(WEB_ENABLED), web-test-post, -s web-pages-disabled) # clean up; accept pretty much everything KVM_TEST_CLEAN_TARGETS = kvm-clean-check kvm-check-clean kvm-clean-test kvm-test-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) $(KVMRESULTS_FLAGS) $(KVM_TEST_FLAGS) $(STRIPPED_KVM_TESTS) $(if $(KVM_BASELINE),--baseline $(KVM_BASELINE)) .PHONY: kvm-diffs kvm-diffs: $(KVMRESULTS) $(KVMRESULTS_FLAGS) $(KVM_TEST_FLAGS) $(STRIPPED_KVM_TESTS) $(if $(KVM_BASELINE),--baseline $(KVM_BASELINE)) --print diffs # # 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 directly depend on the # phony target kvm-shutdown 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. # file to mark keys are up-to-date KVM_KEYS = $(KVM_TESTINGDIR)/x509/keys/up-to-date KVM_KEYS_EXPIRATION_DAY = 7 KVM_KEYS_EXPIRED = find testing/x509/*/ -type f -mtime +$(KVM_KEYS_EXPIRATION_DAY) -ls KVM_KEYS_DOMAIN = $(addprefix $(KVM_FIRST_PREFIX), fedora) .PHONY: kvm-keys kvm-keys: : invoke phony target to shut things down and delete old keys $(MAKE) kvm-shutdown $(MAKE) kvm-clean-keys $(MAKE) $(KVM_KEYS) $(KVM_KEYS): $(KVM_TESTINGDIR)/x509/dist_certs.py $(KVM_KEYS): $(KVM_TESTINGDIR)/x509/openssl.cnf $(KVM_KEYS): $(KVM_TESTINGDIR)/x509/strongswan-ec-gen.sh $(KVM_KEYS): $(KVM_TESTINGDIR)/baseconfigs/all/etc/bind/generate-dnssec.sh $(KVM_KEYS): | $(KVM_POOLDIR)/$(KVM_KEYS_DOMAIN) $(KVM_KEYS): | $(KVM_HOST_OK) : : disable FIPS : $(KVMSH) --chdir /testing $(KVM_KEYS_DOMAIN) rm -f /etc/system-fips $(KVMSH) --chdir /testing $(KVM_KEYS_DOMAIN) guestbin/fipsoff : : Copy the scripts to the empty /tmp/x509 directory : $(KVMSH) --chdir /testing $(KVM_KEYS_DOMAIN) rm -rf /tmp/x509 $(KVMSH) --chdir /testing $(KVM_KEYS_DOMAIN) mkdir /tmp/x509 $(KVMSH) --chdir /testing $(KVM_KEYS_DOMAIN) cp -f x509/dist_certs.py /tmp/x509 $(KVMSH) --chdir /testing $(KVM_KEYS_DOMAIN) cp -f x509/openssl.cnf /tmp/x509 $(KVMSH) --chdir /testing $(KVM_KEYS_DOMAIN) cp -f x509/strongswan-ec-gen.sh /tmp/x509 : : run key scripts in /tmp/x509 : $(KVMSH) --chdir /tmp/x509 $(KVM_KEYS_DOMAIN) ./dist_certs.py $(KVMSH) --chdir /tmp/x509 $(KVM_KEYS_DOMAIN) ./strongswan-ec-gen.sh : : copy the certs from guest to host in a tar ball to avoid 9fs bug : rm -f $(KVM_POOLDIR_PREFIX)kvm-keys.tar $(KVMSH) --chdir /tmp/x509 $(KVM_KEYS_DOMAIN) tar cf kvm-keys.tar '*/' nss-pw $(KVMSH) --chdir /tmp/x509 $(KVM_KEYS_DOMAIN) cp kvm-keys.tar /pool/$(KVM_FIRST_PREFIX)kvm-keys.tar cd $(KVM_TESTINGDIR)/x509 && tar xf $(KVM_POOLDIR_PREFIX)kvm-keys.tar rm -f $(KVM_POOLDIR_PREFIX)kvm-keys.tar : : Also regenerate the DNSSEC keys : $(KVMSH) --chdir /testing $(KVM_KEYS_DOMAIN) ./baseconfigs/all/etc/bind/generate-dnssec.sh : : All done. : $(KVMSH) --shutdown $(KVM_KEYS_DOMAIN) touch $@ .PHONY: kvm-clean-keys kvm-keys-clean kvm-clean-keys kvm-keys-clean: : careful output mixed with repo files rm -rf $(KVM_TESTINGDIR)/x509/*/ rm -f $(KVM_TESTINGDIR)/x509/nss-pw rm -f $(KVM_TESTINGDIR)/baseconfigs/all/etc/bind/signed/*.signed rm -f $(KVM_TESTINGDIR)/baseconfigs/all/etc/bind/keys/*.key rm -f $(KVM_TESTINGDIR)/baseconfigs/all/etc/bind/keys/*.private rm -f $(KVM_TESTINGDIR)/baseconfigs/all/etc/bind/dsset/dsset-* rm -f $(KVM_POOLDIR_PREFIX)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 # # 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 file=$(strip $(1)) : $(VIRSH) net-define $(1) $(VIRSH) net-autostart $(basename $(notdir $(1))) $(VIRSH) net-start $(basename $(notdir $(1))) endef define destroy-kvm-network : destroy-kvm-network network=$(strip $(1)) if $(VIRSH) net-info '$(basename $(notdir $(1)))' 2>/dev/null | grep 'Active:.*yes' > /dev/null ; then \ $(VIRSH) net-destroy '$(basename $(notdir $(1)))' ; \ fi if $(VIRSH) net-info '$(basename $(notdir $(1)))' >/dev/null 2>&1 ; then \ $(VIRSH) net-undefine '$(basename $(notdir $(1)))' ; \ fi rm -f $(1) endef # # The Gateway # # Because the gateway is created directly from libvirt/swandefault and # that file contains hardwired IP addresses, but 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. # 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 KVM_GATEWAY_ADDRESS ?= 192.168.234.1 KVM_GATEWAY_FILE = $(KVM_POOLDIR)/$(KVM_GATEWAY).gw $(KVM_POOLDIR)/$(KVM_GATEWAY).gw: | testing/libvirt/net/$(KVM_GATEWAY) $(KVM_POOLDIR)/$(KVM_GATEWAY).gw: | $(KVM_POOLDIR) $(call destroy-kvm-network, $@) $(call create-kvm-network, testing/libvirt/net/$(KVM_GATEWAY)) touch $@ # # 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 = $(addsuffix .net, $(call add-kvm-localdir-prefixes, $(KVM_TEST_SUBNETS))) .PRECIOUS: $(KVM_TEST_NETWORKS) # .net; if is blank call it swan* KVM_BRIDGE_NAME = $(strip $(if $(patsubst 192_%,,$*), \ $*, \ swan$(subst _,,$(patsubst %192_,,$*)))) $(KVM_LOCALDIR)/%.net: | $(KVM_LOCALDIR) $(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' : rename .net.tmp to .tmp mv $@.tmp $(basename $@).tmp $(call create-kvm-network, $(basename $@).tmp) mv $(basename $@).tmp $@ .PHONY: kvm-networks kvm-gateway kvm-gateway: $(KVM_GATEWAY_FILE) kvm-networks: $(KVM_TEST_NETWORKS) .PHONY: kvm-uninstall-networks kvm-uninstall-gateway kvm-uninstall-networks: $(foreach network, $(KVM_TEST_NETWORKS), \ $(call destroy-kvm-network, $(network))) kvm-uninstall-gateway: $(call destroy-kvm-network, $(KVM_GATEWAY_FILE)) ## ## ## Build the base domains ## ## .PHONY: kvm-base kvm-base: $(patsubst %, kvm-base-%, $(KVM_OS)) $(patsubst %, kvm-base-%, $(KVM_PLATFORM)): \ kvm-base-%: rm -f $(KVM_POOLDIR_PREFIX)$(*)-base rm -f $(KVM_POOLDIR_PREFIX)$(*)-base.* $(MAKE) $(KVM_POOLDIR_PREFIX)$(*)-base $(patsubst %, $(KVM_POOLDIR_PREFIX)%-base, $(KVM_PLATFORM)): \ $(KVM_POOLDIR_PREFIX)%-base: | \ testing/libvirt/%/base.py \ $(KVM_POOLDIR) \ $(KVM_HOST_OK) \ $(KVM_GATEWAY_FILE) : clean up old domains $(MAKE) kvm-undefine-$(notdir $@) : use script to drive build of new domain DOMAIN=$(notdir $@) \ GATEWAY=$(KVM_GATEWAY_ADDRESS) \ POOLDIR=$(KVM_POOLDIR) \ $(KVM_PYTHON) testing/libvirt/$*/base.py \ $(VIRT_INSTALL) \ $(VIRT_INSTALL_FLAGS) \ --name=$(notdir $@) \ $(if $(KVM_$($*)_OS_VARIANT), --os-variant=$(KVM_$($*)_OS_VARIANT)) \ --disk=path=$@.qcow2,size=$(VIRT_DISK_SIZE_GB),bus=virtio,format=qcow2 \ $(KVM_$($*)_VIRT_INSTALL_FLAGS) : : Check that the shell prompt includes the exit code. : : KVMSH uses the prompt exit code to determine the status of : the last command run vis: : : [user@host pwd]# false : [user@host pwd 1]# true : [user@host pwd]# : $(KVMSH) $(notdir $@) -- true ! $(KVMSH) $(notdir $@) -- false : : Check that /pool - KVM_POOLDIR - is mounted. : : The package install, upgrade, and transmogrify scripts : are copied to and then run from that directory. : $(KVMSH) $(notdir $@) -- test -r /pool/$(notdir $@).qcow2 : : Check that /source and /testing directories are not present. : : The /source and /testing directories are set up by transmogrify. : They can change and may not point into this directory tree. : Delaying their creation hopefully makes it harder to accidently : access the wrong files. : $(KVMSH) $(notdir $@) -- test ! -d /source -a ! -d /testing : : Everything seems to be working, shut down. : $(KVMSH) --shutdown $(notdir $@) touch $@ .PHONY: kvm-iso # # Fedora # # - since kickstart is used this is pretty straight forward # KVM_FEDORA_ISO_URL ?= https://download.fedoraproject.org/pub/fedora/linux/releases/35/Server/x86_64/iso/Fedora-Server-dvd-x86_64-35-1.2.iso KVM_FEDORA_KICKSTART_FILE ?= testing/libvirt/fedora/base.ks KVM_FEDORA_ISO = $(KVM_POOLDIR)/$(notdir $(KVM_FEDORA_ISO_URL)) kvm-iso: $(KVM_FEDORA_ISO) $(KVM_FEDORA_ISO): | $(KVM_POOLDIR) wget --output-document $@.tmp --no-clobber -- $(KVM_FEDORA_ISO_URL) mv $@.tmp $@ KVM_FEDORA_BASE_DOMAIN = $(KVM_POOLDIR_PREFIX)fedora-base KVM_FEDORA_VIRT_INSTALL_FLAGS = \ --location=$(KVM_FEDORA_ISO) \ --initrd-inject=$(KVM_FEDORA_KICKSTART_FILE) \ --extra-args="inst.ks=file:/$(notdir $(KVM_FEDORA_KICKSTART_FILE)) console=ttyS0,115200 net.ifnames=0 biosdevname=0" $(KVM_FEDORA_BASE_DOMAIN): | $(KVM_FEDORA_ISO) $(KVM_FEDORA_BASE_DOMAIN): | $(KVM_FEDORA_KICKSTART_FILE) # # FreeBSD # # - uses a modified install CD # KVM_FREEBSD_ISO_URL ?= https://download.freebsd.org/releases/amd64/amd64/ISO-IMAGES/13.0/FreeBSD-13.0-RELEASE-amd64-disc1.iso # 13.1 installer barfs with: # /usr/libexec/bsdinstall/script: 3: Bad file descriptor # See https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=266802 KVM_FREEBSD_ISO_URL ?= https://download.freebsd.org/releases/amd64/amd64/ISO-IMAGES/13.1/FreeBSD-13.1-RELEASE-amd64-disc1.iso KVM_FREEBSD_ISO ?= $(KVM_POOLDIR)/$(notdir $(KVM_FREEBSD_ISO_URL)) kvm-iso: $(KVM_FREEBSD_ISO) # For FreeBSD, download the compressed ISO $(KVM_FREEBSD_ISO): | $(KVM_POOLDIR) wget --output-document $@.xz --no-clobber -- $(KVM_FREEBSD_ISO_URL).xz xz --uncompress --keep $@.xz KVM_FREEBSD_BASE_DOMAIN = $(KVM_POOLDIR_PREFIX)freebsd-base KVM_FREEBSD_BASE_ISO = $(KVM_FREEBSD_BASE_DOMAIN).iso KVM_FREEBSD_VIRT_INSTALL_FLAGS = \ --cdrom=$(KVM_FREEBSD_BASE_ISO) $(KVM_FREEBSD_BASE_DOMAIN): | $(KVM_FREEBSD_BASE_ISO) $(KVM_FREEBSD_BASE_ISO): $(KVM_FREEBSD_ISO) $(KVM_FREEBSD_BASE_ISO): testing/libvirt/freebsd/loader.conf $(KVM_FREEBSD_BASE_ISO): testing/libvirt/freebsd/base.conf cp $(KVM_FREEBSD_ISO) $@.tmp $(KVM_TRANSMOGRIFY) \ testing/libvirt/freebsd/base.conf \ > $(KVM_FREEBSD_BASE_DOMAIN).base.conf growisofs -M $@.tmp -l -R \ -input-charset utf-8 \ -graft-points \ /boot/loader.conf=testing/libvirt/freebsd/loader.conf \ /etc/installerconfig=$(KVM_FREEBSD_BASE_DOMAIN).base.conf mv $@.tmp $@ # # NetBSD # # - needs a second serial console boot iso # KVM_NETBSD_BOOT_ISO_URL ?= https://cdn.netbsd.org/pub/NetBSD/NetBSD-9.3/i386/installation/cdrom/boot-com.iso KVM_NETBSD_BOOT_ISO ?= $(basename $(KVM_NETBSD_INSTALL_ISO))-boot.iso KVM_NETBSD_INSTALL_ISO_URL ?= https://cdn.netbsd.org/pub/NetBSD/NetBSD-9.3/images/NetBSD-9.2-i386.iso KVM_NETBSD_INSTALL_ISO ?= $(KVM_POOLDIR)/$(notdir $(KVM_NETBSD_INSTALL_ISO_URL)) kvm-iso: $(KVM_NETBSD_BOOT_ISO) kvm-iso: $(KVM_NETBSD_INSTALL_ISO) $(KVM_NETBSD_INSTALL_ISO): | $(KVM_POOLDIR) wget --output-document $@.tmp --no-clobber -- $(KVM_NETBSD_INSTALL_ISO_URL) mv $@.tmp $@ $(KVM_NETBSD_BOOT_ISO): | $(KVM_POOLDIR) wget --output-document $@.tmp --no-clobber -- $(KVM_NETBSD_BOOT_ISO_URL) mv $@.tmp $@ KVM_NETBSD_BASE_DOMAIN = $(KVM_POOLDIR_PREFIX)netbsd-base KVM_NETBSD_BASE_ISO = $(KVM_NETBSD_BASE_DOMAIN).iso KVM_NETBSD_VIRT_INSTALL_FLAGS = \ --cdrom=$(KVM_NETBSD_BOOT_ISO) \ --disk=path=$(KVM_NETBSD_BASE_ISO),readonly=on,device=cdrom $(KVM_NETBSD_BASE_DOMAIN): | $(KVM_NETBSD_BOOT_ISO) $(KVM_NETBSD_BASE_DOMAIN): | $(KVM_NETBSD_BASE_ISO) $(KVM_NETBSD_BASE_ISO): $(KVM_NETBSD_INSTALL_ISO) $(KVM_NETBSD_BASE_ISO): testing/libvirt/netbsd/base.sh cp $(KVM_NETBSD_INSTALL_ISO) $@.tmp $(KVM_TRANSMOGRIFY) \ testing/libvirt/netbsd/base.sh \ > $(KVM_NETBSD_BASE_DOMAIN).base.sh : this mangles file/directory names growisofs -M $@.tmp -l \ -input-charset utf-8 \ -graft-points \ /base.sh=$(KVM_NETBSD_BASE_DOMAIN).base.sh mv $@.tmp $@ # # OpenBSD # # - the downloaded ISO needs mangling # - sources are in separate tarballs # # Give the OpenBSD ISO a meaningful name. KVM_OPENBSD_URL ?= https://cdn.openbsd.org/pub/OpenBSD/7.1 KVM_OPENBSD_ISO_URL ?= $(KVM_OPENBSD_URL)/amd64/install71.iso KVM_OPENBSD_SRC_URL += $(KVM_OPENBSD_URL)/src.tar.gz KVM_OPENBSD_SRC_URL += $(KVM_OPENBSD_URL)/sys.tar.gz # not openbsd... as gets deleted by rm openbsd.* KVM_OPENBSD_POOLPREFIX = $(KVM_POOLDIR)/OpenBSD-$(notdir $(KVM_OPENBSD_URL)) KVM_OPENBSD_ISO = $(KVM_OPENBSD_POOLPREFIX)-install.iso KVM_OPENBSD_SRC_TGZ = $(addprefix $(KVM_OPENBSD_POOLPREFIX)-, $(notdir $(KVM_OPENBSD_SRC_URL))) kvm-iso: $(KVM_OPENBSD_ISO) $(KVM_OPENBSD_ISO): | $(KVM_POOLDIR) wget --output-document $@.tmp --no-clobber -- $(KVM_OPENBSD_ISO_URL) mv $@.tmp $@ kvm-iso: $(KVM_OPENBSD_SRC_TGZ) $(KVM_OPENBSD_SRC_TGZ): \ $(KVM_OPENBSD_POOLPREFIX)-%: | $(KVM_POOLDIR) wget --output-document $@.tmp --no-clobber -- $(KVM_OPENBSD_URL)/$(*) mv $@.tmp $@ KVM_OPENBSD_BASE_DOMAIN = $(KVM_POOLDIR_PREFIX)openbsd-base KVM_OPENBSD_BASE_ISO = $(KVM_OPENBSD_BASE_DOMAIN).iso KVM_OPENBSD_VIRT_INSTALL_FLAGS = --cdrom=$(KVM_OPENBSD_BASE_ISO) $(KVM_OPENBSD_BASE_DOMAIN): | $(KVM_OPENBSD_BASE_ISO) kvm-iso: $(KVM_OPENBSD_BASE_ISO) $(KVM_OPENBSD_BASE_ISO): $(KVM_OPENBSD_ISO) $(KVM_OPENBSD_BASE_ISO): $(KVM_OPENBSD_SRC_TGZ) $(KVM_OPENBSD_BASE_ISO): testing/libvirt/openbsd/base.conf $(KVM_OPENBSD_BASE_ISO): testing/libvirt/openbsd/boot.conf $(KVM_OPENBSD_BASE_ISO): testing/libvirt/openbsd/base.sh $(KVM_OPENBSD_BASE_ISO): testing/libvirt/openbsd/base.disk cp $(KVM_OPENBSD_ISO) $@.tmp $(KVM_TRANSMOGRIFY) \ testing/libvirt/openbsd/base.sh \ > $(KVM_OPENBSD_BASE_DOMAIN).base.sh : boot.conf sets up a serial console : base.conf configures the installer : base.sh gets run by base.py after boot growisofs -M $@.tmp -l -R \ -input-charset utf-8 \ -graft-points \ /base.conf="testing/libvirt/openbsd/base.conf" \ /etc/boot.conf="testing/libvirt/openbsd/boot.conf" \ /base.sh=$(KVM_OPENBSD_BASE_DOMAIN).base.sh \ /base.disk=testing/libvirt/openbsd/base.disk \ /src.tar.gz=$(KVM_OPENBSD_POOLPREFIX)-src.tar.gz \ /sys.tar.gz=$(KVM_OPENBSD_POOLPREFIX)-sys.tar.gz mv $@.tmp $@ ## ## Upgrade the base domain: create a clone, install any missing ## packages and upgrade any packages that are out-of-date. ## ## While the script is running only /pool, pointing into this repo, is ## accessible (/source and /testing which may point elsewhere are not ## accessable, see above and below). .PHONY: kvm-upgrade kvm-upgrade: $(patsubst %, kvm-upgrade-%, $(KVM_OS)) $(patsubst %, kvm-upgrade-%, $(KVM_PLATFORM)): \ kvm-upgrade-%: rm -f $(KVM_POOLDIR_PREFIX)$(*)-upgrade rm -f $(KVM_POOLDIR_PREFIX)$(*)-upgrade.* $(MAKE) $(KVM_POOLDIR_PREFIX)$(*)-upgrade $(patsubst %, $(KVM_POOLDIR_PREFIX)%-upgrade, $(KVM_PLATFORM)): \ $(KVM_POOLDIR_PREFIX)%-upgrade: $(KVM_POOLDIR_PREFIX)%-base \ testing/libvirt/%/upgrade.sh \ | $(KVM_HOST_OK) $(MAKE) kvm-undefine-$(notdir $@) $(QEMU_IMG) create -f qcow2 -F qcow2 -b $<.qcow2 $@.qcow2 $(VIRT_INSTALL) \ $(VIRT_INSTALL_FLAGS) \ --name=$(notdir $@) \ --os-variant=$(KVM_$($*)_OS_VARIANT) \ --disk=cache=writeback,path=$@.qcow2 \ --import \ --noautoconsole : Copy/transmogrify upgrade.sh in this directory - $(srcdir) - to : $(KVMPOOLDIR) where it can be run from within the VM. : Do not use upgrade.sh from $(KVM_SOURCEDIR) which can be different : and is only used for building pluto. $(KVM_TRANSMOGRIFY) testing/libvirt/$*/upgrade.sh > $@.upgrade.sh $(KVMSH) $(notdir $@) -- \ /bin/sh -x /pool/$(notdir $@).upgrade.sh $(KVM_$($*)_UPGRADE_FLAGS) : only shutdown when upgrade works $(KVMSH) --shutdown $(notdir $@) touch $@ ## ## Create the os domain by transmogrifying the updated domain. ## ## This also makes /source $(KVM_SOURCEDIR) and /testing ## $(KVM_TESTINGDIR) available to the VM. Setting these during ## transmogrify means changing them only requires a re-transmogrify ## and not a full domain rebuild. .PHONY: kvm-transmogrify kvm-transmogrify: $(patsubst %, kvm-transmogrify-%, $(KVM_OS)) $(patsubst %, kvm-transmogrify-%, $(KVM_PLATFORM)): \ kvm-transmogrify-%: rm -f $(KVM_POOLDIR_PREFIX)$(*) rm -f $(KVM_POOLDIR_PREFIX)$(*).* $(MAKE) $(KVM_POOLDIR_PREFIX)$(*) $(patsubst %, $(KVM_POOLDIR_PREFIX)%, $(KVM_PLATFORM)): \ $(KVM_POOLDIR_PREFIX)%: $(KVM_POOLDIR_PREFIX)%-upgrade \ | \ testing/libvirt/%/transmogrify.sh \ $(KVM_HOST_OK) $(MAKE) kvm-undefine-$(notdir $@) $(QEMU_IMG) create -f qcow2 -F qcow2 -b $<.qcow2 $@.qcow2 $(VIRT_INSTALL) \ $(VIRT_INSTALL_FLAGS) \ $(VIRT_SOURCEDIR) \ $(VIRT_TESTINGDIR) \ --name=$(notdir $@) \ --os-variant=$(KVM_$($*)_OS_VARIANT) \ --disk=cache=writeback,path=$@.qcow2 \ --import \ --noautoconsole : Copy/transmogrify transmogrify.sh in this directory - $(srcdir) - to : $(KVMPOOLDIR) where it can be run from within the VM. : Do not use upgrade.sh from $(KVM_SOURCEDIR) which can be different : and is only used for building pluto. $(KVM_TRANSMOGRIFY) testing/libvirt/$*/transmogrify.sh > $@.transmogrify.sh for f in testing/libvirt/bash_profile $(KVM_$($*)_TRANSMOGRIFY_FILES); do \ cp -v $$f $@.$$(basename $$f) ; \ done $(KVMSH) $(notdir $@) -- \ /bin/sh -x /pool/$(notdir $@).transmogrify.sh $(KVM_$($*)_TRANSMOGRIFY_FLAGS) : only shutdown after transmogrify succeeds $(KVMSH) --shutdown $(notdir $@) touch $@ KVM_FEDORA_TRANSMOGRIFY_FILES += $(wildcard testing/libvirt/fedora/network/*.network) KVM_FREEBSD_TRANSMOGRIFY_FILES += testing/libvirt/freebsd/rc.conf KVM_NETBSD_TRANSMOGRIFY_FILES += testing/libvirt/netbsd/rc.local KVM_OPENBSD_TRANSMOGRIFY_FILES += testing/libvirt/openbsd/rc.local ## ## Build/Install libreswan into the build domain. ## # Notice how the <> and <> rules do # not shut down the domain. That is left to the rule creating all the # test instances. # First delete all of the build domain's clones. The build domain # won't boot when its clones are running. # # 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). # some rules are overwritten below KVM_INSTALL_PLATFORM += $(filter-out fedora, $(KVM_PLATFORM)) ifneq ($(KVM_INSTALL_RPM),true) KVM_INSTALL_PLATFORM += fedora endif .PHONY: kvm-build kvm-build: $(foreach os, $(KVM_OS), kvm-build-$(os)) $(patsubst %, kvm-build-%, $(KVM_INSTALL_PLATFORM)): \ kvm-build-%: $(KVM_POOLDIR_PREFIX)% : $(MAKE) $(patsubst %, kvm-undefine-%, $(call add-kvm-prefixes, $(KVM_$($*)_HOST_NAMES))) $(KVMSH) $(KVMSH_FLAGS) \ --chdir /source \ $(notdir $<) \ -- \ gmake install-base $(KVM_MAKEFLAGS) $(KVM_$($*)_MAKEFLAGS) .PHONY: kvm-install kvm-install: $(foreach os, $(KVM_OS), kvm-install-$(os)) $(MAKE) $(KVM_KEYS) $(patsubst %, kvm-install-%, $(KVM_PLATFORM)): \ kvm-install-%: $(MAKE) $(patsubst %, kvm-undefine-%, $(call add-kvm-prefixes, $(KVM_$($*)_HOST_NAMES))) $(MAKE) kvm-build-$* $(KVMSH) --shutdown $(KVM_FIRST_PREFIX)$* $(MAKE) $(call add-kvm-localdir-prefixes, $(KVM_$($*)_HOST_NAMES)) # # 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 domain-name to indicate that # a domain has been created. .PRECIOUS: $(KVM_TEST_DOMAINS) define define-clone-domain $(addprefix $(1), $(2)): $(3) | \ $$(foreach subnet, $$(KVM_TEST_SUBNETS), \ $(addprefix $(1), $$(subnet).net)) \ testing/libvirt/vm/$(strip $(2)).xml : install-kvm-test-domain prefix=$(strip $(1)) host=$(strip $(2)) template=$(strip $(3)) $$(MAKE) kvm-undefine-$$(notdir $$@) $$(QEMU_IMG) create -f qcow2 -F qcow2 -b $(strip $(3)).qcow2 $$@.qcow2 $$(KVM_TRANSMOGRIFY) \ -e "s:@@NAME@@:$$(notdir $$@):" \ -e "s:network='192_:network='$(addprefix $(notdir $(1)), 192_):" \ < testing/libvirt/vm/$(strip $(2)).xml \ > '$$@.tmp' $$(VIRSH) define $$@.tmp mv $$@.tmp $$@ endef # generate rules for all combinations, including those not enabled $(foreach prefix, $(KVM_LOCALDIR_PREFIXES), \ $(foreach platform, $(KVM_PLATFORM), \ $(foreach host, $(KVM_$($(platform))_HOST_NAMES), \ $(eval $(call define-clone-domain, \ $(prefix), \ $(host), \ $(KVM_POOLDIR_PREFIX)$(platform)))))) # # Get rid of (almost) everything # # After running the operation, kvm-install will: # # kvm-uninstall: transmogrify, install # kvm-clean-keys: keys, install # kvm-clean: transmogrify, build, keys, install # kvm-purge: upgrade, transmogrify, build, keys, install # # For kvm-uninstall, instead of trying to uninstall libreswan from the # build domain, delete both the clones and the build domain and # $(KVM_KEYS_DOMAIN) the install domains were cloned from. This way, # in addition to giving kvm-install a 100% fresh start (no dependence # on 'make uninstall') the next test run also gets entirely new # domains. .PHONY: kvm-shutdown $(patsubst %, kvm-shutdown-%, $(KVM_PLATFORM_DOMAIN_NAMES)): \ kvm-shutdown-%: $(KVMSH) --shutdown $* kvm-shutdown: $(patsubst %, kvm-shutdown-%, $(KVM_PLATFORM_DOMAIN_NAMES)) .PHONY: kvm-undefine $(patsubst %, kvm-undefine-%, $(KVM_PLATFORM_DOMAIN_NAMES)): \ kvm-undefine-%: @if state=$$($(VIRSH) domstate $* 2>&1); then \ case "$${state}" in \ "running" | "in shutdown" | "paused" ) \ echo -n "destroying $*: " ; $(VIRSH) destroy $* ; \ echo -n "undefining $*: " ; $(VIRSH) undefine $* \ ;; \ "shut off" ) \ echo -n "undefining $*: " ; $(VIRSH) undefine $* \ ;; \ * ) \ echo "Unknown state $${state} for $*" ; \ ;; \ esac ; \ else \ echo "No domain $*" ; \ fi rm -f $(KVM_POOLDIR)/$* $(KVM_LOCALDIR)/$* rm -f $(KVM_POOLDIR)/$*.qcow2 $(KVM_LOCALDIR)/$*.qcow2 kvm-undefine: $(patsubst %, kvm-undefine-%, $(KVM_PLATFORM_DOMAIN_NAMES)) .PHONY: kvm-clean kvm-clean: kvm-uninstall kvm-clean: kvm-clean-keys kvm-clean: kvm-clean-check rm -rf OBJ.kvm.* .PHONY: kvm-purge kvm-purge: kvm-clean kvm-purge: kvm-uninstall-networks kvm-purge: kvm-downgrade rm -f $(KVM_HOST_OK) .PHONY: kvm-uninstall kvm-uninstall: $(patsubst %, kvm-uninstall-%, $(KVM_OS)) $(patsubst %, kvm-uninstall-%, $(KVM_PLATFORM)): \ kvm-uninstall-%: $(MAKE) $(patsubst %, kvm-undefine-%, $(call add-kvm-prefixes, $(KVM_$($*)_HOST_NAMES))) $(MAKE) kvm-undefine-$(KVM_FIRST_PREFIX)$* rm -f $(KVM_POOLDIR_PREFIX)$* rm -f $(KVM_POOLDIR_PREFIX)$*.* .PHONY: kvm-downgrade kvm-downgrade: $(foreach os, $(KVM_OS), kvm-downgrade-$(os)) $(patsubst %, kvm-downgrade-%, $(KVM_PLATFORM)): \ kvm-downgrade-%: $(MAKE) kvm-uninstall-$* $(MAKE) kvm-undefine-$(KVM_FIRST_PREFIX)$*-upgrade rm -f $(KVM_POOLDIR_PREFIX)$*-upgrade rm -f $(KVM_POOLDIR_PREFIX)$*-upgrade.* .PHONY: kvm-demolish kvm-demolish: kvm-uninstall-gateway kvm-demolish: $(foreach os, $(KVM_OS), kvm-demolish-$(os)) $(patsubst %, kvm-demolish-%, $(KVM_PLATFORM)): \ kvm-demolish-%: $(MAKE) kvm-downgrade-$* $(MAKE) kvm-undefine-$(KVM_FIRST_PREFIX)$*-base rm -f $(KVM_POOLDIR_PREFIX)$*-base rm -f $(KVM_POOLDIR_PREFIX)$*-base.* # # Create an RPM for the test domains # .PHONY: kvm-rpm kvm-rpm: $(KVM_POOLDIR_PREFIX)fedora @echo building rpm for libreswan testing mkdir -p rpmbuild/SPECS/ : NOTE: testing/packaging/// and NOT packaging/... sed -e "s/@IPSECBASEVERSION@/$(RPM_VERSION)/g" \ -e "s/^Version:.*/Version: $(RPM_VERSION)/g" \ -e "s/@INITSYSTEM@/$(INITSYSTEM)/g" \ testing/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 : add Makefile.in.local? 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 $(KVMSH) --chdir /source $(notdir $<) -- \ rpmbuild -D_topdir\\ /source/rpmbuild \ -ba $(RPM_BUILD_CLEAN) \ rpmbuild/SPECS/libreswan-testing.spec ifeq ($(KVM_INSTALL_RPM), true) .PHONY: kvm-fedora-install kvm-fedora-install: $(KVM_POOLDIR_PREFIX)fedora rm -fr rpmbuild/*RPMS $(MAKE) kvm-rpm $(KVMSH) $(KVMSH_FLAGS) --chdir . $(notdir $<) 'rpm -aq | grep libreswan && rpm -e $$(rpm -aq | grep libreswan) || true' $(KVMSH) $(KVMSH_FLAGS) --chdir . $(notdir $<) 'rpm -i /source/rpmbuild/RPMS/x86_64/libreswan*rpm' $(KVMSH) $(KVMSH_FLAGS) --chdir . $(notdir $<) 'restorecon /usr/local/sbin /usr/local/libexec/ipsec -Rv' endif # # kvmsh-HOST # # Map this onto the first domain group. Logging into the other # domains can be done by invoking kvmsh.py directly. # $(patsubst %, kvmsh-%, $(filter-out $(KVM_DOMAIN_NAMES), $(KVM_HOST_NAMES))): \ kvmsh-%: kvmsh-$(KVM_FIRST_PREFIX)% $(patsubst %, kvmsh-%, $(KVM_TEST_DOMAIN_NAMES)) : \ kvmsh-%: $(KVM_LOCALDIR)/% | $(KVM_HOST_OK) $(KVMSH) $(KVMSH_FLAGS) $* $(KVMSH_COMMAND) $(patsubst %, kvmsh-%, $(KVM_BUILD_DOMAIN_NAMES)) : \ kvmsh-%: $(KVM_POOLDIR)/% | $(KVM_HOST_OK) $(KVMSH) $(KVMSH_FLAGS) $* $(KVMSH_COMMAND) # # Some hints # # Only what is listed in here is "supported" # 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_POOLDIR) directory for storing the shared base VM; should be relatively permanent storage $(call kvm-var-value,KVM_LOCALDIR) directory for storing the VMs local to this build tree; can be temporary storage (for instance /tmp) $(call kvm-var-value,KVM_WORKERS) $(call kvm-var-value,KVM_PREFIX) $(call kvm-var-value,KVM_FIRST_PREFIX) $(call kvm-var-value,KVM_PREFIXES) $(call kvm-var-value,KVM_POOLDIR_PREFIX) $(call kvm-var-value,KVM_LOCALDIR_PREFIXES) $(call kvm-var-value,KVM_GROUP) $(call kvm-var-value,KVM_PIDFILE) $(call kvm-var-value,KVM_UID) $(call kvm-var-value,KVM_GID) $(call kvm-var-value,KVM_CONNECTION) $(call kvm-var-value,KVM_VIRSH) the shared NATting gateway; used by the base domain along with any local domains when internet access is required $(call kvm-var-value,KVM_KEYS_DOMAIN) $(call kvm-var-value,KVM_DEBIAN_MAKEFLAGS) $(call kvm-var-value,KVM_FEDORA_MAKEFLAGS) $(call kvm-var-value,KVM_FREEBSD_MAKEFLAGS) $(call kvm-var-value,KVM_NETBSD_MAKEFLAGS) $(call kvm-var-value,KVM_OPENBSD_MAKEFLAGS) $(call kvm-var-value,KVM_DEBIAN_HOST_NAMES) $(call kvm-var-value,KVM_FEDORA_HOST_NAMES) $(call kvm-var-value,KVM_FREEBSD_HOST_NAMES) $(call kvm-var-value,KVM_NETBSD_HOST_NAMES) $(call kvm-var-value,KVM_OPENBSD_HOST_NAMES) $(call kvm-var-value,KVM_DEBIAN_OS_VARIANT) $(call kvm-var-value,KVM_FEDORA_OS_VARIANT) $(call kvm-var-value,KVM_FREEBSD_OS_VARIANT) $(call kvm-var-value,KVM_NETBSD_OS_VARIANT) $(call kvm-var-value,KVM_OPENBSD_OS_VARIANT) $(call kvm-var-value,KVM_TEST_HOST_NAMES) $(call kvm-var-value,KVM_TEST_DOMAIN_NAMES) $(call kvm-var-value,KVM_TEST_DOMAINS) $(call kvm-var-value,KVM_BUILD_HOST_NAMES) $(call kvm-var-value,KVM_BUILD_DOMAIN_NAMES) $(call kvm-var-value,KVM_BUILD_DOMAINS) $(call kvm-var-value,KVM_GATEWAY) $(call kvm-var-value,KVM_GATEWAY_FILE) $(call kvm-var-value,KVM_TEST_SUBNETS) $(call kvm-var-value,KVM_TEST_NETWORKS) $(call kvm-var-value,KVM_OS) $(call kvm-var-value,KVM_PLATFORM) $(call kvm-var-value,KVM_PLATFORM_BUILD_HOST_NAMES) $(call kvm-var-value,KVM_PLATFORM_TEST_HOST_NAMES) $(call kvm-var-value,KVM_PLATFORM_BUILD_DOMAIN_NAMES) $(call kvm-var-value,KVM_PLATFORM_TEST_DOMAIN_NAMES) $(call kvm-var-value,KVM_PLATFORM_DOMAIN_NAMES) KVM Domains: $(KVM_BASE_DOMAIN) | gateway: $(KVM_GATEWAY) | directory: $(KVM_POOLDIR) | +- $(KVM_KEYS_DOMAIN) | | gateway: $(KVM_GATEWAY) | | directory: $(KVM_POOLDIR) | | \ $(foreach prefix,$(KVM_PREFIXES), \ \ $(crlf)$(sp)$(sp)$(sp)$(sp)|$(sp)$(sp)| test group $(prefix) \ $(crlf)$(sp)$(sp)$(sp)$(sp)|$(sp) +-- \ $(foreach install,$(KVM_TEST_HOST_NAMES),$(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 Manually building and modifying the base domain and network: Normally kvm-install et.al, below, are sufficient. However .... The first step in setting up the test environment is creating the base domain. The make targets below can be used to step through the process of constructing the base domain. At anytime kvmsh-base can be used to log into that domain. kvmsh-base log into the base domain (if necessary, kickstart it); this will not trigger an upgrade or transmogrify kvm-downgrade revert everything back to the kickstarted base domain; no extra packages will have been upgraded and no transmogrification will have been performed if the base domain doesn't exist it will be created kvm-upgrade perform an incremental install/upgrade any packages needed by libreswan; to force a complete re-install of all packages, first kvm-downgrade to keep kickstart (which is something of a black box) as simple as possible, and to make re-running / debugging the upgrade process easier, this step is not embedded in kickstart. kvm-transmogrify install all the configuration files so that the domain will automatically transmogrify from the base domain to a test domain during boot also: kvm-install-gateway kvm-uninstall-gateway just create the base domain's gateway note that uninstalling the gateway also uninstalls the base domain (since it depends on the gateway) Standard targets and operations: Delete the installed KVMs and networks so that the next kvm-install will create new versions: kvm-downgrade: - delete test domains - delete test build - delete test results - delete test networks kvm-demolish: wipe out a directory - delete the base domain - delete the gateway Manipulating and accessing (logging into) domains: kvmsh-HOST ($(filter-out build, $(KVM_TEST_HOST_NAMES))) - 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_TEST_DOMAIN_NAMES)) - 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: build / install (or update) everything needed for a test run kvm-uninstall: Uninstall libreswan from the the test domains (cheats by deleting the build and test domains). Doesn't touch the test results kvm-clean: cleans the directory of the build, test results, and test domains ready for a new 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 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-4.14/mk/library.mk000066400000000000000000000014371457372064200160530ustar00rootroot00000000000000# 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 ARFLAGS=crvs local-check 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/rules.mk libreswan-4.14/mk/local.mk000066400000000000000000000027031457372064200154760ustar00rootroot00000000000000# 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 mk/config.mk need to see the local # definitions in Makefile.inc.local but mk/config.mk can't (yet) # assume dirs.mk has been included. This wrapper prevents multiple # includes. # Why can't mk/dirs.mk include mk/config.mk, or mk/config.mk include # mk/dirs? # # The problem is circular. mk/config.mk 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 # mk/config.mk case, when mk/dirs.mk hasn't been included -include $(LIBRESWANSRCDIR)/Makefile.inc.local endif endif libreswan-4.14/mk/manpages.mk000066400000000000000000000057741457372064200162120ustar00rootroot00000000000000# 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 ?= $(MANDIR)/man3 MANDIR.5 ?= $(MANDIR)/man5 MANDIR.8 ?= $(MANDIR)/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 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-4.14/mk/objdir.mk000066400000000000000000000033101457372064200156500ustar00rootroot00000000000000# Define OBJDIR, for Libreswan pathnames # # 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 mk/defaults/$(OSDEP).mk. # # Trying to query the build environment with tricks like: # # ( echo '#include ' ; echo 'major=__GLIBC__ ; # minor=__GLIBC_MINOR__') | gcc -E - # # have a similar result. # OSDEP=linux,bsd,cygwin,darwin ifeq ($(OSDEP),) OSDEP:=$(shell uname -s | tr 'A-Z' 'a-z') endif export OSDEP ifndef OBJDIR # let Makefile.inc.local override them? ARCH ?= $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/ -e 's/ //g') HOST ?= $(shell hostname | sed -e 's/\..*//') OBJDIR:=OBJ.${OSDEP}.${ARCH}.$(HOST) export OBJDIR endif libreswan-4.14/mk/perf.sh000077500000000000000000000042121457372064200153430ustar00rootroot00000000000000#!/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-4.14/mk/program.mk000066400000000000000000000035451457372064200160600ustar00rootroot00000000000000# 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 ifneq ($(LD_LIBRARY_PATH),) LDFLAGS+=-L$(LD_LIBRARY_PATH) endif ifndef PROGRAMDIR PROGRAMDIR=${LIBEXECDIR} endif local-base: $(PROGRAM) local-clean-base: rm -f $(builddir)/*.o $(foreach p,$(PROGRAM), $(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 ; \ ) list-local-base: @$(call foreach-file, $(PROGRAM), $(PROGRAMDIR), \ 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) $(USERLAND_CFLAGS) \ $(USERLAND_INCLUDES) \ $(CFLAGS) \ -o $@ $(OBJS) \ $(USERLAND_LDFLAGS) \ $(LDFLAGS) endif include $(top_srcdir)/mk/rules.mk libreswan-4.14/mk/rules.mk000066400000000000000000000054661457372064200155470ustar00rootroot00000000000000# generic make rules for libreswan # Targets needing the builddir should add: # # | $(builddir) # # as a soft/order-only dependency. $(builddir): mkdir -p $(builddir) # script transforms # Some Makefiles use $(buildir)/SCRIPT as the target while others use # just SCRIPT. Accommodate both. define transform_script @echo 'IN' $< '->' $(builddir)/$(notdir $@) ${TRANSFORM_VARIABLES} < $< > $(builddir)/$(notdir $@).tmp @if [ -x $< ]; then chmod +x $(builddir)/$(notdir $@).tmp; fi @if [ "${PROGRAM}" = $(notdir $@) ]; then chmod +x $(builddir)/$(notdir $@).tmp; fi mv $(builddir)/$(notdir $@).tmp $(builddir)/$(notdir $@) endef TRANSFORM_DEPS = \ $(top_srcdir)/mk/version.mk \ $(top_srcdir)/mk/config.mk \ $(wildcard $(top_srcdir)/Makefile.inc.local) %: %.sh $(TRANSFORM_DEPS) | $(builddir) $(transform_script) %: %.in $(TRANSFORM_DEPS) | $(builddir) $(transform_script) %: %.pl $(TRANSFORM_DEPS) | $(builddir) $(transform_script) $(builddir)/%: %.sh $(TRANSFORM_DEPS) | $(builddir) $(transform_script) $(builddir)/%: %.in $(TRANSFORM_DEPS) | $(builddir) $(transform_script) $(builddir)/%: %.pl $(TRANSFORM_DEPS) | $(builddir) $(transform_script) # 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. # # -DHERE_FILENAME is because it is a pita to create a path from # __FILE__ using a static C expression # # -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 ifdef OBJS .c.o: $(CC) $(USERLAND_CFLAGS) \ $(USERLAND_INCLUDES) \ -DHERE_FILENAME=\"$(path_srcdir)/$(notdir $<)\" \ $(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. # # Use := so it is evaluated immediately, using the context from # parsing this file (and not later). 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) endif libreswan-4.14/mk/targets.mk000066400000000000000000000074771457372064200160720ustar00rootroot00000000000000# 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)) # 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-4.14/mk/tests.sh000077500000000000000000000013541457372064200155550ustar00rootroot00000000000000#!/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 <. # # This program is distributed in the hope that it will be useful, but # WITHOUT 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 # .PHONY: web web-page web web-page: $(MAKE) WEB_ENABLED=true web-summarydir web-resultsdir web-publish ifdef WEB_ENABLED .PHONY: web-publish web-publish: | $(WEB_RESULTSDIR) $(WEB_UTILSDIR)/kvmresults.py \ --exit-ok \ --quick \ --test-kind '' \ --test-status '' \ --publish-summary $(WEB_RESULTSDIR)/summary.json \ --publish-status $(WEB_SUMMARYDIR)/status.json \ --publish-results $(WEB_RESULTSDIR) \ --publish-hash $(WEB_HASH) \ testing/pluto endif # # 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-test-prep: web-test-post: ifdef WEB_ENABLED web-test-prep: web-resultsdir 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: ifdef WEB_ENABLED web-summarydir: $(WEB_SUMMARYDIR)/commits.json web-summarydir: $(WEB_SUMMARYDIR)/index.html web-summarydir: $(WEB_SUMMARYDIR)/lsw-summary-graph.css web-summarydir: $(WEB_SUMMARYDIR)/lsw-table.css web-summarydir: $(WEB_SUMMARYDIR)/summaries.json web-summarydir: $(WEB_SUMMARYDIR)/summary.css web-summarydir: $(WEB_SUMMARYDIR)/tsconfig.json web-summarydir: | $(WEB_SUMMARYDIR)/status.json $(WEB_SUMMARYDIR)/index.html: $(WEB_SOURCEDIR)/summary.html | $(WEB_SUMMARYDIR) cp $(WEB_SOURCEDIR)/summary.html $(WEB_SUMMARYDIR)/index.html $(WEB_SUMMARYDIR)/%.css: $(WEB_SOURCEDIR)/%.css cp $< $@ $(WEB_SUMMARYDIR): mkdir $(WEB_SUMMARYDIR) endif # # Create or update a test run's results page. # .PHONY: web-resultsdir web-resultsdir: ifdef WEB_ENABLED web-resultsdir: $(WEB_RESULTSDIR)/index.html web-resultsdir: $(WEB_RESULTSDIR)/lsw-summary-graph.css web-resultsdir: $(WEB_RESULTSDIR)/lsw-table.css web-resultsdir: $(WEB_RESULTSDIR)/results.css web-resultsdir: $(WEB_RESULTSDIR)/tsconfig.json web-results-json: $(WEB_RESULTSDIR)/results.json web-results-json: $(WEB_RESULTSDIR)/summary.json $(WEB_RESULTSDIR)/index.html: $(WEB_SOURCEDIR)/results.html | $(WEB_RESULTSDIR) cp $(WEB_SOURCEDIR)/results.html $(WEB_RESULTSDIR)/index.html $(WEB_RESULTSDIR)/%.css: $(WEB_SOURCEDIR)/%.css cp $< $@ $(WEB_RESULTSDIR): | $(WEB_SUMMARYDIR) mkdir $(WEB_RESULTSDIR) endif # # 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 # # 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 $(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 $(WEB_SUMMARYDIR)/status.json: $(WEB_SOURCEDIR)/json-status.sh "initialized" > $@.tmp mv $@.tmp $@ endif # # Update $(WEB_SUMMARYDIR)/commits.json database # # Use the generated $(WEB_HASH).json containing the details of the # most recent commit as the target. That way, any new commits trigger # an update. WEB_COMMITSDIR = $(WEB_SUMMARYDIR)/commits .PHONY: web-commitsdir web-commitsdir: rm -rf $(WEB_COMMITSDIR) $(MAKE) WEB_ENABLED=true $(WEB_SUMMARYDIR)/commits.json $(WEB_SUMMARYDIR)/commits.json: $(WEB_COMMITSDIR)/$(WEB_HASH).json $(wildcard $(WEB_COMMITSDIR)/*.json) : 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 $@ FIRST_COMMIT = $(shell set -x ; $(WEB_SOURCEDIR)/earliest-commit.sh $(WEB_SUMMARYDIR) $(WEB_REPODIR)) $(WEB_COMMITSDIR)/$(WEB_HASH).json: | $(WEB_COMMITSDIR) : order hashes so HEAD is last ( cd $(WEB_REPODIR) && git rev-list --reverse $(FIRST_COMMIT)^..$(WEB_HASH) ) \ | while read hash ; do \ json=$(WEB_COMMITSDIR)/$${hash}.json ; \ if test -r $${json} ; then \ echo $${hash} ; \ else \ echo generating $${json} ; \ $(WEB_SOURCEDIR)/json-commit.sh \ $(WEB_REPODIR) $${hash} \ > $${json}.tmp ; \ mv $${json}.tmp $${json} ; \ fi ; \ done $(WEB_COMMITSDIR): | $(WEB_SUMMARYDIR) mkdir $(WEB_COMMITSDIR) # # 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 $(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 $@ endif # # hack to compile json code # %/tsconfig.json: $(WEB_SOURCEDIR)/tsconfig.json.in $(wildcard $(WEB_SOURCEDIR)/*.js $(WEB_SOURCEDIR)/*.tc) | % sed -e 's;@@DEST_DIR@@;$(realpath $(dir $@));' \ -e 's;@@SOURCE_DIR@@;$(realpath $(WEB_SOURCEDIR));' \ $(WEB_SOURCEDIR)/tsconfig.json.in \ > $@.tmp tsc --project $@.tmp mv $@.tmp $@ # # 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-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-commitsdir: build or update both $$(WEB_COMMITSDIR) and $$(WEB_SUMMARYDIR)/commits.json 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-4.14/ns000077500000000000000000000000661457372064200140120ustar00rootroot00000000000000#!/bin/sh exec $(dirname $0)/testing/utils/nsrun "$@" libreswan-4.14/packaging/000077500000000000000000000000001457372064200153665ustar00rootroot00000000000000libreswan-4.14/packaging/centos000077700000000000000000000000001457372064200174542rhelustar00rootroot00000000000000libreswan-4.14/packaging/debian/000077500000000000000000000000001457372064200166105ustar00rootroot00000000000000libreswan-4.14/packaging/debian/90-libreswan.preset000066400000000000000000000002211457372064200222430ustar00rootroot00000000000000# Libreswan IPsec daemon needs to be configured before enabling. # See /usr/share/doc/libreswan/README.Debian for details. disable ipsec.service libreswan-4.14/packaging/debian/Makefile000066400000000000000000000014201457372064200202450ustar00rootroot00000000000000# these need get fixed not to use root top_srcdir = ../.. .PHONY: deb deb: | $(top_srcdir)/debian cd $(top_srcdir) && debuild -i -us -uc -b rm -fr $(top_srcdir)/debian #debuild -S -sa DEBIAN_IPSEC_BASE_VERSION=$(shell make --directory $(top_srcdir) --silent showversion | sed -e "s/\([0-9]\{1,3\}\)\.\([0-9]\{1,3\}\)\(.*\)/\1.\2~\3/" | sed "s/~-/~/") # racy $(top_srcdir)/debian: cp -r . $(top_srcdir)/debian cat $(top_srcdir)/debian/changelog grep "IPSECBASEVERSION" $(top_srcdir)/debian/changelog && \ sed -i "s/@IPSECBASEVERSION@/$(DEBIAN_IPSEC_BASE_VERSION)/g" $(top_srcdir)/debian/changelog || \ echo "missing IPSECBASEVERSION in debian/changelog. This is not git repository?" cat $(top_srcdir)/debian/changelog showdebversion: @echo $(DEBIAN_IPSEC_BASE_VERSION) libreswan-4.14/packaging/debian/README.Debian000066400000000000000000000044201457372064200206510ustar00rootroot00000000000000libreswan 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. libreswan-4.14/packaging/debian/TODO000066400000000000000000000021071457372064200173000ustar00rootroot00000000000000Notes 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-4.14/packaging/debian/changelog000066400000000000000000000002071457372064200204610ustar00rootroot00000000000000libreswan (4.14-1) unstable; urgency=low * Release 4.14-1 -- Libreswan Team Mon 11 Mar 2024 01:00:00 +0200 libreswan-4.14/packaging/debian/compat000066400000000000000000000000031457372064200200070ustar00rootroot0000000000000010 libreswan-4.14/packaging/debian/control000066400000000000000000000037211457372064200202160ustar00rootroot00000000000000Source: 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 Build-Depends: bison, bzip2, debhelper (>= 9), 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 (>= 1.6.5~), 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, ${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-4.14/packaging/debian/copyright000066400000000000000000000274671457372064200205630ustar00rootroot00000000000000Format: 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/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/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-4.14/packaging/debian/gbp.conf000066400000000000000000000000721457372064200202260ustar00rootroot00000000000000[DEFAULT] pristine-tar = True upstream-tag = v%(version)s libreswan-4.14/packaging/debian/libreswan.dirs000066400000000000000000000000231457372064200214540ustar00rootroot00000000000000/var/lib/ipsec/nss libreswan-4.14/packaging/debian/libreswan.docs000066400000000000000000000001141457372064200214440ustar00rootroot00000000000000CREDITS README.md README.nss README.x509 docs/README.XAUTH docs/README.rfcs libreswan-4.14/packaging/debian/libreswan.examples000066400000000000000000000000201457372064200223260ustar00rootroot00000000000000docs/examples/* libreswan-4.14/packaging/debian/libreswan.install000066400000000000000000000000651457372064200221670ustar00rootroot00000000000000debian/90-libreswan.preset lib/systemd/system-preset libreswan-4.14/packaging/debian/libreswan.lintian-overrides000066400000000000000000000005761457372064200241660ustar00rootroot00000000000000# 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-4.14/packaging/debian/libreswan.logcheck.ignore.paranoid000066400000000000000000000005221457372064200253540ustar00rootroot00000000000000pluto.*: 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-4.14/packaging/debian/libreswan.logcheck.ignore.server000066400000000000000000000007501457372064200250700ustar00rootroot00000000000000pluto.*: 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-4.14/packaging/debian/libreswan.logcheck.ignore.workstation000066400000000000000000000007501457372064200261460ustar00rootroot00000000000000pluto.*: 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-4.14/packaging/debian/libreswan.postrm000066400000000000000000000002651457372064200220470ustar00rootroot00000000000000#!/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-4.14/packaging/debian/patches/000077500000000000000000000000001457372064200202375ustar00rootroot00000000000000libreswan-4.14/packaging/debian/patches/0002-debian-pam.d-pluto.patch000066400000000000000000000023741457372064200252250ustar00rootroot00000000000000From: 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 --- configs/pam.d/pluto | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/configs/pam.d/pluto b/configs/pam.d/pluto index 3855385..bb9b22c 100644 --- a/configs/pam.d/pluto +++ b/configs/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 libreswan-4.14/packaging/debian/patches/series000066400000000000000000000002321457372064200214510ustar00rootroot00000000000000#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-4.14/packaging/debian/rules000077500000000000000000000025351457372064200176750ustar00rootroot00000000000000#!/usr/bin/make -f include /usr/share/dpkg/default.mk %: dh $@ --with systemd # this should track the definition of USERCOMPILE in mk/userland.mk:46 # but without -fstack-protector-all for arches that lack stack-protector ifneq (,$(filter $(DEB_HOST_ARCH), hppa alpha ia64)) 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 override_dh_auto_build: dh_auto_build -- programs \ ARCH=$(DEB_HOST_ARCH) \ IPSECVERSION=$(DEB_VERSION_UPSTREAM_REVISION) \ PREFIX=/usr \ FINALLIBEXECDIR=/usr/libexec/ipsec \ FINALMANDIR=/usr/share/man \ USE_LDAP=true \ $(ENABLE_LIBCAP_NG) \ $(ENABLE_SELINUX) 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) \ PREFIX=/usr \ FINALLIBEXECDIR=/usr/libexec/ipsec \ FINALMANDIR=/usr/share/man \ USE_LDAP=true \ $(ENABLE_LIBCAP_NG) \ $(ENABLE_SELINUX) \ DESTDIR=$(CURDIR)/debian/libreswan override_dh_auto_test: echo "Skip dh_auto_test" override_dh_strip: dh_strip --dbg-package=libreswan-dbg libreswan-4.14/packaging/debian/source/000077500000000000000000000000001457372064200201105ustar00rootroot00000000000000libreswan-4.14/packaging/debian/source/format000066400000000000000000000000141457372064200213160ustar00rootroot000000000000003.0 (quilt) libreswan-4.14/packaging/debian/tests/000077500000000000000000000000001457372064200177525ustar00rootroot00000000000000libreswan-4.14/packaging/debian/tests/control000066400000000000000000000001631457372064200213550ustar00rootroot00000000000000Tests: opportunistic Restrictions: needs-root, isolation-machine Depends: @, iputils-ping, wget, systemd, dnsutils libreswan-4.14/packaging/debian/tests/opportunistic000077500000000000000000000022061457372064200226220ustar00rootroot00000000000000#!/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-4.14/packaging/debian/upstream/000077500000000000000000000000001457372064200204505ustar00rootroot00000000000000libreswan-4.14/packaging/debian/upstream/signing-key.asc000066400000000000000000000066671457372064200234030ustar00rootroot00000000000000-----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-4.14/packaging/debian/watch000066400000000000000000000004771457372064200176510ustar00rootroot00000000000000version=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-4.14/packaging/devuan/000077500000000000000000000000001457372064200166505ustar00rootroot00000000000000libreswan-4.14/packaging/devuan/90-libreswan.preset000066400000000000000000000002211457372064200223030ustar00rootroot00000000000000# Libreswan IPsec daemon needs to be configured before enabling. # See /usr/share/doc/libreswan/README.Debian for details. disable ipsec.service libreswan-4.14/packaging/devuan/Makefile000066400000000000000000000000501457372064200203030ustar00rootroot00000000000000deb: $(MAKE) --directory ../debian deb libreswan-4.14/packaging/devuan/README.Devuan000066400000000000000000000001501457372064200207450ustar00rootroot00000000000000libreswan for Devuan -------------------- Completely untested - provide feedback if something is wrong libreswan-4.14/packaging/devuan/changelog000066400000000000000000000002101457372064200205130ustar00rootroot00000000000000libreswan (4.14-1) unstable; urgency=low * Release 4.14-1 -- Libreswan Team Mon 11 Mar 2024 01:00:00 +0200 libreswan-4.14/packaging/devuan/compat000066400000000000000000000000031457372064200200470ustar00rootroot0000000000000010 libreswan-4.14/packaging/devuan/control000066400000000000000000000037541457372064200202640ustar00rootroot00000000000000Source: 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), 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], libunbound-dev, man2html, pkg-config, po-debconf, 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, ${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-4.14/packaging/devuan/copyright000066400000000000000000000274671457372064200206230ustar00rootroot00000000000000Format: 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/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/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-4.14/packaging/devuan/gbp.conf000066400000000000000000000000721457372064200202660ustar00rootroot00000000000000[DEFAULT] pristine-tar = True upstream-tag = v%(version)s libreswan-4.14/packaging/devuan/libreswan.dirs000066400000000000000000000000231457372064200215140ustar00rootroot00000000000000/var/lib/ipsec/nss libreswan-4.14/packaging/devuan/libreswan.docs000066400000000000000000000001141457372064200215040ustar00rootroot00000000000000CREDITS README.md README.nss README.x509 docs/README.XAUTH docs/README.rfcs libreswan-4.14/packaging/devuan/libreswan.examples000066400000000000000000000000201457372064200223660ustar00rootroot00000000000000docs/examples/* libreswan-4.14/packaging/devuan/libreswan.install000066400000000000000000000000331457372064200222220ustar00rootroot00000000000000debian/90-libreswan.preset libreswan-4.14/packaging/devuan/libreswan.lintian-overrides000066400000000000000000000005761457372064200242260ustar00rootroot00000000000000# 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-4.14/packaging/devuan/libreswan.logcheck.ignore.paranoid000066400000000000000000000005221457372064200254140ustar00rootroot00000000000000pluto.*: 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-4.14/packaging/devuan/libreswan.logcheck.ignore.server000066400000000000000000000007501457372064200251300ustar00rootroot00000000000000pluto.*: 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-4.14/packaging/devuan/libreswan.logcheck.ignore.workstation000066400000000000000000000007501457372064200262060ustar00rootroot00000000000000pluto.*: 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-4.14/packaging/devuan/libreswan.postrm000066400000000000000000000002651457372064200221070ustar00rootroot00000000000000#!/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-4.14/packaging/devuan/patches/000077500000000000000000000000001457372064200202775ustar00rootroot00000000000000libreswan-4.14/packaging/devuan/patches/0002-debian-pam.d-pluto.patch000066400000000000000000000023241457372064200252600ustar00rootroot00000000000000From: 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 libreswan-4.14/packaging/devuan/patches/series000066400000000000000000000002321457372064200215110ustar00rootroot00000000000000#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-4.14/packaging/devuan/rules000077500000000000000000000044701457372064200177350ustar00rootroot00000000000000#!/usr/bin/make -f include /usr/share/dpkg/default.mk %: dh $@ # 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|stretch|xenial' /etc/os-release && echo USE_DNSSEC=false) 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 'cosmic|jessie|xenial' /etc/os-release && echo USE_XFRM_INTERFACE=false) DISTRO_CONF += $(shell grep -qE 'bionic|stretch' /etc/os-release && echo USE_XFRM_INTERFACE_IFLA_HEADER=true) DISTRO_CONF += $(shell grep -qE 'jessie|stretch|xenial' /etc/os-release && echo 'WERROR_CFLAGS="-Werror -Wno-missing-field-initializers -Wno-error=address"') override_dh_auto_build: dh_auto_build -- programs \ ARCH=$(DEB_HOST_ARCH) \ IPSECVERSION=$(DEB_VERSION_UPSTREAM_REVISION) \ PREFIX=/usr \ FINALLIBEXECDIR=/usr/libexec/ipsec \ 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) \ PREFIX=/usr \ FINALLIBEXECDIR=/usr/libexec/ipsec \ FINALNSSDIR=/var/lib/ipsec/nss \ USE_LDAP=true \ USE_FIPSCHECK=false \ $(ENABLE_LIBCAP_NG) \ $(ENABLE_SELINUX) \ 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-4.14/packaging/devuan/source/000077500000000000000000000000001457372064200201505ustar00rootroot00000000000000libreswan-4.14/packaging/devuan/source/format000066400000000000000000000000141457372064200213560ustar00rootroot000000000000003.0 (quilt) libreswan-4.14/packaging/devuan/tests/000077500000000000000000000000001457372064200200125ustar00rootroot00000000000000libreswan-4.14/packaging/devuan/tests/control000066400000000000000000000001521457372064200214130ustar00rootroot00000000000000Tests: opportunistic Restrictions: needs-root, isolation-machine Depends: @, iputils-ping, wget, dnsutils libreswan-4.14/packaging/devuan/tests/opportunistic000077500000000000000000000022061457372064200226620ustar00rootroot00000000000000#!/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-4.14/packaging/devuan/upstream/000077500000000000000000000000001457372064200205105ustar00rootroot00000000000000libreswan-4.14/packaging/devuan/upstream/signing-key.asc000066400000000000000000000066671457372064200234430ustar00rootroot00000000000000-----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-4.14/packaging/devuan/watch000066400000000000000000000004771457372064200177110ustar00rootroot00000000000000version=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-4.14/packaging/fedora/000077500000000000000000000000001457372064200166265ustar00rootroot00000000000000libreswan-4.14/packaging/fedora/libreswan-sysctl.conf000066400000000000000000000010151457372064200227770ustar00rootroot00000000000000# 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-4.14/packaging/fedora/libreswan.spec000066400000000000000000000147401457372064200214760ustar00rootroot00000000000000%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.52 %global unbound_version 1.6.6 # Libreswan config options %global libreswan_config \\\ FINALLIBEXECDIR=%{_libexecdir}/ipsec \\\ FINALMANDIR=%{_mandir} \\\ PREFIX=%{_prefix} \\\ INITSYSTEM=systemd \\\ PYTHON_BINARY=%{__python3} \\\ SHELL_BINARY=%{_bindir}/sh \\\ USE_DNSSEC=true \\\ 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_AUTHPAM=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: 4.14 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: make BuildRequires: nspr-devel BuildRequires: nss-devel >= %{nss_version} BuildRequires: nss-tools >= %{nss_version} BuildRequires: openldap-devel BuildRequires: pam-devel BuildRequires: pkgconfig BuildRequires: systemd BuildRequires: systemd-devel BuildRequires: systemd-rpm-macros BuildRequires: unbound-devel >= %{unbound_version} BuildRequires: xmlto %if 0%{with_efence} BuildRequires: ElectricFence %endif Requires: coreutils Requires: iproute >= 2.6.8 Requires: nss >= %{nss_version} Requires: nss-softokn Requires: nss-tools Requires: procps-ng Requires: unbound-libs >= %{unbound_version} Suggests: logrotate %{?systemd_requires} 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:" configs/ipsec.conf.in %build %make_build \ %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_install \ %{libreswan_config} \ FS=$(pwd) rm -rf %{buildroot}/usr/share/doc/libreswan rm -rf %{buildroot}%{_libexecdir}/ipsec/*check install -d -m 0755 %{buildroot}%{_rundir}/pluto install -d %{buildroot}%{_sbindir} install -d %{buildroot}%{_sysctldir} install -m 0644 packaging/fedora/libreswan-sysctl.conf \ %{buildroot}%{_sysctldir}/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 : 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 %sysctl_apply 50-libreswan.conf %preun %systemd_preun ipsec.service %postun %systemd_postun_with_restart ipsec.service %files %license COPYING LICENSE %doc CHANGES CREDITS README* %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) %{_sysctldir}/50-libreswan.conf %attr(0755,root,root) %dir %{_rundir}/pluto %attr(0700,root,root) %dir %{_sharedstatedir}/ipsec %attr(0700,root,root) %dir %{_sharedstatedir}/ipsec/nss %attr(0644,root,root) %{_tmpfilesdir}/libreswan.conf %attr(0644,root,root) %{_unitdir}/ipsec.service %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/pam.d/pluto %config(noreplace) %{_sysconfdir}/logrotate.d/libreswan %{_sbindir}/ipsec %{_libexecdir}/ipsec %doc %{_mandir}/*/* %changelog * Mon Mar 11 2024 Team Libreswan - 4.14-1 - Automated build from release tar ball libreswan-4.14/packaging/foobar000077700000000000000000000000001457372064200174312rhelustar00rootroot00000000000000libreswan-4.14/packaging/rhel/000077500000000000000000000000001457372064200163205ustar00rootroot00000000000000libreswan-4.14/packaging/rhel/7/000077500000000000000000000000001457372064200164665ustar00rootroot00000000000000libreswan-4.14/packaging/rhel/7/libreswan.spec000066400000000000000000000146721457372064200213420ustar00rootroot00000000000000# 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.79-4 # Libreswan config options %global libreswan_config \\\ FINALLIBEXECDIR=%{_libexecdir}/ipsec \\\ FINALMANDIR=%{_mandir} \\\ FINALNSSDIR=%{_sysconfdir}/ipsec.d \\\ INITSYSTEM=systemd \\\ PREFIX=%{_prefix} \\\ PYTHON_BINARY=%{__python2} \\\ SHELL_BINARY=/bin/sh \\\ USE_AUTHPAM=true \\\ USE_DNSSEC=%{USE_DNSSEC} \\\ USE_FIPSCHECK=false \\\ USE_LABELED_IPSEC=true \\\ USE_LDAP=true \\\ USE_LIBCAP_NG=true \\\ USE_LIBCURL=true \\\ USE_NM=true \\\ USE_NSS_IPSEC_PROFILE=true \\\ USE_NSS_KDF=true \\\ USE_SECCOMP=true \\\ USE_XFRM_INTERFACE_IFLA_HEADER=true \\\ %{nil} #global prever rc1 Name: libreswan Summary: Internet Key Exchange (IKEv1 and IKEv2) implementation for IPsec Version: 4.14 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: gcc make BuildRequires: audit-libs-devel BuildRequires: bison BuildRequires: curl-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: 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: coreutils Requires: iproute Requires: logrotate Requires: nss >= %{nss_version} Requires: nss-softokn Requires: nss-tools %{?systemd_requires} 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 USERLINK="%{?__global_ldflags}" \ WERROR_CFLAGS="-Werror -Wno-error=address -Wno-missing-braces -Wno-missing-field-initializers" \ %{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 install -d %{buildroot}%{_sbindir} install -d %{buildroot}%{_sysctldir} install -m 0644 packaging/rhel/libreswan-sysctl.conf \ %{buildroot}%{_sysctldir}/50-libreswan.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 %sysctl_apply 50-libreswan.conf %preun %systemd_preun ipsec.service %postun %systemd_postun_with_restart ipsec.service %files %license LICENSE COPYING %doc CHANGES CREDITS README* %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) %{_sysctldir}/50-libreswan.conf %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 %config(noreplace) %{_sysconfdir}/logrotate.d/libreswan %{_sbindir}/ipsec %{_libexecdir}/ipsec %doc %{_mandir}/*/* %changelog * Mon Mar 11 2024 Team Libreswan - 4.14-1 - Automated build from release tar ball libreswan-4.14/packaging/rhel/8/000077500000000000000000000000001457372064200164675ustar00rootroot00000000000000libreswan-4.14/packaging/rhel/8/libreswan.spec000066400000000000000000000146051457372064200213370ustar00rootroot00000000000000%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.44.0-8 %global unbound_version 1.6.6 # Libreswan config options. With these settings, libreswan # does not require its own FIPS validation. Only the system # and NSS needs to be FIPS validated. %global libreswan_config \\\ FINALLIBEXECDIR=%{_libexecdir}/ipsec \\\ FINALMANDIR=%{_mandir} \\\ FINALNSSDIR=%{_sysconfdir}/ipsec.d \\\ INITSYSTEM=systemd \\\ NSS_HAS_IPSEC_PROFILE=true \\\ NSS_REQ_AVA_COPY=false \\\ PREFIX=%{_prefix} \\\ PYTHON_BINARY=%{__python3} \\\ SHELL_BINARY=%{_bindir}/sh \\\ USE_AUTHPAM=true \\\ USE_DNSSEC=true \\\ USE_FIPSCHECK=false \\\ USE_LABELED_IPSEC=true \\\ USE_LDAP=true \\\ USE_LIBCAP_NG=true \\\ USE_LIBCURL=true \\\ USE_LINUX_AUDIT=true \\\ USE_NM=true \\\ USE_NSS_KDF=true \\\ USE_SECCOMP=true \\\ %{nil} #global prever rc1 Name: libreswan Summary: IPsec implementation with IKEv1 and IKEv2 keying protocols # version is generated in the release script Version: 4.14 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: flex BuildRequires: gcc BuildRequires: hostname BuildRequires: ldns-devel BuildRequires: libcap-ng-devel BuildRequires: libevent-devel BuildRequires: libseccomp-devel BuildRequires: libselinux-devel BuildRequires: make BuildRequires: nspr-devel BuildRequires: nss-devel >= %{nss_version} BuildRequires: nss-tools BuildRequires: openldap-devel BuildRequires: pam-devel BuildRequires: pkgconfig BuildRequires: redhat-rpm-config BuildRequires: systemd-devel BuildRequires: unbound-devel >= %{unbound_version} BuildRequires: xmlto %if 0%{with_efence} BuildRequires: ElectricFence %endif Requires: coreutils Requires: iproute >= 2.6.8 Requires: nss >= %{nss_version} Requires: nss-softokn Requires: nss-tools Requires: procps-ng Requires: unbound-libs >= %{unbound_version} Suggests: logrotate %{?systemd_requires} %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} # enable crypto-policies support sed -i "s:#[ ]*include \(.*\)\(/crypto-policies/back-ends/libreswan.config\)$:include \1\2:" 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 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 install -d %{buildroot}%{_sbindir} install -d %{buildroot}%{_sysctldir} install -m 0644 packaging/rhel/libreswan-sysctl.conf \ %{buildroot}%{_sysctldir}/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 : 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 %sysctl_apply 50-libreswan.conf %preun %systemd_preun ipsec.service %postun %systemd_postun_with_restart ipsec.service %files %license COPYING LICENSE %doc CHANGES CREDITS README* %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) %{_sysctldir}/50-libreswan.conf %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 %config(noreplace) %{_sysconfdir}/logrotate.d/libreswan %{_sbindir}/ipsec %{_libexecdir}/ipsec %attr(0644,root,root) %doc %{_mandir}/*/* %changelog * Mon Mar 11 2024 Team Libreswan - 4.14-1 - Automated build from release tar ball libreswan-4.14/packaging/rhel/libreswan-sysctl.conf000066400000000000000000000010151457372064200224710ustar00rootroot00000000000000# 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-4.14/packaging/suse/000077500000000000000000000000001457372064200163455ustar00rootroot00000000000000libreswan-4.14/packaging/suse/README.suse000066400000000000000000000001661457372064200202060ustar00rootroot00000000000000The package files for SUSE (openSUSE, SLED, SLES) can be found on: https://software.opensuse.org/package/libreswan libreswan-4.14/packaging/utils/000077500000000000000000000000001457372064200165265ustar00rootroot00000000000000libreswan-4.14/packaging/utils/ciabot.pl000077500000000000000000000151211457372064200203270ustar00rootroot00000000000000#!/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-4.14/packaging/utils/git-private-update-hook000077500000000000000000000012621457372064200231260ustar00rootroot00000000000000#!/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-4.14/packaging/utils/git-update-hook000077500000000000000000000004231457372064200214540ustar00rootroot00000000000000#!/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-4.14/packaging/utils/makerelease000077500000000000000000000025101457372064200207300ustar00rootroot00000000000000#!/bin/sh if [ ! -f mk/version.mk ] 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-4.14/packaging/utils/makeshadowdir000077500000000000000000000022471457372064200213030ustar00rootroot00000000000000#!/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-4.14/packaging/utils/manlink000077500000000000000000000033271457372064200201120ustar00rootroot00000000000000#! /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-4.14/packaging/utils/refnames.sh000077500000000000000000000011071457372064200206640ustar00rootroot00000000000000#!/bin/sh -e awk ' BEGIN { debug = 0 } // && !manvolnum { manvolnum = $0 gsub(/[^0-9]*/, "", manvolnum) if (debug) print "manvolnum:", manvolnum >> "/dev/stderr" } // { refname = $0 if (debug) print "refname:", refname >> "/dev/stderr" sub(/[^>]*>/, "", refname) if (debug) print "refname:", refname >> "/dev/stderr" sub(/<.*/, "", refname) if (debug) print "refname:", refname >> "/dev/stderr" gsub(/ /, "_", refname) if (debug) print "refname:", refname >> "/dev/stderr" print refname "." manvolnum } ' $@ libreswan-4.14/packaging/utils/setlibreswanversion000077500000000000000000000015231457372064200225650ustar00rootroot00000000000000#!/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-4.14/programs/000077500000000000000000000000001457372064200152745ustar00rootroot00000000000000libreswan-4.14/programs/Makefile000066400000000000000000000033001457372064200167300ustar00rootroot00000000000000# Copyright (C) 1998, 1999 Henry Spencer. # Copyright (C) 1999, 2000, 2001 Richard Guy Briggs # Copyright (C) 2012 Paul Wouters # Copyright (C) 2015,2017,2022 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)/mk/config.mk SUBDIRS= # first SUBDIRS += pluto SUBDIRS += whack SUBDIRS += _import_crl SUBDIRS += _plutorun SUBDIRS += _secretcensor SUBDIRS += _unbound-hook SUBDIRS += _updown SUBDIRS += addconn SUBDIRS += algparse SUBDIRS += auto SUBDIRS += barf SUBDIRS += cavp SUBDIRS += ecdsasigkey SUBDIRS += ipsec SUBDIRS += letsencrypt ifneq ($(LINUX_VARIANT),) SUBDIRS += look.linux endif SUBDIRS += newhostkey SUBDIRS += readwriteconf SUBDIRS += rsasigkey SUBDIRS += setup ifneq ($(LINUX_VARIANT),) SUBDIRS += show.linux endif SUBDIRS += showhostkey SUBDIRS += showroute ifneq ($(LINUX_VARIANT),) SUBDIRS += verify.linux endif ifeq ($(USE_PORTEXCLUDES),true) SUBDIRS += portexcludes endif ifeq ($(USE_XFRM),true) SUBDIRS += _updown.xfrm endif ifneq ($(LINUX_VARIANT),) SUBDIRS += _stackmanager endif ifneq ($(BSD_VARIANT),) SUBDIRS += _realsetup.bsd SUBDIRS += _updown.bsd endif include $(top_srcdir)/mk/targets.mk libreswan-4.14/programs/_import_crl/000077500000000000000000000000001457372064200176055ustar00rootroot00000000000000libreswan-4.14/programs/_import_crl/Makefile000066400000000000000000000016051457372064200212470ustar00rootroot00000000000000# _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) USERLAND_LDFLAGS += $(NSS_LDFLAGS) USERLAND_LDFLAGS += $(NSPR_LDFLAGS) ifdef top_srcdir include $(top_srcdir)/mk/program.mk else include ../../mk/program.mk endif libreswan-4.14/programs/_import_crl/_import_crl.8.xml000066400000000000000000000027121457372064200230100ustar00rootroot00000000000000 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-4.14/programs/_import_crl/_import_crl.c000066400000000000000000000063101457372064200222620ustar00rootroot00000000000000/* 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 #include #include #include #include #include /* for NSS_Shutdown() */ #include "lswconf.h" #include "lswnss.h" #include "lswtool.h" #include "lswalloc.h" #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 enum pluto_exit_code 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 PLUTO_EXIT_FAIL; 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 PLUTO_EXIT_OK; } /* * _import_crl * the der blob is passed through STDIN from pluto's fork */ int main(int argc, char *argv[]) { ssize_t rd; int fin; struct logger *logger = tool_init_log(argv[0]); if (argc != 3) { fatal(PLUTO_EXIT_FAIL, logger, "expecting: "); } /* */ const char *len_str = argv[2]; char *len_end; errno = 0; /* strtol() doesn't clear errno; see "pertinent standards" */ ssize_t len = strtol(len_str, &len_end, 0); if (len_end == len_str) { fatal(PLUTO_EXIT_FAIL, logger, " is not a number: %s", len_str); } else if (*len_end != '\0') { fatal(PLUTO_EXIT_FAIL, logger, " contains grailing garbage: %s", len_str); } else if (errno != 0) { fatal_errno(PLUTO_EXIT_FAIL, logger, errno, " '%s' is out-of-range", len_str); } if (len <= 0) { fatal(PLUTO_EXIT_FAIL, logger, " must be positive: %s", len_str); } uint8_t *buf = alloc_things(uint8_t, len, "der buf"); if (buf == NULL) exit(-1); ssize_t tlen = len; uint8_t *tbuf = buf; while (tlen != 0 && (rd = read(STDIN_FILENO, buf, len)) != 0) { if (rd == -1) { if (errno == EINTR) continue; exit(-1); } tlen -= rd; buf += rd; } if ((buf - tbuf) != len) { fatal(PLUTO_EXIT_FAIL, logger, "less then %zd bytes read", len); } const struct lsw_conf_options *oco = lsw_init_options(); diag_t d = lsw_nss_setup(oco->nssdir, 0, logger); if (d != NULL) { fatal_diag(PLUTO_EXIT_FAIL, logger, &d, "%s", ""); } fin = import_crl(url, tbuf, len); if (tbuf != NULL) pfree(tbuf); NSS_Shutdown(); return fin; } libreswan-4.14/programs/_plutorun/000077500000000000000000000000001457372064200173235ustar00rootroot00000000000000libreswan-4.14/programs/_plutorun/Makefile000066400000000000000000000013561457372064200207700ustar00rootroot00000000000000# 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-4.14/programs/_plutorun/_plutorun.8.xml000066400000000000000000000042351457372064200222460ustar00rootroot00000000000000 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-4.14/programs/_plutorun/_plutorun.in000077500000000000000000000060241457372064200217070ustar00rootroot00000000000000#!@SHELL_BINARY@ # -*- mode: sh; sh-shell: sh -*- # 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-4.14/programs/_realsetup.bsd/000077500000000000000000000000001457372064200202065ustar00rootroot00000000000000libreswan-4.14/programs/_realsetup.bsd/Makefile000066400000000000000000000014141457372064200216460ustar00rootroot00000000000000# 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-4.14/programs/_realsetup.bsd/_realsetup.8.xml000066400000000000000000000034201457372064200232400ustar00rootroot00000000000000 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-4.14/programs/_realsetup.bsd/_realsetup.in000077500000000000000000000164311457372064200227110ustar00rootroot00000000000000#!@SHELL_BINARY@ # -*- mode: sh; sh-shell: sh -*- # # 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 overridable 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 # defaults for "config setup" items IPSECuniqueids=${IPSECuniqueids:-yes} IPSECcrlcheckinterval=${IPSECcrlcheckinterval:-0} IPSECprotostack=${IPSECprotostack:-bsdkame} IPSECplutostderrlogtime=${IPSECplutostderrlogtime:-no} # 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" KILLKERNELSTATE='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\"" "||" "{" \ $KILLKERNELSTATE ";" \ 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 $KILLKERNELSTATE rm -f /var/run/pluto.pid 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-4.14/programs/_realsetup.bsd/ipsec_realsetup.8000066400000000000000000000034461457372064200234750ustar00rootroot00000000000000'\" 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-4.14/programs/_secretcensor/000077500000000000000000000000001457372064200201325ustar00rootroot00000000000000libreswan-4.14/programs/_secretcensor/Makefile000066400000000000000000000013621457372064200215740ustar00rootroot00000000000000# 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-4.14/programs/_secretcensor/_secretcensor.8.xml000066400000000000000000000032361457372064200236640ustar00rootroot00000000000000 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-4.14/programs/_secretcensor/_secretcensor.in000077500000000000000000000036451457372064200233330ustar00rootroot00000000000000#!@SHELL_BINARY@ # -*- mode: sh; sh-shell: 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-4.14/programs/_stackmanager/000077500000000000000000000000001457372064200200735ustar00rootroot00000000000000libreswan-4.14/programs/_stackmanager/Makefile000066400000000000000000000013551457372064200215370ustar00rootroot00000000000000# 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-4.14/programs/_stackmanager/_stackmanager.8.xml000066400000000000000000000062501457372064200235650ustar00rootroot00000000000000 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 the modules for the specific IPsec stack. 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-4.14/programs/_stackmanager/_stackmanager.in000066400000000000000000000157411457372064200232320ustar00rootroot00000000000000#!@SHELL_BINARY@ # -*- mode: sh; sh-shell: sh -*- # 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="" 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@" # not all kernels have either :/ xfrm_stat=/proc/sys/net/core/xfrm_acq_expires xfrm_old=/proc/net/xfrm_stat action="${1}" if [ -z "${action}" ]; then echo "no action specified - aborted" >&2 exit 1 fi stop_xfrm() { local wait larval_drop wait="" larval_drop="" # Validate wait option [ "${1}" = "--wait" -o "${1}" = "-w" ] && wait="${1}" if [ -f ${xfrm_stat} -o -f ${xfrm_old}]; 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 # XFRM 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" start_xfrm() { # 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 /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: cannot 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 } stop() { stop_xfrm } cryptomodules() { # 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 ccm gcm ctr cts \ deflate 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 } # 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=xfrm else stack="$(ASAN_OPTIONS=detect_leaks=0 ipsec addconn --config ${IPSEC_CONF} --liststack | grep -v "#")" fi case ${stack} in xfrm|none) ;; auto|mast|klips|netkey) echo "protostack= values auto, klips, mast and netkey are not longer supported, defaulting to xfrm" >&2 stack=xfrm ;; *) echo "unknown stack ${stack}" >&2 exit 1 ;; esac case ${action} in stop) # We don't unload XFRM IPsec on stop if [ -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 xfrm) start_xfrm ;; esac ;; restart) stop start ;; *) echo "unknown action ${action}" >&2 exit 1 ;; esac exit 0 libreswan-4.14/programs/_unbound-hook/000077500000000000000000000000001457372064200200435ustar00rootroot00000000000000libreswan-4.14/programs/_unbound-hook/Makefile000066400000000000000000000014041457372064200215020ustar00rootroot00000000000000# 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-4.14/programs/_unbound-hook/_unbound-hook.8.xml000066400000000000000000000032121457372064200235000ustar00rootroot00000000000000 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-4.14/programs/_unbound-hook/_unbound-hook.in000077500000000000000000000033321457372064200231460ustar00rootroot00000000000000#!@SHELL_BINARY@ # -*- mode: sh; sh-shell: sh -*- # # Copyright (C) 2018 Paul Wouters # Copyright (C) 2022 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. set -u #set -e if test $# -lt 4 ; then echo "Usage: QNAME TTL IP RRDATA" 1>&2 exit 1 fi # Get my %defaultroute (gateway) IP address. myip=$(ipsec showroute --gateway 8.8.8.8) qname=$1 ; shift ttl=$1 ; shift ip=$1 ; shift # Remainder of parameters are quoted DNS RRs, iterate over each # breaking it down. for rr in "$@" ; do # reset args to set -- ${rr} if test $# -lt 5 ; then echo "ingoring short rr record: $@" 1>&2 exit 1 fi gwprec=$1 ; shift gwtype=$1 ; shift gwalg=$1 ; shift gwid=$1 ; shift pubkey=$1 ; shift echo "processing an IPSECKEY record for Opportunistic IPsec to ${qname}(${ip})" ipsec whack --keyid "${ip}" --addkey --pubkeyrsa 0s"${pubkey}" ipsec whack --keyid @"${qname}" --addkey --pubkeyrsa 0s"${pubkey}" done # done injecting all IPSECKEY records into pluto - try actual OE now ipsec whack --oppohere "${myip}" --oppothere "${ip}" #cmdoeqname = "ipsec whack --oppohere %s --oppothere %s"%(myip, qname) #ret, output = commands.getstatusoutput(cmdoeqname) ipsec whack --trafficstatus libreswan-4.14/programs/_updown.bsd/000077500000000000000000000000001457372064200175165ustar00rootroot00000000000000libreswan-4.14/programs/_updown.bsd/Makefile000066400000000000000000000014141457372064200211560ustar00rootroot00000000000000# 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.bsd ifdef top_srcdir include $(top_srcdir)/mk/program.mk else include ../../mk/program.mk endif programs: ${PROGRAM} libreswan-4.14/programs/_updown.bsd/_updown.bsd.8.xml000066400000000000000000000034621457372064200226350ustar00rootroot00000000000000 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-4.14/programs/_updown.bsd/_updown.bsd.in000066400000000000000000000157721457372064200223040ustar00rootroot00000000000000#! /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_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_CONNECTION_TYPE # is type of the connection, "tunnel" or "transport". # # 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 interface used by encrypted traffic and IKE traffic # # 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_SA_REQID # When using KAME or XFRM/NETKEY, the IPsec SA reqid value # # PLUTO_VIRT_INTERFACE # is the name of ipsec interface used by clear traffic in/out # 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-4.14/programs/_updown.xfrm/000077500000000000000000000000001457372064200177225ustar00rootroot00000000000000libreswan-4.14/programs/_updown.xfrm/Makefile000066400000000000000000000014151457372064200213630ustar00rootroot00000000000000# 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.xfrm ifdef top_srcdir include $(top_srcdir)/mk/program.mk else include ../../mk/program.mk endif programs: ${PROGRAM} libreswan-4.14/programs/_updown.xfrm/_updown.xfrm.8.xml000066400000000000000000000032151457372064200232410ustar00rootroot00000000000000 PaulWoutersplaceholder to suppress warning _UPDOWN 8 25 February 2008 libreswan Executable programs ipsec _updown.xfrm 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-4.14/programs/_updown.xfrm/_updown.xfrm.in000066400000000000000000000677631457372064200227230ustar00rootroot00000000000000#!@SHELL_BINARY@ # -*- mode: sh; sh-shell: 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_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_CONNECTION_TYPE # is type of the connection, "tunnel" or "transport". # # PLUTO_CONN_POLICY # the policy of the connection, as in: # RSASIG+ENCRYPT+TUNNEL+PFS+DONTREKEY+OPPORTUNISTIC # +failureDROP+lKOD+rKOD # # CAT=YES| # if client address translation inside IPsec stack is enabled # # 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 interface used by encrypted traffic and IKE traffic # # PLUTO_ME # is the IP address of our host. # # PLUTO_MY_ID # is our ID. # # PLUTO_METRIC # is the metric to set for the route # # PLUTO_MTU # is the mtu to set for the route # # PLUTO_ADD_TIME # Time the IPsec SA was added to the kernel # # PLUTO_MOBIKE_EVENT # wether the connection is underdoing MOBIKE migration # # 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_ID # is the ID 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_PEER_CA # is the DN of the peer's CA that signed its certificate # # PLUTO_CFG_CLIENT=0|1 # is MODECFG or IKEv2 Config client. # # PLUTO_CFG_SERVER=0|1 # is MODECFG or IKEv2 Config server. # # PLUTO_PEER_DNS_INFO # The peer's supplied DNS information (IKEv1 and IKEv2) # # PLUTO_PEER_DOMAIN_INFO # The peer's supplied domain list for local resolving (IKEv2 only) # # PLUTO_PEER_BANNER # is the peer's provided banner # # PLUTO_NM_CONFIGURED=0|1 # is NetworkManager used for resolv.conf update # # PLUTO_CONN_ADDRFAMILY # is the family type, "ipv4" or "ipv6" # # PLUTO_CONN_KIND # is the "kind" of connection (CK_PERMANENT, CK_INSTANCE, etc) # # PLUTO_STACK # is the local IPsec kernel stack used, eg XFRM, BSDKAME, NOSTACK # # PLUTO_IS_PEER_CISCO=0|1 # remote server type is cisco. Add support for cisco extensions # when used with xauth. # # PLUTO_SA_REQID # When using KAME or XFRM, 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_XFRMI_FWMARK # use outgoing mark # # 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 ipsec interface used by clear traffic in/out # # INTERFACE_IP # The IP to configure / expect on the interface? Currently is never set # # PLUTO_XFRM_ROUTE # if an XFRM (ipsec-device) has been specified, value will be "yes" # # 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. # # CONNMARK_IN # the incoming mark to use # # CONNMARK_OUT # the outgoing mark to use # # 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. # # VTI_IP # The IP to configure on the VTI device # # SPI_IN / SPI_OUT # The inbound and outbound SPI's of the connection. # # PLUTO_INBYTES # total bytes received # # PLUTO_OUTBYTES # total bytes sent # # NFLOG # is the nflog group to use # # 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 "unknown 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 signal 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 "leftsubnet == rightsubnet = ${PLUTO_PEER_CLIENT} cannot 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 we 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 } firewall_cmd() { HAVE_IPTABLES=@HAVE_IPTABLES@ HAVE_NFTABLES=@HAVE_NFTABLES@ # if [ "${HAVE_NFTABLES}" = true ]; #nft has precedence # FIREWALL=NFTABLES; if [ "${HAVE_IPTABLES}" = true ]; then FIREWALL=IPTABLES else FIREWALL="" fi } # TODO: We need to specify CIDR mask but our _MASK variables are in old school format # TODO: Exclude udp 4500 traffic addnflog() { firewall_cmd if [ "${FIREWALL}" = IPTABLES -a -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() { firewall_cmd if [ "${FIREWALL}" = IPTABLES -a -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() { firewall_cmd if [ "${FIREWALL}" = IPTABLES -a -n "${CAT}" -a "${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() { firewall_cmd if [ "${FIREWALL}" = IPTABLES -a -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-4.14/programs/_updown/000077500000000000000000000000001457372064200167475ustar00rootroot00000000000000libreswan-4.14/programs/_updown/Makefile000066400000000000000000000014021457372064200204040ustar00rootroot00000000000000# 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-4.14/programs/_updown/_updown.8.xml000066400000000000000000000144751457372064200213250ustar00rootroot00000000000000 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, 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_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 real interface used by encrypted traffic and IKE traffic. 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-4.14/programs/_updown/_updown.in000066400000000000000000000075031457372064200207570ustar00rootroot00000000000000#!@SHELL_BINARY@ # -*- mode: sh; sh-shell: 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_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_CONNECTION_TYPE # is type of the connection, "tunnel" or "transport". # # 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_STACK # The kernel level IPstack used (see protostack=) # # PLUTO_SA_REQID # When using KAME or XFRM/NETKEY, the IPsec SA reqid value 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-4.14/programs/addconn/000077500000000000000000000000001457372064200167025ustar00rootroot00000000000000libreswan-4.14/programs/addconn/Makefile000066400000000000000000000017251457372064200203470ustar00rootroot00000000000000# 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) USERLAND_LDFLAGS += $(UNBOUND_LDFLAGS) USERLAND_LDFLAGS += $(SECCOMP_LDFLAGS) ifdef top_srcdir include $(top_srcdir)/mk/program.mk else include ../../mk/program.mk endif libreswan-4.14/programs/addconn/addconn.8.xml000066400000000000000000000147201457372064200212040ustar00rootroot00000000000000 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-4.14/programs/addconn/addconn.c000066400000000000000000000407571457372064200204710ustar00rootroot00000000000000/* * 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" #include "addr_lookup.h" /* for resolve_default_route() */ #ifdef USE_DNSSEC # include "dnssec.h" #endif #ifdef USE_SECCOMP #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_default_routes(struct starter_conn *conn UNUSED, struct logger *logger) { lset_t verbose_rc_flags = verbose ? (WHACK_STREAM|NO_PREFIX) : LEMPTY; resolve_default_route(&conn->left, &conn->right, verbose_rc_flags, logger); resolve_default_route(&conn->right, &conn->left, verbose_rc_flags, logger); } #ifdef USE_SECCOMP static void init_seccomp_addconn(uint32_t def_action, struct logger *logger) { scmp_filter_ctx ctx = seccomp_init(def_action); if (ctx == NULL) { fatal(PLUTO_EXIT_SECCOMP_FAIL, logger, "seccomp_init_addconn() failed!"); } /* * 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(access); LSW_SECCOMP_ADD(arch_prctl); LSW_SECCOMP_ADD(brk); LSW_SECCOMP_ADD(bind); LSW_SECCOMP_ADD(clone); LSW_SECCOMP_ADD(clock_gettime); LSW_SECCOMP_ADD(close); LSW_SECCOMP_ADD(connect); LSW_SECCOMP_ADD(epoll_create); LSW_SECCOMP_ADD(epoll_create1); LSW_SECCOMP_ADD(epoll_ctl); LSW_SECCOMP_ADD(epoll_wait); LSW_SECCOMP_ADD(epoll_pwait); LSW_SECCOMP_ADD(exit_group); LSW_SECCOMP_ADD(fcntl); LSW_SECCOMP_ADD(fstat); LSW_SECCOMP_ADD(futex); LSW_SECCOMP_ADD(getdents); LSW_SECCOMP_ADD(getegid); LSW_SECCOMP_ADD(getpid); LSW_SECCOMP_ADD(getrlimit); LSW_SECCOMP_ADD(geteuid); LSW_SECCOMP_ADD(getgid); LSW_SECCOMP_ADD(getrandom); LSW_SECCOMP_ADD(getuid); LSW_SECCOMP_ADD(ioctl); LSW_SECCOMP_ADD(mmap); LSW_SECCOMP_ADD(lseek); LSW_SECCOMP_ADD(munmap); LSW_SECCOMP_ADD(mprotect); LSW_SECCOMP_ADD(newfstatat); LSW_SECCOMP_ADD(open); LSW_SECCOMP_ADD(openat); LSW_SECCOMP_ADD(pipe2); LSW_SECCOMP_ADD(poll); LSW_SECCOMP_ADD(prctl); LSW_SECCOMP_ADD(read); LSW_SECCOMP_ADD(readlink); LSW_SECCOMP_ADD(recvfrom); LSW_SECCOMP_ADD(rt_sigaction); LSW_SECCOMP_ADD(rt_sigprocmask); LSW_SECCOMP_ADD(sendto); LSW_SECCOMP_ADD(setsockopt); LSW_SECCOMP_ADD(set_robust_list); LSW_SECCOMP_ADD(set_tid_address); LSW_SECCOMP_ADD(sigreturn); LSW_SECCOMP_ADD(socket); LSW_SECCOMP_ADD(socketcall); LSW_SECCOMP_ADD(socketpair); LSW_SECCOMP_ADD(stat); LSW_SECCOMP_ADD(statfs); LSW_SECCOMP_ADD(uname); LSW_SECCOMP_ADD(waitpid); LSW_SECCOMP_ADD(write); #ifdef USE_EFENCE LSW_SECCOMP_ADD(madvise); #endif int rc = seccomp_load(ctx); if (rc < 0) { seccomp_release(ctx); fatal_errno(PLUTO_EXIT_SECCOMP_FAIL, logger, -rc, "seccomp_load() failed!"); } } #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[]) { struct logger *logger = 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; 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 (ctlsocket == NULL) ctlsocket = clone_str(DEFAULT_CTL_SOCKET, "default ctlsocket"); 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, &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; } if (configfile == NULL) configfile = clone_str(IPSEC_CONF, "default ipsec.conf file"); 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, logger); 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', %s\n", configfile, errl.errors); pfree(errl.errors); } if (checkconfig) { confread_free(cfg); exit(0); } } #ifdef USE_SECCOMP switch (cfg->setup.options[KBF_SECCOMP]) { case SECCOMP_ENABLED: init_seccomp_addconn(SCMP_ACT_KILL, logger); break; case SECCOMP_TOLERANT: init_seccomp_addconn(SCMP_ACT_ERRNO(EACCES), logger); 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], logger); #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=keep, 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_KEEP || conn->desired_state == STARTUP_START) { if (verbose > 0) printf(" %s\n", conn->name); resolve_default_routes(conn, logger); starter_whack_add_conn(cfg, conn, logger); } } /* * 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, logger); } } 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\n", 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_default_routes(conn, logger); exit_status = starter_whack_add_conn(cfg, conn, logger); 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("xfrm\n"); } } } confread_free(cfg); exit(0); } if (configsetup) { const struct keyword_def *kd; printf("%s %sconfreadstatus=''\n", export, varprefix); printf("%s configfile='%s'\n", export, configfile); printf("%s ctlsocket='%s'\n", export, ctlsocket); 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='%jd'\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 pfreeany(ctlsocket); pfreeany(configfile); /* * 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-4.14/programs/algparse/000077500000000000000000000000001457372064200170725ustar00rootroot00000000000000libreswan-4.14/programs/algparse/Makefile000066400000000000000000000020351457372064200205320ustar00rootroot00000000000000# 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 OBJS += $(LIBRESWANLIB) OBJS += $(LSWTOOLLIBS) USERLAND_LDFLAGS += $(NSS_LDFLAGS) USERLAND_LDFLAGS += $(NSPR_LDFLAGS) ifdef top_srcdir include $(top_srcdir)/mk/program.mk else include ../../mk/program.mk endif local-check: $(PROGRAM) $(top_srcdir)/testing/guestbin/algparse.sh $(builddir)/$(PROGRAM) libreswan-4.14/programs/algparse/algparse.c000066400000000000000000000470321457372064200210420ustar00rootroot00000000000000#include #include #include "lswlog.h" #include "lswtool.h" #include "lswalloc.h" #include "lswnss.h" #include "lswfips.h" #include "lswconf.h" #include "crypt_symkey.h" /* for init_crypt_symkey() */ #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 impaired = 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; #define ERROR 124 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, \ .logger_rc_flags = ERROR_STREAM|RC_LOG, \ .logger = logger, \ .check_pfs_vs_dh = CHECK, \ .ignore_parser_errors = ignore_parser_errors, \ }; \ printf("algparse "); \ if (impaired) { \ 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->diag == NULL); \ FOR_EACH_PROPOSAL(proposals, proposal) { \ JAMBUF(buf) { \ jam(buf, "\t"); \ jam_proposal(buf, proposal); \ fprintf(stdout, PRI_SHUNK"\n", \ pri_shunk(jambuf_as_shunk(buf))); \ } \ } \ free_proposals(&proposals); \ if (expected == FAIL) { \ failures++; \ fprintf(stderr, \ "UNEXPECTED PASS: %s%s%s\n", \ #PARSE, \ algstr == NULL ? "" : "=", \ algstr == NULL ? "" : algstr); \ } \ } else { \ pexpect(parser->diag != NULL); \ printf("\tERROR: %s\n", str_diag(parser->diag)); \ 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); \ } /* * 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; } } #define esp(EXPECTED, ALGSTR) test_esp(EXPECTED, ALGSTR, logger) static void test_esp(enum expect expected, const char *algstr, struct logger *logger) { CHECK(true, esp, kernel_alg_is_ok); } #define ah(EXPECTED, ALGSTR) test_ah(EXPECTED, ALGSTR, logger) static void test_ah(enum expect expected, const char *algstr, struct logger *logger) { CHECK(true, ah, kernel_alg_is_ok); } #define ike(EXPECTED, ALGSTR) test_ike(EXPECTED, ALGSTR, logger) static void test_ike(enum expect expected, const char *algstr, struct logger *logger) { CHECK(false, ike, ike_alg_is_ike); } typedef void (protocol_t)(enum expect expected, const char *, struct logger *logger); struct protocol { const char *name; protocol_t *parser; }; const struct protocol protocols[] = { { "ike", test_ike, }, { "ah", test_ah, }, { "esp", test_esp, }, }; static void all(const char *algstr, struct logger *logger) { for (const struct protocol *protocol = protocols; protocol < protocols + elemsof(protocols); protocol++) { protocol->parser(COUNT, algstr, logger); } } static void test_proposal(const char *arg, struct logger *logger) { 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, logger); return; } if (startswith(arg, protocol->name) && arg + strlen(protocol->name) == eq) { protocol->parser(COUNT, eq + 1, logger); return; } } if (eq != NULL) { fprintf(stderr, "unrecognized PROTOCOL in '%s'", arg); exit(1); } all(arg, logger); } static void test(struct logger *logger) { /* * 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 unambiguous */ esp(true, "3des-sha1-modp8192"); /* allow '-' when unambiguous */ # 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(impaired, "3des168-sha1"); /* wrong keylen */ esp(impaired, "3des-null"); /* non-null integ */ esp(impaired, "aes128-null"); /* non-null-integ */ esp(impaired, "aes224-sha1"); /* wrong keylen */ esp(impaired, "aes-224-sha1"); /* wrong keylen */ esp(false, "aes0-sha1"); /* wrong keylen */ esp(false, "aes-0-sha1"); /* wrong keylen */ esp(impaired, "aes512-sha1"); /* wrong keylen */ esp(false, "aes-sha1555"); /* unknown integ */ esp(impaired, "camellia666-sha1"); /* wrong keylen */ esp(false, "blowfish"); /* obsoleted */ esp(false, "des-sha1"); /* obsoleted */ esp(impaired, "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(impaired, "aes_gcm-md5"); /* AEAD must have auth null */ esp(false, "mars"); /* support removed */ esp(impaired, "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(impaired, "aes-sha1"); #endif ah(false, "vanityhash1"); #ifdef USE_AES ah(impaired, "aes_gcm_c-256"); #endif ah(false, "id3"); /* should be rejected; idXXX removed */ #ifdef USE_3DES ah(impaired, "3des"); #endif ah(impaired, "null"); #ifdef USE_AES ah(impaired, "aes_gcm"); ah(impaired, "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, "3des+aes"); 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 */ /* quads */ ike(false, "aes-sha1-sha2-ecp_521"); ike(false, "aes-sha2-sha2;ecp_521"); /* fqn */ ike(ike_version == IKEv2, "aes-sha1_96-sha2-ecp_521"); ike(ike_version == IKEv2, "aes-sha1_96-sha2;ecp_521"); /* toss duplicates */ ike(ike_version == IKEv2, "aes+aes-sha1+sha1-modp8192+modp8192"); /* cycle through 3des-sha2-modp4096 */ ike(ike_version == IKEv2, "3des+aes+aes-sha2+sha1+sha1-modp4096+modp8192+modp8192"); ike(ike_version == IKEv2, "aes+3des+aes-sha1+sha2+sha1-modp8192+modp4096+modp8192"); ike(ike_version == IKEv2, "aes+aes+3des-sha1+sha1+sha2-modp8192+modp8192+modp4096"); /* keys */ ike(ike_version == IKEv2, "aes+aes128+aes256"); /* toss 128/256 */ ike(ike_version == IKEv2, "aes128+aes+aes256"); /* toss 256 */ ike(ike_version == IKEv2, "aes128+aes256+aes"); /* proposals */ ike(true, "aes-sha1-modp8192,aes-sha1-modp8192,aes-sha1-modp8192"); ike(true, "aes-sha1-modp8192,aes-sha2-modp8192,aes-sha1-modp8192"); /* almost middle */ /* aead */ ike(ike_version == IKEv2, "aes_gcm"); ike(ike_version == IKEv2, "aes_gcm-sha2"); ike(ike_version == IKEv2, "aes_gcm-sha2-modp2048"); ike(ike_version == IKEv2, "aes_gcm-sha2;modp2048"); ike(false, "aes_gcm-modp2048"); /* ';' required - PRF */ ike(ike_version == IKEv2, "aes_gcm;modp2048"); ike(ike_version == IKEv2, "aes_gcm-none"); ike(ike_version == IKEv2, "aes_gcm-none-sha2"); ike(ike_version == IKEv2, "aes_gcm-none-sha2-modp2048"); ike(ike_version == IKEv2, "aes_gcm-none-sha2;modp2048"); ike(false, "aes_gcm-none-modp2048"); /* ';' required - INTEG */ ike(ike_version == IKEv2, "aes_gcm-none;modp2048"); ike(false, "aes_gcm-sha1-none-modp2048"); /* old syntax */ ike(false, "aes_gcm-sha1-none;modp2048"); /* old syntax */ ike(false, "aes+aes_gcm"); /* mixing AEAD and NORM encryption */ /* syntax */ ike(false, ","); /* empty algorithm */ ike(false, "aes,"); /* empty algorithm */ ike(false, "aes,,aes"); /* empty algorithm */ ike(false, ",aes"); /* empty algorithm */ ike(false, "-"); /* empty algorithm */ ike(false, "+"); /* empty algorithm */ ike(false, ";"); /* empty algorithm */ ike(false, "aes-"); /* empty algorithm */ ike(false, "aes+"); /* empty algorithm */ ike(false, "aes;"); /* empty algorithm */ ike(false, "-aes"); /* empty algorithm */ ike(false, "+aes"); /* empty algorithm */ ike(false, ";aes"); /* empty algorithm */ ike(false, "aes+-"); /* empty algorithm */ ike(false, "aes+;"); /* empty algorithm */ ike(false, "aes++"); /* empty algorithm */ } static void usage(void) { fprintf(stderr, "Usage:\n" "\n" " algparse [