1
0
mirror of https://github.com/coturn/coturn.git synced 2026-10-24 00:08:57 +03:00
Files
coturn/tests
Pavel Punsky d397f0ddeb Keep the legacy random nonce at 16 chars (#2032)
## What

The legacy (non-`--stateless-nonce`) challenge nonce has been 24 hex
chars instead of 16 since #2002, on every 64-bit server — including
those that never enabled `--stateless-nonce`.

## Why

`generate_random_challenge_nonce` writes each `turn_random_number()`
draw with `snprintf` and relies on the size bound to clip it. `"%08lx"`
of a 64-bit draw is *up to 16* hex chars, and `"%04x"` of a 32-bit draw
is 8 — the bound is what cuts each write back to 8. That bound was
`NONCE_MAX_SIZE`, which [grew from 17 to
25](https://github.com/coturn/coturn/blob/master/src/server/ns_turn_session.h)
when it was redefined as `TURN_STATELESS_NONCE_SIZE` to hold the 24-char
stateless nonce. The extra digits then went through:

| Platform | `sizeof(long)` | Branch | Before #2002 | On master |
|---|---|---|---|---|
| Linux/macOS x86-64, arm64 | 8 | `%08lx` | 16 chars | **24 chars** |
| Windows x64, 32-bit | 4 | `%04x` | 16 chars | **20 chars** |

Reproduced standalone with the exact expressions from the two loops:

```
sizeof(long)=8
old NONCE_MAX_SIZE=17: len=16 'deadbeefdeadbeef'
new NONCE_MAX_SIZE=25: len=24 'deadbeefdeadbeefcafebabf'
```

## Impact

Low, and not a security issue:

- **No overflow** — `ss->nonce` is `NONCE_MAX_SIZE` (25) bytes; the
maximum write is 24 + NUL.
- **No auth breakage** — validation is a `strcmp` against `ss->nonce`,
so the longer nonce round-trips.
- **Entropy went up, not down** — 96 bits vs. the previous 64 on LP64.
- **Still RFC-legal** — RFC 8489 §14.10 caps the nonce below 128
characters.

What it does break is a documented invariant: `ns_turn_session.h` and
`create_challenge_response` both state that the two nonce formats
*differ in length*, and `tests/test_stateless_nonce.c` asserts that
"legacy random-style 16-char nonces are not stateless nonces". On 64-bit
they no longer differ. Nothing branches on that length today
(`turn_check_stateless_nonce` rejects on the MAC, not the length), but
it is a trap for the next length-based fast path. Separately, an opt-in
feature silently changed wire output for deployments that did not opt
in.

## Change

- Add `TURN_RANDOM_NONCE_LENGTH` / `TURN_RANDOM_NONCE_SIZE` so each
nonce format is sized by its own constant.
- Extract the generation into `generate_random_challenge_nonce()`,
bounded by `TURN_RANDOM_NONCE_SIZE`, with a comment recording that the
bound — not the format specifier — is what fixes the width.
- Cover both loops with a unit test in the existing server-core harness.

Behavior is restored byte-for-byte to pre-#2002: the truncation
semantics are preserved rather than replaced with an explicit
bit-selection, which would have picked different bits.

## Validation

- `ctest` — 18/18 pass on macOS/arm64, 17/17 in Linux/Docker.
- Reverting just the bound fails the new test with `Expected 16 Was 24`.
- `run_tests.sh`, `run_tests_conf.sh`, `run_tests_stateless_nonce.sh`,
`run_tests_mobile.sh`, `run_tests_multiplex_peer.sh`,
`run_tests_dtls_default.sh`, `run_tests_rfc5780.sh` — all clean on
Linux; the first four also clean on macOS.
- `fuzzing/run-local.sh ASan 0 -runs=1` and `ASan 1 -runs=1` — clean.
- `clang-format-15` clean.
2026-08-02 19:50:09 -07:00
..
2026-04-27 08:34:38 -07:00
2026-07-26 23:04:31 -07:00
2026-05-24 09:56:03 -07:00
2026-05-24 09:56:03 -07:00
2026-05-24 09:56:03 -07:00
2026-05-24 09:56:03 -07:00
2026-05-24 09:56:03 -07:00
2026-05-24 09:56:03 -07:00
2026-06-09 23:02:29 -07:00
2026-05-24 09:56:03 -07:00
2026-05-24 09:56:03 -07:00
2026-07-31 21:38:36 -07:00