static void HandleConnection(System.IO.DirectoryInfo info, TcpClient client) { Area ws = null; ClientStateInfo clientInfo = new ClientStateInfo(); using (client) using (SharedNetwork.SharedNetworkInfo sharedInfo = new SharedNetwork.SharedNetworkInfo()) { try { var stream = client.GetStream(); Handshake hs = ProtoBuf.Serializer.DeserializeWithLengthPrefix<Handshake>(stream, ProtoBuf.PrefixStyle.Fixed32); DomainInfo domainInfo = null; lock (SyncObject) { if (hs.RequestedModule == null) hs.RequestedModule = string.Empty; if (!Domains.TryGetValue(hs.RequestedModule, out domainInfo)) { domainInfo = Domains.Where(x => x.Key.Equals(hs.RequestedModule, StringComparison.OrdinalIgnoreCase)).Select(x => x.Value).FirstOrDefault(); } if (domainInfo == null) { if (!Config.AllowVaultCreation || !Config.RequiresAuthentication || string.IsNullOrEmpty(hs.RequestedModule) || System.IO.Directory.Exists(System.IO.Path.Combine(info.FullName, hs.RequestedModule))) { Network.StartTransaction startSequence = Network.StartTransaction.CreateRejection(); Printer.PrintDiagnostics("Rejecting client due to invalid domain: \"{0}\".", hs.RequestedModule); ProtoBuf.Serializer.SerializeWithLengthPrefix<Network.StartTransaction>(stream, startSequence, ProtoBuf.PrefixStyle.Fixed32); return; } domainInfo = new DomainInfo() { Bare = true, Directory = null }; } } try { ws = Area.Load(domainInfo.Directory, true, true); if (domainInfo.Bare) throw new Exception("Domain is bare, but workspace could be loaded!"); } catch { if (!domainInfo.Bare) throw new Exception("Domain not bare, but couldn't load workspace!"); } Printer.PrintDiagnostics("Received handshake - protocol: {0}", hs.VersionrProtocol); SharedNetwork.Protocol? clientProtocol = hs.CheckProtocol(); bool valid = true; if (clientProtocol == null) valid = false; else { valid = SharedNetwork.AllowedProtocols.Contains(clientProtocol.Value); if (Config.RequiresAuthentication && !SharedNetwork.SupportsAuthentication(clientProtocol.Value)) valid = false; } if (valid) { sharedInfo.CommunicationProtocol = clientProtocol.Value; Network.StartTransaction startSequence = null; clientInfo.Access = Rights.Read | Rights.Write; clientInfo.BareAccessRequired = domainInfo.Bare; if (PrivateKey != null) { startSequence = Network.StartTransaction.Create(domainInfo.Bare ? string.Empty : ws.Domain.ToString(), PublicKey, clientProtocol.Value); Printer.PrintDiagnostics("Sending RSA key..."); ProtoBuf.Serializer.SerializeWithLengthPrefix<Network.StartTransaction>(stream, startSequence, ProtoBuf.PrefixStyle.Fixed32); if (!HandleAuthentication(clientInfo, client, sharedInfo)) throw new Exception("Authentication failed."); StartClientTransaction clientKey = ProtoBuf.Serializer.DeserializeWithLengthPrefix<StartClientTransaction>(stream, ProtoBuf.PrefixStyle.Fixed32); System.Security.Cryptography.RSAOAEPKeyExchangeDeformatter exch = new System.Security.Cryptography.RSAOAEPKeyExchangeDeformatter(PrivateKey); byte[] aesKey = exch.DecryptKeyExchange(clientKey.Key); byte[] aesIV = exch.DecryptKeyExchange(clientKey.IV); Printer.PrintDiagnostics("Got client key: {0}", System.Convert.ToBase64String(aesKey)); var aesCSP = System.Security.Cryptography.AesManaged.Create(); sharedInfo.DecryptorFunction = () => { return aesCSP.CreateDecryptor(aesKey, aesIV); }; sharedInfo.EncryptorFunction = () => { return aesCSP.CreateEncryptor(aesKey, aesIV); }; } else { startSequence = Network.StartTransaction.Create(domainInfo.Bare ? string.Empty : ws.Domain.ToString(), clientProtocol.Value); ProtoBuf.Serializer.SerializeWithLengthPrefix<Network.StartTransaction>(stream, startSequence, ProtoBuf.PrefixStyle.Fixed32); if (!HandleAuthentication(clientInfo, client, sharedInfo)) throw new Exception("Authentication failed."); StartClientTransaction clientKey = ProtoBuf.Serializer.DeserializeWithLengthPrefix<StartClientTransaction>(stream, ProtoBuf.PrefixStyle.Fixed32); } sharedInfo.Stream = stream; sharedInfo.Workspace = ws; sharedInfo.ChecksumType = Config.ChecksumType; clientInfo.SharedInfo = sharedInfo; while (true) { NetCommand command = ProtoBuf.Serializer.DeserializeWithLengthPrefix<NetCommand>(stream, ProtoBuf.PrefixStyle.Fixed32); if (command.Type == NetCommandType.Close) { Printer.PrintDiagnostics("Client closing connection."); break; } else if (command.Type == NetCommandType.PushInitialVersion) { bool fresh = false; if (domainInfo.Directory == null) { if (!clientInfo.Access.HasFlag(Rights.Create)) throw new Exception("Access denied."); fresh = true; System.IO.DirectoryInfo newDirectory = new System.IO.DirectoryInfo(System.IO.Path.Combine(info.FullName, hs.RequestedModule)); newDirectory.Create(); domainInfo.Directory = newDirectory; if (!newDirectory.Exists) throw new Exception("Access denied."); } if (!clientInfo.Access.HasFlag(Rights.Write)) throw new Exception("Access denied."); lock (SyncObject) { ws = Area.InitRemote(domainInfo.Directory, Utilities.ReceiveEncrypted<ClonePayload>(clientInfo.SharedInfo)); clientInfo.SharedInfo.Workspace = ws; domainInfo.Bare = false; if (fresh) Domains[hs.RequestedModule] = domainInfo; } } else if (command.Type == NetCommandType.PushBranchJournal) { if (!clientInfo.Access.HasFlag(Rights.Write)) throw new Exception("Access denied."); SharedNetwork.ReceiveBranchJournal(sharedInfo); } else if (command.Type == NetCommandType.QueryBranchID) { if (!clientInfo.Access.HasFlag(Rights.Read)) throw new Exception("Access denied."); Printer.PrintDiagnostics("Client is requesting a branch info for {0}", string.IsNullOrEmpty(command.AdditionalPayload) ? "<root>" : "\"" + command.AdditionalPayload + "\""); bool multiple = false; Objects.Branch branch = string.IsNullOrEmpty(command.AdditionalPayload) ? ws.RootBranch : ws.GetBranchByPartialName(command.AdditionalPayload, out multiple); if (branch != null) { ProtoBuf.Serializer.SerializeWithLengthPrefix<NetCommand>(stream, new NetCommand() { Type = NetCommandType.Acknowledge, AdditionalPayload = branch.ID.ToString() }, ProtoBuf.PrefixStyle.Fixed32); } else if (!multiple) { ProtoBuf.Serializer.SerializeWithLengthPrefix<NetCommand>(stream, new NetCommand() { Type = NetCommandType.Error, AdditionalPayload = "branch not recognized" }, ProtoBuf.PrefixStyle.Fixed32); } else { ProtoBuf.Serializer.SerializeWithLengthPrefix<NetCommand>(stream, new NetCommand() { Type = NetCommandType.Error, AdditionalPayload = "multiple branches with that name!" }, ProtoBuf.PrefixStyle.Fixed32); } } else if (command.Type == NetCommandType.ListBranches) { if (!clientInfo.Access.HasFlag(Rights.Read)) throw new Exception("Access denied."); Printer.PrintDiagnostics("Client is requesting a branch list."); ProtoBuf.Serializer.SerializeWithLengthPrefix<NetCommand>(stream, new NetCommand() { Type = NetCommandType.Acknowledge }, ProtoBuf.PrefixStyle.Fixed32); if (command.Identifier == 1) // send extra data { BranchList bl = new BranchList(); bl.Branches = clientInfo.SharedInfo.Workspace.Branches.ToArray(); Dictionary<Guid, Objects.Version> importantVersions = new Dictionary<Guid, Objects.Version>(); List<KeyValuePair<Guid, Guid>> allHeads = new List<KeyValuePair<Guid, Guid>>(); foreach (var x in bl.Branches) { if (x.Terminus.HasValue && !importantVersions.ContainsKey(x.Terminus.Value)) { importantVersions[x.Terminus.Value] = clientInfo.SharedInfo.Workspace.GetVersion(x.Terminus.Value); continue; } var heads = clientInfo.SharedInfo.Workspace.GetBranchHeads(x); foreach (var head in heads) { if (!importantVersions.ContainsKey(head.Version)) importantVersions[head.Version] = clientInfo.SharedInfo.Workspace.GetVersion(head.Version); } allHeads.AddRange(heads.Select(y => new KeyValuePair<Guid, Guid>(y.Branch, y.Version))); } bl.Heads = allHeads.ToArray(); bl.ImportantVersions = importantVersions.Values.ToArray(); Utilities.SendEncrypted<BranchList>(clientInfo.SharedInfo, bl); } else { BranchList bl = new BranchList(); bl.Branches = clientInfo.SharedInfo.Workspace.Branches.ToArray(); List<KeyValuePair<Guid, Guid>> allHeads = new List<KeyValuePair<Guid, Guid>>(); foreach (var x in bl.Branches) { if (x.Terminus.HasValue) continue; var heads = clientInfo.SharedInfo.Workspace.GetBranchHeads(x); if (heads.Count == 1) allHeads.Add(new KeyValuePair<Guid, Guid>(x.ID, heads[0].Version)); } bl.Heads = allHeads.ToArray(); Utilities.SendEncrypted<BranchList>(clientInfo.SharedInfo, bl); } } else if (command.Type == NetCommandType.RequestRecordUnmapped) { if (!clientInfo.Access.HasFlag(Rights.Read)) throw new Exception("Access denied."); Printer.PrintDiagnostics("Client is requesting specific record data blobs."); SharedNetwork.SendRecordDataUnmapped(sharedInfo); } else if (command.Type == NetCommandType.Clone) { if (!clientInfo.Access.HasFlag(Rights.Read)) throw new Exception("Access denied."); Printer.PrintDiagnostics("Client is requesting to clone the vault."); Objects.Version initialRevision = ws.GetVersion(ws.Domain); Objects.Branch initialBranch = ws.GetBranch(initialRevision.Branch); Utilities.SendEncrypted<ClonePayload>(sharedInfo, new ClonePayload() { InitialBranch = initialBranch, RootVersion = initialRevision }); } else if (command.Type == NetCommandType.PullVersions) { if (!clientInfo.Access.HasFlag(Rights.Read)) throw new Exception("Access denied."); Printer.PrintDiagnostics("Client asking for remote version information."); Branch branch = ws.GetBranch(new Guid(command.AdditionalPayload)); if (branch == null) ProtoBuf.Serializer.SerializeWithLengthPrefix<NetCommand>(stream, new NetCommand() { Type = NetCommandType.Error, AdditionalPayload = string.Format("Unknown branch {0}", command.AdditionalPayload) }, ProtoBuf.PrefixStyle.Fixed32); else ProtoBuf.Serializer.SerializeWithLengthPrefix<NetCommand>(stream, new NetCommand() { Type = NetCommandType.Acknowledge }, ProtoBuf.PrefixStyle.Fixed32); Stack<Objects.Branch> branchesToSend = new Stack<Branch>(); Stack<Objects.Version> versionsToSend = new Stack<Objects.Version>(); if (!SharedNetwork.SendBranchJournal(sharedInfo)) throw new Exception(); if (!SharedNetwork.GetVersionList(sharedInfo, sharedInfo.Workspace.GetBranchHeadVersion(branch), out branchesToSend, out versionsToSend)) throw new Exception(); if (!SharedNetwork.SendBranches(sharedInfo, branchesToSend)) throw new Exception(); if (!SharedNetwork.SendVersions(sharedInfo, versionsToSend)) throw new Exception(); } else if (command.Type == NetCommandType.PushObjectQuery) { if (!clientInfo.Access.HasFlag(Rights.Write)) throw new Exception("Access denied."); Printer.PrintDiagnostics("Client asking about objects on the server..."); SharedNetwork.ProcesPushObjectQuery(sharedInfo); } else if (command.Type == NetCommandType.PushBranch) { if (!clientInfo.Access.HasFlag(Rights.Write)) throw new Exception("Access denied."); Printer.PrintDiagnostics("Client attempting to send branch data..."); SharedNetwork.ReceiveBranches(sharedInfo); } else if (command.Type == NetCommandType.PushVersions) { if (!clientInfo.Access.HasFlag(Rights.Write)) throw new Exception("Access denied."); Printer.PrintDiagnostics("Client attempting to send version data..."); SharedNetwork.ReceiveVersions(sharedInfo); } else if (command.Type == NetCommandType.PushHead) { if (!clientInfo.Access.HasFlag(Rights.Write)) throw new Exception("Access denied."); Printer.PrintDiagnostics("Determining head information."); string errorData; lock (ws) { clientInfo.SharedInfo.Workspace.RunLocked(() => { try { clientInfo.SharedInfo.Workspace.BeginDatabaseTransaction(); if (!SharedNetwork.ImportBranchJournal(clientInfo.SharedInfo, false)) { clientInfo.SharedInfo.Workspace.RollbackDatabaseTransaction(); return false; } if (AcceptHeads(clientInfo, ws, out errorData)) { ImportVersions(ws, clientInfo); clientInfo.SharedInfo.Workspace.CommitDatabaseTransaction(); ProtoBuf.Serializer.SerializeWithLengthPrefix<NetCommand>(stream, new NetCommand() { Type = NetCommandType.AcceptPush }, ProtoBuf.PrefixStyle.Fixed32); return true; } else ProtoBuf.Serializer.SerializeWithLengthPrefix<NetCommand>(stream, new NetCommand() { Type = NetCommandType.RejectPush, AdditionalPayload = errorData }, ProtoBuf.PrefixStyle.Fixed32); clientInfo.SharedInfo.Workspace.RollbackDatabaseTransaction(); return false; } catch { clientInfo.SharedInfo.Workspace.RollbackDatabaseTransaction(); return false; } }, false); } } else if (command.Type == NetCommandType.SynchronizeRecords) { if (!clientInfo.Access.HasFlag(Rights.Read)) throw new Exception("Access denied."); Printer.PrintDiagnostics("Received {0} versions in version pack, but need {1} records to commit data.", sharedInfo.PushedVersions.Count, sharedInfo.UnknownRecords.Count); Printer.PrintDiagnostics("Beginning record synchronization..."); if (sharedInfo.UnknownRecords.Count > 0) { Printer.PrintDiagnostics("Requesting record metadata..."); SharedNetwork.RequestRecordMetadata(clientInfo.SharedInfo); Printer.PrintDiagnostics("Requesting record data..."); SharedNetwork.RequestRecordData(sharedInfo); if (!sharedInfo.Workspace.RunLocked(() => { return SharedNetwork.ImportRecords(sharedInfo); }, false)) { throw new Exception("Unable to import records!"); } } ProtoBuf.Serializer.SerializeWithLengthPrefix<NetCommand>(stream, new NetCommand() { Type = NetCommandType.Synchronized }, ProtoBuf.PrefixStyle.Fixed32); } else if (command.Type == NetCommandType.FullClone) { if (!clientInfo.Access.HasFlag(Rights.Read)) throw new Exception("Access denied."); ProtoBuf.Serializer.SerializeWithLengthPrefix<NetCommand>(stream, new NetCommand() { Type = NetCommandType.Acknowledge, Identifier = (int)ws.DatabaseVersion }, ProtoBuf.PrefixStyle.Fixed32); command = ProtoBuf.Serializer.DeserializeWithLengthPrefix<NetCommand>(stream, ProtoBuf.PrefixStyle.Fixed32); if (command.Type == NetCommandType.Acknowledge) { bool accept = false; BackupInfo backupInfo = null; lock (domainInfo) { string backupKey = ws.LastVersion + "-" + ws.LastBranch + "-" + ws.BranchJournalTipID.ToString(); backupInfo = domainInfo.Backup; if (backupKey != backupInfo.Key) { Printer.PrintMessage("Backup key out of date for domain DB[{0}] - {1}", domainInfo.Directory, backupKey); if (System.Threading.Interlocked.Decrement(ref backupInfo.Refs) == 0) backupInfo.Backup.Delete(); backupInfo = new BackupInfo(); domainInfo.Backup = backupInfo; var directory = new System.IO.DirectoryInfo(System.IO.Path.Combine(ws.AdministrationFolder.FullName, "backups")); directory.Create(); backupInfo.Backup = new System.IO.FileInfo(System.IO.Path.Combine(directory.FullName, System.IO.Path.GetRandomFileName())); if (ws.BackupDB(backupInfo.Backup)) { System.Threading.Interlocked.Increment(ref backupInfo.Refs); accept = true; backupInfo.Key = backupKey; } } else { accept = true; } if (accept) System.Threading.Interlocked.Increment(ref backupInfo.Refs); } if (accept) { Printer.PrintDiagnostics("Backup complete. Sending data."); byte[] blob = new byte[256 * 1024]; long filesize = backupInfo.Backup.Length; long position = 0; using (System.IO.FileStream reader = backupInfo.Backup.OpenRead()) { while (true) { long remainder = filesize - position; int count = blob.Length; if (count > remainder) count = (int)remainder; reader.Read(blob, 0, count); position += count; Printer.PrintDiagnostics("Sent {0}/{1} bytes.", position, filesize); if (count == remainder) { Utilities.SendEncrypted(sharedInfo, new DataPayload() { Data = blob.Take(count).ToArray(), EndOfStream = true }); break; } else { Utilities.SendEncrypted(sharedInfo, new DataPayload() { Data = blob, EndOfStream = false }); } } } ProtoBuf.Serializer.SerializeWithLengthPrefix<NetCommand>(stream, new NetCommand() { Type = NetCommandType.Acknowledge }, ProtoBuf.PrefixStyle.Fixed32); lock (domainInfo) { if (System.Threading.Interlocked.Decrement(ref backupInfo.Refs) == 0) backupInfo.Backup.Delete(); } } else { Utilities.SendEncrypted<DataPayload>(sharedInfo, new DataPayload() { Data = new byte[0], EndOfStream = true }); ProtoBuf.Serializer.SerializeWithLengthPrefix<NetCommand>(stream, new NetCommand() { Type = NetCommandType.Error }, ProtoBuf.PrefixStyle.Fixed32); } } } else { Printer.PrintDiagnostics("Client sent invalid command: {0}", command.Type); throw new Exception(); } } } else { Network.StartTransaction startSequence = Network.StartTransaction.CreateRejection(); Printer.PrintDiagnostics("Rejecting client due to protocol mismatch."); ProtoBuf.Serializer.SerializeWithLengthPrefix<Network.StartTransaction>(stream, startSequence, ProtoBuf.PrefixStyle.Fixed32); return; } } catch (Exception e) { Printer.PrintDiagnostics("Client was a terrible person, because: {0}", e); } finally { if (ws != null) ws.Dispose(); } } Printer.PrintDiagnostics("Ended client processor task!"); }
public bool Connect(string host, int port, string module, bool requirewrite = false) { if (port == -1) port = VersionrDefaultPort; IEnumerator<SharedNetwork.Protocol> protocols = SharedNetwork.AllowedProtocols.Cast<SharedNetwork.Protocol>().GetEnumerator(); Retry: if (!protocols.MoveNext()) { Printer.PrintMessage("#e#No valid protocols available.##"); return false; } Host = host; Port = port; Module = module; Connected = false; try { Connection = new System.Net.Sockets.TcpClient(); var connectionTask = Connection.ConnectAsync(Host, Port); if (!connectionTask.Wait(5000)) { throw new Exception(string.Format("Couldn't connect to target: {0}", this.VersionrURL)); } } catch (Exception e) { Printer.PrintError(e.Message); return false; } if (Connection.Connected) { try { Printer.PrintDiagnostics("Connected to server at {0}:{1}", host, port); Handshake hs = Handshake.Create(protocols.Current); hs.RequestedModule = Module; Printer.PrintDiagnostics("Sending handshake..."); Connection.NoDelay = true; ProtoBuf.Serializer.SerializeWithLengthPrefix<Handshake>(Connection.GetStream(), hs, ProtoBuf.PrefixStyle.Fixed32); var startTransaction = ProtoBuf.Serializer.DeserializeWithLengthPrefix<Network.StartTransaction>(Connection.GetStream(), ProtoBuf.PrefixStyle.Fixed32); if (startTransaction == null || !startTransaction.Accepted) { Printer.PrintError("#b#Server rejected connection.##"); if (startTransaction != null && hs.VersionrProtocol != startTransaction.ServerHandshake.VersionrProtocol) Printer.PrintError("## Protocol mismatch - local: {0}, remote: {1}", hs.VersionrProtocol, startTransaction.ServerHandshake.VersionrProtocol); else { if (startTransaction == null) Printer.PrintError("## Connection terminated unexpectedly."); else Printer.PrintError("## Rejected request."); return false; } Printer.PrintError("#b#Attempting to retry with a lower protocol.##"); goto Retry; } Printer.PrintDiagnostics("Server domain: {0}", startTransaction.Domain); if (Workspace != null && !string.IsNullOrEmpty(startTransaction.Domain) && startTransaction.Domain != Workspace.Domain.ToString()) { Printer.PrintError("Server domain doesn't match client domain. Disconnecting."); return false; } RemoteDomain = startTransaction.Domain; if (SharedNetwork.SupportsAuthentication(startTransaction.ServerHandshake.CheckProtocol().Value)) { var command = ProtoBuf.Serializer.DeserializeWithLengthPrefix<NetCommand>(Connection.GetStream(), ProtoBuf.PrefixStyle.Fixed32); if (command.Type == NetCommandType.Authenticate) { bool runauth = true; var challenge = ProtoBuf.Serializer.DeserializeWithLengthPrefix<AuthenticationChallenge>(Connection.GetStream(), ProtoBuf.PrefixStyle.Fixed32); if ((!requirewrite && (command.Identifier & 1) != 0) || (requirewrite && (command.Identifier & 2) != 0)) // server supports unauthenticated access { AuthenticationResponse response = new AuthenticationResponse() { IdentifierToken = string.Empty, Mode = AuthenticationMode.Guest }; ProtoBuf.Serializer.SerializeWithLengthPrefix(Connection.GetStream(), response, ProtoBuf.PrefixStyle.Fixed32); command = ProtoBuf.Serializer.DeserializeWithLengthPrefix<NetCommand>(Connection.GetStream(), ProtoBuf.PrefixStyle.Fixed32); if (command.Type == NetCommandType.Acknowledge) runauth = false; } if (runauth) { bool q = Printer.Quiet; Printer.Quiet = false; Printer.PrintMessage("Server at #b#{0}## requires authentication.", VersionrURL); while (true) { if (challenge.AvailableModes.Contains(AuthenticationMode.Simple)) { System.Console.CursorVisible = true; Printer.PrintMessageSingleLine("#b#Username:## "); string user = System.Console.ReadLine(); Printer.PrintMessageSingleLine("#b#Password:## "); string pass = GetPassword(); System.Console.CursorVisible = false; user = user.Trim(new char[] { '\r', '\n', ' ' }); AuthenticationResponse response = new AuthenticationResponse() { IdentifierToken = user, Mode = AuthenticationMode.Simple, Payload = System.Text.ASCIIEncoding.ASCII.GetBytes(BCrypt.Net.BCrypt.HashPassword(pass, challenge.Salt)) }; Printer.PrintMessage("\n"); ProtoBuf.Serializer.SerializeWithLengthPrefix(Connection.GetStream(), response, ProtoBuf.PrefixStyle.Fixed32); command = ProtoBuf.Serializer.DeserializeWithLengthPrefix<NetCommand>(Connection.GetStream(), ProtoBuf.PrefixStyle.Fixed32); if (command.Type == NetCommandType.AuthRetry) Printer.PrintError("#e#Authentication failed.## Retry."); if (command.Type == NetCommandType.AuthFail) { Printer.PrintError("#e#Authentication failed.##"); return false; } if (command.Type == NetCommandType.Acknowledge) break; } else { Printer.PrintError("Unsupported authentication requirements!"); return false; } } Printer.Quiet = q; } } } if (startTransaction.Encrypted) { var key = startTransaction.RSAKey; Printer.PrintDiagnostics("Server RSA Key: {0}", key.Fingerprint()); var publicKey = new System.Security.Cryptography.RSACryptoServiceProvider(); publicKey.ImportParameters(key); Printer.PrintDiagnostics("Generating secret key for data channel..."); System.Security.Cryptography.RSAOAEPKeyExchangeFormatter exch = new System.Security.Cryptography.RSAOAEPKeyExchangeFormatter(publicKey); System.Security.Cryptography.AesManaged aesProvider = new System.Security.Cryptography.AesManaged(); aesProvider.KeySize = 256; aesProvider.GenerateIV(); aesProvider.GenerateKey(); AESProvider = aesProvider; AESKey = aesProvider.Key; AESIV = aesProvider.IV; Printer.PrintDiagnostics("Key: {0}", System.Convert.ToBase64String(aesProvider.Key)); var keyExchangeObject = new Network.StartClientTransaction() { Key = exch.CreateKeyExchange(aesProvider.Key), IV = exch.CreateKeyExchange(aesProvider.IV) }; ProtoBuf.Serializer.SerializeWithLengthPrefix<StartClientTransaction>(Connection.GetStream(), keyExchangeObject, ProtoBuf.PrefixStyle.Fixed32); Connection.GetStream().Flush(); Connected = true; SharedNetwork.SharedNetworkInfo sharedInfo = new SharedNetwork.SharedNetworkInfo() { DecryptorFunction = () => { return Decryptor; }, EncryptorFunction = () => { return Encryptor; }, Stream = Connection.GetStream(), Workspace = Workspace, Client = true, CommunicationProtocol = protocols.Current }; SharedInfo = sharedInfo; } else { Printer.PrintDiagnostics("Using cleartext communication"); var keyExchangeObject = new Network.StartClientTransaction(); ProtoBuf.Serializer.SerializeWithLengthPrefix<StartClientTransaction>(Connection.GetStream(), keyExchangeObject, ProtoBuf.PrefixStyle.Fixed32); Connection.GetStream().Flush(); Connected = true; SharedNetwork.SharedNetworkInfo sharedInfo = new SharedNetwork.SharedNetworkInfo() { DecryptorFunction = null, EncryptorFunction = null, Stream = Connection.GetStream(), Workspace = Workspace, Client = true, CommunicationProtocol = protocols.Current }; SharedInfo = sharedInfo; } return true; } catch (Exception e) { Printer.PrintError("Error encountered: {0}", e); return false; } } else return false; }