diff --git a/README.md b/README.md index 68d9c232..5e88c245 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ This open source server is in alpha status. Use at your own risk. - wtv-update:/sync for Download-o-Rama style file downloading ### Current issues: -- Occasionally, in certain circumstances, a specific SSID may be unable to reconnect to the server until the server is restarted +- ~~Occasionally, in certain circumstances, a specific SSID may be unable to reconnect to the server until the server is restarted~~ *Hopefully fixed in [v0.9.3](https://github.com/zefie/zefie_wtvp_minisrv/releases/tag/v0.9.3)* - Mis-configuring wtv-update:/sync DiskMaps may cause units to delete contents of partitions (need more info) ### Won't fix: @@ -24,25 +24,23 @@ This open source server is in alpha status. Use at your own risk. - No intentions to support user accounts, registration, or any form of database system ### Feature Todo: -- ~~(maybe) implement HTTP proxy (needs to be able to defluff most of the web, think retro WAP converter)~~ ***Done*** -- ~~(maybe) enable "internet mode" (let user outside of minisrv)~~ ***Done*** -- ~~Flashrom flashing functionality (at least for LC2 and higher)~~ ***Done*** +- ~~Implement HTTP proxy (needs to be able to defluff most of the web, think retro WAP converter)~~ ***Done [v0.7.1](https://github.com/zefie/zefie_wtvp_minisrv/releases/tag/v0.7.1)*** +- ~~Flashrom flashing functionality (at least for LC2 and higher)~~ ***Done [v0.8.0](https://github.com/zefie/zefie_wtvp_minisrv/releases/tag/v0.8.0)*** +- ~~SSID/IP black/whitelisting (including tying SSID to an IP or multiple IPs)~~ ***Done [v0.9.4](https://github.com/zefie/zefie_wtvp_minisrv/releases/tag/v0.9.4)*** - Flashrom flashing for bf0app old classic (need donor unit) -- SSID/IP black/whitelisting (including tying SSID to an IP or multiple IPs) - wtv-lzpf support -- (maybe) Proper wtv-star (generic service outage page) support (maybe useful for allowing a unit to multiple sub-minisrvs). - (maybe) wtvchat stuff -- (probably not) url tokenizer (eg wtv-token-blabla, was mostly to secure service URLs from unintended access, which this server does not aim to do) ### How To Use: - Install [node.js](https://nodejs.org/en/download/). Be sure to say `Yes` when asked about `Chocolatey`. -- If you have trouble running it on Windows, try a Linux machine, Windows may need a full development enviroment or extra steps. - Download a snapshot (either of master, or of any commit/branch/relase/tag etc) - Extract zip somewhere and enter that directory with a command prompt - Enter `zefie_wtvp_minisrv` subdirectory - Verify you are in the same directory as `app.js`, then run `npm install` -- Check any configuration, and modify to your liking. Especally `service_ip` (config can be found in `services.json`) +- Check any configuration. Create your override `user_config.json`. Especally `service_ip`. See [user_config_README.md](user_config_README.md) and [user_config.example.json](zefie_wtvp_minisrv/user_config.example.json) for more information. + - **Note:** The intended use is for all custom config to be in `user_config.json` and any custom service files to go in `UserServiceVault`. If you do not care about potential issues with future `git pull`, and will manually add new upstream `config.json` entries, you could use the standard `ServiceVault` and `config.json` - Run `node app.js` +- If you have trouble running it on Windows, try a Linux machine, Windows may need a full development enviroment or extra steps. - Test with a WebTV Viewer or connect with a real box - To connect with a real box, you will need to open ports in your firewall and have a way to connect your WebTV (and preferably reroute 10.0.0.1 to the server) - See [ServiceVault.md](ServiceVault.md) for a brief introduction to how the service files work diff --git a/ServiceVault.md b/ServiceVault.md index a1d7b0bb..4dc99c59 100644 --- a/ServiceVault.md +++ b/ServiceVault.md @@ -1,14 +1,17 @@ ## Brief ServiceVault Explanation +In `user_config.json`, or `config.json`, under the `config` section: +``` + "ServiceVaults": [ + "UserServiceVault", + "ServiceVault" + ], +``` + +The `ServiceVaults` entry is an array of Service Vaults to check, in order of priority (topmost = check first). If the path is not absolute, the the server will look in the current directory (of `app.js`). An absolute path can be specified in Linux (`/home/zefie/ServiceVault`) or Windows (`C:\\Users\\zefie\\ServiceVault` or `C:/Users/zefie/ServiceVault`) format. + The server will scan configured ServiceVaults in order of priority and look for files within them. -Currently only 2 Service Vaults are supported, the `User Server Vault` and the `Service Vault`. - -The paths to the Service Vaults are user configurable in `user_config.json` or `config.json` - -The `User Service Vault` has priority, and files found in that Service Vault will be loaded, even if the -file exists in the `Service Vault`. - Within the Service Vaults, the server looks for a subdirectory named after the wtv-service URL requested. The server will then look for files in sequential order when requesting a URL, stopping at the first match. diff --git a/user_config_README.md b/user_config_README.md new file mode 100644 index 00000000..79d36bf4 --- /dev/null +++ b/user_config_README.md @@ -0,0 +1,85 @@ +# user_config.json Quick Guide +`user_config.json` is an override file, you do not need to redefine everything that is in `config.json`, just override the values you wish to. You must use the same structure as `config.json`, but can override any value. + +--- + +### `config` section +Some values are available that are not defined in `config.json` by default. I will attempt to cover them here. +``` + "service_logo": "WebTVLogoJewel.gif", + "service_splash_logo": "file://ROM/images/SplashLogo1.gif" +``` +You can set the image to be loaded in the top left in place of the WebTV or MSN logo, as well as the main Splash image shown on login. +If an absolute path (`wtv-url:/`, `file://` url, or `http(s)://` url) is not passed, the server will search for the specified filename in `wtv-star/images` of any Service Vault. You'll want to keep the filesizes low. +``` + "ssid_block_list": [ + "8100000000000000", + "8100000000000010" + ] +``` +This would ban the SSIDs `8100000000000000` and `8100000000000010` from the service, but allow all other SSIDs to connect. +``` + "ssid_ip_allow_list": { + "8100000000000000": [ + "192.168.1.0/24", + "127.0.0.1" + ] + } +``` +This would allow `8100000000000000` to connect, despite being on the block list, if it was connecting from the 192.168.1.0/24 Subnet, or from 127.0.0.1. +``` + "ssid_allow_list": [ + "8100000000000020", + "8100000000000030" + ] +``` +This would allow only the SSIDs `8100000000000020` and `8100000000000030` to use the service, and block all other SSIDs. Note that if you add an SSID/IP combo to the `ssid_ip_allow_list`, it will allow the SSID even if it is not in the whitelist. This is useful to allow a leaked SSID but only from trusted hosts. + +--- +### `service` section + +``` + "wtv-1800" { + "send_tellyscripts": true, + "send_tellyscript_ssid_whitelist": [ + "8100000000000000" + ] + } +``` +This override would enable sending of tellyscripts, but only to the box with SSID `8100000000000000`. The `send_tellyscript_ssid_whitelist` parameter is optional, and if not defined while `send_tellyscripts` is true, the server will simply send tellyscripts to all clients. +``` + "wtv-log": { + "write_logs_to_disk": true + } +``` +By default the wtv-log:/log service discards any submitted data from the WebTV units. You can override this by setting `write_logs_to_disk` to true, then it will save to the directory named `ServiceLogPost` in the same directory as `app.js`. + +``` + "wtv-some-custom-service": { + "port": 1609, + "connections": 1 + } +``` +You can easily define a custom service in your `user_config.json` + +``` + "wtv-tricks": { + "service_ip": "192.168.1.8", + "port": 1702, + "nobind": true + } +``` +The `wtv-tricks` example above shows how you could point a service to another minisrv. +``` + "wtv-1800": { + "port": 1715 + } +``` +The `wtv-1800` example above shows how you could override the default port for a service. + +``` + "wtv-music": { + "disabled": true + } +``` +The `wtv-music` example above shows how you could disable a default service without modifying `config.json` diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-1800/finish-prereg.js b/zefie_wtvp_minisrv/ServiceVault/wtv-1800/finish-prereg.js index 3ee2a2a0..b7e3f32c 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-1800/finish-prereg.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-1800/finish-prereg.js @@ -14,21 +14,29 @@ if (socket.ssid != null) { 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 + if (request_headers.query.relogin) { // relogin ssid_sessions[socket.ssid].data_store.wtvsec_login.ticket_b64 = null; // clear old ticket } - // if relogin, skip tellyscript + // if relogin and wtv-script-id != 0, skip tellyscript var romtype, file_path = null; - if (!request_headers.query.relogin && minisrv_config.config.send_tellyscripts) { - var romtype = ssid_sessions[socket.ssid].get("wtv-client-rom-type"); + var send_tellyscript = true; + var wtv_script_id = parseInt(ssid_sessions[socket.ssid].get("wtv-script-id")); + if (request_headers.query.relogin && wtv_script_id != 0) send_tellyscript = false; + if (send_tellyscript && minisrv_config.services[service_name].send_tellyscripts) { + if (minisrv_config.services[service_name].send_tellyscript_ssid_whitelist) { + var send_telly_to_ssid = (minisrv_config.services[service_name].send_tellyscript_ssid_whitelist.findIndex(element => element == socket.ssid) != -1) + if (send_telly_to_ssid) romtype = ssid_sessions[socket.ssid].get("wtv-client-rom-type"); + } else { + romtype = ssid_sessions[socket.ssid].get("wtv-client-rom-type"); + } } switch (romtype) { case "US-LC2-disk-0MB-8MB": prereg_contype = "text/tellyscript"; - if (ssid_sessions[socket.ssid].get("wtv-open-access")) var file_path = __dirname + "/ServiceDeps/premade_tellyscripts/LC2/LC2_OISP_5555732_56k.tok"; + // if wtv-open-access: true then client expects OpenISP + if (ssid_sessions[socket.ssid].get("wtv-open-access") == "true") var file_path = __dirname + "/ServiceDeps/premade_tellyscripts/LC2/LC2_OISP_5555732_56k.tok"; else var file_path = __dirname + "/ServiceDeps/premade_tellyscripts/LC2/LC2_WTV_18006138199_56k.tok"; break; 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 ccaf410c..fcc973e9 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/get-by-path.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/get-by-path.js @@ -29,7 +29,7 @@ if (request_headers.query.raw) { var flashrom_file_path = null; Object.keys(service_vaults).forEach(function (g) { if (flashrom_file_path != null) return; - flashrom_file_path = service_vaults[g].path + "/" + service_name + "/" + request_path; + flashrom_file_path = service_vaults[g] + "/" + service_name + "/" + request_path; if (!fs.existsSync(flashrom_file_path)) flashrom_file_path = null; }); if (minisrv_config.services[service_name].use_zefie_server && !flashrom_file_path) { 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 5f1e2050..e7e66602 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/get-lc2-page.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/get-lc2-page.js @@ -29,7 +29,7 @@ if (!request_headers.query.path) { var flashrom_file_path = null; Object.keys(service_vaults).forEach(function (g) { if (flashrom_file_path != null) return; - flashrom_file_path = service_vaults[g].path + "/" + service_name + "/" + request_path; + flashrom_file_path = service_vaults[g] + "/" + service_name + "/" + request_path; if (!fs.existsSync(flashrom_file_path)) flashrom_file_path = null; }); @@ -123,7 +123,7 @@ hspace=0 vspace=0 fontsize="large">
- + diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/lc2-download-complete.js b/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/lc2-download-complete.js index 06db1356..de414b98 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/lc2-download-complete.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/lc2-download-complete.js @@ -23,7 +23,7 @@ hspace=0 vspace=0 fontsize="large">
- + diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/lc2-download-failed.js b/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/lc2-download-failed.js index 6a5a5c52..e1667a42 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/lc2-download-failed.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/lc2-download-failed.js @@ -51,7 +51,7 @@ data = `
- + diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-head-waiter/login-stage-two.js b/zefie_wtvp_minisrv/ServiceVault/wtv-head-waiter/login-stage-two.js index 5ad309ac..608ba163 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-head-waiter/login-stage-two.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-head-waiter/login-stage-two.js @@ -50,9 +50,9 @@ Content-type: text/html`; } else { var namerand = Math.floor(Math.random() * 100000); - var nickname = 'HackTVUsr_' + namerand; + var nickname = minisrv_config.config.service_name+'_Usr_' + namerand; var userid = '1'+ Math.floor(Math.random() * 1000000000000000000); - var offline_user_list = CryptoJS.enc.Latin1.parse("\n\t\n").toString(CryptoJS.enc.Base64); + var offline_user_list = CryptoJS.enc.Latin1.parse("\n\t\n").toString(CryptoJS.enc.Base64); data = ''; headers = `200 OK Connection: Keep-Alive diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-home/home.js b/zefie_wtvp_minisrv/ServiceVault/wtv-home/home.js index 51e21954..d6a8cbab 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-home/home.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-home/home.js @@ -44,6 +44,6 @@ data += `width=250 height=10 bgcolor=#444444 text=#ffdd33 cursor=#cc9933 select ` -if (fs.existsSync(service_vaults[0].path + "/" + service_name + "/home.zefie.html")) { - data += fs.readFileSync(service_vaults[0].path + "/" + service_name + "/home.zefie.html", { 'encoding': 'utf8' }); +if (fs.existsSync(service_vaults[0] + "/" + service_name + "/home.zefie.html")) { + data += fs.readFileSync(service_vaults[0] + "/" + service_name + "/home.zefie.html", { 'encoding': 'utf8' }); } \ No newline at end of file diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-home/splash.js b/zefie_wtvp_minisrv/ServiceVault/wtv-home/splash.js new file mode 100644 index 00000000..7de72b69 --- /dev/null +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-home/splash.js @@ -0,0 +1,36 @@ +headers = `200 OK +Connection: Keep-Alive +wtv-expire-all: wtv- +wtv-expire-all: http +Content-type: text/html` + +data = ` + + +Engaging zefie... + + + + +
+ +
+ +


+


+


+ +
+Mini service +
+zefie minisrv v`+ minisrv_config.version; +if (getGitRevision()) { + data += ` (git ` + getGitRevision().substring(0,8) + `)`; +} +data += ` +
&rate; +
+

+ + +`; \ No newline at end of file diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-home/splash.txt b/zefie_wtvp_minisrv/ServiceVault/wtv-home/splash.txt deleted file mode 100644 index 1267aa4d..00000000 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-home/splash.txt +++ /dev/null @@ -1,26 +0,0 @@ -200 OK -Connection: Keep-Alive -wtv-expire-all: wtv- -wtv-expire-all: http -Content-type: text/html - - -Engaging zefie... - - - - - - - -
- -
- -
-
- - diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-star/images/HackTVLogo.gif b/zefie_wtvp_minisrv/ServiceVault/wtv-star/images/HackTVLogo.gif deleted file mode 100644 index 7df20035..00000000 Binary files a/zefie_wtvp_minisrv/ServiceVault/wtv-star/images/HackTVLogo.gif and /dev/null differ diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-star/images/MSNLogo.gif b/zefie_wtvp_minisrv/ServiceVault/wtv-star/images/MSNLogo.gif new file mode 100644 index 00000000..59b3829d Binary files /dev/null and b/zefie_wtvp_minisrv/ServiceVault/wtv-star/images/MSNLogo.gif differ diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-star/images/splash_logo_hacktv.gif b/zefie_wtvp_minisrv/ServiceVault/wtv-star/images/splash_logo_hacktv.gif new file mode 100644 index 00000000..cde26e3d Binary files /dev/null and b/zefie_wtvp_minisrv/ServiceVault/wtv-star/images/splash_logo_hacktv.gif differ diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-star/images/splash_logo_msn.gif b/zefie_wtvp_minisrv/ServiceVault/wtv-star/images/splash_logo_msn.gif new file mode 100644 index 00000000..e69ad2a0 Binary files /dev/null and b/zefie_wtvp_minisrv/ServiceVault/wtv-star/images/splash_logo_msn.gif differ diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-update/DealerDemo.html b/zefie_wtvp_minisrv/ServiceVault/wtv-update/DealerDemo.js similarity index 92% rename from zefie_wtvp_minisrv/ServiceVault/wtv-update/DealerDemo.html rename to zefie_wtvp_minisrv/ServiceVault/wtv-update/DealerDemo.js index 263a2a20..ecf03f93 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-update/DealerDemo.html +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-update/DealerDemo.js @@ -1,4 +1,7 @@ - +headers = `200 OK +Content-Type: text/html` + +data = `
- + @@ -45,4 +48,4 @@
- +` \ No newline at end of file diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-update/sync.js b/zefie_wtvp_minisrv/ServiceVault/wtv-update/sync.js index bf987f34..df0682fc 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-update/sync.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-update/sync.js @@ -103,7 +103,7 @@ function processGroup(diskmap_primary_group, diskmap_group_data, diskmap_subgrou var post_match_file = null; Object.keys(service_vaults).forEach(function (g) { if (post_match_file != null) return; - post_match_file = service_vaults[g].path + "/" + service_name + "/" + diskmap_group_data.files[k].location; + post_match_file = service_vaults[g] + "/" + service_name + "/" + diskmap_group_data.files[k].location; if (!fs.existsSync(post_match_file)) post_match_file = null; }); @@ -136,7 +136,7 @@ if (request_headers.query.diskmap && request_headers.query.group && request_head var diskmap_json_file = null; Object.keys(service_vaults).forEach(function (g) { if (diskmap_json_file != null) return; - diskmap_json_file = service_vaults[g].path + "/" + service_name + "/" + diskmap_dir + request_headers.query.diskmap + ".json"; + diskmap_json_file = service_vaults[g] + "/" + service_name + "/" + diskmap_dir + request_headers.query.diskmap + ".json"; if (!fs.existsSync(diskmap_json_file)) diskmap_json_file = null; }); diff --git a/zefie_wtvp_minisrv/app.js b/zefie_wtvp_minisrv/app.js index 9758b6c7..238a9099 100644 --- a/zefie_wtvp_minisrv/app.js +++ b/zefie_wtvp_minisrv/app.js @@ -89,14 +89,14 @@ async function processPath(socket, service_vault_file_path, request_headers = ne try { service_vaults.forEach(function (service_vault_dir) { if (service_vault_found) return; - service_vault_file_path = service_vault_dir.path + "/" + service_path.replace(/\\/g, "/"); + service_vault_file_path = service_vault_dir + "/" + service_path.replace(/\\/g, "/"); if (fs.existsSync(service_vault_file_path)) { // file exists, read it and return it service_vault_found = true; request_is_async = true; - if (!zquiet) console.log(" * Found " + service_vault_file_path + " in " + service_vault_dir.name +" to handle request (Direct File Mode) [Socket " + socket.id + "]"); + if (!zquiet) console.log(" * Found " + service_vault_file_path + " to handle request (Direct File Mode) [Socket " + socket.id + "]"); var contype = getConType(service_vault_file_path); headers = "200 OK\n" headers += "Content-Type: " + contype; @@ -106,7 +106,7 @@ async function processPath(socket, service_vault_file_path, request_headers = ne } else if (fs.existsSync(service_vault_file_path + ".txt")) { // raw text format, entire payload expected (headers and content) service_vault_found = true; - if (!zquiet) console.log(" * Found " + service_vault_file_path + ".txt in " + service_vault_dir.name +" to handle request (Raw TXT Mode) [Socket " + socket.id + "]"); + if (!zquiet) console.log(" * Found " + service_vault_file_path + ".txt to handle request (Raw TXT Mode) [Socket " + socket.id + "]"); request_is_async = true; fs.readFile(service_vault_file_path + ".txt", 'Utf-8', function (err, file_raw) { if (file_raw.indexOf("\n\n") > 0) { @@ -137,9 +137,9 @@ async function processPath(socket, service_vault_file_path, request_headers = ne // In Asynchronous mode, you are expected to call sendToClient(socket,headers,data) by the end of your script // `socket` is already defined and should be passed-through. service_vault_found = true; - if (!zquiet) console.log(" * Found " + service_vault_file_path + ".js in " + service_vault_dir.name + " to handle request (JS Interpreter mode) [Socket " + socket.id + "]"); + if (!zquiet) console.log(" * Found " + service_vault_file_path + ".js to handle request (JS Interpreter mode) [Socket " + socket.id + "]"); // expose var service_dir for script path to the root of the wtv-service - var service_dir = service_vault_dir.path.replace(/\\/g, "/") + "/" + service_name; + var service_dir = service_vault_dir.replace(/\\/g, "/") + "/" + service_name; socket_sessions[socket.id].starttime = Math.floor(new Date().getTime() / 1000); var jscript_eval = fs.readFileSync(service_vault_file_path + ".js").toString(); eval(jscript_eval); @@ -148,7 +148,7 @@ async function processPath(socket, service_vault_file_path, request_headers = ne else if (fs.existsSync(service_vault_file_path + ".html")) { // Standard HTML with no headers, WTV Style service_vault_found = true; - if (!zquiet) console.log(" * Found " + service_vault_file_path + ".html in " + service_vault_dir.name +" to handle request (HTML Mode) [Socket " + socket.id + "]"); + if (!zquiet) console.log(" * Found " + service_vault_file_path + ".html to handle request (HTML Mode) [Socket " + socket.id + "]"); request_is_async = true; headers = "200 OK\n" headers += "Content-Type: text/html" @@ -186,7 +186,7 @@ async function processPath(socket, service_vault_file_path, request_headers = ne } function filterSSID(obj) { - if (minisrv_config.config.hide_ssid_in_logs) { + if (minisrv_config.config.hide_ssid_in_logs === true) { if (typeof (obj) == "string") { if (obj.substr(0, 8) == "MSTVSIMU") { return obj.substr(0, 10) + ('*').repeat(10) + obj.substr(20); @@ -598,7 +598,86 @@ async function processRequest(socket, data_hex, returnHeadersBeforeSecure = fals ssid_sessions[socket.ssid] = new ClientSessionData(); } if (!ssid_sessions[socket.ssid].data_store.sockets) ssid_sessions[socket.ssid].data_store.sockets = new Array(); - ssid_sessions[socket.ssid].data_store.sockets.push(socket.id); + ssid_sessions[socket.ssid].data_store.sockets.push(socket.id); + } + + var ip2long = function (ip) { + var components; + + if (components = ip.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/)) { + var iplong = 0; + var power = 1; + for (var i = 4; i >= 1; i -= 1) { + iplong += power * parseInt(components[i]); + power *= 256; + } + return iplong; + } + else return -1; + }; + + var isInSubnet = function (ip, subnet) { + var mask, base_ip, long_ip = ip2long(ip); + if ((mask = subnet.match(/^(.*?)\/(\d{1,2})$/)) && ((base_ip = ip2long(mask[1])) >= 0)) { + var freedom = Math.pow(2, 32 - parseInt(mask[2])); + return (long_ip > base_ip) && (long_ip < base_ip + freedom - 1); + } + else return false; + }; + + var rejectSSIDConnection = function (ssid, blacklist) { + if (blacklist) console.log(" * Request from SSID", filterSSID(ssid), "(" + socket.remoteAddr + "), but that SSID is in the blacklist, rejecting."); + else console.log(" * Request from SSID", filterSSID(socket.ssid), "(" + socket.remoteAddress + "), but that SSID is not in the whitelist, rejecting."); + + var errpage = doErrorPage(401, "Access to this service is denied."); + headers = errpage[0]; + data = errpage[1]; + socket_sessions[socket.id].close_me = true; + } + + var checkSSIDIPWhitelist = function (ssid, blacklist) { + var ssid_access_list_ip_override = false; + if (minisrv_config.config.ssid_ip_allow_list) { + if (minisrv_config.config.ssid_ip_allow_list[socket.ssid]) { + Object.keys(minisrv_config.config.ssid_ip_allow_list[socket.ssid]).forEach(function (k) { + if (minisrv_config.config.ssid_ip_allow_list[socket.ssid][k].indexOf('/') > 0) { + if (isInSubnet(socket.remoteAddress, minisrv_config.config.ssid_ip_allow_list[socket.ssid][k])) { + // remoteAddr is in allowed subnet + ssid_access_list_ip_override = true; + } + } else { + if (socket.remoteAddress == minisrv_config.config.ssid_ip_allow_list[socket.ssid][k]) { + // remoteAddr directly matches IP + ssid_access_list_ip_override = true; + } + } + }); + if (!ssid_access_list_ip_override) rejectSSIDConnection(socket.ssid, blacklist); + } else { + rejectSSIDConnection(socket.ssid, blacklist); + } + } else { + rejectSSIDConnection(socket.ssid, blacklist); + } + if (ssid_access_list_ip_override && zdebug) console.log(" * Request from disallowed SSID", filterSSID(ssid), "was allowed due to IP address whitelist"); + } + + // process whitelist first + if (socket.ssid && minisrv_config.config.ssid_allow_list) { + var ssid_is_in_whitelist = minisrv_config.config.ssid_allow_list.findIndex(element => element == socket.ssid); + if (ssid_is_in_whitelist == -1) { + // no whitelist match, but lets see if the remoteAddress is allowed + checkSSIDIPWhitelist(socket.ssid, false); + } + } + + // now check blacklist + if (socket.ssid && minisrv_config.config.ssid_block_list) { + var ssid_is_in_blacklist = minisrv_config.config.ssid_block_list.findIndex(element => element == socket.ssid); + if (ssid_is_in_blacklist != -1) { + // blacklist match, but lets see if the remoteAddress is allowed + checkSSIDIPWhitelist(socket.ssid, true); + } } @@ -756,7 +835,7 @@ async function cleanupSocket(socket) { delete socket_sessions[socket.id]; } if (socket.ssid) { - var socket_array_index = ssid_sessions[socket.ssid].data_store.sockets.findIndex(element => element = socket.id); + var socket_array_index = ssid_sessions[socket.ssid].data_store.sockets.findIndex(element => element == socket.id); if (socket_array_index != -1) { ssid_sessions[socket.ssid].data_store.sockets.splice(socket_array_index,1); } @@ -849,6 +928,19 @@ function returnAbsolsutePath(path) { } +function getGitRevision() { + try { + const rev = fs.readFileSync(__dirname.replace(/\\/g, "/") + '/../.git/HEAD').toString().trim(); + if (rev.indexOf(':') === -1) { + return rev; + } else { + return fs.readFileSync(__dirname.replace(/\\/g, "/") + '/../.git/' + rev.substring(5)).toString().trim(); + } + } catch (e) { + return null; + } +} + // SERVER START var z_title = "zefie's wtv minisrv v" + require('./package.json').version; @@ -886,11 +978,15 @@ if (throw_me) { throw ("An error has occured while reading the configuration files."); } -if (minisrv_config.config.UserServiceVault) service_vaults.push({ "path": returnAbsolsutePath(minisrv_config.config.UserServiceVault), "name": "User Service Vault" }); -service_vaults.push({ "path": returnAbsolsutePath(minisrv_config.config.ServiceVault), "name": "Service Vault" }); -Object.keys(service_vaults).forEach(function (k) { - console.log(" * Using", service_vaults[k].name, "at", service_vaults[k].path); -}); +if (minisrv_config.config.ServiceVaults) { + Object.keys(minisrv_config.config.ServiceVaults).forEach(function (k) { + var service_vault = returnAbsolsutePath(minisrv_config.config.ServiceVaults[k]); + service_vaults.push(service_vault); + console.log(" * Configured Service Vault at", service_vault, "with priority",(parseInt(k)+1)); + }) +} else { + throw ("ERROR: No Service Vaults defined!"); +} var service_ip = minisrv_config.config.service_ip; Object.keys(minisrv_config.services).forEach(function (k) { @@ -917,7 +1013,13 @@ Object.keys(minisrv_config.services).forEach(function (k) { } console.log(" * Configured Service", k, "on Port", minisrv_config.services[k].port, "- Host", minisrv_config.services[k].host, "- Bind Port:", !minisrv_config.services[k].nobind); }) -if (minisrv_config.config.hide_ssid_in_logs) console.log(" * Masking SSIDs in the console for security"); +if (minisrv_config.config.hide_ssid_in_logs) console.log(" * Masking SSIDs in console logs for security"); +else console.log(" * Full SSIDs will be shown in console logs"); + +if (minisrv_config.config.service_logo.indexOf(':') == -1) minisrv_config.config.service_logo = "wtv-star:/images/" + minisrv_config.config.service_logo; +if (minisrv_config.config.service_splash_logo.indexOf(':') == -1) minisrv_config.config.service_splash_logo = "wtv-star:/images/" + minisrv_config.config.service_splash_logo; + +minisrv_config.version = require('./package.json').version; // defaults var zdebug = false; @@ -964,17 +1066,19 @@ ports.sort(); // de-duplicate ports in case user configured multiple services on same port const bind_ports = [...new Set(ports)] - +if (!minisrv_config.config.bind_ip) minisrv_config.config.bind_ip = "0.0.0.0"; bind_ports.forEach(function (v) { try { var server = net.createServer(handleSocket); - server.listen(v, '0.0.0.0'); + server.listen(v, minisrv_config.config.bind_ip); initstring += v + ", "; } catch (e) { - throw ("Could not bind to port", v, e.toString()); + throw ("Could not bind to port", v, "on", minisrv_config.config.bind_ip, e.toString()); } }); initstring = initstring.substring(0, initstring.length - 2); -console.log(" * Started server on ports " + initstring + "... Service IP is " + service_ip); +console.log(" * Started server on ports " + initstring + "...") +var listening_ip_string = (minisrv_config.config.bind_ip != "0.0.0.0") ? "IP: " + minisrv_config.config.bind_ip : "all interfaces"; +console.log(" * Listening on", listening_ip_string,"~","Service IP:", service_ip); diff --git a/zefie_wtvp_minisrv/config.json b/zefie_wtvp_minisrv/config.json index 5f175b8f..34804678 100644 --- a/zefie_wtvp_minisrv/config.json +++ b/zefie_wtvp_minisrv/config.json @@ -1,19 +1,22 @@ { "config": { "service_ip": "0.0.0.0", - "ServiceVault": "ServiceVault", - "UserServiceVault": "UserServiceVault", - "service_name": "HackTV", - "send_tellyscripts": false, + "ServiceVaults": [ + "UserServiceVault", + "ServiceVault" + ], + "service_name": "MSNTV", + "service_logo": "MSNLogo.gif", + "service_splash_logo": "splash_logo_msn.gif", "hide_ssid_in_logs": true, - "socket_timeout": 350, + "socket_timeout": 350, "verbosity": 2 }, "services": { "wtv-1800": { - "host": null, "port": 1615, - "connections": 1 + "connections": 1, + "send_tellyscripts": false }, "wtv-star": { "port": 1603, diff --git a/zefie_wtvp_minisrv/package-lock.json b/zefie_wtvp_minisrv/package-lock.json index 16578ae8..e807ee3e 100644 --- a/zefie_wtvp_minisrv/package-lock.json +++ b/zefie_wtvp_minisrv/package-lock.json @@ -1,6 +1,6 @@ { "name": "zefie_wtvp_minisrv", - "version": "0.9.1", + "version": "0.9.4", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/zefie_wtvp_minisrv/package.json b/zefie_wtvp_minisrv/package.json index 4d9dba7f..b8b8d4b1 100644 --- a/zefie_wtvp_minisrv/package.json +++ b/zefie_wtvp_minisrv/package.json @@ -1,6 +1,6 @@ { "name": "zefie_wtvp_minisrv", - "version": "0.9.3", + "version": "0.9.4", "description": "WebTV Service (WTVP) Emulation Server", "main": "app.js", "homepage": "https://github.com/zefie/zefie_wtvp_minisrv", diff --git a/zefie_wtvp_minisrv/user_config.example.json b/zefie_wtvp_minisrv/user_config.example.json index b6e9f49a..48bce41c 100644 --- a/zefie_wtvp_minisrv/user_config.example.json +++ b/zefie_wtvp_minisrv/user_config.example.json @@ -1,12 +1,36 @@ { "config": { - "service_ip": "192.168.11.8", - "service_name": "MyWebTV", - "send_tellyscripts": true, + "service_ip": "192.168.1.8", + "service_name": "WebTV", + "service_logo": "WebTVLogoJewel.gif", + "service_splash_logo": "file://ROM/images/SplashLogo1.gif", + "ServiceVaults": [ + "UserServiceVault", + "ServiceVault", + "C:\\users\\zefie\\webtv\\ServiceVault", + "C:/Users/zefie/webtv/ServiceVault2", + "/home/zefie/webtv/ServiceVault" + ], + "ssid_block_list": [ + "8100000000000000", + "8100000000000010" + ], + "ssid_ip_allow_list": { + "8100000000000000": [ + "192.168.1.0/24", + "127.0.0.1" + ] + }, "hide_ssid_in_logs": true, - "verbosity": 0 + "verbosity": 2 }, "services": { + "wtv-1800": { + "send_tellyscripts": true, + "send_tellyscript_ssid_whitelist": [ + "8100000000000000" + ] + }, "wtv-log": { "write_logs_to_disk": true }, @@ -15,7 +39,7 @@ "connections": 1 }, "wtv-tricks": { - "service_ip": "192.168.11.8", + "service_ip": "192.168.1.8", "port": 1702, "nobind": true }, diff --git a/zefie_wtvp_minisrv/zefie_wtvp_minisrv.njsproj b/zefie_wtvp_minisrv/zefie_wtvp_minisrv.njsproj index ca2a9579..f64c45c9 100644 --- a/zefie_wtvp_minisrv/zefie_wtvp_minisrv.njsproj +++ b/zefie_wtvp_minisrv/zefie_wtvp_minisrv.njsproj @@ -189,7 +189,7 @@ Code - + @@ -197,11 +197,12 @@ - + Code + Code