use UUID that can decode back to SSID

This commit is contained in:
zefie
2026-05-01 19:21:11 -04:00
parent 9400c1f917
commit 4f20c08ed0
2 changed files with 83 additions and 11 deletions

View File

@@ -4,11 +4,27 @@ let BoxId = request_headers.query.BoxId;
if (Array.isArray(BoxId)) BoxId = BoxId[0];
let clientIp = socket.remoteAddress;
let banned = false;
let sessionId = null;
if (!BoxId || BoxId.length != 20 || !/^\d+$/.test(BoxId))
{
console.warn("Invalid BoxId format "+BoxId+" from "+clientIp);
banned = true;
// Use the shared MSNTV2 helper injected by WTV-MSNTV2 VM context.
if (BoxId) {
if (!BoxId || BoxId.length != 20 || !/^\d+$/.test(BoxId))
{
console.warn("Invalid BoxId format "+BoxId+" from "+clientIp);
banned = true;
} else {
sessionId = encodeSessionID(BoxId);
}
} else if (request_headers.cookie.SessionID) {
BoxID = decodeSessionID(request_headers.cookie.SessionID);
sessionId = request_headers.cookie.SessionID;
} else {
console.warn("No BoxId provided by client "+clientIp);
banned = true;
}
if (!sessionId && !banned) {
banned = true;
}
// Current UTC time
@@ -42,8 +58,6 @@ const {
daylightOffset
} = timezoneMap["UTC"];
const sessionId = crypto.randomUUID();
ssid_sessions[socket.ssid] = new WTVClientSessionData(minisrv_config, socket.ssid);
ssid_sessions[socket.ssid].set('SessionID', sessionId);

View File

@@ -55,6 +55,52 @@ class WTVMSNTV2 {
return this.server;
}
// Encode a BoxID into a reversible UUID v8 (custom layout shared with MSNTV2 scripts).
static encodeSessionID(boxID) {
const source = String(boxID || '').trim();
if (!/^\d{1,20}$/.test(source)) return null;
let value = BigInt(source);
const data = new Uint8Array(9);
for (let i = 8; i >= 0; i--) {
data[i] = Number(value & 0xffn);
value >>= 8n;
}
if (value !== 0n) return null; // would not fit in 9 bytes
const uuid = new Uint8Array(16);
uuid[0] = data[0];
uuid[1] = data[1];
uuid[2] = data[2];
uuid[3] = data[3];
uuid[4] = data[4];
uuid[5] = data[5];
uuid[6] = 0x80; // version 8 (custom)
uuid[7] = data[6];
uuid[8] = 0x80; // variant
uuid[9] = data[7];
uuid[10] = data[8];
// uuid[11..15] remain zero padding
const h = Buffer.from(uuid).toString('hex');
return `${h.slice(0, 8)}-${h.slice(8, 12)}-${h.slice(12, 16)}-${h.slice(16, 20)}-${h.slice(20, 32)}`;
}
// Decode a reversible UUID v8 back to a 20-digit BoxID string.
// Returns null if the UUID does not match our custom layout.
static decodeSessionID(sessionID) {
const h = String(sessionID || '').replace(/-/g, '').toLowerCase();
if (!/^[0-9a-f]{32}$/.test(h)) return null;
const b = Buffer.from(h, 'hex');
if (b[6] !== 0x80 || b[8] !== 0x80) return null;
const data = [b[0], b[1], b[2], b[3], b[4], b[5], b[7], b[9], b[10]];
let big = 0n;
for (const byte of data) big = (big << 8n) | BigInt(byte);
return big.toString().padStart(20, '0');
}
// Set sslv2_debug: true in the service config to enable SSL/TLS protocol-level
// debug logging (handshake stages, cipher setup, record enc/dec, write previews).
// Defaults to false so normal operation is not flooded with crypto noise.
@@ -1425,11 +1471,17 @@ class WTVMSNTV2 {
if (boxId) {
socket.ssid = this.wtvshared.makeSafeSSID(boxId);
} else if (sessionId) {
// Find the ssid whose session_data has a matching stored session_id
const match = Object.keys(this.ssid_sessions).find(
k => this.ssid_sessions[k] && this.ssid_sessions[k].get && this.ssid_sessions[k].get('session_id') === sessionId
);
if (match) socket.ssid = match;
// Try direct decode first (reversible UUID v8 encodes BoxID directly)
const decoded = WTVMSNTV2.decodeSessionID(sessionId);
if (decoded) {
socket.ssid = this.wtvshared.makeSafeSSID(decoded);
} else {
// Fallback: search ssid_sessions for a matching stored session_id
const match = Object.keys(this.ssid_sessions).find(
k => this.ssid_sessions[k] && this.ssid_sessions[k].get && this.ssid_sessions[k].get('session_id') === sessionId
);
if (match) socket.ssid = match;
}
}
if (socket.ssid && !this.ssid_sessions[socket.ssid]) {
this.ssid_sessions[socket.ssid] = new this.WTVClientSessionData(this.minisrv_config, socket.ssid);
@@ -1454,6 +1506,12 @@ class WTVMSNTV2 {
sendToClient: (sock, hdrs, dat) => self._sendScriptResult(sock, request_headers, hdrs, dat),
minisrv_config: this.minisrv_config,
wtvshared: this.wtvshared,
encodeSessionID(boxID) {
return WTVMSNTV2.encodeSessionID(boxID);
},
decodeSessionID(sessionID) {
return WTVMSNTV2.decodeSessionID(sessionID);
},
cwd: path.dirname(filepath),
// Cookie helpers available to scripts
response_cookies: responseCookies,