From 167a9fd76e28dc5732deb35ee63a39ff39ba88a4 Mon Sep 17 00:00:00 2001 From: Jared Date: Wed, 25 Nov 2020 15:13:54 -0800 Subject: [PATCH] Add device banning. Extract interfaces from DataService and ApplicationConfig. Create unit tests. --- Agent/Services/AgentSocket.cs | 2 +- README.md | 1 + Server/API/AgentUpdateController.cs | 8 +- Server/API/AlertsController.cs | 4 +- Server/API/ClientDownloadsController.cs | 4 +- Server/API/CommandsController.cs | 6 +- Server/API/DevicesController.cs | 4 +- Server/API/FileSharingController.cs | 4 +- Server/API/LoginController.cs | 8 +- .../API/OrganizationManagementController.cs | 12 +- Server/API/RemoteControlController.cs | 8 +- Server/API/ScriptingController.cs | 4 +- Server/API/ServerLogsController.cs | 4 +- .../Pages/Account/ForgotPassword.cshtml.cs | 6 +- .../Identity/Pages/Account/Login.cshtml.cs | 4 +- .../Pages/Account/Manage/ApiTokens.cshtml.cs | 4 +- .../Pages/Account/Manage/Index.cshtml.cs | 4 +- .../Pages/Account/Manage/Options.cshtml.cs | 6 +- .../Account/Manage/Organization.cshtml.cs | 6 +- .../Account/Manage/ServerConfig.cshtml.cs | 4 +- .../Pages/Account/Manage/ServerLogs.cshtml.cs | 4 +- .../Identity/Pages/Account/Register.cshtml | 4 +- .../Identity/Pages/Account/Register.cshtml.cs | 4 +- Server/Attributes/ApiAuthorizationFilter.cs | 4 +- .../RemoteControlFilterAttribute.cs | 4 +- Server/Hubs/AgentHub.cs | 67 ++++++++- Server/Hubs/BrowserHub.cs | 12 +- Server/Hubs/CasterHub.cs | 4 +- Server/Hubs/ViewerHub.cs | 8 +- Server/Pages/EditDevice.cshtml.cs | 4 +- Server/Pages/Error.cshtml.cs | 4 +- Server/Pages/GetSupport.cshtml.cs | 4 +- Server/Pages/Index.cshtml.cs | 8 +- Server/Pages/Invite.cshtml.cs | 6 +- Server/Pages/Shared/_Layout.cshtml | 4 +- Server/Pages/Shared/_LoginPartial.cshtml | 4 +- Server/Pages/_IndexNotLoggedIn.cshtml | 4 +- Server/Services/ApplicationConfig.cs | 38 ++++- Server/Services/CleanupService.cs | 2 +- Server/Services/DataService.cs | 85 ++++++++++- Server/Services/DbLogger.cs | 2 +- Server/Services/EmailSender.cs | 6 +- Server/Startup.cs | 6 +- Server/appsettings.json | 1 + .../wwwroot/src/Main/Commands/WebCommands.ts | 2 +- Tests/AgentHubTests.cs | 141 ++++++++++++++++++ Tests/DataServiceTests.cs | 4 +- Tests/IoCActivator.cs | 4 +- Tests/TestData.cs | 8 +- Tests/Tests.csproj | 1 + 50 files changed, 434 insertions(+), 118 deletions(-) create mode 100644 Tests/AgentHubTests.cs diff --git a/Agent/Services/AgentSocket.cs b/Agent/Services/AgentSocket.cs index 6906af488..4c1642603 100644 --- a/Agent/Services/AgentSocket.cs +++ b/Agent/Services/AgentSocket.cs @@ -267,7 +267,7 @@ private void RegisterMessageHandlers() await ScriptRunner.RunScript(mode, fileID, commandResultID, requesterID, HubConnection); }); - HubConnection.On("UninstallClient", () => + HubConnection.On("UninstallAgent", () => { Uninstaller.UninstallAgent(); }); diff --git a/README.md b/README.md index 5ba808097..eeef4db23 100644 --- a/README.md +++ b/README.md @@ -107,6 +107,7 @@ Whenever there's a reference to `appsettings.json` in this document, it refers t For more information on configuring ASP.NET Core, see https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-3.1. * AllowApiLogin: Whether to allow logging in via the API controller. API access tokens are recommended over this approach. +* BannedDevices: An array of device IDs, names, or IP addresses to ban. When they try to connect, an uninstall command will immediately be sent back. * DataRetentionInDays: How long event logs and remote command logs will be kept. * DBProvider: Determines which of the three connection strings (at the top) will be used. The appropriate DB provider for the database type is automatically loaded in code. * DefaultPrompt: The default prompt string you'll see for each line on the console. diff --git a/Server/API/AgentUpdateController.cs b/Server/API/AgentUpdateController.cs index 1d40d6852..902040549 100644 --- a/Server/API/AgentUpdateController.cs +++ b/Server/API/AgentUpdateController.cs @@ -21,16 +21,16 @@ public class AgentUpdateController : ControllerBase public AgentUpdateController(IWebHostEnvironment hostingEnv, - DataService dataService, - ApplicationConfig appConfig) + IDataService dataService, + IApplicationConfig appConfig) { HostEnv = hostingEnv; DataService = dataService; AppConfig = appConfig; } - private DataService DataService { get; } - public ApplicationConfig AppConfig { get; } + private IDataService DataService { get; } + public IApplicationConfig AppConfig { get; } private IWebHostEnvironment HostEnv { get; } diff --git a/Server/API/AlertsController.cs b/Server/API/AlertsController.cs index 3e8590c63..c5457661c 100644 --- a/Server/API/AlertsController.cs +++ b/Server/API/AlertsController.cs @@ -15,13 +15,13 @@ namespace Remotely.Server.API [ServiceFilter(typeof(ApiAuthorizationFilter))] public class AlertsController : ControllerBase { - public AlertsController(DataService dataService, IEmailSenderEx emailSender) + public AlertsController(IDataService dataService, IEmailSenderEx emailSender) { DataService = dataService; EmailSender = emailSender; } - private DataService DataService { get; } + private IDataService DataService { get; } private IEmailSenderEx EmailSender { get; } [HttpPost("Create")] diff --git a/Server/API/ClientDownloadsController.cs b/Server/API/ClientDownloadsController.cs index 9c3701d29..0bae13b67 100644 --- a/Server/API/ClientDownloadsController.cs +++ b/Server/API/ClientDownloadsController.cs @@ -17,13 +17,13 @@ namespace Remotely.Server.API public class ClientDownloadsController : ControllerBase { public ClientDownloadsController(IWebHostEnvironment hostEnv, - ApplicationConfig appConfig) + IApplicationConfig appConfig) { HostEnv = hostEnv; AppConfig = appConfig; } - private ApplicationConfig AppConfig { get; } + private IApplicationConfig AppConfig { get; } private SemaphoreSlim FileLock { get; } = new SemaphoreSlim(1); private IWebHostEnvironment HostEnv { get; set; } diff --git a/Server/API/CommandsController.cs b/Server/API/CommandsController.cs index 3cc5fd190..e42c8337c 100644 --- a/Server/API/CommandsController.cs +++ b/Server/API/CommandsController.cs @@ -17,12 +17,12 @@ namespace Remotely.Server.API [ApiController] public class CommandsController : ControllerBase { - public CommandsController(DataService dataService) + public CommandsController(IDataService dataService) { - this.DataService = dataService; + DataService = dataService; } - private DataService DataService { get; } + private IDataService DataService { get; } // GET: api/ [HttpGet("{fileExt}")] diff --git a/Server/API/DevicesController.cs b/Server/API/DevicesController.cs index b0367ed5a..4e7b9a1d3 100644 --- a/Server/API/DevicesController.cs +++ b/Server/API/DevicesController.cs @@ -15,11 +15,11 @@ namespace Remotely.Server.API public class DevicesController : ControllerBase { - public DevicesController(DataService dataService) + public DevicesController(IDataService dataService) { DataService = dataService; } - private DataService DataService { get; set; } + private IDataService DataService { get; set; } [HttpGet] diff --git a/Server/API/FileSharingController.cs b/Server/API/FileSharingController.cs index 3f5acca27..ab1acf2dc 100644 --- a/Server/API/FileSharingController.cs +++ b/Server/API/FileSharingController.cs @@ -12,11 +12,11 @@ namespace Remotely.Server.API [ApiController] public class FileSharingController : ControllerBase { - public FileSharingController(DataService dataService) + public FileSharingController(IDataService dataService) { DataService = dataService; } - public DataService DataService { get; set; } + public IDataService DataService { get; set; } [HttpGet("{id}")] public ActionResult Get(string id) diff --git a/Server/API/LoginController.cs b/Server/API/LoginController.cs index 0e2a6aec5..d0ee7ef1f 100644 --- a/Server/API/LoginController.cs +++ b/Server/API/LoginController.cs @@ -17,8 +17,8 @@ namespace Remotely.Server.API public class LoginController : ControllerBase { public LoginController(SignInManager signInManager, - DataService dataService, - ApplicationConfig appConfig, + IDataService dataService, + IApplicationConfig appConfig, IHubContext casterHubContext, IHubContext viewerHubContext) { @@ -30,8 +30,8 @@ public LoginController(SignInManager signInManager, } private SignInManager SignInManager { get; } - private DataService DataService { get; } - public ApplicationConfig AppConfig { get; } + private IDataService DataService { get; } + public IApplicationConfig AppConfig { get; } private IHubContext CasterHubContext { get; } private IHubContext ViewerHubContext { get; } diff --git a/Server/API/OrganizationManagementController.cs b/Server/API/OrganizationManagementController.cs index 5d1ea3c8c..1b5a8d8d5 100644 --- a/Server/API/OrganizationManagementController.cs +++ b/Server/API/OrganizationManagementController.cs @@ -17,14 +17,16 @@ namespace Remotely.Server.API [ApiController] public class OrganizationManagementController : ControllerBase { - public OrganizationManagementController(DataService dataService, UserManager userManager, IEmailSenderEx emailSender) + public OrganizationManagementController(IDataService dataService, + UserManager userManager, + IEmailSenderEx emailSender) { - this.DataService = dataService; - this.UserManager = userManager; - this.EmailSender = emailSender; + DataService = dataService; + UserManager = userManager; + EmailSender = emailSender; } - private DataService DataService { get; } + private IDataService DataService { get; } private IEmailSenderEx EmailSender { get; } private UserManager UserManager { get; } diff --git a/Server/API/RemoteControlController.cs b/Server/API/RemoteControlController.cs index f2b160940..db3f39bdc 100644 --- a/Server/API/RemoteControlController.cs +++ b/Server/API/RemoteControlController.cs @@ -19,9 +19,9 @@ namespace Remotely.Server.API [ApiController] public class RemoteControlController : ControllerBase { - public RemoteControlController(DataService dataService, + public RemoteControlController(IDataService dataService, IHubContext agentHub, - ApplicationConfig appConfig, + IApplicationConfig appConfig, SignInManager signInManager) { DataService = dataService; @@ -30,9 +30,9 @@ public RemoteControlController(DataService dataService, SignInManager = signInManager; } - public DataService DataService { get; } + public IDataService DataService { get; } public IHubContext AgentHubContext { get; } - public ApplicationConfig AppConfig { get; } + public IApplicationConfig AppConfig { get; } public SignInManager SignInManager { get; } [HttpGet("{deviceID}")] diff --git a/Server/API/ScriptingController.cs b/Server/API/ScriptingController.cs index 9b5bfaea3..c740b846c 100644 --- a/Server/API/ScriptingController.cs +++ b/Server/API/ScriptingController.cs @@ -18,7 +18,7 @@ namespace Remotely.Server.API [Route("api/[controller]")] public class ScriptingController : ControllerBase { - public ScriptingController(DataService dataService, + public ScriptingController(IDataService dataService, UserManager userManager, IHubContext agentHub) { @@ -27,7 +27,7 @@ public ScriptingController(DataService dataService, AgentHubContext = agentHub; } - private DataService DataService { get; } + private IDataService DataService { get; } private IHubContext AgentHubContext { get; } private UserManager UserManager { get; } diff --git a/Server/API/ServerLogsController.cs b/Server/API/ServerLogsController.cs index 970afea35..2a332a362 100644 --- a/Server/API/ServerLogsController.cs +++ b/Server/API/ServerLogsController.cs @@ -11,11 +11,11 @@ namespace Remotely.Server.API public class ServerLogsController : ControllerBase { - public ServerLogsController(DataService dataService) + public ServerLogsController(IDataService dataService) { DataService = dataService; } - public DataService DataService { get; set; } + public IDataService DataService { get; set; } [ServiceFilter(typeof(ApiAuthorizationFilter))] [HttpGet("Download")] diff --git a/Server/Areas/Identity/Pages/Account/ForgotPassword.cshtml.cs b/Server/Areas/Identity/Pages/Account/ForgotPassword.cshtml.cs index 7d0ad32f6..4f244950b 100644 --- a/Server/Areas/Identity/Pages/Account/ForgotPassword.cshtml.cs +++ b/Server/Areas/Identity/Pages/Account/ForgotPassword.cshtml.cs @@ -18,9 +18,11 @@ public class ForgotPasswordModel : PageModel private readonly UserManager _userManager; private readonly IEmailSenderEx _emailSender; - private DataService DataService { get; } + private IDataService DataService { get; } - public ForgotPasswordModel(UserManager userManager, IEmailSenderEx emailSender, DataService dataService) + public ForgotPasswordModel(UserManager userManager, + IEmailSenderEx emailSender, + IDataService dataService) { _userManager = userManager; _emailSender = emailSender; diff --git a/Server/Areas/Identity/Pages/Account/Login.cshtml.cs b/Server/Areas/Identity/Pages/Account/Login.cshtml.cs index 376d39109..cb22b4277 100644 --- a/Server/Areas/Identity/Pages/Account/Login.cshtml.cs +++ b/Server/Areas/Identity/Pages/Account/Login.cshtml.cs @@ -18,14 +18,14 @@ namespace Remotely.Server.Areas.Identity.Pages.Account [AllowAnonymous] public class LoginModel : PageModel { - private readonly DataService _dataService; + private readonly IDataService _dataService; private readonly SignInManager _signInManager; private readonly UserManager _userManager; private readonly ILogger _logger; public LoginModel(SignInManager signInManager, UserManager userManager, - DataService dataService, + IDataService dataService, ILogger logger) { _dataService = dataService; diff --git a/Server/Areas/Identity/Pages/Account/Manage/ApiTokens.cshtml.cs b/Server/Areas/Identity/Pages/Account/Manage/ApiTokens.cshtml.cs index 97249f2f9..222989b59 100644 --- a/Server/Areas/Identity/Pages/Account/Manage/ApiTokens.cshtml.cs +++ b/Server/Areas/Identity/Pages/Account/Manage/ApiTokens.cshtml.cs @@ -15,7 +15,7 @@ namespace Remotely.Server.Areas.Identity.Pages.Account.Manage [Authorize] public class ApiTokensModel : PageModel { - public ApiTokensModel(DataService dataService) + public ApiTokensModel(IDataService dataService) { DataService = dataService; } @@ -35,7 +35,7 @@ public ApiTokensModel(DataService dataService) [TempData] public string NewTokenSecret { get; set; } - private DataService DataService { get; } + private IDataService DataService { get; } public void OnGet() { diff --git a/Server/Areas/Identity/Pages/Account/Manage/Index.cshtml.cs b/Server/Areas/Identity/Pages/Account/Manage/Index.cshtml.cs index 3a390b908..3f53f3610 100644 --- a/Server/Areas/Identity/Pages/Account/Manage/Index.cshtml.cs +++ b/Server/Areas/Identity/Pages/Account/Manage/Index.cshtml.cs @@ -17,12 +17,12 @@ public partial class IndexModel : PageModel private readonly UserManager _userManager; private readonly SignInManager _signInManager; private readonly IEmailSenderEx _emailSender; - private readonly DataService _dataService; + private readonly IDataService _dataService; public IndexModel( UserManager userManager, SignInManager signInManager, - DataService dataService, + IDataService dataService, IEmailSenderEx emailSender) { _userManager = userManager; diff --git a/Server/Areas/Identity/Pages/Account/Manage/Options.cshtml.cs b/Server/Areas/Identity/Pages/Account/Manage/Options.cshtml.cs index 2319816b4..b21fe8c86 100644 --- a/Server/Areas/Identity/Pages/Account/Manage/Options.cshtml.cs +++ b/Server/Areas/Identity/Pages/Account/Manage/Options.cshtml.cs @@ -7,11 +7,11 @@ namespace Remotely.Server.Areas.Identity.Pages.Account.Manage { public class OptionsModel : PageModel { - public OptionsModel(DataService dataService) + public OptionsModel(IDataService dataService) { - this.DataService = dataService; + DataService = dataService; } - private DataService DataService { get; set; } + private IDataService DataService { get; set; } [TempData] public string Message { get; set; } diff --git a/Server/Areas/Identity/Pages/Account/Manage/Organization.cshtml.cs b/Server/Areas/Identity/Pages/Account/Manage/Organization.cshtml.cs index 240a1947a..41728d049 100644 --- a/Server/Areas/Identity/Pages/Account/Manage/Organization.cshtml.cs +++ b/Server/Areas/Identity/Pages/Account/Manage/Organization.cshtml.cs @@ -15,7 +15,9 @@ namespace Remotely.Server.Areas.Identity.Pages.Account.Manage { public class OrganizationModel : PageModel { - public OrganizationModel(DataService dataService, UserManager userManager, IEmailSenderEx emailSender) + public OrganizationModel(IDataService dataService, + UserManager userManager, + IEmailSenderEx emailSender) { DataService = dataService; UserManager = userManager; @@ -40,7 +42,7 @@ public OrganizationModel(DataService dataService, UserManager user [Display(Name = "Users")] public List Users { get; set; } - private DataService DataService { get; } + private IDataService DataService { get; } private IEmailSenderEx EmailSender { get; } diff --git a/Server/Areas/Identity/Pages/Account/Manage/ServerConfig.cshtml.cs b/Server/Areas/Identity/Pages/Account/Manage/ServerConfig.cshtml.cs index a39f4b262..fbc83e047 100644 --- a/Server/Areas/Identity/Pages/Account/Manage/ServerConfig.cshtml.cs +++ b/Server/Areas/Identity/Pages/Account/Manage/ServerConfig.cshtml.cs @@ -20,7 +20,7 @@ public class ServerConfigModel : PageModel public ServerConfigModel(IConfiguration configuration, IWebHostEnvironment hostEnv, UserManager userManager, - DataService dataService) + IDataService dataService) { Configuration = configuration; HostEnv = hostEnv; @@ -52,7 +52,7 @@ public enum DBProviders public string StatusMessage { get; set; } private IConfiguration Configuration { get; } - private DataService DataService { get; } + private IDataService DataService { get; } private IWebHostEnvironment HostEnv { get; } private UserManager UserManager { get; } diff --git a/Server/Areas/Identity/Pages/Account/Manage/ServerLogs.cshtml.cs b/Server/Areas/Identity/Pages/Account/Manage/ServerLogs.cshtml.cs index c48dc0bb2..f885efffd 100644 --- a/Server/Areas/Identity/Pages/Account/Manage/ServerLogs.cshtml.cs +++ b/Server/Areas/Identity/Pages/Account/Manage/ServerLogs.cshtml.cs @@ -10,7 +10,7 @@ namespace Remotely.Server.Areas.Identity.Pages.Account.Manage { public class ServerLogsModel : PageModel { - public ServerLogsModel(DataService dataService) + public ServerLogsModel(IDataService dataService) { DataService = dataService; } @@ -21,7 +21,7 @@ public ServerLogsModel(DataService dataService) public InputModel Input { get; set; } = new InputModel(); public bool IsAdmin { get; private set; } - private DataService DataService { get; } + private IDataService DataService { get; } public void OnGet() { diff --git a/Server/Areas/Identity/Pages/Account/Register.cshtml b/Server/Areas/Identity/Pages/Account/Register.cshtml index fb896f0ed..429088998 100644 --- a/Server/Areas/Identity/Pages/Account/Register.cshtml +++ b/Server/Areas/Identity/Pages/Account/Register.cshtml @@ -1,6 +1,6 @@ @page -@inject Remotely.Server.Services.ApplicationConfig AppConfig -@inject Remotely.Server.Services.DataService DataService +@inject Remotely.Server.Services.IApplicationConfig AppConfig +@inject Remotely.Server.Services.IDataService DataService @model RegisterModel @{ ViewData["Title"] = "Register"; diff --git a/Server/Areas/Identity/Pages/Account/Register.cshtml.cs b/Server/Areas/Identity/Pages/Account/Register.cshtml.cs index 85fb532f1..196017434 100644 --- a/Server/Areas/Identity/Pages/Account/Register.cshtml.cs +++ b/Server/Areas/Identity/Pages/Account/Register.cshtml.cs @@ -24,7 +24,7 @@ public class RegisterModel : PageModel private readonly ILogger _logger; private readonly IEmailSenderEx _emailSender; private readonly DataService _dataService; - private readonly ApplicationConfig _appConfig; + private readonly IApplicationConfig _appConfig; public RegisterModel( UserManager userManager, @@ -32,7 +32,7 @@ public RegisterModel( ILogger logger, IEmailSenderEx emailSender, DataService dataService, - ApplicationConfig appConfig) + IApplicationConfig appConfig) { _userManager = userManager; _signInManager = signInManager; diff --git a/Server/Attributes/ApiAuthorizationFilter.cs b/Server/Attributes/ApiAuthorizationFilter.cs index ebed44bcb..5b37674fe 100644 --- a/Server/Attributes/ApiAuthorizationFilter.cs +++ b/Server/Attributes/ApiAuthorizationFilter.cs @@ -6,12 +6,12 @@ namespace Remotely.Server.Attributes { public class ApiAuthorizationFilter : ActionFilterAttribute, IAuthorizationFilter { - public ApiAuthorizationFilter(DataService dataService) + public ApiAuthorizationFilter(IDataService dataService) { DataService = dataService; } - private DataService DataService { get; } + private IDataService DataService { get; } public void OnAuthorization(AuthorizationFilterContext context) { diff --git a/Server/Attributes/RemoteControlFilterAttribute.cs b/Server/Attributes/RemoteControlFilterAttribute.cs index 19129941b..130241d5c 100644 --- a/Server/Attributes/RemoteControlFilterAttribute.cs +++ b/Server/Attributes/RemoteControlFilterAttribute.cs @@ -9,13 +9,13 @@ namespace Remotely.Server.Attributes { public class RemoteControlFilterAttribute : ActionFilterAttribute, IAuthorizationFilter { - public RemoteControlFilterAttribute(ApplicationConfig appConfig) + public RemoteControlFilterAttribute(IApplicationConfig appConfig) { AppConfig = appConfig; } private static MemoryCache OtpCache { get; } = new MemoryCache(new MemoryCacheOptions()); - private ApplicationConfig AppConfig { get; } + private IApplicationConfig AppConfig { get; } public static string GetOtp(string deviceId) { diff --git a/Server/Hubs/AgentHub.cs b/Server/Hubs/AgentHub.cs index 177fdeed5..da25c1bae 100644 --- a/Server/Hubs/AgentHub.cs +++ b/Server/Hubs/AgentHub.cs @@ -1,5 +1,6 @@ using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.Caching.Memory; +using Microsoft.Extensions.Logging; using Remotely.Server.Services; using Remotely.Shared.Enums; using Remotely.Shared.Models; @@ -13,29 +14,32 @@ namespace Remotely.Server.Hubs { public class AgentHub : Hub { - public AgentHub(DataService dataService, + public AgentHub(IDataService dataService, + IApplicationConfig appConfig, IHubContext browserHubContext, IHubContext viewerHubContext) { DataService = dataService; BrowserHubContext = browserHubContext; ViewerHubContext = viewerHubContext; + AppConfig = appConfig; } - public static ConcurrentDictionary ServiceConnections { get; } = new ConcurrentDictionary(); public static IMemoryCache ApiScriptResults { get; } = new MemoryCache(new MemoryCacheOptions()); + public static ConcurrentDictionary ServiceConnections { get; } = new ConcurrentDictionary(); + public IApplicationConfig AppConfig { get; } public IHubContext ViewerHubContext { get; } private IHubContext BrowserHubContext { get; } - private DataService DataService { get; } + private IDataService DataService { get; } private Device Device { get { - return this.Context.Items["Device"] as Device; + return Context.Items["Device"] as Device; } set { - this.Context.Items["Device"] = value; + Context.Items["Device"] = value; } } @@ -81,6 +85,11 @@ public Task DeviceCameOnline(Device device) { try { + if (CheckForDeviceBan(device.ID, device.DeviceName)) + { + return Task.FromResult(false); + } + if (ServiceConnections.Any(x => x.Value.ID == device.ID)) { DataService.WriteEvent(new EventLog() @@ -99,6 +108,11 @@ public Task DeviceCameOnline(Device device) } device.PublicIP = ip?.ToString(); + if (CheckForDeviceBan(device.PublicIP)) + { + return Task.FromResult(false); + } + if (DataService.AddOrUpdateDevice(device, out var updatedDevice)) { Device = updatedDevice; @@ -125,7 +139,7 @@ public Task DeviceCameOnline(Device device) } catch (Exception ex) { - DataService.WriteEvent(ex, Device?.OrganizationID); + DataService.WriteEvent(ex, device?.OrganizationID); } Context.Abort(); @@ -134,12 +148,24 @@ public Task DeviceCameOnline(Device device) public Task DeviceHeartbeat(Device device) { + if (CheckForDeviceBan(device.ID, device.DeviceName)) + { + return Task.CompletedTask; + } + var ip = Context.GetHttpContext()?.Connection?.RemoteIpAddress; if (ip != null && ip.IsIPv4MappedToIPv6) { ip = ip.MapToIPv4(); } device.PublicIP = ip?.ToString(); + + if (CheckForDeviceBan(device.PublicIP)) + { + return Task.CompletedTask; + } + + DataService.AddOrUpdateDevice(device, out var updatedDevice); Device = updatedDevice; @@ -160,10 +186,12 @@ public Task DisplayMessage(string consoleMessage, string popupMessage, string re { return BrowserHubContext.Clients.Client(requesterID).SendAsync("DisplayMessage", consoleMessage, popupMessage); } + public Task DownloadFile(string fileID, string requesterID) { return BrowserHubContext.Clients.Client(requesterID).SendAsync("DownloadFile", fileID); } + public Task DownloadFileProgress(int progressPercent, string requesterID) { return BrowserHubContext.Clients.Client(requesterID).SendAsync("DownloadFileProgress", progressPercent); @@ -173,6 +201,7 @@ public override Task OnConnectedAsync() { return base.OnConnectedAsync(); } + public override async Task OnDisconnectedAsync(Exception exception) { if (Device != null) @@ -193,6 +222,7 @@ public override async Task OnDisconnectedAsync(Exception exception) await base.OnDisconnectedAsync(exception); } + public Task PSCoreResult(PSCoreCommandResult result) { result.DeviceID = Device.ID; @@ -201,6 +231,7 @@ public Task PSCoreResult(PSCoreCommandResult result) DataService.AddOrUpdateCommandResult(commandResult); return BrowserHubContext.Clients.Client(commandResult.SenderConnectionID).SendAsync("PSCoreResult", result); } + public async void PSCoreResultViaAjax(string commandID) { var commandResult = DataService.GetCommandResult(commandID); @@ -216,6 +247,7 @@ public Task SendServerVerificationToken() { return Clients.Caller.SendAsync("ServerVerificationToken", Device.ServerVerificationToken); } + public void SetServerVerificationToken(string verificationToken) { Device.ServerVerificationToken = verificationToken; @@ -226,10 +258,33 @@ public Task TransferCompleted(string transferID, string requesterID) { return BrowserHubContext.Clients.Client(requesterID).SendAsync("TransferCompleted", transferID); } + public Task WinPSResultViaAjax(string commandID) { var commandResult = DataService.GetCommandResult(commandID); return BrowserHubContext.Clients.Client(commandResult.SenderConnectionID).SendAsync("WinPSResultViaAjax", commandID, Device.ID); } + + private bool CheckForDeviceBan(params string[] deviceIdNameOrIPs) + { + foreach (var device in deviceIdNameOrIPs) + { + if (string.IsNullOrWhiteSpace(device)) + { + continue; + } + + if (AppConfig.BannedDevices.Any(x => !string.IsNullOrWhiteSpace(x) && + x.Equals(device, StringComparison.OrdinalIgnoreCase))) + { + DataService.WriteEvent($"Device ID/name/IP ({device}) is banned. Sending uninstall command.", null); + + _ = Clients.Caller.SendAsync("UninstallAgent"); + return true; + } + } + + return false; + } } } diff --git a/Server/Hubs/BrowserHub.cs b/Server/Hubs/BrowserHub.cs index e1f196b2f..325cae4b0 100644 --- a/Server/Hubs/BrowserHub.cs +++ b/Server/Hubs/BrowserHub.cs @@ -17,10 +17,10 @@ namespace Remotely.Server.Hubs public class BrowserHub : Hub { public BrowserHub( - DataService dataService, + IDataService dataService, SignInManager signInManager, IHubContext agentHubContext, - ApplicationConfig appConfig) + IApplicationConfig appConfig) { SignInManager = signInManager; DataService = dataService; @@ -29,8 +29,8 @@ public BrowserHub( } public static ConcurrentDictionary ConnectionIdToUserLookup { get; } = new ConcurrentDictionary(); - private ApplicationConfig AppConfig { get; } - private DataService DataService { get; } + private IApplicationConfig AppConfig { get; } + private IDataService DataService { get; } private IHubContext AgentHubContext { get; } private RemotelyUser RemotelyUser { @@ -182,13 +182,13 @@ public Task UploadFiles(List fileIDs, string transferID, string[] device } return Task.CompletedTask; } - public Task UninstallClients(string[] deviceIDs) + public Task UninstallAgents(string[] deviceIDs) { deviceIDs = DataService.FilterDeviceIDsByUserPermission(deviceIDs, RemotelyUser); var connections = GetActiveClientConnections(deviceIDs); foreach (var connection in connections) { - AgentHubContext.Clients.Client(connection.Key).SendAsync("UninstallClient"); + AgentHubContext.Clients.Client(connection.Key).SendAsync("UninstallAgent"); } DataService.RemoveDevices(deviceIDs); return Clients.Caller.SendAsync("RefreshDeviceList"); diff --git a/Server/Hubs/CasterHub.cs b/Server/Hubs/CasterHub.cs index caf3442f5..0cf80a8f9 100644 --- a/Server/Hubs/CasterHub.cs +++ b/Server/Hubs/CasterHub.cs @@ -14,7 +14,7 @@ public class CasterHub : Hub public CasterHub(IHubContext browserHub, IHubContext viewerHubContext, IHubContext agentHubContext, - ApplicationConfig appConfig) + IApplicationConfig appConfig) { BrowserHubContext = browserHub; ViewerHubContext = viewerHubContext; @@ -23,7 +23,7 @@ public CasterHub(IHubContext browserHub, } public static ConcurrentDictionary SessionInfoList { get; } = new ConcurrentDictionary(); - public ApplicationConfig AppConfig { get; } + public IApplicationConfig AppConfig { get; } private IHubContext AgentHubContext { get; } private IHubContext BrowserHubContext { get; } private RCSessionInfo SessionInfo diff --git a/Server/Hubs/ViewerHub.cs b/Server/Hubs/ViewerHub.cs index 3781b0a06..5c8488265 100644 --- a/Server/Hubs/ViewerHub.cs +++ b/Server/Hubs/ViewerHub.cs @@ -14,18 +14,18 @@ namespace Remotely.Server.Hubs [ServiceFilter(typeof(RemoteControlFilterAttribute))] public class ViewerHub : Hub { - public ViewerHub(DataService dataService, + public ViewerHub(IDataService dataService, IHubContext casterHubContext, IHubContext agentHub, - ApplicationConfig appConfig) + IApplicationConfig appConfig) { DataService = dataService; CasterHubContext = casterHubContext; AgentHubContext = agentHub; AppConfig = appConfig; } - private ApplicationConfig AppConfig { get; set; } - private DataService DataService { get; } + private IApplicationConfig AppConfig { get; set; } + private IDataService DataService { get; } private RemoteControlMode Mode { diff --git a/Server/Pages/EditDevice.cshtml.cs b/Server/Pages/EditDevice.cshtml.cs index 5c2cd22bf..2354f981f 100644 --- a/Server/Pages/EditDevice.cshtml.cs +++ b/Server/Pages/EditDevice.cshtml.cs @@ -13,7 +13,7 @@ namespace Remotely.Server.Pages [Authorize] public class EditDeviceModel : PageModel { - public EditDeviceModel(DataService dataService) + public EditDeviceModel(IDataService dataService) { DataService = dataService; } @@ -29,7 +29,7 @@ public EditDeviceModel(DataService dataService) public bool SaveSucessful { get; set; } - private DataService DataService { get; } + private IDataService DataService { get; } public IActionResult OnGet(string deviceID, bool success) { diff --git a/Server/Pages/Error.cshtml.cs b/Server/Pages/Error.cshtml.cs index 64166c683..16598071c 100644 --- a/Server/Pages/Error.cshtml.cs +++ b/Server/Pages/Error.cshtml.cs @@ -10,7 +10,7 @@ namespace Remotely.Server.Pages [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] public class ErrorModel : PageModel { - public ErrorModel(DataService dataService) + public ErrorModel(IDataService dataService) { this.DataService = dataService; } @@ -18,7 +18,7 @@ public ErrorModel(DataService dataService) public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); - private DataService DataService { get; } + private IDataService DataService { get; } public void OnGet() { diff --git a/Server/Pages/GetSupport.cshtml.cs b/Server/Pages/GetSupport.cshtml.cs index 41d2b3411..116a2e797 100644 --- a/Server/Pages/GetSupport.cshtml.cs +++ b/Server/Pages/GetSupport.cshtml.cs @@ -8,13 +8,13 @@ namespace Remotely.Server.Pages { public class GetSupportModel : PageModel { - public GetSupportModel(DataService dataService) + public GetSupportModel(IDataService dataService) { DataService = dataService; } - private DataService DataService { get; } + private IDataService DataService { get; } [TempData] public string StatusMessage { get; set; } diff --git a/Server/Pages/Index.cshtml.cs b/Server/Pages/Index.cshtml.cs index 9ddf0602d..522de886c 100644 --- a/Server/Pages/Index.cshtml.cs +++ b/Server/Pages/Index.cshtml.cs @@ -12,9 +12,9 @@ namespace Remotely.Server.Pages { public class IndexModel : PageModel { - public IndexModel(DataService dataService, + public IndexModel(IDataService dataService, SignInManager signInManager, - ApplicationConfig appConfig) + IApplicationConfig appConfig) { DataService = dataService; SignInManager = signInManager; @@ -24,8 +24,8 @@ public IndexModel(DataService dataService, public string DefaultPrompt { get; set; } public List DeviceGroups { get; set; } = new List(); public List Alerts { get; set; } = new List(); - private ApplicationConfig AppConfig { get; } - private DataService DataService { get; } + private IApplicationConfig AppConfig { get; } + private IDataService DataService { get; } private SignInManager SignInManager { get; } public async Task OnGet() { diff --git a/Server/Pages/Invite.cshtml.cs b/Server/Pages/Invite.cshtml.cs index b287fd4a5..a1fede2b1 100644 --- a/Server/Pages/Invite.cshtml.cs +++ b/Server/Pages/Invite.cshtml.cs @@ -8,11 +8,11 @@ namespace Remotely.Server.Pages [Authorize] public class InviteModel : PageModel { - public InviteModel(DataService dataService) + public InviteModel(IDataService dataService) { - this.DataService = dataService; + DataService = dataService; } - private DataService DataService { get; } + private IDataService DataService { get; } public bool Success { get; set; } public class InputModel diff --git a/Server/Pages/Shared/_Layout.cshtml b/Server/Pages/Shared/_Layout.cshtml index d47e17be0..89cf7cdf7 100644 --- a/Server/Pages/Shared/_Layout.cshtml +++ b/Server/Pages/Shared/_Layout.cshtml @@ -1,6 +1,6 @@ @using Remotely.Shared.Models -@inject Remotely.Server.Services.ApplicationConfig AppConfig -@inject DataService DataService +@inject IApplicationConfig AppConfig +@inject IDataService DataService @{ RemotelyUser user = User.Identity.IsAuthenticated ? diff --git a/Server/Pages/Shared/_LoginPartial.cshtml b/Server/Pages/Shared/_LoginPartial.cshtml index 2b6c4b544..5068e4312 100644 --- a/Server/Pages/Shared/_LoginPartial.cshtml +++ b/Server/Pages/Shared/_LoginPartial.cshtml @@ -1,9 +1,9 @@ -@inject Remotely.Server.Services.ApplicationConfig AppConfig @using Microsoft.AspNetCore.Identity @using Remotely.Shared.Models +@inject IApplicationConfig AppConfig @inject SignInManager SignInManager -@inject DataService DataService +@inject IDataService DataService