IIS SSL updates, mostly SNI/CCS-related, but also a lot of UI fixes/improvements
This commit is contained in:
parent
25fdedd221
commit
eb9b311bba
5 changed files with 299 additions and 344 deletions
|
@ -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)
|
||||
|
@ -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<string>();
|
||||
|
||||
Binding siteBinding = UseCCS ?
|
||||
srvman.Sites[website.SiteId].Bindings.Add(bindingInformation, "https") :
|
||||
srvman.Sites[website.SiteId].Bindings.Add(bindingInformation, certificate.Hash, store.Name);
|
||||
|
||||
if (UseSNI)
|
||||
if (!dedicatedIp)
|
||||
{
|
||||
siteBinding.SslFlags |= SslFlags.Sni;
|
||||
}
|
||||
if (UseCCS)
|
||||
{
|
||||
siteBinding.SslFlags |= SslFlags.CentralCertStore;
|
||||
hostNames.AddRange(from extension in certificate.Extensions.Cast<X509Extension>() where extension.Oid.FriendlyName == "Subject Alternative Name" select extension.Format(true));
|
||||
}
|
||||
|
||||
store.Close();
|
||||
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 && !dedicatedIp)
|
||||
{
|
||||
siteBinding.SslFlags |= SslFlags.Sni;
|
||||
}
|
||||
if (UseCCS)
|
||||
{
|
||||
siteBinding.SslFlags |= SslFlags.CentralCertStore;
|
||||
}
|
||||
}
|
||||
|
||||
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<Tuple<string, byte[]>>();
|
||||
|
||||
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<string, byte[]>(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<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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue