tsp-tcp: reject malformed endpoint syntax instead of treating every split error as a missing port #9

Closed
opened 2026-07-21 17:20:19 +02:00 by heiko · 1 comment
Owner

Problem

internal/tsp-tcp.New calls net.SplitHostPort(addr) and, on every error, assumes the port is missing and calls net.JoinHostPort(addr, "318").

This conflates valid host-without-port input with malformed input. Examples needing explicit behavior include:

  • tcp://example.com:notaport
  • malformed bracketed IPv6
  • empty hosts
  • userinfo, query strings, fragments, or whitespace
  • ambiguous unbracketed IPv6

Some malformed values can be transformed into surprising bracketed hostnames and fail only later during dialing.

Checklist: #49 (validate at the boundary and return contextual errors).

Proposed fix

  • Parse the endpoint with a strict URL/authority parser or explicit host/port logic.
  • Require scheme tcp, no userinfo/path/query/fragment, and a nonempty host.
  • Add port 318 only when the authority genuinely omits a port.
  • Validate numeric/service ports and bracketed IPv6 syntax.
  • Store the normalized address only after all validation succeeds.

Note that the FreeTSA raw-DER TCP behavior is not RFC 3161 section 3.3 framing; keep protocol compatibility and endpoint syntax as separate concerns.

Acceptance criteria

  • Table tests cover DNS names, IPv4, bracketed IPv6, explicit/default ports, empty hosts, malformed ports/brackets, paths, query strings, fragments, and userinfo.
  • Invalid syntax fails in New, before any network operation.
  • Existing valid local endpoint tests pass.

Reviewed against 948b7a9 on master (Go 1.26.2).

## Problem `internal/tsp-tcp.New` calls `net.SplitHostPort(addr)` and, on every error, assumes the port is missing and calls `net.JoinHostPort(addr, "318")`. This conflates valid host-without-port input with malformed input. Examples needing explicit behavior include: - `tcp://example.com:notaport` - malformed bracketed IPv6 - empty hosts - userinfo, query strings, fragments, or whitespace - ambiguous unbracketed IPv6 Some malformed values can be transformed into surprising bracketed hostnames and fail only later during dialing. Checklist: #49 (validate at the boundary and return contextual errors). ## Proposed fix - Parse the endpoint with a strict URL/authority parser or explicit host/port logic. - Require scheme `tcp`, no userinfo/path/query/fragment, and a nonempty host. - Add port 318 only when the authority genuinely omits a port. - Validate numeric/service ports and bracketed IPv6 syntax. - Store the normalized address only after all validation succeeds. Note that the FreeTSA raw-DER TCP behavior is not RFC 3161 section 3.3 framing; keep protocol compatibility and endpoint syntax as separate concerns. ## Acceptance criteria - Table tests cover DNS names, IPv4, bracketed IPv6, explicit/default ports, empty hosts, malformed ports/brackets, paths, query strings, fragments, and userinfo. - Invalid syntax fails in `New`, before any network operation. - Existing valid local endpoint tests pass. Reviewed against `948b7a9` on `master` (Go 1.26.2).
Author
Owner

Strict endpoint validation and the complete valid/invalid endpoint table are complete.

Closing commit: b5c194322a89

Strict endpoint validation and the complete valid/invalid endpoint table are complete. Closing commit: [`b5c194322a89`](https://forgejo.schlittermann.de/heiko/mail-seal/commit/b5c194322a8904230e4771c9aa55d20065f30913)
heiko closed this issue 2026-07-21 23:07:51 +02:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
heiko/mailseal#9
No description provided.