func (cc *GameConnection) HandleAuth() { defer func() { delete(cc.Server.Clients, cc) cc.Conn.Close() }() remoteAddr := cc.Conn.RemoteAddr().String() state := 0 verifyToken := make([]byte, 0) for { cc.Conn.SetReadDeadline(time.Now().Add(time.Second * 10)) id, buf, err := protocol.ReadPacket(cc.Conn) if err != nil { err2, ok := err.(net.Error) if ok && err2.Timeout() { log.Printf("Timeout handling connection (%s): %s", remoteAddr, err2.Error()) } return } else { switch id { case 0x00: // Handshake, Status Request, Login start if state == 1 { log.Printf("Server pinged from: %s", remoteAddr) protocol.WriteNewPacket(cc.Conn, protocol.StatusResponseID, cc.Server.GetMinecraftStatus()) } else if state == 2 { cc.Player.Username, _ = protocol.ReadString(buf, 0) log.Printf("Got connection from %s", cc.Player.Username) defer log.Printf("Connection closed for %s", cc.Player.Username) pubKey := cc.Server.keyPair.Serialize() verifyToken = protocol.GenerateKey(16) protocol.WriteNewPacket(cc.Conn, protocol.EncryptionRequestID, "", int16(len(pubKey)), pubKey, int16(len(verifyToken)), verifyToken) } else { _, n := protocol.ReadVarint(buf, 0) // version _, n = protocol.ReadString(buf, n) // address _, n = protocol.ReadShort(buf, n) // port nextstate, n := protocol.ReadVarint(buf, n) state = int(nextstate) } case 0x01: // Encryption Response, Ping Request if state == 2 { secretLen, n := protocol.ReadShort(buf, 0) secretEncrypted, n := protocol.ReadBytes(buf, n, secretLen) tokenLen, n := protocol.ReadShort(buf, n) tokenEncrypted, n := protocol.ReadBytes(buf, n, tokenLen) verifyToken2, err := protocol.DecryptRSABytes(tokenEncrypted, cc.Server.keyPair) if err != nil { log.Printf("Error decrypting RSA token: %s", err.Error()) return } else if !bytes.Equal(verifyToken, verifyToken2) { log.Printf("Error: verification token did not match!") return } sharedSecret, err := protocol.DecryptRSABytes(secretEncrypted, cc.Server.keyPair) if err != nil { log.Printf("Error decrypting RSA secret: %s", err.Error()) return } cc.ConnEncrypted, err = protocol.NewAESConn(cc.Conn, sharedSecret) if err != nil { log.Printf("Error creating AES connection: %s", err.Error()) } cc.Player.Uuid, err = protocol.CheckAuth(cc.Player.Username, "", cc.Server.keyPair, sharedSecret) if err != nil { log.Printf("Failed to verify username %s: %s", cc.Player.Username, err) protocol.WriteNewPacket(cc.ConnEncrypted, protocol.PreAuthKickID, protocol.CreateJsonMessage("Failed to verify username!", "")) return } // protocol.WriteNewPacket(cc.ConnEncrypted, protocol.PreAuthKickID, protocol.CreateJsonMessage("Server will bbl", "blue")) cc.HandleNewConnection() return } else { time, _ := protocol.ReadLong(buf, 0) //fmt.Printf("Ping: %d\n", time) protocol.WriteNewPacket(cc.Conn, protocol.PingResponseID, time) return } default: log.Printf("Unknown Packet (state:%d): 0x%X : %s", state, id, hex.Dump(buf)) return } } } }
func (cc *GameConnection) HandleEncryptedConnection() { defer func() { cc.EntityServer.SendMessage(&protobuf.PlayerAction{ Player: cc.Player, Action: protobuf.PlayerAction_LEAVE, }) }() go func() { for cc.EntityServer != nil { time.Sleep(1 * time.Second) cc.Server.PlayerConnections[cc.Player.Uuid] <- protocol.CreatePacket(protocol.KeepAliveID, int32(time.Now().Nanosecond())) } }() for cc.EntityServer != nil { cc.Conn.SetReadDeadline(time.Now().Add(time.Second * 30)) id, buf, err := protocol.ReadPacket(cc.ConnEncrypted) n := 0 if err != nil { if err != io.EOF { log.Printf("Error reading packet: %s", err.Error()) } return } else if id == 0x01 { message, _ := protocol.ReadString(buf, 0) if len(message) > 0 && message[0] != '/' { cc.EntityServer.SendMessage(&protobuf.ChatMessage{ Message: message, Uuid: cc.Player.Uuid, }) } } else if id == 0x04 { cc.Player.X, n = protocol.ReadDouble(buf, n) cc.Player.FeetY, n = protocol.ReadDouble(buf, n) cc.Player.HeadY, n = protocol.ReadDouble(buf, n) cc.Player.Z, n = protocol.ReadDouble(buf, n) cc.Player.OnGround, n = protocol.ReadBool(buf, n) cc.EntityServer.SendMessage(&protobuf.PlayerAction{ Player: cc.Player, Action: protobuf.PlayerAction_MOVE_ABSOLUTE, Flags: 1, }) } else if id == 0x05 { cc.Player.Yaw, n = protocol.ReadFloat(buf, n) cc.Player.Pitch, n = protocol.ReadFloat(buf, n) cc.Player.OnGround, n = protocol.ReadBool(buf, n) cc.EntityServer.SendMessage(&protobuf.PlayerAction{ Player: cc.Player, Action: protobuf.PlayerAction_MOVE_ABSOLUTE, Flags: 2, }) } else if id == 0x06 { cc.Player.X, n = protocol.ReadDouble(buf, n) cc.Player.FeetY, n = protocol.ReadDouble(buf, n) cc.Player.HeadY, n = protocol.ReadDouble(buf, n) cc.Player.Z, n = protocol.ReadDouble(buf, n) cc.Player.Yaw, n = protocol.ReadFloat(buf, n) cc.Player.Pitch, n = protocol.ReadFloat(buf, n) cc.Player.OnGround, n = protocol.ReadBool(buf, n) cc.EntityServer.SendMessage(&protobuf.PlayerAction{ Player: cc.Player, Action: protobuf.PlayerAction_MOVE_ABSOLUTE, Flags: 3, }) } else if id == 0x07 { status, n := protocol.ReadByte(buf, n) x, n := protocol.ReadInt(buf, n) y, n := protocol.ReadByte(buf, n) z, n := protocol.ReadInt(buf, n) face, n := protocol.ReadByte(buf, n) chunkConn, err := cc.Server.Cluster.ChunkConnection(int64(x), int64(z), cc.Server) if err != nil { log.Print("Tried to destroy block on missing chunk server: ", err) } chunkConn.SendMessage(&protobuf.BlockUpdate{ X: int64(x), Y: uint32(y), Z: int64(z), BlockId: 0, Uuid: cc.Player.Uuid, }) log.Printf("digging block %d, %d, %d - status %d - face %d", x, y, z, status, face) } else if id == 0x08 { x, n := protocol.ReadInt(buf, n) y, n := protocol.ReadByte(buf, n) z, n := protocol.ReadInt(buf, n) face, n := protocol.ReadByte(buf, n) blockId, n := protocol.ReadShort(buf, n) quantity, n := protocol.ReadByte(buf, n) damage, n := protocol.ReadShort(buf, n) nbtLen, n := protocol.ReadShort(buf, n) if nbtLen > 0 { n += nbtLen } cursorX, n := protocol.ReadByte(buf, n) cursorY, n := protocol.ReadByte(buf, n) cursorZ, n := protocol.ReadByte(buf, n) if blockId > 0 && blockId < 256 && face < 6 { chunkConn, err := cc.Server.Cluster.ChunkConnection(int64(x), int64(z), cc.Server) if err != nil { log.Print("Tried to destroy block on missing chunk server: ", err) } switch face { case 0: y-- case 1: y++ case 2: z-- case 3: z++ case 4: x-- case 5: x++ } chunkConn.SendMessage(&protobuf.BlockUpdate{ X: int64(x), Y: uint32(y), Z: int64(z), BlockId: int32(blockId), BlockMetadata: int32(damage), Uuid: cc.Player.Uuid, }) } log.Printf("right clicked %d, %d, %d - face %d, blockId %d, quantity %d, damage %d, curX %d, curY %d, curZ %d", x, y, z, face, blockId, quantity, damage, cursorX, cursorY, cursorZ) } } }