From eb9b311bba406c2f8ab7f2d7f007ee92b2cf93a9 Mon Sep 17 00:00:00 2001 From: Olov Karlsson Date: Sun, 30 Nov 2014 09:13:06 +0100 Subject: [PATCH] IIS SSL updates, mostly SNI/CCS-related, but also a lot of UI fixes/improvements --- .../SSL/SSLModuleService80.cs | 305 ++++++++++-------- .../WebsitePanel/WebSitesEditSite.ascx.cs | 4 +- .../WebsitePanel/WebsitesSSL.ascx | 18 +- .../WebsitePanel/WebsitesSSL.ascx.cs | 255 ++++++--------- .../WebsitePanel/WebsitesSSL.ascx.designer.cs | 61 ++-- 5 files changed, 299 insertions(+), 344 deletions(-) diff --git a/WebsitePanel/Sources/WebsitePanel.Providers.Web.IIs80/SSL/SSLModuleService80.cs b/WebsitePanel/Sources/WebsitePanel.Providers.Web.IIs80/SSL/SSLModuleService80.cs index 01baf828..1395bde6 100644 --- a/WebsitePanel/Sources/WebsitePanel.Providers.Web.IIs80/SSL/SSLModuleService80.cs +++ b/WebsitePanel/Sources/WebsitePanel.Providers.Web.IIs80/SSL/SSLModuleService80.cs @@ -49,14 +49,6 @@ namespace WebsitePanel.Providers.Web.Iis // We need to move it into "WebHosting" store // Get certificate var servercert = GetServerCertificates(StoreName.My.ToString()).Single(c => c.FriendlyName == cert.FriendlyName); - if (UseCCS) - { - // Delete existing certificate, if any. This is needed to install a new binding - if (CheckCertificate(website)) - { - DeleteCertificate(GetCurrentSiteCertificate(website), website); - } - } // Get certificate data - the one we just added to "Personal" store var storeMy = new X509Store(StoreName.My, StoreLocation.LocalMachine); @@ -64,6 +56,7 @@ namespace WebsitePanel.Providers.Web.Iis X509CertificateCollection existCerts2 = storeMy.Certificates.Find(X509FindType.FindBySerialNumber, servercert.SerialNumber, false); var certData = existCerts2[0].Export(X509ContentType.Pfx); storeMy.Close(); + var x509Cert = new X509Certificate2(certData); if (UseCCS) { @@ -74,7 +67,6 @@ namespace WebsitePanel.Providers.Web.Iis { // Add new certificate to "WebHosting" store var store = new X509Store(CertificateStoreName, StoreLocation.LocalMachine); - var x509Cert = new X509Certificate2(certData); store.Open(OpenFlags.ReadWrite); store.Add(x509Cert); store.Close(); @@ -85,6 +77,7 @@ namespace WebsitePanel.Providers.Web.Iis X509CertificateCollection existCerts = storeMy.Certificates.Find(X509FindType.FindBySerialNumber, servercert.SerialNumber, false); storeMy.Remove((X509Certificate2)existCerts[0]); storeMy.Close(); + // Fill object with certificate data cert.SerialNumber = servercert.SerialNumber; cert.ValidFrom = servercert.ValidFrom; @@ -99,7 +92,7 @@ namespace WebsitePanel.Providers.Web.Iis DeleteCertificate(GetCurrentSiteCertificate(website), website); } - AddBinding(cert, website); + AddBinding(x509Cert, website); } } catch (Exception ex) @@ -113,8 +106,10 @@ namespace WebsitePanel.Providers.Web.Iis public new List GetServerCertificates() { - // Use Web Hosting store - new for IIS 8.0 - return GetServerCertificates(CertificateStoreName); + // Get certificates from both WebHosting and My (Personal) store + var certificates = GetServerCertificates(CertificateStoreName); + certificates.AddRange(GetServerCertificates(StoreName.My.ToString())); + return certificates; } public new SSLCertificate ImportCertificate(WebSite website) @@ -134,12 +129,12 @@ namespace WebsitePanel.Providers.Web.Iis }; } - return certificate; + return certificate ?? (new SSLCertificate {Success = false, Certificate = "No certificate in binding on server, please remove or edit binding"}); } public new SSLCertificate InstallPfx(byte[] certificate, string password, WebSite website) { - SSLCertificate newcert, oldcert = null; + SSLCertificate newcert = null, oldcert = null; // Ensure we perform operations safely and preserve the original state during all manipulations, save the oldcert if one is used if (CheckCertificate(website)) @@ -170,7 +165,7 @@ namespace WebsitePanel.Providers.Web.Iis writer.Write(certData); writer.Flush(); writer.Close(); - // Certificated saved + // Certificate saved } catch (Exception ex) { @@ -189,7 +184,6 @@ namespace WebsitePanel.Providers.Web.Iis try { store.Open(OpenFlags.ReadWrite); - store.Add(x509Cert); } catch (Exception ex) @@ -205,82 +199,38 @@ namespace WebsitePanel.Providers.Web.Iis } // Step 2: Instantiate a copy of new X.509 certificate - try - { - store.Open(OpenFlags.ReadWrite); - newcert = GetSSLCertificateFromX509Certificate2(x509Cert); - } - catch (Exception ex) - { - if (!UseCCS) - { - // Rollback X.509 store changes - store.Remove(x509Cert); - } - // Log error - Log.WriteError("SSLModuleService could not instantiate a copy of new X.509 certificate. All previous changes have been rolled back.", ex); - // Re-throw - throw; - } - finally - { - store.Close(); - } + try + { + newcert = GetSSLCertificateFromX509Certificate2(x509Cert); + } + catch (Exception ex) + { + HandleExceptionAndRollbackCertificate(store, x509Cert, null, website, "SSLModuleService could not instantiate a copy of new X.509 certificate.", ex); + } - if (!UseCCS) - { - // Step 3: Remove old certificate from the web site if any - try - { - store.Open(OpenFlags.ReadWrite); - // Check if certificate already exists, remove it. - if (oldcert != null) - DeleteCertificate(oldcert, website); - } - catch (Exception ex) - { - // Rollback X.509 store changes - store.Remove(x509Cert); - // Log the error - Log.WriteError( - String.Format("SSLModuleService could not remove existing certificate from '{0}' web site. All changes have been rolled back.", website.Name), ex); - // Re-throw - throw; - } - finally - { - store.Close(); - } - } + // Step 3: Remove old certificate from the web site if any + try + { + // Check if certificate already exists, remove it. + if (oldcert != null) + { + DeleteCertificate(oldcert, website); + } + } + catch (Exception ex) + { + HandleExceptionAndRollbackCertificate(store, x509Cert, null, website, string.Format("SSLModuleService could not remove existing certificate from '{0}' web site.", website.Name), ex); + } - // Step 4: Register new certificate with HTTPS binding on the web site - try - { - //if (!UseCCS) - //{ - // store.Open(OpenFlags.ReadWrite); - //} - - AddBinding(newcert, website); - } - catch (Exception ex) - { - if (!UseCCS) - { - // Install old certificate back if any - store.Open(OpenFlags.ReadWrite); - if (oldcert != null) - InstallCertificate(oldcert, website); - // Rollback X.509 store changes - store.Remove(x509Cert); - store.Close(); - } - // Log the error - Log.WriteError( - String.Format("SSLModuleService could not add new X.509 certificate to '{0}' web site. All changes have been rolled back.", website.Name), ex); - // Re-throw - throw; - } + // Step 4: Register new certificate with HTTPS binding on the web site + try + { + AddBinding(x509Cert, website); + } + catch (Exception ex) + { + HandleExceptionAndRollbackCertificate(store, x509Cert, oldcert, website, String.Format("SSLModuleService could not add new X.509 certificate to '{0}' web site.", website.Name), ex); + } return newcert; } @@ -319,32 +269,44 @@ namespace WebsitePanel.Providers.Web.Iis } - public new void AddBinding(SSLCertificate certificate, WebSite website) + public void AddBinding(X509Certificate2 certificate, WebSite website) { using (var srvman = GetServerManager()) { - var store = new X509Store(CertificateStoreName, StoreLocation.LocalMachine); - store.Open(OpenFlags.ReadOnly); - // Look for dedicated ip var dedicatedIp = SiteHasBindingWithDedicatedIp(srvman, website); - var bindingInformation = string.Format("{0}:443:{1}", website.SiteIPAddress, dedicatedIp ? "" : certificate.Hostname); + // Look for all the hostnames this certificate is valid for if we are using SNI + var hostNames = new List(); - Binding siteBinding = UseCCS ? - srvman.Sites[website.SiteId].Bindings.Add(bindingInformation, "https") : - srvman.Sites[website.SiteId].Bindings.Add(bindingInformation, certificate.Hash, store.Name); + if (!dedicatedIp) + { + hostNames.AddRange(from extension in certificate.Extensions.Cast() where extension.Oid.FriendlyName == "Subject Alternative Name" select extension.Format(true)); + } + + if (!hostNames.Any()) + { + hostNames.Add(certificate.GetNameInfo(X509NameType.SimpleName, false)); + } + + // For every hostname (only one if using old school dedicated IP binding) + foreach (var hostName in hostNames) + { + var bindingInformation = string.Format("{0}:443:{1}", website.SiteIPAddress ?? "*", dedicatedIp ? "" : hostName); + + Binding siteBinding = UseCCS ? + srvman.Sites[website.SiteId].Bindings.Add(bindingInformation, "https") : + srvman.Sites[website.SiteId].Bindings.Add(bindingInformation, certificate.GetCertHash(), CertificateStoreName); - if (UseSNI) - { - siteBinding.SslFlags |= SslFlags.Sni; + if (UseSNI && !dedicatedIp) + { + siteBinding.SslFlags |= SslFlags.Sni; + } + if (UseCCS) + { + siteBinding.SslFlags |= SslFlags.CentralCertStore; + } } - if (UseCCS) - { - siteBinding.SslFlags |= SslFlags.CentralCertStore; - } - - store.Close(); srvman.CommitChanges(); } @@ -352,7 +314,9 @@ namespace WebsitePanel.Providers.Web.Iis public new ResultObject DeleteCertificate(SSLCertificate certificate, WebSite website) { - var result = new ResultObject() { IsSuccess = true }; + // This method removes all https bindings and all certificates associated with them. + // Old implementation (IIS70) removed a single binding (there could not be more than one) and the first certificate that matched via serial number + var result = new ResultObject { IsSuccess = true }; if (certificate == null) { @@ -361,35 +325,70 @@ namespace WebsitePanel.Providers.Web.Iis try { - // Regardless of the CCS setting on the server, we try to find and remove the certificate from both CCS and WebHosting Store. - // This is because we don't know how this was set when the certificate was added + var certificatesAndStoreNames = new List>(); - if (!string.IsNullOrWhiteSpace(CCSUncPath) && Directory.Exists(CCSUncPath)) + // User servermanager to get aLL SSL-bindings on this website and try to remove the certificates used + using (var srvman = GetServerManager()) { - // This is where it will be if CCS is used - var path = GetCCSPath(certificate.Hostname); - if (File.Exists(path)) + + var site = srvman.Sites[website.Name]; + var bindings = site.Bindings.Where(b => b.Protocol == "https"); + + foreach (Binding binding in bindings.ToList()) { - File.Delete(path); + if (binding.SslFlags.HasFlag(SslFlags.CentralCertStore)) + { + if (!string.IsNullOrWhiteSpace(CCSUncPath) && Directory.Exists(CCSUncPath)) + { + // This is where it will be if CCS is used + var path = GetCCSPath(certificate.Hostname); + if (File.Exists(path)) + { + File.Delete(path); + } + + // If binding with hostname, also try to delete with the hostname in the binding + // This is because if SNI is used, several bindings are created for every valid name in the cerificate, but only one name exists in the SSLCertificate + if (!string.IsNullOrEmpty(binding.Host)) + { + path = GetCCSPath(binding.Host); + if (File.Exists(path)) + { + File.Delete(path); + } + } + } + } + else + { + var certificateAndStoreName = new Tuple(binding.CertificateStoreName, binding.CertificateHash); + + if (!string.IsNullOrEmpty(binding.CertificateStoreName) && !certificatesAndStoreNames.Contains(certificateAndStoreName)) + { + certificatesAndStoreNames.Add(certificateAndStoreName); + } + } + + // Remove binding from site + site.Bindings.Remove(binding); } - } - // Now delete all certs with the same serialnumber in WebHosting Store - var store = new X509Store(CertificateStoreName, StoreLocation.LocalMachine); - store.Open(OpenFlags.MaxAllowed); + srvman.CommitChanges(); - var certs = store.Certificates.Find(X509FindType.FindBySerialNumber, certificate.SerialNumber, false); - foreach (var cert in certs) - { - store.Remove(cert); - } + foreach (var certificateAndStoreName in certificatesAndStoreNames) + { + // Delete all certs with the same serialnumber in Store + var store = new X509Store(certificateAndStoreName.Item1, StoreLocation.LocalMachine); + store.Open(OpenFlags.MaxAllowed); - store.Close(); + var certs = store.Certificates.Find(X509FindType.FindByThumbprint, BitConverter.ToString(certificateAndStoreName.Item2).Replace("-", ""), false); + foreach (var cert in certs) + { + store.Remove(cert); + } - // Remove binding from site - if (CheckCertificate(website)) - { - RemoveBinding(certificate, website); + store.Close(); + } } } catch (Exception ex) @@ -409,9 +408,7 @@ namespace WebsitePanel.Providers.Web.Iis var site = srvman.Sites[website.SiteId]; var sslBinding = site.Bindings.First(b => b.Protocol == "https"); - X509Certificate2 cert = null; - - // If the certificate is in the central store + // If the certificate is in the central store if (((SslFlags)Enum.Parse(typeof(SslFlags), sslBinding["sslFlags"].ToString())).HasFlag(SslFlags.CentralCertStore)) { // Let's try to match binding host and certificate filename @@ -423,23 +420,19 @@ namespace WebsitePanel.Providers.Web.Iis // Read certificate data from file var certData = new byte[fileStream.Length]; fileStream.Read(certData, 0, (int) fileStream.Length); - cert = new X509Certificate2(certData, CCSCommonPassword); + var cert = new X509Certificate2(certData, CCSCommonPassword); fileStream.Close(); + return GetSSLCertificateFromX509Certificate2(cert); } } else { - var currentHash = sslBinding.CertificateHash; - var store = new X509Store(CertificateStoreName, StoreLocation.LocalMachine); - store.Open(OpenFlags.ReadOnly); - - cert = store.Certificates.Cast().Single(c => Convert.ToBase64String(c.GetCertHash()) == Convert.ToBase64String(currentHash)); - - store.Close(); + var currentHash = Convert.ToBase64String(sslBinding.CertificateHash); + return GetServerCertificates().FirstOrDefault(c => Convert.ToBase64String(c.Hash) == currentHash); } - - return GetSSLCertificateFromX509Certificate2(cert); } + + return null; } private static List GetServerCertificates(string certificateStoreName) @@ -504,5 +497,33 @@ namespace WebsitePanel.Providers.Web.Iis return false; } } + + private void HandleExceptionAndRollbackCertificate(X509Store store, X509Certificate2 x509Cert, SSLCertificate oldCert, WebSite webSite, string errorMessage, Exception ex) + { + if (!UseCCS) + { + try + { + // Rollback X.509 store changes + store.Open(OpenFlags.ReadWrite); + store.Remove(x509Cert); + store.Close(); + } + catch (Exception) + { + Log.WriteError("SSLModuleService could not rollback and remove certificate from store", ex); + } + + // Install old certificate back if any + if (oldCert != null) + InstallCertificate(oldCert, webSite); + } + + // Log the error + Log.WriteError(errorMessage + " All changes have been rolled back.", ex); + + // Re-throw + throw ex; + } } } diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebSitesEditSite.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebSitesEditSite.ascx.cs index 5d5a954d..2b53d79e 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebSitesEditSite.ascx.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebSitesEditSite.ascx.cs @@ -109,7 +109,7 @@ namespace WebsitePanel.Portal { var filteredTabs = TabsList.FilterTabsByHostingPlanQuotas(PackageId).ToList(); - // remove "SSL" tab for a site with dynamic IP + // remove "SSL" tab for a site with dynamic IP and not SNI enabled var sslTab = filteredTabs.SingleOrDefault(t => t.Id == "SSL"); if (!AllowSsl && sslTab != null) filteredTabs.Remove(sslTab); @@ -1071,6 +1071,7 @@ namespace WebsitePanel.Portal sharedIP.Visible = false; switchToDedicatedIP.Visible = true; + WebsitesSSLControl.InstalledCert = null; } protected void cmdSwitchToSharedIP_Click(object sender, EventArgs e) @@ -1090,6 +1091,7 @@ namespace WebsitePanel.Portal dlTabs.SelectedIndex = 0; + WebsitesSSLControl.InstalledCert = null; } catch (Exception ex) { diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebsitesSSL.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebsitesSSL.ascx index 93b38d0f..b7c51011 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebsitesSSL.ascx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebsitesSSL.ascx @@ -141,6 +141,8 @@

+ @@ -151,13 +153,7 @@ - - - - - - - + @@ -173,7 +169,7 @@ + ControlToValidate="txtCompany" ErrorMessage="*" /> @@ -196,7 +192,7 @@ + ControlToValidate="txtState" Display="Dynamic" ErrorMessage="*" /> @@ -204,7 +200,7 @@ + ControlToValidate="txtCity" ErrorMessage="*" />
@@ -254,6 +250,8 @@
+ diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebsitesSSL.ascx.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebsitesSSL.ascx.cs index 91e97c36..d6897098 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebsitesSSL.ascx.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebsitesSSL.ascx.cs @@ -135,10 +135,18 @@ namespace WebsitePanel.Portal } } - private void BindListOfAvailableSslDomains(string websiteName, string domainName) - { - rbSiteCertificate.Text = websiteName; - rbDomainCertificate.Text = "*." + domainName; + private void BindListOfAvailableSslDomains(string defaultBindingName) + { + var domains = ES.Services.WebServers.GetWebSitePointers(SiteId).ToList(); + + // If no pointers at all, add website default domain + if (domains.All(d => d.DomainName != defaultBindingName)) + { + domains.Add(new DomainInfo() { DomainName = defaultBindingName, IsDomainPointer = false}); + } + + ddlbSiteCertificate.Items.AddRange(domains.Select(d => new ListItem(d.DomainName)).ToArray()); + ddlbSiteCertificate.Items.AddRange(domains.Where(d => !d.IsDomainPointer).Select(d => new ListItem("*." + d.DomainName)).ToArray()); } public void BindWebItem(WebVirtualDirectory item) @@ -148,106 +156,10 @@ namespace WebsitePanel.Portal // Skip processing virtual directories, otherwise we will likely run into a trouble if (webSite == null) return; - // - bool hasactive = false; - bool haspending = false; - SiteId = item.Id; - // - try - { - SSLCertificate[] certificates = ES.Services.WebServers.GetCertificatesForSite(item.Id); + SiteId = item.Id; - SSLNotInstalled.Visible = true; - - DomainInfo[] domains = ES.Services.Servers.GetDomains(PanelSecurity.PackageId); - string zoneName = string.Empty; - foreach (DomainInfo d in domains) - { - if (d.WebSiteId == SiteId) - { - zoneName = d.ZoneName; - break; - } - } - - // - BindListOfAvailableSslDomains(webSite.Name, zoneName); - - if (certificates.Length > 0) - { - foreach (SSLCertificate cert in certificates) - { - if (cert.Installed) - { - hasactive = true; - } - else - { - haspending = true; - } - } - } - - // Web site has active certificate - if (hasactive) - { - tabInstalled.Visible = true; - tabInstalled.Enabled = true; - tabInstalled.HeaderText = GetLocalizedString("tabInstalled.Text"); - - InstalledCert = (from c in certificates - where c.Installed == true - select c).SingleOrDefault(); - // - BindCertificateFields(); - // Attention please, the certificate is about to expire! - TimeSpan daystoexp = DateTime.Now - InstalledCert.ExpiryDate; - if (daystoexp.Days < 30) - { - lblInstalledExpiration.ForeColor = System.Drawing.Color.Red; - } - // Put some data to the ViewState - ViewState["SSLID"] = InstalledCert.id; - ViewState["SSLSerial"] = InstalledCert.SerialNumber; - // - if (!haspending) - { - btnShowpnlCSR.Attributes.Add("OnClientClick", "return confirm('" + GetLocalizedString("btnInstallConfirm.Text") + "');"); - btnShowUpload.Attributes.Add("OnClientClick", "return confirm('" + GetLocalizedString("btnInstallConfirm.Text") + "');"); - SSLNotInstalledHeading.Text = GetLocalizedString("SSLInstalledNewHeading.Text"); - SSLNotInstalledDescription.Text = GetLocalizedString("SSLInstalledNewDescription.Text"); - } - } - - // Web site has pending certificate - if (haspending) - { - tabCSR.HeaderText = GetLocalizedString("tabPendingCertificate.HeaderText");//"Pending Certificate"; - SSLNotInstalled.Visible = false; - pnlInstallCertificate.Visible = true; - SSLCertificate pending = (from c in certificates - where c.Installed == false - select c).Single(); - ViewState["CSRID"] = pending.id; - txtCSR.Text = pending.CSR; - txtCSR.Attributes.Add("onfocus", "this.select();"); - if (InstalledCert != null) - { - btnInstallCertificate.Attributes.Add("OnClientClick", "return confirm('" + GetLocalizedString("btnInstallConfirm.Text") + "');"); - } - } - - if (!hasactive && ES.Services.WebServers.CheckCertificate(item.Id).IsSuccess) - { - SSLNotInstalled.Visible = false; - SSLImport.Visible = true; - } - } - catch (Exception ex) - { - messageBox.ShowErrorMessage("WEB_GET_SSL", ex); - } + RefreshControlLayout(); } protected void btnShowpnlCSR_click(object sender, EventArgs e) @@ -271,7 +183,8 @@ namespace WebsitePanel.Portal L={3}, S={4}, C={5}", - rbSiteCertificate.Checked ? rbSiteCertificate.Text : rbDomainCertificate.Text, + //rbSiteCertificate.Checked ? rbSiteCertificate.Text : rbDomainCertificate.Text, + ddlbSiteCertificate.SelectedValue, txtCompany.Text, txtOU.Text, txtCity.Text, @@ -279,7 +192,7 @@ namespace WebsitePanel.Portal lstCountries.SelectedValue); SSLCertificate certificate = new SSLCertificate(); - certificate.Hostname = rbSiteCertificate.Checked ? rbSiteCertificate.Text : rbDomainCertificate.Text; + certificate.Hostname = ddlbSiteCertificate.SelectedValue; //rbSiteCertificate.Checked ? rbSiteCertificate.Text : rbDomainCertificate.Text; certificate.DistinguishedName = distinguishedName; certificate.CSRLength = Convert.ToInt32(lstBits.SelectedValue); certificate.Organisation = txtCompany.Text; @@ -336,7 +249,7 @@ namespace WebsitePanel.Portal OU={2}, L={3}, S={4}, - C={5}", rbSiteCertificate.Checked ? rbSiteCertificate.Text : rbDomainCertificate.Text, + C={5}", ddlbSiteCertificate.SelectedValue, //rbSiteCertificate.Checked ? rbSiteCertificate.Text : rbDomainCertificate.Text, txtCompany.Text, txtOU.Text, txtCity.Text, @@ -344,7 +257,7 @@ namespace WebsitePanel.Portal lstCountries.SelectedValue); SSLCertificate certificate = new SSLCertificate(); - certificate.Hostname = rbSiteCertificate.Checked ? rbSiteCertificate.Text : rbDomainCertificate.Text; + certificate.Hostname = ddlbSiteCertificate.SelectedValue; //rbSiteCertificate.Checked ? rbSiteCertificate.Text : rbDomainCertificate.Text; certificate.DistinguishedName = distinguishedName; certificate.CSRLength = Convert.ToInt32(lstBits.SelectedValue); certificate.Organisation = txtCompany.Text; @@ -369,7 +282,7 @@ namespace WebsitePanel.Portal pnlCSR.Visible = false; ViewState["CSRID"] = certificate.id; txtCSR.Attributes.Add("onfocus", "this.select();"); - RefreshControlLayout(PanelRequest.ItemID); + RefreshControlLayout(); TabContainer1.ActiveTab = TabContainer1.Tabs[0]; messageBox.ShowSuccessMessage(WEB_GEN_CSR); } @@ -402,7 +315,7 @@ namespace WebsitePanel.Portal // TabContainer1.ActiveTab = tabInstalled; - RefreshControlLayout(webSiteId); + RefreshControlLayout(); } protected void btnInstallPFX_Click(object sender, EventArgs e) @@ -428,13 +341,14 @@ namespace WebsitePanel.Portal if (result.IsSuccess.Equals(false)) { messageBox.ShowErrorMessage("WEB_INSTALL_CSR"); - return; + RefreshControlLayout(); + return; } // messageBox.ShowSuccessMessage("WEB_INSTALL_CSR"); SSLNotInstalled.Visible = false; tabInstalled.Visible = true; - RefreshControlLayout(SiteId); + RefreshControlLayout(); } protected void BindCertificateFields() @@ -560,43 +474,43 @@ namespace WebsitePanel.Portal if (!result.IsSuccess) { messageBox.ShowErrorMessage("WEB_INSTALL_CSR"); + RefreshControlLayout(); return; } // Show success message and display appropriate controls messageBox.ShowSuccessMessage("WEB_INSTALL_CSR"); - SSLNotInstalled.Visible = false; - tabInstalled.Visible = true; - // - RefreshControlLayout(webSiteId); + + RefreshControlLayout(); } - protected void RefreshControlLayout(int webSiteId) + public void RefreshControlLayout() { - bool hasActiveCert = false; - bool hasPendingCert = false; - // + // + bool hasactive = false; + bool haspending = false; + try { - SSLCertificate[] certificates = ES.Services.WebServers.GetCertificatesForSite(webSiteId); + var webSite = ES.Services.WebServers.GetWebSite(SiteId); - WebSite item = ES.Services.WebServers.GetWebSite(webSiteId); + // Get all certificate infos stored in database + SSLCertificate[] certificates = ES.Services.WebServers.GetCertificatesForSite(SiteId); - SSLNotInstalled.Visible = true; - // + // Set some default visible values, states and texts + tabInstalled.Visible = false; + tabInstalled.Enabled = false; + SSLNotInstalled.Visible = true; + SSLImport.Visible = false; + pnlCSR.Visible = false; + pnlShowUpload.Visible = false; + pnlInstallCertificate.Visible = false; - DomainInfo[] domains = ES.Services.Servers.GetDomains(PanelSecurity.PackageId); - string zoneName = string.Empty; - foreach (DomainInfo d in domains) - { - if (d.WebSiteId == item.Id) - { - zoneName = d.ZoneName; - break; - } - } + btnShowpnlCSR.Attributes.Remove("OnClientClick"); + btnShowUpload.Attributes.Remove("OnClientClick"); + SSLNotInstalledHeading.Text = GetLocalizedString("SSLNotInstalledHeading.Text"); + SSLNotInstalledDescription.Text = GetLocalizedString("SSLNotInstalledDescription.Text"); - // - BindListOfAvailableSslDomains(item.Name, zoneName); + BindListOfAvailableSslDomains(webSite.Name); if (certificates.Length > 0) { @@ -604,16 +518,17 @@ namespace WebsitePanel.Portal { if (cert.Installed) { - hasActiveCert = true; + hasactive = true; } else { - hasPendingCert = true; + haspending = true; } } } - if (hasActiveCert) + // Web site has active certificate + if (hasactive) { tabInstalled.Visible = true; tabInstalled.Enabled = true; @@ -622,18 +537,19 @@ namespace WebsitePanel.Portal InstalledCert = (from c in certificates where c.Installed == true select c).SingleOrDefault(); - - TimeSpan daystoexp = DateTime.Now - InstalledCert.ExpiryDate; - - BindCertificateFields(); // - bool certAbout2Exp = daystoexp.Days < 30 - ? lblInstalledExpiration.ForeColor == System.Drawing.Color.Red - : lblInstalledExpiration.ForeColor == System.Drawing.Color.Black; + BindCertificateFields(); + // Attention please, the certificate is about to expire! + TimeSpan daystoexp = InstalledCert.ExpiryDate - DateTime.Now; + if (daystoexp.Days < 30) + { + lblInstalledExpiration.ForeColor = System.Drawing.Color.Red; + } + // Put some data to the ViewState ViewState["SSLID"] = InstalledCert.id; ViewState["SSLSerial"] = InstalledCert.SerialNumber; - - if (!hasPendingCert) + // + if (!haspending) { btnShowpnlCSR.Attributes.Add("OnClientClick", "return confirm('" + GetLocalizedString("btnInstallConfirm.Text") + "');"); btnShowUpload.Attributes.Add("OnClientClick", "return confirm('" + GetLocalizedString("btnInstallConfirm.Text") + "');"); @@ -642,9 +558,10 @@ namespace WebsitePanel.Portal } } - if (hasPendingCert) + // Web site has pending certificate + if (haspending) { - tabCSR.HeaderText = GetLocalizedString("tabPendingCertificate.HeaderText"); + tabCSR.HeaderText = GetLocalizedString("tabPendingCertificate.HeaderText");//"Pending Certificate"; SSLNotInstalled.Visible = false; pnlInstallCertificate.Visible = true; SSLCertificate pending = (from c in certificates @@ -653,12 +570,17 @@ namespace WebsitePanel.Portal ViewState["CSRID"] = pending.id; txtCSR.Text = pending.CSR; txtCSR.Attributes.Add("onfocus", "this.select();"); - if (InstalledCert != null) { btnInstallCertificate.Attributes.Add("OnClientClick", "return confirm('" + GetLocalizedString("btnInstallConfirm.Text") + "');"); } } + + if (!hasactive && ES.Services.WebServers.CheckCertificate(SiteId).IsSuccess) + { + SSLNotInstalled.Visible = false; + SSLImport.Visible = true; + } } catch (Exception ex) { @@ -668,7 +590,10 @@ namespace WebsitePanel.Portal protected void SetCertHostnameSelection(string hostname) { - rbSiteCertificate.Checked = (rbSiteCertificate.Text == hostname); + if (ddlbSiteCertificate.Items.Contains(new ListItem(hostname))) + { + ddlbSiteCertificate.SelectedValue = hostname; + } } protected void SetCertCountrySelection(string country) @@ -701,5 +626,33 @@ namespace WebsitePanel.Portal listCtl.ClearSelection(); li.Selected = true; } - } + + protected void btnCancelRequest_Click(object sender, EventArgs e) + { + ResultObject result = null; + try + { + result = ES.Services.WebServers.DeleteCertificateRequest(SiteId, (int)ViewState["CSRID"]); + } + catch (Exception ex) + { + messageBox.ShowErrorMessage(WEB_SSL_DELETE, ex); + } + // + if (!result.IsSuccess) + { + messageBox.ShowErrorMessage(WEB_SSL_DELETE); + return; + } + // + SSLNotInstalled.Visible = true; + pnlCSR.Visible = false; + pnlInstallCertificate.Visible = false; + } + + protected void btnDeleteAll_Click(object sender, EventArgs e) + { + DeleteCertificate(SiteId, new SSLCertificate()); + } + } } \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebsitesSSL.ascx.designer.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebsitesSSL.ascx.designer.cs index a6707def..0434502a 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebsitesSSL.ascx.designer.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/WebsitesSSL.ascx.designer.cs @@ -1,32 +1,4 @@ -// Copyright (c) 2014, Outercurve Foundation. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// - Redistributions of source code must retain the above copyright notice, this -// list of conditions and the following disclaimer. -// -// - Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// -// - Neither the name of the Outercurve Foundation nor the names of its -// contributors may be used to endorse or promote products derived from this -// software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ // // This code was generated by a tool. // @@ -355,6 +327,15 @@ namespace WebsitePanel.Portal { /// protected global::System.Web.UI.WebControls.Button btnImport; + /// + /// btnDeleteAll control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Button btnDeleteAll; + /// /// pnlCSR control. /// @@ -374,22 +355,13 @@ namespace WebsitePanel.Portal { protected global::System.Web.UI.WebControls.Localize SelectCertType; /// - /// rbSiteCertificate control. + /// ddlbSiteCertificate control. /// /// /// Auto-generated field. /// To modify move field declaration from designer file to code-behind file. /// - protected global::System.Web.UI.WebControls.RadioButton rbSiteCertificate; - - /// - /// rbDomainCertificate control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.RadioButton rbDomainCertificate; + protected global::System.Web.UI.WebControls.DropDownList ddlbSiteCertificate; /// /// sslBitLength control. @@ -678,5 +650,14 @@ namespace WebsitePanel.Portal { /// To modify move field declaration from designer file to code-behind file. /// protected global::System.Web.UI.WebControls.Button btnInstallCertificate; + + /// + /// btnCancelRequest control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Button btnCancelRequest; } }