# Extended 6.4 — sqUnixSSL: serverName length truncated by strnlen → checked-vs-actual mismatch

Bug ref      : pharo.md §6.4
Severity     : MEDIUM (attacker-influenced serverName changes what's checked)
File         : extracted/plugins/SqueakSSL/src/unix/sqUnixSSL.c
Lines (HEAD) : ~309-323

## Problem

```c
serverNameLength = strnlen(ssl->serverName, MAX_HOSTNAME_LENGTH);
...
matched = X509_check_host(cert, ssl->serverName, serverNameLength, ..., NULL);
```

`strnlen` caps `serverNameLength` at `MAX_HOSTNAME_LENGTH`. A
serverName longer than that gets its length truncated. The cert
check then compares only the truncated prefix against the
certificate's SAN. An attacker who can influence the serverName
(via a redirect, header, or long URL) can drive a mismatch
between what the image *thinks* it's checking and what
`X509_check_host` actually checked.

## Fix

Reject overly-long serverNames before the check rather than
truncating.

```diff
diff --git a/plugins/SqueakSSL/src/unix/sqUnixSSL.c b/plugins/SqueakSSL/src/unix/sqUnixSSL.c
index 1af71037e..662bef2f6 100644
--- a/plugins/SqueakSSL/src/unix/sqUnixSSL.c
+++ b/plugins/SqueakSSL/src/unix/sqUnixSSL.c
@@ -306,7 +306,17 @@ sqInt sqConnectSSL(sqInt handle, char* srcBuf, sqInt srcLen, char *dstBuf, sqInt
 		ssl->peerName = NULL;
 
 		if (ssl->serverName) {
-			const size_t serverNameLength = strnlen(ssl->serverName, MAX_HOSTNAME_LENGTH);
+			/* Reject overly-long serverNames rather than silently truncating
+			 * the length passed to X509_check_host. Otherwise an attacker
+			 * who can influence serverName can drive a mismatch between
+			 * what the image thinks is checked and what really was. */
+			const size_t serverNameFull = strlen(ssl->serverName);
+			if (serverNameFull >= MAX_HOSTNAME_LENGTH) {
+				ssl->certFlags = SQSSL_OTHER_ISSUE;
+				X509_free(cert);
+				return SQSSL_GENERIC_ERROR;
+			}
+			const size_t serverNameLength = serverNameFull;
 			logTrace("sqConnectSSL: X509_check_host.");
 			/* Try IP first, expect INVALID_IP_STRING to continue with hostname */
 			matched = (enum sqMatchResult) X509_check_ip_asc(cert, ssl->serverName, 0);

```

## Test plan

- Set serverName to a 300-byte string. Before: cert check
  succeeds against the first MAX_HOSTNAME_LENGTH bytes. After:
  rejected as malformed.
- Normal serverName: unchanged.

## Risk notes

- The fix uses `strlen` on the caller-provided string; the caller
  must NUL-terminate it. SqueakSSL's image-side wrapper does.
