91dbe9ae11
- Nuovo progetto MachineGuard: libreria che verifica se la macchina corrente è autorizzata all'esecuzione tramite DPAPI (Data Protection API di Windows) - Nuovo progetto MachineGuardSetup: tool di configurazione da eseguire come Amministratore per registrare la macchina autorizzata - Data_Coupler.sln: aggiunti entrambi i nuovi progetti alla soluzione - Data_Coupler.csproj: aggiunto riferimento al progetto MachineGuard - Program.cs: integrazione MachineGuard all'avvio dell'applicazione; se la macchina non è autorizzata l'app viene arrestata immediatamente con log critico e scrittura nel Windows Event Log
199 lines
8.9 KiB
C#
199 lines
8.9 KiB
C#
using MachineGuard;
|
|
|
|
// ============================================================
|
|
// MachineGuardSetup — Strumento di configurazione machine-binding
|
|
// Utilizzo: eseguire come Amministratore su ogni server autorizzato
|
|
// Indipendente da Data Coupler — nessuna dipendenza dall'applicazione
|
|
// ============================================================
|
|
|
|
Console.OutputEncoding = System.Text.Encoding.UTF8;
|
|
|
|
PrintBanner();
|
|
|
|
if (!OperatingSystem.IsWindows())
|
|
{
|
|
PrintError("Questo strumento richiede Windows (DPAPI è un'API esclusiva di Windows).");
|
|
return 1;
|
|
}
|
|
|
|
if (!IsRunningAsAdministrator())
|
|
{
|
|
PrintWarning("Attenzione: l'applicazione non è in esecuzione come Amministratore.");
|
|
PrintWarning("La scrittura in C:\\ProgramData potrebbe fallire senza privilegi elevati.");
|
|
Console.WriteLine();
|
|
}
|
|
|
|
return RunSetupWindows();
|
|
|
|
// ─────────────────────────────────────────────────────────────
|
|
// Entry point per Windows (isolato per soddisfare l'analizzatore)
|
|
// ─────────────────────────────────────────────────────────────
|
|
[System.Runtime.Versioning.SupportedOSPlatform("windows")]
|
|
static int RunSetupWindows()
|
|
{
|
|
var defaultPath = MachineGuardSetupHelper.GetDefaultSecretFilePath();
|
|
|
|
Console.WriteLine("╔══════════════════════════════════════════════════════════╗");
|
|
Console.WriteLine("║ CONFIGURAZIONE MACHINE-BINDING ║");
|
|
Console.WriteLine("╚══════════════════════════════════════════════════════════╝");
|
|
Console.WriteLine();
|
|
Console.WriteLine($" Percorso predefinito secret: {defaultPath}");
|
|
Console.WriteLine();
|
|
|
|
// Chiedi conferma o percorso personalizzato
|
|
Console.Write(" Usare il percorso predefinito? [S/n]: ");
|
|
var input = Console.ReadLine()?.Trim().ToUpperInvariant();
|
|
Console.WriteLine();
|
|
|
|
string targetPath;
|
|
if (string.IsNullOrEmpty(input) || input == "S" || input == "Y")
|
|
{
|
|
targetPath = defaultPath;
|
|
}
|
|
else
|
|
{
|
|
Console.Write(" Inserire il percorso completo del file secret: ");
|
|
var customPath = Console.ReadLine()?.Trim();
|
|
if (string.IsNullOrWhiteSpace(customPath))
|
|
{
|
|
PrintError("Percorso non valido. Operazione annullata.");
|
|
return 1;
|
|
}
|
|
targetPath = customPath;
|
|
}
|
|
|
|
// Verifica se esiste già un secret
|
|
if (File.Exists(targetPath))
|
|
{
|
|
Console.WriteLine($" ⚠ Il file secret esiste già: {targetPath}");
|
|
Console.Write(" Sovrascrivere? [s/N]: ");
|
|
var overwrite = Console.ReadLine()?.Trim().ToUpperInvariant();
|
|
Console.WriteLine();
|
|
|
|
if (overwrite != "S" && overwrite != "Y")
|
|
{
|
|
Console.ForegroundColor = ConsoleColor.Yellow;
|
|
Console.WriteLine(" Operazione annullata dall'utente.");
|
|
Console.ResetColor();
|
|
return 0;
|
|
}
|
|
|
|
// Verifica se il secret attuale è già valido
|
|
Console.WriteLine(" Verifica del secret esistente...");
|
|
if (MachineGuardSetupHelper.VerifySecret(targetPath))
|
|
{
|
|
Console.ForegroundColor = ConsoleColor.Green;
|
|
Console.WriteLine(" ✓ Il secret esistente è GIÀ valido per questa macchina.");
|
|
Console.ResetColor();
|
|
Console.Write(" Continuare comunque e riscrivere? [s/N]: ");
|
|
var rewrite = Console.ReadLine()?.Trim().ToUpperInvariant();
|
|
Console.WriteLine();
|
|
if (rewrite != "S" && rewrite != "Y")
|
|
{
|
|
Console.WriteLine(" Operazione annullata. Il secret esistente rimane invariato.");
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Scrittura del secret
|
|
Console.WriteLine($" Scrittura del secret cifrato con DPAPI (LocalMachine) in:");
|
|
Console.WriteLine($" {targetPath}");
|
|
Console.WriteLine();
|
|
|
|
try
|
|
{
|
|
MachineGuardSetupHelper.WriteSecret(targetPath);
|
|
}
|
|
catch (UnauthorizedAccessException ex)
|
|
{
|
|
PrintError($"Accesso negato: {ex.Message}");
|
|
PrintError("Riprovare eseguendo il programma come Amministratore (tasto destro → Esegui come amministratore).");
|
|
return 1;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
PrintError($"Errore durante la scrittura del secret: {ex.Message}");
|
|
return 1;
|
|
}
|
|
|
|
// Verifica post-scrittura
|
|
Console.WriteLine(" Verifica del secret appena scritto...");
|
|
if (MachineGuardSetupHelper.VerifySecret(targetPath))
|
|
{
|
|
Console.ForegroundColor = ConsoleColor.Green;
|
|
Console.WriteLine(" ✓ Secret scritto e verificato con successo!");
|
|
Console.ResetColor();
|
|
Console.WriteLine();
|
|
Console.WriteLine(" Questa macchina è ora autorizzata a eseguire Data Coupler.");
|
|
Console.WriteLine();
|
|
PrintFileInfo(targetPath);
|
|
}
|
|
else
|
|
{
|
|
PrintError("Verifica post-scrittura fallita. Il file potrebbe essere corrotto.");
|
|
return 1;
|
|
}
|
|
|
|
Console.WriteLine();
|
|
Console.WriteLine(" Premere un tasto per uscire...");
|
|
if (!Console.IsInputRedirected)
|
|
Console.ReadKey(intercept: true);
|
|
return 0;
|
|
}
|
|
|
|
// ─────────────────────────────────────────────────────────────
|
|
// Funzioni di utilità
|
|
// ─────────────────────────────────────────────────────────────
|
|
|
|
static void PrintBanner()
|
|
{
|
|
Console.ForegroundColor = ConsoleColor.Cyan;
|
|
Console.WriteLine();
|
|
Console.WriteLine(" ██████╗ █████╗ ████████╗ █████╗ ██████╗ ██████╗ ██╗ ██╗██████╗ ██╗ ███████╗██████╗ ");
|
|
Console.WriteLine(" ██╔══██╗██╔══██╗╚══██╔══╝██╔══██╗ ██╔════╝██╔═══██╗██║ ██║██╔══██╗██║ ██╔════╝██╔══██╗");
|
|
Console.WriteLine(" ██║ ██║███████║ ██║ ███████║ ██║ ██║ ██║██║ ██║██████╔╝██║ █████╗ ██████╔╝");
|
|
Console.WriteLine(" ██║ ██║██╔══██║ ██║ ██╔══██║ ██║ ██║ ██║██║ ██║██╔═══╝ ██║ ██╔══╝ ██╔══██╗");
|
|
Console.WriteLine(" ██████╔╝██║ ██║ ██║ ██║ ██║ ╚██████╗╚██████╔╝╚██████╔╝██║ ███████╗███████╗██║ ██║");
|
|
Console.WriteLine(" ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝╚══════╝╚═╝ ╚═╝");
|
|
Console.ResetColor();
|
|
Console.WriteLine();
|
|
Console.ForegroundColor = ConsoleColor.White;
|
|
Console.WriteLine(" MachineGuardSetup — Configurazione protezione machine-binding per Data Coupler");
|
|
Console.WriteLine(" Versione: 1.0 | Tecnologia: DPAPI (DataProtectionScope.LocalMachine)");
|
|
Console.ResetColor();
|
|
Console.WriteLine(new string('─', 70));
|
|
Console.WriteLine();
|
|
}
|
|
|
|
static void PrintError(string message)
|
|
{
|
|
Console.ForegroundColor = ConsoleColor.Red;
|
|
Console.WriteLine($" ✗ ERRORE: {message}");
|
|
Console.ResetColor();
|
|
}
|
|
|
|
static void PrintWarning(string message)
|
|
{
|
|
Console.ForegroundColor = ConsoleColor.Yellow;
|
|
Console.WriteLine($" ⚠ {message}");
|
|
Console.ResetColor();
|
|
}
|
|
|
|
static void PrintFileInfo(string path)
|
|
{
|
|
var fi = new FileInfo(path);
|
|
Console.WriteLine(" Dettagli file:");
|
|
Console.WriteLine($" Percorso : {fi.FullName}");
|
|
Console.WriteLine($" Dimensione: {fi.Length} byte (cifrati con DPAPI)");
|
|
Console.WriteLine($" Creato : {fi.CreationTime:dd/MM/yyyy HH:mm:ss}");
|
|
}
|
|
|
|
static bool IsRunningAsAdministrator()
|
|
{
|
|
if (!OperatingSystem.IsWindows()) return false;
|
|
using var identity = System.Security.Principal.WindowsIdentity.GetCurrent();
|
|
var principal = new System.Security.Principal.WindowsPrincipal(identity);
|
|
return principal.IsInRole(System.Security.Principal.WindowsBuiltInRole.Administrator);
|
|
}
|