using InABox.Core; using System; using System.Collections.Generic; using System.Linq; using System.Security.Cryptography.X509Certificates; using System.Text; using System.Timers; using Timer = System.Timers.Timer; namespace PRSServices; public enum CertificateStatus { Valid, Expired, NotFound, Error } public class CertificateManager { public string? CertificateFile { get; set; } private X509Certificate2? Certificate; private Timer? CertificateRefreshTimer; private Timer? CertificateHaltTimer; public delegate void UpdateCertificateEvent(X509Certificate2 certificate); public event UpdateCertificateEvent? UpdateCertificate; public delegate void CertificateExpiringEvent(DateTime expiry); public event CertificateExpiringEvent? CertificateExpiring; public delegate void CertificateExpiredEvent(); public event CertificateExpiredEvent? CertificateExpired; public CertificateManager(string? filename = null) { CertificateFile = filename; } public void SetFile(string certificateFile) { CertificateFile = certificateFile; } public void SetCertificate(X509Certificate2 certificate) { Certificate = certificate; } public void Clear() { Certificate = null; } public void Stop() { CertificateRefreshTimer?.Stop(); CertificateHaltTimer?.Dispose(); CertificateHaltTimer = null; } public X509Certificate2? GetCertificate() { GetCertificate(out var certificate); return certificate; } public CertificateStatus CheckCertificate() { return GetCertificate(out var certificate); } public CertificateStatus GetCertificate(out X509Certificate2? certificate) { if(Certificate != null) { certificate = Certificate; return CertificateStatus.Valid; } certificate = null; CertificateStatus status; if (File.Exists(CertificateFile)) { try { certificate = new X509Certificate2(CertificateFile); if (certificate.NotAfter > DateTime.Now) { Certificate = certificate; status = CertificateStatus.Valid; } else { status = CertificateStatus.Expired; certificate = null; } } catch (Exception) { status = CertificateStatus.Error; } } else { status = CertificateStatus.NotFound; } if(certificate is not null) { if (CertificateRefreshTimer == null) { CertificateRefreshTimer = new Timer(1000 * 60 * 60 * 24); CertificateRefreshTimer.Elapsed += CertificateTimer_Elapsed; CertificateRefreshTimer.AutoReset = true; } CertificateRefreshTimer.Start(); } return status; } #region Certificate Management private void CertificateTimer_Elapsed(object? sender, ElapsedEventArgs e) { if (Certificate is not null) { X509Certificate2? cert = null; if (File.Exists(CertificateFile)) { cert = new X509Certificate2(CertificateFile); } if (cert != null && cert.NotAfter > Certificate.NotAfter && cert.NotAfter > DateTime.Now) { Certificate = cert; UpdateCertificate?.Invoke(cert); } var expiry = Certificate.NotAfter; var untilExpiry = expiry - DateTime.Now; if (untilExpiry.TotalDays <= 7) { CertificateExpiring?.Invoke(expiry); if (untilExpiry.TotalDays <= 1) { CertificateRefreshTimer?.Stop(); CertificateHaltTimer = new Timer(untilExpiry.TotalMilliseconds); CertificateHaltTimer.Elapsed += HTTPS_Halt_Elapsed; CertificateHaltTimer.AutoReset = false; CertificateHaltTimer.Start(); } } } } /// /// Restarts listener in HTTP mode /// /// /// private void HTTPS_Halt_Elapsed(object? sender, ElapsedEventArgs e) { CertificateHaltTimer?.Dispose(); CertificateHaltTimer = null; CertificateExpired?.Invoke(); } #endregion }