Browse Source

ServerConfigurationManager: Check if a specified SSL certificate can be used when configuration is saved

Emby can only use certificates in PFX format which include a private
key, and where the private key is not protected with a password.

Checking these conditions early helps to avoid misconfigurations and
reduce troubleshooting time...
softworkz 9 years ago
parent
commit
f92b517eda

+ 37 - 0
MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs

@@ -171,12 +171,49 @@ namespace MediaBrowser.Server.Implementations.Configuration
             ValidateItemByNamePath(newConfig);
             ValidatePathSubstitutions(newConfig);
             ValidateMetadataPath(newConfig);
+            ValidateSslCertificate(newConfig);
 
             EventHelper.FireEventIfNotNull(ConfigurationUpdating, this, new GenericEventArgs<ServerConfiguration> { Argument = newConfig }, Logger);
 
             base.ReplaceConfiguration(newConfiguration);
         }
 
+
+        /// <summary>
+        /// Validates the SSL certificate.
+        /// </summary>
+        /// <param name="newConfig">The new configuration.</param>
+        /// <exception cref="System.IO.DirectoryNotFoundException"></exception>
+        private void ValidateSslCertificate(BaseApplicationConfiguration newConfig)
+        {
+            var serverConfig = (ServerConfiguration)newConfig;
+
+            var certPath = serverConfig.CertificatePath;
+
+            if (!string.IsNullOrWhiteSpace(certPath))
+            {
+                // Validate
+                if (!File.Exists(certPath))
+                {
+                    throw new FileNotFoundException(string.Format("Certificate file '{0}' does not exist.", certPath));
+                }
+
+                try
+                {
+                    var cert = new System.Security.Cryptography.X509Certificates.X509Certificate2(certPath);
+
+                    if (cert.PrivateKey == null)
+                    {
+                        throw new ArgumentException("Certificate does not contain a private key!");
+                    }
+                }
+                catch (Exception ex)
+                {
+                    throw new ArgumentException(string.Format("Exception loading certificate: '{0}' - {1}", certPath, ex.Message));
+                }
+            }
+        }
+
         private void ValidatePathSubstitutions(ServerConfiguration newConfig)
         {
             foreach (var map in newConfig.PathSubstitutions)