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:
@ -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 };
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user