private async Task <MemoryStream> CreateAppSettingsFile(RemoteAgentSettings settings, CancellationToken cancellationToken) { var remoteSettings = new RemoteSettings(); // copy any settings across. settings.RemoteApplicationSettings.CopyProperties(remoteSettings.AppSettings); settings.RemoteApplicationSettings.CopyProperties(remoteSettings.Network); settings.RemoteApplicationSettings.CopyProperties(remoteSettings.Permissions); settings.RemoteApplicationSettings.CopyProperties(remoteSettings.Plugins); settings.RemoteApplicationSettings.CopyProperties(remoteSettings.Alerts); //TODO these should be copied by the copy properties. remoteSettings.Permissions.AllowedHubs = settings.RemoteApplicationSettings.AllowedHubs; remoteSettings.Permissions.AllowedPaths = settings.RemoteApplicationSettings.AllowedPaths; settings.RemoteApplicationSettings.CopyProperties(remoteSettings.Privacy); remoteSettings.NamingStandards.LoadDefault(); remoteSettings.AppSettings.UserPrompt = false; remoteSettings.AppSettings.WebServer = (HttpContext.Request.IsHttps ? "https://" : "http://") + HttpContext.Request.Host + HttpContext.Request.PathBase.Value; remoteSettings.AppSettings.RemoteAgentId = Guid.NewGuid().ToString(); var user = await _operations.RepositoryManager.GetUserAsync(User, cancellationToken); var dbRemoteAgent = new DexihRemoteAgent() { RemoteAgentId = remoteSettings.AppSettings.RemoteAgentId, RestrictIp = false, Name = remoteSettings.AppSettings.Name, UserId = user.Id }; if (settings.EmbedUserName) { remoteSettings.AppSettings.UserToken = await _operations.RepositoryManager.GenerateRemoteUserTokenAsync(user, remoteSettings.AppSettings.RemoteAgentId, cancellationToken); var hashedToken = SecureHash.CreateHash(remoteSettings.AppSettings.UserToken); dbRemoteAgent.HashedToken = hashedToken; remoteSettings.AppSettings.User = user.UserName; } if (settings.RemoteApplicationSettings.AutoGenerateCertificate) { remoteSettings.Network.CertificateFilename = "dexih.pfx"; remoteSettings.Network.CertificatePassword = EncryptString.GenerateRandomKey(); } remoteSettings.Logging.LogLevel.Default = settings.LogLevel; remoteSettings.Logging.LogLevel.System = settings.LogLevel; remoteSettings.Logging.LogLevel.Microsoft = settings.LogLevel; await _operations.RepositoryManager.SaveRemoteAgent(user.Id, dbRemoteAgent, cancellationToken); var json = JsonSerializer.Serialize(remoteSettings, new JsonSerializerOptions() { WriteIndented = true }); var appSettingsStream = new MemoryStream(Encoding.ASCII.GetBytes(json)); return(appSettingsStream); }
public void HashFunctions(string testValue) { //Use a for loop to similate gen sequence. var hashString1 = SecureHash.CreateHash(testValue); var hashString2 = SecureHash.CreateHash(testValue); Assert.NotEqual(hashString1, hashString2); //two hashes in a row should not be equal as they are salted; var hashString3 = SecureHash.CreateHash(testValue + " "); Assert.True(SecureHash.ValidateHash(testValue, hashString1)); Assert.True(SecureHash.ValidateHash(testValue, hashString2)); Assert.False(SecureHash.ValidateHash(testValue, hashString3)); Assert.False(SecureHash.ValidateHash(testValue + "1", hashString1)); var uniqueHash1 = UniqueHash.CreateHash(testValue); var uniqueHash2 = UniqueHash.CreateHash(testValue); Assert.Equal(uniqueHash1, uniqueHash2); var uniqueHash3 = UniqueHash.CreateHash(testValue + " "); Assert.NotEqual(uniqueHash1, uniqueHash3); }
public async Task <JsonResult> Login([FromBody] RemoteSettings remoteSettings, CancellationToken cancellationToken) { try { if (ModelState.IsValid) { _logger.LogInformation(LoggingEvents.RemoteLogin, "Login - Remote Agent Login {user}, {servername}, remoteAgentId {remoteAgentId}, version {version}", User, remoteSettings.AppSettings.User, remoteSettings.AppSettings.Name, remoteSettings.Runtime.Version); var user = await _operations.RepositoryManager.GetUserFromLoginAsync(remoteSettings.AppSettings.User, cancellationToken); if (user == null) { _logger.LogWarning(LoggingEvents.RemoteLogin, "Login - Invalid remote login attempt using Email: " + User); return(Json(new { Success = false, Message = "Invalid login attempt." })); } if (remoteSettings.Runtime.Version.Substring(0, 7) != "1.0-rc.") { _logger.LogWarning(LoggingEvents.RemoteLogin, "Login - Invalid remote login attempt incorrect version: " + remoteSettings.Runtime.Version + " from login: "******"The remote agent version number is not compatible with the current integration hub web site. Please update." })); } var remoteIp = GetRequestIP(true); if (remoteIp == "::1") { remoteIp = "127.0.0.1"; } _logger.LogInformation(LoggingEvents.RemoteLogin, "Login - Remote Agent Login {user}, {servername}, remoteAgentId {remoteAgentId}, version {version}, ipAddress {ipAddress}", User, remoteSettings.AppSettings.User, remoteSettings.AppSettings.Name, remoteSettings.Runtime.Version, remoteIp); var dbRemoteAgent = await _operations.RepositoryManager.RemoteAgentLogin(remoteIp, remoteSettings.AppSettings.RemoteAgentId, cancellationToken); bool authenticated; if (!string.IsNullOrEmpty(remoteSettings.AppSettings.UserToken)) { if (dbRemoteAgent == null) { return(Json(new { Success = false, Message = $"The specified remoteAgentId does not exist, cannot be used from this ip address ({remoteIp}) or has been revoked." })); } authenticated = await _operations.RepositoryManager.VerifyUserTokenAsync(user, remoteSettings.AppSettings.RemoteAgentId, remoteSettings.AppSettings.UserToken, cancellationToken); if (!authenticated) { return(Json(new { Success = false, Message = "The authentication token provided is invalid." })); } // validate the login token. var storedUserToken = dbRemoteAgent.HashedToken; var passed = SecureHash.ValidateHash(remoteSettings.AppSettings.UserToken, storedUserToken); if (!passed) { return(Json(new { Success = false, Message = "The UserToken/RemoteID did not match the current value for this user. Please generate a new token." })); } } else if (!string.IsNullOrEmpty(remoteSettings.Runtime.Password)) { var result = await _signInManager.PasswordSignInAsync(user, remoteSettings.Runtime.Password, false, lockoutOnFailure : false); authenticated = result.Succeeded; remoteSettings.Runtime.GenerateUserToken = true; } else { return(Json(new { Success = false, Message = "There was no password or authentication token provided." })); } var newUserToken = ""; if (authenticated && remoteSettings.Runtime.GenerateUserToken) { if (string.IsNullOrEmpty(remoteSettings.Runtime.Password)) { return(Json(new { Success = false, Message = "To generate a new user token, a password must be specified." })); } if (dbRemoteAgent == null) { dbRemoteAgent = new DexihRemoteAgent() { UserId = user.Id, RestrictIp = true, IpAddresses = new [] { remoteIp }, Name = remoteSettings.AppSettings.Name, RemoteAgentId = remoteSettings.AppSettings.RemoteAgentId, }; } else { if (dbRemoteAgent.UserId != user.Id) { return(Json(new { Success = false, Message = "The remote agent can not be updated as it is registered with a different user id." })); } dbRemoteAgent.Name = remoteSettings.AppSettings.Name; if (dbRemoteAgent.RestrictIp && !(dbRemoteAgent.IpAddresses != null && dbRemoteAgent.IpAddresses.Contains(remoteIp))) { if (dbRemoteAgent.IpAddresses == null) { dbRemoteAgent.IpAddresses = new [] { remoteIp }; } else { dbRemoteAgent.IpAddresses = dbRemoteAgent.IpAddresses.Append(remoteIp).ToArray(); } } } newUserToken = await _operations.RepositoryManager.GenerateRemoteUserTokenAsync(user, remoteSettings.AppSettings.RemoteAgentId, cancellationToken); // hash the token so that it's not stored in plain text. var hashedToken = SecureHash.CreateHash(newUserToken); dbRemoteAgent.HashedToken = hashedToken; dbRemoteAgent = await _operations.RepositoryManager.SaveRemoteAgent(user.Id, dbRemoteAgent, cancellationToken); } if (authenticated) { if (dbRemoteAgent == null) { return(Json(new { Success = false, Message = $"There is no remote agent registered with the id {remoteSettings.AppSettings.RemoteAgentId} ." })); } if (dbRemoteAgent.UserId != user.Id) { return(Json(new { Success = false, Message = $"There user {user.Email} is not associated with this remote agent {remoteSettings.AppSettings.RemoteAgentId} ." })); } if (dbRemoteAgent.RestrictIp && !(dbRemoteAgent.IpAddresses != null && dbRemoteAgent.IpAddresses.Contains(remoteIp))) { return(Json(new { Success = false, Message = $"The remote agent has restrictions on the IP, and the IP address {remoteIp} is not allowed.." })); } if (dbRemoteAgent.Name != remoteSettings.AppSettings.Name) { dbRemoteAgent.Name = remoteSettings.AppSettings.Name; await _operations.RepositoryManager.SaveRemoteAgent(dbRemoteAgent.UserId, dbRemoteAgent, cancellationToken); } await _signInManager.RefreshSignInAsync(user); // create a hash of the userid, which is used as part of the dynamic url. var userHash = user.Id.CreateSHA1(); // create a security key, which is not sent the the browser client, and used to ensure the instance id hasn't been hijacked by another remote agent. var(instanceId, securityToken) = await _remoteServers.AuthorizeRemoteAgent(remoteSettings.AppSettings.Name, dbRemoteAgent.RemoteAgentKey, remoteSettings.AppSettings.EncryptionKey, remoteIp, user.Id, cancellationToken); return(Json(new { Success = true, instanceId, securityToken, UserToken = newUserToken, IpAddress = remoteIp, Message = "Login success", UserHash = userHash, _operations.Config.DefaultProxyUrl, dbRemoteAgent.RemoteAgentKey })); } else { return(Json(new { Success = false, Message = "Invalid password or revoked security token." })); } } // If we got this far, something failed, redisplay form return(Json(new { Success = false, Message = "Login failed." })); } catch (Exception ex) { return(Json(new ReturnValue(false, "An unexpected error occurred logging in: message: " + ex.Message, ex))); } }