· 5 years ago · Jun 25, 2020, 08:10 PM
1//Elérés: com.github.games647.fastlogin.bukkit.listener.protocollib/NameCheckTask.java
2//Ez az egész, ami megadja, hogy prémium-e aki bejelentkezett
3//Minecraft server implementation
4 //https://github.com/bergerkiller/CraftSource/blob/master/net.minecraft.server/LoginListener.java#L161
5 @Override
6 public void requestPremiumLogin(ProtocolLibLoginSource source, StoredProfile profile
7 , String username, boolean registered) {
8 try {
9 source.setOnlineMode(); //A source a ProtocolLibLoginSource-re vezet (Lentebb)
10 } catch (Exception ex) {
11 plugin.getLog().error("Cannot send encryption packet. Falling back to cracked login for: {}", profile, ex);
12 return;
13 }
14
15 String ip = player.getAddress().getAddress().getHostAddress();
16 core.getPendingLogin().put(ip + username, new Object());
17
18 String serverId = source.getServerId();
19 byte[] verify = source.getVerifyToken();
20
21 BukkitLoginSession playerSession = new BukkitLoginSession(username, serverId, verify, registered, profile);
22 plugin.putSession(player.getAddress(), playerSession);
23 //cancel only if the player has a paid account otherwise login as normal offline player
24 synchronized (packetEvent.getAsyncMarker().getProcessingLock()) {
25 packetEvent.setCancelled(true);
26 }
27}
28
29//com.github.games647.fastlogin.bukkit.listener.protocollib/ProtocolLibLoginSource
30//Itt igazából egy azonosító csomagot küld ki az egész, gondolom valahol vissza is kapja a plugin (aka szerver)
31@Override
32 public void setOnlineMode() throws Exception {
33 verifyToken = EncryptionUtil.generateVerifyToken(random);
34
35 /*
36 * Packet Information: https://wiki.vg/Protocol#Encryption_Request
37 *
38 * ServerID="" (String) key=public server key verifyToken=random 4 byte array
39 */
40 PacketContainer newPacket = new PacketContainer(ENCRYPTION_BEGIN);
41
42 newPacket.getStrings().write(0, serverId);
43 newPacket.getSpecificModifier(PublicKey.class).write(0, publicKey);
44
45 newPacket.getByteArrays().write(0, verifyToken);
46
47 //serverId is a empty string
48 ProtocolLibrary.getProtocolManager().sendServerPacket(player, newPacket);
49}
50
51//A loginok folyton futnak: (com.github.games647.fastlogin.bukkit.listener.protocollib/NameCheckTask.java)
52@Override
53 public void run() {
54 try {
55 super.onLogin(username, new ProtocolLibLoginSource(packetEvent, player, random, publicKey));
56 } finally {
57 ProtocolLibrary.getProtocolManager().getAsynchronousManager().signalPacketTransmission(packetEvent);
58 }
59 }
60
61//Itt kapja vissza a szerver és kezeli a plugint, amit a kliens küldött azonosításnak (Ha jól láttam SHA1-et használt titkosításnak)
62//Elérés: com.github.games647.fastlogin.bukkit.listener.protocollib/VerifyResponseTask.java
63private void verifyResponse(BukkitLoginSession session) {
64 PrivateKey privateKey = serverKey.getPrivate();
65
66 SecretKey loginKey;
67 try {
68 loginKey = EncryptionUtil.decryptSharedKey(privateKey, sharedSecret);
69 } catch (GeneralSecurityException securityEx) {
70 disconnect("error-kick", false, "Cannot decrypt received contents", securityEx);
71 return;
72 }
73
74 try {
75 if (!checkVerifyToken(session) || !enableEncryption(loginKey)) {
76 return;
77 }
78 } catch (Exception ex) {
79 disconnect("error-kick", false, "Cannot decrypt received contents", ex);
80 return;
81 }
82
83 String serverId = EncryptionUtil.getServerIdHashString("", loginKey, serverKey.getPublic());
84
85 String requestedUsername = session.getRequestUsername();
86 InetSocketAddress socketAddress = player.getAddress();
87 try {
88 MojangResolver resolver = plugin.getCore().getResolver();
89 InetAddress address = socketAddress.getAddress();
90 Optional<Verification> response = resolver.hasJoined(requestedUsername, serverId, address);
91 if (response.isPresent()) {
92 plugin.getLog().info("GameProfile {} has a verified premium account", requestedUsername);
93 String realUsername = response.get().getName();
94 if (realUsername == null) {
95 disconnect("invalid-session", true, "Username field null for {}", requestedUsername);
96 return;
97 }
98
99 SkinProperty[] properties = response.get().getProperties();
100 if (properties.length > 0) {
101 session.setSkinProperty(properties[0]);
102 }
103
104 session.setVerifiedUsername(realUsername);
105 session.setUuid(response.get().getId());
106 session.setVerified(true);
107
108 setPremiumUUID(session.getUuid());
109 receiveFakeStartPacket(realUsername);
110 } else {
111 //user tried to fake a authentication
112 disconnect("invalid-session", true
113 , "GameProfile {0} ({1}) tried to log in with an invalid session ServerId: {2}"
114 , session.getRequestUsername(), socketAddress, serverId);
115 }
116 } catch (IOException ioEx) {
117 disconnect("error-kick", false, "Failed to connect to session server", ioEx);
118 }
119 }
120
121 private void setPremiumUUID(UUID premiumUUID) {
122 if (plugin.getConfig().getBoolean("premiumUuid") && premiumUUID != null) {
123 try {
124 Object networkManager = getNetworkManager();
125 //https://github.com/bergerkiller/CraftSource/blob/master/net.minecraft.server/NetworkManager.java#L69
126 FieldUtils.writeField(networkManager, "spoofedUUID", premiumUUID, true);
127 } catch (Exception exc) {
128 plugin.getLog().error("Error setting premium uuid of {}", player, exc);
129 }
130 }
131 }
132
133 private boolean checkVerifyToken(BukkitLoginSession session) throws GeneralSecurityException {
134 byte[] requestVerify = session.getVerifyToken();
135 //encrypted verify token
136 byte[] responseVerify = packetEvent.getPacket().getByteArrays().read(1);
137
138 //https://github.com/bergerkiller/CraftSource/blob/master/net.minecraft.server/LoginListener.java#L182
139 if (!Arrays.equals(requestVerify, EncryptionUtil.decrypt(serverKey.getPrivate(), responseVerify))) {
140 //check if the verify token are equal to the server sent one
141 disconnect("invalid-verify-token", true
142 , "GameProfile {0} ({1}) tried to login with an invalid verify token. Server: {2} Client: {3}"
143 , session.getRequestUsername(), packetEvent.getPlayer().getAddress(), requestVerify, responseVerify);
144 return false;
145 }
146
147 return true;
148 }