fix ipps certificate lookup
ci/woodpecker/push/build Pipeline was successful

This commit is contained in:
juergen committed 2026-10-19 20:39:02 +02:00
1 parent 548ae918ea
commit 50497780c7
7 files changed
+314 -15

No files matched your search

@@ -0,0 +1,75 @@
# Proposal
## Why
The previous change (`advertise-valid-ipps-certificate`) made the container
*generate* a certificate with the right subject alternative names, but clients
still get a certificate they do not trust. From the workstation,
`curl https://podp.local:631/` fails with `SSL certificate problem: unable to get
local issuer certificate`, and the certificate the server presents has
`CN=host.containers.internal` — not the certificate the entrypoint installed.
The reasoning in the previous change ("CUPS 2.4 keeps serving
`ServerCertificate`, so also write `<host name>.crt`") was wrong. Reading the
CUPS 2.4.2 sources:
- `ServerCertificate`/`ServerKey` are no longer supported. In `cupsd.conf` they
log "Please move … to the cups-files.conf file"; in `cups-files.conf` they log
"is no longer supported" and are ignored (`scheduler/conf.c`). The certificate
directory is `ServerKeychain` (default `ssl` → `/etc/cups/ssl`).
- On a server TLS handshake, `_httpTLSStart()` (`cups/tls-openssl.c`) ignores
the requested (SNI) name. It takes the **local socket address** the client
connected to, reverse-resolves it, and loads `<name>.crt` from the keychain
directory. A name that is not alphanumeric, `-` or `.` is mangled to `_`
(`http_make_path()`), and a numeric IPv6 result is used verbatim because CUPS
only rejects numeric names that start with a digit.
So with host networking the client's connection to the LAN address
`192.168.100.20` makes cupsd look for `/etc/cups/ssl/host.containers.internal.crt`
(the name Podman writes into `/etc/hosts` for the host address). That file did
not exist — only `<host name>.crt` and `<Avahi FQDN>.crt` were written — so cupsd
minted its own, which does not cover `podp.local`. IPv6 connections get a
certificate named after the IPv6 literal for the same reason. The previous
change's verification only checked `localhost`, where cupsd falls back to the
default common name and happened to find the copy.
## What Changes
- Derive the certificate copies from what cupsd actually looks up: write
`<name>.crt`/`<name>.key` for every DNS name in the SAN list **and** for every
local address (the address literal, mangled the way `http_make_path()` does,
plus whatever name the address reverse-resolves to). This covers the Podman
`host.containers.internal` name for the LAN address and the IPv6 literals.
- Keep the SAN list and the regeneration logic unchanged: the certificate
content was already correct and reissuing it is not desirable.
- Correct the comments, the README and the spec so they no longer claim
`ServerCertificate` is what makes cupsd serve our certificate. The directive
is kept only for CUPS versions older than 2.4.
Non-goals: generating a publicly trusted certificate or a private CA, adding the
local addresses to the certificate's IP SANs (that needs `CERT_EXTRA_NAMES` and
is out of scope), and changing the plain `_ipp` service.
## Capabilities
### New Capabilities
<!-- None: this hardens the certificate requirement added by the previous change. -->
### Modified Capabilities
- `printserver/cups`: the requirement that the secure AirPrint certificate
matches the advertised name gains a scenario for serving that certificate for
the address a client connected to, not only for the name it asked for.
## Impact
- `entrypoint.sh`: `install_default_cert_copy` now enumerates the local
addresses and cupsd's filename mangling; `ensure_cupsd_cert_directives`
comment corrected.
- `README.md`: certificate section explains how CUPS selects the certificate.
- `openspec/specs/printserver/cups/spec.md`: one scenario added to the
certificate requirement.
- Clients: fully validating clients (macOS/iOS AirPrint, `curl`) complete the
secure connection once they trust the certificate; plain IPP is unaffected.
- Existing deployments: an existing `/etc/cups` volume is fixed on the next
start; the certificate itself is not reissued, so clients that already trust
it keep trusting it.