Implementation of a basic PEM encoded to OpenSim compatible PKCS12 certificates converter.

As you know most CAs return PEM encoded certificates and require a conversion using OpenSSL to make them compatible with OpenSim.
This implementation does the automatic conversion from .pem to .p12 and .pfx at OpenSim startup which updates the certificate in case of automatic certificates renewal...
Note: still under testing using certbot and Let's Encrypt certs...

Thank you and good continuaion
Web Rain :)
This commit is contained in:
Adil El Farissi 2024-09-16 01:52:19 +00:00
parent 70f3b02f65
commit 52c77b2f12
4 changed files with 110 additions and 1 deletions

View file

@ -1550,6 +1550,53 @@ namespace OpenSim.Framework
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ConvertPemToPKCS12(string certFileName, string fullChainPath, string privateKeyPath)
{
ConvertPemToPKCS12Certificate(certFileName, fullChainPath, privateKeyPath, null);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ConvertPemToPKCS12(string certFileName, string fullChainPath, string privateKeyPath, string outputPassword)
{
ConvertPemToPKCS12Certificate(certFileName, fullChainPath, privateKeyPath, outputPassword);
}
/// <summary>
/// Convert or renew .pem certificate to PKCS12 .pfx and .p12 usable by OpenSim.
/// the parameters are set in the startup section of OpenSim.ini
/// </summary>
/// <param name="certFileName">The output certificate file name.</param>
/// <param name="certPath">The path of fullchain.pem. If your CA don't provide
/// the fullchain file, you can set the cert.pem instead.</param>
/// <param name="keyPath">The path of the private key (privkey.pem).</param>
/// <param name="certPassword">The output certificates password.</param>
private static void ConvertPemToPKCS12Certificate(string certFileName, string certPath, string keyPath, string outputPassword)
{
if(string.IsNullOrEmpty(certPath) || string.IsNullOrEmpty(keyPath)){
m_log.ErrorFormat("[UTIL]: Missing or invalid fullchain.pem / privkey.pem path!.");
return;
}
// Create the SSL folder and sub folders if not exists.
if (!Directory.Exists("SSL\\ssl\\"))
Directory.CreateDirectory("SSL\\ssl\\");
// Convert .pem (like Let's Encrypt files) to X509Certificate2 certificate.
X509Certificate2 certificate = X509Certificate2.CreateFromPemFile(certPath, keyPath);
// Export and store the .pfx and .p12 certificates in SSL\ssl\.
byte[] pfxCertBytes = string.IsNullOrEmpty(outputPassword)
? certificate.Export(X509ContentType.Pfx)
: certificate.Export(X509ContentType.Pfx, outputPassword);
File.WriteAllBytes($"SSL\\ssl\\{certFileName}.pfx", pfxCertBytes);
byte[] p12CertBytes = string.IsNullOrEmpty(outputPassword)
? certificate.Export(X509ContentType.Pkcs12)
: certificate.Export(X509ContentType.Pkcs12, outputPassword);
File.WriteAllBytes($"SSL\\ssl\\{certFileName}.p12", p12CertBytes);
}
public static int fast_distance2d(int x, int y)
{
x = Math.Abs(x);

View file

@ -367,6 +367,16 @@ namespace OpenSim
);
}
}
if(startupConfig.GetBoolean("EnableCertConverter", false))
{
Util.ConvertPemToPKCS12(
string.IsNullOrEmpty(startupConfig.GetString("outputCertName")) ? "letsencrypt" : startupConfig.GetString("outputCertName"),
string.IsNullOrEmpty(startupConfig.GetString("PemCertPublicKey")) ? string.Empty : startupConfig.GetString("PemCertPublicKey"),
string.IsNullOrEmpty(startupConfig.GetString("PemCertPrivateKey")) ? string.Empty : startupConfig.GetString("PemCertPrivateKey"),
string.IsNullOrEmpty(startupConfig.GetString("outputCertPassword")) ? string.Empty : startupConfig.GetString("outputCertPassword")
);
}
if(m_networkServersInfo.HttpUsesSSL)
{

View file

@ -309,12 +309,37 @@
;; default is false
; TelehubAllowLandmark = false
;; Let's Encrypt and others ".pem" certificates converter settings.
;; Enabling this feature will automatically convert the CA .pem certificates to
;; OpenSim compatible PKCS12 .p12 and .pfx certificates on every server startup.
;; The resulting certificates are stored in the bin\SSL\ssl folder.
;# {EnableCertConverter} {} {Enable pem to pkcs12 certificates converter} {true false} false
EnableCertConverter = false
;; Set the absolute path of the "fullchain.pem". If your CA don't provide this file,
;; you can use the "cert.pem" instead.
;# {PemCertPublicKey} {} {Set the path of the public key .pem} {} ""
PemCertPublicKey = ""
;; Set the absolute path of the pem private key "privkey.pem".
;# {PemCertPrivateKey} {} {Set the path of the private key .pem} {} ""
PemCertPrivateKey = ""
;; Set the name of the resulting .p12 and .pfx.
;# {outputCertName} {} {Set the name of the resulting .p12 and .pfx} {} "letsencrypt"
outputCertName = "letsencrypt"
;; Set the .p12 and .pfx password.
;# {outputCertPassword} {} {Set the .p12 and .pfx password} {} ""
outputCertPassword = ""
;; SSL selfsigned certificate settings.
;; Enable selfsigned certificate creation for local and external use. When set to true, will create a folder SSL\ and 2 sub folders SSL\ssl\ and SSL\src\.
;; Next creates and store an RSA private key in SSL\src\ and the derived selfsigned certificate in SSL\ssl\ folder.
;;Is also possible to renew the certificate on every server restart if CertRenewOnStartup is set to true.
;# {EnbleSelfsignedCertSupport} {} {Enable selfsigned certificate creation and renew} {true false} false
;# {EnableSelfsignedCertSupport} {} {Enable selfsigned certificate creation and renew} {true false} false
EnableSelfsignedCertSupport = false
;; Renew the selfsigned certificate on every server startup ?

View file

@ -399,6 +399,33 @@
; routing and land at the landmark coordinates when set to true
; default is false
; TelehubAllowLandmark = false
; #
; # Let's Encrypt and others ".pem" certificates converter settings.
; #
;; Enabling this feature will automatically convert the CA .pem certificates to
;; OpenSim compatible PKCS12 .p12 and .pfx certificates on every server startup.
;; The resulting certificates are stored in the bin\SSL\ssl folder.
;# {EnableCertConverter} {} {Enable pem to pkcs12 certificates converter} {true false} false
EnableCertConverter = false
;; Set the absolute path of the "fullchain.pem". If your CA don't provide this file,
;; you can use the "cert.pem" instead.
;# {PemCertPublicKey} {} {Set the path of the public key .pem} {} ""
PemCertPublicKey = ""
;; Set the absolute path of the pem private key "privkey.pem".
;# {PemCertPrivateKey} {} {Set the path of the private key .pem} {} ""
PemCertPrivateKey = ""
;; Set the name of the resulting .p12 and .pfx.
;# {outputCertName} {} {Set the name of the resulting .p12 and .pfx} {} "letsencrypt"
outputCertName = "letsencrypt"
;; Set the .p12 and .pfx password.
;# {outputCertPassword} {} {Set the .p12 and .pfx password} {} ""
outputCertPassword = ""
; #
; # SSL selfsigned certificate settings.