Many fixes to admin/trace/UUID system

This commit is contained in:
Anuken
2018-06-13 17:52:31 -04:00
parent c077f6e1e8
commit d0302cdbf3
14 changed files with 155 additions and 91 deletions

View File

@@ -1,6 +1,7 @@
package io.anuke.mindustry.core;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.utils.Base64Coder;
import com.badlogic.gdx.utils.Pools;
import io.anuke.annotations.Annotations.Remote;
import io.anuke.annotations.Annotations.Variant;
@@ -14,6 +15,8 @@ import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.net.Net.SendMode;
import io.anuke.mindustry.net.NetworkIO;
import io.anuke.mindustry.net.Packets.*;
import io.anuke.mindustry.net.TraceInfo;
import io.anuke.ucore.core.Settings;
import io.anuke.ucore.core.Timers;
import io.anuke.ucore.entities.Entities;
import io.anuke.ucore.entities.EntityGroup;
@@ -25,6 +28,7 @@ import io.anuke.ucore.util.Timer;
import java.io.DataInputStream;
import java.util.Arrays;
import java.util.Random;
import static io.anuke.mindustry.Vars.*;
@@ -73,6 +77,7 @@ public class NetClient extends Module {
c.name = player.name;
c.mobile = mobile;
c.color = Color.rgba8888(player.color);
c.usid = getUsid(packet.addressTCP);
c.uuid = Platform.instance.getUUID();
if(c.uuid == null){
@@ -170,6 +175,18 @@ public class NetClient extends Module {
}
}
String getUsid(String ip){
if(Settings.getString("usid-" + ip, null) != null){
return Settings.getString("usid-" + ip);
}else{
byte[] bytes = new byte[8];
new Random().nextBytes(bytes);
String result = new String(Base64Coder.encode(bytes));
Settings.putString("usid-" + ip, result);
return result;
}
}
@Remote(variants = Variant.one)
public static void onKick(KickReason reason){
netClient.disconnectQuietly();
@@ -184,6 +201,12 @@ public class NetClient extends Module {
players[0].y = y;
}
@Remote(variants = Variant.one)
public static void onTraceInfo(TraceInfo info){
Player player = playerGroup.getByID(info.playerid);
ui.traces.show(player, info);
}
@Remote(variants = Variant.one, unreliable = true)
public static void onSnapshot(byte[] snapshot, int snapshotID){
//skip snapshot IDs that have already been recieved

View File

@@ -4,7 +4,6 @@ import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Colors;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Base64Coder;
import com.badlogic.gdx.utils.IntMap;
import com.badlogic.gdx.utils.TimeUtils;
import io.anuke.annotations.Annotations.Loc;
@@ -75,7 +74,7 @@ public class NetServer extends Module{
});
Net.handleServer(ConnectPacket.class, (id, packet) -> {
String uuid = new String(Base64Coder.encode(packet.uuid));
String uuid = packet.uuid;
if(Net.getConnection(id) == null ||
admins.isIPBanned(Net.getConnection(id).address)) return;
@@ -127,8 +126,9 @@ public class NetServer extends Module{
}
Player player = new Player();
player.isAdmin = admins.isAdmin(uuid, ip);
player.isAdmin = admins.isAdmin(uuid, packet.usid);
player.clientid = id;
player.usid = packet.usid;
player.name = packet.name;
player.uuid = uuid;
player.mech = packet.mobile ? Mechs.standardShip : Mechs.standard;
@@ -387,6 +387,39 @@ public class NetServer extends Module{
}
}
@Remote(targets = Loc.client, called = Loc.server)
public static void onAdminRequest(Player player, Player other, AdminAction action){
if(!player.isAdmin){
Log.err("ACCESS DENIED: Player {0} / {1} attempted to perform admin action without proper security access.",
player.name, Net.getConnection(player.clientid).address);
return;
}
if(other == null || other.isAdmin){
Log.err("{0} attempted to perform admin action on nonexistant or admin player.", player.name);
return;
}
String ip = Net.getConnection(other.clientid).address;
if(action == AdminAction.ban){
netServer.admins.banPlayerIP(ip);
netServer.kick(other.clientid, KickReason.banned);
Log.info("&lc{0} has banned {1}.", player.name, other.name);
}else if(action == AdminAction.kick){
netServer.kick(other.clientid, KickReason.kick);
Log.info("&lc{0} has kicked {1}.", player.name, other.name);
}else if(action == AdminAction.trace){
if(player.clientid != -1) {
Call.onTraceInfo(player.clientid, netServer.admins.getTraceByID(other.uuid));
}else{
NetClient.onTraceInfo(netServer.admins.getTraceByID(other.uuid));
}
Log.info("&lc{0} has requested trace info of {1}.", player.name, other.name);
}
}
@Remote(targets = Loc.client)
public static void connectConfirm(Player player){
player.add();

View File

@@ -47,8 +47,8 @@ public abstract class Platform {
}
/**Whether debug mode is enabled.*/
public boolean isDebug(){return false;}
/**Must be 8 bytes in length.*/
public byte[] getUUID(){
/**Must be a base64 string 8 bytes in length.*/
public String getUUID(){
String uuid = Settings.getString("uuid", "");
if(uuid.isEmpty()){
byte[] result = new byte[8];
@@ -56,9 +56,9 @@ public abstract class Platform {
uuid = new String(Base64Coder.encode(result));
Settings.putString("uuid", uuid);
Settings.save();
return result;
return uuid;
}
return Base64Coder.decode(uuid);
return uuid;
}
/**Only used for iOS or android: open the share menu for a map or save.*/
public void shareFile(FileHandle file){}

View File

@@ -53,7 +53,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait {
public float pointerX, pointerY;
public String name = "name";
public String uuid;
public String uuid, usid;
public boolean isAdmin, isTransferring, isShooting;
public Color color = new Color();
@@ -651,6 +651,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait {
public void write(DataOutput buffer) throws IOException {
super.writeSave(buffer, !isLocal);
buffer.writeUTF(name);
buffer.writeBoolean(isAdmin);
buffer.writeInt(Color.rgba8888(color));
buffer.writeBoolean(dead);
buffer.writeByte(weapon.id);
@@ -662,6 +663,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait {
float lastx = x, lasty = y, lastrot = rotation;
super.readSave(buffer);
name = buffer.readUTF();
isAdmin = buffer.readBoolean();
color.set(buffer.readInt());
dead = buffer.readBoolean();
weapon = Upgrade.getByID(buffer.readByte());

View File

@@ -1,6 +1,7 @@
package io.anuke.mindustry.io;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.utils.Base64Coder;
import io.anuke.annotations.Annotations.ReadClass;
import io.anuke.annotations.Annotations.WriteClass;
import io.anuke.mindustry.entities.Player;
@@ -10,8 +11,11 @@ import io.anuke.mindustry.entities.traits.CarriableTrait;
import io.anuke.mindustry.entities.traits.CarryTrait;
import io.anuke.mindustry.entities.units.BaseUnit;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.net.Packets.AdminAction;
import io.anuke.mindustry.net.Packets.KickReason;
import io.anuke.mindustry.net.TraceInfo;
import io.anuke.mindustry.type.*;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Tile;
import io.anuke.ucore.core.Effects;
import io.anuke.ucore.core.Effects.Effect;
@@ -129,6 +133,16 @@ public class TypeIO {
return Team.values()[buffer.get()];
}
@WriteClass(AdminAction.class)
public static void writeAction(ByteBuffer buffer, AdminAction reason){
buffer.put((byte)reason.ordinal());
}
@ReadClass(AdminAction.class)
public static AdminAction readAction(ByteBuffer buffer){
return AdminAction.values()[buffer.get()];
}
@WriteClass(Effect.class)
public static void writeEffect(ByteBuffer buffer, Effect effect){
buffer.putShort((short)effect.id);
@@ -245,4 +259,45 @@ public class TypeIO {
buffer.get(bytes);
return bytes;
}
@WriteClass(TraceInfo.class)
public static void writeTrace(ByteBuffer buffer, TraceInfo info){
buffer.putInt(info.playerid);
buffer.putShort((short)info.ip.getBytes().length);
buffer.put(info.ip.getBytes());
buffer.put(info.modclient ? (byte)1 : 0);
buffer.put(info.android ? (byte)1 : 0);
buffer.putInt(info.totalBlocksBroken);
buffer.putInt(info.structureBlocksBroken);
buffer.putInt(info.lastBlockBroken.id);
buffer.putInt(info.totalBlocksPlaced);
buffer.putInt(info.lastBlockPlaced.id);
buffer.put(Base64Coder.decode(info.uuid));
}
@ReadClass(TraceInfo.class)
public static TraceInfo readTrace(ByteBuffer buffer){
int id = buffer.getInt();
short iplen = buffer.getShort();
byte[] ipb = new byte[iplen];
buffer.get(ipb);
TraceInfo info = new TraceInfo(new String(ipb));
info.playerid = id;
info.modclient = buffer.get() == 1;
info.android = buffer.get() == 1;
info.totalBlocksBroken = buffer.getInt();
info.structureBlocksBroken = buffer.getInt();
info.lastBlockBroken = Block.getByID(buffer.getInt());
info.totalBlocksPlaced = buffer.getInt();
info.lastBlockPlaced = Block.getByID(buffer.getInt());
byte[] uuid = new byte[8];
buffer.get(uuid);
info.uuid = new String(Base64Coder.encode(uuid));
return info;
}
}

View File

@@ -270,13 +270,13 @@ public class Administration {
}
/**Makes a player an admin. Returns whether this player was already an admin.*/
public boolean adminPlayer(String id, String ip){
public boolean adminPlayer(String id, String usid){
PlayerInfo info = getCreateInfo(id);
if(info.admin)
return false;
info.validAdminIP = ip;
info.adminUsid = usid;
info.admin = true;
save();
@@ -304,9 +304,9 @@ public class Administration {
return getCreateInfo(uuid).banned;
}
public boolean isAdmin(String id, String ip){
public boolean isAdmin(String id, String usip){
PlayerInfo info = getCreateInfo(id);
return info.admin && ip.equals(info.validAdminIP);
return info.admin && usip.equals(info.adminUsid);
}
public Array<PlayerInfo> findByName(String name, boolean last){
@@ -375,9 +375,9 @@ public class Administration {
public static class PlayerInfo{
public String id;
public String lastName = "<unknown>", lastIP = "<unknown>";
public String validAdminIP;
public Array<String> ips = new Array<>();
public Array<String> names = new Array<>();
public String adminUsid;
public int timesKicked;
public int timesJoined;
public int totalBlockPlaced;

View File

@@ -1,5 +1,6 @@
package io.anuke.mindustry.net;
import com.badlogic.gdx.utils.Base64Coder;
import com.badlogic.gdx.utils.TimeUtils;
import io.anuke.mindustry.Vars;
import io.anuke.mindustry.entities.Player;
@@ -30,29 +31,30 @@ public class Packets {
public static class ConnectPacket implements Packet{
public int version;
public int players;
public String name;
public String name, uuid, usid;
public boolean mobile;
public int color;
public byte[] uuid;
@Override
public void write(ByteBuffer buffer) {
buffer.putInt(Version.build);
IOUtils.writeString(buffer, name);
IOUtils.writeString(buffer, usid);
buffer.put(mobile ? (byte)1 : 0);
buffer.putInt(color);
buffer.put(uuid);
buffer.put(Base64Coder.decode(uuid));
}
@Override
public void read(ByteBuffer buffer) {
version = buffer.getInt();
name = IOUtils.readString(buffer);
usid = IOUtils.readString(buffer);
mobile = buffer.get() == 1;
color = buffer.getInt();
uuid = new byte[8];
buffer.get(uuid);
byte[] idbytes = new byte[8];
buffer.get(idbytes);
uuid = new String(Base64Coder.encode(idbytes));
}
}

View File

@@ -4,10 +4,11 @@ import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.ObjectMap;
import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.gen.Call;
import io.anuke.mindustry.net.EditLog;
import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.net.NetConnection;
import io.anuke.mindustry.net.Packets.KickReason;
import io.anuke.mindustry.net.Packets.AdminAction;
import io.anuke.mindustry.ui.BorderImage;
import io.anuke.mindustry.ui.dialogs.FloatingDialog;
import io.anuke.ucore.core.Inputs;
@@ -138,23 +139,10 @@ public class PlayerListFragment implements Fragment{
//TODO requests.
t.addImageButton("icon-ban", 14*2, () -> {
ui.showConfirm("$text.confirm", "$text.confirmban", () -> {
if(Net.server()) {
netServer.admins.banPlayerIP(connection.address);
netServer.kick(player.clientid, KickReason.banned);
}else{
//NetEvents.handleAdministerRequest(player, AdminAction.ban);
}
});
ui.showConfirm("$text.confirm", "$text.confirmban", () -> Call.onAdminRequest(player, AdminAction.ban));
}).padBottom(-5.1f);
t.addImageButton("icon-cancel", 14*2, () -> {
if(Net.server()) {
netServer.kick(player.clientid, KickReason.kick);
}else{
//NetEvents.handleAdministerRequest(player, AdminAction.kick);
}
}).padBottom(-5.1f);
t.addImageButton("icon-cancel", 14*2, () -> Call.onAdminRequest(player, AdminAction.kick)).padBottom(-5.1f);
t.row();
@@ -166,12 +154,10 @@ public class PlayerListFragment implements Fragment{
if(netServer.admins.isAdmin(id, connection.address)){
ui.showConfirm("$text.confirm", "$text.confirmunadmin", () -> {
netServer.admins.unAdminPlayer(id);
//CallClient.adminSet(player, false);
});
}else{
ui.showConfirm("$text.confirm", "$text.confirmadmin", () -> {
netServer.admins.adminPlayer(id, connection.address);
//CallClient.adminSet(player, true);
netServer.admins.adminPlayer(id, player.usid);
});
}
}).update(b ->{
@@ -179,7 +165,7 @@ public class PlayerListFragment implements Fragment{
b.setDisabled(Net.client());
}).get().setTouchable(() -> Net.client() ? Touchable.disabled : Touchable.enabled);
t.addImageButton("icon-zoom-small", 14*2, () -> {}/*NetEvents.handleTraceRequest(player)*/);
t.addImageButton("icon-zoom-small", 14*2, () -> Call.onAdminRequest(player, AdminAction.trace));
}).padRight(12).padTop(-5).padLeft(0).padBottom(-10).size(bs + 10f, bs);