fix(SniHandler): Improve TLS SNI session resumption handling: connections containing a session ticket are now only rejected when no SNI is present and allowSessionTicket is disabled. Updated return values and logging for clearer resumption detection.

This commit is contained in:
2025-03-11 19:38:41 +00:00
parent 3a1485213a
commit 62a3e1f4b7
4 changed files with 101 additions and 13 deletions

View File

@ -372,6 +372,58 @@ export class SniHandler {
pos += extensionLength;
}
// Check if SNI is included
let hasSNI = false;
// Reset position and scan again for SNI extension
pos = 5 + 1 + 3 + 2; // Reset to after handshake type, length and client version
pos += 32; // Skip client random
if (pos + 1 <= buffer.length) {
const sessionIdLength = buffer[pos];
pos += 1 + sessionIdLength;
// Skip cipher suites
if (pos + 2 <= buffer.length) {
const cipherSuitesLength = (buffer[pos] << 8) + buffer[pos + 1];
pos += 2 + cipherSuitesLength;
// Skip compression methods
if (pos + 1 <= buffer.length) {
const compressionMethodsLength = buffer[pos];
pos += 1 + compressionMethodsLength;
// Check for extensions
if (pos + 2 <= buffer.length) {
const extensionsLength = (buffer[pos] << 8) + buffer[pos + 1];
pos += 2;
// Extensions end position
const extensionsEnd = pos + extensionsLength;
if (extensionsEnd <= buffer.length) {
// Scan for SNI extension
while (pos + 4 <= extensionsEnd) {
const extensionType = (buffer[pos] << 8) + buffer[pos + 1];
pos += 2;
const extensionLength = (buffer[pos] << 8) + buffer[pos + 1];
pos += 2;
if (extensionType === this.TLS_SNI_EXTENSION_TYPE) {
hasSNI = true;
log('Found SNI extension');
break;
}
// Skip extension data
pos += extensionLength;
}
}
}
}
}
}
// Consider it a resumption if any resumption mechanism is present
const isResumption = hasSessionTicket || hasPSK || hasEarlyData ||
(hasNonEmptySessionId && !hasPSK); // Legacy resumption
@ -381,13 +433,18 @@ export class SniHandler {
(hasSessionTicket ? 'session ticket, ' : '') +
(hasPSK ? 'PSK, ' : '') +
(hasEarlyData ? 'early data, ' : '') +
(hasNonEmptySessionId ? 'session ID' : ''));
(hasNonEmptySessionId ? 'session ID' : '') +
(hasSNI ? ', with SNI' : ', without SNI'));
}
return isResumption;
// Return an object with both flags
return {
isResumption,
hasSNI
};
} catch (error) {
log(`Error checking for session resumption: ${error}`);
return false;
return { isResumption: false, hasSNI: false };
}
}