pax_global_header00006660000000000000000000000064147576766100014535gustar00rootroot0000000000000052 comment=7a9c33385d0e7981b09cc3a552215788fcf79563 libreswan-5.2/000077500000000000000000000000001475767661000133715ustar00rootroot00000000000000libreswan-5.2/.github/000077500000000000000000000000001475767661000147315ustar00rootroot00000000000000libreswan-5.2/.github/ISSUE_TEMPLATE/000077500000000000000000000000001475767661000171145ustar00rootroot00000000000000libreswan-5.2/.github/ISSUE_TEMPLATE/bug.yml000066400000000000000000000052041475767661000204150ustar00rootroot00000000000000name: Bug Report description: File a bug report. type: bug body: - type: textarea attributes: label: Please Tell Us About Your System description: | Please provide the output from `ipsec whack --version` and `uname -a`. If the other end is different, then include that as well. validations: required: true - type: checkboxes id: ike_version attributes: label: IKE Version description: | Please note that IKEv1 is (depreciated)[https://www.rfc-editor.org/rfc/rfc9395]. If you can, please try reproducing the problem using IKEv2. options: - label: IKEv1 - label: IKEv2 validations: required: true - type: checkboxes id: protocol attributes: label: Protocol description: | Please note that AH has, for the most part, been made obsolete by ESP with NULL integrity (the exception is AH combined with transport mode). options: - label: ESP - label: AH validations: required: false - type: checkboxes id: interface attributes: label: Is IPsec or VTI involved? description: | Please note that on Linux, VTI has been replaced by XFRMI (enabled using `ipsec-interface=`). (The BSD IPsec devices are only supported using `ipsec-interface=`). options: - label: IPsec Interface - label: VTI validations: required: false - type: textarea attributes: label: What happened? description: Also tell us, what you expected to happen? validations: required: true - type: textarea attributes: label: Your configuration description: Please copy and past your configuration file. placeholder: | - if necessary remove sensitive details but keep as much information as possible - this will be automatically formatted into code, so no need for backticks render: shell validations: required: false - type: textarea attributes: label: Relevant log output description: Please copy and paste the relevant log output placeholder: | - if necessary remove sensitive details but keep as much information as possible - there is no need to include debug output most problems are better understood with just the standard logs - this will be automatically formatted into code, so no need for backticks. render: shell validations: required: false - type: markdown attributes: value: | Thanks for taking the time to fill out this bug report! validations: required: false libreswan-5.2/.github/ISSUE_TEMPLATE/config.yml000066400000000000000000000000341475767661000211010ustar00rootroot00000000000000blank_issues_enabled: true libreswan-5.2/.github/ISSUE_TEMPLATE/task.yml000066400000000000000000000002521475767661000206000ustar00rootroot00000000000000name: Task description: A specific work item type: task body: - type: textarea attributes: label: What needs to be done validations: required: true libreswan-5.2/.github/workflows/000077500000000000000000000000001475767661000167665ustar00rootroot00000000000000libreswan-5.2/.github/workflows/codeql.yml000066400000000000000000000066021475767661000207640ustar00rootroot00000000000000# 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: "29 17 * * 0" # Enable manual trigger of the action. Useful for debugging purposes workflow_dispatch: 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', 'ruby' ] # Use only 'java' to analyze code written in Java, Kotlin or both # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support steps: - name: Checkout repository uses: actions/checkout@v3 - name: Install build dependencies run: | sudo apt-get update sudo apt-get install -fy --no-install-recommends libnss3-dev libnspr4-dev libpam-dev libcap-ng-dev libcap-ng-utils libselinux-dev libcurl3-nss-dev libldns-dev libunbound-dev libnss3-tools libevent-dev xmlto libsystemd-dev # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL # pinning to full commit hash from tagged version v2.20.4 uses: github/codeql-action/init@489225d82a57396c6f426a40e66d461b16b3461d 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. # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs # queries: security-extended,security-and-quality # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild # pinning to full commit hash from tagged version v2.20.4 uses: github/codeql-action/autobuild@489225d82a57396c6f426a40e66d461b16b3461d # ℹ️ Command-line programs to run using the OS shell. # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - run: | echo "Building... " make base - name: Perform CodeQL Analysis # pinning to full commit hash from tagged version v2.20.4 uses: github/codeql-action/analyze@489225d82a57396c6f426a40e66d461b16b3461d with: category: "/language:${{matrix.language}}" libreswan-5.2/.github/workflows/semgrep.yml000066400000000000000000000032301475767661000211510ustar00rootroot00000000000000# Name of this GitHub Actions workflow. name: Semgrep on: # Scan changed files in PRs (diff-aware scanning): pull_request: {} # Scan mainline branches and report all findings: push: branches: ["master", "main"] # Schedule the CI job (this method uses cron syntax): schedule: - cron: "20 17 * * *" # Sets Semgrep to scan every day at 17:20 UTC. # It is recommended to change the schedule to a random time. # Enable manual trigger of the action. Useful for debugging purposes workflow_dispatch: jobs: semgrep: # User definable name of this GitHub Actions job. name: Scan # If you are self-hosting, change the following `runs-on` value: runs-on: ubuntu-latest permissions: # required for all workflows security-events: write container: # A Docker image with Semgrep installed. Do not change this. image: returntocorp/semgrep # Skip any PR created by dependabot to avoid permission issues: if: (github.actor != 'dependabot[bot]') steps: # Fetch project source with GitHub Actions Checkout. - uses: actions/checkout@v3 # Run the "semgrep ci" command on the command line of the docker image. - run: semgrep ci --sarif --output=semgrep.sarif --config auto --exclude-rule c.lang.security.insecure-use-memset.insecure-use-memset --exclude testing/ - name: Upload SARIF file for GitHub Advanced Security Dashboard # pinning to full commit hash from tagged version v2.20.4 uses: github/codeql-action/upload-sarif@489225d82a57396c6f426a40e66d461b16b3461d with: sarif_file: semgrep.sarif if: ${{ hashFiles('semgrep.sarif') != '' }} libreswan-5.2/.gitignore000066400000000000000000000010021475767661000153520ustar00rootroot00000000000000*~ .*.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* 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* nohup.out libreswan-5.2/.travis.yml000066400000000000000000000022151475767661000155020ustar00rootroot00000000000000sudo: 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-5.2/CHANGES000066400000000000000000003703221475767661000143730ustar00rootroot00000000000000See also https://libreswan.org/ v5.2 (Feb 26, 2025) * IKEv2: - add PPK in INTERMEDIATE exchange, draft-ietf-ipsecme-ikev2-qr-alt-04 [Vukasin] - add initial support for RFC 5723 IKE_SESSION_RESUME [Nupur Agrawal, Andrew] - fix crash in <> [Andrew, Ilya Maximets #1894] - fix bogus ERROR when deleting connection [Andrew, Ilya Maximets #1914] * IPsec Interface: - add support on FreeBSD, NetBSD and OpenBSD [Andrew] - add ipsec-interface-managed=no for namespaces [Andrew] * IKEv1: - removed compile-time SOFTREMOTE_CLIENT_WORKAROUND [Andrew] - fix INVALID_ID_INFORMATION response using corrupt IV [Andrew #1830] - fix reconnect with addresspool after restart [Andrew #1790] - fix padding of modecfg payloads [Andrew wmasilva #2023] - update ikepad= to allow {yes,no,auto} [Andrew] * Linux: - packet offload counters supported in 6.7+ [Paul] - Add IPTFS support (RFC 9347) [Paul / Antony / Andrew] - 6.10+ need replay-window 0 on OUTBOUND SA [Paul] - Do not set nopmtudisc on inbound SA [Paul] - Set DSCP options only on the relevant direction SA [Paul] * updown: - Use half-routes for IPv6 to cover whole address space #1994 [Tuomo] - Use sourceip= for all remote subnets when set [Tuomo] * whack/addconn: - fix "duplicated flag ctlsocket" regression in 5.0 #1840 [Andrew, Ilya Maximets #1840] - orders of magnitude speedup of 'ipsec add' w/ protoports= [Ilya Maximets #1987] * building: - fix build with USE_LIBCURL=false [Hans de Graaff #1845, Andrew] - fix build on OpenBSD 7.6 [Andrew] - fix build with GCC 15 / C 23 [Daiki Ueno] - fix init script on Alpine [Andrew #2042] * testing: - update OpenBSD: 7.6; NetBSD: 10.1; FreeBSD: 14.2; Alpine: 3.21 [Andrew] - eliminate pyOpenSSL dependency when generating CRLs and PKCS12 files [Andrew #1990 #1996] v5.1 (Oct 8, 2024) * IKEv2: - fix race when initiator-responder cross rekey requests [Andrew] - don't ignore Delete IKE SA request while waiting for Delete IKE SA response [Andrew] - log arrival of first IKE_AUTH request that triggers DH [Andrew] - rate limit logging of packets with invalid payloads * IKEv1: - fix Quick mode installing 0.0.0.0/0 when no MSG_CONFIG exchange [Andrew, Tuomo] - fix iOS Quick mode request needing to re-recover lease [Andrew, Tuomo] - fix regression where deleting ISAKMP deleted IPsec [Andrew, Tuomo] - add config options of ah=sha2{256,512} [Andrew] - add DH29,DH31 to default proposals [Andrew] - reject ESP AEAD combined with non-NULL integrity [Andrew] * Crypto: - update IKE to use NSS's FIPS compliant PK11_AEADOp() [Andrew, Robert Relyea] - support ESP with CHACHA20POLY1305 on FreeBSD and OpenBSD [Andrew] * IPsec Interface: - fix check for an existing IPsec Interface address (Linux) [Wolfgang] - add IPsec Interface address when connection establishes [Wolfgang] - fix adding IPv6 address to IPsec interface [Wolfgang] - delete Ipsec Interface address when connection unroutes [Wolfgang] - fix setting metric on IPsec Interface [Wolfgang] - add IPsec Interface device when connection orients [Andrew] - support existing IPsec interface on FreeBSD and OpenBSD [Andrew] - log addition of IPsec Interface or Address [Andrew] - don't delete existing ipsec1 interface (Linux) [Andrew] - handle repeated connection adds [Wolfgang] * Linux: - handle NLMSG_DONE at end of response for > 6.9.0 kernels [Andrew] - fix hang because of unhandled NLMSG_DONE at end of response (6.9.0-rc1) [Andrew, Ilya, github/1675] - fix hang when initiating an on-demand TCP connection [Daiki, github/1156] * updown: - restore 4.x behaviour of running "updown unroute|down" when initiate fails [Wolfgang, Andrew] - add test demonstrating redundant tunnels [Wolfgang] - add plutodebug=updown for debugging updown scripts [Andrew] * config: - verbosely ignore x-* style comments in ipsec.conf [Andrew, github/1725] * whack: - ignore older whack as could trigger core dump [Andrew, github/1709] - add --narrowing {yes,no}, retain undocumented --allow-narrowing [Andrew] * building: - replace calloc(size,nr) with alloc_things(), fixing compile error [Daiki] - remove USE_NSS_AVA_COPY and copy of nss source, remove license exception [Tuomo] - fix syntax error in ckaid.c allowed by GCC [yuncang123] v5.0 (Apr 24, 2024) * IKEv1: - globally disabled by default (ikev1-policy=drop); see RFC9395 [Daniel] - limit default cryptosuite [Andrew, Paul, Tuomo] IKE={AES_CBC,3DES_CBC}-{HMAC_SHA2_256,HMAC_SHA2_512HMAC_SHA1}-{MODP2048,MODP1536,DH19,DH31} ESP={AES_CBC,3DES_CBC}-{HMAC_SHA1_96,HMAC_SHA2_512_256,HMAC_SHA2_256_128}-{AES_GCM_16_128,AES_GCM_16_256} AH=HMAC_SHA1_96+HMAC_SHA2_512_256+HMAC_SHA2_256_128 - remove support for Labeled IPsec [Andrew] - properly ignore dpdaction= [Andrew] - see also IKEv2 routing/revival changes * IKEv2: - warn that fragmentation=force is ignored [Andrew] - avoid post-authentication crash on corrupt TS payload [Andrew] - support addresspool=v4/mask,v6/mask [Andrew] - support subnet=SELECTOR,... using a single Child SA [Andrew] - when non-MOBIKE never update NATed endpoint [#1492/Wofferl/Andrew] - fix revival of IKE_AUTH (first) Child SA [Andrew] - properly ignore dpdaction=, keyingtries= [Andrew] - when reviving, install trap then block [Andrew] - for auto=keep only retry once [Andrew] - when redirect fails, fall back to revival [Andrew] * Linux: - HW packet offload support [Raed Salem ,Paul] - XFRM interface IP management with ref-counting [Brady Johnson] - fix IPcomp with XFRM interfaces [Wolfgang] * BSD: - fix esp=aes_gcm [github/1220, Igor V. Gubenko, Andrew] * whack: - review ipsec-whack.8 [Tuomo, Andrew, Paul] - change defaults to match addconn [Andrew] - add --{rekey,delete,down}-{ike,child} --name [Andrew] - match whack and addconn option names [Andrew] - drop NNN_ prefix from all output [Andrew] * config (ipsec.conf, addconn): - update ipsec.conf.5 [Tuomo, Andrew, Paul] - log ipsec.conf errors and warnings in Pluto [Andrew] - <> no longer supported [Andrew] - fix keyexchange={ikev1,ikev2}; deprecate ikev2= [Andrew] - remove nic-offload=auto option, only accept packet,crypto,yes [Paul] - warn when converting legacy ",," to "\," in {left,right}id= [Andrew] - change also= to expand inline (more like C's #include) [Andrew] - fix KEYWORD= sometimes causing Pluto to exit [Andrew] - parse <> as <>, i.e., empty [Andrew] - warn when, within a conn, there are duplicate keys [Andrew] - add encap-dscp= [Wolfgang] - implement interface-ip= [Brady] - implement subnet=SELECTOR,SELECTOR,... [Andrew] - default ikev1-policy to drop [Daniel] - add ppk-ids= [Vukasin] - add experimental per-connection debug= [Andrew] - drop obsolete forceencaps= [Andrew] - add groundhog= [Andrew] - reject non-numeric sourceip=
[Andrew] - fix crash when dpdtimeout= missing [Andrew] * building: - remove dependency on libxz via libsystemd [Tuomo Andrew] - use INSTALL_INITSYSTEM=false to prevent update of /etc/ [Andrew] - use INSTALL_CONFIGS=false prevents update of /etc/ipsec.d et.al. [Andrew] - drop FINAL* make variables; see mk/config.mk for alternatives [Andrew] - remove old copy of unbound headers [Andrew] - use DESTDIR instead of FINAL* env vars [Andrew] - fix "make git-rpm" [Paul/Tuomo] - check return values of libcap-ng functions [Paul] - don't call ischar(signed char) [Andrew] * packaging: - fix Debian systemd service install [Antonio Silva] * testing: - fix namespace tests for super long dir names [Paul] - add Alpine, Debian, NetBSD and FreeBSD KVMs [Andrew] - add Alpine, Debian, NetBSD, FreeBSD and OpenBSD to nightly builds [Andrew] - add man pages to nightly build [Andrew] * initsystem: - use documented ipsec sub-commands [Tuomo] - stop using _stackmanager [Tuomo] * documentation: - update to docbook xml 4.5 [Tuomo] - re-org pages adding libreswan.5 [Andrew] * ipsec utilities: - ipsec auto sub-command: deprecate [Tuomo] - ipsec auto --{cmd} connection -> ipsec {cmd} connection [Tuomo] - ipsec look: script moved to contrib/; use ip xfrm et.al. [Andrew] - ipsec portexcludes: script moved to contrib/ [Andrew] - ipsec barf: script moved to contrib/ [Andrew] - ipsec _secretsensor: script moved to contrib/ [Andrew] - ipsec show: drop ipsec subcommand (old, incomplete) [Paul] - ipsec verify: drop ipsec subcommand (old, incomplete) [Paul] v4.15 (April 15, 2024) * Security: Fixes http://libreswan.org/security/CVE-2024-3652 * Linux: remove dependency on libxz via libsystemd [Tuomo Andrew] * IKEv1: set default proposals to ESP aes-sha1 and AH sha1 [Andrew] * IKEv1: reject ESP proposal combining AEAD and non-empty INTEG [Andrew] * IKEv1: reject exchange when connection has no proposals [Andrew] * IKEv1: limit default cryptosuite [Andrew, Paul, Tuomo] IKE={AES_CBC,3DES_CBC}-{HMAC_SHA2_256,HMAC_SHA2_512HMAC_SHA1}-{MODP2048,MODP1536,DH19,DH31} ESP={AES_CBC,3DES_CBC}-{HMAC_SHA1_96,HMAC_SHA2_512_256,HMAC_SHA2_256_128}-{AES_GCM_16_128,AES_GCM_16_256} AH=HMAC_SHA1_96+HMAC_SHA2_512_256+HMAC_SHA2_256_128 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-5.2/CODE_OF_CONDUCT.md000066400000000000000000000044541475767661000161770ustar00rootroot00000000000000# 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-5.2/COPYING000066400000000000000000000432541475767661000144340ustar00rootroot00000000000000 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-5.2/CREDITS000066400000000000000000000022141475767661000144100ustar00rootroot00000000000000The 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-5.2/CROSSCOMPILE.sh000077500000000000000000000026031475767661000156330ustar00rootroot00000000000000#!/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-5.2/INSTALL000066400000000000000000000000171475767661000144200ustar00rootroot00000000000000See README.md libreswan-5.2/LIBRESWAN-OPENPGP-KEY.txt000066400000000000000000000061131475767661000172150ustar00rootroot00000000000000-----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-5.2/LICENSE000066400000000000000000000002721475767661000143770ustar00rootroot00000000000000This 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. libreswan-5.2/Makefile000066400000000000000000000156071475767661000150420ustar00rootroot00000000000000# 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_RPMBUILD_SOURCES = $(shell rpm --eval %{_sourcedir}) MAIN_RPMBUILD_SPEC = $(shell rpm --eval %{_specdir}) MAIN_RPM_VERSION = $(shell make showversion | sed "s/-.*//") MAIN_RPM_PREVER = $(shell make showversion | sed -e "s/^.[^-]*-\([^-]*\)-\(.*\)/rc\1_\2/" -e "s/-/_/g" -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: rm -rf out.* rm -rf $(OBJDIR)/html # 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: : generated test keys : careful output mixed with repo files rm -rf testing/x509/*/ rm -f testing/baseconfigs/all/etc/bind/signed/*.signed rm -f testing/baseconfigs/all/etc/bind/keys/*.key rm -f testing/baseconfigs/all/etc/bind/keys/*.private rm -f testing/baseconfigs/all/etc/bind/dsset/dsset-* : test results rm -rf testing/pluto/*/OUTPUT* rm -rf BACKUP : build results rm -f out.* rm -rf OBJ.* $(OBJDIR) 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 $(MAIN_RPMBUILD_SPEC) $(MAIN_RPMBUILD_SOURCES) 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) > $(MAIN_RPMBUILD_SPEC)/libreswan.spec git archive --format=tar --prefix=libreswan-$(MAIN_RPM_VERSION)$(MAIN_RPM_PREVER)/ \ -o $(MAIN_RPMBUILD_SOURCES)/libreswan-$(MAIN_RPM_VERSION)$(MAIN_RPM_PREVER).tar HEAD if [ -a Makefile.inc.local ] ; then \ tar --transform "s|^|$(MAIN_RPM_PREFIX)/|" -rf $(MAIN_RPMBUILD_SOURCES)/$(MAIN_RPM_PREFIX).tar Makefile.inc.local ; \ fi; echo 'IPSECBASEVERSION=$(MAIN_RPM_VERSION)$(MAIN_RPM_PREVER)' > $(MAIN_RPMBUILD_SOURCES)/version.mk ( pushd $(MAIN_RPMBUILD_SOURCES); tar --transform "s|^|$(MAIN_RPM_PREFIX)/mk/|" -rf $(MAIN_RPMBUILD_SOURCES)/$(MAIN_RPM_PREFIX).tar version.mk; popd) rm $(MAIN_RPMBUILD_SOURCES)/version.mk gzip -f $(MAIN_RPMBUILD_SOURCES)/$(MAIN_RPM_PREFIX).tar # get IKE test vectors if needed spectool --get-files $(MAIN_RPMBUILD_SPEC)/libreswan.spec --directory $(MAIN_RPMBUILD_SOURCES); rpmbuild -ba $(MAIN_RPMBUILD_SPEC)/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: .PHONY: web web-page web web-page: $(MAKE) -C testing/web web-publish include ${LIBRESWANSRCDIR}/mk/docker-targets.mk libreswan-5.2/README.md000066400000000000000000000161741475767661000146610ustar00rootroot00000000000000# Libreswan The Libreswan Project https://libreswan.org/ Libreswan is an Internet Key Exchange (IKE) implementation for Linux, FreeBSD, NetBSD and OpenBSD. 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 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. ## Installing A pre-built Libreswan package is available on the following OS distributions: RHEL, Fedora, CentOS, Ubuntu, Debian, Arch, Apline, OpenWrt and FreeBSD. On NetBSD the package sources are in wip/libreswan. Unless a source-based build is truly needed, it is often best to use the pre-built version of the distribution you are using. ## Installing from Source ### Requirements There are a few packages required for Libreswan to compile from source: For Debian/Ubuntu apt-get install net-tools make build-essential \ libnss3-dev pkg-config libevent-dev libunbound-dev \ bison flex libsystemd-dev libcurl4-nss-dev \ libpam0g-dev libcap-ng-dev libldns-dev xmlto For Fedora/CentOS-Stream/RHEL/AlmaLinux/RockyLinux etc. dnf 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 Alpine Linux: aph add mandoc mandoc-doc apk-tools-doc bison \ bison-doc bsd-compat-headers coreutils coreutils-doc \ curl-dev curl-doc flex flex-doc gcc gcc-doc git git-doc \ gmp-dev gmp-doc ldns-dev ldns-doc libcap-ng-dev \ libcap-ng-doc libevent-dev linux-pam-dev linux-pam-doc \ make make-doc musl-dev nspr-dev nss-dev nss-tools \ pkgconfig sed sed-doc unbound-doc unbound-dev \ xmlto xmlto-doc FreeBSD: pkg install gmake git pkgconf nss libevent unbound bison \ flex ldns xmlto gcc NetBSD: pkgin install git gmake nss unbound bison flex ldns xmlto pkgconf OpenBSD: pkg_add gmake nss libevent libunbound bison libldns xmlto \ curl git llvm%16 ### Building for RPM based systems Install requirements for rpm package building: dnf install rpm-build rpmdevtools The packaging/ directory is used to find the proper spec 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 directory is used to build deb files. Simply issue the command: make deb ### Building from scratch into /usr/local GNU Make is used: gmake sudo gmake install If you want to build without creating and installing manual pages, run: gmake base sudo gmake install-base ## 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 CentOS Stream 9, 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 older Libreswan versions, Libreswan 5.x you might need to adjust your config files, although great care has been put into making the configuration files full backwards compatible. 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/ ## Help Mailing lists: The mailing lists, including archives are at https://lists.libreswan.org/ Wiki: Libreswan's wiki is at https://libreswan.org/wiki/Main_Page. It contains documentation, interop guides and other useful information. IRC: Libreswan developers and users can be found on IRC, on irc.libera.chat #libreswan ## Bugs Bugs can be reported on the mailing list swan-dev@lists.libreswan.org 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/ Please contact security@libreswan.org or: https://github.com/libreswan/libreswan/security if you suspect you have found a security issue or vulnerability in libreswan. Encrypted email can be received encrypted to the libreswan OpenPGP key. We strongly encourage you to report potential security vulnerabilities to us before disclosing them in a public forum or in a public security paper or conference. ## Development Those interested in the development, patches, and beta releases of Libreswan can join the development mailing list swan-dev@lists.libreswan.org or talk to the development team on IRC in #libreswan 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/ libreswan-5.2/README.nss000066400000000000000000000243271475767661000150630ustar00rootroot00000000000000 ######################################################################### # 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-5.2/README.x509000066400000000000000000000000751475767661000147570ustar00rootroot00000000000000 See README.nss or check the wiki at https://libreswan.org/ libreswan-5.2/RELENG.md000066400000000000000000000023431475767661000146710ustar00rootroot00000000000000# During the Release - Bump mk/version.mk - Bump version and date in packaging/ files - debian changelog and rpm spec files - Add release date to CHANGES - git tag -s vx.y with commit message containing last CHANGES hunk - git archive --format=tgz --prefix=libreswan-x.y/ HEAD > libreswan-x.y.tar.gz - gpg -ba libreswan-x.y.tar.gz - Before publishing, test using local build, mock build, fedora scratch build - Upload CHANGES tar.gz and tar.gz.asc to nl.libreswan.org:/srv/www/download.libreswan.org - Wait 15 mins for fi.libreswan.org sync - Upload tar.gz and tar.gz.asc to github - push tag to vault: git push origin tag vx.y - push tag to github: ssh build@vaul.libreswan.org cd /srv/src/libreswan.git/; git push --follow-tags github vx.y - push commits to github (or wait 15 mins): ssh build@vaul.libreswan.org ./bin/github-push.sh # After the release - Start new section in CHANGES with x.y+1 (unreleased) - Post to announce@libreswan.org (causes mail approval msgs for swan and dev as well) - Build fedora release - future: build copr releases for Centos Stream - twitter: announce using libreswan account [no longer done] ## Update testing.libreswan.org This website will need an update. See "After a Release" in `testing/web/README.md` libreswan-5.2/SECURITY.md000066400000000000000000000014351475767661000151650ustar00rootroot00000000000000# Reporting a Vulnerability Please contact security@libreswan.org if you suspect you have found a security issue or vulnerability in libreswan. Encrypted email can be received encrypted to the libreswan OpenPGP key. We strongly encourage you to report potential security vulnerabilities to us before disclosing them in a public forum or in a public security paper or conference. The Libreswan Team typically responds within a few days but usually needs a few weeks to publish a new release with the security fix. The Libreswan Team does not accept any third party clauses before receiving information. A vulnerability reporter cannot mandate a timeline of public disclosure, however The Libreswan Team might accept reasonable requests for short delays. Ref: https://libreswan.org/security/ libreswan-5.2/TRADEMARK000066400000000000000000000005531475767661000146310ustar00rootroot00000000000000 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-5.2/configs/000077500000000000000000000000001475767661000150215ustar00rootroot00000000000000libreswan-5.2/configs/Makefile000066400000000000000000000144161475767661000164670ustar00rootroot00000000000000# 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 XMLTO_FLAGS = --searchpath $(abs_srcdir)/d.ipsec.conf:$(abs_srcdir) # different mode ipsec.secrets.INSTFLAGS = -m 0600 CONFFILES += ipsec.conf CONFFILES += ipsec.secrets LOGROTATEDFILE += 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 include $(top_srcdir)/mk/install.mk local-base: $(CONFFILES) $(CONFDSUBDIRFILES) $(LOGROTATEDFILE) local-clean-base: rm -f $(foreach file, $(CONFFILES) $(CONFDSUBDIRFILES) $(LOGROTATEDFILE), $(builddir)/$(file)) # For each group of files; first copy to the examples directory and # then, optionally, install into /etc (but only when # INSTALL_CONFIGS=true, and only when not already present). local-install-base: $(CONFFILES) $(CONFDSUBDIRFILES) $(LOGROTATEDFILE) @: CONFDDIR - EXAMPLECONFDIR not EXAMPLECONFDDIR and sample suffix @set -eu ; $(call install-directory, $(DESTDIR)$(EXAMPLE_IPSEC_SYSCONFDIR)) @set -eu ; $(call install-file, $(INSTCONFFLAGS) $(ipsec.conf.INSTFLAGS), $(builddir)/ipsec.conf, $(DESTDIR)$(EXAMPLE_IPSEC_SYSCONFDIR)/$(notdir $(IPSEC_CONF))-sample) @set -eu ; $(call install-file, $(INSTCONFFLAGS) $(ipsec.secrets.INSTFLAGS), $(builddir)/ipsec.secrets, $(DESTDIR)$(EXAMPLE_IPSEC_SYSCONFDIR)/$(notdir $(IPSEC_SECRETS))-sample) ifeq ($(INSTALL_CONFIGS),true) @set -eu ; $(call install-directory, $(DESTDIR)$(IPSEC_CONFDDIR), 0700) @set -eu ; $(call install-missing-file, $(INSTCONFFLAGS) $(ipsec.conf.INSTFLAGS), $(builddir)/ipsec.conf, $(DESTDIR)$(IPSEC_CONF)) @set -eu ; $(call install-missing-file, $(INSTCONFFLAGS) $(ipsec.secrets.INSTFLAGS), $(builddir)/ipsec.secrets, $(DESTDIR)$(IPSEC_SECRETS)) endif @: CONFDSUBDIR @set -eu ; $(call install-directory, $(DESTDIR)$(EXAMPLE_IPSEC_CONFDDIR), 0700) @set -eu ; $(call install-directory, $(DESTDIR)$(EXAMPLE_IPSEC_CONFDDIR)/$(CONFDSUBDIR), 0700) @set -eu ; $(foreach file, $(CONFDSUBDIRFILES), \ $(call install-file, $(INSTCONFFLAGS), \ $(builddir)/$(file), $(DESTDIR)$(EXAMPLE_IPSEC_CONFDDIR)/$(CONFDSUBDIR)/$(file)) ; \ ) ifeq ($(INSTALL_CONFIGS),true) @set -eu ; $(call install-directory, $(DESTDIR)$(IPSEC_CONFDDIR)/$(CONFDSUBDIR), 0700) @set -eu ; $(foreach file, $(CONFDSUBDIRFILES), \ $(call install-missing-file, $(INSTCONFFLAGS), \ $(DESTDIR)$(EXAMPLE_IPSEC_CONFDDIR)/$(CONFDSUBDIR)/$(file), $(DESTDIR)$(IPSEC_CONFDDIR)/$(CONFDSUBDIR)/$(file)) ; \ ) endif @: LOGROTATED @set -eu ; $(call install-directory, $(DESTDIR)$(EXAMPLE_LOGROTATEDDIR)) @set -eu ; $(call install-file, $(INSTCONFFLAGS), \ $(builddir)/$(LOGROTATEDFILE), $(DESTDIR)$(EXAMPLE_LOGROTATEDDIR)/$(LOGROTATEDFILE)) ifeq ($(INSTALL_CONFIGS),true) @set -eu ; $(call install-directory, $(DESTDIR)$(LOGROTATEDDIR)) @set -eu ; $(call install-missing-file, $(INSTCONFFLAGS), \ $(builddir)/$(LOGROTATEDFILE), $(DESTDIR)$(LOGROTATEDDIR)/$(LOGROTATEDFILE)) endif @: NSSDIR install ifeq ($(INSTALL_CONFIGS),true) @set -eu ; $(call install-directory, $(DESTDIR)$(NSSDIR), 0700) endif ifeq ($(USE_AUTHPAM),true) @: PAM @set -eu ; $(call install-directory, $(DESTDIR)$(EXAMPLE_PAMCONFDIR)) @set -eu ; $(call install-file, $(INSTCONFFLAGS), \ pam.d/pluto, $(DESTDIR)$(EXAMPLE_PAMCONFDIR)/pluto) ifeq ($(INSTALL_CONFIGS),true) @set -eu ; $(call install-directory, $(DESTDIR)$(PAMCONFDIR)) @set -eu ; $(call install-missing-file, $(INSTCONFFLAGS), \ $(DESTDIR)$(EXAMPLE_PAMCONFDIR)/pluto, $(DESTDIR)$(PAMCONFDIR)/pluto) endif endif @: $(SELINUX) ifeq ($(INSTALL_CONFIGS),true) @if test -z "$(DESTDIR)" -a -x /usr/sbin/selinuxenabled -a $(DESTDIR)$(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 " sudo restorecon /usr/local/sbin -Rv"; \ echo " sudo 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 endif list-local-base: @set -eu ; $(foreach file, $(CONFFILES), \ echo $(DESTDIR)$(SYSCONFDIR)/$(file) ; \ ) @set -eu ; $(foreach file, $(CONFFILES), \ echo $(DESTDIR)$(EXAMPLE_IPSEC_SYSCONFDIR)/$(file)-sample ; \ ) @set -eu ; $(foreach file, $(CONFDSUBDIRFILES), \ echo $(DESTDIR)$(IPSEC_CONFDDIR)/$(CONFDSUBDIR)/$${file} ; \ ) # Custom rules for ipsec.conf.5; manpages.mk should be updated to # mimic this behaviour. $(builddir)/ipsec.conf.5.man: $(srcdir)/ipsec.conf.5.xml $(srcdir)/d.ipsec.conf/*.xml $(builddir)/ipsec.conf.5.man: $(builddir)/ipsec.conf.5.ok $(builddir)/ipsec.conf.5.ok: $(srcdir)/d.ipsec.conf/*.xml : do all d.ipsec.conf/*.xml files appear in ipsec.conf.5.xml? for x in d.ipsec.conf/*.xml ; do \ b=$$(basename $${x} .xml) ; \ if ! grep '"'$${x}'"' ipsec.conf.5.xml > /dev/null ; then \ echo '"'$${x}'"' missing ; \ exit 1 ; \ fi ; \ if ! grep '&'$${b}';' ipsec.conf.5.xml > /dev/null ; then \ echo $${b} missing ; \ exit 1 ; \ fi ; \ done touch $@ $(top_builddir)/html/ipsec.conf.5.html: $(srcdir)/d.ipsec.conf/*.xml libreswan-5.2/configs/block.in000066400000000000000000000006131475767661000164430ustar00rootroot00000000000000# 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-5.2/configs/clear-or-private.in000066400000000000000000000016621475767661000205320ustar00rootroot00000000000000# 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-5.2/configs/clear.in000066400000000000000000000006411475767661000164400ustar00rootroot00000000000000# 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-5.2/configs/d.ipsec.conf/000077500000000000000000000000001475767661000172725ustar00rootroot00000000000000libreswan-5.2/configs/d.ipsec.conf/accept-redirect-to.xml000066400000000000000000000011161475767661000234710ustar00rootroot00000000000000 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 , 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. libreswan-5.2/configs/d.ipsec.conf/accept-redirect.xml000066400000000000000000000005521475767661000230540ustar00rootroot00000000000000 Whether requests of the remote peer to redirect IKE/IPsec SA's are accepted. Valid options are (the default) and . See also . libreswan-5.2/configs/d.ipsec.conf/aggressive.xml000066400000000000000000000034721475767661000221610ustar00rootroot00000000000000 Use IKEv1 Aggressive Mode instead of IKEv1 Main Mode. This option has no effect when IKEv2 is used. Acceptable values are (the default) or . When this option is enabled, IKEv1 Main Mode will no longer be allowed for this connection. The old name of this option was . 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 . 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 and 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-5.2/configs/d.ipsec.conf/ah.xml000066400000000000000000000033121475767661000204030ustar00rootroot00000000000000 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 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 command ipsec algparse ah=... can be used to query these defaults. This option replaces phase2alg= option for ah. libreswan-5.2/configs/d.ipsec.conf/audit-log.xml000066400000000000000000000016361475767661000217070ustar00rootroot00000000000000 Whether pluto should produce Linux Auditing System log messages. If enabled, pluto will log , stop and 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 (the default) and . 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 . libreswan-5.2/configs/d.ipsec.conf/authby.xml000066400000000000000000000106201475767661000213070ustar00rootroot00000000000000 How the two security gateways should authenticate each other. A comma separated list of one or more of the following: ECDSA digital signature based authentication with any of the hash algorithms SHA2_256, SHA2_385, or SHA2_512 ECDSA digital signature based authentication with the specified SHA2_256, SHA2_385, or SHA2_512 hash algorithm RSA-PKCSv1.5 digital signature based authentication with SHA1 RSASSA-PSS digital signature based authentication with any of the hash algorithms SHA2_256, SHA2_385, or SHA2_512 RSASSA-PSS digital signature based authentication with the specified SHA2_256, SHA2_385, or SHA2_512 hash algorithm shared secrets (PSK) authentication; cannot be combined with other authentication methods negotiation is never to be attempted or accepted; cannot be combined with other authentication methods null-authentication; cannot be combined with other authentication methods For IKEv1, SHA2 based signatures are not defined and ECDSA is not implemented, so the default value is . Using results in only as well. For IKEv2, which allows ECDSA with SHA-2 and RSA with SHA2 or SHA1. Using means using , , and , where will used only if RFC 7427 is not supported by the peer. Note that cannot be used for asymmetric authentication. Instead, IKEv2 must be enabled and the options and used. 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-5.2/configs/d.ipsec.conf/author.xml000066400000000000000000000002621475767661000213160ustar00rootroot00000000000000 AUTHOR PaulWouters libreswan-5.2/configs/d.ipsec.conf/auto.xml000066400000000000000000000044171475767661000207720ustar00rootroot00000000000000 what operation, if any, should be done automatically at IPsec startup; currently-accepted values are: equivalent to: ipsec add connection equivalent to: ipsec add connection ipsec route connection ( is an alias) equivalent to: ipsec add connection ipsec up connection signifying no automatic operation when Libreswan is starting (also the default) signifying an add plus an attempt to keep the connection up once the remote peer brought it up Relevant only locally, other end need not agree on it (but in general, for an intended-to-be-permanent connection, both ends should use to ensure that any reboot causes immediate renegotiation). See the discussion below. libreswan-5.2/configs/d.ipsec.conf/bugs.xml000066400000000000000000000050351475767661000207570ustar00rootroot00000000000000 BUGS Before reporting new bugs, please ensure you are using the latest version of Libreswan. When or is set to or 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, , etc.) as an attribute of a connection, rather than of a participant pair, is dubious and incurs limitations. The use of with the 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 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, , 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, , , and 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). libreswan-5.2/configs/d.ipsec.conf/choosing_a_connection.xml000066400000000000000000000016701475767661000243500ustar00rootroot00000000000000 CHOOSING A CONNECTION [THIS SECTION IS EXTREMELY OUT OF DATE When choosing a connection to apply to an outbound packet caught with a 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. libreswan-5.2/configs/d.ipsec.conf/cisco-unity.xml000066400000000000000000000012551475767661000222650ustar00rootroot00000000000000 whether to send a CISCO_UNITY payload to the peer. Acceptable values are: (the default) and . 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-5.2/configs/d.ipsec.conf/clientaddrfamily.xml000066400000000000000000000007711475767661000233340ustar00rootroot00000000000000 the address family of the clients (subnets); currently the accepted values are and . 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-5.2/configs/d.ipsec.conf/compress.xml000066400000000000000000000014101475767661000216430ustar00rootroot00000000000000 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 encryption); acceptable values are and (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-5.2/configs/d.ipsec.conf/configsections.example000066400000000000000000000000771475767661000236700ustar00rootroot00000000000000config setup logfile=/var/log/pluto.log plutodebug=all libreswan-5.2/configs/d.ipsec.conf/connsections.xml000066400000000000000000000153501475767661000225250ustar00rootroot00000000000000 DESCRIPTION The ipsec.conf file specifies most configuration and control information for the Libreswan IPsec subsystem (the major exception is secrets for authentication; see ipsec.secrets 5 ). Libreswan reads this file during start up (technically, if Libreswan's daemon ipsec-pluto 8 is invoked directly then the file ipsec.conf is not needed; however, this is not recommended). Configurations can be added using eithe this configuration file or by using ipsec whack directly. ipsec.conf is a text file, consisting of one or more . Within the file, 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 and a file name, separated by white space, is replaced by the contents of that file. 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 glob 3 ); for example: /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 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: 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. There are two types of section: a section specifies general configuration information for libreswan, and a section specifies an IPsec connection. 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 empty string. A non-empty 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: The value is a section name. The parameters of that section are inserted, in place, into this section (i.e., as if they had been written as part of and at that point in the section's definition). The specified section must exist, and must have the same section type. Multiple and nested are permitted (duplicate insertions of the same section are ignored). When the same appears in multiple sections, the first definition encountered is used. 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 parameter and an line. Putting at the end of the section after any definitions is recommended. This way, the section's value overrides sections. A section with name 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 section. There may be multiple sections of a given type and multiple default values for a given parameter (the last is used). sections may not contain any parameters. libreswan-5.2/configs/d.ipsec.conf/crl-strict.xml000066400000000000000000000013661475767661000221100ustar00rootroot00000000000000 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 or (the default). This option used to be called . libreswan-5.2/configs/d.ipsec.conf/crlcheckinterval.xml000066400000000000000000000012371475767661000233420ustar00rootroot00000000000000 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 , which is also the default value if this option is not specified, CRL updating is disabled. libreswan-5.2/configs/d.ipsec.conf/curl-iface.xml000066400000000000000000000005521475767661000220300ustar00rootroot00000000000000 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-5.2/configs/d.ipsec.conf/curl-timeout.xml000066400000000000000000000003531475767661000224460ustar00rootroot00000000000000 The timeout for the curl library calls used to fetch CRL and OCSP requests. The default is 5s. libreswan-5.2/configs/d.ipsec.conf/ddos-ike-threshold.xml000066400000000000000000000006541475767661000235120ustar00rootroot00000000000000 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 and ipsec whack --ddos-XXX. libreswan-5.2/configs/d.ipsec.conf/ddos-mode.xml000066400000000000000000000013331475767661000216670ustar00rootroot00000000000000 The startup mode of the DDoS defense mechanism. Acceptable values are , or (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-5.2/configs/d.ipsec.conf/debug.xml000066400000000000000000000011201475767661000210740ustar00rootroot00000000000000 Enable per-connection debug logging. For more information see ipsec-whack 8 and the option. This feature is used by Libreswan developers. The default logs should provide sufficient information to diagnose configuration and connection problems. libreswan-5.2/configs/d.ipsec.conf/decap-dscp.xml000066400000000000000000000010351475767661000220160ustar00rootroot00000000000000 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 (the default) or . Currently this feature is only implemented for the Linux XFRM stack. libreswan-5.2/configs/d.ipsec.conf/default_policy_groups.xml000066400000000000000000000007731475767661000244250ustar00rootroot00000000000000 DEFAULT POLICY GROUPS The standard Libreswan install includes several policy groups which provide a way of classifying possible peers into IPsec security classes: (talk encrypted only), (prefer encryption), (respond to requests for encryption), and . libreswan-5.2/configs/d.ipsec.conf/dns-match-id.xml000066400000000000000000000024171475767661000222700ustar00rootroot00000000000000 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 (the default) or . 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-5.2/configs/d.ipsec.conf/dnssec-anchors.xml000066400000000000000000000005471475767661000227340ustar00rootroot00000000000000 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-5.2/configs/d.ipsec.conf/dnssec-enable.xml000066400000000000000000000007411475767661000225210ustar00rootroot00000000000000 Whether pluto should perform dnssec validation using libunbound, provided libreswan was compiled with USE_DNSSEC. A value of (the default) means pluto should perform DNSSEC validation. Note that pluto reads the file to determine which nameservers to use. libreswan-5.2/configs/d.ipsec.conf/dnssec-rootkey-file.xml000066400000000000000000000004701475767661000237030ustar00rootroot00000000000000 The location of the DNSSEC root zone public key file. The default is but this can be changed at compile time. libreswan-5.2/configs/d.ipsec.conf/dpddelay.xml000066400000000000000000000010651475767661000216040ustar00rootroot00000000000000 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, you might need to adjust for IKEv2 and you must set for IKEv1. libreswan-5.2/configs/d.ipsec.conf/dpdtimeout.xml000066400000000000000000000014221475767661000221710ustar00rootroot00000000000000 Set the length of time (in time units, defaults to seconds) that pluto will idle without hearing back from the peer. After this period has elapsed with no response and no traffic, pluto will declare the peer dead, and remove the SA (default 0 meaning disabled). Set value bigger than dpddelay to enable. If dpdtimeout is set, dpddelay also needs to be set. This option is only valid for IKEv1. For IKEv2, this value is always the same as the retransmit-timeout, as IKEv2 is blocked from sending further IKE messages if an answer is not received. libreswan-5.2/configs/d.ipsec.conf/dumpdir.xml000066400000000000000000000007761475767661000214720ustar00rootroot00000000000000 in what directory should things started by (notably the Pluto daemon) be allowed to dump core? The default value is @@RUNDIR@@. When SELinux runs in enforced mode, changing this requires a similar change in the SELinux policy for the pluto daemon. libreswan-5.2/configs/d.ipsec.conf/enable-tcp.xml000066400000000000000000000021651475767661000220320ustar00rootroot00000000000000 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 (the default), meaning only TCP will be used, or 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 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. To receive incoming TCP connections, the option needs to be enabled. libreswan-5.2/configs/d.ipsec.conf/encap-dscp.xml000066400000000000000000000011011475767661000220220ustar00rootroot00000000000000 Enable encapsulating the Differentiated Services Code Point (DSCP, formerly known as Terms Of Service (TOS)) bits. The extra xfrm flag "dont-encap-dscp" prevents these bits from being copied from the unencrypted IP packets to the encrypted IP packets. Acceptable values are (the default) or . Currently this feature is only implemented for the Linux XFRM stack. libreswan-5.2/configs/d.ipsec.conf/encapsulation.xml000066400000000000000000000017651475767661000226720ustar00rootroot00000000000000 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. forces the NAT detection code to lie and tell the remote peer that RFC-3948 encapsulation (ESP in port 4500 packets) is required. ignores the NAT detection causing ESP packets to send send without encapsulation. The default value of follows the regular outcome of the NAT auto-detection code performed in IKE. This option replaced the obsoleted forceencaps option. libreswan-5.2/configs/d.ipsec.conf/esn.xml000066400000000000000000000016421475767661000206040ustar00rootroot00000000000000 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 (the default), and . If is specified as an initiator, the responder will make the choice. As a responder, if is received, 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-5.2/configs/d.ipsec.conf/esp.xml000066400000000000000000000046541475767661000206140ustar00rootroot00000000000000 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 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 do not not require a separate integrity algorithm. For example or . Note that AES_GCM and AES_CCM for ESP come in 8, 12 and 16 byte ICV versions. RFC 8221 only requires AES_GCM with 16 byte ICV and AES_CCM with 8 byte ICV to be implemented, and "aes_gcm" and "aes_ccm" refer to these variants. The other variants can be specified using an _a (8), _b(12) or _c(16) postfix, eg esp=aes_gcm_a for the 8 byte ICV and esp=aes_gcm_b for the 12 byte ICV. For instance: esp=aes_gcm;aes128+aes256-sha2_512+sha2_256 esp=aes128-sha2_512;dh19 If not specified, a secure set of defaults will be used. The program ipsec algparse can be used to query these defaults for instance: ipsec algparse esp= (see ipsec_algparse 8 ). This option replaces phase2alg= option for esp. libreswan-5.2/configs/d.ipsec.conf/exampleleftright.example000066400000000000000000000003431475767661000242130ustar00rootroot00000000000000conn 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 libreswan-5.2/configs/d.ipsec.conf/exampleleftright.xml000066400000000000000000000044361475767661000233670ustar00rootroot00000000000000 CONN SECTIONS A section contains a , 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: 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 “Child SAs”) used for user packets is herein referred to as the “connection”; the path used for negotiations (built with “IKE 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 and participants, rather than in terms of local and remote. Which participant is considered or 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 for the local side and 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 are listed here, but every parameter whose name begins with has a counterpart, whose description is the same but with and reversed. Parameters are optional unless marked “(required)” libreswan-5.2/configs/d.ipsec.conf/failureshunt.xml000066400000000000000000000005541475767661000225310ustar00rootroot00000000000000 what to do with packets when negotiation fails. The default is : no shunt; , , and have the obvious meanings. libreswan-5.2/configs/d.ipsec.conf/fake-strongswan.xml000066400000000000000000000012761475767661000231330ustar00rootroot00000000000000 whether to send a STRONGSWAN Vendor ID payload to the peer. Acceptable values are: (the default) and . 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-5.2/configs/d.ipsec.conf/files.xml000066400000000000000000000006361475767661000211230ustar00rootroot00000000000000 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 libreswan-5.2/configs/d.ipsec.conf/fragmentation.xml000066400000000000000000000021461475767661000226550ustar00rootroot00000000000000 Whether or not to allow IKE fragmentation. Valid values are (the default) and . In addition IKEv1 allows . IKEv2 fragmentation support is implemented using RFC 7383. IKEv1 fragmentation capabilities are negotiated via a well-known private . If pluto does not receive the fragmentation payload, no IKE fragments will be sent, regardless of the setting. When set to , 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-5.2/configs/d.ipsec.conf/global-redirect-to.xml000066400000000000000000000012621475767661000234740ustar00rootroot00000000000000 Where to send remote peers to via the 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-5.2/configs/d.ipsec.conf/global-redirect.xml000066400000000000000000000015571475767661000230630ustar00rootroot00000000000000 Whether to send requests for the remote peer to redirect IKE/IPsec SA's during IKE_SA_INIT. Valid options are (the default), and , where auto means that the requests will be sent if DDoS mode is active (see ). If set, the option must also be set to indicate where to redirect peers to. For specific connection redirection after IKE SA authentication, see the and options. This configuration can be changed at runtime via the ipsec whack --global-redirect command. libreswan-5.2/configs/d.ipsec.conf/history.xml000066400000000000000000000003501475767661000215130ustar00rootroot00000000000000 HISTORY Designed for the FreeS/WAN project <https://www.freeswan.org> by Henry Spencer. libreswan-5.2/configs/d.ipsec.conf/hostaddrfamily.xml000066400000000000000000000012311475767661000230230ustar00rootroot00000000000000 the address family of the hosts; currently the accepted values are and . 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-5.2/configs/d.ipsec.conf/ignore-peer-dns.xml000066400000000000000000000016461475767661000230210ustar00rootroot00000000000000 whether to ignore received DNS configuration. Acceptable values are: (the default) and . 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-5.2/configs/d.ipsec.conf/ike-socket-bufsize.xml000066400000000000000000000013151475767661000235170ustar00rootroot00000000000000 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 . libreswan-5.2/configs/d.ipsec.conf/ike-socket-errqueue.xml000066400000000000000000000012031475767661000237010ustar00rootroot00000000000000 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 . libreswan-5.2/configs/d.ipsec.conf/ike.xml000066400000000000000000000125321475767661000205670ustar00rootroot00000000000000 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 Any omitited option will be filled in with allowed default values. Multiple proposals are separated by a comma. If an line is specified, no other received proposals will be accepted than those specified on the IKE line. Some examples are , , , , , , , . IKEv2 allows combining elements into a single proposal. These can be specified by using the + symbol. An example is: . 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_256 means propose AES_GCM with SHA2_256 as the prf. Note that for esp, there is no prf, so AES-GCM is specified for ESP as esp=aes_gcm. 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. RFC 8247 only mandates the 16 byte ICV version is implemented, so it is recommended to NOT use the 8 or 12 byte versions of GCM or CCM. These versions are NOT included in the default proposal list and will be removed in a future version. 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 . 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-5.2/configs/d.ipsec.conf/ikelifetime.xml000066400000000000000000000010741475767661000223050ustar00rootroot00000000000000 how long the keying channel of a connection (buzzphrase: “IKE SA” or “ISAKMP SA”) should last before being renegotiated; acceptable values as for . The default as of version 4.2 is , before that it was 1h. The maximum is . The two-ends-disagree case is similar to that of . libreswan-5.2/configs/d.ipsec.conf/ikepad.xml000066400000000000000000000042631475767661000212560ustar00rootroot00000000000000 Work around IKEv1 padding issues when inter-operating with other IKE daemons. By default, Libreswan pads messages to a minimum of 4-bytes. While this is allowed it may cause interoperability issues. To remove this padding, specify (note that this does not affect messages encrypted using a block-mode cipher where padding is always added). Prior to Libreswan 5.2, some MODECFG payloads were incorrectly padded to 4-bytes which caused interoperability issues. To restore this behaviour, specify . In IKEv2, this option is ignored. Background It was thought that padding messages by 4-bytes was causing interoperability issues with Checkpoint ( was added as a workaround). However, it's since been determined that Racoon also had interoperability issues and the cause was the padding of some XAUTH and MODECFG payloads. Setting fixed interoperability because it was also disabling that padding. The padding of XAUTH and MODECFG was removed in Libreswan 5.2. Further details can be found in the RFCs, see: RFC-2409 section 5.3, Phase 1 Authenticated With a Revised Mode of Public Key Encryption, the last byte of the padding contains the number of padding bytes and there will always be padding; RFC-2408 section 3.5, Proposal Payload, there is no padding applied to the payload, however, it can be applied at the end of the message; RFC-2408 section 3.6, Transform Payload, then subsequent payloads will not be aligned and any padding will be added at the end of the message to make the message 4-octet aligned. libreswan-5.2/configs/d.ipsec.conf/ikev1-policy.xml000066400000000000000000000010741475767661000223320ustar00rootroot00000000000000 What to do with received IKEv1 packets. Valid options are (default) which will silently drop any received IKEv1 packet, , and which will reply with an error. 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-5.2/configs/d.ipsec.conf/initial-contact.xml000066400000000000000000000013031475767661000230730ustar00rootroot00000000000000 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: (the default) and . 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-5.2/configs/d.ipsec.conf/interface-ip.xml000066400000000000000000000010231475767661000223560ustar00rootroot00000000000000 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 . See also for configuring IP addresses when using deprecated VTI. libreswan-5.2/configs/d.ipsec.conf/intermediate.xml000066400000000000000000000007531475767661000224730ustar00rootroot00000000000000 EXPERIMENTAL: Whether to enable the INTERMEDIATE exchange in IKEv2 (RFC 9242). Currently the accepted values are , signifying we propose to use the INTERMEDIATE exchange for this connection; (the default), signifying we will not use the INTERMEDIATE exchange for this connection. libreswan-5.2/configs/d.ipsec.conf/ipsec-interface-managed.xml000066400000000000000000000030071475767661000244470ustar00rootroot00000000000000 Specify whether the IPsec Interface specifed by managed by &Libreswan;. Possible values are: (default) &Libreswan; is responsible for managing the IPsec Interface. For instance, creating it when needed, adding the address specified by , installing any kernel policy or state, and marking it and . In this mode identifies the IPsec interface network device. For instance, specifies the network device . &Libreswan; assumes that the IPsec interface specified by exists and &Libreswan; is only responsible for managing kernel policy and state. In this mode identifies the low level kernel ID. For instance, on &Linux;, identifies the device with the XFRM if_id 1. libreswan-5.2/configs/d.ipsec.conf/ipsec-interface.xml000066400000000000000000000102601475767661000230540ustar00rootroot00000000000000 Specify the IPsec Interface for "Routing based IPsec VPNs" (as opposed to "Policy based VPNs"). 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 is equal to , the routing needs to be managed by an external routing daemon or manually by the administrator. By default, &Libreswan; is configured in managed mode. In managed mode, &Libreswan; will create, configure , , and delete the IPsec Interface device (on &Linux;, &FreeBSD;, and &NetBSD; that device is named ; &OpenBSD; it is named ). To specify the IP address to configure when creating the device also specify . Alternatively, &Libreswan; can be configured in unmanaged mode. In unmanaged mode, &Libreswan; does not manipulate the IPsec Interface Device directly. Instead &Libreswan; will assume the IPsec Interface device already exists, manipulating it directly using the low-level kernel ID (on &Linux; that is the XFRMi if_id). A typical use is with namespaces where the IPsec Interface Device and &Libreswan; are in separate namespace. Possible values are: (default) Do not use "Routing based IPsec VPN". Enable "Routing based IPsec VPNs". In managed mode, use IPsec Interface device 1 (for instance, ). In unmanaged mode, use the kernel device 1. Enable "Routing based IPsec VPNs" using the device number. For instance, will use in managed mode, and kernel xfrm interface with if_id in unmanaged mode. Kernel Support: &Linux; (since 4.19) This option is currently only supported on Linux kernels when compiled with XFRMi support (). The number of the ipsecX device corresponds with the 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. &NetBSD; (since 8.0) &OpenBSD; (since 7.4) &FreeBSD; (since 11.0) Supported since &Libreswan; 5.2. libreswan-5.2/configs/d.ipsec.conf/ipsec-max-bytes.xml000066400000000000000000000037521475767661000230350ustar00rootroot00000000000000 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 , , , , or 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 renegotiation (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.). When using Linux with set, Linux 6.7 or later is required. libreswan-5.2/configs/d.ipsec.conf/ipsec-max-packets.xml000066400000000000000000000011751475767661000233360ustar00rootroot00000000000000 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 . This option uses a prefix without "B" for bytes. When using Linux with set, Linux 6.7 or later is required. libreswan-5.2/configs/d.ipsec.conf/ipsecdir.xml000066400000000000000000000030021475767661000216110ustar00rootroot00000000000000 Specifies a directory for administrator-controlled configuration files and directories. The default value is . It may contain the following files and directories: passwd (optional) for IKEv1 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 in this document for more information. When SELinux runs in enforced mode, changing this requires a similar change in the SELinux policy for the pluto daemon. libreswan-5.2/configs/d.ipsec.conf/iptfs.xml000066400000000000000000000065441475767661000211520ustar00rootroot00000000000000 Enable "Aggregation and Fragmentation Mode for Encapsulating Security Payload (ESP) and its use for IP Traffic Flow Security (IP-TFS) as defined in RFC 9347. Currently, this is only supported for the Linux XFRM stack and will likely be merged into Linux 6.7 or 6.8. Valid options are (the default) or . IP-TFS allow the kernel to combine multiple small packets into one ESP packet, which should cause a performance gain when many small packets (eg iperf packets) are sent. It also allows the kernel to fragment the outgoing packet stream so that the ESP packets have a fixed size that can be set manually or fit the path MTU. This should avoid common MTU issues with IPsec. IP-TFS can only be used with tunnel mode and ESP. It cannot be combined with , , or . A number of IP-TFS options can be tuned. Whether or not to fragment IP-TFS. On Linux and , this passes to the kernel. (Unclear to at least one author if this means regular ICMP Dont Fragment sending, or whether it stops IP-TFS from fragmenting). Default is The default IP-TFS max output queue size in octets. The output queue is where received packets destined for output over an IP-TFS tunnel are stored prior to being output in aggregated/fragmented form over the IP-TFS tunnel. Default 1000000. The amount of time before a missing out-of-order IP-TFS tunnel packet is considered lost. See also . The default is 1s. The default time unit is seconds (see duration). The amount of time prior to servicing the output queue after queueing the first packet on said queue. The default is 0s. The default time unit is seconds (see duration). The default IP-TFS reorder window size. The reorder window size dictates the maximum number of IP-TFS tunnel packets in a sequence that may arrive out of order. Default 3. libreswan-5.2/configs/d.ipsec.conf/keep-alive.xml000066400000000000000000000004731475767661000220420ustar00rootroot00000000000000 The delay (in seconds) for NAT-T keep-alive packets, if these are enabled using This parameter may eventually become per-connection. libreswan-5.2/configs/d.ipsec.conf/keyexchange.xml000066400000000000000000000007611475767661000223130ustar00rootroot00000000000000 Whether to use IKEv2 (RFC 7296) or IKEv1 (RFC 4301). Currently the accepted values are (the default) and . This option replaces ikev2=yes|no. Old values yes, propose and instist all map to keyexchange=ikev2. Values no and permit are map to keyexchange=ikev1. libreswan-5.2/configs/d.ipsec.conf/left.xml000066400000000000000000000044071475767661000207530ustar00rootroot00000000000000 (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 , 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 . (Either or may be , but not both.) The value signifies an address to be filled in (by automatic keying) during negotiation. The value signifies that both and are to be filled in (by automatic keying) from DNS data for '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 . The values and 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 ( 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-5.2/configs/d.ipsec.conf/leftaddresspool.xml000066400000000000000000000027771475767661000232230ustar00rootroot00000000000000 address pool from where the IKEv1 ModeCFG or IKEv2 server can assign IP addresses to clients. When configured as a server, using 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: or Generally, the option will be accompanied by , and option. When is specified, the connection may not specify either or . Address pools are fully allocated when the connection is loaded, so the ranges should be sane. For example, specifying a range 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-5.2/configs/d.ipsec.conf/leftauth.xml000066400000000000000000000035111475767661000216300ustar00rootroot00000000000000 How the security gateways will authenticate to the other side in the case of asymmetric authentication; acceptable values are or for RSA Authentication with SHA-1, for RSA-PSS digital signatures based authentication with SHA2-256, for RSA-PSS digital signatures based authentication with SHA2-384, for RSA-PSS digital signatures based authentication with SHA2-512, for ECDSA digital signatures based authentication, for shared secrets (PSK) authentication and for null-authentication. There is no default value - if unset, the symmetrical keyword is used to determine the authentication policy of the connection. Asymmetric authentication is only supported with IKEv2. If symmetric authentication is required, use 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 . Be aware that the symmetric keyword is but the asymmetric keyword is and (without the "by"). libreswan-5.2/configs/d.ipsec.conf/leftautheap.xml000066400000000000000000000010741475767661000223200ustar00rootroot00000000000000 Whether the security gateways will authenticate uing an EAP method. Acceptable values are (the default) and for EAPTLS. If EAP is the only authentication method, set in addition to . The EAP authentication mechanisms are only available for IKEv2 based connections. libreswan-5.2/configs/d.ipsec.conf/leftca.xml000066400000000000000000000013221475767661000212500ustar00rootroot00000000000000 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 . The special is implied when not specifying a 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-5.2/configs/d.ipsec.conf/leftcat.xml000066400000000000000000000014171475767661000214410ustar00rootroot00000000000000 Whether to perform Client Address Translation ("CAT") when using Opportunistic IPsec behind NAT. Accepted values are (the default) and . 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 nftables or 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-5.2/configs/d.ipsec.conf/leftcert.xml000066400000000000000000000005161475767661000216260ustar00rootroot00000000000000 If you are using this defines the certificate nickname of your certificate in the NSS database. This can be on software or hardware security device. libreswan-5.2/configs/d.ipsec.conf/leftckaid.xml000066400000000000000000000007251475767661000217460ustar00rootroot00000000000000 The CKAID of the X.509 certificate or host key. For X.509 certificates, the CKAID is either the certificate's SubjectKeyIdentifier or the public key's SHA1 fingerprint (when the SubjectKeyIdentifier isn't specified). For host keys the CKAID is the SHA1 fingerprint of the public key. libreswan-5.2/configs/d.ipsec.conf/leftfirewall.xml000066400000000000000000000003021475767661000224670ustar00rootroot00000000000000 This option is obsolete and should not used anymore. libreswan-5.2/configs/d.ipsec.conf/leftid.xml000066400000000000000000000024701475767661000212660ustar00rootroot00000000000000 how the left participant should be identified for authentication; defaults to . 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 . The magic value 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 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. 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 backslash (eg OU='Foo\, Bar and associates') libreswan-5.2/configs/d.ipsec.conf/leftikeport.xml000066400000000000000000000004141475767661000223430ustar00rootroot00000000000000 The UDP IKE port to listen on or send data to. This port cannot be 0 or 500. For TCP, see libreswan-5.2/configs/d.ipsec.conf/leftmodecfgclient.xml000066400000000000000000000004711475767661000234740ustar00rootroot00000000000000 Left is a Mode Config client. It can receive network configuration from the server. Acceptable values are or (the default). libreswan-5.2/configs/d.ipsec.conf/leftmodecfgserver.xml000066400000000000000000000004771475767661000235320ustar00rootroot00000000000000 Left is a Mode Config server. It can push network configuration to the client. Acceptable values are or (the default). libreswan-5.2/configs/d.ipsec.conf/leftnexthop.xml000066400000000000000000000015451475767661000223610ustar00rootroot00000000000000 next-hop gateway IP address for the left participant's connection to the public network; defaults to (meaning ). If the value is to be overridden by the method (see above), an explicit value must be given. If that method is not being used, but is , the next-hop gateway address of the default-route interface will be used. The magic value 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-5.2/configs/d.ipsec.conf/leftprotoport.xml000066400000000000000000000056241475767661000227460ustar00rootroot00000000000000 allowed protocols and ports over connection, also called Port Selectors. The argument is in the form , which can be a number or a name that will be looked up in , such as , or in the form of , such as . Ports can be defined as a number (eg. 25) or as a name (eg smtp) which will be looked up in . A special keyword 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: . 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 . 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 . Some clients, notably older Windows XP and some Mac OSX clients, use a random high port as source port. In those cases 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 status eg: 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 scripts. Older workarounds for bugs involved a setting of to denote (not UDP port 0). Some clients, most notably OSX, uses a random high port, instead of port 1701 for L2TP. <code>use with leftsubnet</code> With IKEv2, the leftsubnet specification can include the protocol and port. Combining that syntax with protoport is not supported. libreswan-5.2/configs/d.ipsec.conf/leftrsasigkey.xml000066400000000000000000000040551475767661000226740ustar00rootroot00000000000000 the left participant's public key for RSA signature authentication, in base-64 encoded RFC 2537 format (with 0s prepended), or one of the following: the same as not specifying a value (useful to override a default) (the default) the key is to be fetched from DNS at the time it is needed. the key is to be fetched from DNS at the time the connection description is read from ; currently this will be treated as if or . currently treated as but will change to in the future. The identity used for the left participant must be a specific host, not or another magic value. the information required from a certificate defined in and automatically define leftid for you If two connection descriptions specify different public keys for the same , confusion and madness will ensue. libreswan-5.2/configs/d.ipsec.conf/leftsendcert.xml000066400000000000000000000017031475767661000224770ustar00rootroot00000000000000 This option configures when Libreswan will send X.509 certificates to the remote host. Acceptable values are (signifying that we should always send a certificate), (signifying that we should send a certificate if the remote end asks for it), and (signifying that we will never send a X.509 certificate). The default for this option is 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 . This per-conn option replaces the obsolete global option. libreswan-5.2/configs/d.ipsec.conf/leftsourceip.xml000066400000000000000000000015501475767661000225210ustar00rootroot00000000000000 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 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-5.2/configs/d.ipsec.conf/leftsubnet.xml000066400000000000000000000052141475767661000221710ustar00rootroot00000000000000 A comma separated list of traffic selectors behind the left participant. Each expressed as: network-prefix / netmask/ protocol/ port where trailing elements may be omitted. For instance: leftsubnet=1.2.3.0/24,1:2::/64, leftsubnet=1.2.3.4/32/tcp,1:2::/128/tcp, leftsubnet=1.2.3.4/31/tcp/22,1:2::/128/tcp/22. If both leftsubnet= and rightsubnet= are specified, all combinations will be established as a single IPsec tunnel. When omitted, essentially assumed to be left, signifying that the left end of the connection goes to the left participant only. Support for specifying multiple selectors and the protocol and port was added in Libreswan version 5. IKEv1 In IKEv1 only a single selector is allowed and it is limited to specifying a subnet as in: network / netmask IKEv1 IKEv1 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. Use with <code>leftprotport</code> and <code>leftsubnets</code> Compatible with libreswan version 4, a simple leftsubnet (specifying a single network prefix and netmask) may be combined with leftprotoport and leftsubnets. Anything more complicated should be converted to use the selector syntax. libreswan-5.2/configs/d.ipsec.conf/leftsubnets.xml000066400000000000000000000014201475767661000223470ustar00rootroot00000000000000 specify multiple private subnets behind the left participant, expressed as , If both a leftsubnets= and rightsubnets= are defined, all combinations of subnet tunnels will be established as separate IPsec tunnels. You cannot use leftsubnet= and leftsubnets= together. For examples see . Be aware that when using spaces as separator, that the entire option value needs to be in double quotes. libreswan-5.2/configs/d.ipsec.conf/leftupdown.xml000066400000000000000000000022521475767661000222040ustar00rootroot00000000000000 The 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: updown="ipsec _updown --route yes" To disable calling an updown script, set it to the empty string, eg leftupdown="" or leftupdown="%disabled". Connections with type= set to passthrough, reject or drop never run updown. See libreswan7 for details. Relevant only locally, other end need not agree on it. libreswan-5.2/configs/d.ipsec.conf/leftusername.xml000066400000000000000000000007011475767661000225040ustar00rootroot00000000000000 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 file. This option was previously called leftxauthusername. libreswan-5.2/configs/d.ipsec.conf/leftvti.xml000066400000000000000000000007431475767661000214750ustar00rootroot00000000000000 the address/mask to configure on the VTI interface when is set. It takes the form of Currently, IPv4 and IPv6 addresses with cidr netmask are supported. This option is often used in combination with routed based VPNs. libreswan-5.2/configs/d.ipsec.conf/leftxauthclient.xml000066400000000000000000000017621475767661000232250ustar00rootroot00000000000000 Left is an XAUTH client. The xauth connection will have to be started interactively and cannot be configured using . Instead, it has to be started from the commandline using ipsec up connection. 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 . Acceptable values are or (the default). libreswan-5.2/configs/d.ipsec.conf/leftxauthserver.xml000066400000000000000000000015541475767661000232540ustar00rootroot00000000000000 Left is an XAUTH server. This can use PAM for authentication or md5 passwords in . These are additional credentials to verify the user identity, and should not be confused with the XAUTH , which is just a regular PSK defined in . The other side of the connection should be configured as . XAUTH connections cannot rekey, so should be specified in this conn. For further details on how to compile and use XAUTH, see README.XAUTH. Acceptable values are or (the default). libreswan-5.2/configs/d.ipsec.conf/listen-tcp.xml000066400000000000000000000010171475767661000220750ustar00rootroot00000000000000 Whether the pluto IKE daemon should listen on the (pseudo) standard TCP port . The default is "no". The TCP usage complies to RFC 9329 for IKE and ESP over TCP support. Connections can specify their own non-standard TCP port using and for a non-standard peer TCP port. libreswan-5.2/configs/d.ipsec.conf/listen-udp.xml000066400000000000000000000011551475767661000221020ustar00rootroot00000000000000 Whether the pluto IKE daemon should listen on the standard UDP ports of and . 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-5.2/configs/d.ipsec.conf/listen.xml000066400000000000000000000003361475767661000213140ustar00rootroot00000000000000 IP address to listen on, defaults to ANY. Currently only accepts one IP address. libreswan-5.2/configs/d.ipsec.conf/logappend.xml000066400000000000000000000013441475767661000217670ustar00rootroot00000000000000 If pluto is instructed to log to a file using , this option determines whether the log file should be appended to or overwritten. Valid options are (the default) to append and 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-5.2/configs/d.ipsec.conf/logfile.xml000066400000000000000000000004261475767661000214370ustar00rootroot00000000000000 do not use syslog, but rather log to stderr, and direct stderr to the argument file. This option used to be called plutostderrlog= libreswan-5.2/configs/d.ipsec.conf/logip.xml000066400000000000000000000017131475767661000211300ustar00rootroot00000000000000 If pluto is instructed to log the IP address of incoming connections. Valid options are (the default) and . Note that this only affects regular logging. Any enabled debugging via 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, should also be set. libreswan-5.2/configs/d.ipsec.conf/logtime.xml000066400000000000000000000010641475767661000214550ustar00rootroot00000000000000 When pluto is directed to log to a file using , this option determines whether or not to log the current timestamp as prefix. Values are (the default) or . 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-5.2/configs/d.ipsec.conf/mark-in.xml000066400000000000000000000004241475767661000213520ustar00rootroot00000000000000 The same as , but mark-in only applies to the inbound half of the IPsec SA. It overrides any mark= setting. libreswan-5.2/configs/d.ipsec.conf/mark-out.xml000066400000000000000000000004271475767661000215560ustar00rootroot00000000000000 The same as , but mark-out only applies to the outbound half of the IPsec SA. It overrides any mark= setting. libreswan-5.2/configs/d.ipsec.conf/mark.xml000066400000000000000000000013361475767661000207510ustar00rootroot00000000000000 If set, the MARK to set for the IPsec SA of this connection. The format of a CONNMARK is . 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. libreswan-5.2/configs/d.ipsec.conf/max-halfopen-ike.xml000066400000000000000000000004751475767661000231470ustar00rootroot00000000000000 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-5.2/configs/d.ipsec.conf/metric.xml000066400000000000000000000005411475767661000212770ustar00rootroot00000000000000 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 . libreswan-5.2/configs/d.ipsec.conf/mobike.xml000066400000000000000000000013351475767661000212640ustar00rootroot00000000000000 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 (the default) or , 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-5.2/configs/d.ipsec.conf/modecfgoptions.xml000066400000000000000000000022221475767661000230320ustar00rootroot00000000000000 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-5.2/configs/d.ipsec.conf/modecfgpull.xml000066400000000000000000000005261475767661000223200ustar00rootroot00000000000000 Pull the Mode Config network information from the server. Both server and client must use same setting. Acceptable values are or (the default). libreswan-5.2/configs/d.ipsec.conf/ms-dh-downgrade.xml000066400000000000000000000016061475767661000227770ustar00rootroot00000000000000 Whether to allow a downgrade of Diffie-Hellman 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 (and adding modp1024 proposals to the ike line) will allow this downgrade attack to happen. This should only be used to support Windows that feature this bug. The accepted values are , (the default) or . libreswan-5.2/configs/d.ipsec.conf/mtu.xml000066400000000000000000000012311475767661000206160ustar00rootroot00000000000000 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-5.2/configs/d.ipsec.conf/myvendorid.xml000066400000000000000000000003661475767661000222010ustar00rootroot00000000000000 The string to use as our vendor id (VID) when send-vendorid=yes. The default is OE-Libreswan-VERSION. libreswan-5.2/configs/d.ipsec.conf/narrowing.xml000066400000000000000000000023561475767661000220300ustar00rootroot00000000000000 IKEv2 (RFC5996) Section 2.9 Traffic Selector narrowing options. Currently the accepted values are , (the default) signifying no narrowing will be proposed or accepted, or , 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-5.2/configs/d.ipsec.conf/nat-ikev1-method.xml000066400000000000000000000024751475767661000231010ustar00rootroot00000000000000 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 , , (the default) and . 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-5.2/configs/d.ipsec.conf/nat-keepalive.xml000066400000000000000000000006301475767661000225400ustar00rootroot00000000000000 whether to send any NAT-T keep-alives. These one byte packets prevent the NAT router from closing its port when there is not enough traffic on the IPsec connection. Acceptable values are: (the default) and . libreswan-5.2/configs/d.ipsec.conf/negotiationshunt.xml000066400000000000000000000012341475767661000234160ustar00rootroot00000000000000 What to do with packets during the IKE negotiation. Valid options are (the default) or . 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-5.2/configs/d.ipsec.conf/nflog-all.xml000066400000000000000000000014761475767661000216770ustar00rootroot00000000000000 If set, the NFLOG group number to log pre-crypt and post-decrypt traffic to. The default value of 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 . See also the per-connection option. libreswan-5.2/configs/d.ipsec.conf/nflog.xml000066400000000000000000000015171475767661000211250ustar00rootroot00000000000000 If set, the NFLOG group number to log pre-crypt and post-decrypt traffic to. The default value of 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 option. libreswan-5.2/configs/d.ipsec.conf/nhelpers.xml000066400000000000000000000012011475767661000216260ustar00rootroot00000000000000 how many 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-5.2/configs/d.ipsec.conf/nic-offload.xml000066400000000000000000000043241475767661000222000ustar00rootroot00000000000000 Set the method of Network Interface Controller (NIC) hardware offload for ESP/AH packet processing. Acceptable values are (the default), or . The value is a backwards compatible value for . The nic-offload option is separate from any CPU hardware offload available. When set to , only cryptographic operations are offloaded to the NIC card. When set to , the entire packet processing including the encryption/decryption is offloaded to the NIC card. Crypto nic-offload is available starting Linux 4.13 using the XFRM IPsec stack. Packet nic-offload is available starting Linux 6.3. Both require that the Linux kernel is compiled with the options CONFIG_XFRM_OFFLOAD, CONFIG_INET_ESP_OFFLOAD and CONFIG_INET6_ESP_OFFLOAD. Network card support can be seen by the presence of the capability using the command. The Linux kernel attempts to fall back from crypto hardware offload to software, but only for some algorithms (AEADs only?). There is no fallback from packet offload to crypto offload. At the time of libreswan 5.0, we are only aware of the Nvidia/Mellanox ConnectX-7 (and to some extend ConnectX-6) cards supporting packet offload. In general, it makes no sense to try to offload older (non-AEAD) cryptographic algorithms such as AES-CBC or 3DES, as these algorithms are so much slower than AEAD algorithms (such as AES-GCM) that one would gain more performance by switching the algorithm to AEAD than by offloading. As such, AES-CBC tends to not be implemented in offload hardware. This option has also no effect on IKE packets, which are never offloaded, although IKE encryption does use supported CPU hardware instructions, such as AESNI. libreswan-5.2/configs/d.ipsec.conf/nm-configured.xml000066400000000000000000000006501475767661000225520ustar00rootroot00000000000000 Mark this connection as controlled by Network Manager. Acceptable values are or (the default). Currently, setting this to yes will cause libreswan to skip reconfiguring resolv.conf when used with XAUTH and ModeConfig. libreswan-5.2/configs/d.ipsec.conf/nopmtudisc.xml000066400000000000000000000005371475767661000222060ustar00rootroot00000000000000 Disable Path MTU discovery for the IPsec SA. Acceptable values are (the default) or . Currently this feature is only implemented for the Linux XFRM stack. libreswan-5.2/configs/d.ipsec.conf/nssdir.xml000066400000000000000000000017271475767661000213250ustar00rootroot00000000000000 Specifies a directory for NSS database files. The default value is . It may contain the following files: pkcs11.txt Detailed info about NSS database creation parameters. 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-5.2/configs/d.ipsec.conf/ocsp-cache-max-age.xml000066400000000000000000000003611475767661000233360ustar00rootroot00000000000000 The maximum age (in seconds) before a new fetch will be attempted. The default is 1 day. libreswan-5.2/configs/d.ipsec.conf/ocsp-cache-min-age.xml000066400000000000000000000003621475767661000233350ustar00rootroot00000000000000 The minimum age (in seconds) before a new fetch will be attempted. The default is 1 hour. libreswan-5.2/configs/d.ipsec.conf/ocsp-cache-size.xml000066400000000000000000000005041475767661000227700ustar00rootroot00000000000000 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. libreswan-5.2/configs/d.ipsec.conf/ocsp-enable.xml000066400000000000000000000005501475767661000222040ustar00rootroot00000000000000 Whether to perform Online Certificate Store Protocol ("OCSP") checks on those certificates that have an OCSP URI defined. Acceptable values are or (the default). libreswan-5.2/configs/d.ipsec.conf/ocsp-method.xml000066400000000000000000000010321475767661000222320ustar00rootroot00000000000000 The HTTP methods used for fetching OCSP data. Valid options are (the default) and . 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. libreswan-5.2/configs/d.ipsec.conf/ocsp-strict.xml000066400000000000000000000014461475767661000222730ustar00rootroot00000000000000 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 or (the default). The strict mode refers to the NSS ocspMode_FailureIsVerificationFailure mode, while non-strict mode refers to the NSS ocspMode_FailureIsNotAVerificationFailure mode. libreswan-5.2/configs/d.ipsec.conf/ocsp-timeout.xml000066400000000000000000000003631475767661000224460ustar00rootroot00000000000000 The time until an OCSP request is aborted and considered failed. The default value is 2 seconds. libreswan-5.2/configs/d.ipsec.conf/ocsp-trustname.xml000066400000000000000000000006511475767661000230020ustar00rootroot00000000000000 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 . libreswan-5.2/configs/d.ipsec.conf/ocsp-uri.xml000066400000000000000000000007771475767661000215700ustar00rootroot00000000000000 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 . libreswan-5.2/configs/d.ipsec.conf/oe_conns.example000066400000000000000000000015541475767661000224570ustar00rootroot00000000000000conn clear type=passthrough authby=never left=%defaultroute right=%group auto=ondemand conn clear-or-private type=tunnel left=%defaultroute authby=null leftid=%null rightid=%null right=%opportunisticgroup failureshunt=passthrough negotiationshunt=passthrough auto=add conn private-or-clear type=tunnel left=%defaultroute authby=null leftid=%null rightid=%null right=%opportunisticgroup failureshunt=passthrough negotiationshunt=passthrough auto=ondemand conn private type=tunnel left=%defaultroute leftid=%null rightid=%null right=%opportunisticgroup negotiationshunt=hold failureshunt=drop auto=ondemand conn block type=reject authby=never left=%defaultroute right=%group auto=ondemand libreswan-5.2/configs/d.ipsec.conf/oe_conns.xml000066400000000000000000000006461475767661000216250ustar00rootroot00000000000000 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. libreswan-5.2/configs/d.ipsec.conf/overlapip.xml000066400000000000000000000014511475767661000220160ustar00rootroot00000000000000 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-5.2/configs/d.ipsec.conf/pam-authorize.xml000066400000000000000000000012121475767661000225750ustar00rootroot00000000000000 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 the IKEv1 option libreswan-5.2/configs/d.ipsec.conf/pfs.xml000066400000000000000000000006451475767661000206110ustar00rootroot00000000000000 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 (the default) and . libreswan-5.2/configs/d.ipsec.conf/phase2.xml000066400000000000000000000015731475767661000212040ustar00rootroot00000000000000 Sets the type of SA that will be produced. Valid options are: for encryption (the default), 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 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-5.2/configs/d.ipsec.conf/plutodebug.xml000066400000000000000000000011011475767661000221570ustar00rootroot00000000000000 Enable debug logging. For more information see ipsec-whack 8 and the option. This feature is used by Libreswan developers. The default logs should provide sufficient information to diagnose configuration and connection problems. libreswan-5.2/configs/d.ipsec.conf/policy-label.xml000066400000000000000000000007521475767661000223740ustar00rootroot00000000000000 The string representation of an access control security label that is interpreted by the Linux Security Module (e.g. SELinux) for use with Labeled IPsec. For example, Labeled IPsec support is IKEv2 only. libreswan-5.2/configs/d.ipsec.conf/policy_group_files.xml000066400000000000000000000034271475767661000237170ustar00rootroot00000000000000 POLICY GROUP FILES The optional files under @@IPSEC_CONFDDIR@@/policies, including @@IPSEC_CONFDDIR@@/policies/clear @@IPSEC_CONFDDIR@@/policies/clear-or-private @@IPSEC_CONFDDIR@@/policies/private-or-clear @@IPSEC_CONFDDIR@@/policies/private @@IPSEC_CONFDDIR@@/policies/block may contain policy group configuration information to supplement . 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 or 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 value. The system treats the resulting instances as normal connections. For example, given a suitable connection definition , and the file @@IPSEC_CONFDDIR@@/policies/private with an entry 192.0.2.3, the system creates a connection instance This connection inherits all details from , except that its right client is 192.0.2.3. libreswan-5.2/configs/d.ipsec.conf/ppk-ids.xml000066400000000000000000000012561475767661000213670ustar00rootroot00000000000000 EXPERIMENTAL: Specify which PPK_ID's to look for in .secrets file. The value must be a string (enclosed in quotes) containing a comma-separated list with PPK_ID's. Whitespaces cannot be a part of PPK_ID, i.e., they will be seen as a delimiter. If some PPK_ID's are specified and PPK feature is enabled (), one of the PPK secrets must have an ID matching one of the specified PPK_ID's. If this option is not set and the PPK feature is enabled, any matching PPK secret will be used. libreswan-5.2/configs/d.ipsec.conf/ppk.xml000066400000000000000000000014171475767661000206110ustar00rootroot00000000000000 EXPERIMENTAL: Post-quantum preshared keys (PPKs) to be used. Currently the accepted values are or (the default), signifying we propose to use PPK for this connection; , signifying we allow communication only if PPK is used for key derivation; or , 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 . This feature is based on RFC 8784. libreswan-5.2/configs/d.ipsec.conf/priority.xml000066400000000000000000000021621475767661000216760ustar00rootroot00000000000000 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 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-5.2/configs/d.ipsec.conf/protostack.xml000066400000000000000000000010361475767661000222050ustar00rootroot00000000000000 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-5.2/configs/d.ipsec.conf/redirect-to.xml000066400000000000000000000004221475767661000222330ustar00rootroot00000000000000 Where to send remote peers to via the option. This can be an IP address or hostname (FQDN). libreswan-5.2/configs/d.ipsec.conf/rekey.xml000066400000000000000000000011271475767661000211340ustar00rootroot00000000000000 whether a connection should be renegotiated when it is about to expire; acceptable values are (the default) and . The two ends need not agree, but while a value of prevents Pluto from requesting renegotiation, it does not prevent responding to renegotiation requested from the other end, so will be largely ineffective unless both ends agree on it. libreswan-5.2/configs/d.ipsec.conf/rekeyfuzz.xml000066400000000000000000000014551475767661000220570ustar00rootroot00000000000000 maximum percentage by which 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 ). The value of , after this random increase, must not exceed . The value will suppress time randomization. Relevant only locally, other end need not agree on it. libreswan-5.2/configs/d.ipsec.conf/rekeymargin.xml000066400000000000000000000006341475767661000223340ustar00rootroot00000000000000 how long before connection expiry or keying-channel expiry should attempts to negotiate a replacement begin; acceptable values as for (default ). Relevant only locally, other end need not agree on it. libreswan-5.2/configs/d.ipsec.conf/remote-peer-type.xml000066400000000000000000000011531475767661000232170ustar00rootroot00000000000000 Set the remote peer type. This can enable additional processing during the IKEv1 negotiation. Acceptable values are or (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-5.2/configs/d.ipsec.conf/replay-window.xml000066400000000000000000000024761475767661000226260ustar00rootroot00000000000000 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 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-5.2/configs/d.ipsec.conf/reqid.xml000066400000000000000000000022451475767661000211230ustar00rootroot00000000000000 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-5.2/configs/d.ipsec.conf/require-id-on-certificate.xml000066400000000000000000000013631475767661000247570ustar00rootroot00000000000000 When using certificates, check whether the IKE peer ID is present as a subjectAltName (SAN) on the peer certificate. Accepted values are (the default) or . 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-5.2/configs/d.ipsec.conf/retransmit-interval.xml000066400000000000000000000011431475767661000240250ustar00rootroot00000000000000 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 . See also: and libreswan-5.2/configs/d.ipsec.conf/retransmit-timeout.xml000066400000000000000000000011221475767661000236640ustar00rootroot00000000000000 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 . See also: and . libreswan-5.2/configs/d.ipsec.conf/salifetime.xml000066400000000000000000000021271475767661000221400ustar00rootroot00000000000000 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 (a time in seconds) or a decimal number followed by , , or (a time in minutes, hours, or days respectively) (default , maximum ). Normally, the connection is renegotiated (via the keying channel) before it expires. The two ends need not exactly agree on , 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-5.2/configs/d.ipsec.conf/seccomp.xml000066400000000000000000000045001475767661000214440ustar00rootroot00000000000000 Set the seccomp kernel syscall whitelisting feature. When set to , 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 , the kernel will only block the rogue syscall and pluto will attempt to continue. If set to , 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. By default, seccomp is disabled, as there is a significant performance penalty, custom updown scripts could trigger false positives, and system library updates could also trigger false positives. A false positive (or real malicious remote code execution of a bad syscall) will cause the pluto daemon to crash or hang. 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. To see if a seccomp rule got triggered, you must run with seccomp=enabled, and keep an eye on messages in the audit log (usually . Note that logging can be delayed by many seconds. This feature can be tested using ipsec whack --seccomp-crashtest. 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-5.2/configs/d.ipsec.conf/secretsfile.xml000066400000000000000000000005511475767661000223250ustar00rootroot00000000000000 pathname of the file that stores the secret credentials such as preshared keys (PSKs). See for the syntax. The default value is @@IPSEC_SECRETS@@. libreswan-5.2/configs/d.ipsec.conf/see_also.xml000066400000000000000000000004411475767661000216050ustar00rootroot00000000000000 SEE ALSO ipsec8, ipsec_rsasigkey8 libreswan-5.2/configs/d.ipsec.conf/seedbits.xml000066400000000000000000000013701475767661000216170ustar00rootroot00000000000000 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-5.2/configs/d.ipsec.conf/send-no-esp-tfc.xml000066400000000000000000000010741475767661000227200ustar00rootroot00000000000000 Whether or not to tell the remote peer that we do not support Traffic Flow Confidentiality ("TFC") (RFC-4303). Possible values are (the default) which allows the peer to use TFC or which prevents to peer from using TFC. This does not affect whether this endpoint uses TFC, which only depends on the local setting. This option is only valid for IKEv2. libreswan-5.2/configs/d.ipsec.conf/send-redirect.xml000066400000000000000000000012551475767661000225470ustar00rootroot00000000000000 Whether to send requests for the remote peer to redirect IKE/IPsec SA's during IKE_AUTH. Valid options are (the default) and . If set, the option must also be set to indicate where to redirect peers to. For redirection during IKE_SA_INIT exchange, see the and options. Runtime redirects can be triggered via the ipsec redirect command. libreswan-5.2/configs/d.ipsec.conf/send-vendorid.xml000066400000000000000000000017761475767661000225700ustar00rootroot00000000000000 whether to send our Vendor ID during IKE. Acceptable values are: (the default) and . The vendor id sent can be configured using the "config setup" option . 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-5.2/configs/d.ipsec.conf/sendca.xml000066400000000000000000000007421475767661000212540ustar00rootroot00000000000000 How much of our available X.509 trust chain to send with the End certificate, excluding any root CA's. Specifying sends just the issuing intermediate CA, while will send the entire chain of intermediate CA's. (the default) will not send any CA certs. libreswan-5.2/configs/d.ipsec.conf/sha2-truncbug.xml000066400000000000000000000016131475767661000225010ustar00rootroot00000000000000 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 , (the default) signifying default RFC truncation of 128 bits, or , signifying the draft 96 bits truncation. Another workaround is to switch from sha2_256 to sha2_128 or sha2_512. libreswan-5.2/configs/d.ipsec.conf/shuntlifetime.xml000066400000000000000000000013411475767661000226730ustar00rootroot00000000000000 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 and libreswan-5.2/configs/d.ipsec.conf/statsbin.xml000066400000000000000000000006611475767661000216460ustar00rootroot00000000000000 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-5.2/configs/d.ipsec.conf/syslog.xml000066400000000000000000000005671475767661000213440ustar00rootroot00000000000000 the syslog2 “facility” name and priority to use for startup/shutdown log messages, default . libreswan-5.2/configs/d.ipsec.conf/tcp-remoteport.xml000066400000000000000000000010511475767661000227750ustar00rootroot00000000000000 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 libreswan-5.2/configs/d.ipsec.conf/tfc.xml000066400000000000000000000016111475767661000205670ustar00rootroot00000000000000 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. libreswan-5.2/configs/d.ipsec.conf/type.xml000066400000000000000000000012511475767661000207740ustar00rootroot00000000000000 the type of the connection; currently the accepted values are (the default) signifying a host-to-host, host-to-subnet, or subnet-to-subnet tunnel; , signifying host-to-host transport mode; , signifying that no IPsec processing should be done at all; , signifying that packets should be discarded; and , signifying that packets should be discarded and a diagnostic ICMP returned. libreswan-5.2/configs/d.ipsec.conf/uniqueids.xml000066400000000000000000000017631475767661000220310ustar00rootroot00000000000000 Whether IDs should be considered identifying remote parties uniquely. Acceptable values are (the default) and . 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-5.2/configs/d.ipsec.conf/units.xml000066400000000000000000000050231475767661000211560ustar00rootroot00000000000000 SPECIFYING UNITS BYTE COUNTS AND BINARY DATA Options, such as , that expect a numeric byte count, also accept deciml fractions, and the following multipliers as a suffix: kilobytes (1024 bytes) megabytes (1024*1024 bytes) gigabytes (1024*1024*1024 bytes) terabytes (1024*1024*1024*1024 bytes) petabytes (1024*1024*1024*1024*1024 bytes) exabytes (1024*1024*1024*1024*1024*1024 bytes) DURATION Options, such as , that expect a numeric duration, also accept decimal fractions, and the following multipliers as a suffix: microseconds (1/1000000 seconds) milliseconds (1/1000 seconds) seconds minutes (60 seconds) hours (60*60 seconds) days (24*60*60 seconds) weeks (7*24*60*60 seconds) For instance, 1ms and 1000us, 0.5s and 500ms, 1.5h and 90m, are each equivalent. libreswan-5.2/configs/d.ipsec.conf/virtual-private.xml000066400000000000000000000037201475767661000231540ustar00rootroot00000000000000 contains the networks that are allowed as (left|right)subnet= for the remote clients when using the or keywords in the 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 and IPv6 is denoted as . 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: . 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 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-5.2/configs/d.ipsec.conf/vti-interface.xml000066400000000000000000000031361475767661000225570ustar00rootroot00000000000000 This option is deprecated. See instead. 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 or 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 is used, no manual iptables should be required. However, administrators can use the iptables mangle table to mark traffic manually if desired. libreswan-5.2/configs/d.ipsec.conf/vti-routing.xml000066400000000000000000000014501475767661000223030ustar00rootroot00000000000000 Whether or not to add network rules or routes for IPsec SA's to the respective VTI devices. Valid values are (the default) or . When using "routing based VPNs" with a subnets policy of 0.0.0.0/0, this setting needs to set to 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 , the _updown script will automatically route the leftsubnet/rightsubnet traffic into the VTI device specified with libreswan-5.2/configs/d.ipsec.conf/vti-shared.xml000066400000000000000000000011041475767661000220560ustar00rootroot00000000000000 Whether or not the VTI device is shared amongst connections. Valid values are (the default) or . 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-5.2/configs/d.ipsec.conf/xauthby.xml000066400000000000000000000026131475767661000215020ustar00rootroot00000000000000 When IKEv1 XAUTH support is available, set the method used by XAUTH to authenticate the user with IKEv1. The currently supported values are (the default), or . The password file is located at , and follows a syntax similar to the Apache htpasswd file, except an additional connection name argument (and optional static IP address) are also present: 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 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 libreswan-5.2/configs/d.ipsec.conf/xauthfail.xml000066400000000000000000000012341475767661000220010ustar00rootroot00000000000000 When XAUTH support is available, set the failure method desired when authentication has failed. The currently supported values are (the default) and . 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-5.2/configs/d.ipsec.conf/xfrmlifetime.xml000066400000000000000000000017421475767661000225130ustar00rootroot00000000000000 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 and libreswan-5.2/configs/ipsec.conf.5.xml000066400000000000000000000411701475767661000177400ustar00rootroot00000000000000 Libreswan'> Linux'> NetBSD'> FreeBSD'> OpenBSD'> ]> IPSEC.CONF 5 24 Apr 2023 Libreswan @@IPSECVERSION@@ File formats and conventions ipsec.conf IPsec configuration and connections &connsections; &units; &exampleleftright; CONN 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. &keyexchange; &hostaddrfamily; &clientaddrfamily; &type; &iptfs; &left; &leftsubnet; &leftsubnets; &leftvti; &leftaddresspool; &leftprotoport; &leftnexthop; &leftsourceip; &leftupdown; &leftcat; &leftfirewall; 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 script (see ipsec_pluto8). The implementation of this makes certain assumptions about firewall setup, and the availability of the tools. In situations calling for more control, it may be preferable for the user to supply his own script, which makes the appropriate adjustments for his system. CONN 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. &auto; &authby; &ike; &phase2; &sha2-truncbug; &ms-dh-downgrade; &dns-match-id; &require-id-on-certificate; &ppk; &ppk-ids; &nat-ikev1-method; &esp; &ah; &fragmentation; &ikepad; &mobike; &intermediate; &esn; &decap-dscp; &encap-dscp; &nopmtudisc; &narrowing; &nic-offload; &leftid; &leftrsasigkey; &leftcert; &leftckaid; &leftauth; &leftautheap; &leftca; &leftikeport; &leftsendcert; &leftxauthserver; &leftxauthclient; &leftusername; &leftmodecfgserver; &leftmodecfgclient; &xauthby; &xauthfail; &pam-authorize; &modecfgpull; &modecfgoptions; &remote-peer-type; &nm-configured; &encapsulation; &enable-tcp; &tcp-remoteport; &nat-keepalive; &initial-contact; &cisco-unity; &ignore-peer-dns; &accept-redirect-to; &accept-redirect; &redirect-to; &send-redirect; &fake-strongswan; &send-vendorid; &overlapip; &reqid; &dpddelay; &dpdtimeout; &pfs; &aggressive; &salifetime; &ipsec-max-bytes; &ipsec-max-packets; &replay-window; &rekey; &rekeymargin; &rekeyfuzz; &ikelifetime; &retransmit-timeout; &retransmit-interval; &compress; &metric; &mtu; &tfc; &send-no-esp-tfc; &nflog; &mark; &mark-in; &mark-out; &vti-interface; &vti-routing; &vti-shared; &ipsec-interface; &interface-ip; &priority; &sendca; &policy-label; &failureshunt; &negotiationshunt; &debug; CONFIG SECTIONS At present, the only section known to the IPsec software is the one named , which contains information used when the software is being started. Parameters are optional unless marked “(required)”. The currently-accepted names in a section are: &protostack; &listen; &ike-socket-bufsize; &ike-socket-errqueue; &listen-udp; &listen-tcp; &nflog-all; &keep-alive; &virtual-private; &myvendorid; &nhelpers; &seedbits; &ikev1-policy; &crlcheckinterval; &crl-strict; &curl-iface; &curl-timeout; &ocsp-enable; &ocsp-strict; &ocsp-method; &ocsp-timeout; &ocsp-uri; &ocsp-trustname; &ocsp-cache-size; &ocsp-cache-min-age; &ocsp-cache-max-age; &syslog; &plutodebug; &uniqueids; &logfile; &logappend; &logip; &audit-log; &logtime; &ddos-mode; &ddos-ike-threshold; &global-redirect; &global-redirect-to; &max-halfopen-ike; &shuntlifetime; &xfrmlifetime; &dumpdir; &statsbin; &ipsecdir; &nssdir; &secretsfile; &seccomp; &dnssec-enable; &dnssec-rootkey-file; &dnssec-anchors; &ipsec-interface-managed; &oe_conns; &policy_group_files; &default_policy_groups; &choosing_a_connection; &files; &see_also; &history; &bugs; &author; libreswan-5.2/configs/ipsec.conf.in000066400000000000000000000062131475767661000174020ustar00rootroot00000000000000# @@CONFDIR@@/ipsec.conf - Libreswan 4.x 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=@@LOGDIR@@/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" # Whether to log IP addresses of incoming connections. Disable when # logfile privacy is required. #logip=yes # 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 the IKEv2 # anti-DDoS # counter measures. #ddos-mode=auto # DDoS defense mechanism threshold # The number of half-open IKE SAs before the pluto IKE daemon will be # placed in (anti-ddos) busy mode. The default is 25000. # IKEv1 policy (accept, reject or drop) # See RFC XXX - Deprecation of IKEv1 and obsoleted algorithms #ikev1-policy=accept # IKEv2 global redirect (during IKE_SA_INIT) # 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. this can be given to the IKE daemon while running using # ipsec whack --global-redirect{-to} #global-redirect=no #global-redirect-to=, ... # The number of half-open IKE SAs before the IKE daemon starts # refusing all new IKE attempts. Established IKE peers are not # affected. #max-halfopen-ike=5000 # Whether pluto performs DNSSEC validation. #dnssec-enable=yes # To accept IKE and IPsec encapsulation over TCP. Requires at least # Linux 5.7 kernel or a kernel with TCP backport (like RHEL8 4.18.0-291) # To enable IKE and IPsec over TCP for VPN client, also specify # tcp-remote-port=4500 in the client's conn section. #listen-tcp=no # SECCOMP syscall filtering (enabled,disabled or tolerant) # Whether to log (when tolerant) or restart (when enabled) when # a rogue syscall is attempted by pluto indicating a remote code # exploit attempt. # If using custom _updown scripts, this might # trigger false positives. #seccomp=disabled # 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-5.2/configs/ipsec.secrets.5.xml000066400000000000000000000307421475767661000204660ustar00rootroot00000000000000 IPSEC.SECRETS 5 25 September 2020 Libreswan @@IPSECVERSION@@ File formats and conventions 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. 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 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@@ SEE ALSO The rest of the Libreswan distribution, in particular ipsec.conf5, ipsec8, ipsec-newhostkey8, ipsec-rsasigkey8, ipsec-showhostkey8, ipsec-rereadsecrets8, and ipsec-listen8. 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. AUTHOR PaulWouters libreswan-5.2/configs/ipsec.secrets.example000066400000000000000000000012641475767661000211530ustar00rootroot00000000000000# sample @@IPSEC_SECRETS@@ 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" # get secrets from other files include ipsec.*.secrets libreswan-5.2/configs/ipsec.secrets.in000066400000000000000000000011471475767661000201260ustar00rootroot00000000000000# 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-5.2/configs/libreswan.in000066400000000000000000000001071475767661000173350ustar00rootroot00000000000000@@LOGDIR@@/pluto.log { missingok notifempty copytruncate } libreswan-5.2/configs/pam.d/000077500000000000000000000000001475767661000160205ustar00rootroot00000000000000libreswan-5.2/configs/pam.d/pluto000066400000000000000000000007761475767661000171200ustar00rootroot00000000000000#%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-5.2/configs/pam.d/pluto.example-url000066400000000000000000000016741475767661000213500ustar00rootroot00000000000000#%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-5.2/configs/pam.d/pluto.example.google-authenticator000066400000000000000000000006761475767661000246740ustar00rootroot00000000000000#%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-5.2/configs/pam.d/pluto.example.sssdldap-secureid000066400000000000000000000014241475767661000241560ustar00rootroot00000000000000#%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-5.2/configs/portexcludes.conf.in000066400000000000000000000007301475767661000210160ustar00rootroot00000000000000# 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-5.2/configs/private-or-clear.in000066400000000000000000000013301475767661000205220ustar00rootroot00000000000000# 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-5.2/configs/private.in000066400000000000000000000011461475767661000170250ustar00rootroot00000000000000# 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-5.2/contrib/000077500000000000000000000000001475767661000150315ustar00rootroot00000000000000libreswan-5.2/contrib/README000066400000000000000000000010411475767661000157050ustar00rootroot00000000000000 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-5.2/contrib/_secretcensor/000077500000000000000000000000001475767661000176675ustar00rootroot00000000000000libreswan-5.2/contrib/_secretcensor/Makefile000066400000000000000000000013621475767661000213310ustar00rootroot00000000000000# 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-5.2/contrib/_secretcensor/_secretcensor.in000077500000000000000000000036471475767661000230720ustar00rootroot00000000000000#!@@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-5.2/contrib/_secretcensor/ipsec-_secretcensor.8.xml000066400000000000000000000036071475767661000245240ustar00rootroot00000000000000 IPSEC-_SECRETCENSOR 8 25 Apr 2002 libreswan Executable programs ipsec-_secretcensor internal routing to sanitize files DESCRIPTION ipsec _secretcensor is called by ipsec barf to process the @@IPSEC_SECRETS@@ 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. Upated for <https://libreswan.org> by Paul Wouters and Tuomo Soini. AUTHOR HenrySpencer libreswan-5.2/contrib/barf/000077500000000000000000000000001475767661000157435ustar00rootroot00000000000000libreswan-5.2/contrib/barf/Makefile000066400000000000000000000013511475767661000174030ustar00rootroot00000000000000# 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=barf ifdef top_srcdir include $(top_srcdir)/mk/program.mk else include ../../mk/program.mk endif libreswan-5.2/contrib/barf/barf.in000077500000000000000000000255041475767661000172160ustar00rootroot00000000000000#!@@SHELL_BINARY@@ # -*- mode: sh; sh-shell: sh -*- # dump assorted information of use in debugging # Copyright (C) 1998, 1999 Henry Spencer. # 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. # LC_ALL=C export LC_ALL LOGS=${LOGS-/var/log} me="ipsec barf" # kludge to produce no barf output mentioning policygroups if none are present. # This will not catch ".file" policygroups. PREPOLICIES=@@IPSEC_CONFDDIR@@/policies if [ -n "$(ls ${PREPOLICIES} 2>/dev/null)" ]; then POLICIES=${PREPOLICIES} fi # message patterns that start relevant parts of logs fstart='Starting Libreswan' pstart='Starting Pluto' case "${1}" in --help) echo "Usage: ipsec barf" exit 0 ;; --version) echo "$me $IPSEC_VERSION" exit 0 ;; esac # log-location guesser, results in ${findlog_file} and ${findlog_startline} # Fine point: startline is the *last* line containing "string", or # failing that, the *first* line containing "fallbackstring". findlog() { # findlog string fallbackstring possiblefile ... s="${1}" shift t="${1}" shift # try the suggested files first for f do if [ -s ${LOGS}/${f} -a \ -f ${LOGS}/${f} ] && \ grep -E -q "${s}" ${LOGS}/${f} 2>/dev/null then # aha, this one has it findlog_file=${LOGS}/${f} findlog_startline=$(grep -E -n "${s}" ${LOGS}/${f} | \ sed -n '$s/:.*//p') return 0 fi done for f do if [ -s ${LOGS}/${f} -a \ -f ${LOGS}/${f} ] && \ grep -E -q "${t}" ${LOGS}/${f} 2>/dev/null then # aha, this one has it findlog_file=${LOGS}/${f} findlog_startline=$(grep -E -n "${t}" ${LOGS}/${f} | \ sed -n '1s/:.*//p') return 0 fi done # nope, resort to a search, newest first, of uncompressed logs for f in $(ls -t ${LOGS} | grep -E -v 'lastlog|tmp|^mail|\.(gz|Z)$') do if [ -f ${LOGS}/${f} -a \ ! -d ${LOGS}/${f} ] && \ grep -E -q "${s}" ${LOGS}/${f} 2>/dev/null then # found it findlog_file=${LOGS}/${f} findlog_startline=$(grep -E -n "${s}" ${LOGS}/${f} | \ sed -n '$s/:.*//p') return 0 fi done for f in $(ls -t ${LOGS} | grep -E -v 'lastlog|tmp|^mail|\.(gz|Z)$') do if [ -s ${LOGS}/${f} -a \ -f ${LOGS}/${f} ] && \ grep -E -q "${t}" ${LOGS}/${f} 2>/dev/null then # found it findlog_file=${LOGS}/${f} findlog_startline=$(grep -E -n "${t}" ${LOGS}/${f} | \ sed -n '1s/:.*//p') return 0 fi done # echo "$0: unable to find ${LOGS}/${1} or local equivalent" >&2 findlog_file=/dev/null findlog_startline=1 # arbitrary } if [ ! -x /usr/bin/journalctl -a ! -x /bin/journalctl ]; then # no systemd, need to figure out log file location findlog "$pstart" "Pluto" secure auth.log daemon.log debug if [ "${findlog_file}" = "/dev/null" ]; then echo "Unable to find Pluto messages, typically found in /var/log/secure or equivalent. You may need to run Libreswan for the first time; alternatively, your log files have been emptied (ie, logrotate) or we do not understand your logging configuration." fi plog=${findlog_file} pline=${findlog_startline} fi # /lib/modules examiner modulegoo() { set +x for d in $(ls /lib/modules) do if test -d /lib/modules/${d} then f=/lib/modules/${d}/${1} if [ -f ${f} ]; then nm -g ${f} | grep -E "${2}" else echo fi | sed "s;^;${d}: ;" fi done set -x } # advanced shell deviousness to get dividers into output _________________________() { ${2} # something to do nothing and not echo anything } exec 2>&1 # stderr on stdout, so errors go into main output hostname date set -x _________________________ version ipsec --version _________________________ /proc/version cat /proc/version if [ -r /proc/sys/net/core/xfrm_acq_expires ]; then _________________________ ip-xfrm-state ip xfrm state _________________________ ip-xfrm-policy ip xfrm policy _________________________ cat-proc-net-xfrm_stat cat /proc/net/xfrm_stat fi _________________________ ip-l2tp-tunnel if [ -d /sys/module/l2tp_core ]; then ip l2tp show tunnel _________________________ ip-l2tp-session ip l2tp show session fi if [ -d /sys/module/ip_vti ]; then _________________________ ip-tunnel ip -s tunnel show fi _________________________ /proc/crypto if [ -r /proc/crypto ]; then cat /proc/crypto fi __________________________/proc/sys/net/core/xfrm-star for i in /proc/sys/net/core/xfrm_* do echo -n "${i}: " cat $i done _________________________ /proc/sys/net/ipsec-star if [ -d /proc/sys/net/ipsec ]; then ( cd /proc/sys/net/ipsec && grep -E '^' * ) fi _________________________ ipsec/status ipsec whack --status _________________________ ip-addr-list ip addr list _________________________ ip-route-list-table-all ip route list table all _________________________ ip-rule-list ip rule list _________________________ ipsec_verify ipsec verify --nocolour _________________________ ipsec/directory ipsec --directory _________________________ hostname/fqdn hostname --fqdn _________________________ hostname/ipaddress hostname --ip-address _________________________ uptime uptime _________________________ ps # -i ppid picks up the header ps alxwf | grep -E -i 'ppid|pluto|ipsec' _________________________ ipsec/conf ipsec readwriteconf --config @@IPSEC_CONF@@ _________________________ ipsec/secrets cat @@IPSEC_SECRETS@@ | ipsec _secretcensor _________________________ ipsec/listall ipsec whack --listall _________________________ nss/contents certutil -L -d sql:@@IPSEC_NSSDIR@@ _________________________ nss/crls crlutil -L -d sql:@@IPSEC_NSSDIR@@ if [ -n "${POLICIES}" ]; then for policy in ${POLICIES}/* do base=$(basename ${policy}); _________________________ ipsec/policies/${base} cat ${policy} done fi _________________________ ipsec/ls-execdir ls -l ${IPSEC_EXECDIR} _________________________ /proc/net/dev cat /proc/net/dev _________________________ /proc/net/route cat /proc/net/route _________________________ /proc/sys/net/ipv4/ip_no_pmtu_disc cat /proc/sys/net/ipv4/ip_no_pmtu_disc _________________________ /proc/sys/net/ipv4/ip_forward cat /proc/sys/net/ipv4/ip_forward _________________________ /proc/sys/net/ipv4/tcp_ecn cat /proc/sys/net/ipv4/tcp_ecn _________________________ /proc/sys/net/ipv4/conf/star-rp_filter ( cd /proc/sys/net/ipv4/conf && grep -E '^' */rp_filter ) _________________________ /proc/sys/net/ipv4/conf/star-star-redirects ( cd /proc/sys/net/ipv4/conf && grep -E '^' */*redirects ) _________________________ /proc/sys/net/ipv4/tcp_window_scaling cat /proc/sys/net/ipv4/tcp_window_scaling _________________________ /proc/sys/net/ipv4/tcp_adv_win_scale cat /proc/sys/net/ipv4/tcp_adv_win_scale _________________________ uname-a uname -a _________________________ config-built-with if [ -r /proc/config_built_with ]; then cat /proc/config_built_with fi _________________________ distro-release for distro in /etc/redhat-release /etc/debian-release /etc/SuSE-release /etc/mandrake-release /etc/mandriva-release /etc/gentoo-release do if [ -f ${distro} ]; then cat ${distro} fi done USE_IPTABLES=@@USE_IPTABLES@@ USE_NFTABLES=@@USE_NFTABLES@@ if test "${USE_NFTABLES}" = true; then nft list ruleset elif test "${USE_IPTABLES}" = true; then _________________________ iptables if [ -e /proc/net/ip_tables_names ]; then if [ -r /sbin/iptables-save -o -r /usr/sbin/iptables-save ]; then iptables-save --modprobe=/dev/null else if [ -r /sbin/iptables -o -r /usr/sbin/iptables ]; then iptables -L -v -n _________________________ iptables-nat grep ^nat /proc/net/ip_tables_names >/dev/null 2>&1 && \ iptables -t nat -L -v -n _________________________ iptables-mangle grep ^mangle /proc/net/ip_tables_names >/dev/null 2>&1 && \ iptables -t mangle -L -v -n fi fi fi else echo "no iptable or nftable support" fi _________________________ ip6tables if [ -e ip6_tables_names ]; then if [ -r /sbin/ip6tables-save -o -r /usr/sbin/ip6tables-save ]; then ip6tables-save --modprobe=/dev/null else if [ -r /sbin/ip6tables -o -r /usr/sbin/ip6tables ]; then [ -e /proc/net/ip_tables_names ] && ip6tables -L -v -n # There is no IPv6 NAT yet (hopefully that will remain so) _________________________ ip6tables-mangle grep ^mangle /proc/net/ip6_tables_names >/dev/null 2>&1 && \ ip6tables -t mangle -L -v -n fi fi fi _________________________ /proc/modules if [ -f /proc/modules ]; then cat /proc/modules else echo "kernel without module support" fi _________________________ usr/src/linux/.config if [ -f /proc/config.gz ]; then zcat /proc/config.gz | grep -E 'IPSEC|ESP|CONFIG_NET_KEY|CONFIG_INET|CONFIG_IP|_XFRM' elif [ -f /lib/modules/$(uname -r)/build/.config ]; then cat /lib/modules/$(uname -r)/build/.config | grep -E 'IPSEC|ESP|CONFIG_NET_KEY|CONFIG_INET|CONFIG_IP|_XFRM' else echo "no .config file found, cannot list kernel properties" fi if [ -f /etc/syslog.conf ]; then _________________________ etc/syslog.conf cat /etc/syslog.conf fi if [ -f /etc/syslog-ng/syslog-ng.conf ]; then _________________________ etc/syslog-ng/syslog-ng.conf cat /etc/syslog-ng/syslog-ng.conf fi if [ -f /etc/rsyslog.conf ]; then _________________________ etc/rsyslog.conf cat /etc/rsyslog.conf fi _________________________ etc/resolv.conf cat /etc/resolv.conf _________________________ lib/modules-ls ls -ltr /lib/modules _________________________ fipscheck cat /proc/sys/crypto/fips_enabled _________________________ /proc/ksyms-netif_rx if [ -r /proc/ksyms ]; then grep -E netif_rx /proc/ksyms else if [ -r /proc/kallsyms ]; then grep -E netif_rx /proc/kallsyms else echo "broken (redhat/fedora) 2.6 kernel without kallsyms" fi fi _________________________ kern.debug if [ -f ${LOGS}/kern.debug ]; then tail -100 ${LOGS}/kern.debug fi _________________________ klog dmesg | grep -E -i "xfrm|ipsec|esp" _________________________ plog if [ -x /usr/bin/journalctl -o -x /bin/journalctl ]; then journalctl -u ipsec.service --no-pager --since "24 hours ago" | \ case "${1}" in --short) tail -500 ;; *) cat ;; esac else sed -n ${pline},'$'p ${plog} | \ grep -E -i 'pluto' | \ case "${1}" in --short) tail -500 ;; *) cat ;; esac fi _________________________ date date libreswan-5.2/contrib/barf/ipsec-barf.8.xml000066400000000000000000000103411475767661000206450ustar00rootroot00000000000000 IPSEC-BARF 8 4 September 2016 libreswan Executable programs ipsec-barf spew out collected IPsec debugging information ipsec barf --short DESCRIPTION barf outputs (on standard output) a collection of debugging information (contents of files, selections from logs, etc.) related to the IPsec encryption/authentication system. It is primarily a convenience for remote debugging, a single command that packages up (and labels) all information that might be relevant to diagnosing a problem in IPsec. The option limits the length of the log portion of barf's output, which can otherwise be extremely voluminous if debug logging is turned on. On systems with systemd, ipsec barf will look for logs using the journalctl command. If the logfile= option is used, logs will also not be found by the ipsec barf command. barf censors its output, replacing keys and secrets with brief checksums to avoid revealing sensitive information. Beware that the output of both commands is aimed at humans, not programs, and the output format is subject to change without warning. barf has to figure out which files in /var/log contain the IPsec log messages. It looks for general log messages first in messages and syslog, and for Pluto messages first in secure, auth.log, and debug. In both cases, if it does not find what it is looking for in one of those “likely” places, it will resort to a brute-force search of most (non-compressed) files in /var/log. FILES /proc/net/* /var/log/* @@IPSEC_CONF@@ @@IPSEC_SECRETS@@ HISTORY Written for the Linux FreeS/WAN project <https://www.freeswan.org> by Henry Spencer. BUGS barf uses heuristics to try to pick relevant material out of the logs, and relevant messages that are not labelled with any of the tags that barf looks for will be lost. We think we've eliminated the last such case, but one never knows... Finding updown scripts (so they can be included in output) is, in general, difficult. barf uses a very simple heuristic that is easily fooled. The brute-force search for the right log files can get expensive on systems with a lot of clutter in /var/log. AUTHOR PaulWouters libreswan-5.2/contrib/c-swan/000077500000000000000000000000001475767661000162215ustar00rootroot00000000000000libreswan-5.2/contrib/c-swan/Makefile000066400000000000000000000011101475767661000176520ustar00rootroot00000000000000.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-5.2/contrib/c-swan/is_encrypted.c000066400000000000000000000035711475767661000210630ustar00rootroot00000000000000/* * 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-5.2/contrib/c-swan/swan.c000066400000000000000000000156751475767661000173530ustar00rootroot00000000000000/* * 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-5.2/contrib/c-swan/swan.h000066400000000000000000000017121475767661000173430ustar00rootroot00000000000000/* * 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-5.2/contrib/cisco-decrypt/000077500000000000000000000000001475767661000176015ustar00rootroot00000000000000libreswan-5.2/contrib/cisco-decrypt/Makefile000066400000000000000000000004231475767661000212400ustar00rootroot00000000000000all: 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-5.2/contrib/cisco-decrypt/README000066400000000000000000000002601475767661000204570ustar00rootroot00000000000000See 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-5.2/contrib/cisco-decrypt/cisco-decrypt.1000066400000000000000000000020261475767661000224330ustar00rootroot00000000000000.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-5.2/contrib/cisco-decrypt/cisco-decrypt.c000066400000000000000000000104631475767661000225210ustar00rootroot00000000000000 /* 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-5.2/contrib/cisco-pcf/000077500000000000000000000000001475767661000166775ustar00rootroot00000000000000libreswan-5.2/contrib/cisco-pcf/README000066400000000000000000000006761475767661000175700ustar00rootroot00000000000000This 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-5.2/contrib/cisco-pcf/pcf2os.pl000077500000000000000000000020501475767661000204300ustar00rootroot00000000000000#!/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-5.2/contrib/cisco-pcf/sample.pcf000066400000000000000000000010461475767661000206530ustar00rootroot00000000000000[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-5.2/contrib/ipsec-dyndns/000077500000000000000000000000001475767661000174315ustar00rootroot00000000000000libreswan-5.2/contrib/ipsec-dyndns/README000066400000000000000000000004011475767661000203040ustar00rootroot00000000000000 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-5.2/contrib/ipsec-dyndns/dyn.nohats.ca.key000066400000000000000000000001321475767661000226060ustar00rootroot00000000000000key "dyn.nohats.ca" { algorithm hmac-sha256; secret "NotTheRealSecretKeyObviously"; }; libreswan-5.2/contrib/ipsec-dyndns/ipseckey-update000077500000000000000000000041301475767661000224510ustar00rootroot00000000000000#!/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 < # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT 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=look ifdef top_srcdir include $(top_srcdir)/mk/program.mk else include ../../mk/program.mk endif libreswan-5.2/contrib/look/ipsec-look.8.xml000066400000000000000000000042301475767661000207310ustar00rootroot00000000000000 look 8 28 Oct 2006 libreswan Executable programs ipsec-look get a quick summary of Libreswan status ipsec look DESCRIPTION Look is used to get a quick overview of what the status of Libreswan is. the equivalent to running the commands SEE ALSO ipsec8, ipsec-tncfg8, ipsec-spi8, ipsec-spigrp8, ipsec-eroute5, netstat8 HISTORY Man page written for the Linux FreeS/WAN project <https://www.freeswan.org/> by Michael Richardson. Original program written by Henry Spencer. AUTHOR Paul Wouters libreswan-5.2/contrib/look/look.in000077500000000000000000000114761475767661000173050ustar00rootroot00000000000000#!@@SHELL_BINARY@@ # -*- mode: sh; sh-shell: sh -*- # quick look at current connections and related information # Copyright (C) 1998, 1999 Henry Spencer. # Copyright (C) 2012-2019 Paul Wouters # Copyright (C) 2015 Tuomo Soini # 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. # LC_ALL=C export LC_ALL me="ipsec look" case "$1" in --help) echo "Usage: ${me}" exit 0 ;; --version) echo "$me $IPSEC_VERSION" exit 0 ;; esac # The ability to select what is displayed is internal, but is used for # testing. firewall_cmd() { USE_IPTABLES=@@USE_IPTABLES@@ USE_NFTABLES=@@USE_NFTABLES@@ if [ "${USE_NFTABLES}" = true ]; then #nft has precedence FIREWALL=NFTABLES elif [ "${USE_IPTABLES}" = true ]; then FIREWALL=IPTABLES else FIREWALL="" fi } default() { look_state=$1 look_policy=$1 test "${FIREWALL}" = IPTABLES && look_iptables=$1 || look_iptables=false test "${FIREWALL}" = NFTABLES && look_nftables=$1 || look_nftables=false look_route=$1 look_nss=$1 } firewall_cmd if test $# -eq 0 ; then default true else default false while test $# -gt 0 ; do case "$1" in state) look_state=true ;; policy) look_policy=true ;; iptables) look_iptables=true ;; nftables) look_nftables=true ;; route ) look_route=true ;; nss ) look_nss=true ;; * ) echo Usage: ${me} ; exit 1 ;; esac shift done fi # label it just to be sure echo "$(hostname) $(date)" # xfrm if ${look_state} ; then if [ -f /proc/sys/net/core/xfrm_acq_expires ]; then echo "XFRM state:" ip xfrm state fi fi if ${look_policy} ; then if [ -f /proc/sys/net/core/xfrm_acq_expires ]; then echo "XFRM policy:" # Force the order by feeding sort with lines prefixed by '[46] # TYPE PRIORITY |'. # # XXX: should this also sort the direction? ip -o xfrm policy | { # clean up the input: drop socket lines; strip trailing # white space (either end of line or before \\); strip # double \\s sed -e '/socket/d' \ -e 's/\s*\\/\\/g' \ -e 's/\\\\/\\/g' \ -e 's/[\\]*\s*$//g' } | { # Build the '<[46]> |' prefix ready for # sorting. For each field, start with the assumption that # the value is unknown (setting it to the default), and # then adjust it as necessary. For instance, for the # protocol, start out assuming it is '4' (IPv4) and then # if the line contains a ':' switch the prefix to '6' # (IPv6). sed -e 's/^/| /' \ \ -e 's/^/0 /' \ -e 's/^0 \(.* priority \([0-9][0-9]*\)\)/\2 \1/' \ \ -e 's/^/0 /' \ -e 's/^0 \(.*:.* type \([0-9][0-9]*\)\)/\2 \1/' \ \ -e 's/^/4 /' \ -e 's/^4 \(.*:\)/6 \1/' } | { # sort by each of the prefixes individually, and then by # the rest of the line. Shorter forms like -n and -k1,3n # don't do what is wanted. # # XXX: Should add 'V' so .24. is before .200.? sort -b -k1,1n -k2,2n -k3,3n -k5 } | { # strip the sort prefixes sed -e 's/^.* | //' } | { # convert \ into line breaks tr '\\' '\012' } fi fi if ${look_state} || ${look_policy} ; then if [ -f /proc/sys/net/core/xfrm_acq_expires ]; then echo "XFRM done" fi fi if ${look_nftables} ; then echo nft list ruleset nft list ruleset fi if ${look_iptables} ; then echo IPSEC mangle TABLES if grep -q ^mangle /proc/net/ip_tables_names 2>/dev/null; then iptables -n -t mangle -L IPSEC fi if grep -q ^mangle /proc/net/ip6_tables_names 2>/dev/null; then ip6tables -n -t mangle -L IPSEC fi echo iptables filter TABLE iptables -n -t filter -L fi if ${look_route} ; then echo ROUTING TABLES # The IP command includes extra and evoling white space { ip -4 route ip -6 route } | sed -e 's/ / /g' -e 's/ $//' fi if ${look_nss} ; then if [ -f @@IPSEC_NSSDIR@@/cert9.db ]; then echo NSS_CERTIFICATES certutil -L -d sql:@@IPSEC_NSSDIR@@ | head -4 certutil -L -d sql:@@IPSEC_NSSDIR@@ | \ grep -E -v '^NSS_CERTIFICATES|^$|Trust Attributes|MIME,' | LC_ALL=C sort elif [ -f @@IPSEC_NSSDIR@@/cert8.db ]; then echo NSS_CERTIFICATES certutil -L -d @@IPSEC_NSSDIR@@ | head -4 certutil -L -d @@IPSEC_NSSDIR@@ | \ grep -E -v '^NSS_CERTIFICATES|^$|Trust Attributes|MIME,' | LC_ALL=C sort fi fi libreswan-5.2/contrib/lucent/000077500000000000000000000000001475767661000163235ustar00rootroot00000000000000libreswan-5.2/contrib/lucent/README000066400000000000000000000116411475767661000172060ustar00rootroot00000000000000 helper program to interop with non-rfc IPsec implementation of Lucent. From Rolando: Lucent's way to work around NATing is to change this: | IP | whatever L4 proto | Payload | where IP has the (IP source; IP dest) within it into this: | IP | UDP:XXX | IP | whatever L4 proto | Payload | where IP have the same (IP source; IP dest) within them and XXX is the configurable UDP port (default=501) In a nutshell, they "tunnelize" all the traffic to/from the client and the gateway into a IP/UDP:XXX header May be there are better ways to do it but using iptables QUEUE is the one we used to encapsulate/decapsulate. I thought about adding it to LSW code as well as some code to make it manipulate iptables QUEUE stuff but got lost on it. :-( ---------- Forwarded message ---------- Date: Sun, 5 Apr 2009 10:36:54 -0700 (PDT) From: Rolando Zappacosta Cc: users@libreswan.org To: Paul Wouters Subject: Re: [Libreswan Users] Connection against a Lucent FW success!!!! but may be there's still room for improvement Hi all, I could finally manage to get LSW to work against a Lucen VPN Gateway even through NAT. So, in case someone else needs such connection, compile below code and then run this: modprobe ip_queue UDP501encap & iptables -A OUTPUT -d IPofLucentGW -j QUEUE iptables -A INPUT -s IPofLucentGW -j QUEUE before launching LSW as usual. > I discussed this subject here: > > https://lists.libreswan.org/pipermail/users/2008-February/014030.html > based on >> what I could capture under Windows, the relevant part > of it is: >> "I'm trying to connect OpenSwan to a Lucent > VPN Gateway, which according to >> its ASCII interpretation of its Vendor ID payload is: >> > 4C5647392E312E3235353A425249434B3A392E312E323535="LVG9.1.255:BRICK:9.1.255". > I >> can connect to it by means of the Lucent VPN Client > V7.1.2 on a Windows XP >> computer (Vendor ID= > 4C5643372E312E323A5850="LVC7.1.2:XP")." > > Thanks. Normally vendorids are md5sum's of some text, > though in this case > that does not seem to be the case. I added them as-is to > vendor.c for now. > >> Seems one can know the running version of the client > and server just looking >> on the vendor id part of an ASCII capture dump. >> Interesting thing is, as explained to you privatelly, > the way the PSK gets >> handled here. Under the LVC (windows) I had to > configure a PSK like: >> where the real PSK is 9 ASCII > characters long. However, I >> could find that in order to have LSW establishing > phase 1 successfully I had to >> add the string "01234567890" as a trailer, > i.e. my ipsec.secrets looks like: >> !@#$% : PSK > "01234567890" >> >> what gives a PSK of length 20. Not sure on how they > handle it but my guess is >> they just take the PSK the user configures, add the > string >> "01234567890123456789" and take the first 20 > bytes of it. Easy way to hook you >> on their client while still keeping it simply to > develop. >> >> And I'm not sure if the user !@#$% is the one the > GW admin configured on it or >> if it's the way they handle it but whatever else I > configure, the GW just >> don't respond anything back to me. > > Thanks! I put a note of this in docs/lucent-client.txt, and > it will end up > in the new wiki once we have it online. > >>> Looks like a resend, you can ignore it. >> Strangely, I *always* do receive the duplicate packet > warning. Another >> interesting thing is Lucent's VPN client > doesn't exchange any CFG at all... >> I'm wondering now if I need it indeed. The server > sends it to me but seems >> like LSW only configures the local IP address based on > it. I supossed it was >> going to be able to configure something else, such as > DNS or things like that. > > Libreswan does support DNS/WINS via XAUTH/ModeConfig. Though > as a client, we > might be ignoring it, since we have no structured way of > modifying resolv.conf > in any modern way (eg dbus/networkmanager). I believe we > might only pass it > as env variables to the updown script. > >> The LVC do more things with no CFG at all, configures > the DNS and WINS servers >> for instance, something I'll need to do manually > via a script (or can it be >> made automatically somehow by LSW?) > > You can copy the stock _updown script and add resolv.conf > rewriting to it, > and configure the new script using leftupdown= > >>>> and this one from pluto's debug: >>>> 3) "Intranet" #1: XAUTH: > Unsupported attribute: INTERNAL_ADDRESS_EXPIRY >>> You can also ignore this. Libreswan does not > support INTERNAL_ADDRESS_EXPIRY, >>> so it won't drop the IP address or ask for a new > one. >> Same for "ignoring informational payload, type > IPSEC_RESPONDER_LIFETIME" >> above? > > Yes. the remote is telling us how long they will keep the > SA around. Libreswan > does not really care what the remote does. If the remote > wants to rekey, it > will and can do it anytime. We do enforce our own SA life > similarly. > > Paul libreswan-5.2/contrib/lucent/UDP501encap.c000066400000000000000000000176531475767661000203700ustar00rootroot00000000000000 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-5.2/contrib/munin/000077500000000000000000000000001475767661000161575ustar00rootroot00000000000000libreswan-5.2/contrib/munin/README000066400000000000000000000001571475767661000170420ustar00rootroot00000000000000 this is a libreswan plugin for munin. See: http://munin-monitoring.org/ It requires libreswan 3.20 or later libreswan-5.2/contrib/munin/libreswan000077500000000000000000000175671475767661000201130ustar00rootroot00000000000000#!/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-5.2/contrib/portexcludes/000077500000000000000000000000001475767661000175525ustar00rootroot00000000000000libreswan-5.2/contrib/portexcludes/Makefile000066400000000000000000000014031475767661000212100ustar00rootroot00000000000000# Makefile for miscellaneous programs # Copyright (C) 2018 Paul Wouters # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. PROGRAM=portexcludes ifdef top_srcdir include $(top_srcdir)/mk/program.mk else include ../../mk/program.mk endif programs: ${PROGRAM} libreswan-5.2/contrib/portexcludes/portexcludes.8.xml000066400000000000000000000073211475767661000231660ustar00rootroot00000000000000 ipsec portexcludes 8 11 Feb 2018 libreswan Executable programs ipsec-portexcludes insert and delete port exclusion policies into the kernel SPD ipsec portexcludes DESCRIPTION ipsec portexcludes manages the exclusion list for port excludes in portexcludes.conf (found in the policies directory). It is usually run via the system service startup job. An administrator can run it manually as well. The portexcludes command deletes all passthrough conns that have a name that matches portexcludes-* before re-adding the rules read from its configuration file. The option only removes the active passthrough connections providing a port hole. The shows the translation of the rules defined in the portexcludes.conf file into whack commands. FILE FORMAT The portexcludes.conf file takes the following format. Each non-empty line and line that does not start with a # symbol is read and parsed into five fields separated by whitespace: direction protocol source dest priority. If a rule is not limited by source or destination being ipv4 or ipv6 specific, the rule will be applied for both ipv4 and ipv6. direction of the rule determines whether the rule is an inbound ("in") rule, an outbound ("out") rule, or "both". protocol specifies the protocol either by name (eg "tcp" or "udp") or by number (eg 6 or 17) source and destination specify a source or destination, specified by IPs in CIDR format, optionally followed by @port. The special values "any", "any4" and "any6" are recognised. priority is the priority of the SPD policy. This can be used to tune it to override some but not all defined connections. For example it can be used to override Opportunistic connections but not static tunnels. A priority smaller than 1024 would override every connection that does not manually set its own priority to a lower value. FILES /etc/ipsec.d/policies/portexcludes.conf SEE ALSO ipsec(8) HISTORY Written for the Libreswan Project <https://libreswan.org/> by Paul Wouters. AUTHOR Paul Wouters libreswan-5.2/contrib/portexcludes/portexcludes.in000066400000000000000000000177101475767661000226310ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- mode: python; -*- """Insert/remove port exclude overrides. # OE's IPsec SA's are always setup as full host-to-host covering all protoports # This file specifies higher priority (lower number) rules to define exceptions # Exceptions will prevent ACQUIREs, but if gw responded to OE, tunnel will be # up but exceptions will take priority and thus 'leak' in the clear. # NONE of these exceptions will overrule a statically configured tunnel, unless # a priority of <= XXX is specified # direction (in/out/both) | protocol | source IP@port range | # dest IP@port range | prio # allow incoming port 22 cleartext # direction Protocol Source Dest Prio #in tcp any 22 1023 # allow incoming DNS over udp and tcp in the clear #in tcp any 53 1023 #in udp any 53 1023 # allow in/out traffic to port 22 in cleartext #both tcp any 22 1023 # Allow incoming port 443 unencrypted from 10/8 #in tcp 10.0.0.0/8 443 1023 # Allow syslog to/from all nodes in 10/8 #both udp 10.0.0.0/8@514 10.0.0.0/8@514 1023 """ import os import subprocess import sys import time PORTFILE = "@@IPSEC_CONFDDIR@@/policies/portexcludes.conf" VERBOSE = False INWHACK = ("ipsec whack --name portexclude-DIRECTION-FAMILY-LINENR " "--ipv4 --priority PRIORITY --pass --host 127.0.0.1 " "--client DESTNET --clientprotoport PROTO/DESTPORT " "--to --host 0.0.0.0 --client SOURCENET " "--clientprotoport PROTO/SOURCEPORT --route") OUTWHACK = ("ipsec whack --name portexclude-DIRECTION-FAMILY-LINENR " "--ipv4 --priority PRIORITY --pass --host 127.0.0.1 " "--client SOURCENET --clientprotoport PROTO/SOURCEPORT " "--to --host 0.0.0.0 --client DESTNET " "--clientprotoport PROTO/DESTPORT --route") def clear_portrules(): """Clear all existing rules.""" try: ret = subprocess.check_output("ipsec status", shell=True, stderr=subprocess.STDOUT, encoding='utf-8', errors='ignore') except subprocess.CalledProcessError as error: print(error.output.strip()) return for line in ret.splitlines(): if "policy: AUTH_NEVER+TUNNEL+PASS+NEVER_NEGOTIATE" in line: conn = line.split()[1][:-1] if "portexclude" not in conn: continue whackcmd = f"ipsec whack --delete --name {conn}" if VERBOSE: print(whackcmd) try: subprocess.check_output(whackcmd, shell=True, stderr=subprocess.STDOUT, encoding='utf-8', errors='ignore') except subprocess.CalledProcessError as error: print(error.output.strip()) def main(): """Big Main Program.""" # pylint: disable=too-many-branches if not os.path.isfile("@@RUNDIR@@/pluto.pid"): sys.exit("libreswan service is not running") try: with open(PORTFILE, 'r', encoding='utf-8', errors='ignore') as fhn: lines = fhn.readlines() except FileNotFoundError: sys.exit() # Nothing to do except OSError: sys.exit(f"failed to open {PORTFILE}") clear = False if "-v" in sys.argv or "--verbose" in sys.argv: global VERBOSE # pylint: disable=global-statement VERBOSE = True if "-c" in sys.argv or "--clear" in sys.argv: clear = True if "-w" in sys.argv or "--wait" in sys.argv: time.sleep(5) clear_portrules() if clear: sys.exit() linenr = 0 for line in lines: linenr = linenr + 1 line = line.strip() if not line or line.startswith("#"): continue try: direction, proto, source, dest, prio = line.split() except ValueError: print(f"# skipped broken line {linenr}") continue if direction in ("in", "out"): dorules(linenr, direction, proto, source, dest, prio) else: dorules(linenr, "in", proto, source, dest, prio) # skip symmetric rules which don't need reverse rule if source != dest: dorules(linenr, "out", proto, source, dest, prio) def dorules(linenr, direction, proto, source, dest, prio): """Add single config line rule. Check if we need to expand a rule to ipv4 and ipv6. This happens when network is specified as "any" or when only specifying a port number. """ # pylint: disable=too-many-arguments # pylint: disable=too-many-branches if "any" in source and "any" in dest: print(f"Ignored rule on line {linenr} - any* to any* would cover " f"ALL traffic") return if ( # pylint: disable=too-many-boolean-expressions ("any6" in source and "." in dest) or ("any4" in source and ":" in dest) or ("." in source and ":" in dest) or (":" in source and "." in dest) ): print(f"Ignored rule on line {linenr} - cannot mix ipv4 and ipv6") return if source == "any6": source = "::/0" if source == "any4": source = "0.0.0.0/0" if dest == "any6": dest = "::/0" if dest == "any4": dest = "0.0.0.0/0" if source == "any" or source.isdigit(): if "." in dest: dorule(linenr, direction, proto, "0.0.0.0/0", dest, prio, "ipv4") elif ":" in dest: dorule(linenr, direction, proto, "::/0", dest, prio, "ipv6") else: dorule(linenr, direction, proto, "0.0.0.0/0", dest, prio, "ipv4") dorule(linenr, direction, proto, "::/0", dest, prio, "ipv6") elif dest == "any" or dest.isdigit(): if "." in source: dorule(linenr, direction, proto, source, dest, prio, "ipv4") elif ":" in source: dorule(linenr, direction, proto, source, "::/0", prio, "ipv6") else: dorule(linenr, direction, proto, source, dest, prio, "ipv4") dorule(linenr, direction, proto, source, "::/0", prio, "ipv6") elif "." in source: dorule(linenr, direction, proto, source, dest, prio, "ipv4") elif ":" in source: dorule(linenr, direction, proto, source, dest, prio, "ipv6") def addr_to_net_port(addr, fam): """Split address to net,port.""" if "@" in addr: net, port = addr.split("@", 1) elif addr.isdigit(): port = addr if fam == "ipv4": net = "0.0.0.0/0" else: net = "::/0" else: net = addr port = "0" return net, port def dorule(linenr, direction, proto, source, dest, prio, fam): """Add single whack rule.""" # pylint: disable=too-many-arguments if direction == "in": whackcmd = INWHACK else: whackcmd = OUTWHACK whackcmd = whackcmd.replace("PRIORITY", prio) whackcmd = whackcmd.replace("PROTO", proto) whackcmd = whackcmd.replace("DIRECTION", direction) whackcmd = whackcmd.replace("FAMILY", fam) whackcmd = whackcmd.replace("LINENR", str(linenr)) if fam == "ipv6": whackcmd = whackcmd.replace("--ipv4", "--ipv6") whackcmd = whackcmd.replace("host 127.0.0.1", "host ::1") whackcmd = whackcmd.replace("host 0.0.0.0", "host ::0") sourcenet, sourceport = addr_to_net_port(source, fam) destnet, destport = addr_to_net_port(dest, fam) whackcmd = whackcmd.replace("SOURCENET", sourcenet) whackcmd = whackcmd.replace("SOURCEPORT", sourceport) whackcmd = whackcmd.replace("DESTNET", destnet) whackcmd = whackcmd.replace("DESTPORT", destport) if VERBOSE: print(whackcmd) try: ret = subprocess.check_output(whackcmd, shell=True, stderr=subprocess.STDOUT, encoding='utf-8', errors='ignore') if VERBOSE: print(ret.strip()) except subprocess.CalledProcessError as error: print(error.output.strip()) if __name__ == "__main__": main() libreswan-5.2/contrib/python-swan/000077500000000000000000000000001475767661000173205ustar00rootroot00000000000000libreswan-5.2/contrib/python-swan/is_encrypted.py000066400000000000000000000034251475767661000223660ustar00rootroot00000000000000#!/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-5.2/contrib/python-swan/swan/000077500000000000000000000000001475767661000202705ustar00rootroot00000000000000libreswan-5.2/contrib/python-swan/swan/__init__.py000066400000000000000000000072051475767661000224050ustar00rootroot00000000000000# -*- 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-5.2/contrib/updown-example/000077500000000000000000000000001475767661000177765ustar00rootroot00000000000000libreswan-5.2/contrib/updown-example/example-terminate.py000077500000000000000000000035671475767661000240070ustar00rootroot00000000000000#!/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-5.2/docs/000077500000000000000000000000001475767661000143215ustar00rootroot00000000000000libreswan-5.2/docs/CHANGES.freeswan.pluto000066400000000000000000001171261475767661000202770ustar00rootroot00000000000000Changes 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-5.2/docs/CHANGES.openswan000066400000000000000000002177011475767661000171550ustar00rootroot00000000000000 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-5.2/docs/CREDITS.freeswan000066400000000000000000000056111475767661000171550ustar00rootroot00000000000000We 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-5.2/docs/CREDITS.openswan000066400000000000000000000046021475767661000171740ustar00rootroot00000000000000The 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-5.2/docs/GSoC.md000066400000000000000000000165061475767661000154460ustar00rootroot00000000000000# Google Summer of Code ## Previous Student projects See [Student projects](https://libreswan.org/wiki/Student_projects for completed student projects (sponsored by GSoC and others). ## Proposal submissions Submissions must comply to all GSoC rules. We strongly urge any interested students to read up on the previous student projects and the below project ideas. It is not required to be one of these ideas - we welcome new ideas too! Submissions that tend to be accepted and successful are those that show from the start that the student is putting in the time to understand the concepts. You don't have to be an expert already, and you can contact us at `gsoc at libreswan dot org` for questions. Mentors like to see students that have put in some work to understand and try things. It is the only reliable metric we have for new people to indicate how serious they are to take on a project for the summer. If implementing an RFC, read the RFC and ask us any questions you have. Have a look at the code base structure in general, look at our testing/ directory. If you don't have VPN/IPsec experience, we are happy to give you a client configuration to gain experience using libreswan to a real VPN server. ## Google Summer of Code Ideas While IKE and IPsec have been around for 20 years, like SSL/TLS, the protocols are still evolving and getting new features to deal with an ever changing world. The Libreswan Project's core developers have come up with a list of projects that they believe would be interesting for students to work on. The mentors have a personal interest in these projects as well. If any of these projects look interesting to you, feel free to contact the developers either on the (developer mailing list)(https://lists.libreswan.org/mailman/listinfo/swan-dev) the `#libreswan` channel on `LiberaChat` IRC. You can also email `gsoc at libreswan org` with any questions you have or if you would like to introduce yourself. A quick overview and history of The Libreswan Project was presented by Paul Wouters as part of the Opportunistic IPsec presentation at the [2016 Linux Security Summit](http://events.linuxfoundation.org/events/linux-security-summit) and there is a [video recording](https://www.youtube.com/watch?v=Me_rl6N1m7c&list=PLbzoR-pLrL6pq6qCHZUuhbXsTsyz1N1c0&index=17) of the presentation. ## Improvements ### Implement CHAP authentication within EAP Libreswan currently has support for [EAP](https://www.rfc-editor.org/rfc/rfc3748.html) authentication using [EAP-TLS](https://www.rfc-editor.org/rfc/rfc5216). This project would extend Libreswan to also support EAP authentication to use CHAP. #### Expected outcomes A testcase demonstrating Libreswan authenticating a peer using a [FreeRADIUS](https://www.freeradius.org/) server for CHAP authentication. #### Skills Required/prefered C programming.\ Writing documentation and test cases, Internet Protocols #### Possible Mentors TBD #### Expected size 175 Hours #### Dificulty Intermediate. ### Dynamically configure IKE algorithms based on cryptographic policy Several things determine which cryptographic algorithms Libreswan can use when establishing an IKE SA: - the way libreswan was built - the systems current crypographic policy - the default crypto-suite - the IKE SA's configuration The goal of this project is to modify Libreswan so that dynamically configures its default and acceptable cryptographic algorithms based on what is permitted by the systems cryptographic policy. #### Expected outcomes Test case demonstrating Libreswan accepting / rejecting IKE algorithms based on the system's crypto policy. #### Skills Required/prefered C programming\ Writing documentation and test cases, Internet Protocols #### Possible Mentors TBD #### Expected size 175 Hours #### Dificulty Intermediate. ## RFCs (Requests for Comment), including drafts ### [(draft)](https://datatracker.ietf.org/doc/draft-ietf-ipsecme-g-ikev2/) Group Key Management using IKEv2 #### Expected outcomes #### Skills Required/prefered C programming\ Writing documentation and test cases, Internet Protocols #### Possible Mentors TBD #### Expected size (90, 175 or 350 hour) #### Dificulty An easy, intermediate or hard/difficult rating of each project. ### [(draft)](https://datatracker.ietf.org/doc/draft-ietf-ipsecme-ikev2-qr-alt/) Mixing Preshared Keys in the IKE_INTERMEDIATE and in the CREATE_CHILD_SA Exchanges of IKEv2 for Post-quantum Security more detailed description of the project (2-5 sentences) #### Expected outcomes #### Skills Required/prefered C programming\ Writing documentation and test cases, Internet Protocols #### Possible Mentors TBD #### Expected size (90, 175 or 350 hour) #### Dificulty An easy, intermediate or hard/difficult rating of each project. ### [RFC 9611](https://www.rfc-editor.org/rfc/rfc9593.html): Support for Per-Resource Child Security Associations (SAs) more detailed description of the project (2-5 sentences) #### Expected outcomes #### Skills Required/prefered C programming\ Writing documentation and test cases, Internet Protocols #### Possible Mentors TBD #### Expected size (90, 175 or 350 hour) #### Dificulty An easy, intermediate or hard/difficult rating of each project. ### [RFC 9593](https://www.rfc-editor.org/rfc/rfc9593.html): Announcing Supported Authentication Methods ... more detailed description of the project (2-5 sentences) #### Expected outcomes #### Skills Required/prefered C programming. Writing documentation and test cases, Internet Protocols #### Possible Mentors TBD #### Expected size (90, 175 or 350 hour) #### Dificulty An easy, intermediate or hard/difficult rating of each project. ### [RFC 9464](https://www.rfc-editor.org/rfc/rfc9464.html): Configuration for Encrypted DNS; huh? more detailed description of the project (2-5 sentences) #### Expected outcomes #### Skills Required/prefered C programming. Writing documentation and test cases, Internet Protocols #### Possible Mentors TBD #### Expected size (90, 175 or 350 hour) #### Dificulty An easy, intermediate or hard/difficult rating of each project. ### [RFC 9370](https://www.rfc-editor.org/rfc/rfc9370.html): Intermediate Exchange in the IKEv2 Protocol Ueno has a pull-request for some of the work; but not IKE_FOLLOWUP_KE more detailed description of the project (2-5 sentences) #### Expected outcomes #### Skills Required/prefered C programming\ Writing documentation and test cases, Internet Protocols #### Possible Mentors TBD #### Expected size (90, 175 or 350 hour) #### Dificulty An easy, intermediate or hard/difficult rating of each project. ### [RFC 8598](https://www.rfc-editor.org/rfc/rfc8598.html): Split DNS Configuration more detailed description of the project (2-5 sentences) #### Expected outcomes #### Skills Required/prefered C programming\ Writing documentation and test cases, Internet Protocols #### Possible Mentors TBD #### Expected size (90, 175 or 350 hour) #### Dificulty An easy, intermediate or hard/difficult rating of each project. ### [RFC 7670](https://www.rfc-editor.org/rfc/rfc7670.html): Generic Raw public key support more detailed description of the project (2-5 sentences) #### Expected outcomes #### Skills Required/prefered C programming\ Writing documentation and test cases, Internet Protocols #### Possible Mentors TBD #### Expected size (90, 175 or 350 hour) #### Dificulty An easy, intermediate or hard/difficult rating of each project. libreswan-5.2/docs/PlutoFlow.png000066400000000000000000001064051475767661000167700ustar00rootroot00000000000000PNG  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-5.2/docs/PlutoFlow.svg000066400000000000000000000636551475767661000170140ustar00rootroot00000000000000 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-5.2/docs/ProgrammingConventions.txt000066400000000000000000000124631475767661000216000ustar00rootroot00000000000000Notes 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-5.2/docs/README.IANA-PEN000066400000000000000000000003271475767661000163320ustar00rootroot00000000000000 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-5.2/docs/README.XAUTH000066400000000000000000000053321475767661000160740ustar00rootroot00000000000000 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-5.2/docs/README.labeledipsec000066400000000000000000000002221475767661000176100ustar00rootroot00000000000000Be 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-5.2/docs/README.rfcs000066400000000000000000000157341475767661000161470ustar00rootroot00000000000000 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-5.2/docs/copyright-sh000066400000000000000000000011641475767661000166660ustar00rootroot00000000000000#!/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-5.2/docs/diagrams/000077500000000000000000000000001475767661000161105ustar00rootroot00000000000000libreswan-5.2/docs/diagrams/NETKEY.png000066400000000000000000000307771475767661000176330ustar00rootroot00000000000000PNG  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-5.2/docs/examples/ipv6.conf000066400000000000000000000016261475767661000176770ustar00rootroot00000000000000# 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-5.2/docs/examples/l2tp-cert.conf000066400000000000000000000030551475767661000206250ustar00rootroot00000000000000conn 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-5.2/docs/examples/l2tp-psk.conf000066400000000000000000000032051475767661000204620ustar00rootroot00000000000000conn 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-5.2/docs/examples/linux-linux.conf000066400000000000000000000022051475767661000213010ustar00rootroot00000000000000conn 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-5.2/docs/examples/oe-authnull.conf000066400000000000000000000024571475767661000212530ustar00rootroot00000000000000# /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-5.2/docs/examples/oe-dnssec-client.conf000066400000000000000000000010411475767661000221360ustar00rootroot00000000000000 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-5.2/docs/examples/oe-dnssec-server.conf000066400000000000000000000010121475767661000221640ustar00rootroot00000000000000 # 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-5.2/docs/examples/oe-exclude-dns.conf000066400000000000000000000003531475767661000216230ustar00rootroot00000000000000conn 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-5.2/docs/examples/oe-letsencrypt-README.txt000066400000000000000000000024301475767661000226070ustar00rootroot00000000000000 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-5.2/docs/examples/oe-letsencrypt-client.conf000066400000000000000000000007051475767661000232410ustar00rootroot00000000000000conn 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-5.2/docs/examples/oe-letsencrypt-server.conf000066400000000000000000000007321475767661000232710ustar00rootroot00000000000000conn 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-5.2/docs/examples/oe-upgrade-authnull.conf000066400000000000000000000027221475767661000226730ustar00rootroot00000000000000# /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-5.2/docs/examples/sysctl.conf000066400000000000000000000034461475767661000203360ustar00rootroot00000000000000 # 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-5.2/docs/examples/xauth.conf000066400000000000000000000011351475767661000201370ustar00rootroot00000000000000conn 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-5.2/docs/l2tp-overhead.txt000066400000000000000000000001351475767661000175350ustar00rootroot00000000000000IP 20 UDP 14 ESP spi 4 iv 8 auth 12 pad 8 total 36 UDP 14 L2TP 8 PPP 2 libreswan-5.2/docs/nss-howto.txt000066400000000000000000000077231475767661000170340ustar00rootroot00000000000000######################################################################### # 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-5.2/docs/opportunistic-v1.historic/000077500000000000000000000000001475767661000214125ustar00rootroot00000000000000libreswan-5.2/docs/opportunistic-v1.historic/opportunism-spec.txt000066400000000000000000001407531475767661000255140ustar00rootroot00000000000000 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-5.2/docs/opportunistic-v1.historic/opportunism.nr000066400000000000000000001304361475767661000243610ustar00rootroot00000000000000.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-5.2/docs/pluto-internals.txt000066400000000000000000000347461475767661000202400ustar00rootroot00000000000000Routing 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-5.2/docs/testing/000077500000000000000000000000001475767661000157765ustar00rootroot00000000000000libreswan-5.2/docs/testing/testnet.fig000066400000000000000000000120121475767661000201470ustar00rootroot00000000000000#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-5.2/docs/testing/testnet.png000066400000000000000000000275261475767661000202060ustar00rootroot00000000000000PNG  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-5.2/external/000077500000000000000000000000001475767661000152135ustar00rootroot00000000000000libreswan-5.2/external/include/000077500000000000000000000000001475767661000166365ustar00rootroot00000000000000libreswan-5.2/external/include/pfkeyv2/000077500000000000000000000000001475767661000202245ustar00rootroot00000000000000libreswan-5.2/external/include/pfkeyv2/README.md000066400000000000000000000016251475767661000215070ustar00rootroot00000000000000This 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-5.2/external/include/pfkeyv2/darwin-xnu.h000066400000000000000000000420571475767661000225010ustar00rootroot00000000000000/* * 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-5.2/external/include/pfkeyv2/freebsd.h000066400000000000000000000351561475767661000220210ustar00rootroot00000000000000/* $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_CHACHA20POLY1305 14 #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_CHACHA20POLY1305 15 #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 member 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-5.2/external/include/pfkeyv2/linux.h000066400000000000000000000246141475767661000215430ustar00rootroot00000000000000/* 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_SM3_256HMAC 10 #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_X_EALG_SM4CBC 24 #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-5.2/external/include/pfkeyv2/netbsd.h000066400000000000000000000406231475767661000216610ustar00rootroot00000000000000/* $NetBSD: pfkeyv2.h,v 1.34.2.1 2023/01/04 12:17:08 martin 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_flags; #define IPSEC_POLICY_FLAG_ORIGIN_KERNEL 0x80 /* policy is generated by kernel */ #define sadb_x_policy_reserved sadb_x_policy_flags 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 /* sequential 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-5.2/external/include/pfkeyv2/openbsd.h000066400000000000000000000360561475767661000220410ustar00rootroot00000000000000/* $OpenBSD: pfkeyv2.h,v 1.94 2023/08/07 03:35:06 dlg 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; }; struct sadb_x_iface { uint16_t sadb_x_iface_len; uint16_t sadb_x_iface_exttype; uint32_t sadb_x_iface_unit; uint8_t sadb_x_iface_direction; uint8_t sadb_x_iface_reserved[7]; }; #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_X_EXT_IFACE 40 #define SADB_EXT_MAX 40 /* 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_dosend(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 export_iface(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 *); void import_iface(struct tdb *, struct sadb_x_iface *); 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-5.2/external/include/pfkeyv2/rfc2367.h000066400000000000000000000122151475767661000214720ustar00rootroot00000000000000/* 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-5.2/include/000077500000000000000000000000001475767661000150145ustar00rootroot00000000000000libreswan-5.2/include/addr_lookup.h000066400000000000000000000022771475767661000175000ustar00rootroot00000000000000/* 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-5.2/include/alg_byname.h000066400000000000000000000027251475767661000172710ustar00rootroot00000000000000/* * 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-5.2/include/asn1.h000066400000000000000000000061401475767661000160300ustar00rootroot00000000000000/* 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-5.2/include/authby.h000066400000000000000000000042311475767661000164610ustar00rootroot00000000000000/* 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-5.2/include/binary-iec-60027-2.h000066400000000000000000000015141475767661000200230ustar00rootroot00000000000000/* 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-5.2/include/binaryscale-iec-60027-2.h000066400000000000000000000015761475767661000210430ustar00rootroot00000000000000/* 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 "scale.h" #include "shunk.h" const struct scale *ttobinaryscale(shunk_t s); const struct scale *ttobinarybytesscale(shunk_t s); #endif libreswan-5.2/include/certs.h000066400000000000000000000047041475767661000163120ustar00rootroot00000000000000/* 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-5.2/include/chunk.h000066400000000000000000000077221475767661000163050ustar00rootroot00000000000000/* * 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" /* * 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); #define HUNK_AS_CHUNK(HUNK) \ ({ \ typeof(HUNK) *h_ = &(HUNK); \ chunk2(h_->ptr, h_->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 concatenation 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_bytes(chunk_t *dst, const void *src, size_t sizeof_src, const char *name); #define replace_chunk(DST, SRC, NAME) \ ({ \ typeof (SRC) src_ = SRC; /* evaluate once */ \ replace_chunk_bytes(DST, src_.ptr, src_.len, NAME); \ }) /* * 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-5.2/include/ckaid.h000066400000000000000000000040251475767661000162410ustar00rootroot00000000000000/* * 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-5.2/include/connection_owner.h000066400000000000000000000030461475767661000205410ustar00rootroot00000000000000/* connection owner, for libreswan * * Copyright (C) 2023 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT 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 CONNECTION_OWNER_H #define CONNECTION_OWNER_H /* * Number of ways a connection can be owned by a state. */ enum connection_owner { #define CONNECTION_OWNER_FLOOR IKE_SA_OWNER_FLOOR /* * The current SA, IKE or Child, that owns the kernel policy. * * For instance, during an on-demand IKE_SA_INIT exchange the * ROUTING_SA starts with the IKE_SA. But then, at the start * of IKE_AUTH, ownership transfers to the IKE_SA's first * Child SA. */ ROUTING_SA, #define IKE_SA_OWNER_FLOOR NEGOTIATING_IKE_SA NEGOTIATING_IKE_SA, ESTABLISHED_IKE_SA, #define IKE_SA_OWNER_ROOF (ESTABLISHED_IKE_SA+1) #define CHILD_SA_OWNER_FLOOR NEGOTIATING_CHILD_SA NEGOTIATING_CHILD_SA, ESTABLISHED_CHILD_SA, #define CHILD_SA_OWNER_ROOF (ESTABLISHED_CHILD_SA+1) #define CONNECTION_OWNER_ROOF CHILD_SA_OWNER_ROOF }; extern const struct enum_names connection_owner_names; extern const struct enum_names connection_owner_stories; #endif libreswan-5.2/include/constants.h000066400000000000000000000256511475767661000172120ustar00rootroot00000000000000/* * * 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" #include "names.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 */ /* octet_t / BITS_IN_OCTET anyone? */ #define BITS_IN_BYTE 8 #define BYTES_FOR_BITS(b) (((b) + BITS_IN_BYTE - 1) / BITS_IN_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)); \ }) /* * 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 */ err_t ttobool(const char *t, bool *b); /* string -> bool */ /* 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 true when known, and sets enum_buf to a * non-NULL string. * * 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. * * Caller-allocated buffer * * 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. * * The .name field points either at buf[] or some internal string. It * is never NULL. DANGER: enum_buf can't be returned as that moves * the struct invalidating the internal pointer. */ #define enum_buf name_buf #define esb_buf name_buf /* XXX: TBD */ typedef const struct enum_names enum_names; bool enum_long(const struct enum_names *en, unsigned long val, enum_buf *b); const char *str_enum_long(const struct enum_names *en, unsigned long val, enum_buf *b); size_t jam_enum_long(struct jambuf *, const struct enum_names *en, unsigned long val); #define jam_enum jam_enum_long /* legacy */ #define str_enum str_enum_long /* legacy */ #define enum_name enum_long /* legacy */ bool enum_short(const struct enum_names *en, unsigned long val, enum_buf *b); const char *str_enum_short(const struct enum_names *en, unsigned long val, enum_buf *b); size_t jam_enum_short(struct jambuf *, const struct enum_names *en, unsigned long val); #define enum_name_short enum_short /* drop prefix + transform [_A-Z]->[-a-z] */ size_t jam_enum_human(struct jambuf *, enum_names *en, unsigned long val); /* * 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_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; bool enum_enum_name(enum_enum_names *e, unsigned long table, unsigned long val, enum_buf *buf); 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 #include "ietf_constants.h" #include "pluto_constants.h" #include "names_constant.h" #endif /* _CONSTANTS_H_ */ libreswan-5.2/include/crypt_cipher.h000066400000000000000000000052631475767661000176660ustar00rootroot00000000000000/* Cipher algorithms, for libreswan * * Copyright (C) 2024 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT 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_CIPHER_H #define CRYPT_CIPHER_H #include #include "chunk.h" #include "shunk.h" struct encrypt_desc; struct logger; struct cipher_context; struct crypt_mac; enum cipher_op { DECRYPT = false, ENCRYPT = true, }; #define str_cipher_op(OP) \ ({ \ enum cipher_op op_ = OP; \ (op_ == ENCRYPT ? "encrypt" : \ op_ == DECRYPT ? "decrypt" : \ "???"); \ }) /* * Normally USE_IV:DECRYPT and FILL_IV:ENCRIPT each come as a pair. * The exception is testing where encryption can't generate its own * IV. */ enum cipher_iv_source { USE_WIRE_IV = 1, FILL_WIRE_IV, USE_IKEv1_IV, }; #define str_cipher_iv_source(IV_SOURCE) \ ({ \ enum cipher_iv_source iv_source_ = IV_SOURCE; \ (iv_source_ == USE_WIRE_IV ? "use wire IV" : \ iv_source_ == FILL_WIRE_IV ? "fill wire IV" : \ iv_source_ == USE_IKEv1_IV ? "use IKEv1 IV" : \ "???"); \ }) /* * Separate cipher and integrity. */ void cipher_ikev1(const struct encrypt_desc *cipher, enum cipher_op op, chunk_t text, struct crypt_mac *iv, PK11SymKey *key, struct logger *logger); bool cipher_aead(const struct encrypt_desc *cipher, enum cipher_op op, enum cipher_iv_source iv_source, shunk_t salt, chunk_t wire_iv, shunk_t aad, chunk_t text_and_tag, size_t text_size, size_t tag_size, PK11SymKey *key, struct logger *logger); struct cipher_context *cipher_context_create(const struct encrypt_desc *cipher, enum cipher_op op, enum cipher_iv_source iv_source, PK11SymKey *key, shunk_t salt, struct logger *logger); void cipher_context_destroy(struct cipher_context **, struct logger *logger); void cipher_context_op_normal(const struct cipher_context *, chunk_t wire_iv, chunk_t text, struct crypt_mac *ikev1_iv, struct logger *logger); bool cipher_context_op_aead(const struct cipher_context *, chunk_t wire_iv, shunk_t aad, chunk_t text_and_tag, size_t text_size, size_t tag_size, struct logger *logger); #endif libreswan-5.2/include/crypt_hash.h000066400000000000000000000040771475767661000173410ustar00rootroot00000000000000/* 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; struct logger; /* * 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-5.2/include/crypt_mac.h000066400000000000000000000025241475767661000171510ustar00rootroot00000000000000/* 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-5.2/include/crypt_prf.h000066400000000000000000000064551475767661000172070ustar00rootroot00000000000000/* 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-5.2/include/crypt_symkey.h000066400000000000000000000140571475767661000177360ustar00rootroot00000000000000/* * 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; struct logger; void init_crypt_symkey(struct logger *logger); /* * Log some information on a SYMKEY. * * The format is : -key@... */ void LDBG_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. */ PK11SymKey *symkey_addref_where(struct logger *logger, const char *name, PK11SymKey *key, where_t where); void symkey_delref_where(struct logger *logger, const char *name, PK11SymKey **key, where_t where); #define symkey_addref(LOGGER, NAME, KEY) symkey_addref_where(LOGGER, NAME, KEY, HERE) #define symkey_delref(LOGGER, NAME, KEY) symkey_delref_where(LOGGER, NAME, KEY, HERE) /* * 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, struct logger *logger, where_t where); PK11SymKey *cipher_symkey(const char *name, const struct encrypt_desc *encrypt, unsigned size, struct logger *logger, where_t where); /* * 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-5.2/include/deltatime.h000066400000000000000000000104661475767661000171440ustar00rootroot00000000000000/* 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; enum 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; bool is_set; } deltatime_t; extern const deltatime_t deltatime_zero; extern const deltatime_t one_day; extern const deltatime_t one_hour; extern const deltatime_t one_minute; extern const deltatime_t one_second; #define DELTATIME_INIT(S) { .dt = { .tv_sec = (S), }, .is_set = true, } deltatime_t deltatime(time_t secs); deltatime_t deltatime_from_milliseconds(intmax_t milliseconds); deltatime_t deltatime_from_microseconds(intmax_t microseconds); /* 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) | min(a, b) */ deltatime_t deltatime_max(deltatime_t a, deltatime_t b); deltatime_t deltatime_min(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); /* * Note: seconds_from*() returns INTMAX_T and not TIME_T so that * functions match the format %jd (there is no TIME_T format modifier * and TIME_T's size changes across platforms). */ intmax_t microseconds_from_deltatime(deltatime_t d); intmax_t milliseconds_from_deltatime(deltatime_t d); intmax_t seconds_from_deltatime(deltatime_t d); #define deltasecs seconds_from_deltatime deltatime_t deltatime_scale(deltatime_t d, int num, int denom); /* D*NUM/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.1000000000")+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, enum timescale default_timescale); /* * Primitives used to implement times; try to avoid timeval * explicitly. * * Note: seconds_from*() returns INTMAX_T and not TIME_T so that * functions match the format %jd (there is no TIME_T format modifier * and TIME_T's size changes across platforms). */ struct timeval from_seconds(time_t seconds); struct timeval from_milliseconds(intmax_t milliseconds); struct timeval from_microseconds(intmax_t microseconds); intmax_t seconds_from(struct timeval); intmax_t milliseconds_from(struct timeval); intmax_t microseconds_from(struct timeval); /* for *time_cmp(): sign(l-r) */ int timeval_sub_sign(struct timeval l, struct timeval r); #endif libreswan-5.2/include/diag.h000066400000000000000000000024451475767661000160760ustar00rootroot00000000000000/* 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 *message, va_list ap) VPRINTF_LIKE(1) MUST_USE_RESULT; diag_t diag_jambuf(struct jambuf *buf); diag_t diag_diag(diag_t *diag, const char *message, ...) PRINTF_LIKE(2) MUST_USE_RESULT; const char *str_diag(diag_t diag); size_t jam_diag(struct jambuf *buf, diag_t diag); void pfree_diag(struct diag **diag); #endif libreswan-5.2/include/dnssec.h000066400000000000000000000021471475767661000164500ustar00rootroot00000000000000#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, const 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-5.2/include/encap_mode.h000066400000000000000000000021531475767661000172600ustar00rootroot00000000000000/* encap mode, 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. * */ #ifndef ENCAP_MODE_H #define ENCAP_MODE_H /* * Encapsulation mode. * * Contrary to the RFCs and ENCAPSULATION_MODE_*, the kernel only has * to handle two modes. Hence an ENUM that only defines those values. * * Except contrary to that, PF KEY v2 accepts the mode "any". */ enum encap_mode { ENCAP_MODE_UNSET, ENCAP_MODE_TRANSPORT = 2, /*>true */ ENCAP_MODE_TUNNEL, }; extern const struct enum_names encap_mode_names; extern const struct enum_names encap_mode_story; /* lower-case */ #endif libreswan-5.2/include/encap_proto.h000066400000000000000000000017261475767661000175040ustar00rootroot00000000000000/* encap proto, for libreswan * * Copyright (C) 2023 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT 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 ENCAP_PROTO_H #define ENCAP_PROTO_H /* * (outer) Encapsulation Protocol. * * There may also be an inner compression encapsulation. */ enum encap_proto { ENCAP_PROTO_UNSET = 0, ENCAP_PROTO_ESP, ENCAP_PROTO_AH, }; extern const struct enum_names encap_proto_names; extern const struct enum_names encap_proto_story; /* lower-case */ #endif libreswan-5.2/include/encap_type.h000066400000000000000000000022761475767661000173230ustar00rootroot00000000000000/* encap type, for libreswan * * Copyright (C) 2023 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT 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 ENCAP_TYPE_H #define ENCAP_TYPE_H /* * Encapsulation type. * * SHUNT_TYPEs are mapped onto the below before being passed to the * kernel. * * Linux OpenBSD Net/Free SHUNT * TRAP: ALLOW ACQUIRE IPSEC TRAP * IPSEC: ALLOW REQUIRE IPSEC IPSEC * PASS: ALLOW BYPASS NONE PASS * DROP: BLOCK DENY DISCARD DROP,REJECT,HOLD * invalid: NONE! */ enum encap_type { ENCAP_TYPE_TRAP = 1, ENCAP_TYPE_IPSEC, ENCAP_TYPE_PASS, ENCAP_TYPE_DROP, }; extern const struct enum_names encap_type_names; #endif libreswan-5.2/include/end.h000066400000000000000000000016011475767661000157310ustar00rootroot00000000000000/* information about connections between hosts and clients * * Copyright (C) 2024 Nupur Agrawal * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT 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 END_H #define END_H enum end { LEFT_END, RIGHT_END, }; #define END_ROOF 2 extern const struct enum_names end_names; /* LEFT_END RIGHT_END */ extern const struct enum_names end_stories; /* left right */ #endif libreswan-5.2/include/enum_names.h000066400000000000000000000032521475767661000173160ustar00rootroot00000000000000/* 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 */ }; /* arrays are null terminated */ struct enum_names_check { const char *name; const struct enum_names *enum_names; }; extern const struct enum_names_check enum_names_checklist[]; /* NULL terminated*/ struct enum_enum_names_check { const char *name; const struct enum_enum_names *enum_enum_names; }; extern const struct enum_enum_names_check enum_enum_names_checklist[]; /* NULL terminated*/ extern void check_enum_names(const struct enum_names_check *checklist); extern void check_enum_enum_names(const struct enum_enum_names_check *checklist); extern void init_enum_names(); #endif libreswan-5.2/include/err.h000066400000000000000000000025001475767661000157520ustar00rootroot00000000000000/* 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-5.2/include/fatal.h000066400000000000000000000035241475767661000162600ustar00rootroot00000000000000/* 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 FATAL_H #define FATAL_H #include "lswcdefs.h" #include "logjam.h" enum pluto_exit_code; struct logger; struct jambuf; struct logjam; /* * XXX: The message format is: * FATAL ERROR: * and not: * FATAL ERROR: */ void fatal(enum pluto_exit_code pluto_exit_code, const struct logger *logger, const char *message, ...) PRINTF_LIKE(3) NEVER_RETURNS; void fatal_errno(enum pluto_exit_code pluto_exit_code, const struct logger *logger, int error, const char *message, ...) PRINTF_LIKE(4) NEVER_RETURNS; void fatal_logjam_to_logger(struct logjam *buf) NEVER_RETURNS; #define LLOG_FATAL_JAMBUF(PEC, LOGGER, BUF) \ /* create the buffer */ \ for (struct logjam logjam_, *lbp_ = &logjam_; \ lbp_ != NULL; lbp_ = NULL) \ /* create the jambuf */ \ for (struct jambuf *BUF = \ jambuf_from_logjam(&logjam_, LOGGER, \ PEC, NULL, FATAL_STREAM); \ BUF != NULL; \ fatal_logjam_to_logger(&logjam_), BUF = NULL) #endif libreswan-5.2/include/fd.h000066400000000000000000000045131475767661000155610ustar00rootroot00000000000000/* 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-5.2/include/fips_mode.h000066400000000000000000000026121475767661000171330ustar00rootroot00000000000000/* 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 FIPS_MODE_H #define FIPS_MODE_H #include /* for bool */ struct logger; enum fips_mode { #define FIPS_MODE_UNSET 0 /* 0 is reserved; and not an enum */ #define FIPS_MODE_FLOOR FIPS_MODE_OFF FIPS_MODE_OFF = 1, FIPS_MODE_ON, #define FIPS_MODE_ROOF (FIPS_MODE_ON+1) }; extern const struct enum_names fips_mode_names; void set_fips_mode(enum fips_mode fips); enum fips_mode get_fips_mode(struct logger *logger); bool is_fips_mode(void); #endif libreswan-5.2/include/hunk.h000066400000000000000000000327721475767661000161450ustar00rootroot00000000000000/* 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*() functions ignore case! * * Just like the C NULL and empty("") strings, NULL and non-NULL but * EMPTY hunks are considered non-equal vis: * * NULL = {.ptr=NULL,.len=0); * EMPTY = {.ptr="",.len=0); * eq(NULL,NULL) -> TRUE * eq(NULL,EMPTY) -> FALSE * eq(EMPTY,NULL) -> FALSE * eq(EMPTY,EMPTY) -> TRUE */ int raw_cmp(const void *l_ptr, size_t l_len, const void *r_ptr, size_t r_len); #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); \ }) bool raw_eq(const void *l_ptr, size_t l_len, const void *r_ptr, size_t r_len); bool raw_caseeq(const void *l_ptr, size_t l_len, const void *r_ptr, size_t r_len); bool raw_heq(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 */ \ raw_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 */ \ raw_caseeq(l_.ptr, l_.len, r_.ptr, r_.len); \ }) #define hunk_heq(L, R) /* case and [-_] independent */ \ ({ \ const typeof(L) l_ = L; /* evaluate once */ \ const typeof(R) r_ = R; /* evaluate once */ \ raw_heq(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 */ \ raw_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 */ \ raw_caseeq(hunk_.ptr, hunk_.len, string_, \ string_ != NULL ? strlen(string_) : 0); \ }) #define hunk_strheq(HUNK, STRING) /* case and [-_] independent */ \ ({ \ const typeof(HUNK) hunk_ = HUNK; /* evaluate once */ \ const char *string_ = STRING; /* evaluate once */ \ raw_heq(hunk_.ptr, hunk_.len, string_, \ string_ != NULL ? strlen(string_) : 0); \ }) /* * Note: the starteq() functions return FALSE when either of the * parameters are NULL (which is inconsistent with the *eq() functions * above). * * The weak argument for this is that when *starteq() returns true, it * is safe to manipulate both pointers (and it means that *eat() * functions can be implemented using *starteq(). */ bool raw_starteq(const void *ptr, size_t len, const void *eat, size_t eat_len); #define hunk_starteq(HUNK, START) \ ({ \ const typeof(HUNK) hunk_ = HUNK; /* evaluate once */ \ const typeof(START) start_ = START; /* evaluate once */ \ raw_starteq(hunk_.ptr, hunk_.len, \ start_.ptr, start_.len); \ }) bool raw_casestarteq(const void *ptr, size_t len, const void *eat, size_t eat_len); #define hunk_casestarteq(HUNK, START) /* case independent */ \ ({ \ const typeof(HUNK) hunk_ = HUNK; /* evaluate once */ \ const typeof(START) start_ = START; /* evaluate once */ \ raw_casestarteq(hunk_.ptr, hunk_.len, \ start_.ptr, start_.len); \ }) #define hunk_strstarteq(HUNK, STRING) \ hunk_starteq(HUNK, shunk1(STRING)) #define hunk_strcasestarteq(HUNK, STRING) \ hunk_casestarteq(HUNK, shunk1(STRING)) #define hunk_strnlen(HUNK) \ ({ \ typeof(HUNK) hunk_ = HUNK; /* evaluate once */ \ strnlen((const char *)hunk_.ptr, hunk_.len); \ }) /* * hunk 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. * * eat(NULL,NULL) is always false. */ #define hunk_eat(DINNER, EAT) \ ({ \ typeof(DINNER) _dinner = DINNER; \ typeof(EAT) _eat = EAT; \ bool _ok = raw_starteq(_dinner->ptr, _dinner->len, \ _eat.ptr, _eat.len); \ if (_ok) { \ _dinner->ptr += _eat.len; \ _dinner->len -= _eat.len; \ } \ _ok; \ }) #define hunk_streat(DINNER, STREAT) \ hunk_eat(DINNER, shunk1(STREAT)) #define hunk_caseeat(DINNER, EAT) \ ({ \ typeof(DINNER) _dinner = DINNER; \ typeof(EAT) _eat = EAT; \ bool _ok = raw_casestarteq(_dinner->ptr, _dinner->len, \ _eat.ptr, _eat.len); \ if (_ok) { \ _dinner->ptr += _eat.len; \ _dinner->len -= _eat.len; \ } \ _ok; \ }) #define hunk_strcaseeat(DINNER, STRCASEEAT) \ hunk_caseeat(DINNER, shunk1(STRCASEEAT)) /* 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 */ \ raw_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; \ }) /* hunk[FLOOR..ROOF) */ #define hunk_slice(HUNK, FLOOR, ROOF) \ ({ \ size_t _floor = FLOOR; \ size_t _roof = ROOF; \ typeof(HUNK) _hunk = HUNK; \ passert(_floor <= _roof); \ passert(_roof <= _hunk.len); \ typeof(HUNK) _slice = { \ _hunk.ptr + _floor, \ .len = _roof - _floor, \ }; \ _slice; \ }) /* * Macros to treat a HUNK, pointing into a buffer, like a data stream: * * - initially .ptr is the start of the buffer, and .len is the * buffer's size * * - .ptr is the cursor (next byte) and .len is the upper bound * * - get/put advance .ptr and reduce the .len * * - 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)) /* * Macros for filling in a HUNK like object (hunk like objects have an * array for .ptr, hence sizeof(.ptr) determines the upper bound). */ #define hunk_append_bytes(DST/*pointer*/, SRC_PTR, SRC_LEN) \ ({ \ typeof(SRC_PTR) src_ptr_ = SRC_PTR; /* evaluate once */ \ size_t src_len_ = SRC_LEN; /* evaluate once */ \ typeof(DST) dst_ = DST; /* evaluate once */ \ passert(dst_->len + src_len_ <= sizeof(dst_->ptr/*array*/)); \ typeof(dst_->ptr[0]) *dst_ptr_ = dst_->ptr + dst_->len; \ memcpy(dst_ptr_, src_ptr_, src_len_); \ dst_->len += src_len_; \ dst_ptr_; \ }) #define hunk_append_hunk(DST/*pointer*/, SRC/*value*/) \ ({ \ typeof(SRC) *src_ = &(SRC); /* evaluate once */ \ hunk_append_bytes(DST, src_->ptr, src_->len); \ }) #define hunk_append_byte(DST/*pointer*/, BYTE, COUNT) \ ({ \ size_t count_ = COUNT; \ typeof(DST) dst_ = DST; /* evaluate once */ \ passert(dst_->len + count_ <= sizeof(dst_->ptr)/*array*/); \ typeof(dst_->ptr[0]) *dst_ptr_ = dst_->ptr + dst_->len; \ memset(dst_ptr_, BYTE, count_); \ dst_->len += count_; \ dst_ptr_; \ }) /* see hunkcheck.c */ #define is_digit(HUNK) char_isdigit(hunk_char(HUNK, 0)) #define is_char(HUNK, CHAR) (hunk_char(HUNK, 0) == CHAR) 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_cpy(DST, SRC) \ ({ \ typeof(SRC) *src_ = &(SRC); /* evaluate once */ \ typeof(DST) *dst_ = &(DST); /* evaluate once */ \ passert(src_->len == dst_->len); \ passert(src_->ptr != NULL); \ passert(dst_->ptr != NULL); \ memcpy(dst_->ptr, src_->ptr, dst_->len); \ }) #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. * * Overflow is handed with staturation (returns UINTMAX_MAX). */ void raw_hton(uintmax_t h, void *bytes, size_t size); uintmax_t raw_ntoh(const void *bytes, size_t size); #define ntoh_hunk(HUNK) \ ({ \ const typeof(HUNK) hunk_ = HUNK; /* evaluate once */ \ raw_ntoh(hunk_.ptr, hunk_.len); \ }) #define hton_chunk(H, HUNK) /* writeable */ \ ({ \ const chunk_t hunk_ = HUNK; /* evaluate once */ \ raw_hton(H, hunk_.ptr, hunk_.len); \ }) #define ntoh_thing(THING) \ ({ \ const shunk_t hunk_ = THING_AS_HUNK(THING); \ raw_ntoh(hunk_.ptr, hunk_.len); \ }) #define hton_thing(H, THING) /* writeable */ \ ({ \ chunk_t hunk_ = THING_AS_CHUNK(THING); \ raw_hton(H, hunk_.ptr, hunk_.len); \ }) /* * convert a hunk into a NUL terminated string; NULL is NULL. */ char *raw_clone_as_string(const void *ptr, size_t len, const char *name); #define clone_hunk_as_string(HUNK, NAME) \ ({ \ typeof(HUNK) hunk_ = HUNK; /* evaluate once */ \ raw_clone_as_string(hunk_.ptr, hunk_.len, NAME); \ }) #define clone_thing_as_string(THING, NAME) \ ({ \ shunk_t hunk_ = THING_AS_HUNK(THING); \ raw_clone_as_string(hunk_.ptr, hunk_.len, NAME); \ }) #define clone_bytes_as_hunk(TYPE, PTR, LEN) \ ({ \ TYPE *h_ = overalloc_thing(TYPE, LEN); \ memcpy(h_->ptr, (PTR), (LEN)); \ h_->len = LEN; \ h_; \ }) #endif libreswan-5.2/include/id.h000066400000000000000000000060131475767661000155610ustar00rootroot00000000000000/* 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 */ #include "verbose.h" struct cert; 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. */ typedef struct { char buf[512]; } id_buf; size_t jam_id_bytes(struct jambuf *buf, const struct id *id, jam_bytes_fn *jam_bytes); const char *str_id_bytes(const struct id *id, jam_bytes_fn *jam_bytes, id_buf *buf); size_t jam_id(struct jambuf *buf, const struct id *id); const char *str_id(const struct id *id, id_buf *buf); /* * Operations. */ struct id clone_id(const struct id *id, const char *why); extern void free_id_content(struct id *id); /* also blats ID */ extern bool 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 struct id *a, const struct id *b, int *wildcards, struct verbose verbose); 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); struct id id_from_cert(const struct cert *cert); #endif libreswan-5.2/include/ietf_constants.h000066400000000000000000002210041475767661000202070ustar00rootroot00000000000000/* * 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 /* see ikev2_ship_cp_attr_ip() where prefix is appended */ #define IKEv2_INTERNAL_IP6_ADDRESS_SIZE 17 #define IKEv2_INTERNAL_IP6_PREFIX_LEN_SIZE 1 #define IKEv2_INTERNAL_IP6_PREFIX_LEN 128 #define IKEv2_INTERNAL_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 */, /* 5 Reserved */ IKEv2_INTERNAL_IP4_DHCP = 6, IKEv2_APPLICATION_VERSION = 7, IKEv2_INTERNAL_IP6_ADDRESS = 8, /* 9 Reserved */ IKEv2_INTERNAL_IP6_DNS = 10, /* 11 Reserved */ 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_DIGITAL_SIGNATURE = 1, /* RSA_DIGITAL_SIGNATURE */ IKEv2_AUTH_SHARED_KEY_MAC = 2, /* SHARED_KEY_MIC */ 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_DIGITAL_SIGNATURE = 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; /* * IKEv2, while similar, is different. Let's not re-use and confuse. */ typedef enum v2_notification { /* * Unofficial! Must be zero to match default C initial value. * * Used to indicate success rather than the notification that * should be sent back. */ v2N_NOTHING_WRONG = 0, /* * Error notifications. * * 1-8191 Reserved, ExpertReview. * https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xml#ikev2-parameters-14 */ v2N_ERROR_FLOOR = 1, v2N_UNSUPPORTED_CRITICAL_PAYLOAD = 1, /* 2-3 Reserved */ v2N_INVALID_IKE_SPI = 4, v2N_INVALID_MAJOR_VERSION = 5, /* 6 Reserved */ v2N_INVALID_SYNTAX = 7, /* 8 Reserved */ v2N_INVALID_MESSAGE_ID = 9, /* 10 Reserved */ v2N_INVALID_SPI = 11, /* 12-13 Reserved */ v2N_NO_PROPOSAL_CHOSEN = 14, /* 15-16 Reserved */ v2N_INVALID_KE_PAYLOAD = 17, /* 18-23 Reserved */ v2N_AUTHENTICATION_FAILED = 24, /* 25-33 Reserved */ 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, /* RFC-4555 */ v2N_UNEXPECTED_NAT_DETECTED = 41, /* RFC-4555 */ v2N_USE_ASSIGNED_HoA = 42, /* RFC-5026 */ v2N_TEMPORARY_FAILURE = 43, v2N_CHILD_SA_NOT_FOUND = 44, v2N_INVALID_GROUP_ID = 45, /* draft-yeung-g-ikev2 */ v2N_AUTHORIZATION_FAILED = 46, /* draft-yeung-g-ikev2 */ v2N_STATE_NOT_FOUND = 47, /* RFC-9370 */ v2N_ERROR_PSTATS_ROOF, /* used to cap error statistics array */ /* * Status notifications. * * https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xml#ikev2-parameters-16 */ v2N_STATUS_FLOOR = 16384, 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, 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, /* RFC-8784 */ v2N_PPK_IDENTITY = 16436, /* RFC-8784 */ v2N_NO_PPK_AUTH = 16437, /* RFC-8784 */ v2N_INTERMEDIATE_EXCHANGE_SUPPORTED = 16438, /* draft-ietf-ipsecme-ikev2-intermediate-04 */ v2N_IP4_ALLOWED = 16439, /* RFC-8983 */ v2N_IP6_ALLOWED = 16440, /* RFC-8983 */ v2N_ADDITIONAL_KEY_EXCHANGE = 16441, /* RFC-9370 */ v2N_USE_AGGFRAG = 16442, /* RFC-9347 */ v2N_SUPPORTED_AUTH_METHODS = 16443, /* draft-ietf-ipsecme-ikev2-auth-announce-10 */ v2N_STATUS_PSTATS_ROOF, /* used to cap status statistics array */ /* 16438 - 40959 Unassigned */ /* 40960 - 65535 Private Use */ v2N_NULL_AUTH = 40960, v2N_PPK_IDENTITY_KEY = 50208, /* draft-ietf-ipsecme-ikev2--00 */ v2N_USE_PPK_INT = 50209, /* draft-ietf-ipsecme-ikev2-qr-alt-04 */ } v2_notification_t; /* RFC 8784 created registry */ enum ikev2_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 ikev1_ah_transform { IKEv1_AH_NONE = 0, /* Internal use - IKEv1 is reserved */ /* 1 IKEv1 RESERVED, IKEv2 AUTH_HMAC_MD5_96 */ IKEv1_AH_MD5 = 2, /* IKEv2 AUTH_HMAC_SHA1_96 */ IKEv1_AH_SHA = 3, /* IKEv2 AUTH_DES_MAC */ IKEv1_AH_DES = 4, /* IKEv2 AUTH_KPDK_MD5 */ IKEv1_AH_SHA2_256 = 5, /* IKEv2 AUTH_AES_XCBC_96 */ IKEv1_AH_SHA2_384 = 6, /* IKEv2 AUTH_HMAC_MD5_128 */ IKEv1_AH_SHA2_512 = 7, /* IKEv2 AUTH_HMAC_SHA1_160 */ IKEv1_AH_RIPEMD = 8, /* IKEv2 AUTH_AES_CMAC_96 */ IKEv1_AH_AES_XCBC_MAC = 9, /* IKEv2 AUTH_AES_128_GMAC */ IKEv1_AH_RSA = 10, /* IKEv2 AUTH_AES_192_GMAC */ IKEv1_AH_AES_128_GMAC = 11, /* IKEv2 AUTH_AES_256_GMAC */ IKEv1_AH_AES_192_GMAC = 12, /* IKEv2 AUTH_HMAC_SHA2_256_128 */ IKEv1_AH_AES_256_GMAC = 13, /* IKEv2 AUTH_HMAC_SHA2_384_192 */ IKEv1_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 */ IKEv1_AH_AES_CMAC_96 = 250, /* IKEv2=8 */ IKEv1_AH_NULL = 251, /* comes from kame? */ IKEv1_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 ikev1_esp_transform { IKEv1_ESP_reserved = 0, IKEv1_ESP_DES_IV64 = 1, IKEv1_ESP_DES = 2, /* obsoleted */ IKEv1_ESP_3DES = 3, IKEv1_ESP_RC5 = 4, IKEv1_ESP_IDEA = 5, IKEv1_ESP_CAST = 6, IKEv1_ESP_BLOWFISH = 7, /* obsoleyed */ IKEv1_ESP_3IDEA = 8, IKEv1_ESP_DES_IV32 = 9, IKEv1_ESP_RC4 = 10, IKEv1_ESP_NULL = 11, IKEv1_ESP_AES = 12, /* CBC 128 bit AES */ IKEv1_ESP_AES_CTR = 13, IKEv1_ESP_AES_CCM_8 = 14, IKEv1_ESP_AES_CCM_12 = 15, IKEv1_ESP_AES_CCM_16 = 16, IKEv1_ESP_AES_GCM_8 = 18, IKEv1_ESP_AES_GCM_12 = 19, IKEv1_ESP_AES_GCM_16 = 20, IKEv1_ESP_SEED_CBC = 21, /* IKEv1, IKEv2 is NULL_AUTH_AES_GMAC */ IKEv1_ESP_CAMELLIA = 22, /* IKEv1, IKEv2 is IKEv1_ESP_RESERVED_FOR_IEEE_P1619_XTS_AES */ IKEv1_ESP_NULL_AUTH_AES_GMAC = 23, /* IKEv1, IKEv2 is CAMELLIA_CBC */ IKEv1_ESP_PSTATS_ROOF, IKEv1_ESP_CAMELLIA_CTR = 24, /* not assigned in/for IKEv1 */ IKEv1_ESP_CAMELLIA_CCM_8 = 25, /* not assigned in/for IKEv1 */ IKEv1_ESP_CAMELLIA_CCM_12 = 26, /* not assigned in/for IKEv1 */ 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 */ IKEv1_ESP_MARS = 249, IKEv1_ESP_RC6 = 250, IKEv1_ESP_KAME_NULL = 251, /* kame? */ IKEv1_ESP_SERPENT = 252, IKEv1_ESP_TWOFISH = 253, }; /* * 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. * * TLV == Type/Length/Value; TV == Type/Value! */ #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-5.2/include/ike_alg.h000066400000000000000000000660751475767661000165760ustar00rootroot00000000000000/* * 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; struct enum_buf; /* * 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, /* i.e., ISAKAMP/IKE */ IKEv1_IPSEC_ID, /* either ESP or AH */ IKEv2_ALG_ID, /* IKE or Child */ 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); bool ike_alg_enum_matched(const struct ike_alg_type *type, 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_IPSEC_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_IPSEC_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_ipsec_id id[IKEv1_IPSEC_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; /* * When creating a key for the algorithm, its !?! */ CK_MECHANISM_TYPE key_gen; } 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 ikev1_ah_transform 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_hash_desc(enum ikev2_hash_algorithm, struct enum_buf *b); const struct encrypt_desc *ikev2_encrypt_desc(enum ikev2_trans_type_encr, struct enum_buf *b); const struct prf_desc *ikev2_prf_desc(enum ikev2_trans_type_prf, struct enum_buf *b); const struct integ_desc *ikev2_integ_desc(enum ikev2_trans_type_integ, struct enum_buf *b); const struct dh_desc *ikev2_dh_desc(enum ike_trans_type_dh, struct enum_buf *b); const struct ipcomp_desc *ikev2_ipcomp_desc(enum ipsec_ipcomp_algo, struct enum_buf *b); /* * 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). * * After the call b->buf is non-NULL. It is either the algorithms name * (when known) or "NN??" when unknown. */ const struct encrypt_desc *ikev1_ike_encrypt_desc(enum ikev1_encr_attribute, struct enum_buf *b); const struct prf_desc *ikev1_ike_prf_desc(enum ikev1_auth_attribute, struct enum_buf *b); const struct dh_desc *ikev1_ike_dh_desc(enum ike_trans_type_dh, struct enum_buf *b); const struct ipcomp_desc *ikev1_ike_ipcomp_desc(enum ipsec_ipcomp_algo, struct enum_buf *b); /* * Find the IKEv1 ENCRYPT / INTEG algorithm that will be fed into the * kernel to provide an IPSEC tunnel. */ const struct encrypt_desc *ikev1_kernel_encrypt_desc(enum ikev1_esp_transform, struct enum_buf *b); const struct integ_desc *ikev1_kernel_integ_desc(enum ikev1_auth_attribute, struct enum_buf *b); const struct ipcomp_desc *ikev1_kernel_ipcomp_desc(enum ipsec_ipcomp_algo, struct enum_buf *b); /* * Find the IKE_ALG matching the PFKEYv2 SADB_ALG_ID. */ const struct ike_alg *ike_alg_by_sadb_alg_id(const struct ike_alg_type *type, unsigned id); /* * 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-5.2/include/ike_alg_dh.h000066400000000000000000000031651475767661000172400ustar00rootroot00000000000000/* * 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-5.2/include/ike_alg_dh_ops.h000066400000000000000000000035331475767661000201200ustar00rootroot00000000000000/* * 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-5.2/include/ike_alg_encrypt.h000066400000000000000000000031231475767661000203230ustar00rootroot00000000000000/* 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-5.2/include/ike_alg_encrypt_ops.h000066400000000000000000000057611475767661000212160ustar00rootroot00000000000000/* 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 #include "chunk.h" #include "shunk.h" struct logger; enum cipher_op; enum cipher_iv_source; struct cipher_op_context; struct crypt_mac; struct encrypt_ops { const char *backend; /* * Delegate responsibility for checking OPS specific fields. */ void (*const cipher_check)(const struct encrypt_desc *cipher, struct logger *logger); /* * Create/delete a crypto context for use by the IKE SA. */ struct cipher_op_context *(*const cipher_op_context_create)(const struct encrypt_desc *cipher, enum cipher_op, enum cipher_iv_source, PK11SymKey *symkey, shunk_t salt, struct logger *logger); void (*const cipher_op_context_destroy)(struct cipher_op_context **context, struct logger *logger); /* * Perform simple encryption. * * Presumably something else is implementing the integrity. */ void (*const cipher_op_normal)(const struct encrypt_desc *cipher, struct cipher_op_context *context, enum cipher_op op, enum cipher_iv_source iv_source, PK11SymKey *symkey, shunk_t salt, chunk_t wire_iv, chunk_t text, /**/ struct crypt_mac *ikev1_iv, 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. * * Danger: TEXT and TAG are clearly contigious. */ bool (*const cipher_op_aead)(const struct encrypt_desc *cipher, struct cipher_op_context *context, enum cipher_op op, enum cipher_iv_source iv_source, PK11SymKey *symkey, shunk_t salt, /**/ chunk_t wire_iv, shunk_t aad, chunk_t text_and_tag, size_t text_size, size_t tag_size, 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_null_ops; #endif libreswan-5.2/include/ike_alg_hash.h000066400000000000000000000023431475767661000175650ustar00rootroot00000000000000/* 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-5.2/include/ike_alg_hash_ops.h000066400000000000000000000025601475767661000204470ustar00rootroot00000000000000/* * 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-5.2/include/ike_alg_integ.h000066400000000000000000000026361475767661000177550ustar00rootroot00000000000000/* 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-5.2/include/ike_alg_ipcomp.h000066400000000000000000000016011475767661000201250ustar00rootroot00000000000000/* * 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-5.2/include/ike_alg_ipcomp_ops.h000066400000000000000000000013611475767661000210110ustar00rootroot00000000000000/* 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-5.2/include/ike_alg_prf.h000066400000000000000000000020411475767661000174240ustar00rootroot00000000000000/* 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-5.2/include/ike_alg_prf_ikev1_ops.h000066400000000000000000000131211475767661000214050ustar00rootroot00000000000000/* 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 secret_preshared_stuff; 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, const struct secret_preshared_stuff *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-5.2/include/ike_alg_prf_ikev2_ops.h000066400000000000000000000063521475767661000214160ustar00rootroot00000000000000/* IKEv1 PRF specific operations, for libreswan * * Copyright (C) 2019 Andrew Cagney * Copyright (C) 2020 Yulia Kuzovkova * Copyright (C) 2020 Nupur Agrawal * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT 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); /* * IKEv2 - RFC5723 5.1 SKEYSEED - calculation * SKEYSEED = prf(SK_d (old), "Resumption" | Ni | Nr) */ PK11SymKey *(*ike_sa_resume_skeyseed)(const struct prf_desc *prf_desc, PK11SymKey *old_SK_d, 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); /* AUTH = prf(SK_px, ) */ struct crypt_mac (*psk_resume)(const struct prf_desc *prf_desc, PK11SymKey *SK_px, chunk_t first_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-5.2/include/ike_alg_prf_mac_ops.h000066400000000000000000000034051475767661000211320ustar00rootroot00000000000000/* * 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-5.2/include/ike_alg_test_cbc.h000066400000000000000000000020571475767661000204320ustar00rootroot00000000000000/* * 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-5.2/include/ike_alg_test_ctr.h000066400000000000000000000020471475767661000204720ustar00rootroot00000000000000/* * 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-5.2/include/ike_alg_test_gcm.h000066400000000000000000000022121475767661000204420ustar00rootroot00000000000000/* * 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-5.2/include/ike_alg_test_prf.h000066400000000000000000000027551475767661000204770ustar00rootroot00000000000000/* * 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-5.2/include/ike_spi.h000066400000000000000000000030631475767661000166120ustar00rootroot00000000000000/* 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-5.2/include/ikev1_prf.h000066400000000000000000000052071475767661000170570ustar00rootroot00000000000000/* * 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, const struct secret_preshared_stuff *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-5.2/include/ikev2_prf.h000066400000000000000000000054701475767661000170620ustar00rootroot00000000000000/* 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 * Copyright (C) 2020 Nupur Agrawal * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT 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); PK11SymKey *ikev2_ike_sa_ppk_interm_skeyseed(const struct prf_desc *prf_desc, PK11SymKey *old_SK_d, shunk_t ppk, struct logger *logger); PK11SymKey *ikev2_ike_sa_resume_skeyseed(const struct prf_desc *prf_desc, PK11SymKey *old_SK_d, const chunk_t Ni, const chunk_t Nr, 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); struct crypt_mac ikev2_psk_resume(const struct prf_desc *prf_desc, PK11SymKey *SK_px, chunk_t first_packet, struct logger *logger); #endif libreswan-5.2/include/impair.h000066400000000000000000000133361475767661000164540ustar00rootroot00000000000000/* 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; struct whack_impair; /* * Meddle with the contents of a payload. */ enum impair_emit { IMPAIR_EMIT_NO = 0, IMPAIR_EMIT_OMIT, IMPAIR_EMIT_EMPTY, IMPAIR_EMIT_DUPLICATE, #define IMPAIR_EMIT_ROOF (IMPAIR_EMIT_DUPLICATE+1) /* >= 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, }; struct impair_unsigned { bool enabled; unsigned value; }; /* * 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; struct impair_unsigned log_rate_limit; enum impair_emit v1_hash_payload; enum impair_v1_exchange v1_hash_exchange; bool v1_hash_check; struct impair_unsigned ike_initiator_spi; struct impair_unsigned ike_responder_spi; bool bust_mi2; bool bust_mr2; bool drop_i2; bool jacob_two_two; bool allow_null_none; bool major_version_bump; bool minor_version_bump; bool timeout_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; struct impair_unsigned ikev2_add_ike_transform; struct impair_unsigned ikev2_add_child_transform; 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; struct impair_unsigned add_unknown_v2_payload_to; struct impair_unsigned add_unknown_v2_payload_to_sk; bool unknown_v2_payload_critical; struct impair_unsigned force_v2_auth_method; struct impair_unsigned add_v2_notification; struct impair_unsigned ignore_v2_notification; struct impair_unsigned omit_v2_notification; bool omit_v2_ike_auth_child; bool ignore_v2_ike_auth_child; bool event_check_crls; bool ignore_soft_expire; bool ignore_hard_expire; bool cannot_ondemand; struct impair_unsigned number_of_TSi_selectors; struct impair_unsigned number_of_TSr_selectors; bool lifetime; bool copy_v1_notify_response_SPIs_to_retransmission; struct impair_unsigned v1_remote_quick_id; struct impair_unsigned v1_emit_quick_id; enum impair_emit v1_isakmp_delete_payload; enum impair_emit v1_ipsec_delete_payload; struct impair_unsigned v2_delete_protoid; struct impair_unsigned v2n_rekey_sa_protoid; struct impair_unsigned v2_proposal_protoid; struct impair_unsigned helper_thread_delay; bool install_ipsec_sa_inbound_state; bool install_ipsec_sa_inbound_policy; bool install_ipsec_sa_outbound_state; bool install_ipsec_sa_outbound_policy; bool record_inbound; bool record_outbound; /* * add more here */ }; extern struct impair impair; 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_message_direction { IMPAIR_INBOUND_MESSAGE, IMPAIR_OUTBOUND_MESSAGE, }; enum impair_action { CALL_IMPAIR_UPDATE, CALL_INITIATE_v2_LIVENESS, CALL_SEND_KEEPALIVE, CALL_GLOBAL_EVENT_HANDLER, CALL_STATE_EVENT_HANDLER, CALL_CONNECTION_EVENT_HANDLER, CALL_IMPAIR_MESSAGE_DROP, CALL_IMPAIR_MESSAGE_BLOCK, CALL_IMPAIR_MESSAGE_DRIP, CALL_IMPAIR_MESSAGE_DUPLICATE, CALL_IMPAIR_MESSAGE_REPLAY, #if 0 CALL_IMPAIR_CORRUPT_INBOUND, CALL_IMPAIR_CORRUPT_OUTBOUND, #endif }; bool process_impair(const struct whack_impair *whack_impair, void (*action)(enum impair_action impairment_action, unsigned impairment_param, bool whack_enable, unsigned whack_value, 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-5.2/include/initiated_by.h000066400000000000000000000017711475767661000176370ustar00rootroot00000000000000/* initiating connections, for libreswan * * Copyright (C) 2023 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT 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 INITIATED_BY_H #define INITIATED_BY_H enum initiated_by { INITIATED_BY_UNKNOWN = 0, INITIATED_BY_WHACK, INITIATED_BY_REVIVE, INITIATED_BY_ACQUIRE, INITIATED_BY_REPLACE, INITIATED_BY_PENDING, INITIATED_BY_IKE, /* i.e., IKE_AUTH */ INITIATED_BY_PEER, }; #define INITIATED_BY_ROOF (INITIATED_BY_PEER+1) extern const struct enum_names initiated_by_names; #endif libreswan-5.2/include/ip_address.h000066400000000000000000000135671475767661000173160ustar00rootroot00000000000000/* 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 "diag.h" #include "where.h" #include "ip_bytes.h" #include "ip_version.h" #include "ip_index.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, const struct ip_info *afi, 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); diag_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); /* comma/space separated list */ typedef struct { struct { unsigned len; ip_address *list; } ip[IP_INDEX_ROOF]; unsigned len; ip_address *list; } ip_addresses; extern const ip_addresses empty_ip_addresses; diag_t ttoaddresses_num(shunk_t input, const char *delims, const struct ip_info *afi, ip_addresses *output); size_t jam_addresses(struct jambuf *buf, ip_addresses addresses); /* * 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); /* * 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); /* * Old style. */ /* 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-5.2/include/ip_bytes.h000066400000000000000000000065561475767661000170170ustar00rootroot00000000000000/* 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; /* * 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_routing_prefix_blit keep_routing_prefix; extern const struct ip_routing_prefix_blit clear_routing_prefix; extern const struct ip_routing_prefix_blit set_routing_prefix; extern const struct ip_host_identifier_blit clear_host_identifier; extern const struct ip_host_identifier_blit set_host_identifier; struct ip_bytes ip_bytes_blit(const struct ip_info *afi, const struct ip_bytes bytes, const struct ip_routing_prefix_blit *routing_prefix, const struct ip_host_identifier_blit *host_identifier, int prefix_len); /* 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_len(const struct ip_info *afi, const struct ip_bytes lo, const struct ip_bytes hi); int ip_bytes_host_len(const struct ip_info *afi, const struct ip_bytes lo, const struct ip_bytes hi); int ip_bytes_mask_len(const struct ip_info *afi, const struct ip_bytes bytes); 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) size_t jam_ip_bytes_range(struct jambuf *buf, const struct ip_info *afi, const struct ip_bytes lo, const struct ip_bytes hi); #endif libreswan-5.2/include/ip_cidr.h000066400000000000000000000056551475767661000166110ustar00rootroot00000000000000/* 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_bytes.h" #include "ip_version.h" #include "ip_address.h" struct jambuf; typedef struct { bool is_set; enum ip_version version; struct ip_bytes bytes; unsigned prefix_len; } ip_cidr; #define PRI_CIDR "" #define pri_cidr(A) \ ((A).is_set ? "set" : "unset"), \ (A).version, \ pri_ip_bytes((A).bytes), \ (A).prefix_len void pexpect_cidr(const ip_cidr a, where_t where); #define pcidr(A) pexpect_cidr(A, HERE) extern const ip_cidr unset_cidr; /* convert CIDR address/mask; does not judge the result */ ip_cidr cidr_from_raw(where_t where, const struct ip_info *afi, const struct ip_bytes bytes, unsigned prefix_bits); diag_t data_to_cidr(const void *data, size_t data_size, unsigned prefix_len, const struct ip_info *afi, ip_cidr *cidr) MUST_USE_RESULT; #define hunk_to_cidr(HUNK, PREFIX_LEN, AFI, CIDR) \ data_to_cidr((HUNK).ptr, (HUNK).len, PREFIX_LEN, AFI, CIDR) ip_cidr cidr_from_address(ip_address address); /* * 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_check(const ip_cidr cidr); bool cidr_is_specified(const ip_cidr 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); ip_address cidr_prefix(const ip_cidr cidr); ip_address cidr_host(const ip_cidr cidr); int cidr_prefix_len(const ip_cidr cidr); /* are two is_set() cidrs identical? */ bool cidr_eq_cidr(const ip_cidr address, const ip_cidr another); /* * Raw address bytes, both read-only and read-write. */ shunk_t cidr_as_shunk(const ip_cidr *cidr); chunk_t cidr_as_chunk(ip_cidr *cidr); err_t ttocidr_num(shunk_t src, const struct ip_info *afi, 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-5.2/include/ip_encap.h000066400000000000000000000027111475767661000167440ustar00rootroot00000000000000/* 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-5.2/include/ip_endpoint.h000066400000000000000000000114261475767661000175010ustar00rootroot00000000000000/* 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" #include "ip_version.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; /* For IKE sending socket. With xfrm interface and IKE endpoint is within remote TS*/ uint32_t mark_out; } ip_endpoint; #define PRI_ENDPOINT "" #define pri_endpoint(A) \ ((A)->is_set ? "set" : "unset"), \ (A)->version, \ ((A)->ipproto > 255 ? "PROTO>255" : \ protocol_from_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, const struct ip_info *afi, 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("]:PROTOCOL/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 *); size_t jam_endpoint_address_protocol_port(struct jambuf *, const ip_endpoint*); size_t jam_endpoint_address_protocol_port_sensitive(struct jambuf *, const ip_endpoint*); const char *str_endpoint_address_protocol_port(const ip_endpoint *, endpoint_buf *); const char *str_endpoint_address_protocol_port_sensitive(const ip_endpoint *, endpoint_buf *); typedef struct { char buf[sizeof(endpoint_buf) + sizeof("--UNKNOWN--UNKNOWN-->") + sizeof(endpoint_buf)]; } endpoint_pair_buf; size_t jam_endpoint_pair(struct jambuf *jambuf, const ip_endpoint *src, const ip_endpoint *dst); const char *str_endpoint_pair(const ip_endpoint *src, const ip_endpoint *dst, endpoint_pair_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; #endif libreswan-5.2/include/ip_index.h000066400000000000000000000014231475767661000167640ustar00rootroot00000000000000/* 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-5.2/include/ip_info.h000066400000000000000000000064231475767661000166150ustar00rootroot00000000000000/* 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_version.h" #include "ip_index.h" #include "constants.h" /* for enum ikev2_ts_addr_range_type; et.al. */ struct ip_info { /* * address family */ enum ip_version ip_version; /* 4 or 6 */ enum ip_index ip_index; /* 0 or 1 */ const char *ip_name; /* "IPv4" or "IPv6" */ const char *inet_name; /* "inet" or "inet6" */ size_t ip_size; /* 4 or 16 */ unsigned mask_cnt; /* 32 or 128 */ /* * Formatting primitives. */ struct { /* N.N.N.N or N:N:N:N */ size_t (*address)(struct jambuf *buf, const struct ip_info *info, const struct ip_bytes *bytes); /* N.N.N.N or [MM:MM:MM...] */ size_t (*address_wrapped)(struct jambuf *buf, const struct ip_info *info, const struct ip_bytes *bytes); } jam; /* * ip_address */ struct { const ip_address unspec; /* 0.0.0.0 or :: */ const ip_address loopback; /* 127.0.0.1 or ::1 */ } address; /* * ip_endpoint */ #if 0 struct { } endpoint; #endif /* * 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; /* PF_INET or PF_INET6 */ const char *domain_name; /* "PF_INET" or "PF_INET6" */ } socket; /* * Sockaddr. */ int af; /* AF_INET or AF_INET6 */ const char *af_name; /* "AF_INET" or "AF_INET6" */ /* 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; enum ikev2_cp_attribute_type ikev2_internal_address; enum ikev2_cp_attribute_type ikev2_internal_dns; /* * 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 unspec_ip_info; extern const struct ip_info *aftoinfo(int af); const struct ip_info *ip_version_info(enum ip_version version); /* * Internal. */ diag_t ttoips_num(shunk_t input, const struct ip_info *afi, void **ptr, unsigned *len, err_t (*parse_token)(shunk_t, const struct ip_info *, void **ptr, unsigned len)); #endif libreswan-5.2/include/ip_packet.h000066400000000000000000000062041475767661000171260ustar00rootroot00000000000000/* 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-5.2/include/ip_port.h000066400000000000000000000036661475767661000166540ustar00rootroot00000000000000/* 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 interpreted as either 0, or any-port (is this a * good idea?); host-byte 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 #define port_eq(L,R) ((L).hport == (R).hport) err_t ttoport(shunk_t text, ip_port *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-5.2/include/ip_port_range.h000066400000000000000000000025001475767661000200120ustar00rootroot00000000000000/* 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-5.2/include/ip_protocol.h000066400000000000000000000070001475767661000175130ustar00rootroot00000000000000/* 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). */ 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; /* * When showing a selector or packet, the zero port denotes * any port (0-65535) and should be omitted from the output. * * When parsing an endpoint, zero aka wild ports, aren't * allowed. */ bool zero_port_is_any; }; #if 0 typedef const struct ip_protocol *ip_protocol; /* good idea? */ #endif #ifdef IPPROTO_COMP #define IPCOMP_IPPROTO IPPROTO_COMP /*linux*/ #endif #ifdef IPPROTO_IPCOMP #define IPCOMP_IPPROTO IPPROTO_IPCOMP /*everything else*/ #endif 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 */ /* match then eat the start of prefix */ const struct ip_protocol *protocol_from_caseeat_prefix(shunk_t *prefix); const struct ip_protocol *protocol_from_ipproto(unsigned protoid); const struct ip_protocol *protocol_from_shunk(shunk_t protocol); err_t ttoprotocol(shunk_t text, const struct 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_protocol_pair(struct jambuf *buf, const struct ip_protocol *src, char sep, const struct ip_protocol *dst); /* used to size other buffers */ #endif libreswan-5.2/include/ip_protoport.h000066400000000000000000000026021475767661000177250ustar00rootroot00000000000000/* 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-5.2/include/ip_range.h000066400000000000000000000111451475767661000167530ustar00rootroot00000000000000/* 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" #include "ip_version.h" typedef struct { bool is_set; enum ip_version version; struct ip_bytes lo; struct ip_bytes hi; } ip_range; #define PRI_RANGE "["PRI_IP_BYTES"]>" #define pri_range(R) \ ((R)->is_set ? "set" : "unset"), \ (R)->version, \ pri_ip_bytes((R)->lo), \ pri_ip_bytes((R)->hi) 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, const struct ip_info *afi, 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_num(shunk_t input, const struct ip_info *afi, ip_range *dst) MUST_USE_RESULT; /* comma/space separated list */ typedef struct { unsigned len; ip_range *list; } ip_ranges; extern const ip_ranges empty_ip_ranges; diag_t ttoranges_num(shunk_t input, const char *delims, const struct ip_info *afi, ip_ranges *output) MUST_USE_RESULT; size_t jam_ranges(struct jambuf *buf, ip_ranges ranges); /* * 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); 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_is_cidr(ip_range r); /* prefix/host=0..prefix/host=-1 */ 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. */ int range_host_len(const ip_range range); /* <0 when non-CIDR */ int range_prefix_len(const ip_range range); /* <0 when non-CIDR */ /* * 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-5.2/include/ip_said.h000066400000000000000000000066271475767661000166100ustar00rootroot00000000000000/* 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" #include "ip_version.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 /* * 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, const struct ip_info *afi, 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-5.2/include/ip_selector.h000066400000000000000000000174561475767661000175120ustar00rootroot00000000000000/* 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_cidr.h" #include "ip_range.h" #include "ip_bytes.h" #include "ip_version.h" #include "ip_index.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 lo; struct ip_bytes hi; 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_from_ipproto((S)->ipproto)->name), \ pri_ip_bytes((S)->lo), \ pri_ip_bytes((S)->hi), \ (S)->hport 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, const struct ip_info *afi, const struct ip_bytes lo, const struct ip_bytes hi, 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_cidr(const ip_cidr cidr); 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 ttoselector_num(shunk_t src, const struct ip_info *afi, ip_selector *dst, ip_address *nonzero_host); /* comma/space separated list */ typedef struct { struct { unsigned len; ip_selector *list; } ip[IP_INDEX_ROOF]; unsigned len; ip_selector *list; } ip_selectors; extern const ip_selectors empty_ip_selectors; diag_t ttoselectors_num(shunk_t input, const char *delims, const struct ip_info *afi, ip_selectors *output, ip_address *nonzero_host); size_t jam_selectors(struct jambuf *buf, const ip_selectors selectors); /* * 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); /* assuming a subnet like XFRM does */ ip_address selector_prefix(const ip_selector selector); ip_address selector_prefix_mask(const ip_selector selector); int selector_prefix_len(const ip_selector selector); /* <0 when non-CIDR*/ int selector_host_len(const ip_selector selector); /* <0 when non-CIDR*/ 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/*/CHAOS*/ + 6/*/65535*/)*2 + 1/*-*/]; } selector_buf; const char *str_selector(const ip_selector *selector, selector_buf *out); const char *str_selector_range(const ip_selector *selector, subnet_buf *buf); const char *str_selector_range_port(const ip_selector *selector, selector_buf *out); size_t jam_selector(struct jambuf *buf, const ip_selector *selector); size_t jam_selector_range(struct jambuf *buf, const ip_selector *selector); size_t jam_selector_range_port(struct jambuf *buf, const ip_selector *selector); typedef struct { char buf[sizeof(selector_buf) + sizeof("=UNKNOWN=UNKNOWN=>") + sizeof(selector_buf)]; } selector_pair_buf; const char *str_selector_pair(const ip_selector *src, const ip_selector *dst, selector_pair_buf *out); size_t jam_selector_pair(struct jambuf *buf, const ip_selector *src, const ip_selector *dst); const char *str_selector_pair_sensitive(const ip_selector *src, const ip_selector *dst, selector_pair_buf *out); size_t jam_selector_pair_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 address_in_selector_range(const ip_address l, const ip_selector r); #endif libreswan-5.2/include/ip_sockaddr.h000066400000000000000000000034731475767661000174560ustar00rootroot00000000000000/* 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-5.2/include/ip_subnet.h000066400000000000000000000102431475767661000171550ustar00rootroot00000000000000/* 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_cidr.h" #include "ip_bytes.h" #include "ip_version.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, const struct ip_info *afi, const struct ip_bytes prefix, unsigned prefix_length); /* ADDRESS..ADDRESS */ ip_subnet subnet_from_address(const ip_address address); /* ADDRESS/PREFIX_BITS */ ip_subnet subnet_from_cidr(const ip_cidr cidr); /* 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_num(shunk_t src, const struct ip_info *afi, ip_subnet *dst, ip_address *nonzero_host); /* comma/space separated list */ typedef struct { unsigned len; ip_subnet *list; } ip_subnets; diag_t ttosubnets_num(shunk_t input, const struct ip_info *afi, ip_subnets *output); size_t jam_subnets(struct jambuf *buf, const ip_subnets subnets); #endif libreswan-5.2/include/ip_version.h000066400000000000000000000013511475767661000173420ustar00rootroot00000000000000/* 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_VERSION_H #define IP_VERSION_H enum ip_version { IPv4 = 4, IPv6 = 6, }; #endif libreswan-5.2/include/ipsec_spi.h000066400000000000000000000023101475767661000171370ustar00rootroot00000000000000/* * 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-5.2/include/ipsecconf/000077500000000000000000000000001475767661000167655ustar00rootroot00000000000000libreswan-5.2/include/ipsecconf/confread.h000066400000000000000000000063331475767661000207240ustar00rootroot00000000000000/* 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" #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" #include "end.h" struct logger; /* * Code tests <> to detect either k_unset or * k_default and allow an override. */ enum keyword_set { k_unset = false, k_set = true, k_default = 2 }; struct keyword_value { enum keyword_set set; char *string; intmax_t option; deltatime_t deltatime; }; typedef struct keyword_value keyword_values[KW_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; /* XXX: move to starter_conn? */ enum keyword_host addrtype; enum keyword_host nexttype; ip_address addr; ip_address nexthop; ip_cidr vti_ip; keyword_values values; }; /* * 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; char *name; keyword_values values; enum ike_version ike_version; struct authby authby; lset_t sighash_policy; enum shunt_policy shunt[SHUNT_KIND_ROOF]; struct starter_end end[END_ROOF]; const struct ip_info *clientaddrfamily; enum { STATE_INVALID, STATE_LOADED, STATE_INCOMPLETE, STATE_ADDED, STATE_FAILED, } state; uint32_t xfrm_if_id; }; struct starter_config { keyword_values values; /* conn %default */ struct starter_conn conn_default; /* connections list (without %default) */ TAILQ_HEAD(, starter_conn) conns; }; extern struct config_parsed *parser_load_conf(const char *file, struct logger *logger); extern void parser_freeany_config_parsed(struct config_parsed **cfg); extern struct starter_config *confread_load(const char *file, bool setuponly, struct logger *logger); extern void confread_free(struct starter_config *cfg); #endif /* _IPSEC_CONFREAD_H_ */ libreswan-5.2/include/ipsecconf/confwrite.h000066400000000000000000000021531475767661000211370ustar00rootroot00000000000000/* 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-5.2/include/ipsecconf/interfaces.h000066400000000000000000000020111475767661000212530ustar00rootroot00000000000000/* 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-5.2/include/ipsecconf/keywords.h000066400000000000000000000276021475767661000210140ustar00rootroot00000000000000/* 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 * Copyright (C) 2020 Nupur Agrawal * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT 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" #include "deltatime.h" /* * Keyword value indexes. The value is stored in: * * + the keyword table determines: the keyword type; where it is valid * and where the value is stored are stored: * * "config setup; keyword=": in .setup.{strings,options,set}[]. * "conn ...' keyword=": in .{strings,options,set}[] * "conn ; left...": in .{left,right}.{strings,options,set}[] * * + The original string is always stored in .strings[] and should be * used when logging errors. * * + .set[] is made non-zero (either k_set or k_default); code tests * for non-zero to determine if a value is present * * + for historic reasons, some of the enums have strange prefixes * and/or strange grouping. For instance, KSF_* options only appear * in "config setup" so if the same option used between multiple * sections the prefix should be changed. */ enum keywords { /* * Generic keywords, add more here. */ KW_DEBUG, KW_IP, KW_NEXTHOP, KW_RSASIGKEY, KW_ECDSAKEY, KW_PUBKEY, KWYN_IPSEC_INTERFACE_MANAGED, KWS_IPSEC_INTERFACE, /* * By convention, these are global configuration strings and * only appear in the "config setup" section (KSF == Keyword * String Flag?). */ 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, /* * By convention, these are global configuration numeric (and * boolean) values and only appear in the "config setup" * section (KBF == Keyword Boolean Flag?). */ 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, KBF_OCSP_STRICT, KBF_OCSP_ENABLE, KBF_OCSP_TIMEOUT_SECONDS, KBF_OCSP_CACHE_SIZE, KBF_OCSP_CACHE_MIN_AGE_SECONDS, KBF_OCSP_CACHE_MAX_AGE_SECONDS, KBF_OCSP_METHOD, KBF_CURL_TIMEOUT_SECONDS, KBF_SEEDBITS, KBF_DROP_OPPO_NULL, KBF_KEEP_ALIVE, KBF_NHELPERS, KBF_SHUNTLIFETIME, KBF_FORCEBUSY, /* obsoleted for KBF_DDOS_MODE */ KBF_DDOS_IKE_THRESHOLD, KBF_MAX_HALFOPEN_IKE, 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 drop */ /* * By convention, these are connnection strings (KSCF is * Keyword String Connection Flag?). The initial ones come in * left/right variants. */ KSCF_GROUNDHOG, /* left/right */ KSCF_UPDOWN, /* left/right */ KSCF_ID, /* left/right */ KSCF_CERT, /* left/right */ KSCF_CKAID, /* left/right */ KSCF_CA, /* left/right */ KSCF_PROTOPORT, /* left/right */ KSCF_SOURCEIP, /* left/right */ KSCF_VTI_IP, /* left/right */ KSCF_INTERFACE_IP, /* left/right */ KSCF_USERNAME, /* left/right */ KSCF_ADDRESSPOOL, /* left/right */ KSCF_SUBNET, /* left/right */ KSCF_SUBNETS, /* left/right */ KSCF_AUTHBY, KSCF_PPK_IDS, KSCF_MODECFGDNS, KSCF_MODECFGDOMAINS, KSCF_IKE, KSCF_MODECFGBANNER, KSCF_ESP, KSCF_ALSO, KSCF_REDIRECT_TO, KSCF_ACCEPT_REDIRECT_TO, KSCF_CONNALIAS, KSCF_SEC_LABEL, KSCF_MARK, KSCF_MARK_IN, KSCF_MARK_OUT, KSCF_VTI_INTERFACE, KSCF_DPDDELAY, KSCF_DPDTIMEOUT, /* * By convention, these are connection numeric (or boolean) * values (KNCF is Keyword Numeric Connection Flag?). The * initial ones come in left/right variants. */ 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_PFS_REKEY_WORKAROUND, KNCF_FIREWALL, KNCF_IDTYPE, KNCF_SPIBASE, KNCF_SPI, KNCF_ESPREPLAYWINDOW, KNCF_FAILURESHUNT, KNCF_NEGOTIATIONSHUNT, KNCF_TYPE, KNCF_MOBIKE, KNCF_MTU, KNCF_PRIORITY, KNCF_TFC, KNCF_IPTFS, KNCF_IPTFS_FRAGMENTATION, KNCF_IPTFS_PACKET_SIZE, KNCF_IPTFS_MAX_QUEUE_SIZE, KNCF_IPTFS_INIT_DELAY, KNCF_IPTFS_REORDER_WINDOW, KNCF_IPTFS_DROP_TIME, KNCF_REQID, KNCF_SEND_CA, KNCF_METRIC, KNCF_PHASE2, KNCF_AUTO, KNCF_PFS, KNCF_SHA2_TRUNCBUG, KNCF_MS_DH_DOWNGRADE, KNCF_REQUIRE_ID_ON_CERTIFICATE, KNCF_DNS_MATCH_ID, KNCF_IPSEC_LIFETIME, KNCF_IPSEC_MAXBYTES, KNCF_IPSEC_MAXPACKETS, KNCF_REKEY, KNCF_REAUTH, KNCF_REKEYMARGIN, KNCF_REKEYFUZZ, KNCF_COMPRESS, KNCF_KEYINGTRIES, KNCF_REPLAY_WINDOW, KNCF_IKELIFETIME, KNCF_RETRANSMIT_TIMEOUT, KNCF_RETRANSMIT_INTERVAL, KNCF_AGGRESSIVE, KNCF_MODECFGPULL, KNCF_ENCAPSULATION, KNCF_IKEv2, /* obsolete, use KEYEXCHANGE */ KNCF_KEYEXCHANGE, KNCF_PPK, KNCF_INTERMEDIATE, /* enable support for Intermediate Exchange */ KNCF_ESN, KNCF_DECAP_DSCP, KNCF_ENCAP_DSCP, KNCF_NOPMTUDISC, KNCF_NARROWING, KNCF_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_REMOTE_PEER_TYPE, /* Cisco interop: remote peer type */ KNCF_NM_CONFIGURED, /* Network Manager support */ KNCF_SAREFTRACK, /* saref tracking parameter for _updown */ KNCF_OBSOLETE, /* to ignore but warn obsoleted keywords */ KNCF_XAUTHBY, /* method of xauth user auth - file, pam or alwaysok */ KNCF_XAUTHFAIL, /* method of failing, soft or hard */ KNCF_FRAGMENTATION, /* 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_NAT_IKEv1_METHOD, /* 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_ENABLE_TCP, /* TCP (yes/no/fallback) */ KNCF_TCP_REMOTEPORT, /* TCP remote port - default 4500 */ KNCF_IGNORE_PEER_DNS, /* Accept DNS nameservers from peer */ KNCF_SESSION_RESUMPTION, /* RFC 5723 IKE_RESUME */ KW_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_both = LELEM(2) | LELEM(3), /* also comes in FOO meaning left-FOO and right-FOO */ 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), /* within a connection, the * item can be duplicated * (notably also=) */ #if 0 kv_overrideok = LELEM(?), /* between merged connections * (also=), the item can be * overwritten */ #endif }; #define KV_CONTEXT_MASK (kv_config | kv_conn | kv_leftright) /* * 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_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_sparse_name, /* value is from .sparse_name table */ kt_lset, /* a set of values from .sparse_name */ kt_host, /* %-prefixed .sparse_name, or a hostname string */ kt_pubkey, /* %-prefixed .sparse_name, or a pubkey string */ kt_unsigned, /* an unsigned integer */ kt_seconds, /* deltatime, default in seconds */ kt_milliseconds, /* deltatime, default in milliseconds (1/1000s) */ 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_also, /* i.e., #include */ kt_obsolete, /* option that is obsoleted, allow keyword but warn and ignore */ }; 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_names *sparse_names; 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; deltatime_t deltatime; }; struct section_list { TAILQ_ENTRY(section_list) link; char *name; struct kw_list *kw; bool beenhere; }; struct config_parsed { struct kw_list *config_setup; TAILQ_HEAD(sectionhead, section_list) sections; int ipsec_conf_version; struct section_list conn_default; }; extern const struct keyword_def ipsec_conf_keywords[]; #endif /* _KEYWORDS_H_ */ libreswan-5.2/include/ipsecconf/parser-controls.h000066400000000000000000000033711475767661000222770ustar00rootroot00000000000000/* 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 */ struct logger; #include /* for PATH_MAX */ #include "lswcdefs.h" /* for PRINTF_LIKE() */ 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 */ /* defined in parser.y */ void parser_warning(struct logger *logger, int eerror/*can be 0*/, const char *s, ...) PRINTF_LIKE(3); void parser_fatal(struct logger *logger, int eerror/*can be 0*/, const char *s, ...) PRINTF_LIKE(3) NEVER_RETURNS; /* 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-5.2/include/ipsecconf/parser-flex.h000066400000000000000000000015411475767661000213670ustar00rootroot00000000000000/* 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. */ struct logger; /* declared and defined in lex.yy.c (output of flex) */ extern FILE *yyin; extern int yylex(struct logger *logger); libreswan-5.2/include/ipsecconf/parser.h000066400000000000000000000021611475767661000204320ustar00rootroot00000000000000/* 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_ struct logger; #include "parser.tab.h" /* generated by bison */ #include "parser-controls.h" extern const char *parser_cur_filename(void); extern unsigned parser_cur_line(void); extern void parser_y_init(const char *name, FILE *f ); void parser_y_include(const char *filename, struct logger *logger); #define THIS_IPSEC_CONF_VERSION 2 #endif /* _IPSEC_PARSER_H_ */ libreswan-5.2/include/ipsecconf/pluto.h000066400000000000000000000016611475767661000203050ustar00rootroot00000000000000/* 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-5.2/include/ipsecconf/starterwhack.h000066400000000000000000000020161475767661000216370ustar00rootroot00000000000000/* 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(const char *ctlsocket, const struct starter_conn *conn, struct logger *logger); extern int starter_whack_listen(const char *ctlsocket, struct logger *logger); #endif /* _STARTER_WHACK_H_ */ libreswan-5.2/include/jambuf.h000066400000000000000000000210021475767661000164240ustar00rootroot00000000000000/* 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" #define LOG_WIDTH ((size_t)1024) /* roof of number of chars in log line */ /* * 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); 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); \ }) /* convert lowercase to uppercase, i.e., [a-z] [A-Z] */ jam_bytes_fn jam_uppercase_bytes; size_t jam_string_uppercase(struct jambuf *buf, const char *string); /* convert [_A-Z] to [-a-z]; see jam_enum_human() */ jam_bytes_fn jam_human_bytes; size_t jam_string_human(struct jambuf *buf, const char *string); /* * 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-5.2/include/kernel_mode.h000066400000000000000000000023151475767661000174520ustar00rootroot00000000000000/* kernel mode, for libreswan * * Copyright (C) 2024 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT 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_MODE_H #define KERNEL_MODE_H /* * Kernel's outer most encapsulation mode. * * Contrary to the RFCs and ENCAPSULATION_MODE_*, the kernel only has * to handle three outermost encapsulation. Hence an ENUM that only * defines those values. * * Except contrary to that, PF KEY v2 accepts the mode "any". */ enum kernel_mode { #define KERNEL_MODE_FLOOR 1 KERNEL_MODE_TRANSPORT = 1, KERNEL_MODE_TUNNEL, KERNEL_MODE_IPTFS, #define KERNEL_MODE_ROOF (KERNEL_MODE_IPTFS+1) }; extern const struct enum_names kernel_mode_names; extern const struct enum_names kernel_mode_stories; #endif libreswan-5.2/include/kernel_netlink_query.h000066400000000000000000000014541475767661000214220ustar00rootroot00000000000000/* * 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, const struct logger *logger); #endif libreswan-5.2/include/kernel_netlink_reply.h000066400000000000000000000021171475767661000214050ustar00rootroot00000000000000/* * 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-5.2/include/keyid.h000066400000000000000000000021471475767661000162760ustar00rootroot00000000000000/* 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-5.2/include/lex.h000066400000000000000000000031171475767661000157570ustar00rootroot00000000000000/* 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-5.2/include/linux_netlink.h000066400000000000000000000035311475767661000200520ustar00rootroot00000000000000/* * generic netlink receive message, for libreswan * * Copyright (C) 2024 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT 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 LINUX_NETLINK_H #define LINUX_NETLINK_H #include /* for size_t */ #include #include #include /* for pid_t */ #include "verbose.h" struct nlmsghdr; struct linux_netlink_context; struct logger; /* * Use struct linux_netlink_context to return the result. * * Return FALSE when processing can stop early. Actual status should * be stored in the linux_netlink_context. */ typedef bool linux_netlink_response_processor(struct nlmsghdr *, struct linux_netlink_context *, struct verbose verbose); /* * Send query and process response. * * Returns FALSE when something catastrophic happens. * * Note that the processor, above returning FALSE is not catastrophic. * Things will stop early and return true. */ bool linux_netlink_query(const struct nlmsghdr *nlmsg, int netlink_protocol, linux_netlink_response_processor *processor, struct linux_netlink_context *context, struct verbose); /* * 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 LINUX_NETLINK_BUFSIZE 32768 #endif libreswan-5.2/include/lmod.h000066400000000000000000000031631475767661000161230ustar00rootroot00000000000000/* 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 struct 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); typedef struct { char buf[512]; /* arbitrary */ } lmod_buf; size_t jam_lmod(struct jambuf *buf, const struct enum_names *names, lmod_t mod); const char *str_lmod(const struct enum_names *sd, lmod_t val, lmod_buf *buf); #endif libreswan-5.2/include/logjam.h000066400000000000000000000047311475767661000164430ustar00rootroot00000000000000/* 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. * */ /* * Pair a jambuf with a fixed size buffer plus wrappers to decorate * the output. */ #ifndef LOGJAM_H #define LOGJAM_H #include "lset.h" #include "where.h" #include "jambuf.h" #include "constants.h" /* for enum pluto_exit_code */ struct logger; #define DEBUG_PREFIX "| " #define ERROR_PREFIX "ERROR: " #define PEXPECT_PREFIX "EXPECTATION FAILED: " #define PASSERT_PREFIX "FATAL: ASSERTION FAILED: " #define FATAL_PREFIX "FATAL ERROR: " /*define PRINTF_PREFIX ""*/ #define PEXPECT_FLAGS (PEXPECT_STREAM|RC_INTERNAL_ERROR) #define PASSERT_FLAGS (PASSERT_STREAM|RC_INTERNAL_ERROR) #define PRINTF_FLAGS (NO_PREFIX|WHACK_STREAM) struct logjam { char array[LOG_WIDTH]; struct barf { const struct logger *logger; struct jambuf jambuf; lset_t rc_flags; where_t where; enum pluto_exit_code pluto_exit_code; } barf; }; struct jambuf *jambuf_from_logjam(struct logjam *logjam, const struct logger *logger, enum pluto_exit_code pluto_exit_code, where_t where, lset_t rc_flags) MUST_USE_RESULT; void logjam_to_logger(struct logjam *buf); /* may not return */ #define BARF_JAMBUF(RC_FLAGS, LOGGER, PLUTO_EXIT_CODE, WHERE, BUF) \ /* create the buffer */ \ for (struct logjam logjam_, *bf_ = &logjam_; \ bf_ != NULL; bf_ = NULL) \ /* create the jambuf */ \ for (struct jambuf *BUF = \ jambuf_from_logjam(&logjam_, LOGGER, \ PLUTO_EXIT_CODE, \ WHERE, RC_FLAGS); \ BUF != NULL; \ logjam_to_logger(&logjam_), BUF = NULL) PRINTF_LIKE(5) void barf(lset_t rc_flags, struct logger *logger, enum pluto_exit_code pluto_exit_code, where_t where, const char *fmt, ...); #endif libreswan-5.2/include/lset.h000066400000000000000000000045251475767661000161420ustar00rootroot00000000000000/* 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 #include /* for PRI... */ struct enum_names; struct jambuf; struct sparse_names; /* * 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 "%"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_names *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-5.2/include/lsw-pfkeyv2.h000066400000000000000000000125601475767661000173620ustar00rootroot00000000000000/* Wrapper for , 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 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) completely * 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 /* * OpenBSD's ipsec-interface uses IPSP_DIRECTION_{IN,OUT}, which is * hidden in , to specify the interface's direction * in the sadb_x_ext_iface payload. Why it didn't use values from * PFKEY I don't know. */ #ifdef __OpenBSD__ #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: 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! * * The thing is that, even at the time, IKE daemons were using UDP and * non-standard ports. Things this change seems to prohibit. */ #ifndef __OpenBSD__ #define sadb_address_prefixlen sadb_address_prefixlen #define sadb_address_proto sadb_address_proto #endif /* * Work-around various OSs reusing / renaming fields of existing * structures. * * Use the macro expands to itself hack. */ /* * struct sadb_x_policy * .sadb_x_policy_reserved */ #ifdef __NetBSD__ # ifdef IPSEC_POLICY_FLAG_ORIGIN_KERNEL # define sadb_x_policy_flags sadb_x_policy_flags /* was sadb_x_policy_reserved */ # endif #endif #ifdef __FreeBSD__ # define sadb_x_policy_scope sadb_x_policy_scope /* was sadb_x_policy_reserved */ #endif /* * struct sadb_x_policy * .sadb_x_policy_reserved2 */ #ifdef __linux__ # define sadb_x_policy_priority sadb_x_policy_priority /* was sadb_x_policy_reserved2 */ #endif #ifdef __FreeBSD__ /* define sadb_x_policy_ifindex == sadb_x_policy_priority */ # define sadb_x_policy_priority sadb_x_policy_priority /* was sadb_x_policy_reserved2 */ #endif /* * struct sadb_prop * .sadb_prop_reserved */ #ifdef __OpenBSD__ # define sadb_prop_num sadb_prop_num /* was sadb_prop_reserved */ #endif /* * struct sadb_x_ipsecrequest * .sadb_x_ipsecrequest_reserved1 * .sadb_x_ipsecrequest_reserved2 */ #ifdef __linux__ /* sadb_x_ipsecrequest_reqid is 32-bits not 16-bits; these align it */ # define sadb_x_ipsecrequest_reserved1 sadb_x_ipsecrequest_reserved1 # define sadb_x_ipsecrequest_reserved2 sadb_x_ipsecrequest_reserved2 #endif #endif /* KERNEL_PFKEYV2 */ #endif libreswan-5.2/include/lsw_socket.h000066400000000000000000000015241475767661000173440ustar00rootroot00000000000000/* 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-5.2/include/lswalloc.h000066400000000000000000000113461475767661000170120ustar00rootroot00000000000000/* * 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); /* verify allocation; PTR must be non-NULL */ void pmemory_where(void *ptr, where_t where); #define pmemory(PTR) pmemory_where(PTR, HERE) /* 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 overalloc_thing(THING, EXTRA) \ ((THING*) alloc_bytes(sizeof(THING) + (EXTRA), #THING)) #define alloc_things(THING, COUNT, NAME) \ ((THING*) alloc_bytes(sizeof(THING) * (COUNT), (NAME))) #define overalloc_things(THING, COUNT, EXTRA) \ ((THING*) alloc_bytes(sizeof(THING) * (COUNT) + (EXTRA), #THING"s")) #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_things(ORIG, COUNT, NAME) \ ((__typeof__(&(ORIG[0]))) clone_bytes((ORIG), sizeof((ORIG)[0]) * (COUNT), (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-5.2/include/lswcdefs.h000066400000000000000000000066151475767661000170070ustar00rootroot00000000000000/* 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 #define swap(L,R) \ { \ typeof(L) tmp_ = L; \ L = R; \ R = tmp_; \ } /* * 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 iterate over a list-like structure. */ #define FOR_EACH_ITEM(ENTRY, LIST) \ for (typeof((LIST)->list[0]) *ENTRY = \ (LIST) != NULL ? (LIST)->list : NULL; \ ENTRY != NULL && ENTRY < (LIST)->list + (LIST)->len; \ ENTRY++) #define pfree_list(LIST) { \ typeof(LIST) list_ = LIST; \ pfreeany(list_->list); \ list_->len = 0; \ } /* 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++) /* * 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; \ }) #define is_set(POINTER_TO_THING) ((POINTER_TO_THING) != NULL && (POINTER_TO_THING)->is_set) #define is_unset(POINTER_TO_THING) (!is_set(POINTER_TO_THING)) #endif libreswan-5.2/include/lswconf.h000066400000000000000000000040421475767661000166400ustar00rootroot00000000000000/* 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-5.2/include/lswendian.h000066400000000000000000000037421475767661000171570ustar00rootroot00000000000000/* 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 * These 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-5.2/include/lswglob.h000066400000000000000000000022431475767661000166370ustar00rootroot00000000000000/* 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 struct logger; struct lswglob_context; /* only returns false when no match */ bool lswglob(const char *pattern, const char *what, void (*file)(unsigned count, char **files, struct lswglob_context *, struct logger *logger), struct lswglob_context *context, struct logger *logger); #endif libreswan-5.2/include/lswlog.h000066400000000000000000000346061475767661000165050ustar00rootroot00000000000000/* 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" #include "pexpect.h" #include "fatal.h" /* * 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_LOG = 2, /* message aimed at log (does * not affect exit status) */ RC_SUCCESS = 4, /* success (exit status 0) */ /* entry of secrets */ RC_ENTERSECRET = 10, RC_USERPROMPT = 11, RC_EXIT_FLOOR = 20, /* improper request */ RC_DUPNAME = 20, /* attempt to reuse a connection name */ RC_UNKNOWN_NAME = 21, /* connection name unknown or state number */ RC_ORIENT = 22, /* cannot orient connection: neither end is us */ RC_CLASH = 23, /* clash between two Road Warrior connections OVERLOADED */ RC_DEAF = 24, /* need --listen before --initiate */ RC_ROUTE = 25, /* cannot route */ RC_RTBUSY = 26, /* cannot unroute: route busy */ RC_BADID = 27, /* malformed --id */ RC_NOKEY = 28, /* no key found through DNS */ RC_NOPEERIP = 29, /* cannot initiate when peer IP is unknown */ RC_INITSHUNT = 30, /* cannot initiate a shunt-oly connection */ RC_WILDCARD = 31, /* cannot initiate when ID has wildcards */ RC_CRLERROR = 32, /* CRL fetching disabled or obsolete reread cmd */ RC_WHACK_PROBLEM = 33, /* whack-detected problem */ /* permanent failure */ RC_BADWHACKMESSAGE = 50, RC_NORETRANSMISSION = 51, RC_INTERNAL_ERROR = 52, RC_OPPOFAILURE = 53, /* Opportunism failed */ RC_CRYPTOFAILED = 54, /* system too busy to perform required * cryptographic operations */ RC_AGGRALGO = 55, /* multiple algorithms requested in * phase 1 aggressive */ RC_FATAL = 56, /* fatal error encountered, and * negotiation aborted */ RC_EXIT_ROOF = 100, }; /* * A generic buffer for accumulating unbounded output. * * The buffer's contents can be directed to various logging streams. */ struct jambuf; /* * 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. */ #define RC_MASK 0x00fffff /* rc_type max is 64435+200 */ #define STREAM_MASK 0x0f00000 #define LOG_PREFIX_MASK 0xf000000 enum log_prefix { AUTO_PREFIX = 0x0000000, NO_PREFIX = 0x1000000, ADD_PREFIX = 0x2000000, }; enum stream { /* syslog() */ /* Severity Whack Tools Prefix */ ALL_STREAMS = 0x0000000, /* WARNING yes err? */ LOG_STREAM = 0x0100000, /* WARNING no err? */ WHACK_STREAM = 0x0200000, /* N/A yes err */ DEBUG_STREAM = 0x0300000, /* DEBUG no err | */ ERROR_STREAM = 0x0400000, /* ERR yes err */ PEXPECT_STREAM = 0x0500000, /* ERR yes err EXPECTATION FAILED: */ PASSERT_STREAM = 0x0600000, /* ERR yes err ABORT: ASSERTION_FAILED: */ FATAL_STREAM = 0x0700000, /* ERR yes err FATAL ERROR: */ NO_STREAM = 0x0f00000, /* N/A N/A */ /* * : add prefix when object is available * * | : add both "| " and prefix when object is available and * feature is enabled * * err?: write to stderr when enabled (tests log_to_stderr, * typically via -v). Used by tools such as whack. */ }; /* * 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); }; /* these omit ": " always */ typedef struct { char buf[100];/* completely made up size */ } prefix_buf; const char *str_prefix(const struct logger *logger, prefix_buf *buf); size_t jam_prefix(struct jambuf *buf, const struct logger *logger); /* these include ": " when jam_prefix() is non-empty */ size_t jam_logger_prefix(struct jambuf *buf, const struct logger *logger); void jam_logger_rc_prefix(struct jambuf *buf, const struct logger *logger, lset_t rc_flags); size_t jam_object_prefix_none(struct jambuf *buf, const void *object); #ifndef GLOBAL_LOGGER extern struct logger global_logger; #define GLOBAL_LOGGER &global_logger #endif struct logger { /* support up to two whacks */ struct fd *whackfd[2]; const void *object; const struct logger_object_vec *object_vec; where_t where; /* used by timing to nest its logging output */ int timing_level; lset_t debugging; }; #define PRI_LOGGER "logger@%p/"PRI_FD"/"PRI_FD #define pri_logger(LOGGER) \ (LOGGER), \ pri_fd((LOGGER) == NULL ? NULL : (LOGGER)->whackfd[0]), \ pri_fd((LOGGER) == NULL ? NULL : (LOGGER)->whackfd[1]) 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) \ /* create the buffer */ \ for (struct logjam logjam_, *lbp_ = &logjam_; \ lbp_ != NULL; lbp_ = NULL) \ /* create the jambuf */ \ for (struct jambuf *BUF = \ jambuf_from_logjam(&logjam_, LOGGER, \ 0, NULL, RC_FLAGS); \ BUF != NULL; \ logjam_to_logger(&logjam_), 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(const 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 and/or ": " separator */ void llog_errno(lset_t rc_flags, const struct logger *logger, int error, const char *message, ...) PRINTF_LIKE(4); /* * 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 preprocessor * as macro argument separators. This happens accidentally if * multiple variables are declared in one declaration. * * Naming: All DBG_*() prefixed functions send stuff to the debug * stream unconditionally. Hence they should be wrapped in DBGP(). */ extern lset_t cur_debugging; /* current debugging level */ #define DBGP(cond) (cur_debugging & (cond)) #define LDBGP(COND, LOGGER) (COND & (cur_debugging | (LOGGER)->debugging)) #define dbg(MESSAGE, ...) \ { \ if (DBGP(DBG_BASE)) { \ DBG_log(MESSAGE, ##__VA_ARGS__); \ } \ } void ldbg(const struct logger *logger, const char *message, ...) PRINTF_LIKE(2); void pdbg(const struct logger *logger, const char *message, ...) PRINTF_LIKE(2); void ldbgf(lset_t cond, const struct logger *logger, const char *fmt, ...) PRINTF_LIKE(3); void pdbgf(lset_t cond, const struct logger *logger, const char *fmt, ...) PRINTF_LIKE(3); /* LDBG_JAMBUF() is ambiguous - LDBG_op() or ldbg() ucase? */ #define LDBGP_JAMBUF(COND, LOGGER, BUF) \ for (bool cond_ = LDBGP(COND, LOGGER); cond_; cond_ = false) \ LLOG_JAMBUF(DEBUG_STREAM, LOGGER, BUF) #define PDBGP_JAMBUF(COND, LOGGER, BUF) \ for (bool cond_ = LDBGP(COND, LOGGER); cond_; cond_ = false) \ LLOG_JAMBUF(DEBUG_STREAM|ADD_PREFIX, LOGGER, BUF) /* DBG_*() are unconditional */ void DBG_log(const char *message, ...) PRINTF_LIKE(1); void DBG_dump(const char *label, const void *p, size_t len); #define DBG_dump_hunk(LABEL, HUNK) \ { \ 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)) /* * XXX: unlike dbg_dump() et.al., these don't take a prefix; instead * caller should log that separately. */ #define LDBG_dump(LOGGER, DATA, LEN) \ { \ llog_dump(DEBUG_STREAM, LOGGER, DATA, LEN); \ } #define LDBG_hunk(LOGGER, HUNK) \ { \ const typeof(HUNK) *hunk_ = &(HUNK); /* evaluate once */ \ llog_dump(DEBUG_STREAM, LOGGER, hunk_->ptr, hunk_->len); \ } #define LDBG_thing(LOGGER, THING) \ { \ llog_dump(DEBUG_STREAM, LOGGER, &(THING), sizeof(THING)); \ } #define ldbg_dump(LOGGER, DATA, LEN) \ { \ if (DBGP(DBG_BASE)) { \ LDBG_dump(LOGGER, DATA, LEN); \ } \ } #define ldbg_hunk(LOGGER, HUNK) \ { \ if (DBGP(DBG_BASE)) { \ LDBG_hunk(LOGGER, HUNK); \ } \ } #define ldbg_thing(LOGGER, THING) \ { \ if (DBGP(DBG_BASE)) { \ LDBG_thing(LOGGER, THING); \ } \ } /* LDBG_*(logger, ...) are unconditional wrappers */ #define LDBG_log(LOGGER, FMT, ...) llog(DEBUG_STREAM, LOGGER, FMT, ##__VA_ARGS__) #define LDBG_va_list(LOGGER, FMT, AP) llog_va_list(DEBUG_STREAM, LOGGER, FMT, AP) /* * 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 /* * For a switch statements */ void bad_case_where(const char *expression, long value, where_t where) NEVER_RETURNS; #define bad_case(N) bad_case_where(#N, (N), HERE) void bad_enum_where(const struct logger *logger, const struct enum_names *en, unsigned long val, where_t where) NEVER_RETURNS; #define bad_enum(LOGGER, ENUM_NAMES, VALUE) bad_enum_where(LOGGER, ENUM_NAMES, VALUE, HERE) void bad_sparse_where(const struct logger *logger, const struct sparse_names *sn, unsigned long val, where_t where) NEVER_RETURNS; #define bad_sparse(LOGGER, SPARSE_NAMES, VALUE) bad_sparse_where(LOGGER, SPARSE_NAMES, VALUE, 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-5.2/include/lswnss.h000066400000000000000000000067011475767661000165220ustar00rootroot00000000000000/* * 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" struct nss_flags { bool open_readonly; /* * Should shutdown call PR_CLEANUP. */ bool skip_pr_cleanup; }; /* * If something goes wrong, fatal(PLUTO_EXIT_FAIL, logger, ...) is called. */ void init_nss(const char *config_dir, struct nss_flags flags, struct logger *logger); void shutdown_nss(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_ckg(struct jambuf *buf, CK_GENERATOR_FUNCTION generate); 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-5.2/include/lswsd.h000066400000000000000000000012501475767661000163170ustar00rootroot00000000000000/* SPDX-License-Identifier: MIT-0 */ /* Implement the systemd notify protocol without external dependencies. * Supports both readiness notification on startup and on reloading, * according to the protocol defined at: * https://www.freedesktop.org/software/systemd/man/latest/sd_notify.html * This protocol is guaranteed to be stable as per: * https://systemd.io/PORTABILITY_AND_STABILITY/ */ #ifndef LSWSYSTEMD_H #include /* for uint64_t */ #include "lswcdefs.h" /* for PRINTF_LIKE */ extern int lswsd_watchdog_enabled(uintmax_t *usecs); extern int lswsd_notify(const char *string); extern int lswsd_notifyf(const char *string, ...) PRINTF_LIKE(1); #endif libreswan-5.2/include/lswseccomp.h000066400000000000000000000031431475767661000173450ustar00rootroot00000000000000/* * 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 /* rpm:libseccomp-devel */ #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-5.2/include/lswtool.h000066400000000000000000000004211475767661000166650ustar00rootroot00000000000000#include /* * For stand-alone tools. * * XXX: can "progname" be made private to lswlog.c? */ struct logger; extern const char *progname; struct logger *tool_logger(int argc, char *argv[]); extern bool log_to_stderr; /* should log go to stderr? */ libreswan-5.2/include/lswversion.h000066400000000000000000000020421475767661000173760ustar00rootroot00000000000000/* * 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-5.2/include/message_role.h000066400000000000000000000040271475767661000176350ustar00rootroot00000000000000/* message role, for libreswan * * 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. * */ #ifndef MESSAGE_ROLE_H #define MESSAGE_ROLE_H /* * 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 { #define MESSAGE_ROLE_FLOOR NO_MESSAGE NO_MESSAGE = 0, MESSAGE_REQUEST = 1, /* MSG_R missing */ MESSAGE_RESPONSE = 2, /* MSR_R present */ #define MESSAGE_ROLE_ROOF (MESSAGE_RESPONSE+1) }; extern const struct enum_names message_role_names; #endif libreswan-5.2/include/monotime.h000066400000000000000000000050471475767661000170220ustar00rootroot00000000000000/* monotonic time object and functions, for libreswan * * Copyright (C) 1998, 1999, 2000 Henry Spencer. * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs * Copyright (C) 2017-2019 Andrew Cagney * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. * */ #ifndef MONOTIME_H #define MONOTIME_H /* seen it, no need to see it again */ #include /* for struct timeval */ #include /* for bool */ #include "deltatime.h" /* * The time objects are wrapped so that dimensional analysis will be * enforced by the compiler. */ /* * monotime_t: absolute monotonic time. No discontinuities (except * for machine sleep?) * * - various clocks can jump backwards on UNIX/LINUX; for instance * when the machine's UTC clock is corrected * * - this causes all kinds of problems with timeouts observable in the * Real World * * - this code detects backward jumps and compensates by refusing to * go backwards * * - unfortunately there is no way to detect forward jumps * */ typedef struct { struct timeval mt; } monotime_t; monotime_t monotime(intmax_t seconds); #define MONOTIME_EPOCH { { 0, 0 } } extern const monotime_t monotime_epoch; bool is_monotime_epoch(monotime_t t); monotime_t mononow(void); monotime_t monotime_max(monotime_t l, monotime_t r); monotime_t monotime_min(monotime_t l, monotime_t r); monotime_t monotime_add(monotime_t l, deltatime_t r); monotime_t monotime_sub(monotime_t l, deltatime_t r); deltatime_t monotime_diff(monotime_t l, monotime_t r); /* 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) intmax_t monosecs(monotime_t m); /* for pthread_cond_timedwait() */ clockid_t monotime_clockid(void); 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-5.2/include/names.h000066400000000000000000000016501475767661000162720ustar00rootroot00000000000000/* enums as names, for libreswan * * Copyright (C) 2025 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT 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 NAMES_H #define NAMES_H struct jambuf; typedef struct name_buf { const char *buf; char tmp[((sizeof(unsigned long) * 241 + 99) / 100)*2 + sizeof("_??")]; } name_buf; void bad_name(unsigned long val, name_buf *b); size_t jam_bad(struct jambuf *buf, const char *prefix, unsigned long val); #endif libreswan-5.2/include/names_constant.h000066400000000000000000000063051475767661000202050ustar00rootroot00000000000000#ifndef NAMES_CONSTANT_H #define NAMES_CONSTANT_H /* * names_constant.h */ #include extern enum_names ip_protocol_id_names; /* aka ipproto_*; in ip_protocol.c */ #ifdef KERNEL_XFRM extern enum_names xfrm_policy_names; /* #ifdef KERNEL_XFRM */ #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; /* SHUNT_... */ extern enum_names shunt_policy_percent_names; /* %... */ extern enum_names connection_kind_names; extern enum_names certpolicy_type_names; extern enum_names oakley_attr_names; extern enum_names oakley_attr_bit_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_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; 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[]; #endif libreswan-5.2/include/netlink_attrib.h000066400000000000000000000040231475767661000201750ustar00rootroot00000000000000#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); void nl_addattr16(struct nlmsghdr *n, int maxlen, int type, const uint16_t data); void nl_addattr8(struct nlmsghdr *n, int maxlen, int type, const uint8_t data); const struct nlattr *nl_getattr(const struct nlmsghdr *n, size_t *offset); const char *nl_getattrvalstrz(const struct nlmsghdr *n, const struct nlattr *attr); #endif libreswan-5.2/include/nss_cert_load.h000066400000000000000000000021351475767661000200050ustar00rootroot00000000000000/* * 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-5.2/include/oid.h000066400000000000000000000032111475767661000157350ustar00rootroot00000000000000/* * 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-5.2/include/optarg.h000066400000000000000000000043661475767661000164720ustar00rootroot00000000000000/* getopt parsing, for libreswan * * Copyright (C) 2023,2024 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT 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 OPTARG_H #include #include "deltatime.h" #include "ip_address.h" #include "ip_cidr.h" #include "lmod.h" struct logger; extern unsigned verbose; /* defined by optarg.c */ extern int optarg_index; /* defined by optarg.c */ extern const struct option optarg_options[]; /* defined by program */ enum timescale; void optarg_init(const struct logger *logger); deltatime_t optarg_deltatime(enum timescale default_timescale); uintmax_t optarg_uintmax(void); /* non-zero OPTIONAL provides default */ uintmax_t optarg_sparse(unsigned optional, const struct sparse_names *names); /* * Adddres family dependent options. * * The struct keeps track of the selected value and which param * used/specified it so it can be logged when a conflict occures. */ struct optarg_family { const char *used_by; const struct ip_info *type; }; ip_address optarg_address_dns(struct optarg_family *); ip_cidr optarg_cidr_num(struct optarg_family *); void optarg_family(struct optarg_family *family, const struct ip_info *info); ip_address optarg_any(struct optarg_family *family); /* * Call optarg_verbose() whenever --verbose is encountered. * * Each call increments VERBOSE. * * When VERBOSE>=2 it also adds increasingly verbose debugging to * CUR_DEBUGGING. As verbose increases, START (if non-LEMPTY), * DBG_BASE, DBG_ALL and DBG_TMI are each added in turn. */ void optarg_verbose(lset_t start); /* * parse --debug and --no-debug options * * First variant updates CUR_DEBUGGING; second maintains a set of * updates - see whack.c. */ void optarg_debug(bool enable); void optarg_debug_lmod(bool enable, lmod_t *debugging); #endif libreswan-5.2/include/passert.h000066400000000000000000000055611475767661000166550ustar00rootroot00000000000000/* * 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" #include "lset.h" #include "logjam.h" struct logger; /* our versions of assert: log result */ /* * Preferred: can log with prefix to whack from a thread. */ #ifndef GLOBAL_LOGGER extern struct logger global_logger; #define GLOBAL_LOGGER &global_logger #endif /* * XXX: GCC, at least can't understand that LLOG_PASSERT_JAMBUF() * never returns. Hence code sometimes calls * passert_jambuf_to_logger() explicitly. */ extern void llog_passert(const struct logger *logger, where_t where, const char *message, ...) NEVER_RETURNS PRINTF_LIKE(3); void passert_logjam_to_logger(struct logjam *buf) NEVER_RETURNS; #define LLOG_PASSERT_JAMBUF(LOGGER, WHERE, BUF) \ /* create the buffer */ \ for (struct logjam logjam_, *bf_ = &logjam_; \ bf_ != NULL; bf_ = NULL) \ /* create the jambuf */ \ for (struct jambuf *BUF = \ jambuf_from_logjam(&logjam_, LOGGER, \ 0, WHERE, PASSERT_FLAGS); \ BUF != NULL; \ passert_logjam_to_logger(&logjam_), BUF = NULL) #define PASSERT_WHERE(LOGGER, WHERE, ASSERTION) \ ({ \ /* wrapping ASSERTION in parens suppresses -Wparen */ \ bool assertion__ = ASSERTION; /* no parens */ \ if (!assertion__) { \ const struct logger *logger_ = LOGGER; \ llog_passert(logger_, WHERE, "%s", #ASSERTION); \ } \ /* return something so flipping to pexpect() is easy */ \ (void) true; \ }) #define PASSERT(LOGGER, ASSERTION) \ PASSERT_WHERE(LOGGER, HERE, ASSERTION) #define passert(ASSERTION) \ PASSERT_WHERE(&global_logger, HERE, 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-5.2/include/pexpect.h000066400000000000000000000057371475767661000166510ustar00rootroot00000000000000/* 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 PEXPECT_H #define PEXPECT_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" #include "logjam.h" struct jambuf; /* * 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. */ extern void llog_pexpect(const struct logger *logger, where_t where, const char *message, ...) PRINTF_LIKE(3); #define LLOG_PEXPECT_JAMBUF(LOGGER, WHERE, BUF) \ /* create the buffer */ \ for (struct logjam logjam_, *lbp_ = &logjam_; \ lbp_ != NULL; lbp_ = NULL) \ /* create the jambuf */ \ for (struct jambuf *BUF = \ jambuf_from_logjam(&logjam_, LOGGER, \ 0, WHERE, PEXPECT_FLAGS); \ BUF != NULL; \ logjam_to_logger(&logjam_), BUF = NULL) #define PEXPECT_WHERE(LOGGER, WHERE, ASSERTION) \ ({ \ /* wrapping ASSERTION in parens suppresses -Wparen */ \ bool assertion__ = ASSERTION; /* no parens */ \ if (!assertion__) { \ const struct logger *logger_ = LOGGER; \ llog_pexpect(logger_, WHERE, "%s", #ASSERTION); \ } \ assertion__; /* result */ \ }) #define PEXPECT(LOGGER, ASSERTION) \ PEXPECT_WHERE(LOGGER, HERE, ASSERTION) #define PBAD_WHERE(LOGGER, WHERE, BAD) \ ({ \ /* wrapping BAD in parens suppresses -Wparen */ \ bool bad_ = BAD; /* no parens */ \ if (bad_) { \ const struct logger *logger_ = LOGGER; \ llog_pexpect(logger_, WHERE, "not (%s)", #BAD); \ } \ bad_; /* result */ \ }) #define PBAD(LOGGER, BAD) PBAD_WHERE(LOGGER, HERE, BAD) #define pbad(BAD) PBAD_WHERE(&global_logger, HERE, BAD) #define pexpect(ASSERTION) PEXPECT_WHERE(&global_logger, HERE, ASSERTION) #endif libreswan-5.2/include/pluto_constants.h000066400000000000000000000771021475767661000204330ustar00rootroot00000000000000/* 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 * Copyright (C) 2020 Nupur Agrawal * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT 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_CONSTANTS_H #define PLUTO_CONSTANTS_H #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 #define DEFAULT_UPDOWN "ipsec _updown" #define UPDOWN_DISABLED "%disabled" # 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 deltatime(secs_per_hour * 8) #define IKE_SA_LIFETIME_MAXIMUM deltatime(secs_per_day) #define FIPS_IKE_SA_LIFETIME_MAXIMUM deltatime(secs_per_day) #define IPSEC_SA_LIFETIME_DEFAULT deltatime(secs_per_hour * 8) #define IPSEC_SA_LIFETIME_MAXIMUM deltatime(secs_per_day) #define FIPS_IPSEC_SA_LIFETIME_MAXIMUM deltatime(secs_per_hour * 8) #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_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 IKE_BUF_AUTO 0 /* use system values for IKE socket buffer size */ #define DEFAULT_XFRM_IF_NAME "ipsec1" enum send_ca_policy { CA_SEND_NONE = 0, CA_SEND_ISSUER = 1, CA_SEND_ALL = 2, }; /* values for auto={add,start,{route,ondemand},ignore} */ enum autostart { AUTOSTART_UNSET, AUTOSTART_IGNORE, AUTOSTART_ADD, AUTOSTART_START, AUTOSTART_ROUTE, AUTOSTART_ONDEMAND, AUTOSTART_UP, AUTOSTART_KEEP, }; extern const struct sparse_names autostart_names; /* Cisco interop: values remote_peer_type= */ enum keyword_remote_peer_type { REMOTE_PEER_UNSET = 0, REMOTE_PEER_CISCO, }; 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. */ 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, }; /* Timer events */ /* * Timer events not associated with states (aka global * timers). */ extern const struct enum_names global_timer_names; enum global_timer { #define GLOBAL_TIMER_FLOOR 0 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_CHECK_CRLS, /* check/update CRLS */ 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) #define GLOBAL_TIMER_ROOF (EVENT_RESET_LOG_LIMITER+1) }; /* * Connection based events. */ enum connection_event_kind { CONNECTION_REVIVAL = 1, }; #define CONNECTION_EVENT_KIND_ROOF (CONNECTION_REVIVAL+1) extern const struct enum_names connection_event_kind_names; /* * 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 */ /* * For IKEv2 'replace' is really either a re-key a full * replace, or expire. IKEv1 should be the same but isn't. */ #define EVENT_v1_FLOOR EVENT_v1_SEND_XAUTH 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_EXPIRE, /* v1 SA expiration event */ EVENT_v1_DISCARD, /* v1 discard unfinished state object */ EVENT_v1_RETRANSMIT, EVENT_v1_CRYPTO_TIMEOUT, /* v1 after some time, give up on crypto helper */ EVENT_v1_NAT_KEEPALIVE, EVENT_v1_REPLACE, /* v1 replacement event */ #define EVENT_v1_ROOF (EVENT_v1_REPLACE+1) #define EVENT_v2_FLOOR EVENT_v2_REKEY EVENT_v2_REKEY, /* SA rekey event */ EVENT_v2_REPLACE, /* v2 IKE/Child SA replacement event */ EVENT_v2_EXPIRE, /* v2 SA expiration (drop-dead) event */ EVENT_v2_DISCARD, /* v2 discard unfinished state object */ EVENT_v2_TIMEOUT_INITIATOR, EVENT_v2_TIMEOUT_RESPONDER, EVENT_v2_TIMEOUT_RESPONSE, EVENT_v2_LIVENESS, /* v2 for dead peer detection */ EVENT_v2_RETRANSMIT, EVENT_v2_NAT_KEEPALIVE, EVENT_v2_ADDR_CHANGE, /* process IP address deletion */ #define EVENT_v2_ROOF (EVENT_v2_ADDR_CHANGE+1) 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 deltatime(5) /* seconds */ #define REVIVE_CONN_DELAY_MAX deltatime(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 SEND */ STF_IGNORE, /* no no no */ STF_SUSPEND, /* suspend no no */ STF_OK, /* yes no response? */ STF_OK_INITIATOR_DELETE_IKE, /* yes yes no */ STF_OK_INITIATOR_SEND_DELETE_IKE, /* yes yes request */ STF_OK_RESPONDER_DELETE_IKE, /* yes yes response? */ STF_INTERNAL_ERROR, /* no no never? */ STF_FATAL, /* no yes never */ STF_FAIL_v1N, /* no maybe? response? */ #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, DBG_ROUTING_IX, DBG_base_IX = DBG_ROUTING_IX, /* below are also enabled by debug=all */ DBG_CPU_USAGE_IX, DBG_REFCNT_IX, DBG_all_IX = DBG_REFCNT_IX, /* below are also enabled by debug=tmi */ DBG_TMI_IX, DBG_tmi_IX = DBG_TMI_IX, /* below are excluded */ DBG_UPDOWN_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 LEMPTY /* no options on, including impairments */ #define DBG_BASE LELEM(DBG_BASE_IX) #define DBG_ROUTING LELEM(DBG_ROUTING_IX) #define DBG_CPU_USAGE LELEM(DBG_CPU_USAGE_IX) #define DBG_REFCNT LELEM(DBG_REFCNT_IX) #define DBG_ALL LRANGE(DBG_floor_IX, DBG_all_IX) #define DBG_TMI LELEM(DBG_TMI_IX) #define DBG_CRYPT LELEM(DBG_CRYPT_IX) #define DBG_PRIVATE LELEM(DBG_PRIVATE_IX) #define DBG_UPDOWN LELEM(DBG_UPDOWN_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_SERVER_WAITING_FOR_ACK, /* server initiated * SET, waiting for * ACK */ STATE_MODE_CFG_CLIENT_RESPONDING, /* non-pullclient got * a likely request */ 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. */ /* IKE SA */ #define STATE_IKEv2_FLOOR (STATE_V2_UNSECURED_R) STATE_V2_UNSECURED_R, STATE_V2_IKE_SA_INIT_I0, /* waiting for KE to finish */ STATE_V2_IKE_SA_INIT_I, /* Initiator sent Request */ STATE_V2_IKE_SA_INIT_R, /* Responder send Response */ STATE_V2_IKE_SA_INIT_IR, /* Initiator processed Response */ STATE_V2_IKE_INTERMEDIATE_I, STATE_V2_IKE_INTERMEDIATE_R, STATE_V2_IKE_INTERMEDIATE_IR, STATE_V2_IKE_SESSION_RESUME_I0, STATE_V2_IKE_SESSION_RESUME_I, STATE_V2_IKE_SESSION_RESUME_R0, STATE_V2_IKE_SESSION_RESUME_R, STATE_V2_IKE_SESSION_RESUME_IR, STATE_V2_IKE_AUTH_EAP_R, /* IKE_AUTH EAP negotiation */ STATE_V2_IKE_AUTH_I, /* IKE_AUTH: sent auth message, waiting for reply */ /* IKEv2 CREATE_CHILD_SA Initiator states */ STATE_V2_NEW_CHILD_I0, /* larval: sent nothing yet */ STATE_V2_NEW_CHILD_R0, /* 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_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, /* * (unimplemented) after a state is deleted it can lurk for a * while so that it still responds to retransmits and ignores * responses. */ STATE_V2_ZOMBIE, 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; #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) | \ LELEM(STATE_MODE_CFG_CLIENT_RESPONDING)) #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_SERVER_WAITING_FOR_ACK) | \ LELEM(STATE_MODE_CFG_R0) | \ LELEM(STATE_MODE_CFG_R1) | \ LELEM(STATE_MODE_CFG_R2) | \ LELEM(STATE_MODE_CFG_I1) | \ LELEM(STATE_MODE_CFG_CLIENT_RESPONDING) | \ 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_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_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_IKE_SA_INIT_I0) | \ LELEM(STATE_V2_IKE_SA_INIT_I) | \ LELEM(STATE_V2_IKE_AUTH_I)) /* 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) #define IS_PARENT_SA(ST) ((ST)->st_clonedfrom == SOS_NOBODY) /* IKEv1 or IKEv2 */ #define IS_PARENT_SA_ESTABLISHED(ST) (IS_IKE_SA_ESTABLISHED(ST) || IS_ISAKMP_SA_ESTABLISHED(ST)) /* * Kind of struct connection * * Ordered (mostly) by concreteness. Order is exploited (for * instance, when listing connections the kind is used as the second * sort key after name but before instance number which means that * templates are grouped, followed by their instances, weird). */ enum connection_kind { CK_INVALID = 0, /* better name? */ CK_GROUP, /* policy group: instantiates to CK_TEMPLATE+POLICY_GROUPINSTANCE */ CK_TEMPLATE, /* abstract connection, with wildcard */ CK_PERMANENT, /* normal connection */ CK_INSTANCE, /* instance of template, created for a * particular attempt */ CK_LABELED_TEMPLATE, /* labels are in their own little world */ CK_LABELED_PARENT, CK_LABELED_CHILD, #define CONNECTION_KIND_ROOF (CK_LABELED_CHILD+1) }; 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 = 1, /* the default */ NATT_RFC = 2, NATT_DRAFTS = 3, /* Workaround for Cisco NAT-T bug */ NATT_NONE = 4 /* Workaround for forcing non-encaps */ }; extern const struct sparse_names nat_ikev1_method_option_names; enum nppi_options { NPPI_UNSET = 0, NPPI_NEVER, /* do not propose, do not permit */ NPPI_PERMIT, /* do not propose, but permit peer to propose */ NPPI_PROPOSE, /* propose, and permit, but do not insist */ NPPI_INSIST /* propose, and only accept if peer agrees */ }; extern const struct sparse_names nppi_option_names; enum ynf_options { YNF_UNSET = 0, YNF_YES, YNF_NO, YNF_FORCE, }; extern const struct sparse_names ynf_option_names; enum yn_options { YN_UNSET = 0, YN_NO = 1, YN_YES = 2, }; /* includes things like 0/1 */ extern const struct sparse_names yn_option_names; /* excludes 0/1 */ extern const struct sparse_names yn_text_option_names; enum yna_options { YNA_UNSET = 0, YNA_AUTO = 1, /* default?!? */ YNA_NO = 2, YNA_YES = 3, }; extern const struct sparse_names yna_option_names; enum yne_options { YNE_UNSET, YNE_NO, YNE_YES, YNE_EITHER, }; extern const struct sparse_names yne_option_names; enum tcp_options { IKE_TCP_NO = 1, IKE_TCP_ONLY = 2, IKE_TCP_FALLBACK = 3, }; extern const struct sparse_names tcp_option_names; /* "no", "yes", "fallback" */ enum eap_options { IKE_EAP_NONE = 0, /* default */ IKE_EAP_TLS = 1, }; enum nic_offload_options { NIC_OFFLOAD_UNSET = 0, NIC_OFFLOAD_NO, /* default */ NIC_OFFLOAD_CRYPTO, NIC_OFFLOAD_PACKET, }; extern const struct sparse_names nic_offload_option_names; /* * 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 exhaustively defined as macros. As are derived values. */ enum shunt_policy { SHUNT_UNSET, SHUNT_IPSEC, /* only valid with KIND IPSEC */ 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 shunt_kind { #define SHUNT_KIND_FLOOR 0 SHUNT_KIND_NONE, SHUNT_KIND_NEVER_NEGOTIATE, SHUNT_KIND_ONDEMAND, /* always SHUNT_TRAP */ SHUNT_KIND_NEGOTIATION, SHUNT_KIND_IPSEC, /* always SHUNT_IPSEC */ SHUNT_KIND_FAILURE, SHUNT_KIND_BLOCK, /* always SHUNT_DROP */ #define never_negotiate_shunt shunt[SHUNT_KIND_NEVER_NEGOTIATE] #define negotiation_shunt shunt[SHUNT_KIND_NEGOTIATION] /* during */ #define failure_shunt shunt[SHUNT_KIND_FAILURE] /* after */ #define SHUNT_KIND_ROOF (SHUNT_KIND_BLOCK+1) }; extern const struct enum_names shunt_kind_names; enum sa_policy_bits { POLICY_COMPRESS_IX, /* must be third */ POLICY_TUNNEL_IX, #define POLICY_IX_LAST POLICY_TUNNEL_IX }; #define POLICY_COMPRESS LELEM(POLICY_COMPRESS_IX) /* must be third */ #define POLICY_TUNNEL LELEM(POLICY_TUNNEL_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); /* * 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, }; enum type_options { KS_UNSET, KS_TUNNEL, KS_TRANSPORT, KS_PASSTHROUGH, KS_DROP, KS_REJECT, }; extern const struct sparse_names type_option_names; /* * 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_RESERVED_12, /* was PLUTO_EXIT_LEAVE_STATE = 12 */ /**/ 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 { SA_SOFT_EXPIRED, SA_HARD_EXPIRED, #define SA_EXPIRE_KIND_ROOF (SA_HARD_EXPIRED+1) }; #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) #endif libreswan-5.2/include/proposals.h000066400000000000000000000202671475767661000172160ustar00rootroot00000000000000/* 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" #include "fips_mode.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; 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. * * Code needs FIPS and non-FIPS variants. */ const char *proposals[FIPS_MODE_ROOF]; /* * 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 alg_id; const struct proposal_defaults *defaults; /* * 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-5.2/include/realtime.h000066400000000000000000000051411475767661000167700ustar00rootroot00000000000000/* 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); diag_t ttorealtime(const char *time, realtime_t *rt); /* * 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 */ bool is_realtime_epoch(realtime_t t); realtime_t realtime_add(realtime_t r, deltatime_t d); realtime_t realtime_sub(realtime_t r, deltatime_t d); deltatime_t realtime_diff(realtime_t l, realtime_t r); /* 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) 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); #endif libreswan-5.2/include/refcnt.h000066400000000000000000000105751475767661000164560ustar00rootroot00000000000000/* 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 "lswcdefs.h" /* for MUST_USE_RESULT */ #include "where.h" struct logger; struct refcnt_base { const char *what; }; typedef struct refcnt { volatile unsigned count; const struct refcnt_base *base; } refcnt_t; /* * Allocate the structure (plus extra) initializing the refcnt. * * On return the object has a reference count of one and all other * fields are zero. * * Note: any over-allocated memory is _NOT_ aligned. */ void refcnt_init(const void *pointer, struct refcnt *refcnt, const struct refcnt_base *base, where_t where); #define refcnt_overalloc(THING, EXTRA, WHERE) \ ({ \ static const struct refcnt_base b_ = { \ .what = #THING, \ }; \ THING *t_ = overalloc_thing(THING, EXTRA); \ refcnt_init(t_, &t_->refcnt, &b_, WHERE); \ t_; \ }) #define refcnt_alloc(THING, WHERE) \ refcnt_overalloc(THING, /*extra*/0, WHERE) /* look at refcnt atomically */ unsigned refcnt_peek_where(const void *pointer, const refcnt_t *refcnt, const struct logger *owner, where_t where); #define refcnt_peek(OBJ, OWNER) \ ({ \ typeof(OBJ) o_ = OBJ; /* evaluate once */ \ (o_ == NULL ? 0 : /* a NULL pointer has no references */ \ refcnt_peek_where(o_, &o_->refcnt, OWNER, HERE)); \ }) /* * Add a reference. */ void refcnt_addref_where(const char *what, const void *pointer, refcnt_t *refcnt, const struct logger *logger, const struct logger *new_owner, where_t where); /* old */ #define addref_where(OBJ, WHERE) \ ({ \ typeof(OBJ) o_ = OBJ; /* evaluate once */ \ if (o_ != NULL) { \ refcnt_addref_where(#OBJ, o_, \ &o_->refcnt, \ NULL, NULL, WHERE); \ } \ o_; /* result */ \ }) /* new */ #define laddref_where(OBJ, OWNER, WHERE) \ ({ \ typeof(OBJ) o_ = OBJ; /* evaluate once */ \ if (o_ != NULL) { \ refcnt_addref_where(#OBJ, o_, \ &o_->refcnt, \ o_->logger, \ OWNER, WHERE); \ } \ o_; /* result */ \ }) /* * Delete a reference. * * Returns a non-NULL pointer to the object when it is the last * reference and needs to be pfree()ed. */ void *refcnt_delref_where(const char *what, void *pointer, struct refcnt *refcnt, const struct logger *logger, const struct logger *owner, where_t where) MUST_USE_RESULT; #define delref_where(OBJP, LOGGER, WHERE) \ ({ \ typeof(OBJP) op_ = OBJP; \ typeof(*OBJP) o_ = *op_; \ *op_ = NULL; /* always kill pointer; and early */ \ if (o_ != NULL) { \ o_ = refcnt_delref_where(#OBJP, o_, \ &o_->refcnt, \ LOGGER, NULL, WHERE); \ } \ o_; /* NULL or last OBJ */ \ }) #define ldelref_where(OBJP, OWNER, WHERE) \ ({ \ typeof(OBJP) op_ = OBJP; \ typeof(*OBJP) o_ = *op_; \ *op_ = NULL; /* always kill pointer; and early */ \ if (o_ != NULL) { \ o_ = refcnt_delref_where(#OBJP, o_, \ &o_->refcnt, \ o_->logger, \ OWNER, WHERE); \ } \ o_; /* NULL or last OBJ */ \ }) /* * For code wanting to use refcnt checks but with normal allocs. */ void ldbg_alloc(const struct logger *logger, const char *what, const void *pointer, where_t where); void ldbg_free(const struct logger *logger, const char *what, const void *pointer, where_t where); void ldbg_addref_where(const struct logger *logger, const char *what, const void *pointer, where_t where); void ldbg_delref_where(const struct logger *logger, const char *what, const void *pointer, where_t where); 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-5.2/include/reqid.h000066400000000000000000000033531475767661000162750ustar00rootroot00000000000000/* 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 PRI_REQID "%"PRIu32 #define pri_reqid(ID) ID #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-5.2/include/rnd.h000066400000000000000000000020061475767661000157460ustar00rootroot00000000000000/* 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(void); extern chunk_t alloc_rnd_chunk(size_t size, const char *name); #endif libreswan-5.2/include/sa_role.h000066400000000000000000000037251475767661000166200ustar00rootroot00000000000000/* 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. * */ #ifndef SA_ROLE_H #define SA_ROLE_H /* * 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 { #define SA_ROLE_FLOOR SA_INITIATOR SA_INITIATOR = 1, SA_RESPONDER = 2, #define SA_ROLE_ROOF (SA_RESPONDER+1) }; extern const struct enum_names sa_role_names; #endif libreswan-5.2/include/sa_type.h000066400000000000000000000014731475767661000166360ustar00rootroot00000000000000/* SA type, 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 SA_TYPE_H #define SA_TYPE_H enum sa_type { #define SA_TYPE_FLOOR 0 IKE_SA = SA_TYPE_FLOOR, CHILD_SA, #define SA_TYPE_ROOF (CHILD_SA+1) }; extern const struct enum_names sa_type_names; #endif libreswan-5.2/include/scale.h000066400000000000000000000025451475767661000162620ustar00rootroot00000000000000/* scale, for libreswan * * Copyright (C) 2024 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 SCALE_H #define SCALE_H #include /* for uintmax_t */ #include "shunk.h" struct jambuf; struct scale { const char *suffix; uintmax_t multiplier; }; /* for debugging */ #define PRI_SCALE "1%s(%juu)" #define pri_scale(TS) (TS)->suffix, (TS)->multiplier struct scales { uintmax_t base; struct { const struct scale *list; unsigned len; } scale; }; const struct scale *ttoscale(shunk_t cursor, const struct scales *scales, unsigned default_scale); err_t scale_decimal(const struct scale *scale, uintmax_t decimal, uintmax_t numerator, uintmax_t denominator, uintmax_t *value); size_t jam_decimal(struct jambuf *buf, uintmax_t decimal, uintmax_t numerator, uintmax_t denominator); #endif libreswan-5.2/include/secrets.h000066400000000000000000000234151475767661000166420ustar00rootroot00000000000000/* 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 "refcnt.h" #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, }; /* * Pre-shared Secrets, and XAUTH stuff. */ struct secret_preshared_stuff { size_t len; uint8_t ptr[]; }; const struct secret_preshared_stuff *secret_preshared_stuff(const struct secret *); /* * PKI or raw public/private keys. */ struct secret_pubkey_stuff { struct refcnt refcnt; SECKEYPrivateKey *private_key; struct pubkey_content content; }; struct secret_pubkey_stuff *secret_pubkey_stuff(const struct secret *s); struct secret_pubkey_stuff *secret_pubkey_stuff_addref(struct secret_pubkey_stuff *, where_t where); void secret_pubkey_stuff_delref(struct secret_pubkey_stuff **, where_t where); /* * PPK */ struct secret_ppk_stuff { shunk_t key; chunk_t id; uint8_t data[]; }; const struct secret_ppk_stuff *secret_ppk_stuff(const struct secret *s); const struct secret_ppk_stuff *secret_ppk_stuff_by_id(const struct secret *secrets, shunk_t ppk_id); diag_t secret_pubkey_stuff_to_pubkey_der(struct secret_pubkey_stuff *pks, chunk_t *der); diag_t pubkey_der_to_pubkey_content(shunk_t pubkey_der, struct pubkey_content *pkc); 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 */ struct secret_context; typedef int (*secret_eval)(struct secret *secret, enum secret_kind kind, unsigned line, struct secret_context *context); struct secret *foreach_secret(struct secret *secrets, secret_eval func, struct secret_context *context); 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 accommodate * 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_pubkey_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(const struct secret *lhs, const 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); /* 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, struct secret_pubkey_stuff **pks, bool *load_needed, struct logger *logger); err_t find_or_load_private_key_by_ckaid(struct secret **secrets, const ckaid_t *ckaid, struct secret_pubkey_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-5.2/include/shunk.h000066400000000000000000000120611475767661000163150ustar00rootroot00000000000000/* 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, size_t len); #define HUNK_AS_SHUNK(HUNK) \ ({ \ typeof(HUNK) *h_ = &(HUNK); \ shunk2(h_->ptr, h_->len); \ }) #define THING_AS_SHUNK(THING) shunk2(&(THING), sizeof(THING)) /* * Given LIST, split it using DELIM (and shunk_token()) returning a * .ptr=NULL terminated array of shunks (and a copy of the memory). * * To discard blanks and empty fields specify delims=", ", * opts=EAT_EMPTY_SHUNKS. */ struct shunks { bool kept_empty_shunks; unsigned len; shunk_t list[]; }; enum shunks_opt { KEEP_EMPTY_SHUNKS, EAT_EMPTY_SHUNKS, }; struct shunks *shunks(shunk_t input, const char *delim, enum shunks_opt opt, where_t where); /* * 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; * while (true) { * shunk_t token = shunk_token(&input, &sep, ","); * if (token.ptr == NULL) { * break; * } * ... process token ... * } * */ 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); /* * 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); err_t shunk_to_decimal(shunk_t input, shunk_t *cursor, uintmax_t *decimal, uintmax_t *numerator, uintmax_t *denominator); /* * 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) #define jam_shunk(BUF, SHUNK) jam(BUF, PRI_SHUNK, pri_shunk(SHUNK)) #endif libreswan-5.2/include/sparse_names.h000066400000000000000000000062131475767661000176470ustar00rootroot00000000000000/* 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 #include /* for size_t */ #include "shunk.h" #include "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, NULL, } #define SPARSE(N, V) { .name = N, .value = V, } struct sparse_name { /* field order (backwards?) dictated by started() */ const char *const name; unsigned long value; const char *help; }; struct sparse_names { size_t roof; /* when non-zero, limit on value */ const char *prefix; /* what to remove from short names */ struct sparse_name list[]; }; const struct sparse_name *sparse_lookup(const struct sparse_names *, shunk_t); bool sparse_long(const struct sparse_names *sd, unsigned long val, name_buf *b); bool sparse_short(const struct sparse_names *sd, unsigned long val, name_buf *b); size_t jam_sparse_long(struct jambuf *buf, const struct sparse_names *sd, unsigned long val); const char *str_sparse_long(const struct sparse_names *sd, unsigned long val, name_buf *buf); size_t jam_sparse_short(struct jambuf *buf, const struct sparse_names *sd, unsigned long val); const char *str_sparse_short(const struct sparse_names *sd, unsigned long val, name_buf *buf); size_t jam_sparse_names(struct jambuf *buf, const struct sparse_names *names, const char *separator); #define sparse_buf name_buf #define jam_sparse jam_sparse_long #define str_sparse str_sparse_long /* * 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_names *names; }; struct sparse_sparse_names { size_t ignore_for_now; const struct sparse_sparse_name list[]; }; extern const char *sparse_sparse_name(const struct sparse_sparse_names *sd, unsigned long v1, unsigned long v2); #endif /* _CONSTANTS_H_ */ libreswan-5.2/include/state_category.h000066400000000000000000000022121475767661000201770ustar00rootroot00000000000000/* state categories, 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 STATE_CATEGORY_H #define STATE_CATEGORY_H /* * For auditing, different categories of a state. Of most interest is * half-open states which suggest libreswan being under attack. * * "half-open" is where only one packet was received. */ enum state_category { CAT_UNKNOWN = 0, CAT_HALF_OPEN_IKE_SA, CAT_OPEN_IKE_SA, CAT_ESTABLISHED_IKE_SA, CAT_OPEN_CHILD_SA, CAT_ESTABLISHED_CHILD_SA, CAT_INFORMATIONAL, CAT_IGNORE, #define CAT_ROOF (CAT_IGNORE+1) }; extern const struct enum_names state_category_names; #endif libreswan-5.2/include/sysdep.h000066400000000000000000000006441475767661000165000ustar00rootroot00000000000000/* * 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-5.2/include/terminate_reason.h000066400000000000000000000044361475767661000205330ustar00rootroot00000000000000/* Why an SA is being terminated, for libreswan * * Copyright (C) 1997 Angelos D. Keromytis. * Copyright (C) 1998-2001,2013-2014 D. Hugh Redelmeier * Copyright (C) 2003-2008 Michael C Richardson * Copyright (C) 2003-2009 Paul Wouters * Copyright (C) 2008-2009 David McCullough * Copyright (C) 2009,2012 Avesh Agarwal * Copyright (C) 2012-2013 Paul Wouters * Copyright (C) 2012 Wes Hardaker * Copyright (C) 2013 Matt Rogers * Copyright (C) 2013 Tuomo Soini * Copyright (C) 2014,2017 Antony Antony * Copyright (C) 2015-2019 Andrew Cagney * Copyright (C) 2015-2019 Paul Wouters * Copyright (C) 2017 Vukasin Karadzic * Copyright (C) 2015-2019 Paul Wouters * Copyright (C) 2017 Mayank Totale * Copyright (C) 2020 Yulia Kuzovkova * Copyright (C) 2021 Paul Wouters * Copyright (C) 2020 Nupur Agrawal * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT 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 TERMINATE_REASON_H #define TERMINATE_REASON_H /* * For auditing, why an SA is being terminated. */ enum terminate_reason { #define TERMINATE_REASON_FLOOR (REASON_UNKNOWN) REASON_UNKNOWN, /* aka other */ REASON_CRYPTO_TIMEOUT, REASON_EXCHANGE_TIMEOUT, REASON_TOO_MANY_RETRANSMITS, REASON_SUPERSEDED_BY_NEW_SA, REASON_CRYPTO_FAILED, REASON_AUTH_FAILED, REASON_TRAFFIC_SELECTORS_FAILED, REASON_DELETED, REASON_COMPLETED, #define TERMINATE_REASON_ROOF (REASON_COMPLETED + 1) }; extern const struct enum_names terminate_reason_names; #endif libreswan-5.2/include/test_buffer.h000066400000000000000000000037531475767661000175050ustar00rootroot00000000000000/* * 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. */ #ifndef TEST_BUFFER_H #define TEST_BUFFER_H #include #include #include "chunk.h" #include "where.h" struct logger; struct encrypt_desc; chunk_t decode_to_chunk(const char *prefix, const char *string, struct logger *logger, where_t where); struct crypt_mac decode_to_mac(const char *prefix, const char *string, struct logger *logger, where_t where); PK11SymKey *decode_hex_to_symkey(const char *prefix, const char *string, struct logger *logger, where_t where); PK11SymKey *decode_to_key(const struct encrypt_desc *encrypt_desc, const char *string, struct logger *logger, where_t where); bool verify_symkey(const char *desc, const char *verifying, chunk_t expected, PK11SymKey *actual, struct logger *logger, where_t where); bool verify_bytes(const char *desc, const char *verifying, const void *expected, size_t expected_size, const void *actual, size_t actual_size, struct logger *logger, where_t where); #define verify_hunk(DESC, VERIFYING, EXPECTED, ACTUAL, LOGGER, WHERE) \ ({ \ typeof(EXPECTED) expected_ = EXPECTED; /* evaluate once */ \ typeof(ACTUAL) actual_ = ACTUAL; /* evaluate once */ \ verify_bytes(DESC, VERIFYING, \ expected_.ptr, expected_.len, \ actual_.ptr, actual_.len, \ LOGGER, WHERE); \ }) #endif libreswan-5.2/include/timescale.h000066400000000000000000000022271475767661000171360ustar00rootroot00000000000000/* 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 "shunk.h" #include "scale.h" enum timescale { TIMESCALE_MICROSECONDS, TIMESCALE_MILLISECONDS, TIMESCALE_SECONDS, TIMESCALE_MINUTES, TIMESCALE_HOURS, TIMESCALE_DAYS, TIMESCALE_WEEKS, }; const struct scale *timescale(enum timescale); #define PRI_TIMESCALE "1%s(%juus)" #define pri_timescale(TS) timescale(TS)->suffix, timescale(TS)->multiplier const struct scale *ttotimescale(shunk_t s, enum timescale default_scale); #endif libreswan-5.2/include/ttodata.h000066400000000000000000000025151475767661000166300ustar00rootroot00000000000000/* * 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" /* text conversions */ #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, void *buf, size_t buflen, size_t *needed); extern err_t ttochunk(shunk_t src, int base, chunk_t *chunk); extern size_t datatot(const void *src, size_t srclen, int format, char *buf, size_t buflen); #endif libreswan-5.2/include/vendorid.h000066400000000000000000000132611475767661000170020ustar00rootroot00000000000000/* 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); void llog_vendorids(lset_t rc_flags, 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, /* IKED */ VID_OPENIKED, /* 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-5.2/include/verbose.h000066400000000000000000000067031475767661000166400ustar00rootroot00000000000000/* verbose wrapper around logger * * Copyright (C) 2024 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT 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 VERBOSE_H #define VERBOSE_H /* * Pass-by-value wrapper around logger to make it easy to generate * indented debug/verbose logs. * * Standalone tools, such as <>, can enable more * verbose logging when --verbose is specified, vis: * * struct verbose verbose = { * .logger = logger, * .rc_flags = (verbose ? LOG_STREAM : 0), * }; * * While pluto, internally, enables more verbose debug logging: * * struct verbose verbose = { * .logger = logger, * .rc_flags = (DBGP(DBG_BASE) ? DEBUG_STREAM : 0), * }; * * Functions then pass verbose by value, and increment .level as * needed. */ #include "lset.h" struct verbose { const struct logger *logger; lset_t rc_flags; int level; const char *prefix; }; /* * vlog() output indented logs * verbose() outputs indented logs * vdbg() outputs indented debug logs when DBG_BASE */ #define VERBOSE_LOG(LOGGER, MESSAGE, ...) \ struct verbose verbose = { \ .logger = (LOGGER), \ .rc_flags = RC_LOG, \ .prefix = "", \ }; \ verbose(MESSAGE, ##__VA_ARGS__); \ verbose.level++; /* * vlog() outputs flat logs * verbose() outputs indented debug logs when DBG_BASE * vdbg() outputs indented debug logs when DBG_BASE */ #define VERBOSE_DBGP(COND, LOGGER, MESSAGE, ...) \ struct verbose verbose = { \ .logger = (LOGGER), \ .rc_flags = (LDBGP(COND, LOGGER) ? DEBUG_STREAM : 0), \ .prefix = "", \ }; \ verbose(MESSAGE, ##__VA_ARGS__); \ verbose.level++; #define PRI_VERBOSE "%s%*s" #define pri_verbose "", (verbose.level * 2), "" /* * Normal logging: the message is always logged (no indentation); just * a wrapper around llog(verbose.logger) */ #define vlog(FMT, ...) \ llog(RC_LOG, verbose.logger, FMT, ##__VA_ARGS__); /* * Debug-logging: when the logger has debugging enabled, the message is * logged, prefixed by indentation. */ #define vdbg(FMT, ...) \ { \ if (LDBGP(DBG_BASE, verbose.logger)) { \ llog(DEBUG_STREAM, verbose.logger, \ PRI_VERBOSE""FMT, \ pri_verbose, ##__VA_ARGS__); \ } \ } /* * Informational log: when verbose.rc_info is non-zero, the message is * logged, prefixed by indentation. * * Use this for messages that, depending on the caller, should be * supressed, pretty-logged or pretty-debug-logged. */ #define verbose(FMT, ...) \ { \ if (verbose.rc_flags != 0) { \ llog(verbose.rc_flags, verbose.logger, \ PRI_VERBOSE""FMT, \ pri_verbose, ##__VA_ARGS__); \ } \ } #define vbad(BAD) PBAD(verbose.logger, BAD) #define vexpect(EXPECT) PEXPECT(verbose.logger, EXPECT) #define vassert(ASSERT) PASSERT(verbose.logger, ASSERT) #define vexpect_where(WHERE, EXPECT) PEXPECT_WHERE(verbose.logger, WHERE, EXPECT) #define vassert_where(WHERE, ASSERT) PASSERT_WHERE(verbose.logger, WHERE, ASSERT) #endif libreswan-5.2/include/whack.h000066400000000000000000000333021475767661000162630ustar00rootroot00000000000000/* 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 * Copyright (C) 2020 Nupur Agrawal * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT 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 /* for uintmax_t et.al. */ #include "ietf_constants.h" #include "lset.h" #include "lmod.h" #include "deltatime.h" #include "chunk.h" #include "reqid.h" #include "err.h" #include "ip_range.h" #include "ip_subnet.h" #include "ip_protoport.h" #include "ip_cidr.h" #include "authby.h" #include "encap_proto.h" #include "sa_type.h" #include "constants.h" /* for enum keyword_auth; et.al. */ #include "end.h" #ifndef DEFAULT_CTL_SOCKET # define DEFAULT_CTL_SOCKET IPSEC_RUNDIR "/pluto.ctl" #endif /* * Since the message remains on one host, native representation is * used. */ /* 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 nexthop; /* host */ char *sourceip; ip_cidr host_vtiip; char *interface_ip; /* for ipsec-interface */ char *subnet; /* child */ char *subnets; /* alias subnet expansion */ ip_protoport protoport; bool key_from_DNS_on_demand; char *updown; /* string */ char *virt; char *addresspool; bool xauth_server; /* for XAUTH */ bool xauth_client; char *xauth_username; enum yn_options cat; /* IPv4 Client Address Translation */ enum certpolicy sendcert; enum eap_options eap; bool send_ca; enum ike_cert_type certtype; enum yn_options modecfgserver; /* for MODECFG */ enum yn_options modecfgclient; 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. */ char *groundhog; /* Is this end a groundhog? */ }; /* * Impairments. */ struct whack_impair { unsigned what; uintmax_t value; bool enable; }; struct whack_message { /* * Basic Commands: status and shutdown (NOTHING ELSE!!!) * * Whack (pickle.c) sets .magic == WHACK_BASIC_MAGIC IFF * either .whack_status or .whack_shutdown is valid. * * Whack/addconn (pickle.c) set .magic == whack_magic() for * all other cases. */ struct whack_basic { #define WHACK_BASIC_MAGIC (((((('w' << 8) + 'h') << 8) + 'k') << 8) + 25) unsigned int magic; /* DO NOT ADD BOOLS HERE */ bool whack_status; /* NOR HERE */ bool whack_shutdown; /* AND DON'T EVEN THINK ABOUT HERE */ } basic; /* * END OF BASIC COMMANDS * * If you change anything earlier in this struct, update * WHACK_BASIC_MAGIC so DO NOT DO THAT! */ bool whack_globalstatus; bool whack_clear_stats; bool whack_trafficstatus; bool whack_shuntstatus; bool whack_fipsstatus; bool whack_briefstatus; bool whack_addresspoolstatus; bool whack_connectionstatus; bool whack_briefconnectionstatus; bool whack_showstates; bool whack_seccomp_crashtest; bool whack_processstatus; bool whack_leave_state; /* .basic.shutdown should not * send delete or clean kernel * state on shutdown */ /* name is used in connection and initiate */ char *name; /* for debugging! */ lmod_t debugging; lset_t conn_debug; /* what to impair and how; a list like structure */ struct { unsigned len; struct whack_impair *list; } impairments; bool whack_add; /* whack or addconn semantics; * see from; */ enum whack_from { WHACK_FROM_WHACK = 1, WHACK_FROM_ADDCONN, } whack_from; /* whack and addconn have * different .whack_add * semantics */ bool whack_async; enum ike_version ike_version; /* from keyexchange= */ enum yn_options ikev2; struct authby authby; lset_t sighash_policy; enum shunt_policy shunt[SHUNT_KIND_ROOF]; enum autostart autostart; enum yn_options mobike; /* allow MOBIKE */ enum yn_options intermediate; /* allow Intermediate Exchange */ enum yn_options sha2_truncbug; /* allow Intermediate Exchange */ enum yn_options overlapip; /* can two conns that have * subnet=vhost: declare the * same IP? */ enum yn_options ms_dh_downgrade; /* allow IKEv2 rekey * to downgrade DH * group - Microsoft * bug */ enum yn_options pfs_rekey_workaround; /* during IKEv2 rekey * use full esp= * proposal */ enum yn_options dns_match_id; /* perform reverse DNS lookup * on IP to confirm ID */ enum yn_options pam_authorize; /* non-standard, custom PAM * authorize call on ID * (IKEv2) */ enum yn_options ignore_peer_dns; /* install obtained * DNS servers * locally */ enum yna_options ikepad; /* pad ike packets and * payloads to 4 bytes or * not */ enum yn_options require_id_on_certificate; /* require certificates to * have IKE ID on cert SAN */ enum yn_options modecfgpull; /* is modecfg pulled by * client? */ enum yn_options aggressive; /* do we do aggressive * mode? */ enum yn_options decap_dscp; /* decap ToS/DSCP bits */ enum yn_options encap_dscp; /* encap ToS/DSCP bits */ enum yn_options nopmtudisc; /* ??? */ enum ynf_options fragmentation; /* fragment IKE payload */ enum yne_options esn; /* accept or request ESN{yes,no} */ enum nppi_options ppk; /* pre-shared post-quantum key */ enum yn_options pfs; enum yn_options compress; enum type_options type; /* type=tunnel|transport|SHUNT */ enum encap_proto phase2; /* outer protocol: ESP|AH */ enum yn_options session_resumption; /* for RFC 5723 - * IKEv2 Session * Resumption */ uintmax_t sa_ipsec_max_bytes; uintmax_t sa_ipsec_max_packets; deltatime_t ikelifetime; deltatime_t ipsec_lifetime; deltatime_t rekeymargin; /* which SA? */ uintmax_t sa_rekeyfuzz_percent; struct { bool set; uintmax_t value; } keyingtries; uintmax_t replay_window; deltatime_t retransmit_timeout; deltatime_t retransmit_interval; enum nic_offload_options nic_offload; char *ipsec_interface; /* For IKEv1 RFC 3706 - Dead Peer Detection / IKEv2 liveness */ char *dpddelay; /* seconds */ char *dpdtimeout; /* seconds */ /* Cisco interop: remote peer type */ enum keyword_remote_peer_type remote_peer_type; /* Force the use of NAT-T on a connection */ enum yna_options encapsulation; enum yn_options narrowing; /* IKEv2 only? */ enum yn_options rekey; enum yn_options reauth; /* * TCP: Allow TCP as fallback, only do TCP or only do UDP; and * the port. */ enum tcp_options enable_tcp; uintmax_t tcp_remoteport; /* 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 nat_ikev1_method; /* 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 */ enum yn_options nm_configured; /* 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 mtu; uintmax_t priority; uintmax_t tfc; bool send_no_esp_tfc; enum yn_options iptfs; enum yn_options iptfs_fragmentation; uintmax_t iptfs_packet_size; /* 0 for PMTU */ uintmax_t iptfs_max_queue_size; uintmax_t iptfs_reorder_window; deltatime_t iptfs_drop_time; deltatime_t iptfs_init_delay; reqid_t sa_reqid; int nflog_group; char *sec_label; /* sec_label string (if any) -- decoded by pluto */ struct whack_end end[END_ROOF]; /* names match field */ const struct ip_info *host_afi; const struct ip_info *child_afi; 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_DOWN: */ bool whack_down; /* for WHACK_DELETE: */ bool whack_delete; /* for WHACK_DELETESTATE: */ bool whack_deletestate; long unsigned int whack_deletestateno; /* initiate rekey/delete/down SA now */ enum whack_sa { WHACK_REKEY_SA = 1, WHACK_DELETE_SA, WHACK_DOWN_SA, } whack_sa; #define whack_sa_name(OP) ((OP) == WHACK_REKEY_SA ? "rekey" : \ (OP) == WHACK_DELETE_SA ? "delete" : \ (OP) == WHACK_DOWN_SA ? "down" : \ "???") enum sa_type whack_sa_type; /* 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 */ bool whack_rereadcerts; bool whack_rereadsecrets; bool whack_fetchcrls; /* for connalias string */ char *connalias; /* for IKEv1 MODECFG and IKEv2 CP */ char *modecfgdns; char *modecfgdomains; char *modecfgbanner; char *mark; char *mark_in; char *mark_out; char *vti_interface; enum yn_options vti_routing; /* perform routing into vti * device or not */ enum yn_options vti_shared; /* use remote %any and skip * cleanup on down? */ /* RFC 8784 and draft-ietf-ipsecme-ikev2-qr-alt-04 */ char *ppk_ids; /* for RFC 5685 - IKEv2 Redirect mechanism */ enum allow_global_redirect global_redirect; char *global_redirect_to; char *redirect_to; /* either for connection or active */ enum yn_options accept_redirect; char *accept_redirect_to; enum yna_options send_redirect; /* for RFC 5723 - IKEv2 Session Resumption */ bool whack_suspend; /* what metric to put on ipsec routes */ int metric; char *dnshostname; /* 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 */ struct whackpacker { struct whack_message *msg; unsigned char *str_roof; unsigned char *str_next; size_t n; }; extern err_t pack_whack_msg(struct whackpacker *wp, struct logger *logger); extern bool unpack_whack_msg(struct whackpacker *wp, struct logger *logger); extern void clear_end(const char *leftright, struct whack_end *e); int whack_send_msg(struct whack_message *msg, const char *ctlsocket, char xauthusername[MAX_XAUTH_USERNAME_LEN], char xauthpass[XAUTH_MAX_PASS_LENGTH], int usernamelen, int xauthpasslen, struct logger *logger); extern bool lsw_alias_cmp(const char *name, const char *aliases); extern unsigned whack_magic(void); #endif /* WHACK_H */ libreswan-5.2/include/where.h000066400000000000000000000026641475767661000163070ustar00rootroot00000000000000/* 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 #define jam_where(BUF, WHERE) jam(BUF, PRI_WHERE, pri_where(WHERE)) #endif libreswan-5.2/include/x509.h000066400000000000000000000107341475767661000156770ustar00rootroot00000000000000/* 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 "verbose.h" #include "deltatime.h" #include "chunk.h" #include "err.h" #include "constants.h" #include "jambuf.h" /* for typedef jam_bytes_fn */ #include "asn1.h" #include "verbose.h" struct logger; struct pubkey_list; struct fd; struct show; struct id; struct root_certs; /* * 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(asn1_t a, asn1_t b, int *wildcards, struct verbose verbose); 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_cacerts(struct show *s, struct root_certs *roots); 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 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, struct verbose verbose); extern CERTCertList *get_all_certificates(struct logger *logger); /* * Formatting. * * jam_dn() converts the ASN.1 DN into a "standards compliant" * distinguished 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 escaping 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 distinguished 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); size_t jam_dn_or_null(struct jambuf *buf, asn1_t dn, const char *null_dn, jam_bytes_fn *jam_bytes); size_t jam_dn(struct jambuf *buf, asn1_t dn, jam_bytes_fn *jam_bytes); size_t 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-5.2/initsystems/000077500000000000000000000000001475767661000157645ustar00rootroot00000000000000libreswan-5.2/initsystems/Makefile000066400000000000000000000016041475767661000174250ustar00rootroot00000000000000# 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-5.2/initsystems/docker/000077500000000000000000000000001475767661000172335ustar00rootroot00000000000000libreswan-5.2/initsystems/docker/Makefile000066400000000000000000000025141475767661000206750ustar00rootroot00000000000000ifndef top_srcdir include ../../mk/dirs.mk endif INIT_D_FILE=ipsec.init SYSCONFIGFILE=$(builddir)/sysconfig.pluto SYSCONFIGDIR=$(DESTDIR)$(SYSCONFDIR)/sysconfig SYSVINIT_DEFAULT_START?= include $(top_srcdir)/mk/config.mk include $(top_srcdir)/mk/install.mk include $(top_srcdir)/mk/install.init.d.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: $(INIT_D_FILE) $(SYSCONFIGFILE) local-install-base: installsysconfig checkenabled installsysconfig: local-base mkdir -p $(SYSCONFIGDIR) if test ! -f $(SYSCONFIGDIR)/pluto ; then \ $(INSTALL) $(INSTCONFFLAGS) $(SYSCONFIGFILE) $(SYSCONFIGDIR)/pluto ; \ fi checkenabled: install.init.d 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-5.2/initsystems/docker/ipsec.init.in000077500000000000000000000142371475767661000216420ustar00rootroot00000000000000#!@@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 @@INIT_D_DIR@@/ipsec (/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:-@@IPSEC_CONF@@}" IPSEC_EXECDIR="${IPSEC_EXECDIR:-@@IPSEC_EXECDIR@@}" IPSEC_SBINDIR="${IPSEC_SBINDIR:-@@SBINDIR@@}" unset PLUTO_OPTIONS rundir=@@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 # 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 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 ;; version) version RETVAL=$? ;; *) echo "Usage: $0 {start|stop|restart|reload|force-reload|condrestart|try-restart|status|version}" RETVAL=2 esac exit ${RETVAL} libreswan-5.2/initsystems/docker/sysconfig.pluto.in000066400000000000000000000001061475767661000227260ustar00rootroot00000000000000# Put extra pluto command line options you want here PLUTO_OPTIONS="" libreswan-5.2/initsystems/openrc/000077500000000000000000000000001475767661000172525ustar00rootroot00000000000000libreswan-5.2/initsystems/openrc/Makefile000066400000000000000000000004021475767661000207060ustar00rootroot00000000000000ifndef top_srcdir include ../../mk/dirs.mk endif INIT_D_FILE=ipsec.init include $(top_srcdir)/mk/config.mk include $(top_srcdir)/mk/install.mk include $(top_srcdir)/mk/install.init.d.mk include ${top_srcdir}/mk/targets.mk include ${top_srcdir}/mk/rules.mk libreswan-5.2/initsystems/openrc/ipsec.init.in000077500000000000000000000027461475767661000216630ustar00rootroot00000000000000#!/sbin/openrc-run # -*- mode: sh; sh-shell: sh -*- 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:-@@LIBEXECDIR@@/pluto} PLUTO_CONFFILE=${PLUTO_CONFFILE:-@@IPSEC_CONF@@} IPSEC_BINARY=${IPSEC_BINARY:-@@SBINDIR@@/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 start-stop-daemon --start --pidfile "${PLUTO_PIDFILE}" \ --exec "${PLUTO_BINARY}" -- --config "${PLUTO_CONFFILE}" \ -- ${PLUTO_OPTS} if [ -f @@LIBEXECDIR@@/portexcludes ] ; then @@LIBEXECDIR@@/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} stopnflog eend $RETVAL } reload() { checkconfig || return $? ebegin "Reloading ${SVCNAME}" ${IPSEC_BINARY} rereadall eend $? } libreswan-5.2/initsystems/rc.d/000077500000000000000000000000001475767661000166125ustar00rootroot00000000000000libreswan-5.2/initsystems/rc.d/Makefile000066400000000000000000000027661475767661000202650ustar00rootroot00000000000000ifndef top_srcdir include ../../mk/dirs.mk endif include $(top_srcdir)/mk/config.mk include $(top_srcdir)/mk/install.mk RC_D_FILE = pluto # XXX: Hack to suppress the man page. Should one be added? PROGRAM_MANPAGE= local-base: $(RC_D_FILE) local-install-base: $(RC_D_FILE) local-base @set -eu ; $(call install-directory, $(DESTDIR)$(EXAMPLE_RC_D_DIR)) @set -eu ; $(call install-file, $(INSTBINFLAGS), \ $(builddir)/$(RC_D_FILE), \ $(DESTDIR)$(EXAMPLE_RC_D_DIR)/$(RC_D_FILE)) ifeq ($(INSTALL_INITSYSTEM),true) @set -ue ; $(call install-directory, $(DESTDIR)$(RC_D_DIR)) @set -eu ; $(call install-missing-file, $(INSTBINFLAGS), \ $(DESTDIR)$(EXAMPLE_RC_D_DIR)/$(RC_D_FILE), \ $(DESTDIR)$(RC_D_DIR)/$(RC_D_FILE)) endif ifeq ($(INSTALL_INITSYSTEM),true) ifneq ($(BSD_VARIANT),openbsd) @. /etc/rc.subr ; \ load_rc_config pluto ; \ case " $$rc_directories " in \ *" $(RC_D_DIR) "* ) ;; \ * ) \ echo "" ; \ echo "" ; \ echo " WARNING:" ; \ echo "" ; \ echo " RC_D_DIR=$(RC_D_DIR) is not included in" ; \ echo " the /etc/rc.conf variable:" ; \ echo "" ; \ echo " rc_directories=\"$${rc_directories}\"" ; \ echo "" ; \ ;; \ esac endif endif list-local-base: @set -eu ; echo $(EXAMPLE_RC_D_DIR)/$(RC_D_FILE) ifeq ($(INSTALL_INITSYSTEM),true) @set -eu ; echo $(RC_D_DIR)/$(RC_D_FILE) endif 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-5.2/initsystems/rc.d/freebsd.sh000077500000000000000000000007721475767661000205710ustar00rootroot00000000000000#!/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="@@LIBEXECDIR@@/pluto" command_args="--logfile @@LOGDIR@@/pluto.log --config @@IPSEC_CONF@@ --leak-detective" required_files="@@IPSEC_CONF@@" pidfile="@@RUNDIR@@/${name}.pid" start_precmd="@@SBINDIR@@/ipsec checknss" load_rc_config $name run_rc_command "$1" libreswan-5.2/initsystems/rc.d/netbsd.sh000077500000000000000000000013271475767661000204330ustar00rootroot00000000000000#!/bin/sh # mimic racoon # PROVIDE: ike # REQUIRE: isdnd kdc ppp # BEFORE: SERVERS # KEYWORD: shutdown $_rc_subr_loaded . /etc/rc.subr # standardize PATH, and export it for everything else's benefit; # should config.mk generate this? IPSEC_SBINDIR="${IPSEC_SBINDIR:-@@SBINDIR@@}" NSS_BINDIR="${NSS_BINDIR:-@@NSS_BINDIR@@}" PATH="${NSS_BINDIR}:${PATH#${NSS_BINDIR}:}" PATH="${IPSEC_SBINDIR}:${PATH#${IPSEC_SBINDIR}:}" export PATH name="pluto" rcvar=$name pidfile="@@RUNDIR@@/${name}.pid" command="@@LIBEXECDIR@@/pluto" command_args="--logfile @@LOGDIR@@/pluto.log --config @@IPSEC_CONF@@ --leak-detective" required_files="@@IPSEC_CONF@@" start_precmd="@@SBINDIR@@/ipsec checknss" load_rc_config $name run_rc_command "$1" libreswan-5.2/initsystems/rc.d/openbsd.sh000077500000000000000000000005211475767661000206010ustar00rootroot00000000000000#!/bin/ksh daemon="@@LIBEXECDIR@@/pluto" daemon_flags="--logfile @@LOGDIR@@/pluto.log --config @@IPSEC_CONF@@ --leak-detective" . /etc/rc.d/rc.subr #pidfile="@@RUNDIR@@/${name}.pid" #required_files="@@IPSEC_CONF@@" case $1 in onestart ) set start ;; onestop ) set stop ;; esac rc_pre() { @@SBINDIR@@/ipsec checknss } rc_cmd $1 libreswan-5.2/initsystems/systemd/000077500000000000000000000000001475767661000174545ustar00rootroot00000000000000libreswan-5.2/initsystems/systemd/Makefile000066400000000000000000000067051475767661000211240ustar00rootroot00000000000000ifndef 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) BUILD = $(builddir)/$(UNITFILE) $(builddir)/$(TMPFILESCONFIG) local-base: $(BUILD) local-clean: rm -f $(BUILD) ifeq ($(INSTALL_INITSYSTEM),true) local-install-base: installsystemdservice oldinitdcheck postcheck endif 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 | $(DESTDIR)$(SYSTEMUNITDIR) $(INSTALL) $(INSTCONFFLAGS) $(builddir)/$(UNITFILE) $(DESTDIR)$(SYSTEMUNITDIR) @if test $(DESTDIR)$(SYSTEMUNITDIR) = $(SYSTEMUNITDIR) ; then \ echo running: systemctl --system daemon-reload; \ systemctl --system daemon-reload || echo "failed restart" ; \ fi @if test -f $(DESTDIR)/$(LIBEXECDIR)/portexcludes; then \ echo fixing port excludes ; \ sed -Ei 's@^# (.*/portexcludes)$$@\1@' $(DESTDIR)$(SYSTEMUNITDIR)/$(UNITFILE); \ fi $(DESTDIR)$(SYSTEMUNITDIR): mkdir -p $(DESTDIR)$(SYSTEMUNITDIR) $(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 $(DESTDIR)$(SYSTEMUNITDIR) = $(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-5.2/initsystems/systemd/check-systemd.sh000077500000000000000000000041761475767661000225660ustar00rootroot00000000000000#!/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-5.2/initsystems/systemd/ipsec.service.in000066400000000000000000000022111475767661000225420ustar00rootroot00000000000000[Unit] Description=Internet Key Exchange (IKE) Protocol Daemon for IPsec Wants=network-online.target After=network-online.target Documentation=man:ipsec(8) man:pluto(8) man:ipsec.conf(5) [Service] Type=@@SD_TYPE@@ Restart=@@SD_RESTART_TYPE@@ #RestartPreventExitStatus=137 143 SIGTERM SIGKILL # Set WatchdogSec to the amount of time (in seconds) that systemd will wait # before restarting an unresponsive pluto. # EVENT_SD_WATCHDOG updates the heartbeat every 15 seconds, recommended values # are 60, 90, 120. WatchdogSec=0 disables the action NotifyAccess=all WatchdogSec=@@SD_WATCHDOGSEC@@ # Check configuration file ExecStartPre=@@LIBEXECDIR@@/addconn --config @@IPSEC_CONF@@ --checkconfig # Check for nss database status and migration ExecStartPre=@@SBINDIR@@/ipsec checknss # Check for nflog setup ExecStartPre=@@SBINDIR@@/ipsec checknflog # Start the actual IKE daemon ExecStart=@@LIBEXECDIR@@/pluto @@SD_PLUTO_OPTIONS@@ --config @@IPSEC_CONF@@ --nofork # Enable for portexcludes support # ExecStartPost=@@LIBEXECDIR@@/portexcludes ExecStop=@@LIBEXECDIR@@/whack --shutdown ExecStopPost=@@SBINDIR@@/ipsec stopnflog [Install] WantedBy=multi-user.target libreswan-5.2/initsystems/systemd/libreswan.conf.in000066400000000000000000000000351475767661000227140ustar00rootroot00000000000000d @@RUNDIR@@ 755 root root - libreswan-5.2/initsystems/systemd/test.sh000077500000000000000000000003271475767661000207740ustar00rootroot00000000000000#!/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-5.2/initsystems/sysvinit/000077500000000000000000000000001475767661000176545ustar00rootroot00000000000000libreswan-5.2/initsystems/sysvinit/Makefile000066400000000000000000000025051475767661000213160ustar00rootroot00000000000000ifndef top_srcdir include ../../mk/dirs.mk endif INIT_D_FILE=ipsec.init SYSCONFIGFILE=$(builddir)/sysconfig.pluto SUBDIRS= SYSCONFIGDIR=$(DESTDIR)$(SYSCONFDIR)/sysconfig SYSVINIT_DEFAULT_START?= include $(top_srcdir)/mk/config.mk include $(top_srcdir)/mk/install.mk include $(top_srcdir)/mk/install.init.d.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: $(SYSCONFIGFILE) local-install-base: installsysconfig checkenabled installsysconfig: local-base mkdir -p $(SYSCONFIGDIR) if test ! -f $(SYSCONFIGDIR)/pluto ; then \ $(INSTALL) $(INSTCONFFLAGS) $(SYSCONFIGFILE) $(SYSCONFIGDIR)/pluto ; \ fi checkenabled: install.init.d 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-5.2/initsystems/sysvinit/init.debian.in000066400000000000000000000122341475767661000223720ustar00rootroot00000000000000 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 INIT_D_DIR@/ipsec (/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. . @@INIT_D_DIR@@/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:-@@IPSEC_CONF@@}" IPSEC_EXECDIR="${IPSEC_EXECDIR:-@@IPSEC_EXECDIR@@}" IPSEC_SBINDIR="${IPSEC_SBINDIR:-@@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 @@LIBEXECDIR@@/portexcludes ] ; then @@LIBEXECDIR@@/portexcludes fi return $RETVAL } stop() { ipsec stopnflog > /dev/null ipsec whack --shutdown } restart() { verify_config stop start } condrestart() { verify_config @@INIT_D_DIR@@/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-5.2/initsystems/sysvinit/ipsec.init.in000077500000000000000000000167721475767661000222710ustar00rootroot00000000000000#!@@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 @@INIT_D_DIR@@/ipsec (/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; \ # 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 @@INIT_D_DIR@@/functions ]; then . @@INIT_D_DIR@@/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:-@@IPSEC_CONF@@}" IPSEC_EXECDIR="${IPSEC_EXECDIR:-@@IPSEC_EXECDIR@@}" IPSEC_SBINDIR="${IPSEC_SBINDIR:-@@SBINDIR@@}" unset PLUTO_OPTIONS rundir=@@RUNDIR@@ plutopid=${rundir}/pluto.pid plutoctl=${rundir}/pluto.ctl lockdir=@@VARDIR@@/lock/subsys lockfile=${lockdir}/ipsec # @@SYSCONFDIR@@/resolv.conf related paths LIBRESWAN_RESOLV_CONF=${rundir}/libreswan-resolv-conf-backup ORIG_RESOLV_CONF=@@SYSCONFDIR@@/resolv.conf # there is some confusion over the name - just do both [ -f @@SYSCONFDIR@@/sysconfig/ipsec ] && . @@SYSCONFDIR@@/sysconfig/ipsec [ -f @@SYSCONFDIR@@/sysconfig/pluto ] && . @@SYSCONFDIR@@/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: " # 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 @@LIBEXECDIR@@/portexcludes ] ; then @@LIBEXECDIR@@/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 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-5.2/initsystems/sysvinit/sysconfig.pluto.in000066400000000000000000000001071475767661000233500ustar00rootroot00000000000000# Put extra pluto command line options you want here PLUTO_OPTIONS=" " libreswan-5.2/initsystems/upstart/000077500000000000000000000000001475767661000174665ustar00rootroot00000000000000libreswan-5.2/initsystems/upstart/Makefile000066400000000000000000000016761475767661000211400ustar00rootroot00000000000000ifndef 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=$(DESTDIR)$(SYSCONFDIR)/init DEFAULTDIR=$(DESTDIR)$(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-5.2/initsystems/upstart/default.pluto.in000066400000000000000000000001061475767661000226010ustar00rootroot00000000000000# Put extra pluto command line options you want here PLUTO_OPTIONS="" libreswan-5.2/initsystems/upstart/ipsec.conf.in000066400000000000000000000015421475767661000220470ustar00rootroot00000000000000# ipsec - ipsec services and ike demon (pluto) # # IPsec provides encrypted and authenticated communications; # XFRM 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 @@SBINDIR@@/ipsec addconn --config @@IPSEC_CONF@@ --checkconfig end script script . /etc/default/pluto @@SBINDIR@@/ipsec checknss @@SBINDIR@@/ipsec checknflog @@LIBEXECDIR@@/pluto --config @@IPSEC_CONF@@ --nofork $PLUTO_OPTIONS if [ -f @@LIBEXECDIR@@/portexcludes ] ; then @@LIBEXECDIR@@/portexcludes fi end script pre-stop script # do not run whack --shutdown in pre-stop, it confused stop into restarting # @@SBINDIR@@/ipsec whack --shutdown @@SBINDIR@@/ipsec stopnflog end script libreswan-5.2/kvm000077500000000000000000000342331475767661000141210ustar00rootroot00000000000000#!/bin/bash # uses bash's define set -e declare -a makeflags # gmake isn't on debian? gnumake="make -C $(realpath $(dirname $0))/testing/kvm" print-kvm-variable() { ${gnumake} --no-print-directory print-kvm-variable VARIABLE=$1 "${makeflags[@]}" } kvm_platforms=$(print-kvm-variable KVM_PLATFORMS) kvm_test_host_names=$(print-kvm-variable KVM_TEST_HOST_NAMES) kvm_base_host_names=$(print-kvm-variable KVM_BASE_HOST_NAMES) kvm_build_host_names=$(print-kvm-variable KVM_BUILD_HOST_NAMES) kvm_upgrade_host_names=$(print-kvm-variable KVM_UPGRADE_HOST_NAMES) kvm_testingdir=$(print-kvm-variable KVM_TESTINGDIR) kvm_prefix=($(print-kvm-variable KVM_PREFIX)) kvm_sourcedir=$(print-kvm-variable KVM_SOURCEDIR) kvm_pidfile=$(print-kvm-variable KVM_PIDFILE) # repo under test rutdir=${kvm_testingdir:+$(realpath $(dirname "${kvm_testingdir}"))} # eat newlines hosts="${kvm_test_host_names} ${kvm_build_host_names} ${kvm_base_host_names} ${kvm_upgrade_host_names}" # Note: pass1help() is fed into AWK. Anything that matches # '^____[-a-z]' is considered a Pass 1 command ('_' denotes a space). pass1help() { 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 failed [ ... ] list failed and unresolved test results (for the specified tests) subsequent commands are applied to the resulting list unresolved [ ... ] list unresolved test results (for the specified tests) subsequent commands are applied to the resulting list Re-run, or run a-new the testsuite: recheck [ ... ] re-run the testsuite uninstall deletes test domains deletes build domains leaves test results and keys alone clean deletes test domains deletes build domains deletes test results deletes test keys check-clean delete the test results (leave the build trees and domains alone) keys deletes test keys, and then rebuilds them 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 nohup run in the background writing output to a NEW nohup.out Step wize create/delete the domains (just use ./kvm install): gateway create the gateway (swandefault) used by the VMs base [PLATFORM] create a domain containing the base OS creates: ${kvm_base_host_names} upgrade [PLATFORM] create the upgrade domain from the base domain installs missing packages updates existing packages creates: ${kvm_upgrade_host_names} transmogrify [PLATFORM] create the build domain from the upgrade domain transmogrifies the domain ready for building and testing creates: ${kvm_platforms} build [PLATFORM] build/install libreswan on the build domains uses: ${kvm_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, build domain leaves base domains and upgrade domains alone downgrade [PLATFORM] also deletes upgrade domains also deletes test keys also deletes test results purge [PLATFORM] also deletes base domains demolish [PLATFORM] also deletes shared gateway Libvirt breakage: restart restart libvirt to workaround catatonic daemon performance To log into a domain: sh [ ] start a shell on which can be a: test domain: ${kvm_test_host_names} build domain: ${kvm_build_host_names} base domain: ${kvm_base_host_names} upgrade domain: ${kvm_upgrade_host_names} Configuration: config show the configuration Namespaces - broken: nsinstall install namespaces nsreinstall re-install namespaces nsrun [ ... ] run testsuite using namespaces on the fedora domain EOF } pass2=$(pass2help | awk -v "plat=${kvm_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 # sh hostname compgen -W "${hosts}" "${word}" elif [[ " ${pass2}" =~ " ${word}" ]] ; then # word looks to be matching a command (or is empty), # expand to either or compgen -o plusdirs -W "${pass2}" "${word}" else # doesn't match a command, so throw in the testing directory # as a quick expansion compgen -o plusdirs -W "${pass2}" -G "$(realpath --relative-base $PWD ${kvm_testingdir}/pluto)/${word}*" "${word}" fi exit 0 fi # Handle ../../../kvm [...] # # No arguments implies "check $PWD". Operations but no directory # implies $PWD is the test. # # Set relative to the directory to interpret paths from. relative= if test $(realpath $(dirname $0)) != $(realpath ${PWD}) ; then if test $# -eq 0 ; then set -- check $PWD else relative=$PWD fi cd $(dirname $0) fi # Finally is there at least one parameter? if test $# -eq 0; then cat < ... ... ... EOF pass1help echo pass2help cat <&2 exit 1 fi if test "$#" -eq 1 ; then echo "expecting a command after nohup" 1>&2 exit 1 fi # avoid race tail can try to open nohup.out before nohup # creates it. cp /dev/null nohup.out shift nohup ./kvm "$@" & exec tail -f nohup.out ;; # aliases for pass2 commands diff ) ops[${#ops[@]}]=diffs ;; result ) ops[${#ops[@]}]=results ;; failed ) ops[${#ops[@]}]=failed ;; unresolved ) ops[${#ops[@]}]=unresolved ;; test ) ops[${#ops[@]}]=check ;; retest ) ops[${#ops[@]}]=recheck ;; test-clean ) ops[${#ops[@]}]=check-clean ;; sh ) # remainder of line is host + optional commands shift # drop SH if test $# -lt 1 ; then echo "missing hostname" 1>&2 exit 1 fi # try matching without prefix if [[ " ${hosts} " =~ " $1 " ]] ; then host=${kvm_prefix}$1 shift # drop HOST; add prefix echo "Connecting to ${host}" 1>&2 exec testing/utils/kvmsh.py ${host} "$@" fi # try matching with prefix? echo "unrecognized hostname" 1>&2 exit 1 ;; # 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 ;; *=* ) # capture make variables makeflags[${#makeflags[@]}]=$1 ;; /* ) # an absolute directory path directories[${#directories[@]}]=$(realpath --relative-to=$PWD "$1") ;; * ) # a directory, a pass2 command, or a platform if [[ " ${pass2} " =~ " $1 " ]] ; then # a pass2 command, accumulate ops[${#ops[@]}]=$1 elif [[ " ${kvm_platforms} " =~ " $1 " ]] ; then # platform, accumulate platforms[${#platforms[@]}]=$1 elif test -n "${relative}" -a -d ${relative}/$1 ; then directories[${#directories[@]}]=$(realpath --relative-to=$PWD ${relative}/$1) elif test -z "${relative}" -a -d "$1" ; then directories[${#directories[@]}]=$(realpath --relative-to=$PWD "$1") elif test -z "${relative}" -a -d "${rutdir}/$1" ; then directories[${#directories[@]}]=$(realpath --relative-to=${rutdir} "${rutdir}/$1") elif test -z "${ops[*]}" ; then # first argument, should be a command echo "unrecognized command: $1" 1>&2 else echo "not a directory: $1" 1>&2 fi ;; esac shift done if test -n "${modified}" ; then if test ${#ops[@]} -eq 0 ; then echo "${modified}" exit 0 elif test ${#directories[@]} -gt 0 ; then echo "both modified and tests specified" 1>&2 exit 1 fi directories=(${modified}) elif test ${#directories[@]} -eq 0 ; then directories=(${kvm_testingdir}) fi if test -z "${ops[*]}" ; then echo "nothing to do!" 1>&2 exit 1 fi # Now that makeflags[] is set, extract more variables so they can be # passed to kvmresults. # # For instance ./kvm results KVM_NETBSD=true adds netbsd to platform # and status flags. kvm_test_status=$(print-kvm-variable KVM_TEST_STATUS) kvm_test_platform=$(print-kvm-variable KVM_TEST_PLATFORM) kvm_test_name=$(print-kvm-variable KVM_TEST_NAME) kvm_test_flags=$(print-kvm-variable KVM_TEST_FLAGS) run() { echo "$@" if test -z "${echo}" ; then "$@" fi } run_pid() { if test -r ${kvm_pidfile} ; then local pid=$(cat ${kvm_pidfile}) if ps www --no-headers ${pid} ; then echo "it looks like KVM is already running?" exit 1 fi fi if test -n "${echo}" ; then echo "$@" return fi echo "$@" 1>&2 trap "set -x ; rm -f ${kvm_pidfile}" EXIT echo $$ > ${kvm_pidfile} if "$@" ; then # clean up after every command rm ${kvm_pidfile} else status=$? rm ${kvm_pidfile} exit ${status} fi } kvmresults() { ./testing/utils/kvmresults.py \ ${kvm_testingdir:+--testing-directory ${kvm_testingdir}} \ ${kvm_test_status:+--test-status "${kvm_test_status// /|}"} \ ${kvm_test_platform:+--test-platform "${kvm_test_platform// /|}"} \ ${kvm_test_name:+--test-name "${kvm_test_name}"} \ ${kvm_test_flags} \ "$@" } results_command() { kvmresults "$@" status=$? } diffs_command() { kvmresults --stats none --print diffs "${directories[@]}" status=$? } kill_command() { if test ! -r ${kvm_pidfile} ; then echo "no ${kvm_pidfile} file" 1>&2 exit 1 fi local pid=$(cat ${kvm_pidfile}) echo "killing ${pid}" 1>&2 rm -f ${kvm_pidfile} kill ${pid} } status_command() { if test ! -r ${kvm_pidfile} ; then echo "no ${kvm_pidfile} file" 1>&2 exit 1 fi local pid=$(cat ${kvm_pidfile}) ps="ps www --no-headers ${pid}" echo "${ps}" ${ps} } # second pass status=0 i=0 while test $i -lt ${#ops[@]} ; do op=${ops[${i}]} i=$((i + 1)) # note [ $i -lt ${#ops[@]} ] -> more to come case ${op} in add ) run git add "${directories[@]}" ;; kill ) kill_command ;; status ) status_command ;; base | upgrade | transmogrify | build | install | \ shutdown | uninstall | downgrade | demolish | purge ) if test "${#platforms[@]}" -gt 0 ; then targets=$(for platform in ${platforms[@]} ; do echo kvm-${op}-${platform} done) run_pid ${gnumake} ${targets} "${makeflags[@]}" else run_pid ${gnumake} kvm-${op} "${makeflags[@]}" fi ;; base* | upgrade* | transmogrify* | build* | install* | \ shutdown* | uninstall* | downgrade* | demolish* | purge* ) run_pid ${gnumake} kvm-${op} "${makeflags[@]}" ;; gateway | config | check-clean | clean ) run_pid ${gnumake} kvm-${op} "${makeflags[@]}" ;; check | recheck ) run_pid ${gnumake} kvm-${op} "${makeflags[@]}" KVM_TESTS="${directories[*]}" ;; diffs ) run diffs_command "${directories[@]}" ;; results ) run results_command "${directories[@]}" ;; failed | unresolved ) # should leave: failed and/or unresolved case ${op} in failed ) match="--skip passed --skip unsupported --skip untested" ;; unresolved ) match="--result unresolved" ;; esac if test ${i} -lt ${#ops[@]} ; then run set -- $(results_command ${match} "${directories[@]}" 2>/dev/null) else run results_command ${match} "${directories[@]}" fi ;; patch ) run diffs_command "${directories[@]}" | patch -p1 ;; keys ) run_pid ${gnumake} kvm-keys-clean kvm-keys "${vars[@]}" ;; restart ) run sudo systemctl restart libvirtd ;; nsinstall ) run testing/utils/kvmsh.py --chdir /source ${prefix}fedora -- gmake nsinstall ;; nsreinstall ) run testing/utils/kvmsh.py --chdir /source ${prefix}fedora -- gmake nsreinstall ;; nsrun ) run testing/utils/kvmsh.py --chdir /source ${prefix}fedora -- gmake nsrun ;; esac done exit ${status} libreswan-5.2/lib/000077500000000000000000000000001475767661000141375ustar00rootroot00000000000000libreswan-5.2/lib/COPYING.LIB000066400000000000000000000614471475767661000156130ustar00rootroot00000000000000 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-5.2/lib/Makefile000066400000000000000000000017451475767661000156060ustar00rootroot00000000000000# 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 SUBDIRS += libwhack SUBDIRS += libipsecconf SUBDIRS += liblswtool ifeq ($(USE_SYSTEMD_WATCHDOG),true) SUBDIRS += liblswsd endif include $(top_srcdir)/mk/targets.mk libreswan-5.2/lib/libipsecconf/000077500000000000000000000000001475767661000165775ustar00rootroot00000000000000libreswan-5.2/lib/libipsecconf/Makefile000066400000000000000000000074531475767661000202500ustar00rootroot00000000000000# 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 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$@ --stdout $< | 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 : install result mv $@.tmp $@ # 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-5.2/lib/libipsecconf/confread.c000066400000000000000000000673521475767661000205410ustar00rootroot00000000000000/* 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/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" static bool translate_conn(struct starter_conn *conn, const struct config_parsed *cfgp, struct section_list *sl, enum keyword_set assigned_value, struct logger *logger); /** * 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->values[kbf].option = (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_DO_DNSSEC, true); SOPT(KBF_IKEBUF, IKE_BUF_AUTO); SOPT(KBF_IKE_ERRQUEUE, true); #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_DDOS_IKE_THRESHOLD, DEFAULT_IKE_SA_DDOS_THRESHOLD); SOPT(KBF_MAX_HALFOPEN_IKE, DEFAULT_MAXIMUM_HALFOPEN_IKE_SA); /* Don't inflict BSI requirements on everyone */ SOPT(KBF_GLOBAL_IKEv1, GLOBAL_IKEv1_DROP); SOPT(KBF_DDOS_MODE, DDOS_AUTO); SOPT(KBF_OCSP_CACHE_SIZE, OCSP_DEFAULT_CACHE_SIZE); SOPT(KBF_OCSP_METHOD, OCSP_METHOD_GET); SOPT(KBF_SECCOMP, SECCOMP_DISABLED); /* will be enabled in the future */ # undef SOPT cfg->values[KSF_PLUTO_DNSSEC_ROOTKEY_FILE].string = clone_str(DEFAULT_DNSSEC_ROOTKEY_FILE, "default dnssec rootkey file"); cfg->values[KSF_NSSDIR].string = clone_str(IPSEC_NSSDIR, "default ipsec nssdir"); cfg->values[KSF_SECRETSFILE].string = clone_str(IPSEC_SECRETS, "default ipsec.secrets file"); cfg->values[KSF_DUMPDIR].string = clone_str(IPSEC_RUNDIR, "default dumpdir"); cfg->values[KSF_IPSECDIR].string = clone_str(IPSEC_CONFDDIR, "default ipsec.d dir"); /* ==== end of config setup ==== */ /* ==== conn %default ==== */ struct starter_conn *d = &cfg->conn_default; # define DOPT(kbf, v) { d->values[kbf].option = (v); } DOPT(KNCF_NAT_KEEPALIVE, true); /* per conn */ DOPT(KNCF_TYPE, KS_TUNNEL); DOPT(KNCF_INITIAL_CONTACT, true); DOPT(KNCF_XAUTHBY, XAUTHBY_FILE); DOPT(KNCF_XAUTHFAIL, XAUTHFAIL_HARD); DOPT(KNCF_REPLAY_WINDOW, IPSEC_SA_DEFAULT_REPLAY_WINDOW); 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_HOSTADDRFAMILY, AF_UNSPEC); DOPT(KNCF_CLIENTADDRFAMILY, AF_UNSPEC); DOPT(KNCF_AUTO, AUTOSTART_IGNORE); # undef DOPT d->ike_version = IKEv2; d->authby = AUTHBY_NONE; /* blank goes to defaults */ d->never_negotiate_shunt = SHUNT_UNSET; d->negotiation_shunt = SHUNT_UNSET; d->failure_shunt = SHUNT_UNSET; d->sighash_policy = POL_SIGHASH_DEFAULTS; d->end[LEFT_END].leftright = "left"; d->end[LEFT_END].host_family = NULL; d->end[LEFT_END].addr = unset_address; d->end[LEFT_END].nexttype = KH_NOTSET; d->end[LEFT_END].nexthop = unset_address; d->end[RIGHT_END].leftright = "right"; d->end[RIGHT_END].host_family = NULL; d->end[RIGHT_END].addr = unset_address; d->end[RIGHT_END].nexttype = KH_NOTSET; d->end[RIGHT_END].nexthop = unset_address; d->xfrm_if_id = UINT32_MAX; d->state = STATE_LOADED; /* ==== end of conn %default ==== */ } /** * 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_host: /* all treated as strings for now */ assert(f < elemsof(cfg->values)); pfreeany(cfg->values[f].string); cfg->values[f].string = clone_str(kw->string, "kt_loose_enum kw->string"); cfg->values[f].set = true; break; case kt_lset: case kt_bool: case kt_sparse_name: case kt_unsigned: case kt_percent: case kt_binary: case kt_byte: /* all treated as a number for now */ assert(f < elemsof(cfg->values)); cfg->values[f].option = kw->number; cfg->values[f].set = true; break; case kt_seconds: case kt_milliseconds: /* all treated as a number for now */ assert(f < elemsof(cfg->values)); cfg->values[f].deltatime = kw->deltatime; cfg->values[f].set = 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_also: case kt_appendstring: case kt_appendlist: case kt_obsolete: 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. * * @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, struct logger *logger) { const char *leftright = end->leftright; bool err = false; passert(end->host_family != NULL); pexpect(end->host_family == &ipv4_info || end->host_family == &ipv6_info); /* i.e., not NULL */ # define ERR_FOUND(...) { llog(RC_LOG, logger, __VA_ARGS__); err = true; } if (!end->values[KW_IP].set) conn_st->state = STATE_INCOMPLETE; /* validate the KSCF_IP/KNCF_IP */ end->addrtype = end->values[KW_IP].option; switch (end->addrtype) { case KH_ANY: end->addr = unset_address; break; case KH_IFACE: /* generally, this doesn't show up at this stage */ ldbg(logger, "starter: %s is KH_IFACE", leftright); break; case KH_IPADDR: assert(end->values[KW_IP].string != NULL); if (end->values[KW_IP].string[0] == '%') { const char *iface = end->values[KW_IP].string + 1; if (!starter_iface_find(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; } err_t er = ttoaddress_num(shunk1(end->values[KW_IP].string), 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_info(end->addr)); } break; case KH_OPPO: case KH_OPPOGROUP: case KH_GROUP: /* handled by pluto using .host_type */ break; case KH_IPHOSTNAME: /* generally, this doesn't show up at this stage */ ldbg(logger, "starter: %s is KH_IPHOSTNAME", leftright); break; case KH_DEFAULTROUTE: ldbg(logger, "starter: %s is KH_DEFAULTROUTE", leftright); break; case KH_NOTSET: /* cannot error out here, it might be a partial also= conn */ break; } if (end->values[KSCF_VTI_IP].set) { const char *value = end->values[KSCF_VTI_IP].string; err_t oops = ttocidr_num(shunk1(value), NULL, &end->vti_ip); if (oops != NULL) { ERR_FOUND("bad addr %s%s=%s [%s]", leftright, "vti", value, oops); } oops = cidr_check(end->vti_ip); if (oops != NULL) { ERR_FOUND("bad addr %s%s=%s [%s]", leftright, "vti", value, oops); } /* XXX: check type? */ } /* * validate the KSCF_NEXTHOP; set nexthop address to * something consistent, by default */ end->nexthop = end->host_family->address.unspec; if (end->values[KW_NEXTHOP].set) { char *value = end->values[KW_NEXTHOP].string; if (strcaseeq(value, "%defaultroute")) { end->nexttype = KH_DEFAULTROUTE; } else { err_t e = ttoaddress_num(shunk1(value), end->host_family, &end->nexthop); if (e != NULL) { ERR_FOUND("bad value for %snexthop=%s [%s]", leftright, value, e); } end->nexttype = KH_IPADDR; } } else { end->nexthop = end->host_family->address.unspec; if (end->addrtype == KH_DEFAULTROUTE) { end->nexttype = KH_DEFAULTROUTE; } } 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 config_parsed *cfgp, const struct section_list *sl, enum keyword_set assigned_value, const struct kw_list *kw, const char *leftright, keyword_values values, struct logger *logger) { bool serious_err = false; unsigned int field = kw->keyword.keydef->field; assert(kw->keyword.keydef != NULL); switch (kw->keyword.keydef->type) { case kt_also: { struct section_list *addin; const char *seeking = kw->string; for (addin = TAILQ_FIRST(&cfgp->sections); addin != NULL && !streq(seeking, addin->name); addin = TAILQ_NEXT(addin, link)) ; if (addin == NULL) { llog(RC_LOG, logger, "cannot find conn '%s' needed by conn '%s'", seeking, conn->name); serious_err = true; break; } /* translate things, but do not replace earlier settings! */ serious_err |= translate_conn(conn, cfgp, addin, k_set, logger); break; } 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 */ if (values[field].set == k_set) { llog(RC_LOG, logger, "duplicate key '%s%s' in conn %s while processing def %s", leftright, kw->keyword.keydef->keyname, conn->name, sl->name); /* only fatal if we try to change values */ if (kw->keyword.string == NULL || values[field].string == NULL || !streq(kw->keyword.string, values[field].string)) { serious_err = true; break; } } pfreeany(values[field].string); if (kw->string == NULL) { llog(RC_LOG, logger, "invalid %s value", kw->keyword.keydef->keyname); serious_err = true; break; } values[field].string = clone_str(kw->string, "kt_idtype kw->string"); values[field].set = assigned_value; break; case kt_appendstring: case kt_appendlist: /* implicitly, this field can have multiple values */ if (values[field].string == NULL) { values[field].string = clone_str(kw->string, "kt_appendlist kw->string"); } else { char *s = values[field].string; 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' */ values[field].string = n; pfree(s); } values[field].set = true; break; case kt_pubkey: case kt_host: if (values[field].set == k_set) { llog(RC_LOG, logger, "duplicate key '%s%s' in conn %s while processing def %s", leftright, kw->keyword.keydef->keyname, conn->name, sl->name); /* only fatal if we try to change values */ if (values[field].option != (int)kw->number || !(values[field].option == LOOSE_ENUM_OTHER && kw->number == LOOSE_ENUM_OTHER && kw->keyword.string != NULL && values[field].string != NULL && streq(kw->keyword.string, values[field].string))) { serious_err = true; break; } } values[field].option = kw->number; if (kw->number == LOOSE_ENUM_OTHER) { assert(kw->string != NULL); pfreeany(values[field].string); values[field].string = clone_str( kw->string, "kt_loose_enum kw->keyword.string"); } values[field].set = assigned_value; break; case kt_lset: case kt_bool: case kt_sparse_name: case kt_unsigned: case kt_percent: case kt_binary: case kt_byte: /* all treated as a number for now */ if (values[field].set == k_set) { llog(RC_LOG, logger, "duplicate key '%s%s' in conn %s while processing def %s", leftright, kw->keyword.keydef->keyname, conn->name, sl->name); /* only fatal if we try to change values */ if (values[field].option != (int)kw->number) { serious_err = true; break; } } values[field].option = kw->number; values[field].set = assigned_value; break; case kt_seconds: case kt_milliseconds: /* all treated as a number for now */ if (values[field].set == k_set) { llog(RC_LOG, logger, "duplicate key '%s%s' in conn %s while processing def %s", leftright, kw->keyword.keydef->keyname, conn->name, sl->name); /* only fatal if we try to change values */ if (deltatime_cmp(values[field].deltatime, !=, kw->deltatime)) { serious_err = true; break; } } values[field].deltatime = kw->deltatime; values[field].set = assigned_value; break; case kt_obsolete: break; } return serious_err; } static bool translate_leftright(struct starter_conn *conn, const struct config_parsed *cfgp, const struct section_list *sl, enum keyword_set assigned_value, const struct kw_list *kw, struct starter_end *this, struct logger *logger) { return translate_field(conn, cfgp, sl, assigned_value, kw, /*leftright*/this->leftright, this->values, logger); } static bool translate_conn(struct starter_conn *conn, const struct config_parsed *cfgp, struct section_list *sl, enum keyword_set assigned_value, struct logger *logger) { if (sl->beenhere) { ldbg(logger, "ignore duplicate include"); return false; } sl->beenhere = true; /* 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_leftright) { if (kw->keyword.keyleft) { serious_err |= translate_leftright(conn, cfgp, sl, assigned_value, kw, &conn->end[LEFT_END], logger); } if (kw->keyword.keyright) { serious_err |= translate_leftright(conn, cfgp, sl, assigned_value, kw, &conn->end[RIGHT_END], logger); } } else { serious_err |= translate_field(conn, cfgp, sl, assigned_value, kw, /*leftright*/"", conn->values, logger); } } return serious_err; } static bool load_conn(struct starter_conn *conn, const struct config_parsed *cfgp, struct section_list *sl, bool alsoprocessing, bool defaultconn, struct logger *logger) { /* reset all of the "beenhere" flags */ for (struct section_list *s = TAILQ_FIRST(&cfgp->sections); s != NULL; s = TAILQ_NEXT(s, link)) { s->beenhere = false; } /* turn all of the keyword/value pairs into options/strings in left/right */ bool err = translate_conn(conn, cfgp, sl, defaultconn ? k_default : k_set, logger); if (err) return err; if (conn->values[KSCF_ALSO].string != NULL && !alsoprocessing) { llog(RC_LOG, logger, "also= is not valid in section '%s'", sl->name); return true; /* error */ } if (conn->values[KNCF_TYPE].set) { switch ((enum type_options)conn->values[KNCF_TYPE].option) { case KS_UNSET: bad_case(KS_UNSET); case KS_TUNNEL: break; case KS_TRANSPORT: break; case KS_PASSTHROUGH: conn->authby = AUTHBY_NONE; conn->never_negotiate_shunt = SHUNT_PASS; break; case KS_DROP: conn->authby = AUTHBY_NONE; conn->never_negotiate_shunt = SHUNT_DROP; break; case KS_REJECT: conn->authby = AUTHBY_NONE; conn->never_negotiate_shunt = SHUNT_REJECT; break; } } conn->negotiation_shunt = conn->values[KNCF_NEGOTIATIONSHUNT].option; conn->failure_shunt = conn->values[KNCF_FAILURESHUNT].option; /* i.e., default is to have policy off */ #define KW_POLICY_FLAG(val, fl) \ { \ if (conn->values[val].set) \ conn->policy = (conn->policy & ~(fl)) | \ (conn->values[val].option ? (fl) : LEMPTY); \ } /* i.e., confusion rains */ #define KW_POLICY_NEGATIVE_FLAG(val, fl) \ { \ if (conn->values[val].set) { \ conn->policy = (conn->policy & ~(fl)) | \ (!conn->values[val].option ? (fl) : LEMPTY); \ } \ } /* * ??? sometimes (when? why?) the member is already set. * * When a conn sets it and then expands also=. */ if (conn->values[KNCF_KEYEXCHANGE].set) { if (conn->values[KNCF_KEYEXCHANGE].option == IKE_VERSION_ROOF) { /* * i.e., keyexchange=ike which was ignored. * Use ikev2= when specified. */ if (conn->values[KNCF_IKEv2].set) { conn->ike_version = (conn->values[KNCF_IKEv2].option == YN_YES ? IKEv2 : IKEv1); } } else { /* IKEv1, IKEv2, ... */ conn->ike_version = conn->values[KNCF_KEYEXCHANGE].option; } } else if (conn->values[KNCF_IKEv2].set) { conn->ike_version = (conn->values[KNCF_IKEv2].option == YN_YES ? IKEv2 : IKEv1); } /* * 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->values[KSCF_AUTHBY].set) { conn->sighash_policy = LEMPTY; conn->authby = (struct authby) {0}; shunk_t curseby = shunk1(conn->values[KSCF_AUTHBY].string); 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) { llog(RC_LOG, logger, "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")) { llog(RC_LOG, logger, "authby=ecdsa cannot use sha1, only sha2"); return true; } else { llog(RC_LOG, logger, "connection authby= value is unknown"); return true; } } } /* Let this go through to pluto which will validate it. */ conn->clientaddrfamily = aftoinfo(conn->values[KNCF_CLIENTADDRFAMILY].option); /* * 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->values[KNCF_HOSTADDRFAMILY].option); if (afi == NULL) { FOR_EACH_THING(end, &conn->end[LEFT_END], &conn->end[RIGHT_END]) { FOR_EACH_THING(ips, end->values[KW_IP].string, end->values[KW_NEXTHOP].string) { 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->end[LEFT_END].host_family = conn->end[RIGHT_END].host_family = afi; err |= validate_end(conn, &conn->end[LEFT_END], logger); err |= validate_end(conn, &conn->end[RIGHT_END], logger); 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. */ # define STR_FIELD(f) { conn->f = clone_str(conn->f, #f); } STR_FIELD(name); for (unsigned i = 0; i < elemsof(conn->values); i++) STR_FIELD(values[i].string); /* handle starter_end strings */ # define STR_FIELD_END(f) { STR_FIELD(end[LEFT_END].f); STR_FIELD(end[RIGHT_END].f); } for (unsigned i = 0; i < elemsof(conn->end[LEFT_END].values); i++) STR_FIELD_END(values[i].string); # 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->state = STATE_FAILED; 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, struct logger *logger) { ldbg(logger, "loading conn %s", sconn->name); struct starter_conn *conn = alloc_add_conn(cfg, sconn->name); bool connerr = load_conn(conn, cfgp, sconn, /*also*/true, defaultconn, logger); if (connerr) { /* ??? should caller not log perrl? */ } else { conn->state = STATE_LOADED; } return connerr; } struct starter_config *confread_load(const char *file, bool setuponly, struct logger *logger) { /** * Load file */ struct config_parsed *cfgp = parser_load_conf(file, logger); if (cfgp == NULL) return NULL; struct starter_config *cfg = alloc_thing(struct starter_config, "starter_config cfg"); /** * Set default values */ ipsecconf_default_values(cfg); /** * Load setup * * Danger: reverse fail. */ bool err = load_setup(cfg, cfgp); if (err) { parser_freeany_config_parsed(&cfgp); confread_free(cfg); return NULL; } if (!setuponly) { /* * Load %default conn * ??? is it correct to accept multiple %default conns? */ for (struct section_list *sconn = TAILQ_FIRST(&cfgp->sections); (!err) && sconn != NULL; sconn = TAILQ_NEXT(sconn, link)) { if (streq(sconn->name, "%default")) { ldbg(logger, "loading default conn"); err |= load_conn(&cfg->conn_default, cfgp, sconn, /*also=*/false, true/*default conn*/, logger); } } /* * Load other conns */ for (struct section_list *sconn = TAILQ_FIRST(&cfgp->sections); sconn != NULL; sconn = TAILQ_NEXT(sconn, link)) { if (!streq(sconn->name, "%default")) err |= init_load_conn(cfg, cfgp, sconn, false/*default conn*/, logger); } } parser_freeany_config_parsed(&cfgp); 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); for (unsigned i = 0; i < elemsof(conn->values); i++) STR_FIELD(values[i].string); /* handle starter_end strings */ # define STR_FIELD_END(f) { STR_FIELD(end[LEFT_END].f); STR_FIELD(end[RIGHT_END].f); } for (unsigned i = 0; i < elemsof(conn->end[LEFT_END].values); i++) STR_FIELD_END(values[i].string); # undef STR_FIELD_END # undef STR_FIELD } void confread_free(struct starter_config *cfg) { for (unsigned i = 0; i < elemsof(cfg->values); i++) pfreeany(cfg->values[i].string); confread_free_conn(&cfg->conn_default); for (struct starter_conn *conn = TAILQ_FIRST(&cfg->conns); conn != NULL; ) { struct starter_conn *c = conn; /* step off */ conn = TAILQ_NEXT(conn, link); confread_free_conn(c); pfree(c); } pfree(cfg); } libreswan-5.2/lib/libipsecconf/confwrite.c000066400000000000000000000271061475767661000207510ustar00rootroot00000000000000/* * 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 "encap_proto.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->sparse_names->list; 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, keyword_values values) { 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_also: 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: /* special enumeration */ if (values[k->field].set) { fprintf(out, "\t%s%s=%s\n", side, k->keyname, (values[k->field].option ? "yes" : "no")); } break; case kt_host: /* special enumeration */ if (values[k->field].set) { fprintf(out, "\t%s%s=%s\n", side, k->keyname, values[k->field].string); } break; case kt_sparse_name: /* special enumeration */ if (values[k->field].set) { int val = values[k->field].option; fprintf(out, "\t%s%s=", side, k->keyname); for (const struct sparse_name *kev = k->sparse_names->list; kev->name != NULL; kev++) { /* XXX: INT vs UNSIGNED magic? */ if ((int)kev->value == val) { break; } } } break; case kt_lset: if (values[k->field].set) { unsigned long val = values[k->field].option; 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_obsolete: break; case kt_binary: case kt_byte: case kt_unsigned: if (values[k->field].set) { fprintf(out, "\t%s%s=%jd\n", side, k->keyname, values[k->field].option); } break; case kt_seconds: case kt_milliseconds: if (values[k->field].set) { deltatime_buf d; fprintf(out, "\t%s%s=%s\n", side, k->keyname, str_deltatime(values[k->field].deltatime, &d)); } break; } } } static void confwrite_str(FILE *out, const char *side, unsigned int context, keyword_values values) { 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_also: case kt_appendlist: if (values[k->field].set) fprintf(out, "\t%s%s={%s}\n", side, k->keyname, values[k->field].string); break; case kt_string: case kt_appendstring: case kt_filename: case kt_dirname: /* these are strings */ if (values[k->field].set) { const char *quote = strchr(values[k->field].string, ' ') == NULL ? "" : "\""; fprintf(out, "\t%s%s=%s%s%s\n", side, k->keyname, quote, values[k->field].string, 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_sparse_name: case kt_lset: case kt_host: /* special enumeration */ break; case kt_binary: case kt_byte: /* special number, not a string */ break; case kt_seconds: case kt_milliseconds: /* special value in .deltatime */ break; case kt_percent: case kt_unsigned: break; case kt_obsolete: 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->values[KW_IP].set) fprintf(out, "\t%s=%s\n", side, end->values[KW_IP].string); 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->values[KW_IP].string); break; case KH_IPADDR: { address_buf as; fprintf(out, "\t%s=%s\n", side, str_address(&end->addr, &as)); } break; } switch (end->nexttype) { case KH_NOTSET: /* nothing! */ break; case KH_DEFAULTROUTE: fprintf(out, "\t%snexthop=%%defaultroute\n", side); break; case KH_IPADDR: { address_buf as; fprintf(out, "\t%snexthop=%s\n", side, str_address(&end->nexthop, &as)); } break; default: break; } if (cidr_is_specified(end->vti_ip)) { cidr_buf as; fprintf(out, "\t%svti=%s\n", side, str_cidr(&end->vti_ip, &as)); } if (end->values[KSCF_PROTOPORT].set) fprintf(out, "\t%sprotoport=%s\n", side, end->values[KSCF_PROTOPORT].string); confwrite_int(out, side, kv_conn | kv_leftright, end->values); confwrite_str(out, side, kv_conn | kv_leftright, end->values); } static void confwrite_conn(FILE *out, struct starter_conn *conn, bool verbose) { /* * config-write-field: 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); confwrite_side(out, &conn->end[LEFT_END]); confwrite_side(out, &conn->end[RIGHT_END]); /* fprintf(out, "# confwrite_int:\n"); */ confwrite_int(out, "", kv_conn, conn->values); /* fprintf(out, "# confwrite_str:\n"); */ confwrite_str(out, "", kv_conn, conn->values); if (conn->values[KNCF_AUTO].option != 0) { sparse_buf sb; cwf("auto", str_sparse(&autostart_names, conn->values[KNCF_AUTO].option, &sb)); } if (conn->values[KNCF_PPK].option != NPPI_UNSET) { sparse_buf sb; cwf("ppk", str_sparse(&nppi_option_names, conn->values[KNCF_PPK].option, &sb)); } if (conn->never_negotiate_shunt != SHUNT_UNSET || conn->values[KNCF_PHASE2].option != 0) { enum encap_proto encap_proto = conn->values[KNCF_PHASE2].option; enum shunt_policy shunt_policy = conn->never_negotiate_shunt; enum type_options satype = conn->values[KNCF_TYPE].option; static const char *const noyes[2 /*bool*/] = {"no", "yes"}; /* * config-write-policy-bit: short-cut for writing out a field that is a policy * bit. * * config-write-policy-bit-flipped: cwpbf() flips the * sense of the bit. * * config-write-yn: for writing out optional * yn_options fields. */ # define cwpb(name, p) { cwf(name, noyes[(conn->policy & (p)) != LEMPTY]); } # define cwpbf(name, p) { cwf(name, noyes[(conn->policy & (p)) == LEMPTY]); } #define cwyn(NAME, KNCF) \ { \ if (conn->values[KNCF].option != YN_UNSET) \ cwf(NAME, noyes[conn->values[KNCF].option == YN_YES]); \ } switch (shunt_policy) { case SHUNT_UNSET: switch (satype) { case KS_TUNNEL: cwf("type", "tunnel"); break; case KS_TRANSPORT: cwf("type", "transport"); break; default: break; } cwyn("compress", KNCF_COMPRESS); cwyn("pfs", KNCF_PFS); cwyn("ikepad", KNCF_IKEPAD); if (conn->end[LEFT_END].values[KNCF_AUTH].option == k_unset || conn->end[RIGHT_END].values[KNCF_AUTH].option == k_unset) { authby_buf ab; cwf("authby", str_authby(conn->authby, &ab)); } if (encap_proto != ENCAP_PROTO_UNSET) { /* story is lower-case */ enum_buf eb; cwf("phase2", str_enum_short(&encap_proto_story, encap_proto, &eb)); } /* 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); } /* esn= */ if (conn->values[KNCF_ESN].option != YNE_UNSET) { name_buf nb; cwf("esn", str_sparse(&yne_option_names, conn->values[KNCF_ESN].option, &nb)); } switch (conn->values[KNCF_FRAGMENTATION].option) { case YNF_UNSET: /* it's the default, do not print anything */ break; case YNF_FORCE: cwf("fragmentation", "force"); break; case YNF_NO: cwf("fragmentation", "no"); break; case YNF_YES: cwf("fragmentation", "yes"); } break; /* end of case UNSET aka 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_IPSEC: cwf("type", "ipsec"); /* can't happen */ break ; case SHUNT_TRAP: cwf("type", "trap"); /* can't happen */ 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 #undef cwyn } 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) { /* 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->values); confwrite_str(out, "", kv_config, cfg->values); fprintf(out, "\n"); } /* output connections */ for (struct starter_conn *conn = TAILQ_FIRST(&cfg->conns); conn != NULL; conn = TAILQ_NEXT(conn, link)) { if (name == NULL || streq(name, conn->name)) { confwrite_conn(out, conn, verbose); } } if (verbose) fprintf(out, "# end of config\n"); } libreswan-5.2/lib/libipsecconf/interfaces.c000066400000000000000000000050701475767661000210700ustar00rootroot00000000000000/* 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 "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-5.2/lib/libipsecconf/keywords.c000066400000000000000000000622671475767661000206270ustar00rootroot00000000000000/* * 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 * Copyright (C) 2020 Nupur Agrawal * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY 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 "encap_proto.h" #include "lswalloc.h" #include "ipsecconf/keywords.h" #include "ipsecconf/parser.h" /* includes parser.tab.h generated by bison; requires keywords.h */ /* * Values for failureshunt={passthrough, drop, reject, none} */ static const struct sparse_names kw_failureshunt_names = { .list = { SPARSE("none", SHUNT_NONE), SPARSE("passthrough", SHUNT_PASS), SPARSE("drop", SHUNT_DROP), SPARSE("hold", SHUNT_DROP), /* alias */ SPARSE("reject", SHUNT_REJECT), SPARSE_NULL }, }; /* * Values for negotiationshunt={passthrough, hold} */ static const struct sparse_names kw_negotiationshunt_names = { .list = { SPARSE("passthrough", SHUNT_PASS), SPARSE("drop", SHUNT_HOLD), /* alias */ SPARSE("hold", SHUNT_HOLD), SPARSE_NULL }, }; /* * Common aliases for YES and NO, add this to a keyword list so all * are accepted. * * This list does not include "0" or "1" as they, for things like * yndev have special meanings. */ #define YES_NO(YES, NO) \ SPARSE("yes", YES), \ SPARSE("no", NO), \ SPARSE("true", YES), \ SPARSE("false", NO), \ SPARSE("on", YES), \ SPARSE("off", NO), \ SPARSE("y", YES), \ SPARSE("n", NO) /* * Values for keyexchange= and ikev2= * * The ikev2= keyword, which was originally very flexible, has been * reduced to a boolean. Retain original keywords for backwards * compatibility for now. */ static const struct sparse_names kw_keyexchange_names = { .list = { SPARSE("ike", IKE_VERSION_ROOF), SPARSE("ikev1", IKEv1), SPARSE("ikev2", IKEv2), SPARSE_NULL }, }; static const struct sparse_names kw_ikev2_names = { .list = { /* from fo_{never,permit,propose,insist} */ SPARSE("never", YN_NO), SPARSE("propose", YN_YES), /* originally: initiate IKEv2, * but allow downgrade to * IKEv1; accept IKEv1 or * IKEv2 */ SPARSE("permit", YN_NO), /* reverse of propose: * initiate IKEv1, but allow * upgrade to IKEv2; accept * IKEv1 or IKEv2? */ SPARSE("insist", YN_YES), YES_NO(YN_YES, YN_NO), SPARSE("always", YN_YES), SPARSE_NULL }, }; static const struct sparse_names kw_ddos_names = { .list = { SPARSE("auto", DDOS_AUTO), SPARSE("busy", DDOS_FORCE_BUSY), SPARSE("unlimited", DDOS_FORCE_UNLIMITED), SPARSE_NULL }, }; #ifdef USE_SECCOMP static const struct sparse_names kw_seccomp_names = { .list = { SPARSE("enabled", SECCOMP_ENABLED), SPARSE("disabled", SECCOMP_DISABLED), SPARSE("tolerant", SECCOMP_TOLERANT), SPARSE_NULL }, }; #endif static const struct sparse_names kw_auth_names = { .list = { SPARSE("never", AUTH_NEVER), SPARSE("secret", AUTH_PSK), SPARSE("rsasig", AUTH_RSASIG), SPARSE("rsa", AUTH_RSASIG), /* alias */ SPARSE("ecdsa", AUTH_ECDSA), SPARSE("null", AUTH_NULL), SPARSE("eaponly", AUTH_EAPONLY), SPARSE_NULL }, }; /* * Values for sendca={none,issuer,all} */ static const struct sparse_names kw_sendca_names = { .list = { SPARSE("none", CA_SEND_NONE), SPARSE("issuer", CA_SEND_ISSUER), SPARSE("all", CA_SEND_ALL), SPARSE_NULL }, }; /* * Values for addrfamily={ipv4,ipv6} */ static const struct sparse_names kw_addrfamily_names = { .list = { SPARSE("ipv4", AF_INET), SPARSE("ipv6", AF_INET6), /* aliases - undocumented on purpose */ SPARSE("v4", AF_INET), SPARSE("inet", AF_INET), SPARSE("v6", AF_INET6), SPARSE("inet6", AF_INET6), SPARSE_NULL }, }; /* * Values for {rsasigkey,ecdsakey,pubkey}={ %cert, %dnsondemand, %dns, literal } */ static const struct sparse_names kw_pubkey_names = { .list = { SPARSE("", PUBKEY_PREEXCHANGED), SPARSE("%cert", PUBKEY_CERTIFICATE), #ifdef USE_DNSSEC SPARSE("%dns", PUBKEY_DNSONDEMAND), SPARSE("%dnsondemand", PUBKEY_DNSONDEMAND), #endif SPARSE_NULL }, }; /* * Cisco interop: remote peer type */ static const struct sparse_names kw_remote_peer_type_names = { .list = { SPARSE("cisco", REMOTE_PEER_CISCO), SPARSE_NULL }, }; static const struct sparse_names kw_xauthby_names = { .list = { SPARSE("file", XAUTHBY_FILE), #ifdef USE_PAM_AUTH SPARSE("pam", XAUTHBY_PAM), #endif SPARSE("alwaysok", XAUTHBY_ALWAYSOK), SPARSE_NULL }, }; static const struct sparse_names kw_xauthfail_names = { .list = { SPARSE("hard", XAUTHFAIL_HARD), SPARSE("soft", XAUTHFAIL_SOFT), SPARSE_NULL }, }; /* * Values for right= and left= */ static struct sparse_names kw_host_names = { .list = { SPARSE("%defaultroute", KH_DEFAULTROUTE), SPARSE("%any", KH_ANY), SPARSE("%", KH_IFACE), SPARSE("%oppo", KH_OPPO), SPARSE("%opportunistic", KH_OPPO), SPARSE("%opportunisticgroup", KH_OPPOGROUP), SPARSE("%oppogroup", KH_OPPOGROUP), SPARSE("%group", KH_GROUP), SPARSE("%hostname", KH_IPHOSTNAME), /* makes no sense on input */ SPARSE_NULL }, }; static const struct sparse_names kw_phase2types_names = { .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 */ SPARSE("esp", ENCAP_PROTO_ESP), SPARSE("ah", ENCAP_PROTO_AH), SPARSE("default", ENCAP_PROTO_UNSET), /* i.e., let pluto decide */ SPARSE_NULL }, }; /* * Values for {left/right}sendcert={never,sendifasked,always,forcedtype} */ static const struct sparse_names kw_sendcert_names = { .list = { SPARSE("never", CERT_NEVERSEND), SPARSE("sendifasked", CERT_SENDIFASKED), SPARSE("alwayssend", CERT_ALWAYSSEND), SPARSE("always", CERT_ALWAYSSEND), 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_names kw_ocsp_method_names = { .list = { SPARSE("get", OCSP_METHOD_GET), SPARSE("post", OCSP_METHOD_POST), SPARSE_NULL }, }; static const struct sparse_names kw_global_ikev1_names = { .list = { SPARSE("accept", GLOBAL_IKEv1_ACCEPT), SPARSE("reject", GLOBAL_IKEv1_REJECT), SPARSE("drop", GLOBAL_IKEv1_DROP), SPARSE_NULL }, }; static const struct sparse_names kw_eap_names = { .list = { SPARSE("none", IKE_EAP_NONE), /* default */ SPARSE("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_sparse_name, KBF_GLOBAL_IKEv1, &kw_global_ikev1_names, NULL, }, { "curl-iface", kv_config, kt_string, KSF_CURLIFACE, NULL, NULL, }, { "curl-timeout", kv_config, kt_seconds, KBF_CURL_TIMEOUT_SECONDS, NULL, NULL, }, { "myvendorid", kv_config, kt_string, KSF_MYVENDORID, NULL, NULL, }, { "syslog", kv_config, kt_string, KSF_SYSLOG, NULL, NULL, }, { "plutodebug", kv_config|kv_conn, kt_lset, KW_DEBUG, NULL, &debug_lmod_info, }, { "debug", kv_config|kv_conn, kt_lset, KW_DEBUG, 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_seconds, KBF_SHUNTLIFETIME, 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_seconds, KBF_CRL_CHECKINTERVAL, 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_seconds, KBF_OCSP_TIMEOUT_SECONDS, NULL, NULL, }, { "ocsp-trustname", kv_config, kt_string, KSF_OCSP_TRUSTNAME, NULL, NULL, }, { "ocsp-cache-size", kv_config, kt_unsigned, KBF_OCSP_CACHE_SIZE, NULL, NULL, }, { "ocsp-cache-min-age", kv_config, kt_seconds, KBF_OCSP_CACHE_MIN_AGE_SECONDS, NULL, NULL, }, { "ocsp-cache-max-age", kv_config, kt_seconds, KBF_OCSP_CACHE_MAX_AGE_SECONDS, NULL, NULL, }, { "ocsp-method", kv_config | kv_processed, kt_sparse_name, KBF_OCSP_METHOD, &kw_ocsp_method_names, NULL, }, { "ddos-mode", kv_config | kv_processed , kt_sparse_name, KBF_DDOS_MODE, &kw_ddos_names, NULL, }, #ifdef USE_SECCOMP { "seccomp", kv_config | kv_processed , kt_sparse_name, KBF_SECCOMP, &kw_seccomp_names, NULL, }, #endif { "ddos-ike-threshold", kv_config, kt_unsigned, KBF_DDOS_IKE_THRESHOLD, NULL, NULL, }, { "max-halfopen-ike", kv_config, kt_unsigned, KBF_MAX_HALFOPEN_IKE, NULL, NULL, }, { "ike-socket-bufsize", kv_config, kt_unsigned, KBF_IKEBUF, NULL, NULL, }, { "ike-socket-errqueue", kv_config, kt_bool, KBF_IKE_ERRQUEUE, NULL, NULL, }, #if defined(USE_NFLOG) { "nflog-all", kv_config, kt_unsigned, KBF_NFLOG_ALL, NULL, NULL, }, #endif #ifdef XFRM_LIFETIME_DEFAULT { "xfrmlifetime", kv_config, kt_unsigned, 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_unsigned, KBF_SEEDBITS, NULL, NULL, }, { "keep-alive", kv_config, kt_seconds, KBF_KEEP_ALIVE, 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_unsigned, KBF_NHELPERS, NULL, NULL, }, { "drop-oppo-null", kv_config, kt_bool, KBF_DROP_OPPO_NULL, NULL, NULL, }, { "interfaces", kv_config, kt_obsolete, KNCF_OBSOLETE, 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_host, KW_IP, &kw_host_names, 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_unsigned, KNCF_IKEPORT, NULL, NULL, }, { "interface-ip", kv_conn | kv_leftright, kt_subnet, KSCF_INTERFACE_IP, NULL, NULL, }, { "vti", kv_conn | kv_leftright | kv_processed, kt_subnet, KSCF_VTI_IP, NULL, NULL, }, { "nexthop", kv_conn | kv_leftright, kt_ipaddr, KW_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, KW_RSASIGKEY, &kw_pubkey_names, NULL, }, { "ecdsakey", kv_conn | kv_leftright, kt_pubkey, KW_ECDSAKEY, &kw_pubkey_names, NULL, }, { "pubkey", kv_conn | kv_leftright, kt_pubkey, KW_PUBKEY, &kw_pubkey_names, 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_sparse_name, KNCF_SENDCERT, &kw_sendcert_names, 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_sparse_name, KNCF_MODECONFIGSERVER, &yn_option_names, NULL, }, { "modecfgclient", kv_conn | kv_leftright, kt_sparse_name, KNCF_MODECONFIGCLIENT, &yn_option_names, 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_sparse_name, KNCF_AUTH, &kw_auth_names, NULL, }, #if defined(USE_CAT) { "cat", kv_conn | kv_leftright, kt_sparse_name, KNCF_CAT, &yn_option_names, NULL, }, #endif { "protoport", kv_conn | kv_leftright | kv_processed, kt_string, KSCF_PROTOPORT, NULL, NULL, }, { "autheap", kv_conn | kv_leftright, kt_sparse_name, KNCF_EAP, &kw_eap_names, NULL, }, { "groundhog", kv_conn | kv_leftright, kt_string, KSCF_GROUNDHOG, NULL, NULL, }, /* these are conn statements which are not left/right */ { "auto", kv_conn, kt_sparse_name, KNCF_AUTO, &autostart_names, NULL, }, { "also", kv_conn | kv_duplicateok, kt_also, KSCF_ALSO, NULL, NULL, }, { "ike", kv_conn, kt_string, KSCF_IKE, NULL, NULL, }, { "hostaddrfamily", kv_conn, kt_sparse_name, KNCF_HOSTADDRFAMILY, &kw_addrfamily_names, NULL, }, { "clientaddrfamily", kv_conn, kt_sparse_name, KNCF_CLIENTADDRFAMILY, &kw_addrfamily_names, NULL, }, { "type", kv_conn, kt_sparse_name, KNCF_TYPE, &type_option_names, NULL, }, { "authby", kv_conn, kt_string, KSCF_AUTHBY, NULL, NULL, }, { "keyexchange", kv_conn, kt_sparse_name, KNCF_KEYEXCHANGE, &kw_keyexchange_names, NULL, }, { "ikev2", kv_conn | kv_processed, kt_sparse_name, KNCF_IKEv2, &kw_ikev2_names, NULL, }, { "ppk", kv_conn | kv_processed, kt_sparse_name, KNCF_PPK, &nppi_option_names, NULL, }, { "ppk-ids", kv_conn | kv_processed, kt_string, KSCF_PPK_IDS, NULL, NULL, }, { "intermediate", kv_conn | kv_processed, kt_sparse_name, KNCF_INTERMEDIATE, &yn_option_names, NULL, }, { "esn", kv_conn | kv_processed, kt_sparse_name, KNCF_ESN, &yne_option_names, NULL, }, { "decap-dscp", kv_conn | kv_processed, kt_sparse_name, KNCF_DECAP_DSCP, &yn_option_names, NULL, }, { "encap-dscp", kv_conn | kv_processed, kt_sparse_name, KNCF_ENCAP_DSCP, &yn_option_names, NULL, }, { "nopmtudisc", kv_conn | kv_processed, kt_sparse_name, KNCF_NOPMTUDISC, &yn_option_names, NULL, }, { "fragmentation", kv_conn | kv_processed, kt_sparse_name, KNCF_FRAGMENTATION, &ynf_option_names, NULL, }, { "mobike", kv_conn, kt_sparse_name, KNCF_MOBIKE, &yn_option_names, NULL, }, { "narrowing", kv_conn, kt_sparse_name, KNCF_NARROWING, &yn_option_names, NULL, }, { "pam-authorize", kv_conn, kt_sparse_name, KNCF_PAM_AUTHORIZE, &yn_option_names, NULL, }, { "send-redirect", kv_conn, kt_sparse_name, KNCF_SEND_REDIRECT, &yna_option_names, NULL, }, { "redirect-to", kv_conn, kt_string, KSCF_REDIRECT_TO, NULL, NULL, }, { "accept-redirect", kv_conn, kt_sparse_name, KNCF_ACCEPT_REDIRECT, &yn_option_names, NULL, }, { "accept-redirect-to", kv_conn, kt_string, KSCF_ACCEPT_REDIRECT_TO, NULL, NULL, }, { "pfs", kv_conn, kt_sparse_name, KNCF_PFS, &yn_option_names, NULL, }, { "session-resumption", kv_conn, kt_sparse_name, KNCF_SESSION_RESUMPTION, &yn_option_names, 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, }, { "iptfs", kv_conn, kt_sparse_name, KNCF_IPTFS, &yn_option_names, NULL, }, { "iptfs-fragmentation", kv_conn, kt_sparse_name, KNCF_IPTFS_FRAGMENTATION, &yn_option_names, NULL, }, { "iptfs-packet-size", kv_conn, kt_binary, KNCF_IPTFS_PACKET_SIZE, NULL, NULL, }, { "iptfs-max-queue-size", kv_conn, kt_binary, KNCF_IPTFS_MAX_QUEUE_SIZE, NULL, NULL, }, { "iptfs-reorder-window", kv_conn, kt_binary, KNCF_IPTFS_REORDER_WINDOW, NULL, NULL, }, { "iptfs-init-delay", kv_conn, kt_seconds, KNCF_IPTFS_INIT_DELAY, NULL, NULL, }, { "iptfs-drop-time", kv_conn, kt_seconds, KNCF_IPTFS_DROP_TIME, 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_sparse_name, KNCF_SHA2_TRUNCBUG, &yn_option_names, NULL, }, { "ms-dh-downgrade", kv_conn, kt_sparse_name, KNCF_MS_DH_DOWNGRADE, &yn_option_names, NULL, }, { "pfs-rekey-workaround", kv_conn, kt_sparse_name, KNCF_PFS_REKEY_WORKAROUND, &yn_option_names, NULL, }, { "require-id-on-certificate", kv_conn, kt_sparse_name, KNCF_REQUIRE_ID_ON_CERTIFICATE, &yn_option_names, NULL, }, { "dns-match-id,", kv_conn, kt_sparse_name, KNCF_DNS_MATCH_ID, &yn_option_names, NULL, }, { "ipsec-max-bytes", kv_conn, kt_byte, KNCF_IPSEC_MAXBYTES, NULL, NULL, }, { "ipsec-lifetime", kv_conn, kt_seconds, KNCF_IPSEC_LIFETIME, NULL, NULL, }, { "keylife", kv_conn | kv_alias, kt_seconds, KNCF_IPSEC_LIFETIME, NULL, NULL, }, /* old name */ { "lifetime", kv_conn | kv_alias, kt_seconds, KNCF_IPSEC_LIFETIME, NULL, NULL, }, /* old name */ { "salifetime", kv_conn, kt_seconds, KNCF_IPSEC_LIFETIME, NULL, NULL, }, /* old name */ { "ipsec-max-packets", kv_conn, kt_binary, KNCF_IPSEC_MAXPACKETS, NULL, NULL, }, { "retransmit-timeout", kv_conn, kt_seconds, KNCF_RETRANSMIT_TIMEOUT, NULL, NULL, }, { "retransmit-interval", kv_conn, kt_milliseconds, KNCF_RETRANSMIT_INTERVAL, NULL, NULL, }, { "ikepad", kv_conn, kt_sparse_name, KNCF_IKEPAD, &yna_option_names, NULL, }, { "nat-ikev1-method", kv_conn | kv_processed, kt_sparse_name, KNCF_NAT_IKEv1_METHOD, &nat_ikev1_method_option_names, NULL, }, { "ikev1-secctx-attr-type", kv_config, kt_obsolete, KNCF_OBSOLETE, NULL, NULL, }, /* obsolete: not a value, a type */ { "secctx-attr-type", kv_config, kt_obsolete, KNCF_OBSOLETE, NULL, NULL, }, { "policy-label", kv_conn, kt_string, KSCF_SEC_LABEL, NULL, NULL, }, /* obsolete variant */ { "sec-label", kv_conn, kt_string, KSCF_SEC_LABEL, NULL, NULL, }, /* Cisco interop: remote peer type */ { "remote-peer-type", kv_conn, kt_sparse_name, KNCF_REMOTE_PEER_TYPE, &kw_remote_peer_type_names, NULL, }, /* another alias used by NetworkManager-libreswan :/ */ { "remote_peer_type", kv_conn, kt_sparse_name, KNCF_REMOTE_PEER_TYPE, &kw_remote_peer_type_names, NULL, }, /* Network Manager support */ #ifdef HAVE_NM { "nm-configured", kv_conn, kt_sparse_name, KNCF_NM_CONFIGURED, &yn_option_names, NULL, }, #endif { "xauthby", kv_conn, kt_sparse_name, KNCF_XAUTHBY, &kw_xauthby_names, NULL, }, { "xauthfail", kv_conn, kt_sparse_name, KNCF_XAUTHFAIL, &kw_xauthfail_names, NULL, }, { "modecfgpull", kv_conn, kt_sparse_name, KNCF_MODECFGPULL, &yn_option_names, 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_sparse_name, KNCF_IGNORE_PEER_DNS, &yn_option_names, NULL, }, { "mark", kv_conn, kt_string, KSCF_MARK, NULL, NULL, }, { "mark-in", kv_conn, kt_string, KSCF_MARK_IN, NULL, NULL, }, { "mark-out", kv_conn, kt_string, KSCF_MARK_OUT, NULL, NULL, }, { "vti-interface", kv_conn, kt_string, KSCF_VTI_INTERFACE, NULL, NULL, }, { "vti-routing", kv_conn, kt_sparse_name, KNCF_VTI_ROUTING, &yn_option_names, NULL, }, { "vti-shared", kv_conn, kt_sparse_name, KNCF_VTI_SHARED, &yn_option_names, NULL, }, { "ipsec-interface-managed", kv_config, kt_sparse_name, KWYN_IPSEC_INTERFACE_MANAGED, &yn_option_names, NULL, }, { "ipsec-interface", kv_conn, kt_string, KWS_IPSEC_INTERFACE, NULL, NULL, }, { "nic-offload", kv_conn, kt_sparse_name, KNCF_NIC_OFFLOAD, &nic_offload_option_names, NULL, }, { "encapsulation", kv_conn, kt_sparse_name, KNCF_ENCAPSULATION, &yna_option_names, NULL, }, { "overlapip", kv_conn, kt_sparse_name, KNCF_OVERLAPIP, &yn_option_names, NULL, }, { "reauth", kv_conn, kt_sparse_name, KNCF_REAUTH, &yn_option_names, NULL, }, { "rekey", kv_conn, kt_sparse_name, KNCF_REKEY, &yn_option_names, NULL, }, { "rekeymargin", kv_conn, kt_seconds, KNCF_REKEYMARGIN, NULL, NULL, }, { "rekeyfuzz", kv_conn, kt_percent, KNCF_REKEYFUZZ, NULL, NULL, }, { "keyingtries", kv_conn, kt_unsigned, KNCF_KEYINGTRIES, NULL, NULL, }, { "replay-window", kv_conn, kt_unsigned, KNCF_REPLAY_WINDOW, NULL, NULL, }, { "ikelifetime", kv_conn, kt_seconds, KNCF_IKELIFETIME, NULL, NULL, }, { "failureshunt", kv_conn, kt_sparse_name, KNCF_FAILURESHUNT, &kw_failureshunt_names, NULL, }, { "negotiationshunt", kv_conn, kt_sparse_name, KNCF_NEGOTIATIONSHUNT, &kw_negotiationshunt_names, NULL, }, { "enable-tcp", kv_conn, kt_sparse_name, KNCF_ENABLE_TCP, &tcp_option_names, NULL }, { "tcp-remoteport", kv_conn, kt_unsigned, KNCF_TCP_REMOTEPORT, 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_sparse_name, KNCF_PHASE2, &kw_phase2types_names, NULL, }, { "compress", kv_conn, kt_sparse_name, KNCF_COMPRESS, &yn_option_names, NULL, }, /* route metric */ { "metric", kv_conn, kt_unsigned, KNCF_METRIC, NULL, NULL, }, /* DPD */ { "dpddelay", kv_conn, kt_string, KSCF_DPDDELAY, NULL, NULL, }, { "ikev1-dpdtimeout", kv_conn, kt_string, KSCF_DPDTIMEOUT, NULL, NULL, }, { "dpdtimeout", kv_conn | kv_alias, kt_string, KSCF_DPDTIMEOUT, NULL, NULL, }, /* old name */ { "dpdaction", kv_conn, kt_obsolete, KNCF_OBSOLETE, NULL, NULL, }, { "sendca", kv_conn, kt_sparse_name, KNCF_SEND_CA, &kw_sendca_names, NULL, }, { "mtu", kv_conn, kt_unsigned, KNCF_MTU, NULL, NULL, }, { "priority", kv_conn, kt_unsigned, KNCF_PRIORITY, NULL, NULL, }, { "tfc", kv_conn, kt_unsigned, KNCF_TFC, NULL, NULL, }, { "reqid", kv_conn, kt_unsigned, KNCF_REQID, NULL, NULL, }, #if defined(USE_NFLOG) { "nflog", kv_conn, kt_unsigned, KNCF_NFLOG_CONN, NULL, NULL, }, #endif { "aggressive", kv_conn, kt_sparse_name, KNCF_AGGRESSIVE, &yn_option_names, NULL, }, /* alias for compatibility - undocumented on purpose */ { "aggrmode", kv_conn | kv_alias, kt_sparse_name, KNCF_AGGRESSIVE, &yn_option_names, NULL, }, { NULL, 0, 0, 0, NULL, NULL, } }; libreswan-5.2/lib/libipsecconf/parser.lex000066400000000000000000000303061475767661000206070ustar00rootroot00000000000000/* -*- 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 struct logger; #define YY_DECL int yylex(struct logger *logger) YY_DECL; #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 "lswlog.h" #include "lswglob.h" #include "lswalloc.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 bool parser_y_eof(struct logger *logger); /* 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; char **fileglob; }; static struct { int stack_ptr; struct ic_inputsource stack[MAX_INCLUDE_DEPTH]; } ic_private; static struct ic_inputsource *stacktop; const char *parser_cur_filename(void) { return stacktop->filename; } unsigned parser_cur_line(void) { return stacktop->line; } 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 = clone_str(name, "filename"); stacktop = &ic_private.stack[0]; ic_private.stack_ptr = 0; } static void parser_y_close(struct ic_inputsource *iis) { pfreeany(iis->filename); if (iis->file != NULL) { fclose(iis->file); iis->file = NULL; } if (iis->fileglob != NULL) { for (char **p = iis->fileglob; *p; p++) { pfree(*p); } pfreeany(iis->fileglob); } } static bool parser_y_nextglobfile(struct ic_inputsource *iis, struct logger *logger) { if (iis->fileglob == NULL) { /* EOF */ ldbg(logger, "EOF: no .fileglob"); return false; } if (iis->fileglob[iis->fileglobcnt] == NULL) { /* EOF */ ldbg(logger, "EOF: .fileglob[%u] == NULL", iis->fileglobcnt); return false; } /* increment for next time */ int fcnt = iis->fileglobcnt++; if (iis->file != NULL) { fclose(iis->file); iis->file = NULL; } pfreeany(iis->filename); iis->line = 1; iis->once = true; iis->filename = clone_str(iis->fileglob[fcnt], "fileglob"); /* open the file */ FILE *f = fopen(iis->filename, "r"); if (f == NULL) { int e = errno; parser_warning(logger, e, "cannot open include filename: '%s'", iis->fileglob[fcnt]); return false; } iis->file = f; yy_switch_to_buffer(yy_create_buffer(f, YY_BUF_SIZE)); return true; } struct lswglob_context { const char *filename; const char *try; }; static void glob_include(unsigned count, char **files, struct lswglob_context *context, struct logger *logger) { /* success */ if (ic_private.stack_ptr >= MAX_INCLUDE_DEPTH - 1) { parser_warning(logger, /*errno*/0, "including '%s' exceeds max inclusion depth of %u", context->filename, MAX_INCLUDE_DEPTH); return; } if (lex_verbosity > 0) { ldbg(logger, "including file '%s' ('%s') from %s:%u", context->filename, context->try, stacktop->filename, stacktop->line); } PASSERT(logger, ic_private.stack_ptr < sizeof(ic_private.stack) - 1); ++ic_private.stack_ptr; stacktop = &ic_private.stack[ic_private.stack_ptr]; stacktop->state = YY_CURRENT_BUFFER; stacktop->file = NULL; stacktop->filename = NULL; stacktop->fileglobcnt = 0; stacktop->fileglob = alloc_things(char *, count + 1, "globs"); for (unsigned i = 0; i < count; i++) { stacktop->fileglob[i] = clone_str(files[i], "glob"); } stacktop->fileglob[count] = NULL; parser_y_eof(logger); } void parser_y_include (const char *filename, struct logger *logger) { /* * 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'; } struct lswglob_context context = { .filename = filename, }; if (filename[0] != '/' || rootdir[0] == '\0') { /* try plain name, with no rootdirs */ context.try = filename; if (lswglob(context.try, "ipsec.conf", glob_include, &context, logger)) { return; } /* * Not a wildcard, throw error. * * XXX: throw? */ parser_warning(logger, /*errno*/0, "could not open include filename: '%s'", filename); return; } /* try prefixing with rootdir */ char newname[PATH_MAX]; snprintf(newname, sizeof(newname), "%s%s", rootdir, filename); context.try = newname; if (lswglob(context.try, "ipsec.conf", glob_include, &context, logger)) { return; } if (rootdir2[0] == '\0') { /* not a wildcard, throw error */ parser_warning(logger, /*errno*/0, "could not open include filename '%s' (tried '%s')", filename, newname); return; } /* try again, prefixing with rootdir2 */ char newname2[PATH_MAX]; snprintf(newname2, sizeof(newname2), "%s%s", rootdir2, filename); context.try = newname2; if (lswglob(context.try, "ipsec.conf", glob_include, &context, logger)) { return; } parser_warning(logger, /*errno*/0, "could not open include filename: '%s' (tried '%s' and '%s')", filename, newname, newname2); return; } static bool parser_y_eof(struct logger *logger) { if (stacktop->state != YY_CURRENT_BUFFER) { yy_delete_buffer(YY_CURRENT_BUFFER); } if (!parser_y_nextglobfile(stacktop, logger)) { /* no more glob'ed files to process */ if (lex_verbosity > 0) { int stackp = ic_private.stack_ptr; ldbg(logger, "end of file %s", stacktop->filename); if (stackp > 0) { ldbg(logger, "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 true; } stacktop = &ic_private.stack[ic_private.stack_ptr]; } return false; } /* * Look for one of the tokens, and set the value up right. * * If we don't find it, clone and return the string. */ static bool parse_leftright(const char *s, const struct keyword_def *k, const char *leftright) { size_t split = strlen(leftright); if (!strncaseeq(s, leftright, strlen(leftright))) { return false; } /* allow -; s[split] could be '\0' */ if (s[split] == '-') { split++; } /* keyword matches? */ if (!strcaseeq(s + split, k->keyname)) { return false; } /* success */ return true; } /* type is really "token" type, which is actually int */ static void parser_find_keyword(const char *s, YYSTYPE *lval, struct logger *logger) { bool left = false; bool right = false; (*lval) = (YYSTYPE) {0}; const struct keyword_def *k; for (k = ipsec_conf_keywords; k->keyname != NULL; k++) { if (strcaseeq(s, k->keyname)) { if ((k->validity & kv_both) == kv_both) { left = true; right = true; break; } if (k->validity & kv_leftright) { #if 0 /* see github#663 */ left = true; #endif right = true; } break; } if (k->validity & kv_leftright) { left = parse_leftright(s, k, "left"); if (left) { break; } right = parse_leftright(s, k, "right"); if (right) { break; } } } /* if we still found nothing */ if (k->keyname == NULL) { parser_fatal(logger, /*errno*/0, "unrecognized keyword '%s'", s); } /* else, set up llval.k to point, and return KEYWORD */ lval->k.keydef = k; lval->k.keyleft = left; lval->k.keyright = right; } %} /* lexical states: * * INITIAL: pre-defined and default lex state * * COMMENT_KEY, KEY: just matched the "x-comment", other keyword; * expecting '=' * * VALUE: just matched '=' in KEY state; matches a quoted/braced/raw * string; 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 COMMENT_KEY COMMENT_VALUE %% <> { ldbg(logger, "EOF: stacktop->filename = %s", stacktop->filename == NULL ? "" : stacktop->filename); /* * 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(logger)) { yyterminate(); } } ^[\t ]*#.*\n { /* eat comment lines */ stacktop->line++; } ^[\t ]*\n { /* eat blank lines */ stacktop->line++; } ^[\t ]+ return FIRST_SPACES; [\t ]+ /* ignore spaces in line */ ; %forever { /* a number, really 0 */ yylval.s = clone_str("0", "string"); BEGIN INITIAL; return STRING; } [\t ] /* eat blanks */ \n { /* missing equals? */ stacktop->line++; BEGIN INITIAL; return EOL; } = { BEGIN VALUE; return EQUAL; } [\t ] /* eat blanks (not COMMENT_VALUE) */ \n { /* missing value? (not COMMENT_VALUE) */ stacktop->line++; BEGIN INITIAL; return EOL; } \"[^\"\n]*\" { /* "string" */ char *s = yytext + 1; int len = strlen(s); assert(len>0); /* remove trailing " */ s[len-1] = '\0'; yylval.s = clone_str(s, "yyval.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'; yylval.s = clone_str(s, "yyval.s"); BEGIN INITIAL; return STRING; } [^\" \t\n]+ { /* string-without-quotes-or-blanks */ yylval.s = clone_str(yytext, "string-without-quotes-or-blanks"); BEGIN INITIAL; return STRING; } [^\{} \t\n]+ { /* string-without-braces-or-blanks */ yylval.s = clone_str(yytext, "string-without-braces-or-blanks"); BEGIN INITIAL; return STRING; } \n { stacktop->line++; return EOL; } = { BEGIN VALUE; return EQUAL; } version { BEGIN VALUE; return VERSION; } config return CONFIG; setup return SETUP; conn { BEGIN VALUE; return CONN; } include { BEGIN VALUE; return INCLUDE; } [Xx][_-][^\"= \t\n]+ { yylval.s = clone_str(yytext, "X-s"); BEGIN COMMENT_KEY; return COMMENT; } [\t ] /* eat blanks */ = { BEGIN COMMENT_VALUE; return EQUAL; } \n { /* missing equals? */ stacktop->line++; BEGIN INITIAL; return EOL; } \n { BEGIN INITIAL; return EOL; } [^\n]* { yylval.s = clone_str(yytext, "comment-value"); BEGIN INITIAL; return STRING; } [^\"= \t\n]+ { parser_find_keyword(yytext, &yylval, logger); BEGIN KEY; return KEYWORD; } #.* { /* eat comment to end of line */ } . { parser_warning(logger, /*errno*/0, "unrecognized: %s", yytext); } %% int yywrap(void) { return 1; } libreswan-5.2/lib/libipsecconf/parser.y000066400000000000000000000406661475767661000203010ustar00rootroot00000000000000%{ /* -*- 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" #include "lswlog.h" #include "lmod.h" #include "sparse_names.h" #include "lswalloc.h" #define YYERROR_VERBOSE #define ERRSTRING_LEN 256 /** * Static Globals */ static bool save_errors; static struct parser { struct config_parsed *cfg; struct kw_list **kw; enum section { SECTION_CONFIG_SETUP, SECTION_CONN_DEFAULT, SECTION_CONN, } section; struct starter_comments_list *comments; } parser; static void parser_kw_warning(struct logger *logger, struct keyword *kw, const char *yytext, const char *s, ...) PRINTF_LIKE(4); void parser_kw(struct keyword *kw, const char *string, struct logger *logger); static void yyerror(struct logger *logger, const char *msg); static void new_parser_kw(struct keyword *keyword, const char *string, uintmax_t number, deltatime_t time, struct logger *logger); /** * Functions */ %} %param {struct logger *logger} %union { char *s; bool boolean; struct keyword k; } %token EQUAL FIRST_SPACES EOL CONFIG SETUP CONN INCLUDE VERSION %token STRING %token KEYWORD %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 (UNSIGNED) and with version 2.0 (STRING, now NUMBER/float was removed */ versionstmt: /* NULL */ | VERSION STRING EOL blanklines { /* free strings allocated by lexer */ pfreeany($2); } ; blanklines: /* NULL */ | blanklines EOL ; sections: /* NULL */ | sections section_or_include blanklines ; section_or_include: CONFIG SETUP EOL { parser.kw = &parser.cfg->config_setup; parser.section = SECTION_CONFIG_SETUP; ldbg(logger, "reading config setup"); } kw_sections | CONN STRING EOL { struct section_list *section = alloc_thing(struct section_list, "section list"); PASSERT(logger, section != NULL); section->name = clone_str($2, "section->name"); section->kw = NULL; TAILQ_INSERT_TAIL(&parser.cfg->sections, section, link); /* setup keyword section to record values */ parser.kw = §ion->kw; parser.section = (streq(section->name, "%default") ? SECTION_CONN_DEFAULT : SECTION_CONN); ldbg(logger, "reading conn %s", section->name); /* free strings allocated by lexer */ pfreeany($2); } kw_sections | INCLUDE STRING EOL { parser_y_include($2, logger); /* free strings allocated by lexer */ pfreeany($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 { /* * Because the third argument was also a keyword, we * dig up the string representation. * * There should be a way to stop the lexer converting * the third field into a keyword. */ struct keyword kw = $1; const char *value = $3.keydef->keyname; parser_kw(&kw, value, logger); } | KEYWORD EQUAL STRING { struct keyword kw = $1; const char *string = $3; parser_kw(&kw, string, logger); /* free strings allocated by lexer */ pfreeany($3); } | KEYWORD EQUAL { struct keyword kw = $1; parser_kw(&kw, "", logger); } | COMMENT EQUAL STRING { parser_warning(logger, 0/*error*/, "X- style comment ignored: %s=%s", $1, $3); /* free strings allocated by lexer */ pfreeany($1); pfreeany($3); } | COMMENT EQUAL { parser_warning(logger, 0/*error*/, "X- style comment ignored: %s=", $1); /* free strings allocated by lexer */ pfreeany($1); } | COMMENT { parser_warning(logger, 0/*error*/, "X- style comment ignored: %s", $1); /* free strings allocated by lexer */ pfreeany($1); } ; %% void parser_warning(struct logger *logger, int error, const char *s, ...) { if (save_errors) { LLOG_JAMBUF(RC_LOG, logger, buf) { jam(buf, "%s:%u: warning: ", parser_cur_filename(), parser_cur_line()); va_list ap; va_start(ap, s); jam_va_list(buf, s, ap); va_end(ap); if (error > 0) { jam_errno(buf, error); } } } } void parser_fatal(struct logger *logger, int error, const char *s, ...) { struct logjam logjam; struct jambuf *buf = jambuf_from_logjam(&logjam, logger, PLUTO_EXIT_FAIL, NULL/*where*/, FATAL_STREAM); { jam(buf, "%s:%u: ", parser_cur_filename(), parser_cur_line()); va_list ap; va_start(ap, s); jam_va_list(buf, s, ap); va_end(ap); if (error > 0) { jam_errno(buf, error); } } fatal_logjam_to_logger(&logjam); } static const char *leftright(struct keyword *kw) { if (kw->keyleft && !kw->keyright) { return "left"; } if (!kw->keyleft && kw->keyright) { return "right"; } return ""; } void parser_kw_warning(struct logger *logger, struct keyword *kw, const char *yytext, const char *s, ...) { if (save_errors) { LLOG_JAMBUF(RC_LOG, logger, buf) { jam(buf, "%s:%u: warning: ", parser_cur_filename(), parser_cur_line()); va_list ap; va_start(ap, s); jam_va_list(buf, s, ap); va_end(ap); jam_string(buf, ": "); jam_string(buf, leftright(kw)); jam_string(buf, kw->keydef->keyname); jam_string(buf, "="); jam_string(buf, yytext); } } } void yyerror(struct logger *logger, const char *s) { if (save_errors) { LLOG_JAMBUF(RC_LOG, logger, buf) { jam(buf, "%s:%u: ", parser_cur_filename(), parser_cur_line()); jam_string(buf, s); } } } struct config_parsed *parser_load_conf(const char *file, struct logger *logger) { parser.cfg = alloc_thing(struct config_parsed, __func__); PASSERT(logger, parser.cfg != NULL); ldbg(logger, "allocated config %p", parser.cfg); FILE *f = (streq(file, "-") ? fdopen(STDIN_FILENO, "r") : fopen(file, "r")); if (f == NULL) { llog(RC_LOG, logger, "can't load file '%s'", file); goto err; } yyin = f; parser_y_init(file, f); save_errors = true; TAILQ_INIT(&parser.cfg->sections); if (yyparse(logger) != 0) { save_errors = false; do {} while (yyparse(logger) != 0); goto err; } /** * Config valid */ struct config_parsed *cfg = parser.cfg; parser.cfg = NULL; ldbg(logger, "allocated config %p", cfg->conn_default.kw); return cfg; err: parser_freeany_config_parsed(&parser.cfg); return NULL; } static void parser_free_kwlist(struct kw_list *list) { while (list != NULL) { /* advance */ struct kw_list *elt = list; list = list->next; /* free */ pfreeany(elt->string); pfree(elt); } } void parser_freeany_config_parsed(struct config_parsed **cfgp) { if ((*cfgp) != NULL) { struct config_parsed *cfg = (*cfgp); parser_free_kwlist(cfg->config_setup); for (struct section_list *seci = TAILQ_FIRST(&cfg->sections); seci != NULL; ) { /* step off */ struct section_list *sec = seci; seci = TAILQ_NEXT(seci, link); pfreeany(sec->name); parser_free_kwlist(sec->kw); pfree(sec); } pfreeany(*cfgp); } } static void new_parser_kw(struct keyword *kw, const char *yytext, uintmax_t number, deltatime_t deltatime, struct logger *logger) { /* both means no prefix */ const char *section = "???"; switch (parser.section) { case SECTION_CONFIG_SETUP: section = "'config setup'"; if ((kw->keydef->validity & kv_config) == LEMPTY) { parser_kw_warning(logger, kw, yytext, "invalid %s keyword ignored", section); /* drop it on the floor */ return; } break; case SECTION_CONN: section = "conn"; if ((kw->keydef->validity & kv_conn) == LEMPTY) { parser_kw_warning(logger, kw, yytext, "invalid %s keyword ignored", section); /* drop it on the floor */ return; } break; case SECTION_CONN_DEFAULT: section = "'conn %%default'"; if ((kw->keydef->validity & kv_conn) == LEMPTY || kw->keydef->field == KSCF_ALSO) { parser_kw_warning(logger, kw, yytext, "invalid %s keyword ignored", section); /* drop it on the floor */ return; } break; } /* Find end, while looking for duplicates. */ struct kw_list **end; for (end = parser.kw; (*end) != NULL; end = &(*end)->next) { if ((*end)->keyword.keydef != kw->keydef) { continue; } if (((*end)->keyword.keyleft != kw->keyleft) && ((*end)->keyword.keyright != kw->keyright)) { continue; } if (kw->keydef->validity & kv_duplicateok) { continue; } /* note the weird behaviour! */ if (parser.section == SECTION_CONFIG_SETUP) { parser_kw_warning(logger, kw, yytext, "overriding earlier %s keyword with new value", section); pfreeany((*end)->string); (*end)->string = clone_str(yytext, "keyword.string"); /*handles NULL*/ (*end)->number = number; (*end)->deltatime = deltatime; return; } parser_kw_warning(logger, kw, yytext, "ignoring duplicate %s keyword", section); return; } /* * fill the values into new * (either string or number might have a placeholder value */ struct kw_list *new = alloc_thing(struct kw_list, "kw_list"); (*new) = (struct kw_list) { .keyword = *kw, .string = clone_str(yytext, "keyword.list"), /*handles NULL*/ .number = number, .deltatime = deltatime, }; ldbgf(DBG_TMI, logger, " %s%s=%s number=%ju field=%u", kw->keydef->keyname, leftright(kw), new->string, new->number, kw->keydef->field); /* append the new kw_list to the list */ (*end) = new; } static bool parser_kw_unsigned(struct keyword *kw, const char *yytext, uintmax_t *number, struct logger *logger) { err_t err = shunk_to_uintmax(shunk1(yytext), NULL, /*base*/10, number); if (err != NULL) { parser_kw_warning(logger, kw, yytext, "%s, keyword ignored", err); return false; } return true; } static bool parser_kw_bool(struct keyword *kw, const char *yytext, uintmax_t *number, struct logger *logger) { const struct sparse_name *name = sparse_lookup(&yn_option_names, shunk1(yytext)); if (name == NULL) { parser_kw_warning(logger, kw, yytext, "invalid boolean, keyword ignored"); return false; } enum yn_options yn = name->value; switch (yn) { case YN_YES: (*number) = true; return true; case YN_NO: (*number) = false; return true; case YN_UNSET: break; } bad_case(yn); } static bool parser_kw_deltatime(struct keyword *kw, const char *yytext, enum timescale default_timescale, deltatime_t *deltatime, struct logger *logger) { diag_t diag = ttodeltatime(yytext, deltatime, default_timescale); if (diag != NULL) { parser_kw_warning(logger, kw, yytext, "%s, keyword ignored", str_diag(diag)); pfree_diag(&diag); return false; } return true; } static bool parser_kw_percent(struct keyword *kw, const char *yytext, uintmax_t *number, struct logger *logger) { shunk_t end; err_t err = shunk_to_uintmax(shunk1(yytext), &end, /*base*/10, number); if (err != NULL) { parser_kw_warning(logger, kw, yytext, "%s, percent keyword ignored", err); return false; } if (!hunk_streq(end, "%")) { parser_kw_warning(logger, kw, yytext, "bad percentage multiplier \""PRI_SHUNK"\", keyword ignored", pri_shunk(end)); return false; } if ((*number) > UINT_MAX) { parser_kw_warning(logger, kw, yytext, "percentage way too large, keyword ignored"); return false; } return true; } static bool parser_kw_binary(struct keyword *kw, const char *yytext, uintmax_t *number, struct logger *logger) { diag_t diag = ttobinary(yytext, number, 0 /* no B prefix */); if (diag != NULL) { parser_kw_warning(logger, kw, yytext, "%s, keyword ignored", str_diag(diag)); pfree_diag(&diag); return false; } return true; } static bool parser_kw_byte(struct keyword *kw, const char *yytext, uintmax_t *number, struct logger *logger) { diag_t diag = ttobinary(yytext, number, 1 /* with B prefix */); if (diag != NULL) { parser_kw_warning(logger, kw, yytext, "%s, keyword ignored", str_diag(diag)); pfree_diag(&diag); return false; } return true; } static bool parser_kw_lset(struct keyword *kw, const char *yytext, uintmax_t *number, struct logger *logger) { lmod_t result = {0}; /* * 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, kw->keydef->info, yytext, true/*enable*/)) { /* * If the lookup failed, complain. * * XXX: the error diagnostic is a little vague - * should lmod_arg() instead return the error? */ parser_kw_warning(logger, kw, yytext, "invalid, keyword ignored"); return false; } /* no truncation */ PEXPECT(logger, sizeof(*number) == sizeof(result.set)); (*number) = result.set; return true; } static bool parser_kw_sparse_name(struct keyword *kw, const char *yytext, uintmax_t *number, struct logger *logger) { PASSERT(logger, kw->keydef->sparse_names != NULL); const struct sparse_name *sn = sparse_lookup(kw->keydef->sparse_names, shunk1(yytext)); if (sn != NULL) { (*number) = sn->value; return true; } /* * We didn't find anything, complain. * * XXX: call jam_sparse_names() to list what is valid? */ parser_kw_warning(logger, kw, yytext, "invalid, keyword ignored"); return false; } static bool parser_kw_loose_sparse_name(struct keyword *kw, const char *yytext, uintmax_t *number, struct logger *logger) { PASSERT(logger, (kw->keydef->type == kt_host || kw->keydef->type == kt_pubkey)); PASSERT(logger, kw->keydef->sparse_names != NULL); const struct sparse_name *sn = sparse_lookup(kw->keydef->sparse_names, shunk1(yytext)); if (sn != NULL) { PASSERT(logger, sn->value != LOOSE_ENUM_OTHER); (*number) = sn->value; return true; } (*number) = LOOSE_ENUM_OTHER; /* i.e., use string value */ return true; } void parser_kw(struct keyword *kw, const char *string, struct logger *logger) { uintmax_t number = 0; /* neutral placeholding value */ deltatime_t deltatime = {.is_set = false, }; bool ok = true; switch (kw->keydef->type) { case kt_lset: ok = parser_kw_lset(kw, string, &number, logger); break; case kt_sparse_name: ok = parser_kw_sparse_name(kw, string, &number, logger); break; case kt_pubkey: case kt_host: ok = parser_kw_loose_sparse_name(kw, string, &number, logger); break; case kt_string: case kt_also: 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: break; case kt_unsigned: ok = parser_kw_unsigned(kw, string, &number, logger); break; case kt_seconds: ok = parser_kw_deltatime(kw, string, TIMESCALE_SECONDS, &deltatime, logger); break; case kt_milliseconds: ok = parser_kw_deltatime(kw, string, TIMESCALE_MILLISECONDS, &deltatime, logger); break; case kt_bool: ok = parser_kw_bool(kw, string, &number, logger); break; case kt_percent: ok = parser_kw_percent(kw, string, &number, logger); break; case kt_binary: ok = parser_kw_binary(kw, string, &number, logger); break; case kt_byte: ok = parser_kw_byte(kw, string, &number, logger); break; case kt_obsolete: /* drop it on the floor */ parser_kw_warning(logger, kw, string, "obsolete keyword ignored"); ok = false; break; } if (ok) { new_parser_kw(kw, string, number, deltatime, logger); } } libreswan-5.2/lib/libipsecconf/starterwhack.c000066400000000000000000000424221475767661000214510ustar00rootroot00000000000000/* * 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 * Copyright (C) 2020 Nupur Agrawal * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY 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 "lswalloc.h" #include "lswlog.h" #include "whack.h" #include "id.h" #include "ip_address.h" #include "ip_info.h" #include "lswlog.h" static bool set_whack_end(struct whack_end *w, const struct starter_end *l, struct logger *logger) { const char *lr = l->leftright; w->leftright = lr; /* validate the KSCF_ID */ if (l->values[KSCF_ID].string != NULL) { char *value = l->values[KSCF_ID].string; /* * Fixup old ",," in a ID_DER_ASN1_DN to proper * backslash comma. */ if (value[0] != '@' && strstr(value, ",,") != NULL && strstr(value, "=") != NULL) { llog(RC_LOG, logger, "changing legacy ',,' to '\\,' in %sid=%s", lr, value); char *cc; while ((cc = strstr(value, ",,")) != NULL) { cc[0] = '\\'; } } w->id = value; } else if (l->addrtype == KH_IPADDR) { address_buf b; w->id = clone_str(str_address(&l->addr, &b), "if 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->values[KW_IP].string; switch (l->nexttype) { case KH_IPADDR: w->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->nexthop = l->host_family->address.unspec; break; default: printf("%s: do something with nexthop case: %d\n", lr, l->nexttype); break; } w->sourceip = l->values[KSCF_SOURCEIP].string; /* could be NULL */ if (cidr_is_specified(l->vti_ip)) w->host_vtiip = l->vti_ip; w->interface_ip = l->values[KSCF_INTERFACE_IP].string; /* could be NULL */ /* validate the KSCF_SUBNET */ if (l->values[KSCF_SUBNET].string != NULL) { char *value = l->values[KSCF_SUBNET].string; if (startswith(value, "vhost:") || startswith(value, "vnet:")) { w->virt = value; } else { w->subnet = value; } } w->subnets = l->values[KSCF_SUBNETS].string; w->host_ikeport = l->values[KNCF_IKEPORT].option; if (l->values[KSCF_PROTOPORT].set) { char *value = l->values[KSCF_PROTOPORT].string; err_t ugh = ttoprotoport(value, &w->protoport); if (ugh != NULL) { llog_error(logger, 0, "bad %sprotoport=%s [%s]", lr, value, ugh); return false; } } w->cert = l->values[KSCF_CERT].string; w->ckaid = l->values[KSCF_CKAID].string; static const struct { enum ipseckey_algorithm_type alg; enum keywords kscf; const char *name; } keys[] = { { .alg = IPSECKEY_ALGORITHM_RSA, KW_RSASIGKEY, "rsasigkey", }, { .alg = IPSECKEY_ALGORITHM_ECDSA, KW_ECDSAKEY, "ecdsakey", }, { .alg = IPSECKEY_ALGORITHM_X_PUBKEY, KW_PUBKEY, "pubkey", }, }; FOR_EACH_ELEMENT(key, keys) { if (!l->values[key->kscf].set) { continue; } switch (l->values[key->kscf].option) { case PUBKEY_DNSONDEMAND: w->key_from_DNS_on_demand = true; break; case 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. */ w->key_from_DNS_on_demand = false; w->pubkey = l->values[key->kscf].string; w->pubkey_alg = key->alg; break; default: w->key_from_DNS_on_demand = false; break; } break; } w->ca = l->values[KSCF_CA].string; if (l->values[KNCF_SENDCERT].set) w->sendcert = l->values[KNCF_SENDCERT].option; else w->sendcert = CERT_ALWAYSSEND; if (l->values[KNCF_AUTH].set) w->auth = l->values[KNCF_AUTH].option; if (l->values[KNCF_EAP].set) w->eap = l->values[KNCF_EAP].option; else w->eap = IKE_EAP_NONE; w->updown = l->values[KSCF_UPDOWN].string; if (l->values[KNCF_XAUTHSERVER].set) w->xauth_server = l->values[KNCF_XAUTHSERVER].option; if (l->values[KNCF_XAUTHCLIENT].set) w->xauth_client = l->values[KNCF_XAUTHCLIENT].option; if (l->values[KSCF_USERNAME].set) w->xauth_username = l->values[KSCF_USERNAME].string; if (l->values[KSCF_GROUNDHOG].set) w->groundhog = l->values[KSCF_GROUNDHOG].string; w->modecfgserver = l->values[KNCF_MODECONFIGSERVER].option; w->modecfgclient = l->values[KNCF_MODECONFIGCLIENT].option; w->cat = l->values[KNCF_CAT].option; /* yn_options */ w->addresspool = l->values[KSCF_ADDRESSPOOL].string; return true; } static int starter_whack_add_pubkey(const char *leftright, const char *ctlsocket, const struct starter_conn *conn, char *keyid, const char *pubkey, enum ipseckey_algorithm_type pubkey_alg, struct logger *logger) { struct whack_message msg = { .whack_from = WHACK_FROM_ADDCONN, .whack_key = true, .pubkey_alg = pubkey_alg, .keyid = keyid, }; int base; switch (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(pubkey_alg); } chunk_t keyspace = NULL_HUNK; /* must free */ err_t err = ttochunk(shunk1(pubkey), base, &keyspace); if (err != NULL) { enum_buf pkb; llog_error(logger, 0, "conn %s: %s%s malformed [%s]", conn->name, leftright, str_enum(&ipseckey_algorithm_config_names, pubkey_alg, &pkb), err); return 1; } enum_buf pkb; ldbg(logger, "\tsending %s %s%s=%s", conn->name, leftright, str_enum(&ipseckey_algorithm_config_names, pubkey_alg, &pkb), pubkey); msg.keyval = keyspace; int ret = whack_send_msg(&msg, ctlsocket, NULL, NULL, 0, 0, logger); free_chunk_content(&keyspace); if (ret < 0) { return ret; } return 0; } static void conn_log_val(struct logger *logger, const struct starter_conn *conn, const char *name, const char *value) { if (value != NULL) { ldbg(logger, "conn: \"%s\" %s=%s", conn->name, name, value); } } int starter_whack_add_conn(const char *ctlsocket, const struct starter_conn *conn, struct logger *logger) { struct whack_message msg = { .whack_from = WHACK_FROM_ADDCONN, .whack_add = true, .name = conn->name, }; msg.host_afi = conn->end[LEFT_END].host_family; msg.child_afi = conn->clientaddrfamily; if (conn->end[RIGHT_END].addrtype == KH_IPHOSTNAME) msg.dnshostname = conn->end[RIGHT_END].values[KW_IP].string; msg.nic_offload = conn->values[KNCF_NIC_OFFLOAD].option; if (conn->values[KNCF_IKELIFETIME].set) { msg.ikelifetime = conn->values[KNCF_IKELIFETIME].deltatime; } if (conn->values[KNCF_IPSEC_LIFETIME].set) { msg.ipsec_lifetime = conn->values[KNCF_IPSEC_LIFETIME].deltatime; } if (conn->values[KNCF_REKEYMARGIN].set) { msg.rekeymargin = conn->values[KNCF_REKEYMARGIN].deltatime; } msg.sa_ipsec_max_bytes = conn->values[KNCF_IPSEC_MAXBYTES].option; msg.sa_ipsec_max_packets = conn->values[KNCF_IPSEC_MAXPACKETS].option; msg.sa_rekeyfuzz_percent = conn->values[KNCF_REKEYFUZZ].option; if (conn->values[KNCF_KEYINGTRIES].set) { msg.keyingtries.set = true; msg.keyingtries.value = conn->values[KNCF_KEYINGTRIES].option; } msg.replay_window = conn->values[KNCF_REPLAY_WINDOW].option; /*has default*/ msg.ipsec_interface = conn->values[KWS_IPSEC_INTERFACE].string; if (conn->values[KNCF_RETRANSMIT_INTERVAL].set) { msg.retransmit_interval = conn->values[KNCF_RETRANSMIT_INTERVAL].deltatime; } if (conn->values[KNCF_RETRANSMIT_TIMEOUT].set) { msg.retransmit_timeout = conn->values[KNCF_RETRANSMIT_TIMEOUT].deltatime; } msg.ike_version = conn->ike_version; msg.ikev2 = conn->values[KNCF_IKEv2].option; msg.pfs = conn->values[KNCF_PFS].option; msg.compress = conn->values[KNCF_COMPRESS].option; msg.type = conn->values[KNCF_TYPE].option; msg.phase2 = conn->values[KNCF_PHASE2].option; msg.authby = conn->authby; msg.sighash_policy = conn->sighash_policy; msg.never_negotiate_shunt = conn->never_negotiate_shunt; msg.negotiation_shunt = conn->negotiation_shunt; msg.failure_shunt = conn->failure_shunt; msg.autostart = conn->values[KNCF_AUTO].option; msg.connalias = conn->values[KSCF_CONNALIAS].string; msg.metric = conn->values[KNCF_METRIC].option; msg.narrowing = conn->values[KNCF_NARROWING].option; msg.rekey = conn->values[KNCF_REKEY].option; msg.reauth = conn->values[KNCF_REAUTH].option; if (conn->values[KNCF_MTU].set) msg.mtu = conn->values[KNCF_MTU].option; if (conn->values[KNCF_PRIORITY].set) msg.priority = conn->values[KNCF_PRIORITY].option; if (conn->values[KNCF_TFC].set) msg.tfc = conn->values[KNCF_TFC].option; if (conn->values[KNCF_NO_ESP_TFC].set) msg.send_no_esp_tfc = conn->values[KNCF_NO_ESP_TFC].option; if (conn->values[KNCF_NFLOG_CONN].set) msg.nflog_group = conn->values[KNCF_NFLOG_CONN].option; if (conn->values[KNCF_REQID].set) { if (conn->values[KNCF_REQID].option <= 0 || conn->values[KNCF_REQID].option > IPSEC_MANUAL_REQID_MAX) { llog_error(logger, 0, "ignoring reqid value - range must be 1-%u", IPSEC_MANUAL_REQID_MAX); } else { msg.sa_reqid = conn->values[KNCF_REQID].option; } } if (conn->values[KNCF_TCP_REMOTEPORT].set) { msg.tcp_remoteport = conn->values[KNCF_TCP_REMOTEPORT].option; } if (conn->values[KNCF_ENABLE_TCP].set) { msg.enable_tcp = conn->values[KNCF_ENABLE_TCP].option; } /* default to HOLD */ msg.dpddelay = conn->values[KSCF_DPDDELAY].string; msg.dpdtimeout = conn->values[KSCF_DPDTIMEOUT].string; if (conn->values[KNCF_SEND_CA].set) msg.send_ca = conn->values[KNCF_SEND_CA].option; else msg.send_ca = CA_SEND_NONE; msg.encapsulation = conn->values[KNCF_ENCAPSULATION].option; if (conn->values[KNCF_NAT_KEEPALIVE].set) msg.nat_keepalive = conn->values[KNCF_NAT_KEEPALIVE].option; else msg.nat_keepalive = true; /* can be 0 aka unset */ msg.nat_ikev1_method = conn->values[KNCF_NAT_IKEv1_METHOD].option; /* Activate sending out own vendorid */ if (conn->values[KNCF_SEND_VENDORID].set) msg.send_vendorid = conn->values[KNCF_SEND_VENDORID].option; /* Activate Cisco quircky behaviour not replacing old IPsec SA's */ if (conn->values[KNCF_INITIAL_CONTACT].set) msg.initial_contact = conn->values[KNCF_INITIAL_CONTACT].option; /* Activate their quircky behaviour - rumored to be needed for ModeCfg and RSA */ if (conn->values[KNCF_CISCO_UNITY].set) msg.cisco_unity = conn->values[KNCF_CISCO_UNITY].option; if (conn->values[KNCF_VID_STRONGSWAN].set) msg.fake_strongswan = conn->values[KNCF_VID_STRONGSWAN].option; /* Active our Cisco interop code if set */ msg.remote_peer_type = conn->values[KNCF_REMOTE_PEER_TYPE].option; #ifdef HAVE_NM /* Network Manager support */ msg.nm_configured = conn->values[KNCF_NM_CONFIGURED].option; #endif msg.sec_label = conn->values[KSCF_SEC_LABEL].string; msg.conn_debug = conn->values[KW_DEBUG].option; msg.modecfgdns = conn->values[KSCF_MODECFGDNS].string; msg.modecfgdomains = conn->values[KSCF_MODECFGDOMAINS].string; msg.modecfgbanner = conn->values[KSCF_MODECFGBANNER].string; msg.mark = conn->values[KSCF_MARK].string; msg.mark_in = conn->values[KSCF_MARK_IN].string; msg.mark_out = conn->values[KSCF_MARK_OUT].string; msg.vti_interface = conn->values[KSCF_VTI_INTERFACE].string; conn_log_val(logger, conn, "vti-interface", msg.vti_interface); msg.vti_routing = conn->values[KNCF_VTI_ROUTING].option; msg.vti_shared = conn->values[KNCF_VTI_SHARED].option; msg.ppk_ids = conn->values[KSCF_PPK_IDS].string; msg.redirect_to = conn->values[KSCF_REDIRECT_TO].string; conn_log_val(logger, conn, "redirect-to", msg.redirect_to); msg.accept_redirect_to = conn->values[KSCF_ACCEPT_REDIRECT_TO].string; conn_log_val(logger, conn, "accept-redirect-to", msg.accept_redirect_to); msg.send_redirect = conn->values[KNCF_SEND_REDIRECT].option; msg.session_resumption = conn->values[KNCF_SESSION_RESUMPTION].option; msg.mobike = conn->values[KNCF_MOBIKE].option; /*yn_options*/ msg.intermediate = conn->values[KNCF_INTERMEDIATE].option; /*yn_options*/ msg.sha2_truncbug = conn->values[KNCF_SHA2_TRUNCBUG].option; /*yn_options*/ msg.overlapip = conn->values[KNCF_OVERLAPIP].option; /*yn_options*/ msg.ms_dh_downgrade = conn->values[KNCF_MS_DH_DOWNGRADE].option; /*yn_options*/ msg.pfs_rekey_workaround = conn->values[KNCF_PFS_REKEY_WORKAROUND].option; msg.dns_match_id = conn->values[KNCF_DNS_MATCH_ID].option; /* yn_options */ msg.pam_authorize = conn->values[KNCF_PAM_AUTHORIZE].option; /* yn_options */ msg.ignore_peer_dns = conn->values[KNCF_IGNORE_PEER_DNS].option; /* yn_options */ msg.ikepad = conn->values[KNCF_IKEPAD].option; /* yna_options */ msg.require_id_on_certificate = conn->values[KNCF_REQUIRE_ID_ON_CERTIFICATE].option; /* yn_options */ msg.modecfgpull = conn->values[KNCF_MODECFGPULL].option; /* yn_options */ msg.aggressive = conn->values[KNCF_AGGRESSIVE].option; /* yn_options */ msg.iptfs = conn->values[KNCF_IPTFS].option; /* yn_options */ msg.iptfs_fragmentation = conn->values[KNCF_IPTFS_FRAGMENTATION].option; /* yn_options */ msg.iptfs_packet_size = conn->values[KNCF_IPTFS_PACKET_SIZE].option; msg.iptfs_max_queue_size = conn->values[KNCF_IPTFS_MAX_QUEUE_SIZE].option; msg.iptfs_reorder_window = conn->values[KNCF_IPTFS_REORDER_WINDOW].option; msg.iptfs_init_delay = conn->values[KNCF_IPTFS_INIT_DELAY].deltatime; msg.iptfs_drop_time = conn->values[KNCF_IPTFS_DROP_TIME].deltatime; msg.decap_dscp = conn->values[KNCF_DECAP_DSCP].option; /* yn_options */ msg.encap_dscp = conn->values[KNCF_ENCAP_DSCP].option; /* yn_options */ msg.nopmtudisc = conn->values[KNCF_NOPMTUDISC].option; /* yn_options */ msg.accept_redirect = conn->values[KNCF_ACCEPT_REDIRECT].option; /* yn_options */ msg.fragmentation = conn->values[KNCF_FRAGMENTATION].option; /* yna_options */ msg.esn = conn->values[KNCF_ESN].option; /* yne_options */ msg.ppk = conn->values[KNCF_PPK].option; /* nppi_options */ if (conn->values[KNCF_XAUTHBY].set) msg.xauthby = conn->values[KNCF_XAUTHBY].option; if (conn->values[KNCF_XAUTHFAIL].set) msg.xauthfail = conn->values[KNCF_XAUTHFAIL].option; if (!set_whack_end(&msg.end[LEFT_END], &conn->end[LEFT_END], logger)) return -1; if (!set_whack_end(&msg.end[RIGHT_END], &conn->end[RIGHT_END], logger)) return -1; msg.esp = conn->values[KSCF_ESP].string; msg.ike = conn->values[KSCF_IKE].string; /* * Save the "computed" pubkeys and IDs before the pointers in * MSG are pickled. */ const char *left_pubkey = msg.end[LEFT_END].pubkey; const char *right_pubkey = msg.end[RIGHT_END].pubkey; char *left_id = msg.end[LEFT_END].id; char *right_id = msg.end[RIGHT_END].id; int r = whack_send_msg(&msg, ctlsocket, NULL, NULL, 0, 0, logger); if (r != 0) return r; /* * XXX: the above sent over the pubkeys, why repeat? * * Because the above sending over pubkeys is a hack (but still * the right thing to do). */ if (left_id != NULL && left_pubkey != NULL) { int r = starter_whack_add_pubkey("left", ctlsocket, conn, left_id, left_pubkey, msg.end[LEFT_END].pubkey_alg, logger); if (r != 0) { return r; } } if (right_id != NULL && right_pubkey != NULL) { int r = starter_whack_add_pubkey("right", ctlsocket, conn, right_id, right_pubkey, msg.end[RIGHT_END].pubkey_alg, logger); if (r != 0) { return r; } } return 0; } int starter_whack_listen(const char *ctlsocket, struct logger *logger) { struct whack_message msg = { .whack_from = WHACK_FROM_ADDCONN, .whack_listen = true, }; return whack_send_msg(&msg, ctlsocket, NULL, NULL, 0, 0, logger); } libreswan-5.2/lib/liblswsd/000077500000000000000000000000001475767661000157625ustar00rootroot00000000000000libreswan-5.2/lib/liblswsd/Makefile000066400000000000000000000014621475767661000174250ustar00rootroot00000000000000# Libreswan library # Copyright (C) 2024 Andrew Cagney # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT 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 LIB = liblswsd.a OBJS += lswsd_notify.o OBJS += lswsd_notifyf.o OBJS += lswsd_watchdog_enabled.o include $(top_srcdir)/mk/library.mk libreswan-5.2/lib/liblswsd/lswsd_notify.c000066400000000000000000000113361475767661000206560ustar00rootroot00000000000000/* SPDX-License-Identifier: MIT-0 */ /* Implement the systemd notify protocol without external dependencies. * Supports both readiness notification on startup and on reloading, * according to the protocol defined at: * https://www.freedesktop.org/software/systemd/man/latest/sd_notify.html * This protocol is guaranteed to be stable as per: * https://systemd.io/PORTABILITY_AND_STABILITY/ */ /* https://www.freedesktop.org/software/systemd/man/devel/sd_notify.html#Notes */ #include #include #include #include #include #include #include #include #include #include #include #include "lswsd.h" #define _cleanup_(f) __attribute__((cleanup(f))) static void closep(int *fd) { if (!fd || *fd < 0) return; close(*fd); *fd = -1; } int lswsd_notify(const char *message) { union sockaddr_union { struct sockaddr sa; struct sockaddr_un sun; } socket_addr = { .sun.sun_family = AF_UNIX, }; size_t path_length, message_length; _cleanup_(closep) int fd = -1; const char *socket_path; socket_path = getenv("NOTIFY_SOCKET"); if (!socket_path) return 0; /* Not running under systemd? Nothing to do */ if (!message) return -EINVAL; message_length = strlen(message); if (message_length == 0) return -EINVAL; /* Only AF_UNIX is supported, with path or abstract sockets */ if (socket_path[0] != '/' && socket_path[0] != '@') return -EAFNOSUPPORT; path_length = strlen(socket_path); /* Ensure there is room for NUL byte */ if (path_length >= sizeof(socket_addr.sun.sun_path)) return -E2BIG; memcpy(socket_addr.sun.sun_path, socket_path, path_length); /* Support for abstract socket */ if (socket_addr.sun.sun_path[0] == '@') socket_addr.sun.sun_path[0] = 0; fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0); if (fd < 0) return -errno; if (connect(fd, &socket_addr.sa, offsetof(struct sockaddr_un, sun_path) + path_length) != 0) return -errno; ssize_t written = write(fd, message, message_length); if (written != (ssize_t) message_length) return written < 0 ? -errno : -EPROTO; return 1; /* Notified! */ } #if 0 int notify_ready(void) { return notify("READY=1"); } int notify_reloading(void) { /* A buffer with length sufficient to format the maximum UINT64 value. */ char reload_message[sizeof("RELOADING=1\nMONOTONIC_USEC=18446744073709551615")]; struct timespec ts; uint64_t now; /* Notify systemd that we are reloading, including a CLOCK_MONOTONIC timestamp in usec * so that the program is compatible with a Type=notify-reload service. */ if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0) return -errno; if (ts.tv_sec < 0 || ts.tv_nsec < 0 || (uint64_t) ts.tv_sec > (UINT64_MAX - (ts.tv_nsec / 1000ULL)) / 1000000ULL) return -EINVAL; now = (uint64_t) ts.tv_sec * 1000000ULL + (uint64_t) ts.tv_nsec / 1000ULL; if (snprintf(reload_message, sizeof(reload_message), "RELOADING=1\nMONOTONIC_USEC=%" PRIu64, now) < 0) return -EINVAL; return notify(reload_message); } static volatile sig_atomic_t reloading = 0; static volatile sig_atomic_t terminating = 0; static void signal_handler(int sig) { if (sig == SIGHUP) reloading = 1; else if (sig == SIGINT || sig == SIGTERM) terminating = 1; } int main(int argc, char **argv) { struct sigaction sa = { .sa_handler = signal_handler, .sa_flags = SA_RESTART, }; int r; /* Setup signal handlers */ sigemptyset(&sa.sa_mask); sigaction(SIGHUP, &sa, NULL); sigaction(SIGINT, &sa, NULL); sigaction(SIGTERM, &sa, NULL); /* Do more service initialization work here … */ /* Now that all the preparations steps are done, signal readiness */ r = notify_ready(); if (r < 0) { fprintf(stderr, "Failed to notify readiness to $NOTIFY_SOCKET: %s\n", strerror(-r)); return EXIT_FAILURE; } while (!terminating) { if (reloading) { reloading = false; /* As a separate but related feature, we can also notify the manager * when reloading configuration. This allows accurate state-tracking, * and also automated hook-in of 'systemctl reload' without having to * specify manually an ExecReload= line in the unit file. */ r = notify_reloading(); if (r < 0) { fprintf(stderr, "Failed to notify reloading to $NOTIFY_SOCKET: %s\n", strerror(-r)); return EXIT_FAILURE; } /* Do some reconfiguration work here … */ r = notify_ready(); if (r < 0) { fprintf(stderr, "Failed to notify readiness to $NOTIFY_SOCKET: %s\n", strerror(-r)); return EXIT_FAILURE; } } /* Do some daemon work here … */ sleep(5); } return EXIT_SUCCESS; } #endif libreswan-5.2/lib/liblswsd/lswsd_notifyf.c000066400000000000000000000012111475767661000210130ustar00rootroot00000000000000/* SPDX-License-Identifier: MIT-0 */ /* Implement the systemd notify protocol without external dependencies. * Supports both readiness notification on startup and on reloading, * according to the protocol defined at: * https://www.freedesktop.org/software/systemd/man/latest/sd_notify.html * This protocol is guaranteed to be stable as per: * https://systemd.io/PORTABILITY_AND_STABILITY/ */ #include "lswsd.h" #include "lswalloc.h" int lswsd_notifyf(const char *string, ...) { va_list ap; va_start(ap, string); char *notify = alloc_vprintf(string, ap); va_end(ap); int result = lswsd_notify(notify); pfree(notify); return result; } libreswan-5.2/lib/liblswsd/lswsd_watchdog_enabled.c000066400000000000000000000024141475767661000226150ustar00rootroot00000000000000/* SPDX-License-Identifier: MIT-0 */ /* Implement the systemd notify protocol without external dependencies. * Supports both readiness notification on startup and on reloading, * according to the protocol defined at: * https://www.freedesktop.org/software/systemd/man/latest/sd_notify.html * This protocol is guaranteed to be stable as per: * https://systemd.io/PORTABILITY_AND_STABILITY/ */ #include "stdlib.h" /* for getenv() */ #include "unistd.h" /* for getpid() */ #include "lswsd.h" #include "lswalloc.h" #include "shunk.h" /* for robust string conversions */ int lswsd_watchdog_enabled(uintmax_t *usec) { /* * Spec says that either WATCHDOG_PID is NULL or matches * getpid(). */ const char *watchdog_pid = getenv("WATCHDOG_PID"); if (watchdog_pid != NULL) { uintmax_t pid; if (shunk_to_uintmax(shunk1(watchdog_pid), NULL/*all*/, 10/*base*/, &pid) != NULL) { return -1; } if ((pid_t)pid != getpid()) { return -1; } } /* * Spec when WATCHDOG_USEC isn't set things aren't enabled. */ const char *watchdog_usec = getenv("WATCHDOG_USEC"); if (watchdog_usec == NULL) { return 0; /* not enabled */ } if (shunk_to_uintmax(shunk1(watchdog_usec), NULL/*all*/, 10/*base*/, usec) != NULL) { return -1; /* invalid */ } return 1; /* enabled */ } libreswan-5.2/lib/liblswtool/000077500000000000000000000000001475767661000163315ustar00rootroot00000000000000libreswan-5.2/lib/liblswtool/Makefile000066400000000000000000000014311475767661000177700ustar00rootroot00000000000000# 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-5.2/lib/liblswtool/libreswan_exit.c000066400000000000000000000013301475767661000215110ustar00rootroot00000000000000/* * 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-5.2/lib/liblswtool/lswlog.c000066400000000000000000000061421475767661000200070ustar00rootroot00000000000000/* * 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" #include "lswalloc.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; } const struct logger_object_vec progname_object_vec = { .name = "tool", .jam_object_prefix = jam_progname_prefix, }; static struct logger progname_logger = { .object_vec = &progname_object_vec, .object = NULL, /* progname */ }; struct logger *tool_logger(int argc UNUSED, char *argv[]) { const char *last_slash = strrchr(argv[0], '/'); const char *last_name = (last_slash == NULL ? argv[0] : last_slash + 1); /* need to allocate string then mark as never free */ ssize_t name_size = sizeof("ipsec "/*includes \0*/) + strlen(last_name) + 1/*to be sure*/; char *name = alloc_things(char, name_size, "(ignore)progname"); /* snprintf() returns length, not size */ passert(name_size > snprintf(name, name_size, "ipsec %s", last_name)); progname_logger.object = progname = name; /* redundant? */ setbuf(stderr, NULL); return &progname_logger; } void jambuf_to_logger(struct jambuf *buf, const struct logger *logger UNUSED, lset_t rc_flags) { enum stream stream = (rc_flags & STREAM_MASK); switch (stream) { case ALL_STREAMS: case LOG_STREAM: if (log_to_stderr) { fprintf(stderr, "%s\n", buf->array); } return; case WHACK_STREAM: /* AKA the console */ fprintf(stdout, "%s\n", buf->array); return; case FATAL_STREAM: case DEBUG_STREAM: case ERROR_STREAM: case PEXPECT_STREAM: fprintf(stderr, "%s\n", buf->array); return; case PASSERT_STREAM: fprintf(stderr, "%s\n", buf->array); return; /*abort();?*/ 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. */ return; } fprintf(stderr, "bad stream %d", stream); abort(); /* not bad_case(stream) as recursive */ } libreswan-5.2/lib/libswan/000077500000000000000000000000001475767661000155765ustar00rootroot00000000000000libreswan-5.2/lib/libswan/DBG_dump.c000066400000000000000000000024631475767661000173700ustar00rootroot00000000000000/* 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-5.2/lib/libswan/DBG_log.c000066400000000000000000000020261475767661000171770ustar00rootroot00000000000000/* 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, ...) { LLOG_JAMBUF(DEBUG_STREAM, &global_logger, buf) { va_list args; va_start(args, message); jam_va_list(buf, message, args); va_end(args); } } libreswan-5.2/lib/libswan/Makefile000066400000000000000000000165041475767661000172440ustar00rootroot00000000000000# 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 += option_names.o OBJS += encap_type_names.o OBJS += encap_mode_names.o OBJS += encap_proto_names.o OBJS += initiated_by_names.o OBJS += connection_owner_names.o OBJS += sa_type.o OBJS += fips_mode.o OBJS += fips_mode_names.o OBJS += state_category_names.o OBJS += end_names.o OBJS += terminate_reason_names.o OBJS += constants.o \ id.o \ lex.o \ lswconf.o \ sameaddr.o \ ttodata.o \ ttosaid.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_dns.o OBJS += ttoaddress_num.o OBJS += ttoaddresses_num.o OBJS += ttocidr_num.o OBJS += ttoprotocol.o OBJS += ttorange_num.o OBJS += ttoranges_num.o OBJS += ttoselector_num.o OBJS += ttoselectors_num.o OBJS += ttosubnet_num.o OBJS += ttosubnets_num.o OBJS += ttoips_num.o OBJS += ttobool.o OBJS += ttobinary-iec-60027-2.o OBJS += ttoport.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 OBJS += kernel_mode.o ifneq ($(LINUX_VARIANT),) OBJS += kernel_netlink_reply.o OBJS += kernel_netlink_query.o OBJS += linux_netlink.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 += message_role.o OBJS += sa_role.o OBJS += datatot.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 += scale.o OBJS += timescale.o OBJS += deltatime.o OBJS += realtime.o OBJS += monotime.o OBJS += ttodeltatime.o OBJS += ttorealtime.o OBJS += refcnt.o OBJS += debug.o OBJS += impair.o OBJS += ldbg.o OBJS += DBG_dump.o OBJS += DBG_log.o OBJS += llog_base64_bytes.o OBJS += llog_pem_bytes.o OBJS += llog_errno.o OBJS += log_error.o OBJS += fatal.o OBJS += bad_enum_where.o OBJS += bad_case_where.o OBJS += bad_sparse_where.o OBJS += lswglob.o OBJS += optarg.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_logger_rc_prefix.o OBJS += jam_logger.o OBJS += logjam.o OBJS += jam_nss_cka.o OBJS += jam_nss_ckg.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_null_ops.o 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_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_cipher.o OBJS += crypt_hash.o OBJS += crypt_mac.o OBJS += crypt_prf.o OBJS += crypt_symkey.o ifeq ($(USE_IKEv1),true) OBJS += ikev1_prf.o endif OBJS += ikev2_prf.o ifeq ($(USE_DNSSEC),true) OBJS += unbound.o endif OBJS += names.o 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 += autostart_names.o OBJS += $(abs_builddir)/version.o # # Build version.c using version number from git repo or mk/version.mk # IPSECVIDVERSION ?= $(shell echo ${IPSECVERSION} | sed 's/^\([^-]*\)-\([^-]*\)-.*/\1-\2/') $(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@/$(subst /,_,$(IPSECVIDVERSION))/' \ $(srcdir)/version.in.c \ > $@.tmp mv $@.tmp $@ # generate enum name checklists ENUM_INCLUDES += $(wildcard $(top_srcdir)/include/*.h) ENUM_INCLUDES += $(wildcard $(top_srcdir)/include/*/*.h) OBJS += $(abs_builddir)/enum_names_checklist.o $(abs_builddir)/enum_names_checklist.c: $(srcdir)/Makefile $(srcdir)/enum_checklist.sh $(ENUM_INCLUDES) rm -f $@.tmp $(srcdir)/enum_checklist.sh enum_names $(ENUM_INCLUDES) >$@.tmp mv $@.tmp $@ OBJS += $(abs_builddir)/enum_enum_names_checklist.o $(abs_builddir)/enum_enum_names_checklist.c: $(srcdir)/Makefile $(srcdir)/enum_checklist.sh $(ENUM_INCLUDES) rm -f $@.tmp $(srcdir)/enum_checklist.sh enum_enum_names $(ENUM_INCLUDES) >$@.tmp mv $@.tmp $@ include $(top_srcdir)/mk/library.mk libreswan-5.2/lib/libswan/ah_info.c000066400000000000000000000076161475767661000173570ustar00rootroot00000000000000/* * 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 "fips_mode.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_ikev1_ah_proposals[] = "SHA1_96" /*???*/ "," "SHA2_512" "," "SHA2_256" ; const struct proposal_defaults ikev1_ah_defaults = { .proposals[FIPS_MODE_ON] = default_ikev1_ah_proposals, .proposals[FIPS_MODE_OFF] = default_ikev1_ah_proposals, }; /* * IKEv2: */ static const char default_ikev2_ah_proposals[] = "SHA2_512_256" "," "SHA2_256_128" ; static const struct ike_alg *default_ikev2_ah_integ[] = { #ifdef USE_SHA2 &ike_alg_integ_sha2_512.common, &ike_alg_integ_sha2_256.common, #endif NULL, }; const struct proposal_defaults ikev2_ah_defaults = { .proposals[FIPS_MODE_ON] = default_ikev2_ah_proposals, .proposals[FIPS_MODE_OFF] = default_ikev2_ah_proposals, .integ = default_ikev2_ah_integ, }; /* * All together now ... */ static const struct proposal_protocol ikev1_ah_proposal_protocol = { .name = "AH", .alg_id = IKEv1_IPSEC_ID, .defaults = &ikev1_ah_defaults, .proposal_ok = ah_proposal_ok, .integ = true, .dh = true, }; static const struct proposal_protocol ikev2_ah_proposal_protocol = { .name = "AH", .alg_id = IKEv2_ALG_ID, .defaults = &ikev2_ah_defaults, .proposal_ok = ah_proposal_ok, .integ = true, .dh = true, }; static const struct proposal_protocol *ah_proposal_protocol[] = { [IKEv1] = &ikev1_ah_proposal_protocol, [IKEv2] = &ikev2_ah_proposal_protocol, }; /* * ??? 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[policy->version]); } libreswan-5.2/lib/libswan/alg_byname.c000066400000000000000000000115021475767661000200370ustar00rootroot00000000000000/* * 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 (alg->id[protocol->alg_id] < 0) { enum_buf vb; proposal_error(parser, "%s %s algorithm '"PRI_SHUNK"' is not supported by %s", protocol->name, ike_alg_type_name(alg->algo_type), pri_shunk(print_name), str_enum(&ike_version_names, policy->version, &vb)); return false; } /* * 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) { struct logger *logger = parser->policy->logger; 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_matched(type, name)) { 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); ldbgf(DBG_PROPOSAL_PARSER, logger, "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); ldbgf(DBG_PROPOSAL_PARSER, logger, "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-5.2/lib/libswan/alloc.c000066400000000000000000000223611475767661000170400ustar00rootroot00000000000000/* * 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. */ /* 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 */ }; /* * Detect and passert() an invalid memory address. * * With leak_detective, valid memory has .magic==LEAK_MAGIC, and just * pfree()d memory has .magic=~LEAK_DETECTIVE (and 0xFE scribbled over * the content). */ static union mhdr *pmhdr_where(void *ptr, where_t where) { #if 0 /* * Diagnose a pointer read from a pfree()'d struct. * * Since the pfree() memory contents had 0XEF scribbled on * them, any pointers in that struct will have the value * POINTER_MAGIC. * * This isn't enabled. POINTER_MAGIC is misalligned and * (presumably) invalid. Accessing .i.magic should fail, * SIGSEGVs or SIGBUS. */ #ifdef INTPTR_MAX # if INTPTR_MAX == INT32_C(0x7FFFFFFF) # define POINTER_T uint32_t # define POINTER_MAGIC UINT32_C(0xEFEFEFEF) # elif INTPTR_MAX == INT64_C(0x7FFFFFFFFFFFFFFF) # define POINTER_T uint64_t # define POINTER_MAGIC UINT64_C(0xEFEFEFEFEFEFEFEF) # else # error INTPTR_MAX not recognized # endif #else # error INTPTR_MAX not defined #endif if ((POINTER_T)ptr == POINTER_MAGIC) { llog_passert(&global_logger, where, "pointer %p invalid, possible use after free (pointer == POINTER_MAGIC)", ptr); } #endif union mhdr *p = ((union mhdr *)ptr) - 1; switch (p->i.magic) { case LEAK_MAGIC: break; case ~LEAK_MAGIC: /* * Diagnose of a double free. * * Note: this won't detect a re-allocated pointer vis: * * pfree(p); // p == 1234 * q = alloc_bytes(); // q == 1234 * pfree(p) // p == 1234 * * Note: the testuite has EFENCE enabled (unmap and * never reuse in free()) so just trying to access * .i.magic will trigger a SEGV barf. */ llog_passert(&global_logger, where, "pointer %p invalid, possible double free (magic == ~LEAK_MAGIC)", ptr); default: /* * Diagnose an invalid pointer (possibly corrupt, * possibly...). */ llog_passert(&global_logger, where, "pointer %p invalid, possible heap corruption or bad pointer (magic != LEAK_MAGIC and ~LEAK_MAGIC})", ptr); } return p; } void pmemory_where(void *ptr, where_t where) { passert(ptr != NULL); if (leak_detective) { pmhdr_where(ptr, where); } } /* 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) { passert(ptr != NULL); union mhdr *p = pmhdr_where(ptr, HERE); 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. */ 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 = pmhdr_where(ptr, HERE); 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 = pmhdr_where(*ptr, HERE); 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-5.2/lib/libswan/alloc_printf.c000066400000000000000000000023401475767661000204150ustar00rootroot00000000000000/* 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-5.2/lib/libswan/asn1.c000066400000000000000000000142631475767661000166120ustar00rootroot00000000000000/* * 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-5.2/lib/libswan/atoaddr.3.xml000066400000000000000000000271221475767661000201030ustar00rootroot00000000000000 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 */ AUTHOR Paul Wouters libreswan-5.2/lib/libswan/atoasr.3000066400000000000000000000104221475767661000171520ustar00rootroot00000000000000.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-5.2/lib/libswan/authby.c000066400000000000000000000071641475767661000172460ustar00rootroot00000000000000/* 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-5.2/lib/libswan/autostart_names.c000066400000000000000000000022421475767661000211530ustar00rootroot00000000000000/* tables of names for values defined in constants.h * * Copyright (C) 2023 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY 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 "sparse_names.h" #include "constants.h" /* for enum autostart */ const struct sparse_names autostart_names = { .list = { SPARSE("ignore", AUTOSTART_IGNORE), SPARSE("add", AUTOSTART_ADD), SPARSE("ondemand", AUTOSTART_ONDEMAND), SPARSE("route", AUTOSTART_ROUTE), /* backwards compatibility alias */ SPARSE("up", AUTOSTART_UP), SPARSE("start", AUTOSTART_START), /* alias */ SPARSE("keep", AUTOSTART_KEEP), /* add plus once up, keep up */ SPARSE_NULL }, }; libreswan-5.2/lib/libswan/bad_case_where.c000066400000000000000000000016171475767661000206620ustar00rootroot00000000000000/* 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 bad_case_where(const char *expression, long value, where_t where) { llog_passert(&global_logger, where, "switch (%s) case %ld (0x%lx) unexpected", expression, value, value); } libreswan-5.2/lib/libswan/bad_enum_where.c000066400000000000000000000016761475767661000207200ustar00rootroot00000000000000/* bad_enum() wrapper, for libreswan * * Copyright (C) 2013 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY 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 bad_enum_where(const struct logger *logger, const struct enum_names *en, unsigned long value, where_t where) { enum_buf eb; llog_passert(logger, where, "enum %s (%ld) unexpected", str_enum(en, value, &eb), value); } libreswan-5.2/lib/libswan/bad_sparse_where.c000066400000000000000000000017561475767661000212500ustar00rootroot00000000000000/* bad_sparse() wrapper, for libreswan * * Copyright (C) 2013 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY 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 "sparse_names.h" void bad_sparse_where(const struct logger *logger, const struct sparse_names *sn, unsigned long value, where_t where) { sparse_buf sb; llog_passert(logger, where, "sparse %s (%ld) unexpected", str_sparse(sn, value, &sb), value); } libreswan-5.2/lib/libswan/binaryscale-iec-60027-2.c000066400000000000000000000033411475767661000216100ustar00rootroot00000000000000/* 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" static const struct scale binaryscale[] = { {"", 1, }, {"Ki", 1 * binary_per_kilo, }, {"Mi", 1 * binary_per_mega, }, {"Gi", 1 * binary_per_giga, }, {"Ti", 1 * binary_per_tera, }, {"Pi", 1 * binary_per_peta, }, {"Ei", 1 * binary_per_exa, }, }; static const struct scale binarybytescale[] = { {"", 1, }, {"KiB", 1 * binary_per_kilo, }, {"MiB", 1 * binary_per_mega, }, {"GiB", 1 * binary_per_giga, }, {"TiB", 1 * binary_per_tera, }, {"PiB", 1 * binary_per_peta, }, {"PiB", 1 * binary_per_exa, }, }; static const struct scales binaryscales = { .base = 1024, .scale = { ARRAY_REF(binaryscale), }, }; static const struct scales binarybytescales = { .base = 1024, .scale = { ARRAY_REF(binarybytescale), }, }; const struct scale *ttobinaryscale(shunk_t cursor) { return ttoscale(cursor, &binaryscales, 0); } const struct scale *ttobinarybytesscale(shunk_t cursor) { return ttoscale(cursor, &binarybytescales, 0); } libreswan-5.2/lib/libswan/certs.c000066400000000000000000000046611475767661000170710ustar00rootroot00000000000000/* 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-5.2/lib/libswan/chunk.c000066400000000000000000000063431475767661000170600ustar00rootroot00000000000000/* 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_bytes(chunk_t *dest, const void *src, size_t sizeof_src, const char *name) { free_chunk_content(dest); *dest = clone_bytes_as_chunk(src, sizeof_src, name); } 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); free_chunk_content(lhs); *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-5.2/lib/libswan/ckaid.c000066400000000000000000000063141475767661000170210ustar00rootroot00000000000000/* * 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, ckaid->ptr, ckaid->len, &ckaid->len); if (err != NULL) { return err; } return NULL; } libreswan-5.2/lib/libswan/cloexec_socket.c000066400000000000000000000022751475767661000207420ustar00rootroot00000000000000/* 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-5.2/lib/libswan/clone_shunk_tokens.c000066400000000000000000000037251475767661000216440ustar00rootroot00000000000000/* 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-5.2/lib/libswan/connection_owner_names.c000066400000000000000000000030221475767661000224730ustar00rootroot00000000000000/* connection owner, for libreswan * * Copyright (C) 2023 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include "connection_owner.h" #include "enum_names.h" #include "lswcdefs.h" /* for ARRAY_REF */ const char *connection_owner_name[] = { [ROUTING_SA] = "routing_sa", [NEGOTIATING_IKE_SA] = "negotiating_ike_sa", [ESTABLISHED_IKE_SA] = "established_ike_sa", [NEGOTIATING_CHILD_SA] = "negotiating_child_sa", [ESTABLISHED_CHILD_SA] = "established_child_sa", }; const struct enum_names connection_owner_names = { ROUTING_SA, ESTABLISHED_CHILD_SA, ARRAY_REF(connection_owner_name), .en_prefix = NULL, }; const char *connection_owner_story[] = { [ROUTING_SA] = "routing SA", [NEGOTIATING_IKE_SA] = "negotiating IKE SA", [ESTABLISHED_IKE_SA] = "established IKE SA", [NEGOTIATING_CHILD_SA] = "negotiating Child SA", [ESTABLISHED_CHILD_SA] = "established Child SA", }; const struct enum_names connection_owner_stories = { ROUTING_SA, ESTABLISHED_CHILD_SA, ARRAY_REF(connection_owner_story), .en_prefix = NULL, }; libreswan-5.2/lib/libswan/constants.c000066400000000000000000002101741475767661000177630ustar00rootroot00000000000000/* * 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 */ #include "encap_mode.h" #include "encap_proto.h" #include "initiated_by.h" #include "connection_owner.h" 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); } static const char *const perspective_name[] = { #define S(E) [E - NO_PERSPECTIVE] = #E S(NO_PERSPECTIVE), S(LOCAL_PERSPECTIVE), S(REMOTE_PERSPECTIVE), #undef S }; enum_names perspective_names = { NO_PERSPECTIVE, REMOTE_PERSPECTIVE, ARRAY_REF(perspective_name), NULL, /* prefix */ NULL, }; static const char *const shunt_policy_name[] = { #define S(E) [E - SHUNT_UNSET] = #E S(SHUNT_UNSET), S(SHUNT_IPSEC), S(SHUNT_HOLD), S(SHUNT_NONE), S(SHUNT_PASS), S(SHUNT_DROP), S(SHUNT_REJECT), S(SHUNT_TRAP), #undef S }; enum_names shunt_policy_names = { SHUNT_UNSET, SHUNT_POLICY_ROOF-1, ARRAY_REF(shunt_policy_name), "SHUNT_", /* prefix */ NULL, }; static const char *const shunt_kind_name[] = { #define S(E) [E - SHUNT_KIND_NONE] = #E S(SHUNT_KIND_NONE), S(SHUNT_KIND_NEVER_NEGOTIATE), S(SHUNT_KIND_ONDEMAND), S(SHUNT_KIND_NEGOTIATION), S(SHUNT_KIND_IPSEC), S(SHUNT_KIND_FAILURE), S(SHUNT_KIND_BLOCK), #undef S }; enum_names shunt_kind_names = { 0, SHUNT_KIND_ROOF-1, ARRAY_REF(shunt_kind_name), "SHUNT_KIND_", /*PREFIX*/ NULL, }; static const char *const shunt_policy_percent_name[] = { [SHUNT_UNSET] = "", [SHUNT_HOLD] = "%hold", [SHUNT_NONE] = "%none", [SHUNT_PASS] = "%pass", [SHUNT_DROP] = "%drop", [SHUNT_REJECT] = "%reject", [SHUNT_TRAP] = "%trap", }; enum_names shunt_policy_percent_names = { SHUNT_UNSET, SHUNT_POLICY_ROOF-1, ARRAY_REF(shunt_policy_percent_name), "%"/*prefix*/, NULL, }; /* NAT methods */ static const char *const natt_method_name[] = { [NAT_TRAVERSAL_METHOD_none] = "none", [NAT_TRAVERSAL_METHOD_IETF_02_03] = "draft-ietf-ipsec-nat-t-ike-02/03", [NAT_TRAVERSAL_METHOD_IETF_05] = "draft-ietf-ipsec-nat-t-ike-05", [NAT_TRAVERSAL_METHOD_IETF_RFC] = "RFC 3947 (NAT-Traversal)", }; enum_names natt_method_names = { NAT_TRAVERSAL_METHOD_none, NAT_TRAVERSAL_METHOD_IETF_RFC, ARRAY_REF(natt_method_name), NULL, /* prefix */ NULL }; static const char *const allow_global_redirect_name[] = { #define R(E,S) [E - GLOBAL_REDIRECT_NO] = S R(GLOBAL_REDIRECT_NO, "no"), R(GLOBAL_REDIRECT_YES, "yes"), R(GLOBAL_REDIRECT_AUTO, "auto"), #undef R }; enum_names allow_global_redirect_names = { GLOBAL_REDIRECT_NO, GLOBAL_REDIRECT_AUTO, ARRAY_REF(allow_global_redirect_name), NULL, NULL }; static const char *const dns_auth_level_name[] = { #define S(E) [E - PUBKEY_LOCAL] = #E S(PUBKEY_LOCAL), S(DNSSEC_INSECURE), S(DNSSEC_SECURE), #undef S }; enum_names dns_auth_level_names = { PUBKEY_LOCAL, DNSSEC_ROOF-1, ARRAY_REF(dns_auth_level_name), NULL, /* prefix */ NULL }; static const char *connection_event_kind_name[] = { #define S(E) [E - 1] = #E S(CONNECTION_REVIVAL), #undef S }; const struct enum_names connection_event_kind_names = { 1, CONNECTION_REVIVAL, ARRAY_REF(connection_event_kind_name), "CONNECTION_", NULL, }; /* systemd watchdog action names */ static const char *const sd_action_name[] = { #define R(E,S) [E - PLUTO_SD_EXIT] = S R(PLUTO_SD_EXIT, "action: exit"), /* daemon exiting */ R(PLUTO_SD_START, "action: start"), /* daemon starting */ R(PLUTO_SD_WATCHDOG, "action: watchdog"), /* the keepalive watchdog ping */ R(PLUTO_SD_RELOADING, "action: reloading"), /* the keepalive watchdog ping */ R(PLUTO_SD_READY, "action: ready"), /* the keepalive watchdog ping */ R(PLUTO_SD_STOPPING, "action: stopping"), /* the keepalive watchdog ping */ #undef R }; enum_names sd_action_names = { PLUTO_SD_EXIT, PLUTO_SD_STOPPING, ARRAY_REF(sd_action_name), NULL, /* prefix */ NULL }; static const char *const keyword_auth_name[] = { #define R(E,S) [E - AUTH_UNSET] = S R(AUTH_UNSET, "unset"), R(AUTH_NEVER, "never"), R(AUTH_PSK, "secret"), R(AUTH_RSASIG, "rsasig"), R(AUTH_ECDSA, "ecdsa"), R(AUTH_NULL, "null"), R(AUTH_EAPONLY, "eaponly"), #undef R }; enum_names keyword_auth_names = { AUTH_UNSET, AUTH_EAPONLY, ARRAY_REF(keyword_auth_name), NULL, /* prefix */ NULL }; static const char *const stf_status_strings[] = { #define S(E) [E - STF_SKIP_COMPLETE_STATE_TRANSITION] = #E S(STF_SKIP_COMPLETE_STATE_TRANSITION), S(STF_IGNORE), S(STF_SUSPEND), S(STF_OK), S(STF_INTERNAL_ERROR), S(STF_OK_INITIATOR_DELETE_IKE), S(STF_OK_RESPONDER_DELETE_IKE), S(STF_OK_INITIATOR_SEND_DELETE_IKE), S(STF_FATAL), S(STF_FAIL_v1N), #undef S }; enum_names stf_status_names = { 0, elemsof(stf_status_strings)-1, ARRAY_REF(stf_status_strings), NULL, /* prefix */ NULL }; static const char *const keyword_host_name_ipaddr[] = { #define S(E) [E - KH_IPADDR] = #E S(KH_IPADDR), #undef S }; static enum_names keyword_host_names_ipaddr = { KH_IPADDR, KH_IPADDR, ARRAY_REF(keyword_host_name_ipaddr), "KH_", /* prefix */ NULL }; static const char *const keyword_host_name[] = { #define S(E) [E - KH_NOTSET] = #E S(KH_NOTSET), S(KH_DEFAULTROUTE), S(KH_ANY), S(KH_IFACE), S(KH_OPPO), S(KH_OPPOGROUP), S(KH_GROUP), S(KH_IPHOSTNAME), #undef S }; enum_names keyword_host_names = { KH_NOTSET, KH_IPHOSTNAME, ARRAY_REF(keyword_host_name), "KH_", /* prefix */ &keyword_host_names_ipaddr, }; /* 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[] = { #define S(E) [E - 0] = #E "", S(IKEv1), S(IKEv2), #undef S }; enum_names ike_version_names = { 0, IKEv2, ARRAY_REF(ike_version_name), "IKE", /* prefix */ NULL, }; /* Domain of Interpretation */ static const char *const doi_name[] = { #define S(E) [E - ISAKMP_DOI_ISAKMP] = #E S(ISAKMP_DOI_ISAKMP), S(ISAKMP_DOI_IPSEC), #undef S }; 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[] = { #define S(E) [E - CK_INVALID] = #E S(CK_INVALID), S(CK_GROUP), /* policy group: instantiates to template */ S(CK_TEMPLATE), /* abstract connection, with wildcard */ S(CK_PERMANENT), /* normal connection */ S(CK_INSTANCE), /* instance of template */ S(CK_LABELED_TEMPLATE), S(CK_LABELED_PARENT), S(CK_LABELED_CHILD), #undef S }; enum_names connection_kind_names = { CK_INVALID, CONNECTION_KIND_ROOF - 1, ARRAY_REF(connection_kind_name), "CK_", /* prefix */ NULL }; /* Payload types (RFC 2408 "ISAKMP" section 3.1) */ static const char *const payload_name_ikev1[] = { #define S(E) [E - ISAKMP_NEXT_NONE] = #E S(ISAKMP_NEXT_NONE), S(ISAKMP_NEXT_SA), /* 1 */ S(ISAKMP_NEXT_P), S(ISAKMP_NEXT_T), S(ISAKMP_NEXT_KE), S(ISAKMP_NEXT_ID), /* 5 */ S(ISAKMP_NEXT_CERT), S(ISAKMP_NEXT_CR), S(ISAKMP_NEXT_HASH), S(ISAKMP_NEXT_SIG), S(ISAKMP_NEXT_NONCE), /* 10 */ S(ISAKMP_NEXT_N), S(ISAKMP_NEXT_D), S(ISAKMP_NEXT_VID), S(ISAKMP_NEXT_MODECFG), /* 14 */ S(ISAKMP_NEXT_SAK), /* 15 was ISAKMP_NEXT_NATD_BADDRAFTS */ S(ISAKMP_NEXT_TEK), S(ISAKMP_NEXT_KD), S(ISAKMP_NEXT_SEQ), S(ISAKMP_NEXT_POP), S(ISAKMP_NEXT_NATD_RFC), S(ISAKMP_NEXT_NATOA_RFC), S(ISAKMP_NEXT_GAP), #undef S }; static const char *const payload_name_ikev1_private_use[] = { #define S(E) [E - ISAKMP_NEXT_NATD_DRAFTS] = #E S(ISAKMP_NEXT_NATD_DRAFTS), S(ISAKMP_NEXT_NATOA_DRAFTS), S(ISAKMP_NEXT_IKE_FRAGMENTATION), /* * proprietary Cisco/Microsoft * IKE fragmented payload */ #undef S }; 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[] = { #define S(E) [E - ISAKMP_NEXT_v2NONE] = #E "ISAKMP_NEXT_v2NONE", /* same for IKEv1 */ #undef S }; /* https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xhtml#ikev2-parameters-2 */ static const char *const payload_name_ikev2_main[] = { #define S(E) [E - ISAKMP_NEXT_v2SA] = #E S(ISAKMP_NEXT_v2SA), /* 33 */ S(ISAKMP_NEXT_v2KE), S(ISAKMP_NEXT_v2IDi), S(ISAKMP_NEXT_v2IDr), S(ISAKMP_NEXT_v2CERT), S(ISAKMP_NEXT_v2CERTREQ), S(ISAKMP_NEXT_v2AUTH), S(ISAKMP_NEXT_v2Ni), S(ISAKMP_NEXT_v2N), S(ISAKMP_NEXT_v2D), S(ISAKMP_NEXT_v2V), S(ISAKMP_NEXT_v2TSi), S(ISAKMP_NEXT_v2TSr), S(ISAKMP_NEXT_v2SK), S(ISAKMP_NEXT_v2CP), S(ISAKMP_NEXT_v2EAP), S(ISAKMP_NEXT_v2GSPM), /* RFC 6467 */ S(ISAKMP_NEXT_v2IDG), /* [draft-yeung-g-ikev2] */ S(ISAKMP_NEXT_v2GSA), /* [draft-yeung-g-ikev2] */ S(ISAKMP_NEXT_v2KD), /* [draft-yeung-g-ikev2] */ S(ISAKMP_NEXT_v2SKF), /* RFC 7383 */ #undef S }; /* * Old IKEv1 method applied to IKEv2, different from IKEv2's RFC7383 * Can be removed */ static const char *const payload_name_ikev2_private_use[] = { #define S(E) [E - ISAKMP_NEXT_v2IKE_FRAGMENTATION] = #E S(ISAKMP_NEXT_v2IKE_FRAGMENTATION), #undef S }; 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[] = { #define S(E) [E - v2_PROPOSAL_LAST] = #E S(v2_PROPOSAL_LAST), S(v2_PROPOSAL_NON_LAST), #undef S }; 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[] = { #define S(E) [E - v2_TRANSFORM_LAST] = #E S(v2_TRANSFORM_LAST), S(v2_TRANSFORM_NON_LAST), #undef S }; 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 ikev1_exchange_name[] = { #define S(E) [E - ISAKMP_XCHG_NONE] = #E S(ISAKMP_XCHG_NONE), S(ISAKMP_XCHG_BASE), S(ISAKMP_XCHG_IDPROT), S(ISAKMP_XCHG_AO), S(ISAKMP_XCHG_AGGR), S(ISAKMP_XCHG_INFO), S(ISAKMP_XCHG_MODE_CFG), /* 6 - draft, not RFC */ #undef S }; static const char *const ikev1_exchange_doi_name[] = { #define S(E) [E - ISAKMP_XCHG_QUICK] = #E S(ISAKMP_XCHG_QUICK), /* 32 */ S(ISAKMP_XCHG_NGRP), #undef S }; static enum_names ikev1_exchange_doi_names = { ISAKMP_XCHG_QUICK, ISAKMP_XCHG_NGRP, ARRAY_REF(ikev1_exchange_doi_name), NULL, /* prefix */ NULL, }; enum_names ikev1_exchange_names = { ISAKMP_XCHG_NONE, ISAKMP_XCHG_MODE_CFG, ARRAY_REF(ikev1_exchange_name), "ISAKMP_XCHG_", /* prefix */ &ikev1_exchange_doi_names }; static enum_names isakmp_xchg_type_doi_and_v2_names = { ISAKMP_XCHG_QUICK, ISAKMP_XCHG_NGRP, ARRAY_REF(ikev1_exchange_doi_name), NULL, /* prefix */ &ikev2_exchange_names, }; enum_names isakmp_xchg_type_names = { ISAKMP_XCHG_NONE, ISAKMP_XCHG_MODE_CFG, ARRAY_REF(ikev1_exchange_name), NULL, /* prefix */ &isakmp_xchg_type_doi_and_v2_names, }; /* https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xhtml#ikev2-parameters-1 */ static const char *const ikev2_exchange_name[] = { #define S(E) [E - IKEv2_EXCHANGE_FLOOR] = #E S(ISAKMP_v2_IKE_SA_INIT), S(ISAKMP_v2_IKE_AUTH), S(ISAKMP_v2_CREATE_CHILD_SA), S(ISAKMP_v2_INFORMATIONAL), S(ISAKMP_v2_IKE_SESSION_RESUME), S(ISAKMP_v2_GSA_AUTH), S(ISAKMP_v2_GSA_REGISTRATION), S(ISAKMP_v2_GSA_REKEY), S(ISAKMP_v2_IKE_INTERMEDIATE), S(ISAKMP_v2_IKE_FOLLOWUP_KE), #undef S }; const struct enum_names ikev2_exchange_names = { IKEv2_EXCHANGE_FLOOR, IKEv2_EXCHANGE_ROOF-1, ARRAY_REF(ikev2_exchange_name), "ISAKMP_v2_", /* prefix */ NULL, }; static enum_names *const exchange_type_names_table[] = { [IKEv1 - IKE_VERSION_FLOOR] = &ikev1_exchange_names, [IKEv2 - IKE_VERSION_FLOOR] = &ikev2_exchange_names, }; enum_enum_names exchange_type_names = { IKE_VERSION_FLOOR, IKE_VERSION_ROOF-1, ARRAY_REF(exchange_type_names_table), }; /* Flag BITS */ static const char *const isakmp_flag_name[] = { #define S(E) [E - ISAKMP_FLAG_v1_ENCRYPTION] = #E #define R(E,S) [E - ISAKMP_FLAGS_v1_ENCRYPTION_IX] = #S R(ISAKMP_FLAGS_v1_ENCRYPTION_IX, ISAKMP_FLAG_v1_ENCRYPTION), /* IKEv1 only bit 0 */ R(ISAKMP_FLAGS_v1_COMMIT_IX, ISAKMP_FLAG_v1_COMMIT), /* IKEv1 only bit 1 */ R(ISAKMP_FLAGS_v1_AUTH_IX, ISAKMP_FLAG_v1_AUTHONLY), /* IKEv1 only bit 2 */ R(ISAKMP_FLAGS_v2_IKE_I_IX, ISAKMP_FLAG_v2_IKE_INIT), /* IKEv2 only bit 3 */ R(ISAKMP_FLAGS_v2_VER_IX, ISAKMP_FLAG_v2_VERSION), /* IKEv2 only bit 4 */ R(ISAKMP_FLAGS_v2_MSG_R_IX, ISAKMP_FLAG_v2_MSG_RESPONSE), /* IKEv2 only bit 5 */ R(ISAKMP_FLAGS_RESERVED_BIT6_IX, ISAKMP_FLAG_MSG_RESERVED_BIT6), R(ISAKMP_FLAGS_RESERVED_BIT7_IX, ISAKMP_FLAG_MSG_RESERVED_BIT7), #undef R #undef S }; 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[] = { #define S(E) [E - PROTO_RESERVED] = #E S(PROTO_RESERVED), S(PROTO_ISAKMP), S(PROTO_IPSEC_AH), S(PROTO_IPSEC_ESP), S(PROTO_IPCOMP), #undef S }; 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[] = { #define S(E) [E - KEY_IKE] = #E S(KEY_IKE), #undef S }; 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[] = { #define S(E) [E - IKEv1_AH_AES_CMAC_96] = #E S(IKEv1_AH_AES_CMAC_96), S(IKEv1_AH_NULL), /* verify with kame source? 251 */ S(IKEv1_AH_SHA2_256_TRUNCBUG), /* our own to signal bad truncation to kernel */ #undef S }; static enum_names ah_transformid_names_private_use = { IKEv1_AH_AES_CMAC_96, IKEv1_AH_SHA2_256_TRUNCBUG, ARRAY_REF(ah_transform_name_private_use), "IKEv1_AH_", /* prefix */ NULL }; static const char *const ah_transform_name[] = { /* 0-1 RESERVED */ #define S(E) [E - IKEv1_AH_MD5] = #E S(IKEv1_AH_MD5), S(IKEv1_AH_SHA), S(IKEv1_AH_DES), S(IKEv1_AH_SHA2_256), S(IKEv1_AH_SHA2_384), S(IKEv1_AH_SHA2_512), S(IKEv1_AH_RIPEMD), S(IKEv1_AH_AES_XCBC_MAC), S(IKEv1_AH_RSA), S(IKEv1_AH_AES_128_GMAC), /* RFC4543 Errata1821 */ S(IKEv1_AH_AES_192_GMAC), /* RFC4543 Errata1821 */ S(IKEv1_AH_AES_256_GMAC), /* RFC4543 Errata1821 */ #undef S /* 14-248 Unassigned */ /* 249-255 Reserved for private use */ }; enum_names ah_transformid_names = { IKEv1_AH_MD5, IKEv1_AH_AES_256_GMAC, ARRAY_REF(ah_transform_name), "IKEv1_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 */ #define S(E) [E - IKEv1_ESP_MARS] = #E S(IKEv1_ESP_MARS), S(IKEv1_ESP_RC6), S(IKEv1_ESP_KAME_NULL), S(IKEv1_ESP_SERPENT), S(IKEv1_ESP_TWOFISH), #undef S }; static enum_names esp_transformid_names_private_use = { IKEv1_ESP_MARS, IKEv1_ESP_TWOFISH, ARRAY_REF(esp_transform_name_private_use), "IKEv1_ESP_", /* prefix */ NULL }; /* This tracks the IKEv2 registry now! see ietf_constants.h */ static const char *const esp_transform_name[] = { #define S(E) [E - IKEv1_ESP_DES_IV64] = #E S(IKEv1_ESP_DES_IV64), /* 1 - old DES */ S(IKEv1_ESP_DES), /* obsoleted */ S(IKEv1_ESP_3DES), S(IKEv1_ESP_RC5), S(IKEv1_ESP_IDEA), S(IKEv1_ESP_CAST), S(IKEv1_ESP_BLOWFISH), /* obsoleted */ S(IKEv1_ESP_3IDEA), S(IKEv1_ESP_DES_IV32), S(IKEv1_ESP_RC4), S(IKEv1_ESP_NULL), S(IKEv1_ESP_AES), S(IKEv1_ESP_AES_CTR), S(IKEv1_ESP_AES_CCM_8), S(IKEv1_ESP_AES_CCM_12), S(IKEv1_ESP_AES_CCM_16), S(IKEv1_ESP_AES_GCM_8), S(IKEv1_ESP_AES_GCM_12), S(IKEv1_ESP_AES_GCM_16), S(IKEv1_ESP_SEED_CBC), /* IKEv2 is NULL_AUTH_AES_GMAC */ S(IKEv1_ESP_CAMELLIA), S(IKEv1_ESP_NULL_AUTH_AES_GMAC), /* IKEv2 is CAMELLIA_CBC */ S(IKEv1_ESP_CAMELLIA_CTR), /* not assigned in/for IKEv1 */ S(IKEv1_ESP_CAMELLIA_CCM_8), /* not assigned in/for IKEv1 */ S(IKEv1_ESP_CAMELLIA_CCM_12), /* not assigned in/for IKEv1 */ S(IKEv1_ESP_CAMELLIA_CCM_16), /* not assigned in/for IKEv1 */ #undef S /* 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 = { IKEv1_ESP_DES_IV64, IKEv1_ESP_CAMELLIA_CCM_16, ARRAY_REF(esp_transform_name), "IKEv1_ESP_", /* prefix */ &esp_transformid_names_private_use }; /* IPCOMP transform values */ static const char *const ipsec_ipcomp_algo_name[] = { #define S(E) [E - IPCOMP_NONE] = #E S(IPCOMP_NONE), S(IPCOMP_OUI), S(IPCOMP_DEFLATE), S(IPCOMP_LZS), S(IPCOMP_LZJH), /* 5-47 Reserved for approved algorithms */ /* 48-63 Reserved for private use */ /* 64-255 Unassigned */ #undef S }; 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[] = { #define S(E) [E - IKEv2_HASH_ALGORITHM_RESERVED] = #E S(IKEv2_HASH_ALGORITHM_RESERVED), S(IKEv2_HASH_ALGORITHM_SHA1), S(IKEv2_HASH_ALGORITHM_SHA2_256), S(IKEv2_HASH_ALGORITHM_SHA2_384), S(IKEv2_HASH_ALGORITHM_SHA2_512), S(IKEv2_HASH_ALGORITHM_IDENTITY) #undef S /* 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 */ [0] = "%fromcert", /* -1, ID_FROMCERT:taken from certificate */ [1] = "%none", /* 0, ID_NONE */ /* standardized */ #define S(E) [E + 1] = #E S(ID_IPV4_ADDR), /* 1 */ S(ID_FQDN), S(ID_USER_FQDN), S(ID_IPV4_ADDR_SUBNET), /* v1 only */ S(ID_IPV6_ADDR), S(ID_IPV6_ADDR_SUBNET), /* v1 only */ S(ID_IPV4_ADDR_RANGE), /* v1 only */ S(ID_IPV6_ADDR_RANGE), /* v1 only */ S(ID_DER_ASN1_DN), S(ID_DER_ASN1_GN), S(ID_KEY_ID), S(ID_FC_NAME), /* RFC 3554 */ S(ID_NULL), /* draft-ietf-ipsecme-ikev2-null-auth */ #undef S }; /* * 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[] = { #define S(E) [E - CERT_PKCS7_WRAPPED_X509] = #E S(CERT_PKCS7_WRAPPED_X509), S(CERT_PGP), S(CERT_DNS_SIGNED_KEY), S(CERT_X509_SIGNATURE), S(CERT_X509_KEY_EXCHANGE), /* v1 only */ S(CERT_KERBEROS_TOKENS), S(CERT_CRL), S(CERT_ARL), S(CERT_SPKI), S(CERT_X509_ATTRIBUTE), /* IKEv2 only from here */ S(CERT_RAW_RSA), S(CERT_X509_CERT_URL), S(CERT_X509_BUNDLE_URL), S(CERT_OCSP_CONTENT), /* 14 */ S(CERT_RAW_PUBLIC_KEY), /* 16 - 200 Reserved */ /* 201 - 255 Private use */ #undef S }; 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[] = { #define S(E) [E - CERT_NEVERSEND] = #E S(CERT_NEVERSEND), S(CERT_SENDIFASKED), S(CERT_ALWAYSSEND), #undef S }; 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[] = { #define R(E,S) [E - OAKLEY_GROUP_PRIME] = #S R(OAKLEY_GROUP_PRIME, OAKLEY_GROUP_PRIME (variable length)), R(OAKLEY_GROUP_GENERATOR_ONE, OAKLEY_GROUP_GENERATOR_ONE (variable length)), R(OAKLEY_GROUP_GENERATOR_TWO, OAKLEY_GROUP_GENERATOR_TWO (variable length)), R(OAKLEY_GROUP_CURVE_A, OAKLEY_GROUP_CURVE_A (variable length)), R(OAKLEY_GROUP_CURVE_B, OAKLEY_GROUP_CURVE_B (variable length)), NULL, R(OAKLEY_LIFE_DURATION, OAKLEY_LIFE_DURATION (variable length)), NULL, NULL, NULL, R(OAKLEY_GROUP_ORDER, OAKLEY_GROUP_ORDER (variable length)), #undef R }; 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 */ static const struct enum_names *const ikev1_oakley_attr_value_name[] = { [OAKLEY_ENCRYPTION_ALGORITHM] = &oakley_enc_names, [OAKLEY_HASH_ALGORITHM] = &oakley_hash_names, [OAKLEY_AUTHENTICATION_METHOD] = &oakley_auth_names, [OAKLEY_GROUP_DESCRIPTION] = &oakley_group_names, [OAKLEY_GROUP_TYPE] = &oakley_group_type_names, [OAKLEY_LIFE_TYPE] = &oakley_lifetime_names, [OAKLEY_PRF] = &oakley_prf_names, }; const struct enum_enum_names ikev1_oakley_attr_value_names = { 0, OAKLEY_PRF, ARRAY_REF(ikev1_oakley_attr_value_name), }; /* * IPsec DOI attributes (RFC 2407 "IPsec DOI" section 4.5) * * TLV == Type/Length/Value; TV == Type/Value! */ static const char *const ipsec_attr_name_secctx_vl[] = { #define V(E) [E - SECCTX] = #E" (variable length)" V(SECCTX) /* 32001 */ #undef V }; static enum_names ikev1_ipsec_af_tlv_attr_names_secctx = { SECCTX + ISAKMP_ATTR_AF_TLV, SECCTX + ISAKMP_ATTR_AF_TLV, ARRAY_REF(ipsec_attr_name_secctx_vl), NULL, /* prefix */ NULL }; static const char *const ipsec_attr_name_vl[] = { #define V(E) [E - SA_LIFE_DURATION] = #E" (variable length)" V(SA_LIFE_DURATION), V(COMPRESS_PRIVATE_ALG), V(ECN_TUNNEL), #undef V }; static const struct enum_names ikev1_ipsec_af_tlv_attr_names = { SA_LIFE_DURATION + ISAKMP_ATTR_AF_TLV, ECN_TUNNEL + ISAKMP_ATTR_AF_TLV, ARRAY_REF(ipsec_attr_name_vl), NULL, /* prefix */ &ikev1_ipsec_af_tlv_attr_names_secctx, }; static const char *const ikev1_ipsec_attr_name_secctx[] = { #define S(E) [E - SECCTX] = #E S(SECCTX) /* 32001 */ #undef S }; static enum_names ikev1_ipsec_af_tv_attr_names_secctx = { SECCTX + ISAKMP_ATTR_AF_TV, SECCTX + ISAKMP_ATTR_AF_TV, ARRAY_REF(ikev1_ipsec_attr_name_secctx), NULL, /* prefix */ &ikev1_ipsec_af_tlv_attr_names, }; static const char *const ikev1_ipsec_attr_name[] = { #define S(E) [E - SA_LIFE_TYPE] = #E S(SA_LIFE_TYPE), S(SA_LIFE_DURATION), S(GROUP_DESCRIPTION), S(ENCAPSULATION_MODE), S(AUTH_ALGORITHM), S(KEY_LENGTH), S(KEY_ROUNDS), S(COMPRESS_DICT_SIZE), S(COMPRESS_PRIVATE_ALG), S(ECN_TUNNEL), S(ESN_64BIT_SEQNUM), S(SIG_ENC_ALGO_VAL), S(ADDRESS_PRESERVATION), S(SA_DIRECTION), #undef S }; enum_names ipsec_attr_names = { SA_LIFE_TYPE + ISAKMP_ATTR_AF_TV, SA_DIRECTION + ISAKMP_ATTR_AF_TV, ARRAY_REF(ikev1_ipsec_attr_name), NULL, /* prefix */ &ikev1_ipsec_af_tv_attr_names_secctx, }; /* without TV|TLV; which has same values as TLV */ enum_names ikev1_ipsec_attr_names_secctx = { SECCTX, SECCTX, ARRAY_REF(ikev1_ipsec_attr_name_secctx), NULL, /* prefix */ NULL, }; enum_names ikev1_ipsec_attr_names = { SA_LIFE_TYPE, SA_DIRECTION, ARRAY_REF(ikev1_ipsec_attr_name), NULL, /* prefix */ &ikev1_ipsec_attr_names_secctx, }; /* for each IPsec attribute, which enum_names describes its values? */ static const struct enum_names *ikev1_ipsec_attr_value_name[] = { [SA_LIFE_TYPE] = &sa_lifetime_names, [GROUP_DESCRIPTION] = &oakley_group_names, [ENCAPSULATION_MODE] = &encapsulation_mode_names, [AUTH_ALGORITHM] = &auth_alg_names, }; const struct enum_enum_names ikev1_ipsec_attr_value_names = { 0, AUTH_ALGORITHM, ARRAY_REF(ikev1_ipsec_attr_value_name), }; /* SA Lifetime Type attribute */ static const char *const sa_lifetime_name[] = { #define S(E) [E - SA_LIFE_TYPE_SECONDS] = #E S(SA_LIFE_TYPE_SECONDS), S(SA_LIFE_TYPE_KBYTES), #undef S }; 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 S(E) [E - ENCAPSULATION_MODE_UDP_TUNNEL_DRAFTS] = #E S(ENCAPSULATION_MODE_UDP_TUNNEL_DRAFTS), S(ENCAPSULATION_MODE_UDP_TRANSPORT_DRAFTS), #undef S }; 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 S(E) [E - ENCAPSULATION_MODE_TUNNEL] = #E S(ENCAPSULATION_MODE_TUNNEL), S(ENCAPSULATION_MODE_TRANSPORT), S(ENCAPSULATION_MODE_UDP_TUNNEL_RFC), S(ENCAPSULATION_MODE_UDP_TRANSPORT_RFC), #undef S }; 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[] = { #define S(E) [E - AUTH_ALGORITHM_AES_CMAC_96] = #E S(AUTH_ALGORITHM_AES_CMAC_96), S(AUTH_ALGORITHM_NULL_KAME), /* * according to our source code * comments from jjo, needs * verification */ S(AUTH_ALGORITHM_HMAC_SHA2_256_TRUNCBUG), #undef S }; 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[] = { #define S(E) [E - AUTH_ALGORITHM_NONE] = #E S(AUTH_ALGORITHM_NONE), /* our own value, not standard */ S(AUTH_ALGORITHM_HMAC_MD5), S(AUTH_ALGORITHM_HMAC_SHA1), S(AUTH_ALGORITHM_DES_MAC), S(AUTH_ALGORITHM_KPDK), S(AUTH_ALGORITHM_HMAC_SHA2_256), S(AUTH_ALGORITHM_HMAC_SHA2_384), S(AUTH_ALGORITHM_HMAC_SHA2_512), S(AUTH_ALGORITHM_HMAC_RIPEMD), S(AUTH_ALGORITHM_AES_XCBC), S(AUTH_ALGORITHM_SIG_RSA), /* RFC4359 */ S(AUTH_ALGORITHM_AES_128_GMAC), /* RFC4543 [Errata1821] */ S(AUTH_ALGORITHM_AES_192_GMAC), /* RFC4543 [Errata1821] */ S(AUTH_ALGORITHM_AES_256_GMAC), /* RFC4543 [Errata1821] */ /* 14-61439 Unassigned */ /* 61440-65535 Reserved for private use */ #undef S }; 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 ikev1_xauth_type_name[] = { #define S(E) [E - IKEv1_XAUTH_TYPE_GENERIC] = #E S(IKEv1_XAUTH_TYPE_GENERIC), S(IKEv1_XAUTH_TYPE_CHAP), S(IKEv1_XAUTH_TYPE_OTP), S(IKEv1_XAUTH_TYPE_SKEY), #undef S }; enum_names ikev1_xauth_type_names = { IKEv1_XAUTH_TYPE_GENERIC, IKEv1_XAUTH_TYPE_SKEY, ARRAY_REF(ikev1_xauth_type_name), "IKEv1_XAUTH_TYPE_", /* prefix */ NULL }; /* IKEv1 XAUTH-STATUS attribute names */ static const char *const modecfg_attr_name_draft[] = { #define R(E,S) [E - IKEv1_INTERNAL_IP4_ADDRESS] = #S R(IKEv1_INTERNAL_IP4_ADDRESS, INTERNAL_IP4_ADDRESS), /* 1 */ R(IKEv1_INTERNAL_IP4_NETMASK, INTERNAL_IP4_NETMASK), R(IKEv1_INTERNAL_IP4_DNS, INTERNAL_IP4_DNS), R(IKEv1_INTERNAL_IP4_NBNS, INTERNAL_IP4_NBNS), R(IKEv1_INTERNAL_ADDRESS_EXPIRY, INTERNAL_ADDRESS_EXPIRY), R(IKEv1_INTERNAL_IP4_DHCP, INTERNAL_IP4_DHCP), R(IKEv1_APPLICATION_VERSION, APPLICATION_VERSION), R(IKEv1_INTERNAL_IP6_ADDRESS, INTERNAL_IP6_ADDRESS), R(IKEv1_INTERNAL_IP6_NETMASK, INTERNAL_IP6_NETMASK), R(IKEv1_INTERNAL_IP6_DNS, INTERNAL_IP6_DNS), R(IKEv1_INTERNAL_IP6_NBNS, INTERNAL_IP6_NBNS), R(IKEv1_INTERNAL_IP6_DHCP, INTERNAL_IP6_DHCP), R(IKEv1_INTERNAL_IP4_SUBNET, INTERNAL_IP4_SUBNET), /* 13 */ R(IKEv1_SUPPORTED_ATTRIBUTES, SUPPORTED_ATTRIBUTES), R(IKEv1_INTERNAL_IP6_SUBNET, INTERNAL_IP6_SUBNET), R(IKEv1_MIP6_HOME_PREFIX, MIP6_HOME_PREFIX), R(IKEv1_INTERNAL_IP6_LINK, INTERNAL_IP6_LINK), R(IKEv1_INTERNAL_IP6_PREFIX, INTERNAL_IP6_PREFIX), R(IKEv1_HOME_AGENT_ADDRESS, HOME_AGENT_ADDRESS), /* 19 */ #undef R }; #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[] = { #define S(E) [E - MODECFG_BANNER] = #E S(MODECFG_BANNER), /* 28672 */ S(CISCO_SAVE_PW), S(MODECFG_DOMAIN), S(CISCO_SPLIT_DNS), S(CISCO_SPLIT_INC), S(CISCO_UDP_ENCAP_PORT), S(CISCO_SPLIT_EXCLUDE), S(CISCO_DO_PFS), S(CISCO_FW_TYPE), S(CISCO_BACKUP_SERVER), S(CISCO_DDNS_HOSTNAME), S(CISCO_UNKNOWN_SEEN_ON_IPHONE), /* 28683 */ #undef S }; 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[] = { #define S(E) [E - IKEv1_INTERNAL_IP4_SERVER] = #E S(IKEv1_INTERNAL_IP4_SERVER), /* 23456 */ S(IKEv1_INTERNAL_IP6_SERVER), #undef S }; static enum_names modecfg_microsoft_attr_names = { IKEv1_INTERNAL_IP4_SERVER, IKEv1_INTERNAL_IP6_SERVER, ARRAY_REF(modecfg_microsoft_attr_name), "IKEv1_", /* prefix */ &modecfg_cisco_attr_names }; enum_names modecfg_attr_names = { IKEv1_INTERNAL_IP4_ADDRESS, IKEv1_HOME_AGENT_ADDRESS, ARRAY_REF(modecfg_attr_name_draft), NULL, /* prefix */ &xauth_attr_names }; static const char *const ikev1_attr_xauth_name[] = { #define S(E) [E - IKEv1_ATTR_XAUTH_TYPE] = #E S(IKEv1_ATTR_XAUTH_TYPE), /* 16520 */ S(IKEv1_ATTR_XAUTH_USER_NAME), S(IKEv1_ATTR_XAUTH_USER_PASSWORD), S(IKEv1_ATTR_XAUTH_PASSCODE), S(IKEv1_ATTR_XAUTH_MESSAGE), S(IKEv1_ATTR_XAUTH_CHALLENGE), S(IKEv1_ATTR_XAUTH_DOMAIN), S(IKEv1_ATTR_XAUTH_STATUS), S(IKEv1_ATTR_XAUTH_NEXT_PIN), S(IKEv1_ATTR_XAUTH_ANSWER), /* 16529 */ #undef S }; /* * 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 = { IKEv1_ATTR_XAUTH_TYPE, IKEv1_ATTR_XAUTH_ANSWER, ARRAY_REF(ikev1_attr_xauth_name), "IKEv1_ATTR_", /* prefix */ &modecfg_microsoft_attr_names }; /* Oakley Lifetime Type attribute */ static const char *const oakley_lifetime_name[] = { #define S(E) [E - OAKLEY_LIFE_SECONDS] = #E S(OAKLEY_LIFE_SECONDS), S(OAKLEY_LIFE_KILOBYTES), #undef S }; 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[] = { #define S(E) [E - 0] = #E S(OAKLEY_DES_CBC), /* obsoleted */ S(OAKLEY_IDEA_CBC), S(OAKLEY_BLOWFISH_CBC), /* obsoleted */ S(OAKLEY_RC5_R16_B64_CBC), S(OAKLEY_3DES_CBC), S(OAKLEY_CAST_CBC), S(OAKLEY_AES_CBC), S(OAKLEY_CAMELLIA_CBC), /* 8 */ S(OAKLEY_AES_CTR), /* stolen from IKEv2 */ S(OAKLEY_AES_CCM_8), S(OAKLEY_AES_CCM_12), S(OAKLEY_AES_CCM_16), S(OAKLEY_AES_GCM_8), S(OAKLEY_AES_GCM_12), S(OAKLEY_AES_GCM_16), S(OAKLEY_CAMELLIA_CTR), S(OAKLEY_CAMELLIA_CCM_8), S(OAKLEY_CAMELLIA_CCM_12), S(OAKLEY_CAMELLIA_CCM_16), /* 9-65000 Unassigned */ /* 65001-65535 Reserved for private use */ #undef S }; static const char *const oakley_enc_name_private_use[] = { #define S(E) [E - OAKLEY_MARS_CBC] = #E S(OAKLEY_MARS_CBC), /* 65001 */ S(OAKLEY_RC6_CBC), /* 65002 */ S(OAKLEY_SERPENT_CBC), /* 65004 */ S(OAKLEY_TWOFISH_CBC), /* 65005 */ #undef S }; static const char *const oakley_enc_name_private_use_ssh[] = { #define S(E) [E - OAKLEY_TWOFISH_CBC_SSH] = #E S(OAKLEY_TWOFISH_CBC_SSH), /* 65289 */ #undef S }; 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 = { 0, OAKLEY_CAMELLIA_CCM_16, 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[] = { #define S(E) [E - OAKLEY_MD5] = #E /* 0 - RESERVED */ S(OAKLEY_MD5), S(OAKLEY_SHA1), S(OAKLEY_TIGER), S(OAKLEY_SHA2_256), /* RFC 4878 */ S(OAKLEY_SHA2_384), /* RFC 4878 */ S(OAKLEY_SHA2_512), /* RFC 4878 */ /* 7-65000 Unassigned */ /* 65001-65535 Reserved for private use */ #undef S }; 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[] = { #define S(E) [E - OAKLEY_PRESHARED_KEY] = #E S(OAKLEY_PRESHARED_KEY), S(OAKLEY_DSS_SIG), S(OAKLEY_RSA_SIG), S(OAKLEY_RSA_ENC), S(OAKLEY_RSA_REVISED_MODE), S(OAKLEY_ECDSA_P256), /* RFC 4754 */ S(OAKLEY_ECDSA_P384), /* RFC 4754 */ S(OAKLEY_ECDSA_P521), /* RFC 4754 */ #undef S }; static const char *const oakley_auth_name_private_use2[] = { #define S(E) [E - HybridInitRSA] = #E S(HybridInitRSA), /* 64221 */ S(HybridRespRSA), S(HybridInitDSS), S(HybridRespDSS), #undef S }; static const char *const oakley_auth_name_private_use[] = { #define S(E) [E - XAUTHInitPreShared] = #E S(XAUTHInitPreShared), /* 65001 */ S(XAUTHRespPreShared), S(XAUTHInitDSS), S(XAUTHRespDSS), S(XAUTHInitRSA), S(XAUTHRespRSA), S(XAUTHInitRSAEncryption), S(XAUTHRespRSAEncryption), S(XAUTHInitRSARevisedEncryption), S(XAUTHRespRSARevisedEncryption), /* 65010 */ #undef S }; 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[] = { #define S(E) [E - IKEv2_CP_ATTR_RESERVED] = #E S(IKEv2_CP_ATTR_RESERVED), S(IKEv2_INTERNAL_IP4_ADDRESS), /* 1 */ S(IKEv2_INTERNAL_IP4_NETMASK), S(IKEv2_INTERNAL_IP4_DNS), S(IKEv2_INTERNAL_IP4_NBNS), S(IKEv2_INTERNAL_IP4_DHCP), S(IKEv2_APPLICATION_VERSION), S(IKEv2_INTERNAL_IP6_ADDRESS), S(IKEv2_INTERNAL_IP6_DNS), S(IKEv2_INTERNAL_IP6_DHCP), S(IKEv2_INTERNAL_IP4_SUBNET), /* 13 */ S(IKEv2_SUPPORTED_ATTRIBUTES), S(IKEv2_INTERNAL_IP6_SUBNET), S(IKEv2_MIP6_HOME_PREFIX), S(IKEv2_INTERNAL_IP6_LINK), S(IKEv2_INTERNAL_IP6_PREFIX), S(IKEv2_HOME_AGENT_ADDRESS), S(IKEv2_P_CSCF_IP4_ADDRESS), /* 20 */ S(IKEv2_P_CSCF_IP6_ADDRESS), S(IKEv2_FTT_KAT), S(IKEv2_EXTERNAL_SOURCE_IP4_NAT_INFO), /* 3gpp */ S(IKEv2_TIMEOUT_PERIOD_FOR_LIVENESS_CHECK), /* 3gpp */ S(IKEv2_INTERNAL_DNS_DOMAIN), /* draft-ietf-ipsecme-split-dns */ S(IKEv2_INTERNAL_DNSSEC_TA), /* draft-ietf-ipsecme-split-dns */ #undef S }; 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[] = { #define S(E) [E - IKEv2_CP_CFG_REQUEST] = #E S(IKEv2_CP_CFG_REQUEST), /* 1 */ S(IKEv2_CP_CFG_REPLY), S(IKEv2_CP_CFG_SET), S(IKEv2_CP_CFG_ACK), #undef S }; 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 S(E) [E - IKEv2_AUTH_RESERVED] = #E S(IKEv2_AUTH_RESERVED), S(IKEv2_AUTH_RSA_DIGITAL_SIGNATURE), S(IKEv2_AUTH_SHARED_KEY_MAC), S(IKEv2_AUTH_DSS_DIGITAL_SIGNATURE), /* 4 - 8 unassigned */ S(IKEv2_AUTH_ECDSA_SHA2_256_P256), S(IKEv2_AUTH_ECDSA_SHA2_384_P384), S(IKEv2_AUTH_ECDSA_SHA2_512_P521), S(IKEv2_AUTH_GENERIC_SECURE_PASSWORD_AUTHENTICATION_METHOD), /* 12 - RFC 6467 */ S(IKEv2_AUTH_NULL), S(IKEv2_AUTH_DIGITAL_SIGNATURE), /* 14 - RFC 7427 */ #undef S }; enum_names ikev2_auth_method_names = { IKEv2_AUTH_RESERVED, IKEv2_AUTH_DIGITAL_SIGNATURE, 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[] = { #define S(E) [E - OAKLEY_GROUP_NONE] = #E S(OAKLEY_GROUP_NONE), /* 0! RFC 7296 */ S(OAKLEY_GROUP_MODP768), S(OAKLEY_GROUP_MODP1024), S(OAKLEY_GROUP_GP155), S(OAKLEY_GROUP_GP185), S(OAKLEY_GROUP_MODP1536), /* RFC 3526 */ S(OAKLEY_GROUP_EC2N_2_1), /* draft-ietf-ipsec-ike-ecc-groups */ S(OAKLEY_GROUP_EC2N_2_2), /* draft-ietf-ipsec-ike-ecc-groups */ S(OAKLEY_GROUP_EC2N_2_3), /* draft-ietf-ipsec-ike-ecc-groups */ S(OAKLEY_GROUP_EC2N_2_4), /* draft-ietf-ipsec-ike-ecc-groups */ S(OAKLEY_GROUP_EC2N_2_5), /* draft-ietf-ipsec-ike-ecc-groups */ S(OAKLEY_GROUP_EC2N_2_6), /* draft-ietf-ipsec-ike-ecc-groups */ S(OAKLEY_GROUP_EC2N_2_7), /* draft-ietf-ipsec-ike-ecc-groups */ S(OAKLEY_GROUP_EC2N_2_8), /* draft-ietf-ipsec-ike-ecc-groups */ S(OAKLEY_GROUP_MODP2048), /* RFC 3526 */ S(OAKLEY_GROUP_MODP3072), /* RFC 3526 */ S(OAKLEY_GROUP_MODP4096), /* RFC 3526 */ S(OAKLEY_GROUP_MODP6144), /* RFC 3526 */ S(OAKLEY_GROUP_MODP8192), /* RFC 3526 */ S(OAKLEY_GROUP_ECP_256), /* RFC 5903 */ S(OAKLEY_GROUP_ECP_384), /* RFC 5903 */ S(OAKLEY_GROUP_ECP_521), /* RFC 5903 */ S(OAKLEY_GROUP_DH22), /* RFC 5114 */ S(OAKLEY_GROUP_DH23), /* RFC 5114 */ S(OAKLEY_GROUP_DH24), /* RFC 5114 */ S(OAKLEY_GROUP_ECP_192), /* RFC 5114 */ S(OAKLEY_GROUP_ECP_224), /* RFC 5114 */ S(OAKLEY_GROUP_BRAINPOOL_P224R1), /* RFC 6932 */ S(OAKLEY_GROUP_BRAINPOOL_P256R1), /* RFC 6932 */ S(OAKLEY_GROUP_BRAINPOOL_P384R1), /* RFC 6932 */ S(OAKLEY_GROUP_BRAINPOOL_P512R1), /* RFC 6932 */ S(OAKLEY_GROUP_CURVE25519), /* RFC-ietf-ipsecme-safecurves-05 */ S(OAKLEY_GROUP_CURVE448), /* RFC-ietf-ipsecme-safecurves-05 */ /* 33 - 32767 Unassigned */ /* 32768 - 65535 Reserved for private use */ #undef S }; 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[] = { #define S(E) [E - OAKLEY_GROUP_TYPE_MODP] = #E S(OAKLEY_GROUP_TYPE_MODP), S(OAKLEY_GROUP_TYPE_ECP), S(OAKLEY_GROUP_TYPE_EC2N), #undef S }; static enum_names oakley_group_type_names = { OAKLEY_GROUP_TYPE_MODP, OAKLEY_GROUP_TYPE_EC2N, ARRAY_REF(oakley_group_type_name), "OAKLEY_GROUP_TYPE_", /* prefix */ NULL }; /* Notify message type -- RFC2408 3.14.1 */ static const char *const v1_notification_name[] = { #define S(E) [E - v1N_INVALID_PAYLOAD_TYPE] = #E S(v1N_INVALID_PAYLOAD_TYPE), /* 1 */ S(v1N_DOI_NOT_SUPPORTED), S(v1N_SITUATION_NOT_SUPPORTED), S(v1N_INVALID_COOKIE), S(v1N_INVALID_MAJOR_VERSION), S(v1N_INVALID_MINOR_VERSION), S(v1N_INVALID_EXCHANGE_TYPE), S(v1N_INVALID_FLAGS), S(v1N_INVALID_MESSAGE_ID), S(v1N_INVALID_PROTOCOL_ID), S(v1N_INVALID_SPI), S(v1N_INVALID_TRANSFORM_ID), S(v1N_ATTRIBUTES_NOT_SUPPORTED), S(v1N_NO_PROPOSAL_CHOSEN), S(v1N_BAD_PROPOSAL_SYNTAX), S(v1N_PAYLOAD_MALFORMED), S(v1N_INVALID_KEY_INFORMATION), S(v1N_INVALID_ID_INFORMATION), S(v1N_INVALID_CERT_ENCODING), S(v1N_INVALID_CERTIFICATE), S(v1N_CERT_TYPE_UNSUPPORTED), S(v1N_INVALID_CERT_AUTHORITY), S(v1N_INVALID_HASH_INFORMATION), S(v1N_AUTHENTICATION_FAILED), S(v1N_INVALID_SIGNATURE), S(v1N_ADDRESS_NOTIFICATION), S(v1N_NOTIFY_SA_LIFETIME), S(v1N_CERTIFICATE_UNAVAILABLE), S(v1N_UNSUPPORTED_EXCHANGE_TYPE), S(v1N_UNEQUAL_PAYLOAD_LENGTHS), #undef S }; static const char *const v1_notification_connected_name[] = { #define S(E) [E - v1N_CONNECTED] = #E S(v1N_CONNECTED), /* 16384 */ #undef S }; static const char *const v1_notification_ipsec_name[] = { #define S(E) [E - v1N_IPSEC_RESPONDER_LIFETIME] = #E S(v1N_IPSEC_RESPONDER_LIFETIME), /* 24576 */ S(v1N_IPSEC_REPLAY_STATUS), S(v1N_IPSEC_INITIAL_CONTACT), #undef S }; static const char *const v1_notification_cisco_chatter_name[] = { #define S(E) [E - v1N_ISAKMP_N_CISCO_HELLO] = #E S(v1N_ISAKMP_N_CISCO_HELLO), /* 30000 */ S(v1N_ISAKMP_N_CISCO_WWTEBR), S(v1N_ISAKMP_N_CISCO_SHUT_UP), #undef S }; static const char *const v1_notification_ios_alives_name[] = { #define S(E) [E - v1N_ISAKMP_N_IOS_KEEP_ALIVE_REQ] = #E S(v1N_ISAKMP_N_IOS_KEEP_ALIVE_REQ), /* 32768 */ S(v1N_ISAKMP_N_IOS_KEEP_ALIVE_ACK), #undef S }; static const char *const v1_notification_dpd_name[] = { #define S(E) [E - v1N_R_U_THERE] = #E S(v1N_R_U_THERE), /* 36136 */ S(v1N_R_U_THERE_ACK), #undef S }; static const char *const v1_notification_juniper_name[] = { #define S(E) [E - v1N_NETSCREEN_NHTB_INFORM] = #E /* Next Hop Tunnel Binding */ S(v1N_NETSCREEN_NHTB_INFORM), /* 40001 */ #undef S }; static const char *const v1_notification_cisco_more_name[] = { #define S(E) [E - v1N_ISAKMP_N_CISCO_LOAD_BALANCE] = #E S(v1N_ISAKMP_N_CISCO_LOAD_BALANCE), /* 40501 */ S(v1N_ISAKMP_N_CISCO_UNKNOWN_40502), S(v1N_ISAKMP_N_CISCO_PRESHARED_KEY_HASH), #undef S }; 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 v2_notification_error_name[] = { #define S(E) [E - v2N_NOTHING_WRONG] = #E S(v2N_UNSUPPORTED_CRITICAL_PAYLOAD), S(v2N_INVALID_IKE_SPI), S(v2N_INVALID_MAJOR_VERSION), S(v2N_INVALID_SYNTAX), S(v2N_INVALID_MESSAGE_ID), S(v2N_INVALID_SPI), S(v2N_NO_PROPOSAL_CHOSEN), S(v2N_INVALID_KE_PAYLOAD), S(v2N_AUTHENTICATION_FAILED), S(v2N_SINGLE_PAIR_REQUIRED), S(v2N_NO_ADDITIONAL_SAS), S(v2N_INTERNAL_ADDRESS_FAILURE), S(v2N_FAILED_CP_REQUIRED), S(v2N_TS_UNACCEPTABLE), S(v2N_INVALID_SELECTORS), S(v2N_UNACCEPTABLE_ADDRESSES), S(v2N_UNEXPECTED_NAT_DETECTED), S(v2N_USE_ASSIGNED_HoA), S(v2N_TEMPORARY_FAILURE), S(v2N_CHILD_SA_NOT_FOUND), S(v2N_INVALID_GROUP_ID), S(v2N_AUTHORIZATION_FAILED), S(v2N_STATE_NOT_FOUND), #undef S }; /* https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xml#ikev2-parameters-13 */ static const char *const v2_notification_status_name[] = { #define S(E) [E - v2N_STATUS_FLOOR] = #E S(v2N_INITIAL_CONTACT), /* 16384 */ S(v2N_SET_WINDOW_SIZE), S(v2N_ADDITIONAL_TS_POSSIBLE), S(v2N_IPCOMP_SUPPORTED), S(v2N_NAT_DETECTION_SOURCE_IP), S(v2N_NAT_DETECTION_DESTINATION_IP), S(v2N_COOKIE), S(v2N_USE_TRANSPORT_MODE), S(v2N_HTTP_CERT_LOOKUP_SUPPORTED), S(v2N_REKEY_SA), S(v2N_ESP_TFC_PADDING_NOT_SUPPORTED), S(v2N_NON_FIRST_FRAGMENTS_ALSO), S(v2N_MOBIKE_SUPPORTED), S(v2N_ADDITIONAL_IP4_ADDRESS), S(v2N_ADDITIONAL_IP6_ADDRESS), S(v2N_NO_ADDITIONAL_ADDRESSES), S(v2N_UPDATE_SA_ADDRESSES), S(v2N_COOKIE2), S(v2N_NO_NATS_ALLOWED), S(v2N_AUTH_LIFETIME), S(v2N_MULTIPLE_AUTH_SUPPORTED), S(v2N_ANOTHER_AUTH_FOLLOWS), S(v2N_REDIRECT_SUPPORTED), S(v2N_REDIRECT), S(v2N_REDIRECTED_FROM), S(v2N_TICKET_LT_OPAQUE), S(v2N_TICKET_REQUEST), S(v2N_TICKET_ACK), S(v2N_TICKET_NACK), S(v2N_TICKET_OPAQUE), S(v2N_LINK_ID), S(v2N_USE_WESP_MODE), S(v2N_ROHC_SUPPORTED), S(v2N_EAP_ONLY_AUTHENTICATION), S(v2N_CHILDLESS_IKEV2_SUPPORTED), S(v2N_QUICK_CRASH_DETECTION), S(v2N_IKEV2_MESSAGE_ID_SYNC_SUPPORTED), S(v2N_IPSEC_REPLAY_COUNTER_SYNC_SUPPORTED), S(v2N_IKEV2_MESSAGE_ID_SYNC), S(v2N_IPSEC_REPLAY_COUNTER_SYNC), S(v2N_SECURE_PASSWORD_METHODS), S(v2N_PSK_PERSIST), S(v2N_PSK_CONFIRM), S(v2N_ERX_SUPPORTED), S(v2N_IFOM_CAPABILITY), S(v2N_SENDER_REQUEST_ID), S(v2N_IKEV2_FRAGMENTATION_SUPPORTED), S(v2N_SIGNATURE_HASH_ALGORITHMS), S(v2N_CLONE_IKE_SA_SUPPORTED), S(v2N_CLONE_IKE_SA), S(v2N_PUZZLE), S(v2N_USE_PPK), S(v2N_PPK_IDENTITY), S(v2N_NO_PPK_AUTH), S(v2N_INTERMEDIATE_EXCHANGE_SUPPORTED), S(v2N_IP4_ALLOWED), S(v2N_IP6_ALLOWED), S(v2N_ADDITIONAL_KEY_EXCHANGE), S(v2N_USE_AGGFRAG), #undef S }; static const char *const v2_notification_private_first_range_name[] = { #define S(E) [E - v2N_NULL_AUTH] = #E S(v2N_NULL_AUTH), /* 40960, used for mixed OE */ #undef S }; static const char *const v2_notification_private_second_range_name[] = { #define S(E) [E - v2N_PPK_IDENTITY_KEY] = #E S(v2N_PPK_IDENTITY_KEY), /* 50208, draft-ietf-ipsecme-ikev2-qr-alt-04 */ S(v2N_USE_PPK_INT), /* 50209, draft-ietf-ipsecme-ikev2-qr-alt-04 */ #undef S }; static const struct enum_names v2_notification_private_second_range_names = { v2N_PPK_IDENTITY_KEY, v2N_USE_PPK_INT, ARRAY_REF(v2_notification_private_second_range_name), "v2N_", /* prefix */ NULL }; static const struct enum_names v2_notification_private_first_range_names = { v2N_NULL_AUTH, v2N_NULL_AUTH, ARRAY_REF(v2_notification_private_first_range_name), "v2N_", /* prefix */ &v2_notification_private_second_range_names }; static const struct enum_names v2_notification_status_names = { v2N_INITIAL_CONTACT, v2N_USE_AGGFRAG, ARRAY_REF(v2_notification_status_name), "v2N_", /* prefix */ &v2_notification_private_first_range_names, }; const struct enum_names v2_notification_names = { v2N_NOTHING_WRONG, v2N_STATE_NOT_FOUND, ARRAY_REF(v2_notification_error_name), "v2N_", /* prefix */ &v2_notification_status_names }; /* https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xml#ikev2-parameters-19 */ static const char *const ikev2_ts_type_name[] = { #define S(E) [E - IKEv2_TS_IPV4_ADDR_RANGE] = #E S(IKEv2_TS_IPV4_ADDR_RANGE), /* 7 */ S(IKEv2_TS_IPV6_ADDR_RANGE), /* 8 */ S(IKEv2_TS_FC_ADDR_RANGE), /* 9; not implemented */ S(IKEv2_TS_SECLABEL), /* 10; Early Code Point */ #undef S }; 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[] = { #define S(E) [E - ISAKMP_CFG_REQUEST] = #E S(ISAKMP_CFG_REQUEST), /* 1 */ S(ISAKMP_CFG_REPLY), S(ISAKMP_CFG_SET), S(ISAKMP_CFG_ACK), #undef S }; 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[] = { #define S(E) [E - 0] = #E #define R(E,S) [E - 0] = #S R(0, RESERVED bit 0), /* bit 0 */ R(1, RESERVED bit 1), /* bit 1 */ R(2, RESERVED bit 2), /* bit 2 */ R(3, RESERVED bit 3), /* bit 3 */ R(4, RESERVED bit 4), /* bit 4 */ R(5, RESERVED bit 5), /* bit 5 */ R(6, RESERVED bit 6), /* bit 6 */ R(7, PAYLOAD_CRITICAL), /* bit 7 */ #undef R #undef S }; 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[] = { #define S(E) [E - IKEv2_SEC_PROTO_IKE] = #E S(IKEv2_SEC_PROTO_IKE), S(IKEv2_SEC_PROTO_AH), S(IKEv2_SEC_PROTO_ESP), S(IKEv2_SEC_FC_ESP_HEADER), /* RFC 4595 */ S(IKEv2_SEC_FC_CT_AUTHENTICATION), /* RFC 4595 */ /* 6 - 200 Unassigned */ /* 201 - 255 Private use */ #undef S }; 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[] = { #define S(E) [E - IKEv2_SEC_PROTO_IKE] = #E S(IKEv2_SEC_PROTO_IKE), S(IKEv2_SEC_PROTO_AH), S(IKEv2_SEC_PROTO_ESP), #undef S }; 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 S(E) [E - IKEv2_SEC_PROTO_NONE] = #E S(IKEv2_SEC_PROTO_NONE), S(IKEv2_SEC_PROTO_IKE), S(IKEv2_SEC_PROTO_AH), S(IKEv2_SEC_PROTO_ESP), #undef S }; 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[] = { #define S(E) [E - IKEv2_ENCR_TWOFISH_CBC_SSH] = #E S(IKEv2_ENCR_TWOFISH_CBC_SSH), /* 65289 */ #undef S }; static enum_names ikev2_trans_type_encr_names_private_use2 = { IKEv2_ENCR_TWOFISH_CBC_SSH, IKEv2_ENCR_TWOFISH_CBC_SSH, ARRAY_REF(ikev2_trans_type_encr_name_private_use2), NULL, /* prefix */ NULL }; static const char *const ikev2_trans_type_encr_name_private_use1[] = { #define S(E) [E - IKEv2_ENCR_SERPENT_CBC] = #E S(IKEv2_ENCR_SERPENT_CBC), /* 65004 */ S(IKEv2_ENCR_TWOFISH_CBC), #undef S }; static enum_names ikev2_trans_type_encr_names_private_use1 = { IKEv2_ENCR_SERPENT_CBC, IKEv2_ENCR_TWOFISH_CBC, ARRAY_REF(ikev2_trans_type_encr_name_private_use1), NULL, /* prefix */ &ikev2_trans_type_encr_names_private_use2 }; static const char *const ikev2_trans_type_encr_name[] = { #define S(E) [E - IKEv2_ENCR_DES_IV64] = #E S(IKEv2_ENCR_DES_IV64), /* 1 */ S(IKEv2_ENCR_DES), S(IKEv2_ENCR_3DES), S(IKEv2_ENCR_RC5), S(IKEv2_ENCR_IDEA), S(IKEv2_ENCR_CAST), S(IKEv2_ENCR_BLOWFISH), S(IKEv2_ENCR_3IDEA), S(IKEv2_ENCR_DES_IV32), S(IKEv2_ENCR_NULL), S(IKEv2_ENCR_AES_CBC), S(IKEv2_ENCR_AES_CTR), S(IKEv2_ENCR_AES_CCM_8), /* AES-CCM_8 RFC 4309 */ S(IKEv2_ENCR_AES_CCM_12), /* AES-CCM_12 */ S(IKEv2_ENCR_AES_CCM_16), /* AES-CCM_16 */ S(IKEv2_ENCR_AES_GCM_8), /* AES-GCM_8 RFC 4106 */ S(IKEv2_ENCR_AES_GCM_12), /* AES-GCM_12 */ S(IKEv2_ENCR_AES_GCM_16), /* AES-GCM_16 */ S(IKEv2_ENCR_NULL_AUTH_AES_GMAC), /* RFC 4543 */ S(IKEv2_ENCR_CAMELLIA_CBC), /* RFC 5529 */ S(IKEv2_ENCR_CAMELLIA_CTR), /* RFC 5529 */ S(IKEv2_ENCR_CAMELLIA_CCM_8), /* CAMELLIA_CCM_8 RFC 5529 */ S(IKEv2_ENCR_CAMELLIA_CCM_12), /* CAMELLIA_CCM_12 RFC 5529 */ S(IKEv2_ENCR_CAMELLIA_CCM_16), /* CAMELLIA_CCM_16 RFC 5529 */ S(IKEv2_ENCR_CHACHA20_POLY1305), /* RFC 7634 */ /* 29 - 1023 Unassigned */ /* 1024 - 65535 Private use */ #undef S }; enum_names ikev2_trans_type_encr_names = { IKEv2_ENCR_DES_IV64, IKEv2_ENCR_CHACHA20_POLY1305, ARRAY_REF(ikev2_trans_type_encr_name), "IKEv2_ENCR_", /* prefix */ &ikev2_trans_type_encr_names_private_use1 }; /* Transform-type PRF */ static const char *const ikev2_trans_type_prf_name[] = { #define S(E) [E - IKEv2_PRF_HMAC_MD5] = #E S(IKEv2_PRF_HMAC_MD5), S(IKEv2_PRF_HMAC_SHA1), S(IKEv2_PRF_HMAC_TIGER), S(IKEv2_PRF_AES128_XCBC), /* RFC 4868 Section 4 */ S(IKEv2_PRF_HMAC_SHA2_256), S(IKEv2_PRF_HMAC_SHA2_384), S(IKEv2_PRF_HMAC_SHA2_512), S(IKEv2_PRF_AES128_CMAC) #undef S }; enum_names ikev2_trans_type_prf_names = { IKEv2_PRF_HMAC_MD5, IKEv2_PRF_AES128_CMAC, ARRAY_REF(ikev2_trans_type_prf_name), "IKEv2_PRF_", /* prefix */ NULL }; /* Transform-type Integrity */ static const char *const ikev2_trans_type_integ_name[] = { #define S(E) [E - IKEv2_INTEG_NONE] = #E S(IKEv2_INTEG_NONE), S(IKEv2_INTEG_HMAC_MD5_96), S(IKEv2_INTEG_HMAC_SHA1_96), S(IKEv2_INTEG_DES_MAC), S(IKEv2_INTEG_KPDK_MD5), S(IKEv2_INTEG_AES_XCBC_96), S(IKEv2_INTEG_HMAC_MD5_128), S(IKEv2_INTEG_HMAC_SHA1_160), S(IKEv2_INTEG_AES_CMAC_96), S(IKEv2_INTEG_AES_128_GMAC), S(IKEv2_INTEG_AES_192_GMAC), S(IKEv2_INTEG_AES_256_GMAC), S(IKEv2_INTEG_HMAC_SHA2_256_128), S(IKEv2_INTEG_HMAC_SHA2_384_192), S(IKEv2_INTEG_HMAC_SHA2_512_256), #undef S }; enum_names ikev2_trans_type_integ_names = { IKEv2_INTEG_NONE, IKEv2_INTEG_HMAC_SHA2_512_256, ARRAY_REF(ikev2_trans_type_integ_name), "IKEv2_INTEG_", /* prefix */ NULL }; /* Transform-type Integrity */ static const char *const ikev2_trans_type_esn_name[] = { #define S(E) [E - IKEv2_ESN_FLOOR] = #E S(IKEv2_ESN_YES), S(IKEv2_ESN_NO), #undef S }; enum_names ikev2_trans_type_esn_names = { IKEv2_ESN_FLOOR, IKEv2_ESN_ROOF-1, ARRAY_REF(ikev2_trans_type_esn_name), "IKEv2_ESN_", /* prefix */ NULL }; /* Transform Type */ static const char *const ikev2_trans_type_name[] = { #define S(E) [E - IKEv2_TRANS_TYPE_FLOOR] = #E S(IKEv2_TRANS_TYPE_ENCR), S(IKEv2_TRANS_TYPE_PRF), S(IKEv2_TRANS_TYPE_INTEG), S(IKEv2_TRANS_TYPE_DH), S(IKEv2_TRANS_TYPE_ESN), #undef S }; enum_names ikev2_trans_type_names = { IKEv2_TRANS_TYPE_FLOOR, IKEv2_TRANS_TYPE_ROOF-1, ARRAY_REF(ikev2_trans_type_name), "IKEv2_TRANS_TYPE_", /* prefix */ NULL }; /* for each IKEv2 transform attribute, which enum_names describes its values? */ static enum_names *const ikev2_transid_val_descs[] = { #define S(E,V) [E - IKEv2_TRANS_TYPE_FLOOR] = &V S(IKEv2_TRANS_TYPE_ENCR, ikev2_trans_type_encr_names), /* 1 */ S(IKEv2_TRANS_TYPE_PRF, ikev2_trans_type_prf_names), /* 2 */ S(IKEv2_TRANS_TYPE_INTEG, ikev2_trans_type_integ_names), /* 3 */ S(IKEv2_TRANS_TYPE_DH, oakley_group_names), /* 4 */ S(IKEv2_TRANS_TYPE_ESN, ikev2_trans_type_esn_names), /* 5 */ #undef S }; enum_enum_names v2_transform_ID_enums = { IKEv2_TRANS_TYPE_FLOOR, IKEv2_TRANS_TYPE_ROOF-1, ARRAY_REF(ikev2_transid_val_descs) }; /* Transform Attributes */ static const char *const ikev2_trans_attr_name[] = { #define S(E) [E - IKEv2_KEY_LENGTH] = #E S(IKEv2_KEY_LENGTH), #undef S }; 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[] = { #define S(E) [E - SECRET_PSK] = #E S(SECRET_PSK), S(SECRET_RSA), S(SECRET_XAUTH), S(SECRET_PPK), S(SECRET_ECDSA), S(SECRET_NULL), S(SECRET_INVALID), #undef S }; enum_names secret_kind_names = { SECRET_PSK, SECRET_INVALID, ARRAY_REF(secret_kind_name), "SECRET_", /* prefix */ NULL }; /* * IKEv2 PPK ID types - RFC 8784 */ static const char *const ikev2_ppk_id_type_name[] = { /* 0 - Reserved */ #define S(E) [E - PPK_ID_OPAQUE] = #E S(PPK_ID_OPAQUE), S(PPK_ID_FIXED), #undef S /* 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[] = { #define S(E) [E - GW_IPV4] = #E #define R(E,S) [E - GW_IPV4] = #S /* 0 - Reserved */ R(GW_IPV4, GW_IPv4), R(GW_IPV6, GW_IPv6), S(GW_FQDN), /* 4 - 240 Unassigned */ /* 241 - 255 Private Use */ #undef R #undef S }; 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[] = { #define S(E) [E - EAP_CODE_REQUEST] = #E S(EAP_CODE_REQUEST), S(EAP_CODE_RESPONSE), S(EAP_CODE_SUCCESS), S(EAP_CODE_FAILURE), #undef S }; 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[] = { #define S(E) [E - EAP_TYPE_TLS] = #E S(EAP_TYPE_TLS), #undef S }; 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[] = { #define S(E) [E - EAPTLS_FLAGS_START_IX] = #E #define R(E,S) [E - EAPTLS_FLAGS_START_IX] = #S R(EAPTLS_FLAGS_START_IX, EAPTLS_FLAG_START), R(EAPTLS_FLAGS_MORE_IX, EAPTLS_FLAG_MORE), R(EAPTLS_FLAGS_LENGTH_IX, EAPTLS_FLAG_LENGTH), #undef R #undef S }; 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 */ }; /* * enum global_timers */ static const char *global_timer_name[] = { #define S(E) [E - EVENT_REINIT_SECRET] = #E S(EVENT_REINIT_SECRET), S(EVENT_SHUNT_SCAN), S(EVENT_PENDING_DDNS), S(EVENT_SD_WATCHDOG), S(EVENT_CHECK_CRLS), S(EVENT_FREE_ROOT_CERTS), S(EVENT_RESET_LOG_LIMITER), #undef S }; const struct enum_names global_timer_names = { GLOBAL_TIMER_FLOOR, GLOBAL_TIMER_ROOF-1, ARRAY_REF(global_timer_name), "EVENT_", NULL, }; /* * enum event_type */ static const char *const event_name[] = { #define S(E) [E - EVENT_NULL] = #E S(EVENT_NULL), #undef S }; static const enum_names event_names = { EVENT_NULL, EVENT_NULL, ARRAY_REF(event_name), "EVENT_", /* prefix */ NULL }; static const char *const event_v1_name[] = { #define S(E) [E - EVENT_v1_SEND_XAUTH] = #E S(EVENT_v1_SEND_XAUTH), S(EVENT_v1_DPD), S(EVENT_v1_DPD_TIMEOUT), S(EVENT_v1_PAM_TIMEOUT), S(EVENT_v1_REPLACE), S(EVENT_v1_DISCARD), S(EVENT_v1_RETRANSMIT), S(EVENT_v1_NAT_KEEPALIVE), S(EVENT_v1_CRYPTO_TIMEOUT), S(EVENT_v1_EXPIRE), #undef S }; static const enum_names event_v1_names = { EVENT_v1_FLOOR, EVENT_v1_ROOF-1, ARRAY_REF(event_v1_name), "EVENT_v1_", /* prefix */ &event_names }; static const char *const event_v2_name[] = { #define S(E) [E - EVENT_v2_REKEY] = #E S(EVENT_v2_REKEY), S(EVENT_v2_REPLACE), S(EVENT_v2_DISCARD), S(EVENT_v2_TIMEOUT_INITIATOR), S(EVENT_v2_TIMEOUT_RESPONDER), S(EVENT_v2_TIMEOUT_RESPONSE), S(EVENT_v2_LIVENESS), S(EVENT_v2_ADDR_CHANGE), S(EVENT_v2_RETRANSMIT), S(EVENT_v2_NAT_KEEPALIVE), S(EVENT_v2_EXPIRE), #undef S }; static const enum_names event_v2_names = { EVENT_v2_FLOOR, EVENT_v2_ROOF-1, ARRAY_REF(event_v2_name), "EVENT_v2_", /* prefix */ &event_v1_names, }; static const char *const event_retain_name[] = { #define S(E) [E - EVENT_RETAIN] = #E S(EVENT_RETAIN), #undef S }; const enum_names event_type_names = { EVENT_RETAIN, EVENT_RETAIN, ARRAY_REF(event_retain_name), "EVENT_", /* prefix */ &event_v2_names, }; libreswan-5.2/lib/libswan/crypt_cipher.c000066400000000000000000000144001475767661000204340ustar00rootroot00000000000000/* CIPHER helper functions, for libreswan * * Copyright (C) 2024 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY 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_cipher.h" #include "ike_alg.h" #include "ike_alg_encrypt_ops.h" #include "lswalloc.h" #include "lswlog.h" #include "crypt_symkey.h" #include "crypt_mac.h" void cipher_ikev1(const struct encrypt_desc *cipher, enum cipher_op op, chunk_t data, struct crypt_mac *iv, PK11SymKey *symkey, struct logger *logger) { enum cipher_iv_source iv_source = USE_IKEv1_IV; struct cipher_context *context = cipher_context_create(cipher, op, iv_source, symkey, null_shunk, logger); chunk_t iv_chunk = HUNK_AS_CHUNK((*iv)); chunk_t wire_iv = hunk_slice(iv_chunk, cipher->salt_size, cipher->salt_size + cipher->wire_iv_size); cipher_context_op_normal(context, wire_iv, data, iv, logger); cipher_context_destroy(&context, logger); } bool cipher_aead(const struct encrypt_desc *cipher, enum cipher_op op, enum cipher_iv_source iv_source, shunk_t salt, chunk_t wire_iv, shunk_t aad, chunk_t text_and_tag, size_t text_size, size_t tag_size, PK11SymKey *symkey, struct logger *logger) { struct cipher_context *context = cipher_context_create(cipher, op, iv_source, symkey, salt, logger); if (context == NULL) { /* already logged */ return false; } bool ok = cipher_context_op_aead(context, wire_iv, aad, text_and_tag, text_size, tag_size, logger); cipher_context_destroy(&context, logger); return ok; } struct cipher_context { const struct encrypt_desc *cipher; struct cipher_op_context *op_context; enum cipher_op op; enum cipher_iv_source iv_source; chunk_t salt; PK11SymKey *symkey; chunk_t old_wire_iv; }; struct cipher_context *cipher_context_create(const struct encrypt_desc *cipher, enum cipher_op op, enum cipher_iv_source iv_source, PK11SymKey *symkey, shunk_t salt, struct logger *logger) { if (LDBGP(DBG_BASE, logger)) { bool dump_salt = (LDBGP(DBG_CRYPT, logger) && salt.len > 0); LDBG_log(logger, "%s() %s %s %s symkey %p%s", __func__, cipher->common.fqn, str_cipher_op(op), str_cipher_iv_source(iv_source), symkey, (dump_salt ? ", salt: " : "")); if (dump_salt) { LDBG_hunk(logger, salt); } } struct cipher_context *cipher_context = alloc_thing(struct cipher_context, __func__); cipher_context->cipher = cipher; cipher_context->op = op; cipher_context->iv_source = iv_source; cipher_context->symkey = symkey_addref(logger, __func__, symkey); cipher_context->salt = clone_hunk(salt, __func__); cipher_context->old_wire_iv = alloc_chunk(cipher->wire_iv_size, __func__); if (cipher->encrypt_ops->cipher_op_context_create != NULL) { cipher_context->op_context = cipher->encrypt_ops->cipher_op_context_create(cipher, op, iv_source, symkey, salt, logger); PASSERT(logger, cipher_context->op_context != NULL); } return cipher_context; } void cipher_context_destroy(struct cipher_context **cipher_context, struct logger *logger) { if ((*cipher_context) == NULL) { /* presumably an incomplete state */ ldbg(logger, "no cipher context to delete"); return; } const struct encrypt_desc *cipher = (*cipher_context)->cipher; if (cipher->encrypt_ops->cipher_op_context_destroy != NULL) { PASSERT(logger, (*cipher_context)->op_context != NULL); cipher->encrypt_ops->cipher_op_context_destroy(&(*cipher_context)->op_context, logger); } else { PASSERT(logger, (*cipher_context)->op_context == NULL); } symkey_delref(logger, __func__, &(*cipher_context)->symkey); free_chunk_content(&(*cipher_context)->salt); free_chunk_content(&(*cipher_context)->old_wire_iv); pfreeany(*cipher_context); return; } static void verify_wire_iv(const struct cipher_context *cipher_context, chunk_t new_wire_iv, struct logger *logger) { if (cipher_context->iv_source == FILL_WIRE_IV && cipher_context->cipher->wire_iv_size > 0/*not-NULL*/) { LDBGP_JAMBUF(DBG_BASE, logger, buf) { jam(buf, "update %p %s wire_iv ", cipher_context, cipher_context->cipher->common.fqn); jam_hex_hunk(buf, cipher_context->old_wire_iv); jam_string(buf, " -> "); jam_hex_hunk(buf, new_wire_iv); } PASSERT(logger, !hunk_eq(new_wire_iv, cipher_context->old_wire_iv)); hunk_cpy(cipher_context->old_wire_iv, new_wire_iv); } } bool cipher_context_op_aead(const struct cipher_context *cipher_context, chunk_t wire_iv, shunk_t aad, chunk_t text_and_tag, size_t text_size, size_t tag_size, struct logger *logger) { if (cipher_context->cipher->aead_tag_size != tag_size) { llog(RC_LOG, logger, "tag size %zu is invalid for %s", tag_size, cipher_context->cipher->common.fqn); return false; } if (!cipher_context->cipher->encrypt_ops->cipher_op_aead(cipher_context->cipher, cipher_context->op_context, cipher_context->op, cipher_context->iv_source, cipher_context->symkey, HUNK_AS_SHUNK(cipher_context->salt), wire_iv, aad, text_and_tag, text_size, tag_size, logger)) { return false; } verify_wire_iv(cipher_context, wire_iv, logger); return true; } void cipher_context_op_normal(const struct cipher_context *cipher_context, chunk_t wire_iv, chunk_t text, struct crypt_mac *ikev1_iv, struct logger *logger) { cipher_context->cipher->encrypt_ops->cipher_op_normal(cipher_context->cipher, cipher_context->op_context, cipher_context->op, cipher_context->iv_source, cipher_context->symkey, HUNK_AS_SHUNK(cipher_context->salt), wire_iv, text, ikev1_iv, logger); verify_wire_iv(cipher_context, wire_iv, logger); } libreswan-5.2/lib/libswan/crypt_hash.c000066400000000000000000000103541475767661000201110ustar00rootroot00000000000000/* * 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) { ldbgf(DBG_CRYPT, logger, "%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)); LDBG_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) { ldbgf(DBG_CRYPT, logger, "%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-5.2/lib/libswan/crypt_mac.c000066400000000000000000000013201475767661000177170ustar00rootroot00000000000000/* 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-5.2/lib/libswan/crypt_prf.c000066400000000000000000000157221475767661000177610ustar00rootroot00000000000000/* * 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 */ ldbgf(DBG_CRYPT, logger, "%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 (LDBGP(DBG_CRYPT, logger)) { LDBG_log(logger, "%s PRF %s init %s hunk %p (length %zd)", name, prf_desc->common.fqn, key_name, key, key_size); LDBG_dump(logger, 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)); LDBG_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)); LDBG_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; struct logger *logger = (*prfp)->logger; PK11SymKey *tmp = prf->desc->prf_mac_ops->final_symkey(&prf->context); if (DBGP(DBG_CRYPT)) { LDBG_log(logger, "%s PRF %s final-key@%p (size %zu)", (*prfp)->name, (*prfp)->desc->common.fqn, tmp, sizeof_symkey(tmp)); LDBG_symkey(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-5.2/lib/libswan/crypt_symkey.c000066400000000000000000000433621475767661000205140ustar00rootroot00000000000000/* * 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 "fips_mode.h" #include "lswnss.h" #include "ike_alg_encrypt.h" /* for ike_alg_encrypt_null */ #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) { LLOG_FATAL_JAMBUF(PLUTO_EXIT_FAIL, logger, buf) { jam(buf, "NSS: ephemeral slot error: "); jam_nss_error_code(buf, PR_GetError()); } } ephemeral_symkey = PK11_KeyGen(slot, CKM_AES_KEY_GEN, NULL, 128/8, NULL); PK11_FreeSlot(slot); /* reference counted */ if (DBGP(DBG_CRYPT)) { LDBG_symkey(logger, SPACES, "ephemeral", ephemeral_symkey); } } void symkey_delref_where(struct logger *logger, const char *name, PK11SymKey **key, where_t where) { ldbg_delref_where(logger, name, (*key), where); if (*key != NULL) { PK11_FreeSymKey(*key); } *key = NULL; } PK11SymKey *symkey_addref_where(struct logger *logger, const char *name, PK11SymKey *key, where_t where) { ldbg_addref_where(logger, name, key, where); if (key != NULL) { PK11_ReferenceSymKey(key); } 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 LDBG_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 (is_fips_mode()) { 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) { LLOG_PEXPECT_JAMBUF(logger, HERE, buf) { jam_string(buf, "NSS: "); jam_nss_ckm(buf, derive); jam_string(buf, " failed: "); jam_nss_error_code(buf, PR_GetError()); } 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_where(buf, 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_IN_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) { ldbgf(DBG_CRYPT, logger, "%s NULL key has no bytes", name); return EMPTY_CHUNK; } size_t sizeof_bytes = sizeof_symkey(symkey); if (DBGP(DBG_CRYPT)) { LDBG_log(logger, "%s extracting all %zd bytes of key@%p", name, sizeof_bytes, symkey); LDBG_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 symkey_addref() */ LDBG_log(logger, "%s: slot-key@%p: addref sym-key@%p", name, slot_key, symkey); } else { LDBG_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); ldbgf(DBG_CRYPT, logger, "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); symkey_delref(logger, "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, }; } chunk_t chunk_from_symkey_bytes(const char *prefix, PK11SymKey *symkey, size_t chunk_start, size_t sizeof_chunk, struct logger *logger, where_t where) { PK11SymKey *slice = key_from_symkey_bytes(prefix, symkey, chunk_start, sizeof_chunk, where, logger); chunk_t chunk = chunk_from_symkey("initiator salt", slice, logger); symkey_delref(logger, "slice", &slice); return chunk; } /* * 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); symkey_delref(logger, "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); symkey_delref(logger, "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); symkey_delref(logger, "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); symkey_delref(logger, "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); symkey_delref(logger, "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); symkey_delref(logger, "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 throws a hissy fit when asked to extract 0 bytes. */ if (sizeof_symkey == 0) { PASSERT(logger, encrypt == &ike_alg_encrypt_null); PASSERT(logger, impair.allow_null_none); return NULL; } /* * 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); } PK11SymKey *cipher_symkey(const char *name, const struct encrypt_desc *cipher, unsigned bits, struct logger *logger, where_t where) { bool valid_key_length = false; FOR_EACH_ELEMENT(key, cipher->key_bit_lengths) { if (*key == bits) { valid_key_length = true; break; } } PASSERT(logger, valid_key_length); PASSERT(logger, cipher->nss.key_gen != 0); PK11SlotInfo *slot = PK11_GetBestSlot(cipher->nss.key_gen, lsw_nss_get_password_context(logger)); PK11SymKey *symkey = PK11_KeyGen(slot, cipher->nss.key_gen, /*param*/NULL, BYTES_FOR_BITS(bits), /*wincx*/NULL); ldbg_alloc(logger, name, symkey, where); return symkey; } libreswan-5.2/lib/libswan/datatot.c000066400000000000000000000123021475767661000174000ustar00rootroot00000000000000/* * 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 void *src, size_t srclen, int format, /* character indicating what format */ char *dst, /* need not be valid if dstlen is 0 */ size_t dstlen) { size_t inblocksize; /* process this many bytes at a time */ size_t outblocksize; /* producing this many */ size_t breakevery; /* add a _ every this many (0 means don't) */ size_t sincebreak; /* output bytes since last _ */ char breakchar; /* character used to break between groups */ unsigned char inblock[10]; /* enough for any format */ char outblock[10]; /* enough for any format */ char fake[1]; /* fake output area for dstlen == 0 */ size_t needed; /* return value */ char *stop; /* where the terminating NUL will go */ size_t ntodo; /* remaining input */ size_t nreal; char *out; char *prefix; breakevery = 0; breakchar = '_'; switch (format) { case 0: case 'h': 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); /*dstlen > strlen(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-5.2/lib/libswan/debug.c000066400000000000000000000053111475767661000170300ustar00rootroot00000000000000/* debug set constants, for libreswan * * Copyright (C) 2017-2019 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include "constants.h" #include "enum_names.h" #include "lmod.h" #include "lswcdefs.h" /* for ARRAY_REF() */ /* * Initialize both the .name and .help arrays. * * See plutomain.c why the name has an extra "\0" appended (hint it is * a hack for encoding what to do with flags). * * XXX: since only the --debug ... form is supported, has this all * become redundant. * * So that grepping for DBG. finds this file, the N parameter is * the full enum name (DBG_...) and not just the truncated suffix. */ struct double_double { const char *name[DBG_roof_IX - DBG_floor_IX]; const char *help[DBG_roof_IX - DBG_floor_IX]; }; static struct double_double debug = { #define D(N,A,H) \ .name[N##_IX - DBG_floor_IX] = A "\0", \ .help[N##_IX - DBG_floor_IX] = H D(DBG_BASE, "debug-base", "enable detailed debug logging"), D(DBG_ROUTING, "debug-routing", "enable routing debug logging"), /* end of debug=base */ D(DBG_CPU_USAGE, "debug-cpu-usage", "estimate cpu used"), D(DBG_REFCNT, "debug-refcnt", "debug reference counts"), /* end of debug=all */ D(DBG_TMI, "debug-tmi", "far too much information"), /* end of debug=tmi */ D(DBG_UPDOWN, "debug-updown", "run updown script with 'set -v -x'"), 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"), #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[] = { { "base", LRANGE(DBG_floor_IX, DBG_base_IX), }, { "all", LRANGE(DBG_floor_IX, DBG_all_IX), }, { "tmi", LRANGE(DBG_floor_IX, DBG_tmi_IX), }, { 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-5.2/lib/libswan/deltatime.c000066400000000000000000000122771475767661000177230ustar00rootroot00000000000000/* 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 = { .is_set = true, }; const deltatime_t one_day = DELTATIME_INIT(secs_per_day); const deltatime_t one_hour = DELTATIME_INIT(secs_per_hour); const deltatime_t one_minute = DELTATIME_INIT(secs_per_minute); const deltatime_t one_second = DELTATIME_INIT(1); /* * 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 seconds) { return (deltatime_t) { .dt = from_seconds(seconds), .is_set = true, }; } deltatime_t deltatime_from_milliseconds(intmax_t ms) { return (deltatime_t) { .dt = from_milliseconds(ms), .is_set = true, }; } deltatime_t deltatime_from_microseconds(intmax_t us) { return (deltatime_t) { .dt = from_microseconds(us), .is_set = true, }; } deltatime_t deltatime_timevals_diff(struct timeval a, struct timeval b) { struct timeval res; timersub(&a, &b, &res); return deltatime_from_timeval(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 l, deltatime_t r) { if (deltatime_cmp(l, >, r)) { return l; } else { return r; } } deltatime_t deltatime_min(deltatime_t l, deltatime_t r) { if (deltatime_cmp(l, <, r)) { return l; } else { return r; } } deltatime_t deltatime_add(deltatime_t a, deltatime_t b) { struct timeval res; timeradd(&a.dt, &b.dt, &res); return deltatime_from_timeval(res); } deltatime_t deltatime_sub(deltatime_t a, deltatime_t b) { struct timeval res; timersub(&a.dt, &b.dt, &res); return deltatime_from_timeval(res); } deltatime_t deltatime_mulu(deltatime_t a, unsigned scalar) { return deltatime_from_milliseconds(milliseconds_from_deltatime(a) * scalar); } deltatime_t deltatime_divu(deltatime_t a, unsigned scalar) { return deltatime_from_milliseconds(milliseconds_from_deltatime(a) / scalar); } intmax_t microseconds_from_deltatime(deltatime_t d) { return microseconds_from(d.dt); } intmax_t milliseconds_from_deltatime(deltatime_t d) { return milliseconds_from(d.dt); } intmax_t seconds_from_deltatime(deltatime_t d) { /* XXX: ignore .tv_usec's bias, don't round */ return seconds_from(d.dt); } 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 = { .dt = t, .is_set = true, }; return d; } /* * Try to be smart by only printing the precision necessary. For * instance 1, 0.5, ... */ 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); } jam_decimal(buf, d.dt.tv_sec, d.dt.tv_usec, 1000000/*us*/); 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; } struct timeval from_seconds(time_t seconds) { struct timeval tv = { .tv_sec = seconds, }; return tv; } struct timeval from_milliseconds(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; } struct timeval from_microseconds(intmax_t us) { intmax_t ams = imaxabs(us); struct timeval tv = { .tv_sec = ams / 1000 / 1000, .tv_usec = ams % 1000000, }; if (us < 0) { tv = negate_timeval(tv); } return tv; } intmax_t seconds_from(struct timeval v) { return v.tv_sec; } intmax_t milliseconds_from(struct timeval v) { return ((intmax_t) v.tv_sec) * 1000 + v.tv_usec / 1000; } intmax_t microseconds_from(struct timeval v) { return ((intmax_t) v.tv_sec) * 1000 * 1000 + v.tv_usec; } libreswan-5.2/lib/libswan/diag.c000066400000000000000000000047071475767661000166560ustar00rootroot00000000000000/* 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); /* NO ": "; not *perror() */ 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"); } 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)); } libreswan-5.2/lib/libswan/encap_mode_names.c000066400000000000000000000024701475767661000212220ustar00rootroot00000000000000/* encap mode, 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 "encap_mode.h" #include "lswcdefs.h" /* for ARRAY_REF() */ #include "enum_names.h" static const char *encap_mode_name[] = { #define S(E) [E-ENCAP_MODE_TRANSPORT] = #E S(ENCAP_MODE_TRANSPORT), S(ENCAP_MODE_TUNNEL), #undef S }; const struct enum_names encap_mode_names = { ENCAP_MODE_TRANSPORT, ENCAP_MODE_TUNNEL, ARRAY_REF(encap_mode_name), .en_prefix = "ENCAP_MODE_", }; static const char *encap_mode_story_name[] = { #define S(E,V) [E-ENCAP_MODE_TRANSPORT] = V S(ENCAP_MODE_TRANSPORT, "transport"), S(ENCAP_MODE_TUNNEL, "tunnel"), #undef S }; const struct enum_names encap_mode_story = { ENCAP_MODE_TRANSPORT, ENCAP_MODE_TUNNEL, ARRAY_REF(encap_mode_story_name), .en_prefix = NULL, }; libreswan-5.2/lib/libswan/encap_proto_names.c000066400000000000000000000024171475767661000214420ustar00rootroot00000000000000/* encap proto, 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 "encap_proto.h" #include "lswcdefs.h" /* for ARRAY_REF */ #include "enum_names.h" static const char *encap_proto_name[] = { #define S(E) [E - ENCAP_PROTO_ESP] = #E S(ENCAP_PROTO_ESP), S(ENCAP_PROTO_AH), #undef S }; const struct enum_names encap_proto_names = { ENCAP_PROTO_ESP, ENCAP_PROTO_AH, ARRAY_REF(encap_proto_name), .en_prefix = "ENCAP_PROTO_", }; static const char *encap_proto_story_name[] = { #define S(E,V) [E - ENCAP_PROTO_ESP] = V S(ENCAP_PROTO_ESP, "esp"), S(ENCAP_PROTO_AH, "ah"), #undef S }; const struct enum_names encap_proto_story = { ENCAP_PROTO_ESP, ENCAP_PROTO_AH, ARRAY_REF(encap_proto_story_name), .en_prefix = NULL, }; libreswan-5.2/lib/libswan/encap_type_names.c000066400000000000000000000020151475767661000212520ustar00rootroot00000000000000/* encap type, 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 "encap_type.h" #include "lswcdefs.h" /* for ARRAY_REF() */ #include "enum_names.h" static const char *encap_type_name[] = { #define S(E) [E-ENCAP_TYPE_TRAP] = #E S(ENCAP_TYPE_TRAP), S(ENCAP_TYPE_IPSEC), S(ENCAP_TYPE_PASS), S(ENCAP_TYPE_DROP), #undef S }; const struct enum_names encap_type_names = { ENCAP_TYPE_TRAP, ENCAP_TYPE_DROP, ARRAY_REF(encap_type_name), .en_prefix = "ENCAP_TYPE_", }; libreswan-5.2/lib/libswan/end_names.c000066400000000000000000000021271475767661000176750ustar00rootroot00000000000000/* end, for libreswan * * Copyright (C) 2024 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include "end.h" #include "enum_names.h" #include "lswcdefs.h" /* for ARRAY_REF() */ static const char *end_name[] = { #define S(E) [E-LEFT_END] = #E S(LEFT_END), S(RIGHT_END), #undef S }; const struct enum_names end_names = { LEFT_END, RIGHT_END, ARRAY_REF(end_name), .en_prefix = NULL, }; static const char *end_story[] = { [LEFT_END] = "left", [RIGHT_END] = "right", }; const struct enum_names end_stories = { LEFT_END, RIGHT_END, ARRAY_REF(end_story), .en_prefix = NULL, }; libreswan-5.2/lib/libswan/enum_checklist.sh000077500000000000000000000046221475767661000211360ustar00rootroot00000000000000#!/bin/sh set -eu # enum name checklist, for libreswan # # Copyright (C) 2023-2024 Andrew Cagney # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. names=$1 ; shift list() { # The special comment /* #ifdef MACRO */, at the end of a # declaration is used to flag that the declaration should be # wrapped in #ifdef MACRO. Just the macro name is included. { sed -n \ -e "s/^extern ${names} \([a-z0-9_]*\);.* #ifdef \([A-Z0-9_]*\).*$/\1 \2/p" \ -e "s/^extern ${names} \([a-z0-9_]*\);.*$/\1/p" \ -e "s/^extern const struct ${names} \([a-z0-9_]*\);.* #ifdef \([A-Z0-9_]*\).*$/\1 \2/p" \ -e "s/^extern const struct ${names} \([a-z0-9_]*\);.*$/\1/p" \ "$@" } | { sort } } echo $(list "$@") 1>&2 cat <. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ EOF echo echo '#include "constants.h" /* for typedef ${names} */' echo '#include "enum_names.h"' echo grep -e "^extern ${names} " -e "^extern const struct ${names} " "$@" | \ cut -d: -f1 | \ cut -d/ -f4- | \ sort -u | \ while read h ; do echo '#include "'${h}'"' done echo echo "const struct ${names}_check ${names}_checklist[] = {" list "$@" | while read name ifdef ; do test -z "${ifdef}" || echo "#ifdef ${ifdef}" echo " { \"${name}\", &${name}, }," test -z "${ifdef}" || echo "#endif" done echo " { NULL, NULL, }" echo "};" libreswan-5.2/lib/libswan/enum_names.c000066400000000000000000000247331475767661000201020ustar00rootroot00000000000000/* * 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) { if (l < -1) { llog_passert(&global_logger, HERE, "%ld should be >= -1", l); } unsigned long e; /* * Advance L by 1 giving a starting candidate. */ if (l < 0) { e = 0; } else { e = l+1; } while (true) { /* * Find a range that puts an upper bound on E. E may * fall within the range, but could also fall short. */ const struct enum_names *b = NULL; for (const struct enum_names *p = en; p != NULL; p = p->en_next_range) { if (p->en_last - p->en_first + 1 != p->en_checklen) { llog_passert(&global_logger, HERE, "p->en_last(%lu) - p->en_first(%lu) + 1 == p->en_checklen(%zu)", p->en_last, p->en_first, p->en_checklen); } if (e > p->en_last) { continue; } if (e >= p->en_first) { b = p; break; } /* e < .en_first; save when closer */ if (b == NULL || b->en_first > p->en_first) { b = p; } } if (b == NULL) { return -1; } /* * If E isn't yet within the range, make it so. */ if (e < b->en_first) { e = b->en_first; } /* * Find the first valid name within the range; if this * fails, iterate round looking for a new range. */ while (e <= b->en_last) { if (b->en_names[e - b->en_first] != NULL) { return e; } 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; } } static const char *find_enum(const struct enum_names *en, unsigned long val, bool shorten) { const char *prefix = NULL; /* can be NULL */ const struct enum_names *range = enum_range(en, val, &prefix); /* can be NULL */ return enum_range_name(range, val, prefix, shorten); } bool enum_long(enum_names *ed, unsigned long val, enum_buf *b) { /* can be NULL; handled here */ b->buf = find_enum(ed, val, /*shorten?*/false); if (b->buf == NULL) { bad_name(val, b); return false; } return true; } bool enum_short(enum_names *ed, unsigned long val, enum_buf *b) { /* can be NULL; handled here */ b->buf = find_enum(ed, val, /*shorten?*/true); if (b->buf == NULL) { bad_name(val, b); return false; } return true; } const char *str_enum_long(enum_names *ed, unsigned long val, enum_buf *b) { enum_long(ed, val, b); return b->buf; } const char *str_enum_short(enum_names *ed, unsigned long val, enum_buf *b) { enum_short(ed, val, b); return b->buf; } size_t jam_enum_long(struct jambuf *buf, enum_names *en, unsigned long val) { const char *name = find_enum(en, val, /*shorten*/false); if (name != NULL) { return jam_string(buf, name); } return jam_bad(buf, en->en_prefix, val); } size_t jam_enum_short(struct jambuf *buf, enum_names *en, unsigned long val) { /* can be NULL; handled here */ const char *name = find_enum(en, val, /*shorten*/true); if (name != NULL) { return jam_string(buf, name); } return jam_bad(buf, en->en_prefix, val); } size_t jam_enum_human(struct jambuf *buf, enum_names *en, unsigned long val) { /* can be NULL; handled here */ const char *name = find_enum(en, val, /*shorten?*/true); if (name != NULL) { return jam_string_human(buf, name); } return jam_bad(buf, en->en_prefix, val); } /* * 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 */ static const struct enum_names *enum_enum_table(enum_enum_names *een, unsigned long table) { if (!(een->een_last - een->een_first + 1 == een->een_checklen)) { /* *_{last,first} are longs */ llog_passert(&global_logger, HERE, ".een_last=%lu - .een_first=%lu + 1 == .een_checklen=%zu", een->een_last, een->een_first, een->een_checklen); } if (een->een_first <= table && table <= een->een_last) { return een->een_enum_name[table - een->een_first]; } return NULL; } bool enum_enum_name(enum_enum_names *een, unsigned long table, unsigned long val, enum_buf *b) { enum_names *en = enum_enum_table(een, table); if (en == NULL) { snprintf(b->tmp, sizeof(b->tmp), "%lu.%lu", table, val); b->buf = b->tmp; return false; } return enum_name(en, val, b); } const char *str_enum_enum(enum_enum_names *een, unsigned long table, unsigned long val, enum_buf *b) { enum_enum_name(een, table, val, b); return b->buf; } 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->tmp, sizeof(b->tmp), "%lu.%lu", table, val); b->buf = b->tmp; 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(const struct enum_names_check *checklist) { /* check that enum_names are well-formed */ for (const struct enum_names_check *c = checklist; c->name != NULL && c->enum_names != NULL; c++) { /* * enum_name will check all linked enum_names if given * a value that isn't covered. -42 is probably not * covered. */ enum_buf b; enum_name(c->enum_names, -42UL, &b); } } void check_enum_enum_names(const struct enum_enum_names_check *checklist) { /* check that enum_enum_names are well-formed */ for (const struct enum_enum_names_check *c = checklist; c->name != NULL && c->enum_enum_names != NULL; c++) { /* check v2_transform_ID_enums, the only enum_enum_names */ enum_enum_table(c->enum_enum_names, -42UL); } } void init_enum_names(void) { check_enum_names(enum_names_checklist); check_enum_enum_names(enum_enum_names_checklist); } libreswan-5.2/lib/libswan/esp_info.c000066400000000000000000000103251475767661000175450ustar00rootroot00000000000000/* 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 "fips_mode.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_ikev1_esp_proposals[] = "AES_CBC" /*????*/ "," "AES_GCM_16_128" "," "AES_GCM_16_256" "," "3DES" ; static const struct ike_alg *default_ikev1_esp_integ[] = { #ifdef USE_SHA1 &ike_alg_integ_sha1.common, #endif #ifdef USE_SHA2 &ike_alg_integ_sha2_512.common, &ike_alg_integ_sha2_256.common, #endif NULL, }; static const struct proposal_defaults ikev1_esp_defaults = { .proposals[FIPS_MODE_OFF] = default_ikev1_esp_proposals, .proposals[FIPS_MODE_ON] = default_ikev1_esp_proposals, .integ = default_ikev1_esp_integ, }; /* * IKEv2: */ static const char default_fips_on_ikev2_esp_proposals[] = "AES_GCM_16_256" "," "AES_GCM_16_128" "," "AES_CBC_256" "," "AES_CBC_128" ; static const char default_fips_off_ikev2_esp_proposals[] = "AES_GCM_16_256" "," "AES_GCM_16_128" #ifdef USE_CHACHA "," "CHACHA20_POLY1305" /*non-FIPS*/ #endif "," "AES_CBC_256" "," "AES_CBC_128" ; static const struct ike_alg *default_ikev2_esp_integ[] = { #ifdef USE_SHA2 &ike_alg_integ_sha2_512.common, &ike_alg_integ_sha2_256.common, #endif NULL, }; static const struct proposal_defaults ikev2_esp_defaults = { .proposals[FIPS_MODE_ON] = default_fips_on_ikev2_esp_proposals, .proposals[FIPS_MODE_OFF] = default_fips_off_ikev2_esp_proposals, .integ = default_ikev2_esp_integ, }; /* * All together now ... */ static const struct proposal_protocol ikev1_esp_proposal_protocol = { .name = "ESP", .alg_id = IKEv1_IPSEC_ID, .defaults = &ikev1_esp_defaults, .proposal_ok = esp_proposal_ok, .encrypt = true, .integ = true, .dh = true, }; static const struct proposal_protocol ikev2_esp_proposal_protocol = { .name = "ESP", .alg_id = IKEv2_ALG_ID, .defaults = &ikev2_esp_defaults, .proposal_ok = esp_proposal_ok, .encrypt = true, .integ = true, .dh = true, }; static const struct proposal_protocol *esp_proposal_protocol[] = { [IKEv1] = &ikev1_esp_proposal_protocol, [IKEv2] = &ikev2_esp_proposal_protocol, }; /* * ??? 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[policy->version]); } libreswan-5.2/lib/libswan/fatal.c000066400000000000000000000032541475767661000170350ustar00rootroot00000000000000/* 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 "fatal.h" #include "constants.h" /* for enum pluto_exit_code */ #include "lswlog.h" /* for LOG_WIDTH et.al. */ void fatal(enum pluto_exit_code pluto_exit_code, const struct logger *logger, const char *fmt, ...) { struct logjam logjam; struct jambuf *buf = jambuf_from_logjam(&logjam, logger, pluto_exit_code, NULL/*where*/, FATAL_STREAM); { va_list ap; va_start(ap, fmt); jam_va_list(buf, fmt, ap); va_end(ap); } fatal_logjam_to_logger(&logjam); } void fatal_errno(enum pluto_exit_code pluto_exit_code, const struct logger *logger, int error, const char *fmt, ...) { struct logjam logjam; struct jambuf *buf = jambuf_from_logjam(&logjam, logger, pluto_exit_code, NULL/*where*/, FATAL_STREAM); { va_list ap; va_start(ap, fmt); jam_va_list(buf, fmt, ap); va_end(ap); jam_string(buf, ": "); jam_errno(buf, error); } fatal_logjam_to_logger(&logjam); } void fatal_logjam_to_logger(struct logjam *logjam) { logjam_to_logger(logjam); libreswan_exit(logjam->barf.pluto_exit_code); } libreswan-5.2/lib/libswan/fd.c000066400000000000000000000066261475767661000163450ustar00rootroot00000000000000/* 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" #include "lswlog.h" /* for pexpect() */ 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); } void fd_delref_where(struct fd **fdp, where_t where) { const struct logger *logger = &global_logger; struct fd *fd = delref_where(fdp, logger, where); if (fd != NULL) { pexpect(fd->magic == FD_MAGIC); if (close(fd->fd) != 0) { if (DBGP(DBG_BASE)) { llog_errno(DEBUG_STREAM, logger, errno, "freeref "PRI_FD" close() failed "PRI_WHERE": ", pri_fd(fd), pri_where(where)); } } else { ldbg(logger, "freeref "PRI_FD" "PRI_WHERE"", pri_fd(fd), pri_where(where)); } fd->magic = ~FD_MAGIC; pfree(fd); } } 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, 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-5.2/lib/libswan/fips_mode.c000066400000000000000000000047471475767661000177230ustar00rootroot00000000000000/* * 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 "fips_mode.h" #include "enum_names.h" static enum fips_mode fips_mode = FIPS_MODE_UNSET; /* * Only called by lsw_nss_setup(). */ enum fips_mode 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 > FIPS_MODE_UNSET) { return fips_mode; } /* * 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. */ fips_mode = (PK11_IsFIPS() ? FIPS_MODE_ON : FIPS_MODE_OFF); enum_buf eb; llog(RC_LOG, logger, "FIPS Mode: %s", str_enum_short(&fips_mode_names, fips_mode, &eb)); 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 * (is_fips_mode()) */ bool is_fips_mode(void) { pexpect(fips_mode != FIPS_MODE_UNSET); return fips_mode == FIPS_MODE_ON; } /* * used only for debugging with --impair-force-fips */ void set_fips_mode(enum fips_mode fips) { fips_mode = fips; } libreswan-5.2/lib/libswan/fips_mode_names.c000066400000000000000000000016611475767661000210760ustar00rootroot00000000000000/* fips_mode_names, for libreswan * * Copyright (C) 2024 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include "fips_mode.h" #include "enum_names.h" #include "lswcdefs.h" const char *fips_mode_name[] = { #define S(E) [E - FIPS_MODE_FLOOR] = #E S(FIPS_MODE_ON), S(FIPS_MODE_OFF), }; const struct enum_names fips_mode_names = { FIPS_MODE_FLOOR, FIPS_MODE_ROOF-1, ARRAY_REF(fips_mode_name), "FIPS_MODE_", NULL, }; libreswan-5.2/lib/libswan/global_logger.c000066400000000000000000000021231475767661000205370ustar00rootroot00000000000000/* 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" 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", .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-5.2/lib/libswan/goodmask.3.xml000066400000000000000000000063171475767661000202740ustar00rootroot00000000000000 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. AUTHOR Paul Wouters libreswan-5.2/lib/libswan/hunk.c000066400000000000000000000110011475767661000167000ustar00rootroot00000000000000/* 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 *raw_clone_as_string(const void *ptr, size_t maxlen, const char *name) { if (ptr == NULL) { return NULL; } /* Don't assume terminating NUL */ size_t len = strnlen(ptr, maxlen); /* include space for NUL */ char *out = alloc_things(char, len + 1, name); memcpy(out, ptr, len); /* explict; but redundant as done by alloc_things() */ out[len] = '\0'; 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 raw_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 raw_caseeq(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; } bool raw_heq(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; } const char *l = l_ptr; const char *r = r_ptr; for (unsigned i = 0; i < l_len; i++) { char lc = l[i]; char rc = r[i]; if (char_tolower(lc) == char_tolower(rc)) { continue; } const char *wild = "-_"; if (strchr(wild, lc) != NULL && strchr(wild, rc) != NULL) { continue; } return false; } return true; } void raw_hton(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 raw_ntoh(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) { /* i.e., went backwards */ return UINTMAX_MAX; } 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; } bool raw_starteq(const void *ptr, size_t len, const void *eat_ptr, size_t eat_len) { if (ptr == NULL || eat_ptr == NULL) { return false; } if (len < eat_len) { return false; } if (strncmp(ptr, eat_ptr, eat_len) != 0) { return false; } return true; } bool raw_casestarteq(const void *ptr, size_t len, const void *eat_ptr, size_t eat_len) { if (ptr == NULL || eat_ptr == NULL) { return false; } if (len < eat_len) { return false; } if (strncasecmp(ptr, eat_ptr, eat_len) != 0) { return false; } return true; } libreswan-5.2/lib/libswan/id.c000066400000000000000000000262021475767661000163400ustar00rootroot00000000000000/* * 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" #include "lswnss.h" /* for clone_secitem_as_chunk() */ 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 (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) { /* * 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 (strchr(src, '@') == NULL) { /* * i.e., does not contain an @ at all * * !!! 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 (eat(src, "@#")) { /* * @# - convert from hex to bin as ID */ 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 = ASN1(name), .scratch = name.ptr, }; return NULL; } if (eat(src, "@~")) { /* * @~ - convert from hex to bin as DN */ 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 = ASN1(name), .scratch = name.ptr, }; return NULL; } if (eat(src, "@[")) { /* * @[ or @[] - this is documented */ 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 (eat(src, "@")) { /* * @ - reduced to */ chunk_t name = clone_bytes_as_chunk(src, strlen(src), "fqdn id"); *id = (struct id) { .kind = ID_FQDN, /* discard @ */ .name = ASN1(name), .scratch = name.ptr, }; return NULL; } /* * @ unchanged 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; } size_t jam_id_bytes(struct jambuf *buf, const struct id *id, jam_bytes_fn *jam_bytes) { if (id == NULL) { return jam_string(buf, ""); } size_t s = 0; switch (id->kind) { case ID_FROMCERT: s += jam_string(buf, "%fromcert"); break; case ID_NONE: s += jam_string(buf, "(none)"); break; case ID_NULL: s += jam_string(buf, "ID_NULL"); break; case ID_IPV4_ADDR: case ID_IPV6_ADDR: if (address_is_specified(id->ip_addr)) { s += jam_address(buf, &id->ip_addr); } else { s += jam_string(buf, "%any"); } break; case ID_FQDN: s += jam_string(buf, "@"); s += jam_bytes(buf, id->name.ptr, id->name.len); break; case ID_USER_FQDN: s += jam_bytes(buf, id->name.ptr, id->name.len); break; case ID_DER_ASN1_DN: s += jam_dn(buf, id->name, jam_bytes); break; case ID_KEY_ID: s += jam_string(buf, "@#0x"); s += jam_hex_bytes(buf, id->name.ptr, id->name.len); break; default: s += jam(buf, "unknown id kind %d", id->kind); break; } return s; } 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; } size_t jam_id(struct jambuf *buf, const struct id *id) { return jam_id_bytes(buf, id, jam_raw_bytes); /* see above */ } const char *str_id(const struct id *id, id_buf *buf) { struct jambuf b = ARRAY_AS_JAMBUF(buf->buf); jam_id(&b, id); /* see above */ return buf->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 struct id *a, const struct id *b, int *wildcards_out, struct verbose verbose) { 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(a->name, b->name, &wildcards, verbose); } else if (same_id(a, b)) { wildcards = 0; match = true; } else { wildcards = MAX_WILDCARDS; match = false; } id_buf buf; vdbg("match_id a=%s", str_id(a, &buf)); vdbg(" b=%s", str_id(b, &buf)); vdbg(" result %s wildcards=%d", 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; } /* * choose either subject DN or a subjectAltName as connection end ID */ struct id id_from_cert(const struct cert *cert) { chunk_t name = clone_secitem_as_chunk(cert->nss_cert->derSubject, "cert id"); struct id id = { .name = ASN1(name), .scratch = name.ptr, .kind = ID_DER_ASN1_DN, }; return id; } libreswan-5.2/lib/libswan/ike_alg.c000066400000000000000000001151621475767661000173430ustar00rootroot00000000000000/* * 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 * Copyright (C) 2020 Nupur Agrawal * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY 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 "fips_mode.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_IPSEC_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; } bool ike_alg_enum_matched(const struct ike_alg_type *type, shunk_t name) { passert(type != NULL); for (enum ike_alg_key key = IKE_ALG_KEY_FLOOR; key < IKE_ALG_KEY_ROOF; key++) { if (type->enum_names[key] != NULL && enum_match(type->enum_names[key], name) >= 0) { return true; } } return false; } 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, enum_buf *b, lset_t debug) { FOR_EACH_IKE_ALGP(type, algp) { const struct ike_alg *alg = *algp; if (alg->id[key] == id) { /* Note: .enum_name[key] can be NULL so don't * bother with .enum_name[] lookup. */ ldbgf(debug, &global_logger, "%s %s algorithm %s id: %u found by %s()", ike_alg_key_name(key), type->name, alg->fqn, id, __func__); /* must save name */ b->buf = alg->fqn; return alg; } } /* * Even though the lookup failed, b->buf must still be set. * * When .enum_names[] is NULL then the enum_name() call will * set it to the numeric value. */ bool known = enum_name(type->enum_names[key], id, b); ldbgf(debug, &global_logger, "%s %s id: %u, not found by %s(); %s %s", ike_alg_key_name(key), type->name, id, __func__, b->buf, (type->enum_names[key] == NULL ? "no .enum_names[]" : known ? "known by .enum_names[]" : "unknown by .enum_names[]")); return NULL; } const struct ike_alg *ike_alg_by_sadb_alg_id(const struct ike_alg_type *algorithms, unsigned id) { enum_buf b; return lookup_by_id(algorithms, SADB_ALG_ID, id, &b, DBG_CRYPT); } static const struct ike_alg *ikev1_oakley_lookup(const struct ike_alg_type *algorithms, unsigned id, enum_buf *b) { const struct ike_alg *alg = lookup_by_id(algorithms, IKEv1_OAKLEY_ID, id, b, DBG_CRYPT); if (alg == NULL || !ike_alg_is_ike(alg)) { return NULL; } return alg; } const struct encrypt_desc *ikev1_ike_encrypt_desc(enum ikev1_encr_attribute id, enum_buf *b) { return encrypt_desc(ikev1_oakley_lookup(&ike_alg_encrypt, id, b)); } const struct prf_desc *ikev1_ike_prf_desc(enum ikev1_auth_attribute id, enum_buf *b) { return prf_desc(ikev1_oakley_lookup(&ike_alg_prf, id, b)); } const struct dh_desc *ikev1_ike_dh_desc(enum ike_trans_type_dh id, enum_buf *b) { return dh_desc(ikev1_oakley_lookup(&ike_alg_dh, id, b)); } const struct ipcomp_desc *ikev1_ike_ipcomp_desc(enum ipsec_ipcomp_algo id, enum_buf *b) { return ipcomp_desc(ikev1_oakley_lookup(&ike_alg_ipcomp, id, b)); } const struct encrypt_desc *ikev1_kernel_encrypt_desc(enum ikev1_esp_transform id, enum_buf *b) { return encrypt_desc(lookup_by_id(&ike_alg_encrypt, IKEv1_IPSEC_ID, id, b, DBG_CRYPT)); } const struct integ_desc *ikev1_kernel_integ_desc(enum ikev1_auth_attribute id, enum_buf *b) { return integ_desc(lookup_by_id(&ike_alg_integ, IKEv1_IPSEC_ID, id, b, DBG_CRYPT)); } const struct ipcomp_desc *ikev1_kernel_ipcomp_desc(enum ipsec_ipcomp_algo id, enum_buf *b) { return ipcomp_desc(lookup_by_id(&ike_alg_ipcomp, IKEv1_IPSEC_ID, id, b, DBG_CRYPT)); } static const struct ike_alg *ikev2_lookup(const struct ike_alg_type *algorithms, int id, struct enum_buf *b) { return lookup_by_id(algorithms, IKEv2_ALG_ID, id, b, DBG_CRYPT); } const struct encrypt_desc *ikev2_encrypt_desc(enum ikev2_trans_type_encr id, struct enum_buf *b) { return encrypt_desc(ikev2_lookup(&ike_alg_encrypt, id, b)); } const struct hash_desc *ikev2_hash_desc(enum ikev2_hash_algorithm id, struct enum_buf *b) { return hash_desc(ikev2_lookup(&ike_alg_hash, id, b)); } const struct prf_desc *ikev2_prf_desc(enum ikev2_trans_type_prf id, struct enum_buf *b) { return prf_desc(ikev2_lookup(&ike_alg_prf, id, b)); } const struct integ_desc *ikev2_integ_desc(enum ikev2_trans_type_integ id, struct enum_buf *b) { return integ_desc(ikev2_lookup(&ike_alg_integ, id, b)); } const struct dh_desc *ikev2_dh_desc(enum ike_trans_type_dh id, struct enum_buf *b) { return dh_desc(ikev2_lookup(&ike_alg_dh, id, b)); } const struct ipcomp_desc *ikev2_ipcomp_desc(enum ipsec_ipcomp_algo id, struct enum_buf *b) { return ipcomp_desc(ikev2_lookup(&ike_alg_ipcomp, id, b)); } const struct encrypt_desc *encrypt_desc_by_sadb_ealg_id(unsigned id) { enum_buf b; return encrypt_desc(lookup_by_id(&ike_alg_encrypt, SADB_ALG_ID, id, &b, DBG_CRYPT)); } const struct integ_desc *integ_desc_by_sadb_aalg_id(unsigned id) { enum_buf b; return integ_desc(lookup_by_id(&ike_alg_integ, SADB_ALG_ID, id, &b, DBG_CRYPT)); } const struct ipcomp_desc *ipcomp_desc_by_sadb_calg_id(unsigned id) { enum_buf b; return ipcomp_desc(lookup_by_id(&ike_alg_ipcomp, SADB_ALG_ID, id, &b, 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)); /* Using NSS implies mechanism */ pexpect_ike_alg(logger, alg, (prf->prf_mac_ops == &ike_alg_prf_mac_nss_ops) /*implies*/<= (prf->nss.mechanism > 0)) 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_resume_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); pexpect_ike_alg(logger, alg, prf->prf_ikev2_ops->psk_resume != 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_IPSEC_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_IPSEC_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_IPSEC_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_IPSEC_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"); /* * 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->cipher_check != NULL); pexpect_ike_alg(logger, alg, ((encrypt->encrypt_ops->cipher_op_context_create != NULL) == (encrypt->encrypt_ops->cipher_op_context_destroy != NULL))); pexpect_ike_alg(logger, alg, ((encrypt->encrypt_ops->cipher_op_normal == NULL) != (encrypt->encrypt_ops->cipher_op_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->cipher_op_aead == NULL || encrypt->aead_tag_size > 0)); pexpect_ike_alg(logger, alg, (encrypt->encrypt_ops->cipher_op_normal == 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_IPSEC_ID] == IKEv1_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); if (encrypt->encrypt_ops == NULL) { return false; } if (encrypt->encrypt_ops == &ike_alg_encrypt_null_ops) { return impair.allow_null_none; } return true; } 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_IPSEC_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_IPSEC_ID] == dh->group : dh->dh_ops == &ike_alg_dh_nss_ecp_ops ? dh->common.id[IKEv1_IPSEC_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_IPSEC_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_IPSEC_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); } enum_buf enum_name; bool ok = enum_name_short(enum_names, id, &enum_name); ldbgf(DBG_CRYPT, logger, "%s id: %d enum name: %s", what, id, enum_name.buf); pexpect_ike_alg_has_name(logger, HERE, alg, (ok ? enum_name.buf : NULL), "enum table name"); } else { ldbgf(DBG_CRYPT, logger, "%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); ldbgf(DBG_CRYPT, logger, "%s algorithm assertion checks", type->name); FOR_EACH_IKE_ALGP(type, algp) { const struct ike_alg *alg = *algp; ldbgf(DBG_CRYPT, logger, "%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_IPSEC_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; } enum_buf b; pexpect_ike_alg_key(logger, alg, key, lookup_by_id(&scratch, key, id, &b, 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_IPSEC_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_IPSEC_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_IPSEC_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_IPSEC_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:", is_fips_mode() ? "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 = is_fips_mode(); /* * 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-5.2/lib/libswan/ike_alg_3des.c000066400000000000000000000033121475767661000202520ustar00rootroot00000000000000/* 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_IPSEC_ID] = IKEv1_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_IN_BYTE, .key_bit_lengths = { DES_CBC_BLOCK_SIZE * 3 * BITS_IN_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-5.2/lib/libswan/ike_alg_aes.c000066400000000000000000000303701475767661000201700ustar00rootroot00000000000000/* * 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_IPSEC_ID] = IKEv1_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_IPSEC_ID] = IKEv1_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_IPSEC_ID] = IKEv1_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, .key_gen = CKM_AES_KEY_GEN, }, .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_aead_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_IPSEC_ID] = IKEv1_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, .key_gen = CKM_AES_KEY_GEN, }, .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_aead_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_IPSEC_ID] = IKEv1_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, .key_gen = CKM_AES_KEY_GEN, }, .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_aead_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_IPSEC_ID] = IKEv1_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_IPSEC_ID] = IKEv1_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_IPSEC_ID] = IKEv1_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_IPSEC_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_IPSEC_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 = IKEv1_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_IPSEC_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 = IKEv1_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_IPSEC_ID] = IKEv1_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-5.2/lib/libswan/ike_alg_camellia.c000066400000000000000000000057651475767661000212010ustar00rootroot00000000000000/* * 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_IPSEC_ID] = IKEv1_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_IPSEC_ID] = IKEv1_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-5.2/lib/libswan/ike_alg_desc.c000066400000000000000000000033171475767661000203370ustar00rootroot00000000000000/* * 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-5.2/lib/libswan/ike_alg_dh.c000066400000000000000000000172161475767661000200170ustar00rootroot00000000000000/* * 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_IPSEC_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_IPSEC_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_IPSEC_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_IPSEC_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_IPSEC_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_IPSEC_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_IPSEC_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_IPSEC_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_IPSEC_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_IPSEC_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_IPSEC_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_IPSEC_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_IPSEC_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_IPSEC_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-5.2/lib/libswan/ike_alg_dh_nss_ecp_ops.c000066400000000000000000000157051475767661000224130ustar00rootroot00000000000000/* * 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. */ ldbgf(DBG_CRYPT, logger, "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); ldbg(logger, "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"); } ldbg_alloc(logger, "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); symkey_delref(logger, "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-5.2/lib/libswan/ike_alg_dh_nss_modp_ops.c000066400000000000000000000077601475767661000226050ustar00rootroot00000000000000/* * 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) { ldbgf(DBG_CRYPT, logger, "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) { ldbgf(DBG_CRYPT, logger, "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)) { LDBG_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-5.2/lib/libswan/ike_alg_encrypt_cbc_test_vectors.c000066400000000000000000000157631475767661000245300ustar00rootroot00000000000000/* * 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 "crypt_cipher.h" #include "fips_mode.h" #include "pk11pub.h" #include "crypt_symkey.h" #include "crypt_mac.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, enum cipher_op op, 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 *opstr = str_cipher_op(op); bool ok = true; struct crypt_mac iv = decode_to_mac("IV: ", encoded_iv, logger, HERE); /* * 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: ", (op == ENCRYPT ? output : op == DECRYPT ? input : NULL), logger, HERE); chunk_t tmp = decode_to_chunk(input_name, input, logger, HERE); chunk_t expected = decode_to_chunk(output_name, output, logger, HERE); /* do_crypt modifies the data and IV in place. */ cipher_ikev1(encrypt_desc, op, tmp, &iv, sym_key, logger); if (!verify_hunk(description, opstr, expected, tmp, logger, HERE)) { ok = false; } if (!verify_bytes(description, "updated CBC IV", iv.ptr, iv.len, expected_iv.ptr + expected_iv.len - iv.len, iv.len, logger, HERE)) { ok = false; } 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, HERE); 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. */ symkey_delref(logger, "sym_key", &sym_key); ldbg(logger, "%s() %s: %s", __func__, 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-5.2/lib/libswan/ike_alg_encrypt_chacha20_poly1305.c000066400000000000000000000034121475767661000241060ustar00rootroot00000000000000/* 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" #include "lsw-pfkeyv2.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_IPSEC_ID] = -1, [IKEv2_ALG_ID] = IKEv2_ENCR_CHACHA20_POLY1305, #ifdef SADB_X_EALG_CHACHA20POLY1305 [SADB_ALG_ID] = SADB_X_EALG_CHACHA20POLY1305, #endif }, }, .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-5.2/lib/libswan/ike_alg_encrypt_ctr_test_vectors.c000066400000000000000000000200451475767661000245560ustar00rootroot00000000000000/* * 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 "crypt_cipher.h" #include "fips_mode.h" #include "pk11pub.h" #include "crypt_symkey.h" #include "crypt_mac.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, enum cipher_op op, 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 *opstr = str_cipher_op(op); bool ok = true; struct crypt_mac cb = decode_to_mac("input counter-block: ", encoded_cb, logger, HERE); chunk_t tmp = decode_to_chunk(input_name, input, logger, HERE); chunk_t expected_output = decode_to_chunk(output_name, output, logger, HERE); chunk_t expected_cb = decode_to_chunk("expected counter-block: ", output_cb, logger, HERE); /* do_crypt modifies the data and IV in place. */ cipher_ikev1(encrypt_desc, op, tmp, &cb, sym_key, logger); if (!verify_hunk(description, opstr, expected_output, tmp, logger, HERE)) { ok = false; } if (!verify_hunk(description, "counter-block", expected_cb, cb, logger, HERE)) { ok = false; } 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, HERE); 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. */ symkey_delref(logger, "sym_key", &sym_key); ldbg(logger, "%s() %s %s", __func__, 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-5.2/lib/libswan/ike_alg_encrypt_gcm_test_vectors.c000066400000000000000000000132741475767661000245420ustar00rootroot00000000000000/* * 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 "fips_mode.h" #include "ike_alg.h" #include "test_buffer.h" #include "ike_alg_test_gcm.h" #include "crypt_cipher.h" #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 = "0x95bcde70c094f04e3dd8259cafd88ce8", .salted_iv = "0x12cf097ad22380432ff40a5c", .ciphertext = "0x8a023ba477f5b809bddcda8f55e09064d6d88aaec99c1e141212ea5b08503660", .aad = "0xc783a0cca10a8d9fb8d27d69659463f2", .tag = "0x562f500dae635d60a769b466e15acd1e", .plaintext = "0x32f51e837a9748838925066d69e87180f34a6437e6b396e5643b34cb2ee4f7b1", }, { .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, HERE); chunk_t salted_iv = decode_to_chunk("salted IV", test->salted_iv, logger, HERE); 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, logger, HERE); chunk_t plaintext = decode_to_chunk("plaintext", test->plaintext, logger, HERE); chunk_t ciphertext = decode_to_chunk("ciphertext", test->ciphertext, logger, HERE); passert(plaintext.len == ciphertext.len); size_t len = plaintext.len; chunk_t tag = decode_to_chunk("tag", test->tag, logger, HERE); 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(CIPHER_OP, FROM, TO) \ { \ memcpy(text_and_tag.ptr, FROM.ptr, FROM.len); \ text_and_tag.len = len + tag.len; \ if (LDBGP(DBG_CRYPT, logger)) { \ LDBG_log(logger, "%s() %s: aad-size=%zd salt-size=%zd wire-IV-size=%zd text-size=%zd tag-size=%zd text+tag in:", \ __func__, #CIPHER_OP, aad.len, salt.len, wire_iv.len, len, tag.len); \ LDBG_hunk(logger, text_and_tag); \ } \ if (!cipher_aead(encrypt_desc, CIPHER_OP, USE_WIRE_IV, \ HUNK_AS_SHUNK(salt), \ wire_iv, \ HUNK_AS_SHUNK(aad), \ text_and_tag, \ plaintext.len, tag.len, \ sym_key, \ logger) || \ !verify_bytes(test->description, "output ciphertext", \ TO.ptr, TO.len, \ text_and_tag.ptr, TO.len, \ logger, HERE) || \ !verify_bytes(test->description, "TAG", tag.ptr, tag.len, \ text_and_tag.ptr + len, tag.len, \ logger, HERE)) \ ok = false; \ if (LDBGP(DBG_CRYPT, logger)) { \ LDBG_log(logger, "%s() text+tag out:", __func__); \ LDBG_hunk(logger, text_and_tag); \ } \ } /* test decryption */ memcpy(text_and_tag.ptr + len, tag.ptr, tag.len); try(DECRYPT, ciphertext, plaintext); /* test encryption */ memset(text_and_tag.ptr + len, '\0', tag.len); try(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. */ symkey_delref(logger, "sym_key", &sym_key); ldbg(logger, "%s() %s", __func__, (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-5.2/lib/libswan/ike_alg_encrypt_nss_aead_ops.c000066400000000000000000000126501475767661000236230ustar00rootroot00000000000000/* NSS GCM for libreswan * * Copyright (C) 2014,2016,2018,2024 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY 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 "crypt_cipher.h" #include "ike_alg_encrypt_ops.h" #include "rnd.h" #include "crypt_symkey.h" struct cipher_op_context { PK11Context *context; chunk_t random_iv; unsigned long count; }; static struct cipher_op_context *cipher_op_context_create_aead_nss(const struct encrypt_desc *cipher, enum cipher_op op, enum cipher_iv_source iv_source UNUSED, PK11SymKey *symkey, shunk_t salt UNUSED, struct logger *logger) { CK_ATTRIBUTE_TYPE mode = (op == ENCRYPT ? CKA_ENCRYPT : op == DECRYPT ? CKA_DECRYPT : pexpect(0)); SECItem dummy = {0}; PK11Context *context = PK11_CreateContextBySymKey(cipher->nss.mechanism, CKA_NSS_MESSAGE|mode, symkey, &dummy); if (context == NULL) { enum_buf ckm; passert_nss_error(logger, HERE, "%s: PKCS11_CreateContextBySymKey(%s,%s) failed", cipher->common.fqn, str_cipher_op(op), str_nss_ckm(cipher->nss.mechanism, &ckm)); } struct cipher_op_context *aead = alloc_thing(struct cipher_op_context, __func__); aead->context = context; aead->random_iv = alloc_rnd_chunk(cipher->wire_iv_size, "Random-IV"); aead->count = 0; return aead; } static bool cipher_op_aead_nss(const struct encrypt_desc *cipher, struct cipher_op_context *aead, enum cipher_op op UNUSED, enum cipher_iv_source iv_source, PK11SymKey *symkey, shunk_t salt, chunk_t wire_iv, shunk_t aad, chunk_t text_and_tag, size_t text_len, size_t tag_len, struct logger *logger) { /* must be contigious */ PASSERT(logger, text_len + tag_len == text_and_tag.len); CK_GENERATOR_FUNCTION generator; chunk_t iv; switch (iv_source) { case USE_WIRE_IV: /* * Presumably the IV has come from the peer. */ generator = CKG_NO_GENERATE; iv = clone_hunk_hunk(salt, wire_iv, "IV"); break; case FILL_WIRE_IV: /* * NSS will scribble on this with real IV; need to * copy it back. */ generator = CKG_GENERATE_COUNTER_XOR; iv = clone_hunk_hunk(salt, aead->random_iv, "IV"); break; case USE_IKEv1_IV: /* makes no sense */ default: bad_case(iv_source); } /* Output buffer for transformed data. */ uint8_t *out_ptr = PR_Malloc(text_and_tag.len); /* XXX: use normal malloc? */ int out_len = 0; SECStatus rv = PK11_AEADOp(aead->context, generator, /*fixedbits*/cipher->salt_size * 8, /*nss-scribbles-on-this*/iv.ptr, iv.len, aad.ptr, aad.len, out_ptr, &out_len, /*maxout*/text_and_tag.len, text_and_tag.ptr + text_len, tag_len, text_and_tag.ptr, text_len); bool ok; if (rv != SECSuccess) { llog_nss_error(RC_LOG, logger, "AEAD encryption using %s_%u and PK11_AEADOp() failed", cipher->common.fqn, PK11_GetKeyLength(symkey) * BITS_IN_BYTE); ok = false; } else if ((unsigned)out_len != text_len) { /* should this be a pexpect fail? */ llog_nss_error(RC_LOG, logger, "AEAD encryption using %s_%u and PK11_AEADOp() failed (output length of %u not the expected %zd)", cipher->common.fqn, PK11_GetKeyLength(symkey) * BITS_IN_BYTE, out_len, text_and_tag.len); ok = false; } else { ldbg(logger, "AEAD encryption using %s_%u and PK11_AEADOp() succeded returning %d bytes", cipher->common.fqn, PK11_GetKeyLength(symkey) * BITS_IN_BYTE, out_len); ok = true; } /* Copy updated text back. */ memcpy(text_and_tag.ptr, out_ptr, out_len); PR_Free(out_ptr); if (iv_source == FILL_WIRE_IV) { /* * Cut out and then copy back the generated IV. * * The First time this op is used the .random_iv is * returned, from then on .random_op^count is used. */ chunk_t out_iv = hunk_slice(iv, salt.len, iv.len); PASSERT(logger, out_iv.len == aead->random_iv.len); hunk_cpy(wire_iv, out_iv); } aead->count++; free_chunk_content(&iv); return ok; } static void cipher_op_context_destroy_aead_nss(struct cipher_op_context **aead, struct logger *logger) { PK11_Finalize((*aead)->context); PK11_DestroyContext((*aead)->context, PR_TRUE); free_chunk_content(&(*aead)->random_iv); ldbg(logger, "destroyed"); pfreeany(*aead); } static void cipher_check_aead_nss(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)", .cipher_check = cipher_check_aead_nss, .cipher_op_context_create = cipher_op_context_create_aead_nss, .cipher_op_aead = cipher_op_aead_nss, .cipher_op_context_destroy = cipher_op_context_destroy_aead_nss, }; libreswan-5.2/lib/libswan/ike_alg_encrypt_nss_cbc_ops.c000066400000000000000000000116151475767661000234600ustar00rootroot00000000000000/* * 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 "crypt_cipher.h" #include "lswnss.h" /* for llog_nss_error() */ #include "rnd.h" static void cipher_op_cbc_nss(const struct encrypt_desc *cipher, struct cipher_op_context *context, enum cipher_op op, enum cipher_iv_source iv_source, PK11SymKey *symkey, shunk_t salt, chunk_t wire_iv, chunk_t text, struct crypt_mac *ikev1_iv, struct logger *logger) { ldbgf(DBG_CRYPT, logger, "NSS ike_alg_nss_cbc: %s - enter %p", cipher->common.fqn, context); PEXPECT(logger, salt.len == 0); /* CBC has no salt */ PEXPECT(logger, wire_iv.len == cipher->enc_blocksize); switch (iv_source) { case USE_WIRE_IV: PASSERT(logger, ikev1_iv == NULL); ldbgf(DBG_CRYPT, logger, "using existing wire IV"); break; case FILL_WIRE_IV: /* * AES CBC Must always generate the full IV. */ PASSERT(logger, ikev1_iv == NULL); ldbgf(DBG_CRYPT, logger, "generating wire IV"); fill_rnd_chunk(wire_iv); break; case USE_IKEv1_IV: PASSERT(logger, ikev1_iv != NULL); PEXPECT(logger, ikev1_iv->len == cipher->enc_blocksize); ldbgf(DBG_CRYPT, logger, "using IKEv1 IV"); break; } SECItem ivitem = { .type = siBuffer, .data = wire_iv.ptr, .len = wire_iv.len, }; SECItem *secparam = PK11_ParamFromIV(cipher->nss.mechanism, &ivitem); if (secparam == NULL) { llog_passert(logger, HERE, "%s - Failure to set up PKCS11 param (err %d)", cipher->common.fqn, PR_GetError()); } PK11Context *enccontext; enccontext = PK11_CreateContextBySymKey(cipher->nss.mechanism, (op == ENCRYPT ? CKA_ENCRYPT : op == DECRYPT ? CKA_DECRYPT : pexpect(0)), symkey, secparam); if (enccontext == NULL) { passert_nss_error(logger, HERE, "%s: PKCS11 context creation failure", cipher->common.fqn); } /* Output buffer for transformed data. */ uint8_t *out_ptr = PR_Malloc(text.len); int out_len = 0; /* not size_t; ulgh */ SECStatus rv = PK11_CipherOp(enccontext, out_ptr, &out_len, text.len, text.ptr, text.len); if (rv != SECSuccess) { passert_nss_error(logger, HERE, "%s: PKCS11 operation failure", cipher->common.fqn); } PK11_DestroyContext(enccontext, PR_TRUE); if (iv_source == USE_IKEv1_IV) { /* * Update IKEv1's IV ready for the next call to this * function. * * The next IV is always the last block of the * encrypted message. Hence ENCRYPT gets it from the * output; and decrypt gets it from the INPUT. * * ... and hence this needs to happen before the input * is scribbled on by the memcpy below. */ uint8_t *new_iv; switch (op) { case ENCRYPT: /* * The IV for the next encryption call is the last * block of encrypted OUTPUT data. */ new_iv = out_ptr + out_len - cipher->enc_blocksize; break; case DECRYPT: /* * The IV for the next decryption call is the last * block of the encrypted INPUT data. */ new_iv = text.ptr + text.len - cipher->enc_blocksize; break; default: bad_case(op); } PEXPECT(logger, ikev1_iv->len == cipher->enc_blocksize); memcpy(ikev1_iv->ptr, new_iv, cipher->enc_blocksize); } /* * Finally, copy the transformed data back to the buffer. Do * this after extracting the IV. * * Note: this needs to happen after the IKEv1 IV is saved (so * that the old final block is still available). */ memcpy(text.ptr, out_ptr, text.len); PR_Free(out_ptr); if (secparam != NULL) SECITEM_FreeItem(secparam, PR_TRUE); ldbgf(DBG_CRYPT, logger, "NSS ike_alg_nss_cbc: %s - exit", cipher->common.fqn); } static void cipher_check_cbc_nss(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)", .cipher_check = cipher_check_cbc_nss, .cipher_op_normal = cipher_op_cbc_nss, }; libreswan-5.2/lib/libswan/ike_alg_encrypt_nss_ctr_ops.c000066400000000000000000000147651475767661000235320ustar00rootroot00000000000000/* * 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" #include "crypt_cipher.h" #include "rnd.h" #include "hunk.h" struct cipher_op_context { uint64_t v2_wire_iv; uint64_t v2_wire_count; }; static struct cipher_op_context *cipher_op_context_create_ctr_nss(const struct encrypt_desc *cipher UNUSED, enum cipher_op op UNUSED, enum cipher_iv_source iv_source, PK11SymKey *symkey UNUSED, shunk_t salt UNUSED, struct logger *logger) { struct cipher_op_context *context = alloc_thing(struct cipher_op_context, __func__); switch (iv_source) { case FILL_WIRE_IV: context->v2_wire_iv = get_rnd_uintmax(); context->v2_wire_count = 0; ldbgf(DBG_CRYPT, logger, "%s() initial wire_iv %"PRIx64" count %"PRIu64, __func__, context->v2_wire_iv, context->v2_wire_count); break; case USE_WIRE_IV: case USE_IKEv1_IV: break; } return context; } static void cipher_op_ctr_nss(const struct encrypt_desc *cipher, struct cipher_op_context *context, enum cipher_op op, enum cipher_iv_source iv_source, PK11SymKey *sym_key, shunk_t salt, chunk_t wire_iv, chunk_t text, struct crypt_mac *ikev1_iv/*possbly-NULL*/, struct logger *logger) { ldbgf(DBG_CRYPT, logger, "%s() enter %s %p %s wire_iv %"PRIx64" count %"PRIu64, __func__, cipher->common.fqn, context, str_cipher_iv_source(iv_source), context->v2_wire_iv, context->v2_wire_count); passert(sym_key); if (sym_key == NULL) { llog_passert(logger, HERE, "%s", "NSS derived enc key in NULL"); } CK_AES_CTR_PARAMS ctr_params = { .ulCounterBits = sizeof(uint32_t) * 8, /* Per RFC 3686 */ .cb = {0}, /* be explicit */ }; switch (iv_source) { case USE_WIRE_IV: PASSERT(logger, ikev1_iv == NULL); PASSERT(logger, salt.len + wire_iv.len + ctr_params.ulCounterBits / 8 == sizeof(ctr_params.cb)); memcpy(ctr_params.cb, salt.ptr, salt.len); memcpy(ctr_params.cb + salt.len, wire_iv.ptr, wire_iv.len); ctr_params.cb[sizeof(ctr_params.cb) - 1] = 1; break; case FILL_WIRE_IV: PASSERT(logger, ikev1_iv == NULL); PASSERT(logger, salt.len + wire_iv.len + ctr_params.ulCounterBits / 8 == sizeof(ctr_params.cb)); PASSERT(logger, wire_iv.len > 0); PASSERT(logger, context->v2_wire_iv != 0); PASSERT(logger, sizeof(context->v2_wire_iv) >= wire_iv.len); /* like AEAD, use RND ^ COUNT++ */ hton_chunk(context->v2_wire_iv ^ context->v2_wire_count, wire_iv); context->v2_wire_count++; memcpy(ctr_params.cb, salt.ptr, salt.len); memcpy(ctr_params.cb + salt.len, wire_iv.ptr, wire_iv.len); ctr_params.cb[sizeof(ctr_params.cb) - 1] = 1; break; case USE_IKEv1_IV: PASSERT(logger, ikev1_iv != NULL); PASSERT(logger, ikev1_iv->len == sizeof(ctr_params.cb)); memcpy(ctr_params.cb, ikev1_iv->ptr, sizeof(ctr_params.cb)); break; } LDBGP_JAMBUF(DBG_CRYPT, logger, buf) { jam(buf, "ctr_param: count %lu iv ", ctr_params.ulCounterBits); jam_hex_bytes(buf, ctr_params.cb, sizeof(ctr_params.cb)); } SECItem param; param.type = siBuffer; param.data = (void*)&ctr_params; param.len = sizeof(ctr_params); /* Output buffer for transformed data. */ uint8_t *out_ptr = PR_Malloc(text.len); unsigned int out_len = 0; /* not size_t; ulgh! */ switch (op) { case ENCRYPT: { SECStatus rv = PK11_Encrypt(sym_key, CKM_AES_CTR, ¶m, out_ptr, &out_len, text.len, text.ptr, text.len); if (rv != SECSuccess) { passert_nss_error(logger, HERE, "PK11_Encrypt failure"); } break; } case DECRYPT: { SECStatus rv = PK11_Decrypt(sym_key, CKM_AES_CTR, ¶m, out_ptr, &out_len, text.len, text.ptr, text.len); if (rv != SECSuccess) { passert_nss_error(logger, HERE, "PK11_Decrypt failure"); } break; } default: bad_case(op); } memcpy(text.ptr, out_ptr, text.len); PR_Free(out_ptr); if (iv_source == USE_IKEv1_IV) { /* * 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*)(ikev1_iv->ptr + AES_BLOCK_SIZE - sizeof(uint32_t)); uint32_t old_counter = ntohl(*counter); size_t increment = (text.len + AES_BLOCK_SIZE - 1) / AES_BLOCK_SIZE; uint32_t new_counter = old_counter + increment; ldbgf(DBG_CRYPT, logger, "%s() counter-block updated from 0x%" PRIx32 " to 0x%" PRIx32 " for %zd bytes", __func__, old_counter, new_counter, text.len); /* Wrap ... */ passert(new_counter >= old_counter); *counter = htonl(new_counter); } ldbgf(DBG_CRYPT, logger, "do_aes_ctr: exit"); } static void cipher_op_context_destroy_ctr_nss(struct cipher_op_context **context, struct logger *logger) { ldbgf(DBG_CRYPT, logger, "%s()", __func__); pfreeany(*context); } static void cipher_check_ctr_nss(const struct encrypt_desc *cipher, struct logger *logger) { ldbgf(DBG_CRYPT, logger, "%s() nothing to do with %p", __func__, cipher); } const struct encrypt_ops ike_alg_encrypt_nss_ctr_ops = { .backend = "NSS(CTR)", .cipher_check = cipher_check_ctr_nss, .cipher_op_context_create = cipher_op_context_create_ctr_nss, .cipher_op_normal = cipher_op_ctr_nss, .cipher_op_context_destroy = cipher_op_context_destroy_ctr_nss, }; libreswan-5.2/lib/libswan/ike_alg_encrypt_null_ops.c000066400000000000000000000031771475767661000230240ustar00rootroot00000000000000/* NULL IKE encryption, for libreswan * * Copyright (C) 2023 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY 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 "crypt_cipher.h" #include "ike_alg_encrypt_ops.h" #include "lswnss.h" /* for llog_nss_error() */ static void cipher_op_null(const struct encrypt_desc *cipher UNUSED, struct cipher_op_context *context UNUSED, enum cipher_op op UNUSED, enum cipher_iv_source iv_source UNUSED, PK11SymKey *symkey UNUSED, shunk_t salt UNUSED, chunk_t wire_iv UNUSED, chunk_t text UNUSED, struct crypt_mac *ikev1_iv UNUSED, struct logger *logger UNUSED) { /* nothing happens */ } static void cipher_check_null(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_null_ops = { .backend = "NULL", .cipher_check = cipher_check_null, .cipher_op_normal = cipher_op_null, }; libreswan-5.2/lib/libswan/ike_alg_hash_identity.c000066400000000000000000000020701475767661000222500ustar00rootroot00000000000000/* * 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_IPSEC_ID] = -1, [IKEv2_ALG_ID] = IKEv2_HASH_ALGORITHM_IDENTITY, }, .fips.approved = true, }, }; libreswan-5.2/lib/libswan/ike_alg_hash_md5.c000066400000000000000000000031151475767661000211050ustar00rootroot00000000000000/* 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_IPSEC_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-5.2/lib/libswan/ike_alg_hash_nss_ops.c000066400000000000000000000054501475767661000221100ustar00rootroot00000000000000/* * 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 "fips_mode.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-5.2/lib/libswan/ike_alg_hash_sha1.c000066400000000000000000000043251475767661000212600ustar00rootroot00000000000000/* 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_IPSEC_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-5.2/lib/libswan/ike_alg_hash_sha2_256.c000066400000000000000000000050561475767661000216570ustar00rootroot00000000000000/* * 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_IPSEC_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-5.2/lib/libswan/ike_alg_ipcomp.c000066400000000000000000000041171475767661000207070ustar00rootroot00000000000000/* 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_IPSEC_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_IPSEC_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_IPSEC_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-5.2/lib/libswan/ike_alg_md5.c000066400000000000000000000052311475767661000201030ustar00rootroot00000000000000/* 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_IPSEC_ID] = -1, [IKEv2_ALG_ID] = IKEv2_PRF_HMAC_MD5, }, }, .nss = { .mechanism = CKM_MD5_HMAC, }, .prf_key_size = MD5_DIGEST_SIZE, .prf_output_size = MD5_DIGEST_SIZE, .hasher = &ike_alg_hash_md5, .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 = "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_IPSEC_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 = IKEv1_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-5.2/lib/libswan/ike_alg_none.c000066400000000000000000000065161475767661000203640ustar00rootroot00000000000000/* * 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_encrypt_ops.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_IPSEC_ID] = IKEv1_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", .encrypt_ops = &ike_alg_encrypt_null_ops, }; /* * 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_IPSEC_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_IPSEC_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-5.2/lib/libswan/ike_alg_prf_ikev1_mac_ops.c000066400000000000000000000164311475767661000230110ustar00rootroot00000000000000/* * 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() */ #include "secrets.h" /* for struct secret_preshared_stuff; */ /* * 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, const struct secret_preshared_stuff *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 = symkey_addref(logger, "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); symkey_delref(logger, "old_k:N", &old_k); old_k = new_k; } symkey_delref(logger, "old_k:final", &old_k); PK11SymKey *cryptkey = encrypt_key_from_symkey_bytes("cryptkey", encrypter, 0, required_keymat, keymat, HERE, logger); symkey_delref(logger, "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-5.2/lib/libswan/ike_alg_prf_ikev1_nss_ops.c000066400000000000000000000224251475767661000230540ustar00rootroot00000000000000/* * 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" #include "lswalloc.h" #include "secrets.h" /* for struct secret_preshared_stuff; */ /* * 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, const struct secret_preshared_stuff *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); symkey_delref(logger, "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. */ 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); symkey_delref(logger, "section 5 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-5.2/lib/libswan/ike_alg_prf_ikev2_mac_ops.c000066400000000000000000000251451475767661000230140ustar00rootroot00000000000000/* * 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 Nupur Agrawal * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT 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 "fips_mode.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 = symkey_addref(logger, "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); symkey_delref(logger, "old_t[N]", &old_t); old_t = new_t; } symkey_delref(logger, "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); symkey_delref(logger, "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); } /* * SKEYSEED = prf(SK_d (old), "Resumption" | Ni | Nr) */ static PK11SymKey *ike_sa_resume_skeyseed(const struct prf_desc *prf_desc, PK11SymKey *SK_d_old, 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 session resume 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), 'Resumption' | Ni | Nr)"); return NULL; } /* seed: 'resumption' | Ni | Nr) */ static const char sr_str[] = "Resumption"; crypt_prf_update_bytes(prf,sr_str, sr_str, sizeof(sr_str) - 1); 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); symkey_delref(logger, "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 = symkey_addref(logger, "new_dh_secret", 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); symkey_delref(logger, "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 (is_fips_mode()) { 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); } symkey_delref(logger, "prf-psk", &prf_psk); return signed_octets; } static struct crypt_mac psk_resume(const struct prf_desc *prf_desc, PK11SymKey *SK_px, chunk_t first_packet, struct logger *logger) { struct crypt_prf *prf = crypt_prf_init_symkey(" = prf(SK_px, )", prf_desc, "", SK_px, logger); if (prf == NULL) { llog_pexpect(logger, HERE, "failed to create IKEv2 PRF for computing signed-octets = prf(SK_px, "); return empty_mac; } crypt_prf_update_hunk(prf, "first-packet", first_packet); return crypt_prf_final_mac(&prf, NULL); } 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_resume_skeyseed = ike_sa_resume_skeyseed, .ike_sa_keymat = ike_sa_keymat, .child_sa_keymat = child_sa_keymat, .psk_auth = psk_auth, .psk_resume = psk_resume, }; libreswan-5.2/lib/libswan/ike_alg_prf_ikev2_nss_ops.c000066400000000000000000000217461475767661000230620ustar00rootroot00000000000000/* * 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 Nupur Agrawal * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT 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 "fips_mode.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); } /* * SKEYSEED = prf(SK_d (old), "Resumption" | Ni | Nr) */ static PK11SymKey *ike_sa_resume_skeyseed(const struct prf_desc *prf, PK11SymKey *SK_d_old, const chunk_t Ni, const chunk_t Nr, struct logger *logger) { return ike_alg_prf_ikev2_mac_ops.ike_sa_resume_skeyseed(prf, SK_d_old, Ni, Nr, 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 (is_fips_mode()) { 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); symkey_delref(logger, "psk 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); } symkey_delref(logger, "prf-psk", &prf_psk); return signed_octets; } static struct crypt_mac psk_resume(const struct prf_desc *prf, PK11SymKey *SK_px, chunk_t first_packet, struct logger *logger) { return ike_alg_prf_ikev2_mac_ops.psk_resume(prf, SK_px, first_packet, logger); } 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_resume_skeyseed = ike_sa_resume_skeyseed, .ike_sa_keymat = ike_sa_keymat, .child_sa_keymat = child_sa_keymat, .psk_auth = psk_auth, .psk_resume = psk_resume, }; libreswan-5.2/lib/libswan/ike_alg_prf_mac_hmac_ops.c000066400000000000000000000142121475767661000226750ustar00rootroot00000000000000/* * 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, prf->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 = symkey_addref(prf->logger, name, 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); symkey_delref(prf->logger, "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); symkey_delref(prf->logger, "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); symkey_delref(prf->logger, "hashed-inner", &hashed_inner); symkey_delref(prf->logger, "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); symkey_delref((*prfp)->logger, "outer", &outer); if (DBGP(DBG_CRYPT)) { LDBG_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); symkey_delref((*prfp)->logger, "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-5.2/lib/libswan/ike_alg_prf_mac_nss_ops.c000066400000000000000000000125271475767661000225770ustar00rootroot00000000000000/* * 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; } ldbgf(DBG_CRYPT, logger, "%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; } ldbgf(DBG_CRYPT, logger, "%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); symkey_delref(prf->logger, "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); symkey_delref(prf->logger, "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-5.2/lib/libswan/ike_alg_prf_mac_xcbc_ops.c000066400000000000000000000226151475767661000227120ustar00rootroot00000000000000/* * 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); } symkey_delref(logger, "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) { ldbgf(DBG_CRYPT, logger, "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 = symkey_addref(logger, "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 */ symkey_delref(logger, "local_draft_key", &local_draft_key); free_chunk_content(&zeros); } else if (dkey_sz > prf_desc->prf_key_size) { ldbgf(DBG_CRYPT, logger, "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); symkey_delref(logger, "zero_key", &zero_key); free_chunk_content(&zeros); } else { ldbgf(DBG_CRYPT, logger, "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); symkey_delref(logger, "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); symkey_delref((*prf)->logger, "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); symkey_delref((*prf)->logger, "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-5.2/lib/libswan/ike_alg_prf_test_vectors.c000066400000000000000000000275641475767661000230260ustar00rootroot00000000000000/* * 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 "fips_mode.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, logger, HERE); passert(chunk_key.len == test->key_size); chunk_t chunk_message = (test->message != NULL ? decode_to_chunk(__func__, test->message, logger, HERE) : alloc_chunk(test->message_size, __func__)); chunk_t prf_output = decode_to_chunk(__func__, test->prf_output, logger, HERE); 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 (LDBGP(DBG_CRYPT, logger)) { LDBG_log(logger, "chunk output"); LDBG_hunk(logger, chunk_output); } if (!verify_hunk(test->description, "prf OUT", prf_output, chunk_output, logger, HERE)) { 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 (LDBGP(DBG_CRYPT, logger)) { LDBG_symkey(logger, "output", "symkey", symkey_output); } if (!verify_symkey(test->description, "symkey", prf_output, symkey_output, logger, HERE)) { ok = false; } ldbg(logger, "%s: %s %s", __func__, test->description, (ok ? "passed" : "failed")); free_chunk_content(&chunk_message); free_chunk_content(&chunk_key); symkey_delref(logger, "message", &symkey_message); symkey_delref(logger, "key", &symkey_key); symkey_delref(logger, "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, logger, HERE); passert(chunk_ni.len == test->ni_size); chunk_t chunk_nr = decode_to_chunk(__func__, test->nr, logger, HERE); passert(chunk_nr.len == test->nr_size); chunk_t chunk_spii = decode_to_chunk(__func__, test->spii, logger, HERE); chunk_t chunk_spir = decode_to_chunk(__func__, test->spir, logger, HERE); chunk_t chunk_gir = decode_to_chunk(__func__, test->gir, logger, HERE); passert(chunk_gir.len == test->gir_size); chunk_t chunk_gir_new = decode_to_chunk(__func__, test->gir_new, logger, HERE); passert(chunk_gir_new.len == test->gir_size); chunk_t chunk_skeyseed = decode_to_chunk(__func__, test->skeyseed, logger, HERE); chunk_t chunk_skeyseed_rekey = decode_to_chunk(__func__, test->skeyseed_rekey, logger, HERE); chunk_t chunk_dkm = decode_to_chunk(__func__, test->dkm, logger, HERE); 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, "skeyseed", chunk_skeyseed, skeyseed, logger, HERE)) { 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, "DKM", chunk_dkm, dkm, logger, HERE)) { 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, "skeyseed_rekey", chunk_skeyseed_rekey, skeyseed_rekey, logger, HERE)) { ok = false; } symkey_delref(logger, "gir", &gir); symkey_delref(logger, "gir_new", &gir_new); symkey_delref(logger, "skeyseed", &skeyseed); symkey_delref(logger, "dkm", &dkm); symkey_delref(logger, "skd", &skd); symkey_delref(logger, "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); ldbg(logger, "%s() %s: %s", __func__, test->description, (ok ? "passed" : "failed")); 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-5.2/lib/libswan/ike_alg_sha1.c000066400000000000000000000054411475767661000202550ustar00rootroot00000000000000/* 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_IPSEC_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_IPSEC_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 = IKEv1_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-5.2/lib/libswan/ike_alg_sha2.c000066400000000000000000000235231475767661000202570ustar00rootroot00000000000000/* * 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_IPSEC_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_IPSEC_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 = IKEv1_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_IPSEC_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 = IKEv1_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_IPSEC_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_IPSEC_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_IPSEC_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 = IKEv1_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_IPSEC_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_IPSEC_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_IPSEC_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 = IKEv1_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-5.2/lib/libswan/ike_alg_test.c000066400000000000000000000035131475767661000203760ustar00rootroot00000000000000/* 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-5.2/lib/libswan/ike_info.c000066400000000000000000000142731475767661000175340ustar00rootroot00000000000000/* * 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_ikev1_ike_proposals[] = "AES_CBC" "," "3DES" ; static const struct ike_alg *default_ikev1_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_ikev1_groups[] = { &ike_alg_dh_modp2048.common, &ike_alg_dh_modp1536.common, &ike_alg_dh_secp256r1.common, &ike_alg_dh_curve25519.common, NULL, }; const struct proposal_defaults ikev1_ike_defaults = { .proposals[FIPS_MODE_ON] = default_ikev1_ike_proposals, .proposals[FIPS_MODE_OFF] = default_ikev1_ike_proposals, .dh = default_ikev1_groups, .prf = default_ikev1_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_fips_on_ikev2_ike_proposals[] = "AES_GCM_16_256" "," "AES_GCM_16_128" "," "AES_CBC_256" "," "AES_CBC_128" ; static const char default_fips_off_ikev2_ike_proposals[] = "AES_GCM_16_256" "," "AES_GCM_16_128" #ifdef USE_CHACHA "," "CHACHA20_POLY1305" /*not-FIPS*/ #endif "," "AES_CBC_256" "," "AES_CBC_128" ; static const struct ike_alg *default_ikev2_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_ikev2_groups[] = { &ike_alg_dh_secp256r1.common, &ike_alg_dh_secp384r1.common, &ike_alg_dh_secp521r1.common, #ifdef USE_DH31 &ike_alg_dh_curve25519.common, #endif &ike_alg_dh_modp4096.common, &ike_alg_dh_modp3072.common, &ike_alg_dh_modp2048.common, &ike_alg_dh_modp8192.common, NULL, }; const struct proposal_defaults ikev2_ike_defaults = { .proposals[FIPS_MODE_ON] = default_fips_on_ikev2_ike_proposals, .proposals[FIPS_MODE_OFF] = default_fips_off_ikev2_ike_proposals, .prf = default_ikev2_ike_prfs, /* INTEG is derived from PRF when applicable */ .dh = default_ikev2_groups, }; /* * All together now ... */ static const struct proposal_protocol ikev1_ike_proposal_protocol = { .name = "IKE", .alg_id = IKEv1_OAKLEY_ID, .defaults = &ikev1_ike_defaults, .proposal_ok = ike_proposal_ok, .encrypt = true, .prf = true, .integ = true, .dh = true, }; static const struct proposal_protocol ikev2_ike_proposal_protocol = { .name = "IKE", .alg_id = IKEv2_ALG_ID, .defaults = &ikev2_ike_defaults, .proposal_ok = ike_proposal_ok, .encrypt = true, .prf = true, .integ = true, .dh = true, }; static const struct proposal_protocol *ike_proposal_protocol[] = { [IKEv1] = &ikev1_ike_proposal_protocol, [IKEv2] = &ikev2_ike_proposal_protocol, }; struct proposal_parser *ike_proposal_parser(const struct proposal_policy *policy) { return alloc_proposal_parser(policy, ike_proposal_protocol[policy->version]); } libreswan-5.2/lib/libswan/ikev1_prf.c000066400000000000000000000121401475767661000176260ustar00rootroot00000000000000/* * 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() */ #include "lswlog.h" /* for DBGP() et.al. */ /* * 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, const struct secret_preshared_stuff *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)) { LDBG_log(logger, "calling %s.%s():", prf_desc->prf_ikev1_ops->backend, __func__); LDBG_symkey(logger, __func__, "SKEYID_d:", SKEYID_d); LDBG_symkey(logger, __func__, "g_xy:", g_xy); LDBG_log(logger, "protocol: 0x%02"PRIx8, protocol); LDBG_log(logger, "SPI"); LDBG_hunk(logger, SPI); LDBG_log(logger, "Ni_b"); LDBG_hunk(logger, Ni_b); LDBG_log(logger, "Ni_b"); LDBG_hunk(logger, Nr_b); LDBG_log(logger, "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-5.2/lib/libswan/ikev2_prf.c000066400000000000000000000113751475767661000176400ustar00rootroot00000000000000/* * 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 * Copyright (C) 2020 Nupur Agrawal * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT 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 "fips_mode.h" #include "pexpect.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); } PK11SymKey *ikev2_ike_sa_ppk_interm_skeyseed(const struct prf_desc *prf_desc, PK11SymKey *old_SK_d, shunk_t ppk, struct logger *logger) { PK11SymKey *ppk_key = symkey_from_hunk("PPK Keying material", ppk, logger); PK11SymKey *skeyseed = prf_desc->prf_ikev2_ops->prfplus(prf_desc, ppk_key, old_SK_d, prf_desc->prf_key_size, logger); symkey_delref(logger, "PPK key", &ppk_key); return skeyseed; } /* * 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); } /* * SKEYSEED = prf(SK_d (old), "Resumption" | Ni | Nr) * * XXX: once NSS is figured out this should become part of the PRF * vector (as it was on the branch). */ PK11SymKey *ikev2_ike_sa_resume_skeyseed(const struct prf_desc *prf_desc, PK11SymKey *SK_d_old, const chunk_t Ni, const chunk_t Nr, struct logger *logger) { return prf_desc->prf_ikev2_ops->ike_sa_resume_skeyseed(prf_desc, SK_d_old, Ni, Nr, logger); } /* * XXX: once NSS is figured out this should become part of the PRF * vector (as it was on the branch). */ struct crypt_mac ikev2_psk_resume(const struct prf_desc *prf_desc, PK11SymKey *SK_px, chunk_t first_packet, struct logger *logger) { return prf_desc->prf_ikev2_ops->psk_resume(prf_desc, SK_px, first_packet, logger); } libreswan-5.2/lib/libswan/impair.c000066400000000000000000000640571475767661000172370ustar00rootroot00000000000000/* 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 "sparse_names.h" #include "lmod.h" #include "impair.h" #include "lswlog.h" #include "whack.h" static const struct sparse_names impair_emit_names = { .roof = IMPAIR_EMIT_ROOF, .list = { #define S(E, H) { \ .name = #E, \ .value = IMPAIR_EMIT_##E, \ .help = H, \ } S(OMIT, "do not emit content"), S(EMPTY, "emit zero length content"), S(DUPLICATE, "emit content twice"), #undef S SPARSE_NULL, }, }; static const struct sparse_names impair_v1_exchange_names = { .list = { #define S(E, H) { \ .name = #E, \ .value = IMPAIR_v1_##E##_EXCHANGE, \ .help = 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 SPARSE_NULL, }, }; /* transform */ static const struct sparse_names impair_v2_transform_names = { .list = { #define S(S, E, H) { \ .name = S, \ .value = IMPAIR_v2_TRANSFORM_##E, \ .help = H, \ } 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 SPARSE_NULL, }, }; /* */ struct impairment { const char *what; const char *help; /* * When .how_sparse_names is non-NULL, HOW is the unbiased * value of the keyword. It's assumed that any keyword with * the value 0 disables the impairment. * * And when .unsigned_help is also non-NULL, HOW can also be * an unsigned number encoded as .keywords .nr_keywords + * UNSIGNED. */ const struct sparse_names *how_sparse_names; /* * (else) * * When .how_enum_names is non-NULL, HOW is the unbiased enum * name's value. * * And when .unsigned_help is also non-NULL, HOW can also be * an unsigned value which is passed unchanged. Zero is * allowed. */ const struct enum_names *how_enum_names; /* * (else) * * When .unsigned_help is non-NULL, HOW is the unsigned value. * * Note: either the value is a struct impair_unsigned which as * an enabled bit and allows zero, or the value is being used * by an event. */ const char *unsigned_help; /* * Location of the value to update, and, optionally, the bit * to set/clear. */ void *value; size_t sizeof_value; bool *enabled; /* possibly NULL enabled bit */ /* * Operations. */ 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(VALUE, HELP, ...) \ { \ .what = #VALUE, \ .action = CALL_IMPAIR_UPDATE, \ .value = &impair.VALUE, \ .help = HELP, \ .sizeof_value = sizeof(impair.VALUE), \ ##__VA_ARGS__, \ } #define B(VALUE, HELP) \ { \ .what = #VALUE, \ .action = CALL_IMPAIR_UPDATE, \ .help = HELP, \ .value = &impair.VALUE, \ .sizeof_value = sizeof(impair.VALUE), \ } #define U(VALUE, HELP) \ { \ .what = #VALUE, \ .action = CALL_IMPAIR_UPDATE, \ .help = HELP, \ .value = &impair.VALUE.value, \ .sizeof_value = sizeof(impair.VALUE.value), \ .enabled = &impair.VALUE.enabled, \ .unsigned_help = "", \ } #define E(VALUE, ENUM_NAMES, HELP, ...) \ { \ .what = #VALUE, \ .action = CALL_IMPAIR_UPDATE, \ .help = HELP, \ .enabled = &impair.VALUE.enabled, \ .value = &impair.VALUE.value, \ .sizeof_value = sizeof(impair.VALUE.value), \ .how_enum_names = &ENUM_NAMES, \ ##__VA_ARGS__, \ } B(allow_dns_insecure, "allow IPSECKEY lookups without DNSSEC protection"), B(allow_null_none, "cause pluto to allow esp=null-none and ah=none for testing"), B(bad_ike_auth_xchg, "causes pluto to send IKE_AUTH replies with wrong exchange type"), B(bust_mi2, "make MI2 really large"), B(bust_mr2, "make MR2 really large"), V(child_key_length_attribute, "corrupt the outgoing CHILD proposal's key length attribute", .how_sparse_names = &impair_emit_names, .unsigned_help = "emit as the key length"), B(corrupt_encrypted, "corrupts the encrypted packet so that the decryption fails"), B(drop_i2, "drop second initiator packet"), B(drop_xauth_r0, "causes pluto to drop an XAUTH user/passwd request on IKE initiator"), B(emitting, "disable correctness-checks when emitting a payload (let anything out)"), B(force_fips, "causes pluto to believe we are in fips mode, NSS needs its own hack"), V(ike_key_length_attribute, "corrupt the outgoing IKE proposal's key length attribute", .how_sparse_names = &impair_emit_names, .unsigned_help = "emit as the key length"), U(ike_initiator_spi, "corrupt the IKE initiator SPI setting it to the value"), U(ike_responder_spi, "corrupt the IKE responder SPI setting it to the value"), B(ikev1_del_with_notify, "causes pluto to send IKE Delete with additional bogus Notify payload"), V(v2_proposal_integ, "integrity in proposals", .how_sparse_names = &impair_v2_transform_names), V(v2_proposal_dh, "dh in proposals", .how_sparse_names = &impair_v2_transform_names), U(ikev2_add_ike_transform, "add an extra (possibly bogus) TYPE transform with ID to the first IKE proposal ( is encoded as TYPE<<16|ID)"), U(ikev2_add_child_transform, "add an extra (possibly bogus) TYPE transform with ID to the first CHILD proposal ( is encoded as TYPE<<16|ID)"), B(jacob_two_two, "cause pluto to send all messages twice."), V(ke_payload, "corrupt the outgoing KE payload", .how_sparse_names = &impair_emit_names, .unsigned_help = "emit the KE payload filled with bytes"), U(log_rate_limit, "set the per-hour(?) cap on rate-limited log messages"), B(major_version_bump, "cause pluto to send an IKE major version that's higher then we support."), B(minor_version_bump, "cause pluto to send an IKE minor version that's higher then we support."), B(childless_ikev2_supported, "causes pluto to omit/ignore the CHILDLESS_IKEV2_SUPPORTED notify in the IKE_SA_INIT exchange"), B(proposal_parser, "impair algorithm parser - what you see is what you get"), B(rekey_initiate_supernet, "impair IPsec SA rekey initiator TSi and TSR to 0/0 ::0, emulate Windows client"), B(rekey_initiate_subnet, "impair IPsec SA rekey initiator TSi and TSR to X/32 or X/128"), B(rekey_respond_supernet, "impair IPsec SA rekey responder TSi and TSR to 0/0 ::0"), B(rekey_respond_subnet, "impair IPsec SA rekey responder TSi and TSR to X/32 X/128"), B(replay_encrypted, "replay encrypted packets"), B(revival, "disable code that revives a connection that is supposed to stay up"), B(send_bogus_dcookie, "causes pluto to send a a bogus IKEv2 DCOOKIE"), B(send_bogus_isakmp_flag, "causes pluto to set a RESERVED ISAKMP flag to test ignoring/zeroing it"), B(send_bogus_payload_flag, "causes pluto to set a RESERVED PAYLOAD flag to test ignoring/zeroing it"), B(send_key_size_check, "causes pluto to omit checking configured ESP key sizes for testing"), B(send_no_delete, "causes pluto to omit sending Notify/Delete messages"), B(send_no_ikev2_auth, "causes pluto to omit sending an IKEv2 IKE_AUTH packet"), B(send_no_main_r2, "causes pluto to omit sending an last Main Mode response packet"), B(send_no_xauth_r0, "causes pluto to omit sending an XAUTH user/passwd request"), B(send_no_idr, "causes pluto as initiator to omit sending an IDr payload"), B(send_pkcs7_thingie, "send certificates as a PKCS7 thingie"), B(send_nonzero_reserved, "send non-zero reserved fields in IKEv2 proposal fields"), B(send_nonzero_reserved_id, "send non-zero reserved fields in IKEv2 ID payload that is part of the AUTH hash calculation"), B(suppress_retransmits, "causes pluto to never send retransmits (wait the full timeout)"), B(timeout_on_retransmit, "causes pluto to 'retry' (switch protocol) on the first retransmit"), B(event_check_crls, "do not schedule the CRL check event"), B(v1_hash_check, "disable check of incoming IKEv1 hash payload"), V(v1_hash_exchange, "corrupt the HASH payload in the outgoing exchange", .how_sparse_names = &impair_v1_exchange_names), V(v1_hash_payload, "corrupt the emitted HASH payload", .how_sparse_names = &impair_emit_names, .unsigned_help = "emit the hash payload filled with bytes"), B(tcp_use_blocking_write, "use a blocking write when sending TCP encapsulated IKE messages"), B(tcp_skip_setsockopt_espintcp, "skip the required setsockopt(\"espintcp\") call"), /* * Impair message flow. */ B(record_inbound, "enable recording of inbound messages"), B(record_outbound, "enable recording of outbound messages"), A("drop_inbound", IMPAIR_MESSAGE_DROP, IMPAIR_INBOUND_MESSAGE, "drop the N'th inbound message", "message number"), A("drop_outbound", IMPAIR_MESSAGE_DROP, IMPAIR_OUTBOUND_MESSAGE, "drop the N'th outbound message", "message number"), A("block_inbound", IMPAIR_MESSAGE_BLOCK, IMPAIR_INBOUND_MESSAGE, "block all inbound messages", NULL), A("block_outbound", IMPAIR_MESSAGE_BLOCK, IMPAIR_OUTBOUND_MESSAGE, "block all outbound messages", NULL), A("drip_inbound", IMPAIR_MESSAGE_DRIP, IMPAIR_INBOUND_MESSAGE, "drip N'th inbound message", "message number"), A("drip_outbound", IMPAIR_MESSAGE_DRIP, IMPAIR_OUTBOUND_MESSAGE, "drip N'th outbound message", "message number"), A("duplicate_inbound", IMPAIR_MESSAGE_DUPLICATE, IMPAIR_INBOUND_MESSAGE, "duplicate each inbound packet", NULL), A("duplicate_outbound", IMPAIR_MESSAGE_DUPLICATE, IMPAIR_OUTBOUND_MESSAGE, "duplicate each outbound packet", NULL), A("replay_inbound", IMPAIR_MESSAGE_REPLAY, IMPAIR_INBOUND_MESSAGE, "replay all inbound packets old-to-new", NULL), A("replay_outbound", IMPAIR_MESSAGE_REPLAY, IMPAIR_OUTBOUND_MESSAGE, "replay all outbound packets old-to-new", NULL), /* * Mangle payloads. */ E(add_unknown_v2_payload_to, ikev2_exchange_names, "impair the (unencrypted) part of the exchange"), E(add_unknown_v2_payload_to_sk, ikev2_exchange_names, "impair the encrypted part of the exchange"), B(unknown_v2_payload_critical, "include the unknown payload in the encrypted SK payload"), E(add_v2_notification, v2_notification_names, "add a notification to the message", .unsigned_help = "notification"), E(ignore_v2_notification, v2_notification_names, "ignore a notification in the message", .unsigned_help = "notification"), E(omit_v2_notification, v2_notification_names, "omit a notification in the message", .unsigned_help = "notification"), B(ignore_soft_expire, "ignore kernel soft expire events"), B(ignore_hard_expire, "ignore kernel hard expire events"), E(force_v2_auth_method, ikev2_auth_method_names, "force the use of the specified IKEv2 AUTH method"), B(omit_v2_ike_auth_child, "omit, and don't expect, CHILD SA payloads in IKE_AUTH message"), B(ignore_v2_ike_auth_child, "ignore, but do expect, CHILD SA payloads in the IKE_AUTH message"), /* * Trigger global event. */ A("trigger", GLOBAL_EVENT_HANDLER, 0, "trigger the global event", "EVENT", .how_enum_names = &global_timer_names), /* * Trigger state event. */ A("trigger_v2_rekey", STATE_EVENT_HANDLER, EVENT_v2_REKEY, "trigger the rekey event", "#SA"), A("trigger_v2_liveness", STATE_EVENT_HANDLER, EVENT_v2_LIVENESS, "trigger the liveness event", "#SA"), A("trigger_v1_replace", STATE_EVENT_HANDLER, EVENT_v1_REPLACE, "trigger the IKEv1 replace event", "#SA"), A("trigger_v2_replace", STATE_EVENT_HANDLER, EVENT_v2_REPLACE, "trigger the IKEv2 replace event", "#SA"), /* * Trigger connection event. */ A("trigger_revival", CONNECTION_EVENT_HANDLER, CONNECTION_REVIVAL, "trigger the revival event", "$CONNECTION"), /* * Force the event (bypassing most of the should I do this * logic). */ 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"), B(cannot_ondemand, "force acquire to call cannot_ondemand() and fail"), U(number_of_TSi_selectors, "set the number of selectors in the TSi payload to the bogus "), U(number_of_TSr_selectors, "set the number of selectors in the TSr payload to the bogus "), B(lifetime, "skip any IKE/IPsec lifetime checks when adding connection"), B(copy_v1_notify_response_SPIs_to_retransmission, "copy SPIs in IKEv1 notify response to last sent packet and then retransmit"), U(v1_remote_quick_id, "set the remote quick ID to "), U(v1_emit_quick_id, "number of IDc[ir]s to emit (there should be 2)"), V(v1_isakmp_delete_payload, "corrupt outgoing ISAKMP delete payload", .how_sparse_names = &impair_emit_names), V(v1_ipsec_delete_payload, "corrupt outgoing IPsec delete payload", .how_sparse_names = &impair_emit_names), 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"), U(helper_thread_delay, "pause seconds before starting each helper thread job; 0 will MS warp the delay"), B(install_ipsec_sa_inbound_state, "error after installing the inbound IPsec SA state (but before policy)"), B(install_ipsec_sa_inbound_policy, "error after installing the inbound IPsec SA policy (and state)"), B(install_ipsec_sa_outbound_state, "error after installing the outbound IPsec SA state (but before policy)"), B(install_ipsec_sa_outbound_policy, "error after installing the outbound IPsec SA policy (and state)"), #undef U #undef B #undef V #undef A #undef E }; 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_sparse_names != NULL) { for (const struct sparse_name *sn = cr->how_sparse_names->list; sn->name != NULL; sn++) { /* skip 0, always no */ if (sn->value == 0) { continue; } if (sn->help != NULL) { fprintf(file, "%s %s: %s\n", prefix, sn->name, sn->help); } } } 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, ", "); } enum_buf eb; fprintf(file, "%s", str_enum_short(cr->how_enum_names, e, &eb)); } 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); } } /* * Try to bias VALUE. When the BIAS would overflow log and fail. */ static bool bias_uintmax(const struct impairment *impairment, unsigned bias, uintmax_t *value, struct logger *logger) { /* * Does the result fit? * * Start with 0xff..ff, and then right shift it so it is the * MAX of the value. */ unsigned drop = sizeof(uintmax_t) - impairment->sizeof_value; uintmax_t max = ((uintmax_t)UINTMAX_MAX) >> drop; if (*value > max - bias) { llog(ERROR_STREAM, logger, "impair option '%s' value '%ju' overflows", impairment->what, *value); return false; } *value += bias; return true; } #define IMPAIR_NONE (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_NONE, }; return IMPAIR_OK; } if (enable && streq(optarg, "list")) { *whack_impair = (struct whack_impair) { .what = IMPAIR_LIST, }; 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 = hunk_strcaseeat(&what, "no-"); unsigned ci = 1; const struct impairment *impairment = NULL; for (ci = 1/*skip 0*/; ci < elemsof(impairments); ci++) { if (hunk_strheq(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, .value = 0, .enable = false, }; return IMPAIR_OK; } /* * For WHAT:HOW, lookup the keyword HOW. */ if (impairment->how_sparse_names != NULL) { /* try the keyword. */ const struct sparse_name *sn = sparse_lookup(impairment->how_sparse_names, how); if (sn != NULL) { *whack_impair = (struct whack_impair) { .what = ci, .value = sn->value, /* unbiased */ .enable = true, }; return IMPAIR_OK; } } 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, .value = e, /* unbiased */ .enable = true, }; return IMPAIR_OK; } } /* * "no" always works. */ if (hunk_strcaseeq(how, "no")) { /* --impair WHAT:no */ *whack_impair = (struct whack_impair) { .what = ci, .value = 0, .enable = false, }; return IMPAIR_OK; } /* * Yes only works when there's no other interpretation of the * value. */ if (impairment->how_enum_names == NULL && impairment->how_sparse_names == NULL && impairment->unsigned_help == NULL) { if (how.len == 0 || hunk_strcaseeq(how, "yes")) { /* --impair WHAT:yes or --impair WHAT */ *whack_impair = (struct whack_impair) { .what = ci, .value = true, .enable = true, }; return IMPAIR_OK; } } /* * Not a name, perhaps it is a number. */ if (impairment->unsigned_help != NULL) { uintmax_t value; err_t err = shunk_to_uintmax(how, NULL, 0/*base*/, &value); if (err != NULL) { llog(ERROR_STREAM, logger, "impair option '"PRI_SHUNK"' has invalid parameter '"PRI_SHUNK"': %s", pri_shunk(what), pri_shunk(how), err); return IMPAIR_ERROR; } uintmax_t bias = (impairment->how_sparse_names != NULL ? impairment->how_sparse_names->roof : 0); if (!bias_uintmax(impairment, bias, &value, logger)) { /* already logged */ return IMPAIR_ERROR; } /* * When .enabled, 0 is valid so pass it along. */ *whack_impair = (struct whack_impair) { .what = ci, /*i.e., index*/ .value = value, .enable = (impairment->enabled != NULL ? true : value > 0), }; return IMPAIR_OK; } /* error */ llog(ERROR_STREAM, logger, "impair option '"PRI_SHUNK"' has unrecognized parameter '"PRI_SHUNK"'", pri_shunk(what), pri_shunk(how)); 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 bool impairment_enabled(const struct impairment *impairment) { if (impairment->action != CALL_IMPAIR_UPDATE) { return false; } /* flip logic */ if (impairment->enabled != NULL && *impairment->enabled) { return true; } if (value_of(impairment) != 0) { return true; } return false; } static void jam_impairment_value(struct jambuf *buf, const struct impairment *impairment) { uintmax_t value = value_of(impairment); if (impairment->how_sparse_names != NULL) { name_buf nb; if (sparse_short(impairment->how_sparse_names, value, &nb)) { jam_string(buf, nb.buf); } else if (value >= impairment->how_sparse_names->roof) { /*unbias*/ jam(buf, "%ju", value - impairment->how_sparse_names->roof); } else { jam(buf, "?%ju?", value); } } else if (impairment->how_enum_names != NULL) { enum_buf sname; if (enum_name_short(impairment->how_enum_names, value, &sname)) { jam_string(buf, sname.buf); } else { jam(buf, "%ju", value); } } else if (impairment->unsigned_help != NULL && impairment->enabled != NULL) { if (*impairment->enabled) { jam(buf, "%ju", value); } else { jam_string(buf, "no"); } } else if (impairment->unsigned_help != NULL) { /* should have .enabled */ jam(buf, "?%ju?", value); } else { switch (value) { case 0: jam(buf, "no"); break; case 1: jam(buf, "yes"); break; default: jam(buf, "?%ju?", value); } } } static void jam_impairment(struct jambuf *buf, const struct impairment *impairment) { jam_string(buf, impairment->what); jam_string(buf, ":"); jam_impairment_value(buf, impairment); } bool have_impairments(void) { /* is there anything enabled? */ for (unsigned ci = 1; ci < elemsof(impairments); ci++) { const struct impairment *impairment = &impairments[ci]; if (impairment_enabled(impairment)) { 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_enabled(impairment)) { jam_string(buf, s); s = sep; jam_impairment(buf, impairment); } } } static void process_impair_update(const struct impairment *impairment, const struct whack_impair *wc, struct logger *logger) { LLOG_JAMBUF(LOG_STREAM/*not-whack*/, logger, buf) { /* * XXX: lower case "impair:" for updates; upper case * "IMPAIR:" for actions. */ jam_string(buf, "impair: "); jam_string(buf, impairment->what); jam_string(buf, ": "); /* old value */ jam_impairment_value(buf, impairment); /* update */ switch (impairment->sizeof_value) { #define L(T) case sizeof(uint##T##_t): \ { \ *(uint##T##_t*)impairment->value = wc->value; \ break; \ } L(8); L(16); L(32); L(64); #undef L default: bad_case(impairment->sizeof_value); } if (impairment->enabled != NULL) { *impairment->enabled = wc->enable; } /* new value */ jam_string(buf, " -> "); jam_impairment_value(buf, impairment); } } static void process_impair_none(struct logger *logger) { for (unsigned ci = 1; ci < elemsof(impairments); ci++) { const struct impairment *impairment = &impairments[ci]; if (impairment_enabled(impairment)) { struct whack_impair wc = {0}; /* i.e., none */ process_impair_update(impairment, &wc, logger); } } } static void process_impair_list(struct logger *logger) { for (unsigned ci = 1; ci < elemsof(impairments); ci++) { const struct impairment *impairment = &impairments[ci]; if (impairment_enabled(impairment)) { LLOG_JAMBUF(RC_LOG, logger, buf) { jam_impairment(buf, impairment); } } } } bool process_impair(const struct whack_impair *wc, void (*action)(enum impair_action impairment_action, unsigned impairment_param, bool whack_enable, unsigned whack_value, bool background, struct logger *logger), bool background, struct logger *logger) { if (wc->what == 0) { /* ignore; silently */ return true; } else if (wc->what == IMPAIR_NONE) { process_impair_none(logger); return true; } else if (wc->what == IMPAIR_LIST) { process_impair_list(logger); return true; } else if (wc->what >= elemsof(impairments)) { llog(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: /* log the update; but not to whack */ process_impair_update(impairment, wc, logger); return true; case CALL_INITIATE_v2_LIVENESS: case CALL_SEND_KEEPALIVE: case CALL_GLOBAL_EVENT_HANDLER: case CALL_STATE_EVENT_HANDLER: case CALL_CONNECTION_EVENT_HANDLER: case CALL_IMPAIR_MESSAGE_DROP: case CALL_IMPAIR_MESSAGE_BLOCK: case CALL_IMPAIR_MESSAGE_DRIP: case CALL_IMPAIR_MESSAGE_DUPLICATE: case CALL_IMPAIR_MESSAGE_REPLAY: if (action == NULL) { llog(DEBUG_STREAM, logger, "no action for impairment %s", impairment->what); return false; } action(impairment->action, impairment->param, wc->enable, wc->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-5.2/lib/libswan/initiated_by_names.c000066400000000000000000000021751475767661000215760ustar00rootroot00000000000000/* tables of names for values defined in constants.h * * Copyright (C) 2023 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY 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 "initiated_by.h" #include "enum_names.h" static const char *initiated_by_name[] = { #define S(E) [E] = #E S(INITIATED_BY_ACQUIRE), S(INITIATED_BY_PEER), S(INITIATED_BY_REPLACE), S(INITIATED_BY_REVIVE), S(INITIATED_BY_UNKNOWN), S(INITIATED_BY_IKE), S(INITIATED_BY_PENDING), S(INITIATED_BY_WHACK), #undef S }; const struct enum_names initiated_by_names = { 0, INITIATED_BY_ROOF-1, ARRAY_REF(initiated_by_name), "INITIATED_BY_", NULL, }; libreswan-5.2/lib/libswan/initsubnet.3.xml000066400000000000000000000137471475767661000206610ustar00rootroot00000000000000 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. AUTHOR Paul Wouters HISTORY Written for the FreeS/WAN project by Henry Spencer.
libreswan-5.2/lib/libswan/ip_address.c000066400000000000000000000143331475767661000200630ustar00rootroot00000000000000/* * 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, const struct ip_info *afi, const struct ip_bytes bytes) { ip_address a = { .is_set = true, .version = afi->ip_version, .bytes = bytes, }; pexpect_address(&a, where); return a; } diag_t data_to_address(const void *data, size_t sizeof_data, const struct ip_info *afi, ip_address *dst) { *dst = unset_address; if (afi == NULL) { return diag("unknown address family"); } /* accept longer! */ if (sizeof_data < afi->ip_size) { return diag("%s address must be %zu bytes, not %zu", afi->ip_name, afi->ip_size, sizeof_data); } struct ip_bytes bytes = unset_ip_bytes; memcpy(bytes.byte, data, afi->ip_size); *dst = address_from_raw(HERE, afi, bytes); return NULL; } 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_info, bytes); } 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_info, 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); } 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) { const struct ip_info *afi = address_type(address); if (afi == NULL) { return jam_string(buf, ""); } return afi->jam.address(buf, afi, &address->bytes); } size_t jam_address_wrapped(struct jambuf *buf, const ip_address *address) { const struct ip_info *afi = address_type(address); if (afi == NULL) { return jam_string(buf, ""); } return afi->jam.address_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_info(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_info(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-5.2/lib/libswan/ip_bytes.c000066400000000000000000000165351475767661000175720ustar00rootroot00000000000000/* 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_routing_prefix_blit { const char *op; uint8_t and; /* first operation */ uint8_t or; /* second operation */ }; struct ip_host_identifier_blit { const char *op; uint8_t and; /* first operation */ uint8_t or; /* second operation */ }; const struct ip_routing_prefix_blit clear_routing_prefix = { .op = "clear", .and = 0x00, .or = 0x00, }; const struct ip_routing_prefix_blit set_routing_prefix = { .op = "set", .and = 0x00, .or = 0xff, }; const struct ip_routing_prefix_blit keep_routing_prefix = { .op = "keep", .and = 0xff, .or = 0x00, }; const struct ip_host_identifier_blit clear_host_identifier = { .op = "clear", .and = 0x00, .or = 0x00, }; const struct ip_host_identifier_blit set_host_identifier = { .op = "set", .and = 0x00, .or = 0xff, }; const struct ip_host_identifier_blit keep_host_identifier = { .op = "keep", .and = 0xff, .or = 0x00, }; struct ip_bytes ip_bytes_blit(const struct ip_info *afi, const struct ip_bytes in, const struct ip_routing_prefix_blit *routing_prefix, const struct ip_host_identifier_blit *host_identifier, int prefix_len) { if (prefix_len < 0 || prefix_len > (int)afi->mask_cnt) { llog_pexpect(&global_logger, HERE, "prefix_len=%d <= afi->mask_cnt=%u prefix=%s host=%s "PRI_IP_BYTES, prefix_len, afi->mask_cnt, routing_prefix->op, host_identifier->op, pri_ip_bytes(in)); return unset_ip_bytes; } 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_len / BITS_IN_BYTE; unsigned xbit = prefix_len % BITS_IN_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_len(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; } int ip_bytes_host_len(const struct ip_info *afi, const struct ip_bytes lo, const struct ip_bytes hi) { int prefix_len = ip_bytes_prefix_len(afi, lo, hi); if (prefix_len < 0) { return -1; } return afi->mask_cnt - prefix_len; } /* -1 if not valid mask */ int ip_bytes_mask_len(const struct ip_info *afi, const struct ip_bytes bytes) { const uint8_t *p = bytes.byte; const uint8_t *stop = bytes.byte + afi->ip_size; /* skip leading 0xff bytes */ int n = 0; while (p < stop && *p == 0xff) { p++; n += 8; } /* boundary in mid-byte? */ if (p < stop && *p != 0) { uint8_t b = *p++; while (b & 0x80) { b <<= 1; n++; } if (b != 0) { return -1; /* bits not contiguous */ } } /* check trailing 0x00 bytes */ while (p < stop && *p == 0) { p++; } if (p != stop) { return -1; } return n; } /* * 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); } size_t jam_ip_bytes_range(struct jambuf *buf, const struct ip_info *afi, const struct ip_bytes lo, const struct ip_bytes hi) { int prefix_len = ip_bytes_prefix_len(afi, lo, hi); size_t s = 0; if (prefix_len >= 0) { /* always
/ */ s += afi->jam.address(buf, afi, &lo); s += jam(buf, "/%u", prefix_len); } else { s += afi->jam.address(buf, afi, &lo); s += jam_string(buf, "-"); s += afi->jam.address(buf, afi, &hi); } return s; } libreswan-5.2/lib/libswan/ip_cidr.c000066400000000000000000000120111475767661000173460ustar00rootroot00000000000000/* ip cidr, for libreswan * * Copyright (C) 2019-2024 Andrew Cagney * Copyright (C) 2023 Brady Johnson * Copyright (C) 2021 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 "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, const struct ip_info *afi, const struct ip_bytes bytes, unsigned prefix_len) { /* combine */ ip_cidr cidr = { .is_set = true, .version = afi->ip_version, .bytes = bytes, .prefix_len = prefix_len, }; pexpect_cidr(cidr, where); return cidr; } diag_t data_to_cidr(const void *data, size_t sizeof_data, unsigned prefix_len, const struct ip_info *afi, ip_cidr *dst) { *dst = unset_cidr; if (afi == NULL) { return diag("unknown CIDR address family"); } /* accept longer! */ if (sizeof_data < afi->ip_size) { return diag("minimum %s CIDR address buffer length is %zu, not %zu", afi->ip_name, afi->ip_size, sizeof_data); } if (prefix_len > afi->mask_cnt) { return diag("maximum %s CIDR prefix length is %u, not %u", afi->ip_name, afi->mask_cnt, prefix_len); } struct ip_bytes bytes = unset_ip_bytes; memcpy(bytes.byte, data, afi->ip_size); *dst = cidr_from_raw(HERE, afi, bytes, prefix_len); return NULL; } ip_cidr cidr_from_address(ip_address address) { const struct ip_info *afi = address_info(address); if (afi == NULL) { return unset_cidr; } /* contains both routing-prefix and host-identifier */ return cidr_from_raw(HERE, afi, address.bytes, afi->mask_cnt/*32|128*/); } 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_info(cidr); if (afi == NULL) { return unset_address; } return address_from_raw(HERE, afi, cidr.bytes); } ip_address cidr_prefix(const ip_cidr cidr) { const struct ip_info *afi = cidr_info(cidr); if (afi == NULL) { return unset_address; } return address_from_raw(HERE, afi, ip_bytes_blit(afi, cidr.bytes, &keep_routing_prefix, &clear_host_identifier, cidr.prefix_len)); } int cidr_prefix_len(const ip_cidr cidr) { return cidr.prefix_len; } err_t cidr_check(const ip_cidr cidr) { if (!cidr.is_set) { return "unset"; } const struct ip_info *afi = cidr_info(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_len == 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_check(cidr) == NULL; } shunk_t cidr_as_shunk(const ip_cidr *cidr) { const struct ip_info *afi = cidr_type(cidr); if (afi == NULL) { return null_shunk; } return shunk2(&cidr->bytes, afi->ip_size); } chunk_t cidr_as_chunk(ip_cidr *cidr) { const struct ip_info *afi = cidr_type(cidr); if (afi == NULL) { /* NULL+unset+unknown */ return empty_chunk; } return chunk2(&cidr->bytes, afi->ip_size); } size_t jam_cidr(struct jambuf *buf, const ip_cidr *cidr) { const struct ip_info *afi = cidr_type(cidr); if (afi == NULL) { 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_len); 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)); } } bool cidr_eq_cidr(const ip_cidr l, const ip_cidr r) { bool l_set = cidr_is_specified(l); bool r_set = cidr_is_specified(r); if (! l_set && ! r_set) { /* unset/NULL addresses are equal */ return true; } if (! l_set || ! r_set) { return false; } /* must compare individual fields */ return (l.version == r.version && l.prefix_len == r.prefix_len && thingeq(l.bytes, r.bytes)); } libreswan-5.2/lib/libswan/ip_encap.c000066400000000000000000000025411475767661000175220ustar00rootroot00000000000000/* 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-5.2/lib/libswan/ip_endpoint.c000066400000000000000000000212201475767661000202470ustar00rootroot00000000000000/* 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, const struct ip_info *afi, const struct ip_bytes bytes, const struct ip_protocol *protocol, ip_port port) { ip_endpoint endpoint = { .is_set = true, .version = afi->ip_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) { const struct ip_info *afi = address_info(address); if (afi == NULL) { /* NULL+unset+unknown */ return unset_endpoint; /* empty_address? */ } return endpoint_from_raw(HERE, afi, address.bytes, protocol, port); } ip_address endpoint_address(const ip_endpoint endpoint) { const struct ip_info *afi = endpoint_info(endpoint); if (afi == NULL) { /* NULL+unset+unknown */ return unset_address; /* empty_address? */ } return address_from_raw(HERE, afi, endpoint.bytes); } int endpoint_hport(const ip_endpoint endpoint) { const struct ip_info *afi = endpoint_info(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_info(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); } ip_endpoint set_endpoint_port(const ip_endpoint endpoint, ip_port port) { const struct ip_info *afi = endpoint_info(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_from_ipproto(endpoint.ipproto); } bool endpoint_is_specified(const ip_endpoint endpoint) { const struct ip_info *afi = endpoint_info(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 as ADDRESS:PORT. * * 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) { const struct ip_info *afi = endpoint_type(endpoint); if (afi == NULL) { return jam_string(buf, ""); } size_t s = 0; s += afi->jam.address_wrapped(buf, afi, &endpoint->bytes); s += jam(buf, ":%d", endpoint->hport); return s; } 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; } /* * Format an endpoint as ADDRESS:PROTOCOL/PORT. * * 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_address_protocol_port(struct jambuf *buf, const ip_endpoint *endpoint) { const struct ip_info *afi = endpoint_type(endpoint); if (afi == NULL) { return jam_string(buf, ""); } size_t s = 0; s += afi->jam.address_wrapped(buf, afi, &endpoint->bytes); s += jam_string(buf, ":"); s += jam_protocol(buf, endpoint_protocol(*endpoint)); s += jam_string(buf, "/"); s += jam_hport(buf, endpoint_port(*endpoint)); return s; } const char *str_endpoint_address_protocol_port(const ip_endpoint *endpoint, endpoint_buf *dst) { struct jambuf buf = ARRAY_AS_JAMBUF(dst->buf); jam_endpoint_address_protocol_port(&buf, endpoint); return dst->buf; } size_t jam_endpoint_address_protocol_port_sensitive(struct jambuf *buf, const ip_endpoint *endpoint) { if (!log_ip) { return jam_string(buf, ""); } return jam_endpoint_address_protocol_port(buf, endpoint); } const char *str_endpoint_address_protocol_port_sensitive(const ip_endpoint *endpoint, endpoint_buf *dst) { struct jambuf buf = ARRAY_AS_JAMBUF(dst->buf); jam_endpoint_address_protocol_port_sensitive(&buf, endpoint); return dst->buf; } size_t jam_endpoint_pair(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 struct ip_protocol *srcp = src != NULL ? endpoint_protocol(*src) : &ip_protocol_all; const struct ip_protocol *dstp = src != NULL ? endpoint_protocol(*dst) : &ip_protocol_all; s += jam_protocol_pair(buf, srcp, '-', dstp); s += jam_char(buf, ' '); s += jam_endpoint(buf, dst); return s; } const char *str_endpoint_pair(const ip_endpoint *src, const ip_endpoint *dst, endpoint_pair_buf *out) { struct jambuf buf = ARRAY_AS_JAMBUF(out->buf); jam_endpoint_pair(&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 struct 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-5.2/lib/libswan/ip_info.c000066400000000000000000000177271475767661000174030ustar00rootroot00000000000000/* 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() */ const struct ip_info unspec_ip_info = { .af = AF_UNSPEC, }; /* * 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; } /* * 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 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_index = IPv4_INDEX, .ip_size = sizeof(struct in_addr), .ip_name = "IPv4", .inet_name = "inet", .mask_cnt = 32, /* formatting */ .jam.address = jam_ipv4_address, .jam.address_wrapped = jam_ipv4_address, /* 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, }, }, }, /* 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, .hi = IPv4_FF, }, /* ip_selector - .selector.any matches grep */ .selector.zero = { .is_set = true, .version = IPv4, }, /* 0.0.0.0/0 */ .selector.all = { .is_set = true, .version = IPv4, .hi = IPv4_FF, }, /* 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, .ikev2_internal_address = IKEv2_INTERNAL_IP4_ADDRESS, .ikev2_internal_dns = IKEv2_INTERNAL_IP4_DNS, /* 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_index = IPv6_INDEX, .ip_size = sizeof(struct in6_addr), .ip_name = "IPv6", .inet_name = "inet6", .mask_cnt = 128, /* formatting */ .jam.address = jam_ipv6_address, .jam.address_wrapped = jam_ipv6_address_wrapped, /* ip_address - .address.any matches grep */ .address.unspec = { .is_set = true, .version = IPv6, }, /* :: */ .address.loopback = { .is_set = true, .version = IPv6, .bytes = { { [15] = 1, }, }, }, /* ::1 */ /* 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, .hi = IPv6_FF, }, /* ip_selector - .selector.any matches grep */ .selector.zero = { .is_set = true, .version = IPv6, }, /* ::/0 */ .selector.all = { .is_set = true, .version = IPv6, .hi = IPv6_FF, }, /* ::/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, .ikev2_internal_address = IKEv2_INTERNAL_IP6_ADDRESS, .ikev2_internal_dns = IKEv2_INTERNAL_IP6_DNS, /* 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(enum ip_version 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-5.2/lib/libswan/ip_packet.c000066400000000000000000000106411475767661000177030ustar00rootroot00000000000000/* 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, 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, 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, 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, packet.src.bytes, packet.src.bytes, 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, packet.dst.bytes, packet.dst.bytes, 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; if (packet->src.hport == 0 && packet->protocol->zero_port_is_any) { /* * SRC port can be zero aka wildcard aka ephemeral, it * isn't know to pluto so denotes any and should be * omitted. * * For IPv6, jam_wrapped() includes includes [] so * output is consistent with endpoint.jam(). */ s += afi->jam.address_wrapped(buf, afi, &packet->src.bytes); } else { s += afi->jam.address_wrapped(buf, afi, &packet->src.bytes); s += jam(buf, ":%u", packet->src.hport); } /* DST port is always valid */ s += jam(buf, "-%s->", packet->protocol->name); s += afi->jam.address_wrapped(buf, afi, &packet->dst.bytes); s += jam(buf, ":%u", 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->zero_port_is_any && 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-5.2/lib/libswan/ip_port.c000066400000000000000000000033561475767661000174250ustar00rootroot00000000000000/* 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; } libreswan-5.2/lib/libswan/ip_port_range.c000066400000000000000000000025721475767661000206000ustar00rootroot00000000000000/* 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-5.2/lib/libswan/ip_protocol.c000066400000000000000000001130331475767661000202740ustar00rootroot00000000000000/* 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, .zero_port_is_any = 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, .zero_port_is_any = 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 = 61, .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_from_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 (hunk_strcaseeat(prefix, p->prefix)) { return p; } } return NULL; } const struct ip_protocol *protocol_from_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_from_ipproto(ipproto); } const struct ip_protocol *protocol_from_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_protocol_pair(struct jambuf *buf, const struct ip_protocol *src, char sep, const struct 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-5.2/lib/libswan/ip_protoport.c000066400000000000000000000066211475767661000205070ustar00rootroot00000000000000/* * 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? */ ip_port port; bool port_wildcard; if (service_name[0] == '\0') { /* allow N/ and N; different to N/%any */ port = unset_port; port_wildcard = false; } else if (streq(service_name, "%any")) { if (protocol->ipproto == 0) { return "port wildcard (%any) requires a valid protocol"; } port = unset_port; port_wildcard = true; } else { /* Port 0-65535 is different to %any */ err = ttoport(shunk1(service_name), &port); if (err != NULL) { return err; } if (protocol->ipproto == 0 && port.hport != 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.hport; 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_from_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-5.2/lib/libswan/ip_range.c000066400000000000000000000234221475767661000175310ustar00rootroot00000000000000/* 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, const struct ip_info *afi, const struct ip_bytes lo, const struct ip_bytes hi) { ip_range r = { .is_set = true, .version = afi->ip_version, .lo = lo, .hi = hi, }; pexpect_range(&r, where); return r; } /* * Calculate the number of significant bits in the size of the range. * floor(lg(|high-low| + 1)); or -1. */ int range_prefix_len(const ip_range range) { const struct ip_info *afi = range_info(range); if (afi == NULL) { /* NULL+unset+unknown */ return -1; } return ip_bytes_prefix_len(afi, range.lo, range.hi); } int range_host_len(const ip_range range) { const struct ip_info *afi = range_info(range); if (afi == NULL) { /* NULL+unset+unknown */ return -1; } return ip_bytes_host_len(afi, range.lo, range.hi); } size_t jam_range(struct jambuf *buf, const ip_range *range) { const struct ip_info *afi = range_type(range); if (afi == NULL) { return jam_string(buf, ""); } return jam_ip_bytes_range(buf, afi, range->lo, range->hi); } 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_info(address); if (afi == NULL) { /* NULL+unset+unknown */ return unset_range; } return range_from_raw(HERE, afi, address.bytes, address.bytes); } ip_range range_from_subnet(const ip_subnet subnet) { const struct ip_info *afi = subnet_info(subnet); if (afi == NULL) { /* NULL+unset+unknown */ return unset_range; } return range_from_raw(HERE, afi, ip_bytes_blit(afi, subnet.bytes, &keep_routing_prefix, &clear_host_identifier, subnet.maskbits), ip_bytes_blit(afi, subnet.bytes, &keep_routing_prefix, &set_host_identifier, 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_info(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_info(range); if (afi == NULL) { return false; } return range_eq_range(range, afi->range.all); } bool range_is_cidr(ip_range range) { const struct ip_info *afi = range_info(range); if (afi == NULL) { return false; } return ip_bytes_prefix_len(afi, range.lo, range.hi) >= 0; } uintmax_t range_size(const ip_range range) { const struct ip_info *afi = range_info(range); if (afi == NULL) { return 0; } struct ip_bytes diff_bytes = ip_bytes_sub(afi, range.hi, range.lo); /* 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 = raw_ntoh(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.lo, r.version, r.lo) == 0 && ip_bytes_cmp(l.version, l.hi, r.version, r.hi) == 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.lo, outer.version, outer.lo) >= 0 && ip_bytes_cmp(inner.version, inner.hi, outer.version, outer.hi) <= 0); } ip_address range_start(const ip_range range) { const struct ip_info *afi = range_info(range); if (afi == NULL) { return unset_address; } return address_from_raw(HERE, afi, range.lo); } ip_address range_end(const ip_range range) { const struct ip_info *afi = range_info(range); if (afi == NULL) { return unset_address; } return address_from_raw(HERE, afi, range.hi); } 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.hi, r.version, r.lo) < 0) { return false; } /* l after r */ if (ip_bytes_cmp(l.version, l.lo, r.version, r.hi) > 0) { return false; } return true; } err_t addresses_to_nonzero_range(const ip_address lo, const ip_address hi, ip_range *dst) { *dst = unset_range; const struct ip_info *lo_afi = address_info(lo); if (lo_afi == NULL) { /* NULL+unset+unknown */ return "start address invalid"; } const struct ip_info *hi_afi = address_info(hi); if (hi_afi == NULL) { /* NULL+unset+unknown */ return "end address invalid"; } if (lo_afi != hi_afi) { return "conflicting address types"; } /* reject both 0 */ if (thingeq(lo.bytes, unset_ip_bytes) && thingeq(hi.bytes, unset_ip_bytes)) { return "zero address range"; } if (addrcmp(&lo, &hi) > 0) { return "out-of-order"; } *dst = range_from_raw(HERE, lo_afi, lo.bytes, hi.bytes); return NULL; } err_t range_to_subnet(const ip_range range, ip_subnet *dst) { *dst = unset_subnet; const struct ip_info *afi = range_info(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_len(afi, range.lo, range.hi); if (prefix_bits < 0) { return "address range is not a subnet"; } *dst = subnet_from_raw(HERE, afi, range.lo, 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_info(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.lo.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, afi, 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_info(range); if (afi == NULL) { return "range invalid"; } if (address_info(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.lo); *offset = raw_ntoh(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->lo, r->version, r->hi) > 0) { llog_pexpect(&global_logger, where, "invalid range: "PRI_RANGE, pri_range(r)); } } libreswan-5.2/lib/libswan/ip_said.c000066400000000000000000000066031475767661000173570ustar00rootroot00000000000000/* 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, const struct ip_info *afi, const struct ip_bytes dst, const struct ip_protocol *protocol, ipsec_spi_t spi) { ip_said said = { .is_set = true, .version = afi->ip_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) { const struct ip_info *afi = address_info(address); if (afi == NULL) { /* NULL+unset+unknown */ return unset_said; } return said_from_raw(HERE, afi, 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, ""); } 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->jam.address(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_info(said); if (afi == NULL) { /* NULL+unset+unknown */ return unset_address; /* empty_address? */ } return address_from_raw(HERE, afi, said.dst); } const struct ip_protocol *said_protocol(const ip_said said) { if (said_is_unset(&said)) { return NULL; } return protocol_from_ipproto(said.ipproto); } libreswan-5.2/lib/libswan/ip_selector.c000066400000000000000000000375051475767661000202640ustar00rootroot00000000000000/* 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_info(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_info(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_info(selector); if (afi == NULL) { /* NULL+unset+unknown */ return false; } /* Unlike subnetishost() this rejects 0.0.0.0/32. */ if (thingeq(selector.hi, unset_ip_bytes)) { /* Since .hi is zero, so must .lo */ return false; } return (thingeq(selector.lo, selector.hi) && selector.ipproto == 0 && selector.hport == 0); } size_t jam_selector(struct jambuf *buf, const ip_selector *selector) { const struct ip_info *afi = selector_type(selector); if (afi == NULL) { return jam_string(buf, ""); } size_t s = 0; s += jam_ip_bytes_range(buf, afi, selector->lo, selector->hi); /* optionally // */ if (selector->ipproto != 0 || selector->hport != 0) { const struct ip_protocol *protocol = selector_protocol(*selector); if (selector->hport == 0 && protocol->zero_port_is_any) { s += jam(buf, "/%s", protocol->name); } else { s += jam(buf, "/%s/%d", protocol->name, 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_range(struct jambuf *buf, const ip_selector *selector) { const struct ip_info *afi = selector_type(selector); if (afi == NULL) { return jam_string(buf, ""); } return jam_ip_bytes_range(buf, afi, selector->lo, selector->hi); } const char *str_selector_range(const ip_selector *selector, subnet_buf *out) { struct jambuf buf = ARRAY_AS_JAMBUF(out->buf); jam_selector_range(&buf, selector); return out->buf; } size_t jam_selector_range_port(struct jambuf *buf, const ip_selector *selector) { const struct ip_info *afi = selector_type(selector); if (afi == NULL) { return jam_string(buf, ""); } size_t s = 0; s += jam_ip_bytes_range(buf, afi, selector->lo, selector->hi); if (selector->ipproto != 0 || selector->hport != 0) { s += jam(buf, ":%d", selector->hport); } return s; } const char *str_selector_range_port(const ip_selector *selector, selector_buf *out) { struct jambuf buf = ARRAY_AS_JAMBUF(out->buf); jam_selector_range_port(&buf, selector); return out->buf; } size_t jam_selector_pair(struct jambuf *buf, const ip_selector *src, const ip_selector *dst) { if (selector_is_unset(src) || selector_is_unset(dst)) { return jam_string(buf, ""); } size_t s = 0; const char *sep = ""; FOR_EACH_THING(selector, src, dst) { s += jam_string(buf, sep); sep = "==="; jam_selector(buf, selector); } return s; } const char *str_selector_pair(const ip_selector *src, const ip_selector *dst, selector_pair_buf *out) { struct jambuf buf = ARRAY_AS_JAMBUF(out->buf); jam_selector_pair(&buf, src, dst); return out->buf; } size_t jam_selector_pair_sensitive(struct jambuf *buf, const ip_selector *src, const ip_selector *dst) { if(!log_ip) { return jam_string(buf, ""); } return jam_selector_pair(buf, src, dst); } const char *str_selector_pair_sensitive(const ip_selector *src, const ip_selector *dst, selector_pair_buf *out) { struct jambuf buf = ARRAY_AS_JAMBUF(out->buf); jam_selector_pair_sensitive(&buf, src, dst); return out->buf; } size_t jam_selectors(struct jambuf *buf, ip_selectors selectors) { size_t s = 0; s += jam_string(buf, "["); const char *sep = ""; for (unsigned i = 0; i < selectors.len; i++) { s += jam_string(buf, sep); sep = " "; s += jam_selector(buf, &selectors.list[i]); } s += jam_string(buf, "]"); return s; } ip_selector selector_from_raw(where_t where, const struct ip_info *afi, const struct ip_bytes lo, const struct ip_bytes hi, const struct ip_protocol *protocol, const ip_port port) { ip_selector selector = { .is_set = true, .version = afi->ip_version, .lo = lo, .hi = hi, .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_info(address); if (afi == NULL) { return unset_selector; } return selector_from_raw(HERE, afi, address.bytes, address.bytes, &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_info(address); if (afi == NULL) { return unset_selector; } return selector_from_raw(HERE, afi, address.bytes, address.bytes, 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_info(address); if (afi == NULL) { return unset_selector; } return selector_from_raw(HERE, afi, address.bytes, address.bytes, protocol, port); } ip_selector selector_from_endpoint(const ip_endpoint endpoint) { const struct ip_info *afi = endpoint_info(endpoint); if (afi == NULL) { return unset_selector; } return selector_from_raw(HERE, afi, endpoint.bytes, endpoint.bytes, endpoint_protocol(endpoint), endpoint_port(endpoint)); } ip_selector selector_from_cidr(const ip_cidr cidr) { const struct ip_info *afi = cidr_info(cidr); if (afi == NULL) { return unset_selector; } struct ip_bytes lo = ip_bytes_blit(afi, cidr.bytes, &keep_routing_prefix, &clear_host_identifier, cidr.prefix_len); struct ip_bytes hi = ip_bytes_blit(afi, cidr.bytes, &keep_routing_prefix, &set_host_identifier, cidr.prefix_len); return selector_from_raw(HERE, afi, lo, hi, &ip_protocol_all, unset_port); } ip_selector selector_from_subnet(const ip_subnet subnet) { const struct ip_info *afi = subnet_info(subnet); if (afi == NULL) { return unset_selector; } struct ip_bytes lo = ip_bytes_blit(afi, subnet.bytes, &keep_routing_prefix, &clear_host_identifier, subnet.maskbits); struct ip_bytes hi = ip_bytes_blit(afi, subnet.bytes, &keep_routing_prefix, &set_host_identifier, subnet.maskbits); return selector_from_raw(HERE, afi, lo, hi, &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) { const struct ip_info *afi = subnet_info(subnet); if (afi == NULL) { return unset_selector; } struct ip_bytes lo = ip_bytes_blit(afi, subnet.bytes, &keep_routing_prefix, &clear_host_identifier, subnet.maskbits); struct ip_bytes hi = ip_bytes_blit(afi, subnet.bytes, &keep_routing_prefix, &set_host_identifier, subnet.maskbits); return selector_from_raw(HERE, afi, lo, hi, 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) { const struct ip_info *afi = range_info(range); if (afi == NULL) { return unset_selector; } return selector_from_raw(HERE, afi, range.lo, range.hi, 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_from_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 struct ip_protocol *selector_protocol(const ip_selector selector) { if (selector_is_unset(&selector)) { return NULL; } return protocol_from_ipproto(selector.ipproto); } ip_range selector_range(const ip_selector selector) { const struct ip_info *afi = selector_info(selector); if (afi == NULL) { /* NULL+unset+unknown */ return unset_range; } return range_from_raw(HERE, afi, selector.lo, selector.hi); } ip_address selector_prefix(const ip_selector selector) { const struct ip_info *afi = selector_info(selector); if (afi == NULL) { /* NULL+unset+unknown */ return unset_address; } return address_from_raw(HERE, afi, selector.lo); } int selector_prefix_len(const ip_selector selector) { const struct ip_info *afi = selector_info(selector); if (afi == NULL) { /* NULL+unset+unknown */ return -1; } return ip_bytes_prefix_len(afi, selector.lo, selector.hi); } int selector_host_len(const ip_selector selector) { const struct ip_info *afi = selector_info(selector); if (afi == NULL) { /* NULL+unset+unknown */ return -1; } return ip_bytes_host_len(afi, selector.lo, selector.hi); } ip_address selector_prefix_mask(const ip_selector selector) { const struct ip_info *afi = selector_info(selector); if (afi == NULL) { /* NULL+unset+unknown */ return unset_address; } int prefix_len = ip_bytes_prefix_len(afi, selector.lo, selector.hi); if (prefix_len < 0) { selector_buf sb; prefix_len = afi->mask_cnt; llog_pexpect(&global_logger, HERE, "attempt to extract prefix mask from non-CIDR selector %s, forcing prefix-len=%d", str_selector(&selector, &sb), prefix_len); } struct ip_bytes prefix = ip_bytes_blit(afi, selector.lo, &set_routing_prefix, &clear_host_identifier, prefix_len); return address_from_raw(HERE, afi, 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_info(i); if (afi == NULL) { /* NULL+unset+unknown */ return false; } /* version wild card? (actually version is 4/6) */ /* work in */ if (selector_info(o) != afi) { return false; } /* I.lo >= O.lo && I.hi <= O.hi */ if (ip_bytes_cmp(i.version, i.lo, o.version, o.lo) < 0) { return false; } if (ip_bytes_cmp(i.version, i.hi, o.version, o.hi) > 0) { return false; } /* protocol or wildcard 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_range range = selector_range(selector); return address_in_range(address, range); } 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.lo, r.lo) && thingeq(l.hi, r.hi) && 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; } ip_subnet selector_subnet(const ip_selector selector) { const struct ip_info *afi = selector_info(selector); if (afi == NULL) { return unset_subnet; } int prefix_len = ip_bytes_prefix_len(afi, selector.lo, selector.hi); if (prefix_len < 0) { selector_buf sb; prefix_len = afi->mask_cnt; llog_pexpect(&global_logger, HERE, "attempt to extract subnet from non-CIDR selector %s, forcing prefix-len=%u", str_selector(&selector, &sb), prefix_len); } return subnet_from_raw(HERE, afi, selector.lo, prefix_len); } 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); } libreswan-5.2/lib/libswan/ip_sockaddr.c000066400000000000000000000063041475767661000202270ustar00rootroot00000000000000/* 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_info(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-5.2/lib/libswan/ip_subnet.c000066400000000000000000000166341475767661000177440ustar00rootroot00000000000000/* 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, const struct ip_info *afi, const struct ip_bytes bytes, unsigned prefix_len) { ip_subnet s = { .is_set = true, .version = afi->ip_version, .bytes = bytes, .maskbits = prefix_len, }; pexpect_subnet(&s, where); return s; } ip_subnet subnet_from_address(const ip_address address) { const struct ip_info *afi = address_info(address); if (afi == NULL) { return unset_subnet; } return subnet_from_raw(HERE, afi, address.bytes, afi->mask_cnt); } ip_subnet subnet_from_cidr(const ip_cidr cidr) { const struct ip_info *afi = cidr_info(cidr); if (afi == NULL) { return unset_subnet; } return subnet_from_raw(HERE, afi, ip_bytes_blit(afi, cidr.bytes, &keep_routing_prefix, &clear_host_identifier, cidr.prefix_len), cidr.prefix_len); } 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_info(address); if (afi == NULL) { return "invalid address"; } if (address_info(mask) != afi) { return "invalid mask"; } int prefix_len = ip_bytes_mask_len(afi, mask.bytes); if (prefix_len < 0) { return "invalid mask"; } struct ip_bytes prefix = ip_bytes_blit(afi, address.bytes, &keep_routing_prefix, &clear_host_identifier, prefix_len); *subnet = subnet_from_raw(HERE, afi, prefix, prefix_len); return NULL; } ip_address subnet_prefix(const ip_subnet subnet) { const struct ip_info *afi = subnet_info(subnet); if (afi == NULL) { /* NULL+unset+unknown */ return unset_address; } struct ip_bytes prefix = ip_bytes_blit(afi, subnet.bytes, &keep_routing_prefix, &clear_host_identifier, subnet.maskbits); return address_from_raw(HERE, afi, 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_info(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_info(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_info(subnet); if (afi == NULL) { /* NULL+unset+unknown */ return unset_address; } struct ip_bytes mask = ip_bytes_blit(afi, subnet.bytes, &set_routing_prefix, &clear_host_identifier, subnet.maskbits); return address_from_raw(HERE, afi, mask); } unsigned subnet_prefix_bits(const ip_subnet subnet) { return subnet.maskbits; } size_t jam_subnet(struct jambuf *buf, const ip_subnet *subnet) { 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; } size_t jam_subnets(struct jambuf *buf, ip_subnets subnets) { size_t s = 0; const char *sep = ""; for (unsigned i = 0; i < subnets.len; i++) { s += jam_string(buf, sep); sep = ","; s += jam_subnet(buf, &subnets.list[i]); } return s; } 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_info(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_info(l); if (afi == NULL) { return false; } if (subnet_info(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_blit(afi, /*LEFT*/l.bytes, &keep_routing_prefix, &clear_host_identifier, /*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_info(l); if (afi == NULL) { return false; } if (subnet_info(r) != afi) { return false; } /* L.prefix[0 .. R.bits] == R.prefix[0.. R.bits] */ struct ip_bytes lb = ip_bytes_blit(afi, /*LEFT*/l.bytes, &keep_routing_prefix, &clear_host_identifier, /*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-5.2/lib/libswan/ipsec_addrbytesof.3000066400000000000000000000000321475767661000213460ustar00rootroot00000000000000.so man3/ipsec_initaddr.3 libreswan-5.2/lib/libswan/ipsec_addrbytesptr.3000066400000000000000000000000321475767661000215470ustar00rootroot00000000000000.so man3/ipsec_initaddr.3 libreswan-5.2/lib/libswan/ipsec_addrcmp.3000066400000000000000000000000321475767661000204520ustar00rootroot00000000000000.so man3/ipsec_sameaddr.3 libreswan-5.2/lib/libswan/ipsec_addrinsubnet.3000066400000000000000000000000321475767661000215220ustar00rootroot00000000000000.so man3/ipsec_sameaddr.3 libreswan-5.2/lib/libswan/ipsec_addrlenof.3000066400000000000000000000000321475767661000207760ustar00rootroot00000000000000.so man3/ipsec_initaddr.3 libreswan-5.2/lib/libswan/ipsec_addrtoa.3000066400000000000000000000000311475767661000204550ustar00rootroot00000000000000.so man3/ipsec_atoaddr.3 libreswan-5.2/lib/libswan/ipsec_addrtosubnet.3000066400000000000000000000000341475767661000215400ustar00rootroot00000000000000.so man3/ipsec_initsubnet.3 libreswan-5.2/lib/libswan/ipsec_addrtot.3000066400000000000000000000000311475767661000205000ustar00rootroot00000000000000.so man3/ipsec_ttoaddr.3 libreswan-5.2/lib/libswan/ipsec_addrtypeof.3000066400000000000000000000000321475767661000212010ustar00rootroot00000000000000.so man3/ipsec_initaddr.3 libreswan-5.2/lib/libswan/ipsec_atoasr.3000066400000000000000000000135431475767661000203440ustar00rootroot00000000000000'\" 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-5.2/lib/libswan/ipsec_atosubnet.3000066400000000000000000000000311475767661000210430ustar00rootroot00000000000000.so man3/ipsec_atoaddr.3 libreswan-5.2/lib/libswan/ipsec_bitstomask.3000066400000000000000000000000321475767661000212200ustar00rootroot00000000000000.so man3/ipsec_goodmask.3 libreswan-5.2/lib/libswan/ipsec_broadcastof.3000066400000000000000000000000321475767661000213270ustar00rootroot00000000000000.so man3/ipsec_subnetof.3 libreswan-5.2/lib/libswan/ipsec_datatot.3000066400000000000000000000000311475767661000204770ustar00rootroot00000000000000.so man3/ipsec_ttodata.3 libreswan-5.2/lib/libswan/ipsec_hostof.3000066400000000000000000000000321475767661000203420ustar00rootroot00000000000000.so man3/ipsec_subnetof.3 libreswan-5.2/lib/libswan/ipsec_initsaid.3000066400000000000000000000000271475767661000206500ustar00rootroot00000000000000.so man3/ipsec_ttosa.3 libreswan-5.2/lib/libswan/ipsec_isanyaddr.3000066400000000000000000000000311475767661000210150ustar00rootroot00000000000000.so man3/ipsec_anyaddr.3 libreswan-5.2/lib/libswan/ipsec_isloopbackaddr.3000066400000000000000000000000311475767661000220200ustar00rootroot00000000000000.so man3/ipsec_anyaddr.3 libreswan-5.2/lib/libswan/ipsec_isunspecaddr.3000066400000000000000000000000311475767661000215230ustar00rootroot00000000000000.so man3/ipsec_anyaddr.3 libreswan-5.2/lib/libswan/ipsec_loopbackaddr.3000066400000000000000000000000311475767661000214640ustar00rootroot00000000000000.so man3/ipsec_anyaddr.3 libreswan-5.2/lib/libswan/ipsec_maskof.3000066400000000000000000000000341475767661000203220ustar00rootroot00000000000000.so man3/ipsec_initsubnet.3 libreswan-5.2/lib/libswan/ipsec_masktobits.3000066400000000000000000000000321475767661000212200ustar00rootroot00000000000000.so man3/ipsec_goodmask.3 libreswan-5.2/lib/libswan/ipsec_masktocount.3000066400000000000000000000000341475767661000214110ustar00rootroot00000000000000.so man3/ipsec_initsubnet.3 libreswan-5.2/lib/libswan/ipsec_networkof.3000066400000000000000000000000341475767661000210600ustar00rootroot00000000000000.so man3/ipsec_initsubnet.3 libreswan-5.2/lib/libswan/ipsec_prng_bytes.3000066400000000000000000000000331475767661000212150ustar00rootroot00000000000000.so man3/ipsec_prng_init.3 libreswan-5.2/lib/libswan/ipsec_prng_final.3000066400000000000000000000000331475767661000211600ustar00rootroot00000000000000.so man3/ipsec_prng_init.3 libreswan-5.2/lib/libswan/ipsec_prng_init.3000066400000000000000000000120061475767661000210350ustar00rootroot00000000000000'\" 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-5.2/lib/libswan/ipsec_rangetoa.3000066400000000000000000000000301475767661000206360ustar00rootroot00000000000000.so man3/ipsec_atoasr.3 libreswan-5.2/lib/libswan/ipsec_sameaddrtype.3000066400000000000000000000000321475767661000215220ustar00rootroot00000000000000.so man3/ipsec_sameaddr.3 libreswan-5.2/lib/libswan/ipsec_samesaid.3000066400000000000000000000000321475767661000206260ustar00rootroot00000000000000.so man3/ipsec_sameaddr.3 libreswan-5.2/lib/libswan/ipsec_samesubnet.3000066400000000000000000000000321475767661000212060ustar00rootroot00000000000000.so man3/ipsec_sameaddr.3 libreswan-5.2/lib/libswan/ipsec_samesubnettype.3000066400000000000000000000000321475767661000221100ustar00rootroot00000000000000.so man3/ipsec_sameaddr.3 libreswan-5.2/lib/libswan/ipsec_satot.3000066400000000000000000000000271475767661000201760ustar00rootroot00000000000000.so man3/ipsec_ttosa.3 libreswan-5.2/lib/libswan/ipsec_setportof.3000066400000000000000000000000301475767661000210630ustar00rootroot00000000000000.so man3/ipsec_portof.3 libreswan-5.2/lib/libswan/ipsec_sockaddrlenof.3000066400000000000000000000000301475767661000216540ustar00rootroot00000000000000.so man3/ipsec_portof.3 libreswan-5.2/lib/libswan/ipsec_sockaddrof.3000066400000000000000000000000301475767661000211550ustar00rootroot00000000000000.so man3/ipsec_portof.3 libreswan-5.2/lib/libswan/ipsec_splitkeytoid.3000066400000000000000000000000351475767661000215670ustar00rootroot00000000000000.so man3/ipsec_keyblobtoid.3 libreswan-5.2/lib/libswan/ipsec_subnetinsubnet.3000066400000000000000000000000321475767661000221100ustar00rootroot00000000000000.so man3/ipsec_sameaddr.3 libreswan-5.2/lib/libswan/ipsec_subnetishost.3000066400000000000000000000000321475767661000215720ustar00rootroot00000000000000.so man3/ipsec_sameaddr.3 libreswan-5.2/lib/libswan/ipsec_subnettoa.3000066400000000000000000000000311475767661000210430ustar00rootroot00000000000000.so man3/ipsec_atoaddr.3 libreswan-5.2/lib/libswan/ipsec_subnettot.3000066400000000000000000000000311475767661000210660ustar00rootroot00000000000000.so man3/ipsec_ttoaddr.3 libreswan-5.2/lib/libswan/ipsec_subnettypeof.3000066400000000000000000000000341475767661000215710ustar00rootroot00000000000000.so man3/ipsec_initsubnet.3 libreswan-5.2/lib/libswan/ipsec_tnatoaddr.3000066400000000000000000000000311475767661000210170ustar00rootroot00000000000000.so man3/ipsec_ttoaddr.3 libreswan-5.2/lib/libswan/ipsec_ttosubnet.3000066400000000000000000000000311475767661000210660ustar00rootroot00000000000000.so man3/ipsec_ttoaddr.3 libreswan-5.2/lib/libswan/ipsec_ultot.3000066400000000000000000000000271475767661000202130ustar00rootroot00000000000000.so man3/ipsec_ttoul.3 libreswan-5.2/lib/libswan/ipsec_unspecaddr.3000066400000000000000000000000311475767661000211670ustar00rootroot00000000000000.so man3/ipsec_anyaddr.3 libreswan-5.2/lib/libswan/ipsec_version_code.3000066400000000000000000000044011475767661000215230ustar00rootroot00000000000000'\" 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-5.2/lib/libswan/ipsec_version_string.3000066400000000000000000000000361475767661000221170ustar00rootroot00000000000000.so man3/ipsec_version_code.3 libreswan-5.2/lib/libswan/ipseckey_algorithm_config_names.c000066400000000000000000000022701475767661000243350ustar00rootroot00000000000000/* 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-5.2/lib/libswan/ipseckey_algorithm_type_names.c000066400000000000000000000022651475767661000240550ustar00rootroot00000000000000/* 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-5.2/lib/libswan/jam_base64_bytes.c000066400000000000000000000023431475767661000210650ustar00rootroot00000000000000/* 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" #include "lswalloc.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. */ size_t base64_len = size * 8 / 6 + 1 + 10; char *base64_ptr = alloc_things(char, base64_len, "base64"); size_t length = datatot(ptr, size, 64, base64_ptr, base64_len); passert(length < base64_len); jam_raw_bytes(buf, base64_ptr, length); pfree(base64_ptr); return length; } libreswan-5.2/lib/libswan/jam_bytes.c000066400000000000000000000116401475767661000177210ustar00rootroot00000000000000/* 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. * * 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 * * hence need to pass to characters to jam_sanitized_char(). */ static size_t jam_control(struct jambuf *buf, char c, char c1) { switch (c) { case '\0': return jam_string(buf, "\\0"); case '\a': return jam_string(buf, "\\a"); case '\b': return jam_string(buf, "\\b"); case '\t': return jam_string(buf, "\\t"); case '\n': return jam_string(buf, "\\n"); case '\v': return jam_string(buf, "\\v"); case '\f': return jam_string(buf, "\\f"); case '\r': return jam_string(buf, "\\r"); } if (char_isdigit(c1)) { /* force \OOO when next char is digit */ return jam(buf, "\\%03o", c & 0xFF); } return jam(buf, "\\%o", c & 0xFF); } 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]; if (char_isprint(c)) { n += jam_char(buf, c); } else { /* handle \0001 */ char c1 = (i + 1 == size ? '\0' : chars[i+1]); n += jam_control(buf, c, c1); } } 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; } size_t jam_uppercase_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]; if (char_isprint(c)) { n += jam_char(buf, char_toupper(c)); } else { /* handles \0001 */ char c1 = (i + 1 == size ? '\0' : chars[i+1]); n += jam_control(buf, c, c1); } } return n; } size_t jam_string_uppercase(struct jambuf *buf, const char *string) { return jam_uppercase_bytes(buf, string, strlen(string)); } size_t jam_human_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]; if (c == '_') { n += jam_char(buf, '-'); } else if (char_isprint(c)) { n += jam_char(buf, char_tolower(c)); } else { /* handles \0001 */ char c1 = (i + 1 == size ? '\0' : chars[i+1]); n += jam_control(buf, c, c1); } } return n; } size_t jam_string_human(struct jambuf *buf, const char *string) { if (string == NULL) { /* will inject "(null)" or error */ return jam_string(buf, NULL); } return jam_human_bytes(buf, string, strlen(string)); } libreswan-5.2/lib/libswan/jam_humber.c000066400000000000000000000035051475767661000200560ustar00rootroot00000000000000/* 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" /* * 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. */ size_t jam_humber(struct jambuf *buf, uintmax_t num) { /* in assending order */ static const struct { uintmax_t binary_per; const char *suffix; } map[] = { { .binary_per = binary_per_exa, .suffix = "Ei", }, { .binary_per = binary_per_peta, .suffix = "Pi", }, { .binary_per = binary_per_tera, .suffix = "Ti", }, { .binary_per = binary_per_giga, .suffix = "Gi", }, { .binary_per = binary_per_mega, .suffix = "Mi", }, { .binary_per = binary_per_kilo, .suffix = "Ki", }, }; const char *suffix = ""; uint64_t to_print = num; FOR_EACH_ELEMENT(m, map) { if (num > m->binary_per) { to_print = num / m->binary_per; suffix = m->suffix; break; } } /* fractions? */ 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-5.2/lib/libswan/jam_logger.c000066400000000000000000000022121475767661000200450ustar00rootroot00000000000000/* logging, for libreswan * * Copyright (C) 2023 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY 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 "lswlog.h" size_t jam_prefix(struct jambuf *buf, const struct logger *logger) { return logger->object_vec->jam_object_prefix(buf, logger->object); } const char *str_prefix(const struct logger *logger, prefix_buf *buf) { struct jambuf jb = ARRAY_AS_JAMBUF(buf->buf); jam_prefix(&jb, logger); return buf->buf; } size_t jam_logger_prefix(struct jambuf *buf, const struct logger *logger) { size_t s = jam_prefix(buf, logger); if (s > 0) { s += jam_string(buf, ": "); } return s; } libreswan-5.2/lib/libswan/jam_logger_rc_prefix.c000066400000000000000000000041361475767661000221150ustar00rootroot00000000000000/* logging, 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 /* for abort() */ #include "lswlog.h" /* XXX: The message format is: * FATAL ERROR: * EXPECTATION FAILED: * | * and not: * FATAL ERROR: * | * EXPECTATION_FAILED: * say */ static void jam_stream_prefix(struct jambuf *buf, enum stream stream) { switch (stream) { case DEBUG_STREAM: jam_string(buf, DEBUG_PREFIX); return; case PEXPECT_STREAM: jam_string(buf, PEXPECT_PREFIX); return; case PASSERT_STREAM: jam_string(buf, PASSERT_PREFIX); return; case FATAL_STREAM: jam_string(buf, FATAL_PREFIX); return; case ERROR_STREAM: return; case ALL_STREAMS: case LOG_STREAM: case WHACK_STREAM: case NO_STREAM: return; } abort(); /* not bad_case(stream) as recursive */ } void jam_logger_rc_prefix(struct jambuf *buf, const struct logger *logger, lset_t rc_flags) { enum log_prefix prefix = (rc_flags & LOG_PREFIX_MASK); enum stream stream = (rc_flags & STREAM_MASK); switch (prefix) { case NO_PREFIX: return; case ADD_PREFIX: jam_stream_prefix(buf, stream); jam_logger_prefix(buf, logger); return; case AUTO_PREFIX: jam_stream_prefix(buf, stream); if (stream != DEBUG_STREAM || DBGP(DBG_ADD_PREFIX) || logger->debugging != LEMPTY) { jam_logger_prefix(buf, logger); } return; } abort(); /* not bad_case(stream) as recursive */ } libreswan-5.2/lib/libswan/jam_nss_cka.c000066400000000000000000000030201475767661000202050ustar00rootroot00000000000000/* 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) { /* Not using #T + strlen("CKA_") because of clang's -Wstring-plus-int */ #define CASE(T) case T: return jam_string(buf, &#T[strlen("CKA_")]) CK_ATTRIBUTE_TYPE cka_nss = (attribute & CKA_NSS_MESSAGE_MASK); attribute &= ~CKA_NSS_MESSAGE_MASK; if (cka_nss != 0) { switch (cka_nss) { CASE(CKA_NSS_MESSAGE); CASE(CKA_DIGEST); default: return jam(buf, "CKA_%08lx", (long)attribute); } jam_string(buf, "|"); } switch (attribute) { 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); default: return jam(buf, "CKA_%08lx", (long)attribute); } #undef CASE } libreswan-5.2/lib/libswan/jam_nss_ckf.c000066400000000000000000000023561475767661000202250ustar00rootroot00000000000000/* 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-5.2/lib/libswan/jam_nss_ckg.c000066400000000000000000000022631475767661000202230ustar00rootroot00000000000000/* Output the decoded NSS CK_GENERATE_FUNCTION, for libreswan * * Copyright (C) 2024 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT 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_ckg(struct jambuf *buf, CK_GENERATOR_FUNCTION generator) { switch (generator) { /* Not using #T + strlen("CKG_") because of clang's -Wstring-plus-int */ #define CASE(T) case T: return jam_string(buf, &#T[strlen("CKG_")]) CASE(CKG_NO_GENERATE); CASE(CKG_GENERATE); CASE(CKG_GENERATE_COUNTER); CASE(CKG_GENERATE_COUNTER_XOR); CASE(CKG_GENERATE_RANDOM); default: return jam(buf, "CKG_%08lx", (long)generator); } #undef CASE } libreswan-5.2/lib/libswan/jam_nss_ckm.c000066400000000000000000000052071475767661000202320ustar00rootroot00000000000000/* 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: \ buf->buf = &#T[strlen("CKM_")]; \ break 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->tmp, sizeof(buf->tmp), "CKM_%08lx", (long)mechanism); buf->buf = buf->tmp; } 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-5.2/lib/libswan/jam_nss_error.c000066400000000000000000000037201475767661000206070ustar00rootroot00000000000000/* 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-5.2/lib/libswan/jam_nss_oid.c000066400000000000000000000022721475767661000202320ustar00rootroot00000000000000/* 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 *b) { SECOidData *data = SECOID_FindOIDByTag(oidtag); if (data != NULL) { b->buf = data->desc; } else { snprintf(b->tmp, sizeof(b->tmp), "SEC_OID_%d", oidtag); b->buf = b->tmp; } return b->tmp; } 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-5.2/lib/libswan/jam_nss_secitem.c000066400000000000000000000030111475767661000211000ustar00rootroot00000000000000/* 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-5.2/lib/libswan/jambuf.c000066400000000000000000000200161475767661000172050ustar00rootroot00000000000000/* 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-5.2/lib/libswan/kernel_mode.c000066400000000000000000000025761475767661000202400ustar00rootroot00000000000000/* kernel mode, for libreswan * * Copyright (C) 2024 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include "kernel_mode.h" #include "lswcdefs.h" /* for ARRAY_REF */ #include "enum_names.h" static const char *kernel_mode_name[] = { #define S(E) [E-KERNEL_MODE_TRANSPORT] = #E S(KERNEL_MODE_TRANSPORT), S(KERNEL_MODE_TUNNEL), S(KERNEL_MODE_IPTFS), #undef S }; const struct enum_names kernel_mode_names = { KERNEL_MODE_FLOOR, KERNEL_MODE_ROOF-1, ARRAY_REF(kernel_mode_name), .en_prefix = "KERNEL_MODE_", }; static const char *kernel_mode_story[] = { #define S(E,T) [E-KERNEL_MODE_TRANSPORT] = T S(KERNEL_MODE_TRANSPORT, "Transport Mode"), S(KERNEL_MODE_TUNNEL, "Tunnel Mode"), S(KERNEL_MODE_IPTFS, "IP-TFS Mode"), #undef S }; const struct enum_names kernel_mode_stories = { KERNEL_MODE_FLOOR, KERNEL_MODE_ROOF-1, ARRAY_REF(kernel_mode_story), .en_prefix = NULL, }; libreswan-5.2/lib/libswan/kernel_netlink_query.c000066400000000000000000000031041475767661000221710ustar00rootroot00000000000000/* * 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, const 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-5.2/lib/libswan/kernel_netlink_reply.c000066400000000000000000000042641475767661000221670ustar00rootroot00000000000000/* * 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 netlink query()"); memcpy(newbuf, *pbuf, msglen); pfree(*pbuf); *pbuf = newbuf; } } return msglen; } libreswan-5.2/lib/libswan/keyblobtoid.3.xml000066400000000000000000000121041475767661000207660ustar00rootroot00000000000000 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. AUTHOR Paul Wouters HISTORY Written for the FreeS/WAN project by Henry Spencer. libreswan-5.2/lib/libswan/keyid.c000066400000000000000000000044031475767661000170500ustar00rootroot00000000000000/* 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-5.2/lib/libswan/ldbg.c000066400000000000000000000030031475767661000166460ustar00rootroot00000000000000/* logging, 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 "lswlog.h" void ldbg(const struct logger *logger, const char *message, ...) { if (LDBGP(DBG_BASE, logger)) { va_list ap; va_start(ap, message); llog_va_list(DEBUG_STREAM, logger, message, ap); va_end(ap); } } void pdbg(const struct logger *logger, const char *message, ...) { if (LDBGP(DBG_BASE, logger)) { va_list ap; va_start(ap, message); llog_va_list(DEBUG_STREAM|ADD_PREFIX, logger, message, ap); va_end(ap); } } void ldbgf(lset_t cond, const struct logger *logger, const char *message, ...) { if (LDBGP(cond, logger)) { va_list ap; va_start(ap, message); llog_va_list(DEBUG_STREAM, logger, message, ap); va_end(ap); } } void pdbgf(lset_t cond, const struct logger *logger, const char *message, ...) { if (LDBGP(cond, logger)) { va_list ap; va_start(ap, message); llog_va_list(DEBUG_STREAM|ADD_PREFIX, logger, message, ap); va_end(ap); } } libreswan-5.2/lib/libswan/lex.c000066400000000000000000000154111475767661000165340ustar00rootroot00000000000000/* * 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; } ldbgf(DBG_TMI, oflp->logger, "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) { ldbgf(DBG_TMI, (*flp)->logger, "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; ldbgf(DBG_TMI, flp->logger, "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); ldbgf(DBG_TMI, flp->logger, "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, 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; ldbgf(DBG_TMI, flp->logger, "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); ldbgf(DBG_TMI, flp->logger, "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; ldbgf(DBG_TMI, flp->logger, "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) { ldbgf(DBG_TMI, flp->logger, "lex flushline: already on eof or record boundary"); return true; } /* discard tokens until boundary reached */ ldbgf(DBG_TMI, flp->logger, "lex flushline: need to flush tokens"); if (message != NULL) { llog(RC_LOG, flp->logger, "%s", message); } do { ldbgf(DBG_TMI, flp->logger, "lex flushline: discarding '%s'", flp->tok); } while (shift(flp)); return false; } libreswan-5.2/lib/libswan/linux_netlink.c000066400000000000000000000106331475767661000206300ustar00rootroot00000000000000/* * netlink_read_reply generic netlink response, for libreswan * * Copyright (C) 2012-2013 Kim B. Heino * Copyright (C) 2024 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY 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 "linux_netlink.h" #include "lsw_socket.h" #include "lswalloc.h" #include "lswlog.h" /* ??? one caller thinks errno is meaningful after a failure */ static bool linux_netlink_process_response(const struct nlmsghdr *nlmsg, int sock, linux_netlink_response_processor *processor, struct linux_netlink_context *context, struct verbose verbose) { for (;;) { struct sockaddr_nl sa; ssize_t readlen; /* signed */ union { struct nlmsghdr nlhdr; uint8_t raw[LINUX_NETLINK_BUFSIZE]; } buf; /* * Read netlink message, verifying kernel origin * (in sa.nl_pid?) */ do { socklen_t salen = sizeof(sa); verbose("reading into %zu byte buffer", sizeof(buf)); errno = 0; readlen = recvfrom(sock, &buf, sizeof(buf), 0, (struct sockaddr *)&sa, &salen); if (errno == EAGAIN) { if (nlmsg->nlmsg_flags & NLM_F_ACK) { continue; /* try again!?! */ } return true; } if (readlen <= 0 || salen != sizeof(sa)) { llog_errno(RC_LOG, verbose.logger, errno, "read netlink socket failure: "); return false; } } while (sa.nl_pid != 0); verbose("processing %zu byte response", readlen); /* * Now process the contents. */ struct nlmsghdr *nlhdr = &buf.nlhdr; verbose.level++; do { /* * Check that READLEN is big enough to hold * the current message. */ if (!NLMSG_OK(nlhdr, readlen)) { verbose("TRUNCATED %zd", readlen); return false; } if (nlhdr->nlmsg_type == NLMSG_ERROR) { verbose("ERROR"); return false; } /* * When there's a multi-part message, the last * part has type NLMSG_DONE set. */ if (nlhdr->nlmsg_type == NLMSG_DONE) { verbose("DONE"); return true; } /* * Process this message (could be more). * Processor is responsible for checking PID. */ if (nlhdr->nlmsg_seq == nlmsg->nlmsg_seq) { if (!processor(nlhdr, context, verbose)) { /* this means stop early; not * a failure */ return true; } } /* * When NLM_F_MULTI is set there's another * message following. It could be part of * this read, but it could also be in the * socket waiting for a read. */ if ((nlhdr->nlmsg_flags & NLM_F_MULTI) == 0) { return true; } /* * Advance to the next message in the buffer. * If the buffer has been consumed, loop round * the outer loop re-fill the buffer from the * socket. */ nlhdr = NLMSG_NEXT(nlhdr, readlen); } while (readlen > 0); verbose.level--; } return true; } bool linux_netlink_query(const struct nlmsghdr *nlmsg, int netlink_protocol, bool (*processor)(struct nlmsghdr *, struct linux_netlink_context *, struct verbose verbose), struct linux_netlink_context *context, struct verbose verbose) { /* * When no ACK is required; open non-blocking so that read * doesn't hang. */ unsigned flags = 0; if (nlmsg->nlmsg_flags & NLM_F_ACK) { verbose("opening blocking netlink socket"); } else { verbose("opening non-blocking netlink socket"); flags |= SOCK_NONBLOCK; } int sock = cloexec_socket(PF_NETLINK, SOCK_DGRAM|flags, netlink_protocol); if (sock < 0) { llog_errno(RC_LOG, verbose.logger, errno, "create netlink socket failure: "); return false; } if (send(sock, nlmsg, nlmsg->nlmsg_len, 0) < 0) { llog_errno(RC_LOG, verbose.logger, errno, "write netlink socket failure: "); close(sock); return false; } verbose("sent %d byte netlink message", (int)nlmsg->nlmsg_len); bool ok = linux_netlink_process_response(nlmsg, sock, processor, context, verbose); close(sock); return ok; } libreswan-5.2/lib/libswan/llog.c000066400000000000000000000015171475767661000167030ustar00rootroot00000000000000/* 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-5.2/lib/libswan/llog_base64_bytes.c000066400000000000000000000031061475767661000212510ustar00rootroot00000000000000/* 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" #include "lswalloc.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. */ size_t base64_len = size * 8 / 6 + 1 + 10; char *base64_ptr = alloc_things(char, base64_len, "base64"); /* size includes NUL */ size_t base64_size = datatot(ptr, size, 64, 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 /*drop NUL*/); while (true) { shunk_t line = hunk_slice(rest, 0, min((size_t)64, rest.len)); if (line.len == 0) break; rest = hunk_slice(rest, line.len, rest.len); llog(rc_flags, logger, PRI_SHUNK, pri_shunk(line)); } pfree(base64_ptr); } libreswan-5.2/lib/libswan/llog_dump.c000066400000000000000000000041131475767661000177230ustar00rootroot00000000000000/* 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-5.2/lib/libswan/llog_errno.c000066400000000000000000000020201475767661000200760ustar00rootroot00000000000000/* 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, ...) { JAMBUF(buf) { jam_logger_rc_prefix(buf, logger, rc_flags); va_list ap; va_start(ap, fmt); jam_va_list(buf, fmt, ap); va_end(ap); /* NO ": "; not a *perror() function */ jam_errno(buf, error); jambuf_to_logger(buf, logger, rc_flags); } } libreswan-5.2/lib/libswan/llog_pem_bytes.c000066400000000000000000000016531475767661000207530ustar00rootroot00000000000000/* 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-5.2/lib/libswan/llog_va_list.c000066400000000000000000000015341475767661000204230ustar00rootroot00000000000000/* 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-5.2/lib/libswan/lmod.c000066400000000000000000000061441475767661000167020ustar00rootroot00000000000000/* 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 ? hunk_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, lmod_t mod) { size_t s = 0; static const char separator[] = "+"; 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; } const char *str_lmod(const struct enum_names *sd, lmod_t val, lmod_buf *out) { struct jambuf buf = ARRAY_AS_JAMBUF(out->buf); jam_lmod(&buf, sd, val); return out->buf; } libreswan-5.2/lib/libswan/log_error.c000066400000000000000000000022461475767661000177400ustar00rootroot00000000000000/* 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(const 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_STREAM); } libreswan-5.2/lib/libswan/log_ip.c000066400000000000000000000012651475767661000172170ustar00rootroot00000000000000/* 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-5.2/lib/libswan/log_nss_error.c000066400000000000000000000044341475767661000206240ustar00rootroot00000000000000/* 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, ...) { struct logjam logjam; struct jambuf *buf = jambuf_from_logjam(&logjam, logger, 0, where, PASSERT_FLAGS); { va_list ap; va_start(ap, message); jam_va_nss_error_code(buf, PR_GetError(), message, ap); va_end(ap); } passert_logjam_to_logger(&logjam); } void pexpect_nss_error(struct logger *logger, where_t where, const char *message, ...) { struct logjam logjam; struct jambuf *buf = jambuf_from_logjam(&logjam, logger, 0, where, PEXPECT_FLAGS); { va_list ap; va_start(ap, message); jam_va_nss_error_code(buf, PR_GetError(), message, ap); va_end(ap); } logjam_to_logger(&logjam); } libreswan-5.2/lib/libswan/logjam.c000066400000000000000000000035521475767661000172200ustar00rootroot00000000000000/* logging, 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 /* for abort() */ #include "logjam.h" #include "lswlog.h" struct jambuf *jambuf_from_logjam(struct logjam *logjam, const struct logger *logger, enum pluto_exit_code pluto_exit_code, where_t where, lset_t rc_flags) { /* * Note: don't initialize entire logjam; as that would zero * the very large array[LOG_WIDTH]. */ logjam->barf = (struct barf) { .rc_flags = rc_flags, .jambuf = ARRAY_AS_JAMBUF(logjam->array), .logger = logger, .where = where, .pluto_exit_code = pluto_exit_code, }; jam_logger_rc_prefix(&logjam->barf.jambuf, logger, rc_flags); return &logjam->barf.jambuf; } void logjam_to_logger(struct logjam *logjam) { if (logjam->barf.where != NULL) { jam_string(&logjam->barf.jambuf, " "); jam_where(&logjam->barf.jambuf, logjam->barf.where); } jambuf_to_logger(&logjam->barf.jambuf, logjam->barf.logger, logjam->barf.rc_flags); if ((logjam->barf.rc_flags & STREAM_MASK) == PASSERT_STREAM) { abort(); } } void barf(lset_t rc_flags, struct logger *logger, enum pluto_exit_code pluto_exit_code, where_t where, const char *fmt, ...) { BARF_JAMBUF(rc_flags, logger, pluto_exit_code, where, buf) { va_list ap; va_start(ap, fmt); jam_va_list(buf, fmt, ap); va_end(ap); } } libreswan-5.2/lib/libswan/lset.c000066400000000000000000000065611475767661000167210ustar00rootroot00000000000000/* 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) { enum_buf b; if (!enum_name(en, e, &b)) { 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_names *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 */ name_buf nb; if (sparse_short(sd, bit, &nb)) { s += jam_string(buf, nb.buf); } else { /* No name for this bit, use hex. */ s += jam(buf, "0x" PRI_LSET, bit); } } val &= ~bit; } return s; } libreswan-5.2/lib/libswan/lswconf.3.xml000066400000000000000000000217701475767661000201430ustar00rootroot00000000000000 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. AUTHOR Paul Wouters libreswan-5.2/lib/libswan/lswconf.c000066400000000000000000000124141475767661000174170ustar00rootroot00000000000000/* * 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_SYSCONFDIR, "default conf ipsec_conf_dir"); global_oco.conffile = clone_str(IPSEC_CONF, "default conf conffile"); global_oco.secretsfile = clone_str(IPSEC_SECRETS, "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-5.2/lib/libswan/lswglob.c000066400000000000000000000051331475767661000174150ustar00rootroot00000000000000/* 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. * */ #include #include #ifndef GLOB_ABORTED #define GLOB_ABORTED GLOB_ABEND /* fix for old versions */ #endif #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 */ } bool lswglob(const char *pattern, const char *what, void (*matches)(unsigned count, char **files, struct lswglob_context *context, struct logger *logger), struct lswglob_context *context, struct logger *logger) { int r; glob_t globbuf; /* * Call glob() locked. * * GLOB_ERR means bail when a directory can't be read which is * possibly redundant as having lswlog_errfunc() return 1 * means the same thing!?! */ pthread_mutex_lock(&lswglob_mutex); { lswglob_logger = logger; lswglob_what = what; r = glob(pattern, GLOB_ERR, lswglob_errfunc, &globbuf); lswglob_logger = NULL; lswglob_what = NULL; } pthread_mutex_unlock(&lswglob_mutex); bool ok; switch (r) { case 0: /* success */ ok = true; matches(globbuf.gl_pathc, globbuf.gl_pathv, context, logger); break; case GLOB_NOSPACE: llog_passert(logger, HERE, "out of memory processing %s", what); break; case GLOB_ABORTED: /* already logged by lswglob_errfunc() */ ok = true; break; case GLOB_NOMATCH: /* * Only NOMATCH is a fail, and then only when * no-wildcards. */ ok = (strchr(pattern, '*') != NULL); break; default: ok = true; llog_pexpect(logger, HERE, "%s pattern %s: unknown glob error %d", what, pattern, r); } globfree(&globbuf); return ok; } libreswan-5.2/lib/libswan/lswnss.c000066400000000000000000000177101475767661000173010ustar00rootroot00000000000000/* * 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 "fips_mode.h" static char *lsw_nss_get_password(PK11SlotInfo *slot, PRBool retry, void *arg); static struct nss_flags shutdown_flags; static diag_t setup(const char *configdir, struct nss_flags 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.open_readonly ? "read-only" : "read-write"), nssdir); } /* * save for cleanup */ shutdown_flags = 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 fips_mode fips_mode; if (nssdir != NULL) { SECStatus rv = NSS_Initialize(nssdir, "", "", SECMOD_DB, (flags.open_readonly ? NSS_INIT_READONLY : 0)); if (rv != SECSuccess) { /* NSS: : (SECERR: N) */ diag_t d = diag_nss_error("initialization using %s database \"%s\" failed", (flags.open_readonly ? "read-only" : "read-write"), nssdir); pfree(nssdir); return d; } fips_mode = get_fips_mode(logger); } else { NSS_NoDB_Init("."); fips_mode = get_fips_mode(logger); if (fips_mode == FIPS_MODE_ON && !PK11_IsFIPS()) { /* * Happens when set_fips_mode(FIPS_MODE_ON) is * called before calling this function. For * instance, in algparse. Need to flip NSS's * mode so that it matches. */ 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 == FIPS_MODE_UNSET) { 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 init_nss(const char *configdir, struct nss_flags flags, struct logger *logger) { diag_t d = setup(configdir, flags, logger); if (d != NULL) { LLOG_FATAL_JAMBUF(PLUTO_EXIT_FAIL, logger, buf) { jam_string(buf, str_diag(d)); pfree_diag(&d); } } } void shutdown_nss(void) { NSS_Shutdown(); /* this flag is never set anywhere */ if (!shutdown_flags.skip_pr_cleanup) { PR_Cleanup(); } } PK11SlotInfo *lsw_nss_get_authenticated_slot(struct logger *logger) { PK11SlotInfo *slot = PK11_GetInternalKeySlot(); /* refcnt_add() */ if (slot == NULL) { llog(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(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, password 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-5.2/lib/libswan/message_role.c000066400000000000000000000017751475767661000204210ustar00rootroot00000000000000/* message_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 "lswcdefs.h" /* for ARRAY_REF() */ #include "enum_names.h" #include "message_role.h" const char *message_role_name[] = { #define S(E) [E - MESSAGE_ROLE_FLOOR] = #E S(NO_MESSAGE), S(MESSAGE_REQUEST), S(MESSAGE_RESPONSE), #undef S }; const struct enum_names message_role_names = { MESSAGE_ROLE_FLOOR, MESSAGE_ROLE_ROOF-1, ARRAY_REF(message_role_name), "MESSAGE_", NULL, }; libreswan-5.2/lib/libswan/monotime.c000066400000000000000000000060521475767661000175740ustar00rootroot00000000000000/* 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 = from_seconds(seconds), }; } const monotime_t monotime_epoch = MONOTIME_EPOCH; bool is_monotime_epoch(monotime_t t) { return memeq(&t, &monotime_epoch, sizeof(monotime_t)); } clockid_t monotime_clockid(void) { #ifdef CLOCK_BOOTTIME return CLOCK_BOOTTIME; /* best */ #else return CLOCK_MONOTONIC; /* second best */ #endif } monotime_t mononow(void) { struct timespec t; int e = clock_gettime(monotime_clockid(), &t); if (e < 0) { /* * 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, }, }; } intmax_t monosecs(monotime_t m) { return m.mt.tv_sec; } monotime_t monotime_max(monotime_t l, monotime_t r) { if (monotime_cmp(l, >, r)) { return l; } else { return r; } } monotime_t monotime_min(monotime_t l, monotime_t r) { if (monotime_cmp(l, <, r)) { return l; } else { return r; } } 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; } int monotime_sub_sign(monotime_t l, monotime_t r) { return timeval_sub_sign(l.mt, r.mt); } deltatime_t monotime_diff(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, monotime_diff(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-5.2/lib/libswan/names.c000066400000000000000000000022701475767661000170460ustar00rootroot00000000000000/* enums as names, for libreswan * * Copyright (C) 2025 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY 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 "names.h" #include "jambuf.h" void bad_name(unsigned long val, name_buf *b) { snprintf(b->tmp, sizeof(b->tmp), "%lu", val); b->buf = b->tmp; } size_t jam_bad(struct jambuf *buf, const char *prefix, unsigned long val) { size_t s = 0; if (prefix != NULL) { s += jam_string(buf, prefix); const char c = prefix[strlen(prefix)-1]; /* * Typically .prefix has a trailing "_", but when it * doesn't add one. */ if (c != '_' && c != '.') { s += jam_string(buf, "."); } } s += jam(buf, "%lu", val); return s; } libreswan-5.2/lib/libswan/netlink_attrib.c000066400000000000000000000061561475767661000207630ustar00rootroot00000000000000/* * 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; if (alen != 0) { 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); } const struct nlattr *nl_getattr(const struct nlmsghdr *n, size_t *offset) { struct nlattr *attr = (void *)n + NLMSG_HDRLEN + NLMSG_ALIGN(*offset); struct nlattr *tail = (void *)n + NLMSG_ALIGN(n->nlmsg_len); if (attr == tail) { return NULL; } *offset += NLA_ALIGN(attr->nla_len); return attr; } const char *nl_getattrvalstrz(const struct nlmsghdr *n, const struct nlattr *attr) { struct nlattr *tail = (void *)n + NLMSG_ALIGN(n->nlmsg_len); ptrdiff_t len = (void *)tail - (void *)attr; if (len < (ptrdiff_t)sizeof(struct nlattr) || attr->nla_len <= sizeof(struct nlattr) || attr->nla_len > len || !memchr(attr + NLA_HDRLEN, '\0', attr->nla_len - NLA_HDRLEN)) { return NULL; } return (void *)attr + NLA_HDRLEN; } void nl_addattr8(struct nlmsghdr *n, int maxlen, int type, const uint8_t data) { nl_addattr_l(n, maxlen, type, &data, sizeof(uint8_t)); } void nl_addattr16(struct nlmsghdr *n, int maxlen, int type, const uint16_t data) { nl_addattr_l(n, maxlen, type, &data, sizeof(uint16_t)); } 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-5.2/lib/libswan/nss_cert_load.c000066400000000000000000000041461475767661000205660ustar00rootroot00000000000000/* * 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-5.2/lib/libswan/oid.c000066400000000000000000000277761475767661000165400ustar00rootroot00000000000000/* * 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-5.2/lib/libswan/oid.pl000066400000000000000000000066121475767661000167130ustar00rootroot00000000000000#!/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-5.2/lib/libswan/oid.txt000066400000000000000000000153431475767661000171200ustar00rootroot00000000000000# 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-5.2/lib/libswan/optarg.c000066400000000000000000000130501475767661000172350ustar00rootroot00000000000000/* getopt parsing, for libreswan * * Copyright (C) 2023,2024 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY 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 exit() */ #include "optarg.h" #include "sparse_names.h" #include "passert.h" #include "lswlog.h" #include "ip_info.h" #include "lmod.h" #include "names_constant.h" /* for debug_lmod_info */ #include "timescale.h" int optarg_index = -1; unsigned verbose; static const struct logger *optarg_logger; void optarg_init(const struct logger *logger) { optarg_logger = logger; } /* * XXX: almost identical code lives in plutomain.c */ NEVER_RETURNS PRINTF_LIKE(1) static void fatal_optarg(const char *fmt, ...) { /* * Not exit_pluto() or fatal() as pluto isn't yet up and * running? */ passert(optarg_index >= 0); const char *optname = optarg_options[optarg_index].name; LLOG_JAMBUF(WHACK_STREAM, optarg_logger, buf) { if (optarg == NULL) { jam(buf, "option --%s invalid: ", optname); } else { jam(buf, "option --%s '%s' invalid: ", optname, optarg); } va_list ap; va_start(ap, fmt); jam_va_list(buf, fmt, ap); va_end(ap); } /* not exit_pluto as pluto isn't yet up and running? */ exit(PLUTO_EXIT_FAIL); } deltatime_t optarg_deltatime(enum timescale default_timescale) { passert((optarg_options[optarg_index].has_arg == required_argument) || (optarg_options[optarg_index].has_arg == optional_argument && optarg != NULL)); deltatime_t deltatime; diag_t diag = ttodeltatime(optarg, &deltatime, default_timescale); if (diag != NULL) { fatal_optarg("%s", str_diag(diag)); } return deltatime; } uintmax_t optarg_uintmax(void) { passert((optarg_options[optarg_index].has_arg == required_argument) || (optarg_options[optarg_index].has_arg == optional_argument && optarg != NULL)); uintmax_t val; err_t err = shunk_to_uintmax(shunk1(optarg), NULL, /*base*/0, &val); if (err != NULL) { fatal_optarg("%s", err); } return val; } /* * Lookup OPTARG in NAMES. * * When optional_argument OPTARG is missing, return OPTIONAL (pass * optional=0 when required_argument). */ uintmax_t optarg_sparse(unsigned optional, const struct sparse_names *names) { if (optarg == NULL) { passert(optarg_options[optarg_index].has_arg == optional_argument); passert(optional != 0); return optional; } const struct sparse_name *name = sparse_lookup(names, shunk1(optarg)); if (name == NULL) { JAMBUF(buf) { jam(buf, "'%s' is not recognised, valid arguments are: ", optarg); jam_sparse_names(buf, names, ", "); fatal_optarg(PRI_SHUNK, pri_shunk(jambuf_as_shunk(buf))); } } return name->value; } /* * Addresses. */ void optarg_family(struct optarg_family *family, const struct ip_info *info) { if (family != NULL && family->type == NULL) { family->type = info; family->used_by = optarg_options[optarg_index].name; } } ip_address optarg_address_dns(struct optarg_family *family) { ip_address address; err_t err = ttoaddress_dns(shunk1(optarg), family->type, &address); if (err != NULL) { fatal_optarg("%s", err); } optarg_family(family, address_info(address)); return address; } ip_cidr optarg_cidr_num(struct optarg_family *family) { ip_cidr cidr; err_t err = ttocidr_num(shunk1(optarg), family->type, &cidr); if (err != NULL) { fatal_optarg("%s", err); } optarg_family(family, cidr_info(cidr)); return cidr; } ip_address optarg_any(struct optarg_family *family) { optarg_family(family, &ipv4_info); return family->type->address.unspec; } void optarg_verbose(lset_t start) { verbose++; if (verbose == 1) { return; } const lset_t debugging[] = { start, DBG_BASE, DBG_ALL, DBG_TMI, }; unsigned i = verbose - 2; if (start == LEMPTY) { /* skip start */ i++; } if (i < elemsof(debugging)) { cur_debugging |= debugging[i]; } /* logged when true; log once at end? */ LDBGP_JAMBUF(DEBUG_STREAM, optarg_logger, buf) { jam_string(buf, "debugging: "); jam_lset(buf, &debug_names, cur_debugging); } } void optarg_debug_lmod(bool enable, lmod_t *mods) { if (streq(optarg, "list") || streq(optarg, "help") || streq(optarg, "?")) { fprintf(stderr, "aliases:\n"); for (struct lmod_alias *a = debug_lmod_info.aliases; a->name != NULL; a++) { JAMBUF(buf) { jam(buf, " %s: ", a->name); jam_lset_short(buf, debug_lmod_info.names, "+", a->bits); fprintf(stderr, PRI_SHUNK"\n", pri_shunk(jambuf_as_shunk(buf))); } } fprintf(stderr, "bits:\n"); for (long e = next_enum(&debug_names, -1); e != -1; e = next_enum(&debug_names, e)) { JAMBUF(buf) { jam(buf, " "); jam_enum_short(buf, &debug_names, e); enum_buf help; if (enum_name(&debug_help, e, &help)) { jam(buf, ": "); jam_string(buf, help.buf); } fprintf(stderr, PRI_SHUNK"\n", pri_shunk(jambuf_as_shunk(buf))); } } exit(1); } /* work through the updates */ if (!lmod_arg(mods, &debug_lmod_info, optarg, enable)) { fprintf(stderr, "whack: unrecognized -%s-debug '%s' option ignored\n", enable ? "" : "-no", optarg); } } void optarg_debug(bool enable) { lmod_t mods = {0}; optarg_debug_lmod(enable, &mods); cur_debugging = lmod(cur_debugging, mods); } libreswan-5.2/lib/libswan/option_names.c000066400000000000000000000104431475767661000204370ustar00rootroot00000000000000/* * 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 "constants.h" #include "sparse_names.h" /* * Common aliases for YES and NO, add this to a keyword list so all * are accepted. * * This list does not include "0" or "1" as they, for things like * yndev have special meanings. */ #define YES_NO(YES, NO) \ SPARSE("yes", YES), \ SPARSE("no", NO), \ SPARSE("true", YES), \ SPARSE("false", NO), \ SPARSE("on", YES), \ SPARSE("off", NO), \ SPARSE("y", YES), \ SPARSE("n", NO) /* * Match in parser.lex; includes numbers 0/1. */ const struct sparse_names yn_option_names = { .list = { YES_NO(YN_YES, YN_NO), /* * These are unique to YN, and probably should be dropped * completely. Some keywords, such as ipsec-interface, * interpret "1" and "0". */ SPARSE("1", YN_YES), SPARSE("0", YN_NO), SPARSE_NULL, }, }; /* * Values for no/yes; excludes numeric values. */ const struct sparse_names yn_text_option_names = { .list = { YES_NO(YN_YES, YN_NO), SPARSE_NULL }, }; /* * Values for yes/no/force, used by fragmentation= */ const struct sparse_names ynf_option_names = { .list = { YES_NO(YNF_YES, YNF_NO), SPARSE("force", YNF_FORCE), SPARSE("never", YNF_NO), SPARSE("insist", YNF_FORCE), SPARSE_NULL }, }; /* * Values for ESP */ const struct sparse_names yne_option_names = { .list = { YES_NO(YNE_YES, YNE_NO), SPARSE("either", YNE_EITHER), SPARSE_NULL }, }; /* * Values for Four-State options, used for ppk= */ const struct sparse_names nppi_option_names = { .list = { SPARSE("never", NPPI_NEVER), SPARSE("permit", NPPI_PERMIT), SPARSE("propose", NPPI_PROPOSE), SPARSE("insist", NPPI_INSIST), SPARSE("always", NPPI_INSIST), YES_NO(NPPI_PROPOSE, NPPI_NEVER), SPARSE_NULL }, }; /* * Values for nat-ikev1-method={drafts,rfc,both,none} */ const struct sparse_names nat_ikev1_method_option_names = { .list = { SPARSE("both", NATT_BOTH), SPARSE("rfc", NATT_RFC), SPARSE("drafts", NATT_DRAFTS), SPARSE("none", NATT_NONE), SPARSE_NULL }, }; /* * Values for yes/no/auto, used by encapsulation. */ const struct sparse_names yna_option_names = { .list = { YES_NO(YNA_YES, YNA_NO), SPARSE("auto", YNA_AUTO), SPARSE_NULL, }, }; /* * Values for enable-tcp={no, yes, fallback} */ const struct sparse_names tcp_option_names = { .list = { YES_NO(IKE_TCP_ONLY, IKE_TCP_NO), SPARSE("fallback", IKE_TCP_FALLBACK), SPARSE_NULL }, }; const struct sparse_names nic_offload_option_names = { .list = { SPARSE("no", NIC_OFFLOAD_NO), SPARSE("crypto", NIC_OFFLOAD_CRYPTO), SPARSE("packet", NIC_OFFLOAD_PACKET), SPARSE("yes", NIC_OFFLOAD_CRYPTO), /* backwards compat */ SPARSE_NULL }, }; /* * Values for type={tunnel,transport,etc} */ const struct sparse_names type_option_names = { .list = { SPARSE("tunnel", KS_TUNNEL), SPARSE("transport", KS_TRANSPORT), SPARSE("pass", KS_PASSTHROUGH), SPARSE("passthrough", KS_PASSTHROUGH), SPARSE("reject", KS_REJECT), SPARSE("drop", KS_DROP), SPARSE_NULL }, }; libreswan-5.2/lib/libswan/passert.c000066400000000000000000000021511475767661000174220ustar00rootroot00000000000000/* * 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, ...) { struct logjam logjam; struct jambuf *buf = jambuf_from_logjam(&logjam, logger, 0, where, PASSERT_FLAGS); { va_list ap; va_start(ap, fmt); jam_va_list(buf, fmt, ap); va_end(ap); } passert_logjam_to_logger(&logjam); } void passert_logjam_to_logger(struct logjam *logjam) { logjam_to_logger(logjam); abort(); } libreswan-5.2/lib/libswan/pexpect.c000066400000000000000000000017531475767661000174200ustar00rootroot00000000000000/* 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, ...) { struct logjam logjam; struct jambuf *buf = jambuf_from_logjam(&logjam, logger, 0, where, PEXPECT_FLAGS); { va_list ap; va_start(ap, message); jam_va_list(buf, message, ap); va_end(ap); } logjam_to_logger(&logjam); } libreswan-5.2/lib/libswan/pluto_exit_code_names.c000066400000000000000000000033701475767661000223160ustar00rootroot00000000000000/* 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), #undef S }; enum_names pluto_exit_code_names = { PLUTO_EXIT_OK, PLUTO_EXIT_SELINUX_FAIL, ARRAY_REF(pluto_exit_code_name), "PLUTO_EXIT_", /* prefix */ &pluto_exit_code_names_hi, }; libreswan-5.2/lib/libswan/portof.3.xml000066400000000000000000000072331475767661000177770ustar00rootroot00000000000000 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. AUTHOR Paul Wouters libreswan-5.2/lib/libswan/proposals.c000066400000000000000000000566741475767661000200060ustar00rootroot00000000000000/* * 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) { struct logger *logger = parser->policy->logger; if (alg == NULL) { ldbgf(DBG_PROPOSAL_PARSER, logger, "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, }; ldbgf(DBG_PROPOSAL_PARSER, logger, "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(parser->policy->logger_rc_flags, parser->policy->logger, "IMPAIR: ignoring proposal error: %s", str_diag(parser->diag)); pfree_diag(&parser->diag); return true; } return false; } struct proposals *proposals_from_str(struct proposal_parser *parser, const char *str) { struct proposals *proposals = alloc_thing(struct proposals, "proposals"); if (str == NULL) { proposals->defaulted = true; /* may still be null */ enum fips_mode fips_mode = get_fips_mode(parser->policy->logger); str = parser->protocol->defaults->proposals[fips_mode]; PASSERT(parser->policy->logger, str != NULL); } bool ok = false; switch (parser->policy->version) { case IKEv1: ok = v1_proposals_parse_str(parser, proposals, shunk1(str)); break; case IKEv2: ok = v2_proposals_parse_str(parser, proposals, shunk1(str)); break; default: bad_case(parser->policy->version); } 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) { struct logger *logger = parser->policy->logger; 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) { ldbgf(DBG_PROPOSAL_PARSER, logger, "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 = hunk_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 = hunk_slice(ealg, 0, end); if (hunk_char(ealg, ealg.len-1) == '_') { ealg = hunk_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)) { LLOG_JAMBUF(DEBUG_STREAM, &global_logger, 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, "''"); } } } } libreswan-5.2/lib/libswan/pubkey_der_to_pubkey_content.c000066400000000000000000000055441475767661000237160ustar00rootroot00000000000000/* 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-5.2/lib/libswan/pubkey_ecdsa.c000066400000000000000000000375521475767661000204140ustar00rootroot00000000000000/* * 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 ((*e)->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_pubkey_stuff *pks, const uint8_t *hash_val, size_t hash_len, const struct hash_desc *hash_alg, struct logger *logger) { ldbgf(DBG_CRYPT, logger, "%s: started using NSS", __func__); if (!pexpect(pks->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; SECStatus s = SGN_Digest(pks->private_key, hash_alg->nss.oid_tag, &raw_signature, &hash_to_sign); if (s != SECSuccess) { /* PR_GetError() returns the thread-local error */ llog_nss_error(RC_LOG, logger, "ECDSA SGN_Digest function failed"); return (struct hash_signature) { .len = 0, }; } if (DBGP(DBG_CRYPT)) { DBG_dump("SGN_Digest()", raw_signature.data, raw_signature.len); } passert(sizeof(signature.ptr/*array*/) >= raw_signature.len); memcpy(signature.ptr, raw_signature.data, raw_signature.len); signature.len = raw_signature.len; SECITEM_FreeItem(&raw_signature, PR_FALSE/*only-data*/); if (DBGP(DBG_CRYPT)) { DBG_dump_hunk("PK11_Sign()", signature); } 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_BASE)) { 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); } } /* * PK11_Verify() expects a raw signature like supplied here; * VFY_Verify*() also expects a der encoded prefix so doesn't * work. */ 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_pubkey_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->private_key != NULL)) { dbg("no private key!"); return (struct hash_signature) { .len = 0, }; } ldbgf(DBG_CRYPT, logger, "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->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->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, 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); ldbgf(DBG_CRYPT, logger, "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 *hash_alg, diag_t *fatal_diag, struct logger *logger) { const struct pubkey_content *ecdsa = &pubkey->content; SECItem signature_item = { .type = siBuffer, .data = DISCARD_CONST(unsigned char *, 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_BASE)) { LLOG_JAMBUF(DEBUG_STREAM, logger, buf) { jam(buf, "%d-byte DER encoded ECDSA signature: ", signature_item.len); jam_nss_secitem(buf, &signature_item); } LLOG_JAMBUF(DEBUG_STREAM, logger, buf) { jam(buf, "%d-byte hash: ", hash_item.len); jam_nss_secitem(buf, &hash_item); } } if (VFY_VerifyDigestDirect(&hash_item, ecdsa->public_key, &signature_item, /*pubkey algorithm*/SEC_OID_ANSIX962_EC_PUBLIC_KEY, /*signature hash algorithm*/hash_alg->nss.oid_tag, lsw_nss_get_password_context(logger)) != SECSuccess) { llog_nss_error(DEBUG_STREAM, logger, "verifying AUTH hash using VFY_VerifyDigestDirect(%s,%s) failed: ", ecdsa->type->name, hash_alg->common.fqn); *fatal_diag = NULL; return false; } *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-5.2/lib/libswan/pubkey_rsa.c000066400000000000000000000540551475767661000201170ustar00rootroot00000000000000/* * 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_IN_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_raw_sign_hash(const struct secret_pubkey_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->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->private_key), }; passert(sig.len <= sizeof(sig.ptr/*array*/)); SECItem signature = { .type = siBuffer, .len = sig.len, .data = sig.ptr, }; SECStatus s = PK11_Sign(pks->private_key, &signature, &data); if (s != SECSuccess) { /* PR_GetError() returns the thread-local error */ llog_nss_error(RC_LOG, 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_raw_sign_hash, .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_pkcs1_1_5_sign_hash(const struct secret_pubkey_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->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->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, 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->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_pkcs1_1_5_sign_hash, .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_pkcs1_1_5_sign_hash, .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_rsassa_pss_sign_hash(const struct secret_pubkey_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->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->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, 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->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, 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_rsassa_pss_sign_hash, .authenticate_signature = RSA_authenticate_signature_rsassa_pss, .jam_auth_method = RSA_jam_auth_method, }; libreswan-5.2/lib/libswan/realtime.c000066400000000000000000000066171475767661000175560ustar00rootroot00000000000000/* 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 seconds) { return (realtime_t) { .rt = from_seconds(seconds), }; } realtime_t realtime_add(realtime_t t, deltatime_t d) { realtime_t s; timeradd(&t.rt, &d.dt, &s.rt); return s; } realtime_t realtime_sub(realtime_t t, deltatime_t d) { realtime_t s; timersub(&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 realtime_diff(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 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-5.2/lib/libswan/refcnt.c000066400000000000000000000113221475767661000172220ustar00rootroot00000000000000/* 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" #include "lswlog.h" /* for DBG*() et.al. */ static pthread_mutex_t refcnt_mutex = PTHREAD_MUTEX_INITIALIZER; static void ldbg_ref(const struct logger *logger, const struct logger *owner, const char *why, const char *what, const void *pointer, where_t where, int old_count, int new_count) { if (DBGP(DBG_REFCNT)) { LLOG_JAMBUF(DEBUG_STREAM, &global_logger, buf) { if (logger == NULL) { jam_string(buf, what); jam_string(buf, ": "); } else { jam_logger_prefix(buf, logger); } jam(buf, "%sref @%p(%u->%u)", why, pointer, old_count, new_count); if (owner != NULL) { jam_string(buf, " "); jam_logger_prefix(buf, owner); } jam_string(buf, " "); jam_where(buf, where); } } } #define LDBG_REF(WHY) \ ldbg_ref(logger, owner, WHY, refcnt->base->what, pointer, where, old, new) /* * So existing code can use the refcnt tracer. */ void ldbg_alloc(const struct logger *new_owner, const char *what, const void *pointer, where_t where) { ldbg_ref(NULL, new_owner, "new", what, pointer, where, 0, 1); } void ldbg_free(const struct logger *logger, const char *what, const void *pointer, where_t where) { ldbg_ref(logger, NULL, "del", what, pointer, where, 1, 0); } void ldbg_addref_where(const struct logger *logger, const char *what, const void *pointer, where_t where) { if (DBGP(DBG_REFCNT)) { LDBG_log(logger, "addref %s@%p "PRI_WHERE, what, pointer, pri_where(where)); } } void ldbg_delref_where(const struct logger *logger, const char *what, const void *pointer, where_t where) { if (DBGP(DBG_REFCNT)) { LDBG_log(logger, "delref %s@%p "PRI_WHERE, what, pointer, pri_where(where)); } } void dbg_alloc(const char *what, const void *pointer, where_t where) { ldbg_alloc(NULL, what, pointer, where); } void dbg_free(const char *what, const void *pointer, where_t where) { ldbg_free(NULL, what, pointer, where); } /* -- */ 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_passert(&global_logger, where, "%s() %s@%p should have been 0 initialized", __func__, base->what, pointer); } ldbg_ref(NULL, NULL, "new", base->what, pointer, where, old, new); } void refcnt_addref_where(const char *what, const void *pointer, refcnt_t *refcnt, const struct logger *logger, const struct logger *owner, where_t where) { 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_passert((logger == NULL ? &global_logger : logger), where, "%s() refcnt for %s@%p should have been non-0", __func__, what, pointer); } LDBG_REF("add"); } /* * look at refcnt atomically * This is a bit slow but it is used rarely. */ unsigned refcnt_peek_where(const void *pointer, const refcnt_t *refcnt, const struct logger *logger, where_t where) { unsigned val; pthread_mutex_lock(&refcnt_mutex); { val = refcnt->count; } pthread_mutex_unlock(&refcnt_mutex); ldbg_ref(logger, /*owner*/NULL, "peek", /*what*/NULL, pointer, where, val, val); return val; } void *refcnt_delref_where(const char *what, void *pointer, struct refcnt *refcnt, const struct logger *logger, const struct logger *owner, const struct where *where) { /* 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_passert((logger == NULL ? &global_logger : logger), where, "%s() refcnt for %s@%p should have been non-0", __func__, what, pointer); } LDBG_REF("del"); if (new == 0) { return pointer; } return NULL; } libreswan-5.2/lib/libswan/reqid.c000066400000000000000000000035471475767661000170570ustar00rootroot00000000000000/* 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-5.2/lib/libswan/resolve_default_route_bsd.c000066400000000000000000000133231475767661000231750ustar00rootroot00000000000000/* 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_names rta_names = { .list = { #define E(N) { .name = #N, .value = 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_STREAM, logger, errno, "write failed: "); return ROUTE_FATAL; } /* recv */ int r = read(s, &msg, sizeof(msg)); if (r < 0) { llog_errno(ERROR_STREAM, logger, errno, "write failed: "); return ROUTE_FATAL; } /* verify */ if (sizeof(msg.hdr.rtm_msglen) > (unsigned)r) { llog(ERROR_STREAM, logger, "response of %d bytes way too small", r); return ROUTE_FATAL; } if (msg.hdr.rtm_msglen > r) { llog(ERROR_STREAM, logger, "response of %d bytes was truncated", r); return ROUTE_FATAL; } if (msg.hdr.rtm_version != RTM_VERSION) { llog(ERROR_STREAM, logger, "response version %d wrong", msg.hdr.rtm_version); return ROUTE_FATAL; } if (msg.hdr.rtm_errno != 0) { llog(ERROR_STREAM, logger, "response failed: %s", strerror(errno)); return ROUTE_FATAL; } if (msg.hdr.rtm_type != RTM_GET) { llog(ERROR_STREAM, 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_STREAM, 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_info(dst); int s = cloexec_socket(PF_ROUTE, SOCK_RAW, afi->af); if (s < 0) { llog_errno(ERROR_STREAM, 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-5.2/lib/libswan/resolve_default_route_linux.c000066400000000000000000000440131475767661000235640ustar00rootroot00000000000000/* * 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 "linux_netlink.h" #include "addr_lookup.h" #ifdef USE_DNSSEC # include "dnssec.h" #endif #include "ip_info.h" #include "lswlog.h" 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) { verbose("interface %s had invalid sockaddr: %s", interface, err); continue; } address_buf ab; verbose("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 (LINUX_NETLINK_BUFSIZE + 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 netlink_query_init()"); struct rtmsg *rtmsg; nlmsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); nlmsg->nlmsg_flags = flags; nlmsg->nlmsg_type = type; nlmsg->nlmsg_seq = 1; 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; verbose("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; verbose("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); } /* * 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, }; struct linux_netlink_context { enum resolve_status status; const struct ip_info *afi; enum seeking { NOTHING, PREFSRC, GATEWAY, } seeking; struct starter_end *host; struct starter_end *peer; }; static bool process_netlink_route(struct nlmsghdr *nlmsg, struct linux_netlink_context *context, struct verbose verbose) { const struct ip_info *const afi = context->afi; if (context->status == RESOLVE_FAILURE) { if (PBAD(verbose.logger, nlmsg->nlmsg_type == NLMSG_DONE)) { return false; } if (PBAD(verbose.logger, nlmsg->nlmsg_type == NLMSG_ERROR)) { context->status = RESOLVE_FAILURE; return false; } /* ignore all but IPv4 and IPv6 */ struct rtmsg *rtmsg = (struct rtmsg *) NLMSG_DATA(nlmsg); if (rtmsg->rtm_family != afi->af) { verbose("wrong family"); return true; } /* 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); verbose("parsing route entry (RTA payloads)"); verbose.level++; 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) \ { \ diag_t diag = data_to_address(data, len, afi, OUT); \ if (diag != NULL) { \ verbose("invalid RTA_%s from kernel: %s", \ WHAT, str_diag(diag)); \ pfree_diag(&diag); \ } else { \ address_buf ab; \ verbose("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)) { \ verbose("ignoring RTA_%s with wrong size %d", WHAT, len); \ } else { \ memcpy(&OUT, data, len); \ verbose("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: verbose("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; verbose("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); if (rtmsg->rtm_table != RT_TABLE_MAIN) { verbose("IGNORE: table %d is not main(%d)", rtmsg->rtm_table, RT_TABLE_MAIN); return true; } if (startswith(r_interface, "ipsec") || startswith(r_interface, "mast")) { verbose("IGNORE: interface %s", r_interface); return true; } switch (context->seeking) { case PREFSRC: if (!address_is_unset(&prefsrc)) { context->status = RESOLVE_SUCCESS; context->host->addrtype = KH_IPADDR; context->host->addr = prefsrc; address_buf ab; verbose("found prefsrc(host_addr): %s", str_address(&context->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, context->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. */ context->status = RESOLVE_PLEASE_CALL_AGAIN; context->host->nexttype = KH_IPADDR; context->host->nexthop = gateway; address_buf ab; verbose("found gateway(host_nexthop): %s", str_address(&context->host->nexthop, &ab)); } } break; default: bad_case(context->seeking); } } return true; } 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; verbose("resolving family=%s src=%s gateway=%s peer %s", (afi == NULL ? "" : afi->ip_name), pa(host->addrtype, host->addr, host->values[KW_IP].string, &ab), pa(host->nexttype, host->nexthop, host->values[KW_NEXTHOP].string, &gb), pa(peer->addrtype, peer->addr, peer->values[KW_IP].string, &pb)); verbose.level++; /* * 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 seeking = (host->nexttype == KH_DEFAULTROUTE ? GATEWAY : host->addrtype == KH_DEFAULTROUTE ? PREFSRC : NOTHING); verbose("seeking %s", (seeking == NOTHING ? "NOTHING" : seeking == PREFSRC ? "PREFSRC" : seeking == GATEWAY ? "GATEWAY" : "?")); verbose.level++; 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->values[KW_IP].string), peer->host_family, &peer->addr); if (er != NULL) { /* not numeric, so resolve it */ if (!unbound_resolve(peer->values[KW_IP].string, peer->host_family, &peer->addr, verbose.logger)) { pfree(msgbuf); return RESOLVE_FAILURE; } } #else err_t er = ttoaddress_dns(shunk1(peer->values[KW_IP].string), 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 */ struct linux_netlink_context context = { .status = RESOLVE_FAILURE, .host = host, .peer = peer, .afi = afi, .seeking = seeking, }; verbose.level--; bool ok = linux_netlink_query(msgbuf, NETLINK_ROUTE, process_netlink_route, &context, verbose); if (!ok) { pfree(msgbuf); return RESOLVE_FAILURE; } verbose.level = 1; verbose("%s: src=%s gateway=%s", (context.status == RESOLVE_FAILURE ? "failure" : context.status == RESOLVE_SUCCESS ? "success" : context.status == RESOLVE_PLEASE_CALL_AGAIN ? "please-call-again" : "???"), pa(host->addrtype, host->addr, host->values[KW_IP].string, &ab), pa(host->nexttype, host->nexthop, host->values[KW_NEXTHOP].string, &gb)); pfree(msgbuf); return context.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_info(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-5.2/lib/libswan/rnd.c000066400000000000000000000061031475767661000165250ustar00rootroot00000000000000/* 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(void) { uintmax_t rnd; get_rnd_bytes(&rnd, sizeof(rnd)); return rnd; } 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-5.2/lib/libswan/sa_role.c000066400000000000000000000016761475767661000174000ustar00rootroot00000000000000/* 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 "lswcdefs.h" /* for ARRAY_REF() */ #include "enum_names.h" #include "sa_role.h" const char *sa_role_name[] = { #define S(E) [E - SA_ROLE_FLOOR] = #E S(SA_INITIATOR), S(SA_RESPONDER), #undef S }; const struct enum_names sa_role_names = { SA_ROLE_FLOOR, SA_ROLE_ROOF-1, ARRAY_REF(sa_role_name), "SA_ROLE_", NULL, }; libreswan-5.2/lib/libswan/sa_type.c000066400000000000000000000016651475767661000174160ustar00rootroot00000000000000/* SA type, for libreswan * * Copyright (C) 2024 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include "sa_type.h" #include "lswcdefs.h" /* for ARRAY_REF */ #include "enum_names.h" static const char *sa_type_name[] = { #define S(E) [E - SA_TYPE_FLOOR] = #E S(IKE_SA), S(CHILD_SA), #undef S }; const struct enum_names sa_type_names = { SA_TYPE_FLOOR, SA_TYPE_ROOF-1, ARRAY_REF(sa_type_name), .en_prefix = NULL, }; libreswan-5.2/lib/libswan/sameaddr.3.xml000066400000000000000000000141441475767661000202450ustar00rootroot00000000000000 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. AUTHOR Paul Wouters libreswan-5.2/lib/libswan/sameaddr.c000066400000000000000000000026431475767661000175270ustar00rootroot00000000000000/* * 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-5.2/lib/libswan/scale.c000066400000000000000000000050171475767661000170340ustar00rootroot00000000000000/* scales, for libreswan * * Copyright (C) 2022-2024 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 "scale.h" #include "lswcdefs.h" #include "jambuf.h" #include "lswlog.h" const struct scale *ttoscale(shunk_t cursor, const struct scales *scales, unsigned default_scale) { if (cursor.len == 0) { /* default scaling */ return &scales->scale.list[default_scale]; } FOR_EACH_ITEM(scale, &scales->scale) { if (hunk_strcaseeq(cursor, scale->suffix)) { return scale; } } return NULL; } /* * This does not work for things like 30/60 seconds */ size_t jam_decimal(struct jambuf *buf, uintmax_t decimal, uintmax_t numerator, uintmax_t denominator) { size_t s = 0; const unsigned base = 10; s += jam(buf, "%ju", decimal); if (numerator == 0) { return s; } if (numerator >= denominator) { /* should not be called */ s += jam(buf, ".%ju/%ju", numerator, denominator); return s; } /* strip trailing zeros */ while (numerator % base == 0 && denominator % base == 0) { numerator /= base; denominator /= base; } /* determine precision */ unsigned precision = 0; while (denominator % base == 0) { denominator /= base; precision += 1; } s += jam(buf, ".%0*ju", precision, numerator); return s; } err_t scale_decimal(const struct scale *scale, uintmax_t decimal, uintmax_t numerator, uintmax_t denominator, uintmax_t *value) { ldbgf(DBG_TMI, &global_logger, "%s() decimal=%ju numerator=%ju denominator=%ju "PRI_SCALE"\n", __func__, decimal, numerator, denominator, pri_scale(scale)); /* * Check that scaling DECIMAL doesn't overflow. */ if (UINTMAX_MAX / scale->multiplier < decimal) { return "overflow"; } *value = decimal * scale->multiplier; if (numerator > 0 && denominator > 0) { if (denominator > scale->multiplier) { return "underflow"; } /* fails on really small fractions? */ (*value) += (numerator * (scale->multiplier / denominator)); } return NULL; } libreswan-5.2/lib/libswan/secitem_chunk.c000066400000000000000000000025531475767661000205700ustar00rootroot00000000000000/* * 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-5.2/lib/libswan/secret_pubkey_stuff_to_pubkey_der.c000066400000000000000000000027501475767661000247340ustar00rootroot00000000000000/* 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_pubkey_stuff *pks, chunk_t *der) { SECKEYPublicKey *seckey_pubkey = SECKEY_ConvertToPublicKey(pks->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-5.2/lib/libswan/secrets.c000066400000000000000000001137351475767661000174240ustar00rootroot00000000000000/* * 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" 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 { enum secret_kind kind; /* * The ipsec.secrets line number, but which ipsec.secrets * (include means more than one). * * For NSS, this is the entry number. */ int line; /* * List of IDs, is this part of pubkey stuff? */ struct id_list *ids; union /*kind*/ { struct secret_preshared_stuff *preshared; struct secret_ppk_stuff *ppk; struct secret_pubkey_stuff *pubkey; } u; /* hope the list doesn't get too long */ struct secret *next; }; const struct secret_preshared_stuff *secret_preshared_stuff(const struct secret *secret) { switch (secret->kind) { case SECRET_PSK: case SECRET_XAUTH: /* some sort of PSK */ return secret->u.preshared; default: return NULL; } } struct secret_pubkey_stuff *secret_pubkey_stuff(const struct secret *secret) { switch (secret->kind) { case SECRET_RSA: case SECRET_ECDSA: /* some sort of PKI */ return secret->u.pubkey; default: return NULL; } } const struct secret_ppk_stuff *secret_ppk_stuff(const struct secret *secret) { switch (secret->kind) { case SECRET_PPK: return secret->u.ppk; default: return NULL; } } 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. */ ldbgf(DBG_CRYPT, &global_logger, "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) { const struct secret_pubkey_stuff *pki = secret_pubkey_stuff(secret); if (pki == NULL) { return NULL; } /* some sort of PKI */ return &pki->content.ckaid; } const keyid_t *secret_keyid(const struct secret *secret) { const struct secret_pubkey_stuff *pki = secret_pubkey_stuff(secret); if (pki == NULL) { return NULL; } /* some sort of PKI */ return &pki->content.keyid; } struct secret *foreach_secret(struct secret *secrets, secret_eval func, struct secret_context *context) { for (struct secret *s = secrets; s != NULL; s = s->next) { int result = (*func)(s, s->kind, s->line, context); 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_or_null, const SECItem *pubkey_ckaid) { for (struct secret *s = secrets; s != NULL; s = s->next) { id_buf idb; enum_buf kb; dbg("trying secret %s:%s", str_enum(&secret_kind_names, s->kind, &kb), (pexpect(s->ids != NULL) ? str_id(&s->ids->id, &idb) : "")); const struct secret_pubkey_stuff *pki = secret_pubkey_stuff(s); if (pki == NULL) { /* not a pubkey */ dbg(" not PKI"); continue; } if (type_or_null != NULL && pki->content.type != type_or_null) { /* need exact or wildcard */ dbg(" not %s", type_or_null->name); continue; } if (!ckaid_eq_nss(&pki->content.ckaid, pubkey_ckaid)) { dbg(" wrong ckaid"); continue; } dbg(" matched"); return s; } return NULL; } bool secret_pubkey_same(const struct secret *lhs, const struct secret *rhs) { /* should be == SECRET_PKI */ const struct secret_pubkey_stuff *lpk = secret_pubkey_stuff(lhs); if (lpk == NULL) { return false; } const struct secret_pubkey_stuff *rpk = secret_pubkey_stuff(rhs); if (rpk == NULL) { return false; } if (lpk->content.type != rpk->content.type) { return false; } return lpk->content.type->pubkey_same(&lpk->content, &rpk->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; enum_buf kb, skb; DBG_log("line %d: key type %s(%s) to type %s", s->line, str_enum(&secret_kind_names, kind, &kb), str_id(local_id, &idl), str_enum(&secret_kind_names, s->kind, &skb)); } if (s->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->u.preshared[0], best->u.preshared[0]); 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->u.ppk->key, best->u.ppk->key); 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 asymmetric"); 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->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->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 diag_t process_preshared_secret(const char *what, size_t minlen, struct file_lex_position *flp, struct secret_preshared_stuff **psk) { if (flp->quote == '"' || flp->quote == '\'') { size_t len = strlen(flp->tok); if (minlen > 0 && len < minlen) { llog(RC_LOG, flp->logger, "WARNING: using a weak secret (%s)", what); } *psk = clone_bytes_as_hunk(struct secret_preshared_stuff, flp->tok, len); shift(flp); return NULL; } chunk_t secret; err_t ugh = ttochunk(shunk2(flp->tok, flp->cur - flp->tok), 0, &secret); if (ugh != NULL) { /* ttodata didn't like PSK data */ return diag("%s data malformed (%s): %s", what, ugh, flp->tok); } *psk = clone_bytes_as_hunk(struct secret_preshared_stuff, secret.ptr, secret.len); free_chunk_content(&secret); shift(flp); return NULL; } /* parse static PPK */ static diag_t process_ppk_static_secret(struct file_lex_position *flp, struct secret_ppk_stuff **ppk) { if (flp->quote != '"' && flp->quote != '\'') { return diag("no quotation marks found, PPK ID should be in quotation marks"); } chunk_t id = clone_bytes_as_chunk(flp->tok, strlen(flp->tok), "PPK ID"); if (!shift(flp)) { free_chunk_content(&id); return diag("No PPK found. PPK should be specified after PPK ID"); } chunk_t key; if (flp->quote == '"' || flp->quote == '\'') { key = clone_bytes_as_chunk(flp->tok, strlen(flp->tok), "PPK"); shift(flp); } else { err_t ugh = ttochunk(shunk2(flp->tok, flp->cur - flp->tok), 0, &key); if (ugh != NULL) { /* ttodata didn't like PPK data */ free_chunk_content(&id); return diag("PPK data malformed (%s): %s", ugh, flp->tok); } shift(flp); } /* merge the fields */ (*ppk) = overalloc_thing(struct secret_ppk_stuff, id.len + key.len); uint8_t *dst = (*ppk)->data; (*ppk)->id.ptr = dst; (*ppk)->id.len = id.len; memcpy(dst, id.ptr, id.len); dst += id.len; (*ppk)->key.ptr = dst; (*ppk)->key.len = key.len; memcpy(dst, key.ptr, key.len); free_chunk_content(&key); free_chunk_content(&id); return NULL; } const struct secret_ppk_stuff *secret_ppk_stuff_by_id(const struct secret *s, shunk_t ppk_id) { while (s != NULL) { if (s->kind == SECRET_PPK && hunk_eq(s->u.ppk->id, ppk_id)) return s->u.ppk; 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 sentinel 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) { diag_t ugh = NULL; if (tokeqword(flp, "psk")) { s->kind = SECRET_PSK; /* preshared key: quoted string or ttodata format */ ugh = (!shift(flp) ? diag("ERROR: unexpected end of record in PSK") : process_preshared_secret("PSK", 8, flp, &s->u.preshared)); ldbg(flp->logger, "processing PSK at line %d: %s", s->line, (ugh == NULL ? "passed" : str_diag(ugh))); } else if (tokeqword(flp, "xauth")) { /* xauth key: quoted string or ttodata format */ s->kind = SECRET_XAUTH; ugh = (!shift(flp) ? diag("ERROR: unexpected end of record in PSK") : process_preshared_secret("XAUTH", 0, flp, &s->u.preshared)); ldbg(flp->logger, "processing XAUTH at line %d: %s", s->line, (ugh == NULL ? "passed" : str_diag(ugh))); } else if (tokeqword(flp, "ppks")) { s->kind = SECRET_PPK; ugh = (!shift(flp) ? diag("ERROR: unexpected end of record in static PPK") : process_ppk_static_secret(flp, &s->u.ppk)); ldbg(flp->logger, "processing PPK at line %d: %s", s->line, (ugh == NULL ? "passed" : str_diag(ugh))); } else { ugh = diag("WARNING: ignored unrecognized keyword: %s", flp->tok); } if (ugh != NULL) { llog(RC_LOG, flp->logger, "\"%s\" line %d: %s", flp->filename, s->line, str_diag(ugh)); pfree_diag(&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); return; } 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, 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, 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->kind = 0; /* invalid */ s->line = flp->lino; 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, 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; enum_buf skb; dbg("id type added to secret(%p) %s: %s", s, str_enum(&secret_kind_names, s->kind, &skb), str_id(&id, &b)); } if (!shift(flp)) { /* unexpected Record Boundary or EOF */ llog(RC_LOG, flp->logger, "\"%s\" line %d: unexpected end of id list", flp->filename, flp->lino); pfree(s); break; } } } } } struct lswglob_context { struct file_lex_position *oflp; struct secret **psecrets; }; static void process_secret_files(unsigned count, char **files, struct lswglob_context *context, struct logger *logger UNUSED) { for (unsigned i = 0; i < count; i++) { const char *file = files[i]; struct file_lex_position *flp = NULL; if (lexopen(&flp, file, false, context->oflp)) { llog(RC_LOG, flp->logger, "loading secrets from \"%s\"", file); flushline(flp, "file starts with indentation (continuation notation)"); process_secret_records(flp, context->psecrets); lexclose(&flp); } } } static void process_secrets_file(struct file_lex_position *oflp, struct secret **psecrets, const char *file_pat) { if (oflp->depth > 10) { llog(RC_LOG, oflp->logger, "preshared secrets file \"%s\" nested too deeply", file_pat); return; } struct lswglob_context context = { .oflp = oflp, .psecrets = psecrets, }; if (!lswglob(file_pat, "secrets", process_secret_files, &context, oflp->logger)) { llog(RC_LOG, oflp->logger, "no secrets filename matched \"%s\"", file_pat); } } 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->kind) { case SECRET_PSK: pfreeany(s->u.preshared); break; case SECRET_PPK: pfreeany(s->u.ppk); break; case SECRET_XAUTH: pfreeany(s->u.preshared); break; case SECRET_RSA: case SECRET_ECDSA: secret_pubkey_stuff_delref(&s->u.pubkey, HERE); break; default: bad_case(s->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 */ void pubkey_delref_where(struct pubkey **pkp, where_t where) { const struct logger *logger = &global_logger; struct pubkey *pk = delref_where(pkp, logger, where); if (pk != NULL) { free_id_content(&pk->id); /* algorithm-specific freeing */ pk->content.type->free_pubkey_content(&pk->content); pfree(pk); } } /* * Free a public key record. * As a convenience, this returns a pointer to next. */ struct pubkey_list *free_public_keyentry(struct pubkey_list *p) { struct pubkey_list *nxt = p->next; if (p->key != NULL) 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, 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; } } struct secret_pubkey_stuff *secret_pubkey_stuff_addref(struct secret_pubkey_stuff *pks, where_t where) { return addref_where(pks, where); } void secret_pubkey_stuff_delref(struct secret_pubkey_stuff **pks, where_t where) { struct secret_pubkey_stuff *last = delref_where(pks, &global_logger, where); if (last != NULL) { SECKEY_DestroyPrivateKey(last->private_key); last->content.type->free_pubkey_content(&last->content); pfree(last); } } static err_t add_private_key(struct secret **secrets, struct secret_pubkey_stuff **pks, SECKEYPublicKey *pubk, SECItem *ckaid_nss, const struct pubkey_type *type, SECKEYPrivateKey *private_key) { struct pubkey_content content; err_t err = type->extract_pubkey_content(&content, pubk, ckaid_nss); if (err != NULL) { return err; } passert(content.type == type); pexpect(content.ckaid.len > 0); pexpect(content.keyid.keyid[0] != '\0'); struct secret *s = alloc_thing(struct secret, "pubkey secret"); s->kind = type->private_key_kind; s->line = 0; /* make an unpacked copy of the private key */ s->u.pubkey = refcnt_alloc(struct secret_pubkey_stuff, HERE); s->u.pubkey->private_key = copy_private_key(private_key); s->u.pubkey->content = content; add_secret(secrets, s, "lsw_add_rsa_secret"); *pks = s->u.pubkey; return NULL; } static err_t find_or_load_private_key_by_cert_3(struct secret **secrets, CERTCertificate *cert, struct secret_pubkey_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, struct secret_pubkey_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->u.pubkey; *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, struct secret_pubkey_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, struct secret_pubkey_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, struct secret_pubkey_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, struct secret_pubkey_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->u.pubkey; *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) { id_buf idb; return diag("NSS: could not create public key with ID '%s': certificate '%s' has an unknown key kind", str_id(id, &idb), cert->nickname); } 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 */ id_buf idb; return diag("NSS: could not create public key with ID '%s': extract CKAID from certificate '%s' failed", str_id(id, &idb), 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); id_buf idb; return diag("NSS: could not create public key with ID '%s': %s", str_id(id, &idb), 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; } id_buf idb; ldbg(logger, "creating pubkey for ID %s", str_id(id, &idb)); /* * 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) { id_buf idb; return diag("NSS: could not create public key with ID '%s': extracting public key from certificate '%s' failed", str_id(id, &idb), cert->nickname); } diag_t d = create_pubkey_from_cert_1(id, cert, pubkey_nss, pk, logger); SECKEY_DestroyPublicKey(pubkey_nss); return d; } libreswan-5.2/lib/libswan/shunk.c000066400000000000000000000200631475767661000170730ustar00rootroot00000000000000/* 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() */ #include "lswalloc.h" /* for over_alloc_things() */ /* * 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, size_t 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_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 = hunk_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 = hunk_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; } /* * Convert INPUT to an unsigned. * * If OUTPUT is NULL, INPUT must only contain the numeric value, else * OUTPUT is set to any trailing characters. */ 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))) { hunk_strcaseeat(&input, "0x"); base = 16; } else { base = 10; } } else if (hunk_strcasestarteq(input, "0b")) { if (char_isbdigit(hunk_char(input, 2))) { hunk_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 = hunk_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; } err_t shunk_to_decimal(shunk_t input, shunk_t *cursor, uintmax_t *decimal, uintmax_t *numerator, uintmax_t *denominator) { *decimal = 0; *numerator = 0; *denominator = 0; /* [] */ bool have_decimal = false; if (is_digit(input)) { err_t err = shunk_to_uintmax(input, &input, 10/*base*/, decimal); if (err != NULL) { return err; } have_decimal = true; } /* [.] */ if (is_char(input, '.')) { /* drop '.' */ input = hunk_slice(input, 1, input.len); /* need to handle .01 */ shunk_t tmp = input; /* reject ".???", allow "0." and ".0" */ err_t err = shunk_to_uintmax(input, &input, 10/*base*/, numerator); if (err != NULL && !have_decimal) { return "invalid decimal fraction"; } *denominator = 1; for (ptrdiff_t s = 0; s < input.ptr - tmp.ptr; s++) { (*denominator) *= 10; } } else if (!have_decimal) { return "invalid decimal"; } /* no cursor means no trailing input */ if (cursor == NULL) { if (input.len > 0) { return "unexpected input at end"; } return NULL; } *cursor = input; return NULL; } struct shunks *shunks(shunk_t input, const char *delims, enum shunks_opt opt, where_t where) { ldbgf(DBG_TMI, &global_logger, "%s() input=\""PRI_SHUNK"\" delims=\"%s\"", __func__, pri_shunk(input), delims); /* * Allocate a minimal buffer. Will grow it as more tokens are * found. */ size_t tokens_size = sizeof(struct shunks); struct shunks *tokens = alloc_bytes(tokens_size, where->func); shunk_t cursor = input; while (true) { char delim; shunk_t token = shunk_token(&cursor, &delim, delims); if (token.ptr == NULL) { break; } if (token.len == 0) { if (opt == EAT_EMPTY_SHUNKS) { /* eat spaces when part of delims */ ldbgf(DBG_TMI, &global_logger, "%s() pass 1 eat empty", __func__); continue; } tokens->kept_empty_shunks = true; } ldbgf(DBG_TMI, &global_logger, "%s() [%u] \""PRI_SHUNK"\"", __func__, tokens->len, pri_shunk(token)); /* grow by one shunk_t */ void *new = tokens; size_t new_size = tokens_size + sizeof(shunk_t); realloc_bytes(&new, tokens_size, new_size, where->func); tokens = new; tokens_size = new_size; /* save */ tokens->list[tokens->len] = token; tokens->len++; } return tokens; } libreswan-5.2/lib/libswan/sparse_names.c000066400000000000000000000076101475767661000204260ustar00rootroot00000000000000/* * 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 "constants.h" /* for strcaseeq() */ #include "sparse_names.h" #include "jambuf.h" /* look up enum names in a sparse_names */ const struct sparse_name *sparse_lookup(const struct sparse_names *names, shunk_t name) { for (const struct sparse_name *sn = names->list; sn->name != NULL; sn++) { if (hunk_strcaseeq(name, sn->name)) { return sn; } } return NULL; } /* * find or construct a string to describe an sparse value */ static const char *find_sparse(const struct sparse_names *sn, unsigned long val, bool shorten) { for (const struct sparse_name *p = sn->list; p->name != NULL; p++) { if (p->value == val) { if (!shorten || sn->prefix == NULL) { return p->name; } size_t pl = strlen(sn->prefix); if (strneq(p->name, sn->prefix, pl)) { return p->name + pl; } return p->name; } } return NULL; } bool sparse_long(const struct sparse_names *sn, unsigned long val, sparse_buf *b) { b->buf = find_sparse(sn, val, /*shorten*/false); if (b->buf != NULL) { return true; } bad_name(val, b); return false; } bool sparse_short(const struct sparse_names *sn, unsigned long val, sparse_buf *b) { b->buf = find_sparse(sn, val, /*shorten*/true); if (b->buf != NULL) { return true; } bad_name(val, b); return false; } size_t jam_sparse_long(struct jambuf *buf, const struct sparse_names *sn, unsigned long val) { const char *name = find_sparse(sn, val, /*shorten?*/false); if (name != NULL) { return jam_string(buf, name); } return jam_bad(buf, sn->prefix, val); } size_t jam_sparse_short(struct jambuf *buf, const struct sparse_names *sn, unsigned long val) { const char *name = find_sparse(sn, val, /*shorten?*/true); if (name != NULL) { return jam_string(buf, name); } return jam_bad(buf, sn->prefix, val); } const char *str_sparse_long(const struct sparse_names *sn, unsigned long val, sparse_buf *b) { sparse_long(sn, val, b); return b->buf; } const char *str_sparse_short(const struct sparse_names *sn, unsigned long val, sparse_buf *b) { sparse_short(sn, val, b); return b->buf; } const char *sparse_sparse_name(const struct sparse_sparse_names *ssn, unsigned long v1, unsigned long v2) { const struct sparse_sparse_name *ssd = ssn->list; while (ssd->names != NULL) { if (ssd->value == v1) { for (const struct sparse_name *p = ssd->names->list; p->name != NULL; p++) { if (p->value == v2) { return p->name; } } return NULL; } ssd++; } return NULL; } size_t jam_sparse_names(struct jambuf *buf, const struct sparse_names *names, const char *separator) { const char *sep = ""; size_t s = 0; for (const struct sparse_name *i = names->list; i->name != NULL; i++) { const struct sparse_name *j = names->list; while (j < i && j->value != i->value) { j++; } /* not a duplicate */ if (i == j) { s += jam_string(buf, sep); s += jam_string(buf, i->name); sep = separator; } } return s; } libreswan-5.2/lib/libswan/state_category_names.c000066400000000000000000000022631475767661000221450ustar00rootroot00000000000000/* state categories, 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 "state_category.h" #include "enum_names.h" #include "lswcdefs.h" /* state categories */ static const char *const cat_name[CAT_ROOF] = { [CAT_UNKNOWN] = "unknown", [CAT_HALF_OPEN_IKE_SA] = "half-open IKE SA", [CAT_OPEN_IKE_SA] = "open IKE SA", [CAT_ESTABLISHED_IKE_SA] = "established IKE SA", [CAT_OPEN_CHILD_SA] = "open Child SA", [CAT_ESTABLISHED_CHILD_SA] = "established Child SA", [CAT_INFORMATIONAL] = "informational", [CAT_IGNORE] = "ignore", }; const struct enum_names state_category_names = { 0, CAT_ROOF - 1, ARRAY_REF(cat_name), "", NULL }; libreswan-5.2/lib/libswan/subnetof.3.xml000066400000000000000000000057341475767661000203170ustar00rootroot00000000000000 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. AUTHOR Paul Wouters libreswan-5.2/lib/libswan/terminate_reason_names.c000066400000000000000000000047261475767661000224750ustar00rootroot00000000000000/* delete reason table, for libreswan * * Copyright (C) 1997 Angelos D. Keromytis. * Copyright (C) 1998-2001,2013-2014 D. Hugh Redelmeier * Copyright (C) 2003-2008 Michael C Richardson * Copyright (C) 2003-2009 Paul Wouters * Copyright (C) 2008-2009 David McCullough * Copyright (C) 2009,2012 Avesh Agarwal * Copyright (C) 2012-2013 Paul Wouters * Copyright (C) 2012 Wes Hardaker * Copyright (C) 2013 Matt Rogers * Copyright (C) 2013 Tuomo Soini * Copyright (C) 2014,2017 Antony Antony * Copyright (C) 2015-2019 Andrew Cagney * Copyright (C) 2015-2019 Paul Wouters * Copyright (C) 2017 Vukasin Karadzic * Copyright (C) 2015-2019 Paul Wouters * Copyright (C) 2017 Mayank Totale * Copyright (C) 2020 Yulia Kuzovkova * Copyright (C) 2021 Paul Wouters * Copyright (C) 2020 Nupur Agrawal * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include "terminate_reason.h" #include "lswcdefs.h" /* for ARRAY_REF() */ #include "enum_names.h" static const char *terminate_reason_name[] = { [REASON_UNKNOWN] = "other", [REASON_COMPLETED] = "completed", [REASON_EXCHANGE_TIMEOUT] = "exchange-timeout", [REASON_CRYPTO_TIMEOUT] = "crypto-timeout", [REASON_TOO_MANY_RETRANSMITS] = "too-many-retransmits", [REASON_SUPERSEDED_BY_NEW_SA] = "superseeded-by-new-sa", [REASON_AUTH_FAILED] = "auth-failed", [REASON_TRAFFIC_SELECTORS_FAILED] = "ts-unacceptable", [REASON_CRYPTO_FAILED] = "crypto-failed", [REASON_DELETED] = "deleted", }; const struct enum_names terminate_reason_names = { TERMINATE_REASON_FLOOR, TERMINATE_REASON_ROOF-1, ARRAY_REF(terminate_reason_name), .en_prefix = NULL, }; libreswan-5.2/lib/libswan/test_buffer.c000066400000000000000000000114661475767661000202620ustar00rootroot00000000000000/* * 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 "crypt_mac.h" #include "test_buffer.h" #include "ike_alg.h" #include "lswlog.h" /* * 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, struct logger *logger, where_t where UNUSED) { if (LDBGP(DBG_CRYPT, logger)) { LDBG_log(logger, "%s() %s: input \"%s\"", __func__, prefix, original); } chunk_t chunk; if (startswith(original, "0x")) { chunk = chunk_from_hex(original + strlen("0x"), original); } else { chunk = alloc_chunk(strlen(original), original); memcpy(chunk.ptr, original, chunk.len); } if (LDBGP(DBG_CRYPT, logger)) { LDBG_log(logger, "%s() output:", __func__); LDBG_hunk(logger, chunk); } 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. */ struct crypt_mac decode_to_mac(const char *prefix, const char *original, struct logger *logger, where_t where UNUSED) { if (LDBGP(DBG_CRYPT, logger)) { LDBG_log(logger, "%s() %s: input \"%s\"", __func__, prefix, original); } struct crypt_mac mac; if (startswith(original, "0x")) { chunk_t chunk = chunk_from_hex(original + strlen("0x"), original); PASSERT(logger, chunk.len <= sizeof(mac.ptr/*array*/)); mac.len = chunk.len; memcpy(mac.ptr, chunk.ptr, mac.len); free_chunk_content(&chunk); } else { mac.len = strlen(original); PASSERT(logger, mac.len <= sizeof(mac.ptr/*array*/)); memcpy(mac.ptr, original, mac.len); } if (LDBGP(DBG_CRYPT, logger)) { LDBG_log(logger, "%s() output:", __func__); LDBG_hunk(logger, mac); } return mac; } PK11SymKey *decode_hex_to_symkey(const char *prefix, const char *string, struct logger *logger, where_t where UNUSED) { 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 char *verifying, const void *expected, size_t expected_size, const void *actual, size_t actual_size, struct logger *logger, where_t where) { if (expected_size != actual_size) { llog_pexpect(logger, where, "%s: %s: expected length %zd but got %zd", desc, verifying, 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. */ llog_pexpect(logger, where, "%s: %s: bytes at %zd differ, expected %02x found %02x", desc, verifying, i, e, a); return false; } } if (LDBGP(DBG_CRYPT, logger)) { LDBG_log(logger, "%s() %s: %s: ok", __func__, desc, verifying); } return true; } /* verify that expected is the same as actual */ bool verify_symkey(const char *desc, const char *verifying, chunk_t expected, PK11SymKey *actual, struct logger *logger, where_t where) { if (expected.len != sizeof_symkey(actual)) { llog_pexpect(logger, where, "%s: %s: expected length %zd but got %zd", desc, verifying, expected.len, sizeof_symkey(actual)); return false; } chunk_t chunk = chunk_from_symkey(desc, actual, logger); bool ok = verify_hunk(desc, verifying, expected, chunk, logger, where); 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, where_t where) { chunk_t raw_key = decode_to_chunk("raw_key", encoded_key, logger, where); PK11SymKey *symkey = encrypt_key_from_hunk("symkey", encrypt_desc, raw_key, logger); free_chunk_content(&raw_key); return symkey; } libreswan-5.2/lib/libswan/timescale.c000066400000000000000000000032451475767661000177140ustar00rootroot00000000000000/* 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 "scale.h" #include "lswcdefs.h" #include "constants.h" /* for secs_per_* */ #include "passert.h" static const struct scale scales[] = { [TIMESCALE_MICROSECONDS] = { "us", (uintmax_t)1, }, [TIMESCALE_MILLISECONDS] = { "ms", (uintmax_t)1 * 1000, }, [TIMESCALE_SECONDS] = { "s", (uintmax_t)1 * 1000 * 1000, }, [TIMESCALE_MINUTES] = { "m", (uintmax_t)1 * 1000 * 1000 * secs_per_minute, }, [TIMESCALE_HOURS] = { "h", (uintmax_t)1 * 1000 * 1000 * secs_per_hour, }, [TIMESCALE_DAYS] = { "d", (uintmax_t)1 * 1000 * 1000 * secs_per_day, }, [TIMESCALE_WEEKS] = { "w", (uintmax_t)1 * 1000 * 1000 * secs_per_day * 7, }, }; const struct scales timescales = { .base = 10, .scale = { ARRAY_REF(scales) }, }; const struct scale *ttotimescale(shunk_t cursor, enum timescale default_timescale) { return ttoscale(cursor, ×cales, default_timescale); } const struct scale *timescale(enum timescale scale) { passert(scale < elemsof(scales)); return &scales[scale]; } libreswan-5.2/lib/libswan/ttoaddress.3.xml000066400000000000000000000350031475767661000206360ustar00rootroot00000000000000 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 */ AUTHOR Paul Wouters libreswan-5.2/lib/libswan/ttoaddress_dns.c000066400000000000000000000062721475767661000207710ustar00rootroot00000000000000/* * 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 freeaddrinfo(), getaddrinfo() */ #include /* for AF_INET/AF_INET6/AF_UNSPEC */ #include "passert.h" #include "ip_address.h" #include "ip_info.h" #include "lswalloc.h" /* * 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)"; } } /* * If getaddrinfo succeeded, res must be non-empty. * Make this assumption manifest: it quiets lclint. */ passert(res != NULL); /* * 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-5.2/lib/libswan/ttoaddress_num.c000066400000000000000000000164151475767661000210040ustar00rootroot00000000000000/* * 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 "ip_address.h" #include "ip_info.h" 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 (!hunk_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, 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 (hunk_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, u); return NULL; } libreswan-5.2/lib/libswan/ttoaddresses_num.c000066400000000000000000000052451475767661000213330ustar00rootroot00000000000000/* 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" #include "ip_info.h" #define ip_token ip_address #define ip_tokens ip_addresses diag_t ttoaddresses_num(shunk_t input, const char *delims, const struct ip_info *input_afi, ip_tokens *output) { zero(output); if (input.ptr == NULL) { return NULL; } dbg("%s() input: "PRI_SHUNK, __func__, pri_shunk(input)); /* * Two passes: * * Pass 1: determine the number of tokens. * Pass 1.5: allocate list pointers; zero counters * Pass 2: save the values in separate IPv[46] lists. */ struct shunks *tokens = shunks(input, delims, EAT_EMPTY_SHUNKS, HERE); /* must free */ for (unsigned pass = 1; pass <= 2; pass++) { unsigned nr_tokens = 0; FOR_EACH_ITEM(token, tokens) { passert(token->len > 0); ip_token tmp_token; err_t e = ttoaddress_num(*token, input_afi, &tmp_token); const struct ip_info *afi = address_info(tmp_token); switch (pass) { case 1: /* validate during first pass */ if (e != NULL) { diag_t d = diag(PRI_SHUNK" invalid, %s", pri_shunk(*token), e); pfree(tokens); return d; } break; case 2: /* save value during second pass */ passert(e == NULL); output->ip[afi->ip_index].list[output->ip[afi->ip_index].len] = tmp_token; break; } /* advance the lengths */ output->ip[afi->ip_index].len++; nr_tokens++; } if (nr_tokens == 0) { pfree(tokens); return NULL; } switch (pass) { case 1: /* * Pass 1.5: Allocate. */ dbg("%s() nr tokens %u", __func__, nr_tokens); output->list = alloc_things(ip_token, nr_tokens, "selectors"); FOR_EACH_ELEMENT(afi, ip_families) { enum ip_index ip = afi->ip_index; output->ip[ip].list = output->list + output->len; output->len += output->ip[ip].len; output->ip[ip].len = 0; /* ready for second pass */ } passert(output->len == nr_tokens); break; case 2: passert(nr_tokens == output->len); break; } } pfree(tokens); return NULL; } libreswan-5.2/lib/libswan/ttobinary-iec-60027-2.c000066400000000000000000000033361475767661000213330ustar00rootroot00000000000000/* 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; shunk_t cursor = shunk1(t); const char *suffix = (prefix_B ? " Bytes" : ""); uint64_t decimal, numerator, denominator; err_t err = shunk_to_decimal(cursor, &cursor, &decimal, &numerator, &denominator); if (err != NULL) { return diag("bad binary%s value \"%s\": %s", suffix, t, err); } const struct scale *scale = (prefix_B ? ttobinarybytesscale(cursor) : ttobinaryscale(cursor)); if (scale == NULL) { return diag("unrecognized binary%s multiplier \""PRI_SHUNK"\"", suffix, pri_shunk(cursor)); } uintmax_t binary; err_t e = scale_decimal(scale, decimal, numerator, denominator, &binary); if (e != NULL) { return diag("invalid binary%s \"%s\", %s", suffix, t, e); } *r = binary; return NULL; } libreswan-5.2/lib/libswan/ttobool.c000066400000000000000000000020511475767661000174220ustar00rootroot00000000000000/* text to boolean, for libreswan * * Copyright (C) 2023 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY 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 ttobool() et.al. */ /* mimic parser.lex */ err_t ttobool(const char *t, bool *b) { if (strcaseeq(t, "1") || strcaseeq(t, "yes") || strcaseeq(t, "true") || strcaseeq(t, "on")) { *b = true; return NULL; } if (strcaseeq(t, "0") || strcaseeq(t, "no") || strcaseeq(t, "false") || strcaseeq(t, "off")) { *b = false; return NULL; } *b = false; return "invalid"; } libreswan-5.2/lib/libswan/ttocidr_num.c000066400000000000000000000033621475767661000202750ustar00rootroot00000000000000/* ip cidr, for libreswan * * Copyright (C) 2019-2024 Andrew Cagney * Copyright (C) 2023 Brady Johnson * Copyright (C) 2021 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 "passert.h" #include "jambuf.h" #include "lswlog.h" #include "ip_cidr.h" #include "ip_info.h" err_t ttocidr_num(shunk_t src, const struct ip_info *afi, ip_cidr *cidr) { *cidr = unset_cidr; err_t err; /* split CIDR into ADDRESS [ "/" MASK ]. */ char slash = '\0'; shunk_t address = shunk_token(&src, &slash, "/"); shunk_t mask = src; /* 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_info(addr); passert(afi != NULL); /* parse [ "/" MASK ] */ uintmax_t prefix_len = afi->mask_cnt; if (slash == '/') { /* don't use bound - error is confusing */ err = shunk_to_uintmax(mask, NULL, 0, &prefix_len); if (err != NULL) { /* not a number */ return err; } if (prefix_len > (uintmax_t)afi->mask_cnt) { return "mask is too big"; } } /* combine */ *cidr = cidr_from_raw(HERE, afi, addr.bytes, prefix_len); return NULL; } libreswan-5.2/lib/libswan/ttodata.3.xml000066400000000000000000000253571475767661000201350ustar00rootroot00000000000000 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. AUTHOR Paul Wouters libreswan-5.2/lib/libswan/ttodata.c000066400000000000000000000206501475767661000174050ustar00rootroot00000000000000/* * 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 */ 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) */ { 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; 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; 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 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++; } 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 */ void *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); } 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); 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); 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 } libreswan-5.2/lib/libswan/ttodeltatime.c000066400000000000000000000033561475767661000204500ustar00rootroot00000000000000/* 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 #include "diag.h" #include "deltatime.h" #include "timescale.h" #include "passert.h" #include "lswlog.h" diag_t ttodeltatime(const char *t, deltatime_t *d, enum timescale default_timescale) { *d = deltatime_zero; shunk_t cursor = shunk1(t); /* parse: * * [][] * * Probably allows messed up values such as "." */ /* [][.] */ uintmax_t decimal; uintmax_t numerator; uintmax_t denominator; err_t err = shunk_to_decimal(cursor, &cursor, &decimal, &numerator, &denominator); if (err != NULL) { return diag("invalid duration \"%s\", %s", t, err); } /* [] */ const struct scale *scale = ttotimescale(cursor, default_timescale); if (scale == NULL) { return diag("duration \"%s\" has an unrecognized multiplier \""PRI_SHUNK"\"", t, pri_shunk(cursor)); } uintmax_t microseconds; err_t e = scale_decimal(scale, decimal, numerator, denominator, µseconds); if (e != NULL) { return diag("invalid duration \"%s\", %s", t, e); } *d = deltatime_from_microseconds(microseconds); return NULL; } libreswan-5.2/lib/libswan/ttoips_num.c000066400000000000000000000035671475767661000201560ustar00rootroot00000000000000/* cloning an subnet list, for libreswan * * Copyright (C) 2024 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY 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_info.h" #include "diag.h" #include "lswalloc.h" #include "passert.h" #include "lswlog.h" diag_t ttoips_num(shunk_t input, const struct ip_info *afi, void **ptr, unsigned *len, err_t (*parse_token)(shunk_t, const struct ip_info *, void **ptr, unsigned len)) { *ptr = NULL; *len = 0; /* #subnet= */ if (input.ptr == NULL) { return NULL; } /* subnet= */ if (input.len == 0) { return NULL; } /* * Tokenisze. * * Reduce sequences such as "A ,, " to just A, and ", ," to an * empty list. */ struct shunks *tokens = shunks(input, ", ", EAT_EMPTY_SHUNKS, HERE); /* must free */ /* * The result should be non-empty. */ if (tokens->len == 0) { pfree(tokens); return diag("empty field"); } /* * Now parse the fields and build the table. */ FOR_EACH_ITEM(token, tokens) { passert(token->len > 0); dbg("parsing "PRI_SHUNK" %p %u", pri_shunk(*token), *ptr, (*len)); err_t e = parse_token(*token, afi, ptr, (*len)++); /* validate during first pass */ if (e != NULL) { diag_t d = diag(PRI_SHUNK" invalid, %s", pri_shunk(*token), e); pfree(tokens); pfreeany(*ptr); (*len) = 0; return d; } passert((*ptr) != NULL); passert((*len) > 0); } pfree(tokens); return NULL; } libreswan-5.2/lib/libswan/ttoport.c000066400000000000000000000040111475767661000174510ustar00rootroot00000000000000/* ttoport, 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" #include "lswalloc.h" err_t ttoport(shunk_t service_name, ip_port *port) { *port = unset_port; /* * Try converting it to a number; use SHUNK's variant of strtoul() * as it is more strict around using the full string. * * Number conversion should be checked first, because the service * name lookup is very expensive in comparision. */ uintmax_t l; err_t e = shunk_to_uintmax(service_name, NULL/*trailing-chars-not-allowed*/, 0/*any-base*/, &l); if (e == NULL) { if (l > 0xffff) return "must be between 0 and 65535"; /* success */ *port = ip_hport(l); return NULL; } /* * It's not a number, so trying to resolve it by name. * * XXX: the getservbyname() call requires a NUL terminated * string but SERVICE_NAME, being a shunk_t may not include * that; hence the clone to create a proper string. */ char *service_string = clone_hunk_as_string(service_name, "service name"); const struct servent *service = getservbyname(service_string, NULL); pfree(service_string); if (service != NULL) { /* success */ *port = ip_nport(service->s_port/*network-order*/); return NULL; } /* 'e' still holds a number conversion error. */ return e; } libreswan-5.2/lib/libswan/ttoprotocol.c000066400000000000000000000032721475767661000203360ustar00rootroot00000000000000/* 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 struct ip_protocol **proto) { /* look it up */ *proto = protocol_from_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_from_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_from_ipproto(protocol->p_proto); return NULL; } /* make something up */ return err; } libreswan-5.2/lib/libswan/ttorange_num.c000066400000000000000000000057701475767661000204550ustar00rootroot00000000000000/* 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 "jambuf.h" #include "ip_range.h" #include "ip_info.h" #include "passert.h" #include "lswlog.h" /* for pexpect() */ /* * ttorange_num() * * Convert "addr1-addr2" or subnet/mask to an address range. */ err_t ttorange_num(shunk_t input, const struct ip_info *afi, ip_range *dst) { *dst = unset_range; err_t err; shunk_t cursor = input; /* 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_info(start_address); passert(afi != NULL); switch (sep) { case '\0': { /* single address */ *dst = range_from_raw(HERE, afi, 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_bytes_blit(afi, start_address.bytes, &keep_routing_prefix, &clear_host_identifier, maskbits), ip_bytes_blit(afi, start_address.bytes, &keep_routing_prefix, &set_host_identifier, maskbits)); 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_info(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, start_address.bytes, end_address.bytes); return NULL; } default: /* SEP is invalid, but being more specific means diag_t */ return "expecting '-' or '/'"; } } libreswan-5.2/lib/libswan/ttoranges_num.c000066400000000000000000000037031475767661000206320ustar00rootroot00000000000000/* cloning an range 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_range.h" #include "ip_info.h" #define ip_token ip_range #define ip_tokens ip_ranges diag_t ttoranges_num(shunk_t input, const char *delims, const struct ip_info *input_afi, ip_ranges *output) { zero(output); if (input.ptr == NULL) { return NULL; } dbg("%s() input: "PRI_SHUNK, __func__, pri_shunk(input)); /* * Two passes: * * Pass 1: determine the number of tokens. * Pass 1.5: allocate list pointers; zero counters * Pass 2: save the values. */ struct shunks *tokens = shunks(input, delims, KEEP_EMPTY_SHUNKS, HERE); /* must free */ if (tokens->kept_empty_shunks) { pfree(tokens); return diag("empty field"); } dbg("%s() nr tokens %u", __func__, tokens->len); output->list = alloc_things(ip_token, tokens->len, "selectors"); output->len = tokens->len; unsigned nr = 0; FOR_EACH_ITEM(token, tokens) { passert(token->len > 0); ip_token tmp_token; err_t e = ttorange_num(*token, input_afi, &tmp_token); /* validate during first pass */ if (e != NULL) { diag_t d = diag(PRI_SHUNK" invalid, %s", pri_shunk(*token), e); pfree(tokens); pfree(output->list); zero(output); return d; } output->list[nr++] = tmp_token; } pfree(tokens); return NULL; } libreswan-5.2/lib/libswan/ttorealtime.c000066400000000000000000000032351475767661000202760ustar00rootroot00000000000000/* time objects and functions, for libreswan * * Copyright (C) 2023 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. */ #ifdef linux #define _XOPEN_SOURCE /* expose strptime() */ #endif #include /* for __need_clockid_t */ #include #include #include "lswcdefs.h" /* FOR_EACH_ELEMENT() */ #include "realtime.h" diag_t ttorealtime(const char *t, realtime_t *rt) { /* manual says to pre-initialize */ struct tm tm = {0}; const char *end = strchr(t, '\0'); /* try to parse it */ const char *format[] = { "%Y-%m-%d %H:%M:%S", "%Y-%m-%d", }; FOR_EACH_ELEMENT(f, format) { tm = (struct tm) {0}; if (strptime(t, *f, &tm) == end) { /* convert to time_t */ time_t time = mktime(&tm); if (time == (time_t)-1) { return diag("mktime(strptime(\"%s\",\"%s\")) failed", *f, t); } /* and convert that to realtime_t */ *rt = realtime(time); return NULL; } } /* hack to accumulate all possible formats in error */ diag_t d = diag("\"%s\"", format[0]); FOR_EACH_ELEMENT_FROM_1(f, format) { d = diag_diag(&d, "\"%s\", ", *f); } return diag_diag(&d, "strptime() failed, tried "); } libreswan-5.2/lib/libswan/ttosa.3.xml000066400000000000000000000246221475767661000176210ustar00rootroot00000000000000 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 */ AUTHOR Paul Wouters libreswan-5.2/lib/libswan/ttosaid.c000066400000000000000000000061401475767661000174120ustar00rootroot00000000000000/* * 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 "passert.h" #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" }, { 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_from_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 (hunk_strcaseeat(&input, ".")) { afi = &ipv4_info; base = 16; } else if (hunk_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 (!hunk_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-5.2/lib/libswan/ttoselector_num.c000066400000000000000000000077111475767661000211760ustar00rootroot00000000000000/* 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" /* * Parse the selector: * *
*
/ *
/:/ <- NOTE *
/:/ * * new syntax required for: * *
-
:/- * */ err_t ttoselector_num(shunk_t cursor, const struct ip_info *afi, /* could be NULL */ ip_selector *dst, ip_address *nonzero_host) { *dst = unset_selector; *nonzero_host = unset_address; err_t oops; /* *
[ / [ / [ / ] ] ] */ char prefix_length_separator; shunk_t address_token = shunk_token(&cursor, &prefix_length_separator, "/"); #if 0 fprintf(stderr, "address="PRI_SHUNK"\n", pri_shunk(address_token)); #endif ip_address address; oops = ttoaddress_num(address_token, afi/*possibly NULL*/, &address); if (oops != NULL) { return oops; } if (afi == NULL) { afi = address_info(address); } passert(afi != NULL); /* * [ / [ / ] ] * * XXX: also allow :protocol/port for now. */ uintmax_t prefix_length; shunk_t prefix_length_token = shunk_token(&cursor, NULL, "/:"); #if 0 fprintf(stderr, "prefix-bits="PRI_SHUNK"\n", pri_shunk(prefix_length_token)); #endif if (prefix_length_token.len > 0) { /* "1.2.3.4/123" or "1.2.3.4/123/..." */ uintmax_t tmp = 0; oops = shunk_to_uintmax(prefix_length_token, NULL, 0, &tmp); if (oops != NULL) { return oops; } if (tmp > afi->mask_cnt) { return "too large"; } prefix_length = tmp; } else { prefix_length = afi->mask_cnt; } /* * / */ const struct ip_protocol *protocol; shunk_t protocol_token = shunk_token(&cursor, NULL, "/"); #if 0 fprintf(stderr, "protocol="PRI_SHUNK"\n", pri_shunk(protocol_token)); #endif if (protocol_token.len > 0) { /* "1.2.3.4//udp" or "1.2.3.4//udp/" */ protocol = protocol_from_shunk(protocol_token); if (protocol == NULL) { return "unknown protocol"; } } else { protocol = &ip_protocol_all; } /* * ... */ ip_port port; shunk_t port_token = cursor; #if 0 fprintf(stderr, "port="PRI_SHUNK"\n", pri_shunk(port_token)); #endif if (port_token.len > 0) { /* 1.2.3.4/32/udp/10 */ 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 { port = unset_port; } /* * Now form the routing prefix. If it has less bits than the * address, zero them but return original address. Caller can * use that to log message when so desired. */ struct ip_bytes routing_prefix = ip_bytes_blit(afi, address.bytes, &keep_routing_prefix, &clear_host_identifier, prefix_length); if (ip_bytes_cmp(afi->ip_version, routing_prefix, afi->ip_version, address.bytes) != 0) { *nonzero_host = address; } struct ip_bytes hi = ip_bytes_blit(afi, routing_prefix, &keep_routing_prefix, &set_host_identifier, prefix_length); /* check host-part is zero */ *dst = selector_from_raw(HERE, afi, routing_prefix, hi, protocol, port); return NULL; } libreswan-5.2/lib/libswan/ttoselectors_num.c000066400000000000000000000057251475767661000213640ustar00rootroot00000000000000/* cloning an selector 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_selector.h" #include "ip_info.h" #define ip_token ip_selector #define ip_tokens ip_selectors diag_t ttoselectors_num(shunk_t input, const char *delims, const struct ip_info *input_afi, ip_tokens *output, ip_address *nonzero_host) { zero(output); *nonzero_host = unset_address; if (input.ptr == NULL) { return NULL; } dbg("%s() input: "PRI_SHUNK, __func__, pri_shunk(input)); /* * Two passes: * * Pass 1: determine the number of tokens. * Pass 1.5: allocate list pointers; zero counters * Pass 2: save the values in separate IPv[46] lists. */ struct shunks *tokens = shunks(input, delims, KEEP_EMPTY_SHUNKS, HERE); /* must free */ if (tokens->kept_empty_shunks) { pfree(tokens); return diag("empty field"); } for (unsigned pass = 1; pass <= 2; pass++) { unsigned nr_tokens = 0; FOR_EACH_ITEM(token, tokens) { passert(token->len > 0); ip_token tmp_token; ip_address tmp_nonzero; err_t e = ttoselector_num(*token, input_afi, &tmp_token, &tmp_nonzero); const struct ip_info *afi = selector_info(tmp_token); switch (pass) { case 1: /* validate during first pass */ if (e != NULL) { diag_t d = diag(PRI_SHUNK" invalid, %s", pri_shunk(*token), e); pfree(tokens); return d; } if (tmp_nonzero.is_set && !nonzero_host->is_set) { *nonzero_host = tmp_nonzero; /* save first */ } break; case 2: /* save value during second pass */ passert(e == NULL); output->ip[afi->ip_index].list[output->ip[afi->ip_index].len] = tmp_token; break; } /* advance the lengths */ output->ip[afi->ip_index].len++; nr_tokens++; } if (nr_tokens == 0) { pfree(tokens); return NULL; } switch (pass) { case 1: /* * Pass 1.5: Allocate. */ dbg("%s() nr tokens %u", __func__, nr_tokens); output->list = alloc_things(ip_token, nr_tokens, "selectors"); FOR_EACH_ELEMENT(afi, ip_families) { enum ip_index ip = afi->ip_index; output->ip[ip].list = output->list + output->len; output->len += output->ip[ip].len; output->ip[ip].len = 0; /* ready for second pass */ } passert(output->len == nr_tokens); break; case 2: passert(nr_tokens == output->len); break; } } pfree(tokens); return NULL; } libreswan-5.2/lib/libswan/ttosubnet_num.c000066400000000000000000000057131475767661000206560ustar00rootroot00000000000000/* * 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_num(shunk_t src, const struct ip_info *afi, /* could be NULL */ ip_subnet *dst, ip_address *nonzero_host) { *dst = unset_subnet; *nonzero_host = unset_address; 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 = '\0'; shunk_t addr = shunk_token(&src, &slash, "/"); shunk_t mask = src; /* parse ADDR */ ip_address address; oops = ttoaddress_num(addr, afi, &address); if (oops != NULL) { return oops; } if (afi == NULL) { afi = address_info(address); } passert(afi != NULL); /* parse [ "/" MASK ] */ uintmax_t prefix_len = afi->mask_cnt; if (slash == '/') { /* eat entire MASK */ oops = shunk_to_uintmax(mask, NULL, 10, &prefix_len); if (oops != NULL) { if (afi == &ipv4_info) { /*1.2.3.0/255.255.255.0?*/ ip_address masktmp; oops = ttoaddress_num(mask, afi, &masktmp); if (oops != NULL) { return oops; } int i = ip_bytes_mask_len(afi, masktmp.bytes); if (i < 0) { return "non-contiguous or otherwise erroneous mask"; } prefix_len = i; } else { return "masks are not permitted for IPv6 addresses"; } } else if (prefix_len > afi->mask_cnt) { return "mask is too big"; } } /* check host-part is zero */ struct ip_bytes routing_prefix = ip_bytes_blit(afi, address.bytes, &keep_routing_prefix, &clear_host_identifier, prefix_len); if (ip_bytes_cmp(afi->ip_version, routing_prefix, afi->ip_version, address.bytes) != 0) { *nonzero_host = address; } *dst = subnet_from_raw(HERE, afi, routing_prefix, prefix_len); return NULL; } libreswan-5.2/lib/libswan/ttosubnets_num.c000066400000000000000000000030341475767661000210330ustar00rootroot00000000000000/* cloning an subnet list, for libreswan * * Copyright (C) 2024 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY 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_subnet.h" #include "ip_info.h" static err_t parse_subnets(shunk_t token, const struct ip_info *afi, void **ptr, unsigned len) { ip_subnet tmp_token; ip_address nonzero_host; err_t e = ttosubnet_num(token, afi, &tmp_token, &nonzero_host); if (e != NULL) { return e; } if (nonzero_host.is_set) { return "subnet has non-zero address identifier"; } /* save it */ ip_subnet *subnets = (*ptr); realloc_things(subnets, len, len+1, "subnets"); subnets[len] = tmp_token; (*ptr) = subnets; return NULL; } diag_t ttosubnets_num(shunk_t input, const struct ip_info *afi, ip_subnets *output) { zero(output); void *ptr = NULL; unsigned len = 0; diag_t d = ttoips_num(input, afi, &ptr, &len, parse_subnets); if (d != NULL) { return d; } output->list = ptr; output->len = len; return NULL; } libreswan-5.2/lib/libswan/unbound.c000066400000000000000000000211511475767661000174140ustar00rootroot00000000000000/* * 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 /* ditto */ #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 add_trust_anchors(unsigned count, char **files, struct lswglob_context *context UNUSED, struct logger *logger) { for (unsigned i = 0; i < count; i++) { const char *file = files[i]; int ugh = ub_ctx_add_ta_file(dns_ctx, file); if (ugh != 0) { llog(RC_LOG, logger, "ignored trusted key file %s: %s", file, ub_strerror(ugh)); } else { ldbg(logger, "added contents of trusted key file %s to unbound resolver context", file); } } } 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, 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, 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, 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, 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, logger, "dnssec-enable=yes but no dnssec-rootkey-file or trust anchors specified."); llog(RC_LOG, logger, "WARNING: DNSSEC validation disabled"); return; } else { llog(RC_LOG, 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, logger, "error adding dnssec root key: %s [errno: %s]", ub_strerror(ugh), strerror(e)); llog(RC_LOG, logger, "WARNING: DNSSEC validation disabled"); } } if (trusted == NULL) { dbg("no additional dnssec trust anchors defined via dnssec-trusted= option"); return; } if (!lswglob(trusted, "trusted anchor", add_trust_anchors, /*lswglob_context*/NULL, logger)) { llog(RC_LOG, logger, "no trust anchor files matched '%s'", trusted); } } /* * 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, const 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); /* * XXX: data_to_address() only requires the length >= * address-length. */ diag_t diag = data_to_address(result->data[0], (size_t)result->len[0], afi, ipaddr); if (diag != NULL) { llog_pexpect(logger, HERE, "invalid dns address record: %s", str_diag(diag)); pfree_diag(&diag); ub_resolve_free(result); return false; } ldbg(logger, "success for %s lookup", afi->ip_name); return true; } struct ub_ctx * get_unbound_ctx(void) { return dns_ctx; } libreswan-5.2/lib/libswan/v1_proposals.c000066400000000000000000000271561475767661000204050ustar00rootroot00000000000000/* 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) { struct logger *logger = parser->policy->logger; /* * 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))) { ldbgf(DBG_PROPOSAL_PARSER, logger, "skipping default %s", str_diag(parser->diag)); pfree_diag(&parser->diag); continue; } /* add it */ ldbgf(DBG_PROPOSAL_PARSER, logger, "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. */ const struct proposal_defaults *defaults = proposal->protocol->defaults; 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) { struct logger *logger = parser->policy->logger; ldbgf(DBG_PROPOSAL_PARSER, logger, "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-5.2/lib/libswan/v2_proposals.c000066400000000000000000000314361475767661000204020ustar00rootroot00000000000000/* 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) { struct logger *logger = parser->policy->logger; 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 ...? */ enum_buf vb; llog(RC_LOG, logger, "ignoring %s %s %s algorithm '"PRI_SHUNK"'", str_enum(&ike_version_names, parser->policy->version, &vb), parser->protocol->name, /* ESP|IKE|AH */ what, pri_shunk(print)); result = true; } else { ldbgf(DBG_PROPOSAL_PARSER, logger, "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) { const struct proposal_defaults *defaults = parser->protocol->defaults; 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) { struct logger *logger = parser->policy->logger; 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) { ldbgf(DBG_PROPOSAL_PARSER, logger, "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 */ \ ldbgf(DBG_PROPOSAL_PARSER, logger, "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 */ ldbgf(DBG_PROPOSAL_PARSER, logger, "- succeeded, advancing tokens"); tokens = prf_tokens; remove_duplicate_algorithms(parser, proposal, PROPOSAL_prf); } else { /* toss the result, but save the error */ ldbgf(DBG_PROPOSAL_PARSER, logger, "- 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) { ldbgf(DBG_PROPOSAL_PARSER, logger, "- 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 { ldbgf(DBG_PROPOSAL_PARSER, logger, " 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) { ldbgf(DBG_PROPOSAL_PARSER, logger, "-- 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) { ldbgf(DBG_PROPOSAL_PARSER, logger, "... 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) { struct logger *logger = parser->policy->logger; ldbgf(DBG_PROPOSAL_PARSER, logger, "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-5.2/lib/libswan/vendorid.c000066400000000000000000001054161475767661000175630ustar00rootroot00000000000000/* 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" #include "lswalloc.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') which 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) */ enum vid_kind { VID_KEEP, VID_MD5HASH, VID_STRING, VID_FSWAN_HASH, VID_SUBSTRING, }; struct vid_struct { const enum known_vendorid id; const enum vid_kind kind; const char *const data; /* filled in at runtime: */ const char *descr; shunk_t vid; }; #define DEC_MD5_VID(ID, DATA) \ VID(ID, VID_MD5HASH, NULL, DATA) #define VID(ID, KIND, DESCR, DATA) \ [ID] = { .id = ID, .kind = KIND, .descr = DESCR, .data = DATA, } #define RAW(ID, KIND, DESCR, RAW_VID) \ [ID] = { \ .id = ID, \ .kind = KIND, \ .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, NULL, "Opportunistic IPsec"), VID(VID_OPENPGP, VID_STRING, "OpenPGP", "OpenPGP10171"), VID(VID_KAME_RACOON, VID_MD5HASH, NULL, "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 */ VID(VID_GSSAPILONG, VID_MD5HASH, NULL, "A GSS-API Authentication Method for IKE"), VID(VID_GSSAPI, VID_MD5HASH, NULL, "GSSAPI"), VID(VID_SSH_SENTINEL, VID_MD5HASH, NULL, "SSH Sentinel"), VID(VID_SSH_SENTINEL_1_1, VID_MD5HASH, NULL, "SSH Sentinel 1.1"), VID(VID_SSH_SENTINEL_1_2, VID_MD5HASH, NULL, "SSH Sentinel 1.2"), VID(VID_SSH_SENTINEL_1_3, VID_MD5HASH, NULL, "SSH Sentinel 1.3"), VID(VID_SSH_SENTINEL_1_4, VID_MD5HASH, NULL, "SSH Sentinel 1.4"), VID(VID_SSH_SENTINEL_1_4_1, VID_MD5HASH, NULL, "SSH Sentinel 1.4.1"), /* These ones come from SSH vendors.txt */ VID(VID_SSH_IPSEC_1_1_0, VID_MD5HASH, NULL, "Ssh Communications Security IPSEC Express version 1.1.0"), VID(VID_SSH_IPSEC_1_1_1, VID_MD5HASH, NULL, "Ssh Communications Security IPSEC Express version 1.1.1"), VID(VID_SSH_IPSEC_1_1_2, VID_MD5HASH, NULL, "Ssh Communications Security IPSEC Express version 1.1.2"), VID(VID_SSH_IPSEC_1_2_1, VID_MD5HASH, NULL, "Ssh Communications Security IPSEC Express version 1.2.1"), VID(VID_SSH_IPSEC_1_2_2, VID_MD5HASH, NULL, "Ssh Communications Security IPSEC Express version 1.2.2"), VID(VID_SSH_IPSEC_2_0_0, VID_MD5HASH, NULL, "SSH Communications Security IPSEC Express version 2.0.0"), VID(VID_SSH_IPSEC_2_1_0, VID_MD5HASH, NULL, "SSH Communications Security IPSEC Express version 2.1.0"), VID(VID_SSH_IPSEC_2_1_1, VID_MD5HASH, NULL, "SSH Communications Security IPSEC Express version 2.1.1"), VID(VID_SSH_IPSEC_2_1_2, VID_MD5HASH, NULL, "SSH Communications Security IPSEC Express version 2.1.2"), VID(VID_SSH_IPSEC_3_0_0, VID_MD5HASH, NULL, "SSH Communications Security IPSEC Express version 3.0.0"), VID(VID_SSH_IPSEC_3_0_1, VID_MD5HASH, NULL, "SSH Communications Security IPSEC Express version 3.0.1"), VID(VID_SSH_IPSEC_4_0_0, VID_MD5HASH, NULL, "SSH Communications Security IPSEC Express version 4.0.0"), VID(VID_SSH_IPSEC_4_0_1, VID_MD5HASH, NULL, "SSH Communications Security IPSEC Express version 4.0.1"), VID(VID_SSH_IPSEC_4_1_0, VID_MD5HASH, NULL, "SSH Communications Security IPSEC Express version 4.1.0"), VID(VID_SSH_IPSEC_4_2_0, VID_MD5HASH, NULL, "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, "Cisco VPN 3000 Series", "\x1f\x07\xf7\x0e\xaa\x65\x14\xd3\xb0\xfa\x96\x54\x2a\x50"), RAW(VID_CISCO_IOS, VID_SUBSTRING, "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, NULL, "CISCOVPN-REV-02"), 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, NULL, "CISCO-DELETE-REASON"), /* 434953434f2d44594e414d49432d524f555445 */ VID(VID_CISCO_DYNAMIC_ROUTE, VID_STRING, NULL, "CISCO-DYNAMIC-ROUTE"), /* 464c455856504e2d535550504f52544544 */ VID(VID_CISCO_FLEXVPN_SUPPORTED, VID_STRING, NULL, "FLEXVPN-SUPPORTED"), /* * Timestep VID seen: * - 54494d455354455020312053475720313532302033313520322e303145303133 * = 'TIMESTEP 1 SGW 1520 315 2.01E013' */ RAW(VID_TIMESTEP, VID_SUBSTRING, "TIMESTEP", "TIMESTEP"), VID(VID_FSWAN_2_00_VID, VID_FSWAN_HASH, "FreeS/WAN 2.00", "Linux FreeS/WAN 2.00 PLUTO_SENDS_VENDORID"), VID(VID_FSWAN_2_00_X509_1_3_1_VID, VID_FSWAN_HASH, "FreeS/WAN 2.00 (X.509-1.3.1)", "Linux FreeS/WAN 2.00 X.509-1.3.1 PLUTO_SENDS_VENDORID"), VID(VID_FSWAN_2_00_X509_1_3_1_LDAP_VID, VID_FSWAN_HASH, "FreeS/WAN 2.00 (X.509-1.3.1 + LDAP)", "Linux FreeS/WAN 2.00 X.509-1.3.1 LDAP PLUTO_SENDS_VENDORID"), VID(VID_OPENSWAN2, VID_FSWAN_HASH, "Openswan 2.2.0", "Openswan 2.2.0"), /* always make sure to include ourself! */ VID(VID_LIBRESWANSELF, VID_STRING, "Libreswan (this version)", libreswan_vendorid), /* NAT-Traversal */ VID(VID_NATT_STENBERG_01, VID_MD5HASH, NULL, "draft-stenberg-ipsec-nat-traversal-01"), VID(VID_NATT_STENBERG_02, VID_MD5HASH, NULL, "draft-stenberg-ipsec-nat-traversal-02"), VID(VID_NATT_HUTTUNEN, VID_MD5HASH, NULL, "ESPThruNAT"), VID(VID_NATT_HUTTUNEN_ESPINUDP, VID_MD5HASH, NULL, "draft-huttunen-ipsec-esp-in-udp-00.txt"), VID(VID_NATT_IETF_00, VID_MD5HASH, NULL, "draft-ietf-ipsec-nat-t-ike-00"), VID(VID_NATT_IETF_01, VID_MD5HASH, NULL, "draft-ietf-ipsec-nat-t-ike-01"), VID(VID_NATT_IETF_02, VID_MD5HASH, NULL, "draft-ietf-ipsec-nat-t-ike-02"), /* hash in draft-ietf-ipsec-nat-t-ike-02 contains '\n'... that as well */ VID(VID_NATT_IETF_02_N, VID_MD5HASH, "draft-ietf-ipsec-nat-t-ike-02_n", "draft-ietf-ipsec-nat-t-ike-02\n"), VID(VID_NATT_IETF_03, VID_MD5HASH, NULL, "draft-ietf-ipsec-nat-t-ike-03"), VID(VID_NATT_IETF_04, VID_MD5HASH, NULL, "draft-ietf-ipsec-nat-t-ike-04"), VID(VID_NATT_IETF_05, VID_MD5HASH, NULL, "draft-ietf-ipsec-nat-t-ike-05"), VID(VID_NATT_IETF_06, VID_MD5HASH, NULL, "draft-ietf-ipsec-nat-t-ike-06"), VID(VID_NATT_IETF_07, VID_MD5HASH, NULL, "draft-ietf-ipsec-nat-t-ike-07"), VID(VID_NATT_IETF_08, VID_MD5HASH, NULL, "draft-ietf-ipsec-nat-t-ike-08"), VID(VID_NATT_DRAFT_IETF_IPSEC_NAT_T_IKE, VID_MD5HASH, NULL, "draft-ietf-ipsec-nat-t-ike"), VID(VID_NATT_RFC, VID_MD5HASH, NULL, "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, "CAN-IKEv2(obsolete)", "IKEv2"), /* VID is ASCII "HeartBeat_Notify" plus a few bytes (version?) */ RAW(VID_MISC_HEARTBEAT_NOTIFY, VID_SUBSTRING, "HeartBeat Notify", "HeartBeat_Notify"), /* FRAGMENTATION; Cisco VPN 3000 and strongSwan send extra values */ RAW(VID_IKE_FRAGMENTATION, VID_SUBSTRING, "FRAGMENTATION", "\x40\x48\xb7\xd5\x6e\xbc\xe8\x85\x25\xe7\xde\x7f\x00\xd6\xc2\xd3"), VID(VID_INITIAL_CONTACT, VID_MD5HASH, NULL, "Vid-Initial-Contact"), /* * strongSwan */ VID(VID_STRONGSWAN, VID_MD5HASH, NULL, "strongSwan"), VID(VID_STRONGSWAN_4_0_0, VID_MD5HASH, NULL, "strongSwan 4.0.0"), VID(VID_STRONGSWAN_4_0_1, VID_MD5HASH, NULL, "strongSwan 4.0.1"), VID(VID_STRONGSWAN_4_0_2, VID_MD5HASH, NULL, "strongSwan 4.0.2"), VID(VID_STRONGSWAN_4_0_3, VID_MD5HASH, NULL, "strongSwan 4.0.3"), VID(VID_STRONGSWAN_4_0_4, VID_MD5HASH, NULL, "strongSwan 4.0.4"), VID(VID_STRONGSWAN_4_0_5, VID_MD5HASH, NULL, "strongSwan 4.0.5"), VID(VID_STRONGSWAN_4_0_6, VID_MD5HASH, NULL, "strongSwan 4.0.6"), VID(VID_STRONGSWAN_4_0_7, VID_MD5HASH, NULL, "strongSwan 4.0.7"), VID(VID_STRONGSWAN_4_1_0, VID_MD5HASH, NULL, "strongSwan 4.1.0"), VID(VID_STRONGSWAN_4_1_1, VID_MD5HASH, NULL, "strongSwan 4.1.1"), VID(VID_STRONGSWAN_4_1_2, VID_MD5HASH, NULL, "strongSwan 4.1.2"), VID(VID_STRONGSWAN_4_1_3, VID_MD5HASH, NULL, "strongSwan 4.1.3"), VID(VID_STRONGSWAN_4_1_4, VID_MD5HASH, NULL, "strongSwan 4.1.4"), VID(VID_STRONGSWAN_4_1_5, VID_MD5HASH, NULL, "strongSwan 4.1.5"), VID(VID_STRONGSWAN_4_1_6, VID_MD5HASH, NULL, "strongSwan 4.1.6"), VID(VID_STRONGSWAN_4_1_7, VID_MD5HASH, NULL, "strongSwan 4.1.7"), VID(VID_STRONGSWAN_4_1_8, VID_MD5HASH, NULL, "strongSwan 4.1.8"), VID(VID_STRONGSWAN_4_1_9, VID_MD5HASH, NULL, "strongSwan 4.1.9"), VID(VID_STRONGSWAN_4_1_10, VID_MD5HASH, NULL, "strongSwan 4.1.10"), VID(VID_STRONGSWAN_4_1_11, VID_MD5HASH, NULL, "strongSwan 4.1.11"), VID(VID_STRONGSWAN_4_2_0, VID_MD5HASH, NULL, "strongSwan 4.2.0"), VID(VID_STRONGSWAN_4_2_1, VID_MD5HASH, NULL, "strongSwan 4.2.1"), VID(VID_STRONGSWAN_4_2_2, VID_MD5HASH, NULL, "strongSwan 4.2.2"), VID(VID_STRONGSWAN_4_2_3, VID_MD5HASH, NULL, "strongSwan 4.2.3"), VID(VID_STRONGSWAN_2_8_8, VID_MD5HASH, NULL, "strongSwan 2.8.8"), VID(VID_STRONGSWAN_2_8_7, VID_MD5HASH, NULL, "strongSwan 2.8.7"), VID(VID_STRONGSWAN_2_8_6, VID_MD5HASH, NULL, "strongSwan 2.8.6"), VID(VID_STRONGSWAN_2_8_5, VID_MD5HASH, NULL, "strongSwan 2.8.5"), VID(VID_STRONGSWAN_2_8_4, VID_MD5HASH, NULL, "strongSwan 2.8.4"), VID(VID_STRONGSWAN_2_8_3, VID_MD5HASH, NULL, "strongSwan 2.8.3"), VID(VID_STRONGSWAN_2_8_2, VID_MD5HASH, NULL, "strongSwan 2.8.2"), VID(VID_STRONGSWAN_2_8_1, VID_MD5HASH, NULL, "strongSwan 2.8.1"), VID(VID_STRONGSWAN_2_8_0, VID_MD5HASH, NULL, "strongSwan 2.8.0"), VID(VID_STRONGSWAN_2_7_3, VID_MD5HASH, NULL, "strongSwan 2.7.3"), VID(VID_STRONGSWAN_2_7_2, VID_MD5HASH, NULL, "strongSwan 2.7.2"), VID(VID_STRONGSWAN_2_7_1, VID_MD5HASH, NULL, "strongSwan 2.7.1"), VID(VID_STRONGSWAN_2_7_0, VID_MD5HASH, NULL, "strongSwan 2.7.0"), VID(VID_STRONGSWAN_2_6_4, VID_MD5HASH, NULL, "strongSwan 2.6.4"), VID(VID_STRONGSWAN_2_6_3, VID_MD5HASH, NULL, "strongSwan 2.6.3"), VID(VID_STRONGSWAN_2_6_2, VID_MD5HASH, NULL, "strongSwan 2.6.2"), VID(VID_STRONGSWAN_2_6_1, VID_MD5HASH, NULL, "strongSwan 2.6.1"), VID(VID_STRONGSWAN_2_6_0, VID_MD5HASH, NULL, "strongSwan 2.6.0"), VID(VID_STRONGSWAN_2_5_7, VID_MD5HASH, NULL, "strongSwan 2.5.7"), VID(VID_STRONGSWAN_2_5_6, VID_MD5HASH, NULL, "strongSwan 2.5.6"), VID(VID_STRONGSWAN_2_5_5, VID_MD5HASH, NULL, "strongSwan 2.5.5"), VID(VID_STRONGSWAN_2_5_4, VID_MD5HASH, NULL, "strongSwan 2.5.4"), VID(VID_STRONGSWAN_2_5_3, VID_MD5HASH, NULL, "strongSwan 2.5.3"), VID(VID_STRONGSWAN_2_5_2, VID_MD5HASH, NULL, "strongSwan 2.5.2"), VID(VID_STRONGSWAN_2_5_1, VID_MD5HASH, NULL, "strongSwan 2.5.1"), VID(VID_STRONGSWAN_2_5_0, VID_MD5HASH, NULL, "strongSwan 2.5.0"), VID(VID_STRONGSWAN_2_4_4, VID_MD5HASH, NULL, "strongSwan 2.4.4"), VID(VID_STRONGSWAN_2_4_3, VID_MD5HASH, NULL, "strongSwan 2.4.3"), VID(VID_STRONGSWAN_2_4_2, VID_MD5HASH, NULL, "strongSwan 2.4.2"), VID(VID_STRONGSWAN_2_4_1, VID_MD5HASH, NULL, "strongSwan 2.4.1"), VID(VID_STRONGSWAN_2_4_0, VID_MD5HASH, NULL, "strongSwan 2.4.0"), VID(VID_STRONGSWAN_2_3_2, VID_MD5HASH, NULL, "strongSwan 2.3.2"), VID(VID_STRONGSWAN_2_3_1, VID_MD5HASH, NULL, "strongSwan 2.3.1"), VID(VID_STRONGSWAN_2_3_0, VID_MD5HASH, NULL, "strongSwan 2.3.0"), VID(VID_STRONGSWAN_2_2_2, VID_MD5HASH, NULL, "strongSwan 2.2.2"), VID(VID_STRONGSWAN_2_2_1, VID_MD5HASH, NULL, "strongSwan 2.2.1"), VID(VID_STRONGSWAN_2_2_0, VID_MD5HASH, NULL, "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, "Libreswan (3.6+)", "\x4f\x45\x2d\x4c\x69\x62\x72\x65\x73\x77\x61\x6e\x2d"), RAW(VID_LIBRESWAN_OLD, VID_SUBSTRING, "Libreswan 3.0 - 3.5", "\x4f\x45\x4e"), RAW(VID_XOPENSWAN, VID_SUBSTRING, "Openswan(xeleranized)", "\x4f\x53\x57"), RAW(VID_OPENSWANORG, VID_SUBSTRING, "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_SUBSTRING, "ELVIS-PLUS Zastava", "\x08\xdb\x45\xe6\xcb\x01\xf8\x0b\xb5\x76\xe9\xa7\x8c\x0f\x54\xe1\x30\x0b\x88\x81"), /* * Fortinet */ VID(VID_FORTINET_ENDPOINT_CONTROL, VID_MD5HASH, NULL, "Fortinet Endpoint Control"), VID(VID_FORTINET_CONNECT_LICENSE, VID_MD5HASH, NULL, "forticlient connect license"), /* * OpenIKED */ RAW(VID_OPENIKED, VID_SUBSTRING, "OpenIKED", "OpenIKED"), /* 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->kind == 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 LDBG_vid_struct(const struct logger *logger, const struct vid_struct *vid) { LLOG_JAMBUF(DEBUG_STREAM, logger, buf) { jam(buf, " %3d ", vid->id); /* match " %3s " below */ jam_string(buf, vid->descr); jam_string(buf, " "); switch (vid->kind) { case VID_KEEP: jam_string(buf, " keep"); break; case VID_FSWAN_HASH: jam_string(buf, " fswan-hash"); break; case VID_MD5HASH: jam_string(buf, " md5"); break; case VID_SUBSTRING: jam_string(buf, " substring"); break; case VID_STRING: jam_string(buf, " string"); break; } } 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) { ldbg(logger, "building Vendor ID table"); FOR_EACH_ELEMENT_FROM_1(vid, vid_tab) { bool good = true; switch (vid->kind) { case VID_STRING: /* built using VID() */ 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); break; case VID_SUBSTRING: /* built using RAW */ good &= pexpect(vid->vid.ptr != NULL); good &= pexpect(vid->vid.len > 0); good &= pexpect(vid->descr != NULL); break; case VID_MD5HASH: /* built using VID(), .data 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); break; case 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 break; } case VID_KEEP: /* RAW() */ good &= pexpect(vid->vid.len > 0); good &= pexpect(vid->vid.ptr != NULL); good &= pexpect(vid->descr != NULL); good &= pexpect(vid->data == NULL); break; } 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 || LDBGP(DBG_TMI, logger)) { LDBG_vid_struct(logger, vid); } } /* * Step 1: Sort the VID_TAB[] creating VID_SORTED. * * Because VIDs overlap, the result is a table containing * multiple entries with the same prefix which means it isn't * suitable for a binary search. * * For instance, say the table includes the entries: * * "OA.*" * "OE.*" * "OE Libreswan.*" * "OE Libreswan 123" * "OF.*" * * then a binary search for "OE LIBRESWAN" would match either * "OE.*" or "OE Libreswan", or fail. * * Note that vid_sorted[] is zero indexed. */ ldbg(logger, "building sorted Vendor ID table"); FOR_EACH_ELEMENT_FROM_1(vid, vid_tab) { passert(vid->id > 0); /* make it zero indexed */ unsigned id0 = vid->id - 1; passert(id0 < elemsof(vid_sorted)); vid_sorted[id0].entry = vid; } qsort(vid_sorted, elemsof(vid_sorted), sizeof(vid_sorted[0]), vid_sorted_cmp); /* * Step 2: Prune the VID_SORTED[] table of all but the * shortest overlapping VIDs creating VID_LOOKUP[]. * * Each entry points into VID_SORTED[] at the first of the * overlapping VIDs that match the VID_LOOKUP[] entry. * * For instance, using the above: * * 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 and finding "OE Libreswan.*" */ ldbg(logger, "building lookup Vendor ID table"); vid_lookup[elemsof_vid_lookup++] = &vid_sorted[0]; FOR_EACH_ELEMENT_FROM_1(vidp, vid_sorted) { /* do this and prev entry share their prefix? */ 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 (LDBGP(DBG_BASE, logger)) { LDBG_log(logger, "Vendor IDs '%s' and '%s' have a common prefix", prev->entry->descr, vidp->entry->descr); LDBG_vid_struct(logger, prev->entry); LDBG_vid_struct(logger, vidp->entry); } } } void llog_vendorid(struct logger *logger, enum known_vendorid id, shunk_t vid, bool vid_useful) { const unsigned MAX_LOG_VID_LEN = 32; lset_t stream = (id == VID_none ? RC_LOG|ALL_STREAMS : LDBGP(DBG_BASE, logger) ? DEBUG_STREAM : 0); if (stream == 0) { return; } LLOG_JAMBUF(stream, logger, buf) { /* truncate the VID */ shunk_t tvid = hunk_slice(vid, 0, PMIN(vid.len, MAX_LOG_VID_LEN)); const char *trunc = (vid.len > MAX_LOG_VID_LEN ? " ..." : ""); jam_string(buf, vid_useful ? "received" : "ignoring"); /* description */ jam_string(buf, " "); if (id == VID_none) { jam_string(buf, "unknown"); } else { jam_string(buf, vid_tab[id].descr); } jam_string(buf, " Vendor ID payload"); /* dump as ascii */ jam_string(buf, " \""); jam_sanitized_hunk(buf, tvid); jam_string(buf, trunc); jam_string(buf, "\""); /* dump as hex */ jam_string(buf, " ["); jam_dump_hunk(buf, tvid); jam_string(buf, trunc); jam_string(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) { const struct logger *logger = &global_logger; /* * Find known VendorID in vid_tab */ if (vid.len > 0) { /* 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 (LDBGP(DBG_TMI, logger)) { LDBG_log(logger, "starting with the Vendor ID:"); LDBG_vid_struct(logger, best->entry); } /* * Search through the Vendor IDs sharing a common * prefix looking for the best match. Since they are * sorted short-to-long and the last match is used it * will have the longest prefix. */ for (const struct vid_entry *vidp = best + 1; vidp < &vid_sorted[elemsof(vid_sorted)]; vidp++) { if (LDBGP(DBG_TMI, logger)) { LDBG_log(logger, "comparing with Vendor ID:"); LDBG_vid_struct(logger, vidp->entry); } int c = vid_entry_cmp(&vid, vidp); if (c < 0) { if (LDBGP(DBG_TMI, logger)) { LDBG_log(logger, " reached the end of the overlapping Vendor IDs"); } break; } if (c == 0) { if (LDBGP(DBG_TMI, logger)) { LDBG_log(logger, " better match"); } best = vidp; continue; } if (LDBGP(DBG_TMI, logger)) { LDBG_log(logger, " not the best"); } } return best->entry->id; } 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->tmp, sizeof(eb->tmp), "VID_%u", id); eb->buf = eb->tmp; 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; } void llog_vendorids(lset_t rc_flags, struct logger *logger) { FOR_EACH_ELEMENT(v, vid_sorted) { enum known_vendorid id = v->entry->id; shunk_t vid = shunk_from_vendorid(id); enum_buf idb; llog(rc_flags, logger, "[%s]%s", str_vendorid(id, &idb), (v->entry->kind == VID_SUBSTRING ? " (prefix match)" : "")); llog_dump_hunk(rc_flags, logger, vid); enum known_vendorid r = vendorid_by_shunk(vid); passert(r != VID_none); if (r != id) { enum_buf idb, rb; llog_passert(logger, HERE, "lookup for %d [%s] returned %d [%s]", id, str_vendorid(id, &idb), r, str_vendorid(r, &rb)); } } } libreswan-5.2/lib/libswan/version.in.c000066400000000000000000000024131475767661000200340ustar00rootroot00000000000000/* * 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-5.2/lib/libswan/x509dn.c000066400000000000000000000750231475767661000170000ustar00rootroot00000000000000/* 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" #include "lswalloc.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, size_t *ss) { asn1_t rdn; asn1_t attribute; bool more; size_t s = 0; 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) { s += jam_string(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? */ s += 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"; } s += jam(buf, ".%ju", n); } } else { s += jam_string(buf, oid_names[oid_code].name); } s += jam_string(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 */ s += jam_string(buf, "#"); for (unsigned i = 0; i < value_ber.len; i++) { uint8_t byte = ((const uint8_t*)value_ber.ptr)[i]; s += 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 == '#')) { s += jam_bytes(buf, "\\", 1); s += 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 */ s += jam_bytes(buf, p, run); if (needs_prefix) { /* */ s += jam_bytes(buf, "\\", 1); s += jam_bytes(buf, &c, 1); } else { /* */ s += jam_bytes(buf, "\\", 1); s += jam(buf, "%02X", c); } /* advance past this escaped character */ p += run + 1; run = 0; } } /* emit final run */ s += jam_bytes(buf, p, run); /* * Escape any trailing ' ' characters; using \ * is ok; remember END had these stripped. */ for (unsigned i = 0; i < trailing; i++) { s += jam_bytes(buf, "\\", 1); s += jam_bytes(buf, &end[i], 1); } } } *ss = s; return NULL; } /* * Converts a binary DER-encoded ASN.1 distinguished name * into LDAP-style human-readable ASCII format */ size_t jam_raw_dn(struct jambuf *buf, asn1_t dn, jam_bytes_fn *jam_bytes, bool nss_compatible) { size_t s = 0; /* 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, &s); 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); s = 0; s += jam_string(buf, "0x"); s += jam_HEX_bytes(buf, dn.ptr, dn.len); } return s; } err_t parse_dn(asn1_t dn) { dn_buf dnb; struct jambuf buf = ARRAY_AS_JAMBUF(dnb.buf); size_t s;/*ignored*/ return format_dn(&buf, dn, jam_raw_bytes, true/*nss_compatible*/, &s); } size_t jam_dn_or_null(struct jambuf *buf, asn1_t dn, const char *null_dn, jam_bytes_fn *jam_bytes) { if (dn.ptr == NULL) { return jam_string(buf, null_dn); } else { return 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; } size_t jam_dn(struct jambuf *buf, asn1_t dn, jam_bytes_fn *jam_bytes) { return 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(asn1_t a, asn1_t b, int *const wildcards, struct verbose verbose) { 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. */ vdbg("matching unordered DNs A: '%s' B: '%s'", abuf, bbuf); CERTName *const a_name = CERT_AsciiToName(abuf); CERTName *const b_name = CERT_AsciiToName(bbuf); if (a_name == NULL || b_name == NULL) { /* NULL is ignored; see NSS commit 206 */ CERT_DestroyName(a_name); CERT_DestroyName(b_name); return false; } int rdn_num = 0; int matched = 0; CERTRDN *const *rdns_b; for (rdns_b = b_name->rdns; *rdns_b != NULL; rdns_b++) { CERTRDN *const rdn_b = *rdns_b; rdn_num++; CERTRDN *const *rdns_a; for (rdns_a = a_name->rdns; *rdns_a != NULL; rdns_a++) { CERTRDN *const rdn_a = *rdns_a; bool has_wild = false; if (match_rdn(rdn_a, rdn_b, wildcards != NULL ? &has_wild : NULL)) { matched++; if (wildcards != NULL && has_wild) (*wildcards)++; break; } } } CERT_DestroyName(a_name); CERT_DestroyName(b_name); vdbg("%s() matched: %d, rdn_num: %d, wc %d", __func__, matched, rdn_num, wildcards ? *wildcards : 0); return matched > 0 && rdn_num > 0 && matched == rdn_num; } bool match_dn_any_order_wild(asn1_t a, asn1_t b, int *wildcards, struct verbose verbose) { bool ret = match_dn(a, b, wildcards); if (!ret) { vdbg("%s() not an exact match, now checking any RDN order with %d wildcards", __func__, *wildcards); /* recount wildcards */ *wildcards = 0; ret = match_dn_unordered(a, b, wildcards, verbose); } 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) free_chunk_content(&gn->name); gn = gn->next; pfree(gn_top); } } libreswan-5.2/lib/libswan/xfrm_policy_names.c000066400000000000000000000036011475767661000214600ustar00rootroot00000000000000 /* 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 * arrangement. */ #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-5.2/lib/libwhack/000077500000000000000000000000001475767661000157235ustar00rootroot00000000000000libreswan-5.2/lib/libwhack/Makefile000066400000000000000000000024071475767661000173660ustar00rootroot00000000000000# 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. ifndef top_srcdir include ../../mk/dirs.mk endif include $(top_srcdir)/mk/config.mk LIB = libwhack.a OBJS += whacklib.o OBJS += aliascomp.o OBJS += pickle.o OBJS += send.o OBJS += $(abs_builddir)/whack_magic.o # build whack_magic.c using whack_magic.in.c $(abs_builddir)/whack_magic.c: $(srcdir)/whack_magic.in.c rm -f $@.tmp sed -e "s/@@WHACK_MAGIC@@/$$(echo $(IPSECVERSION) | cksum | { read s e ; echo $$s; })/" \ $(srcdir)/whack_magic.in.c \ > $@.tmp mv $@.tmp $@ include ${top_srcdir}/mk/library.mk libreswan-5.2/lib/libwhack/aliascomp.c000066400000000000000000000027161475767661000200450ustar00rootroot00000000000000/* 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-5.2/lib/libwhack/pickle.c000066400000000000000000000341031475767661000173370ustar00rootroot00000000000000/* 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_bytes(struct whackpacker *wp, const void *bytes, size_t nr_bytes, const char *what, struct logger *logger) { size_t space = wp->str_roof - wp->str_next; if (space < nr_bytes) { llog(RC_LOG, logger, "buffer overflow for '%s', space for %zu bytes but need %zu", what, space, nr_bytes); return false; /* would overflow buffer */ } memcpy(wp->str_next, bytes, nr_bytes); wp->str_next += nr_bytes; return true; } static bool pack_raw(struct whackpacker *wp, void **bytes, size_t nr_bytes, const char *what, struct logger *logger) { if (!pack_bytes(wp, (*bytes), nr_bytes, what, logger)) { return false; } (*bytes) = NULL; return true; } static bool unpack_raw(struct whackpacker *wp, void **bytes, size_t nr_bytes, const char *what, struct logger *logger) { size_t space = wp->str_roof - wp->str_next; if (space < nr_bytes) { /* overflow */ llog(RC_LOG, logger, "buffer overflow for '%s'; have %zu bytes but expecting %zu", what, space, nr_bytes); return false; } (*bytes) = wp->str_next; wp->str_next += nr_bytes; 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, logger)) { \ 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, logger)) { \ return false; \ } \ return true; \ } static bool pack_chunk(struct whackpacker *wp, chunk_t *chunk, const char *what, struct logger *logger) { PACK_HUNK(wp, chunk, what); } static bool unpack_chunk(struct whackpacker *wp, chunk_t *chunk, const char *what, struct logger *logger) { UNPACK_HUNK(wp, chunk, what); } static bool pack_shunk(struct whackpacker *wp, shunk_t *shunk, const char *what, struct logger *logger) { PACK_HUNK(wp, shunk, what); } static bool unpack_shunk(struct whackpacker *wp, shunk_t *shunk, const char *what, struct logger *logger) { UNPACK_HUNK(wp, shunk, what); } /* * Pack and unpack possibly NULL, NUL-terminated strings. * * Notes: * * - On the wire, the pointer contains the number of bytes including * the trailing NUL. So zero is a NULL pointer, and one is an empty * string. * * - to prevent the string pointer going across the wire, it is set to * the number of bytes * * - the unpacked pointer stored in *P points into the whack message * do don't free it */ static bool pack_string(struct whackpacker *wp, char **p, const char *what, struct logger *logger) { if ((*p) == NULL) { /* NULL pointer encoded as zero bytes */ (*p) = NULL; return true; } size_t nr_bytes = strlen((*p)) + 1; if (!pack_bytes(wp, (*p), nr_bytes, what, logger)) { return false; } (*p) = (void*)nr_bytes; return true; } static bool unpack_string(struct whackpacker *wp, char **p, const char *what, struct logger *logger) { if ((*p) == NULL) { /* unpack NULL as NULL */ return true; } /* p carries the string length */ size_t nr_bytes = (ptrdiff_t)(*p); void *s = NULL; if (!unpack_raw(wp, &s, nr_bytes, what, logger)) { return false; } *p = s; if ((*p)[nr_bytes-1] != '\0') { llog(RC_LOG, logger, "%s lost its terminating NUL", what); return false; } return true; } /* * IP pointers. */ static bool pack_ip_info(struct whackpacker *wp UNUSED, const struct ip_info **info, const char *what UNUSED, struct logger *logger UNUSED) { /* spell out conversions */ enum ip_version v = (*info == NULL ? 0 : (*info)->ip_version); *info = (const void*)(uintptr_t)(unsigned)v; return true; } static bool unpack_ip_info(struct whackpacker *wp UNUSED, const struct ip_info **info, const char *what UNUSED, struct logger *logger UNUSED) { /* spell out conversions */ *info = ip_version_info((unsigned)(uintptr_t)(const void*)*info); return true; } static bool pack_ip_protocol(struct whackpacker *wp UNUSED, const struct ip_protocol **protocol, const char *what UNUSED, struct logger *logger 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, struct logger *logger UNUSED) { /* spell out conversions */ *protocol = protocol_from_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, struct logger *logger) { if (*string != NULL) { ldbgf(DBG_TMI, logger, "%s: '%s' was: %s (%s)", __func__, what, *string, constant); passert(streq(*string, constant)); *string = NULL; } else { /* * For instance, when whack sends control messages * such as "status" the whack_end .leftright field is * still NULL. * * The unpack will set the field, oops. */ ldbgf(DBG_TMI, logger, "%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, struct logger *logger) { pexpect(*string == NULL); *string = constant; ldbgf(DBG_TMI, logger, "%s: '%s' is %s", __func__, what, *string); return true; } /* * in and out/ */ struct pickler { bool (*string)(struct whackpacker *wp, char **p, const char *what, struct logger *logger); bool (*shunk)(struct whackpacker *wp, shunk_t *s, const char *what, struct logger *logger); bool (*chunk)(struct whackpacker *wp, chunk_t *s, const char *what, struct logger *logger); bool (*raw)(struct whackpacker *wp, void **bytes, size_t nr_bytes, const char *what, struct logger *logger); bool (*ip_info)(struct whackpacker *wp, const struct ip_info **info, const char *what, struct logger *logger); bool (*ip_protocol)(struct whackpacker *wp, const struct ip_protocol **protocol, const char *what, struct logger *logger); bool (*constant_string)(struct whackpacker *wp, const char **p, const char *leftright, const char *what, struct logger *logger); }; 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, logger) #define PICKLE_CHUNK(FIELD) pickle->chunk(wp, FIELD, #FIELD, logger) #define PICKLE_SHUNK(FIELD) pickle->shunk(wp, FIELD, #FIELD, logger) #define PICKLE_THINGS(THINGS, NR) pickle->raw(wp, (void**)(THINGS), NR*sizeof((THINGS)[0][0]), #THINGS, logger) #define PICKLE_CONSTANT_STRING(FIELD, VALUE) pickle->constant_string(wp, FIELD, VALUE, #FIELD, logger) #define PICKLE_IP_INFO(FIELD) pickle->ip_info(wp, FIELD, #FIELD, logger) #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, struct logger *logger) { 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_STRING(&end->interface_ip) && PICKLE_STRING(&end->addresspool) && PICKLE_STRING(&end->subnet) && PICKLE_STRING(&end->subnets) && PICKLE_STRING(&end->sourceip) && PICKLE_STRING(&end->groundhog) && true); } static bool pickle_whack_message(struct whackpacker *wp, const struct pickler *pickle, struct logger *logger) { return (PICKLE_STRING(&wp->msg->name) && /* first */ pickle_whack_end(wp, "left", &wp->msg->end[LEFT_END], pickle, logger) && pickle_whack_end(wp, "right",&wp->msg->end[RIGHT_END], pickle, logger) && PICKLE_STRING(&wp->msg->keyid) && PICKLE_STRING(&wp->msg->ike) && PICKLE_STRING(&wp->msg->esp) && PICKLE_STRING(&wp->msg->connalias) && PICKLE_STRING(&wp->msg->dnshostname) && PICKLE_STRING(&wp->msg->modecfgdns) && PICKLE_STRING(&wp->msg->modecfgdomains) && PICKLE_STRING(&wp->msg->modecfgbanner) && PICKLE_STRING(&wp->msg->mark) && PICKLE_STRING(&wp->msg->mark_in) && PICKLE_STRING(&wp->msg->mark_out) && PICKLE_STRING(&wp->msg->vti_interface) && PICKLE_STRING(&wp->msg->ipsec_interface) && PICKLE_STRING(&wp->msg->remote_host) && PICKLE_STRING(&wp->msg->ppk_ids) && PICKLE_STRING(&wp->msg->global_redirect_to) && PICKLE_STRING(&wp->msg->redirect_to) && PICKLE_STRING(&wp->msg->accept_redirect_to) && PICKLE_CHUNK(&wp->msg->keyval) && PICKLE_THINGS(&wp->msg->impairments.list, wp->msg->impairments.len) && PICKLE_STRING(&wp->msg->sec_label) && PICKLE_IP_INFO(&wp->msg->host_afi) && PICKLE_IP_INFO(&wp->msg->child_afi) && PICKLE_STRING(&wp->msg->dpdtimeout) && PICKLE_STRING(&wp->msg->dpddelay) && 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, struct logger *logger) { if (wp->msg->basic.magic != 0) { ldbg(logger, "whack magic forced to %u", wp->msg->basic.magic); } else if (wp->msg->basic.whack_status || wp->msg->basic.whack_shutdown) { wp->msg->basic.magic = WHACK_BASIC_MAGIC; ldbg(logger, "whack magic is %u (WHACK_BASIC_MAGIC)", wp->msg->basic.magic); } else { wp->msg->basic.magic = whack_magic(); ldbg(logger, "whack magic is %u (WHACK_MAGIC)", wp->msg->basic.magic); } /* 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, logger)) { 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) { /* sanity check message */ if (wp->msg->basic.magic == WHACK_BASIC_MAGIC) { /* must at least contain .whack_shutdown */ size_t min_bytes = (offsetof(struct whack_message, basic.whack_shutdown) + sizeof(wp->msg->basic.whack_shutdown)); if (wp->n < min_bytes) { llog(RC_BADWHACKMESSAGE, logger, "ignoring runt message from whack: got %zu bytes", wp->n); return false; } /* * Note: since old libreswans (4.x, 5.0) never set * .magic to WHACK_BASIC_MAGIC, a 5.1+ libreswan will * never see a non-zero .whack_shutdown_legacy[] * except when set by a 5.1+ whack. Hence, there's no * point in checking its contents. */ #if 0 FOR_EACH_ELEMENT(b, wp->msg->basic.whack_shutdown_legacy) { wp->msg->basic.whack_shutdown |= (*b); } #endif /* wipe everything beyond basic values */ memset((unsigned char*)wp->msg + sizeof(struct whack_basic), 0, sizeof(struct whack_message) - sizeof(struct whack_basic)); return true; } if (wp->msg->basic.magic != whack_magic()) { llog(RC_BADWHACKMESSAGE, logger, "ignoring message from whack with bad magic %u; should be %u; Mismatched versions of userland tools.", wp->msg->basic.magic, whack_magic()); return false; } /* * Determine the bounds of the trailing string array. Message * must at least extend to strings array. */ wp->str_next = wp->msg->string; wp->str_roof = (unsigned char *)wp->msg + wp->n; if (wp->str_next > wp->str_roof) { llog(RC_BADWHACKMESSAGE, logger, "ignoring truncated message from whack: got %zu bytes; expected %zu", wp->n, sizeof(wp->msg)); return false; } if (!pickle_whack_message(wp, &pickle_unpacker, logger)) { llog(RC_BADWHACKMESSAGE, logger, "message from whack contains bad string or key"); return false; } return true; } libreswan-5.2/lib/libwhack/send.c000066400000000000000000000205161475767661000170240ustar00rootroot00000000000000/* * 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 /* for write() */ #include #include /* for exit() */ #include /* struct sockaddr_un;! */ #include "whack.h" #include "lsw_socket.h" #include "lswlog.h" static 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! */ static size_t whack_get_secret(char *buf, size_t bufsize) { fflush(stdout); passert(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; } static void whack_send_reply(int sock, const char *buf, ssize_t len, struct logger *logger) { /* send the secret to pluto */ if (write(sock, buf, len) != len) { /* not fatal() which should be internal to pluto() */ int e = errno; llog_error(logger, e, "write() failed"); exit(RC_WHACK_PROBLEM); } } static int whack_read_reply(int sock, char xauthusername[MAX_XAUTH_USERNAME_LEN], char xauthpass[XAUTH_MAX_PASS_LENGTH], int usernamelen, int xauthpasslen, struct logger *logger) { char buf[4097]; /* arbitrary limit on log line length */ char *be = buf; int exit_status = 0; for (;; ) { char *ls = buf; ssize_t rl = read(sock, be, (buf + sizeof(buf) - 1) - be); if (rl < 0) { int e = errno; llog_error(logger, e, "read() failed"); exit(RC_WHACK_PROBLEM); } if (rl == 0) { if (be != buf) { llog_error(logger, 0, "last line from pluto too long or unterminated"); } 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 */ /* * figure out prefix number and how it should * affect our exit status and printing */ char *lpe = NULL; /* line-prefix-end */ unsigned long s = strtoul(ls, &lpe, 10); if (lpe == ls || *lpe != ' ') { /* includes embedded NL, see above */ llog_error(logger, 0, "log line missing NNN prefix: %*s", (int)(le - ls), ls); exit(RC_WHACK_PROBLEM); } ls = lpe + 1; /* skip NNN_ */ if (write(STDOUT_FILENO, ls, le - ls) == -1) { int e = errno; llog_errno(RC_LOG, logger, e, "write() failed, and ignored"); } /* * figure out prefix number and how it should affect * our exit status */ switch (s) { case RC_LOG: /* * Ignore; these logs are * informational only. */ break; case RC_ENTERSECRET: if (xauthpass == NULL) { llog_error(logger, 0, "unexpected request for xauth password"); exit(RC_WHACK_PROBLEM); } 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; llog_error(logger, 0, "xauth password cannot be >= %d chars", XAUTH_MAX_PASS_LENGTH); } whack_send_reply(sock, xauthpass, xauthpasslen, logger); break; case RC_USERPROMPT: if (xauthusername == NULL) { llog_error(logger, 0, "unexpected request for xauth username"); exit(RC_WHACK_PROBLEM); } 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; llog_error(logger, 0, "username cannot be >= %d chars", MAX_XAUTH_USERNAME_LEN); } whack_send_reply(sock, xauthusername, usernamelen, logger); break; default: /* * Only RC_ codes between * RC_EXIT_FLOOR (RC_DUPNAME) and * RC_EXIT_ROOF are errors. * * The exit status is sticky so that * incidental logs don't clear or * change it. */ if (exit_status == 0 && s >= RC_EXIT_FLOOR && s < RC_EXIT_ROOF) { exit_status = s; } break; } ls = le; } } return exit_status; } int whack_send_msg(struct whack_message *msg, const char *ctlsocket, char xauthusername[MAX_XAUTH_USERNAME_LEN], char xauthpass[XAUTH_MAX_PASS_LENGTH], int usernamelen, int xauthpasslen, struct logger *logger) { struct sockaddr_un ctl_addr = { .sun_family = AF_UNIX, .sun_path = DEFAULT_CTL_SOCKET, #ifdef USE_SOCKADDR_LEN .sun_len = sizeof(struct sockaddr_un), #endif }; /* copy socket location */ fill_and_terminate(ctl_addr.sun_path, ctlsocket, sizeof(ctl_addr.sun_path)); /* Pack strings */ struct whackpacker wp = { .msg = msg, .str_next = (unsigned char *)msg->string, .str_roof = (unsigned char *)&msg->string[sizeof(msg->string)], }; err_t ugh = pack_whack_msg(&wp, logger); if (ugh != NULL) { llog_error(logger, 0, "send_wack_msg(): can't pack strings: %s", ugh); return -1; } ssize_t len = wp.str_next - (unsigned char *)msg; /* Connect to pluto ctl */ if (access(ctl_addr.sun_path, R_OK | W_OK) < 0) { int e = errno; switch (e) { case EACCES: llog_error(logger, e, "no right to communicate with pluto (access(\"%s\"))", ctl_addr.sun_path); break; case ENOENT: llog_error(logger, e, "Pluto is not running (no \"%s\")", ctl_addr.sun_path); break; default: llog_error(logger, e, "access(\"%s\") failed", ctl_addr.sun_path); break; } exit(RC_WHACK_PROBLEM); } int sock = cloexec_socket(AF_UNIX, SOCK_STREAM, 0); if (sock < 0) { llog_error(logger, errno, "socket() failed"); exit(RC_WHACK_PROBLEM); } if (connect(sock, (struct sockaddr *)&ctl_addr, offsetof(struct sockaddr_un, sun_path) + strlen(ctl_addr.sun_path)) < 0) { llog_error(logger, errno, "connect(pluto_ctl) failed"); close(sock); exit(RC_WHACK_PROBLEM); } /* Send message */ if (write(sock, msg, len) != len) { llog_error(logger, errno, "write(pluto_ctl) failed"); close(sock); exit(RC_WHACK_PROBLEM); } /* read reply (possibly send further messages) */ int ret = whack_read_reply(sock, xauthusername, xauthpass, usernamelen, xauthpasslen, logger); close(sock); return ret; } libreswan-5.2/lib/libwhack/whack_magic.in.c000066400000000000000000000015041475767661000207310ustar00rootroot00000000000000/* whack magic for libreswan * * Copyright (C) 2024 Andrew Cagney * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include "lswversion.h" #include "whack.h" static unsigned magic = @@WHACK_MAGIC@@; unsigned whack_magic(void) { if (magic == WHACK_BASIC_MAGIC) { return ~magic; /* what are the odds? */ } return magic; } libreswan-5.2/lib/libwhack/whacklib.c000066400000000000000000000025351475767661000176600ustar00rootroot00000000000000/* 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" 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; } libreswan-5.2/macports/000077500000000000000000000000001475767661000152215ustar00rootroot00000000000000libreswan-5.2/macports/nspr/000077500000000000000000000000001475767661000162035ustar00rootroot00000000000000libreswan-5.2/macports/nspr/Portfile000066400000000000000000000035721475767661000177210ustar00rootroot00000000000000# $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-5.2/macports/nspr/files/000077500000000000000000000000001475767661000173055ustar00rootroot00000000000000libreswan-5.2/macports/nspr/files/nspr.pc000066400000000000000000000003461475767661000206160ustar00rootroot00000000000000prefix=@@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-5.2/macports/nss/000077500000000000000000000000001475767661000160245ustar00rootroot00000000000000libreswan-5.2/macports/nss/Portfile000066400000000000000000000077051475767661000175440ustar00rootroot00000000000000# $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-5.2/macports/nss/files/000077500000000000000000000000001475767661000171265ustar00rootroot00000000000000libreswan-5.2/macports/nss/files/nss-config.in000066400000000000000000000045141475767661000215300ustar00rootroot00000000000000#!/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-5.2/macports/nss/files/nss.pc.in000066400000000000000000000004011475767661000206550ustar00rootroot00000000000000prefix=@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-5.2/macports/nss/files/patch-Darwin.mk.diff000066400000000000000000000026351475767661000227150ustar00rootroot00000000000000--- 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-5.2/macports/nss/files/patch-UNIX.mk.diff000066400000000000000000000007471475767661000222560ustar00rootroot00000000000000--- 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-5.2/mk/000077500000000000000000000000001475767661000140005ustar00rootroot00000000000000libreswan-5.2/mk/README.md000066400000000000000000000126121475767661000152610ustar00rootroot00000000000000 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-5.2/mk/TODO.md000066400000000000000000000060331475767661000150710ustar00rootroot00000000000000 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 dealt 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-5.2/mk/config.mk000066400000000000000000000710111475767661000155760ustar00rootroot00000000000000# 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-2023 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 5.1 config variables. # ifdef USE_NSS_AVA_COPY $(error ERROR: Deprecated USE_NSS_AVA_COPY variable set, please remove) endif # # Error out on deprecated since 5.0 config variables. # ifdef HAVE_IPTABLES $(error ERROR: Deprecated HAVE_IPTABLES variable set, use USE_IPTABLES instead) endif ifdef HAVE_NFTABLES $(error ERROR: Deprecated HAVE_NFTABLES variable set, use USE_NFTABLES instead) endif # # 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 MANDIR 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 MANDIR instead) endif ifdef INC_DOCDIR $(error ERROR: Deprecated INC_DOCDIR variable is set, use EXAMPLE_IPSEC_SYSCONFDIR instead) endif ifdef INC_RCDIRS $(error ERROR: Deprecated variable INC_RCDIRS is set, use INIT_D_DIR instead endif ifdef INC_RCDEFAULT $(error ERROR: Deprecated variable INC_RCDEFAULT is set, use INIT_D_DIR instead) endif ifdef FINALLIBEXECDIR $(error ERROR: deprecated variable FINALLIBEXECDIR is set, use LIBEXECDIR instead) endif ifdef FINALMANDIR $(error ERROR: deprecated variable FINALMANDIR is set, use MANDIR instead) endif ifdef FINALCONFFILE $(error ERROR: deprecated variable FINALCONFFILE is set, use IPSEC_CONF instead) endif ifdef CONFFILE $(error ERROR: deprecated variable CONFFILE is set, use IPSEC_CONF instead) endif ifdef IPSEC_CONF $(error ERROR: deprecated variable IPSEC_CONF is set, use IPSEC_CONF instead) endif ifdef IPSEC_SECRETS_FILE $(error ERROR: deprecated variable IPSEC_SECRETS_FILE is set, use IPSEC_SECRETS instead) endif ifdef CONFDDIR $(error ERROR: deprecated variable CONFDDIR is set, use IPSEC_CONFDDIR instead) endif ifdef FINALCONFDDIR $(error ERROR: deprecated variable FINALCONFDDIR is set, use IPSEC_CONFDDIR instead) endif ifdef EXAMPLECONFDDIR $(error ERROR: deprecated variable EXAMPLECONFDDIR is set, use EXAMPLE_IPSEC_CONFDDIR instead) endif ifdef EXAMPLEFINALCONFDDIR $(error ERROR: deprecated variable EXAMPLEFINALCONFDDIR is set, use EXAMPLE_IPSEC_CONFDDIR instead) endif ifdef FINALLOGDIR $(error ERROR: deprecated variable FINALLOGDIR is set, use LOGDIR instead) endif ifdef FINALSBINDIR $(error ERROR: deprecated variable FINALSBINDIR is set, use SBINDIR instead) endif ifdef FINALVARDIR $(error ERROR: deprecated variable FINALVARDIR is set, use VARDIR instead) endif ifdef FINALPPKDIR $(error ERROR: deprecated variable FINALPPKDIR is set) endif ifdef PPKDIR $(error ERROR: deprecated variable PPKDIR is set) endif ifdef FINALSYSCONFDIR $(error ERROR: deprecated variable FINALSYSCONFDIR is set, use SYSCONFDIR instead) endif ifdef FINALCONFDIR $(error ERROR: deprecated variable FINALCONFDIR is set, use SYSCONFDIR instead) endif ifdef CONFDIR $(error ERROR: deprecated variable CONFDIR is set, use SYSCONFDIR instead) endif ifdef FINALDOCDIR $(error ERROR: deprecated variable FINALDOCDIR is set, use EXAMPLE_IPSEC_SYSCONFDIR instead) endif ifdef DOCDIR $(error ERROR: deprecated variable DOCDIR is set, use EXAMPLE_IPSEC_SYSCONFDIR instead) endif ifdef FINALINITDDIR $(error ERROR: deprecated variable FINALINITDDIR is set, use INIT_D_DIR instead) endif ifdef FINALRUNDIR $(error ERROR: deprecated variable FINALRUNDIR is set, use RUNDIR instead) endif ifdef FINALLOGROTATEDDIR $(error ERROR: deprecated variable FINALLOGROTATEDDIR is set, use LOGROTATEDDIR instead) endif ifdef EXAMPLEFINALLOGROTATEDDIR $(error ERROR: deprecated variable EXAMPLEFINALLOGROTATEDDIR is set, use EXAMPLE_LOGROTATEDDIR instead) endif ifdef FINALPAMCONFDIR $(error ERROR: deprecated variable FINALPAMCONFDIR is set, use PAMCONFDIR instead) endif ifdef EXAMPLEFINALPAMCONFDIR $(error ERROR: deprecated variable EXAMPLEFINALPAMCONFDIR is set, use EXAMPLE_PAMCONFDIR 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 WARNING_CFLAGS += -Wextra WARNING_CFLAGS += -Wformat WARNING_CFLAGS += -Wformat-nonliteral WARNING_CFLAGS += -Wformat-security WARNING_CFLAGS += -Wundef WARNING_CFLAGS += -Wmissing-declarations WARNING_CFLAGS += -Wredundant-decls WARNING_CFLAGS += -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. the "ipsec" command will # look for them when it is run. LIBEXECDIR ?= $(PREFIX)/libexec/ipsec TRANSFORMS += 's:@@LIBEXECDIR@@:$(LIBEXECDIR):g' TRANSFORMS += 's:@@IPSEC_EXECDIR@@:$(LIBEXECDIR):g' USERLAND_CFLAGS += -DIPSEC_EXECDIR=\"$(LIBEXECDIR)\" # SBINDIR is where the user interface command goes. SBINDIR ?= $(PREFIX)/sbin TRANSFORMS += 's:@@SBINDIR@@:$(SBINDIR):g' USERLAND_CFLAGS += -DIPSEC_SBINDIR=\"$(SBINDIR)\" # where the appropriate manpage tree is located MANDIR ?= $(PREFIX)/share/man TRANSFORMS += 's:@@MANDIR@@:$(MANDIR):' # where readonly configuration files go SYSCONFDIR ?= /etc TRANSFORMS += 's:@@SYSCONFDIR@@:$(SYSCONFDIR):g' # # INITSYSTEM # # Selects directory under initsystems/. The below defines where to # install it (and their examples). # # Unlike ifndef INITSYSTEM, $(origin INITSYSTEM) considers # INITSYSTEM= to be defined. ifeq ($(origin INITSYSTEM),undefined) $(error INITSYSTEM not defined) endif INSTALL_INITSYSTEM ?= true # Where the INITSYSTEM=rc.d boot/shutdown scripts and examples go. # During install the $(DESTDIR) prefix is added. RC_D_DIR ?= $(SYSCONFDIR)/rc.d TRANSFORMS += 's:@@RC_D_DIR@@:$(RC_D_DIR):g' EXAMPLE_RC_D_DIR ?= $(EXAMPLE_IPSEC_SYSCONFDIR)/$(notdir $(RC_D_DIR)) TRANSFORMS += 's:@@EXAMPLE_RC_D_DIR@@:$(EXAMPLE_RC_D_DIR):g' # Where the INITSYSTEM=init.d scripts and examples go. During install # $(DESTDIR) prefix is added. INIT_D_DIR ?= /etc/init.d TRANSFORMS += 's:@@INIT_D_DIR@@:$(INIT_D_DIR):g' EXAMPLE_INIT_D_DIR ?= $(EXAMPLE_IPSEC_SYSCONFDIR)/$(notdir $(INIT_D_DIR)) TRANSFORMS += 's:@@EXAMPLE_INIT_D_DIR@@:$(EXAMPLE_INIT_D_DIR):g' # run dir - defaults to /run/pluto # Some older systems might need to set this to /var/run/pluto RUNDIR ?= /run/pluto TRANSFORMS += 's:@@RUNDIR@@:$(RUNDIR):g' USERLAND_CFLAGS += -DIPSEC_RUNDIR=\"$(RUNDIR)\" # final configuration file IPSEC_CONF ?= $(SYSCONFDIR)/ipsec.conf TRANSFORMS += 's:@@IPSEC_CONF@@:$(IPSEC_CONF):g' USERLAND_CFLAGS += -DIPSEC_CONF=\"$(IPSEC_CONF)\" # final secrets file IPSEC_SECRETS ?= $(SYSCONFDIR)/ipsec.secrets TRANSFORMS += 's:@@IPSEC_SECRETS@@:$(IPSEC_SECRETS):g' USERLAND_CFLAGS += -DIPSEC_SECRETS=\"$(IPSEC_SECRETS)\" IPSEC_CONFDDIR ?= $(SYSCONFDIR)/ipsec.d TRANSFORMS += 's:@@IPSEC_CONFDDIR@@:$(IPSEC_CONFDDIR):g' USERLAND_CFLAGS += -DIPSEC_CONFDDIR=\"$(IPSEC_CONFDDIR)\" EXAMPLE_IPSEC_CONFDDIR ?= $(EXAMPLE_IPSEC_SYSCONFDIR)/ipsec.d TRANSFORMS += 's:@@EXAMPLE_IPSEC_CONFDDIR@@:$(EXAMPLE_IPSEC_CONFDDIR):g' # libreswan's sample configuration files go into ... EXAMPLE_IPSEC_SYSCONFDIR ?= $(PREFIX)/share/doc/libreswan TRANSFORMS += 's:@@EXAMPLE_IPSEC_SYSCONFDIR@@:$(EXAMPLE_IPSEC_SYSCONFDIR):g' # where per-conn pluto logs go VARDIR ?= /var TRANSFORMS += 's:@@VARDIR@@:$(VARDIR):g' USERLAND_CFLAGS += -DIPSEC_VARDIR=\"$(VARDIR)\" LOGDIR ?= $(VARDIR)/log TRANSFORMS += 's:@@LOGDIR@@:$(LOGDIR):g' # Directory for logrotate config LOGROTATEDDIR ?= $(SYSCONFDIR)/logrotate.d TRANSFORMS += 's:@@LOGROTATEDDIR@@:$(LOGROTATEDDIR):g' EXAMPLE_LOGROTATEDDIR ?= $(EXAMPLE_IPSEC_SYSCONFDIR)/logrotate.d TRANSFORMS += 's:@@EXAMPLE_LOGROTATEDDIR@@:$(EXAMPLE_LOGROTATEDDIR):g' # Where nss databases go NSSDIR ?= $(VARDIR)/lib/ipsec/nss # RHEL/CentOS <= 8 and Fedora <= 32 uses /etc/ipsec.d # NSSDIR ?= /etc/ipsec.d TRANSFORMS += 's:@@IPSEC_NSSDIR@@:$(NSSDIR):g' USERLAND_CFLAGS += -DIPSEC_NSSDIR=\"$(NSSDIR)\" # Where NSS programs live (well most of them, fedora hides vfychain, # see hack in ipsec.in). ifndef NSS_BINDIR NSS_BINDIR := $(shell pkg-config --variable prefix nss)/bin export NSS_BINDIR endif TRANSFORMS += 's:@@NSS_BINDIR@@:$(NSS_BINDIR):g' USERLAND_CFLAGS += -DNSS_BINDIR=\"$(NSS_BINDIR)\" DOCKER_PLUTONOFORK ?= --nofork # 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 # For "make install", should stuff be installed into /etc? PKGSRC, # for instance, wants everything copied into examples/ but not # installed into /etc. INSTALL_CONFIGS ?= true # 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 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 # -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) 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_TYPE ?= simple SD_WATCHDOGSEC ?= 0 endif # 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 # 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 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 LSWSDLIB = $(abs_top_builddir)/lib/liblswsd/liblswsd.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 # how to do variable substitution in sed-transformed files # # Most SEDs support -i (in-place) but FreeBSD does not and gets to # override this with gsed. SED ?= sed TRANSFORM_VARIABLES = $(SED) \ -e "s:@@DOCKER_PLUTONOFORK@@:$(DOCKER_PLUTONOFORK):g" \ -e "s:@@INITSYSTEM@@:$(INITSYSTEM):g" \ -e "s:@@IPSECVERSION@@:$(IPSECVERSION):g" \ -e "s:@@MODPROBEARGS@@:$(MODPROBEARGS):g" \ -e "s:@@MODPROBEBIN@@:$(MODPROBEBIN):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" \ $(patsubst %, -e %, $(TRANSFORMS)) # computing checksums; debian things different CKSUM ?= cksum # 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_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 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 endif ifeq ($(USE_LDAP),true) USERLAND_CFLAGS += -DLIBLDAP LDAP_LDFLAGS ?= -lldap -llber endif ifeq ($(USE_NM),true) USERLAND_CFLAGS+=-DHAVE_NM endif # # Enable Client Address Translation; what ever that is. # USE_CAT ?= false ifeq ($(USE_CAT),true) USERLAND_CFLAGS += -DUSE_CAT endif TRANSFORMS += 's:@@USE_CAT@@:$(USE_CAT):g' # # Enable NFLOG; what ever that is. # USE_NFLOG ?= false ifeq ($(USE_NFLOG),true) USERLAND_CFLAGS += -DUSE_NFLOG endif TRANSFORMS += 's:@@USE_NFLOG@@:$(USE_NFLOG):g' # # IPTABLES vs NFTABLES # USE_IPTABLES ?= false ifeq ($(USE_IPTABLES),true) USERLAND_CFLAGS += -DUSE_IPTABLES endif TRANSFORMS += 's:@@USE_IPTABLES@@:$(USE_IPTABLES):g' USE_NFTABLES ?= false ifeq ($(USE_NFTABLES),true) USERLAND_CFLAGS += -DUSE_NFTABLES endif TRANSFORMS += 's:@@USE_NFTABLES@@:$(USE_NFTABLES):g' # # Check for conflicts between NFTABLES, IPTABLES, CAT and # NFLOG. # # CAT and NFLOG require one of USE_NFTABLES or USE_IPTABLES. Can't # have both USE_NFTABLES and USE_IPTABLES. # # Do this after all the MAKE variables have been initialized. ifeq ($(USE_CAT),true) ifeq ($(USE_NFTABLES),false) ifeq ($(USE_IPTABLES),false) $(error ERROR: USE_CAT=true requires either USE_NFTABLES=true or USE_IPTABLES=true) endif endif endif ifeq ($(USE_NFLOG),true) ifeq ($(USE_NFTABLES),false) ifeq ($(USE_IPTABLES),false) $(error ERROR: USE_NFLOG=true requires either USE_NFTABLES=true or USE_IPTABLES=true) endif endif endif ifeq ($(USE_NFTABLES),true) ifeq ($(USE_IPTABLES),true) $(error ERROR: Both USE_NFTABLES=true and USE_IPTABLES=true are set, you can not set both) endif 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 PAMCONFDIR ?= $(SYSCONFDIR)/pam.d TRANSFORMS += 's:@@PAMCONFDIR@@:$(PAMCONFDIR):g' EXAMPLE_PAMCONFDIR ?= $(EXAMPLE_IPSEC_SYSCONFDIR)/pam.d TRANSFORMS += 's:@@EXAMPLEPAMCONFDIR@@:$(EXAMPLE_PAMCONFDIR):g' # # 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 += -DIPSEC_SYSCONFDIR=\"$(SYSCONFDIR)\" USERLAND_CFLAGS += -DPOLICYGROUPSDIR=\"$(IPSEC_CONFDDIR)/policies\" # Ensure that calls to NSPR's PR_ASSERT() really do abort. While all # calls should have been eliminated (replaced by passert()), keep this # definition just in case. USERLAND_CFLAGS += -DFORCE_PR_ASSERT # stick with RETRANSMIT_INTERVAL_DEFAULT as makefile variable name ifdef RETRANSMIT_INTERVAL_DEFAULT USERLAND_CFLAGS += -DRETRANSMIT_INTERVAL_DEFAULT_MS="$(RETRANSMIT_INTERVAL_DEFAULT)" endif ifeq ($(HAVE_BROKEN_POPEN),true) USERLAND_CFLAGS += -DHAVE_BROKEN_POPEN endif # Do things like create a daemon using the sequence fork()+exit(). If # you don't have or don't want to use fork() disable this. USE_FORK ?= true ifeq ($(USE_FORK),true) USERLAND_CFLAGS += -DUSE_FORK=1 else USERLAND_CFLAGS += -DUSE_FORK=0 endif # Where possible use vfork() instead of fork(). For instance, when # creating a child process, use the call sequence vfork()+exec(). # # Systems with nommu, which do not have fork(), should set this. USE_VFORK ?= false ifeq ($(USE_VFORK),true) USERLAND_CFLAGS += -DUSE_VFORK=1 else USERLAND_CFLAGS += -DUSE_VFORK=0 endif # Where possible use daemon() instead of fork()+exit() to create a # daemon (detached) processes. # # Some system's don't support daemon() and some systems don't support # fork(). Since the daemon call can lead to a race it isn't the # preferred option. USE_DAEMON ?= false ifeq ($(USE_DAEMON),true) USERLAND_CFLAGS += -DUSE_DAEMON=1 else USERLAND_CFLAGS += -DUSE_DAEMON=0 endif # OSX, for instance, doesn't have this call. USE_PTHREAD_SETSCHEDPRIO ?= true ifeq ($(USE_PTHREAD_SETSCHEDPRIO),true) USERLAND_CFLAGS += -DUSE_PTHREAD_SETSCHEDPRIO=1 else USERLAND_CFLAGS += -DUSE_PTHREAD_SETSCHEDPRIO=0 endif ifeq ($(origin GCC_LINT),undefined) GCC_LINT = -DGCC_LINT endif USERLAND_CFLAGS += $(GCC_LINT) # 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 # Support for CISCO adding a second, narrower, child to IKEv1?!? # probably broken. USE_CISCO_SPLIT ?= false ifeq ($(USE_CISCO_SPLIT),true) USERLAND_CFLAGS += -DUSE_CISCO_SPLIT endif endif libreswan-5.2/mk/configs.sh000077500000000000000000000010151475767661000157640ustar00rootroot00000000000000#!/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-5.2/mk/defaults/000077500000000000000000000000001475767661000156075ustar00rootroot00000000000000libreswan-5.2/mk/defaults/darwin.mk000066400000000000000000000017251475767661000174310ustar00rootroot00000000000000BSD_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_DNSSEC = false #DEFAULT_DNSSEC_ROOTKEY_FILE = /usr/local/etc/unbound/root.key INITSYSTEM=rc.d # not /run/pluto RUNDIR=/var/run/pluto # PREFIX = /usr/local from mk/config.mk SYSCONFDIR=$(PREFIX)/etc NSSDIR=$(PREFIX)/etc/ipsec.d EXAMPLE_IPSEC_SYSCONFDIR=$(PREFIX)/share/examples/libreswan libreswan-5.2/mk/defaults/freebsd.mk000066400000000000000000000021171475767661000175530ustar00rootroot00000000000000BSD_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_PTHREAD_SETSCHEDPRIO = false USE_DNSSEC = false DEFAULT_DNSSEC_ROOTKEY_FILE = /usr/local/etc/unbound/root.key INITSYSTEM=rc.d # not /run/pluto RUNDIR=/var/run/pluto # PREFIX = /usr/local from mk/config.mk SYSCONFDIR=$(PREFIX)/etc NSSDIR=$(PREFIX)/etc/ipsec.d EXAMPLE_IPSEC_SYSCONFDIR=$(PREFIX)/share/examples/libreswan # LTO seems either broken or confused USE_LTO ?= false # FreeBSD's default SED doesn't support -i (in-place) SED = gsed libreswan-5.2/mk/defaults/linux.mk000066400000000000000000000064321475767661000173040ustar00rootroot00000000000000# 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 CKSUM ?= shasum 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 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 # # Alpine # ifneq ($(filter alpine,$(LINUX_VARIANT)),) DEFAULT_DNSSEC_ROOTKEY_FILE ?= /usr/share/dnssec-root/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 overridden by above) # USE_XFRM ?= true USE_XFRM_HEADER_COPY ?= true USE_DNSSEC ?= true ifneq ($(USE_IPTABLES), true) USE_NFTABLES ?= true endif # Opportunistic Encryption with NAT (Client Address Translation) support # currently only supported on Linux USE_CAT ?= true # Linux NFLOG support USE_NFLOG ?= true libreswan-5.2/mk/defaults/netbsd.mk000066400000000000000000000021301475767661000174130ustar00rootroot00000000000000BSD_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 RUNDIR=/var/run/pluto # PREFIX = /usr/local from mk/config.mk SYSCONFDIR=$(PREFIX)/etc NSSDIR=$(PREFIX)/etc/ipsec.d EXAMPLE_IPSEC_SYSCONFDIR=$(PREFIX)/share/examples/libreswan # Not $(PREFIX)/share/man MANDIR=$(PREFIX)/man # LTO seems either broken or confused USE_LTO ?= false # CHACHA is embedded in the ESP proposal (it shouldn't) this removes # it, but also removes it from IKE, oops. USE_CHACHA = false libreswan-5.2/mk/defaults/openbsd.mk000066400000000000000000000024641475767661000176000ustar00rootroot00000000000000BSD_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 # OpenBSD seems to call GCC egcc #CC=egcc CC=clang-17 WARNING_CFLAGS += -Wself-assign USERLAND_CFLAGS += -DUSE_SOCKADDR_LEN # hack around broken LDNS header refering to undefined USE_ED448 USERLAND_CFLAGS += -DUSE_ED448=LDNS_BUILD_CONFIG_USE_ED448 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_PTHREAD_SETSCHEDPRIO = false USE_AUTHPAM = false USE_DNSSEC = true DEFAULT_DNSSEC_ROOTKEY_FILE = /var/unbound/db/root.key INITSYSTEM=rc.d # not /run/pluto RUNDIR=/var/run/pluto # Not $(PREFIX)/share/man MANDIR=$(PREFIX)/man # PREFIX = /usr/local from mk/config.mk SYSCONFDIR=$(PREFIX)/etc NSSDIR=$(PREFIX)/etc/ipsec.d EXAMPLE_IPSEC_SYSCONFDIR=$(PREFIX)/share/examples/libreswan # LTO seems either broken or confused USE_LTO ?= false libreswan-5.2/mk/dirs.mk000066400000000000000000000124301475767661000152720ustar00rootroot00000000000000# 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 for non-top-level # directories PATH_SRCDIR contains a leading / so that ${builddir} is # built correctly. 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-5.2/mk/docker-targets.mk000066400000000000000000000230651475767661000172550ustar00rootroot00000000000000# 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_DNSSEC ?= false D_USE_NSS_IPSEC_PROFILE ?= false 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 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-5.2/mk/find.sh000077500000000000000000000023741475767661000152650ustar00rootroot00000000000000#!/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/web/*" -print \ -o -type f -path "$d/testing/kvm/*" -print \ -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 \ -o -type f -name '*.lex' -print \ -o -type f -name '*.xml' -print } if test $# -gt 0 ; then look | xargs grep -n "$@" else look fi libreswan-5.2/mk/install.init.d.mk000066400000000000000000000037611475767661000171720ustar00rootroot00000000000000# /etc/init.d install targets, 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. # 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. ifndef INIT_D_FILE $(error need INIT_D_FILE defined) endif # assume include $(top_srcdir)/mk/install.mk # Force dependency order so that base and install rules aren't run in # parallel. local-base: $(INIT_D_FILE) .PHONY: install.init.d local-install-base: install.init.d install.init.d: $(INIT_D_FILE) local-base @set -eu ; $(call install-directory, $(DESTDIR)$(EXAMPLE_INIT_D_DIR)) @set -eu ; $(call install-file, $(INSTBINFLAGS), \ $(builddir)/$(INIT_D_FILE), \ $(DESTDIR)$(EXAMPLE_INIT_D_DIR)/$(INIT_D_FILE)) ifeq ($(INSTALL_INITSYSTEM),true) @set -eu ; $(call install-directory, $(DESTDIR)$(INIT_D_DIR)) @set -eu ; $(call install-missing-file, $(INSTBINFLAGS), \ $(DESTDIR)$(EXAMPLE_INIT_D_DIR)/$(INIT_D_FILE), \ $(DESTDIR)$(INIT_D_DIR)/ipsec) endif list-local-base: list.init.d .PHONY: list.init.d list.init.d: @set -eu ; echo $(EXAMPLE_INIT_D_DIR)/$(INIT_D_FILE) ifeq ($(INSTALL_INITSYSTEM),true) @set -eu ; echo $(INIT_D_DIR)/$(INIT_D_FILE) endif libreswan-5.2/mk/install.mk000066400000000000000000000023601475767661000160000ustar00rootroot00000000000000# Install magic, 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. # $(call install-directory, [, ]) install-directory = \ if test ! -d $(strip $(1)) ; then \ echo mkdir $(if $(2), -m $(strip $(2))) -p $(strip $(1)) ; \ mkdir $(if $(2), -m $(strip $(2))) -p $(strip $(1)) ; \ fi # $(call install-file, , , ) install-file = \ echo $(strip $(2)) '->' $(strip $(3)) ; \ $(INSTALL) $(strip $(1)) $(strip $(2)) $(strip $(3)) # $(call install-missing-file, , , ) install-missing-file = \ if test ! -f $(strip $(3)) ; then \ $(call install-file, $(1), $(2), $(3)); \ else \ echo "WARNING: skipping as file is already installed: $(strip $(3))" 1>&2 ; \ fi libreswan-5.2/mk/library.mk000066400000000000000000000014371475767661000160020ustar00rootroot00000000000000# 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-5.2/mk/local.mk000066400000000000000000000027031475767661000154250ustar00rootroot00000000000000# 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-5.2/mk/man-html-link.xsl000066400000000000000000000010121475767661000171720ustar00rootroot00000000000000 . .html libreswan-5.2/mk/manpages.mk000066400000000000000000000056441475767661000161350ustar00rootroot00000000000000# 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; 5 is file formats; 7 is overviews; 8 is system # programs. MANDIR.3 ?= $(MANDIR)/man3 MANDIR.5 ?= $(MANDIR)/man5 MANDIR.7 ?= $(MANDIR)/man7 MANDIR.8 ?= $(MANDIR)/man8 # 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-html: $(addprefix $(builddir)/, $(addsuffix .html, $(MANPAGES))) local-install-manpages: local-manpages @set -eu $(foreach manpage,$(MANPAGES), \ $(foreach refname,$(call refnames,$(srcdir)/$(manpage).xml), \ $(foreach destdir,$(DESTDIR)$(MANDIR$(suffix $(refname))), \ ; echo '$(builddir)/$(refname)' '->' $(destdir) \ ; mkdir -p $(destdir) \ ; $(INSTALL) $(INSTMANFLAGS) '$(builddir)/$(refname)' '$(destdir)'))) list-local-manpages: @set -eu $(foreach manpage,$(MANPAGES), \ $(foreach refname,$(call refnames,$(srcdir)/$(manpage).xml), \ ; echo $(DESTDIR)$(MANDIR$(suffix $(refname)))/$(refname))) local-clean-manpages: rm -f $(builddir)/*.[1-8] rm -f $(builddir)/*.[1-8].tmp rm -f $(builddir)/*.[1-8].man rm -f $(builddir)/*.[1-8].html # Default rule for creating the man pages. # # Danger: XMLTO will barf when run on 9p (it tries to update ownership # and fails). The test KVMs point OBJDIR at /var/tmp to avoid this # problem. # # Use a dummy target since the generated man pages probably don't # match the target name. define transform-doc $(TRANSFORM_VARIABLES) -i $(1) endef $(builddir)/%.man: $(srcdir)/%.xml | $(builddir) $(XMLTO) $(XMLTO_FLAGS) man $< -o $(builddir) $(foreach r, $(shell $(top_srcdir)/packaging/utils/refnames.sh $<), \ $(call transform-doc, $(builddir)/$(r))) touch $@ $(builddir)/%.html: $(srcdir)/%.xml | $(builddir) $(XMLTO) $(XMLTO_FLAGS) html-nochunks -m $(top_srcdir)/mk/man-html-link.xsl $< -o $(top_builddir)/html $(TRANSFORM_VARIABLES) -i $(top_builddir)/html/$*.html touch $@ libreswan-5.2/mk/objdir.mk000066400000000000000000000040631475767661000156050ustar00rootroot00000000000000# 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. # # OSDEP - the target's OS # # Below assumes a native build. Cross compiling will need to override # this. # # "uname" describes the the build system's kernel, and not the target # system's operating environment (architecture, kernel, operating # system version, glibc version, ...). # # 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 # # OBJDIR - directory to store result # # The obsession with reproducible builds means that this variable # can't contain anything that might identify the build system, such as # the host name. # # Below assumes build directory is local. Shared directory builds # will need to override this (the test VMs, for instance, build into # /var/tmp/OBJDIR). # ifndef OBJDIR 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') # evaluate once OBJDIR := OBJ.$(OSDEP).$(ARCH) endif export OBJDIR libreswan-5.2/mk/perf.sh000077500000000000000000000042121475767661000152720ustar00rootroot00000000000000#!/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-5.2/mk/program.mk000066400000000000000000000036041475767661000160030ustar00rootroot00000000000000# 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 ?= $(addprefix ipsec-, $(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=$(DESTDIR)$(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-5.2/mk/rules.mk000066400000000000000000000055071475767661000154720ustar00rootroot00000000000000# 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='"$(patsubst /%,%,$(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-5.2/mk/targets.mk000066400000000000000000000075521475767661000160130ustar00rootroot00000000000000# 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 man install-all programs: all man: manpages install-all: install # # 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 html $(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-5.2/mk/testing.mk000066400000000000000000000051651475767661000160150ustar00rootroot00000000000000# Testing MAKE variables, for Libreswan # # Copyright (C) 2024 Andrew Cagney # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # Sub directories such as testing/web and testing/kvm pull in this # file so that they get consistent definitions based on the contents # of Makefile.inc.local. ifdef KVM_RUTDIR TESTING_RUTDIR = $(KVM_RUTDIR) else TESTING_RUTDIR ?= $(abs_top_srcdir) KVM_RUTDIR = $(TESTING_RUTDIR) endif ifdef KVM_BENCHDIR TESTING_BENCHDIR = $(KVM_BENCHDIR) else TESTING_BENCHDIR ?= $(abs_top_srcdir) KVM_BENCHDIR = $(TESTING_BENCHDIR) endif ifdef KVM_SOURCEDIR TESTING_SOURCEDIR = $(KVM_SOURCEDIR) else TESTING_SOURCEDIR ?= $(TESTING_RUTDIR) KVM_SOURCEDIR = $(TESTING_SOURCEDIR) endif ifdef KVM_WEBDIR TESTING_WEBDIR = $(KVM_WEBDIR) else TESTING_WEBDIR ?= $(abs_top_srcdir)/RESULTS KVM_WEBDIR = $(TESTING_WEBDIR) endif # This gets different values depending on where WEBDIR is. # # Not sure about the names, need to specify: # # - starting commit # - ending commit # - prefix name # - suffix name TESTING_HASH ?= $(shell git -C $(TESTING_RUTDIR) show --no-patch --format=%H HEAD) TESTING_ABBREV_HASH = $(shell git -C $(TESTING_RUTDIR) show --no-patch --format="%h" $(TESTING_HASH)) ifdef WEB_BRANCH_NAME TESTING_BRANCH_NAME = $(WEB_BRANCH_NAME) else TESTING_BRANCH_NAME ?= $(shell git -C $(TESTING_RUTDIR) describe --abbrev=0) endif ifdef WEB_BRANCH_TAG TESTING_BRANCH_TAG = $(WEB_BRANCH_TAG) else TESTING_BRANCH_TAG ?= $(TESTING_BRANCH_NAME) endif TESTING_BRANCH_COUNT = $(shell git -C $(TESTING_RUTDIR) rev-list --count $(TESTING_BRANCH_TAG)..$(TESTING_HASH)) ifeq ($(TESTING_WEBDIR),$(abs_top_srcdir)/RESULTS) GIT_DESCRIPTION = $(shell git -C $(TESTING_RUTDIR) describe --long) GIT_BRANCH = $(shell $(top_srcdir)/testing/web/gime-git-branch.sh $(TESTING_RUTDIR)) TESTING_RUNDIR ?= $(GIT_DESCRIPTION)-$(GIT_BRANCH) else TESTING_RUNDIR = $(TESTING_BRANCH_NAME)-$(TESTING_BRANCH_COUNT)-g$(TESTING_ABBREV_HASH) endif TESTING_RESULTSDIR = $(TESTING_WEBDIR)/$(TESTING_RUNDIR) # these kickstart web pages; should be merged into above ifneq ($(wildcard $(TESTING_WEBDIR)),) # don't set to empty so that ifdef works WEB_ENABLED = true endif libreswan-5.2/mk/tests.sh000077500000000000000000000013541475767661000155040ustar00rootroot00000000000000#!/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 < Wed, 26 Feb 2026 01:00:00 +0200 libreswan-5.2/packaging/debian/compat000066400000000000000000000000031475767661000177360ustar00rootroot0000000000000010 libreswan-5.2/packaging/debian/control000066400000000000000000000036631475767661000201520ustar00rootroot00000000000000Source: 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-gnutls-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 (>= 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: dns-root-data, bind9-host, iproute2, libnspr4, libnss3 (>= 3.16), libnss3-tools, nftables ${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-5.2/packaging/debian/copyright000066400000000000000000000274671475767661000205120ustar00rootroot00000000000000Format: 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-5.2/packaging/debian/gbp.conf000066400000000000000000000000721475767661000201550ustar00rootroot00000000000000[DEFAULT] pristine-tar = True upstream-tag = v%(version)s libreswan-5.2/packaging/debian/libreswan.dirs000066400000000000000000000000231475767661000214030ustar00rootroot00000000000000/var/lib/ipsec/nss libreswan-5.2/packaging/debian/libreswan.docs000066400000000000000000000001141475767661000213730ustar00rootroot00000000000000CREDITS README.md README.nss README.x509 docs/README.XAUTH docs/README.rfcs libreswan-5.2/packaging/debian/libreswan.examples000066400000000000000000000000201475767661000222550ustar00rootroot00000000000000docs/examples/* libreswan-5.2/packaging/debian/libreswan.install000066400000000000000000000000651475767661000221160ustar00rootroot00000000000000debian/90-libreswan.preset lib/systemd/system-preset libreswan-5.2/packaging/debian/libreswan.lintian-overrides000066400000000000000000000005761475767661000241150ustar00rootroot00000000000000# 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-5.2/packaging/debian/libreswan.logcheck.ignore.paranoid000066400000000000000000000005221475767661000253030ustar00rootroot00000000000000pluto.*: 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-5.2/packaging/debian/libreswan.logcheck.ignore.server000066400000000000000000000007501475767661000250170ustar00rootroot00000000000000pluto.*: 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-5.2/packaging/debian/libreswan.logcheck.ignore.workstation000066400000000000000000000007501475767661000260750ustar00rootroot00000000000000pluto.*: 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-5.2/packaging/debian/libreswan.postrm000066400000000000000000000002651475767661000217760ustar00rootroot00000000000000#!/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-5.2/packaging/debian/patches/000077500000000000000000000000001475767661000201665ustar00rootroot00000000000000libreswan-5.2/packaging/debian/patches/0002-debian-pam.d-pluto.patch000066400000000000000000000023741475767661000251540ustar00rootroot00000000000000From: 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-5.2/packaging/debian/patches/series000066400000000000000000000002321475767661000214000ustar00rootroot00000000000000#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-5.2/packaging/debian/rules000077500000000000000000000025671475767661000176310ustar00rootroot00000000000000#!/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 \ LIBEXECDIR=/usr/libexec/ipsec \ MANDIR=/usr/share/man \ USE_LDAP=true \ INITSYSTEM=systemd \ $(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 \ LIBEXECDIR=/usr/libexec/ipsec \ MANDIR=/usr/share/man \ USE_LDAP=true \ INITSYSTEM=systemd \ $(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-5.2/packaging/debian/source/000077500000000000000000000000001475767661000200375ustar00rootroot00000000000000libreswan-5.2/packaging/debian/source/format000066400000000000000000000000141475767661000212450ustar00rootroot000000000000003.0 (quilt) libreswan-5.2/packaging/debian/tests/000077500000000000000000000000001475767661000177015ustar00rootroot00000000000000libreswan-5.2/packaging/debian/tests/control000066400000000000000000000001631475767661000213040ustar00rootroot00000000000000Tests: opportunistic Restrictions: needs-root, isolation-machine Depends: @, iputils-ping, wget, systemd, dnsutils libreswan-5.2/packaging/debian/tests/opportunistic000077500000000000000000000022061475767661000225510ustar00rootroot00000000000000#!/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-5.2/packaging/debian/upstream/000077500000000000000000000000001475767661000203775ustar00rootroot00000000000000libreswan-5.2/packaging/debian/upstream/signing-key.asc000066400000000000000000000066671475767661000233320ustar00rootroot00000000000000-----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-5.2/packaging/debian/watch000066400000000000000000000004771475767661000176000ustar00rootroot00000000000000version=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-5.2/packaging/devuan/000077500000000000000000000000001475767661000165775ustar00rootroot00000000000000libreswan-5.2/packaging/devuan/90-libreswan.preset000066400000000000000000000002211475767661000222320ustar00rootroot00000000000000# Libreswan IPsec daemon needs to be configured before enabling. # See /usr/share/doc/libreswan/README.Debian for details. disable ipsec.service libreswan-5.2/packaging/devuan/Makefile000066400000000000000000000000501475767661000202320ustar00rootroot00000000000000deb: $(MAKE) --directory ../debian deb libreswan-5.2/packaging/devuan/README.Devuan000066400000000000000000000001501475767661000206740ustar00rootroot00000000000000libreswan for Devuan -------------------- Completely untested - provide feedback if something is wrong libreswan-5.2/packaging/devuan/changelog000066400000000000000000000002071475767661000204500ustar00rootroot00000000000000libreswan (5.2-1) unstable; urgency=low * Release 5.2-1 -- Libreswan Team Wed, 26 Feb 2026 01:00:00 +0200 libreswan-5.2/packaging/devuan/compat000066400000000000000000000000031475767661000177760ustar00rootroot0000000000000010 libreswan-5.2/packaging/devuan/control000066400000000000000000000037541475767661000202130ustar00rootroot00000000000000Source: 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-5.2/packaging/devuan/copyright000066400000000000000000000274671475767661000205520ustar00rootroot00000000000000Format: 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-5.2/packaging/devuan/gbp.conf000066400000000000000000000000721475767661000202150ustar00rootroot00000000000000[DEFAULT] pristine-tar = True upstream-tag = v%(version)s libreswan-5.2/packaging/devuan/libreswan.dirs000066400000000000000000000000231475767661000214430ustar00rootroot00000000000000/var/lib/ipsec/nss libreswan-5.2/packaging/devuan/libreswan.docs000066400000000000000000000001141475767661000214330ustar00rootroot00000000000000CREDITS README.md README.nss README.x509 docs/README.XAUTH docs/README.rfcs libreswan-5.2/packaging/devuan/libreswan.examples000066400000000000000000000000201475767661000223150ustar00rootroot00000000000000docs/examples/* libreswan-5.2/packaging/devuan/libreswan.install000066400000000000000000000000331475767661000221510ustar00rootroot00000000000000debian/90-libreswan.preset libreswan-5.2/packaging/devuan/libreswan.lintian-overrides000066400000000000000000000005761475767661000241550ustar00rootroot00000000000000# 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-5.2/packaging/devuan/libreswan.logcheck.ignore.paranoid000066400000000000000000000005221475767661000253430ustar00rootroot00000000000000pluto.*: 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-5.2/packaging/devuan/libreswan.logcheck.ignore.server000066400000000000000000000007501475767661000250570ustar00rootroot00000000000000pluto.*: 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-5.2/packaging/devuan/libreswan.logcheck.ignore.workstation000066400000000000000000000007501475767661000261350ustar00rootroot00000000000000pluto.*: 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-5.2/packaging/devuan/libreswan.postrm000066400000000000000000000002651475767661000220360ustar00rootroot00000000000000#!/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-5.2/packaging/devuan/patches/000077500000000000000000000000001475767661000202265ustar00rootroot00000000000000libreswan-5.2/packaging/devuan/patches/0002-debian-pam.d-pluto.patch000066400000000000000000000023241475767661000252070ustar00rootroot00000000000000From: 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-5.2/packaging/devuan/patches/series000066400000000000000000000002321475767661000214400ustar00rootroot00000000000000#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-5.2/packaging/devuan/rules000077500000000000000000000025051475767661000176610ustar00rootroot00000000000000#!/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 override_dh_auto_build: dh_auto_build -- programs \ ARCH=$(DEB_HOST_ARCH) \ IPSECVERSION=$(DEB_VERSION_UPSTREAM_REVISION) \ PREFIX=/usr \ LIBEXECDIR=/usr/libexec/ipsec \ NSSDIR=/var/lib/ipsec/nss \ 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 \ LIBEXECDIR=/usr/libexec/ipsec \ NSSDIR=/var/lib/ipsec/nss \ 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-5.2/packaging/devuan/source/000077500000000000000000000000001475767661000200775ustar00rootroot00000000000000libreswan-5.2/packaging/devuan/source/format000066400000000000000000000000141475767661000213050ustar00rootroot000000000000003.0 (quilt) libreswan-5.2/packaging/devuan/tests/000077500000000000000000000000001475767661000177415ustar00rootroot00000000000000libreswan-5.2/packaging/devuan/tests/control000066400000000000000000000001521475767661000213420ustar00rootroot00000000000000Tests: opportunistic Restrictions: needs-root, isolation-machine Depends: @, iputils-ping, wget, dnsutils libreswan-5.2/packaging/devuan/tests/opportunistic000077500000000000000000000022061475767661000226110ustar00rootroot00000000000000#!/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-5.2/packaging/devuan/upstream/000077500000000000000000000000001475767661000204375ustar00rootroot00000000000000libreswan-5.2/packaging/devuan/upstream/signing-key.asc000066400000000000000000000066671475767661000233720ustar00rootroot00000000000000-----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-5.2/packaging/devuan/watch000066400000000000000000000004771475767661000176400ustar00rootroot00000000000000version=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-5.2/packaging/fedora/000077500000000000000000000000001475767661000165555ustar00rootroot00000000000000libreswan-5.2/packaging/fedora/libreswan-sysctl.conf000066400000000000000000000010151475767661000227260ustar00rootroot00000000000000# 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-5.2/packaging/fedora/libreswan.spec000066400000000000000000000152121475767661000214200ustar00rootroot00000000000000%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 \\\ LIBEXECDIR=%{_libexecdir}/ipsec \\\ MANDIR=%{_mandir} \\\ PREFIX=%{_prefix} \\\ INITSYSTEM=systemd \\\ SBINDIR=%{_sbindir} \\\ 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 rc2 Name: libreswan Summary: Internet Key Exchange (IKEv1 and IKEv2) implementation for IPsec # version is generated in the release script Version: 5.2 Release: %{?prever:0.}1%{?prever:.%{prever}}%{?dist} License: GPL-2.0-or-later 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-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} %if "%{_sbindir}" == "%{_bindir}" # Compat symlinks for Requires in other packages. # We rely on filesystem to create the symlinks for us. Requires: filesystem(unmerged-sbin-symlinks) Provides: /usr/sbin/ipsec %endif %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 * Wed Feb 26 2025 Team Libreswan - 5.2-1 - Automated build from release tar ball libreswan-5.2/packaging/foobar000077700000000000000000000000001475767661000173602rhelustar00rootroot00000000000000libreswan-5.2/packaging/rhel/000077500000000000000000000000001475767661000162475ustar00rootroot00000000000000libreswan-5.2/packaging/rhel/7/000077500000000000000000000000001475767661000164155ustar00rootroot00000000000000libreswan-5.2/packaging/rhel/7/libreswan.spec000066400000000000000000000145441475767661000212670ustar00rootroot00000000000000# 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 \\\ LIBEXECDIR=%{_libexecdir}/ipsec \\\ MANDIR=%{_mandir} \\\ NSSDIR=%{_sysconfdir}/ipsec.d \\\ INITSYSTEM=systemd \\\ PREFIX=%{_prefix} \\\ SHELL_BINARY=/bin/sh \\\ USE_AUTHPAM=true \\\ USE_DNSSEC=%{USE_DNSSEC} \\\ 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 rc2 Name: libreswan Summary: Internet Key Exchange (IKEv1 and IKEv2) implementation for IPsec Version: 5.2 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 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 * Wed Feb 26 2025 Team Libreswan - 5.2-1 - Automated build from release tar ball libreswan-5.2/packaging/rhel/8/000077500000000000000000000000001475767661000164165ustar00rootroot00000000000000libreswan-5.2/packaging/rhel/8/libreswan.spec000066400000000000000000000144461475767661000212710ustar00rootroot00000000000000%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 \\\ LIBEXECDIR=%{_libexecdir}/ipsec \\\ MANDIR=%{_mandir} \\\ NSSDIR=%{_sysconfdir}/ipsec.d \\\ INITSYSTEM=systemd \\\ NSS_HAS_IPSEC_PROFILE=true \\\ PREFIX=%{_prefix} \\\ SHELL_BINARY=%{_bindir}/sh \\\ USE_AUTHPAM=true \\\ 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_KDF=true \\\ USE_SECCOMP=true \\\ %{nil} #global prever rc2 Name: libreswan Summary: IPsec implementation with IKEv1 and IKEv2 keying protocols # version is generated in the release script Version: 5.2 Release: %{?prever:0.}1%{?prever:.%{prever}}%{?dist} License: GPL-2.0-or-later 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-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} %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 * Wed Feb 26 2025 Team Libreswan - 5.2-1 - Automated build from release tar ball libreswan-5.2/packaging/rhel/9/000077500000000000000000000000001475767661000164175ustar00rootroot00000000000000libreswan-5.2/packaging/rhel/9/libreswan.spec000066400000000000000000000144461475767661000212720ustar00rootroot00000000000000%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 \\\ LIBEXECDIR=%{_libexecdir}/ipsec \\\ MANDIR=%{_mandir} \\\ NSSDIR=%{_sysconfdir}/ipsec.d \\\ INITSYSTEM=systemd \\\ NSS_HAS_IPSEC_PROFILE=true \\\ PREFIX=%{_prefix} \\\ SHELL_BINARY=%{_bindir}/sh \\\ USE_AUTHPAM=true \\\ 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_KDF=true \\\ USE_SECCOMP=true \\\ %{nil} #global prever rc2 Name: libreswan Summary: IPsec implementation with IKEv1 and IKEv2 keying protocols # version is generated in the release script Version: 5.2 Release: %{?prever:0.}1%{?prever:.%{prever}}%{?dist} License: GPL-2.0-or-later 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-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} %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 * Wed Feb 26 2025 Team Libreswan - 5.2-1 - Automated build from release tar ball libreswan-5.2/packaging/rhel/libreswan-sysctl.conf000066400000000000000000000010151475767661000224200ustar00rootroot00000000000000# 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-5.2/packaging/suse/000077500000000000000000000000001475767661000162745ustar00rootroot00000000000000libreswan-5.2/packaging/suse/README.suse000066400000000000000000000001661475767661000201350ustar00rootroot00000000000000The package files for SUSE (openSUSE, SLED, SLES) can be found on: https://software.opensuse.org/package/libreswan libreswan-5.2/packaging/utils/000077500000000000000000000000001475767661000164555ustar00rootroot00000000000000libreswan-5.2/packaging/utils/ciabot.pl000077500000000000000000000151211475767661000202560ustar00rootroot00000000000000#!/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-5.2/packaging/utils/git-private-update-hook000077500000000000000000000012621475767661000230550ustar00rootroot00000000000000#!/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-5.2/packaging/utils/git-update-hook000077500000000000000000000004231475767661000214030ustar00rootroot00000000000000#!/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-5.2/packaging/utils/makerelease000077500000000000000000000025101475767661000206570ustar00rootroot00000000000000#!/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-5.2/packaging/utils/makeshadowdir000077500000000000000000000022471475767661000212320ustar00rootroot00000000000000#!/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-5.2/packaging/utils/manlink000077500000000000000000000033271475767661000200410ustar00rootroot00000000000000#! /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-5.2/packaging/utils/refnames.sh000077500000000000000000000011071475767661000206130ustar00rootroot00000000000000#!/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-5.2/packaging/utils/setlibreswanversion000077500000000000000000000015341475767661000225160ustar00rootroot00000000000000#!/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 --always ${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-5.2/programs/000077500000000000000000000000001475767661000152235ustar00rootroot00000000000000libreswan-5.2/programs/Makefile000066400000000000000000000026071475767661000166700ustar00rootroot00000000000000# 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 += _unbound-hook SUBDIRS += _updown SUBDIRS += addconn SUBDIRS += algparse SUBDIRS += cavp SUBDIRS += ecdsasigkey SUBDIRS += ipsec SUBDIRS += letsencrypt SUBDIRS += newhostkey SUBDIRS += readwriteconf SUBDIRS += rsasigkey SUBDIRS += setup SUBDIRS += showhostkey SUBDIRS += showroute ifeq ($(USE_XFRM),true) SUBDIRS += _updown.xfrm endif ifneq ($(LINUX_VARIANT),) SUBDIRS += _stackmanager endif ifneq ($(BSD_VARIANT),) SUBDIRS += _updown.bsd endif include $(top_srcdir)/mk/targets.mk libreswan-5.2/programs/_import_crl/000077500000000000000000000000001475767661000175345ustar00rootroot00000000000000libreswan-5.2/programs/_import_crl/Makefile000066400000000000000000000016271475767661000212020ustar00rootroot00000000000000# _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) PROGRAM_MANPAGE = ifdef top_srcdir include $(top_srcdir)/mk/program.mk else include ../../mk/program.mk endif libreswan-5.2/programs/_import_crl/_import_crl.c000066400000000000000000000062521475767661000222160ustar00rootroot00000000000000/* 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" #include "lswlog.h" /* for fatal() */ #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_logger(argc, argv); 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(); init_nss(oco->nssdir, (struct nss_flags){0}, logger); fin = import_crl(url, tbuf, len); if (tbuf != NULL) pfree(tbuf); NSS_Shutdown(); return fin; } libreswan-5.2/programs/_plutorun/000077500000000000000000000000001475767661000172525ustar00rootroot00000000000000libreswan-5.2/programs/_plutorun/Makefile000066400000000000000000000013561475767661000207170ustar00rootroot00000000000000# 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-5.2/programs/_plutorun/_plutorun.in000077500000000000000000000060241475767661000216360ustar00rootroot00000000000000#!@@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=@@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-5.2/programs/_plutorun/ipsec-_plutorun.8.xml000066400000000000000000000043501475767661000232740ustar00rootroot00000000000000 IPSEC-_PLUTORUN 8 24 Apr 2023 Libreswan @@IPSECVERSION@@ Executable programs ipsec-_plutorun internal script to (re)start pluto on old SYSV initscript systems DESCRIPTION _plutorun is called by the ipsec initscript 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, 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 AUTHOR PaulWouters libreswan-5.2/programs/_stackmanager/000077500000000000000000000000001475767661000200225ustar00rootroot00000000000000libreswan-5.2/programs/_stackmanager/Makefile000066400000000000000000000013551475767661000214660ustar00rootroot00000000000000# 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-5.2/programs/_stackmanager/_stackmanager.in000066400000000000000000000157431475767661000231630ustar00rootroot00000000000000#!@@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:-@@IPSEC_CONF@@}" PATH=@@SBINDIR@@:${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-5.2/programs/_stackmanager/ipsec-_stackmanager.8.xml000066400000000000000000000054201475767661000246130ustar00rootroot00000000000000 IPSEC-_STACKMANAGER 8 06 May 2019 Libreswan @@IPSECVERSION@@ Executable programs ipsec-_stackmanager internal script to bring up kernel components for Libreswan ipsec _stackmanager start 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. SEE ALSO ip8, ipsec.conf5, ipsec8, 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. AUTHOR PaulWouters libreswan-5.2/programs/_unbound-hook/000077500000000000000000000000001475767661000177725ustar00rootroot00000000000000libreswan-5.2/programs/_unbound-hook/Makefile000066400000000000000000000014261475767661000214350ustar00rootroot00000000000000# 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 PROGRAM_MANPAGE = ifdef top_srcdir include $(top_srcdir)/mk/program.mk else include ../../mk/program.mk endif programs: ${PROGRAM} libreswan-5.2/programs/_unbound-hook/_unbound-hook.in000077500000000000000000000033341475767661000230770ustar00rootroot00000000000000#!@@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 "ignoring 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-5.2/programs/_updown.bsd/000077500000000000000000000000001475767661000174455ustar00rootroot00000000000000libreswan-5.2/programs/_updown.bsd/Makefile000066400000000000000000000014141475767661000211050ustar00rootroot00000000000000# 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-5.2/programs/_updown.bsd/_updown.bsd.in000066400000000000000000000164411475767661000222250ustar00rootroot00000000000000#! /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 # standardize PATH, and export it for everything else's benefit; # should config.mk generate this? NSS_BINDIR="${NSS_BINDIR:-@@NSS_BINDIR@@}" IPSEC_SBINDIR="${IPSEC_SBINDIR:-@@SBINDIR@@}" PATH="${NSS_BINDIR}:${PATH#${NSS_BINDIR}:}" PATH="${IPSEC_SBINDIR}:${PATH#${IPSEC_SBINDIR}:}" export PATH 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-5.2/programs/_updown.bsd/ipsec-_updown.bsd.8.xml000066400000000000000000000035741475767661000236710ustar00rootroot00000000000000 _UPDOWN 8 25 Apr 2002 Libreswan @@IPSECVERSION@@ Executable programs ipsec-_updown.bsd 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. AUTHOR PaulWouters libreswan-5.2/programs/_updown.xfrm/000077500000000000000000000000001475767661000176515ustar00rootroot00000000000000libreswan-5.2/programs/_updown.xfrm/Makefile000066400000000000000000000014151475767661000213120ustar00rootroot00000000000000# 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-5.2/programs/_updown.xfrm/_updown.xfrm.in000066400000000000000000000776351475767661000226510ustar00rootroot00000000000000#!@@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-2024 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 # whether 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_CLIENT_FAMILY # is the child (client) family type, "ipv4" or "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 host 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_XFRMI_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_IFACE=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 @@SYSCONFDIR@@/sysconfig/pluto_updown ]; then . @@SYSCONFDIR@@/sysconfig/pluto_updown # deb based systems elif [ -f @@SYSCONFDIR@@/default/pluto_updown ]; then . @@SYSCONFDIR@@/default/pluto_updown fi BACKUP_RESOLV_CONF=@@RUNDIR@@/libreswan-resolv-conf-backup ETC_RESOLV_CONF=@@SYSCONFDIR@@/resolv.conf case "${PLUTO_CONN_ADDRFAMILY}" in ipv4) HOST_FAMILY=4 HOST_MAX_CIDR=32 HOST_SCOPE=50 # Use scope 50 to verify ip was added by addsource() ;; ipv6) HOST_FAMILY=6 HOST_MAX_CIDR=128 HOST_SCOPE=global ;; *) echo "unknown address family \"${PLUTO_CONN_ADDRFAMILY}\"" >&2 exit 1 ;; esac export HOST_FAMILY HOST_MAX_CIDR HOST_SCOPE case "${PLUTO_CLIENT_FAMILY}" 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_CLIENT_FAMILY}\"" >&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 grep -q Libreswan "${ETC_RESOLV_CONF}"; then echo "Current resolv.conf is generated by Libreswan, not creating a new backup" else rm -f -- "${BACKUP_RESOLV_CONF}" cp -- "${ETC_RESOLV_CONF}" "${BACKUP_RESOLV_CONF}" fi 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 "${PLUTO_PEER_DOMAIN_INFO} ${new_search}" | 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 # XFRMi interface IPs are managed in Pluto if [ "${PLUTO_XFRMI_ROUTE}" = "yes" ]; 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}" 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 # XFRMi interface IPs are managed in Pluto if [ "${PLUTO_XFRMI_ROUTE}" = "yes" ]; 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}" 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: File exists'*|'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 # Only use PLUTO_NEXT_HOP in routing if address families agree if [ "${FAMILY}" = "${HOST_FAMILY}" ]; then # 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 but one is needed for ESP if [ -n "${PLUTO_XFRMI_ROUTE}" ]; then esp_nexthop="via ${PLUTO_NEXT_HOP} " else parms2="via ${PLUTO_NEXT_HOP}" fi fi 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 ::/1 | \ 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 -${HOST_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} ::/1 ${parms2} && \ ip -${FAMILY} route ${cmd} 8000::/1 ${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 -${HOST_FAMILY} route ${cmd} ${PLUTO_PEER}/${HOST_MAX_CIDR} ${PLUTO_METRIC:+ metric ${PLUTO_METRIC}} ${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 -${HOST_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() { USE_IPTABLES=@@USE_IPTABLES@@ USE_NFTABLES=@@USE_NFTABLES@@ if [ "${USE_NFTABLES}" = true ]; then FIREWALL=nftables elif [ "${USE_IPTABLES}" = true ]; then FIREWALL=iptables else FIREWALL= fi } add_nflog_nftables_conn() { nft -f - </dev/null | wc -l) if [ ${t} -gt 2 ]; then # a table with 2 lines is an empty table c=$(nft -a list chain inet ${table} ${chain} 2>/dev/null | wc -l) if [ ${c} -gt 5 ]; then # 5 or less no rules in it. h=$(nft -a list chain inet ${table} ${chain} | grep "${rulerexp}" | sed -e 's/.*handle\s*//g') for i in ${h}; do nft delete rule inet ${table} ${chain} handle ${i} done fi fi # the chain will live. delete the chain here or in ipsec.in at the end? } nftables_delete_table() { local table=$1 t=$(nft list table inet $table 2>/dev/null | wc -l) [ ${t} -eq 2 ] && nft delete table inet ${table} } nftables_delete_chain() { local table=$1 local chain=$2 t=$(nft list table inet ${table} 2>/dev/null | wc -l) if [ ${t} -gt 2 ]; then c=$(nft list chain inet ${table} ${chain} 2>/dev/null | wc -l) if [ ${c} -eq 5 ]; then nft delete chain inet ${table} ${chain} fi fi } addnflog() { firewall_cmd if [ "${FIREWALL}" = "nftables" -a -n "${NFLOG}" ]; then add_nflog_nftables_conn elif [ "${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}" = "nftables" -a -n "${NFLOG}" ]; then # note the 3rd argument. regexp should be identical to what is used in nft add rule nftables_delete_rule ipsec-log input "ipsec in reqid ${PLUTO_SA_REQID} ip saddr ${PLUTO_PEER_CLIENT} ip daddr ${PLUTO_MY_CLIENT_NET}" nftables_delete_rule ipsec-log output "ipsec out reqid ${PLUTO_SA_REQID} ip saddr ${PLUTO_MY_CLIENT} ip daddr ${PLUTO_PEER_CLIENT}" nftables_delete_chain ipsec-log input nftables_delete_chain ipsec-log output nftables_delete_table ipsec-log elif [ "${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-shared=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 # add_nftables_cat() { # this use reqid. And assume reqid is generated per conn. If you hardcode and have # multiple connections things could get mixed up. nft -f - <&2 exit 1 ;; esac libreswan-5.2/programs/_updown.xfrm/ipsec-_updown.xfrm.8.xml000066400000000000000000000036471475767661000243020ustar00rootroot00000000000000 IPSEC-_UPDOWN 8 25 February 2008 Libreswan @@IPSECVERSION@@ Executable programs ipsec-_updown.xfrm 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. 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. Update for <https://libreswan.org/> by Paul Wouters. AUTHOR PaulWouters libreswan-5.2/programs/_updown/000077500000000000000000000000001475767661000166765ustar00rootroot00000000000000libreswan-5.2/programs/_updown/Makefile000066400000000000000000000014021475767661000203330ustar00rootroot00000000000000# 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-5.2/programs/_updown/_updown.in000066400000000000000000000075131475767661000207070ustar00rootroot00000000000000#!@@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-5.2/programs/_updown/ipsec-_updown.8.xml000066400000000000000000000153511475767661000223470ustar00rootroot00000000000000 IPSEC-_UPDOWN 8 28 Oct 2006 Libreswan @@IPSECVERSION@@ Executable programs ipsec-_updown 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. AUTHOR PaulWouters libreswan-5.2/programs/addconn/000077500000000000000000000000001475767661000166315ustar00rootroot00000000000000libreswan-5.2/programs/addconn/Makefile000066400000000000000000000017251475767661000202760ustar00rootroot00000000000000# 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-5.2/programs/addconn/addconn.c000066400000000000000000000415551475767661000204150ustar00rootroot00000000000000/* * 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 "sparse_names.h" #include "ipsecconf/parser-controls.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 #include "optarg.h" /* * 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->end[LEFT_END], &conn->end[RIGHT_END], verbose_rc_flags, logger); resolve_default_route(&conn->end[RIGHT_END], &conn->end[LEFT_END], 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(sysinfo); 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); } enum opt { OPT_EOF = -1, OPT_HELP = 'h', OPT_CONFIG = 256, OPT_VERBOSE, OPT_DEBUG, OPT_AUTOALL, OPT_LISTALL, OPT_LISTADD, OPT_LISTROUTE, OPT_LISTSTART, OPT_LISTIGNORE, OPT_VARPREFIX, OPT_CTLSOCKET, OPT_CONFIGSETUP, OPT_LISTSTACK, OPT_CHECKCONFIG, OPT_NOEXPORT, /* obsoleted, eat and ignore for compatibility */ OPT_DEFAULTROUTE, OPT_DEFAULTROUTENEXTHOP, }; const struct option optarg_options[] = { { "config", required_argument, NULL, OPT_CONFIG, }, { "debug", no_argument, NULL, OPT_DEBUG, }, { "verbose", no_argument, NULL, OPT_VERBOSE, }, { "autoall", no_argument, NULL, OPT_AUTOALL, }, { "addall", no_argument, NULL, OPT_AUTOALL, }, /* alias, backwards compat */ { "listall", no_argument, NULL, OPT_LISTALL, }, { "listadd", no_argument, NULL, OPT_LISTADD, }, { "listroute", no_argument, NULL, OPT_LISTROUTE, }, { "liststart", no_argument, NULL, OPT_LISTSTART, }, { "listignore", no_argument, NULL, OPT_LISTIGNORE, }, { "varprefix", required_argument, NULL, OPT_VARPREFIX, }, { "ctlsocket", required_argument, NULL, OPT_CTLSOCKET, }, { "ctlbase", required_argument, NULL, OPT_CTLSOCKET, }, /* backwards compatibility */ { "configsetup", no_argument, NULL, OPT_CONFIGSETUP, }, { "liststack", no_argument, NULL, OPT_LISTSTACK, }, { "checkconfig", no_argument, NULL, OPT_CHECKCONFIG, }, { "noexport", no_argument, NULL, OPT_NOEXPORT, }, { "help", no_argument, NULL, OPT_HELP, }, /* obsoleted, eat and ignore for compatibility */ {"defaultroute", required_argument, NULL, OPT_DEFAULTROUTE, }, {"defaultroutenexthop", required_argument, NULL, OPT_DEFAULTROUTENEXTHOP, }, { 0, 0, 0, 0 } }; int main(int argc, char *argv[]) { struct logger *logger = tool_logger(argc, argv); 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; const char *configfile = NULL; const char *varprefix = ""; int exit_status = 0; const char *ctlsocket = DEFAULT_CTL_SOCKET; #if 0 /* efence settings */ extern int EF_PROTECT_BELOW; extern int EF_PROTECT_FREE; EF_PROTECT_BELOW = 1; EF_PROTECT_FREE = 1; #endif enum opt opt; while ((opt = getopt_long(argc, argv, "", optarg_options, 0)) != EOF) { switch (opt) { case OPT_HELP: /* usage: */ usage(); break; case OPT_AUTOALL: autoall = true; break; case OPT_VERBOSE: optarg_verbose(LEMPTY); break; case OPT_DEBUG: optarg_debug(/*enable*/true); break; case OPT_CONFIGSETUP: configsetup = true; break; case OPT_CHECKCONFIG: checkconfig = true; break; case OPT_NOEXPORT: export = ""; break; case OPT_CONFIG: configfile = optarg; break; case OPT_CTLSOCKET: ctlsocket = optarg; break; case OPT_LISTADD: listadd = true; dolist = true; break; case OPT_LISTROUTE: listroute = true; dolist = true; break; case OPT_LISTSTART: liststart = true; dolist = true; break; case OPT_LISTSTACK: liststack = true; dolist = true; break; case OPT_LISTIGNORE: listignore = true; dolist = true; break; case OPT_LISTALL: listall = true; dolist = true; break; case OPT_VARPREFIX: varprefix = optarg; break; case OPT_DEFAULTROUTE: case OPT_DEFAULTROUTENEXTHOP: fprintf(stderr, "Warning: options --defaultroute and --defaultroutenexthop are obsolete and were ignored\n"); break; default: usage(); } } /* if nothing to add, then complain */ if (optind == argc && !autoall && !dolist && !configsetup && !checkconfig) usage(); /* some variables depend on verbose */ lex_verbosity = verbose; yydebug = (verbose >= 4); if (configfile == NULL) { configfile = IPSEC_CONF; } if (verbose > 0) { printf("opening file: %s\n", configfile); } struct starter_config *cfg = confread_load(configfile, configsetup, logger); if (cfg == NULL) { llog(RC_LOG, logger, "cannot load config file '%s'", configfile); exit(3); } if (checkconfig) { confread_free(cfg); exit(0); } #ifdef USE_SECCOMP switch (cfg->values[KBF_SECCOMP].option) { 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->values[KBF_SECCOMP].option); } #endif #ifdef USE_DNSSEC unbound_sync_init(cfg->values[KBF_DO_DNSSEC].option, cfg->values[KSF_PLUTO_DNSSEC_ROOTKEY_FILE].string, cfg->values[KSF_PLUTO_DNSSEC_ANCHORS].string, 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(" Step #1: Loading auto=add, auto=keep, auto=route, auto=up and auto=start connections\n"); for (struct starter_conn *conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) { enum autostart autostart = conn->values[KNCF_AUTO].option; switch (autostart) { case AUTOSTART_UNSET: case AUTOSTART_IGNORE: break; case AUTOSTART_ADD: case AUTOSTART_ROUTE: case AUTOSTART_ONDEMAND: case AUTOSTART_KEEP: case AUTOSTART_UP: case AUTOSTART_START: if (verbose > 0) printf(" %s\n", conn->name); resolve_default_routes(conn, logger); starter_whack_add_conn(ctlsocket, conn, logger); break; } } /* * We loaded all connections. Now tell pluto to * listen, then route the conns and resolve default * route. * * Any connections that orient and have +ROUTE will be * routed. */ if (verbose > 0) printf(" Step #2: Listening which will then orient, route, up connections\n"); starter_whack_listen(ctlsocket, logger); 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 */ struct starter_conn *conn = NULL; for (conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) { if (streq(conn->name, connname)) { break; } } 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->values[KSCF_CONNALIAS].string)) { break; } } } if (conn == NULL) { /* we found neither name nor alias */ exit_status += RC_UNKNOWN_NAME; /* cause non-zero exit code */ fprintf(stderr, "conn '%s': not found (tried aliases)\n", connname); continue; } /* found name or alias */ if (conn->state == STATE_ADDED) { fprintf(stderr, "\n%s%s%sconn %s already added\n", p1, p2, p3, conn->name); continue; } if (conn->state == STATE_FAILED) { fprintf(stderr, "\n%s%s%sconn %s did not load properly\n", p1, p2, p3, conn->name); continue; } /* * Scrub AUTOSTART; conns will need to be * started manually. */ enum autostart autostart = conn->values[KNCF_AUTO].option; if (autostart != AUTOSTART_UNSET && autostart != AUTOSTART_ADD) { if (verbose) { name_buf nb; printf(" overiding auto=%s with auto=add\n", str_sparse(&autostart_names, autostart, &nb)); } conn->values[KNCF_AUTO].option = AUTOSTART_ADD; } resolve_default_routes(conn, logger); exit_status = starter_whack_add_conn(ctlsocket, conn, logger); conn->state = STATE_ADDED; } } if (listall) { if (verbose > 0) printf("listing all conns\n"); for (struct starter_conn *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 (struct starter_conn *conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) { enum autostart autostart = conn->values[KNCF_AUTO].option; if (autostart == AUTOSTART_ADD) printf("%s ", conn->name); } } if (listroute) { if (verbose > 0) printf("listing all conns marked as auto=route and auto=up\n"); /* * list all conns marked as auto=route or start or * better */ for (struct starter_conn *conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) { enum autostart autostart = conn->values[KNCF_AUTO].option; if (autostart == AUTOSTART_UP || autostart == AUTOSTART_START || autostart == AUTOSTART_ROUTE || autostart == AUTOSTART_ONDEMAND) printf("%s ", conn->name); } } if (liststart && !listroute) { if (verbose > 0) printf("listing all conns marked as auto=up\n"); /* list all conns marked as auto=up */ for (struct starter_conn *conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) { enum autostart autostart = conn->values[KNCF_AUTO].option; if (autostart == AUTOSTART_UP || autostart == AUTOSTART_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=up */ for (struct starter_conn *conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) { enum autostart autostart = conn->values[KNCF_AUTO].option; if (autostart == AUTOSTART_IGNORE || autostart == AUTOSTART_UNSET) 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->values[kd->field].string) { printf("%s\n", cfg->values[kd->field].string); } 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_host: if (cfg->values[kd->field].string) { printf("%s %s%s='%s'\n", export, varprefix, safe_kwname, cfg->values[kd->field].string); } break; case kt_bool: printf("%s %s%s='%s'\n", export, varprefix, safe_kwname, bool_str(cfg->values[kd->field].option)); break; case kt_obsolete: break; default: if (cfg->values[kd->field].option || cfg->values[kd->field].set) { printf("%s %s%s='%jd'\n", export, varprefix, safe_kwname, cfg->values[kd->field].option); } break; } free(safe_kwname); } confread_free(cfg); exit(0); } confread_free(cfg); #ifdef USE_DNSSEC unbound_ctx_free(); #endif /* * Only RC_ codes between RC_EXIT_FLOOR (RC_DUPNAME) and * RC_EXIT_ROOF (RC_NEW_V1_STATE) are errors Some starter code * above can also return -1 which is not a valid RC_ code */ if (exit_status > 0 && (exit_status < RC_EXIT_FLOOR || exit_status >= RC_EXIT_ROOF)) exit_status = 0; exit(exit_status); } libreswan-5.2/programs/addconn/ipsec-addconn.8.xml000066400000000000000000000151361475767661000222360ustar00rootroot00000000000000 IPSEC-ADDCONN 8 24 Apr 2023 Libreswan @@IPSECVERSION@@ Executable programs ipsec-addconn load a given policy into the pluto IKE daemon ipsec addconn --configsetup --config @@IPSEC_CONF@@ --ctlsocket @@RUNDIR@@/pluto.ctl --verbose --noexport --warningsfatal ipsec addconn --liststack --config @@IPSEC_CONF@@ --ctlsocket @@RUNDIR@@/pluto.ctl --verbose --noexport --warningsfatal ipsec addconn --checkconfig --config @@IPSEC_CONF@@ --ctlsocket @@RUNDIR@@/pluto.ctl --verbose --warningsfatal ipsec addconn --autoall --config @@IPSEC_CONF@@ --ctlsocket @@RUNDIR@@/pluto.ctl --verbose --warningsfatal ipsec addconn --config @@IPSEC_CONF@@ --ctlsocket @@RUNDIR@@/pluto.ctl --verbose --warningsfatal connection connection ... ipsec addconn --config @@IPSEC_CONF@@ --ctlsocket @@RUNDIR@@/pluto.ctl --listadd --listall --listignore --listroute --liststart --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 is specified, all connections that include the configuration option are processed as follows: the connection is loaded the connection is loaded and routed the connection is loaded, routed, marked as needing to stay up, and initiated If the connection is already loaded then it is first removed. When one or more connections are specified, those connections are loaded. Any in the configuration is ignored. When 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 is specified. When 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 or 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 AUTHOR PaulWouters libreswan-5.2/programs/algparse/000077500000000000000000000000001475767661000170215ustar00rootroot00000000000000libreswan-5.2/programs/algparse/Makefile000066400000000000000000000017161475767661000204660ustar00rootroot00000000000000# 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. 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-5.2/programs/algparse/algparse.c000066400000000000000000000464511475767661000207750ustar00rootroot00000000000000#include #include #include "lswlog.h" #include "lswtool.h" #include "lswalloc.h" #include "lswnss.h" #include "fips_mode.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 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, }; /* * 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; } } typedef void (protocol_t)(enum expect expected, const char *, struct logger *logger); struct protocol { const char *name; struct proposal_parser *(*parser)(const struct proposal_policy *policy); bool pfs_vs_dh; bool (*alg_is_ok)(const struct ike_alg *alg); }; const struct protocol ike_protocol = { "ike", ike_proposal_parser, .pfs_vs_dh = false, .alg_is_ok = ike_alg_is_ike, }; const struct protocol ah_protocol = { "ah", ah_proposal_parser, .pfs_vs_dh = true, .alg_is_ok = kernel_alg_is_ok, }; const struct protocol esp_protocol = { "esp", esp_proposal_parser, .pfs_vs_dh = true, .alg_is_ok = kernel_alg_is_ok, }; const struct protocol *protocols[] = { &ike_protocol, &ah_protocol, &esp_protocol, }; static void check(const struct protocol *protocol, enum expect expected, const char *algstr, struct logger *logger) { /* print the test */ printf("algparse "); if (impaired) { printf("-impair "); } 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'", protocol->name); } else { printf("'%s=%s'", protocol->name, algstr); } switch (expected) { case PASS: printf(" (expect SUCCESS)"); break; case FAIL: printf(" (expect ERROR)"); break; case COUNT: break; } printf("\n"); fflush(NULL); /* run the test */ struct proposal_policy policy = { .version = ike_version, .alg_is_ok = protocol->alg_is_ok, .pfs = pfs, .logger_rc_flags = ERROR_STREAM, .logger = logger, .check_pfs_vs_dh = protocol->pfs_vs_dh, .ignore_parser_errors = ignore_parser_errors, }; struct proposal_parser *parser = protocol->parser(&policy); struct proposals *proposals = proposals_from_str(parser, algstr); /* print the results */ 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", protocol->name, (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", protocol->name, (algstr == NULL ? "" : "="), (algstr == NULL ? "" : algstr)); } else if (expected == COUNT) { failures++; } } free_proposal_parser(&parser); fflush(NULL); } static void all(const char *algstr, struct logger *logger) { FOR_EACH_ELEMENT(protocolp, protocols) { const struct protocol *protocol = (*protocolp); check(protocol, COUNT, algstr, logger); } } static void test_proposal(const char *arg, struct logger *logger) { const char *eq = strchr(arg, '='); FOR_EACH_ELEMENT(protocolp, protocols) { const struct protocol *protocol = (*protocolp); if (streq(arg, protocol->name)) { check(protocol, COUNT, NULL, logger); return; } if (startswith(arg, protocol->name) && arg + strlen(protocol->name) == eq) { check(protocol, COUNT, eq + 1, logger); return; } } if (eq != NULL) { fprintf(stderr, "unrecognized PROTOCOL in '%s'", arg); exit(1); } all(arg, logger); } static void test_esp(struct logger *logger) { #define esp(EXPECTED, ALGSTR) check(&esp_protocol, EXPECTED, ALGSTR, logger) 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"); #undef esp } static void test_ah(struct logger *logger) { #define ah(EXPECTED, ALGSTR) check(&ah_protocol, EXPECTED, ALGSTR, logger) 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 */ #undef ah } static void test_ike(struct logger *logger) { #define ike(EXPECTED, ALGSTR) check(&ike_protocol, EXPECTED, ALGSTR, logger) 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 */ #undef ike } static void test(struct logger *logger) { test_esp(logger); test_ah(logger); test_ike(logger); } static void usage(void) { fprintf(stderr, "Usage:\n" "\n" " algparse [