Skip to content

Scope SSLv2 as a separate dissector; confirm SSLv3-TLS1.3 generic coverage #2457

Closed

Description

@JarryShaw

Summary

Confirm the version range PR #2441's generic record-layer handling already covers, and scope the real gap: SSLv2, which has a structurally different wire format and needs its own dissector rather than fitting the SSL/TLS/DTLS base class.

What's already covered

pcapkit/protocols/application/ssl.py defines _TLS_VERSION_MAJOR = 0x03 and checks only the record's major version byte, not a fixed minor version. That one check structurally accepts every version whose wire byte is 0x03xx:

  • SSLv3 (0x0300)
  • TLS 1.0 (0x0301)
  • TLS 1.1 (0x0302)
  • TLS 1.2 (0x0303)
  • TLS 1.3 (wire-compatible legacy_version = 0x0303, real version negotiated via the supported_versions extension)

So SSLv3 through TLS 1.3 likely already parse at the record layer without per-version special-casing. This needs confirming with real packet captures once #2441 merges — this issue is scoped to that confirmation plus the SSLv2 gap, not a reopening of #2441.

What's missing

SSLv2 has a genuinely different wire format (confirmed against the original Netscape SSLv2 draft spec):

  • No content-type byte at the front of a record.
  • Record header is 2 or 3 bytes (not the 5-byte content-type + version + length SSLv3+/TLS layout): high bit of byte 0 set → 2-byte header, length = (byte[0] & 0x7f) << 8 | byte[1]; high bit clear → 3-byte padded header, length = (byte[0] & 0x3f) << 8 | byte[1], with an escape flag and a padding-length byte.
  • No 0x03xx-style version field on the wire at all — version appears only inside the CLIENT-HELLO/SERVER-HELLO handshake bodies (CLIENT-VERSION/SERVER-VERSION, e.g. 0x0002).
  • Its own handshake message-type numbering (0 ERROR through 8 CLIENT-CERTIFICATE), unrelated to SSLv3+'s handshake type enum.

This means SSLv2 cannot be handled by extending the existing _TLS_VERSION_MAJOR check or subclassing the current SSL/TLS/DTLS base — it needs its own dissector built around its own record and handshake framing.

SSLv1 was never publicly released (Netscape withdrew it internally over serious security flaws before shipping) — there is no real wire format to implement, and no implementation is needed for it.

Proposed scope for implementation

  1. Verify SSLv3–TLS 1.3 round-trip correctly through feat(application): implement TLS/SSL and DTLS record layer + handshake framing #2441's generic check with real ClientHello/ServerHello captures for each version.
  2. New dissector for SSLv2's distinct record/handshake format, following the project's existing protocol-class conventions.
  3. Explicitly document that SSLv1 is out of scope (never released) rather than leaving it silently unimplemented.

Activity

  1. added
    featPull requests that add a new capability (feat: subject prefix)
    pendingAccepted and unstarted - nobody is on it and nothing blocks it
    wipWork in flight - a covering PR is open or an agent is actively on it
    and removed
    pendingAccepted and unstarted - nobody is on it and nothing blocks it
    on Oct 30, 2026
  2. added this to the PyPCAPKit v1.5 milestone on Oct 30, 2026
  3. JarryShaw commented on Nov 1, 2026

    @JarryShaw
    OwnerAuthor

    SSLv2 landed in #2466. The other half, confirming that SSLv3 and TLS 1.0–1.3 parse at the record layer on real captures, had nobody on it, so its wip label was wrong. The repo has no real TLS capture, so a worker is checking publicly available sample captures outside the repo. It reports what parses and what doesn't, and this issue then either closes or gets a fix.

  4. JarryShaw commented on Nov 1, 2026

    @JarryShaw
    OwnerAuthor

    Confirmed on 14 public captures (Wireshark test/captures and Zeek btest traces; versions checked with tshark). SSLv3 and TLS 1.0–1.3 all parse at the record layer. Every record round-trips byte-exact when fed alone, and every TCP 443 segment that holds a whole record dispatches to TLS with the right alias, version, type and length. Records that fall to Raw are the known reassembly limit (#2441) or traffic on non-443 ports.

    Filed from the check: #2516 (the trial parse leaks SchemaWarnings) and #2517 (only the first record per segment is dissected). Not filed: TLS 1.3 draft-20 ServerHellos (pre-RFC); post-hello 1.3 records labelled 1.2 (the record header only carries 0x0303); TLS dispatched only on 443 (by registry design). Closing.

  5. removed
    wipWork in flight - a covering PR is open or an agent is actively on it
    on Nov 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    featPull requests that add a new capability (feat: subject prefix)

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions