diff --git a/docs/superpowers/plans/2026-07-20-obs-simpleimage-tarballs.md.tasks.json b/docs/superpowers/plans/2026-07-20-obs-simpleimage-tarballs.md.tasks.json index 73856c94..374ef9ce 100644 --- a/docs/superpowers/plans/2026-07-20-obs-simpleimage-tarballs.md.tasks.json +++ b/docs/superpowers/plans/2026-07-20-obs-simpleimage-tarballs.md.tasks.json @@ -4,44 +4,80 @@ { "id": 1, "subject": "Task 1: ssl3 variant subproject (reference variant)", - "status": "pending", + "status": "completed", "description": "**Goal:** Create root/ppg/staging/17/tarballs/ssl3/ — project.yaml, macros.yaml, and the percona-postgresql-tarball package (simpleimage + build-tarball.sh) — complete and shellcheck-clean.\n\n**Files:**\n- Create: root/ppg/staging/17/tarballs/ssl3/project.yaml\n- Create: root/ppg/staging/17/tarballs/ssl3/macros.yaml\n- Create: root/ppg/staging/17/tarballs/ssl3/percona-postgresql-tarball/obs/simpleimage\n- Create: root/ppg/staging/17/tarballs/ssl3/percona-postgresql-tarball/obs/build-tarball.sh\n\n**Acceptance Criteria:**\n- simpleimage uses only %!{...} macros defined in ancestor macros.yaml files (PG_MAJOR_VERSION, PG_VERSION, TARBALL_SSL_VARIANT, TARBALL_PYTHON_PKG)\n- All BuildRequires names verified against the published staging repo (dnf repoquery)\n- shellcheck --severity=error build-tarball.sh → no errors\n- build-tarball.sh contains no hardcoded PG major or python version (discovers at run time)\n\n**Verify:** shellcheck --severity=error root/ppg/staging/17/tarballs/ssl3/percona-postgresql-tarball/obs/build-tarball.sh && bash -n → exit 0\n\nFull step-by-step content (including the complete simpleimage recipe, POC modification list 4a-4e, and project.yaml) is in the plan document Task 1.\n\n```json:metadata\n{\"files\": [\"root/ppg/staging/17/tarballs/ssl3/project.yaml\", \"root/ppg/staging/17/tarballs/ssl3/macros.yaml\", \"root/ppg/staging/17/tarballs/ssl3/percona-postgresql-tarball/obs/simpleimage\", \"root/ppg/staging/17/tarballs/ssl3/percona-postgresql-tarball/obs/build-tarball.sh\"], \"verifyCommand\": \"shellcheck --severity=error root/ppg/staging/17/tarballs/ssl3/percona-postgresql-tarball/obs/build-tarball.sh\", \"acceptanceCriteria\": [\"macros resolve from ancestor macros.yaml\", \"BuildRequires names verified vs published repo\", \"shellcheck severity=error clean\", \"no hardcoded PG/python versions\"], \"modelTier\": \"standard\"}\n```" }, { "id": 2, "subject": "Task 2: Local container validation of build-tarball.sh", - "status": "pending", - "blockedBy": [1], + "status": "completed", + "blockedBy": [ + 1 + ], "description": "**Goal:** Prove build-tarball.sh produces a correct tarball in a Rocky 9 container with the staging RPMs installed, before touching OBS. Iterate on the script until it passes.\n\n**Files:**\n- Modify (as needed): root/ppg/staging/17/tarballs/ssl3/percona-postgresql-tarball/obs/build-tarball.sh\n- Create: /tarball-test/run-local.sh (throwaway harness, NOT committed)\n\n**Acceptance Criteria:**\n- Script runs to completion inside rockylinux:9 with all BuildRequires packages installed\n- /.simpleimage.tar.gz produced; top-level entries are exactly the percona-* component dirs\n- Verification gate (section 15) passes: 0 unresolved libs, all smoke commands OK\n- Structure-diff vs official percona-postgresql-17.10-ssl3-linux-x86_64.tar.gz: no missing component dirs / bin,lib,share,include subdirs (haproxy absence accepted)\n\n**Verify:** bash run-local.sh && tar -tzf out/.simpleimage.tar.gz | awk -F/ '{print $1}' | sort -u → component dir list\n\nFull harness script and diff commands are in the plan document Task 2.\n\n```json:metadata\n{\"files\": [\"root/ppg/staging/17/tarballs/ssl3/percona-postgresql-tarball/obs/build-tarball.sh\"], \"verifyCommand\": \"bash run-local.sh (scratchpad harness)\", \"acceptanceCriteria\": [\"container run completes\", \"tarball top-level = percona-* dirs only\", \"ldd audit 0 unresolved + smoke commands OK\", \"structure-diff vs official reviewed\"], \"modelTier\": \"standard\"}\n```" }, { "id": 3, "subject": "Task 3: Replicate to ssl1.1 and ssl3.5 + copy-identity test", - "status": "pending", - "blockedBy": [2], + "status": "completed", + "blockedBy": [ + 2 + ], "description": "**Goal:** Create the ssl1.1 (Rocky 8) and ssl3.5 (Rocky 10) variant subprojects as byte-identical package copies with variant-specific macros.yaml/project.yaml, plus a pytest guarding the copies against divergence.\n\n**Files:**\n- Create: root/ppg/staging/17/tarballs/ssl1.1/{project.yaml,macros.yaml}\n- Create: root/ppg/staging/17/tarballs/ssl1.1/percona-postgresql-tarball/obs/{simpleimage,build-tarball.sh} (copies)\n- Create: root/ppg/staging/17/tarballs/ssl3.5/{project.yaml,macros.yaml}\n- Create: root/ppg/staging/17/tarballs/ssl3.5/percona-postgresql-tarball/obs/{simpleimage,build-tarball.sh} (copies)\n- Test: tests/test_tarball_variants.py\n\n**Acceptance Criteria:**\n- simpleimage and build-tarball.sh byte-identical across the three variant dirs (enforced by pytest)\n- ssl1.1 repo chain = staging RockyLinux_8 chain; ssl3.5 = RockyLinux_10 chain; archs [x86_64]; publish enabled\n- ssl3.5 macros.yaml sets TARBALL_PYTHON_PKG: python3\n- Rocky 10 openssl-libs confirmed 3.5.* (else STOP and ask user about variant naming)\n- black + pyright pass; pytest tests/test_tarball_variants.py passes\n\n**Verify:** venv/bin/pytest tests/test_tarball_variants.py -v → 2 passed\n\nFull project.yaml contents and test code are in the plan document Task 3.\n\n```json:metadata\n{\"files\": [\"root/ppg/staging/17/tarballs/ssl1.1/project.yaml\", \"root/ppg/staging/17/tarballs/ssl1.1/macros.yaml\", \"root/ppg/staging/17/tarballs/ssl3.5/project.yaml\", \"root/ppg/staging/17/tarballs/ssl3.5/macros.yaml\", \"tests/test_tarball_variants.py\"], \"verifyCommand\": \"venv/bin/pytest tests/test_tarball_variants.py -v\", \"acceptanceCriteria\": [\"byte-identical package files across variants\", \"correct repo chains per base\", \"TARBALL_PYTHON_PKG python3 on ssl3.5\", \"Rocky 10 openssl 3.5 confirmed\"], \"modelTier\": \"standard\"}\n```" }, { "id": 4, "subject": "Task 4: Sync tooling dry-run verification", - "status": "pending", - "blockedBy": [3], + "status": "completed", + "blockedBy": [ + 3 + ], "description": "**Goal:** Confirm percona-obs resolves and syncs the new tarball subprojects without code changes (spec says none expected — verify, don't assume).\n\n**Files:**\n- None expected; modify percona_obs/*.py only if the dry-run exposes a container-specific assumption.\n\n**Acceptance Criteria:**\n- sync push --dry-run for each of the three variant projects resolves the target, expands macros, reports files to upload (simpleimage, build-tarball.sh) and project meta/prjconf — no tracebacks\n- Dry-run output shows Type: simpleimage in prjconf and expanded Version: 17.10--linux\n\n**Verify:** venv/bin/python -m percona_obs -P isv sync push --dry-run ppg:staging:17:tarballs:ssl3 percona-postgresql-tarball → dry-run report, exit 0\n\nSTANDING RULE: -P isv is production — NEVER any write op without --dry-run.\n\n```json:metadata\n{\"files\": [], \"verifyCommand\": \"venv/bin/python -m percona_obs -P isv sync push --dry-run ppg:staging:17:tarballs:ssl3 percona-postgresql-tarball\", \"acceptanceCriteria\": [\"all three variants dry-run clean\", \"prjconf Type: simpleimage visible\", \"macro-expanded Version visible\"], \"modelTier\": \"standard\"}\n```" }, { "id": 5, "subject": "Task 5: Document the tarballs subprojects", - "status": "pending", - "blockedBy": [3], + "status": "completed", + "blockedBy": [ + 3 + ], "description": "**Goal:** Record the tarballs layout and build model in root/README.md.\n\n**Files:**\n- Modify: root/README.md\n\n**Acceptance Criteria:**\n- root/README.md explains: one subproject per SSL variant, base-distro mapping, byte-identical package files with variant macros.yaml, #!NoTarBall self-tar model, publish-enabled artifact location\n\n**Verify:** grep -A5 'tarballs' root/README.md → shows the new subsection\n\nFull markdown content is in the plan document Task 5.\n\n```json:metadata\n{\"files\": [\"root/README.md\"], \"verifyCommand\": \"grep -A5 tarballs root/README.md\", \"acceptanceCriteria\": [\"tarballs subsection present with variant table and build model\"], \"modelTier\": \"mechanical\"}\n```" }, { "id": 6, "subject": "Task 6: PR build in production OBS + acceptance test", "status": "pending", - "blockedBy": [4, 5], + "blockedBy": [ + 4, + 5, + 7 + ], "description": "**Goal:** Prove the end-to-end deliverable: obs-pr-sync builds all three variants in a production PR project, and the ssl3 artifact passes the acceptance test on a foreign distro.\n\n**USER-ORDERED GATE — NON-SKIPPABLE.** This task was requested by the user in the current conversation. It MUST NOT be closed by walking around it, by declaring it \"verified inline\", or by substituting a cheaper check. Close only after every item in acceptanceCriteria has been re-validated independently, with output captured.\n\n**Files:**\n- None (operational; fixes loop back into Tasks 1–3 files if builds fail)\n\n**Acceptance Criteria:**\n- User has opened the PR (manual — do NOT git push or gh pr create without explicit go-ahead)\n- obs-pr-sync created the PR project incl. all three tarballs:ssl* subprojects; build status succeeded for percona-postgresql-tarball in all three\n- Artifact downloaded from the PR project\n- Acceptance on ubuntu:24.04 (ssl3): untar to /opt/pgdistro, copy percona-{python3,perl,tcl} to /opt, as non-root: initdb OK, pg_ctl start OK, psql SELECT version() shows Percona 17.10, CREATE EXTENSION pg_tde OK, patronictl version prints\n- Structure-diff vs official 17.10 ssl3 tarball reviewed; divergences accepted explicitly or fixed\n\n**Verify:** venv/bin/python -m percona_obs -A https://api.opensuse.org -R isv:percona:PR:pr- build status ppg:staging:17:tarballs:ssl3 → succeeded; then the containerized acceptance commands (plan Task 6 Step 4), each with captured output\n\n```json:metadata\n{\"files\": [], \"verifyCommand\": \"build status per variant + containerized acceptance script (plan Task 6 Step 4)\", \"acceptanceCriteria\": [\"PR opened by user\", \"all three variants build succeeded in PR project\", \"artifact downloaded\", \"ubuntu:24.04 acceptance: initdb/pg_ctl/psql/pg_tde/patronictl all OK with captured output\", \"structure-diff reviewed\"], \"userGate\": true, \"tags\": [\"user-gate\"], \"gateScope\": \"task\", \"requireEvidenceTokens\": [[\"succeeded\", \"build status\"], [\"initdb\", \"pg_ctl\", \"CREATE EXTENSION\"]], \"modelTier\": \"standard\"}\n```" + }, + { + "id": 7, + "subject": "Task 7: add python3-jmespath + python3-s3transfer (boto3 deps)", + "status": "completed", + "description": "**Goal:** Add python3-jmespath and python3-s3transfer packages to root/ppg/common/deps (+ staging:17 _aggregate stubs), mirroring python3-boto3/botocore, so python3.12-boto3 and percona-patroni-aws resolve in the tarball build chroots.\n\n**Files:**\n- Create: root/ppg/common/deps/python3-jmespath/{obs/_service,rpm/python3-jmespath.spec}\n- Create: root/ppg/common/deps/python3-s3transfer/{obs/_service,rpm/python3-s3transfer.spec}\n- Create: root/ppg/staging/17/python3-jmespath/obs/_aggregate\n- Create: root/ppg/staging/17/python3-s3transfer/obs/_aggregate\n\n**Acceptance Criteria:**\n- Specs mirror boto3/botocore conventions (python3.12 stack, noarch, requires_exclude, correct changelog day-of-week)\n- s3transfer version satisfies published boto3 constraint (evidence recorded)\n- sync push --dry-run clean for all four packages\n\n**Verify:** venv/bin/python -m percona_obs -P isv sync push --dry-run ppg:common:deps python3-jmespath (etc.) → exit 0\n\nUser decision 2026-07-21: add the packages on this branch (option A) rather than dropping percona-patroni-aws.\n\n```json:metadata\n{\"files\": [\"root/ppg/common/deps/python3-jmespath/\", \"root/ppg/common/deps/python3-s3transfer/\", \"root/ppg/staging/17/python3-jmespath/\", \"root/ppg/staging/17/python3-s3transfer/\"], \"verifyCommand\": \"percona-obs -P isv sync push --dry-run (all four)\", \"acceptanceCriteria\": [\"specs mirror boto3 conventions\", \"version constraints satisfied with evidence\", \"dry-runs clean\"], \"modelTier\": \"standard\"}\n```" + }, + { + "id": 8, + "subject": "Task 8: restructure tarballs to single subproject with ssl repos", + "status": "completed", + "description": "**Goal:** Restructure from three SSL-variant subprojects to ONE ppg:staging:17:tarballs subproject with ssl1.1/ssl3/ssl3.5 repositories (user decision 2026-07-21).\n\n**Files:**\n- Create: root/ppg/staging/17/tarballs/project.yaml (3 repos, merged prjconf with %if \"%_repository\" blocks)\n- Create: root/ppg/staging/17/tarballs/percona-postgresql-tarball/obs/{simpleimage,build-tarball.sh} (single copies)\n- Delete: ssl1.1/ ssl3/ ssl3.5/ subtrees, tests/test_tarball_variants.py\n- Modify: root/README.md\n\n**Acceptance Criteria:**\n- Path chains carried verbatim; publish on all 3 repos; Type: simpleimage global\n- simpleimage python BuildRequires via %if %_repository conditional; Version metadata-only\n- Artifact self-named by script into /usr/src/packages/OTHER with exact official name\n- Variant detection EL-major-based (openssl impossible: Rocky 9.8 ships openssl 3.5.5)\n- Container re-validation exit 0; pytest/pyright/black clean; isv dry-run clean\n\n**Verify:** container run produced /usr/src/packages/OTHER/percona-postgresql-17.10-ssl3-linux-x86_64.tar.gz; venv/bin/pytest tests/ -q -> 98 passed\n\nCommits: f65562a (restructure) + b0878e8 (README detection sentence). Spec+quality reviewed, approved.\n\n```json:metadata\n{\"files\": [\"root/ppg/staging/17/tarballs/project.yaml\", \"root/ppg/staging/17/tarballs/percona-postgresql-tarball/obs/simpleimage\", \"root/ppg/staging/17/tarballs/percona-postgresql-tarball/obs/build-tarball.sh\", \"root/README.md\"], \"verifyCommand\": \"venv/bin/pytest tests/ -q && venv/bin/python -m percona_obs -P isv sync push --dry-run ppg:staging:17:tarballs percona-postgresql-tarball\", \"acceptanceCriteria\": [\"single subproject with 3 repos\", \"exact official artifact naming\", \"EL-major variant detection\", \"all validations green\"], \"modelTier\": \"standard\"}\n```" + }, + { + "id": 9, + "subject": "Task 9: per-variant OpenSSL-ABI gate + Net::SSLeay prune", + "status": "completed", + "description": "**Goal:** Enforce each ssl variant's host-OpenSSL promise in the section-15 gate (version-NEEDS audit vs per-variant allowed nodes; /opt/percona-python3 excluded as bundled-OpenSSL domain) and prune Net::SSLeay for official-tarball parity.\n\n**Files:**\n- Modify: root/ppg/staging/17/tarballs/percona-postgresql-tarball/obs/build-tarball.sh\n\n**Acceptance Criteria:**\n- Audit parses version NEEDS only, attributed to libssl/libcrypto sonames\n- ssl3 policy strict OPENSSL_3.0.* (EL9 intentionally red until Ubuntu rebase)\n- Negative test proves audit bites; python exclusion load-bearing; SSLeay fully pruned\n\n**Verify:** container run fails with exactly one violation (pgcrypto OPENSSL_3.4.0), zero SSLeay lines\n\nCommit cd4f043. Reviewed and approved. Findings: EL9/Rocky 9.8 pgcrypto needs OPENSSL_3.4.0 (official tarball needs 3.0.0 only) -> ssl3 rebases to Ubuntu 22.04 in task 10.\n\n```json:metadata\n{\"files\": [\"root/ppg/staging/17/tarballs/percona-postgresql-tarball/obs/build-tarball.sh\"], \"verifyCommand\": \"container acceptance run: single pgcrypto violation, 0 SSLeay lines\", \"acceptanceCriteria\": [\"needs-only parsing\", \"strict ssl3 policy\", \"negative test bites\", \"prune complete\"], \"modelTier\": \"standard\"}\n```" + }, + { + "id": 10, + "subject": "Task 10: rebase ssl3 onto Ubuntu 22.04 debs", + "status": "completed", + "description": "**Goal:** ssl3 variant consumes staging Ubuntu 22.04 debs (OpenSSL 3.0.2, glibc 2.35) via a new build-tarball-deb.sh + os-release dispatcher, restoring the OpenSSL 3.0 host promise that EL9/Rocky 9.8 broke (pgcrypto OPENSSL_3.4.0).\n\n**Files:**\n- Create: root/ppg/staging/17/tarballs/percona-postgresql-tarball/obs/build-tarball-deb.sh\n- Modify: obs/simpleimage (deb %if branch + dispatcher + binutils), obs/build-tarball.sh (EL9 FATAL, readelf assert, polish), project.yaml (ssl3 Ubuntu chain), root/README.md\n\n**Acceptance Criteria:**\n- ubuntu:22.04 container run: strict ssl3 SSL-ABI gate GREEN, exact artifact name, ten component dirs\n- readelf assert prevents vacuous gate; binutils in both BuildRequires branches\n- pytest/pyright/black clean; isv dry-run shows three package files\n\n**Verify:** container gate output green under OPENSSL_3.0.* policy; artifact percona-postgresql-17.10-ssl3-linux-x86_64.tar.gz\n\nCommits b3b2ef3, 4c598e4, 1069eea (+ spec 348e1c6). Spec+quality reviewed, approved.\n\n```json:metadata\n{\"files\": [\"root/ppg/staging/17/tarballs/percona-postgresql-tarball/obs/build-tarball-deb.sh\", \"root/ppg/staging/17/tarballs/percona-postgresql-tarball/obs/simpleimage\", \"root/ppg/staging/17/tarballs/percona-postgresql-tarball/obs/build-tarball.sh\", \"root/ppg/staging/17/tarballs/project.yaml\", \"root/README.md\"], \"verifyCommand\": \"ubuntu:22.04 container run with strict-green ssl3 gate\", \"acceptanceCriteria\": [\"gate green on Ubuntu\", \"exact artifact name\", \"readelf assert\", \"dry-run three files\"], \"modelTier\": \"standard\"}\n```" } ], - "lastUpdated": "2026-07-20" -} + "lastUpdated": "2026-07-21T18:20:00" +} \ No newline at end of file diff --git a/docs/superpowers/plans/2026-07-22-tarballs-ssl-portability.md b/docs/superpowers/plans/2026-07-22-tarballs-ssl-portability.md new file mode 100644 index 00000000..505d2147 --- /dev/null +++ b/docs/superpowers/plans/2026-07-22-tarballs-ssl-portability.md @@ -0,0 +1,98 @@ +# Tarballs SSL Portability Plan (post-acceptance round) + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers-extended-cc:subagent-driven-development or superpowers-extended-cc:executing-plans. Steps use checkbox (`- [ ]`) syntax. + +**Goal:** Make the OBS tarballs genuinely portable per their SSL-variant promises, based on the PR-145 acceptance-gate findings: two variants (ssl1.1 on EL8, ssl3 on EL9), a one-macro PostgreSQL patch, rebuilt krb5/libssh for EL8, and the cross-variant script fixes. + +**Context (findings driving this plan):** +- The acceptance gate failed 2 of 3 variants on foreign hosts. ssl3 (Ubuntu debs) is unfixable — PGDG deb layout is non-relocatable (`SHAREDIR=/usr/share/postgresql/17` hard-compiled; verified identical in PGDG's own debs). ssl1.1 (EL8) fails on stock 1.1 hosts because two bundled RH-prebuilt libs (`libk5crypto`, `libssh`) need the RH-only `OPENSSL_1_1_1b` symbol node. +- All PG-side EL8/EL9 binaries carry only stock OpenSSL nodes EXCEPT `pgcrypto.so` on ≥3.4 build bases: OpenSSL 3.4's headers remap the `EVP_MD_CTX_size()` macro to `EVP_MD_CTX_get_size_ex@OPENSSL_3.4.0`. One-macro patch → EL9-built ssl3 covers ALL OpenSSL 3.x hosts (glibc floor 2.34: includes Ubuntu 22.04/24.04, Debian 12). +- Official-tarball reference behaviors to replicate: krb5 with builtin crypto (no libcrypto dep); psql readline wrapper; no Net::SSLeay (done). +- Cross-variant acceptance findings: `postgres` wrapper must export `PYTHONHOME` (backend segfault in plpython3u otherwise); readline wrapper misses Debian multiarch path; `libunistring`/`libnghttp2`/`libidn2` must be bundled (sonames not universal); `/run/postgresql` socket dir is a host prerequisite (docs). + +**User decisions (already made):** +- ssl3 reverts to Rocky 9 RPMs + pgcrypto macro patch; strict `OPENSSL_3.0.*` gate stays. +- ssl3.5 is DROPPED (redundant: patched ssl3 serves every 3.x host with a lower glibc floor). +- Deb builder (`build-tarball-deb.sh` + dispatcher + deb BuildRequires branch) is REMOVED (history preserves it; rationale recorded in spec). +- ssl1.1 portability via rebuilt packages: krb5 with builtin crypto; libssh built against stock OpenSSL 1.1 headers (requires a build-only, UNPUBLISHED percona openssl-1.1 devel package). Runtime crypto stays host-provided everywhere; we never bundle/ship OpenSSL (EOL-ownership liability rejected). +- ssl1.1 gate pattern TIGHTENED to exactly `OPENSSL_1_1_0`/`OPENSSL_1_1_1` (rejects RH-only suffixed nodes at build time). + +--- + +### Task 11: pgcrypto OpenSSL-3.4 macro patch (staging percona-postgresql RPM) + +**Goal:** EL9-built `pgcrypto.so` references only `OPENSSL_3.0.0` nodes. + +**Files:** +- Create: `root/ppg/staging/17/percona-postgresql/rpm/.patch` +- Modify: `root/ppg/staging/17/percona-postgresql/rpm/*.spec` (Patch entry + %prep application, following the spec's existing patch conventions) + +**Acceptance Criteria:** +- [ ] Patch confines itself to `contrib/pgcrypto` OpenSSL usage: force the pre-3.4 expansion of `EVP_MD_CTX_size()` (e.g. `EVP_MD_get_size(EVP_MD_CTX_get0_md(ctx))`) so no `EVP_MD_CTX_get_size_ex` reference is emitted; behaviorally identical +- [ ] Local rebuild evidence (rocky9 container rpmbuild or OBS PR build): `readelf` on built pgcrypto.so → zero version needs beyond `OPENSSL_3.0.*` +- [ ] Patch header documents why + upstream-flag note (candidate for percona/postgres upstream) + +**Verify:** `readelf -V pgcrypto.so | grep OPENSSL_3.[1-9]` → empty on the EL9-built artifact. + +### Task 12: matrix revert — ssl3 to Rocky 9, drop ssl3.5, remove deb builder, script fixes + +**Goal:** Two-variant tree (ssl1.1, ssl3-on-EL9) with the acceptance-derived script fixes and tightened gate. + +**Files:** +- Modify: `root/ppg/staging/17/tarballs/project.yaml` (ssl3 → Rocky 9 chain [pre-4c598e4 block + `Binarytype: rpm` + any needed Prefers]; delete ssl3.5 repo + prjconf block; keep ssl1.1) +- Modify: `obs/simpleimage` (remove deb `%if` branch AND the ssl3.5 python conditional — python3.12 set unconditionally; `%build` = plain `exec bash -x .../build-tarball.sh`) +- Delete: `obs/build-tarball-deb.sh` +- Modify: `obs/build-tarball.sh`: + - EL mapping: 8→ssl1.1, 9→ssl3 (reachable again — restore active policy arm, drop the "unreachable" annotation), anything else FATAL (10 removed) + - SSL-ABI policy: ssl1.1 pattern tightened to `^OPENSSL_1_1_0$|^OPENSSL_1_1_1$` (grep -qE or two -qx checks); ssl3 stays `OPENSSL_3\.0\.[0-9]*` + - `postgres` wrapper: `export PYTHONHOME=/opt/percona-python3` (comment: embedded plpython3 has no wrapper env otherwise; acceptance-verified backend crash) + - psql wrapper: add `/lib/x86_64-linux-gnu/libreadline.so.8` (+ aarch64-safe generic pattern) to the host-readline search paths + - SYSTEM_LIBS_EXCLUDE: remove `libunistring`, `libnghttp2`, `libidn2` (get bundled; comment why — soname drift across distro generations, acceptance evidence) +- Modify: `root/README.md` + `docs/superpowers/specs/2026-07-20-obs-simpleimage-tarballs-design.md` (two-variant matrix, patched-pgcrypto note, deb-attempt rationale recorded, host prerequisites: `/run/postgresql`, tzdata, krb5 [pending Task 13 outcome]) + +**Acceptance Criteria:** +- [ ] Tree contains exactly ssl1.1 + ssl3 repos; no deb references anywhere outside git history and the spec's rejected-alternatives section +- [ ] shellcheck severity=error + bash -n clean; pytest/pyright/black green +- [ ] Container validation (EL9 provisioned image + Task 11's patched PG RPMs if available, else note): gate GREEN under strict ssl3 policy incl. pgcrypto +- [ ] isv dry-run clean (STANDING RULE: -P isv never without --dry-run) + +**Verify:** container run → artifact `percona-postgresql-17.10-ssl3-linux-x86_64.tar.gz`, both audits 0 findings. + +### Task 13: EL8 portability packages — krb5 (builtin crypto) + libssh (stock OpenSSL) + build-only openssl 1.1 + +**Goal:** ssl1.1 tarball loads on stock OpenSSL 1.1 hosts (Debian 11-class), no RH-only symbol needs. + +**Files (USER DECISION 2026-07-22: packages live in `ppg:common:deps`, RockyLinux_8 ONLY, with the SAME NAMES as the distro originals):** +- Create: `root/ppg/common/deps/krb5/` — krb5 rebuilt with `--with-crypto-impl=builtin` (no OpenSSL linkage at all; official-tarball parity). Same source-package/binary names as the distro (`krb5-libs` etc.); wins resolution via higher EVR (e.g. a `.percona` release suffix). `package.yaml` restricts builds to RockyLinux_8 only (repo-restriction convention already used in the tree). +- Create: `root/ppg/common/deps/libssh/` — libssh rebuilt so its OpenSSL needs are stock-only. PREFERRED approach: build with the **libgcrypt backend** (`-DWITH_GCRYPT=ON`) — no OpenSSL involvement, no extra package needed (note: libgcrypt then must stay host-provided; it is in SYSTEM_LIBS_EXCLUDE and universally present). FALLBACK if gcrypt backend proves unworkable: build against a stock OpenSSL 1.1 devel package — in that case create `root/ppg/common/deps/openssl11-build/` with a DISTINCT name (`percona-openssl11-devel` or similar — same-name shadowing of `openssl` in common:deps would leak into every EL8 staging build chroot and is NOT acceptable), devel-only, never bundled/published. +- Modify: `root/ppg/staging/17/tarballs/project.yaml` — ssl1.1 chain already includes `ppg:common:deps/RockyLinux_8`; verify our same-named packages win (EVR) and add `Prefer:` lines only if OBS still reports a choice. + +**Shadowing side effect to verify (not skip):** `ppg:staging:17`'s RockyLinux_8 repo chains `ppg:common:deps` too, so every EL8 staging build chroot will now resolve OUR krb5/libssh instead of Red Hat's. Consumers reference only stable krb5/libssh sonames+symbols, so produced RPMs should be identical in their requirements — but the implementer must verify at least one affected staging package (e.g. percona-postgresql EL8 buildinfo before/after via dry-run reasoning or PR build) and record the finding. If this side effect is deemed unwanted at review time, escalate to the user rather than silently switching to Prefer-scoped containment. + +**Acceptance Criteria:** +- [ ] Rebuilt libk5crypto: NO libcrypto dependency at all (readelf NEEDED) +- [ ] Rebuilt libssh: OpenSSL needs = stock nodes only +- [ ] openssl11 package never appears in any published repo nor inside the tarball (audit + publish flags) +- [ ] EL8 container validation: full build green under the TIGHTENED ssl1.1 gate; artifact loads `initdb`/`postgres` on a debian:11 container (spot pre-check before the full Task 14 battery) + +**Verify:** `readelf -d libk5crypto.so.3 | grep -i crypto` → no libcrypto NEEDED; gate output on EL8 build → 0 violations under the strict pattern. + +### Task 14: re-validation + PR round 2 + acceptance rerun (USER GATE — continues plan Task 6) + +> **USER-ORDERED GATE — NON-SKIPPABLE.** Close only with captured evidence for every criterion. + +**Steps:** local container validations (EL8 + EL9) → user pushes → PR-145 re-sync → watch both repos to `succeeded` (budget one resolution iteration for the new tarball-deps chain) → download artifacts → acceptance battery: +- ssl1.1 on **debian:11** (previously FAILED — must pass: initdb, server, psql via fixed wrapper, pg_tde, **pgcrypto digest**, plpython3u [PYTHONHOME via wrapper — no manual env], plperlu, pltclu, patronictl, patroni_aws [jmespath present in fresh artifact]) +- ssl3 on **ubuntu:22.04** AND **ubuntu:24.04** (the tier's real audience; pgcrypto digest on host OpenSSL 3.0 is the headline proof; libunistring bundling verified by loading on 24.04) +- structure-diffs vs official; document divergences + host prerequisites for release notes + +**Acceptance Criteria:** +- [ ] Both variants PASS their full battery on the listed hosts with zero manual workarounds beyond documented host prerequisites (`/run/postgresql`, tzdata) +- [ ] Evidence captured per command; user merges the PR + +--- + +## Execution notes +- Order: Task 11 ∥ Task 13 (disjoint files) → Task 12 (needs 11's patch for its container validation ideally; can start structural work in parallel but shares no files with 11/13 except simpleimage with 13 — coordinate: 12 owns tarballs/ tree, 13 adds its Prefer/BuildRequires hunks AFTER 12 lands) → Task 14 last. +- Standing rules: `git commit -s`, no AI attribution, never push / create PRs (user does), `-P isv` writes only with `--dry-run`. +- The pgcrypto patch (11) also changes shipping RPM symbol needs (strictly beneficial); flag to Percona upstream for a permanent home. diff --git a/docs/superpowers/plans/2026-07-22-tarballs-ssl-portability.md.tasks.json b/docs/superpowers/plans/2026-07-22-tarballs-ssl-portability.md.tasks.json new file mode 100644 index 00000000..9b448bde --- /dev/null +++ b/docs/superpowers/plans/2026-07-22-tarballs-ssl-portability.md.tasks.json @@ -0,0 +1,41 @@ +{ + "planPath": "docs/superpowers/plans/2026-07-22-tarballs-ssl-portability.md", + "tasks": [ + { + "id": 11, + "subject": "Task 11: pgcrypto OpenSSL-3.4 macro patch (staging PG RPM)", + "status": "completed", + "description": "**Goal:** EL9-built pgcrypto.so references only OPENSSL_3.0.0 nodes.\n\n**Files:**\n- Create: root/ppg/staging/17/percona-postgresql/rpm/.patch\n- Modify: root/ppg/staging/17/percona-postgresql/rpm/*.spec\n\n**Acceptance Criteria:**\n- Patch forces pre-3.4 EVP_MD_CTX_size expansion in contrib/pgcrypto; behaviorally identical\n- Rebuild evidence: readelf pgcrypto.so -> no nodes beyond OPENSSL_3.0.*\n- Patch header documents why + upstream-flag note\n\n**Verify:** readelf -V pgcrypto.so | grep 'OPENSSL_3.[1-9]' -> empty\n\n```json:metadata\n{\"files\": [\"root/ppg/staging/17/percona-postgresql/rpm/\"], \"verifyCommand\": \"readelf -V pgcrypto.so | grep OPENSSL_3.[1-9] -> empty\", \"acceptanceCriteria\": [\"macro patch minimal\", \"no >3.0 nodes\", \"documented\"], \"modelTier\": \"standard\"}\n```" + }, + { + "id": 12, + "subject": "Task 12: matrix revert to ssl1.1+ssl3(EL9), remove deb builder, script fixes", + "status": "completed", + "blockedBy": [ + 11 + ], + "description": "**Goal:** Two-variant tree with acceptance-derived fixes and tightened ssl1.1 gate.\n\n**Files:**\n- Modify: root/ppg/staging/17/tarballs/project.yaml (ssl3->Rocky9, drop ssl3.5)\n- Modify: obs/simpleimage (RPM-only, plain %build)\n- Delete: obs/build-tarball-deb.sh\n- Modify: obs/build-tarball.sh (EL map 8/9, tightened ssl1.1 pattern, PYTHONHOME in postgres wrapper, readline multiarch path, bundle libunistring/libnghttp2/libidn2)\n- Modify: root/README.md + spec doc\n\n**Acceptance Criteria:**\n- exactly ssl1.1+ssl3 repos; no deb refs outside history/spec-rationale\n- shellcheck/bash -n/pytest/pyright/black green\n- EL9 container gate GREEN incl. patched pgcrypto\n- isv dry-run clean\n\n**Verify:** container run -> ssl3 artifact, both audits 0 findings\n\n```json:metadata\n{\"files\": [\"root/ppg/staging/17/tarballs/\"], \"verifyCommand\": \"EL9 container validation green\", \"acceptanceCriteria\": [\"two-variant tree\", \"gate green\", \"fixes in\"], \"modelTier\": \"standard\"}\n```" + }, + { + "id": 13, + "subject": "Task 13: EL8 portability: krb5+libssh rebuilds in ppg:common:deps (RL8 only, same names)", + "status": "completed", + "description": "**Goal:** ssl1.1 tarball loads on stock OpenSSL 1.1 hosts; no RH-only symbol needs.\n\nUSER DECISION 2026-07-22: packages live in ppg:common:deps, RockyLinux_8 ONLY (package.yaml restriction), SAME NAMES as distro originals (krb5, libssh), winning via higher EVR.\n\n**Files:**\n- Create: root/ppg/common/deps/krb5/ (--with-crypto-impl=builtin, no OpenSSL linkage)\n- Create: root/ppg/common/deps/libssh/ (PREFERRED: libgcrypt backend -DWITH_GCRYPT=ON, no OpenSSL; FALLBACK: distinctly-named percona-openssl11-devel build-only package)\n- Verify: tarballs/project.yaml ssl1.1 chain resolution (EVR wins; Prefer only if choice reported)\n\n**Acceptance Criteria:**\n- libk5crypto: NO libcrypto NEEDED\n- libssh: no OpenSSL needs (gcrypt) or stock nodes only (fallback)\n- Shadowing side effect on EL8 staging builds verified and recorded (escalate if problematic)\n- EL8 container gate green under tightened pattern; debian:11 spot-check loads initdb/postgres\n\n**Verify:** readelf -d libk5crypto.so.3 -> no libcrypto; EL8 gate 0 violations\n\n```json:metadata\n{\"files\": [\"root/ppg/common/deps/krb5/\", \"root/ppg/common/deps/libssh/\", \"root/ppg/staging/17/tarballs/\"], \"verifyCommand\": \"EL8 container gate + debian:11 spot check\", \"acceptanceCriteria\": [\"krb5 no libcrypto\", \"libssh no/stock openssl\", \"same names RL8-only in common:deps\", \"staging shadowing verified\", \"debian11 loads\"], \"modelTier\": \"standard\"}\n```" + }, + { + "id": 14, + "subject": "Task 14: re-validation + PR round 2 + acceptance rerun (USER GATE)", + "status": "completed", + "blockedBy": [ + 12, + 13 + ], + "description": "**Goal:** Both variants pass the full acceptance battery on foreign hosts; user merges.\n\n**USER-ORDERED GATE - NON-SKIPPABLE.** Close only after every acceptanceCriteria item is re-validated independently with captured output.\n\n**Files:** none (operational)\n\n**Acceptance Criteria:**\n- User pushed; PR-145 re-synced; both repos succeeded\n- ssl1.1 on debian:11: full battery PASS (initdb, server, psql, pg_tde, pgcrypto digest, plpython3u w/o manual env, plperlu, pltclu, patronictl, patroni_aws)\n- ssl3 on ubuntu:22.04 AND ubuntu:24.04: full battery PASS incl. pgcrypto digest on host OpenSSL 3.0\n- structure-diffs documented; host prerequisites listed for release notes\n\n**Verify:** containerized battery per variant with captured output\n\n```json:metadata\n{\"files\": [], \"verifyCommand\": \"acceptance battery per variant\", \"acceptanceCriteria\": [\"PR builds succeeded\", \"debian11 ssl1.1 PASS\", \"ubuntu 22.04+24.04 ssl3 PASS\", \"evidence captured\"], \"userGate\": true, \"tags\": [\"user-gate\"], \"requireEvidenceTokens\": [[\"succeeded\"], [\"debian:11\", \"22.04\", \"24.04\"], [\"digest\", \"pgcrypto\"]], \"modelTier\": \"standard\"}\n```", + "notes": [ + "Round-2 battery FAILED 3 defects (EL9 plpython 3.9 vs 3.12 bundle; psql libreadline.so.7 NEEDED; ssl1.1 missing jmespath/s3transfer). Fixes 70c449b/a1309ae/5081378 committed + approved. Awaiting PR round-3 rebuild + re-battery.", + "Round-3 battery PASS 3/3 (debian:11 ssl1.1, ubuntu:22.04+24.04 ssl3), all regression targets fixed, zero manual workarounds. Awaiting user merge of PR-145." + ] + } + ], + "lastUpdated": "2026-07-22T23:30:00" +} \ No newline at end of file diff --git a/docs/superpowers/specs/2026-07-20-obs-simpleimage-tarballs-design.md b/docs/superpowers/specs/2026-07-20-obs-simpleimage-tarballs-design.md index 3fe9b79c..fc3d6a5f 100644 --- a/docs/superpowers/specs/2026-07-20-obs-simpleimage-tarballs-design.md +++ b/docs/superpowers/specs/2026-07-20-obs-simpleimage-tarballs-design.md @@ -1,6 +1,9 @@ # OBS simpleimage Tarballs for Percona PostgreSQL — Design -**Date:** 2026-07-20 (revised same day: real POC supplied, scope expanded to full component set) +**Date:** 2026-07-20 (revised same day: real POC supplied, scope expanded to full +component set; revised 2026-07-21: variants as repositories, ssl3 temporarily +deb-based; revised 2026-07-22: two-variant matrix — ssl3 back on EL9 via the +staging pgcrypto patch, ssl3.5 dropped, deb builder removed) **Status:** Approved design, pending implementation plan ## Background @@ -57,7 +60,8 @@ basis for the build script. - **Full official component set** (POC scope): server + extensions, pgbouncer, pgpool-II, pgbackrest, pgbadger, patroni, etcd, pg_gather, and bundled python3/perl/tcl runtimes. -- Three SSL variants; x86_64 only for now. +- Two SSL variants (ssl1.1, ssl3; ssl3.5 was dropped — see the 2026-07-22 + revision note); x86_64 only for now. - Tarballs rebuild automatically when any package in their dependency closure changes. ## Non-Goals (this iteration) @@ -73,41 +77,72 @@ basis for the build script. ### Project & tree structure -Three variant subprojects, one per SSL generation, mirroring the `containers/` pattern: +*(Revised 2026-07-21, user decision: SSL variants are **repositories** of a single +subproject, not separate subprojects.)* + +One subproject with one package; each SSL variant is an OBS repository whose path +chain points at a different EL base of `ppg:staging:17`: ``` -root/ppg/staging/17/tarballs/ -├── ssl1.1/ → ppg:staging:17:tarballs:ssl1.1 -│ ├── macros.yaml # - TARBALL_SSL_VARIANT: ssl1.1 -│ ├── project.yaml -│ └── percona-postgresql-tarball/ -│ └── obs/ -│ ├── simpleimage -│ └── build-tarball.sh -├── ssl3/ → ppg:staging:17:tarballs:ssl3 (RockyLinux_9) -└── ssl3.5/ → ppg:staging:17:tarballs:ssl3.5 (RockyLinux_10) +root/ppg/staging/17/tarballs/ → ppg:staging:17:tarballs +├── project.yaml # repos: ssl1.1, ssl3 +└── percona-postgresql-tarball/ + └── obs/ + ├── simpleimage + └── build-tarball.sh ``` -Each `project.yaml` defines one repository whose path chain matches the corresponding -base in `ppg:staging:17` (repos listed explicitly — OBS only expands the last path -transitively): - -| Subproject | Repo | Path chain | Host ABI targeted | -|---|---|---|---| -| `tarballs:ssl1.1` | `RockyLinux_8` | `ppg:staging:17/RockyLinux_8` + `ppg:common:deps` + EPEL 8 + Rocky 8 (appstream, baseos, devel) | glibc ≥ 2.28, OpenSSL 1.1 | -| `tarballs:ssl3` | `RockyLinux_9` | `ppg:staging:17/RockyLinux_9` + `ppg:common:deps` + EPEL 9 + Rocky 9 | glibc ≥ 2.34, OpenSSL 3.x | -| `tarballs:ssl3.5` | `RockyLinux_10` | `ppg:staging:17/RockyLinux_10` + EPEL 10 + Rocky 10 | glibc ≥ 2.39, OpenSSL 3.5 | - -- Archs: `[x86_64]`. -- Project-config: `Type: simpleimage`, plus any `ExpandFlags`/`Prefer` lines the base - repo needs (mirroring `staging/17/project.yaml` prjconf for that repo). -- **Publishing: enabled** — the produced `.tar.gz` is directly downloadable from the - published repository tree of each variant project. +Path chains listed explicitly — OBS only expands the last path transitively: + +| Repository | Path chain | Host ABI targeted | +|---|---|---| +| `ssl1.1` | `ppg:staging:17/RockyLinux_8` + `ppg:common:deps` + EPEL 8 + Rocky 8 (appstream, baseos, devel) | glibc ≥ 2.28, OpenSSL 1.1 | +| `ssl3` | `ppg:staging:17/RockyLinux_9` + `ppg:common:deps` + EPEL 9 + Rocky 9 | glibc ≥ 2.34, OpenSSL 3.0+ | + +*(Revised 2026-07-21: ssl3 was originally Rocky 9-based, but RHEL 9.8 rebased to +OpenSSL 3.5 and the EL9 staging `pgcrypto.so` references `OPENSSL_3.4.0` symbols — +breaking the "OpenSSL 3.0 hosts" promise; ssl3 was moved to an Ubuntu 22.04 deb +base with a second builder script. The verification gate enforces each variant's +OpenSSL promise via a versioned-symbol-needs audit, so any future drift fails the +build loudly.)* + +*(Revised 2026-07-22: the Ubuntu-deb ssl3 was abandoned — the PGDG deb layout is +non-relocatable (multiarch lib paths, split `/usr/share/postgresql` trees, tools +hardwired to `/usr/lib/postgresql/`; verified against PGDG's own packages), so +it cannot reproduce the official `/opt/percona-*` tarball layout. ssl3 is back on +the EL9 base: the `OPENSSL_3.4.0` reference was fixed at the source instead — +staging `percona-postgresql` now carries a pgcrypto patch avoiding the +`EVP_MD_CTX_get_size_ex()` OpenSSL-3.4 API, so EL9-built binaries stay at +`OPENSSL_3.0.0` and the gate's strict `OPENSSL_3\.0\.[0-9]*` policy passes. +ssl3.5 (RockyLinux_10 base) was dropped as redundant: with the pgcrypto fix, the +ssl3 tarball already runs on every OpenSSL 3.x host, including 3.5 ones. The deb +builder `build-tarball-deb.sh` and the `%build` os-release dispatcher were +removed; see "Rejected alternatives".)* + +- Archs: `[x86_64]` on every repo. +- Single project-config: `Type: simpleimage` globally, plus per-repo + `%if "%_repository" == "…"` blocks carrying the `ExpandFlags`/`Prefer` hints the + base needs (mirroring `staging/17/project.yaml` prjconf). OBS defines + `%_repository` in every build config (`BSSched/ProjPacks.pm` prepends + `%define _repository `), so the same conditionals also work inside the + `simpleimage` recipe, which is parsed as an RPM spec. +- **Publishing: enabled on both repos** — the produced `.tar.gz` is directly + downloadable from each repo's publish tree. +- OBS builds the one package once per repository → two artifacts per checkin; + no duplicated package files, no copy-identity test needed. ### The simpleimage package -The package files are **byte-identical across all three variants**; variant identity -comes from the subproject's `macros.yaml` and its repo path chain. +One copy of each file. Both remaining variants are EL bases with identical +package naming (the parallel `python3.12` stack exists on EL8 and EL9), so the +recipe needs no `%if "%_repository"` conditionals at all — per-variant +differences live only in the project config's prjconf blocks. *(The mechanism +remains available: OBS defines `%_repository` in the recipe too, and earlier +revisions used it for the ssl3.5 python naming and the deb branch.)* + +`Version:` is plain `%!{PG_VERSION}` — metadata only; it no longer drives the +artifact name (see below). The `TARBALL_SSL_VARIANT`/`TARBALL_PYTHON_PKG` macros +are gone. `obs/simpleimage` (macro-expanded at sync time) — POC preamble adapted to staging:17 package names and macros: @@ -116,7 +151,7 @@ package names and macros: #!NoTarBall #!NoSquashfs Name: percona-postgresql -Version: %!{PG_VERSION}-%!{TARBALL_SSL_VARIANT}-linux +Version: %!{PG_VERSION} # PostgreSQL server and all extensions BuildRequires: percona-postgresql%!{PG_MAJOR_VERSION} @@ -145,11 +180,7 @@ BuildRequires: percona-patroni BuildRequires: percona-patroni-aws BuildRequires: etcd BuildRequires: python3-pysyncobj -# Language runtimes -BuildRequires: python3.12 -BuildRequires: python3.12-pip -BuildRequires: python3.12-devel -BuildRequires: python3.12-idle +# Language runtimes (python via the %if "%_repository" conditional shown above) BuildRequires: perl BuildRequires: perl-libs BuildRequires: perl-devel @@ -170,9 +201,18 @@ Notes: pg_cron / pg-telemetry) are **verified against staging:17 build results and the official tarball structure-diff during implementation** — the POC list is the starting point, and it may need per-repo `%if` guards if names differ across bases. -- Output artifact: `percona-postgresql-17.10-ssl3-linux_x86_64.tar.gz` - (recipe naming is `Name-Version_ARCH.tar.gz`; the underscore before the arch differs - from the official name — exact renaming, if needed, happens at release/download time). +- Output artifact: `percona-postgresql-17.10-ssl3-linux-x86_64.tar.gz` — **exactly** + the official name, including the dash before the arch. The recipe's own + `Name-Version_ARCH` naming cannot vary per repository (it reads the tags with a raw + `sed`, no macro expansion), so the `%build` script writes the artifact itself into + `/usr/src/packages/OTHER/` (the directory OBS collects results from) and creates no + `/.simpleimage.tar.gz` (which makes the recipe's rename step a no-op). The name is + fully self-derived inside the buildroot: PG version from the installed server + package (`rpm -q`), SSL variant mapped from the buildroot's EL major + (`/etc/os-release` `PLATFORM_ID` with a glibc dist-tag fallback: 8→ssl1.1, + 9→ssl3; anything unmapped fails the build loudly), arch from `uname -m`. + *(An openssl-version-based mapping was originally specified but is + impossible: EL9 and EL10 both ship OpenSSL 3.5 now.)* - Version bumps are automatic: `PG_VERSION` derives from `PG_MINOR_VERSION` in `staging/17/macros.yaml`, which is already bumped during release prep. - All build logic lives in `build-tarball.sh`, not inline in `%build`: the `%build` @@ -180,7 +220,7 @@ Notes: standalone script can be exercised locally in a container. The script is macro-free — it discovers the PG major version from `/usr/pgsql-*` and probes perl/tcl/python versions at run time (replacing the POC's hardcoded `PG_MAJOR=17` / `PY_VER=3.12` - where practical) — so it stays identical across variants and future PG majors. + where practical) — so the same script serves all variant repos and future PG majors. ### The %build pipeline (`build-tarball.sh`) @@ -222,18 +262,25 @@ after OBS installs the BuildRequires closure: `pltcl.so` additionally get `/opt/percona-python3/lib`, the perl `CORE` dir, and `/opt/percona-tcl/lib` appended (matching official RUNPATHs). 5. **Pre-tar verification (build fails on error — addition over the POC):** - - `ldd` audit over `/opt`: zero `not found` beyond the deliberate exclusion list. + - DT_NEEDED soname audit over `/opt` (`patchelf --print-needed`): every needed + soname must pass the exclusion list or be bundled (dangling symlinks rejected). + (Replaced the originally-specified `ldd` audit, which is blind inside a fully + populated buildroot — missing libs still resolve from `/usr/lib64`.) - Smoke: `bin/initdb --version`, `bin/postgres.real --version`, `percona-python3/bin/python3 -c 'import ssl, yaml'`, `percona-patroni/bin/patronictl version` — all with RPATH/wrapper resolution only. -6. **Create the artifact ourselves:** `cd /opt && tar -czf /.simpleimage.tar.gz *`. - With `#!NoTarBall` set, the recipe skips its own full-buildroot tar and just renames - our file to `Name-Version_ARCH.tar.gz`. No buildroot pruning, no `rm -rf` tricks. +6. **Create the artifact ourselves, with the official name:** derive the full name + inside the buildroot (PG version from the server RPM, SSL variant from + `openssl-libs`, arch from `uname -m`) and + `tar -czf /usr/src/packages/OTHER/percona-postgresql---linux-.tar.gz` + from `/opt`. `#!NoTarBall` keeps the recipe from tarring the buildroot, and with no + `/.simpleimage.tar.gz` present its rename step is a no-op — OBS collects our file + from `OTHER/` as the build result. No buildroot pruning, no `rm -rf` tricks. ### percona-obs tooling impact -None expected. The `tarballs/ssl*/` dirs have the same shape as `containers/ubi*/`: -colon-named subprojects with `project.yaml` and packages whose `obs/` files sync +None expected. The `tarballs/` dir has the same shape as `containers/ubi*/`: +a colon-named subproject with `project.yaml` and a package whose `obs/` files sync verbatim with macro expansion (a package is any dir with an `obs/` subdir — `common.is_package`). Implementation includes a verification step that nothing in `targets.py` / `cmd_sync.py` / `cmd_project.py` special-cases containers. @@ -260,8 +307,10 @@ verbatim with macro expansion (a package is any dir with an `obs/` subdir — installed (virtually always true). - Tarball binaries are the RPM builds (`--prefix=/usr/pgsql-`); `pg_config` reports those original paths even though runtime path resolution is relocatable. -- OpenSSL versions come from the base distro (EL8 = 1.1.1, EL9 = 3.x, EL10 = 3.5) - rather than Percona-pinned source builds (exception: python3's bundled OpenSSL). +- OpenSSL versions come from the base distro (EL8 = 1.1.1, EL9 = 3.5 since + Rocky 9.8) rather than Percona-pinned source builds (exception: python3's + bundled OpenSSL). The per-variant symbol-needs gate is what keeps the host + promise honest despite the newer buildroot OpenSSL. - The PL runtime wrappers hardcode `/opt/percona-{python3,perl,tcl}` (as the official tarballs do) — PL/Perl, PL/Python, PL/Tcl require the runtimes to be copied to `/opt` per the install docs. @@ -271,11 +320,13 @@ verbatim with macro expansion (a package is any dir with an `obs/` subdir — - Exact `BuildRequires` package names/list — verify against `ppg:staging:17` build results per repo and the official tarball structure-diff (pg_cron, pg-telemetry, haproxy presence; pgvector/postgis/pgpool RPM naming). -- Confirm Rocky 10 ships OpenSSL 3.5 (naming of the `ssl3.5` variant depends on it). +- ~~Confirm Rocky 10 ships OpenSSL 3.5 (naming of the `ssl3.5` variant depends on + it).~~ Confirmed (it does), then mooted: the ssl3.5 variant was dropped on + 2026-07-22 as redundant with the fixed ssl3. - Confirm where published simpleimage artifacts land in the publish tree URL layout. -- Confirm the `obs-pr-sync` workflow correctly creates PR projects for *brand-new* - subprojects (`tarballs:ssl*` do not exist in production yet), including their - repo path rewrites against the PR project namespace. +- Confirm the `obs-pr-sync` workflow correctly creates PR projects for the *brand-new* + subproject (`ppg:staging:17:tarballs` does not exist in production yet), including + its repo path rewrites against the PR project namespace. - Python runtime availability per base: `python3.12` exists on EL8/EL9 as parallel stacks and is the default on EL10 — the script's version probing must handle both (`/usr/bin/python3.12` vs `/usr/bin/python3`). @@ -292,3 +343,14 @@ verbatim with macro expansion (a package is any dir with an `obs/` subdir — - **Buildroot pruning via final `rm -rf` (first spec revision):** superseded by the POC's `#!NoTarBall` + self-created `/.simpleimage.tar.gz` of `/opt` — strictly safer and simpler. +- **Ubuntu 22.04 deb-based ssl3 (2026-07-21 revision, removed 2026-07-22):** built + the ssl3 variant from staging's Ubuntu 22.04 debs (whose OpenSSL 3.0.2 base + guaranteed only `OPENSSL_3.0.0` symbol needs) via a parallel + `build-tarball-deb.sh` and a `%build` os-release dispatcher. Abandoned because + the PGDG deb layout is non-relocatable — multiarch lib dirs + (`/usr/lib/x86_64-linux-gnu`), split `/usr/share/postgresql` trees, and tools + hardwired to `/usr/lib/postgresql/` (verified against PGDG's own packages) — + unlike the PGDG RPM `/usr/pgsql-NN` prefix the official tarball layout derives + from. Superseded by fixing the root cause: the staging pgcrypto patch keeps + EL9-built binaries at `OPENSSL_3.0.0`, so ssl3 builds honestly from Rocky 9 + again. The deb builder survives in git history for reference. diff --git a/percona_obs/obs_api.py b/percona_obs/obs_api.py index a94b7431..d1d1acc8 100644 --- a/percona_obs/obs_api.py +++ b/percona_obs/obs_api.py @@ -1121,6 +1121,30 @@ def _disable_project_builds(apiurl: str, obs_project_name: str) -> None: _print_update(f"project meta {obs_project_name} (builds disabled)") +def _filter_meta_repos( + repos: "list[dict]", only_repos: "set[str] | None" +) -> "list[dict]": + """Apply the --only-repos project-meta filter. + + Keeps a repository when its name is in ``only_repos``. SSL-variant tarball + repos (``ssl1.1``/``ssl3``/``ssl3.5``) are named by OpenSSL variant, not by + distro base, so they never match a label-derived ``--only-repos`` set + (``RockyLinux_9``, ``Debian_13``, …). Without an exemption, any repo label + on a PR would strip a simpleimage tarball project's meta down to zero + repositories and the tarball would silently never build. Always keep + ``ssl*`` repos regardless of the filter. + + ``only_repos`` of ``None`` is a passthrough (no filtering). + """ + if only_repos is None: + return repos + return [ + r + for r in repos + if r.get("name") in only_repos or (r.get("name") or "").startswith("ssl") + ] + + def _apply_project_config( apiurl: str, obs_project_name: str, @@ -1175,8 +1199,7 @@ def _apply_project_config( if branch_rootprj is not None: build = None repos = project_config.get("repositories", []) - if only_repos is not None: - repos = [r for r in repos if r.get("name") in only_repos] + repos = _filter_meta_repos(repos, only_repos) meta = build_project_meta( obs_project_name, project_config.get("title", ""), diff --git a/root/README.md b/root/README.md index 2d7901d8..e497fcf8 100644 --- a/root/README.md +++ b/root/README.md @@ -135,6 +135,55 @@ Each package directory contains the packaging sources split by format: └── debian/ # Debian packaging files ``` +#### `tarballs/` + +Binary-tarball builds (OBS `simpleimage` format) for air-gapped / unsupported-distro +installs, replicating the official Percona tarball layout. One subproject +(`ppg:staging::tarballs`) with a single `percona-postgresql-tarball` package, +built across two repositories — one per SSL variant, each stacked on a different +EL base of `ppg:staging:`: + +| Repository | Base | Host ABI targeted | +|---|---|---| +| `ssl1.1` | RockyLinux_8 | glibc ≥ 2.28, OpenSSL 1.1 (stock and RHEL-fork hosts) | +| `ssl3` | RockyLinux_9 | glibc ≥ 2.34, OpenSSL 3.0+ (all 3.x hosts) | + +The `ssl3` promise ("runs on any OpenSSL 3.0 host") holds on the EL9 base — +whose own OpenSSL is 3.5.x since Rocky 9.8 — because staging +`percona-postgresql` patches pgcrypto to avoid an OpenSSL 3.4-only API, so the +EL9-built binaries reference only `OPENSSL_3.0.0` symbol-version nodes; the +builder's verification gate enforces exactly that per variant. (An interim +Ubuntu 22.04 deb-based `ssl3` was tried and abandoned: the PGDG deb layout is +non-relocatable.) + +Per-repository differences (prjconf resolution hints) are handled with +`%if "%_repository" == "..."` conditionals in the project config; the +`simpleimage` recipe is variant-independent and its `%build` runs the single +builder script, `build-tarball.sh`. The script stages all components under +`/opt/percona-*`, runs the verification gate (unresolved-soname audit plus a +per-variant OpenSSL host-ABI audit) and creates the artifact itself: it derives +the official tarball name at build time (the SSL variant is mapped from the +buildroot's EL major in `/etc/os-release`, with a glibc `%dist`-tag fallback) +and writes it directly into the OBS result directory +(`/usr/src/packages/OTHER`), bypassing the recipe's own fixed-name tar step +(`#!NoTarBall`). Both repositories publish their results, so the `.tar.gz` +files are downloadable from the OBS publish tree. + +Host prerequisites (beyond the glibc/OpenSSL floors above): a `/run/postgresql` +directory writable by the postgres user (the default Unix-socket directory), +tzdata (`/usr/share/zoneinfo` — the server is built with system tzdata), and, +for GSSAPI/Kerberos authentication only, host krb5 *configuration* +(`/etc/krb5.conf`) — the krb5 libraries themselves are bundled. +Note: the `postgres` wrapper exports `PYTHONHOME=/opt/percona-python3` (needed +by the embedded PL/Python) and every child the server spawns inherits it, so +host-python commands launched by the server (`archive_command`, +`restore_command`, backup hooks) must strip it, e.g. +`archive_command = 'env -u PYTHONHOME ...'`. +Operational note: if the `ssl1.1` SSL-ABI audit ever fires on +`OPENSSL_1_1_1b`-class version nodes via libkrb5/libgssapi/libssh, the EL8 +distro has rebased krb5/libssh past the percona `-NN.percona` rebuilds in +`ppg:common:deps` — bump those rebuilds. + ### `devel//` A manually curated subset of `staging//`, built from development branches instead of diff --git a/root/ppg/common/deps/krb5/obs/_service b/root/ppg/common/deps/krb5/obs/_service new file mode 100644 index 00000000..4781ecb0 --- /dev/null +++ b/root/ppg/common/deps/krb5/obs/_service @@ -0,0 +1,8 @@ + + + web.mit.edu + https + /kerberos/dist/krb5/1.18/krb5-1.18.2.tar.gz + krb5-1.18.2.tar.gz + + diff --git a/root/ppg/common/deps/krb5/package.yaml b/root/ppg/common/deps/krb5/package.yaml new file mode 100644 index 00000000..f4e9ce65 --- /dev/null +++ b/root/ppg/common/deps/krb5/package.yaml @@ -0,0 +1,27 @@ +title: krb5 rebuilt with builtin crypto for tarball portability +description: | + Rebuild of the Rocky Linux 8 krb5 source package with + --with-crypto-impl=builtin instead of openssl, for the EL8-built + (ssl1.1) binary tarball. Red Hat's krb5 links libk5crypto.so.3 + against Red Hat's OpenSSL 1.1.1 fork and needs symbol version nodes + (e.g. EVP_KDF_ctrl@OPENSSL_1_1_1b) that exist only in RHEL-family + libcrypto.so.1.1, so the bundled library fails to load on stock + OpenSSL 1.1 hosts (e.g. Debian 11). With builtin crypto the krb5 + libraries have no libcrypto dependency at all, matching the official + Percona tarball. Binary package names are identical to the distro's; + the Release carries a .percona suffix so this EVR wins resolution. + RockyLinux_8 only — every other repository uses the distro krb5. + +build: + RockyLinux_9: false + RockyLinux_10: false + UBI_8: false + UBI_9: false + Debian_11: false + Debian_12: false + Debian_13: false + Ubuntu_22.04: false + Ubuntu_24.04: false + Ubuntu_26.04: false + openSUSE_Leap_16: false + openSUSE_Tumbleweed: false diff --git a/root/ppg/common/deps/krb5/rpm/Add-APIs-for-marshalling-credentials.patch b/root/ppg/common/deps/krb5/rpm/Add-APIs-for-marshalling-credentials.patch new file mode 100644 index 00000000..db04da82 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Add-APIs-for-marshalling-credentials.patch @@ -0,0 +1,222 @@ +From de01999b35773196749ba714f233649c9528aaad Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Thu, 14 Jan 2021 18:13:09 -0500 +Subject: [PATCH] Add APIs for marshalling credentials + +Faciliate KCM daemon implementations by providing functions to +deserialize and reserialize credentials in the FILE v4 format. + +[ghudson@mit.edu: minor editorial changes] + +ticket: 8980 (new) +(cherry picked from commit 18ea3bd2fca55b789b7de9c663624bc11d348fa6) +(cherry picked from commit 3d11179707923b033fa413387a33296b673ff52d) +[rharwood@redhat.com: function backport, so conflict in krb5_32.def] +--- + doc/appdev/refs/api/index.rst | 2 ++ + src/include/krb5/krb5.hin | 36 ++++++++++++++++++++++ + src/lib/krb5/ccache/ccmarshal.c | 53 +++++++++++++++++++++++++++++++++ + src/lib/krb5/ccache/t_marshal.c | 15 +++++++++- + src/lib/krb5/libkrb5.exports | 2 ++ + src/lib/krb5_32.def | 4 +++ + 6 files changed, 111 insertions(+), 1 deletion(-) + +diff --git a/doc/appdev/refs/api/index.rst b/doc/appdev/refs/api/index.rst +index 727d9b492..9e03fd386 100644 +--- a/doc/appdev/refs/api/index.rst ++++ b/doc/appdev/refs/api/index.rst +@@ -232,6 +232,7 @@ Rarely used public interfaces + krb5_kt_remove_entry.rst + krb5_kt_start_seq_get.rst + krb5_make_authdata_kdc_issued.rst ++ krb5_marshal_credentials.rst + krb5_merge_authdata.rst + krb5_mk_1cred.rst + krb5_mk_error.rst +@@ -285,6 +286,7 @@ Rarely used public interfaces + krb5_tkt_creds_get_times.rst + krb5_tkt_creds_init.rst + krb5_tkt_creds_step.rst ++ krb5_unmarshal_credentials.rst + krb5_verify_init_creds.rst + krb5_verify_init_creds_opt_init.rst + krb5_verify_init_creds_opt_set_ap_req_nofail.rst +diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin +index 9264bede1..d2cf1eba2 100644 +--- a/src/include/krb5/krb5.hin ++++ b/src/include/krb5/krb5.hin +@@ -3125,6 +3125,42 @@ krb5_get_credentials(krb5_context context, krb5_flags options, + krb5_ccache ccache, krb5_creds *in_creds, + krb5_creds **out_creds); + ++/** ++ * Serialize a @c krb5_creds object. ++ * ++ * @param [in] context Library context ++ * @param [in] creds The credentials object to serialize ++ * @param [out] data_out The serialized credentials ++ * ++ * Serialize @a creds in the format used by the FILE ccache format (vesion 4) ++ * and KCM ccache protocol. ++ * ++ * Use krb5_free_data() to free @a data_out when it is no longer needed. ++ * ++ * @retval 0 Success; otherwise - Kerberos error codes ++ */ ++krb5_error_code KRB5_CALLCONV ++krb5_marshal_credentials(krb5_context context, krb5_creds *in_creds, ++ krb5_data **data_out); ++ ++/** ++ * Deserialize a @c krb5_creds object. ++ * ++ * @param [in] context Library context ++ * @param [in] data The serialized credentials ++ * @param [out] creds_out The resulting creds object ++ * ++ * Deserialize @a data to credentials in the format used by the FILE ccache ++ * format (vesion 4) and KCM ccache protocol. ++ * ++ * Use krb5_free_creds() to free @a creds_out when it is no longer needed. ++ * ++ * @retval 0 Success; otherwise - Kerberos error codes ++ */ ++krb5_error_code KRB5_CALLCONV ++krb5_unmarshal_credentials(krb5_context context, const krb5_data *data, ++ krb5_creds **creds_out); ++ + /** @deprecated Replaced by krb5_get_validated_creds. */ + krb5_error_code KRB5_CALLCONV + krb5_get_credentials_validate(krb5_context context, krb5_flags options, +diff --git a/src/lib/krb5/ccache/ccmarshal.c b/src/lib/krb5/ccache/ccmarshal.c +index ae634ccab..ab284e721 100644 +--- a/src/lib/krb5/ccache/ccmarshal.c ++++ b/src/lib/krb5/ccache/ccmarshal.c +@@ -515,3 +515,56 @@ k5_marshal_mcred(struct k5buf *buf, krb5_creds *mcred) + if (mcred->second_ticket.length > 0) + put_data(buf, version, &mcred->second_ticket); + } ++ ++krb5_error_code KRB5_CALLCONV ++krb5_marshal_credentials(krb5_context context, krb5_creds *in_creds, ++ krb5_data **data_out) ++{ ++ krb5_error_code ret; ++ krb5_data *data; ++ struct k5buf buf; ++ ++ *data_out = NULL; ++ ++ data = k5alloc(sizeof(krb5_data), &ret); ++ if (ret) ++ return ret; ++ ++ k5_buf_init_dynamic(&buf); ++ k5_marshal_cred(&buf, 4, in_creds); ++ ++ ret = k5_buf_status(&buf); ++ if (ret) { ++ free(data); ++ return ret; ++ } ++ ++ /* Steal payload from buf. */ ++ *data = make_data(buf.data, buf.len); ++ *data_out = data; ++ return 0; ++} ++ ++krb5_error_code KRB5_CALLCONV ++krb5_unmarshal_credentials(krb5_context context, const krb5_data *data, ++ krb5_creds **creds_out) ++{ ++ krb5_error_code ret; ++ krb5_creds *creds; ++ ++ *creds_out = NULL; ++ ++ creds = k5alloc(sizeof(krb5_creds), &ret); ++ if (ret) ++ return ret; ++ ++ ret = k5_unmarshal_cred((unsigned char *)data->data, data->length, 4, ++ creds); ++ if (ret) { ++ free(creds); ++ return ret; ++ } ++ ++ *creds_out = creds; ++ return 0; ++} +diff --git a/src/lib/krb5/ccache/t_marshal.c b/src/lib/krb5/ccache/t_marshal.c +index 144554c30..47ec2e94d 100644 +--- a/src/lib/krb5/ccache/t_marshal.c ++++ b/src/lib/krb5/ccache/t_marshal.c +@@ -268,13 +268,14 @@ main(int argc, char **argv) + krb5_context context; + krb5_ccache cache; + krb5_principal princ; +- krb5_creds cred1, cred2; ++ krb5_creds cred1, cred2, *alloc_cred; + krb5_cc_cursor cursor; + const char *filename; + char *ccname, filebuf[256]; + int version, fd; + const struct test *t; + struct k5buf buf; ++ krb5_data ser_data, *alloc_data; + + if (argc != 2) + abort(); +@@ -285,6 +286,18 @@ main(int argc, char **argv) + if (krb5_init_context(&context) != 0) + abort(); + ++ /* Test public functions for unmarshalling and marshalling. */ ++ ser_data = make_data((char *)tests[3].cred1, tests[3].cred1len); ++ if (krb5_unmarshal_credentials(context, &ser_data, &alloc_cred) != 0) ++ abort(); ++ verify_cred1(alloc_cred); ++ if (krb5_marshal_credentials(context, alloc_cred, &alloc_data) != 0) ++ abort(); ++ assert(alloc_data->length == tests[3].cred1len); ++ assert(memcmp(tests[3].cred1, alloc_data->data, alloc_data->length) == 0); ++ krb5_free_data(context, alloc_data); ++ krb5_free_creds(context, alloc_cred); ++ + for (version = FIRST_VERSION; version <= 4; version++) { + t = &tests[version - 1]; + +diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports +index cab5b3b17..48ae46f5c 100644 +--- a/src/lib/krb5/libkrb5.exports ++++ b/src/lib/krb5/libkrb5.exports +@@ -488,6 +488,7 @@ krb5_lock_file + krb5_make_authdata_kdc_issued + krb5_make_full_ipaddr + krb5_make_fulladdr ++krb5_marshal_credentials + krb5_mcc_ops + krb5_merge_authdata + krb5_mk_1cred +@@ -592,6 +593,7 @@ krb5_timeofday + krb5_timestamp_to_sfstring + krb5_timestamp_to_string + krb5_unlock_file ++krb5_unmarshal_credentials + krb5_unpack_full_ipaddr + krb5_unparse_name + krb5_unparse_name_ext +diff --git a/src/lib/krb5_32.def b/src/lib/krb5_32.def +index de5823c17..209c6aaef 100644 +--- a/src/lib/krb5_32.def ++++ b/src/lib/krb5_32.def +@@ -502,3 +502,7 @@ EXPORTS + + ; new in 1.19 + k5_cc_store_primary_cred @470 ; PRIVATE ++ ++; new in 1.20 ++ krb5_marshal_credentials @472 ++ krb5_unmarshal_credentials @473 diff --git a/root/ppg/common/deps/krb5/rpm/Add-KCM_OP_GET_CRED_LIST-for-faster-iteration.patch b/root/ppg/common/deps/krb5/rpm/Add-KCM_OP_GET_CRED_LIST-for-faster-iteration.patch new file mode 100644 index 00000000..3c9028b1 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Add-KCM_OP_GET_CRED_LIST-for-faster-iteration.patch @@ -0,0 +1,360 @@ +From d4a512e571a93318d37cbf7d18a120f317b87e97 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Thu, 11 Feb 2021 15:33:10 +0100 +Subject: [PATCH] Add KCM_OP_GET_CRED_LIST for faster iteration + +For large caches, one IPC operation per credential dominates the cost +of iteration. Instead transfer the whole list of credentials to the +client in one IPC operation. + +Add optional support for the new opcode to the test KCM server to +allow testing of the main and fallback code paths. + +[ghudson@mit.edu: fixed memory leaks and potential memory errors; +adjusted code style and comments; rewrote commit message; added +kcmserver.py support and tests] + +ticket: 8990 (new) +(cherry picked from commit 81bdb47d8ded390263d8ee48f71d5c312b4f1736) +(cherry picked from commit a0ee8b02e56c65e5dcd569caed0e151cef004ef4) +(cherry picked from commit baf60dbdeceb3cad35cad7d9930782f94b6c8221) +--- + src/include/kcm.h | 12 ++- + src/lib/krb5/ccache/cc_kcm.c | 144 ++++++++++++++++++++++++++++++++--- + src/tests/kcmserver.py | 28 ++++++- + src/tests/t_ccache.py | 10 ++- + 4 files changed, 175 insertions(+), 19 deletions(-) + +diff --git a/src/include/kcm.h b/src/include/kcm.h +index 5ea1447cd..e4140c3a0 100644 +--- a/src/include/kcm.h ++++ b/src/include/kcm.h +@@ -51,9 +51,9 @@ + * + * All replies begin with a 32-bit big-endian reply code. + * +- * Parameters are appended to the request or reply with no delimiters. Flags +- * and time offsets are stored as 32-bit big-endian integers. Names are +- * marshalled as zero-terminated strings. Principals and credentials are ++ * Parameters are appended to the request or reply with no delimiters. Flags, ++ * time offsets, and lengths are stored as 32-bit big-endian integers. Names ++ * are marshalled as zero-terminated strings. Principals and credentials are + * marshalled in the v4 FILE ccache format. UUIDs are 16 bytes. UUID lists + * are not delimited, so nothing can come after them. + */ +@@ -89,7 +89,11 @@ typedef enum kcm_opcode { + KCM_OP_HAVE_NTLM_CRED, + KCM_OP_DEL_NTLM_CRED, + KCM_OP_DO_NTLM_AUTH, +- KCM_OP_GET_NTLM_USER_LIST ++ KCM_OP_GET_NTLM_USER_LIST, ++ ++ /* MIT extensions */ ++ KCM_OP_MIT_EXTENSION_BASE = 13000, ++ KCM_OP_GET_CRED_LIST, /* (name) -> (count, count*{len, cred}) */ + } kcm_opcode; + + #endif /* KCM_H */ +diff --git a/src/lib/krb5/ccache/cc_kcm.c b/src/lib/krb5/ccache/cc_kcm.c +index a76a285d9..197a10fba 100644 +--- a/src/lib/krb5/ccache/cc_kcm.c ++++ b/src/lib/krb5/ccache/cc_kcm.c +@@ -61,6 +61,17 @@ struct uuid_list { + size_t pos; + }; + ++struct cred_list { ++ krb5_creds *creds; ++ size_t count; ++ size_t pos; ++}; ++ ++struct kcm_cursor { ++ struct uuid_list *uuids; ++ struct cred_list *creds; ++}; ++ + struct kcmio { + SOCKET fd; + #ifdef __APPLE__ +@@ -489,6 +500,69 @@ free_uuid_list(struct uuid_list *uuids) + free(uuids); + } + ++static void ++free_cred_list(struct cred_list *list) ++{ ++ size_t i; ++ ++ if (list == NULL) ++ return; ++ ++ /* Creds are transferred to the caller as list->pos is incremented, so we ++ * can start freeing there. */ ++ for (i = list->pos; i < list->count; i++) ++ krb5_free_cred_contents(NULL, &list->creds[i]); ++ free(list->creds); ++ free(list); ++} ++ ++/* Fetch a cred list from req->reply. */ ++static krb5_error_code ++kcmreq_get_cred_list(struct kcmreq *req, struct cred_list **creds_out) ++{ ++ struct cred_list *list; ++ const unsigned char *data; ++ krb5_error_code ret = 0; ++ size_t count, len, i; ++ ++ *creds_out = NULL; ++ ++ /* Check a rough bound on the count to prevent very large allocations. */ ++ count = k5_input_get_uint32_be(&req->reply); ++ if (count > req->reply.len / 4) ++ return KRB5_KCM_MALFORMED_REPLY; ++ ++ list = malloc(sizeof(*list)); ++ if (list == NULL) ++ return ENOMEM; ++ ++ list->creds = NULL; ++ list->count = count; ++ list->pos = 0; ++ list->creds = k5calloc(count, sizeof(*list->creds), &ret); ++ if (list->creds == NULL) { ++ free(list); ++ return ret; ++ } ++ ++ for (i = 0; i < count; i++) { ++ len = k5_input_get_uint32_be(&req->reply); ++ data = k5_input_get_bytes(&req->reply, len); ++ if (data == NULL) ++ break; ++ ret = k5_unmarshal_cred(data, len, 4, &list->creds[i]); ++ if (ret) ++ break; ++ } ++ if (i < count) { ++ free_cred_list(list); ++ return (ret == ENOMEM) ? ENOMEM : KRB5_KCM_MALFORMED_REPLY; ++ } ++ ++ *creds_out = list; ++ return 0; ++} ++ + static void + kcmreq_free(struct kcmreq *req) + { +@@ -753,33 +827,53 @@ kcm_start_seq_get(krb5_context context, krb5_ccache cache, + { + krb5_error_code ret; + struct kcmreq req = EMPTY_KCMREQ; +- struct uuid_list *uuids; ++ struct uuid_list *uuids = NULL; ++ struct cred_list *creds = NULL; ++ struct kcm_cursor *cursor; + + *cursor_out = NULL; + + get_kdc_offset(context, cache); + +- kcmreq_init(&req, KCM_OP_GET_CRED_UUID_LIST, cache); ++ kcmreq_init(&req, KCM_OP_GET_CRED_LIST, cache); + ret = cache_call(context, cache, &req); +- if (ret) ++ if (ret == 0) { ++ /* GET_CRED_LIST is available. */ ++ ret = kcmreq_get_cred_list(&req, &creds); ++ if (ret) ++ goto cleanup; ++ } else if (ret == KRB5_FCC_INTERNAL) { ++ /* Fall back to GET_CRED_UUID_LIST. */ ++ kcmreq_free(&req); ++ kcmreq_init(&req, KCM_OP_GET_CRED_UUID_LIST, cache); ++ ret = cache_call(context, cache, &req); ++ if (ret) ++ goto cleanup; ++ ret = kcmreq_get_uuid_list(&req, &uuids); ++ if (ret) ++ goto cleanup; ++ } else { + goto cleanup; +- ret = kcmreq_get_uuid_list(&req, &uuids); +- if (ret) ++ } ++ ++ cursor = k5alloc(sizeof(*cursor), &ret); ++ if (cursor == NULL) + goto cleanup; +- *cursor_out = (krb5_cc_cursor)uuids; ++ cursor->uuids = uuids; ++ cursor->creds = creds; ++ *cursor_out = (krb5_cc_cursor)cursor; + + cleanup: + kcmreq_free(&req); + return ret; + } + +-static krb5_error_code KRB5_CALLCONV +-kcm_next_cred(krb5_context context, krb5_ccache cache, krb5_cc_cursor *cursor, +- krb5_creds *cred_out) ++static krb5_error_code ++next_cred_by_uuid(krb5_context context, krb5_ccache cache, ++ struct uuid_list *uuids, krb5_creds *cred_out) + { + krb5_error_code ret; + struct kcmreq req; +- struct uuid_list *uuids = (struct uuid_list *)*cursor; + + memset(cred_out, 0, sizeof(*cred_out)); + +@@ -797,11 +891,39 @@ kcm_next_cred(krb5_context context, krb5_ccache cache, krb5_cc_cursor *cursor, + return map_invalid(ret); + } + ++static krb5_error_code KRB5_CALLCONV ++kcm_next_cred(krb5_context context, krb5_ccache cache, krb5_cc_cursor *cursor, ++ krb5_creds *cred_out) ++{ ++ struct kcm_cursor *c = (struct kcm_cursor *)*cursor; ++ struct cred_list *list; ++ ++ if (c->uuids != NULL) ++ return next_cred_by_uuid(context, cache, c->uuids, cred_out); ++ ++ list = c->creds; ++ if (list->pos >= list->count) ++ return KRB5_CC_END; ++ ++ /* Transfer memory ownership of one cred to the caller. */ ++ *cred_out = list->creds[list->pos]; ++ memset(&list->creds[list->pos], 0, sizeof(*list->creds)); ++ list->pos++; ++ ++ return 0; ++} ++ + static krb5_error_code KRB5_CALLCONV + kcm_end_seq_get(krb5_context context, krb5_ccache cache, + krb5_cc_cursor *cursor) + { +- free_uuid_list((struct uuid_list *)*cursor); ++ struct kcm_cursor *c = *cursor; ++ ++ if (c == NULL) ++ return 0; ++ free_uuid_list(c->uuids); ++ free_cred_list(c->creds); ++ free(c); + *cursor = NULL; + return 0; + } +diff --git a/src/tests/kcmserver.py b/src/tests/kcmserver.py +index 57432e5a7..8c5e66ff1 100644 +--- a/src/tests/kcmserver.py ++++ b/src/tests/kcmserver.py +@@ -23,6 +23,7 @@ + # traceback.print_exception(etype, value, tb, file=f) + # sys.excepthook = ehook + ++import optparse + import select + import socket + import struct +@@ -49,12 +50,14 @@ class KCMOpcodes(object): + SET_DEFAULT_CACHE = 21 + GET_KDC_OFFSET = 22 + SET_KDC_OFFSET = 23 ++ GET_CRED_LIST = 13001 + + + class KRB5Errors(object): + KRB5_CC_END = -1765328242 + KRB5_CC_NOSUPP = -1765328137 + KRB5_FCC_NOFILE = -1765328189 ++ KRB5_FCC_INTERNAL = -1765328188 + + + def make_uuid(): +@@ -183,6 +186,14 @@ def op_set_kdc_offset(argbytes): + return 0, b'' + + ++def op_get_cred_list(argbytes): ++ name, rest = unmarshal_name(argbytes) ++ cache = get_cache(name) ++ creds = [cache.creds[u] for u in cache.cred_uuids] ++ return 0, (struct.pack('>L', len(creds)) + ++ b''.join(struct.pack('>L', len(c)) + c for c in creds)) ++ ++ + ophandlers = { + KCMOpcodes.GEN_NEW : op_gen_new, + KCMOpcodes.INITIALIZE : op_initialize, +@@ -197,7 +208,8 @@ ophandlers = { + KCMOpcodes.GET_DEFAULT_CACHE : op_get_default_cache, + KCMOpcodes.SET_DEFAULT_CACHE : op_set_default_cache, + KCMOpcodes.GET_KDC_OFFSET : op_get_kdc_offset, +- KCMOpcodes.SET_KDC_OFFSET : op_set_kdc_offset ++ KCMOpcodes.SET_KDC_OFFSET : op_set_kdc_offset, ++ KCMOpcodes.GET_CRED_LIST : op_get_cred_list + } + + # Read and respond to a request from the socket s. +@@ -215,7 +227,11 @@ def service_request(s): + + majver, minver, op = struct.unpack('>BBH', req[:4]) + argbytes = req[4:] +- code, payload = ophandlers[op](argbytes) ++ ++ if op in ophandlers: ++ code, payload = ophandlers[op](argbytes) ++ else: ++ code, payload = KRB5Errors.KRB5_FCC_INTERNAL, b'' + + # The KCM response is the code (4 bytes) and the response payload. + # The Heimdal IPC response is the length of the KCM response (4 +@@ -226,9 +242,15 @@ def service_request(s): + s.sendall(hipc_response) + return True + ++parser = optparse.OptionParser() ++parser.add_option('-c', '--credlist', action='store_true', dest='credlist', ++ default=False, help='Support KCM_OP_GET_CRED_LIST') ++(options, args) = parser.parse_args() ++if not options.credlist: ++ del ophandlers[KCMOpcodes.GET_CRED_LIST] + + server = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) +-server.bind(sys.argv[1]) ++server.bind(args[0]) + server.listen(5) + select_input = [server,] + sys.stderr.write('starting...\n') +diff --git a/src/tests/t_ccache.py b/src/tests/t_ccache.py +index 66804afa5..90040fb7b 100755 +--- a/src/tests/t_ccache.py ++++ b/src/tests/t_ccache.py +@@ -125,10 +125,18 @@ def collection_test(realm, ccname): + + + collection_test(realm, 'DIR:' + os.path.join(realm.testdir, 'cc')) ++ ++# Test KCM without and with GET_CRED_LIST support. + kcmserver_path = os.path.join(srctop, 'tests', 'kcmserver.py') +-realm.start_server([sys.executable, kcmserver_path, kcm_socket_path], ++kcmd = realm.start_server([sys.executable, kcmserver_path, kcm_socket_path], ++ 'starting...') ++collection_test(realm, 'KCM:') ++stop_daemon(kcmd) ++os.remove(kcm_socket_path) ++realm.start_server([sys.executable, kcmserver_path, '-c', kcm_socket_path], + 'starting...') + collection_test(realm, 'KCM:') ++ + if test_keyring: + def cleanup_keyring(anchor, name): + out = realm.run(['keyctl', 'list', anchor]) diff --git a/root/ppg/common/deps/krb5/rpm/Add-PAC-full-checksums.patch b/root/ppg/common/deps/krb5/rpm/Add-PAC-full-checksums.patch new file mode 100644 index 00000000..d4d69d46 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Add-PAC-full-checksums.patch @@ -0,0 +1,673 @@ +From bf3e55bcd66c5d35fddadc94fd680bdd57508bce Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Thu, 22 Dec 2022 03:05:23 -0500 +Subject: [PATCH] Add PAC full checksums + +A paper by Tom Tervoort noted that computing the PAC privsvr checksum +over only the server checksum is vulnerable to collision attacks +(CVE-2022-37967). In response, Microsoft has added a second KDC +checksum over the full contents of the PAC. Generate and verify full +KDC checksums in PACs for service tickets. Update the t_pac.c ticket +test case to use a ticket issued by a recent version of Active +Directory (provided by Stefan Metzmacher). + +ticket: 9084 (new) +--- + doc/appdev/refs/macros/index.rst | 1 + + src/include/krb5/krb5.hin | 1 + + src/lib/krb5/krb/pac.c | 92 +++++++++-------- + src/lib/krb5/krb/pac_sign.c | 146 +++++++++++++++----------- + src/lib/krb5/krb/t_pac.c | 171 ++++++++++++++++++------------- + src/tests/t_authdata.py | 5 +- + 6 files changed, 242 insertions(+), 174 deletions(-) + +diff --git a/doc/appdev/refs/macros/index.rst b/doc/appdev/refs/macros/index.rst +index c6ea088742..22ef2b2f42 100644 +--- a/doc/appdev/refs/macros/index.rst ++++ b/doc/appdev/refs/macros/index.rst +@@ -247,6 +247,7 @@ Public + KRB5_PAC_SERVER_CHECKSUM.rst + KRB5_PAC_TICKET_CHECKSUM.rst + KRB5_PAC_UPN_DNS_INFO.rst ++ KRB5_PAC_FULL_CHECKSUM.rst + KRB5_PADATA_AFS3_SALT.rst + KRB5_PADATA_AP_REQ.rst + KRB5_PADATA_AS_CHECKSUM.rst +diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin +index 8e59628bd9..12a1d441b8 100644 +--- a/src/include/krb5/krb5.hin ++++ b/src/include/krb5/krb5.hin +@@ -8187,6 +8187,7 @@ krb5_verify_authdata_kdc_issued(krb5_context context, + #define KRB5_PAC_TICKET_CHECKSUM 16 /**< Ticket checksum */ + #define KRB5_PAC_ATTRIBUTES_INFO 17 /**< PAC attributes */ + #define KRB5_PAC_REQUESTOR 18 /**< PAC requestor SID */ ++#define KRB5_PAC_FULL_CHECKSUM 19 /**< KDC full checksum */ + + struct krb5_pac_data; + /** PAC data structure to convey authorization information */ +diff --git a/src/lib/krb5/krb/pac.c b/src/lib/krb5/krb/pac.c +index 2f6ad4e1df..9c00178a28 100644 +--- a/src/lib/krb5/krb/pac.c ++++ b/src/lib/krb5/krb/pac.c +@@ -500,7 +500,8 @@ zero_signature(krb5_context context, const krb5_pac pac, krb5_ui_4 type, + size_t i; + + assert(type == KRB5_PAC_SERVER_CHECKSUM || +- type == KRB5_PAC_PRIVSVR_CHECKSUM); ++ type == KRB5_PAC_PRIVSVR_CHECKSUM || ++ type == KRB5_PAC_FULL_CHECKSUM); + assert(data->length >= pac->data.length); + + for (i = 0; i < pac->pac->cBuffers; i++) { +@@ -567,17 +568,17 @@ verify_checksum(krb5_context context, const krb5_pac pac, uint32_t buffer_type, + } + + static krb5_error_code +-verify_server_checksum(krb5_context context, const krb5_pac pac, +- const krb5_keyblock *server) ++verify_pac_checksums(krb5_context context, const krb5_pac pac, ++ krb5_boolean expect_full_checksum, ++ const krb5_keyblock *server, const krb5_keyblock *privsvr) + { + krb5_error_code ret; +- krb5_data copy; /* PAC with zeroed checksums */ ++ krb5_data copy, server_checksum; + ++ /* Make a copy of the PAC with zeroed out server and privsvr checksums. */ + ret = krb5int_copy_data_contents(context, &pac->data, ©); + if (ret) + return ret; +- +- /* Zero out both checksum buffers */ + ret = zero_signature(context, pac, KRB5_PAC_SERVER_CHECKSUM, ©); + if (ret) + goto cleanup; +@@ -585,32 +586,46 @@ verify_server_checksum(krb5_context context, const krb5_pac pac, + if (ret) + goto cleanup; + +- ret = verify_checksum(context, pac, KRB5_PAC_SERVER_CHECKSUM, server, +- KRB5_KEYUSAGE_APP_DATA_CKSUM, ©); ++ if (server != NULL) { ++ /* Verify the server checksum over the PAC copy. */ ++ ret = verify_checksum(context, pac, KRB5_PAC_SERVER_CHECKSUM, server, ++ KRB5_KEYUSAGE_APP_DATA_CKSUM, ©); ++ } + +-cleanup: +- free(copy.data); +- return ret; +-} ++ if (privsvr != NULL && expect_full_checksum) { ++ /* Zero the full checksum buffer in the copy and verify the full ++ * checksum over the copy with all three checksums zeroed. */ ++ ret = zero_signature(context, pac, KRB5_PAC_FULL_CHECKSUM, ©); ++ if (ret) ++ goto cleanup; ++ ret = verify_checksum(context, pac, KRB5_PAC_FULL_CHECKSUM, privsvr, ++ KRB5_KEYUSAGE_APP_DATA_CKSUM, ©); ++ if (ret) ++ goto cleanup; ++ } + +-static krb5_error_code +-verify_kdc_checksum(krb5_context context, const krb5_pac pac, +- const krb5_keyblock *privsvr) +-{ +- krb5_error_code ret; +- krb5_data server_checksum; ++ if (privsvr != NULL) { ++ /* Verify the privsvr checksum over the server checksum. */ ++ ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_SERVER_CHECKSUM, ++ &server_checksum); ++ if (ret) ++ return ret; ++ if (server_checksum.length < PAC_SIGNATURE_DATA_LENGTH) ++ return KRB5_BAD_MSIZE; ++ server_checksum.data += PAC_SIGNATURE_DATA_LENGTH; ++ server_checksum.length -= PAC_SIGNATURE_DATA_LENGTH; + +- ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_SERVER_CHECKSUM, +- &server_checksum); +- if (ret) +- return ret; +- if (server_checksum.length < PAC_SIGNATURE_DATA_LENGTH) +- return KRB5_BAD_MSIZE; +- server_checksum.data += PAC_SIGNATURE_DATA_LENGTH; +- server_checksum.length -= PAC_SIGNATURE_DATA_LENGTH; ++ ret = verify_checksum(context, pac, KRB5_PAC_PRIVSVR_CHECKSUM, privsvr, ++ KRB5_KEYUSAGE_APP_DATA_CKSUM, &server_checksum); ++ if (ret) ++ goto cleanup; ++ } ++ ++ pac->verified = TRUE; + +- return verify_checksum(context, pac, KRB5_PAC_PRIVSVR_CHECKSUM, privsvr, +- KRB5_KEYUSAGE_APP_DATA_CKSUM, &server_checksum); ++cleanup: ++ free(copy.data); ++ return ret; + } + + /* Per MS-PAC 2.8.3, tickets encrypted to TGS and password change principals +@@ -638,6 +653,7 @@ krb5_kdc_verify_ticket(krb5_context context, const krb5_enc_tkt_part *enc_tkt, + krb5_authdata **authdata, *orig, **ifrel = NULL, **recoded_ifrel = NULL; + uint8_t z = 0; + krb5_authdata zpac = { KV5M_AUTHDATA, KRB5_AUTHDATA_WIN2K_PAC, 1, &z }; ++ krb5_boolean is_service_tkt; + size_t i, j; + + *pac_out = NULL; +@@ -679,7 +695,8 @@ krb5_kdc_verify_ticket(krb5_context context, const krb5_enc_tkt_part *enc_tkt, + if (ret) + goto cleanup; + +- if (privsvr != NULL && k5_pac_should_have_ticket_signature(server_princ)) { ++ is_service_tkt = k5_pac_should_have_ticket_signature(server_princ); ++ if (privsvr != NULL && is_service_tkt) { + /* To check the PAC ticket signatures, re-encode the ticket with the + * PAC contents replaced by a single zero. */ + orig = ifrel[j]; +@@ -703,8 +720,9 @@ krb5_kdc_verify_ticket(krb5_context context, const krb5_enc_tkt_part *enc_tkt, + goto cleanup; + } + +- ret = krb5_pac_verify_ext(context, pac, enc_tkt->times.authtime, NULL, +- server, privsvr, FALSE); ++ ret = verify_pac_checksums(context, pac, is_service_tkt, server, privsvr); ++ if (ret) ++ goto cleanup; + + *pac_out = pac; + pac = NULL; +@@ -740,14 +758,8 @@ krb5_pac_verify_ext(krb5_context context, + { + krb5_error_code ret; + +- if (server != NULL) { +- ret = verify_server_checksum(context, pac, server); +- if (ret != 0) +- return ret; +- } +- +- if (privsvr != NULL) { +- ret = verify_kdc_checksum(context, pac, privsvr); ++ if (server != NULL || privsvr != NULL) { ++ ret = verify_pac_checksums(context, pac, FALSE, server, privsvr); + if (ret != 0) + return ret; + } +@@ -759,8 +771,6 @@ krb5_pac_verify_ext(krb5_context context, + return ret; + } + +- pac->verified = TRUE; +- + return 0; + } + +diff --git a/src/lib/krb5/krb/pac_sign.c b/src/lib/krb5/krb/pac_sign.c +index 0f9581abbb..8ea61ac17b 100644 +--- a/src/lib/krb5/krb/pac_sign.c ++++ b/src/lib/krb5/krb/pac_sign.c +@@ -187,26 +187,41 @@ k5_pac_encode_header(krb5_context context, krb5_pac pac) + return 0; + } + +-krb5_error_code KRB5_CALLCONV +-krb5_pac_sign(krb5_context context, krb5_pac pac, krb5_timestamp authtime, +- krb5_const_principal principal, const krb5_keyblock *server_key, +- const krb5_keyblock *privsvr_key, krb5_data *data) ++/* Find the buffer of type buftype in pac and write within it a checksum of ++ * type cksumtype over data. Set *cksum_out to the checksum. */ ++static krb5_error_code ++compute_pac_checksum(krb5_context context, krb5_pac pac, uint32_t buftype, ++ const krb5_keyblock *key, krb5_cksumtype cksumtype, ++ const krb5_data *data, krb5_data *cksum_out) + { +- return krb5_pac_sign_ext(context, pac, authtime, principal, server_key, +- privsvr_key, FALSE, data); ++ krb5_error_code ret; ++ krb5_data buf; ++ krb5_crypto_iov iov[2]; ++ ++ ret = k5_pac_locate_buffer(context, pac, buftype, &buf); ++ if (ret) ++ return ret; ++ ++ assert(buf.length > PAC_SIGNATURE_DATA_LENGTH); ++ *cksum_out = make_data(buf.data + PAC_SIGNATURE_DATA_LENGTH, ++ buf.length - PAC_SIGNATURE_DATA_LENGTH); ++ iov[0].flags = KRB5_CRYPTO_TYPE_DATA; ++ iov[0].data = *data; ++ iov[1].flags = KRB5_CRYPTO_TYPE_CHECKSUM; ++ iov[1].data = *cksum_out; ++ return krb5_c_make_checksum_iov(context, cksumtype, key, ++ KRB5_KEYUSAGE_APP_DATA_CKSUM, iov, 2); + } + +-krb5_error_code KRB5_CALLCONV +-krb5_pac_sign_ext(krb5_context context, krb5_pac pac, krb5_timestamp authtime, +- krb5_const_principal principal, +- const krb5_keyblock *server_key, +- const krb5_keyblock *privsvr_key, krb5_boolean with_realm, +- krb5_data *data) ++static krb5_error_code ++sign_pac(krb5_context context, krb5_pac pac, krb5_timestamp authtime, ++ krb5_const_principal principal, const krb5_keyblock *server_key, ++ const krb5_keyblock *privsvr_key, krb5_boolean with_realm, ++ krb5_boolean is_service_tkt, krb5_data *data) + { + krb5_error_code ret; +- krb5_data server_cksum, privsvr_cksum; ++ krb5_data full_cksum, server_cksum, privsvr_cksum; + krb5_cksumtype server_cksumtype, privsvr_cksumtype; +- krb5_crypto_iov iov[2]; + + data->length = 0; + data->data = NULL; +@@ -214,67 +229,53 @@ krb5_pac_sign_ext(krb5_context context, krb5_pac pac, krb5_timestamp authtime, + if (principal != NULL) { + ret = k5_insert_client_info(context, pac, authtime, principal, + with_realm); +- if (ret != 0) ++ if (ret) + return ret; + } + +- /* Create zeroed buffers for both checksums */ ++ /* Create zeroed buffers for all checksums. */ + ret = k5_insert_checksum(context, pac, KRB5_PAC_SERVER_CHECKSUM, + server_key, &server_cksumtype); +- if (ret != 0) ++ if (ret) + return ret; +- + ret = k5_insert_checksum(context, pac, KRB5_PAC_PRIVSVR_CHECKSUM, + privsvr_key, &privsvr_cksumtype); +- if (ret != 0) ++ if (ret) + return ret; ++ if (is_service_tkt) { ++ ret = k5_insert_checksum(context, pac, KRB5_PAC_FULL_CHECKSUM, ++ privsvr_key, &privsvr_cksumtype); ++ if (ret) ++ return ret; ++ } + +- /* Now, encode the PAC header so that the checksums will include it */ ++ /* Encode the PAC header so that the checksums will include it. */ + ret = k5_pac_encode_header(context, pac); +- if (ret != 0) +- return ret; +- +- /* Generate the server checksum over the entire PAC */ +- ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_SERVER_CHECKSUM, +- &server_cksum); +- if (ret != 0) ++ if (ret) + return ret; + +- assert(server_cksum.length > PAC_SIGNATURE_DATA_LENGTH); +- +- iov[0].flags = KRB5_CRYPTO_TYPE_DATA; +- iov[0].data = pac->data; +- +- iov[1].flags = KRB5_CRYPTO_TYPE_CHECKSUM; +- iov[1].data.data = server_cksum.data + PAC_SIGNATURE_DATA_LENGTH; +- iov[1].data.length = server_cksum.length - PAC_SIGNATURE_DATA_LENGTH; ++ if (is_service_tkt) { ++ /* Generate a full KDC checksum over the whole PAC. */ ++ ret = compute_pac_checksum(context, pac, KRB5_PAC_FULL_CHECKSUM, ++ privsvr_key, privsvr_cksumtype, ++ &pac->data, &full_cksum); ++ if (ret) ++ return ret; ++ } + +- ret = krb5_c_make_checksum_iov(context, server_cksumtype, +- server_key, KRB5_KEYUSAGE_APP_DATA_CKSUM, +- iov, sizeof(iov)/sizeof(iov[0])); +- if (ret != 0) ++ /* Generate the server checksum over the whole PAC, including the full KDC ++ * checksum if we added one. */ ++ ret = compute_pac_checksum(context, pac, KRB5_PAC_SERVER_CHECKSUM, ++ server_key, server_cksumtype, &pac->data, ++ &server_cksum); ++ if (ret) + return ret; + +- /* Generate the privsvr checksum over the server checksum buffer */ +- ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_PRIVSVR_CHECKSUM, ++ /* Generate the privsvr checksum over the server checksum buffer. */ ++ ret = compute_pac_checksum(context, pac, KRB5_PAC_PRIVSVR_CHECKSUM, ++ privsvr_key, privsvr_cksumtype, &server_cksum, + &privsvr_cksum); +- if (ret != 0) +- return ret; +- +- assert(privsvr_cksum.length > PAC_SIGNATURE_DATA_LENGTH); +- +- iov[0].flags = KRB5_CRYPTO_TYPE_DATA; +- iov[0].data.data = server_cksum.data + PAC_SIGNATURE_DATA_LENGTH; +- iov[0].data.length = server_cksum.length - PAC_SIGNATURE_DATA_LENGTH; +- +- iov[1].flags = KRB5_CRYPTO_TYPE_CHECKSUM; +- iov[1].data.data = privsvr_cksum.data + PAC_SIGNATURE_DATA_LENGTH; +- iov[1].data.length = privsvr_cksum.length - PAC_SIGNATURE_DATA_LENGTH; +- +- ret = krb5_c_make_checksum_iov(context, privsvr_cksumtype, +- privsvr_key, KRB5_KEYUSAGE_APP_DATA_CKSUM, +- iov, sizeof(iov)/sizeof(iov[0])); +- if (ret != 0) ++ if (ret) + return ret; + + data->data = k5memdup(pac->data.data, pac->data.length, &ret); +@@ -288,6 +289,26 @@ krb5_pac_sign_ext(krb5_context context, krb5_pac pac, krb5_timestamp authtime, + return 0; + } + ++krb5_error_code KRB5_CALLCONV ++krb5_pac_sign(krb5_context context, krb5_pac pac, krb5_timestamp authtime, ++ krb5_const_principal principal, const krb5_keyblock *server_key, ++ const krb5_keyblock *privsvr_key, krb5_data *data) ++{ ++ return sign_pac(context, pac, authtime, principal, server_key, ++ privsvr_key, FALSE, FALSE, data); ++} ++ ++krb5_error_code KRB5_CALLCONV ++krb5_pac_sign_ext(krb5_context context, krb5_pac pac, krb5_timestamp authtime, ++ krb5_const_principal principal, ++ const krb5_keyblock *server_key, ++ const krb5_keyblock *privsvr_key, krb5_boolean with_realm, ++ krb5_data *data) ++{ ++ return sign_pac(context, pac, authtime, principal, server_key, privsvr_key, ++ with_realm, FALSE, data); ++} ++ + /* Add a signature over der_enc_tkt in privsvr to pac. der_enc_tkt should be + * encoded with a dummy PAC authdata element containing a single zero byte. */ + static krb5_error_code +@@ -359,6 +380,7 @@ krb5_kdc_sign_ticket(krb5_context context, krb5_enc_tkt_part *enc_tkt, + krb5_error_code ret; + krb5_data *der_enc_tkt = NULL, pac_data = empty_data(); + krb5_authdata **list, *pac_ad; ++ krb5_boolean is_service_tkt; + size_t count; + + /* Reallocate space for another authdata element in enc_tkt. */ +@@ -377,7 +399,8 @@ krb5_kdc_sign_ticket(krb5_context context, krb5_enc_tkt_part *enc_tkt, + memmove(list + 1, list, (count + 1) * sizeof(*list)); + list[0] = pac_ad; + +- if (k5_pac_should_have_ticket_signature(server_princ)) { ++ is_service_tkt = k5_pac_should_have_ticket_signature(server_princ); ++ if (is_service_tkt) { + ret = encode_krb5_enc_tkt_part(enc_tkt, &der_enc_tkt); + if (ret) + goto cleanup; +@@ -388,9 +411,8 @@ krb5_kdc_sign_ticket(krb5_context context, krb5_enc_tkt_part *enc_tkt, + goto cleanup; + } + +- ret = krb5_pac_sign_ext(context, pac, enc_tkt->times.authtime, +- client_princ, server, privsvr, with_realm, +- &pac_data); ++ ret = sign_pac(context, pac, enc_tkt->times.authtime, client_princ, server, ++ privsvr, with_realm, is_service_tkt, &pac_data); + if (ret) + goto cleanup; + +diff --git a/src/lib/krb5/krb/t_pac.c b/src/lib/krb5/krb/t_pac.c +index 173bde7bab..81f1642ab0 100644 +--- a/src/lib/krb5/krb/t_pac.c ++++ b/src/lib/krb5/krb/t_pac.c +@@ -607,78 +607,102 @@ check_pac(krb5_context context, int index, const unsigned char *pdata, + + static const krb5_keyblock ticket_sig_krbtgt_key = { + 0, ENCTYPE_AES256_CTS_HMAC_SHA1_96, +- 32, U("\x7a\x58\x98\xd2\xaf\xa6\xaf\xc0\x6a\xce\x06\x04\x4b\xc2\x70\x84" +- "\x9b\x8e\x0a\x6c\x4c\x07\xdc\x6f\xbb\x48\x43\xe1\xd2\xaa\x97\xf7") ++ 32, U("\x03\x73\x81\xEC\x43\x96\x7B\xC2\xAC\x3D\xF5\x2A\xAE\x95\xA6\x8E" ++ "\xBE\x24\x58\xDB\xCE\x52\x28\x20\xAF\x5E\xB7\x04\xA2\x22\x71\x4F") + }; + + static const krb5_keyblock ticket_sig_server_key = { +- 0, ENCTYPE_ARCFOUR_HMAC, +- 16, U("\xed\x23\x11\x20\x7a\x21\x44\x20\xbf\xc0\x8d\x36\xf7\xf6\xb2\x3e") ++ 0, ENCTYPE_AES256_CTS_HMAC_SHA1_96, ++ 32, U("\x11\x4A\x84\xE3\x14\x8F\xAA\xB1\xFA\x7B\x53\x51\xB2\x8A\xC2\xF1" ++ "\xFD\x19\x6D\x61\xE0\xF3\xF2\x3E\x1F\xDB\xD3\xC1\x79\x7D\xC1\xEE") + }; + ++/* A ticket issued by an Active Directory KDC (Windows Server 2022), containing ++ * a PAC with a full checksum. */ + static const krb5_data ticket_data = { +- .length = 972, .data = +- "\x61\x82\x03\xC8\x30\x82\x03\xC4\xA0\x03\x02\x01\x05\xA1\x0A\x1B" +- "\x08\x43\x44\x4F\x4D\x2E\x43\x4F\x4D\xA2\x0F\x30\x0D\xA0\x03\x02" +- "\x01\x01\xA1\x06\x30\x04\x1B\x02\x73\x31\xA3\x82\x03\x9E\x30\x82" +- "\x03\x9A\xA0\x03\x02\x01\x17\xA1\x03\x02\x01\x03\xA2\x82\x03\x8C" +- "\x04\x82\x03\x88\x44\x31\x61\x20\x17\xC9\xFE\xBC\xAC\x46\xB5\x77" +- "\xE9\x68\x04\x4C\x9B\x31\x91\x0C\xC1\xD4\xDD\xEF\xC7\x34\x20\x08" +- "\x90\x91\xE8\x79\xE0\xB5\x03\x26\xA4\x65\xDE\xEC\x47\x03\x2A\x8F" +- "\x61\xE7\x4D\x38\x5A\x42\x95\x5A\xF9\x2F\x41\x2C\x2A\x6E\x60\xA1" +- "\xEB\x51\xB3\xBD\x4C\x00\x41\x2A\x44\x76\x08\x37\x1A\x51\xFD\x65" +- "\x67\x7E\xBF\x3D\x90\x86\xE3\x9A\x54\x6B\x67\xA8\x08\x7A\x73\xCC" +- "\xC3\xB7\x4B\xD5\x5C\x3A\x14\x6C\xC1\x5F\x54\x4B\x92\x55\xB4\xB7" +- "\x92\x23\x3F\x53\x89\x47\x8E\x1F\x8B\xB9\xDB\x3B\x93\xE8\x70\xE4" +- "\x24\xB8\x9D\xF0\x0E\x35\x28\xF8\x7A\x27\x5D\xF7\x25\x97\x9C\xF5" +- "\x9F\x9F\x64\x04\xF2\xA3\xAB\x11\x15\xB6\xDA\x18\xD6\x46\xD5\xE6" +- "\xB8\x08\xDE\x0A\x62\xFD\xF8\xAA\x52\x90\xD9\x67\x29\xB2\xCD\x06" +- "\xB6\xB0\x50\x2B\x3F\x0F\xA3\xA5\xBF\xAA\x6E\x40\x03\xD6\x5F\x02" +- "\xBC\xD8\x18\x47\x97\x09\xD7\xE4\x96\x3B\xCB\xEB\x92\x2C\x3C\x49" +- "\xFF\x1F\x71\xE0\x52\x94\x0F\x8B\x9F\xB8\x2A\xBB\x9C\xE2\xA3\xDD" +- "\x38\x89\xE2\xB1\x0B\x9E\x1F\x7A\xB3\xE3\xD2\xB0\x94\xDC\x87\xBE" +- "\x37\xA6\xD3\xB3\x29\x35\x9A\x72\xC3\x7A\xF1\xA9\xE6\xC5\xD1\x26" +- "\x83\x65\x44\x17\xBA\x55\xA8\x5E\x94\x26\xED\xE9\x8A\x93\x11\x5D" +- "\x7E\x20\x1B\x9C\x15\x9E\x13\x37\x03\x4D\xDD\x99\x51\xD8\x66\x29" +- "\x6A\xB9\xFB\x49\xFE\x52\x78\xDA\x86\x85\xA9\xA3\xB9\xEF\xEC\xAD" +- "\x35\xA6\x8D\xAC\x0F\x75\x22\xBB\x0B\x49\x1C\x13\x52\x40\xC9\x52" +- "\x69\x09\x54\xD1\x0F\x94\x3F\x22\x48\x67\xB0\x96\x28\xAA\xE6\x28" +- "\xD9\x0C\x08\xEF\x51\xED\x15\x5E\xA2\x53\x59\xA5\x03\xB4\x06\x20" +- "\x3D\xCC\xB4\xC5\xF8\x8C\x73\x67\xA3\x21\x3D\x19\xCD\xD4\x12\x28" +- "\xD2\x93\xDE\x0D\xF0\x71\x10\x50\xD6\x33\x35\x04\x11\x64\x43\x39" +- "\xC3\xDF\x96\xE3\x66\xE3\x85\xCA\xE7\x67\x14\x3A\xF0\x43\xAA\xBB" +- "\xD4\x1D\xB5\x24\xB5\x74\x90\x25\xA7\x87\x7E\xDB\xD3\x83\x8A\x3A" +- "\x69\xA8\x2D\xAF\xB7\xB8\xF3\xDC\x13\xAF\x45\x61\x3F\x59\x39\x7E" +- "\x69\xDE\x0C\x04\xF1\x10\x6B\xB4\x56\xFA\x21\x9F\x72\x2B\x60\x86" +- "\xE3\x23\x0E\xC4\x51\xF6\xBE\xD8\xE1\x5F\xEE\x73\x4C\x17\x4C\x2C" +- "\x1B\xFB\x9F\x1F\x7A\x3B\x07\x5B\x8E\xF1\x01\xAC\xD6\x30\x94\x8A" +- "\x5D\x22\x6F\x08\xCE\xED\x5E\xB6\xDB\x86\x8C\x87\xEB\x8D\x91\xFF" +- "\x0A\x86\x30\xBD\xC0\xF8\x25\xE7\xAE\x24\x35\xF2\xFC\xE5\xFD\x1B" +- "\xB0\x05\x4A\xA3\xE5\xEB\x2E\x05\xAD\x99\x67\x49\x87\xE6\xB3\x87" +- "\x82\xA4\x59\xA7\x6E\xDD\xF2\xB6\x66\xE8\xF7\x70\xF5\xBD\xC9\x0E" +- "\xFA\x9C\x79\x84\xD4\x9B\x05\x0E\xBB\xF5\xDB\xEF\xFC\xCC\x26\xF2" +- "\x93\xCF\xD2\x04\x3C\xA9\x2C\x65\x42\x97\x86\xD8\x38\x0A\x1E\xF6" +- "\xD6\xCA\x30\xB5\x1A\xEC\xFB\xBA\x3B\x84\x57\xB0\xFD\xFB\xE6\xBC" +- "\xF2\x76\xF6\x4C\xBB\xAB\xB1\x31\xA1\x27\x7C\xE6\xE6\x81\xB6\xCE" +- "\x84\x86\x40\xB6\x40\x33\xC4\xF8\xB4\x15\xCF\xAA\xA5\x51\x78\xB9" +- "\x8B\x50\x25\xB2\x88\x86\x96\x72\x8C\x71\x4D\xB5\x3A\x94\x86\x77" +- "\x0E\x95\x9B\x16\x93\xEF\x3A\x11\x79\xBA\x83\xF7\x74\xD3\x8D\xBA" +- "\x15\xE1\x2C\x04\x57\xA8\x92\x1E\x9D\x00\x8E\x20\xFD\x30\x70\xE7" +- "\xF5\x65\x2F\x19\x0C\x94\xBA\x03\x71\x12\x96\xCD\xC8\xB4\x96\xDB" +- "\xCE\x19\xC2\xDF\x3C\xC2\xF6\x3D\x53\xED\x98\xA5\x41\x72\x2A\x22" +- "\x7B\xF3\x2B\x17\x6C\xE1\x39\x7D\xAE\x9B\x11\xF9\xC1\xA6\x9E\x9F" +- "\x89\x3C\x12\xAA\x94\x74\xA7\x4F\x70\xE8\xB9\xDE\x04\xF0\x9D\x39" +- "\x24\x2D\x92\xE8\x46\x2D\x2E\xF0\x40\x66\x1A\xD9\x27\xF9\x98\xF1" +- "\x81\x1D\x70\x62\x63\x30\x6D\xCD\x84\x04\x5F\xFA\x83\xD3\xEC\x8D" +- "\x86\xFB\x40\x61\xC1\x8A\x45\xFF\x7B\xD9\xD4\x18\x61\x7F\x51\xE3" +- "\xFC\x1E\x18\xF0\xAF\xC6\x18\x2C\xE1\x6D\x5D\xF9\x62\xFC\x20\xA3" +- "\xB2\x8A\x5F\xE5\xBB\x29\x0F\x99\x63\x07\x88\x38\x3A\x3B\x73\x2A" +- "\x6D\xDA\x3D\xA8\x0D\x8F\x56\x41\x89\x82\xE5\xB8\x61\x00\x64\x7D" +- "\x17\x0C\xCE\x03\x55\x8F\xF4\x5B\x0D\x50\xF2\xEB\x05\x67\xBE\xDB" +- "\x7B\x75\xC5\xEA\xA1\xAB\x1D\xB0\x3C\x6D\x42\x08\x0B\x9A\x45\x20" +- "\xA8\x8F\xE5\x67\x47\x30\xDE\x93\x5F\x43\x05\xEB\xA8\x2D\x80\xF5" +- "\x1A\xB8\x4A\x4E\x42\x2D\x0B\x7A\xDC\x46\x20\x2D\x13\x17\xDD\x4B" +- "\x94\x96\xAA\x1F\x06\x0C\x1F\x62\x07\x9C\x40\xA1" ++ .length = 1307, .data = ++ "\x61\x82\x05\x17\x30\x82\x05\x13\xA0\x03\x02\x01\x05\xA1\x0F\x1B" ++ "\x0D\x57\x32\x30\x32\x32\x2D\x4C\x37\x2E\x42\x41\x53\x45\xA2\x2A" ++ "\x30\x28\xA0\x03\x02\x01\x01\xA1\x21\x30\x1F\x1B\x04\x63\x69\x66" ++ "\x73\x1B\x17\x77\x32\x30\x32\x32\x2D\x31\x31\x38\x2E\x77\x32\x30" ++ "\x32\x32\x2D\x6C\x37\x2E\x62\x61\x73\x65\xA3\x82\x04\xCD\x30\x82" ++ "\x04\xC9\xA0\x03\x02\x01\x12\xA1\x03\x02\x01\x05\xA2\x82\x04\xBB" ++ "\x04\x82\x04\xB7\x44\x5C\x7B\x5A\x3F\x2E\xA3\x50\x34\xDE\xB0\x69" ++ "\x23\x2D\x47\x89\x2C\xC0\xA3\xF9\xDD\x70\xAA\xA5\x1E\xFE\x74\xE5" ++ "\x19\xA2\x4F\x65\x6C\x9E\x00\xB4\x60\x00\x7C\x0C\x29\x43\x31\x99" ++ "\x77\x02\x73\xED\xB9\x40\xF5\xD2\xD1\xC9\x20\x0F\xE3\x38\xF9\xCC" ++ "\x5E\x2A\xBD\x1F\x91\x66\x1A\xD8\x2A\x80\x3C\x2C\x00\x3C\x1E\xC9" ++ "\x2A\x29\x19\x19\x96\x18\x54\x03\x97\x8F\x1D\x5F\xDB\xE9\x66\x68" ++ "\xCD\xB1\xD5\x00\x35\x69\x49\x45\xF1\x6A\x78\x7B\x37\x71\x87\x14" ++ "\x1C\x98\x4D\x69\xCB\x1B\xD8\xF5\xA3\xD8\x53\x4A\x75\x76\x62\xBA" ++ "\x6C\x3F\xEA\x8B\x97\x21\xCA\x8A\x46\x4B\x38\xDA\x09\x9F\x5A\xC8" ++ "\x38\xFF\x34\x97\x5B\xA2\xE5\xBA\xC9\x87\x17\xD8\x08\x05\x7A\x83" ++ "\x04\xD6\x02\x8E\x9B\x18\xB6\x40\x1A\xF7\x47\x25\x24\x3E\x37\x1E" ++ "\xF6\xC1\x3A\x1F\xCA\xB3\x43\x5A\xAE\x94\x83\x31\xAF\xFB\xEE\xED" ++ "\x46\x71\xEF\xE2\x37\x37\x15\xFE\x1B\x0B\x9E\xF8\x3E\x0C\x43\x96" ++ "\xB6\x0A\x04\x78\xF8\x5E\xAA\x33\x1F\xE2\x07\x5A\x8D\xC4\x4E\x32" ++ "\x6D\xD6\xA0\xC5\xEA\x3D\x12\x59\xD4\x41\x40\x4E\xA1\xD8\xBE\xED" ++ "\x17\xCB\x68\xCC\x59\xCB\x53\xB2\x0E\x58\x8A\xA9\x33\x7F\x6F\x2B" ++ "\x37\x89\x08\x44\xBA\xC7\x67\x17\xBB\x91\xF7\xC3\x0F\x00\xF8\xAA" ++ "\xA1\x33\xA6\x08\x47\xCA\xFA\xE8\x49\x27\x45\x46\xF1\xC1\xC3\x5F" ++ "\xE2\x45\x0A\x7D\x64\x52\x8C\x2E\xE1\xDE\xFF\xB2\x64\xEC\x69\x98" ++ "\x15\xDF\x9E\xB1\xEB\xD6\x9D\x08\x06\x4E\x73\xC1\x0B\x71\x21\x05" ++ "\x9E\xBC\xA2\x17\xCF\xB3\x70\xF4\xEF\xB8\x69\xA9\x94\x27\xFD\x5E" ++ "\x72\xB1\x2D\xD2\x20\x1B\x57\x80\xAB\x38\x97\xCF\x22\x68\x4F\xB8" ++ "\xB7\x17\x53\x25\x67\x0B\xED\xD1\x58\x20\x0D\x45\xF9\x09\xFA\xE7" ++ "\x61\x3E\xDB\xC2\x59\x7B\x3A\x3B\x59\x81\x51\xAA\xA4\x81\xF4\x96" ++ "\x3B\xE1\x6F\x6F\xF4\x8E\x68\x9E\xBA\x1E\x0F\xF2\x44\x68\x11\xFC" ++ "\x2B\x5F\xBE\xF2\xEA\x07\x80\xB9\xCA\x9E\x41\xBD\x2F\x81\xF5\x11" ++ "\x2A\x12\xF3\x4F\xD6\x12\x16\x0F\x21\x90\xF1\xD3\x1E\xF1\xA4\x94" ++ "\x46\xEA\x30\xF3\x84\x06\xC1\xA4\x51\xFC\x43\x35\xBD\xEF\x4D\x89" ++ "\x1D\xA5\x44\xB2\x69\xC4\x0F\xBF\x86\x01\x08\x44\x77\xD5\xB4\xB7" ++ "\x5C\x3F\xA7\xD4\x2F\x39\x73\x85\x88\xEE\xB1\x64\x1D\x80\x6C\xEE" ++ "\x6E\x31\x90\x92\x0D\xA1\xB7\xC4\x5C\xCC\xEE\x91\xC8\xCB\x11\x2D" ++ "\x4A\x1A\x7D\x43\x8F\xEB\x60\x09\xED\x1B\x07\x58\xBE\xBC\xBD\x29" ++ "\xF3\xB3\xA3\x4F\xC5\x8A\x30\x33\xB9\xA9\x9F\x43\x08\x27\x15\xC4" ++ "\x9C\x5D\x8E\xBD\x5C\x05\xC6\x05\x9C\x87\x60\x08\x1E\xE2\x52\xB8" ++ "\x45\x8D\x28\xB6\x2C\x15\x46\x74\x9F\x0E\xAA\x6B\x70\x3A\x2A\x55" ++ "\x45\x26\xB2\x58\x4D\x35\xA6\xF1\x96\xBE\x60\xB2\x71\x7B\xF8\x54" ++ "\xB9\x90\x21\x8E\xB9\x0F\x35\x98\x5E\x88\xEB\x1A\x53\xB4\x59\x7F" ++ "\xAF\x69\x1C\x61\x67\xF4\xF6\xBD\xAC\x24\xCD\xB7\xA9\x67\xE8\xA1" ++ "\x83\x85\x5F\x11\x74\x1F\xF7\x4C\x78\x36\xEF\x50\x74\x88\x58\x4B" ++ "\x1A\x9F\x84\x9A\x9A\x05\x92\xEC\x1D\xD5\xF3\xC4\x95\x51\x28\xE2" ++ "\x3F\x32\x87\xB2\xFD\x21\x27\x66\xE4\x6B\x85\x2F\xDC\x7B\xC0\x22" ++ "\xEB\x7A\x94\x20\x5A\x7B\xD3\x7A\xB9\x5B\xF8\x1A\x5A\x84\x4E\xA1" ++ "\x73\x41\x53\xD2\x60\xF7\x7C\xEE\x68\x59\x85\x80\xFC\x3D\x70\x4B" ++ "\x04\x32\xE7\xF2\xFD\xBD\xB3\xD9\x21\xE2\x37\x56\xA2\x16\xCC\xDE" ++ "\x8A\xD3\xBC\x71\xEF\x58\x19\x0E\x45\x8A\x5B\x53\xD6\x77\x30\x6A" ++ "\xA7\xF8\x68\x06\x4E\x07\xCA\xCE\x30\xD7\x35\xAB\x1A\xC7\x18\xD4" ++ "\xC6\x2F\x1A\xFF\xE9\x7A\x94\x0B\x76\x5E\x7E\x29\x0C\xE6\xD3\x3B" ++ "\x5B\x44\x96\xA8\xF1\x29\x23\x95\xD9\x79\xB3\x39\xFC\x76\xED\xE1" ++ "\x1E\x67\x4E\xF7\xE8\x7B\x7A\x12\x9E\xD8\x4B\x35\x09\x0A\xF2\xC1" ++ "\x63\x5B\xEE\xFD\x2A\xC2\xA6\x66\x30\x3C\x1F\x95\xAF\x65\x22\x95" ++ "\x14\x1D\xF5\xD5\xDC\x38\x79\x35\x1C\xCD\x24\x47\xE0\xFD\x08\xC8" ++ "\xF4\x15\x55\x9F\xD9\xC7\xAC\x3F\x67\xB3\x4F\xEB\x26\x7C\x8E\xD6" ++ "\x74\xB3\x0A\xCD\xE7\xFA\xBE\x7E\xA3\x3E\xEC\x61\x50\x77\x52\x56" ++ "\xCF\x90\x5D\x48\xFB\xD4\x2C\x6C\x61\x8B\xDD\x2B\xF5\x92\x1F\x30" ++ "\xBF\x3F\x80\x0D\x31\xDB\xB2\x0B\x7D\x84\xE3\xA6\x42\x7F\x00\x38" ++ "\x44\x02\xC5\xB8\xD9\x58\x29\x9D\x68\x5C\x32\x8B\x76\xAE\xED\x15" ++ "\xF9\x7C\xAE\x7B\xB6\x8E\xD6\x54\x24\xFF\xFA\x87\x05\xEF\x15\x08" ++ "\x5E\x4B\x21\xA2\x2F\x49\xE7\x0F\xC3\xD0\xB9\x49\x22\xEF\xD5\xCA" ++ "\xB2\x11\xF2\x17\xB6\x77\x24\x68\x76\xB2\x07\xF8\x0A\x73\xDD\x65" ++ "\x9C\x75\x64\xF7\xA1\xC6\x23\x08\x84\x72\x3E\x54\x2E\xEB\x9B\x40" ++ "\xA6\x83\x87\xEB\xB5\x00\x40\x4F\xE1\x72\x2A\x59\x3A\x06\x60\x29" ++ "\x7E\x25\x2F\xD8\x80\x40\x8C\x59\xCA\xCF\x8E\x44\xE4\x2D\x84\x7E" ++ "\xCB\xFD\x1E\x3B\xD5\xFF\x9A\xB9\x66\x93\x6D\x5E\xC8\xB7\x13\x26" ++ "\xD6\x38\x1B\x2B\xE1\x87\x96\x05\xD5\xF3\xAB\x68\xF7\x12\x62\x2C" ++ "\x58\xC1\xC9\x85\x3C\x72\xF1\x26\xEE\xC0\x09\x5F\x1D\x4B\xAC\x01" ++ "\x41\xC8\x12\xF8\xF3\x93\x43\x41\xFF\xEC\x0B\x80\xE2\xEE\x20\x85" ++ "\x25\xCD\x6C\x30\x8C\x0D\x24\x2E\xBA\x19\xEA\x28\x7F\xCF\xD5\x10" ++ "\x5C\xE9\xB2\x9D\x5F\x16\xE4\xC0\xF3\xCC\xD9\x68\x4A\x05\x08\x70" ++ "\x17\x26\xC8\x5C\x4A\xBF\x94\x6A\x0E\xD5\xDA\x67\x47\x4B\xAF\x44" ++ "\xE3\x94\xAA\x05\xDB\xA2\x49\x74\xFA\x5C\x69\xAB\x44\xB7\xF7\xBA" ++ "\xAE\x7A\x23\x87\xEB\x54\x7E\x80\xF1\x5B\x60\xA5\x93\xE5\xD4\x24" ++ "\x84\xF7\x0A\x16\x10\xBE\xE9\x4D\xD8\x6B\x15\x40\x5D\x74\xDA\x1B" ++ "\xFF\x2E\x4D\x17\x9D\x35\xF7\x0D\xCF\x66\x38\x0D\x8A\xE4\xDD\x6B" ++ "\xE1\x0F\x1F\xBD\xFD\x4F\x30\x37\x3F\x96\xB4\x92\x54\xD3\x9A\x7A" ++ "\xD1\x5B\x5B\xA9\x54\x16\xE6\x24\xAB\xD4\x23\x39\x7D\xD2\xC7\x09" ++ "\xFA\xD4\x86\x55\x4D\x60\xC2\x87\x67\x6B\xE6" + }; + + static void +@@ -686,7 +710,7 @@ test_pac_ticket_signature(krb5_context context) + { + krb5_error_code ret; + krb5_ticket *ticket; +- krb5_principal sprinc; ++ krb5_principal cprinc, sprinc; + krb5_authdata **authdata1, **authdata2; + krb5_pac pac, pac2, pac3; + uint32_t *list; +@@ -701,7 +725,13 @@ test_pac_ticket_signature(krb5_context context) + if (ret) + err(context, ret, "while decrypting ticket"); + +- ret = krb5_parse_name(context, "s1@CDOM.COM", &sprinc); ++ ret = krb5_parse_name(context, "administrator@W2022-L7.BASE", &cprinc); ++ if (ret) ++ err(context, ret, "krb5_parse_name"); ++ ++ ret = krb5_parse_name(context, ++ "cifs/w2022-118.w2022-l7.base@W2022-L7.BASE", ++ &sprinc); + if (ret) + err(context, ret, "krb5_parse_name"); + +@@ -713,7 +743,7 @@ test_pac_ticket_signature(krb5_context context) + + /* In this test, the server is also the client. */ + ret = krb5_pac_verify(context, pac, ticket->enc_part2->times.authtime, +- ticket->server, NULL, NULL); ++ cprinc, NULL, NULL); + if (ret) + err(context, ret, "while verifying PAC client info"); + +@@ -722,7 +752,7 @@ test_pac_ticket_signature(krb5_context context) + ticket->enc_part2->authorization_data = NULL; + + ret = krb5_kdc_sign_ticket(context, ticket->enc_part2, pac, sprinc, +- sprinc, &ticket_sig_server_key, ++ cprinc, &ticket_sig_server_key, + &ticket_sig_krbtgt_key, FALSE); + if (ret) + err(context, ret, "while signing ticket"); +@@ -781,6 +811,7 @@ test_pac_ticket_signature(krb5_context context) + krb5_pac_free(context, pac); + krb5_pac_free(context, pac2); + krb5_pac_free(context, pac3); ++ krb5_free_principal(context, cprinc); + krb5_free_principal(context, sprinc); + krb5_free_ticket(context, ticket); + } +diff --git a/src/tests/t_authdata.py b/src/tests/t_authdata.py +index 4fbdbec052..b0666c3b81 100644 +--- a/src/tests/t_authdata.py ++++ b/src/tests/t_authdata.py +@@ -11,7 +11,7 @@ realm = K5Realm(krb5_conf=conf) + # container. + mark('baseline authdata') + out = realm.run(['./adata', realm.host_princ]) +-if '?512: ' not in out or '^-42: Hello' not in out: ++if '?128: [6, 7, 10, 16, 19]' not in out or '^-42: Hello' not in out: + fail('expected authdata not seen for basic request') + + # Requested authdata is copied into the ticket, with KDC-only types +@@ -239,6 +239,9 @@ realm.run(['./s4u2proxy', usercache, 'service/2']) + out = realm.run(['./adata', '-p', realm.user_princ, 'service/2']) + if '+97: [indcl]' not in out or '[inds1]' in out: + fail('correct auth-indicator not seen for S4U2Proxy req') ++# Make sure a PAC with an S4U_DELEGATION_INFO(11) buffer is included. ++if '?128: [1, 6, 7, 10, 11, 16, 19]' not in out: ++ fail('PAC with delegation info not seen for S4U2Proxy req') + + # Get another S4U2Proxy ticket including request-authdata. + realm.run(['./s4u2proxy', usercache, 'service/2', '-2', 'proxy_ad']) +-- +2.39.2 + diff --git a/root/ppg/common/deps/krb5/rpm/Add-PAC-ticket-signature-APIs.patch b/root/ppg/common/deps/krb5/rpm/Add-PAC-ticket-signature-APIs.patch new file mode 100644 index 00000000..79f69c9c --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Add-PAC-ticket-signature-APIs.patch @@ -0,0 +1,840 @@ +From 48be25aaa27487fcbbba76044083de37211b30e7 Mon Sep 17 00:00:00 2001 +From: Isaac Boukris +Date: Fri, 7 Jan 2022 13:46:24 -0500 +Subject: [PATCH] Add PAC ticket signature APIs + +Microsoft added a third PAC signature over the ticket to prevent +servers from setting the forwardable flag on evidence tickets. Add +new APIs to generate and verify ticket signatures, as well as defines +for this and other new PAC buffer types. Deprecate the old signing +functions as they cannot generate ticket signatures. Modify several +error returns to better match the protocol errors generated by Active +Directory. + +[ghudson@mit.edu: adjusted contracts for KDC requirements; simplified +and commented code changes; wrote commit message. rharwood@redhat.com +also did some work on this commit.] + +ticket: 9043 (new) +--- + doc/appdev/refs/api/index.rst | 2 + + doc/appdev/refs/macros/index.rst | 6 + + src/include/krb5/krb5.hin | 98 +++++++++++------ + src/lib/krb5/krb/deps | 5 +- + src/lib/krb5/krb/int-proto.h | 12 ++ + src/lib/krb5/krb/pac.c | 148 ++++++++++++++++++++++++- + src/lib/krb5/krb/pac_sign.c | 121 ++++++++++++++++++++ + src/lib/krb5/krb/t_pac.c | 182 +++++++++++++++++++++++++++++++ + src/lib/krb5/libkrb5.exports | 2 + + src/lib/krb5_32.def | 3 + + src/plugins/kdb/test/kdb_test.c | 6 +- + 11 files changed, 544 insertions(+), 41 deletions(-) + +diff --git a/doc/appdev/refs/api/index.rst b/doc/appdev/refs/api/index.rst +index 9e03fd386f..d12be47c3c 100644 +--- a/doc/appdev/refs/api/index.rst ++++ b/doc/appdev/refs/api/index.rst +@@ -223,6 +223,8 @@ Rarely used public interfaces + krb5_init_creds_step.rst + krb5_init_keyblock.rst + krb5_is_referral_realm.rst ++ krb5_kdc_sign_ticket.rst ++ krb5_kdc_verify_ticket.rst + krb5_kt_add_entry.rst + krb5_kt_end_seq_get.rst + krb5_kt_get_entry.rst +diff --git a/doc/appdev/refs/macros/index.rst b/doc/appdev/refs/macros/index.rst +index 001fb386a7..c6ea088742 100644 +--- a/doc/appdev/refs/macros/index.rst ++++ b/doc/appdev/refs/macros/index.rst +@@ -234,12 +234,18 @@ Public + KRB5_NT_UNKNOWN.rst + KRB5_NT_WELLKNOWN.rst + KRB5_NT_X500_PRINCIPAL.rst ++ KRB5_PAC_ATTRIBUTES_INFO.rst + KRB5_PAC_CLIENT_INFO.rst ++ KRB5_PAC_CLIENT_CLAIMS.rst + KRB5_PAC_CREDENTIALS_INFO.rst + KRB5_PAC_DELEGATION_INFO.rst ++ KRB5_PAC_DEVICE_CLAIMS.rst ++ KRB5_PAC_DEVICE_INFO.rst + KRB5_PAC_LOGON_INFO.rst + KRB5_PAC_PRIVSVR_CHECKSUM.rst ++ KRB5_PAC_REQUESTOR.rst + KRB5_PAC_SERVER_CHECKSUM.rst ++ KRB5_PAC_TICKET_CHECKSUM.rst + KRB5_PAC_UPN_DNS_INFO.rst + KRB5_PADATA_AFS3_SALT.rst + KRB5_PADATA_AP_REQ.rst +diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin +index a7060aa733..8e59628bd9 100644 +--- a/src/include/krb5/krb5.hin ++++ b/src/include/krb5/krb5.hin +@@ -1918,7 +1918,7 @@ krb5_verify_checksum(krb5_context context, krb5_cksumtype ctype, + #define KRB5_AUTHDATA_CAMMAC 96 + #define KRB5_AUTHDATA_WIN2K_PAC 128 + #define KRB5_AUTHDATA_ETYPE_NEGOTIATION 129 /**< RFC 4537 */ +-#define KRB5_AUTHDATA_SIGNTICKET 512 /**< formerly 142 in krb5 1.8 */ ++#define KRB5_AUTHDATA_SIGNTICKET 512 /**< @deprecated use PAC */ + #define KRB5_AUTHDATA_FX_ARMOR 71 + #define KRB5_AUTHDATA_AUTH_INDICATOR 97 + #define KRB5_AUTHDATA_AP_OPTIONS 143 +@@ -8181,6 +8181,12 @@ krb5_verify_authdata_kdc_issued(krb5_context context, + #define KRB5_PAC_CLIENT_INFO 10 /**< Client name and ticket info */ + #define KRB5_PAC_DELEGATION_INFO 11 /**< Constrained delegation info */ + #define KRB5_PAC_UPN_DNS_INFO 12 /**< User principal name and DNS info */ ++#define KRB5_PAC_CLIENT_CLAIMS 13 /**< Client claims information */ ++#define KRB5_PAC_DEVICE_INFO 14 /**< Device information */ ++#define KRB5_PAC_DEVICE_CLAIMS 15 /**< Device claims information */ ++#define KRB5_PAC_TICKET_CHECKSUM 16 /**< Ticket checksum */ ++#define KRB5_PAC_ATTRIBUTES_INFO 17 /**< PAC attributes */ ++#define KRB5_PAC_REQUESTOR 18 /**< PAC requestor SID */ + + struct krb5_pac_data; + /** PAC data structure to convey authorization information */ +@@ -8338,56 +8344,84 @@ krb5_pac_verify_ext(krb5_context context, const krb5_pac pac, + krb5_boolean with_realm); + + /** +- * Sign a PAC. ++ * Verify a PAC, possibly including ticket signature + * +- * @param [in] context Library context +- * @param [in] pac PAC handle +- * @param [in] authtime Expected timestamp +- * @param [in] principal Expected principal name (or NULL) +- * @param [in] server_key Key for server checksum +- * @param [in] privsvr_key Key for KDC checksum +- * @param [out] data Signed PAC encoding ++ * @param [in] context Library context ++ * @param [in] enc_tkt Ticket enc-part, possibly containing a PAC ++ * @param [in] server_princ Canonicalized name of ticket server ++ * @param [in] server Key to validate server checksum (or NULL) ++ * @param [in] privsvr Key to validate KDC checksum (or NULL) ++ * @param [out] pac_out Verified PAC (NULL if no PAC included) + * +- * This function signs @a pac using the keys @a server_key and @a privsvr_key +- * and returns the signed encoding in @a data. @a pac is modified to include +- * the server and KDC checksum buffers. Use krb5_free_data_contents() to free +- * @a data when it is no longer needed. ++ * If a PAC is present in @a enc_tkt, verify its signatures. If @a privsvr is ++ * not NULL and @a server_princ is not a krbtgt or kadmin/changepw service, ++ * require a ticket signature over @a enc_tkt in addition to the KDC signature. ++ * Place the verified PAC in @a pac_out. If an invalid PAC signature is found, ++ * return an error matching the Windows KDC protocol code for that condition as ++ * closely as possible. + * +- * @version New in 1.10 ++ * If no PAC is present in @a enc_tkt, set @a pac_out to NULL and return ++ * successfully. ++ * ++ * @note This function does not validate the PAC_CLIENT_INFO buffer. If a ++ * specific value is expected, the caller can make a separate call to ++ * krb5_pac_verify_ext() with a principal but no keys. ++ * ++ * @retval 0 Success; otherwise - Kerberos error codes ++ * ++ * @version New in 1.20 + */ + krb5_error_code KRB5_CALLCONV ++krb5_kdc_verify_ticket(krb5_context context, const krb5_enc_tkt_part *enc_tkt, ++ krb5_const_principal server_princ, ++ const krb5_keyblock *server, ++ const krb5_keyblock *privsvr, krb5_pac *pac_out); ++ ++/** @deprecated Use krb5_kdc_sign_ticket() instead. */ ++krb5_error_code KRB5_CALLCONV + krb5_pac_sign(krb5_context context, krb5_pac pac, krb5_timestamp authtime, + krb5_const_principal principal, const krb5_keyblock *server_key, + const krb5_keyblock *privsvr_key, krb5_data *data); + ++/** @deprecated Use krb5_kdc_sign_ticket() instead. */ ++krb5_error_code KRB5_CALLCONV ++krb5_pac_sign_ext(krb5_context context, krb5_pac pac, krb5_timestamp authtime, ++ krb5_const_principal principal, ++ const krb5_keyblock *server_key, ++ const krb5_keyblock *privsvr_key, krb5_boolean with_realm, ++ krb5_data *data); ++ + /** +- * Sign a PAC, possibly with a specified realm. ++ * Sign a PAC, possibly including a ticket signature + * + * @param [in] context Library context ++ * @param [in] enc_tkt The ticket for the signature + * @param [in] pac PAC handle +- * @param [in] authtime Expected timestamp +- * @param [in] principal Principal name (or NULL) +- * @param [in] server_key Key for server checksum +- * @param [in] privsvr_key Key for KDC checksum ++ * @param [in] server_princ Canonical ticket server name ++ * @param [in] client_princ PAC_CLIENT_INFO principal (or NULL) ++ * @param [in] server Key for server checksum ++ * @param [in] privsvr Key for KDC and ticket checksum + * @param [in] with_realm If true, include the realm of @a principal +- * @param [out] data Signed PAC encoding + * +- * This function is similar to krb5_pac_sign(), but adds a parameter +- * @a with_realm. If @a with_realm is true, the PAC_CLIENT_INFO field of the +- * signed PAC will include the realm of @a principal as well as the name. This +- * flag is necessary to generate PACs for cross-realm S4U2Self referrals. ++ * Sign @a pac using the keys @a server and @a privsvr. Include a ticket ++ * signature over @a enc_tkt if @a server_princ is not a TGS or kadmin/changepw ++ * principal name. Add the signed PAC's encoding to the authorization data of ++ * @a enc_tkt in the first slot, wrapped in an AD-IF-RELEVANT container. If @a ++ * client_princ is non-null, add a PAC_CLIENT_INFO buffer, including the realm ++ * if @a with_realm is true. + * +- * @version New in 1.17 ++ * @retval 0 on success, otherwise - Kerberos error codes ++ * ++ * @version New in 1.20 + */ + krb5_error_code KRB5_CALLCONV +-krb5_pac_sign_ext(krb5_context context, krb5_pac pac, krb5_timestamp authtime, +- krb5_const_principal principal, +- const krb5_keyblock *server_key, +- const krb5_keyblock *privsvr_key, krb5_boolean with_realm, +- krb5_data *data); ++krb5_kdc_sign_ticket(krb5_context context, krb5_enc_tkt_part *enc_tkt, ++ const krb5_pac pac, krb5_const_principal server_princ, ++ krb5_const_principal client_princ, ++ const krb5_keyblock *server, const krb5_keyblock *privsvr, ++ krb5_boolean with_realm); + +- +-/* ++/** + * Read client information from a PAC. + * + * @param [in] context Library context +diff --git a/src/lib/krb5/krb/deps b/src/lib/krb5/krb/deps +index 439ca02725..cd842b03cd 100644 +--- a/src/lib/krb5/krb/deps ++++ b/src/lib/krb5/krb/deps +@@ -709,7 +709,7 @@ pac.so pac.po $(OUTPRE)pac.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(top_srcdir)/include/k5-utf8.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ +- authdata.h pac.c ++ authdata.h int-proto.h pac.c + pac_sign.so pac_sign.po $(OUTPRE)pac_sign.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ +@@ -720,7 +720,8 @@ pac_sign.so pac_sign.po $(OUTPRE)pac_sign.$(OBJEXT): \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/k5-utf8.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ +- $(top_srcdir)/include/socket-utils.h authdata.h pac_sign.c ++ $(top_srcdir)/include/socket-utils.h authdata.h int-proto.h \ ++ pac_sign.c + padata.so padata.po $(OUTPRE)padata.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ +diff --git a/src/lib/krb5/krb/int-proto.h b/src/lib/krb5/krb/int-proto.h +index fe61bebf5b..453ed60c6c 100644 +--- a/src/lib/krb5/krb/int-proto.h ++++ b/src/lib/krb5/krb/int-proto.h +@@ -386,4 +386,16 @@ k5_get_proxy_cred_from_kdc(krb5_context context, krb5_flags options, + krb5_ccache ccache, krb5_creds *in_creds, + krb5_creds **out_creds); + ++/* Return true if mprinc will match any hostname in a host-based principal name ++ * (possibly due to ignore_acceptor_hostname) with krb5_sname_match(). */ ++krb5_boolean ++k5_sname_wildcard_host(krb5_context context, krb5_const_principal mprinc); ++ ++/* Guess the appropriate name-type for a principal based on the name. */ ++krb5_int32 ++k5_infer_principal_type(krb5_principal princ); ++ ++krb5_boolean ++k5_pac_should_have_ticket_signature(krb5_const_principal sprinc); ++ + #endif /* KRB5_INT_FUNC_PROTO__ */ +diff --git a/src/lib/krb5/krb/pac.c b/src/lib/krb5/krb/pac.c +index 1b9ef12276..6eb23d8090 100644 +--- a/src/lib/krb5/krb/pac.c ++++ b/src/lib/krb5/krb/pac.c +@@ -25,6 +25,7 @@ + */ + + #include "k5-int.h" ++#include "int-proto.h" + #include "authdata.h" + + #define MAX_BUFFERS 4096 +@@ -552,8 +553,10 @@ k5_pac_verify_server_checksum(krb5_context context, + checksum.checksum_type = load_32_le(p); + checksum.length = checksum_data.length - PAC_SIGNATURE_DATA_LENGTH; + checksum.contents = p + PAC_SIGNATURE_DATA_LENGTH; ++ if (checksum.checksum_type == CKSUMTYPE_SHA1) ++ return KRB5KDC_ERR_SUMTYPE_NOSUPP; + if (!krb5_c_is_keyed_cksum(checksum.checksum_type)) +- return KRB5KRB_AP_ERR_INAPP_CKSUM; ++ return KRB5KRB_ERR_GENERIC; + + pac_data.length = pac->data.length; + pac_data.data = k5memdup(pac->data.data, pac->data.length, &ret); +@@ -586,7 +589,7 @@ k5_pac_verify_server_checksum(krb5_context context, + } + + if (valid == FALSE) +- ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; ++ ret = KRB5KRB_AP_ERR_MODIFIED; + + return ret; + } +@@ -623,7 +626,7 @@ k5_pac_verify_kdc_checksum(krb5_context context, + checksum.length = privsvr_checksum.length - PAC_SIGNATURE_DATA_LENGTH; + checksum.contents = p + PAC_SIGNATURE_DATA_LENGTH; + if (!krb5_c_is_keyed_cksum(checksum.checksum_type)) +- return KRB5KRB_AP_ERR_INAPP_CKSUM; ++ return KRB5KRB_ERR_GENERIC; + + server_checksum.data += PAC_SIGNATURE_DATA_LENGTH; + server_checksum.length -= PAC_SIGNATURE_DATA_LENGTH; +@@ -635,11 +638,148 @@ k5_pac_verify_kdc_checksum(krb5_context context, + return ret; + + if (valid == FALSE) +- ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; ++ ret = KRB5KRB_AP_ERR_MODIFIED; + + return ret; + } + ++static krb5_error_code ++verify_ticket_checksum(krb5_context context, const krb5_pac pac, ++ const krb5_data *ticket, const krb5_keyblock *privsvr) ++{ ++ krb5_error_code ret; ++ krb5_checksum checksum; ++ krb5_data checksum_data; ++ krb5_boolean valid; ++ krb5_octet *p; ++ ++ ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_TICKET_CHECKSUM, ++ &checksum_data); ++ if (ret != 0) ++ return KRB5KRB_AP_ERR_MODIFIED; ++ ++ if (checksum_data.length < PAC_SIGNATURE_DATA_LENGTH) ++ return KRB5_BAD_MSIZE; ++ ++ p = (krb5_octet *)checksum_data.data; ++ checksum.checksum_type = load_32_le(p); ++ checksum.length = checksum_data.length - PAC_SIGNATURE_DATA_LENGTH; ++ checksum.contents = p + PAC_SIGNATURE_DATA_LENGTH; ++ if (!krb5_c_is_keyed_cksum(checksum.checksum_type)) ++ return KRB5KRB_ERR_GENERIC; ++ ++ ret = krb5_c_verify_checksum(context, privsvr, ++ KRB5_KEYUSAGE_APP_DATA_CKSUM, ticket, ++ &checksum, &valid); ++ if (ret != 0) ++ return ret; ++ ++ return valid ? 0 : KRB5KRB_AP_ERR_MODIFIED; ++} ++ ++/* Per MS-PAC 2.8.3, tickets encrypted to TGS and password change principals ++ * should not have ticket signatures. */ ++krb5_boolean ++k5_pac_should_have_ticket_signature(krb5_const_principal sprinc) ++{ ++ if (IS_TGS_PRINC(sprinc)) ++ return FALSE; ++ if (sprinc->length == 2 && data_eq_string(sprinc->data[0], "kadmin") && ++ data_eq_string(sprinc->data[1], "changepw")) ++ return FALSE; ++ return TRUE; ++} ++ ++krb5_error_code KRB5_CALLCONV ++krb5_kdc_verify_ticket(krb5_context context, const krb5_enc_tkt_part *enc_tkt, ++ krb5_const_principal server_princ, ++ const krb5_keyblock *server, ++ const krb5_keyblock *privsvr, krb5_pac *pac_out) ++{ ++ krb5_error_code ret; ++ krb5_pac pac = NULL; ++ krb5_data *recoded_tkt = NULL; ++ krb5_authdata **authdata, *orig, **ifrel = NULL, **recoded_ifrel = NULL; ++ uint8_t z = 0; ++ krb5_authdata zpac = { KV5M_AUTHDATA, KRB5_AUTHDATA_WIN2K_PAC, 1, &z }; ++ size_t i, j; ++ ++ *pac_out = NULL; ++ ++ /* ++ * Find the position of the PAC in the ticket authdata. ifrel will be the ++ * decoded AD-IF-RELEVANT container at position i containing a PAC, and j ++ * will be the offset within the container. ++ */ ++ authdata = enc_tkt->authorization_data; ++ for (i = 0; authdata != NULL && authdata[i] != NULL; i++) { ++ if (authdata[i]->ad_type != KRB5_AUTHDATA_IF_RELEVANT) ++ continue; ++ ++ ret = krb5_decode_authdata_container(context, ++ KRB5_AUTHDATA_IF_RELEVANT, ++ authdata[i], &ifrel); ++ if (ret) ++ goto cleanup; ++ ++ for (j = 0; ifrel[j] != NULL; j++) { ++ if (ifrel[j]->ad_type == KRB5_AUTHDATA_WIN2K_PAC) ++ break; ++ } ++ if (ifrel[j] != NULL) ++ break; ++ ++ krb5_free_authdata(context, ifrel); ++ ifrel = NULL; ++ } ++ ++ /* Stop and return successfully if we didn't find a PAC. */ ++ if (ifrel == NULL) { ++ ret = 0; ++ goto cleanup; ++ } ++ ++ ret = krb5_pac_parse(context, ifrel[j]->contents, ifrel[j]->length, &pac); ++ if (ret) ++ goto cleanup; ++ ++ if (privsvr != NULL && k5_pac_should_have_ticket_signature(server_princ)) { ++ /* To check the PAC ticket signatures, re-encode the ticket with the ++ * PAC contents replaced by a single zero. */ ++ orig = ifrel[j]; ++ ifrel[j] = &zpac; ++ ret = krb5_encode_authdata_container(context, ++ KRB5_AUTHDATA_IF_RELEVANT, ++ ifrel, &recoded_ifrel); ++ ifrel[j] = orig; ++ if (ret) ++ goto cleanup; ++ orig = authdata[i]; ++ authdata[i] = recoded_ifrel[0]; ++ ret = encode_krb5_enc_tkt_part(enc_tkt, &recoded_tkt); ++ authdata[i] = orig; ++ if (ret) ++ goto cleanup; ++ ++ ret = verify_ticket_checksum(context, pac, recoded_tkt, privsvr); ++ if (ret) ++ goto cleanup; ++ } ++ ++ ret = krb5_pac_verify_ext(context, pac, enc_tkt->times.authtime, NULL, ++ server, privsvr, FALSE); ++ ++ *pac_out = pac; ++ pac = NULL; ++ ++cleanup: ++ krb5_pac_free(context, pac); ++ krb5_free_data(context, recoded_tkt); ++ krb5_free_authdata(context, ifrel); ++ krb5_free_authdata(context, recoded_ifrel); ++ return ret; ++} ++ + krb5_error_code KRB5_CALLCONV + krb5_pac_verify(krb5_context context, + const krb5_pac pac, +diff --git a/src/lib/krb5/krb/pac_sign.c b/src/lib/krb5/krb/pac_sign.c +index 12f0259b4f..0f9581abbb 100644 +--- a/src/lib/krb5/krb/pac_sign.c ++++ b/src/lib/krb5/krb/pac_sign.c +@@ -25,6 +25,7 @@ + */ + + #include "k5-int.h" ++#include "int-proto.h" + #include "authdata.h" + + /* draft-brezak-win2k-krb-authz-00 */ +@@ -286,3 +287,123 @@ krb5_pac_sign_ext(krb5_context context, krb5_pac pac, krb5_timestamp authtime, + + return 0; + } ++ ++/* Add a signature over der_enc_tkt in privsvr to pac. der_enc_tkt should be ++ * encoded with a dummy PAC authdata element containing a single zero byte. */ ++static krb5_error_code ++add_ticket_signature(krb5_context context, const krb5_pac pac, ++ krb5_data *der_enc_tkt, const krb5_keyblock *privsvr) ++{ ++ krb5_error_code ret; ++ krb5_data ticket_cksum; ++ krb5_cksumtype ticket_cksumtype; ++ krb5_crypto_iov iov[2]; ++ ++ /* Create zeroed buffer for checksum. */ ++ ret = k5_insert_checksum(context, pac, KRB5_PAC_TICKET_CHECKSUM, ++ privsvr, &ticket_cksumtype); ++ if (ret) ++ return ret; ++ ++ ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_TICKET_CHECKSUM, ++ &ticket_cksum); ++ if (ret) ++ return ret; ++ ++ iov[0].flags = KRB5_CRYPTO_TYPE_DATA; ++ iov[0].data = *der_enc_tkt; ++ iov[1].flags = KRB5_CRYPTO_TYPE_CHECKSUM; ++ iov[1].data = make_data(ticket_cksum.data + PAC_SIGNATURE_DATA_LENGTH, ++ ticket_cksum.length - PAC_SIGNATURE_DATA_LENGTH); ++ ret = krb5_c_make_checksum_iov(context, ticket_cksumtype, privsvr, ++ KRB5_KEYUSAGE_APP_DATA_CKSUM, iov, 2); ++ if (ret) ++ return ret; ++ ++ store_32_le(ticket_cksumtype, ticket_cksum.data); ++ return 0; ++} ++ ++/* Set *out to an AD-IF-RELEVANT authdata element containing a PAC authdata ++ * element with contents pac_data. */ ++static krb5_error_code ++encode_pac_ad(krb5_context context, krb5_data *pac_data, krb5_authdata **out) ++{ ++ krb5_error_code ret; ++ krb5_authdata *container[2], **encoded_container = NULL; ++ krb5_authdata pac_ad = { KV5M_AUTHDATA, KRB5_AUTHDATA_WIN2K_PAC }; ++ uint8_t z = 0; ++ ++ pac_ad.contents = (pac_data != NULL) ? (uint8_t *)pac_data->data : &z; ++ pac_ad.length = (pac_data != NULL) ? pac_data->length : 1; ++ container[0] = &pac_ad; ++ container[1] = NULL; ++ ++ ret = krb5_encode_authdata_container(context, KRB5_AUTHDATA_IF_RELEVANT, ++ container, &encoded_container); ++ if (ret) ++ return ret; ++ ++ *out = encoded_container[0]; ++ free(encoded_container); ++ return 0; ++} ++ ++krb5_error_code KRB5_CALLCONV ++krb5_kdc_sign_ticket(krb5_context context, krb5_enc_tkt_part *enc_tkt, ++ const krb5_pac pac, krb5_const_principal server_princ, ++ krb5_const_principal client_princ, ++ const krb5_keyblock *server, const krb5_keyblock *privsvr, ++ krb5_boolean with_realm) ++{ ++ krb5_error_code ret; ++ krb5_data *der_enc_tkt = NULL, pac_data = empty_data(); ++ krb5_authdata **list, *pac_ad; ++ size_t count; ++ ++ /* Reallocate space for another authdata element in enc_tkt. */ ++ list = enc_tkt->authorization_data; ++ for (count = 0; list != NULL && list[count] != NULL; count++); ++ list = realloc(enc_tkt->authorization_data, (count + 2) * sizeof(*list)); ++ if (list == NULL) ++ return ENOMEM; ++ list[count] = NULL; ++ enc_tkt->authorization_data = list; ++ ++ /* Create a dummy PAC for ticket signing and make it the first element. */ ++ ret = encode_pac_ad(context, NULL, &pac_ad); ++ if (ret) ++ goto cleanup; ++ memmove(list + 1, list, (count + 1) * sizeof(*list)); ++ list[0] = pac_ad; ++ ++ if (k5_pac_should_have_ticket_signature(server_princ)) { ++ ret = encode_krb5_enc_tkt_part(enc_tkt, &der_enc_tkt); ++ if (ret) ++ goto cleanup; ++ ++ assert(privsvr != NULL); ++ ret = add_ticket_signature(context, pac, der_enc_tkt, privsvr); ++ if (ret) ++ goto cleanup; ++ } ++ ++ ret = krb5_pac_sign_ext(context, pac, enc_tkt->times.authtime, ++ client_princ, server, privsvr, with_realm, ++ &pac_data); ++ if (ret) ++ goto cleanup; ++ ++ /* Replace the dummy PAC with the signed real one. */ ++ ret = encode_pac_ad(context, &pac_data, &pac_ad); ++ if (ret) ++ goto cleanup; ++ free(list[0]->contents); ++ free(list[0]); ++ list[0] = pac_ad; ++ ++cleanup: ++ krb5_free_data(context, der_enc_tkt); ++ krb5_free_data_contents(context, &pac_data); ++ return ret; ++} +diff --git a/src/lib/krb5/krb/t_pac.c b/src/lib/krb5/krb/t_pac.c +index ccd165380d..173bde7bab 100644 +--- a/src/lib/krb5/krb/t_pac.c ++++ b/src/lib/krb5/krb/t_pac.c +@@ -605,6 +605,186 @@ check_pac(krb5_context context, int index, const unsigned char *pdata, + krb5_pac_free(context, pac); + } + ++static const krb5_keyblock ticket_sig_krbtgt_key = { ++ 0, ENCTYPE_AES256_CTS_HMAC_SHA1_96, ++ 32, U("\x7a\x58\x98\xd2\xaf\xa6\xaf\xc0\x6a\xce\x06\x04\x4b\xc2\x70\x84" ++ "\x9b\x8e\x0a\x6c\x4c\x07\xdc\x6f\xbb\x48\x43\xe1\xd2\xaa\x97\xf7") ++}; ++ ++static const krb5_keyblock ticket_sig_server_key = { ++ 0, ENCTYPE_ARCFOUR_HMAC, ++ 16, U("\xed\x23\x11\x20\x7a\x21\x44\x20\xbf\xc0\x8d\x36\xf7\xf6\xb2\x3e") ++}; ++ ++static const krb5_data ticket_data = { ++ .length = 972, .data = ++ "\x61\x82\x03\xC8\x30\x82\x03\xC4\xA0\x03\x02\x01\x05\xA1\x0A\x1B" ++ "\x08\x43\x44\x4F\x4D\x2E\x43\x4F\x4D\xA2\x0F\x30\x0D\xA0\x03\x02" ++ "\x01\x01\xA1\x06\x30\x04\x1B\x02\x73\x31\xA3\x82\x03\x9E\x30\x82" ++ "\x03\x9A\xA0\x03\x02\x01\x17\xA1\x03\x02\x01\x03\xA2\x82\x03\x8C" ++ "\x04\x82\x03\x88\x44\x31\x61\x20\x17\xC9\xFE\xBC\xAC\x46\xB5\x77" ++ "\xE9\x68\x04\x4C\x9B\x31\x91\x0C\xC1\xD4\xDD\xEF\xC7\x34\x20\x08" ++ "\x90\x91\xE8\x79\xE0\xB5\x03\x26\xA4\x65\xDE\xEC\x47\x03\x2A\x8F" ++ "\x61\xE7\x4D\x38\x5A\x42\x95\x5A\xF9\x2F\x41\x2C\x2A\x6E\x60\xA1" ++ "\xEB\x51\xB3\xBD\x4C\x00\x41\x2A\x44\x76\x08\x37\x1A\x51\xFD\x65" ++ "\x67\x7E\xBF\x3D\x90\x86\xE3\x9A\x54\x6B\x67\xA8\x08\x7A\x73\xCC" ++ "\xC3\xB7\x4B\xD5\x5C\x3A\x14\x6C\xC1\x5F\x54\x4B\x92\x55\xB4\xB7" ++ "\x92\x23\x3F\x53\x89\x47\x8E\x1F\x8B\xB9\xDB\x3B\x93\xE8\x70\xE4" ++ "\x24\xB8\x9D\xF0\x0E\x35\x28\xF8\x7A\x27\x5D\xF7\x25\x97\x9C\xF5" ++ "\x9F\x9F\x64\x04\xF2\xA3\xAB\x11\x15\xB6\xDA\x18\xD6\x46\xD5\xE6" ++ "\xB8\x08\xDE\x0A\x62\xFD\xF8\xAA\x52\x90\xD9\x67\x29\xB2\xCD\x06" ++ "\xB6\xB0\x50\x2B\x3F\x0F\xA3\xA5\xBF\xAA\x6E\x40\x03\xD6\x5F\x02" ++ "\xBC\xD8\x18\x47\x97\x09\xD7\xE4\x96\x3B\xCB\xEB\x92\x2C\x3C\x49" ++ "\xFF\x1F\x71\xE0\x52\x94\x0F\x8B\x9F\xB8\x2A\xBB\x9C\xE2\xA3\xDD" ++ "\x38\x89\xE2\xB1\x0B\x9E\x1F\x7A\xB3\xE3\xD2\xB0\x94\xDC\x87\xBE" ++ "\x37\xA6\xD3\xB3\x29\x35\x9A\x72\xC3\x7A\xF1\xA9\xE6\xC5\xD1\x26" ++ "\x83\x65\x44\x17\xBA\x55\xA8\x5E\x94\x26\xED\xE9\x8A\x93\x11\x5D" ++ "\x7E\x20\x1B\x9C\x15\x9E\x13\x37\x03\x4D\xDD\x99\x51\xD8\x66\x29" ++ "\x6A\xB9\xFB\x49\xFE\x52\x78\xDA\x86\x85\xA9\xA3\xB9\xEF\xEC\xAD" ++ "\x35\xA6\x8D\xAC\x0F\x75\x22\xBB\x0B\x49\x1C\x13\x52\x40\xC9\x52" ++ "\x69\x09\x54\xD1\x0F\x94\x3F\x22\x48\x67\xB0\x96\x28\xAA\xE6\x28" ++ "\xD9\x0C\x08\xEF\x51\xED\x15\x5E\xA2\x53\x59\xA5\x03\xB4\x06\x20" ++ "\x3D\xCC\xB4\xC5\xF8\x8C\x73\x67\xA3\x21\x3D\x19\xCD\xD4\x12\x28" ++ "\xD2\x93\xDE\x0D\xF0\x71\x10\x50\xD6\x33\x35\x04\x11\x64\x43\x39" ++ "\xC3\xDF\x96\xE3\x66\xE3\x85\xCA\xE7\x67\x14\x3A\xF0\x43\xAA\xBB" ++ "\xD4\x1D\xB5\x24\xB5\x74\x90\x25\xA7\x87\x7E\xDB\xD3\x83\x8A\x3A" ++ "\x69\xA8\x2D\xAF\xB7\xB8\xF3\xDC\x13\xAF\x45\x61\x3F\x59\x39\x7E" ++ "\x69\xDE\x0C\x04\xF1\x10\x6B\xB4\x56\xFA\x21\x9F\x72\x2B\x60\x86" ++ "\xE3\x23\x0E\xC4\x51\xF6\xBE\xD8\xE1\x5F\xEE\x73\x4C\x17\x4C\x2C" ++ "\x1B\xFB\x9F\x1F\x7A\x3B\x07\x5B\x8E\xF1\x01\xAC\xD6\x30\x94\x8A" ++ "\x5D\x22\x6F\x08\xCE\xED\x5E\xB6\xDB\x86\x8C\x87\xEB\x8D\x91\xFF" ++ "\x0A\x86\x30\xBD\xC0\xF8\x25\xE7\xAE\x24\x35\xF2\xFC\xE5\xFD\x1B" ++ "\xB0\x05\x4A\xA3\xE5\xEB\x2E\x05\xAD\x99\x67\x49\x87\xE6\xB3\x87" ++ "\x82\xA4\x59\xA7\x6E\xDD\xF2\xB6\x66\xE8\xF7\x70\xF5\xBD\xC9\x0E" ++ "\xFA\x9C\x79\x84\xD4\x9B\x05\x0E\xBB\xF5\xDB\xEF\xFC\xCC\x26\xF2" ++ "\x93\xCF\xD2\x04\x3C\xA9\x2C\x65\x42\x97\x86\xD8\x38\x0A\x1E\xF6" ++ "\xD6\xCA\x30\xB5\x1A\xEC\xFB\xBA\x3B\x84\x57\xB0\xFD\xFB\xE6\xBC" ++ "\xF2\x76\xF6\x4C\xBB\xAB\xB1\x31\xA1\x27\x7C\xE6\xE6\x81\xB6\xCE" ++ "\x84\x86\x40\xB6\x40\x33\xC4\xF8\xB4\x15\xCF\xAA\xA5\x51\x78\xB9" ++ "\x8B\x50\x25\xB2\x88\x86\x96\x72\x8C\x71\x4D\xB5\x3A\x94\x86\x77" ++ "\x0E\x95\x9B\x16\x93\xEF\x3A\x11\x79\xBA\x83\xF7\x74\xD3\x8D\xBA" ++ "\x15\xE1\x2C\x04\x57\xA8\x92\x1E\x9D\x00\x8E\x20\xFD\x30\x70\xE7" ++ "\xF5\x65\x2F\x19\x0C\x94\xBA\x03\x71\x12\x96\xCD\xC8\xB4\x96\xDB" ++ "\xCE\x19\xC2\xDF\x3C\xC2\xF6\x3D\x53\xED\x98\xA5\x41\x72\x2A\x22" ++ "\x7B\xF3\x2B\x17\x6C\xE1\x39\x7D\xAE\x9B\x11\xF9\xC1\xA6\x9E\x9F" ++ "\x89\x3C\x12\xAA\x94\x74\xA7\x4F\x70\xE8\xB9\xDE\x04\xF0\x9D\x39" ++ "\x24\x2D\x92\xE8\x46\x2D\x2E\xF0\x40\x66\x1A\xD9\x27\xF9\x98\xF1" ++ "\x81\x1D\x70\x62\x63\x30\x6D\xCD\x84\x04\x5F\xFA\x83\xD3\xEC\x8D" ++ "\x86\xFB\x40\x61\xC1\x8A\x45\xFF\x7B\xD9\xD4\x18\x61\x7F\x51\xE3" ++ "\xFC\x1E\x18\xF0\xAF\xC6\x18\x2C\xE1\x6D\x5D\xF9\x62\xFC\x20\xA3" ++ "\xB2\x8A\x5F\xE5\xBB\x29\x0F\x99\x63\x07\x88\x38\x3A\x3B\x73\x2A" ++ "\x6D\xDA\x3D\xA8\x0D\x8F\x56\x41\x89\x82\xE5\xB8\x61\x00\x64\x7D" ++ "\x17\x0C\xCE\x03\x55\x8F\xF4\x5B\x0D\x50\xF2\xEB\x05\x67\xBE\xDB" ++ "\x7B\x75\xC5\xEA\xA1\xAB\x1D\xB0\x3C\x6D\x42\x08\x0B\x9A\x45\x20" ++ "\xA8\x8F\xE5\x67\x47\x30\xDE\x93\x5F\x43\x05\xEB\xA8\x2D\x80\xF5" ++ "\x1A\xB8\x4A\x4E\x42\x2D\x0B\x7A\xDC\x46\x20\x2D\x13\x17\xDD\x4B" ++ "\x94\x96\xAA\x1F\x06\x0C\x1F\x62\x07\x9C\x40\xA1" ++}; ++ ++static void ++test_pac_ticket_signature(krb5_context context) ++{ ++ krb5_error_code ret; ++ krb5_ticket *ticket; ++ krb5_principal sprinc; ++ krb5_authdata **authdata1, **authdata2; ++ krb5_pac pac, pac2, pac3; ++ uint32_t *list; ++ size_t len, i; ++ krb5_data data; ++ ++ ret = krb5_decode_ticket(&ticket_data, &ticket); ++ if (ret) ++ err(context, ret, "while decoding ticket"); ++ ++ ret = krb5_decrypt_tkt_part(context, &ticket_sig_server_key, ticket); ++ if (ret) ++ err(context, ret, "while decrypting ticket"); ++ ++ ret = krb5_parse_name(context, "s1@CDOM.COM", &sprinc); ++ if (ret) ++ err(context, ret, "krb5_parse_name"); ++ ++ ret = krb5_kdc_verify_ticket(context, ticket->enc_part2, sprinc, ++ &ticket_sig_server_key, ++ &ticket_sig_krbtgt_key, &pac); ++ if (ret) ++ err(context, ret, "while verifying ticket"); ++ ++ /* In this test, the server is also the client. */ ++ ret = krb5_pac_verify(context, pac, ticket->enc_part2->times.authtime, ++ ticket->server, NULL, NULL); ++ if (ret) ++ err(context, ret, "while verifying PAC client info"); ++ ++ /* We know there is only a PAC in this test's ticket. */ ++ authdata1 = ticket->enc_part2->authorization_data; ++ ticket->enc_part2->authorization_data = NULL; ++ ++ ret = krb5_kdc_sign_ticket(context, ticket->enc_part2, pac, sprinc, ++ sprinc, &ticket_sig_server_key, ++ &ticket_sig_krbtgt_key, FALSE); ++ if (ret) ++ err(context, ret, "while signing ticket"); ++ ++ authdata2 = ticket->enc_part2->authorization_data; ++ assert(authdata2 != NULL); ++ assert(authdata2[1] == NULL); ++ ++ assert(authdata1[0]->length == authdata2[0]->length); ++ assert(memcmp(authdata1[0]->contents, authdata2[0]->contents, ++ authdata1[0]->length) == 0); ++ ++ /* Test adding signatures to a new PAC. */ ++ ret = krb5_pac_init(context, &pac2); ++ if (ret) ++ err(context, ret, "krb5_pac_init"); ++ ++ ret = krb5_pac_get_types(context, pac, &len, &list); ++ if (ret) ++ err(context, ret, "krb5_pac_get_types"); ++ ++ for (i = 0; i < len; i++) { ++ /* Skip server_cksum, privsvr_cksum, and ticket_cksum. */ ++ if (list[i] == 6 || list[i] == 7 || list[i] == 16) ++ continue; ++ ++ ret = krb5_pac_get_buffer(context, pac, list[i], &data); ++ if (ret) ++ err(context, ret, "krb5_pac_get_buffer"); ++ ++ ret = krb5_pac_add_buffer(context, pac2, list[i], &data); ++ if (ret) ++ err(context, ret, "krb5_pac_add_buffer"); ++ ++ krb5_free_data_contents(context, &data); ++ } ++ free(list); ++ ++ krb5_free_authdata(context, authdata1); ++ krb5_free_authdata(context, ticket->enc_part2->authorization_data); ++ ticket->enc_part2->authorization_data = NULL; ++ ++ ret = krb5_kdc_sign_ticket(context, ticket->enc_part2, pac2, sprinc, NULL, ++ &ticket_sig_server_key, &ticket_sig_krbtgt_key, ++ FALSE); ++ if (ret) ++ err(context, ret, "while signing ticket"); ++ ++ /* We can't compare the data since the order of the buffers may differ. */ ++ ret = krb5_kdc_verify_ticket(context, ticket->enc_part2, sprinc, ++ &ticket_sig_server_key, ++ &ticket_sig_krbtgt_key, &pac3); ++ if (ret) ++ err(context, ret, "while verifying ticket"); ++ ++ krb5_pac_free(context, pac); ++ krb5_pac_free(context, pac2); ++ krb5_pac_free(context, pac3); ++ krb5_free_principal(context, sprinc); ++ krb5_free_ticket(context, ticket); ++} ++ + int + main(int argc, char **argv) + { +@@ -618,6 +798,8 @@ main(int argc, char **argv) + if (ret) + err(NULL, 0, "krb5_init_contex"); + ++ test_pac_ticket_signature(context); ++ + ret = krb5_set_default_realm(context, "WIN2K3.THINKER.LOCAL"); + if (ret) + err(context, ret, "krb5_set_default_realm"); +diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports +index 48ae46f5c4..28784ec67c 100644 +--- a/src/lib/krb5/libkrb5.exports ++++ b/src/lib/krb5/libkrb5.exports +@@ -462,6 +462,8 @@ krb5_is_permitted_enctype + krb5_is_referral_realm + krb5_is_thread_safe + krb5_kdc_rep_decrypt_proc ++krb5_kdc_sign_ticket ++krb5_kdc_verify_ticket + krb5_kt_add_entry + krb5_kt_client_default + krb5_kt_close +diff --git a/src/lib/krb5_32.def b/src/lib/krb5_32.def +index 209c6aaef5..8c3469a96c 100644 +--- a/src/lib/krb5_32.def ++++ b/src/lib/krb5_32.def +@@ -506,3 +506,6 @@ EXPORTS + ; new in 1.20 + krb5_marshal_credentials @472 + krb5_unmarshal_credentials @473 ++ k5_sname_compare @474 ; PRIVATE GSSAPI ++ krb5_kdc_sign_ticket @475 ; ++ krb5_kdc_verify_ticket @476 ; +diff --git a/src/plugins/kdb/test/kdb_test.c b/src/plugins/kdb/test/kdb_test.c +index 38d371cb86..7d033acae4 100644 +--- a/src/plugins/kdb/test/kdb_test.c ++++ b/src/plugins/kdb/test/kdb_test.c +@@ -675,7 +675,7 @@ verify_kdc_signature(krb5_context context, krb5_pac pac, + int tries; + + ret = krb5_pac_verify(context, pac, 0, NULL, NULL, tgt_key); +- if (ret != KRB5KRB_AP_ERR_BAD_INTEGRITY) ++ if (ret != KRB5KRB_AP_ERR_MODIFIED) + return ret; + + kvno = tgt->key_data[0].key_data_kvno - 1; +@@ -684,7 +684,7 @@ verify_kdc_signature(krb5_context context, krb5_pac pac, + for (tries = 2; tries > 0 && kvno > 0; tries--, kvno--) { + ret = krb5_dbe_find_enctype(context, tgt, -1, -1, kvno, &kd); + if (ret) +- return KRB5KRB_AP_ERR_BAD_INTEGRITY; ++ return KRB5KRB_AP_ERR_MODIFIED; + ret = krb5_dbe_decrypt_key_data(context, NULL, kd, &old_key, NULL); + if (ret) + return ret; +@@ -697,7 +697,7 @@ verify_kdc_signature(krb5_context context, krb5_pac pac, + kvno = kd->key_data_kvno - 1; + } + +- return KRB5KRB_AP_ERR_BAD_INTEGRITY; ++ return KRB5KRB_AP_ERR_MODIFIED; + } + + static krb5_error_code +-- +2.39.2 + diff --git a/root/ppg/common/deps/krb5/rpm/Add-PKINIT-paChecksum2-from-MS-PKCA-v20230920.patch b/root/ppg/common/deps/krb5/rpm/Add-PKINIT-paChecksum2-from-MS-PKCA-v20230920.patch new file mode 100644 index 00000000..738fbab0 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Add-PKINIT-paChecksum2-from-MS-PKCA-v20230920.patch @@ -0,0 +1,619 @@ +From 7b5dad42e9d5103b763f3c79b82fc619bd3d2d32 Mon Sep 17 00:00:00 2001 +From: Julien Rische +Date: Thu, 3 Apr 2025 16:29:07 +0200 +Subject: [PATCH] Add PKINIT paChecksum2 from MS-PKCA v20230920 + +(This commit was rewrote for CentOS 8 Stream) + +In 2023, Microsoft updated MS-PKCA to add the optional paChecksum2 +element in the PKAuthenticator sequence. This checksum accepts SHA-1, +SHA-256, SHA-384, and SHA-512 digests. + +In Windows Server 2025, this checksum becomes mandatory when using +PKINIT with FFDH (but strangely not with ECDH if SHA-1 is configured as +allowed). + +[ghudson@mit.edu: refactored crypto interfaces to reduce complexity of +calling code] + +ticket: 9166 (new) +--- + src/include/k5-int-pkinit.h | 25 ++-- + src/lib/krb5/asn.1/asn1_k_encode.c | 18 ++- + src/plugins/preauth/pkinit/pkinit.h | 1 + + src/plugins/preauth/pkinit/pkinit_clnt.c | 41 +++---- + src/plugins/preauth/pkinit/pkinit_crypto.h | 18 +++ + .../preauth/pkinit/pkinit_crypto_openssl.c | 110 ++++++++++++++++++ + .../preauth/pkinit/pkinit_kdf_constants.c | 24 ++++ + src/plugins/preauth/pkinit/pkinit_lib.c | 16 ++- + src/plugins/preauth/pkinit/pkinit_srv.c | 39 ++----- + src/plugins/preauth/pkinit/pkinit_trace.h | 5 +- + src/tests/asn.1/krb5_decode_test.c | 2 +- + src/tests/asn.1/ktest.c | 7 +- + src/tests/asn.1/ktest_equal.c | 2 +- + src/tests/asn.1/pkinit_encode.out | 2 +- + src/tests/asn.1/pkinit_trval.out | 2 +- + 15 files changed, 233 insertions(+), 79 deletions(-) + +diff --git a/src/include/k5-int-pkinit.h b/src/include/k5-int-pkinit.h +index c23cfd3043..096f4e6145 100644 +--- a/src/include/k5-int-pkinit.h ++++ b/src/include/k5-int-pkinit.h +@@ -36,15 +36,6 @@ + * pkinit structures + */ + +-/* PKAuthenticator */ +-typedef struct _krb5_pk_authenticator { +- krb5_int32 cusec; /* (0..999999) */ +- krb5_timestamp ctime; +- krb5_int32 nonce; /* (0..4294967295) */ +- krb5_checksum paChecksum; +- krb5_data *freshnessToken; +-} krb5_pk_authenticator; +- + /* AlgorithmIdentifier */ + typedef struct _krb5_algorithm_identifier { + krb5_data algorithm; /* OID */ +@@ -57,6 +48,22 @@ typedef struct _krb5_subject_pk_info { + krb5_data subjectPublicKey; /* BIT STRING */ + } krb5_subject_pk_info; + ++/* PAChecksum2 */ ++typedef struct _krb5_pachecksum2 { ++ krb5_data checksum; ++ krb5_algorithm_identifier algorithmIdentifier; ++} krb5_pachecksum2; ++ ++/* PKAuthenticator */ ++typedef struct _krb5_pk_authenticator { ++ krb5_int32 cusec; /* (0..999999) */ ++ krb5_timestamp ctime; ++ krb5_int32 nonce; /* (0..4294967295) */ ++ krb5_data paChecksum; ++ krb5_data *freshnessToken; /* Optional */ ++ krb5_pachecksum2 *paChecksum2; /* Optional */ ++} krb5_pk_authenticator; ++ + /** AuthPack from RFC 4556*/ + typedef struct _krb5_auth_pack { + krb5_pk_authenticator pkAuthenticator; +diff --git a/src/lib/krb5/asn.1/asn1_k_encode.c b/src/lib/krb5/asn.1/asn1_k_encode.c +index 39fa8e3bbb..79c845b5d6 100644 +--- a/src/lib/krb5/asn.1/asn1_k_encode.c ++++ b/src/lib/krb5/asn.1/asn1_k_encode.c +@@ -1429,20 +1429,30 @@ DEFSEQTYPE(pkinit_supp_pub_info, krb5_pkinit_supp_pub_info, + MAKE_ENCODER(encode_krb5_pkinit_supp_pub_info, pkinit_supp_pub_info); + MAKE_ENCODER(encode_krb5_sp80056a_other_info, sp80056a_other_info); + +-/* A krb5_checksum encoded as an OCTET STRING, for PKAuthenticator. */ +-DEFCOUNTEDTYPE(ostring_checksum, krb5_checksum, contents, length, octetstring); ++DEFFIELD(pachecksum2_0, krb5_pachecksum2, checksum, 0, ostring_data); ++DEFFIELD(pachecksum2_1, krb5_pachecksum2, algorithmIdentifier, 1, ++ algorithm_identifier); ++static const struct atype_info *pachecksum2_fields[] = { ++ &k5_atype_pachecksum2_0, &k5_atype_pachecksum2_1 ++}; ++DEFSEQTYPE(pachecksum2, krb5_pachecksum2, pachecksum2_fields); ++ ++DEFPTRTYPE(pachecksum2_ptr, pachecksum2); ++DEFOPTIONALZEROTYPE(opt_pachecksum2_ptr, pachecksum2_ptr); + + DEFFIELD(pk_authenticator_0, krb5_pk_authenticator, cusec, 0, int32); + DEFFIELD(pk_authenticator_1, krb5_pk_authenticator, ctime, 1, kerberos_time); + DEFFIELD(pk_authenticator_2, krb5_pk_authenticator, nonce, 2, int32); + DEFFIELD(pk_authenticator_3, krb5_pk_authenticator, paChecksum, 3, +- ostring_checksum); ++ ostring_data); + DEFFIELD(pk_authenticator_4, krb5_pk_authenticator, freshnessToken, 4, + opt_ostring_data_ptr); ++DEFFIELD(pk_authenticator_5, krb5_pk_authenticator, paChecksum2, 5, ++ opt_pachecksum2_ptr); + static const struct atype_info *pk_authenticator_fields[] = { + &k5_atype_pk_authenticator_0, &k5_atype_pk_authenticator_1, + &k5_atype_pk_authenticator_2, &k5_atype_pk_authenticator_3, +- &k5_atype_pk_authenticator_4 ++ &k5_atype_pk_authenticator_4, &k5_atype_pk_authenticator_5 + }; + DEFSEQTYPE(pk_authenticator, krb5_pk_authenticator, pk_authenticator_fields); + +diff --git a/src/plugins/preauth/pkinit/pkinit.h b/src/plugins/preauth/pkinit/pkinit.h +index ab132d78a9..b4120f3c61 100644 +--- a/src/plugins/preauth/pkinit/pkinit.h ++++ b/src/plugins/preauth/pkinit/pkinit.h +@@ -339,6 +339,7 @@ void free_krb5_algorithm_identifiers(krb5_algorithm_identifier ***in); + void free_krb5_algorithm_identifier(krb5_algorithm_identifier *in); + void free_krb5_kdc_dh_key_info(krb5_kdc_dh_key_info **in); + void free_krb5_subject_pk_info(krb5_subject_pk_info **in); ++void free_pachecksum2(krb5_context context, krb5_pachecksum2 **in); + krb5_error_code pkinit_copy_krb5_data(krb5_data *dst, const krb5_data *src); + + +diff --git a/src/plugins/preauth/pkinit/pkinit_clnt.c b/src/plugins/preauth/pkinit/pkinit_clnt.c +index ca0162897b..e07c05518c 100644 +--- a/src/plugins/preauth/pkinit/pkinit_clnt.c ++++ b/src/plugins/preauth/pkinit/pkinit_clnt.c +@@ -57,10 +57,9 @@ use_content_info(krb5_context context, pkinit_req_context req, + static krb5_error_code + pkinit_as_req_create(krb5_context context, pkinit_context plgctx, + pkinit_req_context reqctx, krb5_timestamp ctsec, +- krb5_int32 cusec, krb5_ui_4 nonce, +- const krb5_checksum *cksum, +- krb5_principal client, krb5_principal server, +- krb5_data **as_req); ++ krb5_int32 cusec, krb5_ui_4 nonce, const krb5_data *cksum, ++ const krb5_pachecksum2 *cksum2, krb5_principal client, ++ krb5_principal server, krb5_data **as_req); + + static krb5_error_code + pkinit_as_rep_parse(krb5_context context, pkinit_context plgctx, +@@ -90,7 +89,8 @@ pa_pkinit_gen_req(krb5_context context, + krb5_timestamp ctsec = 0; + krb5_int32 cusec = 0; + krb5_ui_4 nonce = 0; +- krb5_checksum cksum; ++ krb5_data cksum = empty_data(); ++ krb5_pachecksum2 *cksum2 = NULL; + krb5_data *der_req = NULL; + krb5_pa_data **return_pa_data = NULL; + +@@ -119,15 +119,10 @@ pa_pkinit_gen_req(krb5_context context, + goto cleanup; + } + +- retval = krb5_c_make_checksum(context, CKSUMTYPE_SHA1, NULL, 0, der_req, +- &cksum); ++ retval = crypto_generate_checksums(context, der_req, &cksum, &cksum2); + if (retval) + goto cleanup; +- TRACE_PKINIT_CLIENT_REQ_CHECKSUM(context, &cksum); +-#ifdef DEBUG_CKSUM +- pkiDebug("calculating checksum on buf size (%d)\n", der_req->length); +- print_buffer(der_req->data, der_req->length); +-#endif ++ TRACE_PKINIT_CLIENT_REQ_CHECKSUMS(context, &cksum, cksum2); + + retval = cb->get_preauth_time(context, rock, TRUE, &ctsec, &cusec); + if (retval) +@@ -141,7 +136,8 @@ pa_pkinit_gen_req(krb5_context context, + nonce = request->nonce; + + retval = pkinit_as_req_create(context, plgctx, reqctx, ctsec, cusec, +- nonce, &cksum, request->client, request->server, &out_data); ++ nonce, &cksum, cksum2, request->client, ++ request->server, &out_data); + if (retval) { + pkiDebug("error %d on pkinit_as_req_create; aborting PKINIT\n", + (int) retval); +@@ -169,23 +165,19 @@ pa_pkinit_gen_req(krb5_context context, + + cleanup: + krb5_free_data(context, der_req); +- krb5_free_checksum_contents(context, &cksum); ++ krb5_free_data_contents(context, &cksum); ++ free_pachecksum2(context, &cksum2); + krb5_free_data(context, out_data); + krb5_free_pa_data(context, return_pa_data); + return retval; + } + + static krb5_error_code +-pkinit_as_req_create(krb5_context context, +- pkinit_context plgctx, +- pkinit_req_context reqctx, +- krb5_timestamp ctsec, +- krb5_int32 cusec, +- krb5_ui_4 nonce, +- const krb5_checksum * cksum, +- krb5_principal client, +- krb5_principal server, +- krb5_data ** as_req) ++pkinit_as_req_create(krb5_context context, pkinit_context plgctx, ++ pkinit_req_context reqctx, krb5_timestamp ctsec, ++ krb5_int32 cusec, krb5_ui_4 nonce, const krb5_data *cksum, ++ const krb5_pachecksum2 *cksum2, krb5_principal client, ++ krb5_principal server, krb5_data **as_req) + { + krb5_error_code retval = ENOMEM; + krb5_subject_pk_info info; +@@ -207,6 +199,7 @@ pkinit_as_req_create(krb5_context context, + auth_pack.pkAuthenticator.paChecksum = *cksum; + if (!reqctx->opts->disable_freshness) + auth_pack.pkAuthenticator.freshnessToken = reqctx->freshness_token; ++ auth_pack.pkAuthenticator.paChecksum2 = (krb5_pachecksum2 *)cksum2; + auth_pack.clientDHNonce.length = 0; + auth_pack.clientPublicValue = &info; + auth_pack.supportedKDFs = (krb5_data **)supported_kdf_alg_ids; +diff --git a/src/plugins/preauth/pkinit/pkinit_crypto.h b/src/plugins/preauth/pkinit/pkinit_crypto.h +index f251e41064..d576cd6cef 100644 +--- a/src/plugins/preauth/pkinit/pkinit_crypto.h ++++ b/src/plugins/preauth/pkinit/pkinit_crypto.h +@@ -568,6 +568,10 @@ extern const krb5_octet krb5_pkinit_sha256_oid[]; + extern const size_t krb5_pkinit_sha256_oid_len; + extern const krb5_octet krb5_pkinit_sha512_oid[]; + extern const size_t krb5_pkinit_sha512_oid_len; ++extern const krb5_data cms_sha1_id; ++extern const krb5_data cms_sha256_id; ++extern const krb5_data cms_sha384_id; ++extern const krb5_data cms_sha512_id; + /** + * An ordered set of OIDs, stored as krb5_data, of KDF algorithms + * supported by this implementation. The order of this array controls +@@ -585,4 +589,18 @@ crypto_req_cert_matching_data(krb5_context context, + pkinit_req_crypto_context reqctx, + pkinit_cert_matching_data **md_out); + ++/* Generate a SHA-1 checksum over body in *cksum1_out and a SHA-256 checksum ++ * over body in *cksum2_out with appropriate metadata. */ ++krb5_error_code ++crypto_generate_checksums(krb5_context context, const krb5_data *body, ++ krb5_data *cksum1_out, ++ krb5_pachecksum2 **cksum2_out); ++ ++/* Verify the SHA-1 checksum in cksum1 and the tagged checksum in cksum2. ++ * cksum2 may be NULL, in which case only cksum1 is verified. */ ++krb5_error_code ++crypto_verify_checksums(krb5_context context, krb5_data *body, ++ const krb5_data *cksum1, ++ const krb5_pachecksum2 *cksum2); ++ + #endif /* _PKINIT_CRYPTO_H */ +diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c +index 76ad7526bb..638971fe83 100644 +--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c ++++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c +@@ -5413,3 +5413,113 @@ crypto_req_cert_matching_data(krb5_context context, + return get_matching_data(context, plgctx, reqctx, reqctx->received_cert, + md_out); + } ++ ++/* Return the OpenSSL message digest type matching the given CMS OID, or NULL ++ * if it doesn't match any of the CMS OIDs we know about. */ ++static const EVP_MD * ++md_from_cms_oid(const krb5_data *alg_id) ++{ ++ if (data_eq(*alg_id, cms_sha1_id)) ++ return EVP_sha1(); ++ if (data_eq(*alg_id, cms_sha256_id)) ++ return EVP_sha256(); ++ if (data_eq(*alg_id, cms_sha384_id)) ++ return EVP_sha384(); ++ if (data_eq(*alg_id, cms_sha512_id)) ++ return EVP_sha512(); ++ return NULL; ++} ++ ++/* Compute a message digest of the given type over body, placing the result in ++ * *digest_out in allocated storage. Return true on success. */ ++static krb5_boolean ++make_digest(const krb5_data *body, const EVP_MD *md, krb5_data *digest_out) ++{ ++ krb5_error_code ret; ++ krb5_data d; ++ ++ if (md == NULL) ++ return FALSE; ++ ret = alloc_data(&d, EVP_MD_size(md)); ++ if (ret) ++ return FALSE; ++ if (!EVP_Digest(body->data, body->length, (uint8_t *)d.data, &d.length, md, ++ NULL)) { ++ free(d.data); ++ return FALSE; ++ } ++ *digest_out = d; ++ return TRUE; ++} ++ ++/* Return true if digest verifies for the given body and message digest ++ * type. */ ++static krb5_boolean ++check_digest(const krb5_data *body, const EVP_MD *md, const krb5_data *digest) ++{ ++ unsigned int digest_len; ++ uint8_t buf[EVP_MAX_MD_SIZE]; ++ ++ if (md == NULL) ++ return FALSE; ++ if (!EVP_Digest(body->data, body->length, buf, &digest_len, md, NULL)) ++ return FALSE; ++ return (digest->length == digest_len && ++ CRYPTO_memcmp(digest->data, buf, digest_len) == 0); ++} ++ ++krb5_error_code ++crypto_generate_checksums(krb5_context context, const krb5_data *body, ++ krb5_data *cksum1_out, krb5_pachecksum2 **cksum2_out) ++{ ++ krb5_data cksum1 = empty_data(); ++ krb5_pachecksum2 *cksum2 = NULL; ++ krb5_error_code ret; ++ ++ if (!make_digest(body, EVP_sha1(), &cksum1)) ++ goto fail; ++ ++ cksum2 = k5alloc(sizeof(*cksum2), &ret); ++ if (cksum2 == NULL) ++ goto fail; ++ ++ if (!make_digest(body, EVP_sha256(), &cksum2->checksum)) ++ goto fail; ++ ++ if (krb5int_copy_data_contents(context, &cms_sha256_id, ++ &cksum2->algorithmIdentifier.algorithm)) ++ goto fail; ++ ++ cksum2->algorithmIdentifier.parameters = empty_data(); ++ ++ *cksum1_out = cksum1; ++ *cksum2_out = cksum2; ++ return 0; ++ ++fail: ++ krb5_free_data_contents(context, &cksum1); ++ free_pachecksum2(context, &cksum2); ++ return KRB5_CRYPTO_INTERNAL; ++} ++ ++krb5_error_code ++crypto_verify_checksums(krb5_context context, krb5_data *body, ++ const krb5_data *cksum1, ++ const krb5_pachecksum2 *cksum2) ++{ ++ const EVP_MD *md; ++ ++ /* RFC 4556 doesn't say what error to return if the checksum doesn't match. ++ * Windows returns this one. */ ++ if (!check_digest(body, EVP_sha1(), cksum1)) ++ return KRB5KRB_AP_ERR_MODIFIED; ++ ++ if (cksum2 == NULL) ++ return 0; ++ ++ md = md_from_cms_oid(&cksum2->algorithmIdentifier.algorithm); ++ if (!check_digest(body, md, &cksum2->checksum)) ++ return KRB5KRB_AP_ERR_MODIFIED; ++ ++ return 0; ++} +diff --git a/src/plugins/preauth/pkinit/pkinit_kdf_constants.c b/src/plugins/preauth/pkinit/pkinit_kdf_constants.c +index 1604f1670a..315fc36866 100644 +--- a/src/plugins/preauth/pkinit/pkinit_kdf_constants.c ++++ b/src/plugins/preauth/pkinit/pkinit_kdf_constants.c +@@ -57,3 +57,27 @@ krb5_data const * const supported_kdf_alg_ids[] = { + &sha512_id, + NULL + }; ++ ++/* RFC 3370 sha-1: iso(1) identified-organization(3) oiw(14) secsig(3) ++ * algorithm(2) 26 */ ++static char cms_sha1[] = { 0x2b, 0x0e, 0x03, 0x02, 0x1a }; ++/* RFC 5754 id-sha256: joint-iso-itu-t(2) country(16) us(840) organization(1) ++ * gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 */ ++static char cms_sha256[] = { ++ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01 ++}; ++/* RFC 5754 id-sha384: joint-iso-itu-t(2) country(16) us(840) organization(1) ++ * gov(101) csor(3) nistalgorithm(4) hashalgs(2) 2 */ ++static char cms_sha384[] = { ++ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02 ++}; ++/* RFC 5754 id-sha512: joint-iso-itu-t(2) country(16) us(840) organization(1) ++ * gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 */ ++static char cms_sha512[] = { ++ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03 ++}; ++ ++const krb5_data cms_sha1_id = { KV5M_DATA, sizeof(cms_sha1), cms_sha1 }; ++const krb5_data cms_sha256_id = { KV5M_DATA, sizeof(cms_sha256), cms_sha256 }; ++const krb5_data cms_sha384_id = { KV5M_DATA, sizeof(cms_sha384), cms_sha384 }; ++const krb5_data cms_sha512_id = { KV5M_DATA, sizeof(cms_sha512), cms_sha512 }; +diff --git a/src/plugins/preauth/pkinit/pkinit_lib.c b/src/plugins/preauth/pkinit/pkinit_lib.c +index 7af880bf5c..47972bb5eb 100644 +--- a/src/plugins/preauth/pkinit/pkinit_lib.c ++++ b/src/plugins/preauth/pkinit/pkinit_lib.c +@@ -29,6 +29,7 @@ + * SUCH DAMAGES. + */ + ++#include "k5-int.h" + #include "pkinit.h" + + #define FAKECERT +@@ -127,8 +128,9 @@ free_krb5_auth_pack(krb5_auth_pack **in) + free((*in)->clientPublicValue->subjectPublicKey.data); + free((*in)->clientPublicValue); + } +- free((*in)->pkAuthenticator.paChecksum.contents); ++ free((*in)->pkAuthenticator.paChecksum.data); + krb5_free_data(NULL, (*in)->pkAuthenticator.freshnessToken); ++ free_pachecksum2(NULL, &(*in)->pkAuthenticator.paChecksum2); + if ((*in)->supportedCMSTypes != NULL) + free_krb5_algorithm_identifiers(&((*in)->supportedCMSTypes)); + if ((*in)->supportedKDFs) { +@@ -213,6 +215,18 @@ free_krb5_kdc_dh_key_info(krb5_kdc_dh_key_info **in) + free(*in); + } + ++void ++free_pachecksum2(krb5_context context, krb5_pachecksum2 **in) ++{ ++ if (*in == NULL) ++ return; ++ krb5_free_data_contents(context, &(*in)->checksum); ++ krb5_free_data_contents(context, &(*in)->algorithmIdentifier.algorithm); ++ krb5_free_data_contents(context, &(*in)->algorithmIdentifier.parameters); ++ free(*in); ++ *in = NULL; ++} ++ + void + init_krb5_pa_pk_as_req(krb5_pa_pk_as_req **in) + { +diff --git a/src/plugins/preauth/pkinit/pkinit_srv.c b/src/plugins/preauth/pkinit/pkinit_srv.c +index 4eab5a2761..f5b3d98ef8 100644 +--- a/src/plugins/preauth/pkinit/pkinit_srv.c ++++ b/src/plugins/preauth/pkinit/pkinit_srv.c +@@ -426,11 +426,12 @@ pkinit_server_verify_padata(krb5_context context, + krb5_data authp_data = {0, 0, NULL}, krb5_authz = {0, 0, NULL}; + krb5_pa_pk_as_req *reqp = NULL; + krb5_auth_pack *auth_pack = NULL; ++ krb5_pk_authenticator *pka; + pkinit_kdc_context plgctx = NULL; + pkinit_kdc_req_context reqctx = NULL; + krb5_checksum cksum = {0, 0, 0, NULL}; + krb5_data *der_req = NULL; +- krb5_data k5data, *ftoken; ++ krb5_data k5data; + int is_signed = 1; + krb5_pa_data **e_data = NULL; + krb5_kdcpreauth_modreq modreq = NULL; +@@ -522,8 +523,9 @@ pkinit_server_verify_padata(krb5_context context, + pkiDebug("failed to decode krb5_auth_pack\n"); + goto cleanup; + } ++ pka = &auth_pack->pkAuthenticator; + +- retval = krb5_check_clockskew(context, auth_pack->pkAuthenticator.ctime); ++ retval = krb5_check_clockskew(context, pka->ctime); + if (retval) + goto cleanup; + +@@ -546,36 +548,13 @@ pkinit_server_verify_padata(krb5_context context, + goto cleanup; + } + der_req = cb->request_body(context, rock); +- retval = krb5_c_make_checksum(context, CKSUMTYPE_SHA1, NULL, 0, der_req, +- &cksum); +- if (retval) { +- pkiDebug("unable to calculate AS REQ checksum\n"); +- goto cleanup; +- } +- if (cksum.length != auth_pack->pkAuthenticator.paChecksum.length || +- k5_bcmp(cksum.contents, auth_pack->pkAuthenticator.paChecksum.contents, +- cksum.length) != 0) { +- pkiDebug("failed to match the checksum\n"); +-#ifdef DEBUG_CKSUM +- pkiDebug("calculating checksum on buf size (%d)\n", req_pkt->length); +- print_buffer(req_pkt->data, req_pkt->length); +- pkiDebug("received checksum type=%d size=%d ", +- auth_pack->pkAuthenticator.paChecksum.checksum_type, +- auth_pack->pkAuthenticator.paChecksum.length); +- print_buffer(auth_pack->pkAuthenticator.paChecksum.contents, +- auth_pack->pkAuthenticator.paChecksum.length); +- pkiDebug("expected checksum type=%d size=%d ", +- cksum.checksum_type, cksum.length); +- print_buffer(cksum.contents, cksum.length); +-#endif +- +- retval = KRB5KDC_ERR_PA_CHECKSUM_MUST_BE_INCLUDED; ++ retval = crypto_verify_checksums(context, der_req, &pka->paChecksum, ++ pka->paChecksum2); ++ if (retval) + goto cleanup; +- } + +- ftoken = auth_pack->pkAuthenticator.freshnessToken; +- if (ftoken != NULL) { +- retval = cb->check_freshness_token(context, rock, ftoken); ++ if (pka->freshnessToken != NULL) { ++ retval = cb->check_freshness_token(context, rock, pka->freshnessToken); + if (retval) + goto cleanup; + valid_freshness_token = TRUE; +diff --git a/src/plugins/preauth/pkinit/pkinit_trace.h b/src/plugins/preauth/pkinit/pkinit_trace.h +index 4f80e0b9b6..3017f9e059 100644 +--- a/src/plugins/preauth/pkinit/pkinit_trace.h ++++ b/src/plugins/preauth/pkinit/pkinit_trace.h +@@ -58,8 +58,9 @@ + TRACE(c, "PKINIT client verified DH reply") + #define TRACE_PKINIT_CLIENT_REP_DH_FAIL(c) \ + TRACE(c, "PKINIT client could not verify DH reply") +-#define TRACE_PKINIT_CLIENT_REQ_CHECKSUM(c, cksum) \ +- TRACE(c, "PKINIT client computed kdc-req-body checksum {cksum}", cksum) ++#define TRACE_PKINIT_CLIENT_REQ_CHECKSUMS(c, ck1, ck2) \ ++ TRACE(c, "PKINIT client computed checksums: {hexdata} {hexdata}", \ ++ ck1, &(ck2)->checksum) + #define TRACE_PKINIT_CLIENT_REQ_DH(c) \ + TRACE(c, "PKINIT client making DH request") + #define TRACE_PKINIT_CLIENT_SAN_CONFIG_DNSNAME(c, host) \ +diff --git a/src/tests/asn.1/krb5_decode_test.c b/src/tests/asn.1/krb5_decode_test.c +index 7a116b40d9..9946ebd3a5 100644 +--- a/src/tests/asn.1/krb5_decode_test.c ++++ b/src/tests/asn.1/krb5_decode_test.c +@@ -1173,7 +1173,7 @@ int main(argc, argv) + /* decode_krb5_auth_pack */ + { + setup(krb5_auth_pack,ktest_make_sample_auth_pack); +- decode_run("krb5_auth_pack","","30 81 93 A0 29 30 27 A0 05 02 03 01 E2 40 A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A2 03 02 01 2A A3 06 04 04 31 32 33 34 A1 22 30 20 30 13 06 09 2A 86 48 86 F7 12 01 02 02 04 06 70 61 72 61 6D 73 03 09 00 6B 72 62 35 64 61 74 61 A2 24 30 22 30 13 06 09 2A 86 48 86 F7 12 01 02 02 04 06 70 61 72 61 6D 73 30 0B 06 09 2A 86 48 86 F7 12 01 02 02 A3 0A 04 08 6B 72 62 35 64 61 74 61 A4 10 30 0E 30 0C A0 0A 06 08 6B 72 62 35 64 61 74 61", ++ decode_run("krb5_auth_pack","","30 81 97 A0 2D 30 2B A0 05 02 03 01 E2 40 A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A2 03 02 01 2A A3 0A 04 08 6B 72 62 35 64 61 74 61 A1 22 30 20 30 13 06 09 2A 86 48 86 F7 12 01 02 02 04 06 70 61 72 61 6D 73 03 09 00 6B 72 62 35 64 61 74 61 A2 24 30 22 30 13 06 09 2A 86 48 86 F7 12 01 02 02 04 06 70 61 72 61 6D 73 30 0B 06 09 2A 86 48 86 F7 12 01 02 02 A3 0A 04 08 6B 72 62 35 64 61 74 61 A4 10 30 0E 30 0C A0 0A 06 08 6B 72 62 35 64 61 74 61", + acc.decode_krb5_auth_pack, + ktest_equal_auth_pack,ktest_free_auth_pack); + ktest_empty_auth_pack(&ref); +diff --git a/src/tests/asn.1/ktest.c b/src/tests/asn.1/ktest.c +index 7bb698732b..fc953ac9b7 100644 +--- a/src/tests/asn.1/ktest.c ++++ b/src/tests/asn.1/ktest.c +@@ -722,9 +722,7 @@ ktest_make_sample_pk_authenticator(krb5_pk_authenticator *p) + p->cusec = SAMPLE_USEC; + p->ctime = SAMPLE_TIME; + p->nonce = SAMPLE_NONCE; +- ktest_make_sample_checksum(&p->paChecksum); +- /* We don't encode the checksum type, only the contents. */ +- p->paChecksum.checksum_type = 0; ++ ktest_make_sample_data(&p->paChecksum); + p->freshnessToken = ealloc(sizeof(krb5_data)); + ktest_make_sample_data(p->freshnessToken); + } +@@ -1666,8 +1664,7 @@ ktest_empty_pa_otp_req(krb5_pa_otp_req *p) + static void + ktest_empty_pk_authenticator(krb5_pk_authenticator *p) + { +- ktest_empty_checksum(&p->paChecksum); +- p->paChecksum.contents = NULL; ++ ktest_empty_data(&p->paChecksum); + krb5_free_data(NULL, p->freshnessToken); + p->freshnessToken = NULL; + } +diff --git a/src/tests/asn.1/ktest_equal.c b/src/tests/asn.1/ktest_equal.c +index eed6872f9f..eec7a71601 100644 +--- a/src/tests/asn.1/ktest_equal.c ++++ b/src/tests/asn.1/ktest_equal.c +@@ -872,7 +872,7 @@ ktest_equal_pk_authenticator(krb5_pk_authenticator *ref, + p = p && scalar_equal(cusec); + p = p && scalar_equal(ctime); + p = p && scalar_equal(nonce); +- p = p && struct_equal(paChecksum, ktest_equal_checksum); ++ p = p && data_eq(ref->paChecksum, var->paChecksum); + return p; + } + +diff --git a/src/tests/asn.1/pkinit_encode.out b/src/tests/asn.1/pkinit_encode.out +index 9bd08e159f..cab27cfb68 100644 +--- a/src/tests/asn.1/pkinit_encode.out ++++ b/src/tests/asn.1/pkinit_encode.out +@@ -1,7 +1,7 @@ + encode_krb5_pa_pk_as_req: 30 38 80 08 6B 72 62 35 64 61 74 61 A1 22 30 20 30 1E 80 08 6B 72 62 35 64 61 74 61 81 08 6B 72 62 35 64 61 74 61 82 08 6B 72 62 35 64 61 74 61 82 08 6B 72 62 35 64 61 74 61 + encode_krb5_pa_pk_as_rep(dhInfo): A0 28 30 26 80 08 6B 72 62 35 64 61 74 61 A1 0A 04 08 6B 72 62 35 64 61 74 61 A2 0E 30 0C A0 0A 06 08 6B 72 62 35 64 61 74 61 + encode_krb5_pa_pk_as_rep(encKeyPack): 81 08 6B 72 62 35 64 61 74 61 +-encode_krb5_auth_pack: 30 81 9F A0 35 30 33 A0 05 02 03 01 E2 40 A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A2 03 02 01 2A A3 06 04 04 31 32 33 34 A4 0A 04 08 6B 72 62 35 64 61 74 61 A1 22 30 20 30 13 06 09 2A 86 48 86 F7 12 01 02 02 04 06 70 61 72 61 6D 73 03 09 00 6B 72 62 35 64 61 74 61 A2 24 30 22 30 13 06 09 2A 86 48 86 F7 12 01 02 02 04 06 70 61 72 61 6D 73 30 0B 06 09 2A 86 48 86 F7 12 01 02 02 A3 0A 04 08 6B 72 62 35 64 61 74 61 A4 10 30 0E 30 0C A0 0A 06 08 6B 72 62 35 64 61 74 61 ++encode_krb5_auth_pack: 30 81 A3 A0 39 30 37 A0 05 02 03 01 E2 40 A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A2 03 02 01 2A A3 0A 04 08 6B 72 62 35 64 61 74 61 A4 0A 04 08 6B 72 62 35 64 61 74 61 A1 22 30 20 30 13 06 09 2A 86 48 86 F7 12 01 02 02 04 06 70 61 72 61 6D 73 03 09 00 6B 72 62 35 64 61 74 61 A2 24 30 22 30 13 06 09 2A 86 48 86 F7 12 01 02 02 04 06 70 61 72 61 6D 73 30 0B 06 09 2A 86 48 86 F7 12 01 02 02 A3 0A 04 08 6B 72 62 35 64 61 74 61 A4 10 30 0E 30 0C A0 0A 06 08 6B 72 62 35 64 61 74 61 + encode_krb5_kdc_dh_key_info: 30 25 A0 0B 03 09 00 6B 72 62 35 64 61 74 61 A1 03 02 01 2A A2 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A + encode_krb5_reply_key_pack: 30 26 A0 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A1 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34 + encode_krb5_sp80056a_other_info: 30 81 81 30 0B 06 09 2A 86 48 86 F7 12 01 02 02 A0 32 04 30 30 2E A0 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A1 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A1 32 04 30 30 2E A0 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A1 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A2 0A 04 08 6B 72 62 35 64 61 74 61 +diff --git a/src/tests/asn.1/pkinit_trval.out b/src/tests/asn.1/pkinit_trval.out +index 3675fba386..047dec842e 100644 +--- a/src/tests/asn.1/pkinit_trval.out ++++ b/src/tests/asn.1/pkinit_trval.out +@@ -38,7 +38,7 @@ encode_krb5_auth_pack: + . . [0] [Integer] 123456 + . . [1] [Generalized Time] "19940610060317Z" + . . [2] [Integer] 42 +-. . [3] [Octet String] "1234" ++. . [3] [Octet String] "krb5data" + . . [4] [Octet String] "krb5data" + . [1] [Sequence/Sequence Of] + . . [Sequence/Sequence Of] +-- +2.49.0 + diff --git a/root/ppg/common/deps/krb5/rpm/Add-a-simple-DER-support-header.patch b/root/ppg/common/deps/krb5/rpm/Add-a-simple-DER-support-header.patch new file mode 100644 index 00000000..e67fe680 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Add-a-simple-DER-support-header.patch @@ -0,0 +1,169 @@ +From 5c2f409c360560c8b99926d6cf1a80419e758b22 Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Tue, 7 Mar 2023 00:19:33 -0500 +Subject: [PATCH] Add a simple DER support header + +(cherry picked from commit 548da160b52b25a106e9f6077d6a42c2c049586c) +--- + src/include/k5-der.h | 149 +++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 149 insertions(+) + create mode 100644 src/include/k5-der.h + +diff --git a/src/include/k5-der.h b/src/include/k5-der.h +new file mode 100644 +index 0000000000..b8371d9b4d +--- /dev/null ++++ b/src/include/k5-der.h +@@ -0,0 +1,149 @@ ++/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ ++/* include/k5-der.h - Distinguished Encoding Rules (DER) declarations */ ++/* ++ * Copyright (C) 2023 by the Massachusetts Institute of Technology. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ++ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, ++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED ++ * OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++/* ++ * Most ASN.1 encoding and decoding is done using the table-driven framework in ++ * libkrb5. When that is not an option, these helpers can be used to encode ++ * and decode simple types. ++ */ ++ ++#ifndef K5_DER_H ++#define K5_DER_H ++ ++#include ++#include ++#include "k5-buf.h" ++#include "k5-input.h" ++ ++/* Return the number of bytes needed to encode len as a DER encoding length. */ ++static inline size_t ++k5_der_len_len(size_t len) ++{ ++ size_t llen; ++ ++ if (len < 128) ++ return 1; ++ llen = 1; ++ while (len > 0) { ++ len >>= 8; ++ llen++; ++ } ++ return llen; ++} ++ ++/* Return the number of bytes needed to encode a DER value (with identifier ++ * byte and length) for a given contents length. */ ++static inline size_t ++k5_der_value_len(size_t contents_len) ++{ ++ return 1 + k5_der_len_len(contents_len) + contents_len; ++} ++ ++/* Add a DER identifier byte (composed by the caller, including the ASN.1 ++ * class, tag, and constructed bit) and length. */ ++static inline void ++k5_der_add_taglen(struct k5buf *buf, uint8_t idbyte, size_t len) ++{ ++ uint8_t *p; ++ size_t llen = k5_der_len_len(len); ++ ++ p = k5_buf_get_space(buf, 1 + llen); ++ if (p == NULL) ++ return; ++ *p++ = idbyte; ++ if (len < 128) { ++ *p = len; ++ } else { ++ *p = 0x80 | (llen - 1); ++ /* Encode the length bytes backwards so the most significant byte is ++ * first. */ ++ p += llen; ++ while (len > 0) { ++ *--p = len & 0xFF; ++ len >>= 8; ++ } ++ } ++} ++ ++/* Add a DER value (identifier byte, length, and contents). */ ++static inline void ++k5_der_add_value(struct k5buf *buf, uint8_t idbyte, const void *contents, ++ size_t len) ++{ ++ k5_der_add_taglen(buf, idbyte, len); ++ k5_buf_add_len(buf, contents, len); ++} ++ ++/* ++ * If the next byte in in matches idbyte and the subsequent DER length is ++ * valid, advance in past the value, set *contents_out to the value contents, ++ * and return true. Otherwise return false. Only set an error on in if the ++ * next bytes matches idbyte but the ensuing length is invalid. contents_out ++ * may be aliased to in; it will only be written to on successful decoding of a ++ * value. ++ */ ++static inline bool ++k5_der_get_value(struct k5input *in, uint8_t idbyte, ++ struct k5input *contents_out) ++{ ++ uint8_t lenbyte, i; ++ size_t len; ++ const void *bytes; ++ ++ /* Do nothing if in is empty or the next byte doesn't match idbyte. */ ++ if (in->status || in->len == 0 || *in->ptr != idbyte) ++ return false; ++ ++ /* Advance past the identifier byte and decode the length. */ ++ (void)k5_input_get_byte(in); ++ lenbyte = k5_input_get_byte(in); ++ if (lenbyte < 128) { ++ len = lenbyte; ++ } else { ++ len = 0; ++ for (i = 0; i < (lenbyte & 0x7F); i++) { ++ if (len > (SIZE_MAX >> 8)) { ++ k5_input_set_status(in, EOVERFLOW); ++ return false; ++ } ++ len = (len << 8) | k5_input_get_byte(in); ++ } ++ } ++ ++ bytes = k5_input_get_bytes(in, len); ++ if (bytes == NULL) ++ return false; ++ k5_input_init(contents_out, bytes, len); ++ return true; ++} ++ ++#endif /* K5_DER_H */ +-- +2.45.1 + diff --git a/root/ppg/common/deps/krb5/rpm/Add-channel-bindings-tests.patch b/root/ppg/common/deps/krb5/rpm/Add-channel-bindings-tests.patch new file mode 100644 index 00000000..6af09491 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Add-channel-bindings-tests.patch @@ -0,0 +1,420 @@ +From 8182f9f08b2593ff8749078ffd3daef9bf39a7fe Mon Sep 17 00:00:00 2001 +From: Isaac Boukris +Date: Fri, 20 Mar 2020 00:17:28 +0100 +Subject: [PATCH] Add channel bindings tests + +[ghudson@mit.edu: adjusted test program to output channel-bound state +instead of optionally enforcing it; adjusted tests to check program +output; split out tests into separate Python script; made cosmetic +changes] + +ticket: 8900 +(cherry picked from commit b0b21b6d25b06f3e2b365dfe9dd4c99b3d43bf57) +[rharwood@redhat.com: .gitignore] +(cherry picked from commit 3e92520c1417f22447751cd9172d5ab30c2e0ad8) +--- + src/plugins/gssapi/negoextest/main.c | 18 +++++ + src/tests/gssapi/Makefile.in | 49 ++++++------ + src/tests/gssapi/common.c | 25 ++++-- + src/tests/gssapi/common.h | 9 +++ + src/tests/gssapi/deps | 4 + + src/tests/gssapi/t_bindings.c | 111 +++++++++++++++++++++++++++ + src/tests/gssapi/t_bindings.py | 43 +++++++++++ + src/tests/gssapi/t_negoex.py | 7 ++ + 8 files changed, 237 insertions(+), 29 deletions(-) + create mode 100644 src/tests/gssapi/t_bindings.c + create mode 100644 src/tests/gssapi/t_bindings.py + +diff --git a/src/plugins/gssapi/negoextest/main.c b/src/plugins/gssapi/negoextest/main.c +index 6c340f41b..72fc5273a 100644 +--- a/src/plugins/gssapi/negoextest/main.c ++++ b/src/plugins/gssapi/negoextest/main.c +@@ -57,6 +57,15 @@ gss_init_sec_context(OM_uint32 *minor_status, + const char *envstr; + uint8_t hops, mech_last_octet; + ++ envstr = getenv("GSS_INIT_BINDING"); ++ if (envstr != NULL) { ++ assert(strlen(envstr) > 0); ++ assert(input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS); ++ assert(strlen(envstr) == input_chan_bindings->application_data.length); ++ assert(strcmp((char *)input_chan_bindings->application_data.value, ++ envstr) == 0); ++ } ++ + if (input_token == GSS_C_NO_BUFFER || input_token->length == 0) { + envstr = getenv("HOPS"); + hops = (envstr != NULL) ? atoi(envstr) : 1; +@@ -112,6 +121,15 @@ gss_accept_sec_context(OM_uint32 *minor_status, gss_ctx_id_t *context_handle, + uint8_t hops, mech_last_octet; + const char *envstr; + ++ envstr = getenv("GSS_ACCEPT_BINDING"); ++ if (envstr != NULL) { ++ assert(strlen(envstr) > 0); ++ assert(input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS); ++ assert(strlen(envstr) == input_chan_bindings->application_data.length); ++ assert(strcmp((char *)input_chan_bindings->application_data.value, ++ envstr) == 0); ++ } ++ + /* + * The unwrapped token sits at the end and is just one byte giving the + * remaining number of hops. The final octet of the mech encoding should +diff --git a/src/tests/gssapi/Makefile.in b/src/tests/gssapi/Makefile.in +index 5cc1e0f58..68c132b79 100644 +--- a/src/tests/gssapi/Makefile.in ++++ b/src/tests/gssapi/Makefile.in +@@ -9,33 +9,33 @@ LOCALINCLUDES = -I$(srcdir)/../../lib/gssapi/mechglue \ + -I../../lib/gssapi/generic + + SRCS= $(srcdir)/ccinit.c $(srcdir)/ccrefresh.c $(srcdir)/common.c \ +- $(srcdir)/t_accname.c $(srcdir)/t_add_cred.c $(srcdir)/t_ccselect.c \ +- $(srcdir)/t_ciflags.c $(srcdir)/t_context.c $(srcdir)/t_credstore.c \ +- $(srcdir)/t_enctypes.c $(srcdir)/t_err.c $(srcdir)/t_export_cred.c \ +- $(srcdir)/t_export_name.c $(srcdir)/t_gssexts.c \ +- $(srcdir)/t_imp_cred.c $(srcdir)/t_imp_name.c $(srcdir)/t_invalid.c \ +- $(srcdir)/t_inq_cred.c $(srcdir)/t_inq_ctx.c \ ++ $(srcdir)/t_accname.c $(srcdir)/t_add_cred.c $(srcdir)/t_bindings.c \ ++ $(srcdir)/t_ccselect.c $(srcdir)/t_ciflags.c $(srcdir)/t_context.c \ ++ $(srcdir)/t_credstore.c $(srcdir)/t_enctypes.c $(srcdir)/t_err.c \ ++ $(srcdir)/t_export_cred.c $(srcdir)/t_export_name.c \ ++ $(srcdir)/t_gssexts.c $(srcdir)/t_imp_cred.c $(srcdir)/t_imp_name.c \ ++ $(srcdir)/t_invalid.c $(srcdir)/t_inq_cred.c $(srcdir)/t_inq_ctx.c \ + $(srcdir)/t_inq_mechs_name.c $(srcdir)/t_iov.c \ + $(srcdir)/t_lifetime.c $(srcdir)/t_namingexts.c $(srcdir)/t_oid.c \ + $(srcdir)/t_pcontok.c $(srcdir)/t_prf.c $(srcdir)/t_s4u.c \ + $(srcdir)/t_s4u2proxy_krb5.c $(srcdir)/t_saslname.c \ + $(srcdir)/t_spnego.c $(srcdir)/t_srcattrs.c + +-OBJS= ccinit.o ccrefresh.o common.o t_accname.o t_add_cred.o t_ccselect.o \ +- t_ciflags.o t_context.o t_credstore.o t_enctypes.o t_err.o \ +- t_export_cred.o t_export_name.o t_gssexts.o t_imp_cred.o t_imp_name.o \ +- t_invalid.o t_inq_cred.o t_inq_ctx.o t_inq_mechs_name.o t_iov.o \ +- t_lifetime.o t_namingexts.o t_oid.o t_pcontok.o t_prf.o t_s4u.o \ +- t_s4u2proxy_krb5.o t_saslname.o t_spnego.o t_srcattrs.o ++OBJS= ccinit.o ccrefresh.o common.o t_accname.o t_add_cred.o t_bindings.o \ ++ t_ccselect.o t_ciflags.o t_context.o t_credstore.o t_enctypes.o \ ++ t_err.o t_export_cred.o t_export_name.o t_gssexts.o t_imp_cred.o \ ++ t_imp_name.o t_invalid.o t_inq_cred.o t_inq_ctx.o t_inq_mechs_name.o \ ++ t_iov.o t_lifetime.o t_namingexts.o t_oid.o t_pcontok.o t_prf.o \ ++ t_s4u.o t_s4u2proxy_krb5.o t_saslname.o t_spnego.o t_srcattrs.o + + COMMON_DEPS= common.o $(GSS_DEPLIBS) $(KRB5_BASE_DEPLIBS) + COMMON_LIBS= common.o $(GSS_LIBS) $(KRB5_BASE_LIBS) + +-all: ccinit ccrefresh t_accname t_add_cred t_ccselect t_ciflags t_context \ +- t_credstore t_enctypes t_err t_export_cred t_export_name t_gssexts \ +- t_imp_cred t_imp_name t_invalid t_inq_cred t_inq_ctx t_inq_mechs_name \ +- t_iov t_lifetime t_namingexts t_oid t_pcontok t_prf t_s4u \ +- t_s4u2proxy_krb5 t_saslname t_spnego t_srcattrs ++all: ccinit ccrefresh t_accname t_add_cred t_bindings t_ccselect t_ciflags \ ++ t_context t_credstore t_enctypes t_err t_export_cred t_export_name \ ++ t_gssexts t_imp_cred t_imp_name t_invalid t_inq_cred t_inq_ctx \ ++ t_inq_mechs_name t_iov t_lifetime t_namingexts t_oid t_pcontok t_prf \ ++ t_s4u t_s4u2proxy_krb5 t_saslname t_spnego t_srcattrs + + check-unix: t_oid + $(RUN_TEST) ./t_invalid +@@ -43,11 +43,12 @@ check-unix: t_oid + $(RUN_TEST) ./t_prf + $(RUN_TEST) ./t_imp_name + +-check-pytests: ccinit ccrefresh t_accname t_add_cred t_ccselect t_ciflags \ +- t_context t_credstore t_enctypes t_err t_export_cred t_export_name \ +- t_imp_cred t_inq_cred t_inq_ctx t_inq_mechs_name t_iov t_lifetime \ +- t_pcontok t_s4u t_s4u2proxy_krb5 t_spnego t_srcattrs ++check-pytests: ccinit ccrefresh t_accname t_add_cred t_bindings t_ccselect \ ++ t_ciflags t_context t_credstore t_enctypes t_err t_export_cred \ ++ t_export_name t_imp_cred t_inq_cred t_inq_ctx t_inq_mechs_name t_iov \ ++ t_lifetime t_pcontok t_s4u t_s4u2proxy_krb5 t_spnego t_srcattrs + $(RUNPYTEST) $(srcdir)/t_gssapi.py $(PYTESTFLAGS) ++ $(RUNPYTEST) $(srcdir)/t_bindings.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_ccselect.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_client_keytab.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_enctypes.py $(PYTESTFLAGS) +@@ -64,6 +65,8 @@ t_accname: t_accname.o $(COMMON_DEPS) + $(CC_LINK) -o $@ t_accname.o $(COMMON_LIBS) + t_add_cred: t_add_cred.o $(COMMON_DEPS) + $(CC_LINK) -o $@ t_add_cred.o $(COMMON_LIBS) ++t_bindings: t_bindings.o $(COMMON_DEPS) ++ $(CC_LINK) -o $@ t_bindings.o $(COMMON_LIBS) + t_ccselect: t_ccselect.o $(COMMON_DEPS) + $(CC_LINK) -o $@ t_ccselect.o $(COMMON_LIBS) + t_ciflags: t_ciflags.o $(COMMON_DEPS) +@@ -118,8 +121,8 @@ t_srcattrs: t_srcattrs.o $(COMMON_DEPS) + $(CC_LINK) -o $@ t_srcattrs.o $(COMMON_LIBS) + + clean: +- $(RM) ccinit ccrefresh t_accname t_add_cred t_ccselect t_ciflags +- $(RM) t_context t_credstore t_enctypes t_err t_export_cred ++ $(RM) ccinit ccrefresh t_accname t_add_cred t_bindings t_ccselect ++ $(RM) t_ciflags t_context t_credstore t_enctypes t_err t_export_cred + $(RM) t_export_name t_gssexts t_imp_cred t_imp_name t_invalid + $(RM) t_inq_cred t_inq_ctx t_inq_mechs_name t_iov t_lifetime + $(RM) t_namingexts t_oid t_pcontok t_prf t_s4u t_s4u2proxy_krb5 +diff --git a/src/tests/gssapi/common.c b/src/tests/gssapi/common.c +index 83e9d9bb8..7ba72f7b2 100644 +--- a/src/tests/gssapi/common.c ++++ b/src/tests/gssapi/common.c +@@ -115,6 +115,20 @@ establish_contexts(gss_OID imech, gss_cred_id_t icred, gss_cred_id_t acred, + gss_name_t tname, OM_uint32 flags, gss_ctx_id_t *ictx, + gss_ctx_id_t *actx, gss_name_t *src_name, gss_OID *amech, + gss_cred_id_t *deleg_cred) ++{ ++ return establish_contexts_ex(imech, icred, acred, tname, flags, ictx, actx, ++ GSS_C_NO_CHANNEL_BINDINGS, ++ GSS_C_NO_CHANNEL_BINDINGS, NULL, src_name, ++ amech, deleg_cred); ++} ++ ++void ++establish_contexts_ex(gss_OID imech, gss_cred_id_t icred, gss_cred_id_t acred, ++ gss_name_t tname, OM_uint32 flags, gss_ctx_id_t *ictx, ++ gss_ctx_id_t *actx, gss_channel_bindings_t icb, ++ gss_channel_bindings_t acb, OM_uint32 *aret_flags, ++ gss_name_t *src_name, gss_OID *amech, ++ gss_cred_id_t *deleg_cred) + { + OM_uint32 minor, imaj, amaj; + gss_buffer_desc itok, atok; +@@ -126,17 +140,16 @@ establish_contexts(gss_OID imech, gss_cred_id_t icred, gss_cred_id_t acred, + for (;;) { + (void)gss_release_buffer(&minor, &itok); + imaj = gss_init_sec_context(&minor, icred, ictx, tname, imech, flags, +- GSS_C_INDEFINITE, +- GSS_C_NO_CHANNEL_BINDINGS, &atok, NULL, +- &itok, NULL, NULL); ++ GSS_C_INDEFINITE, icb, &atok, NULL, &itok, ++ NULL, NULL); + check_gsserr("gss_init_sec_context", imaj, minor); + if (amaj == GSS_S_COMPLETE) + break; + + (void)gss_release_buffer(&minor, &atok); +- amaj = gss_accept_sec_context(&minor, actx, acred, &itok, +- GSS_C_NO_CHANNEL_BINDINGS, src_name, +- amech, &atok, NULL, NULL, deleg_cred); ++ amaj = gss_accept_sec_context(&minor, actx, acred, &itok, acb, ++ src_name, amech, &atok, aret_flags, NULL, ++ deleg_cred); + check_gsserr("gss_accept_sec_context", amaj, minor); + (void)gss_release_buffer(&minor, &itok); + if (imaj == GSS_S_COMPLETE) +diff --git a/src/tests/gssapi/common.h b/src/tests/gssapi/common.h +index ae11b51d4..a5c8f87e6 100644 +--- a/src/tests/gssapi/common.h ++++ b/src/tests/gssapi/common.h +@@ -62,6 +62,15 @@ void establish_contexts(gss_OID imech, gss_cred_id_t icred, + gss_name_t *src_name, gss_OID *amech, + gss_cred_id_t *deleg_cred); + ++/* Establish contexts with channel bindings. */ ++void establish_contexts_ex(gss_OID imech, gss_cred_id_t icred, ++ gss_cred_id_t acred, gss_name_t tname, ++ OM_uint32 flags, gss_ctx_id_t *ictx, ++ gss_ctx_id_t *actx, gss_channel_bindings_t icb, ++ gss_channel_bindings_t acb, OM_uint32 *aret_flags, ++ gss_name_t *src_name, gss_OID *amech, ++ gss_cred_id_t *deleg_cred); ++ + /* Export *cred to a token, then release *cred and replace it by re-importing + * the token. */ + void export_import_cred(gss_cred_id_t *cred); +diff --git a/src/tests/gssapi/deps b/src/tests/gssapi/deps +index acd0e96f8..73e4d9a74 100644 +--- a/src/tests/gssapi/deps ++++ b/src/tests/gssapi/deps +@@ -33,6 +33,10 @@ $(OUTPRE)t_add_cred.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ + common.h t_add_cred.c ++$(OUTPRE)t_bindings.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ ++ $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ ++ $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ ++ common.h t_bindings.c + $(OUTPRE)t_ccselect.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ +diff --git a/src/tests/gssapi/t_bindings.c b/src/tests/gssapi/t_bindings.c +new file mode 100644 +index 000000000..e8906715b +--- /dev/null ++++ b/src/tests/gssapi/t_bindings.c +@@ -0,0 +1,111 @@ ++/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ ++/* ++ * Copyright (C) 2020 by Red Hat, Inc. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ++ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, ++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED ++ * OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include ++#include ++#include ++ ++#include "common.h" ++ ++/* ++ * Establish contexts (without and with GSS_C_DCE_STYLE) with the default ++ * initiator name, a specified principal name as target name, initiator ++ * bindings, and acceptor bindings. If any call is unsuccessful, display an ++ * error message. Output "yes" or "no" to indicate whether the contexts were ++ * reported as channel-bound on the acceptor. Exit with status 0 if all ++ * operations are successful, or 1 if not. ++ * ++ * Usage: ./t_bindings [-s] targetname icb acb ++ * ++ * An icb or abc value of "-" will not specify channel bindings. ++ */ ++ ++int ++main(int argc, char *argv[]) ++{ ++ OM_uint32 minor, flags1, flags2; ++ gss_name_t target_name; ++ gss_ctx_id_t ictx, actx; ++ struct gss_channel_bindings_struct icb_data = {0}, acb_data = {0}; ++ gss_channel_bindings_t icb = GSS_C_NO_CHANNEL_BINDINGS; ++ gss_channel_bindings_t acb = GSS_C_NO_CHANNEL_BINDINGS; ++ gss_OID_desc *mech; ++ ++ argv++; ++ argc--; ++ if (*argv != NULL && strcmp(*argv, "-s") == 0) { ++ mech = &mech_spnego; ++ argv++; ++ argc--; ++ } else { ++ mech = &mech_krb5; ++ } ++ ++ if (argc != 3) { ++ fprintf(stderr, "Usage: t_bindings [-s] targetname icb acb\n"); ++ return 1; ++ } ++ ++ target_name = import_name(argv[0]); ++ ++ if (strcmp(argv[1], "-") != 0) { ++ icb_data.application_data.length = strlen(argv[1]); ++ icb_data.application_data.value = argv[1]; ++ icb = &icb_data; ++ } ++ ++ if (strcmp(argv[2], "-") != 0) { ++ acb_data.application_data.length = strlen(argv[2]); ++ acb_data.application_data.value = argv[2]; ++ acb = &acb_data; ++ } ++ ++ establish_contexts_ex(mech, GSS_C_NO_CREDENTIAL, GSS_C_NO_CREDENTIAL, ++ target_name, 0, &ictx, &actx, icb, acb, &flags1, ++ NULL, NULL, NULL); ++ ++ /* Try again with GSS_C_DCE_STYLE */ ++ (void)gss_delete_sec_context(&minor, &ictx, NULL); ++ (void)gss_delete_sec_context(&minor, &actx, NULL); ++ ++ establish_contexts_ex(mech, GSS_C_NO_CREDENTIAL, GSS_C_NO_CREDENTIAL, ++ target_name, GSS_C_DCE_STYLE, &ictx, &actx, icb, acb, ++ &flags2, NULL, NULL, NULL); ++ assert((flags1 & GSS_C_CHANNEL_BOUND_FLAG) == ++ (flags2 & GSS_C_CHANNEL_BOUND_FLAG)); ++ printf("%s\n", (flags1 & GSS_C_CHANNEL_BOUND_FLAG) ? "yes" : "no"); ++ ++ (void)gss_delete_sec_context(&minor, &ictx, NULL); ++ (void)gss_delete_sec_context(&minor, &actx, NULL); ++ (void)gss_release_name(&minor, &target_name); ++ ++ return 0; ++} +diff --git a/src/tests/gssapi/t_bindings.py b/src/tests/gssapi/t_bindings.py +new file mode 100644 +index 000000000..f377977b6 +--- /dev/null ++++ b/src/tests/gssapi/t_bindings.py +@@ -0,0 +1,43 @@ ++from k5test import * ++ ++realm = K5Realm() ++server = 'p:' + realm.host_princ ++ ++mark('krb5 channel bindings') ++realm.run(['./t_bindings', server, '-', '-'], expected_msg='no') ++realm.run(['./t_bindings', server, 'a', '-'], expected_msg='no') ++realm.run(['./t_bindings', server, 'a', 'a'], expected_msg='yes') ++realm.run(['./t_bindings', server, '-', 'a'], expected_msg='no') ++realm.run(['./t_bindings', server, 'a', 'x'], ++ expected_code=1, expected_msg='Incorrect channel bindings') ++ ++mark('SPNEGO channel bindings') ++realm.run(['./t_bindings', '-s', server, '-', '-'], expected_msg='no') ++realm.run(['./t_bindings', '-s', server, 'a', '-'], expected_msg='no') ++realm.run(['./t_bindings', '-s', server, 'a', 'a'], expected_msg='yes') ++realm.run(['./t_bindings', '-s', server, '-', 'a'], expected_msg='no') ++realm.run(['./t_bindings', '-s', server, 'a', 'x'], ++ expected_code=1, expected_msg='Incorrect channel bindings') ++ ++client_aware_conf = {'libdefaults': {'client_aware_channel_bindings': 'true'}} ++e = realm.special_env('cb_aware', False, krb5_conf=client_aware_conf) ++ ++mark('krb5 client_aware_channel_bindings') ++realm.run(['./t_bindings', server, '-', '-'], env=e, expected_msg='no') ++realm.run(['./t_bindings', server, 'a', '-'], env=e, expected_msg='no') ++realm.run(['./t_bindings', server, 'a', 'a'], env=e, expected_msg='yes') ++realm.run(['./t_bindings', server, '-', 'a'], env=e, ++ expected_code=1, expected_msg='Incorrect channel bindings') ++realm.run(['./t_bindings', server, 'a', 'x'], env=e, ++ expected_code=1, expected_msg='Incorrect channel bindings') ++ ++mark('SPNEGO client_aware_channel_bindings') ++realm.run(['./t_bindings', '-s', server, '-', '-'], env=e, expected_msg='no') ++realm.run(['./t_bindings', '-s', server, 'a', '-'], env=e, expected_msg='no') ++realm.run(['./t_bindings', '-s', server, 'a', 'a'], env=e, expected_msg='yes') ++realm.run(['./t_bindings', '-s', server, '-', 'a'], env=e, ++ expected_code=1, expected_msg='Incorrect channel bindings') ++realm.run(['./t_bindings', '-s', server, 'a', 'x'], env=e, ++ expected_code=1, expected_msg='Incorrect channel bindings') ++ ++success('channel bindings tests') +diff --git a/src/tests/gssapi/t_negoex.py b/src/tests/gssapi/t_negoex.py +index 88470d2fa..a218899c4 100644 +--- a/src/tests/gssapi/t_negoex.py ++++ b/src/tests/gssapi/t_negoex.py +@@ -139,4 +139,11 @@ msgs = ('sending [3]AP_REQUEST', 'sending [7]CHALLENGE', 'sending [8]VERIFY', + 'sending [11]CHALLENGE', 'sending [12]VERIFY', 'sending [13]VERIFY') + test({'HOPS': '4', 'KEY': 'accept-always'}, expected_trace=()) + ++mark('channel bindings') ++e = realm.env.copy() ++e.update({'HOPS': '1', 'GSS_INIT_BINDING': 'a', 'GSS_ACCEPT_BINDING': 'b'}) ++# The test mech will verify that the bindings are communicated to the ++# mech, but does not set the channel-bound flag. ++realm.run(['./t_bindings', '-s', 'h:host', 'a', 'b'], env=e, expected_msg='no') ++ + success('NegoEx tests') diff --git a/root/ppg/common/deps/krb5/rpm/Add-client_aware_channel_bindings-option.patch b/root/ppg/common/deps/krb5/rpm/Add-client_aware_channel_bindings-option.patch new file mode 100644 index 00000000..9d0531ea --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Add-client_aware_channel_bindings-option.patch @@ -0,0 +1,265 @@ +From 64f643a7f798c5528182dc068f15dca7b3f2d8a1 Mon Sep 17 00:00:00 2001 +From: Isaac Boukris +Date: Tue, 10 Mar 2020 13:13:17 +0100 +Subject: [PATCH] Add client_aware_channel_bindings option + +Add client support for KERB_AP_OPTIONS_CBT in the form of a profile +option "client_aware_gss_bindings". Adjust the make_etype_list() +helper so that enctype negotiation and AP_OPTIONS can be included in +the same IF-RELEVANT wrapper. + +[ghudson@mit.edu: refactored; edited documentation; wrote commit +message] + +ticket: 8900 +(cherry picked from commit 225e6ef7f021cd1a8ef2a054af0ca58b7288fd81) +(cherry picked from commit 2a08fe3d2d1972df4ffe37d4bb64b161889ff988) +--- + doc/admin/conf_files/krb5_conf.rst | 6 + + src/include/k5-int.h | 1 + + src/lib/krb5/krb/mk_req_ext.c | 177 +++++++++++++++-------------- + 3 files changed, 98 insertions(+), 86 deletions(-) + +diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst +index 3a8b9cf47..315253e37 100644 +--- a/doc/admin/conf_files/krb5_conf.rst ++++ b/doc/admin/conf_files/krb5_conf.rst +@@ -389,6 +389,12 @@ The libdefaults section may contain any of the following relations: + credentials will fail if the client machine does not have a + keytab. The default value is false. + ++**client_aware_channel_bindings** ++ If this flag is true, then all application protocol authentication ++ requests will be flagged to indicate that the application supports ++ channel bindings when operating over a secure channel. The ++ default value is false. ++ + .. _realms: + + [realms] +diff --git a/src/include/k5-int.h b/src/include/k5-int.h +index 0d9af3d95..eb18a4cd6 100644 +--- a/src/include/k5-int.h ++++ b/src/include/k5-int.h +@@ -299,6 +299,7 @@ typedef unsigned char u_char; + #define KRB5_CONF_V4_INSTANCE_CONVERT "v4_instance_convert" + #define KRB5_CONF_V4_REALM "v4_realm" + #define KRB5_CONF_VERIFY_AP_REQ_NOFAIL "verify_ap_req_nofail" ++#define KRB5_CONF_CLIENT_AWARE_GSS_BINDINGS "client_aware_channel_bindings" + + /* Cache configuration variables */ + #define KRB5_CC_CONF_FAST_AVAIL "fast_avail" +diff --git a/src/lib/krb5/krb/mk_req_ext.c b/src/lib/krb5/krb/mk_req_ext.c +index 9fc6a0e52..08504860c 100644 +--- a/src/lib/krb5/krb/mk_req_ext.c ++++ b/src/lib/krb5/krb/mk_req_ext.c +@@ -68,10 +68,9 @@ + */ + + static krb5_error_code +-make_etype_list(krb5_context context, +- krb5_enctype *desired_etypes, +- krb5_enctype tkt_enctype, +- krb5_authdata ***authdata); ++make_ap_authdata(krb5_context context, krb5_enctype *desired_enctypes, ++ krb5_enctype tkt_enctype, krb5_boolean client_aware_cb, ++ krb5_authdata ***authdata_out); + + static krb5_error_code + generate_authenticator(krb5_context, +@@ -263,7 +262,8 @@ generate_authenticator(krb5_context context, krb5_authenticator *authent, + krb5_enctype tkt_enctype) + { + krb5_error_code retval; +- krb5_authdata **ext_authdata = NULL; ++ krb5_authdata **ext_authdata = NULL, **ap_authdata, **combined; ++ int client_aware_cb; + + authent->client = client; + authent->checksum = cksum; +@@ -297,99 +297,104 @@ generate_authenticator(krb5_context context, krb5_authenticator *authent, + krb5_free_authdata(context, ext_authdata); + } + +- /* Only send EtypeList if we prefer another enctype to tkt_enctype */ +- if (desired_etypes != NULL && desired_etypes[0] != tkt_enctype) { +- TRACE_MK_REQ_ETYPES(context, desired_etypes); +- retval = make_etype_list(context, desired_etypes, tkt_enctype, +- &authent->authorization_data); ++ retval = profile_get_boolean(context->profile, KRB5_CONF_LIBDEFAULTS, ++ KRB5_CONF_CLIENT_AWARE_GSS_BINDINGS, NULL, ++ FALSE, &client_aware_cb); ++ if (retval) ++ return retval; ++ ++ /* Add etype negotiation or channel-binding awareness authdata to the ++ * front, if appropriate. */ ++ retval = make_ap_authdata(context, desired_etypes, tkt_enctype, ++ client_aware_cb, &ap_authdata); ++ if (retval) ++ return retval; ++ if (ap_authdata != NULL) { ++ retval = krb5_merge_authdata(context, ap_authdata, ++ authent->authorization_data, &combined); ++ krb5_free_authdata(context, ap_authdata); + if (retval) + return retval; ++ krb5_free_authdata(context, authent->authorization_data); ++ authent->authorization_data = combined; + } + + return(krb5_us_timeofday(context, &authent->ctime, &authent->cusec)); + } + +-/* RFC 4537 */ ++/* Set *out to a DER-encoded RFC 4537 etype list, or to NULL if no etype list ++ * should be sent. */ + static krb5_error_code +-make_etype_list(krb5_context context, +- krb5_enctype *desired_etypes, +- krb5_enctype tkt_enctype, +- krb5_authdata ***authdata) ++make_etype_list(krb5_context context, krb5_enctype *desired_enctypes, ++ krb5_enctype tkt_enctype, krb5_data **out) + { +- krb5_error_code code; +- krb5_etype_list etypes; +- krb5_data *enc_etype_list; +- krb5_data *ad_if_relevant; +- krb5_authdata *etype_adata[2], etype_adatum, **adata; +- int i; ++ krb5_etype_list etlist; ++ int count; + +- etypes.etypes = desired_etypes; ++ *out = NULL; + +- for (etypes.length = 0; +- etypes.etypes[etypes.length] != ENCTYPE_NULL; +- etypes.length++) +- { +- /* +- * RFC 4537: +- * +- * If the enctype of the ticket session key is included in the enctype +- * list sent by the client, it SHOULD be the last on the list; +- */ +- if (etypes.length && etypes.etypes[etypes.length - 1] == tkt_enctype) ++ /* Only send a list if we prefer another enctype to tkt_enctype. */ ++ if (desired_enctypes == NULL || desired_enctypes[0] == tkt_enctype) ++ return 0; ++ ++ /* Count elements of desired_etypes, stopping at tkt_enctypes if present. ++ * (Per RFC 4537, it must be the last option if it is included.) */ ++ for (count = 0; desired_enctypes[count] != ENCTYPE_NULL; count++) { ++ if (count > 0 && desired_enctypes[count - 1] == tkt_enctype) + break; + } + +- code = encode_krb5_etype_list(&etypes, &enc_etype_list); +- if (code) { +- return code; +- } +- +- etype_adatum.magic = KV5M_AUTHDATA; +- etype_adatum.ad_type = KRB5_AUTHDATA_ETYPE_NEGOTIATION; +- etype_adatum.length = enc_etype_list->length; +- etype_adatum.contents = (krb5_octet *)enc_etype_list->data; +- +- etype_adata[0] = &etype_adatum; +- etype_adata[1] = NULL; +- +- /* Wrap in AD-IF-RELEVANT container */ +- code = encode_krb5_authdata(etype_adata, &ad_if_relevant); +- if (code) { +- krb5_free_data(context, enc_etype_list); +- return code; +- } +- +- krb5_free_data(context, enc_etype_list); +- +- adata = *authdata; +- if (adata == NULL) { +- adata = (krb5_authdata **)calloc(2, sizeof(krb5_authdata *)); +- i = 0; +- } else { +- for (i = 0; adata[i] != NULL; i++) +- ; +- +- adata = (krb5_authdata **)realloc(*authdata, +- (i + 2) * sizeof(krb5_authdata *)); +- } +- if (adata == NULL) { +- krb5_free_data(context, ad_if_relevant); +- return ENOMEM; +- } +- *authdata = adata; +- +- adata[i] = (krb5_authdata *)malloc(sizeof(krb5_authdata)); +- if (adata[i] == NULL) { +- krb5_free_data(context, ad_if_relevant); +- return ENOMEM; +- } +- adata[i]->magic = KV5M_AUTHDATA; +- adata[i]->ad_type = KRB5_AUTHDATA_IF_RELEVANT; +- adata[i]->length = ad_if_relevant->length; +- adata[i]->contents = (krb5_octet *)ad_if_relevant->data; +- free(ad_if_relevant); /* contents owned by adata[i] */ +- +- adata[i + 1] = NULL; +- +- return 0; ++ etlist.etypes = desired_enctypes; ++ etlist.length = count; ++ return encode_krb5_etype_list(&etlist, out); ++} ++ ++/* Set *authdata_out to appropriate authenticator authdata for the request, ++ * encoded in a single AD_IF_RELEVANT element. */ ++static krb5_error_code ++make_ap_authdata(krb5_context context, krb5_enctype *desired_enctypes, ++ krb5_enctype tkt_enctype, krb5_boolean client_aware_cb, ++ krb5_authdata ***authdata_out) ++{ ++ krb5_error_code ret; ++ krb5_authdata etypes_ad, flags_ad, *list[3]; ++ krb5_data *der_etypes = NULL; ++ size_t count = 0; ++ uint8_t flagbuf[4]; ++ const uint32_t KERB_AP_OPTIONS_CBT = 0x4000; ++ ++ *authdata_out = NULL; ++ ++ /* Include an ETYPE_NEGOTIATION element if appropriate. */ ++ ret = make_etype_list(context, desired_enctypes, tkt_enctype, &der_etypes); ++ if (ret) ++ goto cleanup; ++ if (der_etypes != NULL) { ++ etypes_ad.magic = KV5M_AUTHDATA; ++ etypes_ad.ad_type = KRB5_AUTHDATA_ETYPE_NEGOTIATION; ++ etypes_ad.length = der_etypes->length; ++ etypes_ad.contents = (uint8_t *)der_etypes->data; ++ list[count++] = &etypes_ad; ++ } ++ ++ /* Include an AP_OPTIONS element if the CBT flag is configured. */ ++ if (client_aware_cb != 0) { ++ store_32_le(KERB_AP_OPTIONS_CBT, flagbuf); ++ flags_ad.magic = KV5M_AUTHDATA; ++ flags_ad.ad_type = KRB5_AUTHDATA_AP_OPTIONS; ++ flags_ad.length = 4; ++ flags_ad.contents = flagbuf; ++ list[count++] = &flags_ad; ++ } ++ ++ if (count > 0) { ++ list[count] = NULL; ++ ret = krb5_encode_authdata_container(context, ++ KRB5_AUTHDATA_IF_RELEVANT, ++ list, authdata_out); ++ } ++ ++cleanup: ++ krb5_free_data(context, der_etypes); ++ return ret; + } diff --git a/root/ppg/common/deps/krb5/rpm/Add-finalization-safety-check-to-com_err.patch b/root/ppg/common/deps/krb5/rpm/Add-finalization-safety-check-to-com_err.patch new file mode 100644 index 00000000..e2740b0d --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Add-finalization-safety-check-to-com_err.patch @@ -0,0 +1,54 @@ +From 9a9ab4b2cad1597cbafbae756483aefa6e36f1eb Mon Sep 17 00:00:00 2001 +From: Jiri Sasek +Date: Fri, 13 Mar 2020 19:02:58 +0100 +Subject: [PATCH] Add finalization safety check to com_err + +If the linker erroneously runs the libkrb5 finalizer after the +libcom_err finalizer, the consequent remove_error_table() calls could +crash due to accessing a destroyed mutex or an invalid et_list +pointer. Add an unsynchronized check on finalized in +remove_error_table(), and set et_list to null in com_err_terminate() +after destroying the list. + +[ghudson@mit.edu: minimized code hanges; rewrote comment and commit +message] + +ticket: 8890 (new) +(cherry picked from commit 9d654aa05e26bbf22f140abde3436afeff2fdf8d) +(cherry picked from commit c7a37d3e87132864ebc44710baf1d50a69682b5c) +--- + src/util/et/error_message.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/src/util/et/error_message.c b/src/util/et/error_message.c +index d7069a9df..7dc02a34e 100644 +--- a/src/util/et/error_message.c ++++ b/src/util/et/error_message.c +@@ -26,7 +26,7 @@ + + static struct et_list *et_list; + static k5_mutex_t et_list_lock = K5_MUTEX_PARTIAL_INITIALIZER; +-static int terminated = 0; /* for debugging shlib fini sequence errors */ ++static int terminated = 0; /* for safety and finalization debugging */ + + MAKE_INIT_FUNCTION(com_err_initialize); + MAKE_FINI_FUNCTION(com_err_terminate); +@@ -69,6 +69,7 @@ void com_err_terminate(void) + enext = e->next; + free(e); + } ++ et_list = NULL; + k5_mutex_unlock(&et_list_lock); + k5_mutex_destroy(&et_list_lock); + terminated = 1; +@@ -280,6 +281,10 @@ remove_error_table(const struct error_table *et) + { + struct et_list **ep, *e; + ++ /* Safety check in case libraries are finalized in the wrong order. */ ++ if (terminated) ++ return ENOENT; ++ + if (CALL_INIT_FUNCTION(com_err_initialize)) + return 0; + k5_mutex_lock(&et_list_lock); diff --git a/root/ppg/common/deps/krb5/rpm/Add-recursion-limit-for-ASN.1-indefinite-lengths.patch b/root/ppg/common/deps/krb5/rpm/Add-recursion-limit-for-ASN.1-indefinite-lengths.patch new file mode 100644 index 00000000..41cf09cf --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Add-recursion-limit-for-ASN.1-indefinite-lengths.patch @@ -0,0 +1,97 @@ +From 3c47e4adbed5e0a2e7f3993a24097889216a9d50 Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Sat, 31 Oct 2020 17:07:05 -0400 +Subject: [PATCH] Add recursion limit for ASN.1 indefinite lengths + +The libkrb5 ASN.1 decoder supports BER indefinite lengths. It +computes the tag length using recursion; the lack of a recursion limit +allows an attacker to overrun the stack and cause the process to +crash. Reported by Demi Obenour. + +CVE-2020-28196: + +In MIT krb5 releases 1.11 and later, an unauthenticated attacker can +cause a denial of service for any client or server to which it can +send an ASN.1-encoded Kerberos message of sufficient length. + +(cherry picked from commit 57415dda6cf04e73ffc3723be518eddfae599bfd) + +ticket: 8959 +version_fixed: 1.18.3 + +(cherry picked from commit 207ad69c87cf1b5c047d6c0c0165e5afe29700a6) +--- + src/lib/krb5/asn.1/asn1_encode.c | 16 +++++++++------- + 1 file changed, 9 insertions(+), 7 deletions(-) + +diff --git a/src/lib/krb5/asn.1/asn1_encode.c b/src/lib/krb5/asn.1/asn1_encode.c +index a160cf4fe..cd6b879f7 100644 +--- a/src/lib/krb5/asn.1/asn1_encode.c ++++ b/src/lib/krb5/asn.1/asn1_encode.c +@@ -356,7 +356,7 @@ make_tag(asn1buf *buf, const taginfo *t, size_t len) + static krb5_error_code + get_tag(const uint8_t *asn1, size_t len, taginfo *tag_out, + const uint8_t **contents_out, size_t *clen_out, +- const uint8_t **remainder_out, size_t *rlen_out) ++ const uint8_t **remainder_out, size_t *rlen_out, int recursion) + { + krb5_error_code ret; + uint8_t o; +@@ -394,9 +394,11 @@ get_tag(const uint8_t *asn1, size_t len, taginfo *tag_out, + /* Indefinite form (should not be present in DER, but we accept it). */ + if (tag_out->construction != CONSTRUCTED) + return ASN1_MISMATCH_INDEF; ++ if (recursion >= 32) ++ return ASN1_OVERFLOW; + p = asn1; + while (!(len >= 2 && p[0] == 0 && p[1] == 0)) { +- ret = get_tag(p, len, &t, &c, &clen, &p, &len); ++ ret = get_tag(p, len, &t, &c, &clen, &p, &len, recursion + 1); + if (ret) + return ret; + } +@@ -613,7 +615,7 @@ split_der(asn1buf *buf, uint8_t *const *der, size_t len, taginfo *tag_out) + const uint8_t *contents, *remainder; + size_t clen, rlen; + +- ret = get_tag(*der, len, tag_out, &contents, &clen, &remainder, &rlen); ++ ret = get_tag(*der, len, tag_out, &contents, &clen, &remainder, &rlen, 0); + if (ret) + return ret; + if (rlen != 0) +@@ -1199,7 +1201,7 @@ decode_atype(const taginfo *t, const uint8_t *asn1, size_t len, + const uint8_t *rem; + size_t rlen; + if (!tag->implicit) { +- ret = get_tag(asn1, len, &inner_tag, &asn1, &len, &rem, &rlen); ++ ret = get_tag(asn1, len, &inner_tag, &asn1, &len, &rem, &rlen, 0); + if (ret) + return ret; + /* Note: we don't check rlen (it should be 0). */ +@@ -1420,7 +1422,7 @@ decode_sequence(const uint8_t *asn1, size_t len, const struct seq_info *seq, + for (i = 0; i < seq->n_fields; i++) { + if (len == 0) + break; +- ret = get_tag(asn1, len, &t, &contents, &clen, &asn1, &len); ++ ret = get_tag(asn1, len, &t, &contents, &clen, &asn1, &len, 0); + if (ret) + goto error; + /* +@@ -1478,7 +1480,7 @@ decode_sequence_of(const uint8_t *asn1, size_t len, + *seq_out = NULL; + *count_out = 0; + while (len > 0) { +- ret = get_tag(asn1, len, &t, &contents, &clen, &asn1, &len); ++ ret = get_tag(asn1, len, &t, &contents, &clen, &asn1, &len, 0); + if (ret) + goto error; + if (!check_atype_tag(elemtype, &t)) { +@@ -1584,7 +1586,7 @@ k5_asn1_full_decode(const krb5_data *code, const struct atype_info *a, + + *retrep = NULL; + ret = get_tag((uint8_t *)code->data, code->length, &t, &contents, +- &clen, &remainder, &rlen); ++ &clen, &remainder, &rlen, 0); + if (ret) + return ret; + /* rlen should be 0, but we don't check it (and due to padding in diff --git a/root/ppg/common/deps/krb5/rpm/Add-request_timeout-configuration-parameter.patch b/root/ppg/common/deps/krb5/rpm/Add-request_timeout-configuration-parameter.patch new file mode 100644 index 00000000..dc0295a1 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Add-request_timeout-configuration-parameter.patch @@ -0,0 +1,226 @@ +From 433dd85aaf8d9ed0e923c873f107995232b94422 Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Thu, 26 Oct 2023 14:20:34 -0400 +Subject: [PATCH] Add request_timeout configuration parameter + +Add a parameter to limit the total amount of time taken for a KDC or +password change request. + +ticket: 9106 (new) +(cherry picked from commit 802318cda963456b3ed7856c836e89da891483be) +--- + doc/admin/conf_files/krb5_conf.rst | 9 ++++++ + src/include/k5-int.h | 2 ++ + src/lib/krb5/krb/init_ctx.c | 14 +++++++- + src/lib/krb5/os/sendto_kdc.c | 51 ++++++++++++++++++++---------- + 4 files changed, 58 insertions(+), 18 deletions(-) + +diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst +index 315253e378..557094f6a2 100644 +--- a/doc/admin/conf_files/krb5_conf.rst ++++ b/doc/admin/conf_files/krb5_conf.rst +@@ -357,6 +357,15 @@ The libdefaults section may contain any of the following relations: + (:ref:`duration` string.) Sets the default renewable lifetime + for initial ticket requests. The default value is 0. + ++**request_timeout** ++ (:ref:`duration` string.) Sets the maximum total time for KDC or ++ password change requests. This timeout does not affect the ++ intervals between requests, so setting a low timeout may result in ++ fewer requests being attempted and/or some servers not being ++ contacted. A value of 0 indicates no specific maximum, in which ++ case requests will time out if no server responds after several ++ tries. The default value is 0. (New in release 1.22.) ++ + **spake_preauth_groups** + A whitespace or comma-separated list of words which specifies the + groups allowed for SPAKE preauthentication. The possible values +diff --git a/src/include/k5-int.h b/src/include/k5-int.h +index 912aaedac4..9d5e41ca2c 100644 +--- a/src/include/k5-int.h ++++ b/src/include/k5-int.h +@@ -293,6 +293,7 @@ typedef unsigned char u_char; + #define KRB5_CONF_SPAKE_PREAUTH_INDICATOR "spake_preauth_indicator" + #define KRB5_CONF_SPAKE_PREAUTH_KDC_CHALLENGE "spake_preauth_kdc_challenge" + #define KRB5_CONF_SPAKE_PREAUTH_GROUPS "spake_preauth_groups" ++#define KRB5_CONF_REQUEST_TIMEOUT "request_timeout" + #define KRB5_CONF_TICKET_LIFETIME "ticket_lifetime" + #define KRB5_CONF_UDP_PREFERENCE_LIMIT "udp_preference_limit" + #define KRB5_CONF_UNLOCKITER "unlockiter" +@@ -1218,6 +1219,7 @@ struct _krb5_context { + kdb5_dal_handle *dal_handle; + /* allowable clock skew */ + krb5_deltat clockskew; ++ krb5_deltat req_timeout; + krb5_flags kdc_default_options; + krb5_flags library_options; + krb5_boolean profile_secure; +diff --git a/src/lib/krb5/krb/init_ctx.c b/src/lib/krb5/krb/init_ctx.c +index 9a4741fa64..1a6e0bf672 100644 +--- a/src/lib/krb5/krb/init_ctx.c ++++ b/src/lib/krb5/krb/init_ctx.c +@@ -163,7 +163,7 @@ krb5_init_context_profile(profile_t profile, krb5_flags flags, + } seed_data; + krb5_data seed; + int tmp; +- char *plugin_dir = NULL; ++ char *plugin_dir = NULL, *timeout_str = NULL; + + /* Verify some assumptions. If the assumptions hold and the + compiler is optimizing, this should result in no code being +@@ -257,6 +257,17 @@ krb5_init_context_profile(profile_t profile, krb5_flags flags, + get_integer(ctx, KRB5_CONF_CLOCKSKEW, DEFAULT_CLOCKSKEW, &tmp); + ctx->clockskew = tmp; + ++ retval = profile_get_string(ctx->profile, KRB5_CONF_LIBDEFAULTS, ++ KRB5_CONF_REQUEST_TIMEOUT, NULL, NULL, ++ &timeout_str); ++ if (retval) ++ goto cleanup; ++ if (timeout_str != NULL) { ++ retval = krb5_string_to_deltat(timeout_str, &ctx->req_timeout); ++ if (retval) ++ goto cleanup; ++ } ++ + get_integer(ctx, KRB5_CONF_KDC_DEFAULT_OPTIONS, KDC_OPT_RENEWABLE_OK, + &tmp); + ctx->kdc_default_options = tmp; +@@ -298,6 +309,7 @@ krb5_init_context_profile(profile_t profile, krb5_flags flags, + + cleanup: + profile_release_string(plugin_dir); ++ profile_release_string(timeout_str); + krb5_free_context(ctx); + return retval; + } +diff --git a/src/lib/krb5/os/sendto_kdc.c b/src/lib/krb5/os/sendto_kdc.c +index 8e4fcd2a38..f57117126e 100644 +--- a/src/lib/krb5/os/sendto_kdc.c ++++ b/src/lib/krb5/os/sendto_kdc.c +@@ -1390,34 +1390,41 @@ get_endtime(time_ms endtime, struct conn_state *conns) + + static krb5_boolean + service_fds(krb5_context context, struct select_state *selstate, +- time_ms interval, struct conn_state *conns, ++ time_ms interval, time_ms timeout, struct conn_state *conns, + struct select_state *seltemp, const krb5_data *realm, + int (*msg_handler)(krb5_context, const krb5_data *, void *), + void *msg_handler_data, struct conn_state **winner_out) + { + int e, selret = 0; +- time_ms endtime; ++ time_ms curtime, interval_end, endtime; + struct conn_state *state; + + *winner_out = NULL; + +- e = get_curtime_ms(&endtime); ++ e = get_curtime_ms(&curtime); + if (e) + return TRUE; +- endtime += interval; ++ interval_end = curtime + interval; + + e = 0; + while (selstate->nfds > 0) { +- e = cm_select_or_poll(selstate, get_endtime(endtime, conns), +- seltemp, &selret); ++ endtime = get_endtime(interval_end, conns); ++ /* Don't wait longer than the whole request should last. */ ++ if (timeout && endtime > timeout) ++ endtime = timeout; ++ e = cm_select_or_poll(selstate, endtime, seltemp, &selret); + if (e == EINTR) + continue; + if (e != 0) + break; + +- if (selret == 0) +- /* Timeout, return to caller. */ ++ if (selret == 0) { ++ /* We timed out. Stop if we hit the overall request timeout. */ ++ if (timeout && (get_curtime_ms(&curtime) || curtime >= timeout)) ++ return TRUE; ++ /* Otherwise return to the caller to send the next request. */ + return FALSE; ++ } + + /* Got something on a socket, process it. */ + for (state = conns; state != NULL; state = state->next) { +@@ -1490,7 +1497,7 @@ k5_sendto(krb5_context context, const krb5_data *message, + void *msg_handler_data) + { + int pass; +- time_ms delay; ++ time_ms delay, timeout = 0; + krb5_error_code retval; + struct conn_state *conns = NULL, *state, **tailptr, *next, *winner; + size_t s; +@@ -1500,6 +1507,13 @@ k5_sendto(krb5_context context, const krb5_data *message, + + *reply = empty_data(); + ++ if (context->req_timeout) { ++ retval = get_curtime_ms(&timeout); ++ if (retval) ++ return retval; ++ timeout += 1000 * context->req_timeout; ++ } ++ + /* One for use here, listing all our fds in use, and one for + * temporary use in service_fds, for the fds of interest. */ + sel_state = malloc(2 * sizeof(*sel_state)); +@@ -1527,8 +1541,9 @@ k5_sendto(krb5_context context, const krb5_data *message, + if (maybe_send(context, state, message, sel_state, realm, + callback_info)) + continue; +- done = service_fds(context, sel_state, 1000, conns, seltemp, +- realm, msg_handler, msg_handler_data, &winner); ++ done = service_fds(context, sel_state, 1000, timeout, conns, ++ seltemp, realm, msg_handler, msg_handler_data, ++ &winner); + } + } + +@@ -1540,13 +1555,13 @@ k5_sendto(krb5_context context, const krb5_data *message, + if (maybe_send(context, state, message, sel_state, realm, + callback_info)) + continue; +- done = service_fds(context, sel_state, 1000, conns, seltemp, ++ done = service_fds(context, sel_state, 1000, timeout, conns, seltemp, + realm, msg_handler, msg_handler_data, &winner); + } + + /* Wait for two seconds at the end of the first pass. */ + if (!done) { +- done = service_fds(context, sel_state, 2000, conns, seltemp, ++ done = service_fds(context, sel_state, 2000, timeout, conns, seltemp, + realm, msg_handler, msg_handler_data, &winner); + } + +@@ -1557,15 +1572,17 @@ k5_sendto(krb5_context context, const krb5_data *message, + if (maybe_send(context, state, message, sel_state, realm, + callback_info)) + continue; +- done = service_fds(context, sel_state, 1000, conns, seltemp, +- realm, msg_handler, msg_handler_data, &winner); ++ done = service_fds(context, sel_state, 1000, timeout, conns, ++ seltemp, realm, msg_handler, msg_handler_data, ++ &winner); + if (sel_state->nfds == 0) + break; + } + /* Wait for the delay backoff at the end of this pass. */ + if (!done) { +- done = service_fds(context, sel_state, delay, conns, seltemp, +- realm, msg_handler, msg_handler_data, &winner); ++ done = service_fds(context, sel_state, delay, timeout, conns, ++ seltemp, realm, msg_handler, msg_handler_data, ++ &winner); + } + if (sel_state->nfds == 0) + break; +-- +2.44.0 + diff --git a/root/ppg/common/deps/krb5/rpm/Add-support-for-start_realm-cache-config.patch b/root/ppg/common/deps/krb5/rpm/Add-support-for-start_realm-cache-config.patch new file mode 100644 index 00000000..b83092c8 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Add-support-for-start_realm-cache-config.patch @@ -0,0 +1,303 @@ +From bb5552ece2a351dc3ccab52cceea1eaffeacd768 Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Mon, 14 Dec 2020 13:16:17 -0500 +Subject: [PATCH] Add support for start_realm cache config + +When making TGS requests, if start_realm is set in the cache, use the +named realm to look up the initial TGT for referral or cross-realm +requests. (Also correct a comment in struct _tkt_creds_context: the +ccache field is an owner pointer, not an alias.) + +Add an internal API k5_cc_store_primary_cred(), which sets start_realm +if the cred being stored is a TGT for a realm other than the client +realm. Use this API when acquiring initial tickets with a +caller-specified output ccache, when renewing or validating tickets +with kinit, when accepting a delegated credential in a GSS context, +and when storing a single cred with kvno --out-cache. + +ticket: 8332 +tags: pullup +target_version: 1.19 + +(cherry picked from commit 0d56740ab9fcc40dc7f46c6fbebdf8f1214f9d96) +[rharwood@redhat.com: backport around spelling and canonicalization fallback] +--- + doc/formats/ccache_file_format.rst | 6 +++++ + src/clients/kinit/kinit.c | 2 +- + src/clients/kvno/kvno.c | 5 ++++- + src/include/k5-int.h | 4 ++++ + src/lib/gssapi/krb5/accept_sec_context.c | 2 +- + src/lib/krb5/ccache/ccfns.c | 20 +++++++++++++++++ + src/lib/krb5/krb/get_creds.c | 28 ++++++++++++++++++------ + src/lib/krb5/krb/get_in_tkt.c | 2 +- + src/lib/krb5/libkrb5.exports | 1 + + src/lib/krb5_32.def | 3 +++ + src/tests/t_crossrealm.py | 8 +++++++ + src/tests/t_pkinit.py | 3 +++ + 12 files changed, 73 insertions(+), 11 deletions(-) + +diff --git a/doc/formats/ccache_file_format.rst b/doc/formats/ccache_file_format.rst +index 6349e0d29..6138c1b58 100644 +--- a/doc/formats/ccache_file_format.rst ++++ b/doc/formats/ccache_file_format.rst +@@ -174,3 +174,9 @@ refresh_time + decimal representation of a timestamp at which the GSS mechanism + should attempt to refresh the credential cache from the client + keytab. ++ ++start_realm ++ This key indicates the realm of the ticket-granting ticket to be ++ used for TGS requests, when making a referrals request or ++ beginning a cross-realm request. If it is not present, the client ++ realm is used. +diff --git a/src/clients/kinit/kinit.c b/src/clients/kinit/kinit.c +index 3fdae2878..e5ebeb895 100644 +--- a/src/clients/kinit/kinit.c ++++ b/src/clients/kinit/kinit.c +@@ -828,7 +828,7 @@ k5_kinit(struct k_opts *opts, struct k5_data *k5) + if (opts->verbose) + fprintf(stderr, _("Initialized cache\n")); + +- ret = krb5_cc_store_cred(k5->ctx, k5->out_cc, &my_creds); ++ ret = k5_cc_store_primary_cred(k5->ctx, k5->out_cc, &my_creds); + if (ret) { + com_err(progname, ret, _("while storing credentials")); + goto cleanup; +diff --git a/src/clients/kvno/kvno.c b/src/clients/kvno/kvno.c +index c5f6bf700..f83c68a99 100644 +--- a/src/clients/kvno/kvno.c ++++ b/src/clients/kvno/kvno.c +@@ -561,7 +561,10 @@ do_v5_kvno(int count, char *names[], char * ccachestr, char *etypestr, + } + initialized = 1; + } +- ret = krb5_cc_store_cred(context, out_ccache, creds); ++ if (count == 1) ++ ret = k5_cc_store_primary_cred(context, out_ccache, creds); ++ else ++ ret = krb5_cc_store_cred(context, out_ccache, creds); + if (ret) { + com_err(prog, ret, _("while storing creds in output ccache")); + exit(1); +diff --git a/src/include/k5-int.h b/src/include/k5-int.h +index eb18a4cd6..912aaedac 100644 +--- a/src/include/k5-int.h ++++ b/src/include/k5-int.h +@@ -307,6 +307,7 @@ typedef unsigned char u_char; + #define KRB5_CC_CONF_PA_TYPE "pa_type" + #define KRB5_CC_CONF_PROXY_IMPERSONATOR "proxy_impersonator" + #define KRB5_CC_CONF_REFRESH_TIME "refresh_time" ++#define KRB5_CC_CONF_START_REALM "start_realm" + + /* Error codes used in KRB_ERROR protocol messages. + Return values of library routines are based on a different error table +@@ -1910,6 +1911,9 @@ krb5_ser_unpack_bytes(krb5_octet *, size_t, krb5_octet **, size_t *); + krb5_error_code KRB5_CALLCONV + krb5int_cc_default(krb5_context, krb5_ccache *); + ++krb5_error_code ++k5_cc_store_primary_cred(krb5_context, krb5_ccache, krb5_creds *); ++ + /* Fill in the buffer with random alpha-numeric data. */ + krb5_error_code + krb5int_random_string(krb5_context, char *string, unsigned int length); +diff --git a/src/lib/gssapi/krb5/accept_sec_context.c b/src/lib/gssapi/krb5/accept_sec_context.c +index 3d5b84b15..abccb5d11 100644 +--- a/src/lib/gssapi/krb5/accept_sec_context.c ++++ b/src/lib/gssapi/krb5/accept_sec_context.c +@@ -216,7 +216,7 @@ rd_and_store_for_creds(context, auth_context, inbuf, out_cred) + if ((retval = krb5_cc_initialize(context, ccache, creds[0]->client))) + goto cleanup; + +- if ((retval = krb5_cc_store_cred(context, ccache, creds[0]))) ++ if ((retval = k5_cc_store_primary_cred(context, ccache, creds[0]))) + goto cleanup; + + /* generate a delegated credential handle */ +diff --git a/src/lib/krb5/ccache/ccfns.c b/src/lib/krb5/ccache/ccfns.c +index 62a6983d8..23edc2578 100644 +--- a/src/lib/krb5/ccache/ccfns.c ++++ b/src/lib/krb5/ccache/ccfns.c +@@ -297,3 +297,23 @@ krb5_cc_switch(krb5_context context, krb5_ccache cache) + return 0; + return cache->ops->switch_to(context, cache); + } ++ ++krb5_error_code ++k5_cc_store_primary_cred(krb5_context context, krb5_ccache cache, ++ krb5_creds *creds) ++{ ++ krb5_error_code ret; ++ ++ /* Write a start realm if we're writing a TGT and the client realm isn't ++ * the same as the TGS realm. */ ++ if (IS_TGS_PRINC(creds->server) && ++ !data_eq(creds->client->realm, creds->server->data[1])) { ++ ret = krb5_cc_set_config(context, cache, NULL, ++ KRB5_CC_CONF_START_REALM, ++ &creds->server->data[1]); ++ if (ret) ++ return ret; ++ } ++ ++ return krb5_cc_store_cred(context, cache, creds); ++} +diff --git a/src/lib/krb5/krb/get_creds.c b/src/lib/krb5/krb/get_creds.c +index e0a3b5cd8..b40f705fc 100644 +--- a/src/lib/krb5/krb/get_creds.c ++++ b/src/lib/krb5/krb/get_creds.c +@@ -149,7 +149,8 @@ struct _krb5_tkt_creds_context { + krb5_principal client; /* Caller-requested client principal (alias) */ + krb5_principal server; /* Server principal (alias) */ + krb5_principal req_server; /* Caller-requested server principal */ +- krb5_ccache ccache; /* Caller-provided ccache (alias) */ ++ krb5_ccache ccache; /* Caller-provided ccache */ ++ krb5_data start_realm; /* Realm of starting TGT in ccache */ + krb5_flags req_options; /* Caller-requested KRB5_GC_* options */ + krb5_flags req_kdcopt; /* Caller-requested options as KDC options */ + krb5_authdata **authdata; /* Caller-requested authdata */ +@@ -783,7 +784,7 @@ get_cached_local_tgt(krb5_context context, krb5_tkt_creds_context ctx, + return code; + + /* Construct the principal name. */ +- code = krb5int_tgtname(context, &ctx->client->realm, &ctx->client->realm, ++ code = krb5int_tgtname(context, &ctx->start_realm, &ctx->start_realm, + &tgtname); + if (code != 0) + return code; +@@ -821,7 +822,7 @@ init_realm_path(krb5_context context, krb5_tkt_creds_context ctx) + size_t nrealms; + + /* Get the client realm path and count its length. */ +- code = k5_client_realm_path(context, &ctx->client->realm, ++ code = k5_client_realm_path(context, &ctx->start_realm, + &ctx->server->realm, &realm_path); + if (code != 0) + return code; +@@ -933,7 +934,7 @@ step_get_tgt(krb5_context context, krb5_tkt_creds_context ctx) + ctx->cur_realm = path_realm; + ctx->next_realm = ctx->last_realm; + } +- } else if (data_eq(*tgt_realm, ctx->client->realm)) { ++ } else if (data_eq(*tgt_realm, ctx->start_realm)) { + /* We were referred back to the local realm, which is bad. */ + return KRB5_KDCREP_MODIFIED; + } else { +@@ -963,7 +964,7 @@ begin_get_tgt(krb5_context context, krb5_tkt_creds_context ctx) + + ctx->state = STATE_GET_TGT; + +- is_local_service = data_eq(ctx->client->realm, ctx->server->realm); ++ is_local_service = data_eq(ctx->start_realm, ctx->server->realm); + if (!is_local_service) { + /* See if we have a cached TGT for the server realm. */ + code = get_cached_tgt(context, ctx, &ctx->server->realm, &cached_tgt); +@@ -1048,10 +1049,10 @@ begin(krb5_context context, krb5_tkt_creds_context ctx) + if (code != 0 || ctx->state == STATE_COMPLETE) + return code; + +- /* If the server realm is unspecified, start with the client realm. */ ++ /* If the server realm is unspecified, start with the TGT realm. */ + if (krb5_is_referral_realm(&ctx->server->realm)) { + krb5_free_data_contents(context, &ctx->server->realm); +- code = krb5int_copy_data_contents(context, &ctx->client->realm, ++ code = krb5int_copy_data_contents(context, &ctx->start_realm, + &ctx->server->realm); + TRACE_TKT_CREDS_REFERRAL_REALM(context, ctx->server); + if (code != 0) +@@ -1100,6 +1101,18 @@ krb5_tkt_creds_init(krb5_context context, krb5_ccache ccache, + code = krb5_cc_dup(context, ccache, &ctx->ccache); + if (code != 0) + goto cleanup; ++ ++ /* Get the start realm from the cache config, defaulting to the client ++ * realm. */ ++ code = krb5_cc_get_config(context, ccache, NULL, "start_realm", ++ &ctx->start_realm); ++ if (code != 0) { ++ code = krb5int_copy_data_contents(context, &ctx->client->realm, ++ &ctx->start_realm); ++ if (code != 0) ++ goto cleanup; ++ } ++ + code = krb5_copy_authdata(context, in_creds->authdata, &ctx->authdata); + if (code != 0) + goto cleanup; +@@ -1139,6 +1152,7 @@ krb5_tkt_creds_free(krb5_context context, krb5_tkt_creds_context ctx) + krb5int_fast_free_state(context, ctx->fast_state); + krb5_free_creds(context, ctx->in_creds); + krb5_cc_close(context, ctx->ccache); ++ krb5_free_data_contents(context, &ctx->start_realm); + krb5_free_principal(context, ctx->req_server); + krb5_free_authdata(context, ctx->authdata); + krb5_free_creds(context, ctx->cur_tgt); +diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c +index cc0f70e83..f5dd7518b 100644 +--- a/src/lib/krb5/krb/get_in_tkt.c ++++ b/src/lib/krb5/krb/get_in_tkt.c +@@ -1779,7 +1779,7 @@ init_creds_step_reply(krb5_context context, + code = krb5_cc_initialize(context, out_ccache, ctx->cred.client); + if (code != 0) + goto cc_cleanup; +- code = krb5_cc_store_cred(context, out_ccache, &ctx->cred); ++ code = k5_cc_store_primary_cred(context, out_ccache, &ctx->cred); + if (code != 0) + goto cc_cleanup; + if (fast_avail) { +diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports +index 5aba29ee4..cab5b3b17 100644 +--- a/src/lib/krb5/libkrb5.exports ++++ b/src/lib/krb5/libkrb5.exports +@@ -125,6 +125,7 @@ k5_add_pa_data_from_data + k5_alloc_pa_data + k5_authind_decode + k5_build_conf_principals ++k5_cc_store_primary_cred + k5_ccselect_free_context + k5_change_error_message_code + k5_etypes_contains +diff --git a/src/lib/krb5_32.def b/src/lib/krb5_32.def +index a0734c729..de5823c17 100644 +--- a/src/lib/krb5_32.def ++++ b/src/lib/krb5_32.def +@@ -499,3 +499,6 @@ EXPORTS + k5_size_context @467 ; PRIVATE GSSAPI + k5_size_keyblock @468 ; PRIVATE GSSAPI + k5_size_principal @469 ; PRIVATE GSSAPI ++ ++; new in 1.19 ++ k5_cc_store_primary_cred @470 ; PRIVATE +diff --git a/src/tests/t_crossrealm.py b/src/tests/t_crossrealm.py +index fa7fd2604..28b397cfb 100755 +--- a/src/tests/t_crossrealm.py ++++ b/src/tests/t_crossrealm.py +@@ -77,6 +77,14 @@ r1, r2, r3 = cross_realms(3, xtgts=((0,1), (1,2)), + {'realm': 'B.X'})) + test_kvno(r1, r3.host_princ, 'KDC domain walk') + check_klist(r1, (tgt(r1, r1), r3.host_princ)) ++ ++# Test start_realm in this setup. ++r1.run([kvno, '--out-cache', r1.ccache, r2.krbtgt_princ]) ++r1.run([klist, '-C'], expected_msg='config: start_realm = X') ++msgs = ('Requesting TGT krbtgt/B.X@X using TGT krbtgt/X@X', ++ 'Received TGT for service realm: krbtgt/B.X@X') ++r1.run([kvno, r3.host_princ], expected_trace=msgs) ++ + stop(r1, r2, r3) + + # Test client capaths. The client in A will ask for a cross TGT to D, +diff --git a/src/tests/t_pkinit.py b/src/tests/t_pkinit.py +index ecd450e8a..f224383c8 100755 +--- a/src/tests/t_pkinit.py ++++ b/src/tests/t_pkinit.py +@@ -130,6 +130,9 @@ realm.run([kvno, realm.host_princ]) + out = realm.run(['./adata', realm.host_princ]) + if '97:' in out: + fail('auth indicators seen in anonymous PKINIT ticket') ++# Verify start_realm setting and test referrals TGS request. ++realm.run([klist, '-C'], expected_msg='start_realm = KRBTEST.COM') ++realm.run([kvno, '-S', 'host', hostname]) + + # Test anonymous kadmin. + mark('anonymous kadmin') diff --git a/root/ppg/common/deps/krb5/rpm/Add-three-kvno-options-from-Heimdal-kgetcred.patch b/root/ppg/common/deps/krb5/rpm/Add-three-kvno-options-from-Heimdal-kgetcred.patch new file mode 100644 index 00000000..ee427323 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Add-three-kvno-options-from-Heimdal-kgetcred.patch @@ -0,0 +1,403 @@ +From a1f38973435b60c7f147abfca12b95c6a0a64406 Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Wed, 17 Jun 2020 20:48:38 -0400 +Subject: [PATCH] Add three kvno options from Heimdal kgetcred + +Add the flags --cached-only and --no-store, which pass the +corresponding options to krb5_get_credentials(). Add the option +--out-cache to write the retrieved credentials to a specified output +cache. + +Add a Python test script for kvno command-line options, including +tests for the new options. + +ticket: 8917 (new) +--- + doc/user/user_commands/kvno.rst | 13 ++++ + src/clients/kvno/Makefile.in | 3 + + src/clients/kvno/kvno.c | 115 +++++++++++++++++++++++--------- + src/clients/kvno/t_kvno.py | 75 +++++++++++++++++++++ + src/man/kvno.man | 13 ++++ + 5 files changed, 187 insertions(+), 32 deletions(-) + create mode 100644 src/clients/kvno/t_kvno.py + +diff --git a/doc/user/user_commands/kvno.rst b/doc/user/user_commands/kvno.rst +index 3892f0ca5..718313576 100644 +--- a/doc/user/user_commands/kvno.rst ++++ b/doc/user/user_commands/kvno.rst +@@ -74,6 +74,19 @@ OPTIONS + client principal with the X.509 certificate in *cert_file*. The + certificate file must be in PEM format. + ++**--cached-only** ++ Only retrieve credentials already present in the cache, not from ++ the KDC. ++ ++**--no-store** ++ Do not store retrieved credentials in the cache. If ++ **--out-cache** is also specified, credentials will still be ++ stored into the output credential cache. ++ ++**--out-cache** *ccache* ++ Initialize *ccache* and store all retrieved credentials into it. ++ Do not store acquired credentials in the input cache. ++ + **--u2u** *ccache* + Requests a user-to-user ticket. *ccache* must contain a local + krbtgt ticket for the server principal. The reported version +diff --git a/src/clients/kvno/Makefile.in b/src/clients/kvno/Makefile.in +index 1c3f79392..5ba877271 100644 +--- a/src/clients/kvno/Makefile.in ++++ b/src/clients/kvno/Makefile.in +@@ -26,6 +26,9 @@ kvno: kvno.o $(KRB5_BASE_DEPLIBS) + ##WIN32## link $(EXE_LINKOPTS) /out:$@ $** + ##WIN32## $(_VC_MANIFEST_EMBED_EXE) + ++check-pytests: kvno ++ $(RUNPYTEST) $(srcdir)/t_kvno.py $(PYTESTFLAGS) ++ + clean-unix:: + $(RM) kvno.o kvno + +diff --git a/src/clients/kvno/kvno.c b/src/clients/kvno/kvno.c +index 2472c0cfe..9d85864f6 100644 +--- a/src/clients/kvno/kvno.c ++++ b/src/clients/kvno/kvno.c +@@ -44,14 +44,17 @@ xusage() + fprintf(stderr, _("usage: %s [-C] [-u] [-c ccache] [-e etype]\n"), prog); + fprintf(stderr, _("\t[-k keytab] [-S sname] [{-I | -U} for_user | " + "[-F cert_file] [-P]]\n")); +- fprintf(stderr, _("\t[--u2u ccache] service1 service2 ...\n")); ++ fprintf(stderr, _("\t[--cached-only] [--no-store] [--out-cache ccache] " ++ "[--u2u ccache]\n")); ++ fprintf(stderr, _("\tservice1 service2 ...\n")); + exit(1); + } + + static void do_v5_kvno(int argc, char *argv[], char *ccachestr, char *etypestr, +- char *keytab_name, char *sname, int canon, int unknown, +- char *for_user, int for_user_enterprise, +- char *for_user_cert_file, int proxy, ++ char *keytab_name, char *sname, int cached_only, ++ int canon, int no_store, int unknown, char *for_user, ++ int for_user_enterprise, char *for_user_cert_file, ++ int proxy, const char *out_ccname, + const char *u2u_ccname); + + #include +@@ -61,18 +64,21 @@ static void extended_com_err_fn(const char *myprog, errcode_t code, + int + main(int argc, char *argv[]) + { +- enum { OPTION_U2U = 256 }; +- struct option lopts[] = { +- { "u2u", 1, NULL, OPTION_U2U }, +- { NULL, 0, NULL, 0 } +- }; ++ enum { OPTION_U2U = 256, OPTION_OUT_CACHE = 257 }; + const char *shopts = "uCc:e:hk:qPS:I:U:F:"; + int option; + char *etypestr = NULL, *ccachestr = NULL, *keytab_name = NULL; + char *sname = NULL, *for_user = NULL, *u2u_ccname = NULL; +- char *for_user_cert_file = NULL; ++ char *for_user_cert_file = NULL, *out_ccname = NULL; + int canon = 0, unknown = 0, proxy = 0, for_user_enterprise = 0; +- int impersonate = 0; ++ int impersonate = 0, cached_only = 0, no_store = 0; ++ struct option lopts[] = { ++ { "cached-only", 0, &cached_only, 1 }, ++ { "no-store", 0, &no_store, 1 }, ++ { "out-cache", 1, NULL, OPTION_OUT_CACHE }, ++ { "u2u", 1, NULL, OPTION_U2U }, ++ { NULL, 0, NULL, 0 } ++ }; + + setlocale(LC_ALL, ""); + set_com_err_hook(extended_com_err_fn); +@@ -135,6 +141,12 @@ main(int argc, char *argv[]) + case OPTION_U2U: + u2u_ccname = optarg; + break; ++ case OPTION_OUT_CACHE: ++ out_ccname = optarg; ++ break; ++ case 0: ++ /* If this option set a flag, do nothing else now. */ ++ break; + default: + xusage(); + break; +@@ -159,8 +171,9 @@ main(int argc, char *argv[]) + xusage(); + + do_v5_kvno(argc - optind, argv + optind, ccachestr, etypestr, keytab_name, +- sname, canon, unknown, for_user, for_user_enterprise, +- for_user_cert_file, proxy, u2u_ccname); ++ sname, cached_only, canon, no_store, unknown, for_user, ++ for_user_enterprise, for_user_cert_file, proxy, out_ccname, ++ u2u_ccname); + return 0; + } + +@@ -274,14 +287,16 @@ static krb5_error_code + kvno(const char *name, krb5_ccache ccache, krb5_principal me, + krb5_enctype etype, krb5_keytab keytab, const char *sname, + krb5_flags options, int unknown, krb5_principal for_user_princ, +- krb5_data *for_user_cert, int proxy, krb5_data *u2u_ticket) ++ krb5_data *for_user_cert, int proxy, krb5_data *u2u_ticket, ++ krb5_creds **creds_out) + { + krb5_error_code ret; + krb5_principal server = NULL; + krb5_ticket *ticket = NULL; +- krb5_creds in_creds, *out_creds = NULL; ++ krb5_creds in_creds, *creds = NULL; + char *princ = NULL; + ++ *creds_out = NULL; + memset(&in_creds, 0, sizeof(in_creds)); + + if (sname != NULL) { +@@ -321,13 +336,12 @@ kvno(const char *name, krb5_ccache ccache, krb5_principal me, + in_creds.client = for_user_princ; + in_creds.server = me; + ret = krb5_get_credentials_for_user(context, options, ccache, +- &in_creds, for_user_cert, +- &out_creds); ++ &in_creds, for_user_cert, &creds); + } else { + in_creds.client = me; + in_creds.server = server; + ret = krb5_get_credentials(context, options, ccache, &in_creds, +- &out_creds); ++ &creds); + } + + if (ret) { +@@ -336,7 +350,7 @@ kvno(const char *name, krb5_ccache ccache, krb5_principal me, + } + + /* We need a native ticket. */ +- ret = krb5_decode_ticket(&out_creds->ticket, &ticket); ++ ret = krb5_decode_ticket(&creds->ticket, &ticket); + if (ret) { + com_err(prog, ret, _("while decoding ticket for %s"), princ); + goto cleanup; +@@ -362,15 +376,15 @@ kvno(const char *name, krb5_ccache ccache, krb5_principal me, + } + + if (proxy) { +- in_creds.client = out_creds->client; +- out_creds->client = NULL; +- krb5_free_creds(context, out_creds); +- out_creds = NULL; ++ in_creds.client = creds->client; ++ creds->client = NULL; ++ krb5_free_creds(context, creds); ++ creds = NULL; + in_creds.server = server; + + ret = krb5_get_credentials_for_proxy(context, KRB5_GC_CANONICALIZE, + ccache, &in_creds, ticket, +- &out_creds); ++ &creds); + krb5_free_principal(context, in_creds.client); + if (ret) { + com_err(prog, ret, _("%s: constrained delegation failed"), +@@ -379,10 +393,13 @@ kvno(const char *name, krb5_ccache ccache, krb5_principal me, + } + } + ++ *creds_out = creds; ++ creds = NULL; ++ + cleanup: + krb5_free_principal(context, server); + krb5_free_ticket(context, ticket); +- krb5_free_creds(context, out_creds); ++ krb5_free_creds(context, creds); + krb5_free_unparsed_name(context, princ); + return ret; + } +@@ -428,19 +445,28 @@ cleanup: + + static void + do_v5_kvno(int count, char *names[], char * ccachestr, char *etypestr, +- char *keytab_name, char *sname, int canon, int unknown, +- char *for_user, int for_user_enterprise, +- char *for_user_cert_file, int proxy, const char *u2u_ccname) ++ char *keytab_name, char *sname, int cached_only, int canon, ++ int no_store, int unknown, char *for_user, int for_user_enterprise, ++ char *for_user_cert_file, int proxy, const char *out_ccname, ++ const char *u2u_ccname) + { + krb5_error_code ret; +- int i, errors, flags; ++ int i, errors, flags, initialized = 0; + krb5_enctype etype; +- krb5_ccache ccache; ++ krb5_ccache ccache, out_ccache = NULL; + krb5_principal me; + krb5_keytab keytab = NULL; + krb5_principal for_user_princ = NULL; +- krb5_flags options = canon ? KRB5_GC_CANONICALIZE : 0; ++ krb5_flags options = 0; + krb5_data cert_data = empty_data(), *user_cert = NULL, *u2u_ticket = NULL; ++ krb5_creds *creds; ++ ++ if (canon) ++ options |= KRB5_GC_CANONICALIZE; ++ if (cached_only) ++ options |= KRB5_GC_CACHED; ++ if (no_store || out_ccname != NULL) ++ options |= KRB5_GC_NO_STORE; + + ret = krb5_init_context(&context); + if (ret) { +@@ -467,6 +493,14 @@ do_v5_kvno(int count, char *names[], char * ccachestr, char *etypestr, + exit(1); + } + ++ if (out_ccname != NULL) { ++ ret = krb5_cc_resolve(context, out_ccname, &out_ccache); ++ if (ret) { ++ com_err(prog, ret, _("while resolving output ccache")); ++ exit(1); ++ } ++ } ++ + if (keytab_name != NULL) { + ret = krb5_kt_resolve(context, keytab_name, &keytab); + if (ret) { +@@ -513,8 +547,25 @@ do_v5_kvno(int count, char *names[], char * ccachestr, char *etypestr, + errors = 0; + for (i = 0; i < count; i++) { + if (kvno(names[i], ccache, me, etype, keytab, sname, options, unknown, +- for_user_princ, user_cert, proxy, u2u_ticket) != 0) ++ for_user_princ, user_cert, proxy, u2u_ticket, &creds) != 0) { + errors++; ++ } else if (out_ccache != NULL) { ++ if (!initialized) { ++ ret = krb5_cc_initialize(context, out_ccache, creds->client); ++ if (ret) { ++ com_err(prog, ret, _("while initializing output ccache")); ++ exit(1); ++ } ++ initialized = 1; ++ } ++ ret = krb5_cc_store_cred(context, out_ccache, creds); ++ if (ret) { ++ com_err(prog, ret, _("while storing creds in output ccache")); ++ exit(1); ++ } ++ } ++ ++ krb5_free_creds(context, creds); + } + + if (keytab != NULL) +diff --git a/src/clients/kvno/t_kvno.py b/src/clients/kvno/t_kvno.py +new file mode 100644 +index 000000000..e98b90e8a +--- /dev/null ++++ b/src/clients/kvno/t_kvno.py +@@ -0,0 +1,75 @@ ++from k5test import * ++ ++realm = K5Realm() ++ ++def check_cache(ccache, expected_services): ++ # Fetch the klist output and skip past the header. ++ lines = realm.run([klist, '-c', ccache]).splitlines() ++ lines = lines[4:] ++ ++ # For each line not beginning with an indent, match against the ++ # expected service principals. ++ svcs = {x: True for x in expected_services} ++ for l in lines: ++ if not l.startswith('\t'): ++ svcprinc = l.split()[4] ++ if svcprinc in svcs: ++ del svcs[svcprinc] ++ else: ++ fail('unexpected service princ ' + svcprinc) ++ ++ if svcs: ++ fail('services not found in klist output: ' + ' '.join(svcs.keys())) ++ ++ ++mark('no options') ++realm.run([kvno, realm.user_princ], expected_msg='user@KRBTEST.COM: kvno = 1') ++check_cache(realm.ccache, [realm.krbtgt_princ, realm.user_princ]) ++ ++mark('-e') ++msgs = ('etypes requested in TGS request: camellia128-cts', ++ '/KDC has no support for encryption type') ++realm.run([kvno, '-e', 'camellia128-cts', realm.host_princ], ++ expected_code=1, expected_trace=msgs) ++ ++mark('--cached-only') ++realm.run([kvno, '--cached-only', realm.user_princ], expected_msg='kvno = 1') ++realm.run([kvno, '--cached-only', realm.host_princ], ++ expected_code=1, expected_msg='Matching credential not found') ++check_cache(realm.ccache, [realm.krbtgt_princ, realm.user_princ]) ++ ++mark('--no-store') ++realm.run([kvno, '--no-store', realm.host_princ], expected_msg='kvno = 1') ++check_cache(realm.ccache, [realm.krbtgt_princ, realm.user_princ]) ++ ++mark('--out-cache') # and multiple services ++out_ccache = os.path.join(realm.testdir, 'ccache.out') ++realm.run([kvno, '--out-cache', out_ccache, ++ realm.host_princ, realm.admin_princ]) ++check_cache(realm.ccache, [realm.krbtgt_princ, realm.user_princ]) ++check_cache(out_ccache, [realm.host_princ, realm.admin_princ]) ++ ++mark('--out-cache --cached-only') # tests out-cache overwriting, and -q ++realm.run([kvno, '--out-cache', out_ccache, '--cached-only', realm.host_princ], ++ expected_code=1, expected_msg='Matching credential not found') ++out = realm.run([kvno, '-q', '--out-cache', out_ccache, '--cached-only', ++ realm.user_princ]) ++if out: ++ fail('unexpected kvno output with -q') ++check_cache(out_ccache, [realm.user_princ]) ++ ++mark('-U') # and -c ++svc_ccache = os.path.join(realm.testdir, 'ccache.svc') ++realm.run([kinit, '-k', '-c', svc_ccache, realm.host_princ]) ++realm.run([kvno, '-c', svc_ccache, '-U', 'user', realm.host_princ]) ++realm.run([klist, '-c', svc_ccache], expected_msg='for client user@') ++realm.run([kvno, '-c', svc_ccache, '-U', 'user', '--out-cache', out_ccache, ++ realm.host_princ]) ++out = realm.run([klist, '-c', out_ccache]) ++if ('Default principal: user@KRBTEST.COM' not in out): ++ fail('wrong default principal in klist output') ++ ++# More S4U options are tested in tests/gssapi/t_s4u.py. ++# --u2u is tested in tests/t_u2u.py. ++ ++success('kvno tests') +diff --git a/src/man/kvno.man b/src/man/kvno.man +index 005a2ec97..b9f6739eb 100644 +--- a/src/man/kvno.man ++++ b/src/man/kvno.man +@@ -95,6 +95,19 @@ Specifies that protocol transition is to be used, identifying the + client principal with the X.509 certificate in \fIcert_file\fP\&. The + certificate file must be in PEM format. + .TP ++\fB\-\-cached\-only\fP ++Only retrieve credentials already present in the cache, not from ++the KDC. ++.TP ++\fB\-\-no\-store\fP ++Do not store retrieved credentials in the cache. If ++\fB\-\-out\-cache\fP is also specified, credentials will still be ++stored into the output credential cache. ++.TP ++\fB\-\-out\-cache\fP \fIccache\fP ++Initialize \fIccache\fP and store all retrieved credentials into it. ++Do not store acquired credentials in the input cache. ++.TP + \fB\-\-u2u\fP \fIccache\fP + Requests a user\-to\-user ticket. \fIccache\fP must contain a local + krbtgt ticket for the server principal. The reported version diff --git a/root/ppg/common/deps/krb5/rpm/Allow-certauth-modules-to-set-hw-authent-flag.patch b/root/ppg/common/deps/krb5/rpm/Allow-certauth-modules-to-set-hw-authent-flag.patch new file mode 100644 index 00000000..a4f4af0a --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Allow-certauth-modules-to-set-hw-authent-flag.patch @@ -0,0 +1,242 @@ +From ab814a990f109357fc4b505169792f9d4d5b5155 Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Mon, 24 Feb 2020 15:58:59 -0500 +Subject: [PATCH] Allow certauth modules to set hw-authent flag + +In PKINIT, if a certauth module returns KRB5_CERTAUTH_HWAUTH from its +authorize method, set the hw-authent flag in the ticket. + +ticket: 8879 (new) +(cherry picked from commit 50fb43b4a2d97ce2cd53e1ced30e8e8224fede70) +(cherry picked from commit d23b2ed4f06fa77cd021814834dd1391ef6f452f) +--- + doc/plugindev/certauth.rst | 7 +++++-- + src/include/krb5/certauth_plugin.h | 9 ++++++--- + src/lib/krb5/error_tables/k5e1_err.et | 1 + + src/plugins/certauth/test/Makefile.in | 4 ++-- + src/plugins/certauth/test/main.c | 11 +++++++++-- + src/plugins/preauth/pkinit/pkinit_srv.c | 24 ++++++++++++++++-------- + src/tests/t_certauth.py | 13 +++++++++++++ + 7 files changed, 52 insertions(+), 17 deletions(-) + +diff --git a/doc/plugindev/certauth.rst b/doc/plugindev/certauth.rst +index 8a7f7c5eb..3b715f738 100644 +--- a/doc/plugindev/certauth.rst ++++ b/doc/plugindev/certauth.rst +@@ -15,8 +15,11 @@ principal. **authorize** receives the DER-encoded certificate, the + requested client principal, and a pointer to the client's + krb5_db_entry (for modules that link against libkdb5). It returns the + authorization status and optionally outputs a list of authentication +-indicator strings to be added to the ticket. A module must use its +-own internal or library-provided ASN.1 certificate decoder. ++indicator strings to be added to the ticket. Beginning in release ++1.19, the authorize method can request that the hardware ++authentication bit be set in the ticket by returning ++**KRB5_CERTAUTH_HWAUTH**. A module must use its own internal or ++library-provided ASN.1 certificate decoder. + + A module can optionally create and destroy module data with the + **init** and **fini** methods. Module data objects last for the +diff --git a/src/include/krb5/certauth_plugin.h b/src/include/krb5/certauth_plugin.h +index 3074790f8..3466cf345 100644 +--- a/src/include/krb5/certauth_plugin.h ++++ b/src/include/krb5/certauth_plugin.h +@@ -85,14 +85,17 @@ typedef void + (*krb5_certauth_fini_fn)(krb5_context context, krb5_certauth_moddata moddata); + + /* +- * Mandatory: +- * Return 0 if the DER-encoded cert is authorized for PKINIT authentication by +- * princ; otherwise return one of the following error codes: ++ * Mandatory: return 0 or KRB5_CERTAUTH_HWAUTH if the DER-encoded cert is ++ * authorized for PKINIT authentication by princ; otherwise return one of the ++ * following error codes: + * - KRB5KDC_ERR_CLIENT_NAME_MISMATCH - incorrect SAN value + * - KRB5KDC_ERR_INCONSISTENT_KEY_PURPOSE - incorrect EKU + * - KRB5KDC_ERR_CERTIFICATE_MISMATCH - other extension error + * - KRB5_PLUGIN_NO_HANDLE - the module has no opinion about cert + * ++ * Returning KRB5_CERTAUTH_HWAUTH will cause the hw-authent flag to be set in ++ * the issued ticket (new in release 1.19). ++ * + * - opts is used by built-in modules to receive internal data, and must be + * ignored by other modules. + * - db_entry receives the client principal database entry, and can be ignored +diff --git a/src/lib/krb5/error_tables/k5e1_err.et b/src/lib/krb5/error_tables/k5e1_err.et +index ade5caecf..abd9f3bfe 100644 +--- a/src/lib/krb5/error_tables/k5e1_err.et ++++ b/src/lib/krb5/error_tables/k5e1_err.et +@@ -42,4 +42,5 @@ error_code KRB5_KCM_MALFORMED_REPLY, "Malformed reply from KCM daemon" + error_code KRB5_KCM_RPC_ERROR, "Mach RPC error communicating with KCM daemon" + error_code KRB5_KCM_REPLY_TOO_BIG, "KCM daemon reply too big" + error_code KRB5_KCM_NO_SERVER, "No KCM server found" ++error_code KRB5_CERTAUTH_HWAUTH, "Authorize and set hw-authent ticket flag" + end +diff --git a/src/plugins/certauth/test/Makefile.in b/src/plugins/certauth/test/Makefile.in +index d3524084c..e94c13845 100644 +--- a/src/plugins/certauth/test/Makefile.in ++++ b/src/plugins/certauth/test/Makefile.in +@@ -5,8 +5,8 @@ LIBBASE=certauth_test + LIBMAJOR=0 + LIBMINOR=0 + RELDIR=../plugins/certauth/test +-SHLIB_EXPDEPS=$(KRB5_BASE_DEPLIBS) +-SHLIB_EXPLIBS=$(KRB5_BASE_LIBS) ++SHLIB_EXPDEPS=$(KDB5_DEPLIBS) $(KRB5_BASE_DEPLIBS) ++SHLIB_EXPLIBS=$(KDB5_LIBS) $(KRB5_BASE_LIBS) + + STLIBOBJS=main.o + +diff --git a/src/plugins/certauth/test/main.c b/src/plugins/certauth/test/main.c +index 77641230c..d4633b8cd 100644 +--- a/src/plugins/certauth/test/main.c ++++ b/src/plugins/certauth/test/main.c +@@ -31,6 +31,7 @@ + */ + + #include ++#include + #include "krb5/certauth_plugin.h" + + struct krb5_certauth_moddata_st { +@@ -131,7 +132,8 @@ has_cn(krb5_context context, const uint8_t *cert, size_t cert_len, + + /* + * Test module 2 returns OK if princ matches the CN part of the subject name, +- * and returns indicators of the module name and princ. ++ * and returns indicators of the module name and princ. If the "hwauth" string ++ * attribute is set on db_entry, it returns KRB5_CERTAUTH_HWAUTH. + */ + static krb5_error_code + test2_authorize(krb5_context context, krb5_certauth_moddata moddata, +@@ -141,7 +143,7 @@ test2_authorize(krb5_context context, krb5_certauth_moddata moddata, + char ***authinds_out) + { + krb5_error_code ret; +- char *name = NULL, **ais = NULL; ++ char *name = NULL, *strval = NULL, **ais = NULL; + + *authinds_out = NULL; + +@@ -167,6 +169,11 @@ test2_authorize(krb5_context context, krb5_certauth_moddata moddata, + + ais = NULL; + ++ ret = krb5_dbe_get_string(context, (krb5_db_entry *)db_entry, "hwauth", ++ &strval); ++ ret = (strval != NULL) ? KRB5_CERTAUTH_HWAUTH : 0; ++ krb5_dbe_free_string(context, strval); ++ + cleanup: + krb5_free_unparsed_name(context, name); + return ret; +diff --git a/src/plugins/preauth/pkinit/pkinit_srv.c b/src/plugins/preauth/pkinit/pkinit_srv.c +index feca11806..3ae56c064 100644 +--- a/src/plugins/preauth/pkinit/pkinit_srv.c ++++ b/src/plugins/preauth/pkinit/pkinit_srv.c +@@ -320,12 +320,12 @@ static krb5_error_code + authorize_cert(krb5_context context, certauth_handle *certauth_modules, + pkinit_kdc_context plgctx, pkinit_kdc_req_context reqctx, + krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock, +- krb5_principal client) ++ krb5_principal client, krb5_boolean *hwauth_out) + { + krb5_error_code ret; + certauth_handle h; + struct certauth_req_opts opts; +- krb5_boolean accepted = FALSE; ++ krb5_boolean accepted = FALSE, hwauth = FALSE; + uint8_t *cert; + size_t i, cert_len; + void *db_ent = NULL; +@@ -347,9 +347,10 @@ authorize_cert(krb5_context context, certauth_handle *certauth_modules, + + /* + * Check the certificate against each certauth module. For the certificate +- * to be authorized at least one module must return 0, and no module can an +- * error code other than KRB5_PLUGIN_NO_HANDLE (pass). Add indicators from +- * modules that return 0 or pass. ++ * to be authorized at least one module must return 0 or ++ * KRB5_CERTAUTH_HWAUTH, and no module can return an error code other than ++ * KRB5_PLUGIN_NO_HANDLE (pass). Add indicators from modules that return 0 ++ * or pass. + */ + ret = KRB5_PLUGIN_NO_HANDLE; + for (i = 0; certauth_modules != NULL && certauth_modules[i] != NULL; i++) { +@@ -359,6 +360,8 @@ authorize_cert(krb5_context context, certauth_handle *certauth_modules, + &opts, db_ent, &ais); + if (ret == 0) + accepted = TRUE; ++ else if (ret == KRB5_CERTAUTH_HWAUTH) ++ accepted = hwauth = TRUE; + else if (ret != KRB5_PLUGIN_NO_HANDLE) + goto cleanup; + +@@ -374,6 +377,7 @@ authorize_cert(krb5_context context, certauth_handle *certauth_modules, + } + } + ++ *hwauth_out = hwauth; + ret = accepted ? 0 : KRB5KDC_ERR_CLIENT_NAME_MISMATCH; + + cleanup: +@@ -430,7 +434,7 @@ pkinit_server_verify_padata(krb5_context context, + int is_signed = 1; + krb5_pa_data **e_data = NULL; + krb5_kdcpreauth_modreq modreq = NULL; +- krb5_boolean valid_freshness_token = FALSE; ++ krb5_boolean valid_freshness_token = FALSE, hwauth = FALSE; + char **sp; + + pkiDebug("pkinit_verify_padata: entered!\n"); +@@ -494,7 +498,7 @@ pkinit_server_verify_padata(krb5_context context, + } + if (is_signed) { + retval = authorize_cert(context, moddata->certauth_modules, plgctx, +- reqctx, cb, rock, request->client); ++ reqctx, cb, rock, request->client, &hwauth); + if (retval) + goto cleanup; + +@@ -613,6 +617,8 @@ pkinit_server_verify_padata(krb5_context context, + + /* remember to set the PREAUTH flag in the reply */ + enc_tkt_reply->flags |= TKT_FLG_PRE_AUTH; ++ if (hwauth) ++ enc_tkt_reply->flags |= TKT_FLG_HW_AUTH; + modreq = (krb5_kdcpreauth_modreq)reqctx; + reqctx = NULL; + +@@ -1044,7 +1050,9 @@ pkinit_server_get_flags(krb5_context kcontext, krb5_preauthtype patype) + { + if (patype == KRB5_PADATA_PKINIT_KX) + return PA_INFO; +- return PA_SUFFICIENT | PA_REPLACES_KEY | PA_TYPED_E_DATA; ++ /* PKINIT does not normally set the hw-authent ticket flag, but a ++ * certauth module can cause it to do so. */ ++ return PA_SUFFICIENT | PA_REPLACES_KEY | PA_TYPED_E_DATA | PA_HARDWARE; + } + + static krb5_preauthtype supported_server_pa_types[] = { +diff --git a/src/tests/t_certauth.py b/src/tests/t_certauth.py +index 9c7094525..0fe0fdb4a 100644 +--- a/src/tests/t_certauth.py ++++ b/src/tests/t_certauth.py +@@ -43,4 +43,17 @@ out = realm.kinit("user2@KRBTEST.COM", + expected_code=1, + expected_msg='kinit: Certificate mismatch') + ++# Test the KRB5_CERTAUTH_HWAUTH return code. ++mark('hw-authent flag tests') ++# First test +requires_hwauth without causing the hw-authent ticket ++# flag to be set. This currently results in a preauth loop. ++realm.run([kadminl, 'modprinc', '+requires_hwauth', realm.user_princ]) ++realm.kinit(realm.user_princ, ++ flags=['-X', 'X509_user_identity=%s' % file_identity], ++ expected_code=1, expected_msg='Looping detected') ++# Cause the test2 module to return KRB5_CERTAUTH_HWAUTH and try again. ++realm.run([kadminl, 'setstr', realm.user_princ, 'hwauth', 'x']) ++realm.kinit(realm.user_princ, ++ flags=['-X', 'X509_user_identity=%s' % file_identity]) ++ + success("certauth tests") diff --git a/root/ppg/common/deps/krb5/rpm/Correctly-import-service-GSS-host-based-name.patch b/root/ppg/common/deps/krb5/rpm/Correctly-import-service-GSS-host-based-name.patch new file mode 100644 index 00000000..ddc671fd --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Correctly-import-service-GSS-host-based-name.patch @@ -0,0 +1,53 @@ +From cbdae9a9dc2a6af5551d26b32c8d473e1e0ce773 Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Mon, 30 Mar 2020 15:26:02 -0400 +Subject: [PATCH] Correctly import "service@" GSS host-based name + +The intended way to specify only a service in a GSS host-based name is +to omit the "@" separator. Some applications include the separator +but no hostname, and this happened to yield wildcard hostname behavior +prior to commit 996353767fe8afa7f67a3b5b465e4d70e18bad7c when +shortname qualification was added. To restore this behavior, check in +parse_hostbased() that at least one character is present after the "@" +separator before copying the hostname. Add a test case to t_gssapi.py. + +ticket: 8892 +tags: pullup +target_version: 1.18-next + +(cherry picked from commit a2f047af0400ba8080dc26033fae2b17534501e2) +(cherry picked from commit dd4364d76925ce1fe21c2ab995554d6af3a2ea12) +--- + src/lib/gssapi/krb5/import_name.c | 4 ++-- + src/tests/gssapi/t_gssapi.py | 3 +++ + 2 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/src/lib/gssapi/krb5/import_name.c b/src/lib/gssapi/krb5/import_name.c +index da2ab1423..21023dd76 100644 +--- a/src/lib/gssapi/krb5/import_name.c ++++ b/src/lib/gssapi/krb5/import_name.c +@@ -102,8 +102,8 @@ parse_hostbased(const char *str, size_t len, + memcpy(service, str, servicelen); + service[servicelen] = '\0'; + +- /* If present, copy the hostname. */ +- if (at != NULL) { ++ /* Copy the hostname if present (at least one character after '@'). */ ++ if (len - servicelen > 1) { + hostlen = len - servicelen - 1; + host = malloc(hostlen + 1); + if (host == NULL) { +diff --git a/src/tests/gssapi/t_gssapi.py b/src/tests/gssapi/t_gssapi.py +index 54d5cf549..ecf982604 100755 +--- a/src/tests/gssapi/t_gssapi.py ++++ b/src/tests/gssapi/t_gssapi.py +@@ -47,6 +47,9 @@ realm.run(['./t_accname', 'p:service2/calvin', 'h:service2'], + expected_msg='service2/calvin') + realm.run(['./t_accname', 'p:service2/calvin', 'h:service1'], expected_code=1, + expected_msg=' found in keytab but does not match server principal') ++# Regression test for #8892 (trailing @ in name). ++realm.run(['./t_accname', 'p:service1/andrew', 'h:service1@'], ++ expected_msg='service1/abraham') + + # Test with acceptor name containing service and host. Use the + # client's un-canonicalized hostname as acceptor input to mirror what diff --git a/root/ppg/common/deps/krb5/rpm/Do-expiration-warnings-for-all-init_creds-APIs.patch b/root/ppg/common/deps/krb5/rpm/Do-expiration-warnings-for-all-init_creds-APIs.patch new file mode 100644 index 00000000..1e1bece9 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Do-expiration-warnings-for-all-init_creds-APIs.patch @@ -0,0 +1,426 @@ +From ff6cf2a0545d12a020572dd137fd22d1edc726e4 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Fri, 28 Feb 2020 10:11:49 +0100 +Subject: [PATCH] Do expiration warnings for all init_creds APIs + +Move the password expiration warning code from gic_pwd.c to +get_in_tkt.c. Call it from init_creds_step_reply() on successful +completion. + +[ghudson@mit.edu: added test case; simplified doc comment; moved call +site to init_creds_step_reply(); rewrote commit message] + +ticket: 8893 (new) +(cherry picked from commit e1efb890f7ac31b32c68ab816ef118dbfb5a8c7e) +(cherry picked from commit c136cfe050d203c910624573a33247fde2889b09) +--- + src/include/krb5/krb5.hin | 9 ++- + src/lib/krb5/krb/get_in_tkt.c | 112 ++++++++++++++++++++++++++++++ + src/lib/krb5/krb/gic_pwd.c | 110 ----------------------------- + src/lib/krb5/krb/t_expire_warn.c | 47 +++++++++---- + src/lib/krb5/krb/t_expire_warn.py | 22 ++++-- + 5 files changed, 165 insertions(+), 135 deletions(-) + +diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin +index 6355e6540..f8269fb17 100644 +--- a/src/include/krb5/krb5.hin ++++ b/src/include/krb5/krb5.hin +@@ -7174,11 +7174,10 @@ typedef void + * + * Set a callback to receive password and account expiration times. + * +- * This option only applies to krb5_get_init_creds_password(). @a cb will be +- * invoked if and only if credentials are successfully acquired. The callback +- * will receive the @a context from the krb5_get_init_creds_password() call and +- * the @a data argument supplied with this API. The remaining arguments should +- * be interpreted as follows: ++ * @a cb will be invoked if and only if credentials are successfully acquired. ++ * The callback will receive the @a context from the calling function and the ++ * @a data argument supplied with this API. The remaining arguments should be ++ * interpreted as follows: + * + * If @a is_last_req is true, then the KDC reply contained last-req entries + * which unambiguously indicated the password expiration, account expiration, +diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c +index 870df62a1..cc0f70e83 100644 +--- a/src/lib/krb5/krb/get_in_tkt.c ++++ b/src/lib/krb5/krb/get_in_tkt.c +@@ -1482,6 +1482,116 @@ accept_method_data(krb5_context context, krb5_init_creds_context ctx) + ctx->method_padata); + } + ++/* Return the password expiry time indicated by enc_part2. Set *is_last_req ++ * if the information came from a last_req value. */ ++static void ++get_expiry_times(krb5_enc_kdc_rep_part *enc_part2, krb5_timestamp *pw_exp, ++ krb5_timestamp *acct_exp, krb5_boolean *is_last_req) ++{ ++ krb5_last_req_entry **last_req; ++ krb5_int32 lr_type; ++ ++ *pw_exp = 0; ++ *acct_exp = 0; ++ *is_last_req = FALSE; ++ ++ /* Look for last-req entries for password or account expiration. */ ++ if (enc_part2->last_req) { ++ for (last_req = enc_part2->last_req; *last_req; last_req++) { ++ lr_type = (*last_req)->lr_type; ++ if (lr_type == KRB5_LRQ_ALL_PW_EXPTIME || ++ lr_type == KRB5_LRQ_ONE_PW_EXPTIME) { ++ *is_last_req = TRUE; ++ *pw_exp = (*last_req)->value; ++ } else if (lr_type == KRB5_LRQ_ALL_ACCT_EXPTIME || ++ lr_type == KRB5_LRQ_ONE_ACCT_EXPTIME) { ++ *is_last_req = TRUE; ++ *acct_exp = (*last_req)->value; ++ } ++ } ++ } ++ ++ /* If we didn't find any, use the ambiguous key_exp field. */ ++ if (*is_last_req == FALSE) ++ *pw_exp = enc_part2->key_exp; ++} ++ ++/* ++ * Send an appropriate warning prompter if as_reply indicates that the password ++ * is going to expire soon. If an expire callback was provided, use that ++ * instead. ++ */ ++static void ++warn_pw_expiry(krb5_context context, krb5_get_init_creds_opt *options, ++ krb5_prompter_fct prompter, void *data, ++ const char *in_tkt_service, krb5_kdc_rep *as_reply) ++{ ++ krb5_error_code ret; ++ krb5_expire_callback_func expire_cb; ++ void *expire_data; ++ krb5_timestamp pw_exp, acct_exp, now; ++ krb5_boolean is_last_req; ++ krb5_deltat delta; ++ char ts[256], banner[1024]; ++ ++ if (as_reply == NULL || as_reply->enc_part2 == NULL) ++ return; ++ ++ get_expiry_times(as_reply->enc_part2, &pw_exp, &acct_exp, &is_last_req); ++ ++ k5_gic_opt_get_expire_cb(options, &expire_cb, &expire_data); ++ if (expire_cb != NULL) { ++ /* Invoke the expire callback and don't send prompter warnings. */ ++ (*expire_cb)(context, expire_data, pw_exp, acct_exp, is_last_req); ++ return; ++ } ++ ++ /* Don't warn if no password expiry value was sent. */ ++ if (pw_exp == 0) ++ return; ++ ++ /* Don't warn if the password is being changed. */ ++ if (in_tkt_service && strcmp(in_tkt_service, "kadmin/changepw") == 0) ++ return; ++ ++ /* ++ * If the expiry time came from a last_req field, assume the KDC wants us ++ * to warn. Otherwise, warn only if the expiry time is less than a week ++ * from now. ++ */ ++ ret = krb5_timeofday(context, &now); ++ if (ret != 0) ++ return; ++ if (!is_last_req && ++ (ts_after(now, pw_exp) || ts_delta(pw_exp, now) > 7 * 24 * 60 * 60)) ++ return; ++ ++ if (!prompter) ++ return; ++ ++ ret = krb5_timestamp_to_string(pw_exp, ts, sizeof(ts)); ++ if (ret != 0) ++ return; ++ ++ delta = ts_delta(pw_exp, now); ++ if (delta < 3600) { ++ snprintf(banner, sizeof(banner), ++ _("Warning: Your password will expire in less than one hour " ++ "on %s"), ts); ++ } else if (delta < 86400 * 2) { ++ snprintf(banner, sizeof(banner), ++ _("Warning: Your password will expire in %d hour%s on %s"), ++ delta / 3600, delta < 7200 ? "" : "s", ts); ++ } else { ++ snprintf(banner, sizeof(banner), ++ _("Warning: Your password will expire in %d days on %s"), ++ delta / 86400, ts); ++ } ++ ++ /* PROMPTER_INVOCATION */ ++ (*prompter)(context, data, 0, banner, 0, 0); ++} ++ + static krb5_error_code + init_creds_step_reply(krb5_context context, + krb5_init_creds_context ctx, +@@ -1693,6 +1803,8 @@ init_creds_step_reply(krb5_context context, + + /* success */ + ctx->complete = TRUE; ++ warn_pw_expiry(context, ctx->opt, ctx->prompter, ctx->prompter_data, ++ ctx->in_tkt_service, ctx->reply); + + cleanup: + krb5_free_pa_data(context, kdc_padata); +diff --git a/src/lib/krb5/krb/gic_pwd.c b/src/lib/krb5/krb/gic_pwd.c +index 14ce23ba4..54e0a8ebe 100644 +--- a/src/lib/krb5/krb/gic_pwd.c ++++ b/src/lib/krb5/krb/gic_pwd.c +@@ -133,113 +133,6 @@ krb5_init_creds_set_password(krb5_context context, + return 0; + } + +-/* Return the password expiry time indicated by enc_part2. Set *is_last_req +- * if the information came from a last_req value. */ +-static void +-get_expiry_times(krb5_enc_kdc_rep_part *enc_part2, krb5_timestamp *pw_exp, +- krb5_timestamp *acct_exp, krb5_boolean *is_last_req) +-{ +- krb5_last_req_entry **last_req; +- krb5_int32 lr_type; +- +- *pw_exp = 0; +- *acct_exp = 0; +- *is_last_req = FALSE; +- +- /* Look for last-req entries for password or account expiration. */ +- if (enc_part2->last_req) { +- for (last_req = enc_part2->last_req; *last_req; last_req++) { +- lr_type = (*last_req)->lr_type; +- if (lr_type == KRB5_LRQ_ALL_PW_EXPTIME || +- lr_type == KRB5_LRQ_ONE_PW_EXPTIME) { +- *is_last_req = TRUE; +- *pw_exp = (*last_req)->value; +- } else if (lr_type == KRB5_LRQ_ALL_ACCT_EXPTIME || +- lr_type == KRB5_LRQ_ONE_ACCT_EXPTIME) { +- *is_last_req = TRUE; +- *acct_exp = (*last_req)->value; +- } +- } +- } +- +- /* If we didn't find any, use the ambiguous key_exp field. */ +- if (*is_last_req == FALSE) +- *pw_exp = enc_part2->key_exp; +-} +- +-/* +- * Send an appropriate warning prompter if as_reply indicates that the password +- * is going to expire soon. If an expire callback was provided, use that +- * instead. +- */ +-static void +-warn_pw_expiry(krb5_context context, krb5_get_init_creds_opt *options, +- krb5_prompter_fct prompter, void *data, +- const char *in_tkt_service, krb5_kdc_rep *as_reply) +-{ +- krb5_error_code ret; +- krb5_expire_callback_func expire_cb; +- void *expire_data; +- krb5_timestamp pw_exp, acct_exp, now; +- krb5_boolean is_last_req; +- krb5_deltat delta; +- char ts[256], banner[1024]; +- +- get_expiry_times(as_reply->enc_part2, &pw_exp, &acct_exp, &is_last_req); +- +- k5_gic_opt_get_expire_cb(options, &expire_cb, &expire_data); +- if (expire_cb != NULL) { +- /* Invoke the expire callback and don't send prompter warnings. */ +- (*expire_cb)(context, expire_data, pw_exp, acct_exp, is_last_req); +- return; +- } +- +- /* Don't warn if no password expiry value was sent. */ +- if (pw_exp == 0) +- return; +- +- /* Don't warn if the password is being changed. */ +- if (in_tkt_service && strcmp(in_tkt_service, "kadmin/changepw") == 0) +- return; +- +- /* +- * If the expiry time came from a last_req field, assume the KDC wants us +- * to warn. Otherwise, warn only if the expiry time is less than a week +- * from now. +- */ +- ret = krb5_timeofday(context, &now); +- if (ret != 0) +- return; +- if (!is_last_req && +- (ts_after(now, pw_exp) || ts_delta(pw_exp, now) > 7 * 24 * 60 * 60)) +- return; +- +- if (!prompter) +- return; +- +- ret = krb5_timestamp_to_string(pw_exp, ts, sizeof(ts)); +- if (ret != 0) +- return; +- +- delta = ts_delta(pw_exp, now); +- if (delta < 3600) { +- snprintf(banner, sizeof(banner), +- _("Warning: Your password will expire in less than one hour " +- "on %s"), ts); +- } else if (delta < 86400*2) { +- snprintf(banner, sizeof(banner), +- _("Warning: Your password will expire in %d hour%s on %s"), +- delta / 3600, delta < 7200 ? "" : "s", ts); +- } else { +- snprintf(banner, sizeof(banner), +- _("Warning: Your password will expire in %d days on %s"), +- delta / 86400, ts); +- } +- +- /* PROMPTER_INVOCATION */ +- (*prompter)(context, data, 0, banner, 0, 0); +-} +- + /* + * Create a temporary options structure for getting a kadmin/changepw ticket, + * based on the appplication-specified options. Propagate all application +@@ -496,9 +389,6 @@ krb5_get_init_creds_password(krb5_context context, + goto cleanup; + + cleanup: +- if (ret == 0) +- warn_pw_expiry(context, options, prompter, data, in_tkt_service, +- as_reply); + free(chpw_opts); + zapfree(gakpw.storage.data, gakpw.storage.length); + memset(pw0array, 0, sizeof(pw0array)); +diff --git a/src/lib/krb5/krb/t_expire_warn.c b/src/lib/krb5/krb/t_expire_warn.c +index 1e59acba1..dc8dc8fb3 100644 +--- a/src/lib/krb5/krb/t_expire_warn.c ++++ b/src/lib/krb5/krb/t_expire_warn.c +@@ -28,6 +28,13 @@ + + static int exp_dummy, prompt_dummy; + ++static void ++check(krb5_error_code code) ++{ ++ if (code != 0) ++ abort(); ++} ++ + static krb5_error_code + prompter_cb(krb5_context ctx, void *data, const char *name, + const char *banner, int num_prompts, krb5_prompt prompts[]) +@@ -52,36 +59,48 @@ int + main(int argc, char **argv) + { + krb5_context ctx; ++ krb5_init_creds_context icctx; + krb5_get_init_creds_opt *opt; + char *user, *password, *service = NULL; +- krb5_boolean use_cb; ++ krb5_boolean use_cb, stepwise; + krb5_principal client; + krb5_creds creds; + +- if (argc < 4) { +- fprintf(stderr, "Usage: %s username password {1|0} [service]\n", ++ if (argc < 5) { ++ fprintf(stderr, "Usage: %s username password {1|0} {1|0} [service]\n", + argv[0]); + return 1; + } + user = argv[1]; + password = argv[2]; + use_cb = atoi(argv[3]); +- if (argc >= 5) +- service = argv[4]; ++ stepwise = atoi(argv[4]); ++ if (argc >= 6) ++ service = argv[5]; + +- assert(krb5_init_context(&ctx) == 0); +- assert(krb5_get_init_creds_opt_alloc(ctx, &opt) == 0); ++ check(krb5_init_context(&ctx)); ++ check(krb5_get_init_creds_opt_alloc(ctx, &opt)); + if (use_cb) { +- assert(krb5_get_init_creds_opt_set_expire_callback(ctx, opt, expire_cb, +- &exp_dummy) == 0); ++ check(krb5_get_init_creds_opt_set_expire_callback(ctx, opt, expire_cb, ++ &exp_dummy)); ++ } ++ check(krb5_parse_name(ctx, user, &client)); ++ if (stepwise) { ++ check(krb5_init_creds_init(ctx, client, prompter_cb, &prompt_dummy, 0, ++ opt, &icctx)); ++ krb5_init_creds_set_password(ctx, icctx, password); ++ if (service != NULL) ++ check(krb5_init_creds_set_service(ctx, icctx, service)); ++ check(krb5_init_creds_get(ctx, icctx)); ++ krb5_init_creds_free(ctx, icctx); ++ } else { ++ check(krb5_get_init_creds_password(ctx, &creds, client, password, ++ prompter_cb, &prompt_dummy, 0, ++ service, opt)); ++ krb5_free_cred_contents(ctx, &creds); + } +- assert(krb5_parse_name(ctx, user, &client) == 0); +- assert(krb5_get_init_creds_password(ctx, &creds, client, password, +- prompter_cb, &prompt_dummy, 0, service, +- opt) == 0); + krb5_get_init_creds_opt_free(ctx, opt); + krb5_free_principal(ctx, client); +- krb5_free_cred_contents(ctx, &creds); + krb5_free_context(ctx); + return 0; + } +diff --git a/src/lib/krb5/krb/t_expire_warn.py b/src/lib/krb5/krb/t_expire_warn.py +index 781f2728a..e163cc7e4 100755 +--- a/src/lib/krb5/krb/t_expire_warn.py ++++ b/src/lib/krb5/krb/t_expire_warn.py +@@ -34,23 +34,33 @@ realm.run([kadminl, 'addprinc', '-pw', 'pass', '-pwexpire', '12 hours', + realm.run([kadminl, 'addprinc', '-pw', 'pass', '-pwexpire', '3 days', 'days']) + + # Check for expected prompter warnings when no expire callback is used. +-output = realm.run(['./t_expire_warn', 'noexpire', 'pass', '0']) ++output = realm.run(['./t_expire_warn', 'noexpire', 'pass', '0', '0']) + if output: + fail('Unexpected output for noexpire') +-realm.run(['./t_expire_warn', 'minutes', 'pass', '0'], ++realm.run(['./t_expire_warn', 'minutes', 'pass', '0', '0'], + expected_msg=' less than one hour on ') +-realm.run(['./t_expire_warn', 'hours', 'pass', '0'], expected_msg=' hours on ') +-realm.run(['./t_expire_warn', 'days', 'pass', '0'], expected_msg=' days on ') ++realm.run(['./t_expire_warn', 'hours', 'pass', '0', '0'], ++ expected_msg=' hours on ') ++realm.run(['./t_expire_warn', 'days', 'pass', '0', '0'], ++ expected_msg=' days on ') ++# Try one case with the stepwise interface. ++realm.run(['./t_expire_warn', 'days', 'pass', '0', '1'], ++ expected_msg=' days on ') + + # Check for expected expire callback behavior. These tests are + # carefully agnostic about whether the KDC supports last_req fields, + # and could be made more specific if last_req support is added. +-output = realm.run(['./t_expire_warn', 'noexpire', 'pass', '1']) ++output = realm.run(['./t_expire_warn', 'noexpire', 'pass', '1', '0']) + if 'password_expiration = 0\n' not in output or \ + 'account_expiration = 0\n' not in output or \ + 'is_last_req = ' not in output: + fail('Expected callback output not seen for noexpire') +-output = realm.run(['./t_expire_warn', 'days', 'pass', '1']) ++output = realm.run(['./t_expire_warn', 'days', 'pass', '1', '0']) ++if 'password_expiration = ' not in output or \ ++ 'password_expiration = 0\n' in output: ++ fail('Expected non-zero password expiration not seen for days') ++# Try one case with the stepwise interface. ++output = realm.run(['./t_expire_warn', 'days', 'pass', '1', '1']) + if 'password_expiration = ' not in output or \ + 'password_expiration = 0\n' in output: + fail('Expected non-zero password expiration not seen for days') diff --git a/root/ppg/common/deps/krb5/rpm/Document-k-option-in-kvno-1-synopsis.patch b/root/ppg/common/deps/krb5/rpm/Document-k-option-in-kvno-1-synopsis.patch new file mode 100644 index 00000000..d2c2b0c8 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Document-k-option-in-kvno-1-synopsis.patch @@ -0,0 +1,39 @@ +From 5c1c391a80edd8ceb9e8bba9f7bdfb6639883ae6 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Tue, 24 Nov 2020 12:52:02 -0500 +Subject: [PATCH] Document -k option in kvno(1) synopsis + +becd1ad6830b526d08ddaf5b2b6f213154c6446c attempted to unify the +synopsis, option descriptions, and xusage(), but missed one option. + +(cherry picked from commit d81e76d9ddab9e880bcf54eabf07119af91d28c7) +(cherry picked from commit 588d964f59356373353dfd31d4fdcba95e508385) +--- + doc/user/user_commands/kvno.rst | 1 + + src/man/kvno.man | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/doc/user/user_commands/kvno.rst b/doc/user/user_commands/kvno.rst +index 65c44e1c0..93a5132b2 100644 +--- a/doc/user/user_commands/kvno.rst ++++ b/doc/user/user_commands/kvno.rst +@@ -9,6 +9,7 @@ SYNOPSIS + **kvno** + [**-c** *ccache*] + [**-e** *etype*] ++[**-k** *keytab*] + [**-q**] + [**-u** | **-S** *sname*] + [**-P**] +diff --git a/src/man/kvno.man b/src/man/kvno.man +index 22318324d..4e5b43b3b 100644 +--- a/src/man/kvno.man ++++ b/src/man/kvno.man +@@ -35,6 +35,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] + \fBkvno\fP + [\fB\-c\fP \fIccache\fP] + [\fB\-e\fP \fIetype\fP] ++[\fB\-k\fP \fIkeytab\fP] + [\fB\-q\fP] + [\fB\-u\fP | \fB\-S\fP \fIsname\fP] + [\fB\-P\fP] diff --git a/root/ppg/common/deps/krb5/rpm/Don-t-issue-session-keys-with-deprecated-enctypes.patch b/root/ppg/common/deps/krb5/rpm/Don-t-issue-session-keys-with-deprecated-enctypes.patch new file mode 100644 index 00000000..51ec6ef2 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Don-t-issue-session-keys-with-deprecated-enctypes.patch @@ -0,0 +1,374 @@ +From bf57cb193ef7180bb01c8e307258ee6ac93d9b8f Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Fri, 16 Dec 2022 18:31:07 -0500 +Subject: [PATCH] Don't issue session keys with deprecated enctypes + +A paper by Tom Tervoort noted that rc4-hmac pre-hashes the input for +its checksum and GSS operations before applying HMAC, and is therefore +potentially vulnerable to hash collision attacks if a protocol +contains a restricted signing oracle. + +In light of these potential attacks, begin the functional deprecation +of DES3 and RC4 by disallowing their use as session key enctypes by +default. Add the variables allow_des3 and allow_rc4 in case +negotiability of these enctypes for session keys needs to be turned +back on, with the expectation that in future releases the enctypes +will be more comprehensively deprecated. + +ticket: 9081 +(cherry picked from commit 1b57a4d134bbd0e7c52d5885a92eccc815726463) +--- + doc/admin/conf_files/krb5_conf.rst | 12 +++++ + doc/admin/enctypes.rst | 23 ++++++-- + src/include/k5-int.h | 4 ++ + src/kdc/kdc_util.c | 10 ++++ + src/lib/krb5/krb/get_in_tkt.c | 85 ++++++++++++++++++++++++++++++ + src/lib/krb5/krb/init_ctx.c | 10 ++++ + src/tests/gssapi/t_enctypes.py | 5 +- + src/tests/t_etype_info.py | 4 +- + src/tests/t_sesskeynego.py | 28 +++++++++- + src/util/k5test.py | 9 +++- + 10 files changed, 180 insertions(+), 10 deletions(-) + +diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst +index 98fe231813..c77a9fd46d 100644 +--- a/doc/admin/conf_files/krb5_conf.rst ++++ b/doc/admin/conf_files/krb5_conf.rst +@@ -95,6 +95,18 @@ Additionally, krb5.conf may include any of the relations described in + + The libdefaults section may contain any of the following relations: + ++**allow_des3** ++ Permit the KDC to issue tickets with des3-cbc-sha1 session keys. ++ In future releases, this flag will allow des3-cbc-sha1 to be used ++ at all. The default value for this tag is false. (Added in ++ release 1.21.) ++ ++**allow_rc4** ++ Permit the KDC to issue tickets with arcfour-hmac session keys. ++ In future releases, this flag will allow arcfour-hmac to be used ++ at all. The default value for this tag is false. (Added in ++ release 1.21.) ++ + **allow_weak_crypto** + If this flag is set to false, then weak encryption types (as noted + in :ref:`Encryption_types` in :ref:`kdc.conf(5)`) will be filtered +diff --git a/doc/admin/enctypes.rst b/doc/admin/enctypes.rst +index 65b55cdb9d..76ef2a2133 100644 +--- a/doc/admin/enctypes.rst ++++ b/doc/admin/enctypes.rst +@@ -48,12 +48,15 @@ Session key selection + The KDC chooses the session key enctype by taking the intersection of + its **permitted_enctypes** list, the list of long-term keys for the + most recent kvno of the service, and the client's requested list of +-enctypes. ++enctypes. Starting in krb5-1.21, all services are assumed to support ++aes256-cts-hmac-sha1-96; also, des3-cbc-sha1 and arcfour-hmac session ++keys will not be issued by default. + + Starting in krb5-1.11, it is possible to set a string attribute on a + service principal to control what session key enctypes the KDC may +-issue for service tickets for that principal. See :ref:`set_string` +-in :ref:`kadmin(1)` for details. ++issue for service tickets for that principal, overriding the service's ++long-term keys and the assumption of aes256-cts-hmac-sha1-96 support. ++See :ref:`set_string` in :ref:`kadmin(1)` for details. + + + Choosing enctypes for a service +@@ -87,6 +90,20 @@ affect how enctypes are chosen. + acceptable risk for your environment and the weak enctypes are + required for backward compatibility. + ++**allow_des3** ++ was added in release 1.21 and defaults to *false*. Unless this ++ flag is set to *true*, the KDC will not issue tickets with ++ des3-cbc-sha1 session keys. In a future release, this flag will ++ control whether des3-cbc-sha1 is permitted in similar fashion to ++ weak enctypes. ++ ++**allow_rc4** ++ was added in release 1.21 and defaults to *false*. Unless this ++ flag is set to *true*, the KDC will not issue tickets with ++ arcfour-hmac session keys. In a future release, this flag will ++ control whether arcfour-hmac is permitted in similar fashion to ++ weak enctypes. ++ + **permitted_enctypes** + controls the set of enctypes that a service will permit for + session keys and for ticket and authenticator encryption. The KDC +diff --git a/src/include/k5-int.h b/src/include/k5-int.h +index d062617268..c3d081fd30 100644 +--- a/src/include/k5-int.h ++++ b/src/include/k5-int.h +@@ -181,6 +181,8 @@ typedef unsigned char u_char; + * matches the variable name. Keep these alphabetized. */ + #define KRB5_CONF_ACL_FILE "acl_file" + #define KRB5_CONF_ADMIN_SERVER "admin_server" ++#define KRB5_CONF_ALLOW_DES3 "allow_des3" ++#define KRB5_CONF_ALLOW_RC4 "allow_rc4" + #define KRB5_CONF_ALLOW_WEAK_CRYPTO "allow_weak_crypto" + #define KRB5_CONF_AUTH_TO_LOCAL "auth_to_local" + #define KRB5_CONF_AUTH_TO_LOCAL_NAMES "auth_to_local_names" +@@ -1259,6 +1261,8 @@ struct _krb5_context { + struct _kdb_log_context *kdblog_context; + + krb5_boolean allow_weak_crypto; ++ krb5_boolean allow_des3; ++ krb5_boolean allow_rc4; + krb5_boolean ignore_acceptor_hostname; + krb5_boolean enforce_ok_as_delegate; + enum dns_canonhost dns_canonicalize_hostname; +diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c +index 23aadb88e9..b081d8e439 100644 +--- a/src/kdc/kdc_util.c ++++ b/src/kdc/kdc_util.c +@@ -1041,6 +1041,16 @@ select_session_keytype(kdc_realm_t *kdc_active_realm, krb5_db_entry *server, + if (!krb5_is_permitted_enctype(kdc_context, ktype[i])) + continue; + ++ /* ++ * Prevent these deprecated enctypes from being used as session keys ++ * unless they are explicitly allowed. In the future they will be more ++ * comprehensively disabled and eventually removed. ++ */ ++ if (ktype[i] == ENCTYPE_DES3_CBC_SHA1 && !kdc_context->allow_des3) ++ continue; ++ if (ktype[i] == ENCTYPE_ARCFOUR_HMAC && !kdc_context->allow_rc4) ++ continue; ++ + if (dbentry_supports_enctype(kdc_active_realm, server, ktype[i])) + return ktype[i]; + } +diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c +index f5dd7518b0..322fc94892 100644 +--- a/src/lib/krb5/krb/get_in_tkt.c ++++ b/src/lib/krb5/krb/get_in_tkt.c +@@ -1592,6 +1592,90 @@ warn_pw_expiry(krb5_context context, krb5_get_init_creds_opt *options, + (*prompter)(context, data, 0, banner, 0, 0); + } + ++/* Display a warning via the prompter if a deprecated enctype was used for ++ * either the reply key or the session key. */ ++static void ++warn_deprecated(krb5_context context, krb5_init_creds_context ctx, ++ krb5_enctype as_key_enctype) ++{ ++ krb5_enctype etype; ++ char encbuf[128], banner[256]; ++ ++ if (ctx->prompter == NULL) ++ return; ++ ++ if (krb5int_c_deprecated_enctype(as_key_enctype)) ++ etype = as_key_enctype; ++ else if (krb5int_c_deprecated_enctype(ctx->cred.keyblock.enctype)) ++ etype = ctx->cred.keyblock.enctype; ++ else ++ return; ++ ++ if (krb5_enctype_to_name(etype, FALSE, encbuf, sizeof(encbuf)) != 0) ++ return; ++ snprintf(banner, sizeof(banner), ++ _("Warning: encryption type %s used for authentication is " ++ "deprecated and will be disabled"), encbuf); ++ ++ /* PROMPTER_INVOCATION */ ++ (*ctx->prompter)(context, ctx->prompter_data, NULL, banner, 0, NULL); ++} ++ ++/* ++ * If ctx specifies an output ccache, create or refresh it (atomically, if ++ * possible) with the obtained credential and any appropriate ccache ++ * configuration. ++ */ ++static krb5_error_code ++write_out_ccache(krb5_context context, krb5_init_creds_context ctx, ++ krb5_boolean fast_avail) ++{ ++ krb5_error_code ret; ++ krb5_ccache out_ccache = k5_gic_opt_get_out_ccache(ctx->opt); ++ krb5_ccache mcc = NULL; ++ krb5_data yes = string2data("yes"); ++ ++ if (out_ccache == NULL) ++ return 0; ++ ++ ret = krb5_cc_new_unique(context, "MEMORY", NULL, &mcc); ++ if (ret) ++ goto cleanup; ++ ++ ret = krb5_cc_initialize(context, mcc, ctx->cred.client); ++ if (ret) ++ goto cleanup; ++ ++ if (fast_avail) { ++ ret = krb5_cc_set_config(context, mcc, ctx->cred.server, ++ KRB5_CC_CONF_FAST_AVAIL, &yes); ++ if (ret) ++ goto cleanup; ++ } ++ ++ ret = save_selected_preauth_type(context, mcc, ctx); ++ if (ret) ++ goto cleanup; ++ ++ ret = save_cc_config_out_data(context, mcc, ctx); ++ if (ret) ++ goto cleanup; ++ ++ ret = k5_cc_store_primary_cred(context, mcc, &ctx->cred); ++ if (ret) ++ goto cleanup; ++ ++ ret = krb5_cc_move(context, mcc, out_ccache); ++ if (ret) ++ goto cleanup; ++ mcc = NULL; ++ ++cleanup: ++ if (mcc != NULL) ++ krb5_cc_destroy(context, mcc); ++ return ret; ++} ++ + static krb5_error_code + init_creds_step_reply(krb5_context context, + krb5_init_creds_context ctx, +@@ -1805,6 +1889,7 @@ init_creds_step_reply(krb5_context context, + ctx->complete = TRUE; + warn_pw_expiry(context, ctx->opt, ctx->prompter, ctx->prompter_data, + ctx->in_tkt_service, ctx->reply); ++ warn_deprecated(context, ctx, encrypting_key.enctype); + + cleanup: + krb5_free_pa_data(context, kdc_padata); +diff --git a/src/lib/krb5/krb/init_ctx.c b/src/lib/krb5/krb/init_ctx.c +index 1a6e0bf672..4b23738817 100644 +--- a/src/lib/krb5/krb/init_ctx.c ++++ b/src/lib/krb5/krb/init_ctx.c +@@ -226,6 +226,16 @@ krb5_init_context_profile(profile_t profile, krb5_flags flags, + goto cleanup; + ctx->allow_weak_crypto = tmp; + ++ retval = get_boolean(ctx, KRB5_CONF_ALLOW_DES3, 0, &tmp); ++ if (retval) ++ goto cleanup; ++ ctx->allow_des3 = tmp; ++ ++ retval = get_boolean(ctx, KRB5_CONF_ALLOW_RC4, 0, &tmp); ++ if (retval) ++ goto cleanup; ++ ctx->allow_rc4 = tmp; ++ + retval = get_boolean(ctx, KRB5_CONF_IGNORE_ACCEPTOR_HOSTNAME, 0, &tmp); + if (retval) + goto cleanup; +diff --git a/src/tests/gssapi/t_enctypes.py b/src/tests/gssapi/t_enctypes.py +index 2f95d89967..e6bde47afc 100755 +--- a/src/tests/gssapi/t_enctypes.py ++++ b/src/tests/gssapi/t_enctypes.py +@@ -10,8 +10,9 @@ d_rc4 = 'DEPRECATED:arcfour-hmac' + + # These tests make assumptions about the default enctype lists, so set + # them explicitly rather than relying on the library defaults. +-supp='aes256-cts:normal aes128-cts:normal rc4-hmac:normal' +-conf = {'libdefaults': {'permitted_enctypes': 'aes rc4'}, ++supp='aes256-cts:normal aes128-cts:normal des3-cbc-sha1:normal rc4-hmac:normal' ++conf = {'libdefaults': {'permitted_enctypes': 'aes des3 rc4', ++ 'allow_des3': 'true', 'allow_rc4': 'true'}, + 'realms': {'$realm': {'supported_enctypes': supp}}} + realm = K5Realm(krb5_conf=conf) + shutil.copyfile(realm.ccache, os.path.join(realm.testdir, 'save')) +diff --git a/src/tests/t_etype_info.py b/src/tests/t_etype_info.py +index ace0edc3c4..9ea5ca6228 100644 +--- a/src/tests/t_etype_info.py ++++ b/src/tests/t_etype_info.py +@@ -1,7 +1,7 @@ + from k5test import * + +-supported_enctypes = 'aes128-cts rc4-hmac' +-conf = {'libdefaults': {'allow_weak_crypto': 'true'}, ++supported_enctypes = 'aes128-cts des3-cbc-sha1 rc4-hmac' ++conf = {'libdefaults': {'allow_des3': 'true', 'allow_rc4': 'true'}, + 'realms': {'$realm': {'supported_enctypes': supported_enctypes}}} + realm = K5Realm(create_host=False, get_creds=False, krb5_conf=conf) + +diff --git a/src/tests/t_sesskeynego.py b/src/tests/t_sesskeynego.py +index 73a55366c4..f30d0bc16c 100755 +--- a/src/tests/t_sesskeynego.py ++++ b/src/tests/t_sesskeynego.py +@@ -25,6 +25,8 @@ conf3 = {'libdefaults': { + 'default_tkt_enctypes': 'aes128-cts', + 'default_tgs_enctypes': 'rc4-hmac,aes128-cts'}} + conf4 = {'libdefaults': {'permitted_enctypes': 'aes256-cts'}} ++conf5 = {'libdefaults': {'allow_rc4': 'true'}} ++conf6 = {'libdefaults': {'allow_des3': 'true'}} + # Test with client request and session_enctypes preferring aes128, but + # aes256 long-term key. + realm = K5Realm(krb5_conf=conf1, create_host=False, get_creds=False) +@@ -54,10 +56,12 @@ realm.run([kadminl, 'setstr', 'server', 'session_enctypes', + 'aes128-cts,aes256-cts']) + test_kvno(realm, 'aes128-cts-hmac-sha1-96', 'aes256-cts-hmac-sha1-96') + +-# 3b: Negotiate rc4-hmac session key when principal only has aes256 long-term. ++# 3b: Skip RC4 (as the KDC does not allow it for session keys by ++# default) and negotiate aes128-cts session key, with only an aes256 ++# long-term service key. + realm.run([kadminl, 'setstr', 'server', 'session_enctypes', + 'rc4-hmac,aes128-cts,aes256-cts']) +-test_kvno(realm, 'DEPRECATED:arcfour-hmac', 'aes256-cts-hmac-sha1-96') ++test_kvno(realm, 'aes128-cts-hmac-sha1-96', 'aes256-cts-hmac-sha1-96') + realm.stop() + + # 4: Check that permitted_enctypes is a default for session key enctypes. +@@ -67,4 +71,24 @@ realm.run([kvno, 'user'], + expected_trace=('etypes requested in TGS request: aes256-cts',)) + realm.stop() + ++# 5: allow_rc4 permits negotiation of rc4-hmac session key. ++realm = K5Realm(krb5_conf=conf5, create_host=False, get_creds=False) ++realm.run([kadminl, 'addprinc', '-randkey', '-e', 'aes256-cts', 'server']) ++realm.run([kadminl, 'setstr', 'server', 'session_enctypes', 'rc4-hmac']) ++test_kvno(realm, 'DEPRECATED:arcfour-hmac', 'aes256-cts-hmac-sha1-96') ++realm.stop() ++ ++# 6: allow_des3 permits negotiation of des3-cbc-sha1 session key. ++realm = K5Realm(krb5_conf=conf6, create_host=False, get_creds=False) ++realm.run([kadminl, 'addprinc', '-randkey', '-e', 'aes256-cts', 'server']) ++realm.run([kadminl, 'setstr', 'server', 'session_enctypes', 'des3-cbc-sha1']) ++test_kvno(realm, 'DEPRECATED:des3-cbc-sha1', 'aes256-cts-hmac-sha1-96') ++realm.stop() ++ ++# 7: default config negotiates aes256-sha1 session key for RC4-only service. ++realm = K5Realm(create_host=False, get_creds=False) ++realm.run([kadminl, 'addprinc', '-randkey', '-e', 'rc4-hmac', 'server']) ++test_kvno(realm, 'aes256-cts-hmac-sha1-96', 'DEPRECATED:arcfour-hmac') ++realm.stop() ++ + success('sesskeynego') +diff --git a/src/util/k5test.py b/src/util/k5test.py +index eea92275d7..96474cc5aa 100644 +--- a/src/util/k5test.py ++++ b/src/util/k5test.py +@@ -1299,9 +1299,16 @@ _passes = [ + # No special settings; exercises AES256. + ('default', None, None, None), + ++ # Exercise the DES3 enctype. ++ ('des3', None, ++ {'libdefaults': {'permitted_enctypes': 'des3 aes256-sha1'}}, ++ {'realms': {'$realm': { ++ 'supported_enctypes': 'des3-cbc-sha1:normal', ++ 'master_key_type': 'des3-cbc-sha1'}}}), ++ + # Exercise the arcfour enctype. + ('arcfour', None, +- {'libdefaults': {'permitted_enctypes': 'rc4'}}, ++ {'libdefaults': {'permitted_enctypes': 'rc4 aes256-sha1'}}, + {'realms': {'$realm': { + 'supported_enctypes': 'arcfour-hmac:normal', + 'master_key_type': 'arcfour-hmac'}}}), +-- +2.49.0 + diff --git a/root/ppg/common/deps/krb5/rpm/Eliminate-redundant-PKINIT-responder-invocation.patch b/root/ppg/common/deps/krb5/rpm/Eliminate-redundant-PKINIT-responder-invocation.patch new file mode 100644 index 00000000..bf45de85 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Eliminate-redundant-PKINIT-responder-invocation.patch @@ -0,0 +1,94 @@ +From e2cc7a04f0dbfbf1a8bc6cd70f639c56a203af28 Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Mon, 23 Mar 2020 19:10:03 -0400 +Subject: [PATCH] Eliminate redundant PKINIT responder invocation + +In pkinit_client_prep_questions(), only act if the input padata type +is KRB5_PADATA_PK_AS_REQ. Otherwise we will ask questions again when +the KDC issues a ticket. + +Commit 7621d2f9a87214327ca3b2594e34dc7cea84596b (ticket 8242) +unintentionally changed the behavior of pkinit_load_fs_cert_and_key(), +causing pkinit_client_prep_questions() to do nothing on its first +call. Restore the original behavior of returning 0 when prompting is +deferred. + +Modify the existing "FILE identity, password on key (responder)" +PKINIT test to check that the responder is only invoked once. + +ticket: 8885 +(cherry picked from commit f1286842ce7b9e507a4ce0a47f44ab361a98be63) +(cherry picked from commit 4a05805eb39ba088c07f782fb52a6538ec3f2db6) +--- + src/plugins/preauth/pkinit/pkinit_clnt.c | 5 +++++ + src/plugins/preauth/pkinit/pkinit_crypto_openssl.c | 13 +++++++------ + src/tests/t_pkinit.py | 11 +++++++---- + 3 files changed, 19 insertions(+), 10 deletions(-) + +diff --git a/src/plugins/preauth/pkinit/pkinit_clnt.c b/src/plugins/preauth/pkinit/pkinit_clnt.c +index 2f0431991..9b991ffe0 100644 +--- a/src/plugins/preauth/pkinit/pkinit_clnt.c ++++ b/src/plugins/preauth/pkinit/pkinit_clnt.c +@@ -897,6 +897,11 @@ pkinit_client_prep_questions(krb5_context context, + k5_json_object jval = NULL; + k5_json_number jflag = NULL; + ++ /* Don't ask questions for the informational padata items or when the ++ * ticket is issued. */ ++ if (pa_data->pa_type != KRB5_PADATA_PK_AS_REQ) ++ return 0; ++ + if (!reqctx->identity_initialized) { + pkinit_client_profile(context, plgctx, reqctx, cb, rock, + &request->server->realm); +diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c +index dd718c2be..dbb054378 100644 +--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c ++++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c +@@ -4362,17 +4362,18 @@ pkinit_load_fs_cert_and_key(krb5_context context, + + /* Load the certificate. */ + retval = get_cert(certname, &x); +- if (retval != 0 || x == NULL) { +- retval = oerr(context, 0, _("Cannot read certificate file '%s'"), ++ if (retval) { ++ retval = oerr(context, retval, _("Cannot read certificate file '%s'"), + certname); +- goto cleanup; + } ++ if (retval || x == NULL) ++ goto cleanup; + /* Load the key. */ + retval = get_key(context, id_cryptoctx, keyname, fsname, &y, password); +- if (retval != 0 || y == NULL) { +- retval = oerr(context, 0, _("Cannot read key file '%s'"), fsname); ++ if (retval) ++ retval = oerr(context, retval, _("Cannot read key file '%s'"), fsname); ++ if (retval || y == NULL) + goto cleanup; +- } + + id_cryptoctx->creds[cindex] = malloc(sizeof(struct _pkinit_cred_info)); + if (id_cryptoctx->creds[cindex] == NULL) { +diff --git a/src/tests/t_pkinit.py b/src/tests/t_pkinit.py +index 69daf4987..ecd450e8a 100755 +--- a/src/tests/t_pkinit.py ++++ b/src/tests/t_pkinit.py +@@ -248,10 +248,13 @@ realm.run(['./adata', realm.host_princ], + # supplied by the responder. + # Supply the response in raw form. + mark('FILE identity, password on key (responder)') +-realm.run(['./responder', '-x', 'pkinit={"%s": 0}' % file_enc_identity, +- '-r', 'pkinit={"%s": "encrypted"}' % file_enc_identity, +- '-X', 'X509_user_identity=%s' % file_enc_identity, +- realm.user_princ]) ++out = realm.run(['./responder', '-x', 'pkinit={"%s": 0}' % file_enc_identity, ++ '-r', 'pkinit={"%s": "encrypted"}' % file_enc_identity, ++ '-X', 'X509_user_identity=%s' % file_enc_identity, ++ realm.user_princ]) ++# Regression test for #8885 (password question asked twice). ++if out.count('OK: ') != 1: ++ fail('Wrong number of responder calls') + # Supply the response through the convenience API. + realm.run(['./responder', '-X', 'X509_user_identity=%s' % file_enc_identity, + '-p', '%s=%s' % (file_enc_identity, 'encrypted'), realm.user_princ]) diff --git a/root/ppg/common/deps/krb5/rpm/End-connection-on-KDC_ERR_SVC_UNAVAILABLE.patch b/root/ppg/common/deps/krb5/rpm/End-connection-on-KDC_ERR_SVC_UNAVAILABLE.patch new file mode 100644 index 00000000..a0f0d25d --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/End-connection-on-KDC_ERR_SVC_UNAVAILABLE.patch @@ -0,0 +1,34 @@ +From a68fba22588cc21dcd1dc28550529187dca58331 Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Fri, 27 Oct 2023 00:44:53 -0400 +Subject: [PATCH] End connection on KDC_ERR_SVC_UNAVAILABLE + +In sendto_kdc.c:service_fds(), if a message handler indicates that a +message should be discarded, kill the connection so we don't continue +waiting on it for more data. + +ticket: 7899 +(cherry picked from commit ca80f64c786341d5871ae1de18142e62af64f7b9) +--- + src/lib/krb5/os/sendto_kdc.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/src/lib/krb5/os/sendto_kdc.c b/src/lib/krb5/os/sendto_kdc.c +index d76e24ccf0..8e4fcd2a38 100644 +--- a/src/lib/krb5/os/sendto_kdc.c ++++ b/src/lib/krb5/os/sendto_kdc.c +@@ -1435,7 +1435,10 @@ service_fds(krb5_context context, struct select_state *selstate, + if (msg_handler != NULL) { + krb5_data reply = make_data(state->in.buf, state->in.pos); + +- stop = (msg_handler(context, &reply, msg_handler_data) != 0); ++ if (!msg_handler(context, &reply, msg_handler_data)) { ++ kill_conn(context, state, selstate); ++ stop = 0; ++ } + } + + if (stop) { +-- +2.44.0 + diff --git a/root/ppg/common/deps/krb5/rpm/Factor-out-PAC-checksum-verification.patch b/root/ppg/common/deps/krb5/rpm/Factor-out-PAC-checksum-verification.patch new file mode 100644 index 00000000..fa5a21c7 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Factor-out-PAC-checksum-verification.patch @@ -0,0 +1,258 @@ +From b0372e31b81321a820204450a35c7633caf1b7dd Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Fri, 14 Jan 2022 02:05:58 -0500 +Subject: [PATCH] Factor out PAC checksum verification + +Reduce code repetition in PAC checksum handling by adding a helper +function. Remove the unnecessary prefix on several function names. +--- + src/lib/krb5/krb/pac.c | 173 +++++++++++++---------------------------- + 1 file changed, 55 insertions(+), 118 deletions(-) + +diff --git a/src/lib/krb5/krb/pac.c b/src/lib/krb5/krb/pac.c +index 6eb23d8090..2f6ad4e1df 100644 +--- a/src/lib/krb5/krb/pac.c ++++ b/src/lib/krb5/krb/pac.c +@@ -493,10 +493,8 @@ k5_pac_validate_client(krb5_context context, + } + + static krb5_error_code +-k5_pac_zero_signature(krb5_context context, +- const krb5_pac pac, +- krb5_ui_4 type, +- krb5_data *data) ++zero_signature(krb5_context context, const krb5_pac pac, krb5_ui_4 type, ++ krb5_data *data) + { + PAC_INFO_BUFFER *buffer = NULL; + size_t i; +@@ -530,151 +528,89 @@ k5_pac_zero_signature(krb5_context context, + } + + static krb5_error_code +-k5_pac_verify_server_checksum(krb5_context context, +- const krb5_pac pac, +- const krb5_keyblock *server) ++verify_checksum(krb5_context context, const krb5_pac pac, uint32_t buffer_type, ++ const krb5_keyblock *key, krb5_keyusage usage, ++ const krb5_data *data) + { + krb5_error_code ret; +- krb5_data pac_data; /* PAC with zeroed checksums */ ++ krb5_data buffer; ++ krb5_cksumtype cksumtype; + krb5_checksum checksum; +- krb5_data checksum_data; + krb5_boolean valid; +- krb5_octet *p; ++ size_t cksumlen; + +- ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_SERVER_CHECKSUM, +- &checksum_data); ++ ret = k5_pac_locate_buffer(context, pac, buffer_type, &buffer); + if (ret != 0) + return ret; +- +- if (checksum_data.length < PAC_SIGNATURE_DATA_LENGTH) ++ if (buffer.length < PAC_SIGNATURE_DATA_LENGTH) + return KRB5_BAD_MSIZE; + +- p = (krb5_octet *)checksum_data.data; +- checksum.checksum_type = load_32_le(p); +- checksum.length = checksum_data.length - PAC_SIGNATURE_DATA_LENGTH; +- checksum.contents = p + PAC_SIGNATURE_DATA_LENGTH; +- if (checksum.checksum_type == CKSUMTYPE_SHA1) ++ cksumtype = load_32_le(buffer.data); ++ if (buffer_type == KRB5_PAC_SERVER_CHECKSUM && cksumtype == CKSUMTYPE_SHA1) + return KRB5KDC_ERR_SUMTYPE_NOSUPP; +- if (!krb5_c_is_keyed_cksum(checksum.checksum_type)) ++ if (!krb5_c_is_keyed_cksum(cksumtype)) + return KRB5KRB_ERR_GENERIC; + +- pac_data.length = pac->data.length; +- pac_data.data = k5memdup(pac->data.data, pac->data.length, &ret); +- if (pac_data.data == NULL) +- return ret; +- +- /* Zero out both checksum buffers */ +- ret = k5_pac_zero_signature(context, pac, KRB5_PAC_SERVER_CHECKSUM, +- &pac_data); +- if (ret != 0) { +- free(pac_data.data); +- return ret; +- } +- +- ret = k5_pac_zero_signature(context, pac, KRB5_PAC_PRIVSVR_CHECKSUM, +- &pac_data); +- if (ret != 0) { +- free(pac_data.data); ++ /* There may be an RODCIdentifier trailer (see [MS-PAC] 2.8), so look up ++ * the length of the checksum by its type. */ ++ ret = krb5_c_checksum_length(context, cksumtype, &cksumlen); ++ if (ret) + return ret; +- } ++ if (cksumlen > buffer.length - PAC_SIGNATURE_DATA_LENGTH) ++ return KRB5_BAD_MSIZE; ++ checksum.checksum_type = cksumtype; ++ checksum.length = cksumlen; ++ checksum.contents = (uint8_t *)buffer.data + PAC_SIGNATURE_DATA_LENGTH; + +- ret = krb5_c_verify_checksum(context, server, +- KRB5_KEYUSAGE_APP_DATA_CKSUM, +- &pac_data, &checksum, &valid); ++ ret = krb5_c_verify_checksum(context, key, usage, data, &checksum, &valid); ++ return ret ? ret : (valid ? 0 : KRB5KRB_AP_ERR_MODIFIED); ++} + +- free(pac_data.data); ++static krb5_error_code ++verify_server_checksum(krb5_context context, const krb5_pac pac, ++ const krb5_keyblock *server) ++{ ++ krb5_error_code ret; ++ krb5_data copy; /* PAC with zeroed checksums */ + +- if (ret != 0) { ++ ret = krb5int_copy_data_contents(context, &pac->data, ©); ++ if (ret) + return ret; +- } + +- if (valid == FALSE) +- ret = KRB5KRB_AP_ERR_MODIFIED; ++ /* Zero out both checksum buffers */ ++ ret = zero_signature(context, pac, KRB5_PAC_SERVER_CHECKSUM, ©); ++ if (ret) ++ goto cleanup; ++ ret = zero_signature(context, pac, KRB5_PAC_PRIVSVR_CHECKSUM, ©); ++ if (ret) ++ goto cleanup; ++ ++ ret = verify_checksum(context, pac, KRB5_PAC_SERVER_CHECKSUM, server, ++ KRB5_KEYUSAGE_APP_DATA_CKSUM, ©); + ++cleanup: ++ free(copy.data); + return ret; + } + + static krb5_error_code +-k5_pac_verify_kdc_checksum(krb5_context context, +- const krb5_pac pac, +- const krb5_keyblock *privsvr) ++verify_kdc_checksum(krb5_context context, const krb5_pac pac, ++ const krb5_keyblock *privsvr) + { + krb5_error_code ret; +- krb5_data server_checksum, privsvr_checksum; +- krb5_checksum checksum; +- krb5_boolean valid; +- krb5_octet *p; +- +- ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_PRIVSVR_CHECKSUM, +- &privsvr_checksum); +- if (ret != 0) +- return ret; +- +- if (privsvr_checksum.length < PAC_SIGNATURE_DATA_LENGTH) +- return KRB5_BAD_MSIZE; ++ krb5_data server_checksum; + + ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_SERVER_CHECKSUM, + &server_checksum); +- if (ret != 0) ++ if (ret) + return ret; +- + if (server_checksum.length < PAC_SIGNATURE_DATA_LENGTH) + return KRB5_BAD_MSIZE; +- +- p = (krb5_octet *)privsvr_checksum.data; +- checksum.checksum_type = load_32_le(p); +- checksum.length = privsvr_checksum.length - PAC_SIGNATURE_DATA_LENGTH; +- checksum.contents = p + PAC_SIGNATURE_DATA_LENGTH; +- if (!krb5_c_is_keyed_cksum(checksum.checksum_type)) +- return KRB5KRB_ERR_GENERIC; +- + server_checksum.data += PAC_SIGNATURE_DATA_LENGTH; + server_checksum.length -= PAC_SIGNATURE_DATA_LENGTH; + +- ret = krb5_c_verify_checksum(context, privsvr, +- KRB5_KEYUSAGE_APP_DATA_CKSUM, +- &server_checksum, &checksum, &valid); +- if (ret != 0) +- return ret; +- +- if (valid == FALSE) +- ret = KRB5KRB_AP_ERR_MODIFIED; +- +- return ret; +-} +- +-static krb5_error_code +-verify_ticket_checksum(krb5_context context, const krb5_pac pac, +- const krb5_data *ticket, const krb5_keyblock *privsvr) +-{ +- krb5_error_code ret; +- krb5_checksum checksum; +- krb5_data checksum_data; +- krb5_boolean valid; +- krb5_octet *p; +- +- ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_TICKET_CHECKSUM, +- &checksum_data); +- if (ret != 0) +- return KRB5KRB_AP_ERR_MODIFIED; +- +- if (checksum_data.length < PAC_SIGNATURE_DATA_LENGTH) +- return KRB5_BAD_MSIZE; +- +- p = (krb5_octet *)checksum_data.data; +- checksum.checksum_type = load_32_le(p); +- checksum.length = checksum_data.length - PAC_SIGNATURE_DATA_LENGTH; +- checksum.contents = p + PAC_SIGNATURE_DATA_LENGTH; +- if (!krb5_c_is_keyed_cksum(checksum.checksum_type)) +- return KRB5KRB_ERR_GENERIC; +- +- ret = krb5_c_verify_checksum(context, privsvr, +- KRB5_KEYUSAGE_APP_DATA_CKSUM, ticket, +- &checksum, &valid); +- if (ret != 0) +- return ret; +- +- return valid ? 0 : KRB5KRB_AP_ERR_MODIFIED; ++ return verify_checksum(context, pac, KRB5_PAC_PRIVSVR_CHECKSUM, privsvr, ++ KRB5_KEYUSAGE_APP_DATA_CKSUM, &server_checksum); + } + + /* Per MS-PAC 2.8.3, tickets encrypted to TGS and password change principals +@@ -761,7 +697,8 @@ krb5_kdc_verify_ticket(krb5_context context, const krb5_enc_tkt_part *enc_tkt, + if (ret) + goto cleanup; + +- ret = verify_ticket_checksum(context, pac, recoded_tkt, privsvr); ++ ret = verify_checksum(context, pac, KRB5_PAC_TICKET_CHECKSUM, privsvr, ++ KRB5_KEYUSAGE_APP_DATA_CKSUM, recoded_tkt); + if (ret) + goto cleanup; + } +@@ -804,13 +741,13 @@ krb5_pac_verify_ext(krb5_context context, + krb5_error_code ret; + + if (server != NULL) { +- ret = k5_pac_verify_server_checksum(context, pac, server); ++ ret = verify_server_checksum(context, pac, server); + if (ret != 0) + return ret; + } + + if (privsvr != NULL) { +- ret = k5_pac_verify_kdc_checksum(context, pac, privsvr); ++ ret = verify_kdc_checksum(context, pac, privsvr); + if (ret != 0) + return ret; + } +-- +2.39.2 + diff --git a/root/ppg/common/deps/krb5/rpm/Fix-KCM-flag-transmission-for-remove_cred.patch b/root/ppg/common/deps/krb5/rpm/Fix-KCM-flag-transmission-for-remove_cred.patch new file mode 100644 index 00000000..34c2a3b3 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Fix-KCM-flag-transmission-for-remove_cred.patch @@ -0,0 +1,105 @@ +From 261b0ed68fb83c34c70679ae8452cae2dba7e4e3 Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Mon, 29 Mar 2021 14:32:56 -0400 +Subject: [PATCH] Fix KCM flag transmission for remove_cred + +MIT krb5 uses low bits for KRB5_TC flags, while Heimdal uses high bits +so that the same flag word can also hold KRB5_GC flags. Add a mapping +function and send the Heimdal flag values when performing a +remove_cred operation. + +ticket: 8995 +(cherry picked from commit 11a82cf424f9c905bb73680c64524f087090d4ef) +(cherry picked from commit 04f0de4420508161ce439f262f2761ff51a07ab0) +(cherry picked from commit ddbb295dee2adcc6cec26944974420bba188f191) +--- + src/include/kcm.h | 19 +++++++++++++++++++ + src/lib/krb5/ccache/cc_kcm.c | 36 +++++++++++++++++++++++++++++++++++- + 2 files changed, 54 insertions(+), 1 deletion(-) + +diff --git a/src/include/kcm.h b/src/include/kcm.h +index e4140c3a0..9b66f1cbd 100644 +--- a/src/include/kcm.h ++++ b/src/include/kcm.h +@@ -56,8 +56,27 @@ + * are marshalled as zero-terminated strings. Principals and credentials are + * marshalled in the v4 FILE ccache format. UUIDs are 16 bytes. UUID lists + * are not delimited, so nothing can come after them. ++ * ++ * Flag words must use Heimdal flag values, which are not the same as MIT krb5 ++ * values for KRB5_GC and KRB5_TC constants. The same flag word may contain ++ * both kinds of flags in Heimdal, but not in MIT krb5. Defines for the ++ * applicable Heimdal flag values are given below using KCM_GC and KCM_TC ++ * prefixes. + */ + ++#define KCM_GC_CACHED (1U << 0) ++ ++#define KCM_TC_DONT_MATCH_REALM (1U << 31) ++#define KCM_TC_MATCH_KEYTYPE (1U << 30) ++#define KCM_TC_MATCH_SRV_NAMEONLY (1U << 29) ++#define KCM_TC_MATCH_FLAGS_EXACT (1U << 28) ++#define KCM_TC_MATCH_FLAGS (1U << 27) ++#define KCM_TC_MATCH_TIMES_EXACT (1U << 26) ++#define KCM_TC_MATCH_TIMES (1U << 25) ++#define KCM_TC_MATCH_AUTHDATA (1U << 24) ++#define KCM_TC_MATCH_2ND_TKT (1U << 23) ++#define KCM_TC_MATCH_IS_SKEY (1U << 22) ++ + /* Opcodes without comments are currently unused in the MIT client + * implementation. */ + typedef enum kcm_opcode { +diff --git a/src/lib/krb5/ccache/cc_kcm.c b/src/lib/krb5/ccache/cc_kcm.c +index 197a10fba..4141140c3 100644 +--- a/src/lib/krb5/ccache/cc_kcm.c ++++ b/src/lib/krb5/ccache/cc_kcm.c +@@ -110,6 +110,40 @@ map_invalid(krb5_error_code code) + KRB5_KCM_MALFORMED_REPLY : code; + } + ++/* ++ * Map an MIT krb5 KRB5_TC flag word to the equivalent Heimdal flag word. Note ++ * that there is no MIT krb5 equivalent for Heimdal's KRB5_TC_DONT_MATCH_REALM ++ * (which is like KRB5_TC_MATCH_SRV_NAMEONLY but also applies to the client ++ * principal) and no Heimdal equivalent for MIT krb5's KRB5_TC_SUPPORTED_KTYPES ++ * (which matches against enctypes from the krb5_context rather than the ++ * matching cred). ++ */ ++static inline krb5_flags ++map_tcflags(krb5_flags mitflags) ++{ ++ krb5_flags heimflags = 0; ++ ++ if (mitflags & KRB5_TC_MATCH_TIMES) ++ heimflags |= KCM_TC_MATCH_TIMES; ++ if (mitflags & KRB5_TC_MATCH_IS_SKEY) ++ heimflags |= KCM_TC_MATCH_IS_SKEY; ++ if (mitflags & KRB5_TC_MATCH_FLAGS) ++ heimflags |= KCM_TC_MATCH_FLAGS; ++ if (mitflags & KRB5_TC_MATCH_TIMES_EXACT) ++ heimflags |= KCM_TC_MATCH_TIMES_EXACT; ++ if (mitflags & KRB5_TC_MATCH_FLAGS_EXACT) ++ heimflags |= KCM_TC_MATCH_FLAGS_EXACT; ++ if (mitflags & KRB5_TC_MATCH_AUTHDATA) ++ heimflags |= KCM_TC_MATCH_AUTHDATA; ++ if (mitflags & KRB5_TC_MATCH_SRV_NAMEONLY) ++ heimflags |= KCM_TC_MATCH_SRV_NAMEONLY; ++ if (mitflags & KRB5_TC_MATCH_2ND_TKT) ++ heimflags |= KCM_TC_MATCH_2ND_TKT; ++ if (mitflags & KRB5_TC_MATCH_KTYPE) ++ heimflags |= KCM_TC_MATCH_KEYTYPE; ++ return heimflags; ++} ++ + /* Begin a request for the given opcode. If cache is non-null, supply the + * cache name as a request parameter. */ + static void +@@ -936,7 +970,7 @@ kcm_remove_cred(krb5_context context, krb5_ccache cache, krb5_flags flags, + struct kcmreq req; + + kcmreq_init(&req, KCM_OP_REMOVE_CRED, cache); +- k5_buf_add_uint32_be(&req.reqbuf, flags); ++ k5_buf_add_uint32_be(&req.reqbuf, map_tcflags(flags)); + k5_marshal_mcred(&req.reqbuf, mcred); + ret = cache_call(context, cache, &req); + kcmreq_free(&req); diff --git a/root/ppg/common/deps/krb5/rpm/Fix-KCM-retrieval-support-for-sssd.patch b/root/ppg/common/deps/krb5/rpm/Fix-KCM-retrieval-support-for-sssd.patch new file mode 100644 index 00000000..506f0396 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Fix-KCM-retrieval-support-for-sssd.patch @@ -0,0 +1,64 @@ +From 0bfe0b2bc0a8ee0e9a8cee26528030c16d4fd15f Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Tue, 11 May 2021 14:04:07 -0400 +Subject: [PATCH] Fix KCM retrieval support for sssd + +Commit 795ebba8c039be172ab93cd41105c73ffdba0fdb added a retrieval +handler using KCM_OP_RETRIEVE, falling back on the same error codes as +the previous KCM_OP_GET_CRED_LIST support. But sssd (as of 2.4) +returns KRB5_CC_NOSUPP instead of KRB5_CC_IO if it recognizes an +opcode but does not implement it. Add a helper function to recognize +all known unsupported-opcode error codes, and use it in kcm_retrieve() +and kcm_start_seq_get(). + +ticket: 8997 +(cherry picked from commit da103e36e13f3c846bcddbe38dd518a21e5260a0) +(cherry picked from commit a5b2cff51808cd86fe8195e7ac074ecd25c3344d) +(cherry picked from commit 6a00fd149edd017ece894566771e2e9d4ba089f4) +--- + src/lib/krb5/ccache/cc_kcm.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +diff --git a/src/lib/krb5/ccache/cc_kcm.c b/src/lib/krb5/ccache/cc_kcm.c +index b600c6f15..6a36cfdce 100644 +--- a/src/lib/krb5/ccache/cc_kcm.c ++++ b/src/lib/krb5/ccache/cc_kcm.c +@@ -144,6 +144,20 @@ map_tcflags(krb5_flags mitflags) + return heimflags; + } + ++/* ++ * Return true if code could indicate an unsupported operation. Heimdal's KCM ++ * returns KRB5_FCC_INTERNAL. sssd's KCM daemon (as of sssd 2.4) returns ++ * KRB5_CC_NO_SUPP if it recognizes the operation but does not implement it, ++ * and KRB5_CC_IO if it doesn't recognize the operation (which is unfortunate ++ * since it could also indicate a communication failure). ++ */ ++static krb5_boolean ++unsupported_op_error(krb5_error_code code) ++{ ++ return code == KRB5_FCC_INTERNAL || code == KRB5_CC_IO || ++ code == KRB5_CC_NOSUPP; ++} ++ + /* Begin a request for the given opcode. If cache is non-null, supply the + * cache name as a request parameter. */ + static void +@@ -841,7 +855,7 @@ kcm_retrieve(krb5_context context, krb5_ccache cache, krb5_flags flags, + ret = cache_call(context, cache, &req); + + /* Fall back to iteration if the server does not support retrieval. */ +- if (ret == KRB5_FCC_INTERNAL || ret == KRB5_CC_IO) { ++ if (unsupported_op_error(ret)) { + ret = k5_cc_retrieve_cred_default(context, cache, flags, mcred, + cred_out); + goto cleanup; +@@ -922,7 +936,7 @@ kcm_start_seq_get(krb5_context context, krb5_ccache cache, + ret = kcmreq_get_cred_list(&req, &creds); + if (ret) + goto cleanup; +- } else if (ret == KRB5_FCC_INTERNAL || ret == KRB5_CC_IO) { ++ } else if (unsupported_op_error(ret)) { + /* Fall back to GET_CRED_UUID_LIST. */ + kcmreq_free(&req); + kcmreq_init(&req, KCM_OP_GET_CRED_UUID_LIST, cache); diff --git a/root/ppg/common/deps/krb5/rpm/Fix-KDC-null-deref-on-TGS-inner-body-null-server.patch b/root/ppg/common/deps/krb5/rpm/Fix-KDC-null-deref-on-TGS-inner-body-null-server.patch new file mode 100644 index 00000000..e756c950 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Fix-KDC-null-deref-on-TGS-inner-body-null-server.patch @@ -0,0 +1,47 @@ +From 0a8dfc380fe3b210662ba1b1d452fcec2f84841b Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Tue, 3 Aug 2021 01:15:27 -0400 +Subject: [PATCH] Fix KDC null deref on TGS inner body null server + +After the KDC decodes a FAST inner body, it does not check for a null +server. Prior to commit 39548a5b17bbda9eeb63625a201cfd19b9de1c5b this +would typically result in an error from krb5_unparse_name(), but with +the addition of get_local_tgt() it results in a null dereference. Add +a null check. + +Reported by Joseph Sutton of Catalyst. + +CVE-2021-37750: + +In MIT krb5 releases 1.14 and later, an authenticated attacker can +cause a null dereference in the KDC by sending a FAST TGS request with +no server field. + +ticket: 9008 (new) +tags: pullup +target_version: 1.19-next +target_version: 1.18-next + +(cherry picked from commit d775c95af7606a51bf79547a94fa52ddd1cb7f49) +(cherry picked from commit bb8fa495d00ccd931eec87a01b8920636cf7903e) +(cherry picked from commit dfe383f8251d0edc7e5e08ec5e4fdd9b7f902b2a) +--- + src/kdc/do_tgs_req.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c +index 463a9c0dd..7c596a111 100644 +--- a/src/kdc/do_tgs_req.c ++++ b/src/kdc/do_tgs_req.c +@@ -208,6 +208,11 @@ process_tgs_req(krb5_kdc_req *request, krb5_data *pkt, + status = "FIND_FAST"; + goto cleanup; + } ++ if (sprinc == NULL) { ++ status = "NULL_SERVER"; ++ errcode = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; ++ goto cleanup; ++ } + + errcode = get_local_tgt(kdc_context, &sprinc->realm, header_server, + &local_tgt, &local_tgt_storage, &local_tgt_key); diff --git a/root/ppg/common/deps/krb5/rpm/Fix-KDC-null-deref-on-bad-encrypted-challenge.patch b/root/ppg/common/deps/krb5/rpm/Fix-KDC-null-deref-on-bad-encrypted-challenge.patch new file mode 100644 index 00000000..6929363a --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Fix-KDC-null-deref-on-bad-encrypted-challenge.patch @@ -0,0 +1,113 @@ +From 4e8579f0a41b66ed8029f21a52082e1c27ab3996 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 7 Jul 2021 11:47:44 +1200 +Subject: [PATCH] Fix KDC null deref on bad encrypted challenge + +The function ec_verify() in src/kdc/kdc_preauth_ec.c contains a check +to avoid further processing if the armor key is NULL. However, this +check is bypassed by a call to k5memdup0() which overwrites retval +with 0 if the allocation succeeds. If the armor key is NULL, a call +to krb5_c_fx_cf2_simple() will then dereference it, resulting in a +crash. Add a check before the k5memdup0() call to avoid overwriting +retval. + +CVE-2021-36222: + +In MIT krb5 releases 1.16 and later, an unauthenticated attacker can +cause a null dereference in the KDC by sending a request containing a +PA-ENCRYPTED-CHALLENGE padata element without using FAST. + +[ghudson@mit.edu: trimmed patch; added test case; edited commit +message] + +(cherry picked from commit fc98f520caefff2e5ee9a0026fdf5109944b3562) + +ticket: 9007 +version_fixed: 1.18.4 + +(cherry picked from commit c4a406095b3ea4a67ae5b8ea586cbe9abdbae76f) +--- + src/kdc/kdc_preauth_ec.c | 3 ++- + src/tests/Makefile.in | 1 + + src/tests/t_cve-2021-36222.py | 46 +++++++++++++++++++++++++++++++++++ + 3 files changed, 49 insertions(+), 1 deletion(-) + create mode 100644 src/tests/t_cve-2021-36222.py + +diff --git a/src/kdc/kdc_preauth_ec.c b/src/kdc/kdc_preauth_ec.c +index 7e636b3f9..43a9902cc 100644 +--- a/src/kdc/kdc_preauth_ec.c ++++ b/src/kdc/kdc_preauth_ec.c +@@ -87,7 +87,8 @@ ec_verify(krb5_context context, krb5_data *req_pkt, krb5_kdc_req *request, + } + + /* Check for a configured FAST ec auth indicator. */ +- realmstr = k5memdup0(realm.data, realm.length, &retval); ++ if (retval == 0) ++ realmstr = k5memdup0(realm.data, realm.length, &retval); + if (realmstr != NULL) + retval = profile_get_string(context->profile, KRB5_CONF_REALMS, + realmstr, +diff --git a/src/tests/Makefile.in b/src/tests/Makefile.in +index 3f88f1713..0ffbebf56 100644 +--- a/src/tests/Makefile.in ++++ b/src/tests/Makefile.in +@@ -158,6 +158,7 @@ check-pytests: unlockiter s4u2self + $(RUNPYTEST) $(srcdir)/t_cve-2012-1015.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_cve-2013-1416.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_cve-2013-1417.py $(PYTESTFLAGS) ++ $(RUNPYTEST) $(srcdir)/t_cve-2021-36222.py $(PYTESTFLAGS) + $(RM) au.log + $(RUNPYTEST) $(srcdir)/t_audit.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/jsonwalker.py -d $(srcdir)/au_dict.json \ +diff --git a/src/tests/t_cve-2021-36222.py b/src/tests/t_cve-2021-36222.py +new file mode 100644 +index 000000000..57e04993b +--- /dev/null ++++ b/src/tests/t_cve-2021-36222.py +@@ -0,0 +1,46 @@ ++import socket ++from k5test import * ++ ++realm = K5Realm() ++ ++# CVE-2021-36222 KDC null dereference on encrypted challenge preauth ++# without FAST ++ ++s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) ++a = (hostname, realm.portbase) ++ ++m = ('6A81A0' '30819D' # [APPLICATION 10] SEQUENCE ++ 'A103' '0201' '05' # [1] pvno = 5 ++ 'A203' '0201' '0A' # [2] msg-type = 10 ++ 'A30E' '300C' # [3] padata = SEQUENCE OF ++ '300A' # SEQUENCE ++ 'A104' '0202' '008A' # [1] padata-type = PA-ENCRYPTED-CHALLENGE ++ 'A202' '0400' # [2] padata-value = "" ++ 'A48180' '307E' # [4] req-body = SEQUENCE ++ 'A007' '0305' '0000000000' # [0] kdc-options = 0 ++ 'A120' '301E' # [1] cname = SEQUENCE ++ 'A003' '0201' '01' # [0] name-type = NT-PRINCIPAL ++ 'A117' '3015' # [1] name-string = SEQUENCE-OF ++ '1B06' '6B7262746774' # krbtgt ++ '1B0B' '4B5242544553542E434F4D' ++ # KRBTEST.COM ++ 'A20D' '1B0B' '4B5242544553542E434F4D' ++ # [2] realm = KRBTEST.COM ++ 'A320' '301E' # [3] sname = SEQUENCE ++ 'A003' '0201' '01' # [0] name-type = NT-PRINCIPAL ++ 'A117' '3015' # [1] name-string = SEQUENCE-OF ++ '1B06' '6B7262746774' # krbtgt ++ '1B0B' '4B5242544553542E434F4D' ++ # KRBTEST.COM ++ 'A511' '180F' '31393934303631303036303331375A' ++ # [5] till = 19940610060317Z ++ 'A703' '0201' '00' # [7] nonce = 0 ++ 'A808' '3006' # [8] etype = SEQUENCE OF ++ '020112' '020111') # aes256-cts aes128-cts ++ ++s.sendto(bytes.fromhex(m), a) ++ ++# Make sure kinit still works. ++realm.kinit(realm.user_princ, password('user')) ++ ++success('CVE-2021-36222 regression test') diff --git a/root/ppg/common/deps/krb5/rpm/Fix-defcred-leak-in-krb5-gss_inquire_cred.patch b/root/ppg/common/deps/krb5/rpm/Fix-defcred-leak-in-krb5-gss_inquire_cred.patch new file mode 100644 index 00000000..f9e54037 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Fix-defcred-leak-in-krb5-gss_inquire_cred.patch @@ -0,0 +1,45 @@ +From 058dfbaed97c8e09ac4f3f7a1655b64ab3cf0144 Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Wed, 21 Jul 2021 13:44:30 -0400 +Subject: [PATCH] Fix defcred leak in krb5 gss_inquire_cred() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Commit 1cd2821c19b2b95e39d5fc2f451a035585a40fa5 altered the memory +management of krb5_gss_inquire_cred(), introducing defcred to act as +an owner pointer when the function must acquire a default credential. +The commit neglected to update the code to release the default cred +along the successful path. The old code does not trigger because +cred_handle is now reassigned, so the default credential is leaked. + +Reported by Pavel Březina. + +(a minimal alternative to commit 593e16448e1af23eef74689afe06a7bcc86e79c7) + +ticket: 9016 +version_fixed: 1.18.4 + +(cherry picked from commit b92be484630b38e26f5ee4bd67973fbd7627009c) +--- + src/lib/gssapi/krb5/inq_cred.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/src/lib/gssapi/krb5/inq_cred.c b/src/lib/gssapi/krb5/inq_cred.c +index a8f2541102..cd8384d08c 100644 +--- a/src/lib/gssapi/krb5/inq_cred.c ++++ b/src/lib/gssapi/krb5/inq_cred.c +@@ -197,9 +197,7 @@ krb5_gss_inquire_cred(minor_status, cred_handle, name, lifetime_ret, + mechs = GSS_C_NO_OID_SET; + } + +- if (cred_handle == GSS_C_NO_CREDENTIAL) +- krb5_gss_release_cred(minor_status, (gss_cred_id_t *)&cred); +- ++ krb5_gss_release_cred(minor_status, &defcred); + krb5_free_context(context); + *minor_status = 0; + return((lifetime == 0)?GSS_S_CREDENTIALS_EXPIRED:GSS_S_COMPLETE); +-- +2.44.0 + diff --git a/root/ppg/common/deps/krb5/rpm/Fix-integer-overflows-in-PAC-parsing.patch b/root/ppg/common/deps/krb5/rpm/Fix-integer-overflows-in-PAC-parsing.patch new file mode 100644 index 00000000..df97b8dc --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Fix-integer-overflows-in-PAC-parsing.patch @@ -0,0 +1,106 @@ +From d2477aa606ad590ca4097941bb6c2e1955b2a8c8 Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Mon, 17 Oct 2022 20:25:11 -0400 +Subject: [PATCH] Fix integer overflows in PAC parsing + +In krb5_parse_pac(), check for buffer counts large enough to threaten +integer overflow in the header length and memory length calculations. +Avoid potential integer overflows when checking the length of each +buffer. + +CVE-2022-42898: + +In MIT krb5 releases 1.8 and later, an authenticated attacker may be +able to cause a KDC or kadmind process to crash by reading beyond the +bounds of allocated memory, creating a denial of service. A +privileged attacker may similarly be able to cause a Kerberos or GSS +application service to crash. On 32-bit platforms, an attacker can +also cause insufficient memory to be allocated for the result, +potentially leading to remote code execution in a KDC, kadmind, or GSS +or Kerberos application server process. An attacker with the +privileges of a cross-realm KDC may be able to extract secrets from +the KDC process's memory by having them copied into the PAC of a new +ticket. + +ticket: 9074 (new) +tags: pullup +target_version: 1.20-next +target_version: 1.19-next +--- + src/lib/krb5/krb/pac.c | 9 +++++++-- + src/lib/krb5/krb/t_pac.c | 18 ++++++++++++++++++ + 2 files changed, 25 insertions(+), 2 deletions(-) + +diff --git a/src/lib/krb5/krb/pac.c b/src/lib/krb5/krb/pac.c +index 950beda657..1b9ef12276 100644 +--- a/src/lib/krb5/krb/pac.c ++++ b/src/lib/krb5/krb/pac.c +@@ -27,6 +27,8 @@ + #include "k5-int.h" + #include "authdata.h" + ++#define MAX_BUFFERS 4096 ++ + /* draft-brezak-win2k-krb-authz-00 */ + + /* +@@ -316,6 +318,9 @@ krb5_pac_parse(krb5_context context, + if (version != 0) + return EINVAL; + ++ if (cbuffers < 1 || cbuffers > MAX_BUFFERS) ++ return ERANGE; ++ + header_len = PACTYPE_LENGTH + (cbuffers * PAC_INFO_BUFFER_LENGTH); + if (len < header_len) + return ERANGE; +@@ -348,8 +353,8 @@ krb5_pac_parse(krb5_context context, + krb5_pac_free(context, pac); + return EINVAL; + } +- if (buffer->Offset < header_len || +- buffer->Offset + buffer->cbBufferSize > len) { ++ if (buffer->Offset < header_len || buffer->Offset > len || ++ buffer->cbBufferSize > len - buffer->Offset) { + krb5_pac_free(context, pac); + return ERANGE; + } +diff --git a/src/lib/krb5/krb/t_pac.c b/src/lib/krb5/krb/t_pac.c +index ee47152ee4..ccd165380d 100644 +--- a/src/lib/krb5/krb/t_pac.c ++++ b/src/lib/krb5/krb/t_pac.c +@@ -431,6 +431,16 @@ static const unsigned char s4u_pac_ent_xrealm[] = { + 0x8a, 0x81, 0x9c, 0x9c, 0x00, 0x00, 0x00, 0x00 + }; + ++static const unsigned char fuzz1[] = { ++ 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, ++ 0x06, 0xff, 0xff, 0xff, 0x00, 0x00, 0xf5 ++}; ++ ++static const unsigned char fuzz2[] = { ++ 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, ++ 0x20, 0x20 ++}; ++ + static const char *s4u_principal = "w2k8u@ACME.COM"; + static const char *s4u_enterprise = "w2k8u@abc@ACME.COM"; + +@@ -646,6 +656,14 @@ main(int argc, char **argv) + krb5_free_principal(context, sep); + } + ++ /* Check problematic PACs found by fuzzing. */ ++ ret = krb5_pac_parse(context, fuzz1, sizeof(fuzz1), &pac); ++ if (!ret) ++ err(context, ret, "krb5_pac_parse should have failed"); ++ ret = krb5_pac_parse(context, fuzz2, sizeof(fuzz2), &pac); ++ if (!ret) ++ err(context, ret, "krb5_pac_parse should have failed"); ++ + /* + * Test empty free + */ +-- +2.37.3 + diff --git a/root/ppg/common/deps/krb5/rpm/Fix-leak-in-KERB_AP_OPTIONS_CBT-server-support.patch b/root/ppg/common/deps/krb5/rpm/Fix-leak-in-KERB_AP_OPTIONS_CBT-server-support.patch new file mode 100644 index 00000000..ab45a2ea --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Fix-leak-in-KERB_AP_OPTIONS_CBT-server-support.patch @@ -0,0 +1,60 @@ +From 7a87189f7bdabc144e22d4caa6a0785a06416d8f Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Fri, 24 Jul 2020 16:05:24 -0400 +Subject: [PATCH] Fix leak in KERB_AP_OPTIONS_CBT server support + +In check_cbt(), use a local variable to hold the retrieved authdata +list, and free it before returning. + +ticket: 8900 +(cherry picked from commit bf2ddff13c178e0c291f8fb382b040080d159e4f) +(cherry picked from commit 044e2209586fd1935d9a637df76d52f48c4f3e6e) +--- + src/lib/gssapi/krb5/accept_sec_context.c | 23 +++++++++++++---------- + 1 file changed, 13 insertions(+), 10 deletions(-) + +diff --git a/src/lib/gssapi/krb5/accept_sec_context.c b/src/lib/gssapi/krb5/accept_sec_context.c +index 175a24c4e..3d5b84b15 100644 +--- a/src/lib/gssapi/krb5/accept_sec_context.c ++++ b/src/lib/gssapi/krb5/accept_sec_context.c +@@ -433,27 +433,30 @@ static const uint8_t null_cb[CB_MD5_LEN]; + /* Look for AP_OPTIONS in authdata. If present and the options include + * KERB_AP_OPTIONS_CBT, set *cbt_out to true. */ + static krb5_error_code +-check_cbt(krb5_context context, krb5_authdata **authdata, ++check_cbt(krb5_context context, krb5_authdata *const *authdata, + krb5_boolean *cbt_out) + { + krb5_error_code code; ++ krb5_authdata **ad; + uint32_t ad_ap_options; + const uint32_t KERB_AP_OPTIONS_CBT = 0x4000; + + *cbt_out = FALSE; + + code = krb5_find_authdata(context, NULL, authdata, +- KRB5_AUTHDATA_AP_OPTIONS, &authdata); +- if (code || authdata == NULL) ++ KRB5_AUTHDATA_AP_OPTIONS, &ad); ++ if (code || ad == NULL) + return code; +- if (authdata[1] != NULL || authdata[0]->length != 4) +- return KRB5KRB_AP_ERR_MSG_TYPE; ++ if (ad[1] != NULL || ad[0]->length != 4) { ++ code = KRB5KRB_AP_ERR_MSG_TYPE; ++ } else { ++ ad_ap_options = load_32_le(ad[0]->contents); ++ if (ad_ap_options & KERB_AP_OPTIONS_CBT) ++ *cbt_out = TRUE; ++ } + +- ad_ap_options = load_32_le(authdata[0]->contents); +- if (ad_ap_options & KERB_AP_OPTIONS_CBT) +- *cbt_out = TRUE; +- +- return 0; ++ krb5_free_authdata(context, ad); ++ return code; + } + + /* diff --git a/root/ppg/common/deps/krb5/rpm/Fix-two-NegoEx-parsing-vulnerabilities.patch b/root/ppg/common/deps/krb5/rpm/Fix-two-NegoEx-parsing-vulnerabilities.patch new file mode 100644 index 00000000..a2307380 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Fix-two-NegoEx-parsing-vulnerabilities.patch @@ -0,0 +1,65 @@ +From 317d6cc21d12148bbb1366b6d143c1913bff4d80 Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Wed, 8 Apr 2026 17:57:59 -0400 +Subject: [PATCH] Fix two NegoEx parsing vulnerabilities + +In parse_nego_message(), check the result of the second call to +vector_base() before dereferencing it. In parse_message(), check for +a short header_len to prevent an integer underflow when calculating +the remaining message length. + +Reported by Cem Onat Karagun. + +CVE-2026-40355: + +In MIT krb5 release 1.18 and later, if an application calls +gss_accept_sec_context() on a system with a NegoEx mechanism +registered in /etc/gss/mech, an unauthenticated remote attacker can +trigger a null pointer dereference, causing the process to terminate. + +CVE-2026-40356: + +In MIT krb5 release 1.18 and later, if an application calls +gss_accept_sec_context() on a system with a NegoEx mechanism +registered in /etc/gss/mech, an unauthenticated remote attacker can +trigger a read overrun of up to 52 bytes, possibly causing the process +to terminate. Exfiltration of the bytes read does not appear +possible. + +ticket: 9205 (new) +tags: pullup +target_version: 1.22-next + +(cherry picked from commit 2e75f0d9362fb979f5fc92829431a590a130929f) +--- + src/lib/gssapi/spnego/negoex_util.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/src/lib/gssapi/spnego/negoex_util.c b/src/lib/gssapi/spnego/negoex_util.c +index 99580fd79c..632f719ba8 100644 +--- a/src/lib/gssapi/spnego/negoex_util.c ++++ b/src/lib/gssapi/spnego/negoex_util.c +@@ -253,6 +253,10 @@ parse_nego_message(OM_uint32 *minor, struct k5input *in, + offset = k5_input_get_uint32_le(in); + count = k5_input_get_uint16_le(in); + p = vector_base(offset, count, EXTENSION_LENGTH, msg_base, msg_len); ++ if (p == NULL) { ++ *minor = ERR_NEGOEX_INVALID_MESSAGE_SIZE; ++ return GSS_S_DEFECTIVE_TOKEN; ++ } + for (i = 0; i < count; i++) { + extension_type = load_32_le(p + i * EXTENSION_LENGTH); + if (extension_type & EXTENSION_FLAG_CRITICAL) { +@@ -391,7 +395,8 @@ parse_message(OM_uint32 *minor, spnego_gss_ctx_id_t ctx, struct k5input *in, + msg_len = k5_input_get_uint32_le(in); + conv_id = k5_input_get_bytes(in, GUID_LENGTH); + +- if (in->status || msg_len > token_remaining || header_len > msg_len) { ++ if (in->status || msg_len > token_remaining || ++ header_len < (size_t)(in->ptr - msg_base) || header_len > msg_len) { + *minor = ERR_NEGOEX_INVALID_MESSAGE_SIZE; + return GSS_S_DEFECTIVE_TOKEN; + } +-- +2.53.0 + diff --git a/root/ppg/common/deps/krb5/rpm/Fix-two-unlikely-memory-leaks.patch b/root/ppg/common/deps/krb5/rpm/Fix-two-unlikely-memory-leaks.patch new file mode 100644 index 00000000..86bd5a96 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Fix-two-unlikely-memory-leaks.patch @@ -0,0 +1,205 @@ +From efb3acd20cbe6330439635a9f297b9dae8a0a5d3 Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Tue, 5 Mar 2024 19:53:07 -0500 +Subject: [PATCH] Fix two unlikely memory leaks + +In gss_krb5int_make_seal_token_v3(), one of the bounds checks (which +could probably never be triggered) leaks plain.data. Fix this leak +and use current practices for cleanup throughout the function. + +In xmt_rmtcallres() (unused within the tree and likely elsewhere), +store port_ptr into crp->port_ptr as soon as it is allocated; +otherwise it could leak if the subsequent xdr_u_int32() operation +fails. + +(cherry picked from commit c5f9c816107f70139de11b38aa02db2f1774ee0d) +--- + src/lib/gssapi/krb5/k5sealv3.c | 56 +++++++++++++++------------------- + src/lib/rpc/pmap_rmt.c | 9 +++--- + 2 files changed, 29 insertions(+), 36 deletions(-) + +diff --git a/src/lib/gssapi/krb5/k5sealv3.c b/src/lib/gssapi/krb5/k5sealv3.c +index 3b4f8cb837..e881eee835 100644 +--- a/src/lib/gssapi/krb5/k5sealv3.c ++++ b/src/lib/gssapi/krb5/k5sealv3.c +@@ -65,7 +65,7 @@ gss_krb5int_make_seal_token_v3 (krb5_context context, + int conf_req_flag, int toktype) + { + size_t bufsize = 16; +- unsigned char *outbuf = 0; ++ unsigned char *outbuf = NULL; + krb5_error_code err; + int key_usage; + unsigned char acceptor_flag; +@@ -75,9 +75,13 @@ gss_krb5int_make_seal_token_v3 (krb5_context context, + #endif + size_t ec; + unsigned short tok_id; +- krb5_checksum sum; ++ krb5_checksum sum = { 0 }; + krb5_key key; + krb5_cksumtype cksumtype; ++ krb5_data plain = empty_data(); ++ ++ token->value = NULL; ++ token->length = 0; + + acceptor_flag = ctx->initiate ? 0 : FLAG_SENDER_IS_ACCEPTOR; + key_usage = (toktype == KG_TOK_WRAP_MSG +@@ -107,14 +111,15 @@ gss_krb5int_make_seal_token_v3 (krb5_context context, + #endif + + if (toktype == KG_TOK_WRAP_MSG && conf_req_flag) { +- krb5_data plain; + krb5_enc_data cipher; + size_t ec_max; + size_t encrypt_size; + + /* 300: Adds some slop. */ +- if (SIZE_MAX - 300 < message->length) +- return ENOMEM; ++ if (SIZE_MAX - 300 < message->length) { ++ err = ENOMEM; ++ goto cleanup; ++ } + ec_max = SIZE_MAX - message->length - 300; + if (ec_max > 0xffff) + ec_max = 0xffff; +@@ -126,20 +131,20 @@ gss_krb5int_make_seal_token_v3 (krb5_context context, + #endif + err = alloc_data(&plain, message->length + 16 + ec); + if (err) +- return err; ++ goto cleanup; + + /* Get size of ciphertext. */ + encrypt_size = krb5_encrypt_size(plain.length, key->keyblock.enctype); + if (encrypt_size > SIZE_MAX / 2) { + err = ENOMEM; +- goto error; ++ goto cleanup; + } + bufsize = 16 + encrypt_size; + /* Allocate space for header plus encrypted data. */ + outbuf = gssalloc_malloc(bufsize); + if (outbuf == NULL) { +- free(plain.data); +- return ENOMEM; ++ err = ENOMEM; ++ goto cleanup; + } + + /* TOK_ID */ +@@ -164,11 +169,8 @@ gss_krb5int_make_seal_token_v3 (krb5_context context, + cipher.ciphertext.length = bufsize - 16; + cipher.enctype = key->keyblock.enctype; + err = krb5_k_encrypt(context, key, key_usage, 0, &plain, &cipher); +- zap(plain.data, plain.length); +- free(plain.data); +- plain.data = 0; + if (err) +- goto error; ++ goto cleanup; + + /* Now that we know we're returning a valid token.... */ + ctx->seq_send++; +@@ -181,7 +183,6 @@ gss_krb5int_make_seal_token_v3 (krb5_context context, + /* If the rotate fails, don't worry about it. */ + #endif + } else if (toktype == KG_TOK_WRAP_MSG && !conf_req_flag) { +- krb5_data plain; + size_t cksumsize; + + /* Here, message is the application-supplied data; message2 is +@@ -193,21 +194,19 @@ gss_krb5int_make_seal_token_v3 (krb5_context context, + wrap_with_checksum: + err = alloc_data(&plain, message->length + 16); + if (err) +- return err; ++ goto cleanup; + + err = krb5_c_checksum_length(context, cksumtype, &cksumsize); + if (err) +- goto error; ++ goto cleanup; + + assert(cksumsize <= 0xffff); + + bufsize = 16 + message2->length + cksumsize; + outbuf = gssalloc_malloc(bufsize); + if (outbuf == NULL) { +- free(plain.data); +- plain.data = 0; + err = ENOMEM; +- goto error; ++ goto cleanup; + } + + /* TOK_ID */ +@@ -239,23 +238,15 @@ gss_krb5int_make_seal_token_v3 (krb5_context context, + if (message2->length) + memcpy(outbuf + 16, message2->value, message2->length); + +- sum.contents = outbuf + 16 + message2->length; +- sum.length = cksumsize; +- + err = krb5_k_make_checksum(context, cksumtype, key, + key_usage, &plain, &sum); +- zap(plain.data, plain.length); +- free(plain.data); +- plain.data = 0; + if (err) { + zap(outbuf,bufsize); +- goto error; ++ goto cleanup; + } + if (sum.length != cksumsize) + abort(); + memcpy(outbuf + 16 + message2->length, sum.contents, cksumsize); +- krb5_free_checksum_contents(context, &sum); +- sum.contents = 0; + /* Now that we know we're actually generating the token... */ + ctx->seq_send++; + +@@ -285,12 +276,13 @@ gss_krb5int_make_seal_token_v3 (krb5_context context, + + token->value = outbuf; + token->length = bufsize; +- return 0; ++ outbuf = NULL; ++ err = 0; + +-error: ++cleanup: ++ krb5_free_checksum_contents(context, &sum); ++ zapfree(plain.data, plain.length); + gssalloc_free(outbuf); +- token->value = NULL; +- token->length = 0; + return err; + } + +diff --git a/src/lib/rpc/pmap_rmt.c b/src/lib/rpc/pmap_rmt.c +index 8c7e30c21a..0748af34a7 100644 +--- a/src/lib/rpc/pmap_rmt.c ++++ b/src/lib/rpc/pmap_rmt.c +@@ -160,11 +160,12 @@ xdr_rmtcallres( + caddr_t port_ptr; + + port_ptr = (caddr_t)(void *)crp->port_ptr; +- if (xdr_reference(xdrs, &port_ptr, sizeof (uint32_t), +- xdr_u_int32) && xdr_u_int32(xdrs, &crp->resultslen)) { +- crp->port_ptr = (uint32_t *)(void *)port_ptr; ++ if (!xdr_reference(xdrs, &port_ptr, sizeof (uint32_t), ++ (xdrproc_t)xdr_u_int32)) ++ return (FALSE); ++ crp->port_ptr = (uint32_t *)(void *)port_ptr; ++ if (xdr_u_int32(xdrs, &crp->resultslen)) + return ((*(crp->xdr_results))(xdrs, crp->results_ptr)); +- } + return (FALSE); + } + +-- +2.44.0 + diff --git a/root/ppg/common/deps/krb5/rpm/Fix-typo-in-in-in-the-ksu-man-page.patch b/root/ppg/common/deps/krb5/rpm/Fix-typo-in-in-in-the-ksu-man-page.patch new file mode 100644 index 00000000..29aee7da --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Fix-typo-in-in-in-the-ksu-man-page.patch @@ -0,0 +1,38 @@ +From 5a0833a3f3b1c44edd08425d98f682b96ad7a01e Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Thu, 14 May 2020 15:01:18 -0400 +Subject: [PATCH] Fix typo ("in in") in the ksu man page + +(cherry picked from commit 1011841acdc1020f308ef4f569c6622f279d8c3f) +(cherry picked from commit 8de669742ae4190542741f0dc61119a6a0dad666) +--- + doc/user/user_commands/ksu.rst | 2 +- + src/man/ksu.man | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/doc/user/user_commands/ksu.rst b/doc/user/user_commands/ksu.rst +index 8d6c7ef79..933738229 100644 +--- a/doc/user/user_commands/ksu.rst ++++ b/doc/user/user_commands/ksu.rst +@@ -155,7 +155,7 @@ wrong password is typed in, ksu fails. + .. note:: + + During authentication, only the tickets that could be +- obtained without providing a password are cached in in the ++ obtained without providing a password are cached in the + source cache. + + +diff --git a/src/man/ksu.man b/src/man/ksu.man +index 81e34815d..8d4c6a359 100644 +--- a/src/man/ksu.man ++++ b/src/man/ksu.man +@@ -176,7 +176,7 @@ wrong password is typed in, ksu fails. + .INDENT 0.0 + .INDENT 3.5 + During authentication, only the tickets that could be +-obtained without providing a password are cached in in the ++obtained without providing a password are cached in the + source cache. + .UNINDENT + .UNINDENT diff --git a/root/ppg/common/deps/krb5/rpm/Fix-uninitialized-pointer-dereference-in-libkrad.patch b/root/ppg/common/deps/krb5/rpm/Fix-uninitialized-pointer-dereference-in-libkrad.patch new file mode 100644 index 00000000..392d98c6 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Fix-uninitialized-pointer-dereference-in-libkrad.patch @@ -0,0 +1,44 @@ +From f143a0ce9eb923a94a5c20234a8cb85205e8ff9c Mon Sep 17 00:00:00 2001 +From: Julien Rische +Date: Wed, 21 Jan 2026 11:31:39 +0100 +Subject: [PATCH] Fix uninitialized pointer dereference in libkrad + +Commit 871125fea8ce0370a972bf65f7d1de63f619b06c changed +krad_packet_decode_request() to use a local variable "req" to hold the +decoded packet until it is verified, instead of immediately storing +into the caller's *reqpkt. The code to check for duplicate packets +erroneously continues to use *reqpkt, causing a read dereference of +whatever was in *reqpkt on entry to the function (typically null or an +uninitialized value). Fix the code to use req instead of *reqpkt. + +This bug does not affect the KDC (which only uses libkrad as a +client), but can crash external software using libkrad as a server if +it ever processes more than one packet at a time. + +[ghudson@mit.edu: edited commit message] + +ticket: 9193 (new) +tags: pullup +target_version: 1.22-next + +(cherry picked from commit f74a1b3fcde44cfa0d487973fd47a943cda49dc8) +--- + src/lib/krad/packet.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/lib/krad/packet.c b/src/lib/krad/packet.c +index b1a31d78cc..10362cf9ed 100644 +--- a/src/lib/krad/packet.c ++++ b/src/lib/krad/packet.c +@@ -575,7 +575,7 @@ krad_packet_decode_request(krb5_context ctx, const char *secret, + + if (cb != NULL) { + for (tmp = (*cb)(data, FALSE); tmp != NULL; tmp = (*cb)(data, FALSE)) { +- if (pkt_id_get(*reqpkt) == pkt_id_get(tmp)) ++ if (pkt_id_get(req) == pkt_id_get(tmp)) + break; + } + +-- +2.51.1 + diff --git a/root/ppg/common/deps/krb5/rpm/Fix-vulnerabilities-in-GSS-message-token-handling.patch b/root/ppg/common/deps/krb5/rpm/Fix-vulnerabilities-in-GSS-message-token-handling.patch new file mode 100644 index 00000000..edf77e5b --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Fix-vulnerabilities-in-GSS-message-token-handling.patch @@ -0,0 +1,535 @@ +From c73e8ed9f89fdc709d15656b6431492d43de94ce Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Fri, 14 Jun 2024 10:56:12 -0400 +Subject: [PATCH] Fix vulnerabilities in GSS message token handling + +In gss_krb5int_unseal_token_v3() and gss_krb5int_unseal_v3_iov(), +verify the Extra Count field of CFX wrap tokens against the encrypted +header. Reported by Jacob Champion. + +In gss_krb5int_unseal_token_v3(), check for a decrypted plaintext +length too short to contain the encrypted header and extra count +bytes. Reported by Jacob Champion. + +In kg_unseal_iov_token(), separately track the header IOV length and +complete token length when parsing the token's ASN.1 wrapper. This +fix contains modified versions of functions from k5-der.h and +util_token.c; this duplication will be cleaned up in a future commit. + +CVE-2024-37370: + +In MIT krb5 release 1.3 and later, an attacker can modify the +plaintext Extra Count field of a confidential GSS krb5 wrap token, +causing the unwrapped token to appear truncated to the application. + +CVE-2024-37371: + +In MIT krb5 release 1.3 and later, an attacker can cause invalid +memory reads by sending message tokens with invalid length fields. + +ticket: 9128 (new) +tags: pullup +target_version: 1.21-next + +(cherry picked from commit b0a2f8a5365f2eec3e27d78907de9f9d2c80505a) +--- + src/lib/gssapi/krb5/k5sealv3.c | 5 + + src/lib/gssapi/krb5/k5sealv3iov.c | 3 +- + src/lib/gssapi/krb5/k5unsealiov.c | 80 +++++++++- + src/tests/gssapi/t_invalid.c | 233 +++++++++++++++++++++++++----- + 4 files changed, 275 insertions(+), 46 deletions(-) + +diff --git a/src/lib/gssapi/krb5/k5sealv3.c b/src/lib/gssapi/krb5/k5sealv3.c +index e881eee835..d3210c1107 100644 +--- a/src/lib/gssapi/krb5/k5sealv3.c ++++ b/src/lib/gssapi/krb5/k5sealv3.c +@@ -400,10 +400,15 @@ gss_krb5int_unseal_token_v3(krb5_context *contextptr, + /* Don't use bodysize here! Use the fact that + cipher.ciphertext.length has been adjusted to the + correct length. */ ++ if (plain.length < 16 + ec) { ++ free(plain.data); ++ goto defective; ++ } + althdr = (unsigned char *)plain.data + plain.length - 16; + if (load_16_be(althdr) != KG2_TOK_WRAP_MSG + || althdr[2] != ptr[2] + || althdr[3] != ptr[3] ++ || load_16_be(althdr+4) != ec + || memcmp(althdr+8, ptr+8, 8)) { + free(plain.data); + goto defective; +diff --git a/src/lib/gssapi/krb5/k5sealv3iov.c b/src/lib/gssapi/krb5/k5sealv3iov.c +index 333ee124dd..f8e90c35b4 100644 +--- a/src/lib/gssapi/krb5/k5sealv3iov.c ++++ b/src/lib/gssapi/krb5/k5sealv3iov.c +@@ -402,9 +402,10 @@ gss_krb5int_unseal_v3_iov(krb5_context context, + if (load_16_be(althdr) != KG2_TOK_WRAP_MSG + || althdr[2] != ptr[2] + || althdr[3] != ptr[3] ++ || load_16_be(althdr + 4) != ec + || memcmp(althdr + 8, ptr + 8, 8) != 0) { + *minor_status = 0; +- return GSS_S_BAD_SIG; ++ return GSS_S_DEFECTIVE_TOKEN; + } + } else { + /* Verify checksum: note EC is checksum size here, not padding */ +diff --git a/src/lib/gssapi/krb5/k5unsealiov.c b/src/lib/gssapi/krb5/k5unsealiov.c +index 3ce2a90ce9..6a6585d9af 100644 +--- a/src/lib/gssapi/krb5/k5unsealiov.c ++++ b/src/lib/gssapi/krb5/k5unsealiov.c +@@ -25,6 +25,7 @@ + */ + + #include "k5-int.h" ++#include "k5-der.h" + #include "gssapiP_krb5.h" + + static OM_uint32 +@@ -247,6 +248,73 @@ cleanup: + return retval; + } + ++/* Similar to k5_der_get_value(), but output an unchecked content length ++ * instead of a k5input containing the contents. */ ++static inline bool ++get_der_tag(struct k5input *in, uint8_t idbyte, size_t *len_out) ++{ ++ uint8_t lenbyte, i; ++ size_t len; ++ ++ /* Do nothing if in is empty or the next byte doesn't match idbyte. */ ++ if (in->status || in->len == 0 || *in->ptr != idbyte) ++ return false; ++ ++ /* Advance past the identifier byte and decode the length. */ ++ (void)k5_input_get_byte(in); ++ lenbyte = k5_input_get_byte(in); ++ if (lenbyte < 128) { ++ len = lenbyte; ++ } else { ++ len = 0; ++ for (i = 0; i < (lenbyte & 0x7F); i++) { ++ if (len > (SIZE_MAX >> 8)) { ++ k5_input_set_status(in, EOVERFLOW); ++ return false; ++ } ++ len = (len << 8) | k5_input_get_byte(in); ++ } ++ } ++ ++ if (in->status) ++ return false; ++ ++ *len_out = len; ++ return true; ++} ++ ++/* ++ * Similar to g_verify_token_header() without toktype or flags, but do not read ++ * more than *header_len bytes of ASN.1 wrapper, and on output set *header_len ++ * to the remaining number of header bytes. Verify the outer DER tag's length ++ * against token_len, which may be larger (but not smaller) than *header_len. ++ */ ++static gss_int32 ++verify_detached_wrapper(const gss_OID_desc *mech, size_t *header_len, ++ uint8_t **header_in, size_t token_len) ++{ ++ struct k5input in, mech_der; ++ gss_OID_desc toid; ++ size_t len; ++ ++ k5_input_init(&in, *header_in, *header_len); ++ ++ if (get_der_tag(&in, 0x60, &len)) { ++ if (len != token_len - (in.ptr - *header_in)) ++ return G_BAD_TOK_HEADER; ++ if (!k5_der_get_value(&in, 0x06, &mech_der)) ++ return G_BAD_TOK_HEADER; ++ toid.elements = (uint8_t *)mech_der.ptr; ++ toid.length = mech_der.len; ++ if (!g_OID_equal(&toid, mech)) ++ return G_WRONG_MECH; ++ } ++ ++ *header_in = (uint8_t *)in.ptr; ++ *header_len = in.len; ++ return 0; ++} ++ + /* + * Caller must provide TOKEN | DATA | PADDING | TRAILER, except + * for DCE in which case it can just provide TOKEN | DATA (must +@@ -267,8 +335,7 @@ kg_unseal_iov_token(OM_uint32 *minor_status, + gss_iov_buffer_t header; + gss_iov_buffer_t padding; + gss_iov_buffer_t trailer; +- size_t input_length; +- unsigned int bodysize; ++ size_t input_length, hlen; + int toktype2; + + header = kg_locate_header_iov(iov, iov_count, toktype); +@@ -298,15 +365,14 @@ kg_unseal_iov_token(OM_uint32 *minor_status, + input_length += trailer->buffer.length; + } + +- code = g_verify_token_header(ctx->mech_used, +- &bodysize, &ptr, -1, +- input_length, 0); ++ hlen = header->buffer.length; ++ code = verify_detached_wrapper(ctx->mech_used, &hlen, &ptr, input_length); + if (code != 0) { + *minor_status = code; + return GSS_S_DEFECTIVE_TOKEN; + } + +- if (bodysize < 2) { ++ if (hlen < 2) { + *minor_status = (OM_uint32)G_BAD_TOK_HEADER; + return GSS_S_DEFECTIVE_TOKEN; + } +@@ -314,7 +380,7 @@ kg_unseal_iov_token(OM_uint32 *minor_status, + toktype2 = load_16_be(ptr); + + ptr += 2; +- bodysize -= 2; ++ hlen -= 2; + + switch (toktype2) { + case KG2_TOK_MIC_MSG: +diff --git a/src/tests/gssapi/t_invalid.c b/src/tests/gssapi/t_invalid.c +index fb8fe55111..8192935099 100644 +--- a/src/tests/gssapi/t_invalid.c ++++ b/src/tests/gssapi/t_invalid.c +@@ -36,31 +36,41 @@ + * + * 1. A pre-CFX wrap or MIC token processed with a CFX-only context causes a + * null pointer dereference. (The token must use SEAL_ALG_NONE or it will +- * be rejected.) ++ * be rejected.) This vulnerability also applies to IOV unwrap. + * +- * 2. A pre-CFX wrap or MIC token with fewer than 24 bytes after the ASN.1 ++ * 2. A CFX wrap token with a different value of EC between the plaintext and ++ * encrypted copies will be erroneously accepted, which allows a message ++ * truncation attack. This vulnerability also applies to IOV unwrap. ++ * ++ * 3. A CFX wrap token with a plaintext length fewer than 16 bytes causes an ++ * access before the beginning of the input buffer, possibly leading to a ++ * crash. ++ * ++ * 4. A CFX wrap token with a plaintext EC value greater than the plaintext ++ * length - 16 causes an integer underflow when computing the result length, ++ * likely causing a crash. ++ * ++ * 5. An IOV unwrap operation will overrun the header buffer if an ASN.1 ++ * wrapper longer than the header buffer is present. ++ * ++ * 6. A pre-CFX wrap or MIC token with fewer than 24 bytes after the ASN.1 + * header causes an input buffer overrun, usually leading to either a segv + * or a GSS_S_DEFECTIVE_TOKEN error due to garbage algorithm, filler, or +- * sequence number values. ++ * sequence number values. This vulnerability also applies to IOV unwrap. + * +- * 3. A pre-CFX wrap token with fewer than 16 + cksumlen bytes after the ASN.1 ++ * 7. A pre-CFX wrap token with fewer than 16 + cksumlen bytes after the ASN.1 + * header causes an integer underflow when computing the ciphertext length, + * leading to an allocation error on 32-bit platforms or a segv on 64-bit + * platforms. A pre-CFX MIC token of this size causes an input buffer + * overrun when comparing the checksum, perhaps leading to a segv. + * +- * 4. A pre-CFX wrap token with fewer than conflen + padlen bytes in the ++ * 8. A pre-CFX wrap token with fewer than conflen + padlen bytes in the + * ciphertext (where padlen is the last byte of the decrypted ciphertext) + * causes an integer underflow when computing the original message length, + * leading to an allocation error. + * +- * 5. In the mechglue, truncated encapsulation in the initial context token can ++ * 9. In the mechglue, truncated encapsulation in the initial context token can + * cause input buffer overruns in gss_accept_sec_context(). +- * +- * Vulnerabilities #1 and #2 also apply to IOV unwrap, although tokens with +- * fewer than 16 bytes after the ASN.1 header will be rejected. +- * Vulnerabilities #2 and #5 can only be robustly detected using a +- * memory-checking environment such as valgrind. + */ + + #include "k5-int.h" +@@ -97,17 +107,25 @@ struct test { + } + }; + +-/* Fake up enough of a CFX GSS context for gss_unwrap, using an AES key. */ ++static void * ++ealloc(size_t len) ++{ ++ void *ptr = calloc(len, 1); ++ ++ if (ptr == NULL) ++ abort(); ++ return ptr; ++} ++ ++/* Fake up enough of a CFX GSS context for gss_unwrap, using an AES key. ++ * The context takes ownership of subkey. */ + static gss_ctx_id_t +-make_fake_cfx_context() ++make_fake_cfx_context(krb5_key subkey) + { + gss_union_ctx_id_t uctx; + krb5_gss_ctx_id_t kgctx; +- krb5_keyblock kb; + +- kgctx = calloc(1, sizeof(*kgctx)); +- if (kgctx == NULL) +- abort(); ++ kgctx = ealloc(sizeof(*kgctx)); + kgctx->established = 1; + kgctx->proto = 1; + if (g_seqstate_init(&kgctx->seqstate, 0, 0, 0, 0) != 0) +@@ -116,15 +134,10 @@ make_fake_cfx_context() + kgctx->sealalg = -1; + kgctx->signalg = -1; + +- kb.enctype = ENCTYPE_AES128_CTS_HMAC_SHA1_96; +- kb.length = 16; +- kb.contents = (unsigned char *)"1234567887654321"; +- if (krb5_k_create_key(NULL, &kb, &kgctx->subkey) != 0) +- abort(); ++ kgctx->subkey = subkey; ++ kgctx->cksumtype = CKSUMTYPE_HMAC_SHA1_96_AES128; + +- uctx = calloc(1, sizeof(*uctx)); +- if (uctx == NULL) +- abort(); ++ uctx = ealloc(sizeof(*uctx)); + uctx->mech_type = &mech_krb5; + uctx->internal_ctx_id = (gss_ctx_id_t)kgctx; + return (gss_ctx_id_t)uctx; +@@ -138,9 +151,7 @@ make_fake_context(const struct test *test) + krb5_gss_ctx_id_t kgctx; + krb5_keyblock kb; + +- kgctx = calloc(1, sizeof(*kgctx)); +- if (kgctx == NULL) +- abort(); ++ kgctx = ealloc(sizeof(*kgctx)); + kgctx->established = 1; + if (g_seqstate_init(&kgctx->seqstate, 0, 0, 0, 0) != 0) + abort(); +@@ -162,9 +173,7 @@ make_fake_context(const struct test *test) + if (krb5_k_create_key(NULL, &kb, &kgctx->enc) != 0) + abort(); + +- uctx = calloc(1, sizeof(*uctx)); +- if (uctx == NULL) +- abort(); ++ uctx = ealloc(sizeof(*uctx)); + uctx->mech_type = &mech_krb5; + uctx->internal_ctx_id = (gss_ctx_id_t)kgctx; + return (gss_ctx_id_t)uctx; +@@ -194,9 +203,7 @@ make_token(unsigned char *token, size_t len, gss_buffer_t out) + + assert(mech_krb5.length == 9); + assert(len + 11 < 128); +- wrapped = malloc(len + 13); +- if (wrapped == NULL) +- abort(); ++ wrapped = ealloc(len + 13); + wrapped[0] = 0x60; + wrapped[1] = len + 11; + wrapped[2] = 0x06; +@@ -207,6 +214,18 @@ make_token(unsigned char *token, size_t len, gss_buffer_t out) + out->value = wrapped; + } + ++/* Create a 16-byte header for a CFX confidential wrap token to be processed by ++ * the fake CFX context. */ ++static void ++write_cfx_header(uint16_t ec, uint8_t *out) ++{ ++ memset(out, 0, 16); ++ store_16_be(KG2_TOK_WRAP_MSG, out); ++ out[2] = FLAG_WRAP_CONFIDENTIAL; ++ out[3] = 0xFF; ++ store_16_be(ec, out + 4); ++} ++ + /* Unwrap a superficially valid RFC 1964 token with a CFX-only context, with + * regular and IOV unwrap. */ + static void +@@ -238,6 +257,134 @@ test_bogus_1964_token(gss_ctx_id_t ctx) + free(in.value); + } + ++static void ++test_cfx_altered_ec(gss_ctx_id_t ctx, krb5_key subkey) ++{ ++ OM_uint32 major, minor; ++ uint8_t tokbuf[128], plainbuf[24]; ++ krb5_data plain; ++ krb5_enc_data cipher; ++ gss_buffer_desc in, out; ++ gss_iov_buffer_desc iov[2]; ++ ++ /* Construct a header with a plaintext EC value of 3. */ ++ write_cfx_header(3, tokbuf); ++ ++ /* Encrypt a plaintext and a copy of the header with the EC value 0. */ ++ memcpy(plainbuf, "truncate", 8); ++ memcpy(plainbuf + 8, tokbuf, 16); ++ store_16_be(0, plainbuf + 12); ++ plain = make_data(plainbuf, 24); ++ cipher.ciphertext.data = (char *)tokbuf + 16; ++ cipher.ciphertext.length = sizeof(tokbuf) - 16; ++ cipher.enctype = subkey->keyblock.enctype; ++ if (krb5_k_encrypt(NULL, subkey, KG_USAGE_INITIATOR_SEAL, NULL, ++ &plain, &cipher) != 0) ++ abort(); ++ ++ /* Verify that the token is rejected by gss_unwrap(). */ ++ in.value = tokbuf; ++ in.length = 16 + cipher.ciphertext.length; ++ major = gss_unwrap(&minor, ctx, &in, &out, NULL, NULL); ++ if (major != GSS_S_DEFECTIVE_TOKEN) ++ abort(); ++ (void)gss_release_buffer(&minor, &out); ++ ++ /* Verify that the token is rejected by gss_unwrap_iov(). */ ++ iov[0].type = GSS_IOV_BUFFER_TYPE_STREAM; ++ iov[0].buffer = in; ++ iov[1].type = GSS_IOV_BUFFER_TYPE_DATA; ++ major = gss_unwrap_iov(&minor, ctx, NULL, NULL, iov, 2); ++ if (major != GSS_S_DEFECTIVE_TOKEN) ++ abort(); ++} ++ ++static void ++test_cfx_short_plaintext(gss_ctx_id_t ctx, krb5_key subkey) ++{ ++ OM_uint32 major, minor; ++ uint8_t tokbuf[128], zerobyte = 0; ++ krb5_data plain; ++ krb5_enc_data cipher; ++ gss_buffer_desc in, out; ++ ++ write_cfx_header(0, tokbuf); ++ ++ /* Encrypt a single byte, with no copy of the header. */ ++ plain = make_data(&zerobyte, 1); ++ cipher.ciphertext.data = (char *)tokbuf + 16; ++ cipher.ciphertext.length = sizeof(tokbuf) - 16; ++ cipher.enctype = subkey->keyblock.enctype; ++ if (krb5_k_encrypt(NULL, subkey, KG_USAGE_INITIATOR_SEAL, NULL, ++ &plain, &cipher) != 0) ++ abort(); ++ ++ /* Verify that the token is rejected by gss_unwrap(). */ ++ in.value = tokbuf; ++ in.length = 16 + cipher.ciphertext.length; ++ major = gss_unwrap(&minor, ctx, &in, &out, NULL, NULL); ++ if (major != GSS_S_DEFECTIVE_TOKEN) ++ abort(); ++ (void)gss_release_buffer(&minor, &out); ++} ++ ++static void ++test_cfx_large_ec(gss_ctx_id_t ctx, krb5_key subkey) ++{ ++ OM_uint32 major, minor; ++ uint8_t tokbuf[128] = { 0 }, plainbuf[20]; ++ krb5_data plain; ++ krb5_enc_data cipher; ++ gss_buffer_desc in, out; ++ ++ /* Construct a header with an EC value of 5. */ ++ write_cfx_header(5, tokbuf); ++ ++ /* Encrypt a 4-byte plaintext plus the header. */ ++ memcpy(plainbuf, "abcd", 4); ++ memcpy(plainbuf + 4, tokbuf, 16); ++ plain = make_data(plainbuf, 20); ++ cipher.ciphertext.data = (char *)tokbuf + 16; ++ cipher.ciphertext.length = sizeof(tokbuf) - 16; ++ cipher.enctype = subkey->keyblock.enctype; ++ if (krb5_k_encrypt(NULL, subkey, KG_USAGE_INITIATOR_SEAL, NULL, ++ &plain, &cipher) != 0) ++ abort(); ++ ++ /* Verify that the token is rejected by gss_unwrap(). */ ++ in.value = tokbuf; ++ in.length = 16 + cipher.ciphertext.length; ++ major = gss_unwrap(&minor, ctx, &in, &out, NULL, NULL); ++ if (major != GSS_S_DEFECTIVE_TOKEN) ++ abort(); ++ (void)gss_release_buffer(&minor, &out); ++} ++ ++static void ++test_iov_large_asn1_wrapper(gss_ctx_id_t ctx) ++{ ++ OM_uint32 minor, major; ++ uint8_t databuf[10] = { 0 }; ++ gss_iov_buffer_desc iov[2]; ++ ++ /* ++ * In this IOV array, the header contains a DER tag with a dangling eight ++ * bytes of length field. The data IOV indicates a total token length ++ * sufficient to contain the length bytes. ++ */ ++ iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER; ++ iov[0].buffer.value = ealloc(2); ++ iov[0].buffer.length = 2; ++ memcpy(iov[0].buffer.value, "\x60\x88", 2); ++ iov[1].type = GSS_IOV_BUFFER_TYPE_DATA; ++ iov[1].buffer.value = databuf; ++ iov[1].buffer.length = 10; ++ major = gss_unwrap_iov(&minor, ctx, NULL, NULL, iov, 2); ++ if (major != GSS_S_DEFECTIVE_TOKEN) ++ abort(); ++ free(iov[0].buffer.value); ++} ++ + /* Process wrap and MIC tokens with incomplete headers. */ + static void + test_short_header(gss_ctx_id_t ctx) +@@ -387,9 +534,7 @@ try_accept(void *value, size_t len) + gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; + + /* Copy the provided value to make input overruns more obvious. */ +- in.value = malloc(len); +- if (in.value == NULL) +- abort(); ++ in.value = ealloc(len); + memcpy(in.value, value, len); + in.length = len; + (void)gss_accept_sec_context(&minor, &ctx, GSS_C_NO_CREDENTIAL, &in, +@@ -424,11 +569,23 @@ test_short_encapsulation() + int + main(int argc, char **argv) + { ++ krb5_keyblock kb; ++ krb5_key cfx_subkey; + gss_ctx_id_t ctx; + size_t i; + +- ctx = make_fake_cfx_context(); ++ kb.enctype = ENCTYPE_AES128_CTS_HMAC_SHA1_96; ++ kb.length = 16; ++ kb.contents = (unsigned char *)"1234567887654321"; ++ if (krb5_k_create_key(NULL, &kb, &cfx_subkey) != 0) ++ abort(); ++ ++ ctx = make_fake_cfx_context(cfx_subkey); + test_bogus_1964_token(ctx); ++ test_cfx_altered_ec(ctx, cfx_subkey); ++ test_cfx_short_plaintext(ctx, cfx_subkey); ++ test_cfx_large_ec(ctx, cfx_subkey); ++ test_iov_large_asn1_wrapper(ctx); + free_fake_context(ctx); + + for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) { +-- +2.45.1 + diff --git a/root/ppg/common/deps/krb5/rpm/Generate-and-verify-message-MACs-in-libkrad.patch b/root/ppg/common/deps/krb5/rpm/Generate-and-verify-message-MACs-in-libkrad.patch new file mode 100644 index 00000000..d1e50805 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Generate-and-verify-message-MACs-in-libkrad.patch @@ -0,0 +1,629 @@ +From aad00d346e5c7923287fc0016a37b49c4618d78e Mon Sep 17 00:00:00 2001 +From: Julien Rische +Date: Thu, 22 Aug 2024 17:15:50 +0200 +Subject: [PATCH] Generate and verify message MACs in libkrad + +Implement some of the measures specified in +draft-ietf-radext-deprecating-radius-03 for mitigating the BlastRADIUS +attack (CVE-2024-3596): + +* Include a Message-Authenticator MAC as the first attribute when + generating a packet of type Access-Request, Access-Reject, + Access-Accept, or Access-Challenge (sections 5.2.1 and 5.2.4), if + the secret is non-empty. (An empty secret indicates the use of Unix + domain socket transport.) + +* Validate the Message-Authenticator MAC in received packets, if + present. + +FreeRADIUS enforces Message-Authenticator as of versions 3.2.5 and +3.0.27. libkrad must generate Message-Authenticator attributes in +order to remain compatible with these implementations. + +[ghudson@mit.edu: adjusted style and naming; simplified some +functions; edited commit message] + +ticket: 9142 (new) +tags: pullup +target_version: 1.21-next + +(cherry picked from commit 871125fea8ce0370a972bf65f7d1de63f619b06c) +--- + src/include/k5-int.h | 5 + + src/lib/crypto/krb/checksum_hmac_md5.c | 28 ++++ + src/lib/crypto/libk5crypto.exports | 1 + + src/lib/krad/attr.c | 17 ++ + src/lib/krad/attrset.c | 59 +++++-- + src/lib/krad/internal.h | 7 +- + src/lib/krad/packet.c | 206 +++++++++++++++++++++++-- + src/lib/krad/t_attrset.c | 2 +- + src/lib/krad/t_daemon.py | 3 +- + src/lib/krad/t_packet.c | 11 ++ + src/tests/t_otp.py | 3 + + 11 files changed, 311 insertions(+), 31 deletions(-) + +diff --git a/src/include/k5-int.h b/src/include/k5-int.h +index 9d5e41ca2c..d062617268 100644 +--- a/src/include/k5-int.h ++++ b/src/include/k5-int.h +@@ -2415,4 +2415,9 @@ void k5_change_error_message_code(krb5_context ctx, krb5_error_code oldcode, + #define k5_prependmsg krb5_prepend_error_message + #define k5_wrapmsg krb5_wrap_error_message + ++/* Generate an HMAC-MD5 keyed checksum as specified by RFC 2104. */ ++krb5_error_code ++k5_hmac_md5(const krb5_data *key, const krb5_crypto_iov *data, size_t num_data, ++ krb5_data *output); ++ + #endif /* _KRB5_INT_H */ +diff --git a/src/lib/crypto/krb/checksum_hmac_md5.c b/src/lib/crypto/krb/checksum_hmac_md5.c +index ec024f3966..a809388549 100644 +--- a/src/lib/crypto/krb/checksum_hmac_md5.c ++++ b/src/lib/crypto/krb/checksum_hmac_md5.c +@@ -92,3 +92,31 @@ cleanup: + free(hash_iov); + return ret; + } ++ ++krb5_error_code ++k5_hmac_md5(const krb5_data *key, const krb5_crypto_iov *data, size_t num_data, ++ krb5_data *output) ++{ ++ krb5_error_code ret; ++ const struct krb5_hash_provider *hash = &krb5int_hash_md5; ++ krb5_keyblock keyblock = { 0 }; ++ krb5_data hashed_key; ++ uint8_t hkeybuf[16]; ++ krb5_crypto_iov iov; ++ ++ /* Hash the key if it is longer than the block size. */ ++ if (key->length > hash->blocksize) { ++ hashed_key = make_data(hkeybuf, sizeof(hkeybuf)); ++ iov.flags = KRB5_CRYPTO_TYPE_DATA; ++ iov.data = *key; ++ ret = hash->hash(&iov, 1, &hashed_key); ++ if (ret) ++ return ret; ++ key = &hashed_key; ++ } ++ ++ keyblock.magic = KV5M_KEYBLOCK; ++ keyblock.length = key->length; ++ keyblock.contents = (uint8_t *)key->data; ++ return krb5int_hmac_keyblock(hash, &keyblock, data, num_data, output); ++} +diff --git a/src/lib/crypto/libk5crypto.exports b/src/lib/crypto/libk5crypto.exports +index 9db1813810..b4dcd29937 100644 +--- a/src/lib/crypto/libk5crypto.exports ++++ b/src/lib/crypto/libk5crypto.exports +@@ -107,3 +107,4 @@ krb5_c_prfplus + krb5_c_derive_prfplus + k5_enctype_to_ssf + krb5int_c_deprecated_enctype ++k5_hmac_md5 +diff --git a/src/lib/krad/attr.c b/src/lib/krad/attr.c +index 42d354a3b5..65ed1d35e7 100644 +--- a/src/lib/krad/attr.c ++++ b/src/lib/krad/attr.c +@@ -125,6 +125,23 @@ static const attribute_record attributes[UCHAR_MAX] = { + {"NAS-Port-Type", 4, 4, NULL, NULL}, + {"Port-Limit", 4, 4, NULL, NULL}, + {"Login-LAT-Port", 1, MAX_ATTRSIZE, NULL, NULL}, ++ {NULL, 0, 0, NULL, NULL}, /* Reserved for tunnelling */ ++ {NULL, 0, 0, NULL, NULL}, /* Reserved for tunnelling */ ++ {NULL, 0, 0, NULL, NULL}, /* Reserved for tunnelling */ ++ {NULL, 0, 0, NULL, NULL}, /* Reserved for tunnelling */ ++ {NULL, 0, 0, NULL, NULL}, /* Reserved for tunnelling */ ++ {NULL, 0, 0, NULL, NULL}, /* Reserved for tunnelling */ ++ {NULL, 0, 0, NULL, NULL}, /* Reserved for Apple Remote Access Protocol */ ++ {NULL, 0, 0, NULL, NULL}, /* Reserved for Apple Remote Access Protocol */ ++ {NULL, 0, 0, NULL, NULL}, /* Reserved for Apple Remote Access Protocol */ ++ {NULL, 0, 0, NULL, NULL}, /* Reserved for Apple Remote Access Protocol */ ++ {NULL, 0, 0, NULL, NULL}, /* Reserved for Apple Remote Access Protocol */ ++ {NULL, 0, 0, NULL, NULL}, /* Password-Retry */ ++ {NULL, 0, 0, NULL, NULL}, /* Prompt */ ++ {NULL, 0, 0, NULL, NULL}, /* Connect-Info */ ++ {NULL, 0, 0, NULL, NULL}, /* Configuration-Token */ ++ {NULL, 0, 0, NULL, NULL}, /* EAP-Message */ ++ {"Message-Authenticator", MD5_DIGEST_SIZE, MD5_DIGEST_SIZE, NULL, NULL}, + }; + + /* Encode User-Password attribute. */ +diff --git a/src/lib/krad/attrset.c b/src/lib/krad/attrset.c +index 6ec031e320..e5457ebfd7 100644 +--- a/src/lib/krad/attrset.c ++++ b/src/lib/krad/attrset.c +@@ -164,15 +164,44 @@ krad_attrset_copy(const krad_attrset *set, krad_attrset **copy) + return 0; + } + ++/* Place an encoded attributes into outbuf at position *i. Increment *i by the ++ * length of the encoding. */ ++static krb5_error_code ++append_attr(krb5_context ctx, const char *secret, ++ const uint8_t *auth, krad_attr type, const krb5_data *data, ++ uint8_t outbuf[MAX_ATTRSETSIZE], size_t *i, krb5_boolean *is_fips) ++{ ++ uint8_t buffer[MAX_ATTRSIZE]; ++ size_t attrlen; ++ krb5_error_code retval; ++ ++ retval = kr_attr_encode(ctx, secret, auth, type, data, buffer, &attrlen, ++ is_fips); ++ if (retval) ++ return retval; ++ ++ if (attrlen > MAX_ATTRSETSIZE - *i - 2) ++ return EMSGSIZE; ++ ++ outbuf[(*i)++] = type; ++ outbuf[(*i)++] = attrlen + 2; ++ memcpy(outbuf + *i, buffer, attrlen); ++ *i += attrlen; ++ ++ return 0; ++} ++ + krb5_error_code + kr_attrset_encode(const krad_attrset *set, const char *secret, +- const unsigned char *auth, ++ const uint8_t *auth, krb5_boolean add_msgauth, + unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen, + krb5_boolean *is_fips) + { +- unsigned char buffer[MAX_ATTRSIZE]; + krb5_error_code retval; +- size_t i = 0, attrlen; ++ krad_attr msgauth_type = krad_attr_name2num("Message-Authenticator"); ++ const uint8_t zeroes[MD5_DIGEST_SIZE] = { 0 }; ++ krb5_data zerodata; ++ size_t i = 0; + attr *a; + + if (set == NULL) { +@@ -180,19 +209,21 @@ kr_attrset_encode(const krad_attrset *set, const char *secret, + return 0; + } + +- K5_TAILQ_FOREACH(a, &set->list, list) { +- retval = kr_attr_encode(set->ctx, secret, auth, a->type, &a->attr, +- buffer, &attrlen, is_fips); +- if (retval != 0) ++ if (add_msgauth) { ++ /* Encode Message-Authenticator as the first attribute, per ++ * draft-ietf-radext-deprecating-radius-03 section 5.2. */ ++ zerodata = make_data((uint8_t *)zeroes, MD5_DIGEST_SIZE); ++ retval = append_attr(set->ctx, secret, auth, msgauth_type, &zerodata, ++ outbuf, &i, is_fips); ++ if (retval) + return retval; ++ } + +- if (i + attrlen + 2 > MAX_ATTRSETSIZE) +- return EMSGSIZE; +- +- outbuf[i++] = a->type; +- outbuf[i++] = attrlen + 2; +- memcpy(&outbuf[i], buffer, attrlen); +- i += attrlen; ++ K5_TAILQ_FOREACH(a, &set->list, list) { ++ retval = append_attr(set->ctx, secret, auth, a->type, &a->attr, ++ outbuf, &i, is_fips); ++ if (retval) ++ return retval; + } + + *outlen = i; +diff --git a/src/lib/krad/internal.h b/src/lib/krad/internal.h +index b086598fb2..f3e4a1d8d3 100644 +--- a/src/lib/krad/internal.h ++++ b/src/lib/krad/internal.h +@@ -45,6 +45,8 @@ + #define UCHAR_MAX 255 + #endif + ++#define MD5_DIGEST_SIZE 16 ++ + /* RFC 2865 */ + #define MAX_ATTRSIZE (UCHAR_MAX - 2) + #define MAX_ATTRSETSIZE (KRAD_PACKET_SIZE_MAX - 20) +@@ -75,10 +77,11 @@ kr_attr_decode(krb5_context ctx, const char *secret, const unsigned char *auth, + krad_attr type, const krb5_data *in, + unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen); + +-/* Encode the attributes into the buffer. */ ++/* Encode set into outbuf. If add_msgauth is true, include a zeroed ++ * Message-Authenticator as the first attribute. */ + krb5_error_code + kr_attrset_encode(const krad_attrset *set, const char *secret, +- const unsigned char *auth, ++ const uint8_t *auth, krb5_boolean add_msgauth, + unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen, + krb5_boolean *is_fips); + +diff --git a/src/lib/krad/packet.c b/src/lib/krad/packet.c +index fc2d248001..257bbc6345 100644 +--- a/src/lib/krad/packet.c ++++ b/src/lib/krad/packet.c +@@ -36,6 +36,7 @@ + typedef unsigned char uchar; + + /* RFC 2865 */ ++#define MSGAUTH_SIZE (2 + MD5_DIGEST_SIZE) + #define OFFSET_CODE 0 + #define OFFSET_ID 1 + #define OFFSET_LENGTH 2 +@@ -222,6 +223,106 @@ packet_set_attrset(krb5_context ctx, const char *secret, krad_packet *pkt) + return kr_attrset_decode(ctx, &tmp, secret, pkt_auth(pkt), &pkt->attrset); + } + ++/* Determine if a packet requires a Message-Authenticator attribute. */ ++static inline krb5_boolean ++requires_msgauth(const char *secret, krad_code code) ++{ ++ /* If no secret is provided, assume that the transport is a UNIX socket. ++ * Message-Authenticator is required only on UDP and TCP connections. */ ++ if (*secret == '\0') ++ return FALSE; ++ ++ /* ++ * Per draft-ietf-radext-deprecating-radius-03 sections 5.2.1 and 5.2.4, ++ * Message-Authenticator is required in Access-Request packets and all ++ * potential responses when UDP or TCP transport is used. ++ */ ++ return code == krad_code_name2num("Access-Request") || ++ code == krad_code_name2num("Access-Reject") || ++ code == krad_code_name2num("Access-Accept") || ++ code == krad_code_name2num("Access-Challenge"); ++} ++ ++/* Check if the packet has a Message-Authenticator attribute. */ ++static inline krb5_boolean ++has_pkt_msgauth(const krad_packet *pkt) ++{ ++ krad_attr msgauth_type = krad_attr_name2num("Message-Authenticator"); ++ ++ return krad_attrset_get(pkt->attrset, msgauth_type, 0) != NULL; ++} ++ ++/* Return the beginning of the Message-Authenticator attribute in pkt, or NULL ++ * if no such attribute is present. */ ++static const uint8_t * ++lookup_msgauth_addr(const krad_packet *pkt) ++{ ++ krad_attr msgauth_type = krad_attr_name2num("Message-Authenticator"); ++ size_t i; ++ uint8_t *p; ++ ++ i = OFFSET_ATTR; ++ while (i + 2 < pkt->pkt.length) { ++ p = (uint8_t *)offset(&pkt->pkt, i); ++ if (msgauth_type == *p) ++ return p; ++ i += p[1]; ++ } ++ ++ return NULL; ++} ++ ++/* ++ * Calculate the message authenticator MAC for pkt as specified in RFC 2869 ++ * section 5.14, placing the result in mac_out. Use the provided authenticator ++ * auth, which may be from pkt or from a corresponding request. ++ */ ++static krb5_error_code ++calculate_mac(const char *secret, const krad_packet *pkt, ++ const uint8_t auth[AUTH_FIELD_SIZE], ++ uint8_t mac_out[MD5_DIGEST_SIZE]) ++{ ++ uint8_t zeroed_msgauth[MSGAUTH_SIZE]; ++ krad_attr msgauth_type = krad_attr_name2num("Message-Authenticator"); ++ const uint8_t *msgauth_attr, *msgauth_end, *pkt_end; ++ krb5_crypto_iov input[5]; ++ krb5_data ksecr, mac; ++ ++ msgauth_attr = lookup_msgauth_addr(pkt); ++ if (msgauth_attr == NULL) ++ return EINVAL; ++ msgauth_end = msgauth_attr + MSGAUTH_SIZE; ++ pkt_end = (const uint8_t *)pkt->pkt.data + pkt->pkt.length; ++ ++ /* Read code, id, and length from the packet. */ ++ input[0].flags = KRB5_CRYPTO_TYPE_DATA; ++ input[0].data = make_data(pkt->pkt.data, OFFSET_AUTH); ++ ++ /* Read the provided authenticator. */ ++ input[1].flags = KRB5_CRYPTO_TYPE_DATA; ++ input[1].data = make_data((uint8_t *)auth, AUTH_FIELD_SIZE); ++ ++ /* Read any attributes before Message-Authenticator. */ ++ input[2].flags = KRB5_CRYPTO_TYPE_DATA; ++ input[2].data = make_data(pkt_attr(pkt), msgauth_attr - pkt_attr(pkt)); ++ ++ /* Read Message-Authenticator with the data bytes all set to zero, per RFC ++ * 2869 section 5.14. */ ++ zeroed_msgauth[0] = msgauth_type; ++ zeroed_msgauth[1] = MSGAUTH_SIZE; ++ memset(zeroed_msgauth + 2, 0, MD5_DIGEST_SIZE); ++ input[3].flags = KRB5_CRYPTO_TYPE_DATA; ++ input[3].data = make_data(zeroed_msgauth, MSGAUTH_SIZE); ++ ++ /* Read any attributes after Message-Authenticator. */ ++ input[4].flags = KRB5_CRYPTO_TYPE_DATA; ++ input[4].data = make_data((uint8_t *)msgauth_end, pkt_end - msgauth_end); ++ ++ mac = make_data(mac_out, MD5_DIGEST_SIZE); ++ ksecr = string2data((char *)secret); ++ return k5_hmac_md5(&ksecr, input, 5, &mac); ++} ++ + ssize_t + krad_packet_bytes_needed(const krb5_data *buffer) + { +@@ -255,6 +356,7 @@ krad_packet_new_request(krb5_context ctx, const char *secret, krad_code code, + krad_packet *pkt; + uchar id; + size_t attrset_len; ++ krb5_boolean msgauth_required; + + pkt = packet_new(); + if (pkt == NULL) { +@@ -274,9 +376,13 @@ krad_packet_new_request(krb5_context ctx, const char *secret, krad_code code, + if (retval != 0) + goto error; + ++ /* Determine if Message-Authenticator is required. */ ++ msgauth_required = (*secret != '\0' && ++ code == krad_code_name2num("Access-Request")); ++ + /* Encode the attributes. */ +- retval = kr_attrset_encode(set, secret, pkt_auth(pkt), pkt_attr(pkt), +- &attrset_len, &pkt->is_fips); ++ retval = kr_attrset_encode(set, secret, pkt_auth(pkt), msgauth_required, ++ pkt_attr(pkt), &attrset_len, &pkt->is_fips); + if (retval != 0) + goto error; + +@@ -285,6 +391,13 @@ krad_packet_new_request(krb5_context ctx, const char *secret, krad_code code, + pkt_code_set(pkt, code); + pkt_len_set(pkt, pkt->pkt.length); + ++ if (msgauth_required) { ++ /* Calculate and set the Message-Authenticator MAC. */ ++ retval = calculate_mac(secret, pkt, pkt_auth(pkt), pkt_attr(pkt) + 2); ++ if (retval != 0) ++ goto error; ++ } ++ + /* Copy the attrset for future use. */ + retval = packet_set_attrset(ctx, secret, pkt); + if (retval != 0) +@@ -307,14 +420,19 @@ krad_packet_new_response(krb5_context ctx, const char *secret, krad_code code, + krb5_error_code retval; + krad_packet *pkt; + size_t attrset_len; ++ krb5_boolean msgauth_required; + + pkt = packet_new(); + if (pkt == NULL) + return ENOMEM; + ++ /* Determine if Message-Authenticator is required. */ ++ msgauth_required = requires_msgauth(secret, code); ++ + /* Encode the attributes. */ +- retval = kr_attrset_encode(set, secret, pkt_auth(request), pkt_attr(pkt), +- &attrset_len, &pkt->is_fips); ++ retval = kr_attrset_encode(set, secret, pkt_auth(request), ++ msgauth_required, pkt_attr(pkt), &attrset_len, ++ &pkt->is_fips); + if (retval != 0) + goto error; + +@@ -330,6 +448,18 @@ krad_packet_new_response(krb5_context ctx, const char *secret, krad_code code, + if (retval != 0) + goto error; + ++ if (msgauth_required) { ++ /* ++ * Calculate and replace the Message-Authenticator MAC. Per RFC 2869 ++ * section 5.14, use the authenticator from the request, not from the ++ * response. ++ */ ++ retval = calculate_mac(secret, pkt, pkt_auth(request), ++ pkt_attr(pkt) + 2); ++ if (retval != 0) ++ goto error; ++ } ++ + /* Copy the attrset for future use. */ + retval = packet_set_attrset(ctx, secret, pkt); + if (retval != 0) +@@ -343,6 +473,34 @@ error: + return retval; + } + ++/* Verify the Message-Authenticator value in pkt, using the provided ++ * authenticator (which may be from pkt or from a corresponding request). */ ++static krb5_error_code ++verify_msgauth(const char *secret, const krad_packet *pkt, ++ const uint8_t auth[AUTH_FIELD_SIZE]) ++{ ++ uint8_t mac[MD5_DIGEST_SIZE]; ++ krad_attr msgauth_type = krad_attr_name2num("Message-Authenticator"); ++ const krb5_data *msgauth; ++ krb5_error_code retval; ++ ++ msgauth = krad_packet_get_attr(pkt, msgauth_type, 0); ++ if (msgauth == NULL) ++ return ENODATA; ++ ++ retval = calculate_mac(secret, pkt, auth, mac); ++ if (retval) ++ return retval; ++ ++ if (msgauth->length != MD5_DIGEST_SIZE) ++ return EMSGSIZE; ++ ++ if (k5_bcmp(mac, msgauth->data, MD5_DIGEST_SIZE) != 0) ++ return EBADMSG; ++ ++ return 0; ++} ++ + /* Decode a packet. */ + static krb5_error_code + decode_packet(krb5_context ctx, const char *secret, const krb5_data *buffer, +@@ -394,21 +552,35 @@ krad_packet_decode_request(krb5_context ctx, const char *secret, + krad_packet **reqpkt) + { + const krad_packet *tmp = NULL; ++ krad_packet *req; + krb5_error_code retval; + +- retval = decode_packet(ctx, secret, buffer, reqpkt); +- if (cb != NULL && retval == 0) { ++ retval = decode_packet(ctx, secret, buffer, &req); ++ if (retval) ++ return retval; ++ ++ /* Verify Message-Authenticator if present. */ ++ if (has_pkt_msgauth(req)) { ++ retval = verify_msgauth(secret, req, pkt_auth(req)); ++ if (retval) { ++ krad_packet_free(req); ++ return retval; ++ } ++ } ++ ++ if (cb != NULL) { + for (tmp = (*cb)(data, FALSE); tmp != NULL; tmp = (*cb)(data, FALSE)) { + if (pkt_id_get(*reqpkt) == pkt_id_get(tmp)) + break; + } +- } + +- if (cb != NULL && (retval != 0 || tmp != NULL)) +- (*cb)(data, TRUE); ++ if (tmp != NULL) ++ (*cb)(data, TRUE); ++ } + ++ *reqpkt = req; + *duppkt = tmp; +- return retval; ++ return 0; + } + + krb5_error_code +@@ -435,9 +607,17 @@ krad_packet_decode_response(krb5_context ctx, const char *secret, + break; + } + +- /* If the authenticator matches, then the response is valid. */ +- if (memcmp(pkt_auth(*rsppkt), auth, sizeof(auth)) == 0) +- break; ++ /* Verify the response authenticator. */ ++ if (k5_bcmp(pkt_auth(*rsppkt), auth, sizeof(auth)) != 0) ++ continue; ++ ++ /* Verify Message-Authenticator if present. */ ++ if (has_pkt_msgauth(*rsppkt)) { ++ if (verify_msgauth(secret, *rsppkt, pkt_auth(tmp)) != 0) ++ continue; ++ } ++ ++ break; + } + } + +diff --git a/src/lib/krad/t_attrset.c b/src/lib/krad/t_attrset.c +index 0f95762534..9a70529dc5 100644 +--- a/src/lib/krad/t_attrset.c ++++ b/src/lib/krad/t_attrset.c +@@ -63,7 +63,7 @@ main() + noerror(krad_attrset_add(set, krad_attr_name2num("User-Password"), &tmp)); + + /* Encode attrset. */ +- noerror(kr_attrset_encode(set, "foo", auth, buffer, &encode_len, ++ noerror(kr_attrset_encode(set, "foo", auth, FALSE, buffer, &encode_len, + &is_fips)); + krad_attrset_free(set); + +diff --git a/src/lib/krad/t_daemon.py b/src/lib/krad/t_daemon.py +index 7668cd7f87..7fa0449a3c 100755 +--- a/src/lib/krad/t_daemon.py ++++ b/src/lib/krad/t_daemon.py +@@ -40,6 +40,7 @@ DICTIONARY = """ + ATTRIBUTE\tUser-Name\t1\tstring + ATTRIBUTE\tUser-Password\t2\toctets + ATTRIBUTE\tNAS-Identifier\t32\tstring ++ATTRIBUTE\tMessage-Authenticator\t80\toctets + """ + + class TestServer(server.Server): +@@ -52,7 +53,7 @@ class TestServer(server.Server): + if key == "User-Password": + passwd = map(pkt.PwDecrypt, pkt[key]) + +- reply = self.CreateReplyPacket(pkt) ++ reply = self.CreateReplyPacket(pkt, message_authenticator=True) + if passwd == ['accept']: + reply.code = packet.AccessAccept + else: +diff --git a/src/lib/krad/t_packet.c b/src/lib/krad/t_packet.c +index c22489144f..104b6507a2 100644 +--- a/src/lib/krad/t_packet.c ++++ b/src/lib/krad/t_packet.c +@@ -172,6 +172,9 @@ main(int argc, const char **argv) + krb5_data username, password; + krb5_boolean auth = FALSE; + krb5_context ctx; ++ const krad_packet *dupreq; ++ const krb5_data *encpkt; ++ krad_packet *decreq; + + username = string2data("testUser"); + +@@ -184,9 +187,17 @@ main(int argc, const char **argv) + + password = string2data("accept"); + noerror(make_packet(ctx, &username, &password, &packets[ACCEPT_PACKET])); ++ encpkt = krad_packet_encode(packets[ACCEPT_PACKET]); ++ noerror(krad_packet_decode_request(ctx, "foo", encpkt, NULL, NULL, ++ &dupreq, &decreq)); ++ krad_packet_free(decreq); + + password = string2data("reject"); + noerror(make_packet(ctx, &username, &password, &packets[REJECT_PACKET])); ++ encpkt = krad_packet_encode(packets[REJECT_PACKET]); ++ noerror(krad_packet_decode_request(ctx, "foo", encpkt, NULL, NULL, ++ &dupreq, &decreq)); ++ krad_packet_free(decreq); + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; +diff --git a/src/tests/t_otp.py b/src/tests/t_otp.py +index cba871a0f2..1ec916598c 100755 +--- a/src/tests/t_otp.py ++++ b/src/tests/t_otp.py +@@ -49,6 +49,7 @@ ATTRIBUTE User-Name 1 string + ATTRIBUTE User-Password 2 octets + ATTRIBUTE Service-Type 6 integer + ATTRIBUTE NAS-Identifier 32 string ++ATTRIBUTE Message-Authenticator 80 octets + ''' + + class RadiusDaemon(Process): +@@ -97,6 +98,8 @@ class RadiusDaemon(Process): + reply.code = packet.AccessReject + replyq['reply'] = False + ++ reply.add_message_authenticator() ++ + outq.put(replyq) + if addr is None: + sock.send(reply.ReplyPacket()) +-- +2.46.0 + diff --git a/root/ppg/common/deps/krb5/rpm/Ignore-bad-enctypes-in-krb5_string_to_keysalts.patch b/root/ppg/common/deps/krb5/rpm/Ignore-bad-enctypes-in-krb5_string_to_keysalts.patch new file mode 100644 index 00000000..86f8e85c --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Ignore-bad-enctypes-in-krb5_string_to_keysalts.patch @@ -0,0 +1,38 @@ +From 42e29f27ce64fece2839bcce910813e97ca31210 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Wed, 15 Jul 2020 15:42:20 -0400 +Subject: [PATCH] Ignore bad enctypes in krb5_string_to_keysalts() + +Fixes a problem where the presence of legacy/unrecognized keysalts in +supported_enctypes would prevent the kadmin programs from starting. + +[ghudson@mit.edu: ideally we would put a warning in the kadmind log, +but that is difficult to do when the parsing is done inside a library. +Even adding a trace log is difficult because the kadm5 str_conv +functions do not accept contexts.] + +ticket: 8929 (new) +(cherry picked from commit be5396ada0e8dabd68bd0aceb733cfca39a609bc) +(cherry picked from commit 3f873868fb08b77da2d30e164a0ef6c71c17c607) +--- + src/lib/kadm5/str_conv.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/src/lib/kadm5/str_conv.c b/src/lib/kadm5/str_conv.c +index 7cf51d316..798295606 100644 +--- a/src/lib/kadm5/str_conv.c ++++ b/src/lib/kadm5/str_conv.c +@@ -340,9 +340,10 @@ krb5_string_to_keysalts(const char *string, const char *tupleseps, + while ((ksp = strtok_r(p, tseps, &tlasts)) != NULL) { + /* Pass a null pointer to subsequent calls to strtok_r(). */ + p = NULL; +- ret = string_to_keysalt(ksp, ksaltseps, &etype, &stype); +- if (ret) +- goto cleanup; ++ ++ /* Discard unrecognized keysalts. */ ++ if (string_to_keysalt(ksp, ksaltseps, &etype, &stype) != 0) ++ continue; + + /* Ignore duplicate keysalts if caller asks. */ + if (!dups && krb5_keysalt_is_present(ksalts, nksalts, etype, stype)) diff --git a/root/ppg/common/deps/krb5/rpm/Implement-GSS_C_CHANNEL_BOUND_FLAG.patch b/root/ppg/common/deps/krb5/rpm/Implement-GSS_C_CHANNEL_BOUND_FLAG.patch new file mode 100644 index 00000000..2b077d9d --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Implement-GSS_C_CHANNEL_BOUND_FLAG.patch @@ -0,0 +1,92 @@ +From b8bff4973a6642af80cbbc1bc03a52cb0d4e6247 Mon Sep 17 00:00:00 2001 +From: Alexander Scheel +Date: Wed, 5 Jul 2017 11:38:30 -0400 +Subject: [PATCH] Implement GSS_C_CHANNEL_BOUND_FLAG + +Define a new channel-bound GSS return flag, and set it in the krb5 +mech if the initiator sent channel bindings matching the acceptor's. +Do not error out if the acceptor specifies channel bindings and the +initiator does not send them. + +[ghudson@mit.edu: simplified code changes; fleshed out commit message] + +[iboukris: cherry-picked from another PR and reduced in scope] + +ticket: 8899 (new) +(cherry picked from commit 429a31146083fac21958631c2af572b08ec91022) +(cherry picked from commit 3ea1d6296ced3a998e79356f9be212e4c5e6a5d5) +--- + src/lib/gssapi/generic/gssapi_ext.h | 2 ++ + src/lib/gssapi/krb5/accept_sec_context.c | 18 +++++++++++++----- + 2 files changed, 15 insertions(+), 5 deletions(-) + +diff --git a/src/lib/gssapi/generic/gssapi_ext.h b/src/lib/gssapi/generic/gssapi_ext.h +index 218456e44..c675e8ebb 100644 +--- a/src/lib/gssapi/generic/gssapi_ext.h ++++ b/src/lib/gssapi/generic/gssapi_ext.h +@@ -595,6 +595,8 @@ gss_store_cred_into( + * attribute (along with any applicable RFC 5587 attributes). + */ + ++#define GSS_C_CHANNEL_BOUND_FLAG 2048 /* 0x00000800 */ ++ + OM_uint32 KRB5_CALLCONV + gssspi_query_meta_data( + OM_uint32 *minor_status, +diff --git a/src/lib/gssapi/krb5/accept_sec_context.c b/src/lib/gssapi/krb5/accept_sec_context.c +index 70dd7fc0c..9d3e2f4fe 100644 +--- a/src/lib/gssapi/krb5/accept_sec_context.c ++++ b/src/lib/gssapi/krb5/accept_sec_context.c +@@ -427,6 +427,9 @@ kg_process_extension(krb5_context context, + GSS_C_SEQUENCE_FLAG | GSS_C_DCE_STYLE | \ + GSS_C_IDENTIFY_FLAG | GSS_C_EXTENDED_ERROR_FLAG) + ++/* A zero-value channel binding, for comparison */ ++static const uint8_t null_cb[CB_MD5_LEN]; ++ + /* + * The krb5 GSS mech appropriates the authenticator checksum field from RFC + * 4120 to store structured data instead of a checksum, indicated with checksum +@@ -435,9 +438,10 @@ kg_process_extension(krb5_context context, + * + * Interpret the checksum. Read delegated creds into *deleg_out if it is not + * NULL. Set *flags_out to the allowed subset of token flags, plus +- * GSS_C_DELEG_FLAG if a delegated credential was present. Process any +- * extensions found using exts. On error, set *code_out to a krb5_error code +- * for use as a minor status value. ++ * GSS_C_DELEG_FLAG if a delegated credential was present and ++ * GSS_C_CHANNEL_BOUND_FLAG if matching channel bindings are present. Process ++ * any extensions found using exts. On error, set *code_out to a krb5_error ++ * code for use as a minor status value. + */ + static OM_uint32 + process_checksum(OM_uint32 *minor_status, krb5_context context, +@@ -450,7 +454,7 @@ process_checksum(OM_uint32 *minor_status, krb5_context context, + krb5_error_code code = 0; + OM_uint32 status, option_id, token_flags; + size_t cb_len, option_len; +- krb5_boolean valid; ++ krb5_boolean valid, token_cb_present = FALSE, cb_match = FALSE; + krb5_key subkey; + krb5_data option, empty = empty_data(); + krb5_checksum cb_cksum; +@@ -516,7 +520,9 @@ process_checksum(OM_uint32 *minor_status, krb5_context context, + goto fail; + } + assert(cb_cksum.length == cb_len); +- if (k5_bcmp(token_cb, cb_cksum.contents, cb_len) != 0) { ++ token_cb_present = (k5_bcmp(token_cb, null_cb, cb_len) != 0); ++ cb_match = (k5_bcmp(token_cb, cb_cksum.contents, cb_len) == 0); ++ if (token_cb_present && !cb_match) { + status = GSS_S_BAD_BINDINGS; + goto fail; + } +@@ -525,6 +531,8 @@ process_checksum(OM_uint32 *minor_status, krb5_context context, + /* Read the token flags and accept some of them as context flags. */ + token_flags = k5_input_get_uint32_le(&in); + *flags_out = token_flags & INITIATOR_FLAGS; ++ if (cb_match) ++ *flags_out |= GSS_C_CHANNEL_BOUND_FLAG; + + /* Read the delegated credential if present. */ + if (in.len >= 4 && (token_flags & GSS_C_DELEG_FLAG)) { diff --git a/root/ppg/common/deps/krb5/rpm/Implement-KERB_AP_OPTIONS_CBT-server-side.patch b/root/ppg/common/deps/krb5/rpm/Implement-KERB_AP_OPTIONS_CBT-server-side.patch new file mode 100644 index 00000000..4accf9a2 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Implement-KERB_AP_OPTIONS_CBT-server-side.patch @@ -0,0 +1,103 @@ +From b37714a1b9138c0258d357931215fbd5ca7fa72b Mon Sep 17 00:00:00 2001 +From: Isaac Boukris +Date: Mon, 9 Mar 2020 16:04:21 +0100 +Subject: [PATCH] Implement KERB_AP_OPTIONS_CBT (server side) + +Add server support for Microsoft's KERB_AP_OPTIONS_CBT as described in +MS-KILE. If the client includes the AP option in the authenticator +authdata and the server passed channel bindings, require the bindings +to match. + +[ghudson@mit.edu: refactored to put more logic in the helper function; +added a comment; clarified commit message] + +ticket: 8900 (new) +(cherry picked from commit 4f7c77b64a048ca5e3199b26b31493698c777a9c) +(cherry picked from commit 6407bf087fe53088d91efd09df736e979cd4e8db) +--- + src/include/krb5/krb5.hin | 1 + + src/lib/gssapi/krb5/accept_sec_context.c | 45 +++++++++++++++++++++++- + 2 files changed, 45 insertions(+), 1 deletion(-) + +diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin +index f8269fb17..9264bede1 100644 +--- a/src/include/krb5/krb5.hin ++++ b/src/include/krb5/krb5.hin +@@ -1915,6 +1915,7 @@ krb5_verify_checksum(krb5_context context, krb5_cksumtype ctype, + #define KRB5_AUTHDATA_SIGNTICKET 512 /**< formerly 142 in krb5 1.8 */ + #define KRB5_AUTHDATA_FX_ARMOR 71 + #define KRB5_AUTHDATA_AUTH_INDICATOR 97 ++#define KRB5_AUTHDATA_AP_OPTIONS 143 + /** @} */ /* end of KRB5_AUTHDATA group */ + + /* password change constants */ +diff --git a/src/lib/gssapi/krb5/accept_sec_context.c b/src/lib/gssapi/krb5/accept_sec_context.c +index 9d3e2f4fe..175a24c4e 100644 +--- a/src/lib/gssapi/krb5/accept_sec_context.c ++++ b/src/lib/gssapi/krb5/accept_sec_context.c +@@ -430,6 +430,32 @@ kg_process_extension(krb5_context context, + /* A zero-value channel binding, for comparison */ + static const uint8_t null_cb[CB_MD5_LEN]; + ++/* Look for AP_OPTIONS in authdata. If present and the options include ++ * KERB_AP_OPTIONS_CBT, set *cbt_out to true. */ ++static krb5_error_code ++check_cbt(krb5_context context, krb5_authdata **authdata, ++ krb5_boolean *cbt_out) ++{ ++ krb5_error_code code; ++ uint32_t ad_ap_options; ++ const uint32_t KERB_AP_OPTIONS_CBT = 0x4000; ++ ++ *cbt_out = FALSE; ++ ++ code = krb5_find_authdata(context, NULL, authdata, ++ KRB5_AUTHDATA_AP_OPTIONS, &authdata); ++ if (code || authdata == NULL) ++ return code; ++ if (authdata[1] != NULL || authdata[0]->length != 4) ++ return KRB5KRB_AP_ERR_MSG_TYPE; ++ ++ ad_ap_options = load_32_le(authdata[0]->contents); ++ if (ad_ap_options & KERB_AP_OPTIONS_CBT) ++ *cbt_out = TRUE; ++ ++ return 0; ++} ++ + /* + * The krb5 GSS mech appropriates the authenticator checksum field from RFC + * 4120 to store structured data instead of a checksum, indicated with checksum +@@ -454,7 +480,7 @@ process_checksum(OM_uint32 *minor_status, krb5_context context, + krb5_error_code code = 0; + OM_uint32 status, option_id, token_flags; + size_t cb_len, option_len; +- krb5_boolean valid, token_cb_present = FALSE, cb_match = FALSE; ++ krb5_boolean valid, client_cbt, token_cb_present = FALSE, cb_match = FALSE; + krb5_key subkey; + krb5_data option, empty = empty_data(); + krb5_checksum cb_cksum; +@@ -582,6 +608,23 @@ process_checksum(OM_uint32 *minor_status, krb5_context context, + } + } + ++ /* ++ * If the client asserts the KERB_AP_OPTIONS_CBT flag (from MS-KILE) in the ++ * authenticator authdata, and the acceptor passed channel bindings, ++ * require matching channel bindings from the client. The intent is to ++ * prevent an authenticator generated for use outside of a TLS channel from ++ * being used inside of one. ++ */ ++ code = check_cbt(context, authenticator->authorization_data, &client_cbt); ++ if (code) { ++ status = GSS_S_FAILURE; ++ goto fail; ++ } ++ if (client_cbt && acceptor_cb != GSS_C_NO_CHANNEL_BINDINGS && !cb_match) { ++ status = GSS_S_BAD_BINDINGS; ++ goto fail; ++ } ++ + status = GSS_S_COMPLETE; + + fail: diff --git a/root/ppg/common/deps/krb5/rpm/Improve-negoex_parse_token-code-hygiene.patch b/root/ppg/common/deps/krb5/rpm/Improve-negoex_parse_token-code-hygiene.patch new file mode 100644 index 00000000..c6050769 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Improve-negoex_parse_token-code-hygiene.patch @@ -0,0 +1,31 @@ +From 01b93a5522fd0e402401bf6ed3c1ebfde613965e Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Tue, 9 Jun 2020 16:23:37 -0400 +Subject: [PATCH] Improve negoex_parse_token() code hygiene + +If the while loop in negoex_parse_token() runs for zero iterations, +major will be used initialized. Currently this cannot happen, but +only because both of the call sites check for zero-length tokens. +Initialize major for safety. + +[ghudson@mit.edu: rewrote commit message] + +(cherry picked from commit 4f91b6f8fa6fe1de662b3fdac0d59b7758ec642a) +(cherry picked from commit c726a72c68244129eb08b840b92144acfa776573) +--- + src/lib/gssapi/spnego/negoex_util.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/lib/gssapi/spnego/negoex_util.c b/src/lib/gssapi/spnego/negoex_util.c +index 700368456..99580fd79 100644 +--- a/src/lib/gssapi/spnego/negoex_util.c ++++ b/src/lib/gssapi/spnego/negoex_util.c +@@ -454,7 +454,7 @@ negoex_parse_token(OM_uint32 *minor, spnego_gss_ctx_id_t ctx, + gss_const_buffer_t token, + struct negoex_message **messages_out, size_t *count_out) + { +- OM_uint32 major; ++ OM_uint32 major = GSS_S_COMPLETE; + size_t count = 0; + struct k5input in; + struct negoex_message *messages = NULL, *newptr; diff --git a/root/ppg/common/deps/krb5/rpm/Improve-ulog-block-resize-efficiency.patch b/root/ppg/common/deps/krb5/rpm/Improve-ulog-block-resize-efficiency.patch new file mode 100644 index 00000000..1ff61701 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Improve-ulog-block-resize-efficiency.patch @@ -0,0 +1,257 @@ +From b77dd295d796893853f69524ee4dbf94331ab847 Mon Sep 17 00:00:00 2001 +From: Zoltan Borbely +Date: Fri, 31 Jan 2025 18:00:17 +0100 +Subject: [PATCH] Improve ulog block resize efficiency + +When it is necessary to increase the ulog block size, copy the +existing entries instead of reinitializing the log. + +[ghudson@mit.edu: added test case; renamed and split INDEX() to avoid +duplication; added sync_ulog() helper; modified copying loop for +clarity; edited commit message] + +ticket: 9161 (new) +(cherry picked from commit 197ddd4196a3049cd17d29d1c8f0af1424472956) +--- + src/include/kdb_log.h | 20 +++++++++---- + src/kprop/kproplog.c | 2 +- + src/lib/kdb/kdb_log.c | 68 ++++++++++++++++++++++++++++++------------- + src/tests/t_iprop.py | 30 +++++++++++++++++-- + 4 files changed, 90 insertions(+), 30 deletions(-) + +diff --git a/src/include/kdb_log.h b/src/include/kdb_log.h +index 4239575659..2856859f8e 100644 +--- a/src/include/kdb_log.h ++++ b/src/include/kdb_log.h +@@ -18,12 +18,6 @@ + extern "C" { + #endif + +-/* +- * DB macros +- */ +-#define INDEX(ulog, i) (kdb_ent_header_t *)(void *) \ +- ((char *)(ulog) + sizeof(kdb_hlog_t) + (i) * ulog->kdb_block) +- + /* + * Current DB version # + */ +@@ -106,6 +100,20 @@ typedef struct _kdb_log_context { + int ulogfd; + } kdb_log_context; + ++/* Return the address of the i'th record in ulog for the given block size. */ ++static inline uint8_t * ++ulog_record_ptr(kdb_hlog_t *ulog, size_t i, size_t bsize) ++{ ++ return (uint8_t *)ulog + sizeof(*ulog) + i * bsize; ++} ++ ++/* Return the i'th update entry header for ulog. */ ++static inline kdb_ent_header_t * ++ulog_index(kdb_hlog_t *ulog, size_t i) ++{ ++ return (void *)ulog_record_ptr(ulog, i, ulog->kdb_block); ++} ++ + #ifdef __cplusplus + } + #endif +diff --git a/src/kprop/kproplog.c b/src/kprop/kproplog.c +index 865b0d68d5..7052dac870 100644 +--- a/src/kprop/kproplog.c ++++ b/src/kprop/kproplog.c +@@ -330,7 +330,7 @@ print_update(kdb_hlog_t *ulog, uint32_t entry, uint32_t ulogentries, + for (i = start_sno; i < ulog->kdb_last_sno; i++) { + indx = i % ulogentries; + +- indx_log = INDEX(ulog, indx); ++ indx_log = ulog_index(ulog, indx); + + /* + * Check for corrupt update entry +diff --git a/src/lib/kdb/kdb_log.c b/src/lib/kdb/kdb_log.c +index c805ebd988..419beab9e4 100644 +--- a/src/lib/kdb/kdb_log.c ++++ b/src/lib/kdb/kdb_log.c +@@ -103,13 +103,31 @@ sync_header(kdb_hlog_t *ulog) + } + } + ++/* Sync memory to disk for the entire ulog. */ ++static void ++sync_ulog(kdb_hlog_t *ulog, uint32_t ulogentries) ++{ ++ size_t len; ++ ++ if (!pagesize) ++ pagesize = getpagesize(); ++ ++ len = (sizeof(kdb_hlog_t) + ulogentries * ulog->kdb_block + ++ (pagesize - 1)) & ~(pagesize - 1); ++ if (msync(ulog, len, MS_SYNC)) { ++ /* Couldn't sync to disk, let's panic. */ ++ syslog(LOG_ERR, _("could not sync the whole ulog to disk")); ++ abort(); ++ } ++} ++ + /* Return true if the ulog entry for sno matches sno and timestamp. */ + static krb5_boolean + check_sno(kdb_log_context *log_ctx, kdb_sno_t sno, + const kdbe_time_t *timestamp) + { + unsigned int indx = (sno - 1) % log_ctx->ulogentries; +- kdb_ent_header_t *ent = INDEX(log_ctx->ulog, indx); ++ kdb_ent_header_t *ent = ulog_index(log_ctx->ulog, indx); + + return ent->kdb_entry_sno == sno && time_equal(&ent->kdb_time, timestamp); + } +@@ -175,17 +193,16 @@ extend_file_to(int fd, unsigned int new_size) + return 0; + } + +-/* +- * Resize the array elements. We reinitialize the update log rather than +- * unrolling the the log and copying it over to a temporary log for obvious +- * performance reasons. Replicas will subsequently do a full resync, but the +- * need for resizing should be very small. +- */ ++/* Resize the array elements of ulog to be at least as large as recsize. Move ++ * the existing elements into the proper offsets for the new block size. */ + static krb5_error_code + resize(kdb_hlog_t *ulog, uint32_t ulogentries, int ulogfd, + unsigned int recsize, const kdb_incr_update_t *upd) + { +- unsigned int new_block, new_size; ++ size_t old_block = ulog->kdb_block, new_block, new_size; ++ krb5_error_code retval; ++ uint8_t *old_ent, *new_ent; ++ uint32_t i; + + if (ulog == NULL) + return KRB5_LOG_ERROR; +@@ -204,16 +221,25 @@ resize(kdb_hlog_t *ulog, uint32_t ulogentries, int ulogfd, + if (new_size > MAXLOGLEN) + return KRB5_LOG_ERROR; + +- /* Reinit log with new block size. */ +- memset(ulog, 0, sizeof(*ulog)); +- ulog->kdb_hmagic = KDB_ULOG_HDR_MAGIC; +- ulog->db_version_num = KDB_VERSION; +- ulog->kdb_state = KDB_STABLE; +- ulog->kdb_block = new_block; +- sync_header(ulog); +- + /* Expand log considering new block size. */ +- return extend_file_to(ulogfd, new_size); ++ retval = extend_file_to(ulogfd, new_size); ++ if (retval) ++ return retval; ++ ++ /* Copy each record into its new location and zero out the unused areas. ++ * The area is overlapping, so we have to iterate backwards. */ ++ for (i = ulogentries; i > 0; i--) { ++ old_ent = ulog_record_ptr(ulog, i - 1, old_block); ++ new_ent = ulog_record_ptr(ulog, i - 1, new_block); ++ memmove(new_ent, old_ent, old_block); ++ memset(new_ent + old_block, 0, new_block - old_block); ++ } ++ ++ syslog(LOG_INFO, _("ulog block size has been resized from %lu to %lu"), ++ (unsigned long)old_block, (unsigned long)new_block); ++ ulog->kdb_block = new_block; ++ sync_ulog(ulog, ulogentries); ++ return 0; + } + + /* Set the ulog to contain only a dummy entry with the given serial number and +@@ -222,7 +248,7 @@ static void + set_dummy(kdb_log_context *log_ctx, kdb_sno_t sno, const kdbe_time_t *kdb_time) + { + kdb_hlog_t *ulog = log_ctx->ulog; +- kdb_ent_header_t *ent = INDEX(ulog, (sno - 1) % log_ctx->ulogentries); ++ kdb_ent_header_t *ent = ulog_index(ulog, (sno - 1) % log_ctx->ulogentries); + + memset(ent, 0, sizeof(*ent)); + ent->kdb_umagic = KDB_ULOG_MAGIC; +@@ -305,7 +331,7 @@ store_update(kdb_log_context *log_ctx, kdb_incr_update_t *upd) + ulog->kdb_state = KDB_UNSTABLE; + + i = (upd->kdb_entry_sno - 1) % ulogentries; +- indx_log = INDEX(ulog, i); ++ indx_log = ulog_index(ulog, i); + + memset(indx_log, 0, ulog->kdb_block); + indx_log->kdb_umagic = KDB_ULOG_MAGIC; +@@ -335,7 +361,7 @@ store_update(kdb_log_context *log_ctx, kdb_incr_update_t *upd) + } else { + /* We are circling; set kdb_first_sno and time to the next update. */ + i = upd->kdb_entry_sno % ulogentries; +- indx_log = INDEX(ulog, i); ++ indx_log = ulog_index(ulog, i); + ulog->kdb_first_sno = indx_log->kdb_entry_sno; + ulog->kdb_first_time = indx_log->kdb_time; + } +@@ -593,7 +619,7 @@ ulog_get_entries(krb5_context context, const kdb_last_t *last, + + for (; sno < ulog->kdb_last_sno; sno++) { + indx = sno % ulogentries; +- indx_log = INDEX(ulog, indx); ++ indx_log = ulog_index(ulog, indx); + + memset(upd, 0, sizeof(kdb_incr_update_t)); + xdrmem_create(&xdrs, (char *)indx_log->entry_data, +diff --git a/src/tests/t_iprop.py b/src/tests/t_iprop.py +index 371f3a22b6..cfcf4afde3 100755 +--- a/src/tests/t_iprop.py ++++ b/src/tests/t_iprop.py +@@ -85,8 +85,10 @@ def wait_for_prop(kpropd, full_expected, expected_old, expected_new): + # Verify the output of kproplog against the expected number of + # entries, first and last serial number, and a list of principal names + # for the update entrires. +-def check_ulog(num, first, last, entries, env=None): ++def check_ulog(num, first, last, entries, env=None, bsize=2048): + out = realm.run([kproplog], env=env) ++ if 'Entry block size : ' + str(bsize) + '\n' not in out: ++ fail('Expected block size %d' % bsize) + if 'Number of entries : ' + str(num) + '\n' not in out: + fail('Expected %d entries' % num) + if last: +@@ -456,8 +458,32 @@ for realm in multidb_realms(kdc_conf=conf, create_user=False, + wait_for_prop(kpropd2, True, 6, 1) + check_ulog(1, 1, 1, [None], replica2) + +- # Stop the kprop daemons so we can test kpropd -t. ++ # Create an update large enough to cause a block resize, and make ++ # sure that it propagates incrementally. ++ mark('block resize') ++ cmd = [kadminl, 'cpw', ++ '-e', 'aes128-sha1,aes256-sha1,aes128-sha2,aes256-sha2', ++ '-randkey', '-keepold', pr2] ++ n = 6 ++ for i in range(n): ++ realm.run(cmd) ++ check_ulog(n + 1, 1, n + 1, [None] + n * [pr2], bsize=4096) ++ kpropd1.send_signal(signal.SIGUSR1) ++ wait_for_prop(kpropd1, False, 1, n + 1) ++ check_ulog(n + 1, 1, n + 1, [None] + n * [pr2], replica1, bsize=4096) ++ kpropd2.send_signal(signal.SIGUSR1) ++ wait_for_prop(kpropd2, False, 1, n + 1) ++ check_ulog(n + 1, 1, n + 1, [None] + n * [pr2], replica2, bsize=4096) ++ ++ # Reset the ulog again. ++ realm.run([kproplog, '-R']) ++ kpropd1.send_signal(signal.SIGUSR1) ++ wait_for_prop(kpropd1, True, 7, 1) ++ kpropd2.send_signal(signal.SIGUSR1) ++ wait_for_prop(kpropd2, True, 7, 1) + realm.stop_kpropd(kpropd1) ++ ++ # Stop the kprop daemons so we can test kpropd -t. + stop_daemon(kpropd2) + stop_daemon(kadmind_proponly) + mark('kpropd -t') +-- +2.51.1 + diff --git a/root/ppg/common/deps/krb5/rpm/In-KDC-assume-all-services-support-aes256-sha1.patch b/root/ppg/common/deps/krb5/rpm/In-KDC-assume-all-services-support-aes256-sha1.patch new file mode 100644 index 00000000..fc4bfe29 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/In-KDC-assume-all-services-support-aes256-sha1.patch @@ -0,0 +1,51 @@ +From 5b67abf41026a420974f2d938c3e42d7f072abe5 Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Wed, 14 Dec 2022 13:20:46 -0500 +Subject: [PATCH] In KDC, assume all services support aes256-sha1 + +To facilitate negotiating session keys with acceptable security, +assume that services support aes256-cts-hmac-sha1 unless a +session_enctypes string attribute says otherwise. + +ticket: 9075 +(cherry picked from commit 2cbd847e0e92bc4e219b65c770ae33f851b22afc) +--- + src/kdc/kdc_util.c | 4 ++++ + src/tests/t_keyrollover.py | 6 +++--- + 2 files changed, 7 insertions(+), 3 deletions(-) + +diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c +index e3352f9cc6..23aadb88e9 100644 +--- a/src/kdc/kdc_util.c ++++ b/src/kdc/kdc_util.c +@@ -1015,6 +1015,10 @@ dbentry_supports_enctype(kdc_realm_t *kdc_active_realm, krb5_db_entry *server, + free(etypes_str); + free(etypes); + ++ /* Assume every server without a session_enctypes attribute supports ++ * aes256-cts-hmac-sha1-96. */ ++ if (enctype == ENCTYPE_AES256_CTS_HMAC_SHA1_96) ++ return TRUE; + /* Assume the server supports any enctype it has a long-term key for. */ + return !krb5_dbe_find_enctype(kdc_context, server, enctype, -1, 0, &datap); + } +diff --git a/src/tests/t_keyrollover.py b/src/tests/t_keyrollover.py +index f29e0d5500..583c2fa27e 100755 +--- a/src/tests/t_keyrollover.py ++++ b/src/tests/t_keyrollover.py +@@ -22,9 +22,9 @@ realm.run([kvno, princ1]) + realm.run([kadminl, 'purgekeys', realm.krbtgt_princ]) + # Make sure an old TGT fails after purging old TGS key. + realm.run([kvno, princ2], expected_code=1) +-et = "aes128-cts-hmac-sha256-128" +-msg = 'krbtgt/%s@%s\n\tEtype (skey, tkt): %s, %s' % \ +- (realm.realm, realm.realm, et, et) ++msg = 'krbtgt/%s@%s\n\tEtype (skey, tkt): ' \ ++ 'aes256-cts-hmac-sha1-96, aes128-cts-hmac-sha256-128' % \ ++ (realm.realm, realm.realm) + realm.run([klist, '-e'], expected_msg=msg) + + # Check that new key actually works. +-- +2.49.0 + diff --git a/root/ppg/common/deps/krb5/rpm/Make-KCM-iteration-fallback-work-with-sssd-kcm.patch b/root/ppg/common/deps/krb5/rpm/Make-KCM-iteration-fallback-work-with-sssd-kcm.patch new file mode 100644 index 00000000..784cc4da --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Make-KCM-iteration-fallback-work-with-sssd-kcm.patch @@ -0,0 +1,28 @@ +From b96983de501f185a06e8b3d2909ef71033bd9e48 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Tue, 30 Mar 2021 14:35:28 +0200 +Subject: [PATCH] Make KCM iteration fallback work with sssd-kcm + +sssd-kcm returns KRB5_CC_IO if the operation code is not known. + +ticket: 8990 +(cherry picked from commit 06afae820a44c1dc96ad88a0b16c3e50bc938b2a) +(cherry picked from commit 2dbca7e14c945d6394e0e05f285a068dcd541295) +(cherry picked from commit f7702c5b11bdd186d03fed32568c9a252d049d44) +--- + src/lib/krb5/ccache/cc_kcm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/lib/krb5/ccache/cc_kcm.c b/src/lib/krb5/ccache/cc_kcm.c +index 4141140c3..dae622feb 100644 +--- a/src/lib/krb5/ccache/cc_kcm.c ++++ b/src/lib/krb5/ccache/cc_kcm.c +@@ -876,7 +876,7 @@ kcm_start_seq_get(krb5_context context, krb5_ccache cache, + ret = kcmreq_get_cred_list(&req, &creds); + if (ret) + goto cleanup; +- } else if (ret == KRB5_FCC_INTERNAL) { ++ } else if (ret == KRB5_FCC_INTERNAL || ret == KRB5_CC_IO) { + /* Fall back to GET_CRED_UUID_LIST. */ + kcmreq_free(&req); + kcmreq_init(&req, KCM_OP_GET_CRED_UUID_LIST, cache); diff --git a/root/ppg/common/deps/krb5/rpm/Make-kprop-work-for-dump-files-larger-than-4GB.patch b/root/ppg/common/deps/krb5/rpm/Make-kprop-work-for-dump-files-larger-than-4GB.patch new file mode 100644 index 00000000..8358d7e7 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Make-kprop-work-for-dump-files-larger-than-4GB.patch @@ -0,0 +1,365 @@ +From 5d541f1f0b468b1c976acf8ec2359bd0c8c73be7 Mon Sep 17 00:00:00 2001 +From: Julien Rische +Date: Wed, 19 Jan 2022 19:46:08 +0100 +Subject: [PATCH] Make kprop work for dump files larger than 4GB + +If the dump file size does not fit in 32 bits, encode four zero bytes +(forcing an error for unmodified kpropd) followed by the size in the +next 64 bits. + +Add a functional test case, but only run it when an environment +variable is set, as processing a 4GB dump file is too +resource-intensive for make check. + +[ghudson@mit.edu: edited comments and commit message; eliminated use +of defined constant in some cases; added test case] + +ticket: 9053 (new) +--- + src/kprop/kprop.c | 37 +++++++++++++++++++++---------------- + src/kprop/kprop.h | 12 ++++++++++++ + src/kprop/kprop_util.c | 42 ++++++++++++++++++++++++++++++++++++++++++ + src/kprop/kpropd.c | 33 +++++++++++++++++++++------------ + src/tests/t_kprop.py | 34 ++++++++++++++++++++++++++++++++++ + 5 files changed, 130 insertions(+), 28 deletions(-) + +diff --git a/src/kprop/kprop.c b/src/kprop/kprop.c +index 0b53aae7e..5adb4d31f 100644 +--- a/src/kprop/kprop.c ++++ b/src/kprop/kprop.c +@@ -25,6 +25,7 @@ + */ + + #include "k5-int.h" ++#include + #include + #include + #include +@@ -71,11 +72,11 @@ static void open_connection(krb5_context context, char *host, int *fd_out); + static void kerberos_authenticate(krb5_context context, + krb5_auth_context *auth_context, int fd, + krb5_principal me, krb5_creds **new_creds); +-static int open_database(krb5_context context, char *data_fn, int *size); ++static int open_database(krb5_context context, char *data_fn, off_t *size); + static void close_database(krb5_context context, int fd); + static void xmit_database(krb5_context context, + krb5_auth_context auth_context, krb5_creds *my_creds, +- int fd, int database_fd, int in_database_size); ++ int fd, int database_fd, off_t in_database_size); + static void send_error(krb5_context context, krb5_creds *my_creds, int fd, + char *err_text, krb5_error_code err_code); + static void update_last_prop_file(char *hostname, char *file_name); +@@ -90,7 +91,8 @@ static void usage() + int + main(int argc, char **argv) + { +- int fd, database_fd, database_size; ++ int fd, database_fd; ++ off_t database_size; + krb5_error_code retval; + krb5_context context; + krb5_creds *my_creds; +@@ -339,7 +341,7 @@ kerberos_authenticate(krb5_context context, krb5_auth_context *auth_context, + * in the size of the database file. + */ + static int +-open_database(krb5_context context, char *data_fn, int *size) ++open_database(krb5_context context, char *data_fn, off_t *size) + { + struct stat stbuf, stbuf_ok; + char *data_ok_fn; +@@ -413,19 +415,18 @@ close_database(krb5_context context, int fd) + static void + xmit_database(krb5_context context, krb5_auth_context auth_context, + krb5_creds *my_creds, int fd, int database_fd, +- int in_database_size) ++ off_t in_database_size) + { + krb5_int32 n; + krb5_data inbuf, outbuf; +- char buf[KPROP_BUFSIZ]; ++ char buf[KPROP_BUFSIZ], dbsize_buf[KPROP_DBSIZE_MAX_BUFSIZ]; + krb5_error_code retval; + krb5_error *error; +- krb5_ui_4 database_size = in_database_size, send_size, sent_size; ++ uint64_t database_size = in_database_size, send_size, sent_size; + + /* Send over the size. */ +- send_size = htonl(database_size); +- inbuf.data = (char *)&send_size; +- inbuf.length = sizeof(send_size); /* must be 4, really */ ++ inbuf = make_data(dbsize_buf, sizeof(dbsize_buf)); ++ encode_database_size(database_size, &inbuf); + /* KPROP_CKSUMTYPE */ + retval = krb5_mk_safe(context, auth_context, &inbuf, &outbuf, NULL); + if (retval) { +@@ -460,7 +461,7 @@ xmit_database(krb5_context context, krb5_auth_context auth_context, + retval = krb5_mk_priv(context, auth_context, &inbuf, &outbuf, NULL); + if (retval) { + snprintf(buf, sizeof(buf), +- "while encoding database block starting at %d", ++ "while encoding database block starting at %"PRIu64, + sent_size); + com_err(progname, retval, "%s", buf); + send_error(context, my_creds, fd, buf, retval); +@@ -471,14 +472,14 @@ xmit_database(krb5_context context, krb5_auth_context auth_context, + if (retval) { + krb5_free_data_contents(context, &outbuf); + com_err(progname, retval, +- _("while sending database block starting at %d"), ++ _("while sending database block starting at %"PRIu64), + sent_size); + exit(1); + } + krb5_free_data_contents(context, &outbuf); + sent_size += n; + if (debug) +- printf("%d bytes sent.\n", sent_size); ++ printf("%"PRIu64" bytes sent.\n", sent_size); + } + if (sent_size != database_size) { + com_err(progname, 0, _("Premature EOF found for database file!")); +@@ -533,10 +534,14 @@ xmit_database(krb5_context context, krb5_auth_context auth_context, + exit(1); + } + +- memcpy(&send_size, outbuf.data, sizeof(send_size)); +- send_size = ntohl(send_size); ++ retval = decode_database_size(&outbuf, &send_size); ++ if (retval) { ++ com_err(progname, retval, _("malformed sent database size message")); ++ exit(1); ++ } + if (send_size != database_size) { +- com_err(progname, 0, _("Kpropd sent database size %d, expecting %d"), ++ com_err(progname, 0, _("Kpropd sent database size %"PRIu64 ++ ", expecting %"PRIu64), + send_size, database_size); + exit(1); + } +diff --git a/src/kprop/kprop.h b/src/kprop/kprop.h +index 75331cc8a..3a319b535 100644 +--- a/src/kprop/kprop.h ++++ b/src/kprop/kprop.h +@@ -32,6 +32,7 @@ + #define KPROP_PROT_VERSION "kprop5_01" + + #define KPROP_BUFSIZ 32768 ++#define KPROP_DBSIZE_MAX_BUFSIZ 12 /* max length of an encoded DB size */ + + /* pathnames are in osconf.h, included via k5-int.h */ + +@@ -41,3 +42,14 @@ int sockaddr2krbaddr(krb5_context context, int family, struct sockaddr *sa, + krb5_error_code + sn2princ_realm(krb5_context context, const char *hostname, const char *sname, + const char *realm, krb5_principal *princ_out); ++ ++/* ++ * Encode size in four bytes (for backward compatibility) if it fits; otherwise ++ * use the larger encoding. buf must be allocated with at least ++ * KPROP_DBSIZE_MAX_BUFSIZ bytes. ++ */ ++void encode_database_size(uint64_t size, krb5_data *buf); ++ ++/* Decode a database size. Return KRB5KRB_ERR_GENERIC if buf has an invalid ++ * length or did not encode a 32-bit size compactly. */ ++krb5_error_code decode_database_size(const krb5_data *buf, uint64_t *size_out); +diff --git a/src/kprop/kprop_util.c b/src/kprop/kprop_util.c +index c32d174b9..9d6b25389 100644 +--- a/src/kprop/kprop_util.c ++++ b/src/kprop/kprop_util.c +@@ -96,3 +96,45 @@ sn2princ_realm(krb5_context context, const char *hostname, const char *sname, + (*princ_out)->type = KRB5_NT_SRV_HST; + return ret; + } ++ ++void ++encode_database_size(uint64_t size, krb5_data *buf) ++{ ++ assert(buf->length >= 12); ++ if (size > 0 && size <= UINT32_MAX) { ++ /* Encode in 32 bits for backward compatibility. */ ++ store_32_be(size, buf->data); ++ buf->length = 4; ++ } else { ++ /* Set the first 32 bits to 0 and encode in the following 64 bits. */ ++ store_32_be(0, buf->data); ++ store_64_be(size, buf->data + 4); ++ buf->length = 12; ++ } ++} ++ ++krb5_error_code ++decode_database_size(const krb5_data *buf, uint64_t *size_out) ++{ ++ uint64_t size; ++ ++ if (buf->length == 12) { ++ /* A 12-byte buffer must have the first four bytes zeroed. */ ++ if (load_32_be(buf->data) != 0) ++ return KRB5KRB_ERR_GENERIC; ++ ++ /* The size is stored in the next 64 bits. Values from 1..2^32-1 must ++ * be encoded in four bytes. */ ++ size = load_64_be(buf->data + 4); ++ if (size > 0 && size <= UINT32_MAX) ++ return KRB5KRB_ERR_GENERIC; ++ } else if (buf->length == 4) { ++ size = load_32_be(buf->data); ++ } else { ++ /* Invalid buffer size. */ ++ return KRB5KRB_ERR_GENERIC; ++ } ++ ++ *size_out = size; ++ return 0; ++} +diff --git a/src/kprop/kpropd.c b/src/kprop/kpropd.c +index 356e3e0e6..a83a86866 100644 +--- a/src/kprop/kpropd.c ++++ b/src/kprop/kpropd.c +@@ -55,6 +55,7 @@ + #include "com_err.h" + #include "fake-addrinfo.h" + ++#include + #include + #include + #include +@@ -1354,9 +1355,10 @@ static void + recv_database(krb5_context context, int fd, int database_fd, + krb5_data *confmsg) + { +- krb5_ui_4 database_size, received_size; ++ uint64_t database_size, received_size; + int n; + char buf[1024]; ++ char dbsize_buf[KPROP_DBSIZE_MAX_BUFSIZ]; + krb5_data inbuf, outbuf; + krb5_error_code retval; + +@@ -1378,10 +1380,17 @@ recv_database(krb5_context context, int fd, int database_fd, + _("while decoding database size from client")); + exit(1); + } +- memcpy(&database_size, outbuf.data, sizeof(database_size)); ++ ++ retval = decode_database_size(&outbuf, &database_size); ++ if (retval) { ++ send_error(context, fd, retval, "malformed database size message"); ++ com_err(progname, retval, ++ _("malformed database size message from client")); ++ exit(1); ++ } ++ + krb5_free_data_contents(context, &inbuf); + krb5_free_data_contents(context, &outbuf); +- database_size = ntohl(database_size); + + /* Initialize the initial vector. */ + retval = krb5_auth_con_initivector(context, auth_context); +@@ -1401,7 +1410,7 @@ recv_database(krb5_context context, int fd, int database_fd, + retval = krb5_read_message(context, &fd, &inbuf); + if (retval) { + snprintf(buf, sizeof(buf), +- "while reading database block starting at offset %d", ++ "while reading database block starting at offset %"PRIu64, + received_size); + com_err(progname, retval, "%s", buf); + send_error(context, fd, retval, buf); +@@ -1412,8 +1421,8 @@ recv_database(krb5_context context, int fd, int database_fd, + retval = krb5_rd_priv(context, auth_context, &inbuf, &outbuf, NULL); + if (retval) { + snprintf(buf, sizeof(buf), +- "while decoding database block starting at offset %d", +- received_size); ++ "while decoding database block starting at offset %" ++ PRIu64, received_size); + com_err(progname, retval, "%s", buf); + send_error(context, fd, retval, buf); + krb5_free_data_contents(context, &inbuf); +@@ -1424,13 +1433,13 @@ recv_database(krb5_context context, int fd, int database_fd, + krb5_free_data_contents(context, &outbuf); + if (n < 0) { + snprintf(buf, sizeof(buf), +- "while writing database block starting at offset %d", ++ "while writing database block starting at offset %"PRIu64, + received_size); + send_error(context, fd, errno, buf); + } else if ((unsigned int)n != outbuf.length) { + snprintf(buf, sizeof(buf), + "incomplete write while writing database block starting " +- "at \noffset %d (%d written, %d expected)", ++ "at \noffset %"PRIu64" (%d written, %d expected)", + received_size, n, outbuf.length); + send_error(context, fd, KRB5KRB_ERR_GENERIC, buf); + } +@@ -1440,7 +1449,8 @@ recv_database(krb5_context context, int fd, int database_fd, + /* OK, we've seen the entire file. Did we get too many bytes? */ + if (received_size > database_size) { + snprintf(buf, sizeof(buf), +- "Received %d bytes, expected %d bytes for database file", ++ "Received %"PRIu64" bytes, expected %"PRIu64 ++ " bytes for database file", + received_size, database_size); + send_error(context, fd, KRB5KRB_ERR_GENERIC, buf); + } +@@ -1450,9 +1460,8 @@ recv_database(krb5_context context, int fd, int database_fd, + + /* Create message acknowledging number of bytes received, but + * don't send it until kdb5_util returns successfully. */ +- database_size = htonl(database_size); +- inbuf.data = (char *)&database_size; +- inbuf.length = sizeof(database_size); ++ inbuf = make_data(dbsize_buf, sizeof(dbsize_buf)); ++ encode_database_size(database_size, &inbuf); + retval = krb5_mk_safe(context,auth_context,&inbuf,confmsg,NULL); + if (retval) { + com_err(progname, retval, "while encoding # of receieved bytes"); +diff --git a/src/tests/t_kprop.py b/src/tests/t_kprop.py +index c33e4fea2..f8ffd653a 100755 +--- a/src/tests/t_kprop.py ++++ b/src/tests/t_kprop.py +@@ -87,5 +87,39 @@ realm.run([kdb5_util, 'dump', dumpfile]) + realm.run([kprop, '-f', dumpfile, '-P', str(realm.kprop_port()), hostname]) + check_output(kpropd) + realm.run([kadminl, 'listprincs'], replica3, expected_msg='wakawaka') ++stop_daemon(kpropd) ++ ++# This test is too resource-intensive to be included in "make check" ++# by default, but it can be enabled in the environment to test the ++# propagation of databases large enough to require a 12-byte encoding ++# of the database size. ++if 'KPROP_LARGE_DB_TEST' in os.environ: ++ output('Generating >4GB dumpfile\n') ++ with open(dumpfile, 'w') as f: ++ f.write('kdb5_util load_dump version 6\n') ++ f.write('princ\t38\t15\t3\t1\t0\tK/M@KRBTEST.COM\t64\t86400\t0\t0\t0' ++ '\t0\t0\t0\t8\t2\t0100\t9\t8\t0100010000000000\t2\t28' ++ '\tb93e105164625f6372656174696f6e404b5242544553542e434f4d00' ++ '\t1\t1\t18\t62\t2000408c027c250e8cc3b81476414f2214d57c1ce' ++ '38891e29792e87258247c73547df4d5756266931dd6686b62270e6568' ++ '95a31ec66bfe913b4f15226227\t-1;\n') ++ for i in range(1, 20000000): ++ f.write('princ\t38\t21\t1\t1\t0\tp%08d@KRBTEST.COM' % i) ++ f.write('\t0\t86400\t0\t0\t0\t0\t0\t0\t2\t27' ++ '\td73e1051757365722f61646d696e404b5242544553542e434f4d00' ++ '\t1\t1\t17\t46' ++ '\t10009c8ab7b3f89ccf3ca3ad98352a461b7f4f1b0c49' ++ '5605117591d9ad52ba4da0adef7a902126973ed2bdc3ffbf\t-1;\n') ++ assert os.path.getsize(dumpfile) > 4 * 1024 * 1024 * 1024 ++ with open(dumpfile + '.dump_ok', 'w') as f: ++ f.write('\0') ++ conf_large = {'dbmodules': {'db': {'database_name': '$testdir/db.large'}}, ++ 'realms': {'$realm': {'iprop_resync_timeout': '3600'}}} ++ large = realm.special_env('large', True, kdc_conf=conf_large) ++ kpropd = realm.start_kpropd(large, ['-d']) ++ realm.run([kprop, '-f', dumpfile, '-P', str(realm.kprop_port()), hostname]) ++ check_output(kpropd) ++ realm.run([kadminl, 'getprinc', 'p19999999'], env=large, ++ expected_msg='Principal: p19999999') + + success('kprop tests') +-- +2.35.1 + diff --git a/root/ppg/common/deps/krb5/rpm/Omit-KDC-indicator-check-for-S4U2Self-requests.patch b/root/ppg/common/deps/krb5/rpm/Omit-KDC-indicator-check-for-S4U2Self-requests.patch new file mode 100644 index 00000000..b9c2a373 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Omit-KDC-indicator-check-for-S4U2Self-requests.patch @@ -0,0 +1,49 @@ +From f7b6d43533d1d9ec3960e3d7f375995896768aef Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Wed, 6 May 2020 16:03:13 -0400 +Subject: [PATCH] Omit KDC indicator check for S4U2Self requests + +As there was no initial ticket exchange from the client for an +S4U2Self request, the auth indicator check is inapplicable (and would +always fail if any auth indicators are required). + +ticket: 8902 (new) +(cherry picked from commit 183631fbf72351c2d5fc7d60b2d9fc4d09fe7465) +(cherry picked from commit 442f1fa5b2e4034954a51048414cc0863b914379) +--- + src/kdc/do_tgs_req.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c +index 241f34e2a..463a9c0dd 100644 +--- a/src/kdc/do_tgs_req.c ++++ b/src/kdc/do_tgs_req.c +@@ -392,8 +392,8 @@ process_tgs_req(krb5_kdc_req *request, krb5_data *pkt, + } + authtime = subject_tkt->times.authtime; + +- /* Extract auth indicators from the subject ticket, except for S4U2Self +- * requests (where the client didn't authenticate). */ ++ /* Extract and check auth indicators from the subject ticket, except for ++ * S4U2Self requests (where the client didn't authenticate). */ + if (s4u_x509_user == NULL) { + errcode = get_auth_indicators(kdc_context, subject_tkt, local_tgt, + &local_tgt_key, &auth_indicators); +@@ -401,12 +401,12 @@ process_tgs_req(krb5_kdc_req *request, krb5_data *pkt, + status = "GET_AUTH_INDICATORS"; + goto cleanup; + } +- } + +- errcode = check_indicators(kdc_context, server, auth_indicators); +- if (errcode) { +- status = "HIGHER_AUTHENTICATION_REQUIRED"; +- goto cleanup; ++ errcode = check_indicators(kdc_context, server, auth_indicators); ++ if (errcode) { ++ status = "HIGHER_AUTHENTICATION_REQUIRED"; ++ goto cleanup; ++ } + } + + if (is_referral) diff --git a/root/ppg/common/deps/krb5/rpm/Omit-PA_FOR_USER-if-we-can-t-compute-its-checksum.patch b/root/ppg/common/deps/krb5/rpm/Omit-PA_FOR_USER-if-we-can-t-compute-its-checksum.patch new file mode 100644 index 00000000..76420e7d --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Omit-PA_FOR_USER-if-we-can-t-compute-its-checksum.patch @@ -0,0 +1,35 @@ +From e1b2c967266b14bc37e5ed11e6c0525bd259e0bb Mon Sep 17 00:00:00 2001 +From: Isaac Boukris +Date: Sat, 6 Jun 2020 11:03:37 +0200 +Subject: [PATCH] Omit PA_FOR_USER if we can't compute its checksum + +OpenSSL in FIPS mode will refuse to perform hmac-md5. Omit the legacy +PA_FOR_USER element in this case rather than failing out. + +[ghudson@mit.edu: minor code and comment edits; wrote commit message] + +ticket: 8912 (new) +(cherry picked from commit 03f122bdb22cfa53c7d855ed929c9541e56365e0) +(cherry picked from commit 086de78292b8ae89aba8a72926831124da44205d) +--- + src/lib/krb5/krb/s4u_creds.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/src/lib/krb5/krb/s4u_creds.c b/src/lib/krb5/krb/s4u_creds.c +index fc5c886d6..d8f486dc6 100644 +--- a/src/lib/krb5/krb/s4u_creds.c ++++ b/src/lib/krb5/krb/s4u_creds.c +@@ -534,6 +534,13 @@ krb5_get_self_cred_from_kdc(krb5_context context, + if (s4u_user.user_id.user != NULL && s4u_user.user_id.user->length) { + code = build_pa_for_user(context, tgtptr, &s4u_user.user_id, + &in_padata[1]); ++ /* ++ * If we couldn't compute the hmac-md5 checksum, send only the ++ * KRB5_PADATA_S4U_X509_USER; this will still work against modern ++ * Windows and MIT KDCs. ++ */ ++ if (code == KRB5_CRYPTO_INTERNAL) ++ code = 0; + if (code != 0) { + krb5_free_pa_data(context, in_padata); + goto cleanup; diff --git a/root/ppg/common/deps/krb5/rpm/Pass-channel-bindings-through-SPNEGO.patch b/root/ppg/common/deps/krb5/rpm/Pass-channel-bindings-through-SPNEGO.patch new file mode 100644 index 00000000..f802acad --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Pass-channel-bindings-through-SPNEGO.patch @@ -0,0 +1,257 @@ +From 6265b0fbc59e13756364b97a5e3e8672514f8302 Mon Sep 17 00:00:00 2001 +From: Isaac Boukris +Date: Tue, 28 Apr 2020 18:15:55 +0200 +Subject: [PATCH] Pass channel bindings through SPNEGO + +ticket: 8907 (new) +(cherry picked from commit d16325a24c34ec9a5f6fb4910987f162e0d4d9cd) +(cherry picked from commit ee79bd43005245d3e5a2d3ec6d61146945e77717) +--- + src/lib/gssapi/spnego/gssapiP_negoex.h | 8 ++--- + src/lib/gssapi/spnego/negoex_ctx.c | 34 +++++++++++---------- + src/lib/gssapi/spnego/spnego_mech.c | 41 +++++++++++++------------- + 3 files changed, 43 insertions(+), 40 deletions(-) + +diff --git a/src/lib/gssapi/spnego/gssapiP_negoex.h b/src/lib/gssapi/spnego/gssapiP_negoex.h +index 44b08f523..489ab7c42 100644 +--- a/src/lib/gssapi/spnego/gssapiP_negoex.h ++++ b/src/lib/gssapi/spnego/gssapiP_negoex.h +@@ -201,10 +201,10 @@ negoex_restrict_auth_schemes(spnego_gss_ctx_id_t ctx, + OM_uint32 + negoex_init(OM_uint32 *minor, spnego_gss_ctx_id_t ctx, gss_cred_id_t cred, + gss_name_t target_name, OM_uint32 req_flags, OM_uint32 time_req, +- gss_buffer_t input_token, gss_buffer_t output_token, +- OM_uint32 *time_rec); ++ gss_buffer_t input_token, gss_channel_bindings_t bindings, ++ gss_buffer_t output_token, OM_uint32 *time_rec); + + OM_uint32 + negoex_accept(OM_uint32 *minor, spnego_gss_ctx_id_t ctx, gss_cred_id_t cred, +- gss_buffer_t input_token, gss_buffer_t output_token, +- OM_uint32 *time_rec); ++ gss_buffer_t input_token, gss_channel_bindings_t bindings, ++ gss_buffer_t output_token, OM_uint32 *time_rec); +diff --git a/src/lib/gssapi/spnego/negoex_ctx.c b/src/lib/gssapi/spnego/negoex_ctx.c +index 18d9d4147..8848ee4db 100644 +--- a/src/lib/gssapi/spnego/negoex_ctx.c ++++ b/src/lib/gssapi/spnego/negoex_ctx.c +@@ -276,7 +276,8 @@ static OM_uint32 + mech_init(OM_uint32 *minor, spnego_gss_ctx_id_t ctx, gss_cred_id_t cred, + gss_name_t target, OM_uint32 req_flags, OM_uint32 time_req, + struct negoex_message *messages, size_t nmessages, +- gss_buffer_t output_token, OM_uint32 *time_rec) ++ gss_channel_bindings_t bindings, gss_buffer_t output_token, ++ OM_uint32 *time_rec) + { + OM_uint32 major, first_major = 0, first_minor = 0; + struct negoex_auth_mech *mech = NULL; +@@ -316,10 +317,9 @@ mech_init(OM_uint32 *minor, spnego_gss_ctx_id_t ctx, gss_cred_id_t cred, + mech = K5_TAILQ_FIRST(&ctx->negoex_mechs); + + major = gss_init_sec_context(minor, cred, &mech->mech_context, target, +- mech->oid, req_flags, time_req, +- GSS_C_NO_CHANNEL_BINDINGS, input_token, +- &ctx->actual_mech, output_token, +- &ctx->ctx_flags, time_rec); ++ mech->oid, req_flags, time_req, bindings, ++ input_token, &ctx->actual_mech, ++ output_token, &ctx->ctx_flags, time_rec); + + if (major == GSS_S_COMPLETE) + mech->complete = 1; +@@ -351,7 +351,8 @@ mech_init(OM_uint32 *minor, spnego_gss_ctx_id_t ctx, gss_cred_id_t cred, + static OM_uint32 + mech_accept(OM_uint32 *minor, spnego_gss_ctx_id_t ctx, + gss_cred_id_t cred, struct negoex_message *messages, +- size_t nmessages, gss_buffer_t output_token, OM_uint32 *time_rec) ++ size_t nmessages, gss_channel_bindings_t bindings, ++ gss_buffer_t output_token, OM_uint32 *time_rec) + { + OM_uint32 major, tmpmin; + struct negoex_auth_mech *mech; +@@ -395,10 +396,10 @@ mech_accept(OM_uint32 *minor, spnego_gss_ctx_id_t ctx, + gss_release_cred(&tmpmin, &ctx->deleg_cred); + + major = gss_accept_sec_context(minor, &mech->mech_context, cred, +- &msg->token, GSS_C_NO_CHANNEL_BINDINGS, +- &ctx->internal_name, &ctx->actual_mech, +- output_token, &ctx->ctx_flags, +- time_rec, &ctx->deleg_cred); ++ &msg->token, bindings, &ctx->internal_name, ++ &ctx->actual_mech, output_token, ++ &ctx->ctx_flags, time_rec, ++ &ctx->deleg_cred); + + if (major == GSS_S_COMPLETE) + mech->complete = 1; +@@ -609,8 +610,8 @@ make_output_token(OM_uint32 *minor, spnego_gss_ctx_id_t ctx, + OM_uint32 + negoex_init(OM_uint32 *minor, spnego_gss_ctx_id_t ctx, gss_cred_id_t cred, + gss_name_t target_name, OM_uint32 req_flags, OM_uint32 time_req, +- gss_buffer_t input_token, gss_buffer_t output_token, +- OM_uint32 *time_rec) ++ gss_buffer_t input_token, gss_channel_bindings_t bindings, ++ gss_buffer_t output_token, OM_uint32 *time_rec) + { + OM_uint32 major, tmpmin; + gss_buffer_desc mech_output_token = GSS_C_EMPTY_BUFFER; +@@ -663,7 +664,8 @@ negoex_init(OM_uint32 *minor, spnego_gss_ctx_id_t ctx, gss_cred_id_t cred, + /* Process the input token and/or produce an output token. This may prune + * the mech list, but on success there will be at least one mech entry. */ + major = mech_init(minor, ctx, cred, target_name, req_flags, time_req, +- messages, nmessages, &mech_output_token, time_rec); ++ messages, nmessages, bindings, &mech_output_token, ++ time_rec); + if (major != GSS_S_COMPLETE) + goto cleanup; + assert(!K5_TAILQ_EMPTY(&ctx->negoex_mechs)); +@@ -701,8 +703,8 @@ cleanup: + + OM_uint32 + negoex_accept(OM_uint32 *minor, spnego_gss_ctx_id_t ctx, gss_cred_id_t cred, +- gss_buffer_t input_token, gss_buffer_t output_token, +- OM_uint32 *time_rec) ++ gss_buffer_t input_token, gss_channel_bindings_t bindings, ++ gss_buffer_t output_token, OM_uint32 *time_rec) + { + OM_uint32 major, tmpmin; + gss_buffer_desc mech_output_token = GSS_C_EMPTY_BUFFER; +@@ -754,7 +756,7 @@ negoex_accept(OM_uint32 *minor, spnego_gss_ctx_id_t ctx, gss_cred_id_t cred, + * prune the list to a single mech. Continue on error if an output token + * is generated, so that we send the token to the initiator. + */ +- major = mech_accept(minor, ctx, cred, messages, nmessages, ++ major = mech_accept(minor, ctx, cred, messages, nmessages, bindings, + &mech_output_token, time_rec); + if (major != GSS_S_COMPLETE && mech_output_token.length == 0) + goto cleanup; +diff --git a/src/lib/gssapi/spnego/spnego_mech.c b/src/lib/gssapi/spnego/spnego_mech.c +index 594fc5894..4cf011143 100644 +--- a/src/lib/gssapi/spnego/spnego_mech.c ++++ b/src/lib/gssapi/spnego/spnego_mech.c +@@ -130,6 +130,7 @@ init_ctx_reselect(OM_uint32 *, spnego_gss_ctx_id_t, OM_uint32, + static OM_uint32 + init_ctx_call_init(OM_uint32 *, spnego_gss_ctx_id_t, spnego_gss_cred_id_t, + OM_uint32, gss_name_t, OM_uint32, OM_uint32, gss_buffer_t, ++ gss_channel_bindings_t, + gss_buffer_t, OM_uint32 *, send_token_flag *); + + static OM_uint32 +@@ -144,8 +145,8 @@ acc_ctx_vfy_oid(OM_uint32 *, spnego_gss_ctx_id_t, gss_OID, + OM_uint32 *, send_token_flag *); + static OM_uint32 + acc_ctx_call_acc(OM_uint32 *, spnego_gss_ctx_id_t, spnego_gss_cred_id_t, +- gss_buffer_t, gss_buffer_t, OM_uint32 *, OM_uint32 *, +- send_token_flag *); ++ gss_buffer_t, gss_channel_bindings_t, gss_buffer_t, ++ OM_uint32 *, OM_uint32 *, send_token_flag *); + + static gss_OID + negotiate_mech(spnego_gss_ctx_id_t, gss_OID_set, OM_uint32 *); +@@ -905,6 +906,7 @@ init_ctx_call_init(OM_uint32 *minor_status, + OM_uint32 req_flags, + OM_uint32 time_req, + gss_buffer_t mechtok_in, ++ gss_channel_bindings_t bindings, + gss_buffer_t mechtok_out, + OM_uint32 *time_rec, + send_token_flag *send_token) +@@ -921,15 +923,14 @@ init_ctx_call_init(OM_uint32 *minor_status, + if (gss_oid_equal(sc->internal_mech, &negoex_mech)) { + ret = negoex_init(minor_status, sc, mcred, target_name, + mech_req_flags, time_req, mechtok_in, +- mechtok_out, time_rec); ++ bindings, mechtok_out, time_rec); + } else { + ret = gss_init_sec_context(minor_status, mcred, + &sc->ctx_handle, target_name, + sc->internal_mech, mech_req_flags, +- time_req, GSS_C_NO_CHANNEL_BINDINGS, +- mechtok_in, &sc->actual_mech, +- mechtok_out, &sc->ctx_flags, +- time_rec); ++ time_req, bindings, mechtok_in, ++ &sc->actual_mech, mechtok_out, ++ &sc->ctx_flags, time_rec); + } + + /* Bail out if the acceptor gave us an error token but the mech didn't +@@ -981,8 +982,8 @@ init_ctx_call_init(OM_uint32 *minor_status, + gss_delete_sec_context(&tmpmin, &sc->ctx_handle, GSS_C_NO_BUFFER); + tmpret = init_ctx_call_init(&tmpmin, sc, spcred, acc_negState, + target_name, req_flags, time_req, +- mechtok_in, mechtok_out, time_rec, +- send_token); ++ mechtok_in, bindings, mechtok_out, ++ time_rec, send_token); + if (HARD_ERROR(tmpret)) + goto fail; + *minor_status = tmpmin; +@@ -1004,7 +1005,7 @@ spnego_gss_init_sec_context( + gss_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, +- gss_channel_bindings_t input_chan_bindings, ++ gss_channel_bindings_t bindings, + gss_buffer_t input_token, + gss_OID *actual_mech, + gss_buffer_t output_token, +@@ -1084,8 +1085,8 @@ spnego_gss_init_sec_context( + if (!spnego_ctx->mech_complete) { + ret = init_ctx_call_init(minor_status, spnego_ctx, spcred, + acc_negState, target_name, req_flags, +- time_req, mechtok_in, &mechtok_out, +- time_rec, &send_token); ++ time_req, mechtok_in, bindings, ++ &mechtok_out, time_rec, &send_token); + if (ret != GSS_S_COMPLETE) + goto cleanup; + +@@ -1542,8 +1543,9 @@ cleanup: + static OM_uint32 + acc_ctx_call_acc(OM_uint32 *minor_status, spnego_gss_ctx_id_t sc, + spnego_gss_cred_id_t spcred, gss_buffer_t mechtok_in, +- gss_buffer_t mechtok_out, OM_uint32 *time_rec, +- OM_uint32 *negState, send_token_flag *tokflag) ++ gss_channel_bindings_t bindings, gss_buffer_t mechtok_out, ++ OM_uint32 *time_rec, OM_uint32 *negState, ++ send_token_flag *tokflag) + { + OM_uint32 ret, tmpmin; + gss_OID_desc mechoid; +@@ -1568,13 +1570,12 @@ acc_ctx_call_acc(OM_uint32 *minor_status, spnego_gss_ctx_id_t sc, + mcred = (spcred == NULL) ? GSS_C_NO_CREDENTIAL : spcred->mcred; + if (negoex) { + ret = negoex_accept(minor_status, sc, mcred, mechtok_in, +- mechtok_out, time_rec); ++ bindings, mechtok_out, time_rec); + } else { + (void) gss_release_name(&tmpmin, &sc->internal_name); + (void) gss_release_cred(&tmpmin, &sc->deleg_cred); + ret = gss_accept_sec_context(minor_status, &sc->ctx_handle, +- mcred, mechtok_in, +- GSS_C_NO_CHANNEL_BINDINGS, ++ mcred, mechtok_in, bindings, + &sc->internal_name, + &sc->actual_mech, mechtok_out, + &sc->ctx_flags, time_rec, +@@ -1620,7 +1621,7 @@ spnego_gss_accept_sec_context( + gss_ctx_id_t *context_handle, + gss_cred_id_t verifier_cred_handle, + gss_buffer_t input_token, +- gss_channel_bindings_t input_chan_bindings, ++ gss_channel_bindings_t bindings, + gss_name_t *src_name, + gss_OID *mech_type, + gss_buffer_t output_token, +@@ -1734,8 +1735,8 @@ spnego_gss_accept_sec_context( + */ + if (negState != REQUEST_MIC && mechtok_in != GSS_C_NO_BUFFER) { + ret = acc_ctx_call_acc(minor_status, sc, spcred, mechtok_in, +- &mechtok_out, time_rec, &negState, +- &return_token); ++ bindings, &mechtok_out, time_rec, ++ &negState, &return_token); + } + + /* Step 3: process or generate the MIC, if the negotiated mech is diff --git a/root/ppg/common/deps/krb5/rpm/Pass-gss_localname-through-SPNEGO.patch b/root/ppg/common/deps/krb5/rpm/Pass-gss_localname-through-SPNEGO.patch new file mode 100644 index 00000000..fd47b3f1 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Pass-gss_localname-through-SPNEGO.patch @@ -0,0 +1,59 @@ +From e57cdf6610f0b7c8ac38f9b2342b74b8c9e5bc54 Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Sun, 26 Apr 2020 19:55:54 -0400 +Subject: [PATCH] Pass gss_localname() through SPNEGO + +ticket: 8897 (new) +(cherry picked from commit f7b8a6432bd289bdc528017be122305f95b8e285) +(cherry picked from commit 646212314a580a8cdffdacda9cb3c8f806471b08) +--- + src/lib/gssapi/spnego/gssapiP_spnego.h | 8 ++++++++ + src/lib/gssapi/spnego/spnego_mech.c | 9 ++++++++- + 2 files changed, 16 insertions(+), 1 deletion(-) + +diff --git a/src/lib/gssapi/spnego/gssapiP_spnego.h b/src/lib/gssapi/spnego/gssapiP_spnego.h +index a93763314..066ec736f 100644 +--- a/src/lib/gssapi/spnego/gssapiP_spnego.h ++++ b/src/lib/gssapi/spnego/gssapiP_spnego.h +@@ -357,6 +357,14 @@ OM_uint32 KRB5_CALLCONV spnego_gss_wrap_size_limit + OM_uint32 *max_input_size + ); + ++OM_uint32 KRB5_CALLCONV spnego_gss_localname ++( ++ OM_uint32 *minor_status, ++ const gss_name_t pname, ++ const gss_const_OID mech_type, ++ gss_buffer_t localname ++); ++ + OM_uint32 KRB5_CALLCONV spnego_gss_get_mic + ( + OM_uint32 *minor_status, +diff --git a/src/lib/gssapi/spnego/spnego_mech.c b/src/lib/gssapi/spnego/spnego_mech.c +index ec0bae6a4..594fc5894 100644 +--- a/src/lib/gssapi/spnego/spnego_mech.c ++++ b/src/lib/gssapi/spnego/spnego_mech.c +@@ -237,7 +237,7 @@ static struct gss_config spnego_mechanism = + spnego_gss_inquire_context, /* gss_inquire_context */ + NULL, /* gss_internal_release_oid */ + spnego_gss_wrap_size_limit, /* gss_wrap_size_limit */ +- NULL, /* gssd_pname_to_uid */ ++ spnego_gss_localname, + NULL, /* gss_userok */ + NULL, /* gss_export_name */ + spnego_gss_duplicate_name, /* gss_duplicate_name */ +@@ -2371,6 +2371,13 @@ spnego_gss_wrap_size_limit( + return (ret); + } + ++OM_uint32 KRB5_CALLCONV ++spnego_gss_localname(OM_uint32 *minor_status, const gss_name_t pname, ++ const gss_const_OID mech_type, gss_buffer_t localname) ++{ ++ return gss_localname(minor_status, pname, GSS_C_NO_OID, localname); ++} ++ + OM_uint32 KRB5_CALLCONV + spnego_gss_get_mic( + OM_uint32 *minor_status, diff --git a/root/ppg/common/deps/krb5/rpm/Prevent-overflow-when-calculating-ulog-block-size.patch b/root/ppg/common/deps/krb5/rpm/Prevent-overflow-when-calculating-ulog-block-size.patch new file mode 100644 index 00000000..4e3b39ef --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Prevent-overflow-when-calculating-ulog-block-size.patch @@ -0,0 +1,64 @@ +From 105ba83436476f5a08759b8e97bfb0c5a69596b9 Mon Sep 17 00:00:00 2001 +From: Zoltan Borbely +Date: Tue, 28 Jan 2025 16:39:25 -0500 +Subject: [PATCH] Prevent overflow when calculating ulog block size + +In kdb_log.c:resize(), log an error and fail if the update size is +larger than the largest possible block size (2^16-1). + +CVE-2025-24528: + +In MIT krb5 release 1.7 and later with incremental propagation +enabled, an authenticated attacker can cause kadmind to write beyond +the end of the mapped region for the iprop log file, likely causing a +process crash. + +[ghudson@mit.edu: edited commit message and added CVE description] + +ticket: 9159 (new) +tags: pullup +target_version: 1.21-next + +(cherry picked from commit 78ceba024b64d49612375be4a12d1c066b0bfbd0) +--- + src/lib/kdb/kdb_log.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/src/lib/kdb/kdb_log.c b/src/lib/kdb/kdb_log.c +index e9b95fce59..c805ebd988 100644 +--- a/src/lib/kdb/kdb_log.c ++++ b/src/lib/kdb/kdb_log.c +@@ -183,7 +183,7 @@ extend_file_to(int fd, unsigned int new_size) + */ + static krb5_error_code + resize(kdb_hlog_t *ulog, uint32_t ulogentries, int ulogfd, +- unsigned int recsize) ++ unsigned int recsize, const kdb_incr_update_t *upd) + { + unsigned int new_block, new_size; + +@@ -195,6 +195,12 @@ resize(kdb_hlog_t *ulog, uint32_t ulogentries, int ulogfd, + new_block *= ULOG_BLOCK; + new_size += ulogentries * new_block; + ++ if (new_block > UINT16_MAX) { ++ syslog(LOG_ERR, _("ulog overflow caused by principal %.*s"), ++ upd->kdb_princ_name.utf8str_t_len, ++ upd->kdb_princ_name.utf8str_t_val); ++ return KRB5_LOG_ERROR; ++ } + if (new_size > MAXLOGLEN) + return KRB5_LOG_ERROR; + +@@ -291,7 +297,7 @@ store_update(kdb_log_context *log_ctx, kdb_incr_update_t *upd) + recsize = sizeof(kdb_ent_header_t) + upd_size; + + if (recsize > ulog->kdb_block) { +- retval = resize(ulog, ulogentries, log_ctx->ulogfd, recsize); ++ retval = resize(ulog, ulogentries, log_ctx->ulogfd, recsize, upd); + if (retval) + return retval; + } +-- +2.48.1 + diff --git a/root/ppg/common/deps/krb5/rpm/Refactor-krb5-GSS-checksum-handling.patch b/root/ppg/common/deps/krb5/rpm/Refactor-krb5-GSS-checksum-handling.patch new file mode 100644 index 00000000..d952f415 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Refactor-krb5-GSS-checksum-handling.patch @@ -0,0 +1,480 @@ +From 4f14a2f48b52e59c472847a5522fd0cf52927755 Mon Sep 17 00:00:00 2001 +From: Alexander Scheel +Date: Fri, 30 Jun 2017 16:03:01 -0400 +Subject: [PATCH] Refactor krb5 GSS checksum handling + +Separate out checksum handling from kg_accept_krb5() into a new helper +process_checksum(). + +[ghudson@mit.edu: simplified checksum processing and made it use +k5-input.h instead of TREAD_ macros; moved more flag handling into +helper] + +[iboukris: adjusted helper function arguments, allowing access to the +full authenticator for subsequent changes] + +(cherry picked from commit 64d56233f9816a2a93f6e8d3030c8ed6ce397735) +[rharwood@redhat.com: problem with typo fix commit, I think] +(cherry picked from commit a34b7c50e62c19f80d39ece6a72017dac781df64) +--- + src/lib/gssapi/krb5/accept_sec_context.c | 383 +++++++++++------------ + 1 file changed, 179 insertions(+), 204 deletions(-) + +diff --git a/src/lib/gssapi/krb5/accept_sec_context.c b/src/lib/gssapi/krb5/accept_sec_context.c +index c5bddb1e8..70dd7fc0c 100644 +--- a/src/lib/gssapi/krb5/accept_sec_context.c ++++ b/src/lib/gssapi/krb5/accept_sec_context.c +@@ -98,6 +98,7 @@ + */ + + #include "k5-int.h" ++#include "k5-input.h" + #include "gssapiP_krb5.h" + #ifdef HAVE_MEMORY_H + #include +@@ -413,6 +414,174 @@ kg_process_extension(krb5_context context, + return code; + } + ++/* The length of the MD5 channel bindings in an 0x8003 checksum */ ++#define CB_MD5_LEN 16 ++ ++/* The minimum length of an 0x8003 checksum value (4-byte channel bindings ++ * length, 16-byte channel bindings, 4-byte flags) */ ++#define MIN_8003_LEN (4 + CB_MD5_LEN + 4) ++ ++/* The flags we accept from the initiator's authenticator checksum. */ ++#define INITIATOR_FLAGS (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG | \ ++ GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | \ ++ GSS_C_SEQUENCE_FLAG | GSS_C_DCE_STYLE | \ ++ GSS_C_IDENTIFY_FLAG | GSS_C_EXTENDED_ERROR_FLAG) ++ ++/* ++ * The krb5 GSS mech appropriates the authenticator checksum field from RFC ++ * 4120 to store structured data instead of a checksum, indicated with checksum ++ * type 0x8003 (see RFC 4121 section 4.1.1). Some implementations instead send ++ * no checksum, or a regular checksum over empty data. ++ * ++ * Interpret the checksum. Read delegated creds into *deleg_out if it is not ++ * NULL. Set *flags_out to the allowed subset of token flags, plus ++ * GSS_C_DELEG_FLAG if a delegated credential was present. Process any ++ * extensions found using exts. On error, set *code_out to a krb5_error code ++ * for use as a minor status value. ++ */ ++static OM_uint32 ++process_checksum(OM_uint32 *minor_status, krb5_context context, ++ gss_channel_bindings_t acceptor_cb, ++ krb5_auth_context auth_context, krb5_flags ap_req_options, ++ krb5_authenticator *authenticator, krb5_gss_ctx_ext_t exts, ++ krb5_gss_cred_id_t *deleg_out, krb5_ui_4 *flags_out, ++ krb5_error_code *code_out) ++{ ++ krb5_error_code code = 0; ++ OM_uint32 status, option_id, token_flags; ++ size_t cb_len, option_len; ++ krb5_boolean valid; ++ krb5_key subkey; ++ krb5_data option, empty = empty_data(); ++ krb5_checksum cb_cksum; ++ const uint8_t *token_cb, *option_bytes; ++ struct k5input in; ++ const krb5_checksum *cksum = authenticator->checksum; ++ ++ cb_cksum.contents = NULL; ++ ++ if (cksum == NULL) { ++ /* ++ * Some SMB client implementations use handcrafted GSSAPI code that ++ * does not provide a checksum. MS-KILE documents that the Microsoft ++ * implementation considers a missing checksum acceptable; the server ++ * assumes all flags are unset in this case, and does not check channel ++ * bindings. ++ */ ++ *flags_out = 0; ++ } else if (cksum->checksum_type != CKSUMTYPE_KG_CB) { ++ /* Samba sends a regular checksum. */ ++ code = krb5_auth_con_getkey_k(context, auth_context, &subkey); ++ if (code) { ++ status = GSS_S_FAILURE; ++ goto fail; ++ } ++ ++ /* Verifying the checksum ensures that this authenticator wasn't ++ * replayed from one with a checksum over actual data. */ ++ code = krb5_k_verify_checksum(context, subkey, ++ KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM, &empty, ++ cksum, &valid); ++ krb5_k_free_key(context, subkey); ++ if (code || !valid) { ++ status = GSS_S_BAD_SIG; ++ goto fail; ++ } ++ ++ /* Use ap_options from the request to guess the mutual flag. */ ++ *flags_out = GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG; ++ if (ap_req_options & AP_OPTS_MUTUAL_REQUIRED) ++ *flags_out |= GSS_C_MUTUAL_FLAG; ++ } else { ++ /* The checksum must contain at least a fixed 24-byte part. */ ++ if (cksum->length < MIN_8003_LEN) { ++ status = GSS_S_BAD_BINDINGS; ++ goto fail; ++ } ++ ++ k5_input_init(&in, cksum->contents, cksum->length); ++ cb_len = k5_input_get_uint32_le(&in); ++ if (cb_len != CB_MD5_LEN) { ++ code = KG_BAD_LENGTH; ++ status = GSS_S_FAILURE; ++ goto fail; ++ } ++ ++ token_cb = k5_input_get_bytes(&in, cb_len); ++ if (acceptor_cb != GSS_C_NO_CHANNEL_BINDINGS) { ++ code = kg_checksum_channel_bindings(context, acceptor_cb, ++ &cb_cksum); ++ if (code) { ++ status = GSS_S_BAD_BINDINGS; ++ goto fail; ++ } ++ assert(cb_cksum.length == cb_len); ++ if (k5_bcmp(token_cb, cb_cksum.contents, cb_len) != 0) { ++ status = GSS_S_BAD_BINDINGS; ++ goto fail; ++ } ++ } ++ ++ /* Read the token flags and accept some of them as context flags. */ ++ token_flags = k5_input_get_uint32_le(&in); ++ *flags_out = token_flags & INITIATOR_FLAGS; ++ ++ /* Read the delegated credential if present. */ ++ if (in.len >= 4 && (token_flags & GSS_C_DELEG_FLAG)) { ++ option_id = k5_input_get_uint16_le(&in); ++ option_len = k5_input_get_uint16_le(&in); ++ option_bytes = k5_input_get_bytes(&in, option_len); ++ option = make_data((uint8_t *)option_bytes, option_len); ++ if (in.status) { ++ code = KG_BAD_LENGTH; ++ status = GSS_S_FAILURE; ++ goto fail; ++ } ++ if (option_id != KRB5_GSS_FOR_CREDS_OPTION) { ++ status = GSS_S_FAILURE; ++ goto fail; ++ } ++ ++ /* Store the delegated credential. */ ++ code = rd_and_store_for_creds(context, auth_context, &option, ++ deleg_out); ++ if (code) { ++ status = GSS_S_FAILURE; ++ goto fail; ++ } ++ *flags_out |= GSS_C_DELEG_FLAG; ++ } ++ ++ /* Process any extensions at the end of the checksum. Extensions use ++ * 4-byte big-endian tag and length instead of 2-byte little-endian. */ ++ while (in.len > 0) { ++ option_id = k5_input_get_uint32_be(&in); ++ option_len = k5_input_get_uint32_be(&in); ++ option_bytes = k5_input_get_bytes(&in, option_len); ++ option = make_data((uint8_t *)option_bytes, option_len); ++ if (in.status) { ++ code = KG_BAD_LENGTH; ++ status = GSS_S_FAILURE; ++ goto fail; ++ } ++ ++ code = kg_process_extension(context, auth_context, option_id, ++ &option, exts); ++ if (code) { ++ status = GSS_S_FAILURE; ++ goto fail; ++ } ++ } ++ } ++ ++ status = GSS_S_COMPLETE; ++ ++fail: ++ free(cb_cksum.contents); ++ *code_out = code; ++ return status; ++} ++ + static OM_uint32 + kg_accept_krb5(minor_status, context_handle, + verifier_cred_handle, input_token, +@@ -433,17 +602,13 @@ kg_accept_krb5(minor_status, context_handle, + krb5_gss_ctx_ext_t exts; + { + krb5_context context; +- unsigned char *ptr, *ptr2; ++ unsigned char *ptr; + char *sptr; +- OM_uint32 tmp; +- size_t md5len; + krb5_gss_cred_id_t cred = 0; + krb5_data ap_rep, ap_req; +- unsigned int i; + krb5_error_code code; + krb5_address addr, *paddr; + krb5_authenticator *authdat = 0; +- krb5_checksum reqcksum; + krb5_gss_name_t name = NULL; + krb5_ui_4 gss_flags = 0; + krb5_gss_ctx_id_rec *ctx = NULL; +@@ -451,8 +616,6 @@ kg_accept_krb5(minor_status, context_handle, + gss_buffer_desc token; + krb5_auth_context auth_context = NULL; + krb5_ticket * ticket = NULL; +- int option_id; +- krb5_data option; + const gss_OID_desc *mech_used = NULL; + OM_uint32 major_status = GSS_S_FAILURE; + OM_uint32 tmp_minor_status; +@@ -463,7 +626,6 @@ kg_accept_krb5(minor_status, context_handle, + krb5int_access kaccess; + int cred_rcache = 0; + int no_encap = 0; +- int token_deleg_flag = 0; + krb5_flags ap_req_options = 0; + krb5_enctype negotiated_etype; + krb5_authdata_context ad_context = NULL; +@@ -489,7 +651,6 @@ kg_accept_krb5(minor_status, context_handle, + output_token->length = 0; + output_token->value = NULL; + token.value = 0; +- reqcksum.contents = 0; + ap_req.data = 0; + ap_rep.data = 0; + +@@ -654,195 +815,16 @@ kg_accept_krb5(minor_status, context_handle, + + krb5_auth_con_getauthenticator(context, auth_context, &authdat); + +- if (authdat->checksum == NULL) { +- /* +- * Some SMB client implementations use handcrafted GSSAPI code that +- * does not provide a checksum. MS-KILE documents that the Microsoft +- * implementation considers a missing checksum acceptable; the server +- * assumes all flags are unset in this case, and does not check channel +- * bindings. +- */ +- gss_flags = 0; +- } else if (authdat->checksum->checksum_type != CKSUMTYPE_KG_CB) { +- /* Samba does not send 0x8003 GSS-API checksums */ +- krb5_boolean valid; +- krb5_key subkey; +- krb5_data zero; ++ major_status = process_checksum(minor_status, context, input_chan_bindings, ++ auth_context, ap_req_options, ++ authdat, exts, ++ delegated_cred_handle ? &deleg_cred : NULL, ++ &gss_flags, &code); + +- code = krb5_auth_con_getkey_k(context, auth_context, &subkey); +- if (code) { +- major_status = GSS_S_FAILURE; +- goto fail; +- } ++ if (major_status != GSS_S_COMPLETE) ++ goto fail; + +- zero.length = 0; +- zero.data = ""; +- +- code = krb5_k_verify_checksum(context, +- subkey, +- KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM, +- &zero, +- authdat->checksum, +- &valid); +- krb5_k_free_key(context, subkey); +- if (code || !valid) { +- major_status = GSS_S_BAD_SIG; +- goto fail; +- } +- +- /* Use ap_options from the request to guess the mutual flag. */ +- gss_flags = GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG; +- if (ap_req_options & AP_OPTS_MUTUAL_REQUIRED) +- gss_flags |= GSS_C_MUTUAL_FLAG; +- } else { +- /* gss krb5 v1 */ +- +- /* stash this now, for later. */ +- code = krb5_c_checksum_length(context, CKSUMTYPE_RSA_MD5, &md5len); +- if (code) { +- major_status = GSS_S_FAILURE; +- goto fail; +- } +- +- /* verify that the checksum is correct */ +- +- /* +- The checksum may be either exactly 24 bytes, in which case +- no options are specified, or greater than 24 bytes, in which case +- one or more options are specified. Currently, the only valid +- option is KRB5_GSS_FOR_CREDS_OPTION ( = 1 ). +- */ +- +- if ((authdat->checksum->checksum_type != CKSUMTYPE_KG_CB) || +- (authdat->checksum->length < 24)) { +- code = 0; +- major_status = GSS_S_BAD_BINDINGS; +- goto fail; +- } +- +- ptr = (unsigned char *) authdat->checksum->contents; +- +- TREAD_INT(ptr, tmp, 0); +- +- if (tmp != md5len) { +- code = KG_BAD_LENGTH; +- major_status = GSS_S_FAILURE; +- goto fail; +- } +- +- /* +- The following section of code attempts to implement the +- optional channel binding facility as described in RFC2743. +- +- Since this facility is optional channel binding may or may +- not have been provided by either the client or the server. +- +- If the server has specified input_chan_bindings equal to +- GSS_C_NO_CHANNEL_BINDINGS then we skip the check. If +- the server does provide channel bindings then we compute +- a checksum and compare against those provided by the +- client. */ +- +- if ((code = kg_checksum_channel_bindings(context, +- input_chan_bindings, +- &reqcksum))) { +- major_status = GSS_S_BAD_BINDINGS; +- goto fail; +- } +- +- /* Always read the clients bindings - eventhough we might ignore them */ +- TREAD_STR(ptr, ptr2, reqcksum.length); +- +- if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS ) { +- if (memcmp(ptr2, reqcksum.contents, reqcksum.length) != 0) { +- xfree(reqcksum.contents); +- reqcksum.contents = 0; +- code = 0; +- major_status = GSS_S_BAD_BINDINGS; +- goto fail; +- } +- +- } +- +- xfree(reqcksum.contents); +- reqcksum.contents = 0; +- +- /* Read the token flags. Remember if GSS_C_DELEG_FLAG was set, but +- * mask it out until we actually read a delegated credential. */ +- TREAD_INT(ptr, gss_flags, 0); +- token_deleg_flag = (gss_flags & GSS_C_DELEG_FLAG); +- gss_flags &= ~GSS_C_DELEG_FLAG; +- +- /* if the checksum length > 24, there are options to process */ +- +- i = authdat->checksum->length - 24; +- if (i && token_deleg_flag) { +- if (i >= 4) { +- TREAD_INT16(ptr, option_id, 0); +- TREAD_INT16(ptr, option.length, 0); +- i -= 4; +- +- if (i < option.length) { +- code = KG_BAD_LENGTH; +- major_status = GSS_S_FAILURE; +- goto fail; +- } +- +- /* have to use ptr2, since option.data is wrong type and +- macro uses ptr as both lvalue and rvalue */ +- +- TREAD_STR(ptr, ptr2, option.length); +- option.data = (char *) ptr2; +- +- i -= option.length; +- +- if (option_id != KRB5_GSS_FOR_CREDS_OPTION) { +- major_status = GSS_S_FAILURE; +- goto fail; +- } +- +- /* store the delegated credential */ +- +- code = rd_and_store_for_creds(context, auth_context, &option, +- (delegated_cred_handle) ? +- &deleg_cred : NULL); +- if (code) { +- major_status = GSS_S_FAILURE; +- goto fail; +- } +- +- gss_flags |= GSS_C_DELEG_FLAG; +- } /* if i >= 4 */ +- /* ignore any additional trailing data, for now */ +- } +- while (i > 0) { +- /* Process Type-Length-Data options */ +- if (i < 8) { +- code = KG_BAD_LENGTH; +- major_status = GSS_S_FAILURE; +- goto fail; +- } +- TREAD_INT(ptr, option_id, 1); +- TREAD_INT(ptr, option.length, 1); +- i -= 8; +- if (i < option.length) { +- code = KG_BAD_LENGTH; +- major_status = GSS_S_FAILURE; +- goto fail; +- } +- TREAD_STR(ptr, ptr2, option.length); +- option.data = (char *)ptr2; +- +- i -= option.length; +- +- code = kg_process_extension(context, auth_context, +- option_id, &option, exts); +- if (code != 0) { +- major_status = GSS_S_FAILURE; +- goto fail; +- } +- } +- } ++ major_status = GSS_S_FAILURE; + + if (exts->iakerb.conv && !exts->iakerb.verified) { + major_status = GSS_S_BAD_SIG; +@@ -869,12 +851,7 @@ kg_accept_krb5(minor_status, context_handle, + ctx->mech_used = (gss_OID) mech_used; + ctx->auth_context = auth_context; + ctx->initiate = 0; +- ctx->gss_flags = (GSS_C_TRANS_FLAG | +- ((gss_flags) & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG | +- GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | +- GSS_C_SEQUENCE_FLAG | GSS_C_DELEG_FLAG | +- GSS_C_DCE_STYLE | GSS_C_IDENTIFY_FLAG | +- GSS_C_EXTENDED_ERROR_FLAG))); ++ ctx->gss_flags = gss_flags | GSS_C_TRANS_FLAG; + ctx->seed_init = 0; + ctx->cred_rcache = cred_rcache; + +@@ -1161,8 +1138,6 @@ fail: + + krb5_auth_con_free(context, auth_context); + } +- if (reqcksum.contents) +- xfree(reqcksum.contents); + if (ap_rep.data) + krb5_free_data_contents(context, &ap_rep); + if (major_status == GSS_S_COMPLETE || diff --git a/root/ppg/common/deps/krb5/rpm/Refresh-manually-acquired-creds-from-client-keytab.patch b/root/ppg/common/deps/krb5/rpm/Refresh-manually-acquired-creds-from-client-keytab.patch new file mode 100644 index 00000000..f7091481 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Refresh-manually-acquired-creds-from-client-keytab.patch @@ -0,0 +1,79 @@ +From cb8c8af56d306267d6964da217c65e129fe83c82 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Wed, 26 Feb 2020 18:27:17 -0500 +Subject: [PATCH] Refresh manually acquired creds from client keytab + +If a client keytab is present but credentials are acquired manually, +the credentials would not be refreshed because no refresh_time config +var is set in the cache. Change kg_cred_time_to_refresh() to attempt +a refresh from the client keytab on any credentials which will expire +in the next 30 seconds. + +[ghudson@mit.edu: adjused code and added test case] + +ticket: 7976 +(cherry picked from commit 729896467e3c77904666019d6cbbda583ae49b95) +(cherry picked from commit 685aada9eae420cb5156ca7b71c2c7614c0b6e2c) +--- + src/lib/gssapi/krb5/acquire_cred.c | 14 +++++++++++--- + src/tests/gssapi/t_client_keytab.py | 18 ++++++++++++++++++ + 2 files changed, 29 insertions(+), 3 deletions(-) + +diff --git a/src/lib/gssapi/krb5/acquire_cred.c b/src/lib/gssapi/krb5/acquire_cred.c +index acc1868f8..4062f4741 100644 +--- a/src/lib/gssapi/krb5/acquire_cred.c ++++ b/src/lib/gssapi/krb5/acquire_cred.c +@@ -557,15 +557,23 @@ set_refresh_time(krb5_context context, krb5_ccache ccache, + krb5_boolean + kg_cred_time_to_refresh(krb5_context context, krb5_gss_cred_id_rec *cred) + { +- krb5_timestamp now; ++ krb5_timestamp now, soon; + + if (krb5_timeofday(context, &now)) + return FALSE; ++ soon = ts_incr(now, 30); + if (cred->refresh_time != 0 && !ts_after(cred->refresh_time, now)) { +- set_refresh_time(context, cred->ccache, +- ts_incr(cred->refresh_time, 30)); ++ set_refresh_time(context, cred->ccache, soon); + return TRUE; + } ++ ++ /* If the creds will expire soon, try to refresh even if they weren't ++ * acquired with a client keytab. */ ++ if (ts_after(soon, cred->expire)) { ++ set_refresh_time(context, cred->ccache, soon); ++ return TRUE; ++ } ++ + return FALSE; + } + +diff --git a/src/tests/gssapi/t_client_keytab.py b/src/tests/gssapi/t_client_keytab.py +index e474a27c7..7847b3ecd 100755 +--- a/src/tests/gssapi/t_client_keytab.py ++++ b/src/tests/gssapi/t_client_keytab.py +@@ -124,4 +124,22 @@ realm.kinit(realm.user_princ, password('user')) + realm.run(['./t_ccselect', phost], env=bad_cktname, + expected_msg=realm.user_princ) + ++mark('refresh of manually acquired creds') ++ ++# Test 17: no name/ccache specified, manually acquired creds which ++# will expire soon. Verify that creds are refreshed using the current ++# client name, with refresh_time set in the refreshed ccache. ++realm.kinit('bob', password('bob'), ['-l', '15s']) ++realm.run(['./t_ccselect', phost], expected_msg='bob') ++realm.run([klist, '-C'], expected_msg='refresh_time = ') ++ ++# Test 18: no name/ccache specified, manually acquired creds with a ++# client principal not present in the client keytab. A refresh is ++# attempted but fails, and an expired ticket error results. ++realm.kinit(realm.admin_princ, password('admin'), ['-l', '-1s']) ++msgs = ('Getting initial credentials for user/admin@KRBTEST.COM', ++ '/Matching credential not found') ++realm.run(['./t_ccselect', phost], expected_code=1, ++ expected_msg='Ticket expired', expected_trace=msgs) ++ + success('Client keytab tests') diff --git a/root/ppg/common/deps/krb5/rpm/Remove-PKINIT-RSA-support.patch b/root/ppg/common/deps/krb5/rpm/Remove-PKINIT-RSA-support.patch new file mode 100644 index 00000000..2dbaf44b --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Remove-PKINIT-RSA-support.patch @@ -0,0 +1,1299 @@ +From cc31e37cc4f8bbac99ee7eff37e8c25d21343bb7 Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Sun, 26 Nov 2023 17:42:34 -0500 +Subject: [PATCH] Remove PKINIT RSA support + +RSA mode is no longer needed for interoperability. Reduce the attack +surface of clients and KDCs by removing support for it. + +ticket: 9108 (new) +(cherry picked from commit 401f584526e501b68e7516c17d8e467883f8f210) +--- + doc/user/user_commands/kinit.rst | 4 - + src/plugins/preauth/pkinit/pkinit.h | 2 - + src/plugins/preauth/pkinit/pkinit_clnt.c | 242 +++------ + src/plugins/preauth/pkinit/pkinit_crypto.h | 42 -- + .../preauth/pkinit/pkinit_crypto_openssl.c | 487 ------------------ + src/plugins/preauth/pkinit/pkinit_lib.c | 2 - + src/plugins/preauth/pkinit/pkinit_srv.c | 213 +++----- + src/plugins/preauth/pkinit/pkinit_trace.h | 9 - + src/tests/t_pkinit.py | 9 - + src/windows/leash/htmlhelp/html/KINIT.htm | 3 - + 10 files changed, 139 insertions(+), 874 deletions(-) + +diff --git a/doc/user/user_commands/kinit.rst b/doc/user/user_commands/kinit.rst +index e12e88a372..2d67698dac 100644 +--- a/doc/user/user_commands/kinit.rst ++++ b/doc/user/user_commands/kinit.rst +@@ -192,10 +192,6 @@ OPTIONS + **X509_anchors**\ =\ *value* + specify where to find trusted X509 anchor information + +- **flag_RSA_PROTOCOL**\ [**=yes**] +- specify use of RSA, rather than the default Diffie-Hellman +- protocol +- + **disable_freshness**\ [**=yes**] + disable sending freshness tokens (for testing purposes only) + +diff --git a/src/plugins/preauth/pkinit/pkinit.h b/src/plugins/preauth/pkinit/pkinit.h +index b437fd53fb..ab132d78a9 100644 +--- a/src/plugins/preauth/pkinit/pkinit.h ++++ b/src/plugins/preauth/pkinit/pkinit.h +@@ -147,7 +147,6 @@ typedef struct _pkinit_plg_opts { + int require_eku; /* require EKU checking (default is true) */ + int accept_secondary_eku;/* accept secondary EKU (default is false) */ + int allow_upn; /* allow UPN-SAN instead of pkinit-SAN */ +- int dh_or_rsa; /* selects DH or RSA based pkinit */ + int require_crl_checking; /* require CRL for a CA (default is false) */ + int require_freshness; /* require freshness token (default is false) */ + int disable_freshness; /* disable freshness token on client for testing */ +@@ -161,7 +160,6 @@ typedef struct _pkinit_req_opts { + int require_eku; + int accept_secondary_eku; + int allow_upn; +- int dh_or_rsa; + int require_crl_checking; + int dh_size; /* initial request DH modulus size (default=1024) */ + int require_hostname_match; +diff --git a/src/plugins/preauth/pkinit/pkinit_clnt.c b/src/plugins/preauth/pkinit/pkinit_clnt.c +index 021e5f0723..ca0162897b 100644 +--- a/src/plugins/preauth/pkinit/pkinit_clnt.c ++++ b/src/plugins/preauth/pkinit/pkinit_clnt.c +@@ -193,7 +193,6 @@ pkinit_as_req_create(krb5_context context, + krb5_auth_pack auth_pack; + krb5_pa_pk_as_req *req = NULL; + krb5_algorithm_identifier **cmstypes = NULL; +- int protocol = reqctx->opts->dh_or_rsa; + unsigned char *dh_params = NULL, *dh_pubkey = NULL; + unsigned int dh_params_len, dh_pubkey_len; + +@@ -212,35 +211,19 @@ pkinit_as_req_create(krb5_context context, + auth_pack.clientPublicValue = &info; + auth_pack.supportedKDFs = (krb5_data **)supported_kdf_alg_ids; + +- switch(protocol) { +- case DH_PROTOCOL: +- TRACE_PKINIT_CLIENT_REQ_DH(context); +- pkiDebug("as_req: DH key transport algorithm\n"); +- info.algorithm.algorithm = dh_oid; +- +- /* create client-side DH keys */ +- retval = client_create_dh(context, plgctx->cryptoctx, +- reqctx->cryptoctx, reqctx->idctx, +- reqctx->opts->dh_size, &dh_params, +- &dh_params_len, &dh_pubkey, &dh_pubkey_len); +- if (retval != 0) { +- pkiDebug("failed to create dh parameters\n"); +- goto cleanup; +- } +- info.algorithm.parameters = make_data(dh_params, dh_params_len); +- info.subjectPublicKey = make_data(dh_pubkey, dh_pubkey_len); +- break; +- case RSA_PROTOCOL: +- TRACE_PKINIT_CLIENT_REQ_RSA(context); +- pkiDebug("as_req: RSA key transport algorithm\n"); +- auth_pack.clientPublicValue = NULL; +- break; +- default: +- pkiDebug("as_req: unknown key transport protocol %d\n", +- protocol); +- retval = -1; ++ TRACE_PKINIT_CLIENT_REQ_DH(context); ++ info.algorithm.algorithm = dh_oid; ++ ++ /* create client-side DH keys */ ++ retval = client_create_dh(context, plgctx->cryptoctx, reqctx->cryptoctx, ++ reqctx->idctx, reqctx->opts->dh_size, &dh_params, ++ &dh_params_len, &dh_pubkey, &dh_pubkey_len); ++ if (retval != 0) { ++ pkiDebug("failed to create dh parameters\n"); + goto cleanup; + } ++ info.algorithm.parameters = make_data(dh_params, dh_params_len); ++ info.subjectPublicKey = make_data(dh_pubkey, dh_pubkey_len); + + retval = k5int_encode_krb5_auth_pack(&auth_pack, &coded_auth_pack); + if (retval) { +@@ -556,49 +539,33 @@ pkinit_as_rep_parse(krb5_context context, + return retval; + } + +- switch(kdc_reply->choice) { +- case choice_pa_pk_as_rep_dhInfo: +- pkiDebug("as_rep: DH key transport algorithm\n"); ++ if (kdc_reply->choice != choice_pa_pk_as_rep_dhInfo) { ++ pkiDebug("unknown as_rep type %d\n", kdc_reply->choice); ++ retval = KRB5KDC_ERR_PREAUTH_FAILED; ++ goto cleanup; ++ } ++ + #ifdef DEBUG_ASN1 +- print_buffer_bin(kdc_reply->u.dh_Info.dhSignedData.data, +- kdc_reply->u.dh_Info.dhSignedData.length, "/tmp/client_kdc_signeddata"); ++ print_buffer_bin(kdc_reply->u.dh_Info.dhSignedData.data, ++ kdc_reply->u.dh_Info.dhSignedData.length, ++ "/tmp/client_kdc_signeddata"); + #endif +- if ((retval = cms_signeddata_verify(context, plgctx->cryptoctx, +- reqctx->cryptoctx, reqctx->idctx, CMS_SIGN_SERVER, +- reqctx->opts->require_crl_checking, +- (unsigned char *) +- kdc_reply->u.dh_Info.dhSignedData.data, +- kdc_reply->u.dh_Info.dhSignedData.length, +- (unsigned char **)&dh_data.data, +- &dh_data.length, +- NULL, NULL, NULL)) != 0) { +- pkiDebug("failed to verify pkcs7 signed data\n"); +- TRACE_PKINIT_CLIENT_REP_DH_FAIL(context); +- goto cleanup; +- } +- TRACE_PKINIT_CLIENT_REP_DH(context); +- break; +- case choice_pa_pk_as_rep_encKeyPack: +- pkiDebug("as_rep: RSA key transport algorithm\n"); +- if ((retval = cms_envelopeddata_verify(context, plgctx->cryptoctx, +- reqctx->cryptoctx, reqctx->idctx, pa_type, +- reqctx->opts->require_crl_checking, +- (unsigned char *) +- kdc_reply->u.encKeyPack.data, +- kdc_reply->u.encKeyPack.length, +- (unsigned char **)&dh_data.data, +- &dh_data.length)) != 0) { +- pkiDebug("failed to verify pkcs7 enveloped data\n"); +- TRACE_PKINIT_CLIENT_REP_RSA_FAIL(context); +- goto cleanup; +- } +- TRACE_PKINIT_CLIENT_REP_RSA(context); +- break; +- default: +- pkiDebug("unknown as_rep type %d\n", kdc_reply->choice); +- retval = -1; ++ if ((retval = cms_signeddata_verify(context, plgctx->cryptoctx, ++ reqctx->cryptoctx, reqctx->idctx, ++ CMS_SIGN_SERVER, ++ reqctx->opts->require_crl_checking, ++ (unsigned char *) ++ kdc_reply->u.dh_Info.dhSignedData.data, ++ kdc_reply->u.dh_Info.dhSignedData.length, ++ (unsigned char **)&dh_data.data, ++ &dh_data.length, ++ NULL, NULL, NULL)) != 0) { ++ pkiDebug("failed to verify pkcs7 signed data\n"); ++ TRACE_PKINIT_CLIENT_REP_DH_FAIL(context); + goto cleanup; + } ++ TRACE_PKINIT_CLIENT_REP_DH(context); ++ + retval = krb5_build_principal_ext(context, &kdc_princ, + request->server->realm.length, + request->server->realm.data, +@@ -635,116 +602,55 @@ pkinit_as_rep_parse(krb5_context context, + + OCTETDATA_TO_KRB5DATA(&dh_data, &k5data); + +- switch(kdc_reply->choice) { +- case choice_pa_pk_as_rep_dhInfo: + #ifdef DEBUG_ASN1 +- print_buffer_bin(dh_data.data, dh_data.length, +- "/tmp/client_dh_key"); ++ print_buffer_bin(dh_data.data, dh_data.length, "/tmp/client_dh_key"); + #endif +- if ((retval = k5int_decode_krb5_kdc_dh_key_info(&k5data, +- &kdc_dh)) != 0) { +- pkiDebug("failed to decode kdc_dh_key_info\n"); +- goto cleanup; +- } +- +- /* client after KDC reply */ +- if ((retval = client_process_dh(context, plgctx->cryptoctx, +- reqctx->cryptoctx, reqctx->idctx, +- (unsigned char *) +- kdc_dh->subjectPublicKey.data, +- kdc_dh->subjectPublicKey.length, +- &client_key, &client_key_len)) != 0) { +- pkiDebug("failed to process dh params\n"); +- goto cleanup; +- } +- +- /* If we have a KDF algorithm ID, call the algorithm agility KDF... */ +- if (kdc_reply->u.dh_Info.kdfID) { +- secret.length = client_key_len; +- secret.data = (char *)client_key; +- +- retval = pkinit_alg_agility_kdf(context, &secret, +- kdc_reply->u.dh_Info.kdfID, +- request->client, request->server, +- etype, encoded_request, +- (krb5_data *)as_rep, key_block); ++ if ((retval = k5int_decode_krb5_kdc_dh_key_info(&k5data, &kdc_dh)) != 0) { ++ pkiDebug("failed to decode kdc_dh_key_info\n"); ++ goto cleanup; ++ } + +- if (retval) { +- pkiDebug("failed to create key pkinit_alg_agility_kdf %s\n", +- error_message(retval)); +- goto cleanup; +- } +- TRACE_PKINIT_CLIENT_KDF_ALG(context, kdc_reply->u.dh_Info.kdfID, +- key_block); ++ /* client after KDC reply */ ++ if ((retval = client_process_dh(context, plgctx->cryptoctx, ++ reqctx->cryptoctx, reqctx->idctx, ++ (unsigned char *) ++ kdc_dh->subjectPublicKey.data, ++ kdc_dh->subjectPublicKey.length, ++ &client_key, &client_key_len)) != 0) { ++ pkiDebug("failed to process dh params\n"); ++ goto cleanup; ++ } + +- /* ...otherwise, use the older octetstring2key function. */ +- } else { ++ /* If we have a KDF algorithm ID, call the algorithm agility KDF... */ ++ if (kdc_reply->u.dh_Info.kdfID) { ++ secret.length = client_key_len; ++ secret.data = (char *)client_key; + +- retval = pkinit_octetstring2key(context, etype, client_key, +- client_key_len, key_block); +- if (retval) { +- pkiDebug("failed to create key pkinit_octetstring2key %s\n", +- error_message(retval)); +- goto cleanup; +- } +- TRACE_PKINIT_CLIENT_KDF_OS2K(context, key_block); +- } ++ retval = pkinit_alg_agility_kdf(context, &secret, ++ kdc_reply->u.dh_Info.kdfID, ++ request->client, request->server, ++ etype, encoded_request, ++ (krb5_data *)as_rep, key_block); + +- break; +- case choice_pa_pk_as_rep_encKeyPack: +-#ifdef DEBUG_ASN1 +- print_buffer_bin(dh_data.data, dh_data.length, +- "/tmp/client_key_pack"); +-#endif +- retval = k5int_decode_krb5_reply_key_pack(&k5data, &key_pack); + if (retval) { +- pkiDebug("failed to decode reply_key_pack\n"); ++ pkiDebug("failed to create key pkinit_alg_agility_kdf %s\n", ++ error_message(retval)); + goto cleanup; + } +- retval = krb5_c_make_checksum(context, +- key_pack->asChecksum.checksum_type, +- &key_pack->replyKey, +- KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM, +- encoded_request, &cksum); ++ TRACE_PKINIT_CLIENT_KDF_ALG(context, kdc_reply->u.dh_Info.kdfID, ++ key_block); ++ ++ /* ...otherwise, use the older octetstring2key function. */ ++ } else { ++ ++ retval = pkinit_octetstring2key(context, etype, client_key, ++ client_key_len, key_block); + if (retval) { +- pkiDebug("failed to make a checksum\n"); ++ pkiDebug("failed to create key pkinit_octetstring2key %s\n", ++ error_message(retval)); + goto cleanup; + } +- +- if ((cksum.length != key_pack->asChecksum.length) || +- k5_bcmp(cksum.contents, key_pack->asChecksum.contents, +- cksum.length) != 0) { +- TRACE_PKINIT_CLIENT_REP_CHECKSUM_FAIL(context, &cksum, +- &key_pack->asChecksum); +- pkiDebug("failed to match the checksums\n"); +-#ifdef DEBUG_CKSUM +- pkiDebug("calculating checksum on buf size (%d)\n", +- encoded_request->length); +- print_buffer(encoded_request->data, encoded_request->length); +- pkiDebug("encrypting key (%d)\n", key_pack->replyKey.length); +- print_buffer(key_pack->replyKey.contents, +- key_pack->replyKey.length); +- pkiDebug("received checksum type=%d size=%d ", +- key_pack->asChecksum.checksum_type, +- key_pack->asChecksum.length); +- print_buffer(key_pack->asChecksum.contents, +- key_pack->asChecksum.length); +- pkiDebug("expected checksum type=%d size=%d ", +- cksum.checksum_type, cksum.length); +- print_buffer(cksum.contents, cksum.length); +-#endif +- goto cleanup; +- } else +- pkiDebug("checksums match\n"); +- +- krb5_copy_keyblock_contents(context, &key_pack->replyKey, +- key_block); +- TRACE_PKINIT_CLIENT_REP_RSA_KEY(context, key_block, &cksum); +- +- break; +- default: +- pkiDebug("unknow as_rep type %d\n", kdc_reply->choice); +- goto cleanup; ++ TRACE_PKINIT_CLIENT_KDF_OS2K(context, key_block); + } + + retval = 0; +@@ -1286,7 +1192,6 @@ pkinit_client_req_init(krb5_context context, + + reqctx->opts->require_eku = plgctx->opts->require_eku; + reqctx->opts->accept_secondary_eku = plgctx->opts->accept_secondary_eku; +- reqctx->opts->dh_or_rsa = plgctx->opts->dh_or_rsa; + reqctx->opts->allow_upn = plgctx->opts->allow_upn; + reqctx->opts->require_crl_checking = plgctx->opts->require_crl_checking; + reqctx->opts->disable_freshness = plgctx->opts->disable_freshness; +@@ -1457,11 +1362,6 @@ handle_gic_opt(krb5_context context, + retval = add_string_to_array(context, &plgctx->idopts->anchors, value); + if (retval) + return retval; +- } else if (strcmp(attr, "flag_RSA_PROTOCOL") == 0) { +- if (strcmp(value, "yes") == 0) { +- pkiDebug("Setting flag to use RSA_PROTOCOL\n"); +- plgctx->opts->dh_or_rsa = RSA_PROTOCOL; +- } + } else if (strcmp(attr, "disable_freshness") == 0) { + if (strcmp(value, "yes") == 0) + plgctx->opts->disable_freshness = 1; +diff --git a/src/plugins/preauth/pkinit/pkinit_crypto.h b/src/plugins/preauth/pkinit/pkinit_crypto.h +index a291889b0d..f251e41064 100644 +--- a/src/plugins/preauth/pkinit/pkinit_crypto.h ++++ b/src/plugins/preauth/pkinit/pkinit_crypto.h +@@ -183,48 +183,6 @@ krb5_error_code cms_signeddata_verify + int *is_signed); /* OUT + receives whether message is signed */ + +-/* +- * this function creates a CMS message where eContentType is EnvelopedData +- */ +-krb5_error_code cms_envelopeddata_create +- (krb5_context context, /* IN */ +- pkinit_plg_crypto_context plg_cryptoctx, /* IN */ +- pkinit_req_crypto_context req_cryptoctx, /* IN */ +- pkinit_identity_crypto_context id_cryptoctx, /* IN */ +- krb5_preauthtype pa_type, /* IN */ +- int include_certchain, /* IN +- specifies whether the certificates field in +- SignedData should contain certificate path */ +- unsigned char *key_pack, /* IN +- contains DER encoded ReplyKeyPack */ +- unsigned int key_pack_len, /* IN +- contains length of key_pack */ +- unsigned char **envel_data, /* OUT +- receives DER encoded encKeyPack */ +- unsigned int *envel_data_len); /* OUT +- receives length of envel_data */ +- +-/* +- * this function creates a CMS message where eContentType is EnvelopedData +- */ +-krb5_error_code cms_envelopeddata_verify +- (krb5_context context, /* IN */ +- pkinit_plg_crypto_context plg_cryptoctx, /* IN */ +- pkinit_req_crypto_context req_cryptoctx, /* IN */ +- pkinit_identity_crypto_context id_cryptoctx, /* IN */ +- krb5_preauthtype pa_type, /* IN */ +- int require_crl_checking, /* IN +- specifies whether CRL checking should be +- strictly enforced */ +- unsigned char *envel_data, /* IN +- contains DER encoded encKeyPack */ +- unsigned int envel_data_len, /* IN +- contains length of envel_data */ +- unsigned char **signed_data, /* OUT +- receives ReplyKeyPack */ +- unsigned int *signed_data_len); /* OUT +- receives length of signed_data */ +- + /* + * This function retrieves the signer's identity, in a form that could + * be passed back in to a future invocation of this module as a candidate +diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c +index 32291e3ac0..76ad7526bb 100644 +--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c ++++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c +@@ -71,26 +71,14 @@ static krb5_error_code create_signature + (unsigned char **, unsigned int *, unsigned char *, unsigned int, + EVP_PKEY *pkey); + +-static krb5_error_code pkinit_decode_data +-(krb5_context context, pkinit_identity_crypto_context cryptoctx, +- const uint8_t *data, unsigned int data_len, uint8_t **decoded, +- unsigned int *decoded_len); +- + #ifdef DEBUG_DH + static void print_dh(DH *, char *); + static void print_pubkey(BIGNUM *, char *); + #endif + +-static int prepare_enc_data +-(const uint8_t *indata, int indata_len, uint8_t **outdata, int *outdata_len); +- + static int openssl_callback (int, X509_STORE_CTX *); + static int openssl_callback_ignore_crls (int, X509_STORE_CTX *); + +-static int pkcs7_decrypt +-(krb5_context context, pkinit_identity_crypto_context id_cryptoctx, PKCS7 *p7, +- unsigned char **data_out, unsigned int *len_out); +- + static ASN1_OBJECT * pkinit_pkcs7type2oid + (pkinit_plg_crypto_context plg_cryptoctx, int pkcs7_type); + +@@ -111,31 +99,17 @@ static krb5_error_code pkinit_open_session + (krb5_context context, pkinit_identity_crypto_context id_cryptoctx); + static void * pkinit_C_LoadModule(const char *modname, CK_FUNCTION_LIST_PTR_PTR p11p); + static CK_RV pkinit_C_UnloadModule(void *handle); +-#ifdef SILLYDECRYPT +-CK_RV pkinit_C_Decrypt +-(pkinit_identity_crypto_context id_cryptoctx, +- CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, +- CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen); +-#endif + + static krb5_error_code pkinit_sign_data_pkcs11 + (krb5_context context, pkinit_identity_crypto_context id_cryptoctx, + unsigned char *data, unsigned int data_len, + unsigned char **sig, unsigned int *sig_len); +-static krb5_error_code pkinit_decode_data_pkcs11 +-(krb5_context context, pkinit_identity_crypto_context id_cryptoctx, +- const uint8_t *data, unsigned int data_len, uint8_t **decoded_data, +- unsigned int *decoded_data_len); + #endif /* WITHOUT_PKCS11 */ + + static krb5_error_code pkinit_sign_data_fs + (krb5_context context, pkinit_identity_crypto_context id_cryptoctx, + unsigned char *data, unsigned int data_len, + unsigned char **sig, unsigned int *sig_len); +-static krb5_error_code pkinit_decode_data_fs +-(krb5_context context, pkinit_identity_crypto_context id_cryptoctx, +- const uint8_t *data, unsigned int data_len, uint8_t **decoded_data, +- unsigned int *decoded_data_len); + + static krb5_error_code + create_krb5_invalidCertificates(krb5_context context, +@@ -147,9 +121,6 @@ create_krb5_invalidCertificates(krb5_context context, + static krb5_error_code + create_identifiers_from_stack(STACK_OF(X509) *sk, + krb5_external_principal_identifier *** ids); +-static int +-wrap_signeddata(unsigned char *data, unsigned int data_len, +- unsigned char **out, unsigned int *out_len); + + static char * + pkinit_pkcs11_code_to_text(int err); +@@ -1791,176 +1762,6 @@ cleanup: + return retval; + } + +-krb5_error_code +-cms_envelopeddata_create(krb5_context context, +- pkinit_plg_crypto_context plgctx, +- pkinit_req_crypto_context reqctx, +- pkinit_identity_crypto_context idctx, +- krb5_preauthtype pa_type, +- int include_certchain, +- unsigned char *key_pack, +- unsigned int key_pack_len, +- unsigned char **out, +- unsigned int *out_len) +-{ +- +- krb5_error_code retval = ENOMEM; +- PKCS7 *p7 = NULL; +- BIO *in = NULL; +- unsigned char *p = NULL, *signed_data = NULL, *enc_data = NULL; +- int signed_data_len = 0, enc_data_len = 0, flags = PKCS7_BINARY; +- STACK_OF(X509) *encerts = NULL; +- const EVP_CIPHER *cipher = NULL; +- +- retval = cms_signeddata_create(context, plgctx, reqctx, idctx, +- CMS_ENVEL_SERVER, include_certchain, +- key_pack, key_pack_len, &signed_data, +- (unsigned int *)&signed_data_len); +- if (retval) { +- pkiDebug("failed to create pkcs7 signed data\n"); +- goto cleanup; +- } +- +- /* check we have client's certificate */ +- if (reqctx->received_cert == NULL) { +- retval = KRB5KDC_ERR_PREAUTH_FAILED; +- goto cleanup; +- } +- encerts = sk_X509_new_null(); +- sk_X509_push(encerts, reqctx->received_cert); +- +- cipher = EVP_des_ede3_cbc(); +- in = BIO_new(BIO_s_mem()); +- prepare_enc_data(signed_data, signed_data_len, &enc_data, +- &enc_data_len); +- retval = BIO_write(in, enc_data, enc_data_len); +- if (retval != enc_data_len) { +- pkiDebug("BIO_write only wrote %d\n", retval); +- goto cleanup; +- } +- +- p7 = PKCS7_encrypt(encerts, in, cipher, flags); +- if (p7 == NULL) { +- retval = oerr(context, 0, _("Failed to encrypt PKCS7 object")); +- goto cleanup; +- } +- p7->d.enveloped->enc_data->content_type = OBJ_nid2obj(NID_pkcs7_signed); +- +- *out_len = i2d_PKCS7(p7, NULL); +- if (!*out_len || (p = *out = malloc(*out_len)) == NULL) { +- retval = ENOMEM; +- goto cleanup; +- } +- retval = i2d_PKCS7(p7, &p); +- if (!retval) { +- retval = oerr(context, 0, _("Failed to DER encode PKCS7")); +- goto cleanup; +- } +- retval = 0; +- +-#ifdef DEBUG_ASN1 +- print_buffer_bin(*out, *out_len, "/tmp/kdc_enveloped_data"); +-#endif +- +-cleanup: +- if (p7 != NULL) +- PKCS7_free(p7); +- if (in != NULL) +- BIO_free(in); +- free(signed_data); +- free(enc_data); +- if (encerts != NULL) +- sk_X509_free(encerts); +- +- return retval; +-} +- +-krb5_error_code +-cms_envelopeddata_verify(krb5_context context, +- pkinit_plg_crypto_context plg_cryptoctx, +- pkinit_req_crypto_context req_cryptoctx, +- pkinit_identity_crypto_context id_cryptoctx, +- krb5_preauthtype pa_type, +- int require_crl_checking, +- unsigned char *enveloped_data, +- unsigned int enveloped_data_len, +- unsigned char **data, +- unsigned int *data_len) +-{ +- krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED; +- PKCS7 *p7 = NULL; +- const unsigned char *p = enveloped_data; +- unsigned int tmp_buf_len = 0, tmp_buf2_len = 0, vfy_buf_len = 0; +- unsigned char *tmp_buf = NULL, *tmp_buf2 = NULL, *vfy_buf = NULL; +- +-#ifdef DEBUG_ASN1 +- print_buffer_bin(enveloped_data, enveloped_data_len, +- "/tmp/client_envelopeddata"); +-#endif +- /* decode received PKCS7 message */ +- if ((p7 = d2i_PKCS7(NULL, &p, (int)enveloped_data_len)) == NULL) { +- retval = oerr(context, 0, _("Failed to decode PKCS7")); +- goto cleanup; +- } +- +- /* verify that the received message is PKCS7 EnvelopedData message */ +- if (OBJ_obj2nid(p7->type) != NID_pkcs7_enveloped) { +- pkiDebug("Expected id-enveloped PKCS7 msg (received type = %d)\n", +- OBJ_obj2nid(p7->type)); +- krb5_set_error_message(context, retval, "wrong oid\n"); +- goto cleanup; +- } +- +- /* decrypt received PKCS7 message */ +- if (pkcs7_decrypt(context, id_cryptoctx, p7, &tmp_buf, &tmp_buf_len)) { +- pkiDebug("PKCS7 decryption successful\n"); +- } else { +- retval = oerr(context, 0, _("Failed to decrypt PKCS7 message")); +- goto cleanup; +- } +- +-#ifdef DEBUG_ASN1 +- print_buffer_bin(tmp_buf, tmp_buf_len, "/tmp/client_enc_keypack"); +-#endif +- /* verify PKCS7 SignedData message */ +- /* Wrap the signed data to make decoding easier in the verify routine. */ +- retval = wrap_signeddata(tmp_buf, tmp_buf_len, &tmp_buf2, &tmp_buf2_len); +- if (retval) { +- pkiDebug("failed to encode signeddata\n"); +- goto cleanup; +- } +- vfy_buf = tmp_buf2; +- vfy_buf_len = tmp_buf2_len; +- +-#ifdef DEBUG_ASN1 +- print_buffer_bin(vfy_buf, vfy_buf_len, "/tmp/client_enc_keypack2"); +-#endif +- +- retval = cms_signeddata_verify(context, plg_cryptoctx, req_cryptoctx, +- id_cryptoctx, CMS_ENVEL_SERVER, +- require_crl_checking, +- vfy_buf, vfy_buf_len, +- data, data_len, NULL, NULL, NULL); +- +- if (!retval) +- pkiDebug("PKCS7 Verification Success\n"); +- else { +- pkiDebug("PKCS7 Verification Failure\n"); +- goto cleanup; +- } +- +- retval = 0; +- +-cleanup: +- +- if (p7 != NULL) +- PKCS7_free(p7); +- free(tmp_buf); +- free(tmp_buf2); +- +- return retval; +-} +- + static krb5_error_code + crypto_retrieve_X509_sans(krb5_context context, + pkinit_plg_crypto_context plgctx, +@@ -3539,70 +3340,6 @@ pkinit_pkcs7type2oid(pkinit_plg_crypto_context cryptoctx, int pkcs7_type) + + } + +-static int +-wrap_signeddata(unsigned char *data, unsigned int data_len, +- unsigned char **out, unsigned int *out_len) +-{ +- +- unsigned int orig_len = 0, oid_len = 0, tot_len = 0; +- ASN1_OBJECT *oid = NULL; +- unsigned char *p = NULL; +- +- /* Get length to wrap the original data with SEQUENCE tag */ +- tot_len = orig_len = ASN1_object_size(1, (int)data_len, V_ASN1_SEQUENCE); +- +- /* Add the signedData OID and adjust lengths */ +- oid = OBJ_nid2obj(NID_pkcs7_signed); +- oid_len = i2d_ASN1_OBJECT(oid, NULL); +- +- tot_len = ASN1_object_size(1, (int)(orig_len+oid_len), V_ASN1_SEQUENCE); +- +- p = *out = malloc(tot_len); +- if (p == NULL) return -1; +- +- ASN1_put_object(&p, 1, (int)(orig_len+oid_len), +- V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL); +- +- i2d_ASN1_OBJECT(oid, &p); +- +- ASN1_put_object(&p, 1, (int)data_len, 0, V_ASN1_CONTEXT_SPECIFIC); +- memcpy(p, data, data_len); +- +- *out_len = tot_len; +- +- return 0; +-} +- +-static int +-prepare_enc_data(const uint8_t *indata, int indata_len, uint8_t **outdata, +- int *outdata_len) +-{ +- int tag, class; +- long tlen, slen; +- const uint8_t *p = indata, *oldp; +- +- if (ASN1_get_object(&p, &slen, &tag, &class, indata_len) & 0x80) +- return EINVAL; +- if (tag != V_ASN1_SEQUENCE) +- return EINVAL; +- +- oldp = p; +- if (ASN1_get_object(&p, &tlen, &tag, &class, slen) & 0x80) +- return EINVAL; +- p += tlen; +- slen -= (p - oldp); +- +- if (ASN1_get_object(&p, &tlen, &tag, &class, slen) & 0x80) +- return EINVAL; +- +- *outdata = malloc(tlen); +- if (*outdata == NULL) +- return ENOMEM; +- memcpy(*outdata, p, tlen); +- *outdata_len = tlen; +- return 0; +-} +- + #ifndef WITHOUT_PKCS11 + static void * + pkinit_C_LoadModule(const char *modname, CK_FUNCTION_LIST_PTR_PTR p11p) +@@ -3894,148 +3631,6 @@ pkinit_find_private_key(pkinit_identity_crypto_context id_cryptoctx, + } + #endif + +-static krb5_error_code +-pkinit_decode_data_fs(krb5_context context, +- pkinit_identity_crypto_context id_cryptoctx, +- const uint8_t *data, unsigned int data_len, +- uint8_t **decoded_data, unsigned int *decoded_data_len) +-{ +- X509 *cert = sk_X509_value(id_cryptoctx->my_certs, +- id_cryptoctx->cert_index); +- EVP_PKEY *pkey = id_cryptoctx->my_key; +- uint8_t *buf; +- int buf_len, decrypt_len; +- +- *decoded_data = NULL; +- *decoded_data_len = 0; +- +- if (cert != NULL && !X509_check_private_key(cert, pkey)) { +- pkiDebug("private key does not match certificate\n"); +- return KRB5KDC_ERR_PREAUTH_FAILED; +- } +- +- buf_len = EVP_PKEY_size(pkey); +- buf = malloc(buf_len + 10); +- if (buf == NULL) +- return KRB5KDC_ERR_PREAUTH_FAILED; +- +- decrypt_len = EVP_PKEY_decrypt_old(buf, data, data_len, pkey); +- if (decrypt_len <= 0) { +- pkiDebug("unable to decrypt received data (len=%d)\n", data_len); +- free(buf); +- return KRB5KDC_ERR_PREAUTH_FAILED; +- } +- +- *decoded_data = buf; +- *decoded_data_len = decrypt_len; +- return 0; +-} +- +-#ifndef WITHOUT_PKCS11 +-/* +- * When using the ActivCard Linux pkcs11 library (v2.0.1), the decrypt function +- * fails. By inserting an extra function call, which serves nothing but to +- * change the stack, we were able to work around the issue. If the ActivCard +- * library is fixed in the future, this function can be inlined back into the +- * caller. +- */ +-static CK_RV +-pkinit_C_Decrypt(pkinit_identity_crypto_context id_cryptoctx, +- CK_BYTE_PTR pEncryptedData, +- CK_ULONG ulEncryptedDataLen, +- CK_BYTE_PTR pData, +- CK_ULONG_PTR pulDataLen) +-{ +- CK_RV rv = CKR_OK; +- +- rv = id_cryptoctx->p11->C_Decrypt(id_cryptoctx->session, pEncryptedData, +- ulEncryptedDataLen, pData, pulDataLen); +- if (rv == CKR_OK) { +- pkiDebug("pData %p *pulDataLen %d\n", (void *) pData, +- (int) *pulDataLen); +- } +- return rv; +-} +- +-static krb5_error_code +-pkinit_decode_data_pkcs11(krb5_context context, +- pkinit_identity_crypto_context id_cryptoctx, +- const uint8_t *data, unsigned int data_len, +- uint8_t **decoded_data, +- unsigned int *decoded_data_len) +-{ +- CK_OBJECT_HANDLE obj; +- CK_ULONG len; +- CK_MECHANISM mech; +- uint8_t *cp; +- int r; +- +- *decoded_data = NULL; +- *decoded_data_len = 0; +- +- if (pkinit_open_session(context, id_cryptoctx)) { +- pkiDebug("can't open pkcs11 session\n"); +- return KRB5KDC_ERR_PREAUTH_FAILED; +- } +- +- pkinit_find_private_key(id_cryptoctx, CKA_DECRYPT, &obj); +- +- mech.mechanism = CKM_RSA_PKCS; +- mech.pParameter = NULL; +- mech.ulParameterLen = 0; +- +- if ((r = id_cryptoctx->p11->C_DecryptInit(id_cryptoctx->session, &mech, +- obj)) != CKR_OK) { +- pkiDebug("C_DecryptInit: 0x%x\n", (int) r); +- return KRB5KDC_ERR_PREAUTH_FAILED; +- } +- pkiDebug("data_len = %d\n", data_len); +- cp = malloc((size_t) data_len); +- if (cp == NULL) +- return ENOMEM; +- len = data_len; +- pkiDebug("session %p edata %p edata_len %d data %p datalen @%p %d\n", +- (void *) id_cryptoctx->session, (void *) data, (int) data_len, +- (void *) cp, (void *) &len, (int) len); +- r = pkinit_C_Decrypt(id_cryptoctx, (CK_BYTE_PTR) data, (CK_ULONG) data_len, +- cp, &len); +- if (r != CKR_OK) { +- pkiDebug("C_Decrypt: %s\n", pkinit_pkcs11_code_to_text(r)); +- if (r == CKR_BUFFER_TOO_SMALL) +- pkiDebug("decrypt %d needs %d\n", (int) data_len, (int) len); +- return KRB5KDC_ERR_PREAUTH_FAILED; +- } +- pkiDebug("decrypt %d -> %d\n", (int) data_len, (int) len); +- *decoded_data_len = len; +- *decoded_data = cp; +- +- return 0; +-} +-#endif +- +-krb5_error_code +-pkinit_decode_data(krb5_context context, +- pkinit_identity_crypto_context id_cryptoctx, +- const uint8_t *data, unsigned int data_len, +- uint8_t **decoded_data, unsigned int *decoded_data_len) +-{ +- krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED; +- +- *decoded_data = NULL; +- *decoded_data_len = 0; +- +- if (id_cryptoctx->pkcs11_method != 1) +- retval = pkinit_decode_data_fs(context, id_cryptoctx, data, data_len, +- decoded_data, decoded_data_len); +-#ifndef WITHOUT_PKCS11 +- else +- retval = pkinit_decode_data_pkcs11(context, id_cryptoctx, data, +- data_len, decoded_data, decoded_data_len); +-#endif +- +- return retval; +-} +- + static krb5_error_code + pkinit_sign_data_fs(krb5_context context, + pkinit_identity_crypto_context id_cryptoctx, +@@ -5683,88 +5278,6 @@ cleanup: + return retval; + } + +-/* Originally based on OpenSSL's PKCS7_dataDecode(), now modified to remove the +- * use of BIO objects and to fit the PKINIT internal interfaces. */ +-static int +-pkcs7_decrypt(krb5_context context, +- pkinit_identity_crypto_context id_cryptoctx, PKCS7 *p7, +- unsigned char **data_out, unsigned int *len_out) +-{ +- krb5_error_code ret; +- int ok = 0, plaintext_len = 0, final_len; +- unsigned int keylen = 0, eklen = 0, blocksize; +- unsigned char *ek = NULL, *tkey = NULL, *plaintext = NULL, *use_key; +- ASN1_OCTET_STRING *data_body = p7->d.enveloped->enc_data->enc_data; +- const EVP_CIPHER *evp_cipher; +- EVP_CIPHER_CTX *evp_ctx = NULL; +- X509_ALGOR *enc_alg = p7->d.enveloped->enc_data->algorithm; +- STACK_OF(PKCS7_RECIP_INFO) *rsk = p7->d.enveloped->recipientinfo; +- PKCS7_RECIP_INFO *ri = NULL; +- +- *data_out = NULL; +- *len_out = 0; +- +- p7->state = PKCS7_S_HEADER; +- +- /* RFC 4556 section 3.2.3.2 requires that there be exactly one +- * recipientInfo. */ +- if (sk_PKCS7_RECIP_INFO_num(rsk) != 1) { +- pkiDebug("invalid number of EnvelopedData RecipientInfos\n"); +- return 0; +- } +- ri = sk_PKCS7_RECIP_INFO_value(rsk, 0); +- +- evp_cipher = EVP_get_cipherbyobj(enc_alg->algorithm); +- if (evp_cipher == NULL) +- goto cleanup; +- keylen = EVP_CIPHER_key_length(evp_cipher); +- blocksize = EVP_CIPHER_block_size(evp_cipher); +- +- evp_ctx = EVP_CIPHER_CTX_new(); +- if (evp_ctx == NULL) +- goto cleanup; +- if (!EVP_DecryptInit(evp_ctx, evp_cipher, NULL, NULL) || +- EVP_CIPHER_asn1_to_param(evp_ctx, enc_alg->parameter) <= 0) +- goto cleanup; +- +- /* Generate a random symmetric key to avoid exposing timing data if RSA +- * decryption fails the padding check. */ +- tkey = malloc(keylen); +- if (tkey == NULL || !EVP_CIPHER_CTX_rand_key(evp_ctx, tkey)) +- goto cleanup; +- +- /* Decrypt the secret key with the private key. */ +- ret = pkinit_decode_data(context, id_cryptoctx, +- ASN1_STRING_get0_data(ri->enc_key), +- ASN1_STRING_length(ri->enc_key), &ek, &eklen); +- use_key = (ret || eklen != keylen) ? tkey : ek; +- +- /* Allocate a plaintext buffer and decrypt data_body into it. */ +- plaintext = malloc(data_body->length + blocksize); +- if (plaintext == NULL) +- goto cleanup; +- if (!EVP_DecryptInit(evp_ctx, NULL, use_key, NULL)) +- goto cleanup; +- if (!EVP_DecryptUpdate(evp_ctx, plaintext, &plaintext_len, +- data_body->data, data_body->length)) +- goto cleanup; +- if (!EVP_DecryptFinal(evp_ctx, plaintext + plaintext_len, &final_len)) +- goto cleanup; +- plaintext_len += final_len; +- +- *len_out = plaintext_len; +- *data_out = plaintext; +- plaintext = NULL; +- ok = 1; +- +-cleanup: +- EVP_CIPHER_CTX_free(evp_ctx); +- zapfree(plaintext, plaintext_len); +- zapfree(ek, eklen); +- zapfree(tkey, keylen); +- return ok; +-} +- + #ifdef DEBUG_DH + static void + print_dh(DH * dh, char *msg) +diff --git a/src/plugins/preauth/pkinit/pkinit_lib.c b/src/plugins/preauth/pkinit/pkinit_lib.c +index bb2916bd5d..7af880bf5c 100644 +--- a/src/plugins/preauth/pkinit/pkinit_lib.c ++++ b/src/plugins/preauth/pkinit/pkinit_lib.c +@@ -50,7 +50,6 @@ pkinit_init_req_opts(pkinit_req_opts **reqopts) + opts->require_eku = 1; + opts->accept_secondary_eku = 0; + opts->allow_upn = 0; +- opts->dh_or_rsa = DH_PROTOCOL; + opts->require_crl_checking = 0; + opts->dh_size = PKINIT_DEFAULT_DH_MIN_BITS; + +@@ -79,7 +78,6 @@ pkinit_init_plg_opts(pkinit_plg_opts **plgopts) + + opts->require_eku = 1; + opts->accept_secondary_eku = 0; +- opts->dh_or_rsa = DH_PROTOCOL; + opts->allow_upn = 0; + opts->require_crl_checking = 0; + opts->require_freshness = 0; +diff --git a/src/plugins/preauth/pkinit/pkinit_srv.c b/src/plugins/preauth/pkinit/pkinit_srv.c +index 3bff456f8f..4eab5a2761 100644 +--- a/src/plugins/preauth/pkinit/pkinit_srv.c ++++ b/src/plugins/preauth/pkinit/pkinit_srv.c +@@ -826,133 +826,62 @@ pkinit_server_return_padata(krb5_context context, + retval = ENOMEM; + goto cleanup; + } +- /* let's assume it's RSA. we'll reset it to DH if needed */ +- rep->choice = choice_pa_pk_as_rep_encKeyPack; + +- if (reqctx->rcv_auth_pack != NULL && +- reqctx->rcv_auth_pack->clientPublicValue != NULL) { +- subjectPublicKey = (unsigned char *) +- reqctx->rcv_auth_pack->clientPublicValue->subjectPublicKey.data; +- subjectPublicKey_len = +- reqctx->rcv_auth_pack->clientPublicValue->subjectPublicKey.length; +- rep->choice = choice_pa_pk_as_rep_dhInfo; +- +- pkiDebug("received DH key delivery AS REQ\n"); +- retval = server_process_dh(context, plgctx->cryptoctx, +- reqctx->cryptoctx, plgctx->idctx, subjectPublicKey, +- subjectPublicKey_len, &dh_pubkey, &dh_pubkey_len, +- &server_key, &server_key_len); +- if (retval) { +- pkiDebug("failed to process/create dh parameters\n"); +- goto cleanup; +- } ++ if (reqctx->rcv_auth_pack == NULL || ++ reqctx->rcv_auth_pack->clientPublicValue == NULL) { ++ retval = KRB5KDC_ERR_PREAUTH_FAILED; ++ k5_setmsg(context, retval, _("Unsupported PKINIT RSA request")); ++ goto cleanup; ++ } + +- /* +- * This is DH, so don't generate the key until after we +- * encode the reply, because the encoded reply is needed +- * to generate the key in some cases. +- */ ++ subjectPublicKey = (unsigned char *) ++ reqctx->rcv_auth_pack->clientPublicValue->subjectPublicKey.data; ++ subjectPublicKey_len = ++ reqctx->rcv_auth_pack->clientPublicValue->subjectPublicKey.length; ++ rep->choice = choice_pa_pk_as_rep_dhInfo; ++ ++ pkiDebug("received DH key delivery AS REQ\n"); ++ retval = server_process_dh(context, plgctx->cryptoctx, reqctx->cryptoctx, ++ plgctx->idctx, subjectPublicKey, ++ subjectPublicKey_len, &dh_pubkey, &dh_pubkey_len, ++ &server_key, &server_key_len); ++ if (retval) { ++ pkiDebug("failed to process/create dh parameters\n"); ++ goto cleanup; ++ } + +- dhkey_info.subjectPublicKey.length = dh_pubkey_len; +- dhkey_info.subjectPublicKey.data = (char *)dh_pubkey; +- dhkey_info.nonce = request->nonce; +- dhkey_info.dhKeyExpiration = 0; ++ dhkey_info.subjectPublicKey.length = dh_pubkey_len; ++ dhkey_info.subjectPublicKey.data = (char *)dh_pubkey; ++ dhkey_info.nonce = request->nonce; ++ dhkey_info.dhKeyExpiration = 0; + +- retval = k5int_encode_krb5_kdc_dh_key_info(&dhkey_info, +- &encoded_dhkey_info); +- if (retval) { +- pkiDebug("encode_krb5_kdc_dh_key_info failed\n"); +- goto cleanup; +- } ++ retval = k5int_encode_krb5_kdc_dh_key_info(&dhkey_info, ++ &encoded_dhkey_info); ++ if (retval) { ++ pkiDebug("encode_krb5_kdc_dh_key_info failed\n"); ++ goto cleanup; ++ } + #ifdef DEBUG_ASN1 +- print_buffer_bin((unsigned char *)encoded_dhkey_info->data, +- encoded_dhkey_info->length, +- "/tmp/kdc_dh_key_info"); ++ print_buffer_bin((unsigned char *)encoded_dhkey_info->data, ++ encoded_dhkey_info->length, "/tmp/kdc_dh_key_info"); + #endif + +- retval = cms_signeddata_create(context, plgctx->cryptoctx, +- reqctx->cryptoctx, plgctx->idctx, +- CMS_SIGN_SERVER, 1, +- (unsigned char *) +- encoded_dhkey_info->data, +- encoded_dhkey_info->length, +- (unsigned char **) +- &rep->u.dh_Info.dhSignedData.data, +- &rep->u.dh_Info.dhSignedData.length); +- if (retval) { +- pkiDebug("failed to create pkcs7 signed data\n"); +- goto cleanup; +- } +- +- } else { +- pkiDebug("received RSA key delivery AS REQ\n"); +- +- retval = krb5_c_make_random_key(context, enctype, encrypting_key); +- if (retval) { +- pkiDebug("unable to make a session key\n"); +- goto cleanup; +- } +- +- init_krb5_reply_key_pack(&key_pack); +- if (key_pack == NULL) { +- retval = ENOMEM; +- goto cleanup; +- } +- +- retval = krb5_c_make_checksum(context, 0, encrypting_key, +- KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM, +- req_pkt, &key_pack->asChecksum); +- if (retval) { +- pkiDebug("unable to calculate AS REQ checksum\n"); +- goto cleanup; +- } +-#ifdef DEBUG_CKSUM +- pkiDebug("calculating checksum on buf size = %d\n", req_pkt->length); +- print_buffer(req_pkt->data, req_pkt->length); +- pkiDebug("checksum size = %d\n", key_pack->asChecksum.length); +- print_buffer(key_pack->asChecksum.contents, +- key_pack->asChecksum.length); +- pkiDebug("encrypting key (%d)\n", encrypting_key->length); +- print_buffer(encrypting_key->contents, encrypting_key->length); +-#endif +- +- krb5_copy_keyblock_contents(context, encrypting_key, +- &key_pack->replyKey); +- +- retval = k5int_encode_krb5_reply_key_pack(key_pack, +- &encoded_key_pack); +- if (retval) { +- pkiDebug("failed to encode reply_key_pack\n"); +- goto cleanup; +- } +- +- rep->choice = choice_pa_pk_as_rep_encKeyPack; +- retval = cms_envelopeddata_create(context, plgctx->cryptoctx, +- reqctx->cryptoctx, plgctx->idctx, +- padata->pa_type, 1, +- (unsigned char *) +- encoded_key_pack->data, +- encoded_key_pack->length, +- (unsigned char **) +- &rep->u.encKeyPack.data, +- &rep->u.encKeyPack.length); +- if (retval) { +- pkiDebug("failed to create pkcs7 enveloped data: %s\n", +- error_message(retval)); +- goto cleanup; +- } +-#ifdef DEBUG_ASN1 +- print_buffer_bin((unsigned char *)encoded_key_pack->data, +- encoded_key_pack->length, +- "/tmp/kdc_key_pack"); +- print_buffer_bin(rep->u.encKeyPack.data, rep->u.encKeyPack.length, +- "/tmp/kdc_enc_key_pack"); +-#endif ++ retval = cms_signeddata_create(context, plgctx->cryptoctx, ++ reqctx->cryptoctx, plgctx->idctx, ++ CMS_SIGN_SERVER, 1, ++ (unsigned char *) ++ encoded_dhkey_info->data, ++ encoded_dhkey_info->length, ++ (unsigned char **) ++ &rep->u.dh_Info.dhSignedData.data, ++ &rep->u.dh_Info.dhSignedData.length); ++ if (retval) { ++ pkiDebug("failed to create pkcs7 signed data\n"); ++ goto cleanup; + } + +- if (rep->choice == choice_pa_pk_as_rep_dhInfo && +- ((reqctx->rcv_auth_pack != NULL && +- reqctx->rcv_auth_pack->supportedKDFs != NULL))) { ++ if (reqctx->rcv_auth_pack != NULL && ++ reqctx->rcv_auth_pack->supportedKDFs != NULL) { + + /* If using the alg-agility KDF, put the algorithm in the reply + * before encoding it. +@@ -980,35 +909,29 @@ pkinit_server_return_padata(krb5_context context, + "/tmp/kdc_as_rep"); + #endif + +- /* If this is DH, we haven't computed the key yet, so do it now. */ +- if (rep->choice == choice_pa_pk_as_rep_dhInfo) { +- +- /* If mutually supported KDFs were found, use the algorithm agility +- * KDF. */ +- if (rep->u.dh_Info.kdfID) { +- secret.data = (char *)server_key; +- secret.length = server_key_len; ++ /* If mutually supported KDFs were found, use the algorithm agility KDF. */ ++ if (rep->u.dh_Info.kdfID) { ++ secret.data = (char *)server_key; ++ secret.length = server_key_len; + +- retval = pkinit_alg_agility_kdf(context, &secret, +- rep->u.dh_Info.kdfID, +- request->client, request->server, +- enctype, req_pkt, out_data, +- encrypting_key); +- if (retval) { +- pkiDebug("pkinit_alg_agility_kdf failed: %s\n", +- error_message(retval)); +- goto cleanup; +- } ++ retval = pkinit_alg_agility_kdf(context, &secret, rep->u.dh_Info.kdfID, ++ request->client, request->server, ++ enctype, req_pkt, out_data, ++ encrypting_key); ++ if (retval) { ++ pkiDebug("pkinit_alg_agility_kdf failed: %s\n", ++ error_message(retval)); ++ goto cleanup; ++ } + +- /* Otherwise, use the older octetstring2key() function */ +- } else { +- retval = pkinit_octetstring2key(context, enctype, server_key, +- server_key_len, encrypting_key); +- if (retval) { +- pkiDebug("pkinit_octetstring2key failed: %s\n", +- error_message(retval)); +- goto cleanup; +- } ++ /* Otherwise, use the older octetstring2key() function */ ++ } else { ++ retval = pkinit_octetstring2key(context, enctype, server_key, ++ server_key_len, encrypting_key); ++ if (retval) { ++ pkiDebug("pkinit_octetstring2key failed: %s\n", ++ error_message(retval)); ++ goto cleanup; + } + } + +diff --git a/src/plugins/preauth/pkinit/pkinit_trace.h b/src/plugins/preauth/pkinit/pkinit_trace.h +index bba3226bda..4f80e0b9b6 100644 +--- a/src/plugins/preauth/pkinit/pkinit_trace.h ++++ b/src/plugins/preauth/pkinit/pkinit_trace.h +@@ -58,19 +58,10 @@ + TRACE(c, "PKINIT client verified DH reply") + #define TRACE_PKINIT_CLIENT_REP_DH_FAIL(c) \ + TRACE(c, "PKINIT client could not verify DH reply") +-#define TRACE_PKINIT_CLIENT_REP_RSA(c) \ +- TRACE(c, "PKINIT client verified RSA reply") +-#define TRACE_PKINIT_CLIENT_REP_RSA_KEY(c, keyblock, cksum) \ +- TRACE(c, "PKINIT client retrieved reply key {keyblock} from RSA " \ +- "reply (checksum {cksum})", keyblock, cksum) +-#define TRACE_PKINIT_CLIENT_REP_RSA_FAIL(c) \ +- TRACE(c, "PKINIT client could not verify RSA reply") + #define TRACE_PKINIT_CLIENT_REQ_CHECKSUM(c, cksum) \ + TRACE(c, "PKINIT client computed kdc-req-body checksum {cksum}", cksum) + #define TRACE_PKINIT_CLIENT_REQ_DH(c) \ + TRACE(c, "PKINIT client making DH request") +-#define TRACE_PKINIT_CLIENT_REQ_RSA(c) \ +- TRACE(c, "PKINIT client making RSA request") + #define TRACE_PKINIT_CLIENT_SAN_CONFIG_DNSNAME(c, host) \ + TRACE(c, "PKINIT client config accepts KDC dNSName SAN {str}", host) + #define TRACE_PKINIT_CLIENT_SAN_MATCH_DNSNAME(c, host) \ +diff --git a/src/tests/t_pkinit.py b/src/tests/t_pkinit.py +index f224383c81..e8b7b4d207 100755 +--- a/src/tests/t_pkinit.py ++++ b/src/tests/t_pkinit.py +@@ -183,15 +183,6 @@ realm.kinit(realm.user_princ, + realm.klist(realm.user_princ) + realm.run([kvno, realm.host_princ]) + +-# Try again using RSA instead of DH. +-mark('FILE identity, no password, RSA') +-realm.kinit(realm.user_princ, +- flags=['-X', 'X509_user_identity=%s' % file_identity, +- '-X', 'flag_RSA_PROTOCOL=yes'], +- expected_trace=('PKINIT client making RSA request', +- 'PKINIT client verified RSA reply')) +-realm.klist(realm.user_princ) +- + # Test a DH parameter renegotiation by temporarily setting a 4096-bit + # minimum on the KDC. (Preauth type 16 is PKINIT PA_PK_AS_REQ; + # 109 is PKINIT TD_DH_PARAMETERS; 133 is FAST PA-FX-COOKIE.) +diff --git a/src/windows/leash/htmlhelp/html/KINIT.htm b/src/windows/leash/htmlhelp/html/KINIT.htm +index eeee211a6e..46cb4a3ad8 100644 +--- a/src/windows/leash/htmlhelp/html/KINIT.htm ++++ b/src/windows/leash/htmlhelp/html/KINIT.htm +@@ -146,9 +146,6 @@ default credentials cache may vary between systems. If the KRB5CCNAME en + -S service_name + specify an alternate service name to use when getting initial + tickets. +- +- flag_RSA_PROTOCOL[=yes] +- specify use of RSA, rather than the default Diffie-Hellman protocol. + + +

ENVIRONMENT

+-- +2.46.0 + diff --git a/root/ppg/common/deps/krb5/rpm/Set-missing-mask-flags-for-kdb5_util-operations.patch b/root/ppg/common/deps/krb5/rpm/Set-missing-mask-flags-for-kdb5_util-operations.patch new file mode 100644 index 00000000..b36490e6 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Set-missing-mask-flags-for-kdb5_util-operations.patch @@ -0,0 +1,61 @@ +From 8c2dbb9260e8beab6ae7d169e9791d8756eb40a2 Mon Sep 17 00:00:00 2001 +From: Julien Rische +Date: Thu, 1 Aug 2024 10:56:07 +0200 +Subject: [PATCH] Set missing mask flags for kdb5_util operations + +Set KADM5_TL_DATA for the use_mkey and update_princ_encryption +commands. (Commit c877f13c8985d820583b0d7ac1bb4c5dc36e677e did this +for the add_new_mkey and purge_mkeys commands.) Set appropriate flags +for the add_random_key command. + +[ghudson@mit.edu: combined two commits; pruned out proposed mask flag +additions for values represented within key data or tl-data (like +KADM5_MKVNO), as those flags are currently only used in the kadm5 +protocol, not to communicate with the KDB module] + +ticket: 9158 (new) +(cherry picked from commit 4ed7da378940198cf4415f86d4eb013de6ac6455) +--- + src/kadmin/dbutil/kdb5_mkey.c | 4 +++- + src/kadmin/dbutil/kdb5_util.c | 3 +++ + 2 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/src/kadmin/dbutil/kdb5_mkey.c b/src/kadmin/dbutil/kdb5_mkey.c +index aceb0a9b80..ac5c51d05e 100644 +--- a/src/kadmin/dbutil/kdb5_mkey.c ++++ b/src/kadmin/dbutil/kdb5_mkey.c +@@ -525,6 +525,8 @@ kdb5_use_mkey(int argc, char *argv[]) + goto cleanup_return; + } + ++ master_entry->mask |= KADM5_TL_DATA; ++ + if ((retval = krb5_db_put_principal(util_context, master_entry))) { + com_err(progname, retval, + _("while adding master key entry to the database")); +@@ -814,7 +816,7 @@ update_princ_encryption_1(void *cb, krb5_db_entry *ent) + goto fail; + } + +- ent->mask |= KADM5_KEY_DATA; ++ ent->mask |= KADM5_KEY_DATA | KADM5_TL_DATA; + + if ((retval = krb5_db_put_principal(util_context, ent))) { + com_err(progname, retval, _("while updating principal '%s' key data " +diff --git a/src/kadmin/dbutil/kdb5_util.c b/src/kadmin/dbutil/kdb5_util.c +index a720eecf0b..0bb4244681 100644 +--- a/src/kadmin/dbutil/kdb5_util.c ++++ b/src/kadmin/dbutil/kdb5_util.c +@@ -600,6 +600,9 @@ add_random_key(argc, argv) + exit_status++; + return; + } ++ ++ dbent->mask |= KADM5_ATTRIBUTES | KADM5_KEY_DATA | KADM5_TL_DATA; ++ + ret = krb5_db_put_principal(util_context, dbent); + krb5_db_free_principal(util_context, dbent); + if (ret) { +-- +2.48.1 + diff --git a/root/ppg/common/deps/krb5/rpm/Try-harder-to-avoid-password-change-replay-errors.patch b/root/ppg/common/deps/krb5/rpm/Try-harder-to-avoid-password-change-replay-errors.patch new file mode 100644 index 00000000..382559ff --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Try-harder-to-avoid-password-change-replay-errors.patch @@ -0,0 +1,91 @@ +From 6b4cdaac48e6b736b66ccc21f4eed7c6fc4c2e4a Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Fri, 4 Mar 2022 00:45:00 -0500 +Subject: [PATCH] Try harder to avoid password change replay errors + +Commit d7b3018d338fc9c989c3fa17505870f23c3759a8 (ticket 7905) changed +change_set_password() to prefer TCP. However, because UDP_LAST falls +back to UDP after one second, we can still get a replay error due to a +dropped packet, before the TCP layer has a chance to retry. + +Instead, try k5_sendto() with NO_UDP, and only fall back to UDP after +TCP fails completely without reaching a server. In sendto_kdc.c, +implement an ONLY_UDP transport strategy to allow the UDP fallback. + +ticket: 9037 +--- + src/lib/krb5/os/changepw.c | 9 ++++++++- + src/lib/krb5/os/os-proto.h | 1 + + src/lib/krb5/os/sendto_kdc.c | 12 ++++++++---- + 3 files changed, 17 insertions(+), 5 deletions(-) + +diff --git a/src/lib/krb5/os/changepw.c b/src/lib/krb5/os/changepw.c +index 9f968da7f..c59232586 100644 +--- a/src/lib/krb5/os/changepw.c ++++ b/src/lib/krb5/os/changepw.c +@@ -255,9 +255,16 @@ change_set_password(krb5_context context, + callback_info.pfn_cleanup = kpasswd_sendto_msg_cleanup; + krb5_free_data_contents(callback_ctx.context, &chpw_rep); + ++ /* UDP retransmits may be seen as replays. Only try UDP after other ++ * transports fail completely. */ + code = k5_sendto(callback_ctx.context, NULL, &creds->server->realm, +- &sl, UDP_LAST, &callback_info, &chpw_rep, ++ &sl, NO_UDP, &callback_info, &chpw_rep, + ss2sa(&remote_addr), &addrlen, NULL, NULL, NULL); ++ if (code == KRB5_KDC_UNREACH) { ++ code = k5_sendto(callback_ctx.context, NULL, &creds->server->realm, ++ &sl, ONLY_UDP, &callback_info, &chpw_rep, ++ ss2sa(&remote_addr), &addrlen, NULL, NULL, NULL); ++ } + if (code) + goto cleanup; + +diff --git a/src/lib/krb5/os/os-proto.h b/src/lib/krb5/os/os-proto.h +index a16a34b74..ad3839131 100644 +--- a/src/lib/krb5/os/os-proto.h ++++ b/src/lib/krb5/os/os-proto.h +@@ -49,6 +49,7 @@ typedef enum { + UDP_FIRST = 0, + UDP_LAST, + NO_UDP, ++ ONLY_UDP + } k5_transport_strategy; + + /* A single server hostname or address. */ +diff --git a/src/lib/krb5/os/sendto_kdc.c b/src/lib/krb5/os/sendto_kdc.c +index 82523c561..d76e24ccf 100644 +--- a/src/lib/krb5/os/sendto_kdc.c ++++ b/src/lib/krb5/os/sendto_kdc.c +@@ -799,11 +799,14 @@ resolve_server(krb5_context context, const krb5_data *realm, + int err, result; + char portbuf[PORT_LENGTH]; + +- /* Skip UDP entries if we don't want UDP. */ ++ /* Skip entries excluded by the strategy. */ + if (strategy == NO_UDP && entry->transport == UDP) + return 0; ++ if (strategy == ONLY_UDP && entry->transport != UDP && ++ entry->transport != TCP_OR_UDP) ++ return 0; + +- transport = (strategy == UDP_FIRST) ? UDP : TCP; ++ transport = (strategy == UDP_FIRST || strategy == ONLY_UDP) ? UDP : TCP; + if (entry->hostname == NULL) { + /* Added by a module, so transport is either TCP or UDP. */ + ai.ai_socktype = socktype_for_transport(entry->transport); +@@ -847,8 +850,9 @@ resolve_server(krb5_context context, const krb5_data *realm, + } + + /* For TCP_OR_UDP entries, add each address again with the non-preferred +- * transport, unless we are avoiding UDP. Flag these as deferred. */ +- if (retval == 0 && entry->transport == TCP_OR_UDP && strategy != NO_UDP) { ++ * transport, if there is one. Flag these as deferred. */ ++ if (retval == 0 && entry->transport == TCP_OR_UDP && ++ (strategy == UDP_FIRST || strategy == UDP_LAST)) { + transport = (strategy == UDP_FIRST) ? TCP : UDP; + for (a = addrs; a != 0 && retval == 0; a = a->ai_next) { + a->ai_socktype = socktype_for_transport(transport); +-- +2.35.1 + diff --git a/root/ppg/common/deps/krb5/rpm/Unify-kvno-option-documentation.patch b/root/ppg/common/deps/krb5/rpm/Unify-kvno-option-documentation.patch new file mode 100644 index 00000000..81065647 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Unify-kvno-option-documentation.patch @@ -0,0 +1,186 @@ +From 6858ecbb9c407ff6d2b22cac283ea2461af1757b Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Thu, 20 Aug 2020 17:49:29 -0400 +Subject: [PATCH] Unify kvno option documentation + +Add missing kvno options to the kvno.rst synopsis and option +descriptions, and to the kvno usage message. Remove mention of '-h' +(help text), from kvno.rst as it is an implicit option. Note that the +three new caching options were added in release 1.19. + +Indicate the two exclusions (-u/-S and --u2u with the S4U2Self options) +and dependency (-P on S4U2Self) where they are missing. + +Switch xusage() to print only a single localized string, rather than +running each line of output through localization separately. + +Leave kvno -C undocumented for now, as the semantics of +KRB5_GC_CANONICALIZE are minimally useful and likely to change. + +[ghudson@mit.edu: edited documentation and commit message] + +ticket: 7476 +tags: pullup +target_version: 1.18-next + +(cherry picked from commit becd1ad6830b526d08ddaf5b2b6f213154c6446c) +(cherry picked from commit 52e3695cc5ef00766e12adfe8ed276c2885e71bb) +--- + doc/user/user_commands/kvno.rst | 24 +++++++++++++----------- + src/clients/kvno/kvno.c | 15 +++++++++------ + src/man/kvno.man | 24 +++++++++++++----------- + 3 files changed, 35 insertions(+), 28 deletions(-) + +diff --git a/doc/user/user_commands/kvno.rst b/doc/user/user_commands/kvno.rst +index 718313576..65c44e1c0 100644 +--- a/doc/user/user_commands/kvno.rst ++++ b/doc/user/user_commands/kvno.rst +@@ -10,13 +10,9 @@ SYNOPSIS + [**-c** *ccache*] + [**-e** *etype*] + [**-q**] +-[**-h**] ++[**-u** | **-S** *sname*] + [**-P**] +-[**-S** *sname*] +-[**-I** *for_user*] +-[**-U** *for_user*] +-[**-F** *cert_file*] +-[**--u2u** *ccache*] ++[[{**-F** *cert_file* | {**-I** | **-U**} *for_user*} [**-P**]] | **--u2u** *ccache*] + *service1 service2* ... + + +@@ -39,13 +35,18 @@ OPTIONS + of all the services named on the command line. This is useful in + certain backward compatibility situations. + ++**-k** *keytab* ++ Decrypt the acquired tickets using *keytab* to confirm their ++ validity. ++ + **-q** + Suppress printing output when successful. If a service ticket + cannot be obtained, an error message will still be printed and + kvno will exit with nonzero status. + +-**-h** +- Prints a usage statement and exits. ++**-u** ++ Use the unknown name type in requested service principal names. ++ This option Cannot be used with *-S*. + + **-P** + Specifies that the *service1 service2* ... arguments are to be +@@ -76,16 +77,17 @@ OPTIONS + + **--cached-only** + Only retrieve credentials already present in the cache, not from +- the KDC. ++ the KDC. (Added in release 1.19.) + + **--no-store** + Do not store retrieved credentials in the cache. If + **--out-cache** is also specified, credentials will still be +- stored into the output credential cache. ++ stored into the output credential cache. (Added in release 1.19.) + + **--out-cache** *ccache* + Initialize *ccache* and store all retrieved credentials into it. +- Do not store acquired credentials in the input cache. ++ Do not store acquired credentials in the input cache. (Added in ++ release 1.19.) + + **--u2u** *ccache* + Requests a user-to-user ticket. *ccache* must contain a local +diff --git a/src/clients/kvno/kvno.c b/src/clients/kvno/kvno.c +index 9d85864f6..c5f6bf700 100644 +--- a/src/clients/kvno/kvno.c ++++ b/src/clients/kvno/kvno.c +@@ -38,15 +38,18 @@ + static char *prog; + static int quiet = 0; + ++#define XUSAGE_BREAK "\n\t" ++ + static void + xusage() + { +- fprintf(stderr, _("usage: %s [-C] [-u] [-c ccache] [-e etype]\n"), prog); +- fprintf(stderr, _("\t[-k keytab] [-S sname] [{-I | -U} for_user | " +- "[-F cert_file] [-P]]\n")); +- fprintf(stderr, _("\t[--cached-only] [--no-store] [--out-cache ccache] " +- "[--u2u ccache]\n")); +- fprintf(stderr, _("\tservice1 service2 ...\n")); ++ fprintf(stderr, _("usage: %s [-c ccache] [-e etype] [-k keytab] [-q] " ++ "[-u | -S sname]" XUSAGE_BREAK ++ "[[{-F cert_file | {-I | -U} for_user} [-P]] | " ++ "--u2u ccache]" XUSAGE_BREAK ++ "[--cached-only] [--no-store] [--out-cache] " ++ "service1 service2 ...\n"), ++ prog); + exit(1); + } + +diff --git a/src/man/kvno.man b/src/man/kvno.man +index b9f6739eb..22318324d 100644 +--- a/src/man/kvno.man ++++ b/src/man/kvno.man +@@ -36,13 +36,9 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] + [\fB\-c\fP \fIccache\fP] + [\fB\-e\fP \fIetype\fP] + [\fB\-q\fP] +-[\fB\-h\fP] ++[\fB\-u\fP | \fB\-S\fP \fIsname\fP] + [\fB\-P\fP] +-[\fB\-S\fP \fIsname\fP] +-[\fB\-I\fP \fIfor_user\fP] +-[\fB\-U\fP \fIfor_user\fP] +-[\fB\-F\fP \fIcert_file\fP] +-[\fB\-\-u2u\fP \fIccache\fP] ++[[{\fB\-F\fP \fIcert_file\fP | {\fB\-I\fP | \fB\-U\fP} \fIfor_user\fP} [\fB\-P\fP]] | \fB\-\-u2u\fP \fIccache\fP] + \fIservice1 service2\fP ... + .SH DESCRIPTION + .sp +@@ -60,13 +56,18 @@ Specifies the enctype which will be requested for the session key + of all the services named on the command line. This is useful in + certain backward compatibility situations. + .TP ++\fB\-k\fP \fIkeytab\fP ++Decrypt the acquired tickets using \fIkeytab\fP to confirm their ++validity. ++.TP + \fB\-q\fP + Suppress printing output when successful. If a service ticket + cannot be obtained, an error message will still be printed and + kvno will exit with nonzero status. + .TP +-\fB\-h\fP +-Prints a usage statement and exits. ++\fB\-u\fP ++Use the unknown name type in requested service principal names. ++This option Cannot be used with \fI\-S\fP\&. + .TP + \fB\-P\fP + Specifies that the \fIservice1 service2\fP ... arguments are to be +@@ -97,16 +98,17 @@ certificate file must be in PEM format. + .TP + \fB\-\-cached\-only\fP + Only retrieve credentials already present in the cache, not from +-the KDC. ++the KDC. (Added in release 1.19.) + .TP + \fB\-\-no\-store\fP + Do not store retrieved credentials in the cache. If + \fB\-\-out\-cache\fP is also specified, credentials will still be +-stored into the output credential cache. ++stored into the output credential cache. (Added in release 1.19.) + .TP + \fB\-\-out\-cache\fP \fIccache\fP + Initialize \fIccache\fP and store all retrieved credentials into it. +-Do not store acquired credentials in the input cache. ++Do not store acquired credentials in the input cache. (Added in ++release 1.19.) + .TP + \fB\-\-u2u\fP \fIccache\fP + Requests a user\-to\-user ticket. \fIccache\fP must contain a local diff --git a/root/ppg/common/deps/krb5/rpm/Use-14-instead-of-9-for-unkeyed-SHA-1-checksum.patch b/root/ppg/common/deps/krb5/rpm/Use-14-instead-of-9-for-unkeyed-SHA-1-checksum.patch new file mode 100644 index 00000000..4378d399 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Use-14-instead-of-9-for-unkeyed-SHA-1-checksum.patch @@ -0,0 +1,184 @@ +From b6ada496a285a7b350e28c97b53b6f659a9a94b9 Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Sat, 11 Dec 2021 01:25:34 -0500 +Subject: [PATCH] Use 14 instead of 9 for unkeyed SHA-1 checksum + +Although MIT krb5 had been using the value 9 for unkeyed SHA-1 since +its 1.0 release in 1996, RFC 3961 instead assigned this value to +rsa-md5-des3 (likely never used), and assigned the values 10 and 14 to +SHA-1. Heimdal and Microsoft use the value 14. Unkeyed SHA-1 almost +never appears on the wire, but has been seen in PKINIT asChecksum +fields in replies from Windows KDCs (despite the field being specified +as a keyed checksum). + +Define a new symbol CKSUMTYPE_SHA1 with the value 14, and use it where +we currently use CKSUMTYPE_NIST_SHA. Continue to allow the value 9 +for ABI compatibility. Remove the pkinit_clnt.c workaround as the +value 14 will now work without adjustment. + +ticket: 9040 (new) +--- + doc/appdev/refs/macros/index.rst | 1 + + src/include/krb5/krb5.hin | 6 ++++++ + src/lib/crypto/crypto_tests/t_cksums.c | 2 +- + src/lib/crypto/krb/cksumtypes.c | 6 ++++++ + src/lib/gssapi/mechglue/g_saslname.c | 3 +-- + src/lib/krb5/os/trace.c | 2 +- + src/plugins/kdb/test/kdb_test.c | 2 +- + src/plugins/preauth/pkinit/pkinit_clnt.c | 11 ++--------- + src/plugins/preauth/pkinit/pkinit_srv.c | 4 ++-- + 9 files changed, 21 insertions(+), 16 deletions(-) + +diff --git a/doc/appdev/refs/macros/index.rst b/doc/appdev/refs/macros/index.rst +index 788d094bff..001fb386a7 100644 +--- a/doc/appdev/refs/macros/index.rst ++++ b/doc/appdev/refs/macros/index.rst +@@ -42,6 +42,7 @@ Public + CKSUMTYPE_RSA_MD4_DES.rst + CKSUMTYPE_RSA_MD5.rst + CKSUMTYPE_RSA_MD5_DES.rst ++ CKSUMTYPE_SHA1.rst + ENCTYPE_AES128_CTS_HMAC_SHA1_96.rst + ENCTYPE_AES128_CTS_HMAC_SHA256_128.rst + ENCTYPE_AES256_CTS_HMAC_SHA1_96.rst +diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin +index d2cf1eba2a..a7060aa733 100644 +--- a/src/include/krb5/krb5.hin ++++ b/src/include/krb5/krb5.hin +@@ -449,6 +449,11 @@ typedef struct _krb5_crypto_iov { + #define ENCTYPE_CAMELLIA256_CTS_CMAC 0x001a /**< RFC 6803 */ + #define ENCTYPE_UNKNOWN 0x01ff + ++/* ++ * Historically we used the value 9 for unkeyed SHA-1. RFC 3961 assigns this ++ * value to rsa-md5-des3, which fortunately is unused. For ABI compatibility ++ * we allow either 9 or 14 for SHA-1. ++ */ + #define CKSUMTYPE_CRC32 0x0001 + #define CKSUMTYPE_RSA_MD4 0x0002 + #define CKSUMTYPE_RSA_MD4_DES 0x0003 +@@ -459,6 +464,7 @@ typedef struct _krb5_crypto_iov { + #define CKSUMTYPE_RSA_MD5_DES 0x0008 + #define CKSUMTYPE_NIST_SHA 0x0009 + #define CKSUMTYPE_HMAC_SHA1_DES3 0x000c /* @deprecated removed */ ++#define CKSUMTYPE_SHA1 0x000d /**< RFC 3962 */ + #define CKSUMTYPE_HMAC_SHA1_96_AES128 0x000f /**< RFC 3962. Used with + ENCTYPE_AES128_CTS_HMAC_SHA1_96 */ + #define CKSUMTYPE_HMAC_SHA1_96_AES256 0x0010 /**< RFC 3962. Used with +diff --git a/src/lib/crypto/crypto_tests/t_cksums.c b/src/lib/crypto/crypto_tests/t_cksums.c +index 84408fb68a..de5ed3a22b 100644 +--- a/src/lib/crypto/crypto_tests/t_cksums.c ++++ b/src/lib/crypto/crypto_tests/t_cksums.c +@@ -54,7 +54,7 @@ struct test { + }, + { + { KV5M_DATA, 0, "" }, +- CKSUMTYPE_NIST_SHA, 0, 0, { KV5M_DATA, 0, "" }, ++ CKSUMTYPE_SHA1, 0, 0, { KV5M_DATA, 0, "" }, + { KV5M_DATA, 20, + "\xDA\x39\xA3\xEE\x5E\x6B\x4B\x0D\x32\x55\xBF\xEF\x95\x60\x18\x90" + "\xAF\xD8\x07\x09" } +diff --git a/src/lib/crypto/krb/cksumtypes.c b/src/lib/crypto/krb/cksumtypes.c +index f5fbe8a2a7..25a3ffd2d2 100644 +--- a/src/lib/crypto/krb/cksumtypes.c ++++ b/src/lib/crypto/krb/cksumtypes.c +@@ -46,6 +46,12 @@ const struct krb5_cksumtypes krb5int_cksumtypes_list[] = { + krb5int_unkeyed_checksum, NULL, + 20, 20, CKSUM_UNKEYED }, + ++ { CKSUMTYPE_SHA1, ++ "sha", { 0 }, "SHA-1", ++ NULL, &krb5int_hash_sha1, ++ krb5int_unkeyed_checksum, NULL, ++ 20, 20, CKSUM_UNKEYED }, ++ + { CKSUMTYPE_HMAC_MD5_ARCFOUR, + "hmac-md5-rc4", { "hmac-md5-enc", "hmac-md5-earcfour" }, + "Microsoft HMAC MD5", +diff --git a/src/lib/gssapi/mechglue/g_saslname.c b/src/lib/gssapi/mechglue/g_saslname.c +index e25f9e0a53..2be0c8a69a 100644 +--- a/src/lib/gssapi/mechglue/g_saslname.c ++++ b/src/lib/gssapi/mechglue/g_saslname.c +@@ -58,8 +58,7 @@ oidToSaslName(OM_uint32 *minor, const gss_OID mech, + iov[2].data.length = sizeof(cksumBuf); + iov[2].data.data = (char *)cksumBuf; + +- *minor = krb5_k_make_checksum_iov(NULL, CKSUMTYPE_NIST_SHA, +- NULL, 0, iov, 3); ++ *minor = krb5_k_make_checksum_iov(NULL, CKSUMTYPE_SHA1, NULL, 0, iov, 3); + if (*minor != 0) + return GSS_S_FAILURE; + +diff --git a/src/lib/krb5/os/trace.c b/src/lib/krb5/os/trace.c +index e9b99f4ca0..abb8a3f21b 100644 +--- a/src/lib/krb5/os/trace.c ++++ b/src/lib/krb5/os/trace.c +@@ -93,7 +93,7 @@ hash_bytes(krb5_context context, const void *ptr, size_t len) + krb5_data d = make_data((void *) ptr, len); + char *s = NULL; + +- if (krb5_k_make_checksum(context, CKSUMTYPE_NIST_SHA, NULL, 0, &d, ++ if (krb5_k_make_checksum(context, CKSUMTYPE_SHA1, NULL, 0, &d, + &cksum) != 0) + return NULL; + if (cksum.length >= 2) +diff --git a/src/plugins/kdb/test/kdb_test.c b/src/plugins/kdb/test/kdb_test.c +index 95a6062e2a..38d371cb86 100644 +--- a/src/plugins/kdb/test/kdb_test.c ++++ b/src/plugins/kdb/test/kdb_test.c +@@ -205,7 +205,7 @@ make_keyblock(krb5_kvno kvno, krb5_enctype etype, int32_t salttype, + (int)salttype, princstr, (int)realm->length, realm->data) < 0) + abort(); + d = string2data(hashstr); +- check(krb5_c_make_checksum(NULL, CKSUMTYPE_NIST_SHA, NULL, 0, &d, &cksum)); ++ check(krb5_c_make_checksum(NULL, CKSUMTYPE_SHA1, NULL, 0, &d, &cksum)); + + /* Make the appropriate number of input bytes from the hash result. */ + for (pos = 0; pos < keybytes; pos += n) { +diff --git a/src/plugins/preauth/pkinit/pkinit_clnt.c b/src/plugins/preauth/pkinit/pkinit_clnt.c +index 9b991ffe05..021e5f0723 100644 +--- a/src/plugins/preauth/pkinit/pkinit_clnt.c ++++ b/src/plugins/preauth/pkinit/pkinit_clnt.c +@@ -119,8 +119,8 @@ pa_pkinit_gen_req(krb5_context context, + goto cleanup; + } + +- retval = krb5_c_make_checksum(context, CKSUMTYPE_NIST_SHA, NULL, 0, +- der_req, &cksum); ++ retval = krb5_c_make_checksum(context, CKSUMTYPE_SHA1, NULL, 0, der_req, ++ &cksum); + if (retval) + goto cleanup; + TRACE_PKINIT_CLIENT_REQ_CHECKSUM(context, &cksum); +@@ -701,13 +701,6 @@ pkinit_as_rep_parse(krb5_context context, + pkiDebug("failed to decode reply_key_pack\n"); + goto cleanup; + } +- /* +- * This is hack but Windows sends back SHA1 checksum +- * with checksum type of 14. There is currently no +- * checksum type of 14 defined. +- */ +- if (key_pack->asChecksum.checksum_type == 14) +- key_pack->asChecksum.checksum_type = CKSUMTYPE_NIST_SHA; + retval = krb5_c_make_checksum(context, + key_pack->asChecksum.checksum_type, + &key_pack->replyKey, +diff --git a/src/plugins/preauth/pkinit/pkinit_srv.c b/src/plugins/preauth/pkinit/pkinit_srv.c +index 3ae56c0641..3bff456f8f 100644 +--- a/src/plugins/preauth/pkinit/pkinit_srv.c ++++ b/src/plugins/preauth/pkinit/pkinit_srv.c +@@ -546,8 +546,8 @@ pkinit_server_verify_padata(krb5_context context, + goto cleanup; + } + der_req = cb->request_body(context, rock); +- retval = krb5_c_make_checksum(context, CKSUMTYPE_NIST_SHA, NULL, 0, +- der_req, &cksum); ++ retval = krb5_c_make_checksum(context, CKSUMTYPE_SHA1, NULL, 0, der_req, ++ &cksum); + if (retval) { + pkiDebug("unable to calculate AS REQ checksum\n"); + goto cleanup; +-- +2.39.2 + diff --git a/root/ppg/common/deps/krb5/rpm/Use-KCM_OP_RETRIEVE-in-KCM-client.patch b/root/ppg/common/deps/krb5/rpm/Use-KCM_OP_RETRIEVE-in-KCM-client.patch new file mode 100644 index 00000000..a401b8ae --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Use-KCM_OP_RETRIEVE-in-KCM-client.patch @@ -0,0 +1,237 @@ +From 00a2ccfeaeac7a0019a73a97cfe33063ba90c7f3 Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Fri, 26 Mar 2021 23:38:54 -0400 +Subject: [PATCH] Use KCM_OP_RETRIEVE in KCM client + +In kcm_retrieve(), try KCM_OP_RETRIEVE. Fall back to iteration if the +server doesn't implement it, or if we can an answer incompatible with +KRB5_TC_SUPPORTED_KTYPES. + +In kcmserver.py, implement partial decoding for creds and cred tags so +that we can do a basic principal name match. + +ticket: 8997 (new) +(cherry picked from commit 795ebba8c039be172ab93cd41105c73ffdba0fdb) +(cherry picked from commit c56d4b87de0f30a38dc61d374ad225d02d581eb3) +(cherry picked from commit ac0a117096324fa73afae291ed467f2ea66e279b) +--- + src/include/kcm.h | 2 +- + src/lib/krb5/ccache/cc_kcm.c | 52 +++++++++++++++++++++++++++++++++--- + src/tests/kcmserver.py | 44 +++++++++++++++++++++++++++--- + src/tests/t_ccache.py | 11 +++++--- + 4 files changed, 99 insertions(+), 10 deletions(-) + +diff --git a/src/include/kcm.h b/src/include/kcm.h +index 9b66f1cbd..85c20d345 100644 +--- a/src/include/kcm.h ++++ b/src/include/kcm.h +@@ -87,7 +87,7 @@ typedef enum kcm_opcode { + KCM_OP_INITIALIZE, /* (name, princ) -> () */ + KCM_OP_DESTROY, /* (name) -> () */ + KCM_OP_STORE, /* (name, cred) -> () */ +- KCM_OP_RETRIEVE, ++ KCM_OP_RETRIEVE, /* (name, flags, credtag) -> (cred) */ + KCM_OP_GET_PRINCIPAL, /* (name) -> (princ) */ + KCM_OP_GET_CRED_UUID_LIST, /* (name) -> (uuid, ...) */ + KCM_OP_GET_CRED_BY_UUID, /* (name, uuid) -> (cred) */ +diff --git a/src/lib/krb5/ccache/cc_kcm.c b/src/lib/krb5/ccache/cc_kcm.c +index dae622feb..b600c6f15 100644 +--- a/src/lib/krb5/ccache/cc_kcm.c ++++ b/src/lib/krb5/ccache/cc_kcm.c +@@ -826,9 +826,55 @@ static krb5_error_code KRB5_CALLCONV + kcm_retrieve(krb5_context context, krb5_ccache cache, krb5_flags flags, + krb5_creds *mcred, krb5_creds *cred_out) + { +- /* There is a KCM opcode for retrieving creds, but Heimdal's client doesn't +- * use it. It causes the KCM daemon to actually make a TGS request. */ +- return k5_cc_retrieve_cred_default(context, cache, flags, mcred, cred_out); ++ krb5_error_code ret; ++ struct kcmreq req = EMPTY_KCMREQ; ++ krb5_creds cred; ++ krb5_enctype *enctypes = NULL; ++ ++ memset(&cred, 0, sizeof(cred)); ++ ++ /* Include KCM_GC_CACHED in flags to prevent Heimdal's sssd from making a ++ * TGS request itself. */ ++ kcmreq_init(&req, KCM_OP_RETRIEVE, cache); ++ k5_buf_add_uint32_be(&req.reqbuf, map_tcflags(flags) | KCM_GC_CACHED); ++ k5_marshal_mcred(&req.reqbuf, mcred); ++ ret = cache_call(context, cache, &req); ++ ++ /* Fall back to iteration if the server does not support retrieval. */ ++ if (ret == KRB5_FCC_INTERNAL || ret == KRB5_CC_IO) { ++ ret = k5_cc_retrieve_cred_default(context, cache, flags, mcred, ++ cred_out); ++ goto cleanup; ++ } ++ if (ret) ++ goto cleanup; ++ ++ ret = k5_unmarshal_cred(req.reply.ptr, req.reply.len, 4, &cred); ++ if (ret) ++ goto cleanup; ++ ++ /* In rare cases we might retrieve a credential with a session key this ++ * context can't support, in which case we must retry using iteration. */ ++ if (flags & KRB5_TC_SUPPORTED_KTYPES) { ++ ret = krb5_get_tgs_ktypes(context, cred.server, &enctypes); ++ if (ret) ++ goto cleanup; ++ if (!k5_etypes_contains(enctypes, cred.keyblock.enctype)) { ++ ret = k5_cc_retrieve_cred_default(context, cache, flags, mcred, ++ cred_out); ++ goto cleanup; ++ } ++ } ++ ++ *cred_out = cred; ++ memset(&cred, 0, sizeof(cred)); ++ ++cleanup: ++ kcmreq_free(&req); ++ krb5_free_cred_contents(context, &cred); ++ free(enctypes); ++ /* Heimdal's KCM returns KRB5_CC_END if no cred is found. */ ++ return (ret == KRB5_CC_END) ? KRB5_CC_NOTFOUND : map_invalid(ret); + } + + static krb5_error_code KRB5_CALLCONV +diff --git a/src/tests/kcmserver.py b/src/tests/kcmserver.py +index 8c5e66ff1..25e6f2bbe 100644 +--- a/src/tests/kcmserver.py ++++ b/src/tests/kcmserver.py +@@ -40,6 +40,7 @@ class KCMOpcodes(object): + INITIALIZE = 4 + DESTROY = 5 + STORE = 6 ++ RETRIEVE = 7 + GET_PRINCIPAL = 8 + GET_CRED_UUID_LIST = 9 + GET_CRED_BY_UUID = 10 +@@ -54,6 +55,7 @@ class KCMOpcodes(object): + + + class KRB5Errors(object): ++ KRB5_CC_NOTFOUND = -1765328243 + KRB5_CC_END = -1765328242 + KRB5_CC_NOSUPP = -1765328137 + KRB5_FCC_NOFILE = -1765328189 +@@ -86,11 +88,29 @@ def get_cache(name): + return cache + + ++def unpack_data(argbytes): ++ dlen, = struct.unpack('>L', argbytes[:4]) ++ return argbytes[4:dlen+4], argbytes[dlen+4:] ++ ++ + def unmarshal_name(argbytes): + offset = argbytes.find(b'\0') + return argbytes[0:offset], argbytes[offset+1:] + + ++def unmarshal_princ(argbytes): ++ # Ignore the type at argbytes[0:4]. ++ ncomps, = struct.unpack('>L', argbytes[4:8]) ++ realm, rest = unpack_data(argbytes[8:]) ++ comps = [] ++ for i in range(ncomps): ++ comp, rest = unpack_data(rest) ++ comps.append(comp) ++ # Asssume no quoting is needed. ++ princ = b'/'.join(comps) + b'@' + realm ++ return princ, rest ++ ++ + def op_gen_new(argbytes): + # Does not actually check for uniqueness. + global next_unique +@@ -126,6 +146,22 @@ def op_store(argbytes): + return 0, b'' + + ++def op_retrieve(argbytes): ++ name, rest = unmarshal_name(argbytes) ++ # Ignore the flags at rest[0:4] and the header at rest[4:8]. ++ # Assume there are client and server creds in the tag and match ++ # only against them. ++ cprinc, rest = unmarshal_princ(rest[8:]) ++ sprinc, rest = unmarshal_princ(rest) ++ cache = get_cache(name) ++ for cred in (cache.creds[u] for u in cache.cred_uuids): ++ cred_cprinc, rest = unmarshal_princ(cred) ++ cred_sprinc, rest = unmarshal_princ(rest) ++ if cred_cprinc == cprinc and cred_sprinc == sprinc: ++ return 0, cred ++ return KRB5Errors.KRB5_CC_NOTFOUND, b'' ++ ++ + def op_get_principal(argbytes): + name, rest = unmarshal_name(argbytes) + cache = get_cache(name) +@@ -199,6 +235,7 @@ ophandlers = { + KCMOpcodes.INITIALIZE : op_initialize, + KCMOpcodes.DESTROY : op_destroy, + KCMOpcodes.STORE : op_store, ++ KCMOpcodes.RETRIEVE : op_retrieve, + KCMOpcodes.GET_PRINCIPAL : op_get_principal, + KCMOpcodes.GET_CRED_UUID_LIST : op_get_cred_uuid_list, + KCMOpcodes.GET_CRED_BY_UUID : op_get_cred_by_uuid, +@@ -243,10 +280,11 @@ def service_request(s): + return True + + parser = optparse.OptionParser() +-parser.add_option('-c', '--credlist', action='store_true', dest='credlist', +- default=False, help='Support KCM_OP_GET_CRED_LIST') ++parser.add_option('-f', '--fallback', action='store_true', dest='fallback', ++ default=False, help='Do not support RETRIEVE/GET_CRED_LIST') + (options, args) = parser.parse_args() +-if not options.credlist: ++if options.fallback: ++ del ophandlers[KCMOpcodes.RETRIEVE] + del ophandlers[KCMOpcodes.GET_CRED_LIST] + + server = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) +diff --git a/src/tests/t_ccache.py b/src/tests/t_ccache.py +index 90040fb7b..6ea9fb969 100755 +--- a/src/tests/t_ccache.py ++++ b/src/tests/t_ccache.py +@@ -25,7 +25,7 @@ from k5test import * + kcm_socket_path = os.path.join(os.getcwd(), 'testdir', 'kcm') + conf = {'libdefaults': {'kcm_socket': kcm_socket_path, + 'kcm_mach_service': '-'}} +-realm = K5Realm(create_host=False, krb5_conf=conf) ++realm = K5Realm(krb5_conf=conf) + + keyctl = which('keyctl') + out = realm.run([klist, '-c', 'KEYRING:process:abcd'], expected_code=1) +@@ -71,6 +71,11 @@ def collection_test(realm, ccname): + realm.kinit('alice', password('alice')) + realm.run([klist], expected_msg='Default principal: alice@') + realm.run([klist, '-A', '-s']) ++ realm.run([kvno, realm.host_princ], expected_msg = 'kvno = 1') ++ realm.run([kvno, realm.host_princ], expected_msg = 'kvno = 1') ++ out = realm.run([klist]) ++ if out.count(realm.host_princ) != 1: ++ fail('Wrong number of service tickets in cache') + realm.run([kdestroy]) + output = realm.run([klist], expected_code=1) + if 'No credentials cache' not in output and 'not found' not in output: +@@ -126,14 +131,14 @@ def collection_test(realm, ccname): + + collection_test(realm, 'DIR:' + os.path.join(realm.testdir, 'cc')) + +-# Test KCM without and with GET_CRED_LIST support. ++# Test KCM with and without RETRIEVE and GET_CRED_LIST support. + kcmserver_path = os.path.join(srctop, 'tests', 'kcmserver.py') + kcmd = realm.start_server([sys.executable, kcmserver_path, kcm_socket_path], + 'starting...') + collection_test(realm, 'KCM:') + stop_daemon(kcmd) + os.remove(kcm_socket_path) +-realm.start_server([sys.executable, kcmserver_path, '-c', kcm_socket_path], ++realm.start_server([sys.executable, kcmserver_path, '-f', kcm_socket_path], + 'starting...') + collection_test(realm, 'KCM:') + diff --git a/root/ppg/common/deps/krb5/rpm/Use-SHA256-instead-of-SHA1-for-PKINIT-CMS-digest.patch b/root/ppg/common/deps/krb5/rpm/Use-SHA256-instead-of-SHA1-for-PKINIT-CMS-digest.patch new file mode 100644 index 00000000..9d0939fb --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Use-SHA256-instead-of-SHA1-for-PKINIT-CMS-digest.patch @@ -0,0 +1,124 @@ +From baa2a485190d1b31f3dae06a18dc24d71dbe35bf Mon Sep 17 00:00:00 2001 +From: Julien Rische +Date: Fri, 11 Mar 2022 12:04:14 +0100 +Subject: [PATCH] Use SHA-256 instead of SHA-1 for PKINIT CMS digest + +Various organizations including NIST have been strongly recommending to +stop using SHA-1 for digital signatures for some years already. CMS +digest is used to generate such signatures, hence it should be upgraded +to use SHA-256. +--- + .../preauth/pkinit/pkinit_crypto_openssl.c | 40 ++++++++++--------- + 1 file changed, 22 insertions(+), 18 deletions(-) + +diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c +index dbb054378..32291e3ac 100644 +--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c ++++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c +@@ -1234,7 +1234,7 @@ cms_signeddata_create(krb5_context context, + /* will not fill-out EVP_PKEY because it's on the smartcard */ + + /* Set digest algs */ +- p7si->digest_alg->algorithm = OBJ_nid2obj(NID_sha1); ++ p7si->digest_alg->algorithm = OBJ_nid2obj(NID_sha256); + + if (p7si->digest_alg->parameter != NULL) + ASN1_TYPE_free(p7si->digest_alg->parameter); +@@ -1245,17 +1245,18 @@ cms_signeddata_create(krb5_context context, + /* Set sig algs */ + if (p7si->digest_enc_alg->parameter != NULL) + ASN1_TYPE_free(p7si->digest_enc_alg->parameter); +- p7si->digest_enc_alg->algorithm = OBJ_nid2obj(NID_sha1WithRSAEncryption); ++ p7si->digest_enc_alg->algorithm = ++ OBJ_nid2obj(NID_sha256WithRSAEncryption); + if (!(p7si->digest_enc_alg->parameter = ASN1_TYPE_new())) + goto cleanup; + p7si->digest_enc_alg->parameter->type = V_ASN1_NULL; + + /* add signed attributes */ +- /* compute sha1 digest over the EncapsulatedContentInfo */ ++ /* compute sha256 digest over the EncapsulatedContentInfo */ + ctx = EVP_MD_CTX_new(); + if (ctx == NULL) + goto cleanup; +- EVP_DigestInit_ex(ctx, EVP_sha1(), NULL); ++ EVP_DigestInit_ex(ctx, EVP_sha256(), NULL); + EVP_DigestUpdate(ctx, data, data_len); + md_tmp = EVP_MD_CTX_md(ctx); + EVP_DigestFinal_ex(ctx, md_data, &md_len); +@@ -1283,12 +1284,14 @@ cms_signeddata_create(krb5_context context, + goto cleanup2; + + #ifndef WITHOUT_PKCS11 +- /* Some tokens can only do RSAEncryption without sha1 hash */ +- /* to compute sha1WithRSAEncryption, encode the algorithm ID for the hash +- * function and the hash value into an ASN.1 value of type DigestInfo +- * DigestInfo::=SEQUENCE { +- * digestAlgorithm AlgorithmIdentifier, +- * digest OCTET STRING } ++ /* ++ * Some tokens can only do RSAEncryption without a hash. To compute ++ * sha256WithRSAEncryption, encode the algorithm ID for the hash ++ * function and the hash value into an ASN.1 value of type DigestInfo: ++ * DigestInfo ::= SEQUENCE { ++ * digestAlgorithm AlgorithmIdentifier, ++ * digest OCTET STRING ++ * } + */ + if (id_cryptoctx->pkcs11_method == 1 && + id_cryptoctx->mech == CKM_RSA_PKCS) { +@@ -1304,7 +1307,7 @@ cms_signeddata_create(krb5_context context, + alg = X509_ALGOR_new(); + if (alg == NULL) + goto cleanup2; +- X509_ALGOR_set0(alg, OBJ_nid2obj(NID_sha1), V_ASN1_NULL, NULL); ++ X509_ALGOR_set0(alg, OBJ_nid2obj(NID_sha256), V_ASN1_NULL, NULL); + alg_len = i2d_X509_ALGOR(alg, NULL); + + digest = ASN1_OCTET_STRING_new(); +@@ -1333,7 +1336,7 @@ cms_signeddata_create(krb5_context context, + #endif + { + pkiDebug("mech = %s\n", +- id_cryptoctx->pkcs11_method == 1 ? "CKM_SHA1_RSA_PKCS" : "FS"); ++ id_cryptoctx->pkcs11_method == 1 ? "CKM_SHA256_RSA_PKCS" : "FS"); + retval = pkinit_sign_data(context, id_cryptoctx, abuf, alen, + &sig, &sig_len); + } +@@ -4147,7 +4150,7 @@ create_signature(unsigned char **sig, unsigned int *sig_len, + ctx = EVP_MD_CTX_new(); + if (ctx == NULL) + return ENOMEM; +- EVP_SignInit(ctx, EVP_sha1()); ++ EVP_SignInit(ctx, EVP_sha256()); + EVP_SignUpdate(ctx, data, data_len); + *sig_len = EVP_PKEY_size(pkey); + if ((*sig = malloc(*sig_len)) == NULL) +@@ -4623,10 +4626,11 @@ pkinit_get_certs_pkcs11(krb5_context context, + + #ifndef PKINIT_USE_MECH_LIST + /* +- * We'd like to use CKM_SHA1_RSA_PKCS for signing if it's available, but +- * many cards seems to be confused about whether they are capable of +- * this or not. The safe thing seems to be to ignore the mechanism list, +- * always use CKM_RSA_PKCS and calculate the sha1 digest ourselves. ++ * We'd like to use CKM_SHA256_RSA_PKCS for signing if it's available, but ++ * historically many cards seem to be confused about whether they are ++ * capable of mechanisms or not. The safe thing seems to be to ignore the ++ * mechanism list, always use CKM_RSA_PKCS and calculate the sha256 digest ++ * ourselves. + */ + + id_cryptoctx->mech = CKM_RSA_PKCS; +@@ -4654,7 +4658,7 @@ pkinit_get_certs_pkcs11(krb5_context context, + if (mechp[i] == CKM_RSA_PKCS) { + /* This seems backwards... */ + id_cryptoctx->mech = +- (info.flags & CKF_SIGN) ? CKM_SHA1_RSA_PKCS : CKM_RSA_PKCS; ++ (info.flags & CKF_SIGN) ? CKM_SHA256_RSA_PKCS : CKM_RSA_PKCS; + } + } + free(mechp); +-- +2.35.1 + diff --git a/root/ppg/common/deps/krb5/rpm/Wait-indefinitely-on-KDC-TCP-connections.patch b/root/ppg/common/deps/krb5/rpm/Wait-indefinitely-on-KDC-TCP-connections.patch new file mode 100644 index 00000000..30116950 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/Wait-indefinitely-on-KDC-TCP-connections.patch @@ -0,0 +1,138 @@ +From 2e871df888d526a15e9e91807480c15ca4e40618 Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Thu, 26 Oct 2023 16:26:42 -0400 +Subject: [PATCH] Wait indefinitely on KDC TCP connections + +When making a KDC or password change request, wait indefinitely +(limited only by request_timeout if set) once a KDC has accepted a TCP +connection. + +ticket: 9105 (new) +(cherry picked from commit 6436a3808061da787a43c6810f5f0370cdfb6e36) +--- + doc/admin/conf_files/krb5_conf.rst | 2 +- + src/lib/krb5/os/sendto_kdc.c | 50 ++++++++++++++++-------------- + 2 files changed, 27 insertions(+), 25 deletions(-) + +diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst +index 557094f6a2..98fe231813 100644 +--- a/doc/admin/conf_files/krb5_conf.rst ++++ b/doc/admin/conf_files/krb5_conf.rst +@@ -358,7 +358,7 @@ The libdefaults section may contain any of the following relations: + for initial ticket requests. The default value is 0. + + **request_timeout** +- (:ref:`duration` string.) Sets the maximum total time for KDC or ++ (:ref:`duration` string.) Sets the maximum total time for KDC and + password change requests. This timeout does not affect the + intervals between requests, so setting a low timeout may result in + fewer requests being attempted and/or some servers not being +diff --git a/src/lib/krb5/os/sendto_kdc.c b/src/lib/krb5/os/sendto_kdc.c +index f57117126e..19b78aba24 100644 +--- a/src/lib/krb5/os/sendto_kdc.c ++++ b/src/lib/krb5/os/sendto_kdc.c +@@ -134,7 +134,6 @@ struct conn_state { + krb5_data callback_buffer; + size_t server_index; + struct conn_state *next; +- time_ms endtime; + krb5_boolean defer; + struct { + const char *uri_path; +@@ -344,15 +343,19 @@ cm_select_or_poll(const struct select_state *in, time_ms endtime, + struct select_state *out, int *sret) + { + #ifndef USE_POLL +- struct timeval tv; ++ struct timeval tv, *tvp; + #endif + krb5_error_code retval; + time_ms curtime, interval; + +- retval = get_curtime_ms(&curtime); +- if (retval != 0) +- return retval; +- interval = (curtime < endtime) ? endtime - curtime : 0; ++ if (endtime != 0) { ++ retval = get_curtime_ms(&curtime); ++ if (retval != 0) ++ return retval; ++ interval = (curtime < endtime) ? endtime - curtime : 0; ++ } else { ++ interval = -1; ++ } + + /* We don't need a separate copy of the selstate for poll, but use one for + * consistency with how we use select. */ +@@ -361,9 +364,14 @@ cm_select_or_poll(const struct select_state *in, time_ms endtime, + #ifdef USE_POLL + *sret = poll(out->fds, out->nfds, interval); + #else +- tv.tv_sec = interval / 1000; +- tv.tv_usec = interval % 1000 * 1000; +- *sret = select(out->max, &out->rfds, &out->wfds, &out->xfds, &tv); ++ if (interval != -1) { ++ tv.tv_sec = interval / 1000; ++ tv.tv_usec = interval % 1000 * 1000; ++ tvp = &tv; ++ } else { ++ tvp = NULL; ++ } ++ *sret = select(out->max, &out->rfds, &out->wfds, &out->xfds, tvp); + #endif + + return (*sret < 0) ? SOCKET_ERRNO : 0; +@@ -1094,11 +1102,6 @@ service_tcp_connect(krb5_context context, const krb5_data *realm, + } + + conn->state = WRITING; +- +- /* Record this connection's timeout for service_fds. */ +- if (get_curtime_ms(&conn->endtime) == 0) +- conn->endtime += 10000; +- + return conn->service_write(context, realm, conn, selstate); + } + +@@ -1373,19 +1376,18 @@ kill_conn: + return FALSE; + } + +-/* Return the maximum of endtime and the endtime fields of all currently active +- * TCP connections. */ +-static time_ms +-get_endtime(time_ms endtime, struct conn_state *conns) ++/* Return true if conns contains any states with connected TCP sockets. */ ++static krb5_boolean ++any_tcp_connections(struct conn_state *conns) + { + struct conn_state *state; + + for (state = conns; state != NULL; state = state->next) { +- if ((state->state == READING || state->state == WRITING) && +- state->endtime > endtime) +- endtime = state->endtime; ++ if (state->addr.transport != UDP && ++ (state->state == READING || state->state == WRITING)) ++ return TRUE; + } +- return endtime; ++ return FALSE; + } + + static krb5_boolean +@@ -1408,9 +1410,9 @@ service_fds(krb5_context context, struct select_state *selstate, + + e = 0; + while (selstate->nfds > 0) { +- endtime = get_endtime(interval_end, conns); ++ endtime = any_tcp_connections(conns) ? 0 : interval_end; + /* Don't wait longer than the whole request should last. */ +- if (timeout && endtime > timeout) ++ if (timeout && (!endtime || endtime > timeout)) + endtime = timeout; + e = cm_select_or_poll(selstate, endtime, seltemp, &selret); + if (e == EINTR) +-- +2.44.0 + diff --git a/root/ppg/common/deps/krb5/rpm/downstream-Adjust-build-configuration.patch b/root/ppg/common/deps/krb5/rpm/downstream-Adjust-build-configuration.patch new file mode 100644 index 00000000..68a7878e --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/downstream-Adjust-build-configuration.patch @@ -0,0 +1,73 @@ +From 4e42a6786a06b7223f27536267492a463a700c76 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Tue, 23 Aug 2016 16:45:26 -0400 +Subject: [PATCH] [downstream] Adjust build configuration + +Build binaries in this package as RELRO PIEs, libraries as partial RELRO, +and install shared libraries with the execute bit set on them. Prune out +the -L/usr/lib* and PIE flags where they might leak out and affect +apps which just want to link with the libraries. FIXME: needs to check and +not just assume that the compiler supports using these flags. + +Last-updated: krb5-1.15-beta1 +(cherry picked from commit 92508996ed4c69fa6f5cf855fdf10f34cfa07ec9) +--- + src/build-tools/krb5-config.in | 7 +++++++ + src/config/pre.in | 2 +- + src/config/shlib.conf | 5 +++-- + 3 files changed, 11 insertions(+), 3 deletions(-) + +diff --git a/src/build-tools/krb5-config.in b/src/build-tools/krb5-config.in +index c17cb5eb5..1891dea99 100755 +--- a/src/build-tools/krb5-config.in ++++ b/src/build-tools/krb5-config.in +@@ -226,6 +226,13 @@ if test -n "$do_libs"; then + -e 's#\$(PTHREAD_CFLAGS)#'"$PTHREAD_CFLAGS"'#' \ + -e 's#\$(CFLAGS)##'` + ++ if test `dirname $libdir` = /usr ; then ++ lib_flags=`echo $lib_flags | sed -e "s#-L$libdir##" -e "s#$RPATH_FLAG$libdir##"` ++ fi ++ lib_flags=`echo $lib_flags | sed -e "s#-fPIE##g" -e "s#-pie##g"` ++ lib_flags=`echo $lib_flags | sed -e "s#-Wl,-z,relro##g"` ++ lib_flags=`echo $lib_flags | sed -e "s#-Wl,-z,now##g"` ++ + if test $library = 'kdb'; then + lib_flags="$lib_flags -lkdb5 $KDB5_DB_LIB" + library=krb5 +diff --git a/src/config/pre.in b/src/config/pre.in +index 917357df9..a8540ae2a 100644 +--- a/src/config/pre.in ++++ b/src/config/pre.in +@@ -185,7 +185,7 @@ INSTALL_PROGRAM=@INSTALL_PROGRAM@ $(INSTALL_STRIP) + INSTALL_SCRIPT=@INSTALL_PROGRAM@ + INSTALL_DATA=@INSTALL_DATA@ + INSTALL_SHLIB=@INSTALL_SHLIB@ +-INSTALL_SETUID=$(INSTALL) $(INSTALL_STRIP) -m 4755 -o root ++INSTALL_SETUID=$(INSTALL) $(INSTALL_STRIP) -m 4755 + ## This is needed because autoconf will sometimes define @exec_prefix@ to be + ## ${prefix}. + prefix=@prefix@ +diff --git a/src/config/shlib.conf b/src/config/shlib.conf +index 3e4af6c02..2b20c3fda 100644 +--- a/src/config/shlib.conf ++++ b/src/config/shlib.conf +@@ -423,7 +423,7 @@ mips-*-netbsd*) + # Linux ld doesn't default to stuffing the SONAME field... + # Use objdump -x to examine the fields of the library + # UNDEF_CHECK is suppressed by --enable-asan +- LDCOMBINE='$(CC) -shared -fPIC -Wl,-h,$(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT) $(UNDEF_CHECK)' ++ LDCOMBINE='$(CC) -shared -fPIC -Wl,-h,$(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT) $(UNDEF_CHECK) -Wl,-z,relro -Wl,--warn-shared-textrel' + UNDEF_CHECK='-Wl,--no-undefined' + # $(EXPORT_CHECK) runs export-check.pl when in maintainer mode. + LDCOMBINE_TAIL='-Wl,--version-script binutils.versions $(EXPORT_CHECK)' +@@ -435,7 +435,8 @@ mips-*-netbsd*) + SHLIB_EXPFLAGS='$(SHLIB_RPATH_FLAGS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)' + PROFFLAGS=-pg + PROG_RPATH_FLAGS='$(RPATH_FLAG)$(PROG_RPATH)' +- CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CFLAGS) $(LDFLAGS)' ++ CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CFLAGS) -pie -Wl,-z,relro -Wl,-z,now $(LDFLAGS)' ++ INSTALL_SHLIB='${INSTALL} -m755' + CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)' + CXX_LINK_SHARED='$(CXX) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CXXFLAGS) $(LDFLAGS)' + CXX_LINK_STATIC='$(CXX) $(PROG_LIBPATH) $(CXXFLAGS) $(LDFLAGS)' diff --git a/root/ppg/common/deps/krb5/rpm/downstream-Allow-to-make-AD-SIGNEDPATH-optional.patch b/root/ppg/common/deps/krb5/rpm/downstream-Allow-to-make-AD-SIGNEDPATH-optional.patch new file mode 100644 index 00000000..6f522cdc --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/downstream-Allow-to-make-AD-SIGNEDPATH-optional.patch @@ -0,0 +1,126 @@ +From 274464a6faaee694c30ae4d1412a8ab516b1a982 Mon Sep 17 00:00:00 2001 +From: Julien Rische +Date: Wed, 20 Sep 2023 16:22:06 +0200 +Subject: [PATCH] [downstream] Allow to make AD-SIGNEDPATH optional + +MIT krb5 1.20 and newer KDCs do generate a minimal PAC instead of +AD-SIGNEDPATH. As a consequence, an evidence ticket generated by an +older KDC would fail to be processed by a newer KDC for a constrained +delegation request. + +This commit modifies this behavior to check the AD-SIGNEDPATH whenever +it is present in a TGS-REQ, but do not require it in case a PAC is +provided AND the KDB plugin supports its verification. This is done +regardless to the fact the constrained delegation request is from a +local realm or a cross-realm. + +To enable this mechanism, the KDB plugin must set the +"optional_ab_signedpath" string attribute to "true" for the local TGS +principal. +--- + src/include/kdb.h | 1 + + src/kdc/kdc_authdata.c | 65 +++++++++++++++++++++++++++++++++--------- + 2 files changed, 52 insertions(+), 14 deletions(-) + +diff --git a/src/include/kdb.h b/src/include/kdb.h +index c56947ab81..95d07d0195 100644 +--- a/src/include/kdb.h ++++ b/src/include/kdb.h +@@ -136,6 +136,7 @@ + /* String attribute names recognized by krb5 */ + #define KRB5_KDB_SK_SESSION_ENCTYPES "session_enctypes" + #define KRB5_KDB_SK_REQUIRE_AUTH "require_auth" ++#define KRB5_KDB_SK_OPTIONAL_AD_SIGNEDPATH "optional_ad_signedpath" + + #if !defined(_WIN32) + +diff --git a/src/kdc/kdc_authdata.c b/src/kdc/kdc_authdata.c +index 1ebe872467..c0fcccdf21 100644 +--- a/src/kdc/kdc_authdata.c ++++ b/src/kdc/kdc_authdata.c +@@ -668,6 +668,13 @@ has_pac(krb5_context context, krb5_authdata **authdata) + return has_kdc_issued_authdata(context, authdata, KRB5_AUTHDATA_WIN2K_PAC); + } + ++/* Return true if the AD-SIGNEDPATH is present in authorization data. */ ++static krb5_boolean ++has_ad_signedpath(krb5_context context, krb5_authdata **authdata) ++{ ++ return has_kdc_issued_authdata(context, authdata, KRB5_AUTHDATA_SIGNTICKET); ++} ++ + /* Verify AD-SIGNTICKET authdata if we need to, and insert an AD-SIGNEDPATH + * element if we should. */ + static krb5_error_code +@@ -680,24 +687,54 @@ handle_signticket(krb5_context context, unsigned int flags, + { + krb5_error_code ret = 0; + krb5_principal *deleg_path = NULL; +- krb5_boolean signed_path = FALSE; +- krb5_boolean s4u2proxy; ++ krb5_boolean s4u2proxy, adsp_present, adsp_optional, adsp_valid = FALSE; ++ char *str; + + s4u2proxy = isflagset(flags, KRB5_KDB_FLAG_CONSTRAINED_DELEGATION); + +- /* For cross-realm the Windows PAC must have been verified, and it +- * fulfills the same role as the signed path. */ +- if (req->msg_type == KRB5_TGS_REQ && +- (!isflagset(flags, KRB5_KDB_FLAG_CROSS_REALM) || +- !has_pac(context, enc_tkt_req->authorization_data))) { +- ret = verify_signedpath(context, local_tgt, local_tgt_key, enc_tkt_req, +- &deleg_path, &signed_path); +- if (ret) +- goto cleanup; ++ if (req->msg_type == KRB5_TGS_REQ) { ++ adsp_present = has_ad_signedpath(context, ++ enc_tkt_req->authorization_data); ++ ++ /* In case of constained delegation, based on the value of the ++ * "optional_ad_signedpath" string attribute of the local TGS principal: ++ * - "true": in case AD-SIGNEDPATH is absent, the PAC must be present ++ * - "false" or undefined: AD-SIGNEDPATH must be present ++ */ ++ if (s4u2proxy && !adsp_present) { ++ ret = krb5_dbe_get_string(context, local_tgt, ++ KRB5_KDB_SK_OPTIONAL_AD_SIGNEDPATH, ++ &str); ++ /* TODO: should be using _krb5_conf_boolean(), but os-proto.h is not ++ * available here. ++ */ ++ adsp_optional = !ret && str && (strncasecmp(str, "true", 4) == 0 ++ || strncasecmp(str, "t", 1) == 0 ++ || strncasecmp(str, "yes", 3) == 0 ++ || strncasecmp(str, "y", 1) == 0 ++ || strncasecmp(str, "1", 1) == 0 ++ || strncasecmp(str, "on", 2) == 0); ++ ++ if (!adsp_optional || ++ !has_pac(context, enc_tkt_req->authorization_data)) { ++ ret = KRB5KDC_ERR_BADOPTION; ++ goto cleanup; ++ } ++ } + +- if (s4u2proxy && signed_path == FALSE) { +- ret = KRB5KDC_ERR_BADOPTION; +- goto cleanup; ++ /* If AD-SIGNEDPATH is present, verify it */ ++ if (adsp_present) { ++ ret = verify_signedpath(context, local_tgt, local_tgt_key, ++ enc_tkt_req, &deleg_path, &adsp_valid); ++ if (ret) ++ goto cleanup; ++ ++ /* In case of contrained delegation, if AD-SIGNEDPATH is present, it ++ * has to be valid */ ++ if (s4u2proxy && !adsp_valid) { ++ ret = KRB5KDC_ERR_BADOPTION; ++ goto cleanup; ++ } + } + } + +-- +2.41.0 + diff --git a/root/ppg/common/deps/krb5/rpm/downstream-Do-not-block-HMAC-MD4-5-in-FIPS-mode.patch b/root/ppg/common/deps/krb5/rpm/downstream-Do-not-block-HMAC-MD4-5-in-FIPS-mode.patch new file mode 100644 index 00000000..e32fedca --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/downstream-Do-not-block-HMAC-MD4-5-in-FIPS-mode.patch @@ -0,0 +1,157 @@ +From 400c8d5253a81c2bc220dc158a4f60ab7dbc5951 Mon Sep 17 00:00:00 2001 +From: Julien Rische +Date: Thu, 24 Apr 2025 15:56:32 +0200 +Subject: [PATCH] [downstream] Do not block HMAC-MD4/5 in FIPS mode + +To ensure RC4 HMAC-MD5 was not used in FIPS mode, access to HMAC-MD4/5 +was not allowed in this mode. However, since we provide the +"radius_md5_fips_override" configuration parameter to allow using RADIUS +regardless to the FIPS restrictions, we should allow HMAC-MD5 to be used +too in this case, because it is required for the newly supported +Message-Authenticator attribute. + +A FIPS mode check is added in calculate_mac() which will fail if +"radius_md5_fips_override" is not true. It will not affect interactions +between krb5kdc and ipa-otpd, because the Message-Authenticator +attribute is not generated in this case. + +This C8S patch does not include the code for loading the OpenSSL default +and legacy providers in a library context. A flag is enough to unblock +MD5 and HMAC-MD5 in FIPS mode on C8S, contrary to C9S and C10S. +--- + src/lib/crypto/openssl/hmac.c | 19 +++++++++++-------- + src/lib/krad/packet.c | 19 ++++++++++++------- + 2 files changed, 23 insertions(+), 15 deletions(-) + +diff --git a/src/lib/crypto/openssl/hmac.c b/src/lib/crypto/openssl/hmac.c +index 769a50c007..5814328e3c 100644 +--- a/src/lib/crypto/openssl/hmac.c ++++ b/src/lib/crypto/openssl/hmac.c +@@ -103,11 +103,7 @@ map_digest(const struct krb5_hash_provider *hash) + return EVP_sha256(); + else if (!strncmp(hash->hash_name, "SHA-384",7)) + return EVP_sha384(); +- +- if (FIPS_mode()) +- return NULL; +- +- if (!strncmp(hash->hash_name, "MD5", 3)) ++ else if (!strncmp(hash->hash_name, "MD5", 3)) + return EVP_md5(); + else if (!strncmp(hash->hash_name, "MD4", 3)) + return EVP_md4(); +@@ -125,6 +121,7 @@ krb5int_hmac_keyblock(const struct krb5_hash_provider *hash, + unsigned char md[EVP_MAX_MD_SIZE]; + HMAC_CTX *ctx; + size_t hashsize, blocksize; ++ const EVP_MD *md_alg; + + hashsize = hash->hashsize; + blocksize = hash->blocksize; +@@ -134,15 +131,21 @@ krb5int_hmac_keyblock(const struct krb5_hash_provider *hash, + if (output->length < hashsize) + return(KRB5_BAD_MSIZE); + +- if (!map_digest(hash)) ++ md_alg = map_digest(hash); ++ if (!md_alg) + return(KRB5_CRYPTO_INTERNAL); // unsupported alg + + ctx = HMAC_CTX_new(); + if (ctx == NULL) + return ENOMEM; + +- ok = HMAC_Init_ex(ctx, keyblock->contents, keyblock->length, +- map_digest(hash), NULL); ++ if (md_alg == EVP_md4() || md_alg == EVP_md5()) { ++ /* HMAC-MD5 and HMAC-MD4 are blocked by default in FIPS mode, ++ * but needed to support RADIUS Message-Authenticator. */ ++ HMAC_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); ++ } ++ ++ ok = HMAC_Init_ex(ctx, keyblock->contents, keyblock->length, md_alg, NULL); + for (i = 0; ok && i < num_data; i++) { + const krb5_crypto_iov *iov = &data[i]; + +diff --git a/src/lib/krad/packet.c b/src/lib/krad/packet.c +index 257bbc6345..b1a31d78cc 100644 +--- a/src/lib/krad/packet.c ++++ b/src/lib/krad/packet.c +@@ -278,7 +278,7 @@ lookup_msgauth_addr(const krad_packet *pkt) + * auth, which may be from pkt or from a corresponding request. + */ + static krb5_error_code +-calculate_mac(const char *secret, const krad_packet *pkt, ++calculate_mac(krb5_context ctx, const char *secret, const krad_packet *pkt, + const uint8_t auth[AUTH_FIELD_SIZE], + uint8_t mac_out[MD5_DIGEST_SIZE]) + { +@@ -288,6 +288,10 @@ calculate_mac(const char *secret, const krad_packet *pkt, + krb5_crypto_iov input[5]; + krb5_data ksecr, mac; + ++ /* Do not use HMAC-MD5 if not explicitly allowed */ ++ if (kr_use_fips(ctx)) ++ return KRB5_CRYPTO_INTERNAL; ++ + msgauth_attr = lookup_msgauth_addr(pkt); + if (msgauth_attr == NULL) + return EINVAL; +@@ -393,7 +397,8 @@ krad_packet_new_request(krb5_context ctx, const char *secret, krad_code code, + + if (msgauth_required) { + /* Calculate and set the Message-Authenticator MAC. */ +- retval = calculate_mac(secret, pkt, pkt_auth(pkt), pkt_attr(pkt) + 2); ++ retval = calculate_mac(ctx, secret, pkt, pkt_auth(pkt), ++ pkt_attr(pkt) + 2); + if (retval != 0) + goto error; + } +@@ -454,7 +459,7 @@ krad_packet_new_response(krb5_context ctx, const char *secret, krad_code code, + * section 5.14, use the authenticator from the request, not from the + * response. + */ +- retval = calculate_mac(secret, pkt, pkt_auth(request), ++ retval = calculate_mac(ctx, secret, pkt, pkt_auth(request), + pkt_attr(pkt) + 2); + if (retval != 0) + goto error; +@@ -476,7 +481,7 @@ error: + /* Verify the Message-Authenticator value in pkt, using the provided + * authenticator (which may be from pkt or from a corresponding request). */ + static krb5_error_code +-verify_msgauth(const char *secret, const krad_packet *pkt, ++verify_msgauth(krb5_context ctx, const char *secret, const krad_packet *pkt, + const uint8_t auth[AUTH_FIELD_SIZE]) + { + uint8_t mac[MD5_DIGEST_SIZE]; +@@ -488,7 +493,7 @@ verify_msgauth(const char *secret, const krad_packet *pkt, + if (msgauth == NULL) + return ENODATA; + +- retval = calculate_mac(secret, pkt, auth, mac); ++ retval = calculate_mac(ctx, secret, pkt, auth, mac); + if (retval) + return retval; + +@@ -561,7 +566,7 @@ krad_packet_decode_request(krb5_context ctx, const char *secret, + + /* Verify Message-Authenticator if present. */ + if (has_pkt_msgauth(req)) { +- retval = verify_msgauth(secret, req, pkt_auth(req)); ++ retval = verify_msgauth(ctx, secret, req, pkt_auth(req)); + if (retval) { + krad_packet_free(req); + return retval; +@@ -613,7 +618,7 @@ krad_packet_decode_response(krb5_context ctx, const char *secret, + + /* Verify Message-Authenticator if present. */ + if (has_pkt_msgauth(*rsppkt)) { +- if (verify_msgauth(secret, *rsppkt, pkt_auth(tmp)) != 0) ++ if (verify_msgauth(ctx, secret, *rsppkt, pkt_auth(tmp)) != 0) + continue; + } + +-- +2.49.0 + diff --git a/root/ppg/common/deps/krb5/rpm/downstream-FIPS-with-PRNG-and-RADIUS-and-MD4-5.patch b/root/ppg/common/deps/krb5/rpm/downstream-FIPS-with-PRNG-and-RADIUS-and-MD4-5.patch new file mode 100644 index 00000000..80a54ad5 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/downstream-FIPS-with-PRNG-and-RADIUS-and-MD4-5.patch @@ -0,0 +1,603 @@ +From f87e8a6734726bdd166f33757232a8c7cf9a9058 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Fri, 9 Nov 2018 15:12:21 -0500 +Subject: [PATCH] [downstream] FIPS with PRNG and RADIUS and MD4+5 + +NB: Use openssl's PRNG in FIPS mode and taint within krad. + +A lot of the FIPS error conditions from OpenSSL are incredibly +mysterious (at best, things return NULL unexpectedly; at worst, +internal assertions are tripped; most of the time, you just get +ENOMEM). In order to cope with this, we need to have some level of +awareness of what we can and can't safely call. + +This will slow down some calls slightly (FIPS_mode() takes multiple +locks), but not for any ciphers we care about - which is to say that +AES is fine. Shame about SPAKE though. + +post6 restores MD4 (and therefore keygen-only RC4). + +post7 restores MD5 and adds radius_md5_fips_override. + +Last-updated: krb5-1.17 +(cherry picked from commit bf8521bfaa4a4d54f6eb94f785c68942f4afa055) +--- + doc/admin/conf_files/krb5_conf.rst | 6 +++ + src/lib/crypto/krb/prng.c | 11 ++++- + .../crypto/openssl/enc_provider/camellia.c | 6 +++ + src/lib/crypto/openssl/enc_provider/rc4.c | 13 +++++- + .../crypto/openssl/hash_provider/hash_evp.c | 12 +++++ + src/lib/crypto/openssl/hmac.c | 6 ++- + src/lib/krad/attr.c | 46 ++++++++++++++----- + src/lib/krad/attrset.c | 5 +- + src/lib/krad/internal.h | 28 ++++++++++- + src/lib/krad/packet.c | 22 +++++---- + src/lib/krad/remote.c | 10 +++- + src/lib/krad/t_attr.c | 3 +- + src/lib/krad/t_attrset.c | 4 +- + src/plugins/preauth/spake/spake_client.c | 6 +++ + src/plugins/preauth/spake/spake_kdc.c | 6 +++ + 15 files changed, 151 insertions(+), 33 deletions(-) + +diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst +index 1d2aa7f68..3a8b9cf47 100644 +--- a/doc/admin/conf_files/krb5_conf.rst ++++ b/doc/admin/conf_files/krb5_conf.rst +@@ -331,6 +331,12 @@ The libdefaults section may contain any of the following relations: + qualification of shortnames, set this relation to the empty string + with ``qualify_shortname = ""``. (New in release 1.18.) + ++**radius_md5_fips_override** ++ Downstream-only option to enable use of MD5 in RADIUS ++ communication (libkrad). This allows for local (or protected ++ tunnel) communication with a RADIUS server that doesn't use krad ++ (e.g., freeradius) while in FIPS mode. ++ + **rdns** + If this flag is true, reverse name lookup will be used in addition + to forward name lookup to canonicalizing hostnames for use in +diff --git a/src/lib/crypto/krb/prng.c b/src/lib/crypto/krb/prng.c +index cb9ca9b98..f0e9984ca 100644 +--- a/src/lib/crypto/krb/prng.c ++++ b/src/lib/crypto/krb/prng.c +@@ -26,6 +26,8 @@ + + #include "crypto_int.h" + ++#include ++ + krb5_error_code KRB5_CALLCONV + krb5_c_random_seed(krb5_context context, krb5_data *data) + { +@@ -99,9 +101,16 @@ krb5_boolean + k5_get_os_entropy(unsigned char *buf, size_t len, int strong) + { + const char *device; +-#if defined(__linux__) && defined(SYS_getrandom) + int r; + ++ /* A wild FIPS mode appeared! */ ++ if (FIPS_mode()) { ++ /* The return codes on this API are not good */ ++ r = RAND_bytes(buf, len); ++ return r == 1; ++ } ++ ++#if defined(__linux__) && defined(SYS_getrandom) + while (len > 0) { + /* + * Pull from the /dev/urandom pool, but require it to have been seeded. +diff --git a/src/lib/crypto/openssl/enc_provider/camellia.c b/src/lib/crypto/openssl/enc_provider/camellia.c +index 2da691329..f79679a0b 100644 +--- a/src/lib/crypto/openssl/enc_provider/camellia.c ++++ b/src/lib/crypto/openssl/enc_provider/camellia.c +@@ -304,6 +304,9 @@ krb5int_camellia_cbc_mac(krb5_key key, const krb5_crypto_iov *data, + unsigned char blockY[CAMELLIA_BLOCK_SIZE], blockB[CAMELLIA_BLOCK_SIZE]; + struct iov_cursor cursor; + ++ if (FIPS_mode()) ++ return KRB5_CRYPTO_INTERNAL; ++ + if (output->length < CAMELLIA_BLOCK_SIZE) + return KRB5_BAD_MSIZE; + +@@ -331,6 +334,9 @@ static krb5_error_code + krb5int_camellia_init_state (const krb5_keyblock *key, krb5_keyusage usage, + krb5_data *state) + { ++ if (FIPS_mode()) ++ return KRB5_CRYPTO_INTERNAL; ++ + state->length = 16; + state->data = (void *) malloc(16); + if (state->data == NULL) +diff --git a/src/lib/crypto/openssl/enc_provider/rc4.c b/src/lib/crypto/openssl/enc_provider/rc4.c +index a65d57b7a..6ccaca94a 100644 +--- a/src/lib/crypto/openssl/enc_provider/rc4.c ++++ b/src/lib/crypto/openssl/enc_provider/rc4.c +@@ -66,6 +66,9 @@ k5_arcfour_docrypt(krb5_key key, const krb5_data *state, krb5_crypto_iov *data, + EVP_CIPHER_CTX *ctx = NULL; + struct arcfour_state *arcstate; + ++ if (FIPS_mode()) ++ return KRB5_CRYPTO_INTERNAL; ++ + arcstate = (state != NULL) ? (void *)state->data : NULL; + if (arcstate != NULL) { + ctx = arcstate->ctx; +@@ -113,7 +116,12 @@ k5_arcfour_docrypt(krb5_key key, const krb5_data *state, krb5_crypto_iov *data, + static void + k5_arcfour_free_state(krb5_data *state) + { +- struct arcfour_state *arcstate = (void *)state->data; ++ struct arcfour_state *arcstate; ++ ++ if (FIPS_mode()) ++ return; ++ ++ arcstate = (void *) state->data; + + EVP_CIPHER_CTX_free(arcstate->ctx); + free(arcstate); +@@ -125,6 +133,9 @@ k5_arcfour_init_state(const krb5_keyblock *key, + { + struct arcfour_state *arcstate; + ++ if (FIPS_mode()) ++ return KRB5_CRYPTO_INTERNAL; ++ + /* + * The cipher state here is a saved pointer to a struct arcfour_state + * object, rather than a flat byte array as in most enc providers. The +diff --git a/src/lib/crypto/openssl/hash_provider/hash_evp.c b/src/lib/crypto/openssl/hash_provider/hash_evp.c +index 1e0fb8fc3..2eb5139c0 100644 +--- a/src/lib/crypto/openssl/hash_provider/hash_evp.c ++++ b/src/lib/crypto/openssl/hash_provider/hash_evp.c +@@ -49,6 +49,11 @@ hash_evp(const EVP_MD *type, const krb5_crypto_iov *data, size_t num_data, + if (ctx == NULL) + return ENOMEM; + ++ if (type == EVP_md4() || type == EVP_md5()) { ++ /* See comments below in hash_md4() and hash_md5(). */ ++ EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); ++ } ++ + ok = EVP_DigestInit_ex(ctx, type, NULL); + for (i = 0; i < num_data; i++) { + if (!SIGN_IOV(&data[i])) +@@ -64,12 +69,19 @@ hash_evp(const EVP_MD *type, const krb5_crypto_iov *data, size_t num_data, + static krb5_error_code + hash_md4(const krb5_crypto_iov *data, size_t num_data, krb5_data *output) + { ++ /* ++ * MD4 is needed in FIPS mode to perform key generation for RC4 keys used ++ * by IPA. These keys are only used along a (separately) secured channel ++ * for legacy reasons when performing trusts to Active Directory. ++ */ + return hash_evp(EVP_md4(), data, num_data, output); + } + + static krb5_error_code + hash_md5(const krb5_crypto_iov *data, size_t num_data, krb5_data *output) + { ++ /* MD5 is needed in FIPS mode for communication with RADIUS servers. This ++ * is gated in libkrad by libdefaults->radius_md5_fips_override. */ + return hash_evp(EVP_md5(), data, num_data, output); + } + +diff --git a/src/lib/crypto/openssl/hmac.c b/src/lib/crypto/openssl/hmac.c +index 7dc59dcc0..769a50c00 100644 +--- a/src/lib/crypto/openssl/hmac.c ++++ b/src/lib/crypto/openssl/hmac.c +@@ -103,7 +103,11 @@ map_digest(const struct krb5_hash_provider *hash) + return EVP_sha256(); + else if (!strncmp(hash->hash_name, "SHA-384",7)) + return EVP_sha384(); +- else if (!strncmp(hash->hash_name, "MD5", 3)) ++ ++ if (FIPS_mode()) ++ return NULL; ++ ++ if (!strncmp(hash->hash_name, "MD5", 3)) + return EVP_md5(); + else if (!strncmp(hash->hash_name, "MD4", 3)) + return EVP_md4(); +diff --git a/src/lib/krad/attr.c b/src/lib/krad/attr.c +index 9c13d9d75..42d354a3b 100644 +--- a/src/lib/krad/attr.c ++++ b/src/lib/krad/attr.c +@@ -38,7 +38,8 @@ + typedef krb5_error_code + (*attribute_transform_fn)(krb5_context ctx, const char *secret, + const unsigned char *auth, const krb5_data *in, +- unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen); ++ unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen, ++ krb5_boolean *is_fips); + + typedef struct { + const char *name; +@@ -51,12 +52,14 @@ typedef struct { + static krb5_error_code + user_password_encode(krb5_context ctx, const char *secret, + const unsigned char *auth, const krb5_data *in, +- unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen); ++ unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen, ++ krb5_boolean *is_fips); + + static krb5_error_code + user_password_decode(krb5_context ctx, const char *secret, + const unsigned char *auth, const krb5_data *in, +- unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen); ++ unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen, ++ krb5_boolean *ignored); + + static const attribute_record attributes[UCHAR_MAX] = { + {"User-Name", 1, MAX_ATTRSIZE, NULL, NULL}, +@@ -128,7 +131,8 @@ static const attribute_record attributes[UCHAR_MAX] = { + static krb5_error_code + user_password_encode(krb5_context ctx, const char *secret, + const unsigned char *auth, const krb5_data *in, +- unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen) ++ unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen, ++ krb5_boolean *is_fips) + { + const unsigned char *indx; + krb5_error_code retval; +@@ -154,8 +158,15 @@ user_password_encode(krb5_context ctx, const char *secret, + for (blck = 0, indx = auth; blck * BLOCKSIZE < len; blck++) { + memcpy(tmp.data + seclen, indx, BLOCKSIZE); + +- retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0, &tmp, +- &sum); ++ if (kr_use_fips(ctx)) { ++ /* Skip encryption here. Taint so that we won't pass it out of ++ * the machine by accident. */ ++ *is_fips = TRUE; ++ sum.contents = calloc(1, BLOCKSIZE); ++ } else { ++ retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0, &tmp, ++ &sum); ++ } + if (retval != 0) { + zap(tmp.data, tmp.length); + zap(outbuf, len); +@@ -180,7 +191,8 @@ user_password_encode(krb5_context ctx, const char *secret, + static krb5_error_code + user_password_decode(krb5_context ctx, const char *secret, + const unsigned char *auth, const krb5_data *in, +- unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen) ++ unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen, ++ krb5_boolean *is_fips) + { + const unsigned char *indx; + krb5_error_code retval; +@@ -204,8 +216,15 @@ user_password_decode(krb5_context ctx, const char *secret, + for (blck = 0, indx = auth; blck * BLOCKSIZE < in->length; blck++) { + memcpy(tmp.data + seclen, indx, BLOCKSIZE); + +- retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0, +- &tmp, &sum); ++ if (kr_use_fips(ctx)) { ++ /* Skip encryption here. Taint so that we won't pass it out of ++ * the machine by accident. */ ++ *is_fips = TRUE; ++ sum.contents = calloc(1, BLOCKSIZE); ++ } else { ++ retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0, ++ &tmp, &sum); ++ } + if (retval != 0) { + zap(tmp.data, tmp.length); + zap(outbuf, in->length); +@@ -248,7 +267,7 @@ krb5_error_code + kr_attr_encode(krb5_context ctx, const char *secret, + const unsigned char *auth, krad_attr type, + const krb5_data *in, unsigned char outbuf[MAX_ATTRSIZE], +- size_t *outlen) ++ size_t *outlen, krb5_boolean *is_fips) + { + krb5_error_code retval; + +@@ -265,7 +284,8 @@ kr_attr_encode(krb5_context ctx, const char *secret, + return 0; + } + +- return attributes[type - 1].encode(ctx, secret, auth, in, outbuf, outlen); ++ return attributes[type - 1].encode(ctx, secret, auth, in, outbuf, outlen, ++ is_fips); + } + + krb5_error_code +@@ -274,6 +294,7 @@ kr_attr_decode(krb5_context ctx, const char *secret, const unsigned char *auth, + unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen) + { + krb5_error_code retval; ++ krb5_boolean ignored; + + retval = kr_attr_valid(type, in); + if (retval != 0) +@@ -288,7 +309,8 @@ kr_attr_decode(krb5_context ctx, const char *secret, const unsigned char *auth, + return 0; + } + +- return attributes[type - 1].decode(ctx, secret, auth, in, outbuf, outlen); ++ return attributes[type - 1].decode(ctx, secret, auth, in, outbuf, outlen, ++ &ignored); + } + + krad_attr +diff --git a/src/lib/krad/attrset.c b/src/lib/krad/attrset.c +index 03c613716..d89982a13 100644 +--- a/src/lib/krad/attrset.c ++++ b/src/lib/krad/attrset.c +@@ -167,7 +167,8 @@ krad_attrset_copy(const krad_attrset *set, krad_attrset **copy) + krb5_error_code + kr_attrset_encode(const krad_attrset *set, const char *secret, + const unsigned char *auth, +- unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen) ++ unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen, ++ krb5_boolean *is_fips) + { + unsigned char buffer[MAX_ATTRSIZE]; + krb5_error_code retval; +@@ -181,7 +182,7 @@ kr_attrset_encode(const krad_attrset *set, const char *secret, + + K5_TAILQ_FOREACH(a, &set->list, list) { + retval = kr_attr_encode(set->ctx, secret, auth, a->type, &a->attr, +- buffer, &attrlen); ++ buffer, &attrlen, is_fips); + if (retval != 0) + return retval; + +diff --git a/src/lib/krad/internal.h b/src/lib/krad/internal.h +index 996a89372..312dc8258 100644 +--- a/src/lib/krad/internal.h ++++ b/src/lib/krad/internal.h +@@ -39,6 +39,8 @@ + #include + #include + ++#include ++ + #ifndef UCHAR_MAX + #define UCHAR_MAX 255 + #endif +@@ -49,6 +51,13 @@ + + typedef struct krad_remote_st krad_remote; + ++struct krad_packet_st { ++ char buffer[KRAD_PACKET_SIZE_MAX]; ++ krad_attrset *attrset; ++ krb5_data pkt; ++ krb5_boolean is_fips; ++}; ++ + /* Validate constraints of an attribute. */ + krb5_error_code + kr_attr_valid(krad_attr type, const krb5_data *data); +@@ -57,7 +66,8 @@ kr_attr_valid(krad_attr type, const krb5_data *data); + krb5_error_code + kr_attr_encode(krb5_context ctx, const char *secret, const unsigned char *auth, + krad_attr type, const krb5_data *in, +- unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen); ++ unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen, ++ krb5_boolean *is_fips); + + /* Decode an attribute. */ + krb5_error_code +@@ -69,7 +79,8 @@ kr_attr_decode(krb5_context ctx, const char *secret, const unsigned char *auth, + krb5_error_code + kr_attrset_encode(const krad_attrset *set, const char *secret, + const unsigned char *auth, +- unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen); ++ unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen, ++ krb5_boolean *is_fips); + + /* Decode attributes from a buffer. */ + krb5_error_code +@@ -152,4 +163,17 @@ gai_error_code(int err) + } + } + ++static inline krb5_boolean ++kr_use_fips(krb5_context ctx) ++{ ++ int val = 0; ++ ++ if (!FIPS_mode()) ++ return 0; ++ ++ profile_get_boolean(ctx->profile, "libdefaults", ++ "radius_md5_fips_override", NULL, 0, &val); ++ return !val; ++} ++ + #endif /* INTERNAL_H_ */ +diff --git a/src/lib/krad/packet.c b/src/lib/krad/packet.c +index c597174b6..fc2d24800 100644 +--- a/src/lib/krad/packet.c ++++ b/src/lib/krad/packet.c +@@ -53,12 +53,6 @@ typedef unsigned char uchar; + #define pkt_auth(p) ((uchar *)offset(&(p)->pkt, OFFSET_AUTH)) + #define pkt_attr(p) ((unsigned char *)offset(&(p)->pkt, OFFSET_ATTR)) + +-struct krad_packet_st { +- char buffer[KRAD_PACKET_SIZE_MAX]; +- krad_attrset *attrset; +- krb5_data pkt; +-}; +- + typedef struct { + uchar x[(UCHAR_MAX + 1) / 8]; + } idmap; +@@ -187,8 +181,14 @@ auth_generate_response(krb5_context ctx, const char *secret, + memcpy(data.data + response->pkt.length, secret, strlen(secret)); + + /* Hash it. */ +- retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0, &data, +- &hash); ++ if (kr_use_fips(ctx)) { ++ /* This checksum does very little security-wise anyway, so don't ++ * taint. */ ++ hash.contents = calloc(1, AUTH_FIELD_SIZE); ++ } else { ++ retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0, &data, ++ &hash); ++ } + free(data.data); + if (retval != 0) + return retval; +@@ -276,7 +276,7 @@ krad_packet_new_request(krb5_context ctx, const char *secret, krad_code code, + + /* Encode the attributes. */ + retval = kr_attrset_encode(set, secret, pkt_auth(pkt), pkt_attr(pkt), +- &attrset_len); ++ &attrset_len, &pkt->is_fips); + if (retval != 0) + goto error; + +@@ -314,7 +314,7 @@ krad_packet_new_response(krb5_context ctx, const char *secret, krad_code code, + + /* Encode the attributes. */ + retval = kr_attrset_encode(set, secret, pkt_auth(request), pkt_attr(pkt), +- &attrset_len); ++ &attrset_len, &pkt->is_fips); + if (retval != 0) + goto error; + +@@ -451,6 +451,8 @@ krad_packet_decode_response(krb5_context ctx, const char *secret, + const krb5_data * + krad_packet_encode(const krad_packet *pkt) + { ++ if (pkt->is_fips) ++ return NULL; + return &pkt->pkt; + } + +diff --git a/src/lib/krad/remote.c b/src/lib/krad/remote.c +index 437f7e91a..0f90443ce 100644 +--- a/src/lib/krad/remote.c ++++ b/src/lib/krad/remote.c +@@ -263,7 +263,7 @@ on_io_write(krad_remote *rr) + request *r; + + K5_TAILQ_FOREACH(r, &rr->list, list) { +- tmp = krad_packet_encode(r->request); ++ tmp = &r->request->pkt; + + /* If the packet has already been sent, do nothing. */ + if (r->sent == tmp->length) +@@ -359,7 +359,7 @@ on_io_read(krad_remote *rr) + if (req != NULL) { + K5_TAILQ_FOREACH(r, &rr->list, list) { + if (r->request == req && +- r->sent == krad_packet_encode(req)->length) { ++ r->sent == req->pkt.length) { + request_finish(r, 0, rsp); + break; + } +@@ -455,6 +455,12 @@ kr_remote_send(krad_remote *rr, krad_code code, krad_attrset *attrs, + (krad_packet_iter_cb)iterator, &r, &tmp); + if (retval != 0) + goto error; ++ else if (tmp->is_fips && rr->info->ai_family != AF_LOCAL && ++ rr->info->ai_family != AF_UNIX) { ++ /* This would expose cleartext passwords, so abort. */ ++ retval = ESOCKTNOSUPPORT; ++ goto error; ++ } + + K5_TAILQ_FOREACH(r, &rr->list, list) { + if (r->request == tmp) { +diff --git a/src/lib/krad/t_attr.c b/src/lib/krad/t_attr.c +index eb2a780c8..4d285ad9d 100644 +--- a/src/lib/krad/t_attr.c ++++ b/src/lib/krad/t_attr.c +@@ -50,6 +50,7 @@ main() + const char *tmp; + krb5_data in; + size_t len; ++ krb5_boolean is_fips = FALSE; + + noerror(krb5_init_context(&ctx)); + +@@ -73,7 +74,7 @@ main() + in = string2data((char *)decoded); + retval = kr_attr_encode(ctx, secret, auth, + krad_attr_name2num("User-Password"), +- &in, outbuf, &len); ++ &in, outbuf, &len, &is_fips); + insist(retval == 0); + insist(len == sizeof(encoded)); + insist(memcmp(outbuf, encoded, len) == 0); +diff --git a/src/lib/krad/t_attrset.c b/src/lib/krad/t_attrset.c +index 7928335ca..0f9576253 100644 +--- a/src/lib/krad/t_attrset.c ++++ b/src/lib/krad/t_attrset.c +@@ -49,6 +49,7 @@ main() + krb5_context ctx; + size_t len = 0, encode_len; + krb5_data tmp; ++ krb5_boolean is_fips = FALSE; + + noerror(krb5_init_context(&ctx)); + noerror(krad_attrset_new(ctx, &set)); +@@ -62,7 +63,8 @@ main() + noerror(krad_attrset_add(set, krad_attr_name2num("User-Password"), &tmp)); + + /* Encode attrset. */ +- noerror(kr_attrset_encode(set, "foo", auth, buffer, &encode_len)); ++ noerror(kr_attrset_encode(set, "foo", auth, buffer, &encode_len, ++ &is_fips)); + krad_attrset_free(set); + + /* Manually encode User-Name. */ +diff --git a/src/plugins/preauth/spake/spake_client.c b/src/plugins/preauth/spake/spake_client.c +index 00734a13b..a3ce22b70 100644 +--- a/src/plugins/preauth/spake/spake_client.c ++++ b/src/plugins/preauth/spake/spake_client.c +@@ -38,6 +38,8 @@ + #include "groups.h" + #include + ++#include ++ + typedef struct reqstate_st { + krb5_pa_spake *msg; /* set in prep_questions, used in process */ + krb5_keyblock *initial_key; +@@ -375,6 +377,10 @@ clpreauth_spake_initvt(krb5_context context, int maj_ver, int min_ver, + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; ++ ++ if (FIPS_mode()) ++ return KRB5_CRYPTO_INTERNAL; ++ + vt = (krb5_clpreauth_vtable)vtable; + vt->name = "spake"; + vt->pa_type_list = pa_types; +diff --git a/src/plugins/preauth/spake/spake_kdc.c b/src/plugins/preauth/spake/spake_kdc.c +index 88c964ce1..c7df0392f 100644 +--- a/src/plugins/preauth/spake/spake_kdc.c ++++ b/src/plugins/preauth/spake/spake_kdc.c +@@ -41,6 +41,8 @@ + + #include + ++#include ++ + /* + * The SPAKE kdcpreauth module uses a secure cookie containing the following + * concatenated fields (all integer fields are big-endian): +@@ -571,6 +573,10 @@ kdcpreauth_spake_initvt(krb5_context context, int maj_ver, int min_ver, + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; ++ ++ if (FIPS_mode()) ++ return KRB5_CRYPTO_INTERNAL; ++ + vt = (krb5_kdcpreauth_vtable)vtable; + vt->name = "spake"; + vt->pa_type_list = pa_types; diff --git a/root/ppg/common/deps/krb5/rpm/downstream-Fix-dejagnu-unit-tests-directory-name-for-RPC-lib.patch b/root/ppg/common/deps/krb5/rpm/downstream-Fix-dejagnu-unit-tests-directory-name-for-RPC-lib.patch new file mode 100644 index 00000000..7028373e --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/downstream-Fix-dejagnu-unit-tests-directory-name-for-RPC-lib.patch @@ -0,0 +1,156 @@ +From 10b32480395a01798b21818e884a593930b400d1 Mon Sep 17 00:00:00 2001 +From: Julien Rische +Date: Wed, 27 Apr 2022 15:29:08 +0200 +Subject: [PATCH] Fix dejagnu unit tests directory name for RPC lib + +This commit renames RPC library's unit tests directory to match the +newly enforced naming convention of dejagnu. + +Resolves: rhbz#2070879 + +Signed-off-by: Julien Rische +--- + src/configure.ac | 2 +- + src/lib/rpc/Makefile.in | 2 +- + src/lib/rpc/{unit-test => testsuite}/Makefile.in | 10 +++++----- + src/lib/rpc/{unit-test => testsuite}/client.c | 0 + src/lib/rpc/{unit-test => testsuite}/config/unix.exp | 0 + src/lib/rpc/{unit-test => testsuite}/deps | 0 + src/lib/rpc/{unit-test => testsuite}/lib/helpers.exp | 0 + .../rpc/{unit-test => testsuite}/rpc_test.0/expire.exp | 0 + .../{unit-test => testsuite}/rpc_test.0/fullrun.exp | 0 + .../rpc/{unit-test => testsuite}/rpc_test.0/gsserr.exp | 0 + src/lib/rpc/{unit-test => testsuite}/rpc_test.h | 0 + src/lib/rpc/{unit-test => testsuite}/rpc_test.x | 0 + src/lib/rpc/{unit-test => testsuite}/rpc_test_clnt.c | 0 + src/lib/rpc/{unit-test => testsuite}/rpc_test_svc.c | 0 + src/lib/rpc/{unit-test => testsuite}/server.c | 0 + 15 files changed, 7 insertions(+), 7 deletions(-) + rename src/lib/rpc/{unit-test => testsuite}/Makefile.in (93%) + rename src/lib/rpc/{unit-test => testsuite}/client.c (100%) + rename src/lib/rpc/{unit-test => testsuite}/config/unix.exp (100%) + rename src/lib/rpc/{unit-test => testsuite}/deps (100%) + rename src/lib/rpc/{unit-test => testsuite}/lib/helpers.exp (100%) + rename src/lib/rpc/{unit-test => testsuite}/rpc_test.0/expire.exp (100%) + rename src/lib/rpc/{unit-test => testsuite}/rpc_test.0/fullrun.exp (100%) + rename src/lib/rpc/{unit-test => testsuite}/rpc_test.0/gsserr.exp (100%) + rename src/lib/rpc/{unit-test => testsuite}/rpc_test.h (100%) + rename src/lib/rpc/{unit-test => testsuite}/rpc_test.x (100%) + rename src/lib/rpc/{unit-test => testsuite}/rpc_test_clnt.c (100%) + rename src/lib/rpc/{unit-test => testsuite}/rpc_test_svc.c (100%) + rename src/lib/rpc/{unit-test => testsuite}/server.c (100%) + +diff --git a/src/configure.ac b/src/configure.ac +index 37e36b76d..2a48aa83d 100644 +--- a/src/configure.ac ++++ b/src/configure.ac +@@ -1497,7 +1497,7 @@ V5_AC_OUTPUT_MAKEFILE(. + lib/gssapi lib/gssapi/generic lib/gssapi/krb5 lib/gssapi/spnego + lib/gssapi/mechglue + +- lib/rpc lib/rpc/unit-test ++ lib/rpc lib/rpc/testsuite + + lib/kadm5 lib/kadm5/clnt lib/kadm5/srv lib/kadm5/testsuite + lib/krad +diff --git a/src/lib/rpc/Makefile.in b/src/lib/rpc/Makefile.in +index 6b5f1e70a..78c7a1326 100644 +--- a/src/lib/rpc/Makefile.in ++++ b/src/lib/rpc/Makefile.in +@@ -2,7 +2,7 @@ mydir=lib$(S)rpc + BUILDTOP=$(REL)..$(S).. + DEFINES = -DGSSAPI_KRB5 -DDEBUG_GSSAPI=0 -DGSSRPC__IMPL + +-SUBDIRS=unit-test ++SUBDIRS=testsuite + + ##DOSBUILDTOP = ..\.. + ##DOSLIBNAME=libgssrpc.lib +diff --git a/src/lib/rpc/unit-test/Makefile.in b/src/lib/rpc/testsuite/Makefile.in +similarity index 93% +rename from src/lib/rpc/unit-test/Makefile.in +rename to src/lib/rpc/testsuite/Makefile.in +index 0b6e5203d..0fab26c10 100644 +--- a/src/lib/rpc/unit-test/Makefile.in ++++ b/src/lib/rpc/testsuite/Makefile.in +@@ -1,4 +1,4 @@ +-mydir=lib$(S)rpc$(S)unit-test ++mydir=lib$(S)rpc$(S)testsuite + BUILDTOP=$(REL)..$(S)..$(S).. + + OBJS= client.o rpc_test_clnt.o rpc_test_svc.o server.o +@@ -34,19 +34,19 @@ runenv.exp: Makefile + # rm -f rpc_test.h rpc_test_clnt.c rpc_test_svc.c + # + +-check unit-test: unit-test-@DO_TEST@ ++check testsuite: testsuite-@DO_TEST@ + +-unit-test-: ++testsuite-: + @echo "+++" + @echo "+++ WARNING: lib/rpc unit tests not run." + @echo "+++ Either tcl, runtest, or Perl is unavailable." + @echo "+++" + @echo 'Skipped rpc tests: runtest or Perl not found' >> $(SKIPTESTS) + +-unit-test-ok: unit-test-body ++testsuite-ok: testsuite-body + + PASS=@PASS@ +-unit-test-body: runenv.sh runenv.exp ++testsuite-body: runenv.sh runenv.exp + $(RM) krb5cc_rpc_test_* + $(ENV_SETUP) $(VALGRIND) $(START_SERVERS) + RPC_TEST_KEYTAB=/tmp/rpc_test_keytab.$$$$ ; export RPC_TEST_KEYTAB ; \ +diff --git a/src/lib/rpc/unit-test/client.c b/src/lib/rpc/testsuite/client.c +similarity index 100% +rename from src/lib/rpc/unit-test/client.c +rename to src/lib/rpc/testsuite/client.c +diff --git a/src/lib/rpc/unit-test/config/unix.exp b/src/lib/rpc/testsuite/config/unix.exp +similarity index 100% +rename from src/lib/rpc/unit-test/config/unix.exp +rename to src/lib/rpc/testsuite/config/unix.exp +diff --git a/src/lib/rpc/unit-test/deps b/src/lib/rpc/testsuite/deps +similarity index 100% +rename from src/lib/rpc/unit-test/deps +rename to src/lib/rpc/testsuite/deps +diff --git a/src/lib/rpc/unit-test/lib/helpers.exp b/src/lib/rpc/testsuite/lib/helpers.exp +similarity index 100% +rename from src/lib/rpc/unit-test/lib/helpers.exp +rename to src/lib/rpc/testsuite/lib/helpers.exp +diff --git a/src/lib/rpc/unit-test/rpc_test.0/expire.exp b/src/lib/rpc/testsuite/rpc_test.0/expire.exp +similarity index 100% +rename from src/lib/rpc/unit-test/rpc_test.0/expire.exp +rename to src/lib/rpc/testsuite/rpc_test.0/expire.exp +diff --git a/src/lib/rpc/unit-test/rpc_test.0/fullrun.exp b/src/lib/rpc/testsuite/rpc_test.0/fullrun.exp +similarity index 100% +rename from src/lib/rpc/unit-test/rpc_test.0/fullrun.exp +rename to src/lib/rpc/testsuite/rpc_test.0/fullrun.exp +diff --git a/src/lib/rpc/unit-test/rpc_test.0/gsserr.exp b/src/lib/rpc/testsuite/rpc_test.0/gsserr.exp +similarity index 100% +rename from src/lib/rpc/unit-test/rpc_test.0/gsserr.exp +rename to src/lib/rpc/testsuite/rpc_test.0/gsserr.exp +diff --git a/src/lib/rpc/unit-test/rpc_test.h b/src/lib/rpc/testsuite/rpc_test.h +similarity index 100% +rename from src/lib/rpc/unit-test/rpc_test.h +rename to src/lib/rpc/testsuite/rpc_test.h +diff --git a/src/lib/rpc/unit-test/rpc_test.x b/src/lib/rpc/testsuite/rpc_test.x +similarity index 100% +rename from src/lib/rpc/unit-test/rpc_test.x +rename to src/lib/rpc/testsuite/rpc_test.x +diff --git a/src/lib/rpc/unit-test/rpc_test_clnt.c b/src/lib/rpc/testsuite/rpc_test_clnt.c +similarity index 100% +rename from src/lib/rpc/unit-test/rpc_test_clnt.c +rename to src/lib/rpc/testsuite/rpc_test_clnt.c +diff --git a/src/lib/rpc/unit-test/rpc_test_svc.c b/src/lib/rpc/testsuite/rpc_test_svc.c +similarity index 100% +rename from src/lib/rpc/unit-test/rpc_test_svc.c +rename to src/lib/rpc/testsuite/rpc_test_svc.c +diff --git a/src/lib/rpc/unit-test/server.c b/src/lib/rpc/testsuite/server.c +similarity index 100% +rename from src/lib/rpc/unit-test/server.c +rename to src/lib/rpc/testsuite/server.c +-- +2.35.1 + diff --git a/root/ppg/common/deps/krb5/rpm/downstream-Remove-3des-support-cumulative-1.patch b/root/ppg/common/deps/krb5/rpm/downstream-Remove-3des-support-cumulative-1.patch new file mode 100644 index 00000000..ebf6d82c --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/downstream-Remove-3des-support-cumulative-1.patch @@ -0,0 +1,239 @@ +From dea76c0b677ae02f59f6e5a796b0cf8c5d2e02f2 Mon Sep 17 00:00:00 2001 +From: Julien Rische +Date: Fri, 4 Apr 2025 15:08:36 +0200 +Subject: [PATCH] [downstream] Remove 3des support (cumulative 1) + +Remove mentions for the triple-DES encryption type which were added +since the previous downstream patch. +--- + README | 3 +++ + doc/admin/conf_files/krb5_conf.rst | 6 ------ + doc/admin/enctypes.rst | 11 ++--------- + doc/mitK5features.rst | 3 +++ + src/include/k5-int.h | 2 -- + src/kdc/kdc_util.c | 2 -- + src/lib/krb5/krb/init_ctx.c | 5 ----- + src/man/krb5.conf.man | 6 ++++++ + src/tests/gssapi/t_enctypes.py | 5 ++--- + src/tests/t_etype_info.py | 4 ++-- + src/tests/t_sesskeynego.py | 8 -------- + src/util/k5test.py | 7 ------- + 12 files changed, 18 insertions(+), 44 deletions(-) + +diff --git a/README b/README +index 0f39ac2443..b863ef84a3 100644 +--- a/README ++++ b/README +@@ -168,6 +168,9 @@ Developer experience: + + Protocol evolution: + ++* The KDC will no longer issue tickets with RC4 session keys unless ++ explicitly configured with the new allow_rc4 variable. ++ + * Add KDC support for S4U2Self requests where the user is identified + by X.509 certificate. (Requires support for certificate lookup from + a third-party KDB module.) +diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst +index c77a9fd46d..54e4780327 100644 +--- a/doc/admin/conf_files/krb5_conf.rst ++++ b/doc/admin/conf_files/krb5_conf.rst +@@ -95,12 +95,6 @@ Additionally, krb5.conf may include any of the relations described in + + The libdefaults section may contain any of the following relations: + +-**allow_des3** +- Permit the KDC to issue tickets with des3-cbc-sha1 session keys. +- In future releases, this flag will allow des3-cbc-sha1 to be used +- at all. The default value for this tag is false. (Added in +- release 1.21.) +- + **allow_rc4** + Permit the KDC to issue tickets with arcfour-hmac session keys. + In future releases, this flag will allow arcfour-hmac to be used +diff --git a/doc/admin/enctypes.rst b/doc/admin/enctypes.rst +index 76ef2a2133..90e85309fa 100644 +--- a/doc/admin/enctypes.rst ++++ b/doc/admin/enctypes.rst +@@ -49,8 +49,8 @@ The KDC chooses the session key enctype by taking the intersection of + its **permitted_enctypes** list, the list of long-term keys for the + most recent kvno of the service, and the client's requested list of + enctypes. Starting in krb5-1.21, all services are assumed to support +-aes256-cts-hmac-sha1-96; also, des3-cbc-sha1 and arcfour-hmac session +-keys will not be issued by default. ++aes256-cts-hmac-sha1-96; also, arcfour-hmac session keys will not be ++issued by default. + + Starting in krb5-1.11, it is possible to set a string attribute on a + service principal to control what session key enctypes the KDC may +@@ -90,13 +90,6 @@ affect how enctypes are chosen. + acceptable risk for your environment and the weak enctypes are + required for backward compatibility. + +-**allow_des3** +- was added in release 1.21 and defaults to *false*. Unless this +- flag is set to *true*, the KDC will not issue tickets with +- des3-cbc-sha1 session keys. In a future release, this flag will +- control whether des3-cbc-sha1 is permitted in similar fashion to +- weak enctypes. +- + **allow_rc4** + was added in release 1.21 and defaults to *false*. Unless this + flag is set to *true*, the KDC will not issue tickets with +diff --git a/doc/mitK5features.rst b/doc/mitK5features.rst +index f4594ed137..d7e516861f 100644 +--- a/doc/mitK5features.rst ++++ b/doc/mitK5features.rst +@@ -501,6 +501,9 @@ Release 1.18 + + * Protocol evolution: + ++ - The KDC will no longer issue tickets with RC4 session keys unless ++ explicitly configured with the new allow_rc4 variable. ++ + - Add KDC support for S4U2Self requests where the user is identified + by X.509 certificate. (Requires support for certificate lookup + from a third-party KDB module.) +diff --git a/src/include/k5-int.h b/src/include/k5-int.h +index c3d081fd30..3c74934f25 100644 +--- a/src/include/k5-int.h ++++ b/src/include/k5-int.h +@@ -181,7 +181,6 @@ typedef unsigned char u_char; + * matches the variable name. Keep these alphabetized. */ + #define KRB5_CONF_ACL_FILE "acl_file" + #define KRB5_CONF_ADMIN_SERVER "admin_server" +-#define KRB5_CONF_ALLOW_DES3 "allow_des3" + #define KRB5_CONF_ALLOW_RC4 "allow_rc4" + #define KRB5_CONF_ALLOW_WEAK_CRYPTO "allow_weak_crypto" + #define KRB5_CONF_AUTH_TO_LOCAL "auth_to_local" +@@ -1261,7 +1260,6 @@ struct _krb5_context { + struct _kdb_log_context *kdblog_context; + + krb5_boolean allow_weak_crypto; +- krb5_boolean allow_des3; + krb5_boolean allow_rc4; + krb5_boolean ignore_acceptor_hostname; + krb5_boolean enforce_ok_as_delegate; +diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c +index b081d8e439..5a2589b0c0 100644 +--- a/src/kdc/kdc_util.c ++++ b/src/kdc/kdc_util.c +@@ -1046,8 +1046,6 @@ select_session_keytype(kdc_realm_t *kdc_active_realm, krb5_db_entry *server, + * unless they are explicitly allowed. In the future they will be more + * comprehensively disabled and eventually removed. + */ +- if (ktype[i] == ENCTYPE_DES3_CBC_SHA1 && !kdc_context->allow_des3) +- continue; + if (ktype[i] == ENCTYPE_ARCFOUR_HMAC && !kdc_context->allow_rc4) + continue; + +diff --git a/src/lib/krb5/krb/init_ctx.c b/src/lib/krb5/krb/init_ctx.c +index 4b23738817..980cc0893b 100644 +--- a/src/lib/krb5/krb/init_ctx.c ++++ b/src/lib/krb5/krb/init_ctx.c +@@ -226,11 +226,6 @@ krb5_init_context_profile(profile_t profile, krb5_flags flags, + goto cleanup; + ctx->allow_weak_crypto = tmp; + +- retval = get_boolean(ctx, KRB5_CONF_ALLOW_DES3, 0, &tmp); +- if (retval) +- goto cleanup; +- ctx->allow_des3 = tmp; +- + retval = get_boolean(ctx, KRB5_CONF_ALLOW_RC4, 0, &tmp); + if (retval) + goto cleanup; +diff --git a/src/man/krb5.conf.man b/src/man/krb5.conf.man +index 067a9cbfe8..1a1c13b1a1 100644 +--- a/src/man/krb5.conf.man ++++ b/src/man/krb5.conf.man +@@ -178,6 +178,12 @@ kdc.conf(5), but it is not a recommended practice. + The libdefaults section may contain any of the following relations: + .INDENT 0.0 + .TP ++\fBallow_rc4\fP ++Permit the KDC to issue tickets with arcfour\-hmac session keys. ++In future releases, this flag will allow arcfour\-hmac to be used ++at all. The default value for this tag is false. (Added in ++release 1.21.) ++.TP + \fBallow_weak_crypto\fP + If this flag is set to false, then weak encryption types (as noted + in Encryption_types in kdc.conf(5)) will be filtered +diff --git a/src/tests/gssapi/t_enctypes.py b/src/tests/gssapi/t_enctypes.py +index e6bde47afc..1bb8c40b6b 100755 +--- a/src/tests/gssapi/t_enctypes.py ++++ b/src/tests/gssapi/t_enctypes.py +@@ -10,9 +10,8 @@ d_rc4 = 'DEPRECATED:arcfour-hmac' + + # These tests make assumptions about the default enctype lists, so set + # them explicitly rather than relying on the library defaults. +-supp='aes256-cts:normal aes128-cts:normal des3-cbc-sha1:normal rc4-hmac:normal' +-conf = {'libdefaults': {'permitted_enctypes': 'aes des3 rc4', +- 'allow_des3': 'true', 'allow_rc4': 'true'}, ++supp='aes256-cts:normal aes128-cts:normal rc4-hmac:normal' ++conf = {'libdefaults': {'permitted_enctypes': 'aes rc4', 'allow_rc4': 'true'}, + 'realms': {'$realm': {'supported_enctypes': supp}}} + realm = K5Realm(krb5_conf=conf) + shutil.copyfile(realm.ccache, os.path.join(realm.testdir, 'save')) +diff --git a/src/tests/t_etype_info.py b/src/tests/t_etype_info.py +index 9ea5ca6228..cfdd6ab83c 100644 +--- a/src/tests/t_etype_info.py ++++ b/src/tests/t_etype_info.py +@@ -1,7 +1,7 @@ + from k5test import * + +-supported_enctypes = 'aes128-cts des3-cbc-sha1 rc4-hmac' +-conf = {'libdefaults': {'allow_des3': 'true', 'allow_rc4': 'true'}, ++supported_enctypes = 'aes128-cts rc4-hmac' ++conf = {'libdefaults': {'allow_rc4': 'true'}, + 'realms': {'$realm': {'supported_enctypes': supported_enctypes}}} + realm = K5Realm(create_host=False, get_creds=False, krb5_conf=conf) + +diff --git a/src/tests/t_sesskeynego.py b/src/tests/t_sesskeynego.py +index f30d0bc16c..43bdcd5d7e 100755 +--- a/src/tests/t_sesskeynego.py ++++ b/src/tests/t_sesskeynego.py +@@ -26,7 +26,6 @@ conf3 = {'libdefaults': { + 'default_tgs_enctypes': 'rc4-hmac,aes128-cts'}} + conf4 = {'libdefaults': {'permitted_enctypes': 'aes256-cts'}} + conf5 = {'libdefaults': {'allow_rc4': 'true'}} +-conf6 = {'libdefaults': {'allow_des3': 'true'}} + # Test with client request and session_enctypes preferring aes128, but + # aes256 long-term key. + realm = K5Realm(krb5_conf=conf1, create_host=False, get_creds=False) +@@ -78,13 +77,6 @@ realm.run([kadminl, 'setstr', 'server', 'session_enctypes', 'rc4-hmac']) + test_kvno(realm, 'DEPRECATED:arcfour-hmac', 'aes256-cts-hmac-sha1-96') + realm.stop() + +-# 6: allow_des3 permits negotiation of des3-cbc-sha1 session key. +-realm = K5Realm(krb5_conf=conf6, create_host=False, get_creds=False) +-realm.run([kadminl, 'addprinc', '-randkey', '-e', 'aes256-cts', 'server']) +-realm.run([kadminl, 'setstr', 'server', 'session_enctypes', 'des3-cbc-sha1']) +-test_kvno(realm, 'DEPRECATED:des3-cbc-sha1', 'aes256-cts-hmac-sha1-96') +-realm.stop() +- + # 7: default config negotiates aes256-sha1 session key for RC4-only service. + realm = K5Realm(create_host=False, get_creds=False) + realm.run([kadminl, 'addprinc', '-randkey', '-e', 'rc4-hmac', 'server']) +diff --git a/src/util/k5test.py b/src/util/k5test.py +index 96474cc5aa..c3ab63f8e8 100644 +--- a/src/util/k5test.py ++++ b/src/util/k5test.py +@@ -1299,13 +1299,6 @@ _passes = [ + # No special settings; exercises AES256. + ('default', None, None, None), + +- # Exercise the DES3 enctype. +- ('des3', None, +- {'libdefaults': {'permitted_enctypes': 'des3 aes256-sha1'}}, +- {'realms': {'$realm': { +- 'supported_enctypes': 'des3-cbc-sha1:normal', +- 'master_key_type': 'des3-cbc-sha1'}}}), +- + # Exercise the arcfour enctype. + ('arcfour', None, + {'libdefaults': {'permitted_enctypes': 'rc4 aes256-sha1'}}, +-- +2.49.0 + diff --git a/root/ppg/common/deps/krb5/rpm/downstream-Remove-3des-support.patch b/root/ppg/common/deps/krb5/rpm/downstream-Remove-3des-support.patch new file mode 100644 index 00000000..22251b93 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/downstream-Remove-3des-support.patch @@ -0,0 +1,6465 @@ +From 3c1f235c1c82b1cebfd2eba800cd2cd2610f0535 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Tue, 26 Mar 2019 18:51:10 -0400 +Subject: [PATCH] [downstream] Remove 3des support + +Completely remove support for all DES3 enctypes (des3-cbc-raw, +des3-hmac-sha1, des3-cbc-sha1-kd). Update all tests and documentation +to user other enctypes. Mark the 3DES enctypes UNSUPPORTED and retain +their constants. + +Last-updated: 1.18-beta2 +(cherry picked from commit e9cd83237b54e2f6010a063f523217b0a442ecbf) +--- + doc/admin/advanced/retiring-des.rst | 11 + + doc/admin/conf_files/kdc_conf.rst | 7 +- + doc/admin/enctypes.rst | 13 +- + doc/admin/troubleshoot.rst | 9 +- + doc/appdev/refs/macros/index.rst | 1 - + doc/conf.py | 2 +- + doc/mitK5features.rst | 2 +- + src/Makefile.in | 4 +- + src/configure.ac | 1 - + src/include/krb5/krb5.hin | 10 +- + src/kadmin/testing/proto/kdc.conf.proto | 4 +- + src/kdc/kdc_util.c | 4 - + src/lib/crypto/Makefile.in | 8 +- + src/lib/crypto/builtin/Makefile.in | 6 +- + src/lib/crypto/builtin/des/ISSUES | 13 - + src/lib/crypto/builtin/des/Makefile.in | 80 ---- + src/lib/crypto/builtin/des/d3_aead.c | 133 ------ + src/lib/crypto/builtin/des/d3_kysched.c | 51 --- + src/lib/crypto/builtin/des/deps | 148 ------- + src/lib/crypto/builtin/des/des_int.h | 285 ------------- + src/lib/crypto/builtin/des/des_keys.c | 40 -- + src/lib/crypto/builtin/des/destest.c | 240 ----------- + src/lib/crypto/builtin/des/doc/libdes.doc | 208 --------- + src/lib/crypto/builtin/des/f_aead.c | 173 -------- + src/lib/crypto/builtin/des/f_cbc.c | 256 ------------ + src/lib/crypto/builtin/des/f_cksum.c | 136 ------ + src/lib/crypto/builtin/des/f_parity.c | 56 --- + src/lib/crypto/builtin/des/f_sched.c | 359 ---------------- + src/lib/crypto/builtin/des/f_tables.c | 370 ---------------- + src/lib/crypto/builtin/des/f_tables.h | 285 ------------- + src/lib/crypto/builtin/des/key_sched.c | 62 --- + src/lib/crypto/builtin/des/keytest.data | 171 -------- + src/lib/crypto/builtin/des/t_verify.c | 395 ------------------ + src/lib/crypto/builtin/des/weak_key.c | 86 ---- + .../crypto/builtin/enc_provider/Makefile.in | 6 +- + src/lib/crypto/builtin/enc_provider/deps | 12 - + src/lib/crypto/builtin/enc_provider/des3.c | 105 ----- + src/lib/crypto/crypto_tests/t_cf2.expected | 1 - + src/lib/crypto/crypto_tests/t_cf2.in | 5 - + src/lib/crypto/crypto_tests/t_cksums.c | 10 - + src/lib/crypto/crypto_tests/t_decrypt.c | 57 --- + src/lib/crypto/crypto_tests/t_derive.c | 36 -- + src/lib/crypto/crypto_tests/t_encrypt.c | 1 - + src/lib/crypto/crypto_tests/t_short.c | 1 - + src/lib/crypto/crypto_tests/t_str2key.c | 52 --- + src/lib/crypto/krb/Makefile.in | 3 - + src/lib/crypto/krb/cksumtypes.c | 6 - + src/lib/crypto/krb/crypto_int.h | 16 - + src/lib/crypto/krb/default_state.c | 10 - + src/lib/crypto/krb/enctype_util.c | 3 + + src/lib/crypto/krb/etypes.c | 21 - + src/lib/crypto/krb/prf_des.c | 47 --- + src/lib/crypto/krb/random_to_key.c | 45 -- + src/lib/crypto/libk5crypto.exports | 1 - + src/lib/crypto/openssl/Makefile.in | 8 +- + src/lib/crypto/openssl/des/Makefile.in | 20 - + src/lib/crypto/openssl/des/deps | 15 - + src/lib/crypto/openssl/des/des_keys.c | 40 -- + .../crypto/openssl/enc_provider/Makefile.in | 3 - + src/lib/crypto/openssl/enc_provider/deps | 11 - + src/lib/crypto/openssl/enc_provider/des3.c | 184 -------- + src/lib/gssapi/krb5/accept_sec_context.c | 1 - + src/lib/gssapi/krb5/gssapiP_krb5.h | 6 +- + src/lib/gssapi/krb5/k5seal.c | 35 +- + src/lib/gssapi/krb5/k5sealiov.c | 27 +- + src/lib/gssapi/krb5/k5unseal.c | 102 ++--- + src/lib/gssapi/krb5/k5unsealiov.c | 38 +- + src/lib/gssapi/krb5/util_crypt.c | 11 - + .../api.current/chpass-principal-v2.exp | 4 +- + .../api.current/get-principal-v2.exp | 4 +- + .../api.current/randkey-principal-v2.exp | 4 +- + src/lib/krb5/krb/init_ctx.c | 3 - + src/lib/krb5/krb/s4u_creds.c | 2 - + src/lib/krb5/krb/t_copy_context.c | 2 +- + src/lib/krb5/krb/t_etypes.c | 48 +-- + src/lib/krb5/os/t_trace.c | 4 +- + src/lib/krb5/os/t_trace.ref | 2 +- + src/plugins/preauth/pkinit/pkcs11.h | 6 +- + src/plugins/preauth/pkinit/pkinit_clnt.c | 8 - + src/plugins/preauth/pkinit/pkinit_crypto.h | 12 - + .../preauth/pkinit/pkinit_crypto_openssl.c | 38 -- + src/plugins/preauth/pkinit/pkinit_kdf_test.c | 31 -- + src/plugins/preauth/spake/t_vectors.c | 25 -- + src/tests/dejagnu/config/default.exp | 78 ---- + src/tests/dejagnu/krb-standalone/kprop.exp | 2 +- + src/tests/gssapi/t_enctypes.py | 33 +- + src/tests/gssapi/t_invalid.c | 12 - + src/tests/gssapi/t_pcontok.c | 16 +- + src/tests/gssapi/t_prf.c | 7 - + src/tests/t_authdata.py | 2 +- + src/tests/t_etype_info.py | 18 +- + src/tests/t_keyrollover.py | 8 +- + src/tests/t_mkey.py | 35 -- + src/tests/t_salt.py | 5 +- + src/util/k5test.py | 7 - + .../leash/htmlhelp/html/Encryption_Types.htm | 13 - + 96 files changed, 163 insertions(+), 4834 deletions(-) + delete mode 100644 src/lib/crypto/builtin/des/ISSUES + delete mode 100644 src/lib/crypto/builtin/des/Makefile.in + delete mode 100644 src/lib/crypto/builtin/des/d3_aead.c + delete mode 100644 src/lib/crypto/builtin/des/d3_kysched.c + delete mode 100644 src/lib/crypto/builtin/des/deps + delete mode 100644 src/lib/crypto/builtin/des/des_int.h + delete mode 100644 src/lib/crypto/builtin/des/des_keys.c + delete mode 100644 src/lib/crypto/builtin/des/destest.c + delete mode 100644 src/lib/crypto/builtin/des/doc/libdes.doc + delete mode 100644 src/lib/crypto/builtin/des/f_aead.c + delete mode 100644 src/lib/crypto/builtin/des/f_cbc.c + delete mode 100644 src/lib/crypto/builtin/des/f_cksum.c + delete mode 100644 src/lib/crypto/builtin/des/f_parity.c + delete mode 100644 src/lib/crypto/builtin/des/f_sched.c + delete mode 100644 src/lib/crypto/builtin/des/f_tables.c + delete mode 100644 src/lib/crypto/builtin/des/f_tables.h + delete mode 100644 src/lib/crypto/builtin/des/key_sched.c + delete mode 100644 src/lib/crypto/builtin/des/keytest.data + delete mode 100644 src/lib/crypto/builtin/des/t_verify.c + delete mode 100644 src/lib/crypto/builtin/des/weak_key.c + delete mode 100644 src/lib/crypto/builtin/enc_provider/des3.c + delete mode 100644 src/lib/crypto/krb/prf_des.c + delete mode 100644 src/lib/crypto/openssl/des/Makefile.in + delete mode 100644 src/lib/crypto/openssl/des/deps + delete mode 100644 src/lib/crypto/openssl/des/des_keys.c + delete mode 100644 src/lib/crypto/openssl/enc_provider/des3.c + +diff --git a/doc/admin/advanced/retiring-des.rst b/doc/admin/advanced/retiring-des.rst +index 4a964c15c..cb6258d77 100644 +--- a/doc/admin/advanced/retiring-des.rst ++++ b/doc/admin/advanced/retiring-des.rst +@@ -10,6 +10,13 @@ ability have rendered DES vulnerable to brute force attacks on its 56-bit + keyspace. As such, it is now considered insecure and should not be + used (:rfc:`6649`). + ++In 1999, MIT krb5 added support for Triple-DES (3DES) encryption types. ++However, due to weakenings of DES and other security concerns, it is now also ++considered insecure and should not be used (:rfc:`8429`). AES encryption ++types were added to MIT in 2003, meaning that the number of deployments with ++3DES as the strongest encryption type is hopefully small. The rotation ++procedure described herein works for both DES and 3DES. ++ + History + ------- + +@@ -27,6 +34,10 @@ and removed DES (single-DES) support in release 1.18. As a + consequence, a release prior to 1.18 is required to perform these + migrations. + ++3DES (a flagged deprecated encryption type) was also removed downstream by ++rharwood@redhat.com starting in 1.18; likewise, a pre-1.18 release is required ++to perform these migrations. ++ + Types of keys + ------------- + +diff --git a/doc/admin/conf_files/kdc_conf.rst b/doc/admin/conf_files/kdc_conf.rst +index 9759756a2..cf8a12547 100644 +--- a/doc/admin/conf_files/kdc_conf.rst ++++ b/doc/admin/conf_files/kdc_conf.rst +@@ -843,8 +843,6 @@ Encryption types marked as "weak" are available for compatibility but + not recommended for use. + + ==================================================== ========================================================= +-des3-cbc-raw Triple DES cbc mode raw (weak) +-des3-cbc-sha1 des3-hmac-sha1 des3-cbc-sha1-kd Triple DES cbc mode with HMAC/sha1 + aes256-cts-hmac-sha1-96 aes256-cts aes256-sha1 AES-256 CTS mode with 96-bit SHA-1 HMAC + aes128-cts-hmac-sha1-96 aes128-cts aes128-sha1 AES-128 CTS mode with 96-bit SHA-1 HMAC + aes256-cts-hmac-sha384-192 aes256-sha2 AES-256 CTS mode with 192-bit SHA-384 HMAC +@@ -853,7 +851,6 @@ arcfour-hmac rc4-hmac arcfour-hmac-md5 RC4 with HMAC/MD5 + arcfour-hmac-exp rc4-hmac-exp arcfour-hmac-md5-exp Exportable RC4 with HMAC/MD5 (weak) + camellia256-cts-cmac camellia256-cts Camellia-256 CTS mode with CMAC + camellia128-cts-cmac camellia128-cts Camellia-128 CTS mode with CMAC +-des3 The triple DES family: des3-cbc-sha1 + aes The AES family: aes256-cts-hmac-sha1-96, aes128-cts-hmac-sha1-96, aes256-cts-hmac-sha384-192, and aes128-cts-hmac-sha256-128 + rc4 The RC4 family: arcfour-hmac + camellia The Camellia family: camellia256-cts-cmac and camellia128-cts-cmac +@@ -865,8 +862,8 @@ from the current list by prefixing them with a minus sign ("-"). + Types or families can be prefixed with a plus sign ("+") for symmetry; + it has the same meaning as just listing the type or family. For + example, "``DEFAULT -rc4``" would be the default set of encryption +-types with RC4 types removed, and "``des3 DEFAULT``" would be the +-default set of encryption types with triple DES types moved to the ++types with RC4 types removed, and "``aes128-sha2 DEFAULT``" would be ++the default set of encryption types with aes128-sha2 moved to the + front. + + While **aes128-cts** and **aes256-cts** are supported for all Kerberos +diff --git a/doc/admin/enctypes.rst b/doc/admin/enctypes.rst +index caf6d9267..65b55cdb9 100644 +--- a/doc/admin/enctypes.rst ++++ b/doc/admin/enctypes.rst +@@ -129,7 +129,7 @@ enctype weak? krb5 Windows + des-cbc-crc weak <1.18 >=2000 + des-cbc-md4 weak <1.18 ? + des-cbc-md5 weak <1.18 >=2000 +-des3-cbc-sha1 >=1.1 none ++des3-cbc-sha1 <1.18 none + arcfour-hmac >=1.3 >=2000 + arcfour-hmac-exp weak >=1.3 >=2000 + aes128-cts-hmac-sha1-96 >=1.3 >=Vista +@@ -140,7 +140,10 @@ camellia128-cts-cmac >=1.9 none + camellia256-cts-cmac >=1.9 none + ========================== ===== ======== ======= + +-krb5 releases 1.18 and later do not support single-DES. krb5 releases +-1.8 and later disable the single-DES enctypes by default. Microsoft +-Windows releases Windows 7 and later disable single-DES enctypes by +-default. ++krb5 releases 1.8 and later disable the single-DES enctypes by ++default. Microsoft Windows releases Windows 7 and later disable ++single-DES enctypes by default. ++ ++krb5 releases 1.18 and later remove single-DES and 3DES ++(downstream-only patch) enctype support. Microsoft Windows never ++supported 3DES. +diff --git a/doc/admin/troubleshoot.rst b/doc/admin/troubleshoot.rst +index 6a0c7f89b..263fc9c97 100644 +--- a/doc/admin/troubleshoot.rst ++++ b/doc/admin/troubleshoot.rst +@@ -73,11 +73,10 @@ credential verification failed: KDC has no support for encryption type + ...................................................................... + + This most commonly happens when trying to use a principal with only +-DES keys, in a release (MIT krb5 1.7 or later) which disables DES by +-default. DES encryption is considered weak due to its inadequate key +-size. If you cannot migrate away from its use, you can re-enable DES +-by adding ``allow_weak_crypto = true`` to the :ref:`libdefaults` +-section of :ref:`krb5.conf(5)`. ++DES/3DES keys, in a release (MIT krb5 1.7 or later) which disables DES ++by default. DES encryption is considered weak due to its inadequate ++key size and has been removed upstream; 3DES is not recommended, and ++has been removed downstream by rharwood@redhat.com. + + + .. _err_cert_chain_cert_expired: +diff --git a/doc/appdev/refs/macros/index.rst b/doc/appdev/refs/macros/index.rst +index 68debe714..788d094bf 100644 +--- a/doc/appdev/refs/macros/index.rst ++++ b/doc/appdev/refs/macros/index.rst +@@ -36,7 +36,6 @@ Public + CKSUMTYPE_HMAC_SHA1_96_AES256.rst + CKSUMTYPE_HMAC_SHA256_128_AES128.rst + CKSUMTYPE_HMAC_SHA384_192_AES256.rst +- CKSUMTYPE_HMAC_SHA1_DES3.rst + CKSUMTYPE_MD5_HMAC_ARCFOUR.rst + CKSUMTYPE_NIST_SHA.rst + CKSUMTYPE_RSA_MD4.rst +diff --git a/doc/conf.py b/doc/conf.py +index c32b2882a..5eeafc30f 100644 +--- a/doc/conf.py ++++ b/doc/conf.py +@@ -272,7 +272,7 @@ else: + rst_epilog += ''' + .. |krb5conf| replace:: ``/etc/krb5.conf`` + .. |defkeysalts| replace:: ``aes256-cts-hmac-sha1-96:normal aes128-cts-hmac-sha1-96:normal`` +-.. |defetypes| replace:: ``aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 aes256-cts-hmac-sha384-192 aes128-cts-hmac-sha256-128 des3-cbc-sha1 arcfour-hmac-md5 camellia256-cts-cmac camellia128-cts-cmac`` ++.. |defetypes| replace:: ``aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 aes256-cts-hmac-sha384-192 aes128-cts-hmac-sha256-128 arcfour-hmac-md5 camellia256-cts-cmac camellia128-cts-cmac`` + .. |defmkey| replace:: ``aes256-cts-hmac-sha1-96`` + .. |copy| unicode:: U+000A9 + ''' +diff --git a/doc/mitK5features.rst b/doc/mitK5features.rst +index 5d286b6ee..f4594ed13 100644 +--- a/doc/mitK5features.rst ++++ b/doc/mitK5features.rst +@@ -37,7 +37,7 @@ Database backends: LDAP, DB2, LMDB + + krb4 support: Kerberos 5 release < 1.8 + +-DES support: Kerberos 5 release < 1.18 (See :ref:`retiring-des`) ++DES/3DES support: Kerberos 5 release < 1.18 (See :ref:`retiring-des`) + + Interoperability + ---------------- +diff --git a/src/Makefile.in b/src/Makefile.in +index 56c7a4e6f..70db82a30 100644 +--- a/src/Makefile.in ++++ b/src/Makefile.in +@@ -130,7 +130,7 @@ WINMAKEFILES=Makefile \ + lib\Makefile lib\crypto\Makefile lib\crypto\krb\Makefile \ + lib\crypto\builtin\Makefile lib\crypto\builtin\aes\Makefile \ + lib\crypto\builtin\enc_provider\Makefile \ +- lib\crypto\builtin\des\Makefile lib\crypto\builtin\md5\Makefile \ ++ lib\crypto\builtin\md5\Makefile \ + lib\crypto\builtin\camellia\Makefile lib\crypto\builtin\md4\Makefile \ + lib\crypto\builtin\hash_provider\Makefile \ + lib\crypto\builtin\sha2\Makefile lib\crypto\builtin\sha1\Makefile \ +@@ -202,8 +202,6 @@ WINMAKEFILES=Makefile \ + ##DOS## $(WCONFIG) config < $@.in > $@ + ##DOS##lib\crypto\builtin\enc_provider\Makefile: lib\crypto\builtin\enc_provider\Makefile.in $(MKFDEP) + ##DOS## $(WCONFIG) config < $@.in > $@ +-##DOS##lib\crypto\builtin\des\Makefile: lib\crypto\builtin\des\Makefile.in $(MKFDEP) +-##DOS## $(WCONFIG) config < $@.in > $@ + ##DOS##lib\crypto\builtin\md5\Makefile: lib\crypto\builtin\md5\Makefile.in $(MKFDEP) + ##DOS## $(WCONFIG) config < $@.in > $@ + ##DOS##lib\crypto\builtin\camellia\Makefile: lib\crypto\builtin\camellia\Makefile.in $(MKFDEP) +diff --git a/src/configure.ac b/src/configure.ac +index 440a22bd9..d4e4da525 100644 +--- a/src/configure.ac ++++ b/src/configure.ac +@@ -1481,7 +1481,6 @@ V5_AC_OUTPUT_MAKEFILE(. + lib/crypto lib/crypto/krb lib/crypto/$CRYPTO_IMPL + lib/crypto/$CRYPTO_IMPL/enc_provider + lib/crypto/$CRYPTO_IMPL/hash_provider +- lib/crypto/$CRYPTO_IMPL/des + lib/crypto/$CRYPTO_IMPL/md4 lib/crypto/$CRYPTO_IMPL/md5 + lib/crypto/$CRYPTO_IMPL/sha1 lib/crypto/$CRYPTO_IMPL/sha2 + lib/crypto/$CRYPTO_IMPL/aes lib/crypto/$CRYPTO_IMPL/camellia +diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin +index e9435c693..6355e6540 100644 +--- a/src/include/krb5/krb5.hin ++++ b/src/include/krb5/krb5.hin +@@ -426,8 +426,8 @@ typedef struct _krb5_crypto_iov { + #define ENCTYPE_DES_CBC_MD4 0x0002 /**< @deprecated no longer supported */ + #define ENCTYPE_DES_CBC_MD5 0x0003 /**< @deprecated no longer supported */ + #define ENCTYPE_DES_CBC_RAW 0x0004 /**< @deprecated no longer supported */ +-#define ENCTYPE_DES3_CBC_SHA 0x0005 /**< @deprecated DES-3 cbc with SHA1 */ +-#define ENCTYPE_DES3_CBC_RAW 0x0006 /**< @deprecated DES-3 cbc mode raw */ ++#define ENCTYPE_DES3_CBC_SHA 0x0005 /**< @deprecated no longer supported */ ++#define ENCTYPE_DES3_CBC_RAW 0x0006 /**< @deprecated no longer supported */ + #define ENCTYPE_DES_HMAC_SHA1 0x0008 /**< @deprecated no longer supported */ + /* PKINIT */ + #define ENCTYPE_DSA_SHA1_CMS 0x0009 /**< DSA with SHA1, CMS signature */ +@@ -436,9 +436,9 @@ typedef struct _krb5_crypto_iov { + #define ENCTYPE_RC2_CBC_ENV 0x000c /**< RC2 cbc mode, CMS enveloped data */ + #define ENCTYPE_RSA_ENV 0x000d /**< RSA encryption, CMS enveloped data */ + #define ENCTYPE_RSA_ES_OAEP_ENV 0x000e /**< RSA w/OEAP encryption, CMS enveloped data */ +-#define ENCTYPE_DES3_CBC_ENV 0x000f /**< DES-3 cbc mode, CMS enveloped data */ ++#define ENCTYPE_DES3_CBC_ENV 0x000f /**< @deprecated no longer supported */ + +-#define ENCTYPE_DES3_CBC_SHA1 0x0010 ++#define ENCTYPE_DES3_CBC_SHA1 0x0010 /**< @deprecated removed */ + #define ENCTYPE_AES128_CTS_HMAC_SHA1_96 0x0011 /**< RFC 3962 */ + #define ENCTYPE_AES256_CTS_HMAC_SHA1_96 0x0012 /**< RFC 3962 */ + #define ENCTYPE_AES128_CTS_HMAC_SHA256_128 0x0013 /**< RFC 8009 */ +@@ -458,7 +458,7 @@ typedef struct _krb5_crypto_iov { + #define CKSUMTYPE_RSA_MD5 0x0007 + #define CKSUMTYPE_RSA_MD5_DES 0x0008 + #define CKSUMTYPE_NIST_SHA 0x0009 +-#define CKSUMTYPE_HMAC_SHA1_DES3 0x000c ++#define CKSUMTYPE_HMAC_SHA1_DES3 0x000c /* @deprecated removed */ + #define CKSUMTYPE_HMAC_SHA1_96_AES128 0x000f /**< RFC 3962. Used with + ENCTYPE_AES128_CTS_HMAC_SHA1_96 */ + #define CKSUMTYPE_HMAC_SHA1_96_AES256 0x0010 /**< RFC 3962. Used with +diff --git a/src/kadmin/testing/proto/kdc.conf.proto b/src/kadmin/testing/proto/kdc.conf.proto +index 8a4b87de1..d7f1d076b 100644 +--- a/src/kadmin/testing/proto/kdc.conf.proto ++++ b/src/kadmin/testing/proto/kdc.conf.proto +@@ -11,6 +11,6 @@ + dict_file = __K5ROOT__/ovsec_adm.dict + kadmind_port = 1751 + kpasswd_port = 1752 +- master_key_type = des3-hmac-sha1 +- supported_enctypes = des3-hmac-sha1:normal aes256-cts:normal aes128-cts:normal aes256-sha2:normal aes128-sha2:normal ++ master_key_type = aes256-cts ++ supported_enctypes = aes256-cts:normal aes128-cts:normal aes256-sha2:normal aes128-sha2:normal + } +diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c +index ba0ce0b71..e3352f9cc 100644 +--- a/src/kdc/kdc_util.c ++++ b/src/kdc/kdc_util.c +@@ -1103,8 +1103,6 @@ enctype_name(krb5_enctype ktype, char *buf, size_t buflen) + name = "rsaEncryption-EnvOID"; + else if (ktype == ENCTYPE_RSA_ES_OAEP_ENV) + name = "id-RSAES-OAEP-EnvOID"; +- else if (ktype == ENCTYPE_DES3_CBC_ENV) +- name = "des-ede3-cbc-EnvOID"; + else + return krb5_enctype_to_name(ktype, FALSE, buf, buflen); + +@@ -1826,8 +1824,6 @@ krb5_boolean + enctype_requires_etype_info_2(krb5_enctype enctype) + { + switch(enctype) { +- case ENCTYPE_DES3_CBC_SHA1: +- case ENCTYPE_DES3_CBC_RAW: + case ENCTYPE_ARCFOUR_HMAC: + case ENCTYPE_ARCFOUR_HMAC_EXP : + return 0; +diff --git a/src/lib/crypto/Makefile.in b/src/lib/crypto/Makefile.in +index c3fcfd7e8..890d54adf 100644 +--- a/src/lib/crypto/Makefile.in ++++ b/src/lib/crypto/Makefile.in +@@ -13,7 +13,7 @@ STOBJLISTS=$(CRYPTO_IMPL)/enc_provider/OBJS.ST \ + $(CRYPTO_IMPL)/hash_provider/OBJS.ST \ + $(CRYPTO_IMPL)/md4/OBJS.ST $(CRYPTO_IMPL)/md5/OBJS.ST \ + $(CRYPTO_IMPL)/sha1/OBJS.ST $(CRYPTO_IMPL)/sha2/OBJS.ST \ +- $(CRYPTO_IMPL)/aes/OBJS.ST $(CRYPTO_IMPL)/des/OBJS.ST \ ++ $(CRYPTO_IMPL)/aes/OBJS.ST \ + $(CRYPTO_IMPL)/camellia/OBJS.ST krb/OBJS.ST \ + $(CRYPTO_IMPL)/OBJS.ST + +@@ -21,7 +21,7 @@ SUBDIROBJLISTS=$(CRYPTO_IMPL)/enc_provider/OBJS.ST \ + $(CRYPTO_IMPL)/hash_provider/OBJS.ST \ + $(CRYPTO_IMPL)/md4/OBJS.ST $(CRYPTO_IMPL)/md5/OBJS.ST \ + $(CRYPTO_IMPL)/sha1/OBJS.ST $(CRYPTO_IMPL)/sha2/OBJS.ST \ +- $(CRYPTO_IMPL)/aes/OBJS.ST $(CRYPTO_IMPL)/des/OBJS.ST \ ++ $(CRYPTO_IMPL)/aes/OBJS.ST \ + $(CRYPTO_IMPL)/camellia/OBJS.ST krb/OBJS.ST \ + $(CRYPTO_IMPL)/OBJS.ST + +@@ -34,8 +34,8 @@ SHLIB_EXPDEPLIBS= $(SUPPORT_DEPLIB) + SHLIB_LDFLAGS= $(LDFLAGS) @SHLIB_RPATH_DIRS@ + + ##DOS##LIBNAME=$(OUTPRE)crypto.lib +-##DOS##OBJFILEDEP=$(OUTPRE)krb.lst $(OUTPRE)aes.lst $(OUTPRE)enc_provider.lst $(OUTPRE)des.lst $(OUTPRE)md5.lst $(OUTPRE)camellia.lst $(OUTPRE)md4.lst $(OUTPRE)hash_provider.lst $(OUTPRE)sha2.lst $(OUTPRE)sha1.lst $(OUTPRE)builtin.lst +-##DOS##OBJFILELIST=@$(OUTPRE)krb.lst @$(OUTPRE)aes.lst @$(OUTPRE)enc_provider.lst @$(OUTPRE)des.lst @$(OUTPRE)md5.lst @$(OUTPRE)camellia.lst @$(OUTPRE)md4.lst @$(OUTPRE)hash_provider.lst @$(OUTPRE)sha2.lst @$(OUTPRE)sha1.lst @$(OUTPRE)builtin.lst ++##DOS##OBJFILEDEP=$(OUTPRE)krb.lst $(OUTPRE)aes.lst $(OUTPRE)enc_provider.lst $(OUTPRE)md5.lst $(OUTPRE)camellia.lst $(OUTPRE)md4.lst $(OUTPRE)hash_provider.lst $(OUTPRE)sha2.lst $(OUTPRE)sha1.lst $(OUTPRE)builtin.lst ++##DOS##OBJFILELIST=@$(OUTPRE)krb.lst @$(OUTPRE)aes.lst @$(OUTPRE)enc_provider.lst @$(OUTPRE)md5.lst @$(OUTPRE)camellia.lst @$(OUTPRE)md4.lst @$(OUTPRE)hash_provider.lst @$(OUTPRE)sha2.lst @$(OUTPRE)sha1.lst @$(OUTPRE)builtin.lst + + all-unix: all-liblinks + install-unix: install-libs +diff --git a/src/lib/crypto/builtin/Makefile.in b/src/lib/crypto/builtin/Makefile.in +index baf5d974f..82adf1dec 100644 +--- a/src/lib/crypto/builtin/Makefile.in ++++ b/src/lib/crypto/builtin/Makefile.in +@@ -1,6 +1,6 @@ + mydir=lib$(S)crypto$(S)builtin + BUILDTOP=$(REL)..$(S)..$(S).. +-SUBDIRS=camellia des aes md4 md5 sha1 sha2 enc_provider hash_provider ++SUBDIRS=camellia aes md4 md5 sha1 sha2 enc_provider hash_provider + LOCALINCLUDES = -I$(srcdir)/../krb -I$(srcdir) + + ##DOS##BUILDTOP = ..\..\.. +@@ -22,7 +22,7 @@ SRCS=\ + $(srcdir)/init.c \ + $(srcdir)/pbkdf2.c + +-STOBJLISTS= des/OBJS.ST md4/OBJS.ST \ ++STOBJLISTS= md4/OBJS.ST \ + md5/OBJS.ST sha1/OBJS.ST sha2/OBJS.ST \ + enc_provider/OBJS.ST \ + hash_provider/OBJS.ST \ +@@ -30,7 +30,7 @@ STOBJLISTS= des/OBJS.ST md4/OBJS.ST \ + camellia/OBJS.ST \ + OBJS.ST + +-SUBDIROBJLISTS= des/OBJS.ST md4/OBJS.ST \ ++SUBDIROBJLISTS= md4/OBJS.ST \ + md5/OBJS.ST sha1/OBJS.ST sha2/OBJS.ST \ + enc_provider/OBJS.ST \ + hash_provider/OBJS.ST \ +diff --git a/src/lib/crypto/builtin/des/ISSUES b/src/lib/crypto/builtin/des/ISSUES +deleted file mode 100644 +index 157891103..000000000 +--- a/src/lib/crypto/builtin/des/ISSUES ++++ /dev/null +@@ -1,13 +0,0 @@ +-Issues to be addressed for src/lib/crypto/des: -*- text -*- +- +- +-"const" could be used in more places +- +- +-Array types are used in calling interfaces. Under ANSI C, a value of +-type "arraytype *" cannot be assigned to a variable of type "const +-arraytype *", so we get compilation warnings. +- +-Possible fix: Rewrite internal interfaces to not use arrays this way. +-Provide external routines compatible with old API, but not using +-const? +diff --git a/src/lib/crypto/builtin/des/Makefile.in b/src/lib/crypto/builtin/des/Makefile.in +deleted file mode 100644 +index ed25dab7c..000000000 +--- a/src/lib/crypto/builtin/des/Makefile.in ++++ /dev/null +@@ -1,80 +0,0 @@ +-mydir=lib$(S)crypto$(S)builtin$(S)des +-BUILDTOP=$(REL)..$(S)..$(S)..$(S).. +-LOCALINCLUDES = -I$(srcdir)/.. -I$(srcdir)/../../krb +- +-##DOS##BUILDTOP = ..\..\..\.. +-##DOS##PREFIXDIR = builtin\des +-##DOS##OBJFILE = ..\..\$(OUTPRE)des.lst +- +-STLIBOBJS=\ +- d3_aead.o \ +- d3_kysched.o \ +- des_keys.o \ +- f_aead.o \ +- f_cksum.o \ +- f_parity.o \ +- f_sched.o \ +- f_tables.o \ +- key_sched.o \ +- weak_key.o +- +-OBJS= $(OUTPRE)d3_aead.$(OBJEXT) \ +- $(OUTPRE)d3_kysched.$(OBJEXT) \ +- $(OUTPRE)des_keys.$(OBJEXT) \ +- $(OUTPRE)f_aead.$(OBJEXT) \ +- $(OUTPRE)f_cksum.$(OBJEXT) \ +- $(OUTPRE)f_parity.$(OBJEXT) \ +- $(OUTPRE)f_sched.$(OBJEXT) \ +- $(OUTPRE)f_tables.$(OBJEXT) \ +- $(OUTPRE)key_sched.$(OBJEXT) \ +- $(OUTPRE)weak_key.$(OBJEXT) +- +-SRCS= $(srcdir)/d3_aead.c \ +- $(srcdir)/d3_kysched.c \ +- $(srcdir)/des_keys.c \ +- $(srcdir)/f_aead.c \ +- $(srcdir)/f_cksum.c \ +- $(srcdir)/f_parity.c \ +- $(srcdir)/f_sched.c \ +- $(srcdir)/f_tables.c \ +- $(srcdir)/key_sched.c \ +- $(srcdir)/weak_key.c +- +-EXTRADEPSRCS = $(srcdir)/destest.c $(srcdir)/f_cbc.c $(srcdir)/t_verify.c +- +-##DOS##LIBOBJS = $(OBJS) +- +-TOBJS = $(OUTPRE)key_sched.$(OBJEXT) $(OUTPRE)f_sched.$(OBJEXT) \ +- $(OUTPRE)f_cbc.$(OBJEXT) $(OUTPRE)f_tables.$(OBJEXT) \ +- $(OUTPRE)f_cksum.$(OBJEXT) +- +-verify$(EXEEXT): t_verify.$(OBJEXT) $(TOBJS) f_parity.$(OBJEXT) \ +- $(COM_ERR_DEPLIB) $(SUPPORT_DEPLIB) +- $(CC_LINK) -o $@ t_verify.$(OBJEXT) $(TOBJS) f_parity.$(OBJEXT) \ +- -lcom_err $(SUPPORT_LIB) +- +-destest$(EXEEXT): destest.$(OBJEXT) $(TOBJS) $(SUPPORT_DEPLIB) +- $(CC_LINK) -o $@ destest.$(OBJEXT) $(TOBJS) $(SUPPORT_LIB) +- +-all-unix: all-libobjs +- +-check-unix: verify destest +- $(RUN_TEST) ./verify -z +- $(RUN_TEST) ./verify -m +- $(RUN_TEST) ./verify +- $(RUN_TEST) ./destest < $(srcdir)/keytest.data +- +-includes: depend +- +-depend: $(SRCS) +- +-check-windows: +- +-clean: +- $(RM) destest.$(OBJEXT) destest$(EXEEXT) verify$(EXEEXT) \ +- t_verify.$(OBJEXT) $(TOBJS) +- +-clean-unix:: clean-libobjs +- +-@libobj_frag@ +- +diff --git a/src/lib/crypto/builtin/des/d3_aead.c b/src/lib/crypto/builtin/des/d3_aead.c +deleted file mode 100644 +index bddf75a47..000000000 +--- a/src/lib/crypto/builtin/des/d3_aead.c ++++ /dev/null +@@ -1,133 +0,0 @@ +-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +-/* +- * Copyright (C) 2008 by the Massachusetts Institute of Technology. +- * Copyright 1995 by Richard P. Basch. All Rights Reserved. +- * Copyright 1995 by Lehman Brothers, Inc. All Rights Reserved. +- * +- * Export of this software from the United States of America may +- * require a specific license from the United States Government. +- * It is the responsibility of any person or organization contemplating +- * export to obtain such a license before exporting. +- * +- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +- * distribute this software and its documentation for any purpose and +- * without fee is hereby granted, provided that the above copyright +- * notice appear in all copies and that both that copyright notice and +- * this permission notice appear in supporting documentation, and that +- * the name of Richard P. Basch, Lehman Brothers and M.I.T. not be used +- * in advertising or publicity pertaining to distribution of the software +- * without specific, written prior permission. Richard P. Basch, +- * Lehman Brothers and M.I.T. make no representations about the suitability +- * of this software for any purpose. It is provided "as is" without +- * express or implied warranty. +- */ +- +-#include "crypto_int.h" +-#include "des_int.h" +-#include "f_tables.h" +- +-void +-krb5int_des3_cbc_encrypt(krb5_crypto_iov *data, unsigned long num_data, +- const mit_des_key_schedule ks1, +- const mit_des_key_schedule ks2, +- const mit_des_key_schedule ks3, +- mit_des_cblock ivec) +-{ +- unsigned DES_INT32 left, right; +- const unsigned DES_INT32 *kp1, *kp2, *kp3; +- const unsigned char *ip; +- struct iov_cursor cursor; +- unsigned char block[MIT_DES_BLOCK_LENGTH]; +- +- /* Get key pointers here. These won't need to be reinitialized. */ +- kp1 = (const unsigned DES_INT32 *)ks1; +- kp2 = (const unsigned DES_INT32 *)ks2; +- kp3 = (const unsigned DES_INT32 *)ks3; +- +- /* Initialize left and right with the contents of the initial vector. */ +- ip = (ivec != NULL) ? ivec : mit_des_zeroblock; +- left = load_32_be(ip); +- right = load_32_be(ip + 4); +- +- k5_iov_cursor_init(&cursor, data, num_data, MIT_DES_BLOCK_LENGTH, FALSE); +- while (k5_iov_cursor_get(&cursor, block)) { +- /* xor this block with the previous ciphertext. */ +- left ^= load_32_be(block); +- right ^= load_32_be(block + 4); +- +- /* Encrypt what we have and store it back into block. */ +- DES_DO_ENCRYPT(left, right, kp1); +- DES_DO_DECRYPT(left, right, kp2); +- DES_DO_ENCRYPT(left, right, kp3); +- store_32_be(left, block); +- store_32_be(right, block + 4); +- +- k5_iov_cursor_put(&cursor, block); +- } +- +- if (ivec != NULL) { +- store_32_be(left, ivec); +- store_32_be(right, ivec + 4); +- } +-} +- +-void +-krb5int_des3_cbc_decrypt(krb5_crypto_iov *data, unsigned long num_data, +- const mit_des_key_schedule ks1, +- const mit_des_key_schedule ks2, +- const mit_des_key_schedule ks3, +- mit_des_cblock ivec) +-{ +- unsigned DES_INT32 left, right; +- const unsigned DES_INT32 *kp1, *kp2, *kp3; +- const unsigned char *ip; +- unsigned DES_INT32 ocipherl, ocipherr; +- unsigned DES_INT32 cipherl, cipherr; +- struct iov_cursor cursor; +- unsigned char block[MIT_DES_BLOCK_LENGTH]; +- +- /* Get key pointers here. These won't need to be reinitialized. */ +- kp1 = (const unsigned DES_INT32 *)ks1; +- kp2 = (const unsigned DES_INT32 *)ks2; +- kp3 = (const unsigned DES_INT32 *)ks3; +- +- /* +- * Decrypting is harder than encrypting because of +- * the necessity of remembering a lot more things. +- * Should think about this a little more... +- */ +- +- /* Prime the old cipher with ivec.*/ +- ip = (ivec != NULL) ? ivec : mit_des_zeroblock; +- ocipherl = load_32_be(ip); +- ocipherr = load_32_be(ip + 4); +- +- k5_iov_cursor_init(&cursor, data, num_data, MIT_DES_BLOCK_LENGTH, FALSE); +- while (k5_iov_cursor_get(&cursor, block)) { +- /* Split this block into left and right. */ +- cipherl = left = load_32_be(block); +- cipherr = right = load_32_be(block + 4); +- +- /* Decrypt and xor with the old cipher to get plain text. */ +- DES_DO_DECRYPT(left, right, kp3); +- DES_DO_ENCRYPT(left, right, kp2); +- DES_DO_DECRYPT(left, right, kp1); +- left ^= ocipherl; +- right ^= ocipherr; +- +- /* Store the encrypted halves back into block. */ +- store_32_be(left, block); +- store_32_be(right, block + 4); +- +- /* Save current cipher block halves. */ +- ocipherl = cipherl; +- ocipherr = cipherr; +- +- k5_iov_cursor_put(&cursor, block); +- } +- +- if (ivec != NULL) { +- store_32_be(ocipherl, ivec); +- store_32_be(ocipherr, ivec + 4); +- } +-} +diff --git a/src/lib/crypto/builtin/des/d3_kysched.c b/src/lib/crypto/builtin/des/d3_kysched.c +deleted file mode 100644 +index ebd1050b1..000000000 +--- a/src/lib/crypto/builtin/des/d3_kysched.c ++++ /dev/null +@@ -1,51 +0,0 @@ +-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +-/* +- * Copyright 1995 by Richard P. Basch. All Rights Reserved. +- * Copyright 1995 by Lehman Brothers, Inc. All Rights Reserved. +- * +- * Export of this software from the United States of America may +- * require a specific license from the United States Government. +- * It is the responsibility of any person or organization contemplating +- * export to obtain such a license before exporting. +- * +- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +- * distribute this software and its documentation for any purpose and +- * without fee is hereby granted, provided that the above copyright +- * notice appear in all copies and that both that copyright notice and +- * this permission notice appear in supporting documentation, and that +- * the name of Richard P. Basch, Lehman Brothers and M.I.T. not be used +- * in advertising or publicity pertaining to distribution of the software +- * without specific, written prior permission. Richard P. Basch, +- * Lehman Brothers and M.I.T. make no representations about the suitability +- * of this software for any purpose. It is provided "as is" without +- * express or implied warranty. +- */ +- +-#include "k5-int.h" +-#include "des_int.h" +- +-int +-mit_des3_key_sched(mit_des3_cblock k, mit_des3_key_schedule schedule) +-{ +- mit_des_make_key_sched(k[0],schedule[0]); +- mit_des_make_key_sched(k[1],schedule[1]); +- mit_des_make_key_sched(k[2],schedule[2]); +- +- if (!mit_des_check_key_parity(k[0])) /* bad parity --> return -1 */ +- return(-1); +- if (mit_des_is_weak_key(k[0])) +- return(-2); +- +- if (!mit_des_check_key_parity(k[1])) +- return(-1); +- if (mit_des_is_weak_key(k[1])) +- return(-2); +- +- if (!mit_des_check_key_parity(k[2])) +- return(-1); +- if (mit_des_is_weak_key(k[2])) +- return(-2); +- +- /* if key was good, return 0 */ +- return 0; +-} +diff --git a/src/lib/crypto/builtin/des/deps b/src/lib/crypto/builtin/des/deps +deleted file mode 100644 +index df2a31dac..000000000 +--- a/src/lib/crypto/builtin/des/deps ++++ /dev/null +@@ -1,148 +0,0 @@ +-# +-# Generated makefile dependencies follow. +-# +-d3_aead.so d3_aead.po $(OUTPRE)d3_aead.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ +- $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ +- $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h \ +- $(srcdir)/../aes/aes.h $(srcdir)/../crypto_mod.h $(srcdir)/../sha2/sha2.h \ +- $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ +- $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ +- $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ +- $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ +- $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ +- $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ +- $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ +- d3_aead.c des_int.h f_tables.h +-d3_kysched.so d3_kysched.po $(OUTPRE)d3_kysched.$(OBJEXT): \ +- $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ +- $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ +- $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ +- $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ +- $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ +- $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ +- $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ +- $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ +- $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ +- d3_kysched.c des_int.h +-des_keys.so des_keys.po $(OUTPRE)des_keys.$(OBJEXT): \ +- $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ +- $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ +- $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h $(srcdir)/../aes/aes.h \ +- $(srcdir)/../crypto_mod.h $(srcdir)/../sha2/sha2.h \ +- $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ +- $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ +- $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ +- $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ +- $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ +- $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ +- $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ +- des_int.h des_keys.c +-f_aead.so f_aead.po $(OUTPRE)f_aead.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ +- $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ +- $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h \ +- $(srcdir)/../aes/aes.h $(srcdir)/../crypto_mod.h $(srcdir)/../sha2/sha2.h \ +- $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ +- $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ +- $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ +- $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ +- $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ +- $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ +- $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ +- des_int.h f_aead.c f_tables.h +-f_cksum.so f_cksum.po $(OUTPRE)f_cksum.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ +- $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ +- $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ +- $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ +- $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ +- $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ +- $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ +- $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ +- $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ +- $(top_srcdir)/include/socket-utils.h des_int.h f_cksum.c \ +- f_tables.h +-f_parity.so f_parity.po $(OUTPRE)f_parity.$(OBJEXT): \ +- $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ +- $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ +- $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ +- $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ +- $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ +- $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ +- $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ +- $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ +- $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ +- des_int.h f_parity.c +-f_sched.so f_sched.po $(OUTPRE)f_sched.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ +- $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ +- $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ +- $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ +- $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ +- $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ +- $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ +- $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ +- $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ +- $(top_srcdir)/include/socket-utils.h des_int.h f_sched.c +-f_tables.so f_tables.po $(OUTPRE)f_tables.$(OBJEXT): \ +- $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ +- $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ +- $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ +- $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ +- $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ +- $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ +- $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ +- $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ +- $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ +- des_int.h f_tables.c f_tables.h +-key_sched.so key_sched.po $(OUTPRE)key_sched.$(OBJEXT): \ +- $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ +- $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ +- $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ +- $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ +- $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ +- $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ +- $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ +- $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ +- $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ +- des_int.h key_sched.c +-weak_key.so weak_key.po $(OUTPRE)weak_key.$(OBJEXT): \ +- $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ +- $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ +- $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ +- $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ +- $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ +- $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ +- $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ +- $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ +- $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ +- des_int.h weak_key.c +-destest.so destest.po $(OUTPRE)destest.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ +- $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ +- $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ +- $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ +- $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ +- $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ +- $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ +- $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ +- $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ +- $(top_srcdir)/include/socket-utils.h des_int.h destest.c +-f_cbc.so f_cbc.po $(OUTPRE)f_cbc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ +- $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ +- $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ +- $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ +- $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ +- $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ +- $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ +- $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ +- $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ +- $(top_srcdir)/include/socket-utils.h des_int.h f_cbc.c \ +- f_tables.h +-t_verify.so t_verify.po $(OUTPRE)t_verify.$(OBJEXT): \ +- $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ +- $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ +- $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ +- $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ +- $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ +- $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ +- $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ +- $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ +- $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ +- des_int.h t_verify.c +diff --git a/src/lib/crypto/builtin/des/des_int.h b/src/lib/crypto/builtin/des/des_int.h +deleted file mode 100644 +index f8dc6b296..000000000 +--- a/src/lib/crypto/builtin/des/des_int.h ++++ /dev/null +@@ -1,285 +0,0 @@ +-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +-/* lib/crypto/builtin/des/des_int.h */ +-/* +- * Copyright 1987, 1988, 1990, 2002 by the Massachusetts Institute of +- * Technology. All Rights Reserved. +- * +- * Export of this software from the United States of America may +- * require a specific license from the United States Government. +- * It is the responsibility of any person or organization contemplating +- * export to obtain such a license before exporting. +- * +- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +- * distribute this software and its documentation for any purpose and +- * without fee is hereby granted, provided that the above copyright +- * notice appear in all copies and that both that copyright notice and +- * this permission notice appear in supporting documentation, and that +- * the name of M.I.T. not be used in advertising or publicity pertaining +- * to distribution of the software without specific, written prior +- * permission. Furthermore if you modify this software you must label +- * your software as modified software and not distribute it in such a +- * fashion that it might be confused with the original M.I.T. software. +- * M.I.T. makes no representations about the suitability of +- * this software for any purpose. It is provided "as is" without express +- * or implied warranty. +- */ +-/* +- * Copyright (C) 1998 by the FundsXpress, INC. +- * +- * All rights reserved. +- * +- * Export of this software from the United States of America may require +- * a specific license from the United States Government. It is the +- * responsibility of any person or organization contemplating export to +- * obtain such a license before exporting. +- * +- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +- * distribute this software and its documentation for any purpose and +- * without fee is hereby granted, provided that the above copyright +- * notice appear in all copies and that both that copyright notice and +- * this permission notice appear in supporting documentation, and that +- * the name of FundsXpress. not be used in advertising or publicity pertaining +- * to distribution of the software without specific, written prior +- * permission. FundsXpress makes no representations about the suitability of +- * this software for any purpose. It is provided "as is" without express +- * or implied warranty. +- * +- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR +- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. +- */ +- +-/* Private include file for the Data Encryption Standard library. */ +- +-/* only do the whole thing once */ +-#ifndef DES_INTERNAL_DEFS +-#define DES_INTERNAL_DEFS +- +-#include "k5-int.h" +-/* +- * Begin "mit-des.h" +- */ +-#ifndef KRB5_MIT_DES__ +-#define KRB5_MIT_DES__ +- +-#if defined(__MACH__) && defined(__APPLE__) +-#include +-#include +-#if TARGET_RT_MAC_CFM +-#error "Use KfM 4.0 SDK headers for CFM compilation." +-#endif +-#if defined(DEPRECATED_IN_MAC_OS_X_VERSION_10_5) && !defined(KRB5_SUPRESS_DEPRECATED_WARNINGS) +-#define KRB5INT_DES_DEPRECATED DEPRECATED_IN_MAC_OS_X_VERSION_10_5 +-#endif +-#endif /* defined(__MACH__) && defined(__APPLE__) */ +- +-/* Macro to add deprecated attribute to DES types and functions */ +-/* Currently only defined on macOS 10.5 and later. */ +-#ifndef KRB5INT_DES_DEPRECATED +-#define KRB5INT_DES_DEPRECATED +-#endif +- +-#include +- +-#if UINT_MAX >= 0xFFFFFFFFUL +-#define DES_INT32 int +-#define DES_UINT32 unsigned int +-#else +-#define DES_INT32 long +-#define DES_UINT32 unsigned long +-#endif +- +-typedef unsigned char des_cblock[8] /* crypto-block size */ +-KRB5INT_DES_DEPRECATED; +- +-/* +- * Key schedule. +- * +- * This used to be +- * +- * typedef struct des_ks_struct { +- * union { DES_INT32 pad; des_cblock _;} __; +- * } des_key_schedule[16]; +- * +- * but it would cause trouble if DES_INT32 were ever more than 4 +- * bytes. The reason is that all the encryption functions cast it to +- * (DES_INT32 *), and treat it as if it were DES_INT32[32]. If +- * 2*sizeof(DES_INT32) is ever more than sizeof(des_cblock), the +- * caller-allocated des_key_schedule will be overflowed by the key +- * scheduling functions. We can't assume that every platform will +- * have an exact 32-bit int, and nothing should be looking inside a +- * des_key_schedule anyway. +- */ +-typedef struct des_ks_struct { DES_INT32 _[2]; } des_key_schedule[16] +-KRB5INT_DES_DEPRECATED; +- +-typedef des_cblock mit_des_cblock; +-typedef des_key_schedule mit_des_key_schedule; +- +-/* Triple-DES structures */ +-typedef mit_des_cblock mit_des3_cblock[3]; +-typedef mit_des_key_schedule mit_des3_key_schedule[3]; +- +-#define MIT_DES_ENCRYPT 1 +-#define MIT_DES_DECRYPT 0 +- +-typedef struct mit_des_ran_key_seed { +- krb5_encrypt_block eblock; +- krb5_data sequence; +-} mit_des_random_state; +- +-/* the first byte of the key is already in the keyblock */ +- +-#define MIT_DES_BLOCK_LENGTH (8*sizeof(krb5_octet)) +-/* This used to be 8*sizeof(krb5_octet) */ +-#define MIT_DES_KEYSIZE 8 +- +-#define MIT_DES_CBC_CKSUM_LENGTH (4*sizeof(krb5_octet)) +- +-#endif /* KRB5_MIT_DES__ */ +-/* +- * End "mit-des.h" +- */ +- +-/* afsstring2key.c */ +-krb5_error_code mit_afs_string_to_key(krb5_keyblock *keyblock, +- const krb5_data *data, +- const krb5_data *salt); +-char *mit_afs_crypt(const char *pw, const char *salt, char *iobuf); +- +-/* f_cksum.c */ +-unsigned long mit_des_cbc_cksum(const krb5_octet *, krb5_octet *, +- unsigned long, const mit_des_key_schedule, +- const krb5_octet *); +- +-/* f_cbc.c (used by test programs) */ +-int +-mit_des_cbc_encrypt(const mit_des_cblock *in, mit_des_cblock *out, +- unsigned long length, const mit_des_key_schedule schedule, +- const mit_des_cblock ivec, int enc); +- +-#define mit_des_zeroblock krb5int_c_mit_des_zeroblock +-extern const mit_des_cblock mit_des_zeroblock; +- +-/* fin_rndkey.c */ +-krb5_error_code mit_des_finish_random_key(const krb5_encrypt_block *, +- krb5_pointer *); +- +-/* finish_key.c */ +-krb5_error_code mit_des_finish_key(krb5_encrypt_block *); +- +-/* init_rkey.c */ +-krb5_error_code mit_des_init_random_key(const krb5_encrypt_block *, +- const krb5_keyblock *, +- krb5_pointer *); +- +-/* key_parity.c */ +-void mit_des_fixup_key_parity(mit_des_cblock); +-int mit_des_check_key_parity(mit_des_cblock); +- +-/* key_sched.c */ +-int mit_des_key_sched(mit_des_cblock, mit_des_key_schedule); +- +-/* process_ky.c */ +-krb5_error_code mit_des_process_key(krb5_encrypt_block *, +- const krb5_keyblock *); +- +-/* random_key.c */ +-krb5_error_code mit_des_random_key(const krb5_encrypt_block *, +- krb5_pointer, krb5_keyblock **); +- +-/* string2key.c */ +-krb5_error_code mit_des_string_to_key(const krb5_encrypt_block *, +- krb5_keyblock *, const krb5_data *, +- const krb5_data *); +-krb5_error_code mit_des_string_to_key_int(krb5_keyblock *, const krb5_data *, +- const krb5_data *); +- +-/* weak_key.c */ +-int mit_des_is_weak_key(mit_des_cblock); +- +-/* cmb_keys.c */ +-krb5_error_code mit_des_combine_subkeys(const krb5_keyblock *, +- const krb5_keyblock *, +- krb5_keyblock **); +- +-/* f_pcbc.c */ +-int mit_des_pcbc_encrypt(); +- +-/* f_sched.c */ +-int mit_des_make_key_sched(mit_des_cblock, mit_des_key_schedule); +- +- +-/* misc.c */ +-extern void swap_bits(char *); +-extern unsigned long long_swap_bits(unsigned long); +-extern unsigned long swap_six_bits_to_ansi(unsigned long); +-extern unsigned long swap_four_bits_to_ansi(unsigned long); +-extern unsigned long swap_bit_pos_1(unsigned long); +-extern unsigned long swap_bit_pos_0(unsigned long); +-extern unsigned long swap_bit_pos_0_to_ansi(unsigned long); +-extern unsigned long rev_swap_bit_pos_0(unsigned long); +-extern unsigned long swap_byte_bits(unsigned long); +-extern unsigned long swap_long_bytes_bit_number(unsigned long); +-#ifdef FILE +-/* XXX depends on FILE being a #define! */ +-extern void test_set(FILE *, const char *, int, const char *, int); +-#endif +- +-void +-krb5int_des3_cbc_encrypt(krb5_crypto_iov *data, unsigned long num_data, +- const mit_des_key_schedule ks1, +- const mit_des_key_schedule ks2, +- const mit_des_key_schedule ks3, +- mit_des_cblock ivec); +- +-void +-krb5int_des3_cbc_decrypt(krb5_crypto_iov *data, unsigned long num_data, +- const mit_des_key_schedule ks1, +- const mit_des_key_schedule ks2, +- const mit_des_key_schedule ks3, +- mit_des_cblock ivec); +- +-void +-krb5int_des_cbc_encrypt(krb5_crypto_iov *data, unsigned long num_data, +- const mit_des_key_schedule schedule, +- mit_des_cblock ivec); +- +-void +-krb5int_des_cbc_decrypt(krb5_crypto_iov *data, unsigned long num_data, +- const mit_des_key_schedule schedule, +- mit_des_cblock ivec); +- +-void +-krb5int_des_cbc_mac(const krb5_crypto_iov *data, unsigned long num_data, +- const mit_des_key_schedule schedule, mit_des_cblock ivec, +- mit_des_cblock out); +- +-/* d3_procky.c */ +-krb5_error_code mit_des3_process_key(krb5_encrypt_block *eblock, +- const krb5_keyblock *keyblock); +- +-/* d3_kysched.c */ +-int mit_des3_key_sched(mit_des3_cblock key, mit_des3_key_schedule schedule); +- +-/* d3_str2ky.c */ +-krb5_error_code mit_des3_string_to_key(const krb5_encrypt_block *eblock, +- krb5_keyblock *keyblock, +- const krb5_data *data, +- const krb5_data *salt); +- +-/* u_nfold.c */ +-krb5_error_code mit_des_n_fold(const krb5_octet *input, const size_t in_len, +- krb5_octet *output, const size_t out_len); +- +-/* u_rn_key.c */ +-int mit_des_is_weak_keyblock(krb5_keyblock *keyblock); +- +-void mit_des_fixup_keyblock_parity(krb5_keyblock *keyblock); +- +-krb5_error_code mit_des_set_random_generator_seed(const krb5_data *seed, +- krb5_pointer random_state); +- +-krb5_error_code mit_des_set_random_sequence_number(const krb5_data *sequence, +- krb5_pointer random_state); +-#endif /*DES_INTERNAL_DEFS*/ +diff --git a/src/lib/crypto/builtin/des/des_keys.c b/src/lib/crypto/builtin/des/des_keys.c +deleted file mode 100644 +index 32b119aad..000000000 +--- a/src/lib/crypto/builtin/des/des_keys.c ++++ /dev/null +@@ -1,40 +0,0 @@ +-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +-/* lib/crypto/builtin/des/des_keys.c - Key functions used by Kerberos code */ +-/* +- * Copyright (C) 2011 by the Massachusetts Institute of Technology. +- * All rights reserved. +- * +- * Export of this software from the United States of America may +- * require a specific license from the United States Government. +- * It is the responsibility of any person or organization contemplating +- * export to obtain such a license before exporting. +- * +- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +- * distribute this software and its documentation for any purpose and +- * without fee is hereby granted, provided that the above copyright +- * notice appear in all copies and that both that copyright notice and +- * this permission notice appear in supporting documentation, and that +- * the name of M.I.T. not be used in advertising or publicity pertaining +- * to distribution of the software without specific, written prior +- * permission. Furthermore if you modify this software you must label +- * your software as modified software and not distribute it in such a +- * fashion that it might be confused with the original M.I.T. software. +- * M.I.T. makes no representations about the suitability of +- * this software for any purpose. It is provided "as is" without express +- * or implied warranty. +- */ +- +-#include "crypto_int.h" +-#include "des_int.h" +- +-void +-k5_des_fixup_key_parity(unsigned char *keybits) +-{ +- mit_des_fixup_key_parity(keybits); +-} +- +-krb5_boolean +-k5_des_is_weak_key(unsigned char *keybits) +-{ +- return mit_des_is_weak_key(keybits); +-} +diff --git a/src/lib/crypto/builtin/des/destest.c b/src/lib/crypto/builtin/des/destest.c +deleted file mode 100644 +index 52114304e..000000000 +--- a/src/lib/crypto/builtin/des/destest.c ++++ /dev/null +@@ -1,240 +0,0 @@ +-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +-/* lib/crypto/builtin/des/destest.c */ +-/* +- * Copyright 1990,1991 by the Massachusetts Institute of Technology. +- * All Rights Reserved. +- * +- * Export of this software from the United States of America may +- * require a specific license from the United States Government. +- * It is the responsibility of any person or organization contemplating +- * export to obtain such a license before exporting. +- * +- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +- * distribute this software and its documentation for any purpose and +- * without fee is hereby granted, provided that the above copyright +- * notice appear in all copies and that both that copyright notice and +- * this permission notice appear in supporting documentation, and that +- * the name of M.I.T. not be used in advertising or publicity pertaining +- * to distribution of the software without specific, written prior +- * permission. Furthermore if you modify this software you must label +- * your software as modified software and not distribute it in such a +- * fashion that it might be confused with the original M.I.T. software. +- * M.I.T. makes no representations about the suitability of +- * this software for any purpose. It is provided "as is" without express +- * or implied warranty. +- */ +-/* +- * Copyright (C) 1998 by the FundsXpress, INC. +- * +- * All rights reserved. +- * +- * Export of this software from the United States of America may require +- * a specific license from the United States Government. It is the +- * responsibility of any person or organization contemplating export to +- * obtain such a license before exporting. +- * +- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +- * distribute this software and its documentation for any purpose and +- * without fee is hereby granted, provided that the above copyright +- * notice appear in all copies and that both that copyright notice and +- * this permission notice appear in supporting documentation, and that +- * the name of FundsXpress. not be used in advertising or publicity pertaining +- * to distribution of the software without specific, written prior +- * permission. FundsXpress makes no representations about the suitability of +- * this software for any purpose. It is provided "as is" without express +- * or implied warranty. +- * +- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR +- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. +- */ +- +-/* Test a DES implementation against known inputs & outputs. */ +- +-#include "des_int.h" +-#include +-#include +- +-void convert (char *, unsigned char []); +- +-void des_cblock_print_file (mit_des_cblock, FILE *); +- +-krb5_octet zeroblock[8] = {0,0,0,0,0,0,0,0}; +- +-int +-main(argc, argv) +- int argc; +- char *argv[]; +-{ +- char block1[17], block2[17], block3[17]; +- /* Force tests of unaligned accesses. */ +- union { unsigned char c[8*4+3]; long l; } u; +- unsigned char *ioblocks = u.c; +- unsigned char *input = ioblocks+1; +- unsigned char *output = ioblocks+10; +- unsigned char *output2 = ioblocks+19; +- unsigned char *key = ioblocks+27; +- mit_des_key_schedule sched; +- int num = 0; +- int retval; +- +- int error = 0; +- +- while (scanf("%16s %16s %16s", block1, block2, block3) == 3) { +- convert(block1, key); +- convert(block2, input); +- convert(block3, output); +- +- retval = mit_des_key_sched(key, sched); +- if (retval) { +- fprintf(stderr, "des test: can't process key: %d\n", retval); +- fprintf(stderr, "des test: %s %s %s\n", block1, block2, block3); +- exit(1); +- } +- mit_des_cbc_encrypt((const mit_des_cblock *) input, +- (mit_des_cblock *) output2, 8, +- sched, zeroblock, 1); +- +- if (memcmp((char *)output2, (char *)output, 8)) { +- fprintf(stderr, +- "DES ENCRYPT ERROR, key %s, text %s, real cipher %s, computed cyphertext %02X%02X%02X%02X%02X%02X%02X%02X\n", +- block1, block2, block3, +- output2[0],output2[1],output2[2],output2[3], +- output2[4],output2[5],output2[6],output2[7]); +- error++; +- } +- +- /* +- * Now try decrypting.... +- */ +- mit_des_cbc_encrypt((const mit_des_cblock *) output, +- (mit_des_cblock *) output2, 8, +- sched, zeroblock, 0); +- +- if (memcmp((char *)output2, (char *)input, 8)) { +- fprintf(stderr, +- "DES DECRYPT ERROR, key %s, text %s, real cipher %s, computed cleartext %02X%02X%02X%02X%02X%02X%02X%02X\n", +- block1, block2, block3, +- output2[0],output2[1],output2[2],output2[3], +- output2[4],output2[5],output2[6],output2[7]); +- error++; +- } +- +- num++; +- } +- +- if (error) +- printf("destest: failed to pass the test\n"); +- else +- printf("destest: %d tests passed successfully\n", num); +- +- exit( (error > 256 && error % 256) ? 1 : error); +-} +- +-int value[128] = { +- -1, -1, -1, -1, -1, -1, -1, -1, +- -1, -1, -1, -1, -1, -1, -1, -1, +- -1, -1, -1, -1, -1, -1, -1, -1, +- -1, -1, -1, -1, -1, -1, -1, -1, +- -1, -1, -1, -1, -1, -1, -1, -1, +- -1, -1, -1, -1, -1, -1, -1, -1, +- 0, 1, 2, 3, 4, 5, 6, 7, +- 8, 9, -1, -1, -1, -1, -1, -1, +- -1, 10, 11, 12, 13, 14, 15, -1, +- -1, -1, -1, -1, -1, -1, -1, -1, +- -1, -1, -1, -1, -1, -1, -1, -1, +- -1, -1, -1, -1, -1, -1, -1, -1, +- -1, -1, -1, -1, -1, -1, -1, -1, +- -1, -1, -1, -1, -1, -1, -1, -1, +- -1, -1, -1, -1, -1, -1, -1, -1, +- -1, -1, -1, -1, -1, -1, -1, -1, +-}; +- +-void +-convert(text, cblock) +- char *text; +- unsigned char cblock[]; +-{ +- int i; +- for (i = 0; i < 8; i++) { +- if (!isascii((unsigned char)text[i * 2])) +- abort (); +- if (value[(int) text[i*2]] == -1 || value[(int) text[i*2+1]] == -1) { +- printf("Bad value byte %d in %s\n", i, text); +- exit(1); +- } +- cblock[i] = 16*value[(int) text[i*2]] + value[(int) text[i*2+1]]; +- } +- return; +-} +- +-/* +- * Fake out the DES library, for the purposes of testing. +- */ +- +-int +-mit_des_is_weak_key(key) +- mit_des_cblock key; +-{ +- return 0; /* fake it out for testing */ +-} +- +-void +-des_cblock_print_file(x, fp) +- mit_des_cblock x; +- FILE *fp; +-{ +- unsigned char *y = (unsigned char *) x; +- int i = 0; +- fprintf(fp," 0x { "); +- +- while (i++ < 8) { +- fprintf(fp,"%x",*y++); +- if (i < 8) +- fprintf(fp,", "); +- } +- fprintf(fp," }"); +-} +- +- +-#define smask(step) ((1<>step)&smask(step))) +-#define parity_char(x) pstep(pstep(pstep((x),4),2),1) +- +-/* +- * des_check_key_parity: returns true iff key has the correct des parity. +- * See des_fix_key_parity for the definition of +- * correct des parity. +- */ +-int +-mit_des_check_key_parity(key) +- mit_des_cblock key; +-{ +- unsigned int i; +- +- for (i=0; i decrypt, else encrypt */ +- Key_schedule schedule; /* addr of key schedule */ +- +-This is the low level routine that encrypts or decrypts a single 8-byte +-block in electronic code book mode. Always transforms the input +-data into the output data. +- +-If encrypt is non-zero, the input (cleartext) is encrypted into the +-output (ciphertext) using the specified key_schedule, pre-set via "des_set_key". +- +-If encrypt is zero, the input (now ciphertext) is decrypted into +-the output (now cleartext). +- +-Input and output may be the same space. +- +-Does not return any meaningful value. Void is not used for compatibility +-with other compilers. +- +-/* -------------------------------------------------------------- */ +- +-int +- cbc_encrypt(input,output,length,schedule,ivec,encrypt) +- +- C_Block *input; /* ptr to input data */ +- C_Block *output; /* ptr to output data */ +- int length; /* desired length, in bytes */ +- Key_schedule schedule; /* addr of precomputed schedule */ +- C_Block *ivec; /* pointer to 8 byte initialization +- * vector +- */ +- int encrypt /* 0 ==> decrypt; else encrypt*/ +- +- +- If encrypt is non-zero, the routine cipher-block-chain encrypts +- the INPUT (cleartext) into the OUTPUT (ciphertext) using the provided +- key schedule and initialization vector. If the length is not an integral +- multiple of eight bytes, the last block is copied to a temp and zero +- filled (highest addresses). The output is ALWAYS an integral multiple +- of eight bytes. +- +- If encrypt is zero, the routine cipher-block chain decrypts the INPUT +- (ciphertext) into the OUTPUT (cleartext) using the provided key schedule +- and initialization vector. Decryption ALWAYS operates on integral +- multiples of 8 bytes, so will round the length provided up to the +- appropriate multiple. Consequently, it will always produce the rounded-up +- number of bytes of output cleartext. The application must determine if +- the output cleartext was zero-padded due to cleartext lengths not integral +- multiples of 8. +- +- No errors or meaningful value are returned. Void is not used for +- compatibility with other compilers. +- +- +-/* cbc checksum (MAC) only routine ---------------------------------------- */ +-int +- cbc_cksum(input,output,length,schedule,ivec) +- +- C_Block *input; /* >= length bytes of inputtext */ +- C_Block *output; /* >= length bytes of outputtext */ +- int length; /* in bytes */ +- Key_schedule schedule; /* precomputed key schedule */ +- C_Block *ivec; /* 8 bytes of ivec */ +- +- +- Produces a cryptographic checksum, 8 bytes, by cipher-block-chain +- encrypting the input, discarding the ciphertext output, and only retaining +- the last ciphertext 8-byte block. Uses the provided key schedule and ivec. +- The input is effectively zero-padded to an integral multiple of +- eight bytes, though the original input is not modified. +- +- No meaningful value is returned. Void is not used for compatibility +- with other compilers. +- +- +-/* random_key ----------------------------------------*/ +-int +- random_key(key) +- +- C_Block *key; +- +- The start for the random number generated is set from the current time +- in microseconds, then the random number generator is invoked +- to create an eight byte output key (not a schedule). The key +- generated is set to odd parity per FIPS spec. +- +- The caller must supply space for the output key, pointed to +- by "*key", then after getting a new key, call the des_set_key() +- routine when needed. +- +- No meaningfull value is returned. Void is not used for compatibility +- with other compilers. +- +- +-/* string_to_key --------------------------------------------*/ +- +-int +- string_to_key(str,key) +- char *str; +- C_Block *key; +- +- This routines converts an arbitrary length, null terminated string +- to an 8 byte DES key, with each byte parity set to odd, per FIPS spec. +- +- The algorithm is as follows: +- +-| Take the first 8 bytes and remove the parity (leaving 56 bits). +-| Do the same for the second 8 bytes, and the third, etc. Do this for +-| as many sets of 8 bytes as necessary, filling in the remainder of the +-| last set with nulls. Fold the second set back on the first (i.e. bit +-| 0 over bit 55, and bit 55 over bit 0). Fold the third over the second +-| (bit 0 of the third set is now over bit 0 of the first set). Repeat +-| until you have done this to all sets. Xor the folded sets. Break the +-| result into 8 7 bit bytes, and generate odd parity for each byte. You +-| now have 64 bits. Note that DES takes a 64 bit key, and uses only the +-| non parity bits. +- +- +-/* read_password -------------------------------------------*/ +- +-read_password(k,prompt,verify) +- C_Block *k; +- char *prompt; +- int verify; +- +-This routine issues the supplied prompt, turns off echo, if possible, and +-reads an input string. If verify is non-zero, it does it again, for use +-in applications such as changing a password. If verify is non-zero, both +-versions are compared, and the input is requested repeatedly until they +-match. Then, the input string is mapped into a valid DES key, internally +-using the string_to_key routine. The newly created key is copied to the +-area pointed to by parameter "k". +- +-No meaningful value is returned. If an error occurs trying to manipulate +-the terminal echo, the routine forces the process to exit. +- +-/* get_line ------------------------*/ +-long get_line(p,max) +- char *p; +- long max; +- +-Reads input characters from standard input until either a newline appears or +-else the max length is reached. The characters read are stuffed into +-the string pointed to, which will always be null terminated. The newline +-is not inserted in the string. The max parameter includes the byte needed +-for the null terminator, so allocate and pass one more than the maximum +-string length desired. +diff --git a/src/lib/crypto/builtin/des/f_aead.c b/src/lib/crypto/builtin/des/f_aead.c +deleted file mode 100644 +index 71b8dff4d..000000000 +--- a/src/lib/crypto/builtin/des/f_aead.c ++++ /dev/null +@@ -1,173 +0,0 @@ +-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +-/* +- * Copyright (C) 2008 by the Massachusetts Institute of Technology. +- * Copyright 1995 by Richard P. Basch. All Rights Reserved. +- * Copyright 1995 by Lehman Brothers, Inc. All Rights Reserved. +- * +- * Export of this software from the United States of America may +- * require a specific license from the United States Government. +- * It is the responsibility of any person or organization contemplating +- * export to obtain such a license before exporting. +- * +- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +- * distribute this software and its documentation for any purpose and +- * without fee is hereby granted, provided that the above copyright +- * notice appear in all copies and that both that copyright notice and +- * this permission notice appear in supporting documentation, and that +- * the name of Richard P. Basch, Lehman Brothers and M.I.T. not be used +- * in advertising or publicity pertaining to distribution of the software +- * without specific, written prior permission. Richard P. Basch, +- * Lehman Brothers and M.I.T. make no representations about the suitability +- * of this software for any purpose. It is provided "as is" without +- * express or implied warranty. +- */ +- +-#include "crypto_int.h" +-#include "des_int.h" +-#include "f_tables.h" +- +-const mit_des_cblock mit_des_zeroblock /* = all zero */; +- +-void +-krb5int_des_cbc_encrypt(krb5_crypto_iov *data, unsigned long num_data, +- const mit_des_key_schedule schedule, +- mit_des_cblock ivec) +-{ +- unsigned DES_INT32 left, right; +- const unsigned DES_INT32 *kp; +- const unsigned char *ip; +- struct iov_cursor cursor; +- unsigned char block[MIT_DES_BLOCK_LENGTH]; +- +- /* Get key pointer here. This won't need to be reinitialized. */ +- kp = (const unsigned DES_INT32 *)schedule; +- +- /* Initialize left and right with the contents of the initial vector. */ +- ip = (ivec != NULL) ? ivec : mit_des_zeroblock; +- left = load_32_be(ip); +- right = load_32_be(ip + 4); +- +- k5_iov_cursor_init(&cursor, data, num_data, MIT_DES_BLOCK_LENGTH, FALSE); +- while (k5_iov_cursor_get(&cursor, block)) { +- /* Decompose this block and xor it with the previous ciphertext. */ +- left ^= load_32_be(block); +- right ^= load_32_be(block + 4); +- +- /* Encrypt what we have and put back into block. */ +- DES_DO_ENCRYPT(left, right, kp); +- store_32_be(left, block); +- store_32_be(right, block + 4); +- +- k5_iov_cursor_put(&cursor, block); +- } +- +- if (ivec != NULL) { +- store_32_be(left, ivec); +- store_32_be(right, ivec + 4); +- } +-} +- +-void +-krb5int_des_cbc_decrypt(krb5_crypto_iov *data, unsigned long num_data, +- const mit_des_key_schedule schedule, +- mit_des_cblock ivec) +-{ +- unsigned DES_INT32 left, right; +- const unsigned DES_INT32 *kp; +- const unsigned char *ip; +- unsigned DES_INT32 ocipherl, ocipherr; +- unsigned DES_INT32 cipherl, cipherr; +- struct iov_cursor cursor; +- unsigned char block[MIT_DES_BLOCK_LENGTH]; +- +- /* Get key pointer here. This won't need to be reinitialized. */ +- kp = (const unsigned DES_INT32 *)schedule; +- +- /* +- * Decrypting is harder than encrypting because of +- * the necessity of remembering a lot more things. +- * Should think about this a little more... +- */ +- +- /* Prime the old cipher with ivec. */ +- ip = (ivec != NULL) ? ivec : mit_des_zeroblock; +- ocipherl = load_32_be(ip); +- ocipherr = load_32_be(ip + 4); +- +- k5_iov_cursor_init(&cursor, data, num_data, MIT_DES_BLOCK_LENGTH, FALSE); +- while (k5_iov_cursor_get(&cursor, block)) { +- /* Split this block into left and right. */ +- cipherl = left = load_32_be(block); +- cipherr = right = load_32_be(block + 4); +- +- /* Decrypt and xor with the old cipher to get plain text. */ +- DES_DO_DECRYPT(left, right, kp); +- left ^= ocipherl; +- right ^= ocipherr; +- +- /* Store the encrypted halves back into block. */ +- store_32_be(left, block); +- store_32_be(right, block + 4); +- +- /* Save current cipher block halves. */ +- ocipherl = cipherl; +- ocipherr = cipherr; +- +- k5_iov_cursor_put(&cursor, block); +- } +- +- if (ivec != NULL) { +- store_32_be(ocipherl, ivec); +- store_32_be(ocipherr, ivec + 4); +- } +-} +- +-void +-krb5int_des_cbc_mac(const krb5_crypto_iov *data, unsigned long num_data, +- const mit_des_key_schedule schedule, mit_des_cblock ivec, +- mit_des_cblock out) +-{ +- unsigned DES_INT32 left, right; +- const unsigned DES_INT32 *kp; +- const unsigned char *ip; +- struct iov_cursor cursor; +- unsigned char block[MIT_DES_BLOCK_LENGTH]; +- +- /* Get key pointer here. This won't need to be reinitialized. */ +- kp = (const unsigned DES_INT32 *)schedule; +- +- /* Initialize left and right with the contents of the initial vector. */ +- ip = (ivec != NULL) ? ivec : mit_des_zeroblock; +- left = load_32_be(ip); +- right = load_32_be(ip + 4); +- +- k5_iov_cursor_init(&cursor, data, num_data, MIT_DES_BLOCK_LENGTH, TRUE); +- while (k5_iov_cursor_get(&cursor, block)) { +- /* Decompose this block and xor it with the previous ciphertext. */ +- left ^= load_32_be(block); +- right ^= load_32_be(block + 4); +- +- /* Encrypt what we have. */ +- DES_DO_ENCRYPT(left, right, kp); +- } +- +- /* Output the final ciphertext block. */ +- store_32_be(left, out); +- store_32_be(right, out + 4); +-} +- +-#if defined(CONFIG_SMALL) && !defined(CONFIG_SMALL_NO_CRYPTO) +-void krb5int_des_do_encrypt_2 (unsigned DES_INT32 *left, +- unsigned DES_INT32 *right, +- const unsigned DES_INT32 *kp) +-{ +- DES_DO_ENCRYPT_1 (*left, *right, kp); +-} +- +-void krb5int_des_do_decrypt_2 (unsigned DES_INT32 *left, +- unsigned DES_INT32 *right, +- const unsigned DES_INT32 *kp) +-{ +- DES_DO_DECRYPT_1 (*left, *right, kp); +-} +-#endif +diff --git a/src/lib/crypto/builtin/des/f_cbc.c b/src/lib/crypto/builtin/des/f_cbc.c +deleted file mode 100644 +index 84d5382f2..000000000 +--- a/src/lib/crypto/builtin/des/f_cbc.c ++++ /dev/null +@@ -1,256 +0,0 @@ +-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +-/* lib/crypto/builtin/des/f_cbc.c */ +-/* +- * Copyright (C) 1990 by the Massachusetts Institute of Technology. +- * All rights reserved. +- * +- * Export of this software from the United States of America may +- * require a specific license from the United States Government. +- * It is the responsibility of any person or organization contemplating +- * export to obtain such a license before exporting. +- * +- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +- * distribute this software and its documentation for any purpose and +- * without fee is hereby granted, provided that the above copyright +- * notice appear in all copies and that both that copyright notice and +- * this permission notice appear in supporting documentation, and that +- * the name of M.I.T. not be used in advertising or publicity pertaining +- * to distribution of the software without specific, written prior +- * permission. Furthermore if you modify this software you must label +- * your software as modified software and not distribute it in such a +- * fashion that it might be confused with the original M.I.T. software. +- * M.I.T. makes no representations about the suitability of +- * this software for any purpose. It is provided "as is" without express +- * or implied warranty. +- */ +- +-/* +- * CBC functions; used only by the test programs at this time. (krb5 uses the +- * functions in f_aead.c instead.) +- */ +- +-/* +- * des_cbc_encrypt.c - an implementation of the DES cipher function in cbc mode +- */ +-#include "des_int.h" +-#include "f_tables.h" +- +-/* +- * des_cbc_encrypt - {en,de}crypt a stream in CBC mode +- */ +- +-/* +- * This routine performs DES cipher-block-chaining operation, either +- * encrypting from cleartext to ciphertext, if encrypt != 0 or +- * decrypting from ciphertext to cleartext, if encrypt == 0. +- * +- * The key schedule is passed as an arg, as well as the cleartext or +- * ciphertext. The cleartext and ciphertext should be in host order. +- * +- * NOTE-- the output is ALWAYS an multiple of 8 bytes long. If not +- * enough space was provided, your program will get trashed. +- * +- * For encryption, the cleartext string is null padded, at the end, to +- * an integral multiple of eight bytes. +- * +- * For decryption, the ciphertext will be used in integral multiples +- * of 8 bytes, but only the first "length" bytes returned into the +- * cleartext. +- */ +- +-const mit_des_cblock mit_des_zeroblock /* = all zero */; +- +-static void +-des_cbc_encrypt(const mit_des_cblock *in, mit_des_cblock *out, +- unsigned long length, const mit_des_key_schedule schedule, +- const mit_des_cblock ivec) +-{ +- unsigned DES_INT32 left, right; +- const unsigned DES_INT32 *kp; +- const unsigned char *ip; +- unsigned char *op; +- +- /* +- * Get key pointer here. This won't need to be reinitialized +- */ +- kp = (const unsigned DES_INT32 *)schedule; +- +- /* +- * Initialize left and right with the contents of the initial +- * vector. +- */ +- ip = ivec; +- GET_HALF_BLOCK(left, ip); +- GET_HALF_BLOCK(right, ip); +- +- /* +- * Suitably initialized, now work the length down 8 bytes +- * at a time. +- */ +- ip = *in; +- op = *out; +- while (length > 0) { +- /* +- * Get more input, xor it in. If the length is +- * greater than or equal to 8 this is straight +- * forward. Otherwise we have to fart around. +- */ +- if (length >= 8) { +- unsigned DES_INT32 temp; +- GET_HALF_BLOCK(temp, ip); +- left ^= temp; +- GET_HALF_BLOCK(temp, ip); +- right ^= temp; +- length -= 8; +- } else { +- /* +- * Oh, shoot. We need to pad the +- * end with zeroes. Work backwards +- * to do this. +- */ +- ip += (int) length; +- switch(length) { +- case 7: +- right ^= (*(--ip) & FF_UINT32) << 8; +- case 6: +- right ^= (*(--ip) & FF_UINT32) << 16; +- case 5: +- right ^= (*(--ip) & FF_UINT32) << 24; +- case 4: +- left ^= *(--ip) & FF_UINT32; +- case 3: +- left ^= (*(--ip) & FF_UINT32) << 8; +- case 2: +- left ^= (*(--ip) & FF_UINT32) << 16; +- case 1: +- left ^= (*(--ip) & FF_UINT32) << 24; +- break; +- } +- length = 0; +- } +- +- /* +- * Encrypt what we have +- */ +- DES_DO_ENCRYPT(left, right, kp); +- +- /* +- * Copy the results out +- */ +- PUT_HALF_BLOCK(left, op); +- PUT_HALF_BLOCK(right, op); +- } +-} +- +-static void +-des_cbc_decrypt(const mit_des_cblock *in, mit_des_cblock *out, +- unsigned long length, const mit_des_key_schedule schedule, +- const mit_des_cblock ivec) +-{ +- unsigned DES_INT32 left, right; +- const unsigned DES_INT32 *kp; +- const unsigned char *ip; +- unsigned char *op; +- unsigned DES_INT32 ocipherl, ocipherr; +- unsigned DES_INT32 cipherl, cipherr; +- +- /* +- * Get key pointer here. This won't need to be reinitialized +- */ +- kp = (const unsigned DES_INT32 *)schedule; +- +- /* +- * Decrypting is harder than encrypting because of +- * the necessity of remembering a lot more things. +- * Should think about this a little more... +- */ +- +- if (length <= 0) +- return; +- +- /* +- * Prime the old cipher with ivec. +- */ +- ip = ivec; +- GET_HALF_BLOCK(ocipherl, ip); +- GET_HALF_BLOCK(ocipherr, ip); +- +- /* +- * Now do this in earnest until we run out of length. +- */ +- ip = *in; +- op = *out; +- for (;;) { /* check done inside loop */ +- /* +- * Read a block from the input into left and +- * right. Save this cipher block for later. +- */ +- GET_HALF_BLOCK(left, ip); +- GET_HALF_BLOCK(right, ip); +- cipherl = left; +- cipherr = right; +- +- /* +- * Decrypt this. +- */ +- DES_DO_DECRYPT(left, right, kp); +- +- /* +- * Xor with the old cipher to get plain +- * text. Output 8 or less bytes of this. +- */ +- left ^= ocipherl; +- right ^= ocipherr; +- if (length > 8) { +- length -= 8; +- PUT_HALF_BLOCK(left, op); +- PUT_HALF_BLOCK(right, op); +- /* +- * Save current cipher block here +- */ +- ocipherl = cipherl; +- ocipherr = cipherr; +- } else { +- /* +- * Trouble here. Start at end of output, +- * work backwards. +- */ +- op += (int) length; +- switch(length) { +- case 8: +- *(--op) = (unsigned char) (right & 0xff); +- case 7: +- *(--op) = (unsigned char) ((right >> 8) & 0xff); +- case 6: +- *(--op) = (unsigned char) ((right >> 16) & 0xff); +- case 5: +- *(--op) = (unsigned char) ((right >> 24) & 0xff); +- case 4: +- *(--op) = (unsigned char) (left & 0xff); +- case 3: +- *(--op) = (unsigned char) ((left >> 8) & 0xff); +- case 2: +- *(--op) = (unsigned char) ((left >> 16) & 0xff); +- case 1: +- *(--op) = (unsigned char) ((left >> 24) & 0xff); +- break; +- } +- break; /* we're done */ +- } +- } +-} +- +-int +-mit_des_cbc_encrypt(const mit_des_cblock *in, mit_des_cblock *out, +- unsigned long length, const mit_des_key_schedule schedule, +- const mit_des_cblock ivec, int enc) +-{ +- /* +- * Deal with encryption and decryption separately. +- */ +- if (enc) +- des_cbc_encrypt(in, out, length, schedule, ivec); +- else +- des_cbc_decrypt(in, out, length, schedule, ivec); +- return 0; +-} +diff --git a/src/lib/crypto/builtin/des/f_cksum.c b/src/lib/crypto/builtin/des/f_cksum.c +deleted file mode 100644 +index cb482b009..000000000 +--- a/src/lib/crypto/builtin/des/f_cksum.c ++++ /dev/null +@@ -1,136 +0,0 @@ +-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +-/* lib/crypto/builtin/des/f_cksum.c */ +-/* +- * Copyright (C) 1990 by the Massachusetts Institute of Technology. +- * All rights reserved. +- * +- * Export of this software from the United States of America may +- * require a specific license from the United States Government. +- * It is the responsibility of any person or organization contemplating +- * export to obtain such a license before exporting. +- * +- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +- * distribute this software and its documentation for any purpose and +- * without fee is hereby granted, provided that the above copyright +- * notice appear in all copies and that both that copyright notice and +- * this permission notice appear in supporting documentation, and that +- * the name of M.I.T. not be used in advertising or publicity pertaining +- * to distribution of the software without specific, written prior +- * permission. Furthermore if you modify this software you must label +- * your software as modified software and not distribute it in such a +- * fashion that it might be confused with the original M.I.T. software. +- * M.I.T. makes no representations about the suitability of +- * this software for any purpose. It is provided "as is" without express +- * or implied warranty. +- */ +- +-/* DES implementation donated by Dennis Ferguson */ +- +-/* +- * des_cbc_cksum.c - compute an 8 byte checksum using DES in CBC mode +- */ +-#include "des_int.h" +-#include "f_tables.h" +- +-/* +- * This routine performs DES cipher-block-chaining checksum operation, +- * a.k.a. Message Authentication Code. It ALWAYS encrypts from input +- * to a single 64 bit output MAC checksum. +- * +- * The key schedule is passed as an arg, as well as the cleartext or +- * ciphertext. The cleartext and ciphertext should be in host order. +- * +- * NOTE-- the output is ALWAYS 8 bytes long. If not enough space was +- * provided, your program will get trashed. +- * +- * The input is null padded, at the end (highest addr), to an integral +- * multiple of eight bytes. +- */ +- +-unsigned long +-mit_des_cbc_cksum(const krb5_octet *in, krb5_octet *out, +- unsigned long length, const mit_des_key_schedule schedule, +- const krb5_octet *ivec) +-{ +- unsigned DES_INT32 left, right; +- const unsigned DES_INT32 *kp; +- const unsigned char *ip; +- unsigned char *op; +- DES_INT32 len; +- +- /* +- * Initialize left and right with the contents of the initial +- * vector. +- */ +- ip = ivec; +- GET_HALF_BLOCK(left, ip); +- GET_HALF_BLOCK(right, ip); +- +- /* +- * Suitably initialized, now work the length down 8 bytes +- * at a time. +- */ +- ip = in; +- len = length; +- while (len > 0) { +- /* +- * Get more input, xor it in. If the length is +- * greater than or equal to 8 this is straight +- * forward. Otherwise we have to fart around. +- */ +- if (len >= 8) { +- unsigned DES_INT32 temp; +- GET_HALF_BLOCK(temp, ip); +- left ^= temp; +- GET_HALF_BLOCK(temp, ip); +- right ^= temp; +- len -= 8; +- } else { +- /* +- * Oh, shoot. We need to pad the +- * end with zeroes. Work backwards +- * to do this. +- */ +- ip += (int) len; +- switch(len) { +- case 7: +- right ^= (*(--ip) & FF_UINT32) << 8; +- case 6: +- right ^= (*(--ip) & FF_UINT32) << 16; +- case 5: +- right ^= (*(--ip) & FF_UINT32) << 24; +- case 4: +- left ^= *(--ip) & FF_UINT32; +- case 3: +- left ^= (*(--ip) & FF_UINT32) << 8; +- case 2: +- left ^= (*(--ip) & FF_UINT32) << 16; +- case 1: +- left ^= (*(--ip) & FF_UINT32) << 24; +- break; +- } +- len = 0; +- } +- +- /* +- * Encrypt what we have +- */ +- kp = (const unsigned DES_INT32 *)schedule; +- DES_DO_ENCRYPT(left, right, kp); +- } +- +- /* +- * Done. Left and right have the checksum. Put it into +- * the output. +- */ +- op = out; +- PUT_HALF_BLOCK(left, op); +- PUT_HALF_BLOCK(right, op); +- +- /* +- * Return right. I'll bet the MIT code returns this +- * inconsistantly (with the low order byte of the checksum +- * not always in the low order byte of the DES_INT32). We won't. +- */ +- return right & 0xFFFFFFFFUL; +-} +diff --git a/src/lib/crypto/builtin/des/f_parity.c b/src/lib/crypto/builtin/des/f_parity.c +deleted file mode 100644 +index 460b5061b..000000000 +--- a/src/lib/crypto/builtin/des/f_parity.c ++++ /dev/null +@@ -1,56 +0,0 @@ +-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +-/* +- * These routines check and fix parity of encryption keys for the DES +- * algorithm. +- * +- * They are a replacement for routines in key_parity.c, that don't require +- * the table building that they do. +- * +- * Mark Eichin -- Cygnus Support +- */ +- +- +-#include "des_int.h" +- +-/* +- * des_fixup_key_parity: Forces odd parity per byte; parity is bits +- * 8,16,...64 in des order, implies 0, 8, 16, ... +- * vax order. +- */ +-#define smask(step) ((1<>step)&smask(step))) +-#define parity_char(x) pstep(pstep(pstep((x),4),2),1) +- +-void +-mit_des_fixup_key_parity(mit_des_cblock key) +-{ +- unsigned int i; +- for (i=0; i> 29) & 0x7] +- | (PC1_CL[(tmp >> 21) & 0x7] << 1) +- | (PC1_CL[(tmp >> 13) & 0x7] << 2) +- | (PC1_CL[(tmp >> 5) & 0x7] << 3); +- d = PC1_DL[(tmp >> 25) & 0xf] +- | (PC1_DL[(tmp >> 17) & 0xf] << 1) +- | (PC1_DL[(tmp >> 9) & 0xf] << 2) +- | (PC1_DL[(tmp >> 1) & 0xf] << 3); +- +- tmp = load_32_be(k), k += 4; +- +- c |= PC1_CR[(tmp >> 28) & 0xf] +- | (PC1_CR[(tmp >> 20) & 0xf] << 1) +- | (PC1_CR[(tmp >> 12) & 0xf] << 2) +- | (PC1_CR[(tmp >> 4) & 0xf] << 3); +- d |= PC1_DR[(tmp >> 25) & 0x7] +- | (PC1_DR[(tmp >> 17) & 0x7] << 1) +- | (PC1_DR[(tmp >> 9) & 0x7] << 2) +- | (PC1_DR[(tmp >> 1) & 0x7] << 3); +- } +- +- { +- /* +- * Need several temporaries in here +- */ +- unsigned DES_INT32 ltmp, rtmp; +- unsigned DES_INT32 *k; +- int two_bit_shifts; +- int i; +- /* +- * Now iterate to compute the key schedule. Note that we +- * record the entire set of subkeys in 6 bit chunks since +- * they are used that way. At 6 bits/char, we need +- * 48/6 char's/subkey * 16 subkeys/encryption == 128 bytes. +- * The schedule must be this big. +- */ +- k = (unsigned DES_INT32 *)schedule; +- two_bit_shifts = TWO_BIT_SHIFTS; +- for (i = 16; i > 0; i--) { +- /* +- * Do the rotation. One bit and two bit rotations +- * are done separately. Note C and D are 28 bits. +- */ +- if (two_bit_shifts & 0x1) { +- c = ((c << 2) & 0xffffffc) | (c >> 26); +- d = ((d << 2) & 0xffffffc) | (d >> 26); +- } else { +- c = ((c << 1) & 0xffffffe) | (c >> 27); +- d = ((d << 1) & 0xffffffe) | (d >> 27); +- } +- two_bit_shifts >>= 1; +- +- /* +- * Apply permutted choice 2 to C to get the first +- * 24 bits worth of keys. Note that bits 9, 18, 22 +- * and 25 (using DES numbering) in C are unused. The +- * shift-mask stuff is done to delete these bits from +- * the indices, since this cuts the table size in half. +- * +- * The table is torqued, by the way. If the standard +- * byte order for this (high to low order) is 1234, +- * the table actually gives us 4132. +- */ +- ltmp = PC2_C[0][((c >> 22) & 0x3f)] +- | PC2_C[1][((c >> 15) & 0xf) | ((c >> 16) & 0x30)] +- | PC2_C[2][((c >> 4) & 0x3) | ((c >> 9) & 0x3c)] +- | PC2_C[3][((c ) & 0x7) | ((c >> 4) & 0x38)]; +- /* +- * Apply permutted choice 2 to D to get the other half. +- * Here, bits 7, 10, 15 and 26 go unused. The sqeezing +- * actually turns out to be cheaper here. +- * +- * This table is similarly torqued. If the standard +- * byte order is 5678, the table has the bytes permuted +- * to give us 7685. +- */ +- rtmp = PC2_D[0][((d >> 22) & 0x3f)] +- | PC2_D[1][((d >> 14) & 0xf) | ((d >> 15) & 0x30)] +- | PC2_D[2][((d >> 7) & 0x3f)] +- | PC2_D[3][((d ) & 0x3) | ((d >> 1) & 0x3c)]; +- +- /* +- * Make up two words of the key schedule, with a +- * byte order which is convenient for the DES +- * inner loop. The high order (first) word will +- * hold bytes 7135 (high to low order) while the +- * second holds bytes 4682. +- */ +- *k++ = (ltmp & 0x00ffff00) | (rtmp & 0xff0000ff); +- *k++ = (ltmp & 0xff0000ff) | (rtmp & 0x00ffff00); +- } +- } +- return (0); +-} +diff --git a/src/lib/crypto/builtin/des/f_tables.c b/src/lib/crypto/builtin/des/f_tables.c +deleted file mode 100644 +index 6308cb0d5..000000000 +--- a/src/lib/crypto/builtin/des/f_tables.c ++++ /dev/null +@@ -1,370 +0,0 @@ +-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +-/* lib/crypto/builtin/des/f_tables.c */ +-/* +- * Copyright (C) 1990 by the Massachusetts Institute of Technology. +- * All rights reserved. +- * +- * Export of this software from the United States of America may +- * require a specific license from the United States Government. +- * It is the responsibility of any person or organization contemplating +- * export to obtain such a license before exporting. +- * +- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +- * distribute this software and its documentation for any purpose and +- * without fee is hereby granted, provided that the above copyright +- * notice appear in all copies and that both that copyright notice and +- * this permission notice appear in supporting documentation, and that +- * the name of M.I.T. not be used in advertising or publicity pertaining +- * to distribution of the software without specific, written prior +- * permission. Furthermore if you modify this software you must label +- * your software as modified software and not distribute it in such a +- * fashion that it might be confused with the original M.I.T. software. +- * M.I.T. makes no representations about the suitability of +- * this software for any purpose. It is provided "as is" without express +- * or implied warranty. +- */ +- +-/* DES implementation donated by Dennis Ferguson */ +- +-/* +- * des_tables.c - precomputed tables used for the DES cipher function +- */ +- +-/* +- * Include the header file so something will complain if the +- * declarations get out of sync +- */ +-#include "des_int.h" +-#include "f_tables.h" +- +-/* +- * These tables may be declared const if you want. Many compilers +- * don't support this, though. +- */ +- +-/* +- * The DES algorithm which uses these is intended to be fairly speedy +- * at the expense of some memory. All the standard hacks are used. +- * The S boxes and the P permutation are precomputed into one table. +- * The E box never actually appears explicitly since it is easy to apply +- * this algorithmically as needed. The initial permutation and final +- * (inverse initial) permutation are computed from tables designed to +- * permute one byte at a time. This should run pretty fast on machines +- * with 32 bit words and bit field/multiple bit shift instructions which +- * are fast. +- */ +- +-/* +- * The initial permutation array. This is used to compute both the +- * left and the right halves of the initial permutation using bytes +- * from words made from the following operations: +- * +- * ((left & 0x55555555) << 1) | (right & 0x55555555) for left half +- * (left & 0xaaaaaaaa) | ((right & 0xaaaaaaaa) >> 1) for right half +- * +- * The scheme is that we index into the table using each byte. The +- * result from the high order byte is or'd with the result from the +- * next byte shifted left once is or'd with the result from the next +- * byte shifted left twice if or'd with the result from the low order +- * byte shifted left by three. Clear? +- */ +- +-const unsigned DES_INT32 des_IP_table[256] = { +- 0x00000000, 0x00000010, 0x00000001, 0x00000011, +- 0x00001000, 0x00001010, 0x00001001, 0x00001011, +- 0x00000100, 0x00000110, 0x00000101, 0x00000111, +- 0x00001100, 0x00001110, 0x00001101, 0x00001111, +- 0x00100000, 0x00100010, 0x00100001, 0x00100011, +- 0x00101000, 0x00101010, 0x00101001, 0x00101011, +- 0x00100100, 0x00100110, 0x00100101, 0x00100111, +- 0x00101100, 0x00101110, 0x00101101, 0x00101111, +- 0x00010000, 0x00010010, 0x00010001, 0x00010011, +- 0x00011000, 0x00011010, 0x00011001, 0x00011011, +- 0x00010100, 0x00010110, 0x00010101, 0x00010111, +- 0x00011100, 0x00011110, 0x00011101, 0x00011111, +- 0x00110000, 0x00110010, 0x00110001, 0x00110011, +- 0x00111000, 0x00111010, 0x00111001, 0x00111011, +- 0x00110100, 0x00110110, 0x00110101, 0x00110111, +- 0x00111100, 0x00111110, 0x00111101, 0x00111111, +- 0x10000000, 0x10000010, 0x10000001, 0x10000011, +- 0x10001000, 0x10001010, 0x10001001, 0x10001011, +- 0x10000100, 0x10000110, 0x10000101, 0x10000111, +- 0x10001100, 0x10001110, 0x10001101, 0x10001111, +- 0x10100000, 0x10100010, 0x10100001, 0x10100011, +- 0x10101000, 0x10101010, 0x10101001, 0x10101011, +- 0x10100100, 0x10100110, 0x10100101, 0x10100111, +- 0x10101100, 0x10101110, 0x10101101, 0x10101111, +- 0x10010000, 0x10010010, 0x10010001, 0x10010011, +- 0x10011000, 0x10011010, 0x10011001, 0x10011011, +- 0x10010100, 0x10010110, 0x10010101, 0x10010111, +- 0x10011100, 0x10011110, 0x10011101, 0x10011111, +- 0x10110000, 0x10110010, 0x10110001, 0x10110011, +- 0x10111000, 0x10111010, 0x10111001, 0x10111011, +- 0x10110100, 0x10110110, 0x10110101, 0x10110111, +- 0x10111100, 0x10111110, 0x10111101, 0x10111111, +- 0x01000000, 0x01000010, 0x01000001, 0x01000011, +- 0x01001000, 0x01001010, 0x01001001, 0x01001011, +- 0x01000100, 0x01000110, 0x01000101, 0x01000111, +- 0x01001100, 0x01001110, 0x01001101, 0x01001111, +- 0x01100000, 0x01100010, 0x01100001, 0x01100011, +- 0x01101000, 0x01101010, 0x01101001, 0x01101011, +- 0x01100100, 0x01100110, 0x01100101, 0x01100111, +- 0x01101100, 0x01101110, 0x01101101, 0x01101111, +- 0x01010000, 0x01010010, 0x01010001, 0x01010011, +- 0x01011000, 0x01011010, 0x01011001, 0x01011011, +- 0x01010100, 0x01010110, 0x01010101, 0x01010111, +- 0x01011100, 0x01011110, 0x01011101, 0x01011111, +- 0x01110000, 0x01110010, 0x01110001, 0x01110011, +- 0x01111000, 0x01111010, 0x01111001, 0x01111011, +- 0x01110100, 0x01110110, 0x01110101, 0x01110111, +- 0x01111100, 0x01111110, 0x01111101, 0x01111111, +- 0x11000000, 0x11000010, 0x11000001, 0x11000011, +- 0x11001000, 0x11001010, 0x11001001, 0x11001011, +- 0x11000100, 0x11000110, 0x11000101, 0x11000111, +- 0x11001100, 0x11001110, 0x11001101, 0x11001111, +- 0x11100000, 0x11100010, 0x11100001, 0x11100011, +- 0x11101000, 0x11101010, 0x11101001, 0x11101011, +- 0x11100100, 0x11100110, 0x11100101, 0x11100111, +- 0x11101100, 0x11101110, 0x11101101, 0x11101111, +- 0x11010000, 0x11010010, 0x11010001, 0x11010011, +- 0x11011000, 0x11011010, 0x11011001, 0x11011011, +- 0x11010100, 0x11010110, 0x11010101, 0x11010111, +- 0x11011100, 0x11011110, 0x11011101, 0x11011111, +- 0x11110000, 0x11110010, 0x11110001, 0x11110011, +- 0x11111000, 0x11111010, 0x11111001, 0x11111011, +- 0x11110100, 0x11110110, 0x11110101, 0x11110111, +- 0x11111100, 0x11111110, 0x11111101, 0x11111111 +-}; +- +-/* +- * The final permutation array. Like the IP array, used +- * to compute both the left and right results from the bytes +- * of words computed from: +- * +- * ((left & 0x0f0f0f0f) << 4) | (right & 0x0f0f0f0f) for left result +- * (left & 0xf0f0f0f0) | ((right & 0xf0f0f0f0) >> 4) for right result +- * +- * The result from the high order byte is shifted left 6 bits and +- * or'd with the result from the next byte shifted left 4 bits, which +- * is or'd with the result from the next byte shifted left 2 bits, +- * which is or'd with the result from the low byte. +- */ +-const unsigned DES_INT32 des_FP_table[256] = { +- 0x00000000, 0x02000000, 0x00020000, 0x02020000, +- 0x00000200, 0x02000200, 0x00020200, 0x02020200, +- 0x00000002, 0x02000002, 0x00020002, 0x02020002, +- 0x00000202, 0x02000202, 0x00020202, 0x02020202, +- 0x01000000, 0x03000000, 0x01020000, 0x03020000, +- 0x01000200, 0x03000200, 0x01020200, 0x03020200, +- 0x01000002, 0x03000002, 0x01020002, 0x03020002, +- 0x01000202, 0x03000202, 0x01020202, 0x03020202, +- 0x00010000, 0x02010000, 0x00030000, 0x02030000, +- 0x00010200, 0x02010200, 0x00030200, 0x02030200, +- 0x00010002, 0x02010002, 0x00030002, 0x02030002, +- 0x00010202, 0x02010202, 0x00030202, 0x02030202, +- 0x01010000, 0x03010000, 0x01030000, 0x03030000, +- 0x01010200, 0x03010200, 0x01030200, 0x03030200, +- 0x01010002, 0x03010002, 0x01030002, 0x03030002, +- 0x01010202, 0x03010202, 0x01030202, 0x03030202, +- 0x00000100, 0x02000100, 0x00020100, 0x02020100, +- 0x00000300, 0x02000300, 0x00020300, 0x02020300, +- 0x00000102, 0x02000102, 0x00020102, 0x02020102, +- 0x00000302, 0x02000302, 0x00020302, 0x02020302, +- 0x01000100, 0x03000100, 0x01020100, 0x03020100, +- 0x01000300, 0x03000300, 0x01020300, 0x03020300, +- 0x01000102, 0x03000102, 0x01020102, 0x03020102, +- 0x01000302, 0x03000302, 0x01020302, 0x03020302, +- 0x00010100, 0x02010100, 0x00030100, 0x02030100, +- 0x00010300, 0x02010300, 0x00030300, 0x02030300, +- 0x00010102, 0x02010102, 0x00030102, 0x02030102, +- 0x00010302, 0x02010302, 0x00030302, 0x02030302, +- 0x01010100, 0x03010100, 0x01030100, 0x03030100, +- 0x01010300, 0x03010300, 0x01030300, 0x03030300, +- 0x01010102, 0x03010102, 0x01030102, 0x03030102, +- 0x01010302, 0x03010302, 0x01030302, 0x03030302, +- 0x00000001, 0x02000001, 0x00020001, 0x02020001, +- 0x00000201, 0x02000201, 0x00020201, 0x02020201, +- 0x00000003, 0x02000003, 0x00020003, 0x02020003, +- 0x00000203, 0x02000203, 0x00020203, 0x02020203, +- 0x01000001, 0x03000001, 0x01020001, 0x03020001, +- 0x01000201, 0x03000201, 0x01020201, 0x03020201, +- 0x01000003, 0x03000003, 0x01020003, 0x03020003, +- 0x01000203, 0x03000203, 0x01020203, 0x03020203, +- 0x00010001, 0x02010001, 0x00030001, 0x02030001, +- 0x00010201, 0x02010201, 0x00030201, 0x02030201, +- 0x00010003, 0x02010003, 0x00030003, 0x02030003, +- 0x00010203, 0x02010203, 0x00030203, 0x02030203, +- 0x01010001, 0x03010001, 0x01030001, 0x03030001, +- 0x01010201, 0x03010201, 0x01030201, 0x03030201, +- 0x01010003, 0x03010003, 0x01030003, 0x03030003, +- 0x01010203, 0x03010203, 0x01030203, 0x03030203, +- 0x00000101, 0x02000101, 0x00020101, 0x02020101, +- 0x00000301, 0x02000301, 0x00020301, 0x02020301, +- 0x00000103, 0x02000103, 0x00020103, 0x02020103, +- 0x00000303, 0x02000303, 0x00020303, 0x02020303, +- 0x01000101, 0x03000101, 0x01020101, 0x03020101, +- 0x01000301, 0x03000301, 0x01020301, 0x03020301, +- 0x01000103, 0x03000103, 0x01020103, 0x03020103, +- 0x01000303, 0x03000303, 0x01020303, 0x03020303, +- 0x00010101, 0x02010101, 0x00030101, 0x02030101, +- 0x00010301, 0x02010301, 0x00030301, 0x02030301, +- 0x00010103, 0x02010103, 0x00030103, 0x02030103, +- 0x00010303, 0x02010303, 0x00030303, 0x02030303, +- 0x01010101, 0x03010101, 0x01030101, 0x03030101, +- 0x01010301, 0x03010301, 0x01030301, 0x03030301, +- 0x01010103, 0x03010103, 0x01030103, 0x03030103, +- 0x01010303, 0x03010303, 0x01030303, 0x03030303 +-}; +- +- +-/* +- * The SP table is actually the S boxes and the P permutation +- * table combined. This table is actually reordered from the +- * spec, to match the order of key application we follow. +- */ +-const unsigned DES_INT32 des_SP_table[8][64] = { +- { +- 0x00100000, 0x02100001, 0x02000401, 0x00000000, /* 7 */ +- 0x00000400, 0x02000401, 0x00100401, 0x02100400, +- 0x02100401, 0x00100000, 0x00000000, 0x02000001, +- 0x00000001, 0x02000000, 0x02100001, 0x00000401, +- 0x02000400, 0x00100401, 0x00100001, 0x02000400, +- 0x02000001, 0x02100000, 0x02100400, 0x00100001, +- 0x02100000, 0x00000400, 0x00000401, 0x02100401, +- 0x00100400, 0x00000001, 0x02000000, 0x00100400, +- 0x02000000, 0x00100400, 0x00100000, 0x02000401, +- 0x02000401, 0x02100001, 0x02100001, 0x00000001, +- 0x00100001, 0x02000000, 0x02000400, 0x00100000, +- 0x02100400, 0x00000401, 0x00100401, 0x02100400, +- 0x00000401, 0x02000001, 0x02100401, 0x02100000, +- 0x00100400, 0x00000000, 0x00000001, 0x02100401, +- 0x00000000, 0x00100401, 0x02100000, 0x00000400, +- 0x02000001, 0x02000400, 0x00000400, 0x00100001, +- }, +- { +- 0x00808200, 0x00000000, 0x00008000, 0x00808202, /* 1 */ +- 0x00808002, 0x00008202, 0x00000002, 0x00008000, +- 0x00000200, 0x00808200, 0x00808202, 0x00000200, +- 0x00800202, 0x00808002, 0x00800000, 0x00000002, +- 0x00000202, 0x00800200, 0x00800200, 0x00008200, +- 0x00008200, 0x00808000, 0x00808000, 0x00800202, +- 0x00008002, 0x00800002, 0x00800002, 0x00008002, +- 0x00000000, 0x00000202, 0x00008202, 0x00800000, +- 0x00008000, 0x00808202, 0x00000002, 0x00808000, +- 0x00808200, 0x00800000, 0x00800000, 0x00000200, +- 0x00808002, 0x00008000, 0x00008200, 0x00800002, +- 0x00000200, 0x00000002, 0x00800202, 0x00008202, +- 0x00808202, 0x00008002, 0x00808000, 0x00800202, +- 0x00800002, 0x00000202, 0x00008202, 0x00808200, +- 0x00000202, 0x00800200, 0x00800200, 0x00000000, +- 0x00008002, 0x00008200, 0x00000000, 0x00808002, +- }, +- { +- 0x00000104, 0x04010100, 0x00000000, 0x04010004, /* 3 */ +- 0x04000100, 0x00000000, 0x00010104, 0x04000100, +- 0x00010004, 0x04000004, 0x04000004, 0x00010000, +- 0x04010104, 0x00010004, 0x04010000, 0x00000104, +- 0x04000000, 0x00000004, 0x04010100, 0x00000100, +- 0x00010100, 0x04010000, 0x04010004, 0x00010104, +- 0x04000104, 0x00010100, 0x00010000, 0x04000104, +- 0x00000004, 0x04010104, 0x00000100, 0x04000000, +- 0x04010100, 0x04000000, 0x00010004, 0x00000104, +- 0x00010000, 0x04010100, 0x04000100, 0x00000000, +- 0x00000100, 0x00010004, 0x04010104, 0x04000100, +- 0x04000004, 0x00000100, 0x00000000, 0x04010004, +- 0x04000104, 0x00010000, 0x04000000, 0x04010104, +- 0x00000004, 0x00010104, 0x00010100, 0x04000004, +- 0x04010000, 0x04000104, 0x00000104, 0x04010000, +- 0x00010104, 0x00000004, 0x04010004, 0x00010100, +- }, +- { +- 0x00000080, 0x01040080, 0x01040000, 0x21000080, /* 5 */ +- 0x00040000, 0x00000080, 0x20000000, 0x01040000, +- 0x20040080, 0x00040000, 0x01000080, 0x20040080, +- 0x21000080, 0x21040000, 0x00040080, 0x20000000, +- 0x01000000, 0x20040000, 0x20040000, 0x00000000, +- 0x20000080, 0x21040080, 0x21040080, 0x01000080, +- 0x21040000, 0x20000080, 0x00000000, 0x21000000, +- 0x01040080, 0x01000000, 0x21000000, 0x00040080, +- 0x00040000, 0x21000080, 0x00000080, 0x01000000, +- 0x20000000, 0x01040000, 0x21000080, 0x20040080, +- 0x01000080, 0x20000000, 0x21040000, 0x01040080, +- 0x20040080, 0x00000080, 0x01000000, 0x21040000, +- 0x21040080, 0x00040080, 0x21000000, 0x21040080, +- 0x01040000, 0x00000000, 0x20040000, 0x21000000, +- 0x00040080, 0x01000080, 0x20000080, 0x00040000, +- 0x00000000, 0x20040000, 0x01040080, 0x20000080, +- }, +- { +- 0x80401000, 0x80001040, 0x80001040, 0x00000040, /* 4 */ +- 0x00401040, 0x80400040, 0x80400000, 0x80001000, +- 0x00000000, 0x00401000, 0x00401000, 0x80401040, +- 0x80000040, 0x00000000, 0x00400040, 0x80400000, +- 0x80000000, 0x00001000, 0x00400000, 0x80401000, +- 0x00000040, 0x00400000, 0x80001000, 0x00001040, +- 0x80400040, 0x80000000, 0x00001040, 0x00400040, +- 0x00001000, 0x00401040, 0x80401040, 0x80000040, +- 0x00400040, 0x80400000, 0x00401000, 0x80401040, +- 0x80000040, 0x00000000, 0x00000000, 0x00401000, +- 0x00001040, 0x00400040, 0x80400040, 0x80000000, +- 0x80401000, 0x80001040, 0x80001040, 0x00000040, +- 0x80401040, 0x80000040, 0x80000000, 0x00001000, +- 0x80400000, 0x80001000, 0x00401040, 0x80400040, +- 0x80001000, 0x00001040, 0x00400000, 0x80401000, +- 0x00000040, 0x00400000, 0x00001000, 0x00401040, +- }, +- { +- 0x10000008, 0x10200000, 0x00002000, 0x10202008, /* 6 */ +- 0x10200000, 0x00000008, 0x10202008, 0x00200000, +- 0x10002000, 0x00202008, 0x00200000, 0x10000008, +- 0x00200008, 0x10002000, 0x10000000, 0x00002008, +- 0x00000000, 0x00200008, 0x10002008, 0x00002000, +- 0x00202000, 0x10002008, 0x00000008, 0x10200008, +- 0x10200008, 0x00000000, 0x00202008, 0x10202000, +- 0x00002008, 0x00202000, 0x10202000, 0x10000000, +- 0x10002000, 0x00000008, 0x10200008, 0x00202000, +- 0x10202008, 0x00200000, 0x00002008, 0x10000008, +- 0x00200000, 0x10002000, 0x10000000, 0x00002008, +- 0x10000008, 0x10202008, 0x00202000, 0x10200000, +- 0x00202008, 0x10202000, 0x00000000, 0x10200008, +- 0x00000008, 0x00002000, 0x10200000, 0x00202008, +- 0x00002000, 0x00200008, 0x10002008, 0x00000000, +- 0x10202000, 0x10000000, 0x00200008, 0x10002008, +- }, +- { +- 0x08000820, 0x00000800, 0x00020000, 0x08020820, /* 8 */ +- 0x08000000, 0x08000820, 0x00000020, 0x08000000, +- 0x00020020, 0x08020000, 0x08020820, 0x00020800, +- 0x08020800, 0x00020820, 0x00000800, 0x00000020, +- 0x08020000, 0x08000020, 0x08000800, 0x00000820, +- 0x00020800, 0x00020020, 0x08020020, 0x08020800, +- 0x00000820, 0x00000000, 0x00000000, 0x08020020, +- 0x08000020, 0x08000800, 0x00020820, 0x00020000, +- 0x00020820, 0x00020000, 0x08020800, 0x00000800, +- 0x00000020, 0x08020020, 0x00000800, 0x00020820, +- 0x08000800, 0x00000020, 0x08000020, 0x08020000, +- 0x08020020, 0x08000000, 0x00020000, 0x08000820, +- 0x00000000, 0x08020820, 0x00020020, 0x08000020, +- 0x08020000, 0x08000800, 0x08000820, 0x00000000, +- 0x08020820, 0x00020800, 0x00020800, 0x00000820, +- 0x00000820, 0x00020020, 0x08000000, 0x08020800, +- }, +- { +- 0x40084010, 0x40004000, 0x00004000, 0x00084010, /* 2 */ +- 0x00080000, 0x00000010, 0x40080010, 0x40004010, +- 0x40000010, 0x40084010, 0x40084000, 0x40000000, +- 0x40004000, 0x00080000, 0x00000010, 0x40080010, +- 0x00084000, 0x00080010, 0x40004010, 0x00000000, +- 0x40000000, 0x00004000, 0x00084010, 0x40080000, +- 0x00080010, 0x40000010, 0x00000000, 0x00084000, +- 0x00004010, 0x40084000, 0x40080000, 0x00004010, +- 0x00000000, 0x00084010, 0x40080010, 0x00080000, +- 0x40004010, 0x40080000, 0x40084000, 0x00004000, +- 0x40080000, 0x40004000, 0x00000010, 0x40084010, +- 0x00084010, 0x00000010, 0x00004000, 0x40000000, +- 0x00004010, 0x40084000, 0x00080000, 0x40000010, +- 0x00080010, 0x40004010, 0x40000010, 0x00080010, +- 0x00084000, 0x00000000, 0x40004000, 0x00004010, +- 0x40000000, 0x40080010, 0x40084010, 0x00084000 +- }, +-}; +diff --git a/src/lib/crypto/builtin/des/f_tables.h b/src/lib/crypto/builtin/des/f_tables.h +deleted file mode 100644 +index fc91b566c..000000000 +--- a/src/lib/crypto/builtin/des/f_tables.h ++++ /dev/null +@@ -1,285 +0,0 @@ +-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +-/* lib/crypto/builtin/des/f_tables.h */ +-/* +- * Copyright (C) 1990 by the Massachusetts Institute of Technology. +- * All rights reserved. +- * +- * Export of this software from the United States of America may +- * require a specific license from the United States Government. +- * It is the responsibility of any person or organization contemplating +- * export to obtain such a license before exporting. +- * +- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +- * distribute this software and its documentation for any purpose and +- * without fee is hereby granted, provided that the above copyright +- * notice appear in all copies and that both that copyright notice and +- * this permission notice appear in supporting documentation, and that +- * the name of M.I.T. not be used in advertising or publicity pertaining +- * to distribution of the software without specific, written prior +- * permission. Furthermore if you modify this software you must label +- * your software as modified software and not distribute it in such a +- * fashion that it might be confused with the original M.I.T. software. +- * M.I.T. makes no representations about the suitability of +- * this software for any purpose. It is provided "as is" without express +- * or implied warranty. +- */ +- +-/* +- * DES implementation donated by Dennis Ferguson +- */ +- +-/* +- * des_tables.h - declarations to import the DES tables, used internally +- * by some of the library routines. +- */ +-#ifndef __DES_TABLES_H__ +-#define __DES_TABLES_H__ /* nothing */ +- +-#include "k5-platform.h" +-/* +- * These may be declared const if you wish. Be sure to change the +- * declarations in des_tables.c as well. +- */ +-extern const unsigned DES_INT32 des_IP_table[256]; +-extern const unsigned DES_INT32 des_FP_table[256]; +-extern const unsigned DES_INT32 des_SP_table[8][64]; +- +-/* +- * Use standard shortforms to reference these to save typing +- */ +-#define IP des_IP_table +-#define FP des_FP_table +-#define SP des_SP_table +- +-#ifdef DEBUG +-#define DEB(foofraw) printf foofraw +-#else +-#define DEB(foofraw) /* nothing */ +-#endif +- +-/* +- * Code to do a DES round using the tables. Note that the E expansion +- * is easy to compute algorithmically, especially if done out-of-order. +- * Take a look at its form and compare it to everything involving temp +- * below. Since SP[0-7] don't have any bits in common set it is okay +- * to do the successive xor's. +- * +- * Note too that the SP table has been reordered to match the order of +- * the keys (if the original order of SP was 12345678, the reordered +- * table is 71354682). This is unnecessary, but was done since some +- * compilers seem to like you going through the matrix from beginning +- * to end. +- * +- * There is a difference in the best way to do this depending on whether +- * one is encrypting or decrypting. If encrypting we move forward through +- * the keys and hence should move forward through the table. If decrypting +- * we go back. Part of the need for this comes from trying to emulate +- * existing software which generates a single key schedule and uses it +- * both for encrypting and decrypting. Generating separate encryption +- * and decryption key schedules would allow one to use the same code +- * for both. +- * +- * left, right and temp should be unsigned DES_INT32 values. left and right +- * should be the high and low order parts of the cipher block at the +- * current stage of processing (this makes sense if you read the spec). +- * kp should be an unsigned DES_INT32 pointer which points at the current +- * set of subkeys in the key schedule. It is advanced to the next set +- * (i.e. by 8 bytes) when this is done. +- * +- * This occurs in the innermost loop of the DES function. The four +- * variables should really be in registers. +- * +- * When using this, the inner loop of the DES function might look like: +- * +- * for (i = 0; i < 8; i++) { +- * DES_SP_{EN,DE}CRYPT_ROUND(left, right, temp, kp); +- * DES_SP_{EN,DE}CRYPT_ROUND(right, left, temp, kp); +- * } +- * +- * Note the trick above. You are supposed to do 16 rounds, swapping +- * left and right at the end of each round. By doing two rounds at +- * a time and swapping left and right in the code we can avoid the +- * swaps altogether. +- */ +-#define DES_SP_ENCRYPT_ROUND(left, right, temp, kp) do { \ +- (temp) = (((right) >> 11) | ((right) << 21)) ^ *(kp)++; \ +- (left) ^= SP[0][((temp) >> 24) & 0x3f] \ +- | SP[1][((temp) >> 16) & 0x3f] \ +- | SP[2][((temp) >> 8) & 0x3f] \ +- | SP[3][((temp) ) & 0x3f]; \ +- (temp) = (((right) >> 23) | ((right) << 9)) ^ *(kp)++; \ +- (left) ^= SP[4][((temp) >> 24) & 0x3f] \ +- | SP[5][((temp) >> 16) & 0x3f] \ +- | SP[6][((temp) >> 8) & 0x3f] \ +- | SP[7][((temp) ) & 0x3f]; \ +- } while(0); +- +-#define DES_SP_DECRYPT_ROUND(left, right, temp, kp) do { \ +- (temp) = (((right) >> 23) | ((right) << 9)) ^ *(--(kp)); \ +- (left) ^= SP[7][((temp) ) & 0x3f] \ +- | SP[6][((temp) >> 8) & 0x3f] \ +- | SP[5][((temp) >> 16) & 0x3f] \ +- | SP[4][((temp) >> 24) & 0x3f]; \ +- (temp) = (((right) >> 11) | ((right) << 21)) ^ *(--(kp)); \ +- (left) ^= SP[3][((temp) ) & 0x3f] \ +- | SP[2][((temp) >> 8) & 0x3f] \ +- | SP[1][((temp) >> 16) & 0x3f] \ +- | SP[0][((temp) >> 24) & 0x3f]; \ +- } while (0); +- +-/* +- * Macros to help deal with the initial permutation table. Note +- * the IP table only deals with 32 bits at a time, allowing us to +- * collect the bits we need to deal with each half into an unsigned +- * DES_INT32. By carefully selecting how the bits are ordered we also +- * take advantages of symmetries in the table so that we can use a +- * single table to compute the permutation of all bytes. This sounds +- * complicated, but if you go through the process of designing the +- * table you'll find the symmetries fall right out. +- * +- * The follow macros compute the set of bits used to index the +- * table for produce the left and right permuted result. +- * +- * The inserted cast to unsigned DES_INT32 circumvents a bug in +- * the Macintosh MPW 3.2 C compiler which loses the unsignedness and +- * propagates the high-order bit in the shift. +- */ +-#define DES_IP_LEFT_BITS(left, right) \ +- ((((left) & 0x55555555) << 1) | ((right) & 0x55555555)) +-#define DES_IP_RIGHT_BITS(left, right) \ +- (((left) & 0xaaaaaaaa) | \ +- ( ( (unsigned DES_INT32) ((right) & 0xaaaaaaaa) ) >> 1)) +- +-/* +- * The following macro does an in-place initial permutation given +- * the current left and right parts of the block and a single +- * temporary. Use this more as a guide for rolling your own, though. +- * The best way to do the IP depends on the form of the data you +- * are dealing with. If you use this, though, try to make left, +- * right and temp unsigned DES_INT32s. +- */ +-#define DES_INITIAL_PERM(left, right, temp) do { \ +- (temp) = DES_IP_RIGHT_BITS((left), (right)); \ +- (right) = DES_IP_LEFT_BITS((left), (right)); \ +- (left) = IP[((right) >> 24) & 0xff] \ +- | (IP[((right) >> 16) & 0xff] << 1) \ +- | (IP[((right) >> 8) & 0xff] << 2) \ +- | (IP[(right) & 0xff] << 3); \ +- (right) = IP[((temp) >> 24) & 0xff] \ +- | (IP[((temp) >> 16) & 0xff] << 1) \ +- | (IP[((temp) >> 8) & 0xff] << 2) \ +- | (IP[(temp) & 0xff] << 3); \ +- } while(0); +- +-/* +- * Now the final permutation stuff. The same comments apply to +- * this as to the initial permutation, except that we use different +- * bits and shifts. +- * +- * The inserted cast to unsigned DES_INT32 circumvents a bug in +- * the Macintosh MPW 3.2 C compiler which loses the unsignedness and +- * propagates the high-order bit in the shift. +- */ +-#define DES_FP_LEFT_BITS(left, right) \ +- ((((left) & 0x0f0f0f0f) << 4) | ((right) & 0x0f0f0f0f)) +-#define DES_FP_RIGHT_BITS(left, right) \ +- (((left) & 0xf0f0f0f0) | \ +- ( ( (unsigned DES_INT32) ((right) & 0xf0f0f0f0) ) >> 4)) +- +- +-/* +- * Here is a sample final permutation. Note that there is a trick +- * here. DES requires swapping the left and right parts after the +- * last cipher round but before the final permutation. We do this +- * swapping internally, which is why left and right are confused +- * at the beginning. +- */ +-#define DES_FINAL_PERM(left, right, temp) do { \ +- (temp) = DES_FP_RIGHT_BITS((right), (left)); \ +- (right) = DES_FP_LEFT_BITS((right), (left)); \ +- (left) = (FP[((right) >> 24) & 0xff] << 6) \ +- | (FP[((right) >> 16) & 0xff] << 4) \ +- | (FP[((right) >> 8) & 0xff] << 2) \ +- | FP[(right) & 0xff]; \ +- (right) = (FP[((temp) >> 24) & 0xff] << 6) \ +- | (FP[((temp) >> 16) & 0xff] << 4) \ +- | (FP[((temp) >> 8) & 0xff] << 2) \ +- | FP[temp & 0xff]; \ +- } while(0); +- +- +-/* +- * Finally, as a sample of how all this might be held together, the +- * following two macros do in-place encryptions and decryptions. left +- * and right are two unsigned DES_INT32 variables which at the beginning +- * are expected to hold the clear (encrypted) block in host byte order +- * (left the high order four bytes, right the low order). At the end +- * they will contain the encrypted (clear) block. temp is an unsigned DES_INT32 +- * used as a temporary. kp is an unsigned DES_INT32 pointer pointing at +- * the start of the key schedule. All these should be in registers. +- * +- * You can probably do better than these by rewriting for particular +- * situations. These aren't bad, though. +- * +- * The DEB macros enable debugging when this code breaks (typically +- * when a buggy compiler breaks it), by printing the intermediate values +- * at each stage of the encryption, so that by comparing the output to +- * a known good machine, the location of the first error can be found. +- */ +-#define DES_DO_ENCRYPT_1(left, right, kp) \ +- do { \ +- int i; \ +- unsigned DES_INT32 temp1; \ +- DEB (("do_encrypt %8lX %8lX \n", left, right)); \ +- DES_INITIAL_PERM((left), (right), (temp1)); \ +- DEB ((" after IP %8lX %8lX\n", left, right)); \ +- for (i = 0; i < 8; i++) { \ +- DES_SP_ENCRYPT_ROUND((left), (right), (temp1), (kp)); \ +- DEB ((" round %2d %8lX %8lX \n", i*2, left, right)); \ +- DES_SP_ENCRYPT_ROUND((right), (left), (temp1), (kp)); \ +- DEB ((" round %2d %8lX %8lX \n", 1+i*2, left, right)); \ +- } \ +- DES_FINAL_PERM((left), (right), (temp1)); \ +- (kp) -= (2 * 16); \ +- DEB ((" after FP %8lX %8lX \n", left, right)); \ +- } while (0) +- +-#define DES_DO_DECRYPT_1(left, right, kp) \ +- do { \ +- int i; \ +- unsigned DES_INT32 temp2; \ +- DES_INITIAL_PERM((left), (right), (temp2)); \ +- (kp) += (2 * 16); \ +- for (i = 0; i < 8; i++) { \ +- DES_SP_DECRYPT_ROUND((left), (right), (temp2), (kp)); \ +- DES_SP_DECRYPT_ROUND((right), (left), (temp2), (kp)); \ +- } \ +- DES_FINAL_PERM((left), (right), (temp2)); \ +- } while (0) +- +-#if defined(CONFIG_SMALL) && !defined(CONFIG_SMALL_NO_CRYPTO) +-extern void krb5int_des_do_encrypt_2(unsigned DES_INT32 *l, +- unsigned DES_INT32 *r, +- const unsigned DES_INT32 *k); +-extern void krb5int_des_do_decrypt_2(unsigned DES_INT32 *l, +- unsigned DES_INT32 *r, +- const unsigned DES_INT32 *k); +-#define DES_DO_ENCRYPT(L,R,K) krb5int_des_do_encrypt_2(&(L), &(R), (K)) +-#define DES_DO_DECRYPT(L,R,K) krb5int_des_do_decrypt_2(&(L), &(R), (K)) +-#else +-#define DES_DO_ENCRYPT DES_DO_ENCRYPT_1 +-#define DES_DO_DECRYPT DES_DO_DECRYPT_1 +-#endif +- +-/* +- * These are handy dandy utility thingies for straightening out bytes. +- * Included here because they're used a couple of places. +- */ +-#define GET_HALF_BLOCK(lr, ip) ((lr) = load_32_be(ip), (ip) += 4) +-#define PUT_HALF_BLOCK(lr, op) (store_32_be(lr, op), (op) += 4) +- +-/* Shorthand that we'll need in several places, for creating values that +- really can hold 32 bits regardless of the prevailing int size. */ +-#define FF_UINT32 ((unsigned DES_INT32) 0xFF) +- +-#endif /* __DES_TABLES_H__ */ +diff --git a/src/lib/crypto/builtin/des/key_sched.c b/src/lib/crypto/builtin/des/key_sched.c +deleted file mode 100644 +index 87f02b6a9..000000000 +--- a/src/lib/crypto/builtin/des/key_sched.c ++++ /dev/null +@@ -1,62 +0,0 @@ +-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +-/* lib/crypto/builtin/des/key_sched.c */ +-/* +- * Copyright 1985, 1986, 1987, 1988, 1990 by the Massachusetts Institute +- * of Technology. +- * All Rights Reserved. +- * +- * Export of this software from the United States of America may +- * require a specific license from the United States Government. +- * It is the responsibility of any person or organization contemplating +- * export to obtain such a license before exporting. +- * +- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +- * distribute this software and its documentation for any purpose and +- * without fee is hereby granted, provided that the above copyright +- * notice appear in all copies and that both that copyright notice and +- * this permission notice appear in supporting documentation, and that +- * the name of M.I.T. not be used in advertising or publicity pertaining +- * to distribution of the software without specific, written prior +- * permission. Furthermore if you modify this software you must label +- * your software as modified software and not distribute it in such a +- * fashion that it might be confused with the original M.I.T. software. +- * M.I.T. makes no representations about the suitability of +- * this software for any purpose. It is provided "as is" without express +- * or implied warranty. +- */ +- +-/* +- * This routine computes the DES key schedule given a key. The +- * permutations and shifts have been done at compile time, resulting +- * in a direct one-step mapping from the input key to the key +- * schedule. +- * +- * Also checks parity and weak keys. +- * +- * Watch out for the subscripts -- most effectively start at 1 instead +- * of at zero. Maybe some bugs in that area. +- * +- * In case the user wants to cache the computed key schedule, it is +- * passed as an arg. Also implies that caller has explicit control +- * over zeroing both the key schedule and the key. +- * +- * Originally written 6/85 by Steve Miller, MIT Project Athena. +- */ +- +-#include "k5-int.h" +-#include "des_int.h" +- +-int +-mit_des_key_sched(mit_des_cblock k, mit_des_key_schedule schedule) +-{ +- mit_des_make_key_sched(k,schedule); +- +- if (!mit_des_check_key_parity(k)) /* bad parity --> return -1 */ +- return(-1); +- +- if (mit_des_is_weak_key(k)) +- return(-2); +- +- /* if key was good, return 0 */ +- return 0; +-} +diff --git a/src/lib/crypto/builtin/des/keytest.data b/src/lib/crypto/builtin/des/keytest.data +deleted file mode 100644 +index 7ff34eedc..000000000 +--- a/src/lib/crypto/builtin/des/keytest.data ++++ /dev/null +@@ -1,171 +0,0 @@ +-0101010101010101 95F8A5E5DD31D900 8000000000000000 +-0101010101010101 DD7F121CA5015619 4000000000000000 +-0101010101010101 2E8653104F3834EA 2000000000000000 +-0101010101010101 4BD388FF6CD81D4F 1000000000000000 +-0101010101010101 20B9E767B2FB1456 0800000000000000 +-0101010101010101 55579380D77138EF 0400000000000000 +-0101010101010101 6CC5DEFAAF04512F 0200000000000000 +-0101010101010101 0D9F279BA5D87260 0100000000000000 +-0101010101010101 D9031B0271BD5A0A 0080000000000000 +-0101010101010101 424250B37C3DD951 0040000000000000 +-0101010101010101 B8061B7ECD9A21E5 0020000000000000 +-0101010101010101 F15D0F286B65BD28 0010000000000000 +-0101010101010101 ADD0CC8D6E5DEBA1 0008000000000000 +-0101010101010101 E6D5F82752AD63D1 0004000000000000 +-0101010101010101 ECBFE3BD3F591A5E 0002000000000000 +-0101010101010101 F356834379D165CD 0001000000000000 +-0101010101010101 2B9F982F20037FA9 0000800000000000 +-0101010101010101 889DE068A16F0BE6 0000400000000000 +-0101010101010101 E19E275D846A1298 0000200000000000 +-0101010101010101 329A8ED523D71AEC 0000100000000000 +-0101010101010101 E7FCE22557D23C97 0000080000000000 +-0101010101010101 12A9F5817FF2D65D 0000040000000000 +-0101010101010101 A484C3AD38DC9C19 0000020000000000 +-0101010101010101 FBE00A8A1EF8AD72 0000010000000000 +-0101010101010101 750D079407521363 0000008000000000 +-0101010101010101 64FEED9C724C2FAF 0000004000000000 +-0101010101010101 F02B263B328E2B60 0000002000000000 +-0101010101010101 9D64555A9A10B852 0000001000000000 +-0101010101010101 D106FF0BED5255D7 0000000800000000 +-0101010101010101 E1652C6B138C64A5 0000000400000000 +-0101010101010101 E428581186EC8F46 0000000200000000 +-0101010101010101 AEB5F5EDE22D1A36 0000000100000000 +-0101010101010101 E943D7568AEC0C5C 0000000080000000 +-0101010101010101 DF98C8276F54B04B 0000000040000000 +-0101010101010101 B160E4680F6C696F 0000000020000000 +-0101010101010101 FA0752B07D9C4AB8 0000000010000000 +-0101010101010101 CA3A2B036DBC8502 0000000008000000 +-0101010101010101 5E0905517BB59BCF 0000000004000000 +-0101010101010101 814EEB3B91D90726 0000000002000000 +-0101010101010101 4D49DB1532919C9F 0000000001000000 +-0101010101010101 25EB5FC3F8CF0621 0000000000800000 +-0101010101010101 AB6A20C0620D1C6F 0000000000400000 +-0101010101010101 79E90DBC98F92CCA 0000000000200000 +-0101010101010101 866ECEDD8072BB0E 0000000000100000 +-0101010101010101 8B54536F2F3E64A8 0000000000080000 +-0101010101010101 EA51D3975595B86B 0000000000040000 +-0101010101010101 CAFFC6AC4542DE31 0000000000020000 +-0101010101010101 8DD45A2DDF90796C 0000000000010000 +-0101010101010101 1029D55E880EC2D0 0000000000008000 +-0101010101010101 5D86CB23639DBEA9 0000000000004000 +-0101010101010101 1D1CA853AE7C0C5F 0000000000002000 +-0101010101010101 CE332329248F3228 0000000000001000 +-0101010101010101 8405D1ABE24FB942 0000000000000800 +-0101010101010101 E643D78090CA4207 0000000000000400 +-0101010101010101 48221B9937748A23 0000000000000200 +-0101010101010101 DD7C0BBD61FAFD54 0000000000000100 +-0101010101010101 2FBC291A570DB5C4 0000000000000080 +-0101010101010101 E07C30D7E4E26E12 0000000000000040 +-0101010101010101 0953E2258E8E90A1 0000000000000020 +-0101010101010101 5B711BC4CEEBF2EE 0000000000000010 +-0101010101010101 CC083F1E6D9E85F6 0000000000000008 +-0101010101010101 D2FD8867D50D2DFE 0000000000000004 +-0101010101010101 06E7EA22CE92708F 0000000000000002 +-0101010101010101 166B40B44ABA4BD6 0000000000000001 +-8001010101010101 0000000000000000 95A8D72813DAA94D +-4001010101010101 0000000000000000 0EEC1487DD8C26D5 +-2001010101010101 0000000000000000 7AD16FFB79C45926 +-1001010101010101 0000000000000000 D3746294CA6A6CF3 +-0801010101010101 0000000000000000 809F5F873C1FD761 +-0401010101010101 0000000000000000 C02FAFFEC989D1FC +-0201010101010101 0000000000000000 4615AA1D33E72F10 +-0180010101010101 0000000000000000 2055123350C00858 +-0140010101010101 0000000000000000 DF3B99D6577397C8 +-0120010101010101 0000000000000000 31FE17369B5288C9 +-0110010101010101 0000000000000000 DFDD3CC64DAE1642 +-0108010101010101 0000000000000000 178C83CE2B399D94 +-0104010101010101 0000000000000000 50F636324A9B7F80 +-0102010101010101 0000000000000000 A8468EE3BC18F06D +-0101800101010101 0000000000000000 A2DC9E92FD3CDE92 +-0101400101010101 0000000000000000 CAC09F797D031287 +-0101200101010101 0000000000000000 90BA680B22AEB525 +-0101100101010101 0000000000000000 CE7A24F350E280B6 +-0101080101010101 0000000000000000 882BFF0AA01A0B87 +-0101040101010101 0000000000000000 25610288924511C2 +-0101020101010101 0000000000000000 C71516C29C75D170 +-0101018001010101 0000000000000000 5199C29A52C9F059 +-0101014001010101 0000000000000000 C22F0A294A71F29F +-0101012001010101 0000000000000000 EE371483714C02EA +-0101011001010101 0000000000000000 A81FBD448F9E522F +-0101010801010101 0000000000000000 4F644C92E192DFED +-0101010401010101 0000000000000000 1AFA9A66A6DF92AE +-0101010201010101 0000000000000000 B3C1CC715CB879D8 +-0101010180010101 0000000000000000 19D032E64AB0BD8B +-0101010140010101 0000000000000000 3CFAA7A7DC8720DC +-0101010120010101 0000000000000000 B7265F7F447AC6F3 +-0101010110010101 0000000000000000 9DB73B3C0D163F54 +-0101010108010101 0000000000000000 8181B65BABF4A975 +-0101010104010101 0000000000000000 93C9B64042EAA240 +-0101010102010101 0000000000000000 5570530829705592 +-0101010101800101 0000000000000000 8638809E878787A0 +-0101010101400101 0000000000000000 41B9A79AF79AC208 +-0101010101200101 0000000000000000 7A9BE42F2009A892 +-0101010101100101 0000000000000000 29038D56BA6D2745 +-0101010101080101 0000000000000000 5495C6ABF1E5DF51 +-0101010101040101 0000000000000000 AE13DBD561488933 +-0101010101020101 0000000000000000 024D1FFA8904E389 +-0101010101018001 0000000000000000 D1399712F99BF02E +-0101010101014001 0000000000000000 14C1D7C1CFFEC79E +-0101010101012001 0000000000000000 1DE5279DAE3BED6F +-0101010101011001 0000000000000000 E941A33F85501303 +-0101010101010801 0000000000000000 DA99DBBC9A03F379 +-0101010101010401 0000000000000000 B7FC92F91D8E92E9 +-0101010101010201 0000000000000000 AE8E5CAA3CA04E85 +-0101010101010180 0000000000000000 9CC62DF43B6EED74 +-0101010101010140 0000000000000000 D863DBB5C59A91A0 +-0101010101010120 0000000000000000 A1AB2190545B91D7 +-0101010101010110 0000000000000000 0875041E64C570F7 +-0101010101010108 0000000000000000 5A594528BEBEF1CC +-0101010101010104 0000000000000000 FCDB3291DE21F0C0 +-0101010101010102 0000000000000000 869EFD7F9F265A09 +-1046913489980131 0000000000000000 88D55E54F54C97B4 +-1007103489988020 0000000000000000 0C0CC00C83EA48FD +-10071034C8980120 0000000000000000 83BC8EF3A6570183 +-1046103489988020 0000000000000000 DF725DCAD94EA2E9 +-1086911519190101 0000000000000000 E652B53B550BE8B0 +-1086911519580101 0000000000000000 AF527120C485CBB0 +-5107B01519580101 0000000000000000 0F04CE393DB926D5 +-1007B01519190101 0000000000000000 C9F00FFC74079067 +-3107915498080101 0000000000000000 7CFD82A593252B4E +-3107919498080101 0000000000000000 CB49A2F9E91363E3 +-10079115B9080140 0000000000000000 00B588BE70D23F56 +-3107911598080140 0000000000000000 406A9A6AB43399AE +-1007D01589980101 0000000000000000 6CB773611DCA9ADA +-9107911589980101 0000000000000000 67FD21C17DBB5D70 +-9107D01589190101 0000000000000000 9592CB4110430787 +-1007D01598980120 0000000000000000 A6B7FF68A318DDD3 +-1007940498190101 0000000000000000 4D102196C914CA16 +-0107910491190401 0000000000000000 2DFA9F4573594965 +-0107910491190101 0000000000000000 B46604816C0E0774 +-0107940491190401 0000000000000000 6E7E6221A4F34E87 +-19079210981A0101 0000000000000000 AA85E74643233199 +-1007911998190801 0000000000000000 2E5A19DB4D1962D6 +-10079119981A0801 0000000000000000 23A866A809D30894 +-1007921098190101 0000000000000000 D812D961F017D320 +-100791159819010B 0000000000000000 055605816E58608F +-1004801598190101 0000000000000000 ABD88E8B1B7716F1 +-1004801598190102 0000000000000000 537AC95BE69DA1E1 +-1004801598190108 0000000000000000 AED0F6AE3C25CDD8 +-1002911598100104 0000000000000000 B3E35A5EE53E7B8D +-1002911598190104 0000000000000000 61C79C71921A2EF8 +-1002911598100201 0000000000000000 E2F5728F0995013C +-1002911698100101 0000000000000000 1AEAC39A61F0A464 +-7CA110454A1A6E57 01A1D6D039776742 690F5B0D9A26939B +-0131D9619DC1376E 5CD54CA83DEF57DA 7A389D10354BD271 +-07A1133E4A0B2686 0248D43806F67172 868EBB51CAB4599A +-3849674C2602319E 51454B582DDF440A 7178876E01F19B2A +-04B915BA43FEB5B6 42FD443059577FA2 AF37FB421F8C4095 +-0113B970FD34F2CE 059B5E0851CF143A 86A560F10EC6D85B +-0170F175468FB5E6 0756D8E0774761D2 0CD3DA020021DC09 +-43297FAD38E373FE 762514B829BF486A EA676B2CB7DB2B7A +-07A7137045DA2A16 3BDD119049372802 DFD64A815CAF1A0F +-04689104C2FD3B2F 26955F6835AF609A 5C513C9C4886C088 +-37D06BB516CB7546 164D5E404F275232 0A2AEEAE3FF4AB77 +-1F08260D1AC2465E 6B056E18759F5CCA EF1BF03E5DFA575A +-584023641ABA6176 004BD6EF09176062 88BF0DB6D70DEE56 +-025816164629B007 480D39006EE762F2 A1F9915541020B56 +-49793EBC79B3258F 437540C8698F3CFA 6FBF1CAFCFFD0556 +-4FB05E1515AB73A7 072D43A077075292 2F22E49BAB7CA1AC +-49E95D6D4CA229BF 02FE55778117F12A 5A6B612CC26CCE4A +-018310DC409B26D6 1D9D5C5018F728C2 5F4C038ED12B2E41 +-1C587F1C13924FEF 305532286D6F295A 63FAC0D034D9F793 +diff --git a/src/lib/crypto/builtin/des/t_verify.c b/src/lib/crypto/builtin/des/t_verify.c +deleted file mode 100644 +index f4332f5c0..000000000 +--- a/src/lib/crypto/builtin/des/t_verify.c ++++ /dev/null +@@ -1,395 +0,0 @@ +-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +-/* lib/crypto/builtin/des/t_verify.c */ +-/* +- * Copyright 1988, 1990 by the Massachusetts Institute of Technology. +- * All Rights Reserved. +- * +- * Export of this software from the United States of America may +- * require a specific license from the United States Government. +- * It is the responsibility of any person or organization contemplating +- * export to obtain such a license before exporting. +- * +- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +- * distribute this software and its documentation for any purpose and +- * without fee is hereby granted, provided that the above copyright +- * notice appear in all copies and that both that copyright notice and +- * this permission notice appear in supporting documentation, and that +- * the name of M.I.T. not be used in advertising or publicity pertaining +- * to distribution of the software without specific, written prior +- * permission. Furthermore if you modify this software you must label +- * your software as modified software and not distribute it in such a +- * fashion that it might be confused with the original M.I.T. software. +- * M.I.T. makes no representations about the suitability of +- * this software for any purpose. It is provided "as is" without express +- * or implied warranty. +- */ +-/* +- * Copyright (C) 1998 by the FundsXpress, INC. +- * +- * All rights reserved. +- * +- * Export of this software from the United States of America may require +- * a specific license from the United States Government. It is the +- * responsibility of any person or organization contemplating export to +- * obtain such a license before exporting. +- * +- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +- * distribute this software and its documentation for any purpose and +- * without fee is hereby granted, provided that the above copyright +- * notice appear in all copies and that both that copyright notice and +- * this permission notice appear in supporting documentation, and that +- * the name of FundsXpress. not be used in advertising or publicity pertaining +- * to distribution of the software without specific, written prior +- * permission. FundsXpress makes no representations about the suitability of +- * this software for any purpose. It is provided "as is" without express +- * or implied warranty. +- * +- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR +- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. +- */ +- +-/* +- * +- * Program to test the correctness of the DES library +- * implementation. +- * +- * exit returns 0 ==> success +- * -1 ==> error +- */ +- +-#include "k5-int.h" +-#include "des_int.h" +-#include +-#include "com_err.h" +- +-static void do_encrypt(unsigned char *, unsigned char *); +-static void do_decrypt(unsigned char *, unsigned char *); +- +-char *progname; +-int nflag = 2; +-int vflag; +-int mflag; +-int zflag; +-int pid; +-int mit_des_debug; +- +-unsigned char cipher_text[64]; +-unsigned char clear_text[64] = "Now is the time for all " ; +-unsigned char clear_text2[64] = "7654321 Now is the time for "; +-unsigned char clear_text3[64] = {2,0,0,0, 1,0,0,0}; +-unsigned char output[64]; +-unsigned char zero_text[8] = {0x0,0,0,0,0,0,0,0}; +-unsigned char msb_text[8] = {0x0,0,0,0, 0,0,0,0x40}; /* to ANSI MSB */ +-unsigned char *input; +- +-/* 0x0123456789abcdef */ +-unsigned char default_key[8] = { +- 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef +-}; +-unsigned char key2[8] = { 0x08,0x19,0x2a,0x3b,0x4c,0x5d,0x6e,0x7f }; +-unsigned char key3[8] = { 0x80,1,1,1,1,1,1,1 }; +-mit_des_cblock s_key; +-unsigned char default_ivec[8] = { +- 0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef +-}; +-unsigned char *ivec; +-unsigned char zero_key[8] = {1,1,1,1,1,1,1,1}; /* just parity bits */ +- +-unsigned char cipher1[8] = { +- 0x25,0xdd,0xac,0x3e,0x96,0x17,0x64,0x67 +-}; +-unsigned char cipher2[8] = { +- 0x3f,0xa4,0x0e,0x8a,0x98,0x4d,0x48,0x15 +-}; +-unsigned char cipher3[64] = { +- 0xe5,0xc7,0xcd,0xde,0x87,0x2b,0xf2,0x7c, +- 0x43,0xe9,0x34,0x00,0x8c,0x38,0x9c,0x0f, +- 0x68,0x37,0x88,0x49,0x9a,0x7c,0x05,0xf6 +-}; +-unsigned char checksum[8] = { +- 0x58,0xd2,0xe7,0x7e,0x86,0x06,0x27,0x33 +-}; +- +-unsigned char zresult[8] = { +- 0x8c, 0xa6, 0x4d, 0xe9, 0xc1, 0xb1, 0x23, 0xa7 +-}; +- +-unsigned char mresult[8] = { +- 0xa3, 0x80, 0xe0, 0x2a, 0x6b, 0xe5, 0x46, 0x96 +-}; +- +- +-/* +- * Can also add : +- * plaintext = 0, key = 0, cipher = 0x8ca64de9c1b123a7 (or is it a 1?) +- */ +- +-mit_des_key_schedule sched; +- +-int +-main(argc,argv) +- int argc; +- char *argv[]; +-{ +- /* Local Declarations */ +- size_t in_length; +- int retval; +- int i, j; +- +-#ifdef WINDOWS +- /* Set screen window buffer to infinite size -- MS default is tiny. */ +- _wsetscreenbuf (fileno (stdout), _WINBUFINF); +-#endif +- progname=argv[0]; /* salt away invoking program */ +- +- while (--argc > 0 && (*++argv)[0] == '-') +- for (i=1; argv[0][i] != '\0'; i++) { +- switch (argv[0][i]) { +- +- /* debug flag */ +- case 'd': +- mit_des_debug=3; +- continue; +- +- case 'z': +- zflag = 1; +- continue; +- +- case 'm': +- mflag = 1; +- continue; +- +- default: +- printf("%s: illegal flag \"%c\" ", +- progname,argv[0][i]); +- exit(1); +- } +- }; +- +- if (argc) { +- fprintf(stderr, "Usage: %s [-dmz]\n", progname); +- exit(1); +- } +- +- /* do some initialisation */ +- +- /* use known input and key */ +- +- /* ECB zero text zero key */ +- if (zflag) { +- input = zero_text; +- mit_des_key_sched(zero_key, sched); +- printf("plaintext = key = 0, cipher = 0x8ca64de9c1b123a7\n"); +- do_encrypt(input,cipher_text); +- printf("\tcipher = (low to high bytes)\n\t\t"); +- for (j = 0; j<=7; j++) +- printf("%02x ",cipher_text[j]); +- printf("\n"); +- do_decrypt(output,cipher_text); +- if ( memcmp((char *)cipher_text, (char *)zresult, 8) ) { +- printf("verify: error in zero key test\n"); +- exit(-1); +- } +- +- exit(0); +- } +- +- if (mflag) { +- input = msb_text; +- mit_des_key_sched(key3, sched); +- printf("plaintext = 0x00 00 00 00 00 00 00 40, "); +- printf("key = 0x80 01 01 01 01 01 01 01\n"); +- printf(" cipher = 0xa380e02a6be54696\n"); +- do_encrypt(input,cipher_text); +- printf("\tcipher = (low to high bytes)\n\t\t"); +- for (j = 0; j<=7; j++) { +- printf("%02x ",cipher_text[j]); +- } +- printf("\n"); +- do_decrypt(output,cipher_text); +- if ( memcmp((char *)cipher_text, (char *)mresult, 8) ) { +- printf("verify: error in msb test\n"); +- exit(-1); +- } +- exit(0); +- } +- +- /* ECB mode Davies and Price */ +- { +- input = zero_text; +- mit_des_key_sched(key2, sched); +- printf("Examples per FIPS publication 81, keys ivs and cipher\n"); +- printf("in hex. These are the correct answers, see below for\n"); +- printf("the actual answers.\n\n"); +- printf("Examples per Davies and Price.\n\n"); +- printf("EXAMPLE ECB\tkey = 08192a3b4c5d6e7f\n"); +- printf("\tclear = 0\n"); +- printf("\tcipher = 25 dd ac 3e 96 17 64 67\n"); +- printf("ACTUAL ECB\n"); +- printf("\tclear \"%s\"\n", input); +- do_encrypt(input,cipher_text); +- printf("\tcipher = (low to high bytes)\n\t\t"); +- for (j = 0; j<=7; j++) +- printf("%02x ",cipher_text[j]); +- printf("\n\n"); +- do_decrypt(output,cipher_text); +- if ( memcmp((char *)cipher_text, (char *)cipher1, 8) ) { +- printf("verify: error in ECB encryption\n"); +- exit(-1); +- } +- else +- printf("verify: ECB encryption is correct\n\n"); +- } +- +- /* ECB mode */ +- { +- mit_des_key_sched(default_key, sched); +- input = clear_text; +- ivec = default_ivec; +- printf("EXAMPLE ECB\tkey = 0123456789abcdef\n"); +- printf("\tclear = \"Now is the time for all \"\n"); +- printf("\tcipher = 3f a4 0e 8a 98 4d 48 15 ...\n"); +- printf("ACTUAL ECB\n\tclear \"%s\"",input); +- do_encrypt(input,cipher_text); +- printf("\n\tcipher = (low to high bytes)\n\t\t"); +- for (j = 0; j<=7; j++) { +- printf("%02x ",cipher_text[j]); +- } +- printf("\n\n"); +- do_decrypt(output,cipher_text); +- if ( memcmp((char *)cipher_text, (char *)cipher2, 8) ) { +- printf("verify: error in ECB encryption\n"); +- exit(-1); +- } +- else +- printf("verify: ECB encryption is correct\n\n"); +- } +- +- /* CBC mode */ +- printf("EXAMPLE CBC\tkey = 0123456789abcdef"); +- printf("\tiv = 1234567890abcdef\n"); +- printf("\tclear = \"Now is the time for all \"\n"); +- printf("\tcipher =\te5 c7 cd de 87 2b f2 7c\n"); +- printf("\t\t\t43 e9 34 00 8c 38 9c 0f\n"); +- printf("\t\t\t68 37 88 49 9a 7c 05 f6\n"); +- +- printf("ACTUAL CBC\n\tclear \"%s\"\n",input); +- in_length = strlen((char *)input); +- if ((retval = mit_des_cbc_encrypt((const mit_des_cblock *) input, +- (mit_des_cblock *) cipher_text, +- (size_t) in_length, +- sched, +- ivec, +- MIT_DES_ENCRYPT))) { +- com_err("des verify", retval, "can't encrypt"); +- exit(-1); +- } +- printf("\tciphertext = (low to high bytes)\n"); +- for (i = 0; i <= 2; i++) { +- printf("\t\t"); +- for (j = 0; j <= 7; j++) { +- printf("%02x ",cipher_text[i*8+j]); +- } +- printf("\n"); +- } +- if ((retval = mit_des_cbc_encrypt((const mit_des_cblock *) cipher_text, +- (mit_des_cblock *) clear_text, +- (size_t) in_length, +- sched, +- ivec, +- MIT_DES_DECRYPT))) { +- com_err("des verify", retval, "can't decrypt"); +- exit(-1); +- } +- printf("\tdecrypted clear_text = \"%s\"\n",clear_text); +- +- if ( memcmp((char *)cipher_text, (char *)cipher3, in_length) ) { +- printf("verify: error in CBC encryption\n"); +- exit(-1); +- } +- else +- printf("verify: CBC encryption is correct\n\n"); +- +- printf("EXAMPLE CBC checksum"); +- printf("\tkey = 0123456789abcdef\tiv = 1234567890abcdef\n"); +- printf("\tclear =\t\t\"7654321 Now is the time for \"\n"); +- printf("\tchecksum\t58 d2 e7 7e 86 06 27 33, "); +- printf("or some part thereof\n"); +- input = clear_text2; +- mit_des_cbc_cksum(input,cipher_text, strlen((char *)input), +- sched,ivec); +- printf("ACTUAL CBC checksum\n"); +- printf("\t\tencrypted cksum = (low to high bytes)\n\t\t"); +- for (j = 0; j<=7; j++) +- printf("%02x ",cipher_text[j]); +- printf("\n\n"); +- if ( memcmp((char *)cipher_text, (char *)checksum, 8) ) { +- printf("verify: error in CBC cheksum\n"); +- exit(-1); +- } +- else +- printf("verify: CBC checksum is correct\n\n"); +- +- exit(0); +-} +- +-static void +-do_encrypt(in,out) +- unsigned char *in; +- unsigned char *out; +-{ +- int i, j; +- for (i =1; i<=nflag; i++) { +- mit_des_cbc_encrypt((const mit_des_cblock *)in, +- (mit_des_cblock *)out, +- 8, +- sched, +- zero_text, +- MIT_DES_ENCRYPT); +- if (mit_des_debug) { +- printf("\nclear %s\n",in); +- for (j = 0; j<=7; j++) +- printf("%02X ",in[j] & 0xff); +- printf("\tcipher "); +- for (j = 0; j<=7; j++) +- printf("%02X ",out[j] & 0xff); +- } +- } +-} +- +-static void +-do_decrypt(in,out) +- unsigned char *out; +- unsigned char *in; +- /* try to invert it */ +-{ +- int i, j; +- for (i =1; i<=nflag; i++) { +- mit_des_cbc_encrypt((const mit_des_cblock *)out, +- (mit_des_cblock *)in, +- 8, +- sched, +- zero_text, +- MIT_DES_DECRYPT); +- if (mit_des_debug) { +- printf("clear %s\n",in); +- for (j = 0; j<=7; j++) +- printf("%02X ",in[j] & 0xff); +- printf("\tcipher "); +- for (j = 0; j<=7; j++) +- printf("%02X ",out[j] & 0xff); +- } +- } +-} +- +-/* +- * Fake out the DES library, for the purposes of testing. +- */ +- +-int +-mit_des_is_weak_key(key) +- mit_des_cblock key; +-{ +- return 0; /* fake it out for testing */ +-} +diff --git a/src/lib/crypto/builtin/des/weak_key.c b/src/lib/crypto/builtin/des/weak_key.c +deleted file mode 100644 +index eb41b267d..000000000 +--- a/src/lib/crypto/builtin/des/weak_key.c ++++ /dev/null +@@ -1,86 +0,0 @@ +-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +-/* lib/crypto/builtin/des/weak_key.c */ +-/* +- * Copyright 1989,1990 by the Massachusetts Institute of Technology. +- * All Rights Reserved. +- * +- * Export of this software from the United States of America may +- * require a specific license from the United States Government. +- * It is the responsibility of any person or organization contemplating +- * export to obtain such a license before exporting. +- * +- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +- * distribute this software and its documentation for any purpose and +- * without fee is hereby granted, provided that the above copyright +- * notice appear in all copies and that both that copyright notice and +- * this permission notice appear in supporting documentation, and that +- * the name of M.I.T. not be used in advertising or publicity pertaining +- * to distribution of the software without specific, written prior +- * permission. Furthermore if you modify this software you must label +- * your software as modified software and not distribute it in such a +- * fashion that it might be confused with the original M.I.T. software. +- * M.I.T. makes no representations about the suitability of +- * this software for any purpose. It is provided "as is" without express +- * or implied warranty. +- */ +- +-/* +- * Under U.S. law, this software may not be exported outside the US +- * without license from the U.S. Commerce department. +- * +- * These routines form the library interface to the DES facilities. +- * +- * Originally written 8/85 by Steve Miller, MIT Project Athena. +- */ +- +-#include "k5-int.h" +-#include "des_int.h" +- +-/* +- * The following are the weak DES keys: +- */ +-static const mit_des_cblock weak[16] = { +- /* weak keys */ +- {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01}, +- {0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe}, +- {0x1f,0x1f,0x1f,0x1f,0x0e,0x0e,0x0e,0x0e}, +- {0xe0,0xe0,0xe0,0xe0,0xf1,0xf1,0xf1,0xf1}, +- +- /* semi-weak */ +- {0x01,0xfe,0x01,0xfe,0x01,0xfe,0x01,0xfe}, +- {0xfe,0x01,0xfe,0x01,0xfe,0x01,0xfe,0x01}, +- +- {0x1f,0xe0,0x1f,0xe0,0x0e,0xf1,0x0e,0xf1}, +- {0xe0,0x1f,0xe0,0x1f,0xf1,0x0e,0xf1,0x0e}, +- +- {0x01,0xe0,0x01,0xe0,0x01,0xf1,0x01,0xf1}, +- {0xe0,0x01,0xe0,0x01,0xf1,0x01,0xf1,0x01}, +- +- {0x1f,0xfe,0x1f,0xfe,0x0e,0xfe,0x0e,0xfe}, +- {0xfe,0x1f,0xfe,0x1f,0xfe,0x0e,0xfe,0x0e}, +- +- {0x01,0x1f,0x01,0x1f,0x01,0x0e,0x01,0x0e}, +- {0x1f,0x01,0x1f,0x01,0x0e,0x01,0x0e,0x01}, +- +- {0xe0,0xfe,0xe0,0xfe,0xf1,0xfe,0xf1,0xfe}, +- {0xfe,0xe0,0xfe,0xe0,0xfe,0xf1,0xfe,0xf1} +-}; +- +-/* +- * mit_des_is_weak_key: returns true iff key is a [semi-]weak des key. +- * +- * Requires: key has correct odd parity. +- */ +-int +-mit_des_is_weak_key(mit_des_cblock key) +-{ +- unsigned int i; +- const mit_des_cblock *weak_p = weak; +- +- for (i = 0; i < (sizeof(weak)/sizeof(mit_des_cblock)); i++) { +- if (!memcmp(weak_p++,key,sizeof(mit_des_cblock))) +- return 1; +- } +- +- return 0; +-} +diff --git a/src/lib/crypto/builtin/enc_provider/Makefile.in b/src/lib/crypto/builtin/enc_provider/Makefile.in +index 3459e1d0e..af6276b96 100644 +--- a/src/lib/crypto/builtin/enc_provider/Makefile.in ++++ b/src/lib/crypto/builtin/enc_provider/Makefile.in +@@ -1,7 +1,6 @@ + mydir=lib$(S)crypto$(S)builtin$(S)enc_provider + BUILDTOP=$(REL)..$(S)..$(S)..$(S).. +-LOCALINCLUDES = -I$(srcdir)/../des \ +- -I$(srcdir)/../aes \ ++LOCALINCLUDES = -I$(srcdir)/../aes \ + -I$(srcdir)/../camellia \ + -I$(srcdir)/../../krb \ + -I$(srcdir)/.. +@@ -11,19 +10,16 @@ LOCALINCLUDES = -I$(srcdir)/../des \ + ##DOS##OBJFILE = ..\..\$(OUTPRE)enc_provider.lst + + STLIBOBJS= \ +- des3.o \ + rc4.o \ + aes.o \ + camellia.o + + OBJS= \ +- $(OUTPRE)des3.$(OBJEXT) \ + $(OUTPRE)aes.$(OBJEXT) \ + $(OUTPRE)camellia.$(OBJEXT) \ + $(OUTPRE)rc4.$(OBJEXT) + + SRCS= \ +- $(srcdir)/des3.c \ + $(srcdir)/aes.c \ + $(srcdir)/camellia.c \ + $(srcdir)/rc4.c +diff --git a/src/lib/crypto/builtin/enc_provider/deps b/src/lib/crypto/builtin/enc_provider/deps +index 7a3324c44..c1201cc1a 100644 +--- a/src/lib/crypto/builtin/enc_provider/deps ++++ b/src/lib/crypto/builtin/enc_provider/deps +@@ -1,18 +1,6 @@ + # + # Generated makefile dependencies follow. + # +-des3.so des3.po $(OUTPRE)des3.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ +- $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ +- $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h \ +- $(srcdir)/../aes/aes.h $(srcdir)/../crypto_mod.h $(srcdir)/../des/des_int.h \ +- $(srcdir)/../sha2/sha2.h $(top_srcdir)/include/k5-buf.h \ +- $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ +- $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ +- $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ +- $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ +- $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ +- $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ +- $(top_srcdir)/include/socket-utils.h des3.c + aes.so aes.po $(OUTPRE)aes.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h \ +diff --git a/src/lib/crypto/builtin/enc_provider/des3.c b/src/lib/crypto/builtin/enc_provider/des3.c +deleted file mode 100644 +index 9b8244223..000000000 +--- a/src/lib/crypto/builtin/enc_provider/des3.c ++++ /dev/null +@@ -1,105 +0,0 @@ +-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +-/* +- * Copyright (C) 1998 by the FundsXpress, INC. +- * +- * All rights reserved. +- * +- * Export of this software from the United States of America may require +- * a specific license from the United States Government. It is the +- * responsibility of any person or organization contemplating export to +- * obtain such a license before exporting. +- * +- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +- * distribute this software and its documentation for any purpose and +- * without fee is hereby granted, provided that the above copyright +- * notice appear in all copies and that both that copyright notice and +- * this permission notice appear in supporting documentation, and that +- * the name of FundsXpress. not be used in advertising or publicity pertaining +- * to distribution of the software without specific, written prior +- * permission. FundsXpress makes no representations about the suitability of +- * this software for any purpose. It is provided "as is" without express +- * or implied warranty. +- * +- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR +- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. +- */ +- +-#include "crypto_int.h" +-#include "des_int.h" +- +-static krb5_error_code +-validate_and_schedule(krb5_key key, const krb5_data *ivec, +- const krb5_crypto_iov *data, size_t num_data, +- mit_des3_key_schedule *schedule) +-{ +- if (key->keyblock.length != 24) +- return(KRB5_BAD_KEYSIZE); +- if (iov_total_length(data, num_data, FALSE) % 8 != 0) +- return(KRB5_BAD_MSIZE); +- if (ivec && (ivec->length != 8)) +- return(KRB5_BAD_MSIZE); +- +- switch (mit_des3_key_sched(*(mit_des3_cblock *)key->keyblock.contents, +- *schedule)) { +- case -1: +- return(KRB5DES_BAD_KEYPAR); +- case -2: +- return(KRB5DES_WEAK_KEY); +- } +- return 0; +-} +- +-static krb5_error_code +-k5_des3_encrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, +- size_t num_data) +-{ +- mit_des3_key_schedule schedule; +- krb5_error_code err; +- +- err = validate_and_schedule(key, ivec, data, num_data, &schedule); +- if (err) +- return err; +- +- /* this has a return value, but the code always returns zero */ +- krb5int_des3_cbc_encrypt(data, num_data, +- schedule[0], schedule[1], schedule[2], +- ivec != NULL ? (unsigned char *) ivec->data : +- NULL); +- +- zap(schedule, sizeof(schedule)); +- +- return(0); +-} +- +-static krb5_error_code +-k5_des3_decrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, +- size_t num_data) +-{ +- mit_des3_key_schedule schedule; +- krb5_error_code err; +- +- err = validate_and_schedule(key, ivec, data, num_data, &schedule); +- if (err) +- return err; +- +- /* this has a return value, but the code always returns zero */ +- krb5int_des3_cbc_decrypt(data, num_data, +- schedule[0], schedule[1], schedule[2], +- ivec != NULL ? (unsigned char *) ivec->data : +- NULL); +- +- zap(schedule, sizeof(schedule)); +- +- return 0; +-} +- +-const struct krb5_enc_provider krb5int_enc_des3 = { +- 8, +- 21, 24, +- k5_des3_encrypt, +- k5_des3_decrypt, +- NULL, +- krb5int_des_init_state, +- krb5int_default_free_state +-}; +diff --git a/src/lib/crypto/crypto_tests/t_cf2.expected b/src/lib/crypto/crypto_tests/t_cf2.expected +index f8251a16c..bc6aa50c8 100644 +--- a/src/lib/crypto/crypto_tests/t_cf2.expected ++++ b/src/lib/crypto/crypto_tests/t_cf2.expected +@@ -1,6 +1,5 @@ + 97df97e4b798b29eb31ed7280287a92a + 4d6ca4e629785c1f01baf55e2e548566b9617ae3a96868c337cb93b5e72b1c7b +-e58f9eb643862c13ad38e529313462a7f73e62834fe54a01 + 24d7f6b6bae4e5c00d2082c5ebab3672 + edd02a39d2dbde31611c16e610be062c + 67f6ea530aea85a37dcbb23349ea52dcc61ca8493ff557252327fd8304341584 +diff --git a/src/lib/crypto/crypto_tests/t_cf2.in b/src/lib/crypto/crypto_tests/t_cf2.in +index 73e2f8fbc..c4d23b506 100644 +--- a/src/lib/crypto/crypto_tests/t_cf2.in ++++ b/src/lib/crypto/crypto_tests/t_cf2.in +@@ -8,11 +8,6 @@ key1 + key2 + a + b +-16 +-key1 +-key2 +-a +-b + 23 + key1 + key2 +diff --git a/src/lib/crypto/crypto_tests/t_cksums.c b/src/lib/crypto/crypto_tests/t_cksums.c +index 4da14ea43..84408fb68 100644 +--- a/src/lib/crypto/crypto_tests/t_cksums.c ++++ b/src/lib/crypto/crypto_tests/t_cksums.c +@@ -59,16 +59,6 @@ struct test { + "\xDA\x39\xA3\xEE\x5E\x6B\x4B\x0D\x32\x55\xBF\xEF\x95\x60\x18\x90" + "\xAF\xD8\x07\x09" } + }, +- { +- { KV5M_DATA, 9, "six seven" }, +- CKSUMTYPE_HMAC_SHA1_DES3, ENCTYPE_DES3_CBC_SHA1, 2, +- { KV5M_DATA, 24, +- "\x7A\x25\xDF\x89\x92\x29\x6D\xCE\xDA\x0E\x13\x5B\xC4\x04\x6E\x23" +- "\x75\xB3\xC1\x4C\x98\xFB\xC1\x62" }, +- { KV5M_DATA, 20, +- "\x0E\xEF\xC9\xC3\xE0\x49\xAA\xBC\x1B\xA5\xC4\x01\x67\x7D\x9A\xB6" +- "\x99\x08\x2B\xB4" } +- }, + { + { KV5M_DATA, 37, "eight nine ten eleven twelve thirteen" }, + CKSUMTYPE_HMAC_SHA1_96_AES128, ENCTYPE_AES128_CTS_HMAC_SHA1_96, 3, +diff --git a/src/lib/crypto/crypto_tests/t_decrypt.c b/src/lib/crypto/crypto_tests/t_decrypt.c +index a40a85500..716f2c337 100644 +--- a/src/lib/crypto/crypto_tests/t_decrypt.c ++++ b/src/lib/crypto/crypto_tests/t_decrypt.c +@@ -39,62 +39,6 @@ struct test { + krb5_data keybits; + krb5_data ciphertext; + } test_cases[] = { +- { +- ENCTYPE_DES3_CBC_SHA1, +- { KV5M_DATA, 0, "", }, 0, +- { KV5M_DATA, 24, +- "\x7A\x25\xDF\x89\x92\x29\x6D\xCE\xDA\x0E\x13\x5B\xC4\x04\x6E\x23" +- "\x75\xB3\xC1\x4C\x98\xFB\xC1\x62" }, +- { KV5M_DATA, 28, +- "\x54\x8A\xF4\xD5\x04\xF7\xD7\x23\x30\x3F\x12\x17\x5F\xE8\x38\x6B" +- "\x7B\x53\x35\xA9\x67\xBA\xD6\x1F\x3B\xF0\xB1\x43" } +- }, +- { +- ENCTYPE_DES3_CBC_SHA1, +- { KV5M_DATA, 1, "1", }, 1, +- { KV5M_DATA, 24, +- "\xBC\x07\x83\x89\x15\x13\xD5\xCE\x57\xBC\x13\x8F\xD3\xC1\x1A\xE6" +- "\x40\x45\x23\x85\x32\x29\x62\xB6" }, +- { KV5M_DATA, 36, +- "\x9C\x3C\x1D\xBA\x47\x47\xD8\x5A\xF2\x91\x6E\x47\x45\xF2\xDC\xE3" +- "\x80\x46\x79\x6E\x51\x04\xBC\xCD\xFB\x66\x9A\x91\xD4\x4B\xC3\x56" +- "\x66\x09\x45\xC7" } +- }, +- { +- ENCTYPE_DES3_CBC_SHA1, +- { KV5M_DATA, 9, "9 bytesss", }, 2, +- { KV5M_DATA, 24, +- "\x2F\xD0\xF7\x25\xCE\x04\x10\x0D\x2F\xC8\xA1\x80\x98\x83\x1F\x85" +- "\x0B\x45\xD9\xEF\x85\x0B\xD9\x20" }, +- { KV5M_DATA, 44, +- "\xCF\x91\x44\xEB\xC8\x69\x79\x81\x07\x5A\x8B\xAD\x8D\x74\xE5\xD7" +- "\xD5\x91\xEB\x7D\x97\x70\xC7\xAD\xA2\x5E\xE8\xC5\xB3\xD6\x94\x44" +- "\xDF\xEC\x79\xA5\xB7\xA0\x14\x82\xD9\xAF\x74\xE6" } +- }, +- { +- ENCTYPE_DES3_CBC_SHA1, +- { KV5M_DATA, 13, "13 bytes byte", }, 3, +- { KV5M_DATA, 24, +- "\x0D\xD5\x20\x94\xE0\xF4\x1C\xEC\xCB\x5B\xE5\x10\xA7\x64\xB3\x51" +- "\x76\xE3\x98\x13\x32\xF1\xE5\x98" }, +- { KV5M_DATA, 44, +- "\x83\x9A\x17\x08\x1E\xCB\xAF\xBC\xDC\x91\xB8\x8C\x69\x55\xDD\x3C" +- "\x45\x14\x02\x3C\xF1\x77\xB7\x7B\xF0\xD0\x17\x7A\x16\xF7\x05\xE8" +- "\x49\xCB\x77\x81\xD7\x6A\x31\x6B\x19\x3F\x8D\x30" } +- }, +- { +- ENCTYPE_DES3_CBC_SHA1, +- { KV5M_DATA, 30, "30 bytes bytes bytes bytes byt", }, 4, +- { KV5M_DATA, 24, +- "\xF1\x16\x86\xCB\xBC\x9E\x23\xEA\x54\xFE\xCD\x2A\x3D\xCD\xFB\x20" +- "\xB6\xFE\x98\xBF\x26\x45\xC4\xC4" }, +- { KV5M_DATA, 60, +- "\x89\x43\x3E\x83\xFD\x0E\xA3\x66\x6C\xFF\xCD\x18\xD8\xDE\xEB\xC5" +- "\x3B\x9A\x34\xED\xBE\xB1\x59\xD9\xF6\x67\xC6\xC2\xB9\xA9\x64\x40" +- "\x1D\x55\xE7\xE9\xC6\x8D\x64\x8D\x65\xC3\xAA\x84\xFF\xA3\x79\x0C" +- "\x14\xA8\x64\xDA\x80\x73\xA9\xA9\x5C\x4B\xA2\xBC" } +- }, +- + { + ENCTYPE_ARCFOUR_HMAC, + { KV5M_DATA, 0, "", }, 0, +@@ -524,7 +468,6 @@ printhex(const char *head, void *data, size_t len) + + static krb5_enctype + enctypes[] = { +- ENCTYPE_DES3_CBC_SHA1, + ENCTYPE_ARCFOUR_HMAC, + ENCTYPE_ARCFOUR_HMAC_EXP, + ENCTYPE_AES128_CTS_HMAC_SHA1_96, +diff --git a/src/lib/crypto/crypto_tests/t_derive.c b/src/lib/crypto/crypto_tests/t_derive.c +index afbf7477f..93ce30da2 100644 +--- a/src/lib/crypto/crypto_tests/t_derive.c ++++ b/src/lib/crypto/crypto_tests/t_derive.c +@@ -38,41 +38,6 @@ struct test { + enum deriv_alg alg; + krb5_data expected_key; + } test_cases[] = { +- /* Kc, Ke, Kei for a DES3 key */ +- { +- ENCTYPE_DES3_CBC_SHA1, +- { KV5M_DATA, 24, +- "\x85\x0B\xB5\x13\x58\x54\x8C\xD0\x5E\x86\x76\x8C\x31\x3E\x3B\xFE" +- "\xF7\x51\x19\x37\xDC\xF7\x2C\x3E" }, +- { KV5M_DATA, 5, "\0\0\0\2\x99" }, +- DERIVE_RFC3961, +- { KV5M_DATA, 24, +- "\xF7\x8C\x49\x6D\x16\xE6\xC2\xDA\xE0\xE0\xB6\xC2\x40\x57\xA8\x4C" +- "\x04\x26\xAE\xEF\x26\xFD\x6D\xCE" } +- }, +- { +- ENCTYPE_DES3_CBC_SHA1, +- { KV5M_DATA, 24, +- "\x85\x0B\xB5\x13\x58\x54\x8C\xD0\x5E\x86\x76\x8C\x31\x3E\x3B\xFE" +- "\xF7\x51\x19\x37\xDC\xF7\x2C\x3E" }, +- { KV5M_DATA, 5, "\0\0\0\2\xAA" }, +- DERIVE_RFC3961, +- { KV5M_DATA, 24, +- "\x5B\x57\x23\xD0\xB6\x34\xCB\x68\x4C\x3E\xBA\x52\x64\xE9\xA7\x0D" +- "\x52\xE6\x83\x23\x1A\xD3\xC4\xCE" } +- }, +- { +- ENCTYPE_DES3_CBC_SHA1, +- { KV5M_DATA, 24, +- "\x85\x0B\xB5\x13\x58\x54\x8C\xD0\x5E\x86\x76\x8C\x31\x3E\x3B\xFE" +- "\xF7\x51\x19\x37\xDC\xF7\x2C\x3E" }, +- { KV5M_DATA, 5, "\0\0\0\2\x55" }, +- DERIVE_RFC3961, +- { KV5M_DATA, 24, +- "\xA7\x7C\x94\x98\x0E\x9B\x73\x45\xA8\x15\x25\xC4\x23\xA7\x37\xCE" +- "\x67\xF4\xCD\x91\xB6\xB3\xDA\x45" } +- }, +- + /* Kc, Ke, Ki for an AES-128 key */ + { + ENCTYPE_AES128_CTS_HMAC_SHA1_96, +@@ -286,7 +251,6 @@ static const struct krb5_enc_provider * + get_enc_provider(krb5_enctype enctype) + { + switch (enctype) { +- case ENCTYPE_DES3_CBC_SHA1: return &krb5int_enc_des3; + case ENCTYPE_AES128_CTS_HMAC_SHA1_96: return &krb5int_enc_aes128; + case ENCTYPE_AES256_CTS_HMAC_SHA1_96: return &krb5int_enc_aes256; + case ENCTYPE_CAMELLIA128_CTS_CMAC: return &krb5int_enc_camellia128; +diff --git a/src/lib/crypto/crypto_tests/t_encrypt.c b/src/lib/crypto/crypto_tests/t_encrypt.c +index bd9b94691..290a72e1e 100644 +--- a/src/lib/crypto/crypto_tests/t_encrypt.c ++++ b/src/lib/crypto/crypto_tests/t_encrypt.c +@@ -37,7 +37,6 @@ + + /* What enctypes should we test?*/ + krb5_enctype interesting_enctypes[] = { +- ENCTYPE_DES3_CBC_SHA1, + ENCTYPE_ARCFOUR_HMAC, + ENCTYPE_ARCFOUR_HMAC_EXP, + ENCTYPE_AES256_CTS_HMAC_SHA1_96, +diff --git a/src/lib/crypto/crypto_tests/t_short.c b/src/lib/crypto/crypto_tests/t_short.c +index d4c2b97df..4466b7115 100644 +--- a/src/lib/crypto/crypto_tests/t_short.c ++++ b/src/lib/crypto/crypto_tests/t_short.c +@@ -34,7 +34,6 @@ + #include "k5-int.h" + + krb5_enctype interesting_enctypes[] = { +- ENCTYPE_DES3_CBC_SHA1, + ENCTYPE_ARCFOUR_HMAC, + ENCTYPE_ARCFOUR_HMAC_EXP, + ENCTYPE_AES256_CTS_HMAC_SHA1_96, +diff --git a/src/lib/crypto/crypto_tests/t_str2key.c b/src/lib/crypto/crypto_tests/t_str2key.c +index cdb1acc6d..ef4c4a7d3 100644 +--- a/src/lib/crypto/crypto_tests/t_str2key.c ++++ b/src/lib/crypto/crypto_tests/t_str2key.c +@@ -35,58 +35,6 @@ struct test { + krb5_error_code expected_err; + krb5_boolean allow_weak; + } test_cases[] = { +- /* Test vectors from RFC 3961 appendix A.4. */ +- { +- ENCTYPE_DES3_CBC_SHA1, +- "password", +- { KV5M_DATA, 21, "ATHENA.MIT.EDUraeburn" }, +- { KV5M_DATA, 0, NULL }, +- { KV5M_DATA, 24, "\x85\x0B\xB5\x13\x58\x54\x8C\xD0\x5E\x86\x76\x8C" +- "\x31\x3E\x3B\xFE\xF7\x51\x19\x37\xDC\xF7\x2C\x3E" }, +- 0, +- FALSE +- }, +- { +- ENCTYPE_DES3_CBC_SHA1, +- "potatoe", +- { KV5M_DATA, 19, "WHITEHOUSE.GOVdanny" }, +- { KV5M_DATA, 0, NULL }, +- { KV5M_DATA, 24, "\xDF\xCD\x23\x3D\xD0\xA4\x32\x04\xEA\x6D\xC4\x37" +- "\xFB\x15\xE0\x61\xB0\x29\x79\xC1\xF7\x4F\x37\x7A" }, +- 0, +- FALSE +- }, +- { +- ENCTYPE_DES3_CBC_SHA1, +- "penny", +- { KV5M_DATA, 19, "EXAMPLE.COMbuckaroo" }, +- { KV5M_DATA, 0, NULL }, +- { KV5M_DATA, 24, "\x6D\x2F\xCD\xF2\xD6\xFB\xBC\x3D\xDC\xAD\xB5\xDA" +- "\x57\x10\xA2\x34\x89\xB0\xD3\xB6\x9D\x5D\x9D\x4A" }, +- 0, +- FALSE +- }, +- { +- ENCTYPE_DES3_CBC_SHA1, +- "\xC3\x9F", +- { KV5M_DATA, 23, "ATHENA.MIT.EDUJuri\xC5\xA1\x69\xC4\x87" }, +- { KV5M_DATA, 0, NULL }, +- { KV5M_DATA, 24, "\x16\xD5\xA4\x0E\x1C\xE3\xBA\xCB\x61\xB9\xDC\xE0" +- "\x04\x70\x32\x4C\x83\x19\x73\xA7\xB9\x52\xFE\xB0" }, +- 0, +- FALSE +- }, +- { +- ENCTYPE_DES3_CBC_SHA1, +- "\xF0\x9D\x84\x9E", +- { KV5M_DATA, 18, "EXAMPLE.COMpianist" }, +- { KV5M_DATA, 0, NULL }, +- { KV5M_DATA, 24, "\x85\x76\x37\x26\x58\x5D\xBC\x1C\xCE\x6E\xC4\x3E" +- "\x1F\x75\x1F\x07\xF1\xC4\xCB\xB0\x98\xF4\x0B\x19" }, +- 0, +- FALSE +- }, +- + /* Test vectors from RFC 3962 appendix B. */ + { + ENCTYPE_AES128_CTS_HMAC_SHA1_96, +diff --git a/src/lib/crypto/krb/Makefile.in b/src/lib/crypto/krb/Makefile.in +index b74e6f7cc..2b0c4163d 100644 +--- a/src/lib/crypto/krb/Makefile.in ++++ b/src/lib/crypto/krb/Makefile.in +@@ -50,7 +50,6 @@ STLIBOBJS=\ + prf.o \ + prf_aes2.o \ + prf_cmac.o \ +- prf_des.o \ + prf_dk.o \ + prf_rc4.o \ + prng.o \ +@@ -109,7 +108,6 @@ OBJS=\ + $(OUTPRE)prf.$(OBJEXT) \ + $(OUTPRE)prf_aes2.$(OBJEXT) \ + $(OUTPRE)prf_cmac.$(OBJEXT) \ +- $(OUTPRE)prf_des.$(OBJEXT) \ + $(OUTPRE)prf_dk.$(OBJEXT) \ + $(OUTPRE)prf_rc4.$(OBJEXT) \ + $(OUTPRE)prng.$(OBJEXT) \ +@@ -168,7 +166,6 @@ SRCS=\ + $(srcdir)/prf.c \ + $(srcdir)/prf_aes2.c \ + $(srcdir)/prf_cmac.c \ +- $(srcdir)/prf_des.c \ + $(srcdir)/prf_dk.c \ + $(srcdir)/prf_rc4.c \ + $(srcdir)/prng.c \ +diff --git a/src/lib/crypto/krb/cksumtypes.c b/src/lib/crypto/krb/cksumtypes.c +index ecc2e08c9..f5fbe8a2a 100644 +--- a/src/lib/crypto/krb/cksumtypes.c ++++ b/src/lib/crypto/krb/cksumtypes.c +@@ -46,12 +46,6 @@ const struct krb5_cksumtypes krb5int_cksumtypes_list[] = { + krb5int_unkeyed_checksum, NULL, + 20, 20, CKSUM_UNKEYED }, + +- { CKSUMTYPE_HMAC_SHA1_DES3, +- "hmac-sha1-des3", { "hmac-sha1-des3-kd" }, "HMAC-SHA1 DES3 key", +- &krb5int_enc_des3, &krb5int_hash_sha1, +- krb5int_dk_checksum, NULL, +- 20, 20, 0 }, +- + { CKSUMTYPE_HMAC_MD5_ARCFOUR, + "hmac-md5-rc4", { "hmac-md5-enc", "hmac-md5-earcfour" }, + "Microsoft HMAC MD5", +diff --git a/src/lib/crypto/krb/crypto_int.h b/src/lib/crypto/krb/crypto_int.h +index ba693f8a4..5cc1f8e43 100644 +--- a/src/lib/crypto/krb/crypto_int.h ++++ b/src/lib/crypto/krb/crypto_int.h +@@ -276,10 +276,6 @@ krb5_error_code krb5int_aes2_string_to_key(const struct krb5_keytypes *enc, + /* Random to key */ + krb5_error_code k5_rand2key_direct(const krb5_data *randombits, + krb5_keyblock *keyblock); +-krb5_error_code k5_rand2key_des(const krb5_data *randombits, +- krb5_keyblock *keyblock); +-krb5_error_code k5_rand2key_des3(const krb5_data *randombits, +- krb5_keyblock *keyblock); + + /* Pseudo-random function */ + krb5_error_code krb5int_des_prf(const struct krb5_keytypes *ktp, +@@ -368,11 +364,6 @@ krb5_keyusage krb5int_arcfour_translate_usage(krb5_keyusage usage); + /* Ensure library initialization has occurred. */ + int krb5int_crypto_init(void); + +-/* DES default state initialization handler (used by module enc providers). */ +-krb5_error_code krb5int_des_init_state(const krb5_keyblock *key, +- krb5_keyusage keyusage, +- krb5_data *state_out); +- + /* Default state cleanup handler (used by module enc providers). */ + void krb5int_default_free_state(krb5_data *state); + +@@ -425,7 +416,6 @@ void k5_iov_cursor_put(struct iov_cursor *cursor, unsigned char *block); + /* Modules must implement the k5_sha256() function prototyped in k5-int.h. */ + + /* Modules must implement the following enc_providers and hash_providers: */ +-extern const struct krb5_enc_provider krb5int_enc_des3; + extern const struct krb5_enc_provider krb5int_enc_arcfour; + extern const struct krb5_enc_provider krb5int_enc_aes128; + extern const struct krb5_enc_provider krb5int_enc_aes256; +@@ -442,12 +432,6 @@ extern const struct krb5_hash_provider krb5int_hash_sha384; + + /* Modules must implement the following functions. */ + +-/* Set the parity bits to the correct values in keybits. */ +-void k5_des_fixup_key_parity(unsigned char *keybits); +- +-/* Return true if keybits is a weak or semi-weak DES key. */ +-krb5_boolean k5_des_is_weak_key(unsigned char *keybits); +- + /* Compute an HMAC using the provided hash function, key, and data, storing the + * result into output (caller-allocated). */ + krb5_error_code krb5int_hmac(const struct krb5_hash_provider *hash, +diff --git a/src/lib/crypto/krb/default_state.c b/src/lib/crypto/krb/default_state.c +index 0757c8b02..f89dc7902 100644 +--- a/src/lib/crypto/krb/default_state.c ++++ b/src/lib/crypto/krb/default_state.c +@@ -32,16 +32,6 @@ + + #include "crypto_int.h" + +-krb5_error_code +-krb5int_des_init_state(const krb5_keyblock *key, krb5_keyusage usage, +- krb5_data *state_out) +-{ +- if (alloc_data(state_out, 8)) +- return ENOMEM; +- +- return 0; +-} +- + void + krb5int_default_free_state(krb5_data *state) + { +diff --git a/src/lib/crypto/krb/enctype_util.c b/src/lib/crypto/krb/enctype_util.c +index 1542d4062..a0037912a 100644 +--- a/src/lib/crypto/krb/enctype_util.c ++++ b/src/lib/crypto/krb/enctype_util.c +@@ -45,6 +45,9 @@ struct { + { ENCTYPE_DES_CBC_MD5, "des-cbc-md5" }, + { ENCTYPE_DES_CBC_RAW, "des-cbc-raw" }, + { ENCTYPE_DES_HMAC_SHA1, "des-hmac-sha1" }, ++ { ENCTYPE_DES3_CBC_SHA, "des3-cbc-sha1" }, ++ { ENCTYPE_DES3_CBC_RAW, "des3-cbc-raw" }, ++ { ENCTYPE_DES3_CBC_SHA1, "des3-hmac-sha1" }, + { ENCTYPE_NULL, NULL } + }; + +diff --git a/src/lib/crypto/krb/etypes.c b/src/lib/crypto/krb/etypes.c +index fc278783b..7635393a4 100644 +--- a/src/lib/crypto/krb/etypes.c ++++ b/src/lib/crypto/krb/etypes.c +@@ -35,27 +35,6 @@ + + /* Deprecations come from RFC 6649 and RFC 8249. */ + const struct krb5_keytypes krb5int_enctypes_list[] = { +- { ENCTYPE_DES3_CBC_RAW, +- "des3-cbc-raw", { 0 }, "Triple DES cbc mode raw", +- &krb5int_enc_des3, NULL, +- 16, +- krb5int_raw_crypto_length, krb5int_raw_encrypt, krb5int_raw_decrypt, +- krb5int_dk_string_to_key, k5_rand2key_des3, +- NULL, /*PRF*/ +- 0, +- ETYPE_WEAK | ETYPE_DEPRECATED, 112 }, +- +- { ENCTYPE_DES3_CBC_SHA1, +- "des3-cbc-sha1", { "des3-hmac-sha1", "des3-cbc-sha1-kd" }, +- "Triple DES cbc mode with HMAC/sha1", +- &krb5int_enc_des3, &krb5int_hash_sha1, +- 16, +- krb5int_dk_crypto_length, krb5int_dk_encrypt, krb5int_dk_decrypt, +- krb5int_dk_string_to_key, k5_rand2key_des3, +- krb5int_dk_prf, +- CKSUMTYPE_HMAC_SHA1_DES3, +- ETYPE_DEPRECATED, 112 }, +- + /* rc4-hmac uses a 128-bit key, but due to weaknesses in the RC4 cipher, we + * consider its strength degraded and assign it an SSF value of 64. */ + { ENCTYPE_ARCFOUR_HMAC, +diff --git a/src/lib/crypto/krb/prf_des.c b/src/lib/crypto/krb/prf_des.c +deleted file mode 100644 +index 7a2d719c5..000000000 +--- a/src/lib/crypto/krb/prf_des.c ++++ /dev/null +@@ -1,47 +0,0 @@ +-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +-/* lib/crypto/krb/prf_des.c - RFC 3961 DES-based PRF */ +-/* +- * Copyright (C) 2004, 2009 by the Massachusetts Institute of Technology. +- * All rights reserved. +- * +- * Export of this software from the United States of America may +- * require a specific license from the United States Government. +- * It is the responsibility of any person or organization contemplating +- * export to obtain such a license before exporting. +- * +- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +- * distribute this software and its documentation for any purpose and +- * without fee is hereby granted, provided that the above copyright +- * notice appear in all copies and that both that copyright notice and +- * this permission notice appear in supporting documentation, and that +- * the name of M.I.T. not be used in advertising or publicity pertaining +- * to distribution of the software without specific, written prior +- * permission. Furthermore if you modify this software you must label +- * your software as modified software and not distribute it in such a +- * fashion that it might be confused with the original M.I.T. software. +- * M.I.T. makes no representations about the suitability of +- * this software for any purpose. It is provided "as is" without express +- * or implied warranty. +- */ +- +-#include "crypto_int.h" +- +-krb5_error_code +-krb5int_des_prf(const struct krb5_keytypes *ktp, krb5_key key, +- const krb5_data *in, krb5_data *out) +-{ +- const struct krb5_hash_provider *hash = &krb5int_hash_md5; +- krb5_crypto_iov iov; +- krb5_error_code ret; +- +- /* Compute a hash of the input, storing into the output buffer. */ +- iov.flags = KRB5_CRYPTO_TYPE_DATA; +- iov.data = *in; +- ret = hash->hash(&iov, 1, out); +- if (ret != 0) +- return ret; +- +- /* Encrypt the hash in place. */ +- iov.data = *out; +- return ktp->enc->encrypt(key, NULL, &iov, 1); +-} +diff --git a/src/lib/crypto/krb/random_to_key.c b/src/lib/crypto/krb/random_to_key.c +index 157462526..863090beb 100644 +--- a/src/lib/crypto/krb/random_to_key.c ++++ b/src/lib/crypto/krb/random_to_key.c +@@ -71,48 +71,3 @@ k5_rand2key_direct(const krb5_data *randombits, krb5_keyblock *keyblock) + memcpy(keyblock->contents, randombits->data, randombits->length); + return 0; + } +- +-static inline void +-eighth_byte(unsigned char *b) +-{ +- b[7] = (((b[0] & 1) << 1) | ((b[1] & 1) << 2) | ((b[2] & 1) << 3) | +- ((b[3] & 1) << 4) | ((b[4] & 1) << 5) | ((b[5] & 1) << 6) | +- ((b[6] & 1) << 7)); +-} +- +-krb5_error_code +-k5_rand2key_des(const krb5_data *randombits, krb5_keyblock *keyblock) +-{ +- if (randombits->length != 7) +- return(KRB5_CRYPTO_INTERNAL); +- +- keyblock->magic = KV5M_KEYBLOCK; +- +- /* Take the seven bytes, move them around into the top 7 bits of the +- * 8 key bytes, then compute the parity bits. */ +- memcpy(keyblock->contents, randombits->data, randombits->length); +- eighth_byte(keyblock->contents); +- k5_des_fixup_key_parity(keyblock->contents); +- +- return 0; +-} +- +-krb5_error_code +-k5_rand2key_des3(const krb5_data *randombits, krb5_keyblock *keyblock) +-{ +- int i; +- +- if (randombits->length != 21) +- return KRB5_CRYPTO_INTERNAL; +- +- keyblock->magic = KV5M_KEYBLOCK; +- +- /* Take the seven bytes, move them around into the top 7 bits of the +- * 8 key bytes, then compute the parity bits. Do this three times. */ +- for (i = 0; i < 3; i++) { +- memcpy(&keyblock->contents[i * 8], &randombits->data[i * 7], 7); +- eighth_byte(&keyblock->contents[i * 8]); +- k5_des_fixup_key_parity(&keyblock->contents[i * 8]); +- } +- return 0; +-} +diff --git a/src/lib/crypto/libk5crypto.exports b/src/lib/crypto/libk5crypto.exports +index 451d5e035..9db181381 100644 +--- a/src/lib/crypto/libk5crypto.exports ++++ b/src/lib/crypto/libk5crypto.exports +@@ -86,7 +86,6 @@ krb5_k_verify_checksum + krb5_k_verify_checksum_iov + krb5int_aes_encrypt + krb5int_aes_decrypt +-krb5int_enc_des3 + krb5int_arcfour_gsscrypt + krb5int_camellia_cbc_mac + krb5int_cmac_checksum +diff --git a/src/lib/crypto/openssl/Makefile.in b/src/lib/crypto/openssl/Makefile.in +index aa434b168..234fc0e76 100644 +--- a/src/lib/crypto/openssl/Makefile.in ++++ b/src/lib/crypto/openssl/Makefile.in +@@ -1,6 +1,6 @@ + mydir=lib$(S)crypto$(S)openssl + BUILDTOP=$(REL)..$(S)..$(S).. +-SUBDIRS=camellia des aes md4 md5 sha1 sha2 enc_provider hash_provider ++SUBDIRS=camellia aes md4 md5 sha1 sha2 enc_provider hash_provider + LOCALINCLUDES = -I$(srcdir)/../krb -I$(srcdir) + + STLIBOBJS=\ +@@ -24,14 +24,14 @@ SRCS=\ + $(srcdir)/sha256.c \ + $(srcdir)/stubs.c + +-STOBJLISTS= des/OBJS.ST md4/OBJS.ST \ ++STOBJLISTS= md4/OBJS.ST \ + md5/OBJS.ST sha1/OBJS.ST sha2/OBJS.ST \ + enc_provider/OBJS.ST \ + hash_provider/OBJS.ST \ + aes/OBJS.ST \ + OBJS.ST + +-SUBDIROBJLISTS= des/OBJS.ST md4/OBJS.ST \ ++SUBDIROBJLISTS= md4/OBJS.ST \ + md5/OBJS.ST sha1/OBJS.ST sha2/OBJS.ST \ + enc_provider/OBJS.ST \ + hash_provider/OBJS.ST \ +@@ -42,7 +42,7 @@ includes: depend + + depend: $(SRCS) + +-clean-unix:: clean-libobjs ++clean-unix:: clean-libobjsn + + @lib_frag@ + @libobj_frag@ +diff --git a/src/lib/crypto/openssl/des/Makefile.in b/src/lib/crypto/openssl/des/Makefile.in +deleted file mode 100644 +index 4392fb8ea..000000000 +--- a/src/lib/crypto/openssl/des/Makefile.in ++++ /dev/null +@@ -1,20 +0,0 @@ +-mydir=lib$(S)crypto$(S)openssl$(S)des +-BUILDTOP=$(REL)..$(S)..$(S)..$(S).. +-LOCALINCLUDES = -I$(srcdir)/../../krb -I$(srcdir)/.. +- +-STLIBOBJS= des_keys.o +- +-OBJS= $(OUTPRE)des_keys.$(OBJEXT) +- +-SRCS= $(srcdir)/des_keys.c +- +-all-unix: all-libobjs +- +-includes: depend +- +-depend: $(SRCS) +- +-clean-unix:: clean-libobjs +- +-@libobj_frag@ +- +diff --git a/src/lib/crypto/openssl/des/deps b/src/lib/crypto/openssl/des/deps +deleted file mode 100644 +index 21b904f89..000000000 +--- a/src/lib/crypto/openssl/des/deps ++++ /dev/null +@@ -1,15 +0,0 @@ +-# +-# Generated makefile dependencies follow. +-# +-des_keys.so des_keys.po $(OUTPRE)des_keys.$(OBJEXT): \ +- $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ +- $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ +- $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h $(srcdir)/../crypto_mod.h \ +- $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ +- $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ +- $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ +- $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ +- $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ +- $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ +- $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ +- des_keys.c +diff --git a/src/lib/crypto/openssl/des/des_keys.c b/src/lib/crypto/openssl/des/des_keys.c +deleted file mode 100644 +index 51d9db216..000000000 +--- a/src/lib/crypto/openssl/des/des_keys.c ++++ /dev/null +@@ -1,40 +0,0 @@ +-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +-/* lib/crypto/openssl/des/des_keys.c - Key functions used by Kerberos code */ +-/* +- * Copyright (C) 2011 by the Massachusetts Institute of Technology. +- * All rights reserved. +- * +- * Export of this software from the United States of America may +- * require a specific license from the United States Government. +- * It is the responsibility of any person or organization contemplating +- * export to obtain such a license before exporting. +- * +- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +- * distribute this software and its documentation for any purpose and +- * without fee is hereby granted, provided that the above copyright +- * notice appear in all copies and that both that copyright notice and +- * this permission notice appear in supporting documentation, and that +- * the name of M.I.T. not be used in advertising or publicity pertaining +- * to distribution of the software without specific, written prior +- * permission. Furthermore if you modify this software you must label +- * your software as modified software and not distribute it in such a +- * fashion that it might be confused with the original M.I.T. software. +- * M.I.T. makes no representations about the suitability of +- * this software for any purpose. It is provided "as is" without express +- * or implied warranty. +- */ +- +-#include "crypto_int.h" +-#include +- +-void +-k5_des_fixup_key_parity(unsigned char *keybits) +-{ +- DES_set_odd_parity((DES_cblock *)keybits); +-} +- +-krb5_boolean +-k5_des_is_weak_key(unsigned char *keybits) +-{ +- return DES_is_weak_key((DES_cblock *)keybits); +-} +diff --git a/src/lib/crypto/openssl/enc_provider/Makefile.in b/src/lib/crypto/openssl/enc_provider/Makefile.in +index a9069d22d..2b32c3ac4 100644 +--- a/src/lib/crypto/openssl/enc_provider/Makefile.in ++++ b/src/lib/crypto/openssl/enc_provider/Makefile.in +@@ -3,19 +3,16 @@ BUILDTOP=$(REL)..$(S)..$(S)..$(S).. + LOCALINCLUDES = -I$(srcdir)/../../krb -I$(srcdir)/.. + + STLIBOBJS= \ +- des3.o \ + rc4.o \ + aes.o \ + camellia.o + + OBJS= \ +- $(OUTPRE)des3.$(OBJEXT) \ + $(OUTPRE)aes.$(OBJEXT) \ + $(OUTPRE)camellia.$(OBJEXT) \ + $(OUTPRE)rc4.$(OBJEXT) + + SRCS= \ +- $(srcdir)/des3.c \ + $(srcdir)/aes.c \ + $(srcdir)/camellia.c \ + $(srcdir)/rc4.c +diff --git a/src/lib/crypto/openssl/enc_provider/deps b/src/lib/crypto/openssl/enc_provider/deps +index 1c28cc842..91ba48234 100644 +--- a/src/lib/crypto/openssl/enc_provider/deps ++++ b/src/lib/crypto/openssl/enc_provider/deps +@@ -1,17 +1,6 @@ + # + # Generated makefile dependencies follow. + # +-des3.so des3.po $(OUTPRE)des3.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ +- $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ +- $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h \ +- $(srcdir)/../crypto_mod.h $(top_srcdir)/include/k5-buf.h \ +- $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ +- $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ +- $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ +- $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ +- $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ +- $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ +- $(top_srcdir)/include/socket-utils.h des3.c + aes.so aes.po $(OUTPRE)aes.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h \ +diff --git a/src/lib/crypto/openssl/enc_provider/des3.c b/src/lib/crypto/openssl/enc_provider/des3.c +deleted file mode 100644 +index 1c439c2cd..000000000 +--- a/src/lib/crypto/openssl/enc_provider/des3.c ++++ /dev/null +@@ -1,184 +0,0 @@ +-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +-/* lib/crypto/openssl/enc_provider/des3.c */ +-/* +- * Copyright (C) 2009 by the Massachusetts Institute of Technology. +- * All rights reserved. +- * +- * Export of this software from the United States of America may +- * require a specific license from the United States Government. +- * It is the responsibility of any person or organization contemplating +- * export to obtain such a license before exporting. +- * +- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +- * distribute this software and its documentation for any purpose and +- * without fee is hereby granted, provided that the above copyright +- * notice appear in all copies and that both that copyright notice and +- * this permission notice appear in supporting documentation, and that +- * the name of M.I.T. not be used in advertising or publicity pertaining +- * to distribution of the software without specific, written prior +- * permission. Furthermore if you modify this software you must label +- * your software as modified software and not distribute it in such a +- * fashion that it might be confused with the original M.I.T. software. +- * M.I.T. makes no representations about the suitability of +- * this software for any purpose. It is provided "as is" without express +- * or implied warranty. +- */ +-/* +- * Copyright (C) 1998 by the FundsXpress, INC. +- * +- * All rights reserved. +- * +- * Export of this software from the United States of America may require +- * a specific license from the United States Government. It is the +- * responsibility of any person or organization contemplating export to +- * obtain such a license before exporting. +- * +- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +- * distribute this software and its documentation for any purpose and +- * without fee is hereby granted, provided that the above copyright +- * notice appear in all copies and that both that copyright notice and +- * this permission notice appear in supporting documentation, and that +- * the name of FundsXpress. not be used in advertising or publicity pertaining +- * to distribution of the software without specific, written prior +- * permission. FundsXpress makes no representations about the suitability of +- * this software for any purpose. It is provided "as is" without express +- * or implied warranty. +- * +- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR +- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. +- */ +- +-#include "crypto_int.h" +-#include +- +- +-#define DES3_BLOCK_SIZE 8 +-#define DES3_KEY_SIZE 24 +-#define DES3_KEY_BYTES 21 +- +-static krb5_error_code +-validate(krb5_key key, const krb5_data *ivec, const krb5_crypto_iov *data, +- size_t num_data, krb5_boolean *empty) +-{ +- size_t input_length = iov_total_length(data, num_data, FALSE); +- +- if (key->keyblock.length != DES3_KEY_SIZE) +- return(KRB5_BAD_KEYSIZE); +- if ((input_length%DES3_BLOCK_SIZE) != 0) +- return(KRB5_BAD_MSIZE); +- if (ivec && (ivec->length != 8)) +- return(KRB5_BAD_MSIZE); +- +- *empty = (input_length == 0); +- return 0; +-} +- +-static krb5_error_code +-k5_des3_encrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, +- size_t num_data) +-{ +- int ret, olen = DES3_BLOCK_SIZE; +- unsigned char iblock[DES3_BLOCK_SIZE], oblock[DES3_BLOCK_SIZE]; +- struct iov_cursor cursor; +- EVP_CIPHER_CTX *ctx; +- krb5_boolean empty; +- +- ret = validate(key, ivec, data, num_data, &empty); +- if (ret != 0 || empty) +- return ret; +- +- ctx = EVP_CIPHER_CTX_new(); +- if (ctx == NULL) +- return ENOMEM; +- +- ret = EVP_EncryptInit_ex(ctx, EVP_des_ede3_cbc(), NULL, +- key->keyblock.contents, +- (ivec) ? (unsigned char*)ivec->data : NULL); +- if (!ret) { +- EVP_CIPHER_CTX_free(ctx); +- return KRB5_CRYPTO_INTERNAL; +- } +- +- EVP_CIPHER_CTX_set_padding(ctx,0); +- +- k5_iov_cursor_init(&cursor, data, num_data, DES3_BLOCK_SIZE, FALSE); +- while (k5_iov_cursor_get(&cursor, iblock)) { +- ret = EVP_EncryptUpdate(ctx, oblock, &olen, iblock, DES3_BLOCK_SIZE); +- if (!ret) +- break; +- k5_iov_cursor_put(&cursor, oblock); +- } +- +- if (ivec != NULL) +- memcpy(ivec->data, oblock, DES3_BLOCK_SIZE); +- +- EVP_CIPHER_CTX_free(ctx); +- +- zap(iblock, sizeof(iblock)); +- zap(oblock, sizeof(oblock)); +- +- if (ret != 1) +- return KRB5_CRYPTO_INTERNAL; +- return 0; +-} +- +-static krb5_error_code +-k5_des3_decrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, +- size_t num_data) +-{ +- int ret, olen = DES3_BLOCK_SIZE; +- unsigned char iblock[DES3_BLOCK_SIZE], oblock[DES3_BLOCK_SIZE]; +- struct iov_cursor cursor; +- EVP_CIPHER_CTX *ctx; +- krb5_boolean empty; +- +- ret = validate(key, ivec, data, num_data, &empty); +- if (ret != 0 || empty) +- return ret; +- +- ctx = EVP_CIPHER_CTX_new(); +- if (ctx == NULL) +- return ENOMEM; +- +- ret = EVP_DecryptInit_ex(ctx, EVP_des_ede3_cbc(), NULL, +- key->keyblock.contents, +- (ivec) ? (unsigned char*)ivec->data : NULL); +- if (!ret) { +- EVP_CIPHER_CTX_free(ctx); +- return KRB5_CRYPTO_INTERNAL; +- } +- +- EVP_CIPHER_CTX_set_padding(ctx,0); +- +- k5_iov_cursor_init(&cursor, data, num_data, DES3_BLOCK_SIZE, FALSE); +- while (k5_iov_cursor_get(&cursor, iblock)) { +- ret = EVP_DecryptUpdate(ctx, oblock, &olen, +- (unsigned char *)iblock, DES3_BLOCK_SIZE); +- if (!ret) +- break; +- k5_iov_cursor_put(&cursor, oblock); +- } +- +- if (ivec != NULL) +- memcpy(ivec->data, iblock, DES3_BLOCK_SIZE); +- +- EVP_CIPHER_CTX_free(ctx); +- +- zap(iblock, sizeof(iblock)); +- zap(oblock, sizeof(oblock)); +- +- if (ret != 1) +- return KRB5_CRYPTO_INTERNAL; +- return 0; +-} +- +-const struct krb5_enc_provider krb5int_enc_des3 = { +- DES3_BLOCK_SIZE, +- DES3_KEY_BYTES, DES3_KEY_SIZE, +- k5_des3_encrypt, +- k5_des3_decrypt, +- NULL, +- krb5int_des_init_state, +- krb5int_default_free_state +-}; +diff --git a/src/lib/gssapi/krb5/accept_sec_context.c b/src/lib/gssapi/krb5/accept_sec_context.c +index c821cc830..c5bddb1e8 100644 +--- a/src/lib/gssapi/krb5/accept_sec_context.c ++++ b/src/lib/gssapi/krb5/accept_sec_context.c +@@ -1010,7 +1010,6 @@ kg_accept_krb5(minor_status, context_handle, + } + + switch (negotiated_etype) { +- case ENCTYPE_DES3_CBC_SHA1: + case ENCTYPE_ARCFOUR_HMAC: + case ENCTYPE_ARCFOUR_HMAC_EXP: + /* RFC 4121 accidentally omits RC4-HMAC-EXP as a "not-newer" +diff --git a/src/lib/gssapi/krb5/gssapiP_krb5.h b/src/lib/gssapi/krb5/gssapiP_krb5.h +index 2e2c775d6..f5b0fede6 100644 +--- a/src/lib/gssapi/krb5/gssapiP_krb5.h ++++ b/src/lib/gssapi/krb5/gssapiP_krb5.h +@@ -125,14 +125,14 @@ enum sgn_alg { + /* SGN_ALG_DES_MAC = 0x0002, */ + /* SGN_ALG_3 = 0x0003, /\* not published *\/ */ + SGN_ALG_HMAC_MD5 = 0x0011, /* microsoft w2k; */ +- SGN_ALG_HMAC_SHA1_DES3_KD = 0x0004 ++ /* SGN_ALG_HMAC_SHA1_DES3_KD = 0x0004 */ + }; + enum seal_alg { + SEAL_ALG_NONE = 0xffff, + /* SEAL_ALG_DES = 0x0000, */ + /* SEAL_ALG_1 = 0x0001, /\* not published *\/ */ + SEAL_ALG_MICROSOFT_RC4 = 0x0010, /* microsoft w2k; */ +- SEAL_ALG_DES3KD = 0x0002 ++ /* SEAL_ALG_DES3KD = 0x0002 */ + }; + + /* for 3DES */ +@@ -153,7 +153,7 @@ enum qop { + GSS_KRB5_INTEG_C_QOP_HMAC_SHA1 = 0x0004, + GSS_KRB5_INTEG_C_QOP_MASK = 0x00ff, + /* GSS_KRB5_CONF_C_QOP_DES = 0x0100, */ +- GSS_KRB5_CONF_C_QOP_DES3_KD = 0x0200, ++ /* GSS_KRB5_CONF_C_QOP_DES3_KD = 0x0200, */ + GSS_KRB5_CONF_C_QOP_MASK = 0xff00 + }; + +diff --git a/src/lib/gssapi/krb5/k5seal.c b/src/lib/gssapi/krb5/k5seal.c +index d1cdce486..7f7146a0a 100644 +--- a/src/lib/gssapi/krb5/k5seal.c ++++ b/src/lib/gssapi/krb5/k5seal.c +@@ -136,19 +136,12 @@ make_seal_token_v1 (krb5_context context, + + /* pad the plaintext, encrypt if needed, and stick it in the token */ + +- /* initialize the the checksum */ +- switch (signalg) { +- case SGN_ALG_HMAC_SHA1_DES3_KD: +- md5cksum.checksum_type = CKSUMTYPE_HMAC_SHA1_DES3; +- break; +- case SGN_ALG_HMAC_MD5: +- md5cksum.checksum_type = CKSUMTYPE_HMAC_MD5_ARCFOUR; +- if (toktype != KG_TOK_SEAL_MSG) +- sign_usage = 15; +- break; +- default: +- abort (); +- } ++ if (signalg != SGN_ALG_HMAC_MD5) ++ abort(); ++ ++ md5cksum.checksum_type = CKSUMTYPE_HMAC_MD5_ARCFOUR; ++ if (toktype != KG_TOK_SEAL_MSG) ++ sign_usage = 15; + + code = krb5_c_checksum_length(context, md5cksum.checksum_type, &sumlen); + if (code) { +@@ -196,20 +189,8 @@ make_seal_token_v1 (krb5_context context, + gssalloc_free(t); + return(code); + } +- switch(signalg) { +- case SGN_ALG_HMAC_SHA1_DES3_KD: +- /* +- * Using key derivation, the call to krb5_c_make_checksum +- * already dealt with encrypting. +- */ +- if (md5cksum.length != cksum_size) +- abort (); +- memcpy (ptr+14, md5cksum.contents, md5cksum.length); +- break; +- case SGN_ALG_HMAC_MD5: +- memcpy (ptr+14, md5cksum.contents, cksum_size); +- break; +- } ++ ++ memcpy (ptr+14, md5cksum.contents, cksum_size); + + krb5_free_checksum_contents(context, &md5cksum); + +diff --git a/src/lib/gssapi/krb5/k5sealiov.c b/src/lib/gssapi/krb5/k5sealiov.c +index 9bb2ee109..9147bb2c7 100644 +--- a/src/lib/gssapi/krb5/k5sealiov.c ++++ b/src/lib/gssapi/krb5/k5sealiov.c +@@ -144,18 +144,11 @@ make_seal_token_v1_iov(krb5_context context, + /* pad the plaintext, encrypt if needed, and stick it in the token */ + + /* initialize the checksum */ +- switch (ctx->signalg) { +- case SGN_ALG_HMAC_SHA1_DES3_KD: +- md5cksum.checksum_type = CKSUMTYPE_HMAC_SHA1_DES3; +- break; +- case SGN_ALG_HMAC_MD5: +- md5cksum.checksum_type = CKSUMTYPE_HMAC_MD5_ARCFOUR; +- if (toktype != KG_TOK_WRAP_MSG) +- sign_usage = 15; +- break; +- default: +- abort (); +- } ++ if (ctx->signalg != SGN_ALG_HMAC_MD5) ++ abort(); ++ md5cksum.checksum_type = CKSUMTYPE_HMAC_MD5_ARCFOUR; ++ if (toktype != KG_TOK_WRAP_MSG) ++ sign_usage = 15; + + code = krb5_c_checksum_length(context, md5cksum.checksum_type, &k5_trailerlen); + if (code != 0) +@@ -177,15 +170,7 @@ make_seal_token_v1_iov(krb5_context context, + if (code != 0) + goto cleanup; + +- switch (ctx->signalg) { +- case SGN_ALG_HMAC_SHA1_DES3_KD: +- assert(md5cksum.length == ctx->cksum_size); +- memcpy(ptr + 14, md5cksum.contents, md5cksum.length); +- break; +- case SGN_ALG_HMAC_MD5: +- memcpy(ptr + 14, md5cksum.contents, ctx->cksum_size); +- break; +- } ++ memcpy(ptr + 14, md5cksum.contents, ctx->cksum_size); + + /* create the seq_num */ + code = kg_make_seq_num(context, ctx->seq, ctx->initiate ? 0 : 0xFF, +diff --git a/src/lib/gssapi/krb5/k5unseal.c b/src/lib/gssapi/krb5/k5unseal.c +index 9b183bc33..f0cc4a680 100644 +--- a/src/lib/gssapi/krb5/k5unseal.c ++++ b/src/lib/gssapi/krb5/k5unseal.c +@@ -131,28 +131,21 @@ kg_unseal_v1(context, minor_status, ctx, ptr, bodysize, message_buffer, + but few enough that we can try them all. */ + + if ((ctx->sealalg == SEAL_ALG_NONE && signalg > 1) || +- (ctx->sealalg == SEAL_ALG_DES3KD && +- signalg != SGN_ALG_HMAC_SHA1_DES3_KD)|| + (ctx->sealalg == SEAL_ALG_MICROSOFT_RC4 && + signalg != SGN_ALG_HMAC_MD5)) { + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; + } + +- switch (signalg) { +- case SGN_ALG_HMAC_MD5: +- cksum_len = 8; +- if (toktype != KG_TOK_SEAL_MSG) +- sign_usage = 15; +- break; +- case SGN_ALG_HMAC_SHA1_DES3_KD: +- cksum_len = 20; +- break; +- default: ++ if (signalg != SGN_ALG_HMAC_MD5) { + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; + } + ++ cksum_len = 8; ++ if (toktype != KG_TOK_SEAL_MSG) ++ sign_usage = 15; ++ + if ((size_t)bodysize < 14 + cksum_len) { + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; +@@ -252,64 +245,53 @@ kg_unseal_v1(context, minor_status, ctx, ptr, bodysize, message_buffer, + /* compute the checksum of the message */ + + /* initialize the the cksum */ +- switch (signalg) { +- case SGN_ALG_HMAC_MD5: +- md5cksum.checksum_type = CKSUMTYPE_HMAC_MD5_ARCFOUR; +- break; +- case SGN_ALG_HMAC_SHA1_DES3_KD: +- md5cksum.checksum_type = CKSUMTYPE_HMAC_SHA1_DES3; +- break; +- default: +- abort (); +- } ++ if (signalg != SGN_ALG_HMAC_MD5) ++ abort(); ++ md5cksum.checksum_type = CKSUMTYPE_HMAC_MD5_ARCFOUR; + + code = krb5_c_checksum_length(context, md5cksum.checksum_type, &sumlen); + if (code) + return(code); + md5cksum.length = sumlen; + +- switch (signalg) { +- default: ++ if (signalg != SGN_ALG_HMAC_MD5) { + *minor_status = 0; + return(GSS_S_DEFECTIVE_TOKEN); +- +- case SGN_ALG_HMAC_SHA1_DES3_KD: +- case SGN_ALG_HMAC_MD5: +- /* compute the checksum of the message */ +- +- /* 8 = bytes of token body to be checksummed according to spec */ +- +- if (! (data_ptr = xmalloc(8 + plainlen))) { +- if (sealalg != 0xffff) +- xfree(plain); +- if (toktype == KG_TOK_SEAL_MSG) +- gssalloc_free(token.value); +- *minor_status = ENOMEM; +- return(GSS_S_FAILURE); +- } +- +- (void) memcpy(data_ptr, ptr-2, 8); +- +- (void) memcpy(data_ptr+8, plain, plainlen); +- +- plaind.length = 8 + plainlen; +- plaind.data = data_ptr; +- code = krb5_k_make_checksum(context, md5cksum.checksum_type, +- ctx->seq, sign_usage, +- &plaind, &md5cksum); +- xfree(data_ptr); +- +- if (code) { +- if (toktype == KG_TOK_SEAL_MSG) +- gssalloc_free(token.value); +- *minor_status = code; +- return(GSS_S_FAILURE); +- } +- +- code = k5_bcmp(md5cksum.contents, ptr + 14, cksum_len); +- break; + } + ++ /* compute the checksum of the message */ ++ ++ /* 8 = bytes of token body to be checksummed according to spec */ ++ ++ if (! (data_ptr = xmalloc(8 + plainlen))) { ++ if (sealalg != 0xffff) ++ xfree(plain); ++ if (toktype == KG_TOK_SEAL_MSG) ++ gssalloc_free(token.value); ++ *minor_status = ENOMEM; ++ return(GSS_S_FAILURE); ++ } ++ ++ (void) memcpy(data_ptr, ptr-2, 8); ++ ++ (void) memcpy(data_ptr+8, plain, plainlen); ++ ++ plaind.length = 8 + plainlen; ++ plaind.data = data_ptr; ++ code = krb5_k_make_checksum(context, md5cksum.checksum_type, ++ ctx->seq, sign_usage, ++ &plaind, &md5cksum); ++ xfree(data_ptr); ++ ++ if (code) { ++ if (toktype == KG_TOK_SEAL_MSG) ++ gssalloc_free(token.value); ++ *minor_status = code; ++ return(GSS_S_FAILURE); ++ } ++ ++ code = k5_bcmp(md5cksum.contents, ptr + 14, cksum_len); ++ + krb5_free_checksum_contents(context, &md5cksum); + if (sealalg != 0xffff) + xfree(plain); +diff --git a/src/lib/gssapi/krb5/k5unsealiov.c b/src/lib/gssapi/krb5/k5unsealiov.c +index 85a9574f3..3ce2a90ce 100644 +--- a/src/lib/gssapi/krb5/k5unsealiov.c ++++ b/src/lib/gssapi/krb5/k5unsealiov.c +@@ -102,28 +102,21 @@ kg_unseal_v1_iov(krb5_context context, + } + + if ((ctx->sealalg == SEAL_ALG_NONE && signalg > 1) || +- (ctx->sealalg == SEAL_ALG_DES3KD && +- signalg != SGN_ALG_HMAC_SHA1_DES3_KD)|| + (ctx->sealalg == SEAL_ALG_MICROSOFT_RC4 && + signalg != SGN_ALG_HMAC_MD5)) { + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; + } + +- switch (signalg) { +- case SGN_ALG_HMAC_MD5: +- cksum_len = 8; +- if (toktype != KG_TOK_WRAP_MSG) +- sign_usage = 15; +- break; +- case SGN_ALG_HMAC_SHA1_DES3_KD: +- cksum_len = 20; +- break; +- default: ++ if (signalg != SGN_ALG_HMAC_MD5) { + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; + } + ++ cksum_len = 8; ++ if (toktype != KG_TOK_WRAP_MSG) ++ sign_usage = 15; ++ + /* get the token parameters */ + code = kg_get_seq_num(context, ctx->seq, ptr + 14, ptr + 6, &direction, + &seqnum); +@@ -181,16 +174,10 @@ kg_unseal_v1_iov(krb5_context context, + + /* initialize the checksum */ + +- switch (signalg) { +- case SGN_ALG_HMAC_MD5: +- md5cksum.checksum_type = CKSUMTYPE_HMAC_MD5_ARCFOUR; +- break; +- case SGN_ALG_HMAC_SHA1_DES3_KD: +- md5cksum.checksum_type = CKSUMTYPE_HMAC_SHA1_DES3; +- break; +- default: ++ if (signalg != SGN_ALG_HMAC_MD5) + abort(); +- } ++ ++ md5cksum.checksum_type = CKSUMTYPE_HMAC_MD5_ARCFOUR; + + code = krb5_c_checksum_length(context, md5cksum.checksum_type, &sumlen); + if (code != 0) { +@@ -209,18 +196,13 @@ kg_unseal_v1_iov(krb5_context context, + goto cleanup; + } + +- switch (signalg) { +- case SGN_ALG_HMAC_SHA1_DES3_KD: +- case SGN_ALG_HMAC_MD5: +- code = k5_bcmp(md5cksum.contents, ptr + 14, cksum_len); +- break; +- default: ++ if (signalg != SGN_ALG_HMAC_MD5) { + code = 0; + retval = GSS_S_DEFECTIVE_TOKEN; + goto cleanup; +- break; + } + ++ code = k5_bcmp(md5cksum.contents, ptr + 14, cksum_len); + if (code != 0) { + code = 0; + retval = GSS_S_BAD_SIG; +diff --git a/src/lib/gssapi/krb5/util_crypt.c b/src/lib/gssapi/krb5/util_crypt.c +index 80954aff7..f7d3e92c4 100644 +--- a/src/lib/gssapi/krb5/util_crypt.c ++++ b/src/lib/gssapi/krb5/util_crypt.c +@@ -97,17 +97,6 @@ kg_setup_keys(krb5_context context, krb5_gss_ctx_id_rec *ctx, krb5_key subkey, + return code; + + switch (subkey->keyblock.enctype) { +- case ENCTYPE_DES3_CBC_SHA1: +- code = kg_copy_keys(context, ctx, subkey); +- if (code != 0) +- return code; +- +- ctx->enc->keyblock.enctype = ENCTYPE_DES3_CBC_RAW; +- ctx->seq->keyblock.enctype = ENCTYPE_DES3_CBC_RAW; +- ctx->signalg = SGN_ALG_HMAC_SHA1_DES3_KD; +- ctx->cksum_size = 20; +- ctx->sealalg = SEAL_ALG_DES3KD; +- break; + case ENCTYPE_ARCFOUR_HMAC: + case ENCTYPE_ARCFOUR_HMAC_EXP: + /* RFC 4121 accidentally omits RC4-HMAC-EXP as a "not-newer" enctype, +diff --git a/src/lib/kadm5/unit-test/api.current/chpass-principal-v2.exp b/src/lib/kadm5/unit-test/api.current/chpass-principal-v2.exp +index 740425c69..6b45f5f72 100644 +--- a/src/lib/kadm5/unit-test/api.current/chpass-principal-v2.exp ++++ b/src/lib/kadm5/unit-test/api.current/chpass-principal-v2.exp +@@ -53,10 +53,10 @@ proc test200 {} { + } + + # XXX Perhaps I should actually check the key type returned. +- if {$num_keys == 5} { ++ if {$num_keys == 4} { + pass "$test" + } else { +- fail "$test: $num_keys keys, should be 5" ++ fail "$test: $num_keys keys, should be 4" + } + if { ! [cmd {kadm5_destroy $server_handle}]} { + perror "$test: unexpected failure in destroy" +diff --git a/src/lib/kadm5/unit-test/api.current/get-principal-v2.exp b/src/lib/kadm5/unit-test/api.current/get-principal-v2.exp +index 3ea1ba29b..d2c6d1afa 100644 +--- a/src/lib/kadm5/unit-test/api.current/get-principal-v2.exp ++++ b/src/lib/kadm5/unit-test/api.current/get-principal-v2.exp +@@ -143,8 +143,8 @@ proc test101_102 {rpc} { + } + + set failed 0 +- if {$num_keys != 5} { +- fail "$test: num_keys $num_keys should be 5" ++ if {$num_keys != 4} { ++ fail "$test: num_keys $num_keys should be 4" + set failed 1 + } + for {set i 0} {$i < $num_keys} {incr i} { +diff --git a/src/lib/kadm5/unit-test/api.current/randkey-principal-v2.exp b/src/lib/kadm5/unit-test/api.current/randkey-principal-v2.exp +index 2925c1c43..2f76c8b43 100644 +--- a/src/lib/kadm5/unit-test/api.current/randkey-principal-v2.exp ++++ b/src/lib/kadm5/unit-test/api.current/randkey-principal-v2.exp +@@ -46,10 +46,10 @@ proc test100 {} { + } + + # XXX Perhaps I should actually check the key type returned. +- if {$num_keys == 5} { ++ if {$num_keys == 4} { + pass "$test" + } else { +- fail "$test: $num_keys keys, should be 5" ++ fail "$test: $num_keys keys, should be 4" + } + if { ! [cmd {kadm5_destroy $server_handle}]} { + perror "$test: unexpected failure in destroy" +diff --git a/src/lib/krb5/krb/init_ctx.c b/src/lib/krb5/krb/init_ctx.c +index e7d67cca4..9a4741fa6 100644 +--- a/src/lib/krb5/krb/init_ctx.c ++++ b/src/lib/krb5/krb/init_ctx.c +@@ -59,7 +59,6 @@ + static krb5_enctype default_enctype_list[] = { + ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES128_CTS_HMAC_SHA1_96, + ENCTYPE_AES256_CTS_HMAC_SHA384_192, ENCTYPE_AES128_CTS_HMAC_SHA256_128, +- ENCTYPE_DES3_CBC_SHA1, + ENCTYPE_ARCFOUR_HMAC, + ENCTYPE_CAMELLIA128_CTS_CMAC, ENCTYPE_CAMELLIA256_CTS_CMAC, + 0 +@@ -479,8 +478,6 @@ krb5int_parse_enctype_list(krb5_context context, const char *profkey, + /* Set all enctypes in the default list. */ + for (i = 0; default_list[i]; i++) + mod_list(default_list[i], sel, weak, &list); +- } else if (strcasecmp(token, "des3") == 0) { +- mod_list(ENCTYPE_DES3_CBC_SHA1, sel, weak, &list); + } else if (strcasecmp(token, "aes") == 0) { + mod_list(ENCTYPE_AES256_CTS_HMAC_SHA1_96, sel, weak, &list); + mod_list(ENCTYPE_AES128_CTS_HMAC_SHA1_96, sel, weak, &list); +diff --git a/src/lib/krb5/krb/s4u_creds.c b/src/lib/krb5/krb/s4u_creds.c +index 504eb557f..fc5c886d6 100644 +--- a/src/lib/krb5/krb/s4u_creds.c ++++ b/src/lib/krb5/krb/s4u_creds.c +@@ -287,8 +287,6 @@ verify_s4u2self_reply(krb5_context context, + assert(req_s4u_user != NULL); + + switch (subkey->enctype) { +- case ENCTYPE_DES3_CBC_SHA1: +- case ENCTYPE_DES3_CBC_RAW: + case ENCTYPE_ARCFOUR_HMAC: + case ENCTYPE_ARCFOUR_HMAC_EXP : + not_newer = TRUE; +diff --git a/src/lib/krb5/krb/t_copy_context.c b/src/lib/krb5/krb/t_copy_context.c +index 2970a8cea..fb82daf19 100644 +--- a/src/lib/krb5/krb/t_copy_context.c ++++ b/src/lib/krb5/krb/t_copy_context.c +@@ -113,7 +113,7 @@ main(int argc, char **argv) + { + krb5_context ctx, ctx2; + krb5_plugin_initvt_fn *mods; +- const krb5_enctype etypes1[] = { ENCTYPE_DES3_CBC_SHA1, 0 }; ++ const krb5_enctype etypes1[] = { ENCTYPE_AES128_CTS_HMAC_SHA256_128, 0 }; + const krb5_enctype etypes2[] = { ENCTYPE_AES128_CTS_HMAC_SHA1_96, + ENCTYPE_AES256_CTS_HMAC_SHA1_96, 0 }; + krb5_prompt_type ptypes[] = { KRB5_PROMPT_TYPE_PASSWORD }; +diff --git a/src/lib/krb5/krb/t_etypes.c b/src/lib/krb5/krb/t_etypes.c +index f609e938a..248ffea90 100644 +--- a/src/lib/krb5/krb/t_etypes.c ++++ b/src/lib/krb5/krb/t_etypes.c +@@ -50,17 +50,6 @@ static struct { + { ENCTYPE_AES256_CTS_HMAC_SHA1_96, 0 }, + 0, 0 + }, +- /* Family followed by enctype */ +- { "aes des3-cbc-sha1-kd", +- { 0 }, +- { ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES128_CTS_HMAC_SHA1_96, +- ENCTYPE_AES256_CTS_HMAC_SHA384_192, ENCTYPE_AES128_CTS_HMAC_SHA256_128, +- ENCTYPE_DES3_CBC_SHA1, 0 }, +- { ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES128_CTS_HMAC_SHA1_96, +- ENCTYPE_AES256_CTS_HMAC_SHA384_192, ENCTYPE_AES128_CTS_HMAC_SHA256_128, +- ENCTYPE_DES3_CBC_SHA1, 0 }, +- 0, 0 +- }, + /* Family with enctype removed */ + { "camellia -camellia256-cts-cmac", + { 0 }, +@@ -69,46 +58,15 @@ static struct { + }, + /* Default set with family added and enctype removed */ + { "DEFAULT +aes -arcfour-hmac-md5", +- { ENCTYPE_ARCFOUR_HMAC, ENCTYPE_DES3_CBC_SHA1, 0 }, +- { ENCTYPE_DES3_CBC_SHA1, ENCTYPE_AES256_CTS_HMAC_SHA1_96, ++ { ENCTYPE_ARCFOUR_HMAC, 0 }, ++ { ENCTYPE_AES256_CTS_HMAC_SHA1_96, + ENCTYPE_AES128_CTS_HMAC_SHA1_96, ENCTYPE_AES256_CTS_HMAC_SHA384_192, + ENCTYPE_AES128_CTS_HMAC_SHA256_128, 0 }, +- { ENCTYPE_DES3_CBC_SHA1, +- ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES128_CTS_HMAC_SHA1_96, ++ { ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES128_CTS_HMAC_SHA1_96, + ENCTYPE_AES256_CTS_HMAC_SHA384_192, ENCTYPE_AES128_CTS_HMAC_SHA256_128, + 0 }, + 0, 0 + }, +- /* Default set with families removed and enctypes added (one redundant) */ +- { "DEFAULT -des3 rc4-hmac rc4-hmac-exp", +- { ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES128_CTS_HMAC_SHA1_96, +- ENCTYPE_DES3_CBC_SHA1, ENCTYPE_ARCFOUR_HMAC, 0 }, +- { ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES128_CTS_HMAC_SHA1_96, +- ENCTYPE_ARCFOUR_HMAC, 0 }, +- { ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES128_CTS_HMAC_SHA1_96, +- ENCTYPE_ARCFOUR_HMAC, ENCTYPE_ARCFOUR_HMAC_EXP, 0 }, +- 0, 0 +- }, +- /* Default set with family moved to front */ +- { "des3 +DEFAULT", +- { ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES128_CTS_HMAC_SHA1_96, +- ENCTYPE_DES3_CBC_SHA1, 0 }, +- { ENCTYPE_DES3_CBC_SHA1, ENCTYPE_AES256_CTS_HMAC_SHA1_96, +- ENCTYPE_AES128_CTS_HMAC_SHA1_96, 0 }, +- { ENCTYPE_DES3_CBC_SHA1, ENCTYPE_AES256_CTS_HMAC_SHA1_96, +- ENCTYPE_AES128_CTS_HMAC_SHA1_96, 0 }, +- 0, 0 +- }, +- /* Two families with default set removed (exotic case), enctype added */ +- { "aes +rc4 -DEFaulT des3-hmac-sha1", +- { ENCTYPE_AES128_CTS_HMAC_SHA1_96, ENCTYPE_DES3_CBC_SHA1, +- ENCTYPE_ARCFOUR_HMAC, 0 }, +- { ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES256_CTS_HMAC_SHA384_192, +- ENCTYPE_AES128_CTS_HMAC_SHA256_128, ENCTYPE_DES3_CBC_SHA1, 0 }, +- { ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES256_CTS_HMAC_SHA384_192, +- ENCTYPE_AES128_CTS_HMAC_SHA256_128, ENCTYPE_DES3_CBC_SHA1, 0 }, +- 0, 0 +- }, + /* Test krb5_set_default_in_tkt_ktypes */ + { NULL, + { ENCTYPE_AES256_CTS_HMAC_SHA1_96, 0 }, +diff --git a/src/lib/krb5/os/t_trace.c b/src/lib/krb5/os/t_trace.c +index 10ba8d0ac..24064ffcf 100644 +--- a/src/lib/krb5/os/t_trace.c ++++ b/src/lib/krb5/os/t_trace.c +@@ -65,8 +65,8 @@ main (int argc, char *argv[]) + krb5_principal princ = &principal_data; + krb5_pa_data padata, padata2, **padatap; + krb5_enctype enctypes[4] = { +- ENCTYPE_DES3_CBC_SHA, ENCTYPE_ARCFOUR_HMAC_EXP, ENCTYPE_UNKNOWN, +- ENCTYPE_NULL}; ++ ENCTYPE_AES128_CTS_HMAC_SHA1_96, ENCTYPE_ARCFOUR_HMAC_EXP, ++ ENCTYPE_UNKNOWN, ENCTYPE_NULL}; + krb5_ccache ccache; + krb5_keytab keytab; + krb5_creds creds; +diff --git a/src/lib/krb5/os/t_trace.ref b/src/lib/krb5/os/t_trace.ref +index 044a66999..98fb14f3f 100644 +--- a/src/lib/krb5/os/t_trace.ref ++++ b/src/lib/krb5/os/t_trace.ref +@@ -41,7 +41,7 @@ int, krb5_principal type: ? + krb5_pa_data **, display list of padata type numbers: PA-PW-SALT (3), 0 + krb5_pa_data **, display list of padata type numbers: (empty) + krb5_enctype, display shortest name of enctype: aes128-cts +-krb5_enctype *, display list of enctypes: 5, rc4-hmac-exp, 511 ++krb5_enctype *, display list of enctypes: aes128-cts, rc4-hmac-exp, 511 + krb5_enctype *, display list of enctypes: (empty) + krb5_ccache, display type:name: FILE:/path/to/ccache + krb5_keytab, display name: FILE:/etc/krb5.keytab +diff --git a/src/plugins/preauth/pkinit/pkcs11.h b/src/plugins/preauth/pkinit/pkcs11.h +index e3d284631..586661bb7 100644 +--- a/src/plugins/preauth/pkinit/pkcs11.h ++++ b/src/plugins/preauth/pkinit/pkcs11.h +@@ -339,9 +339,9 @@ typedef unsigned long ck_key_type_t; + #define CKK_GENERIC_SECRET (0x10) + #define CKK_RC2 (0x11) + #define CKK_RC4 (0x12) +-#define CKK_DES (0x13) +-#define CKK_DES2 (0x14) +-#define CKK_DES3 (0x15) ++/* #define CKK_DES (0x13) */ ++/* #define CKK_DES2 (0x14) */ ++/* #define CKK_DES3 (0x15) */ + #define CKK_CAST (0x16) + #define CKK_CAST3 (0x17) + #define CKK_CAST128 (0x18) +diff --git a/src/plugins/preauth/pkinit/pkinit_clnt.c b/src/plugins/preauth/pkinit/pkinit_clnt.c +index 1a642139a..2f0431991 100644 +--- a/src/plugins/preauth/pkinit/pkinit_clnt.c ++++ b/src/plugins/preauth/pkinit/pkinit_clnt.c +@@ -212,14 +212,6 @@ pkinit_as_req_create(krb5_context context, + auth_pack.clientPublicValue = &info; + auth_pack.supportedKDFs = (krb5_data **)supported_kdf_alg_ids; + +- /* add List of CMS algorithms */ +- retval = create_krb5_supportedCMSTypes(context, plgctx->cryptoctx, +- reqctx->cryptoctx, +- reqctx->idctx, &cmstypes); +- auth_pack.supportedCMSTypes = cmstypes; +- if (retval) +- goto cleanup; +- + switch(protocol) { + case DH_PROTOCOL: + TRACE_PKINIT_CLIENT_REQ_DH(context); +diff --git a/src/plugins/preauth/pkinit/pkinit_crypto.h b/src/plugins/preauth/pkinit/pkinit_crypto.h +index 8064a07d0..a291889b0 100644 +--- a/src/plugins/preauth/pkinit/pkinit_crypto.h ++++ b/src/plugins/preauth/pkinit/pkinit_crypto.h +@@ -380,18 +380,6 @@ krb5_error_code server_process_dh + unsigned int *server_key_len_out); /* OUT + receives length of DH secret key */ + +-/* +- * this functions takes in crypto specific representation of +- * supportedCMSTypes and creates a list of +- * krb5_algorithm_identifier +- */ +-krb5_error_code create_krb5_supportedCMSTypes +- (krb5_context context, /* IN */ +- pkinit_plg_crypto_context plg_cryptoctx, /* IN */ +- pkinit_req_crypto_context req_cryptoctx, /* IN */ +- pkinit_identity_crypto_context id_cryptoctx, /* IN */ +- krb5_algorithm_identifier ***supportedCMSTypes); /* OUT */ +- + /* + * this functions takes in crypto specific representation of + * trustedCertifiers and creates a list of +diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c +index 8c7fd0cca..52976895b 100644 +--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c ++++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c +@@ -5487,44 +5487,6 @@ cleanup: + return retval; + } + +-krb5_error_code +-create_krb5_supportedCMSTypes(krb5_context context, +- pkinit_plg_crypto_context plg_cryptoctx, +- pkinit_req_crypto_context req_cryptoctx, +- pkinit_identity_crypto_context id_cryptoctx, +- krb5_algorithm_identifier ***oids) +-{ +- +- krb5_error_code retval = ENOMEM; +- krb5_algorithm_identifier **loids = NULL; +- krb5_data des3oid = {0, 8, "\x2A\x86\x48\x86\xF7\x0D\x03\x07" }; +- +- *oids = NULL; +- loids = malloc(2 * sizeof(krb5_algorithm_identifier *)); +- if (loids == NULL) +- goto cleanup; +- loids[1] = NULL; +- loids[0] = malloc(sizeof(krb5_algorithm_identifier)); +- if (loids[0] == NULL) { +- free(loids); +- goto cleanup; +- } +- retval = pkinit_copy_krb5_data(&loids[0]->algorithm, &des3oid); +- if (retval) { +- free(loids[0]); +- free(loids); +- goto cleanup; +- } +- loids[0]->parameters.length = 0; +- loids[0]->parameters.data = NULL; +- +- *oids = loids; +- retval = 0; +-cleanup: +- +- return retval; +-} +- + krb5_error_code + create_krb5_trustedCertifiers(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, +diff --git a/src/plugins/preauth/pkinit/pkinit_kdf_test.c b/src/plugins/preauth/pkinit/pkinit_kdf_test.c +index 7acbd0d28..cd998a29a 100644 +--- a/src/plugins/preauth/pkinit/pkinit_kdf_test.c ++++ b/src/plugins/preauth/pkinit/pkinit_kdf_test.c +@@ -49,7 +49,6 @@ char eighteen_bs[9]; + char party_u_name[] = "lha@SU.SE"; + char party_v_name[] = "krbtgt/SU.SE@SU.SE"; + int enctype_aes = ENCTYPE_AES256_CTS_HMAC_SHA1_96; +-int enctype_des3 = ENCTYPE_DES3_CBC_SHA1; + const krb5_data lha_data = DATA_FROM_STRING("lha"); + + krb5_octet key1_hex[] = +@@ -185,36 +184,6 @@ main(int argc, char **argv) + goto cleanup; + } + +- /* TEST 3: SHA-512/DES3 */ +- /* set up algorithm id */ +- alg_id.algorithm.data = (char *)krb5_pkinit_sha512_oid; +- alg_id.algorithm.length = krb5_pkinit_sha512_oid_len; +- +- enctype = enctype_des3; +- +- /* call pkinit_alg_agility_kdf() with test vector values*/ +- if (0 != (retval = pkinit_alg_agility_kdf(context, &secret, +- &alg_id.algorithm, +- u_principal, v_principal, +- enctype, &as_req, &pk_as_rep, +- &key_block))) { +- printf("ERROR in pkinit_kdf_test: kdf call failed, retval = %d", +- retval); +- goto cleanup; +- } +- +- /* compare key to expected key value */ +- +- if ((key_block.length == sizeof(key3_hex)) && +- (0 == memcmp(key_block.contents, key3_hex, key_block.length))) { +- printf("SUCCESS: TEST 3 (SHA-512/DES3), Correct key value generated.\n"); +- retval = 0; +- } else { +- printf("FAILURE: TEST 2 (SHA-512/DES3), Incorrect key value generated!\n"); +- retval = 1; +- goto cleanup; +- } +- + cleanup: + /* release all allocated resources, whether good or bad return */ + free(secret.data); +diff --git a/src/plugins/preauth/spake/t_vectors.c b/src/plugins/preauth/spake/t_vectors.c +index 2279202d3..96b0307d7 100644 +--- a/src/plugins/preauth/spake/t_vectors.c ++++ b/src/plugins/preauth/spake/t_vectors.c +@@ -56,31 +56,6 @@ struct test { + const char *K2; + const char *K3; + } tests[] = { +- { ENCTYPE_DES3_CBC_SHA1, SPAKE_GROUP_EDWARDS25519, +- /* initial key, w, x, y, T, S, K */ +- "850BB51358548CD05E86768C313E3BFEF7511937DCF72C3E", +- "686D84730CB8679AE95416C6567C6A63F2C9CEF124F7A3371AE81E11CAD42A37", +- "201012D07BFD48DDFA33C4AAC4FB1E229FB0D043CFE65EBFB14399091C71A723", +- "500B294797B8B042ACA1BEDC0F5931A4F52C537B3608B2D05CC8A2372F439F25", +- "18F511E750C97B592ACD30DB7D9E5FCA660389102E6BF610C1BFBED4616C8362", +- "5D10705E0D1E43D5DBF30240CCFBDE4A0230C70D4C79147AB0B317EDAD2F8AE7", +- "25BDE0D875F0FEB5755F45BA5E857889D916ECF7476F116AA31DC3E037EC4292", +- /* support, challenge, thash, body */ +- "A0093007A0053003020101", +- "A1363034A003020101A122042018F511E750C97B592ACD30DB7D9E5FCA660389" +- "102E6BF610C1BFBED4616C8362A20930073005A003020101", +- "EAAA08807D0616026FF51C849EFBF35BA0CE3C5300E7D486DA46351B13D4605B", +- "3075A00703050000000000A1143012A003020101A10B30091B07726165627572" +- "6EA2101B0E415448454E412E4D49542E454455A3233021A003020102A11A3018" +- "1B066B72627467741B0E415448454E412E4D49542E454455A511180F31393730" +- "303130313030303030305AA703020100A8053003020110", +- /* K'[0], K'[1], K'[2], K'[3] */ +- "BAF12FAE7CD958CBF1A29BFBC71F89CE49E03E295D89DAFD", +- "64F73DD9C41908206BCEC1F719026B574F9D13463D7A2520", +- "0454520B086B152C455829E6BAEFF78A61DFE9E3D04A895D", +- "4A92260B25E3EF94C125D5C24C3E5BCED5B37976E67F25C4", +- }, +- + { ENCTYPE_ARCFOUR_HMAC, SPAKE_GROUP_EDWARDS25519, + /* initial key, w, x, y, T, S, K */ + "8846F7EAEE8FB117AD06BDD830B7586C", +diff --git a/src/tests/dejagnu/config/default.exp b/src/tests/dejagnu/config/default.exp +index b047ef1f7..4d8c917cd 100644 +--- a/src/tests/dejagnu/config/default.exp ++++ b/src/tests/dejagnu/config/default.exp +@@ -15,8 +15,6 @@ set timeout 100 + set stty_init {erase \^h kill \^u} + set env(TERM) dumb + +-set des3_krbtgt 0 +- + if { [string length $VALGRIND] } { + rename spawn valgrind_aux_spawn + proc spawn { args } { +@@ -105,17 +103,9 @@ if { $PRIOCNTL_HACK } { + # particularly with regards to encryption types. + + set passes { +- { +- des3 +- mode=udp +- des3_krbtgt=1 +- {supported_enctypes=des3-cbc-sha1:normal} +- {dummy=[verbose -log "DES3 TGT, DES3 enctype"]} +- } + { + aes-only + mode=udp +- des3_krbtgt=0 + {supported_enctypes=aes256-cts-hmac-sha1-96:normal} + {permitted_enctypes(kdc)=aes256-cts-hmac-sha1-96} + {permitted_enctypes(client)=aes256-cts-hmac-sha1-96} +@@ -130,7 +120,6 @@ set passes { + { + aes-sha2-only + mode=udp +- des3_krbtgt=0 + {supported_enctypes=aes256-sha2:normal} + {permitted_enctypes(kdc)=aes256-sha2} + {permitted_enctypes(replica)=aes256-sha2} +@@ -146,7 +135,6 @@ set passes { + { + camellia-only + mode=udp +- des3_krbtgt=0 + {supported_enctypes=camellia256-cts:normal} + {permitted_enctypes(kdc)=camellia256-cts} + {permitted_enctypes(replica)=camellia256-cts} +@@ -159,32 +147,9 @@ set passes { + {master_key_type=camellia256-cts} + {dummy=[verbose -log "Camellia-256 enctype"]} + } +- { +- aes-des3 +- mode=udp +- des3_krbtgt=0 +- {supported_enctypes=aes256-cts-hmac-sha1-96:normal des3-cbc-sha1:normal} +- {permitted_enctypes(kdc)=aes256-cts-hmac-sha1-96 des3-cbc-sha1} +- {permitted_enctypes(client)=aes256-cts-hmac-sha1-96 des3-cbc-sha1} +- {permitted_enctypes(server)=aes256-cts-hmac-sha1-96 des3-cbc-sha1} +- {master_key_type=aes256-cts-hmac-sha1-96} +- {dummy=[verbose -log "AES + DES3 + DES enctypes"]} +- } +- { +- aes-des3tgt +- mode=udp +- des3_krbtgt=1 +- {supported_enctypes=aes256-cts-hmac-sha1-96:normal des3-cbc-sha1:normal} +- {permitted_enctypes(kdc)=aes256-cts-hmac-sha1-96 des3-cbc-sha1} +- {permitted_enctypes(client)=aes256-cts-hmac-sha1-96 des3-cbc-sha1} +- {permitted_enctypes(server)=aes256-cts-hmac-sha1-96 des3-cbc-sha1} +- {master_key_type=aes256-cts-hmac-sha1-96} +- {dummy=[verbose -log "AES enctypes, DES3 TGT"]} +- } + { + all-enctypes + mode=udp +- des3_krbtgt=0 + {allow_weak_crypto(kdc)=false} + {allow_weak_crypto(replica)=false} + {allow_weak_crypto(client)=false} +@@ -946,7 +911,6 @@ proc setup_kerberos_db { standalone } { + global REALMNAME KDB5_UTIL KADMIN_LOCAL KEY + global tmppwd hostname + global spawn_id +- global des3_krbtgt + global multipass_name last_passname_db + + set failall 0 +@@ -1143,48 +1107,6 @@ proc setup_kerberos_db { standalone } { + } + } + +- if $des3_krbtgt { +- # Set the TGT key to DES3. +- set test "kadmin.local TGT to DES3" +- set body { +- if $failall { +- break +- } +- spawn $KADMIN_LOCAL -r $REALMNAME -e des3-cbc-sha1:normal +- verbose "starting $test" +- expect_after $def_exp_after +- +- expect "kadmin.local: " +- send "cpw -randkey krbtgt/$REALMNAME@$REALMNAME\r" +- # It echos... +- expect "cpw -randkey krbtgt/$REALMNAME@$REALMNAME\r" +- expect { +- "Key for \"krbtgt/$REALMNAME@$REALMNAME\" randomized." { } +- } +- expect "kadmin.local: " +- send "quit\r" +- expect eof +- catch expect_after +- if ![check_exit_status kadmin_local] { +- break +- } +- } +- set ret [catch $body] +- catch "expect eof" +- catch expect_after +- if $ret { +- set failall 1 +- if $standalone { +- fail $test +- } else { +- delete_db +- } +- } else { +- if $standalone { +- pass $test +- } +- } +- } + envstack_pop + + # create the admin database lock file +diff --git a/src/tests/dejagnu/krb-standalone/kprop.exp b/src/tests/dejagnu/krb-standalone/kprop.exp +index f71ee8638..8c08cf42f 100644 +--- a/src/tests/dejagnu/krb-standalone/kprop.exp ++++ b/src/tests/dejagnu/krb-standalone/kprop.exp +@@ -54,7 +54,7 @@ proc doit { } { + global REALMNAME KEY + global KADMIN_LOCAL KTUTIL KDB5_UTIL KPROPLOG KPROP kpropd_spawn_id + global hostname tmppwd spawn_id timeout +- global KRBIV supported_enctypes portbase mode ulog des3_krbtgt ++ global KRBIV supported_enctypes portbase mode ulog + + # Delete any db, ulog files + delete_db +diff --git a/src/tests/gssapi/t_enctypes.py b/src/tests/gssapi/t_enctypes.py +index 7494d7fcd..2f95d8996 100755 +--- a/src/tests/gssapi/t_enctypes.py ++++ b/src/tests/gssapi/t_enctypes.py +@@ -1,24 +1,17 @@ + from k5test import * + +-# Define some convenience abbreviations for enctypes we will see in +-# test program output. For background, aes256 and aes128 are "CFX +-# enctypes", meaning that they imply support for RFC 4121, while des3 +-# and rc4 are not. DES3 keys will appear as 'des3-cbc-raw' in +-# t_enctypes output because that's how GSSAPI does raw triple-DES +-# encryption without the RFC3961 framing. ++# Define some convenience abbreviations for enctypes we will see in test ++# program output. For background, aes256 and aes128 are "CFX enctypes", ++# meaning that they imply support for RFC 4121, while rc4 does not. + aes256 = 'aes256-cts-hmac-sha1-96' + aes128 = 'aes128-cts-hmac-sha1-96' +-des3 = 'des3-cbc-sha1' +-d_des3 = 'DEPRECATED:des3-cbc-sha1' +-des3raw = 'des3-cbc-raw' +-d_des3raw = 'DEPRECATED:des3-cbc-raw' + rc4 = 'arcfour-hmac' + d_rc4 = 'DEPRECATED:arcfour-hmac' + + # These tests make assumptions about the default enctype lists, so set + # them explicitly rather than relying on the library defaults. +-supp='aes256-cts:normal aes128-cts:normal des3-cbc-sha1:normal rc4-hmac:normal' +-conf = {'libdefaults': {'permitted_enctypes': 'aes des3 rc4'}, ++supp='aes256-cts:normal aes128-cts:normal rc4-hmac:normal' ++conf = {'libdefaults': {'permitted_enctypes': 'aes rc4'}, + 'realms': {'$realm': {'supported_enctypes': supp}}} + realm = K5Realm(krb5_conf=conf) + shutil.copyfile(realm.ccache, os.path.join(realm.testdir, 'save')) +@@ -87,19 +80,12 @@ test('both aes128', 'aes128-cts', 'aes128-cts', + test_err('acc aes128', None, 'aes128-cts', + 'Encryption type aes256-cts-hmac-sha1-96 not permitted') + +-# If the initiator constrains the permitted session enctypes to des3, +-# no acceptor subkey will be generated because we can't upgrade to a +-# CFX enctype. +-test('init des3', 'des3', None, +- tktenc=aes256, tktsession=d_des3, +- proto='rfc1964', isubkey=des3raw, asubkey=None) +- + # Force the ticket session key to be rc4, so we can test some subkey + # upgrade cases. The ticket encryption key remains aes256. + realm.run([kadminl, 'setstr', realm.host_princ, 'session_enctypes', 'rc4']) + + # With no arguments, the initiator should send an upgrade list of +-# [aes256 aes128 des3] and the acceptor should upgrade to an aes256 ++# [aes256 aes128] and the acceptor should upgrade to an aes256 + # subkey. + test('upgrade noargs', None, None, + tktenc=aes256, tktsession=d_rc4, +@@ -115,13 +101,6 @@ test('upgrade init aes128+rc4', 'aes128-cts rc4', None, + tktenc=aes256, tktsession=d_rc4, + proto='cfx', isubkey=rc4, asubkey=aes128) + +-# If the initiator permits rc4 but prefers des3, it will send an +-# upgrade list of [des3], but the acceptor won't generate a subkey +-# because des3 isn't a CFX enctype. +-test('upgrade init des3+rc4', 'des3 rc4', None, +- tktenc=aes256, tktsession=d_rc4, +- proto='rfc1964', isubkey=rc4, asubkey=None) +- + # If the acceptor permits only aes128, subkey negotiation will fail + # because the ticket session key and initiator subkey are + # non-permitted. (This is unfortunate if the acceptor's restriction +diff --git a/src/tests/gssapi/t_invalid.c b/src/tests/gssapi/t_invalid.c +index 9876a11e6..fb8fe5511 100644 +--- a/src/tests/gssapi/t_invalid.c ++++ b/src/tests/gssapi/t_invalid.c +@@ -84,18 +84,6 @@ struct test { + size_t toklen; + const char *token; + } tests[] = { +- { +- ENCTYPE_DES3_CBC_SHA1, ENCTYPE_DES3_CBC_RAW, +- SEAL_ALG_DES3KD, SGN_ALG_HMAC_SHA1_DES3_KD, 20, +- 24, +- "\x4F\xEA\x19\x19\x5E\x0E\x10\xDF\x3D\x29\xB5\x13\x8F\x01\xC7\xA7" +- "\x92\x3D\x38\xF7\x26\x73\x0D\x6D", +- 65, +- "\x60\x3F\x06\x09\x2A\x86\x48\x86\xF7\x12\x01\x02\x02\x02\x01\x04" +- "\x00\x02\x00\xFF\xFF\xEB\xF3\x9A\x89\x24\x57\xB8\x63\x95\x25\xE8" +- "\x6E\x8E\x79\xE6\x2E\xCA\xD3\xFF\x57\x9F\x8C\xAB\xEF\xDD\x28\x10" +- "\x2F\x93\x21\x2E\xF2\x52\xB6\x6F\xA8\xBB\x8A\x6D\xAA\x6F\xB7\xF4\xD4" +- }, + { + ENCTYPE_ARCFOUR_HMAC, ENCTYPE_ARCFOUR_HMAC, + SEAL_ALG_MICROSOFT_RC4, SGN_ALG_HMAC_MD5, 8, +diff --git a/src/tests/gssapi/t_pcontok.c b/src/tests/gssapi/t_pcontok.c +index 7368f752f..bf22bd3da 100644 +--- a/src/tests/gssapi/t_pcontok.c ++++ b/src/tests/gssapi/t_pcontok.c +@@ -43,7 +43,6 @@ + #include "k5-int.h" + #include "common.h" + +-#define SGN_ALG_HMAC_SHA1_DES3_KD 0x04 + #define SGN_ALG_HMAC_MD5 0x11 + + /* +@@ -77,17 +76,12 @@ make_delete_token(gss_krb5_lucid_context_v1_t *lctx, gss_buffer_desc *out) + ret = krb5_k_create_key(context, &seqkb, &seq); + check_k5err(context, "krb5_k_create_key", ret); + +- if (signalg == SGN_ALG_HMAC_SHA1_DES3_KD) { +- cktype = CKSUMTYPE_HMAC_SHA1_DES3; +- cksize = 20; +- ckusage = 23; +- } else if (signalg == SGN_ALG_HMAC_MD5) { +- cktype = CKSUMTYPE_HMAC_MD5_ARCFOUR; +- cksize = 8; +- ckusage = 15; +- } else { ++ if (signalg != SGN_ALG_HMAC_MD5) + abort(); +- } ++ ++ cktype = CKSUMTYPE_HMAC_MD5_ARCFOUR; ++ cksize = 8; ++ ckusage = 15; + + tlen = 20 + mech_krb5.length + cksize; + token = malloc(tlen); +diff --git a/src/tests/gssapi/t_prf.c b/src/tests/gssapi/t_prf.c +index f71774cdc..d1857c433 100644 +--- a/src/tests/gssapi/t_prf.c ++++ b/src/tests/gssapi/t_prf.c +@@ -41,13 +41,6 @@ static struct { + const char *key2; + const char *out2; + } tests[] = { +- { ENCTYPE_DES3_CBC_SHA1, +- "70378A19CD64134580C27C0115D6B34A1CF2FEECEF9886A2", +- "9F8D127C520BB826BFF3E0FE5EF352389C17E0C073D9" +- "AC4A333D644D21BA3EF24F4A886D143F85AC9F6377FB", +- "3452A167DF1094BA1089E0A20E9E51ABEF1525922558B69E", +- "6BF24FABC858F8DD9752E4FCD331BB831F238B5BE190" +- "4EEA42E38F7A60C588F075C5C96A67E7F8B7BD0AECF4" }, + { ENCTYPE_ARCFOUR_HMAC, + "3BB3AE288C12B3B9D06B208A4151B3B6", + "9AEA11A3BCF3C53F1F91F5A0BA2132E2501ADF5F3C28" +diff --git a/src/tests/t_authdata.py b/src/tests/t_authdata.py +index c589adf2a..4fbdbec05 100644 +--- a/src/tests/t_authdata.py ++++ b/src/tests/t_authdata.py +@@ -174,7 +174,7 @@ realm.run([kvno, 'restricted']) + # preferred krbtgt enctype changes. + mark('#8139 regression test') + realm.kinit(realm.user_princ, password('user'), ['-f']) +-realm.run([kadminl, 'cpw', '-randkey', '-keepold', '-e', 'des3-cbc-sha1', ++realm.run([kadminl, 'cpw', '-randkey', '-keepold', '-e', 'aes256-sha2', + realm.krbtgt_princ]) + realm.run(['./forward']) + realm.run([kvno, realm.host_princ]) +diff --git a/src/tests/t_etype_info.py b/src/tests/t_etype_info.py +index 2a052fc17..ace0edc3c 100644 +--- a/src/tests/t_etype_info.py ++++ b/src/tests/t_etype_info.py +@@ -1,6 +1,6 @@ + from k5test import * + +-supported_enctypes = 'aes128-cts des3-cbc-sha1 rc4-hmac' ++supported_enctypes = 'aes128-cts rc4-hmac' + conf = {'libdefaults': {'allow_weak_crypto': 'true'}, + 'realms': {'$realm': {'supported_enctypes': supported_enctypes}}} + realm = K5Realm(create_host=False, get_creds=False, krb5_conf=conf) +@@ -24,9 +24,9 @@ def test_etinfo(princ, enctypes, expected_lines): + # With no newer enctypes in the request, PA-ETYPE-INFO2, + # PA-ETYPE-INFO, and PA-PW-SALT appear in the AS-REP, each listing one + # key for the most preferred matching enctype. +-test_etinfo('user', 'rc4-hmac-exp des3 rc4', +- ['asrep etype_info2 des3-cbc-sha1 KRBTEST.COMuser', +- 'asrep etype_info des3-cbc-sha1 KRBTEST.COMuser', ++test_etinfo('user', 'rc4-hmac-exp rc4', ++ ['asrep etype_info2 rc4-hmac KRBTEST.COMuser', ++ 'asrep etype_info rc4-hmac KRBTEST.COMuser', + 'asrep pw_salt KRBTEST.COMuser']) + + # With a newer enctype in the request (even if it is not the most +@@ -37,9 +37,9 @@ test_etinfo('user', 'rc4 aes256-cts', + + # In preauth-required errors, PA-PW-SALT does not appear, but the same + # etype-info2 values are expected. +-test_etinfo('preauthuser', 'rc4-hmac-exp des3 rc4', +- ['error etype_info2 des3-cbc-sha1 KRBTEST.COMpreauthuser', +- 'error etype_info des3-cbc-sha1 KRBTEST.COMpreauthuser']) ++test_etinfo('preauthuser', 'rc4-hmac-exp rc4', ++ ['error etype_info2 rc4-hmac KRBTEST.COMpreauthuser', ++ 'error etype_info rc4-hmac KRBTEST.COMpreauthuser']) + test_etinfo('preauthuser', 'rc4 aes256-cts', + ['error etype_info2 rc4-hmac KRBTEST.COMpreauthuser']) + +@@ -48,8 +48,8 @@ test_etinfo('preauthuser', 'rc4 aes256-cts', + # (to allow for preauth mechs which don't depend on long-term keys). + # An AS-REP cannot be generated without preauth as there is no reply + # key. +-test_etinfo('rc4user', 'des3', []) +-test_etinfo('nokeyuser', 'des3', []) ++test_etinfo('rc4user', 'aes128-cts', []) ++test_etinfo('nokeyuser', 'aes128-cts', []) + + # Verify that etype-info2 is included in a MORE_PREAUTH_DATA_REQUIRED + # error if the client does optimistic preauth. +diff --git a/src/tests/t_keyrollover.py b/src/tests/t_keyrollover.py +index 2c825a692..f29e0d550 100755 +--- a/src/tests/t_keyrollover.py ++++ b/src/tests/t_keyrollover.py +@@ -37,9 +37,9 @@ realm.run([klist, '-e'], expected_msg=msg) + + # Test that the KDC only accepts the first enctype for a kvno, for a + # local-realm TGS request. To set this up, we abuse an edge-case +-# behavior of modprinc -kvno. First, set up a DES3 krbtgt entry at ++# behavior of modprinc -kvno. First, set up an aes128-sha2 krbtgt entry at + # kvno 1 and cache a krbtgt ticket. +-realm.run([kadminl, 'cpw', '-randkey', '-e', 'des3-cbc-sha1', ++realm.run([kadminl, 'cpw', '-randkey', '-e', 'aes128-cts-hmac-sha256-128', + realm.krbtgt_princ]) + realm.run([kadminl, 'modprinc', '-kvno', '1', realm.krbtgt_princ]) + realm.kinit(realm.user_princ, password('user')) +@@ -50,9 +50,9 @@ realm.run([kadminl, 'cpw', '-randkey', '-keepold', '-e', 'aes256-cts', + realm.run([kadminl, 'modprinc', '-kvno', '1', realm.krbtgt_princ]) + out = realm.run([kadminl, 'getprinc', realm.krbtgt_princ]) + if 'vno 1, aes256-cts' not in out or \ +- 'vno 1, DEPRECATED:des3-cbc-sha1' not in out: ++ 'vno 1, aes128-cts-hmac-sha256-128' not in out: + fail('keyrollover: setup for TGS enctype test failed') +-# Now present the DES3 ticket to the KDC and make sure it's rejected. ++# Now present the aes128-sha2 ticket to the KDC and make sure it's rejected. + realm.run([kvno, realm.host_princ], expected_code=1) + + realm.stop() +diff --git a/src/tests/t_mkey.py b/src/tests/t_mkey.py +index 99273c907..f84041ca4 100755 +--- a/src/tests/t_mkey.py ++++ b/src/tests/t_mkey.py +@@ -7,7 +7,6 @@ import struct + # default enctype for master keys. + aes256 = 'aes256-cts-hmac-sha1-96' + aes128 = 'aes128-cts-hmac-sha1-96' +-des3 = 'des3-cbc-sha1' + defetype = aes256 + + realm = K5Realm(create_host=False, start_kadmind=True) +@@ -300,40 +299,6 @@ if 'Decrypt integrity check failed' in out or 'added to keytab' not in out: + + realm.stop() + +-# Load a dump file created with krb5 1.6, before the master key +-# rollover changes were introduced. Write out an old-format stash +-# file consistent with the dump's master password ("footes"). The K/M +-# entry in this database will not have actkvno tl-data because it was +-# created prior to master key rollover support. Verify that: +-# 1. We can access the database using the old-format stash file. +-# 2. list_mkeys displays the same list as for a post-1.7 KDB. +-mark('pre-1.7 stash file') +-dumpfile = os.path.join(srctop, 'tests', 'dumpfiles', 'dump.16') +-os.remove(stash_file) +-f = open(stash_file, 'wb') +-f.write(struct.pack('=HL24s', 16, 24, +- b'\xF8\x3E\xFB\xBA\x6D\x80\xD9\x54\xE5\x5D\xF2\xE0' +- b'\x94\xAD\x6D\x86\xB5\x16\x37\xEC\x7C\x8A\xBC\x86')) +-f.close() +-realm.run([kdb5_util, 'load', dumpfile]) +-nprincs = len(realm.run([kadminl, 'listprincs']).splitlines()) +-check_mkvno('K/M', 1) +-check_mkey_list((1, des3, True, True)) +- +-# Create a new master key and verify that, without actkvkno tl-data: +-# 1. list_mkeys displays the same as for a post-1.7 KDB. +-# 2. update_princ_encryption still targets mkvno 1. +-# 3. libkadm5 still uses mkvno 1 for key changes. +-# 4. use_mkey creates the same list as for a post-1.7 KDB. +-mark('rollover from pre-1.7 KDB') +-add_mkey([]) +-check_mkey_list((2, defetype, False, False), (1, des3, True, True)) +-update_princ_encryption(False, 1, 0, nprincs - 1) +-realm.run([kadminl, 'addprinc', '-randkey', realm.user_princ]) +-check_mkvno(realm.user_princ, 1) +-realm.run([kdb5_util, 'use_mkey', '2', 'now-1day']) +-check_mkey_list((2, defetype, True, True), (1, des3, True, False)) +- + # Regression test for #8395. Purge the master key and verify that a + # master key fetch does not segfault. + mark('#8395 regression test') +diff --git a/src/tests/t_salt.py b/src/tests/t_salt.py +index 65084bbf3..55ca89745 100755 +--- a/src/tests/t_salt.py ++++ b/src/tests/t_salt.py +@@ -16,13 +16,12 @@ def test_salt(realm, e1, salt, e2): + + # Enctype/salt pairs chosen with non-default salt types. + # The enctypes are mostly arbitrary. +-salts = [('des3-cbc-sha1', 'norealm'), ++salts = [('aes128-cts-hmac-sha1-96', 'norealm'), + ('arcfour-hmac', 'onlyrealm'), + ('aes128-cts-hmac-sha1-96', 'special')] + # These enctypes are chosen to cover the different string-to-key routines. + # Omit ":normal" from aes256 to check that salttype defaulting works. +-second_kstypes = ['aes256-cts-hmac-sha1-96', 'arcfour-hmac:normal', +- 'des3-cbc-sha1:normal'] ++second_kstypes = ['aes256-cts-hmac-sha1-96', 'arcfour-hmac:normal'] + + # Test using different salt types in a principal's key list. + # Parameters from one key in the list must not leak over to later ones. +diff --git a/src/util/k5test.py b/src/util/k5test.py +index 442a4e4f7..eea92275d 100644 +--- a/src/util/k5test.py ++++ b/src/util/k5test.py +@@ -1299,13 +1299,6 @@ _passes = [ + # No special settings; exercises AES256. + ('default', None, None, None), + +- # Exercise the DES3 enctype. +- ('des3', None, +- {'libdefaults': {'permitted_enctypes': 'des3'}}, +- {'realms': {'$realm': { +- 'supported_enctypes': 'des3-cbc-sha1:normal', +- 'master_key_type': 'des3-cbc-sha1'}}}), +- + # Exercise the arcfour enctype. + ('arcfour', None, + {'libdefaults': {'permitted_enctypes': 'rc4'}}, +diff --git a/src/windows/leash/htmlhelp/html/Encryption_Types.htm b/src/windows/leash/htmlhelp/html/Encryption_Types.htm +index 1aebdd0b4..c38eefd2b 100644 +--- a/src/windows/leash/htmlhelp/html/Encryption_Types.htm ++++ b/src/windows/leash/htmlhelp/html/Encryption_Types.htm +@@ -79,19 +79,6 @@ will have an entry in the Encryption type column.
+ Description + + +- des3- +- The triple DES family improves on +-the original DES (Data Encryption Standard) by using 3 separate 56-bit +-keys. Some modes of 3DES are considered weak while others are strong +-(if slow).
    +-
  • des3-cbc-sha1
  • +-
  • des3-cbc-raw (weak)
  • +-
  • des3-hmac-sha1
  • +-
  • des3-cbc-sha1-kd
  • +-
+- +- +- + aes + The AES Advanced Encryption Standard + family, like 3DES, is a symmetric block cipher and was designed diff --git a/root/ppg/common/deps/krb5/rpm/downstream-SELinux-integration.patch b/root/ppg/common/deps/krb5/rpm/downstream-SELinux-integration.patch new file mode 100644 index 00000000..13aa0b61 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/downstream-SELinux-integration.patch @@ -0,0 +1,1035 @@ +From 791fe183bf67dcab6d044b23d8daaf4a3a96be48 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Tue, 23 Aug 2016 16:30:53 -0400 +Subject: [PATCH] [downstream] SELinux integration + +SELinux bases access to files on the domain of the requesting process, +the operation being performed, and the context applied to the file. + +In many cases, applications needn't be SELinux aware to work properly, +because SELinux can apply a default label to a file based on the label +of the directory in which it's created. + +In the case of files such as /etc/krb5.keytab, however, this isn't +sufficient, as /etc/krb5.keytab will almost always need to be given a +label which differs from that of /etc/issue or /etc/resolv.conf. The +the kdb stash file needs a different label than the database for which +it's holding a master key, even though both typically live in the same +directory. + +To give the file the correct label, we can either force a "restorecon" +call to fix a file's label after it's created, or create the file with +the right label, as we attempt to do here. We lean on THREEPARAMOPEN +and define a similar macro named WRITABLEFOPEN with which we replace +several uses of fopen(). + +The file creation context that we're manipulating here is a process-wide +attribute. While for the most part, applications which need to label +files when they're created have tended to be single-threaded, there's +not much we can do to avoid interfering with an application that +manipulates the creation context directly. Right now we're mediating +access using a library-local mutex, but that can only work for consumers +that are part of this package -- an unsuspecting application will still +stomp all over us. + +The selabel APIs for looking up the context should be thread-safe (per +Red Hat #273081), so switching to using them instead of matchpathcon(), +which we used earlier, is some improvement. + +Last-updated: krb5-1.18-beta1 +(cherry picked from commit 0f8851a23a7b6fa0e195e01d0475e9e55707adf2) +--- + src/aclocal.m4 | 48 +++ + src/build-tools/krb5-config.in | 3 +- + src/config/pre.in | 3 +- + src/configure.ac | 2 + + src/include/k5-int.h | 1 + + src/include/k5-label.h | 32 ++ + src/include/krb5/krb5.hin | 6 + + src/kadmin/dbutil/dump.c | 11 +- + src/kdc/main.c | 2 +- + src/kprop/kpropd.c | 9 + + src/lib/kadm5/logger.c | 4 +- + src/lib/kdb/kdb_log.c | 2 +- + src/lib/krb5/ccache/cc_dir.c | 26 +- + src/lib/krb5/keytab/kt_file.c | 4 +- + src/lib/krb5/os/trace.c | 2 +- + src/plugins/kdb/db2/adb_openclose.c | 2 +- + src/plugins/kdb/db2/kdb_db2.c | 4 +- + src/plugins/kdb/db2/libdb2/btree/bt_open.c | 3 +- + src/plugins/kdb/db2/libdb2/hash/hash.c | 3 +- + src/plugins/kdb/db2/libdb2/recno/rec_open.c | 4 +- + .../kdb/ldap/ldap_util/kdb5_ldap_services.c | 11 +- + src/util/profile/prof_file.c | 3 +- + src/util/support/Makefile.in | 3 +- + src/util/support/selinux.c | 406 ++++++++++++++++++ + 24 files changed, 573 insertions(+), 21 deletions(-) + create mode 100644 src/include/k5-label.h + create mode 100644 src/util/support/selinux.c + +diff --git a/src/aclocal.m4 b/src/aclocal.m4 +index 830203683..6796fec53 100644 +--- a/src/aclocal.m4 ++++ b/src/aclocal.m4 +@@ -89,6 +89,7 @@ AC_SUBST_FILE(libnodeps_frag) + dnl + KRB5_AC_PRAGMA_WEAK_REF + WITH_LDAP ++KRB5_WITH_SELINUX + KRB5_LIB_PARAMS + KRB5_AC_INITFINI + KRB5_AC_ENABLE_THREADS +@@ -1743,4 +1744,51 @@ AC_SUBST(PAM_LIBS) + AC_SUBST(PAM_MAN) + AC_SUBST(NON_PAM_MAN) + ])dnl ++dnl ++dnl Use libselinux to set file contexts on newly-created files. ++dnl ++AC_DEFUN(KRB5_WITH_SELINUX,[ ++AC_ARG_WITH(selinux,[AC_HELP_STRING(--with-selinux,[compile with SELinux labeling support])], ++ withselinux="$withval",withselinux=auto) ++old_LIBS="$LIBS" ++if test "$withselinux" != no ; then ++ AC_MSG_RESULT([checking for libselinux...]) ++ SELINUX_LIBS= ++ AC_CHECK_HEADERS(selinux/selinux.h selinux/label.h) ++ if test "x$ac_cv_header_selinux_selinux_h" != xyes ; then ++ if test "$withselinux" = auto ; then ++ AC_MSG_RESULT([Unable to locate selinux/selinux.h.]) ++ withselinux=no ++ else ++ AC_MSG_ERROR([Unable to locate selinux/selinux.h.]) ++ fi ++ fi + ++ LIBS= ++ unset ac_cv_func_setfscreatecon ++ AC_CHECK_FUNCS(setfscreatecon selabel_open) ++ if test "x$ac_cv_func_setfscreatecon" = xno ; then ++ AC_CHECK_LIB(selinux,setfscreatecon) ++ unset ac_cv_func_setfscreatecon ++ AC_CHECK_FUNCS(setfscreatecon selabel_open) ++ if test "x$ac_cv_func_setfscreatecon" = xyes ; then ++ SELINUX_LIBS="$LIBS" ++ else ++ if test "$withselinux" = auto ; then ++ AC_MSG_RESULT([Unable to locate libselinux.]) ++ withselinux=no ++ else ++ AC_MSG_ERROR([Unable to locate libselinux.]) ++ fi ++ fi ++ fi ++ if test "$withselinux" != no ; then ++ AC_MSG_NOTICE([building with SELinux labeling support]) ++ AC_DEFINE(USE_SELINUX,1,[Define if Kerberos-aware tools should set SELinux file contexts when creating files.]) ++ SELINUX_LIBS="$LIBS" ++ EXTRA_SUPPORT_SYMS="$EXTRA_SUPPORT_SYMS krb5int_labeled_open krb5int_labeled_fopen krb5int_push_fscreatecon_for krb5int_pop_fscreatecon" ++ fi ++fi ++LIBS="$old_LIBS" ++AC_SUBST(SELINUX_LIBS) ++])dnl +diff --git a/src/build-tools/krb5-config.in b/src/build-tools/krb5-config.in +index f6184da3f..c17cb5eb5 100755 +--- a/src/build-tools/krb5-config.in ++++ b/src/build-tools/krb5-config.in +@@ -41,6 +41,7 @@ DL_LIB='@DL_LIB@' + DEFCCNAME='@DEFCCNAME@' + DEFKTNAME='@DEFKTNAME@' + DEFCKTNAME='@DEFCKTNAME@' ++SELINUX_LIBS='@SELINUX_LIBS@' + + LIBS='@LIBS@' + GEN_LIB=@GEN_LIB@ +@@ -255,7 +256,7 @@ if test -n "$do_libs"; then + fi + + # If we ever support a flag to generate output suitable for static +- # linking, we would output "-lkrb5support $GEN_LIB $LIBS $DL_LIB" ++ # linking, we would output "-lkrb5support $GEN_LIB $LIBS $SELINUX_LIBS $DL_LIB" + # here. + + echo $lib_flags +diff --git a/src/config/pre.in b/src/config/pre.in +index ce87e21ca..917357df9 100644 +--- a/src/config/pre.in ++++ b/src/config/pre.in +@@ -177,6 +177,7 @@ LD = $(PURE) @LD@ + KRB_INCLUDES = -I$(BUILDTOP)/include -I$(top_srcdir)/include + LDFLAGS = @LDFLAGS@ + LIBS = @LIBS@ ++SELINUX_LIBS=@SELINUX_LIBS@ + + INSTALL=@INSTALL@ + INSTALL_STRIP= +@@ -402,7 +403,7 @@ SUPPORT_LIB = -l$(SUPPORT_LIBNAME) + # HESIOD_LIBS is -lhesiod... + HESIOD_LIBS = @HESIOD_LIBS@ + +-KRB5_BASE_LIBS = $(KRB5_LIB) $(K5CRYPTO_LIB) $(COM_ERR_LIB) $(SUPPORT_LIB) $(GEN_LIB) $(LIBS) $(DL_LIB) ++KRB5_BASE_LIBS = $(KRB5_LIB) $(K5CRYPTO_LIB) $(COM_ERR_LIB) $(SUPPORT_LIB) $(GEN_LIB) $(LIBS) $(SELINUX_LIBS) $(DL_LIB) + KDB5_LIBS = $(KDB5_LIB) $(GSSRPC_LIBS) + GSS_LIBS = $(GSS_KRB5_LIB) + # needs fixing if ever used on macOS! +diff --git a/src/configure.ac b/src/configure.ac +index d1f576124..440a22bd9 100644 +--- a/src/configure.ac ++++ b/src/configure.ac +@@ -1392,6 +1392,8 @@ AC_PATH_PROG(GROFF, groff) + + KRB5_WITH_PAM + ++KRB5_WITH_SELINUX ++ + # Make localedir work in autoconf 2.5x. + if test "${localedir+set}" != set; then + localedir='$(datadir)/locale' +diff --git a/src/include/k5-int.h b/src/include/k5-int.h +index 9616b24bf..0d9af3d95 100644 +--- a/src/include/k5-int.h ++++ b/src/include/k5-int.h +@@ -128,6 +128,7 @@ typedef unsigned char u_char; + + + #include "k5-platform.h" ++#include "k5-label.h" + + #define KRB5_KDB_MAX_LIFE (60*60*24) /* one day */ + #define KRB5_KDB_MAX_RLIFE (60*60*24*7) /* one week */ +diff --git a/src/include/k5-label.h b/src/include/k5-label.h +new file mode 100644 +index 000000000..dfaaa847c +--- /dev/null ++++ b/src/include/k5-label.h +@@ -0,0 +1,32 @@ ++#ifndef _KRB5_LABEL_H ++#define _KRB5_LABEL_H ++ ++#ifdef THREEPARAMOPEN ++#undef THREEPARAMOPEN ++#endif ++#ifdef WRITABLEFOPEN ++#undef WRITABLEFOPEN ++#endif ++ ++/* Wrapper functions which help us create files and directories with the right ++ * context labels. */ ++#ifdef USE_SELINUX ++#include ++#include ++#include ++#include ++#include ++FILE *krb5int_labeled_fopen(const char *path, const char *mode); ++int krb5int_labeled_creat(const char *path, mode_t mode); ++int krb5int_labeled_open(const char *path, int flags, ...); ++int krb5int_labeled_mkdir(const char *path, mode_t mode); ++int krb5int_labeled_mknod(const char *path, mode_t mode, dev_t device); ++#define THREEPARAMOPEN(x,y,z) krb5int_labeled_open(x,y,z) ++#define WRITABLEFOPEN(x,y) krb5int_labeled_fopen(x,y) ++void *krb5int_push_fscreatecon_for(const char *pathname); ++void krb5int_pop_fscreatecon(void *previous); ++#else ++#define WRITABLEFOPEN(x,y) fopen(x,y) ++#define THREEPARAMOPEN(x,y,z) open(x,y,z) ++#endif ++#endif +diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin +index 79761f6d2..e9435c693 100644 +--- a/src/include/krb5/krb5.hin ++++ b/src/include/krb5/krb5.hin +@@ -87,6 +87,12 @@ + #define THREEPARAMOPEN(x,y,z) open(x,y,z) + #endif + ++#if KRB5_PRIVATE ++#ifndef WRITABLEFOPEN ++#define WRITABLEFOPEN(x,y) fopen(x,y) ++#endif ++#endif ++ + #define KRB5_OLD_CRYPTO + + #include +diff --git a/src/kadmin/dbutil/dump.c b/src/kadmin/dbutil/dump.c +index 301e3476d..19f2cc230 100644 +--- a/src/kadmin/dbutil/dump.c ++++ b/src/kadmin/dbutil/dump.c +@@ -148,12 +148,21 @@ create_ofile(char *ofile, char **tmpname) + { + int fd = -1; + FILE *f; ++#ifdef USE_SELINUX ++ void *selabel; ++#endif + + *tmpname = NULL; + if (asprintf(tmpname, "%s-XXXXXX", ofile) < 0) + goto error; + ++#ifdef USE_SELINUX ++ selabel = krb5int_push_fscreatecon_for(ofile); ++#endif + fd = mkstemp(*tmpname); ++#ifdef USE_SELINUX ++ krb5int_pop_fscreatecon(selabel); ++#endif + if (fd == -1) + goto error; + +@@ -197,7 +206,7 @@ prep_ok_file(krb5_context context, char *file_name, int *fd_out) + goto cleanup; + } + +- fd = open(file_ok, O_WRONLY | O_CREAT | O_TRUNC, 0600); ++ fd = THREEPARAMOPEN(file_ok, O_WRONLY | O_CREAT | O_TRUNC, 0600); + if (fd == -1) { + com_err(progname, errno, _("while creating 'ok' file, '%s'"), file_ok); + goto cleanup; +diff --git a/src/kdc/main.c b/src/kdc/main.c +index fdcd694d7..1ede4bf2f 100644 +--- a/src/kdc/main.c ++++ b/src/kdc/main.c +@@ -872,7 +872,7 @@ write_pid_file(const char *path) + FILE *file; + unsigned long pid; + +- file = fopen(path, "w"); ++ file = WRITABLEFOPEN(path, "w"); + if (file == NULL) + return errno; + pid = (unsigned long) getpid(); +diff --git a/src/kprop/kpropd.c b/src/kprop/kpropd.c +index 5622d56e1..356e3e0e6 100644 +--- a/src/kprop/kpropd.c ++++ b/src/kprop/kpropd.c +@@ -487,6 +487,9 @@ doit(int fd) + krb5_enctype etype; + int database_fd; + char host[INET6_ADDRSTRLEN + 1]; ++#ifdef USE_SELINUX ++ void *selabel; ++#endif + + signal_wrapper(SIGALRM, alarm_handler); + alarm(params.iprop_resync_timeout); +@@ -542,9 +545,15 @@ doit(int fd) + free(name); + exit(1); + } ++#ifdef USE_SELINUX ++ selabel = krb5int_push_fscreatecon_for(file); ++#endif + omask = umask(077); + lock_fd = open(temp_file_name, O_RDWR | O_CREAT, 0600); + (void)umask(omask); ++#ifdef USE_SELINUX ++ krb5int_pop_fscreatecon(selabel); ++#endif + retval = krb5_lock_file(kpropd_context, lock_fd, + KRB5_LOCKMODE_EXCLUSIVE | KRB5_LOCKMODE_DONTBLOCK); + if (retval) { +diff --git a/src/lib/kadm5/logger.c b/src/lib/kadm5/logger.c +index c6885edf2..9aec3c05e 100644 +--- a/src/lib/kadm5/logger.c ++++ b/src/lib/kadm5/logger.c +@@ -309,7 +309,7 @@ krb5_klog_init(krb5_context kcontext, char *ename, char *whoami, krb5_boolean do + */ + append = (cp[4] == ':') ? O_APPEND : 0; + if (append || cp[4] == '=') { +- fd = open(&cp[5], O_CREAT | O_WRONLY | append, ++ fd = THREEPARAMOPEN(&cp[5], O_CREAT | O_WRONLY | append, + S_IRUSR | S_IWUSR | S_IRGRP); + if (fd != -1) + f = fdopen(fd, append ? "a" : "w"); +@@ -776,7 +776,7 @@ krb5_klog_reopen(krb5_context kcontext) + * In case the old logfile did not get moved out of the + * way, open for append to prevent squashing the old logs. + */ +- f = fopen(log_control.log_entries[lindex].lfu_fname, "a+"); ++ f = WRITABLEFOPEN(log_control.log_entries[lindex].lfu_fname, "a+"); + if (f) { + set_cloexec_file(f); + log_control.log_entries[lindex].lfu_filep = f; +diff --git a/src/lib/kdb/kdb_log.c b/src/lib/kdb/kdb_log.c +index 2659a2501..e9b95fce5 100644 +--- a/src/lib/kdb/kdb_log.c ++++ b/src/lib/kdb/kdb_log.c +@@ -480,7 +480,7 @@ ulog_map(krb5_context context, const char *logname, uint32_t ulogentries) + return ENOMEM; + + if (stat(logname, &st) == -1) { +- log_ctx->ulogfd = open(logname, O_RDWR | O_CREAT, 0600); ++ log_ctx->ulogfd = THREEPARAMOPEN(logname, O_RDWR | O_CREAT, 0600); + if (log_ctx->ulogfd == -1) { + retval = errno; + goto cleanup; +diff --git a/src/lib/krb5/ccache/cc_dir.c b/src/lib/krb5/ccache/cc_dir.c +index 7b100a0ec..5683a0433 100644 +--- a/src/lib/krb5/ccache/cc_dir.c ++++ b/src/lib/krb5/ccache/cc_dir.c +@@ -183,10 +183,19 @@ write_primary_file(const char *primary_path, const char *contents) + char *newpath = NULL; + FILE *fp = NULL; + int fd = -1, status; ++#ifdef USE_SELINUX ++ void *selabel; ++#endif + + if (asprintf(&newpath, "%s.XXXXXX", primary_path) < 0) + return ENOMEM; ++#ifdef USE_SELINUX ++ selabel = krb5int_push_fscreatecon_for(primary_path); ++#endif + fd = mkstemp(newpath); ++#ifdef USE_SELINUX ++ krb5int_pop_fscreatecon(selabel); ++#endif + if (fd < 0) + goto cleanup; + #ifdef HAVE_CHMOD +@@ -221,10 +230,23 @@ static krb5_error_code + verify_dir(krb5_context context, const char *dirname) + { + struct stat st; ++ int status; ++#ifdef USE_SELINUX ++ void *selabel; ++#endif + + if (stat(dirname, &st) < 0) { +- if (errno == ENOENT && mkdir(dirname, S_IRWXU) == 0) +- return 0; ++ if (errno == ENOENT) { ++#ifdef USE_SELINUX ++ selabel = krb5int_push_fscreatecon_for(dirname); ++#endif ++ status = mkdir(dirname, S_IRWXU); ++#ifdef USE_SELINUX ++ krb5int_pop_fscreatecon(selabel); ++#endif ++ if (status == 0) ++ return 0; ++ } + k5_setmsg(context, KRB5_FCC_NOFILE, + _("Credential cache directory %s does not exist"), + dirname); +diff --git a/src/lib/krb5/keytab/kt_file.c b/src/lib/krb5/keytab/kt_file.c +index 021c94398..aaf573439 100644 +--- a/src/lib/krb5/keytab/kt_file.c ++++ b/src/lib/krb5/keytab/kt_file.c +@@ -735,14 +735,14 @@ krb5_ktfileint_open(krb5_context context, krb5_keytab id, int mode) + + KTCHECKLOCK(id); + errno = 0; +- KTFILEP(id) = fopen(KTFILENAME(id), ++ KTFILEP(id) = WRITABLEFOPEN(KTFILENAME(id), + (mode == KRB5_LOCKMODE_EXCLUSIVE) ? "rb+" : "rb"); + if (!KTFILEP(id)) { + if ((mode == KRB5_LOCKMODE_EXCLUSIVE) && (errno == ENOENT)) { + /* try making it first time around */ + k5_create_secure_file(context, KTFILENAME(id)); + errno = 0; +- KTFILEP(id) = fopen(KTFILENAME(id), "rb+"); ++ KTFILEP(id) = WRITABLEFOPEN(KTFILENAME(id), "rb+"); + if (!KTFILEP(id)) + goto report_errno; + writevno = 1; +diff --git a/src/lib/krb5/os/trace.c b/src/lib/krb5/os/trace.c +index 7073459f0..e9b99f4ca 100644 +--- a/src/lib/krb5/os/trace.c ++++ b/src/lib/krb5/os/trace.c +@@ -458,7 +458,7 @@ krb5_set_trace_filename(krb5_context context, const char *filename) + fd = malloc(sizeof(*fd)); + if (fd == NULL) + return ENOMEM; +- *fd = open(filename, O_WRONLY|O_CREAT|O_APPEND, 0600); ++ *fd = THREEPARAMOPEN(filename, O_WRONLY|O_CREAT|O_APPEND, 0600); + if (*fd == -1) { + free(fd); + return errno; +diff --git a/src/plugins/kdb/db2/adb_openclose.c b/src/plugins/kdb/db2/adb_openclose.c +index 7db30a33b..2b9d01921 100644 +--- a/src/plugins/kdb/db2/adb_openclose.c ++++ b/src/plugins/kdb/db2/adb_openclose.c +@@ -152,7 +152,7 @@ osa_adb_init_db(osa_adb_db_t *dbp, char *filename, char *lockfilename, + * needs be open read/write so that write locking can work with + * POSIX systems + */ +- if ((lockp->lockinfo.lockfile = fopen(lockfilename, "r+")) == NULL) { ++ if ((lockp->lockinfo.lockfile = WRITABLEFOPEN(lockfilename, "r+")) == NULL) { + /* + * maybe someone took away write permission so we could only + * get shared locks? +diff --git a/src/plugins/kdb/db2/kdb_db2.c b/src/plugins/kdb/db2/kdb_db2.c +index 5106a5c99..e481e8121 100644 +--- a/src/plugins/kdb/db2/kdb_db2.c ++++ b/src/plugins/kdb/db2/kdb_db2.c +@@ -694,8 +694,8 @@ ctx_create_db(krb5_context context, krb5_db2_context *dbc) + if (retval) + return retval; + +- dbc->db_lf_file = open(dbc->db_lf_name, O_CREAT | O_RDWR | O_TRUNC, +- 0600); ++ dbc->db_lf_file = THREEPARAMOPEN(dbc->db_lf_name, ++ O_CREAT | O_RDWR | O_TRUNC, 0600); + if (dbc->db_lf_file < 0) { + retval = errno; + goto cleanup; +diff --git a/src/plugins/kdb/db2/libdb2/btree/bt_open.c b/src/plugins/kdb/db2/libdb2/btree/bt_open.c +index 2977b17f3..d5809a5a9 100644 +--- a/src/plugins/kdb/db2/libdb2/btree/bt_open.c ++++ b/src/plugins/kdb/db2/libdb2/btree/bt_open.c +@@ -60,6 +60,7 @@ static char sccsid[] = "@(#)bt_open.c 8.11 (Berkeley) 11/2/95"; + #include + #include + ++#include "k5-int.h" + #include "db-int.h" + #include "btree.h" + +@@ -203,7 +204,7 @@ __bt_open(fname, flags, mode, openinfo, dflags) + goto einval; + } + +- if ((t->bt_fd = open(fname, flags | O_BINARY, mode)) < 0) ++ if ((t->bt_fd = THREEPARAMOPEN(fname, flags | O_BINARY, mode)) < 0) + goto err; + + } else { +diff --git a/src/plugins/kdb/db2/libdb2/hash/hash.c b/src/plugins/kdb/db2/libdb2/hash/hash.c +index 862dbb164..686a960c9 100644 +--- a/src/plugins/kdb/db2/libdb2/hash/hash.c ++++ b/src/plugins/kdb/db2/libdb2/hash/hash.c +@@ -51,6 +51,7 @@ static char sccsid[] = "@(#)hash.c 8.12 (Berkeley) 11/7/95"; + #include + #endif + ++#include "k5-int.h" + #include "db-int.h" + #include "hash.h" + #include "page.h" +@@ -129,7 +130,7 @@ __kdb2_hash_open(file, flags, mode, info, dflags) + new_table = 1; + } + if (file) { +- if ((hashp->fp = open(file, flags|O_BINARY, mode)) == -1) ++ if ((hashp->fp = THREEPARAMOPEN(file, flags|O_BINARY, mode)) == -1) + RETURN_ERROR(errno, error0); + (void)fcntl(hashp->fp, F_SETFD, 1); + } +diff --git a/src/plugins/kdb/db2/libdb2/recno/rec_open.c b/src/plugins/kdb/db2/libdb2/recno/rec_open.c +index d8b26e701..b0daa7c02 100644 +--- a/src/plugins/kdb/db2/libdb2/recno/rec_open.c ++++ b/src/plugins/kdb/db2/libdb2/recno/rec_open.c +@@ -51,6 +51,7 @@ static char sccsid[] = "@(#)rec_open.c 8.12 (Berkeley) 11/18/94"; + #include + #include + ++#include "k5-int.h" + #include "db-int.h" + #include "recno.h" + +@@ -68,7 +69,8 @@ __rec_open(fname, flags, mode, openinfo, dflags) + int rfd = -1, sverrno; + + /* Open the user's file -- if this fails, we're done. */ +- if (fname != NULL && (rfd = open(fname, flags | O_BINARY, mode)) < 0) ++ if (fname != NULL && ++ (rfd = THREEPARAMOPEN(fname, flags | O_BINARY, mode)) < 0) + return (NULL); + + if (fname != NULL && fcntl(rfd, F_SETFD, 1) == -1) { +diff --git a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c +index b92cb58c7..0a95101ad 100644 +--- a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c ++++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c +@@ -190,7 +190,7 @@ kdb5_ldap_stash_service_password(int argc, char **argv) + + /* set password in the file */ + old_mode = umask(0177); +- pfile = fopen(file_name, "a+"); ++ pfile = WRITABLEFOPEN(file_name, "a+"); + if (pfile == NULL) { + com_err(me, errno, _("Failed to open file %s: %s"), file_name, + strerror (errno)); +@@ -231,6 +231,9 @@ kdb5_ldap_stash_service_password(int argc, char **argv) + * Delete the existing entry and add the new entry + */ + FILE *newfile; ++#ifdef USE_SELINUX ++ void *selabel; ++#endif + + mode_t omask; + +@@ -242,7 +245,13 @@ kdb5_ldap_stash_service_password(int argc, char **argv) + } + + omask = umask(077); ++#ifdef USE_SELINUX ++ selabel = krb5int_push_fscreatecon_for(file_name); ++#endif + newfile = fopen(tmp_file, "w"); ++#ifdef USE_SELINUX ++ krb5int_pop_fscreatecon(selabel); ++#endif + umask (omask); + if (newfile == NULL) { + com_err(me, errno, _("Error creating file %s"), tmp_file); +diff --git a/src/util/profile/prof_file.c b/src/util/profile/prof_file.c +index aa951df05..79f9500f6 100644 +--- a/src/util/profile/prof_file.c ++++ b/src/util/profile/prof_file.c +@@ -33,6 +33,7 @@ + #endif + + #include "k5-platform.h" ++#include "k5-label.h" + + struct global_shared_profile_data { + /* This is the head of the global list of shared trees */ +@@ -391,7 +392,7 @@ static errcode_t write_data_to_file(prf_data_t data, const char *outfile, + + errno = 0; + +- f = fopen(new_file, "w"); ++ f = WRITABLEFOPEN(new_file, "w"); + if (!f) { + retval = errno; + if (retval == 0) +diff --git a/src/util/support/Makefile.in b/src/util/support/Makefile.in +index 86d5a950a..1052d53a1 100644 +--- a/src/util/support/Makefile.in ++++ b/src/util/support/Makefile.in +@@ -74,6 +74,7 @@ IPC_SYMS= \ + + STLIBOBJS= \ + threads.o \ ++ selinux.o \ + init-addrinfo.o \ + plugins.o \ + errors.o \ +@@ -168,7 +169,7 @@ SRCS=\ + + SHLIB_EXPDEPS = + # Add -lm if dumping thread stats, for sqrt. +-SHLIB_EXPLIBS= $(LIBS) $(DL_LIB) ++SHLIB_EXPLIBS= $(LIBS) $(SELINUX_LIBS) $(DL_LIB) + + DEPLIBS= + +diff --git a/src/util/support/selinux.c b/src/util/support/selinux.c +new file mode 100644 +index 000000000..6d41f3244 +--- /dev/null ++++ b/src/util/support/selinux.c +@@ -0,0 +1,406 @@ ++/* ++ * Copyright 2007,2008,2009,2011,2012,2013,2016 Red Hat, Inc. All Rights Reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * ++ * Redistributions of source code must retain the above copyright notice, this ++ * list of conditions and the following disclaimer. ++ * ++ * Redistributions in binary form must reproduce the above copyright notice, ++ * this list of conditions and the following disclaimer in the documentation ++ * and/or other materials provided with the distribution. ++ * ++ * Neither the name of Red Hat, Inc. nor the names of its contributors may be ++ * used to endorse or promote products derived from this software without ++ * specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ * ++ * File-opening wrappers for creating correctly-labeled files. So far, we can ++ * assume that this is Linux-specific, so we make many simplifying assumptions. ++ */ ++ ++#include "../../include/autoconf.h" ++ ++#ifdef USE_SELINUX ++ ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++/* #define DEBUG 1 */ ++static void ++debug_log(const char *fmt, ...) ++{ ++#ifdef DEBUG ++ va_list ap; ++ va_start(ap, fmt); ++ if (isatty(fileno(stderr))) { ++ vfprintf(stderr, fmt, ap); ++ } ++ va_end(ap); ++#endif ++ ++ return; ++} ++ ++/* Mutex used to serialize use of the process-global file creation context. */ ++k5_mutex_t labeled_mutex = K5_MUTEX_PARTIAL_INITIALIZER; ++ ++/* Make sure we finish initializing that mutex before attempting to use it. */ ++k5_once_t labeled_once = K5_ONCE_INIT; ++static void ++label_mutex_init(void) ++{ ++ k5_mutex_finish_init(&labeled_mutex); ++} ++ ++static struct selabel_handle *selabel_ctx; ++static time_t selabel_last_changed; ++ ++MAKE_FINI_FUNCTION(cleanup_fscreatecon); ++ ++static void ++cleanup_fscreatecon(void) ++{ ++ if (selabel_ctx != NULL) { ++ selabel_close(selabel_ctx); ++ selabel_ctx = NULL; ++ } ++} ++ ++static security_context_t ++push_fscreatecon(const char *pathname, mode_t mode) ++{ ++ security_context_t previous, configuredsc, currentsc, derivedsc; ++ context_t current, derived; ++ const char *fullpath, *currentuser; ++ char *genpath; ++ ++ previous = configuredsc = currentsc = derivedsc = NULL; ++ current = derived = NULL; ++ genpath = NULL; ++ ++ fullpath = pathname; ++ ++ if (!is_selinux_enabled()) { ++ goto fail; ++ } ++ ++ if (getfscreatecon(&previous) != 0) { ++ goto fail; ++ } ++ ++ /* Canonicalize pathname */ ++ if (pathname[0] != '/') { ++ char *wd; ++ size_t len; ++ len = 0; ++ ++ wd = getcwd(NULL, len); ++ if (wd == NULL) { ++ goto fail; ++ } ++ ++ len = strlen(wd) + 1 + strlen(pathname) + 1; ++ genpath = malloc(len); ++ if (genpath == NULL) { ++ free(wd); ++ goto fail; ++ } ++ ++ sprintf(genpath, "%s/%s", wd, pathname); ++ free(wd); ++ fullpath = genpath; ++ } ++ ++ debug_log("Looking up context for \"%s\"(%05o).\n", fullpath, mode); ++ ++ /* Check whether context file has changed under us */ ++ if (selabel_ctx != NULL || selabel_last_changed == 0) { ++ const char *cpath; ++ struct stat st; ++ int i = -1; ++ ++ cpath = selinux_file_context_path(); ++ if (cpath == NULL || (i = stat(cpath, &st)) != 0 || ++ st.st_mtime != selabel_last_changed) { ++ cleanup_fscreatecon(); ++ ++ selabel_last_changed = i ? time(NULL) : st.st_mtime; ++ } ++ } ++ ++ if (selabel_ctx == NULL) { ++ selabel_ctx = selabel_open(SELABEL_CTX_FILE, NULL, 0); ++ } ++ ++ if (selabel_ctx != NULL && ++ selabel_lookup(selabel_ctx, &configuredsc, fullpath, mode) != 0) { ++ goto fail; ++ } ++ ++ if (genpath != NULL) { ++ free(genpath); ++ genpath = NULL; ++ } ++ ++ if (configuredsc == NULL) { ++ goto fail; ++ } ++ ++ getcon(¤tsc); ++ ++ /* AAAAAAAA */ ++ if (currentsc != NULL) { ++ derived = context_new(configuredsc); ++ ++ if (derived != NULL) { ++ current = context_new(currentsc); ++ ++ if (current != NULL) { ++ currentuser = context_user_get(current); ++ ++ if (currentuser != NULL) { ++ if (context_user_set(derived, ++ currentuser) == 0) { ++ derivedsc = context_str(derived); ++ ++ if (derivedsc != NULL) { ++ freecon(configuredsc); ++ configuredsc = strdup(derivedsc); ++ } ++ } ++ } ++ ++ context_free(current); ++ } ++ ++ context_free(derived); ++ } ++ ++ freecon(currentsc); ++ } ++ ++ debug_log("Setting file creation context to \"%s\".\n", configuredsc); ++ if (setfscreatecon(configuredsc) != 0) { ++ debug_log("Unable to determine current context.\n"); ++ goto fail; ++ } ++ ++ freecon(configuredsc); ++ return previous; ++ ++fail: ++ if (previous != NULL) { ++ freecon(previous); ++ } ++ if (genpath != NULL) { ++ free(genpath); ++ } ++ if (configuredsc != NULL) { ++ freecon(configuredsc); ++ } ++ ++ cleanup_fscreatecon(); ++ return NULL; ++} ++ ++static void ++pop_fscreatecon(security_context_t previous) ++{ ++ if (!is_selinux_enabled()) { ++ return; ++ } ++ ++ if (previous != NULL) { ++ debug_log("Resetting file creation context to \"%s\".\n", previous); ++ } else { ++ debug_log("Resetting file creation context to default.\n"); ++ } ++ ++ /* NULL resets to default */ ++ setfscreatecon(previous); ++ ++ if (previous != NULL) { ++ freecon(previous); ++ } ++ ++ /* Need to clean this up here otherwise it leaks */ ++ cleanup_fscreatecon(); ++} ++ ++void * ++krb5int_push_fscreatecon_for(const char *pathname) ++{ ++ struct stat st; ++ void *retval; ++ ++ k5_once(&labeled_once, label_mutex_init); ++ k5_mutex_lock(&labeled_mutex); ++ ++ if (stat(pathname, &st) != 0) { ++ st.st_mode = S_IRUSR | S_IWUSR; ++ } ++ ++ retval = push_fscreatecon(pathname, st.st_mode); ++ return retval ? retval : (void *) -1; ++} ++ ++void ++krb5int_pop_fscreatecon(void *con) ++{ ++ if (con != NULL) { ++ pop_fscreatecon((con == (void *) -1) ? NULL : con); ++ k5_mutex_unlock(&labeled_mutex); ++ } ++} ++ ++FILE * ++krb5int_labeled_fopen(const char *path, const char *mode) ++{ ++ FILE *fp; ++ int errno_save; ++ security_context_t ctx; ++ ++ if ((strcmp(mode, "r") == 0) || ++ (strcmp(mode, "rb") == 0)) { ++ return fopen(path, mode); ++ } ++ ++ k5_once(&labeled_once, label_mutex_init); ++ k5_mutex_lock(&labeled_mutex); ++ ctx = push_fscreatecon(path, 0); ++ ++ fp = fopen(path, mode); ++ errno_save = errno; ++ ++ pop_fscreatecon(ctx); ++ k5_mutex_unlock(&labeled_mutex); ++ ++ errno = errno_save; ++ return fp; ++} ++ ++int ++krb5int_labeled_creat(const char *path, mode_t mode) ++{ ++ int fd; ++ int errno_save; ++ security_context_t ctx; ++ ++ k5_once(&labeled_once, label_mutex_init); ++ k5_mutex_lock(&labeled_mutex); ++ ctx = push_fscreatecon(path, 0); ++ ++ fd = creat(path, mode); ++ errno_save = errno; ++ ++ pop_fscreatecon(ctx); ++ k5_mutex_unlock(&labeled_mutex); ++ ++ errno = errno_save; ++ return fd; ++} ++ ++int ++krb5int_labeled_mknod(const char *path, mode_t mode, dev_t dev) ++{ ++ int ret; ++ int errno_save; ++ security_context_t ctx; ++ ++ k5_once(&labeled_once, label_mutex_init); ++ k5_mutex_lock(&labeled_mutex); ++ ctx = push_fscreatecon(path, mode); ++ ++ ret = mknod(path, mode, dev); ++ errno_save = errno; ++ ++ pop_fscreatecon(ctx); ++ k5_mutex_unlock(&labeled_mutex); ++ ++ errno = errno_save; ++ return ret; ++} ++ ++int ++krb5int_labeled_mkdir(const char *path, mode_t mode) ++{ ++ int ret; ++ int errno_save; ++ security_context_t ctx; ++ ++ k5_once(&labeled_once, label_mutex_init); ++ k5_mutex_lock(&labeled_mutex); ++ ctx = push_fscreatecon(path, S_IFDIR); ++ ++ ret = mkdir(path, mode); ++ errno_save = errno; ++ ++ pop_fscreatecon(ctx); ++ k5_mutex_unlock(&labeled_mutex); ++ ++ errno = errno_save; ++ return ret; ++} ++ ++int ++krb5int_labeled_open(const char *path, int flags, ...) ++{ ++ int fd; ++ int errno_save; ++ security_context_t ctx; ++ mode_t mode; ++ va_list ap; ++ ++ if ((flags & O_CREAT) == 0) { ++ return open(path, flags); ++ } ++ ++ k5_once(&labeled_once, label_mutex_init); ++ k5_mutex_lock(&labeled_mutex); ++ ctx = push_fscreatecon(path, 0); ++ ++ va_start(ap, flags); ++ mode = va_arg(ap, mode_t); ++ fd = open(path, flags, mode); ++ va_end(ap); ++ ++ errno_save = errno; ++ ++ pop_fscreatecon(ctx); ++ k5_mutex_unlock(&labeled_mutex); ++ ++ errno = errno_save; ++ return fd; ++} ++ ++#endif /* USE_SELINUX */ diff --git a/root/ppg/common/deps/krb5/rpm/downstream-Support-PAC-full-checksum-w-o-ticket-chec.patch b/root/ppg/common/deps/krb5/rpm/downstream-Support-PAC-full-checksum-w-o-ticket-chec.patch new file mode 100644 index 00000000..0d5b894a --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/downstream-Support-PAC-full-checksum-w-o-ticket-chec.patch @@ -0,0 +1,140 @@ +From 8ded82fb279198f3fa20fb7c836e77290e7bc6f6 Mon Sep 17 00:00:00 2001 +From: Julien Rische +Date: Fri, 24 Mar 2023 16:22:06 +0100 +Subject: [PATCH] [downstream] Support PAC full checksum w/o ticket checksum + +--- + doc/appdev/refs/api/index.rst | 1 + + src/include/krb5/krb5.hin | 38 +++++++++++++++++++++++++++++++++++ + src/lib/krb5/krb/pac.c | 10 ++++++++- + src/lib/krb5/krb/pac_sign.c | 17 ++++++++++++++++ + src/lib/krb5/libkrb5.exports | 1 + + 5 files changed, 66 insertions(+), 1 deletion(-) + +diff --git a/doc/appdev/refs/api/index.rst b/doc/appdev/refs/api/index.rst +index d12be47c3c..ff813108bb 100644 +--- a/doc/appdev/refs/api/index.rst ++++ b/doc/appdev/refs/api/index.rst +@@ -248,6 +248,7 @@ Rarely used public interfaces + krb5_os_localaddr.rst + krb5_pac_add_buffer.rst + krb5_pac_free.rst ++ krb5_pac_full_sign_compat.rst + krb5_pac_get_buffer.rst + krb5_pac_get_types.rst + krb5_pac_init.rst +diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin +index 12a1d441b8..dbe87561c5 100644 +--- a/src/include/krb5/krb5.hin ++++ b/src/include/krb5/krb5.hin +@@ -8392,6 +8392,44 @@ krb5_pac_sign_ext(krb5_context context, krb5_pac pac, krb5_timestamp authtime, + const krb5_keyblock *privsvr_key, krb5_boolean with_realm, + krb5_data *data); + ++/** ++ * Compatibility function used by IPA if the 1.20 KDB diver API is not ++ * available. It generates PAC signatures, including the extended KDC one when ++ * relevant. ++ * ++ * It is similar to krb5_kdc_sign_ticket(), except it will not generate the ++ * PAC ticket signature, and therefore does not expect encrypted ticket part as ++ * parameter. ++ * ++ * @param [in] context Library context ++ * @param [in] pac PAC handle ++ * @param [in] authtime Expected timestamp ++ * @param [in] client_princ Client principal name (or NULL) ++ * @param [in] server_princ Server principal name ++ * @param [in] server_key Key for server checksum ++ * @param [in] privsvr_key Key for KDC checksum ++ * @param [in] with_realm If true, include the realm of @a client_princ ++ * @param [out] data Signed PAC encoding ++ * ++ * This function signs @a pac using the keys @a server_key and @a privsvr_key ++ * and returns the signed encoding in @a data. @a pac is modified to include ++ * the server and KDC checksum buffers. Use krb5_free_data_contents() to free ++ * @a data when it is no longer needed. ++ * ++ * If @a with_realm is true, the PAC_CLIENT_INFO field of the signed PAC will ++ * include the realm of @a client_princ as well as the name. This flag is ++ * necessary to generate PACs for cross-realm S4U2Self referrals. ++ */ ++krb5_error_code KRB5_CALLCONV ++krb5_pac_full_sign_compat(krb5_context context, krb5_pac pac, ++ krb5_timestamp authtime, ++ krb5_const_principal client_princ, ++ krb5_const_principal server_princ, ++ const krb5_keyblock *server_key, ++ const krb5_keyblock *privsvr_key, ++ krb5_boolean with_realm, ++ krb5_data *data); ++ + /** + * Sign a PAC, possibly including a ticket signature + * +diff --git a/src/lib/krb5/krb/pac.c b/src/lib/krb5/krb/pac.c +index 9c00178a28..b7fa064100 100644 +--- a/src/lib/krb5/krb/pac.c ++++ b/src/lib/krb5/krb/pac.c +@@ -757,9 +757,17 @@ krb5_pac_verify_ext(krb5_context context, + krb5_boolean with_realm) + { + krb5_error_code ret; ++ krb5_boolean has_full_chksum; + + if (server != NULL || privsvr != NULL) { +- ret = verify_pac_checksums(context, pac, FALSE, server, privsvr); ++ /* Fail only if full checksum is present and invalid. ++ * Proceed if absent. ++ */ ++ ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_FULL_CHECKSUM, NULL); ++ has_full_chksum = ret != ENOENT; ++ ++ ret = verify_pac_checksums(context, pac, has_full_chksum, server, ++ privsvr); + if (ret != 0) + return ret; + } +diff --git a/src/lib/krb5/krb/pac_sign.c b/src/lib/krb5/krb/pac_sign.c +index 8ea61ac17b..7c3a86d8eb 100644 +--- a/src/lib/krb5/krb/pac_sign.c ++++ b/src/lib/krb5/krb/pac_sign.c +@@ -309,6 +309,23 @@ krb5_pac_sign_ext(krb5_context context, krb5_pac pac, krb5_timestamp authtime, + with_realm, FALSE, data); + } + ++krb5_error_code KRB5_CALLCONV ++krb5_pac_full_sign_compat(krb5_context context, krb5_pac pac, ++ krb5_timestamp authtime, ++ krb5_const_principal client_princ, ++ krb5_const_principal server_princ, ++ const krb5_keyblock *server_key, ++ const krb5_keyblock *privsvr_key, ++ krb5_boolean with_realm, ++ krb5_data *data) ++{ ++ krb5_boolean is_service_tkt; ++ ++ is_service_tkt = k5_pac_should_have_ticket_signature(server_princ); ++ return sign_pac(context, pac, authtime, client_princ, server_key, ++ privsvr_key, with_realm, is_service_tkt, data); ++} ++ + /* Add a signature over der_enc_tkt in privsvr to pac. der_enc_tkt should be + * encoded with a dummy PAC authdata element containing a single zero byte. */ + static krb5_error_code +diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports +index 28784ec67c..ac94e0c236 100644 +--- a/src/lib/krb5/libkrb5.exports ++++ b/src/lib/krb5/libkrb5.exports +@@ -508,6 +508,7 @@ krb5_os_localaddr + krb5_overridekeyname + krb5_pac_add_buffer + krb5_pac_free ++krb5_pac_full_sign_compat + krb5_pac_get_buffer + krb5_pac_get_types + krb5_pac_init +-- +2.40.1 + diff --git a/root/ppg/common/deps/krb5/rpm/downstream-Use-newly-enforced-dejagnu-path-naming-convention.patch b/root/ppg/common/deps/krb5/rpm/downstream-Use-newly-enforced-dejagnu-path-naming-convention.patch new file mode 100644 index 00000000..3b8ccecf --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/downstream-Use-newly-enforced-dejagnu-path-naming-convention.patch @@ -0,0 +1,342 @@ +From cc1cd235a6a8c066531a17d5773f601455bedb52 Mon Sep 17 00:00:00 2001 +From: Julien Rische +Date: Thu, 31 Mar 2022 18:24:39 +0200 +Subject: [PATCH] Use newly enforced dejagnu path naming convention + +Since version 1.6.3, dejagnu started to enforce a naming convention that +was already in place, but not mandatory: dejagnu test directories have +to be named "testsuite". If they don't implicit relative sub-paths +resolution (e.g. "lib", "config") is not forking. + +This commit renames kadm5 library's unit tests directory to match this +requirement. + +Resolves: rhbz#2070879 + +Signed-off-by: Julien Rische +--- + src/configure.ac | 2 +- + src/lib/kadm5/Makefile.in | 2 +- + .../{unit-test => testsuite}/Makefile.in | 28 +++++++++---------- + .../api.2/crte-policy.exp | 0 + .../api.2/get-policy.exp | 0 + .../api.2/mod-policy.exp | 0 + .../api.current/chpass-principal-v2.exp | 0 + .../api.current/chpass-principal.exp | 0 + .../api.current/crte-policy.exp | 0 + .../api.current/crte-principal.exp | 0 + .../api.current/destroy.exp | 0 + .../api.current/dlte-policy.exp | 0 + .../api.current/dlte-principal.exp | 0 + .../api.current/get-policy.exp | 0 + .../api.current/get-principal-v2.exp | 0 + .../api.current/get-principal.exp | 0 + .../api.current/init-v2.exp | 0 + .../api.current/init.exp | 0 + .../api.current/mod-policy.exp | 0 + .../api.current/mod-principal-v2.exp | 0 + .../api.current/mod-principal.exp | 0 + .../api.current/randkey-principal-v2.exp | 0 + .../api.current/randkey-principal.exp | 0 + .../{unit-test => testsuite}/config/unix.exp | 0 + src/lib/kadm5/{unit-test => testsuite}/deps | 0 + .../{unit-test => testsuite}/destroy-test.c | 0 + .../diff-files/destroy-1 | 0 + .../diff-files/no-diffs | 0 + .../{unit-test => testsuite}/handle-test.c | 0 + .../{unit-test => testsuite}/init-test.c | 0 + .../{unit-test => testsuite}/iter-test.c | 0 + .../kadm5/{unit-test => testsuite}/lib/lib.t | 2 +- + .../{unit-test => testsuite}/lock-test.c | 0 + .../{unit-test => testsuite}/randkey-test.c | 0 + .../{unit-test => testsuite}/setkey-test.c | 0 + .../kadm5/{unit-test => testsuite}/site.exp | 0 + 36 files changed, 17 insertions(+), 17 deletions(-) + rename src/lib/kadm5/{unit-test => testsuite}/Makefile.in (86%) + rename src/lib/kadm5/{unit-test => testsuite}/api.2/crte-policy.exp (100%) + rename src/lib/kadm5/{unit-test => testsuite}/api.2/get-policy.exp (100%) + rename src/lib/kadm5/{unit-test => testsuite}/api.2/mod-policy.exp (100%) + rename src/lib/kadm5/{unit-test => testsuite}/api.current/chpass-principal-v2.exp (100%) + rename src/lib/kadm5/{unit-test => testsuite}/api.current/chpass-principal.exp (100%) + rename src/lib/kadm5/{unit-test => testsuite}/api.current/crte-policy.exp (100%) + rename src/lib/kadm5/{unit-test => testsuite}/api.current/crte-principal.exp (100%) + rename src/lib/kadm5/{unit-test => testsuite}/api.current/destroy.exp (100%) + rename src/lib/kadm5/{unit-test => testsuite}/api.current/dlte-policy.exp (100%) + rename src/lib/kadm5/{unit-test => testsuite}/api.current/dlte-principal.exp (100%) + rename src/lib/kadm5/{unit-test => testsuite}/api.current/get-policy.exp (100%) + rename src/lib/kadm5/{unit-test => testsuite}/api.current/get-principal-v2.exp (100%) + rename src/lib/kadm5/{unit-test => testsuite}/api.current/get-principal.exp (100%) + rename src/lib/kadm5/{unit-test => testsuite}/api.current/init-v2.exp (100%) + rename src/lib/kadm5/{unit-test => testsuite}/api.current/init.exp (100%) + rename src/lib/kadm5/{unit-test => testsuite}/api.current/mod-policy.exp (100%) + rename src/lib/kadm5/{unit-test => testsuite}/api.current/mod-principal-v2.exp (100%) + rename src/lib/kadm5/{unit-test => testsuite}/api.current/mod-principal.exp (100%) + rename src/lib/kadm5/{unit-test => testsuite}/api.current/randkey-principal-v2.exp (100%) + rename src/lib/kadm5/{unit-test => testsuite}/api.current/randkey-principal.exp (100%) + rename src/lib/kadm5/{unit-test => testsuite}/config/unix.exp (100%) + rename src/lib/kadm5/{unit-test => testsuite}/deps (100%) + rename src/lib/kadm5/{unit-test => testsuite}/destroy-test.c (100%) + rename src/lib/kadm5/{unit-test => testsuite}/diff-files/destroy-1 (100%) + rename src/lib/kadm5/{unit-test => testsuite}/diff-files/no-diffs (100%) + rename src/lib/kadm5/{unit-test => testsuite}/handle-test.c (100%) + rename src/lib/kadm5/{unit-test => testsuite}/init-test.c (100%) + rename src/lib/kadm5/{unit-test => testsuite}/iter-test.c (100%) + rename src/lib/kadm5/{unit-test => testsuite}/lib/lib.t (99%) + rename src/lib/kadm5/{unit-test => testsuite}/lock-test.c (100%) + rename src/lib/kadm5/{unit-test => testsuite}/randkey-test.c (100%) + rename src/lib/kadm5/{unit-test => testsuite}/setkey-test.c (100%) + rename src/lib/kadm5/{unit-test => testsuite}/site.exp (100%) + +diff --git a/src/configure.ac b/src/configure.ac +index 29be532cb..37e36b76d 100644 +--- a/src/configure.ac ++++ b/src/configure.ac +@@ -1499,7 +1499,7 @@ V5_AC_OUTPUT_MAKEFILE(. + + lib/rpc lib/rpc/unit-test + +- lib/kadm5 lib/kadm5/clnt lib/kadm5/srv lib/kadm5/unit-test ++ lib/kadm5 lib/kadm5/clnt lib/kadm5/srv lib/kadm5/testsuite + lib/krad + lib/apputils + +diff --git a/src/lib/kadm5/Makefile.in b/src/lib/kadm5/Makefile.in +index c4eaad38d..76fc4b548 100644 +--- a/src/lib/kadm5/Makefile.in ++++ b/src/lib/kadm5/Makefile.in +@@ -1,6 +1,6 @@ + mydir=lib$(S)kadm5 + BUILDTOP=$(REL)..$(S).. +-SUBDIRS = clnt srv unit-test ++SUBDIRS = clnt srv testsuite + + ##DOSBUILDTOP = ..\.. + +diff --git a/src/lib/kadm5/unit-test/Makefile.in b/src/lib/kadm5/testsuite/Makefile.in +similarity index 86% +rename from src/lib/kadm5/unit-test/Makefile.in +rename to src/lib/kadm5/testsuite/Makefile.in +index 68fa097ff..5a55b786b 100644 +--- a/src/lib/kadm5/unit-test/Makefile.in ++++ b/src/lib/kadm5/testsuite/Makefile.in +@@ -1,4 +1,4 @@ +-mydir=lib$(S)kadm5$(S)unit-test ++mydir=lib$(S)kadm5$(S)testsuite + BUILDTOP=$(REL)..$(S)..$(S).. + KDB_DEP_LIB=$(DL_LIB) $(THREAD_LINKOPTS) + +@@ -61,7 +61,7 @@ runenv.exp: Makefile + eval echo "set env\($$i\) \$$$$i"; done > runenv.exp + + # +-# The unit-test targets ++# The testsuite targets + # + + check: check-@DO_TEST@ +@@ -72,13 +72,13 @@ check-: + @echo "+++ Either tcl, runtest, or Perl is unavailable." + @echo "+++" + +-check-ok unit-test: unit-test-client unit-test-server ++check-ok testsuite: testsuite-client testsuite-server + +-unit-test-client: unit-test-client-setup unit-test-client-body \ +- unit-test-client-cleanup ++testsuite-client: testsuite-client-setup testsuite-client-body \ ++ testsuite-client-cleanup + +-unit-test-server: unit-test-server-setup unit-test-server-body \ +- unit-test-server-cleanup ++testsuite-server: testsuite-server-setup testsuite-server-body \ ++ testsuite-server-cleanup + + test-randkey: randkey-test + $(ENV_SETUP) $(VALGRIND) ./randkey-test +@@ -98,19 +98,19 @@ test-destroy: destroy-test + test-setkey-client: client-setkey-test + $(ENV_SETUP) $(VALGRIND) ./client-setkey-test testkeys admin admin + +-unit-test-client-setup: runenv.sh ++testsuite-client-setup: runenv.sh + $(ENV_SETUP) $(VALGRIND) $(START_SERVERS) + +-unit-test-client-cleanup: ++testsuite-client-cleanup: + $(ENV_SETUP) $(STOP_SERVERS) + +-unit-test-server-setup: runenv.sh ++testsuite-server-setup: runenv.sh + $(ENV_SETUP) $(VALGRIND) $(START_SERVERS_LOCAL) + +-unit-test-server-cleanup: ++testsuite-server-cleanup: + $(ENV_SETUP) $(STOP_SERVERS_LOCAL) + +-unit-test-client-body: site.exp test-noauth test-destroy test-handle-client \ ++testsuite-client-body: site.exp test-noauth test-destroy test-handle-client \ + test-setkey-client runenv.exp + $(ENV_SETUP) $(RUNTEST) --tool api RPC=1 API=$(CLNTTCL) \ + KINIT=$(BUILDTOP)/clients/kinit/kinit \ +@@ -121,7 +121,7 @@ unit-test-client-body: site.exp test-noauth test-destroy test-handle-client \ + -mv api.log capi.log + -mv api.sum capi.sum + +-unit-test-server-body: site.exp test-handle-server lock-test ++testsuite-server-body: site.exp test-handle-server lock-test + $(ENV_SETUP) $(RUNTEST) --tool api RPC=0 API=$(SRVTCL) \ + LOCKTEST=./lock-test \ + KADMIN_LOCAL=$(BUILDTOP)/kadmin/cli/kadmin.local \ +@@ -140,4 +140,4 @@ clean: + $(RM) lock-test lock-test.o + $(RM) server-iter-test iter-test.o + $(RM) server-setkey-test client-setkey-test setkey-test.o +- $(RM) *.log *.plog *.sum *.psum unit-test-log.* runenv.exp ++ $(RM) *.log *.plog *.sum *.psum testsuite-log.* runenv.exp +diff --git a/src/lib/kadm5/unit-test/api.2/crte-policy.exp b/src/lib/kadm5/testsuite/api.2/crte-policy.exp +similarity index 100% +rename from src/lib/kadm5/unit-test/api.2/crte-policy.exp +rename to src/lib/kadm5/testsuite/api.2/crte-policy.exp +diff --git a/src/lib/kadm5/unit-test/api.2/get-policy.exp b/src/lib/kadm5/testsuite/api.2/get-policy.exp +similarity index 100% +rename from src/lib/kadm5/unit-test/api.2/get-policy.exp +rename to src/lib/kadm5/testsuite/api.2/get-policy.exp +diff --git a/src/lib/kadm5/unit-test/api.2/mod-policy.exp b/src/lib/kadm5/testsuite/api.2/mod-policy.exp +similarity index 100% +rename from src/lib/kadm5/unit-test/api.2/mod-policy.exp +rename to src/lib/kadm5/testsuite/api.2/mod-policy.exp +diff --git a/src/lib/kadm5/unit-test/api.current/chpass-principal-v2.exp b/src/lib/kadm5/testsuite/api.current/chpass-principal-v2.exp +similarity index 100% +rename from src/lib/kadm5/unit-test/api.current/chpass-principal-v2.exp +rename to src/lib/kadm5/testsuite/api.current/chpass-principal-v2.exp +diff --git a/src/lib/kadm5/unit-test/api.current/chpass-principal.exp b/src/lib/kadm5/testsuite/api.current/chpass-principal.exp +similarity index 100% +rename from src/lib/kadm5/unit-test/api.current/chpass-principal.exp +rename to src/lib/kadm5/testsuite/api.current/chpass-principal.exp +diff --git a/src/lib/kadm5/unit-test/api.current/crte-policy.exp b/src/lib/kadm5/testsuite/api.current/crte-policy.exp +similarity index 100% +rename from src/lib/kadm5/unit-test/api.current/crte-policy.exp +rename to src/lib/kadm5/testsuite/api.current/crte-policy.exp +diff --git a/src/lib/kadm5/unit-test/api.current/crte-principal.exp b/src/lib/kadm5/testsuite/api.current/crte-principal.exp +similarity index 100% +rename from src/lib/kadm5/unit-test/api.current/crte-principal.exp +rename to src/lib/kadm5/testsuite/api.current/crte-principal.exp +diff --git a/src/lib/kadm5/unit-test/api.current/destroy.exp b/src/lib/kadm5/testsuite/api.current/destroy.exp +similarity index 100% +rename from src/lib/kadm5/unit-test/api.current/destroy.exp +rename to src/lib/kadm5/testsuite/api.current/destroy.exp +diff --git a/src/lib/kadm5/unit-test/api.current/dlte-policy.exp b/src/lib/kadm5/testsuite/api.current/dlte-policy.exp +similarity index 100% +rename from src/lib/kadm5/unit-test/api.current/dlte-policy.exp +rename to src/lib/kadm5/testsuite/api.current/dlte-policy.exp +diff --git a/src/lib/kadm5/unit-test/api.current/dlte-principal.exp b/src/lib/kadm5/testsuite/api.current/dlte-principal.exp +similarity index 100% +rename from src/lib/kadm5/unit-test/api.current/dlte-principal.exp +rename to src/lib/kadm5/testsuite/api.current/dlte-principal.exp +diff --git a/src/lib/kadm5/unit-test/api.current/get-policy.exp b/src/lib/kadm5/testsuite/api.current/get-policy.exp +similarity index 100% +rename from src/lib/kadm5/unit-test/api.current/get-policy.exp +rename to src/lib/kadm5/testsuite/api.current/get-policy.exp +diff --git a/src/lib/kadm5/unit-test/api.current/get-principal-v2.exp b/src/lib/kadm5/testsuite/api.current/get-principal-v2.exp +similarity index 100% +rename from src/lib/kadm5/unit-test/api.current/get-principal-v2.exp +rename to src/lib/kadm5/testsuite/api.current/get-principal-v2.exp +diff --git a/src/lib/kadm5/unit-test/api.current/get-principal.exp b/src/lib/kadm5/testsuite/api.current/get-principal.exp +similarity index 100% +rename from src/lib/kadm5/unit-test/api.current/get-principal.exp +rename to src/lib/kadm5/testsuite/api.current/get-principal.exp +diff --git a/src/lib/kadm5/unit-test/api.current/init-v2.exp b/src/lib/kadm5/testsuite/api.current/init-v2.exp +similarity index 100% +rename from src/lib/kadm5/unit-test/api.current/init-v2.exp +rename to src/lib/kadm5/testsuite/api.current/init-v2.exp +diff --git a/src/lib/kadm5/unit-test/api.current/init.exp b/src/lib/kadm5/testsuite/api.current/init.exp +similarity index 100% +rename from src/lib/kadm5/unit-test/api.current/init.exp +rename to src/lib/kadm5/testsuite/api.current/init.exp +diff --git a/src/lib/kadm5/unit-test/api.current/mod-policy.exp b/src/lib/kadm5/testsuite/api.current/mod-policy.exp +similarity index 100% +rename from src/lib/kadm5/unit-test/api.current/mod-policy.exp +rename to src/lib/kadm5/testsuite/api.current/mod-policy.exp +diff --git a/src/lib/kadm5/unit-test/api.current/mod-principal-v2.exp b/src/lib/kadm5/testsuite/api.current/mod-principal-v2.exp +similarity index 100% +rename from src/lib/kadm5/unit-test/api.current/mod-principal-v2.exp +rename to src/lib/kadm5/testsuite/api.current/mod-principal-v2.exp +diff --git a/src/lib/kadm5/unit-test/api.current/mod-principal.exp b/src/lib/kadm5/testsuite/api.current/mod-principal.exp +similarity index 100% +rename from src/lib/kadm5/unit-test/api.current/mod-principal.exp +rename to src/lib/kadm5/testsuite/api.current/mod-principal.exp +diff --git a/src/lib/kadm5/unit-test/api.current/randkey-principal-v2.exp b/src/lib/kadm5/testsuite/api.current/randkey-principal-v2.exp +similarity index 100% +rename from src/lib/kadm5/unit-test/api.current/randkey-principal-v2.exp +rename to src/lib/kadm5/testsuite/api.current/randkey-principal-v2.exp +diff --git a/src/lib/kadm5/unit-test/api.current/randkey-principal.exp b/src/lib/kadm5/testsuite/api.current/randkey-principal.exp +similarity index 100% +rename from src/lib/kadm5/unit-test/api.current/randkey-principal.exp +rename to src/lib/kadm5/testsuite/api.current/randkey-principal.exp +diff --git a/src/lib/kadm5/unit-test/config/unix.exp b/src/lib/kadm5/testsuite/config/unix.exp +similarity index 100% +rename from src/lib/kadm5/unit-test/config/unix.exp +rename to src/lib/kadm5/testsuite/config/unix.exp +diff --git a/src/lib/kadm5/unit-test/deps b/src/lib/kadm5/testsuite/deps +similarity index 100% +rename from src/lib/kadm5/unit-test/deps +rename to src/lib/kadm5/testsuite/deps +diff --git a/src/lib/kadm5/unit-test/destroy-test.c b/src/lib/kadm5/testsuite/destroy-test.c +similarity index 100% +rename from src/lib/kadm5/unit-test/destroy-test.c +rename to src/lib/kadm5/testsuite/destroy-test.c +diff --git a/src/lib/kadm5/unit-test/diff-files/destroy-1 b/src/lib/kadm5/testsuite/diff-files/destroy-1 +similarity index 100% +rename from src/lib/kadm5/unit-test/diff-files/destroy-1 +rename to src/lib/kadm5/testsuite/diff-files/destroy-1 +diff --git a/src/lib/kadm5/unit-test/diff-files/no-diffs b/src/lib/kadm5/testsuite/diff-files/no-diffs +similarity index 100% +rename from src/lib/kadm5/unit-test/diff-files/no-diffs +rename to src/lib/kadm5/testsuite/diff-files/no-diffs +diff --git a/src/lib/kadm5/unit-test/handle-test.c b/src/lib/kadm5/testsuite/handle-test.c +similarity index 100% +rename from src/lib/kadm5/unit-test/handle-test.c +rename to src/lib/kadm5/testsuite/handle-test.c +diff --git a/src/lib/kadm5/unit-test/init-test.c b/src/lib/kadm5/testsuite/init-test.c +similarity index 100% +rename from src/lib/kadm5/unit-test/init-test.c +rename to src/lib/kadm5/testsuite/init-test.c +diff --git a/src/lib/kadm5/unit-test/iter-test.c b/src/lib/kadm5/testsuite/iter-test.c +similarity index 100% +rename from src/lib/kadm5/unit-test/iter-test.c +rename to src/lib/kadm5/testsuite/iter-test.c +diff --git a/src/lib/kadm5/unit-test/lib/lib.t b/src/lib/kadm5/testsuite/lib/lib.t +similarity index 99% +rename from src/lib/kadm5/unit-test/lib/lib.t +rename to src/lib/kadm5/testsuite/lib/lib.t +index 3444775cf..327946849 100644 +--- a/src/lib/kadm5/unit-test/lib/lib.t ++++ b/src/lib/kadm5/testsuite/lib/lib.t +@@ -226,7 +226,7 @@ proc end_dump_compare {name} { + global RPC + + if { ! $RPC } { +-# set file $TOP/admin/lib/unit-test/diff-files/$name ++# set file $TOP/admin/lib/testsuite/diff-files/$name + # exec $env(SIMPLE_DUMP) > /tmp/dump.after + # exec $env(COMPARE_DUMP) /tmp/dump.before /tmp/dump.after $file + } +diff --git a/src/lib/kadm5/unit-test/lock-test.c b/src/lib/kadm5/testsuite/lock-test.c +similarity index 100% +rename from src/lib/kadm5/unit-test/lock-test.c +rename to src/lib/kadm5/testsuite/lock-test.c +diff --git a/src/lib/kadm5/unit-test/randkey-test.c b/src/lib/kadm5/testsuite/randkey-test.c +similarity index 100% +rename from src/lib/kadm5/unit-test/randkey-test.c +rename to src/lib/kadm5/testsuite/randkey-test.c +diff --git a/src/lib/kadm5/unit-test/setkey-test.c b/src/lib/kadm5/testsuite/setkey-test.c +similarity index 100% +rename from src/lib/kadm5/unit-test/setkey-test.c +rename to src/lib/kadm5/testsuite/setkey-test.c +diff --git a/src/lib/kadm5/unit-test/site.exp b/src/lib/kadm5/testsuite/site.exp +similarity index 100% +rename from src/lib/kadm5/unit-test/site.exp +rename to src/lib/kadm5/testsuite/site.exp +-- +2.35.1 + diff --git a/root/ppg/common/deps/krb5/rpm/downstream-fix-debuginfo-with-y.tab.c.patch b/root/ppg/common/deps/krb5/rpm/downstream-fix-debuginfo-with-y.tab.c.patch new file mode 100644 index 00000000..fc1c8a45 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/downstream-fix-debuginfo-with-y.tab.c.patch @@ -0,0 +1,42 @@ +From 7f382fc40e082416e90f1e80c9fd0c91afa5baf7 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Tue, 23 Aug 2016 16:49:25 -0400 +Subject: [PATCH] [downstream] fix debuginfo with y.tab.c + +We want to keep these y.tab.c files around because the debuginfo points to +them. It would be more elegant at the end to use symbolic links, but that +could mess up people working in the tree on other things. + +Last-updated: krb5-1.9 +(cherry picked from commit f4002f246332695d8ea12ec803139fcac18fbba2) +--- + src/kadmin/cli/Makefile.in | 5 +++++ + src/plugins/kdb/ldap/ldap_util/Makefile.in | 2 +- + 2 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/src/kadmin/cli/Makefile.in b/src/kadmin/cli/Makefile.in +index adfea6e2b..d1327e400 100644 +--- a/src/kadmin/cli/Makefile.in ++++ b/src/kadmin/cli/Makefile.in +@@ -37,3 +37,8 @@ clean-unix:: + # CC_LINK is not meant for compilation and this use may break in the future. + datetest: getdate.c + $(CC_LINK) $(ALL_CFLAGS) -DTEST -o datetest getdate.c ++ ++%.c: %.y ++ $(RM) y.tab.c $@ ++ $(YACC.y) $< ++ $(CP) y.tab.c $@ +diff --git a/src/plugins/kdb/ldap/ldap_util/Makefile.in b/src/plugins/kdb/ldap/ldap_util/Makefile.in +index 8669c2436..a22f23c02 100644 +--- a/src/plugins/kdb/ldap/ldap_util/Makefile.in ++++ b/src/plugins/kdb/ldap/ldap_util/Makefile.in +@@ -20,7 +20,7 @@ $(PROG): $(OBJS) $(KADMSRV_DEPLIBS) $(KRB5_BASE_DEPLIB) $(GETDATE) + getdate.c: $(GETDATE) + $(RM) getdate.c y.tab.c + $(YACC) $(GETDATE) +- $(MV) y.tab.c getdate.c ++ $(CP) y.tab.c getdate.c + + install: + $(INSTALL_PROGRAM) $(PROG) ${DESTDIR}$(ADMIN_BINDIR)/$(PROG) diff --git a/root/ppg/common/deps/krb5/rpm/downstream-ksu-pam-integration.patch b/root/ppg/common/deps/krb5/rpm/downstream-ksu-pam-integration.patch new file mode 100644 index 00000000..d21ed37b --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/downstream-ksu-pam-integration.patch @@ -0,0 +1,775 @@ +From 664bdd73b620f00d42e36e3888805fe0f035c8ee Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Tue, 23 Aug 2016 16:29:58 -0400 +Subject: [PATCH] [downstream] ksu pam integration + +Modify ksu so that it performs account and session management on behalf of +the target user account, mimicking the action of regular su. The default +service name is "ksu", because on Fedora at least the configuration used +is determined by whether or not a login shell is being opened, and so +this may need to vary, too. At run-time, ksu's behavior can be reset to +the earlier, non-PAM behavior by setting "use_pam" to false in the [ksu] +section of /etc/krb5.conf. + +When enabled, ksu gains a dependency on libpam. + +Originally RT#5939, though it's changed since then to perform the account +and session management before dropping privileges, and to apply on top of +changes we're proposing for how it handles cache collections. + +Last-updated: krb5-1.18-beta1 +(cherry picked from commit a7322a84657752c886c317a6994a9fc7a4a70ca5) +--- + src/aclocal.m4 | 69 +++++++ + src/clients/ksu/Makefile.in | 8 +- + src/clients/ksu/main.c | 88 +++++++- + src/clients/ksu/pam.c | 389 ++++++++++++++++++++++++++++++++++++ + src/clients/ksu/pam.h | 57 ++++++ + src/configure.ac | 2 + + 6 files changed, 610 insertions(+), 3 deletions(-) + create mode 100644 src/clients/ksu/pam.c + create mode 100644 src/clients/ksu/pam.h + +diff --git a/src/aclocal.m4 b/src/aclocal.m4 +index 2394f7e33..830203683 100644 +--- a/src/aclocal.m4 ++++ b/src/aclocal.m4 +@@ -1675,3 +1675,72 @@ if test "$with_ldap" = yes; then + OPENLDAP_PLUGIN=yes + fi + ])dnl ++dnl ++dnl ++dnl Use PAM instead of local crypt() compare for checking local passwords, ++dnl and perform PAM account, session management, and password-changing where ++dnl appropriate. ++dnl ++AC_DEFUN(KRB5_WITH_PAM,[ ++AC_ARG_WITH(pam,[AC_HELP_STRING(--with-pam,[compile with PAM support])], ++ withpam="$withval",withpam=auto) ++AC_ARG_WITH(pam-ksu-service,[AC_HELP_STRING(--with-ksu-service,[PAM service name for ksu ["ksu"]])], ++ withksupamservice="$withval",withksupamservice=ksu) ++old_LIBS="$LIBS" ++if test "$withpam" != no ; then ++ AC_MSG_RESULT([checking for PAM...]) ++ PAM_LIBS= ++ ++ AC_CHECK_HEADERS(security/pam_appl.h) ++ if test "x$ac_cv_header_security_pam_appl_h" != xyes ; then ++ if test "$withpam" = auto ; then ++ AC_MSG_RESULT([Unable to locate security/pam_appl.h.]) ++ withpam=no ++ else ++ AC_MSG_ERROR([Unable to locate security/pam_appl.h.]) ++ fi ++ fi ++ ++ LIBS= ++ unset ac_cv_func_pam_start ++ AC_CHECK_FUNCS(putenv pam_start) ++ if test "x$ac_cv_func_pam_start" = xno ; then ++ unset ac_cv_func_pam_start ++ AC_CHECK_LIB(dl,dlopen) ++ AC_CHECK_FUNCS(pam_start) ++ if test "x$ac_cv_func_pam_start" = xno ; then ++ AC_CHECK_LIB(pam,pam_start) ++ unset ac_cv_func_pam_start ++ unset ac_cv_func_pam_getenvlist ++ AC_CHECK_FUNCS(pam_start pam_getenvlist) ++ if test "x$ac_cv_func_pam_start" = xyes ; then ++ PAM_LIBS="$LIBS" ++ else ++ if test "$withpam" = auto ; then ++ AC_MSG_RESULT([Unable to locate libpam.]) ++ withpam=no ++ else ++ AC_MSG_ERROR([Unable to locate libpam.]) ++ fi ++ fi ++ fi ++ fi ++ if test "$withpam" != no ; then ++ AC_MSG_NOTICE([building with PAM support]) ++ AC_DEFINE(USE_PAM,1,[Define if Kerberos-aware tools should support PAM]) ++ AC_DEFINE_UNQUOTED(KSU_PAM_SERVICE,"$withksupamservice", ++ [Define to the name of the PAM service name to be used by ksu.]) ++ PAM_LIBS="$LIBS" ++ NON_PAM_MAN=".\\\" " ++ PAM_MAN= ++ else ++ PAM_MAN=".\\\" " ++ NON_PAM_MAN= ++ fi ++fi ++LIBS="$old_LIBS" ++AC_SUBST(PAM_LIBS) ++AC_SUBST(PAM_MAN) ++AC_SUBST(NON_PAM_MAN) ++])dnl ++ +diff --git a/src/clients/ksu/Makefile.in b/src/clients/ksu/Makefile.in +index 8b4edce4d..9d58f29b5 100644 +--- a/src/clients/ksu/Makefile.in ++++ b/src/clients/ksu/Makefile.in +@@ -3,12 +3,14 @@ BUILDTOP=$(REL)..$(S).. + DEFINES = -DGET_TGT_VIA_PASSWD -DPRINC_LOOK_AHEAD -DCMD_PATH='"/usr/local/sbin /usr/local/bin /sbin /bin /usr/sbin /usr/bin"' + + KSU_LIBS=@KSU_LIBS@ ++PAM_LIBS=@PAM_LIBS@ + + SRCS = \ + $(srcdir)/krb_auth_su.c \ + $(srcdir)/ccache.c \ + $(srcdir)/authorization.c \ + $(srcdir)/main.c \ ++ $(srcdir)/pam.c \ + $(srcdir)/heuristic.c \ + $(srcdir)/xmalloc.c \ + $(srcdir)/setenv.c +@@ -17,13 +19,17 @@ OBJS = \ + ccache.o \ + authorization.o \ + main.o \ ++ pam.o \ + heuristic.o \ + xmalloc.o @SETENVOBJ@ + + all: ksu + + ksu: $(OBJS) $(KRB5_BASE_DEPLIBS) +- $(CC_LINK) -o $@ $(OBJS) $(KRB5_BASE_LIBS) $(KSU_LIBS) ++ $(CC_LINK) -o $@ $(OBJS) $(KRB5_BASE_LIBS) $(KSU_LIBS) $(PAM_LIBS) ++ ++pam.o: pam.c ++ $(CC) $(ALL_CFLAGS) -c $< + + clean: + $(RM) ksu +diff --git a/src/clients/ksu/main.c b/src/clients/ksu/main.c +index 57c349200..508242e0e 100644 +--- a/src/clients/ksu/main.c ++++ b/src/clients/ksu/main.c +@@ -26,6 +26,7 @@ + * KSU was writen by: Ari Medvinsky, ari@isi.edu + */ + ++#include "autoconf.h" + #include "ksu.h" + #include "adm_proto.h" + #include +@@ -33,6 +34,10 @@ + #include + #include + ++#ifdef USE_PAM ++#include "pam.h" ++#endif ++ + /* globals */ + char * prog_name; + int auth_debug =0; +@@ -40,6 +45,7 @@ char k5login_path[MAXPATHLEN]; + char k5users_path[MAXPATHLEN]; + char * gb_err = NULL; + int quiet = 0; ++int force_fork = 0; + /***********/ + + #define KS_TEMPORARY_CACHE "MEMORY:_ksu" +@@ -536,6 +542,23 @@ main (argc, argv) + prog_name,target_user,client_name, + source_user,ontty()); + ++#ifdef USE_PAM ++ if (appl_pam_enabled(ksu_context, "ksu")) { ++ if (appl_pam_acct_mgmt(KSU_PAM_SERVICE, 1, target_user, NULL, ++ NULL, source_user, ++ ttyname(STDERR_FILENO)) != 0) { ++ fprintf(stderr, "Access denied for %s.\n", target_user); ++ exit(1); ++ } ++ if (appl_pam_requires_chauthtok()) { ++ fprintf(stderr, "Password change required for %s.\n", ++ target_user); ++ exit(1); ++ } ++ force_fork++; ++ } ++#endif ++ + /* Run authorization as target.*/ + if (krb5_seteuid(target_uid)) { + com_err(prog_name, errno, _("while switching to target for " +@@ -596,6 +619,24 @@ main (argc, argv) + + exit(1); + } ++#ifdef USE_PAM ++ } else { ++ /* we always do PAM account management, even for root */ ++ if (appl_pam_enabled(ksu_context, "ksu")) { ++ if (appl_pam_acct_mgmt(KSU_PAM_SERVICE, 1, target_user, NULL, ++ NULL, source_user, ++ ttyname(STDERR_FILENO)) != 0) { ++ fprintf(stderr, "Access denied for %s.\n", target_user); ++ exit(1); ++ } ++ if (appl_pam_requires_chauthtok()) { ++ fprintf(stderr, "Password change required for %s.\n", ++ target_user); ++ exit(1); ++ } ++ force_fork++; ++ } ++#endif + } + + if( some_rest_copy){ +@@ -653,6 +694,30 @@ main (argc, argv) + exit(1); + } + ++#ifdef USE_PAM ++ if (appl_pam_enabled(ksu_context, "ksu")) { ++ if (appl_pam_session_open() != 0) { ++ fprintf(stderr, "Error opening session for %s.\n", target_user); ++ exit(1); ++ } ++#ifdef DEBUG ++ if (auth_debug){ ++ printf(" Opened PAM session.\n"); ++ } ++#endif ++ if (appl_pam_cred_init()) { ++ fprintf(stderr, "Error initializing credentials for %s.\n", ++ target_user); ++ exit(1); ++ } ++#ifdef DEBUG ++ if (auth_debug){ ++ printf(" Initialized PAM credentials.\n"); ++ } ++#endif ++ } ++#endif ++ + /* set permissions */ + if (setgid(target_pwd->pw_gid) < 0) { + perror("ksu: setgid"); +@@ -750,7 +815,7 @@ main (argc, argv) + fprintf(stderr, "program to be execed %s\n",params[0]); + } + +- if( keep_target_cache ) { ++ if( keep_target_cache && !force_fork ) { + execv(params[0], params); + com_err(prog_name, errno, _("while trying to execv %s"), params[0]); + sweep_up(ksu_context, cc_target); +@@ -780,16 +845,35 @@ main (argc, argv) + if (ret_pid == -1) { + com_err(prog_name, errno, _("while calling waitpid")); + } +- sweep_up(ksu_context, cc_target); ++ if( !keep_target_cache ) { ++ sweep_up(ksu_context, cc_target); ++ } + exit (statusp); + case -1: + com_err(prog_name, errno, _("while trying to fork.")); + sweep_up(ksu_context, cc_target); + exit (1); + case 0: ++#ifdef USE_PAM ++ if (appl_pam_enabled(ksu_context, "ksu")) { ++ if (appl_pam_setenv() != 0) { ++ fprintf(stderr, "Error setting up environment for %s.\n", ++ target_user); ++ exit (1); ++ } ++#ifdef DEBUG ++ if (auth_debug){ ++ printf(" Set up PAM environment.\n"); ++ } ++#endif ++ } ++#endif + execv(params[0], params); + com_err(prog_name, errno, _("while trying to execv %s"), + params[0]); ++ if( keep_target_cache ) { ++ sweep_up(ksu_context, cc_target); ++ } + exit (1); + } + } +diff --git a/src/clients/ksu/pam.c b/src/clients/ksu/pam.c +new file mode 100644 +index 000000000..cbfe48704 +--- /dev/null ++++ b/src/clients/ksu/pam.c +@@ -0,0 +1,389 @@ ++/* ++ * src/clients/ksu/pam.c ++ * ++ * Copyright 2007,2009,2010 Red Hat, Inc. ++ * ++ * All Rights Reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * ++ * Redistributions of source code must retain the above copyright notice, this ++ * list of conditions and the following disclaimer. ++ * ++ * Redistributions in binary form must reproduce the above copyright notice, ++ * this list of conditions and the following disclaimer in the documentation ++ * and/or other materials provided with the distribution. ++ * ++ * Neither the name of Red Hat, Inc. nor the names of its contributors may be ++ * used to endorse or promote products derived from this software without ++ * specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ * ++ * Convenience wrappers for using PAM. ++ */ ++ ++#include "autoconf.h" ++#ifdef USE_PAM ++#include ++#include ++#include ++#include ++#include ++#include "k5-int.h" ++#include "pam.h" ++ ++#ifndef MAXPWSIZE ++#define MAXPWSIZE 128 ++#endif ++ ++static int appl_pam_started; ++static pid_t appl_pam_starter = -1; ++static int appl_pam_session_opened; ++static int appl_pam_creds_initialized; ++static int appl_pam_pwchange_required; ++static pam_handle_t *appl_pamh; ++static struct pam_conv appl_pam_conv; ++static char *appl_pam_user; ++struct appl_pam_non_interactive_args { ++ const char *user; ++ const char *password; ++}; ++ ++int ++appl_pam_enabled(krb5_context context, const char *section) ++{ ++ int enabled = 1; ++ if ((context != NULL) && (context->profile != NULL)) { ++ if (profile_get_boolean(context->profile, ++ section, ++ USE_PAM_CONFIGURATION_KEYWORD, ++ NULL, ++ enabled, &enabled) != 0) { ++ enabled = 1; ++ } ++ } ++ return enabled; ++} ++ ++void ++appl_pam_cleanup(void) ++{ ++ if (getpid() != appl_pam_starter) { ++ return; ++ } ++#ifdef DEBUG ++ printf("Called to clean up PAM.\n"); ++#endif ++ if (appl_pam_creds_initialized) { ++#ifdef DEBUG ++ printf("Deleting PAM credentials.\n"); ++#endif ++ pam_setcred(appl_pamh, PAM_DELETE_CRED); ++ appl_pam_creds_initialized = 0; ++ } ++ if (appl_pam_session_opened) { ++#ifdef DEBUG ++ printf("Closing PAM session.\n"); ++#endif ++ pam_close_session(appl_pamh, 0); ++ appl_pam_session_opened = 0; ++ } ++ appl_pam_pwchange_required = 0; ++ if (appl_pam_started) { ++#ifdef DEBUG ++ printf("Shutting down PAM.\n"); ++#endif ++ pam_end(appl_pamh, 0); ++ appl_pam_started = 0; ++ appl_pam_starter = -1; ++ free(appl_pam_user); ++ appl_pam_user = NULL; ++ } ++} ++static int ++appl_pam_interactive_converse(int num_msg, const struct pam_message **msg, ++ struct pam_response **presp, void *appdata_ptr) ++{ ++ const struct pam_message *message; ++ struct pam_response *resp; ++ int i, code; ++ char *pwstring, pwbuf[MAXPWSIZE]; ++ unsigned int pwsize; ++ resp = malloc(sizeof(struct pam_response) * num_msg); ++ if (resp == NULL) { ++ return PAM_BUF_ERR; ++ } ++ memset(resp, 0, sizeof(struct pam_response) * num_msg); ++ code = PAM_SUCCESS; ++ for (i = 0; i < num_msg; i++) { ++ message = &(msg[0][i]); /* XXX */ ++ message = msg[i]; /* XXX */ ++ pwstring = NULL; ++ switch (message->msg_style) { ++ case PAM_TEXT_INFO: ++ case PAM_ERROR_MSG: ++ printf("[%s]\n", message->msg ? message->msg : ""); ++ fflush(stdout); ++ resp[i].resp = NULL; ++ resp[i].resp_retcode = PAM_SUCCESS; ++ break; ++ case PAM_PROMPT_ECHO_ON: ++ case PAM_PROMPT_ECHO_OFF: ++ if (message->msg_style == PAM_PROMPT_ECHO_ON) { ++ if (fgets(pwbuf, sizeof(pwbuf), ++ stdin) != NULL) { ++ pwbuf[strcspn(pwbuf, "\r\n")] = '\0'; ++ pwstring = pwbuf; ++ } ++ } else { ++ pwstring = getpass(message->msg ? ++ message->msg : ++ ""); ++ } ++ if ((pwstring != NULL) && (pwstring[0] != '\0')) { ++ pwsize = strlen(pwstring); ++ resp[i].resp = malloc(pwsize + 1); ++ if (resp[i].resp == NULL) { ++ resp[i].resp_retcode = PAM_BUF_ERR; ++ } else { ++ memcpy(resp[i].resp, pwstring, pwsize); ++ resp[i].resp[pwsize] = '\0'; ++ resp[i].resp_retcode = PAM_SUCCESS; ++ } ++ } else { ++ resp[i].resp_retcode = PAM_CONV_ERR; ++ code = PAM_CONV_ERR; ++ } ++ break; ++ default: ++ break; ++ } ++ } ++ *presp = resp; ++ return code; ++} ++static int ++appl_pam_non_interactive_converse(int num_msg, ++ const struct pam_message **msg, ++ struct pam_response **presp, ++ void *appdata_ptr) ++{ ++ const struct pam_message *message; ++ struct pam_response *resp; ++ int i, code; ++ unsigned int pwsize; ++ struct appl_pam_non_interactive_args *args; ++ const char *pwstring; ++ resp = malloc(sizeof(struct pam_response) * num_msg); ++ if (resp == NULL) { ++ return PAM_BUF_ERR; ++ } ++ args = appdata_ptr; ++ memset(resp, 0, sizeof(struct pam_response) * num_msg); ++ code = PAM_SUCCESS; ++ for (i = 0; i < num_msg; i++) { ++ message = &((*msg)[i]); ++ message = msg[i]; ++ pwstring = NULL; ++ switch (message->msg_style) { ++ case PAM_TEXT_INFO: ++ case PAM_ERROR_MSG: ++ break; ++ case PAM_PROMPT_ECHO_ON: ++ case PAM_PROMPT_ECHO_OFF: ++ if (message->msg_style == PAM_PROMPT_ECHO_ON) { ++ /* assume "user" */ ++ pwstring = args->user; ++ } else { ++ /* assume "password" */ ++ pwstring = args->password; ++ } ++ if ((pwstring != NULL) && (pwstring[0] != '\0')) { ++ pwsize = strlen(pwstring); ++ resp[i].resp = malloc(pwsize + 1); ++ if (resp[i].resp == NULL) { ++ resp[i].resp_retcode = PAM_BUF_ERR; ++ } else { ++ memcpy(resp[i].resp, pwstring, pwsize); ++ resp[i].resp[pwsize] = '\0'; ++ resp[i].resp_retcode = PAM_SUCCESS; ++ } ++ } else { ++ resp[i].resp_retcode = PAM_CONV_ERR; ++ code = PAM_CONV_ERR; ++ } ++ break; ++ default: ++ break; ++ } ++ } ++ *presp = resp; ++ return code; ++} ++static int ++appl_pam_start(const char *service, int interactive, ++ const char *login_username, ++ const char *non_interactive_password, ++ const char *hostname, ++ const char *ruser, ++ const char *tty) ++{ ++ static int exit_handler_registered; ++ static struct appl_pam_non_interactive_args args; ++ int ret = 0; ++ if (appl_pam_started && ++ (strcmp(login_username, appl_pam_user) != 0)) { ++ appl_pam_cleanup(); ++ appl_pam_user = NULL; ++ } ++ if (!appl_pam_started) { ++#ifdef DEBUG ++ printf("Starting PAM up (service=\"%s\",user=\"%s\").\n", ++ service, login_username); ++#endif ++ memset(&appl_pam_conv, 0, sizeof(appl_pam_conv)); ++ appl_pam_conv.conv = interactive ? ++ &appl_pam_interactive_converse : ++ &appl_pam_non_interactive_converse; ++ memset(&args, 0, sizeof(args)); ++ args.user = strdup(login_username); ++ args.password = non_interactive_password ? ++ strdup(non_interactive_password) : ++ NULL; ++ appl_pam_conv.appdata_ptr = &args; ++ ret = pam_start(service, login_username, ++ &appl_pam_conv, &appl_pamh); ++ if (ret == 0) { ++ if (hostname != NULL) { ++#ifdef DEBUG ++ printf("Setting PAM_RHOST to \"%s\".\n", hostname); ++#endif ++ pam_set_item(appl_pamh, PAM_RHOST, hostname); ++ } ++ if (ruser != NULL) { ++#ifdef DEBUG ++ printf("Setting PAM_RUSER to \"%s\".\n", ruser); ++#endif ++ pam_set_item(appl_pamh, PAM_RUSER, ruser); ++ } ++ if (tty != NULL) { ++#ifdef DEBUG ++ printf("Setting PAM_TTY to \"%s\".\n", tty); ++#endif ++ pam_set_item(appl_pamh, PAM_TTY, tty); ++ } ++ if (!exit_handler_registered && ++ (atexit(appl_pam_cleanup) != 0)) { ++ pam_end(appl_pamh, 0); ++ appl_pamh = NULL; ++ ret = -1; ++ } else { ++ appl_pam_started = 1; ++ appl_pam_starter = getpid(); ++ appl_pam_user = strdup(login_username); ++ exit_handler_registered = 1; ++ } ++ } ++ } ++ return ret; ++} ++int ++appl_pam_acct_mgmt(const char *service, int interactive, ++ const char *login_username, ++ const char *non_interactive_password, ++ const char *hostname, ++ const char *ruser, ++ const char *tty) ++{ ++ int ret; ++ appl_pam_pwchange_required = 0; ++ ret = appl_pam_start(service, interactive, login_username, ++ non_interactive_password, hostname, ruser, tty); ++ if (ret == 0) { ++#ifdef DEBUG ++ printf("Calling pam_acct_mgmt().\n"); ++#endif ++ ret = pam_acct_mgmt(appl_pamh, 0); ++ switch (ret) { ++ case PAM_IGNORE: ++ ret = 0; ++ break; ++ case PAM_NEW_AUTHTOK_REQD: ++ appl_pam_pwchange_required = 1; ++ ret = 0; ++ break; ++ default: ++ break; ++ } ++ } ++ return ret; ++} ++int ++appl_pam_requires_chauthtok(void) ++{ ++ return appl_pam_pwchange_required; ++} ++int ++appl_pam_session_open(void) ++{ ++ int ret = 0; ++ if (appl_pam_started) { ++#ifdef DEBUG ++ printf("Opening PAM session.\n"); ++#endif ++ ret = pam_open_session(appl_pamh, 0); ++ if (ret == 0) { ++ appl_pam_session_opened = 1; ++ } ++ } ++ return ret; ++} ++int ++appl_pam_setenv(void) ++{ ++ int ret = 0; ++#ifdef HAVE_PAM_GETENVLIST ++#ifdef HAVE_PUTENV ++ int i; ++ char **list; ++ if (appl_pam_started) { ++ list = pam_getenvlist(appl_pamh); ++ for (i = 0; ((list != NULL) && (list[i] != NULL)); i++) { ++#ifdef DEBUG ++ printf("Setting \"%s\" in environment.\n", list[i]); ++#endif ++ putenv(list[i]); ++ } ++ } ++#endif ++#endif ++ return ret; ++} ++int ++appl_pam_cred_init(void) ++{ ++ int ret = 0; ++ if (appl_pam_started) { ++#ifdef DEBUG ++ printf("Initializing PAM credentials.\n"); ++#endif ++ ret = pam_setcred(appl_pamh, PAM_ESTABLISH_CRED); ++ if (ret == 0) { ++ appl_pam_creds_initialized = 1; ++ } ++ } ++ return ret; ++} ++#endif +diff --git a/src/clients/ksu/pam.h b/src/clients/ksu/pam.h +new file mode 100644 +index 000000000..0ab76569c +--- /dev/null ++++ b/src/clients/ksu/pam.h +@@ -0,0 +1,57 @@ ++/* ++ * src/clients/ksu/pam.h ++ * ++ * Copyright 2007,2009,2010 Red Hat, Inc. ++ * ++ * All Rights Reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * ++ * Redistributions of source code must retain the above copyright notice, this ++ * list of conditions and the following disclaimer. ++ * ++ * Redistributions in binary form must reproduce the above copyright notice, ++ * this list of conditions and the following disclaimer in the documentation ++ * and/or other materials provided with the distribution. ++ * ++ * Neither the name of Red Hat, Inc. nor the names of its contributors may be ++ * used to endorse or promote products derived from this software without ++ * specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ * ++ * Convenience wrappers for using PAM. ++ */ ++ ++#include ++#ifdef HAVE_SECURITY_PAM_APPL_H ++#include ++#endif ++ ++#define USE_PAM_CONFIGURATION_KEYWORD "use_pam" ++ ++#ifdef USE_PAM ++int appl_pam_enabled(krb5_context context, const char *section); ++int appl_pam_acct_mgmt(const char *service, int interactive, ++ const char *local_username, ++ const char *non_interactive_password, ++ const char *hostname, ++ const char *ruser, ++ const char *tty); ++int appl_pam_requires_chauthtok(void); ++int appl_pam_session_open(void); ++int appl_pam_setenv(void); ++int appl_pam_cred_init(void); ++void appl_pam_cleanup(void); ++#endif +diff --git a/src/configure.ac b/src/configure.ac +index 234f4281c..d1f576124 100644 +--- a/src/configure.ac ++++ b/src/configure.ac +@@ -1390,6 +1390,8 @@ AC_SUBST([VERTO_VERSION]) + + AC_PATH_PROG(GROFF, groff) + ++KRB5_WITH_PAM ++ + # Make localedir work in autoconf 2.5x. + if test "${localedir+set}" != set; then + localedir='$(datadir)/locale' diff --git a/root/ppg/common/deps/krb5/rpm/downstream-netlib-and-dns.patch b/root/ppg/common/deps/krb5/rpm/downstream-netlib-and-dns.patch new file mode 100644 index 00000000..b9660830 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/downstream-netlib-and-dns.patch @@ -0,0 +1,25 @@ +From 0a164c9c53a6f8ce20cfe5c6ef94ae5a2c2e9e28 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Tue, 23 Aug 2016 16:46:21 -0400 +Subject: [PATCH] [downstream] netlib and dns + +We want to be able to use --with-netlib and --enable-dns at the same time. + +Last-updated: krb5-1.3.1 +(cherry picked from commit 355dd481511af4d517ee540854f95a6fb12116a9) +--- + src/aclocal.m4 | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/aclocal.m4 b/src/aclocal.m4 +index 6796fec53..c4358988a 100644 +--- a/src/aclocal.m4 ++++ b/src/aclocal.m4 +@@ -724,6 +724,7 @@ AC_HELP_STRING([--with-netlib=LIBS], use user defined resolver library), + LIBS="$LIBS $withval" + AC_MSG_RESULT("netlib will use \'$withval\'") + fi ++ KRB5_AC_ENABLE_DNS + ],dnl + [AC_LIBRARY_NET] + )])dnl diff --git a/root/ppg/common/deps/krb5/rpm/kadm5.acl b/root/ppg/common/deps/krb5/rpm/kadm5.acl new file mode 100644 index 00000000..dc93eb0a --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/kadm5.acl @@ -0,0 +1 @@ +*/admin@EXAMPLE.COM * diff --git a/root/ppg/common/deps/krb5/rpm/kadmin.service b/root/ppg/common/deps/krb5/rpm/kadmin.service new file mode 100644 index 00000000..f1677c6c --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/kadmin.service @@ -0,0 +1,15 @@ +[Unit] +Description=Kerberos 5 Password-changing and Administration +Wants=network-online.target +After=syslog.target network.target network-online.target +AssertPathExists=!/var/kerberos/krb5kdc/kpropd.acl + +[Service] +Type=forking +PIDFile=/var/run/kadmind.pid +EnvironmentFile=-/etc/sysconfig/kadmin +ExecStart=/usr/sbin/kadmind -P /var/run/kadmind.pid $KADMIND_ARGS +ExecReload=/bin/kill -HUP $MAINPID + +[Install] +WantedBy=multi-user.target diff --git a/root/ppg/common/deps/krb5/rpm/kadmin.sysconfig b/root/ppg/common/deps/krb5/rpm/kadmin.sysconfig new file mode 100644 index 00000000..fa72039b --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/kadmin.sysconfig @@ -0,0 +1 @@ +KADMIND_ARGS= diff --git a/root/ppg/common/deps/krb5/rpm/kadmind.logrotate b/root/ppg/common/deps/krb5/rpm/kadmind.logrotate new file mode 100644 index 00000000..52a66c41 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/kadmind.logrotate @@ -0,0 +1,9 @@ +/var/log/kadmind.log { + missingok + notifempty + monthly + rotate 12 + postrotate + /bin/kill -HUP `cat /var/run/kadmind.pid 2>/dev/null` 2> /dev/null || true + endscript +} diff --git a/root/ppg/common/deps/krb5/rpm/kdc.conf b/root/ppg/common/deps/krb5/rpm/kdc.conf new file mode 100644 index 00000000..6b0c2b98 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/kdc.conf @@ -0,0 +1,17 @@ +[libdefaults] +# Allow RC4 HMAC-MD5 for session keys (see CVE-2022-37966) +#allow_rc4 = true + +[kdcdefaults] + kdc_ports = 88 + kdc_tcp_ports = 88 + spake_preauth_kdc_challenge = edwards25519 + +[realms] +EXAMPLE.COM = { + #master_key_type = aes256-cts + acl_file = /var/kerberos/krb5kdc/kadm5.acl + dict_file = /usr/share/dict/words + admin_keytab = /var/kerberos/krb5kdc/kadm5.keytab + supported_enctypes = aes256-cts:normal aes128-cts:normal arcfour-hmac:normal camellia256-cts:normal camellia128-cts:normal +} diff --git a/root/ppg/common/deps/krb5/rpm/kprop.service b/root/ppg/common/deps/krb5/rpm/kprop.service new file mode 100644 index 00000000..7b5d4b9b --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/kprop.service @@ -0,0 +1,13 @@ +[Unit] +Description=Kerberos 5 Propagation +Wants=network-online.target +After=syslog.target network.target network-online.target +AssertPathExists=/var/kerberos/krb5kdc/kpropd.acl + +[Service] +Type=forking +EnvironmentFile=-/etc/sysconfig/kprop +ExecStart=/usr/sbin/kpropd $KPROPD_ARGS + +[Install] +WantedBy=multi-user.target diff --git a/root/ppg/common/deps/krb5/rpm/kprop.sysconfig b/root/ppg/common/deps/krb5/rpm/kprop.sysconfig new file mode 100644 index 00000000..f43e8bb9 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/kprop.sysconfig @@ -0,0 +1 @@ +KPROPD_ARGS= diff --git a/root/ppg/common/deps/krb5/rpm/krb5-1.18.2-pdfs.tar b/root/ppg/common/deps/krb5/rpm/krb5-1.18.2-pdfs.tar new file mode 100644 index 00000000..e6969422 Binary files /dev/null and b/root/ppg/common/deps/krb5/rpm/krb5-1.18.2-pdfs.tar differ diff --git a/root/ppg/common/deps/krb5/rpm/krb5-1.18.2.tar.gz.asc b/root/ppg/common/deps/krb5/rpm/krb5-1.18.2.tar.gz.asc new file mode 100644 index 00000000..aea279d5 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/krb5-1.18.2.tar.gz.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEExEk8tzn0qJ+YUsvCDLoIV1+Dct8FAl7H9FAACgkQDLoIV1+D +ct+rjxAAqLlDjeExNw1sJyyjaAKzo7vGzK0tFVouMglmmGcyluVwsqu9B2uHw3UC +TIm4bn1rgGtUB5oKWmbeD+hiuoAghLDa6gSrmDDkJfFR+o/K/vE7BGZewrrp7QJ5 +jJnEhjuY9O+ZFM/ZNEwHa4/RNG1ga5uJUrfdlNkTUMFje5d1TXvx/ozuSk4bAUTF +nqHuJsyRAuhKcqTOZ9nr5a54me97CbWj7Be6sA7LQVaFDPyWcJCQsBHjFyextTOF +3ewsF7330B3oO8yE9/f+nxFq/x9ot6CctMXZqLzhbvdzcO2GwmwbvXy73ibhvjVU +w9n/zQ1xDjRO0z1wfM54Vq1upQW78+YXA33fEX6od0WBzdiR/o7hfU3arg/WraUy +pVcD9V7jvYhGPpqYwEdRhs4qROhAh/yvebZ+MVe/1Pd8kA4tTXtR+VmVkp21X3cq ++19eTz7actQemfdsUvfcL8guub0Mea/l+1l3cEHl20FOEeZ8RjpPMisYS9IrJ52O +3lro26vYFSWS4+U9j4gwdjuQwLS3xHuPZFwS7aykKGsIQ1r8l5Yb0xorDXXKKLjm +z4DNPaZbxxfcGhDWKTlDudrXEIAGTOD4FC1SJBV3hbqUsv4EH+EJnf92rmVMJ5z/ +AmeUKsL02Abl3BjhwaLWmhIwoXIUhcI/5xNsoI6ePCAT2HLyJlE= +=fGT7 +-----END PGP SIGNATURE----- diff --git a/root/ppg/common/deps/krb5/rpm/krb5-krad-larger-attrs.patch b/root/ppg/common/deps/krb5/rpm/krb5-krad-larger-attrs.patch new file mode 100644 index 00000000..8437921b --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/krb5-krad-larger-attrs.patch @@ -0,0 +1,69 @@ +From b2b7729d71e7ab2cde9c73b40b8e972c82a875a2 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Mon, 8 Nov 2021 17:48:50 +0100 +Subject: [PATCH] Support larger RADIUS attributes in libkrad + +In kr_attrset_decode(), explicitly treat the length byte as unsigned. +Otherwise attributes longer than 125 characters will be rejected with +EBADMSG. + +Add a 253-character-long NAS-Identifier attribute to the tests to make +sure that attributes with the maximal number of characters are working +as expected. + +[ghudson@mit.edu: used uint8_t cast per current practices; edited +commit message] + +ticket: 9036 (new) +--- + src/lib/krad/attrset.c | 2 +- + src/lib/krad/t_packet.c | 13 +++++++++++++ + 2 files changed, 14 insertions(+), 1 deletion(-) + +diff --git a/src/lib/krad/attrset.c b/src/lib/krad/attrset.c +index d89982a13..6ec031e32 100644 +--- a/src/lib/krad/attrset.c ++++ b/src/lib/krad/attrset.c +@@ -218,7 +218,7 @@ kr_attrset_decode(krb5_context ctx, const krb5_data *in, const char *secret, + + for (i = 0; i + 2 < in->length; ) { + type = in->data[i++]; +- tmp = make_data(&in->data[i + 1], in->data[i] - 2); ++ tmp = make_data(&in->data[i + 1], (uint8_t)in->data[i] - 2); + i += tmp.length + 1; + + retval = (in->length < i) ? EBADMSG : 0; +diff --git a/src/lib/krad/t_packet.c b/src/lib/krad/t_packet.c +index 0a92e9cc2..c22489144 100644 +--- a/src/lib/krad/t_packet.c ++++ b/src/lib/krad/t_packet.c +@@ -57,6 +57,14 @@ make_packet(krb5_context ctx, const krb5_data *username, + krb5_error_code retval; + const krb5_data *data; + int i = 0; ++ krb5_data nas_id; ++ ++ nas_id = string2data("12345678901234567890123456789012345678901234567890" ++ "12345678901234567890123456789012345678901234567890" ++ "12345678901234567890123456789012345678901234567890" ++ "12345678901234567890123456789012345678901234567890" ++ "12345678901234567890123456789012345678901234567890" ++ "123"); + + retval = krad_attrset_new(ctx, &set); + if (retval != 0) +@@ -71,6 +79,11 @@ make_packet(krb5_context ctx, const krb5_data *username, + if (retval != 0) + goto out; + ++ retval = krad_attrset_add(set, krad_attr_name2num("NAS-Identifier"), ++ &nas_id); ++ if (retval != 0) ++ goto out; ++ + retval = krad_packet_new_request(ctx, "foo", + krad_code_name2num("Access-Request"), + set, iterator, &i, &tmp); +-- +2.35.3 + diff --git a/root/ppg/common/deps/krb5/rpm/krb5-krad-remote.patch b/root/ppg/common/deps/krb5/rpm/krb5-krad-remote.patch new file mode 100644 index 00000000..d9c4d9ed --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/krb5-krad-remote.patch @@ -0,0 +1,171 @@ +From da677b071dadda3700d12d037f5896b166d3546d Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Tue, 9 Nov 2021 13:00:43 -0500 +Subject: [PATCH] Avoid use after free during libkrad cleanup + +libkrad client requests contain a list of references to remotes, with +no back-references or reference counts. To prevent accesses to +dangling references during cleanup, cancel all requests on all remotes +before freeing any remotes. + +Remove the code for aging out unused servers. This code was fairly +safe as all requests referencing a remote should have completed or +timed out during an hour of disuse, but in the current design we have +no way to guarantee or check that. The set of addresses we send +RADIUS requests to will generally be small, so aging out servers is +unnecessary. + +ticket: 9035 (new) +--- + src/lib/krad/client.c | 42 ++++++++++++++--------------------------- + src/lib/krad/internal.h | 4 ++++ + src/lib/krad/remote.c | 11 ++++++++--- + 3 files changed, 26 insertions(+), 31 deletions(-) + +diff --git a/src/lib/krad/client.c b/src/lib/krad/client.c +index 6365dd1c6..810940afc 100644 +--- a/src/lib/krad/client.c ++++ b/src/lib/krad/client.c +@@ -64,7 +64,6 @@ struct request_st { + + struct server_st { + krad_remote *serv; +- time_t last; + K5_LIST_ENTRY(server_st) list; + }; + +@@ -81,15 +80,10 @@ get_server(krad_client *rc, const struct addrinfo *ai, const char *secret, + krad_remote **out) + { + krb5_error_code retval; +- time_t currtime; + server *srv; + +- if (time(&currtime) == (time_t)-1) +- return errno; +- + K5_LIST_FOREACH(srv, &rc->servers, list) { + if (kr_remote_equals(srv->serv, ai, secret)) { +- srv->last = currtime; + *out = srv->serv; + return 0; + } +@@ -98,7 +92,6 @@ get_server(krad_client *rc, const struct addrinfo *ai, const char *secret, + srv = calloc(1, sizeof(server)); + if (srv == NULL) + return ENOMEM; +- srv->last = currtime; + + retval = kr_remote_new(rc->kctx, rc->vctx, ai, secret, &srv->serv); + if (retval != 0) { +@@ -173,28 +166,12 @@ request_new(krad_client *rc, krad_code code, const krad_attrset *attrs, + return 0; + } + +-/* Close remotes that haven't been used in a while. */ +-static void +-age(struct server_head *head, time_t currtime) +-{ +- server *srv, *tmp; +- +- K5_LIST_FOREACH_SAFE(srv, head, list, tmp) { +- if (currtime == (time_t)-1 || currtime - srv->last > 60 * 60) { +- K5_LIST_REMOVE(srv, list); +- kr_remote_free(srv->serv); +- free(srv); +- } +- } +-} +- + /* Handle a response from a server (or related errors). */ + static void + on_response(krb5_error_code retval, const krad_packet *reqp, + const krad_packet *rspp, void *data) + { + request *req = data; +- time_t currtime; + size_t i; + + /* Do nothing if we are already completed. */ +@@ -221,10 +198,6 @@ on_response(krb5_error_code retval, const krad_packet *reqp, + for (i = 0; req->remotes[i].remote != NULL; i++) + kr_remote_cancel(req->remotes[i].remote, req->remotes[i].packet); + +- /* Age out servers that haven't been used in a while. */ +- if (time(&currtime) != (time_t)-1) +- age(&req->rc->servers, currtime); +- + request_free(req); + } + +@@ -247,10 +220,23 @@ krad_client_new(krb5_context kctx, verto_ctx *vctx, krad_client **out) + void + krad_client_free(krad_client *rc) + { ++ server *srv; ++ + if (rc == NULL) + return; + +- age(&rc->servers, -1); ++ /* Cancel all requests before freeing any remotes, since each request's ++ * callback data may contain references to multiple remotes. */ ++ K5_LIST_FOREACH(srv, &rc->servers, list) ++ kr_remote_cancel_all(srv->serv); ++ ++ while (!K5_LIST_EMPTY(&rc->servers)) { ++ srv = K5_LIST_FIRST(&rc->servers); ++ K5_LIST_REMOVE(srv, list); ++ kr_remote_free(srv->serv); ++ free(srv); ++ } ++ + free(rc); + } + +diff --git a/src/lib/krad/internal.h b/src/lib/krad/internal.h +index 312dc8258..b086598fb 100644 +--- a/src/lib/krad/internal.h ++++ b/src/lib/krad/internal.h +@@ -120,6 +120,10 @@ kr_remote_send(krad_remote *rr, krad_code code, krad_attrset *attrs, + void + kr_remote_cancel(krad_remote *rr, const krad_packet *pkt); + ++/* Cancel all requests awaiting responses. */ ++void ++kr_remote_cancel_all(krad_remote *rr); ++ + /* Determine if this remote object refers to the remote resource identified + * by the addrinfo struct and the secret. */ + krb5_boolean +diff --git a/src/lib/krad/remote.c b/src/lib/krad/remote.c +index 0f90443ce..b5dd8cd19 100644 +--- a/src/lib/krad/remote.c ++++ b/src/lib/krad/remote.c +@@ -421,15 +421,20 @@ error: + return retval; + } + ++void ++kr_remote_cancel_all(krad_remote *rr) ++{ ++ while (!K5_TAILQ_EMPTY(&rr->list)) ++ request_finish(K5_TAILQ_FIRST(&rr->list), ECANCELED, NULL); ++} ++ + void + kr_remote_free(krad_remote *rr) + { + if (rr == NULL) + return; + +- while (!K5_TAILQ_EMPTY(&rr->list)) +- request_finish(K5_TAILQ_FIRST(&rr->list), ECANCELED, NULL); +- ++ kr_remote_cancel_all(rr); + free(rr->secret); + if (rr->info != NULL) + free(rr->info->ai_addr); +-- +2.35.3 + diff --git a/root/ppg/common/deps/krb5/rpm/krb5-krb5kdc.conf b/root/ppg/common/deps/krb5/rpm/krb5-krb5kdc.conf new file mode 100644 index 00000000..5160b284 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/krb5-krb5kdc.conf @@ -0,0 +1 @@ +d /run/krb5kdc 0755 root root diff --git a/root/ppg/common/deps/krb5/rpm/krb5.conf b/root/ppg/common/deps/krb5/rpm/krb5.conf new file mode 100644 index 00000000..c45f3882 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/krb5.conf @@ -0,0 +1,28 @@ +# To opt out of the system crypto-policies configuration of krb5, remove the +# symlink at /etc/krb5.conf.d/crypto-policies which will not be recreated. +includedir /etc/krb5.conf.d/ + +[logging] + default = FILE:/var/log/krb5libs.log + kdc = FILE:/var/log/krb5kdc.log + admin_server = FILE:/var/log/kadmind.log + +[libdefaults] + dns_lookup_realm = false + ticket_lifetime = 24h + renew_lifetime = 7d + forwardable = true + rdns = false + pkinit_anchors = FILE:/etc/pki/tls/certs/ca-bundle.crt + spake_preauth_groups = edwards25519 +# default_realm = EXAMPLE.COM + +[realms] +# EXAMPLE.COM = { +# kdc = kerberos.example.com +# admin_server = kerberos.example.com +# } + +[domain_realm] +# .example.com = EXAMPLE.COM +# example.com = EXAMPLE.COM diff --git a/root/ppg/common/deps/krb5/rpm/krb5.spec b/root/ppg/common/deps/krb5/rpm/krb5.spec new file mode 100644 index 00000000..aa66af51 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/krb5.spec @@ -0,0 +1,3959 @@ +# PERCONA REBUILD of the Rocky Linux 8 krb5 source package, for +# ppg:common:deps (RockyLinux_8 repository only). +# +# Why: the EL8-built Percona PostgreSQL binary tarball (ssl1.1 variant) +# bundles krb5-libs. Red Hat builds krb5 with --with-crypto-impl=openssl +# against Red Hat's OpenSSL 1.1.1 fork, so libk5crypto.so.3 needs symbol +# version nodes (EVP_KDF_ctrl@OPENSSL_1_1_1b) that exist ONLY in +# RHEL-family libcrypto.so.1.1 — the bundled library fails to load on +# stock OpenSSL 1.1 hosts (proven on Debian 11). The official Percona +# tarball's krb5 has no libcrypto dependency at all. +# +# Delta vs. the distro spec (kept minimal, marked "PERCONA"): +# - --with-crypto-impl=builtin (was openssl): krb5's builtin crypto, +# no libcrypto linkage in any krb5-libs shared object. +# - --with-tls-impl=no (was openssl): k5tls.so (shipped in krb5-libs) +# becomes the upstream "notls" stub instead of linking OpenSSL; +# KKDCP/HTTPS KDC transport degrades gracefully. +# - --without-spake-openssl: spake.so (shipped in krb5-libs) supports +# only the native edwards25519 group (the default) instead of also +# offering the OpenSSL-backed NIST P-256/384/521 groups. +# - Patch1000 detaches the RH downstream FIPS/KDF hooks from OpenSSL +# in code shared by all crypto backends (see the patch header). +# - krb5-libs no longer Requires openssl-libs. +# - Release carries a .percona suffix so this EVR wins over the +# distro package inside the OBS build chroots. +# - PDF manuals are not regenerated: the prebuilt Source3 tar is +# packaged as-is and the TeX Live doc-build BuildRequires are +# dropped (unavailable in the ppg:common:deps repo chain). +# PKINIT is still built against OpenSSL: pkinit.so lives in the separate +# krb5-pkinit subpackage, which is never bundled into the tarball, and +# keeping it preserves the distro's binary package set. + +%global WITH_DIRSRV 1 + +# Set this so that find-lang.sh will recognize the .po files. +%global gettext_domain mit-krb5 +# Guess where the -libs subpackage's docs are going to go. +%define libsdocdir %{?_pkgdocdir:%(echo %{_pkgdocdir} | sed -e s,krb5,krb5-libs,g)}%{!?_pkgdocdir:%{_docdir}/%{name}-libs-%{version}} +# Figure out where the default ccache lives and how we set it. +%global configure_default_ccache_name 1 +%global configured_default_ccache_name KEYRING:persistent:%%{uid} + +# leave empty or set to e.g., -beta2 +%global prerelease %{nil} + +# Should be in form 5.0, 6.1, etc. +%global kdbversion 8.0 + +Summary: The Kerberos network authentication system +Name: krb5 +Version: 1.18.2 +# for prerelease, should be e.g., 0.% {prerelease}.1% { ?dist } (without spaces) +# PERCONA: ".percona.N" appended to the distro Release (34) so that this +# rebuild's EVR beats 1.18.2-34.el8_10 during dependency resolution while +# still yielding to a future distro 1.18.2-35 security rebase. +Release: 34.percona.1%{?dist} + +# lookaside-cached sources; two downloads and a build artifact +Source0: https://web.mit.edu/kerberos/dist/krb5/1.18/krb5-%{version}%{prerelease}.tar.gz +# rharwood has trust path to signing key and verifies on check-in +Source1: https://web.mit.edu/kerberos/dist/krb5/1.18/krb5-%{version}%{prerelease}.tar.gz.asc +# This source is generated during the build because it is documentation. +# To override this behavior (e.g., new upstream version), do: +# tar cfT krb5-1.15.2-pdfs.tar /dev/null +# or the like. This logic persists due to how slow the stranger Fedora +# architecture builders are. 5 minutes on my laptop, 45 on koji easy. +Source3: krb5-%{version}%{prerelease}-pdfs.tar + +# Numbering is a relic of old init systems etc. It's easiest to just leave. +Source2: kprop.service +Source4: kadmin.service +Source5: krb5kdc.service +Source6: krb5.conf +Source10: kdc.conf +Source11: kadm5.acl +Source19: krb5kdc.sysconfig +Source20: kadmin.sysconfig +Source21: kprop.sysconfig +Source29: ksu.pamd +Source33: krb5kdc.logrotate +Source34: kadmind.logrotate +Source39: krb5-krb5kdc.conf + +Patch1: downstream-ksu-pam-integration.patch +Patch2: downstream-SELinux-integration.patch +Patch3: downstream-Adjust-build-configuration.patch +Patch4: downstream-netlib-and-dns.patch +Patch5: downstream-fix-debuginfo-with-y.tab.c.patch +Patch6: downstream-Remove-3des-support.patch +Patch7: rhel-Use-backported-version-of-OpenSSL-3-KDF-interfa.patch +Patch8: downstream-FIPS-with-PRNG-and-RADIUS-and-MD4-5.patch +Patch110: Allow-certauth-modules-to-set-hw-authent-flag.patch +Patch112: Refresh-manually-acquired-creds-from-client-keytab.patch +Patch114: Add-finalization-safety-check-to-com_err.patch +Patch115: Eliminate-redundant-PKINIT-responder-invocation.patch +Patch116: Correctly-import-service-GSS-host-based-name.patch +Patch117: Do-expiration-warnings-for-all-init_creds-APIs.patch +Patch118: Pass-gss_localname-through-SPNEGO.patch +Patch119: Omit-KDC-indicator-check-for-S4U2Self-requests.patch +Patch120: Fix-typo-in-in-in-the-ksu-man-page.patch +Patch121: Omit-PA_FOR_USER-if-we-can-t-compute-its-checksum.patch +Patch122: Improve-negoex_parse_token-code-hygiene.patch +Patch123: Refactor-krb5-GSS-checksum-handling.patch +Patch124: Implement-GSS_C_CHANNEL_BOUND_FLAG.patch +Patch125: Implement-KERB_AP_OPTIONS_CBT-server-side.patch +Patch126: Add-client_aware_channel_bindings-option.patch +Patch127: Pass-channel-bindings-through-SPNEGO.patch +Patch128: Add-channel-bindings-tests.patch +Patch129: Add-three-kvno-options-from-Heimdal-kgetcred.patch +Patch130: Ignore-bad-enctypes-in-krb5_string_to_keysalts.patch +Patch131: Fix-leak-in-KERB_AP_OPTIONS_CBT-server-support.patch +Patch132: Unify-kvno-option-documentation.patch +Patch133: Document-k-option-in-kvno-1-synopsis.patch +Patch134: Add-recursion-limit-for-ASN.1-indefinite-lengths.patch +Patch135: Add-support-for-start_realm-cache-config.patch +Patch136: Add-APIs-for-marshalling-credentials.patch +Patch137: Add-KCM_OP_GET_CRED_LIST-for-faster-iteration.patch +Patch138: Fix-KCM-flag-transmission-for-remove_cred.patch +Patch139: Make-KCM-iteration-fallback-work-with-sssd-kcm.patch +Patch140: Use-KCM_OP_RETRIEVE-in-KCM-client.patch +Patch141: Fix-KCM-retrieval-support-for-sssd.patch +Patch142: Fix-KDC-null-deref-on-bad-encrypted-challenge.patch +Patch143: Fix-KDC-null-deref-on-TGS-inner-body-null-server.patch +Patch144: Use-SHA256-instead-of-SHA1-for-PKINIT-CMS-digest.patch +Patch145: downstream-Use-newly-enforced-dejagnu-path-naming-convention.patch +Patch146: Make-kprop-work-for-dump-files-larger-than-4GB.patch +Patch147: Try-harder-to-avoid-password-change-replay-errors.patch +Patch148: downstream-Fix-dejagnu-unit-tests-directory-name-for-RPC-lib.patch +Patch149: krb5-krad-larger-attrs.patch +Patch150: krb5-krad-remote.patch +Patch151: Fix-integer-overflows-in-PAC-parsing.patch +Patch152: Use-14-instead-of-9-for-unkeyed-SHA-1-checksum.patch +Patch153: Add-PAC-ticket-signature-APIs.patch +Patch154: Factor-out-PAC-checksum-verification.patch +Patch155: Add-PAC-full-checksums.patch +Patch156: downstream-Support-PAC-full-checksum-w-o-ticket-chec.patch +Patch157: downstream-Allow-to-make-AD-SIGNEDPATH-optional.patch +Patch158: End-connection-on-KDC_ERR_SVC_UNAVAILABLE.patch +Patch159: Add-request_timeout-configuration-parameter.patch +Patch160: Wait-indefinitely-on-KDC-TCP-connections.patch +Patch161: Fix-two-unlikely-memory-leaks.patch +Patch162: Fix-defcred-leak-in-krb5-gss_inquire_cred.patch +Patch163: Add-a-simple-DER-support-header.patch +Patch164: Fix-vulnerabilities-in-GSS-message-token-handling.patch +Patch165: Remove-PKINIT-RSA-support.patch +Patch166: Generate-and-verify-message-MACs-in-libkrad.patch +Patch167: Set-missing-mask-flags-for-kdb5_util-operations.patch +Patch168: Prevent-overflow-when-calculating-ulog-block-size.patch +Patch169: In-KDC-assume-all-services-support-aes256-sha1.patch +Patch170: Don-t-issue-session-keys-with-deprecated-enctypes.patch +Patch171: downstream-Remove-3des-support-cumulative-1.patch +Patch172: Add-PKINIT-paChecksum2-from-MS-PKCA-v20230920.patch +Patch173: downstream-Do-not-block-HMAC-MD4-5-in-FIPS-mode.patch +Patch174: Improve-ulog-block-resize-efficiency.patch +Patch175: Fix-uninitialized-pointer-dereference-in-libkrad.patch +Patch176: Fix-two-NegoEx-parsing-vulnerabilities.patch +# PERCONA: with --with-crypto-impl=builtin the RH downstream FIPS/KDF +# patches would still drag OpenSSL into shared code (configure hard-fails +# without the RH-only EVP_KDF_* backports; prng.c, libkrad and spake.so +# would link libcrypto). This patch confines those hooks to openssl +# builds. Numbered 1000 to stay clear of future distro patch numbers. +Patch1000: percona-builtin-crypto-portability.patch + +License: MIT +URL: http://web.mit.edu/kerberos/www/ +Group: System Environment/Libraries + +BuildRequires: autoconf, bison, cmake, flex, gawk, gettext, pkgconfig, sed +BuildRequires: gcc +BuildRequires: libcom_err-devel, libedit-devel, libss-devel +BuildRequires: gzip, ncurses-devel +# PERCONA: texlive-pdftex and latexmk dropped — the PDF manuals are not +# rebuilt; the prebuilt Source3 tar is used as-is (the ppg:common:deps +# RockyLinux_8 repository chain carries no TeX Live). python3-sphinx is +# still needed for the man pages and HTML docs. +BuildRequires: python3-sphinx +BuildRequires: libverto-devel +BuildRequires: openldap-devel +BuildRequires: python3 +BuildRequires: keyutils, keyutils-libs-devel >= 1.5.8 +BuildRequires: libselinux-devel +BuildRequires: pam-devel +BuildRequires: tcl-devel +# PERCONA: openssl-devel is still needed for the PKINIT plugin (separate +# krb5-pkinit subpackage, never bundled into the tarball). The libraries +# in krb5-libs are built with the builtin crypto impl and do not link it. +BuildRequires: openssl-devel >= 1:1.1.1c-4 + +# For autosetup +BuildRequires: git + +# PERCONA: the whole TeX toolchain (tex(*.sty) requires, texlive, +# texlive-latex, texlive-texmf-fonts, /usr/bin/pdflatex, +# /usr/bin/makeindex) is dropped — the PDF manuals ship prebuilt in +# Source3 and are never regenerated (see %%build). +BuildRequires: systemd-units + +%ifarch %{ix86} x86_64 +BuildRequires: yasm +%endif + +%description +Kerberos V5 is a trusted-third-party network authentication system, +which can improve your network's security by eliminating the insecure +practice of sending passwords over the network in unencrypted form. + +%package devel +Summary: Development files needed to compile Kerberos 5 programs +Group: Development/Libraries +Requires: %{name}-libs%{?_isa} = %{version}-%{release} +Requires: libkadm5%{?_isa} = %{version}-%{release} +Requires: libcom_err-devel +Requires: keyutils-libs-devel, libselinux-devel +Requires: libverto-devel +Provides: krb5-kdb-devel-version = %{kdbversion} +# IPA wants ^ to be a separate symbol because they don't trust package +# managers to match -server and -devel in version. Just go with it. + +%description devel +Kerberos is a network authentication system. The krb5-devel package +contains the header files and libraries needed for compiling Kerberos +5 programs. If you want to develop Kerberos-aware programs, you need +to install this package. + +%package libs +Summary: The non-admin shared libraries used by Kerberos 5 +Group: System Environment/Libraries +Requires: coreutils, gawk, grep, sed +Requires: keyutils-libs >= 1.5.8 +# PERCONA: openssl-libs Requires dropped — with the builtin crypto impl +# no krb5-libs shared object links libcrypto/libssl. +Requires: /etc/crypto-policies/back-ends/krb5.config + +%description libs +Kerberos is a network authentication system. The krb5-libs package +contains the shared libraries needed by Kerberos 5. If you are using +Kerberos, you need to install this package. + +%package server +Group: System Environment/Daemons +Summary: The KDC and related programs for Kerberos 5 +Requires: %{name}-libs%{?_isa} = %{version}-%{release} +Requires(post): systemd-units +Requires(preun): systemd-units +Requires(postun): systemd-units +# we drop files in its directory, but we don't want to own that directory +Requires: logrotate +# we specify /usr/share/dict/words as the default dict_file in kdc.conf +Requires: /usr/share/dict/words +# for run-time, and for parts of the test suite +BuildRequires: libverto-module-base +Requires: libverto-module-base +%ifarch x86_64 +Obsoletes: %{name}-server-%{version}-%{release}.i686 +%endif +%ifarch ppc64 +Obsoletes: %{name}-server-%{version}-%{release}.ppc +%endif +%ifarch s390x +Obsoletes: %{name}-server-%{version}-%{release}.s390 +%endif +Requires: libkadm5%{?_isa} = %{version}-%{release} +Provides: krb5-kdb-version = %{kdbversion} + +%description server +Kerberos is a network authentication system. The krb5-server package +contains the programs that must be installed on a Kerberos 5 key +distribution center (KDC). If you are installing a Kerberos 5 KDC, +you need to install this package (in other words, most people should +NOT install this package). + +%package server-ldap +Group: System Environment/Daemons +Summary: The LDAP storage plugin for the Kerberos 5 KDC +Requires: %{name}-server%{?_isa} = %{version}-%{release} +Requires: %{name}-libs%{?_isa} = %{version}-%{release} +Requires: libkadm5%{?_isa} = %{version}-%{release} +%ifarch x86_64 +Obsoletes: %{name}-server-ldap-%{version}-%{release}.i686 +%endif +%ifarch ppc64 +Obsoletes: %{name}-server-ldap-%{version}-%{release}.ppc +%endif +%ifarch s390x +Obsoletes: %{name}-server-ldap-%{version}-%{release}.s390 +%endif + +%description server-ldap +Kerberos is a network authentication system. The krb5-server package +contains the programs that must be installed on a Kerberos 5 key +distribution center (KDC). If you are installing a Kerberos 5 KDC, +and you wish to use a directory server to store the data for your +realm, you need to install this package. + +%package workstation +Summary: Kerberos 5 programs for use on workstations +Group: System Environment/Base +Requires: %{name}-libs%{?_isa} = %{version}-%{release} +Requires: libkadm5%{?_isa} = %{version}-%{release} + +%description workstation +Kerberos is a network authentication system. The krb5-workstation +package contains the basic Kerberos programs (kinit, klist, kdestroy, +kpasswd). If your network uses Kerberos, this package should be +installed on every workstation. + +%package pkinit +Summary: The PKINIT module for Kerberos 5 +Group: System Environment/Libraries +Requires: %{name}-libs%{?_isa} = %{version}-%{release} +Obsoletes: krb5-pkinit-openssl < %{version}-%{release} +Provides: krb5-pkinit-openssl = %{version}-%{release} + +%description pkinit +Kerberos is a network authentication system. The krb5-pkinit +package contains the PKINIT plugin, which allows clients +to obtain initial credentials from a KDC using a private key and a +certificate. + +%package -n libkadm5 +Summary: Kerberos 5 Administrative libraries +Group: System Environment/Base +Requires: %{name}-libs%{?_isa} = %{version}-%{release} + +%description -n libkadm5 +Kerberos is a network authentication system. The libkadm5 package +contains only the libkadm5clnt and libkadm5serv shared objects. This +interface is not considered stable. + +%prep +%autosetup -S git -n %{name}-%{version}%{prerelease} -a 3 +ln NOTICE LICENSE + +# Generate an FDS-compatible LDIF file. +inldif=src/plugins/kdb/ldap/libkdb_ldap/kerberos.ldif +cat > '60kerberos.ldif' << EOF +# This is a variation on kerberos.ldif which 389 Directory Server will like. +dn: cn=schema +EOF +egrep -iv '(^$|^dn:|^changetype:|^add:)' $inldif | \ +sed -r 's,^ , ,g' | \ +sed -r 's,^ , ,g' >> 60kerberos.ldif +touch -r $inldif 60kerberos.ldif + +# Rebuild the configure scripts. +pushd src +autoreconf -fiv +popd + +# Mess with some of the default ports that we use for testing, so that multiple +# builds going on the same host don't step on each other. +cfg="src/kadmin/testing/proto/kdc.conf.proto \ + src/kadmin/testing/proto/krb5.conf.proto \ + src/lib/kadm5/testsuite/api.current/init-v2.exp \ + src/util/k5test.py" +LONG_BIT=`getconf LONG_BIT` +PORT=`expr 61000 + $LONG_BIT - 48` +sed -i -e s,61000,`expr "$PORT" + 0`,g $cfg +PORT=`expr 1750 + $LONG_BIT - 48` +sed -i -e s,1750,`expr "$PORT" + 0`,g $cfg +sed -i -e s,1751,`expr "$PORT" + 1`,g $cfg +sed -i -e s,1752,`expr "$PORT" + 2`,g $cfg +PORT=`expr 8888 + $LONG_BIT - 48` +sed -i -e s,8888,`expr "$PORT" - 0`,g $cfg +sed -i -e s,8887,`expr "$PORT" - 1`,g $cfg +sed -i -e s,8886,`expr "$PORT" - 2`,g $cfg +PORT=`expr 7777 + $LONG_BIT - 48` +sed -i -e s,7777,`expr "$PORT" + 0`,g $cfg +sed -i -e s,7778,`expr "$PORT" + 1`,g $cfg + +%build +# Go ahead and supply tcl info, because configure doesn't know how to find it. +source %{_libdir}/tclConfig.sh +pushd src + +# Set this so that configure will have a value even if the current version of +# autoconf doesn't set one. +export runstatedir=%{_localstatedir}/run +# Work out the CFLAGS and CPPFLAGS which we intend to use. +INCLUDES=-I%{_includedir}/et +CFLAGS="`echo $RPM_OPT_FLAGS $DEFINES $INCLUDES -fPIC -fno-strict-aliasing -fstack-protector-all`" +CPPFLAGS="`echo $DEFINES $INCLUDES`" +%configure \ + CC="%{__cc}" \ + CFLAGS="$CFLAGS" \ + CPPFLAGS="$CPPFLAGS" \ + SS_LIB="-lss" \ + --enable-shared \ + --localstatedir=%{_var}/kerberos \ + --disable-rpath \ + --without-krb5-config \ + --with-system-et \ + --with-system-ss \ + --with-netlib=-lresolv \ + --with-tcl \ + --enable-dns-for-realm \ + --with-ldap \ +%if %{WITH_DIRSRV} + --with-dirsrv-account-locking \ +%endif + --enable-pkinit \ + --with-crypto-impl=builtin \ + --with-pkinit-crypto-impl=openssl \ + --with-tls-impl=no \ + --without-spake-openssl \ + --with-system-verto \ + --with-pam \ + --with-selinux \ + --with-prng-alg=os \ + || (cat config.log; exit 1) +# Now build it. +make +popd + +# Sanity check the KDC_RUN_DIR. +configured_kdcrundir=`grep KDC_RUN_DIR src/include/osconf.h | awk '{print $NF}'` +configured_kdcrundir=`eval echo $configured_kdcrundir` +if test "$configured_kdcrundir" != %{_localstatedir}/run/krb5kdc ; then + exit 1 +fi + +# Build the docs. +make -C src/doc paths.py version.py +cp src/doc/paths.py doc/ +mkdir -p build-man build-html build-pdf +sphinx-build -a -b man -t pathsubs doc build-man +sphinx-build -a -b html -t pathsubs doc build-html +rm -fr build-html/_sources +# PERCONA: no PDF regeneration — build-pdf/ was populated at %%prep time +# from the prebuilt Source3 tar (%%autosetup -a 3), and the build +# environment carries no TeX Live. Just assert the expected PDFs exist. +for pdf in admin appdev basic build plugindev user ; do + test -s build-pdf/$pdf.pdf || exit 1 +done + +%install +[ "$RPM_BUILD_ROOT" != '/' ] && rm -rf -- "$RPM_BUILD_ROOT" + +# Sample KDC config files (bundled kdc.conf and kadm5.acl). +mkdir -p $RPM_BUILD_ROOT%{_var}/kerberos/krb5kdc +install -pm 600 %{SOURCE10} $RPM_BUILD_ROOT%{_var}/kerberos/krb5kdc/ +install -pm 600 %{SOURCE11} $RPM_BUILD_ROOT%{_var}/kerberos/krb5kdc/ + +# Where per-user keytabs live by default. +mkdir -p $RPM_BUILD_ROOT%{_var}/kerberos/krb5/user + +# Default configuration file for everything. +mkdir -p $RPM_BUILD_ROOT/etc +install -pm 644 %{SOURCE6} $RPM_BUILD_ROOT/etc/krb5.conf + +# Default include on this directory +mkdir -p $RPM_BUILD_ROOT/etc/krb5.conf.d +ln -sv /etc/crypto-policies/back-ends/krb5.config $RPM_BUILD_ROOT/etc/krb5.conf.d/crypto-policies + +# Parent of configuration file for list of loadable GSS mechs ("mechs"). This +# location is not relative to sysconfdir, but is hard-coded in g_initialize.c. +mkdir -m 755 -p $RPM_BUILD_ROOT/etc/gss +# Parent of groups of configuration files for a list of loadable GSS mechs +# ("mechs"). This location is not relative to sysconfdir, and is also +# hard-coded in g_initialize.c. +mkdir -m 755 -p $RPM_BUILD_ROOT/etc/gss/mech.d + +# If the default configuration needs to start specifying a default cache +# location, add it now, then fixup the timestamp so that it looks the same. +%if 0%{?configure_default_ccache_name} +export DEFCCNAME="%{configured_default_ccache_name}" +awk '{print} + /^# default_realm/{print " default_ccache_name =", ENVIRON["DEFCCNAME"]}' \ + %{SOURCE6} > $RPM_BUILD_ROOT/etc/krb5.conf +touch -r %{SOURCE6} $RPM_BUILD_ROOT/etc/krb5.conf +grep default_ccache_name $RPM_BUILD_ROOT/etc/krb5.conf +%endif + +# Server init scripts (krb5kdc,kadmind,kpropd) and their sysconfig files. +mkdir -p $RPM_BUILD_ROOT%{_unitdir} +for unit in \ + %{SOURCE5}\ + %{SOURCE4} \ + %{SOURCE2} ; do + # In the past, the init script was supposed to be named after the + # service that the started daemon provided. Changing their names + # is an upgrade-time problem I'm in no hurry to deal with. + install -pm 644 ${unit} $RPM_BUILD_ROOT%{_unitdir} +done +mkdir -p $RPM_BUILD_ROOT/%{_tmpfilesdir} +install -pm 644 %{SOURCE39} $RPM_BUILD_ROOT/%{_tmpfilesdir}/ +mkdir -p $RPM_BUILD_ROOT/%{_localstatedir}/run/krb5kdc + +mkdir -p $RPM_BUILD_ROOT/etc/sysconfig +for sysconfig in \ + %{SOURCE19}\ + %{SOURCE20}\ + %{SOURCE21} ; do + install -pm 644 ${sysconfig} \ + $RPM_BUILD_ROOT/etc/sysconfig/`basename ${sysconfig} .sysconfig` +done + +# logrotate configuration files +mkdir -p $RPM_BUILD_ROOT/etc/logrotate.d/ +for logrotate in \ + %{SOURCE33} \ + %{SOURCE34} ; do + install -pm 644 ${logrotate} \ + $RPM_BUILD_ROOT/etc/logrotate.d/`basename ${logrotate} .logrotate` +done + +# PAM configuration files. +mkdir -p $RPM_BUILD_ROOT/etc/pam.d/ +for pam in \ + %{SOURCE29} ; do + install -pm 644 ${pam} \ + $RPM_BUILD_ROOT/etc/pam.d/`basename ${pam} .pamd` +done + +# Plug-in directories. +install -pdm 755 $RPM_BUILD_ROOT/%{_libdir}/krb5/plugins/preauth +install -pdm 755 $RPM_BUILD_ROOT/%{_libdir}/krb5/plugins/kdb +install -pdm 755 $RPM_BUILD_ROOT/%{_libdir}/krb5/plugins/authdata + +# The rest of the binaries, headers, libraries, and docs. +make -C src DESTDIR=$RPM_BUILD_ROOT EXAMPLEDIR=%{libsdocdir}/examples install + +# Munge krb5-config yet again. This is totally wrong for 64-bit, but chunks +# of the buildconf patch already conspire to strip out /usr/ from the +# list of link flags, and it helps prevent file conflicts on multilib systems. +sed -r -i -e 's|^libdir=/usr/lib(64)?$|libdir=/usr/lib|g' $RPM_BUILD_ROOT%{_bindir}/krb5-config + +# Temporay workaround for krb5-config reading too much from LDFLAGS. +# Upstream: http://krbdev.mit.edu/rt/Ticket/Display.html?id=8159 +sed -r -i -e "s/-specs=\/.+?\/redhat-hardened-ld//g" $RPM_BUILD_ROOT%{_bindir}/krb5-config + +if [[ "$(< $RPM_BUILD_ROOT%{_bindir}/krb5-config )" == *redhat-hardened-ld* ]] ; then + printf '# redhat-hardened-ld for krb5-config failed' 1>&2 + exit 1 +fi + +# Install processed man pages. +for section in 1 5 8 ; do + install -m 644 build-man/*.${section} \ + $RPM_BUILD_ROOT/%{_mandir}/man${section}/ +done + +# This script just tells you to send bug reports to krb5-bugs@mit.edu, but +# since we don't have a man page for it, just drop it. +rm -- "$RPM_BUILD_ROOT/%{_sbindir}/krb5-send-pr" + +# These files are already packaged elsewhere +rm -- "$RPM_BUILD_ROOT/%{_docdir}/krb5-libs/examples/kdc.conf" +rm -- "$RPM_BUILD_ROOT/%{_docdir}/krb5-libs/examples/krb5.conf" +rm -- "$RPM_BUILD_ROOT/%{_docdir}/krb5-libs/examples/services.append" + +# This is only needed for tests +rm -- "$RPM_BUILD_ROOT/%{_libdir}/krb5/plugins/preauth/test.so" + +%find_lang %{gettext_domain} + +%ldconfig_scriptlets libs + +%triggerun libs -- krb5-libs < 1.15.1-5 +if ! grep -q 'includedir /etc/krb5.conf.d' /etc/krb5.conf ; then + sed -i '1i # To opt out of the system crypto-policies configuration of krb5, remove the\n# symlink at /etc/krb5.conf.d/crypto-policies which will not be recreated.\nincludedir /etc/krb5.conf.d/\n' /etc/krb5.conf +fi +exit 0 + +%ldconfig_scriptlets server-ldap + +%post server +%systemd_post krb5kdc.service kadmin.service kprop.service +# assert sanity. A cleaner solution probably exists but it is opaque +/bin/systemctl daemon-reload +exit 0 + +%preun server +%systemd_preun krb5kdc.service kadmin.service kprop.service +exit 0 + +%postun server +%systemd_postun_with_restart krb5kdc.service kadmin.service kprop.service +exit 0 + +%ldconfig_scriptlets -n libkadm5 + +%files workstation +%doc src/config-files/services.append +%doc src/config-files/krb5.conf +%doc build-html/* +%doc build-pdf/user.pdf build-pdf/basic.pdf +%attr(0755,root,root) %doc src/config-files/convert-config-files + +# Clients of the KDC, including tools you're likely to need if you're running +# app servers other than those built from this source package. +%{_bindir}/kdestroy +%{_mandir}/man1/kdestroy.1* +%{_bindir}/kinit +%{_mandir}/man1/kinit.1* +%{_bindir}/klist +%{_mandir}/man1/klist.1* +%{_bindir}/kpasswd +%{_mandir}/man1/kpasswd.1* +%{_bindir}/kswitch +%{_mandir}/man1/kswitch.1* + +%{_bindir}/kvno +%{_mandir}/man1/kvno.1* +%{_bindir}/kadmin +%{_mandir}/man1/kadmin.1* +%{_bindir}/k5srvutil +%{_mandir}/man1/k5srvutil.1* +%{_bindir}/ktutil +%{_mandir}/man1/ktutil.1* + +# Doesn't really fit anywhere else. +%attr(4755,root,root) %{_bindir}/ksu +%{_mandir}/man1/ksu.1* +%config(noreplace) /etc/pam.d/ksu + +%files server +%docdir %{_mandir} +%doc build-pdf/admin.pdf build-pdf/build.pdf +%doc src/config-files/kdc.conf +%{_unitdir}/krb5kdc.service +%{_unitdir}/kadmin.service +%{_unitdir}/kprop.service +%{_tmpfilesdir}/krb5-krb5kdc.conf +%dir %{_localstatedir}/run/krb5kdc +%config(noreplace) /etc/sysconfig/krb5kdc +%config(noreplace) /etc/sysconfig/kadmin +%config(noreplace) /etc/sysconfig/kprop +%config(noreplace) /etc/logrotate.d/krb5kdc +%config(noreplace) /etc/logrotate.d/kadmind + +%dir %{_var}/kerberos +%dir %{_var}/kerberos/krb5kdc +%config(noreplace) %{_var}/kerberos/krb5kdc/kdc.conf +%config(noreplace) %{_var}/kerberos/krb5kdc/kadm5.acl + +%dir %{_libdir}/krb5 +%dir %{_libdir}/krb5/plugins +%dir %{_libdir}/krb5/plugins/kdb +%dir %{_libdir}/krb5/plugins/preauth +%dir %{_libdir}/krb5/plugins/authdata +%{_libdir}/krb5/plugins/preauth/otp.so +%{_libdir}/krb5/plugins/kdb/db2.so + +# KDC binaries and configuration. +%{_mandir}/man5/kadm5.acl.5* +%{_mandir}/man5/kdc.conf.5* +%{_sbindir}/kadmin.local +%{_mandir}/man8/kadmin.local.8* +%{_sbindir}/kadmind +%{_mandir}/man8/kadmind.8* +%{_sbindir}/kdb5_util +%{_mandir}/man8/kdb5_util.8* +%{_sbindir}/kprop +%{_mandir}/man8/kprop.8* +%{_sbindir}/kpropd +%{_mandir}/man8/kpropd.8* +%{_sbindir}/kproplog +%{_mandir}/man8/kproplog.8* +%{_sbindir}/krb5kdc +%{_mandir}/man8/krb5kdc.8* + +# This is here for people who want to test their server. It was formerly also +# included in -devel. +%{_bindir}/sclient +%{_mandir}/man1/sclient.1* +%{_sbindir}/sserver +%{_mandir}/man8/sserver.8* + +%files server-ldap +%docdir %{_mandir} +%doc src/plugins/kdb/ldap/libkdb_ldap/kerberos.ldif +%doc src/plugins/kdb/ldap/libkdb_ldap/kerberos.schema +%doc 60kerberos.ldif +%dir %{_libdir}/krb5 +%dir %{_libdir}/krb5/plugins +%dir %{_libdir}/krb5/plugins/kdb +%{_libdir}/krb5/plugins/kdb/kldap.so +%{_libdir}/libkdb_ldap.so +%{_libdir}/libkdb_ldap.so.* +%{_mandir}/man8/kdb5_ldap_util.8.gz +%{_sbindir}/kdb5_ldap_util + +%files libs -f %{gettext_domain}.lang +%doc README NOTICE +%{!?_licensedir:%global license %%doc} +%license LICENSE +%docdir %{_mandir} +# These are hard-coded, not-dependent-on-the-configure-script paths. +%dir /etc/gss +%dir /etc/gss/mech.d +%dir /etc/krb5.conf.d +%config(noreplace) /etc/krb5.conf +%config(noreplace) /etc/krb5.conf.d/crypto-policies +/%{_mandir}/man5/.k5identity.5* +/%{_mandir}/man5/.k5login.5* +/%{_mandir}/man5/k5identity.5* +/%{_mandir}/man5/k5login.5* +/%{_mandir}/man5/krb5.conf.5* +/%{_mandir}/man7/kerberos.7* +%{_libdir}/libgssapi_krb5.so.* +%{_libdir}/libgssrpc.so.* +%{_libdir}/libk5crypto.so.* +%{_libdir}/libkdb5.so.* +%{_libdir}/libkrad.so.* +%{_libdir}/libkrb5.so.* +%{_libdir}/libkrb5support.so.* +%dir %{_libdir}/krb5 +%dir %{_libdir}/krb5/plugins +%dir %{_libdir}/krb5/plugins/* +# PERCONA: with --with-tls-impl=no this is the upstream "notls" stub +# (no OpenSSL linkage); KKDCP/HTTPS KDC transport reports TLS as +# unsupported instead of dlopen-failing. +%{_libdir}/krb5/plugins/tls/k5tls.so +%{_libdir}/krb5/plugins/preauth/spake.so +%dir %{_var}/kerberos +%dir %{_var}/kerberos/krb5 +%dir %{_var}/kerberos/krb5/user + +%files pkinit +%dir %{_libdir}/krb5 +%dir %{_libdir}/krb5/plugins +%dir %{_libdir}/krb5/plugins/preauth +%{_libdir}/krb5/plugins/preauth/pkinit.so + +%files devel +%docdir %{_mandir} +%doc build-pdf/appdev.pdf build-pdf/plugindev.pdf + +%{_includedir}/* +%{_libdir}/libgssapi_krb5.so +%{_libdir}/libgssrpc.so +%{_libdir}/libk5crypto.so +%{_libdir}/libkdb5.so +%{_libdir}/libkrad.so +%{_libdir}/libkrb5.so +%{_libdir}/libkrb5support.so +%{_libdir}/pkgconfig/* + +%{_bindir}/krb5-config +%{_mandir}/man1/krb5-config.1* + +# Protocol test clients. +%{_bindir}/sim_client +%{_bindir}/gss-client +%{_bindir}/uuclient + +# Protocol test servers. +%{_sbindir}/sim_server +%{_sbindir}/gss-server +%{_sbindir}/uuserver + +%files -n libkadm5 +%{_libdir}/libkadm5clnt.so +%{_libdir}/libkadm5clnt_mit.so +%{_libdir}/libkadm5srv.so +%{_libdir}/libkadm5srv_mit.so +%{_libdir}/libkadm5clnt_mit.so.* +%{_libdir}/libkadm5srv_mit.so.* + +%changelog +* Wed Jul 22 2026 Percona Development Team - 1.18.2-34.percona.1 +- Rebuild with --with-crypto-impl=builtin and --with-tls-impl=no so that + no krb5-libs shared object links OpenSSL. Red Hat's build needs symbol + version nodes (EVP_KDF_ctrl@OPENSSL_1_1_1b) that only exist in the + RHEL OpenSSL 1.1.1 fork, which breaks the Percona PostgreSQL binary + tarball on stock OpenSSL 1.1 hosts. +- Ship the prebuilt PDF manuals from Source3 instead of regenerating + them; drop the TeX Live doc-build dependencies. + +* Tue Apr 28 2026 Julien Rische - 1.18.2-34 +- Fix NegoEx parsing vulnerabilities (CVE-2026-40355, CVE-2026-40356) + Resolves: RHEL-171589 RHEL-171594 + +* Wed Jan 28 2026 Julien Rische - 1.18.2-33 +- krad: packet ID fetched from uninitialized variable + Resolves: RHEL-109220 +- Improving kerberos ulog resize efficiency + Resolves: RHEL-93333 + +* Thu Apr 24 2025 Julien Rische - 1.18.2-32 +- Do not block HMAC-MD4/5 in FIPS mode + Resolves: RHEL-86786 +- Don't issue RC4 session keys by default (CVE-2025-3576) + Resolves: RHEL-88049 +- Add PKINIT paChecksum2 from MS-PKCA v20230920 + Resolves: RHEL-82648 + +* Tue Feb 11 2025 Julien Rische - 1.18.2-31 +- Prevent overflow when calculating ulog block size (CVE-2025-24528) + Resolves: RHEL-78248 +- kdb5_util: fix DB entry flags on modification + Resolves: RHEL-56060 + +* Thu Oct 17 2024 Julien Rische - 1.18.2-30 +- libkrad: implement support for Message-Authenticator (CVE-2024-3596) + Resolves: RHEL-50253 +- Remove RSA protocol for PKINIT + Resolves: RHEL-17616 + +* Mon Jul 01 2024 Julien Rische - 1.18.2-29 +- CVE-2024-37370 CVE-2024-37371 + Fix vulnerabilities in GSS message token handling + Resolves: RHEL-45398 RHEL-45386 + +* Tue Apr 09 2024 Julien Rische - 1.18.2-28 +- Fix leak of default credentials in gss_inquire_cred() + Resolves: RHEL-32258 + +* Thu Mar 21 2024 Julien Rische - 1.18.2-27 +- Fix memory leak in GSSAPI interface + Resolves: RHEL-27250 +- Fix memory leak in PMAP RPC interface + Resolves: RHEL-27244 +- Make TCP waiting time configurable + Resolves: RHEL-17131 + +* Wed Sep 27 2023 Julien Rische - 1.18.2-26 +- Allow to make AD-SIGNEDPATH optional + Resolves: RHEL-10514 + +* Thu Jul 06 2023 Julien Rische - 1.18.2-25 +- Bump release number + +* Wed Jul 05 2023 Julien Rische - 1.18.2-24 +- Remove downloadable source signature file +- Resolves: rhbz#2219654 + +* Wed May 31 2023 Julien Rische - 1.18.2-23 +- Support PAC with KDC extended signature and without ticket signature +- Resolves: rhbz#2169477 + +* Tue Nov 08 2022 Julien Rische - 1.18.2-22 +- Fix integer overflows in PAC parsing (CVE-2022-42898) +- Resolves: rhbz#2140968 + +* Fri Jul 01 2022 Julien Rische - 1.18.2-21 +- Backport fix of memory use after free during libkrad cleanup +- Backport support for larger RADIUS attributes in libkrad +- Resolves: rhbz#2103125 + +* Wed Apr 27 2022 Julien Rische - 1.18.2-19 +- Try harder to avoid password change replay errors +- Resolves: #2077563 + +* Wed Apr 13 2022 Julien Rische - 1.18.2-18 +- Fix kprop for propagating dump files larger than 4GB +- Resolves: #2026462 + +* Mon Mar 21 2022 Julien Rische - 1.18.2-15 +- Backport usage of SHA-256 instead of SHA-1 for PKINIT CMS digest +- Resolves: #2066316 + +* Wed Aug 25 2021 Robbie Harwood - 1.18.2-14 +- Fix KDC null deref on TGS inner body null server (CVE-2021-37750) +- Resolves: #1997601 + +* Tue Jul 20 2021 Robbie Harwood - 1.18.2-13 +- Fix KDC null deref on bad encrypted challenge (CVE-2021-36222) +- Resolves: #1983729 + +* Thu Jun 10 2021 Robbie Harwood - 1.18.2-12 +- Backport KCM performance enablements +- Resolves: #1956388 + +* Thu Jun 10 2021 Robbie Harwood - 1.18.2-11 +- Add APIs for marshalling credentials +- Resolves: #1964619 + +* Mon May 03 2021 Robbie Harwood - 1.18.2-10 +- Update tmpfiles dropin to use /run instead of /var/run +- Resolves: #1945679 + +* Tue Apr 20 2021 Robbie Harwood - 1.18.2-9 +- Add support for start_realm cache config +- Resolves: #1901195 + +* Wed Dec 16 2020 Robbie Harwood - 1.18.2-8 +- Add recursion limit for ASN.1 indefinite lengths (CVE-2020-28196) +- Resolves: #1906492 + +* Tue Nov 24 2020 Robbie Harwood - 1.18.2-7 +- Document -k option in kvno(1) synopsis +- Resolves: #1869055 + +* Wed Oct 21 2020 Robbie Harwood - 1.18.2-6 +- Enable MD5 override for FIPS RADIUS +- Resolves: #1872689 + +* Thu Oct 15 2020 Robbie Harwood - 1.18.2-5.2 +- Unify kvno option documentation +- Resolves: #1869055 + +* Wed Oct 14 2020 Robbie Harwood - 1.18.2-5.1 +- Fix upstream URLs in spec file +- Resolves: #1868039 + +* Tue Aug 04 2020 Robbie Harwood - 1.18.2-5 +- Fix leak in KERB_AP_OPTIONS_CBT server support +- Resolves: #1860831 + +* Tue Jul 28 2020 Robbie Harwood - 1.18.2-4 +- Ignore bad enctypes in krb5_string_to_keysalts() +- Resolves: #1858322 + +* Mon Jun 15 2020 Robbie Harwood - 1.18.2-3 +- Match Heimdal behavior for channel bindings +- Code hygiene + test stability fix included +- Resolves: #1840518 + +* Wed May 27 2020 Robbie Harwood - 1.18.2-2 +- Drop DES3 from sample kdc.conf +- Resolves: #1802334 + +* Fri May 22 2020 Robbie Harwood - 1.18.2-1 +- New upstream release (1.18.2) +- Resolves: #1802334 + +* Fri May 08 2020 Robbie Harwood - 1.18.1-3 +- Omit KDC indicator check for S4U2Self requests +- Resolves: #1802334 + +* Tue Apr 28 2020 Robbie Harwood - 1.18.1-2 +- Pass gss_localname() through SPNEGO +- Resolves: #1802334 + +* Tue Apr 14 2020 Robbie Harwood - 1.18.1-1 +- New upstream version (1.18.1) +- Resolves: #1802334 + +* Tue Apr 07 2020 Robbie Harwood - 1.18-1 +- New upstream version (1.18) +- Resolves: #1802334 +- Resolves: #1820311 +- Resolves: #1791062 +- Resolves: #1784655 + +* Wed Feb 19 2020 Robbie Harwood - 1.17-18 +- Put KDB authdata first +- Resolves: #1800575 + +* Thu Nov 21 2019 Robbie Harwood - 1.17-17 +- OpenSSL has an epoch, apparently +- Resolves: #1754690 + +* Wed Nov 20 2019 Robbie Harwood - 1.17-16 +- Put openssl runtime requirement in the right place this time +- Resolves: #1754690 + +* Wed Nov 20 2019 Robbie Harwood - 1.17-15 +- Restore accidentally dropped patch +- Resolves: #1754690 + +* Wed Nov 20 2019 Robbie Harwood - 1.17-14 +- Fix krb5kdf support and add proper openssl version requirements +- Resolves: #1754690 + +* Tue Nov 19 2019 Robbie Harwood - 1.17-13 +- Full FIPS compliance +- Resolves: #1754690 + +* Tue Oct 15 2019 Robbie Harwood - 1.17-12 +- Backport soft-pkcs11 testing code +- Resolves: #1734158 + +* Tue Oct 15 2019 Robbie Harwood - 1.17-11 +- Fix KCM client time offset propagation +- Resolves: #1738553 + +* Tue Oct 15 2019 Robbie Harwood - 1.17-10 +- Fix source URLs in spec file +- Resolves: #1755959 + +* Tue Sep 17 2019 Robbie Harwood - 1.17-9 +- Fix argument order on strlcpy() in enctype_name() +- Resolves: #1754369 + +* Wed Aug 07 2019 Robbie Harwood - 1.17-8 +- Clean up etype display on KDC +- Resolves: #1664157 + +* Tue Jun 04 2019 Robbie Harwood - 1.17-7 +- Fix pkinit_anchors path +- Resolves: #1661339 + +* Wed May 15 2019 Robbie Harwood - 1.17-6 +- Re-provide krb5-kdb-version in -devel as well (IPA wants it) +- Resolves: #1645594 + +* Thu Apr 18 2019 Robbie Harwood - 1.17-5 +- Move kdbversion info into -server for IPA (so we can rebase) +- Resolves: #1645594 + +* Mon Apr 01 2019 Robbie Harwood - 1.17-4 +- FIPS: disable 3DES and ed25519 +- Resolves: #1616326 + +* Tue Mar 19 2019 Robbie Harwood - 1.17-3 +- Use openssl's PRNG in FIPS mode +- Resolves: #1663571 + +* Tue Mar 19 2019 Robbie Harwood - 1.17-2 +- Address some optimized-out memset() calls +- Resolves: #1663503 + +* Mon Mar 18 2019 Robbie Harwood - 1.17-1 +- New upstream version (1.17) +- Resolves: #1645594 + +* Thu Feb 07 2019 Robbie Harwood - 1.16.1-22 +- Remove incorrect KDC assertion +- Resolves: #1673016 + +* Fri Feb 01 2019 Robbie Harwood - 1.16.1-21 +- Fix RC4 blocking in FIPS mode +- Resolves: #1660222 + +* Thu Dec 20 2018 Robbie Harwood - 1.16.1-20 +- Gain FIPS awareness +- Resolves: #1660222 + +* Wed Aug 01 2018 Robbie Harwood - 1.16.1-19 +- In FIPS mode, add plaintext fallback for RC4 usages and taint + +* Thu Jul 26 2018 Robbie Harwood - 1.16.1-18 +- Fix k5test prompts for Python 3 + +* Thu Jul 19 2018 Robbie Harwood - 1.16.1-17 +- Remove outdated note in krb5kdc man page + +* Thu Jul 19 2018 Robbie Harwood - 1.16.1-16 +- Make krb5kdc -p affect TCP ports + +* Thu Jul 19 2018 Robbie Harwood - 1.16.1-15 +- Eliminate preprocessor-disabled dead code + +* Wed Jul 18 2018 Robbie Harwood - 1.16.1-14 +- Fix some broken tests for Python 3 + +* Mon Jul 16 2018 Robbie Harwood - 1.16.1-13 +- Zap copy of secret in RC4 string-to-key + +* Thu Jul 12 2018 Robbie Harwood - 1.16.1-12 +- Convert Python tests to Python 3 + +* Wed Jul 11 2018 Robbie Harwood - 1.16.1-11 +- Add build dependency on gcc + +* Tue Jul 10 2018 Robbie Harwood - 1.16.1-10 +- Use SHA-256 instead of MD5 for audit ticket IDs + +* Fri Jul 06 2018 Robbie Harwood - 1.16.1-9 +- Add BuildRequires on python2 so we can run tests at build-time + +* Fri Jul 06 2018 Robbie Harwood - 1.16.1-8 +- Explicitly look for python2 in configure.in + +* Thu Jun 14 2018 Robbie Harwood - 1.16.1-7 +- Add flag to disable encrypted timestamp on client + +* Thu Jun 14 2018 Robbie Harwood - 1.16.1-6 +- Switch to python3-sphinx for docs +- Resolves: #1590928 + +* Thu Jun 14 2018 Robbie Harwood - 1.16.1-5 +- Make docs build python3-compatible +- Resolves: #1590928 + +* Thu Jun 07 2018 Robbie Harwood - 1.16.1-4 +- Update includedir processing to match upstream + +* Fri Jun 01 2018 Robbie Harwood - 1.16.1-3 +- Log when non-root ksu authorization fails +- Resolves: #1575771 + +* Fri May 04 2018 Robbie Harwood - 1.16.1-2 +- Remove "-nodes" option from make-certs scripts + +* Fri May 04 2018 Robbie Harwood - 1.16.1-1 +- New upstream release - 1.16.1 + +* Thu May 03 2018 Robbie Harwood - 1.16-27 +- Fix configuration of default ccache name to match file indentation + +* Mon Apr 30 2018 Robbie Harwood - 1.16-26 +- Set error message on KCM get_princ failure + +* Mon Apr 30 2018 Robbie Harwood - 1.16-25 +- Set error message on KCM get_princ failure + +* Tue Apr 24 2018 Robbie Harwood - 1.16-24 +- Fix KDC null dereference on large TGS replies + +* Mon Apr 23 2018 Robbie Harwood - 1.16-23 +- Explicitly use openssl rather than builtin crypto +- Resolves: #1570910 + +* Tue Apr 17 2018 Robbie Harwood - 1.16-22 +- Merge duplicate subsections in profile library + +* Mon Apr 09 2018 Robbie Harwood - 1.16-21 +- Restrict pre-authentication fallback cases + +* Tue Apr 03 2018 Robbie Harwood - 1.16-20 +- Be more careful asking for AS key in SPAKE client + +* Mon Apr 02 2018 Robbie Harwood - 1.16-19 +- Zap data when freeing krb5_spake_factor + +* Thu Mar 29 2018 Robbie Harwood - 1.16-18 +- Continue after KRB5_CC_END in KCM cache iteration + +* Tue Mar 27 2018 Robbie Harwood - 1.16-17 +- Fix SPAKE memory leak + +* Tue Mar 27 2018 Robbie Harwood - 1.16-16 +- Fix gitignore problem with previous patchset + +* Tue Mar 27 2018 Robbie Harwood - 1.16-15 +- Add SPAKE support +- Improve protections on internal sensitive buffers +- Improve internal hex encoding/decoding + +* Tue Mar 20 2018 Robbie Harwood - 1.16-14 +- Fix problem with ccache_name logic in previous build + +* Tue Mar 20 2018 Robbie Harwood - 1.16-13 +- Add pkinit_anchors default value to krb5.conf +- Reindent krb5.conf to not be terrible + +* Tue Mar 20 2018 Robbie Harwood - 1.16-12 +- Log preauth names in trace output +- Misc bugfixes from upstream + +* Mon Mar 19 2018 Robbie Harwood - 1.16-11 +- Add PKINIT KDC support for freshness token + +* Wed Mar 14 2018 Robbie Harwood - 1.16-10 +- Exit with status 0 from kadmind + +* Tue Mar 13 2018 Robbie Harwood - 1.16-9 +- Fix hex conversion of PKINIT certid strings + +* Wed Mar 07 2018 Robbie Harwood - 1.16-8 +- Fix capaths "." values on client +- Resolves: 1551099 + +* Tue Feb 13 2018 Robbie Harwood - 1.16-7 +- Fix flaws in LDAP DN checking +- CVE-2018-5729, CVE-2018-5730 + +* Mon Feb 12 2018 Robbie Harwood - 1.16-6 +- Fix a leak in the previous commit +- Restore dist macro that was accidentally removed +- Resolves: #1540939 + +* Wed Feb 07 2018 Fedora Release Engineering - 1.16-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Sat Feb 03 2018 Igor Gnatenko - 1.16-4 +- Switch to %%ldconfig_scriptlets + +* Mon Jan 29 2018 Robbie Harwood - 1.16-3 +- Process included directories in alphabetical order + +* Tue Dec 12 2017 Robbie Harwood - 1.16-2 +- Fix network service dependencies +- Resolves: #1525230 + +* Wed Dec 06 2017 Robbie Harwood - 1.16-1 +- New upstream release (1.16) +- No changes from beta2 + +* Mon Nov 27 2017 Robbie Harwood - 1.16-0.beta2.1 +- New upstream prerelease (1.16-beta2) + +* Tue Oct 24 2017 Robbie Harwood - 1.16-0.beta1.4 +- Fix CVE-2017-15088 (Buffer overflow in get_matching_data()) + +* Mon Oct 23 2017 Robbie Harwood - 1.16-0.beta1.3 +- Drop dependency on python2-pyrad (dead upstream, broken with new python) + +* Mon Oct 09 2017 Robbie Harwood - 1.16-0.beta1.2 +- Actually bump kdbversion like I was supposed to + +* Thu Oct 05 2017 Robbie Harwood - 1.16-0.beta1.1 +- New upstream prerelease (1.16-beta1) + +* Thu Sep 28 2017 Robbie Harwood - 1.15.2-2 +- Add German translation + +* Mon Sep 25 2017 Robbie Harwood - 1.15.2-1 +- New upstream release - krb5-1.15.2 +- Adjust patches as appropriate + +* Wed Sep 06 2017 Robbie Harwood - 1.15.1-28 +- Save other programs from worrying about CVE-2017-11462 +- Resolves: #1488873 +- Resolves: #1488874 + +* Tue Sep 05 2017 Robbie Harwood - 1.15.1-27 +- Add hostname-based ccselect module +- Resolves: #1463665 + +* Tue Sep 05 2017 Robbie Harwood - 1.15.1-26 +- Backport upstream certauth EKU fixes + +* Fri Aug 25 2017 Robbie Harwood - 1.15.1-25 +- Backport certauth eku security fix + +* Mon Aug 21 2017 Robbie Harwood - 1.15.1-24 +- Backport kdc policy plugin, but this time with dependencies + +* Mon Aug 21 2017 Robbie Harwood - 1.15.1-23 +- Backport kdcpolicy interface + +* Wed Aug 16 2017 Robbie Harwood - 1.15.1-22 + +* Mon Aug 07 2017 Robbie Harwood - 1.15.1-21 +- Display an error message if ocsp pkinit is requested + +* Wed Aug 02 2017 Robbie Harwood - 1.15.1-20 +- Disable dns_canonicalize_hostname. This may break some setups. + +* Wed Aug 02 2017 Robbie Harwood - 1.15.1-19 +- Re-enable test suite on ppc64le (no other changes) + +* Wed Jul 26 2017 Fedora Release Engineering - 1.15.1-18 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Thu Jul 20 2017 Robbie Harwood - 1.15.1-17 +- Fix CVE-2017-11368 (remote triggerable assertion failure) + +* Wed Jul 19 2017 Robbie Harwood - 1.15.1-16 +- Explicitly require python2 packages + +* Wed Jul 19 2017 Robbie Harwood - 1.15.1-15 +- Add support to query the SSF of a context +- Pick up rename of perl dependency + +* Thu Jul 06 2017 Robbie Harwood - 1.15.1-14 +- Fix leaks in gss_inquire_cred_by_oid() + +* Mon Jun 26 2017 Robbie Harwood - 1.15.1-13 +- Fix arch name (ppc64le, not ppc64el) +- Related-to: #1464381 + +* Mon Jun 26 2017 Robbie Harwood - 1.15.1-12 +- Skip test suite on ppc64el +- Related-to: #1464381 + +* Fri Jun 23 2017 Robbie Harwood - 1.15.1-11 +- Include more test suite changes from upstream +- Resolves: #1464381 + +* Wed Jun 07 2017 Robbie Harwood - 1.15.1-10 +- Fix custom build with -DDEBUG + +* Wed May 24 2017 Robbie Harwood - 1.15.1-9 +- Use standard trigger logic for krb5 snippet + +* Fri Apr 28 2017 Robbie Harwood - 1.15.1-8 +- Add kprop service env config file + +* Wed Apr 19 2017 Robbie Harwood - 1.15.1-7 +- Update backports of certauth and corresponding test + +* Thu Apr 13 2017 Robbie Harwood - 1.15.1-6 +- Include fixes for previous commit +- Resolves: #1433083 + +* Thu Apr 13 2017 Robbie Harwood - 1.15.1-5 +- Automatically add includedir where not present +- Try removing sleep statement to see if it is still needed +- Resolves: #1433083 + +* Fri Apr 07 2017 Robbie Harwood - 1.15.1-4 +- Fix use of enterprise principals with forwarding + +* Wed Mar 22 2017 Robbie Harwood - 1.15.1-3 +- Backport certauth plugin and related pkinit changes + +* Tue Mar 07 2017 Robbie Harwood - 1.15.1-2 +- Remove duplication between subpackages +- Resolves: #1250228 + +* Fri Mar 03 2017 Robbie Harwood - 1.15.1-1 +- New upstream release - 1.15.1 + +* Wed Mar 01 2017 Robbie Harwood - 1.15-9 +- Patch build by disabling failing test; will fix properly soon + +* Fri Feb 17 2017 Robbie Harwood - 1.15-8 +- Hammer refresh around transient rawhide issue + +* Fri Feb 17 2017 Robbie Harwood - 1.15-7 +- Backport fix for GSSAPI fallback realm + +* Tue Feb 07 2017 Robbie Harwood - 1.15-6 +- Move krb5-kdb-version provides from -libs to -devel + +* Fri Jan 20 2017 Robbie Harwood - 1.15-5 +- Add free hook to KDB; increments KDB version +- Add KDB version flag + +* Mon Dec 05 2016 Robbie Harwood - 1.15-4 +- New upstream release + +* Wed Nov 16 2016 Robbie Harwood - 1.15-beta2-3 +- New upstream release + +* Thu Nov 10 2016 Robbie Harwood - 1.15-beta1-2 +- Ensure we can build with the new CFLAGS +- Remove the git versioning in patches + +* Thu Oct 20 2016 Robbie Harwood - 1.15-beta1-1 +- New upstream release +- Update selinux with RHEL hygene +- Resolves: #1314096 + +* Tue Oct 11 2016 Tomáš Mráz - 1.14.4-6 +- rebuild with OpenSSL 1.1.0, added backported upstream patch + +* Fri Sep 30 2016 Robbie Harwood - 1.14.4-5 +- Properly close krad sockets +- Resolves: #1380836 + +* Fri Sep 30 2016 Robbie Harwood - 1.14.4-4 +- Fix backward check in kprop.service + +* Fri Sep 30 2016 Robbie Harwood - 1.14.4-3 +- Switch to using autosetup macro. + - Patches come from git, so it is easiest to just make a git repo + +* Thu Sep 22 2016 Robbie Harwood - 1.14.4-2 +- Backport getrandom() support +- Remove patch numbering + +* Mon Sep 19 2016 Robbie Harwood - 1.14.4-1 +- New upstream release +- Update names and numbers to match external git + +* Mon Sep 19 2016 Robbie Harwood - 1.14.3-9 +- Add krb5_db_register_keytab +- Resolves: #1376812 + +* Mon Aug 29 2016 Robbie Harwood - 1.14.3-8 +- Use responder for non-preauth AS requests +- Resolves: #1370622 + +* Mon Aug 29 2016 Robbie Harwood - 1.14.3-7 +- Guess Samba client mutual flag using ap_option +- Resolves: #1370980 + +* Thu Aug 25 2016 Robbie Harwood - 1.14.3-6 +- Fix KDC return code and set prompt types for OTP client preauth +- Resolves: #1370072 + +* Mon Aug 15 2016 Robbie Harwood - 1.14.3-5 +- Turn OFD locks back on with glibc workaround +- Resolves: #1274922 + +* Wed Aug 10 2016 Robbie Harwood - 1.14.3-4 +- Fix use of KKDCPP with SNI +- Resolves: #1365027 + +* Fri Aug 05 2016 Robbie Harwood - 1.14.3-3 +- Make krb5-devel depend on libkadm5 +- Resolves: #1364487 + +* Wed Aug 03 2016 Robbie Harwood - 1.14.3-2 +- Up-port a bunch of stuff from the el-7.3 cycle +- Resolves: #1255450, #1314989 + +* Mon Aug 01 2016 Robbie Harwood - 1.14.3-1 +- New upstream version 1.14.3 + +* Thu Jul 28 2016 Robbie Harwood - 1.14.1-9 +- Fix CVE-2016-3120 +- Resolves: #1361051 + +* Wed Jun 22 2016 Robbie Harwood - 1.14.1-8 +- Fix incorrect recv() size calculation in libkrad + +* Thu Jun 16 2016 Robbie Harwood - 1.14.1-7 +- Separate out the kadm5 libs + +* Fri May 27 2016 Robbie Harwood - 1.14.1-6 +- Fix setting of AS key in OTP preauth failure + +* Tue Apr 05 2016 Robbie Harwood - 1.14.1-5 +- Use the correct patches this time. +- Resolves: #1321135 + +* Mon Apr 04 2016 Robbie Harwood - 1.14.1-4 +- Add send/receive sendto_kdc hooks and corresponding tests +- Resolves: #1321135 + +* Fri Mar 18 2016 Robbie Harwood - 1.14.1-3 +- Fix CVE-2016-3119 (NULL deref in LDAP module) + +* Thu Mar 17 2016 Robbie Harwood - 1.14.1-2 +- Backport OID mech fix +- Resolves: #1317609 + +* Mon Feb 29 2016 Robbie Harwood - 1.14.1-1 +- New rawhide, new upstream version +- Drop CVE patches +- Rename fix_interposer.patch to acquire_cred_interposer.patch +- Update acquire_cred_interposer.patch to apply to new source + +* Mon Feb 22 2016 Robbie Harwood - 1.14-23 +- Fix log file permissions patch with our selinux +- Resolves: #1309421 + +* Fri Feb 19 2016 Robbie Harwood - 1.14-22 +- Backport my interposer fixes from upstream + - Supersedes krb5-mechglue_inqure_attrs.patch + +* Tue Feb 16 2016 Robbie Harwood - 1.14-21 +- Adjust dependency on crypto-polices to be just the file we want +- Patch courtesy of lslebodn +- Resolves: #1308984 + +* Thu Feb 04 2016 Fedora Release Engineering - 1.14-20 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Thu Jan 28 2016 Robbie Harwood - 1.14-19 +- Replace _kadmin/_kprop with systemd macros +- Remove traces of upstart from fedora package per policy +- Resolves: #1290185 + +* Wed Jan 27 2016 Robbie Harwood - 1.14-18 +- Fix CVE-2015-8629, CVE-2015-8630, CVE-2015-8631 + +* Thu Jan 21 2016 Robbie Harwood - 1.14-17 +- Make krb5kdc.log not world-readable by default +- Resolves: #1276484 + +* Thu Jan 21 2016 Robbie Harwood - 1.14-16 +- Allow verification of attributes on krb5.conf + +* Wed Jan 20 2016 Robbie Harwood - 1.14-15 +- Use "new" systemd macros for service handling. (Thanks vpavlin!) +- Resolves: #850399 + +* Wed Jan 20 2016 Robbie Harwood - 1.14-14 +- Remove WITH_NSS macro (always false) +- Remove WITH_SYSTEMD macro (always true) +- Remove WITH_LDAP macro (always true) +- Remove WITH_OPENSSL macro (always true) + +* Fri Jan 08 2016 Robbie Harwood - 1.14-13 +- Backport fix for chrome crash in spnego_gss_inquire_context +- Resolves: #1295893 + +* Wed Dec 16 2015 Robbie Harwood - 1.14-12 +- Backport patch to fix mechglue for gss_inqure_attrs_for_mech() + +* Thu Dec 03 2015 Robbie Harwood - 1.14-11 +- Backport interposer fix (#1284985) +- Drop workaround pwsize initialization patch (gcc has been fixed) + +* Tue Nov 24 2015 Robbie Harwood - 1.14-10 +- Fix FTBFS by no longer working around bug in nss_wrapper + +* Mon Nov 23 2015 Robbie Harwood - 1.14-9 +- Upstream release. No actual change from beta, just version bump +- Clean up unused parts of spec file + +* Mon Nov 16 2015 Robbie Harwood - 1.14-beta2-8 +- New upstream beta version + +* Wed Nov 04 2015 Robbie Harwood - 1.14-beta1-7 +- Patch CVE-2015-2698 + +* Tue Oct 27 2015 Robbie Harwood - 1.14-beta1-6 +- Patch CVE-2015-2697, CVE-2015-2696, CVE-2015-2695 + +* Thu Oct 22 2015 Robbie Harwood - 1.14-beta1-5 +- Ensure pwsize is initialized in chpass_util.c + +* Thu Oct 22 2015 Robbie Harwood - 1.14-beta1-4 +- Fix typo of crypto-policies file in previous version + +* Mon Oct 19 2015 Robbie Harwood - 1.14-beta1-3 +- Start using crypto-policies + +* Mon Oct 19 2015 Robbie Harwood - 1.14-beta1-2 +- TEMPORARILY disable usage of OFD locks as a workaround for x86 + +* Thu Oct 15 2015 Robbie Harwood - 1.14-beta1-1 +- New upstream beta version + +* Thu Oct 08 2015 Robbie Harwood - 1.13.2-13 +- Work around KDC client prinicipal in referrals issue (#1259844) + +* Thu Oct 01 2015 Robbie Harwood - 1.13.2-12 +- Enable building with bad system /etc/krb5.conf + +* Wed Sep 23 2015 Robbie Harwood - 1.13.2-11 +- Drop dependency on pax, ksh +- Remove support for fedora < 20 + +* Wed Sep 23 2015 Robbie Harwood - 1.13.2-10 +- Nix /usr/share/krb5.conf.d to reduce complexity + +* Wed Sep 23 2015 Robbie Harwood - 1.13.2-9 +- Depend on crypto-policies which provides /etc/krb5.conf.d (#1225792) + +* Thu Sep 10 2015 Robbie Harwood - 1.13.2-8 +- Remove dependency on systemd-sysv which is no longer needed for fedora > 20 + This also fixes a fail-to-build issue. +- Miscalaneous spec cleanup fixes + +* Thu Sep 10 2015 Robbie Harwood - 1.13.2-7 +- Support config snippets in /etc/krb5.conf.d/ and /usr/share/krb5.conf.d/ + (#1225792, #1146370, #1145808) + +* Thu Jun 25 2015 Roland Mainz - 1.13.2-6 +- Use system nss_wrapper and socket_wrapper for testing. + Patch by Andreas Schneider + +* Thu Jun 25 2015 Roland Mainz - 1.13.2-5 +- Remove Zanata test glue and related workarounds + - Bug #1234292 ("IPA server cannot be run in container due to incorrect /usr/sbin/_kadmind") + - Bug #1234326 ("krb5-server introduces new rpm dependency on ksh") + +* Thu Jun 18 2015 Roland Mainz - 1.13.2-4 +- Fix dependicy on binfmt.service + +* Wed Jun 17 2015 Fedora Release Engineering - 1.13.2-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Tue Jun 2 2015 Roland Mainz - 1.13.2-2 +- Add patch to fix Redhat Bug #1227542 ("[SELinux] AVC denials may appear + when kadmind starts"). The issue was caused by an unneeded |htons()| + which triggered SELinux AVC denials due to the "random" port usage. + +* Thu May 21 2015 Roland Mainz - 1.13.2-1 +- Add fix for RedHat Bug #1164304 ("Upstream unit tests loads + the installed shared libraries instead the ones from the build") + +* Thu May 14 2015 Roland Mainz - 1.13.2-0 +- Update to krb5-1.13.2 + - drop patch for krb5-1.13.2-CVE_2015_2694_requires_preauth_bypass_in_PKINIT_enabled_KDC, fixed in krb5-1.13.2 + - drop patch for krb5-1.12.1-CVE_2014_5355_fix_krb5_read_message_handling, fixed in krb5-1.13.2 +- Add script processing for upcoming Zanata l10n support +- Minor spec cleanup + +* Mon May 4 2015 Roland Mainz - 1.13.1-4 +- fix for CVE-2015-2694 (#1216133) "requires_preauth bypass + in PKINIT-enabled KDC". + In MIT krb5 1.12 and later, when the KDC is configured with + PKINIT support, an unauthenticated remote attacker can + bypass the requires_preauth flag on a client principal and + obtain a ciphertext encrypted in the principal's long-term + key. This ciphertext could be used to conduct an off-line + dictionary attack against the user's password. + +* Wed Mar 25 2015 Roland Mainz - 1.13.1-3 +- Add temporay workaround for RH bug #1204646 ("krb5-config + returns wrong -specs path") which modifies krb5-config post + build so that development of krb5 dependicies gets unstuck. + This MUST be removed before rawhide becomes F23 ... + +* Thu Mar 19 2015 Roland Mainz - 1.13.1-2 +- fix for CVE-2014-5355 (#1193939) "krb5: unauthenticated + denial of service in recvauth_common() and others" + +* Fri Feb 13 2015 Roland Mainz - 1.13.1-1 +- Update to krb5-1.13.1 + - drop patch for CVE_2014_5353_fix_LDAP_misused_policy_name_crash, fixed in krb5-1.13.1 + - drop patch for kinit -C loops (MIT/krb5 bug #243), fixed in krb5-1.13.1 + - drop patch for CVEs { 2014-9421, 2014-9422, 2014-9423, 2014-5352 }, fixed in krb5-1.13.1 +- Minor spec cleanup + +* Wed Feb 4 2015 Roland Mainz - 1.13-8 +- fix for CVE-2014-5352 (#1179856) "gss_process_context_token() + incorrectly frees context (MITKRB5-SA-2015-001)" +- fix for CVE-2014-9421 (#1179857) "kadmind doubly frees partial + deserialization results (MITKRB5-SA-2015-001)" +- fix for CVE-2014-9422 (#1179861) "kadmind incorrectly + validates server principal name (MITKRB5-SA-2015-001)" +- fix for CVE-2014-9423 (#1179863) "libgssrpc server applications + leak uninitialized bytes (MITKRB5-SA-2015-001)" + +* Wed Feb 4 2015 Roland Mainz - 1.13-7 +- Remove "python-sphinx-latex" and "tar" from the build requirements + to fix build failures on F22 machines. +- Minor spec cleanup + +* Mon Feb 02 2015 Nathaniel McCallum - 1.13-6 +- Support KDC_ERR_MORE_PREAUTH_DATA_REQUIRED (RT#8063) + +* Mon Jan 26 2015 Roland Mainz - 1.13-5 +- fix for kinit -C loops (#1184629, MIT/krb5 issue 243, "Do not + loop on principal unknown errors"). +- Added "python-sphinx-latex" to the build requirements + to fix build failures on F22 machines. + +* Thu Dec 18 2014 Roland Mainz - 1.13-4 +- fix for CVE-2014-5354 (#1174546) "krb5: NULL pointer + dereference when using keyless entries" + +* Wed Dec 17 2014 Roland Mainz - 1.13-3 +- fix for CVE-2014-5353 (#1174543) "Fix LDAP misused policy + name crash" + +* Wed Oct 29 2014 Roland Mainz - 1.13-2 +- Bump 1%%{?dist} to 2%%{?dist} to workaround RPM sort issue + which would lead yum updates to treat the last alpha as newer + than the final version. + +* Wed Oct 29 2014 Roland Mainz - 1.13-1 +- Update from krb5-1.13-alpha1 to final krb5-1.13 +- Removed patch for CVE-2014-5351 (#1145425) "krb5: current + keys returned when randomizing the keys for a service principal" - + now part of upstream sources +- Use patch for glibc |eventfd()| prototype mismatch (#1147887) only + for Fedora > 20 + +* Tue Sep 30 2014 Roland Mainz - 1.13-0.alpha1.3 +- fix build failure caused by change of prototype for glibc + |eventfd()| (#1147887) + +* Mon Sep 29 2014 Roland Mainz - 1.13-0.alpha1.3 +- fix for CVE-2014-5351 (#1145425) "krb5: current keys returned when + randomizing the keys for a service principal" + +* Mon Sep 8 2014 Nalin Dahyabhai - 1.13-0.alpha1.3 +- fix the problem where the %%license file has been a dangling symlink + +* Tue Aug 26 2014 Nalin Dahyabhai - 1.13-0.alpha1.2 +- kpropd hasn't bothered with -S since 1.11; stop trying to use that flag + in the systemd unit file + +* Fri Aug 22 2014 Nalin Dahyabhai - 1.13-0.alpha1.1 +- update to 1.13 alpha1 + - drop upstreamed and backported patches + +* Wed Aug 20 2014 Nalin Dahyabhai - 1.12.2-3 +- pull in upstream fix for an incorrect check on the value returned by a + strdup() call (#1132062) + +* Sun Aug 17 2014 Fedora Release Engineering - 1.12.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild + +* Fri Aug 15 2014 Nalin Dahyabhai - 1.12.2-1 +- update to 1.12.2 + - drop patch for RT#7820, fixed in 1.12.2 + - drop patch for #231147, fixed as RT#3277 in 1.12.2 + - drop patch for RT#7818, fixed in 1.12.2 + - drop patch for RT#7836, fixed in 1.12.2 + - drop patch for RT#7858, fixed in 1.12.2 + - drop patch for RT#7924, fixed in 1.12.2 + - drop patch for RT#7926, fixed in 1.12.2 + - drop patches for CVE-2014-4341/CVE-2014-4342, included in 1.12.2 + - drop patch for CVE-2014-4343, included in 1.12.2 + - drop patch for CVE-2014-4344, included in 1.12.2 + - drop patch for CVE-2014-4345, included in 1.12.2 +- replace older proposed changes for ksu with backports of the changes + after review and merging upstream (#1015559, #1026099, #1118347) + +* Thu Aug 7 2014 Nalin Dahyabhai - 1.12.1-14 +- incorporate fix for MITKRB5-SA-2014-001 (CVE-2014-4345) + +* Mon Jul 21 2014 Nalin Dahyabhai - 1.12.1-13 +- gssapi: pull in upstream fix for a possible NULL dereference + in spnego (CVE-2014-4344) + +* Wed Jul 16 2014 Nalin Dahyabhai - 1.12.1-12 +- gssapi: pull in proposed fix for a double free in initiators (David + Woodhouse, CVE-2014-4343, #1117963) + +* Sat Jul 12 2014 Tom Callaway - 1.12.1-11 +- fix license handling + +* Mon Jul 7 2014 Nalin Dahyabhai - 1.12.1-10 +- pull in fix for denial of service by injection of malformed GSSAPI tokens + (CVE-2014-4341, CVE-2014-4342, #1116181) + +* Tue Jun 24 2014 Nalin Dahyabhai - 1.12.1-9 +- pull in changes from upstream which add processing of the contents of + /etc/gss/mech.d/*.conf when loading GSS modules (#1102839) + +* Thu Jun 12 2014 Nalin Dahyabhai - 1.12.1-8 +- pull in fix for building against tcl 8.6 (#1107061) + +* Sun Jun 08 2014 Fedora Release Engineering - 1.12.1-7 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Tue Mar 04 2014 Nathaniel McCallum - 1.12.1-6 +- Backport fix for change password requests when using FAST (RT#7868) + +* Mon Feb 17 2014 Nalin Dahyabhai - 1.12.1-5 +- spnego: pull in patch from master to restore preserving the OID of the + mechanism the initiator requested when we have multiple OIDs for the same + mechanism, so that we reply using the same mechanism OID and the initiator + doesn't get confused (#1066000, RT#7858) + +* Fri Feb 7 2014 Nalin Dahyabhai - 1.12.1-4 +- pull in patch from master to move the default directory which the KDC uses + when computing the socket path for a local OTP daemon from the database + directory (/var/kerberos/krb5kdc) to the newly-added run directory + (/run/krb5kdc), in line with what we're expecting in 1.13 (RT#7859, more + of #1040056 as #1063905) +- add a tmpfiles.d configuration file to have /run/krb5kdc created at + boot-time +- own /var/run/krb5kdc + +* Fri Jan 31 2014 Nalin Dahyabhai - 1.12.1-3 +- refresh nss_wrapper and add socket_wrapper to the %%check environment + +* Fri Jan 31 2014 Nalin Dahyabhai +- add currently-proposed changes to teach ksu about credential cache + collections and the default_ccache_name setting (#1015559,#1026099) + +* Tue Jan 21 2014 Nalin Dahyabhai - 1.12.1-2 +- pull in multiple changes to allow replay caches to be added to a GSS + credential store as "rcache"-type credentials (RT#7818/#7819/#7836, + #1056078/#1056080) + +* Fri Jan 17 2014 Nalin Dahyabhai - 1.12.1-1 +- update to 1.12.1 + - drop patch for RT#7794, included now + - drop patch for RT#7797, included now + - drop patch for RT#7803, included now + - drop patch for RT#7805, included now + - drop patch for RT#7807, included now + - drop patch for RT#7045, included now + - drop patches for RT#7813 and RT#7815, included now + - add patch to always retrieve the KDC time offsets from keyring caches, + so that we don't mistakenly interpret creds as expired before their + time when our clock is ahead of the KDC's (RT#7820, #1030607) + +* Mon Jan 13 2014 Nalin Dahyabhai - 1.12-11 +- update the PIC patch for iaesx86.s to not use ELF relocations to the version + that landed upstream (RT#7815, #1045699) + +* Thu Jan 9 2014 Nalin Dahyabhai +- pass -Wl,--warn-shared-textrel to the compiler when we're creating shared + libraries + +* Thu Jan 9 2014 Nalin Dahyabhai - 1.12-10 +- amend the PIC patch for iaesx86.s to also save/restore ebx in the + functions where we modify it, because the ELF spec says we need to + +* Mon Jan 6 2014 Nalin Dahyabhai - 1.12-9 +- grab a more-commented version of the most recent patch from upstream + master +- make a guess at making the 32-bit AES-NI implementation sufficiently + position-independent to not require execmod permissions for libk5crypto + (more of #1045699) + +* Thu Jan 2 2014 Nalin Dahyabhai - 1.12-8 +- add patch from Dhiru Kholia for the AES-NI implementations to allow + libk5crypto to be properly marked as not needing an executable stack + on arches where they're used (#1045699, and so many others) + +* Thu Jan 2 2014 Nalin Dahyabhai - 1.12-7 +- revert that last change for a bit while sorting out execstack when we + use AES-NI (#1045699) + +* Thu Dec 19 2013 Nalin Dahyabhai - 1.12-6 +- add yasm as a build requirement for AES-NI support, on arches that have + yasm and AES-NI + +* Thu Dec 19 2013 Nalin Dahyabhai - 1.12-5 +- pull in fix from master to make reporting of errors encountered by + the SPNEGO mechanism work better (RT#7045, part of #1043962) + +* Thu Dec 19 2013 Nalin Dahyabhai +- update a test wrapper to properly handle things that the new libkrad does, + and add python-pyrad as a build requirement so that we can run its tests + +* Wed Dec 18 2013 Nalin Dahyabhai - 1.12-4 +- revise previous patch to initialize one more element + +* Wed Dec 18 2013 Nalin Dahyabhai - 1.12-3 +- backport fixes to krb5_copy_context (RT#7807, #1044735/#1044739) + +* Wed Dec 18 2013 Nalin Dahyabhai - 1.12-2 +- pull in fix from master to return a NULL pointer rather than allocating + zero bytes of memory if we read a zero-length input token (RT#7794, part of + #1043962) +- pull in fix from master to ignore an empty token from an acceptor if + we've already finished authenticating (RT#7797, part of #1043962) +- pull in fix from master to avoid a memory leak when a mechanism's + init_sec_context function fails (RT#7803, part of #1043962) +- pull in fix from master to avoid a memory leak in a couple of error + cases which could occur while obtaining acceptor credentials (RT#7805, part + of #1043962) + +* Wed Dec 11 2013 Nalin Dahyabhai - 1.12-1 +- update to 1.12 final + +* Mon Dec 2 2013 Nalin Dahyabhai - 1.12-beta2.0 +- update to beta2 + - drop obsolete backports for storing KDC time offsets and expiration times + in keyring credential caches + +* Tue Nov 19 2013 Nalin Dahyabhai - 1.12-beta1.0 +- rebase to master +- update to beta1 + - drop obsolete backport of fix for RT#7706 + +* Mon Nov 18 2013 Nalin Dahyabhai - 1.11.4-2 +- pull in fix to store KDC time offsets in keyring credential caches (RT#7768, + #1030607) +- pull in fix to set expiration times on credentials stored in keyring + credential caches (RT#7769, #1031724) + +* Tue Nov 12 2013 Nalin Dahyabhai - 1.11.4-1 +- update to 1.11.4 + - drop patch for RT#7650, obsoleted + - drop patch for RT#7706, obsoleted as RT#7723 + - drop patch for CVE-2013-1418/CVE-2013-6800, included in 1.11.4 + +* Tue Nov 12 2013 Nalin Dahyabhai - 1.11.3-31 +- switch to the simplified version of the patch for #1029110 (RT#7764) + +* Mon Nov 11 2013 Nalin Dahyabhai - 1.11.3-30 +- check more thoroughly for errors when resolving KEYRING ccache names of type + "persistent", which should only have a numeric UID as the next part of the + name (#1029110) + +* Tue Nov 5 2013 Nalin Dahyabhai - 1.11.3-29 +- incorporate upstream patch for remote crash of KDCs which serve multiple + realms simultaneously (RT#7756, CVE-2013-1418/CVE-2013-6800, + #1026997/#1031501) + +* Mon Nov 4 2013 Nalin Dahyabhai - 1.11.3-28 +- drop patch to add additional access() checks to ksu - they add to breakage + when non-FILE: caches are in use (#1026099), shouldn't be resulting in any + benefit, and clash with proposed changes to fix its cache handling + +* Tue Oct 22 2013 Nalin Dahyabhai - 1.11.3-27 +- add some minimal description to the top of the wrapper scripts we use + when starting krb5kdc and kadmind to describe why they exist (tooling) + +* Thu Oct 17 2013 Nalin Dahyabhai - 1.12-alpha1.0 +- initial update to alpha1 + - drop backport of persistent keyring support + - drop backport for RT#7689 + - drop obsolete patch for fixing a use-before-init in a test program + - drop obsolete patch teaching config.guess/config.sub about aarch64-linux + - drop backport for RT#7598 + - drop backport for RT#7172 + - drop backport for RT#7642 + - drop backport for RT#7643 + - drop patches from master to not test GSSRPC-over-UDP and to not + depend on the portmapper, which are areas where our build systems + often give us trouble, too; obsolete + - drop backports for RT#7682 + - drop backport for RT#7709 + - drop backport for RT#7590 and partial backport for RT#7680 + - drop OTP backport + - drop backports for RT#7656 and RT#7657 +- BuildRequires: libedit-devel to prefer it +- BuildRequires: pkgconfig, since configure uses it + +* Wed Oct 16 2013 Nalin Dahyabhai - 1.11.3-26 +- create and own /etc/gss (#1019937) + +* Tue Oct 15 2013 Nalin Dahyabhai - 1.11.3-25 +- pull up fix for importing previously-exported credential caches in the + gssapi library (RT# 7706, #1019420) + +* Mon Oct 14 2013 Nalin Dahyabhai - 1.11.3-24 +- backport the callback to use the libkrb5 prompter when we can't load PEM + files for PKINIT (RT#7590, includes part of #965721/#1016690) +- extract the rest of the fix #965721/#1016690 from the changes for RT#7680 + +* Mon Oct 14 2013 Nalin Dahyabhai - 1.11.3-23 +- fix trigger scriptlet's invocation of sed (#1016945) + +* Fri Oct 4 2013 Nalin Dahyabhai - 1.11.3-22 +- rebuild with keyutils 1.5.8 (part of #1012043) + +* Wed Oct 2 2013 Nalin Dahyabhai - 1.11.3-21 +- switch to the version of persistent-keyring that was just merged to + master (RT#7711), along with related changes to kinit (RT#7689) +- go back to setting default_ccache_name to a KEYRING type + +* Mon Sep 30 2013 Nalin Dahyabhai - 1.11.3-20 +- pull up fix for not calling a kdb plugin's check-transited-path + method before calling the library's default version, which only knows + how to read what's in the configuration file (RT#7709, #1013664) + +* Thu Sep 26 2013 Nalin Dahyabhai - 1.11.3-19 +- configure --without-krb5-config so that we don't pull in the old default + ccache name when we want to stop setting a default ccache name at configure- + time + +* Wed Sep 25 2013 Nalin Dahyabhai - 1.11.3-18 +- fix broken dependency on awk (should be gawk, rdieter) + +* Wed Sep 25 2013 Nalin Dahyabhai - 1.11.3-17 +- add missing dependency on newer keyutils-libs (#1012034) + +* Tue Sep 24 2013 Nalin Dahyabhai - 1.11.3-16 +- back out setting default_ccache_name to the new default for now, resetting + it to the old default while the kernel/keyutils bits get sorted (sgallagh) + +* Mon Sep 23 2013 Nalin Dahyabhai - 1.11.3-15 +- add explicit build-time dependency on a version of keyutils that's new + enough to include keyctl_get_persistent() (more of #991148) + +* Thu Sep 19 2013 Nalin Dahyabhai - 1.11.3-14 +- incorporate Simo's updated backport of his updated persistent-keyring changes + (more of #991148) + +* Fri Sep 13 2013 Nalin Dahyabhai - 1.11.3-13 +- don't break during %%check when the session keyring is revoked + +* Fri Sep 13 2013 Nalin Dahyabhai - 1.11.3-12 +- pull the newer F21 defaults back to F20 (sgallagh) + +* Mon Sep 9 2013 Nalin Dahyabhai +- only apply the patch to autocreate /run/user/0 when we're hard-wiring the + default ccache location to be under it; otherwise it's unnecessary + +* Mon Sep 9 2013 Nalin Dahyabhai 1.11.3-11 +- don't let comments intended for one scriptlet become part of the "script" + that gets passed to ldconfig as part of another one (Mattias Ellert, #1005675) + +* Fri Sep 6 2013 Nalin Dahyabhai 1.11.3-10 +- incorporate Simo's backport of his persistent-keyring changes (#991148) +- restore build-time default DEFCCNAME on Fedora 21 and later and EL, and + instead set default_ccache_name in the default krb5.conf's [libdefaults] + section (#991148) +- on releases where we expect krb5.conf to be configured with a + default_ccache_name, add it whenever we upgrade from an older version of + the package that wouldn't have included it in its default configuration + file (#991148) + +* Fri Aug 23 2013 Nalin Dahyabhai 1.11.3-9 +- take another stab at accounting for UnversionedDocdirs for the -libs + subpackage (spotted by ssorce) +- switch to just the snapshot of nss_wrapper we were using, since we + no longer need to carry anything that isn't in the cwrap.org repository + (ssorce) + +* Thu Aug 15 2013 Nalin Dahyabhai 1.11.3-8 +- drop a patch we weren't not applying (build tooling) +- wrap kadmind and kpropd in scripts which check for the presence/absence + of files which dictate particular exit codes before exec'ing the actual + binaries, instead of trying to use ConditionPathExists in the unit files + to accomplish that, so that we exit with failure properly when what we + expect isn't actually in effect on the system (#800343) + +* Mon Jul 29 2013 Nalin Dahyabhai 1.11.3-7 +- attempt to account for UnversionedDocdirs for the -libs subpackage + +* Fri Jul 26 2013 Nalin Dahyabhai 1.11.3-6 +- tweak configuration files used during tests to try to reduce the number + of conflicts encountered when builds for multiple arches land on the same + builder + +* Mon Jul 22 2013 Nalin Dahyabhai 1.11.3-5 +- pull up changes to allow GSSAPI modules to provide more functions + (RT#7682, #986564/#986565) + +* Fri Jul 19 2013 Nalin Dahyabhai 1.11.3-4 +- use (a bundled, for now, copy of) nss_wrapper to let us run some of the + self-tests at build-time in more places than we could previously (#978756) +- cover inconsistencies in whether or not there's a local caching nameserver + that's willing to answer when the build environment doesn't have a + resolver configuration, so that nss_wrapper's faking of the local + hostname can be complete + +* Mon Jul 1 2013 Nalin Dahyabhai 1.11.3-3 +- specify dependencies on the same arch of krb5-libs by using the %%{?_isa} + suffix, to avoid dragging 32-bit libraries onto 64-bit systems (#980155) + +* Thu Jun 13 2013 Nalin Dahyabhai 1.11.3-2 +- special-case /run/user/0, attempting to create it when resolving a + directory cache below it fails due to ENOENT and we find that it doesn't + already exist, either, before attempting to create the directory cache + (maybe helping, maybe just making things more confusing for #961235) + +* Tue Jun 4 2013 Nalin Dahyabhai 1.11.3-1 +- update to 1.11.3 + - drop patch for RT#7605, fixed in this release + - drop patch for CVE-2002-2443, fixed in this release + - drop patch for RT#7369, fixed in this release +- pull upstream fix for breaking t_skew.py by adding the patch for #961221 + +* Fri May 31 2013 Nalin Dahyabhai 1.11.2-10 +- respin with updated version of patch for RT#7650 (#969331) + +* Thu May 30 2013 Nalin Dahyabhai 1.11.2-9 +- don't forget to set the SELinux label when creating the directory for + a DIR: ccache +- pull in proposed fix for attempts to get initial creds, which end up + following referrals, incorrectly trying to always use master KDCs if + they talked to a master at any point (should fix RT#7650) + +* Thu May 30 2013 Nalin Dahyabhai 1.11.2-8 +- pull in patches from master to not test GSSRPC-over-UDP and to not + depend on the portmapper, which are areas where our build systems + often give us trouble, too + +* Tue May 28 2013 Nalin Dahyabhai 1.11.2-7 +- backport fix for not being able to verify the list of transited realms + in GSS acceptors (RT#7639, #959685) +- backport fix for not being able to pass an empty password to the + get-init-creds APIs and have them actually use it (RT#7642, #960001) +- add backported proposed fix to use the unauthenticated server time + as the basis for computing the requested credential expiration times, + rather than the client's idea of the current time, which could be + significantly incorrect (#961221) + +* Tue May 21 2013 Nalin Dahyabhai 1.11.2-6 +- pull in upstream fix to start treating a KRB5CCNAME value that begins + with DIR:: the same as it would a DIR: value with just one ccache file + in it (RT#7172, #965574) + +* Mon May 13 2013 Nalin Dahyabhai 1.11.2-5 +- pull up fix for UDP ping-pong flaw in kpasswd service (CVE-2002-2443, + #962531,#962534) + +* Mon Apr 29 2013 Nathaniel McCallum 1.11.2-4 +- Update otp patches +- Merge otp patches into a single patch +- Add keycheck patch + +* Tue Apr 23 2013 Nalin Dahyabhai 1.11.2-3 +- pull the changing of the compiled-in default ccache location to + DIR:/run/user/%%{uid}/krb5cc back into F19, in line with SSSD and + the most recent pam_krb5 build + +* Wed Apr 17 2013 Nalin Dahyabhai 1.11.2-2 +- correct some configuration file paths which the KDC_DIR patch missed + +* Mon Apr 15 2013 Nalin Dahyabhai 1.11.2-1 +- update to 1.11.2 + - drop pulled in patch for RT#7586, included in this release + - drop pulled in patch for RT#7592, included in this release +- pull in fix for keeping track of the message type when parsing FAST requests + in the KDC (RT#7605, #951843) (also #951965) + +* Fri Apr 12 2013 Nalin Dahyabhai 1.11.1-9 +- move the compiled-in default ccache location from the previous default of + FILE:/tmp/krb5cc_%%{uid} to DIR:/run/user/%%{uid}/krb5cc (part of #949588) + +* Tue Apr 09 2013 Nathaniel McCallum - 1.11.1-8 +- Update otp backport patches (libk5radius => libkrad) + +* Wed Apr 3 2013 Nalin Dahyabhai 1.11.1-7 +- when testing the RPC library, treat denials from the local portmapper the + same as a portmapper-not-running situation, to allow other library tests + to be run while building the package + +* Thu Mar 28 2013 Nalin Dahyabhai 1.11.1-6 +- create and own /var/kerberos/krb5/user instead of /var/kerberos/kdc/user, + since that's what the libraries actually look for +- add buildrequires on nss-myhostname, in an attempt to get more of the tests + to run properly during builds +- pull in Simo's patch to recognize "client_keytab" as a key type which can + be passed in to gss_acquire_cred_from() (RT#7598) + +* Tue Mar 26 2013 Nalin Dahyabhai 1.11.1-5 +- pull up Simo's patch to mark the correct mechanism on imported GSSAPI + contexts (RT#7592) +- go back to using reconf to run autoconf and autoheader (part of #925640) +- add temporary patch to use newer config.guess/config.sub (more of #925640) + +* Mon Mar 18 2013 Nalin Dahyabhai +- fix a version comparison to expect newer texlive build requirements when + %%{_rhel} > 6 rather than when it's > 7 + +* Mon Mar 11 2013 Nathaniel McCallum 1.11.1-4 +- Add libverto-devel requires for krb5-devel +- Add otp support + +* Thu Feb 28 2013 Nalin Dahyabhai 1.11.1-3 +- fix a memory leak when acquiring credentials using a keytab (RT#7586, #911110) + +* Wed Feb 27 2013 Nalin Dahyabhai 1.11.1-2 +- prebuild PDF docs to reduce multilib differences (internal tooling, #884065) +- drop the kerberos-iv portreserve file, and drop the rest on systemd systems +- escape uses of macros in comments (more of #884065) + +* Mon Feb 25 2013 Nalin Dahyabhai 1.11.1-1 +- update to 1.11.1 + - drop patch for noticing negative timeouts being passed to the poll() + wrapper in the client transmit functions + +* Fri Feb 8 2013 Nalin Dahyabhai 1.11-2 +- set "rdns = false" in the default krb5.conf (#908323,#908324) + +* Tue Dec 18 2012 Nalin Dahyabhai 1.11-1 +- update to 1.11 release + +* Thu Dec 13 2012 Nalin Dahyabhai 1.11-0.beta2.0 +- update to 1.11 beta 2 + +* Thu Dec 13 2012 Nalin Dahyabhai +- when building with our bundled copy of libverto, package it in with -libs + rather than with -server (#886049) + +* Wed Nov 21 2012 Nalin Dahyabhai 1.11-0.beta1.0 +- update to 1.11 beta 1 + +* Fri Nov 16 2012 Nalin Dahyabhai 1.11-0.alpha1.1 +- handle releases where texlive packaging wasn't yet as complicated as it + is in Fedora 18 +- fix an uninitialized-variable error building one of the test programs + +* Fri Nov 16 2012 Nalin Dahyabhai 1.11-0.alpha1.0 +- move the rather large pile of html and pdf docs to -workstation, so + that just having something that links to the libraries won't drag + them onto a system, and we avoid having to sort out hard-coded paths + that include %%{_libdir} showing up in docs in multilib packages +- actually create %%{_var}/kerberos/kdc/user, so that it can be packaged +- correct the list of packaged man pages +- don't dummy up required tex stylesheets, require them +- require pdflatex and makeindex + +* Thu Nov 15 2012 Nalin Dahyabhai +- update to 1.11 alpha 1 + - drop backported patch for RT #7406 + - drop backported patch for RT #7407 + - drop backported patch for RT #7408 + - the new docs system generates PDFs, so stop including them as sources + - drop backported patch to allow deltat.y to build with the usual + warning flags and the current gcc + - drop backported fix for disabling use of a replay cache when verifying + initial credentials + - drop backported fix for teaching PKINIT clients which trust the KDC's + certificate directly to verify signed-data messages that are signed with + the KDC's certificate, when the blobs don't include a copy of the KDC's + certificate + - drop backported patches to make keytab-based authentication attempts + work better when the client tells the KDC that it supports a particular + cipher, but doesn't have a key for it in the keytab + - drop backported fix for avoiding spurious clock skew when a TGT is + decrypted long after the KDC sent it to the client which decrypts it + - move the cross-referenced HTML docs into the -libs package to avoid + broken internal links + - drop patches to fixup paths in man pages, shouldn't be needed any more + +* Wed Oct 17 2012 Nalin Dahyabhai 1.10.3-7 +- tag a couple of other patches which we still need to be applied during + %%{?_rawbuild} builds (zmraz) + +* Tue Sep 25 2012 Nalin Dahyabhai 1.10.3-6 +- actually pull up the patch for RT#7063, and not some other ticket (#773496) + +* Mon Sep 10 2012 Nalin Dahyabhai 1.10.3-5 +- add patch based on one from Filip Krska to not call poll() with a negative + timeout when the caller's intent is for us to just stop calling it (#838548) + +* Fri Sep 7 2012 Nalin Dahyabhai +- on EL6, conflict with libsmbclient before 3.5.10-124, which is when it + stopped linking with a symbol which we no longer export (#771687) +- pull up patch for RT#7063, in which not noticing a prompt for a long + time throws the client library's idea of the time difference between it + and the KDC really far out of whack (#773496) +- add a backport of more patches to set the client's list of supported enctypes + when using a keytab to be the list of types of keys in the keytab, plus the + list of other types the client supports but for which it doesn't have keys, + in that order, so that KDCs have a better chance of being able to issue + tickets with session keys of types that the client can use (#837855) + +* Thu Sep 6 2012 Nalin Dahyabhai 1.10.3-4 +- cut down the number of times we load SELinux labeling configuration from + a minimum of two times to actually one (more of #845125) + +* Thu Aug 30 2012 Nalin Dahyabhai 1.10.3-3 +- backport patch to disable replay detection in krb5_verify_init_creds() + while reading the AP-REQ that's generated in the same function (RT#7229) + +* Thu Aug 30 2012 Nalin Dahyabhai 1.10.3-2 +- undo rename from krb5-pkinit-openssl to krb5-pkinit on EL6 +- version the Obsoletes: on the krb5-pkinit-openssl to krb5-pkinit rename +- reintroduce the init scripts for non-systemd releases +- forward-port %%{?_rawbuild} annotations from EL6 packaging + +* Thu Aug 9 2012 Nalin Dahyabhai 1.10.3-1 +- update to 1.10.3, rolling in the fixes from MITKRB5-SA-2012-001 + +* Thu Aug 2 2012 Nalin Dahyabhai 1.10.2-7 +- selinux: hang on to the list of selinux contexts, freeing and reloading + it only when the file we read it from is modified, freeing it when the + shared library is being unloaded (#845125) + +* Thu Aug 2 2012 Nalin Dahyabhai 1.10.2-6 +- go back to not messing with library file paths on Fedora 17: it breaks + file path dependencies in other packages, and since Fedora 17 is already + released, breaking that is our fault + +* Tue Jul 31 2012 Nalin Dahyabhai 1.10.2-5 +- add upstream patch to fix freeing an uninitialized pointer and dereferencing + another uninitialized pointer in the KDC (MITKRB5-SA-2012-001, CVE-2012-1014 + and CVE-2012-1015, #844779 and #844777) +- fix a thinko in whether or not we mess around with devel .so symlinks on + systems without a separate /usr (sbose) + +* Fri Jul 27 2012 Fedora Release Engineering - 1.10.2-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Fri Jun 22 2012 Nalin Dahyabhai 1.10.2-3 +- backport a fix to allow a PKINIT client to handle SignedData from a KDC + that's signed with a certificate that isn't in the SignedData, but which + is available as an anchor or intermediate on the client (RT#7183) + +* Tue Jun 5 2012 Nalin Dahyabhai 1.10.2-2 +- back out this labeling change (dwalsh): + - when building the new label for a file we're about to create, also mix + in the current range, in addition to the current user + +* Fri Jun 1 2012 Nalin Dahyabhai 1.10.2-1 +- update to 1.10.2 + - when building the new label for a file we're about to create, also mix + in the current range, in addition to the current user + - also package the PDF format admin, user, and install guides + - drop some PDFs that no longer get built right +- add a backport of Stef's patch to set the client's list of supported + enctypes to match the types of keys that we have when we are using a + keytab to try to get initial credentials, so that a KDC won't send us + an AS reply that we can't encrypt (RT#2131, #748528) +- don't shuffle around any shared libraries on releases with no-separate-/usr, + since /usr/lib is the same place as /lib +- add explicit buildrequires: on 'hostname', for the tests, on systems where + it's in its own package, and require net-tools, which used to provide the + command, everywhere + +* Mon May 7 2012 Nalin Dahyabhai +- skip the setfscreatecon() if fopen() is passed "rb" as the open mode (part + of #819115) + +* Tue May 1 2012 Nalin Dahyabhai 1.10.1-3 +- have -server require /usr/share/dict/words, which we set as the default + dict_file in kdc.conf (#817089) + +* Tue Mar 20 2012 Nalin Dahyabhai 1.10.1-2 +- change back dns_lookup_kdc to the default setting (Stef Walter, #805318) +- comment out example.com examples in default krb5.conf (Stef Walter, #805320) + +* Fri Mar 9 2012 Nalin Dahyabhai 1.10.1-1 +- update to 1.10.1 + - drop the KDC crash fix + - drop the KDC lookaside cache fix + - drop the fix for kadmind RPC ACLs (CVE-2012-1012) + +* Wed Mar 7 2012 Nalin Dahyabhai 1.10-5 +- when removing -workstation, remove our files from the info index while + the file is still there, in %%preun, rather than %%postun, and use the + compressed file's name (#801035) + +* Tue Feb 21 2012 Nathaniel McCallum - 1.10-4 +- Fix string RPC ACLs (RT#7093); CVE-2012-1012 + +* Tue Jan 31 2012 Nathaniel McCallum - 1.10-3 +- Add upstream lookaside cache behavior fix (RT#7082) + +* Mon Jan 30 2012 Nalin Dahyabhai 1.10-2 +- add patch to accept keytab entries with vno==0 as matches when we're + searching for an entry with a specific name/kvno (#230382/#782211,RT#3349) + +* Mon Jan 30 2012 Nalin Dahyabhai 1.10-1 +- update to 1.10 final + +* Thu Jan 26 2012 Nathaniel McCallum - 1.10-0.beta1.2 +- Add upstream crashfix patch (RT#7081) + +* Thu Jan 12 2012 Nalin Dahyabhai 1.10-0.beta1.1 +- update to beta 1 + +* Wed Jan 11 2012 Peter Robinson +- mktemp was long obsoleted by coreutils + +* Wed Jan 4 2012 Nalin Dahyabhai 1.10-0.alpha2.2 +- modify the deltat grammar to also tell gcc (4.7) to suppress + "maybe-uninitialized" warnings in addition to the "uninitialized" warnings + it's already being told to suppress (RT#7080) + +* Tue Dec 20 2011 Nalin Dahyabhai 1.10-0.alpha2.1 +- update to alpha 2 +- drop a couple of patches which were integrated for alpha 2 + +* Tue Dec 13 2011 Nalin Dahyabhai 1.10-0.alpha1.3 +- pull in patch for RT#7046: tag a ccache containing credentials obtained via + S4U2Proxy with the principal name of the proxying principal (part of #761317) + so that the default principal name can be set to that of the client for which + it is proxying, which results in the ccache looking more normal to consumers + of the ccache that don't care that there's proxying going on +- pull in patch for RT#7047: allow tickets obtained via S4U2Proxy to be cached + (more of #761317) +- pull in patch for RT#7048: allow PAC verification to only bother trying to + verify the signature with keys that it's given (still more of #761317) + +* Tue Dec 6 2011 Nalin Dahyabhai 1.10-0.alpha1.2 +- apply upstream patch to fix a null pointer dereference when processing + TGS requests (CVE-2011-1530, #753748) + +* Wed Nov 30 2011 Nalin Dahyabhai 1.10-0.alpha1.1 +- correct a bug in the fix for #754001 so that the file creation context is + consistently reset + +* Tue Nov 15 2011 Nalin Dahyabhai 1.10-0.alpha1.0 +- update to 1.10 alpha 1 +- on newer releases where we can assume NSS >= 3.13, configure PKINIT to build + using NSS +- on newer releases where we build PKINIT using NSS, configure libk5crypto to + build using NSS +- rename krb5-pkinit-openssl to krb5-pkinit on newer releases where we're + expecting to build PKINIT using NSS instead +- during %%check, run check in the library and kdc subdirectories, which + should be able to run inside of the build system without issue + +* Wed Oct 26 2011 Fedora Release Engineering - 1.9.1-19 +- Rebuilt for glibc bug#747377 + +* Tue Oct 18 2011 Nalin Dahyabhai 1.9.1-18 +- apply upstream patch to fix a null pointer dereference with the LDAP kdb + backend (CVE-2011-1527, #744125), an assertion failure with multiple kdb + backends (CVE-2011-1528), and a null pointer dereference with multiple kdb + backends (CVE-2011-1529) (#737711) + +* Thu Oct 13 2011 Nalin Dahyabhai 1.9.1-17 +- pull in patch from trunk to rename krb5int_pac_sign() to krb5_pac_sign() and + make it public (#745533) + +* Fri Oct 7 2011 Nalin Dahyabhai 1.9.1-16 +- kadmin.service: fix #723723 again +- kadmin.service,krb5kdc.service: remove optional use of $KRB5REALM in command + lines, because systemd parsing doesn't handle alternate value shell variable + syntax +- kprop.service: add missing Type=forking so that systemd doesn't assume simple +- kprop.service: expect the ACL configuration to be there, not absent +- handle a harder-to-trigger assertion failure that starts cropping up when we + exit the transmit loop on time (#739853) + +* Sun Oct 2 2011 Tom Callaway 1.9.1-15 +- hardcode pid file as option in krb5kdc.service + +* Fri Sep 30 2011 Tom Callaway 1.9.1-14 +- fix pid path in krb5kdc.service + +* Mon Sep 19 2011 Tom Callaway 1.9.1-13 +- convert to systemd + +* Tue Sep 6 2011 Nalin Dahyabhai 1.9.1-12 +- pull in upstream patch for RT#6952, confusion following referrals for + cross-realm auth (#734341) +- pull in build-time deps for the tests + +* Thu Sep 1 2011 Nalin Dahyabhai 1.9.1-11 +- switch to the upstream patch for #727829 + +* Wed Aug 31 2011 Nalin Dahyabhai 1.9.1-10 +- handle an assertion failure that starts cropping up when the patch for + using poll (#701446) meets servers that aren't running KDCs or against + which the connection fails for other reasons (#727829, #734172) + +* Mon Aug 8 2011 Nalin Dahyabhai 1.9.1-9 +- override the default build rules to not delete temporary y.tab.c files, + so that they can be packaged, allowing debuginfo files which point to them + do so usefully (#729044) + +* Fri Jul 22 2011 Nalin Dahyabhai 1.9.1-8 +- build shared libraries with partial RELRO support (#723995) +- filter out potentially multiple instances of -Wl,-z,relro from krb5-config + output, now that it's in the buildroot's default LDFLAGS +- pull in a patch to fix losing track of the replay cache FD, from SVN by + way of Kevin Coffman + +* Wed Jul 20 2011 Nalin Dahyabhai 1.9.1-7 +- kadmind.init: drop the attempt to detect no-database-present errors (#723723), + which is too fragile in cases where the database has been manually moved or + is accessed through another kdb plugin + +* Tue Jul 19 2011 Nalin Dahyabhai 1.9.1-6 +- backport fixes to teach libkrb5 to use descriptors higher than FD_SETSIZE + to talk to a KDC by using poll() if it's detected at compile-time (#701446, + RT#6905) + +* Thu Jun 23 2011 Nalin Dahyabhai 1.9.1-5 +- pull a fix from SVN to try to avoid triggering a PTR lookup in getaddrinfo() + during krb5_sname_to_principal(), and to let getaddrinfo() decide whether or + not to ask for an IPv6 address based on the set of configured interfaces + (#717378, RT#6922) +- pull a fix from SVN to use AI_ADDRCONFIG more often (RT#6923) + +* Mon Jun 20 2011 Nalin Dahyabhai 1.9.1-4 +- apply upstream patch by way of Burt Holzman to fall back to a non-referral + method in cases where we might be derailed by a KDC that rejects the + canonicalize option (for example, those from the RHEL 2.1 or 3 era) (#715074) + +* Tue Jun 14 2011 Nalin Dahyabhai 1.9.1-3 +- pull a fix from SVN to get libgssrpc clients (e.g. kadmin) authenticating + using the old protocol over IPv4 again (RT#6920) + +* Tue Jun 14 2011 Nalin Dahyabhai +- incorporate a fix to teach the file labeling bits about when replay caches + are expunged (#576093) + +* Thu May 26 2011 Nalin Dahyabhai +- switch to the upstream patch for #707145 + +* Wed May 25 2011 Nalin Dahyabhai 1.9.1-2 +- klist: don't trip over referral entries when invoked with -s (#707145, + RT#6915) + +* Fri May 6 2011 Nalin Dahyabhai +- fixup URL in a comment +- when built with NSS, require 3.12.10 rather than 3.12.9 + +* Thu May 5 2011 Nalin Dahyabhai 1.9.1-1 +- update to 1.9.1: + - drop no-longer-needed patches for CVE-2010-4022, CVE-2011-0281, + CVE-2011-0282, CVE-2011-0283, CVE-2011-0284, CVE-2011-0285 + +* Wed Apr 13 2011 Nalin Dahyabhai 1.9-9 +- kadmind: add upstream patch to fix free() on an invalid pointer (#696343, + MITKRB5-SA-2011-004, CVE-2011-0285) + +* Mon Apr 4 2011 Nalin Dahyabhai +- don't discard the error code from an error message received in response + to a change-password request (#658871, RT#6893) + +* Fri Apr 1 2011 Nalin Dahyabhai +- override INSTALL_SETUID at build-time so that ksu is installed into + the buildroot with the right permissions (part of #225974) + +* Fri Mar 18 2011 Nalin Dahyabhai 1.9-8 +- backport change from SVN to fix a computed-value-not-used warning in + kpropd (#684065) + +* Tue Mar 15 2011 Nalin Dahyabhai 1.9-7 +- turn off NSS as the backend for libk5crypto for now to work around its + DES string2key not working (#679012) +- add revised upstream patch to fix double-free in KDC while returning + typed-data with errors (MITKRB5-SA-2011-003, CVE-2011-0284, #674325) + +* Thu Feb 17 2011 Nalin Dahyabhai +- throw in a not-applied-by-default patch to try to make pkinit debugging + into a run-time boolean option named "pkinit_debug" + +* Wed Feb 16 2011 Nalin Dahyabhai 1.9-6 +- turn on NSS as the backend for libk5crypto, adding nss-devel as a build + dependency when that switch is flipped + +* Wed Feb 9 2011 Nalin Dahyabhai 1.9-5 +- krb5kdc init script: prototype some changes to do a quick spot-check + of the TGS and kadmind keys and warn if there aren't any non-weak keys + on file for them (to flush out parts of #651466) + +* Tue Feb 8 2011 Nalin Dahyabhai 1.9-4 +- add upstream patches to fix standalone kpropd exiting if the per-client + child process exits with an error (MITKRB5-SA-2011-001), a hang or crash + in the KDC when using the LDAP kdb backend, and an uninitialized pointer + use in the KDC (MITKRB5-SA-2011-002) (CVE-2010-4022, #664009, + CVE-2011-0281, #668719, CVE-2011-0282, #668726, CVE-2011-0283, #676126) + +* Mon Feb 07 2011 Fedora Release Engineering - 1.9-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Mon Feb 7 2011 Nalin Dahyabhai +- fix a compile error in the SELinux labeling patch when -DDEBUG is used (Sumit + Bose) + +* Tue Feb 1 2011 Nalin Dahyabhai +- properly advertise that the kpropd init script now supports force-reload + (Zbysek Mraz, #630587) + +* Wed Jan 26 2011 Nalin Dahyabhai 1.9-2 +- pkinit: when verifying signed data, use the CMS APIs for better + interoperability (#636985, RT#6851) + +* Wed Dec 22 2010 Nalin Dahyabhai 1.9-1 +- update to 1.9 final + +* Mon Dec 20 2010 Nalin Dahyabhai 1.9-0.beta3.1 +- fix link flags and permissions on shared libraries (ausil) + +* Thu Dec 16 2010 Nalin Dahyabhai 1.9-0.beta3.0 +- update to 1.9 beta 3 + +* Mon Dec 6 2010 Nalin Dahyabhai 1.9-0.beta2.0 +- update to 1.9 beta 2 + +* Tue Nov 9 2010 Nalin Dahyabhai 1.9-0.beta1.1 +- drop not-needed-since-1.8 build dependency on rsh (ssorce) + +* Fri Nov 5 2010 Nalin Dahyabhai 1.9-0.beta1.0 +- start moving to 1.9 with beta 1 + - drop patches for RT#5755, RT#6762, RT#6774, RT#6775 + - drop no-longer-needed backport patch for #539423 + - drop no-longer-needed patch for CVE-2010-1322 +- if WITH_NSS is set, built with --with-crypto-impl=nss (requires NSS 3.12.9) + +* Tue Oct 5 2010 Nalin Dahyabhai 1.8.3-8 +- incorporate upstream patch to fix uninitialized pointer crash in the KDC's + authorization data handling (CVE-2010-1322, #636335) + +* Mon Oct 4 2010 Nalin Dahyabhai 1.8.3-7 +- rebuild + +* Mon Oct 4 2010 Nalin Dahyabhai 1.8.3-6 +- pull down patches from trunk to implement k5login_authoritative and + k5login_directory settings for krb5.conf (#539423) + +* Wed Sep 29 2010 jkeating - 1.8.3-5 +- Rebuilt for gcc bug 634757 + +* Wed Sep 15 2010 Nalin Dahyabhai 1.8.3-4 +- fix reading of keyUsage extensions when attempting to select pkinit client + certs (part of #629022, RT#6775) +- fix selection of pkinit client certs when one or more don't include a + subjectAltName extension (part of #629022, RT#6774) + +* Fri Sep 3 2010 Nalin Dahyabhai 1.8.3-3 +- build with -fstack-protector-all instead of the default -fstack-protector, + so that we add checking to more functions (i.e., all of them) (#629950) +- also link binaries with -Wl,-z,relro,-z,now (part of #629950) + +* Tue Aug 24 2010 Nalin Dahyabhai 1.8.3-2 +- fix a logic bug in computing key expiration times (RT#6762, #627022) + +* Wed Aug 4 2010 Nalin Dahyabhai 1.8.3-1 +- update to 1.8.3 + - drop backports of fixes for gss context expiration and error table + registration/deregistration mismatch + - drop patch for upstream #6750 + +* Wed Jul 7 2010 Nalin Dahyabhai 1.8.2-3 +- tell krb5kdc and kadmind to create pid files, since they can +- add logrotate configuration files for krb5kdc and kadmind (#462658) +- fix parsing of the pidfile option in the KDC (upstream #6750) + +* Mon Jun 21 2010 Nalin Dahyabhai 1.8.2-2 +- libgssapi: pull in patch from svn to stop returning context-expired errors + when the ticket which was used to set up the context expires (#605366, + upstream #6739) + +* Mon Jun 21 2010 Nalin Dahyabhai +- pull up fix for upstream #6745, in which the gssapi library would add the + wrong error table but subsequently attempt to unload the right one + +* Thu Jun 10 2010 Nalin Dahyabhai 1.8.2-1 +- update to 1.8.2 + - drop patches for CVE-2010-1320, CVE-2010-1321 + +* Tue Jun 1 2010 Nalin Dahyabhai 1.8.1-7 +- rebuild + +* Thu May 27 2010 Nalin Dahyabhai +- ksu: move session management calls to before we drop privileges, like + su does (#596887), and don't skip the PAM account check for root or the + same user (more of #540769) + +* Mon May 24 2010 Nalin Dahyabhai 1.8.1-6 +- make krb5-server-ldap also depend on the same version-release of krb5-libs, + as the other subpackages do, if only to make it clearer than it is when we + just do it through krb5-server +- drop explicit linking with libtinfo for applications that use libss, now + that readline itself links with libtinfo (as of readline-5.2-3, since + fedora 7 or so) +- go back to building without strict aliasing (compiler warnings in gssrpc) + +* Tue May 18 2010 Nalin Dahyabhai 1.8.1-5 +- add patch to correct GSSAPI library null pointer dereference which could be + triggered by malformed client requests (CVE-2010-1321, #582466) + +* Tue May 4 2010 Nalin Dahyabhai 1.8.1-4 +- fix output of kprop's init script's "status" and "reload" commands (#588222) + +* Tue Apr 20 2010 Nalin Dahyabhai 1.8.1-3 +- incorporate patch to fix double-free in the KDC (CVE-2010-1320, #581922) + +* Wed Apr 14 2010 Nalin Dahyabhai 1.8.1-2 +- fix a typo in kerberos.ldif + +* Fri Apr 9 2010 Nalin Dahyabhai 1.8.1-1 +- update to 1.8.1 + - no longer need patches for #555875, #561174, #563431, RT#6661, CVE-2010-0628 +- replace buildrequires on tetex-latex with one on texlive-latex, which is + the package that provides it now + +* Thu Apr 8 2010 Nalin Dahyabhai +- kdc.conf: no more need to suggest a v4 mode, or listening on the v4 port + +* Thu Apr 8 2010 Nalin Dahyabhai +- drop patch to suppress key expiration warnings sent from the KDC in + the last-req field, as the KDC is expected to just be configured to either + send them or not as a particular key approaches expiration (#556495) + +* Tue Mar 23 2010 Nalin Dahyabhai - 1.8-5 +- add upstream fix for denial-of-service in SPNEGO (CVE-2010-0628, #576325) +- kdc.conf: no more need to suggest keeping keys with v4-compatible salting + +* Fri Mar 19 2010 Nalin Dahyabhai - 1.8-4 +- remove the krb5-appl bits (the -workstation-clients and -workstation-servers + subpackages) now that krb5-appl is its own package +- replace our patch for #563431 (kpasswd doesn't fall back to guessing your + principal name using your user name if you don't have a ccache) with the + one upstream uses + +* Fri Mar 12 2010 Nalin Dahyabhai - 1.8-3 +- add documentation for the ticket_lifetime option (#561174) + +* Mon Mar 8 2010 Nalin Dahyabhai - 1.8-2 +- pull up patch to get the client libraries to correctly perform password + changes over IPv6 (Sumit Bose, RT#6661) + +* Fri Mar 5 2010 Nalin Dahyabhai - 1.8-1 +- update to 1.8 + - temporarily bundling the krb5-appl package (split upstream as of 1.8) + until its package review is complete + - profile.d scriptlets are now only needed by -workstation-clients + - adjust paths in init scripts + - drop upstreamed fix for KDC denial of service (CVE-2010-0283) + - drop patch to check the user's password correctly using crypt(), which + isn't a code path we hit when we're using PAM + +* Wed Mar 3 2010 Nalin Dahyabhai - 1.7.1-6 +- fix a null pointer dereference and crash introduced in our PAM patch that + would happen if ftpd was given the name of a user who wasn't known to the + local system, limited to being triggerable by gssapi-authenticated clients by + the default xinetd config (Olivier Fourdan, #569472) + +* Tue Mar 2 2010 Nalin Dahyabhai - 1.7.1-5 +- fix a regression (not labeling a kdb database lock file correctly, #569902) + +* Thu Feb 25 2010 Nalin Dahyabhai - 1.7.1-4 +- move the package changelog to the end to match the usual style (jdennis) +- scrub out references to $RPM_SOURCE_DIR (jdennis) +- include a symlink to the readme with the name LICENSE so that people can + find it more easily (jdennis) + +* Wed Feb 17 2010 Nalin Dahyabhai - 1.7.1-3 +- pull up the change to make kpasswd's behavior better match the docs + when there's no ccache (#563431) + +* Tue Feb 16 2010 Nalin Dahyabhai - 1.7.1-2 +- apply patch from upstream to fix KDC denial of service (CVE-2010-0283, + #566002) + +* Wed Feb 3 2010 Nalin Dahyabhai - 1.7.1-1 +- update to 1.7.1 + - don't trip AD lockout on wrong password (#542687, #554351) + - incorporates fixes for CVE-2009-4212 and CVE-2009-3295 + - fixes gss_krb5_copy_ccache() when SPNEGO is used +- move sim_client/sim_server, gss-client/gss-server, uuclient/uuserver to + the devel subpackage, better lining up with the expected krb5/krb5-appl + split in 1.8 +- drop kvno,kadmin,k5srvutil,ktutil from -workstation-servers, as it already + depends on -workstation which also includes them + +* Mon Jan 25 2010 Nalin Dahyabhai - 1.7-23 +- tighten up default permissions on kdc.conf and kadm5.acl (#558343) + +* Fri Jan 22 2010 Nalin Dahyabhai - 1.7-22 +- use portreserve correctly -- portrelease takes the basename of the file + whose entries should be released, so we need three files, not one + +* Mon Jan 18 2010 Nalin Dahyabhai - 1.7-21 +- suppress warnings of impending password expiration if expiration is more than + seven days away when the KDC reports it via the last-req field, just as we + already do when it reports expiration via the key-expiration field (#556495) +- link with libtinfo rather than libncurses, when we can, in future RHEL + +* Fri Jan 15 2010 Nalin Dahyabhai - 1.7-20 +- krb5_get_init_creds_password: check opte->flags instead of options->flags + when checking whether or not we get to use the prompter callback (#555875) + +* Thu Jan 14 2010 Nalin Dahyabhai - 1.7-19 +- use portreserve to make sure the KDC can always bind to the kerberos-iv + port, kpropd can always bind to the krb5_prop port, and that kadmind can + always bind to the kerberos-adm port (#555279) +- correct inadvertent use of macros in the changelog (rpmlint) + +* Tue Jan 12 2010 Nalin Dahyabhai - 1.7-18 +- add upstream patch for integer underflow during AES and RC4 decryption + (CVE-2009-4212), via Tom Yu (#545015) + +* Wed Jan 6 2010 Nalin Dahyabhai - 1.7-17 +- put the conditional back for the -devel subpackage +- back down to the earlier version of the patch for #551764; the backported + alternate version was incomplete + +* Tue Jan 5 2010 Nalin Dahyabhai - 1.7-16 +- use %%global instead of %%define +- pull up proposed patch for creating previously-not-there lock files for + kdb databases when 'kdb5_util' is called to 'load' (#551764) + +* Mon Jan 4 2010 Dennis Gregorovic +- fix conditional for future RHEL + +* Mon Jan 4 2010 Nalin Dahyabhai - 1.7-15 +- add upstream patch for KDC crash during referral processing (CVE-2009-3295), + via Tom Yu (#545002) + +* Mon Dec 21 2009 Nalin Dahyabhai - 1.7-14 +- refresh patch for #542868 from trunk + +* Thu Dec 10 2009 Nalin Dahyabhai +- move man pages that live in the -libs subpackage into the regular + %%{_mandir} tree where they'll still be found if that package is the + only one installed (#529319) + +* Wed Dec 9 2009 Nalin Dahyabhai - 1.7-13 +- and put it back in + +* Tue Dec 8 2009 Nalin Dahyabhai +- back that last change out + +* Tue Dec 8 2009 Nalin Dahyabhai - 1.7-12 +- try to make gss_krb5_copy_ccache() work correctly for spnego (#542868) + +* Fri Dec 4 2009 Nalin Dahyabhai +- make krb5-config suppress CFLAGS output when called with --libs (#544391) + +* Thu Dec 3 2009 Nalin Dahyabhai - 1.7-11 +- ksu: move account management checks to before we drop privileges, like + su does (#540769) +- selinux: set the user part of file creation contexts to match the current + context instead of what we looked up +- configure with --enable-dns-for-realm instead of --enable-dns, which isn't + recognized any more + +* Fri Nov 20 2009 Nalin Dahyabhai - 1.7-10 +- move /etc/pam.d/ksu from krb5-workstation-servers to krb5-workstation, + where it's actually needed (#538703) + +* Fri Oct 23 2009 Nalin Dahyabhai - 1.7-9 +- add some conditional logic to simplify building on older Fedora releases + +* Tue Oct 13 2009 Nalin Dahyabhai +- don't forget the README + +* Mon Sep 14 2009 Nalin Dahyabhai - 1.7-8 +- specify the location of the subsystem lock when using the status() function + in the kadmind and kpropd init scripts, so that we get the right error when + we're dead but have a lock file - requires initscripts 8.99 (#521772) + +* Tue Sep 8 2009 Nalin Dahyabhai +- if the init script fails to start krb5kdc/kadmind/kpropd because it's already + running (according to status()), return 0 (part of #521772) + +* Mon Aug 24 2009 Nalin Dahyabhai - 1.7-7 +- work around a compile problem with new openssl + +* Fri Aug 21 2009 Tomas Mraz - 1.7-6 +- rebuilt with new openssl + +* Fri Jul 24 2009 Fedora Release Engineering - 1.7-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild + +* Tue Jul 7 2009 Nalin Dahyabhai 1.7-5 +- rebuild to pick up the current forms of various patches + +* Mon Jul 6 2009 Nalin Dahyabhai +- simplify the man pages patch by only preprocessing the files we care about + and moving shared configure.in logic into a shared function +- catch the case of ftpd printing file sizes using %%i, when they might be + bigger than an int now + +* Tue Jun 30 2009 Nalin Dahyabhai 1.7-4 +- try to merge and clean up all the large file support for ftp and rcp + - ftpd no longer prints a negative length when sending a large file + from a 32-bit host + +* Tue Jun 30 2009 Nalin Dahyabhai +- pam_rhosts_auth.so's been gone, use pam_rhosts.so instead + +* Mon Jun 29 2009 Nalin Dahyabhai 1.7-3 +- switch buildrequires: and requires: on e2fsprogs-devel into + buildrequires: and requires: on libss-devel, libcom_err-devel, per + sandeen on fedora-devel-list + +* Fri Jun 26 2009 Nalin Dahyabhai +- fix a type mismatch in krb5_copy_error_message() +- ftp: fix some odd use of strlen() +- selinux labeling: use selabel_open() family of functions rather than + matchpathcon(), bail on it if attempting to get the mutex lock fails + +* Tue Jun 16 2009 Nalin Dahyabhai +- compile with %%{?_smp_mflags} (Steve Grubb) +- drop the bit where we munge part of the error table header, as it's not + needed any more + +* Fri Jun 5 2009 Nalin Dahyabhai 1.7-2 +- add and own %%{_libdir}/krb5/plugins/authdata + +* Thu Jun 4 2009 Nalin Dahyabhai 1.7-1 +- update to 1.7 + - no need to work around build issues with ASN1BUF_OMIT_INLINE_FUNCS + - configure recognizes --enable/--disable-pkinit now + - configure can take --disable-rpath now + - no more libdes425, krb524d, krb425.info + - kadmin/k5srvutil/ktutil are user commands now + - new kproplog + - FAST encrypted-challenge plugin is new +- drop static build logic +- drop pam_krb5-specific configuration from the default krb5.conf +- drop only-use-v5 flags being passed to various things started by xinetd +- put %%{krb5prefix}/sbin in everyone's path, too (#504525) + +* Tue May 19 2009 Nalin Dahyabhai 1.6.3-106 +- add an auth stack to ksu's PAM configuration so that pam_setcred() calls + won't just fail + +* Mon May 11 2009 Nalin Dahyabhai 1.6.3-105 +- make PAM support for ksu also set PAM_RUSER + +* Thu Apr 23 2009 Nalin Dahyabhai 1.6.3-104 +- extend PAM support to ksu: perform account and session management for the + target user +- pull up and merge James Leddy's changes to also set PAM_RHOST in PAM-aware + network-facing services + +* Tue Apr 21 2009 Nalin Dahyabhai 1.6.3-103 +- fix a typo in a ksu error message (Marek Mahut) +- "rev" works the way the test suite expects now, so don't disable tests + that use it + +* Mon Apr 20 2009 Nalin Dahyabhai 1.6.3-102 +- add LSB-style init script info + +* Fri Apr 17 2009 Nalin Dahyabhai +- explicitly run the pdf generation script using sh (part of #225974) + +* Tue Apr 7 2009 Nalin Dahyabhai 1.6.3-101 +- add patches for read overflow and null pointer dereference in the + implementation of the SPNEGO mechanism (CVE-2009-0844, CVE-2009-0845) +- add patch for attempt to free uninitialized pointer in libkrb5 + (CVE-2009-0846) +- add patch to fix length validation bug in libkrb5 (CVE-2009-0847) +- put the krb5-user .info file into just -workstation and not also + -workstation-clients + +* Mon Apr 6 2009 Nalin Dahyabhai 1.6.3-100 +- turn off krb4 support (it won't be part of the 1.7 release, but do it now) +- use triggeruns to properly shut down and disable krb524d when -server and + -workstation-servers gets upgraded, because it's gone now +- move the libraries to /%%{_lib}, but leave --libdir alone so that plugins + get installed and are searched for in the same locations (#473333) +- clean up buildprereq/prereqs, explicit mktemp requires, and add the + ldconfig for the -server-ldap subpackage (part of #225974) +- escape possible macros in the changelog (part of #225974) +- fixup summary texts (part of #225974) +- take the execute bit off of the protocol docs (part of #225974) +- unflag init scripts as configuration files (part of #225974) +- make the kpropd init script treat 'reload' as 'restart' (part of #225974) + +* Tue Mar 17 2009 Nalin Dahyabhai 1.6.3-19 +- libgssapi_krb5: backport fix for some errors which can occur when + we fail to set up the server half of a context (CVE-2009-0845) + +* Wed Feb 25 2009 Fedora Release Engineering - 1.6.3-18 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild + +* Fri Jan 16 2009 Nalin Dahyabhai 1.6.3-17 +- rebuild + +* Thu Sep 4 2008 Nalin Dahyabhai +- if we successfully change the user's password during an attempt to get + initial credentials, but then fail to get initial creds from a non-master + using the new password, retry against the master (#432334) + +* Tue Aug 5 2008 Tom "spot" Callaway 1.6.3-16 +- fix license tag + +* Wed Jul 16 2008 Nalin Dahyabhai +- clear fuzz out of patches, dropping a man page patch which is no longer + necessary +- quote %%{__cc} where needed because it includes whitespace now +- define ASN1BUF_OMIT_INLINE_FUNCS at compile-time (for now) to keep building + +* Fri Jul 11 2008 Nalin Dahyabhai 1.6.3-15 +- build with -fno-strict-aliasing, which is needed because the library + triggers these warnings +- don't forget to label principal database lock files +- fix the labeling patch so that it doesn't break bootstrapping + +* Sat Jun 14 2008 Tom "spot" Callaway 1.6.3-14 +- generate src/include/krb5/krb5.h before building +- fix conditional for sparcv9 + +* Wed Apr 16 2008 Nalin Dahyabhai 1.6.3-13 +- ftp: use the correct local filename during mget when the 'case' option is + enabled (#442713) + +* Fri Apr 4 2008 Nalin Dahyabhai 1.6.3-12 +- stop exporting kadmin keys to a keytab file when kadmind starts -- the + daemon's been able to use the database directly for a long long time now +- belatedly add aes128,aes256 to the default set of supported key types + +* Tue Apr 1 2008 Nalin Dahyabhai 1.6.3-11 +- libgssapi_krb5: properly export the acceptor subkey when creating a lucid + context (Kevin Coffman, via the nfs4 mailing list) + +* Tue Mar 18 2008 Nalin Dahyabhai 1.6.3-10 +- add fixes from MITKRB5-SA-2008-001 for use of null or dangling pointer + when v4 compatibility is enabled on the KDC (CVE-2008-0062, CVE-2008-0063, + #432620, #432621) +- add fixes from MITKRB5-SA-2008-002 for array out-of-bounds accesses when + high-numbered descriptors are used (CVE-2008-0947, #433596) +- add backport bug fix for an attempt to free non-heap memory in + libgssapi_krb5 (CVE-2007-5901, #415321) +- add backport bug fix for a double-free in out-of-memory situations in + libgssapi_krb5 (CVE-2007-5971, #415351) + +* Tue Mar 18 2008 Nalin Dahyabhai 1.6.3-9 +- rework file labeling patch to not depend on fragile preprocessor trickery, + in another attempt at fixing #428355 and friends + +* Tue Feb 26 2008 Nalin Dahyabhai 1.6.3-8 +- ftp: add patch to fix "runique on" case when globbing fixes applied +- stop adding a redundant but harmless call to initialize the gssapi internals + +* Mon Feb 25 2008 Nalin Dahyabhai +- add patch to suppress double-processing of /etc/krb5.conf when we build + with --sysconfdir=/etc, thereby suppressing double-logging (#231147) + +* Mon Feb 25 2008 Nalin Dahyabhai +- remove a patch, to fix problems with interfaces which are "up" but which + have no address assigned, which conflicted with a different fix for the same + problem in 1.5 (#200979) + +* Mon Feb 25 2008 Nalin Dahyabhai +- ftp: don't lose track of a descriptor on passive get when the server fails to + open a file + +* Mon Feb 25 2008 Nalin Dahyabhai +- in login, allow PAM to interact with the user when they've been strongly + authenticated +- in login, signal PAM when we're changing an expired password that it's an + expired password, so that when cracklib flags a password as being weak it's + treated as an error even if we're running as root + +* Mon Feb 18 2008 Nalin Dahyabhai 1.6.3-7 +- drop netdb patch +- kdb_ldap: add patch to treat 'nsAccountLock: true' as an indication that + the DISALLOW_ALL_TIX flag is set on an entry, for better interop with Fedora, + Netscape, Red Hat Directory Server (Simo Sorce) + +* Wed Feb 13 2008 Nalin Dahyabhai 1.6.3-6 +- patch to avoid depending on to define NI_MAXHOST and NI_MAXSERV + +* Tue Feb 12 2008 Nalin Dahyabhai 1.6.3-5 +- enable patch for key-expiration reporting +- enable patch to make kpasswd fall back to TCP if UDP fails (#251206) +- enable patch to make kpasswd use the right sequence number on retransmit +- enable patch to allow mech-specific creds delegated under spnego to be found + when searching for creds + +* Wed Jan 2 2008 Nalin Dahyabhai 1.6.3-4 +- some init script cleanups + - drop unquoted check and silent exit for "$NETWORKING" (#426852, #242502) + - krb524: don't barf on missing database if it looks like we're using kldap, + same as for kadmin + - return non-zero status for missing files which cause startup to + fail (#242502) + +* Tue Dec 18 2007 Nalin Dahyabhai 1.6.3-3 +- allocate space for the nul-terminator in the local pathname when looking up + a file context, and properly free a previous context (Jose Plans, #426085) + +* Wed Dec 5 2007 Nalin Dahyabhai 1.6.3-2 +- rebuild + +* Tue Oct 23 2007 Nalin Dahyabhai 1.6.3-1 +- update to 1.6.3, dropping now-integrated patches for CVE-2007-3999 + and CVE-2007-4000 (the new pkinit module is built conditionally and goes + into the -pkinit-openssl package, at least for now, to make a buildreq + loop with openssl avoidable) + +* Wed Oct 17 2007 Nalin Dahyabhai 1.6.2-10 +- make proper use of pam_loginuid and pam_selinux in rshd and ftpd + +* Fri Oct 12 2007 Nalin Dahyabhai +- make krb5.conf %%verify(not md5 size mtime) in addition to + %%config(noreplace), like /etc/nsswitch.conf (#329811) + +* Mon Oct 1 2007 Nalin Dahyabhai 1.6.2-9 +- apply the fix for CVE-2007-4000 instead of the experimental patch for + setting ok-as-delegate flags + +* Tue Sep 11 2007 Nalin Dahyabhai 1.6.2-8 +- move the db2 kdb plugin from -server to -libs, because a multilib libkdb + might need it + +* Tue Sep 11 2007 Nalin Dahyabhai 1.6.2-7 +- also perform PAM session and credential management when ftpd accepts a + client using strong authentication, missed earlier +- also label kadmind log files and files created by the db2 plugin + +* Thu Sep 6 2007 Nalin Dahyabhai 1.6.2-6 +- incorporate updated fix for CVE-2007-3999 (CVE-2007-4743) +- fix incorrect call to "test" in the kadmin init script (#252322,#287291) + +* Tue Sep 4 2007 Nalin Dahyabhai 1.6.2-5 +- incorporate fixes for MITKRB5-SA-2007-006 (CVE-2007-3999, CVE-2007-4000) + +* Sat Aug 25 2007 Nalin Dahyabhai 1.6.2-4 +- cover more cases in labeling files on creation +- add missing gawk build dependency + +* Thu Aug 23 2007 Nalin Dahyabhai 1.6.2-3 +- rebuild + +* Thu Jul 26 2007 Nalin Dahyabhai 1.6.2-2 +- kdc.conf: default to listening for TCP clients, too (#248415) + +* Thu Jul 19 2007 Nalin Dahyabhai 1.6.2-1 +- update to 1.6.2 +- add "buildrequires: texinfo-tex" to get texi2pdf + +* Wed Jun 27 2007 Nalin Dahyabhai 1.6.1-8 +- incorporate fixes for MITKRB5-SA-2007-004 (CVE-2007-2442,CVE-2007-2443) + and MITKRB5-SA-2007-005 (CVE-2007-2798) + +* Mon Jun 25 2007 Nalin Dahyabhai 1.6.1-7 +- reintroduce missing %%postun for the non-split_workstation case + +* Mon Jun 25 2007 Nalin Dahyabhai 1.6.1-6 +- rebuild + +* Mon Jun 25 2007 Nalin Dahyabhai 1.6.1-5.1 +- rebuild + +* Sun Jun 24 2007 Nalin Dahyabhai 1.6.1-5 +- add missing pam-devel build requirement, force selinux-or-fail build + +* Sun Jun 24 2007 Nalin Dahyabhai 1.6.1-4 +- rebuild + +* Sun Jun 24 2007 Nalin Dahyabhai 1.6.1-3 +- label all files at creation-time according to the SELinux policy (#228157) + +* Fri Jun 22 2007 Nalin Dahyabhai +- perform PAM account / session management in krshd (#182195,#195922) +- perform PAM authentication and account / session management in ftpd +- perform PAM authentication, account / session management, and password- + changing in login.krb5 (#182195,#195922) + +* Fri Jun 22 2007 Nalin Dahyabhai +- preprocess kerberos.ldif into a format FDS will like better, and include + that as a doc file as well + +* Fri Jun 22 2007 Nalin Dahyabhai +- switch man pages to being generated with the right paths in them +- drop old, incomplete SELinux patch +- add patch from Greg Hudson to make srvtab routines report missing-file errors + at same point that keytab routines do (#241805) + +* Thu May 24 2007 Nalin Dahyabhai 1.6.1-2 +- pull patch from svn to undo unintentional chattiness in ftp +- pull patch from svn to handle NULL krb5_get_init_creds_opt structures + better in a couple of places where they're expected + +* Wed May 23 2007 Nalin Dahyabhai 1.6.1-1 +- update to 1.6.1 + - drop no-longer-needed patches for CVE-2007-0956,CVE-2007-0957,CVE-2007-1216 + - drop patch for sendto bug in 1.6, fixed in 1.6.1 + +* Fri May 18 2007 Nalin Dahyabhai +- kadmind.init: don't fail outright if the default principal database + isn't there if it looks like we might be using the kldap plugin +- kadmind.init: attempt to extract the key for the host-specific kadmin + service when we try to create the keytab + +* Wed May 16 2007 Nalin Dahyabhai 1.6-6 +- omit dependent libraries from the krb5-config --libs output, as using + shared libraries (no more static libraries) makes them unnecessary and + they're not part of the libkrb5 interface (patch by Rex Dieter, #240220) + (strips out libkeyutils, libresolv, libdl) + +* Fri May 4 2007 Nalin Dahyabhai 1.6-5 +- pull in keyutils as a build requirement to get the "KEYRING:" ccache type, + because we've merged + +* Fri May 4 2007 Nalin Dahyabhai 1.6-4 +- fix an uninitialized length value which could cause a crash when parsing + key data coming from a directory server +- correct a typo in the krb5.conf man page ("ldap_server"->"ldap_servers") + +* Fri Apr 13 2007 Nalin Dahyabhai +- move the default acl_file, dict_file, and admin_keytab settings to + the part of the default/example kdc.conf where they'll actually have + an effect (#236417) + +* Thu Apr 5 2007 Nalin Dahyabhai 1.5-24 +- merge security fixes from RHSA-2007:0095 + +* Tue Apr 3 2007 Nalin Dahyabhai 1.6-3 +- add patch to correct unauthorized access via krb5-aware telnet + daemon (#229782, CVE-2007-0956) +- add patch to fix buffer overflow in krb5kdc and kadmind + (#231528, CVE-2007-0957) +- add patch to fix double-free in kadmind (#231537, CVE-2007-1216) + +* Thu Mar 22 2007 Nalin Dahyabhai +- back out buildrequires: keyutils-libs-devel for now + +* Thu Mar 22 2007 Nalin Dahyabhai 1.6-2 +- add buildrequires: on keyutils-libs-devel to enable use of keyring ccaches, + dragging keyutils-libs in as a dependency + +* Mon Mar 19 2007 Nalin Dahyabhai 1.5-23 +- fix bug ID in changelog + +* Thu Mar 15 2007 Nalin Dahyabhai 1.5-22 + +* Thu Mar 15 2007 Nalin Dahyabhai 1.5-21 +- add preliminary patch to fix buffer overflow in krb5kdc and kadmind + (#231528, CVE-2007-0957) +- add preliminary patch to fix double-free in kadmind (#231537, CVE-2007-1216) + +* Wed Feb 28 2007 Nalin Dahyabhai +- add patch to build semi-useful static libraries, but don't apply it unless + we need them + +* Tue Feb 27 2007 Nalin Dahyabhai - 1.5-20 +- temporarily back out %%post changes, fix for #143289 for security update +- add preliminary patch to correct unauthorized access via krb5-aware telnet + +* Mon Feb 19 2007 Nalin Dahyabhai +- make profile.d scriptlets mode 644 instead of 755 (part of #225974) + +* Tue Jan 30 2007 Nalin Dahyabhai 1.6-1 +- clean up quoting of command-line arguments passed to the krsh/krlogin + wrapper scripts + +* Mon Jan 22 2007 Nalin Dahyabhai +- initial update to 1.6, pre-package-reorg +- move workstation daemons to a new subpackage (#81836, #216356, #217301), and + make the new subpackage require xinetd (#211885) + +* Mon Jan 22 2007 Nalin Dahyabhai - 1.5-18 +- make use of install-info more failsafe (Ville Skyttä, #223704) +- preserve timestamps on shell scriptlets at %%install-time + +* Tue Jan 16 2007 Nalin Dahyabhai - 1.5-17 +- move to using pregenerated PDF docs to cure multilib conflicts (#222721) + +* Fri Jan 12 2007 Nalin Dahyabhai - 1.5-16 +- update backport of the preauth module interface (part of #194654) + +* Tue Jan 9 2007 Nalin Dahyabhai - 1.5-14 +- apply fixes from Tom Yu for MITKRB5-SA-2006-002 (CVE-2006-6143) (#218456) +- apply fixes from Tom Yu for MITKRB5-SA-2006-003 (CVE-2006-6144) (#218456) + +* Wed Dec 20 2006 Nalin Dahyabhai - 1.5-12 +- update backport of the preauth module interface + +* Mon Oct 30 2006 Nalin Dahyabhai +- update backport of the preauth module interface +- add proposed patches 4566, 4567 +- add proposed edata reporting interface for KDC +- add temporary placeholder for module global context fixes + +* Mon Oct 23 2006 Nalin Dahyabhai - 1.5-11 +- don't bail from the KDC init script if there's no database, it may be in + a different location than the default (fenlason) +- remove the [kdc] section from the default krb5.conf -- doesn't seem to have + been applicable for a while + +* Wed Oct 18 2006 Nalin Dahyabhai - 1.5-10 +- rename krb5.sh and krb5.csh so that they don't overlap (#210623) +- way-late application of added error info in kadmind.init (#65853) + +* Wed Oct 18 2006 Nalin Dahyabhai - 1.5-9.pal_18695 +- add backport of in-development preauth module interface (#208643) + +* Mon Oct 9 2006 Nalin Dahyabhai - 1.5-9 +- provide docs in PDF format instead of as tex source (Enrico Scholz, #209943) + +* Wed Oct 4 2006 Nalin Dahyabhai - 1.5-8 +- add missing shebang headers to krsh and krlogin wrapper scripts (#209238) + +* Wed Sep 6 2006 Nalin Dahyabhai - 1.5-7 +- set SS_LIB at configure-time so that libss-using apps get working readline + support (#197044) + +* Fri Aug 18 2006 Nalin Dahyabhai - 1.5-6 +- switch to the updated patch for MITKRB-SA-2006-001 + +* Tue Aug 8 2006 Nalin Dahyabhai - 1.5-5 +- apply patch to address MITKRB-SA-2006-001 (CVE-2006-3084) + +* Mon Aug 7 2006 Nalin Dahyabhai - 1.5-4 +- ensure that the gssapi library's been initialized before walking the + internal mechanism list in gss_release_oid(), needed if called from + gss_release_name() right after a gss_import_name() (#198092) + +* Tue Jul 25 2006 Nalin Dahyabhai - 1.5-3 +- rebuild + +* Tue Jul 25 2006 Nalin Dahyabhai - 1.5-2 +- pull up latest revision of patch to reduce lockups in rsh/rshd + +* Mon Jul 17 2006 Nalin Dahyabhai - 1.5-1.2 +- rebuild + +* Wed Jul 12 2006 Jesse Keating - 1.5-1.1 +- rebuild + +* Thu Jul 6 2006 Nalin Dahyabhai 1.5-1 +- build + +* Wed Jul 5 2006 Nalin Dahyabhai 1.5-0 +- update to 1.5 + +* Fri Jun 23 2006 Nalin Dahyabhai 1.4.3-9 +- mark profile.d config files noreplace (Laurent Rineau, #196447) + +* Thu Jun 8 2006 Nalin Dahyabhai 1.4.3-8 +- add buildprereq for autoconf + +* Mon May 22 2006 Nalin Dahyabhai 1.4.3-7 +- further munge krb5-config so that 'libdir=/usr/lib' is given even on 64-bit + architectures, to avoid multilib conflicts; other changes will conspire to + strip out the -L flag which uses this, so it should be harmless (#192692) + +* Fri Apr 28 2006 Nalin Dahyabhai 1.4.3-6 +- adjust the patch which removes the use of rpath to also produce a + krb5-config which is okay in multilib environments (#190118) +- make the name-of-the-tempfile comment which compile_et adds to error code + headers always list the same file to avoid conflicts on multilib installations +- strip SIZEOF_LONG out of krb5.h so that it doesn't conflict on multilib boxes +- strip GSS_SIZEOF_LONG out of gssapi.h so that it doesn't conflict on mulitlib + boxes + +* Fri Apr 14 2006 Stepan Kasal 1.4.3-5 +- Fix formatting typo in kinit.1 (krb5-kinit-man-typo.patch) + +* Fri Feb 10 2006 Jesse Keating 1.4.3-4.1 +- bump again for double-long bug on ppc(64) + +* Mon Feb 6 2006 Nalin Dahyabhai 1.4.3-4 +- give a little bit more information to the user when kinit gets the catch-all + I/O error (#180175) + +* Thu Jan 19 2006 Nalin Dahyabhai 1.4.3-3 +- rebuild properly when pthread_mutexattr_setrobust_np() is defined but not + declared, such as with recent glibc when _GNU_SOURCE isn't being used + +* Thu Jan 19 2006 Matthias Clasen 1.4.3-2 +- Use full paths in krb5.sh to avoid path lookups + +* Fri Dec 09 2005 Jesse Keating +- rebuilt + +* Thu Dec 1 2005 Nalin Dahyabhai +- login: don't truncate passwords before passing them into crypt(), in + case they're significant (#149476) + +* Thu Nov 17 2005 Nalin Dahyabhai 1.4.3-1 +- update to 1.4.3 +- make ksu setuid again (#137934, others) + +* Tue Sep 13 2005 Nalin Dahyabhai 1.4.2-4 +- mark %%{krb5prefix}/man so that files which are packaged within it are + flagged as %%doc (#168163) + +* Tue Sep 6 2005 Nalin Dahyabhai 1.4.2-3 +- add an xinetd configuration file for encryption-only telnetd, parallelling + the kshell/ekshell pair (#167535) + +* Wed Aug 31 2005 Nalin Dahyabhai 1.4.2-2 +- change the default configured encryption type for KDC databases to the + compiled-in default of des3-hmac-sha1 (#57847) + +* Thu Aug 11 2005 Nalin Dahyabhai 1.4.2-1 +- update to 1.4.2, incorporating the fixes for MIT-KRB5-SA-2005-002 and + MIT-KRB5-SA-2005-003 + +* Wed Jun 29 2005 Nalin Dahyabhai 1.4.1-6 +- rebuild + +* Wed Jun 29 2005 Nalin Dahyabhai 1.4.1-5 +- fix telnet client environment variable disclosure the same way NetKit's + telnet client did (CAN-2005-0488) (#159305) +- keep apps which call krb5_principal_compare() or krb5_realm_compare() with + malformed or NULL principal structures from crashing outright (Thomas Biege) + (#161475) + +* Tue Jun 28 2005 Nalin Dahyabhai +- apply fixes from draft of MIT-KRB5-SA-2005-002 (CAN-2005-1174,CAN-2005-1175) + (#157104) +- apply fixes from draft of MIT-KRB5-SA-2005-003 (CAN-2005-1689) (#159755) + +* Fri Jun 24 2005 Nalin Dahyabhai 1.4.1-4 +- fix double-close in keytab handling +- add port of fixes for CAN-2004-0175 to krb5-aware rcp (#151612) + +* Fri May 13 2005 Nalin Dahyabhai 1.4.1-3 +- prevent spurious EBADF in krshd when stdin is closed by the client while + the command is running (#151111) + +* Fri May 13 2005 Martin Stransky 1.4.1-2 +- add deadlock patch, removed old patch + +* Fri May 6 2005 Nalin Dahyabhai 1.4.1-1 +- update to 1.4.1, incorporating fixes for CAN-2005-0468 and CAN-2005-0469 +- when starting the KDC or kadmind, if KRB5REALM is set via the /etc/sysconfig + file for the service, pass it as an argument for the -r flag + +* Wed Mar 23 2005 Nalin Dahyabhai 1.4-3 +- drop krshd patch for now + +* Thu Mar 17 2005 Nalin Dahyabhai +- add draft fix from Tom Yu for slc_add_reply() buffer overflow (CAN-2005-0469) +- add draft fix from Tom Yu for env_opt_add() buffer overflow (CAN-2005-0468) + +* Wed Mar 16 2005 Nalin Dahyabhai 1.4-2 +- don't include into the telnet client when we're not using curses + +* Thu Feb 24 2005 Nalin Dahyabhai 1.4-1 +- update to 1.4 + - v1.4 kadmin client requires a v1.4 kadmind on the server, or use the "-O" + flag to specify that it should communicate with the server using the older + protocol + - new libkrb5support library + - v5passwdd and kadmind4 are gone + - versioned symbols +- pick up $KRB5KDC_ARGS from /etc/sysconfig/krb5kdc, if it exists, and pass + it on to krb5kdc +- pick up $KADMIND_ARGS from /etc/sysconfig/kadmin, if it exists, and pass + it on to kadmind +- pick up $KRB524D_ARGS from /etc/sysconfig/krb524, if it exists, and pass + it on to krb524d *instead of* "-m" +- set "forwardable" in [libdefaults] in the default krb5.conf to match the + default setting which we supply for pam_krb5 +- set a default of 24h for "ticket_lifetime" in [libdefaults], reflecting the + compiled-in default + +* Mon Dec 20 2004 Nalin Dahyabhai 1.3.6-3 +- rebuild + +* Mon Dec 20 2004 Nalin Dahyabhai 1.3.6-2 +- rebuild + +* Mon Dec 20 2004 Nalin Dahyabhai 1.3.6-1 +- update to 1.3.6, which includes the previous fix + +* Mon Dec 20 2004 Nalin Dahyabhai 1.3.5-8 +- apply fix from Tom Yu for MITKRB5-SA-2004-004 (CAN-2004-1189) + +* Fri Dec 17 2004 Martin Stransky 1.3.5-7 +- fix deadlock during file transfer via rsync/krsh +- thanks goes to James Antill for hint + +* Fri Nov 26 2004 Nalin Dahyabhai 1.3.5-6 +- rebuild + +* Mon Nov 22 2004 Nalin Dahyabhai 1.3.5-3 +- fix predictable-tempfile-name bug in krb5-send-pr (CAN-2004-0971, #140036) + +* Tue Nov 16 2004 Nalin Dahyabhai +- silence compiler warning in kprop by using an in-memory ccache with a fixed + name instead of an on-disk ccache with a name generated by tmpnam() + +* Tue Nov 16 2004 Nalin Dahyabhai 1.3.5-2 +- fix globbing patch port mode (#139075) + +* Mon Nov 1 2004 Nalin Dahyabhai 1.3.5-1 +- fix segfault in telnet due to incorrect checking of gethostbyname_r result + codes (#129059) + +* Fri Oct 15 2004 Nalin Dahyabhai +- remove rc4-hmac:norealm and rc4-hmac:onlyrealm from the default list of + supported keytypes in kdc.conf -- they produce exactly the same keys as + rc4-hmac:normal because rc4 string-to-key ignores salts +- nuke kdcrotate -- there are better ways to balance the load on KDCs, and + the SELinux policy for it would have been scary-looking +- update to 1.3.5, mainly to include MITKRB5SA 2004-002 and 2004-003 + +* Tue Aug 31 2004 Nalin Dahyabhai 1.3.4-7 +- rebuild + +* Tue Aug 24 2004 Nalin Dahyabhai 1.3.4-6 +- rebuild + +* Tue Aug 24 2004 Nalin Dahyabhai 1.3.4-5 +- incorporate revised fixes from Tom Yu for CAN-2004-0642, CAN-2004-0644, + CAN-2004-0772 + +* Mon Aug 23 2004 Nalin Dahyabhai 1.3.4-4 +- rebuild + +* Mon Aug 23 2004 Nalin Dahyabhai 1.3.4-3 +- incorporate fixes from Tom Yu for CAN-2004-0642, CAN-2004-0772 + (MITKRB5-SA-2004-002, #130732) +- incorporate fixes from Tom Yu for CAN-2004-0644 (MITKRB5-SA-2004-003, #130732) + +* Tue Jul 27 2004 Nalin Dahyabhai 1.3.4-2 +- fix indexing error in server sorting patch (#127336) + +* Tue Jun 15 2004 Elliot Lee +- rebuilt + +* Mon Jun 14 2004 Nalin Dahyabhai 1.3.4-0.1 +- update to 1.3.4 final + +* Mon Jun 7 2004 Nalin Dahyabhai 1.3.4-0 +- update to 1.3.4 beta1 +- remove MITKRB5-SA-2004-001, included in 1.3.4 + +* Mon Jun 7 2004 Nalin Dahyabhai 1.3.3-8 +- rebuild + +* Fri Jun 4 2004 Nalin Dahyabhai 1.3.3-7 +- rebuild + +* Fri Jun 4 2004 Nalin Dahyabhai 1.3.3-6 +- apply updated patch from MITKRB5-SA-2004-001 (revision 2004-06-02) + +* Tue Jun 1 2004 Nalin Dahyabhai 1.3.3-5 +- rebuild + +* Tue Jun 1 2004 Nalin Dahyabhai 1.3.3-4 +- apply patch from MITKRB5-SA-2004-001 (#125001) + +* Wed May 12 2004 Thomas Woerner 1.3.3-3 +- removed rpath + +* Thu Apr 15 2004 Nalin Dahyabhai 1.3.3-2 +- re-enable large file support, fell out in 1.3-1 +- patch rcp to use long long and %%lld format specifiers when reporting file + sizes on large files + +* Tue Apr 13 2004 Nalin Dahyabhai 1.3.3-1 +- update to 1.3.3 + +* Wed Mar 10 2004 Nalin Dahyabhai 1.3.2-1 +- update to 1.3.2 + +* Mon Mar 8 2004 Nalin Dahyabhai 1.3.1-12 +- rebuild + +* Tue Mar 02 2004 Elliot Lee 1.3.1-11.1 +- rebuilt + +* Fri Feb 13 2004 Elliot Lee 1.3.1-11 +- rebuilt + +* Mon Feb 9 2004 Nalin Dahyabhai 1.3.1-10 +- catch krb4 send_to_kdc cases in kdc preference patch + +* Mon Feb 2 2004 Nalin Dahyabhai 1.3.1-9 +- remove patch to set TERM in klogind which, combined with the upstream fix in + 1.3.1, actually produces the bug now (#114762) + +* Mon Jan 19 2004 Nalin Dahyabhai 1.3.1-8 +- when iterating over lists of interfaces which are "up" from getifaddrs(), + skip over those which have no address (#113347) + +* Mon Jan 12 2004 Nalin Dahyabhai +- prefer the kdc which last replied to a request when sending requests to kdcs + +* Mon Nov 24 2003 Nalin Dahyabhai 1.3.1-7 +- fix combination of --with-netlib and --enable-dns (#82176) + +* Tue Nov 18 2003 Nalin Dahyabhai +- remove libdefault ticket_lifetime option from the default krb5.conf, it is + ignored by libkrb5 + +* Thu Sep 25 2003 Nalin Dahyabhai 1.3.1-6 +- fix bug in patch to make rlogind start login with a clean environment a la + netkit rlogin, spotted and fixed by Scott McClung + +* Tue Sep 23 2003 Nalin Dahyabhai 1.3.1-5 +- include profile.d scriptlets in krb5-devel so that krb5-config will be in + the path if krb5-workstation isn't installed, reported by Kir Kolyshkin + +* Mon Sep 8 2003 Nalin Dahyabhai +- add more etypes (arcfour) to the default enctype list in kdc.conf +- don't apply previous patch, refused upstream + +* Fri Sep 5 2003 Nalin Dahyabhai 1.3.1-4 +- fix 32/64-bit bug storing and retrieving the issue_date in v4 credentials + +* Wed Sep 3 2003 Dan Walsh 1.3.1-3 +- Don't check for write access on /etc/krb5.conf if SELinux + +* Tue Aug 26 2003 Nalin Dahyabhai 1.3.1-2 +- fixup some int/pointer varargs wackiness + +* Tue Aug 5 2003 Nalin Dahyabhai 1.3.1-1 +- rebuild + +* Mon Aug 4 2003 Nalin Dahyabhai 1.3.1-0 +- update to 1.3.1 + +* Thu Jul 24 2003 Nalin Dahyabhai 1.3-2 +- pull fix for non-compliant encoding of salt field in etype-info2 preauth + data from 1.3.1 beta 1, until 1.3.1 is released. + +* Mon Jul 21 2003 Nalin Dahyabhai 1.3-1 +- update to 1.3 + +* Mon Jul 7 2003 Nalin Dahyabhai 1.2.8-4 +- correctly use stdargs + +* Wed Jun 18 2003 Nalin Dahyabhai 1.3-0.beta.4 +- test update to 1.3 beta 4 +- ditch statglue build option +- krb5-devel requires e2fsprogs-devel, which now provides libss and libcom_err + +* Wed Jun 04 2003 Elliot Lee +- rebuilt + +* Wed May 21 2003 Jeremy Katz 1.2.8-2 +- gcc 3.3 doesn't implement varargs.h, include stdarg.h instead + +* Wed Apr 9 2003 Nalin Dahyabhai 1.2.8-1 +- update to 1.2.8 + +* Mon Mar 31 2003 Nalin Dahyabhai 1.2.7-14 +- fix double-free of enc_part2 in krb524d + +* Fri Mar 21 2003 Nalin Dahyabhai 1.2.7-13 +- update to latest patch kit for MITKRB5-SA-2003-004 + +* Wed Mar 19 2003 Nalin Dahyabhai 1.2.7-12 +- add patch included in MITKRB5-SA-2003-003 (CAN-2003-0028) + +* Mon Mar 17 2003 Nalin Dahyabhai 1.2.7-11 +- add patches from patchkit from MITKRB5-SA-2003-004 (CAN-2003-0138 and + CAN-2003-0139) + +* Thu Mar 6 2003 Nalin Dahyabhai 1.2.7-10 +- rebuild + +* Thu Mar 6 2003 Nalin Dahyabhai 1.2.7-9 +- fix buffer underrun in unparsing certain principals (CAN-2003-0082) + +* Tue Feb 4 2003 Nalin Dahyabhai 1.2.7-8 +- add patch to document the reject-bad-transited option in kdc.conf + +* Mon Feb 3 2003 Nalin Dahyabhai +- add patch to fix server-side crashes when principals have no + components (CAN-2003-0072) + +* Thu Jan 23 2003 Nalin Dahyabhai 1.2.7-7 +- add patch from Mark Cox for exploitable bugs in ftp client + +* Wed Jan 22 2003 Tim Powers +- rebuilt + +* Wed Jan 15 2003 Nalin Dahyabhai 1.2.7-5 +- use PICFLAGS when building code from the ktany patch + +* Thu Jan 9 2003 Bill Nottingham 1.2.7-4 +- debloat + +* Tue Jan 7 2003 Jeremy Katz 1.2.7-3 +- include .so.* symlinks as well as .so.*.* + +* Mon Dec 9 2002 Jakub Jelinek 1.2.7-2 +- always #include to access errno, never do it directly +- enable LFS on a bunch of other 32-bit arches + +* Wed Dec 4 2002 Nalin Dahyabhai +- increase the maximum name length allowed by kuserok() to the higher value + used in development versions + +* Mon Dec 2 2002 Nalin Dahyabhai +- install src/krb524/README as README.krb524 in the -servers package, + includes information about converting for AFS principals + +* Fri Nov 15 2002 Nalin Dahyabhai 1.2.7-1 +- update to 1.2.7 +- disable use of tcl + +* Mon Nov 11 2002 Nalin Dahyabhai +- update to 1.2.7-beta2 (internal only, not for release), dropping dnsparse + and kadmind4 fixes + +* Wed Oct 23 2002 Nalin Dahyabhai 1.2.6-5 +- add patch for buffer overflow in kadmind4 (not used by default) + +* Fri Oct 11 2002 Nalin Dahyabhai 1.2.6-4 +- drop a hunk from the dnsparse patch which is actually redundant (thanks to + Tom Yu) + +* Wed Oct 9 2002 Nalin Dahyabhai 1.2.6-3 +- patch to handle truncated dns responses + +* Mon Oct 7 2002 Nalin Dahyabhai 1.2.6-2 +- remove hashless key types from the default kdc.conf, they're not supposed to + be there, noted by Sam Hartman on krbdev + +* Fri Sep 27 2002 Nalin Dahyabhai 1.2.6-1 +- update to 1.2.6 + +* Fri Sep 13 2002 Nalin Dahyabhai 1.2.5-7 +- use %%{_lib} for the sake of multilib systems + +* Fri Aug 2 2002 Nalin Dahyabhai 1.2.5-6 +- add patch from Tom Yu for exploitable bugs in rpc code used in kadmind + +* Tue Jul 23 2002 Nalin Dahyabhai 1.2.5-5 +- fix bug in krb5.csh which would cause the path check to always succeed + +* Fri Jul 19 2002 Jakub Jelinek 1.2.5-4 +- build even libdb.a with -fPIC and $RPM_OPT_FLAGS. + +* Fri Jun 21 2002 Tim Powers +- automated rebuild + +* Sun May 26 2002 Tim Powers +- automated rebuild + +* Wed May 1 2002 Nalin Dahyabhai 1.2.5-1 +- update to 1.2.5 +- disable statglue + +* Fri Mar 1 2002 Nalin Dahyabhai 1.2.4-1 +- update to 1.2.4 + +* Wed Feb 20 2002 Nalin Dahyabhai 1.2.3-5 +- rebuild in new environment +- reenable statglue + +* Sat Jan 26 2002 Florian La Roche +- prereq chkconfig for the server subpackage + +* Wed Jan 16 2002 Nalin Dahyabhai 1.2.3-3 +- build without -g3, which gives us large static libraries in -devel + +* Tue Jan 15 2002 Nalin Dahyabhai 1.2.3-2 +- reintroduce ld.so.conf munging in the -libs %%post + +* Thu Jan 10 2002 Nalin Dahyabhai 1.2.3-1 +- rename the krb5 package back to krb5-libs; the previous rename caused + something of an uproar +- update to 1.2.3, which includes the FTP and telnetd fixes +- configure without --enable-dns-for-kdc --enable-dns-for-realm, which now set + the default behavior instead of enabling the feature (the feature is enabled + by --enable-dns, which we still use) +- reenable optimizations on Alpha +- support more encryption types in the default kdc.conf (heads-up from post + to comp.protocols.kerberos by Jason Heiss) + +* Fri Aug 3 2001 Nalin Dahyabhai 1.2.2-14 +- rename the krb5-libs package to krb5 (naming a subpackage -libs when there + is no main package is silly) +- move defaults for PAM to the appdefaults section of krb5.conf -- this is + the area where the krb5_appdefault_* functions look for settings) +- disable statglue (warning: breaks binary compatibility with previous + packages, but has to be broken at some point to work correctly with + unpatched versions built with newer versions of glibc) + +* Fri Aug 3 2001 Nalin Dahyabhai 1.2.2-13 +- bump release number and rebuild + +* Wed Aug 1 2001 Nalin Dahyabhai +- add patch to fix telnetd vulnerability + +* Fri Jul 20 2001 Nalin Dahyabhai +- tweak statglue.c to fix stat/stat64 aliasing problems +- be cleaner in use of gcc to build shlibs + +* Wed Jul 11 2001 Nalin Dahyabhai +- use gcc to build shared libraries + +* Wed Jun 27 2001 Nalin Dahyabhai +- add patch to support "ANY" keytab type (i.e., + "default_keytab_name = ANY:FILE:/etc/krb5.keytab,SRVTAB:/etc/srvtab" + patch from Gerald Britton, #42551) +- build with -D_FILE_OFFSET_BITS=64 to get large file I/O in ftpd (#30697) +- patch ftpd to use long long and %%lld format specifiers to support the SIZE + command on large files (also #30697) +- don't use LOG_AUTH as an option value when calling openlog() in ksu (#45965) +- implement reload in krb5kdc and kadmind init scripts (#41911) +- lose the krb5server init script (not using it any more) + +* Sun Jun 24 2001 Elliot Lee +- Bump release + rebuild. + +* Tue May 29 2001 Nalin Dahyabhai +- pass some structures by address instead of on the stack in krb5kdc + +* Tue May 22 2001 Nalin Dahyabhai +- rebuild in new environment + +* Thu Apr 26 2001 Nalin Dahyabhai +- add patch from Tom Yu to fix ftpd overflows (#37731) + +* Wed Apr 18 2001 Than Ngo +- disable optimizations on the alpha again + +* Fri Mar 30 2001 Nalin Dahyabhai +- add in glue code to make sure that libkrb5 continues to provide a + weak copy of stat() + +* Thu Mar 15 2001 Nalin Dahyabhai +- build alpha with -O0 for now + +* Thu Mar 8 2001 Nalin Dahyabhai +- fix the kpropd init script + +* Mon Mar 5 2001 Nalin Dahyabhai +- update to 1.2.2, which fixes some bugs relating to empty ETYPE-INFO +- re-enable optimization on Alpha + +* Thu Feb 8 2001 Nalin Dahyabhai +- build alpha with -O0 for now +- own %%{_var}/kerberos + +* Tue Feb 6 2001 Nalin Dahyabhai +- own the directories which are created for each package (#26342) + +* Tue Jan 23 2001 Nalin Dahyabhai +- gettextize init scripts + +* Fri Jan 19 2001 Nalin Dahyabhai +- add some comments to the ksu patches for the curious +- re-enable optimization on alphas + +* Mon Jan 15 2001 Nalin Dahyabhai +- fix krb5-send-pr (#18932) and move it from -server to -workstation +- buildprereq libtermcap-devel +- temporariliy disable optimization on alphas +- gettextize init scripts + +* Tue Dec 5 2000 Nalin Dahyabhai +- force -fPIC + +* Fri Dec 1 2000 Nalin Dahyabhai +- rebuild in new environment + +* Tue Oct 31 2000 Nalin Dahyabhai +- add bison as a BuildPrereq (#20091) + +* Mon Oct 30 2000 Nalin Dahyabhai +- change /usr/dict/words to /usr/share/dict/words in default kdc.conf (#20000) + +* Thu Oct 5 2000 Nalin Dahyabhai +- apply kpasswd bug fixes from David Wragg + +* Wed Oct 4 2000 Nalin Dahyabhai +- make krb5-libs obsolete the old krb5-configs package (#18351) +- don't quit from the kpropd init script if there's no principal database so + that you can propagate the first time without running kpropd manually +- don't complain if /etc/ld.so.conf doesn't exist in the -libs %%post + +* Tue Sep 12 2000 Nalin Dahyabhai +- fix credential forwarding problem in klogind (goof in KRB5CCNAME handling) + (#11588) +- fix heap corruption bug in FTP client (#14301) + +* Wed Aug 16 2000 Nalin Dahyabhai +- fix summaries and descriptions +- switched the default transfer protocol from PORT to PASV as proposed on + bugzilla (#16134), and to match the regular ftp package's behavior + +* Wed Jul 19 2000 Jeff Johnson +- rebuild to compress man pages. + +* Sat Jul 15 2000 Bill Nottingham +- move initscript back + +* Fri Jul 14 2000 Nalin Dahyabhai +- disable servers by default to keep linuxconf from thinking they need to be + started when they don't + +* Thu Jul 13 2000 Prospector +- automatic rebuild + +* Mon Jul 10 2000 Nalin Dahyabhai +- change cleanup code in post to not tickle chkconfig +- add grep as a Prereq: for -libs + +* Thu Jul 6 2000 Nalin Dahyabhai +- move condrestarts to postun +- make xinetd configs noreplace +- add descriptions to xinetd configs +- add /etc/init.d as a prereq for the -server package +- patch to properly truncate $TERM in krlogind + +* Fri Jun 30 2000 Nalin Dahyabhai +- update to 1.2.1 +- back out Tom Yu's patch, which is a big chunk of the 1.2 -> 1.2.1 update +- start using the official source tarball instead of its contents + +* Thu Jun 29 2000 Nalin Dahyabhai +- Tom Yu's patch to fix compatibility between 1.2 kadmin and 1.1.1 kadmind +- pull out 6.2 options in the spec file (sonames changing in 1.2 means it's not + compatible with other stuff in 6.2, so no need) + +* Wed Jun 28 2000 Nalin Dahyabhai +- tweak graceful start/stop logic in post and preun + +* Mon Jun 26 2000 Nalin Dahyabhai +- update to the 1.2 release +- ditch a lot of our patches which went upstream +- enable use of DNS to look up things at build-time +- disable use of DNS to look up things at run-time in default krb5.conf +- change ownership of the convert-config-files script to root.root +- compress PS docs +- fix some typos in the kinit man page +- run condrestart in server post, and shut down in preun + +* Mon Jun 19 2000 Nalin Dahyabhai +- only remove old krb5server init script links if the init script is there + +* Sat Jun 17 2000 Nalin Dahyabhai +- disable kshell and eklogin by default + +* Thu Jun 15 2000 Nalin Dahyabhai +- patch mkdir/rmdir problem in ftpcmd.y +- add condrestart option to init script +- split the server init script into three pieces and add one for kpropd + +* Wed Jun 14 2000 Nalin Dahyabhai +- make sure workstation servers are all disabled by default +- clean up krb5server init script + +* Fri Jun 9 2000 Nalin Dahyabhai +- apply second set of buffer overflow fixes from Tom Yu +- fix from Dirk Husung for a bug in buffer cleanups in the test suite +- work around possibly broken rev binary in running test suite +- move default realm configs from /var/kerberos to %%{_var}/kerberos + +* Tue Jun 6 2000 Nalin Dahyabhai +- make ksu and v4rcp owned by root + +* Sat Jun 3 2000 Nalin Dahyabhai +- use %%{_infodir} to better comply with FHS +- move .so files to -devel subpackage +- tweak xinetd config files (bugs #11833, #11835, #11836, #11840) +- fix package descriptions again + +* Wed May 24 2000 Nalin Dahyabhai +- change a LINE_MAX to 1024, fix from Ken Raeburn +- add fix for login vulnerability in case anyone rebuilds without krb4 compat +- add tweaks for byte-swapping macros in krb.h, also from Ken +- add xinetd config files +- make rsh and rlogin quieter +- build with debug to fix credential forwarding +- add rsh as a build-time req because the configure scripts look for it to + determine paths + +* Wed May 17 2000 Nalin Dahyabhai +- fix config_subpackage logic + +* Tue May 16 2000 Nalin Dahyabhai +- remove setuid bit on v4rcp and ksu in case the checks previously added + don't close all of the problems in ksu +- apply patches from Jeffrey Schiller to fix overruns Chris Evans found +- reintroduce configs subpackage for use in the errata +- add PreReq: sh-utils + +* Mon May 15 2000 Nalin Dahyabhai +- fix double-free in the kdc (patch merged into MIT tree) +- include convert-config-files script as a documentation file + +* Wed May 03 2000 Nalin Dahyabhai +- patch ksu man page because the -C option never works +- add access() checks and disable debug mode in ksu +- modify default ksu build arguments to specify more directories in CMD_PATH + and to use getusershell() + +* Wed May 03 2000 Bill Nottingham +- fix configure stuff for ia64 + +* Mon Apr 10 2000 Nalin Dahyabhai +- add LDCOMBINE=-lc to configure invocation to use libc versioning (bug #10653) +- change Requires: for/in subpackages to include %%{version} + +* Wed Apr 05 2000 Nalin Dahyabhai +- add man pages for kerberos(1), kvno(1), .k5login(5) +- add kvno to -workstation + +* Mon Apr 03 2000 Nalin Dahyabhai +- Merge krb5-configs back into krb5-libs. The krb5.conf file is marked as + a %%config file anyway. +- Make krb5.conf a noreplace config file. + +* Thu Mar 30 2000 Nalin Dahyabhai +- Make klogind pass a clean environment to children, like NetKit's rlogind does. + +* Wed Mar 08 2000 Nalin Dahyabhai +- Don't enable the server by default. +- Compress info pages. +- Add defaults for the PAM module to krb5.conf + +* Mon Mar 06 2000 Nalin Dahyabhai +- Correct copyright: it's exportable now, provided the proper paperwork is + filed with the government. + +* Fri Mar 03 2000 Nalin Dahyabhai +- apply Mike Friedman's patch to fix format string problems +- don't strip off argv[0] when invoking regular rsh/rlogin + +* Thu Mar 02 2000 Nalin Dahyabhai +- run kadmin.local correctly at startup + +* Mon Feb 28 2000 Nalin Dahyabhai +- pass absolute path to kadm5.keytab if/when extracting keys at startup + +* Sat Feb 19 2000 Nalin Dahyabhai +- fix info page insertions + +* Wed Feb 9 2000 Nalin Dahyabhai +- tweak server init script to automatically extract kadm5 keys if + /var/kerberos/krb5kdc/kadm5.keytab doesn't exist yet +- adjust package descriptions + +* Thu Feb 3 2000 Nalin Dahyabhai +- fix for potentially gzipped man pages + +* Fri Jan 21 2000 Nalin Dahyabhai +- fix comments in krb5-configs + +* Fri Jan 7 2000 Nalin Dahyabhai +- move /usr/kerberos/bin to end of PATH + +* Tue Dec 28 1999 Nalin Dahyabhai +- install kadmin header files + +* Tue Dec 21 1999 Nalin Dahyabhai +- patch around TIOCGTLC defined on alpha and remove warnings from libpty.h +- add installation of info docs +- remove krb4 compat patch because it doesn't fix workstation-side servers + +* Mon Dec 20 1999 Nalin Dahyabhai +- remove hesiod dependency at build-time + +* Sun Dec 19 1999 Nalin Dahyabhai +- rebuild on 1.1.1 + +* Thu Oct 7 1999 Nalin Dahyabhai +- clean up init script for server, verify that it works [jlkatz] +- clean up rotation script so that rc likes it better +- add clean stanza + +* Mon Oct 4 1999 Nalin Dahyabhai +- backed out ncurses and makeshlib patches +- update for krb5-1.1 +- add KDC rotation to rc.boot, based on ideas from Michael's C version + +* Mon Sep 27 1999 Nalin Dahyabhai +- added -lncurses to telnet and telnetd makefiles + +* Mon Jul 5 1999 Nalin Dahyabhai +- added krb5.csh and krb5.sh to /etc/profile.d + +* Tue Jun 22 1999 Nalin Dahyabhai +- broke out configuration files + +* Mon Jun 14 1999 Nalin Dahyabhai +- fixed server package so that it works now + +* Sat May 15 1999 Nalin Dahyabhai +- started changelog (previous package from zedz.net) +- updated existing 1.0.5 RPM from Eos Linux to krb5 1.0.6 +- added --force to makeinfo commands to skip errors during build diff --git a/root/ppg/common/deps/krb5/rpm/krb5kdc.logrotate b/root/ppg/common/deps/krb5/rpm/krb5kdc.logrotate new file mode 100644 index 00000000..1100ed3a --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/krb5kdc.logrotate @@ -0,0 +1,9 @@ +/var/log/krb5kdc.log { + missingok + notifempty + monthly + rotate 12 + postrotate + /bin/kill -HUP `cat /var/run/krb5kdc.pid 2>/dev/null` 2> /dev/null || true + endscript +} diff --git a/root/ppg/common/deps/krb5/rpm/krb5kdc.service b/root/ppg/common/deps/krb5/rpm/krb5kdc.service new file mode 100644 index 00000000..806b062d --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/krb5kdc.service @@ -0,0 +1,14 @@ +[Unit] +Description=Kerberos 5 KDC +Wants=network-online.target +After=syslog.target network.target network-online.target + +[Service] +Type=forking +PIDFile=/var/run/krb5kdc.pid +EnvironmentFile=-/etc/sysconfig/krb5kdc +ExecStart=/usr/sbin/krb5kdc -P /var/run/krb5kdc.pid $KRB5KDC_ARGS +ExecReload=/bin/kill -HUP $MAINPID + +[Install] +WantedBy=multi-user.target diff --git a/root/ppg/common/deps/krb5/rpm/krb5kdc.sysconfig b/root/ppg/common/deps/krb5/rpm/krb5kdc.sysconfig new file mode 100644 index 00000000..791216d3 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/krb5kdc.sysconfig @@ -0,0 +1 @@ +KRB5KDC_ARGS= diff --git a/root/ppg/common/deps/krb5/rpm/ksu.pamd b/root/ppg/common/deps/krb5/rpm/ksu.pamd new file mode 100644 index 00000000..66f5b2cc --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/ksu.pamd @@ -0,0 +1,4 @@ +#%PAM-1.0 +auth include su +account include su +session include su diff --git a/root/ppg/common/deps/krb5/rpm/percona-builtin-crypto-portability.patch b/root/ppg/common/deps/krb5/rpm/percona-builtin-crypto-portability.patch new file mode 100644 index 00000000..f80d1867 --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/percona-builtin-crypto-portability.patch @@ -0,0 +1,182 @@ +percona: detach RH downstream FIPS/KDF hooks from OpenSSL for builtin-crypto builds + +This krb5 package is rebuilt with --with-crypto-impl=builtin so that the +krb5-libs shared objects bundled into the Percona PostgreSQL binary +tarball (EL8 / ssl1.1 variant) carry no libcrypto/libssl dependency. +Red Hat's openssl-crypto build references symbol version nodes such as +EVP_KDF_ctrl@OPENSSL_1_1_1b that exist only in the RHEL OpenSSL 1.1.1 +fork, so those libraries fail to load on stock OpenSSL 1.1 hosts +(proven on Debian 11). + +Applied on top of the full RHEL 8 patch series, this change confines +the downstream OpenSSL hooks that live in backend-independent code: + + * configure.ac: the EVP_KDF_* check (added by + rhel-Use-backported-version-of-OpenSSL-3-KDF-interfa.patch) hard-fails + when the backported KDFs are absent; run it only for the openssl + crypto impl. Without OSSL_KDFS, derive.c falls back to the upstream + backend-independent KDF code path. + * lib/crypto/krb/derive.c and plugins/preauth/pkinit + (pkinit_crypto_openssl.c): drop the '#error "Refusing to build + without OpenSSL KDFs!"' guards the same RH patch added — the #else + branches contain the full upstream KDF implementation. pkinit.so + itself stays linked against the build root's OpenSSL; it ships in + the separate krb5-pkinit subpackage, which is never bundled. + * lib/crypto/krb/prng.c: drop the FIPS_mode()/RAND_bytes() OS-entropy + override (would link libcrypto into libk5crypto.so.3). + * lib/krad/internal.h: kr_use_fips() always returns false instead of + consulting FIPS_mode() (would link libcrypto into libkrad.so.0). + Non-FIPS behaviour equals the upstream default (RADIUS MD5 allowed). + * plugins/preauth/spake: drop the FIPS_mode() gate (would link + libcrypto into spake.so, which ships in krb5-libs). + +FIPS mode is a Red Hat OpenSSL concept; the tarball's relocatable +PostgreSQL distribution does not claim FIPS validation, so losing these +FIPS-only refusals has no effect on its supported use. + +diff --git a/src/configure.ac b/src/configure.ac +index 2a48aa8..0acc097 100644 +--- a/src/configure.ac ++++ b/src/configure.ac +@@ -282,9 +282,13 @@ AC_SUBST(CRYPTO_IMPL) + AC_SUBST(CRYPTO_IMPL_CFLAGS) + AC_SUBST(CRYPTO_IMPL_LIBS) + ++dnl Percona: the EVP_KDF_* backports exist only in Red Hat OpenSSL 1.1.1; ++dnl require them only when actually building against OpenSSL. ++if test "$CRYPTO_IMPL" = openssl; then + AC_CHECK_FUNCS(EVP_KDF_CTX_new_id EVP_KDF_ctrl EVP_KDF_derive, + AC_DEFINE(OSSL_KDFS, 1, [Define if using OpenSSL KDFs]), + AC_MSG_ERROR([backported OpenSSL KDFs not found])) ++fi + + AC_ARG_WITH([prng-alg], + AC_HELP_STRING([--with-prng-alg=ALG], [use specified PRNG algorithm. @<:@fortuna@:>@]), +diff --git a/src/lib/crypto/krb/prng.c b/src/lib/crypto/krb/prng.c +index f0e9984..026ab2a 100644 +--- a/src/lib/crypto/krb/prng.c ++++ b/src/lib/crypto/krb/prng.c +@@ -26,8 +26,6 @@ + + #include "crypto_int.h" + +-#include +- + krb5_error_code KRB5_CALLCONV + krb5_c_random_seed(krb5_context context, krb5_data *data) + { +@@ -103,13 +101,6 @@ k5_get_os_entropy(unsigned char *buf, size_t len, int strong) + const char *device; + int r; + +- /* A wild FIPS mode appeared! */ +- if (FIPS_mode()) { +- /* The return codes on this API are not good */ +- r = RAND_bytes(buf, len); +- return r == 1; +- } +- + #if defined(__linux__) && defined(SYS_getrandom) + while (len > 0) { + /* +diff --git a/src/lib/krad/internal.h b/src/lib/krad/internal.h +index f3e4a1d..8665c1c 100644 +--- a/src/lib/krad/internal.h ++++ b/src/lib/krad/internal.h +@@ -39,7 +39,6 @@ + #include + #include + +-#include + + #ifndef UCHAR_MAX + #define UCHAR_MAX 255 +@@ -173,14 +172,10 @@ gai_error_code(int err) + static inline krb5_boolean + kr_use_fips(krb5_context ctx) + { +- int val = 0; +- +- if (!FIPS_mode()) +- return 0; +- +- profile_get_boolean(ctx->profile, "libdefaults", +- "radius_md5_fips_override", NULL, 0, &val); +- return !val; ++ /* Percona: built with the builtin crypto impl (no OpenSSL); FIPS ++ * mode is a Red Hat OpenSSL concept and never applies here. */ ++ (void)ctx; ++ return 0; + } + + #endif /* INTERNAL_H_ */ +diff --git a/src/plugins/preauth/spake/spake_client.c b/src/plugins/preauth/spake/spake_client.c +index a3ce22b..ee5afb3 100644 +--- a/src/plugins/preauth/spake/spake_client.c ++++ b/src/plugins/preauth/spake/spake_client.c +@@ -38,7 +38,6 @@ + #include "groups.h" + #include + +-#include + + typedef struct reqstate_st { + krb5_pa_spake *msg; /* set in prep_questions, used in process */ +@@ -378,9 +377,6 @@ clpreauth_spake_initvt(krb5_context context, int maj_ver, int min_ver, + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + +- if (FIPS_mode()) +- return KRB5_CRYPTO_INTERNAL; +- + vt = (krb5_clpreauth_vtable)vtable; + vt->name = "spake"; + vt->pa_type_list = pa_types; +diff --git a/src/plugins/preauth/spake/spake_kdc.c b/src/plugins/preauth/spake/spake_kdc.c +index c7df039..f25d2b6 100644 +--- a/src/plugins/preauth/spake/spake_kdc.c ++++ b/src/plugins/preauth/spake/spake_kdc.c +@@ -41,7 +41,6 @@ + + #include + +-#include + + /* + * The SPAKE kdcpreauth module uses a secure cookie containing the following +@@ -574,9 +573,6 @@ kdcpreauth_spake_initvt(krb5_context context, int maj_ver, int min_ver, + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + +- if (FIPS_mode()) +- return KRB5_CRYPTO_INTERNAL; +- + vt = (krb5_kdcpreauth_vtable)vtable; + vt->name = "spake"; + vt->pa_type_list = pa_types; +diff --git a/src/lib/crypto/krb/derive.c b/src/lib/crypto/krb/derive.c +index 915a173..b8e5524 100644 +--- a/src/lib/crypto/krb/derive.c ++++ b/src/lib/crypto/krb/derive.c +@@ -30,8 +30,6 @@ + #ifdef OSSL_KDFS + #include + #include +-#else +-#error "Refusing to build without OpenSSL KDFs!" + #endif + + static krb5_key +diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c +index 638971f..8859934 100644 +--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c ++++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c +@@ -41,8 +41,6 @@ + #ifdef OSSL_KDFS + #include + #include +-#else +-#error "Refusing to build without OpenSSL KDFs!" + #endif + + static krb5_error_code pkinit_init_pkinit_oids(pkinit_plg_crypto_context ); diff --git a/root/ppg/common/deps/krb5/rpm/rhel-Use-backported-version-of-OpenSSL-3-KDF-interfa.patch b/root/ppg/common/deps/krb5/rpm/rhel-Use-backported-version-of-OpenSSL-3-KDF-interfa.patch new file mode 100644 index 00000000..cbbfd2dd --- /dev/null +++ b/root/ppg/common/deps/krb5/rpm/rhel-Use-backported-version-of-OpenSSL-3-KDF-interfa.patch @@ -0,0 +1,751 @@ +From 396ce77f48f758efa090aadd00cd7208e7e97491 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Fri, 15 Nov 2019 20:05:16 +0000 +Subject: [PATCH] [rhel] Use backported version of OpenSSL-3 KDF interface + +(cherry picked from commit 0e20daf7ccfe50518c89735c3dae2fde08d92325) +--- + src/configure.ac | 4 + + src/lib/crypto/krb/derive.c | 356 +++++++++++++----- + .../preauth/pkinit/pkinit_crypto_openssl.c | 257 ++++++++----- + 3 files changed, 428 insertions(+), 189 deletions(-) + +diff --git a/src/configure.ac b/src/configure.ac +index d4e4da525..29be532cb 100644 +--- a/src/configure.ac ++++ b/src/configure.ac +@@ -282,6 +282,10 @@ AC_SUBST(CRYPTO_IMPL) + AC_SUBST(CRYPTO_IMPL_CFLAGS) + AC_SUBST(CRYPTO_IMPL_LIBS) + ++AC_CHECK_FUNCS(EVP_KDF_CTX_new_id EVP_KDF_ctrl EVP_KDF_derive, ++ AC_DEFINE(OSSL_KDFS, 1, [Define if using OpenSSL KDFs]), ++ AC_MSG_ERROR([backported OpenSSL KDFs not found])) ++ + AC_ARG_WITH([prng-alg], + AC_HELP_STRING([--with-prng-alg=ALG], [use specified PRNG algorithm. @<:@fortuna@:>@]), + [PRNG_ALG=$withval +diff --git a/src/lib/crypto/krb/derive.c b/src/lib/crypto/krb/derive.c +index 6707a7308..915a173dd 100644 +--- a/src/lib/crypto/krb/derive.c ++++ b/src/lib/crypto/krb/derive.c +@@ -27,6 +27,13 @@ + + #include "crypto_int.h" + ++#ifdef OSSL_KDFS ++#include ++#include ++#else ++#error "Refusing to build without OpenSSL KDFs!" ++#endif ++ + static krb5_key + find_cached_dkey(struct derived_key *list, const krb5_data *constant) + { +@@ -77,55 +84,193 @@ cleanup: + return ENOMEM; + } + ++#ifdef OSSL_KDFS + static krb5_error_code +-derive_random_rfc3961(const struct krb5_enc_provider *enc, +- krb5_key inkey, krb5_data *outrnd, +- const krb5_data *in_constant) ++openssl_kbdkf_counter_hmac(const struct krb5_hash_provider *hash, ++ krb5_key inkey, krb5_data *outrnd, ++ const krb5_data *label, const krb5_data *context) + { +- size_t blocksize, keybytes, n; ++ krb5_error_code ret = KRB5_CRYPTO_INTERNAL; ++ EVP_KDF_CTX *ctx = NULL; ++ const EVP_MD *digest; ++ ++ if (!strcmp(hash->hash_name, "SHA1")) ++ digest = EVP_sha1(); ++ else if (!strcmp(hash->hash_name, "SHA-256")) ++ digest = EVP_sha256(); ++ else if (!strcmp(hash->hash_name, "SHA-384")) ++ digest = EVP_sha384(); ++ else ++ goto done; ++ ++ ctx = EVP_KDF_CTX_new_id(EVP_KDF_KB); ++ if (!ctx) ++ goto done; ++ ++ if (EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_MD, digest) != 1 || ++ EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KB_MAC_TYPE, ++ EVP_KDF_KB_MAC_TYPE_HMAC) != 1 || ++ EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KEY, inkey->keyblock.contents, ++ inkey->keyblock.length) != 1 || ++ (context->length > 0 && ++ EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KB_INFO, context->data, ++ context->length) != 1) || ++ (label->length > 0 && ++ EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SALT, label->data, ++ label->length) != 1) || ++ EVP_KDF_derive(ctx, (unsigned char *)outrnd->data, ++ outrnd->length) != 1) ++ goto done; ++ ++ ret = 0; ++done: ++ if (ret) ++ zap(outrnd->data, outrnd->length); ++ EVP_KDF_CTX_free(ctx); ++ return ret; ++} ++ ++static krb5_error_code ++openssl_kbkdf_feedback_cmac(const struct krb5_enc_provider *enc, ++ krb5_key inkey, krb5_data *outrnd, ++ const krb5_data *in_constant) ++{ ++ krb5_error_code ret = KRB5_CRYPTO_INTERNAL; ++ EVP_KDF_CTX *ctx = NULL; ++ const EVP_CIPHER *cipher; ++ static unsigned char zeroes[16]; ++ ++ memset(zeroes, 0, sizeof(zeroes)); ++ ++ if (enc->keylength == 16) ++ cipher = EVP_camellia_128_cbc(); ++ else if (enc->keylength == 32) ++ cipher = EVP_camellia_256_cbc(); ++ else ++ goto done; ++ ++ ctx = EVP_KDF_CTX_new_id(EVP_KDF_KB); ++ if (!ctx) ++ goto done; ++ ++ if (EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KB_MODE, ++ EVP_KDF_KB_MODE_FEEDBACK) != 1 || ++ EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KB_MAC_TYPE, ++ EVP_KDF_KB_MAC_TYPE_CMAC) != 1 || ++ EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_CIPHER, cipher) != 1 || ++ EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KEY, inkey->keyblock.contents, ++ inkey->keyblock.length) != 1 || ++ EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SALT, in_constant->data, ++ in_constant->length) != 1 || ++ EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KB_SEED, zeroes, ++ sizeof(zeroes)) != 1 || ++ EVP_KDF_derive(ctx, (unsigned char *)outrnd->data, ++ outrnd->length) != 1) ++ goto done; ++ ++ ret = 0; ++done: ++ if (ret) ++ zap(outrnd->data, outrnd->length); ++ EVP_KDF_CTX_free(ctx); ++ return ret; ++} ++ ++static krb5_error_code ++openssl_krb5kdf(const struct krb5_enc_provider *enc, krb5_key inkey, ++ krb5_data *outrnd, const krb5_data *in_constant) ++{ ++ krb5_error_code ret = KRB5_CRYPTO_INTERNAL; ++ EVP_KDF_CTX *ctx = NULL; ++ const EVP_CIPHER *cipher; ++ ++ if (inkey->keyblock.length != enc->keylength || ++ outrnd->length != enc->keybytes) { ++ return KRB5_CRYPTO_INTERNAL; ++ } ++ ++ if (enc->encrypt == krb5int_aes_encrypt && enc->keylength == 16) ++ cipher = EVP_aes_128_cbc(); ++ else if (enc->encrypt == krb5int_aes_encrypt && enc->keylength == 32) ++ cipher = EVP_aes_256_cbc(); ++ else if (enc->keylength == 24) ++ cipher = EVP_des_ede3_cbc(); ++ else ++ goto done; ++ ++ ctx = EVP_KDF_CTX_new_id(EVP_KDF_KRB5KDF); ++ if (ctx == NULL) ++ goto done; ++ ++ if (EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_CIPHER, cipher) != 1 || ++ EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KEY, inkey->keyblock.contents, ++ inkey->keyblock.length) != 1 || ++ EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KRB5KDF_CONSTANT, ++ in_constant->data, in_constant->length) != 1 || ++ EVP_KDF_derive(ctx, (unsigned char *)outrnd->data, ++ outrnd->length) != 1) ++ goto done; ++ ++ ret = 0; ++done: ++ if (ret) ++ zap(outrnd->data, outrnd->length); ++ EVP_KDF_CTX_free(ctx); ++ return ret; ++} ++ ++#else /* OSSL_KDFS */ ++ ++/* ++ * NIST SP800-108 KDF in counter mode (section 5.1). ++ * Parameters: ++ * - HMAC (with hash as the hash provider) is the PRF. ++ * - A block counter of four bytes is used. ++ * - Four bytes are used to encode the output length in the PRF input. ++ * ++ * There are no uses requiring more than a single PRF invocation. ++ */ ++static krb5_error_code ++builtin_sp800_108_counter_hmac(const struct krb5_hash_provider *hash, ++ krb5_key inkey, krb5_data *outrnd, ++ const krb5_data *label, ++ const krb5_data *context) ++{ ++ krb5_crypto_iov iov[5]; + krb5_error_code ret; +- krb5_data block = empty_data(); ++ krb5_data prf; ++ unsigned char ibuf[4], lbuf[4]; + +- blocksize = enc->block_size; +- keybytes = enc->keybytes; +- +- if (blocksize == 1) +- return KRB5_BAD_ENCTYPE; +- if (inkey->keyblock.length != enc->keylength || outrnd->length != keybytes) ++ if (hash == NULL || outrnd->length > hash->hashsize) + return KRB5_CRYPTO_INTERNAL; + + /* Allocate encryption data buffer. */ +- ret = alloc_data(&block, blocksize); ++ ret = alloc_data(&prf, hash->hashsize); + if (ret) + return ret; + +- /* Initialize the input block. */ +- if (in_constant->length == blocksize) { +- memcpy(block.data, in_constant->data, blocksize); +- } else { +- krb5int_nfold(in_constant->length * 8, +- (unsigned char *) in_constant->data, +- blocksize * 8, (unsigned char *) block.data); +- } ++ /* [i]2: four-byte big-endian binary string giving the block counter (1) */ ++ iov[0].flags = KRB5_CRYPTO_TYPE_DATA; ++ iov[0].data = make_data(ibuf, sizeof(ibuf)); ++ store_32_be(1, ibuf); ++ /* Label */ ++ iov[1].flags = KRB5_CRYPTO_TYPE_DATA; ++ iov[1].data = *label; ++ /* 0x00: separator byte */ ++ iov[2].flags = KRB5_CRYPTO_TYPE_DATA; ++ iov[2].data = make_data("", 1); ++ /* Context */ ++ iov[3].flags = KRB5_CRYPTO_TYPE_DATA; ++ iov[3].data = *context; ++ /* [L]2: four-byte big-endian binary string giving the output length */ ++ iov[4].flags = KRB5_CRYPTO_TYPE_DATA; ++ iov[4].data = make_data(lbuf, sizeof(lbuf)); ++ store_32_be(outrnd->length * 8, lbuf); + +- /* Loop encrypting the blocks until enough key bytes are generated. */ +- n = 0; +- while (n < keybytes) { +- ret = encrypt_block(enc, inkey, &block); +- if (ret) +- goto cleanup; +- +- if ((keybytes - n) <= blocksize) { +- memcpy(outrnd->data + n, block.data, (keybytes - n)); +- break; +- } +- +- memcpy(outrnd->data + n, block.data, blocksize); +- n += blocksize; +- } +- +-cleanup: +- zapfree(block.data, blocksize); ++ ret = krb5int_hmac(hash, inkey, iov, 5, &prf); ++ if (!ret) ++ memcpy(outrnd->data, prf.data, outrnd->length); ++ zapfree(prf.data, prf.length); + return ret; + } + +@@ -139,9 +284,9 @@ cleanup: + * - Four bytes are used to encode the output length in the PRF input. + */ + static krb5_error_code +-derive_random_sp800_108_feedback_cmac(const struct krb5_enc_provider *enc, +- krb5_key inkey, krb5_data *outrnd, +- const krb5_data *in_constant) ++builtin_sp800_108_feedback_cmac(const struct krb5_enc_provider *enc, ++ krb5_key inkey, krb5_data *outrnd, ++ const krb5_data *in_constant) + { + size_t blocksize, keybytes, n; + krb5_crypto_iov iov[6]; +@@ -204,56 +349,94 @@ cleanup: + return ret; + } + +-/* +- * NIST SP800-108 KDF in counter mode (section 5.1). +- * Parameters: +- * - HMAC (with hash as the hash provider) is the PRF. +- * - A block counter of four bytes is used. +- * - Four bytes are used to encode the output length in the PRF input. +- * +- * There are no uses requiring more than a single PRF invocation. +- */ ++static krb5_error_code ++builtin_derive_random_rfc3961(const struct krb5_enc_provider *enc, ++ krb5_key inkey, krb5_data *outrnd, ++ const krb5_data *in_constant) ++{ ++ size_t blocksize, keybytes, n; ++ krb5_error_code ret; ++ krb5_data block = empty_data(); ++ ++ blocksize = enc->block_size; ++ keybytes = enc->keybytes; ++ ++ if (blocksize == 1) ++ return KRB5_BAD_ENCTYPE; ++ if (inkey->keyblock.length != enc->keylength || outrnd->length != keybytes) ++ return KRB5_CRYPTO_INTERNAL; ++ ++ /* Allocate encryption data buffer. */ ++ ret = alloc_data(&block, blocksize); ++ if (ret) ++ return ret; ++ ++ /* Initialize the input block. */ ++ if (in_constant->length == blocksize) { ++ memcpy(block.data, in_constant->data, blocksize); ++ } else { ++ krb5int_nfold(in_constant->length * 8, ++ (unsigned char *) in_constant->data, ++ blocksize * 8, (unsigned char *) block.data); ++ } ++ ++ /* Loop encrypting the blocks until enough key bytes are generated. */ ++ n = 0; ++ while (n < keybytes) { ++ ret = encrypt_block(enc, inkey, &block); ++ if (ret) ++ goto cleanup; ++ ++ if ((keybytes - n) <= blocksize) { ++ memcpy(outrnd->data + n, block.data, (keybytes - n)); ++ break; ++ } ++ ++ memcpy(outrnd->data + n, block.data, blocksize); ++ n += blocksize; ++ } ++ ++cleanup: ++ zapfree(block.data, blocksize); ++ return ret; ++} ++#endif /* OSSL_KDFS */ ++ + krb5_error_code + k5_sp800_108_counter_hmac(const struct krb5_hash_provider *hash, + krb5_key inkey, krb5_data *outrnd, + const krb5_data *label, const krb5_data *context) + { +- krb5_crypto_iov iov[5]; +- krb5_error_code ret; +- krb5_data prf; +- unsigned char ibuf[4], lbuf[4]; ++#ifdef OSSL_KDFS ++ return openssl_kbdkf_counter_hmac(hash, inkey, outrnd, label, context); ++#else ++ return builtin_sp800_108_counter_hmac(hash, inkey, outrnd, label, ++ context); ++#endif ++} + +- if (hash == NULL || outrnd->length > hash->hashsize) +- return KRB5_CRYPTO_INTERNAL; ++static krb5_error_code ++k5_sp800_108_feedback_cmac(const struct krb5_enc_provider *enc, ++ krb5_key inkey, krb5_data *outrnd, ++ const krb5_data *in_constant) ++{ ++#ifdef OSSL_KDFS ++ return openssl_kbkdf_feedback_cmac(enc, inkey, outrnd, in_constant); ++#else ++ return builtin_sp800_108_feedback_cmac(enc, inkey, outrnd, in_constant); ++#endif ++} + +- /* Allocate encryption data buffer. */ +- ret = alloc_data(&prf, hash->hashsize); +- if (ret) +- return ret; +- +- /* [i]2: four-byte big-endian binary string giving the block counter (1) */ +- iov[0].flags = KRB5_CRYPTO_TYPE_DATA; +- iov[0].data = make_data(ibuf, sizeof(ibuf)); +- store_32_be(1, ibuf); +- /* Label */ +- iov[1].flags = KRB5_CRYPTO_TYPE_DATA; +- iov[1].data = *label; +- /* 0x00: separator byte */ +- iov[2].flags = KRB5_CRYPTO_TYPE_DATA; +- iov[2].data = make_data("", 1); +- /* Context */ +- iov[3].flags = KRB5_CRYPTO_TYPE_DATA; +- iov[3].data = *context; +- /* [L]2: four-byte big-endian binary string giving the output length */ +- iov[4].flags = KRB5_CRYPTO_TYPE_DATA; +- iov[4].data = make_data(lbuf, sizeof(lbuf)); +- store_32_be(outrnd->length * 8, lbuf); +- +- ret = krb5int_hmac(hash, inkey, iov, 5, &prf); +- if (!ret) +- memcpy(outrnd->data, prf.data, outrnd->length); +- zapfree(prf.data, prf.length); +- return ret; ++static krb5_error_code ++k5_derive_random_rfc3961(const struct krb5_enc_provider *enc, ++ krb5_key inkey, krb5_data *outrnd, ++ const krb5_data *in_constant) ++{ ++#ifdef OSSL_KDFS ++ return openssl_krb5kdf(enc, inkey, outrnd, in_constant); ++#else ++ return builtin_derive_random_rfc3961(enc, inkey, outrnd, in_constant); ++#endif + } + + krb5_error_code +@@ -266,10 +449,9 @@ krb5int_derive_random(const struct krb5_enc_provider *enc, + + switch (alg) { + case DERIVE_RFC3961: +- return derive_random_rfc3961(enc, inkey, outrnd, in_constant); ++ return k5_derive_random_rfc3961(enc, inkey, outrnd, in_constant); + case DERIVE_SP800_108_CMAC: +- return derive_random_sp800_108_feedback_cmac(enc, inkey, outrnd, +- in_constant); ++ return k5_sp800_108_feedback_cmac(enc, inkey, outrnd, in_constant); + case DERIVE_SP800_108_HMAC: + return k5_sp800_108_counter_hmac(hash, inkey, outrnd, in_constant, + &empty); +diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c +index 52976895b..dd718c2be 100644 +--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c ++++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c +@@ -38,6 +38,13 @@ + #include + #include + ++#ifdef OSSL_KDFS ++#include ++#include ++#else ++#error "Refusing to build without OpenSSL KDFs!" ++#endif ++ + static krb5_error_code pkinit_init_pkinit_oids(pkinit_plg_crypto_context ); + static void pkinit_fini_pkinit_oids(pkinit_plg_crypto_context ); + +@@ -2331,11 +2338,51 @@ pkinit_alg_values(krb5_context context, + } + } /* pkinit_alg_values() */ + ++#ifdef OSSL_KDFS ++static krb5_error_code ++openssl_sskdf(krb5_context context, size_t hash_bytes, krb5_data *key, ++ krb5_data *info, char *out, size_t out_len) ++{ ++ krb5_error_code ret = KRB5_CRYPTO_INTERNAL; ++ EVP_KDF_CTX *ctx = NULL; ++ const EVP_MD *digest; + +-/* pkinit_alg_agility_kdf() -- +- * This function generates a key using the KDF described in +- * draft_ietf_krb_wg_pkinit_alg_agility-04.txt. The algorithm is +- * described as follows: ++ /* RFC 8636 defines a SHA384 variant, but we don't use it. */ ++ if (hash_bytes == 20) { ++ digest = EVP_sha1(); ++ } else if (hash_bytes == 32) { ++ digest = EVP_sha256(); ++ } else if (hash_bytes == 64) { ++ digest = EVP_sha512(); ++ } else { ++ krb5_set_error_message(context, ret, "Bad hash type for SSKDF"); ++ goto done; ++ } ++ ++ ctx = EVP_KDF_CTX_new_id(EVP_KDF_SS); ++ if (!ctx) { ++ oerr(context, ret, _("Failed to instantiate SSKDF")); ++ goto done; ++ } ++ ++ if (EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_MD, digest) != 1 || ++ EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KEY, key->data, ++ key->length) != 1 || ++ EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSKDF_INFO, info->data, ++ info->length) != 1 || ++ EVP_KDF_derive(ctx, (unsigned char *)out, out_len) != 1) ++ goto done; ++ ++ ret = 0; ++done: ++ EVP_KDF_CTX_free(ctx); ++ return ret; ++} ++#else ++/* ++ * Generate a key using the KDF described in RFC 8636, also known as SSKDF ++ * (single-step kdf). Our caller precomputes `reps`, but otherwise the ++ * algorithm is as follows: + * + * 1. reps = keydatalen (K) / hash length (H) + * +@@ -2349,95 +2396,16 @@ pkinit_alg_values(krb5_context context, + * + * 4. Set key = Hash1 || Hash2 || ... so that length of key is K bytes. + */ +-krb5_error_code +-pkinit_alg_agility_kdf(krb5_context context, +- krb5_data *secret, +- krb5_data *alg_oid, +- krb5_const_principal party_u_info, +- krb5_const_principal party_v_info, +- krb5_enctype enctype, +- krb5_data *as_req, +- krb5_data *pk_as_rep, +- krb5_keyblock *key_block) ++static krb5_error_code ++builtin_sskdf(krb5_context context, unsigned int reps, size_t hash_len, ++ const EVP_MD *(*EVP_func)(void), krb5_data *secret, ++ krb5_data *other_info, char *out, size_t out_len) + { + krb5_error_code retval = 0; + +- unsigned int reps = 0; +- uint32_t counter = 1; /* Does this type work on Windows? */ ++ uint32_t counter = 1; + size_t offset = 0; +- size_t hash_len = 0; +- size_t rand_len = 0; +- size_t key_len = 0; +- krb5_data random_data; +- krb5_sp80056a_other_info other_info_fields; +- krb5_pkinit_supp_pub_info supp_pub_info_fields; +- krb5_data *other_info = NULL; +- krb5_data *supp_pub_info = NULL; +- krb5_algorithm_identifier alg_id; + EVP_MD_CTX *ctx = NULL; +- const EVP_MD *(*EVP_func)(void); +- +- /* initialize random_data here to make clean-up safe */ +- random_data.length = 0; +- random_data.data = NULL; +- +- /* allocate and initialize the key block */ +- key_block->magic = 0; +- key_block->enctype = enctype; +- if (0 != (retval = krb5_c_keylengths(context, enctype, &rand_len, +- &key_len))) +- goto cleanup; +- +- random_data.length = rand_len; +- key_block->length = key_len; +- +- if (NULL == (key_block->contents = malloc(key_block->length))) { +- retval = ENOMEM; +- goto cleanup; +- } +- +- memset (key_block->contents, 0, key_block->length); +- +- /* If this is anonymous pkinit, use the anonymous principle for party_u_info */ +- if (party_u_info && krb5_principal_compare_any_realm(context, party_u_info, +- krb5_anonymous_principal())) +- party_u_info = (krb5_principal)krb5_anonymous_principal(); +- +- if (0 != (retval = pkinit_alg_values(context, alg_oid, &hash_len, &EVP_func))) +- goto cleanup; +- +- /* 1. reps = keydatalen (K) / hash length (H) */ +- reps = key_block->length/hash_len; +- +- /* ... and round up, if necessary */ +- if (key_block->length > (reps * hash_len)) +- reps++; +- +- /* Allocate enough space in the random data buffer to hash directly into +- * it, even if the last hash will make it bigger than the key length. */ +- if (NULL == (random_data.data = malloc(reps * hash_len))) { +- retval = ENOMEM; +- goto cleanup; +- } +- +- /* Encode the ASN.1 octet string for "SuppPubInfo" */ +- supp_pub_info_fields.enctype = enctype; +- supp_pub_info_fields.as_req = *as_req; +- supp_pub_info_fields.pk_as_rep = *pk_as_rep; +- if (0 != ((retval = encode_krb5_pkinit_supp_pub_info(&supp_pub_info_fields, +- &supp_pub_info)))) +- goto cleanup; +- +- /* Now encode the ASN.1 octet string for "OtherInfo" */ +- memset(&alg_id, 0, sizeof alg_id); +- alg_id.algorithm = *alg_oid; /*alias*/ +- +- other_info_fields.algorithm_identifier = alg_id; +- other_info_fields.party_u_info = (krb5_principal) party_u_info; +- other_info_fields.party_v_info = (krb5_principal) party_v_info; +- other_info_fields.supp_pub_info = *supp_pub_info; +- if (0 != (retval = encode_krb5_sp80056a_other_info(&other_info_fields, &other_info))) +- goto cleanup; + + /* 2. Initialize a 32-bit, big-endian bit string counter as 1. + * 3. For i = 1 to reps by 1, do the following: +@@ -2471,8 +2439,9 @@ pkinit_alg_agility_kdf(krb5_context context, + goto cleanup; + } + +- /* 4. Set key = Hash1 || Hash2 || ... so that length of key is K bytes. */ +- if (!EVP_DigestFinal(ctx, (uint8_t *)random_data.data + offset, &s)) { ++ /* 4. Set key = Hash1 || Hash2 || ... so that length of key is K ++ * bytes. */ ++ if (!EVP_DigestFinal(ctx, (unsigned char *)out + offset, &s)) { + krb5_set_error_message(context, KRB5_CRYPTO_INTERNAL, + "Call to OpenSSL EVP_DigestUpdate() returned an error."); + retval = KRB5_CRYPTO_INTERNAL; +@@ -2484,26 +2453,110 @@ pkinit_alg_agility_kdf(krb5_context context, + EVP_MD_CTX_free(ctx); + ctx = NULL; + } +- +- retval = krb5_c_random_to_key(context, enctype, &random_data, +- key_block); +- + cleanup: + EVP_MD_CTX_free(ctx); ++ return retval; ++} /* builtin_sskdf() */ ++#endif /* OSSL_KDFS */ + +- /* If this has been an error, free the allocated key_block, if any */ +- if (retval) { +- krb5_free_keyblock_contents(context, key_block); ++/* id-pkinit-kdf family, as specified by RFC 8636. */ ++krb5_error_code ++pkinit_alg_agility_kdf(krb5_context context, krb5_data *secret, ++ krb5_data *alg_oid, krb5_const_principal party_u_info, ++ krb5_const_principal party_v_info, ++ krb5_enctype enctype, krb5_data *as_req, ++ krb5_data *pk_as_rep, krb5_keyblock *key_block) ++{ ++ krb5_error_code retval; ++ size_t hash_len = 0, rand_len = 0, key_len = 0; ++ const EVP_MD *(*EVP_func)(void); ++ krb5_sp80056a_other_info other_info_fields; ++ krb5_pkinit_supp_pub_info supp_pub_info_fields; ++ krb5_data *other_info = NULL, *supp_pub_info = NULL; ++ krb5_data random_data = empty_data(); ++ krb5_algorithm_identifier alg_id; ++ unsigned int reps; ++ ++ /* Allocate and initialize the key block. */ ++ key_block->magic = 0; ++ key_block->enctype = enctype; ++ ++ /* Use separate variables to avoid alignment restriction problems. */ ++ retval = krb5_c_keylengths(context, enctype, &rand_len, &key_len); ++ if (retval) ++ goto cleanup; ++ random_data.length = rand_len; ++ key_block->length = key_len; ++ ++ key_block->contents = k5calloc(key_block->length, 1, &retval); ++ if (key_block->contents == NULL) ++ goto cleanup; ++ ++ /* If this is anonymous pkinit, use the anonymous principle for ++ * party_u_info. */ ++ if (party_u_info && ++ krb5_principal_compare_any_realm(context, party_u_info, ++ krb5_anonymous_principal())) { ++ party_u_info = (krb5_principal)krb5_anonymous_principal(); + } + +- /* free other allocated resources, either way */ +- if (random_data.data) +- free(random_data.data); ++ retval = pkinit_alg_values(context, alg_oid, &hash_len, &EVP_func); ++ if (retval) ++ goto cleanup; ++ ++ /* 1. reps = keydatalen (K) / hash length (H) */ ++ reps = key_block->length / hash_len; ++ ++ /* ... and round up, if necessary. */ ++ if (key_block->length > (reps * hash_len)) ++ reps++; ++ ++ /* Allocate enough space in the random data buffer to hash directly into ++ * it, even if the last hash will make it bigger than the key length. */ ++ random_data.data = k5alloc(reps * hash_len, &retval); ++ if (random_data.data == NULL) ++ goto cleanup; ++ ++ /* Encode the ASN.1 octet string for "SuppPubInfo". */ ++ supp_pub_info_fields.enctype = enctype; ++ supp_pub_info_fields.as_req = *as_req; ++ supp_pub_info_fields.pk_as_rep = *pk_as_rep; ++ retval = encode_krb5_pkinit_supp_pub_info(&supp_pub_info_fields, ++ &supp_pub_info); ++ if (retval) ++ goto cleanup; ++ ++ /* Now encode the ASN.1 octet string for "OtherInfo". */ ++ memset(&alg_id, 0, sizeof(alg_id)); ++ alg_id.algorithm = *alg_oid; ++ other_info_fields.algorithm_identifier = alg_id; ++ other_info_fields.party_u_info = (krb5_principal)party_u_info; ++ other_info_fields.party_v_info = (krb5_principal)party_v_info; ++ other_info_fields.supp_pub_info = *supp_pub_info; ++ retval = encode_krb5_sp80056a_other_info(&other_info_fields, &other_info); ++ if (retval) ++ goto cleanup; ++ ++#ifdef OSSL_KDFS ++ retval = openssl_sskdf(context, hash_len, secret, other_info, ++ random_data.data, key_block->length); ++#else ++ retval = builtin_sskdf(context, reps, hash_len, EVP_func, secret, ++ other_info, random_data.data, key_block->length); ++#endif ++ if (retval) ++ goto cleanup; ++ ++ retval = krb5_c_random_to_key(context, enctype, &random_data, key_block); ++cleanup: ++ if (retval) ++ krb5_free_keyblock_contents(context, key_block); ++ ++ zapfree(random_data.data, random_data.length); + krb5_free_data(context, other_info); + krb5_free_data(context, supp_pub_info); +- + return retval; +-} /*pkinit_alg_agility_kdf() */ ++} + + /* Call DH_compute_key() and ensure that we left-pad short results instead of + * leaving junk bytes at the end of the buffer. */ diff --git a/root/ppg/common/deps/libssh/obs/_service b/root/ppg/common/deps/libssh/obs/_service new file mode 100644 index 00000000..32526e6b --- /dev/null +++ b/root/ppg/common/deps/libssh/obs/_service @@ -0,0 +1,8 @@ + + + www.libssh.org + https + /files/0.9/libssh-0.9.6.tar.xz + libssh-0.9.6.tar.xz + + diff --git a/root/ppg/common/deps/libssh/package.yaml b/root/ppg/common/deps/libssh/package.yaml new file mode 100644 index 00000000..0c6b44a7 --- /dev/null +++ b/root/ppg/common/deps/libssh/package.yaml @@ -0,0 +1,27 @@ +title: libssh rebuilt with libgcrypt backend for tarball portability +description: | + Rebuild of the Rocky Linux 8 libssh source package with + -DWITH_GCRYPT=ON (libgcrypt crypto backend) instead of OpenSSL, for + the EL8-built (ssl1.1) binary tarball. Red Hat's libssh.so.4 links + against Red Hat's OpenSSL 1.1.1 fork and needs symbol version nodes + (e.g. EVP_KDF_ctrl@OPENSSL_1_1_1b) that exist only in RHEL-family + libcrypto.so.1.1, so the bundled library fails to load on stock + OpenSSL 1.1 hosts (e.g. Debian 11). With the gcrypt backend libssh + has no OpenSSL dependency at all. Binary package names are identical + to the distro's; the Release carries a .percona suffix so this EVR + wins resolution. RockyLinux_8 only — every other repository uses the + distro libssh. + +build: + RockyLinux_9: false + RockyLinux_10: false + UBI_8: false + UBI_9: false + Debian_11: false + Debian_12: false + Debian_13: false + Ubuntu_22.04: false + Ubuntu_24.04: false + Ubuntu_26.04: false + openSUSE_Leap_16: false + openSUSE_Tumbleweed: false diff --git a/root/ppg/common/deps/libssh/rpm/CVE-2023-48795.patch b/root/ppg/common/deps/libssh/rpm/CVE-2023-48795.patch new file mode 100644 index 00000000..9ff6031d --- /dev/null +++ b/root/ppg/common/deps/libssh/rpm/CVE-2023-48795.patch @@ -0,0 +1,723 @@ +From 87b93be5a2071be782aa84aa5a91544b18959d5e Mon Sep 17 00:00:00 2001 +From: Aris Adamantiadis +Date: Tue, 12 Dec 2023 23:09:57 +0100 +Subject: [PATCH 1/4] CVE-2023-48795: client side mitigation + +Signed-off-by: Aris Adamantiadis +Signed-off-by: Jakub Jelen +Reviewed-by: Andreas Schneider +--- + include/libssh/packet.h | 1 + + include/libssh/session.h | 6 +++++ + src/curve25519.c | 19 +++---------- + src/dh-gex.c | 7 +---- + src/dh.c | 17 +++--------- + src/ecdh.c | 8 +----- + src/ecdh_crypto.c | 12 +++------ + src/ecdh_gcrypt.c | 10 +++---- + src/ecdh_mbedcrypto.c | 11 +++----- + src/kex.c | 34 +++++++++++++++++++---- + src/packet.c | 58 ++++++++++++++++++++++++++++++++++++++++ + src/packet_cb.c | 12 +++++++++ + 12 files changed, 126 insertions(+), 69 deletions(-) + +diff --git a/include/libssh/packet.h b/include/libssh/packet.h +index 561bba8e..c6fbc3fc 100644 +--- a/include/libssh/packet.h ++++ b/include/libssh/packet.h +@@ -63,6 +63,7 @@ SSH_PACKET_CALLBACK(ssh_packet_ext_info); + SSH_PACKET_CALLBACK(ssh_packet_kexdh_init); + #endif + ++int ssh_packet_send_newkeys(ssh_session session); + int ssh_packet_send_unimplemented(ssh_session session, uint32_t seqnum); + int ssh_packet_parse_type(ssh_session session); + //int packet_flush(ssh_session session, int enforce_blocking); +diff --git a/include/libssh/session.h b/include/libssh/session.h +index 64e118ef..3cde0dd4 100644 +--- a/include/libssh/session.h ++++ b/include/libssh/session.h +@@ -80,6 +80,12 @@ enum ssh_pending_call_e { + * sending it twice during key exchange to simplify the state machine. */ + #define SSH_SESSION_FLAG_KEXINIT_SENT 4 + ++/* The current SSH2 session implements the "strict KEX" feature and should behave ++ * differently on SSH2_MSG_NEWKEYS. */ ++#define SSH_SESSION_FLAG_KEX_STRICT 0x0010 ++/* Unexpected packets have been sent while the session was still unencrypted */ ++#define SSH_SESSION_FLAG_KEX_TAINTED 0x0020 ++ + /* codes to use with ssh_handle_packets*() */ + /* Infinite timeout */ + #define SSH_TIMEOUT_INFINITE -1 +diff --git a/src/curve25519.c b/src/curve25519.c +index 37654438..6b7b4238 100644 +--- a/src/curve25519.c ++++ b/src/curve25519.c +@@ -335,16 +335,10 @@ static SSH_PACKET_CALLBACK(ssh_packet_client_curve25519_reply){ + } + + /* Send the MSG_NEWKEYS */ +- if (ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) { +- goto error; +- } +- +- rc=ssh_packet_send(session); ++ rc = ssh_packet_send_newkeys(session); + if (rc == SSH_ERROR) { + goto error; + } +- +- SSH_LOG(SSH_LOG_DEBUG, "SSH_MSG_NEWKEYS sent"); + session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; + + return SSH_PACKET_USED; +@@ -502,18 +496,13 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init){ + return SSH_ERROR; + } + +- /* Send the MSG_NEWKEYS */ +- rc = ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS); +- if (rc < 0) { +- goto error; +- } +- + session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; +- rc = ssh_packet_send(session); ++ ++ /* Send the MSG_NEWKEYS */ ++ rc = ssh_packet_send_newkeys(session); + if (rc == SSH_ERROR) { + goto error; + } +- SSH_LOG(SSH_LOG_DEBUG, "SSH_MSG_NEWKEYS sent"); + + return SSH_PACKET_USED; + error: +diff --git a/src/dh-gex.c b/src/dh-gex.c +index 4a298542..f1880270 100644 +--- a/src/dh-gex.c ++++ b/src/dh-gex.c +@@ -287,15 +287,10 @@ static SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_reply) + } + + /* Send the MSG_NEWKEYS */ +- if (ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) { +- goto error; +- } +- +- rc = ssh_packet_send(session); ++ rc = ssh_packet_send_newkeys(session); + if (rc == SSH_ERROR) { + goto error; + } +- SSH_LOG(SSH_LOG_DEBUG, "SSH_MSG_NEWKEYS sent"); + session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; + + return SSH_PACKET_USED; +diff --git a/src/dh.c b/src/dh.c +index c265efcb..1d519c63 100644 +--- a/src/dh.c ++++ b/src/dh.c +@@ -386,16 +386,10 @@ SSH_PACKET_CALLBACK(ssh_packet_client_dh_reply){ + } + + /* Send the MSG_NEWKEYS */ +- if (ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) { +- goto error; +- } +- +- rc=ssh_packet_send(session); ++ rc = ssh_packet_send_newkeys(session); + if (rc == SSH_ERROR) { + goto error; + } +- +- SSH_LOG(SSH_LOG_DEBUG, "SSH_MSG_NEWKEYS sent"); + session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; + return SSH_PACKET_USED; + error: +@@ -532,15 +526,12 @@ int ssh_server_dh_process_init(ssh_session session, ssh_buffer packet) + } + SSH_LOG(SSH_LOG_DEBUG, "Sent KEX_DH_[GEX]_REPLY"); + +- if (ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) { +- ssh_buffer_reinit(session->out_buffer); +- goto error; +- } + session->dh_handshake_state=DH_STATE_NEWKEYS_SENT; +- if (ssh_packet_send(session) == SSH_ERROR) { ++ /* Send the MSG_NEWKEYS */ ++ rc = ssh_packet_send_newkeys(session); ++ if (rc == SSH_ERROR) { + goto error; + } +- SSH_LOG(SSH_LOG_PACKET, "SSH_MSG_NEWKEYS sent"); + + return SSH_OK; + error: +diff --git a/src/ecdh.c b/src/ecdh.c +index e5b11ba9..af80beec 100644 +--- a/src/ecdh.c ++++ b/src/ecdh.c +@@ -93,16 +93,10 @@ SSH_PACKET_CALLBACK(ssh_packet_client_ecdh_reply){ + } + + /* Send the MSG_NEWKEYS */ +- if (ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) { +- goto error; +- } +- +- rc=ssh_packet_send(session); ++ rc = ssh_packet_send_newkeys(session); + if (rc == SSH_ERROR) { + goto error; + } +- +- SSH_LOG(SSH_LOG_DEBUG, "SSH_MSG_NEWKEYS sent"); + session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; + + return SSH_PACKET_USED; +diff --git a/src/ecdh_crypto.c b/src/ecdh_crypto.c +index a1de27fd..62578c1b 100644 +--- a/src/ecdh_crypto.c ++++ b/src/ecdh_crypto.c +@@ -323,18 +323,12 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){ + goto error; + } + +- /* Send the MSG_NEWKEYS */ +- rc = ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS); +- if (rc < 0) { +- goto error; +- } +- + session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; +- rc = ssh_packet_send(session); +- if (rc == SSH_ERROR){ ++ /* Send the MSG_NEWKEYS */ ++ rc = ssh_packet_send_newkeys(session); ++ if (rc == SSH_ERROR) { + goto error; + } +- SSH_LOG(SSH_LOG_DEBUG, "SSH_MSG_NEWKEYS sent"); + + return SSH_PACKET_USED; + error: +diff --git a/src/ecdh_gcrypt.c b/src/ecdh_gcrypt.c +index d9c41bf9..dd4332d7 100644 +--- a/src/ecdh_gcrypt.c ++++ b/src/ecdh_gcrypt.c +@@ -372,17 +372,13 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){ + goto out; + } + +- ++ session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; + /* Send the MSG_NEWKEYS */ +- rc = ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS); +- if (rc != SSH_OK) { ++ rc = ssh_packet_send_newkeys(session); ++ if (rc == SSH_ERROR) { + goto out; + } + +- session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; +- rc = ssh_packet_send(session); +- SSH_LOG(SSH_LOG_DEBUG, "SSH_MSG_NEWKEYS sent"); +- + out: + gcry_sexp_release(param); + gcry_sexp_release(key); +diff --git a/src/ecdh_mbedcrypto.c b/src/ecdh_mbedcrypto.c +index 718f1522..45251a42 100644 +--- a/src/ecdh_mbedcrypto.c ++++ b/src/ecdh_mbedcrypto.c +@@ -300,16 +300,13 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){ + goto out; + } + +- rc = ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS); +- if (rc < 0) { +- rc = SSH_ERROR; ++ session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; ++ /* Send the MSG_NEWKEYS */ ++ rc = ssh_packet_send_newkeys(session); ++ if (rc == SSH_ERROR) { + goto out; + } + +- session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; +- rc = ssh_packet_send(session); +- SSH_LOG(SSH_LOG_DEBUG, "SSH_MSG_NEWKEYS sent"); +- + out: + mbedtls_ecp_group_free(&grp); + if (rc == SSH_ERROR) { +diff --git a/src/kex.c b/src/kex.c +index 3e5ca6ad..0772cae8 100644 +--- a/src/kex.c ++++ b/src/kex.c +@@ -163,6 +163,9 @@ + + /* RFC 8308 */ + #define KEX_EXTENSION_CLIENT "ext-info-c" ++/* Strict kex mitigation against CVE-2023-48795 */ ++#define KEX_STRICT_CLIENT "kex-strict-c-v00@openssh.com" ++#define KEX_STRICT_SERVER "kex-strict-s-v00@openssh.com" + + /* Allowed algorithms in FIPS mode */ + #define FIPS_ALLOWED_CIPHERS "aes256-gcm@openssh.com,"\ +@@ -491,6 +494,27 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit) + session->first_kex_follows_guess_wrong ? "wrong" : "right"); + } + ++ /* ++ * handle the "strict KEX" feature. If supported by peer, then set up the ++ * flag and verify packet sequence numbers. ++ */ ++ if (server_kex) { ++ ok = ssh_match_group(crypto->client_kex.methods[SSH_KEX], ++ KEX_STRICT_CLIENT); ++ if (ok) { ++ SSH_LOG(SSH_LOG_DEBUG, "Client supports strict kex, enabling."); ++ session->flags |= SSH_SESSION_FLAG_KEX_STRICT; ++ } ++ } else { ++ /* client kex */ ++ ok = ssh_match_group(crypto->server_kex.methods[SSH_KEX], ++ KEX_STRICT_SERVER); ++ if (ok) { ++ SSH_LOG(SSH_LOG_DEBUG, "Server supports strict kex, enabling."); ++ session->flags |= SSH_SESSION_FLAG_KEX_STRICT; ++ } ++ } ++ + if (server_kex) { + /* + * If client sent a ext-info-c message in the kex list, it supports +@@ -767,21 +791,21 @@ int ssh_set_client_kex(ssh_session session) + return SSH_OK; + } + +- /* Here we append ext-info-c to the list of kex algorithms */ ++ /* Here we append ext-info-c and kex-strict-c-v00@openssh.com to the list of kex algorithms */ + kex = client->methods[SSH_KEX]; + len = strlen(kex); +- if (len + strlen(KEX_EXTENSION_CLIENT) + 2 < len) { ++ /* Comma, comma, nul byte */ ++ kex_len = len + 1 + strlen(KEX_EXTENSION_CLIENT) + 1 + strlen(KEX_STRICT_CLIENT ) + 1; ++ if (kex_len >= MAX_PACKET_LEN) { + /* Overflow */ + return SSH_ERROR; + } +- kex_len = len + strlen(KEX_EXTENSION_CLIENT) + 2; /* comma, NULL */ + kex_tmp = realloc(kex, kex_len); + if (kex_tmp == NULL) { +- free(kex); + ssh_set_error_oom(session); + return SSH_ERROR; + } +- snprintf(kex_tmp + len, kex_len - len, ",%s", KEX_EXTENSION_CLIENT); ++ snprintf(kex_tmp + len, kex_len - len, ",%s,%s", KEX_EXTENSION_CLIENT, KEX_STRICT_CLIENT); + client->methods[SSH_KEX] = kex_tmp; + + return SSH_OK; +diff --git a/src/packet.c b/src/packet.c +index ca7a03b7..82965fb3 100644 +--- a/src/packet.c ++++ b/src/packet.c +@@ -1309,6 +1309,19 @@ int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user) + } + #endif /* WITH_ZLIB */ + payloadsize = ssh_buffer_get_len(session->in_buffer); ++ if (session->recv_seq == UINT32_MAX) { ++ /* Overflowing sequence numbers is always fishy */ ++ if (crypto == NULL) { ++ /* don't allow sequence number overflow when unencrypted */ ++ ssh_set_error(session, ++ SSH_FATAL, ++ "Incoming sequence number overflow"); ++ goto error; ++ } else { ++ SSH_LOG(SSH_LOG_WARNING, ++ "Incoming sequence number overflow"); ++ } ++ } + session->recv_seq++; + if (crypto != NULL) { + struct ssh_cipher_struct *cipher = NULL; +@@ -1331,7 +1344,19 @@ int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user) + SSH_LOG(SSH_LOG_PACKET, + "packet: read type %hhd [len=%d,padding=%hhd,comp=%d,payload=%d]", + session->in_packet.type, packet_len, padding, compsize, payloadsize); ++ if (crypto == NULL) { ++ /* In strict kex, only a few packets are allowed. Taint the session ++ * if we received packets that are normally allowed but to be ++ * refused if we are in strict kex when KEX is over. ++ */ ++ uint8_t type = session->in_packet.type; + ++ if (type != SSH2_MSG_KEXINIT && type != SSH2_MSG_NEWKEYS && ++ (type < SSH2_MSG_KEXDH_INIT || ++ type > SSH2_MSG_KEX_DH_GEX_REQUEST)) { ++ session->flags |= SSH_SESSION_FLAG_KEX_TAINTED; ++ } ++ } + /* Check if the packet is expected */ + filter_result = ssh_packet_incoming_filter(session); + +@@ -1347,6 +1372,9 @@ int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user) + session->in_packet.type); + goto error; + case SSH_PACKET_UNKNOWN: ++ if (crypto == NULL) { ++ session->flags |= SSH_SESSION_FLAG_KEX_TAINTED; ++ } + ssh_packet_send_unimplemented(session, session->recv_seq - 1); + break; + } +@@ -1521,7 +1549,33 @@ void ssh_packet_process(ssh_session session, uint8_t type) + SSH_LOG(SSH_LOG_RARE, "Failed to send unimplemented: %s", + ssh_get_error(session)); + } ++ if (session->current_crypto == NULL) { ++ session->flags |= SSH_SESSION_FLAG_KEX_TAINTED; ++ } ++ } ++} ++ ++/** @internal ++ * @brief sends a SSH_MSG_NEWKEYS when enabling the new negotiated ciphers ++ * @param session the SSH session ++ * @return SSH_ERROR on error, else SSH_OK ++ */ ++int ssh_packet_send_newkeys(ssh_session session) ++{ ++ int rc; ++ ++ /* Send the MSG_NEWKEYS */ ++ rc = ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS); ++ if (rc < 0) { ++ return rc; + } ++ ++ rc = ssh_packet_send(session); ++ if (rc == SSH_ERROR) { ++ return rc; ++ } ++ SSH_LOG(SSH_LOG_DEBUG, "SSH_MSG_NEWKEYS sent"); ++ return rc; + } + + /** @internal +@@ -1829,6 +1883,10 @@ int ssh_packet_send(ssh_session session) + if (rc == SSH_OK && type == SSH2_MSG_NEWKEYS) { + struct ssh_iterator *it; + ++ if (session->flags & SSH_SESSION_FLAG_KEX_STRICT) { ++ /* reset packet sequence number when running in strict kex mode */ ++ session->send_seq = 0; ++ } + for (it = ssh_list_get_iterator(session->out_queue); + it != NULL; + it = ssh_list_get_iterator(session->out_queue)) { +diff --git a/src/packet_cb.c b/src/packet_cb.c +index 3e4d5f6d..a08f1d8a 100644 +--- a/src/packet_cb.c ++++ b/src/packet_cb.c +@@ -110,6 +110,18 @@ SSH_PACKET_CALLBACK(ssh_packet_newkeys){ + goto error; + } + ++ if (session->flags & SSH_SESSION_FLAG_KEX_STRICT) { ++ /* reset packet sequence number when running in strict kex mode */ ++ session->recv_seq = 0; ++ /* Check that we aren't tainted */ ++ if (session->flags & SSH_SESSION_FLAG_KEX_TAINTED) { ++ ssh_set_error(session, ++ SSH_FATAL, ++ "Received unexpected packets in strict KEX mode."); ++ goto error; ++ } ++ } ++ + if(session->server){ + /* server things are done in server.c */ + session->dh_handshake_state=DH_STATE_FINISHED; +-- +2.41.0 + + +From fd4948255560039b51c2d61f0a62784ed8b6f5a6 Mon Sep 17 00:00:00 2001 +From: Aris Adamantiadis +Date: Tue, 12 Dec 2023 23:30:26 +0100 +Subject: [PATCH 2/4] CVE-2023-48795: Server side mitigations + +Signed-off-by: Aris Adamantiadis +Signed-off-by: Jakub Jelen +Reviewed-by: Andreas Schneider +--- + include/libssh/kex.h | 1 + + src/kex.c | 46 ++++++++++++++++++++++++++++++++++---------- + src/server.c | 8 +++++++- + 3 files changed, 44 insertions(+), 11 deletions(-) + +diff --git a/include/libssh/kex.h b/include/libssh/kex.h +index 2ace69b6..40da4ef2 100644 +--- a/include/libssh/kex.h ++++ b/include/libssh/kex.h +@@ -36,6 +36,7 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit); + int ssh_send_kex(ssh_session session); + void ssh_list_kex(struct ssh_kex_struct *kex); + int ssh_set_client_kex(ssh_session session); ++int ssh_kex_append_extensions(ssh_session session, struct ssh_kex_struct *pkex); + int ssh_kex_select_methods(ssh_session session); + int ssh_verify_existing_algo(enum ssh_kex_types_e algo, const char *name); + char *ssh_keep_known_algos(enum ssh_kex_types_e algo, const char *list); +diff --git a/src/kex.c b/src/kex.c +index 0772cae8..e37c176c 100644 +--- a/src/kex.c ++++ b/src/kex.c +@@ -738,11 +738,8 @@ int ssh_set_client_kex(ssh_session session) + { + struct ssh_kex_struct *client = &session->next_crypto->client_kex; + const char *wanted; +- char *kex = NULL; +- char *kex_tmp = NULL; + int ok; + int i; +- size_t kex_len, len; + + /* Skip if already set, for example for the rekey or when we do the guessing + * it could have been already used to make some protocol decisions. */ +@@ -791,11 +788,33 @@ int ssh_set_client_kex(ssh_session session) + return SSH_OK; + } + +- /* Here we append ext-info-c and kex-strict-c-v00@openssh.com to the list of kex algorithms */ +- kex = client->methods[SSH_KEX]; ++ ok = ssh_kex_append_extensions(session, client); ++ if (ok != SSH_OK){ ++ return ok; ++ } ++ ++ return SSH_OK; ++} ++ ++int ssh_kex_append_extensions(ssh_session session, struct ssh_kex_struct *pkex) ++{ ++ char *kex = NULL; ++ char *kex_tmp = NULL; ++ size_t kex_len, len; ++ ++ /* Here we append ext-info-c and kex-strict-c-v00@openssh.com for client ++ * and kex-strict-s-v00@openssh.com for server to the list of kex algorithms ++ */ ++ kex = pkex->methods[SSH_KEX]; + len = strlen(kex); +- /* Comma, comma, nul byte */ +- kex_len = len + 1 + strlen(KEX_EXTENSION_CLIENT) + 1 + strlen(KEX_STRICT_CLIENT ) + 1; ++ if (session->server) { ++ /* Comma, nul byte */ ++ kex_len = len + 1 + strlen(KEX_STRICT_SERVER) + 1; ++ } else { ++ /* Comma, comma, nul byte */ ++ kex_len = len + 1 + strlen(KEX_EXTENSION_CLIENT) + 1 + ++ strlen(KEX_STRICT_CLIENT) + 1; ++ } + if (kex_len >= MAX_PACKET_LEN) { + /* Overflow */ + return SSH_ERROR; +@@ -805,9 +824,16 @@ int ssh_set_client_kex(ssh_session session) + ssh_set_error_oom(session); + return SSH_ERROR; + } +- snprintf(kex_tmp + len, kex_len - len, ",%s,%s", KEX_EXTENSION_CLIENT, KEX_STRICT_CLIENT); +- client->methods[SSH_KEX] = kex_tmp; +- ++ if (session->server){ ++ snprintf(kex_tmp + len, kex_len - len, ",%s", KEX_STRICT_SERVER); ++ } else { ++ snprintf(kex_tmp + len, ++ kex_len - len, ++ ",%s,%s", ++ KEX_EXTENSION_CLIENT, ++ KEX_STRICT_CLIENT); ++ } ++ pkex->methods[SSH_KEX] = kex_tmp; + return SSH_OK; + } + +diff --git a/src/server.c b/src/server.c +index ed73e7fb..35e84465 100644 +--- a/src/server.c ++++ b/src/server.c +@@ -195,7 +195,13 @@ int server_set_kex(ssh_session session) + } + } + +- return 0; ++ /* Do not append the extensions during rekey */ ++ if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED) { ++ return SSH_OK; ++ } ++ ++ rc = ssh_kex_append_extensions(session, server); ++ return rc; + } + + int ssh_server_init_kex(ssh_session session) { +-- +2.41.0 + + +From 03bbbc9e4c93aae2ccdd302d6123e4809be37746 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Thu, 14 Dec 2023 12:22:01 +0100 +Subject: [PATCH 3/4] CVE-2023-48795: Strip extensions from both kex lists for + matching + +Signed-off-by: Jakub Jelen +Reviewed-by: Andreas Schneider +--- + src/kex.c | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +diff --git a/src/kex.c b/src/kex.c +index e37c176c..eea3604b 100644 +--- a/src/kex.c ++++ b/src/kex.c +@@ -936,11 +936,19 @@ int ssh_kex_select_methods (ssh_session session) + enum ssh_key_exchange_e kex_type; + int i; + +- /* Here we should drop the ext-info-c from the list so we avoid matching. ++ /* Here we should drop the extensions from the list so we avoid matching. + * it. We added it to the end, so we can just truncate the string here */ +- ext_start = strstr(client->methods[SSH_KEX], ","KEX_EXTENSION_CLIENT); +- if (ext_start != NULL) { +- ext_start[0] = '\0'; ++ if (session->client) { ++ ext_start = strstr(client->methods[SSH_KEX], "," KEX_EXTENSION_CLIENT); ++ if (ext_start != NULL) { ++ ext_start[0] = '\0'; ++ } ++ } ++ if (session->server) { ++ ext_start = strstr(server->methods[SSH_KEX], "," KEX_STRICT_SERVER); ++ if (ext_start != NULL) { ++ ext_start[0] = '\0'; ++ } + } + + for (i = 0; i < SSH_KEX_METHODS; i++) { +-- +2.41.0 + + +From 768d1ed30cf4b3cb9628254ef3ee24b9c38abdbc Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Thu, 14 Dec 2023 12:47:48 +0100 +Subject: [PATCH 4/4] CVE-2023-48795: tests: Adjust calculation to strict kex + +Signed-off-by: Jakub Jelen +Reviewed-by: Andreas Schneider +--- + tests/client/torture_rekey.c | 56 ++++++++++++++++++++---------------- + 1 file changed, 32 insertions(+), 24 deletions(-) + +diff --git a/tests/client/torture_rekey.c b/tests/client/torture_rekey.c +index 13c9a7fe..bfb273af 100644 +--- a/tests/client/torture_rekey.c ++++ b/tests/client/torture_rekey.c +@@ -148,6 +148,29 @@ static void torture_rekey_default(void **state) + ssh_disconnect(s->ssh.session); + } + ++static void sanity_check_session(void **state) ++{ ++ struct torture_state *s = *state; ++ struct ssh_crypto_struct *c = NULL; ++ ++ c = s->ssh.session->current_crypto; ++ assert_non_null(c); ++ assert_int_equal(c->in_cipher->max_blocks, ++ bytes / c->in_cipher->blocksize); ++ assert_int_equal(c->out_cipher->max_blocks, ++ bytes / c->out_cipher->blocksize); ++ /* when strict kex is used, the newkeys reset the sequence number */ ++ if ((s->ssh.session->flags & SSH_SESSION_FLAG_KEX_STRICT) != 0) { ++ assert_int_equal(c->out_cipher->packets, s->ssh.session->send_seq); ++ assert_int_equal(c->in_cipher->packets, s->ssh.session->recv_seq); ++ } else { ++ /* Otherwise we have less encrypted packets than transferred ++ * (first are not encrypted) */ ++ assert_true(c->out_cipher->packets < s->ssh.session->send_seq); ++ assert_true(c->in_cipher->packets < s->ssh.session->recv_seq); ++ } ++} ++ + /* We lower the rekey limits manually and check that the rekey + * really happens when sending data + */ +@@ -166,16 +189,10 @@ static void torture_rekey_send(void **state) + rc = ssh_connect(s->ssh.session); + assert_ssh_return_code(s->ssh.session, rc); + +- /* The blocks limit is set correctly */ +- c = s->ssh.session->current_crypto; +- assert_int_equal(c->in_cipher->max_blocks, +- bytes / c->in_cipher->blocksize); +- assert_int_equal(c->out_cipher->max_blocks, +- bytes / c->out_cipher->blocksize); +- /* We should have less encrypted packets than transfered (first are not encrypted) */ +- assert_true(c->out_cipher->packets < s->ssh.session->send_seq); +- assert_true(c->in_cipher->packets < s->ssh.session->recv_seq); ++ sanity_check_session(state); + /* Copy the initial secret hash = session_id so we know we changed keys later */ ++ c = s->ssh.session->current_crypto; ++ assert_non_null(c); + secret_hash = malloc(c->digest_len); + assert_non_null(secret_hash); + memcpy(secret_hash, c->secret_hash, c->digest_len); +@@ -272,14 +289,10 @@ static void torture_rekey_recv(void **state) + sftp_file file; + mode_t mask; + +- /* The blocks limit is set correctly */ +- c = s->ssh.session->current_crypto; +- assert_int_equal(c->in_cipher->max_blocks, bytes / c->in_cipher->blocksize); +- assert_int_equal(c->out_cipher->max_blocks, bytes / c->out_cipher->blocksize); +- /* We should have less encrypted packets than transfered (first are not encrypted) */ +- assert_true(c->out_cipher->packets < s->ssh.session->send_seq); +- assert_true(c->in_cipher->packets < s->ssh.session->recv_seq); ++ sanity_check_session(state); + /* Copy the initial secret hash = session_id so we know we changed keys later */ ++ c = s->ssh.session->current_crypto; ++ assert_non_null(c); + secret_hash = malloc(c->digest_len); + assert_non_null(secret_hash); + memcpy(secret_hash, c->secret_hash, c->digest_len); +@@ -464,15 +477,10 @@ static void torture_rekey_different_kex(void **state) + assert_ssh_return_code(s->ssh.session, rc); + + /* The blocks limit is set correctly */ +- c = s->ssh.session->current_crypto; +- assert_int_equal(c->in_cipher->max_blocks, +- bytes / c->in_cipher->blocksize); +- assert_int_equal(c->out_cipher->max_blocks, +- bytes / c->out_cipher->blocksize); +- /* We should have less encrypted packets than transfered (first are not encrypted) */ +- assert_true(c->out_cipher->packets < s->ssh.session->send_seq); +- assert_true(c->in_cipher->packets < s->ssh.session->recv_seq); ++ sanity_check_session(state); + /* Copy the initial secret hash = session_id so we know we changed keys later */ ++ c = s->ssh.session->current_crypto; ++ assert_non_null(c); + secret_hash = malloc(c->digest_len); + assert_non_null(secret_hash); + memcpy(secret_hash, c->secret_hash, c->digest_len); +-- +2.41.0 + diff --git a/root/ppg/common/deps/libssh/rpm/CVE-2023-6004.patch b/root/ppg/common/deps/libssh/rpm/CVE-2023-6004.patch new file mode 100644 index 00000000..27a72d68 --- /dev/null +++ b/root/ppg/common/deps/libssh/rpm/CVE-2023-6004.patch @@ -0,0 +1,1114 @@ +From 11bd6e6ad926a38cd7b9f8308a4c2fd8dfd9200c Mon Sep 17 00:00:00 2001 +From: Norbert Pocs +Date: Sun, 5 Nov 2023 13:12:47 +0100 +Subject: [PATCH 01/12] CVE-2023-6004: torture_config: Allow multiple '@' in + usernames + +Signed-off-by: Norbert Pocs +Reviewed-by: Andreas Schneider +--- + tests/unittests/torture_config.c | 44 ++++++++++++++++++-------------- + 1 file changed, 25 insertions(+), 19 deletions(-) + +diff --git a/tests/unittests/torture_config.c b/tests/unittests/torture_config.c +index f91112a9..3a5a74bf 100644 +--- a/tests/unittests/torture_config.c ++++ b/tests/unittests/torture_config.c +@@ -671,24 +671,40 @@ static void torture_config_proxyjump(void **state) { + assert_string_equal(session->opts.ProxyCommand, + "ssh -W [%h]:%p 2620:52:0::fed"); + +- /* Try to create some invalid configurations */ +- /* Non-numeric port */ ++ /* Multiple @ is allowed in second jump */ + torture_write_file(LIBSSH_TESTCONFIG11, +- "Host bad-port\n" +- "\tProxyJump jumpbox:22bad22\n" ++ "Host allowed-hostname\n" ++ "\tProxyJump localhost,user@principal.com@jumpbox:22\n" + ""); + torture_reset_config(session); +- ssh_options_set(session, SSH_OPTIONS_HOST, "bad-port"); ++ ssh_options_set(session, SSH_OPTIONS_HOST, "allowed-hostname"); + ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG11); +- assert_ssh_return_code_equal(session, ret, SSH_ERROR); ++ assert_ssh_return_code(session, ret); ++ assert_string_equal(session->opts.ProxyCommand, ++ "ssh -J user@principal.com@jumpbox:22 -W [%h]:%p localhost"); + +- /* Too many @ */ ++ /* Multiple @ is allowed */ + torture_write_file(LIBSSH_TESTCONFIG11, +- "Host bad-hostname\n" ++ "Host allowed-hostname\n" + "\tProxyJump user@principal.com@jumpbox:22\n" + ""); + torture_reset_config(session); +- ssh_options_set(session, SSH_OPTIONS_HOST, "bad-hostname"); ++ ssh_options_set(session, SSH_OPTIONS_HOST, "allowed-hostname"); ++ ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG11); ++ assert_ssh_return_code(session, ret); ++ assert_string_equal(session->opts.ProxyCommand, ++ "ssh -l user@principal.com -p 22 -W [%h]:%p jumpbox"); ++ ++ /* In this part, we try various other config files and strings. */ ++ ++ /* Try to create some invalid configurations */ ++ /* Non-numeric port */ ++ torture_write_file(LIBSSH_TESTCONFIG11, ++ "Host bad-port\n" ++ "\tProxyJump jumpbox:22bad22\n" ++ ""); ++ torture_reset_config(session); ++ ssh_options_set(session, SSH_OPTIONS_HOST, "bad-port"); + ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG11); + assert_ssh_return_code_equal(session, ret, SSH_ERROR); + +@@ -752,16 +768,6 @@ static void torture_config_proxyjump(void **state) { + ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG11); + assert_ssh_return_code_equal(session, ret, SSH_ERROR); + +- /* Too many @ in second jump */ +- torture_write_file(LIBSSH_TESTCONFIG11, +- "Host bad-hostname\n" +- "\tProxyJump localhost,user@principal.com@jumpbox:22\n" +- ""); +- torture_reset_config(session); +- ssh_options_set(session, SSH_OPTIONS_HOST, "bad-hostname"); +- ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG11); +- assert_ssh_return_code_equal(session, ret, SSH_ERROR); +- + /* Braces mismatch in second jump */ + torture_write_file(LIBSSH_TESTCONFIG11, + "Host mismatch\n" +-- +2.41.0 + + +From c3234e5f94b96d6e29f0c1c82821c1e3ebb181ed Mon Sep 17 00:00:00 2001 +From: Norbert Pocs +Date: Wed, 1 Nov 2023 11:24:43 +0100 +Subject: [PATCH 02/12] CVE-2023-6004: config_parser: Allow multiple '@' in + usernames + +Signed-off-by: Norbert Pocs +Reviewed-by: Andreas Schneider +--- + src/config_parser.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/config_parser.c b/src/config_parser.c +index ae2aa2c8..76cca224 100644 +--- a/src/config_parser.c ++++ b/src/config_parser.c +@@ -152,7 +152,7 @@ int ssh_config_parse_uri(const char *tok, + } + + /* Username part (optional) */ +- endp = strchr(tok, '@'); ++ endp = strrchr(tok, '@'); + if (endp != NULL) { + /* Zero-length username is not valid */ + if (tok == endp) { +-- +2.41.0 + + +From a5b8bd0d8841296cf71d927824d60f576581243f Mon Sep 17 00:00:00 2001 +From: Norbert Pocs +Date: Tue, 31 Oct 2023 09:48:52 +0100 +Subject: [PATCH 03/12] CVE-2023-6004: options: Simplify the hostname parsing + in ssh_options_set + +Using ssh_config_parse_uri can simplify the parsing of the host +parsing inside the function of ssh_options_set + +Signed-off-by: Norbert Pocs +Reviewed-by: Andreas Schneider +--- + src/options.c | 40 ++++++++++++++++------------------------ + 1 file changed, 16 insertions(+), 24 deletions(-) + +diff --git a/src/options.c b/src/options.c +index b5f951ac..7c03e7ab 100644 +--- a/src/options.c ++++ b/src/options.c +@@ -36,6 +36,7 @@ + #include "libssh/session.h" + #include "libssh/misc.h" + #include "libssh/options.h" ++#include "libssh/config_parser.h" + #ifdef WITH_SERVER + #include "libssh/server.h" + #include "libssh/bind.h" +@@ -490,33 +491,24 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type, + ssh_set_error_invalid(session); + return -1; + } else { +- q = strdup(value); +- if (q == NULL) { +- ssh_set_error_oom(session); ++ char *username = NULL, *hostname = NULL, *port = NULL; ++ rc = ssh_config_parse_uri(value, &username, &hostname, &port); ++ if (rc != SSH_OK) { + return -1; + } +- p = strchr(q, '@'); +- +- SAFE_FREE(session->opts.host); +- +- if (p) { +- *p = '\0'; +- session->opts.host = strdup(p + 1); +- if (session->opts.host == NULL) { +- SAFE_FREE(q); +- ssh_set_error_oom(session); +- return -1; +- } +- ++ if (port != NULL) { ++ SAFE_FREE(username); ++ SAFE_FREE(hostname); ++ SAFE_FREE(port); ++ return -1; ++ } ++ if (username != NULL) { + SAFE_FREE(session->opts.username); +- session->opts.username = strdup(q); +- SAFE_FREE(q); +- if (session->opts.username == NULL) { +- ssh_set_error_oom(session); +- return -1; +- } +- } else { +- session->opts.host = q; ++ session->opts.username = username; ++ } ++ if (hostname != NULL) { ++ SAFE_FREE(session->opts.host); ++ session->opts.host = hostname; + } + } + break; +-- +2.41.0 + + +From efb24b6472e8b87c5832c0590f14e99e82fcdeeb Mon Sep 17 00:00:00 2001 +From: Norbert Pocs +Date: Tue, 10 Oct 2023 12:44:16 +0200 +Subject: [PATCH 04/12] CVE-2023-6004: misc: Add function to check allowed + characters of a hostname + +The hostname can be a domain name or an ip address. The colon has to be +allowed because of IPv6 even it is prohibited in domain names. + +Signed-off-by: Norbert Pocs +Reviewed-by: Andreas Schneider +--- + include/libssh/misc.h | 2 ++ + src/misc.c | 68 +++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 70 insertions(+) + +diff --git a/include/libssh/misc.h b/include/libssh/misc.h +index 3cc3b113..a5bee930 100644 +--- a/include/libssh/misc.h ++++ b/include/libssh/misc.h +@@ -97,4 +97,6 @@ int ssh_mkdirs(const char *pathname, mode_t mode); + int ssh_quote_file_name(const char *file_name, char *buf, size_t buf_len); + int ssh_newline_vis(const char *string, char *buf, size_t buf_len); + ++int ssh_check_hostname_syntax(const char *hostname); ++ + #endif /* MISC_H_ */ +diff --git a/src/misc.c b/src/misc.c +index 149eb85e..e4239e81 100644 +--- a/src/misc.c ++++ b/src/misc.c +@@ -94,6 +94,8 @@ + #define ZLIB_STRING "" + #endif + ++#define ARPA_DOMAIN_MAX_LEN 63 ++ + /** + * @defgroup libssh_misc The SSH helper functions. + * @ingroup libssh +@@ -1734,4 +1736,70 @@ int ssh_newline_vis(const char *string, char *buf, size_t buf_len) + return out - buf; + } + ++/** ++ * @brief Checks syntax of a domain name ++ * ++ * The check is made based on the RFC1035 section 2.3.1 ++ * Allowed characters are: hyphen, period, digits (0-9) and letters (a-zA-Z) ++ * ++ * The label should be no longer than 63 characters ++ * The label should start with a letter and end with a letter or number ++ * The label in this implementation can start with a number to allow virtual ++ * URLs to pass. Note that this will make IPv4 addresses to pass ++ * this check too. ++ * ++ * @param hostname The domain name to be checked, has to be null terminated ++ * ++ * @return SSH_OK if the hostname passes syntax check ++ * SSH_ERROR otherwise or if hostname is NULL or empty string ++ */ ++int ssh_check_hostname_syntax(const char *hostname) ++{ ++ char *it = NULL, *s = NULL, *buf = NULL; ++ size_t it_len; ++ char c; ++ ++ if (hostname == NULL || strlen(hostname) == 0) { ++ return SSH_ERROR; ++ } ++ ++ /* strtok_r writes into the string, keep the input clean */ ++ s = strdup(hostname); ++ if (s == NULL) { ++ return SSH_ERROR; ++ } ++ ++ it = strtok_r(s, ".", &buf); ++ /* if the token has 0 length */ ++ if (it == NULL) { ++ free(s); ++ return SSH_ERROR; ++ } ++ do { ++ it_len = strlen(it); ++ if (it_len > ARPA_DOMAIN_MAX_LEN || ++ /* the first char must be a letter, but some virtual urls start ++ * with a number */ ++ isalnum(it[0]) == 0 || ++ isalnum(it[it_len - 1]) == 0) { ++ free(s); ++ return SSH_ERROR; ++ } ++ while (*it != '\0') { ++ c = *it; ++ /* the "." is allowed too, but tokenization removes it from the ++ * string */ ++ if (isalnum(c) == 0 && c != '-') { ++ free(s); ++ return SSH_ERROR; ++ } ++ it++; ++ } ++ } while ((it = strtok_r(NULL, ".", &buf)) != NULL); ++ ++ free(s); ++ ++ return SSH_OK; ++} ++ + /** @} */ +-- +2.41.0 + + +From 234ecdf4d9705efa3727a54dcc1ddfe6377c7bf6 Mon Sep 17 00:00:00 2001 +From: Norbert Pocs +Date: Tue, 10 Oct 2023 12:45:28 +0200 +Subject: [PATCH 05/12] CVE-2023-6004: torture_misc: Add test for + ssh_check_hostname_syntax + +Signed-off-by: Norbert Pocs +Reviewed-by: Andreas Schneider +--- + tests/unittests/torture_misc.c | 73 ++++++++++++++++++++++++++++++++++ + 1 file changed, 73 insertions(+) + +diff --git a/tests/unittests/torture_misc.c b/tests/unittests/torture_misc.c +index 0a48abbe..d14f4254 100644 +--- a/tests/unittests/torture_misc.c ++++ b/tests/unittests/torture_misc.c +@@ -656,6 +656,78 @@ static void torture_ssh_newline_vis(UNUSED_PARAM(void **state)) + assert_string_equal(buffer, "a\\nb\\n"); + } + ++static void torture_ssh_check_hostname_syntax(void **state) ++{ ++ int rc; ++ (void)state; ++ ++ rc = ssh_check_hostname_syntax("duckduckgo.com"); ++ assert_int_equal(rc, SSH_OK); ++ rc = ssh_check_hostname_syntax("www.libssh.org"); ++ assert_int_equal(rc, SSH_OK); ++ rc = ssh_check_hostname_syntax("Some-Thing.com"); ++ assert_int_equal(rc, SSH_OK); ++ rc = ssh_check_hostname_syntax("amazon.a23456789012345678901234567890123456789012345678901234567890123"); ++ assert_int_equal(rc, SSH_OK); ++ rc = ssh_check_hostname_syntax("amazon.a23456789012345678901234567890123456789012345678901234567890123.a23456789012345678901234567890123456789012345678901234567890123.ok"); ++ assert_int_equal(rc, SSH_OK); ++ rc = ssh_check_hostname_syntax("amazon.a23456789012345678901234567890123456789012345678901234567890123.a23456789012345678901234567890123456789012345678901234567890123.a23456789012345678901234567890123456789012345678901234567890123"); ++ assert_int_equal(rc, SSH_OK); ++ rc = ssh_check_hostname_syntax("lavabo-inter.innocentes-manus-meas"); ++ assert_int_equal(rc, SSH_OK); ++ rc = ssh_check_hostname_syntax("localhost"); ++ assert_int_equal(rc, SSH_OK); ++ rc = ssh_check_hostname_syntax("a"); ++ assert_int_equal(rc, SSH_OK); ++ rc = ssh_check_hostname_syntax("a-0.b-b"); ++ assert_int_equal(rc, SSH_OK); ++ rc = ssh_check_hostname_syntax("libssh."); ++ assert_int_equal(rc, SSH_OK); ++ ++ rc = ssh_check_hostname_syntax(NULL); ++ assert_int_equal(rc, SSH_ERROR); ++ rc = ssh_check_hostname_syntax(""); ++ assert_int_equal(rc, SSH_ERROR); ++ rc = ssh_check_hostname_syntax("/"); ++ assert_int_equal(rc, SSH_ERROR); ++ rc = ssh_check_hostname_syntax("@"); ++ assert_int_equal(rc, SSH_ERROR); ++ rc = ssh_check_hostname_syntax("["); ++ assert_int_equal(rc, SSH_ERROR); ++ rc = ssh_check_hostname_syntax("`"); ++ assert_int_equal(rc, SSH_ERROR); ++ rc = ssh_check_hostname_syntax("{"); ++ assert_int_equal(rc, SSH_ERROR); ++ rc = ssh_check_hostname_syntax("&"); ++ assert_int_equal(rc, SSH_ERROR); ++ rc = ssh_check_hostname_syntax("|"); ++ assert_int_equal(rc, SSH_ERROR); ++ rc = ssh_check_hostname_syntax("\""); ++ assert_int_equal(rc, SSH_ERROR); ++ rc = ssh_check_hostname_syntax("`"); ++ assert_int_equal(rc, SSH_ERROR); ++ rc = ssh_check_hostname_syntax(" "); ++ assert_int_equal(rc, SSH_ERROR); ++ rc = ssh_check_hostname_syntax("*the+giant&\"rooks\".c0m"); ++ assert_int_equal(rc, SSH_ERROR); ++ rc = ssh_check_hostname_syntax("!www.libssh.org"); ++ assert_int_equal(rc, SSH_ERROR); ++ rc = ssh_check_hostname_syntax("--.--"); ++ assert_int_equal(rc, SSH_ERROR); ++ rc = ssh_check_hostname_syntax("libssh.a234567890123456789012345678901234567890123456789012345678901234"); ++ assert_int_equal(rc, SSH_ERROR); ++ rc = ssh_check_hostname_syntax("libssh.a234567890123456789012345678901234567890123456789012345678901234.a234567890123456789012345678901234567890123456789012345678901234"); ++ assert_int_equal(rc, SSH_ERROR); ++ rc = ssh_check_hostname_syntax("libssh-"); ++ assert_int_equal(rc, SSH_ERROR); ++ rc = ssh_check_hostname_syntax("fe80::9656:d028:8652:66b6"); ++ assert_int_equal(rc, SSH_ERROR); ++ rc = ssh_check_hostname_syntax("."); ++ assert_int_equal(rc, SSH_ERROR); ++ rc = ssh_check_hostname_syntax(".."); ++ assert_int_equal(rc, SSH_ERROR); ++} ++ + int torture_run_tests(void) { + int rc; + struct CMUnitTest tests[] = { +@@ -678,6 +750,7 @@ int torture_run_tests(void) { + cmocka_unit_test(torture_ssh_newline_vis), + cmocka_unit_test(torture_ssh_mkdirs), + cmocka_unit_test(torture_ssh_quote_file_name), ++ cmocka_unit_test(torture_ssh_check_hostname_syntax), + }; + + ssh_init(); +-- +2.41.0 + + +From 4d7ae19e9cd8c407012b40f3f2eaf480bfb1da7d Mon Sep 17 00:00:00 2001 +From: Norbert Pocs +Date: Tue, 10 Oct 2023 18:33:56 +0200 +Subject: [PATCH 06/12] CVE-2023-6004: config_parser: Check for valid syntax of + a hostname if it is a domain name + +This prevents code injection. +The domain name syntax checker is based on RFC1035. + +Signed-off-by: Norbert Pocs +Reviewed-by: Andreas Schneider +--- + src/config_parser.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/src/config_parser.c b/src/config_parser.c +index 76cca224..87bac5d4 100644 +--- a/src/config_parser.c ++++ b/src/config_parser.c +@@ -30,6 +30,7 @@ + + #include "libssh/config_parser.h" + #include "libssh/priv.h" ++#include "libssh/misc.h" + + char *ssh_config_get_cmd(char **str) + { +@@ -139,6 +140,7 @@ int ssh_config_parse_uri(const char *tok, + { + char *endp = NULL; + long port_n; ++ int rc; + + /* Sanitize inputs */ + if (username != NULL) { +@@ -196,6 +198,14 @@ int ssh_config_parse_uri(const char *tok, + if (*hostname == NULL) { + goto error; + } ++ /* if not an ip, check syntax */ ++ rc = ssh_is_ipaddr(*hostname); ++ if (rc == 0) { ++ rc = ssh_check_hostname_syntax(*hostname); ++ if (rc != SSH_OK) { ++ goto error; ++ } ++ } + } + /* Skip also the closing bracket */ + if (*endp == ']') { +-- +2.41.0 + + +From 8cf4f4bfda968ab526c1a601ea1030bbaccaba17 Mon Sep 17 00:00:00 2001 +From: Norbert Pocs +Date: Tue, 10 Oct 2023 10:28:47 +0200 +Subject: [PATCH 07/12] CVE-2023-6004: torture_proxycommand: Add test for + proxycommand injection + +Signed-off-by: Norbert Pocs +Reviewed-by: Andreas Schneider +--- + tests/client/torture_proxycommand.c | 53 +++++++++++++++++++++++++++++ + 1 file changed, 53 insertions(+) + +diff --git a/tests/client/torture_proxycommand.c b/tests/client/torture_proxycommand.c +index c04ff2ab..dc17f3d8 100644 +--- a/tests/client/torture_proxycommand.c ++++ b/tests/client/torture_proxycommand.c +@@ -161,6 +161,56 @@ static void torture_options_set_proxycommand_ssh_stderr(void **state) + assert_int_equal(rc & O_RDWR, O_RDWR); + } + ++static void torture_options_proxycommand_injection(void **state) ++{ ++ struct torture_state *s = *state; ++ struct passwd *pwd = NULL; ++ const char *malicious_host = "`echo foo > mfile`"; ++ const char *command = "nc %h %p"; ++ char *current_dir = NULL; ++ char *malicious_file_path = NULL; ++ int mfp_len; ++ int verbosity = torture_libssh_verbosity(); ++ struct stat sb; ++ int rc; ++ ++ pwd = getpwnam("bob"); ++ assert_non_null(pwd); ++ ++ rc = setuid(pwd->pw_uid); ++ assert_return_code(rc, errno); ++ ++ s->ssh.session = ssh_new(); ++ assert_non_null(s->ssh.session); ++ ++ ssh_options_set(s->ssh.session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity); ++ // if we would be checking the rc, this should fail ++ ssh_options_set(s->ssh.session, SSH_OPTIONS_HOST, malicious_host); ++ ++ ssh_options_set(s->ssh.session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE); ++ ++ rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_PROXYCOMMAND, command); ++ assert_int_equal(rc, 0); ++ rc = ssh_connect(s->ssh.session); ++ assert_ssh_return_code_equal(s->ssh.session, rc, SSH_ERROR); ++ ++ current_dir = torture_get_current_working_dir(); ++ assert_non_null(current_dir); ++ mfp_len = strlen(current_dir) + 6; ++ malicious_file_path = malloc(mfp_len); ++ assert_non_null(malicious_file_path); ++ rc = snprintf(malicious_file_path, mfp_len, ++ "%s/mfile", current_dir); ++ assert_int_equal(rc, mfp_len); ++ free(current_dir); ++ rc = stat(malicious_file_path, &sb); ++ assert_int_not_equal(rc, 0); ++ ++ // cleanup ++ remove(malicious_file_path); ++ free(malicious_file_path); ++} ++ + int torture_run_tests(void) { + int rc; + struct CMUnitTest tests[] = { +@@ -176,6 +226,9 @@ int torture_run_tests(void) { + cmocka_unit_test_setup_teardown(torture_options_set_proxycommand_ssh_stderr, + session_setup, + session_teardown), ++ cmocka_unit_test_setup_teardown(torture_options_proxycommand_injection, ++ NULL, ++ session_teardown), + }; + + +-- +2.41.0 + + +From a0dbe0d556e073804cc549802569577bb24757d9 Mon Sep 17 00:00:00 2001 +From: Norbert Pocs +Date: Mon, 6 Nov 2023 20:11:38 +0100 +Subject: [PATCH 08/12] CVE-2023-6004: torture_misc: Add test for ssh_is_ipaddr + +Signed-off-by: Norbert Pocs +Reviewed-by: Andreas Schneider +--- + tests/unittests/torture_misc.c | 26 ++++++++++++++++++++++++++ + 1 file changed, 26 insertions(+) + +diff --git a/tests/unittests/torture_misc.c b/tests/unittests/torture_misc.c +index d14f4254..073bc54c 100644 +--- a/tests/unittests/torture_misc.c ++++ b/tests/unittests/torture_misc.c +@@ -728,6 +728,31 @@ static void torture_ssh_check_hostname_syntax(void **state) + assert_int_equal(rc, SSH_ERROR); + } + ++static void torture_ssh_is_ipaddr(void **state) { ++ int rc; ++ (void)state; ++ ++ rc = ssh_is_ipaddr("201.255.3.69"); ++ assert_int_equal(rc, 1); ++ rc = ssh_is_ipaddr("::1"); ++ assert_int_equal(rc, 1); ++ rc = ssh_is_ipaddr("2001:0db8:85a3:0000:0000:8a2e:0370:7334"); ++ assert_int_equal(rc, 1); ++ ++ rc = ssh_is_ipaddr(".."); ++ assert_int_equal(rc, 0); ++ rc = ssh_is_ipaddr(":::"); ++ assert_int_equal(rc, 0); ++ rc = ssh_is_ipaddr("1.1.1.1.1"); ++ assert_int_equal(rc, 0); ++ rc = ssh_is_ipaddr("1.1"); ++ assert_int_equal(rc, 0); ++ rc = ssh_is_ipaddr("caesar"); ++ assert_int_equal(rc, 0); ++ rc = ssh_is_ipaddr("::xa:1"); ++ assert_int_equal(rc, 0); ++} ++ + int torture_run_tests(void) { + int rc; + struct CMUnitTest tests[] = { +@@ -751,6 +776,7 @@ int torture_run_tests(void) { + cmocka_unit_test(torture_ssh_mkdirs), + cmocka_unit_test(torture_ssh_quote_file_name), + cmocka_unit_test(torture_ssh_check_hostname_syntax), ++ cmocka_unit_test(torture_ssh_is_ipaddr), + }; + + ssh_init(); +-- +2.41.0 + + +From cdaec0d6273243a03f460cc5ba1a2265b4afb93a Mon Sep 17 00:00:00 2001 +From: Norbert Pocs +Date: Tue, 28 Nov 2023 15:26:45 +0100 +Subject: [PATCH 09/12] CVE-2023-6004: misc: Add ipv6 link-local check for an + ip address + +Signed-off-by: Norbert Pocs +Reviewed-by: Andreas Schneider +--- + src/CMakeLists.txt | 17 ++++++++++------- + src/connect.c | 2 +- + src/misc.c | 44 ++++++++++++++++++++++++++++++++++++++------ + 3 files changed, 49 insertions(+), 14 deletions(-) + +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index a576cf71..fc401793 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -9,13 +9,6 @@ set(LIBSSH_LINK_LIBRARIES + ${LIBSSH_REQUIRED_LIBRARIES} + ) + +-if (WIN32) +- set(LIBSSH_LINK_LIBRARIES +- ${LIBSSH_LINK_LIBRARIES} +- ws2_32 +- ) +-endif (WIN32) +- + if (OPENSSL_CRYPTO_LIBRARIES) + set(LIBSSH_PRIVATE_INCLUDE_DIRS + ${LIBSSH_PRIVATE_INCLUDE_DIRS} +@@ -93,6 +86,16 @@ if (MINGW AND Threads_FOUND) + ) + endif() + ++# This needs to be last for mingw to build ++# https://gitlab.com/libssh/libssh-mirror/-/issues/84 ++if (WIN32) ++ set(LIBSSH_LINK_LIBRARIES ++ ${LIBSSH_LINK_LIBRARIES} ++ iphlpapi ++ ws2_32 ++ ) ++endif (WIN32) ++ + if (BUILD_STATIC_LIB) + set(LIBSSH_STATIC_LIBRARY + ssh_static +diff --git a/src/connect.c b/src/connect.c +index ce4d58df..ca62dcf0 100644 +--- a/src/connect.c ++++ b/src/connect.c +@@ -136,7 +136,7 @@ static int getai(const char *host, int port, struct addrinfo **ai) + #endif + } + +- if (ssh_is_ipaddr(host)) { ++ if (ssh_is_ipaddr(host) == 1) { + /* this is an IP address */ + SSH_LOG(SSH_LOG_PACKET, "host %s matches an IP address", host); + hints.ai_flags |= AI_NUMERICHOST; +diff --git a/src/misc.c b/src/misc.c +index e4239e81..6f5d2d60 100644 +--- a/src/misc.c ++++ b/src/misc.c +@@ -32,6 +32,7 @@ + #include + #include + #include ++#include + + #endif /* _WIN32 */ + +@@ -59,6 +60,7 @@ + #include + #include + #include ++#include + + #ifdef HAVE_IO_H + #include +@@ -216,22 +218,37 @@ int ssh_is_ipaddr_v4(const char *str) { + + int ssh_is_ipaddr(const char *str) { + int rc = SOCKET_ERROR; ++ char *s = strdup(str); + +- if (strchr(str, ':')) { ++ if (s == NULL) { ++ return -1; ++ } ++ if (strchr(s, ':')) { + struct sockaddr_storage ss; + int sslen = sizeof(ss); ++ char *network_interface = strchr(s, '%'); + +- /* TODO link-local (IP:v6:addr%ifname). */ +- rc = WSAStringToAddressA((LPSTR) str, ++ /* link-local (IP:v6:addr%ifname). */ ++ if (network_interface != NULL) { ++ rc = if_nametoindex(network_interface + 1); ++ if (rc == 0) { ++ free(s); ++ return 0; ++ } ++ *network_interface = '\0'; ++ } ++ rc = WSAStringToAddressA((LPSTR) s, + AF_INET6, + NULL, + (struct sockaddr*)&ss, + &sslen); + if (rc == 0) { ++ free(s); + return 1; + } + } + ++ free(s); + return ssh_is_ipaddr_v4(str); + } + #else /* _WIN32 */ +@@ -335,17 +352,32 @@ int ssh_is_ipaddr_v4(const char *str) { + + int ssh_is_ipaddr(const char *str) { + int rc = -1; ++ char *s = strdup(str); + +- if (strchr(str, ':')) { ++ if (s == NULL) { ++ return -1; ++ } ++ if (strchr(s, ':')) { + struct in6_addr dest6; ++ char *network_interface = strchr(s, '%'); + +- /* TODO link-local (IP:v6:addr%ifname). */ +- rc = inet_pton(AF_INET6, str, &dest6); ++ /* link-local (IP:v6:addr%ifname). */ ++ if (network_interface != NULL) { ++ rc = if_nametoindex(network_interface + 1); ++ if (rc == 0) { ++ free(s); ++ return 0; ++ } ++ *network_interface = '\0'; ++ } ++ rc = inet_pton(AF_INET6, s, &dest6); + if (rc > 0) { ++ free(s); + return 1; + } + } + ++ free(s); + return ssh_is_ipaddr_v4(str); + } + +-- +2.41.0 + + +From 6a8a18c73e73a338283dfbade0a7d83e5cfafe3b Mon Sep 17 00:00:00 2001 +From: Norbert Pocs +Date: Tue, 28 Nov 2023 15:27:31 +0100 +Subject: [PATCH 10/12] CVE-2023-6004: torture_misc: Add tests for ipv6 + link-local + +Signed-off-by: Norbert Pocs +Reviewed-by: Andreas Schneider +--- + tests/unittests/torture_misc.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/tests/unittests/torture_misc.c b/tests/unittests/torture_misc.c +index 073bc54c..f16b766e 100644 +--- a/tests/unittests/torture_misc.c ++++ b/tests/unittests/torture_misc.c +@@ -17,7 +17,14 @@ + #include "misc.c" + #include "error.c" + ++#ifdef _WIN32 ++#include ++#else ++#include ++#endif ++ + #define TORTURE_TEST_DIR "/usr/local/bin/truc/much/.." ++#define TORTURE_IPV6_LOCAL_LINK "fe80::98e1:82ff:fe8d:28b3%%%s" + + const char template[] = "temp_dir_XXXXXX"; + +@@ -730,14 +737,27 @@ static void torture_ssh_check_hostname_syntax(void **state) + + static void torture_ssh_is_ipaddr(void **state) { + int rc; ++ char *interf = malloc(64); ++ char *test_interf = malloc(128); + (void)state; + ++ assert_non_null(interf); ++ assert_non_null(test_interf); + rc = ssh_is_ipaddr("201.255.3.69"); + assert_int_equal(rc, 1); + rc = ssh_is_ipaddr("::1"); + assert_int_equal(rc, 1); + rc = ssh_is_ipaddr("2001:0db8:85a3:0000:0000:8a2e:0370:7334"); + assert_int_equal(rc, 1); ++ if_indextoname(1, interf); ++ assert_non_null(interf); ++ rc = sprintf(test_interf, TORTURE_IPV6_LOCAL_LINK, interf); ++ /* the "%%s" is not written */ ++ assert_int_equal(rc, strlen(interf) + strlen(TORTURE_IPV6_LOCAL_LINK) - 3); ++ rc = ssh_is_ipaddr(test_interf); ++ assert_int_equal(rc, 1); ++ free(interf); ++ free(test_interf); + + rc = ssh_is_ipaddr(".."); + assert_int_equal(rc, 0); +-- +2.41.0 + + +From 72f59157e6ccbd4c0bb806690931413169a0886f Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Fri, 22 Dec 2023 10:32:40 +0100 +Subject: [PATCH 11/12] Fix regression in IPv6 addresses in hostname parsing + +Signed-off-by: Jakub Jelen +Reviewed-by: Andreas Schneider +(cherry picked from commit 4f997aee7c7d7ea346b3e8ba505da0b7601ff318) +--- + include/libssh/config_parser.h | 11 ++++++++--- + src/config.c | 4 ++-- + src/config_parser.c | 16 +++++++++++----- + src/options.c | 10 ++-------- + 4 files changed, 23 insertions(+), 18 deletions(-) + +diff --git a/include/libssh/config_parser.h b/include/libssh/config_parser.h +index e974917c..ee647bfb 100644 +--- a/include/libssh/config_parser.h ++++ b/include/libssh/config_parser.h +@@ -26,6 +26,8 @@ + #ifndef CONFIG_PARSER_H_ + #define CONFIG_PARSER_H_ + ++#include ++ + char *ssh_config_get_cmd(char **str); + + char *ssh_config_get_token(char **str); +@@ -45,13 +47,16 @@ int ssh_config_get_yesno(char **str, int notfound); + * be stored or NULL if we do not care about the result. + * @param[out] port Pointer to the location, where the new port will + * be stored or NULL if we do not care about the result. ++ * @param[in] ignore_port Set to true if the we should not attempt to parse ++ * port number. + * + * @returns SSH_OK if the provided string is in format of SSH URI, + * SSH_ERROR on failure + */ + int ssh_config_parse_uri(const char *tok, +- char **username, +- char **hostname, +- char **port); ++ char **username, ++ char **hostname, ++ char **port, ++ bool ignore_port); + + #endif /* LIBSSH_CONFIG_H_ */ +diff --git a/src/config.c b/src/config.c +index 54ada276..a813568d 100644 +--- a/src/config.c ++++ b/src/config.c +@@ -324,7 +324,7 @@ ssh_config_parse_proxy_jump(ssh_session session, const char *s, bool do_parsing) + } + if (parse_entry) { + /* We actually care only about the first item */ +- rv = ssh_config_parse_uri(cp, &username, &hostname, &port); ++ rv = ssh_config_parse_uri(cp, &username, &hostname, &port, false); + /* The rest of the list needs to be passed on */ + if (endp != NULL) { + next = strdup(endp + 1); +@@ -335,7 +335,7 @@ ssh_config_parse_proxy_jump(ssh_session session, const char *s, bool do_parsing) + } + } else { + /* The rest is just sanity-checked to avoid failures later */ +- rv = ssh_config_parse_uri(cp, NULL, NULL, NULL); ++ rv = ssh_config_parse_uri(cp, NULL, NULL, NULL, false); + } + if (rv != SSH_OK) { + goto out; +diff --git a/src/config_parser.c b/src/config_parser.c +index 87bac5d4..a2da0a62 100644 +--- a/src/config_parser.c ++++ b/src/config_parser.c +@@ -134,9 +134,10 @@ int ssh_config_get_yesno(char **str, int notfound) + } + + int ssh_config_parse_uri(const char *tok, +- char **username, +- char **hostname, +- char **port) ++ char **username, ++ char **hostname, ++ char **port, ++ bool ignore_port) + { + char *endp = NULL; + long port_n; +@@ -182,12 +183,17 @@ int ssh_config_parse_uri(const char *tok, + if (endp == NULL) { + goto error; + } +- } else { +- /* Hostnames or aliases expand to the last colon or to the end */ ++ } else if (!ignore_port) { ++ /* Hostnames or aliases expand to the last colon (if port is requested) ++ * or to the end */ + endp = strrchr(tok, ':'); + if (endp == NULL) { + endp = strchr(tok, '\0'); + } ++ } else { ++ /* If no port is requested, expand to the end of line ++ * (to accommodate the IPv6 addresses) */ ++ endp = strchr(tok, '\0'); + } + if (tok == endp) { + /* Zero-length hostnames are not valid */ +diff --git a/src/options.c b/src/options.c +index 7c03e7ab..0890ff2e 100644 +--- a/src/options.c ++++ b/src/options.c +@@ -491,17 +491,11 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type, + ssh_set_error_invalid(session); + return -1; + } else { +- char *username = NULL, *hostname = NULL, *port = NULL; +- rc = ssh_config_parse_uri(value, &username, &hostname, &port); ++ char *username = NULL, *hostname = NULL; ++ rc = ssh_config_parse_uri(value, &username, &hostname, NULL, true); + if (rc != SSH_OK) { + return -1; + } +- if (port != NULL) { +- SAFE_FREE(username); +- SAFE_FREE(hostname); +- SAFE_FREE(port); +- return -1; +- } + if (username != NULL) { + SAFE_FREE(session->opts.username); + session->opts.username = username; +-- +2.41.0 + + +From 5dc10ff63ca2e8db91abfdccf1d095f5b4261b8e Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Fri, 22 Dec 2023 09:52:18 +0100 +Subject: [PATCH 12/12] tests: Increase test coverage for IPv6 address parsing + as hostnames + +This was an issue in cockpit: + +https://github.com/cockpit-project/cockpit/issues/19772 + +Signed-off-by: Jakub Jelen +Reviewed-by: Andreas Schneider +(cherry picked from commit 6f6e453d7b0ad4ee6a6f6a1c96a9a6b27821410d) +--- + tests/unittests/torture_config.c | 49 +++++++++++++++++++++++++++++++ + tests/unittests/torture_options.c | 22 ++++++++++++++ + 2 files changed, 71 insertions(+) + +diff --git a/tests/unittests/torture_config.c b/tests/unittests/torture_config.c +index 3a5a74bf..d8097e79 100644 +--- a/tests/unittests/torture_config.c ++++ b/tests/unittests/torture_config.c +@@ -2,6 +2,7 @@ + + #define LIBSSH_STATIC + ++#include + #include "torture.h" + #include "libssh/options.h" + #include "libssh/session.h" +@@ -997,6 +998,53 @@ static void torture_config_match_pattern(void **state) + + } + ++static void torture_config_parse_uri(void **state) ++{ ++ char *username = NULL; ++ char *hostname = NULL; ++ char *port = NULL; ++ int rc; ++ ++ (void)state; /* unused */ ++ ++ rc = ssh_config_parse_uri("localhost", &username, &hostname, &port, false); ++ assert_return_code(rc, errno); ++ assert_null(username); ++ assert_string_equal(hostname, "localhost"); ++ SAFE_FREE(hostname); ++ assert_null(port); ++ ++ rc = ssh_config_parse_uri("1.2.3.4", &username, &hostname, &port, false); ++ assert_return_code(rc, errno); ++ assert_null(username); ++ assert_string_equal(hostname, "1.2.3.4"); ++ SAFE_FREE(hostname); ++ assert_null(port); ++ ++ rc = ssh_config_parse_uri("1.2.3.4:2222", &username, &hostname, &port, false); ++ assert_return_code(rc, errno); ++ assert_null(username); ++ assert_string_equal(hostname, "1.2.3.4"); ++ SAFE_FREE(hostname); ++ assert_string_equal(port, "2222"); ++ SAFE_FREE(port); ++ ++ rc = ssh_config_parse_uri("[1:2:3::4]:2222", &username, &hostname, &port, false); ++ assert_return_code(rc, errno); ++ assert_null(username); ++ assert_string_equal(hostname, "1:2:3::4"); ++ SAFE_FREE(hostname); ++ assert_string_equal(port, "2222"); ++ SAFE_FREE(port); ++ ++ /* do not want port */ ++ rc = ssh_config_parse_uri("1:2:3::4", &username, &hostname, NULL, true); ++ assert_return_code(rc, errno); ++ assert_null(username); ++ assert_string_equal(hostname, "1:2:3::4"); ++ SAFE_FREE(hostname); ++} ++ + + int torture_run_tests(void) { + int rc; +@@ -1012,6 +1060,7 @@ int torture_run_tests(void) { + cmocka_unit_test(torture_config_rekey), + cmocka_unit_test(torture_config_pubkeyacceptedkeytypes), + cmocka_unit_test(torture_config_match_pattern), ++ cmocka_unit_test(torture_config_parse_uri), + }; + + +diff --git a/tests/unittests/torture_options.c b/tests/unittests/torture_options.c +index d0fdaed1..576ca9cd 100644 +--- a/tests/unittests/torture_options.c ++++ b/tests/unittests/torture_options.c +@@ -59,12 +59,34 @@ static void torture_options_set_host(void **state) { + assert_non_null(session->opts.host); + assert_string_equal(session->opts.host, "localhost"); + ++ /* IPv4 address */ ++ rc = ssh_options_set(session, SSH_OPTIONS_HOST, "127.1.1.1"); ++ assert_true(rc == 0); ++ assert_non_null(session->opts.host); ++ assert_string_equal(session->opts.host, "127.1.1.1"); ++ assert_null(session->opts.username); ++ ++ /* IPv6 address */ ++ rc = ssh_options_set(session, SSH_OPTIONS_HOST, "::1"); ++ assert_true(rc == 0); ++ assert_non_null(session->opts.host); ++ assert_string_equal(session->opts.host, "::1"); ++ assert_null(session->opts.username); ++ + rc = ssh_options_set(session, SSH_OPTIONS_HOST, "guru@meditation"); + assert_true(rc == 0); + assert_non_null(session->opts.host); + assert_string_equal(session->opts.host, "meditation"); + assert_non_null(session->opts.username); + assert_string_equal(session->opts.username, "guru"); ++ ++ /* more @ in uri is OK -- it should go to the username */ ++ rc = ssh_options_set(session, SSH_OPTIONS_HOST, "at@login@hostname"); ++ assert_true(rc == 0); ++ assert_non_null(session->opts.host); ++ assert_string_equal(session->opts.host, "hostname"); ++ assert_non_null(session->opts.username); ++ assert_string_equal(session->opts.username, "at@login"); + } + + static void torture_options_set_ciphers(void **state) { +-- +2.41.0 + diff --git a/root/ppg/common/deps/libssh/rpm/CVE-2023-6918.patch b/root/ppg/common/deps/libssh/rpm/CVE-2023-6918.patch new file mode 100644 index 00000000..a5bd07d8 --- /dev/null +++ b/root/ppg/common/deps/libssh/rpm/CVE-2023-6918.patch @@ -0,0 +1,1577 @@ +From 93c1dbd69f07f324c6aa1ab9296a632489cd3ead Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Fri, 15 Dec 2023 10:30:09 +0100 +Subject: [PATCH 1/5] CVE-2023-6918: kdf: Reformat + +Signed-off-by: Jakub Jelen +Reviewed-by: Andreas Schneider +--- + src/kdf.c | 20 +++++++++++--------- + 1 file changed, 11 insertions(+), 9 deletions(-) + +diff --git a/src/kdf.c b/src/kdf.c +index 09644739..656a38ed 100644 +--- a/src/kdf.c ++++ b/src/kdf.c +@@ -58,7 +58,7 @@ static ssh_mac_ctx ssh_mac_ctx_init(enum ssh_kdf_digest type) + } + + ctx->digest_type = type; +- switch(type){ ++ switch (type) { + case SSH_KDF_SHA1: + ctx->ctx.sha1_ctx = sha1_init(); + return ctx; +@@ -79,7 +79,7 @@ static ssh_mac_ctx ssh_mac_ctx_init(enum ssh_kdf_digest type) + + static void ssh_mac_update(ssh_mac_ctx ctx, const void *data, size_t len) + { +- switch(ctx->digest_type){ ++ switch (ctx->digest_type) { + case SSH_KDF_SHA1: + sha1_update(ctx->ctx.sha1_ctx, data, len); + break; +@@ -97,26 +97,28 @@ static void ssh_mac_update(ssh_mac_ctx ctx, const void *data, size_t len) + + static void ssh_mac_final(unsigned char *md, ssh_mac_ctx ctx) + { +- switch(ctx->digest_type){ ++ switch (ctx->digest_type) { + case SSH_KDF_SHA1: +- sha1_final(md,ctx->ctx.sha1_ctx); ++ sha1_final(md, ctx->ctx.sha1_ctx); + break; + case SSH_KDF_SHA256: +- sha256_final(md,ctx->ctx.sha256_ctx); ++ sha256_final(md, ctx->ctx.sha256_ctx); + break; + case SSH_KDF_SHA384: +- sha384_final(md,ctx->ctx.sha384_ctx); ++ sha384_final(md, ctx->ctx.sha384_ctx); + break; + case SSH_KDF_SHA512: +- sha512_final(md,ctx->ctx.sha512_ctx); ++ sha512_final(md, ctx->ctx.sha512_ctx); + break; + } + SAFE_FREE(ctx); + } + + int sshkdf_derive_key(struct ssh_crypto_struct *crypto, +- unsigned char *key, size_t key_len, +- int key_type, unsigned char *output, ++ unsigned char *key, ++ size_t key_len, ++ int key_type, ++ unsigned char *output, + size_t requested_len) + { + /* Can't use VLAs with Visual Studio, so allocate the biggest +-- +2.41.0 + + +From 882d9cb5c8d37d93f9b349d517e59bf496817007 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Fri, 15 Dec 2023 12:55:27 +0100 +Subject: [PATCH 2/5] CVE-2023-6918: Remove unused evp functions and types + +Signed-off-by: Jakub Jelen +Reviewed-by: Andreas Schneider +--- + include/libssh/libcrypto.h | 5 --- + include/libssh/libgcrypt.h | 1 - + include/libssh/libmbedcrypto.h | 1 - + include/libssh/wrapper.h | 5 --- + src/libcrypto.c | 55 +------------------------ + src/libgcrypt.c | 52 ------------------------ + src/libmbedcrypto.c | 74 ---------------------------------- + 7 files changed, 1 insertion(+), 192 deletions(-) + +diff --git a/include/libssh/libcrypto.h b/include/libssh/libcrypto.h +index 4117942c..35b277c5 100644 +--- a/include/libssh/libcrypto.h ++++ b/include/libssh/libcrypto.h +@@ -39,11 +39,6 @@ typedef EVP_MD_CTX* SHA384CTX; + typedef EVP_MD_CTX* SHA512CTX; + typedef EVP_MD_CTX* MD5CTX; + typedef HMAC_CTX* HMACCTX; +-#ifdef HAVE_ECC +-typedef EVP_MD_CTX *EVPCTX; +-#else +-typedef void *EVPCTX; +-#endif + + #define SHA_DIGEST_LEN SHA_DIGEST_LENGTH + #define SHA256_DIGEST_LEN SHA256_DIGEST_LENGTH +diff --git a/include/libssh/libgcrypt.h b/include/libssh/libgcrypt.h +index 347d851b..3a803fa4 100644 +--- a/include/libssh/libgcrypt.h ++++ b/include/libssh/libgcrypt.h +@@ -32,7 +32,6 @@ typedef gcry_md_hd_t SHA384CTX; + typedef gcry_md_hd_t SHA512CTX; + typedef gcry_md_hd_t MD5CTX; + typedef gcry_md_hd_t HMACCTX; +-typedef gcry_md_hd_t EVPCTX; + #define SHA_DIGEST_LENGTH 20 + #define SHA_DIGEST_LEN SHA_DIGEST_LENGTH + #define MD5_DIGEST_LEN 16 +diff --git a/include/libssh/libmbedcrypto.h b/include/libssh/libmbedcrypto.h +index fe53019b..b6e3e2a3 100644 +--- a/include/libssh/libmbedcrypto.h ++++ b/include/libssh/libmbedcrypto.h +@@ -41,7 +41,6 @@ typedef mbedtls_md_context_t *SHA384CTX; + typedef mbedtls_md_context_t *SHA512CTX; + typedef mbedtls_md_context_t *MD5CTX; + typedef mbedtls_md_context_t *HMACCTX; +-typedef mbedtls_md_context_t *EVPCTX; + + #define SHA_DIGEST_LENGTH 20 + #define SHA_DIGEST_LEN SHA_DIGEST_LENGTH +diff --git a/include/libssh/wrapper.h b/include/libssh/wrapper.h +index ba64939b..2f5ce189 100644 +--- a/include/libssh/wrapper.h ++++ b/include/libssh/wrapper.h +@@ -90,11 +90,6 @@ void sha512_update(SHA512CTX c, const void *data, unsigned long len); + void sha512_final(unsigned char *md,SHA512CTX c); + void sha512(const unsigned char *digest, int len, unsigned char *hash); + +-void evp(int nid, unsigned char *digest, int len, unsigned char *hash, unsigned int *hlen); +-EVPCTX evp_init(int nid); +-void evp_update(EVPCTX ctx, const void *data, unsigned long len); +-void evp_final(EVPCTX ctx, unsigned char *md, unsigned int *mdlen); +- + HMACCTX hmac_init(const void *key,int len, enum ssh_hmac_e type); + void hmac_update(HMACCTX c, const void *data, unsigned long len); + void hmac_final(HMACCTX ctx,unsigned char *hashmacbuf,unsigned int *len); +diff --git a/src/libcrypto.c b/src/libcrypto.c +index 3db75df6..5f3917ba 100644 +--- a/src/libcrypto.c ++++ b/src/libcrypto.c +@@ -148,60 +148,6 @@ void sha1(const unsigned char *digest, int len, unsigned char *hash) + } + } + +-#ifdef HAVE_OPENSSL_ECC +-static const EVP_MD *nid_to_evpmd(int nid) +-{ +- switch (nid) { +- case NID_X9_62_prime256v1: +- return EVP_sha256(); +- case NID_secp384r1: +- return EVP_sha384(); +- case NID_secp521r1: +- return EVP_sha512(); +- default: +- return NULL; +- } +- +- return NULL; +-} +- +-void evp(int nid, unsigned char *digest, int len, unsigned char *hash, unsigned int *hlen) +-{ +- const EVP_MD *evp_md = nid_to_evpmd(nid); +- EVP_MD_CTX *md = EVP_MD_CTX_new(); +- +- EVP_DigestInit(md, evp_md); +- EVP_DigestUpdate(md, digest, len); +- EVP_DigestFinal(md, hash, hlen); +- EVP_MD_CTX_free(md); +-} +- +-EVPCTX evp_init(int nid) +-{ +- const EVP_MD *evp_md = nid_to_evpmd(nid); +- +- EVPCTX ctx = EVP_MD_CTX_new(); +- if (ctx == NULL) { +- return NULL; +- } +- +- EVP_DigestInit(ctx, evp_md); +- +- return ctx; +-} +- +-void evp_update(EVPCTX ctx, const void *data, unsigned long len) +-{ +- EVP_DigestUpdate(ctx, data, len); +-} +- +-void evp_final(EVPCTX ctx, unsigned char *md, unsigned int *mdlen) +-{ +- EVP_DigestFinal(ctx, md, mdlen); +- EVP_MD_CTX_free(ctx); +-} +-#endif +- + SHA256CTX sha256_init(void) + { + int rc; +@@ -345,6 +291,7 @@ void md5_final(unsigned char *md, MD5CTX c) + EVP_MD_CTX_destroy(c); + } + ++ + #ifdef HAVE_OPENSSL_EVP_KDF_CTX_NEW_ID + static const EVP_MD *sshkdf_digest_to_md(enum ssh_kdf_digest digest_type) + { +diff --git a/src/libgcrypt.c b/src/libgcrypt.c +index 8fbf2157..49488793 100644 +--- a/src/libgcrypt.c ++++ b/src/libgcrypt.c +@@ -82,58 +82,6 @@ void sha1(const unsigned char *digest, int len, unsigned char *hash) { + gcry_md_hash_buffer(GCRY_MD_SHA1, hash, digest, len); + } + +-#ifdef HAVE_GCRYPT_ECC +-static int nid_to_md_algo(int nid) +-{ +- switch (nid) { +- case NID_gcrypt_nistp256: +- return GCRY_MD_SHA256; +- case NID_gcrypt_nistp384: +- return GCRY_MD_SHA384; +- case NID_gcrypt_nistp521: +- return GCRY_MD_SHA512; +- } +- return GCRY_MD_NONE; +-} +- +-void evp(int nid, unsigned char *digest, int len, +- unsigned char *hash, unsigned int *hlen) +-{ +- int algo = nid_to_md_algo(nid); +- +- /* Note: What gcrypt calls 'hash' is called 'digest' here and +- vice-versa. */ +- gcry_md_hash_buffer(algo, hash, digest, len); +- *hlen = gcry_md_get_algo_dlen(algo); +-} +- +-EVPCTX evp_init(int nid) +-{ +- gcry_error_t err; +- int algo = nid_to_md_algo(nid); +- EVPCTX ctx; +- +- err = gcry_md_open(&ctx, algo, 0); +- if (err) { +- return NULL; +- } +- +- return ctx; +-} +- +-void evp_update(EVPCTX ctx, const void *data, unsigned long len) +-{ +- gcry_md_write(ctx, data, len); +-} +- +-void evp_final(EVPCTX ctx, unsigned char *md, unsigned int *mdlen) +-{ +- int algo = gcry_md_get_algo(ctx); +- *mdlen = gcry_md_get_algo_dlen(algo); +- memcpy(md, gcry_md_read(ctx, algo), *mdlen); +- gcry_md_close(ctx); +-} +-#endif + + SHA256CTX sha256_init(void) { + SHA256CTX ctx = NULL; +diff --git a/src/libmbedcrypto.c b/src/libmbedcrypto.c +index a2e74d3b..f37a6a6d 100644 +--- a/src/libmbedcrypto.c ++++ b/src/libmbedcrypto.c +@@ -103,80 +103,6 @@ void sha1(const unsigned char *digest, int len, unsigned char *hash) + } + } + +-static mbedtls_md_type_t nid_to_md_algo(int nid) +-{ +- switch (nid) { +- case NID_mbedtls_nistp256: +- return MBEDTLS_MD_SHA256; +- case NID_mbedtls_nistp384: +- return MBEDTLS_MD_SHA384; +- case NID_mbedtls_nistp521: +- return MBEDTLS_MD_SHA512; +- } +- return MBEDTLS_MD_NONE; +-} +- +-void evp(int nid, unsigned char *digest, int len, +- unsigned char *hash, unsigned int *hlen) +-{ +- mbedtls_md_type_t algo = nid_to_md_algo(nid); +- const mbedtls_md_info_t *md_info = +- mbedtls_md_info_from_type(algo); +- +- +- if (md_info != NULL) { +- *hlen = mbedtls_md_get_size(md_info); +- mbedtls_md(md_info, digest, len, hash); +- } +-} +- +-EVPCTX evp_init(int nid) +-{ +- EVPCTX ctx = NULL; +- int rc; +- mbedtls_md_type_t algo = nid_to_md_algo(nid); +- const mbedtls_md_info_t *md_info = +- mbedtls_md_info_from_type(algo); +- +- if (md_info == NULL) { +- return NULL; +- } +- +- ctx = malloc(sizeof(mbedtls_md_context_t)); +- if (ctx == NULL) { +- return NULL; +- } +- +- mbedtls_md_init(ctx); +- +- rc = mbedtls_md_setup(ctx, md_info, 0); +- if (rc != 0) { +- SAFE_FREE(ctx); +- return NULL; +- } +- +- rc = mbedtls_md_starts(ctx); +- if (rc != 0) { +- SAFE_FREE(ctx); +- return NULL; +- } +- +- return ctx; +-} +- +-void evp_update(EVPCTX ctx, const void *data, unsigned long len) +-{ +- mbedtls_md_update(ctx, data, len); +-} +- +-void evp_final(EVPCTX ctx, unsigned char *md, unsigned int *mdlen) +-{ +- *mdlen = mbedtls_md_get_size(ctx->md_info); +- mbedtls_md_finish(ctx, md); +- mbedtls_md_free(ctx); +- SAFE_FREE(ctx); +-} +- + SHA256CTX sha256_init(void) + { + SHA256CTX ctx = NULL; +-- +2.41.0 + + +From a45a3c940d17abb3bcd2b924ccd5cd68eb8fd753 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Fri, 15 Dec 2023 12:55:54 +0100 +Subject: [PATCH 3/5] CVE-2023-6918: Systematically check return values when + calculating digests + +with all crypto backends + +Signed-off-by: Jakub Jelen +Reviewed-by: Andreas Schneider +--- + include/libssh/wrapper.h | 34 +++++--- + src/kdf.c | 96 +++++++++++++++++---- + src/libcrypto.c | 166 +++++++++++++++++++++++++++-------- + src/libgcrypt.c | 142 +++++++++++++++++++++++------- + src/libmbedcrypto.c | 182 ++++++++++++++++++++++++++++++--------- + src/session.c | 72 ++++++++++++---- + 6 files changed, 533 insertions(+), 159 deletions(-) + +diff --git a/include/libssh/wrapper.h b/include/libssh/wrapper.h +index 2f5ce189..e6384b50 100644 +--- a/include/libssh/wrapper.h ++++ b/include/libssh/wrapper.h +@@ -67,32 +67,38 @@ struct ssh_crypto_struct; + + typedef struct ssh_mac_ctx_struct *ssh_mac_ctx; + MD5CTX md5_init(void); +-void md5_update(MD5CTX c, const void *data, unsigned long len); +-void md5_final(unsigned char *md,MD5CTX c); ++void md5_ctx_free(MD5CTX); ++int md5_update(MD5CTX c, const void *data, unsigned long len); ++int md5_final(unsigned char *md,MD5CTX c); + + SHACTX sha1_init(void); +-void sha1_update(SHACTX c, const void *data, unsigned long len); +-void sha1_final(unsigned char *md,SHACTX c); +-void sha1(const unsigned char *digest,int len,unsigned char *hash); ++void sha1_ctx_free(SHACTX); ++int sha1_update(SHACTX c, const void *data, unsigned long len); ++int sha1_final(unsigned char *md,SHACTX c); ++int sha1(const unsigned char *digest,int len,unsigned char *hash); + + SHA256CTX sha256_init(void); +-void sha256_update(SHA256CTX c, const void *data, unsigned long len); +-void sha256_final(unsigned char *md,SHA256CTX c); +-void sha256(const unsigned char *digest, int len, unsigned char *hash); ++void sha256_ctx_free(SHA256CTX); ++int sha256_update(SHA256CTX c, const void *data, unsigned long len); ++int sha256_final(unsigned char *md,SHA256CTX c); ++int sha256(const unsigned char *digest, int len, unsigned char *hash); + + SHA384CTX sha384_init(void); +-void sha384_update(SHA384CTX c, const void *data, unsigned long len); +-void sha384_final(unsigned char *md,SHA384CTX c); +-void sha384(const unsigned char *digest, int len, unsigned char *hash); ++void sha384_ctx_free(SHA384CTX); ++int sha384_update(SHA384CTX c, const void *data, unsigned long len); ++int sha384_final(unsigned char *md,SHA384CTX c); ++int sha384(const unsigned char *digest, int len, unsigned char *hash); + + SHA512CTX sha512_init(void); +-void sha512_update(SHA512CTX c, const void *data, unsigned long len); +-void sha512_final(unsigned char *md,SHA512CTX c); +-void sha512(const unsigned char *digest, int len, unsigned char *hash); ++void sha512_ctx_free(SHA512CTX); ++int sha512_update(SHA512CTX c, const void *data, unsigned long len); ++int sha512_final(unsigned char *md,SHA512CTX c); ++int sha512(const unsigned char *digest, int len, unsigned char *hash); + + HMACCTX hmac_init(const void *key,int len, enum ssh_hmac_e type); + void hmac_update(HMACCTX c, const void *data, unsigned long len); + void hmac_final(HMACCTX ctx,unsigned char *hashmacbuf,unsigned int *len); ++ + size_t hmac_digest_len(enum ssh_hmac_e type); + + int ssh_kdf(struct ssh_crypto_struct *crypto, +diff --git a/src/kdf.c b/src/kdf.c +index 656a38ed..90f6e9f3 100644 +--- a/src/kdf.c ++++ b/src/kdf.c +@@ -77,41 +77,64 @@ static ssh_mac_ctx ssh_mac_ctx_init(enum ssh_kdf_digest type) + } + } + +-static void ssh_mac_update(ssh_mac_ctx ctx, const void *data, size_t len) ++static void ssh_mac_ctx_free(ssh_mac_ctx ctx) + { ++ if (ctx == NULL) { ++ return; ++ } ++ + switch (ctx->digest_type) { + case SSH_KDF_SHA1: +- sha1_update(ctx->ctx.sha1_ctx, data, len); ++ sha1_ctx_free(ctx->ctx.sha1_ctx); + break; + case SSH_KDF_SHA256: +- sha256_update(ctx->ctx.sha256_ctx, data, len); ++ sha256_ctx_free(ctx->ctx.sha256_ctx); + break; + case SSH_KDF_SHA384: +- sha384_update(ctx->ctx.sha384_ctx, data, len); ++ sha384_ctx_free(ctx->ctx.sha384_ctx); + break; + case SSH_KDF_SHA512: +- sha512_update(ctx->ctx.sha512_ctx, data, len); ++ sha512_ctx_free(ctx->ctx.sha512_ctx); + break; + } ++ SAFE_FREE(ctx); ++} ++ ++static int ssh_mac_update(ssh_mac_ctx ctx, const void *data, size_t len) ++{ ++ switch (ctx->digest_type) { ++ case SSH_KDF_SHA1: ++ return sha1_update(ctx->ctx.sha1_ctx, data, len); ++ case SSH_KDF_SHA256: ++ return sha256_update(ctx->ctx.sha256_ctx, data, len); ++ case SSH_KDF_SHA384: ++ return sha384_update(ctx->ctx.sha384_ctx, data, len); ++ case SSH_KDF_SHA512: ++ return sha512_update(ctx->ctx.sha512_ctx, data, len); ++ } ++ return SSH_ERROR; + } + +-static void ssh_mac_final(unsigned char *md, ssh_mac_ctx ctx) ++static int ssh_mac_final(unsigned char *md, ssh_mac_ctx ctx) + { ++ int rc = SSH_ERROR; ++ + switch (ctx->digest_type) { + case SSH_KDF_SHA1: +- sha1_final(md, ctx->ctx.sha1_ctx); ++ rc = sha1_final(md, ctx->ctx.sha1_ctx); + break; + case SSH_KDF_SHA256: +- sha256_final(md, ctx->ctx.sha256_ctx); ++ rc = sha256_final(md, ctx->ctx.sha256_ctx); + break; + case SSH_KDF_SHA384: +- sha384_final(md, ctx->ctx.sha384_ctx); ++ rc = sha384_final(md, ctx->ctx.sha384_ctx); + break; + case SSH_KDF_SHA512: +- sha512_final(md, ctx->ctx.sha512_ctx); ++ rc = sha512_final(md, ctx->ctx.sha512_ctx); + break; + } + SAFE_FREE(ctx); ++ return rc; + } + + int sshkdf_derive_key(struct ssh_crypto_struct *crypto, +@@ -127,6 +150,7 @@ int sshkdf_derive_key(struct ssh_crypto_struct *crypto, + size_t output_len = crypto->digest_len; + char letter = key_type; + ssh_mac_ctx ctx; ++ int rc; + + if (DIGEST_MAX_LEN < crypto->digest_len) { + return -1; +@@ -137,11 +161,30 @@ int sshkdf_derive_key(struct ssh_crypto_struct *crypto, + return -1; + } + +- ssh_mac_update(ctx, key, key_len); +- ssh_mac_update(ctx, crypto->secret_hash, crypto->digest_len); +- ssh_mac_update(ctx, &letter, 1); +- ssh_mac_update(ctx, crypto->session_id, crypto->session_id_len); +- ssh_mac_final(digest, ctx); ++ rc = ssh_mac_update(ctx, key, key_len); ++ if (rc != SSH_OK) { ++ ssh_mac_ctx_free(ctx); ++ return -1; ++ } ++ rc = ssh_mac_update(ctx, crypto->secret_hash, crypto->digest_len); ++ if (rc != SSH_OK) { ++ ssh_mac_ctx_free(ctx); ++ return -1; ++ } ++ rc = ssh_mac_update(ctx, &letter, 1); ++ if (rc != SSH_OK) { ++ ssh_mac_ctx_free(ctx); ++ return -1; ++ } ++ rc = ssh_mac_update(ctx, crypto->session_id, crypto->session_id_len); ++ if (rc != SSH_OK) { ++ ssh_mac_ctx_free(ctx); ++ return -1; ++ } ++ rc = ssh_mac_final(digest, ctx); ++ if (rc != SSH_OK) { ++ return -1; ++ } + + if (requested_len < output_len) { + output_len = requested_len; +@@ -153,10 +196,25 @@ int sshkdf_derive_key(struct ssh_crypto_struct *crypto, + if (ctx == NULL) { + return -1; + } +- ssh_mac_update(ctx, key, key_len); +- ssh_mac_update(ctx, crypto->secret_hash, crypto->digest_len); +- ssh_mac_update(ctx, output, output_len); +- ssh_mac_final(digest, ctx); ++ rc = ssh_mac_update(ctx, key, key_len); ++ if (rc != SSH_OK) { ++ ssh_mac_ctx_free(ctx); ++ return -1; ++ } ++ rc = ssh_mac_update(ctx, crypto->secret_hash, crypto->digest_len); ++ if (rc != SSH_OK) { ++ ssh_mac_ctx_free(ctx); ++ return -1; ++ } ++ rc = ssh_mac_update(ctx, output, output_len); ++ if (rc != SSH_OK) { ++ ssh_mac_ctx_free(ctx); ++ return -1; ++ } ++ rc = ssh_mac_final(digest, ctx); ++ if (rc != SSH_OK) { ++ return -1; ++ } + if (requested_len < output_len + crypto->digest_len) { + memcpy(output + output_len, digest, requested_len - output_len); + } else { +diff --git a/src/libcrypto.c b/src/libcrypto.c +index 5f3917ba..45f45a9e 100644 +--- a/src/libcrypto.c ++++ b/src/libcrypto.c +@@ -126,26 +126,46 @@ SHACTX sha1_init(void) + return c; + } + +-void sha1_update(SHACTX c, const void *data, unsigned long len) ++void sha1_ctx_free(SHACTX c) + { +- EVP_DigestUpdate(c, data, len); ++ EVP_MD_CTX_destroy(c); + } + +-void sha1_final(unsigned char *md, SHACTX c) ++int sha1_update(SHACTX c, const void *data, unsigned long len) ++{ ++ int rc = EVP_DigestUpdate(c, data, len); ++ if (rc != 1) { ++ return SSH_ERROR; ++ } ++ return SSH_OK; ++} ++ ++int sha1_final(unsigned char *md, SHACTX c) + { + unsigned int mdlen = 0; ++ int rc = EVP_DigestFinal(c, md, &mdlen); + +- EVP_DigestFinal(c, md, &mdlen); + EVP_MD_CTX_destroy(c); ++ if (rc != 1) { ++ return SSH_ERROR; ++ } ++ return SSH_OK; + } + +-void sha1(const unsigned char *digest, int len, unsigned char *hash) ++int sha1(const unsigned char *digest, int len, unsigned char *hash) + { + SHACTX c = sha1_init(); +- if (c != NULL) { +- sha1_update(c, digest, len); +- sha1_final(hash, c); ++ int rc; ++ ++ if (c == NULL) { ++ return SSH_ERROR; + } ++ rc = sha1_update(c, digest, len); ++ if (rc != SSH_OK) { ++ sha1_ctx_free(c); ++ return SSH_ERROR; ++ } ++ return sha1_final(hash, c); + } + + SHA256CTX sha256_init(void) +@@ -164,26 +184,46 @@ SHA256CTX sha256_init(void) + return c; + } + +-void sha256_update(SHA256CTX c, const void *data, unsigned long len) ++void sha256_ctx_free(SHA256CTX c) ++{ ++ EVP_MD_CTX_destroy(c); ++} ++ ++int sha256_update(SHA256CTX c, const void *data, unsigned long len) + { +- EVP_DigestUpdate(c, data, len); ++ int rc = EVP_DigestUpdate(c, data, len); ++ if (rc != 1) { ++ return SSH_ERROR; ++ } ++ return SSH_OK; + } + +-void sha256_final(unsigned char *md, SHA256CTX c) ++int sha256_final(unsigned char *md, SHA256CTX c) + { + unsigned int mdlen = 0; ++ int rc = EVP_DigestFinal(c, md, &mdlen); + +- EVP_DigestFinal(c, md, &mdlen); + EVP_MD_CTX_destroy(c); ++ if (rc != 1) { ++ return SSH_ERROR; ++ } ++ return SSH_OK; + } + +-void sha256(const unsigned char *digest, int len, unsigned char *hash) ++int sha256(const unsigned char *digest, int len, unsigned char *hash) + { + SHA256CTX c = sha256_init(); +- if (c != NULL) { +- sha256_update(c, digest, len); +- sha256_final(hash, c); ++ int rc; ++ ++ if (c == NULL) { ++ return SSH_ERROR; + } ++ rc = sha256_update(c, digest, len); ++ if (rc != SSH_OK) { ++ sha256_ctx_free(c); ++ return SSH_ERROR; ++ } ++ return sha256_final(hash, c); + } + + SHA384CTX sha384_init(void) +@@ -202,26 +242,47 @@ SHA384CTX sha384_init(void) + return c; + } + +-void sha384_update(SHA384CTX c, const void *data, unsigned long len) ++void ++sha384_ctx_free(SHA384CTX c) ++{ ++ EVP_MD_CTX_destroy(c); ++} ++ ++int sha384_update(SHA384CTX c, const void *data, unsigned long len) + { +- EVP_DigestUpdate(c, data, len); ++ int rc = EVP_DigestUpdate(c, data, len); ++ if (rc != 1) { ++ return SSH_ERROR; ++ } ++ return SSH_OK; + } + +-void sha384_final(unsigned char *md, SHA384CTX c) ++int sha384_final(unsigned char *md, SHA384CTX c) + { + unsigned int mdlen = 0; ++ int rc = EVP_DigestFinal(c, md, &mdlen); + +- EVP_DigestFinal(c, md, &mdlen); + EVP_MD_CTX_destroy(c); ++ if (rc != 1) { ++ return SSH_ERROR; ++ } ++ return SSH_OK; + } + +-void sha384(const unsigned char *digest, int len, unsigned char *hash) ++int sha384(const unsigned char *digest, int len, unsigned char *hash) + { + SHA384CTX c = sha384_init(); +- if (c != NULL) { +- sha384_update(c, digest, len); +- sha384_final(hash, c); ++ int rc; ++ ++ if (c == NULL) { ++ return SSH_ERROR; + } ++ rc = sha384_update(c, digest, len); ++ if (rc != SSH_OK) { ++ sha384_ctx_free(c); ++ return SSH_ERROR; ++ } ++ return sha384_final(hash, c); + } + + SHA512CTX sha512_init(void) +@@ -240,26 +301,46 @@ SHA512CTX sha512_init(void) + return c; + } + +-void sha512_update(SHA512CTX c, const void *data, unsigned long len) ++void sha512_ctx_free(SHA512CTX c) ++{ ++ EVP_MD_CTX_destroy(c); ++} ++ ++int sha512_update(SHA512CTX c, const void *data, unsigned long len) + { +- EVP_DigestUpdate(c, data, len); ++ int rc = EVP_DigestUpdate(c, data, len); ++ if (rc != 1) { ++ return SSH_ERROR; ++ } ++ return SSH_OK; + } + +-void sha512_final(unsigned char *md, SHA512CTX c) ++int sha512_final(unsigned char *md, SHA512CTX c) + { + unsigned int mdlen = 0; ++ int rc = EVP_DigestFinal(c, md, &mdlen); + +- EVP_DigestFinal(c, md, &mdlen); + EVP_MD_CTX_destroy(c); ++ if (rc != 1) { ++ return SSH_ERROR; ++ } ++ return SSH_OK; + } + +-void sha512(const unsigned char *digest, int len, unsigned char *hash) ++int sha512(const unsigned char *digest, int len, unsigned char *hash) + { + SHA512CTX c = sha512_init(); +- if (c != NULL) { +- sha512_update(c, digest, len); +- sha512_final(hash, c); ++ int rc; ++ ++ if (c == NULL) { ++ return SSH_ERROR; ++ } ++ rc = sha512_update(c, digest, len); ++ if (rc != SSH_OK) { ++ sha512_ctx_free(c); ++ return SSH_ERROR; + } ++ return sha512_final(hash, c); + } + + MD5CTX md5_init(void) +@@ -278,17 +359,30 @@ MD5CTX md5_init(void) + return c; + } + +-void md5_update(MD5CTX c, const void *data, unsigned long len) ++void md5_ctx_free(MD5CTX c) + { +- EVP_DigestUpdate(c, data, len); ++ EVP_MD_CTX_destroy(c); + } + +-void md5_final(unsigned char *md, MD5CTX c) ++int md5_update(MD5CTX c, const void *data, unsigned long len) ++{ ++ int rc = EVP_DigestUpdate(c, data, len); ++ if (rc != 1) { ++ return SSH_ERROR; ++ } ++ return SSH_OK; ++} ++ ++int md5_final(unsigned char *md, MD5CTX c) + { + unsigned int mdlen = 0; ++ int rc = EVP_DigestFinal(c, md, &mdlen); + +- EVP_DigestFinal(c, md, &mdlen); + EVP_MD_CTX_destroy(c); ++ if (rc != 1) { ++ return SSH_ERROR; ++ } ++ return SSH_OK; + } + + +diff --git a/src/libgcrypt.c b/src/libgcrypt.c +index 49488793..d1332af3 100644 +--- a/src/libgcrypt.c ++++ b/src/libgcrypt.c +@@ -68,18 +68,35 @@ SHACTX sha1_init(void) { + return ctx; + } + +-void sha1_update(SHACTX c, const void *data, unsigned long len) { ++void ++sha1_ctx_free(SHACTX c) ++{ ++ gcry_md_close(c); ++} ++ ++int sha1_update(SHACTX c, const void *data, unsigned long len) { + gcry_md_write(c, data, len); ++ return SSH_OK; + } + +-void sha1_final(unsigned char *md, SHACTX c) { +- gcry_md_final(c); +- memcpy(md, gcry_md_read(c, 0), SHA_DIGEST_LEN); +- gcry_md_close(c); ++int sha1_final(unsigned char *md, SHACTX c) ++{ ++ unsigned char *tmp = NULL; ++ ++ gcry_md_final(c); ++ tmp = gcry_md_read(c, 0); ++ if (tmp == NULL) { ++ gcry_md_close(c); ++ return SSH_ERROR; ++ } ++ memcpy(md, tmp, SHA_DIGEST_LEN); ++ gcry_md_close(c); ++ return SSH_OK; + } + +-void sha1(const unsigned char *digest, int len, unsigned char *hash) { ++int sha1(const unsigned char *digest, int len, unsigned char *hash) { + gcry_md_hash_buffer(GCRY_MD_SHA1, hash, digest, len); ++ return SSH_OK; + } + + +@@ -90,18 +107,35 @@ SHA256CTX sha256_init(void) { + return ctx; + } + +-void sha256_update(SHACTX c, const void *data, unsigned long len) { ++void ++sha256_ctx_free(SHA256CTX c) ++{ ++ gcry_md_close(c); ++} ++ ++int sha256_update(SHACTX c, const void *data, unsigned long len) { + gcry_md_write(c, data, len); ++ return SSH_OK; + } + +-void sha256_final(unsigned char *md, SHACTX c) { +- gcry_md_final(c); +- memcpy(md, gcry_md_read(c, 0), SHA256_DIGEST_LEN); +- gcry_md_close(c); ++int sha256_final(unsigned char *md, SHACTX c) ++{ ++ unsigned char *tmp = NULL; ++ ++ gcry_md_final(c); ++ tmp = gcry_md_read(c, 0); ++ if (tmp == NULL) { ++ gcry_md_close(c); ++ return SSH_ERROR; ++ } ++ memcpy(md, tmp, SHA256_DIGEST_LEN); ++ gcry_md_close(c); ++ return SSH_OK; + } + +-void sha256(const unsigned char *digest, int len, unsigned char *hash){ ++int sha256(const unsigned char *digest, int len, unsigned char *hash){ + gcry_md_hash_buffer(GCRY_MD_SHA256, hash, digest, len); ++ return SSH_OK; + } + + SHA384CTX sha384_init(void) { +@@ -111,18 +145,35 @@ SHA384CTX sha384_init(void) { + return ctx; + } + +-void sha384_update(SHACTX c, const void *data, unsigned long len) { ++void ++sha384_ctx_free(SHA384CTX c) ++{ ++ gcry_md_close(c); ++} ++ ++int sha384_update(SHACTX c, const void *data, unsigned long len) { + gcry_md_write(c, data, len); ++ return SSH_OK; + } + +-void sha384_final(unsigned char *md, SHACTX c) { +- gcry_md_final(c); +- memcpy(md, gcry_md_read(c, 0), SHA384_DIGEST_LEN); +- gcry_md_close(c); ++int sha384_final(unsigned char *md, SHACTX c) ++{ ++ unsigned char *tmp = NULL; ++ ++ gcry_md_final(c); ++ tmp = gcry_md_read(c, 0); ++ if (tmp == NULL) { ++ gcry_md_close(c); ++ return SSH_ERROR; ++ } ++ memcpy(md, tmp, SHA384_DIGEST_LEN); ++ gcry_md_close(c); ++ return SSH_OK; + } + +-void sha384(const unsigned char *digest, int len, unsigned char *hash) { ++int sha384(const unsigned char *digest, int len, unsigned char *hash) { + gcry_md_hash_buffer(GCRY_MD_SHA384, hash, digest, len); ++ return SSH_OK; + } + + SHA512CTX sha512_init(void) { +@@ -132,18 +183,35 @@ SHA512CTX sha512_init(void) { + return ctx; + } + +-void sha512_update(SHACTX c, const void *data, unsigned long len) { ++void ++sha512_ctx_free(SHA512CTX c) ++{ ++ gcry_md_close(c); ++} ++ ++int sha512_update(SHACTX c, const void *data, unsigned long len) { + gcry_md_write(c, data, len); ++ return SSH_OK; + } + +-void sha512_final(unsigned char *md, SHACTX c) { +- gcry_md_final(c); +- memcpy(md, gcry_md_read(c, 0), SHA512_DIGEST_LEN); +- gcry_md_close(c); ++int sha512_final(unsigned char *md, SHACTX c) ++{ ++ unsigned char *tmp = NULL; ++ ++ gcry_md_final(c); ++ tmp = gcry_md_read(c, 0); ++ if (tmp == NULL) { ++ gcry_md_close(c); ++ return SSH_ERROR; ++ } ++ memcpy(md, tmp, SHA512_DIGEST_LEN); ++ gcry_md_close(c); ++ return SSH_OK; + } + +-void sha512(const unsigned char *digest, int len, unsigned char *hash) { ++int sha512(const unsigned char *digest, int len, unsigned char *hash) { + gcry_md_hash_buffer(GCRY_MD_SHA512, hash, digest, len); ++ return SSH_OK; + } + + MD5CTX md5_init(void) { +@@ -153,14 +221,30 @@ MD5CTX md5_init(void) { + return c; + } + +-void md5_update(MD5CTX c, const void *data, unsigned long len) { ++void ++md5_ctx_free(MD5CTX c) ++{ ++ gcry_md_close(c); ++} ++ ++int md5_update(MD5CTX c, const void *data, unsigned long len) { + gcry_md_write(c,data,len); ++ return SSH_OK; + } + +-void md5_final(unsigned char *md, MD5CTX c) { +- gcry_md_final(c); +- memcpy(md, gcry_md_read(c, 0), MD5_DIGEST_LEN); +- gcry_md_close(c); ++int md5_final(unsigned char *md, MD5CTX c) ++{ ++ unsigned char *tmp = NULL; ++ ++ gcry_md_final(c); ++ tmp = gcry_md_read(c, 0); ++ if (tmp == NULL) { ++ gcry_md_close(c); ++ return SSH_ERROR; ++ } ++ memcpy(md, tmp, MD5_DIGEST_LEN); ++ gcry_md_close(c); ++ return SSH_OK; + } + + int ssh_kdf(struct ssh_crypto_struct *crypto, +diff --git a/src/libmbedcrypto.c b/src/libmbedcrypto.c +index f37a6a6d..e9a2b8e5 100644 +--- a/src/libmbedcrypto.c ++++ b/src/libmbedcrypto.c +@@ -82,25 +82,46 @@ SHACTX sha1_init(void) + return ctx; + } + +-void sha1_update(SHACTX c, const void *data, unsigned long len) ++void ++sha1_ctx_free(SHACTX c) + { +- mbedtls_md_update(c, data, len); ++ mbedtls_md_free(c); ++ SAFE_FREE(c); + } + +-void sha1_final(unsigned char *md, SHACTX c) ++int sha1_update(SHACTX c, const void *data, unsigned long len) + { +- mbedtls_md_finish(c, md); +- mbedtls_md_free(c); +- SAFE_FREE(c); ++ int rc = mbedtls_md_update(c, data, len); ++ if (rc != 0) { ++ return SSH_ERROR; ++ } ++ return SSH_OK; + } + +-void sha1(const unsigned char *digest, int len, unsigned char *hash) ++int sha1_final(unsigned char *md, SHACTX c) ++{ ++ int rc = mbedtls_md_finish(c, md); ++ sha1_ctx_free(c); ++ if (rc != 0) { ++ return SSH_ERROR; ++ } ++ return SSH_OK; ++} ++ ++int sha1(const unsigned char *digest, int len, unsigned char *hash) + { + const mbedtls_md_info_t *md_info = + mbedtls_md_info_from_type(MBEDTLS_MD_SHA1); +- if (md_info != NULL) { +- mbedtls_md(md_info, digest, len, hash); ++ int rc; ++ ++ if (md_info == NULL) { ++ return SSH_ERROR; + } ++ rc = mbedtls_md(md_info, digest, len, hash); ++ if (rc != 0) { ++ return SSH_ERROR; ++ } ++ return SSH_OK; + } + + SHA256CTX sha256_init(void) +@@ -136,25 +157,46 @@ SHA256CTX sha256_init(void) + return ctx; + } + +-void sha256_update(SHA256CTX c, const void *data, unsigned long len) ++void ++sha256_ctx_free(SHA256CTX c) + { +- mbedtls_md_update(c, data, len); ++ mbedtls_md_free(c); ++ SAFE_FREE(c); + } + +-void sha256_final(unsigned char *md, SHA256CTX c) ++int sha256_update(SHA256CTX c, const void *data, unsigned long len) + { +- mbedtls_md_finish(c, md); +- mbedtls_md_free(c); +- SAFE_FREE(c); ++ int rc = mbedtls_md_update(c, data, len); ++ if (rc != 0) { ++ return SSH_ERROR; ++ } ++ return SSH_OK; ++} ++ ++int sha256_final(unsigned char *md, SHA256CTX c) ++{ ++ int rc = mbedtls_md_finish(c, md); ++ sha256_ctx_free(c); ++ if (rc != 0) { ++ return SSH_ERROR; ++ } ++ return SSH_OK; + } + +-void sha256(const unsigned char *digest, int len, unsigned char *hash) ++int sha256(const unsigned char *digest, int len, unsigned char *hash) + { + const mbedtls_md_info_t *md_info = + mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); +- if (md_info != NULL) { +- mbedtls_md(md_info, digest, len, hash); ++ int rc; ++ ++ if (md_info == NULL) { ++ return SSH_ERROR; ++ } ++ rc = mbedtls_md(md_info, digest, len, hash); ++ if (rc != 0) { ++ return SSH_ERROR; + } ++ return SSH_OK; + } + + SHA384CTX sha384_init(void) +@@ -190,25 +232,46 @@ SHA384CTX sha384_init(void) + return ctx; + } + +-void sha384_update(SHA384CTX c, const void *data, unsigned long len) ++void ++sha384_ctx_free(SHA384CTX c) + { +- mbedtls_md_update(c, data, len); ++ mbedtls_md_free(c); ++ SAFE_FREE(c); + } + +-void sha384_final(unsigned char *md, SHA384CTX c) ++int sha384_update(SHA384CTX c, const void *data, unsigned long len) + { +- mbedtls_md_finish(c, md); +- mbedtls_md_free(c); +- SAFE_FREE(c); ++ int rc = mbedtls_md_update(c, data, len); ++ if (rc != 0) { ++ return SSH_ERROR; ++ } ++ return SSH_OK; + } + +-void sha384(const unsigned char *digest, int len, unsigned char *hash) ++int sha384_final(unsigned char *md, SHA384CTX c) ++{ ++ int rc = mbedtls_md_finish(c, md); ++ sha384_ctx_free(c); ++ if (rc != 0) { ++ return SSH_ERROR; ++ } ++ return SSH_OK; ++} ++ ++int sha384(const unsigned char *digest, int len, unsigned char *hash) + { + const mbedtls_md_info_t *md_info = + mbedtls_md_info_from_type(MBEDTLS_MD_SHA384); +- if (md_info != NULL) { +- mbedtls_md(md_info, digest, len, hash); ++ int rc; ++ ++ if (md_info == NULL) { ++ return SSH_ERROR; ++ } ++ rc = mbedtls_md(md_info, digest, len, hash); ++ if (rc != 0) { ++ return SSH_ERROR; + } ++ return SSH_OK; + } + + SHA512CTX sha512_init(void) +@@ -243,25 +306,46 @@ SHA512CTX sha512_init(void) + return ctx; + } + +-void sha512_update(SHA512CTX c, const void *data, unsigned long len) ++void ++sha512_ctx_free(SHA512CTX c) + { +- mbedtls_md_update(c, data, len); ++ mbedtls_md_free(c); ++ SAFE_FREE(c); + } + +-void sha512_final(unsigned char *md, SHA512CTX c) ++int sha512_update(SHA512CTX c, const void *data, unsigned long len) + { +- mbedtls_md_finish(c, md); +- mbedtls_md_free(c); +- SAFE_FREE(c); ++ int rc = mbedtls_md_update(c, data, len); ++ if (rc != 0) { ++ return SSH_ERROR; ++ } ++ return SSH_OK; + } + +-void sha512(const unsigned char *digest, int len, unsigned char *hash) ++int sha512_final(unsigned char *md, SHA512CTX c) ++{ ++ int rc = mbedtls_md_finish(c, md); ++ sha512_ctx_free(c); ++ if (rc != 0) { ++ return SSH_ERROR; ++ } ++ return SSH_OK; ++} ++ ++int sha512(const unsigned char *digest, int len, unsigned char *hash) + { + const mbedtls_md_info_t *md_info = + mbedtls_md_info_from_type(MBEDTLS_MD_SHA512); +- if (md_info != NULL) { +- mbedtls_md(md_info, digest, len, hash); ++ int rc; ++ ++ if (md_info == NULL) { ++ return SSH_ERROR; + } ++ rc = mbedtls_md(md_info, digest, len, hash); ++ if (rc != 0) { ++ return SSH_ERROR; ++ } ++ return SSH_OK; + } + + MD5CTX md5_init(void) +@@ -296,16 +380,30 @@ MD5CTX md5_init(void) + return ctx; + } + ++void ++md5_ctx_free(MD5CTX c) ++{ ++ mbedtls_md_free(c); ++ SAFE_FREE(c); ++} + +-void md5_update(MD5CTX c, const void *data, unsigned long len) { +- mbedtls_md_update(c, data, len); ++int md5_update(MD5CTX c, const void *data, unsigned long len) ++{ ++ int rc = mbedtls_md_update(c, data, len); ++ if (rc != 0) { ++ return SSH_ERROR; ++ } ++ return SSH_OK; + } + +-void md5_final(unsigned char *md, MD5CTX c) ++int md5_final(unsigned char *md, MD5CTX c) + { +- mbedtls_md_finish(c, md); +- mbedtls_md_free(c); +- SAFE_FREE(c); ++ int rc = mbedtls_md_finish(c, md); ++ md5_ctx_free(c); ++ if (rc != 0) { ++ return SSH_ERROR; ++ } ++ return SSH_OK; + } + + int ssh_kdf(struct ssh_crypto_struct *crypto, +diff --git a/src/session.c b/src/session.c +index 0cf59e99..349373aa 100644 +--- a/src/session.c ++++ b/src/session.c +@@ -1001,7 +1001,18 @@ int ssh_get_pubkey_hash(ssh_session session, unsigned char **hash) + *hash = NULL; + if (session->current_crypto == NULL || + session->current_crypto->server_pubkey == NULL) { +- ssh_set_error(session,SSH_FATAL,"No current cryptographic context"); ++ ssh_set_error(session, SSH_FATAL, "No current cryptographic context"); ++ return SSH_ERROR; ++ } ++ ++ rc = ssh_get_server_publickey(session, &pubkey); ++ if (rc != SSH_OK) { ++ return SSH_ERROR; ++ } ++ ++ rc = ssh_pki_export_pubkey_blob(pubkey, &pubkey_blob); ++ ssh_key_free(pubkey); ++ if (rc != SSH_OK) { + return SSH_ERROR; + } + +@@ -1016,25 +1027,21 @@ int ssh_get_pubkey_hash(ssh_session session, unsigned char **hash) + return SSH_ERROR; + } + +- rc = ssh_get_server_publickey(session, &pubkey); ++ rc = md5_update(ctx, ++ ssh_string_data(pubkey_blob), ++ ssh_string_len(pubkey_blob)); + if (rc != SSH_OK) { +- md5_final(h, ctx); ++ md5_ctx_free(ctx); + SAFE_FREE(h); +- return SSH_ERROR; ++ return rc; + } +- +- rc = ssh_pki_export_pubkey_blob(pubkey, &pubkey_blob); +- ssh_key_free(pubkey); ++ SSH_STRING_FREE(pubkey_blob); ++ rc = md5_final(h, ctx); + if (rc != SSH_OK) { +- md5_final(h, ctx); + SAFE_FREE(h); +- return SSH_ERROR; ++ return rc; + } + +- md5_update(ctx, ssh_string_data(pubkey_blob), ssh_string_len(pubkey_blob)); +- SSH_STRING_FREE(pubkey_blob); +- md5_final(h, ctx); +- + *hash = h; + + return MD5_DIGEST_LEN; +@@ -1153,8 +1160,17 @@ int ssh_get_publickey_hash(const ssh_key key, + goto out; + } + +- sha1_update(ctx, ssh_string_data(blob), ssh_string_len(blob)); +- sha1_final(h, ctx); ++ rc = sha1_update(ctx, ssh_string_data(blob), ssh_string_len(blob)); ++ if (rc != SSH_OK) { ++ free(h); ++ sha1_ctx_free(ctx); ++ goto out; ++ } ++ rc = sha1_final(h, ctx); ++ if (rc != SSH_OK) { ++ free(h); ++ goto out; ++ } + + *hlen = SHA_DIGEST_LEN; + } +@@ -1176,8 +1192,17 @@ int ssh_get_publickey_hash(const ssh_key key, + goto out; + } + +- sha256_update(ctx, ssh_string_data(blob), ssh_string_len(blob)); +- sha256_final(h, ctx); ++ rc = sha256_update(ctx, ssh_string_data(blob), ssh_string_len(blob)); ++ if (rc != SSH_OK) { ++ free(h); ++ sha256_ctx_free(ctx); ++ goto out; ++ } ++ rc = sha256_final(h, ctx); ++ if (rc != SSH_OK) { ++ free(h); ++ goto out; ++ } + + *hlen = SHA256_DIGEST_LEN; + } +@@ -1207,8 +1232,17 @@ int ssh_get_publickey_hash(const ssh_key key, + goto out; + } + +- md5_update(ctx, ssh_string_data(blob), ssh_string_len(blob)); +- md5_final(h, ctx); ++ rc = md5_update(ctx, ssh_string_data(blob), ssh_string_len(blob)); ++ if (rc != SSH_OK) { ++ free(h); ++ md5_ctx_free(ctx); ++ goto out; ++ } ++ rc = md5_final(h, ctx); ++ if (rc != SSH_OK) { ++ free(h); ++ goto out; ++ } + + *hlen = MD5_DIGEST_LEN; + } +-- +2.41.0 + + +From 9276027c687723886e8277b77061464303845831 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Fri, 15 Dec 2023 13:35:14 +0100 +Subject: [PATCH 4/5] CVE-2023-6918: kdf: Detect context init failures + +Signed-off-by: Jakub Jelen +Reviewed-by: Andreas Schneider +--- + src/kdf.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +diff --git a/src/kdf.c b/src/kdf.c +index 90f6e9f3..b08f0b2f 100644 +--- a/src/kdf.c ++++ b/src/kdf.c +@@ -61,20 +61,32 @@ static ssh_mac_ctx ssh_mac_ctx_init(enum ssh_kdf_digest type) + switch (type) { + case SSH_KDF_SHA1: + ctx->ctx.sha1_ctx = sha1_init(); ++ if (ctx->ctx.sha1_ctx == NULL) { ++ goto err; ++ } + return ctx; + case SSH_KDF_SHA256: + ctx->ctx.sha256_ctx = sha256_init(); ++ if (ctx->ctx.sha256_ctx == NULL) { ++ goto err; ++ } + return ctx; + case SSH_KDF_SHA384: + ctx->ctx.sha384_ctx = sha384_init(); ++ if (ctx->ctx.sha384_ctx == NULL) { ++ goto err; ++ } + return ctx; + case SSH_KDF_SHA512: + ctx->ctx.sha512_ctx = sha512_init(); ++ if (ctx->ctx.sha512_ctx == NULL) { ++ goto err; ++ } + return ctx; +- default: +- SAFE_FREE(ctx); +- return NULL; + } ++err: ++ SAFE_FREE(ctx); ++ return NULL; + } + + static void ssh_mac_ctx_free(ssh_mac_ctx ctx) +-- +2.41.0 + + +From aef4a470003bdede61fa17c22418d25ccedaa983 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Fri, 15 Dec 2023 15:39:12 +0100 +Subject: [PATCH 5/5] CVE-2023-6918: tests: Code coverage for + ssh_get_pubkey_hash() + +Signed-off-by: Jakub Jelen +Reviewed-by: Andreas Schneider +--- + tests/client/torture_session.c | 35 ++++++++++++++++++++++++++++++++++ + 1 file changed, 35 insertions(+) + +diff --git a/tests/client/torture_session.c b/tests/client/torture_session.c +index b5ed7a62..abe458d0 100644 +--- a/tests/client/torture_session.c ++++ b/tests/client/torture_session.c +@@ -118,12 +118,47 @@ static void torture_channel_read_error(void **state) { + ssh_channel_free(channel); + } + ++static void torture_pubkey_hash(void **state) ++{ ++ struct torture_state *s = *state; ++ ssh_session session = s->ssh.session; ++ char *hash = NULL; ++ char *hexa = NULL; ++ int rc = 0; ++ ++ /* bad arguments */ ++ rc = ssh_get_pubkey_hash(session, NULL); ++ assert_int_equal(rc, SSH_ERROR); ++ ++ rc = ssh_get_pubkey_hash(NULL, (unsigned char **)&hash); ++ assert_int_equal(rc, SSH_ERROR); ++ ++ /* deprecated, but should be covered by tests! */ ++ rc = ssh_get_pubkey_hash(session, (unsigned char **)&hash); ++ if (ssh_fips_mode()) { ++ /* When in FIPS mode, expect the call to fail */ ++ assert_int_equal(rc, SSH_ERROR); ++ } else { ++ assert_int_equal(rc, MD5_DIGEST_LEN); ++ ++ hexa = ssh_get_hexa((unsigned char *)hash, rc); ++ SSH_STRING_FREE_CHAR(hash); ++ assert_string_equal(hexa, ++ "ee:80:7f:61:f9:d5:be:f1:96:86:cc:96:7a:db:7a:7b"); ++ ++ SSH_STRING_FREE_CHAR(hexa); ++ } ++} ++ + int torture_run_tests(void) { + int rc; + struct CMUnitTest tests[] = { + cmocka_unit_test_setup_teardown(torture_channel_read_error, + session_setup, + session_teardown), ++ cmocka_unit_test_setup_teardown(torture_pubkey_hash, ++ session_setup, ++ session_teardown), + }; + + ssh_init(); +-- +2.41.0 + diff --git a/root/ppg/common/deps/libssh/rpm/CVE-2025-5318.patch b/root/ppg/common/deps/libssh/rpm/CVE-2025-5318.patch new file mode 100644 index 00000000..fddd2e8b --- /dev/null +++ b/root/ppg/common/deps/libssh/rpm/CVE-2025-5318.patch @@ -0,0 +1,27 @@ +From 9a08a370f68266f92df5a6037bd722041703df27 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Tue, 22 Apr 2025 21:18:44 +0200 +Subject: [PATCH] CVE-2025-5318: sftpserver: Fix possible buffer overrun + +Signed-off-by: Jakub Jelen +Reviewed-by: Andreas Schneider +--- + src/sftpserver.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/sftpserver.c b/src/sftpserver.c +index 9117f155..b3349e16 100644 +--- a/src/sftpserver.c ++++ b/src/sftpserver.c +@@ -538,7 +538,7 @@ void *sftp_handle(sftp_session sftp, ssh_string handle){ + + memcpy(&val, ssh_string_data(handle), sizeof(uint32_t)); + +- if (val > SFTP_HANDLES) { ++ if (val >= SFTP_HANDLES) { + return NULL; + } + +-- +2.50.1 + diff --git a/root/ppg/common/deps/libssh/rpm/CVE-2025-5372.patch b/root/ppg/common/deps/libssh/rpm/CVE-2025-5372.patch new file mode 100644 index 00000000..c60d1cef --- /dev/null +++ b/root/ppg/common/deps/libssh/rpm/CVE-2025-5372.patch @@ -0,0 +1,42 @@ +From 155df31305bee839041a04247645ad066ada95ee Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Wed, 14 May 2025 14:07:58 +0200 +Subject: [PATCH] CVE-2025-5372 libgcrypto: Simplify error checking and + handling of return codes in ssh_kdf() + +Signed-off-by: Jakub Jelen +Reviewed-by: Andreas Schneider +--- + src/libcrypto.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/src/libcrypto.c b/src/libcrypto.c +index 3db75df6..88d93862 100644 +--- a/src/libcrypto.c ++++ b/src/libcrypto.c +@@ -366,6 +366,7 @@ int ssh_kdf(struct ssh_crypto_struct *crypto, + int key_type, unsigned char *output, + size_t requested_len) + { ++ int ret = SSH_ERROR; + EVP_KDF_CTX *ctx = EVP_KDF_CTX_new_id(EVP_KDF_SSHKDF); + int rc; + +@@ -401,10 +402,12 @@ int ssh_kdf(struct ssh_crypto_struct *crypto, + goto out; + } + ++ ret = SSH_OK; ++ + out: + EVP_KDF_CTX_free(ctx); +- if (rc < 0) { +- return rc; ++ if (ret < 0) { ++ return ret; + } + return 0; + } +-- +2.51.0 + diff --git a/root/ppg/common/deps/libssh/rpm/auth_bypass.patch b/root/ppg/common/deps/libssh/rpm/auth_bypass.patch new file mode 100644 index 00000000..8b91601e --- /dev/null +++ b/root/ppg/common/deps/libssh/rpm/auth_bypass.patch @@ -0,0 +1,86 @@ +diff --color -ru ../libssh-0.9.6/src/pki_crypto.c ./src/pki_crypto.c +--- ../libssh-0.9.6/src/pki_crypto.c 2023-04-27 12:59:08.463259052 +0200 ++++ ./src/pki_crypto.c 2023-04-27 13:05:24.020610873 +0200 +@@ -2291,8 +2291,12 @@ + unsigned char *raw_sig_data = NULL; + unsigned int raw_sig_len; + ++ /* Function return code ++ * Do not change this variable throughout the function until the signature ++ * is successfully verified! ++ */ + int rc = SSH_ERROR; +- int evp_rc; ++ int ok; + + if (pubkey == NULL || ssh_key_is_private(pubkey) || input == NULL || + signature == NULL || (signature->raw_sig == NULL +@@ -2307,8 +2311,8 @@ + } + + /* Check if public key and hash type are compatible */ +- rc = pki_key_check_hash_compatible(pubkey, signature->hash_type); +- if (rc != SSH_OK) { ++ ok = pki_key_check_hash_compatible(pubkey, signature->hash_type); ++ if (ok != SSH_OK) { + return SSH_ERROR; + } + +@@ -2351,8 +2355,8 @@ + } + + /* Verify the signature */ +- evp_rc = EVP_DigestVerifyInit(ctx, NULL, md, NULL, pkey); +- if (evp_rc != 1){ ++ ok = EVP_DigestVerifyInit(ctx, NULL, md, NULL, pkey); ++ if (ok != 1){ + SSH_LOG(SSH_LOG_TRACE, + "EVP_DigestVerifyInit() failed: %s", + ERR_error_string(ERR_get_error(), NULL)); +@@ -2360,35 +2364,31 @@ + } + + #ifdef HAVE_OPENSSL_EVP_DIGESTVERIFY +- evp_rc = EVP_DigestVerify(ctx, raw_sig_data, raw_sig_len, input, input_len); ++ ok = EVP_DigestVerify(ctx, raw_sig_data, raw_sig_len, input, input_len); + #else +- evp_rc = EVP_DigestVerifyUpdate(ctx, input, input_len); +- if (evp_rc != 1) { ++ ok = EVP_DigestVerifyUpdate(ctx, input, input_len); ++ if (ok != 1) { + SSH_LOG(SSH_LOG_TRACE, + "EVP_DigestVerifyUpdate() failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto out; + } + +- evp_rc = EVP_DigestVerifyFinal(ctx, raw_sig_data, raw_sig_len); ++ ok = EVP_DigestVerifyFinal(ctx, raw_sig_data, raw_sig_len); + #endif +- if (evp_rc == 1) { +- SSH_LOG(SSH_LOG_TRACE, "Signature valid"); +- rc = SSH_OK; +- } else { ++ if (ok != 1) { + SSH_LOG(SSH_LOG_TRACE, + "Signature invalid: %s", + ERR_error_string(ERR_get_error(), NULL)); +- rc = SSH_ERROR; ++ goto out; + } + ++ SSH_LOG(SSH_LOG_TRACE, "Signature valid"); ++ rc = SSH_OK; ++ + out: +- if (ctx != NULL) { +- EVP_MD_CTX_free(ctx); +- } +- if (pkey != NULL) { +- EVP_PKEY_free(pkey); +- } ++ EVP_MD_CTX_free(ctx); ++ EVP_PKEY_free(pkey); + return rc; + } + diff --git a/root/ppg/common/deps/libssh/rpm/covscan23.patch b/root/ppg/common/deps/libssh/rpm/covscan23.patch new file mode 100644 index 00000000..a79658f8 --- /dev/null +++ b/root/ppg/common/deps/libssh/rpm/covscan23.patch @@ -0,0 +1,228 @@ +diff --color -ru ../libssh-0.9.6/src/buffer.c ./src/buffer.c +--- ../libssh-0.9.6/src/buffer.c 2023-05-03 11:53:48.710217753 +0200 ++++ ./src/buffer.c 2023-05-03 11:58:21.995200990 +0200 +@@ -747,7 +747,8 @@ + */ + int ssh_buffer_validate_length(struct ssh_buffer_struct *buffer, size_t len) + { +- if (buffer->pos + len < len || buffer->pos + len > buffer->used) { ++ if (buffer == NULL || buffer->pos + len < len || ++ buffer->pos + len > buffer->used) { + return SSH_ERROR; + } + +diff --color -ru ../libssh-0.9.6/src/gssapi.c ./src/gssapi.c +--- ../libssh-0.9.6/src/gssapi.c 2023-05-03 11:53:48.732217993 +0200 ++++ ./src/gssapi.c 2023-05-03 11:58:21.976200782 +0200 +@@ -437,11 +437,18 @@ + hexa = ssh_get_hexa(output_token.value, output_token.length); + SSH_LOG(SSH_LOG_PACKET, "GSSAPI: sending token %s",hexa); + SAFE_FREE(hexa); +- ssh_buffer_pack(session->out_buffer, +- "bdP", +- SSH2_MSG_USERAUTH_GSSAPI_TOKEN, +- output_token.length, +- (size_t)output_token.length, output_token.value); ++ rc = ssh_buffer_pack(session->out_buffer, ++ "bdP", ++ SSH2_MSG_USERAUTH_GSSAPI_TOKEN, ++ output_token.length, ++ (size_t)output_token.length, output_token.value); ++ if (rc != SSH_OK) { ++ ssh_set_error_oom(session); ++ ssh_auth_reply_default(session, 0); ++ ssh_gssapi_free(session); ++ session->gssapi = NULL; ++ return SSH_PACKET_USED; ++ } + ssh_packet_send(session); + } + +@@ -846,6 +853,7 @@ + } + + SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_response){ ++ int rc; + ssh_string oid_s; + gss_uint32 maj_stat, min_stat; + gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; +@@ -897,11 +905,15 @@ + hexa = ssh_get_hexa(output_token.value, output_token.length); + SSH_LOG(SSH_LOG_PACKET, "GSSAPI: sending token %s", hexa); + SAFE_FREE(hexa); +- ssh_buffer_pack(session->out_buffer, +- "bdP", +- SSH2_MSG_USERAUTH_GSSAPI_TOKEN, +- output_token.length, +- (size_t)output_token.length, output_token.value); ++ rc = ssh_buffer_pack(session->out_buffer, ++ "bdP", ++ SSH2_MSG_USERAUTH_GSSAPI_TOKEN, ++ output_token.length, ++ (size_t)output_token.length, output_token.value); ++ if (rc != SSH_OK) { ++ ssh_set_error_oom(session); ++ goto error; ++ } + ssh_packet_send(session); + session->auth.state = SSH_AUTH_STATE_GSSAPI_TOKEN; + } +@@ -963,6 +975,7 @@ + } + + SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_client){ ++ int rc; + ssh_string token; + char *hexa; + OM_uint32 maj_stat, min_stat; +@@ -1015,11 +1028,15 @@ + hexa = ssh_get_hexa(output_token.value, output_token.length); + SSH_LOG(SSH_LOG_PACKET, "GSSAPI: sending token %s",hexa); + SAFE_FREE(hexa); +- ssh_buffer_pack(session->out_buffer, +- "bdP", +- SSH2_MSG_USERAUTH_GSSAPI_TOKEN, +- output_token.length, +- (size_t)output_token.length, output_token.value); ++ rc = ssh_buffer_pack(session->out_buffer, ++ "bdP", ++ SSH2_MSG_USERAUTH_GSSAPI_TOKEN, ++ output_token.length, ++ (size_t)output_token.length, output_token.value); ++ if (rc != SSH_OK) { ++ ssh_set_error_oom(session); ++ goto error; ++ } + ssh_packet_send(session); + } + +diff --color -ru ../libssh-0.9.6/src/options.c ./src/options.c +--- ../libssh-0.9.6/src/options.c 2021-08-26 14:27:42.000000000 +0200 ++++ ./src/options.c 2023-05-03 11:58:22.000201044 +0200 +@@ -547,7 +547,9 @@ + } + i = strtol(q, &p, 10); + if (q == p) { ++ SSH_LOG(SSH_LOG_DEBUG, "No port number was parsed"); + SAFE_FREE(q); ++ return -1; + } + SAFE_FREE(q); + if (i <= 0) { +@@ -743,7 +745,9 @@ + } + i = strtol(q, &p, 10); + if (q == p) { ++ SSH_LOG(SSH_LOG_DEBUG, "No log verbositiy was parsed"); + SAFE_FREE(q); ++ return -1; + } + SAFE_FREE(q); + if (i < 0) { +@@ -1818,7 +1822,9 @@ + } + i = strtol(q, &p, 10); + if (q == p) { +- SAFE_FREE(q); ++ SSH_LOG(SSH_LOG_DEBUG, "No bind port was parsed"); ++ SAFE_FREE(q); ++ return -1; + } + SAFE_FREE(q); + +@@ -1845,7 +1851,9 @@ + } + i = strtol(q, &p, 10); + if (q == p) { +- SAFE_FREE(q); ++ SSH_LOG(SSH_LOG_DEBUG, "No log verbositiy was parsed"); ++ SAFE_FREE(q); ++ return -1; + } + SAFE_FREE(q); + +diff --color -ru ../libssh-0.9.6/src/pki_container_openssh.c ./src/pki_container_openssh.c +--- ../libssh-0.9.6/src/pki_container_openssh.c 2023-05-03 11:53:48.713217785 +0200 ++++ ./src/pki_container_openssh.c 2023-05-03 11:58:21.976200782 +0200 +@@ -630,7 +630,11 @@ + goto error; + } + +- ssh_buffer_pack(kdf_buf, "Sd", salt, rounds); ++ rc = ssh_buffer_pack(kdf_buf, "Sd", salt, rounds); ++ if (rc != SSH_OK) { ++ SSH_BUFFER_FREE(kdf_buf); ++ goto error; ++ } + kdf_options = ssh_string_new(ssh_buffer_get_len(kdf_buf)); + if (kdf_options == NULL){ + SSH_BUFFER_FREE(kdf_buf); +diff --color -ru ../libssh-0.9.6/tests/unittests/torture_options.c ./tests/unittests/torture_options.c +--- ../libssh-0.9.6/tests/unittests/torture_options.c 2021-08-26 14:27:42.000000000 +0200 ++++ ./tests/unittests/torture_options.c 2023-05-03 11:59:21.726853027 +0200 +@@ -311,6 +311,7 @@ + + rc = ssh_options_set(session, SSH_OPTIONS_PORT_STR, "five"); + assert_true(rc == -1); ++ assert_int_not_equal(session->opts.port, 0); + + rc = ssh_options_set(session, SSH_OPTIONS_PORT, NULL); + assert_true(rc == -1); +@@ -853,6 +854,26 @@ + ssh_free(new); + } + ++static void torture_options_set_verbosity (void **state) ++{ ++ ssh_session session = *state; ++ int rc, new_level; ++ ++ rc = ssh_options_set(session, ++ SSH_OPTIONS_LOG_VERBOSITY_STR, ++ "3"); ++ assert_int_equal(rc, SSH_OK); ++ new_level = ssh_get_log_level(); ++ assert_int_equal(new_level, SSH_LOG_PACKET); ++ ++ rc = ssh_options_set(session, ++ SSH_OPTIONS_LOG_VERBOSITY_STR, ++ "datsun"); ++ assert_int_equal(rc, -1); ++ new_level = ssh_get_log_level(); ++ assert_int_not_equal(new_level, 0); ++} ++ + #ifdef WITH_SERVER + const char template[] = "temp_dir_XXXXXX"; + +@@ -1107,6 +1128,10 @@ + rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_BINDPORT_STR, "23"); + assert_int_equal(rc, 0); + assert_int_equal(bind->bindport, 23); ++ ++ rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_BINDPORT_STR, "twentythree"); ++ assert_int_equal(rc, -1); ++ assert_int_not_equal(bind->bindport, 0); + } + + static void torture_bind_options_log_verbosity(void **state) +@@ -1156,6 +1181,11 @@ + new_level = ssh_get_log_level(); + assert_int_equal(new_level, SSH_LOG_PACKET); + ++ rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, "verbosity"); ++ assert_int_equal(rc, -1); ++ new_level = ssh_get_log_level(); ++ assert_int_not_equal(new_level, 0); ++ + rc = ssh_set_log_level(previous_level); + assert_int_equal(rc, SSH_OK); + } +@@ -1643,6 +1673,7 @@ + cmocka_unit_test_setup_teardown(torture_options_config_host, setup, teardown), + cmocka_unit_test_setup_teardown(torture_options_config_match, + setup, teardown), ++ cmocka_unit_test_setup_teardown(torture_options_set_verbosity, setup, teardown), + }; + + #ifdef WITH_SERVER diff --git a/root/ppg/common/deps/libssh/rpm/fix_tests.patch b/root/ppg/common/deps/libssh/rpm/fix_tests.patch new file mode 100644 index 00000000..084fb498 --- /dev/null +++ b/root/ppg/common/deps/libssh/rpm/fix_tests.patch @@ -0,0 +1,668 @@ +diff --color -ru ../libssh-0.9.6/examples/sshnetcat.c ./examples/sshnetcat.c +--- ../libssh-0.9.6/examples/sshnetcat.c 2021-08-26 14:27:42.000000000 +0200 ++++ ./examples/sshnetcat.c 2023-05-02 10:36:00.793381735 +0200 +@@ -233,9 +233,10 @@ + } + + void cleanup_pcap(void); +-void cleanup_pcap(){ ++void cleanup_pcap(void) ++{ + ssh_pcap_file_free(pcap); +- pcap=NULL; ++ pcap = NULL; + } + #endif + +diff --color -ru ../libssh-0.9.6/src/init.c ./src/init.c +--- ../libssh-0.9.6/src/init.c 2021-03-15 08:11:33.000000000 +0100 ++++ ./src/init.c 2023-05-02 10:36:00.793381735 +0200 +@@ -269,7 +269,7 @@ + * + * @see ssh_init() + */ +-bool is_ssh_initialized() { ++bool is_ssh_initialized(void) { + + bool is_initialized = false; + +diff --color -ru ../libssh-0.9.6/tests/client/torture_auth.c ./tests/client/torture_auth.c +--- ../libssh-0.9.6/tests/client/torture_auth.c 2021-08-26 14:27:42.000000000 +0200 ++++ ./tests/client/torture_auth.c 2023-05-02 10:36:00.815381960 +0200 +@@ -200,7 +200,8 @@ + assert_non_null(ssh_agent_pidfile); + + /* kill agent pid */ +- torture_terminate_process(ssh_agent_pidfile); ++ rc = torture_terminate_process(ssh_agent_pidfile); ++ assert_return_code(rc, errno); + + unlink(ssh_agent_pidfile); + +@@ -551,6 +552,7 @@ + + static void torture_auth_agent_cert(void **state) + { ++#if OPENSSH_VERSION_MAJOR < 8 || (OPENSSH_VERSION_MAJOR == 8 && OPENSSH_VERSION_MINOR == 0) + struct torture_state *s = *state; + ssh_session session = s->ssh.session; + int rc; +@@ -570,6 +572,7 @@ + "ssh-rsa-cert-v01@openssh.com"); + assert_int_equal(rc, SSH_OK); + } ++#endif /* OPENSSH_VERSION_MAJOR < 8.1 */ + + /* Setup loads a different key, tests are exactly the same. */ + torture_auth_agent(state); +@@ -577,6 +580,7 @@ + + static void torture_auth_agent_cert_nonblocking(void **state) + { ++#if OPENSSH_VERSION_MAJOR < 8 || (OPENSSH_VERSION_MAJOR == 8 && OPENSSH_VERSION_MINOR == 0) + struct torture_state *s = *state; + ssh_session session = s->ssh.session; + int rc; +@@ -596,6 +600,7 @@ + "ssh-rsa-cert-v01@openssh.com"); + assert_int_equal(rc, SSH_OK); + } ++#endif /* OPENSSH_VERSION_MAJOR < 8.1 */ + + torture_auth_agent_nonblocking(state); + } +diff --color -ru ../libssh-0.9.6/tests/client/torture_rekey.c ./tests/client/torture_rekey.c +--- ../libssh-0.9.6/tests/client/torture_rekey.c 2023-04-28 17:26:41.472315318 +0200 ++++ ./tests/client/torture_rekey.c 2023-05-02 10:36:00.805381857 +0200 +@@ -38,6 +38,8 @@ + #include + #include + ++#define KEX_RETRY 32 ++ + static uint64_t bytes = 2048; /* 2KB (more than the authentication phase) */ + + static int sshd_setup(void **state) +@@ -190,10 +192,11 @@ + rc = ssh_userauth_publickey_auto(s->ssh.session, NULL, NULL); + assert_int_equal(rc, SSH_AUTH_SUCCESS); + +- /* send ignore packets of up to 1KB to trigger rekey */ ++ /* send ignore packets of up to 1KB to trigger rekey. Send little bit more ++ * to make sure it completes with all different ciphers */ + memset(data, 0, sizeof(data)); + memset(data, 'A', 128); +- for (i = 0; i < 16; i++) { ++ for (i = 0; i < KEX_RETRY; i++) { + ssh_send_ignore(s->ssh.session, data); + ssh_handle_packets(s->ssh.session, 50); + } +@@ -496,9 +499,15 @@ + * to make sure the rekey it completes with all different ciphers (paddings */ + memset(data, 0, sizeof(data)); + memset(data, 'A', 128); +- for (i = 0; i < 20; i++) { ++ for (i = 0; i < KEX_RETRY; i++) { + ssh_send_ignore(s->ssh.session, data); +- ssh_handle_packets(s->ssh.session, 50); ++ ssh_handle_packets(s->ssh.session, 100); ++ ++ c = s->ssh.session->current_crypto; ++ /* SHA256 len */ ++ if (c->digest_len != 32) { ++ break; ++ } + } + + /* The rekey limit was restored in the new crypto to the same value */ +@@ -568,9 +577,15 @@ + * to make sure the rekey it completes with all different ciphers (paddings */ + memset(data, 0, sizeof(data)); + memset(data, 'A', 128); +- for (i = 0; i < 25; i++) { ++ for (i = 0; i < KEX_RETRY; i++) { + ssh_send_ignore(s->ssh.session, data); +- ssh_handle_packets(s->ssh.session, 50); ++ ssh_handle_packets(s->ssh.session, 100); ++ ++ c = s->ssh.session->current_crypto; ++ /* SHA256 len */ ++ if (c->digest_len != 32) { ++ break; ++ } + } + + /* Check that the secret hash is different than initially */ +diff --color -ru ../libssh-0.9.6/tests/CMakeLists.txt ./tests/CMakeLists.txt +--- ../libssh-0.9.6/tests/CMakeLists.txt 2021-08-26 14:27:42.000000000 +0200 ++++ ./tests/CMakeLists.txt 2023-05-02 10:32:03.964511860 +0200 +@@ -153,6 +153,17 @@ + execute_process(COMMAND ${ID_EXECUTABLE} -u OUTPUT_VARIABLE LOCAL_UID OUTPUT_STRIP_TRAILING_WHITESPACE) + endif() + ++ find_program(TIMEOUT_EXECUTABLE ++ NAME ++ timeout ++ PATHS ++ /bin ++ /usr/bin ++ /usr/local/bin) ++ if (TIMEOUT_EXECUTABLE) ++ set(WITH_TIMEOUT "1") ++ endif() ++ + # chroot_wrapper + add_library(chroot_wrapper SHARED chroot_wrapper.c) + set(CHROOT_WRAPPER_LIBRARY ${libssh_BINARY_DIR}/lib/${CMAKE_SHARED_LIBRARY_PREFIX}chroot_wrapper${CMAKE_SHARED_LIBRARY_SUFFIX}) +diff --color -ru ../libssh-0.9.6/tests/pkd/pkd_keyutil.c ./tests/pkd/pkd_keyutil.c +--- ../libssh-0.9.6/tests/pkd/pkd_keyutil.c 2021-03-15 08:11:33.000000000 +0100 ++++ ./tests/pkd/pkd_keyutil.c 2023-05-02 10:36:00.793381735 +0200 +@@ -22,7 +22,7 @@ + #include "pkd_keyutil.h" + #include "pkd_util.h" + +-void setup_rsa_key() { ++void setup_rsa_key(void) { + int rc = 0; + if (access(LIBSSH_RSA_TESTKEY, F_OK) != 0) { + rc = system_checked(OPENSSH_KEYGEN " -t rsa -q -N \"\" -f " +@@ -31,7 +31,7 @@ + assert_int_equal(rc, 0); + } + +-void setup_ed25519_key() { ++void setup_ed25519_key(void) { + int rc = 0; + if (access(LIBSSH_ED25519_TESTKEY, F_OK) != 0) { + rc = system_checked(OPENSSH_KEYGEN " -t ed25519 -q -N \"\" -f " +@@ -41,7 +41,7 @@ + } + + #ifdef HAVE_DSA +-void setup_dsa_key() { ++void setup_dsa_key(void) { + int rc = 0; + if (access(LIBSSH_DSA_TESTKEY, F_OK) != 0) { + rc = system_checked(OPENSSH_KEYGEN " -t dsa -q -N \"\" -f " +@@ -51,7 +51,7 @@ + } + #endif + +-void setup_ecdsa_keys() { ++void setup_ecdsa_keys(void) { + int rc = 0; + + if (access(LIBSSH_ECDSA_256_TESTKEY, F_OK) != 0) { +@@ -71,27 +71,27 @@ + } + } + +-void cleanup_rsa_key() { ++void cleanup_rsa_key(void) { + cleanup_key(LIBSSH_RSA_TESTKEY); + } + +-void cleanup_ed25519_key() { ++void cleanup_ed25519_key(void) { + cleanup_key(LIBSSH_ED25519_TESTKEY); + } + + #ifdef HAVE_DSA +-void cleanup_dsa_key() { ++void cleanup_dsa_key(void) { + cleanup_key(LIBSSH_DSA_TESTKEY); + } + #endif + +-void cleanup_ecdsa_keys() { ++void cleanup_ecdsa_keys(void) { + cleanup_key(LIBSSH_ECDSA_256_TESTKEY); + cleanup_key(LIBSSH_ECDSA_384_TESTKEY); + cleanup_key(LIBSSH_ECDSA_521_TESTKEY); + } + +-void setup_openssh_client_keys() { ++void setup_openssh_client_keys(void) { + int rc = 0; + + if (access(OPENSSH_CA_TESTKEY, F_OK) != 0) { +@@ -184,7 +184,7 @@ + } + } + +-void cleanup_openssh_client_keys() { ++void cleanup_openssh_client_keys(void) { + cleanup_key(OPENSSH_CA_TESTKEY); + cleanup_key(OPENSSH_RSA_TESTKEY); + cleanup_file(OPENSSH_RSA_TESTKEY "-sha256-cert.pub"); +@@ -199,7 +199,7 @@ + } + } + +-void setup_dropbear_client_rsa_key() { ++void setup_dropbear_client_rsa_key(void) { + int rc = 0; + if (access(DROPBEAR_RSA_TESTKEY, F_OK) != 0) { + rc = system_checked(DROPBEAR_KEYGEN " -t rsa -f " +@@ -208,6 +208,6 @@ + assert_int_equal(rc, 0); + } + +-void cleanup_dropbear_client_rsa_key() { ++void cleanup_dropbear_client_rsa_key(void) { + unlink(DROPBEAR_RSA_TESTKEY); + } +diff --color -ru ../libssh-0.9.6/tests/server/torture_server_config.c ./tests/server/torture_server_config.c +--- ../libssh-0.9.6/tests/server/torture_server_config.c 2021-08-26 14:27:42.000000000 +0200 ++++ ./tests/server/torture_server_config.c 2023-05-02 10:36:00.815381960 +0200 +@@ -285,9 +285,7 @@ + assert_non_null(s); + + rc = torture_terminate_process(s->srv_pidfile); +- if (rc != 0) { +- fprintf(stderr, "XXXXXX Failed to terminate sshd\n"); +- } ++ assert_return_code(rc, errno); + + unlink(s->srv_pidfile); + +@@ -513,6 +511,12 @@ + /* Try each algorithm individually */ + j = 0; + while(tokens->tokens[j] != NULL) { ++ char *cmp = strstr(OPENSSH_CIPHERS, tokens->tokens[j]); ++ if (cmp == NULL) { ++ /* This cipher is not supported by the OpenSSH. Skip it */ ++ j++; ++ continue; ++ } + snprintf(config_content, + sizeof(config_content), + "HostKey %s\nCiphers %s\n", +diff --color -ru ../libssh-0.9.6/tests/tests_config.h.cmake ./tests/tests_config.h.cmake +--- ../libssh-0.9.6/tests/tests_config.h.cmake 2021-08-26 14:27:42.000000000 +0200 ++++ ./tests/tests_config.h.cmake 2023-05-02 10:32:03.964511860 +0200 +@@ -66,4 +66,6 @@ + + #cmakedefine NC_EXECUTABLE "${NC_EXECUTABLE}" + #cmakedefine SSHD_EXECUTABLE "${SSHD_EXECUTABLE}" +-#cmakedefine SSH_EXECUTABLE "${SSH_EXECUTABLE}" +\ No newline at end of file ++#cmakedefine SSH_EXECUTABLE "${SSH_EXECUTABLE}" ++#cmakedefine WITH_TIMEOUT ${WITH_TIMEOUT} ++#cmakedefine TIMEOUT_EXECUTABLE "${TIMEOUT_EXECUTABLE}" +diff --color -ru ../libssh-0.9.6/tests/torture.c ./tests/torture.c +--- ../libssh-0.9.6/tests/torture.c 2021-08-26 14:27:44.000000000 +0200 ++++ ./tests/torture.c 2023-05-02 10:36:00.815381960 +0200 +@@ -51,6 +51,7 @@ + #include "torture.h" + #include "torture_key.h" + #include "libssh/misc.h" ++#include "libssh/token.h" + + #define TORTURE_SSHD_SRV_IPV4 "127.0.0.10" + /* socket wrapper IPv6 prefix fd00::5357:5fxx */ +@@ -250,8 +251,12 @@ + + rc = kill(pid, 0); + if (rc != 0) { +- is_running = 0; +- break; ++ /* Process not found */ ++ if (errno == ESRCH) { ++ is_running = 0; ++ rc = 0; ++ break; ++ } + } + } + +@@ -260,7 +265,7 @@ + "WARNING: The process with pid %u is still running!\n", pid); + } + +- return 0; ++ return rc; + } + + ssh_session torture_ssh_session(struct torture_state *s, +@@ -611,6 +616,112 @@ + *state = s; + } + ++/** ++ * @brief Create a libssh server configuration file ++ * ++ * It is expected the socket directory to be already created before by calling ++ * torture_setup_socket_dir(). The created configuration file will be stored in ++ * the socket directory and the srv_config pointer in the state will be ++ * initialized. ++ * ++ * @param[in] state A pointer to a pointer to an initialized torture_state ++ * structure ++ */ ++void torture_setup_create_libssh_config(void **state) ++{ ++ struct torture_state *s = *state; ++ char ed25519_hostkey[1024] = {0}; ++#ifdef HAVE_DSA ++ char dsa_hostkey[1024]; ++#endif /* HAVE_DSA */ ++ char rsa_hostkey[1024]; ++ char ecdsa_hostkey[1024]; ++ char sshd_config[2048]; ++ char sshd_path[1024]; ++ const char *additional_config = NULL; ++ struct stat sb; ++ const char config_string[]= ++ "LogLevel DEBUG3\n" ++ "Port 22\n" ++ "ListenAddress 127.0.0.10\n" ++ "%s %s\n" ++ "%s %s\n" ++ "%s %s\n" ++#ifdef HAVE_DSA ++ "%s %s\n" ++#endif /* HAVE_DSA */ ++ "%s\n"; /* The space for test-specific options */ ++ bool written = false; ++ int rc; ++ ++ assert_non_null(s->socket_dir); ++ ++ snprintf(sshd_path, ++ sizeof(sshd_path), ++ "%s/sshd", ++ s->socket_dir); ++ ++ rc = lstat(sshd_path, &sb); ++ if (rc == 0 ) { /* The directory is already in place */ ++ written = true; ++ } ++ ++ if (!written) { ++ rc = mkdir(sshd_path, 0755); ++ assert_return_code(rc, errno); ++ } ++ ++ snprintf(ed25519_hostkey, ++ sizeof(ed25519_hostkey), ++ "%s/sshd/ssh_host_ed25519_key", ++ s->socket_dir); ++ ++ snprintf(rsa_hostkey, ++ sizeof(rsa_hostkey), ++ "%s/sshd/ssh_host_rsa_key", ++ s->socket_dir); ++ ++ snprintf(ecdsa_hostkey, ++ sizeof(ecdsa_hostkey), ++ "%s/sshd/ssh_host_ecdsa_key", ++ s->socket_dir); ++ ++#ifdef HAVE_DSA ++ snprintf(dsa_hostkey, ++ sizeof(dsa_hostkey), ++ "%s/sshd/ssh_host_dsa_key", ++ s->socket_dir); ++#endif /* HAVE_DSA */ ++ ++ if (!written) { ++ torture_write_file(ed25519_hostkey, ++ torture_get_openssh_testkey(SSH_KEYTYPE_ED25519, 0)); ++ torture_write_file(rsa_hostkey, ++ torture_get_testkey(SSH_KEYTYPE_RSA, 0)); ++ torture_write_file(ecdsa_hostkey, ++ torture_get_testkey(SSH_KEYTYPE_ECDSA_P521, 0)); ++#ifdef HAVE_DSA ++ torture_write_file(dsa_hostkey, ++ torture_get_testkey(SSH_KEYTYPE_DSS, 0)); ++#endif /* HAVE_DSA */ ++ } ++ ++ additional_config = (s->srv_additional_config != NULL ? ++ s->srv_additional_config : ""); ++ ++ snprintf(sshd_config, sizeof(sshd_config), ++ config_string, ++ "HostKey", ed25519_hostkey, ++ "HostKey", rsa_hostkey, ++ "HostKey", ecdsa_hostkey, ++#ifdef HAVE_DSA ++ "HostKey", dsa_hostkey, ++#endif /* HAVE_DSA */ ++ additional_config); ++ ++ torture_write_file(s->srv_config, sshd_config); ++} ++ + static void torture_setup_create_sshd_config(void **state, bool pam) + { + struct torture_state *s = *state; +@@ -856,21 +967,140 @@ + return 1; + } + +-void torture_setup_sshd_server(void **state, bool pam) ++/** ++ * @brief Run a libssh based server under timeout. ++ * ++ * It is expected that the socket directory and libssh configuration file were ++ * already created before by calling torture_setup_socket_dir() and ++ * torture_setup_create_libssh_config() (or alternatively setup the state with ++ * the correct values). ++ * ++ * @param[in] state The content of the address pointed by this variable must be ++ * a pointer to an initialized instance of torture_state ++ * structure; it can be obtained by calling ++ * torture_setup_socket_dir() and ++ * torture_setup_create_libssh_config(). ++ * @param[in] server_path The path to the server executable. ++ * ++ * @note This function will use the state->srv_additional_config field as ++ * additional command line option used when starting the server instead of extra ++ * configuration file options. ++ * */ ++void torture_setup_libssh_server(void **state, const char *server_path) + { + struct torture_state *s; +- char sshd_start_cmd[1024]; ++ char start_cmd[1024]; ++ char timeout_cmd[512]; ++ char env[1024]; ++ char extra_options[1024]; + int rc; ++ char *ld_preload = NULL; ++ const char *force_fips = NULL; + +- torture_setup_socket_dir(state); +- torture_setup_create_sshd_config(state, pam); ++ struct ssh_tokens_st *env_tokens; ++ struct ssh_tokens_st *arg_tokens; ++ ++ pid_t pid; ++ ssize_t printed; ++ ++ s = *state; ++ ++ /* Get all the wrapper libraries to be pre-loaded */ ++ ld_preload = getenv("LD_PRELOAD"); ++ ++ if (s->srv_additional_config != NULL) { ++ printed = snprintf(extra_options, sizeof(extra_options), " %s ", ++ s->srv_additional_config); ++ if (printed < 0) { ++ fail_msg("Failed to print additional config!"); ++ } ++ } else { ++ printed = snprintf(extra_options, sizeof(extra_options), " "); ++ if (printed < 0) { ++ fail_msg("Failed to print empty additional config!"); ++ } ++ } ++ ++ if (ssh_fips_mode()) { ++ force_fips = "OPENSSL_FORCE_FIPS_MODE=1 "; ++ } else { ++ force_fips = ""; ++ } ++ ++ /* Write the environment setting */ ++ printed = snprintf(env, sizeof(env), ++ "SOCKET_WRAPPER_DIR=%s " ++ "SOCKET_WRAPPER_DEFAULT_IFACE=10 " ++ "LD_PRELOAD=%s " ++ "%s", ++ s->socket_dir, ld_preload, force_fips); ++ if (printed < 0) { ++ fail_msg("Failed to print env!"); ++ } ++ ++#ifdef WITH_TIMEOUT ++ snprintf(timeout_cmd, sizeof(timeout_cmd), ++ "%s %s ", TIMEOUT_EXECUTABLE, "5m"); ++#else ++ timeout_cmd[0] = '\0'; ++#endif ++ ++ /* Write the start command */ ++ printed = snprintf(start_cmd, sizeof(start_cmd), ++ "%s" ++ "%s -f%s -v4 -p22 -i%s -C%s%s%s", ++ timeout_cmd, ++ server_path, s->pcap_file, s->srv_pidfile, ++ s->srv_config, extra_options, TORTURE_SSH_SERVER); ++ if (printed < 0) { ++ fail_msg("Failed to print start command!"); ++ } ++ ++ pid = fork(); ++ switch(pid) { ++ case 0: ++ env_tokens = ssh_tokenize(env, ' '); ++ if (env_tokens == NULL || env_tokens->tokens == NULL) { ++ fail_msg("Failed to tokenize env!"); ++ } ++ ++ arg_tokens = ssh_tokenize(start_cmd, ' '); ++ if (arg_tokens == NULL || arg_tokens->tokens == NULL) { ++ ssh_tokens_free(env_tokens); ++ fail_msg("Failed to tokenize args!"); ++ } ++ ++ rc = execve(arg_tokens->tokens[0], (char **)arg_tokens->tokens, ++ (char **)env_tokens->tokens); ++ ++ /* execve returns only in case of error */ ++ ssh_tokens_free(env_tokens); ++ ssh_tokens_free(arg_tokens); ++ fail_msg("Error in execve: %s", strerror(errno)); ++ case -1: ++ fail_msg("Failed to fork!"); ++ default: ++ /* The parent continues the execution of the tests */ ++ setenv("SOCKET_WRAPPER_DEFAULT_IFACE", "21", 1); ++ unsetenv("PAM_WRAPPER"); ++ ++ /* Wait until the server is ready to accept connections */ ++ rc = torture_wait_for_daemon(15); ++ assert_int_equal(rc, 0); ++ break; ++ } ++} ++ ++static int torture_start_sshd_server(void **state) ++{ ++ struct torture_state *s = *state; ++ char sshd_start_cmd[1024]; ++ int rc; + + /* Set the default interface for the server */ + setenv("SOCKET_WRAPPER_DEFAULT_IFACE", "10", 1); + setenv("PAM_WRAPPER", "1", 1); + +- s = *state; +- + snprintf(sshd_start_cmd, sizeof(sshd_start_cmd), + SSHD_EXECUTABLE " -r -f %s -E %s/sshd/daemon.log 2> %s/sshd/cwrap.log", + s->srv_config, s->socket_dir, s->socket_dir); +@@ -882,7 +1112,20 @@ + unsetenv("PAM_WRAPPER"); + + /* Wait until the sshd is ready to accept connections */ +- rc = torture_wait_for_daemon(5); ++ rc = torture_wait_for_daemon(15); ++ assert_int_equal(rc, 0); ++ ++ return SSH_OK; ++} ++ ++void torture_setup_sshd_server(void **state, bool pam) ++{ ++ int rc; ++ ++ torture_setup_socket_dir(state); ++ torture_setup_create_sshd_config(state, pam); ++ ++ rc = torture_start_sshd_server(state); + assert_int_equal(rc, 0); + } + +@@ -922,29 +1165,12 @@ + torture_reload_sshd_server(void **state) + { + struct torture_state *s = *state; +- pid_t pid; + int rc; + +- /* read the pidfile */ +- pid = torture_read_pidfile(s->srv_pidfile); +- assert_int_not_equal(pid, -1); +- +- kill(pid, SIGHUP); +- +- /* 10 ms */ +- usleep(10 * 1000); +- +- rc = kill(pid, 0); +- if (rc != 0) { +- fprintf(stderr, +- "ERROR: SSHD process %u died during reload!\n", pid); +- return SSH_ERROR; +- } ++ rc = torture_terminate_process(s->srv_pidfile); ++ assert_return_code(rc, errno); + +- /* Wait until the sshd is ready to accept connections */ +- rc = torture_wait_for_daemon(5); +- assert_int_equal(rc, 0); +- return SSH_OK; ++ return torture_start_sshd_server(state); + } + + /* @brief: Updates SSHD server configuration with more options and +@@ -980,9 +1206,7 @@ + int rc; + + rc = torture_terminate_process(s->srv_pidfile); +- if (rc != 0) { +- fprintf(stderr, "XXXXXX Failed to terminate sshd\n"); +- } ++ assert_return_code(rc, errno); + + torture_teardown_socket_dir(state); + } +diff --color -ru ../libssh-0.9.6/tests/torture.h ./tests/torture.h +--- ../libssh-0.9.6/tests/torture.h 2021-08-26 14:27:44.000000000 +0200 ++++ ./tests/torture.h 2023-05-02 10:32:03.964511860 +0200 +@@ -132,6 +132,10 @@ + + void torture_reset_config(ssh_session session); + ++void torture_setup_create_libssh_config(void **state); ++ ++void torture_setup_libssh_server(void **state, const char *server_path); ++ + /* + * This function must be defined in every unit test file. + */ diff --git a/root/ppg/common/deps/libssh/rpm/libssh-0.9.6.tar.xz.asc b/root/ppg/common/deps/libssh/rpm/libssh-0.9.6.tar.xz.asc new file mode 100644 index 00000000..cbed27f4 --- /dev/null +++ b/root/ppg/common/deps/libssh/rpm/libssh-0.9.6.tar.xz.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEjf9T4Y8qvI2PPJIjfuD8TcwBTj0FAmEniOkACgkQfuD8TcwB +Tj0TKQ/9HiMAGSMHoQ+iPVLP06iTc6Cy7rNyON2nPDQwAz0V/dfvkrKAAEflfgYd +3pt3dbE/qgh2kgQLb9kpbCUmFoGuLgKz36RPOsggwuOsN+eD1n65q8W39sMOQid3 +bjUIOKRdYWC1suZ9fMAO1Ignl69Opd8dAq1Has9YzglaeQaV/lnYQOW4UG0xKHck +ZOp2qLfjmaQiBAI61eRyxqIYC0F67WKd0bo9D2csoocDVvHLq4syPdbMOfDTB+LL +KZSAZVW1R1JUVZMkp/P/HU11jNNy3wKoLafocnq8bXkPVrqhyuo+hDJV/OPUvFLa +VE/BzIRoMNG+1R+GJpwE7ut2DIHPxnZTThRkeVN5qP1+hbhgLJhW62I+HeAnD4s+ ++W7fwJovN28I+wqSjVEP8JguprVuoDAX5jVHbeZoMT7p8ATA4Nh3KCbYELEwTtFG +zsEIlBvoNXD3ce7xGXL3MPqfgKqrZQjRG/iOWvKwDV7WrqK1cFFyL7aeBfK2+dQq +1Ew7aYlTsH6Hap7XByeSsy4Z5ts3VXIoFix/h+Br5OTYKYgITM7bijNAQ6A2ZWQN +TxCv8X0sVyaGyXhxG6QhrEWZjFe496MneZkq9e6HKZyaSbzwFwMgOvrUUC7fa8e5 +o1Rvozah81U0nsikwTmDrm15RSK3mr2X34zPW2Ahzr1I5tGZzOk= +=cO0k +-----END PGP SIGNATURE----- diff --git a/root/ppg/common/deps/libssh/rpm/libssh.keyring b/root/ppg/common/deps/libssh/rpm/libssh.keyring new file mode 100644 index 00000000..411bf367 Binary files /dev/null and b/root/ppg/common/deps/libssh/rpm/libssh.keyring differ diff --git a/root/ppg/common/deps/libssh/rpm/libssh.spec b/root/ppg/common/deps/libssh/rpm/libssh.spec new file mode 100644 index 00000000..2583a133 --- /dev/null +++ b/root/ppg/common/deps/libssh/rpm/libssh.spec @@ -0,0 +1,552 @@ +# PERCONA REBUILD of the Rocky Linux 8 libssh source package, for +# ppg:common:deps (RockyLinux_8 repository only). +# +# Why: the EL8-built Percona PostgreSQL binary tarball (ssl1.1 variant) +# bundles libssh.so.4 (a libcurl dependency for scp/sftp). Red Hat +# builds libssh against Red Hat's OpenSSL 1.1.1 fork, so the library +# needs symbol version nodes (EVP_KDF_ctrl@OPENSSL_1_1_1b) that exist +# ONLY in RHEL-family libcrypto.so.1.1 — it fails to load on stock +# OpenSSL 1.1 hosts (proven on Debian 11). +# +# Delta vs. the distro spec (kept minimal, marked "PERCONA"): +# - -DWITH_GCRYPT=ON: libgcrypt crypto backend, no OpenSSL linkage. +# - BuildRequires libgcrypt-devel instead of openssl-devel. +# - Release carries a .percona suffix so this EVR wins over the +# distro package inside the OBS build chroots. +# Binary package names, sonames and the public ABI are unchanged. + +Name: libssh +Version: 0.9.6 +# PERCONA: ".percona.N" appended to the distro Release (16) so that this +# rebuild's EVR beats 0.9.6-16.el8_10 during dependency resolution while +# still yielding to a future distro 0.9.6-17 security rebase. +Release: 16.percona.1%{?dist} +Summary: A library implementing the SSH protocol +License: LGPLv2+ +URL: http://www.libssh.org + +Source0: https://www.libssh.org/files/0.9/%{name}-%{version}.tar.xz +Source1: https://www.libssh.org/files/0.9/%{name}-%{version}.tar.xz.asc +Source2: https://cryptomilk.org/gpgkey-8DFF53E18F2ABC8D8F3C92237EE0FC4DCC014E3D.gpg#/%{name}.keyring +Source3: libssh_client.config +Source4: libssh_server.config + +Patch0: loglevel.patch +Patch1: s390x_fix.patch +Patch2: null_dereference_rekey.patch +Patch3: auth_bypass.patch +Patch4: fix_tests.patch +Patch5: covscan23.patch +Patch6: CVE-2023-48795.patch +Patch7: CVE-2023-6004.patch +Patch8: CVE-2023-6918.patch +Patch9: CVE-2025-5318.patch +Patch10: CVE-2025-5372.patch + +BuildRequires: cmake +BuildRequires: doxygen +BuildRequires: gcc-c++ +BuildRequires: gnupg2 +# PERCONA: libgcrypt backend instead of OpenSSL (was: openssl-devel). +BuildRequires: libgcrypt-devel +BuildRequires: pkgconfig +BuildRequires: zlib-devel +BuildRequires: krb5-devel +BuildRequires: libcmocka-devel +BuildRequires: openssh-clients +BuildRequires: openssh-server +BuildRequires: pam_wrapper +BuildRequires: socket_wrapper +BuildRequires: nss_wrapper +BuildRequires: uid_wrapper +BuildRequires: nmap-ncat + +Requires: crypto-policies +Requires: %{name}-config = %{version}-%{release} + +%ifarch aarch64 ppc64 ppc64le s390x x86_64 +Provides: libssh_threads.so()(64bit) +Provides: libssh_threads.so.4()(64bit) +%else +Provides: libssh_threads.so +Provides: libssh_threads.so.4 +%endif + +%description +The ssh library was designed to be used by programmers needing a working SSH +implementation by the mean of a library. The complete control of the client is +made by the programmer. With libssh, you can remotely execute programs, transfer +files, use a secure and transparent tunnel for your remote programs. With its +Secure FTP implementation, you can play with remote files easily, without +third-party programs others than libcrypto (from openssl). + +%package devel +Summary: Development files for %{name} +Requires: %{name}%{?_isa} = %{version}-%{release} + +%description devel +The %{name}-devel package contains libraries and header files for developing +applications that use %{name}. + +%package config +Summary: Configuration files for %{name} +BuildArch: noarch +Obsoletes: %{name} < 0.9.0-1 + +%description config +The %{name}-config package provides the default configuration files for %{name}. + +%prep +gpgv2 --quiet --keyring %{SOURCE2} %{SOURCE1} %{SOURCE0} +%autosetup -p1 + +%build +if test ! -e "obj"; then + mkdir obj +fi +pushd obj + +%cmake .. \ + -DWITH_GCRYPT=ON \ + -DUNIT_TESTING=ON \ + -DCLIENT_TESTING=ON \ + -DSERVER_TESTING=ON \ + -DGLOBAL_CLIENT_CONFIG="%{_sysconfdir}/libssh/libssh_client.config" \ + -DGLOBAL_BIND_CONFIG="%{_sysconfdir}/libssh/libssh_server.config" + + +%make_build VERBOSE=1 +make docs + +popd + +%install +make DESTDIR=%{buildroot} install/fast -C obj +install -d -m755 %{buildroot}%{_sysconfdir}/libssh +install -m644 %{SOURCE3} %{buildroot}%{_sysconfdir}/libssh/libssh_client.config +install -m644 %{SOURCE4} %{buildroot}%{_sysconfdir}/libssh/libssh_server.config + +# +# Workaround for the removal of libssh_threads.so +# +# This will allow libraries which link against libssh_threads.so or packages +# requiring it to continue working. +# +pushd %{buildroot}%{_libdir} +for i in libssh.so.4*; +do + _target="${i}" + _link_name="${i%libssh*}libssh_threads${i##*libssh}" + if [ -L "${i}" ]; then + _target="$(readlink ${i})" + fi + ln -s "${_target}" "${_link_name}" +done; +popd + +%ldconfig_scriptlets + +%check +pushd obj +ctest --output-on-failure +popd + +%files +%doc AUTHORS BSD ChangeLog README +%license COPYING +%{_libdir}/libssh.so.4* +%{_libdir}/libssh_threads.so.4* + +%files devel +%doc obj/doc/html +%{_includedir}/libssh/ +# own this to avoid dep on cmake -- rex +%dir %{_libdir}/cmake/ +%{_libdir}/cmake/libssh/ +%{_libdir}/pkgconfig/libssh.pc +%{_libdir}/libssh.so + +%files config +%attr(0755,root,root) %dir %{_sysconfdir}/libssh +%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/libssh/libssh_client.config +%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/libssh/libssh_server.config + +%changelog +* Wed Jul 22 2026 Percona Development Team - 0.9.6-16.percona.1 +- Rebuild with the libgcrypt crypto backend (-DWITH_GCRYPT=ON) so that + libssh.so.4 has no OpenSSL linkage. Red Hat's build needs symbol + version nodes (EVP_KDF_ctrl@OPENSSL_1_1_1b) that only exist in the + RHEL OpenSSL 1.1.1 fork, which breaks the Percona PostgreSQL binary + tarball on stock OpenSSL 1.1 hosts. + +* Wed Nov 05 2025 Pavol Žáčik - 0.9.6-16 +- Fix CVE-2025-5372 + Resolves: RHEL-121232 + +* Tue Sep 30 2025 Pavol Žáčik - 0.9.6-15 +- Fix CVE-2025-5318 + Resolves: RHEL-111724 + +* Mon Feb 26 2024 Sahana Prasad - 0.9.6-14 +- Fix CVE-2023-48795 Prefix truncation attack on Binary Packet Protocol (BPP) +- Fix CVE-2023-6918 Missing checks for return values for digests +- Fix CVE-2023-6004 ProxyCommand/ProxyJump features allow injection + of malicious code through hostname +- Note: version is bumped from 12 to 14 directly, as the z-stream + version in 8.9 also has 13. So bumping it to 14, will prevent + upgrade conflicts. +- Resolves:RHEL-19690, RHEL-17244, RHEL-19312 + +* Mon May 15 2023 Norbert Pocs - 0.9.6-12 +- Fix loglevel regression +- Related: rhbz#2182251, rhbz#2189742 + +* Thu May 04 2023 Norbert Pocs - 0.9.6-11 +- .fmf/version is needed to run the tests +- Related: rhbz#2182251, rhbz#2189742 + +* Wed May 03 2023 Norbert Pocs - 0.9.6-10 +- Add missing ci.fmf file +- Related: rhbz#2182251, rhbz#2189742 + +* Wed May 03 2023 Norbert Pocs - 0.9.6-9 +- Fix covscan errors found at gating +- Related: rhbz#2182251, rhbz#2189742 + +* Tue May 02 2023 Norbert Pocs - 0.9.6-8 +- Backport test fixing commits to make the build pass +- Related: rhbz#2182251, rhbz#2189742 + +* Thu Apr 27 2023 Norbert Pocs - 0.9.6-7 +- Fix NULL dereference during rekeying with algorithm guessing + GHSL-2023-032 / CVE-2023-1667 +- Fix possible authentication bypass + GHSL 2023-085 / CVE-2023-2283 +- Resolves: rhbz#2182251, rhbz#2189742 + +* Fri Jan 06 2023 Norbert Pocs - 0.9.6-6 +- Enable client and server testing build time +- Fix failing rekey test on arch s390x +- Resolves: rhbz#2126342 + +* Mon Dec 05 2022 Stanislav Zidek - 0.9.6-5 +- Fix CI configuration for new TMT +- Resolves: rhbz#2149910 + +* Mon Nov 28 2022 Norbert Pocs - 0.9.6-4 +- Make VERBOSE and lower log levels less verbose +- Resolves: rhbz#2091512 + +* Fri Nov 05 2021 Norbert Pocs - 0.9.6-3 +- Remove STI tests + +* Thu Oct 21 2021 Norbert Pocs - 0.9.6-2 +- Remove bad patch causing errors +- Adding BuildRequires for openssh (SSHD support) + +* Thu Oct 14 2021 Norbert Pocs - 0.9.6-1 +- Fix CVE-2021-3634: Fix possible heap-buffer overflow when + rekeying with different key exchange mechanism +- Rebase to version 0.9.6 +- Rename SSHD_EXECUTABLE to SSH_EXECUTABLE in tests/torture.c +- Resolves: rhbz#1896651, rhbz#1994600 + +* Thu Oct 14 2021 Sahana Prasad - 0.9.4-4 +- Revert previous commit as it is incorrect. + +* Thu Oct 14 2021 Norbert Pocs - 0.9.6-1 +- Fix CVE-2021-3634: Fix possible heap-buffer overflow when + rekeying with different key exchange mechanism (#1978810) + +* Wed Apr 21 2021 Sahana Prasad - 0.9.4-3 +- Fix CVE-2020-16135 NULL pointer dereference in sftpserver.c if + ssh_buffer_new returns NULL (#1862646) + +* Wed Jun 24 2020 Anderson Sasaki - 0.9.4-2 +- Do not return error when server properly closed the channel (#1849071) +- Add a test for CVE-2019-14889 +- Do not parse configuration file in torture_knownhosts test + +* Tue May 26 2020 Anderson Sasaki - 0.9.4-1 +- Update to version 0.9.4 + https://www.libssh.org/2020/04/09/libssh-0-9-4-and-libssh-0-8-9-security-release/ +- Fixed CVE-2019-14889 (#1781782) +- Fixed CVE-2020-1730 (#1802422) +- Create missing directories in the path provided for known_hosts files (#1733914) +- Removed inclusion of OpenSSH server configuration file from + libssh_server.config (#1821339) + +* Mon Aug 05 2019 Anderson Sasaki - 0.9.0-4 +- Skip 1024 bits RSA key generation test in FIPS mode (#1734485) + +* Thu Jul 11 2019 Anderson Sasaki - 0.9.0-3 +- Add Obsoletes in libssh-config to avoid conflict with old libssh which + installed the configuration files. + +* Wed Jul 10 2019 Anderson Sasaki - 0.9.0-2 +- Eliminate circular dependency with libssh-config subpackage + +* Wed Jul 10 2019 Anderson Sasaki - 0.9.0-1 +- Update to version 0.9.0 + https://www.libssh.org/2019/06/28/libssh-0-9-0/ +- Added explicit Requires for crypto-policies +- Do not ignore known_hosts keys when SSH_OPTIONS_HOSTKEYS is set +- Provide the configuration files in a separate libssh-config subpackage + +* Mon Jun 17 2019 Anderson Sasaki - 0.8.91-0.1 +- Update to 0.9.0 pre release version (0.8.91) +- Added default configuration files for client and server +- Removed unused patch files left behind +- Fixed issues found to run upstream test suite with SELinux + +* Fri Dec 14 2018 Anderson Sasaki - 0.8.5-2 +- Fix more regressions introduced by the fixes for CVE-2018-10933 + +* Thu Nov 29 2018 Anderson Sasaki - 0.8.5-1 +- Update to version 0.8.5 + * Fixed an issue where global known_hosts file was ignored (#1649321) + * Fixed ssh_get_fd() to return writable file descriptor (#1649319) + * Fixed regression introduced in known_hosts parsing (#1649315) + * Fixed a regression which caused only the first algorithm in known_hosts to + be considered (#1638790) + +* Thu Nov 08 2018 Anderson Sasaki - 0.8.3-5 +- Fix regressions introduced by the fixes for CVE-2018-10933 + +* Wed Oct 17 2018 Nikos Mavrogiannopoulos - 0.8.3-4 +- Fix for authentication bypass issue in server implementation (#1639926) + +* Tue Oct 02 2018 Anderson Sasaki - 0.8.3-3 +- Fixed errors found by static code analysis (#1602594) + +* Fri Sep 21 2018 Anderson Sasaki - 0.8.3-1 +- Update to version 0.8.3 + * Added support for rsa-sha2 (#1610882) + * Added support to parse private keys in openssh container format (other than + ed25519) (#1622983) + * Added support for diffie-hellman-group18-sha512 and + diffie-hellman-group16-sha512 (#1610885) + * Added ssh_get_fingerprint_hash() + * Added ssh_pki_export_privkey_base64() + * Added support for Match keyword in config file + * Improved performance and reduced memory footprint for sftp + * Fixed ecdsa publickey auth + * Fixed reading a closed channel + * Added support to announce posix-rename@openssh.com and hardlink@openssh.com + in the sftp server + * Use -fstack-protector-strong if possible (#1624135) + +* Wed Aug 15 2018 Anderson Sasaki - 0.8.1-4 +- Fix the creation of symbolic links for libssh_threads.so.4 + +* Wed Aug 15 2018 Anderson Sasaki - 0.8.1-3 +- Add missing Provides for libssh_threads.so.4 + +* Tue Aug 14 2018 Anderson Sasaki - 0.8.1-2 +- Add Provides for libssh_threads.so to unbreak applications +- Fix ABIMap detection to not depend on python to build + +* Mon Aug 13 2018 Andreas Schneider - 0.8.1-1 +- Update to version 0.8.1 + https://www.libssh.org/2018/08/13/libssh-0-8-1/ + +* Fri Aug 10 2018 Andreas Schneider - 0.8.0-1 +- Update to version 0.8.0 + https://www.libssh.org/2018/08/10/libssh-0-8-0/ + +* Fri Jul 13 2018 Fedora Release Engineering - 0.7.5-9 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Wed Mar 07 2018 Rex Dieter - 0.7.5-8 +- BR: gcc-c++, use %%make_build + +* Wed Feb 07 2018 Fedora Release Engineering - 0.7.5-7 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild +- Related: bug#1614611 + +* Thu Feb 01 2018 Andreas Schneider - 0.7.5-6 +- resolves: #1540021 - Build against OpenSSL 1.1 + +* Wed Jan 31 2018 Igor Gnatenko - 0.7.5-5 +- Switch to %%ldconfig_scriptlets + +* Fri Dec 29 2017 Andreas Schneider - 0.7.5-4 +- Fix parsing ssh_config + +* Thu Aug 03 2017 Fedora Release Engineering - 0.7.5-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild + +* Wed Jul 26 2017 Fedora Release Engineering - 0.7.5-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Wed Apr 26 2017 Peter Robinson 0.7.5-1 +- Update to version 0.7.5 + +* Sat Mar 11 2017 Rex Dieter - 0.7.4-2 +- BR: compat-openssl10-devel (f26+, #1423088) +- use %%license +- -devel: drop hardcoded pkgconfig dep (let autodeps handle it) +- %%files: track library sonames, simplify -devel +- %%install: use 'install/fast' target +- .spec cosmetics, drop deprecated %%clean section + +* Wed Feb 08 2017 Andreas Schneider - 0.7.4-1 +- Update to version 0.7.4 + * Added id_ed25519 to the default identity list + * Fixed sftp EOF packet handling + * Fixed ssh_send_banner() to confirm with RFC 4253 + * Fixed some memory leaks +- resolves: #1419007 + +* Wed Feb 24 2016 Andreas Schneider - 0.7.3-1 +- resolves: #1311259 - Fix CVE-2016-0739 +- resolves: #1311332 - Update to version 0.7.3 + * Fixed CVE-2016-0739 + * Fixed ssh-agent on big endian + * Fixed some documentation issues +- Enabled GSSAPI support + +* Thu Feb 04 2016 Fedora Release Engineering - 0.7.2-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Thu Oct 22 2015 Andreas Schneider - 0.7.2-2 +- resolves: #1271230 - Fix ssh-agent support on big endian + +* Wed Sep 30 2015 Andreas Schneider - 0.7.2-1 +- Update to version 0.7.2 + * Fixed OpenSSL detection on Windows + * Fixed return status for ssh_userauth_agent() + * Fixed KEX to prefer hmac-sha2-256 + * Fixed sftp packet handling + * Fixed return values of ssh_key_is_(public|private) + * Fixed bug in global success reply +- resolves: #1267346 + +* Tue Jun 30 2015 Andreas Schneider - 0.7.1-1 +- Update to version 0.7.1 + * Fixed SSH_AUTH_PARTIAL auth with auto public key + * Fixed memory leak in session options + * Fixed allocation of ed25519 public keys + * Fixed channel exit-status and exit-signal + * Reintroduce ssh_forward_listen() + +* Wed Jun 17 2015 Fedora Release Engineering - 0.7.0-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Thu May 21 2015 Orion Poplawski - 0.7.0-2 +- Add patch to fix undefined symbol: ssh_forward_listen (bug #1221310) + +* Mon May 11 2015 Andreas Schneider - 0.7.0-1 +- Update to version 0.7.0 + * Added support for ed25519 keys + * Added SHA2 algorithms for HMAC + * Added improved and more secure buffer handling code + * Added callback for auth_none_function + * Added support for ECDSA private key signing + * Added more tests + * Fixed a lot of bugs + * Improved API documentation + +* Thu Apr 30 2015 Andreas Schneider - 0.6.5-1 +- resolves: #1213775 - Security fix for CVE-2015-3146 +- resolves: #1218076 - Security fix for CVE-2015-3146 + +* Fri Dec 19 2014 - Andreas Schneider - 0.6.4-1 +- Security fix for CVE-2014-8132. + +* Sun Aug 17 2014 Fedora Release Engineering - 0.6.3-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild + +* Sat Jun 07 2014 Fedora Release Engineering - 0.6.3-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Tue Mar 04 2014 - Andreas Schneider - 0.6.3-1 +- Fix CVE-2014-0017. + +* Mon Feb 10 2014 - Andreas Schneider - 0.6.1-1 +- Update to version 0.6.1. +- resolves: #1056757 - Fix scp mode. +- resolves: #1053305 - Fix known_hosts heuristic. + +* Wed Jan 08 2014 - Andreas Schneider - 0.6.0-1 +- Update to 0.6.0 + +* Fri Jul 26 2013 - Andreas Schneider - 0.5.5-1 +- Update to 0.5.5. +- Clenup the spec file. + +* Thu Jul 18 2013 Simone Caronni - 0.5.4-5 +- Add EPEL 5 support. +- Add Debian patches to enable Doxygen documentation. + +* Tue Jul 16 2013 Simone Caronni - 0.5.4-4 +- Add patch for #982685. + +* Mon Jun 10 2013 Simone Caronni - 0.5.4-3 +- Clean up SPEC file and fix rpmlint complaints. + +* Thu Feb 14 2013 Fedora Release Engineering - 0.5.4-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Wed Jan 23 2013 Petr Lautrbach 0.5.4-1 +- update to security 0.5.4 release +- CVE-2013-0176 (#894407) + +* Tue Nov 20 2012 Petr Lautrbach 0.5.3-1 +- update to security 0.5.3 release (#878465) + +* Thu Jul 19 2012 Fedora Release Engineering - 0.5.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Thu Feb 02 2012 Petr Lautrbach 0.5.2-1 +- update to 0.5.2 version (#730270) + +* Fri Jan 13 2012 Fedora Release Engineering - 0.5.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Wed Jun 1 2011 Jan F. Chadima - 0.5.0-1 +- bounce versionn to 0.5.0 (#709785) +- the support for protocol v1 is disabled + +* Tue Feb 08 2011 Fedora Release Engineering - 0.4.8-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Wed Jan 19 2011 Jan F. Chadima - 0.4.8-1 +- bounce versionn to 0.4.8 (#670456) + +* Mon Sep 6 2010 Jan F. Chadima - 0.4.6-1 +- bounce versionn to 0.4.6 (#630602) + +* Thu Jun 3 2010 Jan F. Chadima - 0.4.4-1 +- bounce versionn to 0.4.4 (#598592) + +* Wed May 19 2010 Jan F. Chadima - 0.4.3-1 +- bounce versionn to 0.4.3 (#593288) + +* Tue Mar 16 2010 Jan F. Chadima - 0.4.2-1 +- bounce versionn to 0.4.2 (#573972) + +* Tue Feb 16 2010 Jan F. Chadima - 0.4.1-1 +- bounce versionn to 0.4.1 (#565870) + +* Fri Dec 11 2009 Jan F. Chadima - 0.4.0-1 +- bounce versionn to 0.4.0 (#541010) + +* Thu Nov 26 2009 Jan F. Chadima - 0.3.92-2 +- typo in spec file + +* Thu Nov 26 2009 Jan F. Chadima - 0.3.92-1 +- bounce versionn to 0.3.92 (0.4 beta2) (#541010) + +* Fri Aug 21 2009 Tomas Mraz - 0.2-4 +- rebuilt with new openssl + +* Sat Jul 25 2009 Fedora Release Engineering - 0.2-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild + +* Tue Jun 02 2009 Jan F. Chadima - 0.2-2 +- Small changes during review + +* Mon Jun 01 2009 Jan F. Chadima - 0.2-1 +- Initial build + diff --git a/root/ppg/common/deps/libssh/rpm/libssh_client.config b/root/ppg/common/deps/libssh/rpm/libssh_client.config new file mode 100644 index 00000000..1d293bdf --- /dev/null +++ b/root/ppg/common/deps/libssh/rpm/libssh_client.config @@ -0,0 +1,4 @@ +# Parse system-wide crypto configuration file +Include /etc/crypto-policies/back-ends/libssh.config +# Parse OpenSSH configuration file for consistency +Include /etc/ssh/ssh_config diff --git a/root/ppg/common/deps/libssh/rpm/libssh_server.config b/root/ppg/common/deps/libssh/rpm/libssh_server.config new file mode 100644 index 00000000..d3ef5c2d --- /dev/null +++ b/root/ppg/common/deps/libssh/rpm/libssh_server.config @@ -0,0 +1,2 @@ +# Parse system-wide crypto configuration file +Include /etc/crypto-policies/back-ends/libssh.config diff --git a/root/ppg/common/deps/libssh/rpm/loglevel.patch b/root/ppg/common/deps/libssh/rpm/loglevel.patch new file mode 100644 index 00000000..fb2c5b55 --- /dev/null +++ b/root/ppg/common/deps/libssh/rpm/loglevel.patch @@ -0,0 +1,3424 @@ +diff --git a/include/libssh/libssh.h b/include/libssh/libssh.h +index 1664dfce..8ce364a3 100644 +--- a/include/libssh/libssh.h ++++ b/include/libssh/libssh.h +@@ -322,7 +322,7 @@ enum { + /** No logging at all + */ + SSH_LOG_NOLOG=0, +- /** Only warnings ++ /** Only fatal warnings + */ + SSH_LOG_WARNING, + /** High level protocol information +@@ -347,7 +347,7 @@ enum { + + /** No logging at all */ + #define SSH_LOG_NONE 0 +-/** Show only warnings */ ++/** Show only fatal warnings */ + #define SSH_LOG_WARN 1 + /** Get some information what's going on */ + #define SSH_LOG_INFO 2 +diff --git a/src/agent.c b/src/agent.c +index 62b0093e..02f628cd 100644 +--- a/src/agent.c ++++ b/src/agent.c +@@ -261,12 +261,12 @@ static int agent_talk(struct ssh_session_struct *session, + if (atomicio(session->agent, payload, 4, 0) == 4) { + if (atomicio(session->agent, ssh_buffer_get(request), len, 0) + != len) { +- SSH_LOG(SSH_LOG_WARN, "atomicio sending request failed: %s", ++ SSH_LOG(SSH_LOG_TRACE, "atomicio sending request failed: %s", + strerror(errno)); + return -1; + } + } else { +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_TRACE, + "atomicio sending request length failed: %s", + strerror(errno)); + return -1; +@@ -274,7 +274,7 @@ static int agent_talk(struct ssh_session_struct *session, + + /* wait for response, read the length of the response packet */ + if (atomicio(session->agent, payload, 4, 1) != 4) { +- SSH_LOG(SSH_LOG_WARN, "atomicio read response length failed: %s", ++ SSH_LOG(SSH_LOG_TRACE, "atomicio read response length failed: %s", + strerror(errno)); + return -1; + } +@@ -293,12 +293,12 @@ static int agent_talk(struct ssh_session_struct *session, + n = sizeof(payload); + } + if (atomicio(session->agent, payload, n, 1) != n) { +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_DEBUG, + "Error reading response from authentication socket."); + return -1; + } + if (ssh_buffer_add_data(reply, payload, n) < 0) { +- SSH_LOG(SSH_LOG_WARN, "Not enough space"); ++ SSH_LOG(SSH_LOG_DEBUG, "Not enough space"); + return -1; + } + len -= n; +@@ -353,7 +353,7 @@ uint32_t ssh_agent_get_ident_count(struct ssh_session_struct *session) + type = bswap_32(type); + #endif + +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_TRACE, + "Answer type: %d, expected answer: %d", + type, SSH2_AGENT_IDENTITIES_ANSWER); + +@@ -573,7 +573,7 @@ ssh_string ssh_agent_sign_data(ssh_session session, + #endif + + if (agent_failed(type)) { +- SSH_LOG(SSH_LOG_WARN, "Agent reports failure in signing the key"); ++ SSH_LOG(SSH_LOG_DEBUG, "Agent reports failure in signing the key"); + SSH_BUFFER_FREE(reply); + return NULL; + } else if (type != SSH2_AGENT_SIGN_RESPONSE) { +diff --git a/src/auth.c b/src/auth.c +index 3a5f0efb..59d7e8dd 100644 +--- a/src/auth.c ++++ b/src/auth.c +@@ -71,7 +71,7 @@ static int ssh_userauth_request_service(ssh_session session) { + + rc = ssh_service_request(session, "ssh-userauth"); + if ((rc != SSH_OK) && (rc != SSH_AGAIN)) { +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_TRACE, + "Failed to request \"ssh-userauth\" service"); + } + +@@ -199,7 +199,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_banner) { + + banner = ssh_buffer_get_ssh_string(packet); + if (banner == NULL) { +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_TRACE, + "Invalid SSH_USERAUTH_BANNER packet"); + } else { + SSH_LOG(SSH_LOG_DEBUG, +@@ -237,7 +237,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_failure) { + + if (partial) { + session->auth.state = SSH_AUTH_STATE_PARTIAL; +- SSH_LOG(SSH_LOG_INFO, ++ SSH_LOG(SSH_LOG_DEBUG, + "Partial success for '%s'. Authentication that can continue: %s", + current_method, + auth_methods); +@@ -247,7 +247,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_failure) { + "Access denied for '%s'. Authentication that can continue: %s", + current_method, + auth_methods); +- SSH_LOG(SSH_LOG_INFO, ++ SSH_LOG(SSH_LOG_DEBUG, + "%s", + ssh_get_error(session)); + +@@ -942,7 +942,7 @@ int ssh_userauth_agent(ssh_session session, + session->agent_state = NULL; + return rc; + } else if (rc != SSH_AUTH_SUCCESS) { +- SSH_LOG(SSH_LOG_INFO, ++ SSH_LOG(SSH_LOG_DEBUG, + "Server accepted public key but refused the signature"); + ssh_key_free(state->pubkey); + state->pubkey = ssh_agent_get_next_ident(session, &state->comment); +@@ -1102,7 +1102,7 @@ int ssh_userauth_publickey_auto(ssh_session session, + + rc = ssh_pki_export_pubkey_file(state->pubkey, pubkey_file); + if (rc == SSH_ERROR) { +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_TRACE, + "Could not write public key to file: %s", + pubkey_file); + } +@@ -1112,7 +1112,7 @@ int ssh_userauth_publickey_auto(ssh_session session, + if (state->state == SSH_AUTH_AUTO_STATE_KEY_IMPORTED) { + rc = ssh_userauth_try_publickey(session, username, state->pubkey); + if (rc == SSH_AUTH_ERROR) { +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_TRACE, + "Public key authentication error for %s", + privkey_file); + ssh_key_free(state->privkey); +@@ -1159,7 +1159,7 @@ int ssh_userauth_publickey_auto(ssh_session session, + /* If the file doesn't exist, continue */ + ssh_key_free(state->pubkey); + state->pubkey = NULL; +- SSH_LOG(SSH_LOG_INFO, ++ SSH_LOG(SSH_LOG_DEBUG, + "Private key %s doesn't exist.", + privkey_file); + state->it = state->it->next; +@@ -1174,7 +1174,7 @@ int ssh_userauth_publickey_auto(ssh_session session, + ssh_key_free(state->pubkey); + SAFE_FREE(session->auth.auto_state); + if (rc == SSH_AUTH_SUCCESS) { +- SSH_LOG(SSH_LOG_INFO, ++ SSH_LOG(SSH_LOG_DEBUG, + "Successfully authenticated using %s", + privkey_file); + } +@@ -1187,15 +1187,15 @@ int ssh_userauth_publickey_auto(ssh_session session, + ssh_key_free(state->privkey); + ssh_key_free(state->pubkey); + +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_DEBUG, + "The server accepted the public key but refused the signature"); + state->it = state->it->next; + state->state = SSH_AUTH_AUTO_STATE_PUBKEY; + /* continue */ + } + } +- SSH_LOG(SSH_LOG_INFO, +- "Tried every public key, none matched"); ++ SSH_LOG(SSH_LOG_WARN, ++ "Access denied: Tried every public key, none matched"); + SAFE_FREE(session->auth.auto_state); + return SSH_AUTH_DENIED; + } +@@ -1917,7 +1917,7 @@ int ssh_userauth_gssapi(ssh_session session) { + } else if (rc == SSH_ERROR) { + return SSH_AUTH_ERROR; + } +- SSH_LOG(SSH_LOG_PROTOCOL, "Authenticating with gssapi-with-mic"); ++ SSH_LOG(SSH_LOG_DEBUG, "Authenticating with gssapi-with-mic"); + + session->auth.current_method = SSH_AUTH_METHOD_GSSAPI_MIC; + session->auth.state = SSH_AUTH_STATE_NONE; +diff --git a/src/bind.c b/src/bind.c +index fa8df9ea..d65a789e 100644 +--- a/src/bind.c ++++ b/src/bind.c +@@ -294,7 +294,7 @@ int ssh_bind_listen(ssh_bind sshbind) { + + sshbind->bindfd = fd; + } else { +- SSH_LOG(SSH_LOG_INFO, "Using app-provided bind socket"); ++ SSH_LOG(SSH_LOG_DEBUG, "Using app-provided bind socket"); + } + return 0; + } +diff --git a/src/bind_config.c b/src/bind_config.c +index 14b84db0..56b66660 100644 +--- a/src/bind_config.c ++++ b/src/bind_config.c +@@ -343,7 +343,7 @@ ssh_bind_config_parse_line(ssh_bind bind, + if (p && (*parser_flags & PARSING)) { + rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_HOSTKEY, p); + if (rc != 0) { +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_TRACE, + "line %d: Failed to set Hostkey value '%s'", + count, p); + } +@@ -354,7 +354,7 @@ ssh_bind_config_parse_line(ssh_bind bind, + if (p && (*parser_flags & PARSING)) { + rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_BINDADDR, p); + if (rc != 0) { +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_TRACE, + "line %d: Failed to set ListenAddress value '%s'", + count, p); + } +@@ -365,7 +365,7 @@ ssh_bind_config_parse_line(ssh_bind bind, + if (p && (*parser_flags & PARSING)) { + rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_BINDPORT_STR, p); + if (rc != 0) { +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_TRACE, + "line %d: Failed to set Port value '%s'", + count, p); + } +@@ -376,7 +376,7 @@ ssh_bind_config_parse_line(ssh_bind bind, + if (p && (*parser_flags & PARSING)) { + rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_CIPHERS_C_S, p); + if (rc != 0) { +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_TRACE, + "line %d: Failed to set C->S Ciphers value '%s'", + count, p); + break; +@@ -384,7 +384,7 @@ ssh_bind_config_parse_line(ssh_bind bind, + + rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_CIPHERS_S_C, p); + if (rc != 0) { +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_TRACE, + "line %d: Failed to set S->C Ciphers value '%s'", + count, p); + } +@@ -395,7 +395,7 @@ ssh_bind_config_parse_line(ssh_bind bind, + if (p && (*parser_flags & PARSING)) { + rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_HMAC_C_S, p); + if (rc != 0) { +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_TRACE, + "line %d: Failed to set C->S MAC value '%s'", + count, p); + break; +@@ -403,7 +403,7 @@ ssh_bind_config_parse_line(ssh_bind bind, + + rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_HMAC_S_C, p); + if (rc != 0) { +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_TRACE, + "line %d: Failed to set S->C MAC value '%s'", + count, p); + } +@@ -417,10 +417,10 @@ ssh_bind_config_parse_line(ssh_bind bind, + if (strcasecmp(p, "quiet") == 0) { + value = SSH_LOG_NONE; + } else if (strcasecmp(p, "fatal") == 0 || +- strcasecmp(p, "error")== 0 || +- strcasecmp(p, "info") == 0) { ++ strcasecmp(p, "error")== 0) { + value = SSH_LOG_WARN; +- } else if (strcasecmp(p, "verbose") == 0) { ++ } else if (strcasecmp(p, "verbose") == 0 || ++ strcasecmp(p, "info") == 0) { + value = SSH_LOG_INFO; + } else if (strcasecmp(p, "DEBUG") == 0 || + strcasecmp(p, "DEBUG1") == 0) { +@@ -433,7 +433,7 @@ ssh_bind_config_parse_line(ssh_bind bind, + rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_LOG_VERBOSITY, + &value); + if (rc != 0) { +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_TRACE, + "line %d: Failed to set LogLevel value '%s'", + count, p); + } +@@ -445,7 +445,7 @@ ssh_bind_config_parse_line(ssh_bind bind, + if (p && (*parser_flags & PARSING)) { + rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_KEY_EXCHANGE, p); + if (rc != 0) { +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_TRACE, + "line %d: Failed to set KexAlgorithms value '%s'", + count, p); + } +@@ -520,13 +520,13 @@ ssh_bind_config_parse_line(ssh_bind bind, + /* Skip one argument */ + p = ssh_config_get_str_tok(&s, NULL); + if (p == NULL || p[0] == '\0') { +- SSH_LOG(SSH_LOG_WARN, "line %d: Match keyword " ++ SSH_LOG(SSH_LOG_TRACE, "line %d: Match keyword " + "'%s' requires argument\n", count, p2); + SAFE_FREE(x); + return -1; + } + args++; +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_DEBUG, + "line %d: Unsupported Match keyword '%s', ignoring\n", + count, + p2); +@@ -556,7 +556,7 @@ ssh_bind_config_parse_line(ssh_bind bind, + rc = ssh_bind_options_set(bind, + SSH_BIND_OPTIONS_PUBKEY_ACCEPTED_KEY_TYPES, p); + if (rc != 0) { +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_TRACE, + "line %d: Failed to set PubKeyAcceptedKeyTypes value '%s'", + count, p); + } +@@ -568,26 +568,26 @@ ssh_bind_config_parse_line(ssh_bind bind, + rc = ssh_bind_options_set(bind, + SSH_BIND_OPTIONS_HOSTKEY_ALGORITHMS, p); + if (rc != 0) { +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_TRACE, + "line %d: Failed to set HostkeyAlgorithms value '%s'", + count, p); + } + } + break; + case BIND_CFG_NOT_ALLOWED_IN_MATCH: +- SSH_LOG(SSH_LOG_WARN, "Option not allowed in Match block: %s, line: %d", ++ SSH_LOG(SSH_LOG_DEBUG, "Option not allowed in Match block: %s, line: %d", + keyword, count); + break; + case BIND_CFG_UNKNOWN: +- SSH_LOG(SSH_LOG_WARN, "Unknown option: %s, line: %d", ++ SSH_LOG(SSH_LOG_TRACE, "Unknown option: %s, line: %d", + keyword, count); + break; + case BIND_CFG_UNSUPPORTED: +- SSH_LOG(SSH_LOG_WARN, "Unsupported option: %s, line: %d", ++ SSH_LOG(SSH_LOG_TRACE, "Unsupported option: %s, line: %d", + keyword, count); + break; + case BIND_CFG_NA: +- SSH_LOG(SSH_LOG_WARN, "Option not applicable: %s, line: %d", ++ SSH_LOG(SSH_LOG_TRACE, "Option not applicable: %s, line: %d", + keyword, count); + break; + default: +diff --git a/src/buffer.c b/src/buffer.c +index ce12f491..685fd455 100644 +--- a/src/buffer.c ++++ b/src/buffer.c +@@ -878,7 +878,7 @@ static int ssh_buffer_pack_allocate_va(struct ssh_buffer_struct *buffer, + cstring = NULL; + break; + default: +- SSH_LOG(SSH_LOG_WARN, "Invalid buffer format %c", *p); ++ SSH_LOG(SSH_LOG_TRACE, "Invalid buffer format %c", *p); + rc = SSH_ERROR; + } + if (rc != SSH_OK){ +@@ -1007,7 +1007,7 @@ int ssh_buffer_pack_va(struct ssh_buffer_struct *buffer, + cstring = NULL; + break; + default: +- SSH_LOG(SSH_LOG_WARN, "Invalid buffer format %c", *p); ++ SSH_LOG(SSH_LOG_TRACE, "Invalid buffer format %c", *p); + rc = SSH_ERROR; + } + if (rc != SSH_OK){ +@@ -1238,7 +1238,7 @@ int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer, + rc = SSH_OK; + break; + default: +- SSH_LOG(SSH_LOG_WARN, "Invalid buffer format %c", *p); ++ SSH_LOG(SSH_LOG_TRACE, "Invalid buffer format %c", *p); + } + if (rc != SSH_OK) { + break; +diff --git a/src/channels.c b/src/channels.c +index 1041dbff..36e19598 100644 +--- a/src/channels.c ++++ b/src/channels.c +@@ -187,7 +187,7 @@ SSH_PACKET_CALLBACK(ssh_packet_channel_open_conf){ + if (rc != SSH_OK) + goto error; + +- SSH_LOG(SSH_LOG_PROTOCOL, ++ SSH_LOG(SSH_LOG_DEBUG, + "Received a CHANNEL_OPEN_CONFIRMATION for channel %d:%d", + channel->local_channel, + channel->remote_channel); +@@ -200,7 +200,7 @@ SSH_PACKET_CALLBACK(ssh_packet_channel_open_conf){ + goto error; + } + +- SSH_LOG(SSH_LOG_PROTOCOL, ++ SSH_LOG(SSH_LOG_DEBUG, + "Remote window : %"PRIu32", maxpacket : %"PRIu32, + (uint32_t) channel->remote_window, + (uint32_t) channel->remote_maxpacket); +@@ -264,11 +264,14 @@ error: + + static int ssh_channel_open_termination(void *c){ + ssh_channel channel = (ssh_channel) c; +- if (channel->state != SSH_CHANNEL_STATE_OPENING || +- channel->session->session_state == SSH_SESSION_STATE_ERROR) ++ if (channel->state != SSH_CHANNEL_STATE_OPENING) { + return 1; +- else ++ } else if (channel->session->session_state == SSH_SESSION_STATE_ERROR) { ++ SSH_LOG(SSH_LOG_WARN, "Error: %s", ssh_get_error(channel->session)); ++ return 1; ++ } else { + return 0; ++ } + } + + /** +@@ -320,7 +323,7 @@ channel_open(ssh_channel channel, + channel->local_maxpacket = maxpacket; + channel->local_window = window; + +- SSH_LOG(SSH_LOG_PROTOCOL, ++ SSH_LOG(SSH_LOG_DEBUG, + "Creating a channel %d with %d window and %d max packet", + channel->local_channel, window, maxpacket); + +@@ -410,7 +413,7 @@ static int grow_window(ssh_session session, + int rc; + + if(new_window <= channel->local_window){ +- SSH_LOG(SSH_LOG_PROTOCOL, ++ SSH_LOG(SSH_LOG_DEBUG, + "growing window (channel %d:%d) to %d bytes : not needed (%d bytes)", + channel->local_channel, channel->remote_channel, new_window, + channel->local_window); +@@ -434,7 +437,7 @@ static int grow_window(ssh_session session, + goto error; + } + +- SSH_LOG(SSH_LOG_PROTOCOL, ++ SSH_LOG(SSH_LOG_DEBUG, + "growing window (channel %d:%d) to %d bytes", + channel->local_channel, + channel->remote_channel, +@@ -504,7 +507,7 @@ SSH_PACKET_CALLBACK(channel_rcv_change_window) { + return SSH_PACKET_USED; + } + +- SSH_LOG(SSH_LOG_PROTOCOL, ++ SSH_LOG(SSH_LOG_DEBUG, + "Adding %d bytes to channel (%d:%d) (from %d bytes)", + bytes, + channel->local_channel, +@@ -808,7 +811,7 @@ SSH_PACKET_CALLBACK(channel_rcv_request) { + } + if(strcmp(request,"keepalive@openssh.com")==0){ + SAFE_FREE(request); +- SSH_LOG(SSH_LOG_PROTOCOL,"Responding to Openssh's keepalive"); ++ SSH_LOG(SSH_LOG_DEBUG,"Responding to Openssh's keepalive"); + + rc = ssh_buffer_pack(session->out_buffer, + "bd", +@@ -824,7 +827,7 @@ SSH_PACKET_CALLBACK(channel_rcv_request) { + + if (strcmp(request, "auth-agent-req@openssh.com") == 0) { + SAFE_FREE(request); +- SSH_LOG(SSH_LOG_PROTOCOL, "Received an auth-agent-req request"); ++ SSH_LOG(SSH_LOG_DEBUG, "Received an auth-agent-req request"); + ssh_callbacks_execute_list(channel->callbacks, + ssh_channel_callbacks, + channel_auth_agent_req_function, +@@ -840,7 +843,7 @@ SSH_PACKET_CALLBACK(channel_rcv_request) { + */ + ssh_message_handle_channel_request(session,channel,packet,request,status); + #else +- SSH_LOG(SSH_LOG_WARNING, "Unhandled channel request %s", request); ++ SSH_LOG(SSH_LOG_DEBUG, "Unhandled channel request %s", request); + #endif + + SAFE_FREE(request); +@@ -1403,7 +1406,7 @@ static int channel_write_common(ssh_channel channel, + } + + if (len > INT_MAX) { +- SSH_LOG(SSH_LOG_PROTOCOL, ++ SSH_LOG(SSH_LOG_TRACE, + "Length (%u) is bigger than INT_MAX", len); + return SSH_ERROR; + } +@@ -1440,14 +1443,14 @@ static int channel_write_common(ssh_channel channel, + } + while (len > 0) { + if (channel->remote_window < len) { +- SSH_LOG(SSH_LOG_PROTOCOL, ++ SSH_LOG(SSH_LOG_DEBUG, + "Remote window is %d bytes. going to write %d bytes", + channel->remote_window, + len); + /* What happens when the channel window is zero? */ + if(channel->remote_window == 0) { + /* nothing can be written */ +- SSH_LOG(SSH_LOG_PROTOCOL, ++ SSH_LOG(SSH_LOG_DEBUG, + "Wait for a growing window message..."); + rc = ssh_handle_packets_termination(session, SSH_TIMEOUT_DEFAULT, + ssh_channel_waitwindow_termination,channel); +@@ -1698,11 +1701,14 @@ SSH_PACKET_CALLBACK(ssh_packet_channel_failure){ + + static int ssh_channel_request_termination(void *c){ + ssh_channel channel = (ssh_channel)c; +- if(channel->request_state != SSH_CHANNEL_REQ_STATE_PENDING || +- channel->session->session_state == SSH_SESSION_STATE_ERROR) ++ if(channel->request_state != SSH_CHANNEL_REQ_STATE_PENDING) { + return 1; +- else ++ } else if (channel->session->session_state == SSH_SESSION_STATE_ERROR) { ++ SSH_LOG(SSH_LOG_WARN, "Error: %s", ssh_get_error(channel->session)); ++ return 1; ++ } else { + return 0; ++ } + } + + static int channel_request(ssh_channel channel, const char *request, +@@ -1767,7 +1773,7 @@ pending: + rc=SSH_ERROR; + break; + case SSH_CHANNEL_REQ_STATE_ACCEPTED: +- SSH_LOG(SSH_LOG_PROTOCOL, ++ SSH_LOG(SSH_LOG_DEBUG, + "Channel request %s success",request); + rc=SSH_OK; + break; +@@ -2237,11 +2243,14 @@ SSH_PACKET_CALLBACK(ssh_request_denied){ + + static int ssh_global_request_termination(void *s){ + ssh_session session = (ssh_session) s; +- if (session->global_req_state != SSH_CHANNEL_REQ_STATE_PENDING || +- session->session_state == SSH_SESSION_STATE_ERROR) ++ if (session->global_req_state != SSH_CHANNEL_REQ_STATE_PENDING) { + return 1; +- else ++ } else if (session->session_state == SSH_SESSION_STATE_ERROR) { ++ SSH_LOG(SSH_LOG_WARN, "Error: %s", ssh_get_error(session)); ++ return 1; ++ } else { + return 0; ++ } + } + + /** +@@ -2324,7 +2333,7 @@ pending: + } + switch(session->global_req_state){ + case SSH_CHANNEL_REQ_STATE_ACCEPTED: +- SSH_LOG(SSH_LOG_PROTOCOL, "Global request %s success",request); ++ SSH_LOG(SSH_LOG_DEBUG, "Global request %s success",request); + rc=SSH_OK; + break; + case SSH_CHANNEL_REQ_STATE_DENIED: +@@ -2808,11 +2817,14 @@ struct ssh_channel_read_termination_struct { + static int ssh_channel_read_termination(void *s){ + struct ssh_channel_read_termination_struct *ctx = s; + if (ssh_buffer_get_len(ctx->buffer) >= ctx->count || +- ctx->channel->remote_eof || +- ctx->channel->session->session_state == SSH_SESSION_STATE_ERROR) ++ ctx->channel->remote_eof) { + return 1; +- else ++ } else if (ctx->channel->session->session_state == SSH_SESSION_STATE_ERROR) { ++ SSH_LOG(SSH_LOG_WARN, "Error: %s", ssh_get_error(ctx->channel->session)); ++ return 1; ++ } else { + return 0; ++ } + } + + /* TODO FIXME Fix the delayed close thing */ +@@ -3172,10 +3184,12 @@ static int ssh_channel_exit_status_termination(void *c){ + /* When a channel is closed, no exit status message can + * come anymore */ + (channel->flags & SSH_CHANNEL_FLAG_CLOSED_REMOTE) || +- channel->session->session_state == SSH_SESSION_STATE_ERROR) ++ channel->session->session_state == SSH_SESSION_STATE_ERROR) { ++ SSH_LOG(SSH_LOG_WARN, "Error: %s", ssh_get_error(channel->session)); + return 1; +- else ++ } else { + return 0; ++ } + } + + /** +diff --git a/src/client.c b/src/client.c +index a4a7317e..82a436fc 100644 +--- a/src/client.c ++++ b/src/client.c +@@ -72,7 +72,7 @@ static void socket_callback_connected(int code, int errno_code, void *user){ + return; + } + +- SSH_LOG(SSH_LOG_RARE,"Socket connection callback: %d (%d)",code, errno_code); ++ SSH_LOG(SSH_LOG_TRACE,"Socket connection callback: %d (%d)",code, errno_code); + if(code == SSH_SOCKET_CONNECTED_OK) + session->session_state=SSH_SESSION_STATE_SOCKET_CONNECTED; + else { +@@ -400,7 +400,7 @@ static void ssh_client_connection_callback(ssh_session session) + goto error; + } + set_status(session, 0.4f); +- SSH_LOG(SSH_LOG_PROTOCOL, ++ SSH_LOG(SSH_LOG_DEBUG, + "SSH server banner: %s", session->serverbanner); + + /* Here we analyze the different protocols the server allows. */ +@@ -475,7 +475,7 @@ error: + ssh_socket_close(session->socket); + session->alive = 0; + session->session_state=SSH_SESSION_STATE_ERROR; +- ++ SSH_LOG(SSH_LOG_WARN, "%s", ssh_get_error(session)); + } + + /** @internal +@@ -558,7 +558,7 @@ int ssh_connect(ssh_session session) + return SSH_ERROR; + } + +- SSH_LOG(SSH_LOG_PROTOCOL, ++ SSH_LOG(SSH_LOG_DEBUG, + "libssh %s, using threading %s", + ssh_copyright(), + ssh_threads_get_type()); +@@ -593,7 +593,7 @@ int ssh_connect(ssh_session session) + set_status(session, 0.2f); + + session->alive = 1; +- SSH_LOG(SSH_LOG_PROTOCOL, ++ SSH_LOG(SSH_LOG_DEBUG, + "Socket connecting, now waiting for the callbacks to work"); + + pending: +diff --git a/src/config.c b/src/config.c +index 54ada276..5a5058c1 100644 +--- a/src/config.c ++++ b/src/config.c +@@ -360,7 +360,7 @@ ssh_config_parse_proxy_jump(ssh_session session, const char *s, bool do_parsing) + next ? next : "", + hostname); + if (rv < 0 || rv >= (int)sizeof(com)) { +- SSH_LOG(SSH_LOG_WARN, "Too long ProxyJump configuration line"); ++ SSH_LOG(SSH_LOG_TRACE, "Too long ProxyJump configuration line"); + rv = SSH_ERROR; + goto out; + } +@@ -494,7 +494,7 @@ ssh_config_parse_line(ssh_session session, + + case MATCH_FINAL: + case MATCH_CANONICAL: +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_DEBUG, + "line %d: Unsupported Match keyword '%s', skipping", + count, + p); +@@ -506,13 +506,13 @@ ssh_config_parse_line(ssh_session session, + /* Skip to the end of line as unsupported */ + p = ssh_config_get_cmd(&s); + if (p == NULL || p[0] == '\0') { +- SSH_LOG(SSH_LOG_WARN, "line %d: Match keyword " ++ SSH_LOG(SSH_LOG_TRACE, "line %d: Match keyword " + "'%s' requires argument", count, p2); + SAFE_FREE(x); + return -1; + } + args++; +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_DEBUG, + "line %d: Unsupported Match keyword '%s', ignoring", + count, + p2); +@@ -531,7 +531,7 @@ ssh_config_parse_line(ssh_session session, + } + localuser = ssh_get_local_username(); + if (localuser == NULL) { +- SSH_LOG(SSH_LOG_WARN, "line %d: Can not get local username " ++ SSH_LOG(SSH_LOG_TRACE, "line %d: Can not get local username " + "for conditional matching.", count); + SAFE_FREE(x); + return -1; +@@ -545,13 +545,13 @@ ssh_config_parse_line(ssh_session session, + /* Skip one argument */ + p = ssh_config_get_str_tok(&s, NULL); + if (p == NULL || p[0] == '\0') { +- SSH_LOG(SSH_LOG_WARN, "line %d: Match keyword " ++ SSH_LOG(SSH_LOG_TRACE, "line %d: Match keyword " + "'%s' requires argument", count, p2); + SAFE_FREE(x); + return -1; + } + args++; +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_TRACE, + "line %d: Unsupported Match keyword '%s', ignoring", + count, + p2); +@@ -786,10 +786,10 @@ ssh_config_parse_line(ssh_session session, + if (strcasecmp(p, "quiet") == 0) { + value = SSH_LOG_NONE; + } else if (strcasecmp(p, "fatal") == 0 || +- strcasecmp(p, "error")== 0 || +- strcasecmp(p, "info") == 0) { ++ strcasecmp(p, "error")== 0) { + value = SSH_LOG_WARN; +- } else if (strcasecmp(p, "verbose") == 0) { ++ } else if (strcasecmp(p, "verbose") == 0 || ++ strcasecmp(p, "info") == 0) { + value = SSH_LOG_INFO; + } else if (strcasecmp(p, "DEBUG") == 0 || + strcasecmp(p, "DEBUG1") == 0) { +@@ -834,13 +834,13 @@ ssh_config_parse_line(ssh_session session, + ll = strtoll(p, &endp, 10); + if (p == endp || ll < 0) { + /* No number or negative */ +- SSH_LOG(SSH_LOG_WARN, "Invalid argument to rekey limit"); ++ SSH_LOG(SSH_LOG_TRACE, "Invalid argument to rekey limit"); + break; + } + switch (*endp) { + case 'G': + if (ll > LLONG_MAX / 1024) { +- SSH_LOG(SSH_LOG_WARN, "Possible overflow of rekey limit"); ++ SSH_LOG(SSH_LOG_TRACE, "Possible overflow of rekey limit"); + ll = -1; + break; + } +@@ -848,7 +848,7 @@ ssh_config_parse_line(ssh_session session, + FALL_THROUGH; + case 'M': + if (ll > LLONG_MAX / 1024) { +- SSH_LOG(SSH_LOG_WARN, "Possible overflow of rekey limit"); ++ SSH_LOG(SSH_LOG_TRACE, "Possible overflow of rekey limit"); + ll = -1; + break; + } +@@ -856,7 +856,7 @@ ssh_config_parse_line(ssh_session session, + FALL_THROUGH; + case 'K': + if (ll > LLONG_MAX / 1024) { +- SSH_LOG(SSH_LOG_WARN, "Possible overflow of rekey limit"); ++ SSH_LOG(SSH_LOG_TRACE, "Possible overflow of rekey limit"); + ll = -1; + break; + } +@@ -872,7 +872,7 @@ ssh_config_parse_line(ssh_session session, + break; + } + if (*endp != ' ' && *endp != '\0') { +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_TRACE, + "Invalid trailing characters after the rekey limit: %s", + endp); + break; +@@ -893,14 +893,14 @@ ssh_config_parse_line(ssh_session session, + ll = strtoll(p, &endp, 10); + if (p == endp || ll < 0) { + /* No number or negative */ +- SSH_LOG(SSH_LOG_WARN, "Invalid argument to rekey limit"); ++ SSH_LOG(SSH_LOG_TRACE, "Invalid argument to rekey limit"); + break; + } + switch (*endp) { + case 'w': + case 'W': + if (ll > LLONG_MAX / 7) { +- SSH_LOG(SSH_LOG_WARN, "Possible overflow of rekey limit"); ++ SSH_LOG(SSH_LOG_TRACE, "Possible overflow of rekey limit"); + ll = -1; + break; + } +@@ -909,7 +909,7 @@ ssh_config_parse_line(ssh_session session, + case 'd': + case 'D': + if (ll > LLONG_MAX / 24) { +- SSH_LOG(SSH_LOG_WARN, "Possible overflow of rekey limit"); ++ SSH_LOG(SSH_LOG_TRACE, "Possible overflow of rekey limit"); + ll = -1; + break; + } +@@ -918,7 +918,7 @@ ssh_config_parse_line(ssh_session session, + case 'h': + case 'H': + if (ll > LLONG_MAX / 60) { +- SSH_LOG(SSH_LOG_WARN, "Possible overflow of rekey limit"); ++ SSH_LOG(SSH_LOG_TRACE, "Possible overflow of rekey limit"); + ll = -1; + break; + } +@@ -927,7 +927,7 @@ ssh_config_parse_line(ssh_session session, + case 'm': + case 'M': + if (ll > LLONG_MAX / 60) { +- SSH_LOG(SSH_LOG_WARN, "Possible overflow of rekey limit"); ++ SSH_LOG(SSH_LOG_TRACE, "Possible overflow of rekey limit"); + ll = -1; + break; + } +@@ -946,7 +946,7 @@ ssh_config_parse_line(ssh_session session, + break; + } + if (*endp != '\0') { +- SSH_LOG(SSH_LOG_WARN, "Invalid trailing characters after the" ++ SSH_LOG(SSH_LOG_TRACE, "Invalid trailing characters after the" + " rekey limit: %s", endp); + break; + } +@@ -982,7 +982,7 @@ ssh_config_parse_line(ssh_session session, + } + break; + case SOC_NA: +- SSH_LOG(SSH_LOG_INFO, "Unapplicable option: %s, line: %d", ++ SSH_LOG(SSH_LOG_TRACE, "Unapplicable option: %s, line: %d", + keyword, count); + break; + case SOC_UNSUPPORTED: +@@ -990,7 +990,7 @@ ssh_config_parse_line(ssh_session session, + keyword, count); + break; + case SOC_UNKNOWN: +- SSH_LOG(SSH_LOG_WARN, "Unknown option: %s, line: %d", ++ SSH_LOG(SSH_LOG_TRACE, "Unknown option: %s, line: %d", + keyword, count); + break; + default: +diff --git a/src/config_parser.c b/src/config_parser.c +index ae2aa2c8..3a219d61 100644 +--- a/src/config_parser.c ++++ b/src/config_parser.c +@@ -209,7 +209,7 @@ int ssh_config_parse_uri(const char *tok, + /* Verify the port is valid positive number */ + port_n = strtol(endp + 1, &port_end, 10); + if (port_n < 1 || *port_end != '\0') { +- SSH_LOG(SSH_LOG_WARN, "Failed to parse port number." ++ SSH_LOG(SSH_LOG_TRACE, "Failed to parse port number." + " The value '%ld' is invalid or there are some" + " trailing characters: '%s'", port_n, port_end); + goto error; +diff --git a/src/curve25519.c b/src/curve25519.c +index d2517551..d8e0456a 100644 +--- a/src/curve25519.c ++++ b/src/curve25519.c +@@ -339,7 +339,7 @@ static SSH_PACKET_CALLBACK(ssh_packet_client_curve25519_reply){ + goto error; + } + +- SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent"); ++ SSH_LOG(SSH_LOG_DEBUG, "SSH_MSG_NEWKEYS sent"); + session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; + + return SSH_PACKET_USED; +@@ -491,7 +491,7 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init){ + goto error; + } + +- SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_KEX_ECDH_REPLY sent"); ++ SSH_LOG(SSH_LOG_DEBUG, "SSH_MSG_KEX_ECDH_REPLY sent"); + rc = ssh_packet_send(session); + if (rc == SSH_ERROR) { + return SSH_ERROR; +@@ -508,7 +508,7 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init){ + if (rc == SSH_ERROR) { + goto error; + } +- SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent"); ++ SSH_LOG(SSH_LOG_DEBUG, "SSH_MSG_NEWKEYS sent"); + + return SSH_PACKET_USED; + error: +diff --git a/src/dh-gex.c b/src/dh-gex.c +index 88a97140..ace572dc 100644 +--- a/src/dh-gex.c ++++ b/src/dh-gex.c +@@ -112,7 +112,7 @@ SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_group) + (void) type; + (void) user; + +- SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_KEX_DH_GEX_GROUP received"); ++ SSH_LOG(SSH_LOG_DEBUG, "SSH_MSG_KEX_DH_GEX_GROUP received"); + + if (bignum_ctx_invalid(ctx)) { + goto error; +@@ -246,7 +246,7 @@ static SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_reply) + bignum server_pubkey = NULL; + (void)type; + (void)user; +- SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_KEX_DH_GEX_REPLY received"); ++ SSH_LOG(SSH_LOG_DEBUG, "SSH_MSG_KEX_DH_GEX_REPLY received"); + + ssh_packet_remove_callbacks(session, &ssh_dhgex_client_callbacks); + rc = ssh_buffer_unpack(packet, +@@ -290,7 +290,7 @@ static SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_reply) + if (rc == SSH_ERROR) { + goto error; + } +- SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent"); ++ SSH_LOG(SSH_LOG_DEBUG, "SSH_MSG_NEWKEYS sent"); + session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; + + return SSH_PACKET_USED; +@@ -425,7 +425,7 @@ static int ssh_retrieve_dhgroup_file(FILE *moduli, + if (rc == EOF) { + break; + } +- SSH_LOG(SSH_LOG_INFO, "Invalid moduli entry line %zu", line); ++ SSH_LOG(SSH_LOG_DEBUG, "Invalid moduli entry line %zu", line); + do { + firstbyte = getc(moduli); + } while(firstbyte != '\n' && firstbyte != EOF); +@@ -463,13 +463,13 @@ static int ssh_retrieve_dhgroup_file(FILE *moduli, + } + } + if (*best_size != 0) { +- SSH_LOG(SSH_LOG_INFO, ++ SSH_LOG(SSH_LOG_DEBUG, + "Selected %zu bits modulus out of %zu candidates in %zu lines", + *best_size, + best_nlines - 1, + line); + } else { +- SSH_LOG(SSH_LOG_WARNING, ++ SSH_LOG(SSH_LOG_DEBUG, + "No moduli found for [%u:%u:%u]", + pmin, + pn, +@@ -510,7 +510,7 @@ static int ssh_retrieve_dhgroup(uint32_t pmin, + + moduli = fopen(MODULI_FILE, "r"); + if (moduli == NULL) { +- SSH_LOG(SSH_LOG_WARNING, ++ SSH_LOG(SSH_LOG_DEBUG, + "Unable to open moduli file: %s", + strerror(errno)); + return ssh_fallback_group(pmax, p, g); +@@ -605,7 +605,7 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_dhgex_request) + ssh_set_error_invalid(session); + goto error; + } +- SSH_LOG(SSH_LOG_INFO, "dh-gex: DHGEX_REQUEST[%u:%u:%u]", pmin, pn, pmax); ++ SSH_LOG(SSH_LOG_DEBUG, "dh-gex: DHGEX_REQUEST[%u:%u:%u]", pmin, pn, pmax); + + if (pmin > pn || pn > pmax || pn > DH_PMAX || pmax < DH_PMIN) { + ssh_set_error(session, +diff --git a/src/dh.c b/src/dh.c +index 18b71734..ede4855d 100644 +--- a/src/dh.c ++++ b/src/dh.c +@@ -390,7 +390,7 @@ SSH_PACKET_CALLBACK(ssh_packet_client_dh_reply){ + goto error; + } + +- SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent"); ++ SSH_LOG(SSH_LOG_DEBUG, "SSH_MSG_NEWKEYS sent"); + session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; + return SSH_PACKET_USED; + error: +diff --git a/src/ecdh.c b/src/ecdh.c +index a4c07ccb..b57789d4 100644 +--- a/src/ecdh.c ++++ b/src/ecdh.c +@@ -97,7 +97,7 @@ SSH_PACKET_CALLBACK(ssh_packet_client_ecdh_reply){ + goto error; + } + +- SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent"); ++ SSH_LOG(SSH_LOG_DEBUG, "SSH_MSG_NEWKEYS sent"); + session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; + + return SSH_PACKET_USED; +diff --git a/src/ecdh_crypto.c b/src/ecdh_crypto.c +index a1de27fd..d050544f 100644 +--- a/src/ecdh_crypto.c ++++ b/src/ecdh_crypto.c +@@ -317,7 +317,7 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){ + goto error; + } + +- SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_KEXDH_REPLY sent"); ++ SSH_LOG(SSH_LOG_DEBUG, "SSH_MSG_KEXDH_REPLY sent"); + rc = ssh_packet_send(session); + if (rc == SSH_ERROR) { + goto error; +@@ -334,7 +334,7 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){ + if (rc == SSH_ERROR){ + goto error; + } +- SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent"); ++ SSH_LOG(SSH_LOG_DEBUG, "SSH_MSG_NEWKEYS sent"); + + return SSH_PACKET_USED; + error: +diff --git a/src/ecdh_gcrypt.c b/src/ecdh_gcrypt.c +index d9c41bf9..ca643467 100644 +--- a/src/ecdh_gcrypt.c ++++ b/src/ecdh_gcrypt.c +@@ -366,7 +366,7 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){ + goto out; + } + +- SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_KEXDH_REPLY sent"); ++ SSH_LOG(SSH_LOG_DEBUG, "SSH_MSG_KEXDH_REPLY sent"); + rc = ssh_packet_send(session); + if (rc != SSH_OK) { + goto out; +@@ -381,7 +381,7 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){ + + session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; + rc = ssh_packet_send(session); +- SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent"); ++ SSH_LOG(SSH_LOG_DEBUG, "SSH_MSG_NEWKEYS sent"); + + out: + gcry_sexp_release(param); +diff --git a/src/ecdh_mbedcrypto.c b/src/ecdh_mbedcrypto.c +index 718f1522..855d4770 100644 +--- a/src/ecdh_mbedcrypto.c ++++ b/src/ecdh_mbedcrypto.c +@@ -293,7 +293,7 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){ + goto out; + } + +- SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_KEXDH_REPLY sent"); ++ SSH_LOG(SSH_LOG_DEBUG, "SSH_MSG_KEXDH_REPLY sent"); + rc = ssh_packet_send(session); + if (rc != SSH_OK) { + rc = SSH_ERROR; +@@ -308,7 +308,7 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){ + + session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; + rc = ssh_packet_send(session); +- SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent"); ++ SSH_LOG(SSH_LOG_DEBUG, "SSH_MSG_NEWKEYS sent"); + + out: + mbedtls_ecp_group_free(&grp); +diff --git a/src/error.c b/src/error.c +index 22180407..5e850adb 100644 +--- a/src/error.c ++++ b/src/error.c +@@ -63,8 +63,8 @@ void _ssh_set_error(void *error, + va_end(va); + + err->error.error_code = code; +- if (ssh_get_log_level() >= SSH_LOG_WARN) { +- ssh_log_function(SSH_LOG_WARN, ++ if (ssh_get_log_level() == SSH_LOG_TRACE) { ++ ssh_log_function(SSH_LOG_TRACE, + function, + err->error.error_buffer); + } +diff --git a/src/gssapi.c b/src/gssapi.c +index 1d0fb6ae..cfa36a95 100644 +--- a/src/gssapi.c ++++ b/src/gssapi.c +@@ -218,8 +218,8 @@ int ssh_gssapi_handle_userauth(ssh_session session, const char *user, uint32_t n + + maj_stat = gss_indicate_mechs(&min_stat, &supported); + if (maj_stat != GSS_S_COMPLETE) { +- SSH_LOG(SSH_LOG_WARNING, "indicate mecks %d, %d", maj_stat, min_stat); +- ssh_gssapi_log_error(SSH_LOG_WARNING, ++ SSH_LOG(SSH_LOG_DEBUG, "indicate mecks %d, %d", maj_stat, min_stat); ++ ssh_gssapi_log_error(SSH_LOG_DEBUG, + "indicate mechs", + maj_stat, + min_stat); +@@ -240,7 +240,7 @@ int ssh_gssapi_handle_userauth(ssh_session session, const char *user, uint32_t n + continue; + } + if(len < 2 || oid_s[0] != SSH_OID_TAG || ((size_t)oid_s[1]) != len - 2){ +- SSH_LOG(SSH_LOG_WARNING,"GSSAPI: received invalid OID"); ++ SSH_LOG(SSH_LOG_TRACE,"GSSAPI: received invalid OID"); + continue; + } + oid.elements = &oid_s[2]; +@@ -253,7 +253,7 @@ int ssh_gssapi_handle_userauth(ssh_session session, const char *user, uint32_t n + } + gss_release_oid_set(&min_stat, &supported); + if (oid_count == 0){ +- SSH_LOG(SSH_LOG_PROTOCOL,"GSSAPI: no OID match"); ++ SSH_LOG(SSH_LOG_DEBUG,"GSSAPI: no OID match"); + ssh_auth_reply_default(session, 0); + gss_release_oid_set(&min_stat, &both_supported); + return SSH_OK; +@@ -267,8 +267,8 @@ int ssh_gssapi_handle_userauth(ssh_session session, const char *user, uint32_t n + maj_stat = gss_import_name(&min_stat, &name_buf, + (gss_OID) GSS_C_NT_HOSTBASED_SERVICE, &server_name); + if (maj_stat != GSS_S_COMPLETE) { +- SSH_LOG(SSH_LOG_WARNING, "importing name %d, %d", maj_stat, min_stat); +- ssh_gssapi_log_error(SSH_LOG_WARNING, ++ SSH_LOG(SSH_LOG_DEBUG, "importing name %d, %d", maj_stat, min_stat); ++ ssh_gssapi_log_error(SSH_LOG_DEBUG, + "importing name", + maj_stat, + min_stat); +@@ -282,8 +282,8 @@ int ssh_gssapi_handle_userauth(ssh_session session, const char *user, uint32_t n + gss_release_oid_set(&min_stat, &both_supported); + + if (maj_stat != GSS_S_COMPLETE) { +- SSH_LOG(SSH_LOG_WARNING, "error acquiring credentials %d, %d", maj_stat, min_stat); +- ssh_gssapi_log_error(SSH_LOG_WARNING, ++ SSH_LOG(SSH_LOG_TRACE, "error acquiring credentials %d, %d", maj_stat, min_stat); ++ ssh_gssapi_log_error(SSH_LOG_TRACE, + "acquiring creds", + maj_stat, + min_stat); +@@ -291,7 +291,7 @@ int ssh_gssapi_handle_userauth(ssh_session session, const char *user, uint32_t n + return SSH_ERROR; + } + +- SSH_LOG(SSH_LOG_PROTOCOL, "acquiring credentials %d, %d", maj_stat, min_stat); ++ SSH_LOG(SSH_LOG_DEBUG, "acquiring credentials %d, %d", maj_stat, min_stat); + + /* finding which OID from client we selected */ + for (i=0 ; i< n_oid ; ++i){ +@@ -302,7 +302,7 @@ int ssh_gssapi_handle_userauth(ssh_session session, const char *user, uint32_t n + continue; + } + if(len < 2 || oid_s[0] != SSH_OID_TAG || ((size_t)oid_s[1]) != len - 2){ +- SSH_LOG(SSH_LOG_WARNING,"GSSAPI: received invalid OID"); ++ SSH_LOG(SSH_LOG_TRACE,"GSSAPI: received invalid OID"); + continue; + } + oid.elements = &oid_s[2]; +@@ -332,7 +332,7 @@ static char *ssh_gssapi_name_to_char(gss_name_t name){ + OM_uint32 maj_stat, min_stat; + char *ptr; + maj_stat = gss_display_name(&min_stat, name, &buffer, NULL); +- ssh_gssapi_log_error(SSH_LOG_WARNING, ++ ssh_gssapi_log_error(SSH_LOG_DEBUG, + "converting name", + maj_stat, + min_stat); +@@ -407,7 +407,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_server){ + maj_stat = gss_accept_sec_context(&min_stat, &session->gssapi->ctx, session->gssapi->server_creds, + &input_token, input_bindings, &client_name, NULL /*mech_oid*/, &output_token, &ret_flags, + NULL /*time*/, &session->gssapi->client_creds); +- ssh_gssapi_log_error(SSH_LOG_PROTOCOL, ++ ssh_gssapi_log_error(SSH_LOG_DEBUG, + "accepting token", + maj_stat, + min_stat); +@@ -417,7 +417,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_server){ + session->gssapi->canonic_user = ssh_gssapi_name_to_char(client_name); + } + if (GSS_ERROR(maj_stat)){ +- ssh_gssapi_log_error(SSH_LOG_WARNING, ++ ssh_gssapi_log_error(SSH_LOG_DEBUG, + "Gssapi error", + maj_stat, + min_stat); +@@ -524,7 +524,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_mic) + mic_token_buf.value = ssh_string_data(mic_token); + + maj_stat = gss_verify_mic(&min_stat, session->gssapi->ctx, &mic_buf, &mic_token_buf, NULL); +- ssh_gssapi_log_error(SSH_LOG_PROTOCOL, ++ ssh_gssapi_log_error(SSH_LOG_DEBUG, + "verifying MIC", + maj_stat, + min_stat); +@@ -739,8 +739,8 @@ int ssh_gssapi_auth_mic(ssh_session session){ + (gss_OID)GSS_C_NT_HOSTBASED_SERVICE, + &session->gssapi->client.server_name); + if (maj_stat != GSS_S_COMPLETE) { +- SSH_LOG(SSH_LOG_WARNING, "importing name %d, %d", maj_stat, min_stat); +- ssh_gssapi_log_error(SSH_LOG_WARNING, ++ SSH_LOG(SSH_LOG_DEBUG, "importing name %d, %d", maj_stat, min_stat); ++ ssh_gssapi_log_error(SSH_LOG_DEBUG, + "importing name", + maj_stat, + min_stat); +@@ -754,7 +754,7 @@ int ssh_gssapi_auth_mic(ssh_session session){ + return SSH_AUTH_ERROR; + } + +- SSH_LOG(SSH_LOG_PROTOCOL, "Authenticating with gssapi to host %s with user %s", ++ SSH_LOG(SSH_LOG_DEBUG, "Authenticating with gssapi to host %s with user %s", + session->opts.host, session->gssapi->user); + rc = ssh_gssapi_match(session, &selected); + if (rc == SSH_ERROR) { +@@ -762,7 +762,7 @@ int ssh_gssapi_auth_mic(ssh_session session){ + } + + n_oids = selected->count; +- SSH_LOG(SSH_LOG_PROTOCOL, "Sending %zu oids", n_oids); ++ SSH_LOG(SSH_LOG_DEBUG, "Sending %zu oids", n_oids); + + oids = calloc(n_oids, sizeof(ssh_string)); + if (oids == NULL) { +@@ -875,7 +875,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_response){ + 0, NULL, &input_token, NULL, + &output_token, NULL, NULL); + if(GSS_ERROR(maj_stat)){ +- ssh_gssapi_log_error(SSH_LOG_WARNING, ++ ssh_gssapi_log_error(SSH_LOG_DEBUG, + "Initializing gssapi context", + maj_stat, + min_stat); +@@ -923,7 +923,7 @@ static int ssh_gssapi_send_mic(ssh_session session){ + &mic_buf, &mic_token_buf); + if (GSS_ERROR(maj_stat)){ + SSH_BUFFER_FREE(mic_buffer); +- ssh_gssapi_log_error(SSH_LOG_PROTOCOL, ++ ssh_gssapi_log_error(SSH_LOG_DEBUG, + "generating MIC", + maj_stat, + min_stat); +@@ -980,13 +980,13 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_client){ + 0, NULL, &input_token, NULL, + &output_token, NULL, NULL); + +- ssh_gssapi_log_error(SSH_LOG_PROTOCOL, ++ ssh_gssapi_log_error(SSH_LOG_DEBUG, + "accepting token", + maj_stat, + min_stat); + SSH_STRING_FREE(token); + if (GSS_ERROR(maj_stat)){ +- ssh_gssapi_log_error(SSH_LOG_PROTOCOL, ++ ssh_gssapi_log_error(SSH_LOG_DEBUG, + "Gssapi error", + maj_stat, + min_stat); +diff --git a/src/kex.c b/src/kex.c +index 82071c74..9b599657 100644 +--- a/src/kex.c ++++ b/src/kex.c +@@ -345,7 +345,7 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit) + (void)user; + + if (session->session_state == SSH_SESSION_STATE_AUTHENTICATED) { +- SSH_LOG(SSH_LOG_INFO, "Initiating key re-exchange"); ++ SSH_LOG(SSH_LOG_DEBUG, "Initiating key re-exchange"); + } else if (session->session_state != SSH_SESSION_STATE_INITIAL_KEX) { + ssh_set_error(session,SSH_FATAL,"SSH_KEXINIT received in wrong state"); + goto error; +@@ -590,7 +590,7 @@ char *ssh_client_select_hostkeys(ssh_session session) + /* This removes the certificate types, unsupported for now */ + wanted_without_certs = ssh_find_all_matching(HOSTKEYS, wanted); + if (wanted_without_certs == NULL) { +- SSH_LOG(SSH_LOG_WARNING, ++ SSH_LOG(SSH_LOG_TRACE, + "List of allowed host key algorithms is empty or contains only " + "unsupported algorithms"); + return NULL; +@@ -643,7 +643,7 @@ char *ssh_client_select_hostkeys(ssh_session session) + fips_hostkeys = ssh_keep_fips_algos(SSH_HOSTKEYS, new_hostkeys); + SAFE_FREE(new_hostkeys); + if (fips_hostkeys == NULL) { +- SSH_LOG(SSH_LOG_WARNING, ++ SSH_LOG(SSH_LOG_TRACE, + "None of the wanted host keys or keys in known_hosts files " + "is allowed in FIPS mode."); + return NULL; +@@ -813,7 +813,7 @@ int ssh_kex_select_methods (ssh_session session) + } else if (strcmp(session->next_crypto->kex_methods[SSH_KEX], "curve25519-sha256") == 0){ + session->next_crypto->kex_type=SSH_KEX_CURVE25519_SHA256; + } +- SSH_LOG(SSH_LOG_INFO, "Negotiated %s,%s,%s,%s,%s,%s,%s,%s,%s,%s", ++ SSH_LOG(SSH_LOG_DEBUG, "Negotiated %s,%s,%s,%s,%s,%s,%s,%s,%s,%s", + session->next_crypto->kex_methods[SSH_KEX], + session->next_crypto->kex_methods[SSH_HOSTKEYS], + session->next_crypto->kex_methods[SSH_CRYPT_C_S], +@@ -1114,7 +1114,7 @@ int ssh_make_sessionid(ssh_session session) + case SSH_KEX_ECDH_SHA2_NISTP521: + if (session->next_crypto->ecdh_client_pubkey == NULL || + session->next_crypto->ecdh_server_pubkey == NULL) { +- SSH_LOG(SSH_LOG_WARNING, "ECDH parameted missing"); ++ SSH_LOG(SSH_LOG_TRACE, "ECDH parameted missing"); + goto error; + } + rc = ssh_buffer_pack(buf, +diff --git a/src/knownhosts.c b/src/knownhosts.c +index f2ef088c..e632ef22 100644 +--- a/src/knownhosts.c ++++ b/src/knownhosts.c +@@ -224,7 +224,7 @@ static int ssh_known_hosts_read_entries(const char *match, + + fp = fopen(filename, "r"); + if (fp == NULL) { +- SSH_LOG(SSH_LOG_WARN, "Failed to open the known_hosts file '%s': %s", ++ SSH_LOG(SSH_LOG_TRACE, "Failed to open the known_hosts file '%s': %s", + filename, strerror(errno)); + /* The missing file is not an error here */ + return SSH_OK; +@@ -483,7 +483,7 @@ static const char *ssh_known_host_sigs_from_hostkey_type(enum ssh_keytypes_e typ + #endif + case SSH_KEYTYPE_UNKNOWN: + default: +- SSH_LOG(SSH_LOG_WARN, "The given type %d is not a base private key type " ++ SSH_LOG(SSH_LOG_TRACE, "The given type %d is not a base private key type " + "or is unsupported", type); + return NULL; + } +@@ -719,7 +719,7 @@ int ssh_known_hosts_parse_line(const char *hostname, + + key_type = ssh_key_type_from_name(p); + if (key_type == SSH_KEYTYPE_UNKNOWN) { +- SSH_LOG(SSH_LOG_WARN, "key type '%s' unknown!", p); ++ SSH_LOG(SSH_LOG_TRACE, "key type '%s' unknown!", p); + rc = SSH_ERROR; + goto out; + } +@@ -735,7 +735,7 @@ int ssh_known_hosts_parse_line(const char *hostname, + key_type, + &e->publickey); + if (rc != SSH_OK) { +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_TRACE, + "Failed to parse %s key for entry: %s!", + ssh_key_type_to_char(key_type), + e->unparsed); +@@ -806,7 +806,7 @@ enum ssh_known_hosts_e ssh_session_has_known_hosts_entry(ssh_session session) + if (session->opts.knownhosts != NULL) { + known_hosts_found = ssh_file_readaccess_ok(session->opts.knownhosts); + if (!known_hosts_found) { +- SSH_LOG(SSH_LOG_WARN, "Cannot access file %s", ++ SSH_LOG(SSH_LOG_TRACE, "Cannot access file %s", + session->opts.knownhosts); + } + } +@@ -815,7 +815,7 @@ enum ssh_known_hosts_e ssh_session_has_known_hosts_entry(ssh_session session) + global_known_hosts_found = + ssh_file_readaccess_ok(session->opts.global_knownhosts); + if (!global_known_hosts_found) { +- SSH_LOG(SSH_LOG_WARN, "Cannot access file %s", ++ SSH_LOG(SSH_LOG_TRACE, "Cannot access file %s", + session->opts.global_knownhosts); + } + } +diff --git a/src/libcrypto.c b/src/libcrypto.c +index 3db75df6..c002262a 100644 +--- a/src/libcrypto.c ++++ b/src/libcrypto.c +@@ -496,7 +496,7 @@ static void evp_cipher_init(struct ssh_cipher_struct *cipher) { + case SSH_AES128_CTR: + case SSH_AES192_CTR: + case SSH_AES256_CTR: +- SSH_LOG(SSH_LOG_WARNING, "This cipher is not available in evp_cipher_init"); ++ SSH_LOG(SSH_LOG_TRACE, "This cipher is not available in evp_cipher_init"); + break; + #endif + #ifdef HAVE_OPENSSL_EVP_AES_GCM +@@ -509,7 +509,7 @@ static void evp_cipher_init(struct ssh_cipher_struct *cipher) { + #else + case SSH_AEAD_AES128_GCM: + case SSH_AEAD_AES256_GCM: +- SSH_LOG(SSH_LOG_WARNING, "This cipher is not available in evp_cipher_init"); ++ SSH_LOG(SSH_LOG_TRACE, "This cipher is not available in evp_cipher_init"); + break; + #endif /* HAVE_OPENSSL_EVP_AES_GCM */ + case SSH_3DES_CBC: +@@ -522,10 +522,10 @@ static void evp_cipher_init(struct ssh_cipher_struct *cipher) { + /* ciphers not using EVP */ + #endif + case SSH_AEAD_CHACHA20_POLY1305: +- SSH_LOG(SSH_LOG_WARNING, "The ChaCha cipher cannot be handled here"); ++ SSH_LOG(SSH_LOG_TRACE, "The ChaCha cipher cannot be handled here"); + break; + case SSH_NO_CIPHER: +- SSH_LOG(SSH_LOG_WARNING, "No valid ciphertype found"); ++ SSH_LOG(SSH_LOG_TRACE, "No valid ciphertype found"); + break; + } + } +@@ -540,7 +540,7 @@ static int evp_cipher_set_encrypt_key(struct ssh_cipher_struct *cipher, + + rc = EVP_EncryptInit_ex(cipher->ctx, cipher->cipher, NULL, key, IV); + if (rc != 1){ +- SSH_LOG(SSH_LOG_WARNING, "EVP_EncryptInit_ex failed"); ++ SSH_LOG(SSH_LOG_TRACE, "EVP_EncryptInit_ex failed"); + return SSH_ERROR; + } + +@@ -553,7 +553,7 @@ static int evp_cipher_set_encrypt_key(struct ssh_cipher_struct *cipher, + -1, + (uint8_t *)IV); + if (rc != 1) { +- SSH_LOG(SSH_LOG_WARNING, "EVP_CTRL_GCM_SET_IV_FIXED failed"); ++ SSH_LOG(SSH_LOG_TRACE, "EVP_CTRL_GCM_SET_IV_FIXED failed"); + return SSH_ERROR; + } + } +@@ -573,7 +573,7 @@ static int evp_cipher_set_decrypt_key(struct ssh_cipher_struct *cipher, + + rc = EVP_DecryptInit_ex(cipher->ctx, cipher->cipher, NULL, key, IV); + if (rc != 1){ +- SSH_LOG(SSH_LOG_WARNING, "EVP_DecryptInit_ex failed"); ++ SSH_LOG(SSH_LOG_TRACE, "EVP_DecryptInit_ex failed"); + return SSH_ERROR; + } + +@@ -586,7 +586,7 @@ static int evp_cipher_set_decrypt_key(struct ssh_cipher_struct *cipher, + -1, + (uint8_t *)IV); + if (rc != 1) { +- SSH_LOG(SSH_LOG_WARNING, "EVP_CTRL_GCM_SET_IV_FIXED failed"); ++ SSH_LOG(SSH_LOG_TRACE, "EVP_CTRL_GCM_SET_IV_FIXED failed"); + return SSH_ERROR; + } + } +@@ -612,11 +612,11 @@ static void evp_cipher_encrypt(struct ssh_cipher_struct *cipher, + (unsigned char *)in, + (int)len); + if (rc != 1){ +- SSH_LOG(SSH_LOG_WARNING, "EVP_EncryptUpdate failed"); ++ SSH_LOG(SSH_LOG_TRACE, "EVP_EncryptUpdate failed"); + return; + } + if (outlen != (int)len){ +- SSH_LOG(SSH_LOG_WARNING, ++ SSH_LOG(SSH_LOG_DEBUG, + "EVP_EncryptUpdate: output size %d for %zu in", + outlen, + len); +@@ -638,11 +638,11 @@ static void evp_cipher_decrypt(struct ssh_cipher_struct *cipher, + (unsigned char *)in, + (int)len); + if (rc != 1){ +- SSH_LOG(SSH_LOG_WARNING, "EVP_DecryptUpdate failed"); ++ SSH_LOG(SSH_LOG_TRACE, "EVP_DecryptUpdate failed"); + return; + } + if (outlen != (int)len){ +- SSH_LOG(SSH_LOG_WARNING, ++ SSH_LOG(SSH_LOG_DEBUG, + "EVP_DecryptUpdate: output size %d for %zu in", + outlen, + len); +@@ -759,7 +759,7 @@ evp_cipher_aead_encrypt(struct ssh_cipher_struct *cipher, + 1, + lastiv); + if (rc == 0) { +- SSH_LOG(SSH_LOG_WARNING, "EVP_CTRL_GCM_IV_GEN failed"); ++ SSH_LOG(SSH_LOG_TRACE, "EVP_CTRL_GCM_IV_GEN failed"); + return; + } + +@@ -771,7 +771,7 @@ evp_cipher_aead_encrypt(struct ssh_cipher_struct *cipher, + (int)aadlen); + outlen = tmplen; + if (rc == 0 || outlen != aadlen) { +- SSH_LOG(SSH_LOG_WARNING, "Failed to pass authenticated data"); ++ SSH_LOG(SSH_LOG_TRACE, "Failed to pass authenticated data"); + return; + } + memcpy(out, in, aadlen); +@@ -784,7 +784,7 @@ evp_cipher_aead_encrypt(struct ssh_cipher_struct *cipher, + (int)len - aadlen); + outlen = tmplen; + if (rc != 1 || outlen != (int)len - aadlen) { +- SSH_LOG(SSH_LOG_WARNING, "EVP_EncryptUpdate failed"); ++ SSH_LOG(SSH_LOG_TRACE, "EVP_EncryptUpdate failed"); + return; + } + +@@ -793,7 +793,7 @@ evp_cipher_aead_encrypt(struct ssh_cipher_struct *cipher, + NULL, + &tmplen); + if (rc < 0) { +- SSH_LOG(SSH_LOG_WARNING, "EVP_EncryptFinal failed: Failed to create a tag"); ++ SSH_LOG(SSH_LOG_TRACE, "EVP_EncryptFinal failed: Failed to create a tag"); + return; + } + +@@ -802,7 +802,7 @@ evp_cipher_aead_encrypt(struct ssh_cipher_struct *cipher, + authlen, + (unsigned char *)tag); + if (rc != 1) { +- SSH_LOG(SSH_LOG_WARNING, "EVP_CTRL_GCM_GET_TAG failed"); ++ SSH_LOG(SSH_LOG_TRACE, "EVP_CTRL_GCM_GET_TAG failed"); + return; + } + } +@@ -830,7 +830,7 @@ evp_cipher_aead_decrypt(struct ssh_cipher_struct *cipher, + 1, + lastiv); + if (rc == 0) { +- SSH_LOG(SSH_LOG_WARNING, "EVP_CTRL_GCM_IV_GEN failed"); ++ SSH_LOG(SSH_LOG_TRACE, "EVP_CTRL_GCM_IV_GEN failed"); + return SSH_ERROR; + } + +@@ -840,7 +840,7 @@ evp_cipher_aead_decrypt(struct ssh_cipher_struct *cipher, + authlen, + (unsigned char *)complete_packet + aadlen + encrypted_size); + if (rc == 0) { +- SSH_LOG(SSH_LOG_WARNING, "EVP_CTRL_GCM_SET_TAG failed"); ++ SSH_LOG(SSH_LOG_TRACE, "EVP_CTRL_GCM_SET_TAG failed"); + return SSH_ERROR; + } + +@@ -851,7 +851,7 @@ evp_cipher_aead_decrypt(struct ssh_cipher_struct *cipher, + (unsigned char *)complete_packet, + (int)aadlen); + if (rc == 0) { +- SSH_LOG(SSH_LOG_WARNING, "Failed to pass authenticated data"); ++ SSH_LOG(SSH_LOG_TRACE, "Failed to pass authenticated data"); + return SSH_ERROR; + } + /* Do not copy the length to the target buffer, because it is already processed */ +@@ -864,12 +864,12 @@ evp_cipher_aead_decrypt(struct ssh_cipher_struct *cipher, + (unsigned char *)complete_packet + aadlen, + encrypted_size /* already substracted aadlen*/); + if (rc != 1) { +- SSH_LOG(SSH_LOG_WARNING, "EVP_DecryptUpdate failed"); ++ SSH_LOG(SSH_LOG_TRACE, "EVP_DecryptUpdate failed"); + return SSH_ERROR; + } + + if (outlen != (int)encrypted_size) { +- SSH_LOG(SSH_LOG_WARNING, ++ SSH_LOG(SSH_LOG_TRACE, + "EVP_DecryptUpdate: output size %d for %zd in", + outlen, + encrypted_size); +@@ -881,7 +881,7 @@ evp_cipher_aead_decrypt(struct ssh_cipher_struct *cipher, + NULL, + &outlen); + if (rc < 0) { +- SSH_LOG(SSH_LOG_WARNING, "EVP_DecryptFinal failed: Failed authentication"); ++ SSH_LOG(SSH_LOG_TRACE, "EVP_DecryptFinal failed: Failed authentication"); + return SSH_ERROR; + } + +@@ -1084,7 +1084,7 @@ int ssh_crypto_init(void) + return SSH_OK; + } + if (OpenSSL_version_num() != OPENSSL_VERSION_NUMBER){ +- SSH_LOG(SSH_LOG_WARNING, "libssh compiled with %s " ++ SSH_LOG(SSH_LOG_DEBUG, "libssh compiled with %s " + "headers, currently running with %s.", + OPENSSL_VERSION_TEXT, + OpenSSL_version(OpenSSL_version_num()) +diff --git a/src/libgcrypt.c b/src/libgcrypt.c +index 8fbf2157..9a811005 100644 +--- a/src/libgcrypt.c ++++ b/src/libgcrypt.c +@@ -329,7 +329,7 @@ static int aes_set_key(struct ssh_cipher_struct *cipher, void *key, void *IV) { + } + break; + default: +- SSH_LOG(SSH_LOG_WARNING, "Unksupported key length %u.", cipher->keysize); ++ SSH_LOG(SSH_LOG_TRACE, "Unsupported key length %u.", cipher->keysize); + SAFE_FREE(cipher->key); + return -1; + } +@@ -420,7 +420,7 @@ aes_gcm_encrypt(struct ssh_cipher_struct *cipher, + */ + uint64_inc(cipher->last_iv + 4); + if (err) { +- SSH_LOG(SSH_LOG_WARNING, "gcry_cipher_setiv failed: %s", ++ SSH_LOG(SSH_LOG_TRACE, "gcry_cipher_setiv failed: %s", + gpg_strerror(err)); + return; + } +@@ -428,7 +428,7 @@ aes_gcm_encrypt(struct ssh_cipher_struct *cipher, + /* Pass the authenticated data (packet_length) */ + err = gcry_cipher_authenticate(cipher->key[0], in, aadlen); + if (err) { +- SSH_LOG(SSH_LOG_WARNING, "gcry_cipher_authenticate failed: %s", ++ SSH_LOG(SSH_LOG_TRACE, "gcry_cipher_authenticate failed: %s", + gpg_strerror(err)); + return; + } +@@ -441,7 +441,7 @@ aes_gcm_encrypt(struct ssh_cipher_struct *cipher, + (unsigned char *)in + aadlen, + len - aadlen); + if (err) { +- SSH_LOG(SSH_LOG_WARNING, "gcry_cipher_encrypt failed: %s", ++ SSH_LOG(SSH_LOG_TRACE, "gcry_cipher_encrypt failed: %s", + gpg_strerror(err)); + return; + } +@@ -451,7 +451,7 @@ aes_gcm_encrypt(struct ssh_cipher_struct *cipher, + (void *)tag, + authlen); + if (err) { +- SSH_LOG(SSH_LOG_WARNING, "gcry_cipher_gettag failed: %s", ++ SSH_LOG(SSH_LOG_TRACE, "gcry_cipher_gettag failed: %s", + gpg_strerror(err)); + return; + } +@@ -485,7 +485,7 @@ aes_gcm_decrypt(struct ssh_cipher_struct *cipher, + */ + uint64_inc(cipher->last_iv + 4); + if (err) { +- SSH_LOG(SSH_LOG_WARNING, "gcry_cipher_setiv failed: %s", ++ SSH_LOG(SSH_LOG_TRACE, "gcry_cipher_setiv failed: %s", + gpg_strerror(err)); + return SSH_ERROR; + } +@@ -495,7 +495,7 @@ aes_gcm_decrypt(struct ssh_cipher_struct *cipher, + complete_packet, + aadlen); + if (err) { +- SSH_LOG(SSH_LOG_WARNING, "gcry_cipher_authenticate failed: %s", ++ SSH_LOG(SSH_LOG_TRACE, "gcry_cipher_authenticate failed: %s", + gpg_strerror(err)); + return SSH_ERROR; + } +@@ -509,7 +509,7 @@ aes_gcm_decrypt(struct ssh_cipher_struct *cipher, + (unsigned char *)complete_packet + aadlen, + encrypted_size); + if (err) { +- SSH_LOG(SSH_LOG_WARNING, "gcry_cipher_decrypt failed: %s", ++ SSH_LOG(SSH_LOG_TRACE, "gcry_cipher_decrypt failed: %s", + gpg_strerror(err)); + return SSH_ERROR; + } +@@ -519,10 +519,10 @@ aes_gcm_decrypt(struct ssh_cipher_struct *cipher, + (unsigned char *)complete_packet + aadlen + encrypted_size, + authlen); + if (gpg_err_code(err) == GPG_ERR_CHECKSUM) { +- SSH_LOG(SSH_LOG_WARNING, "The authentication tag does not match"); ++ SSH_LOG(SSH_LOG_DEBUG, "The authentication tag does not match"); + return SSH_ERROR; + } else if (err != GPG_ERR_NO_ERROR) { +- SSH_LOG(SSH_LOG_WARNING, "General error while decryption: %s", ++ SSH_LOG(SSH_LOG_TRACE, "General error while decryption: %s", + gpg_strerror(err)); + return SSH_ERROR; + } +diff --git a/src/libmbedcrypto.c b/src/libmbedcrypto.c +index a2e74d3b..ee30c38a 100644 +--- a/src/libmbedcrypto.c ++++ b/src/libmbedcrypto.c +@@ -468,7 +468,7 @@ cipher_init(struct ssh_cipher_struct *cipher, + } else if (operation == MBEDTLS_DECRYPT) { + ctx = &cipher->decrypt_ctx; + } else { +- SSH_LOG(SSH_LOG_WARNING, "unknown operation"); ++ SSH_LOG(SSH_LOG_TRACE, "unknown operation"); + return 1; + } + +@@ -477,7 +477,7 @@ cipher_init(struct ssh_cipher_struct *cipher, + + rc = mbedtls_cipher_setup(ctx, cipher_info); + if (rc != 0) { +- SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_setup failed"); ++ SSH_LOG(SSH_LOG_TRACE, "mbedtls_cipher_setup failed"); + goto error; + } + +@@ -485,13 +485,13 @@ cipher_init(struct ssh_cipher_struct *cipher, + cipher_info->key_bitlen, + operation); + if (rc != 0) { +- SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_setkey failed"); ++ SSH_LOG(SSH_LOG_TRACE, "mbedtls_cipher_setkey failed"); + goto error; + } + + rc = mbedtls_cipher_set_iv(ctx, IV, cipher_info->iv_size); + if (rc != 0) { +- SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_set_iv failed"); ++ SSH_LOG(SSH_LOG_TRACE, "mbedtls_cipher_set_iv failed"); + goto error; + } + +@@ -510,13 +510,13 @@ cipher_set_encrypt_key(struct ssh_cipher_struct *cipher, + + rc = cipher_init(cipher, MBEDTLS_ENCRYPT, key, IV); + if (rc != 0) { +- SSH_LOG(SSH_LOG_WARNING, "cipher_init failed"); ++ SSH_LOG(SSH_LOG_TRACE, "cipher_init failed"); + goto error; + } + + rc = mbedtls_cipher_reset(&cipher->encrypt_ctx); + if (rc != 0) { +- SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_reset failed"); ++ SSH_LOG(SSH_LOG_TRACE, "mbedtls_cipher_reset failed"); + goto error; + } + +@@ -534,7 +534,7 @@ cipher_set_encrypt_key_cbc(struct ssh_cipher_struct *cipher, + + rc = cipher_init(cipher, MBEDTLS_ENCRYPT, key, IV); + if (rc != 0) { +- SSH_LOG(SSH_LOG_WARNING, "cipher_init failed"); ++ SSH_LOG(SSH_LOG_TRACE, "cipher_init failed"); + goto error; + } + +@@ -544,13 +544,13 @@ cipher_set_encrypt_key_cbc(struct ssh_cipher_struct *cipher, + MBEDTLS_PADDING_NONE); + + if (rc != 0) { +- SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_set_padding_mode failed"); ++ SSH_LOG(SSH_LOG_TRACE, "mbedtls_cipher_set_padding_mode failed"); + goto error; + } + + rc = mbedtls_cipher_reset(&cipher->encrypt_ctx); + if (rc != 0) { +- SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_reset failed"); ++ SSH_LOG(SSH_LOG_TRACE, "mbedtls_cipher_reset failed"); + goto error; + } + +@@ -577,7 +577,7 @@ cipher_set_key_gcm(struct ssh_cipher_struct *cipher, + key, + cipher_info->key_bitlen); + if (rc != 0) { +- SSH_LOG(SSH_LOG_WARNING, "mbedtls_gcm_setkey failed"); ++ SSH_LOG(SSH_LOG_TRACE, "mbedtls_gcm_setkey failed"); + goto error; + } + +@@ -600,13 +600,13 @@ cipher_set_decrypt_key(struct ssh_cipher_struct *cipher, + + rc = cipher_init(cipher, MBEDTLS_DECRYPT, key, IV); + if (rc != 0) { +- SSH_LOG(SSH_LOG_WARNING, "cipher_init failed"); ++ SSH_LOG(SSH_LOG_TRACE, "cipher_init failed"); + goto error; + } + + mbedtls_cipher_reset(&cipher->decrypt_ctx); + if (rc != 0) { +- SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_reset failed"); ++ SSH_LOG(SSH_LOG_TRACE, "mbedtls_cipher_reset failed"); + goto error; + } + +@@ -625,20 +625,20 @@ cipher_set_decrypt_key_cbc(struct ssh_cipher_struct *cipher, + + rc = cipher_init(cipher, MBEDTLS_DECRYPT, key, IV); + if (rc != 0) { +- SSH_LOG(SSH_LOG_WARNING, "cipher_init failed"); ++ SSH_LOG(SSH_LOG_TRACE, "cipher_init failed"); + goto error; + } + + rc = mbedtls_cipher_set_padding_mode(&cipher->decrypt_ctx, + MBEDTLS_PADDING_NONE); + if (rc != 0) { +- SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_set_padding_mode failed"); ++ SSH_LOG(SSH_LOG_TRACE, "mbedtls_cipher_set_padding_mode failed"); + goto error; + } + + mbedtls_cipher_reset(&cipher->decrypt_ctx); + if (rc != 0) { +- SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_reset failed"); ++ SSH_LOG(SSH_LOG_TRACE, "mbedtls_cipher_reset failed"); + goto error; + } + +@@ -658,7 +658,7 @@ static void cipher_encrypt(struct ssh_cipher_struct *cipher, + int rc = 0; + rc = mbedtls_cipher_update(&cipher->encrypt_ctx, in, len, out, &outlen); + if (rc != 0) { +- SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_update failed during encryption"); ++ SSH_LOG(SSH_LOG_TRACE, "mbedtls_cipher_update failed during encryption"); + return; + } + +@@ -674,12 +674,12 @@ static void cipher_encrypt(struct ssh_cipher_struct *cipher, + total_len += outlen; + + if (rc != 0) { +- SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_finish failed during encryption"); ++ SSH_LOG(SSH_LOG_TRACE, "mbedtls_cipher_finish failed during encryption"); + return; + } + + if (total_len != len) { +- SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_update: output size %zu for %zu", ++ SSH_LOG(SSH_LOG_DEBUG, "mbedtls_cipher_update: output size %zu for %zu", + outlen, len); + return; + } +@@ -693,12 +693,12 @@ static void cipher_encrypt_cbc(struct ssh_cipher_struct *cipher, void *in, void + int rc = 0; + rc = mbedtls_cipher_update(&cipher->encrypt_ctx, in, len, out, &outlen); + if (rc != 0) { +- SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_update failed during encryption"); ++ SSH_LOG(SSH_LOG_TRACE, "mbedtls_cipher_update failed during encryption"); + return; + } + + if (outlen != len) { +- SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_update: output size %zu for %zu", ++ SSH_LOG(SSH_LOG_DEBUG "mbedtls_cipher_update: output size %zu for %zu", + outlen, len); + return; + } +@@ -716,7 +716,7 @@ static void cipher_decrypt(struct ssh_cipher_struct *cipher, + + rc = mbedtls_cipher_update(&cipher->decrypt_ctx, in, len, out, &outlen); + if (rc != 0) { +- SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_update failed during decryption"); ++ SSH_LOG(SSH_LOG_TRACE, "mbedtls_cipher_update failed during decryption"); + return; + } + +@@ -730,14 +730,14 @@ static void cipher_decrypt(struct ssh_cipher_struct *cipher, + outlen, &outlen); + + if (rc != 0) { +- SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_reset failed during decryption"); ++ SSH_LOG(SSH_LOG_TRACE, "mbedtls_cipher_reset failed during decryption"); + return; + } + + total_len += outlen; + + if (total_len != len) { +- SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_update: output size %zu for %zu", ++ SSH_LOG(SSH_LOG_DEBUG, "mbedtls_cipher_update: output size %zu for %zu", + outlen, len); + return; + } +@@ -751,7 +751,7 @@ static void cipher_decrypt_cbc(struct ssh_cipher_struct *cipher, void *in, void + int rc = 0; + rc = mbedtls_cipher_update(&cipher->decrypt_ctx, in, len, out, &outlen); + if (rc != 0) { +- SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_update failed during decryption"); ++ SSH_LOG(SSH_LOG_TRACE, "mbedtls_cipher_update failed during decryption"); + return; + } + +@@ -770,19 +770,19 @@ static void cipher_decrypt_cbc(struct ssh_cipher_struct *cipher, void *in, void + } + + if (rc != 0) { +- SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_finish failed during decryption"); ++ SSH_LOG(SSH_LOG_TRACE, "mbedtls_cipher_finish failed during decryption"); + return; + } + + rc = mbedtls_cipher_reset(&cipher->decrypt_ctx); + + if (rc != 0) { +- SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_reset failed during decryption"); ++ SSH_LOG(SSH_LOG_TRACE, "mbedtls_cipher_reset failed during decryption"); + return; + } + + if (outlen != len) { +- SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_update: output size %zu for %zu", ++ SSH_LOG(SSH_LOG_DEBUG, "mbedtls_cipher_update: output size %zu for %zu", + outlen, len); + return; + } +@@ -836,7 +836,7 @@ cipher_encrypt_gcm(struct ssh_cipher_struct *cipher, + authlen, + tag); /* tag */ + if (rc != 0) { +- SSH_LOG(SSH_LOG_WARNING, "mbedtls_gcm_crypt_and_tag failed"); ++ SSH_LOG(SSH_LOG_TRACE, "mbedtls_gcm_crypt_and_tag failed"); + return; + } + +@@ -870,7 +870,7 @@ cipher_decrypt_gcm(struct ssh_cipher_struct *cipher, + (const uint8_t *)complete_packet + aadlen, /* input */ + (unsigned char *)out); /* output */ + if (rc != 0) { +- SSH_LOG(SSH_LOG_WARNING, "mbedtls_gcm_auth_decrypt failed"); ++ SSH_LOG(SSH_LOG_TRACE, "mbedtls_gcm_auth_decrypt failed"); + return SSH_ERROR; + } + +diff --git a/src/messages.c b/src/messages.c +index a772d488..2f4f99f8 100644 +--- a/src/messages.c ++++ b/src/messages.c +@@ -160,7 +160,7 @@ static int ssh_execute_server_request(ssh_session session, ssh_message msg) + if (channel != NULL) { + rc = ssh_message_channel_request_open_reply_accept_channel(msg, channel); + if (rc != SSH_OK) { +- SSH_LOG(SSH_LOG_WARNING, ++ SSH_LOG(SSH_LOG_TRACE, + "Failed to send reply for accepting a channel " + "open"); + } +@@ -237,7 +237,7 @@ static int ssh_execute_server_request(ssh_session session, ssh_message msg) + msg->channel_request.pxwidth, + msg->channel_request.pxheight); + if (rc != SSH_OK) { +- SSH_LOG(SSH_LOG_WARNING, ++ SSH_LOG(SSH_LOG_TRACE, + "Failed to iterate callbacks for window change"); + } + return SSH_OK; +@@ -494,8 +494,11 @@ ssh_message ssh_message_pop_head(ssh_session session){ + static int ssh_message_termination(void *s){ + ssh_session session = s; + struct ssh_iterator *it; +- if(session->session_state == SSH_SESSION_STATE_ERROR) ++ if (session->session_state == SSH_SESSION_STATE_ERROR) { ++ // TODO not sure of this ++ SSH_LOG(SSH_LOG_WARN, "Error: %s", ssh_get_error(session)); + return 1; ++ } + it = ssh_list_get_iterator(session->ssh_message_list); + if(!it) + return 0; +@@ -774,7 +777,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_request){ + + cmp = strcmp(service, "ssh-connection"); + if (cmp != 0) { +- SSH_LOG(SSH_LOG_WARNING, ++ SSH_LOG(SSH_LOG_TRACE, + "Invalid service request: %s", + service); + goto end; +@@ -1046,7 +1049,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_info_response){ + } + + if (session->kbdint == NULL) { +- SSH_LOG(SSH_LOG_PROTOCOL, "Warning: Got a keyboard-interactive " ++ SSH_LOG(SSH_LOG_DEBUG, "Warning: Got a keyboard-interactive " + "response but it seems we didn't send the request."); + + session->kbdint = ssh_kbdint_new(); +@@ -1080,7 +1083,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_info_response){ + + if(nanswers != session->kbdint->nprompts) { + /* warn but let the application handle this case */ +- SSH_LOG(SSH_LOG_PROTOCOL, "Warning: Number of prompts and answers" ++ SSH_LOG(SSH_LOG_DEBUG, "Warning: Number of prompts and answers" + " mismatch: p=%u a=%u", session->kbdint->nprompts, nanswers); + } + session->kbdint->nanswers = nanswers; +@@ -1487,7 +1490,7 @@ SSH_PACKET_CALLBACK(ssh_packet_global_request){ + (void)type; + (void)packet; + +- SSH_LOG(SSH_LOG_PROTOCOL,"Received SSH_MSG_GLOBAL_REQUEST packet"); ++ SSH_LOG(SSH_LOG_DEBUG,"Received SSH_MSG_GLOBAL_REQUEST packet"); + r = ssh_buffer_unpack(packet, "sb", + &request, + &want_reply); +@@ -1519,12 +1522,12 @@ SSH_PACKET_CALLBACK(ssh_packet_global_request){ + msg->global_request.type = SSH_GLOBAL_REQUEST_TCPIP_FORWARD; + msg->global_request.want_reply = want_reply; + +- SSH_LOG(SSH_LOG_PROTOCOL, "Received SSH_MSG_GLOBAL_REQUEST %s %d %s:%d", request, want_reply, ++ SSH_LOG(SSH_LOG_DEBUG, "Received SSH_MSG_GLOBAL_REQUEST %s %d %s:%d", request, want_reply, + msg->global_request.bind_address, + msg->global_request.bind_port); + + if(ssh_callbacks_exists(session->common.callbacks, global_request_function)) { +- SSH_LOG(SSH_LOG_PROTOCOL, "Calling callback for SSH_MSG_GLOBAL_REQUEST %s %d %s:%d", request, ++ SSH_LOG(SSH_LOG_DEBUG, "Calling callback for SSH_MSG_GLOBAL_REQUEST %s %d %s:%d", request, + want_reply, msg->global_request.bind_address, + msg->global_request.bind_port); + session->common.callbacks->global_request_function(session, msg, session->common.callbacks->userdata); +@@ -1549,7 +1552,7 @@ SSH_PACKET_CALLBACK(ssh_packet_global_request){ + msg->global_request.type = SSH_GLOBAL_REQUEST_CANCEL_TCPIP_FORWARD; + msg->global_request.want_reply = want_reply; + +- SSH_LOG(SSH_LOG_PROTOCOL, "Received SSH_MSG_GLOBAL_REQUEST %s %d %s:%d", request, want_reply, ++ SSH_LOG(SSH_LOG_DEBUG, "Received SSH_MSG_GLOBAL_REQUEST %s %d %s:%d", request, want_reply, + msg->global_request.bind_address, + msg->global_request.bind_port); + +@@ -1563,14 +1566,14 @@ SSH_PACKET_CALLBACK(ssh_packet_global_request){ + } else if(strcmp(request, "keepalive@openssh.com") == 0) { + msg->global_request.type = SSH_GLOBAL_REQUEST_KEEPALIVE; + msg->global_request.want_reply = want_reply; +- SSH_LOG(SSH_LOG_PROTOCOL, "Received keepalive@openssh.com %d", want_reply); ++ SSH_LOG(SSH_LOG_DEBUG, "Received keepalive@openssh.com %d", want_reply); + if(ssh_callbacks_exists(session->common.callbacks, global_request_function)) { + session->common.callbacks->global_request_function(session, msg, session->common.callbacks->userdata); + } else { + ssh_message_global_request_reply_success(msg, 0); + } + } else { +- SSH_LOG(SSH_LOG_PROTOCOL, "UNKNOWN SSH_MSG_GLOBAL_REQUEST %s, " ++ SSH_LOG(SSH_LOG_DEBUG, "UNKNOWN SSH_MSG_GLOBAL_REQUEST %s, " + "want_reply = %d", request, want_reply); + goto reply_with_failure; + } +@@ -1603,7 +1606,7 @@ reply_with_failure: + error: + SAFE_FREE(msg); + SAFE_FREE(request); +- SSH_LOG(SSH_LOG_WARNING, "Invalid SSH_MSG_GLOBAL_REQUEST packet"); ++ SSH_LOG(SSH_LOG_TRACE, "Invalid SSH_MSG_GLOBAL_REQUEST packet"); + return rc; + } + +diff --git a/src/misc.c b/src/misc.c +index 0f1a7d49..0429ffac 100644 +--- a/src/misc.c ++++ b/src/misc.c +@@ -622,7 +622,7 @@ void ssh_log_hexdump(const char *descr, const unsigned char *what, size_t len) + return; + + error: +- SSH_LOG(SSH_LOG_WARN, "Could not print to buffer"); ++ SSH_LOG(SSH_LOG_DEBUG, "Could not print to buffer"); + return; + } + +@@ -1249,7 +1249,7 @@ int ssh_analyze_banner(ssh_session session, int server) + return -1; + } + +- SSH_LOG(SSH_LOG_PROTOCOL, "Analyzing banner: %s", banner); ++ SSH_LOG(SSH_LOG_DEBUG, "Analyzing banner: %s", banner); + + switch (banner[4]) { + case '2': +@@ -1299,7 +1299,7 @@ int ssh_analyze_banner(ssh_session session, int server) + + session->openssh = SSH_VERSION_INT(((int) major), ((int) minor), 0); + +- SSH_LOG(SSH_LOG_PROTOCOL, ++ SSH_LOG(SSH_LOG_DEBUG, + "We are talking to an OpenSSH client version: %lu.%lu (%x)", + major, minor, session->openssh); + } +@@ -1393,7 +1393,7 @@ int ssh_timeout_elapsed(struct ssh_timestamp *ts, int timeout) { + * -2 means user-defined timeout as available in + * session->timeout, session->timeout_usec. + */ +- SSH_LOG(SSH_LOG_WARN, "ssh_timeout_elapsed called with -2. this needs to " ++ SSH_LOG(SSH_LOG_DEBUG, "ssh_timeout_elapsed called with -2. this needs to " + "be fixed. please set a breakpoint on misc.c:%d and " + "fix the caller\n", __LINE__); + return 0; +@@ -1546,20 +1546,20 @@ int ssh_quote_file_name(const char *file_name, char *buf, size_t buf_len) + enum ssh_quote_state_e state = NO_QUOTE; + + if (file_name == NULL || buf == NULL || buf_len == 0) { +- SSH_LOG(SSH_LOG_WARNING, "Invalid parameter"); ++ SSH_LOG(SSH_LOG_TRACE, "Invalid parameter"); + return SSH_ERROR; + } + + /* Only allow file names smaller than 32kb. */ + if (strlen(file_name) > 32 * 1024) { +- SSH_LOG(SSH_LOG_WARNING, "File name too long"); ++ SSH_LOG(SSH_LOG_TRACE, "File name too long"); + return SSH_ERROR; + } + + /* Paranoia check */ + required_buf_len = (size_t)3 * strlen(file_name) + 1; + if (required_buf_len > buf_len) { +- SSH_LOG(SSH_LOG_WARNING, "Buffer too small"); ++ SSH_LOG(SSH_LOG_TRACE, "Buffer too small"); + return SSH_ERROR; + } + +@@ -1717,7 +1717,7 @@ int ssh_newline_vis(const char *string, char *buf, size_t buf_len) + } + + if ((2 * strlen(string) + 1) > buf_len) { +- SSH_LOG(SSH_LOG_WARNING, "Buffer too small"); ++ SSH_LOG(SSH_LOG_TRACE, "Buffer too small"); + return SSH_ERROR; + } + +diff --git a/src/packet.c b/src/packet.c +index ec4a7203..c9555ba0 100644 +--- a/src/packet.c ++++ b/src/packet.c +@@ -1543,7 +1543,7 @@ SSH_PACKET_CALLBACK(ssh_packet_unimplemented){ + + rc = ssh_buffer_unpack(packet, "d", &seq); + if (rc != SSH_OK) { +- SSH_LOG(SSH_LOG_WARNING, ++ SSH_LOG(SSH_LOG_TRACE, + "Could not unpack SSH_MSG_UNIMPLEMENTED packet"); + } + +@@ -1864,7 +1864,7 @@ ssh_init_rekey_state(struct ssh_session_struct *session, + session->opts.rekey_data / cipher->blocksize); + } + +- SSH_LOG(SSH_LOG_PROTOCOL, ++ SSH_LOG(SSH_LOG_DEBUG, + "Set rekey after %" PRIu64 " blocks", + cipher->max_blocks); + } +@@ -1891,7 +1891,7 @@ ssh_packet_set_newkeys(ssh_session session, + session->next_crypto->used |= direction; + if (session->current_crypto != NULL) { + if (session->current_crypto->used & direction) { +- SSH_LOG(SSH_LOG_WARNING, "This direction isn't used anymore."); ++ SSH_LOG(SSH_LOG_TRACE, "This direction isn't used anymore."); + } + /* Mark the current requested direction unused */ + session->current_crypto->used &= ~direction; +@@ -1966,7 +1966,7 @@ ssh_packet_set_newkeys(ssh_session session, + session->next_crypto->in_cipher); + if (session->opts.rekey_time != 0) { + ssh_timestamp_init(&session->last_rekey_time); +- SSH_LOG(SSH_LOG_PROTOCOL, "Set rekey after %" PRIu32 " seconds", ++ SSH_LOG(SSH_LOG_DEBUG, "Set rekey after %" PRIu32 " seconds", + session->opts.rekey_time/1000); + } + +diff --git a/src/packet_cb.c b/src/packet_cb.c +index 39575b17..98d21b12 100644 +--- a/src/packet_cb.c ++++ b/src/packet_cb.c +@@ -87,7 +87,7 @@ SSH_PACKET_CALLBACK(ssh_packet_ignore_callback){ + (void)user; + (void)type; + (void)packet; +- SSH_LOG(SSH_LOG_PROTOCOL,"Received %s packet",type==SSH2_MSG_IGNORE ? "SSH_MSG_IGNORE" : "SSH_MSG_DEBUG"); ++ SSH_LOG(SSH_LOG_DEBUG,"Received %s packet",type==SSH2_MSG_IGNORE ? "SSH_MSG_IGNORE" : "SSH_MSG_DEBUG"); + /* TODO: handle a graceful disconnect */ + return SSH_PACKET_USED; + } +@@ -99,7 +99,7 @@ SSH_PACKET_CALLBACK(ssh_packet_newkeys){ + (void)packet; + (void)user; + (void)type; +- SSH_LOG(SSH_LOG_PROTOCOL, "Received SSH_MSG_NEWKEYS"); ++ SSH_LOG(SSH_LOG_DEBUG, "Received SSH_MSG_NEWKEYS"); + + if (session->session_state != SSH_SESSION_STATE_DH || + session->dh_handshake_state != DH_STATE_NEWKEYS_SENT) { +@@ -158,7 +158,7 @@ SSH_PACKET_CALLBACK(ssh_packet_newkeys){ + if (rc == SSH_ERROR) { + goto error; + } +- SSH_LOG(SSH_LOG_PROTOCOL,"Signature verified and valid"); ++ SSH_LOG(SSH_LOG_DEBUG,"Signature verified and valid"); + + /* When receiving this packet, we switch on the incomming crypto. */ + rc = ssh_packet_set_newkeys(session, SSH_DIRECTION_IN); +diff --git a/src/pki.c b/src/pki.c +index 932abf2c..db808355 100644 +--- a/src/pki.c ++++ b/src/pki.c +@@ -330,7 +330,7 @@ enum ssh_digest_e ssh_key_hash_from_name(const char *name) + return SSH_DIGEST_AUTO; + } + +- SSH_LOG(SSH_LOG_WARN, "Unknown signature name %s", name); ++ SSH_LOG(SSH_LOG_TRACE, "Unknown signature name %s", name); + + /* TODO we should rather fail */ + return SSH_DIGEST_AUTO; +@@ -362,13 +362,13 @@ int ssh_key_algorithm_allowed(ssh_session session, const char *type) + else if (session->server) { + allowed_list = session->opts.wanted_methods[SSH_HOSTKEYS]; + if (allowed_list == NULL) { +- SSH_LOG(SSH_LOG_WARN, "Session invalid: no host key available"); ++ SSH_LOG(SSH_LOG_TRACE, "Session invalid: no host key available"); + return 0; + } + } + #endif + else { +- SSH_LOG(SSH_LOG_WARN, "Session invalid: not set as client nor server"); ++ SSH_LOG(SSH_LOG_TRACE, "Session invalid: not set as client nor server"); + return 0; + } + +@@ -438,7 +438,7 @@ enum ssh_digest_e ssh_key_type_to_hash(ssh_session session, + case SSH_KEYTYPE_ECDSA: + case SSH_KEYTYPE_UNKNOWN: + default: +- SSH_LOG(SSH_LOG_WARN, "Digest algorithm to be used with key type %u " ++ SSH_LOG(SSH_LOG_TRACE, "Digest algorithm to be used with key type %u " + "is not defined", type); + } + +@@ -625,7 +625,7 @@ int ssh_key_cmp(const ssh_key k1, + } + + if (k1->type != k2->type) { +- SSH_LOG(SSH_LOG_WARN, "key types don't match!"); ++ SSH_LOG(SSH_LOG_DEBUG, "key types don't match!"); + return 1; + } + +@@ -744,7 +744,7 @@ int ssh_pki_import_privkey_base64(const char *b64_key, + return SSH_ERROR; + } + +- SSH_LOG(SSH_LOG_INFO, ++ SSH_LOG(SSH_LOG_DEBUG, + "Trying to decode privkey passphrase=%s", + passphrase ? "true" : "false"); + +@@ -864,7 +864,7 @@ int ssh_pki_import_privkey_file(const char *filename, + + file = fopen(filename, "rb"); + if (file == NULL) { +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_TRACE, + "Error opening %s: %s", + filename, + strerror(errno)); +@@ -874,7 +874,7 @@ int ssh_pki_import_privkey_file(const char *filename, + rc = fstat(fileno(file), &sb); + if (rc < 0) { + fclose(file); +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_TRACE, + "Error getting stat of %s: %s", + filename, + strerror(errno)); +@@ -888,7 +888,7 @@ int ssh_pki_import_privkey_file(const char *filename, + } + + if (sb.st_size > MAX_PRIVKEY_SIZE) { +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_TRACE, + "Private key is bigger than 4M."); + fclose(file); + return SSH_ERROR; +@@ -897,7 +897,7 @@ int ssh_pki_import_privkey_file(const char *filename, + key_buf = malloc(sb.st_size + 1); + if (key_buf == NULL) { + fclose(file); +- SSH_LOG(SSH_LOG_WARN, "Out of memory!"); ++ SSH_LOG(SSH_LOG_TRACE, "Out of memory!"); + return SSH_ERROR; + } + +@@ -906,7 +906,7 @@ int ssh_pki_import_privkey_file(const char *filename, + + if (size != sb.st_size) { + SAFE_FREE(key_buf); +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_TRACE, + "Error reading %s: %s", + filename, + strerror(errno)); +@@ -1068,7 +1068,7 @@ int pki_import_privkey_buffer(enum ssh_keytypes_e type, + rc = ssh_buffer_unpack(buffer, "SSSSS", &p, &q, &g, + &pubkey, &privkey); + if (rc != SSH_OK) { +- SSH_LOG(SSH_LOG_WARN, "Unpack error"); ++ SSH_LOG(SSH_LOG_TRACE, "Unpack error"); + goto fail; + } + +@@ -1109,7 +1109,7 @@ int pki_import_privkey_buffer(enum ssh_keytypes_e type, + rc = ssh_buffer_unpack(buffer, "SSSSSS", &n, &e, &d, + &iqmp, &p, &q); + if (rc != SSH_OK) { +- SSH_LOG(SSH_LOG_WARN, "Unpack error"); ++ SSH_LOG(SSH_LOG_TRACE, "Unpack error"); + goto fail; + } + +@@ -1136,7 +1136,7 @@ int pki_import_privkey_buffer(enum ssh_keytypes_e type, + ssh_string_burn(q); + SSH_STRING_FREE(q); + if (rc == SSH_ERROR) { +- SSH_LOG(SSH_LOG_WARN, "Failed to build RSA private key"); ++ SSH_LOG(SSH_LOG_TRACE, "Failed to build RSA private key"); + goto fail; + } + } +@@ -1153,7 +1153,7 @@ int pki_import_privkey_buffer(enum ssh_keytypes_e type, + + rc = ssh_buffer_unpack(buffer, "SSS", &i, &e, &exp); + if (rc != SSH_OK) { +- SSH_LOG(SSH_LOG_WARN, "Unpack error"); ++ SSH_LOG(SSH_LOG_TRACE, "Unpack error"); + goto fail; + } + +@@ -1173,7 +1173,7 @@ int pki_import_privkey_buffer(enum ssh_keytypes_e type, + ssh_string_burn(exp); + SSH_STRING_FREE(exp); + if (rc < 0) { +- SSH_LOG(SSH_LOG_WARN, "Failed to build ECDSA private key"); ++ SSH_LOG(SSH_LOG_TRACE, "Failed to build ECDSA private key"); + goto fail; + } + } +@@ -1185,7 +1185,7 @@ int pki_import_privkey_buffer(enum ssh_keytypes_e type, + + rc = ssh_buffer_unpack(buffer, "SS", &pubkey, &privkey); + if (rc != SSH_OK){ +- SSH_LOG(SSH_LOG_WARN, "Unpack error"); ++ SSH_LOG(SSH_LOG_TRACE, "Unpack error"); + goto fail; + } + +@@ -1194,7 +1194,7 @@ int pki_import_privkey_buffer(enum ssh_keytypes_e type, + SSH_STRING_FREE(privkey); + SSH_STRING_FREE(pubkey); + if (rc != SSH_OK) { +- SSH_LOG(SSH_LOG_WARN, "Failed to build ed25519 key"); ++ SSH_LOG(SSH_LOG_TRACE, "Failed to build ed25519 key"); + goto fail; + } + } +@@ -1208,7 +1208,7 @@ int pki_import_privkey_buffer(enum ssh_keytypes_e type, + case SSH_KEYTYPE_RSA1: + case SSH_KEYTYPE_UNKNOWN: + default: +- SSH_LOG(SSH_LOG_WARN, "Unknown private key type (%d)", type); ++ SSH_LOG(SSH_LOG_TRACE, "Unknown private key type (%d)", type); + goto fail; + } + +@@ -1245,7 +1245,7 @@ static int pki_import_pubkey_buffer(ssh_buffer buffer, + + rc = ssh_buffer_unpack(buffer, "SSSS", &p, &q, &g, &pubkey); + if (rc != SSH_OK) { +- SSH_LOG(SSH_LOG_WARN, "Unpack error"); ++ SSH_LOG(SSH_LOG_TRACE, "Unpack error"); + goto fail; + } + +@@ -1264,7 +1264,7 @@ static int pki_import_pubkey_buffer(ssh_buffer buffer, + ssh_string_burn(pubkey); + SSH_STRING_FREE(pubkey); + if (rc == SSH_ERROR) { +- SSH_LOG(SSH_LOG_WARN, "Failed to build DSA public key"); ++ SSH_LOG(SSH_LOG_TRACE, "Failed to build DSA public key"); + goto fail; + } + } +@@ -1276,7 +1276,7 @@ static int pki_import_pubkey_buffer(ssh_buffer buffer, + + rc = ssh_buffer_unpack(buffer, "SS", &e, &n); + if (rc != SSH_OK) { +- SSH_LOG(SSH_LOG_WARN, "Unpack error"); ++ SSH_LOG(SSH_LOG_TRACE, "Unpack error"); + goto fail; + } + +@@ -1290,7 +1290,7 @@ static int pki_import_pubkey_buffer(ssh_buffer buffer, + ssh_string_burn(n); + SSH_STRING_FREE(n); + if (rc == SSH_ERROR) { +- SSH_LOG(SSH_LOG_WARN, "Failed to build RSA public key"); ++ SSH_LOG(SSH_LOG_TRACE, "Failed to build RSA public key"); + goto fail; + } + } +@@ -1307,7 +1307,7 @@ static int pki_import_pubkey_buffer(ssh_buffer buffer, + + rc = ssh_buffer_unpack(buffer, "SS", &i, &e); + if (rc != SSH_OK) { +- SSH_LOG(SSH_LOG_WARN, "Unpack error"); ++ SSH_LOG(SSH_LOG_TRACE, "Unpack error"); + goto fail; + } + +@@ -1321,7 +1321,7 @@ static int pki_import_pubkey_buffer(ssh_buffer buffer, + ssh_string_burn(e); + SSH_STRING_FREE(e); + if (rc < 0) { +- SSH_LOG(SSH_LOG_WARN, "Failed to build ECDSA public key"); ++ SSH_LOG(SSH_LOG_TRACE, "Failed to build ECDSA public key"); + goto fail; + } + +@@ -1336,7 +1336,7 @@ static int pki_import_pubkey_buffer(ssh_buffer buffer, + { + ssh_string pubkey = ssh_buffer_get_ssh_string(buffer); + if (ssh_string_len(pubkey) != ED25519_KEY_LEN) { +- SSH_LOG(SSH_LOG_WARN, "Invalid public key length"); ++ SSH_LOG(SSH_LOG_TRACE, "Invalid public key length"); + ssh_string_burn(pubkey); + SSH_STRING_FREE(pubkey); + goto fail; +@@ -1363,7 +1363,7 @@ static int pki_import_pubkey_buffer(ssh_buffer buffer, + case SSH_KEYTYPE_RSA1: + case SSH_KEYTYPE_UNKNOWN: + default: +- SSH_LOG(SSH_LOG_WARN, "Unknown public key protocol %d", type); ++ SSH_LOG(SSH_LOG_TRACE, "Unknown public key protocol %d", type); + goto fail; + } + +@@ -1532,26 +1532,26 @@ int ssh_pki_import_pubkey_blob(const ssh_string key_blob, + + buffer = ssh_buffer_new(); + if (buffer == NULL) { +- SSH_LOG(SSH_LOG_WARN, "Out of memory!"); ++ SSH_LOG(SSH_LOG_TRACE, "Out of memory!"); + return SSH_ERROR; + } + + rc = ssh_buffer_add_data(buffer, ssh_string_data(key_blob), + ssh_string_len(key_blob)); + if (rc < 0) { +- SSH_LOG(SSH_LOG_WARN, "Out of memory!"); ++ SSH_LOG(SSH_LOG_TRACE, "Out of memory!"); + goto fail; + } + + type_s = ssh_buffer_get_ssh_string(buffer); + if (type_s == NULL) { +- SSH_LOG(SSH_LOG_WARN, "Out of memory!"); ++ SSH_LOG(SSH_LOG_TRACE, "Out of memory!"); + goto fail; + } + + type = ssh_key_type_from_name(ssh_string_get_char(type_s)); + if (type == SSH_KEYTYPE_UNKNOWN) { +- SSH_LOG(SSH_LOG_WARN, "Unknown key type found!"); ++ SSH_LOG(SSH_LOG_TRACE, "Unknown key type found!"); + goto fail; + } + SSH_STRING_FREE(type_s); +@@ -1602,7 +1602,7 @@ int ssh_pki_import_pubkey_file(const char *filename, ssh_key *pkey) + + file = fopen(filename, "rb"); + if (file == NULL) { +- SSH_LOG(SSH_LOG_WARN, "Error opening %s: %s", ++ SSH_LOG(SSH_LOG_TRACE, "Error opening %s: %s", + filename, strerror(errno)); + return SSH_EOF; + } +@@ -1610,7 +1610,7 @@ int ssh_pki_import_pubkey_file(const char *filename, ssh_key *pkey) + rc = fstat(fileno(file), &sb); + if (rc < 0) { + fclose(file); +- SSH_LOG(SSH_LOG_WARN, "Error gettint stat of %s: %s", ++ SSH_LOG(SSH_LOG_TRACE, "Error gettint stat of %s: %s", + filename, strerror(errno)); + switch (errno) { + case ENOENT: +@@ -1628,7 +1628,7 @@ int ssh_pki_import_pubkey_file(const char *filename, ssh_key *pkey) + key_buf = malloc(sb.st_size + 1); + if (key_buf == NULL) { + fclose(file); +- SSH_LOG(SSH_LOG_WARN, "Out of memory!"); ++ SSH_LOG(SSH_LOG_TRACE, "Out of memory!"); + return SSH_ERROR; + } + +@@ -1637,7 +1637,7 @@ int ssh_pki_import_pubkey_file(const char *filename, ssh_key *pkey) + + if (size != sb.st_size) { + SAFE_FREE(key_buf); +- SSH_LOG(SSH_LOG_WARN, "Error reading %s: %s", ++ SSH_LOG(SSH_LOG_TRACE, "Error reading %s: %s", + filename, strerror(errno)); + return SSH_ERROR; + } +@@ -1650,7 +1650,7 @@ int ssh_pki_import_pubkey_file(const char *filename, ssh_key *pkey) + *pkey = ssh_pki_openssh_pubkey_import(key_buf); + SAFE_FREE(key_buf); + if (*pkey == NULL) { +- SSH_LOG(SSH_LOG_WARN, "Failed to import public key from OpenSSH" ++ SSH_LOG(SSH_LOG_TRACE, "Failed to import public key from OpenSSH" + " private key file"); + return SSH_ERROR; + } +@@ -2183,7 +2183,7 @@ int pki_key_check_hash_compatible(ssh_key key, + case SSH_KEYTYPE_DSS: + if (hash_type == SSH_DIGEST_SHA1) { + if (ssh_fips_mode()) { +- SSH_LOG(SSH_LOG_WARN, "SHA1 is not allowed in FIPS mode"); ++ SSH_LOG(SSH_LOG_TRACE, "SHA1 is not allowed in FIPS mode"); + return SSH_ERROR; + } else { + return SSH_OK; +@@ -2194,7 +2194,7 @@ int pki_key_check_hash_compatible(ssh_key key, + case SSH_KEYTYPE_RSA: + if (hash_type == SSH_DIGEST_SHA1) { + if (ssh_fips_mode()) { +- SSH_LOG(SSH_LOG_WARN, "SHA1 is not allowed in FIPS mode"); ++ SSH_LOG(SSH_LOG_TRACE, "SHA1 is not allowed in FIPS mode"); + return SSH_ERROR; + } else { + return SSH_OK; +@@ -2234,11 +2234,11 @@ int pki_key_check_hash_compatible(ssh_key key, + case SSH_KEYTYPE_RSA1: + case SSH_KEYTYPE_ECDSA: + case SSH_KEYTYPE_UNKNOWN: +- SSH_LOG(SSH_LOG_WARN, "Unknown key type %d", key->type); ++ SSH_LOG(SSH_LOG_TRACE, "Unknown key type %d", key->type); + return SSH_ERROR; + } + +- SSH_LOG(SSH_LOG_WARN, "Key type %d incompatible with hash type %d", ++ SSH_LOG(SSH_LOG_TRACE, "Key type %d incompatible with hash type %d", + key->type, hash_type); + + return SSH_ERROR; +@@ -2265,7 +2265,7 @@ int ssh_pki_signature_verify(ssh_session session, + sig->type_c); + + if (key_type != sig->type) { +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_TRACE, + "Can not verify %s signature with %s key", + sig->type_c, key->type_c); + return SSH_ERROR; +diff --git a/src/pki_container_openssh.c b/src/pki_container_openssh.c +index ecde4cdd..dadeefaa 100644 +--- a/src/pki_container_openssh.c ++++ b/src/pki_container_openssh.c +@@ -69,20 +69,20 @@ static int pki_openssh_import_privkey_blob(ssh_buffer key_blob_buffer, + + rc = ssh_buffer_unpack(key_blob_buffer, "s", &type_s); + if (rc == SSH_ERROR){ +- SSH_LOG(SSH_LOG_WARN, "Unpack error"); ++ SSH_LOG(SSH_LOG_TRACE, "Unpack error"); + return SSH_ERROR; + } + + type = ssh_key_type_from_name(type_s); + if (type == SSH_KEYTYPE_UNKNOWN) { +- SSH_LOG(SSH_LOG_WARN, "Unknown key type '%s' found!", type_s); ++ SSH_LOG(SSH_LOG_TRACE, "Unknown key type '%s' found!", type_s); + return SSH_ERROR; + } + SAFE_FREE(type_s); + + rc = pki_import_privkey_buffer(type, key_blob_buffer, &key); + if (rc != SSH_OK) { +- SSH_LOG(SSH_LOG_WARN, "Failed to read key in OpenSSH format"); ++ SSH_LOG(SSH_LOG_TRACE, "Failed to read key in OpenSSH format"); + goto fail; + } + +@@ -133,17 +133,17 @@ static int pki_private_key_decrypt(ssh_string blob, + } + + if (ciphers[i].name == NULL){ +- SSH_LOG(SSH_LOG_WARN, "Unsupported cipher %s", ciphername); ++ SSH_LOG(SSH_LOG_TRACE, "Unsupported cipher %s", ciphername); + return SSH_ERROR; + } + + cmp = strcmp(kdfname, "bcrypt"); + if (cmp != 0) { +- SSH_LOG(SSH_LOG_WARN, "Unsupported KDF %s", kdfname); ++ SSH_LOG(SSH_LOG_TRACE, "Unsupported KDF %s", kdfname); + return SSH_ERROR; + } + if (ssh_string_len(blob) % cipher.blocksize != 0) { +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_TRACE, + "Encrypted string not multiple of blocksize: %zu", + ssh_string_len(blob)); + return SSH_ERROR; +@@ -167,7 +167,7 @@ static int pki_private_key_decrypt(ssh_string blob, + /* We need material for key (keysize bits / 8) and IV (blocksize) */ + key_material_len = cipher.keysize/8 + cipher.blocksize; + if (key_material_len > sizeof(key_material)) { +- SSH_LOG(SSH_LOG_WARN, "Key material too big"); ++ SSH_LOG(SSH_LOG_TRACE, "Key material too big"); + return SSH_ERROR; + } + +@@ -181,7 +181,7 @@ static int pki_private_key_decrypt(ssh_string blob, + if (passphrase == NULL) { + if (auth_fn == NULL) { + SAFE_FREE(salt); +- SSH_LOG(SSH_LOG_WARN, "No passphrase provided"); ++ SSH_LOG(SSH_LOG_TRACE, "No passphrase provided"); + return SSH_ERROR; + } + rc = auth_fn("Passphrase", +@@ -251,7 +251,7 @@ ssh_pki_openssh_import(const char *text_key, + + cmp = strncmp(ptr, OPENSSH_HEADER_BEGIN, strlen(OPENSSH_HEADER_BEGIN)); + if (cmp != 0) { +- SSH_LOG(SSH_LOG_WARN, "Not an OpenSSH private key (no header)"); ++ SSH_LOG(SSH_LOG_TRACE, "Not an OpenSSH private key (no header)"); + goto out; + } + ptr += strlen(OPENSSH_HEADER_BEGIN); +@@ -260,7 +260,7 @@ ssh_pki_openssh_import(const char *text_key, + } + end = strstr(ptr, OPENSSH_HEADER_END); + if (end == NULL) { +- SSH_LOG(SSH_LOG_WARN, "Not an OpenSSH private key (no footer)"); ++ SSH_LOG(SSH_LOG_TRACE, "Not an OpenSSH private key (no footer)"); + goto out; + } + base64 = malloc(end - ptr + 1); +@@ -277,7 +277,7 @@ ssh_pki_openssh_import(const char *text_key, + buffer = base64_to_bin(base64); + SAFE_FREE(base64); + if (buffer == NULL) { +- SSH_LOG(SSH_LOG_WARN, "Not an OpenSSH private key (base64 error)"); ++ SSH_LOG(SSH_LOG_TRACE, "Not an OpenSSH private key (base64 error)"); + goto out; + } + rc = ssh_buffer_unpack(buffer, "PssSdSS", +@@ -290,21 +290,21 @@ ssh_pki_openssh_import(const char *text_key, + &pubkey0, + &privkeys); + if (rc == SSH_ERROR) { +- SSH_LOG(SSH_LOG_WARN, "Not an OpenSSH private key (unpack error)"); ++ SSH_LOG(SSH_LOG_TRACE, "Not an OpenSSH private key (unpack error)"); + goto out; + } + cmp = strncmp(magic, OPENSSH_AUTH_MAGIC, strlen(OPENSSH_AUTH_MAGIC)); + if (cmp != 0) { +- SSH_LOG(SSH_LOG_WARN, "Not an OpenSSH private key (bad magic)"); ++ SSH_LOG(SSH_LOG_TRACE, "Not an OpenSSH private key (bad magic)"); + goto out; + } +- SSH_LOG(SSH_LOG_INFO, ++ SSH_LOG(SSH_LOG_DEBUG, + "Opening OpenSSH private key: ciphername: %s, kdf: %s, nkeys: %d", + ciphername, + kdfname, + nkeys); + if (nkeys != 1) { +- SSH_LOG(SSH_LOG_WARN, "Opening OpenSSH private key: only 1 key supported (%d available)", nkeys); ++ SSH_LOG(SSH_LOG_TRACE, "Opening OpenSSH private key: only 1 key supported (%d available)", nkeys); + goto out; + } + +@@ -314,7 +314,7 @@ ssh_pki_openssh_import(const char *text_key, + if (!private) { + rc = ssh_pki_import_pubkey_blob(pubkey0, &key); + if (rc != SSH_OK) { +- SSH_LOG(SSH_LOG_WARN, "Failed to import public key blob"); ++ SSH_LOG(SSH_LOG_TRACE, "Failed to import public key blob"); + } + /* in either case we clean up here */ + goto out; +@@ -343,7 +343,7 @@ ssh_pki_openssh_import(const char *text_key, + + rc = ssh_buffer_unpack(privkey_buffer, "dd", &checkint1, &checkint2); + if (rc == SSH_ERROR || checkint1 != checkint2) { +- SSH_LOG(SSH_LOG_WARN, "OpenSSH private key unpack error (correct password?)"); ++ SSH_LOG(SSH_LOG_TRACE, "OpenSSH private key unpack error (correct password?)"); + goto out; + } + rc = pki_openssh_import_privkey_blob(privkey_buffer, &key); +@@ -358,7 +358,7 @@ ssh_pki_openssh_import(const char *text_key, + if (padding != i) { + ssh_key_free(key); + key = NULL; +- SSH_LOG(SSH_LOG_WARN, "Invalid padding"); ++ SSH_LOG(SSH_LOG_TRACE, "Invalid padding"); + goto out; + } + } +@@ -407,7 +407,7 @@ static int pki_openssh_export_privkey_blob(const ssh_key privkey, + int rc; + + if (privkey->type != SSH_KEYTYPE_ED25519) { +- SSH_LOG(SSH_LOG_WARN, "Type %s not supported", privkey->type_c); ++ SSH_LOG(SSH_LOG_TRACE, "Type %s not supported", privkey->type_c); + return SSH_ERROR; + } + if (privkey->ed25519_privkey == NULL || +@@ -462,29 +462,29 @@ static int pki_private_key_encrypt(ssh_buffer privkey_buffer, + } + + if (ciphers[i].name == NULL){ +- SSH_LOG(SSH_LOG_WARN, "Unsupported cipher %s", ciphername); ++ SSH_LOG(SSH_LOG_TRACE, "Unsupported cipher %s", ciphername); + return SSH_ERROR; + } + + cmp = strcmp(kdfname, "bcrypt"); + if (cmp != 0){ +- SSH_LOG(SSH_LOG_WARN, "Unsupported KDF %s", kdfname); ++ SSH_LOG(SSH_LOG_TRACE, "Unsupported KDF %s", kdfname); + return SSH_ERROR; + } + /* We need material for key (keysize bits / 8) and IV (blocksize) */ + key_material_len = cipher.keysize/8 + cipher.blocksize; + if (key_material_len > sizeof(key_material)){ +- SSH_LOG(SSH_LOG_WARN, "Key material too big"); ++ SSH_LOG(SSH_LOG_TRACE, "Key material too big"); + return SSH_ERROR; + } + +- SSH_LOG(SSH_LOG_WARN, "Encryption: %d key, %d IV, %d rounds, %zu bytes salt", ++ SSH_LOG(SSH_LOG_DEBUG, "Encryption: %d key, %d IV, %d rounds, %zu bytes salt", + cipher.keysize/8, + cipher.blocksize, rounds, ssh_string_len(salt)); + + if (passphrase == NULL){ + if (auth_fn == NULL){ +- SSH_LOG(SSH_LOG_WARN, "No passphrase provided"); ++ SSH_LOG(SSH_LOG_TRACE, "No passphrase provided"); + return SSH_ERROR; + } + rc = auth_fn("Passphrase", +@@ -555,11 +555,11 @@ ssh_string ssh_pki_openssh_privkey_export(const ssh_key privkey, + return NULL; + } + if (privkey->type != SSH_KEYTYPE_ED25519){ +- SSH_LOG(SSH_LOG_WARN, "Unsupported key type %s", privkey->type_c); ++ SSH_LOG(SSH_LOG_TRACE, "Unsupported key type %s", privkey->type_c); + return NULL; + } + if (passphrase != NULL || auth_fn != NULL){ +- SSH_LOG(SSH_LOG_INFO, "Enabling encryption for private key export"); ++ SSH_LOG(SSH_LOG_DEBUG, "Enabling encryption for private key export"); + to_encrypt = 1; + } + buffer = ssh_buffer_new(); +diff --git a/src/pki_crypto.c b/src/pki_crypto.c +index ec9cfa4b..e9fe32d3 100644 +--- a/src/pki_crypto.c ++++ b/src/pki_crypto.c +@@ -587,7 +587,7 @@ int pki_key_generate_ecdsa(ssh_key key, int parameter) { + key->type = SSH_KEYTYPE_ECDSA_P256; + break; + default: +- SSH_LOG(SSH_LOG_WARN, "Invalid parameter %d for ECDSA key " ++ SSH_LOG(SSH_LOG_TRACE, "Invalid parameter %d for ECDSA key " + "generation", parameter); + return SSH_ERROR; + } +@@ -779,7 +779,7 @@ ssh_string pki_private_key_to_pem(const ssh_key key, + rc = 1; + break; + #else +- SSH_LOG(SSH_LOG_WARN, "PEM output not supported for key type ssh-ed25519"); ++ SSH_LOG(SSH_LOG_TRACE, "PEM output not supported for key type ssh-ed25519"); + goto err; + #endif + case SSH_KEYTYPE_DSS_CERT01: +@@ -790,11 +790,11 @@ ssh_string pki_private_key_to_pem(const ssh_key key, + case SSH_KEYTYPE_ED25519_CERT01: + case SSH_KEYTYPE_UNKNOWN: + default: +- SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key type %d", key->type); ++ SSH_LOG(SSH_LOG_TRACE, "Unknown or invalid private key type %d", key->type); + goto err; + } + if (rc != 1) { +- SSH_LOG(SSH_LOG_WARN, "Failed to initialize EVP_PKEY structure"); ++ SSH_LOG(SSH_LOG_TRACE, "Failed to initialize EVP_PKEY structure"); + goto err; + } + +@@ -887,8 +887,8 @@ ssh_key pki_private_key_from_base64(const char *b64_key, + BIO_free(mem); + + if (pkey == NULL) { +- SSH_LOG(SSH_LOG_WARN, +- "Parsing private key: %s", ++ SSH_LOG(SSH_LOG_TRACE, ++ "Error parsing private key: %s", + ERR_error_string(ERR_get_error(), NULL)); + return NULL; + } +@@ -896,8 +896,8 @@ ssh_key pki_private_key_from_base64(const char *b64_key, + case EVP_PKEY_DSA: + dsa = EVP_PKEY_get1_DSA(pkey); + if (dsa == NULL) { +- SSH_LOG(SSH_LOG_WARN, +- "Parsing private key: %s", ++ SSH_LOG(SSH_LOG_TRACE, ++ "Error parsing private key: %s", + ERR_error_string(ERR_get_error(),NULL)); + goto fail; + } +@@ -906,8 +906,8 @@ ssh_key pki_private_key_from_base64(const char *b64_key, + case EVP_PKEY_RSA: + rsa = EVP_PKEY_get1_RSA(pkey); + if (rsa == NULL) { +- SSH_LOG(SSH_LOG_WARN, +- "Parsing private key: %s", ++ SSH_LOG(SSH_LOG_TRACE, ++ "Error parsing private key: %s", + ERR_error_string(ERR_get_error(),NULL)); + goto fail; + } +@@ -917,8 +917,8 @@ ssh_key pki_private_key_from_base64(const char *b64_key, + #ifdef HAVE_OPENSSL_ECC + ecdsa = EVP_PKEY_get1_EC_KEY(pkey); + if (ecdsa == NULL) { +- SSH_LOG(SSH_LOG_WARN, +- "Parsing private key: %s", ++ SSH_LOG(SSH_LOG_TRACE, ++ "Error parsing private key: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } +@@ -927,7 +927,7 @@ ssh_key pki_private_key_from_base64(const char *b64_key, + * keys, so we need to figure out the correct type here */ + type = pki_key_ecdsa_to_key_type(ecdsa); + if (type == SSH_KEYTYPE_UNKNOWN) { +- SSH_LOG(SSH_LOG_WARN, "Invalid private key."); ++ SSH_LOG(SSH_LOG_TRACE, "Invalid private key."); + goto fail; + } + +@@ -954,7 +954,7 @@ ssh_key pki_private_key_from_base64(const char *b64_key, + + ed25519 = malloc(key_len); + if (ed25519 == NULL) { +- SSH_LOG(SSH_LOG_WARN, "Out of memory"); ++ SSH_LOG(SSH_LOG_TRACE, "Out of memory"); + goto fail; + } + +@@ -972,7 +972,7 @@ ssh_key pki_private_key_from_base64(const char *b64_key, + #endif + default: + EVP_PKEY_free(pkey); +- SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key type %d", ++ SSH_LOG(SSH_LOG_TRACE, "Unknown or invalid private key type %d", + EVP_PKEY_base_id(pkey)); + return NULL; + } +@@ -1571,7 +1571,7 @@ ssh_string pki_signature_to_blob(const ssh_signature sig) + #endif + default: + case SSH_KEYTYPE_UNKNOWN: +- SSH_LOG(SSH_LOG_WARN, "Unknown signature key type: %s", sig->type_c); ++ SSH_LOG(SSH_LOG_TRACE, "Unknown signature key type: %s", sig->type_c); + return NULL; + } + +@@ -1591,13 +1591,13 @@ static int pki_signature_from_rsa_blob(const ssh_key pubkey, + size_t len = ssh_string_len(sig_blob); + + if (pubkey->rsa == NULL) { +- SSH_LOG(SSH_LOG_WARN, "Pubkey RSA field NULL"); ++ SSH_LOG(SSH_LOG_TRACE, "Pubkey RSA field NULL"); + goto errout; + } + + rsalen = RSA_size(pubkey->rsa); + if (len > rsalen) { +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_TRACE, + "Signature is too big: %lu > %lu", + (unsigned long)len, + (unsigned long)rsalen); +@@ -1605,7 +1605,7 @@ static int pki_signature_from_rsa_blob(const ssh_key pubkey, + } + + #ifdef DEBUG_CRYPTO +- SSH_LOG(SSH_LOG_WARN, "RSA signature len: %lu", (unsigned long)len); ++ SSH_LOG(SSH_LOG_DEBUG, "RSA signature len: %lu", (unsigned long)len); + ssh_log_hexdump("RSA signature", ssh_string_data(sig_blob), len); + #endif + +@@ -1669,7 +1669,7 @@ static int pki_signature_from_dsa_blob(UNUSED_PARAM(const ssh_key pubkey), + + /* 40 is the dual signature blob len. */ + if (len != 40) { +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_TRACE, + "Signature has wrong size: %lu", + (unsigned long)len); + goto error; +@@ -1832,7 +1832,7 @@ static int pki_signature_from_ecdsa_blob(UNUSED_PARAM(const ssh_key pubkey), + if (rlen != 0) { + ssh_string_burn(s); + SSH_STRING_FREE(s); +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_TRACE, + "Signature has remaining bytes in inner " + "sigblob: %lu", + (unsigned long)rlen); +@@ -1921,7 +1921,7 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey, + int rc; + + if (ssh_key_type_plain(pubkey->type) != type) { +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_TRACE, + "Incompatible public key provided (%d) expecting (%d)", + type, + pubkey->type); +@@ -1972,7 +1972,7 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey, + #endif + default: + case SSH_KEYTYPE_UNKNOWN: +- SSH_LOG(SSH_LOG_WARN, "Unknown signature type"); ++ SSH_LOG(SSH_LOG_TRACE, "Unknown signature type"); + goto error; + } + +diff --git a/src/pki_ed25519_common.c b/src/pki_ed25519_common.c +index 7aa05269..15c9abef 100644 +--- a/src/pki_ed25519_common.c ++++ b/src/pki_ed25519_common.c +@@ -34,7 +34,7 @@ int pki_privkey_build_ed25519(ssh_key key, + if (ssh_string_len(pubkey) != ED25519_KEY_LEN || + ssh_string_len(privkey) != (2 * ED25519_KEY_LEN)) + { +- SSH_LOG(SSH_LOG_WARN, "Invalid ed25519 key len"); ++ SSH_LOG(SSH_LOG_TRACE, "Invalid ed25519 key len"); + return SSH_ERROR; + } + +@@ -266,7 +266,7 @@ int pki_signature_from_ed25519_blob(ssh_signature sig, ssh_string sig_blob) + + len = ssh_string_len(sig_blob); + if (len != ED25519_SIG_LEN){ +- SSH_LOG(SSH_LOG_WARN, "Invalid ssh-ed25519 signature len: %zu", len); ++ SSH_LOG(SSH_LOG_TRACE, "Invalid ssh-ed25519 signature len: %zu", len); + return SSH_ERROR; + } + +diff --git a/src/pki_gcrypt.c b/src/pki_gcrypt.c +index bf45351d..87cd91c8 100644 +--- a/src/pki_gcrypt.c ++++ b/src/pki_gcrypt.c +@@ -938,7 +938,7 @@ ssh_string pki_private_key_to_pem(const ssh_key key, + (void) auth_fn; + (void) auth_data; + +- SSH_LOG(SSH_LOG_WARN, "PEM export not supported by gcrypt backend!"); ++ SSH_LOG(SSH_LOG_TRACE, "PEM export not supported by gcrypt backend!"); + + return NULL; + } +@@ -957,7 +957,7 @@ ssh_key pki_private_key_from_base64(const char *b64_key, + + type = pki_privatekey_type_from_string(b64_key); + if (type == SSH_KEYTYPE_UNKNOWN) { +- SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key."); ++ SSH_LOG(SSH_LOG_TRACE, "Unknown or invalid private key."); + return NULL; + } + +@@ -977,7 +977,7 @@ ssh_key pki_private_key_from_base64(const char *b64_key, + } + + if (!valid) { +- SSH_LOG(SSH_LOG_WARN, "Parsing private key"); ++ SSH_LOG(SSH_LOG_TRACE, "Error parsing private key"); + goto fail; + } + break; +@@ -996,7 +996,7 @@ ssh_key pki_private_key_from_base64(const char *b64_key, + } + + if (!valid) { +- SSH_LOG(SSH_LOG_WARN, "Parsing private key"); ++ SSH_LOG(SSH_LOG_TRACE, "Error parsing private key"); + goto fail; + } + break; +@@ -1027,7 +1027,7 @@ ssh_key pki_private_key_from_base64(const char *b64_key, + } + + if (!valid) { +- SSH_LOG(SSH_LOG_WARN, "Parsing private key"); ++ SSH_LOG(SSH_LOG_TRACE, "Error parsing private key"); + goto fail; + } + +@@ -1035,7 +1035,7 @@ ssh_key pki_private_key_from_base64(const char *b64_key, + * keys, so we need to figure out the correct type here */ + type = pki_key_ecdsa_to_key_type(ecdsa); + if (type == SSH_KEYTYPE_UNKNOWN) { +- SSH_LOG(SSH_LOG_WARN, "Invalid private key."); ++ SSH_LOG(SSH_LOG_TRACE, "Invalid private key."); + goto fail; + } + break; +@@ -1045,7 +1045,7 @@ ssh_key pki_private_key_from_base64(const char *b64_key, + case SSH_KEYTYPE_RSA1: + case SSH_KEYTYPE_UNKNOWN: + default: +- SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key type %d", type); ++ SSH_LOG(SSH_LOG_TRACE, "Unknown or invalid private key type %d", type); + return NULL; + } + +@@ -1905,7 +1905,7 @@ ssh_string pki_signature_to_blob(const ssh_signature sig) + case SSH_KEYTYPE_RSA1: + case SSH_KEYTYPE_UNKNOWN: + default: +- SSH_LOG(SSH_LOG_WARN, "Unknown signature key type: %d", sig->type); ++ SSH_LOG(SSH_LOG_TRACE, "Unknown signature key type: %d", sig->type); + return NULL; + break; + } +@@ -1925,7 +1925,7 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey, + int rc; + + if (ssh_key_type_plain(pubkey->type) != type) { +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_TRACE, + "Incompatible public key provided (%d) expecting (%d)", + type, + pubkey->type); +@@ -1947,7 +1947,7 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey, + case SSH_KEYTYPE_DSS: + /* 40 is the dual signature blob len. */ + if (len != 40) { +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_TRACE, + "Signature has wrong size: %lu", + (unsigned long)len); + ssh_signature_free(sig); +@@ -1977,7 +1977,7 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey, + rsalen = (gcry_pk_get_nbits(pubkey->rsa) + 7) / 8; + + if (len > rsalen) { +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_TRACE, + "Signature is to big size: %lu", + (unsigned long)len); + ssh_signature_free(sig); +@@ -2055,7 +2055,7 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey, + } + + if (rlen != 0) { +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_TRACE, + "Signature has remaining bytes in inner " + "sigblob: %lu", + (unsigned long)rlen); +@@ -2093,7 +2093,7 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey, + case SSH_KEYTYPE_RSA1: + case SSH_KEYTYPE_UNKNOWN: + default: +- SSH_LOG(SSH_LOG_WARN, "Unknown signature type"); ++ SSH_LOG(SSH_LOG_TRACE, "Unknown signature type"); + return NULL; + } + +@@ -2154,7 +2154,7 @@ ssh_signature pki_do_sign_hash(const ssh_key privkey, + break; + case SSH_DIGEST_AUTO: + default: +- SSH_LOG(SSH_LOG_WARN, "Incompatible key algorithm"); ++ SSH_LOG(SSH_LOG_TRACE, "Incompatible key algorithm"); + return NULL; + } + err = gcry_sexp_build(&sexp, +diff --git a/src/pki_mbedcrypto.c b/src/pki_mbedcrypto.c +index c33fb726..ca19a5fa 100644 +--- a/src/pki_mbedcrypto.c ++++ b/src/pki_mbedcrypto.c +@@ -95,7 +95,7 @@ ssh_key pki_private_key_from_base64(const char *b64_key, const char *passphrase, + + type = pki_privatekey_type_from_string(b64_key); + if (type == SSH_KEYTYPE_UNKNOWN) { +- SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key."); ++ SSH_LOG(SSH_LOG_TRACE, "Unknown or invalid private key."); + return NULL; + } + +@@ -136,7 +136,7 @@ ssh_key pki_private_key_from_base64(const char *b64_key, const char *passphrase, + if (valid != 0) { + char error_buf[100]; + mbedtls_strerror(valid, error_buf, 100); +- SSH_LOG(SSH_LOG_WARN,"Parsing private key %s", error_buf); ++ SSH_LOG(SSH_LOG_TRACE,"Parsing private key %s", error_buf); + goto fail; + } + break; +@@ -177,14 +177,14 @@ ssh_key pki_private_key_from_base64(const char *b64_key, const char *passphrase, + if (valid != 0) { + char error_buf[100]; + mbedtls_strerror(valid, error_buf, 100); +- SSH_LOG(SSH_LOG_WARN,"Parsing private key %s", error_buf); ++ SSH_LOG(SSH_LOG_TRACE,"Parsing private key %s", error_buf); + goto fail; + } + break; + case SSH_KEYTYPE_ED25519: + /* Cannot open ed25519 keys with libmbedcrypto */ + default: +- SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key type %d", ++ SSH_LOG(SSH_LOG_TRACE, "Unknown or invalid private key type %d", + type); + return NULL; + } +@@ -213,7 +213,7 @@ ssh_key pki_private_key_from_base64(const char *b64_key, const char *passphrase, + * keys, so we need to figure out the correct type here */ + type = pki_key_ecdsa_to_key_type(key->ecdsa); + if (type == SSH_KEYTYPE_UNKNOWN) { +- SSH_LOG(SSH_LOG_WARN, "Invalid private key."); ++ SSH_LOG(SSH_LOG_TRACE, "Invalid private key."); + goto fail; + } + } else { +@@ -276,19 +276,19 @@ int pki_privkey_build_rsa(ssh_key key, + ssh_string_data(d), ssh_string_len(d), + ssh_string_data(e), ssh_string_len(e)); + if (rc != 0) { +- SSH_LOG(SSH_LOG_WARN, "Failed to import private RSA key"); ++ SSH_LOG(SSH_LOG_TRACE, "Failed to import private RSA key"); + goto fail; + } + + rc = mbedtls_rsa_complete(rsa); + if (rc != 0) { +- SSH_LOG(SSH_LOG_WARN, "Failed to complete private RSA key"); ++ SSH_LOG(SSH_LOG_TRACE, "Failed to complete private RSA key"); + goto fail; + } + + rc = mbedtls_rsa_check_privkey(rsa); + if (rc != 0) { +- SSH_LOG(SSH_LOG_WARN, "Inconsistent private RSA key"); ++ SSH_LOG(SSH_LOG_TRACE, "Inconsistent private RSA key"); + goto fail; + } + +@@ -845,7 +845,7 @@ ssh_string pki_signature_to_blob(const ssh_signature sig) + sig_blob = pki_ed25519_signature_to_blob(sig); + break; + default: +- SSH_LOG(SSH_LOG_WARN, "Unknown signature key type: %s", ++ SSH_LOG(SSH_LOG_TRACE, "Unknown signature key type: %s", + sig->type_c); + return NULL; + } +@@ -865,20 +865,20 @@ static ssh_signature pki_signature_from_rsa_blob(const ssh_key pubkey, const + size_t len = ssh_string_len(sig_blob); + + if (pubkey->rsa == NULL) { +- SSH_LOG(SSH_LOG_WARN, "Pubkey RSA field NULL"); ++ SSH_LOG(SSH_LOG_TRACE, "Pubkey RSA field NULL"); + goto errout; + } + + rsalen = mbedtls_pk_get_bitlen(pubkey->rsa) / 8; + if (len > rsalen) { +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_TRACE, + "Signature is too big: %lu > %lu", + (unsigned long) len, + (unsigned long) rsalen); + goto errout; + } + #ifdef DEBUG_CRYPTO +- SSH_LOG(SSH_LOG_WARN, "RSA signature len: %lu", (unsigned long)len); ++ SSH_LOG(SSH_LOG_TRACE, "RSA signature len: %lu", (unsigned long)len); + ssh_log_hexdump("RSA signature", ssh_string_data(sig_blob), len); + #endif + +@@ -919,7 +919,7 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey, + int rc; + + if (ssh_key_type_plain(pubkey->type) != type) { +- SSH_LOG(SSH_LOG_WARN, ++ SSH_LOG(SSH_LOG_TRACE, + "Incompatible public key provided (%d) expecting (%d)", + type, + pubkey->type); +@@ -1003,7 +1003,7 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey, + } + + if (rlen != 0) { +- SSH_LOG(SSH_LOG_WARN, "Signature has remaining bytes in inner " ++ SSH_LOG(SSH_LOG_TRACE, "Signature has remaining bytes in inner " + "sigblob: %lu", + (unsigned long)rlen); + ssh_signature_free(sig); +@@ -1020,7 +1020,7 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey, + } + break; + default: +- SSH_LOG(SSH_LOG_WARN, "Unknown signature type"); ++ SSH_LOG(SSH_LOG_TRACE, "Unknown signature type"); + return NULL; + } + +@@ -1050,7 +1050,7 @@ static ssh_string rsa_do_sign_hash(const unsigned char *digest, + break; + case SSH_DIGEST_AUTO: + default: +- SSH_LOG(SSH_LOG_WARN, "Incompatible key algorithm"); ++ SSH_LOG(SSH_LOG_TRACE, "Incompatible key algorithm"); + return NULL; + } + +diff --git a/src/scp.c b/src/scp.c +index 85d670a4..d3f9a831 100644 +--- a/src/scp.c ++++ b/src/scp.c +@@ -140,7 +140,7 @@ int ssh_scp_init(ssh_scp scp) + return SSH_ERROR; + } + +- SSH_LOG(SSH_LOG_PROTOCOL, "Initializing scp session %s %son location '%s'", ++ SSH_LOG(SSH_LOG_DEBUG, "Initializing scp session %s %son location '%s'", + scp->mode == SSH_SCP_WRITE?"write":"read", + scp->recursive ? "recursive " : "", + scp->location); +@@ -364,7 +364,7 @@ int ssh_scp_push_directory(ssh_scp scp, const char *dirname, int mode) + goto error; + } + +- SSH_LOG(SSH_LOG_PROTOCOL, ++ SSH_LOG(SSH_LOG_DEBUG, + "SCP pushing directory %s with permissions '%s'", + vis_encoded, perms); + +@@ -501,7 +501,7 @@ int ssh_scp_push_file64(ssh_scp scp, const char *filename, uint64_t size, + goto error; + } + +- SSH_LOG(SSH_LOG_PROTOCOL, ++ SSH_LOG(SSH_LOG_DEBUG, + "SCP pushing file %s, size %" PRIu64 " with permissions '%s'", + vis_encoded, size, perms); + +@@ -800,7 +800,7 @@ int ssh_scp_pull_request(ssh_scp scp) + *p = '\0'; + } + +- SSH_LOG(SSH_LOG_PROTOCOL, "Received SCP request: '%s'", buffer); ++ SSH_LOG(SSH_LOG_DEBUG, "Received SCP request: '%s'", buffer); + switch(buffer[0]) { + case 'C': + /* File */ +diff --git a/src/server.c b/src/server.c +index 841a1c42..acfbfffe 100644 +--- a/src/server.c ++++ b/src/server.c +@@ -348,7 +348,7 @@ static void ssh_server_connection_callback(ssh_session session){ + goto error; + } + set_status(session, 0.4f); +- SSH_LOG(SSH_LOG_PROTOCOL, ++ SSH_LOG(SSH_LOG_DEBUG, + "SSH client banner: %s", session->clientbanner); + + /* Here we analyze the different protocols the server allows. */ +@@ -884,7 +884,7 @@ int ssh_message_auth_interactive_request(ssh_message msg, const char *name, + + /* fill in the kbdint structure */ + if (msg->session->kbdint == NULL) { +- SSH_LOG(SSH_LOG_PROTOCOL, "Warning: Got a " ++ SSH_LOG(SSH_LOG_DEBUG, "Warning: Got a " + "keyboard-interactive response but it " + "seems we didn't send the request."); + +@@ -981,13 +981,13 @@ int ssh_auth_reply_success(ssh_session session, int partial) + + crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_OUT); + if (crypto != NULL && crypto->delayed_compress_out) { +- SSH_LOG(SSH_LOG_PROTOCOL, "Enabling delayed compression OUT"); ++ SSH_LOG(SSH_LOG_DEBUG, "Enabling delayed compression OUT"); + crypto->do_compress_out = 1; + } + + crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_IN); + if (crypto != NULL && crypto->delayed_compress_in) { +- SSH_LOG(SSH_LOG_PROTOCOL, "Enabling delayed compression IN"); ++ SSH_LOG(SSH_LOG_DEBUG, "Enabling delayed compression IN"); + crypto->do_compress_in = 1; + } + return r; +diff --git a/src/session.c b/src/session.c +index 3199096a..fe87cadd 100644 +--- a/src/session.c ++++ b/src/session.c +@@ -504,11 +504,14 @@ int ssh_is_blocking(ssh_session session) + /* Waits until the output socket is empty */ + static int ssh_flush_termination(void *c){ + ssh_session session = c; +- if (ssh_socket_buffered_write_bytes(session->socket) == 0 || +- session->session_state == SSH_SESSION_STATE_ERROR) ++ if (ssh_socket_buffered_write_bytes(session->socket) == 0) { + return 1; +- else ++ } else if (session->session_state == SSH_SESSION_STATE_ERROR) { ++ SSH_LOG(SSH_LOG_WARN, "Error: %s", ssh_get_error(session)); ++ return 1; ++ } else { + return 0; ++ } + } + + /** +@@ -1184,7 +1187,7 @@ int ssh_get_publickey_hash(const ssh_key key, + + /* In FIPS mode, we cannot use MD5 */ + if (ssh_fips_mode()) { +- SSH_LOG(SSH_LOG_WARN, "In FIPS mode MD5 is not allowed." ++ SSH_LOG(SSH_LOG_TRACE, "In FIPS mode MD5 is not allowed." + "Try using SSH_PUBLICKEY_HASH_SHA256"); + rc = SSH_ERROR; + goto out; +diff --git a/src/sftp.c b/src/sftp.c +index a8346040..e3a842d5 100644 +--- a/src/sftp.c ++++ b/src/sftp.c +@@ -316,7 +316,7 @@ int sftp_server_init(sftp_session sftp){ + } + SSH_BUFFER_FREE(reply); + +- SSH_LOG(SSH_LOG_PROTOCOL, "Server version sent"); ++ SSH_LOG(SSH_LOG_DEBUG, "Server version sent"); + + if (version > LIBSFTP_VERSION) { + sftp->version = LIBSFTP_VERSION; +@@ -707,7 +707,7 @@ int sftp_init(sftp_session sftp) { + sftp_set_error(sftp, SSH_FX_FAILURE); + return -1; + } +- SSH_LOG(SSH_LOG_PROTOCOL, ++ SSH_LOG(SSH_LOG_DEBUG, + "SFTP server version %d", + version); + rc = ssh_buffer_unpack(packet->payload, "s", &ext_name); +@@ -720,7 +720,7 @@ int sftp_init(sftp_session sftp) { + break; + } + +- SSH_LOG(SSH_LOG_PROTOCOL, ++ SSH_LOG(SSH_LOG_DEBUG, + "SFTP server extension: %s, version: %s", + ext_name, ext_data); + +@@ -1353,7 +1353,7 @@ static sftp_attributes sftp_parse_attr_3(sftp_session sftp, ssh_buffer buf, + if (rc != SSH_OK){ + goto error; + } +- SSH_LOG(SSH_LOG_PROTOCOL, "Name: %s", attr->name); ++ SSH_LOG(SSH_LOG_DEBUG, "Name: %s", attr->name); + + /* Set owner and group if we talk to openssh and have the longname */ + if (ssh_get_openssh_version(sftp->session)) { +@@ -1373,7 +1373,7 @@ static sftp_attributes sftp_parse_attr_3(sftp_session sftp, ssh_buffer buf, + if (rc != SSH_OK){ + goto error; + } +- SSH_LOG(SSH_LOG_PROTOCOL, ++ SSH_LOG(SSH_LOG_DEBUG, + "Flags: %.8"PRIx32"\n", (uint32_t) attr->flags); + + if (attr->flags & SSH_FILEXFER_ATTR_SIZE) { +@@ -1381,7 +1381,7 @@ static sftp_attributes sftp_parse_attr_3(sftp_session sftp, ssh_buffer buf, + if(rc != SSH_OK) { + goto error; + } +- SSH_LOG(SSH_LOG_PROTOCOL, ++ SSH_LOG(SSH_LOG_DEBUG, + "Size: %"PRIu64"\n", + (uint64_t) attr->size); + } +@@ -1644,7 +1644,7 @@ sftp_attributes sftp_readdir(sftp_session sftp, sftp_dir dir) + return NULL; + } + +- SSH_LOG(SSH_LOG_PROTOCOL, "Count is %d", dir->count); ++ SSH_LOG(SSH_LOG_DEBUG, "Count is %d", dir->count); + + attr = sftp_parse_attr(sftp, dir->buffer, 1); + if (attr == NULL) { +diff --git a/src/socket.c b/src/socket.c +index 2fef8e7e..f470bb28 100644 +--- a/src/socket.c ++++ b/src/socket.c +@@ -473,12 +473,12 @@ void ssh_socket_close(ssh_socket s) + kill(pid, SIGTERM); + while (waitpid(pid, &status, 0) == -1) { + if (errno != EINTR) { +- SSH_LOG(SSH_LOG_WARN, "waitpid failed: %s", strerror(errno)); ++ SSH_LOG(SSH_LOG_TRACE, "waitpid failed: %s", strerror(errno)); + return; + } + } + if (!WIFEXITED(status)) { +- SSH_LOG(SSH_LOG_WARN, "Proxy command exitted abnormally"); ++ SSH_LOG(SSH_LOG_TRACE, "Proxy command exitted abnormally"); + return; + } + SSH_LOG(SSH_LOG_TRACE, "Proxy command returned %d", WEXITSTATUS(status)); +@@ -849,7 +849,7 @@ int ssh_socket_connect(ssh_socket s, + return SSH_ERROR; + } + fd = ssh_connect_host_nonblocking(s->session, host, bind_addr, port); +- SSH_LOG(SSH_LOG_PROTOCOL, "Nonblocking connection socket: %d", fd); ++ SSH_LOG(SSH_LOG_DEBUG, "Nonblocking connection socket: %d", fd); + if (fd == SSH_INVALID_SOCKET) { + return SSH_ERROR; + } +@@ -873,7 +873,7 @@ ssh_execute_command(const char *command, socket_t in, socket_t out) + /* Prepare /dev/null socket for the stderr redirection */ + int devnull = open("/dev/null", O_WRONLY); + if (devnull == -1) { +- SSH_LOG(SSH_LOG_WARNING, "Failed to open /dev/null"); ++ SSH_LOG(SSH_LOG_TRACE, "Failed to open /dev/null"); + exit(1); + } + +@@ -914,7 +914,7 @@ ssh_socket_connect_proxycommand(ssh_socket s, const char *command) + return SSH_ERROR; + } + +- SSH_LOG(SSH_LOG_PROTOCOL, "Executing proxycommand '%s'", command); ++ SSH_LOG(SSH_LOG_DEBUG, "Executing proxycommand '%s'", command); + pid = fork(); + if (pid == 0) { + ssh_execute_command(command, pair[0], pair[0]); +@@ -922,7 +922,7 @@ ssh_socket_connect_proxycommand(ssh_socket s, const char *command) + } + s->proxy_pid = pid; + close(pair[0]); +- SSH_LOG(SSH_LOG_PROTOCOL, "ProxyCommand connection pipe: [%d,%d]",pair[0],pair[1]); ++ SSH_LOG(SSH_LOG_DEBUG, "ProxyCommand connection pipe: [%d,%d]",pair[0],pair[1]); + ssh_socket_set_fd(s, pair[1]); + s->state=SSH_SOCKET_CONNECTED; + s->fd_is_socket=0; diff --git a/root/ppg/common/deps/libssh/rpm/null_dereference_rekey.patch b/root/ppg/common/deps/libssh/rpm/null_dereference_rekey.patch new file mode 100644 index 00000000..505240b5 --- /dev/null +++ b/root/ppg/common/deps/libssh/rpm/null_dereference_rekey.patch @@ -0,0 +1,1845 @@ +diff --color -ru ../libssh-0.9.6/include/libssh/curve25519.h ./include/libssh/curve25519.h +--- ../libssh-0.9.6/include/libssh/curve25519.h 2021-03-15 08:11:33.000000000 +0100 ++++ ./include/libssh/curve25519.h 2023-04-27 12:21:30.257820636 +0200 +@@ -48,6 +48,7 @@ + + + int ssh_client_curve25519_init(ssh_session session); ++void ssh_client_curve25519_remove_callbacks(ssh_session session); + + #ifdef WITH_SERVER + void ssh_server_curve25519_init(ssh_session session); +diff --color -ru ../libssh-0.9.6/include/libssh/dh-gex.h ./include/libssh/dh-gex.h +--- ../libssh-0.9.6/include/libssh/dh-gex.h 2021-03-15 08:11:33.000000000 +0100 ++++ ./include/libssh/dh-gex.h 2023-04-27 12:21:30.257820636 +0200 +@@ -24,6 +24,7 @@ + #define SRC_DH_GEX_H_ + + int ssh_client_dhgex_init(ssh_session session); ++void ssh_client_dhgex_remove_callbacks(ssh_session session); + + #ifdef WITH_SERVER + void ssh_server_dhgex_init(ssh_session session); +diff --color -ru ../libssh-0.9.6/include/libssh/dh.h ./include/libssh/dh.h +--- ../libssh-0.9.6/include/libssh/dh.h 2021-03-15 08:11:33.000000000 +0100 ++++ ./include/libssh/dh.h 2023-04-27 12:21:30.257820636 +0200 +@@ -63,8 +63,10 @@ + ssh_key ssh_dh_get_next_server_publickey(ssh_session session); + int ssh_dh_get_next_server_publickey_blob(ssh_session session, + ssh_string *pubkey_blob); ++int dh_handshake(ssh_session session); + + int ssh_client_dh_init(ssh_session session); ++void ssh_client_dh_remove_callbacks(ssh_session session); + #ifdef WITH_SERVER + void ssh_server_dh_init(ssh_session session); + #endif /* WITH_SERVER */ +diff --color -ru ../libssh-0.9.6/include/libssh/ecdh.h ./include/libssh/ecdh.h +--- ../libssh-0.9.6/include/libssh/ecdh.h 2021-03-15 08:11:33.000000000 +0100 ++++ ./include/libssh/ecdh.h 2023-04-27 12:21:30.257820636 +0200 +@@ -45,6 +45,7 @@ + extern struct ssh_packet_callbacks_struct ssh_ecdh_client_callbacks; + /* Backend-specific functions. */ + int ssh_client_ecdh_init(ssh_session session); ++void ssh_client_ecdh_remove_callbacks(ssh_session session); + int ecdh_build_k(ssh_session session); + + #ifdef WITH_SERVER +diff --color -ru ../libssh-0.9.6/include/libssh/kex.h ./include/libssh/kex.h +--- ../libssh-0.9.6/include/libssh/kex.h 2021-03-15 08:11:33.000000000 +0100 ++++ ./include/libssh/kex.h 2023-04-27 12:21:30.257820636 +0200 +@@ -33,7 +33,7 @@ + + SSH_PACKET_CALLBACK(ssh_packet_kexinit); + +-int ssh_send_kex(ssh_session session, int server_kex); ++int ssh_send_kex(ssh_session session); + void ssh_list_kex(struct ssh_kex_struct *kex); + int ssh_set_client_kex(ssh_session session); + int ssh_kex_select_methods(ssh_session session); +diff --color -ru ../libssh-0.9.6/include/libssh/session.h ./include/libssh/session.h +--- ../libssh-0.9.6/include/libssh/session.h 2021-08-26 14:27:42.000000000 +0200 ++++ ./include/libssh/session.h 2023-04-27 12:24:04.679475777 +0200 +@@ -75,6 +75,11 @@ + /* Client successfully authenticated */ + #define SSH_SESSION_FLAG_AUTHENTICATED 2 + ++/* The KEXINIT message can be sent first by either of the parties so this flag ++ * indicates that the message was already sent to make sure it is sent and avoid ++ * sending it twice during key exchange to simplify the state machine. */ ++#define SSH_SESSION_FLAG_KEXINIT_SENT 4 ++ + /* codes to use with ssh_handle_packets*() */ + /* Infinite timeout */ + #define SSH_TIMEOUT_INFINITE -1 +@@ -131,10 +136,8 @@ + /* Extensions negotiated using RFC 8308 */ + uint32_t extensions; + +- ssh_string banner; /* that's the issue banner from +- the server */ +- char *discon_msg; /* disconnect message from +- the remote host */ ++ ssh_string banner; /* that's the issue banner from the server */ ++ char *discon_msg; /* disconnect message from the remote host */ + ssh_buffer in_buffer; + PACKET in_packet; + ssh_buffer out_buffer; +@@ -158,25 +161,33 @@ + uint32_t current_method; + } auth; + ++ /* Sending this flag before key exchange to save one round trip during the ++ * key exchange. This might make sense on high-latency connections. ++ * So far internal only for testing. Usable only on the client side -- ++ * there is no key exchange method that would start with server message */ ++ bool send_first_kex_follows; + /* + * RFC 4253, 7.1: if the first_kex_packet_follows flag was set in + * the received SSH_MSG_KEXINIT, but the guess was wrong, this + * field will be set such that the following guessed packet will +- * be ignored. Once that packet has been received and ignored, +- * this field is cleared. ++ * be ignored on the receiving side. Once that packet has been received and ++ * ignored, this field is cleared. ++ * On the sending side, this is set after we got peer KEXINIT message and we ++ * need to resend the initial message of the negotiated KEX algorithm. + */ +- int first_kex_follows_guess_wrong; ++ bool first_kex_follows_guess_wrong; + + ssh_buffer in_hashbuf; + ssh_buffer out_hashbuf; + struct ssh_crypto_struct *current_crypto; +- struct ssh_crypto_struct *next_crypto; /* next_crypto is going to be used after a SSH2_MSG_NEWKEYS */ ++ /* next_crypto is going to be used after a SSH2_MSG_NEWKEYS */ ++ struct ssh_crypto_struct *next_crypto; + + struct ssh_list *channels; /* linked list of channels */ + int maxchannel; + ssh_agent agent; /* ssh agent */ + +-/* keyb interactive data */ ++ /* keyboard interactive data */ + struct ssh_kbdint_struct *kbdint; + struct ssh_gssapi_struct *gssapi; + +@@ -193,7 +204,8 @@ + + /* auths accepted by server */ + struct ssh_list *ssh_message_list; /* list of delayed SSH messages */ +- int (*ssh_message_callback)( struct ssh_session_struct *session, ssh_message msg, void *userdata); ++ int (*ssh_message_callback)(struct ssh_session_struct *session, ++ ssh_message msg, void *userdata); + void *ssh_message_callback_data; + ssh_server_callbacks server_callbacks; + void (*ssh_connection_callback)( struct ssh_session_struct *session); +diff --color -ru ../libssh-0.9.6/src/client.c ./src/client.c +--- ../libssh-0.9.6/src/client.c 2023-04-27 12:22:39.797925403 +0200 ++++ ./src/client.c 2023-04-27 12:24:04.680475778 +0200 +@@ -243,10 +243,13 @@ + * @warning this function returning is no proof that DH handshake is + * completed + */ +-static int dh_handshake(ssh_session session) { +- ++int dh_handshake(ssh_session session) ++{ + int rc = SSH_AGAIN; + ++ SSH_LOG(SSH_LOG_TRACE, "dh_handshake_state = %d, kex_type = %d", ++ session->dh_handshake_state, session->next_crypto->kex_type); ++ + switch (session->dh_handshake_state) { + case DH_STATE_INIT: + switch(session->next_crypto->kex_type){ +@@ -386,96 +389,102 @@ + { + int rc; + +- switch(session->session_state) { +- case SSH_SESSION_STATE_NONE: +- case SSH_SESSION_STATE_CONNECTING: +- break; +- case SSH_SESSION_STATE_SOCKET_CONNECTED: +- ssh_set_fd_towrite(session); +- ssh_send_banner(session, 0); +- +- break; +- case SSH_SESSION_STATE_BANNER_RECEIVED: +- if (session->serverbanner == NULL) { +- goto error; +- } +- set_status(session, 0.4f); +- SSH_LOG(SSH_LOG_DEBUG, +- "SSH server banner: %s", session->serverbanner); ++ SSH_LOG(SSH_LOG_DEBUG, "session_state=%d", session->session_state); + +- /* Here we analyze the different protocols the server allows. */ +- rc = ssh_analyze_banner(session, 0); +- if (rc < 0) { +- ssh_set_error(session, SSH_FATAL, +- "No version of SSH protocol usable (banner: %s)", +- session->serverbanner); +- goto error; +- } ++ switch (session->session_state) { ++ case SSH_SESSION_STATE_NONE: ++ case SSH_SESSION_STATE_CONNECTING: ++ break; ++ case SSH_SESSION_STATE_SOCKET_CONNECTED: ++ ssh_set_fd_towrite(session); ++ ssh_send_banner(session, 0); ++ ++ break; ++ case SSH_SESSION_STATE_BANNER_RECEIVED: ++ if (session->serverbanner == NULL) { ++ goto error; ++ } ++ set_status(session, 0.4f); ++ SSH_LOG(SSH_LOG_DEBUG, ++ "SSH server banner: %s", session->serverbanner); ++ ++ /* Here we analyze the different protocols the server allows. */ ++ rc = ssh_analyze_banner(session, 0); ++ if (rc < 0) { ++ ssh_set_error(session, SSH_FATAL, ++ "No version of SSH protocol usable (banner: %s)", ++ session->serverbanner); ++ goto error; ++ } ++ ++ ssh_packet_register_socket_callback(session, session->socket); + +- ssh_packet_register_socket_callback(session, session->socket); ++ ssh_packet_set_default_callbacks(session); ++ session->session_state = SSH_SESSION_STATE_INITIAL_KEX; ++ rc = ssh_set_client_kex(session); ++ if (rc != SSH_OK) { ++ goto error; ++ } ++ rc = ssh_send_kex(session); ++ if (rc < 0) { ++ goto error; ++ } ++ set_status(session, 0.5f); + +- ssh_packet_set_default_callbacks(session); +- session->session_state = SSH_SESSION_STATE_INITIAL_KEX; ++ break; ++ case SSH_SESSION_STATE_INITIAL_KEX: ++ /* TODO: This state should disappear in favor of get_key handle */ ++ break; ++ case SSH_SESSION_STATE_KEXINIT_RECEIVED: ++ set_status(session, 0.6f); ++ ssh_list_kex(&session->next_crypto->server_kex); ++ if ((session->flags & SSH_SESSION_FLAG_KEXINIT_SENT) == 0) { ++ /* in rekeying state if next_crypto client_kex might be empty */ + rc = ssh_set_client_kex(session); + if (rc != SSH_OK) { + goto error; + } +- rc = ssh_send_kex(session, 0); ++ rc = ssh_send_kex(session); + if (rc < 0) { + goto error; + } +- set_status(session, 0.5f); ++ } ++ if (ssh_kex_select_methods(session) == SSH_ERROR) ++ goto error; ++ set_status(session, 0.8f); ++ session->session_state = SSH_SESSION_STATE_DH; + +- break; +- case SSH_SESSION_STATE_INITIAL_KEX: +- /* TODO: This state should disappear in favor of get_key handle */ +- break; +- case SSH_SESSION_STATE_KEXINIT_RECEIVED: +- set_status(session,0.6f); +- ssh_list_kex(&session->next_crypto->server_kex); +- if (session->next_crypto->client_kex.methods[0] == NULL) { +- /* in rekeying state if next_crypto client_kex is empty */ +- rc = ssh_set_client_kex(session); +- if (rc != SSH_OK) { +- goto error; +- } +- rc = ssh_send_kex(session, 0); +- if (rc < 0) { +- goto error; +- } +- } +- if (ssh_kex_select_methods(session) == SSH_ERROR) +- goto error; +- set_status(session,0.8f); +- session->session_state=SSH_SESSION_STATE_DH; +- if (dh_handshake(session) == SSH_ERROR) { +- goto error; +- } +- FALL_THROUGH; +- case SSH_SESSION_STATE_DH: +- if(session->dh_handshake_state==DH_STATE_FINISHED){ +- set_status(session,1.0f); +- session->connected = 1; +- if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED) +- session->session_state = SSH_SESSION_STATE_AUTHENTICATED; +- else +- session->session_state=SSH_SESSION_STATE_AUTHENTICATING; +- } +- break; +- case SSH_SESSION_STATE_AUTHENTICATING: +- break; +- case SSH_SESSION_STATE_ERROR: ++ /* If the init packet was already sent in previous step, this will be no ++ * operation */ ++ if (dh_handshake(session) == SSH_ERROR) { + goto error; +- default: +- ssh_set_error(session,SSH_FATAL,"Invalid state %d",session->session_state); ++ } ++ FALL_THROUGH; ++ case SSH_SESSION_STATE_DH: ++ if (session->dh_handshake_state == DH_STATE_FINISHED) { ++ set_status(session, 1.0f); ++ session->connected = 1; ++ if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED) ++ session->session_state = SSH_SESSION_STATE_AUTHENTICATED; ++ else ++ session->session_state=SSH_SESSION_STATE_AUTHENTICATING; ++ } ++ break; ++ case SSH_SESSION_STATE_AUTHENTICATING: ++ break; ++ case SSH_SESSION_STATE_ERROR: ++ goto error; ++ default: ++ ssh_set_error(session, SSH_FATAL, "Invalid state %d", ++ session->session_state); + } + + return; + error: + ssh_socket_close(session->socket); + session->alive = 0; +- session->session_state=SSH_SESSION_STATE_ERROR; +- SSH_LOG(SSH_LOG_WARN, "%s", ssh_get_error(session)); ++ session->session_state = SSH_SESSION_STATE_ERROR; ++ + } + + /** @internal +diff --color -ru ../libssh-0.9.6/src/curve25519.c ./src/curve25519.c +--- ../libssh-0.9.6/src/curve25519.c 2023-04-27 12:22:39.797925403 +0200 ++++ ./src/curve25519.c 2023-04-27 12:24:04.680475778 +0200 +@@ -172,6 +172,11 @@ + return rc; + } + ++void ssh_client_curve25519_remove_callbacks(ssh_session session) ++{ ++ ssh_packet_remove_callbacks(session, &ssh_curve25519_client_callbacks); ++} ++ + static int ssh_curve25519_build_k(ssh_session session) + { + ssh_curve25519_pubkey k; +@@ -285,7 +290,7 @@ + (void)type; + (void)user; + +- ssh_packet_remove_callbacks(session, &ssh_curve25519_client_callbacks); ++ ssh_client_curve25519_remove_callbacks(session); + + pubkey_blob = ssh_buffer_get_ssh_string(packet); + if (pubkey_blob == NULL) { +diff --color -ru ../libssh-0.9.6/src/dh.c ./src/dh.c +--- ../libssh-0.9.6/src/dh.c 2023-04-27 12:22:39.798925404 +0200 ++++ ./src/dh.c 2023-04-27 12:24:04.680475778 +0200 +@@ -342,6 +342,11 @@ + return SSH_ERROR; + } + ++void ssh_client_dh_remove_callbacks(ssh_session session) ++{ ++ ssh_packet_remove_callbacks(session, &ssh_dh_client_callbacks); ++} ++ + SSH_PACKET_CALLBACK(ssh_packet_client_dh_reply){ + struct ssh_crypto_struct *crypto=session->next_crypto; + ssh_string pubkey_blob = NULL; +@@ -351,7 +356,7 @@ + (void)type; + (void)user; + +- ssh_packet_remove_callbacks(session, &ssh_dh_client_callbacks); ++ ssh_client_dh_remove_callbacks(session); + + rc = ssh_buffer_unpack(packet, "SBS", &pubkey_blob, &server_pubkey, + &crypto->dh_server_signature); +diff --color -ru ../libssh-0.9.6/src/dh-gex.c ./src/dh-gex.c +--- ../libssh-0.9.6/src/dh-gex.c 2023-04-27 12:22:39.797925403 +0200 ++++ ./src/dh-gex.c 2023-04-27 12:24:04.680475778 +0200 +@@ -238,6 +238,11 @@ + return SSH_PACKET_USED; + } + ++void ssh_client_dhgex_remove_callbacks(ssh_session session) ++{ ++ ssh_packet_remove_callbacks(session, &ssh_dhgex_client_callbacks); ++} ++ + static SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_reply) + { + struct ssh_crypto_struct *crypto=session->next_crypto; +@@ -248,7 +253,7 @@ + (void)user; + SSH_LOG(SSH_LOG_DEBUG, "SSH_MSG_KEX_DH_GEX_REPLY received"); + +- ssh_packet_remove_callbacks(session, &ssh_dhgex_client_callbacks); ++ ssh_client_dhgex_remove_callbacks(session); + rc = ssh_buffer_unpack(packet, + "SBS", + &pubkey_blob, &server_pubkey, +diff --color -ru ../libssh-0.9.6/src/ecdh.c ./src/ecdh.c +--- ../libssh-0.9.6/src/ecdh.c 2023-04-27 12:22:39.798925404 +0200 ++++ ./src/ecdh.c 2023-04-27 12:24:04.680475778 +0200 +@@ -43,6 +43,11 @@ + .user = NULL + }; + ++void ssh_client_ecdh_remove_callbacks(ssh_session session) ++{ ++ ssh_packet_remove_callbacks(session, &ssh_ecdh_client_callbacks); ++} ++ + /** @internal + * @brief parses a SSH_MSG_KEX_ECDH_REPLY packet and sends back + * a SSH_MSG_NEWKEYS +@@ -55,7 +60,7 @@ + (void)type; + (void)user; + +- ssh_packet_remove_callbacks(session, &ssh_ecdh_client_callbacks); ++ ssh_client_ecdh_remove_callbacks(session); + pubkey_blob = ssh_buffer_get_ssh_string(packet); + if (pubkey_blob == NULL) { + ssh_set_error(session,SSH_FATAL, "No public key in packet"); +diff --color -ru ../libssh-0.9.6/src/gssapi.c ./src/gssapi.c +--- ../libssh-0.9.6/src/gssapi.c 2023-04-27 12:22:39.798925404 +0200 ++++ ./src/gssapi.c 2023-04-27 12:24:04.681475778 +0200 +@@ -223,6 +223,7 @@ + "indicate mechs", + maj_stat, + min_stat); ++ gss_release_oid_set(&min_stat, &both_supported); + return SSH_ERROR; + } + +@@ -259,8 +260,10 @@ + return SSH_OK; + } + /* from now we have room for context */ +- if (ssh_gssapi_init(session) == SSH_ERROR) ++ if (ssh_gssapi_init(session) == SSH_ERROR) { ++ gss_release_oid_set(&min_stat, &both_supported); + return SSH_ERROR; ++ } + + name_buf.value = service_name; + name_buf.length = strlen(name_buf.value) + 1; +@@ -272,6 +275,7 @@ + "importing name", + maj_stat, + min_stat); ++ gss_release_oid_set(&min_stat, &both_supported); + return -1; + } + +@@ -338,6 +342,7 @@ + min_stat); + ptr = malloc(buffer.length + 1); + if (ptr == NULL) { ++ gss_release_buffer(&min_stat, &buffer); + return NULL; + } + memcpy(ptr, buffer.value, buffer.length); +@@ -421,6 +426,7 @@ + "Gssapi error", + maj_stat, + min_stat); ++ gss_release_buffer(&min_stat, &output_token); + ssh_auth_reply_default(session,0); + ssh_gssapi_free(session); + session->gssapi=NULL; +@@ -438,6 +444,9 @@ + (size_t)output_token.length, output_token.value); + ssh_packet_send(session); + } ++ ++ gss_release_buffer(&min_stat, &output_token); ++ + if(maj_stat == GSS_S_COMPLETE){ + session->gssapi->state = SSH_GSSAPI_STATE_RCV_MIC; + } +@@ -638,7 +647,7 @@ + static int ssh_gssapi_match(ssh_session session, gss_OID_set *valid_oids) + { + OM_uint32 maj_stat, min_stat, lifetime; +- gss_OID_set actual_mechs; ++ gss_OID_set actual_mechs = GSS_C_NO_OID_SET; + gss_buffer_desc namebuf; + gss_name_t client_id = GSS_C_NO_NAME; + gss_OID oid; +@@ -700,6 +709,7 @@ + ret = SSH_OK; + + end: ++ gss_release_oid_set(&min_stat, &actual_mechs); + gss_release_name(&min_stat, &client_id); + return ret; + } +@@ -713,7 +723,7 @@ + */ + int ssh_gssapi_auth_mic(ssh_session session){ + size_t i; +- gss_OID_set selected; /* oid selected for authentication */ ++ gss_OID_set selected = GSS_C_NO_OID_SET; /* oid selected for authentication */ + ssh_string *oids = NULL; + int rc; + size_t n_oids = 0; +@@ -790,6 +800,8 @@ + SSH_STRING_FREE(oids[i]); + } + free(oids); ++ gss_release_oid_set(&min_stat, &selected); ++ + if (rc != SSH_ERROR) { + return SSH_AUTH_AGAIN; + } +@@ -893,6 +905,8 @@ + ssh_packet_send(session); + session->auth.state = SSH_AUTH_STATE_GSSAPI_TOKEN; + } ++ ++ gss_release_buffer(&min_stat, &output_token); + return SSH_PACKET_USED; + + error: +@@ -921,8 +935,10 @@ + + maj_stat = gss_get_mic(&min_stat,session->gssapi->ctx, GSS_C_QOP_DEFAULT, + &mic_buf, &mic_token_buf); ++ ++ SSH_BUFFER_FREE(mic_buffer); ++ + if (GSS_ERROR(maj_stat)){ +- SSH_BUFFER_FREE(mic_buffer); + ssh_gssapi_log_error(SSH_LOG_DEBUG, + "generating MIC", + maj_stat, +@@ -935,8 +951,10 @@ + SSH2_MSG_USERAUTH_GSSAPI_MIC, + mic_token_buf.length, + (size_t)mic_token_buf.length, mic_token_buf.value); ++ ++ gss_release_buffer(&min_stat, &mic_token_buf); ++ + if (rc != SSH_OK) { +- SSH_BUFFER_FREE(mic_buffer); + ssh_set_error_oom(session); + return SSH_ERROR; + } +@@ -1005,6 +1023,8 @@ + ssh_packet_send(session); + } + ++ gss_release_buffer(&min_stat, &output_token); ++ + if (maj_stat == GSS_S_COMPLETE) { + ssh_gssapi_send_mic(session); + session->auth.state = SSH_AUTH_STATE_GSSAPI_MIC_SENT; +diff --color -ru ../libssh-0.9.6/src/kex.c ./src/kex.c +--- ../libssh-0.9.6/src/kex.c 2023-04-27 12:22:39.798925404 +0200 ++++ ./src/kex.c 2023-04-27 12:24:08.450478574 +0200 +@@ -28,6 +28,7 @@ + #include + #include + ++#include "libssh/libssh.h" + #include "libssh/priv.h" + #include "libssh/buffer.h" + #include "libssh/dh.h" +@@ -305,6 +306,10 @@ + + int is_wrong = 1; + ++ if (client_str == NULL || server_str == NULL) { ++ return is_wrong; ++ } ++ + colon = strchr(client_str, ','); + if (colon == NULL) { + client_kex_len = strlen(client_str); +@@ -331,6 +336,7 @@ + SSH_PACKET_CALLBACK(ssh_packet_kexinit) + { + int i, ok; ++ struct ssh_crypto_struct *crypto = session->next_crypto; + int server_kex = session->server; + ssh_string str = NULL; + char *strings[SSH_KEX_METHODS] = {0}; +@@ -344,35 +350,67 @@ + (void)type; + (void)user; + ++ SSH_LOG(SSH_LOG_TRACE, "KEXINIT received"); ++ + if (session->session_state == SSH_SESSION_STATE_AUTHENTICATED) { +- SSH_LOG(SSH_LOG_DEBUG, "Initiating key re-exchange"); ++ if (session->dh_handshake_state == DH_STATE_FINISHED) { ++ SSH_LOG(SSH_LOG_DEBUG, "Peer initiated key re-exchange"); ++ /* Reset the sent flag if the re-kex was initiated by the peer */ ++ session->flags &= ~SSH_SESSION_FLAG_KEXINIT_SENT; ++ } else if (session->flags & SSH_SESSION_FLAG_KEXINIT_SENT && ++ session->dh_handshake_state == DH_STATE_INIT_SENT) { ++ /* This happens only when we are sending our-guessed first kex ++ * packet right after our KEXINIT packet. */ ++ SSH_LOG(SSH_LOG_DEBUG, "Received peer kexinit answer."); ++ } else if (session->session_state != SSH_SESSION_STATE_INITIAL_KEX) { ++ ssh_set_error(session, SSH_FATAL, ++ "SSH_KEXINIT received in wrong state"); ++ goto error; ++ } + } else if (session->session_state != SSH_SESSION_STATE_INITIAL_KEX) { +- ssh_set_error(session,SSH_FATAL,"SSH_KEXINIT received in wrong state"); ++ ssh_set_error(session, SSH_FATAL, ++ "SSH_KEXINIT received in wrong state"); + goto error; + } + + if (server_kex) { +- len = ssh_buffer_get_data(packet,session->next_crypto->client_kex.cookie, 16); ++#ifdef WITH_SERVER ++ len = ssh_buffer_get_data(packet, crypto->client_kex.cookie, 16); + if (len != 16) { +- ssh_set_error(session, SSH_FATAL, "ssh_packet_kexinit: no cookie in packet"); ++ ssh_set_error(session, SSH_FATAL, ++ "ssh_packet_kexinit: no cookie in packet"); + goto error; + } + +- ok = ssh_hashbufin_add_cookie(session, session->next_crypto->client_kex.cookie); ++ ok = ssh_hashbufin_add_cookie(session, crypto->client_kex.cookie); + if (ok < 0) { +- ssh_set_error(session, SSH_FATAL, "ssh_packet_kexinit: adding cookie failed"); ++ ssh_set_error(session, SSH_FATAL, ++ "ssh_packet_kexinit: adding cookie failed"); ++ goto error; ++ } ++ ++ ok = server_set_kex(session); ++ if (ok == SSH_ERROR) { + goto error; + } ++#endif + } else { +- len = ssh_buffer_get_data(packet,session->next_crypto->server_kex.cookie, 16); ++ len = ssh_buffer_get_data(packet, crypto->server_kex.cookie, 16); + if (len != 16) { +- ssh_set_error(session, SSH_FATAL, "ssh_packet_kexinit: no cookie in packet"); ++ ssh_set_error(session, SSH_FATAL, ++ "ssh_packet_kexinit: no cookie in packet"); + goto error; + } + +- ok = ssh_hashbufin_add_cookie(session, session->next_crypto->server_kex.cookie); ++ ok = ssh_hashbufin_add_cookie(session, crypto->server_kex.cookie); + if (ok < 0) { +- ssh_set_error(session, SSH_FATAL, "ssh_packet_kexinit: adding cookie failed"); ++ ssh_set_error(session, SSH_FATAL, ++ "ssh_packet_kexinit: adding cookie failed"); ++ goto error; ++ } ++ ++ ok = ssh_set_client_kex(session); ++ if (ok == SSH_ERROR) { + goto error; + } + } +@@ -385,7 +423,8 @@ + + rc = ssh_buffer_add_ssh_string(session->in_hashbuf, str); + if (rc < 0) { +- ssh_set_error(session, SSH_FATAL, "Error adding string in hash buffer"); ++ ssh_set_error(session, SSH_FATAL, ++ "Error adding string in hash buffer"); + goto error; + } + +@@ -398,14 +437,14 @@ + str = NULL; + } + +- /* copy the server kex info into an array of strings */ ++ /* copy the peer kex info into an array of strings */ + if (server_kex) { + for (i = 0; i < SSH_KEX_METHODS; i++) { +- session->next_crypto->client_kex.methods[i] = strings[i]; ++ crypto->client_kex.methods[i] = strings[i]; + } + } else { /* client */ + for (i = 0; i < SSH_KEX_METHODS; i++) { +- session->next_crypto->server_kex.methods[i] = strings[i]; ++ crypto->server_kex.methods[i] = strings[i]; + } + } + +@@ -419,30 +458,48 @@ + * that its value is included when computing the session ID (see + * 'make_sessionid'). + */ +- if (server_kex) { +- rc = ssh_buffer_get_u8(packet, &first_kex_packet_follows); +- if (rc != 1) { +- goto error; +- } ++ rc = ssh_buffer_get_u8(packet, &first_kex_packet_follows); ++ if (rc != 1) { ++ goto error; ++ } + +- rc = ssh_buffer_add_u8(session->in_hashbuf, first_kex_packet_follows); +- if (rc < 0) { +- goto error; +- } ++ rc = ssh_buffer_add_u8(session->in_hashbuf, first_kex_packet_follows); ++ if (rc < 0) { ++ goto error; ++ } + +- rc = ssh_buffer_add_u32(session->in_hashbuf, kexinit_reserved); +- if (rc < 0) { +- goto error; +- } ++ rc = ssh_buffer_add_u32(session->in_hashbuf, kexinit_reserved); ++ if (rc < 0) { ++ goto error; ++ } ++ ++ /* ++ * Remember whether 'first_kex_packet_follows' was set and the client ++ * guess was wrong: in this case the next SSH_MSG_KEXDH_INIT message ++ * must be ignored on the server side. ++ * Client needs to start the Key exchange over with the correct method ++ */ ++ if (first_kex_packet_follows || session->send_first_kex_follows) { ++ char **client_methods = crypto->client_kex.methods; ++ char **server_methods = crypto->server_kex.methods; ++ session->first_kex_follows_guess_wrong = ++ cmp_first_kex_algo(client_methods[SSH_KEX], ++ server_methods[SSH_KEX]) || ++ cmp_first_kex_algo(client_methods[SSH_HOSTKEYS], ++ server_methods[SSH_HOSTKEYS]); ++ SSH_LOG(SSH_LOG_DEBUG, "The initial guess was %s.", ++ session->first_kex_follows_guess_wrong ? "wrong" : "right"); ++ } + ++ if (server_kex) { + /* + * If client sent a ext-info-c message in the kex list, it supports + * RFC 8308 extension negotiation. + */ +- ok = ssh_match_group(session->next_crypto->client_kex.methods[SSH_KEX], ++ ok = ssh_match_group(crypto->client_kex.methods[SSH_KEX], + KEX_EXTENSION_CLIENT); + if (ok) { +- const char *hostkeys = NULL; ++ const char *hostkeys = NULL, *wanted_hostkeys = NULL; + + /* The client supports extension negotiation */ + session->extensions |= SSH_EXT_NEGOTIATION; +@@ -452,14 +509,14 @@ + * by the client and enable the respective extensions to provide + * correct signature in the next packet if RSA is negotiated + */ +- hostkeys = session->next_crypto->client_kex.methods[SSH_HOSTKEYS]; ++ hostkeys = crypto->client_kex.methods[SSH_HOSTKEYS]; ++ wanted_hostkeys = session->opts.wanted_methods[SSH_HOSTKEYS]; + ok = ssh_match_group(hostkeys, "rsa-sha2-512"); + if (ok) { + /* Check if rsa-sha2-512 is allowed by config */ +- if (session->opts.wanted_methods[SSH_HOSTKEYS] != NULL) { +- char *is_allowed = +- ssh_find_matching(session->opts.wanted_methods[SSH_HOSTKEYS], +- "rsa-sha2-512"); ++ if (wanted_hostkeys != NULL) { ++ char *is_allowed = ssh_find_matching(wanted_hostkeys, ++ "rsa-sha2-512"); + if (is_allowed != NULL) { + session->extensions |= SSH_EXT_SIG_RSA_SHA512; + } +@@ -469,10 +526,9 @@ + ok = ssh_match_group(hostkeys, "rsa-sha2-256"); + if (ok) { + /* Check if rsa-sha2-256 is allowed by config */ +- if (session->opts.wanted_methods[SSH_HOSTKEYS] != NULL) { +- char *is_allowed = +- ssh_find_matching(session->opts.wanted_methods[SSH_HOSTKEYS], +- "rsa-sha2-256"); ++ if (wanted_hostkeys != NULL) { ++ char *is_allowed = ssh_find_matching(wanted_hostkeys, ++ "rsa-sha2-256"); + if (is_allowed != NULL) { + session->extensions |= SSH_EXT_SIG_RSA_SHA256; + } +@@ -488,7 +544,7 @@ + (session->extensions & SSH_EXT_SIG_RSA_SHA512)) { + session->extensions &= ~(SSH_EXT_SIG_RSA_SHA256 | SSH_EXT_SIG_RSA_SHA512); + rsa_sig_ext = ssh_find_matching("rsa-sha2-512,rsa-sha2-256", +- session->next_crypto->client_kex.methods[SSH_HOSTKEYS]); ++ hostkeys); + if (rsa_sig_ext == NULL) { + goto error; /* should never happen */ + } else if (strcmp(rsa_sig_ext, "rsa-sha2-512") == 0) { +@@ -507,24 +563,16 @@ + session->extensions & SSH_EXT_SIG_RSA_SHA256 ? "SHA256" : "", + session->extensions & SSH_EXT_SIG_RSA_SHA512 ? " SHA512" : ""); + } +- +- /* +- * Remember whether 'first_kex_packet_follows' was set and the client +- * guess was wrong: in this case the next SSH_MSG_KEXDH_INIT message +- * must be ignored. +- */ +- if (first_kex_packet_follows) { +- session->first_kex_follows_guess_wrong = +- cmp_first_kex_algo(session->next_crypto->client_kex.methods[SSH_KEX], +- session->next_crypto->server_kex.methods[SSH_KEX]) || +- cmp_first_kex_algo(session->next_crypto->client_kex.methods[SSH_HOSTKEYS], +- session->next_crypto->server_kex.methods[SSH_HOSTKEYS]); +- } + } + + /* Note, that his overwrites authenticated state in case of rekeying */ + session->session_state = SSH_SESSION_STATE_KEXINIT_RECEIVED; +- session->dh_handshake_state = DH_STATE_INIT; ++ /* if we already sent our initial key exchange packet, do not reset the ++ * DH state. We will know if we were right with our guess only in ++ * dh_handshake_state() */ ++ if (session->send_first_kex_follows == false) { ++ session->dh_handshake_state = DH_STATE_INIT; ++ } + session->ssh_connection_callback(session); + return SSH_PACKET_USED; + +@@ -672,14 +720,18 @@ + int i; + size_t kex_len, len; + ++ /* Skip if already set, for example for the rekey or when we do the guessing ++ * it could have been already used to make some protocol decisions. */ ++ if (client->methods[0] != NULL) { ++ return SSH_OK; ++ } ++ + ok = ssh_get_random(client->cookie, 16, 0); + if (!ok) { + ssh_set_error(session, SSH_FATAL, "PRNG error"); + return SSH_ERROR; + } + +- memset(client->methods, 0, SSH_KEX_METHODS * sizeof(char **)); +- + /* Set the list of allowed algorithms in order of preference, if it hadn't + * been set yet. */ + for (i = 0; i < SSH_KEX_METHODS; i++) { +@@ -749,15 +801,89 @@ + return NULL; + } + ++static enum ssh_key_exchange_e ++kex_select_kex_type(const char *kex) ++{ ++ if (strcmp(kex, "diffie-hellman-group1-sha1") == 0) { ++ return SSH_KEX_DH_GROUP1_SHA1; ++ } else if (strcmp(kex, "diffie-hellman-group14-sha1") == 0) { ++ return SSH_KEX_DH_GROUP14_SHA1; ++ } else if (strcmp(kex, "diffie-hellman-group14-sha256") == 0) { ++ return SSH_KEX_DH_GROUP14_SHA256; ++ } else if (strcmp(kex, "diffie-hellman-group16-sha512") == 0) { ++ return SSH_KEX_DH_GROUP16_SHA512; ++ } else if (strcmp(kex, "diffie-hellman-group18-sha512") == 0) { ++ return SSH_KEX_DH_GROUP18_SHA512; ++#ifdef WITH_GEX ++ } else if (strcmp(kex, "diffie-hellman-group-exchange-sha1") == 0) { ++ return SSH_KEX_DH_GEX_SHA1; ++ } else if (strcmp(kex, "diffie-hellman-group-exchange-sha256") == 0) { ++ return SSH_KEX_DH_GEX_SHA256; ++#endif /* WITH_GEX */ ++ } else if (strcmp(kex, "ecdh-sha2-nistp256") == 0) { ++ return SSH_KEX_ECDH_SHA2_NISTP256; ++ } else if (strcmp(kex, "ecdh-sha2-nistp384") == 0) { ++ return SSH_KEX_ECDH_SHA2_NISTP384; ++ } else if (strcmp(kex, "ecdh-sha2-nistp521") == 0) { ++ return SSH_KEX_ECDH_SHA2_NISTP521; ++ } else if (strcmp(kex, "curve25519-sha256@libssh.org") == 0) { ++ return SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG; ++ } else if (strcmp(kex, "curve25519-sha256") == 0) { ++ return SSH_KEX_CURVE25519_SHA256; ++ } ++ /* should not happen. We should be getting only valid names at this stage */ ++ return 0; ++} ++ ++ ++/** @internal ++ * @brief Reverts guessed callbacks set during the dh_handshake() ++ * @param session session handle ++ * @returns void ++ */ ++static void revert_kex_callbacks(ssh_session session) ++{ ++ switch (session->next_crypto->kex_type) { ++ case SSH_KEX_DH_GROUP1_SHA1: ++ case SSH_KEX_DH_GROUP14_SHA1: ++ case SSH_KEX_DH_GROUP14_SHA256: ++ case SSH_KEX_DH_GROUP16_SHA512: ++ case SSH_KEX_DH_GROUP18_SHA512: ++ ssh_client_dh_remove_callbacks(session); ++ break; ++#ifdef WITH_GEX ++ case SSH_KEX_DH_GEX_SHA1: ++ case SSH_KEX_DH_GEX_SHA256: ++ ssh_client_dhgex_remove_callbacks(session); ++ break; ++#endif /* WITH_GEX */ ++#ifdef HAVE_ECDH ++ case SSH_KEX_ECDH_SHA2_NISTP256: ++ case SSH_KEX_ECDH_SHA2_NISTP384: ++ case SSH_KEX_ECDH_SHA2_NISTP521: ++ ssh_client_ecdh_remove_callbacks(session); ++ break; ++#endif ++#ifdef HAVE_CURVE25519 ++ case SSH_KEX_CURVE25519_SHA256: ++ case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG: ++ ssh_client_curve25519_remove_callbacks(session); ++ break; ++#endif ++ } ++} ++ + /** @brief Select the different methods on basis of client's and + * server's kex messages, and watches out if a match is possible. + */ + int ssh_kex_select_methods (ssh_session session) + { +- struct ssh_kex_struct *server = &session->next_crypto->server_kex; +- struct ssh_kex_struct *client = &session->next_crypto->client_kex; ++ struct ssh_crypto_struct *crypto = session->next_crypto; ++ struct ssh_kex_struct *server = &crypto->server_kex; ++ struct ssh_kex_struct *client = &crypto->client_kex; + char *ext_start = NULL; + const char *aead_hmac = NULL; ++ enum ssh_key_exchange_e kex_type; + int i; + + /* Here we should drop the ext-info-c from the list so we avoid matching. +@@ -768,52 +894,41 @@ + } + + for (i = 0; i < SSH_KEX_METHODS; i++) { +- session->next_crypto->kex_methods[i]=ssh_find_matching(server->methods[i],client->methods[i]); ++ crypto->kex_methods[i] = ssh_find_matching(server->methods[i], ++ client->methods[i]); + + if (i == SSH_MAC_C_S || i == SSH_MAC_S_C) { +- aead_hmac = ssh_find_aead_hmac(session->next_crypto->kex_methods[i-2]); ++ aead_hmac = ssh_find_aead_hmac(crypto->kex_methods[i - 2]); + if (aead_hmac) { +- free(session->next_crypto->kex_methods[i]); +- session->next_crypto->kex_methods[i] = strdup(aead_hmac); ++ free(crypto->kex_methods[i]); ++ crypto->kex_methods[i] = strdup(aead_hmac); + } + } +- if (session->next_crypto->kex_methods[i] == NULL && i < SSH_LANG_C_S){ +- ssh_set_error(session,SSH_FATAL,"kex error : no match for method %s: server [%s], client [%s]", +- ssh_kex_descriptions[i],server->methods[i],client->methods[i]); ++ if (crypto->kex_methods[i] == NULL && i < SSH_LANG_C_S) { ++ ssh_set_error(session, SSH_FATAL, ++ "kex error : no match for method %s: server [%s], " ++ "client [%s]", ssh_kex_descriptions[i], ++ server->methods[i], client->methods[i]); + return SSH_ERROR; +- } else if ((i >= SSH_LANG_C_S) && (session->next_crypto->kex_methods[i] == NULL)) { ++ } else if ((i >= SSH_LANG_C_S) && (crypto->kex_methods[i] == NULL)) { + /* we can safely do that for languages */ +- session->next_crypto->kex_methods[i] = strdup(""); ++ crypto->kex_methods[i] = strdup(""); + } + } +- if (strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group1-sha1") == 0){ +- session->next_crypto->kex_type=SSH_KEX_DH_GROUP1_SHA1; +- } else if (strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group14-sha1") == 0){ +- session->next_crypto->kex_type=SSH_KEX_DH_GROUP14_SHA1; +- } else if (strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group14-sha256") == 0){ +- session->next_crypto->kex_type=SSH_KEX_DH_GROUP14_SHA256; +- } else if (strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group16-sha512") == 0){ +- session->next_crypto->kex_type=SSH_KEX_DH_GROUP16_SHA512; +- } else if (strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group18-sha512") == 0){ +- session->next_crypto->kex_type=SSH_KEX_DH_GROUP18_SHA512; +-#ifdef WITH_GEX +- } else if (strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group-exchange-sha1") == 0){ +- session->next_crypto->kex_type=SSH_KEX_DH_GEX_SHA1; +- } else if (strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group-exchange-sha256") == 0){ +- session->next_crypto->kex_type=SSH_KEX_DH_GEX_SHA256; +-#endif /* WITH_GEX */ +- } else if (strcmp(session->next_crypto->kex_methods[SSH_KEX], "ecdh-sha2-nistp256") == 0){ +- session->next_crypto->kex_type=SSH_KEX_ECDH_SHA2_NISTP256; +- } else if (strcmp(session->next_crypto->kex_methods[SSH_KEX], "ecdh-sha2-nistp384") == 0){ +- session->next_crypto->kex_type=SSH_KEX_ECDH_SHA2_NISTP384; +- } else if (strcmp(session->next_crypto->kex_methods[SSH_KEX], "ecdh-sha2-nistp521") == 0){ +- session->next_crypto->kex_type=SSH_KEX_ECDH_SHA2_NISTP521; +- } else if (strcmp(session->next_crypto->kex_methods[SSH_KEX], "curve25519-sha256@libssh.org") == 0){ +- session->next_crypto->kex_type=SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG; +- } else if (strcmp(session->next_crypto->kex_methods[SSH_KEX], "curve25519-sha256") == 0){ +- session->next_crypto->kex_type=SSH_KEX_CURVE25519_SHA256; ++ ++ /* We can not set this value directly as the old value is needed to revert ++ * callbacks if we are client */ ++ kex_type = kex_select_kex_type(crypto->kex_methods[SSH_KEX]); ++ if (session->client && session->first_kex_follows_guess_wrong) { ++ SSH_LOG(SSH_LOG_DEBUG, "Our guess was wrong. Restarting the KEX"); ++ /* We need to remove the wrong callbacks and start kex again */ ++ revert_kex_callbacks(session); ++ session->dh_handshake_state = DH_STATE_INIT; ++ session->first_kex_follows_guess_wrong = false; + } +- SSH_LOG(SSH_LOG_DEBUG, "Negotiated %s,%s,%s,%s,%s,%s,%s,%s,%s,%s", ++ crypto->kex_type = kex_type; ++ ++ SSH_LOG(SSH_LOG_DEBUG, "Negotiated %s,%s,%s,%s,%s,%s,%s,%s,%s,%s", + session->next_crypto->kex_methods[SSH_KEX], + session->next_crypto->kex_methods[SSH_HOSTKEYS], + session->next_crypto->kex_methods[SSH_CRYPT_C_S], +@@ -830,63 +945,116 @@ + + + /* this function only sends the predefined set of kex methods */ +-int ssh_send_kex(ssh_session session, int server_kex) ++int ssh_send_kex(ssh_session session) + { +- struct ssh_kex_struct *kex = (server_kex ? &session->next_crypto->server_kex : +- &session->next_crypto->client_kex); +- ssh_string str = NULL; +- int i; +- int rc; +- +- rc = ssh_buffer_pack(session->out_buffer, +- "bP", +- SSH2_MSG_KEXINIT, +- 16, +- kex->cookie); /* cookie */ +- if (rc != SSH_OK) +- goto error; +- if (ssh_hashbufout_add_cookie(session) < 0) { +- goto error; +- } ++ struct ssh_kex_struct *kex = (session->server ? ++ &session->next_crypto->server_kex : ++ &session->next_crypto->client_kex); ++ ssh_string str = NULL; ++ int i; ++ int rc; ++ int first_kex_packet_follows = 0; ++ ++ /* Only client can initiate the handshake methods we implement. If we ++ * already received the peer mechanisms, there is no point in guessing */ ++ if (session->client && ++ session->session_state != SSH_SESSION_STATE_KEXINIT_RECEIVED && ++ session->send_first_kex_follows) { ++ first_kex_packet_follows = 1; ++ } ++ ++ SSH_LOG(SSH_LOG_TRACE, ++ "Sending KEXINIT packet, first_kex_packet_follows = %d", ++ first_kex_packet_follows); ++ ++ rc = ssh_buffer_pack(session->out_buffer, ++ "bP", ++ SSH2_MSG_KEXINIT, ++ 16, ++ kex->cookie); /* cookie */ ++ if (rc != SSH_OK) ++ goto error; ++ if (ssh_hashbufout_add_cookie(session) < 0) { ++ goto error; ++ } ++ ++ ssh_list_kex(kex); + +- ssh_list_kex(kex); ++ for (i = 0; i < SSH_KEX_METHODS; i++) { ++ str = ssh_string_from_char(kex->methods[i]); ++ if (str == NULL) { ++ goto error; ++ } ++ ++ rc = ssh_buffer_add_ssh_string(session->out_hashbuf, str); ++ if (rc < 0) { ++ goto error; ++ } ++ rc = ssh_buffer_add_ssh_string(session->out_buffer, str); ++ if (rc < 0) { ++ goto error; ++ } ++ SSH_STRING_FREE(str); ++ str = NULL; ++ } + +- for (i = 0; i < SSH_KEX_METHODS; i++) { +- str = ssh_string_from_char(kex->methods[i]); +- if (str == NULL) { +- goto error; ++ rc = ssh_buffer_pack(session->out_buffer, ++ "bd", ++ first_kex_packet_follows, ++ 0); ++ if (rc != SSH_OK) { ++ goto error; + } + +- if (ssh_buffer_add_ssh_string(session->out_hashbuf, str) < 0) { +- goto error; ++ /* Prepare also the first_kex_packet_follows and reserved to 0 */ ++ rc = ssh_buffer_add_u8(session->out_hashbuf, first_kex_packet_follows); ++ if (rc < 0) { ++ goto error; + } +- if (ssh_buffer_add_ssh_string(session->out_buffer, str) < 0) { +- goto error; ++ rc = ssh_buffer_add_u32(session->out_hashbuf, 0); ++ if (rc < 0) { ++ goto error; + } +- SSH_STRING_FREE(str); +- str = NULL; +- } + +- rc = ssh_buffer_pack(session->out_buffer, +- "bd", +- 0, +- 0); +- if (rc != SSH_OK) { +- goto error; +- } ++ rc = ssh_packet_send(session); ++ if (rc == SSH_ERROR) { ++ return -1; ++ } + +- if (ssh_packet_send(session) == SSH_ERROR) { +- return -1; +- } ++ session->flags |= SSH_SESSION_FLAG_KEXINIT_SENT; ++ SSH_LOG(SSH_LOG_PACKET, "SSH_MSG_KEXINIT sent"); ++ ++ /* If we indicated that we are sending the guessed key exchange packet, ++ * do it now. The packet is simple, but we need to do some preparations */ ++ if (first_kex_packet_follows) { ++ char *list = kex->methods[SSH_KEX]; ++ char *colon = strchr(list, ','); ++ size_t kex_name_len = colon ? (size_t)(colon - list) : strlen(list); ++ char *kex_name = calloc(kex_name_len + 1, 1); ++ if (kex_name == NULL) { ++ ssh_set_error_oom(session); ++ goto error; ++ } ++ snprintf(kex_name, kex_name_len + 1, "%.*s", (int)kex_name_len, list); ++ SSH_LOG(SSH_LOG_TRACE, "Sending the first kex packet for %s", kex_name); ++ ++ session->next_crypto->kex_type = kex_select_kex_type(kex_name); ++ free(kex_name); ++ ++ /* run the first step of the DH handshake */ ++ session->dh_handshake_state = DH_STATE_INIT; ++ if (dh_handshake(session) == SSH_ERROR) { ++ goto error; ++ } ++ } ++ return 0; + +- SSH_LOG(SSH_LOG_PACKET, "SSH_MSG_KEXINIT sent"); +- return 0; + error: +- ssh_buffer_reinit(session->out_buffer); +- ssh_buffer_reinit(session->out_hashbuf); +- SSH_STRING_FREE(str); ++ ssh_buffer_reinit(session->out_buffer); ++ ssh_buffer_reinit(session->out_hashbuf); ++ SSH_STRING_FREE(str); + +- return -1; ++ return -1; + } + + /* +@@ -929,7 +1097,7 @@ + } + + session->dh_handshake_state = DH_STATE_INIT; +- rc = ssh_send_kex(session, session->server); ++ rc = ssh_send_kex(session); + if (rc < 0) { + SSH_LOG(SSH_LOG_PACKET, "Failed to send kex"); + return rc; +@@ -1006,33 +1174,6 @@ + client_hash = session->in_hashbuf; + } + +- /* +- * Handle the two final fields for the KEXINIT message (RFC 4253 7.1): +- * +- * boolean first_kex_packet_follows +- * uint32 0 (reserved for future extension) +- */ +- rc = ssh_buffer_add_u8(server_hash, 0); +- if (rc < 0) { +- goto error; +- } +- rc = ssh_buffer_add_u32(server_hash, 0); +- if (rc < 0) { +- goto error; +- } +- +- /* These fields are handled for the server case in ssh_packet_kexinit. */ +- if (session->client) { +- rc = ssh_buffer_add_u8(client_hash, 0); +- if (rc < 0) { +- goto error; +- } +- rc = ssh_buffer_add_u32(client_hash, 0); +- if (rc < 0) { +- goto error; +- } +- } +- + rc = ssh_dh_get_next_server_publickey_blob(session, &server_pubkey_blob); + if (rc != SSH_OK) { + goto error; +diff --color -ru ../libssh-0.9.6/src/packet.c ./src/packet.c +--- ../libssh-0.9.6/src/packet.c 2023-04-27 12:22:39.811925413 +0200 ++++ ./src/packet.c 2023-04-27 12:24:04.682475779 +0200 +@@ -366,6 +366,11 @@ + * - session->dh_handhsake_state = DH_STATE_NEWKEYS_SENT + * */ + ++ if (!session->server) { ++ rc = SSH_PACKET_DENIED; ++ break; ++ } ++ + if (session->session_state != SSH_SESSION_STATE_DH) { + rc = SSH_PACKET_DENIED; + break; +@@ -1410,18 +1415,23 @@ + } + } + +-void ssh_packet_register_socket_callback(ssh_session session, ssh_socket s){ +- session->socket_callbacks.data=ssh_packet_socket_callback; +- session->socket_callbacks.connected=NULL; +- session->socket_callbacks.controlflow = ssh_packet_socket_controlflow_callback; +- session->socket_callbacks.userdata=session; +- ssh_socket_set_callbacks(s,&session->socket_callbacks); ++void ssh_packet_register_socket_callback(ssh_session session, ssh_socket s) ++{ ++ struct ssh_socket_callbacks_struct *callbacks = &session->socket_callbacks; ++ ++ callbacks->data = ssh_packet_socket_callback; ++ callbacks->connected = NULL; ++ callbacks->controlflow = ssh_packet_socket_controlflow_callback; ++ callbacks->userdata = session; ++ ssh_socket_set_callbacks(s, callbacks); + } + + /** @internal + * @brief sets the callbacks for the packet layer + */ +-void ssh_packet_set_callbacks(ssh_session session, ssh_packet_callbacks callbacks){ ++void ++ssh_packet_set_callbacks(ssh_session session, ssh_packet_callbacks callbacks) ++{ + if (session->packet_callbacks == NULL) { + session->packet_callbacks = ssh_list_new(); + if (session->packet_callbacks == NULL) { +@@ -1435,8 +1445,11 @@ + /** @internal + * @brief remove the callbacks from the packet layer + */ +-void ssh_packet_remove_callbacks(ssh_session session, ssh_packet_callbacks callbacks){ ++void ++ssh_packet_remove_callbacks(ssh_session session, ssh_packet_callbacks callbacks) ++{ + struct ssh_iterator *it = NULL; ++ + it = ssh_list_find(session->packet_callbacks, callbacks); + if (it != NULL) { + ssh_list_remove(session->packet_callbacks, it); +@@ -1446,12 +1459,15 @@ + /** @internal + * @brief sets the default packet handlers + */ +-void ssh_packet_set_default_callbacks(ssh_session session){ +- session->default_packet_callbacks.start=1; +- session->default_packet_callbacks.n_callbacks=sizeof(default_packet_handlers)/sizeof(ssh_packet_callback); +- session->default_packet_callbacks.user=session; +- session->default_packet_callbacks.callbacks=default_packet_handlers; +- ssh_packet_set_callbacks(session, &session->default_packet_callbacks); ++void ssh_packet_set_default_callbacks(ssh_session session) ++{ ++ struct ssh_packet_callbacks_struct *c = &session->default_packet_callbacks; ++ ++ c->start = 1; ++ c->n_callbacks = sizeof(default_packet_handlers) / sizeof(ssh_packet_callback); ++ c->user = session; ++ c->callbacks = default_packet_handlers; ++ ssh_packet_set_callbacks(session, c); + } + + /** @internal +@@ -1928,7 +1944,7 @@ + memcpy(session->next_crypto->session_id, + session->current_crypto->session_id, + session_id_len); +- session->next_crypto->session_id_len = session_id_len; ++ session->next_crypto->session_id_len = session_id_len; + + return SSH_OK; + } +diff --color -ru ../libssh-0.9.6/src/packet_cb.c ./src/packet_cb.c +--- ../libssh-0.9.6/src/packet_cb.c 2023-04-27 12:22:39.799925404 +0200 ++++ ./src/packet_cb.c 2023-04-27 12:24:04.682475779 +0200 +@@ -156,6 +156,9 @@ + session->next_crypto->digest_len); + SSH_SIGNATURE_FREE(sig); + if (rc == SSH_ERROR) { ++ ssh_set_error(session, ++ SSH_FATAL, ++ "Failed to verify server hostkey signature"); + goto error; + } + SSH_LOG(SSH_LOG_DEBUG,"Signature verified and valid"); +diff --color -ru ../libssh-0.9.6/src/server.c ./src/server.c +--- ../libssh-0.9.6/src/server.c 2023-04-27 12:22:39.800925405 +0200 ++++ ./src/server.c 2023-04-27 12:24:04.683475780 +0200 +@@ -92,7 +92,11 @@ + size_t len; + int ok; + +- ZERO_STRUCTP(server); ++ /* Skip if already set, for example for the rekey or when we do the guessing ++ * it could have been already used to make some protocol decisions. */ ++ if (server->methods[0] != NULL) { ++ return SSH_OK; ++ } + + ok = ssh_get_random(server->cookie, 16, 0); + if (!ok) { +@@ -335,117 +339,121 @@ + * @brief A function to be called each time a step has been done in the + * connection. + */ +-static void ssh_server_connection_callback(ssh_session session){ ++static void ssh_server_connection_callback(ssh_session session) ++{ + int rc; + +- switch(session->session_state){ +- case SSH_SESSION_STATE_NONE: +- case SSH_SESSION_STATE_CONNECTING: +- case SSH_SESSION_STATE_SOCKET_CONNECTED: +- break; +- case SSH_SESSION_STATE_BANNER_RECEIVED: +- if (session->clientbanner == NULL) { ++ switch (session->session_state) { ++ case SSH_SESSION_STATE_NONE: ++ case SSH_SESSION_STATE_CONNECTING: ++ case SSH_SESSION_STATE_SOCKET_CONNECTED: ++ break; ++ case SSH_SESSION_STATE_BANNER_RECEIVED: ++ if (session->clientbanner == NULL) { ++ goto error; ++ } ++ set_status(session, 0.4f); ++ SSH_LOG(SSH_LOG_DEBUG, ++ "SSH client banner: %s", session->clientbanner); ++ ++ /* Here we analyze the different protocols the server allows. */ ++ rc = ssh_analyze_banner(session, 1); ++ if (rc < 0) { ++ ssh_set_error(session, SSH_FATAL, ++ "No version of SSH protocol usable (banner: %s)", ++ session->clientbanner); ++ goto error; ++ } ++ ++ /* from now, the packet layer is handling incoming packets */ ++ session->socket_callbacks.data = ssh_packet_socket_callback; ++ ssh_packet_register_socket_callback(session, session->socket); ++ ++ ssh_packet_set_default_callbacks(session); ++ set_status(session, 0.5f); ++ session->session_state = SSH_SESSION_STATE_INITIAL_KEX; ++ if (ssh_send_kex(session) < 0) { ++ goto error; ++ } ++ break; ++ case SSH_SESSION_STATE_INITIAL_KEX: ++ /* TODO: This state should disappear in favor of get_key handle */ ++ break; ++ case SSH_SESSION_STATE_KEXINIT_RECEIVED: ++ set_status(session, 0.6f); ++ if ((session->flags & SSH_SESSION_FLAG_KEXINIT_SENT) == 0) { ++ if (server_set_kex(session) == SSH_ERROR) + goto error; +- } +- set_status(session, 0.4f); +- SSH_LOG(SSH_LOG_DEBUG, +- "SSH client banner: %s", session->clientbanner); +- +- /* Here we analyze the different protocols the server allows. */ +- rc = ssh_analyze_banner(session, 1); +- if (rc < 0) { +- ssh_set_error(session, SSH_FATAL, +- "No version of SSH protocol usable (banner: %s)", +- session->clientbanner); ++ /* We are in a rekeying, so we need to send the server kex */ ++ if (ssh_send_kex(session) < 0) + goto error; +- } ++ } ++ ssh_list_kex(&session->next_crypto->client_kex); // log client kex ++ if (ssh_kex_select_methods(session) < 0) { ++ goto error; ++ } ++ if (crypt_set_algorithms_server(session) == SSH_ERROR) ++ goto error; ++ set_status(session, 0.8f); ++ session->session_state = SSH_SESSION_STATE_DH; ++ break; ++ case SSH_SESSION_STATE_DH: ++ if (session->dh_handshake_state == DH_STATE_FINISHED) { + +- /* from now, the packet layer is handling incoming packets */ +- session->socket_callbacks.data=ssh_packet_socket_callback; +- ssh_packet_register_socket_callback(session, session->socket); +- +- ssh_packet_set_default_callbacks(session); +- set_status(session, 0.5f); +- session->session_state=SSH_SESSION_STATE_INITIAL_KEX; +- if (ssh_send_kex(session, 1) < 0) { +- goto error; +- } +- break; +- case SSH_SESSION_STATE_INITIAL_KEX: +- /* TODO: This state should disappear in favor of get_key handle */ +- break; +- case SSH_SESSION_STATE_KEXINIT_RECEIVED: +- set_status(session,0.6f); +- if(session->next_crypto->server_kex.methods[0]==NULL){ +- if(server_set_kex(session) == SSH_ERROR) +- goto error; +- /* We are in a rekeying, so we need to send the server kex */ +- if(ssh_send_kex(session, 1) < 0) +- goto error; +- } +- ssh_list_kex(&session->next_crypto->client_kex); // log client kex +- if (ssh_kex_select_methods(session) < 0) { ++ rc = ssh_packet_set_newkeys(session, SSH_DIRECTION_IN); ++ if (rc != SSH_OK) { + goto error; + } +- if (crypt_set_algorithms_server(session) == SSH_ERROR) +- goto error; +- set_status(session,0.8f); +- session->session_state=SSH_SESSION_STATE_DH; +- break; +- case SSH_SESSION_STATE_DH: +- if(session->dh_handshake_state==DH_STATE_FINISHED){ +- +- rc = ssh_packet_set_newkeys(session, SSH_DIRECTION_IN); +- if (rc != SSH_OK) { +- goto error; +- } ++ ++ /* ++ * If the client supports extension negotiation, we will send ++ * our supported extensions now. This is the first message after ++ * sending NEWKEYS message and after turning on crypto. ++ */ ++ if (session->extensions & SSH_EXT_NEGOTIATION && ++ session->session_state != SSH_SESSION_STATE_AUTHENTICATED) { + + /* +- * If the client supports extension negotiation, we will send +- * our supported extensions now. This is the first message after +- * sending NEWKEYS message and after turning on crypto. ++ * Only send an SSH_MSG_EXT_INFO message the first time the ++ * client undergoes NEWKEYS. It is unexpected for this message ++ * to be sent upon rekey, and may cause clients to log error ++ * messages. ++ * ++ * The session_state can not be used for this purpose because it ++ * is re-set to SSH_SESSION_STATE_KEXINIT_RECEIVED during rekey. ++ * So, use the connected flag which transitions from non-zero ++ * below. ++ * ++ * See also: ++ * - https://bugzilla.mindrot.org/show_bug.cgi?id=2929 + */ +- if (session->extensions & SSH_EXT_NEGOTIATION && +- session->session_state != SSH_SESSION_STATE_AUTHENTICATED) { +- +- /* +- * Only send an SSH_MSG_EXT_INFO message the first time the client +- * undergoes NEWKEYS. It is unexpected for this message to be sent +- * upon rekey, and may cause clients to log error messages. +- * +- * The session_state can not be used for this purpose because it is +- * re-set to SSH_SESSION_STATE_KEXINIT_RECEIVED during rekey. So, +- * use the connected flag which transitions from non-zero below. +- * +- * See also: +- * - https://bugzilla.mindrot.org/show_bug.cgi?id=2929 +- */ +- if (session->connected == 0) { +- ssh_server_send_extensions(session); +- } ++ if (session->connected == 0) { ++ ssh_server_send_extensions(session); + } ++ } + +- set_status(session,1.0f); +- session->connected = 1; +- session->session_state=SSH_SESSION_STATE_AUTHENTICATING; +- if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED) +- session->session_state = SSH_SESSION_STATE_AUTHENTICATED; ++ set_status(session, 1.0f); ++ session->connected = 1; ++ session->session_state = SSH_SESSION_STATE_AUTHENTICATING; ++ if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED) ++ session->session_state = SSH_SESSION_STATE_AUTHENTICATED; + +- } +- break; +- case SSH_SESSION_STATE_AUTHENTICATING: +- break; +- case SSH_SESSION_STATE_ERROR: +- goto error; +- default: +- ssh_set_error(session,SSH_FATAL,"Invalid state %d",session->session_state); ++ } ++ break; ++ case SSH_SESSION_STATE_AUTHENTICATING: ++ break; ++ case SSH_SESSION_STATE_ERROR: ++ goto error; ++ default: ++ ssh_set_error(session, SSH_FATAL, "Invalid state %d", ++ session->session_state); + } + + return; + error: + ssh_socket_close(session->socket); + session->alive = 0; +- session->session_state=SSH_SESSION_STATE_ERROR; ++ session->session_state = SSH_SESSION_STATE_ERROR; + } + + /** +@@ -459,16 +467,17 @@ + * @param user is a pointer to session + * @returns Number of bytes processed, or zero if the banner is not complete. + */ +-static int callback_receive_banner(const void *data, size_t len, void *user) { +- char *buffer = (char *) data; +- ssh_session session = (ssh_session) user; ++static int callback_receive_banner(const void *data, size_t len, void *user) ++{ ++ char *buffer = (char *)data; ++ ssh_session session = (ssh_session)user; + char *str = NULL; + size_t i; + int ret=0; + + for (i = 0; i < len; i++) { + #ifdef WITH_PCAP +- if(session->pcap_ctx && buffer[i] == '\n') { ++ if (session->pcap_ctx && buffer[i] == '\n') { + ssh_pcap_context_write(session->pcap_ctx, + SSH_PCAP_DIR_IN, + buffer, +@@ -477,11 +486,11 @@ + } + #endif + if (buffer[i] == '\r') { +- buffer[i]='\0'; ++ buffer[i] = '\0'; + } + + if (buffer[i] == '\n') { +- buffer[i]='\0'; ++ buffer[i] = '\0'; + + str = strdup(buffer); + /* number of bytes read */ +@@ -494,10 +503,11 @@ + return ret; + } + +- if(i > 127) { ++ if (i > 127) { + /* Too big banner */ + session->session_state = SSH_SESSION_STATE_ERROR; +- ssh_set_error(session, SSH_FATAL, "Receiving banner: too large banner"); ++ ssh_set_error(session, SSH_FATAL, ++ "Receiving banner: too large banner"); + + return 0; + } +@@ -525,10 +535,14 @@ + } + + /* Do the banner and key exchange */ +-int ssh_handle_key_exchange(ssh_session session) { ++int ssh_handle_key_exchange(ssh_session session) ++{ + int rc; +- if (session->session_state != SSH_SESSION_STATE_NONE) +- goto pending; ++ ++ if (session->session_state != SSH_SESSION_STATE_NONE) { ++ goto pending; ++ } ++ + rc = ssh_send_banner(session, 1); + if (rc < 0) { + return SSH_ERROR; +@@ -539,27 +553,28 @@ + session->ssh_connection_callback = ssh_server_connection_callback; + session->session_state = SSH_SESSION_STATE_SOCKET_CONNECTED; + ssh_socket_set_callbacks(session->socket,&session->socket_callbacks); +- session->socket_callbacks.data=callback_receive_banner; +- session->socket_callbacks.exception=ssh_socket_exception_callback; +- session->socket_callbacks.userdata=session; ++ session->socket_callbacks.data = callback_receive_banner; ++ session->socket_callbacks.exception = ssh_socket_exception_callback; ++ session->socket_callbacks.userdata = session; + + rc = server_set_kex(session); + if (rc < 0) { + return SSH_ERROR; + } +- pending: ++pending: + rc = ssh_handle_packets_termination(session, SSH_TIMEOUT_USER, +- ssh_server_kex_termination,session); ++ ssh_server_kex_termination,session); + SSH_LOG(SSH_LOG_PACKET, "ssh_handle_key_exchange: current state : %d", +- session->session_state); +- if (rc != SSH_OK) +- return rc; ++ session->session_state); ++ if (rc != SSH_OK) { ++ return rc; ++ } + if (session->session_state == SSH_SESSION_STATE_ERROR || + session->session_state == SSH_SESSION_STATE_DISCONNECTED) { +- return SSH_ERROR; ++ return SSH_ERROR; + } + +- return SSH_OK; ++ return SSH_OK; + } + + /* messages */ +diff --color -ru ../libssh-0.9.6/src/token.c ./src/token.c +--- ../libssh-0.9.6/src/token.c 2021-03-15 08:11:33.000000000 +0100 ++++ ./src/token.c 2023-04-27 12:21:30.260820657 +0200 +@@ -87,7 +87,7 @@ + return NULL; + } + +- tokens->buffer= strdup(chain); ++ tokens->buffer = strdup(chain); + if (tokens->buffer == NULL) { + goto error; + } +diff --color -ru ../libssh-0.9.6/src/wrapper.c ./src/wrapper.c +--- ../libssh-0.9.6/src/wrapper.c 2021-08-26 14:27:44.000000000 +0200 ++++ ./src/wrapper.c 2023-04-27 12:21:30.260820657 +0200 +@@ -147,15 +147,16 @@ + SAFE_FREE(cipher); + } + +-struct ssh_crypto_struct *crypto_new(void) { +- struct ssh_crypto_struct *crypto; ++struct ssh_crypto_struct *crypto_new(void) ++{ ++ struct ssh_crypto_struct *crypto; + +- crypto = malloc(sizeof(struct ssh_crypto_struct)); +- if (crypto == NULL) { +- return NULL; +- } +- ZERO_STRUCTP(crypto); +- return crypto; ++ crypto = malloc(sizeof(struct ssh_crypto_struct)); ++ if (crypto == NULL) { ++ return NULL; ++ } ++ ZERO_STRUCTP(crypto); ++ return crypto; + } + + void crypto_free(struct ssh_crypto_struct *crypto) +diff --color -ru ../libssh-0.9.6/tests/client/torture_rekey.c ./tests/client/torture_rekey.c +--- ../libssh-0.9.6/tests/client/torture_rekey.c 2021-08-26 14:27:44.000000000 +0200 ++++ ./tests/client/torture_rekey.c 2023-04-27 12:24:04.684475780 +0200 +@@ -651,6 +651,92 @@ + #endif /* WITH_SFTP */ + + ++static void setup_server_for_good_guess(void *state) ++{ ++ const char *default_sshd_config = "KexAlgorithms curve25519-sha256"; ++ const char *fips_sshd_config = "KexAlgorithms ecdh-sha2-nistp256"; ++ const char *sshd_config = default_sshd_config; ++ ++ if (ssh_fips_mode()) { ++ sshd_config = fips_sshd_config; ++ } ++ /* This sets an only supported kex algorithm that we do not have as a first ++ * option */ ++ torture_update_sshd_config(state, sshd_config); ++} ++ ++static void torture_rekey_guess_send(void **state) ++{ ++ struct torture_state *s = *state; ++ ++ setup_server_for_good_guess(state); ++ ++ /* Make the client send the first_kex_packet_follows flag during key ++ * exchange as well as during the rekey */ ++ s->ssh.session->send_first_kex_follows = true; ++ ++ torture_rekey_send(state); ++} ++ ++static void torture_rekey_guess_wrong_send(void **state) ++{ ++ struct torture_state *s = *state; ++ const char *sshd_config = "KexAlgorithms diffie-hellman-group14-sha256"; ++ ++ /* This sets an only supported kex algorithm that we do not have as a first ++ * option */ ++ torture_update_sshd_config(state, sshd_config); ++ ++ /* Make the client send the first_kex_packet_follows flag during key ++ * exchange as well as during the rekey */ ++ s->ssh.session->send_first_kex_follows = true; ++ ++ torture_rekey_send(state); ++} ++ ++#ifdef WITH_SFTP ++static void torture_rekey_guess_recv(void **state) ++{ ++ struct torture_state *s = *state; ++ int rc; ++ ++ setup_server_for_good_guess(state); ++ ++ /* Make the client send the first_kex_packet_follows flag during key ++ * exchange as well as during the rekey */ ++ s->ssh.session->send_first_kex_follows = true; ++ ++ rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_REKEY_DATA, &bytes); ++ assert_ssh_return_code(s->ssh.session, rc); ++ ++ session_setup_sftp(state); ++ ++ torture_rekey_recv(state); ++} ++ ++static void torture_rekey_guess_wrong_recv(void **state) ++{ ++ struct torture_state *s = *state; ++ const char *sshd_config = "KexAlgorithms diffie-hellman-group14-sha256"; ++ int rc; ++ ++ /* This sets an only supported kex algorithm that we do not have as a first ++ * option */ ++ torture_update_sshd_config(state, sshd_config); ++ ++ /* Make the client send the first_kex_packet_follows flag during key ++ * exchange as well as during the rekey */ ++ s->ssh.session->send_first_kex_follows = true; ++ ++ rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_REKEY_DATA, &bytes); ++ assert_ssh_return_code(s->ssh.session, rc); ++ ++ session_setup_sftp(state); ++ ++ torture_rekey_recv(state); ++} ++#endif /* WITH_SFTP */ ++ + int torture_run_tests(void) { + int rc; + struct CMUnitTest tests[] = { +@@ -671,19 +757,34 @@ + cmocka_unit_test_setup_teardown(torture_rekey_different_kex, + session_setup, + session_teardown), +- /* Note, that this modifies the sshd_config */ ++ /* TODO verify the two rekey are possible and the states are not broken after rekey */ ++ ++ cmocka_unit_test_setup_teardown(torture_rekey_server_different_kex, ++ session_setup, ++ session_teardown), ++ /* Note, that these tests modify the sshd_config so follow-up tests ++ * might get unexpected behavior if they do not update the server with ++ * torture_update_sshd_config() too */ + cmocka_unit_test_setup_teardown(torture_rekey_server_send, + session_setup, + session_teardown), ++ cmocka_unit_test_setup_teardown(torture_rekey_guess_send, ++ session_setup, ++ session_teardown), ++ cmocka_unit_test_setup_teardown(torture_rekey_guess_wrong_send, ++ session_setup, ++ session_teardown), + #ifdef WITH_SFTP + cmocka_unit_test_setup_teardown(torture_rekey_server_recv, + session_setup_sftp_server, + session_teardown), +-#endif /* WITH_SFTP */ +- cmocka_unit_test_setup_teardown(torture_rekey_server_different_kex, ++ cmocka_unit_test_setup_teardown(torture_rekey_guess_recv, + session_setup, + session_teardown), +- /* TODO verify the two rekey are possible and the states are not broken after rekey */ ++ cmocka_unit_test_setup_teardown(torture_rekey_guess_wrong_recv, ++ session_setup, ++ session_teardown), ++#endif /* WITH_SFTP */ + }; + + ssh_init(); diff --git a/root/ppg/common/deps/libssh/rpm/s390x_fix.patch b/root/ppg/common/deps/libssh/rpm/s390x_fix.patch new file mode 100644 index 00000000..d06e348e --- /dev/null +++ b/root/ppg/common/deps/libssh/rpm/s390x_fix.patch @@ -0,0 +1,19 @@ +diff --git a/src/packet.c b/src/packet.c +index ec4a7203..a81eb8e3 100644 +--- a/src/packet.c ++++ b/src/packet.c +@@ -1752,10 +1752,12 @@ static bool + ssh_packet_in_rekey(ssh_session session) + { + /* We know we are rekeying if we are authenticated and the DH +- * status is not finished ++ * status is not finished, but we only queue packets until we've ++ * sent our NEWKEYS. + */ + return (session->flags & SSH_SESSION_FLAG_AUTHENTICATED) && +- (session->dh_handshake_state != DH_STATE_FINISHED); ++ (session->dh_handshake_state != DH_STATE_FINISHED) && ++ (session->dh_handshake_state != DH_STATE_NEWKEYS_SENT); + } + + int ssh_packet_send(ssh_session session) diff --git a/root/ppg/common/deps/python3-jmespath/obs/_service b/root/ppg/common/deps/python3-jmespath/obs/_service new file mode 100644 index 00000000..8446ea4f --- /dev/null +++ b/root/ppg/common/deps/python3-jmespath/obs/_service @@ -0,0 +1,15 @@ + + + https://github.com/jmespath/jmespath.py.git + git + 1.0.1 + @PARENT_TAG@ + python3-jmespath + + + + *.tar + gz + + + diff --git a/root/ppg/common/deps/python3-jmespath/rpm/python3-jmespath.spec b/root/ppg/common/deps/python3-jmespath/rpm/python3-jmespath.spec new file mode 100644 index 00000000..11d21fd4 --- /dev/null +++ b/root/ppg/common/deps/python3-jmespath/rpm/python3-jmespath.spec @@ -0,0 +1,54 @@ +%global debug_package %{nil} + +%if 0%{?rhel} && 0%{?rhel} >= 8 +%global __ospython %{_bindir}/python3.12 +%global python3_pkgprefix python3.12 +%global python3_buildversion 3.12 +%global __requires_exclude ^python3\\.12dist +%else +%global __ospython %{_bindir}/python3 +%global python3_pkgprefix python3 +%global python3_buildversion 3 +%endif +%{expand: %%global py3ver %(echo `%{__ospython} -c "import sys; print(f'{sys.version_info[0]}.{sys.version_info[1]}')" `)} +%global python3_sitelib %(%{__ospython} -Esc "import sysconfig; print(sysconfig.get_path('purelib', vars={'platbase': '/usr', 'base': '%{_prefix}'}))") + +%global srcname python3-jmespath + +Summary: JSON Matching Expressions +Name: %{python3_pkgprefix}-jmespath +Version: 1.0.0 +Release: 1%{?dist} +Source0: %{srcname}-%{version}.tar.gz +License: MIT +BuildArch: noarch +Vendor: Percona, LLC +Packager: Percona Development Team +Url: https://github.com/jmespath/jmespath.py +Epoch: 1 + +BuildRequires: python%{python3_buildversion}-devel +BuildRequires: python%{python3_buildversion}-setuptools + +%description +JMESPath (pronounced "james path") allows you to declaratively specify how to +extract elements from a JSON document. It is a runtime dependency of boto3. + +%prep +%setup -n %{srcname}-%{version} + +%build +%{__ospython} setup.py build + +%install +%{__ospython} setup.py install --single-version-externally-managed -O1 --root=$RPM_BUILD_ROOT --record=INSTALLED_FILES +# Own all installed directories (not recorded by --record) +find %{buildroot}%{python3_sitelib} -mindepth 1 -type d | sed "s|%{buildroot}||" >> INSTALLED_FILES + +%files -f INSTALLED_FILES +%defattr(-,root,root) +%dir %{python3_sitelib}/jmespath + +%changelog +* Tue Jul 21 2026 Percona Build/Release Team - 1.0.1-1 +- Initial build of python3-jmespath 1.0.1 diff --git a/root/ppg/common/deps/python3-s3transfer/obs/_service b/root/ppg/common/deps/python3-s3transfer/obs/_service new file mode 100644 index 00000000..e145abf7 --- /dev/null +++ b/root/ppg/common/deps/python3-s3transfer/obs/_service @@ -0,0 +1,15 @@ + + + https://github.com/boto/s3transfer.git + git + 0.12.0 + @PARENT_TAG@ + python3-s3transfer + + + + *.tar + gz + + + diff --git a/root/ppg/common/deps/python3-s3transfer/rpm/python3-s3transfer.spec b/root/ppg/common/deps/python3-s3transfer/rpm/python3-s3transfer.spec new file mode 100644 index 00000000..0b15b05c --- /dev/null +++ b/root/ppg/common/deps/python3-s3transfer/rpm/python3-s3transfer.spec @@ -0,0 +1,56 @@ +%global debug_package %{nil} + +%if 0%{?rhel} && 0%{?rhel} >= 8 +%global __ospython %{_bindir}/python3.12 +%global python3_pkgprefix python3.12 +%global python3_buildversion 3.12 +%global __requires_exclude ^python3\\.12dist +%else +%global __ospython %{_bindir}/python3 +%global python3_pkgprefix python3 +%global python3_buildversion 3 +%endif +%{expand: %%global py3ver %(echo `%{__ospython} -c "import sys; print(f'{sys.version_info[0]}.{sys.version_info[1]}')" `)} +%global python3_sitelib %(%{__ospython} -Esc "import sysconfig; print(sysconfig.get_path('purelib', vars={'platbase': '/usr', 'base': '%{_prefix}'}))") + +%global srcname python3-s3transfer + +Summary: An Amazon S3 Transfer Manager for Python +Name: %{python3_pkgprefix}-s3transfer +Version: 1.0.0 +Release: 1%{?dist} +Source0: %{srcname}-%{version}.tar.gz +License: Apache-2.0 +BuildArch: noarch +Vendor: Percona, LLC +Packager: Percona Development Team +Url: https://github.com/boto/s3transfer +Epoch: 1 + +BuildRequires: python%{python3_buildversion}-devel +BuildRequires: python%{python3_buildversion}-setuptools + +Requires: %{python3_pkgprefix}-botocore + +%description +S3transfer is a Python library for managing Amazon S3 transfers. It is a +runtime dependency of boto3. + +%prep +%setup -n %{srcname}-%{version} + +%build +%{__ospython} setup.py build + +%install +%{__ospython} setup.py install --single-version-externally-managed -O1 --root=$RPM_BUILD_ROOT --record=INSTALLED_FILES +# Own all installed directories (not recorded by --record) +find %{buildroot}%{python3_sitelib} -mindepth 1 -type d | sed "s|%{buildroot}||" >> INSTALLED_FILES + +%files -f INSTALLED_FILES +%defattr(-,root,root) +%dir %{python3_sitelib}/s3transfer + +%changelog +* Tue Jul 21 2026 Percona Build/Release Team - 0.12.0-1 +- Initial build of python3-s3transfer 0.12.0 diff --git a/root/ppg/staging/17/percona-postgresql/rpm/percona-postgresql.spec b/root/ppg/staging/17/percona-postgresql/rpm/percona-postgresql.spec index fac7d0a7..9b45efc7 100644 --- a/root/ppg/staging/17/percona-postgresql/rpm/percona-postgresql.spec +++ b/root/ppg/staging/17/percona-postgresql/rpm/percona-postgresql.spec @@ -106,6 +106,13 @@ Patch3: %{sname}-conf.patch Patch5: %{sname}-var-run-socket.patch Patch6: %{sname}-perl-rpath.patch Patch7: llvm_static_linking.patch +# pgcrypto: OpenSSL >= 3.4 headers remap the EVP_MD_CTX_size() macro to +# EVP_MD_CTX_get_size_ex() (a function new in 3.4.0), so building on a +# newer-OpenSSL base adds an OPENSSL_3.4.0 versioned symbol need that makes +# pgcrypto.so fail to load on OpenSSL 3.0-3.3 hosts. Restore the 3.0-era +# macro expansion (identical behavior). Candidate for upstreaming to +# PostgreSQL. +Patch8: pgcrypto-openssl34-md-ctx-size.patch %if 0%{?suse_version} BuildRequires: update-alternatives @@ -204,7 +211,12 @@ BuildRequires: perl-ExtUtils-Embed %endif %endif -%if 0%{?rhel} >= 8 && 0%{?rhel} < 9 +# PERCONA: build plpython3 against the parallel python3.12 stack on EL8 AND +# EL9 so the embedded interpreter matches the percona python3.12-* runtime +# packages (and the python 3.12 stdlib bundled in the binary tarball). +# EL10 is left on the default python3-devel, which already IS 3.12 there. +# The matching PYTHON= export lives next to %%configure in %%build. +%if 0%{?rhel} >= 8 && 0%{?rhel} < 10 BuildRequires: python3.12-devel %else BuildRequires: python3-devel @@ -594,6 +606,7 @@ benchmarks. %patch -P 3 -p0 %patch -P 5 -p0 %patch -P 6 -p0 +%patch -P 8 -p0 %{__cp} -p %{SOURCE12} . @@ -634,6 +647,17 @@ source /opt/rh/gcc-toolset-%{gts_version}/enable export CLANG=%{_bindir}/clang LLVM_CONFIG=%{_bindir}/llvm-config %endif +# PERCONA: steer --with-python explicitly at the 3.12 interpreter on EL8/EL9 +# (same bounds as the python3.12-devel BuildRequires above). Without this, +# configure probes plain "python3": on EL8 that happened to resolve to 3.12 +# (the python3.12 package registers /usr/bin/python3 via alternatives when it +# is the only python3 in the chroot), but on EL9 /usr/bin/python3 is always +# 3.9 — plpython3.so would link libpython3.9 while the tarball bundles the +# 3.12 stdlib, and the embedded interpreter then fatals at backend start +# ("No module named 'encodings'"). +%if 0%{?rhel} >= 8 && 0%{?rhel} < 10 +export PYTHON=%{_bindir}/python3.12 +%endif # These configure options must match main build ./configure --enable-rpath \ @@ -1432,6 +1456,11 @@ fi * %!{FILE_MODIFY_DATE} Percona Development Team - %!{PG_VERSION}-1 - Update to upstream version %!{PG_VERSION}. +* Wed Jul 22 2026 Ricardo Dias +- EL9: build plpython3 against python 3.12 (previously python 3.9), aligning + the embedded interpreter with EL8 and the percona python3.12-* runtime + stack shipped alongside the server. + * Tue Feb 03 2026 Ricardo Dias - 17.5.3 - Initial spec file for PostgreSQL 17.5.3 diff --git a/root/ppg/staging/17/percona-postgresql/rpm/pgcrypto-openssl34-md-ctx-size.patch b/root/ppg/staging/17/percona-postgresql/rpm/pgcrypto-openssl34-md-ctx-size.patch new file mode 100644 index 00000000..c1fb2dee --- /dev/null +++ b/root/ppg/staging/17/percona-postgresql/rpm/pgcrypto-openssl34-md-ctx-size.patch @@ -0,0 +1,23 @@ +--- contrib/pgcrypto/openssl.c.orig ++++ contrib/pgcrypto/openssl.c +@@ -35,6 +35,20 @@ + #include + #include + ++/* ++ * OpenSSL 3.4 redefines the EVP_MD_CTX_size() compatibility macro to call ++ * EVP_MD_CTX_get_size_ex(), a function introduced in 3.4.0. Merely ++ * compiling against >= 3.4 headers therefore adds a runtime dependency on ++ * the OPENSSL_3.4.0 symbol version, which does not exist on OpenSSL ++ * 3.0-3.3 hosts and makes this module fail to load there. Restore the ++ * 3.0-era expansion (identical behavior) so binaries built on newer ++ * OpenSSL remain loadable on any 3.x host. ++ */ ++#if OPENSSL_VERSION_NUMBER >= 0x30400000L ++#undef EVP_MD_CTX_size ++#define EVP_MD_CTX_size(ctx) EVP_MD_get_size(EVP_MD_CTX_get0_md(ctx)) ++#endif ++ + #include "px.h" + #include "utils/memutils.h" + #include "utils/resowner.h" diff --git a/root/ppg/staging/17/python3-jmespath/obs/_aggregate b/root/ppg/staging/17/python3-jmespath/obs/_aggregate new file mode 100644 index 00000000..1d723cae --- /dev/null +++ b/root/ppg/staging/17/python3-jmespath/obs/_aggregate @@ -0,0 +1,5 @@ + + + python3-jmespath + + diff --git a/root/ppg/staging/17/python3-s3transfer/obs/_aggregate b/root/ppg/staging/17/python3-s3transfer/obs/_aggregate new file mode 100644 index 00000000..2900ec30 --- /dev/null +++ b/root/ppg/staging/17/python3-s3transfer/obs/_aggregate @@ -0,0 +1,5 @@ + + + python3-s3transfer + + diff --git a/root/ppg/staging/17/tarballs/percona-postgresql-tarball/obs/build-tarball.sh b/root/ppg/staging/17/tarballs/percona-postgresql-tarball/obs/build-tarball.sh new file mode 100644 index 00000000..3b4e2b4f --- /dev/null +++ b/root/ppg/staging/17/tarballs/percona-postgresql-tarball/obs/build-tarball.sh @@ -0,0 +1,879 @@ +#!/bin/bash +# Builds the Percona PostgreSQL binary tarball from RPM-installed content. +# Runs chrooted as root inside an OBS simpleimage buildroot; writes the +# final artifact (with its official self-derived name) directly into +# /usr/src/packages/OTHER, where OBS collects build results. The recipe's +# own /.simpleimage.tar.gz handling is skipped (#!NoTarBall, and no such +# file is created). +set -e + +PG_MAJOR=$(basename "$(ls -d /usr/pgsql-*)" | sed 's/^pgsql-//') +[ -n "$PG_MAJOR" ] || { echo "FATAL: no /usr/pgsql-* tree found" >&2; exit 1; } + +# Prefer the parallel 3.12 stack (EL8/EL9); fall back to the default python3 (EL10+). +PY_BIN=$(command -v python3.12 || command -v python3) +PY_VER=$("$PY_BIN" -c 'import sys; print("%d.%d" % sys.version_info[:2])') + +# Interpreter versions discovered up front (used in wrappers below). +PERL_VER=$(perl -e 'printf "%vd", $^V') +TCL_VER=$(echo 'puts $tcl_version' | tclsh) + +PG_PREFIX=/opt/percona-postgresql${PG_MAJOR} +PYTHON_PREFIX=/opt/percona-python3 +PERL_PREFIX=/opt/percona-perl +TCL_PREFIX=/opt/percona-tcl + +############################################################### +# System library exclusion list — these are always on the target +# system and must NOT be bundled (matches pg_tarballs_builder.sh) +############################################################### +# NOTE: the string literal below is a whitespace-separated token list — +# every word in it becomes a live glob prefix in is_system_lib, so never +# put comments inside the quotes. +# libidn2/libunistring/libnghttp2 are deliberately NOT excluded (i.e. they +# ARE bundled): acceptance testing showed their sonames drift across distro +# generations (libunistring.so.2 on EL8/EL9 vs .so.5 on current Debian/ +# Ubuntu) and minimal hosts do not ship them at all. Once unexcluded they +# flow through copy_deps/the NEEDED audit automatically. +SYSTEM_LIBS_EXCLUDE=" +libc.so +libm.so +libpthread.so +libdl.so +librt.so +libresolv.so +libnss_ +libnsl.so +ld-linux +libgcc_s.so +libstdc++.so +libz.so +libbz2.so +liblz4.so +liblzma.so +libzstd.so +libsystemd.so +libselinux.so +libpam.so +libpam_misc.so +libaudit.so +libcap.so +libcap-ng.so +libeconf.so +libgcrypt.so +libgpg-error.so +libssl.so +libcrypto.so +libpcre2-8.so +libpcre2-posix.so +libtinfo.so +libreadline.so +libexpat.so +libtirpc.so +" + +is_system_lib() { + local libname=$(basename "$1") + local pattern + for pattern in $SYSTEM_LIBS_EXCLUDE; do + case "$libname" in + ${pattern}*) return 0 ;; + esac + done + return 1 +} + +############################################################### +# Helper: copy .so deps of an ELF file into destlib, +# preserving symlink chains and filtering system libs +############################################################### +copy_deps() { + local binary="$1" + local destlib="$2" + ldd "$binary" 2>/dev/null | awk '/=>/ && $3 ~ /^\// {print $3}' | sort -u | while read lib; do + [ -f "$lib" ] || continue + is_system_lib "$lib" && continue + # Resolve to real file and copy the whole symlink family + local real=$(readlink -f "$lib") + local dir=$(dirname "$real") + local base=$(basename "$lib" | sed 's/\.so.*//') + # The resolved real file may not match the ${base}.so* glob below + # (e.g. libldap.so.2 -> libldap_r.so.2.0.200, libopenblaso.so.0 -> + # libopenblaso-r0.3.29.so); copy it explicitly so the recreated + # symlinks never dangle. + cp -pn "$real" "$destlib/" 2>/dev/null || true + # Copy real file + all related symlinks + for f in "$dir"/${base}.so*; do + [ -e "$f" ] || [ -L "$f" ] || continue + if [ -L "$f" ]; then + local target=$(readlink "$f") + ln -sf "$target" "$destlib/$(basename "$f")" 2>/dev/null || true + else + cp -pn "$f" "$destlib/" 2>/dev/null || true + fi + done + done +} + +# Run copy_deps over all ELF files in a prefix (3 passes for dep depth). +# Any extra arguments are additional directory trees walked recursively for +# ELF .so files (e.g. python lib-dynload/ + site-packages C extensions), +# so their NEEDED libs are bundled too. +bundle_deps() { + local prefix="$1" + shift + local libdir="$prefix/lib" + mkdir -p "$libdir" + for pass in 1 2 3; do + { + find "$prefix/bin" "$libdir" -maxdepth 1 -type f 2>/dev/null + [ $# -gt 0 ] && find "$@" -type f -name '*.so*' 2>/dev/null + } | while read f; do + file "$f" 2>/dev/null | grep -q ELF && copy_deps "$f" "$libdir" || true + done + done +} + +# patchelf all ELF files in bin/ and lib/ to given RPATH +patch_rpath() { + local prefix="$1" + local rpath="${2:-\$ORIGIN/../lib}" + find "$prefix/bin" "$prefix/lib" -maxdepth 1 -type f 2>/dev/null | while read f; do + file "$f" 2>/dev/null | grep -q ELF && \ + patchelf --set-rpath "$rpath" "$f" 2>/dev/null || true + done +} + +############################################################### +# 1. Create isolated prefix directories +############################################################### +for tool in percona-postgresql${PG_MAJOR} percona-pgbouncer percona-pgpool-II \ + percona-pgbackrest percona-pgbadger percona-patroni \ + percona-python3 percona-perl percona-tcl percona-etcd; do + mkdir -p /opt/${tool}/{bin,lib} +done + +############################################################### +# 2. PostgreSQL: /usr/pgsql-NN -> /opt/percona-postgresqlNN +############################################################### +cp -rp /usr/pgsql-${PG_MAJOR}/bin/. $PG_PREFIX/bin/ +cp -rp /usr/pgsql-${PG_MAJOR}/lib/. $PG_PREFIX/lib/ +cp -rp /usr/pgsql-${PG_MAJOR}/share $PG_PREFIX/ +[ -d /usr/pgsql-${PG_MAJOR}/include ] && cp -rp /usr/pgsql-${PG_MAJOR}/include $PG_PREFIX/ || true +# doc/ +mkdir -p $PG_PREFIX/doc +for d in /usr/share/doc/percona-postgresql${PG_MAJOR}*; do + [ -d "$d" ] && cp -rp "$d" $PG_PREFIX/doc/ || true +done + +############################################################### +# 2b. PostgreSQL cleanup + psql wrapper + gather.sql +############################################################### +# Remove RPM service helpers that don't belong in the tarball +rm -f $PG_PREFIX/bin/postgresql-${PG_MAJOR}-* 2>/dev/null || true + +# gather.sql from percona-pg_gather (installed to pgsql share/contrib) +for f in /usr/pgsql-${PG_MAJOR}/share/contrib/gather.sql \ + /usr/share/percona-pg_gather/gather.sql /usr/bin/gather.sql \ + /usr/share/pgsql/gather.sql; do + [ -f "$f" ] && cp "$f" $PG_PREFIX/bin/ && break || true +done + +# psql wrapper: rename real binary to psql.bin, create wrapper (matches reference tarball) +mv $PG_PREFIX/bin/psql $PG_PREFIX/bin/psql.bin +cat > $PG_PREFIX/bin/psql << 'EOF' +#!/bin/bash +# psql wrapper (mirrors the official Percona tarball wrapper). +# +# psql.bin is built against libreadline, which is deliberately NOT bundled +# (system exclude list) — the HOST copy is used at run time. Two mechanisms: +# +# * LD_PRELOAD of the host libreadline: covers the case where psql.bin's +# DT_NEEDED soname matches a host library (e.g. the EL9-built ssl3 +# binary needs libreadline.so.8, present on all modern hosts). +# +# * libreadline.so.7 symlink fallback: the EL8-built (ssl1.1) psql.bin +# carries "NEEDED libreadline.so.7", but current hosts ship only +# libreadline.so.8 — and LD_PRELOAD can NOT satisfy a missing NEEDED +# soname, the loader still refuses to start. So when the host offers +# only .so.8, create a libreadline.so.7 -> symlink inside +# the artifact's own lib dir, which the loader reaches through +# psql.bin's RUNPATH ($ORIGIN/../lib). readline 7 -> 8 is compatible +# for everything psql uses; the official wrapper does exactly this. +# The symlink write into the extraction dir is best-effort (|| true): +# on a read-only install it fails silently and we still exec psql.bin +# (which then only matters for the .so.7-needing binary anyway). +PG_BIN_PATH=`dirname "$0"` +PG_LIB_PATH=$PG_BIN_PATH/../lib +PLL="" +RL8="" +if [ -f /lib64/libreadline.so.7 ]; then + # Host still ships .so.7: satisfies the EL8-built binary directly. + PLL=/lib64/libreadline.so.7 +elif [ -f /lib64/libreadline.so.8 ]; then + PLL=/lib64/libreadline.so.8 + RL8=$PLL +elif [ -f /usr/lib/x86_64-linux-gnu/libreadline.so.8 ]; then + PLL=/usr/lib/x86_64-linux-gnu/libreadline.so.8 + RL8=$PLL +elif [ -f /lib/x86_64-linux-gnu/libreadline.so.8 ]; then + PLL=/lib/x86_64-linux-gnu/libreadline.so.8 + RL8=$PLL +elif [ -f /lib/aarch64-linux-gnu/libreadline.so.8 ]; then + PLL=/lib/aarch64-linux-gnu/libreadline.so.8 + RL8=$PLL +fi +# Symlink fallback: host has only .so.8 and no .so.7 is reachable yet in +# our lib dir — link .so.7 to the host .so.8 so an EL8-built psql.bin's +# NEEDED entry resolves. Harmless for the .so.8-linked (EL9) binary: the +# extra symlink is simply never looked up. +if [ -n "$RL8" ] && [ ! -e "$PG_LIB_PATH/libreadline.so.7" ]; then + ln -sf "$RL8" "$PG_LIB_PATH/libreadline.so.7" 2>/dev/null || true +fi +if [ -z "$PLL" ]; then + LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PG_BIN_PATH/../lib "$PG_BIN_PATH/psql.bin" "$@" +else + LD_PRELOAD=$PLL LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PG_BIN_PATH/../lib "$PG_BIN_PATH/psql.bin" "$@" +fi +EOF +chmod +x $PG_PREFIX/bin/psql + +############################################################### +# 2c. Wrap postgres binary to set PL/Perl and PL/Tcl runtime paths +############################################################### +# Paths match docs install: extract to /opt/pgdistro/, then: +# cp -r /opt/pgdistro/percona-perl /opt/ +# cp -r /opt/pgdistro/percona-tcl /opt/ +mv $PG_PREFIX/bin/postgres $PG_PREFIX/bin/postgres.real +cat > $PG_PREFIX/bin/postgres << EOF +#!/bin/sh +# Set bundled PL/Perl stdlib path (libperl.so @INC points to system paths by default) +export PERL5LIB="\${PERL5LIB:+\${PERL5LIB}:}/opt/percona-perl/lib/${PERL_VER}" +# Set bundled Tcl library path so pltcl can find init.tcl +export TCL_LIBRARY="/opt/percona-tcl/lib/tcl${TCL_VER}" +# Point the EMBEDDED python (plpython3) at the bundled stdlib: the +# interactive /opt/percona-python3/bin/python3 wrapper sets PYTHONHOME +# itself, but libpython loaded inside the server never runs that wrapper — +# without this the backend crashes on plpython3 use (acceptance-verified +# on every variant). +export PYTHONHOME=/opt/percona-python3 +SELFDIR="\$(cd "\$(dirname "\$0")" && pwd)" +exec "\$SELFDIR/postgres.real" "\$@" +EOF +chmod +x $PG_PREFIX/bin/postgres + +############################################################### +# 3. pgBouncer +############################################################### +cp /usr/bin/pgbouncer /opt/percona-pgbouncer/bin/ +[ -d /etc/pgbouncer ] && \ + mkdir -p /opt/percona-pgbouncer/etc && \ + cp -rp /etc/pgbouncer/. /opt/percona-pgbouncer/etc/ || true +# share/doc (RPM doc dir is unprefixed /usr/share/doc/pgbouncer; reference +# tarball layout is share/doc/pgbouncer/) +[ -d /usr/share/doc/pgbouncer ] && \ + mkdir -p /opt/percona-pgbouncer/share/doc && \ + cp -rp /usr/share/doc/pgbouncer /opt/percona-pgbouncer/share/doc/ || true +[ -d /usr/share/pgbouncer ] && \ + mkdir -p /opt/percona-pgbouncer/share && \ + cp -rp /usr/share/pgbouncer /opt/percona-pgbouncer/share/ || true + +############################################################### +# 4. pgPool-II +############################################################### +find /usr/bin -maxdepth 1 \( -name 'pgpool' -o -name 'pcp_*' -o -name 'pg_md5' \ + -o -name 'pgslap' -o -name 'pgpool_*' \ + -o -name 'pg_enc' -o -name 'pgproto' \ + -o -name 'watchdog_setup' -o -name 'wd_cli' \) -exec cp {} /opt/percona-pgpool-II/bin/ \; +[ -d /etc/pgpool-II ] && \ + mkdir -p /opt/percona-pgpool-II/etc && \ + cp -rp /etc/pgpool-II/. /opt/percona-pgpool-II/etc/ || true +# share/ and include/ +[ -d /usr/share/pgpool-II ] && cp -rp /usr/share/pgpool-II /opt/percona-pgpool-II/share/ || true +# Headers from the -devel package are installed flat into /usr/include +# (pcp.h, libpcp_ext.h, pool_*.h); reference layout nests them under +# include/pgpool2/. Use the RPM manifest to pick exactly those headers. +rpm -ql percona-pgpool-II-pg${PG_MAJOR}-devel 2>/dev/null | \ + grep '^/usr/include/.*\.h$' | while read -r h; do + mkdir -p /opt/percona-pgpool-II/include/pgpool2 + cp -p "$h" /opt/percona-pgpool-II/include/pgpool2/ +done + +############################################################### +# 5. pgBackRest +############################################################### +cp /usr/bin/pgbackrest /opt/percona-pgbackrest/bin/ +[ -d /etc/pgbackrest ] && \ + mkdir -p /opt/percona-pgbackrest/etc && \ + cp -rp /etc/pgbackrest/. /opt/percona-pgbackrest/etc/ || true +[ -f /etc/pgbackrest.conf ] && \ + mkdir -p /opt/percona-pgbackrest/etc && \ + cp /etc/pgbackrest.conf /opt/percona-pgbackrest/etc/ || true +# License (RPMs install %license files under /usr/share/licenses) +for d in /usr/share/licenses/percona-pgbackrest* /usr/share/doc/percona-pgbackrest*; do + [ -f "$d/LICENSE" ] && cp "$d/LICENSE" /opt/percona-pgbackrest/pgbackrest_license && break || true +done + +############################################################### +# 6. pgBadger -- flat layout (matches reference) +############################################################### +cp /usr/bin/pgbadger /opt/percona-pgbadger/pgbadger +rmdir /opt/percona-pgbadger/bin /opt/percona-pgbadger/lib 2>/dev/null || true +# Man page +find /usr/share/man -name 'pgbadger.1*' -exec sh -c 'f="{}"; case "$f" in *.gz) gunzip -c "$f" > /opt/percona-pgbadger/pgbadger.1p ;; *) cp "$f" /opt/percona-pgbadger/pgbadger.1p ;; esac' \; 2>/dev/null || true +# License and README (LICENSE lives under /usr/share/licenses, README under +# /usr/share/doc) +for d in /usr/share/doc/percona-pgbadger* /usr/share/licenses/percona-pgbadger*; do + [ -d "$d" ] || continue + [ -f "$d/LICENSE" ] && cp "$d/LICENSE" /opt/percona-pgbadger/LICENSE || true + for readme in "$d"/README*; do + [ -f "$readme" ] && cp "$readme" /opt/percona-pgbadger/README.md && break || true + done +done + +############################################################### +# 7. Bundle Python -> /opt/percona-python3 +############################################################### +cp "$PY_BIN" "$PYTHON_PREFIX/bin/python${PY_VER}" + +# Copy standard library (pure Python) and compiled extension modules into lib/ +[ -d /usr/lib/python${PY_VER} ] && cp -rp /usr/lib/python${PY_VER} $PYTHON_PREFIX/lib/ || true +[ -d /usr/lib64/python${PY_VER} ] && cp -rp /usr/lib64/python${PY_VER}/. $PYTHON_PREFIX/lib/python${PY_VER}/ 2>/dev/null || true + +# Python binary has sys.platlibdir='lib64' compiled in, so it searches lib64/pythonX.Y/ +# Create a symlink so PYTHONHOME lookup via lib64 resolves to our lib/ tree +mkdir -p $PYTHON_PREFIX/lib64 +ln -sf ../lib/python${PY_VER} $PYTHON_PREFIX/lib64/python${PY_VER} + +# Copy libpython shared lib with symlinks +LIBPYTHON_DIR=/usr/lib64 +cp -a ${LIBPYTHON_DIR}/libpython${PY_VER}*.so* $PYTHON_PREFIX/lib/ 2>/dev/null || true +cp -a ${LIBPYTHON_DIR}/libpython3.so $PYTHON_PREFIX/lib/ 2>/dev/null || true +ln -sf libpython${PY_VER}.so.1.0 $PYTHON_PREFIX/lib/libpython${PY_VER}.so 2>/dev/null || true +ln -sf libpython${PY_VER}.so $PYTHON_PREFIX/lib/libpython3.so 2>/dev/null || true + +# Copy libffi (reference bundles it) +cp -a /usr/lib64/libffi.so* $PYTHON_PREFIX/lib/ 2>/dev/null || true + +# include/ +[ -d /usr/include/python${PY_VER} ] && \ + mkdir -p $PYTHON_PREFIX/include && \ + cp -rp /usr/include/python${PY_VER} $PYTHON_PREFIX/include/ || true + +# pkgconfig +mkdir -p $PYTHON_PREFIX/lib/pkgconfig +cp /usr/lib64/pkgconfig/python-${PY_VER}*.pc $PYTHON_PREFIX/lib/pkgconfig/ 2>/dev/null || true + +# share/man (reference ships the python man page uncompressed + python3.1 alias) +mkdir -p $PYTHON_PREFIX/share/man/man1 +for m in /usr/share/man/man1/python${PY_VER}.1*; do + [ -e "$m" ] || continue + case "$m" in + *.gz) gunzip -c "$m" > $PYTHON_PREFIX/share/man/man1/python${PY_VER}.1 ;; + *) cp -p "$m" $PYTHON_PREFIX/share/man/man1/ ;; + esac +done +[ -f $PYTHON_PREFIX/share/man/man1/python${PY_VER}.1 ] && \ + ln -sf python${PY_VER}.1 $PYTHON_PREFIX/share/man/man1/python3.1 || true + +# Copy Python utility scripts and update shebangs to bundled python +# Note: with PY_VER=X.Y, pip3.${PY_VER#*.} = pip3.Y and 2to3-${PY_VER} = 2to3-X.Y +for script in pip pip3 pip3.${PY_VER#*.} 2to3 2to3-${PY_VER} \ + idle3 idle${PY_VER} pydoc3 pydoc${PY_VER} \ + python3-config python${PY_VER}-config \ + syncobj_admin jp.py; do + [ -f "/usr/bin/$script" ] && cp "/usr/bin/$script" $PYTHON_PREFIX/bin/ || true +done +# ydiff is a Python module with no /usr/bin script; create a wrapper +if [ -f /usr/lib/python${PY_VER}/site-packages/ydiff.py ]; then + cat > $PYTHON_PREFIX/bin/ydiff << 'WEOF' +#!/opt/percona-python3/bin/python3 +from ydiff import main +import sys +sys.exit(main()) +WEOF + chmod +x $PYTHON_PREFIX/bin/ydiff +fi +for script in $PYTHON_PREFIX/bin/pip $PYTHON_PREFIX/bin/pip3 \ + $PYTHON_PREFIX/bin/pip${PY_VER} \ + $PYTHON_PREFIX/bin/syncobj_admin $PYTHON_PREFIX/bin/ydiff \ + $PYTHON_PREFIX/bin/jp.py $PYTHON_PREFIX/bin/2to3 \ + $PYTHON_PREFIX/bin/2to3-${PY_VER} $PYTHON_PREFIX/bin/pydoc3 \ + $PYTHON_PREFIX/bin/pydoc${PY_VER} $PYTHON_PREFIX/bin/idle3 \ + $PYTHON_PREFIX/bin/idle${PY_VER}; do + [ -f "$script" ] && \ + sed -i "1s|^#!.*python.*|#!/opt/percona-python3/bin/python3|" "$script" || true +done + +############################################################### +# 8. Patroni -- copy from RPM-installed location into bundled Python +############################################################### +SITE_DEST=$PYTHON_PREFIX/lib/python${PY_VER}/site-packages +mkdir -p "$SITE_DEST" + +# Patroni may be installed under a different Python version (e.g. system python3.9). +# Search ALL Python site-packages directories to find the packages. +# Pure Python packages work across any Python version; compiled .so extensions +# that match the bundled Python version will also be usable. +for pkg in patroni patroni-*.dist-info patroni-*.egg-info \ + click click-*.dist-info \ + dateutil python_dateutil-*.dist-info \ + psutil psutil-*.dist-info psutil-*.egg-info \ + urllib3 urllib3-*.dist-info \ + six.py six-*.dist-info \ + certifi certifi-*.dist-info \ + dns dnspython-*.dist-info \ + pysyncobj pysyncobj-*.dist-info \ + kazoo kazoo-*.dist-info \ + etcd python_etcd-*.dist-info python_etcd-*.egg-info \ + boto3 boto3-*.dist-info botocore botocore-*.dist-info \ + jmespath jmespath-*.dist-info jmespath-*.egg-info \ + s3transfer s3transfer-*.dist-info s3transfer-*.egg-info \ + psycopg2 psycopg2-*.dist-info psycopg2-*.egg-info \ + consul py_consul-*.dist-info \ + prettytable prettytable-*.dist-info \ + packaging packaging-*.dist-info \ + typing_extensions typing_extensions-*.dist-info \ + requests requests-*.dist-info \ + charset_normalizer charset_normalizer-*.dist-info \ + idna idna-*.dist-info \ + yaml PyYAML-*.dist-info _yaml \ + wcwidth wcwidth-*.dist-info \ + cryptography cryptography-*.dist-info \ + cffi cffi-*.dist-info _cffi_backend* \ + pycparser pycparser-*.dist-info; do + for sitedir in /usr/lib/python${PY_VER}/site-packages /usr/lib64/python${PY_VER}/site-packages; do + [ -d "$sitedir" ] || continue + for match in "$sitedir"/$pkg; do + [ -e "$match" ] && cp -rp "$match" "$SITE_DEST/" 2>/dev/null || true + done + done +done + +# Copy patroni binaries, rewriting shebang to bundled Python +mkdir -p /opt/percona-patroni/bin +for pbin in patroni patronictl patroni_barman patroni_raft_controller patroni_aws patroni_wale_restore; do + [ -f "/usr/bin/$pbin" ] || continue + cp "/usr/bin/$pbin" "/opt/percona-patroni/bin/$pbin" + sed -i "1s|^#!.*|#!/opt/percona-python3/bin/python3|" "/opt/percona-patroni/bin/$pbin" +done + +# share/doc and license +mkdir -p /opt/percona-patroni/share/doc +for d in /usr/share/doc/percona-patroni*; do + [ -d "$d" ] && cp -rp "$d"/. /opt/percona-patroni/share/doc/ || true +done +for d in /usr/share/licenses/percona-patroni* /usr/share/doc/percona-patroni*; do + [ -f "$d/LICENSE" ] && cp "$d/LICENSE" /opt/percona-patroni/patroni_license && break || true +done +# Remove empty lib/ from patroni (Python app, no native libs) +rmdir /opt/percona-patroni/lib 2>/dev/null || true + +############################################################### +# 9. etcd (Go static binary -- no deps to bundle) +############################################################### +for ebin in etcd etcdctl etcdutl; do + [ -f "/usr/bin/$ebin" ] && cp "/usr/bin/$ebin" /opt/percona-etcd/bin/ || true +done +# Remove empty lib/ (etcd is statically linked) +rmdir /opt/percona-etcd/lib 2>/dev/null || true + +############################################################### +# 10. Bundle Perl -> /opt/percona-perl +############################################################### +PERL_ARCH=$(perl -MConfig -e 'print $Config{archname}') + +cp /usr/bin/perl $PERL_PREFIX/bin/ +[ -f "/usr/bin/perl${PERL_VER}" ] && cp "/usr/bin/perl${PERL_VER}" $PERL_PREFIX/bin/ || true + +# Core modules (arch-specific with CORE/ containing libperl.so) +mkdir -p $PERL_PREFIX/lib/${PERL_VER} +[ -d /usr/lib64/perl5/${PERL_VER} ] && \ + cp -rp /usr/lib64/perl5/${PERL_VER}/. $PERL_PREFIX/lib/${PERL_VER}/ || true +# Also check non-versioned path +[ -d /usr/lib64/perl5 ] && [ ! -d /usr/lib64/perl5/${PERL_VER} ] && \ + cp -rp /usr/lib64/perl5/. $PERL_PREFIX/lib/${PERL_VER}/ || true + +# Pure-perl modules +[ -d /usr/share/perl5/${PERL_VER} ] && \ + cp -rp /usr/share/perl5/${PERL_VER}/. $PERL_PREFIX/lib/${PERL_VER}/ || true +[ -d /usr/share/perl5 ] && [ ! -d /usr/share/perl5/${PERL_VER} ] && \ + cp -rp /usr/share/perl5/. $PERL_PREFIX/lib/${PERL_VER}/ || true + +# Vendor modules +[ -d /usr/lib64/perl5/vendor_perl ] && \ + cp -rp /usr/lib64/perl5/vendor_perl/. $PERL_PREFIX/lib/${PERL_VER}/ || true +[ -d /usr/share/perl5/vendor_perl ] && \ + cp -rp /usr/share/perl5/vendor_perl/. $PERL_PREFIX/lib/${PERL_VER}/ || true + +# site_perl +mkdir -p $PERL_PREFIX/lib/site_perl +[ -d /usr/local/lib64/perl5 ] && cp -rp /usr/local/lib64/perl5/. $PERL_PREFIX/lib/site_perl/ || true +[ -d /usr/local/share/perl5 ] && cp -rp /usr/local/share/perl5/. $PERL_PREFIX/lib/site_perl/ || true + +# Prune Net::SSLeay from the staged tree. The official Percona tarball does +# not ship it, and its XS module (auto/Net/SSLeay/SSLeay.so) links the HOST +# libssl/libcrypto with OPENSSL_3.2.0 version needs — that would violate +# the ssl variant host-ABI promise enforced by the verification gate +# (section 15). The copies above can land it in several places (vendor_perl +# is copied both as a subtree and flattened), so sweep the whole prefix: +# both the XS dirs (*/auto/Net/SSLeay) and the pure-perl parts +# (Net/SSLeay.pm + Net/SSLeay.pod + Net/SSLeay/ support dir). Note: the +# path patterns are anchored under Net/ so the unrelated +# Software::License::SSLeay module is left alone. +find "$PERL_PREFIX" -type d -path '*/Net/SSLeay' -prune -exec rm -rf {} + +find "$PERL_PREFIX" -type f \( -path '*/Net/SSLeay.pm' -o -path '*/Net/SSLeay.pod' \) -delete +# Prune IO::Socket::SSL as well: it is pure perl (no host-ABI impact) but +# hard-requires the Net::SSLeay XS module pruned above, so it could never +# load — and the official tarball's percona-perl tree does not ship it +# either (the only IO/Socket/SSL in the official artifact sits inside +# pgbackrest's private bin/vendor_perl bundle, which we do not stage). +find "$PERL_PREFIX" -type d -path '*/IO/Socket/SSL' -prune -exec rm -rf {} + +find "$PERL_PREFIX" -type f \( -path '*/IO/Socket/SSL.pm' -o -path '*/IO/Socket/SSL.pod' \) -delete + +# Copy libcrypt into Perl CORE dir (reference does this) +CORE_DIR=$(find $PERL_PREFIX -name "CORE" -type d | head -1) +if [ -n "$CORE_DIR" ] && [ -d "$CORE_DIR" ]; then + cp -a /usr/lib64/libcrypt.so* "$CORE_DIR/" 2>/dev/null || true + cp -a /usr/lib64/libxcrypt.so* "$CORE_DIR/" 2>/dev/null || true +fi + +# Man pages +mkdir -p $PERL_PREFIX/man/man1 $PERL_PREFIX/man/man3 +cp /usr/share/man/man1/perl*.1* $PERL_PREFIX/man/man1/ 2>/dev/null || true + +# Copy Perl utility scripts from /usr/bin/ +for script in corelist cpan enc2xs encguess h2ph h2xs instmodsh json_pp \ + libnetcfg perlbug perldoc perlivp perlthanks piconv pl2pm \ + pod2html pod2man pod2text pod2usage podchecker prove ptar \ + ptardiff ptargrep shasum splain streamzip xsubpp zipdetails; do + [ -f "/usr/bin/$script" ] && cp "/usr/bin/$script" $PERL_PREFIX/bin/ || true +done +# Update shebangs on Perl scripts to use bundled perl +for script in $PERL_PREFIX/bin/corelist $PERL_PREFIX/bin/cpan \ + $PERL_PREFIX/bin/enc2xs $PERL_PREFIX/bin/json_pp \ + $PERL_PREFIX/bin/pod2html $PERL_PREFIX/bin/pod2man \ + $PERL_PREFIX/bin/pod2text $PERL_PREFIX/bin/pod2usage \ + $PERL_PREFIX/bin/perldoc $PERL_PREFIX/bin/prove \ + $PERL_PREFIX/bin/ptar $PERL_PREFIX/bin/ptardiff \ + $PERL_PREFIX/bin/ptargrep $PERL_PREFIX/bin/shasum \ + $PERL_PREFIX/bin/instmodsh $PERL_PREFIX/bin/piconv \ + $PERL_PREFIX/bin/pl2pm $PERL_PREFIX/bin/podchecker \ + $PERL_PREFIX/bin/splain $PERL_PREFIX/bin/streamzip \ + $PERL_PREFIX/bin/xsubpp $PERL_PREFIX/bin/zipdetails; do + [ -f "$script" ] && \ + sed -i "1s|^#!.*perl.*|#!/opt/percona-perl/bin/perl|" "$script" || true +done + +############################################################### +# 11. Bundle Tcl -> /opt/percona-tcl +############################################################### +cp /usr/bin/tclsh${TCL_VER} $TCL_PREFIX/bin/ +ln -sf tclsh${TCL_VER} $TCL_PREFIX/bin/tclsh + +# Copy libtcl shared lib +cp -a /usr/lib64/libtcl${TCL_VER}.so $TCL_PREFIX/lib/ 2>/dev/null || true +cp -a /usr/lib64/libtclstub${TCL_VER}.a $TCL_PREFIX/lib/ 2>/dev/null || true + +# Tcl library directories (stdlib is in /usr/share/tclX.Y/, arch files in /usr/lib64/tclX.Y/) +mkdir -p $TCL_PREFIX/lib/tcl${TCL_VER} +[ -d /usr/share/tcl${TCL_VER} ] && cp -rp /usr/share/tcl${TCL_VER}/. $TCL_PREFIX/lib/tcl${TCL_VER}/ || true +[ -d /usr/lib64/tcl${TCL_VER} ] && cp -rp /usr/lib64/tcl${TCL_VER}/. $TCL_PREFIX/lib/tcl${TCL_VER}/ 2>/dev/null || true +cp -rp /usr/lib64/tcl8 $TCL_PREFIX/lib/ 2>/dev/null || true + +# Tcl extension packages +for ext in /usr/lib64/itcl* /usr/lib64/tdbc* /usr/lib64/thread* /usr/lib64/sqlite*; do + [ -e "$ext" ] && cp -rp "$ext" $TCL_PREFIX/lib/ || true +done + +# tclConfig.sh +cp /usr/lib64/tclConfig.sh $TCL_PREFIX/lib/ 2>/dev/null || true +cp /usr/lib64/tclooConfig.sh $TCL_PREFIX/lib/ 2>/dev/null || true + +# pkgconfig +mkdir -p $TCL_PREFIX/lib/pkgconfig +cp /usr/lib64/pkgconfig/tcl.pc $TCL_PREFIX/lib/pkgconfig/ 2>/dev/null || true + +# include/ +mkdir -p $TCL_PREFIX/include +cp /usr/include/tcl*.h $TCL_PREFIX/include/ 2>/dev/null || true +cp /usr/include/tclDecls.h $TCL_PREFIX/include/ 2>/dev/null || true + +# man pages +mkdir -p $TCL_PREFIX/man/man1 $TCL_PREFIX/man/man3 $TCL_PREFIX/man/mann +cp /usr/share/man/man1/tclsh*.1* $TCL_PREFIX/man/man1/ 2>/dev/null || true +cp /usr/share/man/man3/Tcl*.3* $TCL_PREFIX/man/man3/ 2>/dev/null || true +cp /usr/share/man/mann/*.n* $TCL_PREFIX/man/mann/ 2>/dev/null || true + +# sqlite3_analyzer (Tcl-based SQLite analysis tool) +for f in /usr/bin/sqlite3_analyzer /usr/lib64/sqlite3_analyzer \ + /usr/lib64/sqlite3/sqlite3_analyzer; do + [ -f "$f" ] && cp "$f" $TCL_PREFIX/bin/ && break || true +done + +############################################################### +# 12. Fix Perl, Tcl, Python for portable execution +############################################################### + +# --- Perl --- +# libperl.so.X.Y.Z lives in /usr/lib64, not inside perl5/ tree; copy into CORE +CORE_DIR=$(find $PERL_PREFIX -name "CORE" -type d | head -1) +if [ -n "$CORE_DIR" ]; then + # Copy only the real file (not symlinks) from /usr/lib64 + LIBPERL_REAL_PATH=$(find /usr/lib64 -maxdepth 1 -name "libperl.so.*" -not -type l | head -1) + LIBPERL_REAL=$(basename "$LIBPERL_REAL_PATH") + cp -p "$LIBPERL_REAL_PATH" "$CORE_DIR/" + # Recreate SONAME symlink and unversioned symlink pointing to real file + ln -sf "$LIBPERL_REAL" "$CORE_DIR/libperl.so.${PERL_VER%.*}" # e.g. libperl.so.5.32 + ln -sf "$LIBPERL_REAL" "$CORE_DIR/libperl.so" + # RPATH libperl itself: RUNPATH is not transitive, so libperl.so must be + # able to find its own deps (libcrypt copied into CORE/ above). + patchelf --set-rpath '$ORIGIN' "$CORE_DIR/$LIBPERL_REAL" +fi +# patchelf perl binary so dynamic linker finds libperl in CORE at $ORIGIN +patchelf --set-rpath "\$ORIGIN/../lib/${PERL_VER}/CORE" "$PERL_PREFIX/bin/perl" + +# --- Tcl --- +# patchelf tclsh so it finds libtclX.Y.so in $PREFIX/lib +patchelf --set-rpath '$ORIGIN/../lib' "$TCL_PREFIX/bin/tclsh${TCL_VER}" +# Replace tclsh symlink with wrapper that sets TCL_LIBRARY at runtime +rm -f "$TCL_PREFIX/bin/tclsh" +cat > "$TCL_PREFIX/bin/tclsh" << EOF +#!/bin/sh +SELFDIR="\$(cd "\$(dirname "\$0")" && pwd)" +PREFIX="\$(dirname "\$SELFDIR")" +export TCL_LIBRARY="\$PREFIX/lib/tcl${TCL_VER}" +export TCLLIBPATH="\$PREFIX/lib" +exec "\$SELFDIR/tclsh${TCL_VER}" "\$@" +EOF +chmod 755 "$TCL_PREFIX/bin/tclsh" + +# --- Python --- +# The RPM python3 binary has sys.prefix=/usr hardcoded; wrap it with PYTHONHOME +rm -f "$PYTHON_PREFIX/bin/python3" +cat > "$PYTHON_PREFIX/bin/python3" << EOF +#!/bin/sh +SELFDIR="\$(cd "\$(dirname "\$0")" && pwd)" +PREFIX="\$(dirname "\$SELFDIR")" +export PYTHONHOME="\$PREFIX" +# Prepend bundled lib/ so compiled extensions (e.g. _hashlib) find our OpenSSL +export LD_LIBRARY_PATH="\$PREFIX/lib\${LD_LIBRARY_PATH:+:\$LD_LIBRARY_PATH}" +exec "\$SELFDIR/python${PY_VER}" "\$@" +EOF +chmod 755 "$PYTHON_PREFIX/bin/python3" +ln -sf python3 "$PYTHON_PREFIX/bin/python" 2>/dev/null || true + +############################################################### +# 13. Bundle .so deps and patchelf RPATH for ELF prefixes +############################################################### +for prefix in $PG_PREFIX /opt/percona-pgbouncer \ + /opt/percona-pgpool-II /opt/percona-pgbackrest; do + bundle_deps "$prefix" + patch_rpath "$prefix" +done +# Python: also walk the whole lib/pythonX.Y tree (lib-dynload/ C extensions, +# site-packages extensions like psycopg2/_psycopg) so their NEEDED libs +# (libsqlite3, libncursesw, libuuid, libgdbm, libpq, ...) are bundled into +# $PYTHON_PREFIX/lib. +bundle_deps $PYTHON_PREFIX "$PYTHON_PREFIX/lib/python${PY_VER}" +patch_rpath $PYTHON_PREFIX +# RPATH the C extensions at the bundled lib dir: the python3 wrapper sets +# LD_LIBRARY_PATH, but embedded interpreters (plpython3 inside postgres.real) +# don't run through the wrapper, and the executable's RUNPATH does not apply +# to dlopened extensions' own deps. +find "$PYTHON_PREFIX/lib/python${PY_VER}" -type f -name '*.so*' | while read -r f; do + file "$f" 2>/dev/null | grep -q ELF || continue + patchelf --set-rpath '/opt/percona-python3/lib:$ORIGIN' "$f" +done +# Perl: walk the lib tree so XS-module deps (libdb for DB_File, libsombok +# for Unicode::LineBreak, ...) are bundled, then point the XS modules at +# the bundled libs (absolute /opt path — same convention as LANG_RPATH; +# depth under auto/ varies so $ORIGIN-relative paths won't work). +# Note: percona-perl/percona-tcl RPATHs for bin/ were already set in +# section 12 and bundle_deps does not touch RPATHs. +bundle_deps $PERL_PREFIX "$PERL_PREFIX/lib" +find "$PERL_PREFIX/lib" -type f -name '*.so' -path '*/auto/*' | while read -r f; do + patchelf --set-rpath '/opt/percona-perl/lib:$ORIGIN' "$f" +done +# Note: etcd (Go static), pgbadger (Perl script), patroni (Python) -- no bundling needed + +# Bundle OpenSSL into percona-python3 explicitly. +# _hashlib.cpython-*.so is compiled against the build env's OpenSSL (3.4+) which may +# be newer than what's on the target system. Bundling ensures Python works portably. +for f in /usr/lib64/libssl.so.3* /usr/lib64/libcrypto.so.3*; do + [ -f "$f" ] && cp -pn "$f" $PYTHON_PREFIX/lib/ 2>/dev/null || true +done + +############################################################### +# 14. Fix PostgreSQL RPATH to include language runtime paths +############################################################### +# Find the actual CORE directory path dynamically +PERL_CORE_DIR=$(find $PERL_PREFIX -name "CORE" -type d | head -1) +PERL_CORE_REL=${PERL_CORE_DIR#/opt/} # e.g., percona-perl/lib/5.32.1/CORE +LANG_RPATH='$ORIGIN/../lib:/opt/percona-python3/lib:/opt/'"${PERL_CORE_REL}"':/opt/percona-tcl/lib' +LANG_RPATH_LIB='$ORIGIN:/opt/percona-python3/lib:/opt/'"${PERL_CORE_REL}"':/opt/percona-tcl/lib' + +# Patch the real postgres binary ($PG_PREFIX/bin/postgres is the shell wrapper +# created in section 2c; postmaster no longer exists in PG >= 16). Mandatory — +# fail loudly if patchelf cannot rewrite it. +patchelf --set-rpath "$LANG_RPATH" "$PG_PREFIX/bin/postgres.real" + +# Patch PL language extension .so files +for ext in plperl.so plpython3.so pltcl.so; do + [ -f "$PG_PREFIX/lib/$ext" ] && \ + patchelf --set-rpath "$LANG_RPATH_LIB" "$PG_PREFIX/lib/$ext" 2>/dev/null || true +done + +# All other PostgreSQL lib/ .so files get $ORIGIN +find $PG_PREFIX/lib -name '*.so*' -type f | while read f; do + case "$(basename "$f")" in + plperl.so|plpython3.so|pltcl.so) continue ;; + esac + patchelf --set-rpath '$ORIGIN' "$f" 2>/dev/null || true +done + +############################################################### +# 15. Verification gate — fail the build on any breakage +############################################################### +# readelf is required by the OpenSSL host-ABI audit below. Assert it exists: +# if it were silently missing, the audit would see empty input and pass +# vacuously — the exact failure mode this gate exists to prevent. +command -v readelf >/dev/null || { echo "FATAL: readelf missing — SSL-ABI audit impossible" >&2; exit 1; } + +# The SSL variant labels follow the official tarball naming and map 1:1 to +# the EL base of each repository: EL8=ssl1.1, EL9=ssl3. Fail loudly on +# anything unmapped, e.g. a future EL10/EL11. +# The variant is derived here, before the gate, because the OpenSSL +# host-ABI audit below picks its allowed-symbol policy from it; section 16 +# reuses it for the artifact name. +EL_MAJOR=$( (. /etc/os-release 2>/dev/null && echo "${PLATFORM_ID#platform:el}") || true) +if [ -z "$EL_MAJOR" ]; then + # Buildroots without a release package (no /etc/os-release): fall back + # to glibc's %dist tag (glibc is present in every buildroot). + EL_MAJOR=$(rpm -q --qf '%{release}' glibc | sed -n 's/.*\.el\([0-9][0-9]*\).*/\1/p') +fi +case "$EL_MAJOR" in + 8) SSL_VARIANT=ssl1.1 ;; + 9) SSL_VARIANT=ssl3 ;; + *) echo "FATAL: unmapped EL major version '$EL_MAJOR'" >&2; exit 1 ;; +esac + +echo "=== Verification: NEEDED-soname audit ===" +# ldd would resolve against the fully-populated buildroot (ld.so.cache), hiding +# libraries we failed to bundle. Instead audit DT_NEEDED sonames directly: each +# must either be host-provided by design (is_system_lib) or bundled under /opt. +# Precompute the bundled-soname list once; a per-soname 'find /opt' rescan +# is O(tree size) for every NEEDED entry. -xtype f = regular files plus +# symlinks that resolve to one, so dangling symlinks never count as bundled. +find /opt -name '*.so*' -xtype f -printf '%f\n' | sort -u \ + > /tmp/bundled-sonames.txt +find /opt -type f \( -perm -u+x -o -name '*.so*' \) | while read -r f; do + file "$f" 2>/dev/null | grep -q ELF || continue + patchelf --print-needed "$f" 2>/dev/null | while read -r soname; do + if is_system_lib "$soname"; then + continue + fi + if ! grep -qxF "$soname" /tmp/bundled-sonames.txt; then + echo "UNRESOLVED: $f needs $soname (not bundled, not in system exclude list)" + fi + done +done > /tmp/needed-audit.txt +if [ -s /tmp/needed-audit.txt ]; then + cat /tmp/needed-audit.txt + echo "FATAL: unresolved libraries found" >&2 + exit 1 +fi + +echo "=== Verification: OpenSSL host-ABI audit ($SSL_VARIANT) ===" +# libssl/libcrypto are deliberately NOT bundled (they are on the system +# exclude list above), so every bundled binary resolves them from the HOST +# at run time. The ssl variant label is therefore a host-compatibility +# promise: ssl1.1 must run on hosts with OpenSSL 1.1, ssl3 on hosts with +# any OpenSSL 3.0+. What enforces that promise at the ELF level is the +# set of versioned symbol references (version +# NEEDS, e.g. OPENSSL_3.0.0) each binary carries against libssl/libcrypto: +# the host's loader refuses to start a binary that needs a version node +# the host libraries do not define. The buildroot may ship a NEWER OpenSSL +# than the promise (the EL9 buildroot has 3.5.x), so a staging rebuild +# could silently start referencing newer nodes — this audit turns the +# variant label into a tested guarantee. +# +# Per-variant allowed version-node pattern (anchored full-line grep): +case "$SSL_VARIANT" in + # Upstream OpenSSL 1.1 defines exactly two version nodes: OPENSSL_1_1_0 + # and OPENSSL_1_1_1. Allow ONLY those — Red Hat's 1.1.1 fork adds + # private nodes (e.g. OPENSSL_1_1_1b, referenced by EL8's krb5/libssh), + # which do not exist on stock-OpenSSL hosts (Debian 11 class), so any + # RH-fork leakage into bundled binaries must fail here at build time. + ssl1.1) OPENSSL_ALLOWED='OPENSSL_1_1_[01]' ;; + # Must run on any OpenSSL 3.0 host: only 3.0.x nodes are acceptable. + # Achievable on the EL9 base (Rocky 9.8+ ships OpenSSL 3.5) because + # staging percona-postgresql patches pgcrypto to avoid the + # EVP_MD_CTX_get_size_ex() 3.4 API — without that patch pgcrypto.so + # would reference OPENSSL_3.4.0 and fail this gate. + ssl3) OPENSSL_ALLOWED='OPENSSL_3\.0\.[0-9]*' ;; + *) echo "FATAL: no SSL-ABI policy for $SSL_VARIANT" >&2; exit 1 ;; +esac +# Scan every ELF under /opt EXCEPT the percona-python3 tree: the python +# component bundles its own OpenSSL copy (libssl/libcrypto in its lib/, +# used by lib-dynload extensions like _ssl/_hashlib and by site-packages +# extensions (psycopg2's _psycopg) whose OpenSSL needs resolve to the +# bundled copy), and its loaders are pointed at those bundled libs via +# RPATH/LD_LIBRARY_PATH — so the python tree's OpenSSL symbol needs are +# satisfied internally and are NOT part of the host promise. +find /opt -path /opt/percona-python3 -prune -o \ + -type f \( -perm -u+x -o -name '*.so*' \) -print | while read -r f; do + file "$f" 2>/dev/null | grep -q ELF || continue + # Parse the version NEEDS only — never version definitions. readelf -V + # prints up to three blocks (Version symbols / Version definition / + # Version needs); grepping the whole output would also match version + # DEFINITIONS (e.g. the bundled libs' own OPENSSL_* defs) and needs + # against non-OpenSSL libs (GLIBC_*). The awk below activates only + # inside the "Version needs section" block, tracks the current + # "File: " attribution line, and emits " " pairs + # only for the host-provided OpenSSL sonames (libssl.so.*/libcrypto.so.*). + readelf -V "$f" 2>/dev/null | awk ' + /^Version needs section/ { inneeds = 1; next } + /^Version (symbols|definition) section/ { inneeds = 0 } + !inneeds { next } + /File:/ { for (i = 1; i <= NF; i++) if ($i == "File:") fname = $(i + 1) } + /Name:/ && fname ~ /^lib(ssl|crypto)\.so/ { + for (i = 1; i <= NF; i++) if ($i == "Name:") print fname, $(i + 1) + } + ' | while read -r soname node; do + # Anchored match: the node must be entirely covered by the allowed + # pattern, otherwise it exceeds what the variant's hosts provide. + if ! echo "$node" | grep -qx "$OPENSSL_ALLOWED"; then + echo "SSL-ABI: $f references $node via $soname (exceeds $SSL_VARIANT promise)" + fi + done +done > /tmp/ssl-abi-audit.txt +if [ -s /tmp/ssl-abi-audit.txt ]; then + cat /tmp/ssl-abi-audit.txt + echo "FATAL: OpenSSL symbol-version needs exceed the $SSL_VARIANT promise" >&2 + exit 1 +fi + +echo "=== Verification: smoke commands ===" +env -u LD_LIBRARY_PATH "$PG_PREFIX/bin/initdb" --version +env -u LD_LIBRARY_PATH "$PG_PREFIX/bin/postgres.real" --version +"$PYTHON_PREFIX/bin/python3" -c 'import ssl, yaml; print("python OK")' +"$PYTHON_PREFIX/bin/python3" -c 'import patroni; print("patroni import OK")' +"$PERL_PREFIX/bin/perl" -e 'print "perl OK\n"' +echo 'puts "tcl OK"' | "$TCL_PREFIX/bin/tclsh" + +############################################################### +# 16. Create the final artifact with the official tarball name +############################################################### +# The simpleimage recipe names its own output from raw (unexpanded) +# Name:/Version: tags, which cannot vary per repository. Instead we +# write the artifact directly into /usr/src/packages/OTHER (collected +# by OBS as a build result) and skip /.simpleimage.tar.gz entirely. +PG_FULL_VERSION=$(rpm -q --qf '%{version}' "percona-postgresql${PG_MAJOR}-server") +# SSL_VARIANT was derived at the top of section 15 (EL-major mapping), +# where the OpenSSL host-ABI audit also depends on it. +TARBALL="percona-postgresql-${PG_FULL_VERSION}-${SSL_VARIANT}-linux-$(uname -m).tar.gz" +mkdir -p /usr/src/packages/OTHER +cd /opt +tar -czf "/usr/src/packages/OTHER/${TARBALL}" -- * +echo "Created ${TARBALL}" diff --git a/root/ppg/staging/17/tarballs/percona-postgresql-tarball/obs/simpleimage b/root/ppg/staging/17/tarballs/percona-postgresql-tarball/obs/simpleimage new file mode 100644 index 00000000..3a519abc --- /dev/null +++ b/root/ppg/staging/17/tarballs/percona-postgresql-tarball/obs/simpleimage @@ -0,0 +1,63 @@ +#!NoTarBall +#!NoSquashfs +Name: percona-postgresql +Version: %!{PG_VERSION} + +# PostgreSQL server and all extensions +BuildRequires: percona-postgresql%!{PG_MAJOR_VERSION} +BuildRequires: percona-postgresql%!{PG_MAJOR_VERSION}-server +BuildRequires: percona-postgresql%!{PG_MAJOR_VERSION}-contrib +BuildRequires: percona-postgresql%!{PG_MAJOR_VERSION}-libs +BuildRequires: percona-postgresql%!{PG_MAJOR_VERSION}-plpython3 +BuildRequires: percona-postgresql%!{PG_MAJOR_VERSION}-plperl +BuildRequires: percona-postgresql%!{PG_MAJOR_VERSION}-pltcl +BuildRequires: percona-postgresql%!{PG_MAJOR_VERSION}-devel +BuildRequires: percona-pg_tde%!{PG_MAJOR_VERSION} +BuildRequires: percona-pgaudit%!{PG_MAJOR_VERSION} +BuildRequires: percona-pgaudit%!{PG_MAJOR_VERSION}_set_user +BuildRequires: percona-pg_stat_monitor%!{PG_MAJOR_VERSION} +BuildRequires: percona-pg_repack%!{PG_MAJOR_VERSION} +BuildRequires: percona-pg_cron_%!{PG_MAJOR_VERSION} +BuildRequires: percona-wal2json%!{PG_MAJOR_VERSION} +BuildRequires: percona-pgvector_%!{PG_MAJOR_VERSION} +BuildRequires: percona-postgis35_%!{PG_MAJOR_VERSION} +BuildRequires: percona-pg-telemetry%!{PG_MAJOR_VERSION} +BuildRequires: percona-pg_gather +# Companion tools +BuildRequires: percona-pgbouncer +BuildRequires: percona-pgpool-II-pg%!{PG_MAJOR_VERSION} +BuildRequires: percona-pgpool-II-pg%!{PG_MAJOR_VERSION}-devel +BuildRequires: percona-pgpool-II-pg%!{PG_MAJOR_VERSION}-extensions +BuildRequires: percona-pgbackrest +BuildRequires: percona-pgbadger +BuildRequires: percona-patroni +BuildRequires: percona-patroni-aws +BuildRequires: etcd +BuildRequires: python3-pysyncobj +# Language runtimes +BuildRequires: python3.12 +BuildRequires: python3.12-pip +BuildRequires: python3.12-devel +# jmespath/s3transfer must be named explicitly: on the EL8 parallel-python +# stack the python3.12dist(...) rich-require generators do not run, so +# python3.12-boto3 carries no dependency that would pull them into the +# chroot transitively (buildinfo-verified). Without them here, section 8 of +# build-tarball.sh stages boto3/botocore but patroni_aws imports fail at +# run time. +BuildRequires: python3.12-jmespath +BuildRequires: python3.12-s3transfer +BuildRequires: perl +BuildRequires: perl-libs +BuildRequires: perl-devel +BuildRequires: tcl +BuildRequires: tcl-devel +# Build tools (binutils provides readelf for the verification gate) +BuildRequires: patchelf +BuildRequires: file +BuildRequires: binutils + +# The %build body is extracted verbatim by the simpleimage recipe and piped +# to a shell — no macro expansion happens here. Keep it a one-liner and put +# all build logic in the script. +%build +exec bash -x /usr/src/packages/SOURCES/build-tarball.sh diff --git a/root/ppg/staging/17/tarballs/project.yaml b/root/ppg/staging/17/tarballs/project.yaml new file mode 100644 index 00000000..165ffd8c --- /dev/null +++ b/root/ppg/staging/17/tarballs/project.yaml @@ -0,0 +1,86 @@ +title: Percona PostgreSQL %!{PG_MAJOR_VERSION} Tarballs +description: | + Binary tarball (simpleimage) builds for Percona Software for PostgreSQL + %!{PG_MAJOR_VERSION}. Each repository is one SSL variant of the official + tarball, built against a different EL base of ppg:staging:%!{PG_MAJOR_VERSION}: + ssl1.1 (RockyLinux 8), ssl3 (RockyLinux 9). + +repositories: + - name: ssl1.1 + paths: + - subproject: ppg:staging:%!{PG_MAJOR_VERSION} + repository: RockyLinux_8 + - subproject: ppg:common:deps + repository: RockyLinux_8 + - project: ${REMOTE_OBS_ORG_INTERCONNECT}Fedora:EPEL:8 + repository: standard + - project: ${REMOTE_OBS_ORG_INTERCONNECT}RockyLinux:8 + repository: appstream + - project: ${REMOTE_OBS_ORG_INTERCONNECT}RockyLinux:8 + repository: baseos + - project: ${REMOTE_OBS_ORG_INTERCONNECT}RockyLinux:8 + repository: devel + archs: [x86_64] + # ssl3 is EL9-based again. The original blocker (staging pgcrypto.so built + # on Rocky 9.8+ referenced OPENSSL_3.4.0 version nodes — RHEL 9.8 rebased + # to OpenSSL 3.5.x — breaking the "ssl3 runs on any OpenSSL 3.0 host" + # promise) is now fixed at the source: staging percona-postgresql carries + # a pgcrypto patch that avoids the EVP_MD_CTX_get_size_ex() 3.4 API, so + # EL9-built pgcrypto stays at OPENSSL_3.0.0. An interim Ubuntu 22.04 + # deb-based ssl3 was abandoned: the PGDG deb layout is non-relocatable + # (multiarch lib paths, /usr/share/postgresql split), unlike the PGDG RPM + # /usr/pgsql-NN prefix the tarball layout is derived from. + - name: ssl3 + paths: + - subproject: ppg:staging:%!{PG_MAJOR_VERSION} + repository: RockyLinux_9 + - subproject: ppg:common:deps + repository: RockyLinux_9 + - project: ${REMOTE_OBS_ORG_INTERCONNECT}Fedora:EPEL:9 + repository: standard + - project: ${REMOTE_OBS_ORG_INTERCONNECT}RockyLinux:9 + repository: standard + archs: [x86_64] + +publish: + ssl1.1: true + ssl3: true + +project-config: | + Type: simpleimage + + %if "%_repository" == "ssl1.1" + # Explicit binary format: "Type: simpleimage" above disables obs-build's + # recipe-type guessing (which would have derived it from the Preinstall + # list), and simpleimage is not one of the image types (kiwi, docker, ...) + # for which Build.pm re-derives the binary format, so without this the + # repo resolves with binarytype UNDEFINED. Harmless for RPM repos (the + # expander falls back to RPM semantics) but declare it anyway. + Binarytype: rpm + # Same install-time resolution hints as staging RockyLinux_8. + ExpandFlags: module:llvm-toolset-rhel8 + ExpandFlags: module:perl-5.26 + ExpandFlags: module:perl-IO-Socket-SSL-2.066 + ExpandFlags: module:perl-libwww-perl-6.34 + Prefer: python3-devel + Prefer: selinux-policy-targeted + # glibc requires the virtual "glibc-langpack"; every glibc-langpack-* + # (plus glibc-all-langpacks and glibc-minimal-langpack) provides it, and + # image-type expansion resolves the full runtime closure while ignoring + # the base config's "Ignore: glibc:glibc-langpack" rule, so OBS reports + # "have choice for glibc-langpack needed by glibc". Pick the minimal + # langpack (same fix as the ubi9 container project config). + Prefer: glibc-minimal-langpack + %endif + + %if "%_repository" == "ssl3" + # Explicit binary format (see the ssl1.1 comment). + Binarytype: rpm + # Same choice-resolution as staging RockyLinux_9 (hdf-libs vs hdf both + # provide libdf.so.0 — pulled in via the PostGIS/gdal dependency chain). + Prefer: hdf-libs + # Same glibc-langpack choice as ssl1.1 above: the EL9 base configs carry + # only "Ignore: glibc:glibc-langpack" (no Prefer), which image-type + # expansion ignores. + Prefer: glibc-minimal-langpack + %endif diff --git a/root/project.yaml b/root/project.yaml index 8026532e..bd1cb376 100644 --- a/root/project.yaml +++ b/root/project.yaml @@ -122,6 +122,8 @@ project-config: | ExpandFlags: module:perl-IO-Socket-SSL-2.066 ExpandFlags: module:perl-libwww-perl-6.34 Prefer: selinux-policy-targeted + Prefer: libverto-libev + Prefer: Lmod %endif %if "%_repository" == "RockyLinux_9" diff --git a/tests/test_meta_repo_filter.py b/tests/test_meta_repo_filter.py new file mode 100644 index 00000000..95911589 --- /dev/null +++ b/tests/test_meta_repo_filter.py @@ -0,0 +1,55 @@ +"""Unit tests for the --only-repos project-meta filter (percona_obs.obs_api). + +SSL-variant tarball repos (ssl1.1/ssl3/ssl3.5) must always survive the filter, +because their names never match a label-derived --only-repos set.""" + +from percona_obs.obs_api import _filter_meta_repos + + +def _names(repos): + return [r["name"] for r in repos] + + +def test_none_is_passthrough(): + repos = [{"name": "RockyLinux_8"}, {"name": "RockyLinux_9"}] + assert _filter_meta_repos(repos, None) == repos + + +def test_standard_filter_drops_non_matching(): + repos = [{"name": "RockyLinux_8"}, {"name": "RockyLinux_9"}, {"name": "Debian_13"}] + assert _names(_filter_meta_repos(repos, {"RockyLinux_9"})) == ["RockyLinux_9"] + + +def test_ssl_repos_survive_non_matching_filter(): + repos = [{"name": "ssl1.1"}, {"name": "ssl3"}] + # A distro-base label like RockyLinux_9 matches neither ssl repo, but both + # must be kept — otherwise the tarball project meta would be emptied. + assert _names(_filter_meta_repos(repos, {"RockyLinux_9"})) == ["ssl1.1", "ssl3"] + + +def test_mixed_project_keeps_matched_standard_and_all_ssl(): + repos = [ + {"name": "RockyLinux_8"}, + {"name": "RockyLinux_9"}, + {"name": "ssl1.1"}, + {"name": "ssl3"}, + {"name": "ssl3.5"}, + ] + assert _names(_filter_meta_repos(repos, {"RockyLinux_9"})) == [ + "RockyLinux_9", + "ssl1.1", + "ssl3", + "ssl3.5", + ] + + +def test_ssl_repo_also_matched_by_name_not_duplicated(): + repos = [{"name": "ssl3"}, {"name": "RockyLinux_9"}] + # ssl3 is both name-matched and ssl-prefixed; it appears exactly once. + assert _names(_filter_meta_repos(repos, {"ssl3"})) == ["ssl3"] + + +def test_empty_only_repos_still_keeps_ssl(): + # An empty set means "no standard repo selected"; ssl repos still survive. + repos = [{"name": "RockyLinux_9"}, {"name": "ssl3"}] + assert _names(_filter_meta_repos(repos, set())) == ["ssl3"]