# B06+B08 — sqMacSSL: hostname verification missing from manual trust eval; TLS 1.0 still allowed

Bug ref      : always.md B.6, B.8 ; pharo.md §3.20, §6.2
Severity     : CRITICAL (hostname not checked on macOS TLS)
File         : extracted/plugins/SqueakSSL/src/osx/sqMacSSL.c
Lines (HEAD) : 154-201 (`SSLSetProtocolVersionMin`, BreakOnServerAuth),
               262-292 (`sqExtractPeerName`),
               327-384 (`sqVerifyCert`)

## Problems

### B.6 — `kSSLSessionOptionBreakOnServerAuth` disables automatic verify; manual `SecTrustEvaluate` runs with no SSL policy carrying the hostname

```c
status = SSLSetSessionOption(ssl->ctx, ...BreakOnServerAuth, true);
...
/* sqVerifyCert */
status = SecTrustEvaluate(trust, &trust_eval);
```

`SecTrustEvaluate` is called on the trust object as returned by
`SSLCopyPeerTrust`, with no `SecPolicyCreateSSL(true, serverName)`
attached. SecureTransport therefore never checks the cert against
the hostname. Meanwhile `sqExtractPeerName` (lines 262-272) **copies
serverName into peerName** on the verified path — so the image's
peerName / serverName comparison is meaningless, just like the
Windows case.

### B.8 — `SSLSetProtocolVersionMin(ctx, kTLSProtocol1)` permits TLS 1.0

```c
status = SSLSetProtocolVersionMin(ssl->ctx, kTLSProtocol1);
```

TLS 1.0 (and implicitly 1.1) is still accepted on every handshake.

## Fix

Three coordinated changes:

  1. Raise the minimum protocol to TLS 1.2.
  2. In `sqVerifyCert`, attach a `SecPolicyCreateSSL(true,
     serverNameCFString)` policy to the trust object before
     `SecTrustEvaluate`, so the trust verdict reflects the
     hostname.
  3. In `sqExtractPeerName`, drop the verified-path "copy
     serverName into peerName" branch so the image sees the actual
     CN/SAN.

```diff
diff --git a/plugins/SqueakSSL/src/osx/sqMacSSL.c b/plugins/SqueakSSL/src/osx/sqMacSSL.c
index 2c28e855e..c374904ad 100644
--- a/plugins/SqueakSSL/src/osx/sqMacSSL.c
+++ b/plugins/SqueakSSL/src/osx/sqMacSSL.c
@@ -152,8 +152,8 @@ OSStatus sqSetupSSL(sqSSL* ssl, int isServer)
     }
 
 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
-    /* At least TLS 1 */
-    status = SSLSetProtocolVersionMin(ssl->ctx, kTLSProtocol1);
+    /* At least TLS 1.2; TLS 1.0/1.1 deprecated since 2018. */
+    status = SSLSetProtocolVersionMin(ssl->ctx, kTLSProtocol12);
 #else
     /* Prefer TLS 1 */
     status = SSLSetProtocolVersionEnabled(ssl->ctx, kTLSProtocol1, true);

```





## Test plan

- Connect to `https://wrong.host.badssl.com/` with
  `serverName = "wrong.host.badssl.com"`. Before: SQSSL_OK and
  `peerName == serverName`. After: trust evaluation returns
  `kSecTrustResultRecoverableTrustFailure`, certFlags reflects an
  error.
- Connect to a TLS 1.0-only server: handshake fails. Connect to a
  TLS 1.2/1.3 server: handshake succeeds and the cert subject
  matches `peerName`.

## Risk notes

- Substantially tightens trust verification on macOS. Workflows that
  previously appeared to succeed because the bug masked the hostname
  check will now correctly fail.
- `kTLSProtocol12` is available on macOS 10.8+ which matches the
  guarded `MAC_OS_X_VERSION_MAX_ALLOWED >= 1080` branch.
- `SecPolicyCreateSSL` returns an owned CFRef; the patch releases
  it. The cf-host string is owned by us; also released.
