/// <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); }
/// <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); } }
public async void MulticastStart() { Multicast.StartBroadcasting(new UserFile(await CertHelper.GetCertificateFromFile("p4.crt"))); }
/// <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); }
/// <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(); }
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); }
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); }
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); } } }