mirror of
https://github.com/chylex/Minecraft-Phantom-Panel.git
synced 2024-11-23 10:42:51 +01:00
114 lines
4.3 KiB
C#
114 lines
4.3 KiB
C#
using NetMQ;
|
|
using Phantom.Common.Data;
|
|
using Phantom.Utils.Cryptography;
|
|
using Phantom.Utils.IO;
|
|
using Phantom.Utils.Logging;
|
|
using Serilog;
|
|
|
|
namespace Phantom.Controller;
|
|
|
|
abstract class ConnectionKeyFiles {
|
|
private const string CommonKeyFileExtension = ".key";
|
|
private const string SecretKeyFileExtension = ".secret";
|
|
|
|
private readonly ILogger logger;
|
|
private readonly string commonKeyFileName;
|
|
private readonly string secretKeyFileName;
|
|
|
|
private ConnectionKeyFiles(ILogger logger, string name) {
|
|
this.logger = logger;
|
|
this.commonKeyFileName = name + CommonKeyFileExtension;
|
|
this.secretKeyFileName = name + SecretKeyFileExtension;
|
|
}
|
|
|
|
public async Task<ConnectionKeyData?> CreateOrLoad(string folderPath) {
|
|
string commonKeyFilePath = Path.Combine(folderPath, commonKeyFileName);
|
|
string secretKeyFilePath = Path.Combine(folderPath, secretKeyFileName);
|
|
|
|
bool commonKeyFileExists = File.Exists(commonKeyFilePath);
|
|
bool secretKeyFileExists = File.Exists(secretKeyFilePath);
|
|
|
|
if (commonKeyFileExists && secretKeyFileExists) {
|
|
try {
|
|
return await ReadKeyFiles(commonKeyFilePath, secretKeyFilePath);
|
|
} catch (IOException e) {
|
|
logger.Fatal("Error reading connection key files.");
|
|
logger.Fatal(e.Message);
|
|
return null;
|
|
} catch (Exception) {
|
|
logger.Fatal("Connection key files contain invalid data.");
|
|
return null;
|
|
}
|
|
}
|
|
|
|
if (commonKeyFileExists || secretKeyFileExists) {
|
|
string existingKeyFilePath = commonKeyFileExists ? commonKeyFilePath : secretKeyFilePath;
|
|
string missingKeyFileName = commonKeyFileExists ? secretKeyFileName : commonKeyFileName;
|
|
logger.Fatal("The connection key file {ExistingKeyFilePath} exists but {MissingKeyFileName} does not. Please delete it to regenerate both files.", existingKeyFilePath, missingKeyFileName);
|
|
return null;
|
|
}
|
|
|
|
logger.Information("Creating connection key files in: {FolderPath}", folderPath);
|
|
|
|
try {
|
|
return await GenerateKeyFiles(commonKeyFilePath, secretKeyFilePath);
|
|
} catch (Exception e) {
|
|
logger.Fatal("Error creating connection key files.");
|
|
logger.Fatal(e.Message);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private async Task<ConnectionKeyData?> ReadKeyFiles(string commonKeyFilePath, string secretKeyFilePath) {
|
|
byte[] commonKeyBytes = await ReadKeyFile(commonKeyFilePath);
|
|
byte[] secretKeyBytes = await ReadKeyFile(secretKeyFilePath);
|
|
|
|
var (publicKey, authToken) = ConnectionCommonKey.FromBytes(commonKeyBytes);
|
|
var certificate = new NetMQCertificate(secretKeyBytes, publicKey);
|
|
|
|
logger.Information("Loaded connection key files.");
|
|
LogCommonKey(commonKeyFilePath, TokenGenerator.EncodeBytes(commonKeyBytes));
|
|
|
|
return new ConnectionKeyData(certificate, authToken);
|
|
}
|
|
|
|
private static Task<byte[]> ReadKeyFile(string filePath) {
|
|
Files.RequireMaximumFileSize(filePath, 64);
|
|
return File.ReadAllBytesAsync(filePath);
|
|
}
|
|
|
|
private async Task<ConnectionKeyData> GenerateKeyFiles(string commonKeyFilePath, string secretKeyFilePath) {
|
|
var certificate = new NetMQCertificate();
|
|
var authToken = AuthToken.Generate();
|
|
var commonKey = new ConnectionCommonKey(certificate.PublicKey, authToken).ToBytes();
|
|
|
|
await Files.WriteBytesAsync(secretKeyFilePath, certificate.SecretKey, FileMode.Create, Chmod.URW_GR);
|
|
await Files.WriteBytesAsync(commonKeyFilePath, commonKey, FileMode.Create, Chmod.URW_GR);
|
|
|
|
logger.Information("Created new connection key files.");
|
|
LogCommonKey(commonKeyFilePath, TokenGenerator.EncodeBytes(commonKey));
|
|
|
|
return new ConnectionKeyData(certificate, authToken);
|
|
}
|
|
|
|
protected abstract void LogCommonKey(string commonKeyFilePath, string commonKeyEncoded);
|
|
|
|
internal sealed class Agent : ConnectionKeyFiles {
|
|
public Agent() : base(PhantomLogger.Create<ConnectionKeyFiles, Agent>(), "agent") {}
|
|
|
|
protected override void LogCommonKey(string commonKeyFilePath, string commonKeyEncoded) {
|
|
logger.Information("Agent key file: {AgentKeyFilePath}", commonKeyFilePath);
|
|
logger.Information("Agent key: {AgentKey}", commonKeyEncoded);
|
|
}
|
|
}
|
|
|
|
internal sealed class Web : ConnectionKeyFiles {
|
|
public Web() : base(PhantomLogger.Create<ConnectionKeyFiles, Web>(), "web") {}
|
|
|
|
protected override void LogCommonKey(string commonKeyFilePath, string commonKeyEncoded) {
|
|
logger.Information("Web key file: {WebKeyFilePath}", commonKeyFilePath);
|
|
logger.Information("Web key: {WebKey}", commonKeyEncoded);
|
|
}
|
|
}
|
|
}
|