merge commit
This commit is contained in:
commit
0b7831549d
41 changed files with 7095 additions and 4821 deletions
|
@ -192,10 +192,10 @@ namespace WebsitePanel.EnterpriseServer
|
|||
try
|
||||
{
|
||||
TaskManager.StartTask("ENTERPRISE_STORAGE", taskName, org.PackageId);
|
||||
|
||||
|
||||
EnterpriseStorageController.SetFRSMQuotaOnFolder(itemId, folder.Name, quota, quotaType);
|
||||
EnterpriseStorageController.SetDirectoryBrowseEnabled(itemId, folder.Url, directoyBrowsingEnabled);
|
||||
EnterpriseStorageController.SetFolderPermission(itemId, folder.Name, permissions);
|
||||
EnterpriseStorageController.SetFRSMQuotaOnFolder(itemId, folder.Name, quota, quotaType);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
|
@ -586,6 +586,7 @@ namespace WebsitePanel.EnterpriseServer
|
|||
List<ExchangeDomainName> acceptedDomains = GetOrganizationDomains(itemId);
|
||||
|
||||
int exchangeServiceId = GetExchangeServiceID(org.PackageId);
|
||||
|
||||
ExchangeServer exchange = GetExchangeServer(exchangeServiceId, org.ServiceId);
|
||||
|
||||
bool successful = exchange.DeleteOrganization(
|
||||
|
@ -599,6 +600,18 @@ namespace WebsitePanel.EnterpriseServer
|
|||
org.AddressBookPolicy,
|
||||
acceptedDomains.ToArray());
|
||||
|
||||
// delete public folders
|
||||
if (successful)
|
||||
{
|
||||
List<ExchangeAccount> folders = GetAccounts(itemId, ExchangeAccountType.PublicFolder);
|
||||
folders.Sort(delegate(ExchangeAccount f1, ExchangeAccount f2) { return f2.AccountId.CompareTo(f1.AccountId);});
|
||||
|
||||
foreach(ExchangeAccount folder in folders)
|
||||
DeletePublicFolder(itemId, folder.AccountId);
|
||||
|
||||
exchange.DeletePublicFolder(org.OrganizationId, "\\" + org.OrganizationId);
|
||||
}
|
||||
|
||||
|
||||
return successful ? 0 : BusinessErrorCodes.ERROR_EXCHANGE_DELETE_SOME_PROBLEMS;
|
||||
}
|
||||
|
@ -1782,7 +1795,9 @@ namespace WebsitePanel.EnterpriseServer
|
|||
//GetServiceSettings
|
||||
StringDictionary primSettings = ServerController.GetServiceSettings(exchangeServiceId);
|
||||
|
||||
string samAccount = exchange.CreateMailEnableUser(email, org.OrganizationId, org.DistinguishedName, accountType, primSettings["mailboxdatabase"],
|
||||
string samAccount = exchange.CreateMailEnableUser(email, org.OrganizationId, org.DistinguishedName,
|
||||
org.SecurityGroup, org.DefaultDomain,
|
||||
accountType, primSettings["mailboxdatabase"],
|
||||
org.OfflineAddressBook,
|
||||
org.AddressBookPolicy,
|
||||
retUser.SamAccountName,
|
||||
|
@ -5317,6 +5332,54 @@ namespace WebsitePanel.EnterpriseServer
|
|||
TaskManager.CompleteTask();
|
||||
}
|
||||
}
|
||||
|
||||
public static string CreateOrganizationRootPublicFolder(int itemId)
|
||||
{
|
||||
string res = null;
|
||||
|
||||
// place log record
|
||||
TaskManager.StartTask("EXCHANGE", "CREATE_ORG_PUBLIC_FOLDER", itemId);
|
||||
|
||||
try
|
||||
{
|
||||
// load organization
|
||||
Organization org = GetOrganization(itemId);
|
||||
if (org == null)
|
||||
return null;
|
||||
|
||||
// get mailbox settings
|
||||
int exchangeServiceId = GetExchangeServiceID(org.PackageId);
|
||||
|
||||
if (exchangeServiceId <= 0)
|
||||
return null;
|
||||
|
||||
ExchangeServer exchange = GetExchangeServer(exchangeServiceId, org.ServiceId);
|
||||
|
||||
if (exchange == null)
|
||||
return null;
|
||||
|
||||
//Create Exchange Organization
|
||||
if (string.IsNullOrEmpty(org.GlobalAddressList))
|
||||
{
|
||||
ExtendToExchangeOrganization(ref org);
|
||||
|
||||
PackageController.UpdatePackageItem(org);
|
||||
}
|
||||
|
||||
res = exchange.CreateOrganizationRootPublicFolder(org.OrganizationId, org.DistinguishedName, org.SecurityGroup, org.DefaultDomain);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw TaskManager.WriteError(ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
TaskManager.CompleteTask();
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Helpers
|
||||
|
|
|
@ -419,6 +419,9 @@ namespace WebsitePanel.EnterpriseServer
|
|||
};
|
||||
|
||||
PackageController.AddPackageItem(orgDomain);
|
||||
|
||||
ExchangeServerController.CreateOrganizationRootPublicFolder(itemId);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
|
@ -37,7 +37,9 @@ namespace WebsitePanel.Providers.HostedSolution
|
|||
bool CheckAccountCredentials(string username, string password);
|
||||
// Organizations
|
||||
|
||||
string CreateMailEnableUser(string upn, string organizationId, string organizationDistinguishedName, ExchangeAccountType accountType,
|
||||
string CreateMailEnableUser(string upn, string organizationId, string organizationDistinguishedName,
|
||||
string securityGroup, string organizationDomain,
|
||||
ExchangeAccountType accountType,
|
||||
string mailboxDatabase, string offlineAddressBook, string addressBookPolicy,
|
||||
string accountName, bool enablePOP, bool enableIMAP,
|
||||
bool enableOWA, bool enableMAPI, bool enableActiveSync,
|
||||
|
@ -74,6 +76,8 @@ namespace WebsitePanel.Providers.HostedSolution
|
|||
void SetMailboxPermissions(string organizationId, string accountName, string[] sendAsAccounts, string[] fullAccessAccounts);
|
||||
ExchangeMailbox GetMailboxPermissions(string organizationId, string accountName);
|
||||
ExchangeMailboxStatistics GetMailboxStatistics(string accountName);
|
||||
string[] SetDefaultPublicFolderMailbox(string id, string organizationId, string organizationDistinguishedName);
|
||||
|
||||
|
||||
// Contacts
|
||||
void CreateContact(string organizationId, string organizationDistinguishedName, string contactDisplayName, string contactAccountName, string contactEmail, string defaultOrganizationDomain);
|
||||
|
@ -113,6 +117,8 @@ namespace WebsitePanel.Providers.HostedSolution
|
|||
ExchangeItemStatistics[] GetPublicFoldersStatistics(string organizationId, string[] folders);
|
||||
string[] GetPublicFoldersRecursive(string organizationId, string parent);
|
||||
long GetPublicFolderSize(string organizationId, string folder);
|
||||
string CreateOrganizationRootPublicFolder(string organizationId, string organizationDistinguishedName, string securityGroup, string organizationDomain);
|
||||
|
||||
|
||||
//ActiveSync
|
||||
void CreateOrganizationActiveSyncPolicy(string organizationId);
|
||||
|
|
|
@ -63,6 +63,7 @@ namespace WebsitePanel.Providers.Web
|
|||
private bool heliconApeInstalled;
|
||||
private bool heliconApeEnabled;
|
||||
private HeliconApeStatus heliconApeStatus;
|
||||
private bool sniEnabled;
|
||||
|
||||
public WebSite()
|
||||
{
|
||||
|
@ -187,6 +188,12 @@ namespace WebsitePanel.Providers.Web
|
|||
get { return this.heliconApeStatus; }
|
||||
set { this.heliconApeStatus = value; }
|
||||
}
|
||||
|
||||
public bool SniEnabled
|
||||
{
|
||||
get { return this.sniEnabled; }
|
||||
set { this.sniEnabled = value; }
|
||||
}
|
||||
}
|
||||
|
||||
[Flags]
|
||||
|
|
|
@ -1871,14 +1871,18 @@ namespace WebsitePanel.Providers.HostedSolution
|
|||
}
|
||||
|
||||
|
||||
public string CreateMailEnableUser(string upn, string organizationId, string organizationDistinguishedName, ExchangeAccountType accountType,
|
||||
public string CreateMailEnableUser(string upn, string organizationId, string organizationDistinguishedName,
|
||||
string securityGroup, string organizationDomain,
|
||||
ExchangeAccountType accountType,
|
||||
string mailboxDatabase, string offlineAddressBook, string addressBookPolicy,
|
||||
string accountName, bool enablePOP, bool enableIMAP,
|
||||
bool enableOWA, bool enableMAPI, bool enableActiveSync,
|
||||
long issueWarningKB, long prohibitSendKB, long prohibitSendReceiveKB, int keepDeletedItemsDays,
|
||||
int maxRecipients, int maxSendMessageSizeKB, int maxReceiveMessageSizeKB, bool hideFromAddressBook, bool IsConsumer, bool enabledLitigationHold, long recoverabelItemsSpace, long recoverabelItemsWarning)
|
||||
{
|
||||
return CreateMailEnableUserInternal(upn, organizationId, organizationDistinguishedName, accountType,
|
||||
return CreateMailEnableUserInternal(upn, organizationId, organizationDistinguishedName,
|
||||
securityGroup, organizationDomain,
|
||||
accountType,
|
||||
mailboxDatabase, offlineAddressBook, addressBookPolicy,
|
||||
accountName, enablePOP, enableIMAP,
|
||||
enableOWA, enableMAPI, enableActiveSync,
|
||||
|
@ -1886,7 +1890,9 @@ namespace WebsitePanel.Providers.HostedSolution
|
|||
keepDeletedItemsDays, maxRecipients, maxSendMessageSizeKB, maxReceiveMessageSizeKB, hideFromAddressBook, IsConsumer, enabledLitigationHold, recoverabelItemsSpace, recoverabelItemsWarning);
|
||||
}
|
||||
|
||||
internal virtual string CreateMailEnableUserInternal(string upn, string organizationId, string organizationDistinguishedName, ExchangeAccountType accountType,
|
||||
internal virtual string CreateMailEnableUserInternal(string upn, string organizationId, string organizationDistinguishedName,
|
||||
string securityGroup, string organizationDomain,
|
||||
ExchangeAccountType accountType,
|
||||
string mailboxDatabase, string offlineAddressBook, string addressBookPolicy,
|
||||
string accountName, bool enablePOP, bool enableIMAP,
|
||||
bool enableOWA, bool enableMAPI, bool enableActiveSync,
|
||||
|
@ -1955,8 +1961,19 @@ namespace WebsitePanel.Providers.HostedSolution
|
|||
|
||||
transaction.RegisterEnableMailbox(id);
|
||||
|
||||
// default public folder
|
||||
string orgCanonicalName = ConvertADPathToCanonicalName(organizationDistinguishedName);
|
||||
|
||||
//create organization public folder mailbox if required
|
||||
CheckOrganizationPublicFolderMailbox(runSpace, orgCanonicalName, organizationId, organizationDomain);
|
||||
|
||||
//create organization root folder if required
|
||||
CheckOrganizationRootFolder(runSpace, organizationId, securityGroup, orgCanonicalName, organizationId);
|
||||
|
||||
string windowsEmailAddress = ObjToString(GetPSObjectProperty(result[0], "WindowsEmailAddress"));
|
||||
|
||||
string defaultPublicFolderMailbox = orgCanonicalName + "/" + GetPublicFolderMailboxName(organizationId);
|
||||
|
||||
//update mailbox
|
||||
cmd = new Command("Set-Mailbox");
|
||||
cmd.Parameters.Add("Identity", id);
|
||||
|
@ -1987,6 +2004,8 @@ namespace WebsitePanel.Providers.HostedSolution
|
|||
cmd.Parameters.Add("RecoverableItemsWarningQuota", ConvertKBToUnlimited(recoverabelItemsWarning));
|
||||
}
|
||||
|
||||
cmd.Parameters.Add("DefaultPublicFolderMailbox", defaultPublicFolderMailbox);
|
||||
|
||||
ExecuteShellCommand(runSpace, cmd);
|
||||
|
||||
//Litigation Hold
|
||||
|
@ -4441,8 +4460,6 @@ namespace WebsitePanel.Providers.HostedSolution
|
|||
ExchangeLog.LogEnd("CheckOrganizationPublicFolderMailbox");
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void CheckOrganizationRootFolder(Runspace runSpace, string folder, string user, string orgCanonicalName, string organizationId)
|
||||
{
|
||||
ExchangeLog.LogStart("CheckOrganizationRootFolder");
|
||||
|
@ -4467,6 +4484,48 @@ namespace WebsitePanel.Providers.HostedSolution
|
|||
ExchangeLog.LogEnd("CheckOrganizationRootFolder");
|
||||
}
|
||||
|
||||
private void CheckOrganizationRootPublicFolderPermission(Runspace runSpace, string organizationId)
|
||||
{
|
||||
string rootFolder = "\\" + organizationId;
|
||||
|
||||
// exchange transport needs access to create new items in order to deliver email
|
||||
AddPublicFolderClientPermission(runSpace, rootFolder, "Anonymous", "CreateItems");
|
||||
}
|
||||
|
||||
public string CreateOrganizationRootPublicFolder(string organizationId, string organizationDistinguishedName, string securityGroup, string organizationDomain)
|
||||
{
|
||||
ExchangeLog.LogStart("CreateOrganizationRootPublicFolder");
|
||||
|
||||
string res = null;
|
||||
|
||||
Runspace runSpace = null;
|
||||
try
|
||||
{
|
||||
runSpace = OpenRunspace();
|
||||
|
||||
// default public folder
|
||||
string orgCanonicalName = ConvertADPathToCanonicalName(organizationDistinguishedName);
|
||||
|
||||
//create organization public folder mailbox if required
|
||||
CheckOrganizationPublicFolderMailbox(runSpace, orgCanonicalName, organizationId, organizationDomain);
|
||||
|
||||
//create organization root folder if required
|
||||
CheckOrganizationRootFolder(runSpace, organizationId, securityGroup, orgCanonicalName, organizationId);
|
||||
|
||||
res = orgCanonicalName + "/" + GetPublicFolderMailboxName(organizationId);
|
||||
|
||||
CheckOrganizationRootPublicFolderPermission(runSpace, organizationId);
|
||||
}
|
||||
finally
|
||||
{
|
||||
CloseRunspace(runSpace);
|
||||
}
|
||||
|
||||
ExchangeLog.LogEnd("CreateOrganizationRootPublicFolder");
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
private string AddPublicFolder(Runspace runSpace, string name, string path, string mailbox)
|
||||
{
|
||||
ExchangeLog.LogStart("CreatePublicFolder");
|
||||
|
@ -4697,9 +4756,7 @@ namespace WebsitePanel.Providers.HostedSolution
|
|||
System.Threading.Thread.Sleep(5000);
|
||||
}
|
||||
|
||||
// exchange transport needs access to create new items in order to deliver email
|
||||
AddPublicFolderClientPermission(runSpace, folder, "Anonymous", "CreateItems");
|
||||
|
||||
CheckOrganizationRootPublicFolderPermission(runSpace, organizationId);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -5209,6 +5266,54 @@ namespace WebsitePanel.Providers.HostedSolution
|
|||
return size;
|
||||
}
|
||||
|
||||
public string[] SetDefaultPublicFolderMailbox(string id, string organizationId, string organizationDistinguishedName)
|
||||
{
|
||||
ExchangeLog.LogStart("SetDefaultPublicFolderMailbox");
|
||||
|
||||
List<string> res = new List<string>();
|
||||
|
||||
Runspace runSpace = null;
|
||||
try
|
||||
{
|
||||
runSpace = OpenRunspace();
|
||||
|
||||
Command cmd = new Command("Get-Mailbox");
|
||||
cmd.Parameters.Add("Identity", id);
|
||||
Collection<PSObject> result = ExecuteShellCommand(runSpace, cmd);
|
||||
|
||||
string oldValue = "";
|
||||
|
||||
if (result != null && result.Count > 0)
|
||||
{
|
||||
oldValue = ObjToString(GetPSObjectProperty(result[0], "DefaultPublicFolderMailbox"));
|
||||
}
|
||||
|
||||
res.Add(oldValue);
|
||||
|
||||
string orgCanonicalName = ConvertADPathToCanonicalName(organizationDistinguishedName);
|
||||
|
||||
string newValue = orgCanonicalName + "/" + GetPublicFolderMailboxName(organizationId);
|
||||
|
||||
if (newValue != oldValue)
|
||||
{
|
||||
cmd = new Command("Set-Mailbox");
|
||||
cmd.Parameters.Add("Identity", id);
|
||||
cmd.Parameters.Add("DefaultPublicFolderMailbox", newValue);
|
||||
|
||||
res.Add(newValue);
|
||||
}
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
CloseRunspace(runSpace);
|
||||
}
|
||||
|
||||
ExchangeLog.LogEnd("SetDefaultPublicFolderMailbox");
|
||||
return res.ToArray();
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Address Lists (GAL, AL, RAL, OAB, ABP)
|
||||
|
|
|
@ -1784,7 +1784,9 @@ namespace WebsitePanel.Providers.HostedSolution
|
|||
}
|
||||
|
||||
|
||||
public string CreateMailEnableUser(string upn, string organizationId, string organizationDistinguishedName, ExchangeAccountType accountType,
|
||||
public string CreateMailEnableUser(string upn, string organizationId, string organizationDistinguishedName,
|
||||
string securityGroup, string organizationDomain,
|
||||
ExchangeAccountType accountType,
|
||||
string mailboxDatabase, string offlineAddressBook, string addressBookPolicy,
|
||||
string accountName, bool enablePOP, bool enableIMAP,
|
||||
bool enableOWA, bool enableMAPI, bool enableActiveSync,
|
||||
|
@ -4852,6 +4854,19 @@ namespace WebsitePanel.Providers.HostedSolution
|
|||
return size;
|
||||
}
|
||||
|
||||
public string CreateOrganizationRootPublicFolder(string organizationId, string organizationDistinguishedName, string securityGroup, string organizationDomain)
|
||||
{
|
||||
// not implemented
|
||||
return null;
|
||||
}
|
||||
|
||||
public string[] SetDefaultPublicFolderMailbox(string id, string organizationId, string organizationDistinguishedName)
|
||||
{
|
||||
// not implemented
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Address Lists (GAL, AL, RAL, OAB, ABP)
|
||||
|
|
|
@ -325,7 +325,8 @@ namespace WebsitePanel.Providers.HostedSolution
|
|||
#endregion
|
||||
|
||||
#region Mailbox
|
||||
internal override string CreateMailEnableUserInternal(string upn, string organizationId, string organizationDistinguishedName, ExchangeAccountType accountType,
|
||||
internal override string CreateMailEnableUserInternal(string upn, string organizationId, string organizationDistinguishedName,
|
||||
ExchangeAccountType accountType,
|
||||
string mailboxDatabase, string offlineAddressBook, string addressBookPolicy,
|
||||
string accountName, bool enablePOP, bool enableIMAP,
|
||||
bool enableOWA, bool enableMAPI, bool enableActiveSync,
|
||||
|
|
|
@ -43,7 +43,7 @@ namespace WebsitePanel.Providers.Web.Iis.Common
|
|||
/// We'll use it in the future to implement management of web farm with shared configuration enabled
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal ServerManager GetServerManager()
|
||||
protected internal ServerManager GetServerManager()
|
||||
{
|
||||
return new ServerManager();
|
||||
}
|
||||
|
|
|
@ -1240,6 +1240,7 @@ namespace WebsitePanel.Providers.Web
|
|||
//
|
||||
site.SiteState = GetSiteState(srvman, siteId);
|
||||
//
|
||||
site.SniEnabled = false;
|
||||
}
|
||||
return site;
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ using WebsitePanel.Providers.Web.Iis.WebObjects;
|
|||
|
||||
namespace WebsitePanel.Providers.Web.Iis
|
||||
{
|
||||
internal sealed class SSLModuleService : ConfigurationModuleService
|
||||
public class SSLModuleService : ConfigurationModuleService
|
||||
{
|
||||
public void GenerateCsr(SSLCertificate cert)
|
||||
{
|
||||
|
|
|
@ -26,18 +26,84 @@
|
|||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
using Microsoft.Web.Administration;
|
||||
using Microsoft.Win32;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using WebsitePanel.Providers.Common;
|
||||
using WebsitePanel.Providers.Web.Iis;
|
||||
|
||||
namespace WebsitePanel.Providers.Web
|
||||
{
|
||||
public class IIs80 : IIs70, IWebServer
|
||||
public class IIs80 : IIs70
|
||||
{
|
||||
public IIs80() : base()
|
||||
private SslFlags SSLFlags {
|
||||
get
|
||||
{
|
||||
return (UseSni ? SslFlags.Sni : SslFlags.None) | (UseCcs ? SslFlags.CentralCertStore : SslFlags.None);
|
||||
}
|
||||
}
|
||||
|
||||
public string CCSUncPath {
|
||||
get { return ProviderSettings["SSLCCSUNCPath"]; }
|
||||
}
|
||||
|
||||
public string CCSCommonPassword {
|
||||
get { return ProviderSettings["SSLCCSCommonPassword"]; }
|
||||
}
|
||||
|
||||
public bool UseSni {
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
return Convert.ToBoolean(ProviderSettings["SSLUseSNI"]);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool UseCcs
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
return Convert.ToBoolean(ProviderSettings["SSLUseCCS"]);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override SettingPair[] GetProviderDefaultSettings()
|
||||
{
|
||||
var allSettings = new List<SettingPair>();
|
||||
allSettings.AddRange(base.GetProviderDefaultSettings());
|
||||
|
||||
// Add these to get som default values in. These are also used a marker in the IIS70_Settings.ascx.cs to know that it is the IIS80 provider that is used
|
||||
allSettings.Add(new SettingPair("SSLUseCCS", false.ToString()));
|
||||
allSettings.Add(new SettingPair("SSLUseSNI", false.ToString()));
|
||||
allSettings.Add(new SettingPair("SSLCCSUNCPath", ""));
|
||||
allSettings.Add(new SettingPair("SSLCCSCommonPassword", ""));
|
||||
|
||||
return allSettings.ToArray();
|
||||
}
|
||||
|
||||
public override string[] Install()
|
||||
{
|
||||
var messages = new List<string>();
|
||||
|
||||
messages.AddRange(base.Install());
|
||||
|
||||
// TODO: Setup ccs
|
||||
|
||||
return messages.ToArray();
|
||||
}
|
||||
|
||||
public override bool IsIISInstalled()
|
||||
|
@ -58,5 +124,70 @@ namespace WebsitePanel.Providers.Web
|
|||
{
|
||||
return IsIISInstalled();
|
||||
}
|
||||
|
||||
public override bool CheckCertificate(WebSite webSite)
|
||||
{
|
||||
var sslObjectService = new SSLModuleService80(SSLFlags, CCSUncPath, CCSCommonPassword);
|
||||
|
||||
return sslObjectService.CheckCertificate(webSite);
|
||||
}
|
||||
|
||||
public override ResultObject DeleteCertificate(SSLCertificate certificate, WebSite website)
|
||||
{
|
||||
var sslObjectService = new SSLModuleService80(SSLFlags, CCSUncPath, CCSCommonPassword);
|
||||
|
||||
return sslObjectService.DeleteCertificate(certificate, website);
|
||||
}
|
||||
|
||||
public override SSLCertificate installPFX(byte[] certificate, string password, WebSite website)
|
||||
{
|
||||
var sslObjectService = new SSLModuleService80(SSLFlags, CCSUncPath, CCSCommonPassword);
|
||||
|
||||
return sslObjectService.InstallPfx(certificate, password, website);
|
||||
}
|
||||
|
||||
public override SSLCertificate ImportCertificate(WebSite website)
|
||||
{
|
||||
var sslObjectService = new SSLModuleService80(SSLFlags, CCSUncPath, CCSCommonPassword);
|
||||
|
||||
return sslObjectService.ImportCertificate(website);
|
||||
}
|
||||
|
||||
public override byte[] exportCertificate(string serialNumber, string password)
|
||||
{
|
||||
var sslObjectService = new SSLModuleService80(SSLFlags, CCSUncPath, CCSCommonPassword);
|
||||
|
||||
return sslObjectService.ExportPfx(serialNumber, password);
|
||||
}
|
||||
|
||||
public override SSLCertificate generateCSR(SSLCertificate certificate)
|
||||
{
|
||||
var sslObjectService = new SSLModuleService80(SSLFlags, CCSUncPath, CCSCommonPassword);
|
||||
|
||||
sslObjectService.GenerateCsr(certificate);
|
||||
|
||||
return certificate;
|
||||
}
|
||||
|
||||
public override List<SSLCertificate> getServerCertificates()
|
||||
{
|
||||
var sslObjectService = new SSLModuleService80(SSLFlags, CCSUncPath, CCSCommonPassword);
|
||||
|
||||
return sslObjectService.GetServerCertificates();
|
||||
}
|
||||
|
||||
public override SSLCertificate installCertificate(SSLCertificate certificate, WebSite website)
|
||||
{
|
||||
var sslObjectService = new SSLModuleService80(SSLFlags, CCSUncPath, CCSCommonPassword);
|
||||
|
||||
return sslObjectService.InstallCertificate(certificate, website);
|
||||
}
|
||||
|
||||
public override WebSite GetSite(string siteId)
|
||||
{
|
||||
var site = base.GetSite(siteId);
|
||||
site.SniEnabled = UseSni;
|
||||
return site;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,508 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using CertEnrollInterop;
|
||||
using WebsitePanel.Providers.Common;
|
||||
using WebsitePanel.Server.Utils;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using Microsoft.Web.Administration;
|
||||
|
||||
namespace WebsitePanel.Providers.Web.Iis
|
||||
{
|
||||
public class SSLModuleService80 : SSLModuleService
|
||||
{
|
||||
private const string CertificateStoreName = "WebHosting";
|
||||
|
||||
public bool UseSNI { get; private set; }
|
||||
public bool UseCCS { get; private set; }
|
||||
public string CCSUncPath { get; private set; }
|
||||
public string CCSCommonPassword { get; private set; }
|
||||
|
||||
public SSLModuleService80(SslFlags sslFlags, string ccsUncPath, string ccsCommonPassword)
|
||||
{
|
||||
UseSNI = sslFlags.HasFlag(SslFlags.Sni);
|
||||
UseCCS = sslFlags.HasFlag(SslFlags.CentralCertStore);
|
||||
CCSUncPath = ccsUncPath;
|
||||
CCSCommonPassword = ccsCommonPassword;
|
||||
}
|
||||
|
||||
public new SSLCertificate InstallCertificate(SSLCertificate cert, WebSite website)
|
||||
{
|
||||
try
|
||||
{
|
||||
var response = Activator.CreateInstance(Type.GetTypeFromProgID("X509Enrollment.CX509Enrollment", true)) as CX509Enrollment;
|
||||
if (response == null)
|
||||
{
|
||||
throw new Exception("Cannot create instance of X509Enrollment.CX509Enrollment");
|
||||
}
|
||||
|
||||
response.Initialize(X509CertificateEnrollmentContext.ContextMachine);
|
||||
response.InstallResponse(
|
||||
InstallResponseRestrictionFlags.AllowUntrustedRoot,
|
||||
cert.Certificate, EncodingType.XCN_CRYPT_STRING_BASE64HEADER,
|
||||
null
|
||||
);
|
||||
|
||||
// At this point, certificate has been installed into "Personal" store
|
||||
// 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);
|
||||
storeMy.Open(OpenFlags.MaxAllowed);
|
||||
X509CertificateCollection existCerts2 = storeMy.Certificates.Find(X509FindType.FindBySerialNumber, servercert.SerialNumber, false);
|
||||
var certData = existCerts2[0].Export(X509ContentType.Pfx);
|
||||
storeMy.Close();
|
||||
|
||||
if (UseCCS)
|
||||
{
|
||||
// Revert to InstallPfx to install new certificate - this also adds binding
|
||||
InstallPfx(certData, string.Empty, website);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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();
|
||||
}
|
||||
|
||||
// Remove certificate from "Personal" store
|
||||
storeMy.Open(OpenFlags.MaxAllowed);
|
||||
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;
|
||||
cert.ExpiryDate = servercert.ExpiryDate;
|
||||
cert.Hash = servercert.Hash;
|
||||
cert.DistinguishedName = servercert.DistinguishedName;
|
||||
|
||||
if (!UseCCS)
|
||||
{
|
||||
if (CheckCertificate(website))
|
||||
{
|
||||
DeleteCertificate(GetCurrentSiteCertificate(website), website);
|
||||
}
|
||||
|
||||
AddBinding(cert, website);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.WriteError("Error adding SSL certificate", ex);
|
||||
cert.Success = false;
|
||||
}
|
||||
|
||||
return cert;
|
||||
}
|
||||
|
||||
public new List<SSLCertificate> GetServerCertificates()
|
||||
{
|
||||
// Use Web Hosting store - new for IIS 8.0
|
||||
return GetServerCertificates(CertificateStoreName);
|
||||
}
|
||||
|
||||
public new SSLCertificate ImportCertificate(WebSite website)
|
||||
{
|
||||
SSLCertificate certificate;
|
||||
|
||||
try
|
||||
{
|
||||
certificate = GetCurrentSiteCertificate(website);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
certificate = new SSLCertificate
|
||||
{
|
||||
Success = false,
|
||||
Certificate = ex.ToString()
|
||||
};
|
||||
}
|
||||
|
||||
return certificate;
|
||||
}
|
||||
|
||||
public new SSLCertificate InstallPfx(byte[] certificate, string password, WebSite website)
|
||||
{
|
||||
SSLCertificate newcert, 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))
|
||||
{
|
||||
oldcert = GetCurrentSiteCertificate(website);
|
||||
}
|
||||
|
||||
X509Certificate2 x509Cert;
|
||||
var store = new X509Store(CertificateStoreName, StoreLocation.LocalMachine);
|
||||
|
||||
if (UseCCS)
|
||||
{
|
||||
// We need to use this constructor or we won't be able to export this certificate
|
||||
x509Cert = new X509Certificate2(certificate, password, X509KeyStorageFlags.Exportable);
|
||||
|
||||
var certData = x509Cert.Export(X509ContentType.Pfx);
|
||||
var convertedCert = new X509Certificate2(certData, string.Empty, X509KeyStorageFlags.Exportable);
|
||||
|
||||
// Attempts to move certificate to CCS UNC path
|
||||
try
|
||||
{
|
||||
// Create a stream out of that new certificate
|
||||
certData = convertedCert.Export(X509ContentType.Pfx, CCSCommonPassword);
|
||||
|
||||
// Open UNC path and set path to certificate subject
|
||||
var filename = (CCSUncPath.EndsWith("/") ? CCSUncPath: CCSUncPath + "/") + x509Cert.GetNameInfo(X509NameType.SimpleName, false) + ".pfx";
|
||||
var writer = new BinaryWriter(File.Open(filename, FileMode.Create));
|
||||
writer.Write(certData);
|
||||
writer.Flush();
|
||||
writer.Close();
|
||||
// Certificated saved
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Log error
|
||||
Log.WriteError("SSLModuleService could not save certificate to Centralized Certificate Store", ex);
|
||||
// Re-throw
|
||||
throw;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
x509Cert = new X509Certificate2(certificate, password);
|
||||
|
||||
// Step 1: Register X.509 certificate in the store
|
||||
// Trying to keep X.509 store open as less as possible
|
||||
try
|
||||
{
|
||||
store.Open(OpenFlags.ReadWrite);
|
||||
|
||||
store.Add(x509Cert);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.WriteError(String.Format("SSLModuleService could not import PFX into X509Store('{0}', '{1}')", store.Name, store.Location), ex);
|
||||
// Re-throw error
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
store.Close();
|
||||
}
|
||||
}
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
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 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;
|
||||
}
|
||||
|
||||
return newcert;
|
||||
}
|
||||
|
||||
public new byte[] ExportPfx(string serialNumber, string password)
|
||||
{
|
||||
if (UseCCS)
|
||||
{
|
||||
// This is not a good way to do it
|
||||
// Find cert by somehow perhaps first looking in the database? There vi kan lookup the serialnumber and find the hostname needed to create the path to the cert in CCS and then we can load the certdata into a cert and do a export with new password.
|
||||
// Another solution would be to look through all SSL-bindings on all sites until we found the site with the binding that has this serialNumber. But serialNumber is not good enough, we need hash that is unique and present in bindingInfo
|
||||
// A third solution is to iterate over all files in CCS, load them into memory and find the one with the correct serialNumber, but that cannot be good if there are thousands of files...
|
||||
foreach (var file in Directory.GetFiles(CCSUncPath))
|
||||
{
|
||||
var fileStream = File.OpenRead(file);
|
||||
|
||||
// Read certificate data from file
|
||||
var certData = new byte[fileStream.Length];
|
||||
fileStream.Read(certData, 0, (int) fileStream.Length);
|
||||
var convertedCert = new X509Certificate2(certData, CCSCommonPassword, X509KeyStorageFlags.Exportable);
|
||||
|
||||
fileStream.Close();
|
||||
|
||||
if (convertedCert.SerialNumber == serialNumber)
|
||||
{
|
||||
return convertedCert.Export(X509ContentType.Pfx, password);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var store = new X509Store(CertificateStoreName, StoreLocation.LocalMachine);
|
||||
store.Open(OpenFlags.ReadOnly);
|
||||
var cert = store.Certificates.Find(X509FindType.FindBySerialNumber, serialNumber, false)[0];
|
||||
var exported = cert.Export(X509ContentType.Pfx, password);
|
||||
return exported;
|
||||
}
|
||||
|
||||
|
||||
public new void AddBinding(SSLCertificate 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);
|
||||
|
||||
Binding siteBinding = UseCCS ?
|
||||
srvman.Sites[website.SiteId].Bindings.Add(bindingInformation, "https") :
|
||||
srvman.Sites[website.SiteId].Bindings.Add(bindingInformation, certificate.Hash, store.Name);
|
||||
|
||||
if (UseSNI)
|
||||
{
|
||||
siteBinding.SslFlags |= SslFlags.Sni;
|
||||
}
|
||||
if (UseCCS)
|
||||
{
|
||||
siteBinding.SslFlags |= SslFlags.CentralCertStore;
|
||||
}
|
||||
|
||||
store.Close();
|
||||
|
||||
srvman.CommitChanges();
|
||||
}
|
||||
}
|
||||
|
||||
public new ResultObject DeleteCertificate(SSLCertificate certificate, WebSite website)
|
||||
{
|
||||
var result = new ResultObject() { IsSuccess = true };
|
||||
|
||||
if (certificate == null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// Now delete all certs with the same serialnumber in WebHosting Store
|
||||
var store = new X509Store(CertificateStoreName, StoreLocation.LocalMachine);
|
||||
store.Open(OpenFlags.MaxAllowed);
|
||||
|
||||
var certs = store.Certificates.Find(X509FindType.FindBySerialNumber, certificate.SerialNumber, false);
|
||||
foreach (var cert in certs)
|
||||
{
|
||||
store.Remove(cert);
|
||||
}
|
||||
|
||||
store.Close();
|
||||
|
||||
// Remove binding from site
|
||||
if (CheckCertificate(website))
|
||||
{
|
||||
RemoveBinding(certificate, website);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.WriteError(String.Format("Unable to delete certificate for website {0}", website.Name), ex);
|
||||
result.IsSuccess = false;
|
||||
result.AddError("", ex);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public new SSLCertificate GetCurrentSiteCertificate(WebSite website)
|
||||
{
|
||||
using (var srvman = GetServerManager())
|
||||
{
|
||||
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))
|
||||
{
|
||||
// Let's try to match binding host and certificate filename
|
||||
var path = GetCCSPath(sslBinding.Host);
|
||||
if (File.Exists(path))
|
||||
{
|
||||
var fileStream = File.OpenRead(path);
|
||||
|
||||
// Read certificate data from file
|
||||
var certData = new byte[fileStream.Length];
|
||||
fileStream.Read(certData, 0, (int) fileStream.Length);
|
||||
cert = new X509Certificate2(certData, CCSCommonPassword);
|
||||
fileStream.Close();
|
||||
}
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
return GetSSLCertificateFromX509Certificate2(cert);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<SSLCertificate> GetServerCertificates(string certificateStoreName)
|
||||
{
|
||||
var store = new X509Store(certificateStoreName, StoreLocation.LocalMachine);
|
||||
|
||||
List<SSLCertificate> certificates;
|
||||
|
||||
try
|
||||
{
|
||||
store.Open(OpenFlags.ReadOnly);
|
||||
certificates = store.Certificates.Cast<X509Certificate2>().Select(GetSSLCertificateFromX509Certificate2).ToList();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.WriteError(
|
||||
String.Format("SSLModuleService is unable to get certificates from X509Store('{0}', '{1}') and complete GetServerCertificates call", store.Name, store.Location), ex);
|
||||
// Re-throw exception
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
store.Close();
|
||||
}
|
||||
|
||||
return certificates;
|
||||
}
|
||||
|
||||
private string GetCCSPath(string bindingName)
|
||||
{
|
||||
return (CCSUncPath.EndsWith("/") ? CCSUncPath : CCSUncPath + "/") + bindingName + ".pfx";
|
||||
}
|
||||
|
||||
private static SSLCertificate GetSSLCertificateFromX509Certificate2(X509Certificate2 cert)
|
||||
{
|
||||
var certificate = new SSLCertificate
|
||||
{
|
||||
Hostname = cert.GetNameInfo(X509NameType.SimpleName, false),
|
||||
FriendlyName = cert.FriendlyName,
|
||||
CSRLength = Convert.ToInt32(cert.PublicKey.Key.KeySize.ToString(CultureInfo.InvariantCulture)),
|
||||
Installed = true,
|
||||
DistinguishedName = cert.Subject,
|
||||
Hash = cert.GetCertHash(),
|
||||
SerialNumber = cert.SerialNumber,
|
||||
ExpiryDate = DateTime.Parse(cert.GetExpirationDateString()),
|
||||
ValidFrom = DateTime.Parse(cert.GetEffectiveDateString()),
|
||||
Success = true
|
||||
};
|
||||
|
||||
return certificate;
|
||||
}
|
||||
|
||||
private static bool SiteHasBindingWithDedicatedIp(ServerManager srvman, WebSite website)
|
||||
{
|
||||
try
|
||||
{
|
||||
var bindings = srvman.Sites[website.SiteId].Bindings;
|
||||
return bindings.Any(b => string.IsNullOrEmpty(b.Host) && b.BindingInformation.Split(':')[1] != "*");
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,8 +9,9 @@
|
|||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>WebsitePanel.Providers.Web</RootNamespace>
|
||||
<AssemblyName>WebsitePanel.Providers.Web.IIs80</AssemblyName>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
@ -32,11 +33,7 @@
|
|||
<ItemGroup>
|
||||
<Reference Include="Microsoft.Web.Administration, Version=7.9.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\Lib\References\Microsoft\Microsoft.Web.Administration.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Web.Management, Version=7.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\Lib\References\Microsoft\Microsoft.Web.Management.dll</HintPath>
|
||||
<HintPath>..\..\Lib\References\Microsoft\Windows2012\Microsoft.Web.Administration.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
|
@ -51,6 +48,9 @@
|
|||
</Compile>
|
||||
<Compile Include="IIs80.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="SSL\SSLModuleService80.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\WebsitePanel.Providers.Base\WebsitePanel.Providers.Base.csproj">
|
||||
|
@ -65,7 +65,12 @@
|
|||
<Project>{1b9dce85-c664-49fc-b6e1-86c63cab88d1}</Project>
|
||||
<Name>WebsitePanel.Providers.Web.IIs70</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\WebsitePanel.Server.Utils\WebsitePanel.Server.Utils.csproj">
|
||||
<Project>{e91e52f3-9555-4d00-b577-2b1dbdd87ca7}</Project>
|
||||
<Name>WebsitePanel.Server.Utils</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -90,7 +90,9 @@ namespace WebsitePanel.Server
|
|||
}
|
||||
|
||||
[WebMethod, SoapHeader("settings")]
|
||||
public string CreateMailEnableUser(string upn, string organizationId, string organizationDistinguishedName, ExchangeAccountType accountType,
|
||||
public string CreateMailEnableUser(string upn, string organizationId, string organizationDistinguishedName,
|
||||
string securityGroup, string organizationDomain,
|
||||
ExchangeAccountType accountType,
|
||||
string mailboxDatabase, string offlineAddressBook, string addressBookPolicy,
|
||||
string accountName, bool enablePOP, bool enableIMAP,
|
||||
bool enableOWA, bool enableMAPI, bool enableActiveSync,
|
||||
|
@ -100,7 +102,9 @@ namespace WebsitePanel.Server
|
|||
try
|
||||
{
|
||||
LogStart("CreateMailEnableUser");
|
||||
string ret = ES.CreateMailEnableUser(upn, organizationId, organizationDistinguishedName, accountType,
|
||||
string ret = ES.CreateMailEnableUser(upn, organizationId, organizationDistinguishedName,
|
||||
securityGroup, organizationDomain,
|
||||
accountType,
|
||||
mailboxDatabase, offlineAddressBook, addressBookPolicy,
|
||||
accountName, enablePOP, enableIMAP,
|
||||
enableOWA, enableMAPI, enableActiveSync,
|
||||
|
@ -556,6 +560,24 @@ namespace WebsitePanel.Server
|
|||
}
|
||||
}
|
||||
|
||||
[WebMethod, SoapHeader("settings")]
|
||||
public string[] SetDefaultPublicFolderMailbox(string id, string organizationId, string organizationDistinguishedName)
|
||||
{
|
||||
try
|
||||
{
|
||||
LogStart("SetDefaultPublicFolderMailbox");
|
||||
string[] ret = ES.SetDefaultPublicFolderMailbox(id, organizationId, organizationDistinguishedName);
|
||||
LogEnd("SetDefaultPublicFolderMailbox");
|
||||
return ret;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.WriteError("SetDefaultPublicFolderMailbox", ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Contacts
|
||||
|
@ -1084,6 +1106,23 @@ namespace WebsitePanel.Server
|
|||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
[WebMethod, SoapHeader("settings")]
|
||||
public string CreateOrganizationRootPublicFolder(string organizationId, string organizationDistinguishedName, string securityGroup, string organizationDomain)
|
||||
{
|
||||
try
|
||||
{
|
||||
LogStart("CreateOrganizationRootPublicFolder");
|
||||
string ret = ES.CreateOrganizationRootPublicFolder(organizationId, organizationDistinguishedName, securityGroup, organizationDomain);
|
||||
LogEnd("CreateOrganizationRootPublicFolder");
|
||||
return ret;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.WriteError("CreateOrganizationRootPublicFolder", ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
|
|
@ -140,7 +140,7 @@ table.BorderFillBox td .Brick {padding:0; line-height:normal; margin-bottom:9px;
|
|||
.CalendarWeekend {}
|
||||
.CalendarSelectedDate {color:#fff; font-weight:700; background:#ffd349 !important;}
|
||||
.MessageBox {padding:15px; margin:20px; color:#fff; font-size:14px; text-align:left; font-weight:600; line-height:16px;}
|
||||
.MessageBox.Green {}
|
||||
.MessageBox.Green {background: #008000}
|
||||
.MessageBox.Yellow {background:#f0ad4e;}
|
||||
.MessageBox.Red {background:#f25555;}
|
||||
input.Button1, input.Button2, input.Button3, input.SmallButton, input.LoginButton, input[type=submit] {font-family:'Segoe UI Light','Open Sans',Arial; color:#fff; border:1px solid #5e86aa; background:#6598c5; font-weight:300; text-align:center; vertical-align:middle; cursor:pointer; white-space:nowrap; padding:6px 12px; font-size:14px; line-height:1.428571429;}
|
||||
|
|
|
@ -499,6 +499,40 @@
|
|||
</uc5:EditDomainsList>
|
||||
</td>
|
||||
</tr>
|
||||
<tbody runat="server" ID="IIS80SSLSettings" Visible="False">
|
||||
<tr>
|
||||
<td width="200" class="Normal" valign="top">
|
||||
<asp:Label ID="lblUseSNI" runat="server" Text="Use SNI (Server Name Indication):"></asp:Label>
|
||||
</td>
|
||||
<td class="Normal" valign="top">
|
||||
<asp:CheckBox ID="cbUseSNI" runat="server" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="200" class="Normal" valign="top">
|
||||
<asp:Label ID="lblUseCCS" runat="server" Text="Use Centralized Certificate Store:"></asp:Label>
|
||||
</td>
|
||||
<td class="Normal" valign="top">
|
||||
<asp:CheckBox ID="cbUseCCS" runat="server" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="200" class="Normal" valign="top">
|
||||
<asp:Label ID="lblCCSUNCPath" runat="server" Text="Centralized Certificate Store UNC path :"></asp:Label>
|
||||
</td>
|
||||
<td class="Normal" valign="top">
|
||||
<asp:TextBox ID="txtCCSUNCPath" runat="server" CssClass="NormalTextBox" Width="400px"></asp:TextBox>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="200" class="Normal" valign="top">
|
||||
<asp:Label ID="lblCCSUNCCommonPassword" runat="server" Text="Centralized Certificate Store common password (blank for none):"></asp:Label>
|
||||
</td>
|
||||
<td class="Normal" valign="top">
|
||||
<asp:TextBox ID="txtCCSCommonPassword" runat="server" CssClass="NormalTextBox" Width="400px"></asp:TextBox>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tr>
|
||||
<td class="Normal" valign="top">
|
||||
<asp:Label ID="lblADIntegration" runat="server" meta:resourcekey="lblADIntegration" Text="Active Directory Integration:"></asp:Label>
|
||||
|
|
|
@ -225,6 +225,16 @@ namespace WebsitePanel.Portal.ProviderControls
|
|||
FilteredAppIds = settings["GalleryAppsFilter"];
|
||||
radioFilterAppsList.SelectedIndex = Utils.ParseInt(settings["GalleryAppsFilterMode"], 0);
|
||||
chkGalleryAppsAlwaysIgnoreDependencies.Checked = Utils.ParseBool(settings["GalleryAppsAlwaysIgnoreDependencies"], false);
|
||||
|
||||
// If any of these exists, we assume we are running against the IIS80 provider
|
||||
if (settings["SSLCCSCommonPassword"] != null || settings["SSLCCSUNCPath"] != null || settings["SSLUseCCS"] != null || settings["SSLUseSNI"] != null)
|
||||
{
|
||||
IIS80SSLSettings.Visible = true;
|
||||
cbUseCCS.Checked = Utils.ParseBool(settings["SSLUseCCS"], false);
|
||||
cbUseSNI.Checked = Utils.ParseBool(settings["SSLUseSNI"], false);
|
||||
txtCCSUNCPath.Text = settings["SSLCCSUNCPath"];
|
||||
txtCCSCommonPassword.Text = settings["SSLCCSCommonPassword"];
|
||||
}
|
||||
}
|
||||
|
||||
public void SaveSettings(StringDictionary settings)
|
||||
|
@ -314,6 +324,15 @@ namespace WebsitePanel.Portal.ProviderControls
|
|||
settings["GalleryAppsFilter"] = GetAppsCatalogFilter();
|
||||
settings["GalleryAppsFilterMode"] = radioFilterAppsList.SelectedIndex.ToString();
|
||||
settings["GalleryAppsAlwaysIgnoreDependencies"] = chkGalleryAppsAlwaysIgnoreDependencies.Checked.ToString();
|
||||
|
||||
|
||||
if (IIS80SSLSettings.Visible)
|
||||
{
|
||||
settings["SSLUseCCS"] = cbUseCCS.Checked.ToString();
|
||||
settings["SSLUseSNI"] = cbUseSNI.Checked.ToString();
|
||||
settings["SSLCCSUNCPath"] = txtCCSUNCPath.Text;
|
||||
settings["SSLCCSCommonPassword"] = txtCCSCommonPassword.Text;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,31 +1,3 @@
|
|||
// 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.
|
||||
|
@ -814,6 +786,87 @@ namespace WebsitePanel.Portal.ProviderControls {
|
|||
/// </remarks>
|
||||
protected global::WebsitePanel.Portal.UserControls.EditDomainsList sharedSslSites;
|
||||
|
||||
/// <summary>
|
||||
/// IIS80SSLSettings control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.HtmlControls.HtmlGenericControl IIS80SSLSettings;
|
||||
|
||||
/// <summary>
|
||||
/// lblUseSNI 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.Label lblUseSNI;
|
||||
|
||||
/// <summary>
|
||||
/// cbUseSNI 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.CheckBox cbUseSNI;
|
||||
|
||||
/// <summary>
|
||||
/// lblUseCCS 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.Label lblUseCCS;
|
||||
|
||||
/// <summary>
|
||||
/// cbUseCCS 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.CheckBox cbUseCCS;
|
||||
|
||||
/// <summary>
|
||||
/// lblCCSUNCPath 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.Label lblCCSUNCPath;
|
||||
|
||||
/// <summary>
|
||||
/// txtCCSUNCPath 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.TextBox txtCCSUNCPath;
|
||||
|
||||
/// <summary>
|
||||
/// lblCCSUNCCommonPassword 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.Label lblCCSUNCCommonPassword;
|
||||
|
||||
/// <summary>
|
||||
/// txtCCSCommonPassword 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.TextBox txtCCSCommonPassword;
|
||||
|
||||
/// <summary>
|
||||
/// lblADIntegration control.
|
||||
/// </summary>
|
||||
|
|
|
@ -76,10 +76,10 @@ namespace WebsitePanel.Portal
|
|||
set { ViewState["PackageId"] = value; }
|
||||
}
|
||||
|
||||
private bool IsDedicatedIP
|
||||
private bool AllowSsl
|
||||
{
|
||||
get { return (bool)ViewState["IsDedicatedIP"]; }
|
||||
set { ViewState["IsDedicatedIP"] = value; }
|
||||
get { return (bool)ViewState["AllowSsl"]; }
|
||||
set { ViewState["AllowSsl"] = value; }
|
||||
}
|
||||
|
||||
private bool IIs7
|
||||
|
@ -111,7 +111,7 @@ namespace WebsitePanel.Portal
|
|||
|
||||
// remove "SSL" tab for a site with dynamic IP
|
||||
var sslTab = filteredTabs.SingleOrDefault(t => t.Id == "SSL");
|
||||
if (!IsDedicatedIP && sslTab != null)
|
||||
if (!AllowSsl && sslTab != null)
|
||||
filteredTabs.Remove(sslTab);
|
||||
|
||||
|
||||
|
@ -277,15 +277,16 @@ namespace WebsitePanel.Portal
|
|||
webSitesCustomErrorsControl.BindWebItem(site);
|
||||
webSitesHeliconZooControl.BindWebItem(site);
|
||||
|
||||
if (site.IsDedicatedIP)
|
||||
// If SNI is enabled on the server, we do allow for SSL even if site not has dedicated Ip
|
||||
if (site.IsDedicatedIP || site.SniEnabled)
|
||||
{
|
||||
IsDedicatedIP = true;
|
||||
AllowSsl = true;
|
||||
WebsitesSSLControl.Visible = true;
|
||||
WebsitesSSLControl.BindWebItem(site);
|
||||
}
|
||||
else
|
||||
{
|
||||
IsDedicatedIP = false;
|
||||
AllowSsl = false;
|
||||
WebsitesSSLControl.Visible = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -102,13 +102,19 @@ namespace WebsitePanel.Portal
|
|||
// php
|
||||
if (PackagesHelper.CheckGroupQuotaEnabled(packageId, ResourceGroups.Web, Quotas.WEB_PHP4))
|
||||
ddlPhp.Items.Add("4");
|
||||
|
||||
var allowSingleValueInPhpDropDown = false;
|
||||
|
||||
if (PackagesHelper.CheckGroupQuotaEnabled(packageId, ResourceGroups.Web, Quotas.WEB_PHP5))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(item.Php5VersionsInstalled))
|
||||
{
|
||||
// Add items from list
|
||||
// Remove empty item. Not allows for PHP5 FastCGI. There is no way to disable a handler without removing it or removing some vital info. If we do that, the user can not choose to run PHP5 FastCGI later
|
||||
ddlPhp.Items.Remove(ddlPhp.Items.FindByValue(""));
|
||||
// Add items from list
|
||||
ddlPhp.Items.AddRange(item.Php5VersionsInstalled.Split('|').Select(v => new ListItem(v.Split(';')[1], "5|" + v.Split(';')[0])).OrderBy(i => i.Text).ToArray());
|
||||
|
||||
allowSingleValueInPhpDropDown = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -116,7 +122,7 @@ namespace WebsitePanel.Portal
|
|||
}
|
||||
}
|
||||
Utils.SelectListItem(ddlPhp, item.PhpInstalled);
|
||||
rowPhp.Visible = ddlPhp.Items.Count > 1;
|
||||
rowPhp.Visible = ddlPhp.Items.Count > 1 || allowSingleValueInPhpDropDown && ddlPhp.Items.Count > 0;
|
||||
|
||||
rowPerl.Visible = PackagesHelper.CheckGroupQuotaEnabled(packageId, ResourceGroups.Web, Quotas.WEB_PERL);
|
||||
rowCgiBin.Visible = PackagesHelper.CheckGroupQuotaEnabled(packageId, ResourceGroups.Web, Quotas.WEB_CGIBIN);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue