Пример #1
0
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
			}
		}
	}
}
Пример #2
0
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)
		}
	}
}