mojira.dev
MC-84786

ban expiration date in banned-players.json isn't functional / banned-ips experation date doesn't fully work

The bug

You can use the expiration time in banned-players.json, and the message "Your ban will be removed on xxxxx" shows up fine.
The issue is, it doesn't unban when the time has passed the "expires" time

I banned myself for 1 minute to test it, and I waited about 10 minutes and it still doesn't let me in.

(Just a note, you can't use the expires in the command, only by direct editing the banned-players.json / banned-ips.json file)

banned-ips.json works fine, you can connect afterwards, but you get an error each first time you try to connect since server restart since expiration date is reached.

Client

Internal Exception: io.netty.handler.codec.DecoderException: java.io.IOException: Bad packet id 26

Server

[21:43:15] [Server thread/WARN]: Failed to handle packet for /IPBLACKEDOUT
0
java.lang.NullPointerException
        at mm.a(SourceFile:383) ~[minecraft_server.jar:?]
        at md.b(SourceFile:97) ~[minecraft_server.jar:?]
        at md.c(SourceFile:62) ~[minecraft_server.jar:?]
        at ek.a(SourceFile:232) ~[minecraft_server.jar:?]
        at ma.c(SourceFile:187) [minecraft_server.jar:?]
        at net.minecraft.server.MinecraftServer.D(SourceFile:643) [minecraft_ser
ver.jar:?]
        at la.D(SourceFile:339) [minecraft_server.jar:?]
        at net.minecraft.server.MinecraftServer.C(SourceFile:553) [minecraft_ser
ver.jar:?]
        at net.minecraft.server.MinecraftServer.run(SourceFile:457) [minecraft_s
erver.jar:?]
        at java.lang.Thread.run(Unknown Source) [?:1.8.0_77]

Steps to reproduce (banned-players)

  1. Run a server

  2. /ban yourself

  3. Close server

  4. Edit the banned-players.json's expiration date to "unban" after 1 minute

  5. Start server again

  6. Wait that time and try to join

Steps to reproduce (banned-ips)

  1. Run a server

  2. /ban-ip yourself

  3. Close server

  4. Edit the banned-ip.json's expiration date to "unban" after 1 minute

  5. Start server again

  6. Wait that time and try to join, you will receive an error

  7. Try joining again, you'll get in

  8. Close and start the server again

  9. Enter the server, and see the same message again

Code analysis

See this comment.

Linked issues

Attachments

Comments 10

Can confirm (See attached picture img.png)

Bug is still in 1.9

Already in the affected versions...

Please link to this comment in the description

The following is based on decompiled version of Minecraft 1.9 using MCP 9.24 beta.

The reason why the entry from the banned-players.json file is not removed is because the method net.minecraft.server.management.UserList.removeExpired() uses the wrong key to remove the entry. It uses the value of the entry to remove it, instead it should uses the method net.minecraft.server.management.UserList.getObjectKey(K) to create the key based on the entry value.

/**
 * Removes expired bans from the list. See {@link BanEntry#hasBanExpired}
 */
private void removeExpired()
{
    List<K> list = Lists.<K>newArrayList();

    for (V v : this.values.values())
    {
        if (v.hasBanExpired())
        {
            list.add(v.getValue());
        }
    }

    for (K k : list)
    {
        // Replaced this
        //this.values.remove(k);
        this.values.remove(this.getObjectKey(k));
    }
}

The reason why an exception is thrown for the first time is because the method net.minecraft.server.management.PlayerList.allowUserToConnect(SocketAddress, GameProfile) first tests if the GameProfile is banned and if this is the case it tries to get the ban entry. The problem is that the method net.minecraft.server.management.UserList.getEntry(K) first removes expired ban entries. This means that it returns null if the ban was removed, which then causes the NullPointerException.
Instead the methods net.minecraft.server.management.UserListIPBans.isBanned(SocketAddress), net.minecraft.server.management.UserListBans.isBanned(GameProfile) and net.minecraft.server.management.UserListBans.isUsernameBanned(String) should remove expired entries first before testing if the IP, GameProfile or username is banned.

Seems to be working fine in 1.13.1
(Yes it unbanned me after)

"created": "2018-08-28 09:34:53 -0400"
"expires": "2018-08-28 09:37:00 -0400"

Please re-open this issue, it's still present in 1.14.4. Reproduction steps are the same - set a ban that will expire, wait until expire time, and then join. The exception will only occur once though.

 

I have submitted a patch to Paper that Mojang is free to use - https://github.com/PaperMC/Paper/pull/2458

(the code is a bit different due to CraftBukkit changes but the same logic applies)

The relevant code is just this one line (spigot mappings), marked // NPE in PlayerList:

if (this.k.isBanned(gameprofile)) {
            GameProfileBanEntry gameprofilebanentry = (GameProfileBanEntry) this.k.get(gameprofile);

            chatmessage = new ChatMessage("multiplayer.disconnect.banned.reason", new Object[]{gameprofilebanentry.getReason()}); // NPE
            if (gameprofilebanentry.getExpires() != null) {
                chatmessage.addSibling(new ChatMessage("multiplayer.disconnect.banned.expiration", new Object[]{PlayerList.g.format(gameprofilebanentry.getExpires())}));
            }

the get() call will remove the relevant entry if it has expired, and then return null.  Then it will clearly NPE on the marked line.

The stacktrace of this occurring on the vanilla server:

[06:30:45] [Server thread/WARN]: Failed to handle packet for /127.0.0.1:50701
java.lang.NullPointerException: null
        at xv.a(SourceFile:357) ~[minecraft_server.jar:?]
        at we.c(SourceFile:97) ~[minecraft_server.jar:?]
        at we.b(SourceFile:63) ~[minecraft_server.jar:?]
        at jc.a(SourceFile:230) ~[minecraft_server.jar:?]
        at wb.c(SourceFile:171) [minecraft_server.jar:?]
        at net.minecraft.server.MinecraftServer.b(SourceFile:847) [minecraft_server.jar:?]
        at uk.b(SourceFile:343) [minecraft_server.jar:?]
        at net.minecraft.server.MinecraftServer.a(SourceFile:774) [minecraft_server.jar:?]
        at net.minecraft.server.MinecraftServer.run(SourceFile:642) [minecraft_server.jar:?]
        at java.lang.Thread.run(Thread.java:748) [?:1.8.0_222]
[06:30:45] [Server thread/INFO]: com.mojang.authlib.GameProfile@664932ca[id=9a9949cc-1987-3d04-b56b-cf3286adfe51,name=searchndstroy,properties={},legacy=false] (/127.0.0.1:50701) lost connection: Internal server error

@unknown, could you please create a new ticket that we can mark as a clone of this ticket? I'd rather have a new ticket than reusing this one.

Thanks! I've linked the tickets accordingly.

user-f2760

(Unassigned)

Confirmed

ban, ban-list, banned, date, functionality, json, players

Minecraft 15w31c, Minecraft 15w36d, Minecraft 15w43c, Minecraft 15w44a, Minecraft 15w44b, ..., Minecraft 1.11 Pre-Release 1, Minecraft 1.12, Minecraft 1.12.1 Pre-Release 1, Minecraft 1.12.2, Minecraft 18w19b

Minecraft 1.13.1

Retrieved