private static bool CheckAuthentication(AuthenticationResponse response, string salt, out Rights accessRights) { accessRights = 0; if (response.Mode == AuthenticationMode.Guest && Config.AllowUnauthenticatedRead) { accessRights = Rights.Read; if (Config.AllowUnauthenticatedWrite) accessRights |= Rights.Write; return true; } else if (response.Mode == AuthenticationMode.Simple) { var login = Config.GetSimpleLogin(response.IdentifierToken); if (login == null) { string doSomeWork = BCrypt.Net.BCrypt.GenerateSalt(); return false; } else { if (BCrypt.Net.BCrypt.HashPassword(login.Password, salt) == System.Text.ASCIIEncoding.ASCII.GetString(response.Payload)) { accessRights = login.Access; return true; } return false; } } else throw new Exception(string.Format("Unknown authentication mode: {0}", response.Mode)); }
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; }