diff --git a/ServiceVault.md b/ServiceVault.md index 3002959b..a1d7b0bb 100644 --- a/ServiceVault.md +++ b/ServiceVault.md @@ -30,7 +30,7 @@ Let us use the URL `wtv-1800:/preregister` as an example. This is what the serve - Access Asynchronous mode by setting `request_is_async = true;` - Client request headers are available as an Array in variable `request_headers`, query arguments are also an Array, in `request_headers.query` - In Asynchronous mode, you are expected to call `sendToClient(socket,headers,data)` yourself, `socket` is already defined by the time your script runs, so you can just pass it through. -- `./ServiceVault/wtv-1800/preregister.html` \[ [Example](zefie_wtvp_minisrv/ServiceVault/wtv-home/zefie.html) \] +- `./ServiceVault/wtv-1800/preregister.html` \[ [Example](zefie_wtvp_minisrv/ServiceVault/wtv-music/demo/index.html) \] - HTML match (*HTML mode*) - Like Direct File Mode, but you don't need to append `.html`. - You do not need to do anything special with this format. diff --git a/zefie_wtvp_minisrv/.gitignore b/zefie_wtvp_minisrv/.gitignore index 1c8fb1f0..2aef617a 100644 --- a/zefie_wtvp_minisrv/.gitignore +++ b/zefie_wtvp_minisrv/.gitignore @@ -8,9 +8,8 @@ ServiceLogPost/*_* # Large files not pertaining to the service code UserServiceVault/*-* -ServiceVault/wtv-flashrom/content/* -ServiceVault/wtv-music/content/* -ServiceVault/wtv-music/midi/* +package-lock.json + # User-specific files *.rsuser diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-1800/finish-prereg.js b/zefie_wtvp_minisrv/ServiceVault/wtv-1800/finish-prereg.js index 8278d416..abc141e0 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-1800/finish-prereg.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-1800/finish-prereg.js @@ -1,17 +1,21 @@ if (socket.ssid != null) { - if (ssid_sessions[socket.ssid].get("wtvsec_login")) ssid_sessions[socket.ssid].delete("wtvsec_login"); - var wtvsec_login = new WTVSec(); - wtvsec_login.IssueChallenge(); - wtvsec_login.set_incarnation(request_headers["wtv-incarnation"]); - ssid_sessions[socket.ssid].set("wtvsec_login", wtvsec_login); + if (!ssid_sessions[socket.ssid].data_store.wtvsec_login) { + ssid_sessions[socket.ssid].data_store.wtvsec_login = new WTVSec(); + ssid_sessions[socket.ssid].data_store.wtvsec_login.IssueChallenge(); + ssid_sessions[socket.ssid].data_store.wtvsec_login.set_incarnation(request_headers["wtv-incarnation"]); + } +} else { + var errpage = doErrorCode(400); + headers = errpage[0]; + data = errpage[1]; } -if (wtvsec_login) { +if (ssid_sessions[socket.ssid].data_store.wtvsec_login) { var prereg_contype = "text/html"; // if relogin, skip tellyscript if (request_headers.query.relogin) { // skip tellyscript - wtvsec_login.ticket_b64 = null; // clear old ticket + ssid_sessions[socket.ssid].data_store.wtvsec_login.ticket_b64 = null; // clear old ticket } // if relogin, skip tellyscript @@ -34,7 +38,7 @@ if (wtvsec_login) { headers = `200 OK Connection: Keep-Alive -wtv-initial-key: ` + wtvsec_login.challenge_key.toString(CryptoJS.enc.Base64) + ` +wtv-initial-key: ` + ssid_sessions[socket.ssid].data_store.wtvsec_login.challenge_key.toString(CryptoJS.enc.Base64) + ` Content-Type: `+ prereg_contype + ` wtv-service: reset ` + getServiceString('wtv-1800') + ` diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/get-by-path.js b/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/get-by-path.js index 764427c9..a18c64a6 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/get-by-path.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/get-by-path.js @@ -3,10 +3,31 @@ request_is_async = true; var request_path = unescape(request_headers.query.path); headers = "200 OK\n" +function doLocalFlashROM(flashrom_file_path) { + // use local flashrom files; + try { + fs.readFile(flashrom_file_path, null, function (err, data) { + if (err) { + errpage = doErrorPage(400) + headers = errpage[0]; + data = err.toString(); + } + sendToClient(socket, headers, data); + }); + } catch (e) { + var errpage = doErrorPage(404, "The service could not find the requested ROM.") + headers = errpage[0]; + data = errpage[1]; + sendToClient(socket, headers, data); + } +} + + if (request_headers.query.raw) { if ((/\.brom$/).test(request_path)) headers += "Content-Type: binary/x-wtv-bootrom"; // maybe? else headers += "Content-Type: binary/x-wtv-flashblock"; - if (minisrv_config.services[service_name].use_zefie_server) { + var flashrom_file_path = service_dir + '/' + request_path; + if (minisrv_config.services[service_name].use_zefie_server && !fs.existsSync(flashrom_file_path)) { // get flashrom files from archive.midnightchannel.net var options = { host: "archive.midnightchannel.net", @@ -40,23 +61,7 @@ if (request_headers.query.raw) { }); req.end(); } else { - // use local flashrom files); - var flashrom_file_path = service_dir + '/' + request_path; - try { - fs.readFile(flashrom_file_path, null, function (err, data) { - if (err) { - errpage = doErrorPage(400) - headers = errpage[0]; - data = err.toString(); - } - sendToClient(socket, headers, data); - }); - } catch (e) { - var errpage = doErrorPage(404, "The service could not find the requested ROM.") - headers = errpage[0]; - data = errpage[1]; - sendToClient(socket, headers, data); - } + doLocalFlashROM(flashrom_file_path); } } else { // no support for bf0app yet, but here we send the client to initiate-lc2-download diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/get-lc2-page.js b/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/get-lc2-page.js index 7dc63478..051eb77c 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/get-lc2-page.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/get-lc2-page.js @@ -4,13 +4,30 @@ // - handle failures request_is_async = true; +function doLocalFlashROM() { + fs.readFile(flashrom_file_path, null, function (err, data) { + try { + var data_128 = new Buffer.alloc(128); + data.copy(data_128, 0, 0, 128); + var flashrom_message = new Buffer.from(data_128.toString('hex').substring(36 * 2, 68 * 2), 'hex').toString('ascii').replace(/[^0-9a-z\ \.\-]/gi, ""); + processLC2DownloadPage(request_headers.query.path, flashrom_message, (request_headers.query.numparts || null)); + } catch (e) { + var errpage = doErrorPage(404, "The service could not find the requested ROM.") + headers = errpage[0]; + data = errpage[1]; + sendToClient(socket, headers, data); + } + }); +} + if (!request_headers.query.path) { var errpage = doErrorPage(400); headers = errpage[0]; data = errpage[1]; } else { var request_path = unescape(request_headers.query.path); - if (minisrv_config.services[service_name].use_zefie_server) { + var flashrom_file_path = service_dir + '/' + request_path; + if (minisrv_config.services[service_name].use_zefie_server && !fs.existsSync(flashrom_file_path)) { // read first 256 bytes of flashrom file from archive.midnightchannel.net // to get `flashrom_message` and `numparts` if missing var options = { @@ -60,21 +77,8 @@ if (!request_headers.query.path) { }); req.end(); } else { - // use local flashrom files - var flashrom_file_path = service_dir + '/' + request_path; - fs.readFile(flashrom_file_path, null, function (err, data) { - try { - var data_128 = new Buffer.alloc(128); - data.copy(data_128, 0, 0, 128); - var flashrom_message = new Buffer.from(data_128.toString('hex').substring(36 * 2, 68 * 2), 'hex').toString('ascii').replace(/[^0-9a-z\ \.\-]/gi, ""); - processLC2DownloadPage(request_headers.query.path, flashrom_message, (request_headers.query.numparts || null)); - } catch (e) { - var errpage = doErrorPage(404, "The service could not find the requested ROM.") - headers = errpage[0]; - data = errpage[1]; - sendToClient(socket, headers, data); - } - }); + // use local flashrom files + doLocalFlashROM(flashrom_file_path); } } @@ -195,7 +199,10 @@ ${flashrom_message} - + +
+ +
diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-home/home.js b/zefie_wtvp_minisrv/ServiceVault/wtv-home/home.js index e39da33d..f5c2065c 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-home/home.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-home/home.js @@ -1,6 +1,7 @@ headers =`200 OK Connection: Keep-Alive wtv-expire-all: wtv-home:/splash +wtv-expire-all: wtv-flashrom: Content-type: text/html` if (ssid_sessions[socket.ssid].get('box-does-psuedo-encryption')) { diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-tricks/blastcache.js b/zefie_wtvp_minisrv/ServiceVault/wtv-tricks/blastcache.js index 6e352b5c..8fff8d16 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-tricks/blastcache.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-tricks/blastcache.js @@ -6,7 +6,7 @@ Content-type: text/html` var visit_url = null; if (request_headers.Referer) visit_url = request_headers.Referer; -else if (request_headers.query.return_to) visit_url = request_headers.query.return_to; +else if (request_headers.query.return_to) visit_url = unescape(request_headers.query.return_to); else visit_url = "client:goback"; data = ` diff --git a/zefie_wtvp_minisrv/app.js b/zefie_wtvp_minisrv/app.js index 16ffdc43..5e20e8fe 100644 --- a/zefie_wtvp_minisrv/app.js +++ b/zefie_wtvp_minisrv/app.js @@ -453,6 +453,17 @@ async function sendToClient(socket, headers_obj, data) { headers_obj["Content-Length"] = data.byteLength; } + if (ssid_sessions[socket.ssid]) { + if (ssid_sessions[socket.ssid].data_store.wtvsec_login) { + if (ssid_sessions[socket.ssid].data_store.wtvsec_login.ticket_b64) { + if (ssid_sessions[socket.ssid].data_store.update_ticket) { + headers_obj["wtv-ticket"] = ssid_sessions[socket.ssid].data_store.wtvsec_login.ticket_b64; + headers_obj = moveObjectElement("wtv-ticket", "Connection", headers_obj); + ssid_sessions[socket.ssid].data_store.update_ticket = false; + } + } + } + } // header object to string if (zshowheaders) console.log(" * Outgoing headers on socket ID", socket.id, (await filterSSID(headers_obj))); @@ -604,6 +615,24 @@ async function processRequest(socket, data_hex, returnHeadersBeforeSecure = fals }); } + if (ssid_sessions[socket.ssid]) { + if (headers["wtv-ticket"]) { + if (!ssid_sessions[socket.ssid].data_store.wtvsec_login) { + ssid_sessions[socket.ssid].data_store.wtvsec_login = new WTVSec(); + ssid_sessions[socket.ssid].data_store.wtvsec_login.IssueChallenge(); + ssid_sessions[socket.ssid].data_store.wtvsec_login.set_incarnation(headers["wtv-incarnation"]); + ssid_sessions[socket.ssid].data_store.wtvsec_login.ticket_b64 = headers["wtv-ticket"]; + ssid_sessions[socket.ssid].data_store.wtvsec_login.DecodeTicket(ssid_sessions[socket.ssid].data_store.wtvsec_login.ticket_b64); + } else { + if (ssid_sessions[socket.ssid].data_store.wtvsec_login.ticket_b64 != headers["wtv-ticket"]) { + if (zdebug) console.log(" # New ticket from client"); + ssid_sessions[socket.ssid].data_store.wtvsec_login.ticket_b64 = headers["wtv-ticket"]; + ssid_sessions[socket.ssid].data_store.wtvsec_login.DecodeTicket(ssid_sessions[socket.ssid].data_store.wtvsec_login.ticket_b64); + } + } + } + } + if (returnHeadersBeforeSecure) { headers = await checkForPostData(socket, headers, data, data_hex); return headers; @@ -789,10 +818,9 @@ async function handleSocket(socket) { function integrateConfig(main, user) { Object.keys(user).forEach(function (k) { - if (typeof (user[k]) == 'object') { + if (typeof (user[k]) == 'object' && user[k] != null) { // new entry if (!main[k]) main[k] = new Array(); - // go down the rabbit hole main[k] = integrateConfig(main[k], user[k]); } else { diff --git a/zefie_wtvp_minisrv/config.json b/zefie_wtvp_minisrv/config.json index dad23fbd..5f175b8f 100644 --- a/zefie_wtvp_minisrv/config.json +++ b/zefie_wtvp_minisrv/config.json @@ -55,16 +55,16 @@ "http": { "port": 1650, "connections": 3, - "use_external_proxy": true, - "external_proxy_is_socks": true, + "use_external_proxy": false, + "external_proxy_is_socks": false, "external_proxy_host": "127.0.0.1", "external_proxy_port": 1080 }, "https": { "port": 1650, "connections": 3, - "use_external_proxy": true, - "external_proxy_is_socks": true, + "use_external_proxy": false, + "external_proxy_is_socks": false, "external_proxy_host": "127.0.0.1", "external_proxy_port": 1080 } diff --git a/zefie_wtvp_minisrv/package.json b/zefie_wtvp_minisrv/package.json index 60de7795..73193312 100644 --- a/zefie_wtvp_minisrv/package.json +++ b/zefie_wtvp_minisrv/package.json @@ -1,6 +1,6 @@ { "name": "zefie_wtvp_minisrv", - "version": "0.9.1", + "version": "0.9.2", "description": "WebTV Service (WTVP) Emulation Server", "main": "app.js", "homepage": "https://github.com/zefie/zefie_wtvp_minisrv", diff --git a/zefie_wtvp_minisrv/wtvsec.js b/zefie_wtvp_minisrv/wtvsec.js index 406c3ff2..147bc03d 100644 --- a/zefie_wtvp_minisrv/wtvsec.js +++ b/zefie_wtvp_minisrv/wtvsec.js @@ -51,14 +51,13 @@ class WTVSec { // store last challenge response in ticket var ticket_data = this.challenge_raw; try { - var ticket_data_enc = CryptoJS.DES.encrypt(ticket_data, this.current_shared_key, { + var ticket_data_enc = CryptoJS.DES.encrypt(ticket_data, this.initial_shared_key, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.NoPadding }); // create a copy of WordArray since concat modifies the original - var current_shared_key = this.DuplicateWordArray(this.current_shared_key); var challenge_signed_key = this.DuplicateWordArray(this.challenge_signed_key); - this.ticket_b64 = current_shared_key.concat(challenge_signed_key.concat(ticket_data_enc.ciphertext)).toString(CryptoJS.enc.Base64); + this.ticket_b64 = challenge_signed_key.concat(ticket_data_enc.ciphertext).toString(CryptoJS.enc.Base64); } catch (e) { console.log("Error encrypting ticket: " + e.toString()); return null; @@ -68,14 +67,13 @@ class WTVSec { DecodeTicket(ticket_b64) { var ticket_hex = CryptoJS.enc.Base64.parse(ticket_b64).toString(CryptoJS.enc.Hex); - var ticket_key = CryptoJS.enc.Hex.parse(ticket_hex.substring(0,16)); - var challenge_key = CryptoJS.enc.Hex.parse(ticket_hex.substring(16, 32)); - var challenge_enc = CryptoJS.enc.Hex.parse(ticket_hex.substring(32)); + var challenge_key = CryptoJS.enc.Hex.parse(ticket_hex.substring(0, 16)); + var challenge_enc = CryptoJS.enc.Hex.parse(ticket_hex.substring(16)); var ticket_dec = CryptoJS.DES.decrypt( { ciphertext: challenge_enc }, - ticket_key, + this.initial_shared_key, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.NoPadding diff --git a/zefie_wtvp_minisrv/zefie_wtvp_minisrv.njsproj b/zefie_wtvp_minisrv/zefie_wtvp_minisrv.njsproj index 4469c7a9..ca2a9579 100644 --- a/zefie_wtvp_minisrv/zefie_wtvp_minisrv.njsproj +++ b/zefie_wtvp_minisrv/zefie_wtvp_minisrv.njsproj @@ -202,7 +202,6 @@ Code - Code