diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index bc5f08a09b..7ca7d93416 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs @@ -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); + } + + /// + /// Convert or renew .pem certificate to PKCS12 .pfx and .p12 usable by OpenSim. + /// the parameters are set in the startup section of OpenSim.ini + /// + /// The output certificate file name. + /// The path of fullchain.pem. If your CA don't provide + /// the fullchain file, you can set the cert.pem instead. + /// The path of the private key (privkey.pem). + /// The output certificates password. + 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); diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index 2971f61326..03c8fdd36f 100755 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -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) { diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index 4f49f1f46d..3c2ff30b47 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -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 ? diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index 57c20cd414..3da8fe1dd6 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -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.