RSCPlus / rscplus

RuneScape Classic client mod & preservation platform
https://rsc.plus
GNU General Public License v3.0
49 stars 35 forks source link

Implement part of the old client 127 protocol for Account Creation and Password Recovery #41

Closed Hubcapp closed 3 years ago

Hubcapp commented 4 years ago

Background information:

mudclient 127 from March 18th 2002 has more advanced Account Manangement than later versions of the client, such as the one that RSC+ is based on.

These Account Management features include:

I'm not sure precisely when these features were removed, but by mudclient 192 (April 8th 2004), the features are gone, and the client instructs the user to use the website instead.

Objective:

It would be useful for private server use if these features were intact in the client, but RSC+ WILL NOT implement private server exclusive features. If this feature enters RSC+, it must behave identically to how it did in Client 127. This way, it is not a private server feature, it is just reintroducing past functionality, similar to the FPS counter already in RSC+.

This feature must look exactly like it did in Client 127, and the network protocol must be exactly the same as Client 127 (regarding opcode, packet structure, and encryption).

Here is some 127 deob code for the relevant packets to be implemented:

Account creation (client opcode 2)

this.conn.enter(2);
this.conn.short_put(version);
this.conn.long_put(DataUtil.encode_name(s));
this.conn.enc_cred_put(pass, id, this.exp, this.mod);
this.conn.int_put(seed());
this.conn.send();
this.conn.read();
int j = this.conn.read();
this.conn.close();
System.out.println("Newplayer response: " + j);

Setting account recovery questions (client opcode 208)

this.conn.enter(208);
for (int j1 = 0; j1 < 5; j1++) {
  String s2 = this.aStringArray975[j1];
  if ((s2 == null) || (s2.length() == 0))
    s2 = String.valueOf(j1 + 1);
  if (s2.length() > 50)
    s2 = s2.substring(0, 50);
  this.conn.byte_put(s2.length());
  this.conn.str_put(s2);
  this.conn.enc_cred_put(DataUtil.base47_encode(this.aClass6_966
      .text(this.anIntArray971[j1])), this.sess_id,
      this.RSA_EXP, this.RSA_MOD);
}

this.conn.exit();

Using account recovery questions (client opcode 8)

this.conn.enter(8);
this.conn.long_put(DataUtil
    .encode_name(this.aString947));
this.conn.int_put(seed());
this.conn.enc_cred_put(new StringBuilder().append(s4)
    .append(s6).toString(), i1, this.RSA_EXP,
    this.RSA_MOD);
for (int k1 = 0; k1 < 5; k1++) {
  this.conn.enc_cred_put(DataUtil
      .base47_encode(this.lost_ui
          .text(this.anIntArray989[k1])), i1,
      this.RSA_EXP, this.RSA_MOD);
}
this.conn.send();
this.conn.read();
int l1 = this.conn.read();
System.out.println(new StringBuilder()
    .append("Recover response: ").append(l1)
    .toString());
if (l1 == 0) {
  this.ui_state = 2;
  status_text(
      "Sorry, recovery failed. You may try again in 1 hour",
      "");
  this.aBoolean976 = true;
  return;
}
if (l1 == 1) {
  this.ui_state = 2;
  status_text(
      "Your pass has been reset. You may now use the new pass to login",
      "");
  return;
}
this.ui_state = 2;
status_text("Recovery failed! Attempts exceeded?", "");
return;

Challenges:

  1. Although there is no client opcode 2 or client opcode 208 in the modern client, client opcode 8 is already CLIENT_OPCODE_SEND_DUEL_SETTINGS. Obviously there is no conflict on our side if the client just sending opcode 8 with all this "extra" data, but if a server were implementing the hybrid RSC127/RSC235 protocol we are looking to adapt here, they would have to write a small distinction to figure out which opcode 8 the client is talking about. It could be done either by seeing that there is no Player associated with the connection, or by checking if packet length is 4 bytes long or not (RSC235 client opcode 8 is always 4 bytes, and RSC127 client opcode 8 can never be 4 bytes). If it were not possible to distinguish the two opcodes, there would be a problem, but it works out.

  2. RSC+ currently automatically skips the first screen of the client with this line of code here:

https://github.com/RSCPlus/rscplus/blob/398a7156de953909d08ac5768d400a765a3b9488/src/Game/Client.java#L457

This should probably have been an option in the first place. We skip this screen right now because: a. After the removal of these Account Management options, the initial screen really serves no purpose. b. Actually, it is a hindrance. Every time this screen is loaded, the saved Username and Password are cleared. And also it is an extra click before you get into the client.

2020-10-09-162953_800x580_scrot

This screen has been disabled in RSC+ since 2016 and all features of the client have been programmed assuming that it is skipped. The screen must be made functional again, it must be tested with replay compatibility (drag-n-drop & queue especially). It must actually be extended to work (currently, even if this one line of code is removed, the "Click here to login" button seems to be broken) and it must be extended further to implement the RSC127 interface.

  1. Like all other things, this feature must be on a toggle. If the user desires to restore the original RSC+ functionality of always launching directly to login screen on start, that must be possible.

  2. Furthermore, I would probably like it if this login screen is only shown at the beginning of client run. Once the user has "click here to login", the client should not show the screen again unless the user clicks "Cancel" or relaunches the client.

Hubcapp commented 4 years ago

I tested dragging a replay onto the client while at that "Click here to login" screen, and luckily, it seems to work properly, just going directly to replay. :p

Hubcapp commented 4 years ago

More information:

The FORGOT_PASSWORD opcode existed in mudclient 127. It is client opcode 4 there, which conflicts with CLIENT_CAST_ON_INVENTORY_ITEM in the 235 protocol. https://github.com/hikilaka/mudclient_127/blob/master/src/mudclient.java#L1848


ALSO I found out that there is indeed already a toggle on the "Click here to login" screen. It is under the Streaming & Privacy tab. "Save login information between logins (Requires restart)".

lmsv-mx123 commented 4 years ago

Will be divided by 3 segments (feature updates) very likely

Hubcapp commented 3 years ago

Account Creation has been implemented in #51

lmsv-mx123 commented 3 years ago

Although was not present in the 127, would like to also get added the in-game option of "Change contact details", this game option was featured sometime between mudclient 127 and 204. This can be seen in the mudclient 175

The relevant code block concerning protocol part would be like:

String string = this.hL.e(this.hN);  //Full name
String string2 = this.hL.e(this.hO); //Postcode/Zipcode
String string3 = this.hL.e(this.hP); //Country
String string4 = this.hL.e(this.hQ); //Email address
if (string != null && string.length() != 0 && string2 != null && string2.length() != 0 && string3 != null && string3.length() != 0 && string4 != null && string4.length() != 0) {
this.Y.a(253, 155); // conn.enter(253);
this.Y.a(string.length()); //conn.byte_put(string.length())
this.Y.a(string); //conn.str_put(string)
this.Y.a(string2.length()); //conn.byte_put(string2.length())
this.Y.a(string2); //conn.str_put(string2)
this.Y.a(string3.length()); //conn.byte_put(string3.length())
this.Y.a(string3); //conn.str_put(string3)
this.Y.a(string4.length()); //conn.byte_put(string4.length())
this.Y.a(string4); //conn.str_put(string4)
this.Y.g(); //conn.exit();
this.bO.c(); //this.screen.clear();
this.hK = false;
return;
}

For reference, the code block above had been from deob of mudclient175. It is important to also include it since having an email for the user may make it easier for servers to provide password recovery mechanism via email token. On the aesthetics part, having the 3 security settings (see bottom part of https://classic.runescape.wiki/w/Manual:Screenshots_(2003)) fills better the space

lmsv-mx123 commented 3 years ago

To place in next, probably will also be good to have included a validation that was on new accounts, basically:

image

Mudclient 175 seems to have opcodes from 127 intact which is good

lmsv-mx123 commented 3 years ago

OPCODE 197 - Change recovery questions request (mudclient 127 & mudclient 175) OPCODE 247 - Change contact details request (mudclient 175)

Hubcapp commented 3 years ago

client opcode 197 is "Decline Duel" in RSC235 client opcode 247 is "Take Ground Item" in RSC235

lmsv-mx123 commented 3 years ago

Change password request is Opcode 25 (after doing preliminary client side validations)

public void send_cred(String oldPwd, String newPwd) {
oldPass = DataUtil.filter_str(oldPwd, 20); 
newPass = DataUtil.filter_str(newPwd, 20);
conn.enter(25);
conn.enc_cred_put(oldPass + newPass, sess_id, exp, mod);
conn.exit();
}

Client receives packet with opcode 224 after doing Change recovery questions request

if (id == 224) {
this.lkb = true;
for (var20 = 0; var20 < 5; ++var20) {
this.ukb[var20] = var20;
this.vkb[var20] = "~:" + this.ukb[var20];
this.mkb.set_text(this.rkb[var20], "");
this.mkb.set_text(this.qkb[var20], var20 + 1 + ": " + this.ymb[this.ukb[var20]]);
}
return;
}

Client receives packet with opcode 232 after doing Change contact details request

if (var1_1 == 232) {
this.hK = true;
this.hL.a(this.hN, "");
this.hL.a(this.hO, "");
this.hL.a(this.hP, "");
this.hL.a(this.hQ, "");
return;
}

Fortunately the received opcodes 224 and 232 seem to be unused in RSC235. Hence can be placed accordingly in handleIncomingPacket() without charging much the client to demux them.

Hubcapp commented 3 years ago

All that's left is RSC175 opcode 196, to cancel Account Recovery questions "If you do not remember making this request"

Hubcapp commented 3 years ago

luckily there is no RSC235 client opcode 196

lmsv-mx123 commented 3 years ago

So here's my thoughts for the cancel Account recovery questions change, probably @Hubcapp can indicate better if wrong

lmsv-mx123 commented 3 years ago

All good to go for this issue, follow-up for any possible enhancements will be in #62