Skip to content

Instantly share code, notes, and snippets.

@rjaeckel
Last active January 12, 2023 13:14
Show Gist options
  • Save rjaeckel/2a1bf6f159e403216539af02322f2997 to your computer and use it in GitHub Desktop.
Save rjaeckel/2a1bf6f159e403216539af02322f2997 to your computer and use it in GitHub Desktop.
ESET Protect Server API c#
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text.Json;
using System.Text.Json.Nodes;
namespace ERA_Api {
public class Program {
public static void Main() {
try {
var api = new ApiInstance();
api.Login("Administrator", "Secret", Locale: "de-DE");
api.Dispose();
} catch (Exception e) {
Console.WriteLine("Error: " + e.Message);
}
}
}
public class ApiInstance : IDisposable {
private ServerApi Api;
private bool Connected = false;
public ApiInstance(string Host = "127.0.0.1", int Port = 2223) {
Api = new ServerApi();
var response = Deserialize(Api.Invoke(Start))["Era.ServerApi.SimpleResponse"];
if (!response["result"].GetValue<bool>())
throw new Exception("Api failed: " + response["error"].GetValue<string>());
Connect(Host, Port);
}
private void Connect(string Host, int Port) {
var socket = new { host=Host, port=Port};
var response = Deserialize(Api.Invoke(RequestData("CreateConnection", Serialize(socket))));
if (null == response["Era.ServerApi.VerifyUserRequest"])
throw new Exception("Connection failed: " + response["Era.ServerApi.SimpleResponse"]["error"].GetValue<string>());
Api.Invoke("{\"Era.ServerApi.VerifyUserResponse\":{\"VerifyResult\":true}}");
Connected = true;
}
public void Login(string Username, string Password, bool UseDomain = false, string Locale = "en-US") {
var cred = new {
username=Username,
password=Password,
isDomainUser=UseDomain,
locale=Locale
};
var result = Request("SessionManagement.RpcAuthLogin", Serialize(cred));
Console.WriteLine("Logged in: " + result);
}
public string Request(string Type, string Data) {
string Namespace = "Era.Common.NetworkMessage.ConsoleApi";
string ExpectedReturnType = Namespace + "." + Type + "Response";
var result = Deserialize(Api.Invoke(RequestData(Type, Data, Namespace)));
if (null != result[ExpectedReturnType])
return result[ExpectedReturnType].ToJsonString();
if (null != result["Era.ServerApi.ReportCSVResponse"])
return result["Era.ServerApi.ReportCSVResponse"].ToJsonString();
throw new Exception(result.ToJsonString());
}
private static string RequestData(string Type, string Data, string Namespace = "Era.ServerApi") {
return "{\"" + Namespace + "." + Type + "Request\":" + Data + "}";
}
~ApiInstance() {
Dispose();
}
public void Dispose() {
if (Connected) {
Api.Invoke(CloseConnection);
Connected = false;
}
try { Api.Invoke(Stop); } catch { }
Api.Dispose();
}
private static string Start { get { return RequestData("Start"); } }
private static string Stop { get { return RequestData("Stop"); } }
private static string CloseConnection { get { return RequestData("CloseConnection"); } }
private static string RequestData(string Type) {
return RequestData(Type, "{}");
}
private static JsonNode Deserialize(string Data) {
return JsonSerializer.Deserialize<JsonNode>(Data);
}
private static string Serialize( Object Obj) {
return JsonSerializer.Serialize(Obj);
}
}
internal class ServerApi : IDisposable {
private int init_result = -1;
protected ServerApi(string ApiPath) {
// era_init_lib_ex function requires a trailing slash for the path
if (!ApiPath.EndsWith(Path.DirectorySeparatorChar))
ApiPath += Path.DirectorySeparatorChar;
// cd into api dir, init and cd back
var initial_dir = Directory.GetCurrentDirectory();
Directory.SetCurrentDirectory(ApiPath);
init_result = era_init_lib_ex(ApiPath);
Directory.SetCurrentDirectory(initial_dir);
// check error
if (0 != init_result)
throw new Exception("Init Failed. RC=" + init_result);
}
public ServerApi() : this(ServerPath) { }
public string Invoke(string Request) {
if (0 != init_result)
throw new Exception("Not initialized");
IntPtr Response;
//Console.WriteLine("> " + Request);
int RC = era_process_request(Request, out Response);
if (0 == RC && IntPtr.Zero != Response) {
string Result = Marshal.PtrToStringAnsi(Response);
//Console.WriteLine("< " + Result);
era_free(Response);
return Result;
}
throw new Exception ("Error processing request: " + RC);
}
~ServerApi() {
Dispose();
}
private static string ServerPath { get { return RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "C:\\Program Files\\ESET\\RemoteAdministrator\\Server" : "/opt/eset/RemoteAdministrator/Server"; } }
[DllImport("ServerApi", CallingConvention = CallingConvention.Cdecl)]
private static extern int era_init_lib_ex(string dependencyLibraryPath);
[DllImport("ServerApi", CallingConvention = CallingConvention.Cdecl)]
private static extern void era_free(IntPtr Response);
[DllImport("ServerApi", CallingConvention = CallingConvention.Cdecl)]
private static extern void era_deinit_lib();
[DllImport("ServerApi", CallingConvention = CallingConvention.Cdecl)]
private static extern int era_process_request(string Request, out IntPtr Response);
public void Dispose() {
if (0 == init_result) {
era_deinit_lib();
init_result = -1;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment