// after receiving response from the client/service // encrypt the sent challenge with the stored password hash // if the received response and the result are the same, user authentication is complete // Logs result public bool CheckPassword(UserRequest userRequest, byte[] response) { byte[] passHash; if (!Database.usersDB.TryGetValue(userRequest.Username, out passHash)) { throw new FaultException <SecurityException>(new SecurityException($"Authentication Service: Username '{userRequest.Username}' doesn't exist")); } ChallengeResponse cr = new ChallengeResponse(); byte[] expected = cr.Encrypt(passHash, userRequest.Challenge); if (Equals(expected, response)) { try { Audit.AuthenticationSuccess(userRequest.Username); } catch (Exception e) { Console.WriteLine(e.Message); } Console.WriteLine($"Authentication service: {userRequest.Username} authenticated."); return(true); } else { try { Audit.AuthenticationFailure(userRequest.Username); } catch (Exception e) { Console.WriteLine(e.Message); } throw new FaultException <SecurityException>(new SecurityException($"Authentication Service: {userRequest.Username} failed to authenticate. Invalid password.")); } }
static void Main(string[] args) { SHA256 sha256Hash = SHA256.Create(); // connection with domain controller NetTcpBinding binding = new NetTcpBinding(); binding.Security.Mode = SecurityMode.Transport; binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.Windows; binding.Security.Transport.ProtectionLevel = System.Net.Security.ProtectionLevel.EncryptAndSign; string address = "net.tcp://localhost:9999/DomainControllerService"; EndpointAddress endpointAddressDC = new EndpointAddress(new Uri(address), EndpointIdentity.CreateUpnIdentity("DomainController")); string username = Environment.UserName; Console.WriteLine("Logging in as " + username + "\n"); Console.WriteLine("Enter password"); string password = Console.ReadLine(); Console.WriteLine("Enter service name:"); //which service to start string serviceName = Console.ReadLine(); // this is only needed for testing since every service instance is run on localhost // in production every service instance should have it's unique address short port; switch (serviceName) { case "wcfService": port = 9900; break; case "wcfService1": port = 9901; break; default: port = 9902; break; } string addressClient = $"net.tcp://localhost:{port}/" + serviceName; byte[] pwBytes = Encoding.ASCII.GetBytes(password); ChallengeResponse cr = new ChallengeResponse(); bool successful = false; using (DCProxy proxy = new DCProxy(binding, endpointAddressDC)) { try { serviceSecret = sha256Hash.ComputeHash(pwBytes); short salt = proxy.StartServiceAuthentication(serviceName); byte[] response = cr.Encrypt(serviceSecret, salt); successful = proxy.SendResponseService(response); // if not successful it will throw an exception Database.Load(username); Console.WriteLine(); } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine("Press return to exit."); Console.ReadLine(); return; } } Console.WriteLine("Starting service..."); // connection with the client and the Domain Controller NetTcpBinding bindingClient = new NetTcpBinding(); bindingClient.Security.Mode = SecurityMode.Transport; bindingClient.Security.Transport.ClientCredentialType = TcpClientCredentialType.Windows; bindingClient.Security.Transport.ProtectionLevel = System.Net.Security.ProtectionLevel.EncryptAndSign; ServiceHost serviceHost = new ServiceHost(typeof(DataManagement)); serviceHost.AddServiceEndpoint(typeof(IDataManagement), bindingClient, addressClient); //for receiving the session key serviceHost.AddServiceEndpoint(typeof(IDataManagementDC), bindingClient, addressClient); try { serviceHost.Open(); } catch (Exception e) { Console.WriteLine("Failed to start service. Error: {0}", e.Message); Console.WriteLine("Press return to exit."); Console.ReadLine(); return; } Console.WriteLine($"Service {serviceName} started. Press return to exit."); Console.ReadLine(); Console.WriteLine("Closing..."); Database.Save(username); serviceHost.Close(); Thread.Sleep(2000); }
static void Main(string[] args) { NetTcpBinding binding = new NetTcpBinding(); string address = "net.tcp://localhost:9999/DomainControllerClient"; binding.Security.Mode = SecurityMode.Transport; binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.Windows; binding.Security.Transport.ProtectionLevel = System.Net.Security.ProtectionLevel.EncryptAndSign; EndpointAddress endpointAddressDC = new EndpointAddress(new Uri(address), EndpointIdentity.CreateUpnIdentity("DomainController")); SHA256 sha256Hash = SHA256.Create(); ChallengeResponse cr = new ChallengeResponse(); ClientSessionData sessionData; string username = Environment.UserName; string password; Console.WriteLine("Logging in as " + username); //user account password Console.WriteLine("Enter password:"******"Enter service name: "); string serviceName = Console.ReadLine(); byte[] pwBytes = Encoding.ASCII.GetBytes(password); byte[] secret; try { using (DCProxy proxy = new DCProxy(binding, endpointAddressDC)) { secret = sha256Hash.ComputeHash(pwBytes); short salt = proxy.StartClientAuthentication(serviceName); byte[] response = cr.Encrypt(secret, salt); sessionData = proxy.SendResponse(response); Console.WriteLine($"Found service address: {sessionData.ServiceAddress}"); Console.WriteLine("--------------------------------------------------------------------------------"); } } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine("Press return to exit."); Console.ReadLine(); return; } NetTcpBinding bindingService = new NetTcpBinding(); try { using (ServiceProxy proxy = new ServiceProxy(bindingService, sessionData.ServiceAddress)) { char c; string key; byte[] encryptedKey; string value; byte[] encryptedValue; byte[] sessionKey = _3DESAlgorithm.Decrypt(sessionData.SessionKey, secret); do { Console.WriteLine(); Console.WriteLine("Choose an action:"); Console.WriteLine("\t- 'w' to write"); Console.WriteLine("\t- 'r' to read"); Console.WriteLine("\t- 'x' to exit"); c = char.ToLower(Console.ReadKey().KeyChar); Console.WriteLine(); switch (c) { case 'r': Console.WriteLine("Key of value to read:"); key = Console.ReadLine(); Console.WriteLine("Encrypting and sending READ request..."); encryptedKey = _3DESAlgorithm.Encrypt(key, sessionKey); encryptedValue = proxy.Read(encryptedKey); if (encryptedValue == null) { Console.WriteLine("Encryption error..."); break; } value = Encoding.ASCII.GetString(_3DESAlgorithm.Decrypt(encryptedValue, sessionKey)); Console.WriteLine("Received value: " + value); break; case 'w': Console.WriteLine("Key of value to write:"); key = Console.ReadLine(); Console.WriteLine("Value to write:"); value = Console.ReadLine(); Console.WriteLine("Encrypting and sending WRITE request..."); encryptedKey = _3DESAlgorithm.Encrypt(key, sessionKey); encryptedValue = _3DESAlgorithm.Encrypt(value, sessionKey); if (encryptedValue == null || encryptedKey == null) { Console.WriteLine("Encryption error..."); break; } if (proxy.Write(encryptedKey, encryptedValue)) { Console.WriteLine("Value written successfully."); } break; default: break; } Console.WriteLine("--------------------------------------------------------------------------------"); } while (c != 'x'); } } catch (CommunicationException e) { Console.WriteLine($"Communication error. Please restart. "); Console.ReadLine(); } catch (Exception e) { Console.WriteLine($"Error: {e.Message}"); Console.WriteLine("Please restart."); Console.ReadLine(); } }