Last active
November 13, 2023 21:09
-
-
Save echicken/02aab754cbb497c8a21670b3212e1f09 to your computer and use it in GitHub Desktop.
Synchronet rlogin proxy for automatic newuser creation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* An rlogin proxy script for automatic new user account creation. | |
* Clients that connect to this service instead of directly to the | |
* actual rlogin server will have an account created for them if none | |
* exists. | |
* | |
* Put this script in mods/ | |
* | |
* Add the following block to ctrl/services.ini: | |
* | |
* [rlogin-proxy] | |
* Port = 1513 | |
* Command = rlogin-proxy.js | |
* | |
* See ctrl/services.ini for other options. | |
* | |
* Port 1513 is just a suggestion, choose whichever one you like. Just make | |
* sure that it's open to whatever downstream servers want to connect to | |
* this Synchronet BBS via rlogin. | |
* | |
* You may instead set this to listen on port 513, and tell Synchronet to use | |
* some other port for its actual rlogin server by editing the RLoginPort | |
* value in the [BBS] section of ctrl/sbbs.ini | |
* | |
*/ | |
load('sbbsdefs.js'); // log levels | |
load('ftelnethelper.js'); // GetRLoginInterface() and GetRLoginPort() | |
const rh = client.socket.recv(); // Read the rlogin "header" string | |
if (typeof rh !== 'string') throw new Error('No rlogin header received'); | |
const cs = rh.match(/\x00(.+)\x00(.+)\x00.+\x00/); // Extract client-user-name and server-user-name from header | |
if (!cs) throw new Error('Invalid rlogin header received: ' + rh); | |
const username = cs[2]; | |
const password = cs[1]; | |
log(LOG_DEBUG, '"' + username + '" connected to rlogin proxy'); | |
const un = system.matchuser(username); // See if this user exists | |
if (un === 0) { // User not found | |
const usr = system.new_user(username, client); // Create the account | |
if (typeof usr === 'number') { // This has never happened to me | |
throw new Error('Failed to create new user record for "' + username + '", error: ' + usr); | |
} | |
usr.security.password = password; // Apply the password sent in the header | |
/** | |
* If you need to set any other user values | |
* (eg. in order to prevent newuser questions being asked) | |
* do it here: | |
* | |
* usr.name = username; | |
* usr.netmail = username + '@fake.netmail.host'; | |
* usr.location = 'Place, Holder'; | |
* | |
* We could get fancy and check the UQ_* values here and do all of that | |
* automatically, but that's more effort than I want to put in tonight. | |
* Most game servers probably have all newuser question toggles turned off | |
* anyway. | |
*/ | |
log(LOG_INFO, 'rlogin proxy created user account for "' + username + '"'); | |
} | |
// Connect to the upstream / actual Synchronet rlogin server | |
const upstreamAddress = GetRLoginInterface(); | |
const upstreamPort = GetRLoginPort(); | |
const upstream = new Socket(); | |
if (!upstream.connect(upstreamAddress, upstreamPort)) { | |
throw new Error('Failed to connect to upstream rlogin server at ' + upstreamAddress + ':' + upstreamPort); | |
} | |
upstream.send(rh); // Forward the initial rlogin "header" string to the upstream server | |
log(LOG_DEBUG, 'rlogin proxy session established for "' + username + '"'); | |
// If you want to filter out the copyright message for a seamless transition into your game | |
var filtering = true; | |
while (client.socket.is_connected && upstream.is_connected && filtering) { | |
var s = true; | |
if (upstream.data_waiting) { | |
s = false; | |
const fromUpstream = upstream.recv(); | |
const toClient = fromUpstream.replace(/Synchronet.*Swindell/ig, ''); | |
client.socket.send(toClient); | |
if (toClient !== fromUpstream) filtering = false; | |
} | |
if (client.socket.data_waiting) { | |
s = false; | |
upstream.send(client.socket.recv()); | |
} | |
if (s) mswait(1); | |
} | |
// Pass all traffic between client and upstream until one of them disconnects | |
while (client.socket.is_connected && upstream.is_connected) { | |
var s = true; | |
if (upstream.data_waiting) { | |
s = false; | |
client.socket.send(upstream.recv()); | |
} | |
if (client.socket.data_waiting) { | |
s = false; | |
upstream.send(client.socket.recv()); | |
} | |
if (s) mswait(1); | |
} | |
log(LOG_DEBUG, 'rlogin proxy session terminated for "' + username + '"'); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment