Added ScriptingController logic.

This commit is contained in:
Jared Goodwin 2020-02-05 08:24:59 -08:00
parent a4fd12c597
commit de9fc42ea2
6 changed files with 112 additions and 36 deletions

View File

@ -99,35 +99,35 @@ namespace Remotely.Agent.Services
}
}
public async Task ExecuteCommandFromApi(string mode, string requestID, string command, string commandID, string senderConnectionID, HubConnection hubConnection)
public async Task ExecuteCommandFromApi(string mode, string requestID, string command, string commandID, string senderUserName, HubConnection hubConnection)
{
try
{
switch (mode.ToLower())
{
case "pscore":
var psCoreResult = PSCore.GetCurrent(senderConnectionID).WriteInput(command, commandID);
var psCoreResult = PSCore.GetCurrent(senderUserName).WriteInput(command, commandID);
await SendResultsViaAjax("PSCore", psCoreResult);
break;
case "winps":
if (OSUtils.IsWindows)
{
var result = WindowsPS.GetCurrent(senderConnectionID).WriteInput(command, commandID);
var result = WindowsPS.GetCurrent(senderUserName).WriteInput(command, commandID);
await SendResultsViaAjax("WinPS", result);
}
break;
case "cmd":
if (OSUtils.IsWindows)
{
var result = CMD.GetCurrent(senderConnectionID).WriteInput(command, commandID);
var result = CMD.GetCurrent(senderUserName).WriteInput(command, commandID);
await SendResultsViaAjax("CMD", result);
}
break;
case "bash":
if (OSUtils.IsLinux)
{
var result = Bash.GetCurrent(senderConnectionID).WriteInput(command, commandID);
var result = Bash.GetCurrent(senderUserName).WriteInput(command, commandID);
await SendResultsViaAjax("Bash", result);
}
break;
@ -140,7 +140,6 @@ namespace Remotely.Agent.Services
catch (Exception ex)
{
Logger.Write(ex);
await hubConnection.InvokeAsync("DisplayMessage", "There was an error executing the command. It has been logged on the client device.", "Error executing command.", senderConnectionID);
}
}
private async Task SendResultsViaAjax(string resultType, object result)

View File

@ -114,16 +114,16 @@ namespace Remotely.Agent.Services
await CommandExecutor.ExecuteCommand(mode, command, commandID, senderConnectionID, HubConnection);
}));
HubConnection.On("ExecuteCommandFromApi", (async (string mode, string requesterID, string command, string commandID, string senderConnectionID) =>
HubConnection.On("ExecuteCommandFromApi", (async (string mode, string requestID, string command, string commandID, string senderUserName) =>
{
if (!IsServerVerified)
{
Logger.Write($"Command attempted before server was verified. Mode: {mode}. Command: {command}. Sender: {senderConnectionID}");
Logger.Write($"Command attempted before server was verified. Mode: {mode}. Command: {command}. Sender: {senderUserName}");
Uninstaller.UninstallAgent();
return;
}
await CommandExecutor.ExecuteCommandFromApi(mode, requesterID, command, commandID, senderConnectionID, HubConnection);
await CommandExecutor.ExecuteCommandFromApi(mode, requestID, command, commandID, senderUserName, HubConnection);
}));
HubConnection.On("TransferFiles", async (string transferID, List<string> fileIDs, string requesterID) =>
{

View File

@ -1,36 +1,84 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
using Remotely.Server.Services;
using Remotely.Shared.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Remotely.Shared.Helpers;
using Microsoft.AspNetCore.Http;
using System.IO;
namespace Remotely.Server.API
{
[ApiController]
[Route("api/[controller]")]
public class ScriptingController : ControllerBase
{
//public Task ExecuteCommand(string mode, string command, string[] deviceIDs)
//{
// deviceIDs = DataService.FilterDeviceIDsByUserPermission(deviceIDs, RemotelyUser);
// var connections = GetActiveClientConnections(deviceIDs);
public ScriptingController(DataService dataService,
UserManager<RemotelyUser> userManager,
IHubContext<DeviceSocketHub> deviceHub)
{
DataService = dataService;
UserManager = userManager;
DeviceHub = deviceHub;
}
// var commandContext = new CommandContext()
// {
// CommandMode = mode,
// CommandText = command,
// SenderConnectionID = Context.ConnectionId,
// SenderUserID = Context.UserIdentifier,
// TargetDeviceIDs = connections.Select(x => x.Value.ID).ToArray(),
// OrganizationID = RemotelyUser.OrganizationID
// };
// DataService.AddOrUpdateCommandContext(commandContext);
// Clients.Caller.SendAsync("CommandContextCreated", commandContext);
// foreach (var connection in connections)
// {
// DeviceHub.Clients.Client(connection.Key).SendAsync("ExecuteCommand", mode, command, commandContext.ID, Context.ConnectionId);
// }
private DataService DataService { get; }
private IHubContext<DeviceSocketHub> DeviceHub { get; }
private UserManager<RemotelyUser> UserManager { get; }
// return Task.CompletedTask;
//}
[Authorize]
[HttpPost("[action]/{mode}/{deviceID}")]
public async Task<ActionResult<CommandContext>> ExecuteCommand(string mode, string deviceID)
{
var command = string.Empty;
using (var sr = new StreamReader(Request.Body))
{
command = await sr.ReadToEndAsync();
}
var username = Request.HttpContext.User.Identity.Name;
var user = await UserManager.FindByNameAsync(username);
if (!DataService.DoesUserHaveAccessToDevice(deviceID, user))
{
return Unauthorized();
}
KeyValuePair<string, Device> connection = DeviceSocketHub.ServiceConnections.FirstOrDefault(x =>
x.Value.OrganizationID == user.OrganizationID &&
x.Value.ID == deviceID);
if (string.IsNullOrWhiteSpace(connection.Key))
{
return NotFound();
}
var commandContext = new CommandContext()
{
CommandMode = "PSCore",
CommandText = command,
SenderConnectionID = string.Empty,
SenderUserID = user.Id,
TargetDeviceIDs = new string[] { deviceID },
OrganizationID = user.OrganizationID
};
DataService.AddOrUpdateCommandContext(commandContext);
var requestID = Guid.NewGuid().ToString();
await DeviceHub.Clients.Client(connection.Key).SendAsync("ExecuteCommandFromApi", mode, requestID, command, commandContext.ID, username);
var success = await TaskHelper.DelayUntil(() => DeviceSocketHub.ApiScriptResults.TryGetValue(requestID, out _), TimeSpan.FromSeconds(30));
if (!success)
{
return commandContext;
}
DeviceSocketHub.ApiScriptResults.TryGetValue(requestID, out var commandID);
DeviceSocketHub.ApiScriptResults.Remove(requestID);
DataService.DetachEntity(commandContext);
var result = DataService.GetCommandContext(commandID.ToString(), username);
return result;
}
}
}

View File

@ -227,6 +227,12 @@ namespace Remotely.Server.Services
RemotelyContext.SaveChanges();
}
public void DetachEntity(object entity)
{
RemotelyContext.Entry(entity).State = EntityState.Detached;
}
public void DeviceDisconnected(string deviceID)
{
var device = RemotelyContext.Devices.Find(deviceID);

View File

@ -9,13 +9,15 @@ using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Internal;
namespace Remotely.Server.Services
{
public class DeviceSocketHub : Hub
{
public DeviceSocketHub(DataService dataService,
IHubContext<BrowserSocketHub> browserHub,
public DeviceSocketHub(DataService dataService,
IHubContext<BrowserSocketHub> browserHub,
IHubContext<RCBrowserSocketHub> rcBrowserHub)
{
DataService = dataService;
@ -23,8 +25,8 @@ namespace Remotely.Server.Services
RCBrowserHub = rcBrowserHub;
}
public static ConcurrentDictionary<string, Device> ServiceConnections { get; } = new ConcurrentDictionary<string, Device>();
public static ConcurrentDictionary<string, string> ApiScriptResults { get; } = new ConcurrentDictionary<string, string>();
public static ConcurrentDictionary<string, Device> ServiceConnections { get; } = new ConcurrentDictionary<string, Device>();
public static IMemoryCache ApiScriptResults { get; } = new MemoryCache(new MemoryCacheOptions());
public IHubContext<RCBrowserSocketHub> RCBrowserHub { get; }
private IHubContext<BrowserSocketHub> BrowserHub { get; }
private DataService DataService { get; }
@ -68,7 +70,7 @@ namespace Remotely.Server.Services
public void CommandResultViaApi(string commandID, string requestID)
{
ApiScriptResults.AddOrUpdate(requestID, commandID, (k, v) => commandID);
ApiScriptResults.Set(requestID, commandID, DateTimeOffset.Now.AddHours(1));
}
public Task DeviceCameOnline(Device device)

View File

@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Threading.Tasks;
namespace Remotely.Shared.Helpers
{
public static class TaskHelper
{
public static async Task<bool> DelayUntil(Func<bool> condition, TimeSpan timeout, int pollingMs = 10)
{
var sw = Stopwatch.StartNew();
while (!condition() && sw.Elapsed < timeout)
{
await Task.Delay(pollingMs);
}
return condition();
}
}
}