IIS SSL updates, mostly SNI/CCS-related, but also a lot of UI fixes/improvements

This commit is contained in:
Olov Karlsson 2014-11-30 09:13:06 +01:00
parent 25fdedd221
commit eb9b311bba
5 changed files with 299 additions and 344 deletions

View file

@ -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<SSLCertificate> 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)
@ -207,79 +201,35 @@ 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();
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();
}
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);
AddBinding(x509Cert, 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;
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,23 +269,36 @@ 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<string>();
if (!dedicatedIp)
{
hostNames.AddRange(from extension in certificate.Extensions.Cast<X509Extension>() 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.Hash, store.Name);
srvman.Sites[website.SiteId].Bindings.Add(bindingInformation, certificate.GetCertHash(), CertificateStoreName);
if (UseSNI)
if (UseSNI && !dedicatedIp)
{
siteBinding.SslFlags |= SslFlags.Sni;
}
@ -343,8 +306,7 @@ namespace WebsitePanel.Providers.Web.Iis
{
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,9 +325,19 @@ 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<Tuple<string, byte[]>>();
// User servermanager to get aLL SSL-bindings on this website and try to remove the certificates used
using (var srvman = GetServerManager())
{
var site = srvman.Sites[website.Name];
var bindings = site.Bindings.Where(b => b.Protocol == "https");
foreach (Binding binding in bindings.ToList())
{
if (binding.SslFlags.HasFlag(SslFlags.CentralCertStore))
{
if (!string.IsNullOrWhiteSpace(CCSUncPath) && Directory.Exists(CCSUncPath))
{
// This is where it will be if CCS is used
@ -372,24 +346,49 @@ namespace WebsitePanel.Providers.Web.Iis
{
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<string, byte[]>(binding.CertificateStoreName, binding.CertificateHash);
if (!string.IsNullOrEmpty(binding.CertificateStoreName) && !certificatesAndStoreNames.Contains(certificateAndStoreName))
{
certificatesAndStoreNames.Add(certificateAndStoreName);
}
}
// Now delete all certs with the same serialnumber in WebHosting Store
var store = new X509Store(CertificateStoreName, StoreLocation.LocalMachine);
// Remove binding from site
site.Bindings.Remove(binding);
}
srvman.CommitChanges();
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);
var certs = store.Certificates.Find(X509FindType.FindBySerialNumber, certificate.SerialNumber, false);
var certs = store.Certificates.Find(X509FindType.FindByThumbprint, BitConverter.ToString(certificateAndStoreName.Item2).Replace("-", ""), false);
foreach (var cert in certs)
{
store.Remove(cert);
}
store.Close();
// Remove binding from site
if (CheckCertificate(website))
{
RemoveBinding(certificate, website);
}
}
}
catch (Exception ex)
@ -409,8 +408,6 @@ 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 (((SslFlags)Enum.Parse(typeof(SslFlags), sslBinding["sslFlags"].ToString())).HasFlag(SslFlags.CentralCertStore))
{
@ -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<X509Certificate2>().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<SSLCertificate> 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;
}
}
}

View file

@ -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)
{

View file

@ -141,6 +141,8 @@
<p class="Normal">
<asp:Localize ID="SSLImportDescription" runat="server" meta:resourcekey="SSLImportDescription" /></p>
<asp:Button ID="btnImport" meta:resourcekey="btnImport" CssClass="Button1" runat="server" OnClick="btnImport_click" />
<asp:Button ID="btnDeleteAll" runat="server" Text="Delete" meta:resourcekey="btnDelete"
CssClass="Button1" OnClick="btnDeleteAll_Click" />
</div>
</asp:Panel>
@ -151,13 +153,7 @@
<tr>
<td class="SubHead">
<asp:Localize ID="SelectCertType" runat="server" meta:resourcekey="SelectCertType" /></td>
<td class="NormalBold" ><asp:radiobutton id="rbSiteCertificate" GroupName="Content" Runat="server" Checked="True"></asp:radiobutton></td>
</tr>
<tr>
<td></td>
<td class="NormalBold" ><asp:radiobutton id="rbDomainCertificate" GroupName="Content" Runat="server" ></asp:radiobutton></td>
</tr>
<td class="NormalBold" ><asp:DropDownList id="ddlbSiteCertificate" GroupName="Content" Runat="server" Checked="True"></asp:DropDownList></td>
<tr>
<td class="SubHead">
<asp:Localize ID="sslBitLength" runat="server" meta:resourcekey="sslBitLength" /></td>
@ -173,7 +169,7 @@
<asp:Localize ID="sslOrganization" runat="server" meta:resourcekey="sslOrganization" /></td>
<td class="Normal">
<asp:TextBox ID="txtCompany" runat="server" /><asp:RequiredFieldValidator ID="SSLCompanyReq" Display="Dynamic" ValidationGroup="SSL" runat="server"
ControlToValidate="txtCompany" ErrorMessage="RequiredFieldValidator" /></td>
ControlToValidate="txtCompany" ErrorMessage="*" /></td>
</tr>
<tr>
<td class="SubHead">
@ -196,7 +192,7 @@
<asp:DropDownList ID="ddlStates" Runat="server" DataTextField="Text" DataValueField="Value" CssClass="NormalTextBox"
Width="200px" Visible="false" />
<asp:RequiredFieldValidator ID="SSLSSLStateReq" ValidationGroup="SSL" runat="server"
ControlToValidate="txtState" Display="Dynamic" /></td>
ControlToValidate="txtState" Display="Dynamic" ErrorMessage="*" /></td>
</tr>
<tr>
<td class="SubHead">
@ -204,7 +200,7 @@
<td class="Normal">
<asp:TextBox ID="txtCity" runat="server" />
<asp:RequiredFieldValidator ID="SSLCityReq" ValidationGroup="SSL" runat="server"
ControlToValidate="txtCity" ErrorMessage="RequiredFieldValidator" /></td>
ControlToValidate="txtCity" ErrorMessage="*" /></td>
</tr>
</table>
<br />
@ -254,6 +250,8 @@
<br />
<asp:Button ID="btnInstallCertificate" meta:resourcekey="btnInstallCertificate" runat="server"
CssClass="Button1" Text="Install" OnClick="btnInstallCertificate_Click" />
<asp:Button ID="btnCancelRequest" runat="server" OnClientClick="return confirm('Are you Sure? This will delete the current request.');"
CssClass="Button1" Text="Cancel request" OnClick="btnCancelRequest_Click" />
</div>
</asp:Panel>
</ContentTemplate>

View file

@ -135,10 +135,18 @@ namespace WebsitePanel.Portal
}
}
private void BindListOfAvailableSslDomains(string websiteName, string domainName)
private void BindListOfAvailableSslDomains(string defaultBindingName)
{
rbSiteCertificate.Text = websiteName;
rbDomainCertificate.Text = "*." + domainName;
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);
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");
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);
// 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());
}
}
}

View file

@ -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.
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
@ -355,6 +327,15 @@ namespace WebsitePanel.Portal {
/// </remarks>
protected global::System.Web.UI.WebControls.Button btnImport;
/// <summary>
/// btnDeleteAll control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.Button btnDeleteAll;
/// <summary>
/// pnlCSR control.
/// </summary>
@ -374,22 +355,13 @@ namespace WebsitePanel.Portal {
protected global::System.Web.UI.WebControls.Localize SelectCertType;
/// <summary>
/// rbSiteCertificate control.
/// ddlbSiteCertificate control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.RadioButton rbSiteCertificate;
/// <summary>
/// rbDomainCertificate control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.RadioButton rbDomainCertificate;
protected global::System.Web.UI.WebControls.DropDownList ddlbSiteCertificate;
/// <summary>
/// sslBitLength control.
@ -678,5 +650,14 @@ namespace WebsitePanel.Portal {
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.Button btnInstallCertificate;
/// <summary>
/// btnCancelRequest control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.Button btnCancelRequest;
}
}