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
}