コード例 #1
0
ファイル: MmoEncrypt.cs プロジェクト: paralin/MatrixServer
        /// <summary>
        /// This is automatically called when you first access Keys.
        /// </summary>
        public static void IndexKeys()
        {
            keys.Clear();
            if(!Directory.Exists(folderName)) Directory.CreateDirectory(folderName);

            var files = Directory.GetFiles(folderName, "*.mek");
            if(files.Length == 0)
            {
                //Generate a new key
                AES newKey = new AES(Encoding.UTF8);
                newKey.KeyToFile(folderName+"/EncryptionKey.mek");
                File.WriteAllText(folderName+"/EncryptionKey.txt", "There were no keys, so this default key was generated for you. Note this key will be erased the next time nodes are synced and this is NOT the proper way to add client keys.");
                files = Directory.GetFiles(folderName, "*.mek");
            }
            foreach(var file in files)
            {
                using (var md5 = MD5.Create())
                {
                    using (var stream = File.OpenRead(file))
                    {
                        var hash = md5.ComputeHash(stream);
                        keys[hash] = new AES(Encoding.UTF8, file);
                    }
                }
            }
        }
コード例 #2
0
 /// <summary>
 /// Create a new key database in a location.
 /// </summary>
 public EncryptionKeyDB(string folderName)
 {
     Instance = this;
     this.folderName = folderName;
     //Load mek files (matrix encryption keys)
     if (!Directory.Exists(folderName)) Directory.CreateDirectory(folderName);
     var files = Directory.GetFiles(this.folderName, "*.mek");
     if(files.Length == 0)
     {
         //Generate a new key
         AES newKey = new AES(Encoding.UTF8);
         newKey.KeyToFile(this.folderName+"/DefaultKey.mek");
         File.WriteAllText(this.folderName+"/DefaultKey.txt", "There were no keys, so this default key was generated for you.");
         files = Directory.GetFiles(this.folderName, "*.mek");
     }
     foreach(var file in files)
     {
         using (var md5 = MD5.Create())
         {
             using (var stream = File.OpenRead(file))
             {
                 var hash = md5.ComputeHash(stream);
                 keys[hash] = new AES(Encoding.UTF8, file);
             }
         }
     }
 }
コード例 #3
0
ファイル: Program.cs プロジェクト: paralin/MatrixServer
        public static void Main(string[] args)
        {
            running = true;
            log4net.Config.XmlConfigurator.Configure();
            log.Info("=== Matrix Host Server Launching ===");

            log.Debug("Searching for encryption key "+Settings.Default.KeyFile+"...");
            if(!File.Exists(Settings.Default.KeyFile))
            {
                log.Error("No encryption key! Exiting...");
                Console.ReadLine();
                return;
            }

            byte[] hash;
            AES encrypt;
            //Hash the file to a all lowercase string
            using (var md5 = MD5.Create())
            {
                using (var stream = File.OpenRead(Settings.Default.KeyFile))
                {
                    hash = md5.ComputeHash(stream);
                    encrypt = new AES(Encoding.UTF8, Settings.Default.KeyFile);
                }
            }

            client = new HostClient(Settings.Default.MasterIP, Settings.Default.MasterPort, encrypt, hash);
            nodeLibraryManager = new NodeLibraryManager("CompiledNodes", client);
            pool = new NodePool();
            client.Startup();

            while(running)
            {
                Thread.Sleep(50);
            }

            client.Shutdown();
            if(restart)
            {
                restart = false;
                Main(args);
            }
        }
コード例 #4
0
ファイル: ClientManager.cs プロジェクト: paralin/MatrixServer
 public void Start()
 {
     if (started) return;
     using (var md5 = MD5.Create())
     {
         using (var stream = File.OpenRead("EncryptionKey.mek"))
         {
             keyHash = md5.ComputeHash(stream);
             encryption = new AES(Encoding.UTF8, "EncryptionKey.mek");
         }
     }
     Task.Factory.StartNew(ClientThread);
     //ClientThread();
 }
コード例 #5
0
ファイル: Client.cs プロジェクト: paralin/MatrixServer
        public void ProcessMessage(byte[] message)
        {
            if (status == ClientStatus.Disconnected)
                return;

            //Reset heartbeat
            heartbeat.Stop();
            heartbeat.Start();

            if(status > ClientStatus.NoEncryption && message.Length > 1)
            {
                //Decrypt message
                var decrypt = encryption.Decrypt(message.Skip(1).ToArray());
                byte[] finalMessage = new byte[1+decrypt.Length];
                decrypt.CopyTo(finalMessage,1);
                finalMessage[0] = message[0];
                message = finalMessage;
            }

            var data = message.Skip(1).ToArray();

            if(message[0] != (byte)MessageIdentifier.Heartbeat)
                log.Debug("Received message: "+System.Enum.GetName(typeof(MessageIdentifier), message[0]));
            switch ((MessageIdentifier)message[0])
            {
            case MessageIdentifier.Heartbeat:
                clientInter.SendTo(clientInfo, BuildMessage(MessageIdentifier.Heartbeat, null));
                break;
            case MessageIdentifier.SetIdentity:
                if (status != ClientStatus.NoIdentity)
                {
                    break;
                }
                log.Debug("Setting up encryption with new client...");
                status = ClientStatus.NoEncryption;
                //Begin encryption exchange
                clientInter.SendTo(clientInfo, BuildMessage(MessageIdentifier.BeginEncryption, null));
                break;
                //Coming from client, this is the encryption md5.
            case MessageIdentifier.BeginEncryption:
                if (status != ClientStatus.NoEncryption)
                {
                    log.Error("Unexpected BeginEncryption from host.");
                    break;
                }
                //Get the encryption key MD5.
                byte[] keymd5 = data;
                AES encrypt = MmoEncrypt.ByHash(keymd5);
                if (encrypt == null)
                {
                    log.Info("Key not valid for client, rejecting and disconnecting.");
                    clientInter.SendTo(clientInfo, BuildMessage(MessageIdentifier.InvalidKey, null));
                    clientInter.Disconnect(clientInfo);
                    status = ClientStatus.Disconnected;
                }
                else
                {
                    log.Debug("Client accepted, beginning login.");
                    status = ClientStatus.LoggingIn;
                    encryption = encrypt;
                    clientInter.SendTo(clientInfo, BuildMessage(MessageIdentifier.ConfirmEncryption, Encoding.UTF8.GetBytes(passwordSalt)));
                }
                break;
            case MessageIdentifier.LoginVerify:
                if(status != ClientStatus.LoggingIn)
                {
                    log.Error("Client tried to log in when not in login state.");
                    break;
                }

                LoginRequest request = data.Deserialize<LoginRequest>();
                log.Debug("Login request, "+request.Username);
                User user;
                ISession session = MmoDatabase.Session;
                using(var transaction = session.BeginTransaction())
                {
                    user = session.CreateCriteria(typeof (User))
                        .Add(Restrictions.Eq("Username", request.Username))
                        .UniqueResult<User>();
                }
                LoginResponse response;
                if(user == null)
                {
                    response = new LoginResponse() {Success = false, Message = "User does not exist."};
                }else
                {
                    string hashedPassword = StringMD5.CreateMD5Hash(StringMD5.CreateMD5Hash(passwordSalt + user.Password)+passwordSalt);
                    if (request.MD5Pass != hashedPassword)
                    {
                        response = new LoginResponse() { Success = false, Message = "Password is incorrect." };
                    }
                    else
                    {
                        //check if the user is logged in
                        if(controller.IsUserLoggedIn(user.Username)){
                            log.Error("User '"+user.Username.Truncate(5)+"' is already logged in, rejecting...");
                            response = new LoginResponse() { Success = false, Message = "User is already logged in!" };
                        }else{
                            //Here we should actually be logged in
                            log.Debug("Client logged in, username: "******"CLIENT "+user.Username.Truncate(4));
                            thisUser = user;
                            status = ClientStatus.CharacterSelect;
                            response = new LoginResponse() {Success = true};
                        }
                    }
                }

                clientInter.SendTo(clientInfo, BuildMessage(MessageIdentifier.LoginVerify, response.Serialize()));
                break;
            case MessageIdentifier.CharacterData:
                if(status != ClientStatus.CharacterSelect){
                    log.Error("Client tried to retreive characters while not in character select state.");
                    break;
                }
                if(thisUser.Characters.Count == 0)
                {
                    thisUser.Characters.Add(new Character()
                                                {Gender = true, Name = "Test Character"+(new Random().Next(0,100)), User = thisUser, XP = 5000, CurrentRealm = MmoWorld.Realms.First()});
                    MmoDatabase.Save(thisUser);
                }
                CharacterData[] characters = new CharacterData[thisUser.Characters.Count];
                int i = 0;
                foreach(var character in thisUser.Characters)
                {
                    if (character.CurrentRealm == null) {
                        character.CurrentRealm = MmoWorld.Realms.First();
                        MmoDatabase.Save(character);
                    }
                    characters[i] = new CharacterData(){Id = character.Id, Name = character.Name, XP = character.XP, Gender=character.Gender, Realm = character.CurrentRealm.Name};
                        i++;
                }
                clientInter.SendTo(clientInfo, BuildMessage(MessageIdentifier.CharacterData, characters.Serialize()));
                break;
            case MessageIdentifier.CharacterVerify:
                if(status != ClientStatus.CharacterSelect){
                    log.Error("Client tried to select a character while not in character select state.");
                    break;
                }
                int characterId = BitConverter.ToInt32(data, 0);
                Character selChar = thisUser.Characters.SingleOrDefault(x=>x.Id == characterId);
                clientInter.SendTo(clientInfo, BuildMessage(MessageIdentifier.CharacterVerify, BitConverter.GetBytes(selChar != null)));
                if(selChar != null){
                    //todo: do something after logging in and selecting character
                }
                selectedCharacter = selChar;
                break;
            case MessageIdentifier.Disconnect:
                    DisconnectClient();
                    break;
            }
        }
コード例 #6
0
ファイル: Host.cs プロジェクト: paralin/MatrixServer
        /// <summary>
        /// Process a message for response.
        /// </summary>
        /// <param name="inter">Interface.</param>
        /// <param name="message">Received message.</param>
        public void ProcessMessage(HostInterface inter, byte[] message)
        {
            lastInter = inter;
            if (status == HostStatus.Disconnected)
                return;

            //Reset heartbeat
            heartbeat.Stop ();
            heartbeat.Start ();

            if (status > HostStatus.NoEncryption && message.Length > 1) {
                //Decrypt message
                var decrypt = encryption.Decrypt (message.Skip (1).ToArray ());
                byte[] finalMessage = new byte[1 + decrypt.Length];
                decrypt.CopyTo (finalMessage, 1);
                finalMessage [0] = message [0];
                message = finalMessage;
            }

            if (message [0] != (byte)MessageIdentifier.Heartbeat)
                log.Debug ("Received message: " + Enum.GetName (typeof(MessageIdentifier), message [0]));
            switch ((MessageIdentifier)message [0]) {
            case MessageIdentifier.Heartbeat:
                inter.SendTo (hostInfo, BuildMessage (MessageIdentifier.Heartbeat, null));
                break;
            //Coming from client, this is confirming an identity.
            case MessageIdentifier.SetIdentity:
                if (status != HostStatus.NoIdentity) {
                    log.Debug ("Host already has registered.");
                    break;
                }
                log.Debug ("Identity confirmed, beginning encryption sequence.");
                status = HostStatus.NoEncryption;
                    //Begin encryption exchange
                inter.SendTo (hostInfo, BuildMessage (MessageIdentifier.BeginEncryption, null));
                break;
            //Coming from client, this is the encryption md5.
            case MessageIdentifier.BeginEncryption:
                if (status != HostStatus.NoEncryption) {
                    log.Error ("Unexpected BeginEncryption from host.");
                    break;
                }
                    //Get the encryption key MD5.
                byte[] keymd5 = message.Skip (1).ToArray ();
                log.Debug ("Encryption key confirmation request: " +
                BitConverter.ToString (keymd5).Replace ("-", "").ToLower ());
                AES encrypt = EncryptionKeyDB.Instance.ByHash (keymd5);
                if (encrypt == null) {
                    log.Info ("Key not valid for host, rejecting and disconnecting.");
                    inter.SendTo (hostInfo, BuildMessage (MessageIdentifier.InvalidKey, null));
                    inter.DisconnectHost (hostInfo);
                    status = HostStatus.Disconnected;
                } else {
                    log.Debug ("Host accepted, beginning node sync.");
                    status = HostStatus.SyncNodes;
                    inter.SendTo (hostInfo, BuildMessage (MessageIdentifier.ConfirmEncryption, null));
                    encryption = encrypt;
                }
                break;
            case MessageIdentifier.NodeSync:
                var inputIndex =
                    Serializer.Deserialize<Dictionary<string, byte[]>> (new MemoryStream (message.Skip (1).ToArray ()));
                var syncJob = NodeLibraryManager.Instance.CreateSyncJob (inputIndex);
                if (syncJob == null) {
                    inter.SendTo (hostInfo, BuildMessage (MessageIdentifier.BeginOperation, null));
                    status = HostStatus.LoadingNodes;
                } else {
                    byte[] serializedJob;
                    using (var ms = new MemoryStream ()) {
                        Serializer.Serialize (ms, syncJob);
                        serializedJob = ms.ToArray ();
                        status = HostStatus.SyncNodes;
                    }
                    inter.SendTo (hostInfo, BuildMessage (MessageIdentifier.NodeSync, serializedJob));
                }
                break;
            case MessageIdentifier.GetLibraryURL:
                    //Retreive the library url for the path
                string dataString = Encoding.Unicode.GetString (message, 1, message.Length - 1);
                int reqId = int.Parse (dataString.Split (':') [0]);
                string library = dataString.Split (':') [1];
                var libraryUrl = Encoding.UTF8.GetBytes (reqId + ":" + NodeHost.Instance.GetDownloadUrl (library));
                inter.SendTo (hostInfo, BuildMessage (MessageIdentifier.GetLibraryURL, libraryUrl));
                break;
            case MessageIdentifier.BeginOperation:
                if (status == HostStatus.LoadingNodes) {
                    status = HostStatus.Operating;
                    log.Info ("New host ready for operation.");
                    try {
                        Task.Factory.StartNew (() => inter.Controller.OnHostAdded (hostInfo));
                    } catch (Exception ex) {
                        log.Error ("Error not caught by Controller, " + ex.ToString ());
                    }
                }
                break;
            case MessageIdentifier.NodeVerify:
                int verId = BitConverter.ToInt32 (message, 1);
                NodeInfo info;
                using (MemoryStream ms = new MemoryStream ()) {
                    var inputBytes = message.Skip (1 + sizeof(int)).ToArray ();
                    ms.Write (inputBytes, 0, inputBytes.Length);
                    ms.Position = 0;
                    info = Serializer.Deserialize<NodeInfo> (ms);
                }

                var response = NodePool.Instance.CheckNodeExists (info);
                var respBytes = new byte[sizeof(int) + sizeof(bool)];
                BitConverter.GetBytes (verId).CopyTo (respBytes, 0);
                BitConverter.GetBytes (response).CopyTo (respBytes, sizeof(int));
                inter.SendTo (hostInfo, BuildMessage (MessageIdentifier.NodeVerify, respBytes));
                break;
            case MessageIdentifier.RMIResponse:
                if (status != HostStatus.Operating)
                    return;
                var data = message.Skip (1).ToArray ();
                var rmi = data.Deserialize<NodeRMI> ();
                var destoNode = NodePool.Instance.NodeForId (rmi.SNodeID);
                if (destoNode == null)
                    return;
                if (destoNode.Id == 0)
                    NodePool.Instance.HandleRMIResponse (rmi);
                else {
                    lastInter.RouteRMIResponse (rmi);
                }
                break;
            case MessageIdentifier.ReqNodeList:
                if (status != HostStatus.Operating)
                    return;
                SendEntireNodeList ();
                break;
            case MessageIdentifier.RMIInvoke:
                if (status != HostStatus.Operating)
                    return;
                NodeRMI trmi = message.Skip (1).ToArray ().Deserialize<NodeRMI> ();
                var tdestoNode = NodePool.Instance.NodeForId (trmi.NodeID);
                if (tdestoNode == null) {
                    trmi.SerializeReturnValue (new NodeNotExistException ());
                    lastInter.SendTo (hostInfo, BuildMessage (MessageIdentifier.RMIResponse, trmi.Serialize ()));
                    break;
                }
                lastInter.RouteRMIRequest (trmi, tdestoNode);
                break;
            }
        }