Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -531,9 +531,15 @@ Three exceptions stand, each authorised rather than assumed:
**Anything else non-ASCII: ask.** Do not quietly pick a typographic character, and do
not quietly rewrite a sentence to avoid one — either way the decision goes unrecorded.

This is a rule about source. Documentation under `docs/` keeps typographic characters,
on the reasoning that prose of that length is written with an authoring tool; `README.md`
is hyphenated by hand and is the deliberate exception.
Documentation under `docs/` follows the same rule: write `-`, not an em or en dash.
One exception is worth knowing because the mechanical fix is wrong. A dash that a
hard wrap has left at the **start** of a line stays an em dash - a hyphen there is a
Markdown list marker, and converting it silently turns a sentence into a bullet.
Rewrap the paragraph or leave the character.

Pages are being converted as they are next edited rather than in a sweep, so most of
`docs/` still carries em dashes. Convert the whole of any page you are already
rewriting, so it is at least internally consistent.

### MISRA-load-bearing `.clang-format` settings

Expand Down
61 changes: 40 additions & 21 deletions docs/platforms/mbedtls/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,23 @@ Credentials are passed as caller-built, caller-owned handles: a seeded
`mbedtls_ctr_drbg_context` for the handshake, an `mbedtls_x509_crt` trust chain,
and for mutual TLS an `mbedtls_x509_crt` and `mbedtls_pk_context` pair. No part
of the adapter opens a file, which is what allows it to run on targets built
without `MBEDTLS_FS_IO`. Each handle must remain valid for the lifetime of the
stream.
without `MBEDTLS_FS_IO`.

Rotation follows from that, and needs sequencing. The adapter re-reads every
handle each time it connects, so replacing the material behind a handle is enough
the stream does not need rebuilding. But while a connection is open, the
adapter's `ssl_config` holds pointers into that material, and freeing it there is
a use-after-free.
Two lifetimes are in play and they are not the same. The **handle objects** must
stay addressable for as long as the stream might open a connection, because the
adapter reads the pointers it was given on every connect. The **parsed material
inside them** only has to be intact while a connection is open, which is when the
adapter's `ssl_config` holds pointers into it.

So: call `SolidSyslogSender_Disconnect` first, which releases the `ssl_config`,
then free and re-parse into the same handle. The next send reconnects with the
new material. There is no reload callback and none is needed.
Rotation follows from the second lifetime. Call `SolidSyslogSender_Disconnect`,
which releases the `ssl_config` and with it every pointer into the material, then
free and re-parse into the same handle. The next send reconnects with the new
material. Freeing before the disconnect completes is a use-after-free, because
the open connection is still reading it.

The adapter does not say when it has finished with the material, so an integrator
who wants the private key out of RAM between connections has to drive that
sequence themselves rather than being told. That is the gap recorded below.

## Coexistence is an auditable contract

Expand All @@ -51,14 +56,36 @@ claim can be checked against the directory.

## Where it differs from the contract

Five differences at 0.1.0, each tracked. Read them before relying on the
corresponding obligation.
Seven differences, each tracked. Read them before relying on the corresponding
obligation.

### A peer cannot be authorised by certificate fingerprint

Only certification path validation is offered, so a deployment with no PKI has no
way to pin the collector's certificate. Tracked as
[#753](https://github.com/cososo-ltd/solid-syslog/issues/753).

### A refused connection does not say which check refused it

An expired certificate, an untrusted chain and a name mismatch all surface as the
same handshake failure, so the report does not distinguish a certificate problem
from a network one. Tracked as
[#731](https://github.com/cososo-ltd/solid-syslog/issues/731).

### Credential material must stay parsed for the life of the stream

The adapter binds the handles into its `ssl_config` on each connection and drops
them on close, but it never says so, so every handle has to remain valid and
parsed for as long as the stream exists. A device that connects rarely still
holds its private key in RAM continuously, and there is no point at which the
adapter invites the integrator to release it. Tracked under
[E39](https://github.com/cososo-ltd/solid-syslog/issues/782).

### A half-supplied client credential is accepted in silence

A client certificate is presented only when both `ClientCertChain` and
`ClientKey` are supplied. Where either is absent the other is ignored, the
connection proceeds with server-authenticated TLS, and nothing is reported so a
connection proceeds with server-authenticated TLS, and nothing is reported, so a
device configured for mutual TLS can run without presenting its certificate, and
without anyone on the device knowing. The contract requires this to be reported.
Until it is, check for a half-supplied pair before you open the stream. Tracked as
Expand All @@ -72,14 +99,6 @@ handshake rejection from the collector rather than as a setup error on the
device, which sends you looking in the wrong place. Tracked as
[#719](https://github.com/cososo-ltd/solid-syslog/issues/719).

### An expired certificate stops delivery

A peer certificate that is expired or not yet valid fails the handshake, even
where it still chains to a trusted anchor. The contract asks for it to be
reported with delivery continuing, because clock skew is the dominant cause and a
device with a wrong clock is one whose logs you still want. Tracked as
[#731](https://github.com/cososo-ltd/solid-syslog/issues/731).

### The cipher policy cannot be expressed

The configuration carries no cipher or ciphersuite field, so the ciphersuites
Expand Down
42 changes: 27 additions & 15 deletions docs/platforms/openssl/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,36 @@ needs them present and readable by the process at the moment a connection is
made, not at startup.

The `SSL_CTX` is rebuilt on every open, re-reading each file named in the
configuration. Rotation is therefore a file replacement and a reconnection:
replace the file, and the new material is in force on the next connection —
either through ordinary reconnection after an outage, or immediately by calling
`SolidSyslogSender_Disconnect`. Nothing needs to be reloaded and nothing needs to
be restarted.
configuration, and freed on close. Nothing parsed from those files is held
between connections. Rotation is therefore a file replacement and a
reconnection: replace the file, and the new material is in force on the next
connection, either through ordinary reconnection after an outage or immediately
by calling `SolidSyslogSender_Disconnect`.

## Where it differs from the contract

Four differences at 0.1.0, each tracked. Read them before relying on the
corresponding obligation.
Six differences, each tracked. Read them before relying on the corresponding
obligation.

### A peer cannot be authorised by certificate fingerprint

Only certification path validation is offered, so a deployment with no PKI has no
way to pin the collector's certificate. Tracked as
[#753](https://github.com/cososo-ltd/solid-syslog/issues/753).

### A refused connection does not say which check refused it

An expired certificate, an untrusted chain and a name mismatch all surface as the
same handshake failure, so the report does not distinguish a certificate problem
from a network one. Tracked as
[#731](https://github.com/cososo-ltd/solid-syslog/issues/731).

### Credentials come from the filesystem, and only from there

The adapter opens the PEM files itself, so material held in a TPM, a keyring or
an encrypted store has to be written to a readable file before this adapter can
use it. Tracked under
[E39](https://github.com/cososo-ltd/solid-syslog/issues/782).

### A half-supplied client credential stops delivery

Expand All @@ -50,14 +70,6 @@ This adapter is stricter than the contract rather than weaker, and the stricter
behaviour is safe. Tracked as
[#734](https://github.com/cososo-ltd/solid-syslog/issues/734).

### An expired certificate stops delivery

A peer certificate that is expired or not yet valid fails the handshake, even
where it still chains to a trusted anchor. The contract asks for it to be
reported with delivery continuing, because clock skew is the dominant cause and a
device with a wrong clock is one whose logs you still want. Tracked as
[#731](https://github.com/cososo-ltd/solid-syslog/issues/731).

### The cipher policy does not bind a TLS 1.3 connection

The cipher list is passed to OpenSSL unchanged and pins nothing of the library's
Expand Down
Loading
Loading