Ejemplo n.º 1
0
        public IServerState Process()
        {
            stream.WriteByte(Node.ProtocolVersion);
            var serverHandshake = new ServerHandshake();
            serverHandshake.NodeId = app.Node.Id;
            Serializer.SerializeWithLengthPrefix(stream, serverHandshake, PrefixStyle.Base128);

            var handshake = Serializer.DeserializeWithLengthPrefix<ClientHandshake>(stream, PrefixStyle.Base128);
            if (handshake.GetObjectRequest != null && handshake.StoreObjectRequest != null)
            {
                this.Warn("Ignoring TCP request from {0} containing multiple requests", client.Client.RemoteEndPoint);
                return null;
            }
            if (handshake.GetObjectRequest == null && handshake.StoreObjectRequest == null)
            {
                this.Warn("Ignoring TCP request from {0} containing no requests", client.Client.RemoteEndPoint);
                return null;
            }

            var clientAddress = ((IPEndPoint) client.Client.RemoteEndPoint).Address;
            app.Node.Kademlia.AddVerifiedNode(new IPEndPoint(clientAddress, handshake.Port), handshake.NodeId);

            if (handshake.GetObjectRequest != null)
            {
                return new GetObjectState(stream, app, handshake.GetObjectRequest);
            }
            return new StoreObjectState(stream, app, handshake.StoreObjectRequest);
        }
Ejemplo n.º 2
0
        private bool ReadHandshake()
        {
            var hs    = new byte[1024];
            int count = Socket.Receive(hs);

            var bytes = new ArraySegment <byte>(hs, 0, count);

            ServerHandshake handshake = null;

            if (bytes.Count > 0)
            {
                handshake = ParseServerHandshake(bytes);
            }


            var isValid = (handshake != null) &&
                          (handshake.Origin == Handshake.Origin) &&
                          (handshake.Location == "ws://" + Handshake.Host + Handshake.ResourcePath);

            if (isValid)
            {
                for (int i = 0; i < 16; i++)
                {
                    if (handshake.AnswerBytes[i] != Handshake.ExpectedAnswer[i])
                    {
                        isValid = false;
                        break;
                    }
                }
            }

            return(isValid);
        }
Ejemplo n.º 3
0
    private void Receive(object sender, MessageEventArgs e)
    {
        PacketChecker packet = JsonUtility.FromJson <PacketChecker>(e.Data);

        if (packet == null)
        {
            return;
        }

        if (packet.packetType == null)
        {
            return;
        }

        switch (packet.packetType)
        {
        case (int)GameServerPackets.Handshake:
            ServerHandshake shake = JsonUtility.FromJson <ServerHandshake>(e.Data);
            Debug.Log(shake.welcomeMessage);
            break;

        case (int)GameServerPackets.GetLobbyCode:
            CreateLobby lobby = JsonUtility.FromJson <CreateLobby>(e.Data);
            info.currentGame = lobby.lobbyCode;
            actionsToRun.Add(() => SceneManager.LoadScene(joinScene));
            break;

        case (int)GameServerPackets.ErrorMessage:
            Disconnect();
            Application.Quit();
            break;
        }
    }
 public void FindsKeysFromMessage(string message)
 {
     ServerHandshake.GetKey(message, actualyKey);
     for (int i = 0; i < ServerHandshake.KeyLength; i++)
     {
         if (expectedKey[i] != actualyKey[i])
         {
             Assert.Fail($"Keys did not match.");
         }
     }
 }
Ejemplo n.º 5
0
        private ServerHandshake ParseServerHandshake(ArraySegment <byte> byteShake)
        {
            // the "grammar" of the handshake
            var pattern = @"^HTTP\/1\.1 101 Web Socket Protocol Handshake\r\n" +
                          @"((?<field_name>[^:\r\n]+):\s(?<field_value>[^\r\n]+)\r\n)+"; // unordered set of fields (name-chars colon space any-chars cr lf)

            // subtract the challenge bytes from the handshake
            var handshake = new ServerHandshake();
            ArraySegment <byte> challenge = new ArraySegment <byte>(byteShake.Array, byteShake.Count - 16, 16);

            handshake.AnswerBytes = new byte[16];
            //challenge.Array;
            Array.Copy(challenge.Array, challenge.Offset, handshake.AnswerBytes, 0, 16);

            // get the rest of the handshake
            var utf8_handshake = Encoding.UTF8.GetString(byteShake.Array, 0, byteShake.Count - 16);

            // match the handshake against the "grammar"
            var regex  = new Regex(pattern, RegexOptions.IgnoreCase);
            var match  = regex.Match(utf8_handshake);
            var fields = match.Groups;


            // run through every match and save them in the handshake object
            for (int i = 0; i < fields["field_name"].Captures.Count; i++)
            {
                var name  = fields["field_name"].Captures[i].ToString();
                var value = fields["field_value"].Captures[i].ToString();

                switch (name.ToLower())
                {
                case "sec-websocket-origin":
                    handshake.Origin = value;
                    break;

                case "sec-websocket-location":
                    handshake.Location = value;
                    break;

                case "sec-websocket-protocol":
                    handshake.SubProtocol = value;
                    break;
                }
            }
            return(handshake);
        }
Ejemplo n.º 6
0
        public void ClientConnecting(IncomingMessageBuffer buffer)
        {
            ClientConnect message = new ClientConnect();

            message.Parse(buffer);

            ServerHandshake handshake = new ServerHandshake();

            handshake.Address  = UdpReceiver.Instance.ServerEndpoint;
            handshake.SendPing = message.SendPing;
            handshake.SendPong = message.SendPing + 1000L;

            Frame frame = new Frame();

            frame.Payload     = handshake.ToByteArray();
            frame.Reliability = Frame.ReliabilityStatus.UNRELIABLE;

            SendFrame(frame);
        }
Ejemplo n.º 7
0
        public static HandshakeReturnCapsula Login(Logger logger, Stream stream, X509Certificate2 cert, string password, string userName = null, int?clientId = null)
        {
            ClientHandshake clientHandshake = new ClientHandshake()
            {
                PemCertificate = X509Certificate2Utils.ExportToPem(cert),
                UserName       = userName,
                ClientId       = clientId,
                ServerPassword = password
            };

            if (userName != null && userName.Length > DataConstants.USER_NAME_MAX_LENGHT)
            {
                throw new Exception("Username is too long.");
            }

            TextEncoder.SendJson(stream, clientHandshake);

            byte[] encrypted = BinaryEncoder.ReceiveBytes(stream);
            byte[] decrypted = RSAEncoder.Decrypt(encrypted, cert);
            BinaryEncoder.SendBytes(stream, decrypted);

            ServerHandshake serverHandshake = TextEncoder.ReadJson <ServerHandshake>(stream);

            logger.Log("Handshake", "Handshake", serverHandshake.Errors, false);

            if (!serverHandshake.Succeeded)
            {
                throw new Exception($"Handshake failed\n{serverHandshake.Errors}");
            }

            return(new HandshakeReturnCapsula()
            {
                UserId = serverHandshake.UserId,
                UserName = serverHandshake.UserName,
                ClientId = serverHandshake.ClientId,
                SelfAesPassword = serverHandshake.SelfAesKey == null ? null : new AESPassword(RSAEncoder.DecryptAndVerify(serverHandshake.SelfAesKey, cert, cert))
            });
        }
Ejemplo n.º 8
0
        private bool CheckAuthenticationResponse(Context context)
        {
            var receivedData = context.UserContext.DataFrame.ToString();
            var header       = new Header(receivedData);
            var handshake    = new ServerHandshake(header);

            if (Authentication.GenerateAccept(_handshake.Key) != handshake.Accept)
            {
                return(false);
            }

            if (SubProtocols != null)
            {
                if (header.SubProtocols == null)
                {
                    return(false);
                }

                foreach (var s in SubProtocols)
                {
                    if (header.SubProtocols.Contains(s) && String.IsNullOrEmpty(CurrentProtocol))
                    {
                        CurrentProtocol = s;
                    }
                }
                if (String.IsNullOrEmpty(CurrentProtocol))
                {
                    return(false);
                }
            }

            ReadyState      = ReadyStates.OPEN;
            IsAuthenticated = true;
            _connecting     = false;
            context.UserContext.OnConnected();
            return(true);
        }
Ejemplo n.º 9
0
        public static ConnectionInfo Run(Stream stream, Action <string> log, ServerConfig config)
        {
            ClientHandshake  clientHandshake   = TextEncoder.ReadJson <ClientHandshake>(stream);
            X509Certificate2 clientCertificate = X509Certificate2Utils.ImportFromPem(clientHandshake.PemCertificate);

            log($"Logging user sent username {clientHandshake.UserName}\n Certificate:\n {clientHandshake.PemCertificate}");

            ServerHandshake errorHandshake = new ServerHandshake()
            {
                Errors    = "",
                NewUser   = false,
                Succeeded = false,
                UserId    = -1,
                UserName  = ""
            };

            if (config.Password != null && !config.Password.Equals(clientHandshake.ServerPassword))
            {
                errorHandshake.Errors = "Server password is wrong.";
                TextEncoder.SendJson(stream, errorHandshake);
                throw new Exception(errorHandshake.Errors);
            }

            log("Generating random bytes");
            byte[] randomBytes = LUtils.GenerateRandomBytes(TcpConstants.HANDSHAKE_LENGHT);

            log("Sending encrypted bytes");
            BinaryEncoder.SendBytes(stream, RSAEncoder.Encrypt(randomBytes, clientCertificate));

            byte[] received = BinaryEncoder.ReceiveBytes(stream);
            if (!randomBytes.SequenceEqual(received))
            {
                log("Client's certificate verification failed.");
                errorHandshake.Errors = "Client's certificate verification failed.";
                TextEncoder.SendJson(stream, errorHandshake);
                throw new Exception(errorHandshake.Errors);
            }

            log("Certificate verification succeeded.");

            Users   user;
            String  message;
            Clients client;

            byte[] aesKey  = null;
            bool   newUser = false;

            using (Context context = new Context(config))
            {
                byte[] hash = SHA256Utils.ComputeByteSha256Hash(clientCertificate);
                user = context.Users.SingleOrDefault(u => u.PublicCertificateSha256.SequenceEqual(hash));

                if (user == null)
                {
                    log("User doesn't exist yet. I'll try to create him.");
                    newUser = true;

                    log("Checking the uniquity of username.");
                    String userName = clientHandshake.UserName;
                    if (context.Users.SingleOrDefault(u => u.UserName.Equals(userName)) != null)
                    {
                        errorHandshake.Errors = "Username isn't unique.";
                        TextEncoder.SendJson(stream, errorHandshake);
                        throw new Exception(errorHandshake.Errors);
                    }
                    else if (userName.Length > 45)
                    {
                        errorHandshake.Errors = "Username is too long (max. 45 chars)";
                        TextEncoder.SendJson(stream, errorHandshake);
                        throw new Exception(errorHandshake.Errors);
                    }
                    else if (userName.Length < 4)
                    {
                        errorHandshake.Errors = "Username is too short (min. 4 chars)";
                        TextEncoder.SendJson(stream, errorHandshake);
                        throw new Exception(errorHandshake.Errors);
                    }
                    else if (!Validators.ValidateRegexUserName(userName))
                    {
                        errorHandshake.Errors = "Username must match this regex ^[a-zA-Z][-a-zA-Z0-9_]+$ (Vaguely can't contain special chars and spaces)";
                        TextEncoder.SendJson(stream, errorHandshake);
                        throw new Exception(errorHandshake.Errors);
                    }

                    log("Creating user.");
                    user = new Users()
                    {
                        PublicCertificate       = clientHandshake.PemCertificate,
                        PublicCertificateSha256 = hash,
                        UserName = clientHandshake.UserName
                    };

                    context.Users.Add(user);
                    context.SaveChanges();

                    message = "User successfully created.";
                    log("User successfully created.");
                }
                else
                {
                    message = "User exists.";
                    log("User exists.");
                }

                client = new Clients()
                {
                    UserId = user.Id
                };

                if (clientHandshake.ClientId == null)
                {
                    log($"Loading self-aes key.");
                    aesKey = context.UsersKeys
                             .Where(u => u.RecepientId == user.Id)
                             .Where(u => u.SenderId == user.Id)
                             .Select(u => u.AesKey)
                             .SingleOrDefault();

                    context.Add(client);
                    context.SaveChanges();

                    log($"Added client with Id {client.Id}.");
                }
                else
                {
                    client.Id = (int)clientHandshake.ClientId;
                    if (context.Clients.Where(u => u.Id == client.Id).Single().UserId != user.Id)
                    {
                        errorHandshake.Errors = "This client id isn't owned by this user.";
                        TextEncoder.SendJson(stream, errorHandshake);
                        throw new Exception(errorHandshake.Errors);
                    }

                    log($"Client with Id {client.Id} has logged in.");
                }
            }

            ServerHandshake toSend = new ServerHandshake()
            {
                Errors     = message,
                NewUser    = newUser,
                Succeeded  = true,
                UserId     = user.Id,
                UserName   = user.UserName,
                ClientId   = client.Id,
                SelfAesKey = aesKey
            };

            TextEncoder.SendJson(stream, toSend);

            ConnectionInfo ret = new ConnectionInfo(user, clientCertificate, client.Id);

            log($"Handshake successeded. User {ret.UserName} with id {ret.UserId} has logged in. Client has id {client.Id}.");
            return(ret);
        }
Ejemplo n.º 10
0
        private ServerHandshake ParseServerHandshake(ArraySegment<byte> byteShake)
        {
            // the "grammar" of the handshake
            var pattern = @"^HTTP\/1\.1 101 Web Socket Protocol Handshake\r\n" +
                          @"((?<field_name>[^:\r\n]+):\s(?<field_value>[^\r\n]+)\r\n)+"; // unordered set of fields (name-chars colon space any-chars cr lf)

            // subtract the challenge bytes from the handshake
            var handshake = new ServerHandshake();
            ArraySegment<byte> challenge = new ArraySegment<byte>(byteShake.Array, byteShake.Count - 16, 16);
            handshake.AnswerBytes = new byte[16];
            //challenge.Array;
            Array.Copy(challenge.Array, challenge.Offset, handshake.AnswerBytes, 0, 16);

            // get the rest of the handshake
            var utf8_handshake = Encoding.UTF8.GetString(byteShake.Array, 0, byteShake.Count - 16);

            // match the handshake against the "grammar"
            var regex = new Regex(pattern, RegexOptions.IgnoreCase);
            var match = regex.Match(utf8_handshake);
            var fields = match.Groups;

            // run through every match and save them in the handshake object
            for (int i = 0; i < fields["field_name"].Captures.Count; i++)
            {
                var name = fields["field_name"].Captures[i].ToString();
                var value = fields["field_value"].Captures[i].ToString();

                switch (name.ToLower())
                {
                    case "sec-websocket-origin":
                        handshake.Origin = value;
                        break;
                    case "sec-websocket-location":
                        handshake.Location = value;
                        break;
                    case "sec-websocket-protocol":
                        handshake.SubProtocol = value;
                        break;
                }
            }
            return handshake;
        }
Ejemplo n.º 11
0
        public static UserCapsula Run(Stream stream, Action <string> log, ServerConfig config)
        {
            ClientHandshake  clientHandshake   = TextEncoder.ReadClientHandshake(stream);
            X509Certificate2 clientCertificate = X509Certificate2Utils.ImportFromPem(clientHandshake.PemCertificate);

            log($"Logging user sent username {clientHandshake.UserName}\n Certificate:\n {clientHandshake.PemCertificate}");

            log("Generating random bytes");
            byte[] randomBytes = LUtils.GenerateRandomBytes(TcpConstants.HANDSHAKE_LENGHT);

            log("Sending encrypted bytes");
            BinaryEncoder.SendBytes(stream, RSAEncoder.Encrypt(randomBytes, clientCertificate));

            ServerHandshake errorHandshake = new ServerHandshake()
            {
                Errors    = "",
                NewUser   = false,
                Succeeded = false,
                UserId    = -1,
                UserName  = ""
            };

            byte[] received = BinaryEncoder.ReceiveBytes(stream);
            if (!randomBytes.SequenceEqual(received))
            {
                log("Sending error to client.");
                errorHandshake.Errors = "Client's certificate verification failed.";
                TextEncoder.SendJson(stream, errorHandshake);
                throw new Exception(errorHandshake.Errors);
            }

            log("Certificate verification succeeded.");

            Users   user;
            String  message;
            Clients client;
            bool    newUser = false;

            using (Context context = new Context(config))
            {
                SHA1   sha  = new SHA1CryptoServiceProvider();
                byte[] hash = sha.ComputeHash(clientCertificate.RawData);
                user = context.Users.SingleOrDefault(u => u.PublicCertificateSha1.SequenceEqual(hash));

                if (user == null)
                {
                    log("User doesn't exist yet. I'll try to create him.");
                    newUser = true;

                    log("Checking the uniquity of username.");
                    String userName = clientHandshake.UserName;
                    if (context.Users.SingleOrDefault(u => u.UserName.Equals(userName)) != null)
                    {
                        log("Username isn't unique.");
                        errorHandshake.Errors = "Username isn't unique.";
                        TextEncoder.SendJson(stream, errorHandshake);
                        throw new Exception(errorHandshake.Errors);
                    }

                    log("Creating user.");
                    user = new Users()
                    {
                        PublicCertificate     = clientHandshake.PemCertificate,
                        PublicCertificateSha1 = hash,
                        UserName = clientHandshake.UserName
                    };

                    context.Users.Add(user);
                    context.SaveChanges();

                    message = "User successfully created.";
                    log("User successfully created.");
                }
                else
                {
                    message = "User exists.";
                    log("User exists.");
                }

                client = new Clients()
                {
                    UserId = user.Id
                };

                if (clientHandshake.ClientId == null)
                {
                    context.Add(client);
                    context.SaveChanges();

                    log($"Added client with Id {client.Id}.");
                }
                else
                {
                    log($"Client with Id {client.Id} has logged in.");
                }
            }

            ServerHandshake toSend = new ServerHandshake()
            {
                Errors    = message,
                NewUser   = newUser,
                Succeeded = true,
                UserId    = user.Id,
                UserName  = user.UserName,
                ClientId  = client.Id
            };

            TextEncoder.SendJson(stream, toSend);

            UserCapsula ret = new UserCapsula(user, clientCertificate);

            log($"Handshake successeded. User {ret.UserName} with id {ret.UserId} has logged in");
            return(ret);
        }
Ejemplo n.º 12
0
 public static ClientHandshake Handshake(ServerHandshake serverData, NetworkStream stream)
 {
     SendServerData(serverData, stream);
     return(GetClientData(stream));
 }
Ejemplo n.º 13
0
 public static void SendServerData(ServerHandshake serverData, NetworkStream stream)
 {
     NetworkInterop.WriteInt(stream, serverData.clientNumber);
 }