· 9 years ago · Dec 23, 2016, 11:08 PM
1package net.bartzzdev.lightlogin.listeners.overrited;
2
3import com.google.common.base.Charsets;
4import com.mojang.authlib.GameProfile;
5import com.mojang.authlib.exceptions.AuthenticationUnavailableException;
6import io.netty.channel.ChannelFuture;
7import io.netty.channel.ChannelFutureListener;
8import io.netty.util.concurrent.GenericFutureListener;
9import net.bartzzdev.lightlogin.LightLogin;
10import net.bartzzdev.lightlogin.api.players.LightPlayer;
11import net.bartzzdev.lightlogin.enums.Account;
12import net.minecraft.server.v1_11_R1.*;
13import org.apache.commons.lang3.Validate;
14import org.apache.logging.log4j.LogManager;
15import org.apache.logging.log4j.Logger;
16import org.bukkit.Bukkit;
17import org.bukkit.craftbukkit.v1_11_R1.CraftServer;
18import org.bukkit.craftbukkit.v1_11_R1.util.Waitable;
19import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
20import org.bukkit.event.player.PlayerPreLoginEvent;
21
22import javax.annotation.Nullable;
23import javax.crypto.SecretKey;
24import java.math.BigInteger;
25import java.net.InetAddress;
26import java.net.InetSocketAddress;
27import java.net.SocketAddress;
28import java.security.PrivateKey;
29import java.util.Arrays;
30import java.util.Random;
31import java.util.UUID;
32import java.util.concurrent.atomic.AtomicInteger;
33import java.util.logging.Level;
34
35public class LoginListenerExtension extends LoginListener implements PacketLoginInListener, ITickable {
36
37 private static final LightLogin lightLogin = LightLogin.getInstance();
38 private static final AtomicInteger b = new AtomicInteger(0);
39 private static final Logger c = LogManager.getLogger();
40 private static final Random random = new Random();
41 private final byte[] e = new byte[4];
42 private final MinecraftServer server;
43 public final NetworkManager networkManager;
44 private EnumProtocolState g;
45 private int h;
46 private GameProfile i;
47 private final String j;
48 private SecretKey loginKey;
49 private EntityPlayer l;
50 public String hostname = "";
51
52 public LoginListenerExtension(MinecraftServer minecraftserver, NetworkManager networkmanager) {
53 super(minecraftserver, networkmanager);
54 this.g = EnumProtocolState.HELLO;
55 this.j = "";
56 this.server = minecraftserver;
57 this.networkManager = networkmanager;
58 random.nextBytes(this.e);
59 }
60
61 public void F_() {
62 if(this.g == EnumProtocolState.READY_TO_ACCEPT) {
63 this.b();
64 } else if(this.g == EnumProtocolState.DELAY_ACCEPT) {
65 EntityPlayer entityplayer = this.server.getPlayerList().a(this.i.getId());
66 if(entityplayer == null) {
67 this.g = EnumProtocolState.READY_TO_ACCEPT;
68 this.server.getPlayerList().a(this.networkManager, this.l);
69 this.l = null;
70 }
71 }
72
73 if(this.h++ == 600) {
74 this.disconnect("Took too long to log in");
75 }
76
77 }
78
79 public void disconnect(String s) {
80 try {
81 c.info("Disconnecting {}: {}", new Object[]{this.d(), s});
82 ChatComponentText exception = new ChatComponentText(s);
83 this.networkManager.sendPacket(new PacketLoginOutDisconnect(exception));
84 this.networkManager.close(exception);
85 } catch (Exception var3) {
86 c.error("Error whilst disconnecting player", var3);
87 }
88
89 }
90
91 public void b() {
92 if(!this.i.isComplete()) {
93 this.i = this.a(this.i);
94 }
95
96 EntityPlayer s = this.server.getPlayerList().attemptLogin(this, this.i, this.hostname);
97 if(s != null) {
98 this.g = EnumProtocolState.ACCEPTED;
99 if(this.server.aG() >= 0 && !this.networkManager.isLocal()) {
100 this.networkManager.sendPacket(new PacketLoginOutSetCompression(server.aG()), new ChannelFutureListener() {
101 public void a(ChannelFuture channelfuture) throws Exception {
102 networkManager.setCompressionLevel(server.aG());
103 }
104
105 public void operationComplete(ChannelFuture future) throws Exception {
106 this.a(future);
107 }
108 }, new GenericFutureListener[0]);
109 }
110
111 this.networkManager.sendPacket(new PacketLoginOutSuccess(this.i));
112 EntityPlayer entityplayer = this.server.getPlayerList().a(this.i.getId());
113 if(entityplayer != null) {
114 this.g = EnumProtocolState.DELAY_ACCEPT;
115 this.l = this.server.getPlayerList().processLogin(this.i, s);
116 } else {
117 this.server.getPlayerList().a(this.networkManager, this.server.getPlayerList().processLogin(this.i, s));
118 }
119 }
120
121 }
122
123 public void a(IChatBaseComponent ichatbasecomponent) {
124 c.info("{} lost connection: {}", new Object[]{this.d(), ichatbasecomponent.toPlainText()});
125 }
126
127 public String d() {
128 return this.i != null?this.i + " (" + this.networkManager.getSocketAddress() + ")":String.valueOf(this.networkManager.getSocketAddress());
129 }
130
131 public void a(PacketLoginInStart packetlogininstart) {
132 Validate.validState(this.g == EnumProtocolState.HELLO, "Unexpected hello packet", new Object[0]);
133 this.i = packetlogininstart.a();
134 if(this.server.getOnlineMode() && !this.networkManager.isLocal()) {
135 this.g = EnumProtocolState.KEY;
136 this.networkManager.sendPacket(new PacketLoginOutEncryptionBegin("", this.server.O().getPublic(), this.e));
137 } else {
138 this.g = EnumProtocolState.READY_TO_ACCEPT;
139 }
140
141 }
142
143 public void a(PacketLoginInEncryptionBegin packetlogininencryptionbegin) {
144 Validate.validState(this.g == EnumProtocolState.KEY, "Unexpected key packet", new Object[0]);
145 PrivateKey privatekey = this.server.O().getPrivate();
146 if(!Arrays.equals(this.e, packetlogininencryptionbegin.b(privatekey))) {
147 throw new IllegalStateException("Invalid nonce!");
148 } else {
149 this.loginKey = packetlogininencryptionbegin.a(privatekey);
150 this.g = EnumProtocolState.AUTHENTICATING;
151 this.networkManager.a(this.loginKey);
152 (new Thread("User Authenticator #" + b.incrementAndGet()) {
153 public void run() {
154 GameProfile gameprofile = i;
155
156 try {
157 String exception = (new BigInteger(MinecraftEncryption.a("", server.O().getPublic(), loginKey))).toString(16);
158 i = server.az().hasJoinedServer(new GameProfile((UUID)null, gameprofile.getName()), exception, this.a());
159 if(i != null) {
160 if(!networkManager.isConnected()) {
161 return;
162 }
163
164 lightLogin.getPlayerManager().loadPlayerName(i.getName());
165
166 AuthLoginEvent authLoginEvent = null;
167 if (lightLogin.getPlayerManager().getPremiumNames().containsValue(i.getName())) {
168 server.setOnlineMode(true);
169 UUID uuid = i.getId();
170 if (uuid != null) {
171 authLoginEvent = new AuthLoginEvent(uuid, Account.PREMIUM);
172 server.setOnlineMode(false);
173 }
174 else {
175 server.setOnlineMode(false);
176 authLoginEvent = new AuthLoginEvent(uuid, Account.CRACKED);
177 }
178 } else {
179 authLoginEvent = new AuthLoginEvent(i.getId(), Account.CRACKED);
180 }
181
182 Bukkit.getPluginManager().callEvent(authLoginEvent);
183 LightPlayer lPlayer = LightLogin.getInstance().getPlayerManager().create(i.getId(), i.getName());
184 lPlayer.setAccount(authLoginEvent.getAccount());
185
186 String playerName = i.getName();
187 InetAddress address = ((InetSocketAddress)networkManager.getSocketAddress()).getAddress();
188 UUID uniqueId = i.getId();
189 final CraftServer server = LoginListenerExtension.this.server.server;
190 AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId);
191 server.getPluginManager().callEvent(asyncEvent);
192 if(PlayerPreLoginEvent.getHandlerList().getRegisteredListeners().length != 0) {
193 final PlayerPreLoginEvent event = new PlayerPreLoginEvent(playerName, address, uniqueId);
194 if(asyncEvent.getResult() != PlayerPreLoginEvent.Result.ALLOWED) {
195 event.disallow(asyncEvent.getResult(), asyncEvent.getKickMessage());
196 }
197
198 Waitable waitable = new Waitable() {
199 protected PlayerPreLoginEvent.Result evaluate() {
200 server.getPluginManager().callEvent(event);
201 return event.getResult();
202 }
203 };
204 LoginListenerExtension.this.server.processQueue.add(waitable);
205 if(waitable.get() != PlayerPreLoginEvent.Result.ALLOWED) {
206 disconnect(event.getKickMessage());
207 return;
208 }
209 } else if(asyncEvent.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) {
210 disconnect(asyncEvent.getKickMessage());
211 return;
212 }
213
214 c.info("UUID of player {} is {}", new Object[]{i.getName(), i.getId()});
215 g = EnumProtocolState.READY_TO_ACCEPT;
216 } else if(server.R()) {
217 c.warn("Failed to verify username but will let them in anyway!");
218 i = LoginListenerExtension.this.a(gameprofile);
219 g = EnumProtocolState.READY_TO_ACCEPT;
220 } else {
221 disconnect("Failed to verify username!");
222 c.error("Username \'{}\' tried to join with an invalid session", new Object[]{gameprofile.getName()});
223 }
224 } catch (AuthenticationUnavailableException var10) {
225 if(server.R()) {
226 c.warn("Authentication servers are down but will let them in anyway!");
227 i = LoginListenerExtension.this.a(gameprofile);
228 g = EnumProtocolState.READY_TO_ACCEPT;
229 } else {
230 disconnect("Authentication servers are down. Please try again later, sorry!");
231 c.error("Couldn\'t verify username because servers are unavailable");
232 }
233 } catch (Exception var11) {
234 disconnect("Failed to verify username!");
235 server.server.getLogger().log(Level.WARNING, "Exception verifying " + gameprofile.getName(), var11);
236 }
237
238 }
239
240 @Nullable
241 private InetAddress a() {
242 SocketAddress socketaddress = networkManager.getSocketAddress();
243 return server.ac() && socketaddress instanceof InetSocketAddress?((InetSocketAddress)socketaddress).getAddress():null;
244 }
245 }).start();
246 }
247 }
248
249 public GameProfile a(GameProfile gameprofile) {
250 UUID uuid = UUID.nameUUIDFromBytes(("OfflinePlayer:" + gameprofile.getName()).getBytes(Charsets.UTF_8));
251 return new GameProfile(uuid, gameprofile.getName());
252 }
253
254 static enum EnumProtocolState {
255 HELLO,
256 KEY,
257 AUTHENTICATING,
258 READY_TO_ACCEPT,
259 DELAY_ACCEPT,
260 ACCEPTED;
261
262 private EnumProtocolState() {
263 }
264 }
265}