Beispiel #1
0
        /// <summary>
        /// Start all IMAP proxy instances from the specified settings file.
        /// </summary>
        /// <param name="fileName">File containing the IMAP proxy settings.</param>
        public static List <ImapProxy> StartProxiesFromSettingsFile(string fileName)
        {
            List <ImapProxy> imapProxies = new List <ImapProxy>();

            try
            {
                if (File.Exists(fileName))
                {
                    XPathDocument  document  = new XPathDocument(fileName);
                    XPathNavigator navigator = document.CreateNavigator();

                    int imapServiceCount = ProxyFunctions.GetXmlIntValue(navigator, "/Settings/IMAP/ServiceCount");
                    for (int i = 1; i <= imapServiceCount; i++)
                    {
                        ImapProxyArguments arguments = new ImapProxyArguments();
                        arguments.AcceptedIPs = ProxyFunctions.GetXmlStringValue(navigator, "/Settings/SMTP/Service" + i + "/AcceptedIPs");

                        string localIpAddress = ProxyFunctions.GetXmlStringValue(navigator, "/Settings/IMAP/Service" + i + "/LocalIPAddress").ToUpper();
                        switch (localIpAddress)
                        {
                        // Treat blank values as "Any".
                        case "":
                        case "ANY":
                            arguments.LocalIpAddress = IPAddress.Any;
                            break;

                        case "BROADCAST":
                            arguments.LocalIpAddress = IPAddress.Broadcast;
                            break;

                        case "IPV6ANY":
                            arguments.LocalIpAddress = IPAddress.IPv6Any;
                            break;

                        case "IPV6LOOPBACK":
                            arguments.LocalIpAddress = IPAddress.IPv6Loopback;
                            break;

                        case "LOOPBACK":
                            arguments.LocalIpAddress = IPAddress.Loopback;
                            break;

                        default:
                            // Try to parse the local IP address.  If unable to, proceed to the next service instance.
                            if (!IPAddress.TryParse(localIpAddress, out arguments.LocalIpAddress))
                            {
                                continue;
                            }
                            break;
                        }

                        arguments.LocalPort = ProxyFunctions.GetXmlIntValue(navigator, "/Settings/IMAP/Service" + i + "/LocalPort");
                        // If the port is invalid, proceed to the next service instance.
                        if (arguments.LocalPort < 1)
                        {
                            continue;
                        }

                        arguments.LocalEnableSsl = ProxyFunctions.GetXmlBoolValue(navigator, "/Settings/IMAP/Service" + i + "/LocalEnableSSL");

                        arguments.RemoteServerHostName = ProxyFunctions.GetXmlStringValue(navigator, "/Settings/IMAP/Service" + i + "/RemoteServerHostName");
                        // If the host name is invalid, proceed to the next service instance.
                        if (string.IsNullOrEmpty(arguments.RemoteServerHostName))
                        {
                            continue;
                        }

                        arguments.RemoteServerPort = ProxyFunctions.GetXmlIntValue(navigator, "/Settings/IMAP/Service" + i + "/RemoteServerPort");
                        // If the port is invalid, proceed to the next service instance.
                        if (arguments.RemoteServerPort < 1)
                        {
                            continue;
                        }

                        arguments.RemoteServerEnableSsl = ProxyFunctions.GetXmlBoolValue(navigator, "/Settings/IMAP/Service" + i + "/RemoteServerEnableSSL");

                        string remoteServerUsername = ProxyFunctions.GetXmlStringValue(navigator, "/Settings/IMAP/Service" + i + "/RemoteServerUsername");
                        if (!string.IsNullOrEmpty(remoteServerUsername))
                        {
                            arguments.RemoteServerCredential          = new NetworkCredential();
                            arguments.RemoteServerCredential.UserName = remoteServerUsername;
                            arguments.RemoteServerCredential.Password = ProxyFunctions.GetXmlStringValue(navigator, "/Settings/IMAP/Service" + i + "/RemoteServerPassword");
                        }

                        string        certificateLocationValue = ProxyFunctions.GetXmlStringValue(navigator, "/Settings/IMAP/Service" + i + "/Certificate/Location");
                        StoreLocation certificateLocation      = StoreLocation.LocalMachine;
                        if (certificateLocationValue.ToUpper() == "CURRENTUSER")
                        {
                            certificateLocation = StoreLocation.CurrentUser;
                        }

                        // Try to load the signing certificate based on its serial number first, then fallback to its subject name.
                        string certificateValue = ProxyFunctions.GetXmlStringValue(navigator, "/Settings/IMAP/Service" + i + "/Certificate/SerialNumber");
                        if (!string.IsNullOrEmpty(certificateValue))
                        {
                            arguments.Certificate = CertHelper.GetCertificateBySerialNumber(certificateLocation, certificateValue);
                        }
                        else
                        {
                            certificateValue = ProxyFunctions.GetXmlStringValue(navigator, "/Settings/IMAP/Service" + i + "/Certificate/SubjectName");
                            if (!string.IsNullOrEmpty(certificateValue))
                            {
                                arguments.Certificate = CertHelper.GetCertificateBySubjectName(certificateLocation, certificateValue);
                            }
                        }

                        arguments.ExportDirectory = ProxyFunctions.GetXmlStringValue(navigator, "Settings/IMAP/Service" + i + "/ExportDirectory");
                        arguments.LogFile         = ProxyFunctions.GetXmlStringValue(navigator, "Settings/IMAP/Service" + i + "/LogFile");

                        string logLevel = ProxyFunctions.GetXmlStringValue(navigator, "Settings/IMAP/Service" + i + "/LogLevel");
                        switch (logLevel.ToUpper())
                        {
                        case "NONE":
                            arguments.LogLevel = LogLevel.None;
                            break;

                        case "CRITICAL":
                            arguments.LogLevel = LogLevel.Critical;
                            break;

                        case "ERROR":
                            arguments.LogLevel = LogLevel.Error;
                            break;

                        case "RAW":
                            arguments.LogLevel = LogLevel.Raw;
                            break;

                        case "VERBOSE":
                            arguments.LogLevel = LogLevel.Verbose;
                            break;

                        case "WARNING":
                            arguments.LogLevel = LogLevel.Warning;
                            break;

                        case "INFORMATION":
                        default:
                            arguments.LogLevel = LogLevel.Information;
                            break;
                        }

                        arguments.InstanceId = i;
                        arguments.DebugMode  = ProxyFunctions.GetXmlBoolValue(navigator, "Settings/IMAP/Service" + i + "/Debug");

                        // Remember the proxy in order to close it when the service stops.
                        arguments.Proxy = new ImapProxy();
                        imapProxies.Add(arguments.Proxy);

                        Thread proxyThread = new Thread(new ParameterizedThreadStart(StartProxy));
                        proxyThread.Name = "OpaqueMail IMAP Proxy";
                        proxyThread.Start(arguments);
                    }
                }
            }
            catch
            {
                // Ignore errors if the XML settings file is malformed.
            }

            return(imapProxies);
        }
Beispiel #2
0
        /// <summary>
        /// Start a IMAP proxy instance.
        /// </summary>
        /// <param name="acceptedIPs">IP addresses to accept connections from.</param>
        /// <param name="localIPAddress">Local IP address to bind to.</param>
        /// <param name="localPort">Local port to listen on.</param>
        /// <param name="localEnableSsl">Whether the local server supports TLS/SSL.</param>
        /// <param name="remoteServerHostName">Remote server hostname to forward all IMAP messages to.</param>
        /// <param name="remoteServerPort">Remote server port to connect to.</param>
        /// <param name="remoteServerEnableSsl">Whether the remote IMAP server requires TLS/SSL.</param>
        /// <param name="remoteServerCredential">(Optional) Credentials to be used for all connections to the remote IMAP server.  When set, this overrides any credentials passed locally.</param>
        /// <param name="exportDirectory">(Optional) Location where all incoming messages are saved as EML files.</param>
        /// <param name="logFile">File where event logs and exception information will be written.</param>
        /// <param name="logLevel">Proxy logging level, determining how much information is logged.</param>
        /// <param name="instanceId">The instance number of the proxy.</param>
        /// <param name="debugMode">Whether the proxy instance is running in DEBUG mode and should output full exception messages.</param>
        public void Start(string acceptedIPs, IPAddress localIPAddress, int localPort, bool localEnableSsl, string remoteServerHostName, int remoteServerPort, bool remoteServerEnableSsl, NetworkCredential remoteServerCredential, string exportDirectory, string logFile, LogLevel logLevel, int instanceId, bool debugMode)
        {
            // Create the log writer.
            string logFileName = "";

            if (!string.IsNullOrEmpty(logFile))
            {
                logFileName         = ProxyFunctions.GetLogFileName(logFile, instanceId, localIPAddress.ToString(), remoteServerHostName, localPort, remoteServerPort);
                LogWriter           = new StreamWriter(logFileName, true, Encoding.UTF8, Constants.SMALLBUFFERSIZE);
                LogWriter.AutoFlush = true;

                LogLevel = logLevel;
            }

            // Make sure the remote server isn't an infinite loop back to this server.
            string fqdn = Functions.GetLocalFQDN();

            if (remoteServerHostName.ToUpper() == fqdn.ToUpper() && remoteServerPort == localPort)
            {
                ProxyFunctions.Log(LogWriter, SessionId, "Cannot start service because the remote server host name {" + remoteServerHostName + "} and port {" + remoteServerPort.ToString() + "} is the same as this proxy, which would cause an infinite loop.", Proxy.LogLevel.Critical, LogLevel);
                return;
            }
            IPHostEntry hostEntry = Dns.GetHostEntry(Dns.GetHostName());

            foreach (IPAddress hostIP in hostEntry.AddressList)
            {
                if (remoteServerHostName == hostIP.ToString() && remoteServerPort == localPort)
                {
                    ProxyFunctions.Log(LogWriter, SessionId, "Cannot start service because the remote server hostname {" + remoteServerHostName + "} and port {" + remoteServerPort.ToString() + "} is the same as this proxy, which would cause an infinite loop.", Proxy.LogLevel.Critical, LogLevel);
                    return;
                }
            }

            ProxyFunctions.Log(LogWriter, SessionId, "Starting service.", Proxy.LogLevel.Information, LogLevel);

            // Attempt to start up to 3 times in case another service using the port is shutting down.
            int startAttempts = 0;

            while (startAttempts < 3)
            {
                startAttempts++;

                // If we've failed to start once, wait an extra 10 seconds.
                if (startAttempts > 1)
                {
                    ProxyFunctions.Log(LogWriter, SessionId, "Attempting to start for the " + (startAttempts == 2 ? "2nd" : "3rd") + " time.", Proxy.LogLevel.Information, LogLevel);
                    Thread.Sleep(10000 * startAttempts);
                }

                try
                {
                    X509Certificate serverCertificate = null;

                    // Generate a unique session ID for logging.
                    SessionId    = Guid.NewGuid().ToString();
                    ConnectionId = 0;

                    // If local SSL is supported via STARTTLS, ensure we have a valid server certificate.
                    if (localEnableSsl)
                    {
                        serverCertificate = CertHelper.GetCertificateBySubjectName(StoreLocation.LocalMachine, fqdn);
                        // In case the service as running as the current user, check the Current User certificate store as well.
                        if (serverCertificate == null)
                        {
                            serverCertificate = CertHelper.GetCertificateBySubjectName(StoreLocation.CurrentUser, fqdn);
                        }

                        // If no certificate was found, generate a self-signed certificate.
                        if (serverCertificate == null)
                        {
                            ProxyFunctions.Log(LogWriter, SessionId, "No signing certificate found, so generating new certificate.", Proxy.LogLevel.Warning, LogLevel);

                            List <string> oids = new List <string>();
                            oids.Add("1.3.6.1.5.5.7.3.1");    // Server Authentication.

                            // Generate the certificate with a duration of 10 years, 4096-bits, and a key usage of server authentication.
                            serverCertificate = CertHelper.CreateSelfSignedCertificate(fqdn, fqdn, StoreLocation.LocalMachine, true, 4096, 10, oids);

                            ProxyFunctions.Log(LogWriter, SessionId, "Certificate generated with Serial Number {" + serverCertificate.GetSerialNumberString() + "}.", Proxy.LogLevel.Information, LogLevel);
                        }
                    }

                    Listener = new TcpListener(localIPAddress, localPort);
                    Listener.Start();

                    ProxyFunctions.Log(LogWriter, SessionId, "Service started.", Proxy.LogLevel.Information, LogLevel);
                    ProxyFunctions.Log(LogWriter, SessionId, "Listening on address {" + localIPAddress.ToString() + "}, port {" + localPort + "}.", Proxy.LogLevel.Information, LogLevel);

                    Started = true;

                    // Accept client requests, forking each into its own thread.
                    while (Started)
                    {
                        TcpClient client = Listener.AcceptTcpClient();

                        string newLogFileName = ProxyFunctions.GetLogFileName(logFile, instanceId, localIPAddress.ToString(), remoteServerHostName, localPort, remoteServerPort);
                        if (newLogFileName != logFileName)
                        {
                            LogWriter.Close();
                            LogWriter           = new StreamWriter(newLogFileName, true, Encoding.UTF8, Constants.SMALLBUFFERSIZE);
                            LogWriter.AutoFlush = true;
                        }

                        // Prepare the arguments for our new thread.
                        ImapProxyConnectionArguments arguments = new ImapProxyConnectionArguments();
                        arguments.AcceptedIPs            = acceptedIPs;
                        arguments.TcpClient              = client;
                        arguments.Certificate            = serverCertificate;
                        arguments.ExportDirectory        = exportDirectory;
                        arguments.LocalIpAddress         = localIPAddress;
                        arguments.LocalPort              = localPort;
                        arguments.LocalEnableSsl         = localEnableSsl;
                        arguments.RemoteServerHostName   = remoteServerHostName;
                        arguments.RemoteServerPort       = remoteServerPort;
                        arguments.RemoteServerEnableSsl  = remoteServerEnableSsl;
                        arguments.RemoteServerCredential = remoteServerCredential;

                        // Increment the connection counter;
                        arguments.ConnectionId = (unchecked (++ConnectionId)).ToString();
                        arguments.InstanceId   = instanceId;
                        arguments.DebugMode    = debugMode;

                        // Fork the thread and continue listening for new connections.
                        Thread processThread = new Thread(new ParameterizedThreadStart(ProcessConnection));
                        processThread.Name = "OpaqueMail IMAP Proxy Connection";
                        processThread.Start(arguments);
                    }
                    return;
                }
                catch (Exception ex)
                {
                    if (debugMode || System.Diagnostics.Debugger.IsAttached)
                    {
                        ProxyFunctions.Log(LogWriter, SessionId, "Exception when starting proxy: " + ex.ToString(), Proxy.LogLevel.Critical, LogLevel);
                    }
                    else
                    {
                        ProxyFunctions.Log(LogWriter, SessionId, "Exception when starting proxy: " + ex.Message, Proxy.LogLevel.Critical, LogLevel);
                    }
                }
            }
        }
        /// <summary>
        /// The main.
        /// </summary>
        /// <param name="args">The args.</param>
        private static void Main(string[] args)
        {
            try
            {
                var tempFilePath = Path.Combine(FrameworkInstallDir, "Temporary ASP.NET Files");
                if (!Directory.Exists(tempFilePath))
                {
                    Directory.CreateDirectory(tempFilePath);
                }
                ScomInstallPath = ReadScomInstallPath();
                //CreateConfigLibraryMp();
#if DEBUG
                //ReadScomInstallPath();
                //ResetSubscribeStatus();
                // CreateConfigLibraryMp();
                // ModifyWebServerConfig();
                // Install();
                // SealMpb(Path.GetFullPath("..\\..\\..\\..\\..\\..\\..\\release\\MPFiles\\sealTemp"));
                // CreateMP(Path.GetFullPath("..\\..\\..\\..\\..\\..\\..\\release\\MPFiles\\Temp"), 44301);
                // UnInstall();
                Console.ReadLine();
#else
                if (args.Length == 0)
                {
                    return;
                }
                OnLog($"RunPath:{RunPath}");
                OnLog($"FrameworkInstallDir:{FrameworkInstallDir}");
                OnLog($"ScomInstallPath:{ScomInstallPath}");
                if (args[0] == "/u")
                {
                    if (!GetAttrValue(args, "keepIISExpress"))
                    {
                        UnInstallIISExpress();
                    }

                    UnInstall();
                    OnLog("PackageHelper work done.");
                }
                else if (args[0] == "/i")
                {
                    if (!int.TryParse(GetParamValue(args, "port"), out port))
                    {
                        throw new Exception("port is error");
                    }
                    if (port < 0 || port > 65536)
                    {
                        throw new Exception("port is error");
                    }
                    ipAddress = GetParamValue(args, "ip");
                    certPwd   = GetParamValue(args, "certpwd");
                    OnLog($"ip:{ipAddress} port:{port} ");

                    isEnableAlert = GetParamValue(args, "isEnableAlert");
                    OnLog($"ip:{isEnableAlert} port:{port}");
                    var isPdRight = CertHelper.CheckPfxPwd(Path.GetFullPath($"{RunPath}\\..\\Certs\\scomforfd.pfx"), certPwd);
                    if (!isPdRight)
                    {
                        OnLog("The Certificate password is incorrect");
                        Environment.Exit(-2);
                    }
                    Install();
                    OnLog("PackageHelper work done.");
                }
                else if (args[0] == "/h")
                {
                    OnLog("/i install");
                    OnLog("/u uninstall");
                    Console.ReadLine();
                }
#endif
            }
            catch (Exception ex)
            {
                OnLog("Main Error", ex);
                Environment.Exit(-1);
            }
        }
Beispiel #4
0
 public async void MulticastStart()
 {
     Multicast.StartBroadcasting(new UserFile(await CertHelper.GetCertificateFromFile("p4.crt")));
 }
Beispiel #5
0
        /// <summary>
        /// Gets the current client
        /// </summary>
        /// <returns>The current client</returns>
        private Client GetCurrentClient(HttpContext context, ConfigSettings configSettings)
        {
            string clientCertSubjectDistinguishedName,
                   clientCertIssuerDistinguishedName,
                   clientCertSerialNumber;

            if (!context.Request.Headers.TryGetValue(CommonConstants.HttpHeaders.SSLClientSDN, out var clientCertSubjectDistinguishedNameValues) ||
                string.IsNullOrEmpty(clientCertSubjectDistinguishedName = clientCertSubjectDistinguishedNameValues.ToString()) ||
                !context.Request.Headers.TryGetValue(CommonConstants.HttpHeaders.SSLClientIDN, out var clientCertIssuerDistinguishedNameValues) ||
                string.IsNullOrEmpty(clientCertIssuerDistinguishedName = clientCertIssuerDistinguishedNameValues.ToString()) ||
                !context.Request.Headers.TryGetValue(CommonConstants.HttpHeaders.SSLClientSerial, out var clientCertSerialNumberValues) ||
                string.IsNullOrEmpty(clientCertSerialNumber = clientCertSerialNumberValues.ToString()))
            {
                return(null);
            }

            Log.Information($"In GetCurrentClient: clientCertSubjectDistinguishedName={clientCertSubjectDistinguishedName}");
            Log.Information($"In GetCurrentClient: clientCertIssuerDistinguishedName={clientCertIssuerDistinguishedName}");

            var clientCertSubjectCommonName = this.GetCertCommonName(clientCertSubjectDistinguishedName);
            var clientCertIssuerCommonName  = this.GetCertCommonName(clientCertIssuerDistinguishedName);

            Log.Information($"In GetCurrentClient: clientCertSubjectCommonName={clientCertSubjectCommonName}");
            Log.Information($"In GetCurrentClient: clientCertIssuerCommonName={clientCertIssuerCommonName}");

            var configClientData = configSettings.Clients.FirstOrDefault(c =>
                                                                         c.ClientCert.SubjectCommonName == clientCertSubjectCommonName &&
                                                                         c.ClientCert.IssuerCommonName == clientCertIssuerCommonName &&
                                                                         c.ClientCert.SerialNumber.Replace(":", "") == clientCertSerialNumber.ToLowerInvariant());

            if (configClientData == null)
            {
                Log.Information("In GetCurrentClient: configClientData is null");
                return(null);
            }
            var client = new Client
            {
                ConfigClientData = configClientData
            };

            var extraClientData = new ExtraClientData
            {
                SessionId  = Guid.NewGuid().ToString(),
                ClientName = configClientData.ClientCert.SubjectCommonName
            };

            if (context.Request.Headers.TryGetValue(CommonConstants.HttpHeaders.SSLClientCert, out var pemEncodedCert))
            {
                extraClientData.ClientCert = CertHelper.GetX509Certificate(pemEncodedCert);
            }
            if (context.Request.Headers.TryGetValue(CommonConstants.HttpHeaders.ForwardedFor, out var clientIpAddress))
            {
                extraClientData.IpAddress = clientIpAddress;
            }
            if (context.Request.Headers.TryGetValue(CommonConstants.HttpHeaders.ForwardedProto, out var scheme))
            {
                extraClientData.ForwardedProto = scheme;
            }
            if (context.Request.Query.TryGetValue("username", out var userNameValues))
            {
                extraClientData.UserName = userNameValues.ToString();
            }

            client.ExtraClientData = extraClientData;

            return(client);
        }
Beispiel #6
0
        /// <summary>
        /// Populate the gridview with appropriate e-mail account and certificate choices.
        /// </summary>
        private void PopulateAccounts()
        {
            // Prepare the certificate choices.
            List <Choice> certChoices = new List <Choice>();

            X509Certificate2Collection certs = CertHelper.GetWindowsCertificates(StoreLocation.CurrentUser);

            certs.AddRange(CertHelper.GetWindowsCertificates(StoreLocation.LocalMachine));

            HashSet <string> certificatesSeen = new HashSet <string>();

            foreach (X509Certificate2 cert in certs)
            {
                // Avoid duplicate certificates.
                if (!certificatesSeen.Contains(cert.SerialNumber))
                {
                    // Ensure that the certificate has a valid subject name.
                    if (cert.Subject.IndexOf("@") > -1)
                    {
                        if (cert.Verify())
                        {
                            certChoices.Add(new Choice(cert.Subject + " (SN: " + cert.SerialNumber + ")", cert.SerialNumber));
                            certificatesSeen.Add(cert.SerialNumber);
                        }
                    }
                }
            }

            certChoices.Add(new Choice("New self-signed certificate", "self-signed"));
            CertificateColumn.DataSource    = certChoices;
            CertificateColumn.DisplayMember = "Name";
            CertificateColumn.ValueMember   = "Value";

            // Check which Outlook registry keys, Thunderbird configs, Windows Live Mail configs, and Opera Mail configs have proxies associated.
            XPathDocument    document;
            HashSet <string> outlookRegistryKeys = new HashSet <string>();
            HashSet <string> thunderbirdKeys     = new HashSet <string>();
            HashSet <string> liveMailKeys        = new HashSet <string>();
            HashSet <string> operaMailKeys       = new HashSet <string>();

            try
            {
                document = new XPathDocument(SettingsFileName);
                XPathNavigator navigator        = document.CreateNavigator();
                int            smtpServiceCount = GetXmlIntValue(navigator, "/Settings/SMTP/ServiceCount") ?? 0;
                for (int i = 1; i <= smtpServiceCount; i++)
                {
                    int?registryKeyCount = GetXmlIntValue(navigator, "/Settings/SMTP/Service" + i + "/OutlookRegistryKeyCount") ?? 0;
                    for (int j = 1; j <= registryKeyCount; j++)
                    {
                        string registryKey = GetXmlStringValue(navigator, "/Settings/SMTP/Service" + i + "/OutlookRegistryKey" + j);
                        if (!string.IsNullOrEmpty(registryKey))
                        {
                            outlookRegistryKeys.Add(registryKey);
                        }
                    }

                    int?thunderbirdKeyCount = GetXmlIntValue(navigator, "/Settings/SMTP/Service" + i + "/ThunderbirdKeyCount") ?? 0;
                    for (int j = 1; j <= thunderbirdKeyCount; j++)
                    {
                        string thunderbirdKey = GetXmlStringValue(navigator, "/Settings/SMTP/Service" + i + "/ThunderbirdKey" + j);
                        if (!string.IsNullOrEmpty(thunderbirdKey))
                        {
                            thunderbirdKeys.Add(thunderbirdKey);
                        }
                    }

                    int?liveMailKeyCount = GetXmlIntValue(navigator, "/Settings/SMTP/Service" + i + "/LiveMailKeyCount") ?? 0;
                    for (int j = 1; j <= liveMailKeyCount; j++)
                    {
                        string liveMailKey = GetXmlStringValue(navigator, "/Settings/SMTP/Service" + i + "/LiveMailKey" + j);
                        if (!string.IsNullOrEmpty(liveMailKey))
                        {
                            liveMailKeys.Add(liveMailKey);
                        }
                    }

                    int?operaMailKeyCount = GetXmlIntValue(navigator, "/Settings/SMTP/Service" + i + "/OperaMailKeyCount") ?? 0;
                    for (int j = 1; j <= operaMailKeyCount; j++)
                    {
                        string operaMailKey = GetXmlStringValue(navigator, "/Settings/SMTP/Service" + i + "/OperaMailKey" + j);
                        if (!string.IsNullOrEmpty(operaMailKey))
                        {
                            operaMailKeys.Add(operaMailKey);
                        }
                    }
                }
            }
            catch { }

            // First, correlate Outlook registry keys with accounts.
            AccountGrid.Rows.Clear();
            foreach (string outlookVersion in OutlookVersions.Keys)
            {
                using (RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Office\" + outlookVersion + @"\Outlook\Profiles\Outlook\9375CFF0413111d3B88A00104B2A6676", false))
                {
                    if (key != null)
                    {
                        string[] subkeyNames = key.GetSubKeyNames();
                        if (subkeyNames != null)
                        {
                            foreach (string subkeyName in subkeyNames)
                            {
                                using (RegistryKey subKey = key.OpenSubKey(subkeyName, false))
                                {
                                    string smtpServer = GetOutlookRegistryValue(subKey, "SMTP Server");

                                    if (!string.IsNullOrEmpty(smtpServer))
                                    {
                                        string accountName = GetOutlookRegistryValue(subKey, "Account Name");

                                        string matchingCert = GetMatchingCert(certs, accountName);

                                        AccountGrid.Rows.Add(OutlookVersions[outlookVersion], accountName, outlookRegistryKeys.Contains(subKey.Name), matchingCert, subKey.Name);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            // Second, correlate Thunderbird config keys with accounts.
            if (Directory.Exists(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\Thunderbird\\Profiles"))
            {
                foreach (string directory in Directory.GetDirectories(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\Thunderbird\\Profiles"))
                {
                    if (File.Exists(directory + "\\prefs.js"))
                    {
                        string prefsFile = File.ReadAllText(directory + "\\prefs.js");

                        int keyCount;
                        int.TryParse(Functions.ReturnBetween(prefsFile, "user_pref(\"mail.account.lastKey\", ", ")"), out keyCount);
                        for (int i = 1; i <= keyCount; i++)
                        {
                            string smtpServer  = Functions.ReturnBetween(prefsFile, "user_pref(\"mail.smtpserver.smtp" + i.ToString() + ".hostname\", \"", "\"");
                            string accountName = Functions.ReturnBetween(prefsFile, "user_pref(\"mail.smtpserver.smtp" + i.ToString() + ".username\", \"", "\"");

                            if (!string.IsNullOrEmpty(smtpServer) && !string.IsNullOrEmpty(accountName))
                            {
                                string thunderbirdKey = directory + "~" + i.ToString();

                                string matchingCert = GetMatchingCert(certs, accountName);

                                AccountGrid.Rows.Add("Thunderbird", accountName, thunderbirdKeys.Contains(thunderbirdKey), matchingCert, thunderbirdKey);
                            }
                        }
                    }
                }
            }

            // Third, correlate Windows Live Mail config keys with accounts.
            if (Directory.Exists(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\Microsoft\\Windows Live Mail"))
            {
                foreach (string directory in Directory.GetDirectories(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\Microsoft\\Windows Live Mail"))
                {
                    foreach (string file in Directory.GetFiles(directory))
                    {
                        if (file.EndsWith(".oeaccount"))
                        {
                            string settingsFile = File.ReadAllText(file);

                            int pos = 0;
                            while (pos > -1)
                            {
                                pos = settingsFile.IndexOf("<MessageAccount>", pos);
                                if (pos > -1)
                                {
                                    int pos2 = settingsFile.IndexOf("</MessageAccount>", pos);
                                    if (pos2 > -1)
                                    {
                                        string accountSettings = settingsFile.Substring(pos + 16, pos2 - pos - 16);

                                        string accountName = Functions.ReturnBetween(accountSettings, "<Account_Name type=\"SZ\">", "</Account_Name>");
                                        string smtpServer  = Functions.ReturnBetween(accountSettings, "<SMTP_Server type=\"SZ\">", "</SMTP_Server>");
                                        string address     = Functions.ReturnBetween(accountSettings, "<SMTP_Email_Address type=\"SZ\">", "</SMTP_Email_Address>");

                                        if (!string.IsNullOrEmpty(smtpServer) && !string.IsNullOrEmpty(address))
                                        {
                                            string liveMailKey = file + "~" + accountName;

                                            string matchingCert = GetMatchingCert(certs, address);

                                            AccountGrid.Rows.Add("Live Mail", address, liveMailKeys.Contains(liveMailKey), matchingCert, liveMailKey);
                                        }

                                        pos = pos2 + 17;
                                    }
                                    else
                                    {
                                        pos = -1;
                                    }
                                }
                            }
                        }
                    }
                }
            }

            // Fourth, correlate Opera Mail config keys with accounts.
            if (File.Exists(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\Opera Mail\\Opera Mail\\mail\\accounts.ini"))
            {
                string settingsFile = File.ReadAllText(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\Opera Mail\\Opera Mail\\mail\\accounts.ini");

                int accountCount = 0;
                int.TryParse(Functions.ReturnBetween(settingsFile, "Count=", "\r\n"), out accountCount);

                for (int i = 1; i <= accountCount; i++)
                {
                    int pos = settingsFile.IndexOf("[Account" + i.ToString() + "]");

                    string smtpServer = Functions.ReturnBetween(settingsFile, "Outgoing Servername=", "\r\n", pos);
                    string address    = Functions.ReturnBetween(settingsFile, "Account Name=", "\r\n", pos);

                    if (!string.IsNullOrEmpty(smtpServer) && !string.IsNullOrEmpty(address))
                    {
                        string operaMailKey = i.ToString() + "~" + address;

                        string matchingCert = GetMatchingCert(certs, address);

                        AccountGrid.Rows.Add("Opera Mail", address, operaMailKeys.Contains(operaMailKey), matchingCert, operaMailKey);
                    }
                }
            }

            // Ensure the service is running.
            InstallService();
            StartService();
        }
Beispiel #7
0
        public override bool ValidateServerCertificate(Uri uri, X509Certificate2 certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
            if (_verifyHostname)
            {
                if (sslPolicyErrors.HasFlag(SslPolicyErrors.RemoteCertificateNameMismatch))
                {
                    Logger?.Error(null, $"{GetType().Name}: Certificate '{certificate.Subject}' does not match with host name '{uri.Host}'.");
                    return(false);
                }
            }

            var result = !sslPolicyErrors.HasFlag(SslPolicyErrors.RemoteCertificateChainErrors);

            if (_useMachineCtx || chain.ChainPolicy.RevocationFlag != _revocationScope ||
                chain.ChainPolicy.RevocationMode != _revocationMode)
            {
                result = BuildChain(certificate, chain.ChainPolicy.ExtraStore, out var newChain);
                if (!result)
                {
                    Logger?.Error(null,
                                  $"{GetType().Name}: Certificate '{certificate.Subject}' failed validation. Reason: {CertHelper.ChainStatusToText(newChain.ChainStatus)}");
                }
            }

            return(result);
        }
Beispiel #8
0
        private async Task ResolveCertificate(AcmeClient acme)
        {
            _logger.LogInformation("Refreshing Order status");
            _order = await acme.GetOrderDetailsAsync(_order);

            // FIXME, wait for ready
            if (OrderStatus.Ready == _order.Status)
            {
                CertPrivateKey key = null;
                _logger.LogInformation("Generating CSR");
                byte[] csr;
                switch (_options.CertificateKeyAlgor)
                {
                case "rsa":
                    key = CertHelper.GenerateRsaPrivateKey(
                        _options.CertificateKeySize ?? AcmeOptions.DefaultRsaKeySize);
                    csr = CertHelper.GenerateRsaCsr(_options.DnsNames, key);
                    break;

                case "ec":
                    key = CertHelper.GenerateEcPrivateKey(
                        _options.CertificateKeySize ?? AcmeOptions.DefaultEcKeySize);
                    csr = CertHelper.GenerateEcCsr(_options.DnsNames, key);
                    break;

                default:
                    throw new Exception("Unknown Certificate Key Algorithm: " + _options.CertificateKeyAlgor);
                }

                await _stateStore.SavePrivateKeyAsync(_order.Url, key.KeyPair, _order.Expires);

                _logger.LogInformation("Finalizing Order");
                _order = await acme.FinalizeOrderAsync(_order, csr);
            }

            // FIXME extract out
            if (string.IsNullOrEmpty(_order.CertificateUrl))
            {
                _logger.LogWarning("Order Certificate is NOT READY YET");
                var now = DateTime.Now;
                do
                {
                    _logger.LogInformation("Waiting...");
                    await Task.Delay(5000);

                    _order = await acme.GetOrderDetailsAsync(_order);

                    if (!string.IsNullOrEmpty(_order.CertificateUrl))
                    {
                        break;
                    }

                    _logger.LogInformation($"order status {_order.Status}");

                    if (DateTime.Now > now.AddSeconds(_options.WaitForCertificate))
                    {
                        throw new TimeoutException("Failed to get certificate url");
                    }
                } while (true);

                await _stateStore.SaveOrderAsync(_order);
            }

            _logger.LogInformation("Retrieving Certificate");
            X509Certificate newCert = await acme.GetOrderCertificateAsync(_order);

            await _stateStore.SaveCertificateAsync(_order.Url, newCert);
        }
        protected async Task <bool> ResolveCertificate(AcmeProtocolClient acme)
        {
            if (_state.Certificate != null)
            {
                _logger.LogInformation("Certificate is already resolved");
                return(true);
            }

            CertPrivateKey key = null;

            _logger.LogInformation("Refreshing Order status");
            _state.Order = await acme.GetOrderDetailsAsync(_state.Order.OrderUrl, _state.Order);

            Save(_state.OrderFile, _state.Order);

            if (AcmeState.PendingStatus == _state.Order.Payload.Status)
            {
                _logger.LogInformation("Generating CSR");
                byte[] csr;
                switch (_options.CertificateKeyAlgor)
                {
                case "rsa":
                    key = CertHelper.GenerateRsaPrivateKey(
                        _options.CertificateKeySize ?? AcmeOptions.DefaultRsaKeySize);
                    csr = CertHelper.GenerateRsaCsr(_options.DnsNames, key);
                    break;

                case "ec":
                    key = CertHelper.GenerateEcPrivateKey(
                        _options.CertificateKeySize ?? AcmeOptions.DefaultEcKeySize);
                    csr = CertHelper.GenerateEcCsr(_options.DnsNames, key);
                    break;

                default:
                    throw new Exception("Unknown Certificate Key Algorithm: "
                                        + _options.CertificateKeyAlgor);
                }

                using (var keyPem = new MemoryStream())
                {
                    CertHelper.ExportPrivateKey(key, EncodingFormat.PEM, keyPem);
                    keyPem.Position = 0L;
                    Save(_state.CertificateKeysFile, keyPem);
                }
                Save(_state.CertificateRequestFile, csr);

                _logger.LogInformation("Finalizing Order");
                _state.Order = await acme.FinalizeOrderAsync(_state.Order.Payload.Finalize, csr);

                Save(_state.OrderFile, _state.Order);
            }

            if (AcmeState.ValidStatus != _state.Order.Payload.Status)
            {
                _logger.LogWarning("Order is NOT VALID");
                return(false);
            }

            if (string.IsNullOrEmpty(_state.Order.Payload.Certificate))
            {
                _logger.LogWarning("Order Certificate is NOT READY YET");
                var now = DateTime.Now;
                do
                {
                    _logger.LogInformation("Waiting...");
                    // We wait in 5s increments
                    await Task.Delay(5000);

                    _state.Order = await acme.GetOrderDetailsAsync(_state.Order.OrderUrl, _state.Order);

                    Save(_state.OrderFile, _state.Order);

                    if (!string.IsNullOrEmpty(_state.Order.Payload.Certificate))
                    {
                        break;
                    }

                    if (DateTime.Now < now.AddSeconds(_options.WaitForCertificate))
                    {
                        _logger.LogWarning("Timed Out!");
                        return(false);
                    }
                } while (true);
            }

            _logger.LogInformation("Retreiving Certificate");
            var certBytes = await acme.GetOrderCertificateAsync(_state.Order);

            Save(_state.CertificateChainFile, certBytes);

            if (key == null)
            {
                _logger.LogInformation("Loading private key");
                key = CertHelper.ImportPrivateKey(EncodingFormat.PEM,
                                                  Load <Stream>(_state.CertificateKeysFile).value);
            }

            using (var crtStream = new MemoryStream(certBytes))
                using (var pfxStream = new MemoryStream())
                {
                    _logger.LogInformation("Reading in Certificate chain (PEM)");
                    var cert = CertHelper.ImportCertificate(EncodingFormat.PEM, crtStream);
                    _logger.LogInformation("Writing out Certificate archive (PKCS12)");
                    CertHelper.ExportArchive(key, new[] { cert }, ArchiveFormat.PKCS12, pfxStream);
                    pfxStream.Position = 0L;
                    Save(_state.CertificateFile, pfxStream);
                }

            _logger.LogInformation("Loading PKCS12 archive as active certificate");
            _state.Certificate = new X509Certificate2(Load <byte[]>(_state.CertificateFile).value);

            return(true);
        }
Beispiel #10
0
        public static async Task Main(string[] args)
        {
            var environment   = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Development";
            var isDevelopment = "Development".Equals(environment, StringComparison.OrdinalIgnoreCase);

            var config = new ConfigurationBuilder()
                         .SetBasePath(Directory.GetCurrentDirectory())
                         .AddInMemoryCollection(
                new Dictionary <string, string>    // add default settings, that will be overridden by commandline
            {
                { "Id", "Webapp" },
                { "Version", "1.0.0" },
                { "ClusterId", "rrod-cluster" },
                { "ServiceId", "rrod" }
            })
                         .AddCommandLine(args)
                         .AddJsonFile("Webapp.settings.json", true, true)
                         .AddJsonFile($"Webapp.settings.{environment}.json", true, true)
                         .AddJsonFile("/run/config/Webapp.settings.json", true, true)
                         .AddDockerSecrets("/run/secrets", true)
                         .AddUserSecrets <Program>(true)
                         .AddEnvironmentVariables("RROD_")
                         .Build();

            var loggerFactory = new LoggerFactory()
                                .AddConsole(config.GetSection("Logging"))
                                .AddDebug();
            var logger = loggerFactory.CreateLogger <Program>();

            logger.LogWarning($"Starting Webapp in {environment} environment...");

            foreach (var provider in config.Providers)
            {
                logger.LogInformation(
                    $"Config Provider {provider.GetType().Name}: {provider.GetChildKeys(Enumerable.Empty<string>(), null).Count()} settings");
            }

            // ServicePointManager.CheckCertificateRevocationList = false;
            ServicePointManager.SecurityProtocol =
                SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
            ServicePointManager.DefaultConnectionLimit = 20;

            var            attempt = 0;
            var            initializeAttemptsBeforeFailing = 7;
            IClusterClient clusterClient = null;

            while (true)
            {
                // Initialize orleans client
                clusterClient = new ClientBuilder()
                                .ConfigureServices((context, services) =>
                {
                    // services.AddOptions();
                    services.AddSingleton(loggerFactory);

                    // services.AddSingleton<IConfiguration>(config);
                    services.Configure <ClusterOptions>(config);
                })

                                //.AddAzureQueueStreams<AzureQueueDataAdapterV2>("Default", builder => builder.Configure(options => options.ConnectionString = config.GetConnectionString("DataConnectionString")))
                                .ConfigureApplicationParts(parts =>
                {
                    parts.AddApplicationPart(typeof(ICounterGrain).Assembly).WithReferences();

                    //parts.AddApplicationPart(typeof(AzureQueueDataAdapterV2).Assembly).WithReferences();
                })

                                //.UseAzureStorageClustering(options => options.ConnectionString = config.GetConnectionString("DataConnectionString"))
                                .Build();

                try
                {
                    await clusterClient.Connect().ConfigureAwait(false);

                    logger.LogInformation("Client successfully connected to silo host");
                    break;
                }
                catch (OrleansException)
                {
                    attempt++;
                    logger.LogWarning(
                        $"Attempt {attempt} of {initializeAttemptsBeforeFailing} failed to initialize the Orleans client.");

                    if (clusterClient != null)
                    {
                        clusterClient.Dispose();
                        clusterClient = null;
                    }

                    if (attempt > initializeAttemptsBeforeFailing)
                    {
                        throw;
                    }

                    // Wait 4 seconds before retrying
                    await Task.Delay(TimeSpan.FromSeconds(4));
                }
            }

            var endpoints = config.GetSection("Http:Endpoints")
                            .GetChildren()
                            .ToDictionary(section => section.Key, section =>
            {
                var endpoint = new EndpointConfiguration();
                section.Bind(endpoint);
                return(endpoint);
            });

            // if so, start a listener to respond to Acme (Let's Encrypt) requests, using a response received via an Orleans Cache Grain
            var hasHttps = endpoints.Any(endpoint =>
                                         endpoint.Value.Scheme.Equals("https", StringComparison.InvariantCultureIgnoreCase));
            var needPort80 = endpoints.Any(endpoint =>
                                           (endpoint.Value.Port ??
                                            (endpoint.Value.Scheme.Equals("https", StringComparison.InvariantCultureIgnoreCase) ? 443 : 80)) ==
                                           80);
            var certs = new Dictionary <string, X509Certificate2>();

            var acmeOptions = new AcmeOptions
            {
                AcmeSettings         = config.GetSection(nameof(AcmeSettings)).Get <AcmeSettings>(),
                GetChallengeResponse = async challenge =>
                {
                    var cacheGrain = clusterClient.GetGrain <ICacheGrain <string> >(challenge);
                    var response   = await cacheGrain.Get();

                    return(response.Value);
                },
                SetChallengeResponse = async(challenge, response) =>
                {
                    var cacheGrain = clusterClient.GetGrain <ICacheGrain <string> >(challenge);
                    await cacheGrain.Set(new Immutable <string>(response), TimeSpan.FromHours(2));
                },
                StoreCertificate = async(domainName, certData) =>
                {
                    var certGrain = clusterClient.GetGrain <ICertGrain>(domainName);
                    await certGrain.UpdateCertificate(certData);
                },
                RetrieveCertificate = async domainName =>
                {
                    var certGrain = clusterClient.GetGrain <ICertGrain>(domainName);
                    var certData  = await certGrain.GetCertificate();

                    return(certData.Value);
                }
            };

            if (hasHttps)
            {
                logger.LogWarning($"At least one https endpoint is present. Initialize Acme endpoint.");

                var acmeHost = new WebHostBuilder()
                               .UseEnvironment(environment)
                               .UseConfiguration(config)
                               .ConfigureServices(services =>
                {
                    services.AddSingleton(clusterClient);
                    services.AddSingleton(loggerFactory);
                    services.Configure <AcmeSettings>(config.GetSection(nameof(AcmeSettings)));

                    // Register a certitificate manager, supplying methods to store and retreive certificates and acme challenge responses
                    services.AddAcmeCertificateManager(acmeOptions);
                })

                               // .UseUrls("http://*:80")
                               .PreferHostingUrls(false)
                               .UseKestrel(options => { options.Listen(IPAddress.Any, 80); })
                               .Configure(app => { app.UseAcmeResponse(); })
                               .Build();

                try
                {
                    await acmeHost.StartAsync().ConfigureAwait(false);
                }
                catch (Exception e)
                {
                    logger.LogError(
                        "Error: can't start web listener for acme certificate renewal, probably the web address is in use by another process. Exception message is: " +
                        e.Message);
                    logger.LogError("Ignoring noncritical error (stop W3SVC or Skype to fix this), continuing...");
                }

                var certificateManager = acmeHost.Services.GetRequiredService <ICertificateManager>();

                // var certificateManager = new AcmeCertificateManager(Options.Create(acmeOptions));
                foreach (var endpoint in endpoints)
                {
                    var endpointConfig  = endpoint.Value;
                    var isHttpsEndpoint =
                        endpointConfig.Scheme.Equals("https", StringComparison.InvariantCultureIgnoreCase);
                    var port = endpointConfig.Port ?? (isHttpsEndpoint ? 443 : 80);

                    X509Certificate2 certificate = null;
                    if (isHttpsEndpoint)
                    {
                        try
                        {
                            var domains = new List <string> {
                                endpointConfig.Domain
                            }
                            .Concat(endpointConfig.Domains)
                            .Where(ep => !string.IsNullOrEmpty(ep))
                            .Distinct()
                            .ToArray();

                            logger.LogInformation($"Getting certificate for domain {domains.First()} on port {port}");

                            // Request a new certificate with Let's Encrypt and store it for next time
                            try
                            {
                                certificate = await certificateManager.GetCertificate(domains);
                            }
                            catch (Exception e)
                            {
                                logger.LogCritical(e,
                                                   $"Exception getting certificate for domain {domains.First()}. PfxPassword configured incorrectly?");
                            }

                            if (certificate == null)
                            {
                                // It didn't work - create a temporary certificate so that we can still start with an untrusted certificate
                                logger.LogCritical(
                                    $"Error getting certificate for domain {domains.First()} (endpoint '{endpoint.Key}'). Creating self-signed temporary certificate...");
                                certificate = CertHelper.BuildTlsSelfSignedServer(domains);
                            }

                            certs.Add(domains.First(), certificate);
                            logger.LogInformation($"Certificate for domain {domains.First()}: {certificate != null}");
                        }
                        catch (Exception e)
                        {
                            logger.LogCritical($"Kestrel startup: Exception getting certificate. {e.Message}");
                        }
                    }
                }

                if (needPort80)
                {
                    await acmeHost.StopAsync();
                }
            }

            var webHost = new WebHostBuilder()
                          .UseEnvironment(environment)
                          .UseConfiguration(config)
                          .ConfigureServices(services =>
            {
                // services.AddSingleton<IConfiguration>(config);
                services.AddSingleton(clusterClient);
                services.AddSingleton(loggerFactory);
                services.Configure <AcmeSettings>(config.GetSection(nameof(AcmeSettings)));
                services.AddAcmeCertificateManager(acmeOptions);
            })
                          .UseContentRoot(Directory.GetCurrentDirectory())

                          // .UseUrls(listenUrls.ToArray())
                          .PreferHostingUrls(false)
                          .Configure(app => { app.UseAcmeResponse(); })
                          .UseStartup <Startup>()
                          .UseKestrel(options =>
            {
                foreach (var endpoint in endpoints)
                {
                    var endpointConfig  = endpoint.Value;
                    var isHttpsEndpoint =
                        endpointConfig.Scheme.Equals("https", StringComparison.InvariantCultureIgnoreCase);
                    var port = endpointConfig.Port ?? (isHttpsEndpoint ? 443 : 80);

                    var ipAddresses = new List <IPAddress>();
                    var hosts       = new List <string> {
                        endpointConfig.Host
                    }
                    .Concat(endpointConfig.Hosts)
                    .Where(ep => !string.IsNullOrEmpty(ep))
                    .Distinct();

                    foreach (var host in hosts)
                    {
                        if (host == "localhost")
                        {
                            ipAddresses.Add(IPAddress.IPv6Loopback);
                            ipAddresses.Add(IPAddress.Loopback);
                        }
                        else if (IPAddress.TryParse(host, out var address))
                        {
                            ipAddresses.Add(address);
                        }
                        else
                        {
                            logger.LogError($"Error parsing endpoint host: {host}");
                        }
                    }

                    foreach (var address in ipAddresses)
                    {
                        options.Listen(address, port, listenOptions =>
                        {
                            if (isHttpsEndpoint)
                            {
                                var domains = new List <string> {
                                    endpointConfig.Domain
                                }
                                .Concat(endpointConfig.Domains)
                                .Where(ep => !string.IsNullOrEmpty(ep))
                                .Distinct()
                                .ToArray();

                                if (certs.TryGetValue(domains.First(), out var certificate))
                                {
                                    logger.LogInformation(
                                        $"Kestrel config: Listen on address {address.ToString()}:{port}, certificate {(certificate == null ? "NULL" : certificate.Subject.ToString())}");
                                    listenOptions.UseHttps(certificate);
                                    listenOptions.NoDelay = false;

                                    // listenOptions.UseConnectionLogging();
                                }
                                else
                                {
                                    logger.LogError($"No certificate for domain: {domains.First()}");
                                }
                            }
                        });
                    }
                }
            })
                          .Build();

            webHost.Run();
        }
        public void ConfigureService(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            if (ConfigHelper.IsSecurityEnabled(serviceHostBase))
            {
                // Get certificate location from the cert store.
                StoreLocation location = StoreLocation.LocalMachine;
                CertHelper.TryGetCertLocation(ServiceCert, out location, true);

                // Set certificate

                serviceHostBase.Credentials.ServiceCertificate.SetCertificate(
                    location,
                    System.Security.Cryptography.X509Certificates.StoreName.My,
                    X509FindType.FindBySubjectName,
                    ServiceCert);

                // Set certificate validation mode (defaults to peer trust).
                serviceHostBase.Credentials.ClientCertificate.Authentication.CertificateValidationMode = ValidationMode;

                if (serviceHostBase.Description.Endpoints != null)
                {
                    bool reConfigure = false;
                    foreach (var endpoint in serviceHostBase.Description.Endpoints)
                    {
                        if (endpoint.Binding is WS2007HttpBinding)
                        {
                            // Setup each endpoint to use Message security.
                            var binding = endpoint.Binding as WS2007HttpBinding;
                            binding.Security.Mode = SecurityMode.Message;
                            binding.Security.Message.ClientCredentialType       = MessageCredentialType.Certificate;
                            binding.Security.Message.EstablishSecurityContext   = false;
                            binding.Security.Message.NegotiateServiceCredential = false;
                            MaxSetter.SetMaxes(binding);
                        }
                        if (endpoint.Binding is NetTcpBinding)
                        {
                            // Setup each endpoint to use Message security.
                            var binding = endpoint.Binding as NetTcpBinding;
                            binding.Security.Mode = SecurityMode.Message;
                            binding.Security.Message.ClientCredentialType = MessageCredentialType.Certificate;
                            MaxSetter.SetMaxes(binding);
                        }
                        if (endpoint.Binding is BasicHttpBinding)
                        {
                            reConfigure = true;
                        }
                    }

                    // reconfigure host
                    if (reConfigure && serviceHostBase.Description.Endpoints.Count() > 0)
                    {
                        var host = (serviceHostBase as ServiceHost);
                        if (host != null)
                        {
                            // Don't use this crappy binding
                            var address  = serviceHostBase.Description.Endpoints.First().Address;
                            var contract = serviceHostBase.Description.Endpoints.First().Contract;

                            // clear existing
                            host.Description.Endpoints.Clear();

                            var binding = new WS2007HttpBinding();
                            binding.Security.Mode = SecurityMode.Message;
                            binding.Security.Message.ClientCredentialType     = MessageCredentialType.Certificate;
                            binding.Security.Message.EstablishSecurityContext = false;

                            MaxSetter.SetMaxes(binding);

                            var endpoint = host.AddServiceEndpoint(contract.ContractType, binding, address.Uri);
                        }
                    }

                    DisableErrorMasking.Disable(serviceHostBase);
                }
            }
        }